From 8d673fa1bf1d578439057f29de6bb19a7820d0a5 Mon Sep 17 00:00:00 2001 From: "Colin J. Brigato" Date: Mon, 3 Sep 2018 00:02:44 +0200 Subject: [PATCH 0001/1938] First pass rewrite of flashmem driver for optimization. Lot of changes here. Provides PoC of saving and recalling a tag in Standalone mode. Added some printing passthrough to client to azccomodate for vt100 eye-candyness. FastREAD mode implemented for flashmem, testable from client. Beta but functionnal. Reading the whole flash with 1Kb to 32kb buffers was ~730ms, now 380ms Max (even at 24Mhz spi baudrate) --- armsrc/Makefile | 12 +- armsrc/Standalone/hf_colin.c | 626 ++++++++++++++++++++++++++++------- armsrc/Standalone/hf_colin.h | 22 +- armsrc/appmain.c | 96 ++++-- armsrc/flashmem.c | 329 ++++++++++++------ armsrc/flashmem.h | 30 +- client/cmdflashmem.c | 16 +- client/cmdmain.c | 26 +- 8 files changed, 865 insertions(+), 292 deletions(-) diff --git a/armsrc/Makefile b/armsrc/Makefile index a0f5c7f5c..fb2a2a91b 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -24,7 +24,7 @@ APP_CFLAGS = -DWITH_CRC \ -DWITH_FLASH \ -DWITH_SMARTCARD \ -DWITH_HFSNOOP \ - -DWITH_LF_SAMYRUN \ + -DWITH_HF_COLIN \ -fno-strict-aliasing -ffunction-sections -fdata-sections ### IMPORTANT - move the commented variable below this line @@ -106,12 +106,9 @@ ARMSRC = fpgaloader.c \ parity.c \ usb_cdc.c \ cmd.c \ - lf_samyrun.c \ - vtsend.c - # lf_samyrun.c \ - # lf_hidbrute.c \ - # lf_proxbrute.c \ - # hf_mattyrun.c \ + vtsend.c \ + hf_colin.c \ + lib_AT91SAM7.c VERSIONSRC = version.c \ fpga_version_info.c @@ -120,7 +117,6 @@ VERSIONSRC = version.c \ include ../common/Makefile.common COMMON_FLAGS = -Os - OBJS = $(OBJDIR)/fullimage.s19 FPGA_COMPRESSOR = ../client/fpga_compress diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index 1ba31a9c7..3a34396eb 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -12,8 +12,6 @@ #define MF1KSZ 1024 #define MF1KSZSIZE 64 -//#define FALSE false -//#define TRUE true #define AUTHENTICATION_TIMEOUT 848 uint8_t cjuid[10]; @@ -27,58 +25,328 @@ int curlline; // Colin's VIGIKPWN sniff/simulate/clone repeat routine for HF Mifare -void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug) { +void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug) +{ uint32_t chunksize = (USB_CMD_DATA_SIZE / 4); uint8_t totalchunks = len / chunksize; uint8_t last_chunksize = len - (totalchunks * chunksize); char chunk[chunksize + 1]; memset(chunk, 0x00, sizeof(chunk)); - if (debug > 0) { + if (debug > 0) + { Dbprintf("len : %d", len); Dbprintf("chunksize : %d bytes", chunksize); Dbprintf("totalchunks : %d", totalchunks); Dbprintf("last_chunksize: %d", last_chunksize); } - for (uint8_t i = 0; i < totalchunks; i++) { + for (uint8_t i = 0; i < totalchunks; i++) + { memset(chunk, 0x00, sizeof(chunk)); memcpy(chunk, &bigar[i * chunksize], chunksize); DbprintfEx(FLAG_RAWPRINT, "%s", chunk); } - if (last_chunksize > 0) { + if (last_chunksize > 0) + { memset(chunk, 0x00, sizeof(chunk)); memcpy(chunk, &bigar[totalchunks * chunksize], last_chunksize); DbprintfEx(FLAG_RAWPRINT, "%s", chunk); } - if (newlines > 0) { + if (newlines > 0) + { DbprintfEx(FLAG_NOLOG, " "); } } -void cjSetCursFRight() { +void cjSetCursFRight() +{ vtsend_cursor_position(NULL, 98, (currfline)); currfline++; } -void cjSetCursRight() { +void cjSetCursRight() +{ vtsend_cursor_position(NULL, 59, (currline)); currline++; } -void cjSetCursLeft() { +void cjSetCursLeft() +{ vtsend_cursor_position(NULL, 0, (curlline)); curlline++; } void cjTabulize() { DbprintfEx(FLAG_RAWPRINT, "\t\t\t"); } -void cjPrintKey(uint64_t key, uint8_t *foundKey, uint16_t sectorNo, uint8_t type) { +void cjPrintKey(uint64_t key, uint8_t *foundKey, uint16_t sectorNo, uint8_t type) +{ char tosendkey[13]; sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[0], foundKey[1], foundKey[2], foundKey[3], foundKey[4], foundKey[5]); cjSetCursRight(); DbprintfEx(FLAG_NOLOG, "SEC: %02x | KEY : %s | TYP: %d", sectorNo, tosendkey, type); } -void RunMod() { +void SpinOff(uint32_t pause) +{ + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + LED_D_OFF(); + SpinDelay(pause); +} + +// 0=A, 1=B, 2=C, 3=D +void SpinErr(uint8_t led, uint32_t speed, uint8_t times) +{ + SpinOff(speed); + NTIME(times) + { + switch (led) + { + case 0: + LED_A_INV(); + break; + case 1: + LED_B_INV(); + break; + case 2: + LED_C_INV(); + break; + case 3: + LED_D_INV(); + break; + } + SpinDelay(speed); + } +} + +void SpinDown(uint32_t speed) +{ + SpinOff(speed); + LED_D_ON(); + SpinDelay(speed); + LED_D_OFF(); + LED_C_ON(); + SpinDelay(speed); + LED_C_OFF(); + LED_B_ON(); + SpinDelay(speed); + LED_B_OFF(); + LED_A_ON(); + SpinDelay(speed); + LED_A_OFF(); +} + +void SpinUp(uint32_t speed) +{ + SpinOff(speed); + LED_A_ON(); + SpinDelay(speed); + LED_A_OFF(); + LED_B_ON(); + SpinDelay(speed); + LED_B_OFF(); + LED_C_ON(); + SpinDelay(speed); + LED_C_OFF(); + LED_D_ON(); + SpinDelay(speed); + LED_D_OFF(); +} + +void TestFlashmemSpeed(size_t buffersize, bool fastmode) +{ + + DbprintfEx(FLAG_NOLOG, "%s---+----[ %s %s[%dKB] %s]", _GREEN_, _WHITE_, _YELLOW_, buffersize / 1024, _WHITE_); + uint16_t t = 0; + + LED_B_ON(); + uint8_t *mem = BigBuf_malloc(buffersize); + bool isok = false; + size_t len = 0; + uint32_t startidx = 0; + uint32_t numofbytes = 0x3FFFF; + + if (!FlashInit(fastmode)) { + return; + } + Flash_CheckBusy(BUSY_TIMEOUT); + + //Flash_ReadStat1(); + + uint32_t end_time; + uint32_t start_time = end_time = GetTickCount(); + + for (size_t i = 0; i < numofbytes; i += buffersize) + { + len = MIN((numofbytes - i), buffersize); + + //isok = Flash_ReadData(startidx + i, mem, len); + //uint32_t iend_time; + //uint32_t istart_time = iend_time = GetTickCount(); + if (fastmode) + { + isok = Flash_FastReadDataCont(startidx + i, mem, len); + } + else + { + isok = Flash_ReadDataCont(startidx + i, mem, len); + } + //iend_time = GetTickCount(); + //DbprintfEx(FLAG_RAWPRINT, "%s%dms%s>", _YELLOW_, iend_time - istart_time, _WHITE_); + //cjSetCursLeft(); + if (!isok) + { + Dbprintf("[FAIL] reading flash memory failed :: | bytes between %d - %d", i, len); + return; + } + //isok = cmd_send(CMD_DOWNLOADED_FLASHMEM, i, len, 0, mem, len); + //if (!isok) + // Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); + t++; + } + end_time = GetTickCount(); + DbprintfEx(FLAG_NOLOG, "%s |--< %s %s%dms%s for FULL_FLASH_READ", _GREEN_, _WHITE_, _YELLOW_, end_time - start_time, _WHITE_); + DbprintfEx(FLAG_NOLOG, "%s `--= %s %d runs of %s~%dms%s each", _GREEN_, _WHITE_, t, _YELLOW_, (end_time - start_time) / t, _WHITE_); + DbprintfEx(FLAG_NOLOG, ""); + //cjSetCursLeft(); + LED_B_OFF(); + FlashStop(); +} + +void ReadLastTagFromFlash() +{ + + SpinOff(0); + LED_A_ON(); + LED_B_ON(); + LED_C_ON(); + LED_D_ON(); + uint16_t isok = 0; + uint32_t startidx = 0; + uint16_t len = 1024; + + DbprintfEx(FLAG_NOLOG, "Button HELD ! Using LAST Known TAG for Simulation..."); + cjSetCursLeft(); + + size_t size = len; + uint8_t *mem = BigBuf_malloc(size); + + //if (!FlashFastReadInit()){ + if (!FlashInit(0)) + { + return; + } + //Flash_ReadStat1(); + + uint32_t end_time; + uint32_t start_time = end_time = GetTickCount(); + + for (size_t i = 0; i < len; i += size) + { + len = MIN((len - i), size); + + // isok = Flash_FastReadDataCont(startidx + i, mem, len); + isok = Flash_ReadDataCont(startidx + i, mem, len); + if (isok == len) + { + //print_result("Chunk: ", mem, len); + emlSetMem(mem, 0, 64); + } + else + { + DbprintfEx(FLAG_NOLOG, "FlashMem reading failed | %d | %d", len, isok); + cjSetCursLeft(); + SpinOff(100); + FlashStop(); + return; + } + } + end_time = GetTickCount(); + DbprintfEx(FLAG_NOLOG, "[OK] Last tag recovered from FLASHMEM set to emulator"); + cjSetCursLeft(); + DbprintfEx(FLAG_NOLOG, "%s[IN]%s %s%dms%s for TAG_FLASH_READ", _GREEN_, _WHITE_, _YELLOW_, end_time - start_time, _WHITE_); + cjSetCursLeft(); + FlashStop(); + SpinOff(0); + return; +} + +void WriteTagToFlash(uint8_t index, size_t size) +{ + + SpinOff(0); + LED_A_ON(); + LED_B_ON(); + LED_C_ON(); + LED_D_ON(); + + uint8_t isok = 0; + uint16_t res = 0; + uint32_t len = size; + uint32_t bytes_sent = 0; + uint32_t bytes_remaining = len; + + uint8_t data[(size * (16 * 64))/1024]; + uint8_t buff[PAGESIZE]; + // cnt = 0; + emlGetMem(data, 0, (size * 64)/1024); + + //if (!FlashFastReadInit()){ + if (!FlashInit(0)) + { + return; + } + + Flash_WriteEnable(); + Flash_Erase4k(0,0); + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); + + uint32_t end_time; + uint32_t start_time = end_time = GetTickCount(); + + while (bytes_remaining > 0) + { + uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); + + memcpy(buff, data + bytes_sent, bytes_in_packet); + + bytes_remaining -= bytes_in_packet; + res = Flash_WriteDataCont(bytes_sent + (index * size), buff, bytes_in_packet); + bytes_sent += bytes_in_packet; + + isok = (res == bytes_in_packet) ? 1 : 0; + + if (!isok) + { + DbprintfEx(FLAG_NOLOG, "FlashMem write FAILEd [offset %u]", bytes_sent); + cjSetCursLeft(); + SpinOff(100); + + return; + } + + LED_A_INV(); + LED_B_INV(); + LED_C_INV(); + LED_D_INV(); + } + end_time = GetTickCount(); + + DbprintfEx(FLAG_NOLOG, "[OK] TAG WRITTEN TO FLASH ! [0-to offset %u]", bytes_sent); + cjSetCursLeft(); + DbprintfEx(FLAG_NOLOG, "%s[IN]%s %s%dms%s for TAG_FLASH_WRITE", _GREEN_, _WHITE_, _YELLOW_, end_time - start_time, _WHITE_); + cjSetCursLeft(); + + FlashStop(); + + SpinOff(0); + + return; +} + +void RunMod() +{ currline = 20; curlline = 20; currfline = 24; @@ -89,7 +357,7 @@ void RunMod() { uint64_t key64; // Defines current key uint8_t *keyBlock = NULL; // Where the keys will be held in memory. -/* VIGIK EXPIRED DUMP FOR STUDY + /* VIGIK EXPIRED DUMP FOR STUDY Sector 0 121C7F730208040001FA33F5CB2D021D 44001049164916491649000000000000 @@ -125,11 +393,11 @@ KEY A : 1KGIV ; ACCBITS : 796788[00]+VALUE */ -//---------------------------- -// Set of keys to be used. -// This should cover ~98% of -// French VIGIK system @2017 -//---------------------------- + //---------------------------- + // Set of keys to be used. + // This should cover ~98% of + // French VIGIK system @2017 + //---------------------------- #define STKEYS 37 @@ -177,7 +445,8 @@ ACCBITS : 796788[00]+VALUE keyBlock = BigBuf_malloc(STKEYS * 6); int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t); - for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) { + for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) + { num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t *)(keyBlock + mfKeyCounter * 6)); } @@ -185,10 +454,13 @@ ACCBITS : 796788[00]+VALUE // and why not a simple memset abuse to 0xffize the whole space in one go ? // uint8_t foundKey[2][40][6]; //= [ {0xff} ]; /* C99 abusal 6.7.8.21 uint8_t foundKey[2][40][6]; - for (uint16_t t = 0; t < 2; t++) { - for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { + for (uint16_t t = 0; t < 2; t++) + { + for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) + { // validKey[t][sectorNo] = false; - for (uint16_t i = 0; i < 6; i++) { + for (uint16_t i = 0; i < 6; i++) + { foundKey[t][sectorNo][i] = 0xff; } } @@ -200,11 +472,6 @@ ACCBITS : 796788[00]+VALUE bool allKeysFound = true; uint32_t size = mfKeysCnt; - LED_A_OFF(); - LED_B_OFF(); - LED_C_OFF(); - LED_D_OFF(); - LED_A_ON(); // banner: vtsend_reset(NULL); @@ -218,7 +485,36 @@ ACCBITS : 796788[00]+VALUE currfline = 24; cjSetCursLeft(); + SpinDown(50); + SpinOff(50); + SpinUp(50); + SpinOff(50); + SpinDown(50); + +#if 0 + DbprintfEx(FLAG_NOLOG, "%s>>%s Will Now Test dumping Full flash [256Kb] (2Mbits)through Bigbuf buffers\n", _GREEN_, _WHITE_); + MF_DBGLEVEL = MF_DBG_NONE; + DbprintfEx(FLAG_NOLOG, "---------\n%s[A]%s Using NORMAL Reads @Max (24Mhz=MCK/2)\n--------", _GREEN_, _WHITE_); + TestFlashmemSpeed(32768,0); + TestFlashmemSpeed(16384 + 4096 + 4096,0); + TestFlashmemSpeed(16384,0); + TestFlashmemSpeed(4096,0); + TestFlashmemSpeed(1024,0); + SpinDelay(1000); + WDT_HIT(); + DbprintfEx(FLAG_NOLOG, "--------\n%s[B]%s Using FAST Reads @Max (48Mhz=MCK=CPUClock/2=MAXSPI)\n--------", _GREEN_, _WHITE_); + TestFlashmemSpeed(32768,1); + TestFlashmemSpeed(16384 + 4096 + 4096,1); + TestFlashmemSpeed(16384,1); + TestFlashmemSpeed(4096,1); + TestFlashmemSpeed(1024,1); + SpinDelay(1000); + WDT_HIT(); + return; +#endif + failtag: + vtsend_cursor_position_save(NULL); vtsend_set_attribute(NULL, 1); vtsend_set_attribute(NULL, 5); @@ -226,11 +522,32 @@ failtag: vtsend_set_attribute(NULL, 0); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - while (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) { + SpinOff(50); + LED_A_ON(); + uint8_t ticker = 0; + //while (!BUTTON_PRESS() && !iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) + while (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) + { WDT_HIT(); + + ticker++; + if (ticker % 64 == 0) + { + LED_A_INV(); + } + + if (BUTTON_HELD(10) > 0) + { + WDT_HIT(); + DbprintfEx(FLAG_NOLOG, "\t\t\t[ READING FLASH ]"); + ReadLastTagFromFlash(); + goto readysim; + } } + + SpinOff(50); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelay(200); vtsend_cursor_position_restore(NULL); DbprintfEx(FLAG_NOLOG, "\t\t\t%s[ GOT a Tag ! ]%s", _GREEN_, _WHITE_); cjSetCursLeft(); @@ -239,12 +556,16 @@ failtag: DbprintfEx(FLAG_NOLOG, "\t%sGOT TAG :%s %08x%s", _RED_, _CYAN_, cjcuid, _WHITE_); - if (cjcuid == 0) { + if (cjcuid == 0) + { cjSetCursLeft(); - DbprintfEx(FLAG_NOLOG, "%s>>%s BUG: 0000_CJCUID! Retrying...", _RED_, _WHITE_); + SpinErr(0, 100, 8); goto failtag; } + + SpinOff(50); + LED_B_ON(); cjSetCursRight(); DbprintfEx(FLAG_NOLOG, "--------+--------------------+-------"); cjSetCursRight(); @@ -283,31 +604,38 @@ failtag: // also we could avoid first UID check for every block // then let’s expose this “optimal case” of “well known vigik schemes” : - for (uint8_t type = 0; type < 2 && !err && !trapped; type++) { - for (int sec = 0; sec < sectorsCnt && !err && !trapped; ++sec) { + for (uint8_t type = 0; type < 2 && !err && !trapped; type++) + { + for (int sec = 0; sec < sectorsCnt && !err && !trapped; ++sec) + { key = cjat91_saMifareChkKeys(sec * 4, type, NULL, size, &keyBlock[0], &key64); // key = saMifareChkKeys(sec * 4, type, NULL, size, &keyBlock[0], &key64); - if (key == -1) { + if (key == -1) + { err = 1; allKeysFound = false; // used in “portable” imlementation on microcontroller: it reports back the fail and open the standalone lock // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); break; - } else if (key == -2) { + } + else if (key == -2) + { err = 1; // Can't select card. allKeysFound = false; // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); break; - } else { + } + else + { /* BRACE YOURSELF : AS LONG AS WE TRAP A KNOWN KEY, WE STOP CHECKING AND ENFORCE KNOWN SCHEMES */ // uint8_t tosendkey[12]; - char tosendkey[13]; + char tosendkey[12]; num_to_bytes(key64, 6, foundKey[type][sec]); cjSetCursRight(); DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %012" PRIx64 " ; TYP: %i", sec, key64, type); /*cmd_send(CMD_CJB_INFORM_CLIENT_KEY, 12, sec, type, tosendkey, 12);*/ - - switch (key64) { + switch (key64) + { ///////////////////////////////////////////////////////// // COMMON SCHEME 1 : INFINITRON/HEXACT case 0x484558414354: @@ -328,7 +656,8 @@ failtag: ; // Type 0 / A first uint16_t t = 0; - for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { + for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) + { num_to_bytes(0x484558414354, 6, foundKey[t][sectorNo]); sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); @@ -474,8 +803,10 @@ failtag: // emlClearMem(); // A very weak one... - for (uint16_t t = 0; t < 2; t++) { - for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { + for (uint16_t t = 0; t < 2; t++) + { + for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) + { num_to_bytes(key64, 6, foundKey[t][sectorNo]); sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); @@ -509,7 +840,8 @@ failtag: DbprintfEx(FLAG_NOLOG, "%s>>>>>>>>>>>>!*DONE*!<<<<<<<<<<<<<<%s", _GREEN_, _WHITE_); ; t = 0; - for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { + for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) + { num_to_bytes(0x414c41524f4e, 6, foundKey[t][sectorNo]); sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); @@ -519,7 +851,8 @@ failtag: ; } t = 1; - for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { + for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) + { num_to_bytes(0x424c41524f4e, 6, foundKey[t][sectorNo]); sprintf(tosendkey, "%02x%02x%02x%02x%02x%02x", foundKey[t][sectorNo][0], foundKey[t][sectorNo][1], foundKey[t][sectorNo][2], foundKey[t][sectorNo][3], foundKey[t][sectorNo][4], foundKey[t][sectorNo][5]); @@ -536,21 +869,25 @@ failtag: } } - if (!allKeysFound) { - // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); + if (!allKeysFound) + { cjSetCursLeft(); cjTabulize(); DbprintfEx(FLAG_NOLOG, "%s[ FAIL ]%s\r\n->did not found all the keys :'(", _RED_, _WHITE_); cjSetCursLeft(); + SpinErr(1, 100, 8); + SpinOff(100); return; } /* Settings keys to emulator */ emlClearMem(); uint8_t mblock[16]; - for (uint8_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { + for (uint8_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) + { emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); - for (uint8_t t = 0; t < 2; t++) { + for (uint8_t t = 0; t < 2; t++) + { memcpy(mblock + t * 10, foundKey[t][sectorNo], 6); } emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); @@ -565,27 +902,41 @@ failtag: DbprintfEx(FLAG_NOLOG, "%s>>%s Filling Emulator <- from A keys...", _YELLOW_, _WHITE_); e_MifareECardLoad(sectorsCnt, 0, 0, &filled); - if (filled != 1) { + if (filled != 1) + { cjSetCursLeft(); DbprintfEx(FLAG_NOLOG, "%s>>%s W_FAILURE ! %sTrying fallback B keys....", _RED_, _ORANGE_, _WHITE_); /* no trace, no dbg */ e_MifareECardLoad(sectorsCnt, 1, 0, &filled); - if (filled != 1) { + if (filled != 1) + { cjSetCursLeft(); DbprintfEx(FLAG_NOLOG, "FATAL:EML_FALLBACKFILL_B"); - // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); + SpinErr(2, 100, 8); + SpinOff(100); return; } } + end_time = GetTickCount(); cjSetCursLeft(); DbprintfEx(FLAG_NOLOG, "%s>>%s Time for VIGIK break :%s%dms%s", _GREEN_, _WHITE_, _YELLOW_, end_time - start_time, _WHITE_); - // cmd_send(CMD_CJB_FSMSTATE_MENU, 0, 0, 0, 0, 0); + vtsend_cursor_position_save(NULL); + vtsend_set_attribute(NULL, 1); + vtsend_set_attribute(NULL, 5); + cjTabulize(); + DbprintfEx(FLAG_NOLOG, "[ WRITING FLASH ]"); + cjSetCursLeft(); + cjSetCursLeft(); + + WriteTagToFlash(0,1024); + +readysim: // SIM ? cjSetCursLeft(); @@ -602,12 +953,14 @@ failtag: cjTabulize(); - vtsend_cursor_position_save(NULL); - vtsend_set_attribute(NULL, 1); - vtsend_set_attribute(NULL, 5); DbprintfEx(FLAG_NOLOG, "[ SIMULATION ]"); vtsend_set_attribute(NULL, 0); - Mifare1ksim((FLAG_4B_UID_IN_DATA | FLAG_UID_IN_EMUL ), 0, 0, cjuid); + + SpinOff(100); + LED_C_ON(); + Mifare1ksim(FLAG_4B_UID_IN_DATA | FLAG_UID_IN_EMUL, 0, 0, cjuid); + LED_C_OFF(); + SpinOff(50); vtsend_cursor_position_restore(NULL); DbprintfEx(FLAG_NOLOG, "[ SIMUL ENDED ]%s", _GREEN_, _WHITE_); cjSetCursLeft(); @@ -652,7 +1005,9 @@ failtag: DbprintfEx(FLAG_NOLOG, "- [ LA FIN ] -\r\n%s`-> You can take shell back :) ...", _WHITE_); cjSetCursLeft(); vtsend_set_attribute(NULL, 0); - + SpinErr(3, 100, 16); + SpinDown(75); + SpinOff(100); return; } @@ -660,7 +1015,8 @@ failtag: * - *datain used as error return * - tracing is falsed */ -void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { +void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) +{ MF_DBGLEVEL = MF_DBG_NONE; uint8_t numSectors = arg0; @@ -675,9 +1031,6 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat byte_t dataoutbuf2[16]; // uint8_t uid[10]; - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); @@ -686,23 +1039,30 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat bool isOK = true; // iso14443a_fast_select_card(cjuid, 0); - if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) { + if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) + { isOK = false; if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_RAWPRINT, "Can't select card"); } - for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) { + for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) + { ui64Key = emlGetKey(sectorNo, keyType); - if (sectorNo == 0) { - if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { + if (sectorNo == 0) + { + if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) + { isOK = false; if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "Sector[%2d]. Auth error", sectorNo); break; } - } else { - if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) { + } + else + { + if (isOK && mifare_classic_auth(pcs, cjcuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) + { isOK = false; if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "Sector[%2d]. Auth nested error", sectorNo); @@ -710,29 +1070,38 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat } } - for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { - if (isOK && mifare_classic_readblock(pcs, cjcuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) { + for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) + { + if (isOK && mifare_classic_readblock(pcs, cjcuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) + { isOK = false; if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "Error reading sector %2d block %2d", sectorNo, blockNo); break; }; - if (isOK) { + if (isOK) + { *datain = 1; - if (blockNo < NumBlocksPerSector(sectorNo) - 1) { + if (blockNo < NumBlocksPerSector(sectorNo) - 1) + { emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1); - } else { // sector trailer, keep the keys, set only the AC + } + else + { // sector trailer, keep the keys, set only the AC emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4); emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); } - } else { + } + else + { *datain = 0; } } } - if (mifare_classic_halt(pcs, cjcuid)) { + if (mifare_classic_halt(pcs, cjcuid)) + { if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "Halt error"); }; @@ -741,7 +1110,6 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat crypto1_destroy(pcs); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); if (MF_DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED\n"); @@ -752,7 +1120,8 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat /* the chk function is a piwi’ed(tm) check that will try all keys for a particular sector. also no tracing no dbg */ -int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key) { +int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key) +{ MF_DBGLEVEL = MF_DBG_NONE; iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); set_tracing(false); @@ -763,40 +1132,41 @@ int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, ui pcs = &mpcs; // byte_t isOK = 0; - for (int i = 0; i < keyCount; ++i) { - LEDsoff(); + for (int i = 0; i < keyCount; ++i) + { /* no need for anticollision. just verify tag is still here */ // if (!iso14443a_fast_select_card(cjuid, 0)) { - if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) { + if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) + { cjSetCursLeft(); DbprintfEx(FLAG_NOLOG, "%sFATAL%s : E_MF_LOSTTAG", _RED_, _WHITE_); return -1; } uint64_t ui64Key = bytes_to_num(datain + i * 6, 6); - if (mifare_classic_auth(pcs, cjcuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { + if (mifare_classic_auth(pcs, cjcuid, blockNo, keyType, ui64Key, AUTH_FIRST)) + { uint8_t dummy_answer = 0; ReaderTransmit(&dummy_answer, 1, NULL); // wait for the card to become ready again SpinDelayUs(AUTHENTICATION_TIMEOUT); continue; } - LED_A_ON(); crypto1_destroy(pcs); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); *key = ui64Key; return i; } - LED_A_ON(); crypto1_destroy(pcs); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); return -1; } -void saMifareMakeTag(void) { - // uint8_t cfail = 0;` +void saMifareMakeTag(void) +{ + uint8_t cfail = 0; cjSetCursLeft(); cjTabulize(); vtsend_cursor_position_save(NULL); @@ -808,8 +1178,8 @@ void saMifareMakeTag(void) { DbprintfEx(FLAG_NOLOG, ">> Write to Special:"); int flags = 0; - LED_A_ON(); // yellow - for (int blockNum = 0; blockNum < 16 * 4; blockNum++) { + for (int blockNum = 0; blockNum < 16 * 4; blockNum++) + { uint8_t mblock[16]; // cnt = 0; emlGetMem(mblock, blockNum, 1); @@ -825,10 +1195,12 @@ void saMifareMakeTag(void) { if (blockNum == 16 * 4 - 1) flags = 0x04 + 0x10; - if (saMifareCSetBlock(0, flags & 0xFE, blockNum, mblock)) { //&& cnt <= retry) { - // cnt++; + if (saMifareCSetBlock(0, flags & 0xFE, blockNum, mblock)) + { //&& cnt <= retry) { + // cnt++; cjSetCursFRight(); - if (currfline > 53) { + if (currfline > 53) + { currfline = 54; } DbprintfEx(FLAG_NOLOG, "Block :%02x %sOK%s", blockNum, _GREEN_, _WHITE_); @@ -836,14 +1208,16 @@ void saMifareMakeTag(void) { // cfail=1; // return; continue; - } else { + } + else + { cjSetCursLeft(); cjSetCursLeft(); DbprintfEx(FLAG_NOLOG, "`--> %sFAIL%s : CHN_FAIL_BLK_%02x_NOK", _RED_, _WHITE_, blockNum); cjSetCursFRight(); DbprintfEx(FLAG_NOLOG, "%s>>>>%s STOP AT %02x", _RED_, _WHITE_, blockNum); - + cfail++; break; } cjSetCursFRight(); @@ -855,13 +1229,20 @@ void saMifareMakeTag(void) { break; } */ } + if (cfail == 0) + { + SpinUp(50); + SpinUp(50); + SpinUp(50); + } } //----------------------------------------------------------------------------- // Matt's StandAlone mod. // Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn) //----------------------------------------------------------------------------- -int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { +int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) +{ // params uint8_t needWipe = arg0; @@ -888,30 +1269,32 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; // reset FPGA and LED - if (workFlags & 0x08) { - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); + if (workFlags & 0x08) + { iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); // clear_trace(); set_tracing(FALSE); } - while (true) { - // cjSetCursLeft(); + while (true) + { + cjSetCursLeft(); // get UID from chip - if (workFlags & 0x01) { + if (workFlags & 0x01) + { // if (!iso14443a_fast_select_card(cjuid, 0)) { - if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) { + if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) + { if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "Can't select card"); break; }; - if (mifare_classic_halt(NULL, cjcuid)) { + if (mifare_classic_halt(NULL, cjcuid)) + { if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "Halt error"); break; @@ -919,22 +1302,26 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data }; // reset chip - if (needWipe) { + if (needWipe) + { ReaderTransmitBitsPar(wupC1, 7, 0, NULL); - if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) + { // if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "wupC1 error"); break; }; ReaderTransmit(wipeC, sizeof(wipeC), NULL); - if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) + { if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "wipeC error"); break; }; - if (mifare_classic_halt(NULL, cjcuid)) { + if (mifare_classic_halt(NULL, cjcuid)) + { if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "Halt error"); break; @@ -943,39 +1330,46 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data // chaud // write block - if (workFlags & 0x02) { + if (workFlags & 0x02) + { ReaderTransmitBitsPar(wupC1, 7, 0, NULL); - if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) + { // if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "wupC1 error"); break; }; ReaderTransmit(wupC2, sizeof(wupC2), NULL); - if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) + { // if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "wupC2 errorv"); break; }; } - if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { + if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) + { // if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "write block send command error"); break; }; memcpy(d_block, datain, 16); - AddCrc14A(d_block,16); + AddCrc14A(d_block, 16); ReaderTransmit(d_block, sizeof(d_block), NULL); - if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) { + if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) + { // if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "write block send data error"); break; }; - if (workFlags & 0x04) { - if (mifare_classic_halt(NULL, cjcuid)) { + if (workFlags & 0x04) + { + if (mifare_classic_halt(NULL, cjcuid)) + { // if (MF_DBGLEVEL >= 1) cjSetCursFRight(); @@ -988,12 +1382,10 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data break; } - if ((workFlags & 0x10) || (!isOK)) { + if ((workFlags & 0x10) || (!isOK)) + { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); } return isOK; } - - diff --git a/armsrc/Standalone/hf_colin.h b/armsrc/Standalone/hf_colin.h index 83c152095..29f8f52e6 100644 --- a/armsrc/Standalone/hf_colin.h +++ b/armsrc/Standalone/hf_colin.h @@ -16,18 +16,21 @@ #ifndef __HF_COLIN_H #define __HF_COLIN_H -#include // for bool -#include -#include -#include "standalone.h" // standalone definitions + #include "proxmark3.h" #include "mifareutil.h" #include "iso14443a.h" +//#include "printf.h" #include "protocols.h" #include "util.h" +#include "standalone.h" // standalone definitions +#include // for bool +#include +#include +//#include #include "vtsend.h" #include "apps.h" -#include "usb_cmd.h" // mifare1ksim flags +#include "printf.h" #define _RED_ "\x1b[31m" #define _GREEN_ "\x1b[32m" @@ -38,14 +41,19 @@ #define _WHITE_ "\x1b[0m" #define _ORANGE_ _YELLOW_ +#define NTIME(n) for (int _index = 0; _index < n; _index++) + int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key); void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void saMifareMakeTag(void); int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug); +void WriteTagToFlash(uint8_t index, size_t size); const char clearTerm[8] = {0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x32, 0x4a, '\0'}; + + #define LOGO logo_kigiv const char sub_banner[] = " From Vigik : \"20 years of (un)security without a single update\""; @@ -410,7 +418,7 @@ const char logo_kigiv[] = { 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x0d, 0x0a}; unsigned int logo_kigiv_len = 9303; -const char logo_kigiv_nocolor[] = { +/*const char logo_kigiv_nocolor[] = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, @@ -494,6 +502,6 @@ const char logo_kigiv_nocolor[] = { 0x30, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x31, 0x31, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x30, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x31, 0x31, 0x30, 0x31, 0x31, 0x0d, 0x0a}; -unsigned int logo_kigiv_nocolor_len = 2153; +unsigned int logo_kigiv_nocolor_len = 2153;*/ #endif /* __HF_COLIN_H */ diff --git a/armsrc/appmain.c b/armsrc/appmain.c index c6e6e0dee..b0538383e 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -33,10 +33,6 @@ #include "i2c.h" #endif -#ifdef WITH_FPC -#include "usart.h" -#endif - //============================================================================= // A buffer where we can queue things up to be sent through the FPGA, for // any purpose (fake tag, as reader, whatever). We go MSB first, since that @@ -78,26 +74,24 @@ void PrintToSendBuffer(void) { } void print_result(char *name, uint8_t *buf, size_t len) { - uint8_t *p = buf; - uint16_t tmp = len & 0xFFF0; - for(; p-buf < tmp; p += 16) { - Dbprintf("[%s: %02d/%02d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + if ( len % 16 == 0 ) { + for(; p-buf < len; p += 16) + Dbprintf("[%s:%d/%d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", name, p-buf, len, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15] ); } - if (len % 16 != 0) { - char s[46] = {0}; - char *sp = s; - for (; p-buf < len; p++ ) { - sprintf(sp, "%02x ", p[0] ); - sp += 3; - } - Dbprintf("[%s: %02d/%02d] %s", name, p-buf, len, s); + else { + for(; p-buf < len; p += 8) + Dbprintf("[%s:%d/%d] %02x %02x %02x %02x %02x %02x %02x %02x", + name, + p-buf, + len, + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); } } @@ -107,7 +101,7 @@ void print_result(char *name, uint8_t *buf, size_t len) { void DbpStringEx(char *str, uint32_t cmd) { #if DEBUG - uint8_t len = strlen(str); + byte_t len = strlen(str); cmd_send(CMD_DEBUG_PRINT_STRING, len, cmd, 0, (byte_t*)str, len); #endif } @@ -119,7 +113,7 @@ void DbpString(char *str) { } #if 0 -void DbpIntegers(int x1, int x2, int x3) { +void DbpIntegers(inst x1, int x2, int x3) { cmd_send(CMD_DEBUG_PRINT_INTEGERS,x1,x2,x3,0,0); } #endif @@ -440,7 +434,7 @@ void printStandAloneModes(void) { DbpString(" LF HID corporate 1000 bruteforce - (Federico dotta & Maurizio Agazzini)"); #endif #if defined(WITH_HF_MATTYRUN) - DbpString(" HF Mifare sniff/clone - aka MattyRun (Matas A. R Medina)"); + DbpString(" HF Mifare sniff/clone - aka MattyRun (Mat�as A. R� Medina)"); #endif #if defined(WITH_HF_COLIN) DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN (Colin Brigato)"); @@ -448,7 +442,6 @@ void printStandAloneModes(void) { //DbpString("Running "); //Dbprintf(" Is Device attached to USB| %s", USB_ATTACHED() ? "Yes" : "No"); - //Dbprintf(" Is Device attached to FPC| %s", 0 ? "Yes" : "No"); //Dbprintf(" Is USB_reconnect value | %d", GetUSBreconnect() ); //Dbprintf(" Is USB_configured value | %d", GetUSBconfigured() ); @@ -1077,7 +1070,6 @@ void UsbPacketReceived(uint8_t *packet, int len) { #endif case CMD_BUFF_CLEAR: BigBuf_Clear(); - BigBuf_free(); break; case CMD_MEASURE_ANTENNA_TUNING: @@ -1114,7 +1106,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { len = MIN( (numofbytes - i), USB_CMD_DATA_SIZE); isok = cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, i, len, BigBuf_get_traceLen(), mem + startidx + i, len); if (!isok) - Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len); + Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); } // Trigger a finish downloading signal with an ACK frame // iceman, when did sending samplingconfig array got attached here?!? @@ -1160,7 +1152,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); isok = cmd_send(CMD_DOWNLOADED_EML_BIGBUF, i, len, 0, mem + startidx + i, len); if (!isok) - Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len); + Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); } // Trigger a finish downloading signal with an ACK frame cmd_send(CMD_ACK, 1, 0, 0, 0, 0); @@ -1177,6 +1169,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { uint16_t isok = 0; uint32_t startidx = c->arg[0]; uint16_t len = c->arg[1]; + uint8_t fast = c->arg[2]; Dbprintf("FlashMem read | %d - %d", startidx, len); @@ -1184,14 +1177,23 @@ void UsbPacketReceived(uint8_t *packet, int len) { uint8_t *mem = BigBuf_malloc(size); + + if (fast) { + FlashInit(1); + //FlashInit(); + Flash_CheckBusy(BUSY_TIMEOUT); + } for(size_t i = 0; i < len; i += size) { len = MIN((len - i), size); - memset(mem, 0, len); - Dbprintf("FlashMem reading | %d | %d | %d", startidx + i, i, len); + if (!fast){ isok = Flash_ReadData(startidx + i, mem, len); + } + if (fast){ + isok = Flash_FastReadDataCont(startidx + i, mem, len); + } if ( isok == len ) { print_result("Chunk: ", mem, len); } else { @@ -1199,6 +1201,9 @@ void UsbPacketReceived(uint8_t *packet, int len) { break; } } + if (fast){ + FlashStop(); + } LED_B_OFF(); break; } @@ -1271,21 +1276,36 @@ void UsbPacketReceived(uint8_t *packet, int len) { size_t len = 0; uint32_t startidx = c->arg[0]; uint32_t numofbytes = c->arg[1]; + uint8_t fast = c->arg[2]; + // arg0 = startindex // arg1 = length bytes to transfer // arg2 = RFU + + + if (fast) { + FlashInit(1); + //FlashInit(); + Flash_CheckBusy(BUSY_TIMEOUT); + } for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); - + if (!fast){ isok = Flash_ReadData(startidx + i, mem, len); + } + if (fast){ + isok = Flash_FastReadDataCont(startidx + i, mem, len); + } if (!isok ) Dbprintf("reading flash memory failed :: | bytes between %d - %d", i, len); isok = cmd_send(CMD_DOWNLOADED_FLASHMEM, i, len, 0, mem, len); if (!isok) - Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len); + Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); + } + if (fast){ + FlashStop(); } - cmd_send(CMD_ACK, 1, 0, 0, 0, 0); LED_B_OFF(); break; @@ -1297,7 +1317,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { bool isok = Flash_ReadData(FLASH_MEM_SIGNATURE_OFFSET, info->signature, FLASH_MEM_SIGNATURE_LEN); - if (FlashInit()) { + if (FlashInit(0)) { Flash_UniqueID( info->flashid); FlashStop(); } @@ -1392,8 +1412,6 @@ void __attribute__((noreturn)) AppMain(void) { LEDsoff(); - usb_enable(); - // The FPGA gets its clock from us from PCK0 output, so set that up. AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0; AT91C_BASE_PIOA->PIO_PDR = GPIO_PCK0; @@ -1419,16 +1437,22 @@ void __attribute__((noreturn)) AppMain(void) { StartTickCount(); #ifdef WITH_LCD - LCDInit(); +// LCDInit(); #endif #ifdef WITH_SMARTCARD - I2C_init(); +// I2C_init(); #endif #ifdef WITH_FPC - usart_init(); +// usart_init(); #endif + + // This is made as late as possible to ensure enumeration without timeout + // against device such as http://www.hobbytronics.co.uk/usb-host-board-v2 + usb_disable(); + usb_enable(); + uint8_t rx[sizeof(UsbCommand)]; for(;;) { @@ -1464,6 +1488,10 @@ void __attribute__((noreturn)) AppMain(void) { RunMod(); #endif + // when here, we are no longer in standalone mode. + // reseting the variables which keeps track of usb re-attached/configured + //SetUSBreconnect(0); + //SetUSBconfigured(0); } } } diff --git a/armsrc/flashmem.c b/armsrc/flashmem.c index 7c5beb47a..b5786fbe9 100644 --- a/armsrc/flashmem.c +++ b/armsrc/flashmem.c @@ -1,39 +1,43 @@ #include "flashmem.h" + +#define MCK 48000000 +//#define FLASH_BAUD 24000000 +//define FLASH_BAUD 33000000 +#define FLASH_BAUD MCK/2 +#define FLASH_FASTBAUD MCK + /* here: use NCPS2 @ PA10: */ -#define SPI_CSR_NUM 2 // Chip Select register[] 0,1,2,3 (at91samv512 has 4) - -/* PCS_0 for NPCS0, PCS_1 for NPCS1 ... */ -#define PCS_0 ((0<<0)|(1<<1)|(1<<2)|(1<<3)) // 0xE - 1110 -#define PCS_1 ((1<<0)|(0<<1)|(1<<2)|(1<<3)) // 0xD - 1101 -#define PCS_2 ((1<<0)|(1<<1)|(0<<2)|(1<<3)) // 0xB - 1011 -#define PCS_3 ((1<<0)|(1<<1)|(1<<2)|(0<<3)) // 0x7 - 0111 - -// TODO -#if (SPI_CSR_NUM == 0) -#define SPI_MR_PCS PCS_0 -#elif (SPI_CSR_NUM == 1) -#define SPI_MR_PCS PCS_1 -#elif (SPI_CSR_NUM == 2) -#define SPI_MR_PCS PCS_2 -#elif (SPI_CSR_NUM == 3) -#define SPI_MR_PCS PCS_3 -#else -#error "SPI_CSR_NUM invalid" -// not realy - when using an external address decoder... -// but this code takes over the complete SPI-interace anyway -#endif +#define SPI_CSR_NUM 2 +#define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16) +/// Calculates the value of the CSR SCBR field given the baudrate and MCK. +#define SPI_SCBR(baudrate, masterClock) ((uint32_t) ((masterClock) / (baudrate)) << 8) +/// Calculates the value of the CSR DLYBS field given the desired delay (in ns) +#define SPI_DLYBS(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 1000) << 16) +/// Calculates the value of the CSR DLYBCT field given the desired delay (in ns) +#define SPI_DLYBCT(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 32000) << 24) -/* - ȡָԴһλÿʼĶܽоƬȡ - ҳдָÿдΪ1-256ֽڣDzܿԽ256ֽڱ߽ - ָָ뽫CSߣ򲻻ִ -*/ -void FlashSetup(void) { - // PA1 -> SPI_NCS3 chip select (MEM) - // PA10 -> SPI_NCS2 chip select (LCD) +// initialize +bool FlashInit(bool fast) { + FlashSetup(fast); + + StartTicks(); + + if (Flash_CheckBusy(BUSY_TIMEOUT)) { + StopTicks(); + return false; + } + + return true; +} + +void FlashSetup(bool fast){ + //WDT_DISABLE + AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS; + + // PA10 -> SPI_NCS2 chip select (FLASHMEM) // PA11 -> SPI_NCS0 chip select (FPGA) // PA12 -> SPI_MISO Master-In Slave-Out // PA13 -> SPI_MOSI Master-Out Slave-In @@ -54,27 +58,71 @@ void FlashSetup(void) { //enable the SPI Peripheral clock AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI); + + //reset spi needs double SWRST, see atmel's errata on this case + AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; + AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; + // Enable SPI AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN; // NPCS2 Mode 0 AT91C_BASE_SPI->SPI_MR = - ( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods) - (0xB << 16) | // Peripheral Chip Select (selects SPI_NCS2 or PA10) - ( 0 << 7) | // Local Loopback Disabled - ( 1 << 4) | // Mode Fault Detection disabled - ( 0 << 2) | // Chip selects connected directly to peripheral - ( 0 << 1) | // Fixed Peripheral Select - ( 1 << 0); // Master Mode + (0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT: + // If DLYBCS is less than or equal to six, six MCK periods + // will be inserted by default. + SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10) + ( 0 << 7) | // Disable LLB (1=MOSI2MISO test mode) + ( 1 << 4) | // Disable ModeFault Protection + ( 0 << 3) | // makes spi operate at MCK (1 is MCK/2) + ( 0 << 2) | // Chip selects connected directly to peripheral + AT91C_SPI_PS_FIXED | // Fixed Peripheral Select + AT91C_SPI_MSTR; // Master Mode + + int baudrate = FLASH_BAUD; + uint8_t csaat = 1; + int dlybct = 0; + if (fast) { + baudrate = FLASH_FASTBAUD; + //csaat = 0; + dlybct = MCK/32; + } - // 8 bit AT91C_BASE_SPI->SPI_CSR[2] = - ( 0 << 24) | // Delay between Consecutive Transfers (32 MCK periods) - ( 0 << 16) | // Delay Before SPCK (1 MCK period) - ( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud - ( 0 << 4) | // Bits per Transfer (8 bits) - ( 1 << 3) | // Chip Select inactive after transfer - ( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge + SPI_DLYBCT(dlybct,MCK) | // Delay between Consecutive Transfers (32 MCK periods) + SPI_DLYBS(0,MCK) | // Delay Beforce SPCK CLock + SPI_SCBR(baudrate,MCK) | // SPI Baudrate Selection + AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits) + //AT91C_SPI_CSAAT | // Chip Select inactive after transfer + // 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1 + // If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on + // the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been + // transferred in the shifter. This can imply for example, that the second data is sent twice. + // COLIN :: For now we STILL use CSAAT=1 to avoid having to (de)assert NPCS manually via PIO lines and we deal with delay + ( csaat << 3) | +/* Spi modes: +Mode CPOL CPHA NCPHA +0 0 0 1 clock normally low read on rising edge +1 0 1 0 clock normally low read on falling edge +2 1 0 1 clock normally high read on falling edge +3 1 1 0 clock normally high read on rising edge +However, page 512 of the AT91SAM7Sx datasheet say "Note that in SPI +master mode the ATSAM7S512/256/128/64/321/32 does not sample the data +(MISO) on the opposite edge where data clocks out (MOSI) but the same +edge is used as shown in Figure 36-3 and Figure 36-4." Figure 36-3 +shows that CPOL=NCPHA=0 or CPOL=NCPHA=1 samples on the rising edge and +that the data changes sometime after the rising edge (about 2 ns). To +be consistent with normal SPI operation, it is probably safe to say +that the data changes on the falling edge and should be sampled on the +rising edge. Therefore, it appears that NCPHA should be treated the +same as CPHA. Thus: +Mode CPOL CPHA NCPHA +0 0 0 0 clock normally low read on rising edge +1 0 1 1 clock normally low read on falling edge +2 1 0 0 clock normally high read on falling edge +3 1 1 1 clock normally high read on rising edge +*/ + ( 0 << 1) | // Clock Phase data captured on leading edge, changes on following edge ( 0 << 0); // Clock Polarity inactive state is logic 0 // read first, empty buffer @@ -82,6 +130,7 @@ void FlashSetup(void) { } void FlashStop(void) { + //Bof //* Reset all the Chip Select register AT91C_BASE_SPI->SPI_CSR[0] = 0; AT91C_BASE_SPI->SPI_CSR[1] = 0; @@ -104,24 +153,21 @@ void FlashStop(void) { // send one byte over SPI uint16_t FlashSendByte(uint32_t data) { - uint16_t incoming = 0; - - WDT_HIT(); // wait until SPI is ready for transfer - while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {}; + //if you are checking for incoming data returned then the TXEMPTY flag is redundant + //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {}; // send the data AT91C_BASE_SPI->SPI_TDR = data; + while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){}; + // wait recive transfer is complete - while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0) - WDT_HIT(); + while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0); // reading incoming data - incoming = ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF); - - return incoming; + return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF); } // send last byte over SPI @@ -132,41 +178,35 @@ uint16_t FlashSendLastByte(uint32_t data) { // read state register 1 uint8_t Flash_ReadStat1(void) { FlashSendByte(READSTAT1); - uint8_t stat1 = FlashSendLastByte(0xFF); -// if ( MF_DBGLEVEL > 3 ) Dbprintf("stat1 [%02x]", stat1); - return stat1; + return FlashSendLastByte(0xFF); } -// read state register 2 -uint8_t Flash_ReadStat2(void) { - FlashSendByte(READSTAT2); - uint8_t stat2 = FlashSendLastByte(0xFF); -// if ( MF_DBGLEVEL > 3 ) Dbprintf("stat2 [%02x]", stat2); - return stat2; -} +bool Flash_CheckBusy(uint32_t timeout) +{ + WaitUS(WINBOND_WRITE_DELAY); + StartCountUS(); + uint32_t _time = GetCountUS(); -// determine whether FLASHMEM is busy -bool Flash_CheckBusy(uint16_t times) { - bool ret = (Flash_ReadStat1() & BUSY); + do + { + if (!(Flash_ReadStat1() & BUSY)) + { + return false; + } + } while ((GetCountUS() - _time) < timeout); - if (!ret || !times || !(times--)) - return ret; - - while (times) { - WDT_HIT(); - SpinDelay(1); - ret = (Flash_ReadStat1() & BUSY); - if (!ret) - break; - times--; + if (timeout <= (GetCountUS() - _time)) + { + return true; } - return ret; + + return false; } // read ID out uint8_t Flash_ReadID(void) { - if (Flash_CheckBusy(100)) return 0; + if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0; // Manufacture ID / device ID FlashSendByte(ID); @@ -188,7 +228,7 @@ uint8_t Flash_ReadID(void) { // read unique id for chip. void Flash_UniqueID(uint8_t *uid) { - if (Flash_CheckBusy(100)) return; + if (Flash_CheckBusy(BUSY_TIMEOUT)) return; // reading unique serial number FlashSendByte(UNIQUE_ID); @@ -209,12 +249,10 @@ void Flash_UniqueID(uint8_t *uid) { uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) { - if (!FlashInit()) return 0; - - Flash_ReadStat1(); - + if (!FlashInit(0)) return 0; + // length should never be zero - if (!len || Flash_CheckBusy(100)) return 0; + if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0; FlashSendByte(READDATA); FlashSendByte((address >> 16) & 0xFF); @@ -231,6 +269,55 @@ uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) { return len; } +/* This ensure we can ReadData without having to cycle through initialization everytime */ +uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) { + + // length should never be zero + if (!len) return 0; + + FlashSendByte(READDATA); + FlashSendByte((address >> 16) & 0xFF); + FlashSendByte((address >> 8) & 0xFF); + FlashSendByte((address >> 0) & 0xFF); + + uint16_t i = 0; + for (; i < (len - 1); i++) + out[i] = FlashSendByte(0xFF); + + out[i] = FlashSendLastByte(0xFF); + + return len; +} + +uint16_t Flash_FastReadDataCont(uint32_t address, uint8_t *out, uint16_t len) { + + // length should never be zero + if (!len) return 0; + + //if (Flash_CheckBusy(BUSY_TIMEOUT)) + //{return 0;} + + FlashSendByte(FASTREAD); + FlashSendByte((address >> 16) & 0xFF); + FlashSendByte((address >> 8) & 0xFF); + FlashSendByte((address >> 0) & 0xFF); + FlashSendByte(0xFF); + //Flash_CheckBusy(BUSY_TIMEOUT); + + + uint16_t i = 0; + for (; i < (len - 1); i++) + out[i] = FlashSendByte(0xFF); + + out[i] = FlashSendLastByte(0xFF); + + return len; +} + + + +//////////////////////////////////////// + // Write data can only program one page. A page has 256 bytes. // if len > 256, it might wrap around and overwrite pos 0. uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { @@ -251,12 +338,13 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { return 0; } - if (!FlashInit()) { + if (!FlashInit(0)) { if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); return 0; } - Flash_ReadStat1(); + Flash_CheckBusy(BUSY_TIMEOUT); + //Flash_ReadStat1(); Flash_WriteEnable(); @@ -275,22 +363,61 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { return len; } +uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) { + + // length should never be zero + if (!len) + return 0; + + // Max 256 bytes write + if (((address & 0xFF) + len) > 256) { + Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len ); + return 0; + } + + // out-of-range + if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) { + Dbprintf("Flash_WriteData, block out-of-range"); + return 0; + } + + + //Flash_CheckBusy(100); + //SpinDelay(1); + Flash_CheckBusy(BUSY_TIMEOUT); + //Flash_ReadStat1(); + Flash_WriteEnable(); + + FlashSendByte(PAGEPROG); + FlashSendByte((address >> 16) & 0xFF); + FlashSendByte((address >> 8) & 0xFF); + FlashSendByte((address >> 0) & 0xFF); + + uint16_t i = 0; + for (; i < (len - 1); i++) + FlashSendByte(in[i]); + + FlashSendLastByte(in[i]); + + return len; +} + bool Flash_WipeMemoryPage(uint8_t page) { - if (!FlashInit()) { + if (!FlashInit(0)) { if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); return false; } Flash_ReadStat1(); // Each block is 64Kb. One block erase takes 1s ( 1000ms ) - Flash_WriteEnable(); Flash_Erase64k(page); Flash_CheckBusy(1000); + Flash_WriteEnable(); Flash_Erase64k(page); Flash_CheckBusy(BUSY_TIMEOUT); FlashStop(); return true; } // Wipes flash memory completely, fills with 0xFF bool Flash_WipeMemory() { - if (!FlashInit()) { + if (!FlashInit(0)) { if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); return false; } @@ -298,10 +425,10 @@ bool Flash_WipeMemory() { // Each block is 64Kb. Four blocks // one block erase takes 1s ( 1000ms ) - Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(1000); - Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(1000); - Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(1000); - Flash_WriteEnable(); Flash_Erase64k(3); Flash_CheckBusy(1000); + Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); Flash_Erase64k(3); Flash_CheckBusy(BUSY_TIMEOUT); FlashStop(); return true; @@ -366,25 +493,13 @@ void Flash_EraseChip(void) { FlashSendLastByte(CHIPERASE); } -// initialize -bool FlashInit(void) { - FlashSetup(); - StartTicks(); - - if (Flash_CheckBusy(100)) { - StopTicks(); - return false; - } - if ( MF_DBGLEVEL > 3 ) Dbprintf("FlashInit OK"); - return true; -} void Flashmem_print_status(void) { DbpString("Flash memory"); - if (!FlashInit()) { + if (!FlashInit(0)) { DbpString(" init....................FAIL"); return; } @@ -414,4 +529,4 @@ void Flashmem_print_status(void) { ); FlashStop(); -} \ No newline at end of file +} diff --git a/armsrc/flashmem.h b/armsrc/flashmem.h index 198e3392d..3563eb41d 100644 --- a/armsrc/flashmem.h +++ b/armsrc/flashmem.h @@ -45,6 +45,7 @@ #define WRITEENABLE 0x06 #define READDATA 0x03 +#define FASTREAD 0x0B #define PAGEPROG 0x02 #define SECTORERASE 0x20 @@ -57,27 +58,17 @@ // Not used or not support command #define RELEASE 0xAB #define POWERDOWN 0xB9 -#define FASTREAD 0x0B #define SUSPEND 0x75 #define RESUME 0x7A +#define BUSY_TIMEOUT 1000000000L -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -// Chip specific instructions // -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - -//~~~~~~~~~~~~~~~~~~~~~~~~~ Winbond ~~~~~~~~~~~~~~~~~~~~~~~~~// #define WINBOND_MANID 0xEF #define WINBOND_DEVID 0x11 #define PAGESIZE 0x100 +#define WINBOND_WRITE_DELAY 0x02 -//~~~~~~~~~~~~~~~~~~~~~~~~ Microchip ~~~~~~~~~~~~~~~~~~~~~~~~// -#define MICROCHIP_MANID 0xBF -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -// Definitions // -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// - -#define SPI_CLK 75000000 //Hex equivalent of 75MHz +#define SPI_CLK 48000000 #define BUSY 0x01 #define WRTEN 0x02 @@ -113,14 +104,17 @@ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// extern void Dbprintf(const char *fmt, ...); - -void FlashSetup(void); +bool FlashInit(bool fast); +void FlashSetup(bool fast); void FlashStop(void); bool Flash_WaitIdle(void); uint8_t Flash_ReadStat1(void); uint8_t Flash_ReadStat2(void); uint16_t FlashSendByte(uint32_t data); +bool Flash_CheckBusy(uint32_t timeout); + + void Flash_WriteEnable(); bool Flash_WipeMemoryPage(uint8_t page); bool Flash_WipeMemory(); @@ -128,12 +122,16 @@ bool Flash_Erase4k(uint8_t block, uint8_t sector); //bool Flash_Erase32k(uint32_t address); bool Flash_Erase64k(uint8_t block); -bool FlashInit(); void Flash_UniqueID(uint8_t *uid); uint8_t Flash_ReadID(void); uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len); + +uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len); +uint16_t Flash_FastReadDataCont(uint32_t address, uint8_t *out, uint16_t len); + uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len); +uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len); void Flashmem_print_status(void); #endif \ No newline at end of file diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index 2b86bdcfc..5f83f9263 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -15,9 +15,10 @@ static int CmdHelp(const char *Cmd); int usage_flashmem_read(void){ PrintAndLogEx(NORMAL, "Read flash memory on device"); - PrintAndLogEx(NORMAL, "Usage: mem read o l "); + PrintAndLogEx(NORMAL, "Usage: mem read o l [f]"); PrintAndLogEx(NORMAL, " o : offset in memory"); PrintAndLogEx(NORMAL, " l : length"); + PrintAndLogEx(NORMAL, " f : fastRead mode"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " mem read o 0 l 32"); // read 32 bytes starting at offset 0 @@ -41,6 +42,7 @@ int usage_flashmem_save(void){ PrintAndLogEx(NORMAL, " o : offset in memory"); PrintAndLogEx(NORMAL, " l : length"); PrintAndLogEx(NORMAL, " f : file name"); + PrintAndLogEx(NORMAL, " + : fast read mode"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " mem save f myfile"); // download whole flashmem to file myfile @@ -79,9 +81,14 @@ int CmdFlashMemRead(const char *Cmd) { uint8_t cmdp = 0; bool errors = false; uint32_t start_index = 0, len = 0; + uint8_t fast = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { + case 'f': + fast = 1; + cmdp += 1; + break; case 'o': start_index = param_get32ex(Cmd, cmdp+1, 0, 10); cmdp += 2; @@ -107,7 +114,7 @@ int CmdFlashMemRead(const char *Cmd) { return 1; } - UsbCommand c = {CMD_READ_FLASH_MEM, {start_index, len, 0}}; + UsbCommand c = {CMD_READ_FLASH_MEM, {start_index, len, fast}}; clearCommandBuffer(); SendCommand(&c); return 0; @@ -221,6 +228,7 @@ int CmdFlashMemSave(const char *Cmd){ uint8_t cmdp = 0; bool errors = false; uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE; + uint8_t fast = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { @@ -233,6 +241,10 @@ int CmdFlashMemSave(const char *Cmd){ start_index = param_get32ex(Cmd, cmdp+1, 0, 10); cmdp += 2; break; + case '+': + fast = 1; + cmdp += 1; + break; case 'f': //File handling if ( param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) { diff --git a/client/cmdmain.c b/client/cmdmain.c index ea118a2f0..ac391f1b8 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -199,7 +199,31 @@ void UsbCommandReceived(UsbCommand* _ch) { memset(s, 0x00, sizeof(s)); size_t len = MIN(c->arg[0], USB_CMD_DATA_SIZE); memcpy(s, c->d.asBytes, len); - + + //#define FLAG_RAWPRINT 0x0111 + //#define FLAG_NOOPT 0x0000 + //#define FLAG_NOLOG 0x0001 + //#define FLAG_NONEWLINE 0x0010 + //#define FLAG_NOPROMPT 0x0100 + uint64_t flag = c->arg[1]; + if (flag > 0) { // FLAG_RAWPRINT) { + switch (flag) { + case FLAG_RAWPRINT: { + printf("%s", s); + } return; break; + case FLAG_NONEWLINE: { + printf("%s\r", s); + } return; break; + case FLAG_NOLOG: { + printf("%s\r\n", s); + } return; break; + // printf("%s", s); + fflush(stdout); + return; + } + } + + // print debug line on same row. escape seq \r if ( c->arg[1] == CMD_MEASURE_ANTENNA_TUNING_HF) { PrintAndLogEx(NORMAL, "\r#db# %s", s); From ecb0f2118462b3b2527311ed2a31b7ba018ccc06 Mon Sep 17 00:00:00 2001 From: xilni Date: Tue, 4 Sep 2018 22:23:49 -0400 Subject: [PATCH 0002/1938] feature: Handle Kastle format 32 bit cards --- client/cmdlfhid.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index 08cbc8661..63857751e 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -167,6 +167,7 @@ int CmdHIDDemod(const char *Cmd) { PrintAndLogEx(NORMAL, "HID Prox TAG ID: %x%08x%08x (%u)", hi2, hi, lo, (lo>>1) & 0xFFFF); } else { //standard HID tags <38 bits uint8_t fmtLen = 0; + uint32_t cc = 0; uint32_t fc = 0; uint32_t cardnum = 0; if ((( hi >> 5) & 1) == 1){//if bit 38 is set then < 37 bit format is used @@ -184,6 +185,11 @@ int CmdHIDDemod(const char *Cmd) { cardnum = (lo >> 1) & 0xFFFF; fc = ( lo >> 17) & 0xFF; } + if(fmtLen==32 && (lo & 0x40000000)){//if 32 bit and Kastle bit set + cardnum = (lo >> 1) & 0xFFFF; + fc = (lo >> 17) & 0xFF; + cc = (lo >> 25) & 0x1F; + } if(fmtLen==34){ cardnum = (lo >> 1) & 0xFFFF; fc= ((hi & 1)<< 15) | (lo >> 17); @@ -202,7 +208,11 @@ int CmdHIDDemod(const char *Cmd) { fc = ((hi & 0xF) << 12) | (lo >> 20); } } - PrintAndLogEx(NORMAL, "HID Prox TAG ID: %x%08x (%u) - Format Len: %ubit - FC: %u - Card: %u", hi, lo, (lo>>1) & 0xFFFF, fmtLen, fc, cardnum); + if(fmtLen==32 && (lo & 0x40000000)){//if 32 bit and Kastle bit set + PrintAndLogEx(NORMAL, "HID Prox TAG (Kastle format) ID: %08x (%u) - Format Len: 32bit - CC: %u - FC: %u - Card: %u", lo, (lo >> 1) & 0xFFFF, cc, fc, cardnum); + }else{ + PrintAndLogEx(NORMAL, "HID Prox TAG ID: %x%08x (%u) - Format Len: %ubit - FC: %u - Card: %u", hi, lo, (lo >> 1) & 0xFFFF, fmtLen, fc, cardnum); + } } PrintAndLogEx(DEBUG, "DEBUG: HID idx: %d, Len: %d, Printing Demod Buffer:", idx, size); From 2263c826dbf33a02a63648fbde7736e0f105d502 Mon Sep 17 00:00:00 2001 From: "Colin J. Brigato" Date: Wed, 5 Sep 2018 20:34:28 +0200 Subject: [PATCH 0003/1938] Restore Makefile, temporiraly provide Makefile.Colin --- armsrc/Makefile | 65 ++++++++++++--- armsrc/Makefile.colin | 183 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 239 insertions(+), 9 deletions(-) create mode 100644 armsrc/Makefile.colin diff --git a/armsrc/Makefile b/armsrc/Makefile index fb2a2a91b..55699b564 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -1,4 +1,4 @@ -#----------------------------------------------------------------------------- + # This code is licensed to you under the terms of the GNU GPL, version 2 or, # at your option, any later version. See the LICENSE.txt file for the text of # the license. @@ -24,7 +24,8 @@ APP_CFLAGS = -DWITH_CRC \ -DWITH_FLASH \ -DWITH_SMARTCARD \ -DWITH_HFSNOOP \ - -DWITH_HF_COLIN \ + -DWITH_LF_SAMYRUN \ + -DWITH_FPC \ -fno-strict-aliasing -ffunction-sections -fdata-sections ### IMPORTANT - move the commented variable below this line @@ -54,11 +55,58 @@ SRC_CRAPTO1 = crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire SRC_CRC = crc.c crc16.c crc32.c SRC_ICLASS = iclass.c optimized_cipher.c SRC_LEGIC = legicrf.c legic_prng.c -SRC_FLASH = flashmem.c -SRC_SMARTCARD = i2c.c -#SRC_FPC = usart.c SRC_BEE = bee.c +# RDV40 related hardware support +ifneq (,$(findstring WITH_FLASH,$(APP_CFLAGS))) + SRC_FLASH = flashmem.c +else + SRC_FLASH = +endif + +ifneq (,$(findstring WITH_SMARTCARD,$(APP_CFLAGS))) + SRC_SMARTCARD = i2c.c +else + SRC_SMARTCARD = +endif + +ifneq (,$(findstring WITH_FPC,$(APP_CFLAGS))) + SRC_FPC = usart.c +else + SRC_FPC = +endif + +# Generic standalone Mode injection of source code +SRC_STANDALONE = +# WITH_LF_ICERUN +ifneq (,$(findstring WITH_LF_ICERUN,$(APP_CFLAGS))) + SRC_STANDALONE = +endif +# WITH_LF_SAMYRUN +ifneq (,$(findstring WITH_LF_SAMYRUN,$(APP_CFLAGS))) + SRC_STANDALONE = lf_samyrun.c +endif +# WITH_LF_PROXBRUTE +ifneq (,$(findstring WITH_LF_PROXBRUTE,$(APP_CFLAGS))) + SRC_STANDALONE = lf_proxbrute.c +endif +# WITH_LF_HIDBRUTE +ifneq (,$(findstring WITH_LF_HIDBRUTE,$(APP_CFLAGS))) + SRC_STANDALONE = lf_hidbrute.c +endif +# WITH_HF_YOUNG +ifneq (,$(findstring WITH_HF_YOUNG,$(APP_CFLAGS))) + SRC_STANDALONE = hf_young.c +endif +# WITH_HF_MATTYRUN +ifneq (,$(findstring WITH_HF_MATTYRUN,$(APP_CFLAGS))) + SRC_STANDALONE = hf_mattyrun.c +endif +# WITH_HF_COLIN +ifneq (,$(findstring WITH_HF_COLIN,$(APP_CFLAGS))) + SRC_STANDALONE = hf_colin.c vtsend.c +endif + #the FPGA bitstream files. Note: order matters! FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit @@ -103,12 +151,10 @@ ARMSRC = fpgaloader.c \ $(SRC_EMV) \ $(SRC_CRC) \ $(SRC_FELICA) \ + $(SRC_STANDALONE) \ parity.c \ usb_cdc.c \ - cmd.c \ - vtsend.c \ - hf_colin.c \ - lib_AT91SAM7.c + cmd.c VERSIONSRC = version.c \ fpga_version_info.c @@ -117,6 +163,7 @@ VERSIONSRC = version.c \ include ../common/Makefile.common COMMON_FLAGS = -Os + OBJS = $(OBJDIR)/fullimage.s19 FPGA_COMPRESSOR = ../client/fpga_compress diff --git a/armsrc/Makefile.colin b/armsrc/Makefile.colin new file mode 100644 index 000000000..fb2a2a91b --- /dev/null +++ b/armsrc/Makefile.colin @@ -0,0 +1,183 @@ +#----------------------------------------------------------------------------- +# This code is licensed to you under the terms of the GNU GPL, version 2 or, +# at your option, any later version. See the LICENSE.txt file for the text of +# the license. +#----------------------------------------------------------------------------- +# Makefile for armsrc, see ../common/Makefile.common for common settings +#----------------------------------------------------------------------------- + +APP_INCLUDES = apps.h + +#remove one of the following defines and comment out the relevant line +#in the next section to remove that particular feature from compilation. +# NO space,TABs after the "\" sign. +APP_CFLAGS = -DWITH_CRC \ + -DON_DEVICE \ + -DWITH_LF \ + -DWITH_HITAG \ + -DWITH_ISO15693 \ + -DWITH_LEGICRF \ + -DWITH_ISO14443b \ + -DWITH_ISO14443a \ + -DWITH_ICLASS \ + -DWITH_FELICA \ + -DWITH_FLASH \ + -DWITH_SMARTCARD \ + -DWITH_HFSNOOP \ + -DWITH_HF_COLIN \ + -fno-strict-aliasing -ffunction-sections -fdata-sections + +### IMPORTANT - move the commented variable below this line +# -DWITH_LCD \ +# -DWITH_EMV \ +# -DWITH_FPC \ +# +# Standalone Mods +#------------------------------------------------------- +# -DWITH_LF_ICERUN +# -DWITH_LF_SAMYRUN +# -DWITH_LF_PROXBRUTE +# -DWITH_LF_HIDBRUTE +# -DWITH_HF_YOUNG +# -DWITH_HF_MATTYRUN +# -DWITH_HF_COLIN + + +SRC_LCD = fonts.c LCD.c +SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c +SRC_ISO15693 = iso15693.c iso15693tools.c +#SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c +SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c +SRC_ISO14443b = iso14443b.c +SRC_FELICA = felica.c +SRC_CRAPTO1 = crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire.c +SRC_CRC = crc.c crc16.c crc32.c +SRC_ICLASS = iclass.c optimized_cipher.c +SRC_LEGIC = legicrf.c legic_prng.c +SRC_FLASH = flashmem.c +SRC_SMARTCARD = i2c.c +#SRC_FPC = usart.c +SRC_BEE = bee.c + +#the FPGA bitstream files. Note: order matters! +FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit + +#the zlib source files required for decompressing the fpga config at run time +SRC_ZLIB = inflate.c inffast.c inftrees.c adler32.c zutil.c +#additional defines required to compile zlib +ZLIB_CFLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED +APP_CFLAGS += $(ZLIB_CFLAGS) +# zlib includes: +APP_CFLAGS += -I../zlib + +# stdint.h provided locally until GCC 4.5 becomes C99 compliant +APP_CFLAGS += -I. + +# Compile these in thumb mode (small size) +THUMBSRC = start.c \ + protocols.c \ + $(SRC_LCD) \ + $(SRC_ISO15693) \ + $(SRC_LF) \ + $(SRC_ZLIB) \ + $(SRC_LEGIC) \ + $(SRC_FLASH) \ + $(SRC_SMARTCARD) \ + $(SRC_FPC) \ + appmain.c \ + printf.c \ + util.c \ + string.c \ + BigBuf.c \ + ticks.c \ + random.c \ + hfsnoop.c + + +# These are to be compiled in ARM mode +ARMSRC = fpgaloader.c \ + $(SRC_ISO14443a) \ + $(SRC_ISO14443b) \ + $(SRC_CRAPTO1) \ + $(SRC_ICLASS) \ + $(SRC_EMV) \ + $(SRC_CRC) \ + $(SRC_FELICA) \ + parity.c \ + usb_cdc.c \ + cmd.c \ + vtsend.c \ + hf_colin.c \ + lib_AT91SAM7.c + +VERSIONSRC = version.c \ + fpga_version_info.c + +# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC +include ../common/Makefile.common + +COMMON_FLAGS = -Os +OBJS = $(OBJDIR)/fullimage.s19 +FPGA_COMPRESSOR = ../client/fpga_compress + +all: $(OBJS) + +.DELETE_ON_ERROR: + +# version.c should be remade on every compilation +.PHONY: version.c +version.c: default_version.c + perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@ + +fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) + $(FPGA_COMPRESSOR) -v $(filter %.bit,$^) $@ + +$(OBJDIR)/fpga_all.o: $(OBJDIR)/fpga_all.bit.z + $(OBJCOPY) -O elf32-littlearm -I binary -B arm --prefix-sections=fpga_all_bit $^ $@ + +$(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) + $(FPGA_COMPRESSOR) $(filter %.bit,$^) $@ + +$(FPGA_COMPRESSOR): + make -C ../client $(notdir $(FPGA_COMPRESSOR)) + +$(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) + $(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS) + +$(OBJDIR)/fullimage.nodata.bin: $(OBJDIR)/fullimage.stage1.elf + $(OBJCOPY) -O binary -I elf32-littlearm --remove-section .data $^ $@ + +$(OBJDIR)/fullimage.nodata.o: $(OBJDIR)/fullimage.nodata.bin + $(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=stage1_image $^ $@ + +$(OBJDIR)/fullimage.data.bin: $(OBJDIR)/fullimage.stage1.elf + $(OBJCOPY) -O binary -I elf32-littlearm --only-section .data $^ $@ + +$(OBJDIR)/fullimage.data.bin.z: $(OBJDIR)/fullimage.data.bin $(FPGA_COMPRESSOR) + $(FPGA_COMPRESSOR) $(filter %.bin,$^) $@ + +$(OBJDIR)/fullimage.data.o: $(OBJDIR)/fullimage.data.bin.z + $(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=compressed_data $^ $@ + +$(OBJDIR)/fullimage.elf: $(OBJDIR)/fullimage.nodata.o $(OBJDIR)/fullimage.data.o + $(CC) $(LDFLAGS) -Wl,-T,ldscript,-e,_osimage_entry,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ + +tarbin: $(OBJS) + $(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=armsrc/%) $(OBJS:%.s19=armsrc/%.elf) + +clean: + $(DELETE) $(OBJDIR)$(PATHSEP)*.o + $(DELETE) $(OBJDIR)$(PATHSEP)*.elf + $(DELETE) $(OBJDIR)$(PATHSEP)*.s19 + $(DELETE) $(OBJDIR)$(PATHSEP)*.map + $(DELETE) $(OBJDIR)$(PATHSEP)*.d + $(DELETE) $(OBJDIR)$(PATHSEP)*.z + $(DELETE) $(OBJDIR)$(PATHSEP)*.bin + $(DELETE) version.c + +.PHONY: all clean help +help: + @echo Multi-OS Makefile, you are running on $(DETECTED_OS) + @echo Possible targets: + @echo + all - Build the full image $(OBJDIR)/fullimage.s19 + @echo + clean - Clean $(OBJDIR) From 6ca899d130f4dcf2f8159d23ac5df90f20503d17 Mon Sep 17 00:00:00 2001 From: AntiCat Date: Wed, 5 Sep 2018 22:23:18 +0200 Subject: [PATCH 0004/1938] FPGA Hi-Simulate: Formatted code --- fpga/hi_simulate.v | 15 +++++---------- 1 file changed, 5 insertions(+), 10 deletions(-) diff --git a/fpga/hi_simulate.v b/fpga/hi_simulate.v index 0768c29de..3976de93d 100644 --- a/fpga/hi_simulate.v +++ b/fpga/hi_simulate.v @@ -59,7 +59,7 @@ always @(posedge adc_clk) ssp_clk_divider <= (ssp_clk_divider + 1); reg ssp_clk; -reg ssp_frame; + always @(negedge adc_clk) begin //If we're in 101, we only need a new bit every 8th carrier bit (53Hz). Otherwise, get next bit at 424Khz @@ -81,8 +81,6 @@ begin end -//assign ssp_clk = ssp_clk_divider[4]; - // Divide SSP_CLK by 8 to produce the byte framing signal; the phase of // this is arbitrary, because it's just a bitstream. // One nasty issue, though: I can't make it work with both rx and tx at @@ -96,12 +94,12 @@ always @(negedge ssp_clk) ssp_frame_divider_from_arm <= (ssp_frame_divider_from_arm + 1); - +reg ssp_frame; always @(ssp_frame_divider_to_arm or ssp_frame_divider_from_arm or mod_type) if(mod_type == 3'b000) // not modulating, so listening, to ARM ssp_frame = (ssp_frame_divider_to_arm == 3'b000); else - ssp_frame = (ssp_frame_divider_from_arm == 3'b000); + ssp_frame = (ssp_frame_divider_from_arm == 3'b000); // Synchronize up the after-hysteresis signal, to produce DIN. reg ssp_din; @@ -116,9 +114,9 @@ always @(mod_type or ssp_clk or ssp_dout) else if(mod_type == 3'b001) modulating_carrier <= ssp_dout ^ ssp_clk_divider[3]; // XOR means BPSK else if(mod_type == 3'b010) - modulating_carrier <= ssp_dout & ssp_clk_divider[5]; // switch 212kHz subcarrier on/off + modulating_carrier <= ssp_dout & ssp_clk_divider[5]; // switch 212kHz subcarrier on/off else if(mod_type == 3'b100 || mod_type == 3'b101) - modulating_carrier <= ssp_dout & ssp_clk_divider[4]; // switch 424kHz modulation on/off + modulating_carrier <= ssp_dout & ssp_clk_divider[4]; // switch 424kHz modulation on/off else modulating_carrier <= 1'b0; // yet unused @@ -134,8 +132,5 @@ assign pwr_oe4 = modulating_carrier; assign pwr_oe3 = 1'b0; assign dbg = modulating_carrier; -//reg dbg; -//always @(ssp_dout) -// dbg <= ssp_dout; endmodule From cef5dc4e838675ef8b69265d39845e68a127009a Mon Sep 17 00:00:00 2001 From: AntiCat Date: Wed, 5 Sep 2018 22:23:20 +0200 Subject: [PATCH 0005/1938] FPGA Hi-Simulate: Fixed documantation --- fpga/hi_simulate.v | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/fpga/hi_simulate.v b/fpga/hi_simulate.v index 3976de93d..65b61d6aa 100644 --- a/fpga/hi_simulate.v +++ b/fpga/hi_simulate.v @@ -51,8 +51,8 @@ begin end -// Divide 13.56 MHz by 32 to produce the SSP_CLK -// The register is bigger to allow higher division factors of up to /128 +// Divide 13.56 MHz to produce various frequencies for SSP_CLK +// and modulation. 11 bits allow for factors of up to /128. reg [10:0] ssp_clk_divider; always @(posedge adc_clk) @@ -106,7 +106,7 @@ reg ssp_din; always @(posedge ssp_clk) ssp_din = after_hysteresis; -// Modulating carrier frequency is fc/16, reuse ssp_clk divider for that +// Modulating carrier frequency is fc/64 (212kHz) to fc/16 (848kHz). Reuse ssp_clk divider for that. reg modulating_carrier; always @(mod_type or ssp_clk or ssp_dout) if(mod_type == 3'b000) From 0994c91888bceb7f407d57d713f4b4e50e1fe9a5 Mon Sep 17 00:00:00 2001 From: AntiCat Date: Wed, 5 Sep 2018 22:23:22 +0200 Subject: [PATCH 0006/1938] FPGA Hi-Simulate: Freed up 4 LUTs --- fpga/hi_simulate.v | 18 ++++-------------- 1 file changed, 4 insertions(+), 14 deletions(-) diff --git a/fpga/hi_simulate.v b/fpga/hi_simulate.v index 65b61d6aa..92445edb6 100644 --- a/fpga/hi_simulate.v +++ b/fpga/hi_simulate.v @@ -62,22 +62,12 @@ reg ssp_clk; always @(negedge adc_clk) begin - //If we're in 101, we only need a new bit every 8th carrier bit (53Hz). Otherwise, get next bit at 424Khz if(mod_type == 3'b101) - begin - if(ssp_clk_divider[7:0] == 8'b00000000) - ssp_clk <= 1'b0; - if(ssp_clk_divider[7:0] == 8'b10000000) - ssp_clk <= 1'b1; - - end + // Get bit every at 53KHz (every 8th carrier bit of 424kHz) + ssp_clk <= ssp_clk_divider[7]; else - begin - if(ssp_clk_divider[4:0] == 5'd0)//[4:0] == 5'b00000) - ssp_clk <= 1'b1; - if(ssp_clk_divider[4:0] == 5'd16) //[4:0] == 5'b10000) - ssp_clk <= 1'b0; - end + // Get next bit at 424Khz + ssp_clk <= ssp_clk_divider[4] end From e472a21194b407fc201b9e310c74f57f32238486 Mon Sep 17 00:00:00 2001 From: AntiCat Date: Wed, 5 Sep 2018 22:23:23 +0200 Subject: [PATCH 0007/1938] FPGA Hi-Simulate: Added 212kHz SSP-Clock option --- fpga/fpga_hf.bit | Bin 42175 -> 42175 bytes fpga/hi_simulate.v | 7 +++++-- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/fpga/fpga_hf.bit b/fpga/fpga_hf.bit index 00e71c432289cab51d023861a43828767f15d241..7e3fc14e2223e60a37b3427515e38c4d3dd62f4b 100644 GIT binary patch literal 42175 zcma&P4R}-6nJ)Ti?QLgUTeddFWSj)jW!X^S%0|eP5C`Oip{+tZMa}fwhndsUqfn;x zZ<*3PZpIN;bqz1tG*u)0Qwyj-XEBq$DE< zZOu>MzDu$t_dNHU=P=JR-4z>Yuf5jyz2EzO?^>lYZ#MsbM6QQu_Ln=p^3Z>6|8hge z#)rQ2*BcuD?n@hJJ-I_)Z3_PVBa4GU`VyI;;NoSA_`QpG6K$Zf(BkGL!RAmC{WZ~G z$1VJM_Iv;7%R!PZBDyW;imCrJf-deN+0qasNBwu2`unmV;q&5ucLhmMlA8<@S`?#d zDkYc1#eXJmMw_6A=}uW{yM|gurMk%}xk0bQTQX}WXWyh-blCA^wGf@!+{F9RT97)_ zJ<_^J3E9Zagf>7UZQF4kpDIiyIc8c~9cM|0GSY5=08Du_J z?t7d$dsu=RBj$FN$$gJI)yl~rw%L>v)MM&f1Zb;ljG6yP7wK@qch2}Jn@^_jeZlBvAuJ&L$&|E_JRjI-&Sj_NKF*IB zDQ1vOe(4X!N3g{3hr8}(n`MJ-w)llaFNJ=PsH$$V=N~x(@yaZ zDd>2pOQ+w`vb2Y-+MZuHqWq`y5w$qptace=@1sRo?F_x{`XqTfv}kEe{nk*)`_4%U z3Qx7hD6K#53Zxzg&~+J#d5)U(`T2^>+DThzmrTUiTwNpEF$A;p{Zu0j5wFa@XNUep zZk09MA8}W@b*F|K2CJka@<;sHG(#|{--=Y7qAtlDBgiVK*Wp=Qcxa#PAIC*ye%>eM zB#o0c-m0xNi<8uRV4JP^#kF+v{tA4O|E&mR;+P%F>u6bVgSU{nFm8yC&oW1~*DyEu zV^}ddLBqn6Ts2NtX(=wWI{La3e#E=;OULuSCG`zhWBfrQ$=;$vG$8y*cO5Poh1t(C zWU23|E(x&5sdlCN47-BA`k_dCo-J|x)U{}(ImTYf&xN782=|EkC_6{b`D@k~55}wL zAT>B<2RoiiBQ#RpN@)sFh19Y%X)pDAwrU&;DXbp;11&f2{qsJ=qlU%fNe$1u=jg-U z?{|&UC0Z`LmiBgONB(*KK*uN~yciBUkqSNR>F-*Ne>JQ=c_}|%%d89~5LPM*D3SFo zGqxhERG^s|b~->R~)>@_KUU*=q_SbaPX^!?isZHeL%TG_qtL!MA z&{T5~7Tzbdx8>EkaH}`jbuu4cerp$!5D3Ev)CuyjwI_reG6O-(%d(el8c=-gVkv(Tj3%#?!97NuzQFe>Jk|J*FOq zjCqf@UQ@&2T6cablYf?>>qsEp1FMeb<4cs>!oO;Yc_y``bPEyhIirQ-N3x~P^XK@A z+vUpcMxC#mQp3K9vQ(vq_R5XiC}l=|-iPMAKrafU3tMXxlOmKYe|{BJ zUyCe1?@4J>za=pf7#H{UBiCIQN3m$T-WT`su;zdBbYec z1K`N5%-lWF`VV@+sm&T!*mBWp)b6A!@we%a?yEMXyNF+6*y6fTgSFDdxipsI;fEzJ zHK~YSLr5t;ry4_+(&dwpRO>~4SPqbxVpI4f=1k(5o1DNH)(;Yh9Z0QG02JD|w!4U5 zN9Y~j8lG9?j`Pw{0~eg;WBkTimB%p&pc0GB7H zOxHHoSz~^C(O8-A3y*X^dq z9AwB%Mf^%rN(2_0`kERm!2-5F$h->C&S2~X{2IbsgojWk`0*Gmgg{#sJ55dfsFn)& zm8C0@6_sA6D~oXf0;G0cpX5ia+qM<)3#rl$0k-a{LtYIL()-8hY7$7D)Mnt4i0aR? zIkZ{SrOjdYHhZt1pEN4t1^il1lX92`5}FTb8P6j%pUm1J1!U9sb;nzDRfMD7o!UEe zRkk$t{ae=+`e>--Vei?l0)D-1pRmL2xAp&asdYjRMRK_O3g*j`tu5f!1SMuIBD0(E z)~!Q+l?wc9D-EcN0)D-Y8ElAR$U1d$Ulhp!7sLf}!Zd!(8U%JPQbSgMRWA}2TR=UM zuQZ-y)A%)K+&a-27Hj*>I_rd^Ubs2mIw3+L@cjaQxw`q)8sz!P+HvD5505WObzM|I z=3r80;8z-1A|N$RX)(+_ou1ee#IgMXba*bY< zEfc7O@3wGZd(UY%=@r?O37n}d;8(xcGOOYE17F=f*SE!Lh@*r!Lz~yttTtlt0)F+= z7HUX5(9t?q;9?Z_yh3q-93Dlqa}|TU>I8MA1Jc|dFXvrOz%i`{Pl?VF|6*fq5x@2@ z)bks>H_R4#)c{E0ndzi#-q~gs@#`YLE-+sy?G#-%5MQ?TE~4^wt1qM#@avQsm+)q_ z%oM(?U&O*Jxr}4{Ay}Z#;_fW46 z*i!M;gXC#S#`C$(&<&I#7>+7;alwuLHDuX(fK0>9Tx#e<T}u?_=B z_*i44kv4^2lRzS5^=ux$sL#O#K2g{-F^yk0_|IgM5vbaMCX zu?H-l%dj!_e=?r6jYPbFUsqUKh8&>q9(s?KIDs8qwec}R;CF*JyIUCV#XKPoxEGt zaCbG{m{8LdG3vk~mpGn~=3!eYNEIB~`1OKQbJ3UtB>i)uX5fx?_C+61_=35qwZOkF(mpj`smc;LAblC6$`6o9{EoS# zh+ogjKR6+I%KpS%^tv9B<+k?U=(N)$y>FWZ{K^=UJWPwa5ls`SP~4`S=abdppjUPk z_}AO=1cf6WRhM{CD~)93C{ybhi1yeN|C;kQJ0YGIfuvc-6yXJI;XPBRy>I&r z{IWrTfka(zD}Y|<-LAa@UKx(yV$C%Fvej!b8l}dWqlYYy)H16ljp1s<=`?zQ<+K1()@-*&ajndV>p1|Z2XI@}6I zkr=Y+{>tYyH(*qr)4skW7yvi}UM8LsFJqofx z#PBNjide)%@t>dfp*chBRl3_jIE3XbyGaBF@$lEhaK?K>oBAz@fVn;wnSZ}_k*>SK zX>Xl2ngl>Q7*_$mGJuH{V}VWP@?4Vfoat)T!N>$Me}R8JDtf8WF^(YDsS?6?9Q6;@ znDnPuW*WaZSN9|iimh z!fIU0>5oWyo}|V})#3Q0$iF~ORyf{{znJ1*&~3nOawuHDuQ%DN*5a&Z6TatFYRZW%c$Wx8jN!P4_hDS_54SF)1ou&Se-Xbf%B~s>kAQTkyoEf9Dc4YHTkUvQ_~0C5@+WyvCbodzz4(tBF8Mebe-IcuMs{Y8F; zf->+Ovw&YC0(oB563{%27H82q?V?af?d`vo_dD0`8D z5f8_!QjbHT{0QB$UWhCL?Gm?)`=aGz<|Rd(Bi?tlvC^2jXQ*Ucjp96JS<&rK)U#ci zZ=vp$AU*~BLhQI|go-bxD_A4Sf8nm8{aA;{8wLLLUEgL|ZyTG~-Od&pm*EwkdWO3E`Zay& zPKdV zpT}@Ig}vIapu0Wi|C=@b2e;xQ^=G795b7xM3WZeBd9{Du zP4;`|Xl(6>_Dj0zgd>a2b|KF{6Mh&qQh|SsvzM*r)t)D{1>y~aC+74idWG(R`lXdl z|FSfa6VZ{9)tCE|M3Km+dJBMFo*263xU)6I4 zE1`=<*PLNX_~XnM^(WbU>haZou0B~>I*ngHqZ6)rQLz(x<{RV_4awR;c1(oCr!3Py zr60NmjZ40xq8$360BniAxoR#XbkUTnz`txdXF%R}Q00Q3&MF6x@kwOpHfg%^@#Qb^ z>syH@h%8OLOevzG}@YuqXd)%4CC*=pUcs{z!%Bs`d`_8xB z(2D$v9zl?GXocwOn8ClSSK^E9KX04eq@Rkf;Lv-sbc*fc;Am6$ya+r zHXy7d6lcummUKy)^%}l-*#P5G>Kh}56**vmGto<|2hP;`j~|Bc17F}7|tc|FW@pNkRpD) zFF#C&IM50JjNF3hwgJ#sy)>;KrqTaWlDiReBQc{^K;X}%oQNT&@k>HKd_gwYK&z$H zEf?9wI^Y+C#0%yO{Cb7+ z4|a&3cETxddr?2k@JV`}P^$yKgwhYq^H{54h61?2zf^Sr4I~Mk(u+Lr*`ewDM0MD4 zC;tS$L}S$4ffVriq*JHZD2yG`@ipREkM`nnf||iq0;vMO0FcQreKuhh@at(M8^*k6YX3lQ zsIZD^zhWObz^`)!{F?K&I3Yp`zv=*6Ey5GU#YYSSe7&}SU%#V-98mZbVp|ECj09mx zL9ax@eIg%Uk&;mdsWM^!zwA!64wIES9^NMs)p+JyeONuG8~F!y%Y&tJq@tz%eqS9O zUg;A(PZs!B$v9K}FRXkrH)0f2zvZ%S5LA8X$w1qA6@pva*z9Y_ zE%zN?o1Mllsc*tG)kuGaoul6562}-~Zy|1d$IPr2o916iv+`m6unaggfUKXXcUbR0 zQRMl#fPRR~KOiub8S0`1j-RtpR|;s=n_{gl^*GQEH&WUaqHS_E3Osxd@`mEV&1w|W z_;p7v`=N%MeMOb=4j^eNA7+dAb&XER7I-1x85n)6#pr7XsrkKZ$zbBL`T7w4jYO|( zRBnxngo|MB5OkzNa6T9#?0o(`CrZ-1%cUe-b_&lN(6RiK4iLy-E-p;r*PLyXfMkl* z3weYZ4ReTHCOph%cg83Q#*+PhcF(XI?$%iqeYDC}`DrgL=<_?IyfZSAI|KoteyiOmhwit06rKH31R$fnpw=cn6hRd`XY=ue{+B{40)CCDi*5k) z4F`OA6hJnXe?LPdA27fcd2L`pnwq88p8bIZ<<0RdEAp>|LMsRHb%WtTnz71%*Aa1! z|B-3@a?n2nTB-imo48nb!Cc2~%FT&Ikow#m7$^Qjs#JZ5_#)=OMit1KHS87YOb0Gw zP9MzA`^20fI;qg}+1Y91B;6;y6TXSo(_)3~8PvX!pRWk1u4{|6)|ss?!WLlbJbESQ zFUK`V%<8ucE2rc{kuwMBgk1jRwqz~3OESE=?fF&5^S`C|7u*_A@UL;|5se*yn~Sci zSci$7EaS4&_vHIui{MybSLks+a`=;MoFAHngrADPl%G?NK8K#8hLw0fze2(fi0W!K zO1mf!8&X=F`WhPX#E^}{s8UcKoWeRpqE@COBx+gcf6XnVci0=KWz0K<8tEgpLZNVx zf1$k0LBQ8=(JVaBd#y{R){7Y8h_2!>voH|8wR97$a zstA1^&)lAm3qK9AtFEy4Y!WHux@-CISD#lGPHq$@^Yi7mY{F|H?=daI(otN<+Khz3 z!15OLL)77b;}OLBq`FAq;$3~1YImSUI+=UT;9naRZ23)&QnpJX&`MR_uz+y|{Sf{Q znOn~>Kmab7DJsv=3ouTY9r1L2PW?tW{*qjgLDh7PfM0dq`?WXek8*Lw8*!b?$Cokh z$2M|;gV;fO=U9h3w08%uw}Fw#Y5Wo;H~CH3l0iO1Bg|>x5T=@u@LR@#XjA$R{2St6 zb;E1sYK&`(Xpn}eoGX6A5pn-XdpIAbL_6t#z$bt;jwEujWfM(gVp)PZ)>EHv#vWJ&j)*6{4jPgA>$W2T(|{i{hWiciu!VsYIyf zG4z}qs<0rJKr$H4sC5`ZA}-?U4*V(mCS7xdoR1~7A=G|YKgr6AuIrTZHIbH!W#!+< z=lL9LtssQVIrWL~MvM6M8XN*mvh9BDLAn@gaw;;l@E?kn)j;Zkes}?q;&c4lfjON) zUn()M`^!l9jS&PrjOCb%?Z2?c{7d3njO{D^8A=xWUzL$9V?VrNq*-(2W6}@) z<^I04f5*ZOwvHM3_=*@rFGiPs8h(;jY;cZWd-iGxx<<{%16DyloR@-rc;9HBqaA_4 z@*jR>UUGdC7cIxVzbNvr3&4w9e=tMW^w60Kr5oRZQwAd~=!g9l{8~-|ZDsuc?Q&52 z?a&eLc6qk4pdW6hxKopfY$|O%1g^v%^pfq%WOf8?y_SahcL3jO!v%cF~Kpttprb5F+%{#A03Udc4Y zzA&b}4&b;?c*e9PAY$k{yjj!_Q9eoEV#tOWV~l}z$=U6QucKsC%VgvP9e;0*!rJx^<(utL!n18$WG~F+o zqn}NhItqr6*w$av5BH!FUMjphyWW=9^{^=0C}=Z5@$%D*}WMomv?8Pu^@yA@<@&Th$v zj1&w-QMC?jSH6X0es)2%F=#Aoy~6@Q*lv7WLRgr=zh01gGiKU-JB`a=rY&NAQGciN zUf#CuGxbb;4g80oUF;~Ti`sE^CK9H0N83g>;STwiWY_W1SnekH4_}qAe@u3r6{qCl zSjE)`!gNdiG3~jk75LXqdcxW@3O~u1Ge|W_<1gSXJYv4Y6LvIYH64~Q<;g$!ty zU-lDv(1}VPmC5=GWyvD{(oqd^?oTlv>fUy8TTC(tq!RZ`>xX3U*`1Vp)buF)(}AEH+GN(6quN;v!><5Cg7?&r`v9e*t=CzT+z`zogjza#Lrr#x~kp@8+9j z&A8FdDqFY6T?6PY74XYLFIvEzN;4oGY994)P3;Q^N+8;F|7+fU`pEi;gX#jtQ46#S zLLv~YWe^iLmXEKYl6U#b?V)3VWN)tjlaw8Jfb{Z2y??wN@=8{ z$iM!X9&>6lkPYu9Wu8PmuZY-u8~m$?Uo!4+>90nw7PdnNQ>jeOb?QYG`d>dvo=omT z+iSOw|Ml0h2Q`xWJFHIhNS^|!I#NW#vlFpnsr6i4lJo9n{CQgx^usZ> zq*S@(p(qycOZC5e(R#~W!a9jZBT%=OG0v+Xfd7;YCTUh8%>=O#E8tDAm|K!J3UXX=$$i#h##AX-u%0`XPgI+X&eZ z3B*C(AkpP;js^KA__e6j9Yt38N1C5bL;wL>M2%$x;|2V>Q~WW$0{%nuPI^hgE_jD_ zJN;aycp#z`@axC&y1=;96o9b2>FvJjybp{Fb<{Nfq7t;!(@mL*GvHtFZ)7UcWzEJb zavw)yrGQ`kiv2mpLu^bz(kSY~YKe#=<8$t*o)l3Me^u+al{N7oVh|UrfoL^)S*(a( z$CW>-19j9m?Gw4N3qqXovS*6^!>8meIh?IHtc_dO1^9*3VyNpvR(Yz}|GG#YR)=4~ zxZW}_Uk*f`AL`e|a!-X_#ILNp1$%?%*s2@!Z^j}ADdmguBsFqO9IXzjIqlT{jt&E; zV0n6nLuYfaEu~TRf{6Kd#Q8M;Qq~S&L6Uty|5S~823R}w9B(x62`8bxN9l+AXh5Zl zQF@Y;5pjVB;|fqU-8qe4s1I*ZNXelS)&Hi%w3N0Hc?|l7ZITvM-(%0q;vT3O8Nk+m zsCzolCj$SH$ovKW#;;-9z;=MF8I;)gV0$OEFnuHe&@=Xbz0GDf+vPl11ZfKlw;pnP8v)AT5oRwG?YHaq@>Gw@517{`nXE z9VY`^OIQOG?1XHXv3^0z1%T`|tZ4iZ^Nv*BVmTG`3?{CHAh_lHq6)|g_;re2c7>g` zl&18$unY{Lp?2a_v*@$6_wstL+W++%2WnvlI|CqV5XM+*HFcNNNHfM>%j+A;KflEe zoCkhg18gnoFe21N|4W}-9ad!_@JrQEX)Q%Jc$LZc{aPLL+ehWHvYO2y^%a2VuU-rmRaCmX9?Sg zVnC~#bQ*w&e||d*A^2pXh+p5MZB#1~QTFex-4Vps=PIlCW*3Z7v1v|3v|nIpN${`N zVfI)=*ozkw+blmJ;tKrB(ZQf=jJc(wQi-UBL>Sw9xAr+*7COHS(HDh%f>fuds6`xFLvoo+vcq*vfyS$d_ji9DCOuFw^usne4| z&406OvGj};@oPOBkh??fk=D135wTku<4AEw^;+p3EAX!pzf8nHyVM#xWMPfTf$?0` z6ag0GbDg1cQq094WKK@vMoltmq30spFy!asi-2Dkm*YvHmbk9x<4Y|h3Rp${mDQ2n zg*U5>p+0P(MUIAjqwEC&_!jUht89m;EVL!Yt(qp@c3BImPh#aUT;$?HTJPF@oN;5s zJwS)6ecbqv1zd`i7=u*6uTiI~niEo-EZfU{qB{6pNw`Op)qT2vU)w~lYk;FH98iL! z4w)`c*HadEu&}4`Yt{w&IR!7Ht$cv4iIm)yGIzHoMCj4-%%9*F3(G}sU@mUewX`;* zKv=F*OLnGz-lpFLLvow)16&isjyGl2(1d`W&90rnzxo{bQqI+Eki$K&&1Y8y&=~;= zzg6U45vxnsLtqUa6cv04^xhclhJXY7+LVtkzVc2$Knix^VJ0$B z8p+S8^3Qj1-W>?;E*IBhK>_@Vto|)MPXXTbAXYT~h!K<%qHQ~B z>k=@Y zj)S1q!UcZ@>k!Sd0)CYkovR@&2HiS!ewwc|t6=tcQYnf>|3>+GdQT2>;Fpi(jED)7 z(S$Kfff@SYJNngQEzul)-Kz-8PVFs>0ulFmq5tK2i=lcKo+$f!dY?j~PZj^@!wS#$ zi}-axCZawvWTj1sA-rA!kSRt6=lL}M`qWFg(*O)B^eNXaipB1-*z5G1{*cvO>z^_~S4e1*6+^>b({$cw)9Q8c*Ny(;h)bmb0ALjaB zw5!`#1zXf}Rs)$?Y&Pt!t{HU;_Fn!ytNvFCY^z69R=Ez+-;&wElCf@}UiCU;b*{$F zt6rgD;sf^*D|bD)G7#(y-YF>|d@;9G^dBA(*C=S0TV@0F`K2$d&93@a_OcjGco6UT z-;(%?%Pg!{NbRCjq!_l1wgh-((mMmcZm?7KzEqo|EtMY`Xz*df6nT|{G+Xq~f0GiA z`Gz2`1?Z&nlRPXE_s&F*O z@^l~Jo~&_>R{RNmeMqm!#pH2-R@gpo0ovYF^#(P7e~AwDQ;wC9z1#;)l=&zk8;uA0 z85+&9mP1eA`MF4!z)5KEh@X&)CHW2TlyMp&ziVN2e4vx(zGu$AGKFY{jC1OTVqhlY z@1f&dFW?MG<$L`!=RN-7e)wd@wdHhL+?NEmI!+VLee28nHJQIB;~LR#(hHzeu=T!| zucIKix$fEE9WyskO#K%88+5${Htazy;5sSb>wZr2^OtF{0mM)0T-}p)dE{X}koNeQ zhv4rWFh*MID87z$lpiVL*BaU@ebf$@7b#w85c>>ENqm@n7;(!ZXaam#SM7|I&ZY zTSNt9UV(aJwKwfb(Fe3bP43ujF?EmHzkG~R5~B#vzo7w&W$dR9Wk}Yk+``p8=~*Mx zt)un}BEGsP=m2V~=m6C$^GAU@xqBpipFJ)Yo`=HuS%B|+kVjU@58#>c$y9trs!s6E z$dF^)%hozwNj`2YWZrHF9hc$Tnfe~(pFbUYekcIa$&S+j8OW5~K{xyNZTHONU(lMW zsE;&hP0$kZidERZT(X?75v;(!##`T@VU^VvNEBwd3pydg?HgzEFTFG4Q*L?Sm-LB9 z|Lm`bH!2s!>UUyA<=(Txubw(z>q4AC!5-(e;GXJc%6SwE_%+{h!9Tw+3Vh#8yP`&v zZB#->tbPXnYKN=K$IB8X@T(IAa2oLi=ggn*ubb|VWVoXOT!yX+r5|cnboe)-YtMFF zD9y!Af5|!a?>hRqXLtWWzG64ELpEH(lo1jB$7%jW8A~!>mA{+Sumr^+8zQXGUnbOb z)BeLxsVW!C&$@F|bSkLL3yF=QI>jnox!IdX z3zSNPRzgl6CH0rWzo9Qzur;pdjuU~Ap2JHcu>TADkg>#| zAKH`_Ar_Dt7piRb$W@#seW9wh$BO;0W~#u7@?Suw_<5=waA&l2bTm=>9V4TyQQxBQ z>oaw(7`Ob(*0>3_!}Tc9%W;v(pvUUYC@lk}KT<3>GS?aJ8>>)7XA2ji||_h(ro zf6owsC3V&Y1Dmuv5e~a!746_n%D+**NprK@+A!t}mcl>JfmSF2p+{BNxcDk9cPa|_ z1^)*9vAgMfU=sQvcw7wUcpN48H*gnAVWQ8zv}&50~h z8skDabq^?TEI!7zL>m}B0d%Rc$Ex1NNS`IdsXC_ulgrutnEpU8kzmz&P~9^$XOOb} z_Yt}b6V`PV7lR;TFN)>ko}FEv$mhc(z0a@G0`jJ6)wqBK1GE3NZgM4d)+f6%`FxnP zt|%R#2Hmb^*DWL&NIEwqPKuC})jC&m^;=T^O6fClfPhwh*Wu2_*UVikL(iY|js5vZ zk$*MnJ;zW(rq=l7VJuP9Bshpe`l{Uh%+BXSr62CXa4=s=NQ425e;Q|5&;Xf;FZE0K zE%@ib`U!c=k0KeVK+VN9ETqPiCiC-U&r@evfOe_2m%2b{GzLUlLFG=7f5Am5TVlYk zBXTV@rM;KCmMifpf%(ej=Sy1e;Rzcvi4hj2pKSMKANU$uE)LV8Bu1Lezi0RlDWwz` zV%t>DWwcjqsK>*1V|Fgj%EcG_^O2E6qhqMOZ>SF)aG3yzSfk8+PfU$Vz<)RyU!L)t z()Q5H)N~AsEkL(A!YX4I{D(Q8UK*v*4fUuhy@M}H2m&B1Mf^gx$#_4lo#MY-0KyW~ zHZq*NBm*h%IIeyxU4ks(poBQudPBb2S__#Kpb2H*yV$Y2l!UrxykreY4hfgoDf%|q zlUk7BL@BcE>Lu}I`T63mX3^dMx0g(K`2>jA+vcXyy9xW36&5VFa^C~}kULf&jor$p z#4nAYdY(2qPL`b6|LS+&sDd3i@F`>Q%UlJD8_#OM6Ymcr-pwJZJG8{*Knm`8=lFHcxfdoOff} zGVsfvao>k$KAL~#Og_HgKjd8*xQ4cWC;J^G=2p}zDJGgamLFy9WoZEJU^eF!9B>~ zFXiVH`zuLV(EUn_%YlO8U%T3&F;*4)htN09QkdF?@Kz_~QXIqqAe*qmyv;875AS%L zuv=MptAJmZ;N|O6K=uZKk@Xk&S4nQyhVY(&2l$gz8v`gnuNy)lQcjgzT&VM-uoupS z9T|Drg~i4JWV;CmNuAD*-6(kpj~Wngf{nWH%<3SHD$0qUR{S+r?t7}|JcS`Q3bZXS zc0I>EaZfcmHK`frZ{YO;iSp-kDZ3X6;QT=x+C)Ad`d!Lijx>mSj7xM>pr4{91^g=o z{K~CEgkWzHC<|L6&dr-2?^rAM*VrzM2MiNgM`c|SC+i*O}U$~gUwVSqLg{N^Ec2>S1zXNtYVYkb{^A|%XJrB55SSADiF%ypv$@`ZpnKb zK)@3EhwmPA0vWBEPP=k0f=vFm(Esx6s{{R)?Blf8S>hz1_s)fJbj-Xm9bXbT^DtlF z+}Rm#tT`kWsHIh>srnHADl;8l2Hdk;U>Spd(FP|G#05?l6j-zc{tRG|m09i(hs`q1qf2lNRLN-+Rr7%|+IaUa`C=2@G70|AG2vpqYq9X^ie%TA z&ec6>*IfqM4NsQO*SiE**f-D^jNZSpbS7}9FTvz0iP86UvNGI)%hC+O04CwTou3{E(~w3 z2+rt#!L0$d)uCMz9|;_sl3|n3dqKqDpD&H6XC5lKK`-mM?1$q!oDgdI8k{JFj+mT* zUq6sts;y(8{@F}`n<)D{9nc}dcK~;C-;?*x1KKvRJ8845wR`Z)bg;7_^ZiY}V*d-z zoP(_h!K^3^gNaCr8ksu~FW^@{VK=4RW}DUQWGW;dAL`2Ggk1^w{LW>4A{MkV44>+q5C?J7~b z8vkOZe`A5(!*_#rEm*>O5mw+|SLmm-NOh$P{A+>A{4un><|3>XIc1+O{S`eY8dS54 zxzuY$|7$%ZxNOaujr~c67}wIy`}moLcx{}o)W7Vo5rtx z%-0EfvFfKRMFH#;IDg}7^f>*$qHS!|OVjvuz7nbt!GCCr1dbL3?c!=>s!s~|^%jA4 zeJ)bPbk^yD=ie$-IRQGhReF31zu@1y-Ukb1T$Iq=F_&2Pyv5d-P7k5o^SRlG< zA0im!T;9jDlll1amsD5c*o~x-sa)pz;CO?b$gpO5f@aH#3>J-0?-~2QSZ8N@dk<$G zv3D%+8l>q80rly!IT!cj^O%d=ok%R8Fje$4Yh-uCD(12+biUR7H8zp|9<~4LXNh}x z`6l=e56Tt!K0cg;nYEj0-(%{ha{j}wZwR~Aa=_MA0CYtPMe=plBKrP>fAuA2$8ci6 zQt_&+jhPcJI6Bn%hgY?Neu(n{I%VU1e ze6y%IW_I|_@q@U zaSRdxtaou3>A}&&VXKiF`&)T_E|h;BEOMovkbk!7+@)}tz-|bh(y928s1Jcw5@F@X zJVRGUeCgP{MySJS3cuh#yn={BRv)X(T{y0+KDEQBfM35RsJm@wsYB-NZt_6p#RfNO z;@;Nc`BADJ?6a^>Y5@Vrwn4zTMSYHsn=i$S{Vzll9|PukD4}x&TQDNd!lZN-@#`r# zRR*GFA|7Cg>LJ4STx2HprvSUB`(Jb3rWZ$>u6X^XU%<{(8Q8h%q7J9!5^ti2Uq|r! zpk1KA*#C9UC5!rT)UCgaZiDNg{`M$!=uIt_A%qR&VcP+ z$4=AJPE7`!#K_NS#DLonyK!M##YQk4xQvZp(ce;Vn|H?kv4gW?A=iA@{+ho|k^L`jGYkp$R_r&Q)%Xb40L!Lb;!aKZgYdIZ2dMAqh!}BV>2)n(|>le6?T?z}1R-tGw z@UM61L^8FyJgGH8KMXs_t4iPkD9rHBe+Ajt*OBONy-n{;BR?yWg+x7xCf7{;kbKdy zoW{sE3e;Lyy)})iaZdri)E-RO4wFo`P!=kVHcBW?1R7ye@umFp$Q!&|q7S2FLj>9d zQu~*&4vYSI`bfw5QBei8%IA>P-eOl<@yx~j%fPQ=)bjPuTC0|*dlUpHB`0?=tsmyj z?`<6MOUA7cy-^jw8G?Q&aWUQhDjCJt15vky`Vg{)z+B*&3Ce)dJUdiwfq#SJZNM9k z+;WI2RPS%x0EkB(m^H({K_}oOthifSV5#T%Sid&T)O+rm(f=A$+hBz^^#EF9EO%_w zXztQeYclcfs3kSg)Uu(_|cz`vHku3W3Or8M*BKZoJiY=S-UnorK` ze?{20cPx0cY*{HujLQN4${CnnL(^os|K(cFe$rVJH#&wb)k{iaJ)fhlM2`6Q^YNwd z>o@WqyL_ElNxx65nDA~w9|R}*f6Uo zG}&zzS6!ylvgNX8QoAYsAe%C{pnSc7{ujau<=ofU85)F_4@UZP&OvJ-&fl2U57GbP zeHQLn$;N22)c_+so*9lr!Ud?8nlJRfWY-4Ye%R(6vQ;8lmWwaHCJAk}pd&kUbTcEO4KK z;~u4G)Fnm*KA?gn0%_tHtpsoec|; zyx9i|`1Lyb$n`Pc*KEj!xaYR4OP%P8{#UlBA6}8C_}-ZJ7qe5zmt>3D$c&T37CuKt zyH?;|=WW^Uv&}8MUh%IO>}Lz8H&*X~qrQM&aPYgMb+*>AUaI%uduHGlqF`8^g%U^mLwFaM^Sje$4s^h1H?@B-<4Vzu zL{1LJ1*eYZe$7gGl#s3>6#3UdIz-z%5*fZ4m>q|{zke)vwBYW zvPJ-pdPw-P*tqAx0GBK==Eg($xyY2X;Zf_JF%&MR$oAcZ`jB=zevWY!@T-Y!8JK_3 zIL$sr2ghn+cb%)e-PkfvV#6mq1HX>Zes>#=<);rV_&3P()cuyQ+kOUq_0uhWpMlB& zvSAf~>=EsXfLPuAUyl{>>mt%=DCQAbg28?-Dn{T(Iz#(JV5o>+IsH%=u=P?m^cIAS z>VPj)pA_)xUtC)pwM{?5jOhb8h{MjmMh|#EhjBF zre^4eK&xX)&RPXtfaCa9LtaDk#V^|Wi~8XP3vPL}e|bSGh(^@E(+3ljTq??wNcfh@ z3DqTyz8=H(X;?ezkj#DJ&hN1C)rWZfYGW@e=!eQbkF~lZCu{JS+xj$=9I+=_R?s)p z`SVUE+z6`Yn?RsdpgzPNjb zpcPZ69coMHXE+$&qb_i+3HX;*z%NIKO+@L3+}P^E@2Lw(_2ib71^gOESlI$-rDOk> zZzZNcrziEHl{wBhjbHAb)dPU7lXX=XyP}f;_C38mg2Jre-*`)&h=v|Pt4?PpMC$Va z95|`J5q*BW=g#8(ucxg`33N~H(16PvF}P#ZxO`VG7vAp``PaZ2Y;U2!W2=B)B2?w= zd@<9FQ&y@0^hN$f@M6fsxO{lWTh+p{eude=qN|(FZB; zFI!i>%C%WcB@({84LTAMW7t_#;9v018-Ko|$=uBEal`!BTLct%D#TBrCI zue!i-eqGe8^D#o?Z7L%s(A)Np4b3?J@W=9GGDX;$u|dAv9m+P?+D1Hl^JdTUMgE1b zg7p`;?5Ozat~j9mgf7tn4s0sm*MvB2H`RN_wuI%Y1bfw(7B;RY?v=o0C(pk+^@o(s zW+(bf8%aLm>o6scD}+e*^v_4WKKT5;GfU2tv*K^ z0}%skMIplDz$Pm1tMi=Du+5w|ZSx)nY@Jdk($6^m@RZzI#}mf(O6vYi z?Ad;E+k?9w%mvx@BL7PB0mDxQRT{yrYTj?U7?BiQH(W*hN{9iS%XX`k_&-s7+>~4G zU_$p{UqAuBT;ufK>Slr-RYMO@Q_?$b&T4(d+P6AzW>o>d_S2h&>I%)C1pj&gIn%YC zlx{O)|1#OiZc3hk*){Q(c_{h#p!Sf&K9>mM%hI`eh3OI>xv6olvETf^W#5JYY1FgY zIFduukiG(bwYtE++6=w5oc%~}r>vT-W!q&YwQ$Dyy_K#l@rI1?m#zO7J-r=12W+Ym z-`!gC6i%cs;FpWP$d^Z5tf*~dP2 z+YRx7)v~!_#`%XCXgfjC=GW?smt(`qNS~`@9L#%xe8g_D*rvZjlpBU?rHp* z^{lu?OJun{yS@7?g=FAa5S9yKX%bel!uf~iX%l_#`uq*}{ZL*;Jv+Ws zm&0YxSs1`x>27-1^ZnX_eu%agTjs~%+>G`NEG3*D1tUi*d|yATEa-=-RfiJ;USm7# z%?A7%xt<+R7@5DIAO27r((8qPtbVTbV_JaMg8zM)XISq2yfo$CaN($YTCV&XgP>i* z0tIlLa(*gDeX;+g=UjP7P_rCogw~C{9!JF5~TQwljI9Nt*UfTnK)IE(~YvJnN=)m9mS?ZNO$Eb#X1Dg#ev1kkY zYi`*=qd_J*w(sCi8a1QP!ab>uF*$M%X!bls+%t0SH^n=8_Lv$=SJ5w z|GFayS7*a9{n5%Bbx-k6I;MJ_r>RDGFICp(-?Q=`;+}X}%y&*~W}u2u_64!!PtQNp zf5t&iB%)~o>8eg~&o+X#a}4MA8hTJY^H512p+o01q_lT|=ldM=B2~Nxoj`WR{x5-5 z2P<+dd_=ez<9gh{2De|JxShr?%F^j4as1So+0DK;sma-vG{f}rG3=Ad7Wfy%tc3iy zG@RLwcz(QQse`ZrPm#Ve{u%shp=+xVSPeTHmpD5|-P0gYEUDyB;9uO;iQ!aRY&Fgf zL;|sxNADu6)!?*#NQkeKv|OrXV~k;3Scd_OE0lYlDg3%ax#j;%PMzDMcnV-FccSkM z{`DH+e;oi@a#rPzNy${K(;lUBas~IKUD-TecB~83>j(epZ-su?4XIO!^u67U=ix(} z@^7R|aF5M(RU1>MtI^qNSH`Sl96~*@%XxjnQTjap|Ju9O*tm}CeC}hVOYPFUD{_@B zBD=$f6hfiQrQ{c4*&41$dXvh{rh3-Uk4wR5^+RnbyFlF^afeHaURerE+d?WA0!qnh z!3Ksa%TA)WZgNSH1f3`j?FxmE80c1DTELt>#(E z%QaRq?ltlKFE9Rx`E%oC(cD`6#C(i~P*Ssd=)q7=W&Ghe)KizVrUyTw)8mPi&nM{Z z%w5wDGwZofzxeGhnb4-Lx)-OO~0^_eMtI6v9MWUc;GUU zY0JZ;6~%8%!@nVK_TzonmZ3yG%&r+2V#q$kSAH0dv&?^ZT%7RG_f_F+E4HjzZ2@$T0H*#A{*TyJoSAXl{TcWo#&G%m z3(dgm;fdqTvw{EcVR>M{J!Agxu;Q;E{~_3_{W-Mos()u^oxEp+BT@EC$8VgVl85MP zAN($-G6L{fRoGwmv!_{;aQ+7SGl&cqE9QIbb-R7|@JZ~&T&}U!7-uJa#&A~m>9pIH z1{ik$=CGM-`)ifVCo_`^U2yH=IEG1I-1?b#Usl^+tLS}knzik-er|t^?Q823&F{D$ zAC!Ug+Wx8?47fl}69^h+muL?7OFG;l{*v*Be<5%^wA(`d!(nVP)AiT#Zw+r|2;`Vi z_80O;xhMGV^cGfoh@ZC+$Z>%m%&#YCTx5Tx!Cyb1#-aEX*l6<8VDY}fCoMx9G6$eU zO!nPF{QN6;g({9$iRcy4#-LVHPQTqo@%xZDC*ZHMsZ$*8qu#o~_*%M}L-5H#%oh~o z!@4)h_SY}zLm4f9#`=}G#vXhV-I*&~%VWN@{Us28_@DF-ysl(P7aUaYiZua0z~=AN zU3syj^y?4hIvmDo`B(NjLtvZ0#34{&C47S=*OhG+v39~6yFO%Q0i?{z%O-r(gq@@m z&Z&%#!h1IqXXZ44pb1lX2^JaFsQ3Ni3)dKQ zFak5${xYtN%;yk)__nnPX?r(L;G!7`ib2r02#fejxNou_5pMC$tY~*G3Yb)9tv{9r z@*ji9qP`cQU$3$|`6zNe&;ZhxIm1ms&U_!Ii%XinIJ#Uyrs6jCSG=jKc-Gv<4@>SI z8ISmjgTIiA^0BrH^_v}BwzRf61C8`EW227`?ahSoQ6=N`UYt7R~IjpfOR*8K? z@Z?nFk2+<_{3MB^@fb(?4)9mA5%T+M12Z<0b1`kS&@+t9)S^8!@8i7jeaoX~X5byv z`43Am`9{3AGyQG24F$(0v&l3#&JsTC$|!zA=0AK&G<&~=Z)usYi8Zs%C+6=V5q+af z#4)Y-tA@@QY@#h=Ip#QJ2;cv*&2#C@1Wv;5DE^Z6*8>ynAH+Z9*WDlab$!x*h(sLi z9}LVa^JJSxW4{zXIlX~{2it6X)|2+j1rYRfNby%Ld8Bo~ZRCf&CVW3dzW&o^9l?1O z_Sas-T?F;W_m}^2q_OnHYdGaTBd~$U_>HFoE5Udy$8X^MzV1p zX44pe=C4tl3N{vDCVxe|<-aEA21b z!tC8TY%R0jmJZTk=$Cxc7C`YAJxYhXmOm}dShFh*@g~oCp#YMillbBubSKcSbj&t! z2b697uGup5Lb|D|6*&Nl(vgUFyUPAUqrY=4cN$j6E2JP6eS+cZ3A=Gn)cmzKxa~^F zu)~Yu48uY3Qo+xiX#&vv1zX1d0{n+@_z!V6Q8$CTEgXQozt{Ygj!D|u$PqTbmi@H2 z@rlHYg+#u^4STVRR@z^ZzvTB*5TAaZBamYO5go}ge}(afh)H$}HeT{-mA*k+Hoo() z+obHT)G6$l=;^cHSyOz0)^TUJ@F;^nfya-R`Ag<(JhT1CaQ$+7%zvG?HK0Ax5JM(9 zZGZi35vO+#NB#Hd>an{(TLb6uS5NZ4u87|lq3M@tWf;;&-x{jUc`YNxHN{m z?}hq>{D&rNPpre{QWMtUBe;6T3sWRBAt?T$*gSj7?-)V$vkhkOAxos8CS;^9VL$Z4 z^TufM4I1K&qIR$8ib1xKJAYsvhvqgz(G-74`)i1r$>Aqm8!xYwoD!7ryHW=^n3~DH zQ^RE{5KGrElXxMI@29YnM=*jTxScSkLry8C-oQSVVYnS=rsr(oDEsS# zy`PGH6La2QHwy4&z5-`;@pl~ivtxP6e~52(u%@P(QR!DNVzG^4^Tb;9ap+>voZ83_ zAlEZP+9*N$__`5Xnw&(xuxPVJ&~^F#mrUD&ZyYf5$7Zvi7=isYE%$j*j^7BPuc@wt z*S?;V_e8$+sUba70CUUwf{G?Ptv>#)d#_zP7J(Xo&Y;Ba2%k0C6+2+;;k(?_1OSf! z$&wv@M?Me|rolvxt#oV+3aUgjhV=+CJopM%QA_~r4nRx+7CkE$d(7A)cCpm7tw2!n z5KF0NO>&a;L?4!31XP=Ic9Y?VEOX(Y41qu>Oi&_}%-3Ss{`|=H*3=3GKu-O6+zO;f z^($d)qaA)K6WbbsK7d`sQDXC`&4P$y`?Lvj17H9+XrUwjyEBrR^xzD}Y89AO01S-; zv7n?gde$V5dB*S4PFf>Ez*8djsF6cSO1GI?9`3vDp<1Cp5yBVcAy3O>?M#1yZE;-e z{2HM9osO%J)jeAst(0ECy8W7tSKgm1~s-Wga5CVA!IQxj9?OO!ipc5Es0=)3ueLKPXYp zn(T=k=-=agAsw3vz^-&^YPl?VD2=rmj$wC?bwIr9-J7nRG7t2>>n%?kQ^tY*==G>!D>vuh{LaN_P)M zAT|{1?a$%(l@cMpQ#X(G8GC3KrTkbQ?V)Yd01&L{lzLWomOPPW%N(N+fMDf%m@kx& zYO`sxeurfp5UO0um^g%*VFpnmluR}TZDQMI5CR)Wm`tx-=0Y& zVp}SJ*v?W;jH`Y*lqI)cs;>mpg+}1Dl(Yym&J8->oi#}aoWmSbf)Um#L4Q$}sAr+? zp0OM2MeaYQ1SzpREJ>+0PjYL4eg&IVpMl6qXk73l`H!73610U}zYIM4h#^a~j8rRL zsb4eHf;}N9iG*TC2j7~nZ?Gpdh;>jGuXk--PjhVF*dv*pM^Z1AK`ty2_Y0=Y|EJ|Sa7~d#%dCBx3O0*1h=abtTb{Huxfh|F2-VK4S z2iK1I0`iSG0Z6ffIe_h01qYP~tuRc%N8DCB1juxwOSDYF+C~@ryEC<01F$CJY^~pB z9F-+p2{{oLteMuNuw0UYOYz||3LsYRst<^|C7J_FVBB}_SaV> zc<$cWZ(Y6riQH8EE3=pXT+0|{A3yGX$*vh&1R835C1h9fa!Am2#MD~mM*Bvzfe2L( zQ5ByWOfqcR&@v9_cr`{oDS3Gz@NZI2x#md7QFN?%IRc)mpS8~ZTK~$CuF+&QP__7p zaO=t#TdP2L)RN3bmAp)fpvlJ0k_l>Ze62R5^rsB8jO`g|>Y=2l2BC~=aMPn>(7GB? z1qxxKdG`%@IV5O5+z&ZKH62%jpdyY2W<-Kn4#5&$1pGjR1EG8}w*16~f9nn#>s z^w118pdS2rSYZI7nw*7e`Me-p(yG<1WmXKDCuo!- zId2uvGJ)Z>XoHXTe%+qM!%{I&sveh?XN>bCMTt0&-?PJ)j+qU`hV$?|F<%WRJc;9b({5~|SU@}DWRq{}zj3jS~PUCqsB|3+B9A(u&pvS0mdsipt3 zGy+Q_urvZoBd|0AOCzu}0-xUz2+m75FyXw!Kfj}})bphgSQ>$)5m*|5r4d*ffzRs* oz@3kaoUgunJ)TkpJQ{ZBU=aCzdh?49J)Sh0xZ`Fu4cEO`Hzx2tyMmq2$;&i2(-`CaaewnN(0GbrRB= zgd~O-c;A+6$(glg)_Trb?T);CwD;Nj|G)qH{(tXKk$W=x50PUtmEGU|&CP$)c7IL# zw$1l_V{7f--nW&ukhA{p8Ula+-4%fV-A8(TU`1n{*;uzCKwGJ3#fqktjZF)Q}(l zCqJsl{NlgvlaPHJN~Y(3_CF%?3-+J=I`et9Pw9WvNB#fNhyNE3QZv81VNirBsE`~2 zjfGTbIr`}a)rxs&G>>HFWfx4-%hX`IFDe`9tY}bODW&QDR|5DXq6Da2K1dihXm8Y; z?tYe;^agni?Z>5eP?zC-Qx|0sH6Z)M3ocQNOj{4I2pYatZDrIa;uIOy8(FU-^BjA@ z9_l8qttXk69wC#oLFU6Jy|&)NCe?_14lTH(ouGQ#Jy_PlPV*+)pHO^sGJ#K0No-5PE=0Nb*4D1eH^|+KJB7n3pS|RA<*KH2gt(_V4JHw2kah~s>8e3~G+n9aNHa!;o z$-bv1eA}H*)05(0+PR&*E_Mn3C2bRfG0E==m5(_dA>W7Ee0GQ*;pT|5k&S9{?!G|F z#_YOJEa<1#>CS*FjkodMpAT3iKUb#M843zlL}|)?SBTOyK~?2$(Gj6d6s+(F#il8( zmfUgW984HLnz5BmQa!EjQO22^&V~dUSTDXlv6f}OOHeE8Aa9G7Q2MBgYQuVhy`5=j z3G7TmKBuCf%F%@#<$RcZAkb%x?8CbZKmLjpX4gVftMFGQISuwAb+q{J)=Q%!qQmFE zTRXs*Lq3KEi?`6Is5filN}5J#NxyqH#yn~Teg3#!t7O)_XYt3{b^d};{Mx+7=xRss z+wRw6pQNw%qw#g+4~6aWITZyX>?9>4Se;3Fh3ff+l(Le^hI>jc%&u3Xk*2unCCzTx zLUHnvE-;?OZ2CG8D$MyY%ENfpC3y#u*RJkdX8Xm!~ zygbtfc8X2Q3bSirmG^0Q&)okb`FhO(?oQ|`-u!diyNWRH-I=v7Uu(6%EaIBQKBCwL)aCc3vUXLc=o1?yRiEbJ(DmS-GDBRfkm0Z+2hdH1Y+RbWIO(m0!@UE~pZ zJ9|xjV(Y}(W}c%hp%Y?-<=UkDPP{yE_@aCJ+8gYwIGox+5$scK9$b9<9#4XQG7bI5|i=U$}^Nshe&6&snMvD=74c6D~uJXKVQg z9VT;9^Q-Hn^GxX`;Y2j`fOW?TfUC93kP&UjhJOIs!wT%zi>jSU$&Ee1$$` z8LvJ~H(4{e?aE1-CN#J*QP?i~*acIaW1fH2T()9}Gv+h$S51ktN$iBQj-WyI5ypF= z?tR{I*D+Sp3Ug@Jf9z~D_o}z``qIpkeb4cNQ4+LFXr1ubg3M0c6D=}g^UY4|Uauqb zer)(UOqmxYnMyisd04liK8l&u0(}D6b>|DF=uGJL()Hu972dNjv~`B!W2Z%Z-})iN zn8mL_cAc8-+LS(ROdo9K?o{jz31k+GXew)8+=!dQT79hcpwdr6^mM}ASLQQL(|~Zr z@f=gmYqX$R>++hBc!jsh*e$$ID~Im((Ho9RQA~OK3bnvp+`D^;vy&w$!j%fAhDGrT zjhum5`)Z<{!s^p}tjTz0baO=iOSVvZMBHZ;t%v1s`CTDR6GIfRou$eidQMFW-4pZC z32KkKNLh$p_~DCt=o160lg{|MJB4yVxhnBXxJUE&H9`LdujL9TRrFh`-{k&rY&pFV zT6xITtLN}5F0H!*_O7v=^i-=JW{tGh^e`gbbGJ= zJ>|~qcLBfDX?lU`Y|QHtU(MW|G2oZnt7;y<#+^f~k=OR_aMkeh31t?) z)UDLD#>+!Lg6r-IdDm#thj&Rw{Ug{;#=d}G^q_Vd*HXhPjbC(n!@m6t4^(^M=jYP3 zbE9#A$GLaDHUcLd@0a+s(ZdC=CQSu?W#*+7Tmd#o{9;>q2M25!g?$ppxKEBbW6Ko_ z_B(-JL%x)JEgg6*J*+C)Mb#lLu{(k-M%IFH8e;X_l_=ZFhNvk7Y|9o>9I9v1@iCk3aBvXEu zufPWs#%@W&C+y~{_UmsuD~#RhDtzM1`{br$ot0D68mdOWjKppRPYv^?Py55u9gMqjA)p2 zP3gxakfmKyN)Eqzv`)jL`qnCov_9jYQQXQFsQ}g&efP5*ejT8lTBW@_RJf>RFDz0CWtNXhv??rG&A!Ghd#h1|brmgK^<}7|yQkUs9E0WA_?4~Uvdc4#{ z2>xxS1smk@yJUQbxW(24^RwNw)dp<2*gwfW=B#~DaYSw#3JGPkih#;?3w<^H35{Bz z%;MJJ=K2!pLwj&%sCjAfimuzJ0LKv3_VWAm{ zZ}B3^_HylKtXhM^Ps2dWS^OH4um$YhLX?DAX;i36`x-(};mz6?_!k$1I8!)HGpTu7 zG%xc5(ZIiwdHlLWuZV_L|Eu~6J{@kjS2_@O{sP9M=JD&7blo@}L40_TrbIB}o+z6T zpRQ@P_jc(y{Q3o=$|QFg3f#_D>ca?t3;3vk7nR84mtT6nHtkX7H8H^-YR|A*>P}VK z`qAAv{J7*#>Z%v z9DF1Dzi5Z>Oq^~5E}L>Zq4GabEP~w&-(qB*)403XjD-*z*XQvoNvB%t6Rtkc+f#Hz z_{U?7bS7Od_FkOJzb0uls}nI9VgaCm%rwP=1{xc)_N5tVFSc=;t3oLhXmB;5e2FgG z^?Ywa8P4u8A@Pg65iqG`nuIN1!dXSnQm-Up=^TEsE~@0(t8AqThrbCV%a1 zv-ahn9b968vz&G~4svH{)MXv4pj6z?iwrhGzY2L;w2kZ*tk-wK zSkvLGeN`;zR6#j;MS_jfv#gRkQ*5Q!OLbg7&%Tn4C9L`5TTaqy{Bgvm*CSeubr_Re%+w6_KJh}tA!H3F1RL?r`4PL z7DvpJdHg!SBn^apRmh-%d?{xIKWfy(@yQ(g%Jtbv2T6-WH_=f?4OOTZjVb4DmV;@+ zJhgyR)4-P}0b74&9^u=DDguQ${QBP!gz*Aq4jIZ(KMX(iZJM%!=$EU3Ay$|vYEJD74Ol^p*9YomsK_mnc#@ruzv{*-csZpNFps zLcmf^IUb_NZ3G?@G|2r)|1p-H#jlLV7W!c}Q3z)~q;)Jyn}cR;!uhL~bapK?HS2Z| z?vBa{k`^e$nv$P8342w36;bgInVi?&WZ8rkrvRpdwUC%wl2q)heOZgA**{`O?M-28 zL71{(Rx^9do|ofa*Jw;M^trAm(*nG5YssWio{g+hN)Ep!s$!;BgeEusyA>B+t{qp!%}()pUQ&f%61<6AKg#3RF%{F{n9j61$zIs%o{UXL;pfTS zlgF<^CS*hIPUusP!HQ=ZUHX!W+Md=7rG?#tdE>NnY4eD@~vUOin}PH&iATiciC zUu}{z3amv5MTKc2MDL^o_ZEiC>KuM8?356&u8}Q)OW8aQcX2xbnXIIANP$g1g-Js`l} z=jex1Se*@>%0V`zH7$bQNJBqdO?5V$OvZLJW1LR**SD=tNcV1Gf&)q+zhHqEJo-8Q z)#=@={g^EkU7|L;4*Wv>t*DM@70k-vS5{|BNDe~xOWIXMPf=w^OXd030{Rj6gtc;3 zKpp0`@M(h;vLE#?|Eti(Xf$hIgT)aT-x2a@I`GR{B|y7OYr+B%JEi3G!*}R?5!~!P zpnOW#`QnKCG2qu_2Lh@@9>1qt+5_4Arfm$D$*EZg8YV4_0H>xhRg~04QCF&PVIWwGyc`@?^_+&MKx(>`@VA8 zr7b0G<*a_#uK{inN37yEoVVC7b=GaEohrM9y&Mgsp#=V%Nsmcd@gA_q;HHv3Df(N`2|?#OL|f0sb`AJOn0H&UelC3_0&* zi};iD<&m0p<-P2CChDPQDr&~!-(`zvC$DS;|8lXP7>JtMF&a~j$1ESCB>CsZiJ8Vh zf<9jgVd@C=@uJ(=Xm;KE7aXH$(Tw*D4^+e&xT{mILK3Im_RGLEBA+Ah-lgZ?kOTyr zJAw7;Q~sd6FXO`i3@u|{&=1)e4XKu}vJwvDPVP=u-m+W9&;Dz9{EQq<@_0S+tsDcq!P*FmyD5gtJFtb+{<*qOkcOaUQN#OFPB2!2ZziLUA54Ozk zuh9a;hh(180^VUt&@yt$K=Cjz7wTb(_1^layKTqB(P=IIn*F?ep zZ3=Gk=JZa?Y-eR3m zjCq@k=WWk-L)+P8*1nMc(&Tz+9&G*SC;kZ#u@a7e>YP^AaxQCMGXHgk5A^yc*i~_c z2L}+Z-l?5Q9kI~3mi;c7|C%!3B|0n9CTJH){E9~Z)dUcUy!wpuMUA#67 zAD-i11$3C3VV}WXK_6%ZFf=QZ|1xIdLz(}Y67?p$ahgtnXzU^IFPZ;BpqS%dpK3Sl z=5}{V`3+q^l*xZxL6)JJZKN!<6pn0QSJ@; zgc6~+W%@LkN{BlkB&OM!?0XIsjEN5Nam=EMb|~Oh8>4?g2s|Ql`Bxv8v{Xy%+e!{c zWlISBi$hUdqrb{t%C3bq{~h306ZaobR61!4@REf7P2(gV2)hqd&hW1`N1yhtxw-{j zeZ1y;euxAytK!{K_NF>WIf@h3E5#hK8^c?^C&X7&Ge-O6a5f6-2}Mj!&&PKUsEv=Qc@ zPE8WAJpT&Ph;^6g3dI)ExHxQO|QD`!_gzHz}EzpS#6e z{xueFumD>!?R9$^()}ulASN0){Sf@i__6>6J};!OskcWf_%o$7_PPg@Z)e{#(E;kD zD$-gD&!e%Ffl61EC z{hm&5S~ckoR90)?RuQ)|k6)MQYCFs-vGxMX$nw!U-|2)fWx0>$@#{A`Du|-!T0S_=TbRz)x$3^g%YOA3FTJ%ia=4pNl2}dwZS4 zuR*GfgOQopHPzHYLX=A|t29fXp(mX#d?m0zX0l{lY`;tN;e1cz-C=AX>N?7g< zYw>xhKH1n&scfTthJQgw{5=1XtMj1)%aq2vq~3d1+65rX>4zfL=}oT-us@bRFKTTJ z!>`4t)`p>_v+o)F%Y-WsPzz<)D#L}ALs%WZjagiDw9E0>3l0H}ALHh`K%VLdHk5I^-_X{rm(Ej67z<{tY`CKhO_RDI>k#yrTpl z;~V~u6cVYqwHPbNBC=0^!5{H{vMvSqUSCoCXjzT#v;(|S1M$hc=g|BfhH4F=N7yEq zj3=sdV-XY&2miC+A7*mXe-X{m_Db_$;q&*Aw2i#j^xR+Rwhpx&R7TuNnQY zv7m~6O?54LDtd)}ZTe;Y3pF0VueOKt__ct3B|XW#>@_s}VeJ<7Vj+@BVanlGPcfHL z42Fs)Pon{+YO4qsq{aOa@gRPB7QbVBU#>+D#w-gS;NG{gkJ&Sy!>@7JDf-ypm6#U? zE>}s*<*x87|Ee(3kWlKVJ6?)?2)WZIAhg8kaREfj>4)Rsl^8Q2M3-TqhTxxm#5_Ed z@UpCZRV?UJ!M{R!DXZeoqEG1F(sJ>mEeBhHdS98rukt=RxfR|Ic}DGOB)AFhu!??4 zc!vqam$eIxz`rEhidVwD8^Ns-zvx}DL;~3<>;wGx42#CT8r0@R6~rX%LBrJvA#s!% z47?v__BlSa5olGL&_|;v1F&mF$YMTiw^S5OCC9(kQ)Z6^ye|{Th^;l2x-{f~EO6=> z{$)BA#dlIoO8+iaD!9xZtyW1Zg5j&P`3LwjyvEkQ8~u0s4Zmwh+t{+G=*0k%m*Khk;jb9_Aciy$Lki6mO|G z*y9-mFX<}RbNnlV!oPv5e0$AQ%MT<3T;lIjFzQak^8AZFAk6DS30n#2JY$n|Mr*Lu z*Yo^q8$I8Os)FOrrRw0CS^>Q`t)lS8#{RML{0pY{Qg^a&8-ht-L4sW(Sq)X40Dfis zq0|qv5Wqq-K>i`!U}Mxl7C93vs>s8cjoxlbw|(!VEer{WIsWwtA)b%;%at~opx{b`Mi;~zv`Q`RJDB5NnLLrSrYXb;Sd>ZS zy6>lZ$ImHo8@ zt5boehwpP zp;`Qr`LCE6u`i`&zNnVS^^%_yrxl|x zBGeD~@N?Whsb_g~a8&G!?QT@0DDpoPI{%3IoXgdj=E~!`b4HU1suM zO;ilokVfHF0JW1C^D1*gJg*;qN>}Y>UiTV?`m8EJL3xKh?r;9V-nU{;6lO54qTq)0 zVkcyu6#T|3ncxJX!BuMDhf?!$`r+w#{Gu1IKo6J?{oU$A)~7m{0m_rdx{|PWD;Q=7O<(ba0b5?jDyt<{Qdfb-p5Xc0IU+5 zE>nH$`iGr4{cxufE`{&yQCiKb7W(`Yobf6xiDd9ABHxb>g4d{7PsIZK3t0p5i%jSm zWb5N)v-nle6nrZfS@BC!dbA1DckHI-xRwSs@yv4y?rDJy+C@gSi#o!Qp18?e zCRmB>8=S>2<$2#FZ-Nq{l?+Q*ETtqXfMY8?jQuE zAiZoiM^J!K&E!|1{_v1-jZ{ooM_y0;2YWC4Jd`&SJR}@*^It$cQ6GyE$)zlVUH5}Ov$$EK(A)-BS$jPE?Ae{T-|;xSs@s!t+@+@T?c3`gJ0 z@UM04Ejj*`R=c^cT@Mtx)PoVLN56#)ad>`1?=W)w>zCpb4UWMILKNk)K1%rjwNSyd zyT_5kuW>OIT4rPWr4e+2u%wl3=4S%YV4@73Rn8syAqP9=>#wX0va{lLfj%?nkecOR z9qI$xLjrz2;ao=GR%yKtnYBBqHlU-8PB7r>r3L%Ocu%Q}BTCqyn*Cq8c6`O4i|C)B*RKH}`wJRxF z4M{MAU+{;rG0VRkll&&sT`-qx^onR6cTZ&I)gauL^Z0eaeolA+H{SO!FJNvz`=hk4 zgnl_+zhP@f9O+S*)dcKoTl`jRYoM^1z?gIR^-Fq=yeWNObOMn5xAHmTG^k}VhB^Ei zr;n(9965zimPzysf`d%)BLefv;a5`DIoKJt1p%iG`1QwZpw8v=L*gGfR@!b4<~2mCJBv+a zh=$F8KqX;bKjfd#og?lGW#=6?>8_!Y3(95snC=poU}_e>{v=V@2A%ZD3EJ*PN2cIG z_y?36|B7?Ot9Ex<*@UeQLkmN@h%t}QzMRj0{TM?9Y_+k4j%UQ?v_4T<@7Q5iTBxXR z$DYHFte=lk?P`Q!AuOeL1dvG-;}Lbp#5!!4G9w0MO8!7UthfeQqgbvy>ceS|P%g#?yXs986#Y^O%RW7e|9~+E zBVdSE*mcnysY?M1u8X_cv3qm+;W)hwzX8v$(sh0p8fEXGF%ZEgIsB6R3u+;x7#b8A z{7TbcueS-Glw{{F>o=YvRG1hgS^fn>dl8uH3!{**=%i_QdSChNZ_E7 z(+?B$G|5bs@^wH`9cdA^7!42kzWX`;Wh}R~_UIyPHi)0#%MtV$!Ax`bH3YNz`6#k@ z>j{-lq!}ga>3Q3-wLqzsUHAS4eH;io>H2uBU%MI)wz@>D5_K1-{G815uRmZG-jTXw zCF)W*7EUM!=}u{1bLuxxt)VrfT?q9h5fcy+Z&;_-9I@eB?A8p%b*SHrAE91briaw& zoqmeMA;?w20oGF$=a8-crsgmI9YZ@j+v1EnnsP{ zuVtTE{K9#MD+2s0rBpyCY0w}WuA;Fh-p^_SvksjdB#1>U~hw!#KdkS;-b&;-( z2Cn#fDt&|mM5F64tI|$ISD1?q{0ICJ$TCdPr5=<4OzAgDp(xT9C-eNvqHAXTKG!3a zKJ!iKh$PUTgi!A~n#V6w8{poa&>|p_uzLv$R|SAZVcY6xeReI<1stN76~P|UC_$#^ zLR|{mM-f|F6x~i4KV~}0`0<3NO}hi(rAQpy3fNjg`-M4~50hgo=`AKLEAbOr0xZ2xOYNzCGx4g6~2t{&jm z1iRD5`L9dh1>kYX%9;FEXnq2_?jR4DY$2i0*Zx|2sWh~jL1#P5@vleOF0nkKh1f#T zCzemjL>N62uM41&<6mbex(Qx=kvuZM%`|Eh?}5*(P2F8jIsVmSp6R@!XWN9*$llZL z?9;wo`JVWMnk`q_ljC0(3t?8J8)AqLCqps;p&&;{K?Xz1@h|9X@anEd0Ri0<;I4!T z!A*nCmYB=GI<|N>Ic09^sZ@2?xxe&h^enIB62Ef%ivhNvm_=WdWxY~AlzqH5@GHl^ z3Q6)5XL;$1o`jdyRyxO1v>1_(F-DtKV=mY7db|EV{&&7d@2n3KVkqj8lkvzc!)d^+P5u zmvD0D)OX4lTqLWuN=N39c|0nspMZHVuhtm zt$md55S5m{P5A-)qd0t_q%Bv!v3L($T+mUHR8B@eqT|ACu{MOItL+WetbRxZHwfq2 z(i!^pK@_lcUio`MMYPW~xBgJut0EfQ%)UUK^krV00+GkrE=@a8I>U*Gj&YdY2u=zt zqFz87FgIW#S>~z;MRWKC&FW!urRLkG8Bu$gSyTi^0OqpD=gQa5{{m_5q;Nd}ckynz zerkR4wpuzNgsuJBnd4uV#8f2MlfmVWpuGdO4$)@|fz)&IU(+-;)F9S_b~#?r>V-=t zUv8kz9EdiP|LRaTc*QW>;4fP~P@fw87Xg~QT|G{fcJTvw{xDmAiRVZ|gHNC-M}Yi^ zeE#b-c3o}enKA%bl2L~=ig85(SxV30*Q6LLzpKg#g^FYz)^%d-N|8D5FbBUbaM6zX z-ab}IaoZcv9IT3W17SmEX%4?eEYzG($Wuxo92!zJC>9h$?5EACpYOm>{T|JVnk=xA{sHe^0*Y8_KMKG{_Twle`@P>qIwCpZ+(r&a}7I3FszMr&Xz?g2ubkfQv z90wnS`{cT9Sc}``DeNhV$UZXvh4|Sh=~G6;Fc0i^8A>rcWIdh(95iJguO;-fU1@3G_r5N6h~-;R z!nctMg(vN7E6wpQl|JMFs$HRs(vUgW>JOB0cFIiJwI1XvW7!E12)pqu1$n z*%;uGX%?r~rV1mnPk+IC>@=+=Y*D`<(_ZVXG9PRZM9flh_;o_#;KApQl*DH;&Np+dOLb zZq>zp z`CtaEe#S0a_1terKd)v!8CEm#q0|qbwM}UA$9^q|AD2B!d`j*ML({{=50-;cMd z6i&vLM3p_rH-`XZJ7@L7clg!O`mLxDkT8nZ`(wQ4AvD(aDE)c-`Y0Qcwxc9?p*L(UxdaLtx%RiClU%#*rM~#A4jwAR7?Rp|6PyRNEy>s!) zeA%9#c1|fv_*sE4Y$CQw;#cHz_$B$E?fZ}|vUkm|>GVa|N^B%gYkX~9KioqoL4T>b z-COQ})M=xSVRlwL&a_cjyD8@`>kozL#d)h1=_--?GnwLub8G<0*KZu-C%p}m$ok6i zyr2!-scSiHqyDfyU%xSiS;%=QA7EZf!W%4oEIYx^;nypk3|bu*uZX${cSONC7p*~n z$K~*An~JJ(Y#ZhZKxd1rL%tG)qgXH8@W2f@W>MhBP`$E-ypOu8pv76G8KGkhBE}qk zA%h9GBk4(Iadi{5vOqLxxij%0@?Y>;M{MYaeUuTD(h%x#-t%+#HLXo62;(QAZ$OW- zF=kmm|7%IaX7S7M7M-brN*q!G_A6$CR&rh`rI(^#j<|=F$u$|fu#I;pUW#gs-e`e{ zH&zD_M|laAX{Nph3BHVP87&y6sIT^vX11W}hfLL(EHzOx3GvgxE_OuZ+)=+lyZ6+N z0xzlvrx#2#YH4?bZGlcQnYA5~_49Tx9kSN?1j_0HB`9Eqp_O{}9#eAl8^>C%Qgga4 zz3xisv~=d@kyE(Q`2u%O$L8SIX`mIndJ&C=>+c1=kMmRE`ro>a=IS>bCDAVUh=;6} zDufTKBB(z+Lqo#5PfJEW%-UDFU_J7BrhTg=H7lM;E8FbhNWUZA$Y$y{(vB~-0JhT3 z_Yv-P?*GP$&{x5Pcg6r@+hNj~b(i;V44DC2_bMtr3qZ^Vkewsoa)6z~j>ZpP{A=m` zMhY)hqOQ`>Y;Q=fo#p_tjymXv^CGej?%!ai)xbGa%dbYM8)Q16K-vtgwihL5bL*%- zl-49orW~~E%L4U>i<~q|YIqX1j33deKG9Z3i)kPEKh%Q2!OU~y`Qx+~$j z^f~;ZW#kr>2(bvVMkj>C2>~M3q2%!E1FSOOII&i`)0OQ=3w|kZ+R9WU=J4yAW*1-r z{9>um#e3W0JrL@>~E&=0ka*4}VYIa{iB^JN)l&bp*BkYq1q*HoUblxS5{ z?v;r!OU8#)4mf<-n9(;-KTo)S1HzB2pBJl4ggqu4^#J+f`TE0gc6|u?;U-x>Z{L-w z3zxkHKaYs`R?@FI-!DW_=>hk7u3eworZw%lv_c00XnkLb2Xa z>)AfCej~$AvHgs(R?yPn%6b~(&8|Jswa%G71&vT?ss*a$eXfVdE0FkJPP^4w02y#F z^W!UMaR99@bTz{CqJnJS1FVEgXC7J#{*_r%Ykt6dglb+bdVu{ifXri~Y$M?4q&h1U zW}$4Kek!Hkh}*523H=&7D-K$&O~@vVh`YT0M$~U)o}(=g>^-1WiKVn5)dIg^DH;7R zgt-s1h#U|vc#Cc5Y~Bpo^$AUjJJSz^lzKvKnCZT%7)EAI`=M{_GHY596})B~MgB|M z{P@@T(ej#B{lBrFXWz3yJ+za)LmH2!=vQJnccwwsWbujKUO0nak@8_9%B8%J65qxsV zzGeWI`^q3BqR1KZN@wGZgz*V`iI5daLuWhTthY-hVnKmdFpj?(YBlBDg}O$4h;9>l znl);B9o|hc?WO*cW7z;2=~?_*&btX}A-0wjy@fuoJ5!@*%RUsA&(TyeV&s#3R00-= zOan=4fxSAc$}S{|BVghI_ym|0!Z~@&)66=DgkopcOX`P+-pOt2ld6>0FnD*CV1GDkXtkWzXALL;s;Z%gUYK}-#c1RYwU_6+IfUcgiuEErZxb5zB^u<20(w3 z^>yij4W^7GpdY@%pXcU~Q%0Gwkl(_t%hey2(5?I>rW^r<%X8$x!;0v1dg zT&@@H-=GtoKw>@3dxd{Q0lOriOfb}MY;-yD^&3Yqi{?($A5J3?2HJHcc7^|A1u6ty zJ(1&If23|tKHE2wWwi zeUE*Zeb2amV|lE%($c<;RQL;G=|%l@Xr6m5aK`O;31()@<*4sfz4ygk&J89~ndvXw z0mTm|0bg*r6gBm4Z{QmW~b@G1*FVY&Cznj^`Q{#Z^wOsiSgQf#?Jjbd?I z7RVeTmcy?<(p8-M!+O=Cz#9kmdX!8?Oe&>0`~v@?Ug?&fl;KlEKf=c8$S@LNzh<-i ztDuS>hJE>x3}?j1`TdRnZUM?6^h1tu_2|9hyo|_iP`%3%=u**!5U08F)uWhjW|$<7{({( z90B+gLC*-LV10be^~-*s^Q-Ww=-(id-m*vtAuhQGh(MyQ;x@1u$-P_ zUa&3iQ+%gdDR6LR0vAbvk^LfiDr;Z9g0Jzz0`^q}bvHI-+RFoM4E)QVUcQHTSLJd_r_Ms{JnB}%OLXlVDTZZJq*;vX4X~0BIvz(=}_SL`ODfomH zsp6HO_AiUTP)!mEtZN*Z{b$QAX1`0&gai4?w7XOJce=`h>Agp#@Jj%)!&uzR-f$S7 z;Yd!y3D>n)qlt6Aw#&vL)3e51!)Q!ozpF$2mU!Rcwd4EQ9W8rDVOD*pE$p^yd2uHe z&X8l4{OfrG91W=!vrF`*HLDbdc{Q*bYj!PwU-UTj4q-Z-)CIrcqtY?(FTdSIrKcS7 zF{nS>hI!!@ktFWz=|bR&Z8Hr&*34mXX(cSXNc{Q$VZ7T`+7YWmsK=P)jZ(6aE^L>5 zY~;VDk?V8Y4#fO)N7ee1YmXBS?scn^YjgF7IAIOhP}x)YB!BL1FH)>dFX8@;heJ>0 z^IxMPY4}tGb0d@p__)ttf_{$Z3%)Lw|LO}MN5m@bve*A}(N4M;ZwfqiYKLv-Wk%_+dKJn8lfFK)~0 zhy65#(_YZ$YpOC1qz~aGPOOAoM=Fi1eT^1W(O>{_=pLhvc5|;C>ecVZdbuvpF?cL4 z-;d0H9kH$Rz7=;X4y5x&oj+zfJEIr;D`eDRz3!wx(4YVqyCq!jh`%CBR^kh#> z-`yJJ^g|6-u32DP3VBaaa--i=;^qko?#C?)IsNcg62C^=m*;)R&lq2{5pUefe+NV> zzMQY$m|!T|NV{(>**(SfnLn{B)1e9$$l6z^{H2Tz0NL;q?=7mHbS9$@(Id>*;+%ny`@C^)~S!?~GF@F1(BJpa1H zp<=bV6SNhk*VN*A6agM=FueZZeE#cx*2Mr@QgT0hzjvGKF@39eHjNnRfD*~tS49C_ zH+!7x=e!R9lB#8Dtk3bRsO4>mXkm6uHFc@vr)%_Z;cpy=TTz}@&StS7Uw_D1e5Y4d z8-5Q!R!x4PSO#VRAu*r-dWXSXgy-#7-c~=hnvi4*bGRH97t83jGXcuHhkHqr+;% zhJE$n#sq)JS1~95C2-n{J5%fd`YGGeT2bzNf^|{J7I>S&>{?h0-pTMURNRfLR{>-t z31ydgGPR^#{pWoBMqkC{!XST09#wl)60rkok^hRW=I#n`{D`y*pV48DnYUBMw@gu! zQ5;n^1K%@=jJf(DM~E(A>$qqT+PJe3yuWfk4l?KT!>=MluOgiocO=c)SkWD9eS9F) zpLRCkj;X94b5vj-X6pUk)Q)nGaI~{>^Vgy+wa|?EX7G!e*ogSD^~E;jFVrjIg>=ED zvcINJ#U1I|?Mn45e)ZGytX8s;2|9+F?GmA+wGU}k`oWxji28YYMa-*`=ZR=qG(>79 zD*pnXG+&%szi~j_Ip6V`F3(pUrQ1$v5oZPUnKi@Omf89ZgZdC0;cCRq>@|Kg?BR`R zmZT@N@3d;hEdOdNf00EIljw%@2vltW-;3y=hWOdssm{YHW&Oqh&7=r~Rv+L+h=qF>UrmL*!9hM*!K*Gm{v#xUJ!yC;>Km|_F> zpI26zXwWu0uOGHK5f&QyP9V`W+iUgj$307jqYd@NUCvqk(1GfGqng78CscsKme8-3 z`T28kfL(%_v-ai3H)hUKjgUoF2kze>86WcHG^-zq;;lHg++@4uT^56wAj;}|##ILr z2Z?$#N)Erq zldz^VDkLw`?vyuDJh;(oyb!89g+t|L_C3c@*DVCfdXck(;D(%?3<8e?%rUKgVGh5Z zFyo?jc-^4)lIZ5R2yrm#H5(imG|%O~{s_=!X@K_)K~7rN0WuPXPsr6D2B}lj zO@e=&)1K})80r2#xD3!?tM+{}hhHwT&D9dW#?%kzJ;2>7l-9^cl;r+^BZpr&=D_b7 z`CqRg%zzu@IJS(cAp`z!PW|B}I>8aHfPa~ja$`3tzJs4>^(ohp{QZaW?Bqcam-pKo zr7v?B+G09ldWP<9kLK{}F?viw?Nt5W&~e)n(Wgq6bUrfx6#fAWE%Sb4{rn@?hmZ}| zYe%RmqOXj~lO5i1#3cK&>prnykiQQ0=kG83f9Qr?-|rs3)dw|xK)5XBxg37cgdGgH zJ9Gr?ro1*v79vVSBge+9eaZVb-tg2%usVKm)mYUk>*7%JHh_B}a`;89Pz%kCS}FYM zVdf3#`%2{@6q(z?2|h!vX+^YwasKOk)*E|iN~{9-!q-iSfVp1F-`{(Ku8LnvfA}_C=QyvIQnngb zZLHUv`a|fw*sDM*lpR_txI3KTl@0Qw_AGwk{$2sJ3JLi6LA95 zM6cx(^7|P2z>WHd+r%sq!+zu>3S0|Uh_<@Y#?*TfGU!)C+HOSWq=pZ|KB zK63<1OFGMj2?15a-4B5Nj8+33X7Nkj-+R;eN8z@+>*-a|!1ttMxBLDPHVBKeTQeBf zp?*U=KZHtn9G};^T2@9h|JrYf=c%p=zAmR9dI{C?mh2;b>g$bYhrFizq(%0b#Vwib92dGFN~21&LOW4ej}p z;9qypzuILp2bm}H_;pUQtpa2x7t+h3IqmvwS%dbb-Qa`*+@9sj!kDnSs=RSn!7_^P zs5LdV(WKo3<}#4SuQOngmP^}Lsv_;>ms?bec2${XC=lI}wJ&@A6Rg|t%3t}VjPPgi z!_g}0)-tz2=J0ErP6$k=LSG8ISe;()*DG638%Ut9jD@rI1^o~+y=%mMPMMPT1bX1! zKct%ig@|+N520(}wd~oi$hw01J&^A2^Pbk~*uwFF)s*a z5>YqDZU+DQ4*m-W7LFgY0)gv#!g?+Hh8p7*|ALXnuZ7M%!;vjoTkpa@+nMn6>ECC6 zrQt>?^9$QqDEl1LADXslZUSE};{S&HAP#hF6Q>=4P)#ylKYtX}@>w_zVc|yHBWtrj zR+7&1uMyNEHE^<&QDT&cWKut;3+|G*oU7kR&>qC$u$0%N5edz{TUH>~*!Uz@zwsRH z7oG?>?a?hOmH!gUAU%0kcnKUn@upvhki>3m&e_oX3^uuvFX|2LN z70OaV-m@L}^#sTL8z_L!2XLLO}{EdZj`wig?S{bulMnWLMQacz=S zdAig}uD@1zh`QpnVH6qW_*a3^y#^7;YlROK?j=ve`PwbTtb_acZTs{1)kbkzWr22? zYMcgOM2e-3vY=Ta=HM5*9tBzruEn(*I51VxvlbU|h~{wd`C0x|f&AB5I44)?zLlyx z|K-A+7+7Ug)bCeb%Gww7LrswBfNW@LakZA>Xh{4bT#kAs8z)HpP}Uy;tyDEee=8fE zj>8Tgzg23Uv-nlmrO7_tr6hqYUIC8wEPXrtKX7(?mVdp>QN_glJu>Zu*XvJo_le8q zb8Fm>uARv#_#AzdIrg=$a$H>X1`+#}Z4G4-VLf^LvZSnPLf=S-Ge;qI>ShA?1;3To z5AQH{(&Lsd9sNv0705yT9lFyz-l235?lj5T1@4bBW24wwOBfFGa(`NHT&QbDHdTd+ z9PCx9CrWe!GfZAR39eZJm zcd_;(S}HJRI~yOGoP3dhk0GIgOMEx<@d&WElsr7%H!7+8Y_h=l2Wdj z(;dwd@RXkQ)~vA`(Wx zIp_RWap!K^J6S#GbntH5JETvt)wEZRXYTng>fp=B)5~@^9uX5ZhKgc5)VQLN<6pOy z?udIYz)>kVqOA;Qaxe3M}`^88D?ZoJT0 zcUsv_H@&xyV2@=kLPQ~AEL9khHrQV zGi=LVxY_7&>;wN&MD~-p_47b0@B&;3MW>(4T(49GVH`nn9>3K4wXWgX_D~O-Cw`0C z-gWZ+-ro|6pz{37fr^Epnk_iF(1$;V*k~{ub_R1nBadISgMTNi-3xvGr#!-uZYWR> zn|{9TbNtJu)#S4k5Dkf6@*>{}3*JxroPHP$M$Y!!`aeO$n%97K{Xsps26=}(|5|W` zNxX19te4X(tlq|Skaz+ELLS|!P_dXfsM%eL*UmyWCIFj z&SA8Ua#wdo092pW}2)btVLwdXgX)glXG70y5dtdN$n!6G|NLPqbX8wMzY{Coc2Da;CK1iuq~FG*>B#fTVD$fAd)FQu zS9RXM`;xDum37zBx=Y4%jvl}wB)sywjw2sESwO)X{8BUiVnA)^3?88F@7&j}w2qt3 z^fiO_5BsOH-=2G3-}!ytIo~-KJvdm2_(SEzDIEKH@2y`@+qtS|3;gx(^no~&ulh)9 zGe5|#JcWg+HVZ3M`N$^&6!6z^9p|YX^GoV6*w5JZk_Vah>n#MUsmZewh)&S6R7YmN zdV-$B9vSMjjPJLWpG67<{57Q>M(T1bATmBd2 zn7(FlPdiqqSaZ?&uROh5)@CivWpIyl`w!FAqnoebS8apE{?}D{Rl&B`G-5bkk<)uW z=DODu+#dyh$LBBln)MiVuI`x__+9<`U2FDKj;@#U^PSIOt_%II2<$_|Oy<-dnBaoD z@zql%WKvRwxZBRU3ASRHCRTA4$J`tFy-D?utQTp?AU=w!dcj{w9wF_NoGvmb#tB(3 zRItI(JpQ@~7yT$}X}?ps1^$;@aMS+Cgy%v4;rijMctt#Z8Qzw>Zl#qWY-0t@h>Z+J z@~qcij`g+$wo(xD-vrwb{B>GgOo-o*D~hw8oiJsLbJS}J^-4gkU<4*Q67;yzOt3Eg z)w2(s*ocZL#eod#LWUy=8Hk8WJtQg2`u!fu)7TLilF;hdC2BibeLx!v z_zV7*zHvAFFBw<4QJ|TMI0|#8+dhc;HRoA4&o1= z>iF1#*N>ya9)%<3AWEsZ4t*NNZ#ENtf%W`VI+JbQiMW)XQQK({Ss{Kye1tO* z)uPh9pAA7E7+Nr>ELc{d|8*A8^6ql+t)B6Jyhc~wP}&d+Q5?U4?O=IZ)GdzO(yBay zJ+cGpoi-K;^MU^bkDi+PVH!2cWetw6R?(jl?qHuSoAmlZ-p_`vl#vg*XCEGKS_Nyl zg~PD-*Eeu}Sv{w$m)l;je zzQ}fET>ooPS5;bTqzQM30!XHoGM;|P_zleS8R>t)>2qldJuQI~#BU(}5M_o}0y?%p zTd499lvzjoVH)upu3Z;Le6OVJq2aGL0-)|kac}eY1?oOs@W1|<9iTP+RkcgX-Z8wMY3g_3AOCd|SJc{fpr?yLxy4{NB_293X zSrzez(pnDVH*UfijpZZed)eEu|JCr_d-Li$Oh(j$$U^^XlP>D-oQ7*(!OrA!atIm zohtZWPoWkYo#oj75{NT*;8(iyJVAH-^+UP;bxkaP8_Q5@0a`Cd-tAmZn}(Om9kJ;` z{2@+LPMMwA-5a^dM>Scr*GjkOQju4}+$`{lsPo{{! zaF;zHt`cGMs293Y4s6UD&b0qR_(M96B@5_Rqtq|HNmR;cjdywWxKOeRb{YtrL#_k>l1{?~WufCZ*LrrxR!sUx`r&NHgt z;q_Q}EcjnPr}F}{guvVVaNKw_a^)bSH;13GdUKtYr|)^?S^8MuUj3IfoXeIfV{4P* zZQ8&N+r|DD;twORwOVk$)(X)(f`BXdUseR?zr6W*$}nM>*XPi@E#m1*^}~s$4(^uz z7n%Q5h~MZI@Hl2M4KB)@5%nLXn$ampk-Zc8Uu)<|>ABpE`1v0nJ$ZTPVfB96FHSOC zm}7c#ru+U%4AE*uGw7Gribv6Lq~b*?yqOJz{?`k5FAUCqjiFv2%Ik>pnCCG=c2(yO z&fzbd%a;9qo~;mf3fy;bKGo)+UZMYWj9$mG;ZPc8;bE&zROMj=J}Q~$fr9__B7JkH zuHKZdY}zmETxFlMAw^3bmxqM@*AyKgR*%yk)pQW|RNQ`B#bF1x)lHYPiY4Bde<${r z>}Ql5Zhl|;oH)l;=9XWn`7QGt-#F5O_g5NBj#c;mUV720&SEv?BmUyjR8bo+4jcOcV*J+f?>*B3H={v@xLXQ{dM*BC+B)I=DjNg#!hc9z? zweTVoZRNhj|A3Ce0;#N5=zrx2W+7FYDu`^PDe>5lwnv?!5%gHW|GKP7^9ec#A~RWE z(^8DXM>vd=bcGu5*C~ELzOC|@dL?_nYU(OKfeJn%6nO|P@V{c%|AO0f_?Y(B3Ctzd&0mDrf<`i%DkjaOi)*u$KFSFh%NUDzj!uvl!TkGNZ+K zVgGBLz%2*a@*MoHZ{(gBs($KaTyLNDWf($8&7Tn-}(S%rO!>|wiuVH$ftsVxS z%CM-0iWVFC^|#n)Ho1C7;D3$MlNEI${vnQieZ#C9j@u}_yzCb%1EK#lhPpSNN+eZ9 zWJQkMR8uj;hKCyomQ}d_m4QE)6p>kJ&x;kq&6hRI^Vk7z&IR!sg7Qr6992Ju>VOL@ zT-$p=@|Sa%1^lI0vveN&)V-3wJ}Ga_MNR{}YT{R;TDX4rKo+y#aALOp4tgQ`1WVlG z_7|p@QMG9O5HtUjnN&xx##sOLp`-8_U1Ld-6qkA`;}3E2SHLC_xE6pZBro4{*9r(@ zRf-_~(3Y!esF&PI0O-vj5OGR+$HRs7!&!JGKN9e^(zJmv;X8OYu3S+(JRR^CO|)zM ze8yUD-n?w8955RpFWR=$7UfMg4k3l+Co&i6xC*5A*|UC+@neX1o8a32xZRZ__rkh6i{|EZVK4kP-{a z%rzS`#~P{(GHZq=fxNlq7iXB;9x) zSSxfdg^~L~pC&~wt16vyw2?lNt!n6cN!tMC=TQUD0g*nb$m*@=2j>+Ugvd;n7R zX5WN#~&LgYN>wNgQnCt5fr*i*(v()2;)&>r-(~XX6(%L**)=CAk)o_eq{%3 zr2_Q#Lk}WF zVBE`3cZUIOVqK=ER>`fASck%$Ev(iw0{tRQNjqDTv53)G0QZY6EM^*9;chJ3 z)t5S;XkDbhEY#yNg~-#>?hciNU<^Kt1UZ(FATtE>%M?Mqq<;0e`URDd0Q%*n#DaQF zaBYr$Ev1`Dn>Q|2$hk%BGgau zh0Ly9(YVu77afv7?@<8kXnYVUg?zfx(JlH`CB}WA@b}5AZ}GC6tM1o9UvnI$720g1V&HTeF#t$rK(4nZ|=8xxkpx zeNvcO^q?|>l&BNPG{jSrR_oxQoj!={Y_PbqBsqAfE)b!O*EU`In`<9l`?M5q0Hz1o&by@^Ue#Eq4MTy@-zI5p*bXy?Mi*Nkotj(XZgsxDv{k z=z?Y9E*6!2F&Bi-`jz=maX#~T*(Ye*3ZK=a-;-IA>pC4R1%8oDC*n57Z{qp8^PFbnp!IfM-g9Cu1pGwdpwBO68&iWZg#*?=Irykf43w zcyknoXh6r;0d7Vd1q7Q*_8cz(jw|9mE2Po+z@HB}n3G{vFS17p7K-rlNh=)%Ixfj4 zcox^wN-cF$v=nrB^-570wF}GE<4P&;vY`}tbR6<>G4N%0_dH$>30m^9KhG;Y`rgbk z`>uF&vIIDOnUx-OuQ*}f7B8PH0lrLnE-!mTA29WJ&|m+#esR=Y(s5Z_d9(xwuRPRk z>-&`7q`O2kUjl-$f&QAq%OOEaUiR`qpN70#0sqhz|d>ORiI%P3+3M*d%{5DJz zG@nN-O{cLE;Q0BFL9N_9s6SBx#)D^d>Neif*%OHllmOwkA}>JrMbC<>k3_91!#$htDdd;~?eJP-YG`P$v9UDZp@*A9X`Cxgas4^L>5*F&| z7f1dl3d-zuTv3WIRWM*=!UbCCr@Q~@toW}R;SC#Z@NISV4Zi%J`fB5~Yu6l^c_|1V zS^8C&^8Z$5o-T(<{lB2g*PRneRWD5O+puV477yBRY)UccX)ptnfK9%SjMF4n=*Txw>5V zrHdAH`Fc~q|E<2y>!R!YiETMW4wEEx+9Ue;kA(UjFMef-i3* SDJOpiTT13LR@j#EGx-nlfX!L} diff --git a/fpga/hi_simulate.v b/fpga/hi_simulate.v index 92445edb6..78650c4a9 100644 --- a/fpga/hi_simulate.v +++ b/fpga/hi_simulate.v @@ -65,9 +65,12 @@ begin if(mod_type == 3'b101) // Get bit every at 53KHz (every 8th carrier bit of 424kHz) ssp_clk <= ssp_clk_divider[7]; + else if(mod_type == 3'b010) + // Get next bit at 212kHz + ssp_clk <= ssp_clk_divider[5]; else // Get next bit at 424Khz - ssp_clk <= ssp_clk_divider[4] + ssp_clk <= ssp_clk_divider[4]; end @@ -121,6 +124,6 @@ assign pwr_oe4 = modulating_carrier; // This one is always on, so that we can watch the carrier. assign pwr_oe3 = 1'b0; -assign dbg = modulating_carrier; +assign dbg = ssp_din; endmodule From 61e4eac2b249e8a4d4b86fe6ea2089c22e87b49f Mon Sep 17 00:00:00 2001 From: AntiCat Date: Wed, 5 Sep 2018 22:23:25 +0200 Subject: [PATCH 0008/1938] Legic: Moved card simulator into separate file & cleaned interface. Reader and card simulation have almost no common code. Moreover the sim uses an SSP Clock at 212kHz for all timings to prevent any drifting from the PRNG. This clock speed is not available in reader simulation mode (SSP runs at up to 3.4MHz, and changes speed between TX and RX). For these reasons having the code in separate files makes it significantly cleaner. --- armsrc/Makefile | 2 +- armsrc/appmain.c | 5 +- armsrc/legicrf.c | 14 ++--- armsrc/legicrf.h | 2 +- armsrc/legicrfsim.c | 139 ++++++++++++++++++++++++++++++++++++++++++++ armsrc/legicrfsim.h | 19 ++++++ client/cmdhflegic.c | 19 +++--- 7 files changed, 176 insertions(+), 24 deletions(-) create mode 100644 armsrc/legicrfsim.c create mode 100644 armsrc/legicrfsim.h diff --git a/armsrc/Makefile b/armsrc/Makefile index d70008e0c..aedcd79a1 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -54,7 +54,7 @@ SRC_FELICA = felica.c SRC_CRAPTO1 = crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire.c SRC_CRC = crc.c crc16.c crc32.c SRC_ICLASS = iclass.c optimized_cipher.c -SRC_LEGIC = legicrf.c legic_prng.c +SRC_LEGIC = legicrf.c legicrfsim.c legic_prng.c SRC_BEE = bee.c # RDV40 related hardware support diff --git a/armsrc/appmain.c b/armsrc/appmain.c index c6e6e0dee..a048418d0 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -19,6 +19,7 @@ #include "printf.h" #include "string.h" #include "legicrf.h" +#include "legicrfsim.h" #include "lfsampling.h" #include "BigBuf.h" #include "mifareutil.h" @@ -796,10 +797,10 @@ void UsbPacketReceived(uint8_t *packet, int len) { #ifdef WITH_LEGICRF case CMD_SIMULATE_TAG_LEGIC_RF: - LegicRfSimulate(c->arg[0], c->arg[1], c->arg[2]); + LegicRfSimulate(c->arg[0]); break; case CMD_WRITER_LEGIC_RF: - LegicRfWriter( c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + LegicRfWriter(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; case CMD_READER_LEGIC_RF: LegicRfReader(c->arg[0], c->arg[1], c->arg[2]); diff --git a/armsrc/legicrf.c b/armsrc/legicrf.c index 3a45c4c67..59cda1221 100644 --- a/armsrc/legicrf.c +++ b/armsrc/legicrf.c @@ -1,7 +1,7 @@ //----------------------------------------------------------------------------- // (c) 2009 Henryk Plötz // 2016 Iceman -// 2018 AntiCat (rwd rewritten) +// 2018 AntiCat // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -16,7 +16,7 @@ #include "legic_prng.h" /* legic PRNG impl */ #include "legic.h" /* legic_card_select_t struct */ -static uint8_t* legic_mem; /* card memory, used for read, write and sim */ +static uint8_t* legic_mem; /* card memory, used for read, write */ static legic_card_select_t card;/* metadata of currently selected card */ static crc_t legic_crc; @@ -179,7 +179,7 @@ static uint32_t rx_frame(uint8_t len) { uint32_t last_frame_start = last_frame_end; uint32_t frame = 0; - for(uint8_t i = 0; i < len; i++) { + for(uint8_t i = 0; i < len; ++i) { frame |= (rx_bit() ^ legic_prng_get_bit()) << i; legic_prng_forward(1); @@ -235,7 +235,7 @@ static bool rx_ack() { // Legic Reader //----------------------------------------------------------------------------- -int init_card(uint8_t cardtype, legic_card_select_t *p_card) { +static int init_card(uint8_t cardtype, legic_card_select_t *p_card) { p_card->tagtype = cardtype; switch(p_card->tagtype) { @@ -314,7 +314,7 @@ static uint32_t setup_phase_reader(uint8_t iv) { legic_prng_init(0); tx_frame(iv, 7); - // configure iv + // configure prng legic_prng_init(iv); legic_prng_forward(2); @@ -501,7 +501,3 @@ OUT: switch_off(); StopTicks(); } - -void LegicRfSimulate(int phase, int frame, int reqresp) { - cmd_send(CMD_ACK, 0, 0, 0, 0, 0); //TODO Implement -} diff --git a/armsrc/legicrf.h b/armsrc/legicrf.h index 4bcf04899..639687558 100644 --- a/armsrc/legicrf.h +++ b/armsrc/legicrf.h @@ -1,5 +1,6 @@ //----------------------------------------------------------------------------- // (c) 2009 Henryk Plötz +// 2018 AntiCat // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -16,6 +17,5 @@ extern void LegicRfInfo(void); extern void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv); extern void LegicRfWriter(uint16_t offset, uint16_t byte, uint8_t iv, uint8_t *data); -extern void LegicRfSimulate(int phase, int frame, int reqresp); #endif /* __LEGICRF_H */ diff --git a/armsrc/legicrfsim.c b/armsrc/legicrfsim.c new file mode 100644 index 000000000..791082d6b --- /dev/null +++ b/armsrc/legicrfsim.c @@ -0,0 +1,139 @@ +//----------------------------------------------------------------------------- +// (c) 2009 Henryk Plötz +// 2016 Iceman +// 2018 AntiCat +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// LEGIC RF simulation code +//----------------------------------------------------------------------------- +#include "legicrf.h" + +#include "ticks.h" /* timers */ +#include "crc.h" /* legic crc-4 */ +#include "legic_prng.h" /* legic PRNG impl */ +#include "legic.h" /* legic_card_select_t struct */ + +static uint8_t* legic_mem; /* card memory, used for sim */ +static legic_card_select_t card;/* metadata of currently selected card */ +static crc_t legic_crc; + +//----------------------------------------------------------------------------- +// Frame timing and pseudorandom number generator +// +// The Prng is forwarded every 99.1us (TAG_BIT_PERIOD), except when the reader is +// transmitting. In that case the prng has to be forwarded every bit transmitted: +// - 31.3us for a 0 (RWD_TIME_0) +// - 99.1us for a 1 (RWD_TIME_1) +// +// The data dependent timing makes writing comprehensible code significantly +// harder. The current aproach forwards the prng data based if there is data on +// air and time based, using GetCountSspClk(), during computational and wait +// periodes. SSP Clock is clocked by the FPGA at 212 kHz (subcarrier frequency). +// +// To not have the necessity to calculate/guess exection time dependend timeouts +// tx_frame and rx_frame use a shared timestamp to coordinate tx and rx timeslots. +//----------------------------------------------------------------------------- + +static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */ + +#define TAG_FRAME_WAIT 70 /* 330us from READER frame end to TAG frame start */ +#define TAG_BIT_PERIOD 21 /* 99.1us */ + +#define RWD_TIME_PAUSE 4 /* 18.9us */ +#define RWD_TIME_1 21 /* RWD_TIME_PAUSE 18.9us off + 80.2us on = 99.1us */ +#define RWD_TIME_0 13 /* RWD_TIME_PAUSE 18.9us off + 42.4us on = 61.3us */ +#define RWD_CMD_TIMEOUT 40 /* 40 * 99.1us (arbitrary value) */ + +//----------------------------------------------------------------------------- +// Legic Simulator +//----------------------------------------------------------------------------- + +static int32_t init_card(uint8_t cardtype, legic_card_select_t *p_card) { + p_card->tagtype = cardtype; + + switch(p_card->tagtype) { + case 0: + p_card->cmdsize = 6; + p_card->addrsize = 5; + p_card->cardsize = 22; + break; + case 1: + p_card->cmdsize = 9; + p_card->addrsize = 8; + p_card->cardsize = 256; + break; + case 2: + p_card->cmdsize = 11; + p_card->addrsize = 10; + p_card->cardsize = 1024; + break; + default: + p_card->cmdsize = 0; + p_card->addrsize = 0; + p_card->cardsize = 0; + return 2; + } + return 0; +} + +static void init_tag() { + // configure FPGA + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR + | FPGA_HF_SIMULATOR_MODULATE_212K); + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + + // configure SSC with defaults + FpgaSetupSsc(); + + // first pull output to low to prevent glitches then re-claim GPIO_SSC_DOUT + LOW(GPIO_SSC_DOUT); + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + + // reserve a cardmem, meaning we can use the tracelog function in bigbuff easier. + legic_mem = BigBuf_get_EM_addr(); + + // init crc calculator + crc_init(&legic_crc, 4, 0x19 >> 1, 0x05, 0); + + // start 212kHz timer (running from SSP Clock) + StartCountSspClk(); +} + +//----------------------------------------------------------------------------- +// Command Line Interface +// +// Only this function is public / called from appmain.c +//----------------------------------------------------------------------------- + +void LegicRfSimulate(uint8_t cardtype) { + // configure ARM and FPGA + init_tag(); + + // verify command line input + if(init_card(cardtype, &card) != 0) { + DbpString("Unknown tagtype."); + goto OUT; + } + + LED_A_ON(); + DbpString("Starting Legic emulator, press button to end"); + while(!BUTTON_PRESS()) { + WDT_HIT(); + + // init coordination timestamp + last_frame_end = GetCountSspClk(); + + // reset prng + legic_prng_init(0); + } + +OUT: + DbpString("Stopped"); + switch_off(); + StopTicks(); +} diff --git a/armsrc/legicrfsim.h b/armsrc/legicrfsim.h new file mode 100644 index 000000000..c1c8a86e2 --- /dev/null +++ b/armsrc/legicrfsim.h @@ -0,0 +1,19 @@ +//----------------------------------------------------------------------------- +// (c) 2009 Henryk Plötz +// 2018 AntiCat +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// LEGIC RF emulation public interface +//----------------------------------------------------------------------------- + +#ifndef __LEGICRFSIM_H +#define __LEGICRFSIM_H + +#include "proxmark3.h" + +extern void LegicRfSimulate(uint8_t tagtype); + +#endif /* __LEGICRFSIM_H */ diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 559209afb..0b744c659 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -46,19 +46,15 @@ int usage_legic_rdmem(void){ int usage_legic_sim(void){ PrintAndLogEx(NORMAL, "Simulates a LEGIC Prime tag. MIM22, MIM256, MIM1024 types can be emulated"); PrintAndLogEx(NORMAL, "Use eload/esave to upload a dump into emulator memory"); - PrintAndLogEx(NORMAL, "Usage: hf legic sim [h] "); + PrintAndLogEx(NORMAL, "Usage: hf legic sim [h] "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, " : 0 = MIM22"); PrintAndLogEx(NORMAL, " : 1 = MIM256 (default)"); - PrintAndLogEx(NORMAL, " : 2 = MIM1024"); - PrintAndLogEx(NORMAL, " : phase drift"); - PrintAndLogEx(NORMAL, " : frame drift"); - PrintAndLogEx(NORMAL, " : reqresp drift"); + PrintAndLogEx(NORMAL, " : 2 = MIM1024"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf legic sim"); - PrintAndLogEx(NORMAL, " hf legic sim "); return 0; } int usage_legic_write(void){ @@ -504,12 +500,13 @@ int CmdLegicRdmem(const char *Cmd) { return status; } -// should say which tagtype -// should load a tag to device mem. -// int phase, int frame, int reqresp int CmdLegicRfSim(const char *Cmd) { - UsbCommand c = {CMD_SIMULATE_TAG_LEGIC_RF, {6,3,0}}; - sscanf(Cmd, " %" SCNi64 " %" SCNi64 " %" SCNi64 , &c.arg[0], &c.arg[1], &c.arg[2]); + + char cmdp = param_getchar(Cmd, 0); + if ( cmdp == 'H' || cmdp == 'h' ) return usage_legic_sim(); + + UsbCommand c = {CMD_SIMULATE_TAG_LEGIC_RF, {1}}; + sscanf(Cmd, " %" SCNi64, &c.arg[0]); clearCommandBuffer(); SendCommand(&c); return 0; From fe91a3f52f2f4fc68a8578a05d9a4ce0ce86da4d Mon Sep 17 00:00:00 2001 From: AntiCat Date: Wed, 5 Sep 2018 22:23:26 +0200 Subject: [PATCH 0009/1938] Legic: Implemented RX and TX for card simulation --- armsrc/legicrfsim.c | 192 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 192 insertions(+) diff --git a/armsrc/legicrfsim.c b/armsrc/legicrfsim.c index 791082d6b..862078bf7 100644 --- a/armsrc/legicrfsim.c +++ b/armsrc/legicrfsim.c @@ -40,12 +40,204 @@ static crc_t legic_crc; static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */ #define TAG_FRAME_WAIT 70 /* 330us from READER frame end to TAG frame start */ +#define TAG_ACK_WAIT 758 /* 3.57ms from READER frame end to TAG write ACK */ #define TAG_BIT_PERIOD 21 /* 99.1us */ #define RWD_TIME_PAUSE 4 /* 18.9us */ #define RWD_TIME_1 21 /* RWD_TIME_PAUSE 18.9us off + 80.2us on = 99.1us */ #define RWD_TIME_0 13 /* RWD_TIME_PAUSE 18.9us off + 42.4us on = 61.3us */ #define RWD_CMD_TIMEOUT 40 /* 40 * 99.1us (arbitrary value) */ +#define RWD_MIN_FRAME_LEN 6 /* Shortest frame is 6 bits */ +#define RWD_MAX_FRAME_LEN 23 /* Longest frame is 23 bits */ + +#define RWD_PULSE 1 /* Pulse is signaled with GPIO_SSC_DIN high */ +#define RWD_PAUSE 0 /* Pause is signaled with GPIO_SSC_DIN low */ + +//----------------------------------------------------------------------------- +// Demodulation +//----------------------------------------------------------------------------- + +// Returns true if a pulse/pause is received within timeout +static inline bool wait_for(bool value, const uint32_t timeout) { + while((bool)(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN) != value) { + if(GetCountSspClk() > timeout) { + return false; + } + } + return true; +} + +// Returns a demedulated bit or -1 on code violation +// +// rx_bit decodes bits using a thresholds. rx_bit has to be called by as soon as +// a frame starts (first pause is received). rx_bit checks for a pause up to +// 18.9us followed by a pulse of 80.2us or 42.4us: +// - A bit length <18.9us is a code violation +// - A bit length >80.2us is a 1 +// - A bit length <80.2us is a 0 +// - A bit length >148.6us is a code violation +static inline int8_t rx_bit() { + // backup ts for threshold calculation + uint32_t bit_start = last_frame_end; + + // wait for pause to end + if(!wait_for(RWD_PULSE, bit_start + RWD_TIME_1*3/2)) { + return -1; + } + + // wait for next pause + if(!wait_for(RWD_PAUSE, bit_start + RWD_TIME_1*3/2)) { + return -1; + } + + // update bit and frame end + last_frame_end = GetCountSspClk(); + + // check for code violation (bit to short) + if(last_frame_end - bit_start < RWD_TIME_PAUSE) { + return -1; + } + + // apply threshold (average of RWD_TIME_0 and ) + return (last_frame_end - bit_start > (RWD_TIME_0 + RWD_TIME_1) / 2); +} + +//----------------------------------------------------------------------------- +// Modulation +// +// LEGIC RF uses a very basic load modulation from card to reader: +// - Subcarrier on for a 1 +// - Subcarrier off for for a 0 +// +// The 212kHz subcarrier is generated by the FPGA as well as a mathcing ssp clk. +// Each bit is transfered in a 99.1us slot and the first timeslot starts 330us +// after the final 20us pause generated by the reader. +//----------------------------------------------------------------------------- + +// Transmits a bit +// +// Note: The Subcarrier is not disabled during bits to prevent glitches. This is +// not mandatory but results in a cleaner signal. tx_frame will disable +// the subcarrier when the frame is done. +static inline void tx_bit(bool bit) { + LED_C_ON(); + + if(bit) { + // modulate subcarrier + HIGH(GPIO_SSC_DOUT); + } else { + // do not modulate subcarrier + LOW(GPIO_SSC_DOUT); + } + + // wait for tx timeslot to end + last_frame_end += TAG_BIT_PERIOD; + while(GetCountSspClk() < last_frame_end) { }; + LED_C_OFF(); +} + +//----------------------------------------------------------------------------- +// Frame Handling +// +// The LEGIC RF protocol from reader to card does not include explicit frame +// start/stop information or length information. The tag detects end of frame +// trough an extended pulse (>99.1us) without a pause. +// In reverse direction (card to reader) the number of bites is well known +// and depends only the command received (IV, ACK, READ or WRITE). +//----------------------------------------------------------------------------- + +static void tx_frame(uint32_t frame, uint8_t len) { + // wait for next tx timeslot + last_frame_end += TAG_FRAME_WAIT; + legic_prng_forward(TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1); + while(GetCountSspClk() < last_frame_end) { }; + + // transmit frame, MSB first + for(uint8_t i = 0; i < len; ++i) { + bool bit = (frame >> i) & 0x01; + tx_bit(bit ^ legic_prng_get_bit()); + legic_prng_forward(1); + }; + + // disable subcarrier + LOW(GPIO_SSC_DOUT); +} + +static void tx_ack() { + // wait for ack timeslot + last_frame_end += TAG_ACK_WAIT; + legic_prng_forward(TAG_ACK_WAIT/TAG_BIT_PERIOD - 1); + while(GetCountSspClk() < last_frame_end) { }; + + // transmit ack (ack is not encrypted) + tx_bit(true); + legic_prng_forward(1); + + // disable subcarrier + LOW(GPIO_SSC_DOUT); +} + +// Returns a demedulated frame or -1 on code violation +// +// Since TX to RX delay is arbitrary rx_frame has to: +// - detect start of frame (first pause) +// - forward prng based on ts/TAG_BIT_PERIOD +// - receive the frame +// - detect end of frame (last pause) +static int32_t rx_frame(uint8_t *len) { + int32_t frame = 0; + + // add 2 SSP clock cycles (1 for tx and 1 for rx pipeline delay) + // those will be substracted at the end of the rx phase + last_frame_end -= 2; + + // wait for first pause (start of frame) + for(uint8_t i = 0; true; ++i) { + // increment prng every TAG_BIT_PERIOD + last_frame_end += TAG_BIT_PERIOD; + legic_prng_forward(1); + + // if start of frame was received exit delay loop + if(wait_for(RWD_PAUSE, last_frame_end)) { + last_frame_end = GetCountSspClk(); + break; + } + + // check for code violation + if(i > RWD_CMD_TIMEOUT) { + return -1; + } + } + + // receive frame + for(*len = 0; true; ++(*len)) { + // receive next bit + LED_B_ON(); + int8_t bit = rx_bit(); + LED_B_OFF(); + + // check for code violation and to short / long frame + if((bit < 0) && ((*len < RWD_MIN_FRAME_LEN) || (*len > RWD_MAX_FRAME_LEN))) { + return -1; + } + + // check for code violation caused by end of frame + if(bit < 0) { + break; + } + + // append bit + frame |= (bit ^ legic_prng_get_bit()) << (*len); + legic_prng_forward(1); + } + + // rx_bit sets coordination timestamp to start of pause, append pause duration + // and substract 2 SSP clock cycles (1 for rx and 1 for tx pipeline delay) to + // obtain exact end of frame. + last_frame_end += RWD_TIME_PAUSE - 2; + + return frame; +} //----------------------------------------------------------------------------- // Legic Simulator From 2c6c4e5bc64383dd511e70a24501f2b7e0bdb436 Mon Sep 17 00:00:00 2001 From: AntiCat Date: Wed, 5 Sep 2018 22:23:28 +0200 Subject: [PATCH 0010/1938] Legic: Implemented trace log --- armsrc/legicrfsim.c | 25 +++++++++++++++++++++++++ client/cmdtrace.c | 3 ++- 2 files changed, 27 insertions(+), 1 deletion(-) diff --git a/armsrc/legicrfsim.c b/armsrc/legicrfsim.c index 862078bf7..d73f09857 100644 --- a/armsrc/legicrfsim.c +++ b/armsrc/legicrfsim.c @@ -152,6 +152,9 @@ static void tx_frame(uint32_t frame, uint8_t len) { legic_prng_forward(TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1); while(GetCountSspClk() < last_frame_end) { }; + // backup ts for trace log + uint32_t last_frame_start = last_frame_end; + // transmit frame, MSB first for(uint8_t i = 0; i < len; ++i) { bool bit = (frame >> i) & 0x01; @@ -161,6 +164,10 @@ static void tx_frame(uint32_t frame, uint8_t len) { // disable subcarrier LOW(GPIO_SSC_DOUT); + + // log + uint8_t cmdbytes[] = {len, BYTEx(frame, 0), BYTEx(frame, 1)}; + LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false); } static void tx_ack() { @@ -169,12 +176,19 @@ static void tx_ack() { legic_prng_forward(TAG_ACK_WAIT/TAG_BIT_PERIOD - 1); while(GetCountSspClk() < last_frame_end) { }; + // backup ts for trace log + uint32_t last_frame_start = last_frame_end; + // transmit ack (ack is not encrypted) tx_bit(true); legic_prng_forward(1); // disable subcarrier LOW(GPIO_SSC_DOUT); + + // log + uint8_t cmdbytes[] = {1, 1}; + LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, false); } // Returns a demedulated frame or -1 on code violation @@ -209,6 +223,9 @@ static int32_t rx_frame(uint8_t *len) { } } + // backup ts for trace log + uint32_t last_frame_start = last_frame_end; + // receive frame for(*len = 0; true; ++(*len)) { // receive next bit @@ -236,6 +253,10 @@ static int32_t rx_frame(uint8_t *len) { // obtain exact end of frame. last_frame_end += RWD_TIME_PAUSE - 2; + // log + uint8_t cmdbytes[] = {*len, BYTEx(frame, 0), BYTEx(frame, 1), BYTEx(frame, 2)}; + LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, true); + return frame; } @@ -289,6 +310,10 @@ static void init_tag() { // reserve a cardmem, meaning we can use the tracelog function in bigbuff easier. legic_mem = BigBuf_get_EM_addr(); + // start trace + clear_trace(); + set_tracing(true); + // init crc calculator crc_init(&legic_crc, 4, 0x19 >> 1, 0x05, 0); diff --git a/client/cmdtrace.c b/client/cmdtrace.c index b30f7898a..537786bb4 100644 --- a/client/cmdtrace.c +++ b/client/cmdtrace.c @@ -521,7 +521,8 @@ int CmdTraceList(const char *Cmd) { if ( protocol == ICLASS ) PrintAndLogEx(NORMAL, "iClass - Timings are not as accurate"); if ( protocol == LEGIC ) - PrintAndLogEx(NORMAL, "LEGIC - Timings are in ticks (1us == 1.5ticks)"); + PrintAndLogEx(NORMAL, "LEGIC - Reader Mode: Timings are in ticks (1us == 1.5ticks)\n" + " Tag Mode: Timings are in sub carrier periods (1/212 kHz == 4.7us)"); if ( protocol == ISO_15693 ) PrintAndLogEx(NORMAL, "ISO15693 - Timings are not as accurate"); if ( protocol == FELICA ) From cd78b008156e4d1fe084c16757bd5b15036fd49f Mon Sep 17 00:00:00 2001 From: AntiCat Date: Wed, 5 Sep 2018 22:23:35 +0200 Subject: [PATCH 0011/1938] Legic: Implemented setup phase for card simulation --- armsrc/legicrf.c | 10 ++--- armsrc/legicrfsim.c | 89 +++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 90 insertions(+), 9 deletions(-) diff --git a/armsrc/legicrf.c b/armsrc/legicrf.c index 59cda1221..00d284926 100644 --- a/armsrc/legicrf.c +++ b/armsrc/legicrf.c @@ -302,8 +302,8 @@ static void init_reader(bool clear_mem) { // The setup consists of a three way handshake: // - Transmit initialisation vector 7 bits // - Receive card type 6 bits -// - Acknowledge frame 6 bits -static uint32_t setup_phase_reader(uint8_t iv) { +// - Transmit Acknowledge 6 bits +static uint32_t setup_phase(uint8_t iv) { // init coordination timestamp last_frame_end = GET_TICKS; @@ -398,7 +398,7 @@ void LegicRfInfo(void) { init_reader(false); // establish shared secret and detect card type - uint8_t card_type = setup_phase_reader(0x01); + uint8_t card_type = setup_phase(0x01); if(init_card(card_type, &card) != 0) { cmd_send(CMD_ACK, 0, 0, 0, 0, 0); goto OUT; @@ -435,7 +435,7 @@ void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) { init_reader(false); // establish shared secret and detect card type - uint8_t card_type = setup_phase_reader(iv); + uint8_t card_type = setup_phase(iv); if(init_card(card_type, &card) != 0) { cmd_send(CMD_ACK, 0, 0, 0, 0, 0); goto OUT; @@ -474,7 +474,7 @@ void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) { } // establish shared secret and detect card type - uint8_t card_type = setup_phase_reader(iv); + uint8_t card_type = setup_phase(iv); if(init_card(card_type, &card) != 0) { cmd_send(CMD_ACK, 0, 0, 0, 0, 0); goto OUT; diff --git a/armsrc/legicrfsim.c b/armsrc/legicrfsim.c index d73f09857..195aa2738 100644 --- a/armsrc/legicrfsim.c +++ b/armsrc/legicrfsim.c @@ -321,6 +321,78 @@ static void init_tag() { StartCountSspClk(); } +// Setup reader to card connection +// +// The setup consists of a three way handshake: +// - Receive initialisation vector 7 bits +// - Transmit card type 6 bits +// - Receive Acknowledge 6 bits +static int32_t setup_phase(legic_card_select_t *p_card) { + uint8_t len = 0; + + // init coordination timestamp + last_frame_end = GetCountSspClk(); + + // reset prng + legic_prng_init(0); + + // wait for iv + int32_t iv = rx_frame(&len); + if((len != 7) || (iv < 0)) { + return -1; + } + + // configure prng + legic_prng_init(iv); + + // reply with card type + switch(p_card->tagtype) { + case 0: + tx_frame(0x0D, 6); + break; + case 1: + tx_frame(0x1D, 6); + break; + case 2: + tx_frame(0x3D, 6); + break; + } + + // wait for ack + int32_t ack = rx_frame(&len); + if((len != 6) || (ack < 0)) { + return -1; + } + + // validate data + switch(p_card->tagtype) { + case 0: + if(ack != 0x19) return -1; + break; + case 1: + if(ack != 0x39) return -1; + break; + case 2: + if(ack != 0x39) return -1; + break; + } + + // During rx the prng is clocked using the variable reader period. + // Since rx_frame detects end of frame by detecting a code violation, + // the prng is off by one bit period after each rx phase. Hence, tx + // code advances the prng by (TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1). + // This is not possible for back to back rx, so this quirk reduces + // the gap by one period. + last_frame_end += TAG_BIT_PERIOD; + + return 0; +} + +// TODO Commands are left as an exercise to the reader +static int32_t connected_phase(legic_card_select_t *p_card) { + return 0; +} + //----------------------------------------------------------------------------- // Command Line Interface // @@ -342,11 +414,20 @@ void LegicRfSimulate(uint8_t cardtype) { while(!BUTTON_PRESS()) { WDT_HIT(); - // init coordination timestamp - last_frame_end = GetCountSspClk(); + // wait for carrier, restart after timeout + if(!wait_for(RWD_PULSE, GetCountSspClk() + TAG_BIT_PERIOD)) { + continue; + } - // reset prng - legic_prng_init(0); + // wait for connection, restart on error + if(setup_phase(&card)) { + continue; + } + + // conection is established, process commands until one fails + while(!connected_phase(&card)) { + WDT_HIT(); + } } OUT: From 2981fe7ce8db62eaf836daf2136c614105065839 Mon Sep 17 00:00:00 2001 From: AntiCat Date: Wed, 5 Sep 2018 22:23:37 +0200 Subject: [PATCH 0012/1938] Legic: Implemented read command for card simulation --- armsrc/legicrfsim.c | 28 ++++++++++++++++++++++++++-- 1 file changed, 26 insertions(+), 2 deletions(-) diff --git a/armsrc/legicrfsim.c b/armsrc/legicrfsim.c index 195aa2738..641907741 100644 --- a/armsrc/legicrfsim.c +++ b/armsrc/legicrfsim.c @@ -388,9 +388,33 @@ static int32_t setup_phase(legic_card_select_t *p_card) { return 0; } -// TODO Commands are left as an exercise to the reader +static uint8_t calc_crc4(uint16_t cmd, uint8_t cmd_sz, uint8_t value) { + crc_clear(&legic_crc); + crc_update(&legic_crc, (value << cmd_sz) | cmd, 8 + cmd_sz); + return crc_finish(&legic_crc); +} + static int32_t connected_phase(legic_card_select_t *p_card) { - return 0; + uint8_t len = 0; + + // wait for command + int32_t cmd = rx_frame(&len); + if(cmd < 0) { + return -1; + } + + // check if command is LEGIC_READ + if(len == p_card->cmdsize) { + // prepare data + uint8_t byte = legic_mem[cmd >> 1]; + uint8_t crc = calc_crc4(cmd, p_card->cmdsize, byte); + + // transmit data + tx_frame((crc << 8) | byte, 12); + return 0; + } + + return -1; } //----------------------------------------------------------------------------- From e1fa1e659aef8d4537748db2e5f0f0182ab91168 Mon Sep 17 00:00:00 2001 From: AntiCat Date: Wed, 5 Sep 2018 22:23:44 +0200 Subject: [PATCH 0013/1938] Legic: Implemented write command for card simulation --- armsrc/legicrfsim.c | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/armsrc/legicrfsim.c b/armsrc/legicrfsim.c index 641907741..71c747115 100644 --- a/armsrc/legicrfsim.c +++ b/armsrc/legicrfsim.c @@ -411,6 +411,31 @@ static int32_t connected_phase(legic_card_select_t *p_card) { // transmit data tx_frame((crc << 8) | byte, 12); + + return 0; + } + + // check if command is LEGIC_WRITE + if(len == p_card->cmdsize + 8 + 4) { + // decode data + uint16_t mask = (1 << p_card->addrsize) - 1; + uint16_t addr = (cmd >> 1) & mask; + uint8_t byte = (cmd >> p_card->cmdsize) & 0xff; + uint8_t crc = (cmd >> (p_card->cmdsize + 8)) & 0xf; + + // check received against calculated crc + uint8_t calc_crc = calc_crc4(addr << 1, p_card->cmdsize, byte); + if(calc_crc != crc) { + Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc); + return -1; + } + + // store data + legic_mem[addr] = byte; + + // transmit ack + tx_ack(); + return 0; } From 368fe11df08eeb3a881428c984399eebb4aa106d Mon Sep 17 00:00:00 2001 From: "Colin J. Brigato" Date: Thu, 6 Sep 2018 05:15:52 +0200 Subject: [PATCH 0014/1938] Second Pass rewrite of flashmem. added command 'mem spibaud' to switch between 24/48Mhz operation. All is more consistant, less messy. All logic rewrittent avoiding multiple flashinit/flashstop. busywait is now at it's lowest possible. Beware : 48Mhz is VERY buggy cause of sillicon bug (see source for more info), and doesn't give much more than 24Mhz for now since we doubled nearly every operation speed here. --- armsrc/Standalone/hf_colin.c | 74 ++++++++-------- armsrc/Standalone/hf_colin.h | 1 + armsrc/appmain.c | 130 +++++++++++++--------------- armsrc/flashmem.c | 163 +++++++++++++++++------------------ armsrc/flashmem.h | 22 ++++- 5 files changed, 201 insertions(+), 189 deletions(-) diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index 3a34396eb..7259fcab3 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -153,10 +153,11 @@ void SpinUp(uint32_t speed) LED_D_OFF(); } -void TestFlashmemSpeed(size_t buffersize, bool fastmode) +void TestFlashmemSpeed(size_t buffersize, uint32_t spibaudrate) { - DbprintfEx(FLAG_NOLOG, "%s---+----[ %s %s[%dKB] %s]", _GREEN_, _WHITE_, _YELLOW_, buffersize / 1024, _WHITE_); + FLASHMEM_SPIBAUDRATE = spibaudrate*1000000; + DbprintfEx(FLAG_NOLOG, "%s---+----[ %s %s[%dKB] %s] (%d)", _GREEN_, _WHITE_, _YELLOW_, buffersize / 1024, _WHITE_, FLASHMEM_SPIBAUDRATE); uint16_t t = 0; LED_B_ON(); @@ -166,10 +167,10 @@ void TestFlashmemSpeed(size_t buffersize, bool fastmode) uint32_t startidx = 0; uint32_t numofbytes = 0x3FFFF; - if (!FlashInit(fastmode)) { + if (!FlashInit()) { return; } - Flash_CheckBusy(BUSY_TIMEOUT); + //Flash_CheckBusy(BUSY_TIMEOUT); //Flash_ReadStat1(); @@ -183,14 +184,7 @@ void TestFlashmemSpeed(size_t buffersize, bool fastmode) //isok = Flash_ReadData(startidx + i, mem, len); //uint32_t iend_time; //uint32_t istart_time = iend_time = GetTickCount(); - if (fastmode) - { - isok = Flash_FastReadDataCont(startidx + i, mem, len); - } - else - { - isok = Flash_ReadDataCont(startidx + i, mem, len); - } + isok = Flash_ReadDataCont(startidx + i, mem, len); //iend_time = GetTickCount(); //DbprintfEx(FLAG_RAWPRINT, "%s%dms%s>", _YELLOW_, iend_time - istart_time, _WHITE_); //cjSetCursLeft(); @@ -199,7 +193,7 @@ void TestFlashmemSpeed(size_t buffersize, bool fastmode) Dbprintf("[FAIL] reading flash memory failed :: | bytes between %d - %d", i, len); return; } - //isok = cmd_send(CMD_DOWNLOADED_FLASHMEM, i, len, 0, mem, len); + //isok = cmd_send(CMD_FLASHMEM_DOWNLOADED, i, len, 0, mem, len); //if (!isok) // Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); t++; @@ -213,6 +207,29 @@ void TestFlashmemSpeed(size_t buffersize, bool fastmode) FlashStop(); } +void TestFlashmemRoutine() +{ + DbprintfEx(FLAG_NOLOG, "%s>>%s Will Now Test dumping Full flash [256Kb] (2Mbits)through Bigbuf buffers\n", _GREEN_, _WHITE_); + MF_DBGLEVEL = MF_DBG_NONE; + //DbprintfEx(FLAG_NOLOG, "---------\n%s[A]%s Using NORMAL Reads @Max (24Mhz=MCK/2)\n--------", _GREEN_, _WHITE_); + TestFlashmemSpeed(32768,24); + TestFlashmemSpeed(16384 + 4096 + 4096,24); + TestFlashmemSpeed(16384,24); + TestFlashmemSpeed(4096,24); + TestFlashmemSpeed(1024,24); + //SpinDelay(1000); + //WDT_HIT(); + //DbprintfEx(FLAG_NOLOG, "--------\n%s[B]%s Using FAST Reads @Max (48Mhz=MCK=CPUClock/2=MAXSPI)\n--------", _GREEN_, _WHITE_); + TestFlashmemSpeed(32768,48); + TestFlashmemSpeed(16384 + 4096 + 4096,48); + TestFlashmemSpeed(16384,48); + TestFlashmemSpeed(4096,48); + TestFlashmemSpeed(1024,48); + //SpinDelay(1000); + //WDT_HIT(); + return; +} + void ReadLastTagFromFlash() { @@ -231,11 +248,12 @@ void ReadLastTagFromFlash() size_t size = len; uint8_t *mem = BigBuf_malloc(size); - //if (!FlashFastReadInit()){ - if (!FlashInit(0)) + if (!FlashInit()) { return; } + Flash_CheckBusy(BUSY_TIMEOUT); + //Flash_ReadStat1(); uint32_t end_time; @@ -256,8 +274,8 @@ void ReadLastTagFromFlash() { DbprintfEx(FLAG_NOLOG, "FlashMem reading failed | %d | %d", len, isok); cjSetCursLeft(); - SpinOff(100); FlashStop(); + SpinOff(100); return; } } @@ -292,11 +310,12 @@ void WriteTagToFlash(uint8_t index, size_t size) emlGetMem(data, 0, (size * 64)/1024); //if (!FlashFastReadInit()){ - if (!FlashInit(0)) + if (!FlashInit()) { return; } + Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); Flash_Erase4k(0,0); Flash_CheckBusy(BUSY_TIMEOUT); @@ -492,25 +511,8 @@ ACCBITS : 796788[00]+VALUE SpinDown(50); #if 0 - DbprintfEx(FLAG_NOLOG, "%s>>%s Will Now Test dumping Full flash [256Kb] (2Mbits)through Bigbuf buffers\n", _GREEN_, _WHITE_); - MF_DBGLEVEL = MF_DBG_NONE; - DbprintfEx(FLAG_NOLOG, "---------\n%s[A]%s Using NORMAL Reads @Max (24Mhz=MCK/2)\n--------", _GREEN_, _WHITE_); - TestFlashmemSpeed(32768,0); - TestFlashmemSpeed(16384 + 4096 + 4096,0); - TestFlashmemSpeed(16384,0); - TestFlashmemSpeed(4096,0); - TestFlashmemSpeed(1024,0); - SpinDelay(1000); - WDT_HIT(); - DbprintfEx(FLAG_NOLOG, "--------\n%s[B]%s Using FAST Reads @Max (48Mhz=MCK=CPUClock/2=MAXSPI)\n--------", _GREEN_, _WHITE_); - TestFlashmemSpeed(32768,1); - TestFlashmemSpeed(16384 + 4096 + 4096,1); - TestFlashmemSpeed(16384,1); - TestFlashmemSpeed(4096,1); - TestFlashmemSpeed(1024,1); - SpinDelay(1000); - WDT_HIT(); - return; +TestFlashmemRoutine(); +return; #endif failtag: diff --git a/armsrc/Standalone/hf_colin.h b/armsrc/Standalone/hf_colin.h index 29f8f52e6..dd3da6322 100644 --- a/armsrc/Standalone/hf_colin.h +++ b/armsrc/Standalone/hf_colin.h @@ -52,6 +52,7 @@ void WriteTagToFlash(uint8_t index, size_t size); const char clearTerm[8] = {0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x32, 0x4a, '\0'}; +void TestFlashmemSpeed(size_t buffersize, uint32_t spibaudrate); #define LOGO logo_kigiv diff --git a/armsrc/appmain.c b/armsrc/appmain.c index b0538383e..03502f132 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -33,6 +33,10 @@ #include "i2c.h" #endif +#ifdef WITH_FPC +#include "usart.h" +#endif + //============================================================================= // A buffer where we can queue things up to be sent through the FPGA, for // any purpose (fake tag, as reader, whatever). We go MSB first, since that @@ -74,24 +78,26 @@ void PrintToSendBuffer(void) { } void print_result(char *name, uint8_t *buf, size_t len) { - uint8_t *p = buf; - if ( len % 16 == 0 ) { - for(; p-buf < len; p += 16) - Dbprintf("[%s:%d/%d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + uint8_t *p = buf; + uint16_t tmp = len & 0xFFF0; + + for(; p-buf < tmp; p += 16) { + Dbprintf("[%s: %02d/%02d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", name, p-buf, len, p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15] ); } - else { - for(; p-buf < len; p += 8) - Dbprintf("[%s:%d/%d] %02x %02x %02x %02x %02x %02x %02x %02x", - name, - p-buf, - len, - p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7]); + if (len % 16 != 0) { + char s[46] = {0}; + char *sp = s; + for (; p-buf < len; p++ ) { + sprintf(sp, "%02x ", p[0] ); + sp += 3; + } + Dbprintf("[%s: %02d/%02d] %s", name, p-buf, len, s); } } @@ -101,7 +107,7 @@ void print_result(char *name, uint8_t *buf, size_t len) { void DbpStringEx(char *str, uint32_t cmd) { #if DEBUG - byte_t len = strlen(str); + uint8_t len = strlen(str); cmd_send(CMD_DEBUG_PRINT_STRING, len, cmd, 0, (byte_t*)str, len); #endif } @@ -113,7 +119,7 @@ void DbpString(char *str) { } #if 0 -void DbpIntegers(inst x1, int x2, int x3) { +void DbpIntegers(int x1, int x2, int x3) { cmd_send(CMD_DEBUG_PRINT_INTEGERS,x1,x2,x3,0,0); } #endif @@ -442,6 +448,7 @@ void printStandAloneModes(void) { //DbpString("Running "); //Dbprintf(" Is Device attached to USB| %s", USB_ATTACHED() ? "Yes" : "No"); + //Dbprintf(" Is Device attached to FPC| %s", 0 ? "Yes" : "No"); //Dbprintf(" Is USB_reconnect value | %d", GetUSBreconnect() ); //Dbprintf(" Is USB_configured value | %d", GetUSBconfigured() ); @@ -1070,6 +1077,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { #endif case CMD_BUFF_CLEAR: BigBuf_Clear(); + BigBuf_free(); break; case CMD_MEASURE_ANTENNA_TUNING: @@ -1106,7 +1114,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { len = MIN( (numofbytes - i), USB_CMD_DATA_SIZE); isok = cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, i, len, BigBuf_get_traceLen(), mem + startidx + i, len); if (!isok) - Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); + Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len); } // Trigger a finish downloading signal with an ACK frame // iceman, when did sending samplingconfig array got attached here?!? @@ -1163,37 +1171,30 @@ void UsbPacketReceived(uint8_t *packet, int len) { ReadMem(c->arg[0]); break; #ifdef WITH_FLASH - case CMD_READ_FLASH_MEM: { - + case CMD_FLASHMEM_SET_SPIBAUDRATE: + FlashmemSetSpiBaudrate(c->arg[0]); + break; + case CMD_FLASHMEM_READ: { LED_B_ON(); uint16_t isok = 0; uint32_t startidx = c->arg[0]; uint16_t len = c->arg[1]; - uint8_t fast = c->arg[2]; + //uint8_t fast = c->arg[2]; - Dbprintf("FlashMem read | %d - %d", startidx, len); + Dbprintf("FlashMem read | %d - %d | ", startidx, len); size_t size = MIN(USB_CMD_DATA_SIZE, len); uint8_t *mem = BigBuf_malloc(size); - - if (fast) { - FlashInit(1); - //FlashInit(); - Flash_CheckBusy(BUSY_TIMEOUT); - } + FlashInit(); + //Flash_CheckBusy(BUSY_TIMEOUT); + for(size_t i = 0; i < len; i += size) { len = MIN((len - i), size); - Dbprintf("FlashMem reading | %d | %d | %d", startidx + i, i, len); - - if (!fast){ - isok = Flash_ReadData(startidx + i, mem, len); - } - if (fast){ - isok = Flash_FastReadDataCont(startidx + i, mem, len); - } + Dbprintf("FlashMem reading | %d | %d | %d |", startidx + i, i, len); + isok = Flash_ReadDataCont(startidx + i, mem, len); if ( isok == len ) { print_result("Chunk: ", mem, len); } else { @@ -1201,13 +1202,11 @@ void UsbPacketReceived(uint8_t *packet, int len) { break; } } - if (fast){ - FlashStop(); - } + FlashStop(); LED_B_OFF(); break; } - case CMD_WRITE_FLASH_MEM: { + case CMD_FLASHMEM_WRITE: { LED_B_ON(); uint8_t isok = 0; uint16_t res = 0; @@ -1217,6 +1216,14 @@ void UsbPacketReceived(uint8_t *packet, int len) { uint32_t tmp = startidx + len; + if (!FlashInit()) + { + break; + } + + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); + // inside 256b page? if ( (tmp & 0xFF) != 0) { @@ -1230,27 +1237,28 @@ void UsbPacketReceived(uint8_t *packet, int len) { uint8_t first_len = (~startidx & 0xFF)+1; // first mem page - res = Flash_WriteData(startidx, data, first_len); + res = Flash_WriteDataCont(startidx, data, first_len); // second mem page - res = Flash_WriteData(startidx + first_len, data + first_len, len - first_len); + res = Flash_WriteDataCont(startidx + first_len, data + first_len, len - first_len); isok = (res == (len - first_len)) ? 1 : 0; } else { - res = Flash_WriteData(startidx, data, len); + res = Flash_WriteDataCont(startidx, data, len); isok = (res == len) ? 1 : 0; } } else { - res = Flash_WriteData(startidx, data, len); + res = Flash_WriteDataCont(startidx, data, len); isok = (res == len) ? 1 : 0; } + FlashStop(); cmd_send(CMD_ACK, isok, 0, 0, 0, 0); LED_B_OFF(); break; } - case CMD_WIPE_FLASH_MEM: { + case CMD_FLASHMEM_WIPE: { LED_B_ON(); uint8_t page = c->arg[0]; uint8_t initalwipe = c->arg[1]; @@ -1268,7 +1276,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { LED_B_OFF(); break; } - case CMD_DOWNLOAND_FLASH_MEM: { + case CMD_FLASHMEM_DOWNLOAD: { LED_B_ON(); uint8_t *mem = BigBuf_malloc(USB_CMD_DATA_SIZE); @@ -1276,48 +1284,39 @@ void UsbPacketReceived(uint8_t *packet, int len) { size_t len = 0; uint32_t startidx = c->arg[0]; uint32_t numofbytes = c->arg[1]; - uint8_t fast = c->arg[2]; + //uint8_t fast = c->arg[2]; // arg0 = startindex // arg1 = length bytes to transfer // arg2 = RFU + FlashInit(); - if (fast) { - FlashInit(1); - //FlashInit(); - Flash_CheckBusy(BUSY_TIMEOUT); - } for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); - if (!fast){ - isok = Flash_ReadData(startidx + i, mem, len); - } - if (fast){ - isok = Flash_FastReadDataCont(startidx + i, mem, len); - } + + isok = Flash_ReadDataCont(startidx + i, mem, len); if (!isok ) Dbprintf("reading flash memory failed :: | bytes between %d - %d", i, len); - - isok = cmd_send(CMD_DOWNLOADED_FLASHMEM, i, len, 0, mem, len); + + isok = cmd_send(CMD_FLASHMEM_DOWNLOADED, i, len, 0, mem, len); if (!isok) Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); } - if (fast){ FlashStop(); - } + cmd_send(CMD_ACK, 1, 0, 0, 0, 0); LED_B_OFF(); break; } - case CMD_INFO_FLASH_MEM: { + case CMD_FLASHMEM_INFO: { LED_B_ON(); rdv40_validation_t *info = (rdv40_validation_t*)BigBuf_malloc( sizeof(rdv40_validation_t) ); bool isok = Flash_ReadData(FLASH_MEM_SIGNATURE_OFFSET, info->signature, FLASH_MEM_SIGNATURE_LEN); - if (FlashInit(0)) { + if (FlashInit()) { Flash_UniqueID( info->flashid); FlashStop(); } @@ -1437,15 +1436,15 @@ void __attribute__((noreturn)) AppMain(void) { StartTickCount(); #ifdef WITH_LCD -// LCDInit(); + LCDInit(); #endif #ifdef WITH_SMARTCARD -// I2C_init(); + I2C_init(); #endif #ifdef WITH_FPC -// usart_init(); + usart_init(); #endif // This is made as late as possible to ensure enumeration without timeout @@ -1487,11 +1486,6 @@ void __attribute__((noreturn)) AppMain(void) { #if defined (WITH_ISO14443a) && ( defined (WITH_HF_YOUNG) || defined(WITH_HF_COLIN) || defined(WITH_HF_MATTYRUN) ) RunMod(); #endif - - // when here, we are no longer in standalone mode. - // reseting the variables which keeps track of usb re-attached/configured - //SetUSBreconnect(0); - //SetUSBconfigured(0); } } } diff --git a/armsrc/flashmem.c b/armsrc/flashmem.c index b5786fbe9..f173b66b4 100644 --- a/armsrc/flashmem.c +++ b/armsrc/flashmem.c @@ -1,11 +1,6 @@ #include "flashmem.h" -#define MCK 48000000 -//#define FLASH_BAUD 24000000 -//define FLASH_BAUD 33000000 -#define FLASH_BAUD MCK/2 -#define FLASH_FASTBAUD MCK /* here: use NCPS2 @ PA10: */ #define SPI_CSR_NUM 2 @@ -18,10 +13,17 @@ #define SPI_DLYBCT(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 32000) << 24) +uint32_t FLASHMEM_SPIBAUDRATE = FLASH_BAUD; + + +void FlashmemSetSpiBaudrate(uint32_t baudrate){ + FLASHMEM_SPIBAUDRATE = baudrate; + Dbprintf("Spi Baudrate : %dMhz", FLASHMEM_SPIBAUDRATE/1000000); +} // initialize -bool FlashInit(bool fast) { - FlashSetup(fast); +bool FlashInit() { + FlashSetup(FLASHMEM_SPIBAUDRATE); StartTicks(); @@ -33,7 +35,7 @@ bool FlashInit(bool fast) { return true; } -void FlashSetup(bool fast){ +void FlashSetup(uint32_t baudrate){ //WDT_DISABLE AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS; @@ -79,13 +81,12 @@ void FlashSetup(bool fast){ AT91C_SPI_PS_FIXED | // Fixed Peripheral Select AT91C_SPI_MSTR; // Master Mode - int baudrate = FLASH_BAUD; uint8_t csaat = 1; - int dlybct = 0; - if (fast) { + uint32_t dlybct = 0; + if (baudrate > FLASH_MINFAST) { baudrate = FLASH_FASTBAUD; //csaat = 0; - dlybct = MCK/32; + dlybct = 1500; } AT91C_BASE_SPI->SPI_CSR[2] = @@ -100,28 +101,28 @@ void FlashSetup(bool fast){ // transferred in the shifter. This can imply for example, that the second data is sent twice. // COLIN :: For now we STILL use CSAAT=1 to avoid having to (de)assert NPCS manually via PIO lines and we deal with delay ( csaat << 3) | -/* Spi modes: -Mode CPOL CPHA NCPHA -0 0 0 1 clock normally low read on rising edge -1 0 1 0 clock normally low read on falling edge -2 1 0 1 clock normally high read on falling edge -3 1 1 0 clock normally high read on rising edge -However, page 512 of the AT91SAM7Sx datasheet say "Note that in SPI -master mode the ATSAM7S512/256/128/64/321/32 does not sample the data -(MISO) on the opposite edge where data clocks out (MOSI) but the same -edge is used as shown in Figure 36-3 and Figure 36-4." Figure 36-3 -shows that CPOL=NCPHA=0 or CPOL=NCPHA=1 samples on the rising edge and -that the data changes sometime after the rising edge (about 2 ns). To -be consistent with normal SPI operation, it is probably safe to say -that the data changes on the falling edge and should be sampled on the -rising edge. Therefore, it appears that NCPHA should be treated the -same as CPHA. Thus: -Mode CPOL CPHA NCPHA -0 0 0 0 clock normally low read on rising edge -1 0 1 1 clock normally low read on falling edge -2 1 0 0 clock normally high read on falling edge -3 1 1 1 clock normally high read on rising edge -*/ + /* Spi modes: + Mode CPOL CPHA NCPHA + 0 0 0 1 clock normally low read on rising edge + 1 0 1 0 clock normally low read on falling edge + 2 1 0 1 clock normally high read on falling edge + 3 1 1 0 clock normally high read on rising edge + However, page 512 of the AT91SAM7Sx datasheet say "Note that in SPI + master mode the ATSAM7S512/256/128/64/321/32 does not sample the data + (MISO) on the opposite edge where data clocks out (MOSI) but the same + edge is used as shown in Figure 36-3 and Figure 36-4." Figure 36-3 + shows that CPOL=NCPHA=0 or CPOL=NCPHA=1 samples on the rising edge and + that the data changes sometime after the rising edge (about 2 ns). To + be consistent with normal SPI operation, it is probably safe to say + that the data changes on the falling edge and should be sampled on the + rising edge. Therefore, it appears that NCPHA should be treated the + same as CPHA. Thus: + Mode CPOL CPHA NCPHA + 0 0 0 0 clock normally low read on rising edge + 1 0 1 1 clock normally low read on falling edge + 2 1 0 0 clock normally high read on falling edge + 3 1 1 1 clock normally high read on rising edge + */ ( 0 << 1) | // Clock Phase data captured on leading edge, changes on following edge ( 0 << 0); // Clock Polarity inactive state is logic 0 @@ -161,10 +162,10 @@ uint16_t FlashSendByte(uint32_t data) { // send the data AT91C_BASE_SPI->SPI_TDR = data; - while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){}; + //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){}; // wait recive transfer is complete - while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0); + while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0){}; // reading incoming data return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF); @@ -187,6 +188,8 @@ bool Flash_CheckBusy(uint32_t timeout) StartCountUS(); uint32_t _time = GetCountUS(); + if ( MF_DBGLEVEL > 3 ) Dbprintf("Checkbusy in..."); + do { if (!(Flash_ReadStat1() & BUSY)) @@ -249,37 +252,61 @@ void Flash_UniqueID(uint8_t *uid) { uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) { - if (!FlashInit(0)) return 0; + if (!FlashInit()) return 0; // length should never be zero if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0; - FlashSendByte(READDATA); - FlashSendByte((address >> 16) & 0xFF); - FlashSendByte((address >> 8) & 0xFF); - FlashSendByte((address >> 0) & 0xFF); + + uint8_t cmd = READDATA; + + if(FASTFLASH) { + cmd = FASTREAD; + } + + FlashSendByte(cmd); + Flash_TransferAdresse(address); + + if (FASTFLASH){ + FlashSendByte(DUMMYBYTE); + } uint16_t i = 0; for (; i < (len - 1); i++) out[i] = FlashSendByte(0xFF); out[i] = FlashSendLastByte(0xFF); - + + FlashStop(); return len; } +void Flash_TransferAdresse(uint32_t address){ + FlashSendByte((address >> 16) & 0xFF); + FlashSendByte((address >> 8) & 0xFF); + FlashSendByte((address >> 0) & 0xFF); +} + /* This ensure we can ReadData without having to cycle through initialization everytime */ uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) { // length should never be zero if (!len) return 0; + + uint8_t cmd = READDATA; - FlashSendByte(READDATA); - FlashSendByte((address >> 16) & 0xFF); - FlashSendByte((address >> 8) & 0xFF); - FlashSendByte((address >> 0) & 0xFF); + if(FASTFLASH) { + cmd = FASTREAD; + } + FlashSendByte(cmd); + Flash_TransferAdresse(address); + + if (FASTFLASH){ + FlashSendByte(DUMMYBYTE); + } + uint16_t i = 0; for (; i < (len - 1); i++) out[i] = FlashSendByte(0xFF); @@ -289,32 +316,6 @@ uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) { return len; } -uint16_t Flash_FastReadDataCont(uint32_t address, uint8_t *out, uint16_t len) { - - // length should never be zero - if (!len) return 0; - - //if (Flash_CheckBusy(BUSY_TIMEOUT)) - //{return 0;} - - FlashSendByte(FASTREAD); - FlashSendByte((address >> 16) & 0xFF); - FlashSendByte((address >> 8) & 0xFF); - FlashSendByte((address >> 0) & 0xFF); - FlashSendByte(0xFF); - //Flash_CheckBusy(BUSY_TIMEOUT); - - - uint16_t i = 0; - for (; i < (len - 1); i++) - out[i] = FlashSendByte(0xFF); - - out[i] = FlashSendLastByte(0xFF); - - return len; -} - - //////////////////////////////////////// @@ -338,13 +339,12 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { return 0; } - if (!FlashInit(0)) { + if (!FlashInit()) { if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); return 0; } Flash_CheckBusy(BUSY_TIMEOUT); - //Flash_ReadStat1(); Flash_WriteEnable(); @@ -382,10 +382,8 @@ uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) { } - //Flash_CheckBusy(100); - //SpinDelay(1); + Flash_CheckBusy(BUSY_TIMEOUT); - //Flash_ReadStat1(); Flash_WriteEnable(); FlashSendByte(PAGEPROG); @@ -403,7 +401,7 @@ uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) { } bool Flash_WipeMemoryPage(uint8_t page) { - if (!FlashInit(0)) { + if (!FlashInit()) { if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); return false; } @@ -417,7 +415,7 @@ bool Flash_WipeMemoryPage(uint8_t page) { } // Wipes flash memory completely, fills with 0xFF bool Flash_WipeMemory() { - if (!FlashInit(0)) { + if (!FlashInit()) { if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); return false; } @@ -498,12 +496,13 @@ void Flash_EraseChip(void) { void Flashmem_print_status(void) { DbpString("Flash memory"); + Dbprintf(" Baudrate................%dMHz",FLASHMEM_SPIBAUDRATE/1000000); - if (!FlashInit(0)) { - DbpString(" init....................FAIL"); + if (!FlashInit()) { + DbpString(" Init....................FAIL"); return; } - DbpString(" init....................OK"); + DbpString(" Init....................OK"); uint8_t dev_id = Flash_ReadID(); switch (dev_id) { diff --git a/armsrc/flashmem.h b/armsrc/flashmem.h index 3563eb41d..ae10ea388 100644 --- a/armsrc/flashmem.h +++ b/armsrc/flashmem.h @@ -102,15 +102,30 @@ #define MAX_SECTORS 16 + + +#define MCK 48000000 +//#define FLASH_BAUD 24000000 +#define FLASH_MINFAST 24000000 //33000000 +#define FLASH_BAUD MCK/2 +#define FLASH_FASTBAUD MCK +#define FLASH_MINBAUD FLASH_FASTBAUD + +#define FASTFLASH (FLASHMEM_SPIBAUDRATE > FLASH_MINFAST) + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// extern void Dbprintf(const char *fmt, ...); -bool FlashInit(bool fast); -void FlashSetup(bool fast); + +void FlashmemSetSpiBaudrate(uint32_t baudrate); +bool FlashInit(); +void FlashSetup(uint32_t baudrate); void FlashStop(void); bool Flash_WaitIdle(void); uint8_t Flash_ReadStat1(void); uint8_t Flash_ReadStat2(void); uint16_t FlashSendByte(uint32_t data); +void Flash_TransferAdresse(uint32_t address); bool Flash_CheckBusy(uint32_t timeout); @@ -128,10 +143,11 @@ uint8_t Flash_ReadID(void); uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len); uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len); -uint16_t Flash_FastReadDataCont(uint32_t address, uint8_t *out, uint16_t len); uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len); uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len); void Flashmem_print_status(void); + + #endif \ No newline at end of file From c74dbb63b8e9768edad04c40b09554c8e1cb32b9 Mon Sep 17 00:00:00 2001 From: "Colin J. Brigato" Date: Thu, 6 Sep 2018 05:24:50 +0200 Subject: [PATCH 0015/1938] Pass 2; commit 2; --- client/cmdflashmem.c | 62 +++++++++++++++++++++++++----------- client/cmdmain.c | 4 +-- client/hid-flasher/usb_cmd.h | 12 +++---- include/common.h | 3 ++ include/usb_cmd.h | 16 ++++++---- tools/mkversion.pl | 14 ++++++-- 6 files changed, 77 insertions(+), 34 deletions(-) diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index 5f83f9263..43230218f 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -12,13 +12,36 @@ #include "rsa.h" #include "sha1.h" +#define MCK 48000000 +//#define FLASH_BAUD 24000000 +#define FLASH_MINFAST 24000000 //33000000 +#define FLASH_BAUD MCK/2 +#define FLASH_FASTBAUD MCK +#define FLASH_MINBAUD FLASH_FASTBAUD + +#define FASTFLASH (FLASHMEM_SPIBAUDRATE > FLASH_MINFAST) + static int CmdHelp(const char *Cmd); + +int usage_flashmem_spibaud(void){ + PrintAndLogEx(NORMAL, "Usage: mem spibaud [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " SPI baudrate in MHz [24|48]"); + PrintAndLogEx(NORMAL, " "); + PrintAndLogEx(NORMAL, " If >= 24Mhz, FASTREADS instead of READS instruction will be used."); + PrintAndLogEx(NORMAL, " Reading Flash ID will virtually always fail under 48Mhz setting"); + PrintAndLogEx(NORMAL, " Unless you know what you are doing, please stay at 24Mhz"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " mem spibaud 48"); + return 0; +} + int usage_flashmem_read(void){ PrintAndLogEx(NORMAL, "Read flash memory on device"); - PrintAndLogEx(NORMAL, "Usage: mem read o l [f]"); + PrintAndLogEx(NORMAL, "Usage: mem read o l "); PrintAndLogEx(NORMAL, " o : offset in memory"); PrintAndLogEx(NORMAL, " l : length"); - PrintAndLogEx(NORMAL, " f : fastRead mode"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " mem read o 0 l 32"); // read 32 bytes starting at offset 0 @@ -42,7 +65,6 @@ int usage_flashmem_save(void){ PrintAndLogEx(NORMAL, " o : offset in memory"); PrintAndLogEx(NORMAL, " l : length"); PrintAndLogEx(NORMAL, " f : file name"); - PrintAndLogEx(NORMAL, " + : fast read mode"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " mem save f myfile"); // download whole flashmem to file myfile @@ -81,14 +103,9 @@ int CmdFlashMemRead(const char *Cmd) { uint8_t cmdp = 0; bool errors = false; uint32_t start_index = 0, len = 0; - uint8_t fast = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { - case 'f': - fast = 1; - cmdp += 1; - break; case 'o': start_index = param_get32ex(Cmd, cmdp+1, 0, 10); cmdp += 2; @@ -114,11 +131,24 @@ int CmdFlashMemRead(const char *Cmd) { return 1; } - UsbCommand c = {CMD_READ_FLASH_MEM, {start_index, len, fast}}; + UsbCommand c = {CMD_FLASHMEM_READ, {start_index, len, 0}}; clearCommandBuffer(); SendCommand(&c); return 0; } + +int CmdFlashmemSpiBaudrate(const char *Cmd) { + + char ctmp = param_getchar(Cmd, 0); + if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_flashmem_spibaud(); + uint32_t baudrate = param_get32ex(Cmd, 0, 0, 10); + baudrate = baudrate*1000000; + if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD ) return usage_flashmem_spibaud(); + UsbCommand c = {CMD_FLASHMEM_SET_SPIBAUDRATE, {baudrate, 0, 0}}; + SendCommand(&c); + return 0; +} + int CmdFlashMemLoad(const char *Cmd){ FILE *f; @@ -196,7 +226,7 @@ int CmdFlashMemLoad(const char *Cmd){ while (bytes_remaining > 0){ uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); - UsbCommand c = {CMD_WRITE_FLASH_MEM, {start_index + bytes_sent, bytes_in_packet, 0}}; + UsbCommand c = {CMD_FLASHMEM_WRITE, {start_index + bytes_sent, bytes_in_packet, 0}}; memcpy(c.d.asBytes, dump + bytes_sent, bytes_in_packet); clearCommandBuffer(); @@ -228,7 +258,6 @@ int CmdFlashMemSave(const char *Cmd){ uint8_t cmdp = 0; bool errors = false; uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE; - uint8_t fast = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { @@ -241,10 +270,6 @@ int CmdFlashMemSave(const char *Cmd){ start_index = param_get32ex(Cmd, cmdp+1, 0, 10); cmdp += 2; break; - case '+': - fast = 1; - cmdp += 1; - break; case 'f': //File handling if ( param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) { @@ -314,7 +339,7 @@ int CmdFlashMemWipe(const char *Cmd){ //Validations if (errors || cmdp == 0 ) return usage_flashmem_wipe(); - UsbCommand c = {CMD_WIPE_FLASH_MEM, {page, initalwipe, 0}}; + UsbCommand c = {CMD_FLASHMEM_WIPE, {page, initalwipe, 0}}; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; @@ -359,7 +384,7 @@ int CmdFlashMemInfo(const char *Cmd){ //Validations if (errors ) return usage_flashmem_info(); - UsbCommand c = {CMD_INFO_FLASH_MEM, {0, 0, 0}}; + UsbCommand c = {CMD_FLASHMEM_INFO, {0, 0, 0}}; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; @@ -488,7 +513,7 @@ int CmdFlashMemInfo(const char *Cmd){ if (shall_write) { // save to mem - c = (UsbCommand){CMD_WRITE_FLASH_MEM, {FLASH_MEM_SIGNATURE_OFFSET, FLASH_MEM_SIGNATURE_LEN, 0}}; + c = (UsbCommand){CMD_FLASHMEM_WRITE, {FLASH_MEM_SIGNATURE_OFFSET, FLASH_MEM_SIGNATURE_LEN, 0}}; memcpy(c.d.asBytes, sign, sizeof(sign)); clearCommandBuffer(); SendCommand(&c); @@ -520,6 +545,7 @@ int CmdFlashMemInfo(const char *Cmd){ static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, + {"spibaud", CmdFlashmemSpiBaudrate, 1, "Set Flash memory Spi baudrate [rdv40]"}, {"read", CmdFlashMemRead, 1, "Read Flash memory [rdv40]"}, {"info", CmdFlashMemInfo, 1, "Flash memory information [rdv40]"}, {"load", CmdFlashMemLoad, 1, "Load data into flash memory [rdv40]"}, diff --git a/client/cmdmain.c b/client/cmdmain.c index 447e83ac8..351152179 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -298,9 +298,9 @@ bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint3 return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_DOWNLOADED_EML_BIGBUF); } case FLASH_MEM: { - UsbCommand c = {CMD_DOWNLOAND_FLASH_MEM, {start_index, bytes, 0}}; + UsbCommand c = {CMD_FLASHMEM_DOWNLOAD, {start_index, bytes, 0}}; SendCommand(&c); - return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_DOWNLOADED_FLASHMEM); + return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_FLASHMEM_DOWNLOADED); } case SIM_MEM: { //UsbCommand c = {CMD_DOWNLOAND_SIM_MEM, {start_index, bytes, 0}}; diff --git a/client/hid-flasher/usb_cmd.h b/client/hid-flasher/usb_cmd.h index 736b11a06..2ced2cd18 100644 --- a/client/hid-flasher/usb_cmd.h +++ b/client/hid-flasher/usb_cmd.h @@ -57,12 +57,12 @@ typedef struct { #define CMD_DOWNLOADED_EML_BIGBUF 0x0111 // RDV40, Flash memory operations -#define CMD_READ_FLASH_MEM 0x0120 -#define CMD_WRITE_FLASH_MEM 0x0121 -#define CMD_WIPE_FLASH_MEM 0x0122 -#define CMD_DOWNLOAND_FLASH_MEM 0x0123 -#define CMD_DOWNLOADED_FLASHMEM 0x0124 -#define CMD_INFO_FLASH_MEM 0x0125 +#define CMD_FLASHMEM_READ 0x0120 +#define CMD_FLASHMEM_WRITE 0x0121 +#define CMD_FLASHMEM_WIPE 0x0122 +#define CMD_FLASHMEM_DOWNLOAD 0x0123 +#define CMD_FLASHMEM_DOWNLOADED 0x0124 +#define CMD_FLASHMEM_INFO 0x0125 // For low-frequency tags #define CMD_READ_TI_TYPE 0x0202 diff --git a/include/common.h b/include/common.h index 8fdb45ab0..8a3f33abd 100644 --- a/include/common.h +++ b/include/common.h @@ -30,6 +30,9 @@ typedef unsigned char byte_t; #define MF_DBG_EXTENDED 4 extern int MF_DBGLEVEL; +// Flashmem spi baudrate +extern uint32_t FLASHMEM_SPIBAUDRATE; + // reader voltage field detector #define MF_MINFIELDV 4000 diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 4de39eef4..51df5896b 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -67,13 +67,17 @@ typedef struct{ #define CMD_DOWNLOAD_EML_BIGBUF 0x0110 #define CMD_DOWNLOADED_EML_BIGBUF 0x0111 + + + // RDV40, Flash memory operations -#define CMD_READ_FLASH_MEM 0x0120 -#define CMD_WRITE_FLASH_MEM 0x0121 -#define CMD_WIPE_FLASH_MEM 0x0122 -#define CMD_DOWNLOAND_FLASH_MEM 0x0123 -#define CMD_DOWNLOADED_FLASHMEM 0x0124 -#define CMD_INFO_FLASH_MEM 0x0125 +#define CMD_FLASHMEM_READ 0x0120 +#define CMD_FLASHMEM_WRITE 0x0121 +#define CMD_FLASHMEM_WIPE 0x0122 +#define CMD_FLASHMEM_DOWNLOAD 0x0123 +#define CMD_FLASHMEM_DOWNLOADED 0x0124 +#define CMD_FLASHMEM_INFO 0x0125 +#define CMD_FLASHMEM_SET_SPIBAUDRATE 0x0126 // RDV40, Smart card operations #define CMD_SMART_RAW 0x0140 diff --git a/tools/mkversion.pl b/tools/mkversion.pl index 6bbc1dfec..1acca6efa 100644 --- a/tools/mkversion.pl +++ b/tools/mkversion.pl @@ -18,13 +18,23 @@ my $fullgitinfo = 'iceman'; my $ctime; # GIT status 0 = dirty, 1 = clean , 2 = undecided my $clean = 2; + # Do we have acces to git command? -my $commandGIT = `bash which git`; +####### +# solves some bug on macos i.e: +## +# perl ../tools/mkversion.pl .. > version.c || cp ../common/default_version.c version.c +# /usr/bin/which: /usr/bin/which: cannot execute binary file +# fatal: No names found, cannot describe anything. +## +# anyway forcing any kind of shell is at least useless, at worst fatal. +my $commandGIT = "env -S which git"; if ( defined($commandGIT) ) { my $githistory = `git fetch --all`; - my $gitversion = `git describe --dirty`; + # now avoiding the "fatal: No names found, cannot describe anything." error by fallbacking to abbrev hash in such case + my $gitversion = `git describe --dirty --always`; my $gitbranch = `git rev-parse --abbrev-ref HEAD`; $clean = $gitversion =~ '-dirty' ? 0 : 1; From 7e12fc0ceb28f322ffe2cef5370ccc3a3f165bac Mon Sep 17 00:00:00 2001 From: "Colin J. Brigato" Date: Thu, 6 Sep 2018 05:34:48 +0200 Subject: [PATCH 0016/1938] Pass 2; commit 3/3; --- armsrc/Standalone/hf_colin.c | 6 ++++-- armsrc/flashmem.c | 4 ---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index 7259fcab3..f19706af1 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -318,14 +318,16 @@ void WriteTagToFlash(uint8_t index, size_t size) Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); Flash_Erase4k(0,0); - Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); uint32_t end_time; uint32_t start_time = end_time = GetTickCount(); while (bytes_remaining > 0) { + + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); + uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); memcpy(buff, data + bytes_sent, bytes_in_packet); diff --git a/armsrc/flashmem.c b/armsrc/flashmem.c index f173b66b4..a8642dd74 100644 --- a/armsrc/flashmem.c +++ b/armsrc/flashmem.c @@ -382,10 +382,6 @@ uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) { } - - Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); - FlashSendByte(PAGEPROG); FlashSendByte((address >> 16) & 0xFF); FlashSendByte((address >> 8) & 0xFF); From 24eaac86810e39a219431daf9bb959323366760d Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 6 Sep 2018 21:43:20 +0200 Subject: [PATCH 0017/1938] CHG: the thread comms refactoring from offical pm3 repo chg: FPC com speed limited to 115200 when compiled with FPC chg: USART remake (@drandreas) --- armsrc/Makefile | 2 +- armsrc/appmain.c | 81 ++++--- armsrc/apps.h | 4 +- armsrc/lfops.c | 2 +- bootrom/bootrom.c | 10 +- client/Makefile | 5 +- client/cmdanalyse.c | 3 +- client/cmddata.h | 2 +- client/cmdflashmem.h | 2 +- client/cmdhffelica.h | 2 +- client/cmdhficlass.h | 2 +- client/cmdhflegic.h | 2 +- client/cmdhfmfu.h | 1 + client/cmdlf.c | 6 +- client/cmdlfawid.c | 2 +- client/cmdlfcotag.h | 2 +- client/cmdlfem4x.h | 3 +- client/cmdlfhid.c | 2 +- client/cmdlfhitag.c | 2 +- client/cmdlfindala.c | 2 +- client/cmdlft55xx.c | 10 +- client/cmdlft55xx.h | 2 +- client/cmdmain.c | 292 +----------------------- client/cmdmain.h | 28 +-- client/cmdparser.c | 3 +- client/cmdscript.c | 1 + client/cmdsmartcard.h | 2 +- client/cmdtrace.h | 2 +- client/comms.c | 510 ++++++++++++++++++++++++++++++++++++++++++ client/comms.h | 67 ++++++ client/flash.c | 41 ++-- client/flash.h | 2 + client/flasher.c | 93 ++------ client/proxmark3.c | 192 ++-------------- client/proxmark3.h | 4 - client/scripting.h | 1 + client/ui.c | 11 +- client/ui.h | 3 +- common/cmd.c | 37 +-- common/cmd.h | 3 +- common/usart.c | 316 +++++++++----------------- common/usart.h | 13 +- uart/uart.h | 14 +- uart/uart_posix.c | 32 +-- uart/uart_win32.c | 48 ++-- 45 files changed, 915 insertions(+), 949 deletions(-) create mode 100644 client/comms.c create mode 100644 client/comms.h diff --git a/armsrc/Makefile b/armsrc/Makefile index b2ae9f9a2..8f0cd025e 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -104,7 +104,7 @@ ifneq (,$(findstring WITH_HF_MATTYRUN,$(APP_CFLAGS))) endif # WITH_HF_COLIN ifneq (,$(findstring WITH_HF_COLIN,$(APP_CFLAGS))) - SRC_STANDALONE = hf_colin.c vtsend.c + SRC_STANDALONE = vtsend.c hf_colin.c endif #the FPGA bitstream files. Note: order matters! diff --git a/armsrc/appmain.c b/armsrc/appmain.c index e9237c25c..9cb3758af 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -441,7 +441,7 @@ void printStandAloneModes(void) { DbpString(" LF HID corporate 1000 bruteforce - (Federico dotta & Maurizio Agazzini)"); #endif #if defined(WITH_HF_MATTYRUN) - DbpString(" HF Mifare sniff/clone - aka MattyRun (Mat�as A. R� Medina)"); + DbpString(" HF Mifare sniff/clone - aka MattyRun (Matías A. Ré Medina)"); #endif #if defined(WITH_HF_COLIN) DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN (Colin Brigato)"); @@ -1063,15 +1063,45 @@ void UsbPacketReceived(uint8_t *packet, int len) { #ifdef WITH_FPC case CMD_FPC_SEND: { -// char header[] = {"*** Iceman Usart ***"}; -// uint32_t res = usart_writebuffer((uint8_t *)header, sizeof(header), 10000); + + char dest[USB_CMD_DATA_SIZE] = { '\0' }; + + static const char* welcome = "Proxmark3 Serial interface ready\n"; + strncat(dest, welcome, sizeof(dest) - strlen(dest) - 1); - //temp++; - uint8_t got = usart_read(10000); - if ( got > 0 ) { - Dbprintf("got %02x", got); - usart_write(got, 10000); + sprintf(dest + strlen(dest) - 1, "Arg0 | 0x%" PRIx64 " \n", c->arg[0]); + sprintf(dest + strlen(dest) - 1, "Arg1 | 0x%" PRIx64 " \n", c->arg[1]); + sprintf(dest + strlen(dest) - 1, "Arg2 | 0x%" PRIx64 " \n", c->arg[2]); + sprintf(dest + strlen(dest) - 1, "bytes | 0x%02x 0x%02x 0x%02x 0x%02x \n" + ,c->d.asBytes[0], c->d.asBytes[1], c->d.asBytes[2], c->d.asBytes[3]); + +/* + UsbCommand txcmd; + for (size_t i=0; i < sizeof(UsbCommand); i++) + ((uint8_t*)&txcmd)[i] = 0x00; + + // Compose the outgoing command frame + txcmd.cmd = CMD_DEBUG_PRINT_STRING; + txcmd.arg[0] = len; + txcmd.arg[1] = 0; + txcmd.arg[2] = 0; + memcpy(txcmd.d.asBytes, dest, USB_CMD_DATA_SIZE); + usart_writebuffer((uint8_t*)&txcmd, sizeof(UsbCommand)); +*/ + DbpString("Starting to listen"); + LED_A_ON(); + /* + uint8_t rx[sizeof(UsbCommand)]; + usart_init(); + while (!BUTTON_PRESS() && !usb_poll_validate_length()) { + WaitMS(1); + if (usart_readbuffer(rx, sizeof(rx)) ) + DbpString("got 544"); } + */ + cmd_send(CMD_DEBUG_PRINT_STRING, strlen(dest), 0, 0, dest, strlen(dest)); + //DbpString("finished"); + LED_A_OFF(); cmd_send(CMD_ACK,0,0,0,0,0); break; } @@ -1114,7 +1144,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { for(size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { len = MIN( (numofbytes - i), USB_CMD_DATA_SIZE); isok = cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, i, len, BigBuf_get_traceLen(), mem + startidx + i, len); - if (!isok) + if (isok != 0) Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len); } // Trigger a finish downloading signal with an ACK frame @@ -1160,8 +1190,8 @@ void UsbPacketReceived(uint8_t *packet, int len) { for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); isok = cmd_send(CMD_DOWNLOADED_EML_BIGBUF, i, len, 0, mem + startidx + i, len); - if (!isok) - Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); + if (isok != 0) + Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len); } // Trigger a finish downloading signal with an ACK frame cmd_send(CMD_ACK, 1, 0, 0, 0, 0); @@ -1180,7 +1210,6 @@ void UsbPacketReceived(uint8_t *packet, int len) { uint16_t isok = 0; uint32_t startidx = c->arg[0]; uint16_t len = c->arg[1]; - //uint8_t fast = c->arg[2]; Dbprintf("FlashMem read | %d - %d | ", startidx, len); @@ -1285,8 +1314,6 @@ void UsbPacketReceived(uint8_t *packet, int len) { size_t len = 0; uint32_t startidx = c->arg[0]; uint32_t numofbytes = c->arg[1]; - //uint8_t fast = c->arg[2]; - // arg0 = startindex // arg1 = length bytes to transfer // arg2 = RFU @@ -1301,7 +1328,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { Dbprintf("reading flash memory failed :: | bytes between %d - %d", i, len); isok = cmd_send(CMD_FLASHMEM_DOWNLOADED, i, len, 0, mem, len); - if (!isok) + if (isok != 0) Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); } FlashStop(); @@ -1458,19 +1485,20 @@ void __attribute__((noreturn)) AppMain(void) { for(;;) { WDT_HIT(); -#ifdef WITH_FPC - // check if there is a FPC USART1 message? - /* - uint32_t fpc_rxlen = usart_read(rx, sizeof(UsbCommand)); - if ( fpc_rxlen > 0) - Dbprintf("got a package [len %d] %02x", fpc_rxlen, rx[0]); - */ -#endif - // Check if there is a usb packet available - if ( cmd_receive( (UsbCommand*)rx ) ) { - UsbPacketReceived(rx, sizeof(UsbCommand) ); + if (usb_poll_validate_length()) { + if (usb_read(rx, sizeof(rx)) ) + UsbPacketReceived(rx, sizeof(rx)); } +#ifdef WITH_FPC + // Check is there is FPC package available + /* + usart_init(); + if (usart_readbuffer(rx, sizeof(rx)) ) + UsbPacketReceived(rx, sizeof(rx) ); + */ + +#endif // Press button for one second to enter a possible standalone mode if (BUTTON_HELD(1000) > 0) { @@ -1487,6 +1515,7 @@ void __attribute__((noreturn)) AppMain(void) { #if defined (WITH_ISO14443a) && ( defined (WITH_HF_YOUNG) || defined(WITH_HF_COLIN) || defined(WITH_HF_MATTYRUN) ) RunMod(); #endif + } } } diff --git a/armsrc/apps.h b/armsrc/apps.h index 7852d1439..f8d24f4ae 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -230,8 +230,8 @@ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page); void check_challenges(bool file_given, byte_t* data); // cmd.h -bool cmd_receive(UsbCommand* cmd); -bool cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void* data, size_t len); +uint8_t cmd_receive(UsbCommand* cmd); +uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void* data, size_t len); // util.h void HfSnoop(int , int); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 5afce8549..9d6cfbf0e 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -27,7 +27,7 @@ #endif -#define START_GAP 48*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc) +#define START_GAP 52*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc) #define WRITE_GAP 18*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc) #define WRITE_0 24*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc) #define WRITE_1 54*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (56fc) 432 for T55x7; 448 for E5550 diff --git a/bootrom/bootrom.c b/bootrom/bootrom.c index 0dcf52b28..d2a18628a 100644 --- a/bootrom/bootrom.c +++ b/bootrom/bootrom.c @@ -191,7 +191,7 @@ static void flash_mode(int externally_entered) { start_addr = 0; end_addr = 0; bootrom_unlocked = 0; - byte_t rx[sizeof(UsbCommand)]; + uint8_t rx[sizeof(UsbCommand)]; usb_enable(); @@ -200,10 +200,12 @@ static void flash_mode(int externally_entered) { for(;;) { WDT_HIT(); - + // Check if there is a usb packet available - if ( cmd_receive( (UsbCommand*)rx ) ) - UsbPacketReceived(rx, sizeof(UsbCommand) ); + if (usb_poll_validate_length()) { + if (usb_read(rx, sizeof(rx)) ) + UsbPacketReceived(rx, sizeof(rx)); + } if (!externally_entered && !BUTTON_PRESS()) { /* Perform a reset to leave flash mode */ diff --git a/client/Makefile b/client/Makefile index af2efb26c..f577a6386 100644 --- a/client/Makefile +++ b/client/Makefile @@ -82,7 +82,7 @@ else endif # RDV40 flag enables flashmemory commands in client. comment out if you don't have rdv40 -CFLAGS += -DWITH_FLASH -DWITH_SMARTCARD +CFLAGS += -DWITH_FLASH -DWITH_SMARTCARD -DWITH_FPC # Flags to generate temporary dependency files DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td @@ -94,7 +94,8 @@ CORESRCS = uart_posix.c \ ui.c \ util.c \ util_posix.c \ - scandir.c + scandir.c \ + comms.c CMDSRCS = crapto1/crapto1.c \ crapto1/crypto1.c \ diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c index 1c65b8cc4..490dda9d3 100644 --- a/client/cmdanalyse.c +++ b/client/cmdanalyse.c @@ -515,6 +515,7 @@ int CmdAnalyseA(const char *Cmd){ UsbCommand c = {CMD_FPC_SEND, {0, 0, 0}}; + memcpy(c.d.asBytes, data, USB_CMD_DATA_SIZE); clearCommandBuffer(); SendCommand(&c); @@ -522,7 +523,7 @@ int CmdAnalyseA(const char *Cmd){ if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { return 1; } - PrintAndLogEx(NORMAL, "got ack"); + PrintAndLogEx(NORMAL, "got ack. Status %d", resp.arg[0]); return 0; PrintAndLogEx(NORMAL, "-- " _BLUE_(its my message) "\n"); diff --git a/client/cmddata.h b/client/cmddata.h index dbd735747..27c446ecb 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -25,7 +25,7 @@ #include "proxmark3.h" // sendcommand #include "ui.h" // for show graph controls #include "graph.h" // for graph data -#include "usb_cmd.h" // already included in cmdmain.h and proxmark3.h +#include "comms.h" #include "lfdemod.h" // for demod code #include "crc.h" // for pyramid checksum maxim #include "crc16.h" // for FDXB demod checksum diff --git a/client/cmdflashmem.h b/client/cmdflashmem.h index 99b18b4c5..843c17d6f 100644 --- a/client/cmdflashmem.h +++ b/client/cmdflashmem.h @@ -22,7 +22,7 @@ #include "util.h" #include "util_posix.h" // msclock #include "loclass/fileutils.h" //saveFile -#include "cmdmain.h" //getfromdevice +#include "comms.h" //getfromdevice extern int CmdFlashMem(const char *Cmd); diff --git a/client/cmdhffelica.h b/client/cmdhffelica.h index f82d2d574..bcec38a0b 100644 --- a/client/cmdhffelica.h +++ b/client/cmdhffelica.h @@ -21,7 +21,7 @@ #include "ui.h" #include "util.h" #include "cmdparser.h" -#include "cmdmain.h" +#include "comms.h" // getfromdevice #include "iso14443crc.h" #include "cmdhf.h" // list cmd #include "mifare.h" // felica_card_select_t struct diff --git a/client/cmdhficlass.h b/client/cmdhficlass.h index e9bedf9fe..c53e88f49 100644 --- a/client/cmdhficlass.h +++ b/client/cmdhficlass.h @@ -21,7 +21,7 @@ #include "cmdparser.h" #include "common.h" #include "util.h" -#include "cmdmain.h" +#include "comms.h" #include "des.h" #include "loclass/cipherutils.h" #include "loclass/cipher.h" diff --git a/client/cmdhflegic.h b/client/cmdhflegic.h index 645a6b993..4e3c8cc86 100644 --- a/client/cmdhflegic.h +++ b/client/cmdhflegic.h @@ -16,7 +16,7 @@ #include "proxmark3.h" #include "ui.h" #include "cmdparser.h" -#include "cmdmain.h" +#include "comms.h" #include "util.h" #include "crc.h" #include "legic_prng.h" diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index da9cfd02f..2e07bae80 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -9,6 +9,7 @@ #include "mifare.h" #include "util.h" #include "protocols.h" +#include "comms.h" typedef struct { uint8_t version[8]; diff --git a/client/cmdlf.c b/client/cmdlf.c index ec9527bcc..ccb781014 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -320,7 +320,7 @@ int CmdLFSetConfig(const char *Cmd) { } bool lf_read(bool silent, uint32_t samples) { - if (offline) return false; + if ( IsOffline() ) return false; UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_125K, {silent, samples, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -342,7 +342,7 @@ bool lf_read(bool silent, uint32_t samples) { int CmdLFRead(const char *Cmd) { - if (offline) return 0; + if ( IsOffline() ) return 0; bool errors = false; bool silent = false; @@ -844,7 +844,7 @@ int CmdLFfind(const char *Cmd) { if (cmdp == 'u') testRaw = 'u'; - bool isOnline = (!offline && (cmdp != '1') ); + bool isOnline = (!IsOffline() && (cmdp != '1') ); if (isOnline) lf_read(true, 30000); diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index 8b1205e52..420caeb62 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -539,7 +539,7 @@ int CmdAWIDBrute(const char *Cmd) { // main loop for (;;){ - if ( offline ) { + if ( IsOffline() ) { PrintAndLogEx(WARNING, "Device offline\n"); return 2; } diff --git a/client/cmdlfcotag.h b/client/cmdlfcotag.h index 589089a61..e03f7d5f5 100644 --- a/client/cmdlfcotag.h +++ b/client/cmdlfcotag.h @@ -15,7 +15,7 @@ #include "util.h" // FALSE / TRUE #include "cmddata.h" // getSamples #include "cmdparser.h" // CmdsParse, CmdsHelp -#include "cmdmain.h" +#include "comms.h" #include "ui.h" // PrintAndLog #include "cmdlf.h" // Setconfig diff --git a/client/cmdlfem4x.h b/client/cmdlfem4x.h index aa044b9c7..676c6fd6b 100644 --- a/client/cmdlfem4x.h +++ b/client/cmdlfem4x.h @@ -21,8 +21,7 @@ #include "graph.h" #include "cmdparser.h" #include "cmddata.h" -#include "cmdmain.h" -#include "cmdmain.h" +#include "comms.h" #include "cmdlf.h" #include "lfdemod.h" diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index 08cbc8661..02fd9c791 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -544,7 +544,7 @@ int CmdHIDBrute(const char *Cmd){ // main loop for (;;){ - if ( offline ) { + if ( IsOffline() ) { PrintAndLogEx(WARNING, "Device offline\n"); return 2; } diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index ed2250a0c..69bae1b38 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -20,7 +20,7 @@ #include "hitag2.h" #include "hitagS.h" #include "util_posix.h" -#include "cmdmain.h" +#include "comms.h" #include "cmddata.h" static int CmdHelp(const char *Cmd); diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 6f6eb4f37..f4993fb5e 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -122,7 +122,7 @@ int CmdIndalaDemod(const char *Cmd) { ans = PSKDemod("32", 0); if (!ans){ - PrintAndLogEx(DEBUG, "DEBUG: Error - Indala can't demod signal: %d",ans); + PrintAndLogEx(DEBUG, "DEBUG: Error - Indala can't demod signal: %d", ans); return 0; } diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 0982337f3..c4d1e3be6 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -452,7 +452,7 @@ bool DecodeT5555TraceBlock() { // sanity check. Don't use proxmark if it is offline and you didn't specify useGraphbuf static int SanityOfflineCheck( bool useGraphBuffer ){ - if ( !useGraphBuffer && offline) { + if ( !useGraphBuffer && IsOffline() ) { PrintAndLogEx(NORMAL, "Your proxmark3 device is offline. Specify [1] to use graphbuffer data instead"); return 0; } @@ -466,13 +466,11 @@ int CmdT55xxDetect(const char *Cmd){ uint32_t password = 0; uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch ( tolower(param_getchar(Cmd, cmdp))) { case 'h': - case 'H': return usage_t55xx_detect(); case 'p': - case 'P': password = param_get32ex(Cmd, cmdp+1, 0, 16); usepwd = true; cmdp += 2; @@ -1572,7 +1570,7 @@ int CmdT55xxBruteForce(const char *Cmd) { uint64_t testpwd = 0x00; for (uint16_t c = 0; c < keycnt; ++c ) { - if ( offline ) { + if ( IsOffline() ) { PrintAndLogEx(WARNING, "Device offline\n"); free(keyBlock); return 2; diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index ad170514c..b6c355778 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -18,7 +18,7 @@ #include "proxmark3.h" #include "ui.h" #include "graph.h" -#include "cmdmain.h" +#include "comms.h" #include "cmdparser.h" #include "cmddata.h" #include "cmdlf.h" diff --git a/client/cmdmain.c b/client/cmdmain.c index 351152179..85d7f19c3 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -15,18 +15,6 @@ static int CmdQuit(const char *Cmd); static int CmdRev(const char *Cmd); static int CmdRem(const char *Cmd); -//For storing command that are received from the device -static UsbCommand cmdBuffer[CMD_BUFFER_SIZE]; - -//Points to the next empty position to write to -static int cmd_head = 0; - -//Points to the position of the last unread command -static int cmd_tail = 0; - -// to lock cmdBuffer operations from different threads -static pthread_mutex_t cmdBufferMutex = PTHREAD_MUTEX_INITIALIZER; - static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help. Use ' help' for details of a particular command."}, {"analyse", CmdAnalyse, 1, "{ Analyse utils... }"}, @@ -38,7 +26,7 @@ static command_t CommandTable[] = { {"reveng", CmdRev, 1, "{ Crc calculations from the software reveng 1.53... }"}, {"script", CmdScript, 1, "{ Scripting commands }"}, {"trace", CmdTrace, 1, "{ Trace manipulation... }"}, -#ifdef WITH_FLASH +#ifdef WITH_FLASH {"mem", CmdFlashMem, 1, "{ RDV40, Flash Memory manipulation... }"}, #endif #ifdef WITH_SMARTCARD @@ -79,286 +67,10 @@ int CmdRev(const char *Cmd) { return 0; } -bool dl_it(uint8_t *dest, uint32_t bytes, uint32_t start_index, UsbCommand *response, size_t ms_timeout, bool show_warning, uint32_t rec_cmd); -/** - * @brief This method should be called when sending a new command to the pm3. In case any old - * responses from previous commands are stored in the buffer, a call to this method should clear them. - * A better method could have been to have explicit command-ACKS, so we can know which ACK goes to which - * operation. Right now we'll just have to live with this. - */ -void clearCommandBuffer() { - //This is a very simple operation - pthread_mutex_lock(&cmdBufferMutex); - cmd_tail = cmd_head; - pthread_mutex_unlock(&cmdBufferMutex); -} - -/** - * @brief storeCommand stores a USB command in a circular buffer - * @param UC - */ -void storeCommand(UsbCommand *command) { - - pthread_mutex_lock(&cmdBufferMutex); - if ( ( cmd_head+1) % CMD_BUFFER_SIZE == cmd_tail) { - //If these two are equal, we're about to overwrite in the - // circular buffer. - PrintAndLogEx(FAILED, "WARNING: Command buffer about to overwrite command! This needs to be fixed!"); - fflush(NULL); - } - //Store the command at the 'head' location - UsbCommand* destination = &cmdBuffer[cmd_head]; - memcpy(destination, command, sizeof(UsbCommand)); - - //increment head and wrap - cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; - pthread_mutex_unlock(&cmdBufferMutex); -} -/** - * @brief getCommand gets a command from an internal circular buffer. - * @param response location to write command - * @return 1 if response was returned, 0 if nothing has been received - */ -int getCommand(UsbCommand* response) { - pthread_mutex_lock(&cmdBufferMutex); - //If head == tail, there's nothing to read, or if we just got initialized - if (cmd_head == cmd_tail) { - pthread_mutex_unlock(&cmdBufferMutex); - return 0; - } - - //Pick out the next unread command - UsbCommand* last_unread = &cmdBuffer[cmd_tail]; - memcpy(response, last_unread, sizeof(UsbCommand)); - - //Increment tail - this is a circular buffer, so modulo buffer size - cmd_tail = (cmd_tail +1 ) % CMD_BUFFER_SIZE; - - pthread_mutex_unlock(&cmdBufferMutex); - return 1; -} - -/** - * @brief Waits for a certain response type. This method waits for a maximum of - * ms_timeout milliseconds for a specified response command. - * @param cmd command to wait for, or CMD_UNKNOWN to take any command. - * @param response struct to copy received command into. - * @param ms_timeout display message after 2 seconds - * @return true if command was returned, otherwise false - */ -bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning) { - - UsbCommand resp; - - if (response == NULL) - response = &resp; - - uint64_t start_time = msclock(); - - // Wait until the command is received - while (true) { - - while ( getCommand(response) ) { - if (cmd == CMD_UNKNOWN || response->cmd == cmd) - return true; - } - - if (msclock() - start_time > ms_timeout) - break; - - if (msclock() - start_time > 3000 && show_warning) { - // 3 seconds elapsed (but this doesn't mean the timeout was exceeded) - PrintAndLogEx(NORMAL, "Waiting for a response from the proxmark..."); - PrintAndLogEx(NORMAL, "You can cancel this operation by pressing the pm3 button"); - show_warning = false; - } - } - return false; -} - -bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) { - return WaitForResponseTimeoutW(cmd, response, ms_timeout, true); -} - -bool WaitForResponse(uint32_t cmd, UsbCommand* response) { - return WaitForResponseTimeoutW(cmd, response, -1, true); -} - //----------------------------------------------------------------------------- // Entry point into our code: called whenever the user types a command and // then presses Enter, which the full command line that they typed. //----------------------------------------------------------------------------- int CommandReceived(char *Cmd) { return CmdsParse(CommandTable, Cmd); -} - -//----------------------------------------------------------------------------- -// Entry point into our code: called whenever we received a packet over USB -// that we weren't necessarily expecting, for example a debug print. -//----------------------------------------------------------------------------- -void UsbCommandReceived(UsbCommand* _ch) { - - //UsbCommand *c = malloc(sizeof(UsbCommand)); - //memset(cp, 0x00, sizeof(*cp)); - - pthread_mutex_lock(&cmdBufferMutex); - UsbCommand* c = _ch; - pthread_mutex_unlock(&cmdBufferMutex); - - switch(c->cmd) { - // First check if we are handling a debug message - case CMD_DEBUG_PRINT_STRING: { - - char s[USB_CMD_DATA_SIZE+1]; - memset(s, 0x00, sizeof(s)); - size_t len = MIN(c->arg[0], USB_CMD_DATA_SIZE); - memcpy(s, c->d.asBytes, len); - - //#define FLAG_RAWPRINT 0x0111 - //#define FLAG_NOOPT 0x0000 - //#define FLAG_NOLOG 0x0001 - //#define FLAG_NONEWLINE 0x0010 - //#define FLAG_NOPROMPT 0x0100 - uint64_t flag = c->arg[1]; - if (flag > 0) { // FLAG_RAWPRINT) { - switch (flag) { - case FLAG_RAWPRINT: { - printf("%s", s); - } return; break; - case FLAG_NONEWLINE: { - printf("%s\r", s); - } return; break; - case FLAG_NOLOG: { - printf("%s\r\n", s); - } return; break; - // printf("%s", s); - fflush(stdout); - return; - } - } - - - // print debug line on same row. escape seq \r - if ( c->arg[1] == CMD_MEASURE_ANTENNA_TUNING_HF) { - PrintAndLogEx(NORMAL, "\r#db# %s", s); - } else { - PrintAndLogEx(NORMAL, "#db# %s", s); - } - fflush(NULL); - break; - } - case CMD_DEBUG_PRINT_INTEGERS: { - PrintAndLogEx(NORMAL, "#db# %08x, %08x, %08x", c->arg[0], c->arg[1], c->arg[2]); - break; - } - // iceman: hw status - down the path on device, runs printusbspeed which starts sending a lot of - // CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K packages which is not dealt with. I wonder if simply ignoring them will - // work. lets try it. - default: { - storeCommand(c); - break; - } - } -} - -/** -* Data transfer from Proxmark to client. This method times out after -* ms_timeout milliseconds. -* @brief GetFromDevice -* @param memtype Type of memory to download from proxmark -* @param dest Destination address for transfer -* @param bytes number of bytes to be transferred -* @param start_index offset into Proxmark3 BigBuf[] -* @param response struct to copy last command (CMD_ACK) into -* @param ms_timeout timeout in milliseconds -* @param show_warning display message after 2 seconds -* @return true if command was returned, otherwise false -*/ -bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint32_t start_index, UsbCommand *response, size_t ms_timeout, bool show_warning) { - - if (dest == NULL) return false; - if (bytes == 0) return true; - - UsbCommand resp; - if (response == NULL) - response = &resp; - - // clear - clearCommandBuffer(); - - switch (memtype) { - case BIG_BUF: { - UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {start_index, bytes, 0}}; - SendCommand(&c); - return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K); - } - case BIG_BUF_EML: { - UsbCommand c = {CMD_DOWNLOAD_EML_BIGBUF, {start_index, bytes, 0}}; - SendCommand(&c); - return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_DOWNLOADED_EML_BIGBUF); - } - case FLASH_MEM: { - UsbCommand c = {CMD_FLASHMEM_DOWNLOAD, {start_index, bytes, 0}}; - SendCommand(&c); - return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_FLASHMEM_DOWNLOADED); - } - case SIM_MEM: { - //UsbCommand c = {CMD_DOWNLOAND_SIM_MEM, {start_index, bytes, 0}}; - //SendCommand(&c); - //return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_DOWNLOADED_SIMMEM); - return false; - } - } - return false; -} - -bool dl_it(uint8_t *dest, uint32_t bytes, uint32_t start_index, UsbCommand *response, size_t ms_timeout, bool show_warning, uint32_t rec_cmd) { - - uint32_t bytes_completed = 0; - uint64_t start_time = msclock(); - - while (true) { - - if (getCommand(response)) { - - // sample_buf is a array pointer, located in data.c - // arg0 = offset in transfer. Startindex of this chunk - // arg1 = length bytes to transfer - // arg2 = bigbuff tracelength (?) - if (response->cmd == rec_cmd) { - - uint32_t offset = response->arg[0]; - uint32_t copy_bytes = MIN(bytes - bytes_completed, response->arg[1]); - //uint32_t tracelen = c->arg[2]; - - // extended bounds check1. upper limit is USB_CMD_DATA_SIZE - // shouldn't happen - copy_bytes = MIN(copy_bytes, USB_CMD_DATA_SIZE); - - // extended bounds check2. - if ( offset + copy_bytes > bytes ) { - PrintAndLogEx(FAILED, "ERROR: Out of bounds when downloading from device, offset %u | len %u | total len %u > buf_size %u", offset, copy_bytes, offset+copy_bytes, bytes); - break; - } - - memcpy(dest + offset, response->d.asBytes, copy_bytes); - bytes_completed += copy_bytes; - } else if (response->cmd == CMD_ACK) { - return true; - } - } - - if (msclock() - start_time > ms_timeout) { - PrintAndLogEx(FAILED, "Timed out while trying to download data from device"); - break; - } - - if (msclock() - start_time > 3000 && show_warning) { - // 3 seconds elapsed (but this doesn't mean the timeout was exceeded) - PrintAndLogEx(NORMAL, "Waiting for a response from the proxmark..."); - PrintAndLogEx(NORMAL, "You can cancel this operation by pressing the pm3 button"); - show_warning = false; - } - } - return false; -} +} \ No newline at end of file diff --git a/client/cmdmain.h b/client/cmdmain.h index de728e11c..74804300d 100644 --- a/client/cmdmain.h +++ b/client/cmdmain.h @@ -13,7 +13,6 @@ #include #include -#include #include #include #include @@ -24,7 +23,6 @@ #include "util.h" #include "ui.h" #include "cmdparser.h" -#include "loclass/fileutils.h" #include "cmdhf.h" #include "cmddata.h" #include "cmdhw.h" @@ -33,26 +31,16 @@ #include "cmdscript.h" #include "cmdcrc.h" #include "cmdanalyse.h" -#include "cmdflashmem.h" // rdv40 flashmem commands -#include "cmdsmartcard.h" // rdv40 smart card ISO7816 commands -//For storing command that are received from the device -#define CMD_BUFFER_SIZE 100 -typedef enum { - BIG_BUF, - BIG_BUF_EML, - FLASH_MEM, - SIM_MEM, - } DeviceMemType_t; - -extern void UsbCommandReceived(UsbCommand *c); +#ifdef WITH_FLASH +#include "cmdflashmem.h" // rdv40 flashmem commands +#endif + +#ifdef WITH_SMARTCARD +#include "cmdsmartcard.h" // rdv40 smart card ISO7816 commands +#endif + extern int CommandReceived(char *Cmd); -extern bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning); -extern bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout); -extern bool WaitForResponse(uint32_t cmd, UsbCommand* response); -extern void clearCommandBuffer(); extern command_t* getTopLevelCommandTable(); -extern bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint32_t start_index, UsbCommand *response, size_t ms_timeout, bool show_warning); - #endif diff --git a/client/cmdparser.c b/client/cmdparser.c index f12b4966e..974439298 100644 --- a/client/cmdparser.c +++ b/client/cmdparser.c @@ -15,12 +15,13 @@ #include "ui.h" #include "cmdparser.h" #include "proxmark3.h" +#include "comms.h" void CmdsHelp(const command_t Commands[]) { if (Commands[0].Name == NULL) return; int i = 0; while (Commands[i].Name) { - if (!offline || Commands[i].Offline) + if (!IsOffline() || Commands[i].Offline) PrintAndLogEx(NORMAL, "%-16s %s", Commands[i].Name, Commands[i].Help); ++i; } diff --git a/client/cmdscript.c b/client/cmdscript.c index a34a42815..7159fa70b 100644 --- a/client/cmdscript.c +++ b/client/cmdscript.c @@ -24,6 +24,7 @@ #include "graph.h" #include "cmdparser.h" #include "cmdmain.h" +#include "comms.h" #include "cmdscript.h" #include "cmdhfmf.h" #include "pm3_binlib.h" diff --git a/client/cmdsmartcard.h b/client/cmdsmartcard.h index 1c7b5d3f8..5ba453e30 100644 --- a/client/cmdsmartcard.h +++ b/client/cmdsmartcard.h @@ -21,7 +21,7 @@ #include "common.h" #include "util.h" #include "loclass/fileutils.h" // saveFile -#include "cmdmain.h" // getfromdevice +#include "comms.h" // getfromdevice #include "emv/emvcore.h" // decodeTVL #include "emv/apduinfo.h" // APDUcode description diff --git a/client/cmdtrace.h b/client/cmdtrace.h index 8e940d220..c6ba0cc38 100644 --- a/client/cmdtrace.h +++ b/client/cmdtrace.h @@ -24,7 +24,7 @@ #include "util.h" // for parsing cli command utils #include "ui.h" // for show graph controls #include "cmdparser.h" // for getting cli commands included in cmdmain.h -#include "cmdmain.h" // for sending cmds to device. GetFromBigBuf +#include "comms.h" // for sending cmds to device. GetFromBigBuf #include "loclass/fileutils.h" // for saveFile extern int CmdTrace(const char *Cmd); diff --git a/client/comms.c b/client/comms.c new file mode 100644 index 000000000..ec1a36860 --- /dev/null +++ b/client/comms.c @@ -0,0 +1,510 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2009 Michael Gernoth +// Copyright (C) 2010 iZsh +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Code for communicating with the proxmark3 hardware. +//----------------------------------------------------------------------------- + +#include "comms.h" + +// Serial port that we are communicating with the PM3 on. +static serial_port sp = NULL; +static char *serial_port_name = NULL; + +// If TRUE, then there is no active connection to the PM3, and we will drop commands sent. +static bool offline; + +static communication_arg_t conn; + +static pthread_t USB_communication_thread; +//static pthread_t FPC_communication_thread; + +// Transmit buffer. +static UsbCommand txBuffer; +static bool txBuffer_pending = false; +static pthread_mutex_t txBufferMutex = PTHREAD_MUTEX_INITIALIZER; +static pthread_cond_t txBufferSig = PTHREAD_COND_INITIALIZER; + +// Used by UsbReceiveCommand as a ring buffer for messages that are yet to be +// processed by a command handler (WaitForResponse{,Timeout}) +static UsbCommand rxBuffer[CMD_BUFFER_SIZE]; + +// Points to the next empty position to write to +static int cmd_head = 0; + +// Points to the position of the last unread command +static int cmd_tail = 0; + +// to lock rxBuffer operations from different threads +static pthread_mutex_t rxBufferMutex = PTHREAD_MUTEX_INITIALIZER; + +// These wrappers are required because it is not possible to access a static +// global variable outside of the context of a single file. +void SetOffline(bool value) { + offline = value; +} + +bool IsOffline() { + return offline; +} + +void SendCommand(UsbCommand *c) { + + #ifdef COMMS_DEBUG + PrintAndLogEx(NORMAL, "Sending %d bytes | cmd %04x\n", sizeof(UsbCommand), c->cmd); + #endif + + if (offline) { + PrintAndLogEx(NORMAL, "Sending bytes to proxmark failed - offline"); + return; + } + + pthread_mutex_lock(&txBufferMutex); + /** + This causes hangups at times, when the pm3 unit is unresponsive or disconnected. The main console thread is alive, + but comm thread just spins here. Not good.../holiman + **/ + while (txBuffer_pending) { + // wait for communication thread to complete sending a previous commmand + pthread_cond_wait(&txBufferSig, &txBufferMutex); + } + + txBuffer = *c; + txBuffer_pending = true; + + // tell communication thread that a new command can be send + pthread_cond_signal(&txBufferSig); + + pthread_mutex_unlock(&txBufferMutex); + +//__atomic_test_and_set(&txcmd_pending, __ATOMIC_SEQ_CST); +} + +/** + * @brief This method should be called when sending a new command to the pm3. In case any old + * responses from previous commands are stored in the buffer, a call to this method should clear them. + * A better method could have been to have explicit command-ACKS, so we can know which ACK goes to which + * operation. Right now we'll just have to live with this. + */ +void clearCommandBuffer() { + //This is a very simple operation + pthread_mutex_lock(&rxBufferMutex); + cmd_tail = cmd_head; + pthread_mutex_unlock(&rxBufferMutex); +} +/** + * @brief storeCommand stores a USB command in a circular buffer + * @param UC + */ +static void storeCommand(UsbCommand *command) { + + pthread_mutex_lock(&rxBufferMutex); + if ( ( cmd_head+1) % CMD_BUFFER_SIZE == cmd_tail) { + //If these two are equal, we're about to overwrite in the + // circular buffer. + PrintAndLogEx(FAILED, "WARNING: Command buffer about to overwrite command! This needs to be fixed!"); + fflush(NULL); + } + //Store the command at the 'head' location + UsbCommand* destination = &rxBuffer[cmd_head]; + memcpy(destination, command, sizeof(UsbCommand)); + + //increment head and wrap + cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; + pthread_mutex_unlock(&rxBufferMutex); +} +/** + * @brief getCommand gets a command from an internal circular buffer. + * @param response location to write command + * @return 1 if response was returned, 0 if nothing has been received + */ +static int getCommand(UsbCommand* response) { + pthread_mutex_lock(&rxBufferMutex); + //If head == tail, there's nothing to read, or if we just got initialized + if (cmd_head == cmd_tail) { + pthread_mutex_unlock(&rxBufferMutex); + return 0; + } + + //Pick out the next unread command + UsbCommand* last_unread = &rxBuffer[cmd_tail]; + memcpy(response, last_unread, sizeof(UsbCommand)); + + //Increment tail - this is a circular buffer, so modulo buffer size + cmd_tail = (cmd_tail +1 ) % CMD_BUFFER_SIZE; + + pthread_mutex_unlock(&rxBufferMutex); + return 1; +} + + +//----------------------------------------------------------------------------- +// Entry point into our code: called whenever we received a packet over USB +// that we weren't necessarily expecting, for example a debug print. +//----------------------------------------------------------------------------- +static void UsbCommandReceived(UsbCommand* c) { + + switch(c->cmd) { + // First check if we are handling a debug message + case CMD_DEBUG_PRINT_STRING: { + + char s[USB_CMD_DATA_SIZE+1]; + memset(s, 0x00, sizeof(s)); + size_t len = MIN(c->arg[0], USB_CMD_DATA_SIZE); + memcpy(s, c->d.asBytes, len); + + + //#define FLAG_RAWPRINT 0x0111 + //#define FLAG_NOOPT 0x0000 + //#define FLAG_NOLOG 0x0001 + //#define FLAG_NONEWLINE 0x0010 + //#define FLAG_NOPROMPT 0x0100 + uint64_t flag = c->arg[1]; + if (flag > 0) { // FLAG_RAWPRINT) { + switch (flag) { + case FLAG_RAWPRINT: + printf("%s", s); + return; + case FLAG_NONEWLINE: + printf("%s\r", s); + return; + case FLAG_NOLOG: + printf("%s\r\n", s); + return; + } + fflush(stdout); + return; + } + + // print debug line on same row. escape seq \r + if ( c->arg[1] == CMD_MEASURE_ANTENNA_TUNING_HF) { + PrintAndLogEx(NORMAL, "\r#db# %s", s); + } else { + PrintAndLogEx(NORMAL, "#db# %s", s); + } + fflush(NULL); + break; + } + case CMD_DEBUG_PRINT_INTEGERS: { + PrintAndLogEx(NORMAL, "#db# %08x, %08x, %08x", c->arg[0], c->arg[1], c->arg[2]); + break; + } + // iceman: hw status - down the path on device, runs printusbspeed which starts sending a lot of + // CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K packages which is not dealt with. I wonder if simply ignoring them will + // work. lets try it. + default: { + storeCommand(c); + break; + } + } +} + +/* +bool hookUpPM3() { + bool ret = false; + sp = uart_open( comport ); + + if (sp == INVALID_SERIAL_PORT) { + PrintAndLogEx(WARNING, "Reconnect failed, retrying... (reason: invalid serial port)\n"); + sp = NULL; + serial_port_name = NULL; + ret = false; + offline = 1; + } else if (sp == CLAIMED_SERIAL_PORT) { + PrintAndLogEx(WARNING, "Reconnect failed, retrying... (reason: serial port is claimed by another process)\n"); + sp = NULL; + serial_port_name = NULL; + ret = false; + offline = 1; + } else { + PrintAndLogEx(SUCCESS, "Proxmark reconnected\n"); + serial_port_name = ; + ret = true; + offline = 0; + } + return ret; +} +*/ + +void +#ifdef __has_attribute +#if __has_attribute(force_align_arg_pointer) +__attribute__((force_align_arg_pointer)) +#endif +#endif +*uart_communication(void *targ) { + communication_arg_t *conn = (communication_arg_t*)targ; + size_t rxlen; + UsbCommand rx; + UsbCommand *prx = ℞ + + //int counter_to_offline = 0; + + while (conn->run) { + rxlen = 0; + bool ACK_received = false; + if (uart_receive(sp, (uint8_t *)prx, sizeof(UsbCommand) - (prx - &rx), &rxlen) && rxlen) { + prx += rxlen; + + if (prx - &rx < sizeof(UsbCommand)) { + PrintAndLogEx(NORMAL, "Foo %d | %d (will loop)", prx - &rx, rxlen); + continue; + } + UsbCommandReceived(&rx); + if (rx.cmd == CMD_ACK) { + ACK_received = true; + } + } + prx = ℞ + + pthread_mutex_lock(&txBufferMutex); + + if (conn->block_after_ACK) { + // if we just received an ACK, wait here until a new command is to be transmitted + if (ACK_received) { + while (!txBuffer_pending) { + pthread_cond_wait(&txBufferSig, &txBufferMutex); + } + } + } + + if (txBuffer_pending) { + if (!uart_send(sp, (uint8_t*) &txBuffer, sizeof(UsbCommand))) { + //counter_to_offline++; + PrintAndLogEx(WARNING, "sending bytes to proxmark failed"); + } + txBuffer_pending = false; + + // tell main thread that txBuffer is empty + pthread_cond_signal(&txBufferSig); + } + + pthread_mutex_unlock(&txBufferMutex); + } + + // when this reader thread dies, we close the serial port. + uart_close(sp); + + pthread_exit(NULL); + return NULL; +} + +bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode) { + + char *portname = (char *)port; + if (!wait_for_port) { + sp = uart_open(portname); + } else { + PrintAndLogEx(SUCCESS, "Waiting for Proxmark to appear on " _YELLOW_(%s), portname); + fflush(stdout); + int openCount = 0; + do { + sp = uart_open(portname); + msleep(500); + printf("."); fflush(stdout); + } while (++openCount < timeout && (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT)); + //PrintAndLogEx(NORMAL, "\n"); + } + + // check result of uart opening + if (sp == INVALID_SERIAL_PORT) { + PrintAndLogEx(WARNING, _RED_(ERROR:) "invalid serial port"); + sp = NULL; + serial_port_name = NULL; + return false; + } else if (sp == CLAIMED_SERIAL_PORT) { + PrintAndLogEx(WARNING, _RED_(ERROR:) "serial port is claimed by another process"); + sp = NULL; + serial_port_name = NULL; + return false; + } else { + // start the USB communication thread + serial_port_name = portname; + conn.run = true; + conn.block_after_ACK = flash_mode; + pthread_create(&USB_communication_thread, NULL, &uart_communication, &conn); + //pthread_create(&FPC_communication_thread, NULL, &uart_communication, &conn); + + fflush(NULL); + // create a mutex to avoid interlacing print commands from our different threads + //pthread_mutex_init(&print_lock, NULL); + return true; + } +} + +void CloseProxmark(void) { + conn.run = false; + pthread_join(USB_communication_thread, NULL); + //pthread_join(FPC_communication_thread, NULL); + + if (sp) { + uart_close(sp); + } + +#if defined(__linux__) && !defined(NO_UNLINK) + // Fix for linux, it seems that it is extremely slow to release the serial port file descriptor /dev/* + // + // This may be disabled at compile-time with -DNO_UNLINK (used for a JNI-based serial port on Android). + if (serial_port_name) { + unlink(serial_port_name); + } +#endif + + // Clean up our state + sp = NULL; + serial_port_name = NULL; +} + +/** + * @brief Waits for a certain response type. This method waits for a maximum of + * ms_timeout milliseconds for a specified response command. + + * @param cmd command to wait for, or CMD_UNKNOWN to take any command. + * @param response struct to copy received command into. + * @param ms_timeout display message after 3 seconds + * @param show_warning display message after 3 seconds + * @return true if command was returned, otherwise false + */ +bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning) { + + UsbCommand resp; + + if (response == NULL) + response = &resp; + + uint64_t start_time = msclock(); + + // Wait until the command is received + while (true) { + + while ( getCommand(response) ) { + if (cmd == CMD_UNKNOWN || response->cmd == cmd) + return true; + } + + if (msclock() - start_time > ms_timeout) + break; + + if (msclock() - start_time > 3000 && show_warning) { + // 3 seconds elapsed (but this doesn't mean the timeout was exceeded) + PrintAndLogEx(NORMAL, "Waiting for a response from the proxmark..."); + PrintAndLogEx(NORMAL, "You can cancel this operation by pressing the pm3 button"); + show_warning = false; + } + } + return false; +} + +bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout) { + return WaitForResponseTimeoutW(cmd, response, ms_timeout, true); +} + +bool WaitForResponse(uint32_t cmd, UsbCommand* response) { + return WaitForResponseTimeoutW(cmd, response, -1, true); +} + +/** +* Data transfer from Proxmark to client. This method times out after +* ms_timeout milliseconds. +* @brief GetFromDevice +* @param memtype Type of memory to download from proxmark +* @param dest Destination address for transfer +* @param bytes number of bytes to be transferred +* @param start_index offset into Proxmark3 BigBuf[] +* @param response struct to copy last command (CMD_ACK) into +* @param ms_timeout timeout in milliseconds +* @param show_warning display message after 2 seconds +* @return true if command was returned, otherwise false +*/ +bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint32_t start_index, UsbCommand *response, size_t ms_timeout, bool show_warning) { + + if (dest == NULL) return false; + if (bytes == 0) return true; + + UsbCommand resp; + if (response == NULL) + response = &resp; + + // clear + clearCommandBuffer(); + + switch (memtype) { + case BIG_BUF: { + UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {start_index, bytes, 0}}; + SendCommand(&c); + return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K); + } + case BIG_BUF_EML: { + UsbCommand c = {CMD_DOWNLOAD_EML_BIGBUF, {start_index, bytes, 0}}; + SendCommand(&c); + return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_DOWNLOADED_EML_BIGBUF); + } + case FLASH_MEM: { + UsbCommand c = {CMD_FLASHMEM_DOWNLOAD, {start_index, bytes, 0}}; + SendCommand(&c); + return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_FLASHMEM_DOWNLOADED); + } + case SIM_MEM: { + //UsbCommand c = {CMD_DOWNLOAND_SIM_MEM, {start_index, bytes, 0}}; + //SendCommand(&c); + //return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_DOWNLOADED_SIMMEM); + return false; + } + } + return false; +} + +bool dl_it(uint8_t *dest, uint32_t bytes, uint32_t start_index, UsbCommand *response, size_t ms_timeout, bool show_warning, uint32_t rec_cmd) { + + uint32_t bytes_completed = 0; + uint64_t start_time = msclock(); + + while (true) { + + if (getCommand(response)) { + + // sample_buf is a array pointer, located in data.c + // arg0 = offset in transfer. Startindex of this chunk + // arg1 = length bytes to transfer + // arg2 = bigbuff tracelength (?) + if (response->cmd == rec_cmd) { + + uint32_t offset = response->arg[0]; + uint32_t copy_bytes = MIN(bytes - bytes_completed, response->arg[1]); + //uint32_t tracelen = c->arg[2]; + + // extended bounds check1. upper limit is USB_CMD_DATA_SIZE + // shouldn't happen + copy_bytes = MIN(copy_bytes, USB_CMD_DATA_SIZE); + + // extended bounds check2. + if ( offset + copy_bytes > bytes ) { + PrintAndLogEx(FAILED, "ERROR: Out of bounds when downloading from device, offset %u | len %u | total len %u > buf_size %u", offset, copy_bytes, offset+copy_bytes, bytes); + break; + } + + memcpy(dest + offset, response->d.asBytes, copy_bytes); + bytes_completed += copy_bytes; + } else if (response->cmd == CMD_ACK) { + return true; + } + } + + if (msclock() - start_time > ms_timeout) { + PrintAndLogEx(FAILED, "Timed out while trying to download data from device"); + break; + } + + if (msclock() - start_time > 3000 && show_warning) { + // 3 seconds elapsed (but this doesn't mean the timeout was exceeded) + PrintAndLogEx(NORMAL, "Waiting for a response from the proxmark..."); + PrintAndLogEx(NORMAL, "You can cancel this operation by pressing the pm3 button"); + show_warning = false; + } + } + return false; +} diff --git a/client/comms.h b/client/comms.h new file mode 100644 index 000000000..eba0d45d5 --- /dev/null +++ b/client/comms.h @@ -0,0 +1,67 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2009 Michael Gernoth +// Copyright (C) 2010 iZsh +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Code for communicating with the proxmark3 hardware. +//----------------------------------------------------------------------------- + +#ifndef COMMS_H_ +#define COMMS_H_ + +#include +#include + +#include "usb_cmd.h" +#include "uart.h" +#include "ui.h" +#include "common.h" +#include "util_posix.h" +#include "util.h" + +#if defined(__linux__) && !defined(NO_UNLINK) +#include // for unlink() +#endif + +//For storing command that are received from the device +#ifndef CMD_BUFFER_SIZE +#define CMD_BUFFER_SIZE 100 +#endif + +typedef enum { + BIG_BUF, + BIG_BUF_EML, + FLASH_MEM, + SIM_MEM, + } DeviceMemType_t; + +typedef struct { + bool run; // If TRUE, continue running the uart_communication thread + bool block_after_ACK; // if true, block after receiving an ACK package +} communication_arg_t; + + +bool dl_it(uint8_t *dest, uint32_t bytes, uint32_t start_index, UsbCommand *response, size_t ms_timeout, bool show_warning, uint32_t rec_cmd); + +void SetOffline(bool value); +bool IsOffline(); + +void *uart_receiver(void *targ); +void SendCommand(UsbCommand *c); +void clearCommandBuffer(); + +bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode); +void CloseProxmark(void); + +bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning); +bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout); +bool WaitForResponse(uint32_t cmd, UsbCommand* response); + +extern bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint32_t start_index, UsbCommand *response, size_t ms_timeout, bool show_warning); + +#endif + + diff --git a/client/flash.c b/client/flash.c index ed58c1153..de6fdf7e6 100644 --- a/client/flash.c +++ b/client/flash.c @@ -10,11 +10,6 @@ #include "flash.h" -void SendCommand(UsbCommand* txcmd); -void ReceiveCommand(UsbCommand* rxcmd); -void CloseProxmark(); -int OpenProxmark(); - #define FLASH_START 0x100000 #ifdef HAS_512_FLASH @@ -192,12 +187,12 @@ int flash_load(flash_file_t *ctx, const char *name, int can_write_bl) { fd = fopen(name, "rb"); if (!fd) { - fprintf(stderr, "Could not open file '%s': ", name); + fprintf(stderr, _RED_(Could not open file) "%s >>> ", name); perror(NULL); goto fail; } - fprintf(stdout, "Loading ELF file '%s'...\n", name); + fprintf(stdout, _BLUE_(Loading ELF file) "%s\n", name); if (fread(&ehdr, sizeof(ehdr), 1, fd) != 1) { fprintf(stderr, "Error while reading ELF file header\n"); @@ -268,7 +263,7 @@ static int get_proxmark_state(uint32_t *state) { UsbCommand c = {CMD_DEVICE_INFO}; SendCommand(&c); UsbCommand resp; - ReceiveCommand(&resp); + WaitForResponse(CMD_UNKNOWN, &resp); // wait for any response. No timeout. // Three outcomes: // 1. The old bootrom code will ignore CMD_DEVICE_INFO, but respond with an ACK @@ -286,7 +281,7 @@ static int get_proxmark_state(uint32_t *state) { *state = resp.arg[0]; break; default: - fprintf(stderr, "Error: Couldn't get proxmark state, bad response type: 0x%04" PRIx64 "\n", resp.cmd); + fprintf(stderr, _RED_(Error:) "Couldn't get proxmark state, bad response type: 0x%04" PRIx64 "\n", resp.cmd); return -1; break; } @@ -305,7 +300,7 @@ static int enter_bootloader(char *serial_port_name) { return 0; if (state & DEVICE_INFO_FLAG_CURRENT_MODE_OS) { - fprintf(stdout, "Entering bootloader...\n"); + fprintf(stdout, _BLUE_(Entering bootloader...) "\n"); UsbCommand c; memset(&c, 0, sizeof (c)); @@ -325,21 +320,22 @@ static int enter_bootloader(char *serial_port_name) { msleep(100); CloseProxmark(); - fprintf(stdout, "Waiting for Proxmark to reappear on %s", serial_port_name); - do { - msleep(1000); - fprintf(stdout, "."); fflush(stdout); - } while ( !OpenProxmark()); - fprintf(stdout, " Found.\n"); - return 0; + bool opened = OpenProxmark(serial_port_name, true, 60, true); + if (opened) { + fprintf(stdout, " " _GREEN_(Found) "\n"); + return 0; + } else { + fprintf(stdout, _RED_(Error:) "Proxmark not found.\n"); + return -1; + } } - fprintf(stderr, "Error: Unknown Proxmark mode\n"); + fprintf(stderr, _RED_(Error:) "Unknown Proxmark mode\n"); return -1; } static int wait_for_ack(UsbCommand *ack) { - ReceiveCommand(ack); + WaitForResponse(CMD_UNKNOWN, ack); if (ack->cmd != CMD_ACK) { printf("Error: Unexpected reply 0x%04" PRIx64 " %s (expected ACK)\n", @@ -378,10 +374,9 @@ int flash_start_flashing(int enable_bl_writes, char *serial_port_name) { SendCommand(&c); return wait_for_ack(&c); } else { - fprintf(stderr, "Note: Your bootloader does not understand the new START_FLASH command\n"); - fprintf(stderr, " It is recommended that you update your bootloader\n\n"); + fprintf(stderr, _RED_(Note: Your bootloader does not understand the new START_FLASH command) "\n"); + fprintf(stderr, _RED_( It is recommended that you update your bootloader) "\n\n"); } - return 0; } @@ -439,7 +434,7 @@ int flash_write(flash_file_t *ctx) { block++; fprintf(stdout, "."); fflush(stdout); } - fprintf(stdout, " OK\n"); + fprintf(stdout, _GREEN_(OK) "\n"); fflush(stdout); } return 0; diff --git a/client/flash.h b/client/flash.h index ec93a2787..5372df089 100644 --- a/client/flash.h +++ b/client/flash.h @@ -21,6 +21,8 @@ #include "usb_cmd.h" #include "at91sam7s512.h" #include "util_posix.h" +#include "util.h" +#include "comms.h" typedef struct { void *data; diff --git a/client/flasher.c b/client/flasher.c index 48e66d8f9..a20b264b9 100644 --- a/client/flasher.c +++ b/client/flasher.c @@ -10,31 +10,16 @@ #include #include #include +#include #include "util_posix.h" #include "proxmark3.h" +#include "util.h" #include "flash.h" -#include "uart.h" +#include "comms.h" #include "usb_cmd.h" #define MAX_FILES 4 -#ifdef _WIN32 -# define unlink(x) -#else -# include -#endif - -#if defined (_WIN32) -#define SERIAL_PORT_H "com3" -#elif defined(__APPLE__) -#define SERIAL_PORT_H "/dev/cu.usbmodem888" -#else -#define SERIAL_PORT_H "/dev/ttyACM0" -#endif - -static serial_port sp; -static char* serial_port_name; - void cmd_debug(UsbCommand* c) { // Debug printf("UsbCommand length[len=%zd]\n", sizeof(UsbCommand)); @@ -50,49 +35,6 @@ void cmd_debug(UsbCommand* c) { printf("...\n"); } -void SendCommand(UsbCommand* txcmd) { - // printf("send: "); - // cmd_debug(txcmd); - if (!uart_send(sp, (byte_t*)txcmd, sizeof(UsbCommand))) { - printf("Sending bytes to proxmark failed\n"); - exit(1); - } -} - -void ReceiveCommand(UsbCommand* rxcmd) { - byte_t* prxcmd = (byte_t*)rxcmd; - byte_t* prx = prxcmd; - size_t rxlen; - while (true) { - if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-prxcmd), &rxlen)) { - prx += rxlen; - if ((prx-prxcmd) >= sizeof(UsbCommand)) { - return; - } - } - } -} - -void CloseProxmark() { - // Clean up the port - uart_close(sp); - // Fix for linux, it seems that it is extremely slow to release the serial port file descriptor /dev/* - unlink(serial_port_name); -} - -int OpenProxmark() { - sp = uart_open(serial_port_name); - - //poll once a second - if (sp == INVALID_SERIAL_PORT) { - return 0; - } else if (sp == CLAIMED_SERIAL_PORT) { - fprintf(stderr, "ERROR: serial port is claimed by another process\n"); - return 0; - } - return 1; -} - static void usage(char *argv0) { fprintf(stdout, "Usage: %s [-b] image.elf [image.elf...]\n\n", argv0); fprintf(stdout, "\t-b\tEnable flashing of bootloader area (DANGEROUS)\n\n"); @@ -129,30 +71,28 @@ int main(int argc, char **argv) { } } else { res = flash_load(&files[num_files], argv[i], can_write_bl); - if (res < 0) { - fprintf(stderr, "Error while loading %s\n", argv[i]); + if (res < 0) return -1; - } + fprintf(stderr, "\n"); num_files++; } } + + char* serial_port_name = argv[1]; - serial_port_name = argv[1]; - - fprintf(stdout, "Waiting for Proxmark to appear on %s", serial_port_name); - do { - msleep(500); - fprintf(stderr, "."); fflush(stdout); - } while (!OpenProxmark()); - - fprintf(stdout, " Found.\n"); + if (!OpenProxmark(serial_port_name, true, 60, true)) { + fprintf(stderr, "Could not find Proxmark on " _RED_(%s) ".\n\n", serial_port_name); + return -1; + } else { + fprintf(stderr, _GREEN_(Found) "\n"); + } res = flash_start_flashing(can_write_bl, serial_port_name); if (res < 0) return -1; - fprintf(stdout, "\nFlashing...\n"); + fprintf(stdout, "\n" _BLUE_(Flashing...)"\n"); for (int i = 0; i < num_files; i++) { res = flash_write(&files[i]); @@ -162,7 +102,7 @@ int main(int argc, char **argv) { fprintf(stdout, "\n"); } - fprintf(stdout, "Resetting hardware...\n"); + fprintf(stdout, _BLUE_(Resetting hardware...) "\n"); res = flash_stop_flashing(); if (res < 0) @@ -170,7 +110,6 @@ int main(int argc, char **argv) { CloseProxmark(); - fprintf(stdout, "All done.\n\n"); - fprintf(stdout, "Have a nice day!\n"); + fprintf(stdout, _BLUE_(All done.) "\n\nHave a nice day!\n"); return 0; } diff --git a/client/proxmark3.c b/client/proxmark3.c index b7dffe6e7..78230bd36 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -17,55 +17,16 @@ #include #include #include + +#include "util_posix.h" #include "proxgui.h" #include "cmdmain.h" -#include "uart.h" #include "ui.h" #include "util.h" #include "cmdparser.h" #include "cmdhw.h" #include "whereami.h" - -#if defined (_WIN32) -#define SERIAL_PORT_H "com3" -#elif defined(__APPLE__) -#define SERIAL_PORT_H "/dev/cu.usbmodem888" -#else -#define SERIAL_PORT_H "/dev/ttyACM0" -#endif - -static serial_port sp; -static UsbCommand txcmd; -static char comport[255]; -byte_t rx[sizeof(UsbCommand)]; -byte_t* prx = rx; -volatile static bool txcmd_pending = false; -struct receiver_arg { - int run; -}; - -void SendCommand(UsbCommand *c) { - #if 0 - //pthread_mutex_lock(&print_lock); - PrintAndLogEx(NORMAL, "Sending %d bytes\n", sizeof(UsbCommand)); - //pthread_mutex_unlock(&print_lock); - #endif - - if (offline) { - PrintAndLogEx(NORMAL, "Sending bytes to proxmark failed - offline"); - return; - } - /** - The while-loop below causes hangups at times, when the pm3 unit is unresponsive - or disconnected. The main console thread is alive, but comm thread just spins here. - Not good.../holiman - **/ - while (txcmd_pending); - - txcmd = *c; - __atomic_test_and_set(&txcmd_pending, __ATOMIC_SEQ_CST); -} - +#include "comms.h" #if defined(__linux__) || (__APPLE__) static void showBanner(void){ @@ -83,84 +44,6 @@ static void showBanner(void){ } #endif -bool hookUpPM3() { - bool ret = false; - sp = uart_open( comport ); - - //pthread_mutex_lock(&print_lock); - - if (sp == INVALID_SERIAL_PORT) { - PrintAndLogEx(WARNING, "Reconnect failed, retrying... (reason: invalid serial port)\n"); - sp = NULL; - ret = false; - offline = 1; - } else if (sp == CLAIMED_SERIAL_PORT) { - PrintAndLogEx(WARNING, "Reconnect failed, retrying... (reason: serial port is claimed by another process)\n"); - sp = NULL; - ret = false; - offline = 1; - } else { - PrintAndLogEx(SUCCESS, "Proxmark reconnected\n"); - ret = true; - offline = 0; - } - //pthread_mutex_unlock(&print_lock); - return ret; -} - -// (iceman) if uart_receiver fails a command three times, we conside the device to be offline. -void -#ifdef __has_attribute -#if __has_attribute(force_align_arg_pointer) -__attribute__((force_align_arg_pointer)) -#endif -#endif -*uart_receiver(void *targ) { - struct receiver_arg *arg = (struct receiver_arg*)targ; - size_t rxlen; - bool tmpsignal; - int counter_to_offline = 0; - - while (arg->run) { - rxlen = 0; - - if (uart_receive(sp, prx, sizeof(UsbCommand) - (prx-rx), &rxlen)) { - - if ( rxlen == 0 ) continue; - - prx += rxlen; - if ( (prx-rx) < sizeof(UsbCommand)) { - continue; - } - - UsbCommandReceived((UsbCommand*)rx); - } - prx = rx; - - __atomic_load(&txcmd_pending, &tmpsignal, __ATOMIC_SEQ_CST); - if ( tmpsignal ) { - bool res = uart_send(sp, (byte_t*) &txcmd, sizeof(UsbCommand)); - if (!res) { - counter_to_offline++; - PrintAndLogEx(NORMAL, "sending bytes to proxmark failed"); - } - __atomic_clear(&txcmd_pending, __ATOMIC_SEQ_CST); - - // set offline flag - if ( counter_to_offline == 3 ) { - __atomic_test_and_set(&offline, __ATOMIC_SEQ_CST); - break; - } - } - } - - // when this reader thread dies, we close the serial port. - uart_close(sp); - - pthread_exit(NULL); - return NULL; -} - void #ifdef __has_attribute #if __has_attribute(force_align_arg_pointer) @@ -169,9 +52,7 @@ __attribute__((force_align_arg_pointer)) #endif main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { - struct receiver_arg rarg; char *cmd = NULL; - pthread_t reader_thread; bool execCommand = (script_cmd != NULL); bool stdinOnPipe = !isatty(STDIN_FILENO); FILE *sf = NULL; @@ -180,13 +61,14 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { PrintAndLogEx(DEBUG, "ISATTY/STDIN_FILENO == %s\n", (stdinOnPipe) ? "true" : "false"); if (usb_present) { - rarg.run = 1; - pthread_create(&reader_thread, NULL, &uart_receiver, &rarg); + SetOffline(false); // cache Version information now: if ( execCommand || script_cmds_file || stdinOnPipe) CmdVersion("s"); else CmdVersion(""); + } else { + SetOffline(true); } if (script_cmds_file) { @@ -202,13 +84,14 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { while (1) { // this should hook up the PM3 again. - if (offline) { + /* + if ( IsOffline() ) { // sets the global variable, SP and offline) usb_present = hookUpPM3(); // usb and the reader_thread is NULL, create a new reader thread. - if (usb_present && !offline) { + if (usb_present && !IsOffline() ) { rarg.run = 1; pthread_create(&reader_thread, NULL, &uart_receiver, &rarg); // cache Version information now: @@ -218,6 +101,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { CmdVersion(""); } } + */ // If there is a script file if (sf) { @@ -304,11 +188,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { free(cmd); cmd = NULL; - - if (usb_present) { - rarg.run = 0; - pthread_join(reader_thread, NULL); - } + } static void dumpAllHelp(int markdown) { @@ -346,7 +226,7 @@ static void set_my_executable_path(void) { } static void show_help(bool showFullHelp, char *command_line){ - PrintAndLogEx(NORMAL, "syntax: %s [-h|-help|-m|-f|-flush|-w|-wait|-c|-command|-l|-lua] [cmd_script_file_name] [command][lua_script_name]\n", command_line); + PrintAndLogEx(NORMAL, "syntax: %s [-h | -help | -m | -f | -flush | -w | -wait | -c | -command | -l | -lua] [cmd_script_file_name] [command][lua_script_name]\n", command_line); PrintAndLogEx(NORMAL, "\texample:'%s "SERIAL_PORT_H"'\n\n", command_line); if (showFullHelp){ @@ -384,10 +264,6 @@ int main(int argc, char* argv[]) { show_help(true, argv[0]); return 1; } - - // lets copy the comport string. - memset(comport, 0, sizeof(comport)); - memcpy(comport, argv[1], strlen(argv[1])); for (int i = 1; i < argc; i++) { @@ -406,7 +282,7 @@ int main(int argc, char* argv[]) { // flush output if(strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "-flush") == 0){ - g_flushAfterWrite = 1; + SetFlushAfterWrite(true); PrintAndLogEx(INFO, "Output will be flushed after every print.\n"); } @@ -474,39 +350,11 @@ int main(int argc, char* argv[]) { // set global variables set_my_executable_path(); - // open uart - if (!waitCOMPort) { - sp = uart_open(argv[1]); - } else { - PrintAndLogEx(SUCCESS, "waiting for Proxmark to appear on %s ", argv[1]); - fflush(stdout); - int openCount = 0; - do { - sp = uart_open(argv[1]); - msleep(500); - printf("."); fflush(stdout); - } while (++openCount < 30 && (sp == INVALID_SERIAL_PORT || sp == CLAIMED_SERIAL_PORT)); - PrintAndLogEx(NORMAL, "\n"); - } - - // check result of uart opening - if (sp == INVALID_SERIAL_PORT) { - PrintAndLogEx(WARNING, "ERROR: invalid serial port"); - usb_present = false; - offline = 1; - } else if (sp == CLAIMED_SERIAL_PORT) { - PrintAndLogEx(WARNING, "ERROR: serial port is claimed by another process"); - usb_present = false; - offline = 1; - } else { - usb_present = true; - offline = 0; - } - - fflush(NULL); - // create a mutex to avoid interlacing print commands from our different threads - pthread_mutex_init(&print_lock, NULL); + // try to open USB connection to Proxmark + usb_present = OpenProxmark(argv[1], waitCOMPort, 20, false); + + printf("\x1b[31m test\n"); #ifdef HAVE_GUI # ifdef _WIN32 @@ -527,8 +375,10 @@ int main(int argc, char* argv[]) { main_loop(script_cmds_file, script_cmd, usb_present); #endif - // clean up mutex - pthread_mutex_destroy(&print_lock); + // Clean up the port + if (usb_present) { + CloseProxmark(); + } exit(0); } \ No newline at end of file diff --git a/client/proxmark3.h b/client/proxmark3.h index c68e8275c..0a69e71ba 100644 --- a/client/proxmark3.h +++ b/client/proxmark3.h @@ -21,14 +21,10 @@ extern "C" { #endif -void SendCommand(UsbCommand *c); const char *get_my_executable_path(void); const char *get_my_executable_directory(void); void main_loop(char *script_cmds_file, char *script_cmd, bool usb_present); -bool hookUpPM3(void); -void *uart_receiver(void *targ); - #ifdef __cplusplus } #endif diff --git a/client/scripting.h b/client/scripting.h index feb611549..a6aaf157a 100644 --- a/client/scripting.h +++ b/client/scripting.h @@ -17,6 +17,7 @@ #include "proxmark3.h" #include "usb_cmd.h" #include "cmdmain.h" +#include "comms.h" #include "util.h" #include "mifarehost.h" #include "crc.h" diff --git a/client/ui.c b/client/ui.c index ba2e028a0..a8b45273d 100644 --- a/client/ui.c +++ b/client/ui.c @@ -13,8 +13,7 @@ double CursorScaleFactor = 1; int PlotGridX=0, PlotGridY=0, PlotGridXdefault= 64, PlotGridYdefault= 64, CursorCPos= 0, CursorDPos= 0; -int offline; -int g_flushAfterWrite = 0; //buzzy +bool flushAfterWrite = 0; int GridOffset = 0; bool GridLocked = false; bool showDemod = true; @@ -178,7 +177,7 @@ void PrintAndLog(char *fmt, ...) { } va_end(argptr2); - if (g_flushAfterWrite == 1) + if (flushAfterWrite) fflush(NULL); //release lock @@ -189,7 +188,11 @@ void SetLogFilename(char *fn) { logfilename = fn; } -void iceIIR_Butterworth(int *data, const size_t len){ +void SetFlushAfterWrite(bool value) { + flushAfterWrite = value; +} + + void iceIIR_Butterworth(int *data, const size_t len){ int i,j; diff --git a/client/ui.h b/client/ui.h index 6d59393b0..fc3439033 100644 --- a/client/ui.h +++ b/client/ui.h @@ -37,14 +37,13 @@ extern void PrintAndLog(char *fmt, ...); void PrintAndLogOptions(char *str[][2], size_t size, size_t space); void PrintAndLogEx(logLevel_t level, char *fmt, ...); extern void SetLogFilename(char *fn); +void SetFlushAfterWrite(bool value); extern double CursorScaleFactor; extern int PlotGridX, PlotGridY, PlotGridXdefault, PlotGridYdefault, CursorCPos, CursorDPos, GridOffset; extern bool GridLocked; extern bool showDemod; -extern int offline; -extern int g_flushAfterWrite; //buzzy //extern uint8_t g_debugMode; extern pthread_mutex_t print_lock; diff --git a/common/cmd.c b/common/cmd.c index 3aa6870ee..281ff0065 100644 --- a/common/cmd.c +++ b/common/cmd.c @@ -31,29 +31,9 @@ */ #include "cmd.h" -bool cmd_receive(UsbCommand* cmd) { - - // Check if there is a usb packet available - if (!usb_poll_validate_length()) return false; - - // Try to retrieve the available command frame - usb_read((uint8_t*)cmd, sizeof(UsbCommand)); - - // (iceman) this check is wrong. Since USB can send packages which is not sizeof(usbcommand) 544 bytes. - // hence, I comment it out - - // Check if the transfer was complete - //if (rxlen != sizeof(UsbCommand)) return false; - // Received command successfully - //return true; - return true; -} - -bool cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void* data, size_t len) { - +uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void* data, size_t len) { UsbCommand txcmd; - // 0x00 the whole command. for (size_t i=0; i < sizeof(UsbCommand); i++) ((uint8_t*)&txcmd)[i] = 0x00; @@ -70,10 +50,15 @@ bool cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void* d txcmd.d.asBytes[i] = ((uint8_t*)data)[i]; } } - - // Send frame and make sure all bytes are transmitted - if ( usb_write( (uint8_t*)&txcmd, sizeof(UsbCommand)) != 0) - return false; - return true; + uint32_t sendlen = 0; + // Send frame and make sure all bytes are transmitted + sendlen = usb_write( (uint8_t*)&txcmd, sizeof(UsbCommand) ); + +#ifdef WITH_FPC + usart_init(); + usart_writebuffer( (uint8_t*)&txcmd, sizeof(UsbCommand) ); +#endif + + return sendlen; } \ No newline at end of file diff --git a/common/cmd.h b/common/cmd.h index 0fd2cc142..9aa6bec33 100644 --- a/common/cmd.h +++ b/common/cmd.h @@ -39,8 +39,7 @@ #include "usart.h" #include "proxmark3.h" -bool cmd_receive(UsbCommand* cmd); -bool cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void* data, size_t len); +uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void* data, size_t len); #endif // _PROXMARK_CMD_H_ diff --git a/common/usart.c b/common/usart.c index e8e613ddf..b58a7cbaa 100644 --- a/common/usart.c +++ b/common/usart.c @@ -1,17 +1,23 @@ +//----------------------------------------------------------------------------- +// Iceman, July 2018 +// edists by - Anticat, August 2018 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// The main USART code, for serial communications over FPC connector +//----------------------------------------------------------------------------- #include "usart.h" -#include "apps.h" +#include "string.h" -#define USART_INTERRUPT_LEVEL 7 #define AT91_BAUD_RATE 115200 -volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_US1; volatile AT91PS_USART pUS1 = AT91C_BASE_US1; -volatile AT91PS_AIC pAIC = AT91C_BASE_AIC; volatile AT91PS_PIO pPIOA = AT91C_BASE_PIOA; +volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_US1; -#define usart_rx_ready {(pUS1->US_CSR & AT91C_US_RXRDY)} -#define usart_tx_ready {(pUS1->US_CSR & AT91C_US_TXRDY)} - +/* void usart_close(void) { // Reset the USART mode pUS1->US_MR = 0; @@ -25,259 +31,155 @@ void usart_close(void) { // Disable all interrupts pUS1->US_IDR = 0xFFFFFFFF; - //* Abort the Peripheral Data Transfers - //AT91F_PDC_Close((AT91PS_PDC) &(pUSART->US_RPR)); + // Abort the Peripheral Data Transfers + pUS1->US_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS; // Disable receiver and transmitter and stop any activity immediately pUS1->US_CR = AT91C_US_TXDIS | AT91C_US_RXDIS | AT91C_US_RSTTX | AT91C_US_RSTRX; } +*/ -/// Reads data from an USART peripheral, filling the provided buffer until it -/// becomes full. This function returns immediately with 1 if the buffer has -/// been queued for transmission; otherwise 0. +static uint8_t outbuf[sizeof(UsbCommand)]; +//static uint8_t inbuf[sizeof(UsbCommand)]; + + +/// Reads data from an USART peripheral /// \param data Pointer to the buffer where the received data will be stored. /// \param len Size of the data buffer (in bytes). -uint8_t usart_readbuffer(uint8_t *data, size_t len) { +inline int usart_readbuffer(uint8_t *data, size_t len) { + + pUS1->US_PTSR = AT91C_PDC_TXTEN; + pUS1->US_PTCR = AT91C_PDC_TXTEN; // Check if the first PDC bank is free - if ((pUS1->US_RCR == 0) && (pUS1->US_RNCR == 0)) { - + if (!(pUS1->US_RCR)) { pUS1->US_RPR = (uint32_t)data; pUS1->US_RCR = len; - pUS1->US_PTCR = AT91C_PDC_RXTEN; - return 1; + return 2; } // Check if the second PDC bank is free - else if (pUS1->US_RNCR == 0) { - + else if (!(pUS1->US_RNCR)) { pUS1->US_RNPR = (uint32_t)data; pUS1->US_RNCR = len; return 1; } else { return 0; } + + /* + pPDC->PDC_PTSR = AT91C_PDC_RXTEN; + pPDC->PDC_PTCR = AT91C_PDC_RXTEN; + + //check if data is available + if (pPDC->PDC_RCR != 0) return -1; + + memcpy(data, inbuf, len); + + //start next transfer + pPDC->PDC_RNPR = (uint32_t)inbuf; + pPDC->PDC_RNCR = sizeof(inbuf); + + return sizeof(inbuf); + */ } +/* +int16_t usart_writebuffer(uint8_t *data, size_t len) { -/// Reads and return a packet of data on the specified USART peripheral. This -/// function operates asynchronously, so it waits until some data has been -/// received. -/// \param timeout Time out value (0 -> no timeout). -uint8_t usart_read(uint32_t timeout) { - if (timeout == 0) { - while ((pUS1->US_CSR & AT91C_US_RXRDY) == 0) {}; - } - else { +// pUS1->US_PTSR = AT91C_PDC_TXTEN; + pUS1->US_PTCR = AT91C_PDC_TXTEN; + + // if buffer is sent + if (pUS1->US_TCR != 0) return -1; + + memcpy(outbuf, data, len); - while ((pUS1->US_CSR & AT91C_US_RXRDY) == 0) { + //start next transfer + pUS1->US_TNPR = (uint32_t)outbuf; + pUS1->US_TNCR = sizeof(outbuf); - if (timeout == 0) { - - DbpString("USART_Read: Timed out."); - return 0; - } - timeout--; - } - } - uint8_t res = pUS1->US_RHR; - Dbprintf(" usar got %02x", res); - return res; + return sizeof(outbuf); } +*/ -/// Sends one packet of data through the specified USART peripheral. This -/// function operates synchronously, so it only returns when the data has been -/// actually sent. -/// \param data Data to send including 9nth bit and sync field if necessary (in -/// the same format as the US_THR register in the datasheet). -/// \param timeOut Time out value (0 = no timeout). -void usart_write( uint8_t data, uint32_t timeout) { - if ( timeout == 0) { - - while ((pUS1->US_CSR & AT91C_US_TXEMPTY) == 0) {}; - - } else { - while ((pUS1->US_CSR & AT91C_US_TXEMPTY) == 0) { - - if (timeout == 0) { - DbpString("USART_Write: Timed out."); - return; - } - timeout--; - } - } - pUS1->US_THR = data; -} - -uint8_t usart_writebuffer(uint8_t *data, size_t len, uint32_t timeout) { +// works. +// transfer to client +inline int16_t usart_writebuffer(uint8_t *data, size_t len) { + pUS1->US_PTSR = AT91C_PDC_TXTEN; + pUS1->US_PTCR = AT91C_PDC_TXTEN; + // Check if the first PDC bank is free - if ((pUS1->US_TCR == 0) && (pUS1->US_TNCR == 0)) { - - pUS1->US_TPR = (uint32_t)data; - pUS1->US_TCR = len; - pUS1->US_PTCR = AT91C_PDC_TXTEN; - return 1; + if (!(pUS1->US_TCR)) { + + memcpy(outbuf, data, len); + + pUS1->US_TPR = (uint32_t)outbuf; + pUS1->US_TCR = sizeof(outbuf); + return 2; } // Check if the second PDC bank is free - else if (pUS1->US_TNCR == 0) { - - pUS1->US_TNPR = (uint32_t)data; - pUS1->US_TNCR = len; - return 1; - } - else { + else if (!(pUS1->US_TNCR)) { + memcpy(outbuf, data, len); + + pUS1->US_TNPR = (uint32_t)outbuf; + pUS1->US_TNCR = sizeof(outbuf); + return 1; + } else { return 0; } } -// interupt version -void Usart_c_irq_handler(void) { - - // get Usart status register - uint32_t status = pUS1->US_CSR; - - if ( status & AT91C_US_RXRDY){ - // Get byte and send - pUS1->US_THR = (pUS1->US_RHR & 0x1FF); - LED_B_INV(); - } - // tx - if ( status & AT91C_US_TXRDY){ - LED_D_INV(); - } - - - if ( status & AT91C_US_OVRE) { - // clear US_RXRDY - (void)(pUS1->US_RHR & 0x1FF); - pUS1->US_THR = ('O' & 0x1FF); - } - - // Check error - if ( status & AT91C_US_PARE) { - pUS1->US_THR = ('P' & 0x1FF); - } - - if ( status & AT91C_US_FRAME) { - pUS1->US_THR = ('F' & 0x1FF); - } - - if ( status & AT91C_US_TIMEOUT){ - pUS1->US_CR = AT91C_US_STTTO; - pUS1->US_THR = ('T' & 0x1FF); - } - - // Reset the status bit - pUS1->US_CR = AT91C_US_RSTSTA; -} - -__inline unsigned int AT91F_AIC_ConfigureIt ( - AT91PS_AIC pAIC, // \arg pointer to the AIC registers - unsigned int irq_id, // \arg interrupt number to initialize - unsigned int priority, // \arg priority to give to the interrupt - unsigned int src_type, // \arg activation and sense of activation - void (*newHandler) (void) ) // \arg address of the interrupt handler -{ - unsigned int oldHandler; - unsigned int mask; - - oldHandler = pAIC->AIC_SVR[irq_id]; - - mask = (0x1 << irq_id); - // Disable the interrupt on the interrupt controller - pAIC->AIC_IDCR = mask; - // Save the interrupt handler routine pointer and the interrupt priority - pAIC->AIC_SVR[irq_id] = (unsigned int) newHandler; - // Store the Source Mode Register - pAIC->AIC_SMR[irq_id] = (src_type | priority); - // Clear the interrupt on the interrupt controller - pAIC->AIC_ICCR = mask; - - return oldHandler; -} - void usart_init(void) { + + // disable & reset receiver / transmitter for configuration + pUS1->US_CR = (AT91C_US_RSTRX | AT91C_US_RSTTX); - // disable & reset receiver / transmitter - pUS1->US_CR = AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS; - - //enable the USART 1 Peripheral clock + //enable the USART1 Peripheral clock AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US1); - - // Configure PIO controllers to peripheral mode A - pPIOA->PIO_ASR = (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); - - // Disable PIO control of the following pins, allows use by the SPI peripheral - pPIOA->PIO_PDR = (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); - // kill pull-ups -// pPIOA->PIO_PPUDR = ~(AT91C_PA21_RXD1 | AT91C_PA22_TXD1); -// pPIOA->PIO_MDDR = (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); + // disable PIO control of receive / transmit pins + pPIOA->PIO_PDR |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); - // Pull-up Enable + // enable peripheral mode A on receive / transmit pins + pPIOA->PIO_ASR |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); + + // enable pull-up on receive / transmit pins (see 31.5.1 I/O Lines) pPIOA->PIO_PPUER |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); - // MultiDriver Enable - //pPIOA->PIO_MDER |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); - - // Enable the pins to be controlled - pPIOA->PIO_PER |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); - - // Configure the pins to be outputs - pPIOA->PIO_OER |= AT91C_PA22_TXD1; - - //enable PIO in input mode - //pPIOA->PIO_ODR = AT91C_PA21_RXD1; // set mode pUS1->US_MR = AT91C_US_USMODE_NORMAL | // normal mode - AT91C_US_CLKS_CLOCK | // MCK + AT91C_US_CLKS_CLOCK | // MCK (48MHz) AT91C_US_CHRL_8_BITS | // 8 bits AT91C_US_PAR_NONE | // parity: none AT91C_US_NBSTOP_1_BIT | // 1 stop bit AT91C_US_CHMODE_NORMAL; // channel mode: normal - // baud rate - // CD = MCK / (16 * baud) - // MCK = 24027428 (pm3 runs on 24MHZ clock PMC_PCKR[0] ) - - - // baudrate 115200 - // 16*115200 = 1843200 - // 24027428 / 1843200 == 13 --< CD - - // baudrate 460800 - // 16*460800 = 7372800 - // 24027428 / 7372800 == 3 - pUS1->US_BRGR = 24*1024*1024/(115200*16); // OVER=0 16 + // set baudrate to 115200 + pUS1->US_BRGR = (48UL*1000*1000) / (115200*16); // Write the Timeguard Register pUS1->US_TTGR = 0; - pUS1->US_RTOR = 0; pUS1->US_FIDI = 0; pUS1->US_IF = 0; - - // Enable USART IT error and RXRDY - // Write to the IER register -// pUS1->US_IER = (AT91C_US_TIMEOUT | AT91C_US_FRAME | AT91C_US_OVRE | AT91C_US_RXRDY); - // open Usart 1 interrupt -/* - AT91F_AIC_ConfigureIt( - pAIC, - AT91C_ID_US1, - USART_INTERRUPT_LEVEL, - AT91C_AIC_SRCTYPE_INT_HIGH_LEVEL, - Usart_c_irq_handler - ); -*/ - - // enable interupt -// pAIC->AIC_IECR = (1 << AT91C_ID_US1); - - // trigger interrup software -// pAIC->AIC_ISCR = (1 << AT91C_ID_US1) ; - - // enable RX + TX - pUS1->US_CR = AT91C_US_RXEN | AT91C_US_TXEN; + /* + //Empty PDC + pUS1->US_RNPR = (uint32_t)(char *)0; + pUS1->US_RNCR = 0; + pUS1->US_RPR = (uint32_t)(char *)0; + pUS1->US_RCR = 0; + pUS1->US_TNPR = (uint32_t)(char *)0; + pUS1->US_TNCR = 0; + pUS1->US_TPR = (uint32_t)(char *)0; + pUS1->US_TCR = 0; + */ + + //pUS1->US_PTCR = (AT91C_PDC_RXTEN | AT91C_PDC_TXTEN); + //pUS1->US_PTSR = (AT91C_PDC_RXTEN | AT91C_PDC_TXTEN); + + // re-enable receiver / transmitter + pUS1->US_CR = (AT91C_US_RXEN | AT91C_US_TXEN); + } \ No newline at end of file diff --git a/common/usart.h b/common/usart.h index 3623451d5..271a24ba4 100644 --- a/common/usart.h +++ b/common/usart.h @@ -4,18 +4,9 @@ #include #include "proxmark3.h" -//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -extern void Dbprintf(const char *fmt, ...); - void usart_init(void); void usart_close(void); -uint32_t usart_rx_ready(); -uint32_t usart_tx_ready(); - -uint8_t usart_read(uint32_t timeout); -uint8_t usart_readbuffer(uint8_t *data, size_t len); - -void usart_write( uint8_t data, uint32_t timeout); -uint8_t usart_writebuffer(uint8_t *data, size_t len, uint32_t timeout); +int usart_readbuffer(uint8_t *data, size_t len); +int16_t usart_writebuffer(uint8_t *data, size_t len); #endif diff --git a/uart/uart.h b/uart/uart.h index ab0f9c076..a1521a58d 100644 --- a/uart/uart.h +++ b/uart/uart.h @@ -41,6 +41,16 @@ #include "common.h" #include "util_posix.h" // msclock + + +#if defined (_WIN32) +#define SERIAL_PORT_H "com3" +#elif defined(__APPLE__) +#define SERIAL_PORT_H "/dev/cu.usbmodem" +#else +#define SERIAL_PORT_H "/dev/ttyACM0" +#endif + /* serial_port is declared as a void*, which you should cast to whatever type * makes sense to your connection method. Both the posix and win32 * implementations define their own structs in place. @@ -78,13 +88,13 @@ void uart_close(const serial_port sp); * partial read may have completed into the buffer by the corresponding * implementation, so pszRxLen should be checked to see if any data was written. */ -bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen); +bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen); /* Sends a buffer to a given serial port. * pbtTx: A pointer to a buffer containing the data to send. * len: The amount of data to be sent. */ -bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t len); +bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t len); /* Sets the current speed of the serial port, in baud. */ diff --git a/uart/uart_posix.c b/uart/uart_posix.c index 33bdc525f..20a577ded 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -117,10 +117,19 @@ serial_port uart_open(const char* pcPortName) // Flush all lingering data that may exist tcflush(sp->fd, TCIOFLUSH); +#ifdef WITH_FPC + uart_set_speed(sp, 115200); + printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n"); +#else // set speed, works for UBUNTU 14.04 - bool err = uart_set_speed(sp, 460800); - if (!err) - uart_set_speed(sp, 115200); + bool success = uart_set_speed(sp, 460800); + if (success) { + printf("[=] UART Setting serial baudrate 460800\n"); + } else { + uart_set_speed(sp, 115200); + printf("[=] UART Setting serial baudrate 115200\n"); + } +#endif return sp; } @@ -144,7 +153,7 @@ void uart_close(const serial_port sp) { free(sp); } -bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen) { +bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen) { int res; int byteCount; fd_set rfds; @@ -156,9 +165,9 @@ bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_ do { // Reset file descriptor FD_ZERO(&rfds); - FD_SET(((serial_port_unix*)sp)->fd,&rfds); + FD_SET(((serial_port_unix*)sp)->fd, &rfds); tv = timeout; - res = select(((serial_port_unix*)sp)->fd+1, &rfds, NULL, NULL, &tv); + res = select(((serial_port_unix*)sp)->fd + 1, &rfds, NULL, NULL, &tv); // Read error if (res < 0) { @@ -186,7 +195,7 @@ bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_ } // There is something available, read the data - res = read(((serial_port_unix*)sp)->fd, pbtRx+(*pszRxLen), byteCount); + res = read(((serial_port_unix*)sp)->fd, pbtRx + (*pszRxLen), byteCount); // Stop if the OS has some troubles reading the data if (res <= 0) return false; @@ -203,7 +212,7 @@ bool uart_receive(const serial_port sp, byte_t* pbtRx, size_t pszMaxRxLen, size_ return true; } -bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t len) { +bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t len) { int32_t res; size_t pos = 0; fd_set rfds; @@ -229,13 +238,10 @@ bool uart_send(const serial_port sp, const byte_t* pbtTx, const size_t len) { } // Send away the bytes - res = write(((serial_port_unix*)sp)->fd, pbtTx+pos, len-pos); + res = write(((serial_port_unix*)sp)->fd, pbtTx + pos, len - pos); // Stop if the OS has some troubles sending the data - if (res <= 0) { - printf("UART:: os troubles (%d)\n", res); - return false; - } + if (res <= 0) return false; pos += res; } diff --git a/uart/uart_win32.c b/uart/uart_win32.c index 7be3a8fe9..eef350cda 100644 --- a/uart/uart_win32.c +++ b/uart/uart_win32.c @@ -47,16 +47,6 @@ typedef struct { DCB dcb; // Device control settings COMMTIMEOUTS ct; // Serial port time-out configuration } serial_port_windows; -/* -void upcase(char *p) { - while(*p != '\0') { - if(*p >= 97 && *p <= 122) { - *p -= 32; - } - ++p; - } -} -*/ serial_port uart_open(const char* pcPortName) { char acPortName[255]; @@ -110,10 +100,17 @@ serial_port uart_open(const char* pcPortName) { PurgeComm(sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR); +#ifdef WITH_FPC + uart_set_speed(sp, 115200); +#else bool success = uart_set_speed(sp, 460800); - if (!success) + if (success) { + printf("[=] UART Setting serial baudrate 460800\n"); + } else { uart_set_speed(sp, 115200); - + printf("[=] UART Setting serial baudrate 115200\n"); + } +#endif return sp; } @@ -155,32 +152,13 @@ uint32_t uart_get_speed(const serial_port sp) { return 0; } -bool uart_receive(const serial_port sp, byte_t* p_rx, size_t pszMaxRxLen, size_t* p_rxlen) { - int res = ReadFile(((serial_port_windows*)sp)->hPort, p_rx, pszMaxRxLen, (LPDWORD)p_rxlen, NULL); - if ( res == 0 ) { - //printf("[!] UART error reading from port\n"); - return false; - } - - bool read_test = ( pszMaxRxLen == *p_rxlen ); - if ( !read_test && *p_rxlen > 0 ) { - printf("[!] UART error, not all data read from port len %u | read %u\n", pszMaxRxLen, *p_rxlen); - } - return read_test; +bool uart_receive(const serial_port sp, uint8_t* p_rx, size_t pszMaxRxLen, size_t* len) { + return ReadFile(((serial_port_windows*)sp)->hPort, p_rx, pszMaxRxLen, (LPDWORD)len, NULL); } -bool uart_send(const serial_port sp, const byte_t* p_tx, const size_t len) { +bool uart_send(const serial_port sp, const uint8_t* p_tx, const size_t len) { DWORD txlen = 0; - int res = WriteFile(((serial_port_windows*)sp)->hPort, p_tx, len, &txlen, NULL); - if ( res == 0) { - printf("[!] UART error writing to port\n"); - return false; - } - bool write_test = ( len == txlen ); - if ( !write_test ) { - printf("[!] UART error, not all data written to port len %u | sent %lu\n", len, txlen); - } - return write_test; + return WriteFile(((serial_port_windows*)sp)->hPort, p_tx, len, &txlen, NULL); } #endif \ No newline at end of file From 3a338f566e6282ac139e79bc1c618aaf40fbe8bd Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 6 Sep 2018 21:44:53 +0200 Subject: [PATCH 0018/1938] chg: zero mean in hidfskdemod chg: idteck demod return values --- common/lfdemod.c | 33 +++++++++++++++++++++++++-------- 1 file changed, 25 insertions(+), 8 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index 81e9135dc..f5a0611f3 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -1697,11 +1697,11 @@ size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t clk, uint8_t invert, u //by marshmellow (from holiman's base) // full fsk demod from GraphBuffer wave to decoded 1s and 0s (no mandemod) -size_t fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, int *startIdx) { +size_t fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, int *start_idx) { if (signalprop.isnoise) return 0; // FSK demodulator - size = fsk_wave_demod(dest, size, fchigh, fclow, startIdx); - size = aggregate_bits(dest, size, rfLen, invert, fchigh, fclow, startIdx); + size = fsk_wave_demod(dest, size, fchigh, fclow, start_idx); + size = aggregate_bits(dest, size, rfLen, invert, fchigh, fclow, start_idx); return size; } @@ -1905,6 +1905,16 @@ int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32 if (signalprop.isnoise) return -2; + // zero mean data + int i, accum = 0; + for (i = 10; i < *size; ++i) + accum += dest[i]; + + accum /= (*size - 10); + + for (i = 0; i < *size; ++i) + dest[i] -= accum; + // FSK demodulator fsk2a so invert and fc/10/8 *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); //hid fsk2a @@ -1943,12 +1953,19 @@ int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32 int detectIdteck(uint8_t *dest, size_t *size) { //make sure buffer has data if (*size < 64*2) return -1; - size_t startIdx = 0; + + if (signalprop.isnoise) return -2; + + size_t start_idx = 0; uint8_t preamble[] = {0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,1,0,1,1}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) - return -2; //preamble not found - if (*size != 64) return -3; // wrong demoded size - return (int) startIdx; + + //preamble not found + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &start_idx)) + return -3; + + // wrong demoded size + if (*size != 64) return -4; + return (int)start_idx; } int detectIOProx(uint8_t *dest, size_t *size, int *waveStartIdx) { From bb5804b1b0b38a9a58af657b8694390202a77b6c Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 6 Sep 2018 21:47:57 +0200 Subject: [PATCH 0019/1938] text --- CHANGELOG.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index d384e8a61..966d26729 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,9 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] - + - Chg adaptations for FPC communications (work in progress) (@iceman) + - Fix 'stand-alone Colin' - remake to benefit from flashmem for persistence. (@cjbrigato) + - Fix 'LEGIC SIM' - remake of legic sim (@drandreas) - Changed 'proxmark3 client threading' - remake from official repo (@micolous) - Add 'rem' - new command that adds a line to the log file (@didierStevens) - Fix 'EM410xdemod empty tag id in lfops.c' (@Defensor7) From e5e8c0b5d81714b61a217830bfc3dbd91efbfce7 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 7 Sep 2018 23:45:08 +0200 Subject: [PATCH 0020/1938] not needed anymore --- armsrc/Makefile.colin | 183 ------------------------------------------ 1 file changed, 183 deletions(-) delete mode 100644 armsrc/Makefile.colin diff --git a/armsrc/Makefile.colin b/armsrc/Makefile.colin deleted file mode 100644 index fb2a2a91b..000000000 --- a/armsrc/Makefile.colin +++ /dev/null @@ -1,183 +0,0 @@ -#----------------------------------------------------------------------------- -# This code is licensed to you under the terms of the GNU GPL, version 2 or, -# at your option, any later version. See the LICENSE.txt file for the text of -# the license. -#----------------------------------------------------------------------------- -# Makefile for armsrc, see ../common/Makefile.common for common settings -#----------------------------------------------------------------------------- - -APP_INCLUDES = apps.h - -#remove one of the following defines and comment out the relevant line -#in the next section to remove that particular feature from compilation. -# NO space,TABs after the "\" sign. -APP_CFLAGS = -DWITH_CRC \ - -DON_DEVICE \ - -DWITH_LF \ - -DWITH_HITAG \ - -DWITH_ISO15693 \ - -DWITH_LEGICRF \ - -DWITH_ISO14443b \ - -DWITH_ISO14443a \ - -DWITH_ICLASS \ - -DWITH_FELICA \ - -DWITH_FLASH \ - -DWITH_SMARTCARD \ - -DWITH_HFSNOOP \ - -DWITH_HF_COLIN \ - -fno-strict-aliasing -ffunction-sections -fdata-sections - -### IMPORTANT - move the commented variable below this line -# -DWITH_LCD \ -# -DWITH_EMV \ -# -DWITH_FPC \ -# -# Standalone Mods -#------------------------------------------------------- -# -DWITH_LF_ICERUN -# -DWITH_LF_SAMYRUN -# -DWITH_LF_PROXBRUTE -# -DWITH_LF_HIDBRUTE -# -DWITH_HF_YOUNG -# -DWITH_HF_MATTYRUN -# -DWITH_HF_COLIN - - -SRC_LCD = fonts.c LCD.c -SRC_LF = lfops.c hitag2.c hitagS.c lfsampling.c pcf7931.c lfdemod.c -SRC_ISO15693 = iso15693.c iso15693tools.c -#SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c mifaresim.c -SRC_ISO14443a = iso14443a.c mifareutil.c mifarecmd.c epa.c -SRC_ISO14443b = iso14443b.c -SRC_FELICA = felica.c -SRC_CRAPTO1 = crypto1.c des.c aes.c desfire_key.c desfire_crypto.c mifaredesfire.c -SRC_CRC = crc.c crc16.c crc32.c -SRC_ICLASS = iclass.c optimized_cipher.c -SRC_LEGIC = legicrf.c legic_prng.c -SRC_FLASH = flashmem.c -SRC_SMARTCARD = i2c.c -#SRC_FPC = usart.c -SRC_BEE = bee.c - -#the FPGA bitstream files. Note: order matters! -FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit - -#the zlib source files required for decompressing the fpga config at run time -SRC_ZLIB = inflate.c inffast.c inftrees.c adler32.c zutil.c -#additional defines required to compile zlib -ZLIB_CFLAGS = -DZ_SOLO -DZ_PREFIX -DNO_GZIP -DZLIB_PM3_TUNED -APP_CFLAGS += $(ZLIB_CFLAGS) -# zlib includes: -APP_CFLAGS += -I../zlib - -# stdint.h provided locally until GCC 4.5 becomes C99 compliant -APP_CFLAGS += -I. - -# Compile these in thumb mode (small size) -THUMBSRC = start.c \ - protocols.c \ - $(SRC_LCD) \ - $(SRC_ISO15693) \ - $(SRC_LF) \ - $(SRC_ZLIB) \ - $(SRC_LEGIC) \ - $(SRC_FLASH) \ - $(SRC_SMARTCARD) \ - $(SRC_FPC) \ - appmain.c \ - printf.c \ - util.c \ - string.c \ - BigBuf.c \ - ticks.c \ - random.c \ - hfsnoop.c - - -# These are to be compiled in ARM mode -ARMSRC = fpgaloader.c \ - $(SRC_ISO14443a) \ - $(SRC_ISO14443b) \ - $(SRC_CRAPTO1) \ - $(SRC_ICLASS) \ - $(SRC_EMV) \ - $(SRC_CRC) \ - $(SRC_FELICA) \ - parity.c \ - usb_cdc.c \ - cmd.c \ - vtsend.c \ - hf_colin.c \ - lib_AT91SAM7.c - -VERSIONSRC = version.c \ - fpga_version_info.c - -# Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC -include ../common/Makefile.common - -COMMON_FLAGS = -Os -OBJS = $(OBJDIR)/fullimage.s19 -FPGA_COMPRESSOR = ../client/fpga_compress - -all: $(OBJS) - -.DELETE_ON_ERROR: - -# version.c should be remade on every compilation -.PHONY: version.c -version.c: default_version.c - perl ../tools/mkversion.pl .. > $@ || $(COPY) $^ $@ - -fpga_version_info.c: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) - $(FPGA_COMPRESSOR) -v $(filter %.bit,$^) $@ - -$(OBJDIR)/fpga_all.o: $(OBJDIR)/fpga_all.bit.z - $(OBJCOPY) -O elf32-littlearm -I binary -B arm --prefix-sections=fpga_all_bit $^ $@ - -$(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) - $(FPGA_COMPRESSOR) $(filter %.bit,$^) $@ - -$(FPGA_COMPRESSOR): - make -C ../client $(notdir $(FPGA_COMPRESSOR)) - -$(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) - $(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS) - -$(OBJDIR)/fullimage.nodata.bin: $(OBJDIR)/fullimage.stage1.elf - $(OBJCOPY) -O binary -I elf32-littlearm --remove-section .data $^ $@ - -$(OBJDIR)/fullimage.nodata.o: $(OBJDIR)/fullimage.nodata.bin - $(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=stage1_image $^ $@ - -$(OBJDIR)/fullimage.data.bin: $(OBJDIR)/fullimage.stage1.elf - $(OBJCOPY) -O binary -I elf32-littlearm --only-section .data $^ $@ - -$(OBJDIR)/fullimage.data.bin.z: $(OBJDIR)/fullimage.data.bin $(FPGA_COMPRESSOR) - $(FPGA_COMPRESSOR) $(filter %.bin,$^) $@ - -$(OBJDIR)/fullimage.data.o: $(OBJDIR)/fullimage.data.bin.z - $(OBJCOPY) -O elf32-littlearm -I binary -B arm --rename-section .data=compressed_data $^ $@ - -$(OBJDIR)/fullimage.elf: $(OBJDIR)/fullimage.nodata.o $(OBJDIR)/fullimage.data.o - $(CC) $(LDFLAGS) -Wl,-T,ldscript,-e,_osimage_entry,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ - -tarbin: $(OBJS) - $(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(OBJS:%=armsrc/%) $(OBJS:%.s19=armsrc/%.elf) - -clean: - $(DELETE) $(OBJDIR)$(PATHSEP)*.o - $(DELETE) $(OBJDIR)$(PATHSEP)*.elf - $(DELETE) $(OBJDIR)$(PATHSEP)*.s19 - $(DELETE) $(OBJDIR)$(PATHSEP)*.map - $(DELETE) $(OBJDIR)$(PATHSEP)*.d - $(DELETE) $(OBJDIR)$(PATHSEP)*.z - $(DELETE) $(OBJDIR)$(PATHSEP)*.bin - $(DELETE) version.c - -.PHONY: all clean help -help: - @echo Multi-OS Makefile, you are running on $(DETECTED_OS) - @echo Possible targets: - @echo + all - Build the full image $(OBJDIR)/fullimage.s19 - @echo + clean - Clean $(OBJDIR) From b7d0786ab818ab277f4923d6e044bd1e6c93e3a8 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 7 Sep 2018 23:45:52 +0200 Subject: [PATCH 0021/1938] code clean --- client/cmdhflegic.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 0b744c659..b14fa6946 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -45,7 +45,7 @@ int usage_legic_rdmem(void){ } int usage_legic_sim(void){ PrintAndLogEx(NORMAL, "Simulates a LEGIC Prime tag. MIM22, MIM256, MIM1024 types can be emulated"); - PrintAndLogEx(NORMAL, "Use eload/esave to upload a dump into emulator memory"); + PrintAndLogEx(NORMAL, "Use ELOAD/ESAVE to upload a dump into emulator memory"); PrintAndLogEx(NORMAL, "Usage: hf legic sim [h] "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : this help"); @@ -502,8 +502,8 @@ int CmdLegicRdmem(const char *Cmd) { int CmdLegicRfSim(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if ( cmdp == 'H' || cmdp == 'h' ) return usage_legic_sim(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if ( strlen(Cmd) = 0 | |cmdp == 'h' ) return usage_legic_sim(); UsbCommand c = {CMD_SIMULATE_TAG_LEGIC_RF, {1}}; sscanf(Cmd, " %" SCNi64, &c.arg[0]); @@ -520,7 +520,7 @@ int CmdLegicRfWrite(const char *Cmd) { int len = 0, bg, en; uint32_t offset = 0, IV = 0x55; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'd': // peek at length of the input string so we can @@ -651,7 +651,7 @@ int CmdLegicCalcCrc(const char *Cmd){ int len = 0; int bg, en; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'd': // peek at length of the input string so we can @@ -821,7 +821,7 @@ int HFLegicReader(const char *Cmd, bool verbose) { if ( cmdp == 'h' ) return usage_legic_reader(); legic_card_select_t card; - switch(legic_get_type(&card)){ + switch (legic_get_type(&card)){ case 1: return 2; case 2: @@ -852,7 +852,7 @@ int CmdLegicDump(const char *Cmd){ memset(filename, 0, sizeof(filename)); - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_legic_dump(); @@ -950,7 +950,7 @@ int CmdLegicRestore(const char *Cmd){ memset(filename, 0, sizeof(filename)); - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': errors = true; From 51fdde0bbf263d10d45c8244fca1bde2cdd745c1 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 7 Sep 2018 23:46:44 +0200 Subject: [PATCH 0022/1938] code clean --- client/cmddata.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 57aec5b70..61e182ca3 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -932,14 +932,13 @@ int CmdAskEdgeDetect(const char *Cmd) { /* Print our clock rate */ // uses data from graphbuffer // adjusted to take char parameter for type of modulation to find the clock - by marshmellow. -int CmdDetectClockRate(const char *Cmd) -{ - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) > 6 || strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') +int CmdDetectClockRate(const char *Cmd) { + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 6 || strlen(Cmd) == 0 || cmdp == 'h') return usage_data_detectclock(); int clock = 0; - switch ( tolower(cmdp) ) { + switch ( cmdp ) { case 'a' : clock = GetAskClock(Cmd+1, true); break; @@ -965,16 +964,21 @@ char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert) static char fType[8]; memset(fType, 0x00, 8); char *fskType = fType; - if (fchigh==10 && fclow==8){ - if (invert) //fsk2a + + if (fchigh == 10 && fclow == 8){ + + if (invert) memcpy(fskType, "FSK2a", 5); - else //fsk2 + else memcpy(fskType, "FSK2", 4); + } else if (fchigh == 8 && fclow == 5) { + if (invert) memcpy(fskType, "FSK1", 4); else memcpy(fskType, "FSK1a", 5); + } else { memcpy(fskType, "FSK??", 5); } @@ -985,8 +989,7 @@ char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert) //fsk raw demod and print binary //takes 4 arguments - Clock, invert, fchigh, fclow //defaults: clock = 50, invert=1, fchigh=10, fclow=8 (RF/10 RF/8 (fsk2a)) -int FSKrawDemod(const char *Cmd, bool verbose) -{ +int FSKrawDemod(const char *Cmd, bool verbose) { //raw fsk demod no manchester decoding no start bit finding just get binary from wave uint8_t rfLen, invert, fchigh, fclow; @@ -996,18 +999,20 @@ int FSKrawDemod(const char *Cmd, bool verbose) invert = param_get8(Cmd, 1); fchigh = param_get8(Cmd, 2); fclow = param_get8(Cmd, 3); - if (strlen(Cmd)>0 && strlen(Cmd)<=2) { - if (rfLen==1) { + + if (strlen(Cmd) > 0 && strlen(Cmd) <= 2) { + if (rfLen == 1) { invert = 1; //if invert option only is used rfLen = 0; } } - uint8_t BitStream[MAX_GRAPH_TRACE_LEN]={0}; + uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; size_t BitLen = getFromGraphBuf(BitStream); - if (BitLen==0) return 0; + if (BitLen == 0) return 0; + //get field clock lengths - uint16_t fcs=0; + uint16_t fcs = 0; if (!fchigh || !fclow) { fcs = countFC(BitStream, BitLen, 1); if (!fcs) { @@ -1061,7 +1066,7 @@ int PSKDemod(const char *Cmd, bool verbose) { sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr); if (clk == 1) { invert = 1; - clk=0; + clk = 0; } if (invert != 0 && invert != 1) { if (g_debugMode || verbose) PrintAndLogEx(WARNING, "Invalid argument: %s", Cmd); From e29bb51e7604602412353576012e981e4b84ec65 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 7 Sep 2018 23:47:42 +0200 Subject: [PATCH 0023/1938] chg;: idea of auto adjusting signal to zero mean baseline in order to compensate different antennas --- common/lfdemod.c | 32 ++++++++++++++++++++++---------- common/lfdemod.h | 1 + 2 files changed, 23 insertions(+), 10 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index f5a0611f3..f1a593221 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -105,6 +105,21 @@ int32_t compute_mean_int(int *in, size_t N) { return mean / (int)N; } + +void zeromean(uint8_t* data, size_t size) { + + // zero mean data + int i, accum = 0; + for (i = 10; i < size; ++i) + accum += data[i]; + + accum /= (size - 10); + + for (i = 0; i < size; ++i) + data[i] -= accum; +} + + //test samples are not just noise // By measuring mean and look at amplitude of signal from HIGH / LOW, we can detect noise bool isNoise_int(int *bits, uint32_t size) { @@ -1841,6 +1856,8 @@ int detectAWID(uint8_t *dest, size_t *size, int *waveStartIdx) { if (signalprop.isnoise) return -2; + zeromean(dest, *size); + // FSK2a demodulator clock 50, invert 1, fcHigh 10, fcLow 8 *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); //awid fsk2a @@ -1898,22 +1915,15 @@ int Em410xDecode(uint8_t *bits, size_t *size, size_t *start_idx, uint32_t *hi, u return 1; } + // loop to get raw HID waveform then FSK demodulate the TAG ID from it int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx) { //make sure buffer has data if (*size < 96*50) return -1; if (signalprop.isnoise) return -2; - - // zero mean data - int i, accum = 0; - for (i = 10; i < *size; ++i) - accum += dest[i]; - - accum /= (*size - 10); - - for (i = 0; i < *size; ++i) - dest[i] -= accum; + + zeromean(dest, *size); // FSK demodulator fsk2a so invert and fc/10/8 *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); //hid fsk2a @@ -1974,6 +1984,8 @@ int detectIOProx(uint8_t *dest, size_t *size, int *waveStartIdx) { if (signalprop.isnoise) return -2; + zeromean(dest, *size); + // FSK demodulator RF/64, fsk2a so invert, and fc/10/8 *size = fskdemod(dest, *size, 64, 1, 10, 8, waveStartIdx); //io fsk2a diff --git a/common/lfdemod.h b/common/lfdemod.h index f0620801f..3a7f873d7 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -34,6 +34,7 @@ extern uint32_t compute_mean_uint(uint8_t *in, size_t N); extern int32_t compute_mean_int(int *in, size_t N); bool isNoise_int(int *bits, uint32_t size); bool isNoise(uint8_t *bits, uint32_t size); +extern void zeromean(uint8_t* data, size_t size); // buffer is unsigned on DEVIE #ifdef ON_DEVICE From 0b673683d921ba9d4e0048034ee5769a877b8c82 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 8 Sep 2018 11:17:31 +0200 Subject: [PATCH 0024/1938] fix: 'hf legic sim' no assign... (Thanks to @625) --- client/cmdhflegic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index b14fa6946..d64c8b5ba 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -503,7 +503,7 @@ int CmdLegicRdmem(const char *Cmd) { int CmdLegicRfSim(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); - if ( strlen(Cmd) = 0 | |cmdp == 'h' ) return usage_legic_sim(); + if ( strlen(Cmd) == 0 | |cmdp == 'h' ) return usage_legic_sim(); UsbCommand c = {CMD_SIMULATE_TAG_LEGIC_RF, {1}}; sscanf(Cmd, " %" SCNi64, &c.arg[0]); From 0e2dbe742462ade60c2a5613266ea46dff14d14e Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 8 Sep 2018 11:18:10 +0200 Subject: [PATCH 0025/1938] chg: code cleanup --- client/cmdanalyse.c | 12 ++++++------ client/cmddata.c | 8 ++++---- client/cmdflashmem.c | 6 +++--- 3 files changed, 13 insertions(+), 13 deletions(-) diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c index 490dda9d3..f756a44c0 100644 --- a/client/cmdanalyse.c +++ b/client/cmdanalyse.c @@ -244,8 +244,8 @@ int CmdAnalyseLfsr(const char *Cmd){ } int CmdAnalyseLCR(const char *Cmd) { uint8_t data[50]; - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0|| cmdp == 'h' || cmdp == 'H') return usage_analyse_lcr(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0|| cmdp == 'h') return usage_analyse_lcr(); int len = 0; switch (param_gethex_to_eol(Cmd, 0, data, sizeof(data), &len)) { @@ -265,8 +265,8 @@ int CmdAnalyseLCR(const char *Cmd) { } int CmdAnalyseCRC(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_analyse_crc(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_analyse_crc(); int len = strlen(Cmd); if ( len & 1 ) return usage_analyse_crc(); @@ -867,8 +867,8 @@ int CmdAnalyseNuid(const char *Cmd){ uint8_t nuid[4] = {0}; uint8_t uid[7] = {0}; int len = 0; - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0|| cmdp == 'h' || cmdp == 'H') return usage_analyse_nuid(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0|| cmdp == 'h') return usage_analyse_nuid(); /* selftest UID 040D681AB52281 -> NUID 8F430FEF */ if (cmdp == 't' || cmdp == 'T') { diff --git a/client/cmddata.c b/client/cmddata.c index 61e182ca3..7d8cef081 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -701,8 +701,8 @@ int ASKbiphaseDemod(const char *Cmd, bool verbose) //by marshmellow - see ASKbiphaseDemod int Cmdaskbiphdemod(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) > 25 || cmdp == 'h' || cmdp == 'H') return usage_data_rawdemod_ab(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ab(); return ASKbiphaseDemod(Cmd, true); } @@ -710,8 +710,8 @@ int Cmdaskbiphdemod(const char *Cmd) //by marshmellow - see ASKDemod int Cmdaskrawdemod(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) > 25 || cmdp == 'h' || cmdp == 'H') return usage_data_rawdemod_ar(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ar(); return ASKDemod(Cmd, true, false, 0); } diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index 43230218f..d6d27e6fc 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -139,10 +139,10 @@ int CmdFlashMemRead(const char *Cmd) { int CmdFlashmemSpiBaudrate(const char *Cmd) { - char ctmp = param_getchar(Cmd, 0); - if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_flashmem_spibaud(); + char ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || ctmp == 'h') return usage_flashmem_spibaud(); uint32_t baudrate = param_get32ex(Cmd, 0, 0, 10); - baudrate = baudrate*1000000; + baudrate = baudrate * 1000000; if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD ) return usage_flashmem_spibaud(); UsbCommand c = {CMD_FLASHMEM_SET_SPIBAUDRATE, {baudrate, 0, 0}}; SendCommand(&c); From 65b29410d44a81aa47b0b114357d560bd914fd93 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 8 Sep 2018 11:23:17 +0200 Subject: [PATCH 0026/1938] chg.. space.. --- client/cmdhflegic.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index d64c8b5ba..281912866 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -503,7 +503,7 @@ int CmdLegicRdmem(const char *Cmd) { int CmdLegicRfSim(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); - if ( strlen(Cmd) == 0 | |cmdp == 'h' ) return usage_legic_sim(); + if ( strlen(Cmd) == 0 || cmdp == 'h' ) return usage_legic_sim(); UsbCommand c = {CMD_SIMULATE_TAG_LEGIC_RF, {1}}; sscanf(Cmd, " %" SCNi64, &c.arg[0]); From 56f3ef2a5584400dc4193b4fe85031810459cc2d Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 8 Sep 2018 12:38:36 +0200 Subject: [PATCH 0027/1938] chg: helptext (@drandreas) chg: 'hf legic esave' now saves to both BIN / EML --- client/cmdhflegic.c | 18 ++++-------------- client/cmdhflegic.h | 1 + 2 files changed, 5 insertions(+), 14 deletions(-) diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 281912866..393d73ed0 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -54,7 +54,7 @@ int usage_legic_sim(void){ PrintAndLogEx(NORMAL, " : 2 = MIM1024"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf legic sim"); + PrintAndLogEx(NORMAL, " hf legic sim 2"); return 0; } int usage_legic_write(void){ @@ -1120,7 +1120,7 @@ int CmdLegicELoad(const char *Cmd) { } int CmdLegicESave(const char *Cmd) { - FILE *f; + char filename[FILE_PATH_SIZE]; char *fnameptr = filename; int fileNlen, numofbytes, nameParamNo = 1; @@ -1160,24 +1160,14 @@ int CmdLegicESave(const char *Cmd) { free(data); return 4; } - // user supplied filename? if (fileNlen < 1) sprintf(fnameptr,"%02X%02X%02X%02X.bin", data[0], data[1], data[2], data[3]); else sprintf(fnameptr + fileNlen,".bin"); - // open file - f = fopen(filename,"wb"); - if (!f) { - PrintAndLogEx(WARNING, "Could not create file name %s", filename); - free(data); - return 1; - } - fwrite(data, 1, numofbytes, f); - fclose(f); - free(data); - PrintAndLogEx(NORMAL, "\nSaved %d bytes from emulator memory to file: %s", numofbytes, filename); + saveFileEML(filename, "eml", data, numofbytes, 8); + saveFile(filename, "bin", data, numofbytes); return 0; } diff --git a/client/cmdhflegic.h b/client/cmdhflegic.h index 4e3c8cc86..6ee08253c 100644 --- a/client/cmdhflegic.h +++ b/client/cmdhflegic.h @@ -22,6 +22,7 @@ #include "legic_prng.h" #include "legic.h" // legic_card_select_t struct #include "cmdhf.h" // "hf list" +#include "loclass/fileutils.h" //saveFile int CmdHFLegic(const char *Cmd); From 79afc031fcd8db4e9930dae8ea4a7324e8d1a629 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 8 Sep 2018 14:11:51 +0200 Subject: [PATCH 0028/1938] FIX: LF antenna discharge after interfer timings. As suggested by @ts And thanks to @drandreas who patiently explains fpga verilog code to me. This introduces a new majoe mode, FPGA_MAJOR_MODE_OFF_LF, which should ONLY be used in sending loops for LF. Basically the PWR_LO is set HIGH in order to discharge voltage faster. Once sending is over, the normal FPGA_MAJOR_MODE_OFF SHALL be used. --- armsrc/fpgaloader.h | 12 +++++++----- armsrc/lfops.c | 9 ++++----- fpga/fpga_lf.bit | Bin 42175 -> 42175 bytes fpga/fpga_lf.v | 14 +++++++++----- 4 files changed, 20 insertions(+), 15 deletions(-) diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 21731b571..a1e0d1ee0 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -62,7 +62,9 @@ extern void switch_off(void); #define FPGA_MAJOR_MODE_HF_SNOOP (4<<5) #define FPGA_MAJOR_MODE_HF_FELICA (5<<5) // BOTH +#define FPGA_MAJOR_MODE_OFF_LF (6<<5) #define FPGA_MAJOR_MODE_OFF (7<<5) + // Options for LF_ADC #define FPGA_LF_ADC_READER_FIELD (1<<0) // Options for LF_EDGE_DETECT @@ -76,11 +78,11 @@ extern void switch_off(void); #define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1) #define FPGA_HF_READER_RX_XCORR_QUARTER (1<<2) // Options for the HF simulated tag, how to modulate -#define FPGA_HF_SIMULATOR_NO_MODULATION (0<<0) // 0000 -#define FPGA_HF_SIMULATOR_MODULATE_BPSK (1<<0) // 0001 -#define FPGA_HF_SIMULATOR_MODULATE_212K (2<<0) // 0010 -#define FPGA_HF_SIMULATOR_MODULATE_424K (4<<0) // 0100 -#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5 // 0101 +#define FPGA_HF_SIMULATOR_NO_MODULATION 0x0 // 0000 +#define FPGA_HF_SIMULATOR_MODULATE_BPSK 0x1 // 0001 +#define FPGA_HF_SIMULATOR_MODULATE_212K 0x2 // 0010 +#define FPGA_HF_SIMULATOR_MODULATE_424K 0x4 // 0100 +#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5 // 0101 // no 848K // Options for ISO14443A diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 9d6cfbf0e..a957e4dfb 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -26,10 +26,9 @@ # define OPEN_COIL() HIGH(GPIO_SSC_DOUT) #endif - -#define START_GAP 52*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc) -#define WRITE_GAP 18*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc) -#define WRITE_0 24*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc) +#define START_GAP 31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc) +#define WRITE_GAP 20*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc) +#define WRITE_0 18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc) #define WRITE_1 54*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (56fc) 432 for T55x7; 448 for E5550 #define READ_GAP 15*8 @@ -1260,7 +1259,7 @@ void TurnReadLFOn(uint32_t delay) { WaitUS(delay); } void TurnReadLF_off(uint32_t delay) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); WaitUS(delay); } diff --git a/fpga/fpga_lf.bit b/fpga/fpga_lf.bit index 44ef60365e23b68c25c2a068972265ff4f8ea495..7d9a840a33150630332b2219d4c4f14ee3ada715 100644 GIT binary patch literal 42175 zcmeIbeRx#YbuYZmK1cFlX2cvM;i?HCM32EJS_=pYuJYYct#1_+?w~6-lU&H6Gzx?svNs`ov=%%EW;{TdS&DKbEFG!NheDQHj9HR^VwMSao}3VM;QQa43M^$Ak% zajZwm@8K7IFt;sXziBQV!J9`7n}2Gg#{2bhfA$I6c)T@6VJR+S1L0GsSuY2b6!^hU<(qnQ#A-qYv>paQ-Dpxjt%Pu1C;PI! zgrcOM@ivb0fvMxVgaN)o-NP8^s7Uc|?W?JnA2m@tKW|e9=0|&t)co|$dYB%g1#Y-s zocDy3u;>sqQ>IUx@#fj3znaqL4Px$$$IxeUlPHqSzt!6qETu2lLeOE_W5;XKXS{VE zpS_RXqArPL8ux|phvi#N$Kl8$E8g;ctCtEiL0uG;x-V?ki*{$ETSQ&`jJG#TYmDBc zE+?ARePL&K9=$oRG!@C}$GqQ?#(FwJZB95V#ysIG_4Di_NB8u{v!Xy2_qnO2wW`hX zuq75dPc?n`&iJS};jM*f7_^@f4!#=pgg((o-=bzG-Y1SJGeU>!s`@;am&v9gEuo03 zzpkrw-}Qm1eST$SuxU{>3B*Odf4 zWn^d%#ie+`8@pNKcQxp9Rv6lDvK`YxpS|Cjy|-%YJW=bl-5T2L6eqm3$Tf1CV4mA} z!dvNw)PXkoxTjxn+B;<}EG)|R@V9nk^;4dH#jV_wHBIZbIiYo!ksDf#TuP|6wQSGyynd_(KH(< zqa*rdx+bFxWL?IKvc0gj*wA0E+IaXCtH7^}h*3ti+1uU`wl_bFUyqY5VG~@h^Z8Ih z3{XOblRfu(`o;Kl#ECiB&zK*xZ8$7zZQ4q0z2SU)(pz^2_%-2l)JLJqHWqGtTTVBu zQ`A+!TJ)9i>t~E#SM+xnwhGZtG)&MtMzd$!gX9|9`?+%TK4*L=LVcYx@QGs9Vfk3UWroD*~bFqlfU~k+tlRZ=L>n4R? zPFH5;UOi5)(NYP2qXNHzaRJDzs2jc{KH+@BY6o_E`=<)O-j)a4X!eV(=9|>vM8DFI zHj+H{D*W0{v0n>Yp5#1Efxor;i3RKXv#zL@oQf-e%)4x#`T-&r*c^;y5R=+ z^*CYS#%C$-3qDe9ir17X@#_tStqpoTt;{yqk#qX>@#{9Xj`eFZHM?eN3Vt2)eaL2a zMj_4X^+^ZH=;N2o_~j->!=2(qI_R_}XLOzlrPF6~yW=D(@vG1^8hu*-cli@1xwq~S zJ#L@M#ty-+yDok?T|@qc>{0L1RFrLNh<5z0F9m>aS z^Dr%?ZCK?JekCd}&Wf#T%89sq+-}RLo#5~knnneFJwb8jeR<%QvZ7`Dsw?3aumJA2 z19OqE-lorju&lT~el26zDguW;O5iCK_*Ld#X$)sX@1WBUbT`A_D0=!eoqrt`3EC#x zT=Vda`BzR*C|A3YfVmgS_*KonvNIF(H-z^D{EP9+^EcQ&6L4opzg3R+b~VC2-;jSL z^(*xKo!xGG@rL{>x>vuIMyRVEi#uAzub@94LpNaJzTt#vCNsqA@vlXs@M}E{8epSI zaYOz!E?&B8NG`C!$fohH7LR{{h^@DuwK|VMxFP>?^}}ov48|`{zdZhRyIaTnRLxHo ze#>)OmumpOy!9&cuh{v3e;Grxfa3kt{Ogv&jDRy97ISH{TyP!!_5OfUQ^F`a+;WTYr=6Ax1RC^*^_{m9~89}8Hx0{rTBB3b>${0k;7gL!^8{$+{N#sF>f`mFqxrfK}^Aq;Q} zd@amRiGL~ls_xGi`qRbzDe*7Huc|)p(#M4VIDh?qKFLmS0#RVM67;-wo-fE zd>8(e6we!jMr1smya9gsfrZW5f@8pf>*JS4#KgB@pWlst0ly62+En1z&*Z_%c$B#6 zd_Rl#OyOV6ZaKcu-*eX8{EN4w(Vr^*RoUj#;=K7K>-Sd9uf{L3-Ez!oiTGCx-R#r|x}` z;))ybuWkAIJ+zJ5EZFBM_yxA*akLqE5oa5IjN6p_!wUT3pxm~+NYfxZVc3ll|MKx` zX337#h&l;&{`&aE0k@VST@&53qgaVwFH(1gCiFL)7v)FqiCoq{OW$W)uEH;% z)q0@S7+@<_FeiIrbQt_=bq0M_zHtV;V33h0S$|r76PRl*6uoqS60fYTz_0BBv#~0k z?-`>lM(kcQPp!;=D4gl>1{g{-jxpU>sLWN>~wf>dW;Tc6NO()iXF7yN#w#!)%dl$0JQopJ(m81!n!5( z57DCo3)WY~5A91<(w&*qx6@DhI-R=YFJ#Q3{u#O1f(=(6=3nm^pTjc2#34ZHM2o-h zX%?18$E)zm=yvP!`l|$5D&bI_prbNrN93X@`1N1iD4xbnsvTU#(|! za3M^=FVn>+09%sz7f22C!Y#)S&oXCp%s%MgfR=E=ed2C|pFjxWhll7X+3sK)kBKcc z7<(2R&1a+4_|=2{oS>5y)WPo$kD>~{I{VwvX9?Z80NTZiqEIiuuRO1yg=nhplSq9( zO*$Ms7!3H=tqx!-2ed-`FxQq3=VD-FwQUkaEQlXE1deZmah#^SnULULlAlo6sK&1Z zqt$tNh!*sPQ{X#~iE92;uhEDVlF6 zb$&&FUvI#YbnpG(N&TvGS}wFBwNq%`lySJ z1^Bg-*UMd#o!1^S7aR+x(gFV(VGC(tAD*U%w0JI*tbaC>cjI=rDIM@H z6`xO{&sW7cnaq7Yx8eeAl3mGYri@=|bw;3i7ioN;%b8&}T(tg_mL6N1Z%BFeS+gc! zNj|n5wq=q-a1yXJhh8)p6m(~$vf%^9dgrj!CT9%69%A7@D=3EzITHZ^s=zPhie$w_ z?TFPzl*3-lh&Ix*6yO&rwl#xeR{Qalnd^B(0KeRA_FYx@wbWI(%xVRL4?mpsBBwig z9~;En2RtiL=c3P7s2jEpcH>EoP>ojN*DxRl`fLY=m7@T8Ss^ve88Y@t0)JfFUZjg3Ia z&iXdsJKj^lzfO~z?O42KJM`i$0bVKfl~A-t9mSjad0a&ecAmP^(bE{t)l;1XjBA3f zX4C-7_yySNFd}lW*@m6(iF{pe9Z_+cfPbB<0T(uNqw&L{EtYoMCXgn$mA1MuSH?o@`cSczZ1%dnL}IO`NGaTAJvc^;aN zUn7VgZWeVe{KGl)KuU!*@?r@2FFf({Uy`1tZ%Dw_CeW@2+91x+tfZ4@(r-atW+~g%GJc6I^|Ai=u7`e*9>7L2|MGob z%Whd2TMk1V;Fkf$v8T^`2s*fhVk=F=*^Iw^--p?l2mGrQU)c`W)-Vmuw^x~?^*cGf z>cEot`o;J)g0LaBUx7yK4s%Fi!VB~<=8Qr9>n!g>XGfoYmi5bt)^Ah!FYa>{eqkFc z{F3maM)kACztHWBaaH&glVDo~k)d`nWlsS%0r5jw!mr*M#;@IuxlX)6_iKP!bl&;` zwR(M4dcpkbDXYaXzk@cQoJ_j_c7%vM#_sv*Dt>rx(uwSBIS$&@=G1{(ncwsJsL4$f7VSxVMn#N zW- z9@W2@er{dt4Eh}KuhWEFiGwG9%f326_@U<`Rq`*5v#uD$GV_{?xacqHOY9fLK{s41 z#SbO&Uy}A@!xRENabmJg3LW|$b72ny{EE|7-cgSN0-m5)23Qa?)6#204%=tbhyxvL zi3l)jv9be6p) z7f;4()t>kAU)^>D`7h&|Y(JGKuI{84c|%TMXR0=S{1DN?7}sxnsA&F7EORzHv3Mql zf`=scne$)pnjFS2jX9&4d?>Paur;1ClOpEF4`)3>Pl&_-h79hh%>%y25Qn7suVnH) ze*TNVzuvMH9A7{<6lEJ8E`Ll$@?rAg^IX3HyHRWhF3W3l8xQ%SxJHMZ_Nw?H!dcGR z{EAm>yyqCwd2@j8i)3Vf*fMPHv!DNx;qBtb_K$ko{~=sNu4D%$989yrTMIA$wNZw( z^b2$_lPHAqp@`UqbvEo+71ncmjA&KsBYZs)l; z9FM#{zZ^e=o9cueF$za9F%tju)=1B02Nt^+s`u=e%70}Pet9(~=;~a#S$;DQAqoEj zAFkg}o^S*jchKN9<@}e3pTP>&d+Q$5Z+yMQiytD69XC$V$8w3BzSR3IuHV3}qqS~J z5qq_h>HrGHgmyDy!L<0{pmHXiL^j+?m#71RF1+6g@?U=rE_}pjWBc4{9Dz1L$d&6i ze8w?}uiE+mQq1u&_FbaZTMMq=VCJ%|PjLP#vC6DZ*W~uc(PoZ-1>sLs{tN!0843ns&*j|TQ#Ubw#ab>*}%G(=3{RZc1d2y8? zQiwmGhy3@zj`?B3A3|8luob75fM4cVD5R#DO7$D>CvjBfosAUEuZplw>&6$uQS|i- zYztflmY?I{x4PjDF~|L))qMKabtU~O)o+A1VMkq&%Tm$L4$h@-?>ji2n9xI>eg*X# zl6418;EqEr7maIn*Gn@;OZer~a2ea8vFOQ$H|Wm>y6v0ZZ0VLS?p#z@Gu~o(`laeO znwpP??@OOc0a%B({9&k5eq$jVMMuo{_B_$U^bCE?UEN>n5$ABSe$L1s{q}Guh2Gda z`V{mFX|Dp9=1DqWB;*X}m+@6<9S>zilegzp{YLioGt9PnReZjv!#>kv=Vs=^{%?8l zLsglEHHDi|#{m5^ZHZems{8RVuHQh+%8e8U;p$WO@edZmov~R|0Q^e0g!S5zP6wL(zp#wffN@VBwu8hZMbT)7eq|07wR_v0UOy|NXh{e zFm^-~g?-c{Aw2ym)o;MOV=Y9N8!k3SgJQu@0D$gWW=kKk(K-_Q{y7P z4huk79m%0ig3*&gVQ!g!(H6PqXgnXXEtGA5h~Yh3wkqr{dh71YeuZ2oxjr&Oj}4Ci zPPPv{`>(>43YUZU;bC3^XU8ba`&F%b!`fke0_&r2IpAO4q>-ME)Q&IcF?!qTD(o0& z`5{+^FxZWH`ZZD$UA1j=54?+2GwBJp4FxJar;Q`6sy{*eu*Z>>y>6Qs17cC4DI5~R zTp#7amk9D-w>z5$nhUEp)_-v2q2UEKfb3=GscdrrLcqU}B}e=)+N={@>g$v{R3Rci zsmgzGUCP>iUM2(ydA+P_mJ&v5Q@mdLY6=`SbYLz{W7l`(A~Kw$f51M(xGLg@n~eoW z!~H$y326csftMzgUxo#!s6XUv7k8B)6aiaNv017!|Q0j%$gj7VVfOv*_Qh{G5a~=JW zto|W_;6xwRQ5PpwokPICR@M%5K{>5K01b}w6=C)DJ<1*Yt;g`?9Y(>P_KFe`Bz@wPLzoMgv_bNxR zZ^a}8#ZyZ7g}6GievE6(Qi7!~rhmkfD*k0=uubEjU5#9}5if*n#xF*+0Kd+P&Bj+< z@UOE7V1E^^2nP6N;IiV3N|&2v9|G-aNtu^oSF8tZ2>2{+gN4IG_ zRL#HQ=7Hrg54Jdvh}fV>Q~B2#I%tD!EfjSQ{NC?kYei_!XwF5}HQ-+sqDH&5)g!_p zIA*lEAlBeLQ~B2wxzLXGhM9jYv!lNio-6)MF0A5TIr<4Q#cPudp3Pi4jdRdHjL_U(E&?u#%&R$fn1#RE8t&JPB_VUB&0VJ%%BDL zseS89o*fJL*N^G#KE)z0I&Vt|59=2tJO3D0fL}#=Q6P)Q@OOLd%r68{=7 zevdNEZT0b?`eqya%UXRvTr~E(${q&%YaVSIXgdiHpOY_ufPDhN#+28lq+fB%hXCeZ zwuTZu*j3MN1pI3~)CxQWYNhyBRJNdUj}CC31O7D;0_}36{rY+EuWonSXu~A^l)8_i z&lUXZ9fqwU$~Ha&0UPoii9k>xGO8yvr5DVxuDuh-|cS5Qd*&d@$Bb^$)E?O_4) zFZhRKCg+*xbAtZT7S997Y_~W0z@Ax2wh5~K&}vJ;dv7(Lu-i_CvppASALIMso_qAntk&7ms(CEI#1oM!lk^CZm0B%K?W@0z*#O8(W9h=muX9T+bVF~WMu zLhPuSrA?l{!Tih5CH+_DTk@9F>P_`8)0eWh7JAQ#UT;km|DsMSyeQo3T&B*Ua5MVz z+^mj~HCFg8!ChAT>m31HzE3~Y`wo4`iH`o#JE?1ppL5##^lS;g*dDgoGxE)^(l#;I zg-N+6Uj%+d@+&I%*ZqWCNxwKpT(-eM_@Qr5^U-*}c*vV)=3n<`+P(S>AIM&igYv@# zb4dt$j{C#>YfvVN@S~2BbP%XF#A*7Q#=jmOS%UYdH65Rw0iJg6tIO%*J*Ozk>V1GKWs{A-KGZBXvz6R|M{GPJq3f`6eh7S)DZ8$rZwal(D#IPG4U zb4;t`A2R|n3{fc|XxGN=7)z`tq$ z0d%{wjYD}D*YX|NPma;?4D-rxt>@3H`gs*CtS@r8m&QcQ*f(HPudJ*;e9G&p;*1Vp zYnTSioYQO73Qtc}{7`iGyG5A`afN%>OGjU#i ziJFJwpAs9q_v|xO{tKBS{Vr8M|GzfrR|meGzOS(6YWR0O{W3q0;}Rnmp4B5DBlFl) za{YYQvmeguX-~hX<}xAMm4g|)YJM*L!NTT=maDNB;Ln4{QHg(Lxj%j3`vk`~792-^ zCY{an*f2Eiuf07_lx2=Dv9*{pqVwo84K}G9w9minMx_a>DEQkm4%S&RXtpRE+ zfO}><{n|GheU_aL`s~WLlU>8nrv@kKq+C=;^y>ltDzK@{B25{<7OZFrjjQkr%%vyt z=87cfo97$TPqT|)HwH`m3tdOnHJi!6uS1~%9D8xm`d@{(`(QrcUo|#8ZXq?6t1q>w zy@>b*)(dUCwJ@>#j0JHkMk?(E{&kwZK=a*O^CkTv=$98>3-f!r+!uK*-UObmL7YwR z9_V>~XWBF|t)p^j?O2###jY>yY`ghn^Yx`y=mvf!=ny z3ei7)|7+Hy^*J73z`yQCwD8bqWU;<6{jbz9itt*iamrchy~pPH8G(MWmzx<7Ep(3d z&<^lLW9xTRe**sH5NGk?5wQZPN*u`{krBHcWXA@`Bw;2Qa_ly_T`x+K@y?wGxR=VyPU$mXz-}*0?{JI7rziInES;{Q`T4WuW!;R*|Dqr@4`P!pTe=P z#3SMP@|3LRU&rXmoNn==``oB~#Z5JAVM{Q6;T$%Zyd|9YBvijf_hXTX_s zqB|?{U$iA1ORd@|=7}xK_c-zF`{vP+oIa^FW-Ux?|kA1Z)rssiZU~T36m&N-KF&Vol1AmnTwKFUE z*9rI%h;KAuDZv??xCNfFg<2WNj+OCiiw3lMNPLL4xv`YFD>QE!|9TbHuj5mRtbPlf zbUN;e+^n~XlMedB@xu~+rQfulPDQg}9?sLt)d1hL)JOyVh24v^MM5^%=@A==!Xe!j zBfV-(gZx+A*s9sm{G|9r>wy_DIlmAxafl%%;k2JB;ny0NxEy;;P!I>MERwA>=t94i zl=&A|r`yMXXkMB6)=y#VI~?XR>G2YN&7^0+wi25_m!6gTCn8J2bB%8geYA>yF>H0Y ze=o6K5Jsbq4ql|ojA#}7>nd@!tM1L!T@V%)6BApzP!O`Hihn)qY_@JY7GI&S>)DL7 zmw8`$PWG`yid*@dh-f=b4>hlxL9vLCRx=l$G`2o%?q(fyp`7^GjnA6{TI;%u8S8jn7}8>2V?jQh#n z&XMSW6(E>)*HJ87z`rKxd6`Tliuy+g^yDano8k9<%&ohm%auv)56*uH_ViYfXtpzQ zkDJMhy@YHR16e74Sd*YF_MTod-vi^>7;{5Ow8;RQ&?Z;HuZY^BCLu_SaiQF+$G|G9 zah2kSs6SNU2<#saF~Dd)2+Jv2>el6TS;8-lW^_AifnOjN$_!rN$eX*iihrSgJ{2kI zSK+sSc1`GAgbZd5Ppb1@Df1~p{%dG{GYUC4koe&*o0Ii+3BM4_C2*^xU;#!iS(|}= z*$=>%hgPLC5r*TRP?8dhx9z24)PaJB z7OTv^uBo#Ox_7{>eFU@%BbDtH_@(yh^2h=GV*lGlMQsT{{hRy4x&M(Wh z@z7vNEDqi`;Ml`V;kFDb_l`TTNwA@s+H z#XTllaBfL_ineE)b0dEuMl6SaOP&8h{%cKg#cAg!c5*nP>Ag62b3me^XuvI8RujEX-$_>`>QXMR7_Cil8$bW$Mh~mw5?!22!n(_j?UAK=1^!3)Czyskm zMFCh+Y)5=PK42z$s`6jmU&X174c1#m*Wm?rIAovdL!L1guE>9}i@sLssm2NAv^OAW z!tACBzXB|Hvxe~t<2p&5P9$52U&!y=72dh$2ljr=US5|Kx6t>Tw&iBFrvkrJ4k&x` zn016c$@p~}J?J1<{e=qrLRl1CsQNv_=6)1Kg!wGhpHpI;S&3ipMZ0KqdIeH-MhE?> z4BJqA)c0247n^rge~5e>wK-cXeV8s8T`Sk_ti-SKxV+)47ph);RIlJ)d1^znu)fF+ zFoh)iy6q4$Rs74ZHU$6D+LzB5MPlWCLdKanqrx42I6}v@Qdg3Giz!9g@wd@H+jw)*Dh4a@Q67lkr@Aq3~Zvl_;lqW+M?dLUW?Kvu5b*a#P*jXehxJRqo>$TuX!bHFCpXSa-B z9>*8n^%M+bJPJ2jgCZ%fDA%;6YF zpX7uQ`fT(3jMNkuskfT>`qr!$u7MBfRj-K)1FDTXJI8HgJijN7{MY<}P);OlkEq^N z^stF$p9a4`G%Tl^fGxm{4MEjaVq6}7NBxF*?V;|m9YvLQ_=rmr~aE+i=j%~xK zsD&?)aADPb{#Ae_u9Gb(b6m{LY?dtr;MY>}gK{GtFX%N9KgCvxH0yj^G>K@OZrIOK zryE@;&eZZ00>82-V_QZuQ~DHR1q=%sI?KVm!uhI_rp+cPN5B*z2 zTyK7Q5#QiYu$dCBBWJ}7QxoKHkOyP;-&3mJz%8Oh z!`O#@(5Zrdsd2H*JV{G?LAzd6BZUqLuNB!-fl-Tl;u^WV17$g%ba&;pqwLH|nHbfPV;Dk!uP19PlrOfX-Dj zvkk+!OE~t$20!Pc)dg=q@A~){PGKK#U~R_W0qv*ADDq$5GZdFO;k8*p1;Ca~afA)w z%EoNqmkogtt(5=jtr?~x(oV%K!QoI4v8*rW@5Wcl1W;;U|0#I|`j2_txF7Kg5%ku@LG32(aaW9ooF)wTV+stsu~x z=ckJhHuM9nIRE9hsfn}slJT4vseORjo6SP${4&=cs*hK{0qe&;5)R-<(+ahf_Sh*; zcXG4lup2f4v^wu>77MnN{U-+$!oAFqC+%bl4Yyl7AKA%>r67_)twP@oi#U0RbG zS3X1#f`gs!mI>rsG0TH1!TWbcCWkG}=}RiHk8PwD(JyxcV~G^k4<0GV$$j&Te0r*0!C%rZu+Nim{z z$ptxH3)rz8u=Cz}<$e*_fAqP%C_V%J^)cDb24B^0RN$A2_ckNmTTjOa78bT|0{?o^ zUR2mVp$Giy0#bEth1G{wwb4rw=dv?G%D+F?f@pmx>CH385A!m?ev|>#^MWDvpluIh zXLe})+-JtGCj_Hj&wTSQX}-HPFCM|!x7aK33jT$%dDbRNC*vf_DKWqZa0fyXPtWu(>Y1Yzz~ioZ?_vDHZ5u;TyCKr!YDptOIuYs*k3}lthk0hlcZ7dU6rE?NeHdHo zs)PCs7Dj7RJcs*g3iLK2x2VQ6VdwKaKNrpC?2a=Kg7{$;{$VpImk-CjDCCHu*u23W z>FviMFZCW5_ywxSJ?tV5B%(O^3~kOekKu{$lX&=Lv-?D_Ew($~Gcxv3OhQnL(qw81LtP}dPYD(Hg*C-q)h=3>YWdh#1JKGr;I~|V2;6~J z$@|&!TQD3016+6v!mFM=ZZ^IvTW7tb?cFL)sG7FR0(>Bu?Xo`$V5L zw6etlC``&PC2s|SRPwJOxhxmn1lanvT*$|kUoHu+VgKTT`a?01>XK`Dw=mCT=U=|< zbh+(cujF5o?lQaXPa585;9yZ|&8C(Q+Aq3`3X$`A1%7cEN#?G>yXl{(S)v4gmhfQm9e-!^Jz(2e>b|-z2S~28w#NI}&g}B}0 z;}_Q-qR)1uRj(EQEFYDLL*Y5%MLOU@(O&n~l<^DaQ?fIM5CNV@F8vgOGmLSa!_co+ z;56f-_?Kjx*|0eEB9~!vAqVHp6K|mySheB%qfp{-05@sOZ_3f)<)Ng$k^Y(Xq~O^5 z`Xy@;blAqp-&~qqte7zKDp?l0pmfmT-(vh?zxVwVifDgB>)lXZY{UQ&lnde;g!thE zmSA-bW*KQ^f?4+Z1HCBdef%Eam!D%@F=^u1vb&?$!hxx0Tp0Wy|8<7c`L7ZEc7xA5 zfG>BN$ih&xB7XQ9q1uqof6XfiZM*^O@K4jWH}*`;IG~p43GfR7nKok7JPH)M2Jyq~ zl(F!hhteowX^y$(KJd81PFot-?Z*#kHnhNmmB_#?9FY*VV_d3eEswejAHSX?ctkQf z9-b8M&@(IB3t?1;T3zeW=K#MRkt0c*CmPVl9IgY|u~$#X=XyFuVdqB;o9Bn)hYDpn z#f#3t(ZrSTte!6TyfL@8D1!Lm@*e5rtbOc4sNqCHP&9xs7S88iDeZkDsNCCY{u$zj z>LRHP>ACh$rr8D-jCgw5Ynl@L%Rx25u!H&y8EtNe2!;8T^@s3?m>sY19FM5G;=Da+ zbq__0H&x&l(7XVelPFOb#Jb^8M-PN6;)e*!L%Zwe7|KnB?M#!4 zb=5&vFY4n!;V1Thf0g5ha$gr$pjKnKfw;Y@`u?a9ps?yH1j+U}jYN-$gUmtw##!-Gddi9R z!7b!KJ+|K!2PiRA6`0&GLDV?^MJOnQg7k`F0h#t7bxh zF7vP8{-~Ehr58A`;b%>(sS_R*HNY<*T1EWuQNWgech*yOdn$ZRv@)XcN$raGA^Ot` zgast!aL8+Cs1+G8z9cGKuHQfeff-o~lSf6(hWQRsJSo?29AMjGMvv)9`!oWHk>k1@ zAFLuHIW8ms_3K9@EzU)cU;BCUxdt4zHKuUna^nJ{qcnTbMh8u)Lsj zeFAkMXye&2&4ND${OT3;n)0;@;%@r^0{{9{1%6pq6%s=WY1&zOYX3(5_~?$H2eJ@k8e^2fzM5#J|vE zu?3@H2l({{_ou%UKeWJ&aa#FA_|q}aEw>^axgLlz0*OZrMspW)Xy91QPt4av091?eTVOaLv={Z zkLP=1Z0myjS1ZR4PlgYmjO_`hZ6v%qjXNJ~uZ_2+rV;W?CEevV=CuT^&I1&Xd~x9) z`uQ(ex4y}Xz_civphaakKI=^lJf&YJ-COq$pwG%4f~P29w52!;iUtc=#xG8LE#$Ca zy-dbn6P*OnJZs7b{=i=Hpx%!W0V7)5RySLJy8f)|C?BBufg9Pa$B%)YoCa(m(8`woa3y}>sI_S}VtW53qm}@RqIy`yFTVdU zM`nG`O>E4Wf3drnb0Gxv8*}L?*>VN3xcAXFWHXbRm+5Iw2=FUHd^=^t3iGkAyo+OB z!<^t_p(6hUv~m$PEZ5s$fT(b*;9nd+#JG}hm?!JUmQPdrnnPo5*(I?TB#rg z3unA}=KR-_@~g!rIBv$~^nyZoQ|v1FG0&o>UtE892tG+K_*X6J=XoiIX{+?(he|Iv zeu(OtJn+;6?dp_(t#NuGhr=~h{0re4EqWB=nlMz_t56T0gwde_zc8*<5ijl4;Xq)Y zU*T6({1BtEkT%^d=R2TO96tm$?GlCZ{f9@WWx2^Itu3v3$IwAMl zNPE3ZKXa?==O01+{1S<<;c50I*rc$vdD_L;ef**twug)M;uurAyPkeA|3axiqiM%9 z19z&he({r5wk<*Z#v{PoWESU%boZ#&=hx*m=3mKj{RVrm>Snx)CW2R%H!k*?7{4su z8{YlBSSI)d7Wmh2q^OK13W|WsD^(ljUk53cH2Fx^KAIl`Z@S2~u26|zod1gDka12} zIGW+&D`hiB%r6MLq+bzkLs)LYy2mNR<5G4tz%S-s@VW_Vo`Cs+K~rl1p|bvv&HFNf zBR0y;5=Ff}f55qEw2WUI4qaq#S7|R=lrzW6_bn$&_;rn#f1$22MmyYC%G}ozLtYPo z`V0#8lpV{|sA_r5q#neY8g0Ub6(*%Mo0@PyyNq93=)%eP*H^{Us{Sy8BFrsxuZ#DT z>o*LSqeiB#+iF~KodX^DqY=BzzaF7$E4x$Ckp|p3jI9k{q9{}#akR|8wnIIkr#tml zdY0q-5(%0S2`0X;j9;CI*~ALSPPRKcQuYDp`|Dt2ZN<8WEAY#bnbw#Yf?GJ~;9Bfj zaa<0j5@%*u=`wza2ey1|-v-7nsm{E|D;E%50?mo}Jd;X6ZKLm}cl=)9=FufY-9 zMWnRO9@OkC1SBc66zf+-{P2Xke`n&A@JE4P2W6yy`uS7212R#l$bX3m3urZ@zXA|{ znjwJi;lzdCuRT2QyV2~R!Y{r^ssg{Z4C5T)+*qx>#l_vcj7|GRECs>W z)213jY%%vZ@rOd79`QZ6Y)arTFN}G3w2WV^IYqm&0wK7#f-OE|ib9UQ3jC4?Ye>v0 z;v2S4#1wwHmH72DZJD!n6#VN=TIK+f#*9l^r-MFM;1{ZN7$%0rQQ$=@#}6-2k`bf= zzYvPiOnFy2Ej^LH(*JEpDabC=d0s-tW>(^t&9Jp&SIZCRlKJ#{9**>Y zY%r+bkaXHX{l*D>p@&~Xa83YZ0v0l4*laW7HMdfl?47H>E<$j7?3@`BKN{I8Vv=6f zSCQkj`4us!6XM&Sa#F4CX!y~H_9IsXzHGQh95 z2x%|dc&?!XZv3KD^ql^Xh9``S0sq=Xh-VI)|93qn=5`D4uZL;KUeFt=sGrY34Q zL?kn4v%_#-bg`aT>dMYyWPh1|!KdZ(Ux&g!?gfw$e8>VWe?WjV1N>6bZI`9ZQvqA0&lX*_~o7dD)ku~Qs8nPf>U7!_%-Vhc#Qa47&|@T%y&VPU$wWP zb_M=e8NX3$@sNcX6Y}_4gO&_-h zu*Wd2F;Bn#S}gJOi_d=@k_%GrUngFozmT_p%ZN8TBDMh_uHNIH|B_LA5a&igyP!nK zjDRl#$m#|ElwW_??cDSoi~{u=YFv&Yn1yow3$bqMdIc;p!A=*?4=U<=;lSkdiufVw z6X-!4K{UBg3clZ2g=lpt#QjqITg<<{CEJ)Pa{b`~?(=tTTy#?~H(!j^b4ET zo>sr1`Rg_2s00o30yr>EWZL~3+p@7&&F?vF&djX%0Y?=3LXGhKlzug7t>7Skz-V=a z9_0HE(MD`>Vtu$AthS_I2JKg|IF#_A?9d5W*sEAvCzLJ4H#q-w*zYRTT=m%n5zAAA z%JIW7xKFV27P`uv2LxR4{{56Q+bZx2r5%iDt)&eK1aUh0Fs_RDA*W+7v$pvp1nB#P zGzypzkP8LzLuQC7e#pfqDr|VxzTa+k%)8Pez%S@myAv*gqdi4x?86G|GJTctL+?m3 zpRe>fHfF1HcJEq$hylu{c@zPDfqyZ6xq4ChYx)Z22Of0=elh>rlMBZM-@nl&XXf;M zu#m8a1t6Nk`;g;@FmV*7T317Sp7+=b@FDGj8AqEwZo~J_<9@c$Fs{H=MG=6B|4Ex2 z92{Pc%(cU97{5?|$nnFM2p36l+5B4q=eBZ)##P`KcAcwK20VoY@6s3u0e&fam_s~V zU4&Qw|9XR-2aq8`72uc3Z8>J2IH&pp{laEz!dkec_#u&MBh6I$Jl0F;;Hb@axZwnP zfM19onu#9sW^oM8vl_c=t6TW2Qv6WmzueBg$Sxoe68hX{*f9xxw=3}r(TpLe-bDw; z9Jq~QWG!@3i5fN^$7zam&ub(U%bn^ui$7=ex)xAEhLUj9p6ujF@?sp1I0 z7J5Otx9<4&QzpT`c#kpv;yx>Z;3$sQ_Vc>q{wNE>IhHsX>LLidUX#v?$wh928+&ck zzyH;K3BS%~u2liXJ92Y>%N27{6b&`@5yTI;eo*&h_xc>4i?>)#xB6jM= zhe8P@VC)yQZ9}4N87)n2k}F7K^8Au zMf^~`2iNkK?EFP~PN?_z_@(YYq;{sjL4PJ`2Z7@kVZ$AsAI2{=E{S6){d>16CH#n%VqAlxwJGk8Uq62ef6E(J7>(Vx?XHpNp+TR2as44uB%`R*W&e8_W}$MOrt(fI-l3O?%J|I$O{k6^8l8ZxLFMj3&_VpbJ*)FyY)%uNomb&3&K$Kl*w4b-W9t4W zt<5nl@FqVjHU|EVC)ohMYWOSlq!sn^>S_+O5vZT9$bT_@C05}H3n~ORoEwPqMN(UR z{qpNKaG|WO{9a&+j{DVZTqMQ$FN^0#-5;d^o6c-w{8HwlTz`l@^VkhzzoGEU!(2Qm*Khb^ zM@q{txg54|Q8v#{1^=p;XYLPzpSVBD*>(p#JbH<+4K_#gp8)qJD#~0#p3dcSQ;& zp9sU^R>codQpojDj9+k5$BFR^!YNO`O7}zkhd|SbEW+(5D!=J zL%h)8dG_LmorMUW|N7be%U%I~ecyT3-G80)U(rL`0{z0x6&sYn5At7LwIPmKb@lo7 z@G9XTSRqkWf9Umx^~+i?4E#DzJFI3G@r~g87waH&2Rb;*(?M|_!TjCa#`W}z^IvRI zdXu%08sD~X5hgOuNl{V1!FDWhMd`aLIG-K<>im}<-{ATUw&5n1y0O4E9D?6QtwpK+ zus12nYl@MoHTC23s6SL)MYbzZ>N9!>`^um_Dv*{Nhy(h7$-u{E&6WPkT)j%JIW#T@5-9Z;Sh*@C*8N-LX%>FL-(Z zYz4ww9#&5O_bY(~%p%#=Rpq}ta~kl1l5nh~U+YU|d2E^x#18}0J-y8dZ!I|g#aIw# z+BH@1^{ZTeSng`j=W_n5)I$%X7z;{ID)?84=9In)+Em03eb_3L@GB64`orm64W5+a zhtsAdn1m_#RoT^`Kjr+_w5|qiD*0E5pO)~ew5C(=OTkuvU%oH}zplH-rr?)?iK+X! z3cnQXLfT7K3$J99`UsKJXhiGu@tMXqr(61`|xg^RFA(!*cxa#x@gvufukugkRTPQ(wQl z{8uGatXLE`z%THW8}!-7FFL+l?|05yA2I5V`a;c7&41!96OyE*sEKZ-8VO;Y5^DI#FW`ya=6G+-r?gMV z-?V3sl!XqO!%s@Tb=)ETTeYOg3PJOpl=|Fja7LlWwlXC_8n*XDmfEbU=^5zD-5sAD zDhWdC8|cg5otQ$p>s(teA6gJw%laAwP!)@!}$NvY3{p2B4zw^N-g z2^lSgKn6eY`*XagJ}J2LhqSdosJ!<_@Q(U;708Ce3!0@axnFfp|{`zja3srDT&`YiemFs12LK zdf^11^!r@XW7v4oV_In?sD-n!f{tlP&Fjz|JvGiipMAGETdCK+crW6tx~0^Y1zJg(iLi!x;x!<;134rqZB%0k7IL^y z2Eu@PQu-~7J*BPl^$Yfg744?d6MtOC9et{Pv9TIa`c?WdGLl+^R*>bEg?{KeKMC5f zS~->aHA<~$qn`MUYP5yUn*N4H<2Va_EYvI{$7!&P;5{uh8;<^8{lBq&_E%X*vS4g* z?_xogf6K<31vD1hR|WF2)T;SU{6^-=duKJtJDX=^STOF?Af#qB4dF@oJ$LlYy4(1; zHp^M*3A3H$eX|^pUX#-~8C7-V+V`$1eVH&_)ye4h~)zGmcIX8fUnrMn(l3 zPXXwl&GqbtLh2?%mfk~j9Xu@|tl!8qKBdi(zhuuEnIgnzx&QCpGZmM8fKK7kO#d_A zST#_eTe)x6bir?7x)D;QE2*uSCODSY$}Pb$>`^s9I~uf;Kc?%H)F#lMvJkW}Qt&SB zq*-#h;I*+dN2F*M&7&D|nvhmMMa~`9#bpnmUC$mmXgVF2gD2`m4my|wnxkSeI3XVh zu49-uCPiv$*Xx4P0$NQ~bVmP)^Mw2#O z@Lof`z_{tS>_73_IKb2Cxa>c1N|flsSh>HI5AD| z+w@%zmrFo@th8P?)UN=S9gO`R*_5hn(jJ&5NUuM1N6OfQIQ}omS%qmrX>VY?s&F{~ zXbAp$9IRIrE(ZV&q0|QZ&>67omF6rlO`y`abn0^(lQj`-#Wcb3`s@I6DsedgXcoLC zybr5zIRI!DO24H!)72_?;{VpW>6i4|U=EjPGiimi3eyCC4*Lk2@1XX`Kh0Prxc+;n zh88-JKE08SPZN%nertu1I@*-HGcs#%njrl-g!@v7%VoQwOpbbyqxCWzGYTtQt`cPF zw-}BajXN}j%Tt8XdR6#hm1~|ZuLVuTaTsK{CO5^IC0s$4E z;Cg)~VmPiZ;c}I*ywv19#pP-^E&=qP1-~^Nj!RG83EEWQasbdu2-=7tq(W5@c_92# z(|$ae;iC?>te}F>1cg18FO*(naxyu?B_62lf*>q&IHsv5r6$*V&rOTrsPYSgkDRv2 zTzFZ^`SaS8J;U-2gcq76Frd;~OwVoPq>u6+mEg`x5)KUV-{KG2lwY8>Fz@bp@H&%r zxlL$D?52Ire5+E}Z}OA!dn$>SZ{X)?h6G#pehTj;m2AhfR0xf;OcPH^@3H8nq;{JA zkmk50Ve}?j8>Zzn=a}bdUjIGug=Bszcn@7?RQ1#dD^{K#bZgo?TN3`f=_gOQ-z5X< zkAeSVdWqH*RHuNO&8Sn*Z(SL{GYbXb#%F;)Ip!=I=Za2f$Y{K+Crj+qN(B(iCOL|eE!cy2OlN%^?xy^NUz5k}5O{EG?QR<*gRS>1xeGA%D zs4$Ekt8nn7)aE+694Pg>>azbr|2@~!Wqjr7Zh1|o>2i7I{YKZ(&@u`ZX}c+&NB zIcW24x*RlmuZ2J>rwhSPP5&x*@}IU%(6Ji|NnCBq+ayUnzkI_+KmX$AGw|~n`1uU{ zdT zWn(#(_3o{2{4M&!@A*IO4^n;qspd!ZC;8qC%T2yVFM1F5&wDkl_iF#(Juc?w|5z{H ztNrs{&Ch?z_q+%D=jZn4#;M1& literal 42175 zcmeIbeRNdkbuYZnbB^RA%}8?);H$N+vvE%fTUYa{#l91F*hY#Drp9dln8Dm>quQWWs71ysw=O6~osjazY%F3I*%VnPpvGjt)>ZYPfG<5~|llGfYwv}`KH28A!| zE(;|i!)*pCj?z9#yRnQ2g&`_Z+KG`kiDkl%JNq$unws2LQJnIGLdRS5^gvSqZyqrB?T`4WbMtW1_So0N8Ehc@lq%Lv8`rRdk;>RIF@Y_H zA6uJCPs)X**aq<Y5cUr7zgR@SYsRo3vAh@!1r5ImKdTvTAZil7(MRI&mm<-Xs{;iYD75Bqj2@N zb+zu>t}b^q>@y3z>)xzXYf)b@y-j1#_^`KL%d8R&QWM3b2n2mS4QhDeidVd`n-%D4 z*k=|-#H@0ky>HFl6%09?pFgK(so9N(ACl^f6DrQZ%)VRbG@M zo_?jQ!n8F#P1vheVn{#Y=~v1~(NokUV+Ao52tVyoPj-nT-dd!l=~rV8d#sE1Snf!m zUvnn!=QUYz!t{6enExJgF8xZbC?z)NKk|h2`s?&dxuTF*ufOH#mwB~k6V?Sb0V)$t z!lBA6?;j_yhv&-na4Eefl|6L5_1Zm6zk2jL=m~4#Q0z|emN(Btfeu#sI#?7Kg}G2d zD_u{&veWb{BUVyT#&3&NieYcvcf)2*vWMt%(j9bJQ-W_vnrahl{gm;p*;Y(E2IHCG zacP!sD$6#rZy8ft0@4olVU(N*|C8-e||#zDvHqHpR#gvj|)3L6~Fci0EeM~tVA2BDYHh_`S|51 z{AznGwttm3z^#m5FH+k`VsILMo$d<;xatJ21tktn!LMV9;!G^ArSPj{Pgreu@}9ouD%0^Qua2gh&Q$!mBfzf>;xz(( z0Tfz(9e&XnYNZ6}ukorwcRc(W0a^v)(#Kc6$9wD?#-8Oi9)7jTc)`bItouniD2sNj z)ZeO8>*eE@tZ@STVj#Pp=DB7MI;P&^;a79XTwm_s+{4NEWx)dh7B~vX#;sFWuPPV)QM%*fSE=SJY*Gr7fou|f zrL*QEj9=y?Akzzz@axtp599uX!S1Z~tkLXD$1l^vFJOTMf8%kvFbg2d1^AU!_PM6O zeFnIAo%iue>*lox@oOYBgAJZNT$i8ubq@<3%N0RP5~JW zh#Y*sHH9hoRj4A~V>0c=Y=DhaK9cnDtDq_TDw*DX{;a!ZOguvmmNI!WBM6-MJ_JH zkLxrUziJ%))3o2Z!3Aucp!;ZEr+KGXFbTgp%@Sbi38-Eyi?!HF4X!z!gUieN$M*57 zDg&EYq(&b5OBlRun{i=!>+a!KYd$^z^ZpJc;Tnmztl>Lau8e<0_rK-i*KlG>U=x<; zqptGadH1UQ6W~|eg>8AyUChpZ8@)`6o%py;ovMwGU!&DI@QXorfg9T|a!!tH87E-} z_yyAqeqr`14w8h;tW41+BPq>(Vf*-HFn%>1tmZY{gH4QmxC?e3d#osgr(aZ~%=|*7Mzw?bj*tGpZOYUXXIhuxU+?y>D50yXLBv*!H&5eV zwaV9WZnok@{U^rHx|Yg#@e0fH4;B9s9v?Js#?+b5&?#qgscB^3*<6da76JeI5RYpQ z935JcJ1BaG8tX6#%L4x}%D?j2MstJse)WAay%R#0_nv@%)du`4ZS@ToRys@Ec&4FF z@OBRHi?`MV=MvrMDj)-X4JA(NdCx!G?cqBw_dRq@-t4LYeuwR0QD5M#*A)I`yMV2u z#{IN}g*tDZBmC?4X`efPyqd}5R(D%4UztMK^O zx`Mu*F6M78)D{}vz3Z^Ecz3!GTkd_U%)f}SpiKY^T$-qEGa&@{MWKZpHP2D21M|Mi z`6y+a_(QtzzBP@10f4Tjjbg#d)FaRxi~Br{e=W$1uhBP+q%-hHM`fU2;9nx`Y*zS{ zO0TZY3#0JORBE+pRr~riSmWWB2U~WV3HP8N$Lu=rXuZkPuModHY-)FEM)b4d$JFj5 z9_|bHmsW-?`hjS1YBG8w`(sXgM6dMLYYP8@DUia3$Jz{`y4D+elz(XtQOfz~NcEMl znF}3Eg18KR9iX?m0BuXG2Sqctsr1&O;Nh2(;6DFAE_WW>re8-d%C??#UQhY_OY`xI z+nmlX$tE7w56g3QYZw01Wc&(Xy@g;Hi*&(RY}LwGwWnVxgfGygTO>Q%{OvNw1&2_H1UleFFEpW|Q9h2}2 zt_a&qCSusnaZ6&*CI$NC;}_d89@kQsLH#k{*K!y7H3h%?KEsW78+`udhWG`41MC&0mOiXR~a|n!BrQPrn$y5Z`dCGgoe* zM=3SDx}|Q5`6z%4lMvw7jK?^>;chN=`14Z~Y3=W*wwHF~GTvG+esKh*rnm|eSZi~) z6lbQ5pV2jg#tA)&U(Pk|72}`rcuMnl>}cJO&DO5wu2>{~=tXiqbBbOv+uZoL-YQ?B z_Tl)Omx&))h4 zYfgV;#K$kh5B&($XQgtn&gd)bcXEqh56$WL^-q4_rFxEhlIA(EV-frU<4|Ekse+$3 ziLXMKKNY`v)9#u~-BH5}2-I!ChTJ`oS{C9L#}7>vy<8vguL1Ks-TZKTY&w21ms!ca zx?pseMTrMP{3^!}hm?7*v1VS+cGZbn)A7q5rHuvVU;5o*W4`I*=3ie9zqE~3lLI2w z$Q=LU19?%#FDs12^%D43U9PjxE7Lqblkm%NFkZO+H;#<+lAb?<{;Z4{R<7e^64Tsx#s!!NL;r|c%+7tMDz z8BM(avdiJuUP`<3Gu1VskJ2S`8QOI7xXSodcLH2yp^3+cYE$RdyI^1Rwe*Gf9 z;%vp^eUM8r(z=vTb9e{KF~yt9E?V1>-%Z{UF}6 zBz}|@OXfSB8Sc-d_~BqbJN9}P^^xs>n@{0ij9(gp-e^N9Z8L#e<)MQPzsEF~f29v9 z{6e~cg-+xFZP{f9`sLwQlUwWIS2K^xreT63Bq!t7Ume^!-f)3_i7-^m17DRn+Fhyk zJjV~u%EdPPmKM4s7tP`JHt}>;}{hU^oCWf>ROT7h<`Clr&<+Y8!2KcBckK6a5_~p*lkm{2F&!GFXd- z>^szA$G7PX^fOv+rHio$eqD6hJ22$)_9bfVhoGE_T@WVWSBp&S)f>Cswc8$s0V&W+ z){4&By?WmB58VoI;X8JgVy(G_^t97-#=KE%v17974f6@%^RF?)=h+*KEfK=p=cY3; zqfW?~rS!7uC1TLiuc9`Wp2*M3#x_)c$N?6Nn!{qR1N_Q@%M5sH%KYoJlX)2VFN5AO z;Umraa25Td)|$r(K8!iT&y@VvHSW6c*a-rD@#1!e_$9tW88<$t$KkGEnMw%nLvYjZ z$Gr6#MtuGOFIqT<9xxUjgv)naJOBkL^DjwXr3a*9Th~BR~aO+*qINfLh&6-=rqzL$fOH_twHR z8u>j=mjyfDOZIB>;Y~&Xh_-s0RT;rAUzXC-XHKrQLt4*1s)LW1p1t)-t; z0{HS-#xFO*zbY8fz>f3!kUv1J(F2Yt{3}T*;1~AGqf{+BQs!=I*2?^=tAaChI~U+XpS zFVWVsl`$8BllYK6WSlcvJDc-;5&p%|LeQ>p8?Z(3A-$M6VYbhT_v)KG{R00IIk#zd z>g&m$Rc{(f52SW=%%@FGtu)7?_|<2phs{h5o2{$SHHGMyzJ?`H(B9M+xPW-WbJt|)+Zy$0C2p)uYS`x`oj_+fe?_AO7pn17uI zwNDf^_W4`8VPu9N!224H@GtSQY`4>0YwE<1+?P$?A(nQ%+TUJ)hY!A|z6Je4H&~mX zU)DS_vvu_@@bp&m<3Ub}Xgl3!f*qrc4Q0$>QRbKrF!*ML>**Kc7b2xOc=!at9x>Ab z!8%HtAS}b)p5G1s@Fl6-1Ht>SC%!wT=Z1|o#G~}L0{-<=FC4mG|2e(u0Ja|LQ)JCe zl=Kk4Cg2h;&Tbh;obA=z;$8SvN*slLCB7Hnmo(O!dpqpnz{X^Wq=VRCzIqq9Rg;YM z=R*8S*|6cmW-)iFu-Q(!n-_^jq1pfoytOb56Iz)hj0^9<*++_Vv#z z0RraI{j!0%jOnc@*dzhq*E&iOBF$U-b7-gepw@xrP| z{_6s40=C~7W1PUh2x@hQse~YY81S!$*k)R=tJ`$8^Lu#(BlvZ|YU+$_6K@&^dI3NW z)pe8b(~mAu2j z2bDbx;)l8v;eCZ)^D6fe?V{VHeVcR=}hEfDNipZ*KZiDE1_QqB+9nzRtx;g#x^9b-%y!! z;1>*08?DVXxMJ9OisvWbUk2yDVEqaL`LE+mvSt^AO_by()%+H`hy6oJQ;aIH$0Q)B z6;`#6kTl5z{L9u<{>zPdd?)Qz{kb?n57;U?=j&Gr`L8E{U&wa7PQQ>VM&ld$UXiaB zZYm{~#i~91V*Co$3w^FVme{YKvfu4SBCHtT7uRp7y{hb?Y%gsY)-T$xx{F6q;bwX3 zrQ(Oq!V&$?^}o$N2_UORe~f>ycDS+6Mfn$~qKsv8$DxA&yDa+rKj>OSGb%y7Fm%cS zzxE8=bJtb%_xI03!pPl}5l6Ls`Nk5)UT-MBj`LsVWK%Y=P1!@`rd|*~cAgl9J&feP z&RcE$i2^d1=Nt@YzkZZ{W-sS)h4|%#s;*%yc#l5krYH1M^j$(CtS7)P=3j$O6IW}z zL3`YtZq0rK5`PHA2NBB#`LBD}V`Oa_WiI2Id(nn%CTzIv`5Ron0XivTcI7bdRoD%z z>6ZvtkP#gk4;>`!9#9xnp2tuN+gn7(UiA`TB)Yi?*Kc@xOdCg^uW=d3Os?G9I&7&*HPG(`0%PT5Ek25ucap9hrloFOx1?-U#QlYXAabzvF_*`EooB5`IJzwC+n7I=e?E})6J zwmFG@{pS{ZEnd@+0Kb~-r+bqnWU^|p7U@!K1p!FUpL>sUdEjrq+DI zf&=VVB)(S0uU}~^ct>5ZFdT6FRTC`m!iD&CR2+f30$6_wG^Z^aw}FE{^Tt)iFYvD& zKr6&s9?;lPOxELxie^OcYwLhQ*dJ*RxC;Tb_kT$HhFn-e6f}ZgeTIFIedF7(l*d!c zs;h%Fjnp3=rbRM-3ZBC&)Si!z>A#hFi+$Ru^&6Dv)xp1#(KQfL+Azrepvdl=Uk5X>c}H!eL|zhN|KYXDo;fC2n+t5bydA>&tA ze;8Cqg7>2&W95Po!ItwQDyi!O0%j;oKf2e_fRkf{Om+u2WYi-#YIFlW|{kB_ED8iVw@DP9}?Hq3#Fv>!c9vh_@Ch|7F?knj4ZFbh3wNk$821 zZ#TmF4U6{o&ZC&yVa{wT<4#FNg{V5c3fRS-U;#;16 znO7H#cj-BIT}D4;y<@bx>-u5meVY)*4_^m;Tim$irC5u36fcbbKwNZudl>SsM;JYa z%zHil<$@Rp26V%@3C=8ojZKp~klgEoPFnec9snn@k5B@J7H-%G)`eEp)DyJ=W!p)InZM8jYU z5Nx*d2e%f>^@nWzo^_jh^b>Wz0(1J)k=TfrSOI=jdYGd8jm4#!4YA)B|3~gA#kl|# zf#17L;FpIx(mKVQ(MCux2_RcwR}Y}1aPMw_FXNZZV+a3|MWAq%tiFf7LP-X)A=+yz z@I5(0%@5aa;5}plspTeGaIm^4#;m6ppeNziIfRdDiu!tbodab>ogI4+D8?PtXXan; z+2CI;!Zp7@>_Q3PDR=+r)cB!OBlY!C#ebx3!{GbxQGI6qb%1OM_n2jtG7|CmXT|8!lhDC4Z+4;dAuYU;YE; zUlIH|!|x%Oor5^;k)l3>4pEDf&gc>R`X%^s<+%0~`LydiT{IZKW`_9nw)hS$)i6I! zFq{<6PiYGynwp=k8PBlpxG6`>5%_;6;!YGnuYJLuv@$0nLA49w-;gN0ARbcZ@^e2j6jA+|qOfcuJZ~hy7)R~~?rqpi? z^ZfKT6zQl~Ob8@$Ojym&5ra(vxD_hXFdSsN7Eq2i2@^47BA9)95U;D#-y7v!QW0+Mr` zt@*`oz@HECYrBJNvWsfNS#-ZOzaRW-J3X)niLeNMZKvm%R-pb+Y^6ut)To$aKr6Xs zGQ=+~Z?Gr276@HRJ7rbZi!FAau;0MgL;QLMUT)@ie5bBS*8z|{tS_YR5GqU}@k2ja zSO6}+E89wN9p4r{E{FKV{Oe{nUecG)+q5qi2baN0%X9aQUEL{oqzl z=M}dK@e4T@iE0fl#rdX&HhFG?KLww^6yR6fe-B*89N98ui=%jA^O}bEbq^30(XfKf z;MJPwv=?u6k5*YF?&VQw-iuo66K`j_+#$46skbgZ! zPix6T=H6UdQO>TSc+AEQ=dnll*ThGcTMOZ$+Y_H!T9@wsQnKSEy9MLAA|K+H`CiA0 zpENIvop9dS()yF;o7SAT@=Tt`72#iqcq|`j+OMabmz<^U+C8y_^rGPRl=)ZMc#4uD zCF_98+D`Lh19f(O!0S&0zc4QQTU09$6W&Dw)fg8Rh1Vj2U;AWX)cgxEm%f2mTtH@!%U^HjN8C*c=h%Sgby8*}J+qvqhM9@s<1uQLDQ z`i&M|?zr)i)^ZSaJMp?2>8{kc0!nt=+4`!suqfedS!<*`Tb>%6n{;qYvtPbpa2C#KnYjxJ;A^1Ec zz^@8MG*l^%z;65#-RKFZ-{5gg#xFwHFja@`*J~C)#CA{NUqgUM+dgi%=7wqUcXlSU>@>}bM)&a*U6wiQT%$OjnQf} z!^3HQSRcxrvsIgre-#v3eXKX8b&Q!$)u;Po^O&g8RvE3I-z)6`LT5Kue&3vz?;3^C z^COB8{Mtu_()>1Ttw(9Mn`)_6*?-<+A$}o#*m>vou>IyB1gE%67*P!IYc9PbGw{Rp zTKZ?X3<>JkT=Q4C6{W2a{`DBM5+3Pj<#|jC3qed~3V!|lgx*H4etBOBWdLnrD*xI} zk6Unikb+EpJ+tF52I$4-flWRqBHGT_)M+}KEZ}lMnu|8YZ9fJQ!LL18yT>$zPK8{f zwcD($lzoMJcAclafE7(SKNHK{+M@mj@7|1hk4^X)u1L~>gURd~ zE&~{}K@4+A_!5PtQgyMM|8i)LY2N|M_7S;rWqR4B_;v6lN=?TBzG42Wj-HeAz8PCD zevh7&%_l)&UZW=;T9~c=i*o*pu*Zs>>t@6{&698fYi-0XIDQCVtpg2R zzd*Z2tbW$_Y|^3!#5{LRk9gR#V=g^RPs--fzy@&H#XOKYuM6*6(zum29!%aI%O@G6P_{7( z`UU*z9>|LVS=?vT&&vn31}Dbc>Hsx&n8zS+MMqb({*Y;x8yi_YhaQK5nA~`yV|Sx| zKBw_(aDF)pdb<}>gX1J@mJ!ZpgW4j~_eJUt1@kXdYm8cm2`hVu7q&U;xb2!5%wyPTOZ5lEz3SGQ?ca^54%e^sR97p)y~O`#)Y>=ns@ z0e0HIXnwc=@4cEFp667>YFIXV116UY#AR&c#p1A;h{ea4_@eSo84xec$v-DhS-%HKg`zN5t}Pskc$gzHiC21if!V0j5KcXMW#o72oUs!*br^jJ=V?7;!(d@!bz}5-p z0q4U`&3MkwNfG7gYtBLoznVq+ozEVM-JW}ozT7qMR`i)X{j#B7m@h51R8&di{%mB9 zRqoHJT2^g(dww@;=FenX3fZm{sA5|tkwTxL?*P_v{tGstyGE)|MW(2ve#DcslZ5$M&wgO8oz2n5sP@kLGF)$-Qym&q6+51E$$YS zZE!f$ZQ>>PN2=?=0Ns#((K{%uPjFo&)}n+(Ib&mIHey_Zl;v+Z^q9u)iF@x+!hFsX zp^h=+Us@U*|HE!AXducU`D|dd4&7;5f{sP_7f{&ib005LMpRjkYN(G2`BzEf^I!8v zt2ZRSO5cz>PJVcUSZbq|kAZC1v#Xr{+D91|(Zaa=4rt((MgPU5e>Pi3;@~os+~uJD z@L=ufnHZOaV_$q;4+DhIFmgqf+o<{tr{yq@tMVlS=K_jXe8>JFeSv4p&#iO);l8RH zhCjx~QvMG$kF4&w?wG25g6_O#*!&)@KYX%?*dR(xOmuY&!g&idll;Uj#}D_3U2ave z`X1v;8kdO*SN0iAV;H;t9uL1-;9;Vi3Hi8Gx}g6|zK-e|2$A@qD%+5&5MuJeh8$~Z zGbZB~`(rivhDP&6v`Oc&0gwpG#>@N*^@j)OTU?f~OCY6{H92nuAiEt;CdChxRc}O+ ztEmg7yU|9~M>m9ke;EeKHu$s`Qna8jtId1|p0I#eTm?^$!mkPNFFuXJX)hE0p^ZMb zLWsl<8ERMm_QP^?*Ey}dI`LW`*jB22H4Ml}Z?A3x|Kf3B6rBHpfz5-6vG=vL%)f}Q z-PoypjOuK}&rs+q>ud|f$+RZSe{}%|*{4O2iPK(86(RV^yVpGb5b;A3w#BL9X#r$+ z#qu4ESx3q^*^w#K}@q3REP{Ne!;euV-R;4*~QJ=@Fm z8{@#0v|I()LK{rW8#YH=v8F-(OJlb6E!kW^`PsLrDFxV?pr>*TMHN3(^X#4fLd=S7 z0**GjP`y`ZUp{pb*6)a?JB1l@pgSl*zc;zv`8qX^VH^Jd8aFQ&>k0I0H_bJE)tfoF z_P>KS9hNJ`(tiouxg>8YA^&wmSo|>)`3v}dBV4voIL~Uew-1MO2$nyLA9DQ$;)f?u zwb)ko3fsep>ZL1j!YB)SIO6$--ubT^hiXpif9c#$&8~TGWj#G^FRVm=d`@I3{^e7} z`)T2!>K=4LRp9gp*PBDG-$1FGJHJ?su^UY#OhOf}X*b4x+{3Ry)#t@7jRUfeP*bUP zTx;S{jH1s!^Y$2@|Kj6pc;cVSMkvNcfhCWtD{#&?Ya*LMs9r&#?MJBk(-CBnZr5{M^gLpXDUnl20awHi+fp1)xlZ0l?n z<|2+YZR9p4kBczCL;NLti_b4>i`_ZgpChni=^j1BTv)hlB@l zsLHc-a{M$U5Y25JL)~Dc{_vuUQH%hNVcy-^abJMJ5BV3@$}S(SE$X|t{N7t!Xs(NZ zo8{>#=f9pBN!BA@nUa1A@**9uk^dSOPk6or*B{~txm_L4ZMJb7K#j}UgTbUSV!5|o zT)*)+m+);6R|3BlmQVumBkNgtJwJKIdylH$FqcuSg%r|1(=r!9r=xT_s}g)6|9S@A z1?o4l(3Bs0VZ-;>*75n}k;*L3A>-GCxYDgD=xE z$Gd-n@k`lxWh!C$4>A#ph5QTnWqa5J`>euZZ({$X@u!3x@-HA-!^$d9Dr=+hC-D6$ zMPAdqlr-I6yaab z(uY@8Bd=%eAXT<8M7^3i2v+CmmzV!~)Isc&DW{sBQDdW)2Ct0rFV&yFMt}Y*!kAa& zwNcbVvY&wZL#3xFZ5P9q(+t>BLV`IOoPS{4XI}U0p;v!+vnrcc_=Pns(C|w5hf)3o z58KWopYkELbrP^OW^5Wrz}pdV#l+TuLw*^T}VIKa{j>ks+-*M4ds#1k^& z8`#DmJ}6A0W@+}+?e^Zo^&7vGHnYCm{##OJ?|wI{eeS*!&gaN|3#a2{=4Pt4Z4xe4Rf zd-S}E5uNe9U@EB>M+;B-7@mx}-C(1Hkbuj8yTj zEccn~=TX*M!uh882uHM7xH!e365>c0V6=XN+DnNE9+$)bCt?@HkG1D{fD!ycHd)3C zNOwYE^KmvHIAP?y$L3ElehnJ-4%6<4TTrx>rd^#H;C!4ug?|+~;rDV;Xlf;Lk(=$D zfr_b+e`U3~^gPO<&Ew)j&a?T3T?3yISBm>2VsVr5UuUqD;+kGX?^w$~yTF&fgZvkO z>@~sNQTz+_8UHGYw~kEu1Nli&kCiw z;l&|PCR5$l&C>2O=DAlf|H|^W7{8v84V?BmkFa4wX<$NJwEma;<{Rj9r2eo7DhB*I z4!c@lK|)&=@Onk_UsBEU82VF`TNuAyr{xS}5&q@Tu9@SeckN-ahc3`{3}lh`p$`Eb zVM*up>n%K4iG_>em(g@*EH6gk79u2QA@B?T$4TXJqR`@TdG~KLXJaGcO@I^|bHoOp zwWs1&SU;~0RgECX^Ef~OcHWO~MC#{D^<0*q_!sBwpm9x}eyRI6Jf3pOIGt)+jX>g1 z0exn{$1jh6wL2(NUxHe`MNaw{gkO+iWaapwy6q77WgAGylKHJl8_Y!^S_Hpyz-gCo+J{B2xyzl5Ur!1^z_>uX&T1GiKZi~GAYBXMQ;r{o z_aDwBq(64oeqMjw`fl%yZvb}|c>0Cq?+%NGaKx(HY&m|PQLs0D1v;-OAPeG$ z707?d#hmuS`7a4jaP^FXbJ!Mex!Cp_wT7NVKc|!Ljnsz{Mt!~J{dTdRC4(KL)6cs{@Fpon%`sdxP~hl zXs>KK27CB(=jm?l57c1*eXfq2|5_;#qb|ih#9Y_x=OM9WK2JkDBTbqgIzrePPLE5OVY;mBqrGRmT_*Kq-vC9W_0Fg(QL7M-qj9;Ap`qNVNhRPoWeV$9)XK=<4 zzp$ounm$C8eEy5aE@}npqj*C`@r&Aen|7`mv(B^2SBNc;M+BxSf?sa{t*)W_hP2b> zG8I3ZS)y@zp0-ZMFRq_|aR^4n!u-JBSPvn9YfKw;M0_Au9P%wHX=3+}gx z;8(`u7dg~#4BLzO&Z{VXQ7c>ZfTzSp8NYD;>k}dW;-k&XB4_fohxirlYbw0F8=i1E ze(2xdJ0L}g9%KG>U-dj1aF$v%Vf@g$KdRZO?iOc3rC}T_VZbJE&Tex3A=-?f&EHcn zKjJ#4s$9P@!|Q4j_t`I-ZxsH?@o4=9wRJqG#>Mv^T4?N_0*K((Fh_D=F0i<5?2166 zU@U=OLHw{{8EvxT+hUv&eX6qw{0rv-;2##izm9lok*fGuvQMUGAlgDybkrVGdzI}* zSifUfVn2@n6vFxqb=#p0+Qmd{MJcgNZ_9mGF5-gfw*<7E$h=y@ zw!qaVMAfiNE_CN@2Nm@WghQ2C)d={7Xkkg&LnR=w0wBYaNd4g>90?>K5#PUYlN;ke zJxJCeJbBCW4>|vZHux3VggWRGG1tQ{&VTK((`HNvSE5La_3Iu1!h)Oo%Jmz&=v*g` zob>B&Sa2A)&#kZYs2wFg-x1;BUCnynRD99 zuWiOXOSHIzCn0`)Mjq$|TJb(a$O0gRK;pZka$6yO@r?mME7?)94tPh6(jaR)yI{jZ z{9+fYiLio44H!=zmlsil&Ghk$kpJQ(NO9WB2WVx-T-Y&J@8-2AT+PS6)E-lH%P!2I z3b;8CLj3v>*wzZhuh-bkuyFwJf{7bBMz->0zdnAc^ItY#>m>30hq2v)FOq5)iJi@r z3^hME{{_!HO@J*JJ z0pStE`Q^;Cc*#+jwGqSS`CGFlJDrG82t(pnB} z-M={!KjdS}q3)R7;;8w6F@G56E9<;@X8!fO#}I*E0}IF1MZWjR`K8!RBCOv4>vwE7 zwoJTi?d!#+U4k{0tZ3!?4{<-h#rnnlD506)wJ5~z*2n4&(*n5_H*$F2Qt?AR_5~fJ z3E5`!iSLRS187#Bsf|Gzo1_V0){}}&<0pg*k}}1;~=xpcx!n1 zFV8H)-6iH+cqrgsIR8b>or-euwNa@PVzdJH zi(-Bz)gM~mU&=jTBK8OanWp*^#V-MG@GJViC?d9%ei)@s;*C`=!$Cv8(K+s7XWRBpM zI&oQy9YylxIX7{CtVC}aZO0Q&tP1h#44swxls|959$pK>cu^(7wnX^X--3V58)5y* zf*6j(J`Rw&-$EiRa{pl-{+X)y_3`U&I2Hb_9X|i!_#u3LJ7(l?0XLR=O-2kM3k5~P zBzSg}@81Bu70?~u9$J8jVcF~gcYOZE`1Nj9K^yMhaN9~yt5G^X1NfDJqv+!o?%y!l zONsOPMR}HPB3hmcm@ z=JT)Wkcjd5FCV{P>kw-KehqWy>z*s<*bXSb=zsm_a2EU-O{;1}vH zGPp~bL%6L@ZN5x2BJsmZ@aL}>0o%fGeEjmp74k2Jb;Pyq(@(iCS#5{miku37K7wCQ z(gJCI8CznY8w)4P{R#1FE$!<<49yhZF{I?QoCwDi!7tQrFn;|A6lP(G^Irj}iQpH` zaZsFQ4uhe#%7i^LBw}U!!g{UfZ~vZlcI74OuR0SWp1;8>7{xCvH>^Y>z3T-M!*PZD zYdbyZAky9qHQz7h$?7chOF4m);)kd|WVSVzp6s1hsz;wSpFD>AOO5oO%+^DiRdlkb z7$~plB>vT2Os_|M)OopA#tS;1*JC0!DSpUXv{xUO7c%YjuyqUyylEr&#r~LsTeTax zRG=HCG9Wc!{XExiII!5;#kKN4S5sC8NWmLaXcevBknkb%95#dvkByYuMCv#8rSP7N z3LC;n?iQT?Qiygaf?qbSm5{1z16_5?eU8-6pF_T~xd)#(jeuLU&msRpMF-Hq|5ZyM zs3()^=bH%hzl4BxgD*h4@g#Eoi+gxgw>V}zPIo#nt8PdO``p8r%lR)>tJrJetiuUD z2Jv8i4tu_Ye}8Xx;t~B#%=6ytx^3loF5_2NcF2p;lVFAA)xju2{3>`W=)%k8`=i(p z1#24euM~1XDt_*7H=J0+d;05$+5~+#s zFBLxo|C;%IfotbE|MeqevXl_w7uy82>xOxYQq(4d_;rzR`jzpkg;2j?UVL3p&U(ljCBE?e+QL6PmAsA^*Z{8%87B%qpwkU=o(`*nwXF z@nO%d`uQ(AA!Ep=6p%7LP_|EWa_!Ig<>)kuyKNt9g)N)sRhd#@&S>KOW#3*N@lCV-B zcHtt_iR4|X5B{OKEvTO#t5^rO5T3As!rmgt2z>S5&cjj6r!4V#>gM;1uWYmXxomy{ zSn&KnL%}>={W-#c@~nAE{H3?1%)bsgt;1_u^tgP-0gzdGC&3|+af;oB@8ie0dJAg) zTS>(?@K?P!h}#UX#&seXlCR8i8|GgwS#G=t&iImSS&elc#{2-$@`#ftJ2pIH3y0jv z^H(82(T)k+&*pYz#TioXk+3ZN@=hDKiMCYs_kuHS$eqEHX3mI}$mVaU^UH;-Yu;2@ zqxISFjR(ccg!o3OYf}91h{W-zU9nXE5qoa|ur+L;5OH_9RK~A^;zBq6W+=CB+*bQg z@`g09A>A^5y~)wSjySH3GS1n`R5sci;KH~Ld3%iSKkP+x7fa9>m}SHd1&}B&N`CyX z;#&Ej)6kuI4K)nUn!v9-1dx%eIU+**;wKFbo^aX=Ns4Z9rEwp?Zg+PO-{AP+u)(wo z+h)SE&o*2$%(JV%t*LcK{;Tqw_MEfMnmOc!*HB20Bv-40MS0WPtJ^A$Va_!0CUc4S z7%k%Agz>sa{RWrKv+fYWYtlshAq$%62K5_Uf2fXZbI8=6gz)fnq<#Zx<Y%i9>KMMp{|MuY)qv6`wP+QhN7HUR4Q=+v}uf1@#-M{_yL_;^EFB=bU`5r#a$F zMCv!7O*7Wsug|05k0VcwHHDSp8xhO*&)3rzsUhEWvMy!ZPqu`90m!;hoAHx!{rp<$ zlZ8^%5~N5VaEgR$$Q1_(>*sL<*qnE$st4f_{wqiZ{tTgyero0&p7QjI>o?eH)ohsQ z3GvVOA^#D>1{X|;@2N4{4!fgiD&eGrI*~6vnWNr zj?T%}B0Rkizs6|7X}cq_OGo{ovy`#mqMFq2(2F(> z+YQCP4CRw-A#fRYa|RcC_7UO$Vf;|m@coCtFNBX!kcPDwM_2tq)>439J*zi@A|H=UrCN9gr_Mw~-=F882MFfBBTz`nJvM+&LiBK*?h`CYz z#oQBDW=WrRg_98BU%=&+%3t;4q9MPC@UM#!YcYn@YCtdpA;Q0qN9*AC*wf!*^E`9> z@G07vM>zCnbo01cudqK6{p=#ekc?4v8^0*@W>v1_RyP5Al^eN2c_}3XL)1R29 z4`<)8T3zJ7F2}zRhFS^QbvC#*D)f;?Dzn^Y6+dLvD`MTJjw`~yBKIFggYZ-M*Jn#t zA^#Q7uCUJ${#CT^F|QJpZm&gD($ z{ISXOB=q?s_;r95__V?g5(YpP;a`taLr3g;xwH0^zay-SUwr@Je1p(y8BaL=Y+!@rnGh202+GXDzLR`{z>n8d%72g1JbC-Ma?V^c^Sd@PSc7ttQEaIz2`PUSh6UGxF@k6k!ENIvF1KRaI{7Yg@VeqFYQG|b? ze!c+yrOGxY*~7{F%VD=L2y2A>iSVz<@k0a~gT`h4Mf--qzqH&zd+OMu{L57PP^ru$ z#SigInF1AJa;DmZ2>(KLp97dsC47t*p>2uqFVq%F>^fYN;)TURdl=zgxC-@s+64F& z2ZP2Dj||jms@?GQi}@FyZ@R1jeiSqMj;AgUb*Kn)f8=bC+U+xX8ex zg%BiP#U)t?+N`eV=4r1iB`_Tzwz@z7IFO?JE3+&&~h|Snk)Tpz2H=2wNKIS&}``m z&TM(b-CCD=;`jMJN5@~~KsdN8m4L|{z+@hWZ+CS#t_~y9i;J903zk0=q4ni00iR@|XoNw>%uS>q1vcj%K4 zw0b2}IKg^VYAa=Tc2<4Gbb-p_BIzYHH5PCXIyb|RADw4)89|#DZq+|7k7aMDuZar1 zC-_P5tru>sxVQJy+25_7eYoOY=?Pc(Ph5Y!Zn;&zSDwh;SYLBE6g2P2)$R;$o^Of1 z$A97MMRE?m*`49(7l~#W8lp<=PI*W6%KD1?L!shM*@Y*wgEqG~6+POg z=_54TRl+A|76e*Lzl$gSw{GcxCthz?n%JH!s12LNdf|x-`rKjIc+z27IVGrtv$2AB zQf^ZLZL)7SXA2fGpN!A$(42#}<4FYt=X;V>Phe|j6JK};p-O+5i8mi!4rR6FF5)n{bEH! z_-I&ZT<|e6GFqHgAr4X&vSg|!VH;MfY*fESs1a?{6TeXf3R2g0&zxnv5DFEGsLR3M zbm#`}X{cC#@b`LtXUptIS;%;Ts{|ReA?#Wd2NNtT1SxFFQzPa`J@Ffvop;Tsm$%NF zF~EXxs|F!EqrM+c%I~?Qd&Vr|7Hx(D;dbMb5FAgK?F8R4=XIFfxmosoo-o_KuWMdM z{PsRP37Sx~CZtoa5VZ0I^@R9I*e0%jf{wX2WNOwb;o6J|LF?xyI<_5VpDb3%~v2FFiT>^K&dbeBu?;$F~Xo#mQSU_0+#{?YD zkskpZPZQjr&HKKGk=p+;r{S^>&{_NyasJN&V|8y`p>y|)=|b=pH%`iQWwf=^1jmCW zARA4^W&eqzK|A@!be%wLJZ*_8Qn`%*oS|E3hMX>V@3AyTWVLN{9aTw@rO850eTtl0 zE{n?^K)aqjbkH<_QNdMB)VJ7lPsURpSf&3h?Q*#6dnnR- zPq)@#y#ITGZ#hP{F^g`Y84$F|LWlRQE~=!J(#jh3+H}Et4eXv!aLmO<(*(bb13bM9 zE_+Dr1ekKGac}RO>__Tn9G)h)exJ2l#l3QS_WJs&!_x%6P50$+IY9hF!Fv7M`sHBk zcgp%~WxaO)G(md(pUL*kD&pFzX@cXw2bdGZW#wN7PrN3)4=3Sr2+%A9-_o4vY85{5 zzs34BMXkz;=C{EdF4Jmhm9$FJ1b+^@37YSy>Yszt1lNBLRS*K@-TEvPDoqs*1>ag_ zWDnM7ZjI0AnZN9$rZW)xPqJV}tjx17!Zm!}KCdPRJ(=$hvu zKGJkt4gosAW#^WU>7Q_pjoh%LX1d@63UZ05=j_U$ko+PXcntY(RJQ!$mY5IW{r1HqH9N#s4L=nMJH;g1Y9nQLOV!Rht9K;CxVPjm;uuBzr8L94Kh zavN0|sJGU}-!sn{RydOU#D9|+*~>bA2EPv99k!|N7dvRTv%q4(-0jR)f_f6RnPlJ% z>7cePF!^DB2sdwWg2keKbDnAPkb@_|dn~#lqa7uO=D1fZt0MX{7WfH-L*9-yDg0CP zKq`14%{$6(_TNK1KyO-Fg89J{WVtZB@=rL=y^TE2YCZ76V0O?jFt8AH8~^ayK;R$4 zR{tvhBeI0$hb*RF-5dT) z`QupC@JZMv++%^jN1&7r`b|Q8dmn+DK~DqCoi6x$KB~**?eFVB*k+P0hf4ixba_%( zCD5;^4hAY5YGv>(UzejQ{Off2{oWJNWq&Y{i3+FL*Y@cx{NA8pM3>8dERd$@a`203 z|BmSLwBKDum#4S+z@PlzsHgv)KL6Vjg|dE)7dS&5AN{vm|E9%nX5cq7@S7R<%?$iz z27WUGznOvm|IL8%m*6nLUvi?O*U5F`W+asp{pG)3#%pxsn=|o${~x(*OQAVAIV+l4 zx@@z5^C9}f@A(h+hyIhzkLpk6gBg~a`G8*Z0qma-YFr=G{=s`(%+G&VFFvUK^Fhte zf6DiK0Q=`R_UG4|#1CqIKB)b}X7xXl{rRBg=Yz68=+AHP>(^}Q|Iq%)sA9h5xEewt g@Q+iDC?77`V0fo`dDIl>dtV4?kTI^8f$< diff --git a/fpga/fpga_lf.v b/fpga/fpga_lf.v index 1b7a11276..3082b037b 100644 --- a/fpga/fpga_lf.v +++ b/fpga/fpga_lf.v @@ -104,15 +104,19 @@ lo_edge_detect le( // 000 -- LF reader (generic) // 001 -- LF edge detect (generic) // 010 -- LF passthrough - -mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, le_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_ssp_din (major_mode, ssp_din, lr_ssp_din, 1'b0, lp_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_ssp_frame (major_mode, ssp_frame, lr_ssp_frame, le_ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); +/* +FPGA_MAJOR_MODE_OFF_LF (6<<5) +FPGA_MAJOR_MODE_OFF (7<<5) +*/ +// 000 001 010 011 100 101 110 111 +mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, le_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_ssp_din (major_mode, ssp_din, lr_ssp_din, 1'b0, lp_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_ssp_frame (major_mode, ssp_frame, lr_ssp_frame, le_ssp_frame, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); mux8 mux_pwr_oe1 (major_mode, pwr_oe1, lr_pwr_oe1, le_pwr_oe1, lp_pwr_oe1, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); mux8 mux_pwr_oe2 (major_mode, pwr_oe2, lr_pwr_oe2, le_pwr_oe2, lp_pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); mux8 mux_pwr_oe3 (major_mode, pwr_oe3, lr_pwr_oe3, le_pwr_oe3, lp_pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); mux8 mux_pwr_oe4 (major_mode, pwr_oe4, lr_pwr_oe4, le_pwr_oe4, lp_pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pwr_lo (major_mode, pwr_lo, lr_pwr_lo, le_pwr_lo, lp_pwr_lo, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); +mux8 mux_pr_lo (major_mode, pwr_lo, lr_pwr_lo, le_pwr_lo, lp_pwr_lo, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0); mux8 mux_pwr_hi (major_mode, pwr_hi, lr_pwr_hi, le_pwr_hi, lp_pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); mux8 mux_adc_clk (major_mode, adc_clk, lr_adc_clk, le_adc_clk, lp_adc_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); mux8 mux_dbg (major_mode, dbg, lr_dbg, le_dbg, lp_dbg, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); From 1d51b2cd8f07f2f8352f0bda29f5aa8d593ad0bd Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 8 Sep 2018 14:15:05 +0200 Subject: [PATCH 0029/1938] fix: variable name textual --- fpga/fpga_lf.v | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/fpga/fpga_lf.v b/fpga/fpga_lf.v index 3082b037b..2c0a498d0 100644 --- a/fpga/fpga_lf.v +++ b/fpga/fpga_lf.v @@ -104,10 +104,8 @@ lo_edge_detect le( // 000 -- LF reader (generic) // 001 -- LF edge detect (generic) // 010 -- LF passthrough -/* -FPGA_MAJOR_MODE_OFF_LF (6<<5) -FPGA_MAJOR_MODE_OFF (7<<5) -*/ +// 110 -- FPGA_MAJOR_MODE_OFF_LF (rdv40 specific) +// 111 -- FPGA_MAJOR_MODE_OFF // 000 001 010 011 100 101 110 111 mux8 mux_ssp_clk (major_mode, ssp_clk, lr_ssp_clk, le_ssp_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); mux8 mux_ssp_din (major_mode, ssp_din, lr_ssp_din, 1'b0, lp_ssp_din, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); @@ -116,7 +114,7 @@ mux8 mux_pwr_oe1 (major_mode, pwr_oe1, lr_pwr_oe1, le_pwr_oe1, lp_pwr_oe1 mux8 mux_pwr_oe2 (major_mode, pwr_oe2, lr_pwr_oe2, le_pwr_oe2, lp_pwr_oe2, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); mux8 mux_pwr_oe3 (major_mode, pwr_oe3, lr_pwr_oe3, le_pwr_oe3, lp_pwr_oe3, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); mux8 mux_pwr_oe4 (major_mode, pwr_oe4, lr_pwr_oe4, le_pwr_oe4, lp_pwr_oe4, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); -mux8 mux_pr_lo (major_mode, pwr_lo, lr_pwr_lo, le_pwr_lo, lp_pwr_lo, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0); +mux8 mux_pwr_lo (major_mode, pwr_lo, lr_pwr_lo, le_pwr_lo, lp_pwr_lo, 1'b0, 1'b0, 1'b0, 1'b1, 1'b0); mux8 mux_pwr_hi (major_mode, pwr_hi, lr_pwr_hi, le_pwr_hi, lp_pwr_hi, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); mux8 mux_adc_clk (major_mode, adc_clk, lr_adc_clk, le_adc_clk, lp_adc_clk, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); mux8 mux_dbg (major_mode, dbg, lr_dbg, le_dbg, lp_dbg, 1'b0, 1'b0, 1'b0, 1'b0, 1'b0); From 4e42d11d1535e0966fa308f1fad0675f5da7ce3b Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 8 Sep 2018 20:54:54 +0200 Subject: [PATCH 0030/1938] FIX: HI/LOW fuzz levels. (one step for ASK/NZR etc) --- common/lfdemod.c | 75 ++++++++++++++++++++++++++---------------------- 1 file changed, 40 insertions(+), 35 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index f1a593221..9fbf933f4 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -176,10 +176,14 @@ int getHiLo(uint8_t *bits, size_t size, int *high, int *low, uint8_t fuzzHi, uin if (signalprop.isnoise) return -1; // add fuzz. - *high = ((signalprop.high - 128) * fuzzHi + 12800)/100; - *low = ((signalprop.low - 128) * fuzzLo + 12800)/100; + *high = (signalprop.high * fuzzHi) / 100; + if ( signalprop.low < 0 ) { + *low = (signalprop.low * fuzzLo) / 100; + } else { + *low = signalprop.low * (100 + (100 - fuzzLo))/100; + } - if (g_debugMode == 1) + if (g_debugMode > 0) prnt("getHiLo fuzzed: High %d | Low %d", *high, *low); return 1; } @@ -361,7 +365,7 @@ bool loadWaveCounters(uint8_t *samples, size_t size, int lowToLowWaveLen[], int size_t testsize = (size < 512) ? size : 512; if ( getHiLo(samples, testsize, high, low, 80, 80) == -1 ) { - if (g_debugMode==2) prnt("DEBUG STT: just noise detected - quitting"); + if (g_debugMode == 2) prnt("DEBUG STT: just noise detected - quitting"); return false; //just noise } @@ -508,7 +512,7 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo // loop through all samples while (i < size) { // measure from low to low - startwave= i; + startwave = i; getNextHigh(dest, size, high, &i); getNextLow(dest, size, low, &i); @@ -521,7 +525,7 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo } // set clock - if (g_debugMode==2) prnt("DEBUG ASK: DetectStrongAskClock smallest wave: %d", minClk); + if (g_debugMode == 2) prnt("DEBUG ASK: DetectStrongAskClock smallest wave: %d", minClk); *clock = getClosestClock(minClk); if (*clock == 0) return 0; @@ -554,7 +558,7 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { if (!clockFnd){ if (DetectCleanAskWave(dest, size, peak, low)==1){ int ans = DetectStrongAskClock(dest, size, peak, low, clock); - if (g_debugMode==2) prnt("DEBUG ASK: detectaskclk Clean Ask Wave Detected: clk %i, ShortestWave: %i", *clock ,ans); + if (g_debugMode == 2) prnt("DEBUG ASK: detectaskclk Clean Ask Wave Detected: clk %i, ShortestWave: %i", *clock ,ans); if (ans > 0){ return ans; //return shortest wave start position } @@ -609,9 +613,10 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { } //if we found no errors then we can stop here and a low clock (common clocks) // this is correct one - return this clock - if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d", clk[clkCnt], errCnt, ii, i); - if (errCnt==0 && clkCnt<7) { - if (!clockFnd) *clock = clk[clkCnt]; + //if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d", clk[clkCnt], errCnt, ii, i); + if (errCnt == 0 && clkCnt < 7) { + if (!clockFnd) + *clock = clk[clkCnt]; return ii; } //if we found errors see if it is lowest so far and save it as best run @@ -625,13 +630,13 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { uint8_t best = 0; for (k=1; k < clkEnd; ++k){ if (bestErr[k] < bestErr[best]){ - if (bestErr[k] == 0) bestErr[k]=1; + if (bestErr[k] == 0) bestErr[k] = 1; // current best bit to error ratio vs new bit to error ratio if ( (size/clk[best])/bestErr[best] < (size/clk[k])/bestErr[k] ){ best = k; } } - if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, # Errors %d, Current Best Clk %d, bestStart %d", clk[k], bestErr[k], clk[best], bestStart[best]); + //if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, # Errors %d, Current Best Clk %d, bestStart %d", clk[k], bestErr[k], clk[best], bestStart[best]); } if (!clockFnd) *clock = clk[best]; @@ -672,7 +677,7 @@ int DetectStrongNRZClk(uint8_t *dest, size_t size, int peak, int low, bool *stro if (lowestTransition == 255) lowestTransition = 0; - if (g_debugMode==2) prnt("DEBUG NRZ: detectstrongNRZclk smallest wave: %d", lowestTransition); + if (g_debugMode == 2) prnt("DEBUG NRZ: detectstrongNRZclk smallest wave: %d", lowestTransition); // if less than 10% of the samples were not peaks (or 90% were peaks) then we have a strong wave if (transitionSampleCount / size < 10) { *strong = true; @@ -795,7 +800,7 @@ int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx) } else if (peaksdet[m] > peaksdet[best]){ best = m; } - if (g_debugMode==2) prnt("DEBUG NRZ: Clk: %d, peaks: %d, minPeak: %d, bestClk: %d, lowestTrs: %d", clk[m], peaksdet[m], minPeak, clk[best], lowestTransition); + if (g_debugMode == 2) prnt("DEBUG NRZ: Clk: %d, peaks: %d, minPeak: %d, bestClk: %d, lowestTrs: %d", clk[m], peaksdet[m], minPeak, clk[best], lowestTransition); } *clockStartIdx = bestStart[best]; return clk[best]; @@ -867,7 +872,7 @@ uint16_t countFC(uint8_t *bits, size_t size, uint8_t fskAdj) { } else if(fcCnts[i]>fcCnts[best3]){ best3=i; } - if (g_debugMode==2) prnt("DEBUG countfc: FC %u, Cnt %u, best fc: %u, best2 fc: %u",fcLens[i],fcCnts[i],fcLens[best1],fcLens[best2]); + if (g_debugMode == 2) prnt("DEBUG countfc: FC %u, Cnt %u, best fc: %u, best2 fc: %u",fcLens[i],fcCnts[i],fcLens[best1],fcLens[best2]); if (fcLens[i]==0) break; } if (fcLens[best1]==0) return 0; @@ -880,7 +885,7 @@ uint16_t countFC(uint8_t *bits, size_t size, uint8_t fskAdj) { fcL=fcLens[best1]; } if ((size-180)/fcH/3 > fcCnts[best1]+fcCnts[best2]) { - if (g_debugMode==2) prnt("DEBUG countfc: fc is too large: %u > %u. Not psk or fsk",(size-180)/fcH/3,fcCnts[best1]+fcCnts[best2]); + if (g_debugMode == 2) prnt("DEBUG countfc: fc is too large: %u > %u. Not psk or fsk",(size-180)/fcH/3,fcCnts[best1]+fcCnts[best2]); return 0; //lots of waves not psk or fsk } // TODO: take top 3 answers and compare to known Field clocks to get top 2 @@ -910,7 +915,7 @@ int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShif *fc = fcs & 0xFF; - if (g_debugMode==2) prnt("DEBUG PSK: FC: %d, FC2: %d",*fc, fcs>>8); + if (g_debugMode == 2) prnt("DEBUG PSK: FC: %d, FC2: %d",*fc, fcs>>8); if ((fcs >> 8) == 10 && *fc == 8) return 0; @@ -1068,14 +1073,14 @@ uint8_t detectFSKClk(uint8_t *bits, size_t size, uint8_t fcHigh, uint8_t fcLow, } else if(rfCnts[i] > rfCnts[rfHighest3]){ rfHighest3 = i; } - if (g_debugMode==2) + if (g_debugMode == 2) prnt("DEBUG FSK: RF %d, cnts %d", rfLens[i], rfCnts[i]); } // set allowed clock remainder tolerance to be 1 large field clock length+1 // we could have mistakenly made a 9 a 10 instead of an 8 or visa versa so rfLens could be 1 FC off uint8_t tol1 = fcHigh+1; - if (g_debugMode==2) + if (g_debugMode == 2) prnt("DEBUG FSK: most counted rf values: 1 %d, 2 %d, 3 %d", rfLens[rfHighest], rfLens[rfHighest2], rfLens[rfHighest3]); // loop to find the highest clock that has a remainder less than the tolerance @@ -1086,7 +1091,7 @@ uint8_t detectFSKClk(uint8_t *bits, size_t size, uint8_t fcHigh, uint8_t fcLow, if (rfLens[rfHighest] % clk[ii] < tol1 || rfLens[rfHighest] % clk[ii] > clk[ii]-tol1){ if (rfLens[rfHighest2] % clk[ii] < tol1 || rfLens[rfHighest2] % clk[ii] > clk[ii]-tol1){ if (rfLens[rfHighest3] % clk[ii] < tol1 || rfLens[rfHighest3] % clk[ii] > clk[ii]-tol1){ - if (g_debugMode==2) + if (g_debugMode == 2) prnt("DEBUG FSK: clk %d divides into the 3 most rf values within tolerance",clk[ii]); break; } @@ -1147,7 +1152,7 @@ bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, s clk = getClosestClock(minClk); // clock not found - ERROR if (!clk) { - if (g_debugMode==2) prnt("DEBUG STT: clock not found - quitting"); + if (g_debugMode == 2) prnt("DEBUG STT: clock not found - quitting"); return false; } *foundclock = clk; @@ -1155,10 +1160,10 @@ bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, s tol = clk/8; if (!findST(&start, &skip, tmpbuff, waveLen, clk, tol, j, &i)) { // first ST not found - ERROR - if (g_debugMode==2) prnt("DEBUG STT: first STT not found - quitting"); + if (g_debugMode == 2) prnt("DEBUG STT: first STT not found - quitting"); return false; } else { - if (g_debugMode==2) prnt("DEBUG STT: first STT found at wave: %i, skip: %i, j=%i", start, skip, j); + if (g_debugMode == 2) prnt("DEBUG STT: first STT found at wave: %i, skip: %i, j=%i", start, skip, j); } if (waveLen[i+2] > clk*1+tol) phaseoff = 0; @@ -1174,11 +1179,11 @@ bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, s i += 3; if (!findST(&dummy1, &end, tmpbuff, waveLen, clk, tol, j, &i)) { //didn't find second ST - ERROR - if (g_debugMode==2) prnt("DEBUG STT: second STT not found - quitting"); + if (g_debugMode == 2) prnt("DEBUG STT: second STT not found - quitting"); return false; } end -= phaseoff; - if (g_debugMode==2) prnt("DEBUG STT: start of data: %d end of data: %d, datalen: %d, clk: %d, bits: %d, phaseoff: %d", skip, end, end-skip, clk, (end-skip)/clk, phaseoff); + if (g_debugMode == 2) prnt("DEBUG STT: start of data: %d end of data: %d, datalen: %d, clk: %d, bits: %d, phaseoff: %d", skip, end, end-skip, clk, (end-skip)/clk, phaseoff); //now begin to trim out ST so we can use normal demod cmds start = skip; size_t datalen = end - start; @@ -1190,12 +1195,12 @@ bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, s // padd the amount off - could be problematic... but shouldn't happen often datalen -= datalen % clk; } else { - if (g_debugMode==2) prnt("DEBUG STT: datalen not divisible by clk: %u %% %d = %d - quitting", datalen, clk, datalen % clk); + if (g_debugMode == 2) prnt("DEBUG STT: datalen not divisible by clk: %u %% %d = %d - quitting", datalen, clk, datalen % clk); return false; } // if datalen is less than one t55xx block - ERROR if (datalen/clk < 8*4) { - if (g_debugMode==2) prnt("DEBUG STT: datalen is less than 1 full t55xx block - quitting"); + if (g_debugMode == 2) prnt("DEBUG STT: datalen is less than 1 full t55xx block - quitting"); return false; } size_t dataloc = start; @@ -1211,7 +1216,7 @@ bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, s size_t newloc = 0; i=0; - if (g_debugMode==2) prnt("DEBUG STT: Starting STT trim - start: %d, datalen: %d ",dataloc, datalen); + if (g_debugMode == 2) prnt("DEBUG STT: Starting STT trim - start: %d, datalen: %d ",dataloc, datalen); bool firstrun = true; // warning - overwriting buffer given with raw wave data with ST removed... while ( dataloc < bufsize-(clk/2) ) { @@ -1241,7 +1246,7 @@ bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, s } newloc += i; //skip next ST - we just assume it will be there from now on... - if (g_debugMode==2) prnt("DEBUG STT: skipping STT at %d to %d", dataloc, dataloc+(clk*4)); + if (g_debugMode == 2) prnt("DEBUG STT: skipping STT at %d to %d", dataloc, dataloc+(clk*4)); dataloc += clk*4; } *size = newloc; @@ -1387,7 +1392,7 @@ int cleanAskRawDemod(uint8_t *bits, size_t *size, int clk, int invert, int high, if (smplCnt > clk-(clk/4)-1) { //full clock if (smplCnt > clk + (clk/4)+1) { //too many samples errCnt++; - if (g_debugMode==2) prnt("DEBUG:(cleanAskRawDemod) ASK Modulation Error at: %u", i); + if (g_debugMode == 2) prnt("DEBUG:(cleanAskRawDemod) ASK Modulation Error at: %u", i); bits[bitCnt++] = 7; } else if (waveHigh) { bits[bitCnt++] = invert; @@ -1431,7 +1436,7 @@ int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, if (*clk==0 || start < 0) return -3; if (*invert != 1) *invert = 0; if (amp==1) askAmp(bits, *size); - if (g_debugMode==2) prnt("DEBUG ASK: clk %d, beststart %d, amp %d", *clk, start, amp); + if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, beststart %d, amp %d", *clk, start, amp); //start pos from detect ask clock is 1/2 clock offset // NOTE: can be negative (demod assumes rest of wave was there) @@ -1448,7 +1453,7 @@ int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, // if clean clipped waves detected run alternate demod if (DetectCleanAskWave(bits, *size, high, low)) { - if (g_debugMode==2) prnt("DEBUG ASK: Clean Wave Detected - using clean wave demod"); + if (g_debugMode == 2) prnt("DEBUG ASK: Clean Wave Detected - using clean wave demod"); errCnt = cleanAskRawDemod(bits, size, *clk, *invert, high, low, startIdx); @@ -1479,7 +1484,7 @@ int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, bits[bitnum++] = *invert ^ 1; } else if (i-lastBit >= *clk+tol) { if (bitnum > 0) { - if (g_debugMode==2) prnt("DEBUG: (askdemod_ext) Modulation Error at: %u", i); + if (g_debugMode == 2) prnt("DEBUG: (askdemod_ext) Modulation Error at: %u", i); bits[bitnum++]=7; errCnt++; } @@ -1545,7 +1550,7 @@ int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startId numBits += (i - lastBit + (*clk/4)) / *clk; if (lastBit == 0) { *startIdx = i - (numBits * *clk); - if (g_debugMode==2) prnt("DEBUG NRZ: startIdx %i", *startIdx); + if (g_debugMode == 2) prnt("DEBUG NRZ: startIdx %i", *startIdx); } lastBit = i-1; } @@ -1791,7 +1796,7 @@ int pskRawDemod_ext(uint8_t *dest, size_t *size, int *clock, int *invert, int *s *startIdx = firstFullWave - (*clock * numBits)+2; //set start of wave as clock align lastClkBit = firstFullWave; - if (g_debugMode==2) prnt("DEBUG PSK: firstFullWave: %u, waveLen: %u, startIdx %i",firstFullWave,fullWaveLen, *startIdx); + if (g_debugMode == 2) prnt("DEBUG PSK: firstFullWave: %u, waveLen: %u, startIdx %i",firstFullWave,fullWaveLen, *startIdx); if (g_debugMode == 2) prnt("DEBUG PSK: clk: %d, lastClkBit: %u, fc: %u", *clock, lastClkBit, fc); waveStart = 0; dest[numBits++] = curPhase; //set first read bit From ba9de80eeb3c63bb78ccc97cb758cc2359db0609 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 9 Sep 2018 11:29:11 +0200 Subject: [PATCH 0031/1938] chg: 'hf legic sim' break sim by sending another cmd --- armsrc/legicrfsim.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/legicrfsim.c b/armsrc/legicrfsim.c index 71c747115..1816a29ca 100644 --- a/armsrc/legicrfsim.c +++ b/armsrc/legicrfsim.c @@ -460,7 +460,7 @@ void LegicRfSimulate(uint8_t cardtype) { LED_A_ON(); DbpString("Starting Legic emulator, press button to end"); - while(!BUTTON_PRESS()) { + while (!BUTTON_PRESS() && !usb_poll_validate_length()) { WDT_HIT(); // wait for carrier, restart after timeout From 90f29bf430a73d3824eab03abc0f7b8886bb3201 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 9 Sep 2018 11:29:37 +0200 Subject: [PATCH 0032/1938] chg: call specific noise function --- armsrc/lfsampling.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index c419d5781..22171e2c3 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -204,7 +204,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag } // Ensure that noise check is performed for any device-side processing - justNoise(dest, bufsize); + isNoise(dest, bufsize); return data.numbits; } From d774e4c84fb59a1ff4f3aa61fd52e92547769883 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 9 Sep 2018 12:34:43 +0200 Subject: [PATCH 0033/1938] Chg: step2 in the signed vis unsigned graphbuffer signal processing. It will break some tone-based demods like ti etc. --- client/cmddata.c | 48 ++++++++----- client/cmdlf.c | 68 +++++++++--------- client/cmdlfem4x.c | 138 ++++++++++++++++++------------------ client/cmdlfindala.c | 40 ++++++----- client/cmdlfio.c | 4 +- client/cmdlft55xx.c | 17 +++-- common/lfdemod.c | 164 ++++++++++++++++++++++++++++--------------- common/lfdemod.h | 14 ++-- 8 files changed, 276 insertions(+), 217 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 7d8cef081..f4bfb3ff4 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -456,8 +456,8 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, int maxErr = 100; int maxLen = 0; uint8_t askamp = 0; - char amp = param_getchar(Cmd, 0); - uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; + char amp = tolower(param_getchar(Cmd, 0)); + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; sscanf(Cmd, "%i %i %i %i %c", &clk, &invert, &maxErr, &maxLen, &); @@ -473,7 +473,7 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, clk = 0; } - size_t BitLen = getFromGraphBuf(BitStream); + size_t BitLen = getFromGraphBuf(bits); PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Bitlen from grphbuff: %d", BitLen); @@ -483,13 +483,13 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, int foundclk = 0; //amp before ST check - if (amp == 'a' || amp == 'A') - askAmp(BitStream, BitLen); + if (amp == 'a') + askAmp(bits, BitLen); bool st = false; size_t ststart = 0, stend = 0; if (*stCheck) - st = DetectST(BitStream, &BitLen, &foundclk, &ststart, &stend); + st = DetectST(bits, &BitLen, &foundclk, &ststart, &stend); if (st) { *stCheck = st; @@ -501,10 +501,10 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, } int startIdx = 0; - int errCnt = askdemod_ext(BitStream, &BitLen, &clk, &invert, maxErr, askamp, askType, &startIdx); + int errCnt = askdemod_ext(bits, &BitLen, &clk, &invert, maxErr, askamp, askType, &startIdx); if (errCnt < 0 || BitLen < 16){ //if fatal error (or -1) - PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) No data found errors:%d, invert:%d, bitlen:%d, clock:%d", errCnt, invert, BitLen, clk); + PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) No data found errors:%d, invert:%c, bitlen:%d, clock:%d", errCnt, (invert)?'Y':'N', BitLen, clk); return 0; } @@ -516,7 +516,7 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Using clock:%d, invert:%d, bits found:%d", clk, invert, BitLen); //output - setDemodBuf(BitStream,BitLen,0); + setDemodBuf(bits, BitLen, 0); setClockGrid(clk, startIdx); if (verbose || g_debugMode){ @@ -1429,6 +1429,7 @@ int getSamples(int n, bool silent) { GraphTraceLen = j; if (!silent) PrintAndLogEx(NORMAL, "Unpacked %d samples" , j ); + } else { for (int j = 0; j < n; j++) { GraphBuffer[j] = ((int)got[j]) - 128; @@ -1436,9 +1437,11 @@ int getSamples(int n, bool silent) { GraphTraceLen = n; } -//ICEMAN todo - // set signal properties low/high/mean/amplitude and is_noice detection - justNoise(GraphBuffer, GraphTraceLen); + //ICEMAN todo + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + // set signal properties low/high/mean/amplitude and is_noice detection + isNoise(bits, size); setClockGrid(0, 0); DemodBufferLen = 0; @@ -1569,9 +1572,9 @@ int CmdLoad(const char *Cmd) { DemodBufferLen = 0; RepaintGraphWindow(); -//ICEMAN todo + //ICEMAN todo // set signal properties low/high/mean/amplitude and isnoice detection - justNoise(GraphBuffer, GraphTraceLen); + isNoise_int(GraphBuffer, GraphTraceLen); return 0; } @@ -1637,9 +1640,9 @@ int CmdNorm(const char *Cmd) { } RepaintGraphWindow(); -//ICEMAN todo + //ICEMAN todo // set signal properties low/high/mean/amplitude and isnoice detection - justNoise(GraphBuffer, GraphTraceLen); + isNoise_int(GraphBuffer, GraphTraceLen); return 0; } @@ -1722,7 +1725,12 @@ int CmdDirectionalThreshold(const char *Cmd) { PrintAndLogEx(INFO, "Applying Up Threshold: %d, Down Threshold: %d\n", up, down); - directionalThreshold(GraphBuffer, GraphBuffer,GraphTraceLen, up, down); + directionalThreshold(GraphBuffer, GraphBuffer, GraphTraceLen, up, down); + + //ICEMAN todo + // set signal properties low/high/mean/amplitude and isnoice detection + isNoise_int(GraphBuffer, GraphTraceLen); + RepaintGraphWindow(); return 0; } @@ -1751,7 +1759,7 @@ int CmdZerocrossings(const char *Cmd) { //ICEMAN todo // set signal properties low/high/mean/amplitude and isnoice detection - justNoise(GraphBuffer, GraphTraceLen); + isNoise_int(GraphBuffer, GraphTraceLen); RepaintGraphWindow(); return 0; @@ -2004,6 +2012,10 @@ int CmdDataIIR(const char *Cmd){ uint8_t k = param_get8(Cmd, 0); //iceIIR_Butterworth(GraphBuffer, GraphTraceLen); iceSimple_Filter(GraphBuffer, GraphTraceLen, k); + //ICEMAN todo + // set signal properties low/high/mean/amplitude and isnoice detection + isNoise_int(GraphBuffer, GraphTraceLen); + RepaintGraphWindow(); return 0; } diff --git a/client/cmdlf.c b/client/cmdlf.c index ccb781014..50077add2 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -147,10 +147,9 @@ int CmdLFCommandRead(const char *Cmd) { bool errors = false; uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': - case 'H': return usage_lf_cmdread(); case 'c': param_getstr(Cmd, cmdp+1, (char *)&c.d.asBytes, sizeof(c.d.asBytes)); @@ -188,16 +187,20 @@ int CmdLFCommandRead(const char *Cmd) { int CmdFlexdemod(const char *Cmd) { #define LONG_WAIT 100 - int i, j, start, bit, sum; - int phase = 0; + int i, j, start, bit, sum, phase = 0; - for (i = 0; i < GraphTraceLen; ++i) - GraphBuffer[i] = (GraphBuffer[i] < 0) ? -1 : 1; + uint8_t data[MAX_GRAPH_TRACE_LEN] = {0}; + size_t size = getFromGraphBuf(data); + if (size == 0) + return 0; + + for (i = 0; i < size; ++i) + data[i] = (data[i] < 0) ? -1 : 1; - for (start = 0; start < GraphTraceLen - LONG_WAIT; start++) { - int first = GraphBuffer[start]; + for (start = 0; start < size - LONG_WAIT; start++) { + int first = data[start]; for (i = start; i < start + LONG_WAIT; i++) { - if (GraphBuffer[i] != first) { + if (data[i] != first) { break; } } @@ -205,20 +208,21 @@ int CmdFlexdemod(const char *Cmd) { break; } - if (start == GraphTraceLen - LONG_WAIT) { + if (start == size - LONG_WAIT) { PrintAndLogEx(NORMAL, "nothing to wait for"); return 0; } - GraphBuffer[start] = 2; - GraphBuffer[start+1] = -2; + data[start] = 4; + data[start+1] = 0; + uint8_t bits[64] = {0x00}; i = start; for (bit = 0; bit < 64; bit++) { sum = 0; for (int j = 0; j < 16; j++) { - sum += GraphBuffer[i++]; + sum += data[i++]; } bits[bit] = (sum > 0) ? 1 : 0; PrintAndLogEx(NORMAL, "bit %d sum %d", bit, sum); @@ -227,7 +231,7 @@ int CmdFlexdemod(const char *Cmd) { for (bit = 0; bit < 64; bit++) { sum = 0; for (j = 0; j < 16; j++) - sum += GraphBuffer[i++]; + sum += data[i++]; if (sum > 0 && bits[bit] != 1) PrintAndLogEx(NORMAL, "oops1 at %d", bit); @@ -235,8 +239,9 @@ int CmdFlexdemod(const char *Cmd) { } + // iceman, use demod buffer? blue line? // HACK writing back to graphbuffer. - GraphTraceLen = 32*64; + GraphTraceLen = 32 * 64; i = 0; for (bit = 0; bit < 64; bit++) { @@ -261,8 +266,8 @@ int CmdLFSetConfig(const char *Cmd) { uint8_t unsigned_trigg = 0; uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (param_getchar(Cmd, cmdp)) { case 'h': return usage_lf_config(); case 'H': @@ -348,18 +353,15 @@ int CmdLFRead(const char *Cmd) { bool silent = false; uint32_t samples = 0; uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': - case 'H': return usage_lf_read(); case 's': - case 'S': silent = true; cmdp++; break; case 'd': - case 'D': samples = param_get32ex(Cmd, cmdp, 0, 10); cmdp +=2; break; @@ -377,8 +379,8 @@ int CmdLFRead(const char *Cmd) { } int CmdLFSnoop(const char *Cmd) { - uint8_t cmdp = param_getchar(Cmd, 0); - if(cmdp == 'h' || cmdp == 'H') return usage_lf_snoop(); + uint8_t cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_lf_snoop(); UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES,{0,0,0}}; clearCommandBuffer(); @@ -444,8 +446,8 @@ int CmdLFfskSim(const char *Cmd) { int dataLen = 0; uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)){ + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (param_getchar(Cmd, cmdp)){ case 'h': return usage_lf_simfsk(); case 'c': @@ -473,7 +475,7 @@ int CmdLFfskSim(const char *Cmd) { if (dataLen == 0) errors = true; if (errors) PrintAndLogEx(WARNING, "Error getting hex data"); - cmdp+=2; + cmdp += 2; break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); @@ -533,13 +535,12 @@ int CmdLFaskSim(const char *Cmd) { uint8_t encoding = 1, separator = 0, clk = 0, invert = 0; bool errors = false; char hexData[64] = {0x00}; - uint8_t data[255]= {0x00}; // store entered hex data + uint8_t data[255] = {0x00}; // store entered hex data int dataLen = 0; uint8_t cmdp = 0; while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { - case 'H': + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_lf_simask(); case 'i': invert = 1; @@ -632,8 +633,8 @@ int CmdLFpskSim(const char *Cmd) { uint8_t cmdp = 0; uint8_t pskType = 1; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_lf_simpsk(); case 'i': @@ -735,6 +736,7 @@ int CmdLFSimBidir(const char *Cmd) { return 0; } +// ICEMAN, todo, swap from Graphbuffer. int CmdVchDemod(const char *Cmd) { // Is this the entire sync pattern, or does this also include some // data bits that happen to be the same everywhere? That would be diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 806628fcb..1664a3c2b 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -411,7 +411,7 @@ int CmdEM410xRead(const char *Cmd) { // this read loops on device side. // uses the demod in lfops.c int CmdEM410xRead_device(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); + char cmdp = tolower(param_getchar(Cmd, 0)); uint8_t findone = (cmdp == '1') ? 1 : 0; UsbCommand c = {CMD_EM410X_DEMOD, {findone, 0, 0}}; SendCommand(&c); @@ -423,13 +423,13 @@ int CmdEM410xRead_device(const char *Cmd) { //attempts to demodulate ask while decoding manchester //prints binary found and saves in graphbuffer for further commands int CmdEM410xDemod(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) > 10 || cmdp == 'h' || cmdp == 'H') return usage_lf_em410x_demod(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 10 || cmdp == 'h') return usage_lf_em410x_demod(); uint32_t hi = 0; uint64_t lo = 0; - if(AskEm410xDemod(Cmd, &hi, &lo, true) != 1) return 0; + if (AskEm410xDemod(Cmd, &hi, &lo, true) != 1) return 0; g_em410xid = lo; return 1; @@ -437,8 +437,8 @@ int CmdEM410xDemod(const char *Cmd) { // emulate an EM410X tag int CmdEM410xSim(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_lf_em410x_sim(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_lf_em410x_sim(); uint8_t uid[5] = {0x00}; @@ -594,8 +594,8 @@ int CmdEM410xWatch(const char *Cmd) { //currently only supports manchester modulations int CmdEM410xWatchnSpoof(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_lf_em410x_ws(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_lf_em410x_ws(); // loops if the captured ID was in XL-format. CmdEM410xWatch(Cmd); @@ -784,64 +784,59 @@ uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool //completed by Marshmellow int EM4x50Read(const char *Cmd, bool verbose) { uint8_t fndClk[] = {8,16,32,40,50,64,128}; - int clk = 0; - int invert = 0; - int tol = 0; - int i, j, startblock, skip, block, start, end, low, high, minClk; - bool complete = false; - int tmpbuff[MAX_GRAPH_TRACE_LEN / 64]; + int clk = 0, invert = 0, tol = 0, phaseoff; + int i = 0, j = 0, startblock, skip, block, start, end, low = 0, high = 0, minClk = 255; uint32_t Code[6]; char tmp[6]; char tmp2[20]; - int phaseoff; - high = low = 0; + bool complete = false; + + int tmpbuff[MAX_GRAPH_TRACE_LEN / 64]; memset(tmpbuff, 0, sizeof(tmpbuff) ); // get user entry if any sscanf(Cmd, "%i %i", &clk, &invert); - // first get high and low values - for (i = 0; i < GraphTraceLen; i++) { - if (GraphBuffer[i] > high) - high = GraphBuffer[i]; - else if (GraphBuffer[i] < low) - low = GraphBuffer[i]; - } + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; + size_t size = getFromGraphBuf(bits); + + isNoise(bits, size); + + signal_t *sp = getSignalProperties(); + high = sp->high; + low = sp->low; - i = 0; - j = 0; - minClk = 255; // get to first full low to prime loop and skip incomplete first pulse - while ((GraphBuffer[i] < high) && (i < GraphTraceLen)) + while ((bits[i] < high) && (i < size)) ++i; - while ((GraphBuffer[i] > low) && (i < GraphTraceLen)) + while ((bits[i] > low) && (i < size)) ++i; skip = i; // populate tmpbuff buffer with pulse lengths - while (i < GraphTraceLen) { + while (i < size) { // measure from low to low - while ((GraphBuffer[i] > low) && (i < GraphTraceLen)) + while ((bits[i] > low) && (i < size)) ++i; start= i; - while ((GraphBuffer[i] < high) && (i < GraphTraceLen)) + while ((bits[i] < high) && (i < size)) ++i; - while ((GraphBuffer[i] > low) && (i < GraphTraceLen)) + while ((bits[i] > low) && (i < size)) ++i; - if (j>=(MAX_GRAPH_TRACE_LEN/64)) { + if (j >= (MAX_GRAPH_TRACE_LEN/64)) { break; } - tmpbuff[j++]= i - start; - if (i-start < minClk && i < GraphTraceLen) { + tmpbuff[j++] = i - start; + if (i-start < minClk && i < size) { minClk = i - start; } } // set clock if (!clk) { - for (uint8_t clkCnt = 0; clkCnt<7; clkCnt++) { - tol = fndClk[clkCnt]/8; - if (minClk >= fndClk[clkCnt]-tol && minClk <= fndClk[clkCnt]+1) { - clk=fndClk[clkCnt]; + for (uint8_t clkCnt = 0; clkCnt < 7; clkCnt++) { + tol = fndClk[clkCnt] / 8; + if (minClk >= fndClk[clkCnt] - tol && minClk <= fndClk[clkCnt] + 1) { + clk = fndClk[clkCnt]; break; } } @@ -849,15 +844,15 @@ int EM4x50Read(const char *Cmd, bool verbose) { if (verbose || g_debugMode) PrintAndLogEx(WARNING, "Error: EM4x50 - didn't find a clock"); return 0; } - } else tol = clk/8; + } else tol = clk / 8; // look for data start - should be 2 pairs of LW (pulses of clk*3,clk*2) start = -1; for (i= 0; i < j - 4 ; ++i) { skip += tmpbuff[i]; - if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol) //3 clocks - if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol) //2 clocks - if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3+tol) //3 clocks + if (tmpbuff[i] >= clk * 3 - tol && tmpbuff[i] <= clk * 3 + tol) //3 clocks + if (tmpbuff[i+1] >= clk * 2 - tol && tmpbuff[i+1] <= clk * 2 + tol) //2 clocks + if (tmpbuff[i+2] >= clk * 3 - tol && tmpbuff[i+2] <= clk * 3 + tol) //3 clocks if (tmpbuff[i+3] >= clk-tol) //1.5 to 2 clocks - depends on bit following { start= i + 4; @@ -867,18 +862,20 @@ int EM4x50Read(const char *Cmd, bool verbose) { startblock = i + 4; // skip over the remainder of LW - skip += tmpbuff[i+1] + tmpbuff[i+2] + clk; - if (tmpbuff[i+3]>clk) - phaseoff = tmpbuff[i+3]-clk; + skip += (tmpbuff[i+1] + tmpbuff[i+2] + clk); + + if (tmpbuff[i+3] > clk) + phaseoff = tmpbuff[i+3] - clk; else phaseoff = 0; + // now do it again to find the end end = skip; for (i += 3; i < j - 4 ; ++i) { end += tmpbuff[i]; - if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol) //3 clocks - if (tmpbuff[i+1] >= clk*2-tol && tmpbuff[i+1] <= clk*2+tol) //2 clocks - if (tmpbuff[i+2] >= clk*3-tol && tmpbuff[i+2] <= clk*3+tol) //3 clocks + if (tmpbuff[i] >= clk * 3 - tol && tmpbuff[i] <= clk * 3 + tol) //3 clocks + if (tmpbuff[i+1] >= clk * 2 - tol && tmpbuff[i+1] <= clk * 2 + tol) //2 clocks + if (tmpbuff[i+2] >= clk * 3 - tol && tmpbuff[i+2] <= clk * 3 + tol) //3 clocks if (tmpbuff[i+3] >= clk-tol) //1.5 to 2 clocks - depends on bit following { complete= true; @@ -897,8 +894,9 @@ int EM4x50Read(const char *Cmd, bool verbose) { return 0; } } else if (start < 0) return 0; + start = skip; - snprintf(tmp2, sizeof(tmp2),"%d %d 1000 %d", clk, invert, clk*47); + snprintf(tmp2, sizeof(tmp2),"%d %d 1000 %d", clk, invert, clk * 47); // save GraphBuffer - to restore it later save_restoreGB(GRAPH_SAVE); // get rid of leading crap @@ -916,17 +914,19 @@ int EM4x50Read(const char *Cmd, bool verbose) { // look for LW before start of next block for ( ; i < j - 4 ; ++i) { skip += tmpbuff[i]; - if (tmpbuff[i] >= clk*3-tol && tmpbuff[i] <= clk*3+tol) + if (tmpbuff[i] >= clk * 3 - tol && tmpbuff[i] <= clk * 3 + tol) if (tmpbuff[i+1] >= clk-tol) break; } if (i >= j-4) break; //next LW not found skip += clk; - if (tmpbuff[i+1]>clk) - phaseoff = tmpbuff[i+1]-clk; + if (tmpbuff[i+1] > clk) + phaseoff = tmpbuff[i+1] - clk; else phaseoff = 0; + i += 2; + if (ASKDemod(tmp2, false, false, 1) < 1) { save_restoreGB(GRAPH_RESTORE); return 0; @@ -934,14 +934,14 @@ int EM4x50Read(const char *Cmd, bool verbose) { //set DemodBufferLen to just one block DemodBufferLen = skip/clk; //test parities - pTest = EM_ByteParityTest(DemodBuffer,DemodBufferLen,5,9,0); - pTest &= EM_EndParityTest(DemodBuffer,DemodBufferLen,5,9,0); + pTest = EM_ByteParityTest(DemodBuffer,DemodBufferLen, 5, 9, 0); + pTest &= EM_EndParityTest(DemodBuffer,DemodBufferLen, 5, 9, 0); AllPTest &= pTest; //get output - Code[block] = OutputEM4x50_Block(DemodBuffer,DemodBufferLen,verbose, pTest); + Code[block] = OutputEM4x50_Block(DemodBuffer, DemodBufferLen, verbose, pTest); PrintAndLogEx(DEBUG, "\nskipping %d samples, bits:%d", skip, skip/clk); //skip to start of next block - snprintf(tmp,sizeof(tmp),"%i",skip); + snprintf(tmp, sizeof(tmp), "%i", skip); CmdLtrim(tmp); block++; if (i >= end) break; //in case chip doesn't output 6 blocks @@ -956,7 +956,7 @@ int EM4x50Read(const char *Cmd, bool verbose) { PrintAndLogEx(NORMAL, "Found data at sample: %i - using clock: %i", start, clk); end = block; for (block=0; block < end; block++){ - PrintAndLogEx(NORMAL, "Block %d: %08x",block,Code[block]); + PrintAndLogEx(NORMAL, "Block %d: %08x", block, Code[block]); } if (AllPTest) { PrintAndLogEx(NORMAL, "Parities Passed"); @@ -972,19 +972,19 @@ int EM4x50Read(const char *Cmd, bool verbose) { } int CmdEM4x50Read(const char *Cmd) { - uint8_t ctmp = param_getchar(Cmd, 0); - if ( ctmp == 'H' || ctmp == 'h' ) return usage_lf_em4x50_read(); + uint8_t ctmp = tolower(param_getchar(Cmd, 0)); + if ( ctmp == 'h' ) return usage_lf_em4x50_read(); return EM4x50Read(Cmd, true); } int CmdEM4x50Write(const char *Cmd){ - uint8_t ctmp = param_getchar(Cmd, 0); - if ( ctmp == 'H' || ctmp == 'h' ) return usage_lf_em4x50_write(); + uint8_t ctmp = tolower(param_getchar(Cmd, 0)); + if ( ctmp == 'h' ) return usage_lf_em4x50_write(); PrintAndLogEx(NORMAL, "no implemented yet"); return 0; } int CmdEM4x50Dump(const char *Cmd){ - uint8_t ctmp = param_getchar(Cmd, 0); - if ( ctmp == 'H' || ctmp == 'h' ) return usage_lf_em4x50_dump(); + uint8_t ctmp = tolower(param_getchar(Cmd, 0)); + if ( ctmp == 'h' ) return usage_lf_em4x50_dump(); PrintAndLogEx(NORMAL, "no implemented yet"); return 0; } @@ -1000,6 +1000,11 @@ bool downloadSamplesEM(){ return false; } setGraphBuf(got, sizeof(got)); + + if (isNoise(got, sizeof(got))) { + PrintAndLogEx(DEBUG, "No tag found"); + return false; + } return true; } @@ -1146,12 +1151,7 @@ int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word) if ( !downloadSamplesEM() ) { return -1; } - int testLen = (GraphTraceLen < 1000) ? GraphTraceLen : 1000; - if (justNoise(GraphBuffer, testLen)) { - PrintAndLogEx(DEBUG, "No tag found"); - return -1; - } return demodEM4x05resp(word); } diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index f4993fb5e..dd262e0dc 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -184,9 +184,11 @@ int CmdIndalaDemodAlt(const char *Cmd) { int count = 0; int i, j; - // worst case with GraphTraceLen=64000 is < 4096 + // worst case with GraphTraceLen=40000 is < 4096 // under normal conditions it's < 2048 - + uint8_t data[MAX_GRAPH_TRACE_LEN] = {0}; + size_t datasize = getFromGraphBuf(data); + uint8_t rawbits[4096]; int rawbit = 0; int worst = 0, worstPos = 0; @@ -197,9 +199,9 @@ int CmdIndalaDemodAlt(const char *Cmd) { // PrintAndLogEx(NORMAL, "Expecting a bit less than %d raw bits", GraphTraceLen / 32); // loop through raw signal - since we know it is psk1 rf/32 fc/2 skip every other value (+=2) - for (i = 0; i < GraphTraceLen-1; i += 2) { + for (i = 0; i < datasize-1; i += 2) { count += 1; - if ((GraphBuffer[i] > GraphBuffer[i + 1]) && (state != 1)) { + if ((data[i] > data[i + 1]) && (state != 1)) { // appears redundant - marshmellow if (state == 0) { for (j = 0; j < count - 8; j += 16) { @@ -212,7 +214,7 @@ int CmdIndalaDemodAlt(const char *Cmd) { } state = 1; count = 0; - } else if ((GraphBuffer[i] < GraphBuffer[i + 1]) && (state != 0)) { + } else if ((data[i] < data[i + 1]) && (state != 0)) { //appears redundant if (state == 1) { for (j = 0; j < count - 8; j += 16) { @@ -228,7 +230,7 @@ int CmdIndalaDemodAlt(const char *Cmd) { } } - if (rawbit>0){ + if (rawbit > 0){ PrintAndLogEx(NORMAL, "Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32); PrintAndLogEx(NORMAL, "worst metric (0=best..7=worst): %d at pos %d", worst, worstPos); } else { @@ -301,14 +303,14 @@ int CmdIndalaDemodAlt(const char *Cmd) { int idx; uid1 = uid2 = 0; - if (uidlen==64){ - for( idx=0; idx<64; idx++) { + if (uidlen == 64){ + for( idx=0; idx < 64; idx++) { if (showbits[idx] == '0') { - uid1=(uid1<<1)|(uid2>>31); - uid2=(uid2<<1)|0; + uid1 = (uid1<<1) | (uid2>>31); + uid2 = (uid2<<1) | 0; } else { - uid1=(uid1<<1)|(uid2>>31); - uid2=(uid2<<1)|1; + uid1 = (uid1<<1) | (uid2>>31); + uid2 = (uid2<<1) | 1; } } PrintAndLogEx(NORMAL, "UID=%s (%x%08x)", showbits, uid1, uid2); @@ -317,12 +319,12 @@ int CmdIndalaDemodAlt(const char *Cmd) { uid3 = uid4 = uid5 = uid6 = uid7 = 0; for( idx=0; idx<224; idx++) { - uid1=(uid1<<1)|(uid2>>31); - uid2=(uid2<<1)|(uid3>>31); - uid3=(uid3<<1)|(uid4>>31); - uid4=(uid4<<1)|(uid5>>31); - uid5=(uid5<<1)|(uid6>>31); - uid6=(uid6<<1)|(uid7>>31); + uid1 = (uid1<<1) | (uid2>>31); + uid2 = (uid2<<1) | (uid3>>31); + uid3 = (uid3<<1) | (uid4>>31); + uid4 = (uid4<<1) | (uid5>>31); + uid5 = (uid5<<1) | (uid6>>31); + uid6 = (uid6<<1) | (uid7>>31); if (showbits[idx] == '0') uid7 = (uid7<<1) | 0; @@ -353,7 +355,7 @@ int CmdIndalaDemodAlt(const char *Cmd) { // Remodulating for tag cloning // HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod) // since this changes graphbuffer data. - GraphTraceLen = 32*uidlen; + GraphTraceLen = 32 * uidlen; i = 0; int phase = 0; for (bit = 0; bit < uidlen; bit++) { diff --git a/client/cmdlfio.c b/client/cmdlfio.c index a2bc08217..d2cecec4b 100644 --- a/client/cmdlfio.c +++ b/client/cmdlfio.c @@ -83,10 +83,10 @@ int CmdIOProxRead_device(const char *Cmd) { int CmdIOProxDemod(const char *Cmd) { int retval = 0; int idx = 0; - uint8_t bits[MAX_GRAPH_TRACE_LEN]={0}; + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; size_t size = getFromGraphBuf(bits); if (size < 65) { - if (g_debugMode)PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox not enough samples in GraphBuffer"); + if (g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox not enough samples in GraphBuffer"); return 0; } //get binary from fsk wave diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index c4d1e3be6..7fbf143d3 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -504,12 +504,13 @@ int CmdT55xxDetect(const char *Cmd){ // detect configuration? bool tryDetectModulation(){ - uint8_t hits = 0; + t55xx_conf_block_t tests[15]; - int bitRate=0; - uint8_t fc1 = 0, fc2 = 0, ans = 0; - int clk = 0, firstClockEdge = 0; + int bitRate = 0, clk = 0, firstClockEdge = 0; + uint8_t hits = 0, fc1 = 0, fc2 = 0, ans = 0; + ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, &firstClockEdge); + if (ans && ((fc1==10 && fc2==8) || (fc1==8 && fc2==5))) { if ( FSKrawDemod("0 0", false) && test(DEMOD_FSK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)){ tests[hits].modulation = DEMOD_FSK; @@ -1305,15 +1306,13 @@ bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ){ return false; } - //uint8_t got[12288]; - uint8_t got[7679]; - if ( !GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 6000, true)) { + uint8_t got[8000]; + if ( !GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 4000, true)) { PrintAndLogEx(WARNING, "command execution time out"); return false; } setGraphBuf(got, sizeof(got)); - - return !justNoise(GraphBuffer, sizeof(got)); + return !isNoise(got, sizeof(got)); } char * GetBitRateStr(uint32_t id, bool xmode) { diff --git a/common/lfdemod.c b/common/lfdemod.c index 9fbf933f4..0525f7ff9 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -105,7 +105,6 @@ int32_t compute_mean_int(int *in, size_t N) { return mean / (int)N; } - void zeromean(uint8_t* data, size_t size) { // zero mean data @@ -119,13 +118,13 @@ void zeromean(uint8_t* data, size_t size) { data[i] -= accum; } - //test samples are not just noise // By measuring mean and look at amplitude of signal from HIGH / LOW, we can detect noise bool isNoise_int(int *bits, uint32_t size) { resetSignal(); if ( bits == NULL || size < 100 ) return true; - + //zeromean(bits, size); + int32_t sum = 0; for ( size_t i = 0; i < size; i++) { if ( bits[i] < signalprop.low ) signalprop.low = bits[i]; @@ -138,7 +137,7 @@ bool isNoise_int(int *bits, uint32_t size) { signalprop.amplitude = ABS(signalprop.high - signalprop.mean); signalprop.isnoise = signalprop.amplitude < NOICE_AMPLITUDE_THRESHOLD; - if (g_debugMode == 1) + if (g_debugMode) printSignal(); return signalprop.isnoise; @@ -149,6 +148,7 @@ bool isNoise_int(int *bits, uint32_t size) { bool isNoise(uint8_t *bits, uint32_t size) { resetSignal(); if ( bits == NULL || size < 100 ) return true; + zeromean(bits, size); uint32_t sum = 0; for ( uint32_t i = 0; i < size; i++) { @@ -162,7 +162,7 @@ bool isNoise(uint8_t *bits, uint32_t size) { signalprop.amplitude = signalprop.high - signalprop.mean; signalprop.isnoise = signalprop.amplitude < NOICE_AMPLITUDE_THRESHOLD; - if (g_debugMode == 1) + if (g_debugMode) printSignal(); return signalprop.isnoise; @@ -170,22 +170,20 @@ bool isNoise(uint8_t *bits, uint32_t size) { //by marshmellow //get high and low values of a wave with passed in fuzz factor. also return noise test = 1 for passed or 0 for only noise -int getHiLo(uint8_t *bits, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo) { - - // just noise - no super good detection. good enough - if (signalprop.isnoise) return -1; - +//void getHiLo(uint8_t *bits, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo) { +void getHiLo(int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo) { // add fuzz. *high = (signalprop.high * fuzzHi) / 100; if ( signalprop.low < 0 ) { *low = (signalprop.low * fuzzLo) / 100; - } else { - *low = signalprop.low * (100 + (100 - fuzzLo))/100; + } else { + uint8_t range = signalprop.high - signalprop.low; + + *low = signalprop.low + ((range * (100-fuzzLo))/100); } - if (g_debugMode > 0) + if (g_debugMode) prnt("getHiLo fuzzed: High %d | Low %d", *high, *low); - return 1; } // by marshmellow @@ -361,13 +359,17 @@ void getNextHigh(uint8_t *samples, size_t size, int high, size_t *i) { // load wave counters bool loadWaveCounters(uint8_t *samples, size_t size, int lowToLowWaveLen[], int highToLowWaveLen[], int *waveCnt, int *skip, int *minClk, int *high, int *low) { - size_t i=0, firstLow, firstHigh; - size_t testsize = (size < 512) ? size : 512; - - if ( getHiLo(samples, testsize, high, low, 80, 80) == -1 ) { + size_t i = 0, firstLow, firstHigh; + //size_t testsize = (size < 512) ? size : 512; + + // just noise - no super good detection. good enough + if (signalprop.isnoise) { if (g_debugMode == 2) prnt("DEBUG STT: just noise detected - quitting"); - return false; //just noise + return false; } + + //getHiLo(samples, testsize, high, low, 80, 80); + getHiLo(high, low, 80, 80); // get to first full low to prime loop and skip incomplete first pulse getNextHigh(samples, size, *high, &i); @@ -469,7 +471,8 @@ int ManchesterEncode(uint8_t *bits, size_t size) { // by marshmellow // to detect a wave that has heavily clipped (clean) samples -uint8_t DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low) { +// loop 512 samples, if 300 of them is deemed maxed out, we assume the wave is clipped. +bool DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low) { bool allArePeaks = true; uint16_t cntPeaks = 0; size_t loopEnd = 512 + 160; @@ -484,8 +487,9 @@ uint8_t DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low else cntPeaks++; } + if (!allArePeaks){ - if (cntPeaks > 300) return true; + if (cntPeaks > 250) return true; } return allArePeaks; } @@ -504,11 +508,13 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo size_t i = 100; size_t minClk = 512; int shortestWaveIdx = 0; - + + if (g_debugMode == 1) prnt("DEBUG ASK: DetectStrongAskClock: hi %d | low %d ", high, low); + // get to first full low to prime loop and skip incomplete first pulse getNextHigh(dest, size, high, &i); getNextLow(dest, size, low, &i); - + // loop through all samples while (i < size) { // measure from low to low @@ -516,7 +522,7 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo getNextHigh(dest, size, high, &i); getNextLow(dest, size, low, &i); - + //get minimum measured distance if (i-startwave < minClk && i < size) { minClk = i - startwave; @@ -546,18 +552,29 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { size -= 60; //sometimes there is a strange end wave - filter out this.... //if we already have a valid clock uint8_t clockFnd = 0; - for (; i < clkEnd; ++i) - if (clk[i] == *clock) clockFnd = i; - //clock found but continue to find best startpos + for (; i < clkEnd; ++i) { + if (clk[i] == *clock) { + //clock found but continue to find best startpos + clockFnd = i; + } + } + // just noise - no super good detection. good enough + if (signalprop.isnoise) { + if (g_debugMode == 2) prnt("DEBUG DetectASKClock: just noise detected - quitting"); + return -1; + } + //get high and low peak - int peak, low; - if (getHiLo(dest, loopCnt, &peak, &low, 75, 75) < 1) return -1; + int peak_hi, peak_low; + //getHiLo(dest, loopCnt, &peak_hi, &peak_low, 75, 75); + getHiLo(&peak_hi, &peak_low, 75, 75); //test for large clean peaks if (!clockFnd){ - if (DetectCleanAskWave(dest, size, peak, low)==1){ - int ans = DetectStrongAskClock(dest, size, peak, low, clock); + if (DetectCleanAskWave(dest, size, peak_hi, peak_low)){ + + int ans = DetectStrongAskClock(dest, size, peak_hi, peak_low, clock); if (g_debugMode == 2) prnt("DEBUG ASK: detectaskclk Clean Ask Wave Detected: clk %i, ShortestWave: %i", *clock ,ans); if (ans > 0){ return ans; //return shortest wave start position @@ -570,8 +587,8 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { uint16_t ii; uint8_t clkCnt, tol = 0; - uint16_t bestErr[]={1000,1000,1000,1000,1000,1000,1000,1000,1000}; - uint8_t bestStart[]={0,0,0,0,0,0,0,0,0}; + uint16_t bestErr[] = {1000,1000,1000,1000,1000,1000,1000,1000,1000}; + uint8_t bestStart[] = {0,0,0,0,0,0,0,0,0}; size_t errCnt = 0; size_t arrLoc, loopEnd; @@ -585,9 +602,9 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { //test each valid clock from smallest to greatest to see which lines up for (; clkCnt < clkEnd; clkCnt++) { if (clk[clkCnt] <= 32) { - tol=1; + tol = 1; } else { - tol=0; + tol = 0; } //if no errors allowed - keep start within the first clock if (!maxErr && size > clk[clkCnt]*2 + tol && clk[clkCnt] < 128) @@ -597,17 +614,17 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { //try lining up the peaks by moving starting point (try first few clocks) for (ii=0; ii < loopCnt; ii++){ - if (dest[ii] < peak && dest[ii] > low) continue; + if (dest[ii] < peak_hi && dest[ii] > peak_low) continue; errCnt = 0; // now that we have the first one lined up test rest of wave array loopEnd = ((size-ii-tol) / clk[clkCnt]) - 1; for (i=0; i < loopEnd; ++i){ arrLoc = ii + (i * clk[clkCnt]); - if (dest[arrLoc] >= peak || dest[arrLoc] <= low){ - }else if (dest[arrLoc-tol] >= peak || dest[arrLoc-tol] <= low){ - }else if (dest[arrLoc+tol] >= peak || dest[arrLoc+tol] <= low){ - }else{ //error no peak detected + if (dest[arrLoc] >= peak_hi || dest[arrLoc] <= peak_low){ + } else if (dest[arrLoc-tol] >= peak_hi || dest[arrLoc-tol] <= peak_low){ + } else if (dest[arrLoc+tol] >= peak_hi || dest[arrLoc+tol] <= peak_low){ + } else { //error no peak detected errCnt++; } } @@ -618,7 +635,7 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { if (!clockFnd) *clock = clk[clkCnt]; return ii; - } + } //if we found errors see if it is lowest so far and save it as best run if (errCnt < bestErr[clkCnt]) { bestErr[clkCnt] = errCnt; @@ -701,10 +718,18 @@ int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx) // size must be larger than 20 here if (size < loopCnt) loopCnt = size-20; + + // just noise - no super good detection. good enough + if (signalprop.isnoise) { + if (g_debugMode == 2) prnt("DEBUG DetectNZRClock: just noise detected - quitting"); + return 0; + } + //get high and low peak int peak, low; - if (getHiLo(dest, loopCnt, &peak, &low, 90, 90) < 1) return 0; - + //getHiLo(dest, loopCnt, &peak, &low, 90, 90); + getHiLo(&peak, &low, 90, 90); + bool strong = false; int lowestTransition = DetectStrongNRZClk(dest, size-20, peak, low, &strong); if (strong) return lowestTransition; @@ -1431,11 +1456,18 @@ int cleanAskRawDemod(uint8_t *bits, size_t *size, int clk, int invert, int high, //by marshmellow //attempts to demodulate ask modulations, askType == 0 for ask/raw, askType==1 for ask/manchester int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType, int *startIdx) { - if (*size==0) return -1; - int start = DetectASKClock(bits, *size, clk, maxErr); //clock default - if (*clk==0 || start < 0) return -3; + + if (*size == 0) return -1; + + int start = DetectASKClock(bits, *size, clk, maxErr); + if (*clk == 0 || start < 0) return -3; + if (*invert != 1) *invert = 0; - if (amp==1) askAmp(bits, *size); + + // amplify signal data. + // ICEMAN todo, + if (amp == 1) askAmp(bits, *size); + if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, beststart %d, amp %d", *clk, start, amp); //start pos from detect ask clock is 1/2 clock offset @@ -1443,12 +1475,19 @@ int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, *startIdx = start - (*clk/2); uint16_t initLoopMax = 1024; if (initLoopMax > *size) initLoopMax = *size; + + // just noise - no super good detection. good enough + if (signalprop.isnoise) { + if (g_debugMode == 2) prnt("DEBUG askdemod_ext: just noise detected - quitting"); + return -2; + } + // Detect high and lows //25% clip in case highs and lows aren't clipped [marshmellow] int high, low; - if (getHiLo(bits, initLoopMax, &high, &low, 75, 75) < 1) - return -2; //just noise - + //getHiLo(bits, initLoopMax, &high, &low, 75, 75); + getHiLo(&high, &low, 75, 75); + size_t errCnt = 0; // if clean clipped waves detected run alternate demod if (DetectCleanAskWave(bits, *size, high, low)) { @@ -1461,11 +1500,13 @@ int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, uint8_t alignPos = 0; errCnt = manrawdecode(bits, size, 0, &alignPos); *startIdx += *clk/2 * alignPos; + if (g_debugMode) prnt("DEBUG: (askdemod_ext) CLEAN: startIdx %i, alignPos %u", *startIdx, alignPos); } return errCnt; } + if (g_debugMode) prnt("DEBUG: (askdemod_ext) Weak wave detected: startIdx %i", *startIdx); int lastBit; //set first clock check - can go negative @@ -1477,28 +1518,28 @@ int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, lastBit = start - *clk; for (i = start; i < *size; ++i) { - if (i-lastBit >= *clk-tol){ + if (i - lastBit >= *clk - tol){ if (bits[i] >= high) { bits[bitnum++] = *invert; } else if (bits[i] <= low) { bits[bitnum++] = *invert ^ 1; - } else if (i-lastBit >= *clk+tol) { + } else if (i-lastBit >= *clk + tol) { if (bitnum > 0) { if (g_debugMode == 2) prnt("DEBUG: (askdemod_ext) Modulation Error at: %u", i); - bits[bitnum++]=7; - errCnt++; + bits[bitnum++] = 7; + errCnt++; } } else { //in tolerance - looking for peak continue; } midBit = 0; lastBit += *clk; - } else if (i-lastBit >= (*clk/2-tol) && !midBit && !askType){ + } else if (i-lastBit >= (*clk/2 - tol) && !midBit && !askType){ if (bits[i] >= high) { bits[bitnum++] = *invert; } else if (bits[i] <= low) { bits[bitnum++] = *invert ^ 1; - } else if (i-lastBit >= *clk/2+tol) { + } else if (i-lastBit >= *clk/2 + tol) { bits[bitnum] = bits[bitnum-1]; bitnum++; } else { //in tolerance - looking for peak @@ -1530,8 +1571,17 @@ int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startId if (gLen > *size) gLen = *size-20; + + // just noise - no super good detection. good enough + if (signalprop.isnoise) { + if (g_debugMode == 2) prnt("DEBUG nrzRawDemod: just noise detected - quitting"); + return -3; + } + int high, low; - if (getHiLo(dest, gLen, &high, &low, 75, 75) < 1) return -3; //25% fuzz on high 25% fuzz on low + //getHiLo(dest, gLen, &high, &low, 75, 75); + getHiLo(&high, &low, 75, 75); + getHiLo(&high, &low, 75, 75); uint8_t bit=0; //convert wave samples to 1's and 0's diff --git a/common/lfdemod.h b/common/lfdemod.h index 3a7f873d7..48b4b9481 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -35,14 +35,7 @@ extern int32_t compute_mean_int(int *in, size_t N); bool isNoise_int(int *bits, uint32_t size); bool isNoise(uint8_t *bits, uint32_t size); extern void zeromean(uint8_t* data, size_t size); - -// buffer is unsigned on DEVIE -#ifdef ON_DEVICE - #define justNoise(a, b) isNoise((a), (b)) -#else - #define justNoise(a, b) isNoise_int((a), (b)) -#endif - + void getNextLow(uint8_t *samples, size_t size, int low, size_t *i); void getNextHigh(uint8_t *samples, size_t size, int high, size_t *i); bool loadWaveCounters(uint8_t *samples, size_t size, int lowToLowWaveLen[], int highToLowWaveLen[], int *waveCnt, int *skip, int *minClk, int *high, int *low); @@ -58,14 +51,15 @@ extern uint32_t bytebits_to_byte(uint8_t *src, size_t numbits); extern uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits); extern uint16_t countFC(uint8_t *bits, size_t size, uint8_t fskAdj); extern int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr); -extern uint8_t DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low); +extern bool DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low); extern uint8_t detectFSKClk(uint8_t *bits, size_t size, uint8_t fcHigh, uint8_t fcLow, int *firstClockEdge); extern int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx); extern int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShift, uint8_t *curPhase, uint8_t *fc); extern int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clock); extern bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, size_t *stend); extern size_t fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, int *startIdx); -extern int getHiLo(uint8_t *bits, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo); +//extern void getHiLo(uint8_t *bits, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo); +extern void getHiLo(int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo); extern uint32_t manchesterEncode2Bytes(uint16_t datain); extern int ManchesterEncode(uint8_t *bits, size_t size); extern int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos); From be5735447806d90f8139c6126cb66da2623b2fc5 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 9 Sep 2018 12:36:16 +0200 Subject: [PATCH 0034/1938] chg: seems to be a free bug on macos --- client/proxmark3.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/client/proxmark3.c b/client/proxmark3.c index 78230bd36..ae528a9e9 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -186,9 +186,10 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { write_history(".history"); - free(cmd); - cmd = NULL; - + if (cmd) { + free(cmd); + cmd = NULL; + } } static void dumpAllHelp(int markdown) { @@ -353,8 +354,6 @@ int main(int argc, char* argv[]) { // try to open USB connection to Proxmark usb_present = OpenProxmark(argv[1], waitCOMPort, 20, false); - - printf("\x1b[31m test\n"); #ifdef HAVE_GUI # ifdef _WIN32 From 617610302336fd64919d05eb1cdb7128fc8546d6 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 9 Sep 2018 12:36:44 +0200 Subject: [PATCH 0035/1938] cleanup --- client/cmdhf15.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index f54dfe7d8..1fe44de0e 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -396,8 +396,8 @@ int usage_15_readmulti(void){ // Mode 3 //helptext int CmdHF15Demod(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_15_demod(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_15_demod(); // The sampling rate is 106.353 ksps/s, for T = 18.8 us int i, j; From c4b3edef8988271ccf2338214fb9a0f0ea699101 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 9 Sep 2018 18:03:49 +0200 Subject: [PATCH 0036/1938] fix: double free bug on MacOS (thanks @drandreas) --- client/comms.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/comms.c b/client/comms.c index ec1a36860..e0d0670ff 100644 --- a/client/comms.c +++ b/client/comms.c @@ -288,6 +288,7 @@ __attribute__((force_align_arg_pointer)) // when this reader thread dies, we close the serial port. uart_close(sp); + sp = NULL; pthread_exit(NULL); return NULL; From 0a548c5da027c70b9331cf19af6ed5c409b546bb Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 9 Sep 2018 18:08:20 +0200 Subject: [PATCH 0037/1938] clean up --- client/cmdlfti.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/client/cmdlfti.c b/client/cmdlfti.c index 9f32e67f8..e5f3530f0 100644 --- a/client/cmdlfti.c +++ b/client/cmdlfti.c @@ -77,9 +77,9 @@ int CmdTIDemod(const char *Cmd) 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1 }; - int lowLen = sizeof(LowTone)/sizeof(int); - int highLen = sizeof(HighTone)/sizeof(int); - int convLen = (highLen>lowLen)?highLen:lowLen; + int lowLen = sizeof(LowTone) / sizeof(int); + int highLen = sizeof(HighTone) / sizeof(int); + int convLen = (highLen > lowLen) ? highLen : lowLen; uint16_t crc; int i, j, TagType; int lowSum = 0, highSum = 0;; @@ -90,15 +90,15 @@ int CmdTIDemod(const char *Cmd) highSum = 0;; for (j = 0; j < lowLen; j++) { - lowSum += LowTone[j]*GraphBuffer[i+j]; + lowSum += LowTone[j] * GraphBuffer[i+j]; } for (j = 0; j < highLen; j++) { - highSum += HighTone[j]*GraphBuffer[i+j]; + highSum += HighTone[j] * GraphBuffer[i+j]; } lowSum = abs((100*lowSum) / lowLen); highSum = abs((100*highSum) / highLen); - lowSum = (lowSum<0)?-lowSum:lowSum; - highSum = (highSum<0)?-highSum:highSum; + lowSum = (lowSum<0) ? -lowSum : lowSum; + highSum = (highSum<0) ? -highSum : highSum; GraphBuffer[i] = (highSum << 16) | lowSum; } From bc0ffa9e514a272099d2db2845e2faef85fcb104 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 9 Sep 2018 19:54:22 +0200 Subject: [PATCH 0038/1938] fix: remove zeromean chg: cleanup --- common/lfdemod.c | 88 ++++++++++++++++++++++++------------------------ common/lfdemod.h | 2 +- 2 files changed, 45 insertions(+), 45 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index 0525f7ff9..f6d4f4d89 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -123,7 +123,6 @@ void zeromean(uint8_t* data, size_t size) { bool isNoise_int(int *bits, uint32_t size) { resetSignal(); if ( bits == NULL || size < 100 ) return true; - //zeromean(bits, size); int32_t sum = 0; for ( size_t i = 0; i < size; i++) { @@ -148,7 +147,6 @@ bool isNoise_int(int *bits, uint32_t size) { bool isNoise(uint8_t *bits, uint32_t size) { resetSignal(); if ( bits == NULL || size < 100 ) return true; - zeromean(bits, size); uint32_t sum = 0; for ( uint32_t i = 0; i < size; i++) { @@ -835,7 +833,7 @@ int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx) //countFC is to detect the field clock lengths. //counts and returns the 2 most common wave lengths //mainly used for FSK field clock detection -uint16_t countFC(uint8_t *bits, size_t size, uint8_t fskAdj) { +uint16_t countFC(uint8_t *bits, size_t size, bool fskAdj) { uint8_t fcLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint16_t fcCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t fcLensFnd = 0; @@ -855,17 +853,18 @@ uint16_t countFC(uint8_t *bits, size_t size, uint8_t fskAdj) { fcCounter++; if (fskAdj){ //if we had 5 and now have 9 then go back to 8 (for when we get a fc 9 instead of an 8) - if (lastFCcnt==5 && fcCounter==9) fcCounter--; + if (lastFCcnt == 5 && fcCounter == 9) fcCounter--; + //if fc=9 or 4 add one (for when we get a fc 9 instead of 10 or a 4 instead of a 5) - if ((fcCounter==9) || fcCounter==4) fcCounter++; - // save last field clock count (fc/xx) - lastFCcnt = fcCounter; + if ((fcCounter == 9) || fcCounter == 4) fcCounter++; + // save last field clock count (fc/xx) + lastFCcnt = fcCounter; } // find which fcLens to save it to: - for (int ii=0; ii<15; ii++){ - if (fcLens[ii]==fcCounter){ - fcCnts[ii]++; - fcCounter=0; + for (int m=0; m<15; m++){ + if (fcLens[m] == fcCounter){ + fcCnts[m]++; + fcCounter = 0; break; } } @@ -881,36 +880,37 @@ uint16_t countFC(uint8_t *bits, size_t size, uint8_t fskAdj) { } } - uint8_t best1=14, best2=14, best3=14; - uint16_t maxCnt1=0; + uint8_t best1 = 14, best2 = 14, best3 = 14; + uint16_t maxCnt1 = 0; // go through fclens and find which ones are bigest 2 for (i=0; i<15; i++){ // get the 3 best FC values - if (fcCnts[i]>maxCnt1) { - best3=best2; - best2=best1; - maxCnt1=fcCnts[i]; - best1=i; - } else if(fcCnts[i]>fcCnts[best2]){ - best3=best2; - best2=i; - } else if(fcCnts[i]>fcCnts[best3]){ - best3=i; + if (fcCnts[i] > maxCnt1) { + best3 = best2; + best2 = best1; + maxCnt1 = fcCnts[i]; + best1 = i; + } else if(fcCnts[i] > fcCnts[best2]){ + best3 = best2; + best2 = i; + } else if(fcCnts[i] > fcCnts[best3]){ + best3 = i; } - if (g_debugMode == 2) prnt("DEBUG countfc: FC %u, Cnt %u, best fc: %u, best2 fc: %u",fcLens[i],fcCnts[i],fcLens[best1],fcLens[best2]); - if (fcLens[i]==0) break; + if (g_debugMode == 2) prnt("DEBUG countfc: FC %u, Cnt %u, best fc: %u, best2 fc: %u", fcLens[i], fcCnts[i], fcLens[best1], fcLens[best2]); + if (fcLens[i] == 0) break; } - if (fcLens[best1]==0) return 0; - uint8_t fcH=0, fcL=0; - if (fcLens[best1]>fcLens[best2]){ - fcH=fcLens[best1]; - fcL=fcLens[best2]; + + if (fcLens[best1] == 0) return 0; + uint8_t fcH = 0, fcL = 0; + if (fcLens[best1] > fcLens[best2]){ + fcH = fcLens[best1]; + fcL = fcLens[best2]; } else{ - fcH=fcLens[best2]; - fcL=fcLens[best1]; + fcH = fcLens[best2]; + fcL = fcLens[best1]; } - if ((size-180)/fcH/3 > fcCnts[best1]+fcCnts[best2]) { - if (g_debugMode == 2) prnt("DEBUG countfc: fc is too large: %u > %u. Not psk or fsk",(size-180)/fcH/3,fcCnts[best1]+fcCnts[best2]); + if ((size-180)/fcH/3 > fcCnts[best1] + fcCnts[best2]) { + if (g_debugMode == 2) prnt("DEBUG countfc: fc is too large: %u > %u. Not psk or fsk", (size-180)/fcH/3, fcCnts[best1] + fcCnts[best2]); return 0; //lots of waves not psk or fsk } // TODO: take top 3 answers and compare to known Field clocks to get top 2 @@ -1036,7 +1036,7 @@ uint8_t detectFSKClk(uint8_t *bits, size_t size, uint8_t fcHigh, uint8_t fcLow, uint16_t rfCounter = 0; uint8_t firstBitFnd = 0; size_t i; - uint8_t fcTol = ((fcHigh*100 - fcLow*100)/2 + 50)/100; //(uint8_t)(0.5+(float)(fcHigh-fcLow)/2); + uint8_t fcTol = ((fcHigh * 100 - fcLow * 100)/2 + 50)/100; //(uint8_t)(0.5+(float)(fcHigh-fcLow)/2); // prime i to first peak / up transition for (i = 160; i < size-20; i++) @@ -1084,7 +1084,7 @@ uint8_t detectFSKClk(uint8_t *bits, size_t size, uint8_t fcHigh, uint8_t fcLow, } fcCounter = 0; } - uint8_t rfHighest=15, rfHighest2=15, rfHighest3=15; + uint8_t rfHighest = 15, rfHighest2 = 15, rfHighest3 = 15; for (i=0; i<15; i++){ //get highest 2 RF values (might need to get more values to compare or compare all?) @@ -1111,22 +1111,22 @@ uint8_t detectFSKClk(uint8_t *bits, size_t size, uint8_t fcHigh, uint8_t fcLow, // loop to find the highest clock that has a remainder less than the tolerance // compare samples counted divided by // test 128 down to 32 (shouldn't be possible to have fc/10 & fc/8 and rf/16 or less) - int ii=7; - for (; ii>=2; ii--){ - if (rfLens[rfHighest] % clk[ii] < tol1 || rfLens[rfHighest] % clk[ii] > clk[ii]-tol1){ - if (rfLens[rfHighest2] % clk[ii] < tol1 || rfLens[rfHighest2] % clk[ii] > clk[ii]-tol1){ - if (rfLens[rfHighest3] % clk[ii] < tol1 || rfLens[rfHighest3] % clk[ii] > clk[ii]-tol1){ + int m = 7; + for (; m >= 2; m--){ + if (rfLens[rfHighest] % clk[m] < tol1 || rfLens[rfHighest] % clk[m] > clk[m]-tol1){ + if (rfLens[rfHighest2] % clk[m] < tol1 || rfLens[rfHighest2] % clk[m] > clk[m]-tol1){ + if (rfLens[rfHighest3] % clk[m] < tol1 || rfLens[rfHighest3] % clk[m] > clk[m]-tol1){ if (g_debugMode == 2) - prnt("DEBUG FSK: clk %d divides into the 3 most rf values within tolerance",clk[ii]); + prnt("DEBUG FSK: clk %d divides into the 3 most rf values within tolerance", clk[m]); break; } } } } - if (ii < 2) return 0; // oops we went too far + if (m < 2) return 0; // oops we went too far - return clk[ii]; + return clk[m]; } diff --git a/common/lfdemod.h b/common/lfdemod.h index 48b4b9481..daa5c3c56 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -49,7 +49,7 @@ extern int BiphaseRawDecode(uint8_t *bits, size_t *size, int *offset, int i extern uint8_t bits_to_array(const uint8_t *bits, size_t size, uint8_t *dest); extern uint32_t bytebits_to_byte(uint8_t *src, size_t numbits); extern uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits); -extern uint16_t countFC(uint8_t *bits, size_t size, uint8_t fskAdj); +extern uint16_t countFC(uint8_t *bits, size_t size, bool fskAdj); extern int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr); extern bool DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low); extern uint8_t detectFSKClk(uint8_t *bits, size_t size, uint8_t fcHigh, uint8_t fcLow, int *firstClockEdge); From fef85d4caa7daafae3bfdfc71a46abcd86795fef Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 9 Sep 2018 19:56:11 +0200 Subject: [PATCH 0039/1938] chg: 'data load' , 'data norm' etc all commands that manipulate graphbuffer need to update signalproperty struct. But its not based on the signed data. --- client/cmddata.c | 45 ++++++++++++++++++++++++++++----------------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index f4bfb3ff4..bcaeaf3bc 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1007,14 +1007,14 @@ int FSKrawDemod(const char *Cmd, bool verbose) { } } - uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; - size_t BitLen = getFromGraphBuf(BitStream); + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; + size_t BitLen = getFromGraphBuf(bits); if (BitLen == 0) return 0; //get field clock lengths uint16_t fcs = 0; if (!fchigh || !fclow) { - fcs = countFC(BitStream, BitLen, 1); + fcs = countFC(bits, BitLen, true); if (!fcs) { fchigh = 10; fclow = 8; @@ -1026,13 +1026,13 @@ int FSKrawDemod(const char *Cmd, bool verbose) { //get bit clock length if (!rfLen) { int firstClockEdge = 0; //todo - align grid on graph with this... - rfLen = detectFSKClk(BitStream, BitLen, fchigh, fclow, &firstClockEdge); + rfLen = detectFSKClk(bits, BitLen, fchigh, fclow, &firstClockEdge); if (!rfLen) rfLen = 50; } int startIdx = 0; - int size = fskdemod(BitStream, BitLen, rfLen, invert, fchigh, fclow, &startIdx); + int size = fskdemod(bits, BitLen, rfLen, invert, fchigh, fclow, &startIdx); if (size > 0) { - setDemodBuf(BitStream, size, 0); + setDemodBuf(bits, size, 0); setClockGrid(rfLen, startIdx); // Now output the bitstream to the scrollback by line of 16 bits @@ -1574,7 +1574,9 @@ int CmdLoad(const char *Cmd) { //ICEMAN todo // set signal properties low/high/mean/amplitude and isnoice detection - isNoise_int(GraphBuffer, GraphTraceLen); + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + isNoise(bits, sizeof(bits)); return 0; } @@ -1638,11 +1640,13 @@ int CmdNorm(const char *Cmd) { //marshmelow: adjusted *1000 to *256 to make +/- 128 so demod commands still work } } - RepaintGraphWindow(); - + //ICEMAN todo // set signal properties low/high/mean/amplitude and isnoice detection - isNoise_int(GraphBuffer, GraphTraceLen); + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + isNoise(bits, sizeof(bits)); + RepaintGraphWindow(); return 0; } @@ -1729,8 +1733,10 @@ int CmdDirectionalThreshold(const char *Cmd) { //ICEMAN todo // set signal properties low/high/mean/amplitude and isnoice detection - isNoise_int(GraphBuffer, GraphTraceLen); - + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + isNoise(bits, sizeof(bits)); + RepaintGraphWindow(); return 0; } @@ -1759,8 +1765,10 @@ int CmdZerocrossings(const char *Cmd) { //ICEMAN todo // set signal properties low/high/mean/amplitude and isnoice detection - isNoise_int(GraphBuffer, GraphTraceLen); - + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + isNoise(bits, sizeof(bits)); + RepaintGraphWindow(); return 0; } @@ -2012,11 +2020,14 @@ int CmdDataIIR(const char *Cmd){ uint8_t k = param_get8(Cmd, 0); //iceIIR_Butterworth(GraphBuffer, GraphTraceLen); iceSimple_Filter(GraphBuffer, GraphTraceLen, k); + //ICEMAN todo // set signal properties low/high/mean/amplitude and isnoice detection - isNoise_int(GraphBuffer, GraphTraceLen); - - RepaintGraphWindow(); + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + isNoise(bits, sizeof(bits)); + + RepaintGraphWindow(); return 0; } From b66a4815818048ab27558e4fe722130f4dccb899 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 9 Sep 2018 19:56:25 +0200 Subject: [PATCH 0040/1938] cleanup --- client/graph.c | 38 +++++++++++++++++++------------------- client/graph.h | 2 +- 2 files changed, 20 insertions(+), 20 deletions(-) diff --git a/client/graph.c b/client/graph.c index 2e492cf30..2d6a28233 100644 --- a/client/graph.c +++ b/client/graph.c @@ -57,7 +57,6 @@ void save_restoreGB(uint8_t saveOpt) { return; } -// DETECT CLOCK NOW IN LFDEMOD.C void setGraphBuf(uint8_t *buf, size_t size) { if ( buf == NULL ) return; @@ -73,6 +72,7 @@ void setGraphBuf(uint8_t *buf, size_t size) { RepaintGraphWindow(); return; } + size_t getFromGraphBuf(uint8_t *buf) { if (buf == NULL ) return 0; uint32_t i; @@ -102,18 +102,18 @@ int GetAskClock(const char *str, bool printAns) { return clock; // Auto-detect clock - uint8_t grph[MAX_GRAPH_TRACE_LEN] = {0}; - size_t size = getFromGraphBuf(grph); + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; + size_t size = getFromGraphBuf(bits); if (size == 0) { PrintAndLogEx(WARNING, "Failed to copy from graphbuffer"); return -1; } - //, size_t *ststart, size_t *stend + size_t ststart = 0, stend = 0; - bool st = DetectST(grph, &size, &clock, &ststart, &stend); + bool st = DetectST(bits, &size, &clock, &ststart, &stend); int start = stend; if (st == false) { - start = DetectASKClock(grph, size, &clock, 20); + start = DetectASKClock(bits, size, &clock, 20); } setClockGrid(clock, start); // Only print this message if we're not looping something @@ -125,13 +125,13 @@ int GetAskClock(const char *str, bool printAns) { uint8_t GetPskCarrier(const char *str, bool printAns) { uint8_t carrier = 0; - uint8_t grph[MAX_GRAPH_TRACE_LEN] = {0}; - size_t size = getFromGraphBuf(grph); + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; + size_t size = getFromGraphBuf(bits); if ( size == 0 ) { PrintAndLogEx(WARNING, "Failed to copy from graphbuffer"); return 0; } - uint16_t fc = countFC(grph, size, 0); + uint16_t fc = countFC(bits, size, false); carrier = fc & 0xFF; if (carrier != 2 && carrier != 4 && carrier != 8) return 0; if (( fc >> 8) == 10 && carrier == 8) return 0; @@ -194,12 +194,13 @@ int GetFskClock(const char* str, bool printAns) { uint8_t fc1 = 0, fc2 = 0, rf1 = 0; int firstClockEdge = 0; - int ans = fskClocks(&fc1, &fc2, &rf1, &firstClockEdge); - if (ans == 0) + + if ( !fskClocks(&fc1, &fc2, &rf1, &firstClockEdge)) return 0; if ((fc1==10 && fc2==8) || (fc1==8 && fc2==5)){ - if (printAns) PrintAndLogEx(NORMAL, "Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1, fc2, rf1); + if (printAns) + PrintAndLogEx(NORMAL, "Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1, fc2, rf1); setClockGrid(rf1, firstClockEdge); return rf1; } @@ -208,26 +209,25 @@ int GetFskClock(const char* str, bool printAns) { PrintAndLogEx(DEBUG, "Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1, fc2, rf1); return 0; } -int fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, int *firstClockEdge) { +bool fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, int *firstClockEdge) { uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; size_t size = getFromGraphBuf(bits); if (size == 0) - return 0; + return false; - uint16_t ans = countFC(bits, size, 1); + uint16_t ans = countFC(bits, size, true); if (ans == 0) { PrintAndLogEx(DEBUG, "DEBUG: No data found"); - return 0; + return false; } *fc1 = (ans >> 8) & 0xFF; *fc2 = ans & 0xFF; - //int firstClockEdge = 0; *rf1 = detectFSKClk(bits, size, *fc1, *fc2, firstClockEdge); if (*rf1 == 0) { PrintAndLogEx(DEBUG, "DEBUG: Clock detect error"); - return 0; + return false; } - return 1; + return true; } diff --git a/client/graph.h b/client/graph.h index ec6011c27..3e56d09f2 100644 --- a/client/graph.h +++ b/client/graph.h @@ -26,7 +26,7 @@ int GetPskClock(const char *str, bool printAns); uint8_t GetPskCarrier(const char *str, bool printAns); int GetNrzClock(const char *str, bool printAns); int GetFskClock(const char *str, bool printAns); -int fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, int *firstClockEdge); +bool fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, int *firstClockEdge); void setGraphBuf(uint8_t *buff, size_t size); void save_restoreGB(uint8_t saveOpt); From c187774a986ce8e2af9f8b5a26aed3e77a17d402 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 9 Sep 2018 22:08:32 +0200 Subject: [PATCH 0041/1938] fix: hilow fuzzing overlap --- common/lfdemod.c | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index f6d4f4d89..4ab05bfa9 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -180,6 +180,12 @@ void getHiLo(int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo) { *low = signalprop.low + ((range * (100-fuzzLo))/100); } + // if fuzzing to great and overlap + if ( *high < *low ) { + *high = signalprop.high; + *low = signalprop.low; + } + if (g_debugMode) prnt("getHiLo fuzzed: High %d | Low %d", *high, *low); } @@ -388,7 +394,7 @@ bool loadWaveCounters(uint8_t *samples, size_t size, int lowToLowWaveLen[], int break; highToLowWaveLen[*waveCnt] = i - firstHigh; //first high to first low - lowToLowWaveLen[*waveCnt] = i - firstLow; + lowToLowWaveLen[*waveCnt] = i - firstLow; *waveCnt += 1; if (i-firstLow < *minClk && i < size) { *minClk = i - firstLow; From d42b4f6ddfc918a1489e351dec59297d0fc4c280 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 9 Sep 2018 23:02:41 +0200 Subject: [PATCH 0042/1938] CHG: ask clean wave - better start position in signal --- common/lfdemod.c | 28 +++++++++++++++------------- 1 file changed, 15 insertions(+), 13 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index 4ab05bfa9..8f0630d52 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -372,7 +372,6 @@ bool loadWaveCounters(uint8_t *samples, size_t size, int lowToLowWaveLen[], int return false; } - //getHiLo(samples, testsize, high, low, 80, 80); getHiLo(high, low, 80, 80); // get to first full low to prime loop and skip incomplete first pulse @@ -513,8 +512,6 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo size_t minClk = 512; int shortestWaveIdx = 0; - if (g_debugMode == 1) prnt("DEBUG ASK: DetectStrongAskClock: hi %d | low %d ", high, low); - // get to first full low to prime loop and skip incomplete first pulse getNextHigh(dest, size, high, &i); getNextLow(dest, size, low, &i); @@ -1409,10 +1406,15 @@ int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos) //RETURN: num of errors. if 0, is ok. int cleanAskRawDemod(uint8_t *bits, size_t *size, int clk, int invert, int high, int low, int *startIdx) { *startIdx = 0; - size_t bitCnt=0, smplCnt=1, errCnt=0; - bool waveHigh = (bits[0] >= high); + size_t bitCnt = 0, smplCnt = 1, errCnt = 0, pos = 0; + + uint8_t cl_4 = clk / 4; + uint8_t cl_2 = clk / 2; + + getNextHigh(bits, *size, high, &pos); + bool waveHigh = true; - for (size_t i=1; i < *size; i++){ + for (size_t i=pos; i < *size; i++){ if (bits[i] >= high && waveHigh){ smplCnt++; } else if (bits[i] <= low && !waveHigh){ @@ -1420,8 +1422,8 @@ int cleanAskRawDemod(uint8_t *bits, size_t *size, int clk, int invert, int high, } else { //transition if ((bits[i] >= high && !waveHigh) || (bits[i] <= low && waveHigh)){ - if (smplCnt > clk-(clk/4)-1) { //full clock - if (smplCnt > clk + (clk/4)+1) { //too many samples + if (smplCnt > clk - cl_4 - 1) { //full clock + if (smplCnt > clk + cl_4 + 1) { //too many samples errCnt++; if (g_debugMode == 2) prnt("DEBUG:(cleanAskRawDemod) ASK Modulation Error at: %u", i); bits[bitCnt++] = 7; @@ -1432,18 +1434,18 @@ int cleanAskRawDemod(uint8_t *bits, size_t *size, int clk, int invert, int high, bits[bitCnt++] = invert ^ 1; bits[bitCnt++] = invert ^ 1; } - if (*startIdx==0) - *startIdx = i-clk; + if (*startIdx == 0) + *startIdx = i - clk; waveHigh = !waveHigh; smplCnt = 0; - } else if (smplCnt > (clk/2) - (clk/4)-1) { //half clock + } else if (smplCnt > cl_2 - cl_4 - 1) { //half clock if (waveHigh) { bits[bitCnt++] = invert; } else if (!waveHigh) { bits[bitCnt++] = invert ^ 1; } - if (*startIdx==0) - *startIdx = i-(clk/2); + if (*startIdx == 0) + *startIdx = i - cl_2; waveHigh = !waveHigh; smplCnt = 0; } else { From 0a648d482d6c11236753be8fc81c008c8134a612 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 9 Sep 2018 23:16:47 +0200 Subject: [PATCH 0043/1938] chg: remove warning unused variable --- client/cmddata.c | 2 +- client/cmdlfawid.c | 2 +- client/cmdlfem4x.c | 1 - client/cmdlfhid.c | 2 +- client/cmdlft55xx.c | 6 +++--- 5 files changed, 6 insertions(+), 7 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index bcaeaf3bc..8b263e44d 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1576,7 +1576,7 @@ int CmdLoad(const char *Cmd) { // set signal properties low/high/mean/amplitude and isnoice detection uint8_t bits[GraphTraceLen]; size_t size = getFromGraphBuf(bits); - isNoise(bits, sizeof(bits)); + isNoise(bits, size); return 0; } diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index 420caeb62..b17864dcf 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -242,7 +242,7 @@ int CmdAWIDRead_device(const char *Cmd) { int CmdAWIDDemod(const char *Cmd) { uint8_t bits[MAX_GRAPH_TRACE_LEN]={0}; size_t size = getFromGraphBuf(bits); - if (size==0) { + if (size == 0) { PrintAndLogEx(DEBUG, "DEBUG: Error - AWID not enough samples"); return 0; } diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 1664a3c2b..1e408bbf6 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -799,7 +799,6 @@ int EM4x50Read(const char *Cmd, bool verbose) { uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; size_t size = getFromGraphBuf(bits); - isNoise(bits, size); signal_t *sp = getSignalProperties(); diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index 02fd9c791..ced656789 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -130,7 +130,7 @@ int CmdHIDDemod(const char *Cmd) { uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; size_t size = getFromGraphBuf(bits); - if (size==0) { + if (size == 0) { PrintAndLogEx(DEBUG, "DEBUG: Error - HID not enough samples"); return 0; } diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 7fbf143d3..9102efc5c 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -538,7 +538,7 @@ bool tryDetectModulation(){ } } else { clk = GetAskClock("", false); - if (clk>0) { + if (clk > 0) { tests[hits].ST = true; // "0 0 1 " == clock auto, invert false, maxError 1. // false = no verbose @@ -583,7 +583,7 @@ bool tryDetectModulation(){ } } clk = GetNrzClock("", false); - if (clk>8) { //clock of rf/8 is likely a false positive, so don't use it. + if (clk > 8) { //clock of rf/8 is likely a false positive, so don't use it. if ( NRZrawDemod("0 0 1", false) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { tests[hits].modulation = DEMOD_NRZ; tests[hits].bitrate = bitRate; @@ -604,7 +604,7 @@ bool tryDetectModulation(){ } clk = GetPskClock("", false); - if (clk>0) { + if (clk > 0) { // allow undo save_restoreGB(GRAPH_SAVE); // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) From 9ee550af45a10b87965576e95d4f67cd5eaf5f6f Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 10 Sep 2018 21:45:00 +0200 Subject: [PATCH 0044/1938] FIX: lf t55xx detect works better with adjusted timings CHG: applied fpga_off patch. --- armsrc/lfops.c | 47 ++++++++++++++++++++++++++--------------------- 1 file changed, 26 insertions(+), 21 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index a957e4dfb..612e2a2f4 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -26,10 +26,10 @@ # define OPEN_COIL() HIGH(GPIO_SSC_DOUT) #endif -#define START_GAP 31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc) -#define WRITE_GAP 20*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc) -#define WRITE_0 18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc) -#define WRITE_1 54*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (56fc) 432 for T55x7; 448 for E5550 +#define START_GAP 28*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc) +#define WRITE_GAP 17*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc) +#define WRITE_0 15*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc) +#define WRITE_1 47*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (56fc) 432 for T55x7; 448 for E5550 #define READ_GAP 15*8 // VALUES TAKEN FROM EM4x function: SendForward @@ -68,7 +68,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint // Make sure the tag is reset FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); WaitMS(500); // clear read buffer @@ -109,7 +109,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint if (command[counter] == '0') { // if field already off leave alone (affects timing otherwise) if (off == false) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); LED_D_OFF(); off = true; } @@ -136,7 +136,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint TurnReadLFOn(period_1); LED_D_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); WaitUS(delay_off); } @@ -1269,7 +1269,7 @@ void T55xxWriteBit(int bit) { TurnReadLFOn(WRITE_0); else TurnReadLFOn(WRITE_1); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); WaitUS(WRITE_GAP); } @@ -1279,14 +1279,15 @@ void T55xxResetRead(void) { //clear buffer now so it does not interfere with timing later BigBuf_Clear_keep_EM(); + StartTicks(); + // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); - StartTicks(); // make sure tag is fully powered up... - WaitMS(5); + WaitMS(6); // Trigger T55x7 in mode. - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); WaitUS(START_GAP); // reset tag - op code 00 @@ -1312,13 +1313,15 @@ void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) bool testMode = arg & 0x4; uint32_t i = 0; + StartTicks(); + // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); - StartTicks(); + // make sure tag is fully powered up... - WaitMS(5); + WaitMS(6); // Trigger T55x7 in mode. - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); WaitUS(START_GAP); if (testMode) Dbprintf("TestMODE"); @@ -1396,13 +1399,14 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { //make sure block is at max 7 Block &= 0x7; + StartTicks(); + // Set up FPGA, 125kHz to power up the tag LFSetupFPGAForADC(95, true); - StartTicks(); // make sure tag is fully powered up... - WaitMS(5); + WaitMS(6); // Trigger T55x7 Direct Access Mode with start gap - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); WaitUS(START_GAP); // Opcode 1[page] @@ -1440,15 +1444,16 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { void T55xxWakeUp(uint32_t Pwd){ LED_B_ON(); uint32_t i = 0; + + StartTicks(); // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); - StartTicks(); // make sure tag is fully powered up... - WaitMS(5); + WaitMS(6); // Trigger T55x7 Direct Access Mode - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); WaitUS(START_GAP); // Opcode 10 @@ -1888,7 +1893,7 @@ This triggers a COTAG tag to response */ void Cotag(uint32_t arg0) { #ifndef OFF -# define OFF { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(2035); } +# define OFF { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); WaitUS(2035); } #endif #ifndef ON # define ON(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); WaitUS((x)); } From 5959cdf62c689886c2f55b6f041536f39264af63 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 10 Sep 2018 22:49:29 +0200 Subject: [PATCH 0045/1938] chg: remove some warning of unused variables --- client/cmddata.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 8b263e44d..a9f58b962 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1645,7 +1645,7 @@ int CmdNorm(const char *Cmd) { // set signal properties low/high/mean/amplitude and isnoice detection uint8_t bits[GraphTraceLen]; size_t size = getFromGraphBuf(bits); - isNoise(bits, sizeof(bits)); + isNoise(bits, size); RepaintGraphWindow(); return 0; } @@ -1735,7 +1735,7 @@ int CmdDirectionalThreshold(const char *Cmd) { // set signal properties low/high/mean/amplitude and isnoice detection uint8_t bits[GraphTraceLen]; size_t size = getFromGraphBuf(bits); - isNoise(bits, sizeof(bits)); + isNoise(bits, size); RepaintGraphWindow(); return 0; @@ -1767,7 +1767,7 @@ int CmdZerocrossings(const char *Cmd) { // set signal properties low/high/mean/amplitude and isnoice detection uint8_t bits[GraphTraceLen]; size_t size = getFromGraphBuf(bits); - isNoise(bits, sizeof(bits)); + isNoise(bits, size); RepaintGraphWindow(); return 0; @@ -2025,7 +2025,7 @@ int CmdDataIIR(const char *Cmd){ // set signal properties low/high/mean/amplitude and isnoice detection uint8_t bits[GraphTraceLen]; size_t size = getFromGraphBuf(bits); - isNoise(bits, sizeof(bits)); + isNoise(bits, size); RepaintGraphWindow(); return 0; From ba2543b6273c93997c9d0a61b59bd0718771849c Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 11 Sep 2018 18:35:07 +0200 Subject: [PATCH 0046/1938] ADD: 'lf t55xx deviceconfig' - command that allows for setting t55xx timings via the client. If run on a RDV40, it also saves the config to flashmemory. This gives you option to have custom timings for your custom antenna in order for your RDV40 to work optimal against a t55xx tag and with your custom antenna. (@iceman) --- CHANGELOG.md | 1 + armsrc/appmain.c | 15 ++++-- armsrc/apps.h | 4 ++ armsrc/flashmem.c | 2 - armsrc/lfops.c | 97 +++++++++++++++++++++++++++++------- client/cmdlft55xx.c | 70 ++++++++++++++++++++++++-- client/cmdlft55xx.h | 1 + client/hid-flasher/usb_cmd.h | 1 + include/common.h | 11 +++- include/usb_cmd.h | 9 ++++ 10 files changed, 185 insertions(+), 26 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 966d26729..fa2dd86fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added 'lf t55xx deviceconfig' - enables custom t55xx timing settings. (RDV40) (@iceman) - Chg adaptations for FPC communications (work in progress) (@iceman) - Fix 'stand-alone Colin' - remake to benefit from flashmem for persistence. (@cjbrigato) - Fix 'LEGIC SIM' - remake of legic sim (@drandreas) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 9cb3758af..f3b2e6c60 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -392,7 +392,8 @@ void SendStatus(void) { I2C_print_status(); #endif #ifdef WITH_LF - printConfig(); //LF Sampling config + printConfig(); // LF Sampling config + printT55xxConfig(); // LF T55XX Config #endif printUSBSpeed(); Dbprintf("Various"); @@ -625,6 +626,9 @@ void UsbPacketReceived(uint8_t *packet, int len) { switch(c->cmd) { #ifdef WITH_LF + case CMD_SET_LF_T55XX_CONFIG: + setT55xxConfig((t55xx_config *) c->d.asBytes); + break; case CMD_SET_LF_SAMPLING_CONFIG: setSamplingConfig((sample_config *) c->d.asBytes); break; @@ -701,10 +705,11 @@ void UsbPacketReceived(uint8_t *packet, int len) { c->d.asDwords[4], c->d.asDwords[5], c->d.asDwords[6] ); break; - case CMD_T55XX_READ_BLOCK: + case CMD_T55XX_READ_BLOCK: { T55xxReadBlock(c->arg[0], c->arg[1], c->arg[2]); break; - case CMD_T55XX_WRITE_BLOCK: + } + case CMD_T55XX_WRITE_BLOCK: T55xxWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]); break; case CMD_T55XX_WAKEUP: @@ -1475,6 +1480,10 @@ void __attribute__((noreturn)) AppMain(void) { usart_init(); #endif +#ifdef WITH_FLASH + loadT55xxConfig(); +#endif + // This is made as late as possible to ensure enumeration without timeout // against device such as http://www.hobbytronics.co.uk/usb-host-board-v2 usb_disable(); diff --git a/armsrc/apps.h b/armsrc/apps.h index f8d24f4ae..81a073904 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -108,6 +108,10 @@ void TurnReadLFOn(uint32_t delay); void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd); void EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd); void Cotag(uint32_t arg0); +void setT55xxConfig(t55xx_config *c); +t55xx_config * getT55xxConfig(void); +void printT55xxConfig(void); +void loadT55xxConfig(void); /// iso14443b.h void SimulateIso14443bTag(uint32_t pupi); diff --git a/armsrc/flashmem.c b/armsrc/flashmem.c index a8642dd74..d7ec37f81 100644 --- a/armsrc/flashmem.c +++ b/armsrc/flashmem.c @@ -1,7 +1,5 @@ #include "flashmem.h" - - /* here: use NCPS2 @ PA10: */ #define SPI_CSR_NUM 2 #define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 612e2a2f4..df49da530 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -18,6 +18,8 @@ #include "lfsampling.h" #include "protocols.h" #include "usb_cdc.h" // for usb_poll_validate_length +#include "common.h" +#include "flashmem.h" // persistence on mem #ifndef SHORT_COIL # define SHORT_COIL() LOW(GPIO_SSC_DOUT) @@ -26,11 +28,11 @@ # define OPEN_COIL() HIGH(GPIO_SSC_DOUT) #endif -#define START_GAP 28*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc) -#define WRITE_GAP 17*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc) -#define WRITE_0 15*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc) -#define WRITE_1 47*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (56fc) 432 for T55x7; 448 for E5550 -#define READ_GAP 15*8 +//#define START_GAP 31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc) +//#define WRITE_GAP 8*8 // 17*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc) +//#define WRITE_0 15*8 // 18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc) +//#define WRITE_1 47*8 // 50*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (56fc) 432 for T55x7; 448 for E5550 +//#define READ_GAP 15*8 // VALUES TAKEN FROM EM4x function: SendForward // START_GAP = 440; (55*8) cycles at 125Khz (8us = 1cycle) @@ -49,7 +51,68 @@ // new timer: // = 1us = 1.5ticks // 1fc = 8us = 12ticks +/* +Default LF T55xx config is set to: + startgap = 31*8 + writegap = 17*8 + write_0 = 15*8 + write_1 = 47*8 + read_gap = 15*8 +*/ +t55xx_config t_config = { 31*8, 17*8, 15*8, 47*8, 15*8 } ; +void printT55xxConfig(void) { + Dbprintf("LF T55XX config"); + Dbprintf(" [q] startgap............%d*8 (%d)", t_config.start_gap/8, t_config.start_gap); + Dbprintf(" [b] writegap............%d*8 (%d)", t_config.write_gap/8, t_config.write_gap); + Dbprintf(" [d] write_0.............%d*8 (%d)", t_config.write_0/8, t_config.write_0); + Dbprintf(" [a] write_1.............%d*8 (%d)", t_config.write_1/8, t_config.write_1); + Dbprintf(" [t] readgap.............%d*8 (%d)", t_config.read_gap/8, t_config.read_gap); +} +void setT55xxConfig(t55xx_config *c) { + + if (c->start_gap != 0) t_config.start_gap = c->start_gap*8; + if (c->write_gap != 0) t_config.write_gap = c->write_gap*8; + if (c->write_0 != 0) t_config.write_0 = c->write_0*8; + if (c->write_1 != 0) t_config.write_1 = c->write_1*8; + if (c->read_gap != 0) t_config.read_gap = c->read_gap*8; + + printT55xxConfig(); + +#if WITH_FLASH + if (!FlashInit()) + return; + + Flash_CheckBusy(BUSY_TIMEOUT); + + uint16_t isok = Flash_WriteDataCont(T55XX_CONFIG_OFFSET, (uint8_t *)&t_config, sizeof(t55xx_config)); + FlashStop(); + + if ( isok == T55XX_CONFIG_LEN) { + if (MF_DBGLEVEL > 1) DbpString("T55XX Config save success"); + } +#endif +} + +t55xx_config* getT55xxConfig(void) { + return &t_config; +} + +void loadT55xxConfig(void) { +#if WITH_FLASH + if (!FlashInit()) + return; + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); + + uint16_t isok = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, (uint8_t *)&t_config, T55XX_CONFIG_LEN); + FlashStop(); + + if ( isok == T55XX_CONFIG_LEN) { + if (MF_DBGLEVEL > 1) DbpString("T55XX Config load success"); + } +#endif +} /** * Function to do a modulation and then get samples. @@ -1266,11 +1329,11 @@ void TurnReadLF_off(uint32_t delay) { // Write one bit to card void T55xxWriteBit(int bit) { if (!bit) - TurnReadLFOn(WRITE_0); + TurnReadLFOn(t_config.write_0); else - TurnReadLFOn(WRITE_1); + TurnReadLFOn(t_config.write_1); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); - WaitUS(WRITE_GAP); + WaitUS(t_config.write_gap); } // Send T5577 reset command then read stream (see if we can identify the start of the stream) @@ -1284,17 +1347,17 @@ void T55xxResetRead(void) { // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... - WaitMS(6); + WaitMS(4); // Trigger T55x7 in mode. FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); - WaitUS(START_GAP); + WaitUS(t_config.start_gap); // reset tag - op code 00 T55xxWriteBit(0); T55xxWriteBit(0); - TurnReadLFOn(READ_GAP); + TurnReadLFOn(t_config.read_gap); // Acquisition DoPartialAcquisition(0, true, BigBuf_max_traceLen(), 0); @@ -1319,10 +1382,10 @@ void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... - WaitMS(6); + WaitMS(4); // Trigger T55x7 in mode. FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); - WaitUS(START_GAP); + WaitUS(t_config.start_gap); if (testMode) Dbprintf("TestMODE"); // Std Opcode 10 @@ -1404,10 +1467,10 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { // Set up FPGA, 125kHz to power up the tag LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... - WaitMS(6); + WaitMS(4); // Trigger T55x7 Direct Access Mode with start gap FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); - WaitUS(START_GAP); + WaitUS(t_config.start_gap); // Opcode 1[page] T55xxWriteBit(1); @@ -1450,11 +1513,11 @@ void T55xxWakeUp(uint32_t Pwd){ // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... - WaitMS(6); + WaitMS(4); // Trigger T55x7 Direct Access Mode FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); - WaitUS(START_GAP); + WaitUS(t_config.start_gap); // Opcode 10 T55xxWriteBit(1); diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 9102efc5c..a1f072425 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -187,6 +187,22 @@ int usage_t55xx_recoverpw(){ PrintAndLogEx(NORMAL, " lf t55xx wipe Q5 - wipes a t5555 Q5 tag, config block 0x6001F004"); return 0; } +int usage_lf_deviceconfig(){ + PrintAndLogEx(NORMAL, "Usage: lf t55xx deviceconfig a b c d e "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - This help"); + PrintAndLogEx(NORMAL, " a <8..28> - Set start gap"); + PrintAndLogEx(NORMAL, " b <8..28> - Set write gap"); + PrintAndLogEx(NORMAL, " c <8..28> - Set write ZERO gap"); + PrintAndLogEx(NORMAL, " d <8..28> - Set write ONE gap"); + PrintAndLogEx(NORMAL, " e <8..28> - Set read gap"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 31 - start gap 31*8"); + PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 31 b 20 - start gap 31*8, write gap 20*8"); + PrintAndLogEx(NORMAL, ""); + return 0; +} static int CmdHelp(const char *Cmd); void printT5xxHeader(uint8_t page){ @@ -461,8 +477,7 @@ static int SanityOfflineCheck( bool useGraphBuffer ){ int CmdT55xxDetect(const char *Cmd){ bool errors = false; - bool useGB = false; - bool usepwd = false; + bool useGB = false, usepwd = false; uint32_t password = 0; uint8_t cmdp = 0; @@ -1291,7 +1306,7 @@ int CmdT55xxDump(const char *Cmd){ return 1; } -bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ){ +bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ) { // arg0 bitmodes: // bit0 = pwdmode // bit1 = page to read from @@ -1882,11 +1897,60 @@ int CmdT55xxDetectPage1(const char *Cmd){ return success; } +int CmdT55xxSetDeviceConfig(const char *Cmd){ + uint8_t startgap = 0, writegap = 0; + uint8_t write0 = 0, write1 = 0, readgap = 0; + bool errors = false; + uint8_t cmdp = 0; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_lf_deviceconfig(); + case 'a': + errors |= param_getdec(Cmd, cmdp+1, &startgap); + cmdp += 2; + break; + case 'b': + errors |= param_getdec(Cmd, cmdp+1, &writegap); + cmdp += 2; + break; + case 'c': + errors |= param_getdec(Cmd, cmdp+1, &write0); + cmdp += 2; + break; + case 'd': + errors |= param_getdec(Cmd, cmdp+1, &write1); + cmdp += 2; + break; + case 'e': + errors |= param_getdec(Cmd, cmdp+1, &readgap); + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = 1; + break; + } + } + + //Validations + if (errors || cmdp == 0) return usage_lf_deviceconfig(); + + t55xx_config config = { startgap, writegap, write0, write1, readgap }; + + UsbCommand c = {CMD_SET_LF_T55XX_CONFIG, {0,0,0} }; + memcpy(c.d.asBytes, &config, sizeof(t55xx_config)); + clearCommandBuffer(); + SendCommand(&c); + return 0; +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"bruteforce", CmdT55xxBruteForce,0, " [i <*.dic>] Simple bruteforce attack to find password"}, {"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"}, {"detect", CmdT55xxDetect, 1, "[1] Try detecting the tag modulation from reading the configuration block."}, + {"deviceconfig", CmdT55xxSetDeviceConfig, 1, "Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap"}, {"p1detect", CmdT55xxDetectPage1,1, "[1] Try detecting if this is a t55xx tag by reading page 1"}, {"dump", CmdT55xxDump, 0, "[password] [o] Dump T55xx card block 0-7. Optional [password], [override]"}, {"info", CmdT55xxInfo, 1, "[1] Show T55x7 configuration data (page 0/ blk 0)"}, diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index b6c355778..15adab0b6 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -160,6 +160,7 @@ extern bool tryDetectP1(bool getData); bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5); int special(const char *Cmd); bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ); +bool AquireDataEx( uint8_t page, uint8_t block, bool pwdmode, uint32_t password, uint32_t timing ) ; bool detectPassword(int password); diff --git a/client/hid-flasher/usb_cmd.h b/client/hid-flasher/usb_cmd.h index 2ced2cd18..59027c9d3 100644 --- a/client/hid-flasher/usb_cmd.h +++ b/client/hid-flasher/usb_cmd.h @@ -105,6 +105,7 @@ typedef struct { #define CMD_VIKING_CLONE_TAG 0x0222 #define CMD_T55XX_WAKEUP 0x0224 #define CMD_COTAG 0x0225 +#define CMD_SET_LF_T55XX_CONFIG 0x0226 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ diff --git a/include/common.h b/include/common.h index 8a3f33abd..24e085699 100644 --- a/include/common.h +++ b/include/common.h @@ -55,7 +55,7 @@ extern uint32_t FLASHMEM_SPIBAUDRATE; #endif #ifndef FLASH_MEM_MAX_SIZE -# define FLASH_MEM_MAX_SIZE 0x3FFFF +# define FLASH_MEM_MAX_SIZE 0x3FFFF // (262143) #endif #ifndef FLASH_MEM_ID_LEN @@ -70,6 +70,15 @@ extern uint32_t FLASHMEM_SPIBAUDRATE; # define FLASH_MEM_SIGNATURE_OFFSET (FLASH_MEM_MAX_SIZE - FLASH_MEM_SIGNATURE_LEN) #endif +#if WITH_FLASH +#ifndef T55XX_CONFIG_LEN +# define T55XX_CONFIG_LEN sizeof( t55xx_config ) +#endif + +#ifndef T55XX_CONFIG_OFFSET +#define T55XX_CONFIG_OFFSET (FLASH_MEM_MAX_SIZE - FLASH_MEM_SIGNATURE_LEN - T55XX_CONFIG_LEN) +#endif +#endif // RDV40, validation structure to help identifying that client/firmware is talking with RDV40 typedef struct { diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 51df5896b..d6b240fb6 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -43,6 +43,14 @@ typedef struct{ int trigger_threshold; } sample_config; +typedef struct{ + uint16_t start_gap; + uint16_t write_gap; + uint16_t write_0; + uint16_t write_1; + uint16_t read_gap; +} t55xx_config; + // For the bootloader #define CMD_DEVICE_INFO 0x0000 #define CMD_SETUP_WRITE 0x0001 @@ -130,6 +138,7 @@ typedef struct{ #define CMD_VIKING_CLONE_TAG 0x0222 #define CMD_T55XX_WAKEUP 0x0224 #define CMD_COTAG 0x0225 +#define CMD_SET_LF_T55XX_CONFIG 0x0226 /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ From dcd0300913cfd205e79a39131cfd579f1b2267e3 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 11 Sep 2018 22:14:41 +0200 Subject: [PATCH 0047/1938] chg: helptext --- client/cmdlft55xx.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index a1f072425..5ffda3d9b 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -199,11 +199,13 @@ int usage_lf_deviceconfig(){ PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 31 - start gap 31*8"); - PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 31 b 20 - start gap 31*8, write gap 20*8"); + PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 29 b 17 c 15 d 47 e 15 - Default T55XX"); + PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 55 b 14 c 21 d 30 - Default EM4305"); PrintAndLogEx(NORMAL, ""); return 0; } -static int CmdHelp(const char *Cmd); + + CmdHelp(const char *Cmd); void printT5xxHeader(uint8_t page){ PrintAndLogEx(NORMAL, "Reading Page %d:", page); From 43c399876f603bb5c9050bf7034a904c929bfcb9 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 12 Sep 2018 07:59:43 +0200 Subject: [PATCH 0048/1938] chg: helptext --- armsrc/lfops.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index df49da530..4bf54791b 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -63,11 +63,11 @@ t55xx_config t_config = { 31*8, 17*8, 15*8, 47*8, 15*8 } ; void printT55xxConfig(void) { Dbprintf("LF T55XX config"); - Dbprintf(" [q] startgap............%d*8 (%d)", t_config.start_gap/8, t_config.start_gap); + Dbprintf(" [a] startgap............%d*8 (%d)", t_config.start_gap/8, t_config.start_gap); Dbprintf(" [b] writegap............%d*8 (%d)", t_config.write_gap/8, t_config.write_gap); - Dbprintf(" [d] write_0.............%d*8 (%d)", t_config.write_0/8, t_config.write_0); - Dbprintf(" [a] write_1.............%d*8 (%d)", t_config.write_1/8, t_config.write_1); - Dbprintf(" [t] readgap.............%d*8 (%d)", t_config.read_gap/8, t_config.read_gap); + Dbprintf(" [c] write_0.............%d*8 (%d)", t_config.write_0/8, t_config.write_0); + Dbprintf(" [d] write_1.............%d*8 (%d)", t_config.write_1/8, t_config.write_1); + Dbprintf(" [e] readgap.............%d*8 (%d)", t_config.read_gap/8, t_config.read_gap); } void setT55xxConfig(t55xx_config *c) { @@ -102,6 +102,7 @@ void loadT55xxConfig(void) { #if WITH_FLASH if (!FlashInit()) return; + Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); @@ -1317,8 +1318,6 @@ void TurnReadLFOn(uint32_t delay) { // measure antenna strength. //int adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10); - - // Give it a bit of time for the resonant antenna to settle. WaitUS(delay); } void TurnReadLF_off(uint32_t delay) { From 1fff6ae09a5a6b07b799d0c000ba73ccd4e03954 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 12 Sep 2018 08:01:35 +0200 Subject: [PATCH 0049/1938] chg: rename variable --- client/graph.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/graph.c b/client/graph.c index 2d6a28233..4346a8040 100644 --- a/client/graph.c +++ b/client/graph.c @@ -111,14 +111,14 @@ int GetAskClock(const char *str, bool printAns) { size_t ststart = 0, stend = 0; bool st = DetectST(bits, &size, &clock, &ststart, &stend); - int start = stend; + int idx = stend; if (st == false) { - start = DetectASKClock(bits, size, &clock, 20); + idx = DetectASKClock(bits, size, &clock, 20); } - setClockGrid(clock, start); + setClockGrid(clock, idx); // Only print this message if we're not looping something if (printAns || g_debugMode) - PrintAndLogEx(NORMAL, "Auto-detected clock rate: %d, Best Starting Position: %d", clock, start); + PrintAndLogEx(NORMAL, "Auto-detected clock rate: %d, Best Starting Position: %d", clock, idx); return clock; } From b7a1674bf6227a0231682a0865e099efbd8719f5 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 14 Sep 2018 08:12:03 +0200 Subject: [PATCH 0050/1938] helptext --- client/cmdlfem4x.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 1e408bbf6..762b4fe0b 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -41,7 +41,7 @@ int usage_lf_em410x_write(void) { PrintAndLogEx(NORMAL, " - 0|1 T5555 (Q5) / T55x7"); PrintAndLogEx(NORMAL, " - 16|32|40|64, optional, set R/F clock rate, defaults to 64"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf em 410x_write 0F0368568B"); + PrintAndLogEx(NORMAL, " lf em 410x_write 0F0368568B 1 = write ID to t55x7 card"); return 0; } int usage_lf_em410x_ws(void) { From 54bea5a067ea6f83e405916a7620cc09c6566f93 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 14 Sep 2018 08:13:42 +0200 Subject: [PATCH 0051/1938] textual --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index fa2dd86fc..0ebfa7bab 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Change 'lf hid' - got an updated to Kastle format (@xilni) - Added 'lf t55xx deviceconfig' - enables custom t55xx timing settings. (RDV40) (@iceman) - Chg adaptations for FPC communications (work in progress) (@iceman) - Fix 'stand-alone Colin' - remake to benefit from flashmem for persistence. (@cjbrigato) From 3e9397e337521d9b4532e9b470a9bed6a916c437 Mon Sep 17 00:00:00 2001 From: TomHarkness Date: Sat, 15 Sep 2018 16:20:44 +1000 Subject: [PATCH 0052/1938] Fix syntax --- armsrc/lfops.c | 258 +++++++++++++++++++++++++------------------------ 1 file changed, 130 insertions(+), 128 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 4bf54791b..12da53f9e 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -32,15 +32,15 @@ //#define WRITE_GAP 8*8 // 17*8 // was 160 // SPEC: 1*8 to 20*8 - typ 10*8 (10fc) //#define WRITE_0 15*8 // 18*8 // was 144 // SPEC: 16*8 to 32*8 - typ 24*8 (24fc) //#define WRITE_1 47*8 // 50*8 // was 400 // SPEC: 48*8 to 64*8 - typ 56*8 (56fc) 432 for T55x7; 448 for E5550 -//#define READ_GAP 15*8 +//#define READ_GAP 15*8 // VALUES TAKEN FROM EM4x function: SendForward // START_GAP = 440; (55*8) cycles at 125Khz (8us = 1cycle) // WRITE_GAP = 128; (16*8) -// WRITE_1 = 256 32*8; (32*8) +// WRITE_1 = 256 32*8; (32*8) // These timings work for 4469/4269/4305 (with the 55*8 above) -// WRITE_0 = 23*8 , 9*8 +// WRITE_0 = 23*8 , 9*8 // Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) // TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz @@ -70,24 +70,25 @@ void printT55xxConfig(void) { Dbprintf(" [e] readgap.............%d*8 (%d)", t_config.read_gap/8, t_config.read_gap); } void setT55xxConfig(t55xx_config *c) { - + if (c->start_gap != 0) t_config.start_gap = c->start_gap*8; if (c->write_gap != 0) t_config.write_gap = c->write_gap*8; if (c->write_0 != 0) t_config.write_0 = c->write_0*8; if (c->write_1 != 0) t_config.write_1 = c->write_1*8; - if (c->read_gap != 0) t_config.read_gap = c->read_gap*8; + if (c->read_gap != 0) t_config.read_gap = c->read_gap*8; printT55xxConfig(); - + #if WITH_FLASH - if (!FlashInit()) + if (!FlashInit()) { return; - + } + Flash_CheckBusy(BUSY_TIMEOUT); - + uint16_t isok = Flash_WriteDataCont(T55XX_CONFIG_OFFSET, (uint8_t *)&t_config, sizeof(t55xx_config)); FlashStop(); - + if ( isok == T55XX_CONFIG_LEN) { if (MF_DBGLEVEL > 1) DbpString("T55XX Config save success"); } @@ -100,15 +101,16 @@ t55xx_config* getT55xxConfig(void) { void loadT55xxConfig(void) { #if WITH_FLASH - if (!FlashInit()) + if (!FlashInit()) { return; - + } + Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); - + uint16_t isok = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, (uint8_t *)&t_config, T55XX_CONFIG_LEN); FlashStop(); - + if ( isok == T55XX_CONFIG_LEN) { if (MF_DBGLEVEL > 1) DbpString("T55XX Config load success"); } @@ -139,10 +141,10 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint BigBuf_Clear_keep_EM(); LFSetupFPGAForADC(sc->divisor, 1); - + // little more time for the tag to fully power up WaitMS(200); - + // if delay_off = 0 then just bitbang 1 = antenna on 0 = off for respective periods. bool bitbang = delay_off == 0; // now modulate the reader field @@ -156,8 +158,8 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint return; } - // hack2 needed--- it appears to take about 8-16us to turn the antenna back on - // leading to ~ 1 to 2 125khz samples extra in every off period + // hack2 needed--- it appears to take about 8-16us to turn the antenna back on + // leading to ~ 1 to 2 125khz samples extra in every off period // so we should test for last 0 before next 1 and reduce period_0 by this extra amount... // but is this time different for every antenna or other hw builds??? more testing needed @@ -212,10 +214,10 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint // now do the read DoAcquisition_config(false, 0); - // Turn off antenna + // Turn off antenna FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - // tell client we are done - cmd_send(CMD_ACK,0,0,0,0,0); + // tell client we are done + cmd_send(CMD_ACK,0,0,0,0,0); } /* blank r/w tag data stream @@ -370,7 +372,7 @@ void WriteTIbyte(uint8_t b) LOW(GPIO_SSC_DOUT); WaitUS(1000); // modulate antenna 1ms - HIGH(GPIO_SSC_DOUT); + HIGH(GPIO_SSC_DOUT); WaitUS(1000); } else { // stop modulating antenna 0.3ms @@ -435,7 +437,7 @@ void AcquireTiType(void) for (;;) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { buf[i] = AT91C_BASE_SSC->SSC_RHR; // store 32 bit values in buffer - i++; + i++; if (i >= TIBUFLEN) break; } WDT_HIT(); @@ -447,7 +449,7 @@ void AcquireTiType(void) char *dest = (char *)BigBuf_get_addr(); n = TIBUFLEN * 32; - + // unpack buffer for (i = TIBUFLEN-1; i >= 0; i--) { for (j = 0; j < 32; j++) { @@ -458,7 +460,7 @@ void AcquireTiType(void) } } } - + // reset SSC FpgaSetupSsc(); } @@ -489,9 +491,9 @@ void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc) // or listening to the antenna (low) FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU); StartTicks(); - + LED_A_ON(); - + // steal this pin from the SSP and use it to control the modulation AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; @@ -547,7 +549,7 @@ void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycle int i = 0, x = 0; uint8_t *buf = BigBuf_get_addr(); - + // set frequency, get values from 'lf config' command sample_config *sc = getSamplingConfig(); @@ -557,7 +559,7 @@ void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycle FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz else FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor); - + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK; AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK; @@ -567,14 +569,14 @@ void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycle if ( numcycles > -1 ) { if ( x != numcycles ) { ++x; - } else { + } else { // exit without turning of field - return; + return; } } - + if (ledcontrol) LED_D_ON(); - + // wait until SSC_CLK goes HIGH // used as a simple detection of a reader field? while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) { @@ -582,12 +584,12 @@ void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycle if ( usb_poll_validate_length() || BUTTON_PRESS() ) goto OUT; } - + if(buf[i]) OPEN_COIL(); else SHORT_COIL(); - + //wait until SSC_CLK goes LOW while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) { WDT_HIT(); @@ -595,7 +597,7 @@ void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycle if ( BUTTON_PRESS() ) goto OUT; } - + i++; if(i == period) { i = 0; @@ -604,10 +606,10 @@ void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycle SpinDelayUs(gap); } } - + if (ledcontrol) LED_D_OFF(); } -OUT: +OUT: FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); } @@ -624,7 +626,7 @@ void SimulateTagLowFrequencyBidir(int divisor, int t0) // compose fc/5 fc/8 waveform (FSK1) // compose fc/8 fc/10 waveform (FSK2) -// also manchester, +// also manchester, static void fc(int c, int *n) { uint8_t *dest = BigBuf_get_addr(); @@ -675,15 +677,15 @@ static void fc(int c, int *n) // special start of frame marker containing invalid bit sequences // this one is focused on HID, with manchester encoding. -static void fcSTT(int *n) { - fc(8, n); fc(8, n); // invalid +static void fcSTT(int *n) { + fc(8, n); fc(8, n); // invalid fc(8, n); fc(10, n); // logical 0 fc(10, n); fc(10, n); // invalid fc(8, n); fc(10, n); // logical 0 } // compose fc/X fc/Y waveform (FSKx) -static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) +static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) { uint8_t *dest = BigBuf_get_addr(); uint8_t halfFC = fc/2; @@ -700,7 +702,7 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) *n += fc; } if (mod>0) (*modCnt)++; - if ((mod>0) && modAdjOk){ //fsk2 + if ((mod>0) && modAdjOk){ //fsk2 if ((*modCnt % modAdj) == 0){ //if 4th 8 length wave in a rf/50 add extra 8 length wave memset(dest+(*n), 0, fc-halfFC); memset(dest+(*n)+(fc-halfFC), 1, halfFC); @@ -722,15 +724,15 @@ void CmdHIDsimTAGEx( uint32_t hi, uint32_t lo, int ledcontrol, int numcycles) { DbpString("[!] tags can only have 44 bits. - USE lf simfsk for larger tags"); return; } - + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); set_tracing(false); - + int n = 0, i = 0; /* HID tag bitstream format The tag contains a 44bit unique code. This is sent out MSB first in sets of 4 bits - A 1 bit is represented as 6 fc8 and 5 fc10 patterns (manchester 10) during 2 clock periods. (1bit = 1clock period) + A 1 bit is represented as 6 fc8 and 5 fc10 patterns (manchester 10) during 2 clock periods. (1bit = 1clock period) A 0 bit is represented as 5 fc10 and 6 fc8 patterns (manchester 01) A fc8 is inserted before every 4 bits A special start of frame pattern is used consisting a0b0 where a and b are neither 0 @@ -745,12 +747,12 @@ void CmdHIDsimTAGEx( uint32_t hi, uint32_t lo, int ledcontrol, int numcycles) { // special start of frame marker containing invalid bit sequences fcSTT(&n); - + // manchester encode bits 43 to 32 for (i=11; i>=0; i--) { - + if ((i%4)==3) fc(0, &n); - + if ((hi>>i) & 1) { fc(10, &n); fc(8, &n); // low-high transition } else { @@ -760,9 +762,9 @@ void CmdHIDsimTAGEx( uint32_t hi, uint32_t lo, int ledcontrol, int numcycles) { // manchester encode bits 31 to 0 for (i=31; i>=0; i--) { - + if ((i%4)==3) fc(0, &n); - + if ((lo>>i) & 1) { fc(10, &n); fc(8, &n); // low-high transition } else { @@ -790,7 +792,7 @@ void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *bits) { BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); set_tracing(false); - + int ledcontrol = 1, n = 0, i = 0; uint8_t fcHigh = arg1 >> 8; uint8_t fcLow = arg1 & 0xFF; @@ -799,19 +801,19 @@ void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *bits) { uint8_t stt = (arg2 >> 8) & 1; if ( stt ) { - //int fsktype = ( fcHigh == 8 && fcLow == 5) ? 1 : 2; + //int fsktype = ( fcHigh == 8 && fcLow == 5) ? 1 : 2; //fcSTT(&n); } - + for (i=0; i> 8) & 0xFF; uint8_t encoding = arg1 & 0xFF; @@ -898,7 +900,7 @@ void CmdASKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream) Dbprintf("sorry but separator option not yet available"); WDT_HIT(); - + Dbprintf("Simulating with clk: %d, invert: %d, encoding: %d, separator: %d, n: %d",clk, invert, encoding, separator, n); if (ledcontrol) LED_A_ON(); @@ -932,9 +934,9 @@ static void pskSimBit(uint8_t waveLen, int *n, uint8_t clk, uint8_t *curPhase, b // args clock, carrier, invert, void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream) { - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); set_tracing(false); - + int ledcontrol = 1, n = 0, i = 0; uint8_t clk = arg1 >> 8; uint8_t carrier = arg1 & 0xFF; @@ -947,11 +949,11 @@ void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream) pskSimBit(carrier, &n, clk, &curPhase, true); } } - + WDT_HIT(); - + Dbprintf("Simulating with Carrier: %d, clk: %d, invert: %d, n: %d",carrier, clk, invert, n); - + if (ledcontrol) LED_A_ON(); SimulateTagLowFrequency(n, 0, ledcontrol); if (ledcontrol) LED_A_OFF(); @@ -960,7 +962,7 @@ void CmdPSKsimTag(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *BitStream) // loop to get raw HID waveform then FSK demodulate the TAG ID from it void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { uint8_t *dest = BigBuf_get_addr(); - size_t size = 0; + size_t size = 0; uint32_t hi2 = 0, hi = 0, lo = 0; int idx = 0; int dummyIdx = 0; @@ -980,7 +982,7 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) size = 50*128*2; //big enough to catch 2 sequences of largest format idx = HIDdemodFSK(dest, &size, &hi2, &hi, &lo, &dummyIdx); if ( idx < 0 ) continue; - + if (idx > 0 && lo > 0 && (size == 96 || size == 192)){ // go over previously decoded manchester data and decode into usable tag ID if (hi2 != 0){ //extra large HID tags 88/192 bits @@ -994,7 +996,7 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) uint8_t bitlen = 0; uint32_t fc = 0; uint32_t cardnum = 0; - + if (((hi >> 5) & 1) == 1){//if bit 38 is set then < 37 bit format is used uint32_t lo2 = 0; lo2=(((hi & 31) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit @@ -1059,9 +1061,9 @@ void CmdHIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { uint8_t *dest = BigBuf_get_addr(); - + //big enough to catch 2 sequences of largest format - size_t size = 12800; //50 * 128 * 2; + size_t size = 12800; //50 * 128 * 2; int idx = 0, dummyIdx = 0; @@ -1078,7 +1080,7 @@ void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) // FSK demodulator idx = detectAWID(dest, &size, &dummyIdx); - + if (idx <= 0 || size != 96) continue; // Index map // 0 10 20 30 40 50 60 @@ -1169,7 +1171,7 @@ void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol) if (ledcontrol) LED_A_ON(); DoAcquisition_default(-1, true); - + size = BigBuf_max_traceLen(); //askdemod and manchester decode if (size > 16385) size = 16385; //big enough to catch 2 sequences of largest format @@ -1177,7 +1179,7 @@ void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol) WDT_HIT(); if (errCnt < 0) continue; - + errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo); if (errCnt == 1){ if (size == 128){ @@ -1208,7 +1210,7 @@ void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol) hi = lo = size = idx = 0; clk = invert = errCnt = 0; } - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); DbpString("Stopped"); if (ledcontrol) LED_A_OFF(); } @@ -1223,9 +1225,9 @@ void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { uint16_t number = 0, calccrc = 0; size_t size = BigBuf_max_traceLen(); - + BigBuf_Clear_keep_EM(); - + // Configure to go in 125Khz listen mode LFSetupFPGAForADC(95, true); @@ -1248,7 +1250,7 @@ void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { //----------------------------------------------------------------------------- //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 checksum 11 // - //Checksum: + //Checksum: //00000000 0 11110000 1 11100000 1 00000001 1 00000011 1 10110110 1 01110101 11 //preamble F0 E0 01 03 B6 75 // How to calc checksum, @@ -1279,7 +1281,7 @@ void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { calccrc += bytebits_to_byte(dest+idx+9*i, 8); calccrc &= 0xff; calccrc = 0xff - calccrc; - + char *crcStr = (crc == calccrc) ? "ok" : "!crc"; Dbprintf("IO Prox XSF(%02d)%02x:%05d (%08x%08x) [%02x %s]", version, facilitycode, number, code, code2, crc, crcStr); @@ -1297,7 +1299,7 @@ void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { WDT_HIT(); } - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); DbpString("Stopped"); if (ledcontrol) LED_A_OFF(); } @@ -1305,12 +1307,12 @@ void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { /*------------------------------ * T5555/T5557/T5567/T5577 routines *------------------------------ - * NOTE: T55x7/T5555 configuration register definitions moved to protocols.h + * NOTE: T55x7/T5555 configuration register definitions moved to protocols.h * * Relevant communication times in microsecond * To compensate antenna falling times shorten the write times * and enlarge the gap ones. - * Q5 tags seems to have issues when these values changes. + * Q5 tags seems to have issues when these values changes. */ void TurnReadLFOn(uint32_t delay) { @@ -1363,7 +1365,7 @@ void T55xxResetRead(void) { // Turn the field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off - cmd_send(CMD_ACK,0,0,0,0,0); + cmd_send(CMD_ACK,0,0,0,0,0); LED_A_OFF(); } @@ -1376,7 +1378,7 @@ void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) uint32_t i = 0; StartTicks(); - + // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); @@ -1410,32 +1412,32 @@ void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) // Perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550, // so wait a little more) - // "there is a clock delay before programming" + // "there is a clock delay before programming" // - programming takes ~5.6ms for t5577 ~18ms for E5550 or t5567 - // so we should wait 1 clock + 5.6ms then read response? + // so we should wait 1 clock + 5.6ms then read response? // but we need to know we are dealing with t5577 vs t5567 vs e5550 (or q5) marshmellow... if (testMode) { - //TESTMODE TIMING TESTS: - // <566us does nothing + //TESTMODE TIMING TESTS: + // <566us does nothing // 566-568 switches between wiping to 0s and doing nothing // 5184 wipes and allows 1 block to be programmed. // indefinite power on wipes and then programs all blocks with bitshifted data sent. - TurnReadLFOn(5184); + TurnReadLFOn(5184); } else { TurnReadLFOn(20 * 1000); - + //could attempt to do a read to confirm write took - // as the tag should repeat back the new block - // until it is reset, but to confirm it we would + // as the tag should repeat back the new block + // until it is reset, but to confirm it we would // need to know the current block 0 config mode for // modulation clock an other details to demod the response... - // response should be (for t55x7) a 0 bit then (ST if on) - // block data written in on repeat until reset. + // response should be (for t55x7) a 0 bit then (ST if on) + // block data written in on repeat until reset. //DoPartialAcquisition(20, true, 12000); } - + // turn field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_A_OFF(); @@ -1454,7 +1456,7 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { uint8_t Page = (arg0 & 0x2) >> 1; uint32_t i = 0; bool RegReadMode = (Block == 0xFF);//regular read mode - + //clear buffer now so it does not interfere with timing later BigBuf_Clear_keep_EM(); @@ -1470,7 +1472,7 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { // Trigger T55x7 Direct Access Mode with start gap FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); WaitUS(t_config.start_gap); - + // Opcode 1[page] T55xxWriteBit(1); T55xxWriteBit(Page); //Page 0 @@ -1482,24 +1484,24 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { } // Send a zero bit separation T55xxWriteBit(0); - + // Send Block number (if direct access mode) if (!RegReadMode) for (i = 0x04; i != 0; i >>= 1) T55xxWriteBit(Block & i); // Turn field on to read the response - // 137*8 seems to get to the start of data pretty well... + // 137*8 seems to get to the start of data pretty well... // but we want to go past the start and let the repeating data settle in... - TurnReadLFOn(210*8); - + TurnReadLFOn(210*8); + // Acquisition // Now do the acquisition DoPartialAcquisition(0, true, 12000, 0); - + // Turn the field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off - cmd_send(CMD_ACK,0,0,0,0,0); + cmd_send(CMD_ACK,0,0,0,0,0); LED_A_OFF(); } @@ -1508,16 +1510,16 @@ void T55xxWakeUp(uint32_t Pwd){ uint32_t i = 0; StartTicks(); - + // Set up FPGA, 125kHz LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... WaitMS(4); - + // Trigger T55x7 Direct Access Mode FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); WaitUS(t_config.start_gap); - + // Opcode 10 T55xxWriteBit(1); T55xxWriteBit(0); //Page 0 @@ -1610,7 +1612,7 @@ void CopyIndala64toT55x7(uint32_t hi, uint32_t lo) { void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7) { //Program the 7 data blocks for supplied 224bit UID uint32_t data[] = {0, uid1, uid2, uid3, uid4, uid5, uid6, uid7}; - // and the block 0 for Indala224 format + // and the block 0 for Indala224 format //Config for Indala (RF/32;PSK2 with RF/2;Maxblock=7) data[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (7 << T55x7_MAXBLOCK_SHIFT); //TODO add selection of chip for Q5 or T55x7 @@ -1708,7 +1710,7 @@ void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo) { } else { //t5555 (Q5) data[0] = T5555_SET_BITRATE(clock) | T5555_MODULATION_MANCHESTER | (2 << T5555_MAXBLOCK_SHIFT); } - + WriteT55xx(data, 0, 3); LED_D_OFF(); @@ -1721,9 +1723,9 @@ void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo) { //----------------------------------- // EM4469 / EM4305 routines //----------------------------------- -// Below given command set. +// Below given command set. // Commands are including the even parity, binary mirrored -#define FWD_CMD_LOGIN 0xC +#define FWD_CMD_LOGIN 0xC #define FWD_CMD_WRITE 0xA #define FWD_CMD_READ 0x9 #define FWD_CMD_DISABLE 0x5 @@ -1741,7 +1743,7 @@ uint8_t * fwd_write_ptr; //forwardlink bit pointer // VALUES TAKEN FROM EM4x function: SendForward // START_GAP = 440; (55*8) cycles at 125Khz (8us = 1cycle) // WRITE_GAP = 128; (16*8) -// WRITE_1 = 256 32*8; (32*8) +// WRITE_1 = 256 32*8; (32*8) // These timings work for 4469/4269/4305 (with the 55*8 above) // WRITE_0 = 23*8 , 9*8 @@ -1829,7 +1831,7 @@ void SendForward(uint8_t fwd_bit_count) { // iceman, 21.3us increments for the USclock verification. // 55FC * 8us == 440us / 21.3 === 20.65 steps. could be too short. Go for 56FC instead // 32FC * 8us == 256us / 21.3 == 12.018 steps. ok -// 16FC * 8us == 128us / 21.3 == 6.009 steps. ok +// 16FC * 8us == 128us / 21.3 == 6.009 steps. ok #ifndef EM_START_GAP #define EM_START_GAP 55*8 #endif @@ -1839,11 +1841,11 @@ void SendForward(uint8_t fwd_bit_count) { // Set up FPGA, 125kHz or 95 divisor LFSetupFPGAForADC(95, true); - + // force 1st mod pulse (start gap must be longer for 4305) fwd_bit_sz--; //prepare next bit modulation fwd_write_ptr++; - + TurnReadLF_off(EM_START_GAP); TurnReadLFOn(18*8); @@ -1874,11 +1876,11 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) { LED_A_ON(); uint8_t len; - + //clear buffer now so it does not interfere with timing later BigBuf_Clear_ext(false); - - StartTicks(); + + StartTicks(); /* should we read answer from Logincommand? * * should receive @@ -1905,11 +1907,11 @@ void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) { void EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd) { LED_A_ON(); - + bool usePwd = (flag & 0xF); uint8_t addr = (flag >> 8) & 0xFF; uint8_t len; - + //clear buffer now so it does not interfere with timing later BigBuf_Clear_ext(false); StartTicks(); @@ -1918,7 +1920,7 @@ void EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd) { * should receive * 0000 1010 ok. * 0000 0001 fail - **/ + **/ if (usePwd) EM4xLogin(pwd); forward_ptr = forwardLink_data; @@ -1933,7 +1935,7 @@ void EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd) { //Capture response if one exists DoPartialAcquisition(20, true, 6000, 1000); - + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); cmd_send(CMD_ACK,0,0,0,0,0); LED_A_OFF(); @@ -1962,27 +1964,27 @@ void Cotag(uint32_t arg0) { #endif uint8_t rawsignal = arg0 & 0xF; - LED_A_ON(); + LED_A_ON(); // Switching to LF image on FPGA. This might empty BigBuff FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - + //clear buffer now so it does not interfere with timing later BigBuf_Clear_ext(false); - - // Set up FPGA, 132kHz to power up the tag + + // Set up FPGA, 132kHz to power up the tag FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 89); 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(); // start clock - 1.5ticks is 1us StartTicks(); - + //send COTAG start pulse ON(740) OFF ON(3330) OFF @@ -1994,10 +1996,10 @@ void Cotag(uint32_t arg0) { case 1: doCotagAcquisitionManchester(); break; case 2: DoAcquisition_config(true, 0); break; } - + // Turn the field off FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off - cmd_send(CMD_ACK,0,0,0,0,0); + cmd_send(CMD_ACK,0,0,0,0,0); LEDsoff(); } From 9d1c3a3538f652200a0437fc40413a404146b7af Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 15 Sep 2018 12:00:53 +0200 Subject: [PATCH 0053/1938] FIX: crash on Bionic libc if CloseProxmark is called twice. (@micolous) https://github.com/Proxmark/proxmark3/pull/672 --- client/comms.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/client/comms.c b/client/comms.c index e0d0670ff..21d9ad4a7 100644 --- a/client/comms.c +++ b/client/comms.c @@ -141,7 +141,6 @@ static int getCommand(UsbCommand* response) { return 1; } - //----------------------------------------------------------------------------- // Entry point into our code: called whenever we received a packet over USB // that we weren't necessarily expecting, for example a debug print. @@ -339,9 +338,17 @@ bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode) void CloseProxmark(void) { conn.run = false; + + +#ifdef __BIONIC__ + if (USB_communication_thread != 0) { + pthread_join(USB_communication_thread, NULL); + } +#else pthread_join(USB_communication_thread, NULL); //pthread_join(FPC_communication_thread, NULL); - +#endif + if (sp) { uart_close(sp); } @@ -358,6 +365,7 @@ void CloseProxmark(void) { // Clean up our state sp = NULL; serial_port_name = NULL; + memset(&USB_communication_thread, 0, sizeof(pthread_t)); } /** From 97f9c1a49fefb78205bcc29ecd593715464ee182 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 15 Sep 2018 12:03:01 +0200 Subject: [PATCH 0054/1938] text --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ebfa7bab..8301bfa06 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fix 'compiler warning on macos and gcc7.1 or higher' (@TomHarkness) + - Fix 'crash on Bionic libc if CloseProxmark is called twice' (@micolous) - Change 'lf hid' - got an updated to Kastle format (@xilni) - Added 'lf t55xx deviceconfig' - enables custom t55xx timing settings. (RDV40) (@iceman) - Chg adaptations for FPC communications (work in progress) (@iceman) From 1d322686bbe81e7b8713fe38acbee1d352eb7fe0 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 15 Sep 2018 12:58:50 +0200 Subject: [PATCH 0055/1938] CHG: added possible SE credential identification text --- client/cmdhficlass.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 7f0e3aa07..6b57d7efd 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -547,9 +547,14 @@ int HFiClassReader(const char *Cmd, bool loop, bool verbose) { } if (readStatus & FLAG_ICLASS_READER_AIA) { bool legacy = ( memcmp( (uint8_t *)(data + 8*5), "\xff\xff\xff\xff\xff\xff\xff\xff", 8) == 0 ); + + bool se_enabled = ( memcmp( (uint8_t *)(data + 8*5), "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0 ); + PrintAndLogEx(NORMAL, " App IA: %s", sprint_hex(data+8*5, 8)); if ( legacy ) - PrintAndLogEx(SUCCESS, " : Possible iClass (legacy tag)"); + PrintAndLogEx(SUCCESS, " : Possible iClass (legacy credential tag)"); + else if( se_enabled ) + PrintAndLogEx(SUCCESS, " : Possible iClass (SE credential tag)"); else PrintAndLogEx(WARNING, " : Possible iClass (NOT legacy tag)"); } From df706198887b20abaabfdb902fb16004072abf78 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 15 Sep 2018 18:33:16 +0200 Subject: [PATCH 0056/1938] chg: turn off FPC specific functions (still work in progress) --- client/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/Makefile b/client/Makefile index f577a6386..a1d06eb76 100644 --- a/client/Makefile +++ b/client/Makefile @@ -82,7 +82,7 @@ else endif # RDV40 flag enables flashmemory commands in client. comment out if you don't have rdv40 -CFLAGS += -DWITH_FLASH -DWITH_SMARTCARD -DWITH_FPC +CFLAGS += -DWITH_FLASH -DWITH_SMARTCARD # Flags to generate temporary dependency files DEPFLAGS = -MT $@ -MMD -MP -MF $(OBJDIR)/$*.Td From 02cc278e195cdba2c043e423d5e2abe2d826b30b Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 16 Sep 2018 20:47:23 +0200 Subject: [PATCH 0057/1938] chg: remove warnings on coverity chg: encapsule flasmem function calls --- armsrc/Standalone/hf_colin.c | 14 ++++---------- armsrc/appmain.c | 19 ++++++++++++++----- armsrc/flashmem.c | 3 --- armsrc/iclass.c | 2 -- 4 files changed, 18 insertions(+), 20 deletions(-) diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index f19706af1..fc0c7967a 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -153,8 +153,7 @@ void SpinUp(uint32_t speed) LED_D_OFF(); } -void TestFlashmemSpeed(size_t buffersize, uint32_t spibaudrate) -{ +void TestFlashmemSpeed(size_t buffersize, uint32_t spibaudrate) { FLASHMEM_SPIBAUDRATE = spibaudrate*1000000; DbprintfEx(FLAG_NOLOG, "%s---+----[ %s %s[%dKB] %s] (%d)", _GREEN_, _WHITE_, _YELLOW_, buffersize / 1024, _WHITE_, FLASHMEM_SPIBAUDRATE); @@ -230,9 +229,7 @@ void TestFlashmemRoutine() return; } -void ReadLastTagFromFlash() -{ - +void ReadLastTagFromFlash() { SpinOff(0); LED_A_ON(); LED_B_ON(); @@ -248,8 +245,7 @@ void ReadLastTagFromFlash() size_t size = len; uint8_t *mem = BigBuf_malloc(size); - if (!FlashInit()) - { + if (!FlashInit()) { return; } Flash_CheckBusy(BUSY_TIMEOUT); @@ -309,9 +305,7 @@ void WriteTagToFlash(uint8_t index, size_t size) // cnt = 0; emlGetMem(data, 0, (size * 64)/1024); - //if (!FlashFastReadInit()){ - if (!FlashInit()) - { + if (!FlashInit()){ return; } diff --git a/armsrc/appmain.c b/armsrc/appmain.c index f3b2e6c60..8a63f72e4 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -38,6 +38,10 @@ #include "usart.h" #endif +#ifdef WITH_FLASH +#include "flashmem.h" +#endif + //============================================================================= // A buffer where we can queue things up to be sent through the FPGA, for // any purpose (fake tag, as reader, whatever). We go MSB first, since that @@ -387,7 +391,9 @@ void printUSBSpeed(void) { void SendStatus(void) { BigBuf_print_status(); Fpga_print_status(); +#ifdef WITH_FLASH Flashmem_print_status(); +#endif #ifdef WITH_SMARTCARD I2C_print_status(); #endif @@ -1222,7 +1228,9 @@ void UsbPacketReceived(uint8_t *packet, int len) { uint8_t *mem = BigBuf_malloc(size); - FlashInit(); + if (!FlashInit()) { + break; + } //Flash_CheckBusy(BUSY_TIMEOUT); for(size_t i = 0; i < len; i += size) { @@ -1251,8 +1259,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { uint32_t tmp = startidx + len; - if (!FlashInit()) - { + if (!FlashInit()) { break; } @@ -1322,8 +1329,10 @@ void UsbPacketReceived(uint8_t *packet, int len) { // arg0 = startindex // arg1 = length bytes to transfer // arg2 = RFU - - FlashInit(); + + if (!FlashInit()) { + break; + } for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); diff --git a/armsrc/flashmem.c b/armsrc/flashmem.c index d7ec37f81..3007ffbc1 100644 --- a/armsrc/flashmem.c +++ b/armsrc/flashmem.c @@ -485,9 +485,6 @@ void Flash_EraseChip(void) { FlashSendLastByte(CHIPERASE); } - - - void Flashmem_print_status(void) { DbpString("Flash memory"); Dbprintf(" Baudrate................%dMHz",FLASHMEM_SPIBAUDRATE/1000000); diff --git a/armsrc/iclass.c b/armsrc/iclass.c index a5481103b..21cb9f299 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -1815,7 +1815,6 @@ void setupIclassReader() { SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - // Reset trace buffer clear_trace(); set_tracing(true); @@ -1824,7 +1823,6 @@ void setupIclassReader() { FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); SpinDelay(300); - // Start the timer StartCountSspClk(); LED_A_ON(); From d5963434380f0df8538218be6a218dc9eb31842e Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 16 Sep 2018 20:48:39 +0200 Subject: [PATCH 0058/1938] chg: 'lf t55xx deviceconfig' - assume total time, and writeenable when writting... --- armsrc/lfops.c | 33 +++++++++++++++++++-------------- 1 file changed, 19 insertions(+), 14 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 12da53f9e..ce161d6dd 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -59,7 +59,7 @@ Default LF T55xx config is set to: write_1 = 47*8 read_gap = 15*8 */ -t55xx_config t_config = { 31*8, 17*8, 15*8, 47*8, 15*8 } ; +t55xx_config t_config = { 29*8, 17*8, 15*8, 47*8, 15*8 } ; void printT55xxConfig(void) { Dbprintf("LF T55XX config"); @@ -69,28 +69,35 @@ void printT55xxConfig(void) { Dbprintf(" [d] write_1.............%d*8 (%d)", t_config.write_1/8, t_config.write_1); Dbprintf(" [e] readgap.............%d*8 (%d)", t_config.read_gap/8, t_config.read_gap); } + void setT55xxConfig(t55xx_config *c) { - if (c->start_gap != 0) t_config.start_gap = c->start_gap*8; - if (c->write_gap != 0) t_config.write_gap = c->write_gap*8; - if (c->write_0 != 0) t_config.write_0 = c->write_0*8; - if (c->write_1 != 0) t_config.write_1 = c->write_1*8; - if (c->read_gap != 0) t_config.read_gap = c->read_gap*8; + if (c->start_gap != 0) t_config.start_gap = c->start_gap; + if (c->write_gap != 0) t_config.write_gap = c->write_gap; + if (c->write_0 != 0) t_config.write_0 = c->write_0; + if (c->write_1 != 0) t_config.write_1 = c->write_1; + if (c->read_gap != 0) t_config.read_gap = c->read_gap; printT55xxConfig(); #if WITH_FLASH if (!FlashInit()) { return; - } - + } + + uint8_t buf[T55XX_CONFIG_LEN]; + memcpy(buf, &t_config, T55XX_CONFIG_LEN); + Flash_CheckBusy(BUSY_TIMEOUT); - - uint16_t isok = Flash_WriteDataCont(T55XX_CONFIG_OFFSET, (uint8_t *)&t_config, sizeof(t55xx_config)); + Flash_WriteEnable(); + uint16_t isok = Flash_WriteDataCont(T55XX_CONFIG_OFFSET, buf, sizeof(buf)); FlashStop(); if ( isok == T55XX_CONFIG_LEN) { - if (MF_DBGLEVEL > 1) DbpString("T55XX Config save success"); + if (MF_DBGLEVEL > 1) { + DbpString("T55XX Config save success"); + Dbhexdump(sizeof(buf), buf, false); + } } #endif } @@ -103,11 +110,9 @@ void loadT55xxConfig(void) { #if WITH_FLASH if (!FlashInit()) { return; - } + } Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); - uint16_t isok = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, (uint8_t *)&t_config, T55XX_CONFIG_LEN); FlashStop(); From 5a95cee5ed5093766e74735e28bb4af1e67c8900 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 16 Sep 2018 20:49:29 +0200 Subject: [PATCH 0059/1938] clean --- client/loclass/fileutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 49f75ebfa..71f4e02aa 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -57,7 +57,7 @@ int fileExists(const char *filename) { int saveFile(const char *preferredName, const char *suffix, const void* data, size_t datalen) { int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10); - char * fileName = calloc(size,sizeof(char)); + char * fileName = calloc(size, sizeof(char)); int num = 1; sprintf(fileName,"%s.%s", preferredName, suffix); while (fileExists(fileName)) { From a965dff52c923b7233512f55848c3d4a6ef83ffc Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 16 Sep 2018 20:54:08 +0200 Subject: [PATCH 0060/1938] CHG: 'lf t55xx deviceconfig' - better helptext. Command takes timing values in FIELD CLOCK, which is converted to (US) on device. --- client/cmdlft55xx.c | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 5ffda3d9b..046ee40e3 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -188,24 +188,25 @@ int usage_t55xx_recoverpw(){ return 0; } int usage_lf_deviceconfig(){ + PrintAndLogEx(NORMAL, "Sets t55x7 timings for direkt commands. The timings are set here in Field Clocks (FC), \nwhich is converted to (US) on device"); PrintAndLogEx(NORMAL, "Usage: lf t55xx deviceconfig a b c d e "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - This help"); - PrintAndLogEx(NORMAL, " a <8..28> - Set start gap"); - PrintAndLogEx(NORMAL, " b <8..28> - Set write gap"); - PrintAndLogEx(NORMAL, " c <8..28> - Set write ZERO gap"); - PrintAndLogEx(NORMAL, " d <8..28> - Set write ONE gap"); - PrintAndLogEx(NORMAL, " e <8..28> - Set read gap"); + PrintAndLogEx(NORMAL, " h - This help"); + PrintAndLogEx(NORMAL, " a <8..255> - Set start gap"); + PrintAndLogEx(NORMAL, " b <8..255> - Set write gap"); + PrintAndLogEx(NORMAL, " c <8..255> - Set write ZERO gap"); + PrintAndLogEx(NORMAL, " d <8..255> - Set write ONE gap"); + PrintAndLogEx(NORMAL, " e <8..255> - Set read gap"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 31 - start gap 31*8"); - PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 29 b 17 c 15 d 47 e 15 - Default T55XX"); - PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 55 b 14 c 21 d 30 - Default EM4305"); + PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 31 - start gap 31*8"); + PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 29 b 17 c 15 d 47 e 15 - default T55XX"); + PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 55 b 14 c 21 d 30 - default EM4305"); PrintAndLogEx(NORMAL, ""); return 0; } - CmdHelp(const char *Cmd); +CmdHelp(const char *Cmd); void printT5xxHeader(uint8_t page){ PrintAndLogEx(NORMAL, "Reading Page %d:", page); @@ -1938,7 +1939,7 @@ int CmdT55xxSetDeviceConfig(const char *Cmd){ //Validations if (errors || cmdp == 0) return usage_lf_deviceconfig(); - t55xx_config config = { startgap, writegap, write0, write1, readgap }; + t55xx_config config = { startgap*8, writegap*8, write0*8, write1*8, readgap*8 }; UsbCommand c = {CMD_SET_LF_T55XX_CONFIG, {0,0,0} }; memcpy(c.d.asBytes, &config, sizeof(t55xx_config)); From 151ad3b31fa517b4e90d3a0e37dd56ac7ceb54d1 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 16 Sep 2018 22:40:09 +0200 Subject: [PATCH 0061/1938] CHG: missing declaration --- client/cmdlft55xx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 046ee40e3..71a26ddd3 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -206,7 +206,7 @@ int usage_lf_deviceconfig(){ return 0; } -CmdHelp(const char *Cmd); +int CmdHelp(const char *Cmd); void printT5xxHeader(uint8_t page){ PrintAndLogEx(NORMAL, "Reading Page %d:", page); From 5c0517526a65be65962316b14b064fdcc7a391bb Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 16 Sep 2018 23:05:09 +0200 Subject: [PATCH 0062/1938] CHG: 'hf mf csave' CHG: 'hf mf esave' - --- client/cmdhfmf.c | 230 +++++++++++++++-------------------------------- 1 file changed, 74 insertions(+), 156 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 142dbd3a4..5af1922af 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2427,80 +2427,49 @@ int CmdHF14AMfELoad(const char *Cmd) { return 0; } +#define MFBLOCK_SIZE 16 int CmdHF14AMfESave(const char *Cmd) { - FILE * f; + char filename[FILE_PATH_SIZE]; char * fnameptr = filename; - uint8_t buf[64]; - int i, j, len, numBlocks; - int nameParamNo = 1; - + uint8_t *dump; + int len, bytes, nameParamNo = 1; + uint16_t blocks; + memset(filename, 0, sizeof(filename)); - memset(buf, 0, sizeof(buf)); - char c = param_getchar(Cmd, 0); - - if ( c == 'h' || c == 'H') return usage_hf14_esave(); + char c = tolower(param_getchar(Cmd, 0)); + if (c == 'h') return usage_hf14_esave(); - switch (c) { - case '0' : numBlocks = 5*4; break; - case '1' : - case '\0': numBlocks = 16*4; break; - case '2' : numBlocks = 32*4; break; - case '4' : numBlocks = 256; break; - default: { - numBlocks = 16*4; - nameParamNo = 0; - } + blocks = NumOfBlocks(c); + bytes = blocks * MFBLOCK_SIZE; + + dump = malloc(bytes); + if (!dump) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); + return 1; } + memset(dump, 0, bytes); + + PrintAndLogEx(INFO, "dowingloading from emulator memory"); + if (!GetFromDevice( BIG_BUF_EML, dump, bytes, 0, NULL, 2500, false)) { + PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); + free(dump); + return 2; + } len = param_getstr(Cmd, nameParamNo, filename, sizeof(filename)); - if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; // user supplied filename? if (len < 1) { - // get filename (UID from memory) - if (mfEmlGetMem(buf, 0, 1)) { - PrintAndLogEx(WARNING, "Can\'t get UID from block: %d", 0); - len = sprintf(fnameptr, "dump"); - fnameptr += len; - } - else { - for (j = 0; j < 7; j++, fnameptr += 2) - sprintf(fnameptr, "%02X", buf[j]); - } - } else { - fnameptr += len; - } - - // add file extension - sprintf(fnameptr, ".eml"); - - // open file - f = fopen(filename, "w+"); - - if ( !f ) { - PrintAndLogEx(WARNING, "Can't open file %s ", filename); - return 1; + fnameptr += sprintf(fnameptr, "hf-mf-"); + FillFileNameByUID(fnameptr, dump, "-dump", 4); } - // put hex - for (i = 0; i < numBlocks; i++) { - if (mfEmlGetMem(buf, i, 1)) { - PrintAndLogEx(WARNING, "Cant get block: %d", i); - break; - } - for (j = 0; j < 16; j++) - fprintf(f, "%02X", buf[j]); - - if (i != numBlocks -1) - fprintf(f, "\n"); - printf("."); fflush(stdout); - } - PrintAndLogEx(NORMAL, "\n"); - fclose(f); - PrintAndLogEx(SUCCESS, "Saved %d blocks to file: %s", numBlocks, filename); + saveFile(filename, "bin", dump, bytes); + saveFileEML(filename, "eml", dump, bytes, MFBLOCK_SIZE); + free(dump); return 0; } @@ -2811,75 +2780,50 @@ int CmdHF14AMfCGetSc(const char *Cmd) { int CmdHF14AMfCSave(const char *Cmd) { - FILE * feml; - FILE * fbin; - char filename[2][FILE_PATH_SIZE]; - char * femlptr = filename[0]; - char * fbinptr = filename[1]; - bool fillFromEmulator = false; - bool errors = false; - bool hasname = false; - uint8_t buf[16]; - int i, j, len, flags; - uint8_t numblocks = 0; - uint8_t cmdp = 0; + char filename[FILE_PATH_SIZE]; + char * fnameptr = filename; + uint8_t *dump; + bool fillEmulator = false; + bool errors = false, hasname = false, useuid = false; + int i, len, flags; + uint8_t numblocks = 0, cmdp = 0; + uint16_t bytes = 0; char ctmp; - - memset(filename, 0, sizeof(filename)); - memset(buf, 0, sizeof(buf)); - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - ctmp = param_getchar(Cmd, cmdp); - switch(ctmp) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + ctmp = tolower(param_getchar(Cmd, cmdp)); + switch (ctmp) { case 'e': - case 'E': - fillFromEmulator = true; + useuid = true; + fillEmulator = true; cmdp++; break; case 'h': - case 'H': return usage_hf14_csave(); case '0': case '1': case '2': case '4': numblocks = NumOfBlocks(ctmp); + bytes = numblocks * MFBLOCK_SIZE; PrintAndLogEx(SUCCESS, "Saving magic mifare %cK", ctmp); cmdp++; break; case 'u': - case 'U': - // get filename based on UID - if (mfCGetBlock(0, buf, MAGIC_SINGLE)) { - PrintAndLogEx(FAILED, "Cant get block: %d", 0); - femlptr += sprintf(femlptr, "dump"); - fbinptr += sprintf(fbinptr, "dump"); - } else { - for (j = 0; j < 7; j++) { - femlptr += sprintf(femlptr, "%02x", buf[j]); - fbinptr += sprintf(fbinptr, "%02x", buf[j]); - } - } + useuid = true; hasname = true; cmdp++; break; case 'o': - case 'O': - // input file - len = param_getstr(Cmd, cmdp+1, filename[0], FILE_PATH_SIZE); - len = param_getstr(Cmd, cmdp+1, filename[1], FILE_PATH_SIZE); - + len = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); if (len < 1) { errors = true; break; } - if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; - femlptr += len; - fbinptr += len; - - hasname = true; + useuid = false; + hasname = true; cmdp += 2; break; default: @@ -2889,75 +2833,49 @@ int CmdHF14AMfCSave(const char *Cmd) { } } - // must have filename when saving. - if (!hasname && !fillFromEmulator) errors = true; + if (!hasname && !fillEmulator) errors = true; - //Validations if (errors || cmdp == 0) return usage_hf14_csave(); - - if (fillFromEmulator) { - // put into emulator - flags = MAGIC_INIT + MAGIC_WUPC; - for (i = 0; i < numblocks; i++) { - if (i == 1) flags = 0; - if (i == numblocks - 1) flags = MAGIC_HALT + MAGIC_OFF; - - if (mfCGetBlock(i, buf, flags)) { - PrintAndLogEx(WARNING, "Cant get block: %d", i); - return 3; - } - - if (mfEmlSetMem(buf, i, 1)) { - PrintAndLogEx(WARNING, "Cant set emul block: %d", i); - return 3; - } - printf("."); fflush(stdout); - } - PrintAndLogEx(NORMAL, "\n"); - return 0; - } - sprintf(femlptr, ".eml"); - sprintf(fbinptr, ".bin"); - - if ((feml = fopen(filename[0], "w+")) == NULL ) { - PrintAndLogEx(WARNING, "File not found or locked"); + dump = malloc(bytes); + if (!dump) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return 1; } + memset(dump, 0, bytes); - if ((fbin = fopen(filename[1], "wb")) == NULL) { - PrintAndLogEx(WARNING, "File not found or locked"); - return 1; - } - - // dump to files flags = MAGIC_INIT + MAGIC_WUPC; for (i = 0; i < numblocks; i++) { if (i == 1) flags = 0; if (i == numblocks - 1) flags = MAGIC_HALT + MAGIC_OFF; - if (mfCGetBlock(i, buf, flags)) { + if (mfCGetBlock(i, dump + (i*MFBLOCK_SIZE), flags)) { PrintAndLogEx(WARNING, "Cant get block: %d", i); - break; + free(dump); + return 2; } - // eml - for (j = 0; j < 16; j++) - fprintf(feml, "%02x", buf[j]); - - if (i != numblocks -1) - fprintf(feml,"\n"); - - // bin - fwrite(buf, 1, sizeof(buf), fbin); - printf("."); fflush(stdout); } - PrintAndLogEx(NORMAL, "\n"); - fflush(feml); fflush(fbin); - fclose(feml); fclose(fbin); - - for (uint8_t i=0; i<2; ++i) - PrintAndLogEx(SUCCESS, "Saved %d blocks to file: %s", numblocks, filename[i]); + + if ( useuid ){ + fnameptr += sprintf(fnameptr, "hf-mf-"); + FillFileNameByUID(fnameptr, dump, "-dump", 4); + } + + if (fillEmulator) { + PrintAndLogEx(INFO, "uploading to emulator memory"); + for (i = 0; i < numblocks; i += 5) { + if (mfEmlSetMem(dump + (i*MFBLOCK_SIZE), i, 5)) { + PrintAndLogEx(WARNING, "Cant set emul block: %d", i); + } + printf("."); fflush(stdout); + } + PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(SUCCESS, "uploaded %d bytes to emulator memory", bytes); + } + saveFile(filename, "bin", dump, bytes); + saveFileEML(filename, "eml", dump, bytes, MFBLOCK_SIZE); + free(dump); return 0; } From f679db96837089bcdd80b4fb61dc20336fb090dd Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 16 Sep 2018 23:07:19 +0200 Subject: [PATCH 0063/1938] textual --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 8301bfa06..9f1f9702a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Change 'hf mf csave' - now saves both EML/BIN formats (@iceman) + - Change 'hf mf esave' - now saves both EML/BIN formats (@iceman) - Fix 'compiler warning on macos and gcc7.1 or higher' (@TomHarkness) - Fix 'crash on Bionic libc if CloseProxmark is called twice' (@micolous) - Change 'lf hid' - got an updated to Kastle format (@xilni) From b89b62164d43ed0293cff577f6521c7ba0762dfa Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 18 Sep 2018 20:28:54 +0200 Subject: [PATCH 0064/1938] added emv tag (@merlokk) https://github.com/Proxmark/proxmark3/pull/676 --- client/emv/emv_tags.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index cdd57cb51..a29b15048 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -272,6 +272,7 @@ static const struct emv_tag emv_tags[] = { { 0x9f6a, "Unpredictable Number", EMV_TAG_NUMERIC }, { 0x9f6b, "Track 2 Data" }, { 0x9f6c, "Card Transaction Qualifiers (CTQ)", EMV_TAG_BITMASK, &EMV_CTQ }, + { 0x9f6e, "Form Factor Indicator" }, { 0xa5 , "File Control Information (FCI) Proprietary Template" }, { 0xbf0c, "File Control Information (FCI) Issuer Discretionary Data" }, { 0xdf20, "Issuer Proprietary Bitmap (IPB)" }, From dc67b5d7c9301cef64ee2286887243fcc34384c4 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 23 Sep 2018 05:29:55 +0200 Subject: [PATCH 0065/1938] chg: revert fpga_major mode in LF. chg: 'lf t55xx deviceconfig' - persistence to flashmem is now option with param P --- armsrc/appmain.c | 2 +- armsrc/apps.h | 2 +- armsrc/flashmem.c | 48 +++++++++++++++++++++++++++++++++-------- armsrc/flashmem.h | 1 + armsrc/lfops.c | 52 ++++++++++++++++++++++++++++----------------- client/cmdlft55xx.c | 14 +++++++----- client/util.c | 4 ++-- common/i2c.c | 10 ++++----- common/protocols.h | 1 + include/common.h | 32 ++++++++++++++++++++++------ 10 files changed, 117 insertions(+), 49 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 8a63f72e4..a84a33d48 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -633,7 +633,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { switch(c->cmd) { #ifdef WITH_LF case CMD_SET_LF_T55XX_CONFIG: - setT55xxConfig((t55xx_config *) c->d.asBytes); + setT55xxConfig( c->arg[0], (t55xx_config *) c->d.asBytes); break; case CMD_SET_LF_SAMPLING_CONFIG: setSamplingConfig((sample_config *) c->d.asBytes); diff --git a/armsrc/apps.h b/armsrc/apps.h index 81a073904..1e8524d57 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -108,7 +108,7 @@ void TurnReadLFOn(uint32_t delay); void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd); void EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd); void Cotag(uint32_t arg0); -void setT55xxConfig(t55xx_config *c); +void setT55xxConfig(uint8_t arg0, t55xx_config *c); t55xx_config * getT55xxConfig(void); void printT55xxConfig(void); void loadT55xxConfig(void); diff --git a/armsrc/flashmem.c b/armsrc/flashmem.c index 3007ffbc1..3a46500ba 100644 --- a/armsrc/flashmem.c +++ b/armsrc/flashmem.c @@ -13,7 +13,6 @@ uint32_t FLASHMEM_SPIBAUDRATE = FLASH_BAUD; - void FlashmemSetSpiBaudrate(uint32_t baudrate){ FLASHMEM_SPIBAUDRATE = baudrate; Dbprintf("Spi Baudrate : %dMhz", FLASHMEM_SPIBAUDRATE/1000000); @@ -316,7 +315,6 @@ uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) { //////////////////////////////////////// - // Write data can only program one page. A page has 256 bytes. // if len > 256, it might wrap around and overwrite pos 0. uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { @@ -361,25 +359,25 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { return len; } + +// length should never be zero +// Max 256 bytes write +// out-of-range uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) { - // length should never be zero if (!len) return 0; - // Max 256 bytes write if (((address & 0xFF) + len) > 256) { - Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len ); + Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len ); return 0; } - // out-of-range if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) { - Dbprintf("Flash_WriteData, block out-of-range"); + Dbprintf("Flash_WriteDataCont, block out-of-range"); return 0; } - FlashSendByte(PAGEPROG); FlashSendByte((address >> 16) & 0xFF); FlashSendByte((address >> 8) & 0xFF); @@ -390,10 +388,42 @@ uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) { FlashSendByte(in[i]); FlashSendLastByte(in[i]); - return len; } +// assumes valid start 256 based 00 address +// +uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len) { + + bool isok; + uint16_t res, bytes_sent = 0, bytes_remaining = len; + uint8_t buf[FLASH_MEM_BLOCK_SIZE]; + while (bytes_remaining > 0) { + + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); + + uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); + + memcpy(buf, in + bytes_sent, bytes_in_packet); + + res = Flash_WriteDataCont(address + bytes_sent, buf, bytes_in_packet); + + bytes_remaining -= bytes_in_packet; + bytes_sent += bytes_in_packet; + + isok = (res == bytes_in_packet); + + if (!isok) + goto out; + } + +out: + FlashStop(); + return len; +} + + bool Flash_WipeMemoryPage(uint8_t page) { if (!FlashInit()) { if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); diff --git a/armsrc/flashmem.h b/armsrc/flashmem.h index ae10ea388..da81363c0 100644 --- a/armsrc/flashmem.h +++ b/armsrc/flashmem.h @@ -144,6 +144,7 @@ uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len); uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len); +uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len); uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len); uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len); void Flashmem_print_status(void); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index ce161d6dd..18e178c1f 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -70,7 +70,7 @@ void printT55xxConfig(void) { Dbprintf(" [e] readgap.............%d*8 (%d)", t_config.read_gap/8, t_config.read_gap); } -void setT55xxConfig(t55xx_config *c) { +void setT55xxConfig(uint8_t arg0, t55xx_config *c) { if (c->start_gap != 0) t_config.start_gap = c->start_gap; if (c->write_gap != 0) t_config.write_gap = c->write_gap; @@ -81,24 +81,36 @@ void setT55xxConfig(t55xx_config *c) { printT55xxConfig(); #if WITH_FLASH + // shall persist to flashmem + if (arg0 == 0) { + return; + } + if (!FlashInit()) { return; } - uint8_t buf[T55XX_CONFIG_LEN]; + uint8_t *buf = BigBuf_malloc(4096); + Flash_CheckBusy(BUSY_TIMEOUT); + uint16_t res = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, 4096); + if ( res == 0) { + FlashStop(); + BigBuf_free(); + return; + } + memcpy(buf, &t_config, T55XX_CONFIG_LEN); Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); - uint16_t isok = Flash_WriteDataCont(T55XX_CONFIG_OFFSET, buf, sizeof(buf)); - FlashStop(); + Flash_WriteEnable(); + Flash_Erase4k(3, 0xD); + res = Flash_Write(T55XX_CONFIG_OFFSET, buf, 4096); - if ( isok == T55XX_CONFIG_LEN) { - if (MF_DBGLEVEL > 1) { - DbpString("T55XX Config save success"); - Dbhexdump(sizeof(buf), buf, false); - } + if ( res == 4096 && MF_DBGLEVEL > 1) { + DbpString("T55XX Config save success"); } + + BigBuf_free(); #endif } @@ -139,7 +151,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint // Make sure the tag is reset FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitMS(500); // clear read buffer @@ -180,7 +192,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint if (command[counter] == '0') { // if field already off leave alone (affects timing otherwise) if (off == false) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); off = true; } @@ -207,7 +219,7 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint TurnReadLFOn(period_1); LED_D_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(delay_off); } @@ -1328,7 +1340,7 @@ void TurnReadLFOn(uint32_t delay) { WaitUS(delay); } void TurnReadLF_off(uint32_t delay) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(delay); } @@ -1338,7 +1350,7 @@ void T55xxWriteBit(int bit) { TurnReadLFOn(t_config.write_0); else TurnReadLFOn(t_config.write_1); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(t_config.write_gap); } @@ -1356,7 +1368,7 @@ void T55xxResetRead(void) { WaitMS(4); // Trigger T55x7 in mode. - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(t_config.start_gap); // reset tag - op code 00 @@ -1390,7 +1402,7 @@ void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) // make sure tag is fully powered up... WaitMS(4); // Trigger T55x7 in mode. - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(t_config.start_gap); if (testMode) Dbprintf("TestMODE"); @@ -1475,7 +1487,7 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { // make sure tag is fully powered up... WaitMS(4); // Trigger T55x7 Direct Access Mode with start gap - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(t_config.start_gap); // Opcode 1[page] @@ -1522,7 +1534,7 @@ void T55xxWakeUp(uint32_t Pwd){ WaitMS(4); // Trigger T55x7 Direct Access Mode - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(t_config.start_gap); // Opcode 10 @@ -1962,7 +1974,7 @@ This triggers a COTAG tag to response */ void Cotag(uint32_t arg0) { #ifndef OFF -# define OFF { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF_LF); WaitUS(2035); } +# define OFF { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(2035); } #endif #ifndef ON # define ON(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); WaitUS((x)); } diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 71a26ddd3..743d2db9c 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -189,7 +189,7 @@ int usage_t55xx_recoverpw(){ } int usage_lf_deviceconfig(){ PrintAndLogEx(NORMAL, "Sets t55x7 timings for direkt commands. The timings are set here in Field Clocks (FC), \nwhich is converted to (US) on device"); - PrintAndLogEx(NORMAL, "Usage: lf t55xx deviceconfig a b c d e "); + PrintAndLogEx(NORMAL, "Usage: lf t55xx deviceconfig a b c d e p"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - This help"); PrintAndLogEx(NORMAL, " a <8..255> - Set start gap"); @@ -197,9 +197,9 @@ int usage_lf_deviceconfig(){ PrintAndLogEx(NORMAL, " c <8..255> - Set write ZERO gap"); PrintAndLogEx(NORMAL, " d <8..255> - Set write ONE gap"); PrintAndLogEx(NORMAL, " e <8..255> - Set read gap"); + PrintAndLogEx(NORMAL, " p - persist to flashmemory"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 31 - start gap 31*8"); PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 29 b 17 c 15 d 47 e 15 - default T55XX"); PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 55 b 14 c 21 d 30 - default EM4305"); PrintAndLogEx(NORMAL, ""); @@ -1903,7 +1903,7 @@ int CmdT55xxDetectPage1(const char *Cmd){ int CmdT55xxSetDeviceConfig(const char *Cmd){ uint8_t startgap = 0, writegap = 0; uint8_t write0 = 0, write1 = 0, readgap = 0; - bool errors = false; + bool errors = false, shall_persist = false; uint8_t cmdp = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { @@ -1928,7 +1928,11 @@ int CmdT55xxSetDeviceConfig(const char *Cmd){ case 'e': errors |= param_getdec(Cmd, cmdp+1, &readgap); cmdp += 2; - break; + break; + case 'p': + shall_persist = true; + cmdp++; + break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = 1; @@ -1941,7 +1945,7 @@ int CmdT55xxSetDeviceConfig(const char *Cmd){ t55xx_config config = { startgap*8, writegap*8, write0*8, write1*8, readgap*8 }; - UsbCommand c = {CMD_SET_LF_T55XX_CONFIG, {0,0,0} }; + UsbCommand c = {CMD_SET_LF_T55XX_CONFIG, {shall_persist,0,0} }; memcpy(c.d.asBytes, &config, sizeof(t55xx_config)); clearCommandBuffer(); SendCommand(&c); diff --git a/client/util.c b/client/util.c index 4a256e0b2..6ed6201fa 100644 --- a/client/util.c +++ b/client/util.c @@ -110,8 +110,8 @@ void FillFileNameByUID(char *filenamePrefix, uint8_t *uid, const char *ext, int return; } - int len=0; - len=strlen(filenamePrefix); + int len = 0; + len = strlen(filenamePrefix); //memset(fn, 0x00, FILE_PATH_SIZE); for (int j = 0; j < uidlen; j++) diff --git a/common/i2c.c b/common/i2c.c index 159efcad2..262fd832a 100644 --- a/common/i2c.c +++ b/common/i2c.c @@ -88,11 +88,11 @@ void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) { // Reset the SIM_Adapter, then enter the main program // Note: the SIM_Adapter will not enter the main program after power up. Please run this function before use SIM_Adapter. void I2C_Reset_EnterMainProgram(void) { - I2C_SetResetStatus(0, 0, 0); // ͸λ + I2C_SetResetStatus(0, 0, 0); SpinDelay(30); - I2C_SetResetStatus(1, 0, 0); // λ + I2C_SetResetStatus(1, 0, 0); SpinDelay(30); - I2C_SetResetStatus(1, 1, 1); // + I2C_SetResetStatus(1, 1, 1); SpinDelay(10); } @@ -100,9 +100,9 @@ void I2C_Reset_EnterMainProgram(void) { // Reset the SIM_Adapter, then enter the bootloader program // ReserveFor firmware update. void I2C_Reset_EnterBootloader(void) { - I2C_SetResetStatus(0, 1, 1); // ͸λ + I2C_SetResetStatus(0, 1, 1); SpinDelay(100); - I2C_SetResetStatus(1, 1, 1); // λ + I2C_SetResetStatus(1, 1, 1); SpinDelay(10); } diff --git a/common/protocols.h b/common/protocols.h index 82cea74ad..0f3ef3407 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -304,6 +304,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define ISO7816_GET_CHALLENGE 0xB4 #define ISO7816_MANAGE_CHANNEL 0x70 +#define ISO7816_GETSTATUS 0xC0 // ISO7816-4 For response APDU's #define ISO7816_OK 0x9000 // 6x xx = ERROR diff --git a/include/common.h b/include/common.h index 24e085699..90394448c 100644 --- a/include/common.h +++ b/include/common.h @@ -50,6 +50,13 @@ extern uint32_t FLASHMEM_SPIBAUDRATE; #define RAMFUNC __attribute((long_call, section(".ramfunc"))) // RDV40 Section +// 256kb divided into 4k sectors. +// +// last 4k sector = signature +// second last 4k sector = settings +// third last 4k sector = default MF keys dictionary +// forth last 4k sector = default LF keys dictionary + #ifndef FLASH_MEM_BLOCK_SIZE # define FLASH_MEM_BLOCK_SIZE 256 #endif @@ -58,6 +65,11 @@ extern uint32_t FLASHMEM_SPIBAUDRATE; # define FLASH_MEM_MAX_SIZE 0x3FFFF // (262143) #endif +#ifndef FLASH_MEM_MAX_4K_SECTOR +# define FLASH_MEM_MAX_4K_SECTOR 0x3F000 +#endif + + #ifndef FLASH_MEM_ID_LEN # define FLASH_MEM_ID_LEN 8 #endif @@ -71,13 +83,21 @@ extern uint32_t FLASHMEM_SPIBAUDRATE; #endif #if WITH_FLASH -#ifndef T55XX_CONFIG_LEN -# define T55XX_CONFIG_LEN sizeof( t55xx_config ) -#endif + #ifndef T55XX_CONFIG_LEN + # define T55XX_CONFIG_LEN sizeof( t55xx_config ) + #endif -#ifndef T55XX_CONFIG_OFFSET -#define T55XX_CONFIG_OFFSET (FLASH_MEM_MAX_SIZE - FLASH_MEM_SIGNATURE_LEN - T55XX_CONFIG_LEN) -#endif + #ifndef T55XX_CONFIG_OFFSET + # define T55XX_CONFIG_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x2000) + #endif + + #ifndef DEFAULT_MF_KEYS_OFFSET + # define DEFAULT_MF_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x3000) + #endif + + #ifndef DEFAULT_LF_KEYS_OFFSET + # define DEFAULT_LF_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x4000) + #endif #endif // RDV40, validation structure to help identifying that client/firmware is talking with RDV40 From 125884c3d5d01764658a9d2370320025ba997223 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 23 Sep 2018 16:35:40 +0200 Subject: [PATCH 0066/1938] CHG: 'sc raw' - now requests response if inital command got 0x61 response --- client/cmdsmartcard.c | 87 +++++++++++++++++++++++++++++++------------ 1 file changed, 64 insertions(+), 23 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 7f894abde..3bf12115a 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -62,6 +62,53 @@ int usage_sm_setclock(void) { return 0; } +static int smart_wait(uint8_t *data) { + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { + PrintAndLogEx(WARNING, "smart card response failed"); + return -1; + } + + uint32_t len = resp.arg[0]; + if ( !len ) { + PrintAndLogEx(WARNING, "smart card response failed"); + return -2; + } + memcpy(data, resp.d.asBytes, len); + PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len)); + return len; +} + +static int smart_response(uint8_t *data) { + + int len = -1; + int datalen = smart_wait(data); + + if ( datalen == 3 && data[1] == 0x61 ) { + len = data[2]; + } else if ( datalen == 2 && data[0] == 0x61 ) { + len = data[1]; + } + + if (len == -1 ) { + goto out; + } + + PrintAndLogEx(INFO, "Requesting response"); + uint8_t getstatus[] = {0x00, ISO7816_GETSTATUS, 0x00, 0x00, len }; + UsbCommand cStatus = {CMD_SMART_RAW, {SC_RAW, sizeof(getstatus), 0}}; + memcpy(cStatus.d.asBytes, getstatus, sizeof(getstatus) ); + clearCommandBuffer(); + SendCommand(&cStatus); + + datalen = smart_wait(data); +out: + if (data) + free(data); + + return datalen; +} + int CmdSmartRaw(const char *Cmd) { int hexlen = 0; @@ -135,41 +182,35 @@ int CmdSmartRaw(const char *Cmd) { memcpy(c.d.asBytes, data, hexlen ); clearCommandBuffer(); - SendCommand(&c); - + SendCommand(&c); + // reading response from smart card if ( reply ) { - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - PrintAndLogEx(WARNING, "smart card response failed"); - return 1; - } - uint32_t datalen = resp.arg[0]; - - if ( !datalen ) { - PrintAndLogEx(WARNING, "smart card response failed"); - return 1; - } - PrintAndLogEx(INFO, "received %i bytes", datalen); - - if (!datalen) - return 1; + uint8_t* buf = malloc(USB_CMD_DATA_SIZE); + if ( !buf ) + return 1; - uint8_t *data = resp.d.asBytes; + int len = smart_response(buf); + if ( len < 0 ) { + free(buf); + return 2; + } // TLV decoder if (decodeTLV ) { - if (datalen >= 2) { - PrintAndLogEx(SUCCESS, "%02x %02x | %s", data[datalen - 2], data[datalen - 1], GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1])); + if (len >= 2) { + PrintAndLogEx(SUCCESS, "%02x %02x | %s", buf[len - 2], buf[len - 1], GetAPDUCodeDescription(buf[len - 2], buf[len - 1])); } - if (datalen > 4) { - TLVPrintFromBuffer(data, datalen - 2); + if (len > 4) { + TLVPrintFromBuffer(buf, len - 2); } } else { - PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, datalen)); + PrintAndLogEx(SUCCESS, "%s", sprint_hex(buf, len)); } + + free(buf); } return 0; } From f3d1c9ea774dec68473770cbc17f3e919782987c Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 23 Sep 2018 17:05:29 +0200 Subject: [PATCH 0067/1938] chg: 'sc raw' - added response code annotation --- client/cmdsmartcard.c | 23 ++++++++++------------- 1 file changed, 10 insertions(+), 13 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 3bf12115a..6fb74b14a 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -73,9 +73,13 @@ static int smart_wait(uint8_t *data) { if ( !len ) { PrintAndLogEx(WARNING, "smart card response failed"); return -2; - } + } memcpy(data, resp.d.asBytes, len); - PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len)); + PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len)); + + if (len >= 2) { + PrintAndLogEx(SUCCESS, "%02x %02x | %s", data[len - 2], data[len - 1], GetAPDUCodeDescription(data[len - 2], data[len - 1])); + } return len; } @@ -84,12 +88,10 @@ static int smart_response(uint8_t *data) { int len = -1; int datalen = smart_wait(data); - if ( datalen == 3 && data[1] == 0x61 ) { - len = data[2]; - } else if ( datalen == 2 && data[0] == 0x61 ) { - len = data[1]; + if ( data[datalen - 2] == 0x61 ) { + len = data[datalen - 1]; } - + if (len == -1 ) { goto out; } @@ -103,8 +105,6 @@ static int smart_response(uint8_t *data) { datalen = smart_wait(data); out: - if (data) - free(data); return datalen; } @@ -206,10 +206,7 @@ int CmdSmartRaw(const char *Cmd) { if (len > 4) { TLVPrintFromBuffer(buf, len - 2); } - } else { - PrintAndLogEx(SUCCESS, "%s", sprint_hex(buf, len)); - } - + } free(buf); } return 0; From 4fa0835d5f7823b9b850be7c7162a98f9a3973a2 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 23 Sep 2018 20:18:27 +0200 Subject: [PATCH 0068/1938] FIX: APDUCodeTable has more items than 100 --- client/emv/apduinfo.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/client/emv/apduinfo.c b/client/emv/apduinfo.c index 81331241c..b1bb84dae 100644 --- a/client/emv/apduinfo.c +++ b/client/emv/apduinfo.c @@ -255,7 +255,7 @@ const APDUCode APDUCodeTable[] = { {"9F00", APDUCODE_TYPE_NONE, "PIN blocked and Unblock Try Counter is 3"}, {"9F04", APDUCODE_TYPE_NONE, "PIN not succesfully verified, PIN blocked and Unblock Try Counter is 3"}, {"9FXX", APDUCODE_TYPE_NONE, "Command successfully executed; 'xx' bytes of data are available and can be requested using GET RESPONSE."}, - {"9xXX", APDUCODE_TYPE_NONE, "Application related status, (ISO 7816-3)"} + {"9XXX", APDUCODE_TYPE_NONE, "Application related status, (ISO 7816-3)"} }; const size_t APDUCodeTableLen = sizeof(APDUCodeTable)/sizeof(APDUCode); @@ -280,11 +280,10 @@ int CodeCmp(const char *code1, const char *code2) { const APDUCode* const GetAPDUCode(uint8_t sw1, uint8_t sw2) { char buf[6] = {0}; int res; - int mineq = 100; + int mineq = APDUCodeTableLen; int mineqindx = 0; - sprintf(&buf[0], "%02X", sw1); - sprintf(&buf[2], "%02X", sw2); + sprintf(buf, "%02X%02X", sw1, sw2); for (int i = 0; i < APDUCodeTableLen; i++) { res = CodeCmp(APDUCodeTable[i].ID, buf); @@ -302,7 +301,7 @@ const APDUCode* const GetAPDUCode(uint8_t sw1, uint8_t sw2) { } // if we have not equal, but with some 'X' - if (mineqindx < 100) { + if (mineqindx < APDUCodeTableLen) { return &APDUCodeTable[mineqindx]; } From dbed5d58551b0c35554e1e542bb6857781a61063 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 23 Sep 2018 20:40:37 +0200 Subject: [PATCH 0069/1938] ADD: 'sc brute' - a naive sfi bruteforcer for smartcards. When a SFI is found, it is read/printed A first attempt, work-in-progress. --- client/cmdsmartcard.c | 92 ++++++++++++++++++++++++++++++++++--------- 1 file changed, 73 insertions(+), 19 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 6fb74b14a..e6374db9e 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -15,13 +15,14 @@ int usage_sm_raw(void) { PrintAndLogEx(NORMAL, "Usage: sc raw [h|r|c] d <0A 0B 0C ... hex>"); PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, " r : do not read response"); - PrintAndLogEx(NORMAL, " a : active signal field ON without select"); - PrintAndLogEx(NORMAL, " s : active signal field ON with select"); + PrintAndLogEx(NORMAL, " a : active smartcard without select"); + PrintAndLogEx(NORMAL, " s : active smartcard with select"); PrintAndLogEx(NORMAL, " t : executes TLV decoder if it possible"); PrintAndLogEx(NORMAL, " d : bytes to send"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " sc raw d 11223344"); + PrintAndLogEx(NORMAL, " sc raw d 00a404000e315041592e5359532e444446303100 - “1PAY.SYS.DDF01” PPSE directory"); + PrintAndLogEx(NORMAL, " sc raw d 00a404000e325041592e5359532e444446303100 - “2PAY.SYS.DDF01” PPSE directory"); return 0; } int usage_sm_reader(void) { @@ -61,6 +62,15 @@ int usage_sm_setclock(void) { PrintAndLogEx(NORMAL, " sc setclock c 2"); return 0; } +int usage_sm_brute(void) { + PrintAndLogEx(NORMAL, "Tries to bruteforce SFI, "); + PrintAndLogEx(NORMAL, "Usage: sc brute [h]"); + PrintAndLogEx(NORMAL, " h : this help"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " sc brute"); + return 0; +} static int smart_wait(uint8_t *data) { UsbCommand resp; @@ -75,10 +85,10 @@ static int smart_wait(uint8_t *data) { return -2; } memcpy(data, resp.d.asBytes, len); - PrintAndLogEx(SUCCESS, "%s", sprint_hex(data, len)); + PrintAndLogEx(SUCCESS, "%s", sprint_hex_inrow_ex(data, len, 32)); if (len >= 2) { - PrintAndLogEx(SUCCESS, "%02x %02x | %s", data[len - 2], data[len - 1], GetAPDUCodeDescription(data[len - 2], data[len - 1])); + PrintAndLogEx(SUCCESS, "%02X%02X | %s", data[len - 2], data[len - 1], GetAPDUCodeDescription(data[len - 2], data[len - 1])); } return len; } @@ -88,7 +98,7 @@ static int smart_response(uint8_t *data) { int len = -1; int datalen = smart_wait(data); - if ( data[datalen - 2] == 0x61 ) { + if ( data[datalen - 2] == 0x61 || data[datalen - 2] == 0x9F ) { len = data[datalen - 1]; } @@ -198,15 +208,9 @@ int CmdSmartRaw(const char *Cmd) { } // TLV decoder - if (decodeTLV ) { - - if (len >= 2) { - PrintAndLogEx(SUCCESS, "%02x %02x | %s", buf[len - 2], buf[len - 1], GetAPDUCodeDescription(buf[len - 2], buf[len - 1])); - } - if (len > 4) { - TLVPrintFromBuffer(buf, len - 2); - } - } + if (decodeTLV && len > 4) { + TLVPrintFromBuffer(buf+1, len-2); + } free(buf); } return 0; @@ -469,14 +473,64 @@ int CmdSmartList(const char *Cmd) { return 0; } +int CmdSmartBruteforceSFI(const char *Cmd) { + + char ctmp = tolower(param_getchar(Cmd, 0)); + if (ctmp == 'h') return usage_sm_brute(); + + uint8_t data[5] = {0x00, 0xB2, 0x00, 0x00, 0x00}; + + PrintAndLogEx(INFO, "Selecting"); + CmdSmartRaw("d 00a404000e325041592e5359532e444446303100"); + CmdSmartRaw("d 00a4040007a000000004101000"); + + PrintAndLogEx(INFO, "starting"); + + UsbCommand c = {CMD_SMART_RAW, {SC_RAW, sizeof(data), 0}}; + + uint8_t* buf = malloc(USB_CMD_DATA_SIZE); + if ( !buf ) + return 1; + + for (uint8_t i=1; i < 4; i++) { + for (int p1=1; p1 < 5; p1++) { + + data[2] = p1; + data[3] = (i << 3) + 4; + + memcpy(c.d.asBytes, data, sizeof(data) ); + clearCommandBuffer(); + SendCommand(&c); + + smart_response(buf); + + // if 0x6C + if ( buf[0] == 0x6C ) { + data[4] = buf[1]; + + memcpy(c.d.asBytes, data, sizeof(data) ); + clearCommandBuffer(); + SendCommand(&c); + smart_response(buf); + + data[4] = 0; + } + memset(buf, 0x00, USB_CMD_DATA_SIZE); + } + } + free(buf); + return 0; +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"list", CmdSmartList, 0, "List ISO 7816 history"}, - {"info", CmdSmartInfo, 1, "Tag information [rdv40]"}, - {"reader", CmdSmartReader, 1, "Act like an IS07816 reader [rdv40]"}, - {"raw", CmdSmartRaw, 1, "Send raw hex data to tag [rdv40]"}, - {"upgrade", CmdSmartUpgrade, 1, "Upgrade firmware [rdv40]"}, + {"info", CmdSmartInfo, 1, "Tag information"}, + {"reader", CmdSmartReader, 1, "Act like an IS07816 reader"}, + {"raw", CmdSmartRaw, 1, "Send raw hex data to tag"}, + {"upgrade", CmdSmartUpgrade, 1, "Upgrade firmware"}, {"setclock", CmdSmartSetClock, 1, "Set clock speed"}, + {"brute", CmdSmartBruteforceSFI, 1, "Bruteforce SFI"}, {NULL, NULL, 0, NULL} }; From 50143e460d3af81950d20702e3ca69a44613c165 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 23 Sep 2018 20:41:29 +0200 Subject: [PATCH 0070/1938] syntax --- client/cmdhf14a.c | 8 ++++---- client/cmdhf15.c | 1 - client/cmdhffelica.c | 4 ++-- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 617a703e4..418de8ec5 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -657,10 +657,10 @@ int CmdHF14ASniff(const char *Cmd) { int param = 0; uint8_t ctmp; for (int i = 0; i < 2; i++) { - ctmp = param_getchar(Cmd, i); - if (ctmp == 'h' || ctmp == 'H') return usage_hf_14a_sniff(); - if (ctmp == 'c' || ctmp == 'C') param |= 0x01; - if (ctmp == 'r' || ctmp == 'R') param |= 0x02; + ctmp = tolower(param_getchar(Cmd, i)); + if (ctmp == 'h') return usage_hf_14a_sniff(); + if (ctmp == 'c') param |= 0x01; + if (ctmp == 'r') param |= 0x02; } UsbCommand c = {CMD_SNOOP_ISO_14443a, {param, 0, 0}}; clearCommandBuffer(); diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 1fe44de0e..d8a212130 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -686,7 +686,6 @@ int CmdHF15Dump(const char*Cmd) { fptr += sprintf(fptr, "hf-15-"); FillFileNameByUID(fptr,uid,"-dump",sizeof(uid)); - } // detect blocksize from card :) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 25baca523..e8eeceb5e 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -350,8 +350,8 @@ uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace,uint16_t tracelen) { int CmdHFFelicaDumpLite(const char *Cmd) { - char ctmp = param_getchar(Cmd, 0); - if ( ctmp == 'h' || ctmp == 'H') return usage_hf_felica_dumplite(); + char ctmp = tolower(param_getchar(Cmd, 0)); + if ( ctmp == 'h') return usage_hf_felica_dumplite(); PrintAndLogEx(SUCCESS, "FeliCa lite - dump started"); PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); From 8792849732313d7625dcfcd499c0d968ba041a3b Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 23 Sep 2018 20:56:33 +0200 Subject: [PATCH 0071/1938] text --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9f1f9702a..b0e2cdec9 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added 'sc brute' - a naive SFI bruteforcer for contact smartcards (RDV40) (@iceman) + - Change 'lf t55xx detectconfig' - now optional to persist settings to flashmem (RDV40) (@iceman) - Change 'hf mf csave' - now saves both EML/BIN formats (@iceman) - Change 'hf mf esave' - now saves both EML/BIN formats (@iceman) - Fix 'compiler warning on macos and gcc7.1 or higher' (@TomHarkness) From 97c0729289299ab247ed7b277db8fc22158cba05 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 25 Sep 2018 02:54:51 +0200 Subject: [PATCH 0072/1938] fix: 'sc raw t' - tlv decoding work again chg: 'sc brute' - now decodes TLV by default the found SFI chg: 'sc raw' - better detection on armside when failing --- client/cmdsmartcard.c | 47 ++++++++++++++++++++++++++++++++++--------- common/i2c.c | 35 +++++++++----------------------- 2 files changed, 47 insertions(+), 35 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index e6374db9e..f60e04e06 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -72,6 +72,24 @@ int usage_sm_brute(void) { return 0; } +static bool smart_select(bool silent) { + UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) { + if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); + return false; + } + + uint8_t isok = resp.arg[0] & 0xFF; + if (!isok) { + if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); + return false; + } + return true; +} + static int smart_wait(uint8_t *data) { UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { @@ -85,7 +103,7 @@ static int smart_wait(uint8_t *data) { return -2; } memcpy(data, resp.d.asBytes, len); - PrintAndLogEx(SUCCESS, "%s", sprint_hex_inrow_ex(data, len, 32)); + PrintAndLogEx(SUCCESS, " %d | %s", len, sprint_hex_inrow_ex(data, len, 32)); if (len >= 2) { PrintAndLogEx(SUCCESS, "%02X%02X | %s", data[len - 2], data[len - 1], GetAPDUCodeDescription(data[len - 2], data[len - 1])); @@ -197,7 +215,7 @@ int CmdSmartRaw(const char *Cmd) { // reading response from smart card if ( reply ) { - uint8_t* buf = malloc(USB_CMD_DATA_SIZE); + uint8_t* buf = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t)); if ( !buf ) return 1; @@ -208,9 +226,9 @@ int CmdSmartRaw(const char *Cmd) { } // TLV decoder - if (decodeTLV && len > 4) { - TLVPrintFromBuffer(buf+1, len-2); - } + if (decodeTLV && len > 4) + TLVPrintFromBuffer(buf+1, len-3); + free(buf); } return 0; @@ -477,17 +495,22 @@ int CmdSmartBruteforceSFI(const char *Cmd) { char ctmp = tolower(param_getchar(Cmd, 0)); if (ctmp == 'h') return usage_sm_brute(); - + + uint8_t data[5] = {0x00, 0xB2, 0x00, 0x00, 0x00}; - PrintAndLogEx(INFO, "Selecting"); + PrintAndLogEx(INFO, "Selecting card"); + if ( !smart_select(false) ) { + return 1; + } + + PrintAndLogEx(INFO, "Selecting PPSE aid"); CmdSmartRaw("d 00a404000e325041592e5359532e444446303100"); CmdSmartRaw("d 00a4040007a000000004101000"); PrintAndLogEx(INFO, "starting"); - UsbCommand c = {CMD_SMART_RAW, {SC_RAW, sizeof(data), 0}}; - + UsbCommand c = {CMD_SMART_RAW, {SC_RAW, sizeof(data), 0}}; uint8_t* buf = malloc(USB_CMD_DATA_SIZE); if ( !buf ) return 1; @@ -511,8 +534,12 @@ int CmdSmartBruteforceSFI(const char *Cmd) { memcpy(c.d.asBytes, data, sizeof(data) ); clearCommandBuffer(); SendCommand(&c); - smart_response(buf); + uint8_t len = smart_response(buf); + // TLV decoder + if (len > 4) + TLVPrintFromBuffer(buf+1, len-3); + data[4] = 0; } memset(buf, 0x00, USB_CMD_DATA_SIZE); diff --git a/common/i2c.c b/common/i2c.c index 262fd832a..794564de3 100644 --- a/common/i2c.c +++ b/common/i2c.c @@ -34,38 +34,29 @@ volatile unsigned long c; void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) { for (c = delay * 2; c; c--) {}; } - -// ͨѶӳٺ ommunication delay function + #define I2C_DELAY_1CLK I2CSpinDelayClk(1) #define I2C_DELAY_2CLK I2CSpinDelayClk(2) #define I2C_DELAY_XCLK(x) I2CSpinDelayClk((x)) - #define ISO7618_MAX_FRAME 255 void I2C_init(void) { - // øλţرĬϸ // Configure reset pin, close up pull up, push-pull output, default high AT91C_BASE_PIOA->PIO_PPUDR = GPIO_RST; AT91C_BASE_PIOA->PIO_MDDR = GPIO_RST; - // I2C ţ© // Configure I2C pin, open up, open leakage AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_SCL | GPIO_SDA); // Open up the pull up AT91C_BASE_PIOA->PIO_MDER |= (GPIO_SCL | GPIO_SDA); - // Ĭȫ // default three lines all pull up AT91C_BASE_PIOA->PIO_SODR |= (GPIO_SCL | GPIO_SDA | GPIO_RST); - // - // allow output AT91C_BASE_PIOA->PIO_OER |= (GPIO_SCL | GPIO_SDA | GPIO_RST); AT91C_BASE_PIOA->PIO_PER |= (GPIO_SCL | GPIO_SDA | GPIO_RST); } - -// øλ״̬ // set the reset state void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) { if (LineRST) @@ -84,7 +75,6 @@ void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) { LOW(GPIO_SDA); } -// λ // Reset the SIM_Adapter, then enter the main program // Note: the SIM_Adapter will not enter the main program after power up. Please run this function before use SIM_Adapter. void I2C_Reset_EnterMainProgram(void) { @@ -96,9 +86,8 @@ void I2C_Reset_EnterMainProgram(void) { SpinDelay(10); } -// λģʽ // Reset the SIM_Adapter, then enter the bootloader program -// ReserveFor firmware update. +// Reserve for firmware update. void I2C_Reset_EnterBootloader(void) { I2C_SetResetStatus(0, 1, 1); SpinDelay(100); @@ -106,7 +95,6 @@ void I2C_Reset_EnterBootloader(void) { SpinDelay(10); } -// ȴʱӱ // Wait for the clock to go High. bool WaitSCL_H_delay(uint32_t delay) { while (delay--) { @@ -301,7 +289,6 @@ bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address) { return true; } -// д1ֽ дݣдַͣ // Sends 1 byte data (Data to be written, command to be written , SlaveDevice address ). bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address) { bool bBreak = true; @@ -332,8 +319,7 @@ bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address) { return true; } -// д1ݣдַд볤ȣдַͣ -//Sends a string of data (Array, length, command to be written , SlaveDevice address ). +//Sends array of data (Array, length, command to be written , SlaveDevice address ). // len = uint8 (max buffer to write 256bytes) bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) { bool bBreak = true; @@ -371,8 +357,7 @@ bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t dev return true; } -// 1ݣŶݣȣַͣ -// read 1 strings of data (Data array, Readout length, command to be written , SlaveDevice address ). +// read one array of data (Data array, Readout length, command to be written , SlaveDevice address ). // len = uint8 (max buffer to read 256bytes) int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) { @@ -460,12 +445,10 @@ int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t if (!I2C_WaitAck()) break; - // msb I2C_SendByte(msb); if (!I2C_WaitAck()) break; - // lsb I2C_SendByte(lsb); if (!I2C_WaitAck()) break; @@ -522,12 +505,10 @@ bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t d if (!I2C_WaitAck()) break; - // msb I2C_SendByte(msb); if (!I2C_WaitAck()) break; - // lsb I2C_SendByte(lsb); if (!I2C_WaitAck()) break; @@ -698,8 +679,12 @@ void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) { // read bytes from module len = ISO7618_MAX_FRAME; - sc_rx_bytes(resp, &len); - LogTrace(resp, len, 0, 0, NULL, false); + bool res = sc_rx_bytes(resp, &len); + if ( res ) { + LogTrace(resp, len, 0, 0, NULL, false); + } else { + len = 0; + } } OUT: cmd_send(CMD_ACK, len, 0, 0, resp, len); From 7d09a466fb67d3115d790dc7b406a2a093bdb96c Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 6 Oct 2018 13:29:20 +0200 Subject: [PATCH 0073/1938] FIX: OSX disable app-nap during serial comm (@anticat) https://github.com/Proxmark/proxmark3/pull/687 --- CHANGELOG.md | 1 + client/Makefile | 19 ++++++++++++++----- client/comms.c | 10 ++++++++++ client/comms.h | 1 + client/util_darwin.c | 40 ++++++++++++++++++++++++++++++++++++++++ client/util_darwin.h | 17 +++++++++++++++++ 6 files changed, 83 insertions(+), 5 deletions(-) create mode 100644 client/util_darwin.c create mode 100644 client/util_darwin.h diff --git a/CHANGELOG.md b/CHANGELOG.md index b0e2cdec9..e2648fedb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Implemented AppNap API, fixing #283 and #627 OSX USB comm issues (AntiCat) - Added 'sc brute' - a naive SFI bruteforcer for contact smartcards (RDV40) (@iceman) - Change 'lf t55xx detectconfig' - now optional to persist settings to flashmem (RDV40) (@iceman) - Change 'hf mf csave' - now saves both EML/BIN formats (@iceman) diff --git a/client/Makefile b/client/Makefile index a1d06eb76..31c9c6a2d 100644 --- a/client/Makefile +++ b/client/Makefile @@ -34,9 +34,11 @@ LUAPLATFORM = generic platform = $(shell uname) ifneq (,$(findstring MINGW,$(platform))) LUAPLATFORM = mingw - else +else ifeq ($(platform),Darwin) LUAPLATFORM = macosx + OBJCSRCS = util_darwin.m + LDFLAGS += -framework Foundation else LUALIB += -ldl LDLIBS += -ltermcap -lncurses @@ -223,6 +225,7 @@ QTGUISRCS = proxgui.cpp proxguiqt.cpp proxguiqt.moc.cpp guidummy.cpp COREOBJS = $(CORESRCS:%.c=$(OBJDIR)/%.o) CMDOBJS = $(CMDSRCS:%.c=$(OBJDIR)/%.o) +OBJCOBJS = $(OBJCSRCS:%.m=$(OBJDIR)/%.o) ZLIBOBJS = $(ZLIBSRCS:%.c=$(OBJDIR)/%.o) MULTIARCHOBJS = $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_NOSIMD.o) \ $(MULTIARCHSRCS:%.c=$(OBJDIR)/%_MMX.o) \ @@ -249,7 +252,7 @@ endif BINS = proxmark3 flasher fpga_compress WINBINS = $(patsubst %, %.exe, $(BINS)) -CLEAN = $(BINS) $(WINBINS) $(COREOBJS) $(CMDOBJS) $(ZLIBOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(OBJDIR)/*.o *.moc.cpp ui/ui_overlays.h lualibs/usb_cmd.lua lualibs/mf_default_keys.lua +CLEAN = $(BINS) $(WINBINS) $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(ZLIBOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(OBJDIR)/*.o *.moc.cpp ui/ui_overlays.h lualibs/usb_cmd.lua lualibs/mf_default_keys.lua # need to assign dependancies to build these first... all: lua_build $(BINS) @@ -258,10 +261,10 @@ all-static: LDLIBS:=-static $(LDLIBS) all-static: proxmark3 flasher fpga_compress proxmark3: LDLIBS+=$(LUALIB) $(QTLDLIBS) -proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) lualibs/usb_cmd.lua lualibs/mf_default_keys.lua - $(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) $(LDLIBS) -o $@ +proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) lualibs/usb_cmd.lua lualibs/mf_default_keys.lua + $(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) $(LDLIBS) -o $@ -flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(COREOBJS) +flasher: $(OBJDIR)/flash.o $(OBJDIR)/flasher.o $(COREOBJS) $(OBJCOBJS) $(LD) $(LDFLAGS) $^ $(LDLIBS) -o $@ fpga_compress: $(OBJDIR)/fpga_compress.o $(ZLIBOBJS) @@ -325,6 +328,11 @@ $(OBJDIR)/%.o : %.cpp $(OBJDIR)/%.d $(CXX) $(DEPFLAGS) $(CXXFLAGS) $(QTINCLUDES) -c -o $@ $< $(POSTCOMPILE) +%.o: %.m +$(OBJDIR)/%.o : %.m $(OBJDIR)/%.d + $(CC) $(DEPFLAGS) $(CFLAGS) -c -o $@ $< + $(POSTCOMPILE) + #$(CMDOBJS) $(COREOBJS): $(notdir $(%.c)) %.d # $(CC) $(DEPFLAGS) $(CFLAGS) -c -o $@ $< # $(POSTCOMPILE) @@ -339,6 +347,7 @@ $(OBJDIR)/%.o : %.cpp $(OBJDIR)/%.d DEPENDENCY_FILES = $(patsubst %.c, $(OBJDIR)/%.d, $(CORESRCS) $(CMDSRCS) $(ZLIBSRCS) $(MULTIARCHSRCS)) \ $(patsubst %.cpp, $(OBJDIR)/%.d, $(QTGUISRCS)) \ + $(patsubst %.m, $(OBJDIR)/%.d, $(OBJCSRCS)) \ $(OBJDIR)/proxmark3.d $(OBJDIR)/flash.d $(OBJDIR)/flasher.d $(OBJDIR)/fpga_compress.d $(DEPENDENCY_FILES): ; diff --git a/client/comms.c b/client/comms.c index 21d9ad4a7..e297e9057 100644 --- a/client/comms.c +++ b/client/comms.c @@ -242,6 +242,11 @@ __attribute__((force_align_arg_pointer)) UsbCommand *prx = ℞ //int counter_to_offline = 0; + +#if defined(__MACH__) && defined(__APPLE__) + disableAppNap("Proxmark3 polling UART"); +#endif + while (conn->run) { rxlen = 0; @@ -288,6 +293,11 @@ __attribute__((force_align_arg_pointer)) // when this reader thread dies, we close the serial port. uart_close(sp); sp = NULL; + +#if defined(__MACH__) && defined(__APPLE__) + enableAppNap(); +#endif + pthread_exit(NULL); return NULL; diff --git a/client/comms.h b/client/comms.h index eba0d45d5..e311f5e0c 100644 --- a/client/comms.h +++ b/client/comms.h @@ -21,6 +21,7 @@ #include "common.h" #include "util_posix.h" #include "util.h" +#include "util_darwin.h" #if defined(__linux__) && !defined(NO_UNLINK) #include // for unlink() diff --git a/client/util_darwin.c b/client/util_darwin.c new file mode 100644 index 000000000..d07ebebc4 --- /dev/null +++ b/client/util_darwin.c @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// (c) 2018 AntiCat +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// macOS framework bindings +//----------------------------------------------------------------------------- + +#import "util_darwin.h" + +#import +#import + +static id activity = nil; + +//OS X Version 10.10 is defined in OS X 10.10 and later +#if defined(MAC_OS_X_VERSION_10_10) +void disableAppNap(const char* reason) { + if(activity == nil) { + //NSLog(@"disableAppNap: %@", @(reason)); + activity = [[NSProcessInfo processInfo] beginActivityWithOptions:NSActivityBackground reason:@(reason)]; + [activity retain]; + } +} + +void enableAppNap() { + if(activity != nil) { + //NSLog(@"enableAppNap"); + [[NSProcessInfo processInfo] endActivity:activity]; + [activity release]; + activity = nil; + } +} + +#else +void disableAppNap(const char* reason) { } +void enableAppNap() { } +#endif diff --git a/client/util_darwin.h b/client/util_darwin.h new file mode 100644 index 000000000..923a4dfc0 --- /dev/null +++ b/client/util_darwin.h @@ -0,0 +1,17 @@ +//----------------------------------------------------------------------------- +// (c) 2018 AntiCat +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// macOS framework bindings +//----------------------------------------------------------------------------- + +#ifndef UTIL_DARWIN_H__ +#define UTIL_DARWIN_H__ + +void disableAppNap(const char* reason); +void enableAppNap(); + +#endif \ No newline at end of file From 2a24f97355c8f7ee417e1369015c6ac0a7fd2717 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 6 Oct 2018 14:52:50 +0200 Subject: [PATCH 0074/1938] chg: using three spaces instead of tabs for intendention --- client/emv/dump.c | 2 +- client/emv/emv_tags.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/emv/dump.c b/client/emv/dump.c index a699b188d..47de7c3c2 100644 --- a/client/emv/dump.c +++ b/client/emv/dump.c @@ -20,7 +20,7 @@ #include "dump.h" -#define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, "\t");} +#define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, " ");} void dump_buffer_simple(const unsigned char *ptr, size_t len, FILE *f) { diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index a29b15048..fdccb8923 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -23,7 +23,7 @@ #include #include -#define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, "\t");} +#define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, " ");} enum emv_tag_t { EMV_TAG_GENERIC, From 61d7f74ab9b5ba1520717003d64e746324cb453a Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 6 Oct 2018 14:53:21 +0200 Subject: [PATCH 0075/1938] chg: code clean up --- client/emv/cmdemv.c | 18 ++---------------- 1 file changed, 2 insertions(+), 16 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index abe4c4727..5ff31770d 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -215,24 +215,19 @@ int CmdHFEMVPPSE(const char *cmd) { while(param_getchar(cmd, cmdp) != 0x00) { char c = param_getchar(cmd, cmdp); if ((c == '-') && (param_getlength(cmd, cmdp) == 2)) - switch (param_getchar_indx(cmd, 1, cmdp)) { + switch (tolower(param_getchar_indx(cmd, 1, cmdp))) { case 'h': - case 'H': return usage_emv_ppse(); case 's': - case 'S': activateField = true; break; case 'k': - case 'K': leaveSignalON = true; break; case 'a': - case 'A': SetAPDULogging(true); break; case 't': - case 'T': decodeTLV = true; break; case '1': @@ -316,40 +311,31 @@ int CmdHFEMVExec(const char *cmd) { while(param_getchar(cmd, cmdp) != 0x00) { char c = param_getchar(cmd, cmdp); if ((c == '-') && (param_getlength(cmd, cmdp) == 2)) - switch (param_getchar_indx(cmd, 1, cmdp)) { + switch (tolower(param_getchar_indx(cmd, 1, cmdp))) { case 'h': - case 'H': return usage_emv_exec(); case 's': - case 'S': activateField = true; break; case 'a': - case 'A': showAPDU = true; break; case 't': - case 'T': decodeTLV = true; break; case 'f': - case 'F': forceSearch = true; break; case 'x': - case 'X': TrType = TT_VSDC; break; case 'v': - case 'V': TrType = TT_QVSDCMCHIP; break; case 'c': - case 'C': TrType = TT_CDA; break; case 'g': - case 'G': GenACGPO = true; break; default: From 1fb121474e89e321ba79718ac395899573a4bf62 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 7 Oct 2018 09:01:24 +0200 Subject: [PATCH 0076/1938] osx: fix annoying focus behaviour (@anticat) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit https://github.com/Proxmark/proxmark3/pull/689 OS X has a global menu bar and a per app dock icon. Therefore, all GUI applications launched from a terminal will become focused - even if they don’t show any windows. Thereby the terminal loses focus. Since is it very annoying to re-focus the terminal after each proxmark client launch, this change makes the client unfocusable during launch and restores the regular behaviour when a window is created. --- client/Makefile | 2 +- client/proxguiqt.cpp | 19 +++++++++++++++++-- client/util_darwin.h | 2 ++ client/{util_darwin.c => util_darwin.m} | 15 +++++++++++++++ 4 files changed, 35 insertions(+), 3 deletions(-) rename client/{util_darwin.c => util_darwin.m} (75%) diff --git a/client/Makefile b/client/Makefile index 31c9c6a2d..4d0312e80 100644 --- a/client/Makefile +++ b/client/Makefile @@ -38,7 +38,7 @@ else ifeq ($(platform),Darwin) LUAPLATFORM = macosx OBJCSRCS = util_darwin.m - LDFLAGS += -framework Foundation + LDFLAGS += -framework Foundation -framework AppKit else LUALIB += -ldl LDLIBS += -ltermcap -lncurses diff --git a/client/proxguiqt.cpp b/client/proxguiqt.cpp index 56de71b24..296862e65 100644 --- a/client/proxguiqt.cpp +++ b/client/proxguiqt.cpp @@ -27,6 +27,10 @@ #include "proxgui.h" #include +extern "C" { +#include "util_darwin.h" +} + bool g_useOverlays = false; int g_absVMax = 0; int startMax; @@ -53,9 +57,14 @@ void ProxGuiQT::_ShowGraphWindow(void) { if(!plotapp) return; - if (!plotwidget) + if (!plotwidget) { + +#if defined(__MACH__) && defined(__APPLE__) + makeFocusable(); +#endif + plotwidget = new ProxWidget(); - + } plotwidget->show(); } @@ -100,6 +109,12 @@ void ProxGuiQT::MainLoop() //start proxmark thread after starting event loop QTimer::singleShot(200, this, SLOT(_StartProxmarkThread())); +#if defined(__MACH__) && defined(__APPLE__) + //Prevent the terminal from loosing focus during launch by making the client unfocusable + makeUnfocusable(); +#endif + + plotapp->exec(); } diff --git a/client/util_darwin.h b/client/util_darwin.h index 923a4dfc0..c69a551d3 100644 --- a/client/util_darwin.h +++ b/client/util_darwin.h @@ -13,5 +13,7 @@ void disableAppNap(const char* reason); void enableAppNap(); +void makeUnfocusable(); +void makeFocusable(); #endif \ No newline at end of file diff --git a/client/util_darwin.c b/client/util_darwin.m similarity index 75% rename from client/util_darwin.c rename to client/util_darwin.m index d07ebebc4..9d7583903 100644 --- a/client/util_darwin.c +++ b/client/util_darwin.m @@ -12,6 +12,7 @@ #import #import +#import static id activity = nil; @@ -38,3 +39,17 @@ void enableAppNap() { void disableAppNap(const char* reason) { } void enableAppNap() { } #endif + + +//OS X Version 10.6 is defined in OS X 10.6 and later +#if defined(MAC_OS_X_VERSION_10_6) +void makeUnfocusable() { + [NSApp setActivationPolicy:NSApplicationActivationPolicyProhibited]; +} +void makeFocusable() { + [NSApp setActivationPolicy:NSApplicationActivationPolicyRegular]; +} +#else +void makeUnfocusable() { } +void makeFocusable() { } +#endif \ No newline at end of file From 642e5e906c5d5739804578c377d5288db49a5275 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 7 Oct 2018 09:04:59 +0200 Subject: [PATCH 0077/1938] textual --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e2648fedb..848fe6832 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,7 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] - - Implemented AppNap API, fixing #283 and #627 OSX USB comm issues (AntiCat) + - Fix 'annoying focus behaviour' on OSX (@Anticat) + - Implemented AppNap API, fixing #283 and #627 OSX USB comm issues (@AntiCat) - Added 'sc brute' - a naive SFI bruteforcer for contact smartcards (RDV40) (@iceman) - Change 'lf t55xx detectconfig' - now optional to persist settings to flashmem (RDV40) (@iceman) - Change 'hf mf csave' - now saves both EML/BIN formats (@iceman) From 769dee7e7a8d8baa6e82a502cc263bace87ff789 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 7 Oct 2018 12:17:21 +0200 Subject: [PATCH 0078/1938] Fix: ControlWidget placement https://github.com/iceman1001/proxmark3/pull/258 --- CHANGELOG.md | 1 + client/proxguiqt.cpp | 21 +++++++-------------- 2 files changed, 8 insertions(+), 14 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 848fe6832..20f1c1f8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fix 'Lining up plot and control window' (@anticat) - Fix 'annoying focus behaviour' on OSX (@Anticat) - Implemented AppNap API, fixing #283 and #627 OSX USB comm issues (@AntiCat) - Added 'sc brute' - a naive SFI bruteforcer for contact smartcards (RDV40) (@iceman) diff --git a/client/proxguiqt.cpp b/client/proxguiqt.cpp index 296862e65..15f036b79 100644 --- a/client/proxguiqt.cpp +++ b/client/proxguiqt.cpp @@ -172,8 +172,7 @@ ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) { this->master = master; resize(800,500); - /** Setup the controller widget **/ - + // Setup the controller widget controlWidget = new QWidget(); opsController = new Ui::Form(); opsController->setupUi(controlWidget); @@ -195,23 +194,17 @@ ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) { QObject::connect(opsController->horizontalSlider_dirthr_down, SIGNAL(valueChanged(int)), this, SLOT(vchange_dthr_down(int))); QObject::connect(opsController->horizontalSlider_askedge, SIGNAL(valueChanged(int)), this, SLOT(vchange_askedge(int))); - controlWidget->show(); - // Set up the plot widget, which does the actual plotting - plot = new Plot(this); - /* - QSlider* slider = new QSlider(Qt::Horizontal); - slider->setFocusPolicy(Qt::StrongFocus); - slider->setTickPosition(QSlider::TicksBothSides); - slider->setTickInterval(10); - slider->setSingleStep(1); - */ QVBoxLayout *layout = new QVBoxLayout; - //layout->addWidget(slider); layout->addWidget(plot); setLayout(layout); - //printf("Proxwidget Constructor just set layout\r\n"); + show(); // places the window on the screen. + + // Move controller widget below plot + controlWidget->move(x(),y()+frameSize().height()); + controlWidget->resize(size().width(), controlWidget->size().height()); + controlWidget->show(); } // not 100% sure what i need in this block From 29982a6cdc77e7770a248e8626e71f44ef45b239 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 7 Oct 2018 12:32:14 +0200 Subject: [PATCH 0079/1938] CHG: 'make control widget smaller' --- client/proxguiqt.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/proxguiqt.cpp b/client/proxguiqt.cpp index 15f036b79..c8ccba197 100644 --- a/client/proxguiqt.cpp +++ b/client/proxguiqt.cpp @@ -170,7 +170,7 @@ void ProxWidget::vchange_dthr_down(int v) { } ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) { this->master = master; - resize(800,500); + resize(800, 400); // Setup the controller widget controlWidget = new QWidget(); @@ -203,7 +203,7 @@ ProxWidget::ProxWidget(QWidget *parent, ProxGuiQT *master) : QWidget(parent) { // Move controller widget below plot controlWidget->move(x(),y()+frameSize().height()); - controlWidget->resize(size().width(), controlWidget->size().height()); + controlWidget->resize(size().width(), 200); controlWidget->show(); } @@ -553,7 +553,7 @@ Plot::Plot(QWidget *parent) : QWidget(parent), GraphStart(0), GraphPixelsPerPoin { //Need to set this, otherwise we don't receive keypress events setFocusPolicy( Qt::StrongFocus); - resize(600, 300); + resize(400, 200); QPalette palette(QColor(0,0,0,0)); palette.setColor(QPalette::WindowText, QColor(255,255,255)); From 6e1f757047ace3dcabaf3f1a47f14ccf7134b27c Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 7 Oct 2018 16:17:25 +0200 Subject: [PATCH 0080/1938] fix: warning about %lu in gcc 8.2.0 --- client/fpga_compress.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/fpga_compress.c b/client/fpga_compress.c index 5020914ae..ee9003581 100644 --- a/client/fpga_compress.c +++ b/client/fpga_compress.c @@ -97,11 +97,11 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardn i = 0; do { - if (i >= num_infiles * (hardnested_mode?HARDNESTED_TABLE_SIZE:FPGA_CONFIG_SIZE)) { + if (i >= num_infiles * (hardnested_mode ? HARDNESTED_TABLE_SIZE : FPGA_CONFIG_SIZE)) { if (hardnested_mode) { - fprintf(stderr, "Input file too big (> %lu bytes). This is probably not a hardnested bitflip state table.\n", HARDNESTED_TABLE_SIZE); + fprintf(stderr, "Input file too big (> %llu bytes). This is probably not a hardnested bitflip state table.\n", HARDNESTED_TABLE_SIZE); } else { - fprintf(stderr, "Input files too big (total > %lu bytes). These are probably not PM3 FPGA config files.\n", num_infiles*FPGA_CONFIG_SIZE); + fprintf(stderr, "Input files too big (total > %llu bytes). These are probably not PM3 FPGA config files.\n", num_infiles * FPGA_CONFIG_SIZE); } for(uint16_t j = 0; j < num_infiles; j++) { fclose(infile[j]); From 3d312723404a4f7cb08f8c3b6080ddd089b90399 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 7 Oct 2018 16:19:45 +0200 Subject: [PATCH 0081/1938] fix gcc8.2.0 --- client/fpga_compress.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/fpga_compress.c b/client/fpga_compress.c index ee9003581..ce0f41982 100644 --- a/client/fpga_compress.c +++ b/client/fpga_compress.c @@ -101,7 +101,7 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardn if (hardnested_mode) { fprintf(stderr, "Input file too big (> %llu bytes). This is probably not a hardnested bitflip state table.\n", HARDNESTED_TABLE_SIZE); } else { - fprintf(stderr, "Input files too big (total > %llu bytes). These are probably not PM3 FPGA config files.\n", num_infiles * FPGA_CONFIG_SIZE); + fprintf(stderr, "Input files too big (total > %lu bytes). These are probably not PM3 FPGA config files.\n", num_infiles * FPGA_CONFIG_SIZE); } for(uint16_t j = 0; j < num_infiles; j++) { fclose(infile[j]); From ab5233d29f1f2a51fde43ac2cd14e0212575028e Mon Sep 17 00:00:00 2001 From: merlokk Date: Thu, 11 Oct 2018 11:48:46 +0300 Subject: [PATCH 0082/1938] now it needs to resolve issues in reveng --- client/Makefile | 3 +- client/cliparser/README.md | 13 + client/cliparser/argtable3.c | 5004 ++++++++++++++++++++++++++++++++++ client/cliparser/argtable3.h | 305 +++ client/cliparser/cliparser.c | 188 ++ client/cliparser/cliparser.h | 37 + client/cmdhf14a.c | 89 + client/cmdhf14a.h | 1 + client/cmdhfmf.c | 144 + client/cmdhfmf.h | 2 + client/obj/cliparser/.dummy | 0 client/reveng/cli.c | 2 +- 12 files changed, 5786 insertions(+), 2 deletions(-) create mode 100644 client/cliparser/README.md create mode 100644 client/cliparser/argtable3.c create mode 100644 client/cliparser/argtable3.h create mode 100644 client/cliparser/cliparser.c create mode 100644 client/cliparser/cliparser.h create mode 100644 client/obj/cliparser/.dummy diff --git a/client/Makefile b/client/Makefile index 4d0312e80..eaf846610 100644 --- a/client/Makefile +++ b/client/Makefile @@ -110,6 +110,8 @@ CMDSRCS = crapto1/crapto1.c \ polarssl/sha1.c \ polarssl/sha256.c \ polarssl/base64.c \ + cliparser/argtable3.c\ + cliparser/cliparser.c\ loclass/cipher.c \ loclass/cipherutils.c \ loclass/ikeys.c \ @@ -203,7 +205,6 @@ CMDSRCS = crapto1/crapto1.c \ reveng/bmpbit.c \ reveng/model.c \ reveng/poly.c \ - reveng/getopt.c \ bucketsort.c cpu_arch = $(shell uname -m) diff --git a/client/cliparser/README.md b/client/cliparser/README.md new file mode 100644 index 000000000..2b321946f --- /dev/null +++ b/client/cliparser/README.md @@ -0,0 +1,13 @@ +# Command line parser + +cliparser - librari for proxmark with command line parsing high level functions. + +## External libraries: + +### argtable + +Argtable3 is a single-file, ANSI C, command-line parsing library that parses GNU-style command-line options. + +You can download argtable3 from this repository https://github.com/argtable/argtable3 + +[argtable3 license](https://github.com/argtable/argtable3/blob/master/LICENSE) diff --git a/client/cliparser/argtable3.c b/client/cliparser/argtable3.c new file mode 100644 index 000000000..38ce7a24f --- /dev/null +++ b/client/cliparser/argtable3.c @@ -0,0 +1,5004 @@ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include "argtable3.h" + +// On Windows isspace crashes app in case of using Unicode character set and string to be above ASCII +// so you have to use _istspace instead of space +#ifdef UNICODE +#include + #define ISSPACE _istspace +#else + #define ISSPACE isspace +#endif + +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 2013 Tom G. Huang + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#ifndef ARG_UTILS_H +#define ARG_UTILS_H + +#define ARG_ENABLE_TRACE 0 +#define ARG_ENABLE_LOG 1 + +#ifdef __cplusplus +extern "C" { +#endif + +enum +{ + EMINCOUNT = 1, + EMAXCOUNT, + EBADINT, + // The same name define EOVERFLOW in errno.h on windows platform +#ifdef __STDC_WANT_SECURE_LIB__ + EOVERFLOW_, +#else + EOVERFLOW, +#endif + EBADDOUBLE, + EBADDATE, + EREGNOMATCH +}; + + +#if defined(_MSC_VER) +#define ARG_TRACE(x) \ + __pragma(warning(push)) \ + __pragma(warning(disable:4127)) \ + do { if (ARG_ENABLE_TRACE) dbg_printf x; } while (0) \ + __pragma(warning(pop)) + +#define ARG_LOG(x) \ + __pragma(warning(push)) \ + __pragma(warning(disable:4127)) \ + do { if (ARG_ENABLE_LOG) dbg_printf x; } while (0) \ + __pragma(warning(pop)) +#else +#define ARG_TRACE(x) \ + do { if (ARG_ENABLE_TRACE) dbg_printf x; } while (0) + +#define ARG_LOG(x) \ + do { if (ARG_ENABLE_LOG) dbg_printf x; } while (0) +#endif + +extern void dbg_printf(const char *fmt, ...); + +#ifdef __cplusplus +} +#endif + +#endif + +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include +#include + + +void dbg_printf(const char *fmt, ...) +{ + va_list args; + va_start(args, fmt); + vfprintf(stderr, fmt, args); + va_end(args); +} + +/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ +/* $FreeBSD$ */ + +/*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _GETOPT_H_ +#define _GETOPT_H_ + +#include + +/* + * GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension. + * getopt() is declared here too for GNU programs. + */ +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +struct option { + /* name of long option */ + const char *name; + /* + * one of no_argument, required_argument, and optional_argument: + * whether option takes an argument + */ + int has_arg; + /* if not NULL, set *flag to val when option found */ + int *flag; + /* if flag not NULL, value to set *flag to; else return value */ + int val; +}; + +__BEGIN_DECLS +int getopt_long(int, char * const *, const char *, + const struct option *, int *); +int getopt_long_only(int, char * const *, const char *, + const struct option *, int *); +#ifndef _GETOPT_DECLARED +#define _GETOPT_DECLARED +int getopt(int, char * const [], const char *); + +extern char *optarg; /* getopt(3) external variables */ +extern int optind, opterr, optopt; +#endif +#ifndef _OPTRESET_DECLARED +#define _OPTRESET_DECLARED +extern int optreset; /* getopt(3) external variable */ +#endif +__END_DECLS + +#endif /* !_GETOPT_H_ */ +/* $Id: getopt_long.c,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $ */ +/* $OpenBSD: getopt_long.c,v 1.23 2007/10/31 12:34:57 chl Exp $ */ +/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ + +/* + * Copyright (c) 2002 Todd C. Miller + * + * Permission to use, copy, modify, and distribute this software for any + * purpose with or without fee is hereby granted, provided that the above + * copyright notice and this permission notice appear in all copies. + * + * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES + * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF + * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR + * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES + * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN + * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF + * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Sponsored in part by the Defense Advanced Research Projects + * Agency (DARPA) and Air Force Research Laboratory, Air Force + * Materiel Command, USAF, under agreement number F39502-99-1-0512. + */ + +// $Id: getopt_long.c,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $" + +/*- + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#if 0 +#include +#endif +#include +#include +#include + + +#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ + +#ifdef REPLACE_GETOPT +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ +#endif + +#define PRINT_ERROR ((opterr) && (*options != ':')) + +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ + +/* return values */ +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 + +#define EMSG "" + +static int getopt_internal(int, char * const *, const char *, + const struct option *, int *, int); +static int parse_long_options(char * const *, const char *, + const struct option *, int *, int); +static int gcd(int, int); +static void permute_args(int, int, int, char * const *); + +static char *place = EMSG; /* option letter processing */ + +/* XXX: set optreset to 1 rather than these two */ +static int nonopt_start = -1; /* first non option argument (for permute) */ +static int nonopt_end = -1; /* first option after non options (for permute) */ + +/* Error messages */ +static const char recargchar[] = "option requires an argument -- %c"; +static const char recargstring[] = "option requires an argument -- %s"; +static const char ambig[] = "ambiguous option -- %.*s"; +static const char noarg[] = "option doesn't take an argument -- %.*s"; +static const char illoptchar[] = "unknown option -- %c"; +static const char illoptstring[] = "unknown option -- %s"; + + + +#ifdef _WIN32 + +/* Windows needs warnx(). We change the definition though: + * 1. (another) global is defined, opterrmsg, which holds the error message + * 2. errors are always printed out on stderr w/o the program name + * Note that opterrmsg always gets set no matter what opterr is set to. The + * error message will not be printed if opterr is 0 as usual. + */ + +#include +#include + +#define MAX_OPTER_MSG_SIZE 128 + +extern char opterrmsg[MAX_OPTER_MSG_SIZE]; +char opterrmsg[MAX_OPTER_MSG_SIZE]; /* buffer for the last error message */ + +static void warnx(const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + /* + Make sure opterrmsg is always zero-terminated despite the _vsnprintf() + implementation specifics and manually suppress the warning. + */ + memset(opterrmsg, 0, sizeof opterrmsg); + if (fmt != NULL) +#ifdef __STDC_WANT_SECURE_LIB__ + _vsnprintf_s(opterrmsg, MAX_OPTER_MSG_SIZE, sizeof(opterrmsg) - 1, fmt, ap); +#else + _vsnprintf(opterrmsg, sizeof(opterrmsg) - 1, fmt, ap); +#endif + va_end(ap); + + fprintf(stderr, "%s\n", opterrmsg); +} + +#else +#include +#endif /*_WIN32*/ + + +/* + * Compute the greatest common divisor of a and b. + */ +static int +gcd(int a, int b) +{ + int c; + + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } + + return (b); +} + +/* + * Exchange the block from nonopt_start to nonopt_end with the block + * from nonopt_end to opt_end (keeping the same order of arguments + * in each block). + */ +static void +permute_args(int panonopt_start, int panonopt_end, int opt_end, + char * const *nargv) +{ + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; + + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; + + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end+i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **) nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; + } + } +} + +/* + * parse_long_options -- + * Parse long options in argc/argv argument vector. + * Returns -1 if short_too is set and the option does not match long_options. + */ +static int +parse_long_options(char * const *nargv, const char *options, + const struct option *long_options, int *idx, int short_too) +{ + char *current_argv, *has_equal; + size_t current_argv_len; + int i, match; + + current_argv = place; + match = -1; + + optind++; + + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); + + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; + + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + break; + } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; + + if (match == -1) /* partial match */ + match = i; + else { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, + current_argv); + optopt = 0; + return (BADCH); + } + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return (BADARG); + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return (BADARG); + } + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); + } + if (PRINT_ERROR) + warnx(illoptstring, current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } else + return (long_options[match].val); +} + +/* + * getopt_internal -- + * Parse argc/argv argument vector. Called by user level routines. + */ +static int +getopt_internal(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx, int flags) +{ + char *oli; /* option letter list index */ + int optchar, short_too; + static int posixly_correct = -1; +#ifdef __STDC_WANT_SECURE_LIB__ + char* buffer = NULL; + size_t buffer_size = 0; + errno_t err = 0; +#endif + + if (options == NULL) + return (-1); + + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + */ + +#ifdef __STDC_WANT_SECURE_LIB__ + if (posixly_correct == -1) { + err = _dupenv_s(&buffer, &buffer_size, "POSIXLY_CORRECT") == 0; + posixly_correct = buffer != NULL; + if(buffer != NULL && err == 0) { + free(buffer); + } + } +#else + if (posixly_correct == -1) + posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); +#endif + if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + else if (*options == '-') + flags |= FLAG_ALLARGS; + if (*options == '+' || *options == '-') + options++; + + /* + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. + */ + if (optind == 0) + optind = optreset = 1; + + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; +start: + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + if (*(place = nargv[optind]) != '-' || + (place[1] == '\0' && strchr(options, '-') == NULL)) { + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return (INORDER); + } + if (!(flags & FLAG_PERMUTE)) { + /* + * If no permutation wanted, stop parsing + * at first non-option. + */ + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; + + /* + * If we have "-" do nothing, if "--" we are done. + */ + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } + + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; + if (*place == '-') + place++; /* --foo long option */ + else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ + + optchar = parse_long_options(nargv, options, long_options, + idx, short_too); + if (optchar != -1) { + place = EMSG; + return (optchar); + } + } + + if ((optchar = (int)*place++) == (int)':' || + (optchar == (int)'-' && *place != '\0') || + (oli = strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; + if (PRINT_ERROR) + warnx(illoptchar, optchar); + optopt = optchar; + return (BADCH); + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else /* white space */ + place = nargv[optind]; + optchar = parse_long_options(nargv, options, long_options, + idx, 0); + place = EMSG; + return (optchar); + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = place; + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); +} + +#ifdef REPLACE_GETOPT +/* + * getopt -- + * Parse argc/argv argument vector. + * + * [eventually this will replace the BSD getopt] + */ +int +getopt(int nargc, char * const *nargv, const char *options) +{ + + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); +} +#endif /* REPLACE_GETOPT */ + +/* + * getopt_long -- + * Parse argc/argv argument vector. + */ +int +getopt_long(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE)); +} + +/* + * getopt_long_only -- + * Parse argc/argv argument vector. + */ +int +getopt_long_only(int nargc, char * const *nargv, const char *options, + const struct option *long_options, int *idx) +{ + + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE|FLAG_LONGONLY)); +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include +#include + +#include "argtable3.h" + + +char * arg_strptime(const char *buf, const char *fmt, struct tm *tm); + + +static void arg_date_resetfn(struct arg_date *parent) +{ + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + + +static int arg_date_scanfn(struct arg_date *parent, const char *argval) +{ + int errorcode = 0; + + if (parent->count == parent->hdr.maxcount) + { + errorcode = EMAXCOUNT; + } + else if (!argval) + { + /* no argument value was given, leave parent->tmval[] unaltered but still count it */ + parent->count++; + } + else + { + const char *pend; + struct tm tm = parent->tmval[parent->count]; + + /* parse the given argument value, store result in parent->tmval[] */ + pend = arg_strptime(argval, parent->format, &tm); + if (pend && pend[0] == '\0') + parent->tmval[parent->count++] = tm; + else + errorcode = EBADDATE; + } + + ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static int arg_date_checkfn(struct arg_date *parent) +{ + int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; + + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static void arg_date_errorfn( + struct arg_date *parent, + FILE *fp, + int errorcode, + const char *argval, + const char *progname) +{ + const char *shortopts = parent->hdr.shortopts; + const char *longopts = parent->hdr.longopts; + const char *datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + fprintf(fp, "%s: ", progname); + switch(errorcode) + { + case EMINCOUNT: + fputs("missing option ", fp); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + + case EMAXCOUNT: + fputs("excess option ", fp); + arg_print_option(fp, shortopts, longopts, argval, "\n"); + break; + + case EBADDATE: + { + struct tm tm; + char buff[200]; + + fprintf(fp, "illegal timestamp format \"%s\"\n", argval); + memset(&tm, 0, sizeof(tm)); + arg_strptime("1999-12-31 23:59:59", "%F %H:%M:%S", &tm); + strftime(buff, sizeof(buff), parent->format, &tm); + printf("correct format is \"%s\"\n", buff); + break; + } + } +} + + +struct arg_date * arg_date0( + const char * shortopts, + const char * longopts, + const char * format, + const char *datatype, + const char *glossary) +{ + return arg_daten(shortopts, longopts, format, datatype, 0, 1, glossary); +} + + +struct arg_date * arg_date1( + const char * shortopts, + const char * longopts, + const char * format, + const char *datatype, + const char *glossary) +{ + return arg_daten(shortopts, longopts, format, datatype, 1, 1, glossary); +} + + +struct arg_date * arg_daten( + const char * shortopts, + const char * longopts, + const char * format, + const char *datatype, + int mincount, + int maxcount, + const char *glossary) +{ + size_t nbytes; + struct arg_date *result; + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + /* default time format is the national date format for the locale */ + if (!format) + format = "%x"; + + nbytes = sizeof(struct arg_date) /* storage for struct arg_date */ + + maxcount * sizeof(struct tm); /* storage for tmval[maxcount] array */ + + /* allocate storage for the arg_date struct + tmval[] array. */ + /* we use calloc because we want the tmval[] array zero filled. */ + result = (struct arg_date *)calloc(1, nbytes); + if (result) + { + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = datatype ? datatype : format; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn *)arg_date_resetfn; + result->hdr.scanfn = (arg_scanfn *)arg_date_scanfn; + result->hdr.checkfn = (arg_checkfn *)arg_date_checkfn; + result->hdr.errorfn = (arg_errorfn *)arg_date_errorfn; + + /* store the tmval[maxcount] array immediately after the arg_date struct */ + result->tmval = (struct tm *)(result + 1); + + /* init the remaining arg_date member variables */ + result->count = 0; + result->format = format; + } + + ARG_TRACE(("arg_daten() returns %p\n", result)); + return result; +} + + +/*- + * Copyright (c) 1997, 1998, 2005, 2008 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code was contributed to The NetBSD Foundation by Klaus Klein. + * Heavily optimised by David Laight + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include + +/* + * We do not implement alternate representations. However, we always + * check whether a given modifier is allowed for a certain conversion. + */ +#define ALT_E 0x01 +#define ALT_O 0x02 +#define LEGAL_ALT(x) { if (alt_format & ~(x)) return (0); } +#define TM_YEAR_BASE (1900) + +static int conv_num(const char * *, int *, int, int); + +static const char *day[7] = { + "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", + "Friday", "Saturday" +}; + +static const char *abday[7] = { + "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" +}; + +static const char *mon[12] = { + "January", "February", "March", "April", "May", "June", "July", + "August", "September", "October", "November", "December" +}; + +static const char *abmon[12] = { + "Jan", "Feb", "Mar", "Apr", "May", "Jun", + "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" +}; + +static const char *am_pm[2] = { + "AM", "PM" +}; + + +static int arg_strcasecmp(const char *s1, const char *s2) +{ + const unsigned char *us1 = (const unsigned char *)s1; + const unsigned char *us2 = (const unsigned char *)s2; + while (tolower(*us1) == tolower(*us2++)) + if (*us1++ == '\0') + return 0; + + return tolower(*us1) - tolower(*--us2); +} + + +static int arg_strncasecmp(const char *s1, const char *s2, size_t n) +{ + if (n != 0) + { + const unsigned char *us1 = (const unsigned char *)s1; + const unsigned char *us2 = (const unsigned char *)s2; + do + { + if (tolower(*us1) != tolower(*us2++)) + return tolower(*us1) - tolower(*--us2); + + if (*us1++ == '\0') + break; + } while (--n != 0); + } + + return 0; +} + + +char * arg_strptime(const char *buf, const char *fmt, struct tm *tm) +{ + char c; + const char *bp; + size_t len = 0; + int alt_format, i, split_year = 0; + + bp = buf; + + while ((c = *fmt) != '\0') { + /* Clear `alternate' modifier prior to new conversion. */ + alt_format = 0; + + /* Eat up white-space. */ + if (ISSPACE(c)) { + while (ISSPACE(*bp)) + bp++; + + fmt++; + continue; + } + + if ((c = *fmt++) != '%') + goto literal; + + +again: + switch (c = *fmt++) + { + case '%': /* "%%" is converted to "%". */ +literal: + if (c != *bp++) + return (0); + break; + + /* + * "Alternative" modifiers. Just set the appropriate flag + * and start over again. + */ + case 'E': /* "%E?" alternative conversion modifier. */ + LEGAL_ALT(0); + alt_format |= ALT_E; + goto again; + + case 'O': /* "%O?" alternative conversion modifier. */ + LEGAL_ALT(0); + alt_format |= ALT_O; + goto again; + + /* + * "Complex" conversion rules, implemented through recursion. + */ + case 'c': /* Date and time, using the locale's format. */ + LEGAL_ALT(ALT_E); + bp = arg_strptime(bp, "%x %X", tm); + if (!bp) + return (0); + break; + + case 'D': /* The date as "%m/%d/%y". */ + LEGAL_ALT(0); + bp = arg_strptime(bp, "%m/%d/%y", tm); + if (!bp) + return (0); + break; + + case 'R': /* The time as "%H:%M". */ + LEGAL_ALT(0); + bp = arg_strptime(bp, "%H:%M", tm); + if (!bp) + return (0); + break; + + case 'r': /* The time in 12-hour clock representation. */ + LEGAL_ALT(0); + bp = arg_strptime(bp, "%I:%M:%S %p", tm); + if (!bp) + return (0); + break; + + case 'T': /* The time as "%H:%M:%S". */ + LEGAL_ALT(0); + bp = arg_strptime(bp, "%H:%M:%S", tm); + if (!bp) + return (0); + break; + + case 'X': /* The time, using the locale's format. */ + LEGAL_ALT(ALT_E); + bp = arg_strptime(bp, "%H:%M:%S", tm); + if (!bp) + return (0); + break; + + case 'x': /* The date, using the locale's format. */ + LEGAL_ALT(ALT_E); + bp = arg_strptime(bp, "%m/%d/%y", tm); + if (!bp) + return (0); + break; + + /* + * "Elementary" conversion rules. + */ + case 'A': /* The day of week, using the locale's form. */ + case 'a': + LEGAL_ALT(0); + for (i = 0; i < 7; i++) { + /* Full name. */ + len = strlen(day[i]); + if (arg_strncasecmp(day[i], bp, len) == 0) + break; + + /* Abbreviated name. */ + len = strlen(abday[i]); + if (arg_strncasecmp(abday[i], bp, len) == 0) + break; + } + + /* Nothing matched. */ + if (i == 7) + return (0); + + tm->tm_wday = i; + bp += len; + break; + + case 'B': /* The month, using the locale's form. */ + case 'b': + case 'h': + LEGAL_ALT(0); + for (i = 0; i < 12; i++) { + /* Full name. */ + len = strlen(mon[i]); + if (arg_strncasecmp(mon[i], bp, len) == 0) + break; + + /* Abbreviated name. */ + len = strlen(abmon[i]); + if (arg_strncasecmp(abmon[i], bp, len) == 0) + break; + } + + /* Nothing matched. */ + if (i == 12) + return (0); + + tm->tm_mon = i; + bp += len; + break; + + case 'C': /* The century number. */ + LEGAL_ALT(ALT_E); + if (!(conv_num(&bp, &i, 0, 99))) + return (0); + + if (split_year) { + tm->tm_year = (tm->tm_year % 100) + (i * 100); + } else { + tm->tm_year = i * 100; + split_year = 1; + } + break; + + case 'd': /* The day of month. */ + case 'e': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_mday, 1, 31))) + return (0); + break; + + case 'k': /* The hour (24-hour clock representation). */ + LEGAL_ALT(0); + /* FALLTHROUGH */ + case 'H': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_hour, 0, 23))) + return (0); + break; + + case 'l': /* The hour (12-hour clock representation). */ + LEGAL_ALT(0); + /* FALLTHROUGH */ + case 'I': + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_hour, 1, 12))) + return (0); + if (tm->tm_hour == 12) + tm->tm_hour = 0; + break; + + case 'j': /* The day of year. */ + LEGAL_ALT(0); + if (!(conv_num(&bp, &i, 1, 366))) + return (0); + tm->tm_yday = i - 1; + break; + + case 'M': /* The minute. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_min, 0, 59))) + return (0); + break; + + case 'm': /* The month. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &i, 1, 12))) + return (0); + tm->tm_mon = i - 1; + break; + + case 'p': /* The locale's equivalent of AM/PM. */ + LEGAL_ALT(0); + /* AM? */ + if (arg_strcasecmp(am_pm[0], bp) == 0) { + if (tm->tm_hour > 11) + return (0); + + bp += strlen(am_pm[0]); + break; + } + /* PM? */ + else if (arg_strcasecmp(am_pm[1], bp) == 0) { + if (tm->tm_hour > 11) + return (0); + + tm->tm_hour += 12; + bp += strlen(am_pm[1]); + break; + } + + /* Nothing matched. */ + return (0); + + case 'S': /* The seconds. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_sec, 0, 61))) + return (0); + break; + + case 'U': /* The week of year, beginning on sunday. */ + case 'W': /* The week of year, beginning on monday. */ + LEGAL_ALT(ALT_O); + /* + * XXX This is bogus, as we can not assume any valid + * information present in the tm structure at this + * point to calculate a real value, so just check the + * range for now. + */ + if (!(conv_num(&bp, &i, 0, 53))) + return (0); + break; + + case 'w': /* The day of week, beginning on sunday. */ + LEGAL_ALT(ALT_O); + if (!(conv_num(&bp, &tm->tm_wday, 0, 6))) + return (0); + break; + + case 'Y': /* The year. */ + LEGAL_ALT(ALT_E); + if (!(conv_num(&bp, &i, 0, 9999))) + return (0); + + tm->tm_year = i - TM_YEAR_BASE; + break; + + case 'y': /* The year within 100 years of the epoch. */ + LEGAL_ALT(ALT_E | ALT_O); + if (!(conv_num(&bp, &i, 0, 99))) + return (0); + + if (split_year) { + tm->tm_year = ((tm->tm_year / 100) * 100) + i; + break; + } + split_year = 1; + if (i <= 68) + tm->tm_year = i + 2000 - TM_YEAR_BASE; + else + tm->tm_year = i + 1900 - TM_YEAR_BASE; + break; + + /* + * Miscellaneous conversions. + */ + case 'n': /* Any kind of white-space. */ + case 't': + LEGAL_ALT(0); + while (ISSPACE(*bp)) + bp++; + break; + + + default: /* Unknown/unsupported conversion. */ + return (0); + } + + + } + + /* LINTED functional specification */ + return ((char *)bp); +} + + +static int conv_num(const char * *buf, int *dest, int llim, int ulim) +{ + int result = 0; + + /* The limit also determines the number of valid digits. */ + int rulim = ulim; + + if (**buf < '0' || **buf > '9') + return (0); + + do { + result *= 10; + result += *(*buf)++ - '0'; + rulim /= 10; + } while ((result * 10 <= ulim) && rulim && **buf >= '0' && **buf <= '9'); + + if (result < llim || result > ulim) + return (0); + + *dest = result; + return (1); +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include + +#include "argtable3.h" + + +static void arg_dbl_resetfn(struct arg_dbl *parent) +{ + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + + +static int arg_dbl_scanfn(struct arg_dbl *parent, const char *argval) +{ + int errorcode = 0; + + if (parent->count == parent->hdr.maxcount) + { + /* maximum number of arguments exceeded */ + errorcode = EMAXCOUNT; + } + else if (!argval) + { + /* a valid argument with no argument value was given. */ + /* This happens when an optional argument value was invoked. */ + /* leave parent argument value unaltered but still count the argument. */ + parent->count++; + } + else + { + double val; + char *end; + + /* extract double from argval into val */ + val = strtod(argval, &end); + + /* if success then store result in parent->dval[] array otherwise return error*/ + if (*end == 0) + parent->dval[parent->count++] = val; + else + errorcode = EBADDOUBLE; + } + + ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static int arg_dbl_checkfn(struct arg_dbl *parent) +{ + int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; + + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static void arg_dbl_errorfn( + struct arg_dbl *parent, + FILE *fp, + int errorcode, + const char *argval, + const char *progname) +{ + const char *shortopts = parent->hdr.shortopts; + const char *longopts = parent->hdr.longopts; + const char *datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + fprintf(fp, "%s: ", progname); + switch(errorcode) + { + case EMINCOUNT: + fputs("missing option ", fp); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + + case EMAXCOUNT: + fputs("excess option ", fp); + arg_print_option(fp, shortopts, longopts, argval, "\n"); + break; + + case EBADDOUBLE: + fprintf(fp, "invalid argument \"%s\" to option ", argval); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + } +} + + +struct arg_dbl * arg_dbl0( + const char * shortopts, + const char * longopts, + const char *datatype, + const char *glossary) +{ + return arg_dbln(shortopts, longopts, datatype, 0, 1, glossary); +} + + +struct arg_dbl * arg_dbl1( + const char * shortopts, + const char * longopts, + const char *datatype, + const char *glossary) +{ + return arg_dbln(shortopts, longopts, datatype, 1, 1, glossary); +} + + +struct arg_dbl * arg_dbln( + const char * shortopts, + const char * longopts, + const char *datatype, + int mincount, + int maxcount, + const char *glossary) +{ + size_t nbytes; + struct arg_dbl *result; + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + nbytes = sizeof(struct arg_dbl) /* storage for struct arg_dbl */ + + (maxcount + 1) * sizeof(double); /* storage for dval[maxcount] array plus one extra for padding to memory boundary */ + + result = (struct arg_dbl *)malloc(nbytes); + if (result) + { + size_t addr; + size_t rem; + + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = datatype ? datatype : ""; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn *)arg_dbl_resetfn; + result->hdr.scanfn = (arg_scanfn *)arg_dbl_scanfn; + result->hdr.checkfn = (arg_checkfn *)arg_dbl_checkfn; + result->hdr.errorfn = (arg_errorfn *)arg_dbl_errorfn; + + /* Store the dval[maxcount] array on the first double boundary that + * immediately follows the arg_dbl struct. We do the memory alignment + * purely for SPARC and Motorola systems. They require floats and + * doubles to be aligned on natural boundaries. + */ + addr = (size_t)(result + 1); + rem = addr % sizeof(double); + result->dval = (double *)(addr + sizeof(double) - rem); + ARG_TRACE(("addr=%p, dval=%p, sizeof(double)=%d rem=%d\n", addr, result->dval, (int)sizeof(double), (int)rem)); + + result->count = 0; + } + + ARG_TRACE(("arg_dbln() returns %p\n", result)); + return result; +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include + +#include "argtable3.h" + + +static void arg_end_resetfn(struct arg_end *parent) +{ + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + +static void arg_end_errorfn( + void *parent, + FILE *fp, + int error, + const char *argval, + const char *progname) +{ + /* suppress unreferenced formal parameter warning */ + (void)parent; + + progname = progname ? progname : ""; + argval = argval ? argval : ""; + + fprintf(fp, "%s: ", progname); + switch(error) + { + case ARG_ELIMIT: + fputs("too many errors to display", fp); + break; + case ARG_EMALLOC: + fputs("insufficent memory", fp); + break; + case ARG_ENOMATCH: + fprintf(fp, "unexpected argument \"%s\"", argval); + break; + case ARG_EMISSARG: + fprintf(fp, "option \"%s\" requires an argument", argval); + break; + case ARG_ELONGOPT: + fprintf(fp, "invalid option \"%s\"", argval); + break; + default: + fprintf(fp, "invalid option \"-%c\"", error); + break; + } + + fputc('\n', fp); +} + + +struct arg_end * arg_end(int maxcount) +{ + size_t nbytes; + struct arg_end *result; + + nbytes = sizeof(struct arg_end) + + maxcount * sizeof(int) /* storage for int error[maxcount] array*/ + + maxcount * sizeof(void *) /* storage for void* parent[maxcount] array */ + + maxcount * sizeof(char *); /* storage for char* argval[maxcount] array */ + + result = (struct arg_end *)malloc(nbytes); + if (result) + { + /* init the arg_hdr struct */ + result->hdr.flag = ARG_TERMINATOR; + result->hdr.shortopts = NULL; + result->hdr.longopts = NULL; + result->hdr.datatype = NULL; + result->hdr.glossary = NULL; + result->hdr.mincount = 1; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn *)arg_end_resetfn; + result->hdr.scanfn = NULL; + result->hdr.checkfn = NULL; + result->hdr.errorfn = (arg_errorfn *)arg_end_errorfn; + + /* store error[maxcount] array immediately after struct arg_end */ + result->error = (int *)(result + 1); + + /* store parent[maxcount] array immediately after error[] array */ + result->parent = (void * *)(result->error + maxcount ); + + /* store argval[maxcount] array immediately after parent[] array */ + result->argval = (const char * *)(result->parent + maxcount ); + } + + ARG_TRACE(("arg_end(%d) returns %p\n", maxcount, result)); + return result; +} + + +void arg_print_errors(FILE * fp, struct arg_end * end, const char * progname) +{ + int i; + ARG_TRACE(("arg_errors()\n")); + for (i = 0; i < end->count; i++) + { + struct arg_hdr *errorparent = (struct arg_hdr *)(end->parent[i]); + if (errorparent->errorfn) + errorparent->errorfn(end->parent[i], + fp, + end->error[i], + end->argval[i], + progname); + } +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include +#include + +#include "argtable3.h" + +#ifdef WIN32 +# define FILESEPARATOR1 '\\' +# define FILESEPARATOR2 '/' +#else +# define FILESEPARATOR1 '/' +# define FILESEPARATOR2 '/' +#endif + + +static void arg_file_resetfn(struct arg_file *parent) +{ + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + + +/* Returns ptr to the base filename within *filename */ +static const char * arg_basename(const char *filename) +{ + const char *result = NULL, *result1, *result2; + + /* Find the last occurrence of eother file separator character. */ + /* Two alternative file separator chars are supported as legal */ + /* file separators but not both together in the same filename. */ + result1 = (filename ? strrchr(filename, FILESEPARATOR1) : NULL); + result2 = (filename ? strrchr(filename, FILESEPARATOR2) : NULL); + + if (result2) + result = result2 + 1; /* using FILESEPARATOR2 (the alternative file separator) */ + + if (result1) + result = result1 + 1; /* using FILESEPARATOR1 (the preferred file separator) */ + + if (!result) + result = filename; /* neither file separator was found so basename is the whole filename */ + + /* special cases of "." and ".." are not considered basenames */ + if (result && ( strcmp(".", result) == 0 || strcmp("..", result) == 0 )) + result = filename + strlen(filename); + + return result; +} + + +/* Returns ptr to the file extension within *basename */ +static const char * arg_extension(const char *basename) +{ + /* find the last occurrence of '.' in basename */ + const char *result = (basename ? strrchr(basename, '.') : NULL); + + /* if no '.' was found then return pointer to end of basename */ + if (basename && !result) + result = basename + strlen(basename); + + /* special case: basenames with a single leading dot (eg ".foo") are not considered as true extensions */ + if (basename && result == basename) + result = basename + strlen(basename); + + /* special case: empty extensions (eg "foo.","foo..") are not considered as true extensions */ + if (basename && result && result[1] == '\0') + result = basename + strlen(basename); + + return result; +} + + +static int arg_file_scanfn(struct arg_file *parent, const char *argval) +{ + int errorcode = 0; + + if (parent->count == parent->hdr.maxcount) + { + /* maximum number of arguments exceeded */ + errorcode = EMAXCOUNT; + } + else if (!argval) + { + /* a valid argument with no argument value was given. */ + /* This happens when an optional argument value was invoked. */ + /* leave parent arguiment value unaltered but still count the argument. */ + parent->count++; + } + else + { + parent->filename[parent->count] = argval; + parent->basename[parent->count] = arg_basename(argval); + parent->extension[parent->count] = + arg_extension(parent->basename[parent->count]); /* only seek extensions within the basename (not the file path)*/ + parent->count++; + } + + ARG_TRACE(("%s4:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static int arg_file_checkfn(struct arg_file *parent) +{ + int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; + + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static void arg_file_errorfn( + struct arg_file *parent, + FILE *fp, + int errorcode, + const char *argval, + const char *progname) +{ + const char *shortopts = parent->hdr.shortopts; + const char *longopts = parent->hdr.longopts; + const char *datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + fprintf(fp, "%s: ", progname); + switch(errorcode) + { + case EMINCOUNT: + fputs("missing option ", fp); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + + case EMAXCOUNT: + fputs("excess option ", fp); + arg_print_option(fp, shortopts, longopts, argval, "\n"); + break; + + default: + fprintf(fp, "unknown error at \"%s\"\n", argval); + } +} + + +struct arg_file * arg_file0( + const char * shortopts, + const char * longopts, + const char *datatype, + const char *glossary) +{ + return arg_filen(shortopts, longopts, datatype, 0, 1, glossary); +} + + +struct arg_file * arg_file1( + const char * shortopts, + const char * longopts, + const char *datatype, + const char *glossary) +{ + return arg_filen(shortopts, longopts, datatype, 1, 1, glossary); +} + + +struct arg_file * arg_filen( + const char * shortopts, + const char * longopts, + const char *datatype, + int mincount, + int maxcount, + const char *glossary) +{ + size_t nbytes; + struct arg_file *result; + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + nbytes = sizeof(struct arg_file) /* storage for struct arg_file */ + + sizeof(char *) * maxcount /* storage for filename[maxcount] array */ + + sizeof(char *) * maxcount /* storage for basename[maxcount] array */ + + sizeof(char *) * maxcount; /* storage for extension[maxcount] array */ + + result = (struct arg_file *)malloc(nbytes); + if (result) + { + int i; + + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.glossary = glossary; + result->hdr.datatype = datatype ? datatype : ""; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn *)arg_file_resetfn; + result->hdr.scanfn = (arg_scanfn *)arg_file_scanfn; + result->hdr.checkfn = (arg_checkfn *)arg_file_checkfn; + result->hdr.errorfn = (arg_errorfn *)arg_file_errorfn; + + /* store the filename,basename,extension arrays immediately after the arg_file struct */ + result->filename = (const char * *)(result + 1); + result->basename = result->filename + maxcount; + result->extension = result->basename + maxcount; + result->count = 0; + + /* foolproof the string pointers by initialising them with empty strings */ + for (i = 0; i < maxcount; i++) + { + result->filename[i] = ""; + result->basename[i] = ""; + result->extension[i] = ""; + } + } + + ARG_TRACE(("arg_filen() returns %p\n", result)); + return result; +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include +#include +#include + +#include "argtable3.h" + + +static void arg_int_resetfn(struct arg_int *parent) +{ + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + + +/* strtol0x() is like strtol() except that the numeric string is */ +/* expected to be prefixed by "0X" where X is a user supplied char. */ +/* The string may optionally be prefixed by white space and + or - */ +/* as in +0X123 or -0X123. */ +/* Once the prefix has been scanned, the remainder of the numeric */ +/* string is converted using strtol() with the given base. */ +/* eg: to parse hex str="-0X12324", specify X='X' and base=16. */ +/* eg: to parse oct str="+0o12324", specify X='O' and base=8. */ +/* eg: to parse bin str="-0B01010", specify X='B' and base=2. */ +/* Failure of conversion is indicated by result where *endptr==str. */ +static long int strtol0X(const char * str, + const char * *endptr, + char X, + int base) +{ + long int val; /* stores result */ + int s = 1; /* sign is +1 or -1 */ + const char *ptr = str; /* ptr to current position in str */ + + /* skip leading whitespace */ + while (ISSPACE(*ptr)) + ptr++; + /* printf("1) %s\n",ptr); */ + + /* scan optional sign character */ + switch (*ptr) + { + case '+': + ptr++; + s = 1; + break; + case '-': + ptr++; + s = -1; + break; + default: + s = 1; + break; + } + /* printf("2) %s\n",ptr); */ + + /* '0X' prefix */ + if ((*ptr++) != '0') + { + /* printf("failed to detect '0'\n"); */ + *endptr = str; + return 0; + } + /* printf("3) %s\n",ptr); */ + if (toupper(*ptr++) != toupper(X)) + { + /* printf("failed to detect '%c'\n",X); */ + *endptr = str; + return 0; + } + /* printf("4) %s\n",ptr); */ + + /* attempt conversion on remainder of string using strtol() */ + val = strtol(ptr, (char * *)endptr, base); + if (*endptr == ptr) + { + /* conversion failed */ + *endptr = str; + return 0; + } + + /* success */ + return s * val; +} + + +/* Returns 1 if str matches suffix (case insensitive). */ +/* Str may contain trailing whitespace, but nothing else. */ +static int detectsuffix(const char *str, const char *suffix) +{ + /* scan pairwise through strings until mismatch detected */ + while( toupper(*str) == toupper(*suffix) ) + { + /* printf("'%c' '%c'\n", *str, *suffix); */ + + /* return 1 (success) if match persists until the string terminator */ + if (*str == '\0') + return 1; + + /* next chars */ + str++; + suffix++; + } + /* printf("'%c' '%c' mismatch\n", *str, *suffix); */ + + /* return 0 (fail) if the matching did not consume the entire suffix */ + if (*suffix != 0) + return 0; /* failed to consume entire suffix */ + + /* skip any remaining whitespace in str */ + while (ISSPACE(*str)) + str++; + + /* return 1 (success) if we have reached end of str else return 0 (fail) */ + return (*str == '\0') ? 1 : 0; +} + + +static int arg_int_scanfn(struct arg_int *parent, const char *argval) +{ + int errorcode = 0; + + if (parent->count == parent->hdr.maxcount) + { + /* maximum number of arguments exceeded */ + errorcode = EMAXCOUNT; + } + else if (!argval) + { + /* a valid argument with no argument value was given. */ + /* This happens when an optional argument value was invoked. */ + /* leave parent arguiment value unaltered but still count the argument. */ + parent->count++; + } + else + { + long int val; + const char *end; + + /* attempt to extract hex integer (eg: +0x123) from argval into val conversion */ + val = strtol0X(argval, &end, 'X', 16); + if (end == argval) + { + /* hex failed, attempt octal conversion (eg +0o123) */ + val = strtol0X(argval, &end, 'O', 8); + if (end == argval) + { + /* octal failed, attempt binary conversion (eg +0B101) */ + val = strtol0X(argval, &end, 'B', 2); + if (end == argval) + { + /* binary failed, attempt decimal conversion with no prefix (eg 1234) */ + val = strtol(argval, (char * *)&end, 10); + if (end == argval) + { + /* all supported number formats failed */ + return EBADINT; + } + } + } + } + + /* Safety check for integer overflow. WARNING: this check */ + /* achieves nothing on machines where size(int)==size(long). */ + if ( val > INT_MAX || val < INT_MIN ) +#ifdef __STDC_WANT_SECURE_LIB__ + errorcode = EOVERFLOW_; +#else + errorcode = EOVERFLOW; +#endif + + /* Detect any suffixes (KB,MB,GB) and multiply argument value appropriately. */ + /* We need to be mindful of integer overflows when using such big numbers. */ + if (detectsuffix(end, "KB")) /* kilobytes */ + { + if ( val > (INT_MAX / 1024) || val < (INT_MIN / 1024) ) +#ifdef __STDC_WANT_SECURE_LIB__ + errorcode = EOVERFLOW_; /* Overflow would occur if we proceed */ +#else + errorcode = EOVERFLOW; /* Overflow would occur if we proceed */ +#endif + else + val *= 1024; /* 1KB = 1024 */ + } + else if (detectsuffix(end, "MB")) /* megabytes */ + { + if ( val > (INT_MAX / 1048576) || val < (INT_MIN / 1048576) ) +#ifdef __STDC_WANT_SECURE_LIB__ + errorcode = EOVERFLOW_; /* Overflow would occur if we proceed */ +#else + errorcode = EOVERFLOW; /* Overflow would occur if we proceed */ +#endif + else + val *= 1048576; /* 1MB = 1024*1024 */ + } + else if (detectsuffix(end, "GB")) /* gigabytes */ + { + if ( val > (INT_MAX / 1073741824) || val < (INT_MIN / 1073741824) ) +#ifdef __STDC_WANT_SECURE_LIB__ + errorcode = EOVERFLOW_; /* Overflow would occur if we proceed */ +#else + errorcode = EOVERFLOW; /* Overflow would occur if we proceed */ +#endif + else + val *= 1073741824; /* 1GB = 1024*1024*1024 */ + } + else if (!detectsuffix(end, "")) + errorcode = EBADINT; /* invalid suffix detected */ + + /* if success then store result in parent->ival[] array */ + if (errorcode == 0) + parent->ival[parent->count++] = val; + } + + /* printf("%s:scanfn(%p,%p) returns %d\n",__FILE__,parent,argval,errorcode); */ + return errorcode; +} + + +static int arg_int_checkfn(struct arg_int *parent) +{ + int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; + /*printf("%s:checkfn(%p) returns %d\n",__FILE__,parent,errorcode);*/ + return errorcode; +} + + +static void arg_int_errorfn( + struct arg_int *parent, + FILE *fp, + int errorcode, + const char *argval, + const char *progname) +{ + const char *shortopts = parent->hdr.shortopts; + const char *longopts = parent->hdr.longopts; + const char *datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + fprintf(fp, "%s: ", progname); + switch(errorcode) + { + case EMINCOUNT: + fputs("missing option ", fp); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + + case EMAXCOUNT: + fputs("excess option ", fp); + arg_print_option(fp, shortopts, longopts, argval, "\n"); + break; + + case EBADINT: + fprintf(fp, "invalid argument \"%s\" to option ", argval); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + +#ifdef __STDC_WANT_SECURE_LIB__ + case EOVERFLOW_: +#else + case EOVERFLOW: +#endif + fputs("integer overflow at option ", fp); + arg_print_option(fp, shortopts, longopts, datatype, " "); + fprintf(fp, "(%s is too large)\n", argval); + break; + } +} + + +struct arg_int * arg_int0( + const char *shortopts, + const char *longopts, + const char *datatype, + const char *glossary) +{ + return arg_intn(shortopts, longopts, datatype, 0, 1, glossary); +} + + +struct arg_int * arg_int1( + const char *shortopts, + const char *longopts, + const char *datatype, + const char *glossary) +{ + return arg_intn(shortopts, longopts, datatype, 1, 1, glossary); +} + + +struct arg_int * arg_intn( + const char *shortopts, + const char *longopts, + const char *datatype, + int mincount, + int maxcount, + const char *glossary) +{ + size_t nbytes; + struct arg_int *result; + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + nbytes = sizeof(struct arg_int) /* storage for struct arg_int */ + + maxcount * sizeof(int); /* storage for ival[maxcount] array */ + + result = (struct arg_int *)malloc(nbytes); + if (result) + { + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = datatype ? datatype : ""; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn *)arg_int_resetfn; + result->hdr.scanfn = (arg_scanfn *)arg_int_scanfn; + result->hdr.checkfn = (arg_checkfn *)arg_int_checkfn; + result->hdr.errorfn = (arg_errorfn *)arg_int_errorfn; + + /* store the ival[maxcount] array immediately after the arg_int struct */ + result->ival = (int *)(result + 1); + result->count = 0; + } + + ARG_TRACE(("arg_intn() returns %p\n", result)); + return result; +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include + +#include "argtable3.h" + + +static void arg_lit_resetfn(struct arg_lit *parent) +{ + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + + +static int arg_lit_scanfn(struct arg_lit *parent, const char *argval) +{ + int errorcode = 0; + if (parent->count < parent->hdr.maxcount ) + parent->count++; + else + errorcode = EMAXCOUNT; + + ARG_TRACE(("%s:scanfn(%p,%s) returns %d\n", __FILE__, parent, argval, + errorcode)); + return errorcode; +} + + +static int arg_lit_checkfn(struct arg_lit *parent) +{ + int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static void arg_lit_errorfn( + struct arg_lit *parent, + FILE *fp, + int errorcode, + const char *argval, + const char *progname) +{ + const char *shortopts = parent->hdr.shortopts; + const char *longopts = parent->hdr.longopts; + const char *datatype = parent->hdr.datatype; + + switch(errorcode) + { + case EMINCOUNT: + fprintf(fp, "%s: missing option ", progname); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + fprintf(fp, "\n"); + break; + + case EMAXCOUNT: + fprintf(fp, "%s: extraneous option ", progname); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + } + + ARG_TRACE(("%s:errorfn(%p, %p, %d, %s, %s)\n", __FILE__, parent, fp, + errorcode, argval, progname)); +} + + +struct arg_lit * arg_lit0( + const char * shortopts, + const char * longopts, + const char * glossary) +{ + return arg_litn(shortopts, longopts, 0, 1, glossary); +} + + +struct arg_lit * arg_lit1( + const char *shortopts, + const char *longopts, + const char *glossary) +{ + return arg_litn(shortopts, longopts, 1, 1, glossary); +} + + +struct arg_lit * arg_litn( + const char *shortopts, + const char *longopts, + int mincount, + int maxcount, + const char *glossary) +{ + struct arg_lit *result; + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + result = (struct arg_lit *)malloc(sizeof(struct arg_lit)); + if (result) + { + /* init the arg_hdr struct */ + result->hdr.flag = 0; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = NULL; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn *)arg_lit_resetfn; + result->hdr.scanfn = (arg_scanfn *)arg_lit_scanfn; + result->hdr.checkfn = (arg_checkfn *)arg_lit_checkfn; + result->hdr.errorfn = (arg_errorfn *)arg_lit_errorfn; + + /* init local variables */ + result->count = 0; + } + + ARG_TRACE(("arg_litn() returns %p\n", result)); + return result; +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include + +#include "argtable3.h" + +struct arg_rem *arg_rem(const char *datatype, const char *glossary) +{ + struct arg_rem *result = (struct arg_rem *)malloc(sizeof(struct arg_rem)); + if (result) + { + result->hdr.flag = 0; + result->hdr.shortopts = NULL; + result->hdr.longopts = NULL; + result->hdr.datatype = datatype; + result->hdr.glossary = glossary; + result->hdr.mincount = 1; + result->hdr.maxcount = 1; + result->hdr.parent = result; + result->hdr.resetfn = NULL; + result->hdr.scanfn = NULL; + result->hdr.checkfn = NULL; + result->hdr.errorfn = NULL; + } + + ARG_TRACE(("arg_rem() returns %p\n", result)); + return result; +} + +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include +#include + +#include "argtable3.h" + + +#ifndef _TREX_H_ +#define _TREX_H_ +/*************************************************************** + T-Rex a tiny regular expression library + + Copyright (C) 2003-2006 Alberto Demichelis + + This software is provided 'as-is', without any express + or implied warranty. In no event will the authors be held + liable for any damages arising from the use of this software. + + Permission is granted to anyone to use this software for + any purpose, including commercial applications, and to alter + it and redistribute it freely, subject to the following restrictions: + + 1. The origin of this software must not be misrepresented; + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but + is not required. + + 2. Altered source versions must be plainly marked as such, + and must not be misrepresented as being the original software. + + 3. This notice may not be removed or altered from any + source distribution. + +****************************************************************/ + +#ifdef __cplusplus +extern "C" { +#endif + +#ifdef _UNICODE +#define TRexChar unsigned short +#define MAX_CHAR 0xFFFF +#define _TREXC(c) L##c +#define trex_strlen wcslen +#define trex_printf wprintf +#else +#define TRexChar char +#define MAX_CHAR 0xFF +#define _TREXC(c) (c) +#define trex_strlen strlen +#define trex_printf printf +#endif + +#ifndef TREX_API +#define TREX_API extern +#endif + +#define TRex_True 1 +#define TRex_False 0 + +#define TREX_ICASE ARG_REX_ICASE + +typedef unsigned int TRexBool; +typedef struct TRex TRex; + +typedef struct { + const TRexChar *begin; + int len; +} TRexMatch; + +TREX_API TRex *trex_compile(const TRexChar *pattern, const TRexChar **error, int flags); +TREX_API void trex_free(TRex *exp); +TREX_API TRexBool trex_match(TRex* exp, const TRexChar* text); +TREX_API TRexBool trex_search(TRex* exp, const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end); +TREX_API TRexBool trex_searchrange(TRex* exp, const TRexChar* text_begin, const TRexChar* text_end, const TRexChar** out_begin, const TRexChar** out_end); +TREX_API int trex_getsubexpcount(TRex* exp); +TREX_API TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp); + +#ifdef __cplusplus +} +#endif + +#endif + + + +struct privhdr +{ + const char *pattern; + int flags; +}; + + +static void arg_rex_resetfn(struct arg_rex *parent) +{ + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + +static int arg_rex_scanfn(struct arg_rex *parent, const char *argval) +{ + int errorcode = 0; + const TRexChar *error = NULL; + TRex *rex = NULL; + TRexBool is_match = TRex_False; + + if (parent->count == parent->hdr.maxcount ) + { + /* maximum number of arguments exceeded */ + errorcode = EMAXCOUNT; + } + else if (!argval) + { + /* a valid argument with no argument value was given. */ + /* This happens when an optional argument value was invoked. */ + /* leave parent argument value unaltered but still count the argument. */ + parent->count++; + } + else + { + struct privhdr *priv = (struct privhdr *)parent->hdr.priv; + + /* test the current argument value for a match with the regular expression */ + /* if a match is detected, record the argument value in the arg_rex struct */ + + rex = trex_compile(priv->pattern, &error, priv->flags); + is_match = trex_match(rex, argval); + if (!is_match) + errorcode = EREGNOMATCH; + else + parent->sval[parent->count++] = argval; + + trex_free(rex); + } + + ARG_TRACE(("%s:scanfn(%p) returns %d\n",__FILE__,parent,errorcode)); + return errorcode; +} + +static int arg_rex_checkfn(struct arg_rex *parent) +{ + int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; + //struct privhdr *priv = (struct privhdr*)parent->hdr.priv; + + /* free the regex "program" we constructed in resetfn */ + //regfree(&(priv->regex)); + + /*printf("%s:checkfn(%p) returns %d\n",__FILE__,parent,errorcode);*/ + return errorcode; +} + +static void arg_rex_errorfn(struct arg_rex *parent, + FILE *fp, + int errorcode, + const char *argval, + const char *progname) +{ + const char *shortopts = parent->hdr.shortopts; + const char *longopts = parent->hdr.longopts; + const char *datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + fprintf(fp, "%s: ", progname); + switch(errorcode) + { + case EMINCOUNT: + fputs("missing option ", fp); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + + case EMAXCOUNT: + fputs("excess option ", fp); + arg_print_option(fp, shortopts, longopts, argval, "\n"); + break; + + case EREGNOMATCH: + fputs("illegal value ", fp); + arg_print_option(fp, shortopts, longopts, argval, "\n"); + break; + + default: + { + //char errbuff[256]; + //regerror(errorcode, NULL, errbuff, sizeof(errbuff)); + //printf("%s\n", errbuff); + } + break; + } +} + + +struct arg_rex * arg_rex0(const char * shortopts, + const char * longopts, + const char * pattern, + const char *datatype, + int flags, + const char *glossary) +{ + return arg_rexn(shortopts, + longopts, + pattern, + datatype, + 0, + 1, + flags, + glossary); +} + +struct arg_rex * arg_rex1(const char * shortopts, + const char * longopts, + const char * pattern, + const char *datatype, + int flags, + const char *glossary) +{ + return arg_rexn(shortopts, + longopts, + pattern, + datatype, + 1, + 1, + flags, + glossary); +} + + +struct arg_rex * arg_rexn(const char * shortopts, + const char * longopts, + const char * pattern, + const char *datatype, + int mincount, + int maxcount, + int flags, + const char *glossary) +{ + size_t nbytes; + struct arg_rex *result; + struct privhdr *priv; + int i; + const TRexChar *error = NULL; + TRex *rex = NULL; + + if (!pattern) + { + printf( + "argtable: ERROR - illegal regular expression pattern \"(NULL)\"\n"); + printf("argtable: Bad argument table.\n"); + return NULL; + } + + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + nbytes = sizeof(struct arg_rex) /* storage for struct arg_rex */ + + sizeof(struct privhdr) /* storage for private arg_rex data */ + + maxcount * sizeof(char *); /* storage for sval[maxcount] array */ + + result = (struct arg_rex *)malloc(nbytes); + if (result == NULL) + return result; + + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = datatype ? datatype : pattern; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn *)arg_rex_resetfn; + result->hdr.scanfn = (arg_scanfn *)arg_rex_scanfn; + result->hdr.checkfn = (arg_checkfn *)arg_rex_checkfn; + result->hdr.errorfn = (arg_errorfn *)arg_rex_errorfn; + + /* store the arg_rex_priv struct immediately after the arg_rex struct */ + result->hdr.priv = result + 1; + priv = (struct privhdr *)(result->hdr.priv); + priv->pattern = pattern; + priv->flags = flags; + + /* store the sval[maxcount] array immediately after the arg_rex_priv struct */ + result->sval = (const char * *)(priv + 1); + result->count = 0; + + /* foolproof the string pointers by initializing them to reference empty strings */ + for (i = 0; i < maxcount; i++) + result->sval[i] = ""; + + /* here we construct and destroy a regex representation of the regular + * expression for no other reason than to force any regex errors to be + * trapped now rather than later. If we don't, then errors may go undetected + * until an argument is actually parsed. + */ + + rex = trex_compile(priv->pattern, &error, priv->flags); + if (rex == NULL) + { + ARG_LOG(("argtable: %s \"%s\"\n", error ? error : _TREXC("undefined"), priv->pattern)); + ARG_LOG(("argtable: Bad argument table.\n")); + } + + trex_free(rex); + + ARG_TRACE(("arg_rexn() returns %p\n", result)); + return result; +} + + + +/* see copyright notice in trex.h */ +#include +#include +#include +#include + +#ifdef _UINCODE +#define scisprint iswprint +#define scstrlen wcslen +#define scprintf wprintf +#define _SC(x) L(x) +#else +#define scisprint isprint +#define scstrlen strlen +#define scprintf printf +#define _SC(x) (x) +#endif + +#ifdef _DEBUG +#include + +static const TRexChar *g_nnames[] = +{ + _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"), + _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"), + _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"), + _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB") +}; + +#endif +#define OP_GREEDY (MAX_CHAR+1) // * + ? {n} +#define OP_OR (MAX_CHAR+2) +#define OP_EXPR (MAX_CHAR+3) //parentesis () +#define OP_NOCAPEXPR (MAX_CHAR+4) //parentesis (?:) +#define OP_DOT (MAX_CHAR+5) +#define OP_CLASS (MAX_CHAR+6) +#define OP_CCLASS (MAX_CHAR+7) +#define OP_NCLASS (MAX_CHAR+8) //negates class the [^ +#define OP_RANGE (MAX_CHAR+9) +#define OP_CHAR (MAX_CHAR+10) +#define OP_EOL (MAX_CHAR+11) +#define OP_BOL (MAX_CHAR+12) +#define OP_WB (MAX_CHAR+13) + +#define TREX_SYMBOL_ANY_CHAR ('.') +#define TREX_SYMBOL_GREEDY_ONE_OR_MORE ('+') +#define TREX_SYMBOL_GREEDY_ZERO_OR_MORE ('*') +#define TREX_SYMBOL_GREEDY_ZERO_OR_ONE ('?') +#define TREX_SYMBOL_BRANCH ('|') +#define TREX_SYMBOL_END_OF_STRING ('$') +#define TREX_SYMBOL_BEGINNING_OF_STRING ('^') +#define TREX_SYMBOL_ESCAPE_CHAR ('\\') + + +typedef int TRexNodeType; + +typedef struct tagTRexNode{ + TRexNodeType type; + int left; + int right; + int next; +}TRexNode; + +struct TRex{ + const TRexChar *_eol; + const TRexChar *_bol; + const TRexChar *_p; + int _first; + int _op; + TRexNode *_nodes; + int _nallocated; + int _nsize; + int _nsubexpr; + TRexMatch *_matches; + int _currsubexp; + void *_jmpbuf; + const TRexChar **_error; + int _flags; +}; + +static int trex_list(TRex *exp); + +static int trex_newnode(TRex *exp, TRexNodeType type) +{ + TRexNode n; + int newid; + n.type = type; + n.next = n.right = n.left = -1; + if(type == OP_EXPR) + n.right = exp->_nsubexpr++; + if(exp->_nallocated < (exp->_nsize + 1)) { + exp->_nallocated *= 2; + exp->_nodes = (TRexNode *)realloc(exp->_nodes, exp->_nallocated * sizeof(TRexNode)); + } + exp->_nodes[exp->_nsize++] = n; + newid = exp->_nsize - 1; + return (int)newid; +} + +static void trex_error(TRex *exp,const TRexChar *error) +{ + if(exp->_error) *exp->_error = error; + longjmp(*((jmp_buf*)exp->_jmpbuf),-1); +} + +static void trex_expect(TRex *exp, int n){ + if((*exp->_p) != n) + trex_error(exp, _SC("expected paren")); + exp->_p++; +} + +static TRexChar trex_escapechar(TRex *exp) +{ + if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR){ + exp->_p++; + switch(*exp->_p) { + case 'v': exp->_p++; return '\v'; + case 'n': exp->_p++; return '\n'; + case 't': exp->_p++; return '\t'; + case 'r': exp->_p++; return '\r'; + case 'f': exp->_p++; return '\f'; + default: return (*exp->_p++); + } + } else if(!scisprint(*exp->_p)) trex_error(exp,_SC("letter expected")); + return (*exp->_p++); +} + +static int trex_charclass(TRex *exp,int classid) +{ + int n = trex_newnode(exp,OP_CCLASS); + exp->_nodes[n].left = classid; + return n; +} + +static int trex_charnode(TRex *exp,TRexBool isclass) +{ + TRexChar t; + if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) { + exp->_p++; + switch(*exp->_p) { + case 'n': exp->_p++; return trex_newnode(exp,'\n'); + case 't': exp->_p++; return trex_newnode(exp,'\t'); + case 'r': exp->_p++; return trex_newnode(exp,'\r'); + case 'f': exp->_p++; return trex_newnode(exp,'\f'); + case 'v': exp->_p++; return trex_newnode(exp,'\v'); + case 'a': case 'A': case 'w': case 'W': case 's': case 'S': + case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': + case 'p': case 'P': case 'l': case 'u': + { + t = *exp->_p; exp->_p++; + return trex_charclass(exp,t); + } + case 'b': + case 'B': + if(!isclass) { + int node = trex_newnode(exp,OP_WB); + exp->_nodes[node].left = *exp->_p; + exp->_p++; + return node; + } //else default + default: + t = *exp->_p; exp->_p++; + return trex_newnode(exp,t); + } + } + else if(!scisprint(*exp->_p)) { + + trex_error(exp,_SC("letter expected")); + } + t = *exp->_p; exp->_p++; + return trex_newnode(exp,t); +} +static int trex_class(TRex *exp) +{ + int ret = -1; + int first = -1,chain; + if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING){ + ret = trex_newnode(exp,OP_NCLASS); + exp->_p++; + }else ret = trex_newnode(exp,OP_CLASS); + + if(*exp->_p == ']') trex_error(exp,_SC("empty class")); + chain = ret; + while(*exp->_p != ']' && exp->_p != exp->_eol) { + if(*exp->_p == '-' && first != -1){ + int r,t; + if(*exp->_p++ == ']') trex_error(exp,_SC("unfinished range")); + r = trex_newnode(exp,OP_RANGE); + if(first>*exp->_p) trex_error(exp,_SC("invalid range")); + if(exp->_nodes[first].type == OP_CCLASS) trex_error(exp,_SC("cannot use character classes in ranges")); + exp->_nodes[r].left = exp->_nodes[first].type; + t = trex_escapechar(exp); + exp->_nodes[r].right = t; + exp->_nodes[chain].next = r; + chain = r; + first = -1; + } + else{ + if(first!=-1){ + int c = first; + exp->_nodes[chain].next = c; + chain = c; + first = trex_charnode(exp,TRex_True); + } + else{ + first = trex_charnode(exp,TRex_True); + } + } + } + if(first!=-1){ + int c = first; + exp->_nodes[chain].next = c; + chain = c; + first = -1; + } + /* hack? */ + exp->_nodes[ret].left = exp->_nodes[ret].next; + exp->_nodes[ret].next = -1; + return ret; +} + +static int trex_parsenumber(TRex *exp) +{ + int ret = *exp->_p-'0'; + int positions = 10; + exp->_p++; + while(isdigit(*exp->_p)) { + ret = ret*10+(*exp->_p++-'0'); + if(positions==1000000000) trex_error(exp,_SC("overflow in numeric constant")); + positions *= 10; + }; + return ret; +} + +static int trex_element(TRex *exp) +{ + int ret = -1; + switch(*exp->_p) + { + case '(': { + int expr,newn; + exp->_p++; + + + if(*exp->_p =='?') { + exp->_p++; + trex_expect(exp,':'); + expr = trex_newnode(exp,OP_NOCAPEXPR); + } + else + expr = trex_newnode(exp,OP_EXPR); + newn = trex_list(exp); + exp->_nodes[expr].left = newn; + ret = expr; + trex_expect(exp,')'); + } + break; + case '[': + exp->_p++; + ret = trex_class(exp); + trex_expect(exp,']'); + break; + case TREX_SYMBOL_END_OF_STRING: exp->_p++; ret = trex_newnode(exp,OP_EOL);break; + case TREX_SYMBOL_ANY_CHAR: exp->_p++; ret = trex_newnode(exp,OP_DOT);break; + default: + ret = trex_charnode(exp,TRex_False); + break; + } + + { + TRexBool isgreedy = TRex_False; + unsigned short p0 = 0, p1 = 0; + switch(*exp->_p){ + case TREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; + case TREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; + case TREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = TRex_True; break; + case '{': + exp->_p++; + if(!isdigit(*exp->_p)) trex_error(exp,_SC("number expected")); + p0 = (unsigned short)trex_parsenumber(exp); + /*******************************/ + switch(*exp->_p) { + case '}': + p1 = p0; exp->_p++; + break; + case ',': + exp->_p++; + p1 = 0xFFFF; + if(isdigit(*exp->_p)){ + p1 = (unsigned short)trex_parsenumber(exp); + } + trex_expect(exp,'}'); + break; + default: + trex_error(exp,_SC(", or } expected")); + } + /*******************************/ + isgreedy = TRex_True; + break; + + } + if(isgreedy) { + int nnode = trex_newnode(exp,OP_GREEDY); + exp->_nodes[nnode].left = ret; + exp->_nodes[nnode].right = ((p0)<<16)|p1; + ret = nnode; + } + } + if((*exp->_p != TREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != TREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != TREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) { + int nnode = trex_element(exp); + exp->_nodes[ret].next = nnode; + } + + return ret; +} + +static int trex_list(TRex *exp) +{ + int ret=-1,e; + if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) { + exp->_p++; + ret = trex_newnode(exp,OP_BOL); + } + e = trex_element(exp); + if(ret != -1) { + exp->_nodes[ret].next = e; + } + else ret = e; + + if(*exp->_p == TREX_SYMBOL_BRANCH) { + int temp,tright; + exp->_p++; + temp = trex_newnode(exp,OP_OR); + exp->_nodes[temp].left = ret; + tright = trex_list(exp); + exp->_nodes[temp].right = tright; + ret = temp; + } + return ret; +} + +static TRexBool trex_matchcclass(int cclass,TRexChar c) +{ + switch(cclass) { + case 'a': return isalpha(c)?TRex_True:TRex_False; + case 'A': return !isalpha(c)?TRex_True:TRex_False; + case 'w': return (isalnum(c) || c == '_')?TRex_True:TRex_False; + case 'W': return (!isalnum(c) && c != '_')?TRex_True:TRex_False; + case 's': return ISSPACE(c)?TRex_True:TRex_False; + case 'S': return !ISSPACE(c)?TRex_True:TRex_False; + case 'd': return isdigit(c)?TRex_True:TRex_False; + case 'D': return !isdigit(c)?TRex_True:TRex_False; + case 'x': return isxdigit(c)?TRex_True:TRex_False; + case 'X': return !isxdigit(c)?TRex_True:TRex_False; + case 'c': return iscntrl(c)?TRex_True:TRex_False; + case 'C': return !iscntrl(c)?TRex_True:TRex_False; + case 'p': return ispunct(c)?TRex_True:TRex_False; + case 'P': return !ispunct(c)?TRex_True:TRex_False; + case 'l': return islower(c)?TRex_True:TRex_False; + case 'u': return isupper(c)?TRex_True:TRex_False; + } + return TRex_False; /*cannot happen*/ +} + +static TRexBool trex_matchclass(TRex* exp,TRexNode *node,TRexChar c) +{ + do { + switch(node->type) { + case OP_RANGE: + if (exp->_flags & TREX_ICASE) + { + if(c >= toupper(node->left) && c <= toupper(node->right)) return TRex_True; + if(c >= tolower(node->left) && c <= tolower(node->right)) return TRex_True; + } + else + { + if(c >= node->left && c <= node->right) return TRex_True; + } + break; + case OP_CCLASS: + if(trex_matchcclass(node->left,c)) return TRex_True; + break; + default: + if (exp->_flags & TREX_ICASE) + { + if (c == tolower(node->type) || c == toupper(node->type)) return TRex_True; + } + else + { + if(c == node->type)return TRex_True; + } + + } + } while((node->next != -1) && (node = &exp->_nodes[node->next])); + return TRex_False; +} + +static const TRexChar *trex_matchnode(TRex* exp,TRexNode *node,const TRexChar *str,TRexNode *next) +{ + + TRexNodeType type = node->type; + switch(type) { + case OP_GREEDY: { + //TRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; + TRexNode *greedystop = NULL; + int p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0; + const TRexChar *s=str, *good = str; + + if(node->next != -1) { + greedystop = &exp->_nodes[node->next]; + } + else { + greedystop = next; + } + + while((nmaches == 0xFFFF || nmaches < p1)) { + + const TRexChar *stop; + if(!(s = trex_matchnode(exp,&exp->_nodes[node->left],s,greedystop))) + break; + nmaches++; + good=s; + if(greedystop) { + //checks that 0 matches satisfy the expression(if so skips) + //if not would always stop(for instance if is a '?') + if(greedystop->type != OP_GREEDY || + (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0)) + { + TRexNode *gnext = NULL; + if(greedystop->next != -1) { + gnext = &exp->_nodes[greedystop->next]; + }else if(next && next->next != -1){ + gnext = &exp->_nodes[next->next]; + } + stop = trex_matchnode(exp,greedystop,s,gnext); + if(stop) { + //if satisfied stop it + if(p0 == p1 && p0 == nmaches) break; + else if(nmaches >= p0 && p1 == 0xFFFF) break; + else if(nmaches >= p0 && nmaches <= p1) break; + } + } + } + + if(s >= exp->_eol) + break; + } + if(p0 == p1 && p0 == nmaches) return good; + else if(nmaches >= p0 && p1 == 0xFFFF) return good; + else if(nmaches >= p0 && nmaches <= p1) return good; + return NULL; + } + case OP_OR: { + const TRexChar *asd = str; + TRexNode *temp=&exp->_nodes[node->left]; + while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) { + if(temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + asd = str; + temp = &exp->_nodes[node->right]; + while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) { + if(temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + return NULL; + break; + } + case OP_EXPR: + case OP_NOCAPEXPR:{ + TRexNode *n = &exp->_nodes[node->left]; + const TRexChar *cur = str; + int capture = -1; + if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) { + capture = exp->_currsubexp; + exp->_matches[capture].begin = cur; + exp->_currsubexp++; + } + + do { + TRexNode *subnext = NULL; + if(n->next != -1) { + subnext = &exp->_nodes[n->next]; + }else { + subnext = next; + } + if(!(cur = trex_matchnode(exp,n,cur,subnext))) { + if(capture != -1){ + exp->_matches[capture].begin = 0; + exp->_matches[capture].len = 0; + } + return NULL; + } + } while((n->next != -1) && (n = &exp->_nodes[n->next])); + + if(capture != -1) + exp->_matches[capture].len = (int)(cur - exp->_matches[capture].begin); + return cur; + } + case OP_WB: + if((str == exp->_bol && !ISSPACE(*str)) + || ((str == exp->_eol && !ISSPACE(*(str-1)))) + || ((!ISSPACE(*str) && ISSPACE(*(str+1)))) + || ((ISSPACE(*str) && !ISSPACE(*(str+1)))) ) { + return (node->left == 'b')?str:NULL; + } + return (node->left == 'b')?NULL:str; + case OP_BOL: + if(str == exp->_bol) return str; + return NULL; + case OP_EOL: + if(str == exp->_eol) return str; + return NULL; + case OP_DOT: + str++; + return str; + case OP_NCLASS: + case OP_CLASS: + if(trex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?TRex_True:TRex_False):(type == OP_NCLASS?TRex_True:TRex_False)) { + str++; + return str; + } + return NULL; + case OP_CCLASS: + if(trex_matchcclass(node->left,*str)) { + str++; + return str; + } + return NULL; + default: /* char */ + if (exp->_flags & TREX_ICASE) + { + if(*str != tolower(node->type) && *str != toupper(node->type)) return NULL; + } + else + { + if (*str != node->type) return NULL; + } + str++; + return str; + } + return NULL; +} + +/* public api */ +TRex *trex_compile(const TRexChar *pattern,const TRexChar **error,int flags) +{ + TRex *exp = (TRex *)malloc(sizeof(TRex)); + exp->_eol = exp->_bol = NULL; + exp->_p = pattern; + exp->_nallocated = (int)scstrlen(pattern) * sizeof(TRexChar); + exp->_nodes = (TRexNode *)malloc(exp->_nallocated * sizeof(TRexNode)); + exp->_nsize = 0; + exp->_matches = 0; + exp->_nsubexpr = 0; + exp->_first = trex_newnode(exp,OP_EXPR); + exp->_error = error; + exp->_jmpbuf = malloc(sizeof(jmp_buf)); + exp->_flags = flags; + if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) { + int res = trex_list(exp); + exp->_nodes[exp->_first].left = res; + if(*exp->_p!='\0') + trex_error(exp,_SC("unexpected character")); +#ifdef _DEBUG + { + int nsize,i; + TRexNode *t; + nsize = exp->_nsize; + t = &exp->_nodes[0]; + scprintf(_SC("\n")); + for(i = 0;i < nsize; i++) { + if(exp->_nodes[i].type>MAX_CHAR) + scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]); + else + scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type); + scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next); + } + scprintf(_SC("\n")); + } +#endif + exp->_matches = (TRexMatch *) malloc(exp->_nsubexpr * sizeof(TRexMatch)); + memset(exp->_matches,0,exp->_nsubexpr * sizeof(TRexMatch)); + } + else{ + trex_free(exp); + return NULL; + } + return exp; +} + +void trex_free(TRex *exp) +{ + if(exp) { + if(exp->_nodes) free(exp->_nodes); + if(exp->_jmpbuf) free(exp->_jmpbuf); + if(exp->_matches) free(exp->_matches); + free(exp); + } +} + +TRexBool trex_match(TRex* exp,const TRexChar* text) +{ + const TRexChar* res = NULL; + exp->_bol = text; + exp->_eol = text + scstrlen(text); + exp->_currsubexp = 0; + res = trex_matchnode(exp,exp->_nodes,text,NULL); + if(res == NULL || res != exp->_eol) + return TRex_False; + return TRex_True; +} + +TRexBool trex_searchrange(TRex* exp,const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end) +{ + const TRexChar *cur = NULL; + int node = exp->_first; + if(text_begin >= text_end) return TRex_False; + exp->_bol = text_begin; + exp->_eol = text_end; + do { + cur = text_begin; + while(node != -1) { + exp->_currsubexp = 0; + cur = trex_matchnode(exp,&exp->_nodes[node],cur,NULL); + if(!cur) + break; + node = exp->_nodes[node].next; + } + text_begin++; + } while(cur == NULL && text_begin != text_end); + + if(cur == NULL) + return TRex_False; + + --text_begin; + + if(out_begin) *out_begin = text_begin; + if(out_end) *out_end = cur; + return TRex_True; +} + +TRexBool trex_search(TRex* exp,const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end) +{ + return trex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end); +} + +int trex_getsubexpcount(TRex* exp) +{ + return exp->_nsubexpr; +} + +TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp) +{ + if( n<0 || n >= exp->_nsubexpr) return TRex_False; + *subexp = exp->_matches[n]; + return TRex_True; +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include + +#include "argtable3.h" + + +static void arg_str_resetfn(struct arg_str *parent) +{ + ARG_TRACE(("%s:resetfn(%p)\n", __FILE__, parent)); + parent->count = 0; +} + + +static int arg_str_scanfn(struct arg_str *parent, const char *argval) +{ + int errorcode = 0; + + if (parent->count == parent->hdr.maxcount) + { + /* maximum number of arguments exceeded */ + errorcode = EMAXCOUNT; + } + else if (!argval) + { + /* a valid argument with no argument value was given. */ + /* This happens when an optional argument value was invoked. */ + /* leave parent arguiment value unaltered but still count the argument. */ + parent->count++; + } + else + { + parent->sval[parent->count++] = argval; + } + + ARG_TRACE(("%s:scanfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static int arg_str_checkfn(struct arg_str *parent) +{ + int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; + + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); + return errorcode; +} + + +static void arg_str_errorfn( + struct arg_str *parent, + FILE *fp, + int errorcode, + const char *argval, + const char *progname) +{ + const char *shortopts = parent->hdr.shortopts; + const char *longopts = parent->hdr.longopts; + const char *datatype = parent->hdr.datatype; + + /* make argval NULL safe */ + argval = argval ? argval : ""; + + fprintf(fp, "%s: ", progname); + switch(errorcode) + { + case EMINCOUNT: + fputs("missing option ", fp); + arg_print_option(fp, shortopts, longopts, datatype, "\n"); + break; + + case EMAXCOUNT: + fputs("excess option ", fp); + arg_print_option(fp, shortopts, longopts, argval, "\n"); + break; + } +} + + +struct arg_str * arg_str0( + const char *shortopts, + const char *longopts, + const char *datatype, + const char *glossary) +{ + return arg_strn(shortopts, longopts, datatype, 0, 1, glossary); +} + + +struct arg_str * arg_str1( + const char *shortopts, + const char *longopts, + const char *datatype, + const char *glossary) +{ + return arg_strn(shortopts, longopts, datatype, 1, 1, glossary); +} + + +struct arg_str * arg_strn( + const char *shortopts, + const char *longopts, + const char *datatype, + int mincount, + int maxcount, + const char *glossary) +{ + size_t nbytes; + struct arg_str *result; + + /* should not allow this stupid error */ + /* we should return an error code warning this logic error */ + /* foolproof things by ensuring maxcount is not less than mincount */ + maxcount = (maxcount < mincount) ? mincount : maxcount; + + nbytes = sizeof(struct arg_str) /* storage for struct arg_str */ + + maxcount * sizeof(char *); /* storage for sval[maxcount] array */ + + result = (struct arg_str *)malloc(nbytes); + if (result) + { + int i; + + /* init the arg_hdr struct */ + result->hdr.flag = ARG_HASVALUE; + result->hdr.shortopts = shortopts; + result->hdr.longopts = longopts; + result->hdr.datatype = datatype ? datatype : ""; + result->hdr.glossary = glossary; + result->hdr.mincount = mincount; + result->hdr.maxcount = maxcount; + result->hdr.parent = result; + result->hdr.resetfn = (arg_resetfn *)arg_str_resetfn; + result->hdr.scanfn = (arg_scanfn *)arg_str_scanfn; + result->hdr.checkfn = (arg_checkfn *)arg_str_checkfn; + result->hdr.errorfn = (arg_errorfn *)arg_str_errorfn; + + /* store the sval[maxcount] array immediately after the arg_str struct */ + result->sval = (const char * *)(result + 1); + result->count = 0; + + /* foolproof the string pointers by initialising them to reference empty strings */ + for (i = 0; i < maxcount; i++) + result->sval[i] = ""; + } + + ARG_TRACE(("arg_strn() returns %p\n", result)); + return result; +} +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#include +#include +#include +#include + +#include "argtable3.h" + +static +void arg_register_error(struct arg_end *end, + void *parent, + int error, + const char *argval) +{ + /* printf("arg_register_error(%p,%p,%d,%s)\n",end,parent,error,argval); */ + if (end->count < end->hdr.maxcount) + { + end->error[end->count] = error; + end->parent[end->count] = parent; + end->argval[end->count] = argval; + end->count++; + } + else + { + end->error[end->hdr.maxcount - 1] = ARG_ELIMIT; + end->parent[end->hdr.maxcount - 1] = end; + end->argval[end->hdr.maxcount - 1] = NULL; + } +} + + +/* + * Return index of first table entry with a matching short option + * or -1 if no match was found. + */ +static +int find_shortoption(struct arg_hdr * *table, char shortopt) +{ + int tabindex; + for(tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) + { + if (table[tabindex]->shortopts && + strchr(table[tabindex]->shortopts, shortopt)) + return tabindex; + } + return -1; +} + + +struct longoptions +{ + int getoptval; + int noptions; + struct option *options; +}; + +#if 0 +static +void dump_longoptions(struct longoptions * longoptions) +{ + int i; + printf("getoptval = %d\n", longoptions->getoptval); + printf("noptions = %d\n", longoptions->noptions); + for (i = 0; i < longoptions->noptions; i++) + { + printf("options[%d].name = \"%s\"\n", + i, + longoptions->options[i].name); + printf("options[%d].has_arg = %d\n", i, longoptions->options[i].has_arg); + printf("options[%d].flag = %p\n", i, longoptions->options[i].flag); + printf("options[%d].val = %d\n", i, longoptions->options[i].val); + } +} +#endif + +static +struct longoptions * alloc_longoptions(struct arg_hdr * *table) +{ + struct longoptions *result; + size_t nbytes; + int noptions = 1; + size_t longoptlen = 0; + int tabindex; + + /* + * Determine the total number of option structs required + * by counting the number of comma separated long options + * in all table entries and return the count in noptions. + * note: noptions starts at 1 not 0 because we getoptlong + * requires a NULL option entry to terminate the option array. + * While we are at it, count the number of chars required + * to store private copies of all the longoption strings + * and return that count in logoptlen. + */ + tabindex = 0; + do + { + const char *longopts = table[tabindex]->longopts; + longoptlen += (longopts ? strlen(longopts) : 0) + 1; + while (longopts) + { + noptions++; + longopts = strchr(longopts + 1, ','); + } + } while(!(table[tabindex++]->flag & ARG_TERMINATOR)); + /*printf("%d long options consuming %d chars in total\n",noptions,longoptlen);*/ + + + /* allocate storage for return data structure as: */ + /* (struct longoptions) + (struct options)[noptions] + char[longoptlen] */ + nbytes = sizeof(struct longoptions) + + sizeof(struct option) * noptions + + longoptlen; + result = (struct longoptions *)malloc(nbytes); + if (result) + { + int option_index = 0; + char *store; + + result->getoptval = 0; + result->noptions = noptions; + result->options = (struct option *)(result + 1); + store = (char *)(result->options + noptions); + + for(tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) + { + const char *longopts = table[tabindex]->longopts; + + while(longopts && *longopts) + { + char *storestart = store; + + /* copy progressive longopt strings into the store */ + while (*longopts != 0 && *longopts != ',') + *store++ = *longopts++; + *store++ = 0; + if (*longopts == ',') + longopts++; + /*fprintf(stderr,"storestart=\"%s\"\n",storestart);*/ + + result->options[option_index].name = storestart; + result->options[option_index].flag = &(result->getoptval); + result->options[option_index].val = tabindex; + if (table[tabindex]->flag & ARG_HASOPTVALUE) + result->options[option_index].has_arg = 2; + else if (table[tabindex]->flag & ARG_HASVALUE) + result->options[option_index].has_arg = 1; + else + result->options[option_index].has_arg = 0; + + option_index++; + } + } + /* terminate the options array with a zero-filled entry */ + result->options[option_index].name = 0; + result->options[option_index].has_arg = 0; + result->options[option_index].flag = 0; + result->options[option_index].val = 0; + } + + /*dump_longoptions(result);*/ + return result; +} + +static +char * alloc_shortoptions(struct arg_hdr * *table) +{ + char *result; + size_t len = 2; + int tabindex; + + /* determine the total number of option chars required */ + for(tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) + { + struct arg_hdr *hdr = table[tabindex]; + len += 3 * (hdr->shortopts ? strlen(hdr->shortopts) : 0); + } + + result = malloc(len); + if (result) + { + char *res = result; + + /* add a leading ':' so getopt return codes distinguish */ + /* unrecognised option and options missing argument values */ + *res++ = ':'; + + for(tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) + { + struct arg_hdr *hdr = table[tabindex]; + const char *shortopts = hdr->shortopts; + while(shortopts && *shortopts) + { + *res++ = *shortopts++; + if (hdr->flag & ARG_HASVALUE) + *res++ = ':'; + if (hdr->flag & ARG_HASOPTVALUE) + *res++ = ':'; + } + } + /* null terminate the string */ + *res = 0; + } + + /*printf("alloc_shortoptions() returns \"%s\"\n",(result?result:"NULL"));*/ + return result; +} + + +/* return index of the table terminator entry */ +static +int arg_endindex(struct arg_hdr * *table) +{ + int tabindex = 0; + while (!(table[tabindex]->flag & ARG_TERMINATOR)) + tabindex++; + return tabindex; +} + + +static +void arg_parse_tagged(int argc, + char * *argv, + struct arg_hdr * *table, + struct arg_end *endtable) +{ + struct longoptions *longoptions; + char *shortoptions; + int copt; + + /*printf("arg_parse_tagged(%d,%p,%p,%p)\n",argc,argv,table,endtable);*/ + + /* allocate short and long option arrays for the given opttable[]. */ + /* if the allocs fail then put an error msg in the last table entry. */ + longoptions = alloc_longoptions(table); + shortoptions = alloc_shortoptions(table); + if (!longoptions || !shortoptions) + { + /* one or both memory allocs failed */ + arg_register_error(endtable, endtable, ARG_EMALLOC, NULL); + /* free anything that was allocated (this is null safe) */ + free(shortoptions); + free(longoptions); + return; + } + + /*dump_longoptions(longoptions);*/ + + /* reset getopts internal option-index to zero, and disable error reporting */ + optind = 0; + opterr = 0; + + /* fetch and process args using getopt_long */ + while( (copt = + getopt_long(argc, argv, shortoptions, longoptions->options, + NULL)) != -1) + { + /* + printf("optarg='%s'\n",optarg); + printf("optind=%d\n",optind); + printf("copt=%c\n",(char)copt); + printf("optopt=%c (%d)\n",optopt, (int)(optopt)); + */ + switch(copt) + { + case 0: + { + int tabindex = longoptions->getoptval; + void *parent = table[tabindex]->parent; + /*printf("long option detected from argtable[%d]\n", tabindex);*/ + if (optarg && optarg[0] == 0 && + (table[tabindex]->flag & ARG_HASVALUE)) + { + /* printf(": long option %s requires an argument\n",argv[optind-1]); */ + arg_register_error(endtable, endtable, ARG_EMISSARG, + argv[optind - 1]); + /* continue to scan the (empty) argument value to enforce argument count checking */ + } + if (table[tabindex]->scanfn) + { + int errorcode = table[tabindex]->scanfn(parent, optarg); + if (errorcode != 0) + arg_register_error(endtable, parent, errorcode, optarg); + } + } + break; + + case '?': + /* + * getopt_long() found an unrecognised short option. + * if it was a short option its value is in optopt + * if it was a long option then optopt=0 + */ + switch (optopt) + { + case 0: + /*printf("?0 unrecognised long option %s\n",argv[optind-1]);*/ + arg_register_error(endtable, endtable, ARG_ELONGOPT, + argv[optind - 1]); + break; + default: + /*printf("?* unrecognised short option '%c'\n",optopt);*/ + arg_register_error(endtable, endtable, optopt, NULL); + break; + } + break; + + case ':': + /* + * getopt_long() found an option with its argument missing. + */ + /*printf(": option %s requires an argument\n",argv[optind-1]); */ + arg_register_error(endtable, endtable, ARG_EMISSARG, + argv[optind - 1]); + break; + + default: + { + /* getopt_long() found a valid short option */ + int tabindex = find_shortoption(table, (char)copt); + /*printf("short option detected from argtable[%d]\n", tabindex);*/ + if (tabindex == -1) + { + /* should never get here - but handle it just in case */ + /*printf("unrecognised short option %d\n",copt);*/ + arg_register_error(endtable, endtable, copt, NULL); + } + else + { + if (table[tabindex]->scanfn) + { + void *parent = table[tabindex]->parent; + int errorcode = table[tabindex]->scanfn(parent, optarg); + if (errorcode != 0) + arg_register_error(endtable, parent, errorcode, optarg); + } + } + break; + } + } + } + + free(shortoptions); + free(longoptions); +} + + +static +void arg_parse_untagged(int argc, + char * *argv, + struct arg_hdr * *table, + struct arg_end *endtable) +{ + int tabindex = 0; + int errorlast = 0; + const char *optarglast = NULL; + void *parentlast = NULL; + + /*printf("arg_parse_untagged(%d,%p,%p,%p)\n",argc,argv,table,endtable);*/ + while (!(table[tabindex]->flag & ARG_TERMINATOR)) + { + void *parent; + int errorcode; + + /* if we have exhausted our argv[optind] entries then we have finished */ + if (optind >= argc) + { + /*printf("arg_parse_untagged(): argv[] exhausted\n");*/ + return; + } + + /* skip table entries with non-null long or short options (they are not untagged entries) */ + if (table[tabindex]->longopts || table[tabindex]->shortopts) + { + /*printf("arg_parse_untagged(): skipping argtable[%d] (tagged argument)\n",tabindex);*/ + tabindex++; + continue; + } + + /* skip table entries with NULL scanfn */ + if (!(table[tabindex]->scanfn)) + { + /*printf("arg_parse_untagged(): skipping argtable[%d] (NULL scanfn)\n",tabindex);*/ + tabindex++; + continue; + } + + /* attempt to scan the current argv[optind] with the current */ + /* table[tabindex] entry. If it succeeds then keep it, otherwise */ + /* try again with the next table[] entry. */ + parent = table[tabindex]->parent; + errorcode = table[tabindex]->scanfn(parent, argv[optind]); + if (errorcode == 0) + { + /* success, move onto next argv[optind] but stay with same table[tabindex] */ + /*printf("arg_parse_untagged(): argtable[%d] successfully matched\n",tabindex);*/ + optind++; + + /* clear the last tentative error */ + errorlast = 0; + } + else + { + /* failure, try same argv[optind] with next table[tabindex] entry */ + /*printf("arg_parse_untagged(): argtable[%d] failed match\n",tabindex);*/ + tabindex++; + + /* remember this as a tentative error we may wish to reinstate later */ + errorlast = errorcode; + optarglast = argv[optind]; + parentlast = parent; + } + + } + + /* if a tenative error still remains at this point then register it as a proper error */ + if (errorlast) + { + arg_register_error(endtable, parentlast, errorlast, optarglast); + optind++; + } + + /* only get here when not all argv[] entries were consumed */ + /* register an error for each unused argv[] entry */ + while (optind < argc) + { + /*printf("arg_parse_untagged(): argv[%d]=\"%s\" not consumed\n",optind,argv[optind]);*/ + arg_register_error(endtable, endtable, ARG_ENOMATCH, argv[optind++]); + } + + return; +} + + +static +void arg_parse_check(struct arg_hdr * *table, struct arg_end *endtable) +{ + int tabindex = 0; + /* printf("arg_parse_check()\n"); */ + do + { + if (table[tabindex]->checkfn) + { + void *parent = table[tabindex]->parent; + int errorcode = table[tabindex]->checkfn(parent); + if (errorcode != 0) + arg_register_error(endtable, parent, errorcode, NULL); + } + } while(!(table[tabindex++]->flag & ARG_TERMINATOR)); +} + + +static +void arg_reset(void * *argtable) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + int tabindex = 0; + /*printf("arg_reset(%p)\n",argtable);*/ + do + { + if (table[tabindex]->resetfn) + table[tabindex]->resetfn(table[tabindex]->parent); + } while(!(table[tabindex++]->flag & ARG_TERMINATOR)); +} + + +int arg_parse(int argc, char * *argv, void * *argtable) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + struct arg_end *endtable; + int endindex; + char * *argvcopy = NULL; + + /*printf("arg_parse(%d,%p,%p)\n",argc,argv,argtable);*/ + + /* reset any argtable data from previous invocations */ + arg_reset(argtable); + + /* locate the first end-of-table marker within the array */ + endindex = arg_endindex(table); + endtable = (struct arg_end *)table[endindex]; + + /* Special case of argc==0. This can occur on Texas Instruments DSP. */ + /* Failure to trap this case results in an unwanted NULL result from */ + /* the malloc for argvcopy (next code block). */ + if (argc == 0) + { + /* We must still perform post-parse checks despite the absence of command line arguments */ + arg_parse_check(table, endtable); + + /* Now we are finished */ + return endtable->count; + } + + argvcopy = (char **)malloc(sizeof(char *) * (argc + 1)); + if (argvcopy) + { + int i; + + /* + Fill in the local copy of argv[]. We need a local copy + because getopt rearranges argv[] which adversely affects + susbsequent parsing attempts. + */ + for (i = 0; i < argc; i++) + argvcopy[i] = argv[i]; + + argvcopy[argc] = NULL; + + /* parse the command line (local copy) for tagged options */ + arg_parse_tagged(argc, argvcopy, table, endtable); + + /* parse the command line (local copy) for untagged options */ + arg_parse_untagged(argc, argvcopy, table, endtable); + + /* if no errors so far then perform post-parse checks otherwise dont bother */ + if (endtable->count == 0) + arg_parse_check(table, endtable); + + /* release the local copt of argv[] */ + free(argvcopy); + } + else + { + /* memory alloc failed */ + arg_register_error(endtable, endtable, ARG_EMALLOC, NULL); + } + + return endtable->count; +} + + +/* + * Concatenate contents of src[] string onto *pdest[] string. + * The *pdest pointer is altered to point to the end of the + * target string and *pndest is decremented by the same number + * of chars. + * Does not append more than *pndest chars into *pdest[] + * so as to prevent buffer overruns. + * Its something like strncat() but more efficient for repeated + * calls on the same destination string. + * Example of use: + * char dest[30] = "good" + * size_t ndest = sizeof(dest); + * char *pdest = dest; + * arg_char(&pdest,"bye ",&ndest); + * arg_char(&pdest,"cruel ",&ndest); + * arg_char(&pdest,"world!",&ndest); + * Results in: + * dest[] == "goodbye cruel world!" + * ndest == 10 + */ +static +void arg_cat(char * *pdest, const char *src, size_t *pndest) +{ + char *dest = *pdest; + char *end = dest + *pndest; + + /*locate null terminator of dest string */ + while(dest < end && *dest != 0) + dest++; + + /* concat src string to dest string */ + while(dest < end && *src != 0) + *dest++ = *src++; + + /* null terminate dest string */ + *dest = 0; + + /* update *pdest and *pndest */ + *pndest = end - dest; + *pdest = dest; +} + + +static +void arg_cat_option(char *dest, + size_t ndest, + const char *shortopts, + const char *longopts, + const char *datatype, + int optvalue) +{ + if (shortopts) + { + char option[3]; + + /* note: option array[] is initialiazed dynamically here to satisfy */ + /* a deficiency in the watcom compiler wrt static array initializers. */ + option[0] = '-'; + option[1] = shortopts[0]; + option[2] = 0; + + arg_cat(&dest, option, &ndest); + if (datatype) + { + arg_cat(&dest, " ", &ndest); + if (optvalue) + { + arg_cat(&dest, "[", &ndest); + arg_cat(&dest, datatype, &ndest); + arg_cat(&dest, "]", &ndest); + } + else + arg_cat(&dest, datatype, &ndest); + } + } + else if (longopts) + { + size_t ncspn; + + /* add "--" tag prefix */ + arg_cat(&dest, "--", &ndest); + + /* add comma separated option tag */ + ncspn = strcspn(longopts, ","); +#ifdef __STDC_WANT_SECURE_LIB__ + strncat_s(dest, ndest, longopts, (ncspn < ndest) ? ncspn : ndest); +#else + strncat(dest, longopts, (ncspn < ndest) ? ncspn : ndest); +#endif + + if (datatype) + { + arg_cat(&dest, "=", &ndest); + if (optvalue) + { + arg_cat(&dest, "[", &ndest); + arg_cat(&dest, datatype, &ndest); + arg_cat(&dest, "]", &ndest); + } + else + arg_cat(&dest, datatype, &ndest); + } + } + else if (datatype) + { + if (optvalue) + { + arg_cat(&dest, "[", &ndest); + arg_cat(&dest, datatype, &ndest); + arg_cat(&dest, "]", &ndest); + } + else + arg_cat(&dest, datatype, &ndest); + } +} + +static +void arg_cat_optionv(char *dest, + size_t ndest, + const char *shortopts, + const char *longopts, + const char *datatype, + int optvalue, + const char *separator) +{ + separator = separator ? separator : ""; + + if (shortopts) + { + const char *c = shortopts; + while(*c) + { + /* "-a|-b|-c" */ + char shortopt[3]; + + /* note: shortopt array[] is initialiazed dynamically here to satisfy */ + /* a deficiency in the watcom compiler wrt static array initializers. */ + shortopt[0] = '-'; + shortopt[1] = *c; + shortopt[2] = 0; + + arg_cat(&dest, shortopt, &ndest); + if (*++c) + arg_cat(&dest, separator, &ndest); + } + } + + /* put separator between long opts and short opts */ + if (shortopts && longopts) + arg_cat(&dest, separator, &ndest); + + if (longopts) + { + const char *c = longopts; + while(*c) + { + size_t ncspn; + + /* add "--" tag prefix */ + arg_cat(&dest, "--", &ndest); + + /* add comma separated option tag */ + ncspn = strcspn(c, ","); +#ifdef __STDC_WANT_SECURE_LIB__ + strncat_s(dest, ndest, c, (ncspn < ndest) ? ncspn : ndest); +#else + strncat(dest, c, (ncspn < ndest) ? ncspn : ndest); +#endif + c += ncspn; + + /* add given separator in place of comma */ + if (*c == ',') + { + arg_cat(&dest, separator, &ndest); + c++; + } + } + } + + if (datatype) + { + if (longopts) + arg_cat(&dest, "=", &ndest); + else if (shortopts) + arg_cat(&dest, " ", &ndest); + + if (optvalue) + { + arg_cat(&dest, "[", &ndest); + arg_cat(&dest, datatype, &ndest); + arg_cat(&dest, "]", &ndest); + } + else + arg_cat(&dest, datatype, &ndest); + } +} + + +/* this function should be deprecated because it doesnt consider optional argument values (ARG_HASOPTVALUE) */ +void arg_print_option(FILE *fp, + const char *shortopts, + const char *longopts, + const char *datatype, + const char *suffix) +{ + char syntax[200] = ""; + suffix = suffix ? suffix : ""; + + /* there is no way of passing the proper optvalue for optional argument values here, so we must ignore it */ + arg_cat_optionv(syntax, + sizeof(syntax), + shortopts, + longopts, + datatype, + 0, + "|"); + + fputs(syntax, fp); + fputs(suffix, fp); +} + + +/* + * Print a GNU style [OPTION] string in which all short options that + * do not take argument values are presented in abbreviated form, as + * in: -xvfsd, or -xvf[sd], or [-xvsfd] + */ +static +void arg_print_gnuswitch(FILE *fp, struct arg_hdr * *table) +{ + int tabindex; + char *format1 = " -%c"; + char *format2 = " [-%c"; + char *suffix = ""; + + /* print all mandatory switches that are without argument values */ + for(tabindex = 0; + table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); + tabindex++) + { + /* skip optional options */ + if (table[tabindex]->mincount < 1) + continue; + + /* skip non-short options */ + if (table[tabindex]->shortopts == NULL) + continue; + + /* skip options that take argument values */ + if (table[tabindex]->flag & ARG_HASVALUE) + continue; + + /* print the short option (only the first short option char, ignore multiple choices)*/ + fprintf(fp, format1, table[tabindex]->shortopts[0]); + format1 = "%c"; + format2 = "[%c"; + } + + /* print all optional switches that are without argument values */ + for(tabindex = 0; + table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); + tabindex++) + { + /* skip mandatory args */ + if (table[tabindex]->mincount > 0) + continue; + + /* skip args without short options */ + if (table[tabindex]->shortopts == NULL) + continue; + + /* skip args with values */ + if (table[tabindex]->flag & ARG_HASVALUE) + continue; + + /* print first short option */ + fprintf(fp, format2, table[tabindex]->shortopts[0]); + format2 = "%c"; + suffix = "]"; + } + + fprintf(fp, "%s", suffix); +} + + +void arg_print_syntax(FILE *fp, void * *argtable, const char *suffix) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + int i, tabindex; + + /* print GNU style [OPTION] string */ + arg_print_gnuswitch(fp, table); + + /* print remaining options in abbreviated style */ + for(tabindex = 0; + table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); + tabindex++) + { + char syntax[200] = ""; + const char *shortopts, *longopts, *datatype; + + /* skip short options without arg values (they were printed by arg_print_gnu_switch) */ + if (table[tabindex]->shortopts && + !(table[tabindex]->flag & ARG_HASVALUE)) + continue; + + shortopts = table[tabindex]->shortopts; + longopts = table[tabindex]->longopts; + datatype = table[tabindex]->datatype; + arg_cat_option(syntax, + sizeof(syntax), + shortopts, + longopts, + datatype, + table[tabindex]->flag & ARG_HASOPTVALUE); + + if (strlen(syntax) > 0) + { + /* print mandatory instances of this option */ + for (i = 0; i < table[tabindex]->mincount; i++) + fprintf(fp, " %s", syntax); + + /* print optional instances enclosed in "[..]" */ + switch ( table[tabindex]->maxcount - table[tabindex]->mincount ) + { + case 0: + break; + case 1: + fprintf(fp, " [%s]", syntax); + break; + case 2: + fprintf(fp, " [%s] [%s]", syntax, syntax); + break; + default: + fprintf(fp, " [%s]...", syntax); + break; + } + } + } + + if (suffix) + fprintf(fp, "%s", suffix); +} + + +void arg_print_syntaxv(FILE *fp, void * *argtable, const char *suffix) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + int i, tabindex; + + /* print remaining options in abbreviated style */ + for(tabindex = 0; + table[tabindex] && !(table[tabindex]->flag & ARG_TERMINATOR); + tabindex++) + { + char syntax[200] = ""; + const char *shortopts, *longopts, *datatype; + + shortopts = table[tabindex]->shortopts; + longopts = table[tabindex]->longopts; + datatype = table[tabindex]->datatype; + arg_cat_optionv(syntax, + sizeof(syntax), + shortopts, + longopts, + datatype, + table[tabindex]->flag & ARG_HASOPTVALUE, + "|"); + + /* print mandatory options */ + for (i = 0; i < table[tabindex]->mincount; i++) + fprintf(fp, " %s", syntax); + + /* print optional args enclosed in "[..]" */ + switch ( table[tabindex]->maxcount - table[tabindex]->mincount ) + { + case 0: + break; + case 1: + fprintf(fp, " [%s]", syntax); + break; + case 2: + fprintf(fp, " [%s] [%s]", syntax, syntax); + break; + default: + fprintf(fp, " [%s]...", syntax); + break; + } + } + + if (suffix) + fprintf(fp, "%s", suffix); +} + + +void arg_print_glossary(FILE *fp, void * *argtable, const char *format) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + int tabindex; + + format = format ? format : " %-20s %s\n"; + for (tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) + { + if (table[tabindex]->glossary) + { + char syntax[200] = ""; + const char *shortopts = table[tabindex]->shortopts; + const char *longopts = table[tabindex]->longopts; + const char *datatype = table[tabindex]->datatype; + const char *glossary = table[tabindex]->glossary; + arg_cat_optionv(syntax, + sizeof(syntax), + shortopts, + longopts, + datatype, + table[tabindex]->flag & ARG_HASOPTVALUE, + ", "); + fprintf(fp, format, syntax, glossary); + } + } +} + + +/** + * Print a piece of text formatted, which means in a column with a + * left and a right margin. The lines are wrapped at whitspaces next + * to right margin. The function does not indent the first line, but + * only the following ones. + * + * Example: + * arg_print_formatted( fp, 0, 5, "Some text that doesn't fit." ) + * will result in the following output: + * + * Some + * text + * that + * doesn' + * t fit. + * + * Too long lines will be wrapped in the middle of a word. + * + * arg_print_formatted( fp, 2, 7, "Some text that doesn't fit." ) + * will result in the following output: + * + * Some + * text + * that + * doesn' + * t fit. + * + * As you see, the first line is not indented. This enables output of + * lines, which start in a line where output already happened. + * + * Author: Uli Fouquet + */ +static +void arg_print_formatted( FILE *fp, + const unsigned lmargin, + const unsigned rmargin, + const char *text ) +{ + const unsigned textlen = (unsigned)strlen( text ); + unsigned line_start = 0; + unsigned line_end = textlen + 1; + const unsigned colwidth = (rmargin - lmargin) + 1; + + /* Someone doesn't like us... */ + if ( line_end < line_start ) + { fprintf( fp, "%s\n", text ); } + + while (line_end - 1 > line_start ) + { + /* Eat leading whitespaces. This is essential because while + wrapping lines, there will often be a whitespace at beginning + of line */ + while ( ISSPACE(*(text + line_start)) ) + { line_start++; } + + if ((line_end - line_start) > colwidth ) + { line_end = line_start + colwidth; } + + /* Find last whitespace, that fits into line */ + while ( ( line_end > line_start ) + && ( line_end - line_start > colwidth ) + && !ISSPACE(*(text + line_end))) + { line_end--; } + + /* Do not print trailing whitespace. If this text + has got only one line, line_end now points to the + last char due to initialization. */ + line_end--; + + /* Output line of text */ + while ( line_start < line_end ) + { + fputc(*(text + line_start), fp ); + line_start++; + } + fputc( '\n', fp ); + + /* Initialize another line */ + if ( line_end + 1 < textlen ) + { + unsigned i; + + for (i = 0; i < lmargin; i++ ) + { fputc( ' ', fp ); } + + line_end = textlen; + } + + /* If we have to print another line, get also the last char. */ + line_end++; + + } /* lines of text */ +} + +/** + * Prints the glossary in strict GNU format. + * Differences to arg_print_glossary() are: + * - wraps lines after 80 chars + * - indents lines without shortops + * - does not accept formatstrings + * + * Contributed by Uli Fouquet + */ +void arg_print_glossary_gnu(FILE *fp, void * *argtable ) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + int tabindex; + + for(tabindex = 0; !(table[tabindex]->flag & ARG_TERMINATOR); tabindex++) + { + if (table[tabindex]->glossary) + { + char syntax[200] = ""; + const char *shortopts = table[tabindex]->shortopts; + const char *longopts = table[tabindex]->longopts; + const char *datatype = table[tabindex]->datatype; + const char *glossary = table[tabindex]->glossary; + + if ( !shortopts && longopts ) + { + /* Indent trailing line by 4 spaces... */ + memset( syntax, ' ', 4 ); + *(syntax + 4) = '\0'; + } + + arg_cat_optionv(syntax, + sizeof(syntax), + shortopts, + longopts, + datatype, + table[tabindex]->flag & ARG_HASOPTVALUE, + ", "); + + /* If syntax fits not into column, print glossary in new line... */ + if ( strlen(syntax) > 25 ) + { + fprintf( fp, " %-25s %s\n", syntax, "" ); + *syntax = '\0'; + } + + fprintf( fp, " %-25s ", syntax ); + arg_print_formatted( fp, 28, 79, glossary ); + } + } /* for each table entry */ + + fputc( '\n', fp ); +} + + +/** + * Checks the argtable[] array for NULL entries and returns 1 + * if any are found, zero otherwise. + */ +int arg_nullcheck(void * *argtable) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + int tabindex; + /*printf("arg_nullcheck(%p)\n",argtable);*/ + + if (!table) + return 1; + + tabindex = 0; + do + { + /*printf("argtable[%d]=%p\n",tabindex,argtable[tabindex]);*/ + if (!table[tabindex]) + return 1; + } while(!(table[tabindex++]->flag & ARG_TERMINATOR)); + + return 0; +} + + +/* + * arg_free() is deprecated in favour of arg_freetable() due to a flaw in its design. + * The flaw results in memory leak in the (very rare) case that an intermediate + * entry in the argtable array failed its memory allocation while others following + * that entry were still allocated ok. Those subsequent allocations will not be + * deallocated by arg_free(). + * Despite the unlikeliness of the problem occurring, and the even unlikelier event + * that it has any deliterious effect, it is fixed regardless by replacing arg_free() + * with the newer arg_freetable() function. + * We still keep arg_free() for backwards compatibility. + */ +void arg_free(void * *argtable) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + int tabindex = 0; + int flag; + /*printf("arg_free(%p)\n",argtable);*/ + do + { + /* + if we encounter a NULL entry then somewhat incorrectly we presume + we have come to the end of the array. It isnt strictly true because + an intermediate entry could be NULL with other non-NULL entries to follow. + The subsequent argtable entries would then not be freed as they should. + */ + if (table[tabindex] == NULL) + break; + + flag = table[tabindex]->flag; + free(table[tabindex]); + table[tabindex++] = NULL; + + } while(!(flag & ARG_TERMINATOR)); +} + +/* frees each non-NULL element of argtable[], where n is the size of the number of entries in the array */ +void arg_freetable(void * *argtable, size_t n) +{ + struct arg_hdr * *table = (struct arg_hdr * *)argtable; + size_t tabindex = 0; + /*printf("arg_freetable(%p)\n",argtable);*/ + for (tabindex = 0; tabindex < n; tabindex++) + { + if (table[tabindex] == NULL) + continue; + + free(table[tabindex]); + table[tabindex] = NULL; + }; +} + diff --git a/client/cliparser/argtable3.h b/client/cliparser/argtable3.h new file mode 100644 index 000000000..1107de250 --- /dev/null +++ b/client/cliparser/argtable3.h @@ -0,0 +1,305 @@ +/******************************************************************************* + * This file is part of the argtable3 library. + * + * Copyright (C) 1998-2001,2003-2011,2013 Stewart Heitmann + * + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of STEWART HEITMANN nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL STEWART HEITMANN BE LIABLE FOR ANY DIRECT, + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + ******************************************************************************/ + +#ifndef ARGTABLE3 +#define ARGTABLE3 + +#include /* FILE */ +#include /* struct tm */ + +#ifdef __cplusplus +extern "C" { +#endif + +#define ARG_REX_ICASE 1 + +/* bit masks for arg_hdr.flag */ +enum +{ + ARG_TERMINATOR=0x1, + ARG_HASVALUE=0x2, + ARG_HASOPTVALUE=0x4 +}; + +typedef void (arg_resetfn)(void *parent); +typedef int (arg_scanfn)(void *parent, const char *argval); +typedef int (arg_checkfn)(void *parent); +typedef void (arg_errorfn)(void *parent, FILE *fp, int error, const char *argval, const char *progname); + + +/* +* The arg_hdr struct defines properties that are common to all arg_xxx structs. +* The argtable library requires each arg_xxx struct to have an arg_hdr +* struct as its first data member. +* The argtable library functions then use this data to identify the +* properties of the command line option, such as its option tags, +* datatype string, and glossary strings, and so on. +* Moreover, the arg_hdr struct contains pointers to custom functions that +* are provided by each arg_xxx struct which perform the tasks of parsing +* that particular arg_xxx arguments, performing post-parse checks, and +* reporting errors. +* These functions are private to the individual arg_xxx source code +* and are the pointer to them are initiliased by that arg_xxx struct's +* constructor function. The user could alter them after construction +* if desired, but the original intention is for them to be set by the +* constructor and left unaltered. +*/ +struct arg_hdr +{ + char flag; /* Modifier flags: ARG_TERMINATOR, ARG_HASVALUE. */ + const char *shortopts; /* String defining the short options */ + const char *longopts; /* String defiing the long options */ + const char *datatype; /* Description of the argument data type */ + const char *glossary; /* Description of the option as shown by arg_print_glossary function */ + int mincount; /* Minimum number of occurences of this option accepted */ + int maxcount; /* Maximum number of occurences if this option accepted */ + void *parent; /* Pointer to parent arg_xxx struct */ + arg_resetfn *resetfn; /* Pointer to parent arg_xxx reset function */ + arg_scanfn *scanfn; /* Pointer to parent arg_xxx scan function */ + arg_checkfn *checkfn; /* Pointer to parent arg_xxx check function */ + arg_errorfn *errorfn; /* Pointer to parent arg_xxx error function */ + void *priv; /* Pointer to private header data for use by arg_xxx functions */ +}; + +struct arg_rem +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ +}; + +struct arg_lit +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args */ +}; + +struct arg_int +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args */ + int *ival; /* Array of parsed argument values */ +}; + +struct arg_dbl +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args */ + double *dval; /* Array of parsed argument values */ +}; + +struct arg_str +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args */ + const char **sval; /* Array of parsed argument values */ +}; + +struct arg_rex +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args */ + const char **sval; /* Array of parsed argument values */ +}; + +struct arg_file +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of matching command line args*/ + const char **filename; /* Array of parsed filenames (eg: /home/foo.bar) */ + const char **basename; /* Array of parsed basenames (eg: foo.bar) */ + const char **extension; /* Array of parsed extensions (eg: .bar) */ +}; + +struct arg_date +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ + const char *format; /* strptime format string used to parse the date */ + int count; /* Number of matching command line args */ + struct tm *tmval; /* Array of parsed time values */ +}; + +enum {ARG_ELIMIT=1, ARG_EMALLOC, ARG_ENOMATCH, ARG_ELONGOPT, ARG_EMISSARG}; +struct arg_end +{ + struct arg_hdr hdr; /* The mandatory argtable header struct */ + int count; /* Number of errors encountered */ + int *error; /* Array of error codes */ + void **parent; /* Array of pointers to offending arg_xxx struct */ + const char **argval; /* Array of pointers to offending argv[] string */ +}; + + +/**** arg_xxx constructor functions *********************************/ + +struct arg_rem* arg_rem(const char* datatype, const char* glossary); + +struct arg_lit* arg_lit0(const char* shortopts, + const char* longopts, + const char* glossary); +struct arg_lit* arg_lit1(const char* shortopts, + const char* longopts, + const char *glossary); +struct arg_lit* arg_litn(const char* shortopts, + const char* longopts, + int mincount, + int maxcount, + const char *glossary); + +struct arg_key* arg_key0(const char* keyword, + int flags, + const char* glossary); +struct arg_key* arg_key1(const char* keyword, + int flags, + const char* glossary); +struct arg_key* arg_keyn(const char* keyword, + int flags, + int mincount, + int maxcount, + const char* glossary); + +struct arg_int* arg_int0(const char* shortopts, + const char* longopts, + const char* datatype, + const char* glossary); +struct arg_int* arg_int1(const char* shortopts, + const char* longopts, + const char* datatype, + const char *glossary); +struct arg_int* arg_intn(const char* shortopts, + const char* longopts, + const char *datatype, + int mincount, + int maxcount, + const char *glossary); + +struct arg_dbl* arg_dbl0(const char* shortopts, + const char* longopts, + const char* datatype, + const char* glossary); +struct arg_dbl* arg_dbl1(const char* shortopts, + const char* longopts, + const char* datatype, + const char *glossary); +struct arg_dbl* arg_dbln(const char* shortopts, + const char* longopts, + const char *datatype, + int mincount, + int maxcount, + const char *glossary); + +struct arg_str* arg_str0(const char* shortopts, + const char* longopts, + const char* datatype, + const char* glossary); +struct arg_str* arg_str1(const char* shortopts, + const char* longopts, + const char* datatype, + const char *glossary); +struct arg_str* arg_strn(const char* shortopts, + const char* longopts, + const char* datatype, + int mincount, + int maxcount, + const char *glossary); + +struct arg_rex* arg_rex0(const char* shortopts, + const char* longopts, + const char* pattern, + const char* datatype, + int flags, + const char* glossary); +struct arg_rex* arg_rex1(const char* shortopts, + const char* longopts, + const char* pattern, + const char* datatype, + int flags, + const char *glossary); +struct arg_rex* arg_rexn(const char* shortopts, + const char* longopts, + const char* pattern, + const char* datatype, + int mincount, + int maxcount, + int flags, + const char *glossary); + +struct arg_file* arg_file0(const char* shortopts, + const char* longopts, + const char* datatype, + const char* glossary); +struct arg_file* arg_file1(const char* shortopts, + const char* longopts, + const char* datatype, + const char *glossary); +struct arg_file* arg_filen(const char* shortopts, + const char* longopts, + const char* datatype, + int mincount, + int maxcount, + const char *glossary); + +struct arg_date* arg_date0(const char* shortopts, + const char* longopts, + const char* format, + const char* datatype, + const char* glossary); +struct arg_date* arg_date1(const char* shortopts, + const char* longopts, + const char* format, + const char* datatype, + const char *glossary); +struct arg_date* arg_daten(const char* shortopts, + const char* longopts, + const char* format, + const char* datatype, + int mincount, + int maxcount, + const char *glossary); + +struct arg_end* arg_end(int maxerrors); + + +/**** other functions *******************************************/ +int arg_nullcheck(void **argtable); +int arg_parse(int argc, char **argv, void **argtable); +void arg_print_option(FILE *fp, const char *shortopts, const char *longopts, const char *datatype, const char *suffix); +void arg_print_syntax(FILE *fp, void **argtable, const char *suffix); +void arg_print_syntaxv(FILE *fp, void **argtable, const char *suffix); +void arg_print_glossary(FILE *fp, void **argtable, const char *format); +void arg_print_glossary_gnu(FILE *fp, void **argtable); +void arg_print_errors(FILE* fp, struct arg_end* end, const char* progname); +void arg_freetable(void **argtable, size_t n); + +/**** deprecated functions, for back-compatibility only ********/ +void arg_free(void **argtable); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/client/cliparser/cliparser.c b/client/cliparser/cliparser.c new file mode 100644 index 000000000..56be2ca6a --- /dev/null +++ b/client/cliparser/cliparser.c @@ -0,0 +1,188 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2017 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Command line parser core commands +//----------------------------------------------------------------------------- + +#include "cliparser.h" +#include +#include + +void **argtable = NULL; +size_t argtableLen = 0; +char *programName = NULL; +char *programHint = NULL; +char *programHelp = NULL; +char buf[500] = {0}; + +int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp) { + argtable = NULL; + argtableLen = 0; + programName = vprogramName; + programHint = vprogramHint; + programHelp = vprogramHelp; + memset(buf, 0x00, 500); + + return 0; +} + +int CLIParserParseArg(int argc, char **argv, void* vargtable[], size_t vargtableLen, bool allowEmptyExec) { + int nerrors; + + argtable = vargtable; + argtableLen = vargtableLen; + + /* verify the argtable[] entries were allocated sucessfully */ + if (arg_nullcheck(argtable) != 0) { + /* NULL entries were detected, some allocations must have failed */ + printf("ERROR: Insufficient memory\n"); + return 2; + } + /* Parse the command line as defined by argtable[] */ + nerrors = arg_parse(argc, argv, argtable); + + /* special case: '--help' takes precedence over error reporting */ + if ((argc < 2 && !allowEmptyExec) ||((struct arg_lit *)argtable[0])->count > 0) { // help must be the first record + printf("Usage: %s", programName); + arg_print_syntaxv(stdout, argtable, "\n"); + if (programHint) + printf("%s\n\n", programHint); + arg_print_glossary(stdout, argtable, " %-20s %s\n"); + printf("\n"); + if (programHelp) + printf("%s \n", programHelp); + + return 1; + } + + /* If the parser returned any errors then display them and exit */ + if (nerrors > 0) { + /* Display the error details contained in the arg_end struct.*/ + arg_print_errors(stdout, ((struct arg_end *)argtable[vargtableLen - 1]), programName); + printf("Try '%s --help' for more information.\n", programName); + + return 3; + } + + return 0; +} + +enum ParserState { + PS_FIRST, + PS_ARGUMENT, + PS_OPTION, +}; + +#define isSpace(c)(c == ' ' || c == '\t') + +int CLIParserParseString(const char* str, void* vargtable[], size_t vargtableLen, bool allowEmptyExec) { + return CLIParserParseStringEx(str, vargtable, vargtableLen, allowEmptyExec, false); +} + +int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData) { + int argc = 0; + char *argv[200] = {NULL}; + + int len = strlen(str); + char *bufptr = buf; + char *spaceptr = NULL; + enum ParserState state = PS_FIRST; + + argv[argc++] = bufptr; + // param0 = program name + memcpy(buf, programName, strlen(programName) + 1); // with 0x00 + bufptr += strlen(programName) + 1; + if (len) + argv[argc++] = bufptr; + + // parse params + for (int i = 0; i < len; i++) { + switch(state){ + case PS_FIRST: // first char + if (!clueData || str[i] == '-'){ // first char before space is '-' - next element - option OR not "clueData" for not-option fields + state = PS_OPTION; + + if (spaceptr) { + bufptr = spaceptr; + *bufptr = 0x00; + bufptr++; + argv[argc++] = bufptr; + } + } + spaceptr = NULL; + case PS_ARGUMENT: + if (state == PS_FIRST) + state = PS_ARGUMENT; + if (isSpace(str[i])) { + spaceptr = bufptr; + state = PS_FIRST; + } + *bufptr = str[i]; + bufptr++; + break; + case PS_OPTION: + if (isSpace(str[i])){ + state = PS_FIRST; + + *bufptr = 0x00; + bufptr++; + argv[argc++] = bufptr; + break; + } + + *bufptr = str[i]; + bufptr++; + break; + } + } + + return CLIParserParseArg(argc, argv, vargtable, vargtableLen, allowEmptyExec); +} + +void CLIParserFree() { + arg_freetable(argtable, argtableLen); + argtable = NULL; + + return; +} + +// convertors +int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) { + *datalen = 0; + if (!argstr->count) + return 0; + + char buf[256] = {0}; + int ibuf = 0; + + for (int i = 0; i < argstr->count; i++) { + int len = strlen(argstr->sval[i]); + memcpy(&buf[ibuf], argstr->sval[i], len); + ibuf += len; + } + buf[ibuf] = 0; + + if (!ibuf) + return 0; + + switch(param_gethex_to_eol(buf, 0, data, maxdatalen, datalen)) { + case 1: + printf("Parameter error: Invalid HEX value.\n"); + return 1; + case 2: + printf("Parameter error: parameter too large.\n"); + return 2; + case 3: + printf("Parameter error: Hex string must have even number of digits.\n"); + return 3; + } + + return 0; +} + + + diff --git a/client/cliparser/cliparser.h b/client/cliparser/cliparser.h new file mode 100644 index 000000000..7c1ced207 --- /dev/null +++ b/client/cliparser/cliparser.h @@ -0,0 +1,37 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2017 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Command line parser core commands +//----------------------------------------------------------------------------- + +#include "argtable3.h" +#include "util.h" +#include + +#define arg_param_begin arg_lit0("hH", "help", "print this help and exit") +#define arg_param_end arg_end(20) + +#define arg_getsize(a) (sizeof(a) / sizeof(a[0])) +#define arg_get_lit(n)(((struct arg_lit*)argtable[n])->count) +#define arg_get_int(n)(((struct arg_int*)argtable[n])->ival[0]) +#define arg_get_str(n)((struct arg_str*)argtable[n]) +#define arg_get_str_len(n)(strlen(((struct arg_str*)argtable[n])->sval[0])) + +#define arg_strx1(shortopts, longopts, datatype, glossary) (arg_strn((shortopts), (longopts), (datatype), 1, 250, (glossary))) +#define arg_strx0(shortopts, longopts, datatype, glossary) (arg_strn((shortopts), (longopts), (datatype), 0, 250, (glossary))) + +#define CLIExecWithReturn(cmd, atbl, ifempty) if (CLIParserParseString(cmd, atbl, arg_getsize(atbl), ifempty)){CLIParserFree();return 0;} +#define CLIGetStrBLessWithReturn(paramnum, data, datalen, delta) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data) - (delta), datalen)) {CLIParserFree();return 1;} +#define CLIGetStrWithReturn(paramnum, data, datalen) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree();return 1;} + +extern int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp); +extern int CLIParserParseString(const char* str, void* argtable[], size_t vargtableLen, bool allowEmptyExec); +extern int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData); +extern int CLIParserParseArg(int argc, char **argv, void* argtable[], size_t vargtableLen, bool allowEmptyExec); +extern void CLIParserFree(); + +extern int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 418de8ec5..fc24356a5 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -668,6 +668,95 @@ int CmdHF14ASniff(const char *Cmd) { return 0; } +int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { + uint16_t cmdc = 0; + *dataoutlen = 0; + + if (activateField) { + UsbCommand resp; + + // Anticollision + SELECT card + UsbCommand ca = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; + SendCommand(&ca); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + PrintAndLogEx(ERROR, "Proxmark connection timeout."); + return 1; + } + + // check result + if (resp.arg[0] == 0) { + PrintAndLogEx(NORMAL, "No card in field."); + return 1; + } + + if (resp.arg[0] != 1 && resp.arg[0] != 2) { + PrintAndLogEx(ERROR, "Card not in iso14443-4. res=%d.", resp.arg[0]); + return 1; + } + + if (resp.arg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision + // get ATS + UsbCommand cr = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0}}; + uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 + memcpy(cr.d.asBytes, rats, 2); + SendCommand(&cr); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + PrintAndLogEx(ERROR, "Proxmark connection timeout."); + return 1; + } + + if (resp.arg[0] <= 0) { // ats_len + PrintAndLogEx(ERROR, "Can't get ATS."); + return 1; + } + } + } + + if (leaveSignalON) + cmdc |= ISO14A_NO_DISCONNECT; + + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF), 0}}; + memcpy(c.d.asBytes, datain, datainlen); + SendCommand(&c); + + uint8_t *recv; + UsbCommand resp; + + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + recv = resp.d.asBytes; + int iLen = resp.arg[0]; + + *dataoutlen = iLen - 2; + if (*dataoutlen < 0) + *dataoutlen = 0; + + if (maxdataoutlen && *dataoutlen > maxdataoutlen) { + PrintAndLogEx(ERROR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); + return 2; + } + + memcpy(dataout, recv, *dataoutlen); + + if(!iLen) { + PrintAndLogEx(ERROR, "No card response."); + return 1; + } + + // CRC Check + if (iLen == -1) { + PrintAndLogEx(ERROR, "ISO 14443A CRC error."); + return 3; + } + + + } else { + PrintAndLogEx(ERROR, "Reply timeout."); + return 4; + } + + return 0; +} + int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { uint16_t cmdc = 0; diff --git a/client/cmdhf14a.h b/client/cmdhf14a.h index b2ae5896e..310a2f7d5 100644 --- a/client/cmdhf14a.h +++ b/client/cmdhf14a.h @@ -51,6 +51,7 @@ extern int CmdHF14AAntiFuzz(const char *cmd); extern char* getTagInfo(uint8_t uid); extern int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); +extern int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); extern int usage_hf_14a_sim(void); extern int usage_hf_14a_sniff(void); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 5af1922af..d76699045 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -3067,6 +3067,149 @@ out: return 0; } +int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){ + uint8_t iiv[16] = {0}; + if (iv) + memcpy(iiv, iv, 16); + + aes_context aes; + aes_init(&aes); + if (aes_setkey_enc(&aes, key, 128)) + return 1; + if (aes_crypt_cbc(&aes, AES_ENCRYPT, length, iiv, input, output)) + return 2; + aes_free(&aes); + + return 0; +} + +int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){ + uint8_t iiv[16] = {0}; + if (iv) + memcpy(iiv, iv, 16); + + aes_context aes; + aes_init(&aes); + if (aes_setkey_dec(&aes, key, 128)) + return 1; + if (aes_crypt_cbc(&aes, AES_DECRYPT, length, iiv, input, output)) + return 2; + aes_free(&aes); + + return 0; +} + +int CmdHF14AMfAuth4(const char *cmd) { + uint8_t keyn[20] = {0}; + int keynlen = 0; + uint8_t key[16] = {0}; + int keylen = 0; + uint8_t data[257] = {0}; + int datalen = 0; + + uint8_t Rnd1[17] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00}; + uint8_t Rnd2[17] = {0}; + + + CLIParserInit("hf mf auth4", + "Executes AES authentication command in ISO14443-4", + "Usage:\n\thf mf auth4 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n" + "\thf mf auth4 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -> executes authentication\n"); + + void* argtable[] = { + arg_param_begin, + arg_str1(NULL, NULL, "", NULL), + arg_str1(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + CLIGetStrWithReturn(1, keyn, &keynlen); + CLIGetStrWithReturn(2, key, &keylen); + CLIParserFree(); + + if (keynlen != 2) { + PrintAndLogEx(ERROR, " must be 2 bytes long instead of: %d", keynlen); + return 1; + } + + if (keylen != 16) { + PrintAndLogEx(ERROR, " must be 16 bytes long instead of: %d", keylen); + return 1; + } + + uint8_t cmd1[] = {0x0a, 0x00, 0x70, keyn[1], keyn[0], 0x00}; + int res = ExchangeRAW14a(cmd1, sizeof(cmd1), true, true, data, sizeof(data), &datalen); + if (res) { + PrintAndLog("ERROR exchande raw error: %d", res); + return 2; + } + + PrintAndLog("phase2: %s", sprint_hex(cmd2, 35)); + + res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, false, data, sizeof(data), &datalen); + if (res) { + PrintAndLogEx(ERROR, "exchande raw error: %d", res); + DropField(); + return 4; + } + + PrintAndLog(" #include #include +#include #include "proxmark3.h" #include "iso14443crc.h" #include "ui.h" @@ -29,6 +30,7 @@ #include "util_posix.h" // msclock #include "mifaredefault.h" // mifare default key array #include "cmdhf14a.h" // dropfield +#include "cliparser/cliparser.h" // argtable extern int CmdHFMF(const char *Cmd); diff --git a/client/obj/cliparser/.dummy b/client/obj/cliparser/.dummy new file mode 100644 index 000000000..e69de29bb diff --git a/client/reveng/cli.c b/client/reveng/cli.c index 643d70b74..882229d90 100644 --- a/client/reveng/cli.c +++ b/client/reveng/cli.c @@ -53,7 +53,7 @@ #include #include -#include "getopt.h" +#include "cliparser/argtable3.h" #ifdef _WIN32 # include # include From de31f052848be754d991d67c6b60114ac9461699 Mon Sep 17 00:00:00 2001 From: merlokk Date: Thu, 11 Oct 2018 16:54:50 +0300 Subject: [PATCH 0083/1938] ok, compiles) --- client/cliparser/argtable3.c | 80 +----------------------------------- client/reveng/cli.c | 4 +- 2 files changed, 3 insertions(+), 81 deletions(-) diff --git a/client/cliparser/argtable3.c b/client/cliparser/argtable3.c index 38ce7a24f..abffa9dc2 100644 --- a/client/cliparser/argtable3.c +++ b/client/cliparser/argtable3.c @@ -166,86 +166,8 @@ void dbg_printf(const char *fmt, ...) va_end(args); } -/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ -/* $FreeBSD$ */ +#include "getopt.h" -/*- - * SPDX-License-Identifier: BSD-2-Clause-NetBSD - * - * Copyright (c) 2000 The NetBSD Foundation, Inc. - * All rights reserved. - * - * This code is derived from software contributed to The NetBSD Foundation - * by Dieter Baron and Thomas Klausner. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * - * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS - * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED - * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR - * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS - * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR - * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF - * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS - * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN - * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGE. - */ - -#ifndef _GETOPT_H_ -#define _GETOPT_H_ - -#include - -/* - * GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension. - * getopt() is declared here too for GNU programs. - */ -#define no_argument 0 -#define required_argument 1 -#define optional_argument 2 - -struct option { - /* name of long option */ - const char *name; - /* - * one of no_argument, required_argument, and optional_argument: - * whether option takes an argument - */ - int has_arg; - /* if not NULL, set *flag to val when option found */ - int *flag; - /* if flag not NULL, value to set *flag to; else return value */ - int val; -}; - -__BEGIN_DECLS -int getopt_long(int, char * const *, const char *, - const struct option *, int *); -int getopt_long_only(int, char * const *, const char *, - const struct option *, int *); -#ifndef _GETOPT_DECLARED -#define _GETOPT_DECLARED -int getopt(int, char * const [], const char *); - -extern char *optarg; /* getopt(3) external variables */ -extern int optind, opterr, optopt; -#endif -#ifndef _OPTRESET_DECLARED -#define _OPTRESET_DECLARED -extern int optreset; /* getopt(3) external variable */ -#endif -__END_DECLS - -#endif /* !_GETOPT_H_ */ /* $Id: getopt_long.c,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $ */ /* $OpenBSD: getopt_long.c,v 1.23 2007/10/31 12:34:57 chl Exp $ */ /* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ diff --git a/client/reveng/cli.c b/client/reveng/cli.c index 882229d90..f4b40856a 100644 --- a/client/reveng/cli.c +++ b/client/reveng/cli.c @@ -53,7 +53,7 @@ #include #include -#include "cliparser/argtable3.h" +#include "cliparser/getopt.h" #ifdef _WIN32 # include # include @@ -96,7 +96,7 @@ int reveng_main(int argc, char *argv[]) { SETBMP(); - pos=0; +// pos=0; --- not in this ver of getopt optind=1; do { c=getopt(argc, argv, "?A:BDFGLMP:SVXa:bcdefhi:k:lm:p:q:rstuvw:x:yz"); From 4563210a96a1bcd27307ec2bf2f89aba23c4c892 Mon Sep 17 00:00:00 2001 From: merlokk Date: Thu, 11 Oct 2018 16:55:21 +0300 Subject: [PATCH 0084/1938] forgot h file --- client/cliparser/getopt.h | 80 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 80 insertions(+) create mode 100644 client/cliparser/getopt.h diff --git a/client/cliparser/getopt.h b/client/cliparser/getopt.h new file mode 100644 index 000000000..789b4d1d4 --- /dev/null +++ b/client/cliparser/getopt.h @@ -0,0 +1,80 @@ +/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ +/* $FreeBSD$ */ + +/*- + * SPDX-License-Identifier: BSD-2-Clause-NetBSD + * + * Copyright (c) 2000 The NetBSD Foundation, Inc. + * All rights reserved. + * + * This code is derived from software contributed to The NetBSD Foundation + * by Dieter Baron and Thomas Klausner. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR + * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS + * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR + * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +#ifndef _GETOPT_H_ +#define _GETOPT_H_ + +#include + +/* + * GNU-like getopt_long()/getopt_long_only() with 4.4BSD optreset extension. + * getopt() is declared here too for GNU programs. + */ +#define no_argument 0 +#define required_argument 1 +#define optional_argument 2 + +struct option { + /* name of long option */ + const char *name; + /* + * one of no_argument, required_argument, and optional_argument: + * whether option takes an argument + */ + int has_arg; + /* if not NULL, set *flag to val when option found */ + int *flag; + /* if flag not NULL, value to set *flag to; else return value */ + int val; +}; + +__BEGIN_DECLS +int getopt_long(int, char * const *, const char *, + const struct option *, int *); +int getopt_long_only(int, char * const *, const char *, + const struct option *, int *); +#ifndef _GETOPT_DECLARED +#define _GETOPT_DECLARED +int getopt(int, char * const [], const char *); + +extern char *optarg; /* getopt(3) external variables */ +extern int optind, opterr, optopt; +#endif +#ifndef _OPTRESET_DECLARED +#define _OPTRESET_DECLARED +extern int optreset; /* getopt(3) external variable */ +#endif +__END_DECLS + +#endif /* !_GETOPT_H_ */ From 375aada810ebc73d2e3714ae77f9f7c33fe7cccc Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 13 Oct 2018 11:26:40 +0200 Subject: [PATCH 0085/1938] more keys --- client/default_keys.dic | 11 +++++++++++ client/default_pwd.dic | 2 ++ 2 files changed, 13 insertions(+) diff --git a/client/default_keys.dic b/client/default_keys.dic index 69272317f..2f7e459e4 100644 --- a/client/default_keys.dic +++ b/client/default_keys.dic @@ -573,6 +573,17 @@ d58023ba2bdc,-- charlie 60012e9ba3fa # de1fcbec764b +81bfbe8cacba +bff123126c9b +2f47741062a0 +b4166b0a27ea +a170d9b59f95 +400bc9be8976 +d80511fc2ab4 +1fcef3005bcf +bb467463acd6 +e67c8010502d +ff58ba1b4478 # Data from https://pastebin.com/Kz8xp4ev 2aa05ed1856f 73068f118c13 diff --git a/client/default_pwd.dic b/client/default_pwd.dic index 2f18b5ae7..9ef5b9e1e 100644 --- a/client/default_pwd.dic +++ b/client/default_pwd.dic @@ -10,6 +10,8 @@ 314159E0, # ref. http://www.proxmark.org/forum/viewtopic.php?pid=28115#p28115 AA55BBBB, +# ref. http://www.proxmark.org/forum/viewtopic.php?pid=33376#p33376 +A5B4C3D2, # ref. http://www.proxmark.org/forum/viewtopic.php?pid=30379#p30379 1C0B5848, # paxton bullit? From 2be56183c0075b02107f5f0171f7e68881d1a55d Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 14 Oct 2018 12:02:26 +0200 Subject: [PATCH 0086/1938] fix: error enum rename --- client/cmdhf14a.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index fc24356a5..de1854630 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -679,7 +679,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav UsbCommand ca = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; SendCommand(&ca); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(ERROR, "Proxmark connection timeout."); + PrintAndLogEx(ERR, "Proxmark connection timeout."); return 1; } @@ -690,7 +690,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav } if (resp.arg[0] != 1 && resp.arg[0] != 2) { - PrintAndLogEx(ERROR, "Card not in iso14443-4. res=%d.", resp.arg[0]); + PrintAndLogEx(ERR, "Card not in iso14443-4. res=%d.", resp.arg[0]); return 1; } @@ -701,12 +701,12 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav memcpy(cr.d.asBytes, rats, 2); SendCommand(&cr); if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(ERROR, "Proxmark connection timeout."); + PrintAndLogEx(ERR, "Proxmark connection timeout."); return 1; } if (resp.arg[0] <= 0) { // ats_len - PrintAndLogEx(ERROR, "Can't get ATS."); + PrintAndLogEx(ERR, "Can't get ATS."); return 1; } } @@ -731,26 +731,26 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav *dataoutlen = 0; if (maxdataoutlen && *dataoutlen > maxdataoutlen) { - PrintAndLogEx(ERROR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); + PrintAndLogEx(ERR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); return 2; } memcpy(dataout, recv, *dataoutlen); if(!iLen) { - PrintAndLogEx(ERROR, "No card response."); + PrintAndLogEx(ERR, "No card response."); return 1; } // CRC Check if (iLen == -1) { - PrintAndLogEx(ERROR, "ISO 14443A CRC error."); + PrintAndLogEx(ERR, "ISO 14443A CRC error."); return 3; } } else { - PrintAndLogEx(ERROR, "Reply timeout."); + PrintAndLogEx(ERR, "Reply timeout."); return 4; } From bd34d145f196d653b7962948de6aeba631b4dc05 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 14 Oct 2018 12:05:45 +0200 Subject: [PATCH 0087/1938] fix: error enum rename --- client/cmdhfmf.c | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index d76699045..f40db51cf 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -3129,12 +3129,12 @@ int CmdHF14AMfAuth4(const char *cmd) { CLIParserFree(); if (keynlen != 2) { - PrintAndLogEx(ERROR, " must be 2 bytes long instead of: %d", keynlen); + PrintAndLogEx(ERR, " must be 2 bytes long instead of: %d", keynlen); return 1; } if (keylen != 16) { - PrintAndLogEx(ERROR, " must be 16 bytes long instead of: %d", keylen); + PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); return 1; } @@ -3148,22 +3148,22 @@ int CmdHF14AMfAuth4(const char *cmd) { PrintAndLog(" Date: Tue, 16 Oct 2018 19:39:29 +0000 Subject: [PATCH 0088/1938] Include the HF_BOG standalone mode --- armsrc/Makefile | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/armsrc/Makefile b/armsrc/Makefile index 8f0cd025e..8a576f001 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -24,7 +24,7 @@ APP_CFLAGS = -DWITH_CRC \ -DWITH_FLASH \ -DWITH_SMARTCARD \ -DWITH_HFSNOOP \ - -DWITH_LF_SAMYRUN \ + -DWITH_HF_BOG \ -DWITH_FPC \ -fno-strict-aliasing -ffunction-sections -fdata-sections @@ -42,6 +42,7 @@ APP_CFLAGS = -DWITH_CRC \ # -DWITH_HF_YOUNG # -DWITH_HF_MATTYRUN # -DWITH_HF_COLIN +# -DWITH_HF_BOG SRC_LCD = fonts.c LCD.c @@ -106,6 +107,10 @@ endif ifneq (,$(findstring WITH_HF_COLIN,$(APP_CFLAGS))) SRC_STANDALONE = vtsend.c hf_colin.c endif +# WITH_HF_BOG +ifneq (,$(findstring WITH_HF_BOG,$(APP_CFLAGS))) + SRC_STANDALONE = hf_bog.c +endif #the FPGA bitstream files. Note: order matters! FPGA_BITSTREAMS = fpga_lf.bit fpga_hf.bit From 8079613b37640b8f940bf412143b4ec6d9d7cbb6 Mon Sep 17 00:00:00 2001 From: bogiton <34060135+bogiton@users.noreply.github.com> Date: Tue, 16 Oct 2018 19:41:05 +0000 Subject: [PATCH 0089/1938] Add check for the HF_BOG directive for RunMod --- armsrc/appmain.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index a84a33d48..79eba9cf8 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1530,7 +1530,7 @@ void __attribute__((noreturn)) AppMain(void) { RunMod(); #endif -#if defined (WITH_ISO14443a) && ( defined (WITH_HF_YOUNG) || defined(WITH_HF_COLIN) || defined(WITH_HF_MATTYRUN) ) +#if defined (WITH_ISO14443a) && ( defined (WITH_HF_YOUNG) || defined(WITH_HF_COLIN) || defined(WITH_HF_MATTYRUN) || defined(WITH_HF_BOG) ) RunMod(); #endif From 1c2af2a5ed9bb376898178f6de1f2ff7a1f17f97 Mon Sep 17 00:00:00 2001 From: bogiton <34060135+bogiton@users.noreply.github.com> Date: Tue, 16 Oct 2018 19:50:18 +0000 Subject: [PATCH 0090/1938] Added hf_bog standalone --- armsrc/Standalone/hf_bog.c | 366 +++++++++++++++++++++++++++++++++++++ armsrc/Standalone/hf_bog.h | 31 ++++ 2 files changed, 397 insertions(+) create mode 100644 armsrc/Standalone/hf_bog.c create mode 100644 armsrc/Standalone/hf_bog.h diff --git a/armsrc/Standalone/hf_bog.c b/armsrc/Standalone/hf_bog.c new file mode 100644 index 000000000..5a279ebd9 --- /dev/null +++ b/armsrc/Standalone/hf_bog.c @@ -0,0 +1,366 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// main code for standalone HF Sniff (and ULC/NTAG/ULEV1 pwd storing) +//----------------------------------------------------------------------------- +#include "hf_bog.h" + +#define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8) +#define DELAY_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8) +#define MAX_PWDS_PER_SESSION 15 + +uint8_t ReadCounterFromFlash() { + uint8_t mem = 0; + + uint8_t isok = Flash_ReadData(0, &mem, 1); + if (isok == 1) + { + return mem; + } + + Dbprintf("Reading of counter from flashmem failed"); + return -1; +} + +uint8_t* ReadDataFromFlash(uint8_t datacnt) { + + uint16_t isok = 0; + + if (!datacnt) + { + uint8_t *tmp = BigBuf_malloc(4); + for (int i=0;i<4;i++) + tmp[i] = 0x00; + return tmp; + } + + size_t size = (datacnt + 1) * 4; + uint8_t *mem = BigBuf_malloc(size); + + isok = Flash_ReadData(0, mem, (datacnt + 1) * 4); + if (isok == ((datacnt + 1) * 4)) + { + Dbprintf("[OK] Data recovered from flashmem"); + return mem; + } + + Dbprintf("FlashMem reading failed | isok = %d", isok); + SpinDelay(100); + return 0; +} + +/* +void WriteDataToFlash(uint8_t *data, size_t size) +{ + uint8_t isok = 0; + + isok = Flash_WriteData(0, data, size); + + if (!isok) + { + Dbprintf("FlashMem write failed"); + SpinDelay(100); + + return; + } + + Dbprintf("[OK] Data written to flash!"); +} +*/ + +void EraseMemory() +{ + if (!FlashInit()){ + return; + } + + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); + Flash_Erase4k(0,0); + + Dbprintf("[OK] Erased flash!"); + FlashStop(); + SpinDelay(100); +} + + +void WriteDataToFlash(uint8_t* data, size_t size) +{ + uint8_t isok = 0; + uint16_t res = 0; + uint32_t len = size; + uint32_t bytes_sent = 0; + uint32_t bytes_remaining = len; + + uint8_t buff[PAGESIZE]; + + if (!FlashInit()){ + return; + } + + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); + Flash_Erase4k(0,0); + + while (bytes_remaining > 0) + { + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); + + uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); + + memcpy(buff, data + bytes_sent, bytes_in_packet); + + bytes_remaining -= bytes_in_packet; + res = Flash_WriteDataCont(bytes_sent, buff, bytes_in_packet); + bytes_sent += bytes_in_packet; + + isok = (res == bytes_in_packet) ? 1 : 0; + + if (!isok) + { + Dbprintf("FlashMem write failed [offset %u]", bytes_sent); + SpinDelay(100); + + return; + } + } + + Dbprintf("[OK] Data written to flash! [0-to offset %u]", bytes_sent); + FlashStop(); + + return; +} + +void RAMFUNC SniffAndStore(uint8_t param) { + + // Array to store the authpwds + uint8_t *capturedPwds = BigBuf_malloc(4 * MAX_PWDS_PER_SESSION); + + SpinDelay(500); + + /* This is actually copied from SniffIso14443a */ + + iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); + + // Allocate memory from BigBuf for some buffers + // free all previous allocations first + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); + + // The command (reader -> tag) that we're receiving. + uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); + uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE); + + // The response (tag -> reader) that we're receiving. + uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE); + uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE); + + // The DMA buffer, used to stream samples from the FPGA + uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); + uint8_t *data = dmaBuf; + + uint8_t previous_data = 0; + int dataLen = 0; + bool TagIsActive = false; + bool ReaderIsActive = false; + + // Set up the demodulator for tag -> reader responses. + DemodInit(receivedResp, receivedRespPar); + + // Set up the demodulator for the reader -> tag commands + UartInit(receivedCmd, receivedCmdPar); + + // Setup and start DMA. + if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE) ){ + if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); + return; + } + + tUart* uart = GetUart(); + tDemod* demod = GetDemod(); + + // We won't start recording the frames that we acquire until we trigger; + // a good trigger condition to get started is probably when we see a + // response from the tag. + // triggered == false -- to wait first for card + bool triggered = !(param & 0x03); + + uint32_t rsamples = 0; + + // Current captured passwords counter + uint8_t auth_attempts = 0; + + SpinDelay(50); + + // loop and listen + while (!BUTTON_PRESS()) { + WDT_HIT(); + LED_A_ON(); + + int register readBufDataP = data - dmaBuf; + int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; + if (readBufDataP <= dmaBufDataP) + dataLen = dmaBufDataP - readBufDataP; + else + dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; + + // test for length of buffer + if (dataLen > DMA_BUFFER_SIZE) { // TODO: Check if this works properly + Dbprintf("[!] blew circular buffer! | datalen %u", dataLen); + break; + } + if (dataLen < 1) continue; + + // primary buffer was stopped( <-- we lost data! + if (!AT91C_BASE_PDC_SSC->PDC_RCR) { + AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf; + AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE; + //Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary + } + // secondary buffer sets as primary, secondary buffer was stopped + if (!AT91C_BASE_PDC_SSC->PDC_RNCR) { + AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; + AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; + } + + LED_A_OFF(); + + // Need two samples to feed Miller and Manchester-Decoder + if (rsamples & 0x01) { + + if (!TagIsActive) { // no need to try decoding reader data if the tag is sending + uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4); + if (MillerDecoding(readerdata, (rsamples-1)*4)) { + LED_C_ON(); + + // check - if there is a short 7bit request from reader + if ((!triggered) && (param & 0x02) && (uart->len == 1) && (uart->bitCount == 7)) triggered = true; + + if (triggered) { + if ((receivedCmd) && ((receivedCmd[0] == MIFARE_ULEV1_AUTH) || (receivedCmd[0] == MIFARE_ULC_AUTH_1))) { + Dbprintf("PWD-AUTH KEY: 0x%02x%02x%02x%02x", receivedCmd[1], receivedCmd[2], receivedCmd[3], receivedCmd[4]); + + // temporarily save the captured pwd in our array + memcpy(&capturedPwds[4 * auth_attempts], receivedCmd+1, 4); + auth_attempts++; + } + + if (!LogTrace(receivedCmd, + uart->len, + uart->startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, + uart->endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, + uart->parity, + true)) break; + } + /* ready to receive another command. */ + UartReset(); + /* reset the demod code, which might have been */ + /* false-triggered by the commands from the reader. */ + DemodReset(); + LED_B_OFF(); + } + ReaderIsActive = (uart->state != STATE_UNSYNCD); + } + + // no need to try decoding tag data if the reader is sending - and we cannot afford the time + if (!ReaderIsActive) { + uint8_t tagdata = (previous_data << 4) | (*data & 0x0F); + if (ManchesterDecoding(tagdata, 0, (rsamples-1)*4)) { + LED_B_ON(); + + if (!LogTrace(receivedResp, + demod->len, + demod->startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, + demod->endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, + demod->parity, + false)) break; + + if ((!triggered) && (param & 0x01)) triggered = true; + + // ready to receive another response. + DemodReset(); + // reset the Miller decoder including its (now outdated) input buffer + UartReset(); + //UartInit(receivedCmd, receivedCmdPar); + LED_C_OFF(); + } + TagIsActive = (demod->state != DEMOD_UNSYNCD); + } + } + + previous_data = *data; + rsamples++; + data++; + if (data == dmaBuf + DMA_BUFFER_SIZE) { + data = dmaBuf; + } + } // end main loop + + FpgaDisableSscDma(); + set_tracing(false); + + Dbprintf("Stopped sniffing"); + + SpinDelay(200); + + // Write stuff to flash + if (auth_attempts > 0) { + Dbprintf("[!] auth_attempts = %u", auth_attempts); + + // Read from flash the counter of pwds (to be used as flash mem offset) + uint8_t pwdcnt = 0; + pwdcnt = ReadCounterFromFlash(); + if (pwdcnt == 255) { + // Same as zero + pwdcnt = 0; + } + Dbprintf("[!] PWDs Offset = %u", pwdcnt); + + uint8_t *previousdata = ReadDataFromFlash(pwdcnt); + + // total size = (pwdcnt+1)*4 + 4 * auth_attempts + size_t total_size = (pwdcnt+1)*4 + 4 * auth_attempts; + // create new bigbuf to hold all data + uint8_t *total_data = BigBuf_malloc(total_size); + + // Add the previousdata array into total_data array + memcpy(total_data, previousdata, sizeof(*previousdata) * ((pwdcnt+1)*4)); + + // Copy bytes of capturedPwds immediately following bytes of previousdata + memcpy(total_data + ((pwdcnt+1)*4), capturedPwds, sizeof(*capturedPwds) * (4 * auth_attempts)); + + // change the counter byte + //memset (total_data,pwdcnt + auth_attempts,1); + total_data[0] = (uint8_t)(pwdcnt + auth_attempts); + + //EraseMemory(); + + //for (int i=0;i<(pwdcnt+1)*4 + 4 * auth_attempts;i++) + // Dbprintf("[!] total_data[%d] = 0x%02x", i, total_data[i]); + + //Flash_WriteData(0, total_data, (pwdcnt+1)*4 + 4 * auth_attempts); + WriteDataToFlash(total_data, (pwdcnt+1)*4 + 4 * auth_attempts); + + SpinDelay(200); + } +} + +void RunMod() +{ + Dbprintf("Sniffing started"); + SpinDelay(500); + + // param: + // bit 0 - trigger from first card answer + // bit 1 - trigger from first reader 7-bit request + SniffAndStore(0); + + LEDsoff(); + + SpinDelay(300); +} + diff --git a/armsrc/Standalone/hf_bog.h b/armsrc/Standalone/hf_bog.h new file mode 100644 index 000000000..8b7d4c695 --- /dev/null +++ b/armsrc/Standalone/hf_bog.h @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// StandAlone Mod +//----------------------------------------------------------------------------- + +#ifndef FALSE +#define FALSE 0 +#endif + +#ifndef __HF_BOG_H +#define __HF_BOG_H + +#include "proxmark3.h" +#include "mifareutil.h" +#include "iso14443a.h" +#include "protocols.h" +#include "util.h" +#include "standalone.h" // standalone definitions +#include // for bool +#include +#include +#include "apps.h" +#include "printf.h" + +#include "parity.h" +#include "random.h" + +#endif /* __HF_BOG_H */ From 3690914405c3294d754bdd773ee0a70f8f6d5e4d Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 19 Oct 2018 21:52:23 +0200 Subject: [PATCH 0091/1938] another cloner --- client/default_pwd.dic | 1 + 1 file changed, 1 insertion(+) diff --git a/client/default_pwd.dic b/client/default_pwd.dic index 9ef5b9e1e..cdc99b5c4 100644 --- a/client/default_pwd.dic +++ b/client/default_pwd.dic @@ -2,6 +2,7 @@ # ref. http://www.proxmark.org/forum/viewtopic.php?id=2022 51243648, 000D8787, +19920427, # ref. http://kazus.ru/forums/showpost.php?p=1045937&postcount=77 05D73B9F, # ref. http://www.proxmark.org/forum/viewtopic.php?= From 58ea9caeae7e02966ecddecc927016b600544dc2 Mon Sep 17 00:00:00 2001 From: Pavel Zhovner Date: Sun, 21 Oct 2018 18:56:27 +0300 Subject: [PATCH 0092/1938] Added full key set of russian Troika card. Dupicates removed, added missed commas --- client/default_keys.dic | 148 ++++++++++++++++++++++++---------------- 1 file changed, 90 insertions(+), 58 deletions(-) diff --git a/client/default_keys.dic b/client/default_keys.dic index 2f7e459e4..a77418df8 100644 --- a/client/default_keys.dic +++ b/client/default_keys.dic @@ -173,7 +173,6 @@ B39AE17435DC, # # Data from: http://pastebin.com/gQ6nk38G D39BB83F5297, -A27D3804C259, 85675B200017, 528C9DFFE28C, C82EC29E3235, @@ -202,15 +201,10 @@ B0C9DD55DD4D, A0B0C0D0E0F0, A1B1C1D1E1F1, # -# Data from: msk three -ae3d65a3dad4, -a73f5dc1d333, -# # Data from: msk social 2735fc181807, 2aba9519f574, 84fd7f7a12b6, -73068f118c13, 186d8c4b93f9, 3a4bba8adaf0, 8765b17968a2, @@ -223,7 +217,6 @@ a73f5dc1d333, bf23a53c1f63, cb9a1f2d7368, c7c0adb3284f, -2b7f3253fac5, 9f131d8c2057, 67362d90f973, 6202a38f69e2, @@ -335,11 +328,8 @@ a56c2df9a26d, # # Data from: https://pastebin.com/vbwast74 # -2031d1e57a3b, 68d3f7307c89, -9189449ea24e, 568c9083f71c,--Smart Rider. Western Australian Public Transport Cards -53c11f90822a, # Vigik Keys # Various sources : # * https://github.com/DumpDos/Vigik @@ -492,7 +482,6 @@ f7a39753d018, # # Data from TransPert 2031d1e57a3b, -68d3f7307c89, 53c11f90822a, 9189449ea24e, 568c9083f71c, @@ -566,61 +555,104 @@ d58023ba2bdc,-- charlie 2548a443df28,-- charlie 2ed3b15e7c0f,-- charlie # -# Data from forum -6a1987c40a21 -7f33625bc129 +60012e9ba3fa, # -60012e9ba3fa -# -de1fcbec764b -81bfbe8cacba -bff123126c9b -2f47741062a0 -b4166b0a27ea -a170d9b59f95 -400bc9be8976 -d80511fc2ab4 -1fcef3005bcf -bb467463acd6 -e67c8010502d -ff58ba1b4478 +de1fcbec764b, +81bfbe8cacba, +bff123126c9b, +2f47741062a0, +b4166b0a27ea, +a170d9b59f95, +400bc9be8976, +d80511fc2ab4, +1fcef3005bcf, +bb467463acd6, +e67c8010502d, +ff58ba1b4478, # Data from https://pastebin.com/Kz8xp4ev -2aa05ed1856f -73068f118c13 -2b7f3253fac5 -eaac88e5dc99 -ae3d65a3dad4 -a73f5dc1d333 -a82607b01c0d -2910989b6880 -0f1c63013dba -fbf225dc5d58 +fbf225dc5d58, # # Data https://pastebin.com/BEm6bdAE # vingcard.txt -4708111c8604 -3d50d902ea48 -96a301bce267 -6700f10fec09 -7a09cc1db70a -560f7cff2d81 -66b31e64ca4b -9e53491f685b -3a09911d860c -8a036920ac0c -361f69d2c462 -d9bcde7fc489 -0c03a720f208 -6018522fac02 +4708111c8604, +3d50d902ea48, +96a301bce267, +6700f10fec09, +7a09cc1db70a, +560f7cff2d81, +66b31e64ca4b, +9e53491f685b, +3a09911d860c, +8a036920ac0c, +361f69d2c462, +d9bcde7fc489, +0c03a720f208, +6018522fac02, # # Data from https://pastebin.com/4t2yFMgt # Mifare technische Universität Graz TUG -D58660D1ACDE -50A11381502C -C01FC822C6E5 -0854BF31111E +D58660D1ACDE, +50A11381502C, +C01FC822C6E5, +0854BF31111E, # More keys: -8a19d40cf2b5 -ae8587108640 +8a19d40cf2b5, +ae8587108640, 8829DA9DAF76,-- Meriton Suites Syd, Aus ;). Not sure where this came from... 135b88a94b8b, SafLock standalone door locks. +# +# Russian Troika card +08B386463229, +0E8F64340BA4, +0F1C63013DBA, +2AA05ED1856F, +2B7F3253FAC5, +69A32F1C2F19, +73068F118C13, +9BECDF3D9273, +A73F5DC1D333, +A82607B01C0D, +AE3D65A3DAD4, +CD4C61C26E3D, +D3EAFB5DF46D, +E35173494A81, +FBC2793D540B, +5125974CD391, +ECF751084A80, +7545DF809202, +AB16584C972A, +7A38E3511A38, +C8454C154CB5, +04C297B91308, +EFCB0E689DB3, +07894FFEC1D6, +FBA88F109B32, +2FE3CB83EA43, +B90DE525CEB6, +1CC219E9FEC1, +A74332F74994, +764CD061F1E6, +8F79C4FD8A01, +CD64E567ABCD, +CE26ECB95252, +ABA208516740, +9868925175BA, +16A27AF45407, +372CC880F216, +3EBCE0925B2F, +73E5B9D9D3A4, +0DB520C78C1C, +70D901648CB9, +C11F4597EFB5, +B39D19A280DF, +403D706BA880, +7038CD25C408, +6B02733BB6EC, +EAAC88E5DC99, +4ACEC1205D75, +2910989B6880, +31C7610DE3B0, +5EFBAECEF46B, +F8493407799D, +6B8BD9860763, +D3A297DC2698, \ No newline at end of file From 22fb92f9c869c144eb2d8475fc735df6c74248a6 Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 21 Oct 2018 19:51:22 +0200 Subject: [PATCH 0093/1938] sugar --- armsrc/flashmem.c | 16 ++-------------- 1 file changed, 2 insertions(+), 14 deletions(-) diff --git a/armsrc/flashmem.c b/armsrc/flashmem.c index 3a46500ba..92204baff 100644 --- a/armsrc/flashmem.c +++ b/armsrc/flashmem.c @@ -254,12 +254,7 @@ uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) { // length should never be zero if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0; - - uint8_t cmd = READDATA; - - if(FASTFLASH) { - cmd = FASTREAD; - } + uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA; FlashSendByte(cmd); Flash_TransferAdresse(address); @@ -273,8 +268,6 @@ uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) { out[i] = FlashSendByte(0xFF); out[i] = FlashSendLastByte(0xFF); - - FlashStop(); return len; } @@ -291,11 +284,7 @@ uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) { // length should never be zero if (!len) return 0; - uint8_t cmd = READDATA; - - if(FASTFLASH) { - cmd = FASTREAD; - } + uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA; FlashSendByte(cmd); Flash_TransferAdresse(address); @@ -309,7 +298,6 @@ uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) { out[i] = FlashSendByte(0xFF); out[i] = FlashSendLastByte(0xFF); - return len; } From 746299b9ad8a7b72ce46b174044620fc0495a75e Mon Sep 17 00:00:00 2001 From: Hector Sanjuan Date: Sun, 21 Oct 2018 18:24:16 +0200 Subject: [PATCH 0094/1938] Add nonce2key to .gitignore --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index f3fbe950a..785934f46 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,7 @@ luac fpga_compress mfkey32 mfkey64 +tools/nonce2key/nonce2key fpga/* !fpga/tests From 34775c81f57c58837fe86a2ae7d4733150d73331 Mon Sep 17 00:00:00 2001 From: bogiton <34060135+bogiton@users.noreply.github.com> Date: Sun, 21 Oct 2018 18:29:49 +0000 Subject: [PATCH 0095/1938] Added BogitoRun identification --- armsrc/appmain.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 79eba9cf8..2a3ae823a 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -453,7 +453,10 @@ void printStandAloneModes(void) { #if defined(WITH_HF_COLIN) DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN (Colin Brigato)"); #endif - +#if defined(WITH_HF_BOG) + DbpString(" HF 14a sniff standalone with ULC/ULEV1/NTAG auth storing in flashmem - aka BogitoRun (Bogito)"); +#endif + //DbpString("Running "); //Dbprintf(" Is Device attached to USB| %s", USB_ATTACHED() ? "Yes" : "No"); //Dbprintf(" Is Device attached to FPC| %s", 0 ? "Yes" : "No"); From 4784cfd3fd2acc12d3057e322cbd8cb719a5325c Mon Sep 17 00:00:00 2001 From: Pavel Zhovner Date: Mon, 22 Oct 2018 22:03:58 +0300 Subject: [PATCH 0096/1938] Added new keys from MifareClassicTool project. Remove two dups --- client/default_keys.dic | 58 ++++++++++++++++++++++++++++++++++++++--- 1 file changed, 55 insertions(+), 3 deletions(-) diff --git a/client/default_keys.dic b/client/default_keys.dic index a77418df8..e8f0743d1 100644 --- a/client/default_keys.dic +++ b/client/default_keys.dic @@ -484,7 +484,6 @@ f7a39753d018, 2031d1e57a3b, 53c11f90822a, 9189449ea24e, -568c9083f71c, # # data from Github 410b9b40b872, @@ -598,7 +597,6 @@ C01FC822C6E5, # More keys: 8a19d40cf2b5, ae8587108640, -8829DA9DAF76,-- Meriton Suites Syd, Aus ;). Not sure where this came from... 135b88a94b8b, SafLock standalone door locks. # # Russian Troika card @@ -655,4 +653,58 @@ EAAC88E5DC99, 5EFBAECEF46B, F8493407799D, 6B8BD9860763, -D3A297DC2698, \ No newline at end of file +D3A297DC2698, +# +# Keys from MifareClassicTool project +044CE1872BC3, +045CECA15535, +0BE5FAC8B06A, +0CE7CD2CC72B, +0EB23CC8110B, +0F01CEFF2742, +0F318130ED18, +114D6BE9440C, +18E3A02B5EFF, +19FC84A3784B, +1B61B2E78C75, +22052B480D11, +3367BFAA91DB, +3A8A139C20B4, +42E9B54E51AB, +46D78E850A7E, +4B609876BBA3, +518DC6EEA089, +6B07877E2C5C, +7259FA0197C6, +72F96BDD3714, +7413B599C4EA, +77DABC9825E1, +7A396F0D633D, +7A86AA203788, +8791B2CCB5C4, +8A8D88151A00, +8C97CD7A0E56, +8E26E45E7D65, +9D993C5D4EF4, +9EA3387A63C1, +A3FAA6DAFF67, +A7141147D430, +AAFB06045877, +ACFFFFFFFFFF, +AFCEF64C9913, +B27ADDFB64B0, +B81F2B0C2F66, +B9F8A7D83978, +BAFF3053B496, +BB52F8CCE07F, +BC2D1791DEC1, +BC4580B7F20B, +C65D4EAA645B, +C76BF71A2509, +D5524F591EED, +E328A1C7156D, +E4821A377B75, +E56AC127DD45, +EA0FD73CB149, +FC0001877BF7, +FD8705E721B0, From 61ea3109c9d6529c1b1f77c7ff78fe6aafb0f80f Mon Sep 17 00:00:00 2001 From: merlokk Date: Wed, 24 Oct 2018 18:18:05 +0300 Subject: [PATCH 0097/1938] start merge --- client/Makefile | 3 + client/cliparser/cliparser.c | 45 ++- client/cliparser/cliparser.h | 8 +- client/cmdhf.c | 1 + client/cmdhf.h | 1 + client/cmdhfmf.c | 120 +----- client/cmdhfmfp.c | 696 +++++++++++++++++++++++++++++++++++ client/cmdhfmfp.h | 18 + client/mifare4.c | 153 ++++++++ client/mifare4.h | 35 ++ common/polarssl/libpcrypto.c | 44 +++ common/polarssl/libpcrypto.h | 20 + 12 files changed, 1015 insertions(+), 129 deletions(-) create mode 100644 client/cmdhfmfp.c create mode 100644 client/cmdhfmfp.h create mode 100644 client/mifare4.c create mode 100644 client/mifare4.h create mode 100644 common/polarssl/libpcrypto.c create mode 100644 common/polarssl/libpcrypto.h diff --git a/client/Makefile b/client/Makefile index eaf846610..c832d9e49 100644 --- a/client/Makefile +++ b/client/Makefile @@ -110,6 +110,7 @@ CMDSRCS = crapto1/crapto1.c \ polarssl/sha1.c \ polarssl/sha256.c \ polarssl/base64.c \ + polarssl/libpcrypto.c \ cliparser/argtable3.c\ cliparser/cliparser.c\ loclass/cipher.c \ @@ -147,6 +148,7 @@ CMDSRCS = crapto1/crapto1.c \ emv/test/dda_test.c\ emv/test/cda_test.c\ emv/cmdemv.c \ + mifare4.c \ cmdanalyse.c \ cmdhf.c \ cmdhflist.c \ @@ -158,6 +160,7 @@ CMDSRCS = crapto1/crapto1.c \ cmdhficlass.c \ cmdhfmf.c \ cmdhfmfu.c \ + cmdhfmfp.c \ cmdhfmfhard.c \ hardnested/hardnested_bruteforce.c \ cmdhfmfdes.c \ diff --git a/client/cliparser/cliparser.c b/client/cliparser/cliparser.c index 56be2ca6a..954220398 100644 --- a/client/cliparser/cliparser.c +++ b/client/cliparser/cliparser.c @@ -153,23 +153,14 @@ void CLIParserFree() { // convertors int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) { *datalen = 0; - if (!argstr->count) - return 0; - char buf[256] = {0}; int ibuf = 0; + uint8_t buf[256] = {0}; + int res = CLIParamStrToBuf(argstr, buf, maxdatalen * 2, &ibuf); // *2 because here HEX + if (res || !ibuf) + return res; - for (int i = 0; i < argstr->count; i++) { - int len = strlen(argstr->sval[i]); - memcpy(&buf[ibuf], argstr->sval[i], len); - ibuf += len; - } - buf[ibuf] = 0; - - if (!ibuf) - return 0; - - switch(param_gethex_to_eol(buf, 0, data, maxdatalen, datalen)) { + switch(param_gethex_to_eol((char *)buf, 0, data, maxdatalen, datalen)) { case 1: printf("Parameter error: Invalid HEX value.\n"); return 1; @@ -184,5 +175,31 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int return 0; } +int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) { + *datalen = 0; + if (!argstr->count) + return 0; + + uint8_t buf[256] = {0}; + int ibuf = 0; + + for (int i = 0; i < argstr->count; i++) { + int len = strlen(argstr->sval[i]); + memcpy(&buf[ibuf], argstr->sval[i], len); + ibuf += len; + } + buf[ibuf] = 0; + + if (!ibuf) + return 0; + + if (ibuf > maxdatalen) + return 2; + + memcpy(data, buf, ibuf); + *datalen = ibuf; + + return 0; +} diff --git a/client/cliparser/cliparser.h b/client/cliparser/cliparser.h index 7c1ced207..05910ea43 100644 --- a/client/cliparser/cliparser.h +++ b/client/cliparser/cliparser.h @@ -17,7 +17,9 @@ #define arg_getsize(a) (sizeof(a) / sizeof(a[0])) #define arg_get_lit(n)(((struct arg_lit*)argtable[n])->count) +#define arg_get_int_count(n)(((struct arg_int*)argtable[n])->count) #define arg_get_int(n)(((struct arg_int*)argtable[n])->ival[0]) +#define arg_get_int_def(n,def)(arg_get_int_count(n)?(arg_get_int(n)):(def)) #define arg_get_str(n)((struct arg_str*)argtable[n]) #define arg_get_str_len(n)(strlen(((struct arg_str*)argtable[n])->sval[0])) @@ -25,8 +27,9 @@ #define arg_strx0(shortopts, longopts, datatype, glossary) (arg_strn((shortopts), (longopts), (datatype), 0, 250, (glossary))) #define CLIExecWithReturn(cmd, atbl, ifempty) if (CLIParserParseString(cmd, atbl, arg_getsize(atbl), ifempty)){CLIParserFree();return 0;} -#define CLIGetStrBLessWithReturn(paramnum, data, datalen, delta) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data) - (delta), datalen)) {CLIParserFree();return 1;} -#define CLIGetStrWithReturn(paramnum, data, datalen) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree();return 1;} +#define CLIGetHexBLessWithReturn(paramnum, data, datalen, delta) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data) - (delta), datalen)) {CLIParserFree();return 1;} +#define CLIGetHexWithReturn(paramnum, data, datalen) if (CLIParamHexToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree();return 1;} +#define CLIGetStrWithReturn(paramnum, data, datalen) if (CLIParamStrToBuf(arg_get_str(paramnum), data, sizeof(data), datalen)) {CLIParserFree();return 1;} extern int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp); extern int CLIParserParseString(const char* str, void* argtable[], size_t vargtableLen, bool allowEmptyExec); @@ -35,3 +38,4 @@ extern int CLIParserParseArg(int argc, char **argv, void* argtable[], size_t var extern void CLIParserFree(); extern int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); +extern int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen); diff --git a/client/cmdhf.c b/client/cmdhf.c index 594450271..30669d24d 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -117,6 +117,7 @@ static command_t CommandTable[] = { {"legic", CmdHFLegic, 1, "{ LEGIC RFIDs... }"}, {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, + {"mfp", CmdHFMFP, 1, "{ MIFARE Plus RFIDs... }"}, {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, {"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"}, {"topaz", CmdHFTopaz, 1, "{ TOPAZ (NFC Type 1) RFIDs... }"}, diff --git a/client/cmdhf.h b/client/cmdhf.h index be369b626..a4cc2e95c 100644 --- a/client/cmdhf.h +++ b/client/cmdhf.h @@ -26,6 +26,7 @@ #include "cmdhficlass.h" // ICLASS #include "cmdhfmf.h" // CLASSIC #include "cmdhfmfu.h" // ULTRALIGHT/NTAG etc +#include "cmdhfmfp.h" // Mifare Plus #include "cmdhfmfdes.h" // DESFIRE #include "cmdhftopaz.h" // TOPAZ #include "cmdhffelica.h" // ISO18092 / FeliCa diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index f40db51cf..2ef1fd6ba 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -9,6 +9,7 @@ //----------------------------------------------------------------------------- #include "cmdhfmf.h" +#include "mifare4.h" #define MIFARE_4K_MAXBLOCK 255 #define MIFARE_2K_MAXBLOCK 128 @@ -3067,50 +3068,12 @@ out: return 0; } -int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){ - uint8_t iiv[16] = {0}; - if (iv) - memcpy(iiv, iv, 16); - - aes_context aes; - aes_init(&aes); - if (aes_setkey_enc(&aes, key, 128)) - return 1; - if (aes_crypt_cbc(&aes, AES_ENCRYPT, length, iiv, input, output)) - return 2; - aes_free(&aes); - - return 0; -} - -int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){ - uint8_t iiv[16] = {0}; - if (iv) - memcpy(iiv, iv, 16); - - aes_context aes; - aes_init(&aes); - if (aes_setkey_dec(&aes, key, 128)) - return 1; - if (aes_crypt_cbc(&aes, AES_DECRYPT, length, iiv, input, output)) - return 2; - aes_free(&aes); - - return 0; -} - int CmdHF14AMfAuth4(const char *cmd) { uint8_t keyn[20] = {0}; int keynlen = 0; uint8_t key[16] = {0}; int keylen = 0; - uint8_t data[257] = {0}; - int datalen = 0; - - uint8_t Rnd1[17] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00}; - uint8_t Rnd2[17] = {0}; - - + CLIParserInit("hf mf auth4", "Executes AES authentication command in ISO14443-4", "Usage:\n\thf mf auth4 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n" @@ -3124,90 +3087,21 @@ int CmdHF14AMfAuth4(const char *cmd) { }; CLIExecWithReturn(cmd, argtable, true); - CLIGetStrWithReturn(1, keyn, &keynlen); - CLIGetStrWithReturn(2, key, &keylen); + CLIGetHexWithReturn(1, keyn, &keynlen); + CLIGetHexWithReturn(2, key, &keylen); CLIParserFree(); if (keynlen != 2) { - PrintAndLogEx(ERR, " must be 2 bytes long instead of: %d", keynlen); + PrintAndLog(ERROR, " must be 2 bytes long instead of: %d", keynlen); return 1; } if (keylen != 16) { - PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); + PrintAndLog(ERROR, " must be 16 bytes long instead of: %d", keylen); return 1; } - uint8_t cmd1[] = {0x0a, 0x00, 0x70, keyn[1], keyn[0], 0x00}; - int res = ExchangeRAW14a(cmd1, sizeof(cmd1), true, true, data, sizeof(data), &datalen); - if (res) { - PrintAndLog("ERROR exchande raw error: %d", res); - return 2; - } - - PrintAndLog("phase2: %s", sprint_hex(cmd2, 35)); - - res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, false, data, sizeof(data), &datalen); - if (res) { - PrintAndLogEx(ERR, "exchande raw error: %d", res); - DropField(); - return 4; - } - - PrintAndLog(" +#include +#include +#include +#include +#include "comms.h" +#include "cmdmain.h" +#include "util.h" +#include "ui.h" +#include "cmdhf14a.h" +#include "mifare.h" +#include "mifare4.h" +#include "cliparser/cliparser.h" +#include "polarssl/libpcrypto.h" + +static const uint8_t DefaultKey[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + +typedef struct { + uint8_t Code; + const char *Description; +} PlusErrorsElm; + +static const PlusErrorsElm PlusErrors[] = { + {0xFF, ""}, + {0x00, "Unknown error"}, + {0x06, "Block use error"}, + {0x07, "Command use error"}, + {0x08, "Invalid write command"}, + {0x09, "Invalid block number"}, + {0x0b, "Command code error"}, + {0x0c, "Length error"}, + {0x90, "OK"}, +}; +int PlusErrorsLen = sizeof(PlusErrors) / sizeof(PlusErrorsElm); + +const char * GetErrorDescription(uint8_t errorCode) { + for(int i = 0; i < PlusErrorsLen; i++) + if (errorCode == PlusErrors[i].Code) + return PlusErrors[i].Description; + + return PlusErrors[0].Description; +} + +static int CmdHelp(const char *Cmd); + +static bool VerboseMode = false; +void SetVerboseMode(bool verbose) { + VerboseMode = verbose; +} + +int intExchangeRAW14aPlus(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { + if(VerboseMode) + PrintAndLog(">>> %s", sprint_hex(datain, datainlen)); + + int res = ExchangeRAW14a(datain, datainlen, activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); + + if(VerboseMode) + PrintAndLog("<<< %s", sprint_hex(dataout, *dataoutlen)); + + return res; +} + +int MFPWritePerso(uint8_t *keyNum, uint8_t *key, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { + uint8_t rcmd[3 + 16] = {0xa8, keyNum[1], keyNum[0], 0x00}; + memmove(&rcmd[3], key, 16); + + return intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); +} + +int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { + uint8_t rcmd[1] = {0xaa}; + + return intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); +} + +int MFPReadBlock(mf4Session *session, bool plain, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { + uint8_t rcmd[4 + 8] = {(plain?(0x37):(0x33)), blockNum, 0x00, blockCount}; + + return intExchangeRAW14aPlus(rcmd, plain?4:sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); +} + +int MFPWriteBlock(mf4Session *session, uint8_t blockNum, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { + uint8_t rcmd[1 + 2 + 16 + 8] = {0xA3, blockNum, 0x00}; + memmove(&rcmd[3], data, 16); + + return intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); +} + +int CmdHFMFPInfo(const char *cmd) { + + if (cmd && strlen(cmd) > 0) + PrintAndLog("WARNING: command don't have any parameters.\n"); + + // info about 14a part + CmdHF14AInfo(""); + + // Mifare Plus info + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; + SendCommand(&c); + + UsbCommand resp; + WaitForResponse(CMD_ACK,&resp); + + iso14a_card_select_t card; + memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); + + uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision + + if (select_status == 1 || select_status == 2) { + PrintAndLog("----------------------------------------------"); + PrintAndLog("Mifare Plus info:"); + + // MIFARE Type Identification Procedure + // https://www.nxp.com/docs/en/application-note/AN10833.pdf + uint16_t ATQA = card.atqa[0] + (card.atqa[1] << 8); + if (ATQA == 0x0004) PrintAndLog("ATQA: Mifare Plus 2k 4bUID"); + if (ATQA == 0x0002) PrintAndLog("ATQA: Mifare Plus 4k 4bUID"); + if (ATQA == 0x0044) PrintAndLog("ATQA: Mifare Plus 2k 7bUID"); + if (ATQA == 0x0042) PrintAndLog("ATQA: Mifare Plus 4k 7bUID"); + + uint8_t SLmode = 0xff; + if (card.sak == 0x08) { + PrintAndLog("SAK: Mifare Plus 2k 7bUID"); + if (select_status == 2) SLmode = 1; + } + if (card.sak == 0x18) { + PrintAndLog("SAK: Mifare Plus 4k 7bUID"); + if (select_status == 2) SLmode = 1; + } + if (card.sak == 0x10) { + PrintAndLog("SAK: Mifare Plus 2k"); + if (select_status == 2) SLmode = 2; + } + if (card.sak == 0x11) { + PrintAndLog("SAK: Mifare Plus 4k"); + if (select_status == 2) SLmode = 2; + } + if (card.sak == 0x20) { + PrintAndLog("SAK: Mifare Plus SL0/SL3 or Mifare desfire"); + if (card.ats_len > 0) { + SLmode = 3; + + // check SL0 + uint8_t data[250] = {0}; + int datalen = 0; + // https://github.com/Proxmark/proxmark3/blob/master/client/scripts/mifarePlus.lua#L161 + uint8_t cmd[3 + 16] = {0xa8, 0x90, 0x90, 0x00}; + int res = ExchangeRAW14a(cmd, sizeof(cmd), false, false, data, sizeof(data), &datalen); + if (!res && datalen > 1 && data[0] == 0x09) { + SLmode = 0; + } + } + } + + if (SLmode != 0xff) + PrintAndLog("Mifare Plus SL mode: SL%d", SLmode); + else + PrintAndLog("Mifare Plus SL mode: unknown("); + } else { + PrintAndLog("Mifare Plus info not available."); + } + + DropField(); + + return 0; +} + +int CmdHFMFPWritePerso(const char *cmd) { + uint8_t keyNum[64] = {0}; + int keyNumLen = 0; + uint8_t key[64] = {0}; + int keyLen = 0; + + CLIParserInit("hf mfp wrp", + "Executes Write Perso command. Can be used in SL0 mode only.", + "Usage:\n\thf mfp wrp 4000 000102030405060708090a0b0c0d0e0f -> write key (00..0f) to key number 4000 \n" + "\thf mfp wrp 4000 -> write default key(0xff..0xff) to key number 4000"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("vV", "verbose", "show internal data."), + arg_str1(NULL, NULL, "", NULL), + arg_strx0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + bool verbose = arg_get_lit(1); + CLIGetHexWithReturn(2, keyNum, &keyNumLen); + CLIGetHexWithReturn(3, key, &keyLen); + CLIParserFree(); + + SetVerboseMode(verbose); + + if (!keyLen) { + memmove(key, DefaultKey, 16); + keyLen = 16; + } + + if (keyNumLen != 2) { + PrintAndLog("Key number length must be 2 bytes instead of: %d", keyNumLen); + return 1; + } + if (keyLen != 16) { + PrintAndLog("Key length must be 16 bytes instead of: %d", keyLen); + return 1; + } + + uint8_t data[250] = {0}; + int datalen = 0; + + int res = MFPWritePerso(keyNum, key, true, false, data, sizeof(data), &datalen); + if (res) { + PrintAndLog("Exchange error: %d", res); + return res; + } + + if (datalen != 3) { + PrintAndLog("Command must return 3 bytes instead of: %d", datalen); + return 1; + } + + if (data[0] != 0x90) { + PrintAndLog("Command error: %02x %s", data[0], GetErrorDescription(data[0])); + return 1; + } + PrintAndLog("Write OK."); + + return 0; +} + +uint16_t CardAddresses[] = {0x9000, 0x9001, 0x9002, 0x9003, 0x9004, 0xA000, 0xA001, 0xA080, 0xA081, 0xC000, 0xC001}; + +int CmdHFMFPInitPerso(const char *cmd) { + int res; + uint8_t key[256] = {0}; + int keyLen = 0; + uint8_t keyNum[2] = {0}; + uint8_t data[250] = {0}; + int datalen = 0; + + CLIParserInit("hf mfp initp", + "Executes Write Perso command for all card's keys. Can be used in SL0 mode only.", + "Usage:\n\thf mfp initp 000102030405060708090a0b0c0d0e0f -> fill all the keys with key (00..0f)\n" + "\thf mfp initp -vv -> fill all the keys with default key(0xff..0xff) and show all the data exchange"); + + void* argtable[] = { + arg_param_begin, + arg_litn("vV", "verbose", 0, 2, "show internal data."), + arg_strx0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + bool verbose = arg_get_lit(1); + bool verbose2 = arg_get_lit(1) > 1; + CLIGetHexWithReturn(2, key, &keyLen); + CLIParserFree(); + + if (keyLen && keyLen != 16) { + PrintAndLog("Key length must be 16 bytes instead of: %d", keyLen); + return 1; + } + + if (!keyLen) + memmove(key, DefaultKey, 16); + + SetVerboseMode(verbose2); + for (uint16_t sn = 0x4000; sn < 0x4050; sn++) { + keyNum[0] = sn >> 8; + keyNum[1] = sn & 0xff; + res = MFPWritePerso(keyNum, key, (sn == 0x4000), true, data, sizeof(data), &datalen); + if (!res && (datalen == 3) && data[0] == 0x09) { + PrintAndLog("2k card detected."); + break; + } + if (res || (datalen != 3) || data[0] != 0x90) { + PrintAndLog("Write error on address %04x", sn); + break; + } + } + + SetVerboseMode(verbose); + for (int i = 0; i < sizeof(CardAddresses) / 2; i++) { + keyNum[0] = CardAddresses[i] >> 8; + keyNum[1] = CardAddresses[i] & 0xff; + res = MFPWritePerso(keyNum, key, false, true, data, sizeof(data), &datalen); + if (!res && (datalen == 3) && data[0] == 0x09) { + PrintAndLog("Skipped[%04x]...", CardAddresses[i]); + } else { + if (res || (datalen != 3) || data[0] != 0x90) { + PrintAndLog("Write error on address %04x", CardAddresses[i]); + break; + } + } + } + + DropField(); + + if (res) + return res; + + PrintAndLog("Done."); + + return 0; +} + +int CmdHFMFPCommitPerso(const char *cmd) { + CLIParserInit("hf mfp commitp", + "Executes Commit Perso command. Can be used in SL0 mode only.", + "Usage:\n\thf mfp commitp -> \n"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("vV", "verbose", "show internal data."), + arg_int0(NULL, NULL, "SL mode", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + bool verbose = arg_get_lit(1); + CLIParserFree(); + + SetVerboseMode(verbose); + + uint8_t data[250] = {0}; + int datalen = 0; + + int res = MFPCommitPerso(true, false, data, sizeof(data), &datalen); + if (res) { + PrintAndLog("Exchange error: %d", res); + return res; + } + + if (datalen != 3) { + PrintAndLog("Command must return 3 bytes instead of: %d", datalen); + return 1; + } + + if (data[0] != 0x90) { + PrintAndLog("Command error: %02x %s", data[0], GetErrorDescription(data[0])); + return 1; + } + PrintAndLog("Switch level OK."); + + return 0; +} + +int CmdHFMFPAuth(const char *cmd) { + uint8_t keyn[250] = {0}; + int keynlen = 0; + uint8_t key[250] = {0}; + int keylen = 0; + + CLIParserInit("hf mfp auth", + "Executes AES authentication command for Mifare Plus card", + "Usage:\n\thf mfp auth 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n" + "\thf mfp auth 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -v -> executes authentication and shows all the system data\n"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("vV", "verbose", "show internal data."), + arg_str1(NULL, NULL, "", NULL), + arg_str1(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + bool verbose = arg_get_lit(1); + CLIGetHexWithReturn(2, keyn, &keynlen); + CLIGetHexWithReturn(3, key, &keylen); + CLIParserFree(); + + if (keynlen != 2) { + PrintAndLog("ERROR: must be 2 bytes long instead of: %d", keynlen); + return 1; + } + + if (keylen != 16) { + PrintAndLog("ERROR: must be 16 bytes long instead of: %d", keylen); + return 1; + } + + return MifareAuth4(NULL, keyn, key, true, false, verbose); +} + +int CmdHFMFPRdbl(const char *cmd) { + uint8_t keyn[2] = {0}; + uint8_t key[250] = {0}; + int keylen = 0; + + CLIParserInit("hf mfp rdbl", + "Reads several blocks from Mifare Plus card in plain mode.", + "Usage:\n\thf mfp rdbl 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read block 0 data\n" + "\thf mfp rdbl 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data\n"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("vV", "verbose", "show internal data."), + arg_int0("nN", "count", "blocks count (by default 1).", NULL), + arg_lit0("bB", "keyb", "use key B (by default keyA)."), + arg_lit0("pP", "plain", "plain communication between reader and card."), + arg_int1(NULL, NULL, "", NULL), + arg_str0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, false); + + bool verbose = arg_get_lit(1); + int blocksCount = arg_get_int_def(2, 1); + bool keyB = arg_get_lit(3); + int plain = arg_get_lit(4) | true; + uint32_t blockn = arg_get_int(5); + CLIGetHexWithReturn(6, key, &keylen); + CLIParserFree(); + + if (!keylen) { + memmove(key, DefaultKey, 16); + keylen = 16; + } + + if (blockn > 255) { + PrintAndLog("ERROR: must be in range [0..255] instead of: %d", blockn); + return 1; + } + + if (keylen != 16) { + PrintAndLog("ERROR: must be 16 bytes long instead of: %d", keylen); + return 1; + } + + // 3 blocks - wo iso14443-4 chaining + if (blocksCount > 3) { + PrintAndLog("ERROR: blocks count must be less than 3 instead of: %d", blocksCount); + return 1; + } + + uint8_t sectorNum = mfSectorNum(blockn & 0xff); + uint16_t uKeyNum = 0x4000 + sectorNum * 2 + (keyB ? 1 : 0); + keyn[0] = uKeyNum >> 8; + keyn[1] = uKeyNum & 0xff; + if (verbose) + PrintAndLog("--block:%d sector[%d]:%02x key:%04x", blockn, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); + + mf4Session session; + int res = MifareAuth4(&session, keyn, key, true, true, verbose); + if (res) { + PrintAndLog("Authentication error: %d", res); + return res; + } + + uint8_t data[250] = {0}; + int datalen = 0; + res = MFPReadBlock(&session, plain, blockn & 0xff, blocksCount, false, false, data, sizeof(data), &datalen); + if (res) { + PrintAndLog("Read error: %d", res); + return res; + } + + if (datalen && data[0] != 0x90) { + PrintAndLog("Card read error: %02x %s", data[0], GetErrorDescription(data[0])); + return 6; + } + + if (datalen != 1 + blocksCount * 16 + 8 + 2) { + PrintAndLog("Error return length:%d", datalen); + return 5; + } + + int indx = blockn; + for(int i = 0; i < blocksCount; i++) { + PrintAndLog("data[%03d]: %s", indx, sprint_hex(&data[1 + i * 16], 16)); + indx++; + if (mfIsSectorTrailer(indx)){ + PrintAndLog("data[%03d]: ------------------- trailer -------------------", indx); + indx++; + } + } + + if(verbose) + PrintAndLog("MAC: %s", sprint_hex(&data[blocksCount * 16 + 1], 8)); + + return 0; +} + +int CmdHFMFPRdsc(const char *cmd) { + uint8_t keyn[2] = {0}; + uint8_t key[250] = {0}; + int keylen = 0; + + CLIParserInit("hf mfp rdsc", + "Reads one sector from Mifare Plus card in plain mode.", + "Usage:\n\thf mfp rdsc 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read sector 0 data\n" + "\thf mfp rdsc 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data\n"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("vV", "verbose", "show internal data."), + arg_lit0("bB", "keyb", "use key B (by default keyA)."), + arg_lit0("pP", "plain", "plain communication between reader and card."), + arg_int1(NULL, NULL, "", NULL), + arg_str0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, false); + + bool verbose = arg_get_lit(1); + bool keyB = arg_get_lit(2); + bool plain = arg_get_lit(3) | true; + uint32_t sectorNum = arg_get_int(4); + CLIGetHexWithReturn(5, key, &keylen); + CLIParserFree(); + + if (!keylen) { + memmove(key, DefaultKey, 16); + keylen = 16; + } + + if (sectorNum > 39) { + PrintAndLog("ERROR: must be in range [0..39] instead of: %d", sectorNum); + return 1; + } + + if (keylen != 16) { + PrintAndLog("ERROR: must be 16 bytes long instead of: %d", keylen); + return 1; + } + + uint16_t uKeyNum = 0x4000 + sectorNum * 2 + (keyB ? 1 : 0); + keyn[0] = uKeyNum >> 8; + keyn[1] = uKeyNum & 0xff; + if (verbose) + PrintAndLog("--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); + + mf4Session session; + int res = MifareAuth4(&session, keyn, key, true, true, verbose); + if (res) { + PrintAndLog("Authentication error: %d", res); + return res; + } + + uint8_t data[250] = {0}; + int datalen = 0; + for(int n = mfFirstBlockOfSector(sectorNum); n < mfFirstBlockOfSector(sectorNum) + mfNumBlocksPerSector(sectorNum); n++) { + res = MFPReadBlock(&session, plain, n & 0xff, 1, false, true, data, sizeof(data), &datalen); + if (res) { + PrintAndLog("Read error: %d", res); + DropField(); + return res; + } + + if (datalen && data[0] != 0x90) { + PrintAndLog("Card read error: %02x %s", data[0], GetErrorDescription(data[0])); + DropField(); + return 6; + } + if (datalen != 1 + 16 + 8 + 2) { + PrintAndLog("Error return length:%d", datalen); + DropField(); + return 5; + } + + PrintAndLog("data[%03d]: %s", n, sprint_hex(&data[1], 16)); + + if(verbose) + PrintAndLog("MAC: %s", sprint_hex(&data[1 + 16], 8)); + } + DropField(); + + return 0; +} + +int CmdHFMFPWrbl(const char *cmd) { + uint8_t keyn[2] = {0}; + uint8_t key[250] = {0}; + int keylen = 0; + uint8_t datain[250] = {0}; + int datainlen = 0; + + CLIParserInit("hf mfp wrbl", + "Writes one block to Mifare Plus card.", + "Usage:\n\thf mfp wrbl 1 ff0000000000000000000000000000ff 000102030405060708090a0b0c0d0e0f -> writes block 1 data\n" + "\thf mfp wrbl 2 ff0000000000000000000000000000ff -v -> writes block 2 data with default key 0xFF..0xFF and some additional data\n"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("vV", "verbose", "show internal data."), + arg_lit0("bB", "keyb", "use key B (by default keyA)."), + arg_int1(NULL, NULL, "", NULL), + arg_str1(NULL, NULL, "", NULL), + arg_str0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, false); + + bool verbose = arg_get_lit(1); + bool keyB = arg_get_lit(2); + uint32_t blockNum = arg_get_int(3); + CLIGetHexWithReturn(4, datain, &datainlen); + CLIGetHexWithReturn(5, key, &keylen); + CLIParserFree(); + + if (!keylen) { + memmove(key, DefaultKey, 16); + keylen = 16; + } + + if (blockNum > 39) { + PrintAndLog("ERROR: must be in range [0..255] instead of: %d", blockNum); + return 1; + } + + if (keylen != 16) { + PrintAndLog("ERROR: must be 16 bytes long instead of: %d", keylen); + return 1; + } + + if (datainlen != 16) { + PrintAndLog("ERROR: must be 16 bytes long instead of: %d", datainlen); + return 1; + } + + uint8_t sectorNum = mfSectorNum(blockNum & 0xff); + uint16_t uKeyNum = 0x4000 + sectorNum * 2 + (keyB ? 1 : 0); + keyn[0] = uKeyNum >> 8; + keyn[1] = uKeyNum & 0xff; + if (verbose) + PrintAndLog("--block:%d sector[%d]:%02x key:%04x", blockNum & 0xff, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); + + mf4Session session; + int res = MifareAuth4(&session, keyn, key, true, true, verbose); + if (res) { + PrintAndLog("Authentication error: %d", res); + return res; + } + + uint8_t data[250] = {0}; + int datalen = 0; + res = MFPWriteBlock(&session, blockNum & 0xff, datain, false, false, data, sizeof(data), &datalen); + if (res) { + PrintAndLog("Write error: %d", res); + return res; + } + + if (datalen != 3 && (datalen != 3 + 8)) { + PrintAndLog("Error return length:%d", datalen); + return 5; + } + + if (datalen && data[0] != 0x90) { + PrintAndLog("Card write error: %02x %s", data[0], GetErrorDescription(data[0])); + return 6; + } + + if(verbose) + PrintAndLog("MAC: %s", sprint_hex(&data[1], 8)); + + return 0; +} + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help"}, + {"info", CmdHFMFPInfo, 0, "Info about Mifare Plus tag"}, + {"wrp", CmdHFMFPWritePerso, 0, "Write Perso command"}, + {"initp", CmdHFMFPInitPerso, 0, "Fills all the card's keys"}, + {"commitp", CmdHFMFPCommitPerso, 0, "Move card to SL1 or SL3 mode"}, + {"auth", CmdHFMFPAuth, 0, "Authentication"}, + {"rdbl", CmdHFMFPRdbl, 0, "Read blocks"}, + {"rdsc", CmdHFMFPRdsc, 0, "Read sectors"}, +// {"wrbl", CmdHFMFPWrbl, 0, "Write blocks"}, + {NULL, NULL, 0, NULL} +}; + +int CmdHFMFP(const char *Cmd) { + (void)WaitForResponseTimeout(CMD_ACK,NULL,100); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdhfmfp.h b/client/cmdhfmfp.h new file mode 100644 index 000000000..b1ac7c349 --- /dev/null +++ b/client/cmdhfmfp.h @@ -0,0 +1,18 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency MIFARE Plus commands +//----------------------------------------------------------------------------- +#ifndef CMDHFMFP_H__ +#define CMDHFMFP_H__ + +#include "mifaredefault.h" + +extern int CmdHFMFP(const char *Cmd); + + +#endif \ No newline at end of file diff --git a/client/mifare4.c b/client/mifare4.c new file mode 100644 index 000000000..145dd243e --- /dev/null +++ b/client/mifare4.c @@ -0,0 +1,153 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// iso14443-4 mifare commands +//----------------------------------------------------------------------------- + +#include "mifare4.h" +#include +#include +#include "cmdhf14a.h" +#include "util.h" +#include "ui.h" +#include "polarssl/libpcrypto.h" + +int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose) { + uint8_t data[257] = {0}; + int datalen = 0; + + uint8_t Rnd1[17] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00}; + uint8_t Rnd2[17] = {0}; + + if (session) + session->Authenticated = false; + + uint8_t cmd1[] = {0x70, keyn[1], keyn[0], 0x00}; + int res = ExchangeRAW14a(cmd1, sizeof(cmd1), activateField, true, data, sizeof(data), &datalen); + if (res) { + PrintAndLog("ERROR exchande raw error: %d", res); + DropField(); + return 2; + } + + if (verbose) + PrintAndLog("phase2: %s", sprint_hex(cmd2, 33)); + + res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, true, data, sizeof(data), &datalen); + if (res) { + PrintAndLog("ERROR exchande raw error: %d", res); + DropField(); + return 4; + } + + if (verbose) + PrintAndLog("Authenticated = true; + session->KeyNum = keyn[1] + (keyn[0] << 8); + memmove(session->Rnd1, Rnd1, 16); + memmove(session->Rnd2, Rnd2, 16); + } + + PrintAndLog("Authentication OK"); + + return 0; +} + +// Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards), +// plus evtl. 8 sectors with 16 blocks each (4k cards) +uint8_t mfNumBlocksPerSector(uint8_t sectorNo) { + if (sectorNo < 32) + return 4; + else + return 16; +} + +uint8_t mfFirstBlockOfSector(uint8_t sectorNo) { + if (sectorNo < 32) + return sectorNo * 4; + else + return 32 * 4 + (sectorNo - 32) * 16; +} + +uint8_t mfSectorTrailer(uint8_t blockNo) { + if (blockNo < 32*4) { + return (blockNo | 0x03); + } else { + return (blockNo | 0x0f); + } +} + +bool mfIsSectorTrailer(uint8_t blockNo) { + return (blockNo == mfSectorTrailer(blockNo)); +} + +uint8_t mfSectorNum(uint8_t blockNo) { + if (blockNo < 32 * 4) + return blockNo / 4; + else + return 32 + (blockNo - 32 * 4) / 16; + +} diff --git a/client/mifare4.h b/client/mifare4.h new file mode 100644 index 000000000..d26152cb4 --- /dev/null +++ b/client/mifare4.h @@ -0,0 +1,35 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// iso14443-4 mifare commands +//----------------------------------------------------------------------------- + +#ifndef MIFARE4_H +#define MIFARE4_H + +#include +#include +#include + +typedef struct { + bool Authenticated; + uint16_t KeyNum; + uint8_t Rnd1[16]; + uint8_t Rnd2[16]; + +}mf4Session; + +extern int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose); + +extern uint8_t mfNumBlocksPerSector(uint8_t sectorNo); +extern uint8_t mfFirstBlockOfSector(uint8_t sectorNo); +extern uint8_t mfSectorTrailer(uint8_t blockNo); +extern bool mfIsSectorTrailer(uint8_t blockNo); +extern uint8_t mfSectorNum(uint8_t blockNo); + + +#endif // mifare4.h diff --git a/common/polarssl/libpcrypto.c b/common/polarssl/libpcrypto.c new file mode 100644 index 000000000..032c3a18b --- /dev/null +++ b/common/polarssl/libpcrypto.c @@ -0,0 +1,44 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// crypto commands +//----------------------------------------------------------------------------- + +#include "polarssl/libpcrypto.h" +#include + +int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){ + uint8_t iiv[16] = {0}; + if (iv) + memcpy(iiv, iv, 16); + + aes_context aes; + aes_init(&aes); + if (aes_setkey_enc(&aes, key, 128)) + return 1; + if (aes_crypt_cbc(&aes, AES_ENCRYPT, length, iiv, input, output)) + return 2; + aes_free(&aes); + + return 0; +} + +int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){ + uint8_t iiv[16] = {0}; + if (iv) + memcpy(iiv, iv, 16); + + aes_context aes; + aes_init(&aes); + if (aes_setkey_dec(&aes, key, 128)) + return 1; + if (aes_crypt_cbc(&aes, AES_DECRYPT, length, iiv, input, output)) + return 2; + aes_free(&aes); + + return 0; +} \ No newline at end of file diff --git a/common/polarssl/libpcrypto.h b/common/polarssl/libpcrypto.h new file mode 100644 index 000000000..84732cd31 --- /dev/null +++ b/common/polarssl/libpcrypto.h @@ -0,0 +1,20 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// crypto commands +//----------------------------------------------------------------------------- + +#ifndef LIBPCRYPTO_H +#define LIBPCRYPTO_H + +#include +#include + +extern int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); +extern int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); + +#endif /* libpcrypto.h */ From 8720d10da9ff1b98428b431c2ec9fa24267d3364 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 24 Oct 2018 19:02:14 +0300 Subject: [PATCH 0098/1938] changed logs --- client/cmdhfmf.c | 4 +-- client/cmdhfmfp.c | 74 +++++++++++++++++++++++------------------------ 2 files changed, 39 insertions(+), 39 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 2ef1fd6ba..016025fbc 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -3092,12 +3092,12 @@ int CmdHF14AMfAuth4(const char *cmd) { CLIParserFree(); if (keynlen != 2) { - PrintAndLog(ERROR, " must be 2 bytes long instead of: %d", keynlen); + PrintAndLogEx(ERR, " must be 2 bytes long instead of: %d", keynlen); return 1; } if (keylen != 16) { - PrintAndLog(ERROR, " must be 16 bytes long instead of: %d", keylen); + PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); return 1; } diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 7f7660df1..7ba1c2561 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -62,12 +62,12 @@ void SetVerboseMode(bool verbose) { int intExchangeRAW14aPlus(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { if(VerboseMode) - PrintAndLog(">>> %s", sprint_hex(datain, datainlen)); + PrintAndLogEx(INFO, ">>> %s", sprint_hex(datain, datainlen)); int res = ExchangeRAW14a(datain, datainlen, activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); if(VerboseMode) - PrintAndLog("<<< %s", sprint_hex(dataout, *dataoutlen)); + PrintAndLogEx(INFO, "<<< %s", sprint_hex(dataout, *dataoutlen)); return res; } @@ -101,7 +101,7 @@ int MFPWriteBlock(mf4Session *session, uint8_t blockNum, uint8_t *data, bool act int CmdHFMFPInfo(const char *cmd) { if (cmd && strlen(cmd) > 0) - PrintAndLog("WARNING: command don't have any parameters.\n"); + PrintAndLogEx(WARNING, "command don't have any parameters.\n"); // info about 14a part CmdHF14AInfo(""); @@ -119,8 +119,8 @@ int CmdHFMFPInfo(const char *cmd) { uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision if (select_status == 1 || select_status == 2) { - PrintAndLog("----------------------------------------------"); - PrintAndLog("Mifare Plus info:"); + PrintAndLogEx(INFO, "----------------------------------------------"); + PrintAndLogEx(INFO, "Mifare Plus info:"); // MIFARE Type Identification Procedure // https://www.nxp.com/docs/en/application-note/AN10833.pdf @@ -165,11 +165,11 @@ int CmdHFMFPInfo(const char *cmd) { } if (SLmode != 0xff) - PrintAndLog("Mifare Plus SL mode: SL%d", SLmode); + PrintAndLogEx(INFO, "Mifare Plus SL mode: SL%d", SLmode); else - PrintAndLog("Mifare Plus SL mode: unknown("); + PrintAndLogEx(WARNING, "Mifare Plus SL mode: unknown("); } else { - PrintAndLog("Mifare Plus info not available."); + PrintAndLogEx(INFO, "Mifare Plus info not available."); } DropField(); @@ -210,11 +210,11 @@ int CmdHFMFPWritePerso(const char *cmd) { } if (keyNumLen != 2) { - PrintAndLog("Key number length must be 2 bytes instead of: %d", keyNumLen); + PrintAndLogEx(ERR, "Key number length must be 2 bytes instead of: %d", keyNumLen); return 1; } if (keyLen != 16) { - PrintAndLog("Key length must be 16 bytes instead of: %d", keyLen); + PrintAndLogEx(ERR, "Key length must be 16 bytes instead of: %d", keyLen); return 1; } @@ -223,20 +223,20 @@ int CmdHFMFPWritePerso(const char *cmd) { int res = MFPWritePerso(keyNum, key, true, false, data, sizeof(data), &datalen); if (res) { - PrintAndLog("Exchange error: %d", res); + PrintAndLogEx(ERR, "Exchange error: %d", res); return res; } if (datalen != 3) { - PrintAndLog("Command must return 3 bytes instead of: %d", datalen); + PrintAndLogEx(ERR, "Command must return 3 bytes instead of: %d", datalen); return 1; } if (data[0] != 0x90) { - PrintAndLog("Command error: %02x %s", data[0], GetErrorDescription(data[0])); + PrintAndLogEx(ERR, "Command error: %02x %s", data[0], GetErrorDescription(data[0])); return 1; } - PrintAndLog("Write OK."); + PrintAndLogEx(INFO, "Write OK."); return 0; } @@ -270,7 +270,7 @@ int CmdHFMFPInitPerso(const char *cmd) { CLIParserFree(); if (keyLen && keyLen != 16) { - PrintAndLog("Key length must be 16 bytes instead of: %d", keyLen); + PrintAndLogEx(ERR, "Key length must be 16 bytes instead of: %d", keyLen); return 1; } @@ -283,11 +283,11 @@ int CmdHFMFPInitPerso(const char *cmd) { keyNum[1] = sn & 0xff; res = MFPWritePerso(keyNum, key, (sn == 0x4000), true, data, sizeof(data), &datalen); if (!res && (datalen == 3) && data[0] == 0x09) { - PrintAndLog("2k card detected."); + PrintAndLogEx(INFO, "2k card detected."); break; } if (res || (datalen != 3) || data[0] != 0x90) { - PrintAndLog("Write error on address %04x", sn); + PrintAndLogEx(ERR, "Write error on address %04x", sn); break; } } @@ -298,10 +298,10 @@ int CmdHFMFPInitPerso(const char *cmd) { keyNum[1] = CardAddresses[i] & 0xff; res = MFPWritePerso(keyNum, key, false, true, data, sizeof(data), &datalen); if (!res && (datalen == 3) && data[0] == 0x09) { - PrintAndLog("Skipped[%04x]...", CardAddresses[i]); + PrintAndLogEx(WARNING, "Skipped[%04x]...", CardAddresses[i]); } else { if (res || (datalen != 3) || data[0] != 0x90) { - PrintAndLog("Write error on address %04x", CardAddresses[i]); + PrintAndLogEx(ERR, "Write error on address %04x", CardAddresses[i]); break; } } @@ -312,7 +312,7 @@ int CmdHFMFPInitPerso(const char *cmd) { if (res) return res; - PrintAndLog("Done."); + PrintAndLogEx(INFO, "Done."); return 0; } @@ -340,20 +340,20 @@ int CmdHFMFPCommitPerso(const char *cmd) { int res = MFPCommitPerso(true, false, data, sizeof(data), &datalen); if (res) { - PrintAndLog("Exchange error: %d", res); + PrintAndLogEx(ERR, "Exchange error: %d", res); return res; } if (datalen != 3) { - PrintAndLog("Command must return 3 bytes instead of: %d", datalen); + PrintAndLogEx(ERR, "Command must return 3 bytes instead of: %d", datalen); return 1; } if (data[0] != 0x90) { - PrintAndLog("Command error: %02x %s", data[0], GetErrorDescription(data[0])); + PrintAndLogEx(ERR, "Command error: %02x %s", data[0], GetErrorDescription(data[0])); return 1; } - PrintAndLog("Switch level OK."); + PrintAndLogEx(INFO, "Switch level OK."); return 0; } @@ -384,12 +384,12 @@ int CmdHFMFPAuth(const char *cmd) { CLIParserFree(); if (keynlen != 2) { - PrintAndLog("ERROR: must be 2 bytes long instead of: %d", keynlen); + PrintAndLogEx(ERR, "ERROR: must be 2 bytes long instead of: %d", keynlen); return 1; } if (keylen != 16) { - PrintAndLog("ERROR: must be 16 bytes long instead of: %d", keylen); + PrintAndLogEx(ERR, "ERROR: must be 16 bytes long instead of: %d", keylen); return 1; } @@ -432,18 +432,18 @@ int CmdHFMFPRdbl(const char *cmd) { } if (blockn > 255) { - PrintAndLog("ERROR: must be in range [0..255] instead of: %d", blockn); + PrintAndLogEx(ERR, " must be in range [0..255] instead of: %d", blockn); return 1; } if (keylen != 16) { - PrintAndLog("ERROR: must be 16 bytes long instead of: %d", keylen); + PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); return 1; } // 3 blocks - wo iso14443-4 chaining if (blocksCount > 3) { - PrintAndLog("ERROR: blocks count must be less than 3 instead of: %d", blocksCount); + PrintAndLogEx(ERR, "blocks count must be less than 3 instead of: %d", blocksCount); return 1; } @@ -452,12 +452,12 @@ int CmdHFMFPRdbl(const char *cmd) { keyn[0] = uKeyNum >> 8; keyn[1] = uKeyNum & 0xff; if (verbose) - PrintAndLog("--block:%d sector[%d]:%02x key:%04x", blockn, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); + PrintAndLogEx(INFO, "--block:%d sector[%d]:%02x key:%04x", blockn, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); mf4Session session; int res = MifareAuth4(&session, keyn, key, true, true, verbose); if (res) { - PrintAndLog("Authentication error: %d", res); + PrintAndLogEx(ERR, "Authentication error: %d", res); return res; } @@ -465,32 +465,32 @@ int CmdHFMFPRdbl(const char *cmd) { int datalen = 0; res = MFPReadBlock(&session, plain, blockn & 0xff, blocksCount, false, false, data, sizeof(data), &datalen); if (res) { - PrintAndLog("Read error: %d", res); + PrintAndLogEx(ERR, "Read error: %d", res); return res; } if (datalen && data[0] != 0x90) { - PrintAndLog("Card read error: %02x %s", data[0], GetErrorDescription(data[0])); + PrintAndLogEx(ERR, "Card read error: %02x %s", data[0], GetErrorDescription(data[0])); return 6; } if (datalen != 1 + blocksCount * 16 + 8 + 2) { - PrintAndLog("Error return length:%d", datalen); + PrintAndLogEx(ERR, "Error return length:%d", datalen); return 5; } int indx = blockn; for(int i = 0; i < blocksCount; i++) { - PrintAndLog("data[%03d]: %s", indx, sprint_hex(&data[1 + i * 16], 16)); + PrintAndLogEx(INFO, "data[%03d]: %s", indx, sprint_hex(&data[1 + i * 16], 16)); indx++; if (mfIsSectorTrailer(indx)){ - PrintAndLog("data[%03d]: ------------------- trailer -------------------", indx); + PrintAndLogEx(INFO, "data[%03d]: ------------------- trailer -------------------", indx); indx++; } } if(verbose) - PrintAndLog("MAC: %s", sprint_hex(&data[blocksCount * 16 + 1], 8)); + PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[blocksCount * 16 + 1], 8)); return 0; } From 0af06c0b63e7afbacd7e1466f0c08be93651eca6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 24 Oct 2018 19:05:30 +0300 Subject: [PATCH 0099/1938] mifare4 logging --- client/mifare4.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/client/mifare4.c b/client/mifare4.c index 145dd243e..494d63e61 100644 --- a/client/mifare4.c +++ b/client/mifare4.c @@ -29,28 +29,28 @@ int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateF uint8_t cmd1[] = {0x70, keyn[1], keyn[0], 0x00}; int res = ExchangeRAW14a(cmd1, sizeof(cmd1), activateField, true, data, sizeof(data), &datalen); if (res) { - PrintAndLog("ERROR exchande raw error: %d", res); + PrintAndLogEx(ERR, "Exchande raw error: %d", res); DropField(); return 2; } if (verbose) - PrintAndLog("phase2: %s", sprint_hex(cmd2, 33)); + PrintAndLogEx(INFO, ">phase2: %s", sprint_hex(cmd2, 33)); res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, true, data, sizeof(data), &datalen); if (res) { - PrintAndLog("ERROR exchande raw error: %d", res); + PrintAndLogEx(ERR, "Exchande raw error: %d", res); DropField(); return 4; } if (verbose) - PrintAndLog("Rnd2, Rnd2, 16); } - PrintAndLog("Authentication OK"); + PrintAndLogEx(INFO, "Authentication OK"); return 0; } From 122cbe7d1dded6ed384663f38a6996afd1a40f6c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 24 Oct 2018 19:19:15 +0300 Subject: [PATCH 0100/1938] info and some fix in exchange --- client/cmdhf14a.c | 28 +++++++++++++++++++--------- 1 file changed, 19 insertions(+), 9 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index de1854630..7880bf38f 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -669,10 +669,12 @@ int CmdHF14ASniff(const char *Cmd) { } int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { + static bool responseNum = false; uint16_t cmdc = 0; *dataoutlen = 0; if (activateField) { + responseNum = false; UsbCommand resp; // Anticollision + SELECT card @@ -685,7 +687,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav // check result if (resp.arg[0] == 0) { - PrintAndLogEx(NORMAL, "No card in field."); + PrintAndLogEx(ERR, "No card in field."); return 1; } @@ -715,8 +717,11 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav if (leaveSignalON) cmdc |= ISO14A_NO_DISCONNECT; - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF), 0}}; - memcpy(c.d.asBytes, datain, datainlen); + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF) + 2, 0}}; + uint8_t header[] = {0x0a | responseNum, 0x00}; + responseNum ^= 1; + memcpy(c.d.asBytes, header, 2); + memcpy(&c.d.asBytes[2], datain, datainlen); SendCommand(&c); uint8_t *recv; @@ -726,6 +731,11 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav recv = resp.d.asBytes; int iLen = resp.arg[0]; + if(!iLen) { + PrintAndLogEx(ERR, "No card response."); + return 1; + } + *dataoutlen = iLen - 2; if (*dataoutlen < 0) *dataoutlen = 0; @@ -735,13 +745,13 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav return 2; } - memcpy(dataout, recv, *dataoutlen); - - if(!iLen) { - PrintAndLogEx(ERR, "No card response."); - return 1; + if (recv[0] != header[0]) { + PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", dataout[0], header[0]); + return 2; } - + + memcpy(dataout, &recv[2], *dataoutlen); + // CRC Check if (iLen == -1) { PrintAndLogEx(ERR, "ISO 14443A CRC error."); From b08ce3a1f75db30ffc05f228db28e65b3ef2fdd6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 24 Oct 2018 19:19:55 +0300 Subject: [PATCH 0101/1938] changed logs --- client/cmdhfmfp.c | 58 +++++++++++++++++++++++------------------------ 1 file changed, 29 insertions(+), 29 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 7ba1c2561..b50b3bdd3 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -119,36 +119,36 @@ int CmdHFMFPInfo(const char *cmd) { uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision if (select_status == 1 || select_status == 2) { - PrintAndLogEx(INFO, "----------------------------------------------"); - PrintAndLogEx(INFO, "Mifare Plus info:"); + PrintAndLogEx(NORMAL, "----------------------------------------------"); + PrintAndLogEx(NORMAL, "Mifare Plus info:"); // MIFARE Type Identification Procedure // https://www.nxp.com/docs/en/application-note/AN10833.pdf uint16_t ATQA = card.atqa[0] + (card.atqa[1] << 8); - if (ATQA == 0x0004) PrintAndLog("ATQA: Mifare Plus 2k 4bUID"); - if (ATQA == 0x0002) PrintAndLog("ATQA: Mifare Plus 4k 4bUID"); - if (ATQA == 0x0044) PrintAndLog("ATQA: Mifare Plus 2k 7bUID"); - if (ATQA == 0x0042) PrintAndLog("ATQA: Mifare Plus 4k 7bUID"); + if (ATQA == 0x0004) PrintAndLogEx(INFO, "ATQA: Mifare Plus 2k 4bUID"); + if (ATQA == 0x0002) PrintAndLogEx(INFO, "ATQA: Mifare Plus 4k 4bUID"); + if (ATQA == 0x0044) PrintAndLogEx(INFO, "ATQA: Mifare Plus 2k 7bUID"); + if (ATQA == 0x0042) PrintAndLogEx(INFO, "ATQA: Mifare Plus 4k 7bUID"); uint8_t SLmode = 0xff; if (card.sak == 0x08) { - PrintAndLog("SAK: Mifare Plus 2k 7bUID"); + PrintAndLogEx(INFO, "SAK: Mifare Plus 2k 7bUID"); if (select_status == 2) SLmode = 1; } if (card.sak == 0x18) { - PrintAndLog("SAK: Mifare Plus 4k 7bUID"); + PrintAndLogEx(INFO, "SAK: Mifare Plus 4k 7bUID"); if (select_status == 2) SLmode = 1; } if (card.sak == 0x10) { - PrintAndLog("SAK: Mifare Plus 2k"); + PrintAndLogEx(INFO, "SAK: Mifare Plus 2k"); if (select_status == 2) SLmode = 2; } if (card.sak == 0x11) { - PrintAndLog("SAK: Mifare Plus 4k"); + PrintAndLogEx(INFO, "SAK: Mifare Plus 4k"); if (select_status == 2) SLmode = 2; } if (card.sak == 0x20) { - PrintAndLog("SAK: Mifare Plus SL0/SL3 or Mifare desfire"); + PrintAndLogEx(INFO, "SAK: Mifare Plus SL0/SL3 or Mifare desfire"); if (card.ats_len > 0) { SLmode = 3; @@ -529,12 +529,12 @@ int CmdHFMFPRdsc(const char *cmd) { } if (sectorNum > 39) { - PrintAndLog("ERROR: must be in range [0..39] instead of: %d", sectorNum); + PrintAndLogEx(ERR, " must be in range [0..39] instead of: %d", sectorNum); return 1; } if (keylen != 16) { - PrintAndLog("ERROR: must be 16 bytes long instead of: %d", keylen); + PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); return 1; } @@ -542,12 +542,12 @@ int CmdHFMFPRdsc(const char *cmd) { keyn[0] = uKeyNum >> 8; keyn[1] = uKeyNum & 0xff; if (verbose) - PrintAndLog("--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); + PrintAndLogEx(INFO, "--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); mf4Session session; int res = MifareAuth4(&session, keyn, key, true, true, verbose); if (res) { - PrintAndLog("Authentication error: %d", res); + PrintAndLogEx(ERR, "Authentication error: %d", res); return res; } @@ -556,26 +556,26 @@ int CmdHFMFPRdsc(const char *cmd) { for(int n = mfFirstBlockOfSector(sectorNum); n < mfFirstBlockOfSector(sectorNum) + mfNumBlocksPerSector(sectorNum); n++) { res = MFPReadBlock(&session, plain, n & 0xff, 1, false, true, data, sizeof(data), &datalen); if (res) { - PrintAndLog("Read error: %d", res); + PrintAndLogEx(ERR, "Read error: %d", res); DropField(); return res; } if (datalen && data[0] != 0x90) { - PrintAndLog("Card read error: %02x %s", data[0], GetErrorDescription(data[0])); + PrintAndLogEx(ERR, "Card read error: %02x %s", data[0], GetErrorDescription(data[0])); DropField(); return 6; } if (datalen != 1 + 16 + 8 + 2) { - PrintAndLog("Error return length:%d", datalen); + PrintAndLogEx(ERR, "Error return length:%d", datalen); DropField(); return 5; } - PrintAndLog("data[%03d]: %s", n, sprint_hex(&data[1], 16)); + PrintAndLogEx(INFO, "data[%03d]: %s", n, sprint_hex(&data[1], 16)); if(verbose) - PrintAndLog("MAC: %s", sprint_hex(&data[1 + 16], 8)); + PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1 + 16], 8)); } DropField(); @@ -618,17 +618,17 @@ int CmdHFMFPWrbl(const char *cmd) { } if (blockNum > 39) { - PrintAndLog("ERROR: must be in range [0..255] instead of: %d", blockNum); + PrintAndLogEx(ERR, " must be in range [0..255] instead of: %d", blockNum); return 1; } if (keylen != 16) { - PrintAndLog("ERROR: must be 16 bytes long instead of: %d", keylen); + PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); return 1; } if (datainlen != 16) { - PrintAndLog("ERROR: must be 16 bytes long instead of: %d", datainlen); + PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", datainlen); return 1; } @@ -637,12 +637,12 @@ int CmdHFMFPWrbl(const char *cmd) { keyn[0] = uKeyNum >> 8; keyn[1] = uKeyNum & 0xff; if (verbose) - PrintAndLog("--block:%d sector[%d]:%02x key:%04x", blockNum & 0xff, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); + PrintAndLogEx(INFO, "--block:%d sector[%d]:%02x key:%04x", blockNum & 0xff, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); mf4Session session; int res = MifareAuth4(&session, keyn, key, true, true, verbose); if (res) { - PrintAndLog("Authentication error: %d", res); + PrintAndLogEx(ERR, "Authentication error: %d", res); return res; } @@ -650,22 +650,22 @@ int CmdHFMFPWrbl(const char *cmd) { int datalen = 0; res = MFPWriteBlock(&session, blockNum & 0xff, datain, false, false, data, sizeof(data), &datalen); if (res) { - PrintAndLog("Write error: %d", res); + PrintAndLogEx(ERR, "Write error: %d", res); return res; } if (datalen != 3 && (datalen != 3 + 8)) { - PrintAndLog("Error return length:%d", datalen); + PrintAndLogEx(ERR, "Error return length:%d", datalen); return 5; } if (datalen && data[0] != 0x90) { - PrintAndLog("Card write error: %02x %s", data[0], GetErrorDescription(data[0])); + PrintAndLogEx(ERR, "Card write error: %02x %s", data[0], GetErrorDescription(data[0])); return 6; } if(verbose) - PrintAndLog("MAC: %s", sprint_hex(&data[1], 8)); + PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1], 8)); return 0; } From 8bb192fc75b8ef79431d1af567c2341f277e684d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 26 Oct 2018 14:12:20 +0300 Subject: [PATCH 0102/1938] added some crypto --- client/Makefile | 1 + client/mifare4.c | 12 ++ client/mifare4.h | 2 + common/polarssl/aes_cmac128.c | 322 ++++++++++++++++++++++++++++++++++ common/polarssl/aes_cmac128.h | 81 +++++++++ common/polarssl/libpcrypto.c | 40 ++++- common/polarssl/libpcrypto.h | 2 + 7 files changed, 459 insertions(+), 1 deletion(-) create mode 100644 common/polarssl/aes_cmac128.c create mode 100644 common/polarssl/aes_cmac128.h diff --git a/client/Makefile b/client/Makefile index c832d9e49..a31be08d5 100644 --- a/client/Makefile +++ b/client/Makefile @@ -105,6 +105,7 @@ CMDSRCS = crapto1/crapto1.c \ tea.c \ polarssl/des.c \ polarssl/aes.c \ + polarssl/aes_cmac128.c \ polarssl/bignum.c \ polarssl/rsa.c \ polarssl/sha1.c \ diff --git a/client/mifare4.c b/client/mifare4.c index 494d63e61..2ca28cb3f 100644 --- a/client/mifare4.c +++ b/client/mifare4.c @@ -16,6 +16,18 @@ #include "ui.h" #include "polarssl/libpcrypto.h" +int CalulateMAC(mf4Session *session, uint8_t *data, int datalen, uint8_t *mac, bool verbose) { + if (!session || !session->Authenticated || !mac || !data || !datalen) + return 1; + + memset(mac, 0x00, 8); + + if (verbose) + PrintAndLog("MAC data[%d]: %s", datalen, sprint_hex(data, datalen)); + + return aes_cmac8(NULL, session->Key, data, mac, datalen); +} + int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose) { uint8_t data[257] = {0}; int datalen = 0; diff --git a/client/mifare4.h b/client/mifare4.h index d26152cb4..7867add5d 100644 --- a/client/mifare4.h +++ b/client/mifare4.h @@ -17,12 +17,14 @@ typedef struct { bool Authenticated; + uint8_t Key[16]; uint16_t KeyNum; uint8_t Rnd1[16]; uint8_t Rnd2[16]; }mf4Session; +extern int CalulateMAC(mf4Session *session, uint8_t *data, int datalen, uint8_t *mac, bool verbose); extern int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose); extern uint8_t mfNumBlocksPerSector(uint8_t sectorNo); diff --git a/common/polarssl/aes_cmac128.c b/common/polarssl/aes_cmac128.c new file mode 100644 index 000000000..595f89b8d --- /dev/null +++ b/common/polarssl/aes_cmac128.c @@ -0,0 +1,322 @@ +/* + * AES-CMAC from NIST Special Publication 800-38B Recommendation for block cipher modes of operation: The CMAC mode for authentication. + * + * Copyright (C) 2006-2014, Brainspark B.V. + * Copyright (C) 2014, Anargyros Plemenos + * Tests added Merkok, 2018 + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * 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. + * + * Reference : https://polarssl.org/discussions/generic/authentication-token + * NIST Special Publication 800-38B Recommendation for block cipher modes of operation: The CMAC mode for authentication. + * Tests here: + * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf +*/ + +#include "polarssl/aes_cmac128.h" +#include + +#define MIN(a,b) ((a)<(b)?(a):(b)) +#define _MSB(x) (((x)[0] & 0x80)?1:0) + +#if !defined(POLARSSL_CONFIG_FILE) +#include "polarssl_config.h" +#else +#include POLARSSL_CONFIG_FILE +#endif + +#if defined(POLARSSL_AES_C) +#include "aes.h" +#endif + +#if defined(POLARSSL_PLATFORM_C) +#include "polarssl/platform.h" +#else +#define polarssl_printf printf +#endif + + +/** + * zero a structure + */ +#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x)) + +/** + * zero a structure given a pointer to the structure + */ +#define ZERO_STRUCTP(x) do{ if((x) != NULL) memset((char *)(x), 0, sizeof(*(x)));} while(0) + + +/* For CMAC Calculation */ +static unsigned char const_Rb[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 +}; +static unsigned char const_Zero[16] = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static inline void aes_cmac_128_left_shift_1(const uint8_t in[16], uint8_t out[16]) +{ + uint8_t overflow = 0; + int8_t i; + + for (i = 15; i >= 0; i--) { + out[i] = in[i] << 1; + out[i] |= overflow; + overflow = _MSB(&in[i]); + } +} + +static inline void aes_cmac_128_xor(const uint8_t in1[16], const uint8_t in2[16], + uint8_t out[16]) +{ + uint8_t i; + + for (i = 0; i < 16; i++) { + out[i] = in1[i] ^ in2[i]; + } +} + +/* + * AES-CMAC-128 context setup + */ +void aes_cmac128_starts(aes_cmac128_context *ctx, const uint8_t K[16]) +{ + uint8_t L[16]; + + /* Zero struct of aes_context */ + ZERO_STRUCTP(ctx); + /* Initialize aes_context */ + aes_setkey_enc(&ctx->aes_key, K, 128); + + /* step 1 - generate subkeys k1 and k2 */ + aes_crypt_ecb(&ctx->aes_key, AES_ENCRYPT, const_Zero, L); + + if (_MSB(L) == 0) { + aes_cmac_128_left_shift_1(L, ctx->K1); + } else { + uint8_t tmp_block[16]; + + aes_cmac_128_left_shift_1(L, tmp_block); + aes_cmac_128_xor(tmp_block, const_Rb, ctx->K1); + ZERO_STRUCT(tmp_block); + } + + if (_MSB(ctx->K1) == 0) { + aes_cmac_128_left_shift_1(ctx->K1, ctx->K2); + } else { + uint8_t tmp_block[16]; + + aes_cmac_128_left_shift_1(ctx->K1, tmp_block); + aes_cmac_128_xor(tmp_block, const_Rb, ctx->K2); + ZERO_STRUCT(tmp_block); + } + + ZERO_STRUCT(L); +} + +/* + * AES-CMAC-128 process message + */ +void aes_cmac128_update(aes_cmac128_context *ctx, const uint8_t *_msg, size_t _msg_len) +{ + uint8_t tmp_block[16]; + uint8_t Y[16]; + const uint8_t *msg = _msg; + size_t msg_len = _msg_len; + + /* + * copy the remembered last block + */ + ZERO_STRUCT(tmp_block); + if (ctx->last_len) { + memcpy(tmp_block, ctx->last, ctx->last_len); + } + + /* + * check if we expand the block + */ + if (ctx->last_len < 16) { + size_t len = MIN(16 - ctx->last_len, msg_len); + + memcpy(&tmp_block[ctx->last_len], msg, len); + memcpy(ctx->last, tmp_block, 16); + msg += len; + msg_len -= len; + ctx->last_len += len; + } + + if (msg_len == 0) { + /* if it is still the last block, we are done */ + ZERO_STRUCT(tmp_block); + return; + } + + /* + * It is not the last block anymore + */ + ZERO_STRUCT(ctx->last); + ctx->last_len = 0; + + /* + * now checksum everything but the last block + */ + aes_cmac_128_xor(ctx->X, tmp_block, Y); + aes_crypt_ecb(&ctx->aes_key, AES_ENCRYPT, Y, ctx->X); + + while (msg_len > 16) { + memcpy(tmp_block, msg, 16); + msg += 16; + msg_len -= 16; + + aes_cmac_128_xor(ctx->X, tmp_block, Y); + aes_crypt_ecb(&ctx->aes_key, AES_ENCRYPT, Y, ctx->X); + } + + /* + * copy the last block, it will be processed in + * aes_cmac128_final(). + */ + memcpy(ctx->last, msg, msg_len); + ctx->last_len = msg_len; + + ZERO_STRUCT(tmp_block); + ZERO_STRUCT(Y); +} + +/* + * AES-CMAC-128 compute T + */ +void aes_cmac128_final(aes_cmac128_context *ctx, uint8_t T[16]) +{ + uint8_t tmp_block[16]; + uint8_t Y[16]; + + if (ctx->last_len < 16) { + ctx->last[ctx->last_len] = 0x80; + aes_cmac_128_xor(ctx->last, ctx->K2, tmp_block); + } else { + aes_cmac_128_xor(ctx->last, ctx->K1, tmp_block); + } + + aes_cmac_128_xor(tmp_block, ctx->X, Y); + aes_crypt_ecb(&ctx->aes_key, AES_ENCRYPT, Y, T); + + ZERO_STRUCT(tmp_block); + ZERO_STRUCT(Y); + ZERO_STRUCTP(ctx); +} + +/* + * Checkup routine + * + * https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values + * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf + */ +int aes_cmac_self_test( int verbose ) +{ + unsigned char key[16] = {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C}; + unsigned char mac[16] = {0}; + aes_cmac128_context ctx; + int ret; + + // check Example1: + if( verbose != 0 ) + polarssl_printf( " AES-CMAC-128 zero length data: " ); + unsigned char ex1data[16] = {0}; + aes_cmac128_starts(&ctx, key); + aes_cmac128_update(&ctx, ex1data, 0); + aes_cmac128_final(&ctx, mac); + unsigned char ex1res[16] = {0xBB, 0x1D, 0x69, 0x29, 0xE9, 0x59, 0x37, 0x28, 0x7F, 0xA3, 0x7D, 0x12, 0x9B, 0x75, 0x67, 0x46}; + if(!memcmp(mac, ex1res, 16)) { + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } else { + polarssl_printf( "failed\n" ); + ret = 1; + goto exit; + } + + // check Example2: + if( verbose != 0 ) + polarssl_printf( " AES-CMAC-128 one block data : " ); + unsigned char ex2data[16] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A}; + aes_cmac128_starts(&ctx, key); + aes_cmac128_update(&ctx, ex2data, sizeof(ex2data)); + aes_cmac128_final(&ctx, mac); + unsigned char ex2res[16] = {0x07, 0x0A, 0x16, 0xB4, 0x6B, 0x4D, 0x41, 0x44, 0xF7, 0x9B, 0xDD, 0x9D, 0xD0, 0x4A, 0x28, 0x7C}; + if(!memcmp(mac, ex2res, 16)) { + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } else { + polarssl_printf( "failed\n" ); + ret = 1; + goto exit; + } + + // check Example3: + if( verbose != 0 ) + polarssl_printf( " AES-CMAC-128 20 bytes of data: " ); + unsigned char ex3data[20] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57}; + aes_cmac128_starts(&ctx, key); + aes_cmac128_update(&ctx, ex3data, sizeof(ex3data)); + aes_cmac128_final(&ctx, mac); + unsigned char ex3res[16] = {0x7D, 0x85, 0x44, 0x9E, 0xA6, 0xEA, 0x19, 0xC8, 0x23, 0xA7, 0xBF, 0x78, 0x83, 0x7D, 0xFA, 0xDE}; + if(!memcmp(mac, ex3res, 16)) { + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } else { + polarssl_printf( "failed\n" ); + ret = 1; + goto exit; + } + + // check Example4: + if( verbose != 0 ) + polarssl_printf( " AES-CMAC-128 4 blocks of data: " ); + unsigned char ex4data[64] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, + 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10}; + aes_cmac128_starts(&ctx, key); + aes_cmac128_update(&ctx, ex4data, sizeof(ex4data)); + aes_cmac128_final(&ctx, mac); + unsigned char ex4res[16] = {0x51, 0xF0, 0xBE, 0xBF, 0x7E, 0x3B, 0x9D, 0x92, 0xFC, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3C, 0xFE}; + if(!memcmp(mac, ex4res, 16)) { + if( verbose != 0 ) + polarssl_printf( "passed\n" ); + } else { + polarssl_printf( "failed\n" ); + ret = 1; + goto exit; + } + + if( verbose != 0 ) + polarssl_printf( "\n" ); + + ret = 0; + +exit: + return( ret ); +} + diff --git a/common/polarssl/aes_cmac128.h b/common/polarssl/aes_cmac128.h new file mode 100644 index 000000000..b792755fc --- /dev/null +++ b/common/polarssl/aes_cmac128.h @@ -0,0 +1,81 @@ +/* + * AES-CMAC from NIST Special Publication 800-38B Recommendation for block cipher modes of operation: The CMAC mode for authentication. + * + * Copyright (C) 2006-2014, Brainspark B.V. + * Copyright (C) 2014, Anargyros Plemenos + * Tests added Merkok, 2018 + * + * This file is part of PolarSSL (http://www.polarssl.org) + * Lead Maintainer: Paul Bakker + * + * All rights reserved. + * + * 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. + * + * Reference : https://polarssl.org/discussions/generic/authentication-token + * NIST Special Publication 800-38B Recommendation for block cipher modes of operation: The CMAC mode for authentication. + * Tests here: + * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf +*/ + +#include +#include +#include "aes.h" + +typedef struct aes_cmac_128_context { + aes_context aes_key; + + uint8_t K1[16]; + uint8_t K2[16]; + + uint8_t X[16]; + + uint8_t last[16]; + size_t last_len; +} +aes_cmac128_context; + +/* + * \brief AES-CMAC-128 context setup + * + * \param ctx context to be initialized + * \param key secret key for AES-128 + */ +void aes_cmac128_starts(aes_cmac128_context *ctx, const uint8_t K[16]); + +/* + * \brief AES-CMAC-128 process message + * + * \param ctx context to be initialized + * \param _msg the given message + * \param _msg_len the length of message + */ +void aes_cmac128_update(aes_cmac128_context *ctx, const uint8_t *_msg, size_t _msg_len); + +/* + * \brief AES-CMAC-128 compute T + * + * \param ctx context to be initialized + * \param T the generated MAC which is used to validate the message + */ +void aes_cmac128_final(aes_cmac128_context *ctx, uint8_t T[16]); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int aes_cmac_self_test( int verbose ); + diff --git a/common/polarssl/libpcrypto.c b/common/polarssl/libpcrypto.c index 032c3a18b..d86c97568 100644 --- a/common/polarssl/libpcrypto.c +++ b/common/polarssl/libpcrypto.c @@ -10,6 +10,7 @@ #include "polarssl/libpcrypto.h" #include +#include int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){ uint8_t iiv[16] = {0}; @@ -41,4 +42,41 @@ int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int l aes_free(&aes); return 0; -} \ No newline at end of file +} + +// NIST Special Publication 800-38B Recommendation for block cipher modes of operation: The CMAC mode for authentication. +// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf +int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length) { + memset(mac, 0x00, 16); + uint8_t iiv[16] = {0}; + if (iv) + memcpy(iiv, iv, 16); + + // padding: ISO/IEC 9797-1 Message Authentication Codes (MACs) - Part 1: Mechanisms using a block cipher + uint8_t data[2049] = {0}; // length + 16 + memcpy(data, input, length); + data[length] = 0x80; + int datalen = (length & 0xfffffff0) + 0x10; + + // NIST 800-38B + aes_cmac128_context ctx; + aes_cmac128_starts(&ctx, key); + aes_cmac128_update(&ctx, data, datalen); + aes_cmac128_final(&ctx, mac); + + return 0; +} + +int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length) { + uint8_t cmac[16] = {0}; + memset(mac, 0x00, 8); + + int res = aes_cmac(iv, key, input, cmac, length); + if (res) + return res; + + for(int i = 0; i < 8; i++) + mac[i] = cmac[i * 2 + 1]; + + return 0; +} diff --git a/common/polarssl/libpcrypto.h b/common/polarssl/libpcrypto.h index 84732cd31..1b74c143f 100644 --- a/common/polarssl/libpcrypto.h +++ b/common/polarssl/libpcrypto.h @@ -16,5 +16,7 @@ extern int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); extern int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); +extern int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length); +extern int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length); #endif /* libpcrypto.h */ From 7467368fbc02b33d161801dacf5b6b2fa3c701fd Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 26 Oct 2018 14:17:08 +0300 Subject: [PATCH 0103/1938] added cmac test --- client/emv/test/cryptotest.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/emv/test/cryptotest.c b/client/emv/test/cryptotest.c index 8cc3812c1..b9be38ad5 100644 --- a/client/emv/test/cryptotest.c +++ b/client/emv/test/cryptotest.c @@ -14,6 +14,7 @@ #include "bignum.h" #include "aes.h" +#include "aes_cmac128.h" #include "des.h" #include "rsa.h" #include "sha1.h" @@ -33,6 +34,9 @@ int ExecuteCryptoTests(bool verbose) { res = aes_self_test(verbose); if (res) TestFail = true; + res = aes_cmac_self_test(verbose); + if (res) TestFail = true; + res = des_self_test(verbose); if (res) TestFail = true; From af278d977bb47e4694ddb24401cb1115c5282af6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 26 Oct 2018 14:19:10 +0300 Subject: [PATCH 0104/1938] added SetVerboseMode 6bb33f377663126fbf645d8faaf00d4a1734f924 --- client/cmdhfmfp.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index b50b3bdd3..cc64297e8 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -426,6 +426,8 @@ int CmdHFMFPRdbl(const char *cmd) { CLIGetHexWithReturn(6, key, &keylen); CLIParserFree(); + SetVerboseMode(verbose); + if (!keylen) { memmove(key, DefaultKey, 16); keylen = 16; @@ -523,6 +525,8 @@ int CmdHFMFPRdsc(const char *cmd) { CLIGetHexWithReturn(5, key, &keylen); CLIParserFree(); + SetVerboseMode(verbose); + if (!keylen) { memmove(key, DefaultKey, 16); keylen = 16; @@ -612,6 +616,8 @@ int CmdHFMFPWrbl(const char *cmd) { CLIGetHexWithReturn(5, key, &keylen); CLIParserFree(); + SetVerboseMode(verbose); + if (!keylen) { memmove(key, DefaultKey, 16); keylen = 16; From 6dc02ff49b339f2db03b99c9c9296760ba3136ae Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 26 Oct 2018 14:59:07 +0300 Subject: [PATCH 0105/1938] new appveyor --- appveyor.yml | 51 +++++++++++++++++++++++++++++++++++++++++---------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/appveyor.yml b/appveyor.yml index 65aeab1d9..a38ff647b 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -66,9 +66,20 @@ clone_script: Write-Host "[ OK ]" -ForegroundColor Green - Write-Host "Fill msys\etc\fstab file..." -NoNewLine + Write-Host "Fill msys2\etc\fstab file..." -NoNewLine - New-Item c:\ProxSpace\msys\etc\fstab -type file -force -value "#Win32_Path Mount_Point`nc:\ProxSpace\devkitARM /devkitARM`nc:\ProxSpace\Qt\5.6 /qt `nc:\ProxSpace\pm3 /pm3`n" + New-Item c:\ProxSpace\msys2\etc\fstab -type file -force -value "# For a description of the file format, see the Users Guide`n# http://cygwin.com/cygwin-ug-net/using.html#mount-table`nnone / cygdrive binary,posix=0,noacl,user 0 0 `nC:\ProxSpace\pm3 /pm3 ntfs noacl 0 0 `nC:\ProxSpace\gcc-arm-none-eabi /gcc-arm-none-eabi ntfs noacl 0 0 `n" + + Write-Host "[ OK ]" -ForegroundColor Green + + + Write-Host "Update msys2 packages..." -NoNewLine + + $env:Path = "C:\ProxSpace\msys2\usr\bin;C:\ProxSpace\msys2\mingw32\bin;C:\ProxSpace\gcc-arm-none-eabi\bin;$env:Path" + + C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null 1> msys1.txt 2>&1 + + C:\ProxSpace\msys2\msys2_shell.cmd -mingw32 -defterm -no-start /dev/null 1> msys1.txt 2>&1 Write-Host "[ OK ]" -ForegroundColor Green install: @@ -84,12 +95,25 @@ install: } build_script: - ps: >- - $env:Path = "C:\ProxSpace\msys\bin;$env:Path" + "C:\ProxSpace\msys2\usr\bin;C:\ProxSpace\msys2\mingw32\bin;C:\ProxSpace\gcc-arm-none-eabi\bin;$env:Path" + + + $env:MINGW_HOME="C:\ProxSpace\msys2\mingw32" + + $env:MSYS_HOME="C:\ProxSpace\msys2" + + $env:MSYSTEM="MINGW32" + + $env:MINGW_PREFIX="/mingw32" + + $env:SHELL="/bin/bash" + + $env:MSYSTEM_CHOST="i686-w64-mingw32" #make - bash -lc -i "pwd;make all" + bash -c -i 'pwd;make clean;make all' #some checks @@ -232,8 +256,8 @@ test_script: #--- end Job [bool]$res=$false - # Wait 60 sec timeout for Job - if(Wait-Job $Job -Timeout 60){ + # Wait 120 sec timeout for Job + if(Wait-Job $Job -Timeout 150){ $Results = $Job | Receive-Job if($Results -like "true"){ $res=$true @@ -268,13 +292,20 @@ test_script: #proxmark logic tests - ExecTest "proxmark help" "proxmark3 -h" {bash -lc 'cd ~/client;proxmark3 -h | grep -q Execute && echo Passed || echo Failed'} + ExecTest "proxmark help" "proxmark3 -h" {bash -lc 'cd ~/client;./proxmark3 -h | grep -q Execute && echo Passed || echo Failed'} - ExecTest "proxmark help hardnested" "proxmark3 -h" {bash -lc 'cd ~/client;proxmark3 -h | grep -q hardnested && echo Passed || echo Failed'} + ExecTest "proxmark help hardnested" "proxmark3 -h" {bash -lc 'cd ~/client;./proxmark3 -h | grep -q hardnested && echo Passed || echo Failed'} - ExecTest "hf mf offline text" "hf mf" {bash -lc "cd ~/client;proxmark3 comx -c 'hf mf'"} "at_enc" - ExecTest "hf mf hardnested" "hf mf hardnested" {bash -lc "cd ~/client;proxmark3 comx -c 'hf mf hardnested t 1 000000000000'"} "found:" + ExecTest "hf mf offline text" "hf mf" {bash -lc "cd ~/client;./proxmark3 comx -c 'hf mf'"} "at_enc" + + ExecTest "hf mf hardnested" "hf mf hardnested" {bash -lc "cd ~/client;./proxmark3 comx -c 'hf mf hardnested t 1 000000000000'"} "found:" + + + #proxmark crypto tests + + ExecTest "hf emv test" "hf emv test" {bash -lc "cd ~/client;./proxmark3 comx -c 'hf emv test'"} "Tests ?OK" + if ($global:TestsPassed) { Write-Host "Tests [ OK ]" -ForegroundColor Green From 785ab8f73ea7374cd93e7afbbe8b4c74e4646a0a Mon Sep 17 00:00:00 2001 From: bogiton <34060135+bogiton@users.noreply.github.com> Date: Sun, 28 Oct 2018 12:01:36 +0000 Subject: [PATCH 0106/1938] Baudrate and optimization (removed counter) --- armsrc/Standalone/hf_bog.c | 174 +++++++++---------------------------- 1 file changed, 43 insertions(+), 131 deletions(-) diff --git a/armsrc/Standalone/hf_bog.c b/armsrc/Standalone/hf_bog.c index 5a279ebd9..38d08c320 100644 --- a/armsrc/Standalone/hf_bog.c +++ b/armsrc/Standalone/hf_bog.c @@ -8,68 +8,29 @@ #include "hf_bog.h" #define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8) -#define DELAY_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8) -#define MAX_PWDS_PER_SESSION 15 +#define DELAY_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8) -uint8_t ReadCounterFromFlash() { - uint8_t mem = 0; +// Maximum number of auth attempts per standalone session +#define MAX_PWDS_PER_SESSION 20 - uint8_t isok = Flash_ReadData(0, &mem, 1); - if (isok == 1) + +uint8_t FindOffsetInFlash() { + uint8_t mem[4] = { 0x00, 0x00, 0x00, 0x00 }; + uint8_t eom[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; + uint8_t memcnt = 0; + + while (1) { - return mem; + Flash_ReadData(memcnt, mem, 4); + if (memcmp(mem, eom, 4) == 0) { + break; + } + memcnt += 4; } - Dbprintf("Reading of counter from flashmem failed"); - return -1; + return memcnt; } -uint8_t* ReadDataFromFlash(uint8_t datacnt) { - - uint16_t isok = 0; - - if (!datacnt) - { - uint8_t *tmp = BigBuf_malloc(4); - for (int i=0;i<4;i++) - tmp[i] = 0x00; - return tmp; - } - - size_t size = (datacnt + 1) * 4; - uint8_t *mem = BigBuf_malloc(size); - - isok = Flash_ReadData(0, mem, (datacnt + 1) * 4); - if (isok == ((datacnt + 1) * 4)) - { - Dbprintf("[OK] Data recovered from flashmem"); - return mem; - } - - Dbprintf("FlashMem reading failed | isok = %d", isok); - SpinDelay(100); - return 0; -} - -/* -void WriteDataToFlash(uint8_t *data, size_t size) -{ - uint8_t isok = 0; - - isok = Flash_WriteData(0, data, size); - - if (!isok) - { - Dbprintf("FlashMem write failed"); - SpinDelay(100); - - return; - } - - Dbprintf("[OK] Data written to flash!"); -} -*/ - void EraseMemory() { if (!FlashInit()){ @@ -80,60 +41,11 @@ void EraseMemory() Flash_WriteEnable(); Flash_Erase4k(0,0); - Dbprintf("[OK] Erased flash!"); + if (MF_DBGLEVEL > 1) Dbprintf("[!] Erased flash!"); FlashStop(); SpinDelay(100); } - -void WriteDataToFlash(uint8_t* data, size_t size) -{ - uint8_t isok = 0; - uint16_t res = 0; - uint32_t len = size; - uint32_t bytes_sent = 0; - uint32_t bytes_remaining = len; - - uint8_t buff[PAGESIZE]; - - if (!FlashInit()){ - return; - } - - Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); - Flash_Erase4k(0,0); - - while (bytes_remaining > 0) - { - Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); - - uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); - - memcpy(buff, data + bytes_sent, bytes_in_packet); - - bytes_remaining -= bytes_in_packet; - res = Flash_WriteDataCont(bytes_sent, buff, bytes_in_packet); - bytes_sent += bytes_in_packet; - - isok = (res == bytes_in_packet) ? 1 : 0; - - if (!isok) - { - Dbprintf("FlashMem write failed [offset %u]", bytes_sent); - SpinDelay(100); - - return; - } - } - - Dbprintf("[OK] Data written to flash! [0-to offset %u]", bytes_sent); - FlashStop(); - - return; -} - void RAMFUNC SniffAndStore(uint8_t param) { // Array to store the authpwds @@ -242,7 +154,7 @@ void RAMFUNC SniffAndStore(uint8_t param) { if (triggered) { if ((receivedCmd) && ((receivedCmd[0] == MIFARE_ULEV1_AUTH) || (receivedCmd[0] == MIFARE_ULC_AUTH_1))) { - Dbprintf("PWD-AUTH KEY: 0x%02x%02x%02x%02x", receivedCmd[1], receivedCmd[2], receivedCmd[3], receivedCmd[4]); + if (MF_DBGLEVEL > 1) Dbprintf("PWD-AUTH KEY: 0x%02x%02x%02x%02x", receivedCmd[1], receivedCmd[2], receivedCmd[3], receivedCmd[4]); // temporarily save the captured pwd in our array memcpy(&capturedPwds[4 * auth_attempts], receivedCmd+1, 4); @@ -309,50 +221,51 @@ void RAMFUNC SniffAndStore(uint8_t param) { // Write stuff to flash if (auth_attempts > 0) { - Dbprintf("[!] auth_attempts = %u", auth_attempts); + if (MF_DBGLEVEL > 1) Dbprintf("[!] Authentication attempts = %u", auth_attempts); - // Read from flash the counter of pwds (to be used as flash mem offset) - uint8_t pwdcnt = 0; - pwdcnt = ReadCounterFromFlash(); - if (pwdcnt == 255) { - // Same as zero - pwdcnt = 0; - } - Dbprintf("[!] PWDs Offset = %u", pwdcnt); + // Setting the SPI Baudrate to 48MHz to avoid the bit-flip issue (https://github.com/RfidResearchGroup/proxmark3/issues/34) + FlashmemSetSpiBaudrate(48000000); - uint8_t *previousdata = ReadDataFromFlash(pwdcnt); + // Find the offset in flash mem to continue writing the auth attempts + uint8_t memoffset = FindOffsetInFlash(); + if (MF_DBGLEVEL > 1) Dbprintf("[!] Memory offset = %u", memoffset); - // total size = (pwdcnt+1)*4 + 4 * auth_attempts - size_t total_size = (pwdcnt+1)*4 + 4 * auth_attempts; + // Get previous data from flash mem + uint8_t *previousdata = BigBuf_malloc(memoffset); + uint16_t readlen = Flash_ReadData(0, previousdata, memoffset); + if (MF_DBGLEVEL > 1) Dbprintf("[!] Read %u bytes from flash mem", readlen); + // create new bigbuf to hold all data + size_t total_size = memoffset + 4 * auth_attempts; uint8_t *total_data = BigBuf_malloc(total_size); // Add the previousdata array into total_data array - memcpy(total_data, previousdata, sizeof(*previousdata) * ((pwdcnt+1)*4)); + memcpy(total_data, previousdata, memoffset); // Copy bytes of capturedPwds immediately following bytes of previousdata - memcpy(total_data + ((pwdcnt+1)*4), capturedPwds, sizeof(*capturedPwds) * (4 * auth_attempts)); + memcpy(total_data + memoffset, capturedPwds, 4 * auth_attempts); - // change the counter byte - //memset (total_data,pwdcnt + auth_attempts,1); - total_data[0] = (uint8_t)(pwdcnt + auth_attempts); + // Erase first page of flash mem + EraseMemory(); - //EraseMemory(); + //for (int i=0; i 1) Dbprintf("[-] total_data[%d] = 0x%02x", i, total_data[i]); - //for (int i=0;i<(pwdcnt+1)*4 + 4 * auth_attempts;i++) - // Dbprintf("[!] total_data[%d] = 0x%02x", i, total_data[i]); + // Write total data to flash mem + uint16_t writelen = Flash_WriteData(0, total_data, memoffset + 4 * auth_attempts); + if (MF_DBGLEVEL > 1) Dbprintf("[!] Wrote %u bytes into flash mem", writelen); - //Flash_WriteData(0, total_data, (pwdcnt+1)*4 + 4 * auth_attempts); - WriteDataToFlash(total_data, (pwdcnt+1)*4 + 4 * auth_attempts); + SpinDelay(100); - SpinDelay(200); + // Reset the SPI Baudrate to the default value (24MHz) + FlashmemSetSpiBaudrate(24000000); } } void RunMod() { Dbprintf("Sniffing started"); - SpinDelay(500); + SpinDelay(200); // param: // bit 0 - trigger from first card answer @@ -363,4 +276,3 @@ void RunMod() SpinDelay(300); } - From 9bd7770dfe9ee4c540f58c2af901741bd3335e58 Mon Sep 17 00:00:00 2001 From: bogiton <34060135+bogiton@users.noreply.github.com> Date: Sun, 28 Oct 2018 12:04:44 +0000 Subject: [PATCH 0107/1938] Revert to default standalone mode --- armsrc/Makefile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/Makefile b/armsrc/Makefile index 8a576f001..d1895e7fa 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -24,7 +24,7 @@ APP_CFLAGS = -DWITH_CRC \ -DWITH_FLASH \ -DWITH_SMARTCARD \ -DWITH_HFSNOOP \ - -DWITH_HF_BOG \ + -DWITH_LF_SAMYRUN \ -DWITH_FPC \ -fno-strict-aliasing -ffunction-sections -fdata-sections From 43f90181b3e1ded43b4a012925edac8e7a9bf17c Mon Sep 17 00:00:00 2001 From: bogiton <34060135+bogiton@users.noreply.github.com> Date: Sun, 28 Oct 2018 13:34:42 +0000 Subject: [PATCH 0108/1938] Update hf_bog.c --- armsrc/Standalone/hf_bog.c | 19 +++++++++---------- 1 file changed, 9 insertions(+), 10 deletions(-) diff --git a/armsrc/Standalone/hf_bog.c b/armsrc/Standalone/hf_bog.c index 38d08c320..108c7ad59 100644 --- a/armsrc/Standalone/hf_bog.c +++ b/armsrc/Standalone/hf_bog.c @@ -11,7 +11,7 @@ #define DELAY_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8) // Maximum number of auth attempts per standalone session -#define MAX_PWDS_PER_SESSION 20 +#define MAX_PWDS_PER_SESSION 64 uint8_t FindOffsetInFlash() { @@ -19,16 +19,16 @@ uint8_t FindOffsetInFlash() { uint8_t eom[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; uint8_t memcnt = 0; - while (1) + while (memcnt < 4096) { Flash_ReadData(memcnt, mem, 4); if (memcmp(mem, eom, 4) == 0) { - break; + return memcnt; } memcnt += 4; } - return memcnt; + return 0; // wrap-around } void EraseMemory() @@ -48,11 +48,6 @@ void EraseMemory() void RAMFUNC SniffAndStore(uint8_t param) { - // Array to store the authpwds - uint8_t *capturedPwds = BigBuf_malloc(4 * MAX_PWDS_PER_SESSION); - - SpinDelay(500); - /* This is actually copied from SniffIso14443a */ iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); @@ -63,6 +58,9 @@ void RAMFUNC SniffAndStore(uint8_t param) { clear_trace(); set_tracing(true); + // Array to store the authpwds + uint8_t *capturedPwds = BigBuf_malloc(4 * MAX_PWDS_PER_SESSION); + // The command (reader -> tag) that we're receiving. uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE); @@ -265,7 +263,8 @@ void RAMFUNC SniffAndStore(uint8_t param) { void RunMod() { Dbprintf("Sniffing started"); - SpinDelay(200); + + SpinDelay(200); // param: // bit 0 - trigger from first card answer From e14e47735512da332599afbf8fb67fb64fb45348 Mon Sep 17 00:00:00 2001 From: bogiton <34060135+bogiton@users.noreply.github.com> Date: Sun, 28 Oct 2018 13:48:27 +0000 Subject: [PATCH 0109/1938] Update CHANGELOG.md --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 20f1c1f8f..329eda594 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added HF sniff standalone mode with optional storing of ULC/NTAG/ULEV1 authentication attempts (@bogiton) - Fix 'Lining up plot and control window' (@anticat) - Fix 'annoying focus behaviour' on OSX (@Anticat) - Implemented AppNap API, fixing #283 and #627 OSX USB comm issues (@AntiCat) From 2718e783dc219dec632e996094172a2aaaff1aa9 Mon Sep 17 00:00:00 2001 From: bogiton <34060135+bogiton@users.noreply.github.com> Date: Sun, 28 Oct 2018 13:54:38 +0000 Subject: [PATCH 0110/1938] Added small description --- armsrc/Standalone/hf_bog.c | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/armsrc/Standalone/hf_bog.c b/armsrc/Standalone/hf_bog.c index 108c7ad59..761e67b1a 100644 --- a/armsrc/Standalone/hf_bog.c +++ b/armsrc/Standalone/hf_bog.c @@ -5,6 +5,19 @@ //----------------------------------------------------------------------------- // main code for standalone HF Sniff (and ULC/NTAG/ULEV1 pwd storing) //----------------------------------------------------------------------------- + +/* +This can actually be used in two separate ways. +It can either be used to just HF 14a sniff on the go and/or grab the +authentication attempts for ULC/NTAG/ULEV1 into the flash mem (RDV4). + +The retrieved sniffing session can be acquired by connecting the device +to a client that supports the reconnect capability and issue 'hf 14a list'. + +In order to view the grabbed authentication attempts in the flash mem, +you can simply 'mem read l 256' from the client to view the stored quadlets. +*/ + #include "hf_bog.h" #define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8) @@ -13,7 +26,6 @@ // Maximum number of auth attempts per standalone session #define MAX_PWDS_PER_SESSION 64 - uint8_t FindOffsetInFlash() { uint8_t mem[4] = { 0x00, 0x00, 0x00, 0x00 }; uint8_t eom[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; From bb359b356747ce049d88d3e79551f17ca4b70aba Mon Sep 17 00:00:00 2001 From: indigowor2 Date: Wed, 31 Oct 2018 16:56:14 +0000 Subject: [PATCH 0111/1938] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 329eda594..9ac0e7328 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -79,6 +79,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added to `hf 14a apdu` - apdu and tlv results parser (@merlokk) - Added 'hf emv' commands (@merlokk) - lots of bug fixes (many many) + - Changed hf mfp security. Now it works in all the modes. (drHatson) ### Fixed - Changed driver file proxmark3.inf to support both old and new Product/Vendor IDs (piwi) - Changed start sequence in Qt mode (fix: short commands hangs main Qt thread) (Merlok) From f29c94954f0d4958ba7947d11a44f61c900d4168 Mon Sep 17 00:00:00 2001 From: indigowor2 Date: Wed, 31 Oct 2018 17:39:32 +0000 Subject: [PATCH 0112/1938] merge --- client/cmdhfmfp.c | 109 +++++++++++++++++++++------- client/mifare4.c | 136 ++++++++++++++++++++++++++++++----- client/mifare4.h | 22 ++++-- common/polarssl/libpcrypto.c | 10 +-- 4 files changed, 222 insertions(+), 55 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index cc64297e8..78cec3e2c 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -1,5 +1,6 @@ //----------------------------------------------------------------------------- // Copyright (C) 2018 Merlok +// Copyright (C) 2018 drHatson // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -34,13 +35,15 @@ typedef struct { static const PlusErrorsElm PlusErrors[] = { {0xFF, ""}, - {0x00, "Unknown error"}, - {0x06, "Block use error"}, - {0x07, "Command use error"}, - {0x08, "Invalid write command"}, - {0x09, "Invalid block number"}, - {0x0b, "Command code error"}, + {0x00, "Transfer cannot be granted within the current authentication."}, + {0x06, "Access Conditions not fulfilled. Block does not exist, block is not a value block."}, + {0x07, "Too many read or write commands in the session or in the transaction."}, + {0x08, "Invalid MAC in command or response"}, + {0x09, "Block Number is not valid"}, + {0x0a, "Invalid block number, not existing block number"}, + {0x0b, "The current command code not available at the current card state."}, {0x0c, "Length error"}, + {0x0f, "General Manipulation Error. Failure in the operation of the PICC (cannot write to the data block), etc."}, {0x90, "OK"}, }; int PlusErrorsLen = sizeof(PlusErrors) / sizeof(PlusErrorsElm); @@ -85,17 +88,41 @@ int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int return intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); } -int MFPReadBlock(mf4Session *session, bool plain, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { +int MFPReadBlock(mf4Session *session, bool plain, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) { uint8_t rcmd[4 + 8] = {(plain?(0x37):(0x33)), blockNum, 0x00, blockCount}; + if (!plain && session) + CalculateMAC(session, mtypReadCmd, blockNum, blockCount, rcmd, 4, &rcmd[4], VerboseMode); - return intExchangeRAW14aPlus(rcmd, plain?4:sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); + int res = intExchangeRAW14aPlus(rcmd, plain?4:sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); + if(res) + return res; + + if (session) + session->R_Ctr++; + + if(session && mac && *dataoutlen > 11) + CalculateMAC(session, mtypReadResp, blockNum, blockCount, dataout, *dataoutlen - 8 - 2, mac, VerboseMode); + + return 0; } -int MFPWriteBlock(mf4Session *session, uint8_t blockNum, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { +int MFPWriteBlock(mf4Session *session, uint8_t blockNum, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) { uint8_t rcmd[1 + 2 + 16 + 8] = {0xA3, blockNum, 0x00}; memmove(&rcmd[3], data, 16); + if (session) + CalculateMAC(session, mtypWriteCmd, blockNum, 1, rcmd, 19, &rcmd[19], VerboseMode); - return intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); + int res = intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); + if(res) + return res; + + if (session) + session->W_Ctr++; + + if(session && mac && *dataoutlen > 3) + CalculateMAC(session, mtypWriteResp, blockNum, 1, dataout, *dataoutlen, mac, VerboseMode); + + return 0; } int CmdHFMFPInfo(const char *cmd) { @@ -402,7 +429,7 @@ int CmdHFMFPRdbl(const char *cmd) { int keylen = 0; CLIParserInit("hf mfp rdbl", - "Reads several blocks from Mifare Plus card in plain mode.", + "Reads several blocks from Mifare Plus card.", "Usage:\n\thf mfp rdbl 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read block 0 data\n" "\thf mfp rdbl 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data\n"); @@ -411,7 +438,7 @@ int CmdHFMFPRdbl(const char *cmd) { arg_lit0("vV", "verbose", "show internal data."), arg_int0("nN", "count", "blocks count (by default 1).", NULL), arg_lit0("bB", "keyb", "use key B (by default keyA)."), - arg_lit0("pP", "plain", "plain communication between reader and card."), + arg_lit0("pP", "plain", "plain communication mode between reader and card."), arg_int1(NULL, NULL, "", NULL), arg_str0(NULL, NULL, "", NULL), arg_param_end @@ -421,7 +448,7 @@ int CmdHFMFPRdbl(const char *cmd) { bool verbose = arg_get_lit(1); int blocksCount = arg_get_int_def(2, 1); bool keyB = arg_get_lit(3); - int plain = arg_get_lit(4) | true; + int plain = arg_get_lit(4); uint32_t blockn = arg_get_int(5); CLIGetHexWithReturn(6, key, &keylen); CLIParserFree(); @@ -449,6 +476,10 @@ int CmdHFMFPRdbl(const char *cmd) { return 1; } + if (blocksCount > 1 && mfIsSectorTrailer(blockn)) { + PrintAndLog("WARNING: trailer!"); + } + uint8_t sectorNum = mfSectorNum(blockn & 0xff); uint16_t uKeyNum = 0x4000 + sectorNum * 2 + (keyB ? 1 : 0); keyn[0] = uKeyNum >> 8; @@ -465,7 +496,8 @@ int CmdHFMFPRdbl(const char *cmd) { uint8_t data[250] = {0}; int datalen = 0; - res = MFPReadBlock(&session, plain, blockn & 0xff, blocksCount, false, false, data, sizeof(data), &datalen); + uint8_t mac[8] = {0}; + res = MFPReadBlock(&session, plain, blockn & 0xff, blocksCount, false, false, data, sizeof(data), &datalen, mac); if (res) { PrintAndLogEx(ERR, "Read error: %d", res); return res; @@ -485,14 +517,20 @@ int CmdHFMFPRdbl(const char *cmd) { for(int i = 0; i < blocksCount; i++) { PrintAndLogEx(INFO, "data[%03d]: %s", indx, sprint_hex(&data[1 + i * 16], 16)); indx++; - if (mfIsSectorTrailer(indx)){ + if (mfIsSectorTrailer(indx) && i != blocksCount - 1){ PrintAndLogEx(INFO, "data[%03d]: ------------------- trailer -------------------", indx); indx++; } } + if (memcmp(&data[blocksCount * 16 + 1], mac, 8)) { + PrintAndLogEx(WARNING, "WARNING: mac not equal..."); + PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[blocksCount * 16 + 1], 8)); + PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8)); + } else { if(verbose) - PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[blocksCount * 16 + 1], 8)); + PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[blocksCount * 16 + 1], 8)); + } return 0; } @@ -503,7 +541,7 @@ int CmdHFMFPRdsc(const char *cmd) { int keylen = 0; CLIParserInit("hf mfp rdsc", - "Reads one sector from Mifare Plus card in plain mode.", + "Reads one sector from Mifare Plus card.", "Usage:\n\thf mfp rdsc 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read sector 0 data\n" "\thf mfp rdsc 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data\n"); @@ -511,7 +549,7 @@ int CmdHFMFPRdsc(const char *cmd) { arg_param_begin, arg_lit0("vV", "verbose", "show internal data."), arg_lit0("bB", "keyb", "use key B (by default keyA)."), - arg_lit0("pP", "plain", "plain communication between reader and card."), + arg_lit0("pP", "plain", "plain communication mode between reader and card."), arg_int1(NULL, NULL, "", NULL), arg_str0(NULL, NULL, "", NULL), arg_param_end @@ -520,7 +558,7 @@ int CmdHFMFPRdsc(const char *cmd) { bool verbose = arg_get_lit(1); bool keyB = arg_get_lit(2); - bool plain = arg_get_lit(3) | true; + bool plain = arg_get_lit(3); uint32_t sectorNum = arg_get_int(4); CLIGetHexWithReturn(5, key, &keylen); CLIParserFree(); @@ -557,8 +595,9 @@ int CmdHFMFPRdsc(const char *cmd) { uint8_t data[250] = {0}; int datalen = 0; + uint8_t mac[8] = {0}; for(int n = mfFirstBlockOfSector(sectorNum); n < mfFirstBlockOfSector(sectorNum) + mfNumBlocksPerSector(sectorNum); n++) { - res = MFPReadBlock(&session, plain, n & 0xff, 1, false, true, data, sizeof(data), &datalen); + res = MFPReadBlock(&session, plain, n & 0xff, 1, false, true, data, sizeof(data), &datalen, mac); if (res) { PrintAndLogEx(ERR, "Read error: %d", res); DropField(); @@ -578,8 +617,14 @@ int CmdHFMFPRdsc(const char *cmd) { PrintAndLogEx(INFO, "data[%03d]: %s", n, sprint_hex(&data[1], 16)); - if(verbose) - PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1 + 16], 8)); + if (memcmp(&data[1 + 16], mac, 8)) { + PrintAndLogEx(WARNING, "WARNING: mac on block %d not equal...", n); + PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[1 + 16], 8)); + PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8)); + } else { + if(verbose) + PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1 + 16], 8)); + } } DropField(); @@ -654,25 +699,37 @@ int CmdHFMFPWrbl(const char *cmd) { uint8_t data[250] = {0}; int datalen = 0; - res = MFPWriteBlock(&session, blockNum & 0xff, datain, false, false, data, sizeof(data), &datalen); + uint8_t mac[8] = {0}; + res = MFPWriteBlock(&session, blockNum & 0xff, datain, false, false, data, sizeof(data), &datalen, mac); if (res) { PrintAndLogEx(ERR, "Write error: %d", res); + DropField(); return res; } if (datalen != 3 && (datalen != 3 + 8)) { PrintAndLogEx(ERR, "Error return length:%d", datalen); + DropField(); return 5; } if (datalen && data[0] != 0x90) { PrintAndLogEx(ERR, "Card write error: %02x %s", data[0], GetErrorDescription(data[0])); + DropField(); return 6; } - if(verbose) - PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1], 8)); + if (memcmp(&data[1], mac, 8)) { + PrintAndLogEx(WARNING, "WARNING: mac not equal..."); + PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[1], 8)); + PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8)); + } else { + if(verbose) + PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1], 8)); + } + DropField(); + PrintAndLogEx(INFO, "Write OK."); return 0; } @@ -686,7 +743,7 @@ static command_t CommandTable[] = {"auth", CmdHFMFPAuth, 0, "Authentication"}, {"rdbl", CmdHFMFPRdbl, 0, "Read blocks"}, {"rdsc", CmdHFMFPRdsc, 0, "Read sectors"}, -// {"wrbl", CmdHFMFPWrbl, 0, "Write blocks"}, + {"wrbl", CmdHFMFPWrbl, 0, "Write blocks"}, {NULL, NULL, 0, NULL} }; diff --git a/client/mifare4.c b/client/mifare4.c index 2ca28cb3f..8f9bd9e67 100644 --- a/client/mifare4.c +++ b/client/mifare4.c @@ -1,5 +1,6 @@ //----------------------------------------------------------------------------- // Copyright (C) 2018 Merlok +// Copyright (C) 2018 drHatson // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -16,24 +17,85 @@ #include "ui.h" #include "polarssl/libpcrypto.h" -int CalulateMAC(mf4Session *session, uint8_t *data, int datalen, uint8_t *mac, bool verbose) { - if (!session || !session->Authenticated || !mac || !data || !datalen) +int CalculateEncIVCommand(mf4Session *session, uint8_t *iv, bool verbose) { + memcpy(&iv[0], session->TI, 4); + memcpy(&iv[4], &session->R_Ctr, 2); + memcpy(&iv[6], &session->W_Ctr, 2); + memcpy(&iv[8], &session->R_Ctr, 2); + memcpy(&iv[10], &session->W_Ctr, 2); + memcpy(&iv[12], &session->R_Ctr, 2); + memcpy(&iv[14], &session->W_Ctr, 2); + + return 0; +} + +int CalculateEncIVResponse(mf4Session *session, uint8_t *iv, bool verbose) { + memcpy(&iv[0], &session->R_Ctr, 2); + memcpy(&iv[2], &session->W_Ctr, 2); + memcpy(&iv[4], &session->R_Ctr, 2); + memcpy(&iv[6], &session->W_Ctr, 2); + memcpy(&iv[8], &session->R_Ctr, 2); + memcpy(&iv[10], &session->W_Ctr, 2); + memcpy(&iv[12], session->TI, 4); + + return 0; +} + + +int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose) { + if (!session || !session->Authenticated || !mac || !data || !datalen || datalen < 1) return 1; memset(mac, 0x00, 8); - if (verbose) - PrintAndLog("MAC data[%d]: %s", datalen, sprint_hex(data, datalen)); + uint16_t ctr = session->R_Ctr; + switch(mtype) { + case mtypWriteCmd: + case mtypWriteResp: + ctr = session->W_Ctr; + break; + case mtypReadCmd: + case mtypReadResp: + break; + } + + uint8_t macdata[2049] = {data[0], (ctr & 0xFF), (ctr >> 8), 0}; + int macdatalen = datalen; + memcpy(&macdata[3], session->TI, 4); + + switch(mtype) { + case mtypReadCmd: + memcpy(&macdata[7], &data[1], datalen - 1); + macdatalen = datalen + 6; + break; + case mtypReadResp: + macdata[7] = blockNum; + macdata[8] = 0; + macdata[9] = blockCount; + memcpy(&macdata[10], &data[1], datalen - 1); + macdatalen = datalen + 9; + break; + case mtypWriteCmd: + memcpy(&macdata[7], &data[1], datalen - 1); + macdatalen = datalen + 6; + break; + case mtypWriteResp: + macdatalen = 1 + 6; + break; + } - return aes_cmac8(NULL, session->Key, data, mac, datalen); + if (verbose) + PrintAndLog("MAC data[%d]: %s", macdatalen, sprint_hex(macdata, macdatalen)); + + return aes_cmac8(NULL, session->Kmac, macdata, mac, macdatalen); } int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose) { uint8_t data[257] = {0}; int datalen = 0; - uint8_t Rnd1[17] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00}; - uint8_t Rnd2[17] = {0}; + uint8_t RndA[17] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00}; + uint8_t RndB[17] = {0}; if (session) session->Authenticated = false; @@ -67,17 +129,17 @@ int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateF return 3; } - aes_decode(NULL, key, &data[1], Rnd2, 16); - Rnd2[16] = Rnd2[0]; + aes_decode(NULL, key, &data[1], RndB, 16); + RndB[16] = RndB[0]; if (verbose) - PrintAndLogEx(INFO, "Rnd2: %s", sprint_hex(Rnd2, 16)); + PrintAndLogEx(INFO, "RndB: %s", sprint_hex(RndB, 16)); uint8_t cmd2[33] = {0}; cmd2[0] = 0x72; uint8_t raw[32] = {0}; - memmove(raw, Rnd1, 16); - memmove(&raw[16], &Rnd2[1], 16); + memmove(raw, RndA, 16); + memmove(&raw[16], &RndB[1], 16); aes_encode(NULL, key, raw, &cmd2[1], 32); if (verbose) @@ -97,19 +159,49 @@ int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateF if (verbose) { PrintAndLogEx(INFO, "res: %s", sprint_hex(raw, 32)); - PrintAndLogEx(INFO, "Rnd1`: %s", sprint_hex(&raw[4], 16)); + PrintAndLogEx(INFO, "RndA`: %s", sprint_hex(&raw[4], 16)); } - if (memcmp(&raw[4], &Rnd1[1], 16)) { + if (memcmp(&raw[4], &RndA[1], 16)) { PrintAndLogEx(ERR, "\nAuthentication FAILED. rnd not equal"); if (verbose) { - PrintAndLogEx(ERR, "rnd1 reader: %s", sprint_hex(&Rnd1[1], 16)); - PrintAndLogEx(ERR, "rnd1 card: %s", sprint_hex(&raw[4], 16)); + PrintAndLogEx(ERR, "RndA reader: %s", sprint_hex(&RndA[1], 16)); + PrintAndLogEx(ERR, "RndA card: %s", sprint_hex(&raw[4], 16)); } DropField(); return 5; } + if (verbose) { + PrintAndLogEx(INFO, " TI: %s", sprint_hex(raw, 4)); + PrintAndLogEx(INFO, "pic: %s", sprint_hex(&raw[20], 6)); + PrintAndLogEx(INFO, "pcd: %s", sprint_hex(&raw[26], 6)); + } + + uint8_t kenc[16] = {0}; + memcpy(&kenc[0], &RndA[11], 5); + memcpy(&kenc[5], &RndB[11], 5); + for(int i = 0; i < 5; i++) + kenc[10 + i] = RndA[4 + i] ^ RndB[4 + i]; + kenc[15] = 0x11; + + aes_encode(NULL, key, kenc, kenc, 16); + if (verbose) { + PrintAndLogEx(INFO, "kenc: %s", sprint_hex(kenc, 16)); + } + + uint8_t kmac[16] = {0}; + memcpy(&kmac[0], &RndA[7], 5); + memcpy(&kmac[5], &RndB[7], 5); + for(int i = 0; i < 5; i++) + kmac[10 + i] = RndA[0 + i] ^ RndB[0 + i]; + kmac[15] = 0x22; + + aes_encode(NULL, key, kmac, kmac, 16); + if (verbose) { + PrintAndLogEx(INFO, "kmac: %s", sprint_hex(kmac, 16)); + } + if (!leaveSignalON) DropField(); @@ -118,9 +210,17 @@ int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateF if (session) { session->Authenticated = true; + session->R_Ctr = 0; + session->W_Ctr = 0; session->KeyNum = keyn[1] + (keyn[0] << 8); - memmove(session->Rnd1, Rnd1, 16); - memmove(session->Rnd2, Rnd2, 16); + memmove(session->RndA, RndA, 16); + memmove(session->RndB, RndB, 16); + memmove(session->Key, key, 16); + memmove(session->TI, raw, 4); + memmove(session->PICCap2, &raw[20], 6); + memmove(session->PCDCap2, &raw[26], 6); + memmove(session->Kenc, kenc, 16); + memmove(session->Kmac, kmac, 16); } PrintAndLogEx(INFO, "Authentication OK"); diff --git a/client/mifare4.h b/client/mifare4.h index 7867add5d..b85d512f1 100644 --- a/client/mifare4.h +++ b/client/mifare4.h @@ -1,5 +1,6 @@ //----------------------------------------------------------------------------- // Copyright (C) 2018 Merlok +// Copyright (C) 2018 drHatson // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -19,12 +20,25 @@ typedef struct { bool Authenticated; uint8_t Key[16]; uint16_t KeyNum; - uint8_t Rnd1[16]; - uint8_t Rnd2[16]; - + uint8_t RndA[16]; + uint8_t RndB[16]; + uint8_t TI[4]; + uint8_t PICCap2[6]; + uint8_t PCDCap2[6]; + uint8_t Kenc[16]; + uint8_t Kmac[16]; + uint16_t R_Ctr; + uint16_t W_Ctr; }mf4Session; + +typedef enum { + mtypReadCmd, + mtypReadResp, + mtypWriteCmd, + mtypWriteResp, +} MACType_t; -extern int CalulateMAC(mf4Session *session, uint8_t *data, int datalen, uint8_t *mac, bool verbose); +extern int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose); extern int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose); extern uint8_t mfNumBlocksPerSector(uint8_t sectorNo); diff --git a/common/polarssl/libpcrypto.c b/common/polarssl/libpcrypto.c index d86c97568..0dea75fac 100644 --- a/common/polarssl/libpcrypto.c +++ b/common/polarssl/libpcrypto.c @@ -1,5 +1,6 @@ //----------------------------------------------------------------------------- // Copyright (C) 2018 Merlok +// Copyright (C) 2018 drHatson // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -12,6 +13,7 @@ #include #include +// NIST Special Publication 800-38A Recommendation for block cipher modes of operation: methods and techniques, 2001. int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){ uint8_t iiv[16] = {0}; if (iv) @@ -52,16 +54,10 @@ int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length if (iv) memcpy(iiv, iv, 16); - // padding: ISO/IEC 9797-1 Message Authentication Codes (MACs) - Part 1: Mechanisms using a block cipher - uint8_t data[2049] = {0}; // length + 16 - memcpy(data, input, length); - data[length] = 0x80; - int datalen = (length & 0xfffffff0) + 0x10; - // NIST 800-38B aes_cmac128_context ctx; aes_cmac128_starts(&ctx, key); - aes_cmac128_update(&ctx, data, datalen); + aes_cmac128_update(&ctx, input, length); aes_cmac128_final(&ctx, mac); return 0; From 4da4b33d8d3768389dd59479cf6e779377bda856 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 1 Nov 2018 19:51:45 +0100 Subject: [PATCH 0113/1938] fix: 'lf t55xx deviceconfig' - bug that failed to load default values if wiped flashmem. --- armsrc/lfops.c | 27 +++++++++++++++++++++------ 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 18e178c1f..021fc2411 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -90,9 +90,9 @@ void setT55xxConfig(uint8_t arg0, t55xx_config *c) { return; } - uint8_t *buf = BigBuf_malloc(4096); + uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN); Flash_CheckBusy(BUSY_TIMEOUT); - uint16_t res = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, 4096); + uint16_t res = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN); if ( res == 0) { FlashStop(); BigBuf_free(); @@ -104,9 +104,9 @@ void setT55xxConfig(uint8_t arg0, t55xx_config *c) { Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); Flash_Erase4k(3, 0xD); - res = Flash_Write(T55XX_CONFIG_OFFSET, buf, 4096); + res = Flash_Write(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN); - if ( res == 4096 && MF_DBGLEVEL > 1) { + if ( res == T55XX_CONFIG_LEN && MF_DBGLEVEL > 1) { DbpString("T55XX Config save success"); } @@ -124,10 +124,25 @@ void loadT55xxConfig(void) { return; } + uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN); + Flash_CheckBusy(BUSY_TIMEOUT); - uint16_t isok = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, (uint8_t *)&t_config, T55XX_CONFIG_LEN); + uint16_t isok = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN); FlashStop(); - + + // verify read mem is actual data. + uint8_t cntA = T55XX_CONFIG_LEN, cntB = T55XX_CONFIG_LEN; + for (int i=0; i< T55XX_CONFIG_LEN; i++) { + if ( buf[i] == 0xFF) cntA--; + if ( buf[i] == 0x00) cntB--; + } + if ( !cntA || !cntB ) { + BigBuf_free(); + return; + } + + memcpy((uint8_t *)&t_config, buf, T55XX_CONFIG_LEN); + if ( isok == T55XX_CONFIG_LEN) { if (MF_DBGLEVEL > 1) DbpString("T55XX Config load success"); } From d30454fc5af3c3dbe684d01d99c17efbdf186dc9 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 2 Nov 2018 18:27:42 +0100 Subject: [PATCH 0114/1938] fix: fflush(stdout), should sort out the blocking pipe problem add: line length (@merlokk) --- client/comms.c | 6 +++--- client/proxmark3.c | 12 +++++++----- client/ui.c | 19 ++++++++----------- 3 files changed, 18 insertions(+), 19 deletions(-) diff --git a/client/comms.c b/client/comms.c index e297e9057..7204aa1c4 100644 --- a/client/comms.c +++ b/client/comms.c @@ -107,7 +107,7 @@ static void storeCommand(UsbCommand *command) { //If these two are equal, we're about to overwrite in the // circular buffer. PrintAndLogEx(FAILED, "WARNING: Command buffer about to overwrite command! This needs to be fixed!"); - fflush(NULL); + fflush(stdout); } //Store the command at the 'head' location UsbCommand* destination = &rxBuffer[cmd_head]; @@ -185,7 +185,7 @@ static void UsbCommandReceived(UsbCommand* c) { } else { PrintAndLogEx(NORMAL, "#db# %s", s); } - fflush(NULL); + fflush(stdout); break; } case CMD_DEBUG_PRINT_INTEGERS: { @@ -339,7 +339,7 @@ bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode) pthread_create(&USB_communication_thread, NULL, &uart_communication, &conn); //pthread_create(&FPC_communication_thread, NULL, &uart_communication, &conn); - fflush(NULL); + fflush(stdout); // create a mutex to avoid interlacing print commands from our different threads //pthread_mutex_init(&print_lock, NULL); return true; diff --git a/client/proxmark3.c b/client/proxmark3.c index ae528a9e9..6f664f4ce 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -40,7 +40,7 @@ static void showBanner(void){ printf("\nKeep iceman fork alive with a donation! https://paypal.me/iceman1001/"); printf("\nMONERO: 43mNJLpgBVaTvyZmX9ajcohpvVkaRy1kbZPm8tqAb7itZgfuYecgkRF36rXrKFUkwEGeZedPsASRxgv4HPBHvJwyJdyvQuP"); printf("\n\n\n"); - fflush(NULL); + fflush(stdout); } #endif @@ -260,6 +260,8 @@ int main(int argc, char* argv[]) { /* initialize history */ using_history(); + + rl_extend_line_buffer(1024); if (argc < 2) { show_help(true, argv[0]); @@ -282,23 +284,23 @@ int main(int argc, char* argv[]) { } // flush output - if(strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "-flush") == 0){ + if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "-flush") == 0){ SetFlushAfterWrite(true); PrintAndLogEx(INFO, "Output will be flushed after every print.\n"); } // wait for comport - if(strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "-wait") == 0){ + if (strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "-wait") == 0){ waitCOMPort = true; } // execute pm3 command - if(strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "-command") == 0){ + if (strcmp(argv[i], "-c") == 0 || strcmp(argv[i], "-command") == 0){ executeCommand = true; } // execute lua script - if(strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "-lua") == 0){ + if (strcmp(argv[i], "-l") == 0 || strcmp(argv[i], "-lua") == 0){ executeCommand = true; addLuaExec = true; } diff --git a/client/ui.c b/client/ui.c index a8b45273d..070f75b7a 100644 --- a/client/ui.c +++ b/client/ui.c @@ -25,23 +25,20 @@ void PrintAndLogOptions(char *str[][2], size_t size, size_t space) { char buff[2000] = "Options:\n"; char format[2000] = ""; size_t counts[2] = {0, 0}; - for(int i = 0; i < size; i++) - for(int j = 0 ; j < 2 ; j++) - if(counts[j] < strlen(str[i][j])) - { + for (int i = 0; i < size; i++) + for (int j = 0 ; j < 2 ; j++) + if (counts[j] < strlen(str[i][j])) { counts[j] = strlen(str[i][j]); } - for(int i = 0; i < size; i++) - { - for(int j = 0; j < 2; j++) - { - if(j == 0) + for (int i = 0; i < size; i++) { + for (int j = 0; j < 2; j++) { + if (j == 0) snprintf(format, sizeof(format), "%%%zus%%%zus", space, counts[j]); else snprintf(format, sizeof(format), "%%%zus%%-%zus", space, counts[j]); snprintf(buff + strlen(buff), sizeof(buff) - strlen(buff), format, " ", str[i][j]); } - if(i Date: Fri, 2 Nov 2018 18:38:06 +0100 Subject: [PATCH 0115/1938] chg: use signal mean instead of hardcoded FSK_PSK_THRESHOLD chg: stricter clock identification chg: askclock detection, trying to find a better starting point --- common/lfdemod.c | 72 ++++++++++++++++++++++++++++-------------------- common/lfdemod.h | 2 +- 2 files changed, 43 insertions(+), 31 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index 8f0630d52..4714cdb69 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -320,14 +320,14 @@ size_t findModStart(uint8_t *src, size_t size, uint8_t expWaveSize) { size_t i = 0; size_t waveSizeCnt = 0; uint8_t thresholdCnt = 0; - bool isAboveThreshold = src[i++] >= FSK_PSK_THRESHOLD; + bool isAboveThreshold = src[i++] >= signalprop.mean; //FSK_PSK_THRESHOLD; for (; i < size-20; i++ ) { - if(src[i] < FSK_PSK_THRESHOLD && isAboveThreshold) { + if(src[i] < signalprop.mean && isAboveThreshold) { thresholdCnt++; if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break; isAboveThreshold = false; waveSizeCnt = 0; - } else if (src[i] >= FSK_PSK_THRESHOLD && !isAboveThreshold) { + } else if (src[i] >= signalprop.mean && !isAboveThreshold) { thresholdCnt++; if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break; isAboveThreshold = true; @@ -337,15 +337,24 @@ size_t findModStart(uint8_t *src, size_t size, uint8_t expWaveSize) { } if (thresholdCnt > 10) break; } - if (g_debugMode == 2) prnt("DEBUG: threshold Count reached at %u, count: %u", i, thresholdCnt); + if (g_debugMode == 2) prnt("DEBUG: threshold Count reached at index %u, count: %u", i, thresholdCnt); return i; } +// iceman: ranges the old defintion, becomes very forgiving when clock speed increase. +// clocks[i] - (clocks[i]/8) && testclk <= clocks[i]+1 ) +// 8 (7-9) +// 16 (14-17) +// 32 (28-33) +// 40 (35-41) +// 50 (46-51) +// 64 (56-65) +// 128 (112-129) int getClosestClock(int testclk) { uint8_t clocks[] = {8,16,32,40,50,64,128}; for (uint8_t i = 0; i < 7; i++) - if ( testclk >= clocks[i] - (clocks[i]/8) && testclk <= clocks[i]+1 ) + if ( testclk >= clocks[i]-2 && testclk <= clocks[i]+1 ) return clocks[i]; return 0; @@ -474,7 +483,7 @@ int ManchesterEncode(uint8_t *bits, size_t size) { // by marshmellow // to detect a wave that has heavily clipped (clean) samples -// loop 512 samples, if 300 of them is deemed maxed out, we assume the wave is clipped. +// loop 512 samples, if 250 of them is deemed maxed out, we assume the wave is clipped. bool DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low) { bool allArePeaks = true; uint16_t cntPeaks = 0; @@ -516,8 +525,8 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo getNextHigh(dest, size, high, &i); getNextLow(dest, size, low, &i); - // loop through all samples - while (i < size) { + // loop through all samples (well, we don't want to go out-of-bounds) + while (i < size-512) { // measure from low to low startwave = i; @@ -562,36 +571,35 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { // just noise - no super good detection. good enough if (signalprop.isnoise) { - if (g_debugMode == 2) prnt("DEBUG DetectASKClock: just noise detected - quitting"); + if (g_debugMode == 2) prnt("DEBUG DetectASKClock: just noise detected - aborting"); return -1; } //get high and low peak int peak_hi, peak_low; - //getHiLo(dest, loopCnt, &peak_hi, &peak_low, 75, 75); getHiLo(&peak_hi, &peak_low, 75, 75); //test for large clean peaks if (!clockFnd){ if (DetectCleanAskWave(dest, size, peak_hi, peak_low)){ - int ans = DetectStrongAskClock(dest, size, peak_hi, peak_low, clock); - if (g_debugMode == 2) prnt("DEBUG ASK: detectaskclk Clean Ask Wave Detected: clk %i, ShortestWave: %i", *clock ,ans); - if (ans > 0){ - return ans; //return shortest wave start position - } + int idx = DetectStrongAskClock(dest, size, peak_hi, peak_low, clock); + if (g_debugMode == 2) + prnt("DEBUG ASK: detectaskclk Clean Ask Wave Detected: clk %i, Best Starting Position: %i", *clock, idx); + if (idx > 0) + return idx; //return shortest wave start position + } } // test clock if given as cmd parameter if ( *clock > 0 ) clk[0] = *clock; - uint16_t ii; uint8_t clkCnt, tol = 0; + size_t j = 0; uint16_t bestErr[] = {1000,1000,1000,1000,1000,1000,1000,1000,1000}; uint8_t bestStart[] = {0,0,0,0,0,0,0,0,0}; - size_t errCnt = 0; - size_t arrLoc, loopEnd; + size_t errCnt = 0, arrLoc, loopEnd; if (clockFnd > 0) { clkCnt = clockFnd; @@ -614,14 +622,17 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { bestErr[clkCnt] = 1000; //try lining up the peaks by moving starting point (try first few clocks) - for (ii=0; ii < loopCnt; ii++){ - if (dest[ii] < peak_hi && dest[ii] > peak_low) continue; + // get to first full low to prime loop and skip incomplete first pulse + getNextHigh(dest, size, peak_hi, &j); + getNextLow(dest, size, peak_low, &j); + + for (; j < loopCnt; j++){ errCnt = 0; // now that we have the first one lined up test rest of wave array - loopEnd = ((size-ii-tol) / clk[clkCnt]) - 1; + loopEnd = ((size-j-tol) / clk[clkCnt]) - 1; for (i=0; i < loopEnd; ++i){ - arrLoc = ii + (i * clk[clkCnt]); + arrLoc = j + (i * clk[clkCnt]); if (dest[arrLoc] >= peak_hi || dest[arrLoc] <= peak_low){ } else if (dest[arrLoc-tol] >= peak_hi || dest[arrLoc-tol] <= peak_low){ } else if (dest[arrLoc+tol] >= peak_hi || dest[arrLoc+tol] <= peak_low){ @@ -631,21 +642,22 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { } //if we found no errors then we can stop here and a low clock (common clocks) // this is correct one - return this clock - //if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d", clk[clkCnt], errCnt, ii, i); + //if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d", clk[clkCnt], errCnt, j, i); if (errCnt == 0 && clkCnt < 7) { if (!clockFnd) *clock = clk[clkCnt]; - return ii; + return j; } //if we found errors see if it is lowest so far and save it as best run if (errCnt < bestErr[clkCnt]) { bestErr[clkCnt] = errCnt; - bestStart[clkCnt] = ii; + bestStart[clkCnt] = j; } } } - uint8_t k; - uint8_t best = 0; + + uint8_t k, best = 0; + for (k=1; k < clkEnd; ++k){ if (bestErr[k] < bestErr[best]){ if (bestErr[k] == 0) bestErr[k] = 1; @@ -1486,7 +1498,7 @@ int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, // just noise - no super good detection. good enough if (signalprop.isnoise) { - if (g_debugMode == 2) prnt("DEBUG askdemod_ext: just noise detected - quitting"); + if (g_debugMode == 2) prnt("DEBUG askdemod_ext: just noise detected - aborting"); return -2; } @@ -1636,7 +1648,7 @@ size_t fsk_wave_demod(uint8_t *dest, size_t size, uint8_t fchigh, uint8_t fclow, //find start of modulating data in trace idx = findModStart(dest, size, fchigh); // Need to threshold first sample - dest[0] = (dest[idx] < FSK_PSK_THRESHOLD) ? 0 : 1; + dest[0] = (dest[idx] < signalprop.mean) ? 0 : 1; last_transition = idx; idx++; @@ -1674,7 +1686,7 @@ size_t fsk_wave_demod(uint8_t *dest, size_t size, uint8_t fchigh, uint8_t fclow, for(; idx < size-20; idx++) { // threshold current value - dest[idx] = (dest[idx] < FSK_PSK_THRESHOLD) ? 0 : 1; + dest[idx] = (dest[idx] < signalprop.mean) ? 0 : 1; // Check for 0->1 transition if (dest[idx-1] < dest[idx]) { diff --git a/common/lfdemod.h b/common/lfdemod.h index daa5c3c56..43537b18b 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -19,7 +19,7 @@ #include // for #include // for bool #include "parity.h" // for parity test - +#include "util.h" // for ARRAYLEN //generic typedef struct { int low; From 12af27967bcbaa41da984feb42c289b2312ac845 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 2 Nov 2018 20:47:19 +0100 Subject: [PATCH 0116/1938] fix: remove gcc7.3.0 warning --- client/scandir.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/client/scandir.c b/client/scandir.c index 6f8778318..12bbef110 100644 --- a/client/scandir.c +++ b/client/scandir.c @@ -63,9 +63,10 @@ int scandir (const char *dir, if (err_no != 0) { closedir (dirp); if (nl) { - while (count > 0) + while (count > 0) { free (nl[--count]); - free (nl); + } + free (nl); } return -1; } From 92d89dd5398f097938826833a78a83bb841b5c3a Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 3 Nov 2018 11:10:55 +0100 Subject: [PATCH 0117/1938] fix: readline not installed on mac by default.. --- client/proxmark3.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/proxmark3.c b/client/proxmark3.c index 6f664f4ce..ed7fd245d 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -261,7 +261,9 @@ int main(int argc, char* argv[]) { /* initialize history */ using_history(); +#ifdef RL_STATE_READCMD rl_extend_line_buffer(1024); +#endif if (argc < 2) { show_help(true, argv[0]); From 1e4847739bcaf5a727dc997c2896e35ae121b204 Mon Sep 17 00:00:00 2001 From: Chris Date: Sat, 3 Nov 2018 14:22:51 +0100 Subject: [PATCH 0118/1938] chg: updated the instructions to include libjansson. --- README.md | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 7ae1db78c..fdf02f0a2 100644 --- a/README.md +++ b/README.md @@ -47,6 +47,9 @@ This fork now compiles just fine on - Mac OS X / Homebrew - Docker container +## KALI and ARCHLINUX users +Kali and ArchLinux users usually must kill their modem manager in order for the proxmark3 to enumerate properly. + ## Setup and build for UBUNTU GC made updates to allow this to build easily on Ubuntu 14.04.2 LTS, 15.10 or 16.04 See https://github.com/Proxmark/proxmark3/wiki/Ubuntu%20Linux @@ -57,7 +60,7 @@ I have also added this script to the fork. https://github.com/RfidResearchGroup/proxmark3/blob/master/install.sh - Run -`sudo apt-get install p7zip git build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev libqt4-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi` +`sudo apt-get install p7zip git build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev libqt4-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libjansson-dev` - Clone fork `git clone https://github.com/RfidResearchGroup/proxmark3.git` @@ -82,7 +85,7 @@ https://github.com/RfidResearchGroup/proxmark3/blob/master/install.sh ## Setup and build for ArchLinux - Run -`sudo pacman -Sy base-devel p7zip libusb readline ncurses arm-none-eabi-newlib --needed` +`sudo pacman -Sy base-devel p7zip libusb readline ncurses libjansson-dev arm-none-eabi-newlib --needed` `yaourt -S termcap` - Clone fork @@ -148,8 +151,8 @@ Afterwards just clone the iceman repo or download someone elses. Read instructions on @Gator96100 repo page. (https://github.com/Gator96100/ProxSpace/) Links -- https://github.com/Gator96100/ProxSpace/archive/master.zip -- https://github.com/Gator96100/ProxSpace/releases/tag/v2.2 (release v2.2 with gcc v5.3.0 arm-none-eabi-gcc v7.1.0) +- https://github.com/Gator96100/ProxSpace/releases/tag/v3.1 (release v3.1 with gcc v7.3.0 ) +- https://github.com/Gator96100/ProxSpace/releases/tag/v2.2 (release v2.2 with gcc v5.3.0 arm-none-eabi-gcc v7.1.0) ### 7. Build and run From 3e7d9fde015e2de45ba71615c874e4383e68f146 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 5 Nov 2018 17:46:32 +0100 Subject: [PATCH 0119/1938] CHG: 'hf mf hardnest' auto detect supported cpu-commandset. See helptext for more info. (@piwi) --- client/cmdhfmf.c | 50 +++++++++++--- client/cmdhfmf.h | 1 + client/cmdhfmfhard.c | 43 +++++++----- client/hardnested/hardnested_bf_core.c | 95 +++++++++++++++++++++----- client/hardnested/hardnested_bf_core.h | 12 ++++ 5 files changed, 160 insertions(+), 41 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 016025fbc..8f7004d66 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -131,6 +131,13 @@ int usage_hf14_hardnested(void){ PrintAndLogEx(NORMAL, " u read/write hf-mf--nonces.bin instead of default name"); PrintAndLogEx(NORMAL, " f read/write instead of default name"); PrintAndLogEx(NORMAL, " t tests?"); + PrintAndLogEx(NORMAL, " i set type of SIMD instructions. Without this flag programs autodetect it."); + PrintAndLogEx(NORMAL, " i 5 = AVX512"); + PrintAndLogEx(NORMAL, " i 2 = AVX2"); + PrintAndLogEx(NORMAL, " i a = AVX"); + PrintAndLogEx(NORMAL, " i s = SSE2"); + PrintAndLogEx(NORMAL, " i m = MMX"); + PrintAndLogEx(NORMAL, " i n = none (use CPU regular instruction set)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf hardnested 0 A FFFFFFFFFFFF 4 A"); @@ -1252,8 +1259,8 @@ int CmdHF14AMfNestedHard(const char *Cmd) { switch(tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_hf14_hardnested(); case 'r': - fptr=GenerateFilename("hf-mf-","-nonces.bin"); - if(fptr==NULL) + fptr = GenerateFilename("hf-mf-","-nonces.bin"); + if (fptr == NULL) strncpy(filename,"nonces.bin", FILE_PATH_SIZE); else strncpy(filename,fptr, FILE_PATH_SIZE); @@ -1269,10 +1276,10 @@ int CmdHF14AMfNestedHard(const char *Cmd) { if (!param_gethex(Cmd, cmdp+2, trgkey, 12)) { know_target_key = true; } - cmdp+=2; + cmdp += 2; break; default: - if(param_getchar(Cmd, cmdp) == 0x00) + if (param_getchar(Cmd, cmdp) == 0x00) { PrintAndLogEx(NORMAL, "Block number is missing"); return 1; @@ -1309,7 +1316,7 @@ int CmdHF14AMfNestedHard(const char *Cmd) { if (ctmp != 'A' && ctmp != 'a') { trgKeyType = 1; } - cmdp+=5; + cmdp += 5; } if (!param_gethex(Cmd, cmdp, trgkey, 12)) { know_target_key = true; @@ -1317,14 +1324,13 @@ int CmdHF14AMfNestedHard(const char *Cmd) { } while ((ctmp = param_getchar(Cmd, cmdp))) { - switch(tolower(ctmp)) - { + switch(tolower(ctmp)) { case 's': slow = true; break; case 'w': nonce_file_write = true; - fptr=GenerateFilename("hf-mf-","-nonces.bin"); + fptr = GenerateFilename("hf-mf-","-nonces.bin"); if (fptr == NULL) return 1; strncpy(filename, fptr, FILE_PATH_SIZE); @@ -1339,6 +1345,34 @@ int CmdHF14AMfNestedHard(const char *Cmd) { strncpy(filename, szTemp, FILE_PATH_SIZE); cmdp++; break; + case 'i': + SetSIMDInstr(SIMD_AUTO); + ctmp = tolower(param_getchar(Cmd, cmdp+1)); + switch (ctmp) { + case '5': + SetSIMDInstr(SIMD_AVX512); + break; + case '2': + SetSIMDInstr(SIMD_AVX2); + break; + case 'a': + SetSIMDInstr(SIMD_AVX); + break; + case 's': + SetSIMDInstr(SIMD_SSE2); + break; + case 'm': + SetSIMDInstr(SIMD_MMX); + break; + case 'n': + SetSIMDInstr(SIMD_NONE); + break; + default: + PrintAndLog("Unknown SIMD type. %c", ctmp); + return 1; + } + cmdp += 2; + break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", ctmp); usage_hf14_hardnested(); diff --git a/client/cmdhfmf.h b/client/cmdhfmf.h index 3404548d5..b253ac0bb 100644 --- a/client/cmdhfmf.h +++ b/client/cmdhfmf.h @@ -31,6 +31,7 @@ #include "mifaredefault.h" // mifare default key array #include "cmdhf14a.h" // dropfield #include "cliparser/cliparser.h" // argtable +#include "hardnested/hardnested_bf_core.h" // SetSIMDInstr extern int CmdHFMF(const char *Cmd); diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index c35664a7f..42e97e4b9 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -33,6 +33,7 @@ #include "crapto1/crapto1.h" #include "parity.h" #include "hardnested/hardnested_bruteforce.h" +#include "hardnested/hardnested_bf_core.h" #include "hardnested/hardnested_bitarray_core.h" #include "zlib.h" @@ -72,22 +73,27 @@ static float brute_force_per_second; static void get_SIMD_instruction_set(char* instruction_set) { -#if defined (__i386__) || defined (__x86_64__) - #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) - #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) - if (__builtin_cpu_supports("avx512f")) strcpy(instruction_set, "AVX512F"); - else if (__builtin_cpu_supports("avx2")) strcpy(instruction_set, "AVX2"); - #else - if (__builtin_cpu_supports("avx2")) strcpy(instruction_set, "AVX2"); - #endif - else if (__builtin_cpu_supports("avx")) strcpy(instruction_set, "AVX"); - else if (__builtin_cpu_supports("sse2")) strcpy(instruction_set, "SSE2"); - else if (__builtin_cpu_supports("mmx")) strcpy(instruction_set, "MMX"); - else - #endif -#endif - strcpy(instruction_set, "no"); -} + switch(GetSIMDInstrAuto()) { + case SIMD_AVX512: + strcpy(instruction_set, "AVX512F"); + break; + case SIMD_AVX2: + strcpy(instruction_set, "AVX2"); + break; + case SIMD_AVX: + strcpy(instruction_set, "AVX"); + break; + case SIMD_SSE2: + strcpy(instruction_set, "SSE2"); + break; + case SIMD_MMX: + strcpy(instruction_set, "MMX"); + break; + default: + strcpy(instruction_set, "no"); + break; + } +} static void print_progress_header(void) { @@ -267,6 +273,7 @@ static void init_bitflip_bitarrays(void) if (bytesread != filesize) { PrintAndLogEx(WARNING, "File read error with %s. Aborting...\n", state_file_name); fclose(statesfile); + inflateEnd(&compressed_stream); exit(5); } fclose(statesfile); @@ -2208,6 +2215,10 @@ static void set_test_state(uint8_t byte) int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests, uint64_t *foundkey, char *filename) { char progress_text[80]; + + char instr_set[12] = {0}; + get_SIMD_instruction_set(instr_set); + PrintAndLog("Using %s SIMD core.", instr_set); srand((unsigned) time(NULL)); brute_force_per_second = brute_force_benchmark(); diff --git a/client/hardnested/hardnested_bf_core.c b/client/hardnested/hardnested_bf_core.c index 3982a144a..c00434a52 100644 --- a/client/hardnested/hardnested_bf_core.c +++ b/client/hardnested/hardnested_bf_core.c @@ -548,44 +548,105 @@ out: crack_states_bitsliced_t *crack_states_bitsliced_function_p = &crack_states_bitsliced_dispatch; bitslice_test_nonces_t *bitslice_test_nonces_function_p = &bitslice_test_nonces_dispatch; -// determine the available instruction set at runtime and call the correct function -const uint64_t crack_states_bitsliced_dispatch(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonce_2nd_byte, noncelist_t *nonces) { +static SIMDExecInstr intSIMDInstr = SIMD_AUTO; + +void SetSIMDInstr(SIMDExecInstr instr) { + intSIMDInstr = instr; + + crack_states_bitsliced_function_p = &crack_states_bitsliced_dispatch; + bitslice_test_nonces_function_p = &bitslice_test_nonces_dispatch; +} + +SIMDExecInstr GetSIMDInstr() { + SIMDExecInstr instr = SIMD_NONE; + #if defined (__i386__) || defined (__x86_64__) - #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) + #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) - if (__builtin_cpu_supports("avx512f")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX512; - else if (__builtin_cpu_supports("avx2")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX2; + if (__builtin_cpu_supports("avx512f")) instr = SIMD_AVX512; + else if (__builtin_cpu_supports("avx2")) instr = SIMD_AVX2; #else - if (__builtin_cpu_supports("avx2")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX2; + if (__builtin_cpu_supports("avx2")) instr = SIMD_AVX2; #endif - else if (__builtin_cpu_supports("avx")) crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX; - else if (__builtin_cpu_supports("sse2")) crack_states_bitsliced_function_p = &crack_states_bitsliced_SSE2; - else if (__builtin_cpu_supports("mmx")) crack_states_bitsliced_function_p = &crack_states_bitsliced_MMX; + else if (__builtin_cpu_supports("avx")) instr = SIMD_AVX; + else if (__builtin_cpu_supports("sse2")) instr = SIMD_SSE2; + else if (__builtin_cpu_supports("mmx")) instr = SIMD_MMX; else #endif #endif + instr = SIMD_NONE; + + return instr; +} + +SIMDExecInstr GetSIMDInstrAuto() { + SIMDExecInstr instr = intSIMDInstr; + if (instr == SIMD_AUTO) + return GetSIMDInstr(); + + return instr; +} + +// determine the available instruction set at runtime and call the correct function +const uint64_t crack_states_bitsliced_dispatch(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonce_2nd_byte, noncelist_t *nonces) { + switch(GetSIMDInstrAuto()) { +#if defined (__i386__) || defined (__x86_64__) + #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) + #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) + case SIMD_AVX512: + crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX512; + break; + #endif + case SIMD_AVX2: + crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX2; + break; + case SIMD_AVX: + crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX; + break; + case SIMD_SSE2: + crack_states_bitsliced_function_p = &crack_states_bitsliced_SSE2; + break; + case SIMD_MMX: + crack_states_bitsliced_function_p = &crack_states_bitsliced_MMX; + break; + #endif +#endif + default: crack_states_bitsliced_function_p = &crack_states_bitsliced_NOSIMD; + break; + } // call the most optimized function for this CPU return (*crack_states_bitsliced_function_p)(cuid, best_first_bytes, p, keys_found, num_keys_tested, nonces_to_bruteforce, bf_test_nonce_2nd_byte, nonces); } void bitslice_test_nonces_dispatch(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonce, uint8_t *bf_test_nonce_par) { + switch(GetSIMDInstrAuto()) { #if defined (__i386__) || defined (__x86_64__) #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) - if (__builtin_cpu_supports("avx512f")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX512; - else if (__builtin_cpu_supports("avx2")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX2; - #else - if (__builtin_cpu_supports("avx2")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX2; + case SIMD_AVX512: + bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX512; + break; #endif - else if (__builtin_cpu_supports("avx")) bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX; - else if (__builtin_cpu_supports("sse2")) bitslice_test_nonces_function_p = &bitslice_test_nonces_SSE2; - else if (__builtin_cpu_supports("mmx")) bitslice_test_nonces_function_p = &bitslice_test_nonces_MMX; - else + case SIMD_AVX2: + bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX2; + break; + case SIMD_AVX: + bitslice_test_nonces_function_p = &bitslice_test_nonces_AVX; + break; + case SIMD_SSE2: + bitslice_test_nonces_function_p = &bitslice_test_nonces_SSE2; + break; + case SIMD_MMX: + bitslice_test_nonces_function_p = &bitslice_test_nonces_MMX; + break; #endif #endif + default: bitslice_test_nonces_function_p = &bitslice_test_nonces_NOSIMD; + break; + } // call the most optimized function for this CPU (*bitslice_test_nonces_function_p)(nonces_to_bruteforce, bf_test_nonce, bf_test_nonce_par); diff --git a/client/hardnested/hardnested_bf_core.h b/client/hardnested/hardnested_bf_core.h index 7a445993e..b3df05474 100644 --- a/client/hardnested/hardnested_bf_core.h +++ b/client/hardnested/hardnested_bf_core.h @@ -52,6 +52,18 @@ THE SOFTWARE. #include "hardnested_bruteforce.h" // statelist_t +typedef enum { + SIMD_AUTO, + SIMD_AVX512, + SIMD_AVX2, + SIMD_AVX, + SIMD_SSE2, + SIMD_MMX, + SIMD_NONE, +} SIMDExecInstr; +extern void SetSIMDInstr(SIMDExecInstr instr); +extern SIMDExecInstr GetSIMDInstrAuto(); + extern const uint64_t crack_states_bitsliced(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonces_2nd_byte, noncelist_t *nonces); extern void bitslice_test_nonces(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonces, uint8_t *bf_test_nonce_par); From e60d4b38925caeb692ccd419bb360cfffa8b14bb Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 5 Nov 2018 17:48:58 +0100 Subject: [PATCH 0120/1938] add: emv json file (@merlokk) chg: compiler warning --- client/emv/defparams.json | 58 +++++++++++++++++++++++++++++++++++++++ client/emv/emv_tags.c | 17 ++++-------- client/emv/emv_tags.h | 1 + 3 files changed, 65 insertions(+), 11 deletions(-) create mode 100644 client/emv/defparams.json diff --git a/client/emv/defparams.json b/client/emv/defparams.json new file mode 100644 index 000000000..e615d3239 --- /dev/null +++ b/client/emv/defparams.json @@ -0,0 +1,58 @@ +[ + { + "name": "Transaction Date", + "tag": "9A", + "value": "00 00 00", + "length": 3, + "hint": "format: YYMMDD" + }, + { + "name": "Transaction Type", + "tag": "9C", + "value": "00", + "length": 1, + "hint": "00: Goods and service, 01: Cash" + }, + { + "name": "Amount, authorized", + "tag": "9F 02", + "value": "00 00 00 00 01 00", + "length": 6, + "hint": "amount (numberic) in cents" + }, + { + "name": "Transaction Currency Code", + "tag": "5F 2A", + "value": "09 80", + "length": 2, + "hint": "USD 840, EUR 978, RUB 643, RUR 810(old), UAH 980, AZN 031, n/a 999" + }, + { + "name": "Terminal Country Code", + "tag": "9F 1A", + "value": "72 75", + "length": 2, + "hint": "ISO3166: de, en (65 6e), uk(75 6b), ru (72 75), us, ua" + }, + { + "name": "Terminal Transaction Qualifiers (TTQ)", + "tag": "9F 66", + "value": "26 00 00 00", + "length": 4, + "hint": "qVSDC 26 00 00 00, gen AC from GPO 26 80 00 00, MSD 86 00 00 00, VSDC 46 00 00 00" + }, + { + "name": "Unpredictable Number", + "tag": "9F 37", + "value": "01 02 03 04", + "length": 4, + "hint": "4 byte random number" + }, + { + "name": "Unpredictable Number (MSD for UDOL)", + "tag": "9F 6A", + "value": "01 02 03 05", + "length": 4, + "hint": "4 byte random number" + } +] diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index fdccb8923..a1bf3d25e 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -353,15 +353,13 @@ static void emv_tag_dump_dol(const struct tlv *tlv, const struct emv_tag *tag, F } } -static void emv_tag_dump_string(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) -{ +static void emv_tag_dump_string(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level){ fprintf(f, "\tString value '"); fwrite(tlv->value, 1, tlv->len, f); fprintf(f, "'\n"); } -static unsigned long emv_value_numeric(const struct tlv *tlv, unsigned start, unsigned end) -{ +static unsigned long emv_value_numeric(const struct tlv *tlv, unsigned start, unsigned end) { unsigned long ret = 0; int i; @@ -391,14 +389,12 @@ static unsigned long emv_value_numeric(const struct tlv *tlv, unsigned start, un return ret; } -static void emv_tag_dump_numeric(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) -{ +static void emv_tag_dump_numeric(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { PRINT_INDENT(level); - fprintf(f, "\tNumeric value %lu\n", emv_value_numeric(tlv, 0, tlv->len * 2)); + fprintf(f, "\tNumeric value %" PRIu32 " \n", emv_value_numeric(tlv, 0, tlv->len * 2)); } -static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) -{ +static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { PRINT_INDENT(level); fprintf(f, "\tDate: 20%02ld.%ld.%ld\n", emv_value_numeric(tlv, 0, 2), @@ -406,8 +402,7 @@ static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag emv_value_numeric(tlv, 4, 6)); } -static uint32_t emv_get_binary(const unsigned char *S) -{ +static uint32_t emv_get_binary(const unsigned char *S) { return (S[0] << 24) | (S[1] << 16) | (S[2] << 8) | (S[3] << 0); } diff --git a/client/emv/emv_tags.h b/client/emv/emv_tags.h index f6d44f015..a9d1eea98 100644 --- a/client/emv/emv_tags.h +++ b/client/emv/emv_tags.h @@ -18,6 +18,7 @@ #include "tlv.h" #include +#include // AC # define EMVAC_AC_MASK 0xC0 From e26e9aa7105c979fe52dfd588d1946135ce41af9 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 5 Nov 2018 18:32:53 +0100 Subject: [PATCH 0121/1938] ADD: added support for lua-script to download from Flashmemory. --- client/scripting.c | 64 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 57 insertions(+), 7 deletions(-) diff --git a/client/scripting.c b/client/scripting.c index d981f1d7b..2a7baed0d 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -55,18 +55,17 @@ static int l_SendCommand(lua_State *L){ */ static int l_GetFromBigBuf(lua_State *L){ - int len = 0; - int startindex = 0; + int len = 0, startindex = 0; //Check number of arguments int n = lua_gettop(L); - if(n == 0) { + if (n == 0) { //signal error by returning Nil, errorstring lua_pushnil(L); - lua_pushstring(L,"You need to supply number of len and startindex"); + lua_pushstring(L, "You need to supply number of bytes and startindex"); return 2; // two return values } - if(n >= 2) { + if (n >= 2) { len = luaL_checknumber(L, 1); startindex = luaL_checknumber(L, 2); } @@ -78,11 +77,11 @@ static int l_GetFromBigBuf(lua_State *L){ lua_pushstring(L,"Allocating memory failed"); return 2; // two return values } - + if ( !GetFromDevice(BIG_BUF, data, len, startindex, NULL, 2500, false)) { free(data); lua_pushnil(L); - lua_pushstring(L,"command execution time out"); + lua_pushstring(L, "command execution time out"); return 2; } @@ -91,6 +90,56 @@ static int l_GetFromBigBuf(lua_State *L){ free(data); return 1;// return 1 to signal one return value } + +/** + * @brief The following params expected: + * uint8_t *dest + * int bytes + * int start_index + * @param L + * @return + */ +static int l_GetFromFlashMem(lua_State *L){ + +#ifndef WITH_FLASH + lua_pushnil(L); + lua_pushstring(L, "Not compiled with FLASH MEM support"); + return 2; +#else + int len = 0, startindex = 0; + + int n = lua_gettop(L); + if (n == 0) { + lua_pushnil(L); + lua_pushstring(L, "You need to supply number of bytes and startindex"); + return 2; + } + if (n >= 2) { + len = luaL_checknumber(L, 1); + startindex = luaL_checknumber(L, 2); + } + + uint8_t *data = calloc(len, sizeof(uint8_t)); + if ( !data ) { + lua_pushnil(L); + lua_pushstring(L, "Allocating memory failed"); + return 2; + } + + if ( !GetFromDevice(FLASH_MEM, data, len, startindex, NULL, -1, false)) { + free(data); + lua_pushnil(L); + lua_pushstring(L, "command execution time out"); + return 2; + } + + lua_pushlstring(L,(const char *)data, len); + free(data); + return 1; +#endif +} + + /** * @brief The following params expected: * uint32_t cmd @@ -655,6 +704,7 @@ int set_pm3_libraries(lua_State *L) { static const luaL_Reg libs[] = { {"SendCommand", l_SendCommand}, {"GetFromBigBuf", l_GetFromBigBuf}, + {"GetFromFlashMem", l_GetFromFlashMem}, {"WaitForResponseTimeout", l_WaitForResponseTimeout}, {"mfDarkside", l_mfDarkside}, {"foobar", l_foobar}, From b3ebf73ecc33513aab4d602505559e54c3966987 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 5 Nov 2018 18:45:46 +0100 Subject: [PATCH 0122/1938] chg: lua - Swapping param order to make it more clear. From (length,offset) to (offset,length) --- client/scripting.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/scripting.c b/client/scripting.c index 2a7baed0d..06356293f 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -66,8 +66,8 @@ static int l_GetFromBigBuf(lua_State *L){ return 2; // two return values } if (n >= 2) { - len = luaL_checknumber(L, 1); - startindex = luaL_checknumber(L, 2); + startindex = luaL_checknumber(L, 1); + len = luaL_checknumber(L, 2); } uint8_t *data = calloc(len, sizeof(uint8_t)); @@ -115,8 +115,8 @@ static int l_GetFromFlashMem(lua_State *L){ return 2; } if (n >= 2) { - len = luaL_checknumber(L, 1); - startindex = luaL_checknumber(L, 2); + startindex = luaL_checknumber(L, 1); + len = luaL_checknumber(L, 2); } uint8_t *data = calloc(len, sizeof(uint8_t)); From 4d500dff2f7479b3df69c023659f1c0dc306890b Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 5 Nov 2018 21:20:03 +0100 Subject: [PATCH 0123/1938] textual --- client/cmdsmartcard.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index f60e04e06..fc188b951 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -21,8 +21,8 @@ int usage_sm_raw(void) { PrintAndLogEx(NORMAL, " d : bytes to send"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " sc raw d 00a404000e315041592e5359532e444446303100 - “1PAY.SYS.DDF01” PPSE directory"); - PrintAndLogEx(NORMAL, " sc raw d 00a404000e325041592e5359532e444446303100 - “2PAY.SYS.DDF01” PPSE directory"); + PrintAndLogEx(NORMAL, " sc raw d 00a404000e315041592e5359532e444446303100 - `1PAY.SYS.DDF01` PPSE directory"); + PrintAndLogEx(NORMAL, " sc raw d 00a404000e325041592e5359532e444446303100 - `2PAY.SYS.DDF01` PPSE directory"); return 0; } int usage_sm_reader(void) { @@ -225,7 +225,6 @@ int CmdSmartRaw(const char *Cmd) { return 2; } - // TLV decoder if (decodeTLV && len > 4) TLVPrintFromBuffer(buf+1, len-3); @@ -496,7 +495,6 @@ int CmdSmartBruteforceSFI(const char *Cmd) { char ctmp = tolower(param_getchar(Cmd, 0)); if (ctmp == 'h') return usage_sm_brute(); - uint8_t data[5] = {0x00, 0xB2, 0x00, 0x00, 0x00}; PrintAndLogEx(INFO, "Selecting card"); From ecc79838665716acb03c505de7bcb28496b47fc4 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 5 Nov 2018 22:29:31 +0100 Subject: [PATCH 0124/1938] fix: hf mf hardnested - access out of malloc mem. (@vdwel) https://github.com/RfidResearchGroup/proxmark3/issues/46 looks like increasing size removes the problem. --- client/cmdhfmfhard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 42e97e4b9..07e05a81e 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -1750,7 +1750,7 @@ static void add_matching_states(statelist_t *candidates, uint8_t part_sum_a0, ui PrintAndLogEx(WARNING, "Out of memory error in add_matching_states() - statelist.\n"); exit(4); } - uint32_t *candidates_bitarray = (uint32_t *)malloc_bitarray(sizeof(uint32_t) * (1<<19)); + uint32_t *candidates_bitarray = (uint32_t *)malloc_bitarray(sizeof(uint32_t) * worstcase_size); if (candidates_bitarray == NULL) { PrintAndLogEx(WARNING, "Out of memory error in add_matching_states() - bitarray.\n"); free(candidates->states[odd_even]); From d58786ed74a82e282ab0b1612db4e9733391443b Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 5 Nov 2018 22:30:46 +0100 Subject: [PATCH 0125/1938] chg: 'hf iclass chk' - remove some printing --- client/cmdhficlass.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 6b57d7efd..1f0204ba0 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -2047,7 +2047,7 @@ int CmdHFiClassCheckKeys(const char *Cmd) { return 1; } - PrintPreCalcMac(keyBlock, keycnt, pre); + //PrintPreCalcMac(keyBlock, keycnt, pre); // max 42 keys inside USB_COMMAND. 512/4 = 103 mac uint32_t chunksize = keycnt > (USB_CMD_DATA_SIZE/4) ? (USB_CMD_DATA_SIZE/4) : keycnt; From 98e24013cfe68aef60d129f089ed72ec4c5dcac5 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 5 Nov 2018 22:34:46 +0100 Subject: [PATCH 0126/1938] chg: 'hf mf chk' - since the function ends with droping the field, lets just make sure the field is off to start with. --- armsrc/mifarecmd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index fcfe99134..7d39b3f29 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1425,6 +1425,8 @@ OUT: void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + struct Crypto1State mpcs = {0, 0}; struct Crypto1State *pcs; pcs = &mpcs; From d6d96eb7fecf1378cdfe2c2f8bd875eded7ac466 Mon Sep 17 00:00:00 2001 From: bogiton <34060135+bogiton@users.noreply.github.com> Date: Tue, 6 Nov 2018 13:36:00 +0000 Subject: [PATCH 0127/1938] Fixed offset bug (thanks iceman) --- armsrc/Standalone/hf_bog.c | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/armsrc/Standalone/hf_bog.c b/armsrc/Standalone/hf_bog.c index 761e67b1a..01232a6a0 100644 --- a/armsrc/Standalone/hf_bog.c +++ b/armsrc/Standalone/hf_bog.c @@ -15,7 +15,8 @@ The retrieved sniffing session can be acquired by connecting the device to a client that supports the reconnect capability and issue 'hf 14a list'. In order to view the grabbed authentication attempts in the flash mem, -you can simply 'mem read l 256' from the client to view the stored quadlets. +you can simply run 'script run read_pwd_mem' or just 'mem read l 256' +from the client to view the stored quadlets. */ #include "hf_bog.h" @@ -31,7 +32,7 @@ uint8_t FindOffsetInFlash() { uint8_t eom[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; uint8_t memcnt = 0; - while (memcnt < 4096) + while (memcnt < 0xFF) { Flash_ReadData(memcnt, mem, 4); if (memcmp(mem, eom, 4) == 0) { @@ -240,10 +241,20 @@ void RAMFUNC SniffAndStore(uint8_t param) { uint8_t memoffset = FindOffsetInFlash(); if (MF_DBGLEVEL > 1) Dbprintf("[!] Memory offset = %u", memoffset); + if ((memoffset + 4 * auth_attempts) > 0xFF) + { + // We opt to keep the new data only + memoffset = 0; + if (MF_DBGLEVEL > 1) Dbprintf("[!] Size of total data > 256 bytes. Discarding the old data."); + } + // Get previous data from flash mem uint8_t *previousdata = BigBuf_malloc(memoffset); - uint16_t readlen = Flash_ReadData(0, previousdata, memoffset); - if (MF_DBGLEVEL > 1) Dbprintf("[!] Read %u bytes from flash mem", readlen); + if (memoffset > 0) + { + uint16_t readlen = Flash_ReadData(0, previousdata, memoffset); + if (MF_DBGLEVEL > 1) Dbprintf("[!] Read %u bytes from flash mem", readlen); + } // create new bigbuf to hold all data size_t total_size = memoffset + 4 * auth_attempts; @@ -276,7 +287,7 @@ void RunMod() { Dbprintf("Sniffing started"); - SpinDelay(200); + SpinDelay(200); // param: // bit 0 - trigger from first card answer From db374585451b2098925abc2c294e269c1dd58d22 Mon Sep 17 00:00:00 2001 From: bogiton <34060135+bogiton@users.noreply.github.com> Date: Tue, 6 Nov 2018 13:37:34 +0000 Subject: [PATCH 0128/1938] Added lua script to read stored pwds in flashmem --- client/scripts/read_pwd_mem.lua | 86 +++++++++++++++++++++++++++++++++ 1 file changed, 86 insertions(+) create mode 100644 client/scripts/read_pwd_mem.lua diff --git a/client/scripts/read_pwd_mem.lua b/client/scripts/read_pwd_mem.lua new file mode 100644 index 000000000..fbe4d0459 --- /dev/null +++ b/client/scripts/read_pwd_mem.lua @@ -0,0 +1,86 @@ +local getopt = require('getopt') +local bin = require('bin') + +author = "Bogito" +version = 'v1.0.0' +desc =[[ +This script will read the flash memory of RDV4 and print the stored passwords. +It was meant to be used as a help tool after using the BogRun standalone mode. +]] +usage = [[ +Usage: + script run read_pwd_mem -h -o -l + +Arguments: + -h : this help + -o : Memory offset. Default is 0. + -l : Length in bytes. Default is 256. +]] +example =[[ +Examples: + -- This will scan the first 256 bytes of flash memory for stored passwords + script run read_pwd_mem + + -- This will scan 256 bytes of flash memory at offset 64 for stored passwords + script run read_pwd_mem -o 64 + + -- This will scan 32 bytes of flash memory at offset 64 for stored passwords + script run read_pwd_mem -o 64 -l 32 +]] + +-- Usage help +local function help() + print(desc) + print(usage) + print(example) +end + +local function main(args) + + local data, err, quadlet, pwdcnt + local offset = 0 + local length = 256 + + -- Read the parameters + for o, a in getopt.getopt(args, 'ho:l:') do + if o == "h" then return help() end + if o == "o" then offset = tonumber(a) end + if o == "l" then length = tonumber(a) end + end + + if length < 0 or length > 256 then + return print('Error: Length is not valid. Must be less than 256') + end + + if ((offset < 0) or (offset % 4 ~= 0)) then + return print('Error: Offset is not valid. Mod-4 values are only allowed.') + end + + print('Offset: ' .. offset) + print('Length: ' .. length) + print() + + data, err = core.GetFromFlashMem(offset, length) + + if err then + print(err) + return + end + + local count, s = bin.unpack('H'..length, data) + + pwdcnt = 0 + for i = 1,(length/4),1 + do + quadlet = string.sub(s, (i-1)*8+1, i*8) + if quadlet == "FFFFFFFF" then break end + print(string.format("[%02d]",i) .. ' ' .. quadlet) + pwdcnt = pwdcnt + 1 + + end + print() + print('Found passwords: ' .. pwdcnt) + +end + +main(args) From 4d124c46f226041b4f0e5ab09013f293c4d7264e Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 6 Nov 2018 19:13:06 +0100 Subject: [PATCH 0129/1938] chg: 'standlone mode colinrun aka KIGIV' - made it smaller to fit a normal compilation of fullimage --- armsrc/Standalone/hf_colin.c | 174 +++++------------------------------ armsrc/Standalone/hf_colin.h | 14 ++- 2 files changed, 28 insertions(+), 160 deletions(-) diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index fc0c7967a..18547ee12 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -1,5 +1,5 @@ //----------------------------------------------------------------------------- -// Colin Brigato, 2016,2017 +// Colin Brigato, 2016, 2017 // Christian Herrmann, 2017 // // This code is licensed to you under the terms of the GNU GPL, version 2 or, @@ -21,10 +21,11 @@ int currfline; int curlline; // TODO : Implement fast read of KEYS like in RFIdea -// als ohttp://ext.delaat.net/rp/2015-2016/p04/report.pdf +// also http://ext.delaat.net/rp/2015-2016/p04/report.pdf // Colin's VIGIKPWN sniff/simulate/clone repeat routine for HF Mifare +/* void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug) { uint32_t chunksize = (USB_CMD_DATA_SIZE / 4); @@ -56,6 +57,7 @@ void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug DbprintfEx(FLAG_NOLOG, " "); } } +*/ void cjSetCursFRight() { @@ -153,83 +155,8 @@ void SpinUp(uint32_t speed) LED_D_OFF(); } -void TestFlashmemSpeed(size_t buffersize, uint32_t spibaudrate) { - - FLASHMEM_SPIBAUDRATE = spibaudrate*1000000; - DbprintfEx(FLAG_NOLOG, "%s---+----[ %s %s[%dKB] %s] (%d)", _GREEN_, _WHITE_, _YELLOW_, buffersize / 1024, _WHITE_, FLASHMEM_SPIBAUDRATE); - uint16_t t = 0; - - LED_B_ON(); - uint8_t *mem = BigBuf_malloc(buffersize); - bool isok = false; - size_t len = 0; - uint32_t startidx = 0; - uint32_t numofbytes = 0x3FFFF; - - if (!FlashInit()) { - return; - } - //Flash_CheckBusy(BUSY_TIMEOUT); - - //Flash_ReadStat1(); - - uint32_t end_time; - uint32_t start_time = end_time = GetTickCount(); - - for (size_t i = 0; i < numofbytes; i += buffersize) - { - len = MIN((numofbytes - i), buffersize); - - //isok = Flash_ReadData(startidx + i, mem, len); - //uint32_t iend_time; - //uint32_t istart_time = iend_time = GetTickCount(); - isok = Flash_ReadDataCont(startidx + i, mem, len); - //iend_time = GetTickCount(); - //DbprintfEx(FLAG_RAWPRINT, "%s%dms%s>", _YELLOW_, iend_time - istart_time, _WHITE_); - //cjSetCursLeft(); - if (!isok) - { - Dbprintf("[FAIL] reading flash memory failed :: | bytes between %d - %d", i, len); - return; - } - //isok = cmd_send(CMD_FLASHMEM_DOWNLOADED, i, len, 0, mem, len); - //if (!isok) - // Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); - t++; - } - end_time = GetTickCount(); - DbprintfEx(FLAG_NOLOG, "%s |--< %s %s%dms%s for FULL_FLASH_READ", _GREEN_, _WHITE_, _YELLOW_, end_time - start_time, _WHITE_); - DbprintfEx(FLAG_NOLOG, "%s `--= %s %d runs of %s~%dms%s each", _GREEN_, _WHITE_, t, _YELLOW_, (end_time - start_time) / t, _WHITE_); - DbprintfEx(FLAG_NOLOG, ""); - //cjSetCursLeft(); - LED_B_OFF(); - FlashStop(); -} - -void TestFlashmemRoutine() +void ReadLastTagFromFlash() { - DbprintfEx(FLAG_NOLOG, "%s>>%s Will Now Test dumping Full flash [256Kb] (2Mbits)through Bigbuf buffers\n", _GREEN_, _WHITE_); - MF_DBGLEVEL = MF_DBG_NONE; - //DbprintfEx(FLAG_NOLOG, "---------\n%s[A]%s Using NORMAL Reads @Max (24Mhz=MCK/2)\n--------", _GREEN_, _WHITE_); - TestFlashmemSpeed(32768,24); - TestFlashmemSpeed(16384 + 4096 + 4096,24); - TestFlashmemSpeed(16384,24); - TestFlashmemSpeed(4096,24); - TestFlashmemSpeed(1024,24); - //SpinDelay(1000); - //WDT_HIT(); - //DbprintfEx(FLAG_NOLOG, "--------\n%s[B]%s Using FAST Reads @Max (48Mhz=MCK=CPUClock/2=MAXSPI)\n--------", _GREEN_, _WHITE_); - TestFlashmemSpeed(32768,48); - TestFlashmemSpeed(16384 + 4096 + 4096,48); - TestFlashmemSpeed(16384,48); - TestFlashmemSpeed(4096,48); - TestFlashmemSpeed(1024,48); - //SpinDelay(1000); - //WDT_HIT(); - return; -} - -void ReadLastTagFromFlash() { SpinOff(0); LED_A_ON(); LED_B_ON(); @@ -250,20 +177,15 @@ void ReadLastTagFromFlash() { } Flash_CheckBusy(BUSY_TIMEOUT); - //Flash_ReadStat1(); - uint32_t end_time; uint32_t start_time = end_time = GetTickCount(); for (size_t i = 0; i < len; i += size) { len = MIN((len - i), size); - - // isok = Flash_FastReadDataCont(startidx + i, mem, len); isok = Flash_ReadDataCont(startidx + i, mem, len); if (isok == len) { - //print_result("Chunk: ", mem, len); emlSetMem(mem, 0, 64); } else @@ -287,7 +209,6 @@ void ReadLastTagFromFlash() { void WriteTagToFlash(uint8_t index, size_t size) { - SpinOff(0); LED_A_ON(); LED_B_ON(); @@ -302,7 +223,7 @@ void WriteTagToFlash(uint8_t index, size_t size) uint8_t data[(size * (16 * 64))/1024]; uint8_t buff[PAGESIZE]; - // cnt = 0; + emlGetMem(data, 0, (size * 64)/1024); if (!FlashInit()){ @@ -318,9 +239,8 @@ void WriteTagToFlash(uint8_t index, size_t size) while (bytes_remaining > 0) { - - Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); @@ -337,7 +257,6 @@ void WriteTagToFlash(uint8_t index, size_t size) DbprintfEx(FLAG_NOLOG, "FlashMem write FAILEd [offset %u]", bytes_sent); cjSetCursLeft(); SpinOff(100); - return; } @@ -352,11 +271,8 @@ void WriteTagToFlash(uint8_t index, size_t size) cjSetCursLeft(); DbprintfEx(FLAG_NOLOG, "%s[IN]%s %s%dms%s for TAG_FLASH_WRITE", _GREEN_, _WHITE_, _YELLOW_, end_time - start_time, _WHITE_); cjSetCursLeft(); - FlashStop(); - SpinOff(0); - return; } @@ -473,11 +389,12 @@ ACCBITS : 796788[00]+VALUE { for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { - // validKey[t][sectorNo] = false; - for (uint16_t i = 0; i < 6; i++) - { - foundKey[t][sectorNo][i] = 0xff; - } + foundKey[t][sectorNo][0] = 0xFF; + foundKey[t][sectorNo][1] = 0xFF; + foundKey[t][sectorNo][2] = 0xFF; + foundKey[t][sectorNo][3] = 0xFF; + foundKey[t][sectorNo][4] = 0xFF; + foundKey[t][sectorNo][5] = 0xFF; } } @@ -491,7 +408,6 @@ ACCBITS : 796788[00]+VALUE // banner: vtsend_reset(NULL); DbprintfEx(FLAG_NOLOG, "\r\n%s", clearTerm); - cjPrintBigArray(LOGO, sizeof(LOGO), 0, 0); DbprintfEx(FLAG_NOLOG, "%s%s%s", _CYAN_, sub_banner, _WHITE_); DbprintfEx(FLAG_NOLOG, "%s>>%s C.J.B's MifareFastPwn Started\r\n", _RED_, _WHITE_); @@ -506,11 +422,6 @@ ACCBITS : 796788[00]+VALUE SpinOff(50); SpinDown(50); -#if 0 -TestFlashmemRoutine(); -return; -#endif - failtag: vtsend_cursor_position_save(NULL); @@ -607,7 +518,7 @@ failtag: for (int sec = 0; sec < sectorsCnt && !err && !trapped; ++sec) { key = cjat91_saMifareChkKeys(sec * 4, type, NULL, size, &keyBlock[0], &key64); - // key = saMifareChkKeys(sec * 4, type, NULL, size, &keyBlock[0], &key64); + if (key == -1) { err = 1; @@ -932,7 +843,7 @@ failtag: cjSetCursLeft(); cjSetCursLeft(); - WriteTagToFlash(0,1024); + WriteTagToFlash(0, 1024); readysim: // SIM ? @@ -966,16 +877,6 @@ readysim: DbprintfEx(FLAG_NOLOG, "<- We're out of Emulation"); // END SIM - /*for (;;) { - WDT_HIT(); - - int button_action = BUTTON_HELD(500); - if (button_action == 0) { // No button action, proceed with sim - SpinDelay(100); - WDT_HIT(); - - } else if (button_action == BUTTON_SINGLE_CLICK) { - */ cjSetCursLeft(); DbprintfEx(FLAG_NOLOG, "-> Trying a clone !"); @@ -987,15 +888,7 @@ readysim: DbprintfEx(FLAG_NOLOG, "-> End Cloning."); WDT_HIT(); - // break; - /*} else if (button_action == BUTTON_HOLD) { - DbprintfEx(FLAG_RAWPRINT,"Playtime over. Begin cloning..."); - iGotoClone = 1; - break; - }*/ - // Debunk... - // SpinDelay(300); cjSetCursLeft(); cjTabulize(); vtsend_set_attribute(NULL, 0); @@ -1020,14 +913,13 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat uint8_t numSectors = arg0; uint8_t keyType = arg1; uint64_t ui64Key = 0; - // uint32_t cuid; + struct Crypto1State mpcs = {0, 0}; struct Crypto1State *pcs; pcs = &mpcs; byte_t dataoutbuf[16]; byte_t dataoutbuf2[16]; - // uint8_t uid[10]; iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); @@ -1035,7 +927,6 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat set_tracing(false); bool isOK = true; - // iso14443a_fast_select_card(cjuid, 0); if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) { @@ -1113,22 +1004,17 @@ void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *dat DbpString("EMUL FILL SECTORS FINISHED\n"); } -/* . . . */ - /* the chk function is a piwi’ed(tm) check that will try all keys for a particular sector. also no tracing no dbg */ - int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key) { MF_DBGLEVEL = MF_DBG_NONE; iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); set_tracing(false); - // uint8_t uid[10]; - // uint32_t cuid; + struct Crypto1State mpcs = {0, 0}; struct Crypto1State *pcs; pcs = &mpcs; - // byte_t isOK = 0; for (int i = 0; i < keyCount; ++i) { @@ -1241,7 +1127,6 @@ void saMifareMakeTag(void) //----------------------------------------------------------------------------- int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { - // params uint8_t needWipe = arg0; // bit 0 - need get UID @@ -1259,9 +1144,7 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data // variables byte_t isOK = 0; - // uint8_t uid[10] = {0x00}; uint8_t d_block[18] = {0x00}; - // uint32_t cuid; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; @@ -1270,7 +1153,6 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data if (workFlags & 0x08) { iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - // clear_trace(); set_tracing(FALSE); } @@ -1282,19 +1164,15 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data // get UID from chip if (workFlags & 0x01) { - // if (!iso14443a_fast_select_card(cjuid, 0)) { - if (!iso14443a_select_card(cjuid, NULL, &cjcuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) - DbprintfEx(FLAG_NOLOG, "Can't select card"); + DbprintfEx(FLAG_NOLOG, "Can't select card"); break; }; if (mifare_classic_halt(NULL, cjcuid)) { - if (MF_DBGLEVEL >= 1) - DbprintfEx(FLAG_NOLOG, "Halt error"); + DbprintfEx(FLAG_NOLOG, "Halt error"); break; }; }; @@ -1305,7 +1183,6 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data ReaderTransmitBitsPar(wupC1, 7, 0, NULL); if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - // if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "wupC1 error"); break; }; @@ -1313,15 +1190,13 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data ReaderTransmit(wipeC, sizeof(wipeC), NULL); if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) - DbprintfEx(FLAG_NOLOG, "wipeC error"); + DbprintfEx(FLAG_NOLOG, "wipeC error"); break; }; if (mifare_classic_halt(NULL, cjcuid)) { - if (MF_DBGLEVEL >= 1) - DbprintfEx(FLAG_NOLOG, "Halt error"); + DbprintfEx(FLAG_NOLOG, "Halt error"); break; }; }; @@ -1333,7 +1208,6 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data ReaderTransmitBitsPar(wupC1, 7, 0, NULL); if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - // if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "wupC1 error"); break; }; @@ -1341,7 +1215,6 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data ReaderTransmit(wupC2, sizeof(wupC2), NULL); if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - // if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "wupC2 errorv"); break; }; @@ -1349,7 +1222,6 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { - // if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "write block send command error"); break; }; @@ -1359,7 +1231,6 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data ReaderTransmit(d_block, sizeof(d_block), NULL); if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) { - // if (MF_DBGLEVEL >= 1) DbprintfEx(FLAG_NOLOG, "write block send data error"); break; }; @@ -1368,7 +1239,6 @@ int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *data { if (mifare_classic_halt(NULL, cjcuid)) { - // if (MF_DBGLEVEL >= 1) cjSetCursFRight(); DbprintfEx(FLAG_NOLOG, "Halt error"); diff --git a/armsrc/Standalone/hf_colin.h b/armsrc/Standalone/hf_colin.h index dd3da6322..028c7b5b6 100644 --- a/armsrc/Standalone/hf_colin.h +++ b/armsrc/Standalone/hf_colin.h @@ -16,18 +16,15 @@ #ifndef __HF_COLIN_H #define __HF_COLIN_H - #include "proxmark3.h" #include "mifareutil.h" #include "iso14443a.h" -//#include "printf.h" #include "protocols.h" #include "util.h" #include "standalone.h" // standalone definitions #include // for bool #include #include -//#include #include "vtsend.h" #include "apps.h" #include "printf.h" @@ -47,17 +44,17 @@ int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, ui void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void saMifareMakeTag(void); int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); -void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug); void WriteTagToFlash(uint8_t index, size_t size); const char clearTerm[8] = {0x1b, 0x5b, 0x48, 0x1b, 0x5b, 0x32, 0x4a, '\0'}; -void TestFlashmemSpeed(size_t buffersize, uint32_t spibaudrate); +//void cjPrintBigArray(const char *bigar, int len, uint8_t newlines, uint8_t debug); +//void TestFlashmemSpeed(size_t buffersize, uint32_t spibaudrate); +//#define LOGO logo_kigiv -#define LOGO logo_kigiv - -const char sub_banner[] = " From Vigik : \"20 years of (un)security without a single update\""; +const char sub_banner[] = " From Vigik : \"20 years of (un)security without a single update\""; +/* const char logo_kigiv[] = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x31, 0x33, 0x37, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x39, 0x35, @@ -418,6 +415,7 @@ const char logo_kigiv[] = { 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x30, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x1b, 0x5b, 0x33, 0x38, 0x3b, 0x35, 0x3b, 0x35, 0x39, 0x6d, 0x31, 0x0d, 0x0a}; unsigned int logo_kigiv_len = 9303; +*/ /*const char logo_kigiv_nocolor[] = { 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x20, 0x30, 0x30, 0x30, 0x30, 0x20, 0x20, From 5a03ea7135d6a08369a2816f2ca24d24f6fb747c Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 6 Nov 2018 19:14:19 +0100 Subject: [PATCH 0130/1938] chg: 'standalone mode BogRun' - cleaning --- armsrc/Standalone/hf_bog.c | 19 +++++-------------- 1 file changed, 5 insertions(+), 14 deletions(-) diff --git a/armsrc/Standalone/hf_bog.c b/armsrc/Standalone/hf_bog.c index 761e67b1a..510d08d02 100644 --- a/armsrc/Standalone/hf_bog.c +++ b/armsrc/Standalone/hf_bog.c @@ -43,8 +43,7 @@ uint8_t FindOffsetInFlash() { return 0; // wrap-around } -void EraseMemory() -{ +void EraseMemory() { if (!FlashInit()){ return; } @@ -257,10 +256,7 @@ void RAMFUNC SniffAndStore(uint8_t param) { // Erase first page of flash mem EraseMemory(); - - //for (int i=0; i 1) Dbprintf("[-] total_data[%d] = 0x%02x", i, total_data[i]); - + // Write total data to flash mem uint16_t writelen = Flash_WriteData(0, total_data, memoffset + 4 * auth_attempts); if (MF_DBGLEVEL > 1) Dbprintf("[!] Wrote %u bytes into flash mem", writelen); @@ -272,18 +268,13 @@ void RAMFUNC SniffAndStore(uint8_t param) { } } -void RunMod() -{ +void RunMod() { Dbprintf("Sniffing started"); - SpinDelay(200); - // param: // bit 0 - trigger from first card answer // bit 1 - trigger from first reader 7-bit request - SniffAndStore(0); - - LEDsoff(); - + SniffAndStore(0); + LEDsoff(); SpinDelay(300); } From 078196773cdda29b9873851c5f2f90650fcf93ea Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 6 Nov 2018 22:20:55 +0100 Subject: [PATCH 0131/1938] CHG: 'standalone bogitorun' - adapted some ledshow from Kigiv mode and increased time for user to stop pressing button after triggering the mode.. --- armsrc/Standalone/hf_bog.c | 15 ++++++-- armsrc/Standalone/hf_colin.c | 68 ------------------------------------ armsrc/Standalone/hf_colin.h | 2 -- armsrc/util.c | 64 +++++++++++++++++++++++++++++++++ armsrc/util.h | 11 +++++- 5 files changed, 86 insertions(+), 74 deletions(-) diff --git a/armsrc/Standalone/hf_bog.c b/armsrc/Standalone/hf_bog.c index 510d08d02..bea2a1877 100644 --- a/armsrc/Standalone/hf_bog.c +++ b/armsrc/Standalone/hf_bog.c @@ -57,10 +57,9 @@ void EraseMemory() { SpinDelay(100); } +// This is actually copied from SniffIso14443a void RAMFUNC SniffAndStore(uint8_t param) { - /* This is actually copied from SniffIso14443a */ - iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); // Allocate memory from BigBuf for some buffers @@ -269,7 +268,16 @@ void RAMFUNC SniffAndStore(uint8_t param) { } void RunMod() { - Dbprintf("Sniffing started"); + + Dbprintf(">> Bogiton 14a Sniff UL/UL-EV1/NTAG a.k.a BogitoRun Started <<"); + Dbprintf("Starting to sniff"); + + SpinDown(50); + SpinOff(50); + SpinUp(50); + SpinOff(50); + SpinDown(50); + SpinDelay(500); // param: // bit 0 - trigger from first card answer @@ -277,4 +285,5 @@ void RunMod() { SniffAndStore(0); LEDsoff(); SpinDelay(300); + Dbprintf("- [ End ] -> You can take shell back ..."); } diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index 18547ee12..c91c05766 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -87,74 +87,6 @@ void cjPrintKey(uint64_t key, uint8_t *foundKey, uint16_t sectorNo, uint8_t type DbprintfEx(FLAG_NOLOG, "SEC: %02x | KEY : %s | TYP: %d", sectorNo, tosendkey, type); } -void SpinOff(uint32_t pause) -{ - LED_A_OFF(); - LED_B_OFF(); - LED_C_OFF(); - LED_D_OFF(); - SpinDelay(pause); -} - -// 0=A, 1=B, 2=C, 3=D -void SpinErr(uint8_t led, uint32_t speed, uint8_t times) -{ - SpinOff(speed); - NTIME(times) - { - switch (led) - { - case 0: - LED_A_INV(); - break; - case 1: - LED_B_INV(); - break; - case 2: - LED_C_INV(); - break; - case 3: - LED_D_INV(); - break; - } - SpinDelay(speed); - } -} - -void SpinDown(uint32_t speed) -{ - SpinOff(speed); - LED_D_ON(); - SpinDelay(speed); - LED_D_OFF(); - LED_C_ON(); - SpinDelay(speed); - LED_C_OFF(); - LED_B_ON(); - SpinDelay(speed); - LED_B_OFF(); - LED_A_ON(); - SpinDelay(speed); - LED_A_OFF(); -} - -void SpinUp(uint32_t speed) -{ - SpinOff(speed); - LED_A_ON(); - SpinDelay(speed); - LED_A_OFF(); - LED_B_ON(); - SpinDelay(speed); - LED_B_OFF(); - LED_C_ON(); - SpinDelay(speed); - LED_C_OFF(); - LED_D_ON(); - SpinDelay(speed); - LED_D_OFF(); -} - void ReadLastTagFromFlash() { SpinOff(0); diff --git a/armsrc/Standalone/hf_colin.h b/armsrc/Standalone/hf_colin.h index 028c7b5b6..2b7879b6b 100644 --- a/armsrc/Standalone/hf_colin.h +++ b/armsrc/Standalone/hf_colin.h @@ -38,8 +38,6 @@ #define _WHITE_ "\x1b[0m" #define _ORANGE_ _YELLOW_ -#define NTIME(n) for (int _index = 0; _index < n; _index++) - int cjat91_saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key); void e_MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain); void saMifareMakeTag(void); diff --git a/armsrc/util.c b/armsrc/util.c index b5be57923..77ef3a494 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -154,6 +154,70 @@ void LED(int led, int ms) { LED_D_OFF(); } +void SpinOff(uint32_t pause) { + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + LED_D_OFF(); + SpinDelay(pause); +} + +// 0=A, 1=B, 2=C, 3=D +void SpinErr(uint8_t led, uint32_t speed, uint8_t times) { + SpinOff(speed); + NTIME(times) + { + switch (led) { + case 0: + LED_A_INV(); + break; + case 1: + LED_B_INV(); + break; + case 2: + LED_C_INV(); + break; + case 3: + LED_D_INV(); + break; + } + SpinDelay(speed); + } +} + +void SpinDown(uint32_t speed) { + SpinOff(speed); + LED_D_ON(); + SpinDelay(speed); + LED_D_OFF(); + LED_C_ON(); + SpinDelay(speed); + LED_C_OFF(); + LED_B_ON(); + SpinDelay(speed); + LED_B_OFF(); + LED_A_ON(); + SpinDelay(speed); + LED_A_OFF(); +} + +void SpinUp(uint32_t speed) { + SpinOff(speed); + LED_A_ON(); + SpinDelay(speed); + LED_A_OFF(); + LED_B_ON(); + SpinDelay(speed); + LED_B_OFF(); + LED_C_ON(); + SpinDelay(speed); + LED_C_OFF(); + LED_D_ON(); + SpinDelay(speed); + LED_D_OFF(); +} + + // Determine if a button is double clicked, single clicked, // not clicked, or held down (for ms || 1sec) // In general, don't use this function unless you expect a diff --git a/armsrc/util.h b/armsrc/util.h index 77fd81ee4..cc613b273 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -39,6 +39,10 @@ # define ARRAYLEN(x) (sizeof(x)/sizeof((x)[0])) #endif +#ifndef NTIME +# define NTIME(n) for (int _index = 0; _index < n; _index++) +#endif + size_t nbytes(size_t nbits); extern uint32_t reflect(uint32_t v, int b); // used in crc.c ... @@ -53,7 +57,12 @@ int32_t le24toh (uint8_t data[3]); uint8_t hex2int(char hexchar); void LED(int led, int ms); -void LEDsoff(); +void LEDsoff(void); +void SpinOff(uint32_t pause); +void SpinErr(uint8_t led, uint32_t speed, uint8_t times); +void SpinDown(uint32_t speed); +void SpinUp(uint32_t speed); + int BUTTON_CLICKED(int ms); int BUTTON_HELD(int ms); void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information); From c75c0e4e52a64130827951b4bbb55942ac43ab9a Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 7 Nov 2018 12:21:57 +0100 Subject: [PATCH 0132/1938] chg: cleaning up in lfdemod.c, currently the ASK clock, demod of strong and weak signals --- common/lfdemod.c | 126 ++++++++++++++++++++++++++++------------------- 1 file changed, 75 insertions(+), 51 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index 4714cdb69..6b755d3dc 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -322,7 +322,7 @@ size_t findModStart(uint8_t *src, size_t size, uint8_t expWaveSize) { uint8_t thresholdCnt = 0; bool isAboveThreshold = src[i++] >= signalprop.mean; //FSK_PSK_THRESHOLD; for (; i < size-20; i++ ) { - if(src[i] < signalprop.mean && isAboveThreshold) { + if (src[i] < signalprop.mean && isAboveThreshold) { thresholdCnt++; if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break; isAboveThreshold = false; @@ -341,20 +341,12 @@ size_t findModStart(uint8_t *src, size_t size, uint8_t expWaveSize) { return i; } -// iceman: ranges the old defintion, becomes very forgiving when clock speed increase. -// clocks[i] - (clocks[i]/8) && testclk <= clocks[i]+1 ) -// 8 (7-9) -// 16 (14-17) -// 32 (28-33) -// 40 (35-41) -// 50 (46-51) -// 64 (56-65) -// 128 (112-129) int getClosestClock(int testclk) { - uint8_t clocks[] = {8,16,32,40,50,64,128}; + uint16_t clocks[] = {8, 16, 32, 40, 50, 64, 128, 256, 384}; + uint8_t limit[] = {1, 2, 4, 4, 5, 8, 8, 8, 8}; - for (uint8_t i = 0; i < 7; i++) - if ( testclk >= clocks[i]-2 && testclk <= clocks[i]+1 ) + for (uint8_t i = 0; i < 9; i++) + if ( testclk >= clocks[i]-limit[i] && testclk <= clocks[i]+limit[i] ) return clocks[i]; return 0; @@ -543,8 +535,9 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo // set clock if (g_debugMode == 2) prnt("DEBUG ASK: DetectStrongAskClock smallest wave: %d", minClk); *clock = getClosestClock(minClk); + if (*clock == 0) - return 0; + return -1; return shortestWaveIdx; } @@ -554,43 +547,60 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo // maybe somehow adjust peak trimming value based on samples to fix? // return start index of best starting position for that clock and return clock (by reference) int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { - size_t i = 1; - uint16_t clk[] = {255,8,16,32,40,50,64,100,128,255}; - uint16_t clkEnd = 9; - uint16_t loopCnt = 1500; //don't need to loop through entire array... (cotag has clock of 384) - if (size <= loopCnt + 60) return -1; //not enough samples - size -= 60; //sometimes there is a strange end wave - filter out this.... - //if we already have a valid clock - uint8_t clockFnd = 0; - for (; i < clkEnd; ++i) { - if (clk[i] == *clock) { - //clock found but continue to find best startpos - clockFnd = i; - } - } + //don't need to loop through entire array. (cotag has clock of 384) + uint16_t loopCnt = 1500; + + // not enough samples + if (size <= loopCnt + 60){ + if (g_debugMode == 2) prnt("DEBUG DetectASKClock: not enough samples - aborting"); + return -1; + } + // just noise - no super good detection. good enough if (signalprop.isnoise) { if (g_debugMode == 2) prnt("DEBUG DetectASKClock: just noise detected - aborting"); - return -1; + return -2; } - //get high and low peak + size_t i = 1; + uint16_t num_clks = 9; + // first 255 value pos0 is placeholder for user inputed clock. + uint16_t clk[] = {255, 8, 16, 32, 40, 50, 64, 100, 128, 255}; + + // sometimes there is a strange end wave - filter out this + size -= 60; + + // What is purpose? + // already have a valid clock? + uint8_t found_clk = 0; + for (; i < num_clks; ++i) { + if (clk[i] == *clock) { + found_clk = i; + } + } + + // threshold 75% of high, low peak int peak_hi, peak_low; getHiLo(&peak_hi, &peak_low, 75, 75); - //test for large clean peaks - if (!clockFnd){ + // test for large clean, STRONG, CLIPPED peaks + + if (!found_clk) { + if (DetectCleanAskWave(dest, size, peak_hi, peak_low)){ int idx = DetectStrongAskClock(dest, size, peak_hi, peak_low, clock); if (g_debugMode == 2) - prnt("DEBUG ASK: detectaskclk Clean Ask Wave Detected: clk %i, Best Starting Position: %i", *clock, idx); - if (idx > 0) - return idx; //return shortest wave start position - + prnt("DEBUG ASK: DetectASKClock Clean ASK Wave detected: clk %i, Best Starting Position: %i", *clock, idx); + + // return shortest wave start position + if (idx > -1) + return idx; } } + // test for weak peaks + // test clock if given as cmd parameter if ( *clock > 0 ) clk[0] = *clock; @@ -601,15 +611,15 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { uint8_t bestStart[] = {0,0,0,0,0,0,0,0,0}; size_t errCnt = 0, arrLoc, loopEnd; - if (clockFnd > 0) { - clkCnt = clockFnd; - clkEnd = clockFnd+1; + if (found_clk) { + clkCnt = found_clk; + num_clks = found_clk + 1; } else { clkCnt = 1; } //test each valid clock from smallest to greatest to see which lines up - for (; clkCnt < clkEnd; clkCnt++) { + for (; clkCnt < num_clks; clkCnt++) { if (clk[clkCnt] <= 32) { tol = 1; } else { @@ -640,15 +650,15 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { errCnt++; } } - //if we found no errors then we can stop here and a low clock (common clocks) + // if we found no errors then we can stop here and a low clock (common clocks) // this is correct one - return this clock - //if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d", clk[clkCnt], errCnt, j, i); + // if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d", clk[clkCnt], errCnt, j, i); if (errCnt == 0 && clkCnt < 7) { - if (!clockFnd) + if (!found_clk) *clock = clk[clkCnt]; return j; } - //if we found errors see if it is lowest so far and save it as best run + // if we found errors see if it is lowest so far and save it as best run if (errCnt < bestErr[clkCnt]) { bestErr[clkCnt] = errCnt; bestStart[clkCnt] = j; @@ -658,7 +668,7 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { uint8_t k, best = 0; - for (k=1; k < clkEnd; ++k){ + for (k=1; k < num_clks; ++k){ if (bestErr[k] < bestErr[best]){ if (bestErr[k] == 0) bestErr[k] = 1; // current best bit to error ratio vs new bit to error ratio @@ -668,7 +678,9 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { } //if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, # Errors %d, Current Best Clk %d, bestStart %d", clk[k], bestErr[k], clk[best], bestStart[best]); } - if (!clockFnd) *clock = clk[best]; + + if (!found_clk) + *clock = clk[best]; return bestStart[best]; } @@ -1419,14 +1431,14 @@ int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos) int cleanAskRawDemod(uint8_t *bits, size_t *size, int clk, int invert, int high, int low, int *startIdx) { *startIdx = 0; size_t bitCnt = 0, smplCnt = 1, errCnt = 0, pos = 0; - uint8_t cl_4 = clk / 4; uint8_t cl_2 = clk / 2; - - getNextHigh(bits, *size, high, &pos); bool waveHigh = true; - for (size_t i=pos; i < *size; i++){ + getNextHigh(bits, *size, high, &pos); + + // sample counts, like clock = 32.. it tries to find 32/4 = 8, 32/2 = 16 + for (size_t i = pos; i < *size; i++){ if (bits[i] >= high && waveHigh){ smplCnt++; } else if (bits[i] <= low && !waveHigh){ @@ -1434,10 +1446,13 @@ int cleanAskRawDemod(uint8_t *bits, size_t *size, int clk, int invert, int high, } else { //transition if ((bits[i] >= high && !waveHigh) || (bits[i] <= low && waveHigh)){ + // 32-8-1 = 23 + // 32+8+1 = 41 if (smplCnt > clk - cl_4 - 1) { //full clock + if (smplCnt > clk + cl_4 + 1) { //too many samples errCnt++; - if (g_debugMode == 2) prnt("DEBUG:(cleanAskRawDemod) ASK Modulation Error at: %u", i); + if (g_debugMode == 2) prnt("DEBUG ASK: cleanAskRawDemod ASK Modulation Error FULL at: %u [%u]", i, smplCnt); bits[bitCnt++] = 7; } else if (waveHigh) { bits[bitCnt++] = invert; @@ -1450,7 +1465,16 @@ int cleanAskRawDemod(uint8_t *bits, size_t *size, int clk, int invert, int high, *startIdx = i - clk; waveHigh = !waveHigh; smplCnt = 0; + + // 16-8-1 = 7 } else if (smplCnt > cl_2 - cl_4 - 1) { //half clock + + if (smplCnt > cl_2 + cl_4 + 1) { //too many samples + errCnt++; + if (g_debugMode == 2) prnt("DEBUG ASK: cleanAskRawDemod ASK Modulation Error HALF at: %u [%u]", i, smplCnt); + bits[bitCnt++] = 7; + } + if (waveHigh) { bits[bitCnt++] = invert; } else if (!waveHigh) { From 6ab12db7a0e80faff6df53951fc033d34add4af7 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Nov 2018 18:05:02 +0200 Subject: [PATCH 0133/1938] mbedtls added --- client/Makefile | 21 +- client/cmdhf14b.h | 2 +- client/cmdhfmf.h | 2 +- client/cmdhfmfp.c | 2 +- client/crypto/asn1utils.c | 63 + client/crypto/asn1utils.h | 21 + client/crypto/libpcrypto.c | 381 ++ .../polarssl => client/crypto}/libpcrypto.h | 10 + client/emv/crypto_polarssl.c | 73 +- client/emv/test/cryptotest.c | 62 +- client/mifare4.c | 2 +- client/obj/crypto/.dummy | 0 common/mbedtls/Makefile | 86 + common/mbedtls/aes.c | 2125 +++++++++++ common/mbedtls/aes.h | 628 ++++ common/mbedtls/arc4.c | 203 ++ common/mbedtls/arc4.h | 143 + common/mbedtls/asn1.h | 360 ++ common/mbedtls/asn1parse.c | 391 ++ common/mbedtls/asn1write.c | 392 +++ common/mbedtls/asn1write.h | 242 ++ common/{polarssl => mbedtls}/base64.c | 36 +- common/{polarssl => mbedtls}/base64.h | 22 +- common/mbedtls/bignum.c | 2470 +++++++++++++ common/mbedtls/bignum.h | 774 ++++ common/mbedtls/blowfish.c | 654 ++++ common/mbedtls/blowfish.h | 246 ++ common/mbedtls/bn_mul.h | 895 +++++ common/mbedtls/camellia.c | 1070 ++++++ common/mbedtls/camellia.h | 273 ++ common/mbedtls/certs.c | 405 +++ common/mbedtls/certs.h | 102 + common/mbedtls/check_config.h | 685 ++++ common/mbedtls/cipher.c | 1108 ++++++ common/mbedtls/cipher.h | 808 +++++ common/mbedtls/cipher_internal.h | 127 + common/mbedtls/cipher_wrap.c | 2274 ++++++++++++ common/mbedtls/cmac.c | 1080 ++++++ common/mbedtls/cmac.h | 208 ++ common/mbedtls/config.h | 3129 +++++++++++++++++ common/mbedtls/ctr_drbg.c | 652 ++++ common/mbedtls/ctr_drbg.h | 332 ++ common/mbedtls/des.c | 1059 ++++++ common/mbedtls/des.h | 352 ++ common/mbedtls/ecdsa.c | 463 +++ common/mbedtls/ecdsa.h | 341 ++ common/mbedtls/ecp.c | 2209 ++++++++++++ common/mbedtls/ecp.h | 766 ++++ common/mbedtls/ecp_curves.c | 1462 ++++++++ common/mbedtls/ecp_internal.h | 295 ++ common/mbedtls/entropy.c | 723 ++++ common/mbedtls/entropy.h | 291 ++ common/mbedtls/entropy_poll.c | 277 ++ common/mbedtls/entropy_poll.h | 112 + common/mbedtls/error.c | 897 +++++ common/mbedtls/error.h | 124 + common/mbedtls/md.c | 477 +++ common/mbedtls/md.h | 468 +++ common/mbedtls/md5.c | 497 +++ common/mbedtls/md5.h | 308 ++ common/mbedtls/md_internal.h | 117 + common/mbedtls/md_wrap.c | 588 ++++ common/mbedtls/oid.c | 757 ++++ common/mbedtls/oid.h | 607 ++++ common/mbedtls/pem.c | 490 +++ common/mbedtls/pem.h | 132 + common/mbedtls/pk.c | 381 ++ common/mbedtls/pk.h | 620 ++++ common/mbedtls/pk_internal.h | 117 + common/mbedtls/pk_wrap.c | 525 +++ common/mbedtls/pkcs12.c | 363 ++ common/mbedtls/pkcs12.h | 122 + common/mbedtls/pkcs5.c | 428 +++ common/mbedtls/pkcs5.h | 97 + common/mbedtls/pkparse.c | 1449 ++++++++ common/mbedtls/platform.c | 341 ++ common/mbedtls/platform.h | 366 ++ common/mbedtls/platform_util.c | 69 + common/mbedtls/platform_util.h | 64 + common/mbedtls/rsa.c | 2400 +++++++++++++ common/mbedtls/rsa.h | 1133 ++++++ common/mbedtls/rsa_internal.c | 489 +++ common/mbedtls/rsa_internal.h | 228 ++ common/{polarssl => mbedtls}/sha1.c | 468 +-- common/mbedtls/sha1.h | 326 ++ common/{polarssl => mbedtls}/sha256.c | 214 +- common/mbedtls/sha256.h | 274 ++ common/mbedtls/sha512.c | 612 ++++ common/mbedtls/sha512.h | 272 ++ common/mbedtls/threading.c | 142 + common/mbedtls/threading.h | 110 + common/mbedtls/timing.c | 547 +++ common/mbedtls/timing.h | 155 + common/mbedtls/x509.c | 1073 ++++++ common/mbedtls/x509.h | 335 ++ common/mbedtls/x509_crl.c | 775 ++++ common/mbedtls/x509_crl.h | 176 + common/mbedtls/x509_crt.c | 2488 +++++++++++++ common/mbedtls/x509_crt.h | 672 ++++ common/polarssl/aes.c | 1454 -------- common/polarssl/aes.h | 256 -- common/polarssl/aes_cmac128.c | 322 -- common/polarssl/aes_cmac128.h | 81 - common/polarssl/bignum.c | 2143 ----------- common/polarssl/bignum.h | 685 ---- common/polarssl/bn_mul.h | 864 ----- common/polarssl/hmac_drbg.c | 533 --- common/polarssl/hmac_drbg.h | 300 -- common/polarssl/libpcrypto.c | 78 - common/polarssl/rsa.c | 1466 -------- common/polarssl/rsa.h | 597 ---- common/polarssl/sha1.h | 213 -- common/polarssl/sha256.h | 142 - 113 files changed, 53771 insertions(+), 9565 deletions(-) create mode 100644 client/crypto/asn1utils.c create mode 100644 client/crypto/asn1utils.h create mode 100644 client/crypto/libpcrypto.c rename {common/polarssl => client/crypto}/libpcrypto.h (65%) create mode 100644 client/obj/crypto/.dummy create mode 100644 common/mbedtls/Makefile create mode 100644 common/mbedtls/aes.c create mode 100644 common/mbedtls/aes.h create mode 100644 common/mbedtls/arc4.c create mode 100644 common/mbedtls/arc4.h create mode 100644 common/mbedtls/asn1.h create mode 100644 common/mbedtls/asn1parse.c create mode 100644 common/mbedtls/asn1write.c create mode 100644 common/mbedtls/asn1write.h rename common/{polarssl => mbedtls}/base64.c (87%) rename common/{polarssl => mbedtls}/base64.h (77%) create mode 100644 common/mbedtls/bignum.c create mode 100644 common/mbedtls/bignum.h create mode 100644 common/mbedtls/blowfish.c create mode 100644 common/mbedtls/blowfish.h create mode 100644 common/mbedtls/bn_mul.h create mode 100644 common/mbedtls/camellia.c create mode 100644 common/mbedtls/camellia.h create mode 100644 common/mbedtls/certs.c create mode 100644 common/mbedtls/certs.h create mode 100644 common/mbedtls/check_config.h create mode 100644 common/mbedtls/cipher.c create mode 100644 common/mbedtls/cipher.h create mode 100644 common/mbedtls/cipher_internal.h create mode 100644 common/mbedtls/cipher_wrap.c create mode 100644 common/mbedtls/cmac.c create mode 100644 common/mbedtls/cmac.h create mode 100644 common/mbedtls/config.h create mode 100644 common/mbedtls/ctr_drbg.c create mode 100644 common/mbedtls/ctr_drbg.h create mode 100644 common/mbedtls/des.c create mode 100644 common/mbedtls/des.h create mode 100644 common/mbedtls/ecdsa.c create mode 100644 common/mbedtls/ecdsa.h create mode 100644 common/mbedtls/ecp.c create mode 100644 common/mbedtls/ecp.h create mode 100644 common/mbedtls/ecp_curves.c create mode 100644 common/mbedtls/ecp_internal.h create mode 100644 common/mbedtls/entropy.c create mode 100644 common/mbedtls/entropy.h create mode 100644 common/mbedtls/entropy_poll.c create mode 100644 common/mbedtls/entropy_poll.h create mode 100644 common/mbedtls/error.c create mode 100644 common/mbedtls/error.h create mode 100644 common/mbedtls/md.c create mode 100644 common/mbedtls/md.h create mode 100644 common/mbedtls/md5.c create mode 100644 common/mbedtls/md5.h create mode 100644 common/mbedtls/md_internal.h create mode 100644 common/mbedtls/md_wrap.c create mode 100644 common/mbedtls/oid.c create mode 100644 common/mbedtls/oid.h create mode 100644 common/mbedtls/pem.c create mode 100644 common/mbedtls/pem.h create mode 100644 common/mbedtls/pk.c create mode 100644 common/mbedtls/pk.h create mode 100644 common/mbedtls/pk_internal.h create mode 100644 common/mbedtls/pk_wrap.c create mode 100644 common/mbedtls/pkcs12.c create mode 100644 common/mbedtls/pkcs12.h create mode 100644 common/mbedtls/pkcs5.c create mode 100644 common/mbedtls/pkcs5.h create mode 100644 common/mbedtls/pkparse.c create mode 100644 common/mbedtls/platform.c create mode 100644 common/mbedtls/platform.h create mode 100644 common/mbedtls/platform_util.c create mode 100644 common/mbedtls/platform_util.h create mode 100644 common/mbedtls/rsa.c create mode 100644 common/mbedtls/rsa.h create mode 100644 common/mbedtls/rsa_internal.c create mode 100644 common/mbedtls/rsa_internal.h rename common/{polarssl => mbedtls}/sha1.c (50%) create mode 100644 common/mbedtls/sha1.h rename common/{polarssl => mbedtls}/sha256.c (70%) create mode 100644 common/mbedtls/sha256.h create mode 100644 common/mbedtls/sha512.c create mode 100644 common/mbedtls/sha512.h create mode 100644 common/mbedtls/threading.c create mode 100644 common/mbedtls/threading.h create mode 100644 common/mbedtls/timing.c create mode 100644 common/mbedtls/timing.h create mode 100644 common/mbedtls/x509.c create mode 100644 common/mbedtls/x509.h create mode 100644 common/mbedtls/x509_crl.c create mode 100644 common/mbedtls/x509_crl.h create mode 100644 common/mbedtls/x509_crt.c create mode 100644 common/mbedtls/x509_crt.h delete mode 100644 common/polarssl/aes.c delete mode 100644 common/polarssl/aes.h delete mode 100644 common/polarssl/aes_cmac128.c delete mode 100644 common/polarssl/aes_cmac128.h delete mode 100644 common/polarssl/bignum.c delete mode 100644 common/polarssl/bignum.h delete mode 100644 common/polarssl/bn_mul.h delete mode 100644 common/polarssl/hmac_drbg.c delete mode 100644 common/polarssl/hmac_drbg.h delete mode 100644 common/polarssl/libpcrypto.c delete mode 100644 common/polarssl/rsa.c delete mode 100644 common/polarssl/rsa.h delete mode 100644 common/polarssl/sha1.h delete mode 100644 common/polarssl/sha256.h diff --git a/client/Makefile b/client/Makefile index a31be08d5..03c4c1288 100644 --- a/client/Makefile +++ b/client/Makefile @@ -25,6 +25,8 @@ OBJDIR = obj LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm LUALIB = ../liblua/liblua.a +MBEDTLSLIBPATH = ../common/mbedtls +MBEDTLSLIB = $(MBEDTLSLIBPATH)/libmbedtls.a LDFLAGS = $(ENV_LDFLAGS) INCLUDES_CLIENT = -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua CFLAGS = $(ENV_CFLAGS) -std=c99 -D_ISOC99_SOURCE -DPRESETS $(INCLUDES_CLIENT) -Wall -g -O3 @@ -104,14 +106,8 @@ CMDSRCS = crapto1/crapto1.c \ mfkey.c \ tea.c \ polarssl/des.c \ - polarssl/aes.c \ - polarssl/aes_cmac128.c \ - polarssl/bignum.c \ - polarssl/rsa.c \ - polarssl/sha1.c \ - polarssl/sha256.c \ - polarssl/base64.c \ - polarssl/libpcrypto.c \ + crypto/libpcrypto.c\ + crypto/asn1utils.c\ cliparser/argtable3.c\ cliparser/cliparser.c\ loclass/cipher.c \ @@ -260,7 +256,7 @@ WINBINS = $(patsubst %, %.exe, $(BINS)) CLEAN = $(BINS) $(WINBINS) $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(ZLIBOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(OBJDIR)/*.o *.moc.cpp ui/ui_overlays.h lualibs/usb_cmd.lua lualibs/mf_default_keys.lua # need to assign dependancies to build these first... -all: lua_build $(BINS) +all: lua_build mbedtls_build $(BINS) all-static: LDLIBS:=-static $(LDLIBS) all-static: proxmark3 flasher fpga_compress @@ -292,6 +288,7 @@ lualibs/mf_default_keys.lua : default_keys.dic clean: $(RM) $(CLEAN) cd ../liblua && make clean + cd $(MBEDTLSLIBPATH) && make clean tarbin: $(BINS) $(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%) $(WINBINS:%=client/%) @@ -299,7 +296,11 @@ tarbin: $(BINS) lua_build: @echo Compiling liblua, using platform $(LUAPLATFORM) cd ../liblua && make $(LUAPLATFORM) - + +mbedtls_build: + @echo Compiling mbedtls + cd $(MBEDTLSLIBPATH) && make all + .PHONY: all clean # easy printing of MAKE VARIABLES diff --git a/client/cmdhf14b.h b/client/cmdhf14b.h index 6b44a7304..793949c86 100644 --- a/client/cmdhf14b.h +++ b/client/cmdhf14b.h @@ -25,7 +25,7 @@ #include "cmdhf14a.h" #include "cmdhf.h" #include "prng.h" -#include "sha1.h" +#include "mbedtls/sha1.h" #include "mifare.h" // structs/enum for ISO14B #include "protocols.h" // definitions of ISO14B protocol diff --git a/client/cmdhfmf.h b/client/cmdhfmf.h index b253ac0bb..eeb7a74f6 100644 --- a/client/cmdhfmf.h +++ b/client/cmdhfmf.h @@ -16,7 +16,7 @@ #include #include #include -#include +#include #include "proxmark3.h" #include "iso14443crc.h" #include "ui.h" diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 78cec3e2c..0d7a623d4 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -24,7 +24,7 @@ #include "mifare.h" #include "mifare4.h" #include "cliparser/cliparser.h" -#include "polarssl/libpcrypto.h" +#include "crypto/libpcrypto.h" static const uint8_t DefaultKey[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; diff --git a/client/crypto/asn1utils.c b/client/crypto/asn1utils.c new file mode 100644 index 000000000..2a3fe698b --- /dev/null +++ b/client/crypto/asn1utils.c @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// asn.1 utils +//----------------------------------------------------------------------------- + +#include "asn1utils.h" +#include + +int ecdsa_asn1_get_signature(uint8_t *signature, size_t signaturelen, uint8_t *rval, uint8_t *sval) { + if (!signature || !signaturelen || !rval || !sval) + return 1; + + int res = 0; + unsigned char *p = signature; + const unsigned char *end = p + signaturelen; + size_t len; + mbedtls_mpi xmpi; + + if ((res = mbedtls_asn1_get_tag(&p, end, &len, MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE)) == 0) { + mbedtls_mpi_init(&xmpi); + res = mbedtls_asn1_get_mpi(&p, end, &xmpi); + if (res) { + mbedtls_mpi_free(&xmpi); + goto exit; + } + + res = mbedtls_mpi_write_binary(&xmpi, rval, 32); + mbedtls_mpi_free(&xmpi); + if (res) + goto exit; + + mbedtls_mpi_init(&xmpi); + res = mbedtls_asn1_get_mpi(&p, end, &xmpi); + if (res) { + mbedtls_mpi_free(&xmpi); + goto exit; + } + + res = mbedtls_mpi_write_binary(&xmpi, sval, 32); + mbedtls_mpi_free(&xmpi); + if (res) + goto exit; + + // check size + if (end != p) + return 2; + } + +exit: + return res; +} + +int asn1_print(uint8_t *asn1buf, int level) { + + return 0; +} + + diff --git a/client/crypto/asn1utils.h b/client/crypto/asn1utils.h new file mode 100644 index 000000000..2b00f4501 --- /dev/null +++ b/client/crypto/asn1utils.h @@ -0,0 +1,21 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// asn.1 utils +//----------------------------------------------------------------------------- + +#ifndef ASN1UTILS_H +#define ASN1UTILS_H + +#include +#include +#include + +extern int asn1_print(uint8_t *asn1buf, int level); +extern int ecdsa_asn1_get_signature(uint8_t *signature, size_t signaturelen, uint8_t *rval, uint8_t *sval); + +#endif /* asn1utils.h */ diff --git a/client/crypto/libpcrypto.c b/client/crypto/libpcrypto.c new file mode 100644 index 000000000..030be15a3 --- /dev/null +++ b/client/crypto/libpcrypto.c @@ -0,0 +1,381 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// Copyright (C) 2018 drHatson +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// crypto commands +//----------------------------------------------------------------------------- + +#include "crypto/libpcrypto.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +// NIST Special Publication 800-38A — Recommendation for block cipher modes of operation: methods and techniques, 2001. +int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){ + uint8_t iiv[16] = {0}; + if (iv) + memcpy(iiv, iv, 16); + + mbedtls_aes_context aes; + mbedtls_aes_init(&aes); + if (mbedtls_aes_setkey_enc(&aes, key, 128)) + return 1; + if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_ENCRYPT, length, iiv, input, output)) + return 2; + mbedtls_aes_free(&aes); + + return 0; +} + +int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){ + uint8_t iiv[16] = {0}; + if (iv) + memcpy(iiv, iv, 16); + + mbedtls_aes_context aes; + mbedtls_aes_init(&aes); + if (mbedtls_aes_setkey_dec(&aes, key, 128)) + return 1; + if (mbedtls_aes_crypt_cbc(&aes, MBEDTLS_AES_DECRYPT, length, iiv, input, output)) + return 2; + mbedtls_aes_free(&aes); + + return 0; +} + +// NIST Special Publication 800-38B — Recommendation for block cipher modes of operation: The CMAC mode for authentication. +// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf +int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length) { + memset(mac, 0x00, 16); + + // NIST 800-38B + return mbedtls_aes_cmac_prf_128(key, MBEDTLS_AES_BLOCK_SIZE, input, length, mac); +} + +int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length) { + uint8_t cmac[16] = {0}; + memset(mac, 0x00, 8); + + int res = aes_cmac(iv, key, input, cmac, length); + if (res) + return res; + + for(int i = 0; i < 8; i++) + mac[i] = cmac[i * 2 + 1]; + + return 0; +} + +static uint8_t fixed_rand_value[250] = {0}; +static int fixed_rand(void *rng_state, unsigned char *output, size_t len) { + if (len <= 250) { + memcpy(output, fixed_rand_value, len); + } else { + memset(output, 0x00, len); + } + + return 0; +} + +int sha256hash(uint8_t *input, int length, uint8_t *hash) { + if (!hash || !input) + return 1; + + mbedtls_sha256_context sctx; + mbedtls_sha256_init(&sctx); + mbedtls_sha256_starts(&sctx, 0); // SHA-256, not 224 + mbedtls_sha256_update(&sctx, input, length); + mbedtls_sha256_finish(&sctx, hash); + mbedtls_sha256_free(&sctx); + + return 0; +} + +int ecdsa_init_str(mbedtls_ecdsa_context *ctx, char * key_d, char *key_x, char *key_y) { + if (!ctx) + return 1; + + int res; + + mbedtls_ecdsa_init(ctx); + res = mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1); // secp256r1 + if (res) + return res; + + if (key_d) { + res = mbedtls_mpi_read_string(&ctx->d, 16, key_d); + if (res) + return res; + } + + if (key_x && key_y) { + res = mbedtls_ecp_point_read_string(&ctx->Q, 16, key_x, key_y); + if (res) + return res; + } + + return 0; +} + +int ecdsa_init(mbedtls_ecdsa_context *ctx, uint8_t * key_d, uint8_t *key_xy) { + if (!ctx) + return 1; + + int res; + + mbedtls_ecdsa_init(ctx); + res = mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1); // secp256r1 + if (res) + return res; + + if (key_d) { + res = mbedtls_mpi_read_binary(&ctx->d, key_d, 32); + if (res) + return res; + } + + if (key_xy) { + res = mbedtls_ecp_point_read_binary(&ctx->grp, &ctx->Q, key_xy, 32 * 2 + 1); + if (res) + return res; + } + + return 0; +} + +int ecdsa_key_create(uint8_t * key_d, uint8_t *key_xy) { + int res; + mbedtls_ecdsa_context ctx; + ecdsa_init(&ctx, NULL, NULL); + + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + const char *pers = "ecdsaproxmark"; + + mbedtls_entropy_init(&entropy); + mbedtls_ctr_drbg_init(&ctr_drbg); + + res = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers)); + if (res) + goto exit; + + res = mbedtls_ecdsa_genkey(&ctx, MBEDTLS_ECP_DP_SECP256R1, mbedtls_ctr_drbg_random, &ctr_drbg); + if (res) + goto exit; + + res = mbedtls_mpi_write_binary(&ctx.d, key_d, 32); + if (res) + goto exit; + + size_t keylen = 0; + uint8_t public_key[200] = {0}; + res = mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &keylen, public_key, sizeof(public_key)); + if (res) + goto exit; + + if (keylen != 65) { // 0x04 + res = 1; + goto exit; + } + memcpy(key_xy, public_key, 65); + +exit: + mbedtls_entropy_free(&entropy); + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_ecdsa_free(&ctx); + return res; +} + +char *ecdsa_get_error(int ret) { + static char retstr[300]; + memset(retstr, 0x00, sizeof(retstr)); + mbedtls_strerror(ret, retstr, sizeof(retstr)); + return retstr; +} + +int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen) { + int res; + *signaturelen = 0; + + uint8_t shahash[32] = {0}; + res = sha256hash(input, length, shahash); + if (res) + return res; + + mbedtls_entropy_context entropy; + mbedtls_ctr_drbg_context ctr_drbg; + const char *pers = "ecdsaproxmark"; + + mbedtls_entropy_init(&entropy); + mbedtls_ctr_drbg_init(&ctr_drbg); + + res = mbedtls_ctr_drbg_seed(&ctr_drbg, mbedtls_entropy_func, &entropy, (const unsigned char *)pers, strlen(pers)); + if (res) + goto exit; + + mbedtls_ecdsa_context ctx; + ecdsa_init(&ctx, key_d, key_xy); + res = mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256, shahash, sizeof(shahash), signature, signaturelen, mbedtls_ctr_drbg_random, &ctr_drbg); + +exit: + mbedtls_ctr_drbg_free(&ctr_drbg); + mbedtls_ecdsa_free(&ctx); + return res; +} + +int ecdsa_signature_create_test(char * key_d, char *key_x, char *key_y, char *random, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen) { + int res; + *signaturelen = 0; + + uint8_t shahash[32] = {0}; + res = sha256hash(input, length, shahash); + if (res) + return res; + + int rndlen = 0; + param_gethex_to_eol(random, 0, fixed_rand_value, sizeof(fixed_rand_value), &rndlen); + + mbedtls_ecdsa_context ctx; + ecdsa_init_str(&ctx, key_d, key_x, key_y); + res = mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256, shahash, sizeof(shahash), signature, signaturelen, fixed_rand, NULL); + + mbedtls_ecdsa_free(&ctx); + return res; +} + +int ecdsa_signature_verify_keystr(char *key_x, char *key_y, uint8_t *input, int length, uint8_t *signature, size_t signaturelen) { + int res; + uint8_t shahash[32] = {0}; + res = sha256hash(input, length, shahash); + if (res) + return res; + + mbedtls_ecdsa_context ctx; + ecdsa_init_str(&ctx, NULL, key_x, key_y); + res = mbedtls_ecdsa_read_signature(&ctx, shahash, sizeof(shahash), signature, signaturelen); + + mbedtls_ecdsa_free(&ctx); + return res; +} + +int ecdsa_signature_verify(uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t signaturelen) { + int res; + uint8_t shahash[32] = {0}; + res = sha256hash(input, length, shahash); + if (res) + return res; + + mbedtls_ecdsa_context ctx; + ecdsa_init(&ctx, NULL, key_xy); + res = mbedtls_ecdsa_read_signature(&ctx, shahash, sizeof(shahash), signature, signaturelen); + + mbedtls_ecdsa_free(&ctx); + return res; +} + +#define T_PRIVATE_KEY "C477F9F65C22CCE20657FAA5B2D1D8122336F851A508A1ED04E479C34985BF96" +#define T_Q_X "B7E08AFDFE94BAD3F1DC8C734798BA1C62B3A0AD1E9EA2A38201CD0889BC7A19" +#define T_Q_Y "3603F747959DBF7A4BB226E41928729063ADC7AE43529E61B563BBC606CC5E09" +#define T_K "7A1A7E52797FC8CAAA435D2A4DACE39158504BF204FBE19F14DBB427FAEE50AE" +#define T_R "2B42F576D07F4165FF65D1F3B1500F81E44C316F1F0B3EF57325B69ACA46104F" +#define T_S "DC42C2122D6392CD3E3A993A89502A8198C1886FE69D262C4B329BDB6B63FAF1" + +int ecdsa_nist_test(bool verbose) { + int res; + uint8_t input[] = "Example of ECDSA with P-256"; + int length = strlen((char *)input); + uint8_t signature[300] = {0}; + size_t siglen = 0; + + // NIST ecdsa test + if (verbose) + printf(" ECDSA NIST test: "); + // make signature + res = ecdsa_signature_create_test(T_PRIVATE_KEY, T_Q_X, T_Q_Y, T_K, input, length, signature, &siglen); +// printf("res: %x signature[%x]: %s\n", (res<0)?-res:res, siglen, sprint_hex(signature, siglen)); + if (res) + goto exit; + + // check vectors + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; + res = ecdsa_asn1_get_signature(signature, siglen, rval, sval); + if (res) + goto exit; + + int slen = 0; + uint8_t rval_s[33] = {0}; + param_gethex_to_eol(T_R, 0, rval_s, sizeof(rval_s), &slen); + uint8_t sval_s[33] = {0}; + param_gethex_to_eol(T_S, 0, sval_s, sizeof(sval_s), &slen); + if (strncmp((char *)rval, (char *)rval_s, 32) || strncmp((char *)sval, (char *)sval_s, 32)) { + printf("R or S check error\n"); + res = 100; + goto exit; + } + + // verify signature + res = ecdsa_signature_verify_keystr(T_Q_X, T_Q_Y, input, length, signature, siglen); + if (res) + goto exit; + + // verify wrong signature + input[0] ^= 0xFF; + res = ecdsa_signature_verify_keystr(T_Q_X, T_Q_Y, input, length, signature, siglen); + if (!res) { + res = 1; + goto exit; + } + if (verbose) + printf("passed\n"); + + // random ecdsa test + if (verbose) + printf(" ECDSA binary signature create/check test: "); + + uint8_t key_d[32] = {0}; + uint8_t key_xy[32 * 2 + 2] = {0}; + memset(signature, 0x00, sizeof(signature)); + siglen = 0; + + res = ecdsa_key_create(key_d, key_xy); + if (res) + goto exit; + + res = ecdsa_signature_create(key_d, key_xy, input, length, signature, &siglen); + if (res) + goto exit; + + res = ecdsa_signature_verify(key_xy, input, length, signature, siglen); + if (res) + goto exit; + + input[0] ^= 0xFF; + res = ecdsa_signature_verify(key_xy, input, length, signature, siglen); + if (!res) + goto exit; + + if (verbose) + printf("passed\n\n"); + + return 0; +exit: + if (verbose) + printf("failed\n\n"); + return res; +} diff --git a/common/polarssl/libpcrypto.h b/client/crypto/libpcrypto.h similarity index 65% rename from common/polarssl/libpcrypto.h rename to client/crypto/libpcrypto.h index 1b74c143f..8d4b4a0d0 100644 --- a/common/polarssl/libpcrypto.h +++ b/client/crypto/libpcrypto.h @@ -12,6 +12,7 @@ #define LIBPCRYPTO_H #include +#include #include extern int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); @@ -19,4 +20,13 @@ extern int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output extern int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length); extern int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length); +extern int sha256hash(uint8_t *input, int length, uint8_t *hash); + +extern int ecdsa_key_create(uint8_t * key_d, uint8_t *key_xy); +extern int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen); +extern int ecdsa_signature_verify(uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t signaturelen); +extern char *ecdsa_get_error(int ret); + +extern int ecdsa_nist_test(bool verbose); + #endif /* libpcrypto.h */ diff --git a/client/emv/crypto_polarssl.c b/client/emv/crypto_polarssl.c index cf68b40ea..938535059 100644 --- a/client/emv/crypto_polarssl.c +++ b/client/emv/crypto_polarssl.c @@ -24,13 +24,14 @@ #include #include #include +#include -#include "rsa.h" -#include "sha1.h" +#include "mbedtls/rsa.h" +#include "mbedtls/sha1.h" struct crypto_hash_polarssl { struct crypto_hash ch; - sha1_context ctx; + mbedtls_sha1_context ctx; }; static void crypto_hash_polarssl_close(struct crypto_hash *_ch) @@ -44,7 +45,7 @@ static void crypto_hash_polarssl_write(struct crypto_hash *_ch, const unsigned c { struct crypto_hash_polarssl *ch = (struct crypto_hash_polarssl *)_ch; - sha1_update(&(ch->ctx), buf, len); + mbedtls_sha1_update(&(ch->ctx), buf, len); } static unsigned char *crypto_hash_polarssl_read(struct crypto_hash *_ch) @@ -52,7 +53,7 @@ static unsigned char *crypto_hash_polarssl_read(struct crypto_hash *_ch) struct crypto_hash_polarssl *ch = (struct crypto_hash_polarssl *)_ch; static unsigned char sha1sum[20]; - sha1_finish(&(ch->ctx), sha1sum); + mbedtls_sha1_finish(&(ch->ctx), sha1sum); return sha1sum; } @@ -71,7 +72,7 @@ static struct crypto_hash *crypto_hash_polarssl_open(enum crypto_algo_hash hash) struct crypto_hash_polarssl *ch = malloc(sizeof(*ch)); - sha1_starts(&(ch->ctx)); + mbedtls_sha1_starts(&(ch->ctx)); ch->ch.write = crypto_hash_polarssl_write; ch->ch.read = crypto_hash_polarssl_read; @@ -83,7 +84,7 @@ static struct crypto_hash *crypto_hash_polarssl_open(enum crypto_algo_hash hash) struct crypto_pk_polarssl { struct crypto_pk cp; - rsa_context ctx; + mbedtls_rsa_context ctx; }; static struct crypto_pk *crypto_pk_polarssl_open_rsa(va_list vl) @@ -96,13 +97,13 @@ static struct crypto_pk *crypto_pk_polarssl_open_rsa(va_list vl) char *exp = va_arg(vl, char *); // E int explen = va_arg(vl, size_t); - rsa_init(&cp->ctx, RSA_PKCS_V15, 0); + mbedtls_rsa_init(&cp->ctx, MBEDTLS_RSA_PKCS_V15, 0); cp->ctx.len = modlen; // size(N) in bytes - mpi_read_binary(&cp->ctx.N, (const unsigned char *)mod, modlen); - mpi_read_binary(&cp->ctx.E, (const unsigned char *)exp, explen); + mbedtls_mpi_read_binary(&cp->ctx.N, (const unsigned char *)mod, modlen); + mbedtls_mpi_read_binary(&cp->ctx.E, (const unsigned char *)exp, explen); - int res = rsa_check_pubkey(&cp->ctx); + int res = mbedtls_rsa_check_pubkey(&cp->ctx); if(res != 0) { fprintf(stderr, "PolarSSL public key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen); free(cp); @@ -134,23 +135,23 @@ static struct crypto_pk *crypto_pk_polarssl_open_priv_rsa(va_list vl) // char *inv = va_arg(vl, char *); // int invlen = va_arg(vl, size_t); - rsa_init(&cp->ctx, RSA_PKCS_V15, 0); + mbedtls_rsa_init(&cp->ctx, MBEDTLS_RSA_PKCS_V15, 0); cp->ctx.len = modlen; // size(N) in bytes - mpi_read_binary(&cp->ctx.N, (const unsigned char *)mod, modlen); - mpi_read_binary(&cp->ctx.E, (const unsigned char *)exp, explen); + mbedtls_mpi_read_binary(&cp->ctx.N, (const unsigned char *)mod, modlen); + mbedtls_mpi_read_binary(&cp->ctx.E, (const unsigned char *)exp, explen); - mpi_read_binary(&cp->ctx.D, (const unsigned char *)d, dlen); - mpi_read_binary(&cp->ctx.P, (const unsigned char *)p, plen); - mpi_read_binary(&cp->ctx.Q, (const unsigned char *)q, qlen); - mpi_read_binary(&cp->ctx.DP, (const unsigned char *)dp, dplen); - mpi_read_binary(&cp->ctx.DQ, (const unsigned char *)dq, dqlen); - mpi_inv_mod(&cp->ctx.QP, &cp->ctx.Q, &cp->ctx.P); + mbedtls_mpi_read_binary(&cp->ctx.D, (const unsigned char *)d, dlen); + mbedtls_mpi_read_binary(&cp->ctx.P, (const unsigned char *)p, plen); + mbedtls_mpi_read_binary(&cp->ctx.Q, (const unsigned char *)q, qlen); + mbedtls_mpi_read_binary(&cp->ctx.DP, (const unsigned char *)dp, dplen); + mbedtls_mpi_read_binary(&cp->ctx.DQ, (const unsigned char *)dq, dqlen); + mbedtls_mpi_inv_mod(&cp->ctx.QP, &cp->ctx.Q, &cp->ctx.P); - int res = rsa_check_privkey(&cp->ctx); + int res = mbedtls_rsa_check_privkey(&cp->ctx); if(res != 0) { fprintf(stderr, "PolarSSL private key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen); - free(cp); + free(cp); return NULL; } @@ -182,10 +183,10 @@ static struct crypto_pk *crypto_pk_polarssl_genkey_rsa(va_list vl) if (transient) { } - int res = rsa_gen_key(&cp->ctx, &myrand, NULL, nbits, exp); + int res = mbedtls_rsa_gen_key(&cp->ctx, &myrand, NULL, nbits, exp); if (res) { fprintf(stderr, "PolarSSL private key generation error res=%x exp=%d nbits=%d.\n", res * -1, exp, nbits); - free(cp); + free(cp); return NULL; } @@ -196,7 +197,7 @@ static void crypto_pk_polarssl_close(struct crypto_pk *_cp) { struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp; - rsa_free(&cp->ctx); + mbedtls_rsa_free(&cp->ctx); free(cp); } @@ -207,7 +208,7 @@ static unsigned char *crypto_pk_polarssl_encrypt(const struct crypto_pk *_cp, co unsigned char *result; *clen = 0; - size_t keylen = mpi_size(&cp->ctx.N); + size_t keylen = mbedtls_mpi_size(&cp->ctx.N); result = malloc(keylen); if (!result) { @@ -215,9 +216,9 @@ static unsigned char *crypto_pk_polarssl_encrypt(const struct crypto_pk *_cp, co return NULL; } - res = rsa_public(&cp->ctx, buf, result); - if (res) { - printf("RSA encrypt failed. Error: %x data len: %zu key len: %zu\n", res * -1, len, keylen); + res = mbedtls_rsa_public(&cp->ctx, buf, result); + if(res) { + printf("RSA encrypt failed. Error: %x data len: %zd key len: %zd\n", res * -1, len, keylen); free(result); return NULL; } @@ -234,7 +235,7 @@ static unsigned char *crypto_pk_polarssl_decrypt(const struct crypto_pk *_cp, co unsigned char *result; *clen = 0; - size_t keylen = mpi_size(&cp->ctx.N); + size_t keylen = mbedtls_mpi_size(&cp->ctx.N); result = malloc(keylen); if (!result) { @@ -242,9 +243,9 @@ static unsigned char *crypto_pk_polarssl_decrypt(const struct crypto_pk *_cp, co return NULL; } - res = rsa_private(&cp->ctx, buf, result); // CHECK??? + res = mbedtls_rsa_private(&cp->ctx, NULL, NULL, buf, result); // CHECK??? if(res) { - printf("RSA decrypt failed. Error: %x data len: %zu key len: %zu\n", res * -1, len, keylen); + printf("RSA decrypt failed. Error: %x data len: %zd key len: %zd\n", res * -1, len, keylen); free(result); return NULL; } @@ -269,17 +270,17 @@ static unsigned char *crypto_pk_polarssl_get_parameter(const struct crypto_pk *_ switch(param){ // mod case 0: - *plen = mpi_size(&cp->ctx.N); + *plen = mbedtls_mpi_size(&cp->ctx.N); result = malloc(*plen); memset(result, 0x00, *plen); - mpi_write_binary(&cp->ctx.N, result, *plen); + mbedtls_mpi_write_binary(&cp->ctx.N, result, *plen); break; // exp case 1: - *plen = mpi_size(&cp->ctx.E); + *plen = mbedtls_mpi_size(&cp->ctx.E); result = malloc(*plen); memset(result, 0x00, *plen); - mpi_write_binary(&cp->ctx.E, result, *plen); + mbedtls_mpi_write_binary(&cp->ctx.E, result, *plen); break; default: printf("Error get parameter. Param=%d", param); diff --git a/client/emv/test/cryptotest.c b/client/emv/test/cryptotest.c index b9be38ad5..1d5891fe0 100644 --- a/client/emv/test/cryptotest.c +++ b/client/emv/test/cryptotest.c @@ -12,38 +12,70 @@ #include "util.h" #include "ui.h" -#include "bignum.h" -#include "aes.h" -#include "aes_cmac128.h" -#include "des.h" -#include "rsa.h" -#include "sha1.h" +#include "mbedtls/bignum.h" +#include "mbedtls/aes.h" +#include "mbedtls/cmac.h" +#include "mbedtls/des.h" +#include "mbedtls/ecp.h" +#include "mbedtls/rsa.h" +#include "mbedtls/sha1.h" +#include "mbedtls/md5.h" +#include "mbedtls/x509.h" +#include "mbedtls/base64.h" +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/entropy.h" +#include "mbedtls/timing.h" #include "crypto_test.h" #include "sda_test.h" #include "dda_test.h" #include "cda_test.h" +#include "crypto/libpcrypto.h" int ExecuteCryptoTests(bool verbose) { int res; bool TestFail = false; - res = mpi_self_test(verbose); + res = mbedtls_mpi_self_test(verbose); if (res) TestFail = true; - res = aes_self_test(verbose); + res = mbedtls_aes_self_test(verbose); + if (res) TestFail = true; + + res = mbedtls_des_self_test(verbose); if (res) TestFail = true; - res = aes_cmac_self_test(verbose); + res = mbedtls_sha1_self_test(verbose); + if (res) TestFail = true; + + res = mbedtls_md5_self_test(verbose); if (res) TestFail = true; - res = des_self_test(verbose); + res = mbedtls_rsa_self_test(verbose); if (res) TestFail = true; - res = sha1_self_test(verbose); + res = mbedtls_entropy_self_test(verbose); + if (res) TestFail = true; + + res = mbedtls_timing_self_test(verbose); + if (res) TestFail = true; + + res = mbedtls_ctr_drbg_self_test(verbose); if (res) TestFail = true; - res = rsa_self_test(verbose); + res = mbedtls_base64_self_test(verbose); + if (res) TestFail = true; + + res = mbedtls_cmac_self_test(verbose); + if (res) TestFail = true; + + res = ecdsa_nist_test(verbose); + if (res) TestFail = true; + + res = mbedtls_ecp_self_test(verbose); + if (res) TestFail = true; + + res = mbedtls_x509_self_test(verbose); if (res) TestFail = true; res = exec_sda_test(verbose); @@ -58,11 +90,11 @@ int ExecuteCryptoTests(bool verbose) { res = exec_crypto_test(verbose); if (res) TestFail = true; - PrintAndLogEx(NORMAL, "\n--------------------------"); + PrintAndLog("\n--------------------------"); if (TestFail) - PrintAndLogEx(ERR, "Test(s) [ERROR]."); + PrintAndLog("Test(s) [ERROR]."); else - PrintAndLogEx(SUCCESS, "Tests [OK]."); + PrintAndLog("Tests [OK]."); return TestFail; } diff --git a/client/mifare4.c b/client/mifare4.c index 8f9bd9e67..39869ab77 100644 --- a/client/mifare4.c +++ b/client/mifare4.c @@ -15,7 +15,7 @@ #include "cmdhf14a.h" #include "util.h" #include "ui.h" -#include "polarssl/libpcrypto.h" +#include "crypto/libpcrypto.h" int CalculateEncIVCommand(mf4Session *session, uint8_t *iv, bool verbose) { memcpy(&iv[0], session->TI, 4); diff --git a/client/obj/crypto/.dummy b/client/obj/crypto/.dummy new file mode 100644 index 000000000..e69de29bb diff --git a/common/mbedtls/Makefile b/common/mbedtls/Makefile new file mode 100644 index 000000000..3e57fdac2 --- /dev/null +++ b/common/mbedtls/Makefile @@ -0,0 +1,86 @@ + +LIB_A = libmbedtls.a +mbedtls_SOURCES = \ + aes.c \ + asn1parse.c \ + asn1write.c \ + base64.c \ + bignum.c \ + ctr_drbg.c \ + entropy_poll.c \ + entropy.c \ + error.c \ + timing.c \ + ecp.c \ + ecp_curves.c \ + certs.c \ + camellia.c \ + blowfish.c \ + cipher_wrap.c \ + cipher.c \ + cmac.c \ + des.c \ + ecdsa.c \ + md.c \ + md_wrap.c \ + md5.c \ + oid.c \ + pem.c \ + arc4.c \ + pk.c \ + pk_wrap.c \ + pkcs5.c \ + pkcs12.c \ + pkparse.c \ + platform.c \ + platform_util.c \ + rsa.c \ + rsa_internal.c \ + sha1.c \ + sha256.c \ + sha512.c \ + threading.c \ + x509.c \ + x509_crl.c \ + x509_crt.c +mbedtls_LDFLAGS = \ + -no-undefined \ + -export-symbols-regex '^mbedtls_' \ + -version-info 15:0:11 + + +CFILES = $(filter %.c, $(mbedtls_SOURCES)) +CMDOBJS = $(CFILES:%.c=%.o) +CLEAN = $(CMDOBJS) + +CC= gcc +CFLAGS= -O2 -Wall -Wno-unused-variable -Wno-unused-function +LDFLAGS= $(SYSLDFLAGS) $(mbedtls_LDFLAGS) +LIBS= -lm $(SYSLIBS) $(MYLIBS) +DEFAULT_INCLUDES = -I. -I.. +DEFS = -DHAVE_STDINT_H + +AR= ar rcs +RANLIB= ranlib +RM= rm -f +TST= echo + +SYSLDFLAGS= +SYSLIBS= + +MYLIBS= +MYOBJS= + +all: $(CMDOBJS) + $(AR) $(LIB_A) $(CMDOBJS) + $(RANLIB) $(LIB_A) + +clean: + $(RM) $(CLEAN) + $(RM) $(LIB_A) + +%.o: %.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(CFLAGS) -c -o $@ $< $(LIBS) + +.PHONY: all clean + diff --git a/common/mbedtls/aes.c b/common/mbedtls/aes.c new file mode 100644 index 000000000..07391ecd5 --- /dev/null +++ b/common/mbedtls/aes.c @@ -0,0 +1,2125 @@ +/* + * FIPS-197 compliant AES implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The AES block cipher was designed by Vincent Rijmen and Joan Daemen. + * + * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf + * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_AES_C) + +#include + +#include "mbedtls/aes.h" +#include "mbedtls/platform_util.h" +#if defined(MBEDTLS_PADLOCK_C) +#include "mbedtls/padlock.h" +#endif +#if defined(MBEDTLS_AESNI_C) +#include "mbedtls/aesni.h" +#endif + +#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 */ + +#if !defined(MBEDTLS_AES_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +#if defined(MBEDTLS_PADLOCK_C) && \ + ( defined(MBEDTLS_HAVE_X86) || defined(MBEDTLS_PADLOCK_ALIGN16) ) +static int aes_padlock_ace = -1; +#endif + +#if defined(MBEDTLS_AES_ROM_TABLES) +/* + * Forward S-box + */ +static const unsigned char FSb[256] = +{ + 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, + 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, + 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, + 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, + 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, + 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, + 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, + 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, + 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, + 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, + 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, + 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, + 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, + 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, + 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, + 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, + 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, + 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, + 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, + 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, + 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, + 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, + 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, + 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, + 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, + 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, + 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, + 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, + 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, + 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, + 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, + 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 +}; + +/* + * Forward tables + */ +#define FT \ +\ + V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ + V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ + V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ + V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ + V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ + V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ + V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ + V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ + V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ + V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ + V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ + V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ + V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ + V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ + V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ + V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ + V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ + V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ + V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ + V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ + V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ + V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ + V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ + V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ + V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ + V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ + V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ + V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ + V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ + V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ + V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ + V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ + V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ + V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ + V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ + V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ + V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ + V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ + V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ + V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ + V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ + V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ + V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ + V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ + V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ + V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ + V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ + V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ + V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ + V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ + V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ + V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ + V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ + V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ + V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ + V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ + V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ + V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ + V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ + V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ + V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ + V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ + V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ + V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t FT0[256] = { FT }; +#undef V + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t FT1[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t FT2[256] = { FT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t FT3[256] = { FT }; +#undef V + +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +#undef FT + +/* + * Reverse S-box + */ +static const unsigned char RSb[256] = +{ + 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, + 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, + 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, + 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, + 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, + 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, + 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, + 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, + 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, + 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, + 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, + 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, + 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, + 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, + 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, + 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, + 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, + 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, + 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, + 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, + 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, + 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, + 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, + 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, + 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, + 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, + 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, + 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, + 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, + 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, + 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, + 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D +}; + +/* + * Reverse tables + */ +#define RT \ +\ + V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ + V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ + V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ + V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ + V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ + V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ + V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ + V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ + V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ + V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ + V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ + V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ + V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ + V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ + V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ + V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ + V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ + V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ + V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ + V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ + V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ + V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ + V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ + V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ + V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ + V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ + V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ + V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ + V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ + V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ + V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ + V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ + V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ + V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ + V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ + V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ + V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ + V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ + V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ + V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ + V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ + V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ + V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ + V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ + V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ + V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ + V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ + V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ + V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ + V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ + V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ + V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ + V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ + V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ + V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ + V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ + V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ + V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ + V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ + V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ + V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ + V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ + V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ + V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) + +#define V(a,b,c,d) 0x##a##b##c##d +static const uint32_t RT0[256] = { RT }; +#undef V + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + +#define V(a,b,c,d) 0x##b##c##d##a +static const uint32_t RT1[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##c##d##a##b +static const uint32_t RT2[256] = { RT }; +#undef V + +#define V(a,b,c,d) 0x##d##a##b##c +static const uint32_t RT3[256] = { RT }; +#undef V + +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +#undef RT + +/* + * Round constants + */ +static const uint32_t RCON[10] = +{ + 0x00000001, 0x00000002, 0x00000004, 0x00000008, + 0x00000010, 0x00000020, 0x00000040, 0x00000080, + 0x0000001B, 0x00000036 +}; + +#else /* MBEDTLS_AES_ROM_TABLES */ + +/* + * Forward S-box & tables + */ +static unsigned char FSb[256]; +static uint32_t FT0[256]; +#if !defined(MBEDTLS_AES_FEWER_TABLES) +static uint32_t FT1[256]; +static uint32_t FT2[256]; +static uint32_t FT3[256]; +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +/* + * Reverse S-box & tables + */ +static unsigned char RSb[256]; +static uint32_t RT0[256]; +#if !defined(MBEDTLS_AES_FEWER_TABLES) +static uint32_t RT1[256]; +static uint32_t RT2[256]; +static uint32_t RT3[256]; +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + +/* + * Round constants + */ +static uint32_t RCON[10]; + +/* + * Tables generation code + */ +#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) +#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) +#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) + +static int aes_init_done = 0; + +static void aes_gen_tables( void ) +{ + int i, x, y, z; + int pow[256]; + int log[256]; + + /* + * compute pow and log tables over GF(2^8) + */ + for( i = 0, x = 1; i < 256; i++ ) + { + pow[i] = x; + log[x] = i; + x = ( x ^ XTIME( x ) ) & 0xFF; + } + + /* + * calculate the round constants + */ + for( i = 0, x = 1; i < 10; i++ ) + { + RCON[i] = (uint32_t) x; + x = XTIME( x ) & 0xFF; + } + + /* + * generate the forward and reverse S-boxes + */ + FSb[0x00] = 0x63; + RSb[0x63] = 0x00; + + for( i = 1; i < 256; i++ ) + { + x = pow[255 - log[i]]; + + y = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; + x ^= y ^ 0x63; + + FSb[i] = (unsigned char) x; + RSb[x] = (unsigned char) i; + } + + /* + * generate the forward and reverse tables + */ + for( i = 0; i < 256; i++ ) + { + x = FSb[i]; + y = XTIME( x ) & 0xFF; + z = ( y ^ x ) & 0xFF; + + FT0[i] = ( (uint32_t) y ) ^ + ( (uint32_t) x << 8 ) ^ + ( (uint32_t) x << 16 ) ^ + ( (uint32_t) z << 24 ); + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + FT1[i] = ROTL8( FT0[i] ); + FT2[i] = ROTL8( FT1[i] ); + FT3[i] = ROTL8( FT2[i] ); +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + + x = RSb[i]; + + RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^ + ( (uint32_t) MUL( 0x09, x ) << 8 ) ^ + ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ + ( (uint32_t) MUL( 0x0B, x ) << 24 ); + +#if !defined(MBEDTLS_AES_FEWER_TABLES) + RT1[i] = ROTL8( RT0[i] ); + RT2[i] = ROTL8( RT1[i] ); + RT3[i] = ROTL8( RT2[i] ); +#endif /* !MBEDTLS_AES_FEWER_TABLES */ + } +} + +#undef ROTL8 + +#endif /* MBEDTLS_AES_ROM_TABLES */ + +#if defined(MBEDTLS_AES_FEWER_TABLES) + +#define ROTL8(x) ( (uint32_t)( ( x ) << 8 ) + (uint32_t)( ( x ) >> 24 ) ) +#define ROTL16(x) ( (uint32_t)( ( x ) << 16 ) + (uint32_t)( ( x ) >> 16 ) ) +#define ROTL24(x) ( (uint32_t)( ( x ) << 24 ) + (uint32_t)( ( x ) >> 8 ) ) + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) ROTL8( RT0[idx] ) +#define AES_RT2(idx) ROTL16( RT0[idx] ) +#define AES_RT3(idx) ROTL24( RT0[idx] ) + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) ROTL8( FT0[idx] ) +#define AES_FT2(idx) ROTL16( FT0[idx] ) +#define AES_FT3(idx) ROTL24( FT0[idx] ) + +#else /* MBEDTLS_AES_FEWER_TABLES */ + +#define AES_RT0(idx) RT0[idx] +#define AES_RT1(idx) RT1[idx] +#define AES_RT2(idx) RT2[idx] +#define AES_RT3(idx) RT3[idx] + +#define AES_FT0(idx) FT0[idx] +#define AES_FT1(idx) FT1[idx] +#define AES_FT2(idx) FT2[idx] +#define AES_FT3(idx) FT3[idx] + +#endif /* MBEDTLS_AES_FEWER_TABLES */ + +void mbedtls_aes_init( mbedtls_aes_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_aes_context ) ); +} + +void mbedtls_aes_free( mbedtls_aes_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_aes_context ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ) +{ + mbedtls_aes_init( &ctx->crypt ); + mbedtls_aes_init( &ctx->tweak ); +} + +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ) +{ + mbedtls_aes_free( &ctx->crypt ); + mbedtls_aes_free( &ctx->tweak ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/* + * AES key schedule (encryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_ENC_ALT) +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + unsigned int i; + uint32_t *RK; + +#if !defined(MBEDTLS_AES_ROM_TABLES) + if( aes_init_done == 0 ) + { + aes_gen_tables(); + aes_init_done = 1; + + } +#endif + + switch( keybits ) + { + case 128: ctx->nr = 10; break; + case 192: ctx->nr = 12; break; + case 256: ctx->nr = 14; break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_aesni_setkey_enc( (unsigned char *) ctx->rk, key, keybits ) ); +#endif + + for( i = 0; i < ( keybits >> 5 ); i++ ) + { + GET_UINT32_LE( RK[i], key, i << 2 ); + } + + switch( ctx->nr ) + { + case 10: + + for( i = 0; i < 10; i++, RK += 4 ) + { + RK[4] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 ); + + RK[5] = RK[1] ^ RK[4]; + RK[6] = RK[2] ^ RK[5]; + RK[7] = RK[3] ^ RK[6]; + } + break; + + case 12: + + for( i = 0; i < 8; i++, RK += 6 ) + { + RK[6] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 ); + + RK[7] = RK[1] ^ RK[6]; + RK[8] = RK[2] ^ RK[7]; + RK[9] = RK[3] ^ RK[8]; + RK[10] = RK[4] ^ RK[9]; + RK[11] = RK[5] ^ RK[10]; + } + break; + + case 14: + + for( i = 0; i < 7; i++, RK += 8 ) + { + RK[8] = RK[0] ^ RCON[i] ^ + ( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 ); + + RK[9] = RK[1] ^ RK[8]; + RK[10] = RK[2] ^ RK[9]; + RK[11] = RK[3] ^ RK[10]; + + RK[12] = RK[4] ^ + ( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); + + RK[13] = RK[5] ^ RK[12]; + RK[14] = RK[6] ^ RK[13]; + RK[15] = RK[7] ^ RK[14]; + } + break; + } + + return( 0 ); +} +#endif /* !MBEDTLS_AES_SETKEY_ENC_ALT */ + +/* + * AES key schedule (decryption) + */ +#if !defined(MBEDTLS_AES_SETKEY_DEC_ALT) +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int i, j, ret; + mbedtls_aes_context cty; + uint32_t *RK; + uint32_t *SK; + + mbedtls_aes_init( &cty ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_PADLOCK_ALIGN16) + if( aes_padlock_ace == -1 ) + aes_padlock_ace = mbedtls_padlock_has_support( MBEDTLS_PADLOCK_ACE ); + + if( aes_padlock_ace ) + ctx->rk = RK = MBEDTLS_PADLOCK_ALIGN16( ctx->buf ); + else +#endif + ctx->rk = RK = ctx->buf; + + /* Also checks keybits */ + if( ( ret = mbedtls_aes_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + { + mbedtls_aesni_inverse_key( (unsigned char *) ctx->rk, + (const unsigned char *) cty.rk, ctx->nr ); + goto exit; + } +#endif + + SK = cty.rk + cty.nr * 4; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) + { + for( j = 0; j < 4; j++, SK++ ) + { + *RK++ = AES_RT0( FSb[ ( *SK ) & 0xFF ] ) ^ + AES_RT1( FSb[ ( *SK >> 8 ) & 0xFF ] ) ^ + AES_RT2( FSb[ ( *SK >> 16 ) & 0xFF ] ) ^ + AES_RT3( FSb[ ( *SK >> 24 ) & 0xFF ] ); + } + } + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + mbedtls_aes_free( &cty ); + + return( ret ); +} + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int mbedtls_aes_xts_decode_keys( const unsigned char *key, + unsigned int keybits, + const unsigned char **key1, + unsigned int *key1bits, + const unsigned char **key2, + unsigned int *key2bits ) +{ + const unsigned int half_keybits = keybits / 2; + const unsigned int half_keybytes = half_keybits / 8; + + switch( keybits ) + { + case 256: break; + case 512: break; + default : return( MBEDTLS_ERR_AES_INVALID_KEY_LENGTH ); + } + + *key1bits = half_keybits; + *key2bits = half_keybits; + *key1 = &key[0]; + *key2 = &key[half_keybytes]; + + return 0; +} + +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for the encryption mode. */ + ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for encryption. */ + return mbedtls_aes_setkey_enc( &ctx->crypt, key1, key1bits ); +} + +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits) +{ + int ret; + const unsigned char *key1, *key2; + unsigned int key1bits, key2bits; + + ret = mbedtls_aes_xts_decode_keys( key, keybits, &key1, &key1bits, + &key2, &key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set the tweak key. Always set tweak key for encryption. */ + ret = mbedtls_aes_setkey_enc( &ctx->tweak, key2, key2bits ); + if( ret != 0 ) + return( ret ); + + /* Set crypt key for decryption. */ + return mbedtls_aes_setkey_dec( &ctx->crypt, key1, key1bits ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#endif /* !MBEDTLS_AES_SETKEY_DEC_ALT */ + +#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ AES_FT0( ( Y0 ) & 0xFF ) ^ \ + AES_FT1( ( Y1 >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( Y2 >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( Y3 >> 24 ) & 0xFF ); \ + \ + X1 = *RK++ ^ AES_FT0( ( Y1 ) & 0xFF ) ^ \ + AES_FT1( ( Y2 >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( Y3 >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( Y0 >> 24 ) & 0xFF ); \ + \ + X2 = *RK++ ^ AES_FT0( ( Y2 ) & 0xFF ) ^ \ + AES_FT1( ( Y3 >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( Y0 >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( Y1 >> 24 ) & 0xFF ); \ + \ + X3 = *RK++ ^ AES_FT0( ( Y3 ) & 0xFF ) ^ \ + AES_FT1( ( Y0 >> 8 ) & 0xFF ) ^ \ + AES_FT2( ( Y1 >> 16 ) & 0xFF ) ^ \ + AES_FT3( ( Y2 >> 24 ) & 0xFF ); \ +} + +#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ +{ \ + X0 = *RK++ ^ AES_RT0( ( Y0 ) & 0xFF ) ^ \ + AES_RT1( ( Y3 >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( Y2 >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( Y1 >> 24 ) & 0xFF ); \ + \ + X1 = *RK++ ^ AES_RT0( ( Y1 ) & 0xFF ) ^ \ + AES_RT1( ( Y0 >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( Y3 >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( Y2 >> 24 ) & 0xFF ); \ + \ + X2 = *RK++ ^ AES_RT0( ( Y2 ) & 0xFF ) ^ \ + AES_RT1( ( Y1 >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( Y0 >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( Y3 >> 24 ) & 0xFF ); \ + \ + X3 = *RK++ ^ AES_RT0( ( Y3 ) & 0xFF ) ^ \ + AES_RT1( ( Y2 >> 8 ) & 0xFF ) ^ \ + AES_RT2( ( Y1 >> 16 ) & 0xFF ) ^ \ + AES_RT3( ( Y0 >> 24 ) & 0xFF ); \ +} + +/* + * AES-ECB block encryption + */ +#if !defined(MBEDTLS_AES_ENCRYPT_ALT) +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + + RK = ctx->rk; + + GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; + GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; + GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; + GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); + } + + AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + X0 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + + X1 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + + X2 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + + X3 = *RK++ ^ \ + ( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^ + ( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + + PUT_UINT32_LE( X0, output, 0 ); + PUT_UINT32_LE( X1, output, 4 ); + PUT_UINT32_LE( X2, output, 8 ); + PUT_UINT32_LE( X3, output, 12 ); + + return( 0 ); +} +#endif /* !MBEDTLS_AES_ENCRYPT_ALT */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + mbedtls_internal_aes_encrypt( ctx, input, output ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/* + * AES-ECB block decryption + */ +#if !defined(MBEDTLS_AES_DECRYPT_ALT) +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + int i; + uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; + + RK = ctx->rk; + + GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; + GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; + GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; + GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; + + for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) + { + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); + } + + AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); + + X0 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); + + X1 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); + + X2 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); + + X3 = *RK++ ^ \ + ( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^ + ( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ + ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ + ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); + + PUT_UINT32_LE( X0, output, 0 ); + PUT_UINT32_LE( X1, output, 4 ); + PUT_UINT32_LE( X2, output, 8 ); + PUT_UINT32_LE( X3, output, 12 ); + + return( 0 ); +} +#endif /* !MBEDTLS_AES_DECRYPT_ALT */ + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ) +{ + mbedtls_internal_aes_decrypt( ctx, input, output ); +} +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/* + * AES-ECB block encryption/decryption + */ +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ +#if defined(MBEDTLS_AESNI_C) && defined(MBEDTLS_HAVE_X86_64) + if( mbedtls_aesni_has_support( MBEDTLS_AESNI_AES ) ) + return( mbedtls_aesni_crypt_ecb( ctx, mode, input, output ) ); +#endif + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if( aes_padlock_ace ) + { + if( mbedtls_padlock_xcryptecb( ctx, mode, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == MBEDTLS_AES_ENCRYPT ) + return( mbedtls_internal_aes_encrypt( ctx, input, output ) ); + else + return( mbedtls_internal_aes_decrypt( ctx, input, output ) ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * AES-CBC buffer encryption/decryption + */ +int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + + if( length % 16 ) + return( MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH ); + +#if defined(MBEDTLS_PADLOCK_C) && defined(MBEDTLS_HAVE_X86) + if( aes_padlock_ace ) + { + if( mbedtls_padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) + return( 0 ); + + // If padlock data misaligned, we just fall back to + // unaccelerated mode + // + } +#endif + + if( mode == MBEDTLS_AES_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + mbedtls_aes_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_aes_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + +/* Endianess with 64 bits values */ +#ifndef GET_UINT64_LE +#define GET_UINT64_LE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) + 7] << 56 ) \ + | ( (uint64_t) (b)[(i) + 6] << 48 ) \ + | ( (uint64_t) (b)[(i) + 5] << 40 ) \ + | ( (uint64_t) (b)[(i) + 4] << 32 ) \ + | ( (uint64_t) (b)[(i) + 3] << 24 ) \ + | ( (uint64_t) (b)[(i) + 2] << 16 ) \ + | ( (uint64_t) (b)[(i) + 1] << 8 ) \ + | ( (uint64_t) (b)[(i) ] ); \ +} +#endif + +#ifndef PUT_UINT64_LE +#define PUT_UINT64_LE(n,b,i) \ +{ \ + (b)[(i) + 7] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) ] = (unsigned char) ( (n) ); \ +} +#endif + +typedef unsigned char mbedtls_be128[16]; + +/* + * GF(2^128) multiplication function + * + * This function multiplies a field element by x in the polynomial field + * representation. It uses 64-bit word operations to gain speed but compensates + * for machine endianess and hence works correctly on both big and little + * endian machines. + */ +static void mbedtls_gf128mul_x_ble( unsigned char r[16], + const unsigned char x[16] ) +{ + uint64_t a, b, ra, rb; + + GET_UINT64_LE( a, x, 0 ); + GET_UINT64_LE( b, x, 8 ); + + ra = ( a << 1 ) ^ 0x0087 >> ( 8 - ( ( b >> 63 ) << 3 ) ); + rb = ( a >> 63 ) | ( b << 1 ); + + PUT_UINT64_LE( ra, r, 0 ); + PUT_UINT64_LE( rb, r, 8 ); +} + +/* + * AES-XTS buffer encryption/decryption + */ +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t blocks = length / 16; + size_t leftover = length % 16; + unsigned char tweak[16]; + unsigned char prev_tweak[16]; + unsigned char tmp[16]; + + /* Sectors must be at least 16 bytes. */ + if( length < 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* NIST SP 80-38E disallows data units larger than 2**20 blocks. */ + if( length > ( 1 << 20 ) * 16 ) + return MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH; + + /* Compute the tweak. */ + ret = mbedtls_aes_crypt_ecb( &ctx->tweak, MBEDTLS_AES_ENCRYPT, + data_unit, tweak ); + if( ret != 0 ) + return( ret ); + + while( blocks-- ) + { + size_t i; + + if( leftover && ( mode == MBEDTLS_AES_DECRYPT ) && blocks == 0 ) + { + /* We are on the last block in a decrypt operation that has + * leftover bytes, so we need to use the next tweak for this block, + * and this tweak for the lefover bytes. Save the current tweak for + * the leftovers and then update the current tweak for use on this, + * the last full block. */ + memcpy( prev_tweak, tweak, sizeof( tweak ) ); + mbedtls_gf128mul_x_ble( tweak, tweak ); + } + + for( i = 0; i < 16; i++ ) + tmp[i] = input[i] ^ tweak[i]; + + ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return( ret ); + + for( i = 0; i < 16; i++ ) + output[i] = tmp[i] ^ tweak[i]; + + /* Update the tweak for the next block. */ + mbedtls_gf128mul_x_ble( tweak, tweak ); + + output += 16; + input += 16; + } + + if( leftover ) + { + /* If we are on the leftover bytes in a decrypt operation, we need to + * use the previous tweak for these bytes (as saved in prev_tweak). */ + unsigned char *t = mode == MBEDTLS_AES_DECRYPT ? prev_tweak : tweak; + + /* We are now on the final part of the data unit, which doesn't divide + * evenly by 16. It's time for ciphertext stealing. */ + size_t i; + unsigned char *prev_output = output - 16; + + /* Copy ciphertext bytes from the previous block to our output for each + * byte of cyphertext we won't steal. At the same time, copy the + * remainder of the input for this final round (since the loop bounds + * are the same). */ + for( i = 0; i < leftover; i++ ) + { + output[i] = prev_output[i]; + tmp[i] = input[i] ^ t[i]; + } + + /* Copy ciphertext bytes from the previous block for input in this + * round. */ + for( ; i < 16; i++ ) + tmp[i] = prev_output[i] ^ t[i]; + + ret = mbedtls_aes_crypt_ecb( &ctx->crypt, mode, tmp, tmp ); + if( ret != 0 ) + return ret; + + /* Write the result back to the previous block, overriding the previous + * output we copied. */ + for( i = 0; i < 16; i++ ) + prev_output[i] = tmp[i] ^ t[i]; + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 buffer encryption/decryption + */ +int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n = *iv_off; + + if( mode == MBEDTLS_AES_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} + +/* + * AES-CFB8 buffer encryption/decryption + */ +int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + unsigned char c; + unsigned char ov[17]; + + while( length-- ) + { + memcpy( ov, iv, 16 ); + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + + if( mode == MBEDTLS_AES_DECRYPT ) + ov[16] = *input; + + c = *output++ = (unsigned char)( iv[0] ^ *input++ ); + + if( mode == MBEDTLS_AES_ENCRYPT ) + ov[16] = c; + + memcpy( iv, ov + 1, 16 ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB (Output Feedback Mode) buffer encryption/decryption + */ +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int ret = 0; + size_t n = *iv_off; + + while( length-- ) + { + if( n == 0 ) + { + ret = mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, iv, iv ); + if( ret != 0 ) + goto exit; + } + *output++ = *input++ ^ iv[n]; + + n = ( n + 1 ) & 0x0F; + } + + *iv_off = n; + +exit: + return( ret ); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR buffer encryption/decryption + */ +int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + if ( n > 0x0F ) + return( MBEDTLS_ERR_AES_BAD_INPUT_DATA ); + + while( length-- ) + { + if( n == 0 ) { + mbedtls_aes_crypt_ecb( ctx, MBEDTLS_AES_ENCRYPT, nonce_counter, stream_block ); + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#endif /* !MBEDTLS_AES_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * AES test vectors from: + * + * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip + */ +static const unsigned char aes_test_ecb_dec[3][16] = +{ + { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, + 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, + { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, + 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, + { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, + 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } +}; + +static const unsigned char aes_test_ecb_enc[3][16] = +{ + { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, + 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, + { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, + 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, + { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, + 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const unsigned char aes_test_cbc_dec[3][16] = +{ + { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, + 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, + { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, + 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, + { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, + 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } +}; + +static const unsigned char aes_test_cbc_enc[3][16] = +{ + { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, + 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, + { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, + 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, + { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, + 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * AES-CFB128 test vectors from: + * + * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf + */ +static const unsigned char aes_test_cfb128_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_cfb128_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_cfb128_pt[64] = +{ + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, + 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 +}; + +static const unsigned char aes_test_cfb128_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, + 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, + 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, + 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, + 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, + 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, + 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, + 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, + 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, + 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, + 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, + 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, + 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, + 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, + 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, + 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/* + * AES-OFB test vectors from: + * + * https://csrc.nist.gov/publications/detail/sp/800-38a/final + */ +static const unsigned char aes_test_ofb_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char aes_test_ofb_iv[16] = +{ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F +}; + +static const unsigned char aes_test_ofb_pt[64] = +{ + 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, + 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, + 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, + 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, + 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 +}; + +static const unsigned char aes_test_ofb_ct[3][64] = +{ + { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, + 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, + 0x77, 0x89, 0x50, 0x8d, 0x16, 0x91, 0x8f, 0x03, + 0xf5, 0x3c, 0x52, 0xda, 0xc5, 0x4e, 0xd8, 0x25, + 0x97, 0x40, 0x05, 0x1e, 0x9c, 0x5f, 0xec, 0xf6, + 0x43, 0x44, 0xf7, 0xa8, 0x22, 0x60, 0xed, 0xcc, + 0x30, 0x4c, 0x65, 0x28, 0xf6, 0x59, 0xc7, 0x78, + 0x66, 0xa5, 0x10, 0xd9, 0xc1, 0xd6, 0xae, 0x5e }, + { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, + 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, + 0xfc, 0xc2, 0x8b, 0x8d, 0x4c, 0x63, 0x83, 0x7c, + 0x09, 0xe8, 0x17, 0x00, 0xc1, 0x10, 0x04, 0x01, + 0x8d, 0x9a, 0x9a, 0xea, 0xc0, 0xf6, 0x59, 0x6f, + 0x55, 0x9c, 0x6d, 0x4d, 0xaf, 0x59, 0xa5, 0xf2, + 0x6d, 0x9f, 0x20, 0x08, 0x57, 0xca, 0x6c, 0x3e, + 0x9c, 0xac, 0x52, 0x4b, 0xd9, 0xac, 0xc9, 0x2a }, + { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, + 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, + 0x4f, 0xeb, 0xdc, 0x67, 0x40, 0xd2, 0x0b, 0x3a, + 0xc8, 0x8f, 0x6a, 0xd8, 0x2a, 0x4f, 0xb0, 0x8d, + 0x71, 0xab, 0x47, 0xa0, 0x86, 0xe8, 0x6e, 0xed, + 0xf3, 0x9d, 0x1c, 0x5b, 0xba, 0x97, 0xc4, 0x08, + 0x01, 0x26, 0x14, 0x1d, 0x67, 0xf3, 0x7b, 0xe8, + 0x53, 0x8f, 0x5a, 0x8b, 0xe7, 0x40, 0xe4, 0x84 } +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * AES-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc3686.html + */ + +static const unsigned char aes_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char aes_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char aes_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23 } +}; + +static const unsigned char aes_test_ctr_ct[3][48] = +{ + { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, + 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, + { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, + 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, + 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, + 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, + { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, + 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, + 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, + 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, + 0x25, 0xB2, 0x07, 0x2F } +}; + +static const int aes_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/* + * AES-XTS test vectors from: + * + * IEEE P1619/D16 Annex B + * https://web.archive.org/web/20150629024421/http://grouper.ieee.org/groups/1619/email/pdf00086.pdf + * (Archived from original at http://grouper.ieee.org/groups/1619/email/pdf00086.pdf) + */ +static const unsigned char aes_test_xts_key[][32] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, 0x11, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, + { 0xff, 0xfe, 0xfd, 0xfc, 0xfb, 0xfa, 0xf9, 0xf8, + 0xf7, 0xf6, 0xf5, 0xf4, 0xf3, 0xf2, 0xf1, 0xf0, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, + 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22, 0x22 }, +}; + +static const unsigned char aes_test_xts_pt32[][32] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, + { 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, + 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44, 0x44 }, +}; + +static const unsigned char aes_test_xts_ct32[][32] = +{ + { 0x91, 0x7c, 0xf6, 0x9e, 0xbd, 0x68, 0xb2, 0xec, + 0x9b, 0x9f, 0xe9, 0xa3, 0xea, 0xdd, 0xa6, 0x92, + 0xcd, 0x43, 0xd2, 0xf5, 0x95, 0x98, 0xed, 0x85, + 0x8c, 0x02, 0xc2, 0x65, 0x2f, 0xbf, 0x92, 0x2e }, + { 0xc4, 0x54, 0x18, 0x5e, 0x6a, 0x16, 0x93, 0x6e, + 0x39, 0x33, 0x40, 0x38, 0xac, 0xef, 0x83, 0x8b, + 0xfb, 0x18, 0x6f, 0xff, 0x74, 0x80, 0xad, 0xc4, + 0x28, 0x93, 0x82, 0xec, 0xd6, 0xd3, 0x94, 0xf0 }, + { 0xaf, 0x85, 0x33, 0x6b, 0x59, 0x7a, 0xfc, 0x1a, + 0x90, 0x0b, 0x2e, 0xb2, 0x1e, 0xc9, 0x49, 0xd2, + 0x92, 0xdf, 0x4c, 0x04, 0x7e, 0x0b, 0x21, 0x53, + 0x21, 0x86, 0xa5, 0x97, 0x1a, 0x22, 0x7a, 0x89 }, +}; + +static const unsigned char aes_test_xts_data_unit[][16] = +{ + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x33, 0x33, 0x33, 0x33, 0x33, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, +}; + +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/* + * Checkup routine + */ +int mbedtls_aes_self_test( int verbose ) +{ + int ret = 0, i, j, u, mode; + unsigned int keybits; + unsigned char key[32]; + unsigned char buf[64]; + const unsigned char *aes_tests; +#if defined(MBEDTLS_CIPHER_MODE_CBC) || defined(MBEDTLS_CIPHER_MODE_CFB) + unsigned char iv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char prv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_CFB) || \ + defined(MBEDTLS_CIPHER_MODE_OFB) + size_t offset; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) || defined(MBEDTLS_CIPHER_MODE_XTS) + int len; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + mbedtls_aes_context ctx; + + memset( key, 0, 32 ); + mbedtls_aes_init( &ctx ); + + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-ECB-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( buf, 0, 16 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); + aes_tests = aes_test_ecb_dec[u]; + } + else + { + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + aes_tests = aes_test_ecb_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + for( j = 0; j < 10000; j++ ) + { + ret = mbedtls_aes_crypt_ecb( &ctx, mode, buf, buf ); + if( ret != 0 ) + goto exit; + } + + if( memcmp( buf, aes_tests, 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CBC-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( iv , 0, 16 ); + memset( prv, 0, 16 ); + memset( buf, 0, 16 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_setkey_dec( &ctx, key, keybits ); + aes_tests = aes_test_cbc_dec[u]; + } + else + { + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + aes_tests = aes_test_cbc_enc[u]; + } + + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + for( j = 0; j < 10000; j++ ) + { + if( mode == MBEDTLS_AES_ENCRYPT ) + { + unsigned char tmp[16]; + + memcpy( tmp, prv, 16 ); + memcpy( prv, buf, 16 ); + memcpy( buf, tmp, 16 ); + } + + ret = mbedtls_aes_crypt_cbc( &ctx, mode, 16, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + } + + if( memcmp( buf, aes_tests, 16 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /* + * CFB128 mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CFB128-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_cfb128_iv, 16 ); + memcpy( key, aes_test_cfb128_key[u], keybits / 8 ); + + offset = 0; + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_cfb128_ct[u], 64 ); + aes_tests = aes_test_cfb128_pt; + } + else + { + memcpy( buf, aes_test_cfb128_pt, 64 ); + aes_tests = aes_test_cfb128_ct[u]; + } + + ret = mbedtls_aes_crypt_cfb128( &ctx, mode, 64, &offset, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, 64 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /* + * OFB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + keybits = 128 + u * 64; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-OFB-%3d (%s): ", keybits, + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, aes_test_ofb_iv, 16 ); + memcpy( key, aes_test_ofb_key[u], keybits / 8 ); + + offset = 0; + ret = mbedtls_aes_setkey_enc( &ctx, key, keybits ); + /* + * AES-192 is an optional feature that may be unavailable when + * there is an alternative underlying implementation i.e. when + * MBEDTLS_AES_ALT is defined. + */ + if( ret == MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE && keybits == 192 ) + { + mbedtls_printf( "skipped\n" ); + continue; + } + else if( ret != 0 ) + { + goto exit; + } + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_ofb_ct[u], 64 ); + aes_tests = aes_test_ofb_pt; + } + else + { + memcpy( buf, aes_test_ofb_pt, 64 ); + aes_tests = aes_test_ofb_ct[u]; + } + + ret = mbedtls_aes_crypt_ofb( &ctx, 64, &offset, iv, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, 64 ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-CTR-128 (%s): ", + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); + memcpy( key, aes_test_ctr_key[u], 16 ); + + offset = 0; + if( ( ret = mbedtls_aes_setkey_enc( &ctx, key, 128 ) ) != 0 ) + goto exit; + + len = aes_test_ctr_len[u]; + + if( mode == MBEDTLS_AES_DECRYPT ) + { + memcpy( buf, aes_test_ctr_ct[u], len ); + aes_tests = aes_test_ctr_pt[u]; + } + else + { + memcpy( buf, aes_test_ctr_pt[u], len ); + aes_tests = aes_test_ctr_ct[u]; + } + + ret = mbedtls_aes_crypt_ctr( &ctx, len, &offset, nonce_counter, + stream_block, buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, len ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { + static const int num_tests = + sizeof(aes_test_xts_key) / sizeof(*aes_test_xts_key); + mbedtls_aes_xts_context ctx_xts; + + /* + * XTS mode + */ + mbedtls_aes_xts_init( &ctx_xts ); + + for( i = 0; i < num_tests << 1; i++ ) + { + const unsigned char *data_unit; + u = i >> 1; + mode = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " AES-XTS-128 (%s): ", + ( mode == MBEDTLS_AES_DECRYPT ) ? "dec" : "enc" ); + + memset( key, 0, sizeof( key ) ); + memcpy( key, aes_test_xts_key[u], 32 ); + data_unit = aes_test_xts_data_unit[u]; + + len = sizeof( *aes_test_xts_ct32 ); + + if( mode == MBEDTLS_AES_DECRYPT ) + { + ret = mbedtls_aes_xts_setkey_dec( &ctx_xts, key, 256 ); + if( ret != 0) + goto exit; + memcpy( buf, aes_test_xts_ct32[u], len ); + aes_tests = aes_test_xts_pt32[u]; + } + else + { + ret = mbedtls_aes_xts_setkey_enc( &ctx_xts, key, 256 ); + if( ret != 0) + goto exit; + memcpy( buf, aes_test_xts_pt32[u], len ); + aes_tests = aes_test_xts_ct32[u]; + } + + + ret = mbedtls_aes_crypt_xts( &ctx_xts, mode, len, data_unit, + buf, buf ); + if( ret != 0 ) + goto exit; + + if( memcmp( buf, aes_tests, len ) != 0 ) + { + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + mbedtls_aes_xts_free( &ctx_xts ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + + ret = 0; + +exit: + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "failed\n" ); + + mbedtls_aes_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_AES_C */ diff --git a/common/mbedtls/aes.h b/common/mbedtls/aes.h new file mode 100644 index 000000000..9af6bb729 --- /dev/null +++ b/common/mbedtls/aes.h @@ -0,0 +1,628 @@ +/** + * \file aes.h + * + * \brief This file contains AES definitions and functions. + * + * The Advanced Encryption Standard (AES) specifies a FIPS-approved + * cryptographic algorithm that can be used to protect electronic + * data. + * + * The AES algorithm is a symmetric block cipher that can + * encrypt and decrypt information. For more information, see + * FIPS Publication 197: Advanced Encryption Standard and + * ISO/IEC 18033-2:2006: Information technology -- Security + * techniques -- Encryption algorithms -- Part 2: Asymmetric + * ciphers. + * + * The AES-XTS block mode is standardized by NIST SP 800-38E + * + * and described in detail by IEEE P1619 + * . + */ + +/* Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved. + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_AES_H +#define MBEDTLS_AES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +/* padlock.c and aesni.c rely on these values! */ +#define MBEDTLS_AES_ENCRYPT 1 /**< AES encryption. */ +#define MBEDTLS_AES_DECRYPT 0 /**< AES decryption. */ + +/* Error codes in range 0x0020-0x0022 */ +#define MBEDTLS_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ +#define MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ + +/* Error codes in range 0x0021-0x0025 */ +#define MBEDTLS_ERR_AES_BAD_INPUT_DATA -0x0021 /**< Invalid input data. */ +#define MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE -0x0023 /**< Feature not available. For example, an unsupported AES key size. */ +#define MBEDTLS_ERR_AES_HW_ACCEL_FAILED -0x0025 /**< AES hardware accelerator failed. */ + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_AES_ALT) +// Regular implementation +// + +/** + * \brief The AES context-type definition. + */ +typedef struct mbedtls_aes_context +{ + int nr; /*!< The number of rounds. */ + uint32_t *rk; /*!< AES round keys. */ + uint32_t buf[68]; /*!< Unaligned data buffer. This buffer can + hold 32 extra Bytes, which can be used for + one of the following purposes: +
  • Alignment if VIA padlock is + used.
  • +
  • Simplifying key expansion in the 256-bit + case by generating an extra round key. +
*/ +} +mbedtls_aes_context; + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief The AES XTS context-type definition. + */ +typedef struct mbedtls_aes_xts_context +{ + mbedtls_aes_context crypt; /*!< The AES context to use for AES block + encryption or decryption. */ + mbedtls_aes_context tweak; /*!< The AES context used for tweak + computation. */ +} mbedtls_aes_xts_context; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#else /* MBEDTLS_AES_ALT */ +#include "aes_alt.h" +#endif /* MBEDTLS_AES_ALT */ + +/** + * \brief This function initializes the specified AES context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES context to initialize. + */ +void mbedtls_aes_init( mbedtls_aes_context *ctx ); + +/** + * \brief This function releases and clears the specified AES context. + * + * \param ctx The AES context to clear. + */ +void mbedtls_aes_free( mbedtls_aes_context *ctx ); + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function initializes the specified AES XTS context. + * + * It must be the first API called before using + * the context. + * + * \param ctx The AES XTS context to initialize. + */ +void mbedtls_aes_xts_init( mbedtls_aes_xts_context *ctx ); + +/** + * \brief This function releases and clears the specified AES XTS context. + * + * \param ctx The AES XTS context to clear. + */ +void mbedtls_aes_xts_free( mbedtls_aes_xts_context *ctx ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * \brief This function sets the encryption key. + * + * \param ctx The AES context to which the key should be bound. + * \param key The encryption key. + * \param keybits The size of data passed in bits. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_setkey_enc( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function sets the decryption key. + * + * \param ctx The AES context to which the key should be bound. + * \param key The decryption key. + * \param keybits The size of data passed. Valid options are: + *
  • 128 bits
  • + *
  • 192 bits
  • + *
  • 256 bits
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_setkey_dec( mbedtls_aes_context *ctx, const unsigned char *key, + unsigned int keybits ); + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function prepares an XTS context for encryption and + * sets the encryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * \param key The encryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_xts_setkey_enc( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); + +/** + * \brief This function prepares an XTS context for decryption and + * sets the decryption key. + * + * \param ctx The AES XTS context to which the key should be bound. + * \param key The decryption key. This is comprised of the XTS key1 + * concatenated with the XTS key2. + * \param keybits The size of \p key passed in bits. Valid options are: + *
  • 256 bits (each of key1 and key2 is a 128-bit key)
  • + *
  • 512 bits (each of key1 and key2 is a 256-bit key)
+ * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_KEY_LENGTH on failure. + */ +int mbedtls_aes_xts_setkey_dec( mbedtls_aes_xts_context *ctx, + const unsigned char *key, + unsigned int keybits ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +/** + * \brief This function performs an AES single-block encryption or + * decryption operation. + * + * It performs the operation defined in the \p mode parameter + * (encrypt or decrypt), on the input data buffer defined in + * the \p input parameter. + * + * mbedtls_aes_init(), and either mbedtls_aes_setkey_enc() or + * mbedtls_aes_setkey_dec() must be called before the first + * call to this API with the same context. + * + * \param ctx The AES context to use for encryption or decryption. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param input The 16-Byte buffer holding the input data. + * \param output The 16-Byte buffer holding the output data. + + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ecb( mbedtls_aes_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief This function performs an AES-CBC encryption or decryption operation + * on full blocks. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined in + * the \p input parameter. + * + * It can be called as many times as needed, until all the input + * data is processed. mbedtls_aes_init(), and either + * mbedtls_aes_setkey_enc() or mbedtls_aes_setkey_dec() must be called + * before the first call to this API with the same context. + * + * \note This function operates on aligned blocks, that is, the input size + * must be a multiple of the AES block size of 16 Bytes. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the IV, you should + * either save it manually or use the cipher module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data in Bytes. This must be a + * multiple of the block size (16 Bytes). + * \param iv Initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH + * on failure. + */ +int mbedtls_aes_crypt_cbc( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +/** + * \brief This function performs an AES-XTS encryption or decryption + * operation for an entire XTS data unit. + * + * AES-XTS encrypts or decrypts blocks based on their location as + * defined by a data unit number. The data unit number must be + * provided by \p data_unit. + * + * NIST SP 800-38E limits the maximum size of a data unit to 2^20 + * AES blocks. If the data unit is larger than this, this function + * returns #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH. + * + * \param ctx The AES XTS context to use for AES XTS operations. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of a data unit in bytes. This can be any + * length between 16 bytes and 2^24 bytes inclusive + * (between 1 and 2^20 block cipher blocks). + * \param data_unit The address of the data unit encoded as an array of 16 + * bytes in little-endian format. For disk encryption, this + * is typically the index of the block device sector that + * contains the data. + * \param input The buffer holding the input data (which is an entire + * data unit). This function reads \p length bytes from \p + * input. + * \param output The buffer holding the output data (which is an entire + * data unit). This function writes \p length bytes to \p + * output. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH if \p length is + * smaller than an AES block in size (16 bytes) or if \p + * length is larger than 2^20 blocks (16 MiB). + */ +int mbedtls_aes_crypt_xts( mbedtls_aes_xts_context *ctx, + int mode, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief This function performs an AES-CFB128 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt or decrypt), on the input data buffer + * defined in the \p input parameter. + * + * For CFB, you must set up the context with mbedtls_aes_setkey_enc(), + * regardless of whether you are performing an encryption or decryption + * operation, that is, regardless of the \p mode parameter. This is + * because CFB mode uses the same key schedule for encryption and + * decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you must either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * \param iv The initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_cfb128( mbedtls_aes_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an AES-CFB8 encryption or decryption + * operation. + * + * It performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer defined + * in the \p input parameter. + * + * Due to the nature of CFB, you must use the same key schedule for + * both encryption and decryption operations. Therefore, you must + * use the context initialized with mbedtls_aes_setkey_enc() for + * both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the same function again on the next + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * + * \param ctx The AES context to use for encryption or decryption. + * \param mode The AES operation: #MBEDTLS_AES_ENCRYPT or + * #MBEDTLS_AES_DECRYPT + * \param length The length of the input data. + * \param iv The initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_cfb8( mbedtls_aes_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +/** + * \brief This function performs an AES-OFB (Output Feedback Mode) + * encryption or decryption operation. + * + * For OFB, you must set up the context with + * mbedtls_aes_setkey_enc(), regardless of whether you are + * performing an encryption or decryption operation. This is + * because OFB mode uses the same key schedule for encryption and + * decryption. + * + * The OFB operation is identical for encryption or decryption, + * therefore no operation mode needs to be specified. + * + * \note Upon exit, the content of iv, the Initialisation Vector, is + * updated so that you can call the same function again on the next + * block(s) of data and get the same result as if it was encrypted + * in one call. This allows a "streaming" usage, by initialising + * iv_off to 0 before the first call, and preserving its value + * between calls. + * + * For non-streaming use, the iv should be initialised on each call + * to a unique value, and iv_off set to 0 on each call. + * + * If you need to retain the contents of the initialisation vector, + * you must either save it manually or use the cipher module + * instead. + * + * \warning For the OFB mode, the initialisation vector must be unique + * every encryption operation. Reuse of an initialisation vector + * will compromise security. + * + * \param ctx The AES context to use for encryption or decryption. + * \param length The length of the input data. + * \param iv_off The offset in IV (updated after use). + * \param iv The initialization vector (updated after use). + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ofb( mbedtls_aes_context *ctx, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); + +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief This function performs an AES-CTR encryption or decryption + * operation. + * + * This function performs the operation defined in the \p mode + * parameter (encrypt/decrypt), on the input data buffer + * defined in the \p input parameter. + * + * Due to the nature of CTR, you must use the same key schedule + * for both encryption and decryption operations. Therefore, you + * must use the context initialized with mbedtls_aes_setkey_enc() + * for both #MBEDTLS_AES_ENCRYPT and #MBEDTLS_AES_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that an AES block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx The AES context to use for encryption or decryption. + * \param length The length of the input data. + * \param nc_off The offset in the current \p stream_block, for + * resuming within the current cipher stream. The + * offset pointer should be 0 at the start of a stream. + * \param nonce_counter The 128-bit nonce and counter. + * \param stream_block The saved stream block for resuming. This is + * overwritten by the function. + * \param input The buffer holding the input data. + * \param output The buffer holding the output data. + * + * \return \c 0 on success. + */ +int mbedtls_aes_crypt_ctr( mbedtls_aes_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/** + * \brief Internal AES block encryption function. This is only + * exposed to allow overriding it using + * \c MBEDTLS_AES_ENCRYPT_ALT. + * + * \param ctx The AES context to use for encryption. + * \param input The plaintext block. + * \param output The output (ciphertext) block. + * + * \return \c 0 on success. + */ +int mbedtls_internal_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Internal AES block decryption function. This is only + * exposed to allow overriding it using see + * \c MBEDTLS_AES_DECRYPT_ALT. + * + * \param ctx The AES context to use for decryption. + * \param input The ciphertext block. + * \param output The output (plaintext) block. + * + * \return \c 0 on success. + */ +int mbedtls_internal_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Deprecated internal AES block encryption function + * without return value. + * + * \deprecated Superseded by mbedtls_aes_encrypt_ext() in 2.5.0. + * + * \param ctx The AES context to use for encryption. + * \param input Plaintext block. + * \param output Output (ciphertext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_encrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +/** + * \brief Deprecated internal AES block decryption function + * without return value. + * + * \deprecated Superseded by mbedtls_aes_decrypt_ext() in 2.5.0. + * + * \param ctx The AES context to use for decryption. + * \param input Ciphertext block. + * \param output Output (plaintext) block. + */ +MBEDTLS_DEPRECATED void mbedtls_aes_decrypt( mbedtls_aes_context *ctx, + const unsigned char input[16], + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_aes_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* aes.h */ diff --git a/common/mbedtls/arc4.c b/common/mbedtls/arc4.c new file mode 100644 index 000000000..22992dd46 --- /dev/null +++ b/common/mbedtls/arc4.c @@ -0,0 +1,203 @@ +/* + * An implementation of the ARCFOUR algorithm + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The ARCFOUR algorithm was publicly disclosed on 94/09. + * + * http://groups.google.com/group/sci.crypt/msg/10a300c9d21afca0 + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ARC4_C) + +#include "mbedtls/arc4.h" +#include "mbedtls/platform_util.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 */ + +#if !defined(MBEDTLS_ARC4_ALT) + +void mbedtls_arc4_init( mbedtls_arc4_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_arc4_context ) ); +} + +void mbedtls_arc4_free( mbedtls_arc4_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_arc4_context ) ); +} + +/* + * ARC4 key schedule + */ +void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, + unsigned int keylen ) +{ + int i, j, a; + unsigned int k; + unsigned char *m; + + ctx->x = 0; + ctx->y = 0; + m = ctx->m; + + for( i = 0; i < 256; i++ ) + m[i] = (unsigned char) i; + + j = k = 0; + + for( i = 0; i < 256; i++, k++ ) + { + if( k >= keylen ) k = 0; + + a = m[i]; + j = ( j + a + key[k] ) & 0xFF; + m[i] = m[j]; + m[j] = (unsigned char) a; + } +} + +/* + * ARC4 cipher function + */ +int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ) +{ + int x, y, a, b; + size_t i; + unsigned char *m; + + x = ctx->x; + y = ctx->y; + m = ctx->m; + + for( i = 0; i < length; i++ ) + { + x = ( x + 1 ) & 0xFF; a = m[x]; + y = ( y + a ) & 0xFF; b = m[y]; + + m[x] = (unsigned char) b; + m[y] = (unsigned char) a; + + output[i] = (unsigned char) + ( input[i] ^ m[(unsigned char)( a + b )] ); + } + + ctx->x = x; + ctx->y = y; + + return( 0 ); +} + +#endif /* !MBEDTLS_ARC4_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * ARC4 tests vectors as posted by Eric Rescorla in sep. 1994: + * + * http://groups.google.com/group/comp.security.misc/msg/10a300c9d21afca0 + */ +static const unsigned char arc4_test_key[3][8] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char arc4_test_pt[3][8] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char arc4_test_ct[3][8] = +{ + { 0x75, 0xB7, 0x87, 0x80, 0x99, 0xE0, 0xC5, 0x96 }, + { 0x74, 0x94, 0xC2, 0xE7, 0x10, 0x4B, 0x08, 0x79 }, + { 0xDE, 0x18, 0x89, 0x41, 0xA3, 0x37, 0x5D, 0x3A } +}; + +/* + * Checkup routine + */ +int mbedtls_arc4_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char ibuf[8]; + unsigned char obuf[8]; + mbedtls_arc4_context ctx; + + mbedtls_arc4_init( &ctx ); + + for( i = 0; i < 3; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " ARC4 test #%d: ", i + 1 ); + + memcpy( ibuf, arc4_test_pt[i], 8 ); + + mbedtls_arc4_setup( &ctx, arc4_test_key[i], 8 ); + mbedtls_arc4_crypt( &ctx, 8, ibuf, obuf ); + + if( memcmp( obuf, arc4_test_ct[i], 8 ) != 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_arc4_free( &ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ARC4_C */ diff --git a/common/mbedtls/arc4.h b/common/mbedtls/arc4.h new file mode 100644 index 000000000..0355fb8b5 --- /dev/null +++ b/common/mbedtls/arc4.h @@ -0,0 +1,143 @@ +/** + * \file arc4.h + * + * \brief The ARCFOUR stream cipher + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + */ +#ifndef MBEDTLS_ARC4_H +#define MBEDTLS_ARC4_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#define MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED -0x0019 /**< ARC4 hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_ARC4_ALT) +// Regular implementation +// + +/** + * \brief ARC4 context structure + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + * + */ +typedef struct mbedtls_arc4_context +{ + int x; /*!< permutation index */ + int y; /*!< permutation index */ + unsigned char m[256]; /*!< permutation table */ +} +mbedtls_arc4_context; + +#else /* MBEDTLS_ARC4_ALT */ +#include "arc4_alt.h" +#endif /* MBEDTLS_ARC4_ALT */ + +/** + * \brief Initialize ARC4 context + * + * \param ctx ARC4 context to be initialized + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_init( mbedtls_arc4_context *ctx ); + +/** + * \brief Clear ARC4 context + * + * \param ctx ARC4 context to be cleared + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_free( mbedtls_arc4_context *ctx ); + +/** + * \brief ARC4 key schedule + * + * \param ctx ARC4 context to be setup + * \param key the secret key + * \param keylen length of the key, in bytes + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +void mbedtls_arc4_setup( mbedtls_arc4_context *ctx, const unsigned char *key, + unsigned int keylen ); + +/** + * \brief ARC4 cipher function + * + * \param ctx ARC4 context + * \param length length of the input data + * \param input buffer holding the input data + * \param output buffer for the output data + * + * \return 0 if successful + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +int mbedtls_arc4_crypt( mbedtls_arc4_context *ctx, size_t length, const unsigned char *input, + unsigned char *output ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + * + */ +int mbedtls_arc4_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* arc4.h */ diff --git a/common/mbedtls/asn1.h b/common/mbedtls/asn1.h new file mode 100644 index 000000000..00b6f2c0f --- /dev/null +++ b/common/mbedtls/asn1.h @@ -0,0 +1,360 @@ +/** + * \file asn1.h + * + * \brief Generic ASN.1 parsing + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ASN1_H +#define MBEDTLS_ASN1_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "bignum.h" +#endif + +/** + * \addtogroup asn1_module + * \{ + */ + +/** + * \name ASN1 Error codes + * These error codes are OR'ed to X509 error codes for + * higher error granularity. + * ASN1 is a standard to specify data structures. + * \{ + */ +#define MBEDTLS_ERR_ASN1_OUT_OF_DATA -0x0060 /**< Out of data when parsing an ASN1 data structure. */ +#define MBEDTLS_ERR_ASN1_UNEXPECTED_TAG -0x0062 /**< ASN1 tag was of an unexpected value. */ +#define MBEDTLS_ERR_ASN1_INVALID_LENGTH -0x0064 /**< Error when trying to determine the length or invalid length. */ +#define MBEDTLS_ERR_ASN1_LENGTH_MISMATCH -0x0066 /**< Actual length differs from expected length. */ +#define MBEDTLS_ERR_ASN1_INVALID_DATA -0x0068 /**< Data is invalid. (not used) */ +#define MBEDTLS_ERR_ASN1_ALLOC_FAILED -0x006A /**< Memory allocation failed */ +#define MBEDTLS_ERR_ASN1_BUF_TOO_SMALL -0x006C /**< Buffer too small when writing ASN.1 data structure. */ + +/* \} name */ + +/** + * \name DER constants + * These constants comply with the DER encoded ASN.1 type tags. + * DER encoding uses hexadecimal representation. + * An example DER sequence is:\n + * - 0x02 -- tag indicating INTEGER + * - 0x01 -- length in octets + * - 0x05 -- value + * Such sequences are typically read into \c ::mbedtls_x509_buf. + * \{ + */ +#define MBEDTLS_ASN1_BOOLEAN 0x01 +#define MBEDTLS_ASN1_INTEGER 0x02 +#define MBEDTLS_ASN1_BIT_STRING 0x03 +#define MBEDTLS_ASN1_OCTET_STRING 0x04 +#define MBEDTLS_ASN1_NULL 0x05 +#define MBEDTLS_ASN1_OID 0x06 +#define MBEDTLS_ASN1_UTF8_STRING 0x0C +#define MBEDTLS_ASN1_SEQUENCE 0x10 +#define MBEDTLS_ASN1_SET 0x11 +#define MBEDTLS_ASN1_PRINTABLE_STRING 0x13 +#define MBEDTLS_ASN1_T61_STRING 0x14 +#define MBEDTLS_ASN1_IA5_STRING 0x16 +#define MBEDTLS_ASN1_UTC_TIME 0x17 +#define MBEDTLS_ASN1_GENERALIZED_TIME 0x18 +#define MBEDTLS_ASN1_UNIVERSAL_STRING 0x1C +#define MBEDTLS_ASN1_BMP_STRING 0x1E +#define MBEDTLS_ASN1_PRIMITIVE 0x00 +#define MBEDTLS_ASN1_CONSTRUCTED 0x20 +#define MBEDTLS_ASN1_CONTEXT_SPECIFIC 0x80 + +/* + * Bit masks for each of the components of an ASN.1 tag as specified in + * ITU X.690 (08/2015), section 8.1 "General rules for encoding", + * paragraph 8.1.2.2: + * + * Bit 8 7 6 5 1 + * +-------+-----+------------+ + * | Class | P/C | Tag number | + * +-------+-----+------------+ + */ +#define MBEDTLS_ASN1_TAG_CLASS_MASK 0xC0 +#define MBEDTLS_ASN1_TAG_PC_MASK 0x20 +#define MBEDTLS_ASN1_TAG_VALUE_MASK 0x1F + +/* \} name */ +/* \} addtogroup asn1_module */ + +/** Returns the size of the binary string, without the trailing \\0 */ +#define MBEDTLS_OID_SIZE(x) (sizeof(x) - 1) + +/** + * Compares an mbedtls_asn1_buf structure to a reference OID. + * + * Only works for 'defined' oid_str values (MBEDTLS_OID_HMAC_SHA1), you cannot use a + * 'unsigned char *oid' here! + */ +#define MBEDTLS_OID_CMP(oid_str, oid_buf) \ + ( ( MBEDTLS_OID_SIZE(oid_str) != (oid_buf)->len ) || \ + memcmp( (oid_str), (oid_buf)->p, (oid_buf)->len) != 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Functions to parse ASN.1 data structures + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef struct mbedtls_asn1_buf +{ + int tag; /**< ASN1 type, e.g. MBEDTLS_ASN1_UTF8_STRING. */ + size_t len; /**< ASN1 length, in octets. */ + unsigned char *p; /**< ASN1 data, e.g. in ASCII. */ +} +mbedtls_asn1_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef struct mbedtls_asn1_bitstring +{ + size_t len; /**< ASN1 length, in octets. */ + unsigned char unused_bits; /**< Number of unused bits at the end of the string */ + unsigned char *p; /**< Raw ASN1 data for the bit string */ +} +mbedtls_asn1_bitstring; + +/** + * Container for a sequence of ASN.1 items + */ +typedef struct mbedtls_asn1_sequence +{ + mbedtls_asn1_buf buf; /**< Buffer containing the given ASN.1 item. */ + struct mbedtls_asn1_sequence *next; /**< The next entry in the sequence. */ +} +mbedtls_asn1_sequence; + +/** + * Container for a sequence or list of 'named' ASN.1 data items + */ +typedef struct mbedtls_asn1_named_data +{ + mbedtls_asn1_buf oid; /**< The object identifier. */ + mbedtls_asn1_buf val; /**< The named value. */ + struct mbedtls_asn1_named_data *next; /**< The next entry in the sequence. */ + unsigned char next_merged; /**< Merge next item into the current one? */ +} +mbedtls_asn1_named_data; + +/** + * \brief Get the length of an ASN.1 element. + * Updates the pointer to immediately behind the length. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len The variable that will receive the value + * + * \return 0 if successful, MBEDTLS_ERR_ASN1_OUT_OF_DATA on reaching + * end of data, MBEDTLS_ERR_ASN1_INVALID_LENGTH if length is + * unparseable. + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ); + +/** + * \brief Get the tag and length of the tag. Check for the requested tag. + * Updates the pointer to immediately behind the tag and length. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len The variable that will receive the length + * \param tag The expected tag + * + * \return 0 if successful, MBEDTLS_ERR_ASN1_UNEXPECTED_TAG if tag did + * not match requested tag, or another specific ASN.1 error code. + */ +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ); + +/** + * \brief Retrieve a boolean ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param val The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve an integer ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param val The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ); + +/** + * \brief Retrieve a bitstring ASN.1 tag and its value. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param bs The variable that will receive the value + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs); + +/** + * \brief Retrieve a bitstring ASN.1 tag without unused bits and its + * value. + * Updates the pointer to the beginning of the bit/octet string. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param len Length of the actual bit/octect string in bytes + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ); + +/** + * \brief Parses and splits an ASN.1 "SEQUENCE OF " + * Updated the pointer to immediately behind the full sequence tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param cur First variable in the chain to fill + * \param tag Type of sequence + * + * \return 0 if successful or a specific ASN.1 error code. + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Retrieve a MPI value from an integer ASN.1 tag. + * Updates the pointer to immediately behind the full tag. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param X The MPI that will receive the value + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * \param params The buffer to receive the params (if any) + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ); + +/** + * \brief Retrieve an AlgorithmIdentifier ASN.1 sequence with NULL or no + * params. + * Updates the pointer to immediately behind the full + * AlgorithmIdentifier. + * + * \param p The position in the ASN.1 data + * \param end End of data + * \param alg The buffer to receive the OID + * + * \return 0 if successful or a specific ASN.1 or MPI error code. + */ +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ); + +/** + * \brief Find a specific named_data entry in a sequence or list based on + * the OID. + * + * \param list The list to seek through + * \param oid The OID to look for + * \param len Size of the OID + * + * \return NULL if not found, or a pointer to the existing entry. + */ +mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, + const char *oid, size_t len ); + +/** + * \brief Free a mbedtls_asn1_named_data entry + * + * \param entry The named data entry to free + */ +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *entry ); + +/** + * \brief Free all entries in a mbedtls_asn1_named_data list + * Head will be set to NULL + * + * \param head Pointer to the head of the list of named data entries to free + */ +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ); + +#ifdef __cplusplus +} +#endif + +#endif /* asn1.h */ diff --git a/common/mbedtls/asn1parse.c b/common/mbedtls/asn1parse.c new file mode 100644 index 000000000..aeec173ae --- /dev/null +++ b/common/mbedtls/asn1parse.c @@ -0,0 +1,391 @@ +/* + * Generic ASN.1 parsing + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ASN1_PARSE_C) + +#include "mbedtls/asn1.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +/* + * ASN.1 DER decoding routines + */ +int mbedtls_asn1_get_len( unsigned char **p, + const unsigned char *end, + size_t *len ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( ( **p & 0x80 ) == 0 ) + *len = *(*p)++; + else + { + switch( **p & 0x7F ) + { + case 1: + if( ( end - *p ) < 2 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = (*p)[1]; + (*p) += 2; + break; + + case 2: + if( ( end - *p ) < 3 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 8 ) | (*p)[2]; + (*p) += 3; + break; + + case 3: + if( ( end - *p ) < 4 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 16 ) | + ( (size_t)(*p)[2] << 8 ) | (*p)[3]; + (*p) += 4; + break; + + case 4: + if( ( end - *p ) < 5 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + *len = ( (size_t)(*p)[1] << 24 ) | ( (size_t)(*p)[2] << 16 ) | + ( (size_t)(*p)[3] << 8 ) | (*p)[4]; + (*p) += 5; + break; + + default: + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + } + } + + if( *len > (size_t) ( end - *p ) ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + return( 0 ); +} + +int mbedtls_asn1_get_tag( unsigned char **p, + const unsigned char *end, + size_t *len, int tag ) +{ + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != tag ) + return( MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + + return( mbedtls_asn1_get_len( p, end, len ) ); +} + +int mbedtls_asn1_get_bool( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_BOOLEAN ) ) != 0 ) + return( ret ); + + if( len != 1 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = ( **p != 0 ) ? 1 : 0; + (*p)++; + + return( 0 ); +} + +int mbedtls_asn1_get_int( unsigned char **p, + const unsigned char *end, + int *val ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( ret ); + + if( len == 0 || len > sizeof( int ) || ( **p & 0x80 ) != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + *val = 0; + + while( len-- > 0 ) + { + *val = ( *val << 8 ) | **p; + (*p)++; + } + + return( 0 ); +} + +#if defined(MBEDTLS_BIGNUM_C) +int mbedtls_asn1_get_mpi( unsigned char **p, + const unsigned char *end, + mbedtls_mpi *X ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( ret ); + + ret = mbedtls_mpi_read_binary( X, *p, len ); + + *p += len; + + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +int mbedtls_asn1_get_bitstring( unsigned char **p, const unsigned char *end, + mbedtls_asn1_bitstring *bs) +{ + int ret; + + /* Certificate type is a single byte bitstring */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &bs->len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + /* Check length, subtract one for actual bit string length */ + if( bs->len < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + bs->len -= 1; + + /* Get number of unused bits, ensure unused bits <= 7 */ + bs->unused_bits = **p; + if( bs->unused_bits > 7 ) + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + (*p)++; + + /* Get actual bitstring */ + bs->p = *p; + *p += bs->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Get a bit string without unused bits + */ +int mbedtls_asn1_get_bitstring_null( unsigned char **p, const unsigned char *end, + size_t *len ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_tag( p, end, len, MBEDTLS_ASN1_BIT_STRING ) ) != 0 ) + return( ret ); + + if( (*len)-- < 2 || *(*p)++ != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + + + +/* + * Parses and splits an ASN.1 "SEQUENCE OF " + */ +int mbedtls_asn1_get_sequence_of( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_sequence *cur, + int tag) +{ + int ret; + size_t len; + mbedtls_asn1_buf *buf; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + buf = &(cur->buf); + buf->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &buf->len, tag ) ) != 0 ) + return( ret ); + + buf->p = *p; + *p += buf->len; + + /* Allocate and assign next pointer */ + if( *p < end ) + { + cur->next = (mbedtls_asn1_sequence*)mbedtls_calloc( 1, + sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_asn1_get_alg( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg, mbedtls_asn1_buf *params ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + alg->tag = **p; + end = *p + len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &alg->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + alg->p = *p; + *p += alg->len; + + if( *p == end ) + { + mbedtls_platform_zeroize( params, sizeof(mbedtls_asn1_buf) ); + return( 0 ); + } + + params->tag = **p; + (*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, ¶ms->len ) ) != 0 ) + return( ret ); + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_asn1_get_alg_null( unsigned char **p, + const unsigned char *end, + mbedtls_asn1_buf *alg ) +{ + int ret; + mbedtls_asn1_buf params; + + memset( ¶ms, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, ¶ms ) ) != 0 ) + return( ret ); + + if( ( params.tag != MBEDTLS_ASN1_NULL && params.tag != 0 ) || params.len != 0 ) + return( MBEDTLS_ERR_ASN1_INVALID_DATA ); + + return( 0 ); +} + +void mbedtls_asn1_free_named_data( mbedtls_asn1_named_data *cur ) +{ + if( cur == NULL ) + return; + + mbedtls_free( cur->oid.p ); + mbedtls_free( cur->val.p ); + + mbedtls_platform_zeroize( cur, sizeof( mbedtls_asn1_named_data ) ); +} + +void mbedtls_asn1_free_named_data_list( mbedtls_asn1_named_data **head ) +{ + mbedtls_asn1_named_data *cur; + + while( ( cur = *head ) != NULL ) + { + *head = cur->next; + mbedtls_asn1_free_named_data( cur ); + mbedtls_free( cur ); + } +} + +mbedtls_asn1_named_data *mbedtls_asn1_find_named_data( mbedtls_asn1_named_data *list, + const char *oid, size_t len ) +{ + while( list != NULL ) + { + if( list->oid.len == len && + memcmp( list->oid.p, oid, len ) == 0 ) + { + break; + } + + list = list->next; + } + + return( list ); +} + +#endif /* MBEDTLS_ASN1_PARSE_C */ diff --git a/common/mbedtls/asn1write.c b/common/mbedtls/asn1write.c new file mode 100644 index 000000000..f8e29dc74 --- /dev/null +++ b/common/mbedtls/asn1write.c @@ -0,0 +1,392 @@ +/* + * ASN.1 buffer writing functionality + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ASN1_WRITE_C) + +#include "mbedtls/asn1write.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ) +{ + if( len < 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + return( 1 ); + } + + if( len <= 0xFF ) + { + if( *p - start < 2 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (unsigned char) len; + *--(*p) = 0x81; + return( 2 ); + } + + if( len <= 0xFFFF ) + { + if( *p - start < 3 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = ( len ) & 0xFF; + *--(*p) = ( len >> 8 ) & 0xFF; + *--(*p) = 0x82; + return( 3 ); + } + + if( len <= 0xFFFFFF ) + { + if( *p - start < 4 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = ( len ) & 0xFF; + *--(*p) = ( len >> 8 ) & 0xFF; + *--(*p) = ( len >> 16 ) & 0xFF; + *--(*p) = 0x83; + return( 4 ); + } + +#if SIZE_MAX > 0xFFFFFFFF + if( len <= 0xFFFFFFFF ) +#endif + { + if( *p - start < 5 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = ( len ) & 0xFF; + *--(*p) = ( len >> 8 ) & 0xFF; + *--(*p) = ( len >> 16 ) & 0xFF; + *--(*p) = ( len >> 24 ) & 0xFF; + *--(*p) = 0x84; + return( 5 ); + } + +#if SIZE_MAX > 0xFFFFFFFF + return( MBEDTLS_ERR_ASN1_INVALID_LENGTH ); +#endif +} + +int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, unsigned char tag ) +{ + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = tag; + + return( 1 ); +} + +int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + size_t len = 0; + + if( *p < start || (size_t)( *p - start ) < size ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = size; + (*p) -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +#if defined(MBEDTLS_BIGNUM_C) +int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ) +{ + int ret; + size_t len = 0; + + // Write the MPI + // + len = mbedtls_mpi_size( X ); + + if( *p < start || (size_t)( *p - start ) < len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + (*p) -= len; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( X, *p, len ) ); + + // DER format assumes 2s complement for numbers, so the leftmost bit + // should be 0 for positive numbers and 1 for negative numbers. + // + if( X->s ==1 && **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); + + ret = (int) len; + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_BIGNUM_C */ + +int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ) +{ + int ret; + size_t len = 0; + + // Write NULL + // + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, 0) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_NULL ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) oid, oid_len ) ); + MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len , mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OID ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ) +{ + int ret; + size_t len = 0; + + if( par_len == 0 ) + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_null( p, start ) ); + else + len += par_len; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ) +{ + int ret; + size_t len = 0; + + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = (boolean) ? 255 : 0; + len++; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BOOLEAN ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ) +{ + int ret; + size_t len = 0; + + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len += 1; + *--(*p) = val; + + if( val > 0 && **p & 0x80 ) + { + if( *p - start < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *--(*p) = 0x00; + len += 1; + } + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_INTEGER ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) text, text_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_PRINTABLE_STRING ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, + (const unsigned char *) text, text_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_IA5_STRING ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ) +{ + int ret; + size_t len = 0, size; + + size = ( bits / 8 ) + ( ( bits % 8 ) ? 1 : 0 ); + + // Calculate byte length + // + if( *p < start || (size_t)( *p - start ) < size + 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + len = size + 1; + (*p) -= size; + memcpy( *p, buf, size ); + + // Write unused bits + // + *--(*p) = (unsigned char) (size * 8 - bits); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_BIT_STRING ) ); + + return( (int) len ); +} + +int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ) +{ + int ret; + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_raw_buffer( p, start, buf, size ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_OCTET_STRING ) ); + + return( (int) len ); +} + +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **head, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ) +{ + mbedtls_asn1_named_data *cur; + + if( ( cur = mbedtls_asn1_find_named_data( *head, oid, oid_len ) ) == NULL ) + { + // Add new entry if not present yet based on OID + // + cur = (mbedtls_asn1_named_data*)mbedtls_calloc( 1, + sizeof(mbedtls_asn1_named_data) ); + if( cur == NULL ) + return( NULL ); + + cur->oid.len = oid_len; + cur->oid.p = mbedtls_calloc( 1, oid_len ); + if( cur->oid.p == NULL ) + { + mbedtls_free( cur ); + return( NULL ); + } + + memcpy( cur->oid.p, oid, oid_len ); + + cur->val.len = val_len; + cur->val.p = mbedtls_calloc( 1, val_len ); + if( cur->val.p == NULL ) + { + mbedtls_free( cur->oid.p ); + mbedtls_free( cur ); + return( NULL ); + } + + cur->next = *head; + *head = cur; + } + else if( cur->val.len < val_len ) + { + /* + * Enlarge existing value buffer if needed + * Preserve old data until the allocation succeeded, to leave list in + * a consistent state in case allocation fails. + */ + void *p = mbedtls_calloc( 1, val_len ); + if( p == NULL ) + return( NULL ); + + mbedtls_free( cur->val.p ); + cur->val.p = p; + cur->val.len = val_len; + } + + if( val != NULL ) + memcpy( cur->val.p, val, val_len ); + + return( cur ); +} +#endif /* MBEDTLS_ASN1_WRITE_C */ diff --git a/common/mbedtls/asn1write.h b/common/mbedtls/asn1write.h new file mode 100644 index 000000000..0b832e5c2 --- /dev/null +++ b/common/mbedtls/asn1write.h @@ -0,0 +1,242 @@ +/** + * \file asn1write.h + * + * \brief ASN.1 buffer writing functionality + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ASN1_WRITE_H +#define MBEDTLS_ASN1_WRITE_H + +#include "asn1.h" + +#define MBEDTLS_ASN1_CHK_ADD(g, f) do { if( ( ret = f ) < 0 ) return( ret ); else \ + g += ret; } while( 0 ) + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Write a length field in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param len the length to write + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_len( unsigned char **p, unsigned char *start, size_t len ); + +/** + * \brief Write a ASN.1 tag in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param tag the tag to write + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_tag( unsigned char **p, unsigned char *start, + unsigned char tag ); + +/** + * \brief Write raw buffer data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_raw_buffer( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_BIGNUM_C) +/** + * \brief Write a big number (MBEDTLS_ASN1_INTEGER) in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param X the MPI to write + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_mpi( unsigned char **p, unsigned char *start, const mbedtls_mpi *X ); +#endif /* MBEDTLS_BIGNUM_C */ + +/** + * \brief Write a NULL tag (MBEDTLS_ASN1_NULL) with zero data in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_null( unsigned char **p, unsigned char *start ); + +/** + * \brief Write an OID tag (MBEDTLS_ASN1_OID) and data in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param oid the OID to write + * \param oid_len length of the OID + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_oid( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len ); + +/** + * \brief Write an AlgorithmIdentifier sequence in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param oid the OID of the algorithm + * \param oid_len length of the OID + * \param par_len length of parameters, which must be already written. + * If 0, NULL parameters are added + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_algorithm_identifier( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + size_t par_len ); + +/** + * \brief Write a boolean tag (MBEDTLS_ASN1_BOOLEAN) and value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param boolean 0 or 1 + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_bool( unsigned char **p, unsigned char *start, int boolean ); + +/** + * \brief Write an int tag (MBEDTLS_ASN1_INTEGER) and value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param val the integer value + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_int( unsigned char **p, unsigned char *start, int val ); + +/** + * \brief Write a printable string tag (MBEDTLS_ASN1_PRINTABLE_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param text the text to write + * \param text_len length of the text + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_printable_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write an IA5 string tag (MBEDTLS_ASN1_IA5_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param text the text to write + * \param text_len length of the text + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_ia5_string( unsigned char **p, unsigned char *start, + const char *text, size_t text_len ); + +/** + * \brief Write a bitstring tag (MBEDTLS_ASN1_BIT_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf the bitstring + * \param bits the total number of bits in the bitstring + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_bitstring( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t bits ); + +/** + * \brief Write an octet string tag (MBEDTLS_ASN1_OCTET_STRING) and + * value in ASN.1 format + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param buf data buffer to write + * \param size length of the data buffer + * + * \return the length written or a negative error code + */ +int mbedtls_asn1_write_octet_string( unsigned char **p, unsigned char *start, + const unsigned char *buf, size_t size ); + +/** + * \brief Create or find a specific named_data entry for writing in a + * sequence or list based on the OID. If not already in there, + * a new entry is added to the head of the list. + * Warning: Destructive behaviour for the val data! + * + * \param list Pointer to the location of the head of the list to seek + * through (will be updated in case of a new entry) + * \param oid The OID to look for + * \param oid_len Size of the OID + * \param val Data to store (can be NULL if you want to fill it by hand) + * \param val_len Minimum length of the data buffer needed + * + * \return NULL if if there was a memory allocation error, or a pointer + * to the new / existing entry. + */ +mbedtls_asn1_named_data *mbedtls_asn1_store_named_data( mbedtls_asn1_named_data **list, + const char *oid, size_t oid_len, + const unsigned char *val, + size_t val_len ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_ASN1_WRITE_H */ diff --git a/common/polarssl/base64.c b/common/mbedtls/base64.c similarity index 87% rename from common/polarssl/base64.c rename to common/mbedtls/base64.c index d470bae0c..412000217 100644 --- a/common/polarssl/base64.c +++ b/common/mbedtls/base64.c @@ -2,35 +2,41 @@ * RFC 1521 base64 encoding/decoding * * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: GPL-2.0 * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at + * 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. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * 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. * * This file is part of mbed TLS (https://tls.mbed.org) */ -#include "polarssl_config.h" +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif -//#if defined(MBEDTLS_BASE64_C) +#if defined(MBEDTLS_BASE64_C) -#include "base64.h" +#include "mbedtls/base64.h" #include #if defined(MBEDTLS_SELF_TEST) #include #if defined(MBEDTLS_PLATFORM_C) -#include "platform.h" +#include "mbedtls/platform.h" #else #include #define mbedtls_printf printf @@ -286,4 +292,4 @@ int mbedtls_base64_self_test( int verbose ) #endif /* MBEDTLS_SELF_TEST */ -//#endif /* MBEDTLS_BASE64_C */ +#endif /* MBEDTLS_BASE64_C */ diff --git a/common/polarssl/base64.h b/common/mbedtls/base64.h similarity index 77% rename from common/polarssl/base64.h rename to common/mbedtls/base64.h index 7a64f5216..ce5563e1d 100644 --- a/common/polarssl/base64.h +++ b/common/mbedtls/base64.h @@ -5,19 +5,21 @@ */ /* * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved - * SPDX-License-Identifier: Apache-2.0 + * SPDX-License-Identifier: GPL-2.0 * - * Licensed under the Apache License, Version 2.0 (the "License"); you may - * not use this file except in compliance with the License. - * You may obtain a copy of the License at + * 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. * - * http://www.apache.org/licenses/LICENSE-2.0 + * 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. * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT - * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. + * 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. * * This file is part of mbed TLS (https://tls.mbed.org) */ diff --git a/common/mbedtls/bignum.c b/common/mbedtls/bignum.c new file mode 100644 index 000000000..2c9ecbe26 --- /dev/null +++ b/common/mbedtls/bignum.c @@ -0,0 +1,2470 @@ +/* + * Multi-precision integer library + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * The following sources were referenced in the design of this Multi-precision + * Integer library: + * + * [1] Handbook of Applied Cryptography - 1997 + * Menezes, van Oorschot and Vanstone + * + * [2] Multi-Precision Math + * Tom St Denis + * https://github.com/libtom/libtommath/blob/develop/tommath.pdf + * + * [3] GNU Multi-Precision Arithmetic Library + * https://gmplib.org/manual/index.html + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_BIGNUM_C) + +#include "mbedtls/bignum.h" +#include "mbedtls/bn_mul.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#define ciL (sizeof(mbedtls_mpi_uint)) /* chars in limb */ +#define biL (ciL << 3) /* bits in limb */ +#define biH (ciL << 2) /* half limb size */ + +#define MPI_SIZE_T_MAX ( (size_t) -1 ) /* SIZE_T_MAX is not standard */ + +/* + * Convert between bits/chars and number of limbs + * Divide first in order to avoid potential overflows + */ +#define BITS_TO_LIMBS(i) ( (i) / biL + ( (i) % biL != 0 ) ) +#define CHARS_TO_LIMBS(i) ( (i) / ciL + ( (i) % ciL != 0 ) ) + +/* Implementation that should never be optimized out by the compiler */ +static void mbedtls_mpi_zeroize( mbedtls_mpi_uint *v, size_t n ) +{ + mbedtls_platform_zeroize( v, ciL * n ); +} + +/* + * Initialize one MPI + */ +void mbedtls_mpi_init( mbedtls_mpi *X ) +{ + if( X == NULL ) + return; + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Unallocate one MPI + */ +void mbedtls_mpi_free( mbedtls_mpi *X ) +{ + if( X == NULL ) + return; + + if( X->p != NULL ) + { + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->s = 1; + X->n = 0; + X->p = NULL; +} + +/* + * Enlarge to the specified number of limbs + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + + if( nblimbs > MBEDTLS_MPI_MAX_LIMBS ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->n < nblimbs ) + { + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( nblimbs, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, X->n * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = nblimbs; + X->p = p; + } + + return( 0 ); +} + +/* + * Resize down as much as possible, + * while keeping at least the specified number of limbs + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ) +{ + mbedtls_mpi_uint *p; + size_t i; + + /* Actually resize up in this case */ + if( X->n <= nblimbs ) + return( mbedtls_mpi_grow( X, nblimbs ) ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + i++; + + if( i < nblimbs ) + i = nblimbs; + + if( ( p = (mbedtls_mpi_uint*)mbedtls_calloc( i, ciL ) ) == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + if( X->p != NULL ) + { + memcpy( p, X->p, i * ciL ); + mbedtls_mpi_zeroize( X->p, X->n ); + mbedtls_free( X->p ); + } + + X->n = i; + X->p = p; + + return( 0 ); +} + +/* + * Copy the contents of Y into X + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + int ret = 0; + size_t i; + + if( X == Y ) + return( 0 ); + + if( Y->p == NULL ) + { + mbedtls_mpi_free( X ); + return( 0 ); + } + + for( i = Y->n - 1; i > 0; i-- ) + if( Y->p[i] != 0 ) + break; + i++; + + X->s = Y->s; + + if( X->n < i ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i ) ); + } + else + { + memset( X->p + i, 0, ( X->n - i ) * ciL ); + } + + memcpy( X->p, Y->p, i * ciL ); + +cleanup: + + return( ret ); +} + +/* + * Swap the contents of X and Y + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ) +{ + mbedtls_mpi T; + + memcpy( &T, X, sizeof( mbedtls_mpi ) ); + memcpy( X, Y, sizeof( mbedtls_mpi ) ); + memcpy( Y, &T, sizeof( mbedtls_mpi ) ); +} + +/* + * Conditionally assign X = Y, without leaking information + * about whether the assignment was made or not. + * (Leaking information about the respective sizes of X and Y is ok however.) + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ) +{ + int ret = 0; + size_t i; + + /* make sure assign is 0 or 1 in a time-constant manner */ + assign = (assign | (unsigned char)-assign) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + + X->s = X->s * ( 1 - assign ) + Y->s * assign; + + for( i = 0; i < Y->n; i++ ) + X->p[i] = X->p[i] * ( 1 - assign ) + Y->p[i] * assign; + + for( ; i < X->n; i++ ) + X->p[i] *= ( 1 - assign ); + +cleanup: + return( ret ); +} + +/* + * Conditionally swap X and Y, without leaking information + * about whether the swap was made or not. + * Here it is not ok to simply swap the pointers, which whould lead to + * different memory access patterns when X and Y are used afterwards. + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char swap ) +{ + int ret, s; + size_t i; + mbedtls_mpi_uint tmp; + + if( X == Y ) + return( 0 ); + + /* make sure swap is 0 or 1 in a time-constant manner */ + swap = (swap | (unsigned char)-swap) >> 7; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, Y->n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( Y, X->n ) ); + + s = X->s; + X->s = X->s * ( 1 - swap ) + Y->s * swap; + Y->s = Y->s * ( 1 - swap ) + s * swap; + + + for( i = 0; i < X->n; i++ ) + { + tmp = X->p[i]; + X->p[i] = X->p[i] * ( 1 - swap ) + Y->p[i] * swap; + Y->p[i] = Y->p[i] * ( 1 - swap ) + tmp * swap; + } + +cleanup: + return( ret ); +} + +/* + * Set value from integer + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, 1 ) ); + memset( X->p, 0, X->n * ciL ); + + X->p[0] = ( z < 0 ) ? -z : z; + X->s = ( z < 0 ) ? -1 : 1; + +cleanup: + + return( ret ); +} + +/* + * Get a specific bit + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ) +{ + if( X->n * biL <= pos ) + return( 0 ); + + return( ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01 ); +} + +/* + * Set a bit to a specific value of 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ) +{ + int ret = 0; + size_t off = pos / biL; + size_t idx = pos % biL; + + if( val != 0 && val != 1 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( X->n * biL <= pos ) + { + if( val == 0 ) + return( 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, off + 1 ) ); + } + + X->p[off] &= ~( (mbedtls_mpi_uint) 0x01 << idx ); + X->p[off] |= (mbedtls_mpi_uint) val << idx; + +cleanup: + + return( ret ); +} + +/* + * Return the number of less significant zero-bits + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ) +{ + size_t i, j, count = 0; + + for( i = 0; i < X->n; i++ ) + for( j = 0; j < biL; j++, count++ ) + if( ( ( X->p[i] >> j ) & 1 ) != 0 ) + return( count ); + + return( 0 ); +} + +/* + * Count leading zero bits in a given integer + */ +static size_t mbedtls_clz( const mbedtls_mpi_uint x ) +{ + size_t j; + mbedtls_mpi_uint mask = (mbedtls_mpi_uint) 1 << (biL - 1); + + for( j = 0; j < biL; j++ ) + { + if( x & mask ) break; + + mask >>= 1; + } + + return j; +} + +/* + * Return the number of bits + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ) +{ + size_t i, j; + + if( X->n == 0 ) + return( 0 ); + + for( i = X->n - 1; i > 0; i-- ) + if( X->p[i] != 0 ) + break; + + j = biL - mbedtls_clz( X->p[i] ); + + return( ( i * biL ) + j ); +} + +/* + * Return the total size in bytes + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ) +{ + return( ( mbedtls_mpi_bitlen( X ) + 7 ) >> 3 ); +} + +/* + * Convert an ASCII character to digit value + */ +static int mpi_get_digit( mbedtls_mpi_uint *d, int radix, char c ) +{ + *d = 255; + + if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; + if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; + if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; + + if( *d >= (mbedtls_mpi_uint) radix ) + return( MBEDTLS_ERR_MPI_INVALID_CHARACTER ); + + return( 0 ); +} + +/* + * Import from an ASCII string + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ) +{ + int ret; + size_t i, j, slen, n; + mbedtls_mpi_uint d; + mbedtls_mpi T; + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + + slen = strlen( s ); + + if( radix == 16 ) + { + if( slen > MPI_SIZE_T_MAX >> 2 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = BITS_TO_LIMBS( slen << 2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = slen, j = 0; i > 0; i--, j++ ) + { + if( i == 1 && s[i - 1] == '-' ) + { + X->s = -1; + break; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); + X->p[j / ( 2 * ciL )] |= d << ( ( j % ( 2 * ciL ) ) << 2 ); + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = 0; i < slen; i++ ) + { + if( i == 0 && s[i] == '-' ) + { + X->s = -1; + continue; + } + + MBEDTLS_MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T, X, radix ) ); + + if( X->s == 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, &T, d ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( X, &T, d ) ); + } + } + } + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +/* + * Helper to write the digits high-order first + */ +static int mpi_write_hlp( mbedtls_mpi *X, int radix, char **p ) +{ + int ret; + mbedtls_mpi_uint r; + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, radix ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_int( X, NULL, X, radix ) ); + + if( mbedtls_mpi_cmp_int( X, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mpi_write_hlp( X, radix, p ) ); + + if( r < 10 ) + *(*p)++ = (char)( r + 0x30 ); + else + *(*p)++ = (char)( r + 0x37 ); + +cleanup: + + return( ret ); +} + +/* + * Export into an ASCII string + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ) +{ + int ret = 0; + size_t n; + char *p; + mbedtls_mpi T; + + if( radix < 2 || radix > 16 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + n = mbedtls_mpi_bitlen( X ); + if( radix >= 4 ) n >>= 1; + if( radix >= 16 ) n >>= 1; + /* + * Round up the buffer length to an even value to ensure that there is + * enough room for hexadecimal values that can be represented in an odd + * number of digits. + */ + n += 3 + ( ( n + 1 ) & 1 ); + + if( buflen < n ) + { + *olen = n; + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + } + + p = buf; + mbedtls_mpi_init( &T ); + + if( X->s == -1 ) + *p++ = '-'; + + if( radix == 16 ) + { + int c; + size_t i, j, k; + + for( i = X->n, k = 0; i > 0; i-- ) + { + for( j = ciL; j > 0; j-- ) + { + c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; + + if( c == 0 && k == 0 && ( i + j ) != 2 ) + continue; + + *(p++) = "0123456789ABCDEF" [c / 16]; + *(p++) = "0123456789ABCDEF" [c % 16]; + k = 1; + } + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T, X ) ); + + if( T.s == -1 ) + T.s = 1; + + MBEDTLS_MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); + } + + *p++ = '\0'; + *olen = p - buf; + +cleanup: + + mbedtls_mpi_free( &T ); + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Read X from an opened file + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ) +{ + mbedtls_mpi_uint d; + size_t slen; + char *p; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + + memset( s, 0, sizeof( s ) ); + if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + + slen = strlen( s ); + if( slen == sizeof( s ) - 2 ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + + if( slen > 0 && s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } + if( slen > 0 && s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } + + p = s + slen; + while( p-- > s ) + if( mpi_get_digit( &d, radix, *p ) != 0 ) + break; + + return( mbedtls_mpi_read_string( X, radix, p + 1 ) ); +} + +/* + * Write X into an opened file (or stdout if fout == NULL) + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ) +{ + int ret; + size_t n, slen, plen; + /* + * Buffer should have space for (short) label and decimal formatted MPI, + * newline characters and '\0' + */ + char s[ MBEDTLS_MPI_RW_BUFFER_SIZE ]; + + memset( s, 0, sizeof( s ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_write_string( X, radix, s, sizeof( s ) - 2, &n ) ); + + if( p == NULL ) p = ""; + + plen = strlen( p ); + slen = strlen( s ); + s[slen++] = '\r'; + s[slen++] = '\n'; + + if( fout != NULL ) + { + if( fwrite( p, 1, plen, fout ) != plen || + fwrite( s, 1, slen, fout ) != slen ) + return( MBEDTLS_ERR_MPI_FILE_IO_ERROR ); + } + else + mbedtls_printf( "%s%s", p, s ); + +cleanup: + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +/* + * Import X from unsigned binary data, big endian + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t i, j; + size_t const limbs = CHARS_TO_LIMBS( buflen ); + + /* Ensure that target MPI has exactly the necessary number of limbs */ + if( X->n != limbs ) + { + mbedtls_mpi_free( X ); + mbedtls_mpi_init( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, limbs ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( i = buflen, j = 0; i > 0; i--, j++ ) + X->p[j / ciL] |= ((mbedtls_mpi_uint) buf[i - 1]) << ((j % ciL) << 3); + +cleanup: + + return( ret ); +} + +/* + * Export X into unsigned binary data, big endian + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ) +{ + size_t i, j, n; + + n = mbedtls_mpi_size( X ); + + if( buflen < n ) + return( MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL ); + + memset( buf, 0, buflen ); + + for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) + buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); + + return( 0 ); +} + +/* + * Left-shift: X <<= count + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ) +{ + int ret; + size_t i, v0, t1; + mbedtls_mpi_uint r0 = 0, r1; + + v0 = count / (biL ); + t1 = count & (biL - 1); + + i = mbedtls_mpi_bitlen( X ) + count; + + if( X->n * biL < i ) + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, BITS_TO_LIMBS( i ) ) ); + + ret = 0; + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = X->n; i > v0; i-- ) + X->p[i - 1] = X->p[i - v0 - 1]; + + for( ; i > 0; i-- ) + X->p[i - 1] = 0; + } + + /* + * shift by count % limb_size + */ + if( t1 > 0 ) + { + for( i = v0; i < X->n; i++ ) + { + r1 = X->p[i] >> (biL - t1); + X->p[i] <<= t1; + X->p[i] |= r0; + r0 = r1; + } + } + +cleanup: + + return( ret ); +} + +/* + * Right-shift: X >>= count + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ) +{ + size_t i, v0, v1; + mbedtls_mpi_uint r0 = 0, r1; + + v0 = count / biL; + v1 = count & (biL - 1); + + if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) + return mbedtls_mpi_lset( X, 0 ); + + /* + * shift by count / limb_size + */ + if( v0 > 0 ) + { + for( i = 0; i < X->n - v0; i++ ) + X->p[i] = X->p[i + v0]; + + for( ; i < X->n; i++ ) + X->p[i] = 0; + } + + /* + * shift by count % limb_size + */ + if( v1 > 0 ) + { + for( i = X->n; i > 0; i-- ) + { + r1 = X->p[i - 1] << (biL - v1); + X->p[i - 1] >>= v1; + X->p[i - 1] |= r0; + r0 = r1; + } + } + + return( 0 ); +} + +/* + * Compare unsigned values + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( 1 ); + if( j > i ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ) +{ + size_t i, j; + + for( i = X->n; i > 0; i-- ) + if( X->p[i - 1] != 0 ) + break; + + for( j = Y->n; j > 0; j-- ) + if( Y->p[j - 1] != 0 ) + break; + + if( i == 0 && j == 0 ) + return( 0 ); + + if( i > j ) return( X->s ); + if( j > i ) return( -Y->s ); + + if( X->s > 0 && Y->s < 0 ) return( 1 ); + if( Y->s > 0 && X->s < 0 ) return( -1 ); + + for( ; i > 0; i-- ) + { + if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); + if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); + } + + return( 0 ); +} + +/* + * Compare signed values + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ) +{ + mbedtls_mpi Y; + mbedtls_mpi_uint p[1]; + + *p = ( z < 0 ) ? -z : z; + Y.s = ( z < 0 ) ? -1 : 1; + Y.n = 1; + Y.p = p; + + return( mbedtls_mpi_cmp_mpi( X, &Y ) ); +} + +/* + * Unsigned addition: X = |A| + |B| (HAC 14.7) + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t i, j; + mbedtls_mpi_uint *o, *p, c, tmp; + + if( X == B ) + { + const mbedtls_mpi *T = A; A = X; B = T; + } + + if( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned additions. + */ + X->s = 1; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + + o = B->p; p = X->p; c = 0; + + /* + * tmp is used because it might happen that p == o + */ + for( i = 0; i < j; i++, o++, p++ ) + { + tmp= *o; + *p += c; c = ( *p < c ); + *p += tmp; c += ( *p < tmp ); + } + + while( c != 0 ) + { + if( i >= X->n ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + 1 ) ); + p = X->p + i; + } + + *p += c; c = ( *p < c ); i++; p++; + } + +cleanup: + + return( ret ); +} + +/* + * Helper for mbedtls_mpi subtraction + */ +static void mpi_sub_hlp( size_t n, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d ) +{ + size_t i; + mbedtls_mpi_uint c, z; + + for( i = c = 0; i < n; i++, s++, d++ ) + { + z = ( *d < c ); *d -= c; + c = ( *d < *s ) + z; *d -= *s; + } + + while( c != 0 ) + { + z = ( *d < c ); *d -= c; + c = z; d++; + } +} + +/* + * Unsigned subtraction: X = |A| - |B| (HAC 14.9) + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + mbedtls_mpi TB; + int ret; + size_t n; + + if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + mbedtls_mpi_init( &TB ); + + if( X == B ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + B = &TB; + } + + if( X != A ) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, A ) ); + + /* + * X should always be positive as a result of unsigned subtractions. + */ + X->s = 1; + + ret = 0; + + for( n = B->n; n > 0; n-- ) + if( B->p[n - 1] != 0 ) + break; + + mpi_sub_hlp( n, B->p, X->p ); + +cleanup: + + mbedtls_mpi_free( &TB ); + + return( ret ); +} + +/* + * Signed addition: X = A + B + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s = A->s; + + if( A->s * B->s < 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed subtraction: X = A - B + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret, s = A->s; + + if( A->s * B->s > 0 ) + { + if( mbedtls_mpi_cmp_abs( A, B ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, A, B ) ); + X->s = s; + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( X, B, A ) ); + X->s = -s; + } + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( X, A, B ) ); + X->s = s; + } + +cleanup: + + return( ret ); +} + +/* + * Signed addition: X = A + b + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_add_mpi( X, A, &_B ) ); +} + +/* + * Signed subtraction: X = A - b + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_sub_mpi( X, A, &_B ) ); +} + +/* + * Helper for mbedtls_mpi multiplication + */ +static +#if defined(__APPLE__) && defined(__arm__) +/* + * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) + * appears to need this to prevent bad ARM code generation at -O3. + */ +__attribute__ ((noinline)) +#endif +void mpi_mul_hlp( size_t i, mbedtls_mpi_uint *s, mbedtls_mpi_uint *d, mbedtls_mpi_uint b ) +{ + mbedtls_mpi_uint c = 0, t = 0; + +#if defined(MULADDC_HUIT) + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_HUIT + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#else /* MULADDC_HUIT */ + for( ; i >= 16; i -= 16 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i >= 8; i -= 8 ) + { + MULADDC_INIT + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + + MULADDC_CORE MULADDC_CORE + MULADDC_CORE MULADDC_CORE + MULADDC_STOP + } + + for( ; i > 0; i-- ) + { + MULADDC_INIT + MULADDC_CORE + MULADDC_STOP + } +#endif /* MULADDC_HUIT */ + + t++; + + do { + *d += c; c = ( *d < c ); d++; + } + while( c != 0 ); +} + +/* + * Baseline multiplication: X = A * B (HAC 14.12) + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t i, j; + mbedtls_mpi TA, TB; + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + if( X == A ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); A = &TA; } + if( X == B ) { MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); B = &TB; } + + for( i = A->n; i > 0; i-- ) + if( A->p[i - 1] != 0 ) + break; + + for( j = B->n; j > 0; j-- ) + if( B->p[j - 1] != 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, i + j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( X, 0 ) ); + + for( ; j > 0; j-- ) + mpi_mul_hlp( i, A->p, X->p + j - 1, B->p[j - 1] ); + + X->s = A->s * B->s; + +cleanup: + + mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TA ); + + return( ret ); +} + +/* + * Baseline multiplication: X = A * b + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + + _B.s = 1; + _B.n = 1; + _B.p = p; + p[0] = b; + + return( mbedtls_mpi_mul_mpi( X, A, &_B ) ); +} + +/* + * Unsigned integer divide - double mbedtls_mpi_uint dividend, u1/u0, and + * mbedtls_mpi_uint divisor, d + */ +static mbedtls_mpi_uint mbedtls_int_div_int( mbedtls_mpi_uint u1, + mbedtls_mpi_uint u0, mbedtls_mpi_uint d, mbedtls_mpi_uint *r ) +{ +#if defined(MBEDTLS_HAVE_UDBL) + mbedtls_t_udbl dividend, quotient; +#else + const mbedtls_mpi_uint radix = (mbedtls_mpi_uint) 1 << biH; + const mbedtls_mpi_uint uint_halfword_mask = ( (mbedtls_mpi_uint) 1 << biH ) - 1; + mbedtls_mpi_uint d0, d1, q0, q1, rAX, r0, quotient; + mbedtls_mpi_uint u0_msw, u0_lsw; + size_t s; +#endif + + /* + * Check for overflow + */ + if( 0 == d || u1 >= d ) + { + if (r != NULL) *r = ~0; + + return ( ~0 ); + } + +#if defined(MBEDTLS_HAVE_UDBL) + dividend = (mbedtls_t_udbl) u1 << biL; + dividend |= (mbedtls_t_udbl) u0; + quotient = dividend / d; + if( quotient > ( (mbedtls_t_udbl) 1 << biL ) - 1 ) + quotient = ( (mbedtls_t_udbl) 1 << biL ) - 1; + + if( r != NULL ) + *r = (mbedtls_mpi_uint)( dividend - (quotient * d ) ); + + return (mbedtls_mpi_uint) quotient; +#else + + /* + * Algorithm D, Section 4.3.1 - The Art of Computer Programming + * Vol. 2 - Seminumerical Algorithms, Knuth + */ + + /* + * Normalize the divisor, d, and dividend, u0, u1 + */ + s = mbedtls_clz( d ); + d = d << s; + + u1 = u1 << s; + u1 |= ( u0 >> ( biL - s ) ) & ( -(mbedtls_mpi_sint)s >> ( biL - 1 ) ); + u0 = u0 << s; + + d1 = d >> biH; + d0 = d & uint_halfword_mask; + + u0_msw = u0 >> biH; + u0_lsw = u0 & uint_halfword_mask; + + /* + * Find the first quotient and remainder + */ + q1 = u1 / d1; + r0 = u1 - d1 * q1; + + while( q1 >= radix || ( q1 * d0 > radix * r0 + u0_msw ) ) + { + q1 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + rAX = ( u1 * radix ) + ( u0_msw - q1 * d ); + q0 = rAX / d1; + r0 = rAX - q0 * d1; + + while( q0 >= radix || ( q0 * d0 > radix * r0 + u0_lsw ) ) + { + q0 -= 1; + r0 += d1; + + if ( r0 >= radix ) break; + } + + if (r != NULL) + *r = ( rAX * radix + u0_lsw - q0 * d ) >> s; + + quotient = q1 * radix + q0; + + return quotient; +#endif +} + +/* + * Division by mbedtls_mpi: A = Q * B + R (HAC 14.20) + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t i, n, t, k; + mbedtls_mpi X, Y, Z, T1, T2; + + if( mbedtls_mpi_cmp_int( B, 0 ) == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); + + if( mbedtls_mpi_cmp_abs( A, B ) < 0 ) + { + if( Q != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_lset( Q, 0 ) ); + if( R != NULL ) MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, A ) ); + return( 0 ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &X, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, B ) ); + X.s = Y.s = 1; + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &Z, A->n + 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Z, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T1, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T2, 3 ) ); + + k = mbedtls_mpi_bitlen( &Y ) % biL; + if( k < biL - 1 ) + { + k = biL - 1 - k; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &X, k ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, k ) ); + } + else k = 0; + + n = X.n - 1; + t = Y.n - 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &Y, biL * ( n - t ) ) ); + + while( mbedtls_mpi_cmp_mpi( &X, &Y ) >= 0 ) + { + Z.p[n - t]++; + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &Y ) ); + } + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, biL * ( n - t ) ) ); + + for( i = n; i > t ; i-- ) + { + if( X.p[i] >= Y.p[t] ) + Z.p[i - t - 1] = ~0; + else + { + Z.p[i - t - 1] = mbedtls_int_div_int( X.p[i], X.p[i - 1], + Y.p[t], NULL); + } + + Z.p[i - t - 1]++; + do + { + Z.p[i - t - 1]--; + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T1, 0 ) ); + T1.p[0] = ( t < 1 ) ? 0 : Y.p[t - 1]; + T1.p[1] = Y.p[t]; + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &T2, 0 ) ); + T2.p[0] = ( i < 2 ) ? 0 : X.p[i - 2]; + T2.p[1] = ( i < 1 ) ? 0 : X.p[i - 1]; + T2.p[2] = X.p[i]; + } + while( mbedtls_mpi_cmp_mpi( &T1, &T2 ) > 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); + + if( mbedtls_mpi_cmp_int( &X, 0 ) < 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &T1, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T1, biL * ( i - t - 1 ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &X, &X, &T1 ) ); + Z.p[i - t - 1]--; + } + } + + if( Q != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( Q, &Z ) ); + Q->s = A->s * B->s; + } + + if( R != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &X, k ) ); + X.s = A->s; + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( R, &X ) ); + + if( mbedtls_mpi_cmp_int( R, 0 ) == 0 ) + R->s = 1; + } + +cleanup: + + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); + + return( ret ); +} + +/* + * Division by int: A = Q * b + R + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + mbedtls_mpi _B; + mbedtls_mpi_uint p[1]; + + p[0] = ( b < 0 ) ? -b : b; + _B.s = ( b < 0 ) ? -1 : 1; + _B.n = 1; + _B.p = p; + + return( mbedtls_mpi_div_mpi( Q, R, A, &_B ) ); +} + +/* + * Modulo: R = A mod B + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + + if( mbedtls_mpi_cmp_int( B, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( NULL, R, A, B ) ); + + while( mbedtls_mpi_cmp_int( R, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( R, R, B ) ); + + while( mbedtls_mpi_cmp_mpi( R, B ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( R, R, B ) ); + +cleanup: + + return( ret ); +} + +/* + * Modulo: r = A mod b + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ) +{ + size_t i; + mbedtls_mpi_uint x, y, z; + + if( b == 0 ) + return( MBEDTLS_ERR_MPI_DIVISION_BY_ZERO ); + + if( b < 0 ) + return( MBEDTLS_ERR_MPI_NEGATIVE_VALUE ); + + /* + * handle trivial cases + */ + if( b == 1 ) + { + *r = 0; + return( 0 ); + } + + if( b == 2 ) + { + *r = A->p[0] & 1; + return( 0 ); + } + + /* + * general case + */ + for( i = A->n, y = 0; i > 0; i-- ) + { + x = A->p[i - 1]; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + + x <<= biH; + y = ( y << biH ) | ( x >> biH ); + z = y / b; + y -= z * b; + } + + /* + * If A is negative, then the current y represents a negative value. + * Flipping it to the positive side. + */ + if( A->s < 0 && y != 0 ) + y = b - y; + + *r = y; + + return( 0 ); +} + +/* + * Fast Montgomery initialization (thanks to Tom St Denis) + */ +static void mpi_montg_init( mbedtls_mpi_uint *mm, const mbedtls_mpi *N ) +{ + mbedtls_mpi_uint x, m0 = N->p[0]; + unsigned int i; + + x = m0; + x += ( ( m0 + 2 ) & 4 ) << 1; + + for( i = biL; i >= 8; i /= 2 ) + x *= ( 2 - ( m0 * x ) ); + + *mm = ~x + 1; +} + +/* + * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) + */ +static int mpi_montmul( mbedtls_mpi *A, const mbedtls_mpi *B, const mbedtls_mpi *N, mbedtls_mpi_uint mm, + const mbedtls_mpi *T ) +{ + size_t i, n, m; + mbedtls_mpi_uint u0, u1, *d; + + if( T->n < N->n + 1 || T->p == NULL ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + memset( T->p, 0, T->n * ciL ); + + d = T->p; + n = N->n; + m = ( B->n < n ) ? B->n : n; + + for( i = 0; i < n; i++ ) + { + /* + * T = (T + u0*B + u1*N) / 2^biL + */ + u0 = A->p[i]; + u1 = ( d[0] + u0 * B->p[0] ) * mm; + + mpi_mul_hlp( m, B->p, d, u0 ); + mpi_mul_hlp( n, N->p, d, u1 ); + + *d++ = u0; d[n + 1] = 0; + } + + memcpy( A->p, d, ( n + 1 ) * ciL ); + + if( mbedtls_mpi_cmp_abs( A, N ) >= 0 ) + mpi_sub_hlp( n, N->p, A->p ); + else + /* prevent timing attacks */ + mpi_sub_hlp( n, A->p, T->p ); + + return( 0 ); +} + +/* + * Montgomery reduction: A = A * R^-1 mod N + */ +static int mpi_montred( mbedtls_mpi *A, const mbedtls_mpi *N, mbedtls_mpi_uint mm, const mbedtls_mpi *T ) +{ + mbedtls_mpi_uint z = 1; + mbedtls_mpi U; + + U.n = U.s = (int) z; + U.p = &z; + + return( mpi_montmul( A, &U, N, mm, T ) ); +} + +/* + * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ) +{ + int ret; + size_t wbits, wsize, one = 1; + size_t i, j, nblimbs; + size_t bufsize, nbits; + mbedtls_mpi_uint ei, mm, state; + mbedtls_mpi RR, T, W[ 2 << MBEDTLS_MPI_WINDOW_SIZE ], Apos; + int neg; + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || ( N->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( E, 0 ) < 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + /* + * Init temps and window size + */ + mpi_montg_init( &mm, N ); + mbedtls_mpi_init( &RR ); mbedtls_mpi_init( &T ); + mbedtls_mpi_init( &Apos ); + memset( W, 0, sizeof( W ) ); + + i = mbedtls_mpi_bitlen( E ); + + wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : + ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; + + if( wsize > MBEDTLS_MPI_WINDOW_SIZE ) + wsize = MBEDTLS_MPI_WINDOW_SIZE; + + j = N->n + 1; + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( X, j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[1], j ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &T, j * 2 ) ); + + /* + * Compensate for negative A (and correct at the end) + */ + neg = ( A->s == -1 ); + if( neg ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Apos, A ) ); + Apos.s = 1; + A = &Apos; + } + + /* + * If 1st call, pre-compute R^2 mod N + */ + if( _RR == NULL || _RR->p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &RR, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &RR, N->n * 2 * biL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &RR, &RR, N ) ); + + if( _RR != NULL ) + memcpy( _RR, &RR, sizeof( mbedtls_mpi ) ); + } + else + memcpy( &RR, _RR, sizeof( mbedtls_mpi ) ); + + /* + * W[1] = A * R^2 * R^-1 mod N = A * R mod N + */ + if( mbedtls_mpi_cmp_mpi( A, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &W[1], A, N ) ); + else + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[1], A ) ); + + MBEDTLS_MPI_CHK( mpi_montmul( &W[1], &RR, N, mm, &T ) ); + + /* + * X = R^2 * R^-1 mod N = R mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &RR ) ); + MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); + + if( wsize > 1 ) + { + /* + * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) + */ + j = one << ( wsize - 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[j], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[j], &W[1] ) ); + + for( i = 0; i < wsize - 1; i++ ) + MBEDTLS_MPI_CHK( mpi_montmul( &W[j], &W[j], N, mm, &T ) ); + + /* + * W[i] = W[i - 1] * W[1] + */ + for( i = j + 1; i < ( one << wsize ); i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( &W[i], N->n + 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &W[i], &W[i - 1] ) ); + + MBEDTLS_MPI_CHK( mpi_montmul( &W[i], &W[1], N, mm, &T ) ); + } + } + + nblimbs = E->n; + bufsize = 0; + nbits = 0; + wbits = 0; + state = 0; + + while( 1 ) + { + if( bufsize == 0 ) + { + if( nblimbs == 0 ) + break; + + nblimbs--; + + bufsize = sizeof( mbedtls_mpi_uint ) << 3; + } + + bufsize--; + + ei = (E->p[nblimbs] >> bufsize) & 1; + + /* + * skip leading 0s + */ + if( ei == 0 && state == 0 ) + continue; + + if( ei == 0 && state == 1 ) + { + /* + * out of window, square X + */ + MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + continue; + } + + /* + * add ei to current window + */ + state = 2; + + nbits++; + wbits |= ( ei << ( wsize - nbits ) ); + + if( nbits == wsize ) + { + /* + * X = X^wsize R^-1 mod N + */ + for( i = 0; i < wsize; i++ ) + MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + + /* + * X = X * W[wbits] R^-1 mod N + */ + MBEDTLS_MPI_CHK( mpi_montmul( X, &W[wbits], N, mm, &T ) ); + + state--; + nbits = 0; + wbits = 0; + } + } + + /* + * process the remaining bits + */ + for( i = 0; i < nbits; i++ ) + { + MBEDTLS_MPI_CHK( mpi_montmul( X, X, N, mm, &T ) ); + + wbits <<= 1; + + if( ( wbits & ( one << wsize ) ) != 0 ) + MBEDTLS_MPI_CHK( mpi_montmul( X, &W[1], N, mm, &T ) ); + } + + /* + * X = A^E * R * R^-1 mod N = A^E mod N + */ + MBEDTLS_MPI_CHK( mpi_montred( X, N, mm, &T ) ); + + if( neg && E->n != 0 && ( E->p[0] & 1 ) != 0 ) + { + X->s = -1; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( X, N, X ) ); + } + +cleanup: + + for( i = ( one << ( wsize - 1 ) ); i < ( one << wsize ); i++ ) + mbedtls_mpi_free( &W[i] ); + + mbedtls_mpi_free( &W[1] ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &Apos ); + + if( _RR == NULL || _RR->p == NULL ) + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Greatest common divisor: G = gcd(A, B) (HAC 14.54) + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ) +{ + int ret; + size_t lz, lzt; + mbedtls_mpi TG, TA, TB; + + mbedtls_mpi_init( &TG ); mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TA, A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, B ) ); + + lz = mbedtls_mpi_lsb( &TA ); + lzt = mbedtls_mpi_lsb( &TB ); + + if( lzt < lz ) + lz = lzt; + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, lz ) ); + + TA.s = TB.s = 1; + + while( mbedtls_mpi_cmp_int( &TA, 0 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, mbedtls_mpi_lsb( &TA ) ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, mbedtls_mpi_lsb( &TB ) ) ); + + if( mbedtls_mpi_cmp_mpi( &TA, &TB ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TA, &TA, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TA, 1 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &TB, &TB, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TB, 1 ) ); + } + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &TB, lz ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( G, &TB ) ); + +cleanup: + + mbedtls_mpi_free( &TG ); mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TB ); + + return( ret ); +} + +/* + * Fill X with size bytes of random. + * + * Use a temporary bytes representation to make sure the result is the same + * regardless of the platform endianness (useful when f_rng is actually + * deterministic, eg for tests). + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + if( size > MBEDTLS_MPI_MAX_SIZE ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( f_rng( p_rng, buf, size ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( X, buf, size ) ); + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + return( ret ); +} + +/* + * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ) +{ + int ret; + mbedtls_mpi G, TA, TU, U1, U2, TB, TV, V1, V2; + + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &TA ); mbedtls_mpi_init( &TU ); mbedtls_mpi_init( &U1 ); mbedtls_mpi_init( &U2 ); + mbedtls_mpi_init( &G ); mbedtls_mpi_init( &TB ); mbedtls_mpi_init( &TV ); + mbedtls_mpi_init( &V1 ); mbedtls_mpi_init( &V2 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, A, N ) ); + + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &TA, A, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TU, &TA ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TB, N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &TV, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &U2, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V1, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &V2, 1 ) ); + + do + { + while( ( TU.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TU, 1 ) ); + + if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &U1, &U1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &U2, 1 ) ); + } + + while( ( TV.p[0] & 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &TV, 1 ) ); + + if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, &TB ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &TA ) ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V1, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &V2, 1 ) ); + } + + if( mbedtls_mpi_cmp_mpi( &TU, &TV ) >= 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TU, &TU, &TV ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U1, &U1, &V1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U2, &U2, &V2 ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &TV, &TV, &TU ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, &U1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V2, &V2, &U2 ) ); + } + } + while( mbedtls_mpi_cmp_int( &TU, 0 ) != 0 ); + + while( mbedtls_mpi_cmp_int( &V1, 0 ) < 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &V1, &V1, N ) ); + + while( mbedtls_mpi_cmp_mpi( &V1, N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &V1, &V1, N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( X, &V1 ) ); + +cleanup: + + mbedtls_mpi_free( &TA ); mbedtls_mpi_free( &TU ); mbedtls_mpi_free( &U1 ); mbedtls_mpi_free( &U2 ); + mbedtls_mpi_free( &G ); mbedtls_mpi_free( &TB ); mbedtls_mpi_free( &TV ); + mbedtls_mpi_free( &V1 ); mbedtls_mpi_free( &V2 ); + + return( ret ); +} + +#if defined(MBEDTLS_GENPRIME) + +static const int small_prime[] = +{ + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251, 257, 263, 269, + 271, 277, 281, 283, 293, 307, 311, 313, + 317, 331, 337, 347, 349, 353, 359, 367, + 373, 379, 383, 389, 397, 401, 409, 419, + 421, 431, 433, 439, 443, 449, 457, 461, + 463, 467, 479, 487, 491, 499, 503, 509, + 521, 523, 541, 547, 557, 563, 569, 571, + 577, 587, 593, 599, 601, 607, 613, 617, + 619, 631, 641, 643, 647, 653, 659, 661, + 673, 677, 683, 691, 701, 709, 719, 727, + 733, 739, 743, 751, 757, 761, 769, 773, + 787, 797, 809, 811, 821, 823, 827, 829, + 839, 853, 857, 859, 863, 877, 881, 883, + 887, 907, 911, 919, 929, 937, 941, 947, + 953, 967, 971, 977, 983, 991, 997, -103 +}; + +/* + * Small divisors test (X must be positive) + * + * Return values: + * 0: no small factor (possible prime, more tests needed) + * 1: certain prime + * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE: certain non-prime + * other negative: error + */ +static int mpi_check_small_factors( const mbedtls_mpi *X ) +{ + int ret = 0; + size_t i; + mbedtls_mpi_uint r; + + if( ( X->p[0] & 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + for( i = 0; small_prime[i] > 0; i++ ) + { + if( mbedtls_mpi_cmp_int( X, small_prime[i] ) <= 0 ) + return( 1 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, small_prime[i] ) ); + + if( r == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + } + +cleanup: + return( ret ); +} + +/* + * Miller-Rabin pseudo-primality test (HAC 4.24) + */ +static int mpi_miller_rabin( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret, count; + size_t i, j, k, n, s; + mbedtls_mpi W, R, T, A, RR; + + mbedtls_mpi_init( &W ); mbedtls_mpi_init( &R ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &A ); + mbedtls_mpi_init( &RR ); + + /* + * W = |X| - 1 + * R = W >> lsb( W ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &W, X, 1 ) ); + s = mbedtls_mpi_lsb( &W ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R, &W ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &R, s ) ); + + i = mbedtls_mpi_bitlen( X ); + /* + * HAC, table 4.4 + */ + n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : + ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : + ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); + + for( i = 0; i < n; i++ ) + { + /* + * pick a random A, 1 < A < |X| - 1 + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + if( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 ) + { + j = mbedtls_mpi_bitlen( &A ) - mbedtls_mpi_bitlen( &W ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j + 1 ) ); + } + A.p[0] |= 3; + + count = 0; + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); + + j = mbedtls_mpi_bitlen( &A ); + k = mbedtls_mpi_bitlen( &W ); + if (j > k) { + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &A, j - k ) ); + } + + if (count++ > 30) { + return MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + } + + } while ( mbedtls_mpi_cmp_mpi( &A, &W ) >= 0 || + mbedtls_mpi_cmp_int( &A, 1 ) <= 0 ); + + /* + * A = A^R mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &A, &A, &R, X, &RR ) ); + + if( mbedtls_mpi_cmp_mpi( &A, &W ) == 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + continue; + + j = 1; + while( j < s && mbedtls_mpi_cmp_mpi( &A, &W ) != 0 ) + { + /* + * A = A * A mod |X| + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &A, &A ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &A, &T, X ) ); + + if( mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + break; + + j++; + } + + /* + * not prime if A != |X| - 1 or A == 1 + */ + if( mbedtls_mpi_cmp_mpi( &A, &W ) != 0 || + mbedtls_mpi_cmp_int( &A, 1 ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + break; + } + } + +cleanup: + mbedtls_mpi_free( &W ); mbedtls_mpi_free( &R ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &A ); + mbedtls_mpi_free( &RR ); + + return( ret ); +} + +/* + * Pseudo-primality test: small factors, then Miller-Rabin + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_mpi XX; + + XX.s = 1; + XX.n = X->n; + XX.p = X->p; + + if( mbedtls_mpi_cmp_int( &XX, 0 ) == 0 || + mbedtls_mpi_cmp_int( &XX, 1 ) == 0 ) + return( MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ); + + if( mbedtls_mpi_cmp_int( &XX, 2 ) == 0 ) + return( 0 ); + + if( ( ret = mpi_check_small_factors( &XX ) ) != 0 ) + { + if( ret == 1 ) + return( 0 ); + + return( ret ); + } + + return( mpi_miller_rabin( &XX, f_rng, p_rng ) ); +} + +/* + * Prime number generation + * + * If dh_flag is 0 and nbits is at least 1024, then the procedure + * follows the RSA probably-prime generation method of FIPS 186-4. + * NB. FIPS 186-4 only allows the specific bit lengths of 1024 and 1536. + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ +#ifdef MBEDTLS_HAVE_INT64 +// ceil(2^63.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f333f9de6485ULL +#else +// ceil(2^31.5) +#define CEIL_MAXUINT_DIV_SQRT2 0xb504f334U +#endif + int ret = MBEDTLS_ERR_MPI_NOT_ACCEPTABLE; + size_t k, n; + mbedtls_mpi_uint r; + mbedtls_mpi Y; + + if( nbits < 3 || nbits > MBEDTLS_MPI_MAX_BITS ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &Y ); + + n = BITS_TO_LIMBS( nbits ); + + while( 1 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); + /* make sure generated number is at least (nbits-1)+0.5 bits (FIPS 186-4 §B.3.3 steps 4.4, 5.5) */ + if( X->p[n-1] < CEIL_MAXUINT_DIV_SQRT2 ) continue; + + k = n * biL; + if( k > nbits ) MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( X, k - nbits ) ); + X->p[0] |= 1; + + if( dh_flag == 0 ) + { + ret = mbedtls_mpi_is_prime( X, f_rng, p_rng ); + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + } + else + { + /* + * An necessary condition for Y and X = 2Y + 1 to be prime + * is X = 2 mod 3 (which is equivalent to Y = 2 mod 3). + * Make sure it is satisfied, while keeping X = 3 mod 4 + */ + + X->p[0] |= 2; + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_int( &r, X, 3 ) ); + if( r == 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 8 ) ); + else if( r == 1 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 4 ) ); + + /* Set Y = (X-1) / 2, which is X / 2 because X is odd */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Y, X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Y, 1 ) ); + + while( 1 ) + { + /* + * First, check small factors for X and Y + * before doing Miller-Rabin on any of them + */ + if( ( ret = mpi_check_small_factors( X ) ) == 0 && + ( ret = mpi_check_small_factors( &Y ) ) == 0 && + ( ret = mpi_miller_rabin( X, f_rng, p_rng ) ) == 0 && + ( ret = mpi_miller_rabin( &Y, f_rng, p_rng ) ) == 0 ) + goto cleanup; + + if( ret != MBEDTLS_ERR_MPI_NOT_ACCEPTABLE ) + goto cleanup; + + /* + * Next candidates. We want to preserve Y = (X-1) / 2 and + * Y = 1 mod 2 and Y = 2 mod 3 (eq X = 3 mod 4 and X = 2 mod 3) + * so up Y by 6 and X by 12. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( X, X, 12 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &Y, &Y, 6 ) ); + } + } + } + +cleanup: + + mbedtls_mpi_free( &Y ); + + return( ret ); +} + +#endif /* MBEDTLS_GENPRIME */ + +#if defined(MBEDTLS_SELF_TEST) + +#define GCD_PAIR_COUNT 3 + +static const int gcd_pairs[GCD_PAIR_COUNT][3] = +{ + { 693, 609, 21 }, + { 1764, 868, 28 }, + { 768454923, 542167814, 1 } +}; + +/* + * Checkup routine + */ +int mbedtls_mpi_self_test( int verbose ) +{ + int ret, i; + mbedtls_mpi A, E, N, X, Y, U, V; + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &N ); mbedtls_mpi_init( &X ); + mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &U ); mbedtls_mpi_init( &V ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &A, 16, + "EFE021C2645FD1DC586E69184AF4A31E" \ + "D5F53E93B5F123FA41680867BA110131" \ + "944FE7952E2517337780CB0DB80E61AA" \ + "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &E, 16, + "B2E7EFD37075B9F03FF989C7C5051C20" \ + "34D2A323810251127E7BF8625A4F49A5" \ + "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ + "5B5C25763222FEFCCFC38B832366C29E" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &N, 16, + "0066A198186C18C10B2F5ED9B522752A" \ + "9830B69916E535C8F047518A889A43A5" \ + "94B6BED27A168D31D4A52F88925AA8F5" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "602AB7ECA597A3D6B56FF9829A5E8B85" \ + "9E857EA95A03512E2BAE7391688D264A" \ + "A5663B0341DB9CCFD2C4C5F421FEC814" \ + "8001B72E848A38CAE1C65F78E56ABDEF" \ + "E12D3C039B8A02D6BE593F0BBBDA56F1" \ + "ECF677152EF804370C1A305CAF3B5BF1" \ + "30879B56C61DE584A0F53A2447A51E" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #1 (mul_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &X, &Y, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "256567336059E52CAE22925474705F39A94" ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &V, 16, + "6613F26162223DF488E9CD48CC132C7A" \ + "0AC93C701B001B092E4E5B9F73BCD27B" \ + "9EE50D0657C77F374E903CDFA4C642" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #2 (div_mpi): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 || + mbedtls_mpi_cmp_mpi( &Y, &V ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &X, &A, &E, &N, NULL ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "36E139AEA55215609D2816998ED020BB" \ + "BD96C37890F65171D948E9BC7CBAA4D9" \ + "325D24D6A3C12710F10A09FA08AB87" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #3 (exp_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &X, &A, &N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &U, 16, + "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ + "C3DBA76456363A10869622EAC2DD84EC" \ + "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #4 (inv_mod): " ); + + if( mbedtls_mpi_cmp_mpi( &X, &U ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " MPI test #5 (simple gcd): " ); + + for( i = 0; i < GCD_PAIR_COUNT; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &X, gcd_pairs[i][0] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &Y, gcd_pairs[i][1] ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &A, &X, &Y ) ); + + if( mbedtls_mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed at %d\n", i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + + if( ret != 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); + + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &N ); mbedtls_mpi_free( &X ); + mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &U ); mbedtls_mpi_free( &V ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_BIGNUM_C */ diff --git a/common/mbedtls/bignum.h b/common/mbedtls/bignum.h new file mode 100644 index 000000000..00787908c --- /dev/null +++ b/common/mbedtls/bignum.h @@ -0,0 +1,774 @@ +/** + * \file bignum.h + * + * \brief Multi-precision integer library + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_BIGNUM_H +#define MBEDTLS_BIGNUM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#define MBEDTLS_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ +#define MBEDTLS_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ +#define MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ +#define MBEDTLS_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ +#define MBEDTLS_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ +#define MBEDTLS_ERR_MPI_ALLOC_FAILED -0x0010 /**< Memory allocation failed. */ + +#define MBEDTLS_MPI_CHK(f) do { if( ( ret = f ) != 0 ) goto cleanup; } while( 0 ) + +/* + * Maximum size MPIs are allowed to grow to in number of limbs. + */ +#define MBEDTLS_MPI_MAX_LIMBS 10000 + +#if !defined(MBEDTLS_MPI_WINDOW_SIZE) +/* + * Maximum window size used for modular exponentiation. Default: 6 + * Minimum value: 1. Maximum value: 6. + * + * Result is an array of ( 2 << MBEDTLS_MPI_WINDOW_SIZE ) MPIs used + * for the sliding window calculation. (So 64 by default) + * + * Reduction in size, reduces speed. + */ +#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +#endif /* !MBEDTLS_MPI_WINDOW_SIZE */ + +#if !defined(MBEDTLS_MPI_MAX_SIZE) +/* + * Maximum size of MPIs allowed in bits and bytes for user-MPIs. + * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) + * + * Note: Calculations can temporarily result in larger MPIs. So the number + * of limbs required (MBEDTLS_MPI_MAX_LIMBS) is higher. + */ +#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ +#endif /* !MBEDTLS_MPI_MAX_SIZE */ + +#define MBEDTLS_MPI_MAX_BITS ( 8 * MBEDTLS_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ + +/* + * When reading from files with mbedtls_mpi_read_file() and writing to files with + * mbedtls_mpi_write_file() the buffer should have space + * for a (short) label, the MPI (in the provided radix), the newline + * characters and the '\0'. + * + * By default we assume at least a 10 char label, a minimum radix of 10 + * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). + * Autosized at compile time for at least a 10 char label, a minimum radix + * of 10 (decimal) for a number of MBEDTLS_MPI_MAX_BITS size. + * + * This used to be statically sized to 1250 for a maximum of 4096 bit + * numbers (1234 decimal chars). + * + * Calculate using the formula: + * MBEDTLS_MPI_RW_BUFFER_SIZE = ceil(MBEDTLS_MPI_MAX_BITS / ln(10) * ln(2)) + + * LabelSize + 6 + */ +#define MBEDTLS_MPI_MAX_BITS_SCALE100 ( 100 * MBEDTLS_MPI_MAX_BITS ) +#define MBEDTLS_LN_2_DIV_LN_10_SCALE100 332 +#define MBEDTLS_MPI_RW_BUFFER_SIZE ( ((MBEDTLS_MPI_MAX_BITS_SCALE100 + MBEDTLS_LN_2_DIV_LN_10_SCALE100 - 1) / MBEDTLS_LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) + +/* + * Define the base integer type, architecture-wise. + * + * 32 or 64-bit integer types can be forced regardless of the underlying + * architecture by defining MBEDTLS_HAVE_INT32 or MBEDTLS_HAVE_INT64 + * respectively and undefining MBEDTLS_HAVE_ASM. + * + * Double-width integers (e.g. 128-bit in 64-bit architectures) can be + * disabled by defining MBEDTLS_NO_UDBL_DIVISION. + */ +#if !defined(MBEDTLS_HAVE_INT32) + #if defined(_MSC_VER) && defined(_M_AMD64) + /* Always choose 64-bit when using MSC */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #elif defined(__GNUC__) && ( \ + defined(__amd64__) || defined(__x86_64__) || \ + defined(__ppc64__) || defined(__powerpc64__) || \ + defined(__ia64__) || defined(__alpha__) || \ + ( defined(__sparc__) && defined(__arch64__) ) || \ + defined(__s390x__) || defined(__mips64) ) + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef unsigned int mbedtls_t_udbl __attribute__((mode(TI))); + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(__ARMCC_VERSION) && defined(__aarch64__) + /* + * __ARMCC_VERSION is defined for both armcc and armclang and + * __aarch64__ is only defined by armclang when compiling 64-bit code + */ + #if !defined(MBEDTLS_HAVE_INT64) + #define MBEDTLS_HAVE_INT64 + #endif /* !MBEDTLS_HAVE_INT64 */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + /* mbedtls_t_udbl defined as 128-bit unsigned int */ + typedef __uint128_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ + #elif defined(MBEDTLS_HAVE_INT64) + /* Force 64-bit integers with unknown compiler */ + typedef int64_t mbedtls_mpi_sint; + typedef uint64_t mbedtls_mpi_uint; + #endif +#endif /* !MBEDTLS_HAVE_INT32 */ + +#if !defined(MBEDTLS_HAVE_INT64) + /* Default to 32-bit compilation */ + #if !defined(MBEDTLS_HAVE_INT32) + #define MBEDTLS_HAVE_INT32 + #endif /* !MBEDTLS_HAVE_INT32 */ + typedef int32_t mbedtls_mpi_sint; + typedef uint32_t mbedtls_mpi_uint; + #if !defined(MBEDTLS_NO_UDBL_DIVISION) + typedef uint64_t mbedtls_t_udbl; + #define MBEDTLS_HAVE_UDBL + #endif /* !MBEDTLS_NO_UDBL_DIVISION */ +#endif /* !MBEDTLS_HAVE_INT64 */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief MPI structure + */ +typedef struct mbedtls_mpi +{ + int s; /*!< integer sign */ + size_t n; /*!< total # of limbs */ + mbedtls_mpi_uint *p; /*!< pointer to limbs */ +} +mbedtls_mpi; + +/** + * \brief Initialize one MPI (make internal references valid) + * This just makes it ready to be set or freed, + * but does not define a value for the MPI. + * + * \param X One MPI to initialize. + */ +void mbedtls_mpi_init( mbedtls_mpi *X ); + +/** + * \brief Unallocate one MPI + * + * \param X One MPI to unallocate. + */ +void mbedtls_mpi_free( mbedtls_mpi *X ); + +/** + * \brief Enlarge to the specified number of limbs + * + * This function does nothing if the MPI is already large enough. + * + * \param X MPI to grow + * \param nblimbs The target number of limbs + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_grow( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief Resize down, keeping at least the specified number of limbs + * + * If \c X is smaller than \c nblimbs, it is resized up + * instead. + * + * \param X MPI to shrink + * \param nblimbs The minimum number of limbs to keep + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * (this can only happen when resizing up). + */ +int mbedtls_mpi_shrink( mbedtls_mpi *X, size_t nblimbs ); + +/** + * \brief Copy the contents of Y into X + * + * \param X Destination MPI. It is enlarged if necessary. + * \param Y Source MPI. + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_copy( mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Swap the contents of X and Y + * + * \param X First MPI value + * \param Y Second MPI value + */ +void mbedtls_mpi_swap( mbedtls_mpi *X, mbedtls_mpi *Y ); + +/** + * \brief Safe conditional assignement X = Y if assign is 1 + * + * \param X MPI to conditionally assign to + * \param Y Value to be assigned + * \param assign 1: perform the assignment, 0: keep X's original value + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if( assign ) mbedtls_mpi_copy( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + */ +int mbedtls_mpi_safe_cond_assign( mbedtls_mpi *X, const mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Safe conditional swap X <-> Y if swap is 1 + * + * \param X First mbedtls_mpi value + * \param Y Second mbedtls_mpi value + * \param assign 1: perform the swap, 0: keep X and Y's original values + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * + * \note This function is equivalent to + * if( assign ) mbedtls_mpi_swap( X, Y ); + * except that it avoids leaking any information about whether + * the assignment was done or not (the above code may leak + * information through branch prediction and/or memory access + * patterns analysis). + */ +int mbedtls_mpi_safe_cond_swap( mbedtls_mpi *X, mbedtls_mpi *Y, unsigned char assign ); + +/** + * \brief Set value from integer + * + * \param X MPI to set + * \param z Value to use + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_lset( mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Get a specific bit from X + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * + * \return Either a 0 or a 1 + */ +int mbedtls_mpi_get_bit( const mbedtls_mpi *X, size_t pos ); + +/** + * \brief Set a bit of X to a specific value of 0 or 1 + * + * \note Will grow X if necessary to set a bit to 1 in a not yet + * existing limb. Will not grow if bit should be set to 0 + * + * \param X MPI to use + * \param pos Zero-based index of the bit in X + * \param val The value to set the bit to (0 or 1) + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 + */ +int mbedtls_mpi_set_bit( mbedtls_mpi *X, size_t pos, unsigned char val ); + +/** + * \brief Return the number of zero-bits before the least significant + * '1' bit + * + * Note: Thus also the zero-based index of the least significant '1' bit + * + * \param X MPI to use + */ +size_t mbedtls_mpi_lsb( const mbedtls_mpi *X ); + +/** + * \brief Return the number of bits up to and including the most + * significant '1' bit' + * + * Note: Thus also the one-based index of the most significant '1' bit + * + * \param X MPI to use + */ +size_t mbedtls_mpi_bitlen( const mbedtls_mpi *X ); + +/** + * \brief Return the total size in bytes + * + * \param X MPI to use + */ +size_t mbedtls_mpi_size( const mbedtls_mpi *X ); + +/** + * \brief Import from an ASCII string + * + * \param X Destination MPI + * \param radix Input numeric base + * \param s Null-terminated string buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + */ +int mbedtls_mpi_read_string( mbedtls_mpi *X, int radix, const char *s ); + +/** + * \brief Export into an ASCII string + * + * \param X Source MPI + * \param radix Output numeric base + * \param buf Buffer to write the string to + * \param buflen Length of buf + * \param olen Length of the string written, including final NUL byte + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code. + * *olen is always updated to reflect the amount + * of data that has (or would have) been written. + * + * \note Call this function with buflen = 0 to obtain the + * minimum required buffer size in *olen. + */ +int mbedtls_mpi_write_string( const mbedtls_mpi *X, int radix, + char *buf, size_t buflen, size_t *olen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Read MPI from a line in an opened file + * + * \param X Destination MPI + * \param radix Input numeric base + * \param fin Input file handle + * + * \return 0 if successful, MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if + * the file read buffer is too small or a + * MBEDTLS_ERR_MPI_XXX error code + * + * \note On success, this function advances the file stream + * to the end of the current line or to EOF. + * + * The function returns 0 on an empty line. + * + * Leading whitespaces are ignored, as is a + * '0x' prefix for radix 16. + * + */ +int mbedtls_mpi_read_file( mbedtls_mpi *X, int radix, FILE *fin ); + +/** + * \brief Write X into an opened file, or stdout if fout is NULL + * + * \param p Prefix, can be NULL + * \param X Source MPI + * \param radix Output numeric base + * \param fout Output file handle (can be NULL) + * + * \return 0 if successful, or a MBEDTLS_ERR_MPI_XXX error code + * + * \note Set fout == NULL to print X on the console. + */ +int mbedtls_mpi_write_file( const char *p, const mbedtls_mpi *X, int radix, FILE *fout ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Import X from unsigned binary data, big endian + * + * \param X Destination MPI + * \param buf Input buffer + * \param buflen Input buffer size + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_read_binary( mbedtls_mpi *X, const unsigned char *buf, size_t buflen ); + +/** + * \brief Export X into unsigned binary data, big endian. + * Always fills the whole buffer, which will start with zeros + * if the number is smaller. + * + * \param X Source MPI + * \param buf Output buffer + * \param buflen Output buffer size + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough + */ +int mbedtls_mpi_write_binary( const mbedtls_mpi *X, unsigned char *buf, size_t buflen ); + +/** + * \brief Left-shift: X <<= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shift_l( mbedtls_mpi *X, size_t count ); + +/** + * \brief Right-shift: X >>= count + * + * \param X MPI to shift + * \param count Amount to shift + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_shift_r( mbedtls_mpi *X, size_t count ); + +/** + * \brief Compare unsigned values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if |X| is greater than |Y|, + * -1 if |X| is lesser than |Y| or + * 0 if |X| is equal to |Y| + */ +int mbedtls_mpi_cmp_abs( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param Y Right-hand MPI + * + * \return 1 if X is greater than Y, + * -1 if X is lesser than Y or + * 0 if X is equal to Y + */ +int mbedtls_mpi_cmp_mpi( const mbedtls_mpi *X, const mbedtls_mpi *Y ); + +/** + * \brief Compare signed values + * + * \param X Left-hand MPI + * \param z The integer value to compare to + * + * \return 1 if X is greater than z, + * -1 if X is lesser than z or + * 0 if X is equal to z + */ +int mbedtls_mpi_cmp_int( const mbedtls_mpi *X, mbedtls_mpi_sint z ); + +/** + * \brief Unsigned addition: X = |A| + |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_add_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Unsigned subtraction: X = |A| - |B| + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B is greater than A + */ +int mbedtls_mpi_sub_abs( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Signed addition: X = A + B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_add_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Signed subtraction: X = A - B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_sub_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Signed addition: X = A + b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to add + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_add_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Signed subtraction: X = A - b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The integer value to subtract + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_sub_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Baseline multiplication: X = A * B + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_mul_mpi( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Baseline multiplication: X = A * b + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param b The unsigned integer value to multiply with + * + * \note b is unsigned + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_mul_int( mbedtls_mpi *X, const mbedtls_mpi *A, mbedtls_mpi_uint b ); + +/** + * \brief Division by mbedtls_mpi: A = Q * B + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0 + * + * \note Either Q or R can be NULL. + */ +int mbedtls_mpi_div_mpi( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Division by int: A = Q * b + R + * + * \param Q Destination MPI for the quotient + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0 + * + * \note Either Q or R can be NULL. + */ +int mbedtls_mpi_div_int( mbedtls_mpi *Q, mbedtls_mpi *R, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Modulo: R = A mod B + * + * \param R Destination MPI for the rest value + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if B == 0, + * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if B < 0 + */ +int mbedtls_mpi_mod_mpi( mbedtls_mpi *R, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Modulo: r = A mod b + * + * \param r Destination mbedtls_mpi_uint + * \param A Left-hand MPI + * \param b Integer to divide by + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_DIVISION_BY_ZERO if b == 0, + * MBEDTLS_ERR_MPI_NEGATIVE_VALUE if b < 0 + */ +int mbedtls_mpi_mod_int( mbedtls_mpi_uint *r, const mbedtls_mpi *A, mbedtls_mpi_sint b ); + +/** + * \brief Sliding-window exponentiation: X = A^E mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param E Exponent MPI + * \param N Modular MPI + * \param _RR Speed-up MPI used for recalculations + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is negative or even or + * if E is negative + * + * \note _RR is used to avoid re-computing R*R mod N across + * multiple calls, which speeds up things a bit. It can + * be set to NULL if the extra performance is unneeded. + */ +int mbedtls_mpi_exp_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *E, const mbedtls_mpi *N, mbedtls_mpi *_RR ); + +/** + * \brief Fill an MPI X with size bytes of random + * + * \param X Destination MPI + * \param size Size in bytes + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + * + * \note The bytes obtained from the PRNG are interpreted + * as a big-endian representation of an MPI; this can + * be relevant in applications like deterministic ECDSA. + */ +int mbedtls_mpi_fill_random( mbedtls_mpi *X, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Greatest common divisor: G = gcd(A, B) + * + * \param G Destination MPI + * \param A Left-hand MPI + * \param B Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed + */ +int mbedtls_mpi_gcd( mbedtls_mpi *G, const mbedtls_mpi *A, const mbedtls_mpi *B ); + +/** + * \brief Modular inverse: X = A^-1 mod N + * + * \param X Destination MPI + * \param A Left-hand MPI + * \param N Right-hand MPI + * + * \return 0 if successful, + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if N is <= 1, + MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N. + */ +int mbedtls_mpi_inv_mod( mbedtls_mpi *X, const mbedtls_mpi *A, const mbedtls_mpi *N ); + +/** + * \brief Miller-Rabin primality test + * + * \param X MPI to check + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_NOT_ACCEPTABLE if X is not prime + */ +int mbedtls_mpi_is_prime( const mbedtls_mpi *X, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Prime number generation + * + * \param X Destination MPI + * \param nbits Required size of X in bits + * ( 3 <= nbits <= MBEDTLS_MPI_MAX_BITS ) + * \param dh_flag If 1, then (X-1)/2 will be prime too + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 if successful (probably prime), + * MBEDTLS_ERR_MPI_ALLOC_FAILED if memory allocation failed, + * MBEDTLS_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 + */ +int mbedtls_mpi_gen_prime( mbedtls_mpi *X, size_t nbits, int dh_flag, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_mpi_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* bignum.h */ diff --git a/common/mbedtls/blowfish.c b/common/mbedtls/blowfish.c new file mode 100644 index 000000000..404d24e1f --- /dev/null +++ b/common/mbedtls/blowfish.c @@ -0,0 +1,654 @@ +/* + * Blowfish implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The Blowfish block cipher was designed by Bruce Schneier in 1993. + * http://www.schneier.com/blowfish.html + * http://en.wikipedia.org/wiki/Blowfish_%28cipher%29 + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + +#include "mbedtls/blowfish.h" +#include "mbedtls/platform_util.h" + +#include + +#if !defined(MBEDTLS_BLOWFISH_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +static const uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2] = { + 0x243F6A88L, 0x85A308D3L, 0x13198A2EL, 0x03707344L, + 0xA4093822L, 0x299F31D0L, 0x082EFA98L, 0xEC4E6C89L, + 0x452821E6L, 0x38D01377L, 0xBE5466CFL, 0x34E90C6CL, + 0xC0AC29B7L, 0xC97C50DDL, 0x3F84D5B5L, 0xB5470917L, + 0x9216D5D9L, 0x8979FB1BL +}; + +/* declarations of data at the end of this file */ +static const uint32_t S[4][256]; + +static uint32_t F( mbedtls_blowfish_context *ctx, uint32_t x ) +{ + unsigned short a, b, c, d; + uint32_t y; + + d = (unsigned short)(x & 0xFF); + x >>= 8; + c = (unsigned short)(x & 0xFF); + x >>= 8; + b = (unsigned short)(x & 0xFF); + x >>= 8; + a = (unsigned short)(x & 0xFF); + y = ctx->S[0][a] + ctx->S[1][b]; + y = y ^ ctx->S[2][c]; + y = y + ctx->S[3][d]; + + return( y ); +} + +static void blowfish_enc( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) +{ + uint32_t Xl, Xr, temp; + short i; + + Xl = *xl; + Xr = *xr; + + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS; ++i ) + { + Xl = Xl ^ ctx->P[i]; + Xr = F( ctx, Xl ) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS]; + Xl = Xl ^ ctx->P[MBEDTLS_BLOWFISH_ROUNDS + 1]; + + *xl = Xl; + *xr = Xr; +} + +static void blowfish_dec( mbedtls_blowfish_context *ctx, uint32_t *xl, uint32_t *xr ) +{ + uint32_t Xl, Xr, temp; + short i; + + Xl = *xl; + Xr = *xr; + + for( i = MBEDTLS_BLOWFISH_ROUNDS + 1; i > 1; --i ) + { + Xl = Xl ^ ctx->P[i]; + Xr = F( ctx, Xl ) ^ Xr; + + temp = Xl; + Xl = Xr; + Xr = temp; + } + + temp = Xl; + Xl = Xr; + Xr = temp; + + Xr = Xr ^ ctx->P[1]; + Xl = Xl ^ ctx->P[0]; + + *xl = Xl; + *xr = Xr; +} + +void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_blowfish_context ) ); +} + +void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_blowfish_context ) ); +} + +/* + * Blowfish key schedule + */ +int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + unsigned int i, j, k; + uint32_t data, datal, datar; + + if( keybits < MBEDTLS_BLOWFISH_MIN_KEY_BITS || keybits > MBEDTLS_BLOWFISH_MAX_KEY_BITS || + ( keybits % 8 ) ) + { + return( MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH ); + } + + keybits >>= 3; + + for( i = 0; i < 4; i++ ) + { + for( j = 0; j < 256; j++ ) + ctx->S[i][j] = S[i][j]; + } + + j = 0; + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; ++i ) + { + data = 0x00000000; + for( k = 0; k < 4; ++k ) + { + data = ( data << 8 ) | key[j++]; + if( j >= keybits ) + j = 0; + } + ctx->P[i] = P[i] ^ data; + } + + datal = 0x00000000; + datar = 0x00000000; + + for( i = 0; i < MBEDTLS_BLOWFISH_ROUNDS + 2; i += 2 ) + { + blowfish_enc( ctx, &datal, &datar ); + ctx->P[i] = datal; + ctx->P[i + 1] = datar; + } + + for( i = 0; i < 4; i++ ) + { + for( j = 0; j < 256; j += 2 ) + { + blowfish_enc( ctx, &datal, &datar ); + ctx->S[i][j] = datal; + ctx->S[i][j + 1] = datar; + } + } + return( 0 ); +} + +/* + * Blowfish-ECB block encryption/decryption + */ +int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, + int mode, + const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ) +{ + uint32_t X0, X1; + + GET_UINT32_BE( X0, input, 0 ); + GET_UINT32_BE( X1, input, 4 ); + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + blowfish_dec( ctx, &X0, &X1 ); + } + else /* MBEDTLS_BLOWFISH_ENCRYPT */ + { + blowfish_enc( ctx, &X0, &X1 ); + } + + PUT_UINT32_BE( X0, output, 0 ); + PUT_UINT32_BE( X1, output, 4 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * Blowfish-CBC buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[MBEDTLS_BLOWFISH_BLOCKSIZE]; + + if( length % MBEDTLS_BLOWFISH_BLOCKSIZE ) + return( MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, MBEDTLS_BLOWFISH_BLOCKSIZE ); + mbedtls_blowfish_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE;i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, MBEDTLS_BLOWFISH_BLOCKSIZE ); + + input += MBEDTLS_BLOWFISH_BLOCKSIZE; + output += MBEDTLS_BLOWFISH_BLOCKSIZE; + length -= MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < MBEDTLS_BLOWFISH_BLOCKSIZE; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_blowfish_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, MBEDTLS_BLOWFISH_BLOCKSIZE ); + + input += MBEDTLS_BLOWFISH_BLOCKSIZE; + output += MBEDTLS_BLOWFISH_BLOCKSIZE; + length -= MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * Blowfish CFB buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n = *iv_off; + + if( mode == MBEDTLS_BLOWFISH_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Blowfish CTR buffer encryption/decryption + */ +int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + mbedtls_blowfish_crypt_ecb( ctx, MBEDTLS_BLOWFISH_ENCRYPT, nonce_counter, + stream_block ); + + for( i = MBEDTLS_BLOWFISH_BLOCKSIZE; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) % MBEDTLS_BLOWFISH_BLOCKSIZE; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static const uint32_t S[4][256] = { + { 0xD1310BA6L, 0x98DFB5ACL, 0x2FFD72DBL, 0xD01ADFB7L, + 0xB8E1AFEDL, 0x6A267E96L, 0xBA7C9045L, 0xF12C7F99L, + 0x24A19947L, 0xB3916CF7L, 0x0801F2E2L, 0x858EFC16L, + 0x636920D8L, 0x71574E69L, 0xA458FEA3L, 0xF4933D7EL, + 0x0D95748FL, 0x728EB658L, 0x718BCD58L, 0x82154AEEL, + 0x7B54A41DL, 0xC25A59B5L, 0x9C30D539L, 0x2AF26013L, + 0xC5D1B023L, 0x286085F0L, 0xCA417918L, 0xB8DB38EFL, + 0x8E79DCB0L, 0x603A180EL, 0x6C9E0E8BL, 0xB01E8A3EL, + 0xD71577C1L, 0xBD314B27L, 0x78AF2FDAL, 0x55605C60L, + 0xE65525F3L, 0xAA55AB94L, 0x57489862L, 0x63E81440L, + 0x55CA396AL, 0x2AAB10B6L, 0xB4CC5C34L, 0x1141E8CEL, + 0xA15486AFL, 0x7C72E993L, 0xB3EE1411L, 0x636FBC2AL, + 0x2BA9C55DL, 0x741831F6L, 0xCE5C3E16L, 0x9B87931EL, + 0xAFD6BA33L, 0x6C24CF5CL, 0x7A325381L, 0x28958677L, + 0x3B8F4898L, 0x6B4BB9AFL, 0xC4BFE81BL, 0x66282193L, + 0x61D809CCL, 0xFB21A991L, 0x487CAC60L, 0x5DEC8032L, + 0xEF845D5DL, 0xE98575B1L, 0xDC262302L, 0xEB651B88L, + 0x23893E81L, 0xD396ACC5L, 0x0F6D6FF3L, 0x83F44239L, + 0x2E0B4482L, 0xA4842004L, 0x69C8F04AL, 0x9E1F9B5EL, + 0x21C66842L, 0xF6E96C9AL, 0x670C9C61L, 0xABD388F0L, + 0x6A51A0D2L, 0xD8542F68L, 0x960FA728L, 0xAB5133A3L, + 0x6EEF0B6CL, 0x137A3BE4L, 0xBA3BF050L, 0x7EFB2A98L, + 0xA1F1651DL, 0x39AF0176L, 0x66CA593EL, 0x82430E88L, + 0x8CEE8619L, 0x456F9FB4L, 0x7D84A5C3L, 0x3B8B5EBEL, + 0xE06F75D8L, 0x85C12073L, 0x401A449FL, 0x56C16AA6L, + 0x4ED3AA62L, 0x363F7706L, 0x1BFEDF72L, 0x429B023DL, + 0x37D0D724L, 0xD00A1248L, 0xDB0FEAD3L, 0x49F1C09BL, + 0x075372C9L, 0x80991B7BL, 0x25D479D8L, 0xF6E8DEF7L, + 0xE3FE501AL, 0xB6794C3BL, 0x976CE0BDL, 0x04C006BAL, + 0xC1A94FB6L, 0x409F60C4L, 0x5E5C9EC2L, 0x196A2463L, + 0x68FB6FAFL, 0x3E6C53B5L, 0x1339B2EBL, 0x3B52EC6FL, + 0x6DFC511FL, 0x9B30952CL, 0xCC814544L, 0xAF5EBD09L, + 0xBEE3D004L, 0xDE334AFDL, 0x660F2807L, 0x192E4BB3L, + 0xC0CBA857L, 0x45C8740FL, 0xD20B5F39L, 0xB9D3FBDBL, + 0x5579C0BDL, 0x1A60320AL, 0xD6A100C6L, 0x402C7279L, + 0x679F25FEL, 0xFB1FA3CCL, 0x8EA5E9F8L, 0xDB3222F8L, + 0x3C7516DFL, 0xFD616B15L, 0x2F501EC8L, 0xAD0552ABL, + 0x323DB5FAL, 0xFD238760L, 0x53317B48L, 0x3E00DF82L, + 0x9E5C57BBL, 0xCA6F8CA0L, 0x1A87562EL, 0xDF1769DBL, + 0xD542A8F6L, 0x287EFFC3L, 0xAC6732C6L, 0x8C4F5573L, + 0x695B27B0L, 0xBBCA58C8L, 0xE1FFA35DL, 0xB8F011A0L, + 0x10FA3D98L, 0xFD2183B8L, 0x4AFCB56CL, 0x2DD1D35BL, + 0x9A53E479L, 0xB6F84565L, 0xD28E49BCL, 0x4BFB9790L, + 0xE1DDF2DAL, 0xA4CB7E33L, 0x62FB1341L, 0xCEE4C6E8L, + 0xEF20CADAL, 0x36774C01L, 0xD07E9EFEL, 0x2BF11FB4L, + 0x95DBDA4DL, 0xAE909198L, 0xEAAD8E71L, 0x6B93D5A0L, + 0xD08ED1D0L, 0xAFC725E0L, 0x8E3C5B2FL, 0x8E7594B7L, + 0x8FF6E2FBL, 0xF2122B64L, 0x8888B812L, 0x900DF01CL, + 0x4FAD5EA0L, 0x688FC31CL, 0xD1CFF191L, 0xB3A8C1ADL, + 0x2F2F2218L, 0xBE0E1777L, 0xEA752DFEL, 0x8B021FA1L, + 0xE5A0CC0FL, 0xB56F74E8L, 0x18ACF3D6L, 0xCE89E299L, + 0xB4A84FE0L, 0xFD13E0B7L, 0x7CC43B81L, 0xD2ADA8D9L, + 0x165FA266L, 0x80957705L, 0x93CC7314L, 0x211A1477L, + 0xE6AD2065L, 0x77B5FA86L, 0xC75442F5L, 0xFB9D35CFL, + 0xEBCDAF0CL, 0x7B3E89A0L, 0xD6411BD3L, 0xAE1E7E49L, + 0x00250E2DL, 0x2071B35EL, 0x226800BBL, 0x57B8E0AFL, + 0x2464369BL, 0xF009B91EL, 0x5563911DL, 0x59DFA6AAL, + 0x78C14389L, 0xD95A537FL, 0x207D5BA2L, 0x02E5B9C5L, + 0x83260376L, 0x6295CFA9L, 0x11C81968L, 0x4E734A41L, + 0xB3472DCAL, 0x7B14A94AL, 0x1B510052L, 0x9A532915L, + 0xD60F573FL, 0xBC9BC6E4L, 0x2B60A476L, 0x81E67400L, + 0x08BA6FB5L, 0x571BE91FL, 0xF296EC6BL, 0x2A0DD915L, + 0xB6636521L, 0xE7B9F9B6L, 0xFF34052EL, 0xC5855664L, + 0x53B02D5DL, 0xA99F8FA1L, 0x08BA4799L, 0x6E85076AL }, + { 0x4B7A70E9L, 0xB5B32944L, 0xDB75092EL, 0xC4192623L, + 0xAD6EA6B0L, 0x49A7DF7DL, 0x9CEE60B8L, 0x8FEDB266L, + 0xECAA8C71L, 0x699A17FFL, 0x5664526CL, 0xC2B19EE1L, + 0x193602A5L, 0x75094C29L, 0xA0591340L, 0xE4183A3EL, + 0x3F54989AL, 0x5B429D65L, 0x6B8FE4D6L, 0x99F73FD6L, + 0xA1D29C07L, 0xEFE830F5L, 0x4D2D38E6L, 0xF0255DC1L, + 0x4CDD2086L, 0x8470EB26L, 0x6382E9C6L, 0x021ECC5EL, + 0x09686B3FL, 0x3EBAEFC9L, 0x3C971814L, 0x6B6A70A1L, + 0x687F3584L, 0x52A0E286L, 0xB79C5305L, 0xAA500737L, + 0x3E07841CL, 0x7FDEAE5CL, 0x8E7D44ECL, 0x5716F2B8L, + 0xB03ADA37L, 0xF0500C0DL, 0xF01C1F04L, 0x0200B3FFL, + 0xAE0CF51AL, 0x3CB574B2L, 0x25837A58L, 0xDC0921BDL, + 0xD19113F9L, 0x7CA92FF6L, 0x94324773L, 0x22F54701L, + 0x3AE5E581L, 0x37C2DADCL, 0xC8B57634L, 0x9AF3DDA7L, + 0xA9446146L, 0x0FD0030EL, 0xECC8C73EL, 0xA4751E41L, + 0xE238CD99L, 0x3BEA0E2FL, 0x3280BBA1L, 0x183EB331L, + 0x4E548B38L, 0x4F6DB908L, 0x6F420D03L, 0xF60A04BFL, + 0x2CB81290L, 0x24977C79L, 0x5679B072L, 0xBCAF89AFL, + 0xDE9A771FL, 0xD9930810L, 0xB38BAE12L, 0xDCCF3F2EL, + 0x5512721FL, 0x2E6B7124L, 0x501ADDE6L, 0x9F84CD87L, + 0x7A584718L, 0x7408DA17L, 0xBC9F9ABCL, 0xE94B7D8CL, + 0xEC7AEC3AL, 0xDB851DFAL, 0x63094366L, 0xC464C3D2L, + 0xEF1C1847L, 0x3215D908L, 0xDD433B37L, 0x24C2BA16L, + 0x12A14D43L, 0x2A65C451L, 0x50940002L, 0x133AE4DDL, + 0x71DFF89EL, 0x10314E55L, 0x81AC77D6L, 0x5F11199BL, + 0x043556F1L, 0xD7A3C76BL, 0x3C11183BL, 0x5924A509L, + 0xF28FE6EDL, 0x97F1FBFAL, 0x9EBABF2CL, 0x1E153C6EL, + 0x86E34570L, 0xEAE96FB1L, 0x860E5E0AL, 0x5A3E2AB3L, + 0x771FE71CL, 0x4E3D06FAL, 0x2965DCB9L, 0x99E71D0FL, + 0x803E89D6L, 0x5266C825L, 0x2E4CC978L, 0x9C10B36AL, + 0xC6150EBAL, 0x94E2EA78L, 0xA5FC3C53L, 0x1E0A2DF4L, + 0xF2F74EA7L, 0x361D2B3DL, 0x1939260FL, 0x19C27960L, + 0x5223A708L, 0xF71312B6L, 0xEBADFE6EL, 0xEAC31F66L, + 0xE3BC4595L, 0xA67BC883L, 0xB17F37D1L, 0x018CFF28L, + 0xC332DDEFL, 0xBE6C5AA5L, 0x65582185L, 0x68AB9802L, + 0xEECEA50FL, 0xDB2F953BL, 0x2AEF7DADL, 0x5B6E2F84L, + 0x1521B628L, 0x29076170L, 0xECDD4775L, 0x619F1510L, + 0x13CCA830L, 0xEB61BD96L, 0x0334FE1EL, 0xAA0363CFL, + 0xB5735C90L, 0x4C70A239L, 0xD59E9E0BL, 0xCBAADE14L, + 0xEECC86BCL, 0x60622CA7L, 0x9CAB5CABL, 0xB2F3846EL, + 0x648B1EAFL, 0x19BDF0CAL, 0xA02369B9L, 0x655ABB50L, + 0x40685A32L, 0x3C2AB4B3L, 0x319EE9D5L, 0xC021B8F7L, + 0x9B540B19L, 0x875FA099L, 0x95F7997EL, 0x623D7DA8L, + 0xF837889AL, 0x97E32D77L, 0x11ED935FL, 0x16681281L, + 0x0E358829L, 0xC7E61FD6L, 0x96DEDFA1L, 0x7858BA99L, + 0x57F584A5L, 0x1B227263L, 0x9B83C3FFL, 0x1AC24696L, + 0xCDB30AEBL, 0x532E3054L, 0x8FD948E4L, 0x6DBC3128L, + 0x58EBF2EFL, 0x34C6FFEAL, 0xFE28ED61L, 0xEE7C3C73L, + 0x5D4A14D9L, 0xE864B7E3L, 0x42105D14L, 0x203E13E0L, + 0x45EEE2B6L, 0xA3AAABEAL, 0xDB6C4F15L, 0xFACB4FD0L, + 0xC742F442L, 0xEF6ABBB5L, 0x654F3B1DL, 0x41CD2105L, + 0xD81E799EL, 0x86854DC7L, 0xE44B476AL, 0x3D816250L, + 0xCF62A1F2L, 0x5B8D2646L, 0xFC8883A0L, 0xC1C7B6A3L, + 0x7F1524C3L, 0x69CB7492L, 0x47848A0BL, 0x5692B285L, + 0x095BBF00L, 0xAD19489DL, 0x1462B174L, 0x23820E00L, + 0x58428D2AL, 0x0C55F5EAL, 0x1DADF43EL, 0x233F7061L, + 0x3372F092L, 0x8D937E41L, 0xD65FECF1L, 0x6C223BDBL, + 0x7CDE3759L, 0xCBEE7460L, 0x4085F2A7L, 0xCE77326EL, + 0xA6078084L, 0x19F8509EL, 0xE8EFD855L, 0x61D99735L, + 0xA969A7AAL, 0xC50C06C2L, 0x5A04ABFCL, 0x800BCADCL, + 0x9E447A2EL, 0xC3453484L, 0xFDD56705L, 0x0E1E9EC9L, + 0xDB73DBD3L, 0x105588CDL, 0x675FDA79L, 0xE3674340L, + 0xC5C43465L, 0x713E38D8L, 0x3D28F89EL, 0xF16DFF20L, + 0x153E21E7L, 0x8FB03D4AL, 0xE6E39F2BL, 0xDB83ADF7L }, + { 0xE93D5A68L, 0x948140F7L, 0xF64C261CL, 0x94692934L, + 0x411520F7L, 0x7602D4F7L, 0xBCF46B2EL, 0xD4A20068L, + 0xD4082471L, 0x3320F46AL, 0x43B7D4B7L, 0x500061AFL, + 0x1E39F62EL, 0x97244546L, 0x14214F74L, 0xBF8B8840L, + 0x4D95FC1DL, 0x96B591AFL, 0x70F4DDD3L, 0x66A02F45L, + 0xBFBC09ECL, 0x03BD9785L, 0x7FAC6DD0L, 0x31CB8504L, + 0x96EB27B3L, 0x55FD3941L, 0xDA2547E6L, 0xABCA0A9AL, + 0x28507825L, 0x530429F4L, 0x0A2C86DAL, 0xE9B66DFBL, + 0x68DC1462L, 0xD7486900L, 0x680EC0A4L, 0x27A18DEEL, + 0x4F3FFEA2L, 0xE887AD8CL, 0xB58CE006L, 0x7AF4D6B6L, + 0xAACE1E7CL, 0xD3375FECL, 0xCE78A399L, 0x406B2A42L, + 0x20FE9E35L, 0xD9F385B9L, 0xEE39D7ABL, 0x3B124E8BL, + 0x1DC9FAF7L, 0x4B6D1856L, 0x26A36631L, 0xEAE397B2L, + 0x3A6EFA74L, 0xDD5B4332L, 0x6841E7F7L, 0xCA7820FBL, + 0xFB0AF54EL, 0xD8FEB397L, 0x454056ACL, 0xBA489527L, + 0x55533A3AL, 0x20838D87L, 0xFE6BA9B7L, 0xD096954BL, + 0x55A867BCL, 0xA1159A58L, 0xCCA92963L, 0x99E1DB33L, + 0xA62A4A56L, 0x3F3125F9L, 0x5EF47E1CL, 0x9029317CL, + 0xFDF8E802L, 0x04272F70L, 0x80BB155CL, 0x05282CE3L, + 0x95C11548L, 0xE4C66D22L, 0x48C1133FL, 0xC70F86DCL, + 0x07F9C9EEL, 0x41041F0FL, 0x404779A4L, 0x5D886E17L, + 0x325F51EBL, 0xD59BC0D1L, 0xF2BCC18FL, 0x41113564L, + 0x257B7834L, 0x602A9C60L, 0xDFF8E8A3L, 0x1F636C1BL, + 0x0E12B4C2L, 0x02E1329EL, 0xAF664FD1L, 0xCAD18115L, + 0x6B2395E0L, 0x333E92E1L, 0x3B240B62L, 0xEEBEB922L, + 0x85B2A20EL, 0xE6BA0D99L, 0xDE720C8CL, 0x2DA2F728L, + 0xD0127845L, 0x95B794FDL, 0x647D0862L, 0xE7CCF5F0L, + 0x5449A36FL, 0x877D48FAL, 0xC39DFD27L, 0xF33E8D1EL, + 0x0A476341L, 0x992EFF74L, 0x3A6F6EABL, 0xF4F8FD37L, + 0xA812DC60L, 0xA1EBDDF8L, 0x991BE14CL, 0xDB6E6B0DL, + 0xC67B5510L, 0x6D672C37L, 0x2765D43BL, 0xDCD0E804L, + 0xF1290DC7L, 0xCC00FFA3L, 0xB5390F92L, 0x690FED0BL, + 0x667B9FFBL, 0xCEDB7D9CL, 0xA091CF0BL, 0xD9155EA3L, + 0xBB132F88L, 0x515BAD24L, 0x7B9479BFL, 0x763BD6EBL, + 0x37392EB3L, 0xCC115979L, 0x8026E297L, 0xF42E312DL, + 0x6842ADA7L, 0xC66A2B3BL, 0x12754CCCL, 0x782EF11CL, + 0x6A124237L, 0xB79251E7L, 0x06A1BBE6L, 0x4BFB6350L, + 0x1A6B1018L, 0x11CAEDFAL, 0x3D25BDD8L, 0xE2E1C3C9L, + 0x44421659L, 0x0A121386L, 0xD90CEC6EL, 0xD5ABEA2AL, + 0x64AF674EL, 0xDA86A85FL, 0xBEBFE988L, 0x64E4C3FEL, + 0x9DBC8057L, 0xF0F7C086L, 0x60787BF8L, 0x6003604DL, + 0xD1FD8346L, 0xF6381FB0L, 0x7745AE04L, 0xD736FCCCL, + 0x83426B33L, 0xF01EAB71L, 0xB0804187L, 0x3C005E5FL, + 0x77A057BEL, 0xBDE8AE24L, 0x55464299L, 0xBF582E61L, + 0x4E58F48FL, 0xF2DDFDA2L, 0xF474EF38L, 0x8789BDC2L, + 0x5366F9C3L, 0xC8B38E74L, 0xB475F255L, 0x46FCD9B9L, + 0x7AEB2661L, 0x8B1DDF84L, 0x846A0E79L, 0x915F95E2L, + 0x466E598EL, 0x20B45770L, 0x8CD55591L, 0xC902DE4CL, + 0xB90BACE1L, 0xBB8205D0L, 0x11A86248L, 0x7574A99EL, + 0xB77F19B6L, 0xE0A9DC09L, 0x662D09A1L, 0xC4324633L, + 0xE85A1F02L, 0x09F0BE8CL, 0x4A99A025L, 0x1D6EFE10L, + 0x1AB93D1DL, 0x0BA5A4DFL, 0xA186F20FL, 0x2868F169L, + 0xDCB7DA83L, 0x573906FEL, 0xA1E2CE9BL, 0x4FCD7F52L, + 0x50115E01L, 0xA70683FAL, 0xA002B5C4L, 0x0DE6D027L, + 0x9AF88C27L, 0x773F8641L, 0xC3604C06L, 0x61A806B5L, + 0xF0177A28L, 0xC0F586E0L, 0x006058AAL, 0x30DC7D62L, + 0x11E69ED7L, 0x2338EA63L, 0x53C2DD94L, 0xC2C21634L, + 0xBBCBEE56L, 0x90BCB6DEL, 0xEBFC7DA1L, 0xCE591D76L, + 0x6F05E409L, 0x4B7C0188L, 0x39720A3DL, 0x7C927C24L, + 0x86E3725FL, 0x724D9DB9L, 0x1AC15BB4L, 0xD39EB8FCL, + 0xED545578L, 0x08FCA5B5L, 0xD83D7CD3L, 0x4DAD0FC4L, + 0x1E50EF5EL, 0xB161E6F8L, 0xA28514D9L, 0x6C51133CL, + 0x6FD5C7E7L, 0x56E14EC4L, 0x362ABFCEL, 0xDDC6C837L, + 0xD79A3234L, 0x92638212L, 0x670EFA8EL, 0x406000E0L }, + { 0x3A39CE37L, 0xD3FAF5CFL, 0xABC27737L, 0x5AC52D1BL, + 0x5CB0679EL, 0x4FA33742L, 0xD3822740L, 0x99BC9BBEL, + 0xD5118E9DL, 0xBF0F7315L, 0xD62D1C7EL, 0xC700C47BL, + 0xB78C1B6BL, 0x21A19045L, 0xB26EB1BEL, 0x6A366EB4L, + 0x5748AB2FL, 0xBC946E79L, 0xC6A376D2L, 0x6549C2C8L, + 0x530FF8EEL, 0x468DDE7DL, 0xD5730A1DL, 0x4CD04DC6L, + 0x2939BBDBL, 0xA9BA4650L, 0xAC9526E8L, 0xBE5EE304L, + 0xA1FAD5F0L, 0x6A2D519AL, 0x63EF8CE2L, 0x9A86EE22L, + 0xC089C2B8L, 0x43242EF6L, 0xA51E03AAL, 0x9CF2D0A4L, + 0x83C061BAL, 0x9BE96A4DL, 0x8FE51550L, 0xBA645BD6L, + 0x2826A2F9L, 0xA73A3AE1L, 0x4BA99586L, 0xEF5562E9L, + 0xC72FEFD3L, 0xF752F7DAL, 0x3F046F69L, 0x77FA0A59L, + 0x80E4A915L, 0x87B08601L, 0x9B09E6ADL, 0x3B3EE593L, + 0xE990FD5AL, 0x9E34D797L, 0x2CF0B7D9L, 0x022B8B51L, + 0x96D5AC3AL, 0x017DA67DL, 0xD1CF3ED6L, 0x7C7D2D28L, + 0x1F9F25CFL, 0xADF2B89BL, 0x5AD6B472L, 0x5A88F54CL, + 0xE029AC71L, 0xE019A5E6L, 0x47B0ACFDL, 0xED93FA9BL, + 0xE8D3C48DL, 0x283B57CCL, 0xF8D56629L, 0x79132E28L, + 0x785F0191L, 0xED756055L, 0xF7960E44L, 0xE3D35E8CL, + 0x15056DD4L, 0x88F46DBAL, 0x03A16125L, 0x0564F0BDL, + 0xC3EB9E15L, 0x3C9057A2L, 0x97271AECL, 0xA93A072AL, + 0x1B3F6D9BL, 0x1E6321F5L, 0xF59C66FBL, 0x26DCF319L, + 0x7533D928L, 0xB155FDF5L, 0x03563482L, 0x8ABA3CBBL, + 0x28517711L, 0xC20AD9F8L, 0xABCC5167L, 0xCCAD925FL, + 0x4DE81751L, 0x3830DC8EL, 0x379D5862L, 0x9320F991L, + 0xEA7A90C2L, 0xFB3E7BCEL, 0x5121CE64L, 0x774FBE32L, + 0xA8B6E37EL, 0xC3293D46L, 0x48DE5369L, 0x6413E680L, + 0xA2AE0810L, 0xDD6DB224L, 0x69852DFDL, 0x09072166L, + 0xB39A460AL, 0x6445C0DDL, 0x586CDECFL, 0x1C20C8AEL, + 0x5BBEF7DDL, 0x1B588D40L, 0xCCD2017FL, 0x6BB4E3BBL, + 0xDDA26A7EL, 0x3A59FF45L, 0x3E350A44L, 0xBCB4CDD5L, + 0x72EACEA8L, 0xFA6484BBL, 0x8D6612AEL, 0xBF3C6F47L, + 0xD29BE463L, 0x542F5D9EL, 0xAEC2771BL, 0xF64E6370L, + 0x740E0D8DL, 0xE75B1357L, 0xF8721671L, 0xAF537D5DL, + 0x4040CB08L, 0x4EB4E2CCL, 0x34D2466AL, 0x0115AF84L, + 0xE1B00428L, 0x95983A1DL, 0x06B89FB4L, 0xCE6EA048L, + 0x6F3F3B82L, 0x3520AB82L, 0x011A1D4BL, 0x277227F8L, + 0x611560B1L, 0xE7933FDCL, 0xBB3A792BL, 0x344525BDL, + 0xA08839E1L, 0x51CE794BL, 0x2F32C9B7L, 0xA01FBAC9L, + 0xE01CC87EL, 0xBCC7D1F6L, 0xCF0111C3L, 0xA1E8AAC7L, + 0x1A908749L, 0xD44FBD9AL, 0xD0DADECBL, 0xD50ADA38L, + 0x0339C32AL, 0xC6913667L, 0x8DF9317CL, 0xE0B12B4FL, + 0xF79E59B7L, 0x43F5BB3AL, 0xF2D519FFL, 0x27D9459CL, + 0xBF97222CL, 0x15E6FC2AL, 0x0F91FC71L, 0x9B941525L, + 0xFAE59361L, 0xCEB69CEBL, 0xC2A86459L, 0x12BAA8D1L, + 0xB6C1075EL, 0xE3056A0CL, 0x10D25065L, 0xCB03A442L, + 0xE0EC6E0EL, 0x1698DB3BL, 0x4C98A0BEL, 0x3278E964L, + 0x9F1F9532L, 0xE0D392DFL, 0xD3A0342BL, 0x8971F21EL, + 0x1B0A7441L, 0x4BA3348CL, 0xC5BE7120L, 0xC37632D8L, + 0xDF359F8DL, 0x9B992F2EL, 0xE60B6F47L, 0x0FE3F11DL, + 0xE54CDA54L, 0x1EDAD891L, 0xCE6279CFL, 0xCD3E7E6FL, + 0x1618B166L, 0xFD2C1D05L, 0x848FD2C5L, 0xF6FB2299L, + 0xF523F357L, 0xA6327623L, 0x93A83531L, 0x56CCCD02L, + 0xACF08162L, 0x5A75EBB5L, 0x6E163697L, 0x88D273CCL, + 0xDE966292L, 0x81B949D0L, 0x4C50901BL, 0x71C65614L, + 0xE6C6C7BDL, 0x327A140AL, 0x45E1D006L, 0xC3F27B9AL, + 0xC9AA53FDL, 0x62A80F00L, 0xBB25BFE2L, 0x35BDD2F6L, + 0x71126905L, 0xB2040222L, 0xB6CBCF7CL, 0xCD769C2BL, + 0x53113EC0L, 0x1640E3D3L, 0x38ABBD60L, 0x2547ADF0L, + 0xBA38209CL, 0xF746CE76L, 0x77AFA1C5L, 0x20756060L, + 0x85CBFE4EL, 0x8AE88DD8L, 0x7AAAF9B0L, 0x4CF9AA7EL, + 0x1948C25CL, 0x02FB8A8CL, 0x01C36AE4L, 0xD6EBE1F9L, + 0x90D4F869L, 0xA65CDEA0L, 0x3F09252DL, 0xC208E69FL, + 0xB74E6132L, 0xCE77E25BL, 0x578FDFE3L, 0x3AC372E6L } +}; + +#endif /* !MBEDTLS_BLOWFISH_ALT */ +#endif /* MBEDTLS_BLOWFISH_C */ diff --git a/common/mbedtls/blowfish.h b/common/mbedtls/blowfish.h new file mode 100644 index 000000000..b63af8cdd --- /dev/null +++ b/common/mbedtls/blowfish.h @@ -0,0 +1,246 @@ +/** + * \file blowfish.h + * + * \brief Blowfish block cipher + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_BLOWFISH_H +#define MBEDTLS_BLOWFISH_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_BLOWFISH_ENCRYPT 1 +#define MBEDTLS_BLOWFISH_DECRYPT 0 +#define MBEDTLS_BLOWFISH_MAX_KEY_BITS 448 +#define MBEDTLS_BLOWFISH_MIN_KEY_BITS 32 +#define MBEDTLS_BLOWFISH_ROUNDS 16 /**< Rounds to use. When increasing this value, make sure to extend the initialisation vectors */ +#define MBEDTLS_BLOWFISH_BLOCKSIZE 8 /* Blowfish uses 64 bit blocks */ + +#define MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH -0x0016 /**< Invalid key length. */ +#define MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED -0x0017 /**< Blowfish hardware accelerator failed. */ +#define MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH -0x0018 /**< Invalid data input length. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_BLOWFISH_ALT) +// Regular implementation +// + +/** + * \brief Blowfish context structure + */ +typedef struct mbedtls_blowfish_context +{ + uint32_t P[MBEDTLS_BLOWFISH_ROUNDS + 2]; /*!< Blowfish round keys */ + uint32_t S[4][256]; /*!< key dependent S-boxes */ +} +mbedtls_blowfish_context; + +#else /* MBEDTLS_BLOWFISH_ALT */ +#include "blowfish_alt.h" +#endif /* MBEDTLS_BLOWFISH_ALT */ + +/** + * \brief Initialize Blowfish context + * + * \param ctx Blowfish context to be initialized + */ +void mbedtls_blowfish_init( mbedtls_blowfish_context *ctx ); + +/** + * \brief Clear Blowfish context + * + * \param ctx Blowfish context to be cleared + */ +void mbedtls_blowfish_free( mbedtls_blowfish_context *ctx ); + +/** + * \brief Blowfish key schedule + * + * \param ctx Blowfish context to be initialized + * \param key encryption key + * \param keybits must be between 32 and 448 bits + * + * \return 0 if successful, or MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH + */ +int mbedtls_blowfish_setkey( mbedtls_blowfish_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief Blowfish-ECB block encryption/decryption + * + * \param ctx Blowfish context + * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT + * \param input 8-byte input block + * \param output 8-byte output block + * + * \return 0 if successful + */ +int mbedtls_blowfish_crypt_ecb( mbedtls_blowfish_context *ctx, + int mode, + const unsigned char input[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char output[MBEDTLS_BLOWFISH_BLOCKSIZE] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief Blowfish-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (8 bytes) + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx Blowfish context + * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH + */ +int mbedtls_blowfish_crypt_cbc( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief Blowfish CFB buffer encryption/decryption. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx Blowfish context + * \param mode MBEDTLS_BLOWFISH_ENCRYPT or MBEDTLS_BLOWFISH_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful + */ +int mbedtls_blowfish_crypt_cfb64( mbedtls_blowfish_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /*MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief Blowfish-CTR buffer encryption/decryption + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**64 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 4 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 4 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**32 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. + * + * Note that for both stategies, sizes are measured in blocks and + * that a Blowfish block is 8 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx Blowfish context + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 64-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int mbedtls_blowfish_crypt_ctr( mbedtls_blowfish_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[MBEDTLS_BLOWFISH_BLOCKSIZE], + unsigned char stream_block[MBEDTLS_BLOWFISH_BLOCKSIZE], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#ifdef __cplusplus +} +#endif + +#endif /* blowfish.h */ diff --git a/common/mbedtls/bn_mul.h b/common/mbedtls/bn_mul.h new file mode 100644 index 000000000..ff0c9fe23 --- /dev/null +++ b/common/mbedtls/bn_mul.h @@ -0,0 +1,895 @@ +/** + * \file bn_mul.h + * + * \brief Multi-precision integer library + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * Multiply source vector [s] with b, add result + * to destination vector [d] and set carry c. + * + * Currently supports: + * + * . IA-32 (386+) . AMD64 / EM64T + * . IA-32 (SSE2) . Motorola 68000 + * . PowerPC, 32-bit . MicroBlaze + * . PowerPC, 64-bit . TriCore + * . SPARC v8 . ARM v3+ + * . Alpha . MIPS32 + * . C, longlong . C, generic + */ +#ifndef MBEDTLS_BN_MUL_H +#define MBEDTLS_BN_MUL_H + +#include "bignum.h" + +#if defined(MBEDTLS_HAVE_ASM) + +#ifndef asm +#define asm __asm +#endif + +/* armcc5 --gnu defines __GNUC__ but doesn't support GNU's extended asm */ +#if defined(__GNUC__) && \ + ( !defined(__ARMCC_VERSION) || __ARMCC_VERSION >= 6000000 ) + +/* + * Disable use of the i386 assembly code below if option -O0, to disable all + * compiler optimisations, is passed, detected with __OPTIMIZE__ + * This is done as the number of registers used in the assembly code doesn't + * work with the -O0 option. + */ +#if defined(__i386__) && defined(__OPTIMIZE__) + +#define MULADDC_INIT \ + asm( \ + "movl %%ebx, %0 \n\t" \ + "movl %5, %%esi \n\t" \ + "movl %6, %%edi \n\t" \ + "movl %7, %%ecx \n\t" \ + "movl %8, %%ebx \n\t" + +#define MULADDC_CORE \ + "lodsl \n\t" \ + "mull %%ebx \n\t" \ + "addl %%ecx, %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "addl (%%edi), %%eax \n\t" \ + "adcl $0, %%edx \n\t" \ + "movl %%edx, %%ecx \n\t" \ + "stosl \n\t" + +#if defined(MBEDTLS_HAVE_SSE2) + +#define MULADDC_HUIT \ + "movd %%ecx, %%mm1 \n\t" \ + "movd %%ebx, %%mm0 \n\t" \ + "movd (%%edi), %%mm3 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd (%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "movd 4(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "movd 8(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd 12(%%esi), %%mm7 \n\t" \ + "pmuludq %%mm0, %%mm7 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 4(%%edi), %%mm3 \n\t" \ + "paddq %%mm4, %%mm3 \n\t" \ + "movd 8(%%edi), %%mm5 \n\t" \ + "paddq %%mm6, %%mm5 \n\t" \ + "movd 12(%%edi), %%mm4 \n\t" \ + "paddq %%mm4, %%mm7 \n\t" \ + "movd %%mm1, (%%edi) \n\t" \ + "movd 16(%%esi), %%mm2 \n\t" \ + "pmuludq %%mm0, %%mm2 \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 20(%%esi), %%mm4 \n\t" \ + "pmuludq %%mm0, %%mm4 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd 24(%%esi), %%mm6 \n\t" \ + "pmuludq %%mm0, %%mm6 \n\t" \ + "movd %%mm1, 4(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd 28(%%esi), %%mm3 \n\t" \ + "pmuludq %%mm0, %%mm3 \n\t" \ + "paddq %%mm5, %%mm1 \n\t" \ + "movd 16(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm2 \n\t" \ + "movd %%mm1, 8(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm7, %%mm1 \n\t" \ + "movd 20(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm4 \n\t" \ + "movd %%mm1, 12(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm2, %%mm1 \n\t" \ + "movd 24(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm6 \n\t" \ + "movd %%mm1, 16(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm4, %%mm1 \n\t" \ + "movd 28(%%edi), %%mm5 \n\t" \ + "paddq %%mm5, %%mm3 \n\t" \ + "movd %%mm1, 20(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm6, %%mm1 \n\t" \ + "movd %%mm1, 24(%%edi) \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "paddq %%mm3, %%mm1 \n\t" \ + "movd %%mm1, 28(%%edi) \n\t" \ + "addl $32, %%edi \n\t" \ + "addl $32, %%esi \n\t" \ + "psrlq $32, %%mm1 \n\t" \ + "movd %%mm1, %%ecx \n\t" + +#define MULADDC_STOP \ + "emms \n\t" \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ + ); + +#else + +#define MULADDC_STOP \ + "movl %4, %%ebx \n\t" \ + "movl %%ecx, %1 \n\t" \ + "movl %%edi, %2 \n\t" \ + "movl %%esi, %3 \n\t" \ + : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ + : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ + : "eax", "ebx", "ecx", "edx", "esi", "edi" \ + ); +#endif /* SSE2 */ +#endif /* i386 */ + +#if defined(__amd64__) || defined (__x86_64__) + +#define MULADDC_INIT \ + asm( \ + "xorq %%r8, %%r8 \n\t" + +#define MULADDC_CORE \ + "movq (%%rsi), %%rax \n\t" \ + "mulq %%rbx \n\t" \ + "addq $8, %%rsi \n\t" \ + "addq %%rcx, %%rax \n\t" \ + "movq %%r8, %%rcx \n\t" \ + "adcq $0, %%rdx \n\t" \ + "nop \n\t" \ + "addq %%rax, (%%rdi) \n\t" \ + "adcq %%rdx, %%rcx \n\t" \ + "addq $8, %%rdi \n\t" + +#define MULADDC_STOP \ + : "+c" (c), "+D" (d), "+S" (s) \ + : "b" (b) \ + : "rax", "rdx", "r8" \ + ); + +#endif /* AMD64 */ + +#if defined(__mc68020__) || defined(__mcpu32__) + +#define MULADDC_INIT \ + asm( \ + "movl %3, %%a2 \n\t" \ + "movl %4, %%a3 \n\t" \ + "movl %5, %%d3 \n\t" \ + "movl %6, %%d2 \n\t" \ + "moveq #0, %%d0 \n\t" + +#define MULADDC_CORE \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "moveq #0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d4, %%d3 \n\t" + +#define MULADDC_STOP \ + "movl %%d3, %0 \n\t" \ + "movl %%a3, %1 \n\t" \ + "movl %%a2, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "d2", "d3", "d4", "a2", "a3" \ + ); + +#define MULADDC_HUIT \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d4:%%d1 \n\t" \ + "addxl %%d3, %%d1 \n\t" \ + "addxl %%d0, %%d4 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "movel %%a2@+, %%d1 \n\t" \ + "mulul %%d2, %%d3:%%d1 \n\t" \ + "addxl %%d4, %%d1 \n\t" \ + "addxl %%d0, %%d3 \n\t" \ + "addl %%d1, %%a3@+ \n\t" \ + "addxl %%d0, %%d3 \n\t" + +#endif /* MC68000 */ + +#if defined(__powerpc64__) || defined(__ppc64__) + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "ld r3, %3 \n\t" \ + "ld r4, %4 \n\t" \ + "ld r5, %5 \n\t" \ + "ld r6, %6 \n\t" \ + "addi r3, r3, -8 \n\t" \ + "addi r4, r4, -8 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu r7, 8(r3) \n\t" \ + "mulld r8, r7, r6 \n\t" \ + "mulhdu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "ld r7, 8(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stdu r8, 8(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 8 \n\t" \ + "addi r3, r3, 8 \n\t" \ + "std r5, %0 \n\t" \ + "std r4, %1 \n\t" \ + "std r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %%r3, %3 \n\t" \ + "ld %%r4, %4 \n\t" \ + "ld %%r5, %5 \n\t" \ + "ld %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -8 \n\t" \ + "addi %%r4, %%r4, -8 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "ldu %%r7, 8(%%r3) \n\t" \ + "mulld %%r8, %%r7, %%r6 \n\t" \ + "mulhdu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "ld %%r7, 8(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stdu %%r8, 8(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 8 \n\t" \ + "addi %%r3, %%r3, 8 \n\t" \ + "std %%r5, %0 \n\t" \ + "std %%r4, %1 \n\t" \ + "std %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#elif defined(__powerpc__) || defined(__ppc__) /* end PPC64/begin PPC32 */ + +#if defined(__MACH__) && defined(__APPLE__) + +#define MULADDC_INIT \ + asm( \ + "lwz r3, %3 \n\t" \ + "lwz r4, %4 \n\t" \ + "lwz r5, %5 \n\t" \ + "lwz r6, %6 \n\t" \ + "addi r3, r3, -4 \n\t" \ + "addi r4, r4, -4 \n\t" \ + "addic r5, r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu r7, 4(r3) \n\t" \ + "mullw r8, r7, r6 \n\t" \ + "mulhwu r9, r7, r6 \n\t" \ + "adde r8, r8, r5 \n\t" \ + "lwz r7, 4(r4) \n\t" \ + "addze r5, r9 \n\t" \ + "addc r8, r8, r7 \n\t" \ + "stwu r8, 4(r4) \n\t" + +#define MULADDC_STOP \ + "addze r5, r5 \n\t" \ + "addi r4, r4, 4 \n\t" \ + "addi r3, r3, 4 \n\t" \ + "stw r5, %0 \n\t" \ + "stw r4, %1 \n\t" \ + "stw r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#else /* __MACH__ && __APPLE__ */ + +#define MULADDC_INIT \ + asm( \ + "lwz %%r3, %3 \n\t" \ + "lwz %%r4, %4 \n\t" \ + "lwz %%r5, %5 \n\t" \ + "lwz %%r6, %6 \n\t" \ + "addi %%r3, %%r3, -4 \n\t" \ + "addi %%r4, %%r4, -4 \n\t" \ + "addic %%r5, %%r5, 0 \n\t" + +#define MULADDC_CORE \ + "lwzu %%r7, 4(%%r3) \n\t" \ + "mullw %%r8, %%r7, %%r6 \n\t" \ + "mulhwu %%r9, %%r7, %%r6 \n\t" \ + "adde %%r8, %%r8, %%r5 \n\t" \ + "lwz %%r7, 4(%%r4) \n\t" \ + "addze %%r5, %%r9 \n\t" \ + "addc %%r8, %%r8, %%r7 \n\t" \ + "stwu %%r8, 4(%%r4) \n\t" + +#define MULADDC_STOP \ + "addze %%r5, %%r5 \n\t" \ + "addi %%r4, %%r4, 4 \n\t" \ + "addi %%r3, %%r3, 4 \n\t" \ + "stw %%r5, %0 \n\t" \ + "stw %%r4, %1 \n\t" \ + "stw %%r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", "r9" \ + ); + +#endif /* __MACH__ && __APPLE__ */ + +#endif /* PPC32 */ + +/* + * The Sparc(64) assembly is reported to be broken. + * Disable it for now, until we're able to fix it. + */ +#if 0 && defined(__sparc__) +#if defined(__sparc64__) + +#define MULADDC_INIT \ + asm( \ + "ldx %3, %%o0 \n\t" \ + "ldx %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + + #define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "stx %%o1, %1 \n\t" \ + "stx %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#else /* __sparc64__ */ + +#define MULADDC_INIT \ + asm( \ + "ld %3, %%o0 \n\t" \ + "ld %4, %%o1 \n\t" \ + "ld %5, %%o2 \n\t" \ + "ld %6, %%o3 \n\t" + +#define MULADDC_CORE \ + "ld [%%o0], %%o4 \n\t" \ + "inc 4, %%o0 \n\t" \ + "ld [%%o1], %%o5 \n\t" \ + "umul %%o3, %%o4, %%o4 \n\t" \ + "addcc %%o4, %%o2, %%o4 \n\t" \ + "rd %%y, %%g1 \n\t" \ + "addx %%g1, 0, %%g1 \n\t" \ + "addcc %%o4, %%o5, %%o4 \n\t" \ + "st %%o4, [%%o1] \n\t" \ + "addx %%g1, 0, %%o2 \n\t" \ + "inc 4, %%o1 \n\t" + +#define MULADDC_STOP \ + "st %%o2, %0 \n\t" \ + "st %%o1, %1 \n\t" \ + "st %%o0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "g1", "o0", "o1", "o2", "o3", "o4", \ + "o5" \ + ); + +#endif /* __sparc64__ */ +#endif /* __sparc__ */ + +#if defined(__microblaze__) || defined(microblaze) + +#define MULADDC_INIT \ + asm( \ + "lwi r3, %3 \n\t" \ + "lwi r4, %4 \n\t" \ + "lwi r5, %5 \n\t" \ + "lwi r6, %6 \n\t" \ + "andi r7, r6, 0xffff \n\t" \ + "bsrli r6, r6, 16 \n\t" + +#define MULADDC_CORE \ + "lhui r8, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "lhui r9, r3, 0 \n\t" \ + "addi r3, r3, 2 \n\t" \ + "mul r10, r9, r6 \n\t" \ + "mul r11, r8, r7 \n\t" \ + "mul r12, r9, r7 \n\t" \ + "mul r13, r8, r6 \n\t" \ + "bsrli r8, r10, 16 \n\t" \ + "bsrli r9, r11, 16 \n\t" \ + "add r13, r13, r8 \n\t" \ + "add r13, r13, r9 \n\t" \ + "bslli r10, r10, 16 \n\t" \ + "bslli r11, r11, 16 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r11 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "lwi r10, r4, 0 \n\t" \ + "add r12, r12, r10 \n\t" \ + "addc r13, r13, r0 \n\t" \ + "add r12, r12, r5 \n\t" \ + "addc r5, r13, r0 \n\t" \ + "swi r12, r4, 0 \n\t" \ + "addi r4, r4, 4 \n\t" + +#define MULADDC_STOP \ + "swi r5, %0 \n\t" \ + "swi r4, %1 \n\t" \ + "swi r3, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r3", "r4", "r5", "r6", "r7", "r8", \ + "r9", "r10", "r11", "r12", "r13" \ + ); + +#endif /* MicroBlaze */ + +#if defined(__tricore__) + +#define MULADDC_INIT \ + asm( \ + "ld.a %%a2, %3 \n\t" \ + "ld.a %%a3, %4 \n\t" \ + "ld.w %%d4, %5 \n\t" \ + "ld.w %%d1, %6 \n\t" \ + "xor %%d5, %%d5 \n\t" + +#define MULADDC_CORE \ + "ld.w %%d0, [%%a2+] \n\t" \ + "madd.u %%e2, %%e4, %%d0, %%d1 \n\t" \ + "ld.w %%d0, [%%a3] \n\t" \ + "addx %%d2, %%d2, %%d0 \n\t" \ + "addc %%d3, %%d3, 0 \n\t" \ + "mov %%d4, %%d3 \n\t" \ + "st.w [%%a3+], %%d2 \n\t" + +#define MULADDC_STOP \ + "st.w %0, %%d4 \n\t" \ + "st.a %1, %%a3 \n\t" \ + "st.a %2, %%a2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "d0", "d1", "e2", "d4", "a2", "a3" \ + ); + +#endif /* TriCore */ + +/* + * gcc -O0 by default uses r7 for the frame pointer, so it complains about our + * use of r7 below, unless -fomit-frame-pointer is passed. Unfortunately, + * passing that option is not easy when building with yotta. + * + * On the other hand, -fomit-frame-pointer is implied by any -Ox options with + * x !=0, which we can detect using __OPTIMIZE__ (which is also defined by + * clang and armcc5 under the same conditions). + * + * So, only use the optimized assembly below for optimized build, which avoids + * the build error and is pretty reasonable anyway. + */ +#if defined(__GNUC__) && !defined(__OPTIMIZE__) +#define MULADDC_CANNOT_USE_R7 +#endif + +#if defined(__arm__) && !defined(MULADDC_CANNOT_USE_R7) + +#if defined(__thumb__) && !defined(__thumb2__) + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" \ + "lsr r7, r3, #16 \n\t" \ + "mov r9, r7 \n\t" \ + "lsl r7, r3, #16 \n\t" \ + "lsr r7, r7, #16 \n\t" \ + "mov r8, r7 \n\t" + +#define MULADDC_CORE \ + "ldmia r0!, {r6} \n\t" \ + "lsr r7, r6, #16 \n\t" \ + "lsl r6, r6, #16 \n\t" \ + "lsr r6, r6, #16 \n\t" \ + "mov r4, r8 \n\t" \ + "mul r4, r6 \n\t" \ + "mov r3, r9 \n\t" \ + "mul r6, r3 \n\t" \ + "mov r5, r9 \n\t" \ + "mul r5, r7 \n\t" \ + "mov r3, r8 \n\t" \ + "mul r7, r3 \n\t" \ + "lsr r3, r6, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "lsr r3, r7, #16 \n\t" \ + "add r5, r5, r3 \n\t" \ + "add r4, r4, r2 \n\t" \ + "mov r2, #0 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r6, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "lsl r3, r7, #16 \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r5, r2 \n\t" \ + "ldr r3, [r1] \n\t" \ + "add r4, r4, r3 \n\t" \ + "adc r2, r5 \n\t" \ + "stmia r1!, {r4} \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "r8", "r9", "cc" \ + ); + +#else + +#define MULADDC_INIT \ + asm( \ + "ldr r0, %3 \n\t" \ + "ldr r1, %4 \n\t" \ + "ldr r2, %5 \n\t" \ + "ldr r3, %6 \n\t" + +#define MULADDC_CORE \ + "ldr r4, [r0], #4 \n\t" \ + "mov r5, #0 \n\t" \ + "ldr r6, [r1] \n\t" \ + "umlal r2, r5, r3, r4 \n\t" \ + "adds r7, r6, r2 \n\t" \ + "adc r2, r5, #0 \n\t" \ + "str r7, [r1], #4 \n\t" + +#define MULADDC_STOP \ + "str r2, %0 \n\t" \ + "str r1, %1 \n\t" \ + "str r0, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "r0", "r1", "r2", "r3", "r4", "r5", \ + "r6", "r7", "cc" \ + ); + +#endif /* Thumb */ + +#endif /* ARMv3 */ + +#if defined(__alpha__) + +#define MULADDC_INIT \ + asm( \ + "ldq $1, %3 \n\t" \ + "ldq $2, %4 \n\t" \ + "ldq $3, %5 \n\t" \ + "ldq $4, %6 \n\t" + +#define MULADDC_CORE \ + "ldq $6, 0($1) \n\t" \ + "addq $1, 8, $1 \n\t" \ + "mulq $6, $4, $7 \n\t" \ + "umulh $6, $4, $6 \n\t" \ + "addq $7, $3, $7 \n\t" \ + "cmpult $7, $3, $3 \n\t" \ + "ldq $5, 0($2) \n\t" \ + "addq $7, $5, $7 \n\t" \ + "cmpult $7, $5, $5 \n\t" \ + "stq $7, 0($2) \n\t" \ + "addq $2, 8, $2 \n\t" \ + "addq $6, $3, $3 \n\t" \ + "addq $5, $3, $3 \n\t" + +#define MULADDC_STOP \ + "stq $3, %0 \n\t" \ + "stq $2, %1 \n\t" \ + "stq $1, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$1", "$2", "$3", "$4", "$5", "$6", "$7" \ + ); +#endif /* Alpha */ + +#if defined(__mips__) && !defined(__mips64) + +#define MULADDC_INIT \ + asm( \ + "lw $10, %3 \n\t" \ + "lw $11, %4 \n\t" \ + "lw $12, %5 \n\t" \ + "lw $13, %6 \n\t" + +#define MULADDC_CORE \ + "lw $14, 0($10) \n\t" \ + "multu $13, $14 \n\t" \ + "addi $10, $10, 4 \n\t" \ + "mflo $14 \n\t" \ + "mfhi $9 \n\t" \ + "addu $14, $12, $14 \n\t" \ + "lw $15, 0($11) \n\t" \ + "sltu $12, $14, $12 \n\t" \ + "addu $15, $14, $15 \n\t" \ + "sltu $14, $15, $14 \n\t" \ + "addu $12, $12, $9 \n\t" \ + "sw $15, 0($11) \n\t" \ + "addu $12, $12, $14 \n\t" \ + "addi $11, $11, 4 \n\t" + +#define MULADDC_STOP \ + "sw $12, %0 \n\t" \ + "sw $11, %1 \n\t" \ + "sw $10, %2 \n\t" \ + : "=m" (c), "=m" (d), "=m" (s) \ + : "m" (s), "m" (d), "m" (c), "m" (b) \ + : "$9", "$10", "$11", "$12", "$13", "$14", "$15" \ + ); + +#endif /* MIPS */ +#endif /* GNUC */ + +#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) + +#define MULADDC_INIT \ + __asm mov esi, s \ + __asm mov edi, d \ + __asm mov ecx, c \ + __asm mov ebx, b + +#define MULADDC_CORE \ + __asm lodsd \ + __asm mul ebx \ + __asm add eax, ecx \ + __asm adc edx, 0 \ + __asm add eax, [edi] \ + __asm adc edx, 0 \ + __asm mov ecx, edx \ + __asm stosd + +#if defined(MBEDTLS_HAVE_SSE2) + +#define EMIT __asm _emit + +#define MULADDC_HUIT \ + EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ + EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ + EMIT 0x0F EMIT 0x6E EMIT 0x1F \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x16 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ + EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ + EMIT 0x0F EMIT 0x7E EMIT 0x0F \ + EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ + EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ + EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ + EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ + EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ + EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ + EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ + EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ + EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ + EMIT 0x0F EMIT 0x7E EMIT 0xC9 + +#define MULADDC_STOP \ + EMIT 0x0F EMIT 0x77 \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#else + +#define MULADDC_STOP \ + __asm mov c, ecx \ + __asm mov d, edi \ + __asm mov s, esi \ + +#endif /* SSE2 */ +#endif /* MSVC */ + +#endif /* MBEDTLS_HAVE_ASM */ + +#if !defined(MULADDC_CORE) +#if defined(MBEDTLS_HAVE_UDBL) + +#define MULADDC_INIT \ +{ \ + mbedtls_t_udbl r; \ + mbedtls_mpi_uint r0, r1; + +#define MULADDC_CORE \ + r = *(s++) * (mbedtls_t_udbl) b; \ + r0 = (mbedtls_mpi_uint) r; \ + r1 = (mbedtls_mpi_uint)( r >> biL ); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#else +#define MULADDC_INIT \ +{ \ + mbedtls_mpi_uint s0, s1, b0, b1; \ + mbedtls_mpi_uint r0, r1, rx, ry; \ + b0 = ( b << biH ) >> biH; \ + b1 = ( b >> biH ); + +#define MULADDC_CORE \ + s0 = ( *s << biH ) >> biH; \ + s1 = ( *s >> biH ); s++; \ + rx = s0 * b1; r0 = s0 * b0; \ + ry = s1 * b0; r1 = s1 * b1; \ + r1 += ( rx >> biH ); \ + r1 += ( ry >> biH ); \ + rx <<= biH; ry <<= biH; \ + r0 += rx; r1 += (r0 < rx); \ + r0 += ry; r1 += (r0 < ry); \ + r0 += c; r1 += (r0 < c); \ + r0 += *d; r1 += (r0 < *d); \ + c = r1; *(d++) = r0; + +#define MULADDC_STOP \ +} + +#endif /* C (generic) */ +#endif /* C (longlong) */ + +#endif /* bn_mul.h */ diff --git a/common/mbedtls/camellia.c b/common/mbedtls/camellia.c new file mode 100644 index 000000000..3d9ae72c7 --- /dev/null +++ b/common/mbedtls/camellia.c @@ -0,0 +1,1070 @@ +/* + * Camellia implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The Camellia block cipher was designed by NTT and Mitsubishi Electric + * Corporation. + * + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/01espec.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CAMELLIA_C) + +#include "mbedtls/camellia.h" +#include "mbedtls/platform_util.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 */ + +#if !defined(MBEDTLS_CAMELLIA_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +static const unsigned char SIGMA_CHARS[6][8] = +{ + { 0xa0, 0x9e, 0x66, 0x7f, 0x3b, 0xcc, 0x90, 0x8b }, + { 0xb6, 0x7a, 0xe8, 0x58, 0x4c, 0xaa, 0x73, 0xb2 }, + { 0xc6, 0xef, 0x37, 0x2f, 0xe9, 0x4f, 0x82, 0xbe }, + { 0x54, 0xff, 0x53, 0xa5, 0xf1, 0xd3, 0x6f, 0x1c }, + { 0x10, 0xe5, 0x27, 0xfa, 0xde, 0x68, 0x2d, 0x1d }, + { 0xb0, 0x56, 0x88, 0xc2, 0xb3, 0xe6, 0xc1, 0xfd } +}; + +#if defined(MBEDTLS_CAMELLIA_SMALL_MEMORY) + +static const unsigned char FSb[256] = +{ + 112,130, 44,236,179, 39,192,229,228,133, 87, 53,234, 12,174, 65, + 35,239,107,147, 69, 25,165, 33,237, 14, 79, 78, 29,101,146,189, + 134,184,175,143,124,235, 31,206, 62, 48,220, 95, 94,197, 11, 26, + 166,225, 57,202,213, 71, 93, 61,217, 1, 90,214, 81, 86,108, 77, + 139, 13,154,102,251,204,176, 45,116, 18, 43, 32,240,177,132,153, + 223, 76,203,194, 52,126,118, 5,109,183,169, 49,209, 23, 4,215, + 20, 88, 58, 97,222, 27, 17, 28, 50, 15,156, 22, 83, 24,242, 34, + 254, 68,207,178,195,181,122,145, 36, 8,232,168, 96,252,105, 80, + 170,208,160,125,161,137, 98,151, 84, 91, 30,149,224,255,100,210, + 16,196, 0, 72,163,247,117,219,138, 3,230,218, 9, 63,221,148, + 135, 92,131, 2,205, 74,144, 51,115,103,246,243,157,127,191,226, + 82,155,216, 38,200, 55,198, 59,129,150,111, 75, 19,190, 99, 46, + 233,121,167,140,159,110,188,142, 41,245,249,182, 47,253,180, 89, + 120,152, 6,106,231, 70,113,186,212, 37,171, 66,136,162,141,250, + 114, 7,185, 85,248,238,172, 10, 54, 73, 42,104, 60, 56,241,164, + 64, 40,211,123,187,201, 67,193, 21,227,173,244,119,199,128,158 +}; + +#define SBOX1(n) FSb[(n)] +#define SBOX2(n) (unsigned char)((FSb[(n)] >> 7 ^ FSb[(n)] << 1) & 0xff) +#define SBOX3(n) (unsigned char)((FSb[(n)] >> 1 ^ FSb[(n)] << 7) & 0xff) +#define SBOX4(n) FSb[((n) << 1 ^ (n) >> 7) &0xff] + +#else /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ + +static const unsigned char FSb[256] = +{ + 112, 130, 44, 236, 179, 39, 192, 229, 228, 133, 87, 53, 234, 12, 174, 65, + 35, 239, 107, 147, 69, 25, 165, 33, 237, 14, 79, 78, 29, 101, 146, 189, + 134, 184, 175, 143, 124, 235, 31, 206, 62, 48, 220, 95, 94, 197, 11, 26, + 166, 225, 57, 202, 213, 71, 93, 61, 217, 1, 90, 214, 81, 86, 108, 77, + 139, 13, 154, 102, 251, 204, 176, 45, 116, 18, 43, 32, 240, 177, 132, 153, + 223, 76, 203, 194, 52, 126, 118, 5, 109, 183, 169, 49, 209, 23, 4, 215, + 20, 88, 58, 97, 222, 27, 17, 28, 50, 15, 156, 22, 83, 24, 242, 34, + 254, 68, 207, 178, 195, 181, 122, 145, 36, 8, 232, 168, 96, 252, 105, 80, + 170, 208, 160, 125, 161, 137, 98, 151, 84, 91, 30, 149, 224, 255, 100, 210, + 16, 196, 0, 72, 163, 247, 117, 219, 138, 3, 230, 218, 9, 63, 221, 148, + 135, 92, 131, 2, 205, 74, 144, 51, 115, 103, 246, 243, 157, 127, 191, 226, + 82, 155, 216, 38, 200, 55, 198, 59, 129, 150, 111, 75, 19, 190, 99, 46, + 233, 121, 167, 140, 159, 110, 188, 142, 41, 245, 249, 182, 47, 253, 180, 89, + 120, 152, 6, 106, 231, 70, 113, 186, 212, 37, 171, 66, 136, 162, 141, 250, + 114, 7, 185, 85, 248, 238, 172, 10, 54, 73, 42, 104, 60, 56, 241, 164, + 64, 40, 211, 123, 187, 201, 67, 193, 21, 227, 173, 244, 119, 199, 128, 158 +}; + +static const unsigned char FSb2[256] = +{ + 224, 5, 88, 217, 103, 78, 129, 203, 201, 11, 174, 106, 213, 24, 93, 130, + 70, 223, 214, 39, 138, 50, 75, 66, 219, 28, 158, 156, 58, 202, 37, 123, + 13, 113, 95, 31, 248, 215, 62, 157, 124, 96, 185, 190, 188, 139, 22, 52, + 77, 195, 114, 149, 171, 142, 186, 122, 179, 2, 180, 173, 162, 172, 216, 154, + 23, 26, 53, 204, 247, 153, 97, 90, 232, 36, 86, 64, 225, 99, 9, 51, + 191, 152, 151, 133, 104, 252, 236, 10, 218, 111, 83, 98, 163, 46, 8, 175, + 40, 176, 116, 194, 189, 54, 34, 56, 100, 30, 57, 44, 166, 48, 229, 68, + 253, 136, 159, 101, 135, 107, 244, 35, 72, 16, 209, 81, 192, 249, 210, 160, + 85, 161, 65, 250, 67, 19, 196, 47, 168, 182, 60, 43, 193, 255, 200, 165, + 32, 137, 0, 144, 71, 239, 234, 183, 21, 6, 205, 181, 18, 126, 187, 41, + 15, 184, 7, 4, 155, 148, 33, 102, 230, 206, 237, 231, 59, 254, 127, 197, + 164, 55, 177, 76, 145, 110, 141, 118, 3, 45, 222, 150, 38, 125, 198, 92, + 211, 242, 79, 25, 63, 220, 121, 29, 82, 235, 243, 109, 94, 251, 105, 178, + 240, 49, 12, 212, 207, 140, 226, 117, 169, 74, 87, 132, 17, 69, 27, 245, + 228, 14, 115, 170, 241, 221, 89, 20, 108, 146, 84, 208, 120, 112, 227, 73, + 128, 80, 167, 246, 119, 147, 134, 131, 42, 199, 91, 233, 238, 143, 1, 61 +}; + +static const unsigned char FSb3[256] = +{ + 56, 65, 22, 118, 217, 147, 96, 242, 114, 194, 171, 154, 117, 6, 87, 160, + 145, 247, 181, 201, 162, 140, 210, 144, 246, 7, 167, 39, 142, 178, 73, 222, + 67, 92, 215, 199, 62, 245, 143, 103, 31, 24, 110, 175, 47, 226, 133, 13, + 83, 240, 156, 101, 234, 163, 174, 158, 236, 128, 45, 107, 168, 43, 54, 166, + 197, 134, 77, 51, 253, 102, 88, 150, 58, 9, 149, 16, 120, 216, 66, 204, + 239, 38, 229, 97, 26, 63, 59, 130, 182, 219, 212, 152, 232, 139, 2, 235, + 10, 44, 29, 176, 111, 141, 136, 14, 25, 135, 78, 11, 169, 12, 121, 17, + 127, 34, 231, 89, 225, 218, 61, 200, 18, 4, 116, 84, 48, 126, 180, 40, + 85, 104, 80, 190, 208, 196, 49, 203, 42, 173, 15, 202, 112, 255, 50, 105, + 8, 98, 0, 36, 209, 251, 186, 237, 69, 129, 115, 109, 132, 159, 238, 74, + 195, 46, 193, 1, 230, 37, 72, 153, 185, 179, 123, 249, 206, 191, 223, 113, + 41, 205, 108, 19, 100, 155, 99, 157, 192, 75, 183, 165, 137, 95, 177, 23, + 244, 188, 211, 70, 207, 55, 94, 71, 148, 250, 252, 91, 151, 254, 90, 172, + 60, 76, 3, 53, 243, 35, 184, 93, 106, 146, 213, 33, 68, 81, 198, 125, + 57, 131, 220, 170, 124, 119, 86, 5, 27, 164, 21, 52, 30, 28, 248, 82, + 32, 20, 233, 189, 221, 228, 161, 224, 138, 241, 214, 122, 187, 227, 64, 79 +}; + +static const unsigned char FSb4[256] = +{ + 112, 44, 179, 192, 228, 87, 234, 174, 35, 107, 69, 165, 237, 79, 29, 146, + 134, 175, 124, 31, 62, 220, 94, 11, 166, 57, 213, 93, 217, 90, 81, 108, + 139, 154, 251, 176, 116, 43, 240, 132, 223, 203, 52, 118, 109, 169, 209, 4, + 20, 58, 222, 17, 50, 156, 83, 242, 254, 207, 195, 122, 36, 232, 96, 105, + 170, 160, 161, 98, 84, 30, 224, 100, 16, 0, 163, 117, 138, 230, 9, 221, + 135, 131, 205, 144, 115, 246, 157, 191, 82, 216, 200, 198, 129, 111, 19, 99, + 233, 167, 159, 188, 41, 249, 47, 180, 120, 6, 231, 113, 212, 171, 136, 141, + 114, 185, 248, 172, 54, 42, 60, 241, 64, 211, 187, 67, 21, 173, 119, 128, + 130, 236, 39, 229, 133, 53, 12, 65, 239, 147, 25, 33, 14, 78, 101, 189, + 184, 143, 235, 206, 48, 95, 197, 26, 225, 202, 71, 61, 1, 214, 86, 77, + 13, 102, 204, 45, 18, 32, 177, 153, 76, 194, 126, 5, 183, 49, 23, 215, + 88, 97, 27, 28, 15, 22, 24, 34, 68, 178, 181, 145, 8, 168, 252, 80, + 208, 125, 137, 151, 91, 149, 255, 210, 196, 72, 247, 219, 3, 218, 63, 148, + 92, 2, 74, 51, 103, 243, 127, 226, 155, 38, 55, 59, 150, 75, 190, 46, + 121, 140, 110, 142, 245, 182, 253, 89, 152, 106, 70, 186, 37, 66, 162, 250, + 7, 85, 238, 10, 73, 104, 56, 164, 40, 123, 201, 193, 227, 244, 199, 158 +}; + +#define SBOX1(n) FSb[(n)] +#define SBOX2(n) FSb2[(n)] +#define SBOX3(n) FSb3[(n)] +#define SBOX4(n) FSb4[(n)] + +#endif /* MBEDTLS_CAMELLIA_SMALL_MEMORY */ + +static const unsigned char shifts[2][4][4] = +{ + { + { 1, 1, 1, 1 }, /* KL */ + { 0, 0, 0, 0 }, /* KR */ + { 1, 1, 1, 1 }, /* KA */ + { 0, 0, 0, 0 } /* KB */ + }, + { + { 1, 0, 1, 1 }, /* KL */ + { 1, 1, 0, 1 }, /* KR */ + { 1, 1, 1, 0 }, /* KA */ + { 1, 1, 0, 1 } /* KB */ + } +}; + +static const signed char indexes[2][4][20] = +{ + { + { 0, 1, 2, 3, 8, 9, 10, 11, 38, 39, + 36, 37, 23, 20, 21, 22, 27, -1, -1, 26 }, /* KL -> RK */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }, /* KR -> RK */ + { 4, 5, 6, 7, 12, 13, 14, 15, 16, 17, + 18, 19, -1, 24, 25, -1, 31, 28, 29, 30 }, /* KA -> RK */ + { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 } /* KB -> RK */ + }, + { + { 0, 1, 2, 3, 61, 62, 63, 60, -1, -1, + -1, -1, 27, 24, 25, 26, 35, 32, 33, 34 }, /* KL -> RK */ + { -1, -1, -1, -1, 8, 9, 10, 11, 16, 17, + 18, 19, -1, -1, -1, -1, 39, 36, 37, 38 }, /* KR -> RK */ + { -1, -1, -1, -1, 12, 13, 14, 15, 58, 59, + 56, 57, 31, 28, 29, 30, -1, -1, -1, -1 }, /* KA -> RK */ + { 4, 5, 6, 7, 65, 66, 67, 64, 20, 21, + 22, 23, -1, -1, -1, -1, 43, 40, 41, 42 } /* KB -> RK */ + } +}; + +static const signed char transposes[2][20] = +{ + { + 21, 22, 23, 20, + -1, -1, -1, -1, + 18, 19, 16, 17, + 11, 8, 9, 10, + 15, 12, 13, 14 + }, + { + 25, 26, 27, 24, + 29, 30, 31, 28, + 18, 19, 16, 17, + -1, -1, -1, -1, + -1, -1, -1, -1 + } +}; + +/* Shift macro for 128 bit strings with rotation smaller than 32 bits (!) */ +#define ROTL(DEST, SRC, SHIFT) \ +{ \ + (DEST)[0] = (SRC)[0] << (SHIFT) ^ (SRC)[1] >> (32 - (SHIFT)); \ + (DEST)[1] = (SRC)[1] << (SHIFT) ^ (SRC)[2] >> (32 - (SHIFT)); \ + (DEST)[2] = (SRC)[2] << (SHIFT) ^ (SRC)[3] >> (32 - (SHIFT)); \ + (DEST)[3] = (SRC)[3] << (SHIFT) ^ (SRC)[0] >> (32 - (SHIFT)); \ +} + +#define FL(XL, XR, KL, KR) \ +{ \ + (XR) = ((((XL) & (KL)) << 1) | (((XL) & (KL)) >> 31)) ^ (XR); \ + (XL) = ((XR) | (KR)) ^ (XL); \ +} + +#define FLInv(YL, YR, KL, KR) \ +{ \ + (YL) = ((YR) | (KR)) ^ (YL); \ + (YR) = ((((YL) & (KL)) << 1) | (((YL) & (KL)) >> 31)) ^ (YR); \ +} + +#define SHIFT_AND_PLACE(INDEX, OFFSET) \ +{ \ + TK[0] = KC[(OFFSET) * 4 + 0]; \ + TK[1] = KC[(OFFSET) * 4 + 1]; \ + TK[2] = KC[(OFFSET) * 4 + 2]; \ + TK[3] = KC[(OFFSET) * 4 + 3]; \ + \ + for( i = 1; i <= 4; i++ ) \ + if( shifts[(INDEX)][(OFFSET)][i -1] ) \ + ROTL(TK + i * 4, TK, ( 15 * i ) % 32); \ + \ + for( i = 0; i < 20; i++ ) \ + if( indexes[(INDEX)][(OFFSET)][i] != -1 ) { \ + RK[indexes[(INDEX)][(OFFSET)][i]] = TK[ i ]; \ + } \ +} + +static void camellia_feistel( const uint32_t x[2], const uint32_t k[2], + uint32_t z[2]) +{ + uint32_t I0, I1; + I0 = x[0] ^ k[0]; + I1 = x[1] ^ k[1]; + + I0 = ((uint32_t) SBOX1((I0 >> 24) & 0xFF) << 24) | + ((uint32_t) SBOX2((I0 >> 16) & 0xFF) << 16) | + ((uint32_t) SBOX3((I0 >> 8) & 0xFF) << 8) | + ((uint32_t) SBOX4((I0 ) & 0xFF) ); + I1 = ((uint32_t) SBOX2((I1 >> 24) & 0xFF) << 24) | + ((uint32_t) SBOX3((I1 >> 16) & 0xFF) << 16) | + ((uint32_t) SBOX4((I1 >> 8) & 0xFF) << 8) | + ((uint32_t) SBOX1((I1 ) & 0xFF) ); + + I0 ^= (I1 << 8) | (I1 >> 24); + I1 ^= (I0 << 16) | (I0 >> 16); + I0 ^= (I1 >> 8) | (I1 << 24); + I1 ^= (I0 >> 8) | (I0 << 24); + + z[0] ^= I1; + z[1] ^= I0; +} + +void mbedtls_camellia_init( mbedtls_camellia_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_camellia_context ) ); +} + +void mbedtls_camellia_free( mbedtls_camellia_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_camellia_context ) ); +} + +/* + * Camellia key schedule (encryption) + */ +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int idx; + size_t i; + uint32_t *RK; + unsigned char t[64]; + uint32_t SIGMA[6][2]; + uint32_t KC[16]; + uint32_t TK[20]; + + RK = ctx->rk; + + memset( t, 0, 64 ); + memset( RK, 0, sizeof(ctx->rk) ); + + switch( keybits ) + { + case 128: ctx->nr = 3; idx = 0; break; + case 192: + case 256: ctx->nr = 4; idx = 1; break; + default : return( MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH ); + } + + for( i = 0; i < keybits / 8; ++i ) + t[i] = key[i]; + + if( keybits == 192 ) { + for( i = 0; i < 8; i++ ) + t[24 + i] = ~t[16 + i]; + } + + /* + * Prepare SIGMA values + */ + for( i = 0; i < 6; i++ ) { + GET_UINT32_BE( SIGMA[i][0], SIGMA_CHARS[i], 0 ); + GET_UINT32_BE( SIGMA[i][1], SIGMA_CHARS[i], 4 ); + } + + /* + * Key storage in KC + * Order: KL, KR, KA, KB + */ + memset( KC, 0, sizeof(KC) ); + + /* Store KL, KR */ + for( i = 0; i < 8; i++ ) + GET_UINT32_BE( KC[i], t, i * 4 ); + + /* Generate KA */ + for( i = 0; i < 4; ++i ) + KC[8 + i] = KC[i] ^ KC[4 + i]; + + camellia_feistel( KC + 8, SIGMA[0], KC + 10 ); + camellia_feistel( KC + 10, SIGMA[1], KC + 8 ); + + for( i = 0; i < 4; ++i ) + KC[8 + i] ^= KC[i]; + + camellia_feistel( KC + 8, SIGMA[2], KC + 10 ); + camellia_feistel( KC + 10, SIGMA[3], KC + 8 ); + + if( keybits > 128 ) { + /* Generate KB */ + for( i = 0; i < 4; ++i ) + KC[12 + i] = KC[4 + i] ^ KC[8 + i]; + + camellia_feistel( KC + 12, SIGMA[4], KC + 14 ); + camellia_feistel( KC + 14, SIGMA[5], KC + 12 ); + } + + /* + * Generating subkeys + */ + + /* Manipulating KL */ + SHIFT_AND_PLACE( idx, 0 ); + + /* Manipulating KR */ + if( keybits > 128 ) { + SHIFT_AND_PLACE( idx, 1 ); + } + + /* Manipulating KA */ + SHIFT_AND_PLACE( idx, 2 ); + + /* Manipulating KB */ + if( keybits > 128 ) { + SHIFT_AND_PLACE( idx, 3 ); + } + + /* Do transpositions */ + for( i = 0; i < 20; i++ ) { + if( transposes[idx][i] != -1 ) { + RK[32 + 12 * idx + i] = RK[transposes[idx][i]]; + } + } + + return( 0 ); +} + +/* + * Camellia key schedule (decryption) + */ +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, const unsigned char *key, + unsigned int keybits ) +{ + int idx, ret; + size_t i; + mbedtls_camellia_context cty; + uint32_t *RK; + uint32_t *SK; + + mbedtls_camellia_init( &cty ); + + /* Also checks keybits */ + if( ( ret = mbedtls_camellia_setkey_enc( &cty, key, keybits ) ) != 0 ) + goto exit; + + ctx->nr = cty.nr; + idx = ( ctx->nr == 4 ); + + RK = ctx->rk; + SK = cty.rk + 24 * 2 + 8 * idx * 2; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + + for( i = 22 + 8 * idx, SK -= 6; i > 0; i--, SK -= 4 ) + { + *RK++ = *SK++; + *RK++ = *SK++; + } + + SK -= 2; + + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + *RK++ = *SK++; + +exit: + mbedtls_camellia_free( &cty ); + + return( ret ); +} + +/* + * Camellia-ECB block encryption/decryption + */ +int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ) +{ + int NR; + uint32_t *RK, X[4]; + + ( (void) mode ); + + NR = ctx->nr; + RK = ctx->rk; + + GET_UINT32_BE( X[0], input, 0 ); + GET_UINT32_BE( X[1], input, 4 ); + GET_UINT32_BE( X[2], input, 8 ); + GET_UINT32_BE( X[3], input, 12 ); + + X[0] ^= *RK++; + X[1] ^= *RK++; + X[2] ^= *RK++; + X[3] ^= *RK++; + + while( NR ) { + --NR; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + camellia_feistel( X, RK, X + 2 ); + RK += 2; + camellia_feistel( X + 2, RK, X ); + RK += 2; + + if( NR ) { + FL(X[0], X[1], RK[0], RK[1]); + RK += 2; + FLInv(X[2], X[3], RK[0], RK[1]); + RK += 2; + } + } + + X[2] ^= *RK++; + X[3] ^= *RK++; + X[0] ^= *RK++; + X[1] ^= *RK++; + + PUT_UINT32_BE( X[2], output, 0 ); + PUT_UINT32_BE( X[3], output, 4 ); + PUT_UINT32_BE( X[0], output, 8 ); + PUT_UINT32_BE( X[1], output, 12 ); + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * Camellia-CBC buffer encryption/decryption + */ +int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[16]; + + if( length % 16 ) + return( MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_CAMELLIA_DECRYPT ) + { + while( length > 0 ) + { + memcpy( temp, input, 16 ); + mbedtls_camellia_crypt_ecb( ctx, mode, input, output ); + + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + else + { + while( length > 0 ) + { + for( i = 0; i < 16; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_camellia_crypt_ecb( ctx, mode, output, output ); + memcpy( iv, output, 16 ); + + input += 16; + output += 16; + length -= 16; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/* + * Camellia-CFB128 buffer encryption/decryption + */ +int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ) +{ + int c; + size_t n = *iv_off; + + if( mode == MBEDTLS_CAMELLIA_DECRYPT ) + { + while( length-- ) + { + if( n == 0 ) + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); + + c = *input++; + *output++ = (unsigned char)( c ^ iv[n] ); + iv[n] = (unsigned char) c; + + n = ( n + 1 ) & 0x0F; + } + } + else + { + while( length-- ) + { + if( n == 0 ) + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, iv, iv ); + + iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); + + n = ( n + 1 ) & 0x0F; + } + } + + *iv_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Camellia-CTR buffer encryption/decryption + */ +int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ) +{ + int c, i; + size_t n = *nc_off; + + while( length-- ) + { + if( n == 0 ) { + mbedtls_camellia_crypt_ecb( ctx, MBEDTLS_CAMELLIA_ENCRYPT, nonce_counter, + stream_block ); + + for( i = 16; i > 0; i-- ) + if( ++nonce_counter[i - 1] != 0 ) + break; + } + c = *input++; + *output++ = (unsigned char)( c ^ stream_block[n] ); + + n = ( n + 1 ) & 0x0F; + } + + *nc_off = n; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* !MBEDTLS_CAMELLIA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Camellia test vectors from: + * + * http://info.isl.ntt.co.jp/crypt/eng/camellia/technology.html: + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/intermediate.txt + * http://info.isl.ntt.co.jp/crypt/eng/camellia/dl/cryptrec/t_camellia.txt + * (For each bitlength: Key 0, Nr 39) + */ +#define CAMELLIA_TESTS_ECB 2 + +static const unsigned char camellia_test_ecb_key[3][CAMELLIA_TESTS_ECB][32] = +{ + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77 }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, + { + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10, + 0x00, 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, + 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff }, + { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } + }, +}; + +static const unsigned char camellia_test_ecb_plain[CAMELLIA_TESTS_ECB][16] = +{ + { 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + 0xfe, 0xdc, 0xba, 0x98, 0x76, 0x54, 0x32, 0x10 }, + { 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 } +}; + +static const unsigned char camellia_test_ecb_cipher[3][CAMELLIA_TESTS_ECB][16] = +{ + { + { 0x67, 0x67, 0x31, 0x38, 0x54, 0x96, 0x69, 0x73, + 0x08, 0x57, 0x06, 0x56, 0x48, 0xea, 0xbe, 0x43 }, + { 0x38, 0x3C, 0x6C, 0x2A, 0xAB, 0xEF, 0x7F, 0xDE, + 0x25, 0xCD, 0x47, 0x0B, 0xF7, 0x74, 0xA3, 0x31 } + }, + { + { 0xb4, 0x99, 0x34, 0x01, 0xb3, 0xe9, 0x96, 0xf8, + 0x4e, 0xe5, 0xce, 0xe7, 0xd7, 0x9b, 0x09, 0xb9 }, + { 0xD1, 0x76, 0x3F, 0xC0, 0x19, 0xD7, 0x7C, 0xC9, + 0x30, 0xBF, 0xF2, 0xA5, 0x6F, 0x7C, 0x93, 0x64 } + }, + { + { 0x9a, 0xcc, 0x23, 0x7d, 0xff, 0x16, 0xd7, 0x6c, + 0x20, 0xef, 0x7c, 0x91, 0x9e, 0x3a, 0x75, 0x09 }, + { 0x05, 0x03, 0xFB, 0x10, 0xAB, 0x24, 0x1E, 0x7C, + 0xF4, 0x5D, 0x8C, 0xDE, 0xEE, 0x47, 0x43, 0x35 } + } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define CAMELLIA_TESTS_CBC 3 + +static const unsigned char camellia_test_cbc_key[3][32] = +{ + { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, + 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C } + , + { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, + 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, + 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B } + , + { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, + 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, + 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, + 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } +}; + +static const unsigned char camellia_test_cbc_iv[16] = + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F } +; + +static const unsigned char camellia_test_cbc_plain[CAMELLIA_TESTS_CBC][16] = +{ + { 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, + 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A }, + { 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, + 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51 }, + { 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, + 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF } + +}; + +static const unsigned char camellia_test_cbc_cipher[3][CAMELLIA_TESTS_CBC][16] = +{ + { + { 0x16, 0x07, 0xCF, 0x49, 0x4B, 0x36, 0xBB, 0xF0, + 0x0D, 0xAE, 0xB0, 0xB5, 0x03, 0xC8, 0x31, 0xAB }, + { 0xA2, 0xF2, 0xCF, 0x67, 0x16, 0x29, 0xEF, 0x78, + 0x40, 0xC5, 0xA5, 0xDF, 0xB5, 0x07, 0x48, 0x87 }, + { 0x0F, 0x06, 0x16, 0x50, 0x08, 0xCF, 0x8B, 0x8B, + 0x5A, 0x63, 0x58, 0x63, 0x62, 0x54, 0x3E, 0x54 } + }, + { + { 0x2A, 0x48, 0x30, 0xAB, 0x5A, 0xC4, 0xA1, 0xA2, + 0x40, 0x59, 0x55, 0xFD, 0x21, 0x95, 0xCF, 0x93 }, + { 0x5D, 0x5A, 0x86, 0x9B, 0xD1, 0x4C, 0xE5, 0x42, + 0x64, 0xF8, 0x92, 0xA6, 0xDD, 0x2E, 0xC3, 0xD5 }, + { 0x37, 0xD3, 0x59, 0xC3, 0x34, 0x98, 0x36, 0xD8, + 0x84, 0xE3, 0x10, 0xAD, 0xDF, 0x68, 0xC4, 0x49 } + }, + { + { 0xE6, 0xCF, 0xA3, 0x5F, 0xC0, 0x2B, 0x13, 0x4A, + 0x4D, 0x2C, 0x0B, 0x67, 0x37, 0xAC, 0x3E, 0xDA }, + { 0x36, 0xCB, 0xEB, 0x73, 0xBD, 0x50, 0x4B, 0x40, + 0x70, 0xB1, 0xB7, 0xDE, 0x2B, 0x21, 0xEB, 0x50 }, + { 0xE3, 0x1A, 0x60, 0x55, 0x29, 0x7D, 0x96, 0xCA, + 0x33, 0x30, 0xCD, 0xF1, 0xB1, 0x86, 0x0A, 0x83 } + } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/* + * Camellia-CTR test vectors from: + * + * http://www.faqs.org/rfcs/rfc5528.html + */ + +static const unsigned char camellia_test_ctr_key[3][16] = +{ + { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, + 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, + { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, + 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, + { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, + 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } +}; + +static const unsigned char camellia_test_ctr_nonce_counter[3][16] = +{ + { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, + 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, + { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, + 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } +}; + +static const unsigned char camellia_test_ctr_pt[3][48] = +{ + { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, + 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, + + { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, + 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, + 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, + 0x20, 0x21, 0x22, 0x23 } +}; + +static const unsigned char camellia_test_ctr_ct[3][48] = +{ + { 0xD0, 0x9D, 0xC2, 0x9A, 0x82, 0x14, 0x61, 0x9A, + 0x20, 0x87, 0x7C, 0x76, 0xDB, 0x1F, 0x0B, 0x3F }, + { 0xDB, 0xF3, 0xC7, 0x8D, 0xC0, 0x83, 0x96, 0xD4, + 0xDA, 0x7C, 0x90, 0x77, 0x65, 0xBB, 0xCB, 0x44, + 0x2B, 0x8E, 0x8E, 0x0F, 0x31, 0xF0, 0xDC, 0xA7, + 0x2C, 0x74, 0x17, 0xE3, 0x53, 0x60, 0xE0, 0x48 }, + { 0xB1, 0x9D, 0x1F, 0xCD, 0xCB, 0x75, 0xEB, 0x88, + 0x2F, 0x84, 0x9C, 0xE2, 0x4D, 0x85, 0xCF, 0x73, + 0x9C, 0xE6, 0x4B, 0x2B, 0x5C, 0x9D, 0x73, 0xF1, + 0x4F, 0x2D, 0x5D, 0x9D, 0xCE, 0x98, 0x89, 0xCD, + 0xDF, 0x50, 0x86, 0x96 } +}; + +static const int camellia_test_ctr_len[3] = + { 16, 32, 36 }; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/* + * Checkup routine + */ +int mbedtls_camellia_self_test( int verbose ) +{ + int i, j, u, v; + unsigned char key[32]; + unsigned char buf[64]; + unsigned char src[16]; + unsigned char dst[16]; +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char iv[16]; +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + size_t offset, len; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; +#endif + + mbedtls_camellia_context ctx; + + memset( key, 0, 32 ); + + for( j = 0; j < 6; j++ ) { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-ECB-%3d (%s): ", 128 + u * 64, + (v == MBEDTLS_CAMELLIA_DECRYPT) ? "dec" : "enc"); + + for( i = 0; i < CAMELLIA_TESTS_ECB; i++ ) { + memcpy( key, camellia_test_ecb_key[u][i], 16 + 8 * u ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + memcpy( src, camellia_test_ecb_cipher[u][i], 16 ); + memcpy( dst, camellia_test_ecb_plain[i], 16 ); + } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ + mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + memcpy( src, camellia_test_ecb_plain[i], 16 ); + memcpy( dst, camellia_test_ecb_cipher[u][i], 16 ); + } + + mbedtls_camellia_crypt_ecb( &ctx, v, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( j = 0; j < 6; j++ ) + { + u = j >> 1; + v = j & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-CBC-%3d (%s): ", 128 + u * 64, + ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( src, camellia_test_cbc_iv, 16 ); + memcpy( dst, camellia_test_cbc_iv, 16 ); + memcpy( key, camellia_test_cbc_key[u], 16 + 8 * u ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + mbedtls_camellia_setkey_dec( &ctx, key, 128 + u * 64 ); + } else { + mbedtls_camellia_setkey_enc( &ctx, key, 128 + u * 64 ); + } + + for( i = 0; i < CAMELLIA_TESTS_CBC; i++ ) { + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) { + memcpy( iv , src, 16 ); + memcpy( src, camellia_test_cbc_cipher[u][i], 16 ); + memcpy( dst, camellia_test_cbc_plain[i], 16 ); + } else { /* MBEDTLS_CAMELLIA_ENCRYPT */ + memcpy( iv , dst, 16 ); + memcpy( src, camellia_test_cbc_plain[i], 16 ); + memcpy( dst, camellia_test_cbc_cipher[u][i], 16 ); + } + + mbedtls_camellia_crypt_cbc( &ctx, v, 16, iv, src, buf ); + + if( memcmp( buf, dst, 16 ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /* + * CTR mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " CAMELLIA-CTR-128 (%s): ", + ( v == MBEDTLS_CAMELLIA_DECRYPT ) ? "dec" : "enc" ); + + memcpy( nonce_counter, camellia_test_ctr_nonce_counter[u], 16 ); + memcpy( key, camellia_test_ctr_key[u], 16 ); + + offset = 0; + mbedtls_camellia_setkey_enc( &ctx, key, 128 ); + + if( v == MBEDTLS_CAMELLIA_DECRYPT ) + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_ct[u], len ); + + mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, camellia_test_ctr_pt[u], len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + else + { + len = camellia_test_ctr_len[u]; + memcpy( buf, camellia_test_ctr_pt[u], len ); + + mbedtls_camellia_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, + buf, buf ); + + if( memcmp( buf, camellia_test_ctr_ct[u], len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CAMELLIA_C */ diff --git a/common/mbedtls/camellia.h b/common/mbedtls/camellia.h new file mode 100644 index 000000000..cb36312b4 --- /dev/null +++ b/common/mbedtls/camellia.h @@ -0,0 +1,273 @@ +/** + * \file camellia.h + * + * \brief Camellia block cipher + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_CAMELLIA_H +#define MBEDTLS_CAMELLIA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_CAMELLIA_ENCRYPT 1 +#define MBEDTLS_CAMELLIA_DECRYPT 0 + +#define MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH -0x0024 /**< Invalid key length. */ +#define MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH -0x0026 /**< Invalid data input length. */ +#define MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED -0x0027 /**< Camellia hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_CAMELLIA_ALT) +// Regular implementation +// + +/** + * \brief CAMELLIA context structure + */ +typedef struct mbedtls_camellia_context +{ + int nr; /*!< number of rounds */ + uint32_t rk[68]; /*!< CAMELLIA round keys */ +} +mbedtls_camellia_context; + +#else /* MBEDTLS_CAMELLIA_ALT */ +#include "camellia_alt.h" +#endif /* MBEDTLS_CAMELLIA_ALT */ + +/** + * \brief Initialize CAMELLIA context + * + * \param ctx CAMELLIA context to be initialized + */ +void mbedtls_camellia_init( mbedtls_camellia_context *ctx ); + +/** + * \brief Clear CAMELLIA context + * + * \param ctx CAMELLIA context to be cleared + */ +void mbedtls_camellia_free( mbedtls_camellia_context *ctx ); + +/** + * \brief CAMELLIA key schedule (encryption) + * + * \param ctx CAMELLIA context to be initialized + * \param key encryption key + * \param keybits must be 128, 192 or 256 + * + * \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH + */ +int mbedtls_camellia_setkey_enc( mbedtls_camellia_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief CAMELLIA key schedule (decryption) + * + * \param ctx CAMELLIA context to be initialized + * \param key decryption key + * \param keybits must be 128, 192 or 256 + * + * \return 0 if successful, or MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH + */ +int mbedtls_camellia_setkey_dec( mbedtls_camellia_context *ctx, const unsigned char *key, + unsigned int keybits ); + +/** + * \brief CAMELLIA-ECB block encryption/decryption + * + * \param ctx CAMELLIA context + * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT + * \param input 16-byte input block + * \param output 16-byte output block + * + * \return 0 if successful + */ +int mbedtls_camellia_crypt_ecb( mbedtls_camellia_context *ctx, + int mode, + const unsigned char input[16], + unsigned char output[16] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief CAMELLIA-CBC buffer encryption/decryption + * Length should be a multiple of the block + * size (16 bytes) + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx CAMELLIA context + * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH + */ +int mbedtls_camellia_crypt_cbc( mbedtls_camellia_context *ctx, + int mode, + size_t length, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +/** + * \brief CAMELLIA-CFB128 buffer encryption/decryption + * + * Note: Due to the nature of CFB you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and CAMELLIE_DECRYPT. + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx CAMELLIA context + * \param mode MBEDTLS_CAMELLIA_ENCRYPT or MBEDTLS_CAMELLIA_DECRYPT + * \param length length of the input data + * \param iv_off offset in IV (updated after use) + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or + * MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH + */ +int mbedtls_camellia_crypt_cfb128( mbedtls_camellia_context *ctx, + int mode, + size_t length, + size_t *iv_off, + unsigned char iv[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +/** + * \brief CAMELLIA-CTR buffer encryption/decryption + * + * Note: Due to the nature of CTR you should use the same key schedule for + * both encryption and decryption. So a context initialized with + * mbedtls_camellia_setkey_enc() for both MBEDTLS_CAMELLIA_ENCRYPT and MBEDTLS_CAMELLIA_DECRYPT. + * + * \warning You must never reuse a nonce value with the same key. Doing so + * would void the encryption for the two messages encrypted with + * the same nonce and key. + * + * There are two common strategies for managing nonces with CTR: + * + * 1. You can handle everything as a single message processed over + * successive calls to this function. In that case, you want to + * set \p nonce_counter and \p nc_off to 0 for the first call, and + * then preserve the values of \p nonce_counter, \p nc_off and \p + * stream_block across calls to this function as they will be + * updated by this function. + * + * With this strategy, you must not encrypt more than 2**128 + * blocks of data with the same key. + * + * 2. You can encrypt separate messages by dividing the \p + * nonce_counter buffer in two areas: the first one used for a + * per-message nonce, handled by yourself, and the second one + * updated by this function internally. + * + * For example, you might reserve the first 12 bytes for the + * per-message nonce, and the last 4 bytes for internal use. In that + * case, before calling this function on a new message you need to + * set the first 12 bytes of \p nonce_counter to your chosen nonce + * value, the last 4 to 0, and \p nc_off to 0 (which will cause \p + * stream_block to be ignored). That way, you can encrypt at most + * 2**96 messages of up to 2**32 blocks each with the same key. + * + * The per-message nonce (or information sufficient to reconstruct + * it) needs to be communicated with the ciphertext and must be unique. + * The recommended way to ensure uniqueness is to use a message + * counter. An alternative is to generate random nonces, but this + * limits the number of messages that can be securely encrypted: + * for example, with 96-bit random nonces, you should not encrypt + * more than 2**32 messages with the same key. + * + * Note that for both stategies, sizes are measured in blocks and + * that a CAMELLIA block is 16 bytes. + * + * \warning Upon return, \p stream_block contains sensitive data. Its + * content must not be written to insecure storage and should be + * securely discarded as soon as it's no longer needed. + * + * \param ctx CAMELLIA context + * \param length The length of the data + * \param nc_off The offset in the current stream_block (for resuming + * within current cipher stream). The offset pointer to + * should be 0 at the start of a stream. + * \param nonce_counter The 128-bit nonce and counter. + * \param stream_block The saved stream-block for resuming. Is overwritten + * by the function. + * \param input The input data stream + * \param output The output data stream + * + * \return 0 if successful + */ +int mbedtls_camellia_crypt_ctr( mbedtls_camellia_context *ctx, + size_t length, + size_t *nc_off, + unsigned char nonce_counter[16], + unsigned char stream_block[16], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_camellia_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* camellia.h */ diff --git a/common/mbedtls/certs.c b/common/mbedtls/certs.c new file mode 100644 index 000000000..dd9d02ba3 --- /dev/null +++ b/common/mbedtls/certs.c @@ -0,0 +1,405 @@ +/* + * X.509 test certificates + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/certs.h" + +#if defined(MBEDTLS_CERTS_C) + +#if defined(MBEDTLS_ECDSA_C) +#define TEST_CA_CRT_EC \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIICUjCCAdegAwIBAgIJAMFD4n5iQ8zoMAoGCCqGSM49BAMCMD4xCzAJBgNVBAYT\r\n" \ +"Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n" \ +"QyBDQTAeFw0xMzA5MjQxNTQ5NDhaFw0yMzA5MjIxNTQ5NDhaMD4xCzAJBgNVBAYT\r\n" \ +"Ak5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBF\r\n" \ +"QyBDQTB2MBAGByqGSM49AgEGBSuBBAAiA2IABMPaKzRBN1gvh1b+/Im6KUNLTuBu\r\n" \ +"ww5XUzM5WNRStJGVOQsj318XJGJI/BqVKc4sLYfCiFKAr9ZqqyHduNMcbli4yuiy\r\n" \ +"aY7zQa0pw7RfdadHb9UZKVVpmlM7ILRmFmAzHqOBoDCBnTAdBgNVHQ4EFgQUnW0g\r\n" \ +"JEkBPyvLeLUZvH4kydv7NnwwbgYDVR0jBGcwZYAUnW0gJEkBPyvLeLUZvH4kydv7\r\n" \ +"NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEcMBoGA1UE\r\n" \ +"AxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAwGA1UdEwQFMAMBAf8w\r\n" \ +"CgYIKoZIzj0EAwIDaQAwZgIxAMO0YnNWKJUAfXgSJtJxexn4ipg+kv4znuR50v56\r\n" \ +"t4d0PCu412mUC6Nnd7izvtE2MgIxAP1nnJQjZ8BWukszFQDG48wxCCyci9qpdSMv\r\n" \ +"uCjn8pwUOkABXK8Mss90fzCfCEOtIA==\r\n" \ +"-----END CERTIFICATE-----\r\n" +const char mbedtls_test_ca_crt_ec[] = TEST_CA_CRT_EC; +const size_t mbedtls_test_ca_crt_ec_len = sizeof( mbedtls_test_ca_crt_ec ); + +const char mbedtls_test_ca_key_ec[] = +"-----BEGIN EC PRIVATE KEY-----\r\n" +"Proc-Type: 4,ENCRYPTED\r\n" +"DEK-Info: DES-EDE3-CBC,307EAB469933D64E\r\n" +"\r\n" +"IxbrRmKcAzctJqPdTQLA4SWyBYYGYJVkYEna+F7Pa5t5Yg/gKADrFKcm6B72e7DG\r\n" +"ihExtZI648s0zdYw6qSJ74vrPSuWDe5qm93BqsfVH9svtCzWHW0pm1p0KTBCFfUq\r\n" +"UsuWTITwJImcnlAs1gaRZ3sAWm7cOUidL0fo2G0fYUFNcYoCSLffCFTEHBuPnagb\r\n" +"a77x/sY1Bvii8S9/XhDTb6pTMx06wzrm\r\n" +"-----END EC PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_ca_key_ec_len = sizeof( mbedtls_test_ca_key_ec ); + +const char mbedtls_test_ca_pwd_ec[] = "PolarSSLTest"; +const size_t mbedtls_test_ca_pwd_ec_len = sizeof( mbedtls_test_ca_pwd_ec ) - 1; + +const char mbedtls_test_srv_crt_ec[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIICHzCCAaWgAwIBAgIBCTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" +"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDBZMBMGByqGSM49AgEG\r\n" +"CCqGSM49AwEHA0IABDfMVtl2CR5acj7HWS3/IG7ufPkGkXTQrRS192giWWKSTuUA\r\n" +"2CMR/+ov0jRdXRa9iojCa3cNVc2KKg76Aci07f+jgZ0wgZowCQYDVR0TBAIwADAd\r\n" +"BgNVHQ4EFgQUUGGlj9QH2deCAQzlZX+MY0anE74wbgYDVR0jBGcwZYAUnW0gJEkB\r\n" +"PyvLeLUZvH4kydv7NnyhQqRAMD4xCzAJBgNVBAYTAk5MMREwDwYDVQQKEwhQb2xh\r\n" +"clNTTDEcMBoGA1UEAxMTUG9sYXJzc2wgVGVzdCBFQyBDQYIJAMFD4n5iQ8zoMAoG\r\n" +"CCqGSM49BAMCA2gAMGUCMQCaLFzXptui5WQN8LlO3ddh1hMxx6tzgLvT03MTVK2S\r\n" +"C12r0Lz3ri/moSEpNZWqPjkCMCE2f53GXcYLqyfyJR078c/xNSUU5+Xxl7VZ414V\r\n" +"fGa5kHvHARBPc8YAIVIqDvHH1Q==\r\n" +"-----END CERTIFICATE-----\r\n"; +const size_t mbedtls_test_srv_crt_ec_len = sizeof( mbedtls_test_srv_crt_ec ); + +const char mbedtls_test_srv_key_ec[] = +"-----BEGIN EC PRIVATE KEY-----\r\n" +"MHcCAQEEIPEqEyB2AnCoPL/9U/YDHvdqXYbIogTywwyp6/UfDw6noAoGCCqGSM49\r\n" +"AwEHoUQDQgAEN8xW2XYJHlpyPsdZLf8gbu58+QaRdNCtFLX3aCJZYpJO5QDYIxH/\r\n" +"6i/SNF1dFr2KiMJrdw1VzYoqDvoByLTt/w==\r\n" +"-----END EC PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_srv_key_ec_len = sizeof( mbedtls_test_srv_key_ec ); + +const char mbedtls_test_cli_crt_ec[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIICLDCCAbKgAwIBAgIBDTAKBggqhkjOPQQDAjA+MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0EwHhcN\r\n" +"MTMwOTI0MTU1MjA0WhcNMjMwOTIyMTU1MjA0WjBBMQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxHzAdBgNVBAMTFlBvbGFyU1NMIFRlc3QgQ2xpZW50IDIw\r\n" +"WTATBgcqhkjOPQIBBggqhkjOPQMBBwNCAARX5a6xc9/TrLuTuIH/Eq7u5lOszlVT\r\n" +"9jQOzC7jYyUL35ji81xgNpbA1RgUcOV/n9VLRRjlsGzVXPiWj4dwo+THo4GdMIGa\r\n" +"MAkGA1UdEwQCMAAwHQYDVR0OBBYEFHoAX4Zk/OBd5REQO7LmO8QmP8/iMG4GA1Ud\r\n" +"IwRnMGWAFJ1tICRJAT8ry3i1Gbx+JMnb+zZ8oUKkQDA+MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UEChMIUG9sYXJTU0wxHDAaBgNVBAMTE1BvbGFyc3NsIFRlc3QgRUMgQ0GC\r\n" +"CQDBQ+J+YkPM6DAKBggqhkjOPQQDAgNoADBlAjBKZQ17IIOimbmoD/yN7o89u3BM\r\n" +"lgOsjnhw3fIOoLIWy2WOGsk/LGF++DzvrRzuNiACMQCd8iem1XS4JK7haj8xocpU\r\n" +"LwjQje5PDGHfd3h9tP38Qknu5bJqws0md2KOKHyeV0U=\r\n" +"-----END CERTIFICATE-----\r\n"; +const size_t mbedtls_test_cli_crt_ec_len = sizeof( mbedtls_test_cli_crt_ec ); + +const char mbedtls_test_cli_key_ec[] = +"-----BEGIN EC PRIVATE KEY-----\r\n" +"MHcCAQEEIPb3hmTxZ3/mZI3vyk7p3U3wBf+WIop6hDhkFzJhmLcqoAoGCCqGSM49\r\n" +"AwEHoUQDQgAEV+WusXPf06y7k7iB/xKu7uZTrM5VU/Y0Dswu42MlC9+Y4vNcYDaW\r\n" +"wNUYFHDlf5/VS0UY5bBs1Vz4lo+HcKPkxw==\r\n" +"-----END EC PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_cli_key_ec_len = sizeof( mbedtls_test_cli_key_ec ); +#endif /* MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_RSA_C) + +#if defined(MBEDTLS_SHA256_C) +#define TEST_CA_CRT_RSA_SHA256 \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" \ +"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ +"MTcwNTA0MTY1NzAxWhcNMjcwNTA1MTY1NzAxWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ +"A1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ +"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ +"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ +"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ +"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ +"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ +"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ +"gZUwgZIwHQYDVR0OBBYEFLRa5KWz3tJS9rnVppUP6z68x/3/MGMGA1UdIwRcMFqA\r\n" \ +"FLRa5KWz3tJS9rnVppUP6z68x/3/oT+kPTA7MQswCQYDVQQGEwJOTDERMA8GA1UE\r\n" \ +"CgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0GCAQAwDAYDVR0T\r\n" \ +"BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOCAQEAHK/HHrTZMnnVMpde1io+voAtql7j\r\n" \ +"4sRhLrjD7o3THtwRbDa2diCvpq0Sq23Ng2LMYoXsOxoL/RQK3iN7UKxV3MKPEr0w\r\n" \ +"XQS+kKQqiT2bsfrjnWMVHZtUOMpm6FNqcdGm/Rss3vKda2lcKl8kUnq/ylc1+QbB\r\n" \ +"G6A6tUvQcr2ZyWfVg+mM5XkhTrOOXus2OLikb4WwEtJTJRNE0f+yPODSUz0/vT57\r\n" \ +"ApH0CnB80bYJshYHPHHymOtleAB8KSYtqm75g/YNobjnjB6cm4HkW3OZRVIl6fYY\r\n" \ +"n20NRVA1Vjs6GAROr4NqW4k/+LofY9y0LLDE+p0oIEKXIsIvhPr39swxSA==\r\n" \ +"-----END CERTIFICATE-----\r\n" + +const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA_SHA256; +const size_t mbedtls_test_ca_crt_rsa_len = sizeof( mbedtls_test_ca_crt_rsa ); +#define TEST_CA_CRT_RSA_SOME + +static const char mbedtls_test_ca_crt_rsa_sha256[] = TEST_CA_CRT_RSA_SHA256; + +#endif + +#if !defined(TEST_CA_CRT_RSA_SOME) || defined(MBEDTLS_SHA1_C) +#define TEST_CA_CRT_RSA_SHA1 \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIDhzCCAm+gAwIBAgIBADANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" \ +"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" \ +"MTEwMjEyMTQ0NDAwWhcNMjEwMjEyMTQ0NDAwWjA7MQswCQYDVQQGEwJOTDERMA8G\r\n" \ +"A1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwggEiMA0G\r\n" \ +"CSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDA3zf8F7vglp0/ht6WMn1EpRagzSHx\r\n" \ +"mdTs6st8GFgIlKXsm8WL3xoemTiZhx57wI053zhdcHgH057Zk+i5clHFzqMwUqny\r\n" \ +"50BwFMtEonILwuVA+T7lpg6z+exKY8C4KQB0nFc7qKUEkHHxvYPZP9al4jwqj+8n\r\n" \ +"YMPGn8u67GB9t+aEMr5P+1gmIgNb1LTV+/Xjli5wwOQuvfwu7uJBVcA0Ln0kcmnL\r\n" \ +"R7EUQIN9Z/SG9jGr8XmksrUuEvmEF/Bibyc+E1ixVA0hmnM3oTDPb5Lc9un8rNsu\r\n" \ +"KNF+AksjoBXyOGVkCeoMbo4bF6BxyLObyavpw/LPh5aPgAIynplYb6LVAgMBAAGj\r\n" \ +"gZUwgZIwDAYDVR0TBAUwAwEB/zAdBgNVHQ4EFgQUtFrkpbPe0lL2udWmlQ/rPrzH\r\n" \ +"/f8wYwYDVR0jBFwwWoAUtFrkpbPe0lL2udWmlQ/rPrzH/f+hP6Q9MDsxCzAJBgNV\r\n" \ +"BAYTAk5MMREwDwYDVQQKEwhQb2xhclNTTDEZMBcGA1UEAxMQUG9sYXJTU0wgVGVz\r\n" \ +"dCBDQYIBADANBgkqhkiG9w0BAQUFAAOCAQEAuP1U2ABUkIslsCfdlc2i94QHHYeJ\r\n" \ +"SsR4EdgHtdciUI5I62J6Mom+Y0dT/7a+8S6MVMCZP6C5NyNyXw1GWY/YR82XTJ8H\r\n" \ +"DBJiCTok5DbZ6SzaONBzdWHXwWwmi5vg1dxn7YxrM9d0IjxM27WNKs4sDQhZBQkF\r\n" \ +"pjmfs2cb4oPl4Y9T9meTx/lvdkRYEug61Jfn6cA+qHpyPYdTH+UshITnmp5/Ztkf\r\n" \ +"m/UTSLBNFNHesiTZeH31NcxYGdHSme9Nc/gfidRa0FLOCfWxRlFqAI47zG9jAQCZ\r\n" \ +"7Z2mCGDNMhjQc+BYcdnl0lPXjdDK6V0qCg1dVewhUBcW5gZKzV7e9+DpVA==\r\n" \ +"-----END CERTIFICATE-----\r\n" + +#if !defined (TEST_CA_CRT_RSA_SOME) +const char mbedtls_test_ca_crt_rsa[] = TEST_CA_CRT_RSA_SHA1; +const size_t mbedtls_test_ca_crt_rsa_len = sizeof( mbedtls_test_ca_crt_rsa ); +#endif + +static const char mbedtls_test_ca_crt_rsa_sha1[] = TEST_CA_CRT_RSA_SHA1; + +#endif + +const char mbedtls_test_ca_key_rsa[] = +"-----BEGIN RSA PRIVATE KEY-----\r\n" +"Proc-Type: 4,ENCRYPTED\r\n" +"DEK-Info: DES-EDE3-CBC,A8A95B05D5B7206B\r\n" +"\r\n" +"9Qd9GeArejl1GDVh2lLV1bHt0cPtfbh5h/5zVpAVaFpqtSPMrElp50Rntn9et+JA\r\n" +"7VOyboR+Iy2t/HU4WvA687k3Bppe9GwKHjHhtl//8xFKwZr3Xb5yO5JUP8AUctQq\r\n" +"Nb8CLlZyuUC+52REAAthdWgsX+7dJO4yabzUcQ22Tp9JSD0hiL43BlkWYUNK3dAo\r\n" +"PZlmiptjnzVTjg1MxsBSydZinWOLBV8/JQgxSPo2yD4uEfig28qbvQ2wNIn0pnAb\r\n" +"GxnSAOazkongEGfvcjIIs+LZN9gXFhxcOh6kc4Q/c99B7QWETwLLkYgZ+z1a9VY9\r\n" +"gEU7CwCxYCD+h9hY6FPmsK0/lC4O7aeRKpYq00rPPxs6i7phiexg6ax6yTMmArQq\r\n" +"QmK3TAsJm8V/J5AWpLEV6jAFgRGymGGHnof0DXzVWZidrcZJWTNuGEX90nB3ee2w\r\n" +"PXJEFWKoD3K3aFcSLdHYr3mLGxP7H9ThQai9VsycxZKS5kwvBKQ//YMrmFfwPk8x\r\n" +"vTeY4KZMaUrveEel5tWZC94RSMKgxR6cyE1nBXyTQnDOGbfpNNgBKxyKbINWoOJU\r\n" +"WJZAwlsQn+QzCDwpri7+sV1mS3gBE6UY7aQmnmiiaC2V3Hbphxct/en5QsfDOt1X\r\n" +"JczSfpRWLlbPznZg8OQh/VgCMA58N5DjOzTIK7sJJ5r+94ZBTCpgAMbF588f0NTR\r\n" +"KCe4yrxGJR7X02M4nvD4IwOlpsQ8xQxZtOSgXv4LkxvdU9XJJKWZ/XNKJeWztxSe\r\n" +"Z1vdTc2YfsDBA2SEv33vxHx2g1vqtw8SjDRT2RaQSS0QuSaMJimdOX6mTOCBKk1J\r\n" +"9Q5mXTrER+/LnK0jEmXsBXWA5bqqVZIyahXSx4VYZ7l7w/PHiUDtDgyRhMMKi4n2\r\n" +"iQvQcWSQTjrpnlJbca1/DkpRt3YwrvJwdqb8asZU2VrNETh5x0QVefDRLFiVpif/\r\n" +"tUaeAe/P1F8OkS7OIZDs1SUbv/sD2vMbhNkUoCms3/PvNtdnvgL4F0zhaDpKCmlT\r\n" +"P8vx49E7v5CyRNmED9zZg4o3wmMqrQO93PtTug3Eu9oVx1zPQM1NVMyBa2+f29DL\r\n" +"1nuTCeXdo9+ni45xx+jAI4DCwrRdhJ9uzZyC6962H37H6D+5naNvClFR1s6li1Gb\r\n" +"nqPoiy/OBsEx9CaDGcqQBp5Wme/3XW+6z1ISOx+igwNTVCT14mHdBMbya0eIKft5\r\n" +"X+GnwtgEMyCYyyWuUct8g4RzErcY9+yW9Om5Hzpx4zOuW4NPZgPDTgK+t2RSL/Yq\r\n" +"rE1njrgeGYcVeG3f+OftH4s6fPbq7t1A5ZgUscbLMBqr9tK+OqygR4EgKBPsH6Cz\r\n" +"L6zlv/2RV0qAHvVuDJcIDIgwY5rJtINEm32rhOeFNJwZS5MNIC1czXZx5//ugX7l\r\n" +"I4sy5nbVhwSjtAk8Xg5dZbdTZ6mIrb7xqH+fdakZor1khG7bC2uIwibD3cSl2XkR\r\n" +"wN48lslbHnqqagr6Xm1nNOSVl8C/6kbJEsMpLhAezfRtGwvOucoaE+WbeUNolGde\r\n" +"P/eQiddSf0brnpiLJRh7qZrl9XuqYdpUqnoEdMAfotDOID8OtV7gt8a48ad8VPW2\r\n" +"-----END RSA PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_ca_key_rsa_len = sizeof( mbedtls_test_ca_key_rsa ); + +const char mbedtls_test_ca_pwd_rsa[] = "PolarSSLTest"; +const size_t mbedtls_test_ca_pwd_rsa_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; + +const char mbedtls_test_srv_crt_rsa[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIIDNzCCAh+gAwIBAgIBAjANBgkqhkiG9w0BAQUFADA7MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UEChMIUG9sYXJTU0wxGTAXBgNVBAMTEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" +"MTEwMjEyMTQ0NDA2WhcNMjEwMjEyMTQ0NDA2WjA0MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UEChMIUG9sYXJTU0wxEjAQBgNVBAMTCWxvY2FsaG9zdDCCASIwDQYJKoZIhvcN\r\n" +"AQEBBQADggEPADCCAQoCggEBAMFNo93nzR3RBNdJcriZrA545Do8Ss86ExbQWuTN\r\n" +"owCIp+4ea5anUrSQ7y1yej4kmvy2NKwk9XfgJmSMnLAofaHa6ozmyRyWvP7BBFKz\r\n" +"NtSj+uGxdtiQwWG0ZlI2oiZTqqt0Xgd9GYLbKtgfoNkNHC1JZvdbJXNG6AuKT2kM\r\n" +"tQCQ4dqCEGZ9rlQri2V5kaHiYcPNQEkI7mgM8YuG0ka/0LiqEQMef1aoGh5EGA8P\r\n" +"hYvai0Re4hjGYi/HZo36Xdh98yeJKQHFkA4/J/EwyEoO79bex8cna8cFPXrEAjya\r\n" +"HT4P6DSYW8tzS1KW2BGiLICIaTla0w+w3lkvEcf36hIBMJcCAwEAAaNNMEswCQYD\r\n" +"VR0TBAIwADAdBgNVHQ4EFgQUpQXoZLjc32APUBJNYKhkr02LQ5MwHwYDVR0jBBgw\r\n" +"FoAUtFrkpbPe0lL2udWmlQ/rPrzH/f8wDQYJKoZIhvcNAQEFBQADggEBAJxnXClY\r\n" +"oHkbp70cqBrsGXLybA74czbO5RdLEgFs7rHVS9r+c293luS/KdliLScZqAzYVylw\r\n" +"UfRWvKMoWhHYKp3dEIS4xTXk6/5zXxhv9Rw8SGc8qn6vITHk1S1mPevtekgasY5Y\r\n" +"iWQuM3h4YVlRH3HHEMAD1TnAexfXHHDFQGe+Bd1iAbz1/sH9H8l4StwX6egvTK3M\r\n" +"wXRwkKkvjKaEDA9ATbZx0mI8LGsxSuCqe9r9dyjmttd47J1p1Rulz3CLzaRcVIuS\r\n" +"RRQfaD8neM9c1S/iJ/amTVqJxA1KOdOS5780WhPfSArA+g4qAmSjelc3p4wWpha8\r\n" +"zhuYwjVuX6JHG0c=\r\n" +"-----END CERTIFICATE-----\r\n"; +const size_t mbedtls_test_srv_crt_rsa_len = sizeof( mbedtls_test_srv_crt_rsa ); + +const char mbedtls_test_srv_key_rsa[] = +"-----BEGIN RSA PRIVATE KEY-----\r\n" +"MIIEpAIBAAKCAQEAwU2j3efNHdEE10lyuJmsDnjkOjxKzzoTFtBa5M2jAIin7h5r\r\n" +"lqdStJDvLXJ6PiSa/LY0rCT1d+AmZIycsCh9odrqjObJHJa8/sEEUrM21KP64bF2\r\n" +"2JDBYbRmUjaiJlOqq3ReB30Zgtsq2B+g2Q0cLUlm91slc0boC4pPaQy1AJDh2oIQ\r\n" +"Zn2uVCuLZXmRoeJhw81ASQjuaAzxi4bSRr/QuKoRAx5/VqgaHkQYDw+Fi9qLRF7i\r\n" +"GMZiL8dmjfpd2H3zJ4kpAcWQDj8n8TDISg7v1t7HxydrxwU9esQCPJodPg/oNJhb\r\n" +"y3NLUpbYEaIsgIhpOVrTD7DeWS8Rx/fqEgEwlwIDAQABAoIBAQCXR0S8EIHFGORZ\r\n" +"++AtOg6eENxD+xVs0f1IeGz57Tjo3QnXX7VBZNdj+p1ECvhCE/G7XnkgU5hLZX+G\r\n" +"Z0jkz/tqJOI0vRSdLBbipHnWouyBQ4e/A1yIJdlBtqXxJ1KE/ituHRbNc4j4kL8Z\r\n" +"/r6pvwnTI0PSx2Eqs048YdS92LT6qAv4flbNDxMn2uY7s4ycS4Q8w1JXnCeaAnYm\r\n" +"WYI5wxO+bvRELR2Mcz5DmVnL8jRyml6l6582bSv5oufReFIbyPZbQWlXgYnpu6He\r\n" +"GTc7E1zKYQGG/9+DQUl/1vQuCPqQwny0tQoX2w5tdYpdMdVm+zkLtbajzdTviJJa\r\n" +"TWzL6lt5AoGBAN86+SVeJDcmQJcv4Eq6UhtRr4QGMiQMz0Sod6ettYxYzMgxtw28\r\n" +"CIrgpozCc+UaZJLo7UxvC6an85r1b2nKPCLQFaggJ0H4Q0J/sZOhBIXaoBzWxveK\r\n" +"nupceKdVxGsFi8CDy86DBfiyFivfBj+47BbaQzPBj7C4rK7UlLjab2rDAoGBAN2u\r\n" +"AM2gchoFiu4v1HFL8D7lweEpi6ZnMJjnEu/dEgGQJFjwdpLnPbsj4c75odQ4Gz8g\r\n" +"sw9lao9VVzbusoRE/JGI4aTdO0pATXyG7eG1Qu+5Yc1YGXcCrliA2xM9xx+d7f+s\r\n" +"mPzN+WIEg5GJDYZDjAzHG5BNvi/FfM1C9dOtjv2dAoGAF0t5KmwbjWHBhcVqO4Ic\r\n" +"BVvN3BIlc1ue2YRXEDlxY5b0r8N4XceMgKmW18OHApZxfl8uPDauWZLXOgl4uepv\r\n" +"whZC3EuWrSyyICNhLY21Ah7hbIEBPF3L3ZsOwC+UErL+dXWLdB56Jgy3gZaBeW7b\r\n" +"vDrEnocJbqCm7IukhXHOBK8CgYEAwqdHB0hqyNSzIOGY7v9abzB6pUdA3BZiQvEs\r\n" +"3LjHVd4HPJ2x0N8CgrBIWOE0q8+0hSMmeE96WW/7jD3fPWwCR5zlXknxBQsfv0gP\r\n" +"3BC5PR0Qdypz+d+9zfMf625kyit4T/hzwhDveZUzHnk1Cf+IG7Q+TOEnLnWAWBED\r\n" +"ISOWmrUCgYAFEmRxgwAc/u+D6t0syCwAYh6POtscq9Y0i9GyWk89NzgC4NdwwbBH\r\n" +"4AgahOxIxXx2gxJnq3yfkJfIjwf0s2DyP0kY2y6Ua1OeomPeY9mrIS4tCuDQ6LrE\r\n" +"TB6l9VGoxJL4fyHnZb8L5gGvnB1bbD8cL6YPaDiOhcRseC9vBiEuVg==\r\n" +"-----END RSA PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_srv_key_rsa_len = sizeof( mbedtls_test_srv_key_rsa ); + +const char mbedtls_test_cli_crt_rsa[] = +"-----BEGIN CERTIFICATE-----\r\n" +"MIIDhTCCAm2gAwIBAgIBBDANBgkqhkiG9w0BAQsFADA7MQswCQYDVQQGEwJOTDER\r\n" +"MA8GA1UECgwIUG9sYXJTU0wxGTAXBgNVBAMMEFBvbGFyU1NMIFRlc3QgQ0EwHhcN\r\n" +"MTcwNTA1MTMwNzU5WhcNMjcwNTA2MTMwNzU5WjA8MQswCQYDVQQGEwJOTDERMA8G\r\n" +"A1UECgwIUG9sYXJTU0wxGjAYBgNVBAMMEVBvbGFyU1NMIENsaWVudCAyMIIBIjAN\r\n" +"BgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6f\r\n" +"M60Nj4o8VmXl3ETZzGaFB9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu\r\n" +"1C93KYRhTYJQj6eVSHD1bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEw\r\n" +"MjDV0/YI0FZPRo7yX/k9Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v\r\n" +"4Jv4EFbMs44TFeY0BGbH7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx/\r\n" +"/DZrtenNLQNiTrM9AM+vdqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQAB\r\n" +"o4GSMIGPMB0GA1UdDgQWBBRxoQBzckAvVHZeM/xSj7zx3WtGITBjBgNVHSMEXDBa\r\n" +"gBS0WuSls97SUva51aaVD+s+vMf9/6E/pD0wOzELMAkGA1UEBhMCTkwxETAPBgNV\r\n" +"BAoMCFBvbGFyU1NMMRkwFwYDVQQDDBBQb2xhclNTTCBUZXN0IENBggEAMAkGA1Ud\r\n" +"EwQCMAAwDQYJKoZIhvcNAQELBQADggEBAC7yO786NvcHpK8UovKIG9cB32oSQQom\r\n" +"LoR0eHDRzdqEkoq7yGZufHFiRAAzbMqJfogRtxlrWAeB4y/jGaMBV25IbFOIcH2W\r\n" +"iCEaMMbG+VQLKNvuC63kmw/Zewc9ThM6Pa1Hcy0axT0faf1B/U01j0FIcw/6mTfK\r\n" +"D8w48OIwc1yr0JtutCVjig5DC0yznGMt32RyseOLcUe+lfq005v2PAiCozr5X8rE\r\n" +"ofGZpiM2NqRPePgYy+Vc75Zk28xkRQq1ncprgQb3S4vTsZdScpM9hLf+eMlrgqlj\r\n" +"c5PLSkXBeLE5+fedkyfTaLxxQlgCpuoOhKBm04/R1pWNzUHyqagjO9Q=\r\n" +"-----END CERTIFICATE-----\r\n"; +const size_t mbedtls_test_cli_crt_rsa_len = sizeof( mbedtls_test_cli_crt_rsa ); + +const char mbedtls_test_cli_key_rsa[] = +"-----BEGIN RSA PRIVATE KEY-----\r\n" +"MIIEpAIBAAKCAQEAyHTEzLn5tXnpRdkUYLB9u5Pyax6fM60Nj4o8VmXl3ETZzGaF\r\n" +"B9X4J7BKNdBjngpuG7fa8H6r7gwQk4ZJGDTzqCrSV/Uu1C93KYRhTYJQj6eVSHD1\r\n" +"bk2y1RPD0hrt5kPqQhTrdOrA7R/UV06p86jt0uDBMHEwMjDV0/YI0FZPRo7yX/k9\r\n" +"Z5GIMC5Cst99++UMd//sMcB4j7/Cf8qtbCHWjdmLao5v4Jv4EFbMs44TFeY0BGbH\r\n" +"7vk2DmqV9gmaBmf0ZXH4yqSxJeD+PIs1BGe64E92hfx//DZrtenNLQNiTrM9AM+v\r\n" +"dqBpVoNq0qjU51Bx5rU2BXcFbXvI5MT9TNUhXwIDAQABAoIBAGdNtfYDiap6bzst\r\n" +"yhCiI8m9TtrhZw4MisaEaN/ll3XSjaOG2dvV6xMZCMV+5TeXDHOAZnY18Yi18vzz\r\n" +"4Ut2TnNFzizCECYNaA2fST3WgInnxUkV3YXAyP6CNxJaCmv2aA0yFr2kFVSeaKGt\r\n" +"ymvljNp2NVkvm7Th8fBQBO7I7AXhz43k0mR7XmPgewe8ApZOG3hstkOaMvbWAvWA\r\n" +"zCZupdDjZYjOJqlA4eEA4H8/w7F83r5CugeBE8LgEREjLPiyejrU5H1fubEY+h0d\r\n" +"l5HZBJ68ybTXfQ5U9o/QKA3dd0toBEhhdRUDGzWtjvwkEQfqF1reGWj/tod/gCpf\r\n" +"DFi6X0ECgYEA4wOv/pjSC3ty6TuOvKX2rOUiBrLXXv2JSxZnMoMiWI5ipLQt+RYT\r\n" +"VPafL/m7Dn6MbwjayOkcZhBwk5CNz5A6Q4lJ64Mq/lqHznRCQQ2Mc1G8eyDF/fYL\r\n" +"Ze2pLvwP9VD5jTc2miDfw+MnvJhywRRLcemDFP8k4hQVtm8PMp3ZmNECgYEA4gz7\r\n" +"wzObR4gn8ibe617uQPZjWzUj9dUHYd+in1gwBCIrtNnaRn9I9U/Q6tegRYpii4ys\r\n" +"c176NmU+umy6XmuSKV5qD9bSpZWG2nLFnslrN15Lm3fhZxoeMNhBaEDTnLT26yoi\r\n" +"33gp0mSSWy94ZEqipms+ULF6sY1ZtFW6tpGFoy8CgYAQHhnnvJflIs2ky4q10B60\r\n" +"ZcxFp3rtDpkp0JxhFLhiizFrujMtZSjYNm5U7KkgPVHhLELEUvCmOnKTt4ap/vZ0\r\n" +"BxJNe1GZH3pW6SAvGDQpl9sG7uu/vTFP+lCxukmzxB0DrrDcvorEkKMom7ZCCRvW\r\n" +"KZsZ6YeH2Z81BauRj218kQKBgQCUV/DgKP2985xDTT79N08jUo3hTP5MVYCCuj/+\r\n" +"UeEw1TvZcx3LJby7P6Xad6a1/BqveaGyFKIfEFIaBUBItk801sDDpDaYc4gL00Xc\r\n" +"7lFuBHOZkxJYlss5QrGpuOEl9ZwUt5IrFLBdYaKqNHzNVC1pCPfb/JyH6Dr2HUxq\r\n" +"gxUwAQKBgQCcU6G2L8AG9d9c0UpOyL1tMvFe5Ttw0KjlQVdsh1MP6yigYo9DYuwu\r\n" +"bHFVW2r0dBTqegP2/KTOxKzaHfC1qf0RGDsUoJCNJrd1cwoCLG8P2EF4w3OBrKqv\r\n" +"8u4ytY0F+Vlanj5lm3TaoHSVF1+NWPyOTiwevIECGKwSxvlki4fDAA==\r\n" +"-----END RSA PRIVATE KEY-----\r\n"; +const size_t mbedtls_test_cli_key_rsa_len = sizeof( mbedtls_test_cli_key_rsa ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_PEM_PARSE_C) +/* Concatenation of all available CA certificates */ +const char mbedtls_test_cas_pem[] = +#ifdef TEST_CA_CRT_RSA_SHA1 + TEST_CA_CRT_RSA_SHA1 +#endif +#ifdef TEST_CA_CRT_RSA_SHA256 + TEST_CA_CRT_RSA_SHA256 +#endif +#ifdef TEST_CA_CRT_EC + TEST_CA_CRT_EC +#endif + ""; +const size_t mbedtls_test_cas_pem_len = sizeof( mbedtls_test_cas_pem ); +#endif + +/* List of all available CA certificates */ +const char * mbedtls_test_cas[] = { +#if defined(TEST_CA_CRT_RSA_SHA1) + mbedtls_test_ca_crt_rsa_sha1, +#endif +#if defined(TEST_CA_CRT_RSA_SHA256) + mbedtls_test_ca_crt_rsa_sha256, +#endif +#if defined(MBEDTLS_ECDSA_C) + mbedtls_test_ca_crt_ec, +#endif + NULL +}; +const size_t mbedtls_test_cas_len[] = { +#if defined(TEST_CA_CRT_RSA_SHA1) + sizeof( mbedtls_test_ca_crt_rsa_sha1 ), +#endif +#if defined(TEST_CA_CRT_RSA_SHA256) + sizeof( mbedtls_test_ca_crt_rsa_sha256 ), +#endif +#if defined(MBEDTLS_ECDSA_C) + sizeof( mbedtls_test_ca_crt_ec ), +#endif + 0 +}; + +#if defined(MBEDTLS_RSA_C) +const char *mbedtls_test_ca_crt = mbedtls_test_ca_crt_rsa; /* SHA1 or SHA256 */ +const char *mbedtls_test_ca_key = mbedtls_test_ca_key_rsa; +const char *mbedtls_test_ca_pwd = mbedtls_test_ca_pwd_rsa; +const char *mbedtls_test_srv_crt = mbedtls_test_srv_crt_rsa; +const char *mbedtls_test_srv_key = mbedtls_test_srv_key_rsa; +const char *mbedtls_test_cli_crt = mbedtls_test_cli_crt_rsa; +const char *mbedtls_test_cli_key = mbedtls_test_cli_key_rsa; +const size_t mbedtls_test_ca_crt_len = sizeof( mbedtls_test_ca_crt_rsa ); +const size_t mbedtls_test_ca_key_len = sizeof( mbedtls_test_ca_key_rsa ); +const size_t mbedtls_test_ca_pwd_len = sizeof( mbedtls_test_ca_pwd_rsa ) - 1; +const size_t mbedtls_test_srv_crt_len = sizeof( mbedtls_test_srv_crt_rsa ); +const size_t mbedtls_test_srv_key_len = sizeof( mbedtls_test_srv_key_rsa ); +const size_t mbedtls_test_cli_crt_len = sizeof( mbedtls_test_cli_crt_rsa ); +const size_t mbedtls_test_cli_key_len = sizeof( mbedtls_test_cli_key_rsa ); +#else /* ! MBEDTLS_RSA_C, so MBEDTLS_ECDSA_C */ +const char *mbedtls_test_ca_crt = mbedtls_test_ca_crt_ec; +const char *mbedtls_test_ca_key = mbedtls_test_ca_key_ec; +const char *mbedtls_test_ca_pwd = mbedtls_test_ca_pwd_ec; +const char *mbedtls_test_srv_crt = mbedtls_test_srv_crt_ec; +const char *mbedtls_test_srv_key = mbedtls_test_srv_key_ec; +const char *mbedtls_test_cli_crt = mbedtls_test_cli_crt_ec; +const char *mbedtls_test_cli_key = mbedtls_test_cli_key_ec; +const size_t mbedtls_test_ca_crt_len = sizeof( mbedtls_test_ca_crt_ec ); +const size_t mbedtls_test_ca_key_len = sizeof( mbedtls_test_ca_key_ec ); +const size_t mbedtls_test_ca_pwd_len = sizeof( mbedtls_test_ca_pwd_ec ) - 1; +const size_t mbedtls_test_srv_crt_len = sizeof( mbedtls_test_srv_crt_ec ); +const size_t mbedtls_test_srv_key_len = sizeof( mbedtls_test_srv_key_ec ); +const size_t mbedtls_test_cli_crt_len = sizeof( mbedtls_test_cli_crt_ec ); +const size_t mbedtls_test_cli_key_len = sizeof( mbedtls_test_cli_key_ec ); +#endif /* MBEDTLS_RSA_C */ + +#endif /* MBEDTLS_CERTS_C */ diff --git a/common/mbedtls/certs.h b/common/mbedtls/certs.h new file mode 100644 index 000000000..ae0f84a30 --- /dev/null +++ b/common/mbedtls/certs.h @@ -0,0 +1,102 @@ +/** + * \file certs.h + * + * \brief Sample certificates and DHM parameters for testing + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_CERTS_H +#define MBEDTLS_CERTS_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +/* Concatenation of all CA certificates in PEM format if available */ +extern const char mbedtls_test_cas_pem[]; +extern const size_t mbedtls_test_cas_pem_len; +#endif + +/* List of all CA certificates, terminated by NULL */ +extern const char * mbedtls_test_cas[]; +extern const size_t mbedtls_test_cas_len[]; + +/* + * Convenience for users who just want a certificate: + * RSA by default, or ECDSA if RSA is not available + */ +extern const char * mbedtls_test_ca_crt; +extern const size_t mbedtls_test_ca_crt_len; +extern const char * mbedtls_test_ca_key; +extern const size_t mbedtls_test_ca_key_len; +extern const char * mbedtls_test_ca_pwd; +extern const size_t mbedtls_test_ca_pwd_len; +extern const char * mbedtls_test_srv_crt; +extern const size_t mbedtls_test_srv_crt_len; +extern const char * mbedtls_test_srv_key; +extern const size_t mbedtls_test_srv_key_len; +extern const char * mbedtls_test_cli_crt; +extern const size_t mbedtls_test_cli_crt_len; +extern const char * mbedtls_test_cli_key; +extern const size_t mbedtls_test_cli_key_len; + +#if defined(MBEDTLS_ECDSA_C) +extern const char mbedtls_test_ca_crt_ec[]; +extern const size_t mbedtls_test_ca_crt_ec_len; +extern const char mbedtls_test_ca_key_ec[]; +extern const size_t mbedtls_test_ca_key_ec_len; +extern const char mbedtls_test_ca_pwd_ec[]; +extern const size_t mbedtls_test_ca_pwd_ec_len; +extern const char mbedtls_test_srv_crt_ec[]; +extern const size_t mbedtls_test_srv_crt_ec_len; +extern const char mbedtls_test_srv_key_ec[]; +extern const size_t mbedtls_test_srv_key_ec_len; +extern const char mbedtls_test_cli_crt_ec[]; +extern const size_t mbedtls_test_cli_crt_ec_len; +extern const char mbedtls_test_cli_key_ec[]; +extern const size_t mbedtls_test_cli_key_ec_len; +#endif + +#if defined(MBEDTLS_RSA_C) +extern const char mbedtls_test_ca_crt_rsa[]; +extern const size_t mbedtls_test_ca_crt_rsa_len; +extern const char mbedtls_test_ca_key_rsa[]; +extern const size_t mbedtls_test_ca_key_rsa_len; +extern const char mbedtls_test_ca_pwd_rsa[]; +extern const size_t mbedtls_test_ca_pwd_rsa_len; +extern const char mbedtls_test_srv_crt_rsa[]; +extern const size_t mbedtls_test_srv_crt_rsa_len; +extern const char mbedtls_test_srv_key_rsa[]; +extern const size_t mbedtls_test_srv_key_rsa_len; +extern const char mbedtls_test_cli_crt_rsa[]; +extern const size_t mbedtls_test_cli_crt_rsa_len; +extern const char mbedtls_test_cli_key_rsa[]; +extern const size_t mbedtls_test_cli_key_rsa_len; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* certs.h */ diff --git a/common/mbedtls/check_config.h b/common/mbedtls/check_config.h new file mode 100644 index 000000000..a4fa7bdde --- /dev/null +++ b/common/mbedtls/check_config.h @@ -0,0 +1,685 @@ +/** + * \file check_config.h + * + * \brief Consistency checks for configuration options + */ +/* + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * It is recommended to include this file from your config.h + * in order to catch dependency issues early. + */ + +#ifndef MBEDTLS_CHECK_CONFIG_H +#define MBEDTLS_CHECK_CONFIG_H + +/* + * We assume CHAR_BIT is 8 in many places. In practice, this is true on our + * target platforms, so not an issue, but let's just be extra sure. + */ +#include +#if CHAR_BIT != 8 +#error "mbed TLS requires a platform with 8-bit chars" +#endif + +#if defined(_WIN32) +#if !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_C is required on Windows" +#endif + +/* Fix the config here. Not convenient to put an #ifdef _WIN32 in config.h as + * it would confuse config.pl. */ +#if !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && \ + !defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define MBEDTLS_PLATFORM_SNPRINTF_ALT +#endif +#endif /* _WIN32 */ + +#if defined(TARGET_LIKE_MBED) && \ + ( defined(MBEDTLS_NET_C) || defined(MBEDTLS_TIMING_C) ) +#error "The NET and TIMING modules are not available for mbed OS - please use the network and timing functions provided by mbed OS" +#endif + +#if defined(MBEDTLS_DEPRECATED_WARNING) && \ + !defined(__GNUC__) && !defined(__clang__) +#error "MBEDTLS_DEPRECATED_WARNING only works with GCC and Clang" +#endif + +#if defined(MBEDTLS_HAVE_TIME_DATE) && !defined(MBEDTLS_HAVE_TIME) +#error "MBEDTLS_HAVE_TIME_DATE without MBEDTLS_HAVE_TIME does not make sense" +#endif + +#if defined(MBEDTLS_AESNI_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_AESNI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) && !defined(MBEDTLS_AES_C) +#error "MBEDTLS_CTR_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_DHM_C) && !defined(MBEDTLS_BIGNUM_C) +#error "MBEDTLS_DHM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT) && !defined(MBEDTLS_SSL_TRUNCATED_HMAC) +#error "MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_CMAC_C) && \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_DES_C) +#error "MBEDTLS_CMAC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_NIST_KW_C) && \ + ( !defined(MBEDTLS_AES_C) || !defined(MBEDTLS_CIPHER_C) ) +#error "MBEDTLS_NIST_KW_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDH_C) && !defined(MBEDTLS_ECP_C) +#error "MBEDTLS_ECDH_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_C) && \ + ( !defined(MBEDTLS_ECP_C) || \ + !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_ASN1_WRITE_C) ) +#error "MBEDTLS_ECDSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECJPAKE_C) && \ + ( !defined(MBEDTLS_ECP_C) || !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_ECJPAKE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) && !defined(MBEDTLS_HMAC_DRBG_C) +#error "MBEDTLS_ECDSA_DETERMINISTIC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_C) && ( !defined(MBEDTLS_BIGNUM_C) || ( \ + !defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) && \ + !defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) ) ) +#error "MBEDTLS_ECP_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_C) && (!defined(MBEDTLS_SHA512_C) && \ + !defined(MBEDTLS_SHA256_C)) +#error "MBEDTLS_ENTROPY_C defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_ENTROPY_C) && defined(MBEDTLS_SHA512_C) && \ + defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 64) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + ( !defined(MBEDTLS_SHA512_C) || defined(MBEDTLS_ENTROPY_FORCE_SHA256) ) \ + && defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) && (MBEDTLS_CTR_DRBG_ENTROPY_LEN > 32) +#error "MBEDTLS_CTR_DRBG_ENTROPY_LEN value too high" +#endif +#if defined(MBEDTLS_ENTROPY_C) && \ + defined(MBEDTLS_ENTROPY_FORCE_SHA256) && !defined(MBEDTLS_SHA256_C) +#error "MBEDTLS_ENTROPY_FORCE_SHA256 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( !defined(MBEDTLS_ENTROPY_C) || !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but not all prerequisites" +#endif +#if defined(MBEDTLS_TEST_NULL_ENTROPY) && \ + ( defined(MBEDTLS_ENTROPY_NV_SEED) || defined(MBEDTLS_ENTROPY_HARDWARE_ALT) || \ + defined(MBEDTLS_HAVEGE_C) ) +#error "MBEDTLS_TEST_NULL_ENTROPY defined, but entropy sources too" +#endif + +#if defined(MBEDTLS_GCM_C) && ( \ + !defined(MBEDTLS_AES_C) && !defined(MBEDTLS_CAMELLIA_C) ) +#error "MBEDTLS_GCM_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_ADD_MIXED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_JAC_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_RANDOMIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) && !defined(MBEDTLS_ECP_INTERNAL_ALT) +#error "MBEDTLS_ECP_NORMALIZE_MXZ_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVEGE_C) && !defined(MBEDTLS_TIMING_C) +#error "MBEDTLS_HAVEGE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HKDF_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HKDF_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) && !defined(MBEDTLS_MD_C) +#error "MBEDTLS_HMAC_DRBG_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED) && !defined(MBEDTLS_DHM_C) +#error "MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED) && \ + !defined(MBEDTLS_ECDH_C) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_DHM_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_RSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) || !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED) && \ + ( !defined(MBEDTLS_ECDH_C) || !defined(MBEDTLS_ECDSA_C) || \ + !defined(MBEDTLS_X509_CRT_PARSE_C) ) +#error "MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_RSA_ENABLED) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_X509_CRT_PARSE_C) || \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_KEY_EXCHANGE_RSA_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED) && \ + ( !defined(MBEDTLS_ECJPAKE_C) || !defined(MBEDTLS_SHA256_C) || \ + !defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) ) +#error "MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_MEMORY_BUFFER_ALLOC_C) && \ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_MEMORY_BUFFER_ALLOC_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PADLOCK_C) && !defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_PADLOCK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PEM_WRITE_C) && !defined(MBEDTLS_BASE64_C) +#error "MBEDTLS_PEM_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_C) && \ + ( !defined(MBEDTLS_RSA_C) && !defined(MBEDTLS_ECP_C) ) +#error "MBEDTLS_PK_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_PARSE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PK_WRITE_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PK_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PKCS11_C) && !defined(MBEDTLS_PK_C) +#error "MBEDTLS_PKCS11_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_EXIT_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_EXIT) ||\ + defined(MBEDTLS_PLATFORM_EXIT_ALT) ) +#error "MBEDTLS_PLATFORM_EXIT_MACRO and MBEDTLS_PLATFORM_STD_EXIT/MBEDTLS_PLATFORM_EXIT_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_TIME_TYPE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_TIME) ||\ + defined(MBEDTLS_PLATFORM_TIME_ALT) ) +#error "MBEDTLS_PLATFORM_TIME_TYPE_MACRO and MBEDTLS_PLATFORM_STD_TIME/MBEDTLS_PLATFORM_TIME_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_FPRINTF) ||\ + defined(MBEDTLS_PLATFORM_FPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_FPRINTF_MACRO and MBEDTLS_PLATFORM_STD_FPRINTF/MBEDTLS_PLATFORM_FPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_FREE_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_FREE) +#error "MBEDTLS_PLATFORM_FREE_MACRO and MBEDTLS_PLATFORM_STD_FREE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && !defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO must be defined if MBEDTLS_PLATFORM_FREE_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_PLATFORM_MEMORY) ) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) &&\ + defined(MBEDTLS_PLATFORM_STD_CALLOC) +#error "MBEDTLS_PLATFORM_CALLOC_MACRO and MBEDTLS_PLATFORM_STD_CALLOC cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_CALLOC_MACRO) && !defined(MBEDTLS_PLATFORM_FREE_MACRO) +#error "MBEDTLS_PLATFORM_FREE_MACRO must be defined if MBEDTLS_PLATFORM_CALLOC_MACRO is" +#endif + +#if defined(MBEDTLS_PLATFORM_MEMORY) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_MEMORY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_PRINTF) ||\ + defined(MBEDTLS_PLATFORM_PRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_PRINTF_MACRO and MBEDTLS_PLATFORM_STD_PRINTF/MBEDTLS_PLATFORM_PRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) && !defined(MBEDTLS_PLATFORM_C) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_SNPRINTF) ||\ + defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) ) +#error "MBEDTLS_PLATFORM_SNPRINTF_MACRO and MBEDTLS_PLATFORM_STD_SNPRINTF/MBEDTLS_PLATFORM_SNPRINTF_ALT cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) &&\ + !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) +#error "MBEDTLS_PLATFORM_STD_MEM_HDR defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_CALLOC) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_CALLOC defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FREE) && !defined(MBEDTLS_PLATFORM_MEMORY) +#error "MBEDTLS_PLATFORM_STD_FREE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_EXIT) &&\ + !defined(MBEDTLS_PLATFORM_EXIT_ALT) +#error "MBEDTLS_PLATFORM_STD_EXIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_TIME) &&\ + ( !defined(MBEDTLS_PLATFORM_TIME_ALT) ||\ + !defined(MBEDTLS_HAVE_TIME) ) +#error "MBEDTLS_PLATFORM_STD_TIME defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_FPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_FPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_PRINTF) &&\ + !defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_PRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_SNPRINTF) &&\ + !defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#error "MBEDTLS_PLATFORM_STD_SNPRINTF defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) &&\ + ( !defined(MBEDTLS_PLATFORM_C) || !defined(MBEDTLS_ENTROPY_C) ) +#error "MBEDTLS_ENTROPY_NV_SEED defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) &&\ + !defined(MBEDTLS_ENTROPY_NV_SEED) +#error "MBEDTLS_PLATFORM_NV_SEED_ALT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_READ defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) &&\ + !defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#error "MBEDTLS_PLATFORM_STD_NV_SEED_WRITE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_READ_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_READ cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) &&\ + ( defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) ||\ + defined(MBEDTLS_PLATFORM_NV_SEED_ALT) ) +#error "MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO and MBEDTLS_PLATFORM_STD_NV_SEED_WRITE cannot be defined simultaneously" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) ) +#error "MBEDTLS_RSA_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_RSA_C) && ( !defined(MBEDTLS_PKCS1_V21) && \ + !defined(MBEDTLS_PKCS1_V15) ) +#error "MBEDTLS_RSA_C defined, but none of the PKCS1 versions enabled" +#endif + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) && \ + ( !defined(MBEDTLS_RSA_C) || !defined(MBEDTLS_PKCS1_V21) ) +#error "MBEDTLS_X509_RSASSA_PSS_SUPPORT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_SSL3) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_SSL3 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_1) && ( !defined(MBEDTLS_MD5_C) || \ + !defined(MBEDTLS_SHA1_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_1 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_TLS1_2) && ( !defined(MBEDTLS_SHA1_C) && \ + !defined(MBEDTLS_SHA256_C) && !defined(MBEDTLS_SHA512_C) ) +#error "MBEDTLS_SSL_PROTO_TLS1_2 defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_PROTO_DTLS) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_PROTO_DTLS defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CLI_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_CLI_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && ( !defined(MBEDTLS_CIPHER_C) || \ + !defined(MBEDTLS_MD_C) ) +#error "MBEDTLS_SSL_TLS_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SRV_C) && !defined(MBEDTLS_SSL_TLS_C) +#error "MBEDTLS_SSL_SRV_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (!defined(MBEDTLS_SSL_PROTO_SSL3) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2)) +#error "MBEDTLS_SSL_TLS_C defined, but no protocols are active" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_1) && !defined(MBEDTLS_SSL_PROTO_TLS1)) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_TLS1) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && !defined(MBEDTLS_SSL_PROTO_TLS1_1)) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) && (defined(MBEDTLS_SSL_PROTO_SSL3) && \ + defined(MBEDTLS_SSL_PROTO_TLS1_2) && (!defined(MBEDTLS_SSL_PROTO_TLS1) || \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1))) +#error "Illegal protocol selection" +#endif + +#if defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) && !defined(MBEDTLS_SSL_PROTO_DTLS) +#error "MBEDTLS_SSL_DTLS_HELLO_VERIFY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE) && \ + !defined(MBEDTLS_SSL_DTLS_HELLO_VERIFY) +#error "MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_ANTI_REPLAY) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_ANTI_REPLAY defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_DTLS_BADMAC_LIMIT) && \ + ( !defined(MBEDTLS_SSL_TLS_C) || !defined(MBEDTLS_SSL_PROTO_DTLS) ) +#error "MBEDTLS_SSL_DTLS_BADMAC_LIMIT defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_ENCRYPT_THEN_MAC) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_ENCRYPT_THEN_MAC defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_EXTENDED_MASTER_SECRET) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_1) && \ + !defined(MBEDTLS_SSL_PROTO_TLS1_2) +#error "MBEDTLS_SSL_EXTENDED_MASTER_SECRET defined, but not all prerequsites" +#endif + +#if defined(MBEDTLS_SSL_TICKET_C) && !defined(MBEDTLS_CIPHER_C) +#error "MBEDTLS_SSL_TICKET_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_CBC_RECORD_SPLITTING) && \ + !defined(MBEDTLS_SSL_PROTO_SSL3) && !defined(MBEDTLS_SSL_PROTO_TLS1) +#error "MBEDTLS_SSL_CBC_RECORD_SPLITTING defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_SSL_SERVER_NAME_INDICATION) && \ + !defined(MBEDTLS_X509_CRT_PARSE_C) +#error "MBEDTLS_SSL_SERVER_NAME_INDICATION defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_THREADING_PTHREAD) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_PTHREAD defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_ALT) +#if !defined(MBEDTLS_THREADING_C) || defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_ALT defined, but not all prerequisites" +#endif +#define MBEDTLS_THREADING_IMPL +#endif + +#if defined(MBEDTLS_THREADING_C) && !defined(MBEDTLS_THREADING_IMPL) +#error "MBEDTLS_THREADING_C defined, single threading implementation required" +#endif +#undef MBEDTLS_THREADING_IMPL + +#if defined(MBEDTLS_VERSION_FEATURES) && !defined(MBEDTLS_VERSION_C) +#error "MBEDTLS_VERSION_FEATURES defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_USE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_PARSE_C) || \ + !defined(MBEDTLS_PK_PARSE_C) ) +#error "MBEDTLS_X509_USE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CREATE_C) && ( !defined(MBEDTLS_BIGNUM_C) || \ + !defined(MBEDTLS_OID_C) || !defined(MBEDTLS_ASN1_WRITE_C) || \ + !defined(MBEDTLS_PK_WRITE_C) ) +#error "MBEDTLS_X509_CREATE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRT_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRL_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CRL_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_PARSE_C) && ( !defined(MBEDTLS_X509_USE_C) ) +#error "MBEDTLS_X509_CSR_PARSE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CRT_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CRT_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_X509_CSR_WRITE_C) && ( !defined(MBEDTLS_X509_CREATE_C) ) +#error "MBEDTLS_X509_CSR_WRITE_C defined, but not all prerequisites" +#endif + +#if defined(MBEDTLS_HAVE_INT32) && defined(MBEDTLS_HAVE_INT64) +#error "MBEDTLS_HAVE_INT32 and MBEDTLS_HAVE_INT64 cannot be defined simultaneously" +#endif /* MBEDTLS_HAVE_INT32 && MBEDTLS_HAVE_INT64 */ + +#if ( defined(MBEDTLS_HAVE_INT32) || defined(MBEDTLS_HAVE_INT64) ) && \ + defined(MBEDTLS_HAVE_ASM) +#error "MBEDTLS_HAVE_INT32/MBEDTLS_HAVE_INT64 and MBEDTLS_HAVE_ASM cannot be defined simultaneously" +#endif /* (MBEDTLS_HAVE_INT32 || MBEDTLS_HAVE_INT64) && MBEDTLS_HAVE_ASM */ + +/* + * Avoid warning from -pedantic. This is a convenient place for this + * workaround since this is included by every single file before the + * #if defined(MBEDTLS_xxx_C) that results in emtpy translation units. + */ +typedef int mbedtls_iso_c_forbids_empty_translation_units; + +#endif /* MBEDTLS_CHECK_CONFIG_H */ diff --git a/common/mbedtls/cipher.c b/common/mbedtls/cipher.c new file mode 100644 index 000000000..de9402a2f --- /dev/null +++ b/common/mbedtls/cipher.c @@ -0,0 +1,1108 @@ +/** + * \file cipher.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CIPHER_C) + +#include "mbedtls/cipher.h" +#include "mbedtls/cipher_internal.h" +#include "mbedtls/platform_util.h" + +#include +#include + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/* Compare the contents of two buffers in constant time. + * Returns 0 if the contents are bitwise identical, otherwise returns + * a non-zero value. + * This is currently only used by GCM and ChaCha20+Poly1305. + */ +static int mbedtls_constant_time_memcmp( const void *v1, const void *v2, size_t len ) +{ + const unsigned char *p1 = (const unsigned char*) v1; + const unsigned char *p2 = (const unsigned char*) v2; + size_t i; + unsigned char diff; + + for( diff = 0, i = 0; i < len; i++ ) + diff |= p1[i] ^ p2[i]; + + return (int)diff; +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +static int supported_init = 0; + +const int *mbedtls_cipher_list( void ) +{ + const mbedtls_cipher_definition_t *def; + int *type; + + if( ! supported_init ) + { + def = mbedtls_cipher_definitions; + type = mbedtls_cipher_supported; + + while( def->type != 0 ) + *type++ = (*def++).type; + + *type = 0; + + supported_init = 1; + } + + return( mbedtls_cipher_supported ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->type == cipher_type ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ) +{ + const mbedtls_cipher_definition_t *def; + + if( NULL == cipher_name ) + return( NULL ); + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( ! strcmp( def->info->name, cipher_name ) ) + return( def->info ); + + return( NULL ); +} + +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ) +{ + const mbedtls_cipher_definition_t *def; + + for( def = mbedtls_cipher_definitions; def->info != NULL; def++ ) + if( def->info->base->cipher == cipher_id && + def->info->key_bitlen == (unsigned) key_bitlen && + def->info->mode == mode ) + return( def->info ); + + return( NULL ); +} + +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); +} + +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_CMAC_C) + if( ctx->cmac_ctx ) + { + mbedtls_platform_zeroize( ctx->cmac_ctx, + sizeof( mbedtls_cmac_context_t ) ); + mbedtls_free( ctx->cmac_ctx ); + } +#endif + + if( ctx->cipher_ctx ) + ctx->cipher_info->base->ctx_free_func( ctx->cipher_ctx ); + + mbedtls_platform_zeroize( ctx, sizeof(mbedtls_cipher_context_t) ); +} + +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ) +{ + if( NULL == cipher_info || NULL == ctx ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + memset( ctx, 0, sizeof( mbedtls_cipher_context_t ) ); + + if( NULL == ( ctx->cipher_ctx = cipher_info->base->ctx_alloc_func() ) ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cipher_info = cipher_info; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /* + * Ignore possible errors caused by a cipher mode that doesn't use padding + */ +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_PKCS7 ); +#else + (void) mbedtls_cipher_set_padding_mode( ctx, MBEDTLS_PADDING_NONE ); +#endif +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + + return( 0 ); +} + +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, + int key_bitlen, const mbedtls_operation_t operation ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_KEY_LEN ) == 0 && + (int) ctx->cipher_info->key_bitlen != key_bitlen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + ctx->key_bitlen = key_bitlen; + ctx->operation = operation; + + /* + * For OFB, CFB and CTR mode always use the encryption key schedule + */ + if( MBEDTLS_ENCRYPT == operation || + MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_OFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode ) + { + return ctx->cipher_info->base->setkey_enc_func( ctx->cipher_ctx, key, + ctx->key_bitlen ); + } + + if( MBEDTLS_DECRYPT == operation ) + return ctx->cipher_info->base->setkey_dec_func( ctx->cipher_ctx, key, + ctx->key_bitlen ); + + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); +} + +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len ) +{ + size_t actual_iv_size; + + if( NULL == ctx || NULL == ctx->cipher_info || NULL == iv ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + /* avoid buffer overflow in ctx->iv */ + if( iv_len > MBEDTLS_MAX_IV_LENGTH ) + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + + if( ( ctx->cipher_info->flags & MBEDTLS_CIPHER_VARIABLE_IV_LEN ) != 0 ) + actual_iv_size = iv_len; + else + { + actual_iv_size = ctx->cipher_info->iv_size; + + /* avoid reading past the end of input buffer */ + if( actual_iv_size > iv_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_CHACHA20_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20 ) + { + if ( 0 != mbedtls_chacha20_starts( (mbedtls_chacha20_context*)ctx->cipher_ctx, + iv, + 0U ) ) /* Initial counter value */ + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + } +#endif + + memcpy( ctx->iv, iv, actual_iv_size ); + ctx->iv_size = actual_iv_size; + + return( 0 ); +} + +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + ctx->unprocessed_len = 0; + + return( 0 ); +} + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + return mbedtls_gcm_starts( (mbedtls_gcm_context *) ctx->cipher_ctx, ctx->operation, + ctx->iv, ctx->iv_size, ad, ad_len ); + } +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if (MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + int result; + mbedtls_chachapoly_mode_t mode; + + mode = ( ctx->operation == MBEDTLS_ENCRYPT ) + ? MBEDTLS_CHACHAPOLY_ENCRYPT + : MBEDTLS_CHACHAPOLY_DECRYPT; + + result = mbedtls_chachapoly_starts( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ctx->iv, + mode ); + if ( result != 0 ) + return( result ); + + return mbedtls_chachapoly_update_aad( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ad, ad_len ); + } +#endif + + return( 0 ); +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ) +{ + int ret; + size_t block_size = 0; + + if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = 0; + block_size = mbedtls_cipher_get_block_size( ctx ); + + if( ctx->cipher_info->mode == MBEDTLS_MODE_ECB ) + { + if( ilen != block_size ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + *olen = ilen; + + if( 0 != ( ret = ctx->cipher_info->base->ecb_func( ctx->cipher_ctx, + ctx->operation, input, output ) ) ) + { + return( ret ); + } + + return( 0 ); + } + +#if defined(MBEDTLS_GCM_C) + if( ctx->cipher_info->mode == MBEDTLS_MODE_GCM ) + { + *olen = ilen; + return mbedtls_gcm_update( (mbedtls_gcm_context *) ctx->cipher_ctx, ilen, input, + output ); + } +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( ctx->cipher_info->type == MBEDTLS_CIPHER_CHACHA20_POLY1305 ) + { + *olen = ilen; + return mbedtls_chachapoly_update( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + ilen, input, output ); + } +#endif + + if ( 0 == block_size ) + { + return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + } + + if( input == output && + ( ctx->unprocessed_len != 0 || ilen % block_size ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CBC ) + { + size_t copy_len = 0; + + /* + * If there is not enough data for a full block, cache it. + */ + if( ( ctx->operation == MBEDTLS_DECRYPT && NULL != ctx->add_padding && + ilen <= block_size - ctx->unprocessed_len ) || + ( ctx->operation == MBEDTLS_DECRYPT && NULL == ctx->add_padding && + ilen < block_size - ctx->unprocessed_len ) || + ( ctx->operation == MBEDTLS_ENCRYPT && + ilen < block_size - ctx->unprocessed_len ) ) + { + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + ilen ); + + ctx->unprocessed_len += ilen; + return( 0 ); + } + + /* + * Process cached data first + */ + if( 0 != ctx->unprocessed_len ) + { + copy_len = block_size - ctx->unprocessed_len; + + memcpy( &( ctx->unprocessed_data[ctx->unprocessed_len] ), input, + copy_len ); + + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, block_size, ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + *olen += block_size; + output += block_size; + ctx->unprocessed_len = 0; + + input += copy_len; + ilen -= copy_len; + } + + /* + * Cache final, incomplete block + */ + if( 0 != ilen ) + { + if( 0 == block_size ) + { + return MBEDTLS_ERR_CIPHER_INVALID_CONTEXT; + } + + /* Encryption: only cache partial blocks + * Decryption w/ padding: always keep at least one whole block + * Decryption w/o padding: only cache partial blocks + */ + copy_len = ilen % block_size; + if( copy_len == 0 && + ctx->operation == MBEDTLS_DECRYPT && + NULL != ctx->add_padding) + { + copy_len = block_size; + } + + memcpy( ctx->unprocessed_data, &( input[ilen - copy_len] ), + copy_len ); + + ctx->unprocessed_len += copy_len; + ilen -= copy_len; + } + + /* + * Process remaining full blocks + */ + if( ilen ) + { + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen += ilen; + } + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->cfb_func( ctx->cipher_ctx, + ctx->operation, ilen, &ctx->unprocessed_len, ctx->iv, + input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + if( ctx->cipher_info->mode == MBEDTLS_MODE_OFB ) + { + if( 0 != ( ret = ctx->cipher_info->base->ofb_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + if( ctx->cipher_info->mode == MBEDTLS_MODE_CTR ) + { + if( 0 != ( ret = ctx->cipher_info->base->ctr_func( ctx->cipher_ctx, + ilen, &ctx->unprocessed_len, ctx->iv, + ctx->unprocessed_data, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + if( ctx->cipher_info->mode == MBEDTLS_MODE_XTS ) + { + if( ctx->unprocessed_len > 0 ) { + /* We can only process an entire data unit at a time. */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + ret = ctx->cipher_info->base->xts_func( ctx->cipher_ctx, + ctx->operation, ilen, ctx->iv, input, output ); + if( ret != 0 ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + if( ctx->cipher_info->mode == MBEDTLS_MODE_STREAM ) + { + if( 0 != ( ret = ctx->cipher_info->base->stream_func( ctx->cipher_ctx, + ilen, input, output ) ) ) + { + return( ret ); + } + + *olen = ilen; + + return( 0 ); + } +#endif /* MBEDTLS_CIPHER_MODE_STREAM */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) +/* + * PKCS7 (and PKCS5) padding: fill with ll bytes, with ll = padding_len + */ +static void add_pkcs_padding( unsigned char *output, size_t output_len, + size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i; + + for( i = 0; i < padding_len; i++ ) + output[data_len + i] = (unsigned char) padding_len; +} + +static int get_pkcs_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len, + * so pick input_len, which is usually 8 or 16 (one block) */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len; i++ ) + bad |= ( input[i] ^ padding_len ) * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_PKCS7 */ + +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) +/* + * One and zeros padding: fill with 80 00 ... 00 + */ +static void add_one_and_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + output[data_len] = 0x80; + for( i = 1; i < padding_len; i++ ) + output[data_len + i] = 0x00; +} + +static int get_one_and_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done, bad; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + bad = 0x80; + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i - 1] != 0 ); + *data_len |= ( i - 1 ) * ( done != prev_done ); + bad ^= input[i - 1] * ( done != prev_done ); + } + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); + +} +#endif /* MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) +/* + * Zeros and len padding: fill with 00 ... 00 ll, where ll is padding length + */ +static void add_zeros_and_len_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t padding_len = output_len - data_len; + unsigned char i = 0; + + for( i = 1; i < padding_len; i++ ) + output[data_len + i - 1] = 0x00; + output[output_len - 1] = (unsigned char) padding_len; +} + +static int get_zeros_and_len_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i, pad_idx; + unsigned char padding_len, bad = 0; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + padding_len = input[input_len - 1]; + *data_len = input_len - padding_len; + + /* Avoid logical || since it results in a branch */ + bad |= padding_len > input_len; + bad |= padding_len == 0; + + /* The number of bytes checked must be independent of padding_len */ + pad_idx = input_len - padding_len; + for( i = 0; i < input_len - 1; i++ ) + bad |= input[i] * ( i >= pad_idx ); + + return( MBEDTLS_ERR_CIPHER_INVALID_PADDING * ( bad != 0 ) ); +} +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN */ + +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) +/* + * Zero padding: fill with 00 ... 00 + */ +static void add_zeros_padding( unsigned char *output, + size_t output_len, size_t data_len ) +{ + size_t i; + + for( i = data_len; i < output_len; i++ ) + output[i] = 0x00; +} + +static int get_zeros_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + size_t i; + unsigned char done = 0, prev_done; + + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = 0; + for( i = input_len; i > 0; i-- ) + { + prev_done = done; + done |= ( input[i-1] != 0 ); + *data_len |= i * ( done != prev_done ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_PADDING_ZEROS */ + +/* + * No padding: don't pad :) + * + * There is no add_padding function (check for NULL in mbedtls_cipher_finish) + * but a trivial get_padding function + */ +static int get_no_padding( unsigned char *input, size_t input_len, + size_t *data_len ) +{ + if( NULL == input || NULL == data_len ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *data_len = input_len; + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ) +{ + if( NULL == ctx || NULL == ctx->cipher_info || NULL == olen ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + *olen = 0; + + if( MBEDTLS_MODE_CFB == ctx->cipher_info->mode || + MBEDTLS_MODE_OFB == ctx->cipher_info->mode || + MBEDTLS_MODE_CTR == ctx->cipher_info->mode || + MBEDTLS_MODE_GCM == ctx->cipher_info->mode || + MBEDTLS_MODE_XTS == ctx->cipher_info->mode || + MBEDTLS_MODE_STREAM == ctx->cipher_info->mode ) + { + return( 0 ); + } + + if ( ( MBEDTLS_CIPHER_CHACHA20 == ctx->cipher_info->type ) || + ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) ) + { + return( 0 ); + } + + if( MBEDTLS_MODE_ECB == ctx->cipher_info->mode ) + { + if( ctx->unprocessed_len != 0 ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + if( MBEDTLS_MODE_CBC == ctx->cipher_info->mode ) + { + int ret = 0; + + if( MBEDTLS_ENCRYPT == ctx->operation ) + { + /* check for 'no padding' mode */ + if( NULL == ctx->add_padding ) + { + if( 0 != ctx->unprocessed_len ) + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + + return( 0 ); + } + + ctx->add_padding( ctx->unprocessed_data, mbedtls_cipher_get_iv_size( ctx ), + ctx->unprocessed_len ); + } + else if( mbedtls_cipher_get_block_size( ctx ) != ctx->unprocessed_len ) + { + /* + * For decrypt operations, expect a full block, + * or an empty block if no padding + */ + if( NULL == ctx->add_padding && 0 == ctx->unprocessed_len ) + return( 0 ); + + return( MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED ); + } + + /* cipher block */ + if( 0 != ( ret = ctx->cipher_info->base->cbc_func( ctx->cipher_ctx, + ctx->operation, mbedtls_cipher_get_block_size( ctx ), ctx->iv, + ctx->unprocessed_data, output ) ) ) + { + return( ret ); + } + + /* Set output size for decryption */ + if( MBEDTLS_DECRYPT == ctx->operation ) + return ctx->get_padding( output, mbedtls_cipher_get_block_size( ctx ), + olen ); + + /* Set output size for encryption */ + *olen = mbedtls_cipher_get_block_size( ctx ); + return( 0 ); + } +#else + ((void) output); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ) +{ + if( NULL == ctx || + MBEDTLS_MODE_CBC != ctx->cipher_info->mode ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + switch( mode ) + { +#if defined(MBEDTLS_CIPHER_PADDING_PKCS7) + case MBEDTLS_PADDING_PKCS7: + ctx->add_padding = add_pkcs_padding; + ctx->get_padding = get_pkcs_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS) + case MBEDTLS_PADDING_ONE_AND_ZEROS: + ctx->add_padding = add_one_and_zeros_padding; + ctx->get_padding = get_one_and_zeros_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN) + case MBEDTLS_PADDING_ZEROS_AND_LEN: + ctx->add_padding = add_zeros_and_len_padding; + ctx->get_padding = get_zeros_and_len_padding; + break; +#endif +#if defined(MBEDTLS_CIPHER_PADDING_ZEROS) + case MBEDTLS_PADDING_ZEROS: + ctx->add_padding = add_zeros_padding; + ctx->get_padding = get_zeros_padding; + break; +#endif + case MBEDTLS_PADDING_NONE: + ctx->add_padding = NULL; + ctx->get_padding = get_no_padding; + break; + + default: + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ) +{ + if( NULL == ctx || NULL == ctx->cipher_info || NULL == tag ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( MBEDTLS_ENCRYPT != ctx->operation ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + return mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, tag, tag_len ); +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* Don't allow truncated MAC for Poly1305 */ + if ( tag_len != 16U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + tag ); + } +#endif + + return( 0 ); +} + +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ) +{ + unsigned char check_tag[16]; + int ret; + + if( NULL == ctx || NULL == ctx->cipher_info || + MBEDTLS_DECRYPT != ctx->operation ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + if( tag_len > sizeof( check_tag ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( 0 != ( ret = mbedtls_gcm_finish( (mbedtls_gcm_context *) ctx->cipher_ctx, + check_tag, tag_len ) ) ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) + return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); + + return( 0 ); + } +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* Don't allow truncated MAC for Poly1305 */ + if ( tag_len != sizeof( check_tag ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + ret = mbedtls_chachapoly_finish( (mbedtls_chachapoly_context*) ctx->cipher_ctx, + check_tag ); + if ( ret != 0 ) + { + return( ret ); + } + + /* Check the tag in "constant-time" */ + if( mbedtls_constant_time_memcmp( tag, check_tag, tag_len ) != 0 ) + return( MBEDTLS_ERR_CIPHER_AUTH_FAILED ); + + return( 0 ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ + + return( 0 ); +} +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/* + * Packet-oriented wrapper for non-AEAD modes + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ) +{ + int ret; + size_t finish_olen; + + if( ( ret = mbedtls_cipher_set_iv( ctx, iv, iv_len ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_reset( ctx ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_update( ctx, input, ilen, output, olen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_cipher_finish( ctx, output + *olen, &finish_olen ) ) != 0 ) + return( ret ); + + *olen += finish_olen; + + return( 0 ); +} + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +/* + * Packet-oriented encryption for AEAD modes + */ +int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ) +{ +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( mbedtls_gcm_crypt_and_tag( ctx->cipher_ctx, MBEDTLS_GCM_ENCRYPT, ilen, + iv, iv_len, ad, ad_len, input, output, + tag_len, tag ) ); + } +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) + { + *olen = ilen; + return( mbedtls_ccm_encrypt_and_tag( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, input, output, + tag, tag_len ) ); + } +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + /* ChachaPoly has fixed length nonce and MAC (tag) */ + if ( ( iv_len != ctx->cipher_info->iv_size ) || + ( tag_len != 16U ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = ilen; + return( mbedtls_chachapoly_encrypt_and_tag( ctx->cipher_ctx, + ilen, iv, ad, ad_len, input, output, tag ) ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} + +/* + * Packet-oriented decryption for AEAD modes + */ +int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ) +{ +#if defined(MBEDTLS_GCM_C) + if( MBEDTLS_MODE_GCM == ctx->cipher_info->mode ) + { + int ret; + + *olen = ilen; + ret = mbedtls_gcm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + tag, tag_len, input, output ); + + if( ret == MBEDTLS_ERR_GCM_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_GCM_C */ +#if defined(MBEDTLS_CCM_C) + if( MBEDTLS_MODE_CCM == ctx->cipher_info->mode ) + { + int ret; + + *olen = ilen; + ret = mbedtls_ccm_auth_decrypt( ctx->cipher_ctx, ilen, + iv, iv_len, ad, ad_len, + input, output, tag, tag_len ); + + if( ret == MBEDTLS_ERR_CCM_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_CCM_C */ +#if defined(MBEDTLS_CHACHAPOLY_C) + if ( MBEDTLS_CIPHER_CHACHA20_POLY1305 == ctx->cipher_info->type ) + { + int ret; + + /* ChachaPoly has fixed length nonce and MAC (tag) */ + if ( ( iv_len != ctx->cipher_info->iv_size ) || + ( tag_len != 16U ) ) + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + *olen = ilen; + ret = mbedtls_chachapoly_auth_decrypt( ctx->cipher_ctx, ilen, + iv, ad, ad_len, tag, input, output ); + + if( ret == MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED ) + ret = MBEDTLS_ERR_CIPHER_AUTH_FAILED; + + return( ret ); + } +#endif /* MBEDTLS_CHACHAPOLY_C */ + + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); +} +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#endif /* MBEDTLS_CIPHER_C */ diff --git a/common/mbedtls/cipher.h b/common/mbedtls/cipher.h new file mode 100644 index 000000000..9e3832dde --- /dev/null +++ b/common/mbedtls/cipher.h @@ -0,0 +1,808 @@ +/** + * \file cipher.h + * + * \brief This file contains an abstraction interface for use with the cipher + * primitives provided by the library. It provides a common interface to all of + * the available cipher operations. + * + * \author Adriaan de Jong + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CIPHER_H +#define MBEDTLS_CIPHER_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +#define MBEDTLS_CIPHER_MODE_AEAD +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +#define MBEDTLS_CIPHER_MODE_WITH_PADDING +#endif + +#if defined(MBEDTLS_ARC4_C) || defined(MBEDTLS_CIPHER_NULL_CIPHER) || \ + defined(MBEDTLS_CHACHA20_C) +#define MBEDTLS_CIPHER_MODE_STREAM +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE -0x6080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA -0x6100 /**< Bad input parameters. */ +#define MBEDTLS_ERR_CIPHER_ALLOC_FAILED -0x6180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_CIPHER_INVALID_PADDING -0x6200 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED -0x6280 /**< Decryption of block requires a full block. */ +#define MBEDTLS_ERR_CIPHER_AUTH_FAILED -0x6300 /**< Authentication failed (for AEAD modes). */ +#define MBEDTLS_ERR_CIPHER_INVALID_CONTEXT -0x6380 /**< The context is invalid. For example, because it was freed. */ +#define MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED -0x6400 /**< Cipher hardware accelerator failed. */ + +#define MBEDTLS_CIPHER_VARIABLE_IV_LEN 0x01 /**< Cipher accepts IVs of variable length. */ +#define MBEDTLS_CIPHER_VARIABLE_KEY_LEN 0x02 /**< Cipher accepts keys of variable length. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Supported cipher types. + * + * \warning RC4 and DES are considered weak ciphers and their use + * constitutes a security risk. Arm recommends considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_ID_NONE = 0, /**< Placeholder to mark the end of cipher ID lists. */ + MBEDTLS_CIPHER_ID_NULL, /**< The identity cipher, treated as a stream cipher. */ + MBEDTLS_CIPHER_ID_AES, /**< The AES cipher. */ + MBEDTLS_CIPHER_ID_DES, /**< The DES cipher. */ + MBEDTLS_CIPHER_ID_3DES, /**< The Triple DES cipher. */ + MBEDTLS_CIPHER_ID_CAMELLIA, /**< The Camellia cipher. */ + MBEDTLS_CIPHER_ID_BLOWFISH, /**< The Blowfish cipher. */ + MBEDTLS_CIPHER_ID_ARC4, /**< The RC4 cipher. */ + MBEDTLS_CIPHER_ID_ARIA, /**< The Aria cipher. */ + MBEDTLS_CIPHER_ID_CHACHA20, /**< The ChaCha20 cipher. */ +} mbedtls_cipher_id_t; + +/** + * \brief Supported {cipher type, cipher mode} pairs. + * + * \warning RC4 and DES are considered weak ciphers and their use + * constitutes a security risk. Arm recommends considering stronger + * ciphers instead. + */ +typedef enum { + MBEDTLS_CIPHER_NONE = 0, /**< Placeholder to mark the end of cipher-pair lists. */ + MBEDTLS_CIPHER_NULL, /**< The identity stream cipher. */ + MBEDTLS_CIPHER_AES_128_ECB, /**< AES cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_AES_192_ECB, /**< AES cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_AES_256_ECB, /**< AES cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_AES_128_CBC, /**< AES cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_AES_192_CBC, /**< AES cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_AES_256_CBC, /**< AES cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_AES_128_CFB128, /**< AES cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_192_CFB128, /**< AES cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_256_CFB128, /**< AES cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_AES_128_CTR, /**< AES cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_AES_192_CTR, /**< AES cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_AES_256_CTR, /**< AES cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_AES_128_GCM, /**< AES cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_AES_192_GCM, /**< AES cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_AES_256_GCM, /**< AES cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_ECB, /**< Camellia cipher with 128-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_ECB, /**< Camellia cipher with 192-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_ECB, /**< Camellia cipher with 256-bit ECB mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CBC, /**< Camellia cipher with 128-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CBC, /**< Camellia cipher with 192-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CBC, /**< Camellia cipher with 256-bit CBC mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, /**< Camellia cipher with 128-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, /**< Camellia cipher with 192-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, /**< Camellia cipher with 256-bit CFB128 mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CTR, /**< Camellia cipher with 128-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CTR, /**< Camellia cipher with 192-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CTR, /**< Camellia cipher with 256-bit CTR mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_GCM, /**< Camellia cipher with 128-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_GCM, /**< Camellia cipher with 192-bit GCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_GCM, /**< Camellia cipher with 256-bit GCM mode. */ + MBEDTLS_CIPHER_DES_ECB, /**< DES cipher with ECB mode. */ + MBEDTLS_CIPHER_DES_CBC, /**< DES cipher with CBC mode. */ + MBEDTLS_CIPHER_DES_EDE_ECB, /**< DES cipher with EDE ECB mode. */ + MBEDTLS_CIPHER_DES_EDE_CBC, /**< DES cipher with EDE CBC mode. */ + MBEDTLS_CIPHER_DES_EDE3_ECB, /**< DES cipher with EDE3 ECB mode. */ + MBEDTLS_CIPHER_DES_EDE3_CBC, /**< DES cipher with EDE3 CBC mode. */ + MBEDTLS_CIPHER_BLOWFISH_ECB, /**< Blowfish cipher with ECB mode. */ + MBEDTLS_CIPHER_BLOWFISH_CBC, /**< Blowfish cipher with CBC mode. */ + MBEDTLS_CIPHER_BLOWFISH_CFB64, /**< Blowfish cipher with CFB64 mode. */ + MBEDTLS_CIPHER_BLOWFISH_CTR, /**< Blowfish cipher with CTR mode. */ + MBEDTLS_CIPHER_ARC4_128, /**< RC4 cipher with 128-bit mode. */ + MBEDTLS_CIPHER_AES_128_CCM, /**< AES cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_AES_192_CCM, /**< AES cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_AES_256_CCM, /**< AES cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_128_CCM, /**< Camellia cipher with 128-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_192_CCM, /**< Camellia cipher with 192-bit CCM mode. */ + MBEDTLS_CIPHER_CAMELLIA_256_CCM, /**< Camellia cipher with 256-bit CCM mode. */ + MBEDTLS_CIPHER_ARIA_128_ECB, /**< Aria cipher with 128-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_192_ECB, /**< Aria cipher with 192-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_256_ECB, /**< Aria cipher with 256-bit key and ECB mode. */ + MBEDTLS_CIPHER_ARIA_128_CBC, /**< Aria cipher with 128-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_192_CBC, /**< Aria cipher with 192-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_256_CBC, /**< Aria cipher with 256-bit key and CBC mode. */ + MBEDTLS_CIPHER_ARIA_128_CFB128, /**< Aria cipher with 128-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_192_CFB128, /**< Aria cipher with 192-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_256_CFB128, /**< Aria cipher with 256-bit key and CFB-128 mode. */ + MBEDTLS_CIPHER_ARIA_128_CTR, /**< Aria cipher with 128-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_192_CTR, /**< Aria cipher with 192-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_256_CTR, /**< Aria cipher with 256-bit key and CTR mode. */ + MBEDTLS_CIPHER_ARIA_128_GCM, /**< Aria cipher with 128-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_192_GCM, /**< Aria cipher with 192-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_256_GCM, /**< Aria cipher with 256-bit key and GCM mode. */ + MBEDTLS_CIPHER_ARIA_128_CCM, /**< Aria cipher with 128-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_192_CCM, /**< Aria cipher with 192-bit key and CCM mode. */ + MBEDTLS_CIPHER_ARIA_256_CCM, /**< Aria cipher with 256-bit key and CCM mode. */ + MBEDTLS_CIPHER_AES_128_OFB, /**< AES 128-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_192_OFB, /**< AES 192-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_256_OFB, /**< AES 256-bit cipher in OFB mode. */ + MBEDTLS_CIPHER_AES_128_XTS, /**< AES 128-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_AES_256_XTS, /**< AES 256-bit cipher in XTS block mode. */ + MBEDTLS_CIPHER_CHACHA20, /**< ChaCha20 stream cipher. */ + MBEDTLS_CIPHER_CHACHA20_POLY1305, /**< ChaCha20-Poly1305 AEAD cipher. */ +} mbedtls_cipher_type_t; + +/** Supported cipher modes. */ +typedef enum { + MBEDTLS_MODE_NONE = 0, /**< None. */ + MBEDTLS_MODE_ECB, /**< The ECB cipher mode. */ + MBEDTLS_MODE_CBC, /**< The CBC cipher mode. */ + MBEDTLS_MODE_CFB, /**< The CFB cipher mode. */ + MBEDTLS_MODE_OFB, /**< The OFB cipher mode. */ + MBEDTLS_MODE_CTR, /**< The CTR cipher mode. */ + MBEDTLS_MODE_GCM, /**< The GCM cipher mode. */ + MBEDTLS_MODE_STREAM, /**< The stream cipher mode. */ + MBEDTLS_MODE_CCM, /**< The CCM cipher mode. */ + MBEDTLS_MODE_XTS, /**< The XTS cipher mode. */ + MBEDTLS_MODE_CHACHAPOLY, /**< The ChaCha-Poly cipher mode. */ +} mbedtls_cipher_mode_t; + +/** Supported cipher padding types. */ +typedef enum { + MBEDTLS_PADDING_PKCS7 = 0, /**< PKCS7 padding (default). */ + MBEDTLS_PADDING_ONE_AND_ZEROS, /**< ISO/IEC 7816-4 padding. */ + MBEDTLS_PADDING_ZEROS_AND_LEN, /**< ANSI X.923 padding. */ + MBEDTLS_PADDING_ZEROS, /**< Zero padding (not reversible). */ + MBEDTLS_PADDING_NONE, /**< Never pad (full blocks only). */ +} mbedtls_cipher_padding_t; + +/** Type of operation. */ +typedef enum { + MBEDTLS_OPERATION_NONE = -1, + MBEDTLS_DECRYPT = 0, + MBEDTLS_ENCRYPT, +} mbedtls_operation_t; + +enum { + /** Undefined key length. */ + MBEDTLS_KEY_LENGTH_NONE = 0, + /** Key length, in bits (including parity), for DES keys. */ + MBEDTLS_KEY_LENGTH_DES = 64, + /** Key length in bits, including parity, for DES in two-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE = 128, + /** Key length in bits, including parity, for DES in three-key EDE. */ + MBEDTLS_KEY_LENGTH_DES_EDE3 = 192, +}; + +/** Maximum length of any IV, in Bytes. */ +#define MBEDTLS_MAX_IV_LENGTH 16 +/** Maximum block size of any cipher, in Bytes. */ +#define MBEDTLS_MAX_BLOCK_LENGTH 16 + +/** + * Base cipher information (opaque struct). + */ +typedef struct mbedtls_cipher_base_t mbedtls_cipher_base_t; + +/** + * CMAC context (opaque struct). + */ +typedef struct mbedtls_cmac_context_t mbedtls_cmac_context_t; + +/** + * Cipher information. Allows calling cipher functions + * in a generic way. + */ +typedef struct mbedtls_cipher_info_t +{ + /** Full cipher identifier. For example, + * MBEDTLS_CIPHER_AES_256_CBC. + */ + mbedtls_cipher_type_t type; + + /** The cipher mode. For example, MBEDTLS_MODE_CBC. */ + mbedtls_cipher_mode_t mode; + + /** The cipher key length, in bits. This is the + * default length for variable sized ciphers. + * Includes parity bits for ciphers like DES. + */ + unsigned int key_bitlen; + + /** Name of the cipher. */ + const char * name; + + /** IV or nonce size, in Bytes. + * For ciphers that accept variable IV sizes, + * this is the recommended size. + */ + unsigned int iv_size; + + /** Bitflag comprised of MBEDTLS_CIPHER_VARIABLE_IV_LEN and + * MBEDTLS_CIPHER_VARIABLE_KEY_LEN indicating whether the + * cipher supports variable IV or variable key sizes, respectively. + */ + int flags; + + /** The block size, in Bytes. */ + unsigned int block_size; + + /** Struct for base cipher information and functions. */ + const mbedtls_cipher_base_t *base; + +} mbedtls_cipher_info_t; + +/** + * Generic cipher context. + */ +typedef struct mbedtls_cipher_context_t +{ + /** Information about the associated cipher. */ + const mbedtls_cipher_info_t *cipher_info; + + /** Key length to use. */ + int key_bitlen; + + /** Operation that the key of the context has been + * initialized for. + */ + mbedtls_operation_t operation; + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) + /** Padding functions to use, if relevant for + * the specific cipher mode. + */ + void (*add_padding)( unsigned char *output, size_t olen, size_t data_len ); + int (*get_padding)( unsigned char *input, size_t ilen, size_t *data_len ); +#endif + + /** Buffer for input that has not been processed yet. */ + unsigned char unprocessed_data[MBEDTLS_MAX_BLOCK_LENGTH]; + + /** Number of Bytes that have not been processed yet. */ + size_t unprocessed_len; + + /** Current IV or NONCE_COUNTER for CTR-mode, data unit (or sector) number + * for XTS-mode. */ + unsigned char iv[MBEDTLS_MAX_IV_LENGTH]; + + /** IV size in Bytes, for ciphers with variable-length IVs. */ + size_t iv_size; + + /** The cipher-specific context. */ + void *cipher_ctx; + +#if defined(MBEDTLS_CMAC_C) + /** CMAC-specific context. */ + mbedtls_cmac_context_t *cmac_ctx; +#endif +} mbedtls_cipher_context_t; + +/** + * \brief This function retrieves the list of ciphers supported by the generic + * cipher module. + * + * \return A statically-allocated array of ciphers. The last entry + * is zero. + */ +const int *mbedtls_cipher_list( void ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher name. + * + * \param cipher_name Name of the cipher to search for. + * + * \return The cipher information structure associated with the + * given \p cipher_name. + * \return NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_string( const char *cipher_name ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher type. + * + * \param cipher_type Type of the cipher to search for. + * + * \return The cipher information structure associated with the + * given \p cipher_type. + * \return NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_type( const mbedtls_cipher_type_t cipher_type ); + +/** + * \brief This function retrieves the cipher-information + * structure associated with the given cipher ID, + * key size and mode. + * + * \param cipher_id The ID of the cipher to search for. For example, + * #MBEDTLS_CIPHER_ID_AES. + * \param key_bitlen The length of the key in bits. + * \param mode The cipher mode. For example, #MBEDTLS_MODE_CBC. + * + * \return The cipher information structure associated with the + * given \p cipher_id. + * \return NULL if the associated cipher information is not found. + */ +const mbedtls_cipher_info_t *mbedtls_cipher_info_from_values( const mbedtls_cipher_id_t cipher_id, + int key_bitlen, + const mbedtls_cipher_mode_t mode ); + +/** + * \brief This function initializes a \p cipher_context as NONE. + */ +void mbedtls_cipher_init( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function frees and clears the cipher-specific + * context of \p ctx. Freeing \p ctx itself remains the + * responsibility of the caller. + */ +void mbedtls_cipher_free( mbedtls_cipher_context_t *ctx ); + + +/** + * \brief This function initializes and fills the cipher-context + * structure with the appropriate values. It also clears + * the structure. + * + * \param ctx The context to initialize. May not be NULL. + * \param cipher_info The cipher to use. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_ALLOC_FAILED if allocation of the + * cipher-specific context fails. + * + * \internal Currently, the function also clears the structure. + * In future versions, the caller will be required to call + * mbedtls_cipher_init() on the structure first. + */ +int mbedtls_cipher_setup( mbedtls_cipher_context_t *ctx, const mbedtls_cipher_info_t *cipher_info ); + +/** + * \brief This function returns the block size of the given cipher. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The size of the blocks of the cipher. + * \return 0 if \p ctx has not been initialized. + */ +static inline unsigned int mbedtls_cipher_get_block_size( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + return ctx->cipher_info->block_size; +} + +/** + * \brief This function returns the mode of operation for + * the cipher. For example, MBEDTLS_MODE_CBC. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The mode of operation. + * \return #MBEDTLS_MODE_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_cipher_mode_t mbedtls_cipher_get_cipher_mode( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return MBEDTLS_MODE_NONE; + + return ctx->cipher_info->mode; +} + +/** + * \brief This function returns the size of the IV or nonce + * of the cipher, in Bytes. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The recommended IV size if no IV has been set. + * \return \c 0 for ciphers not using an IV or a nonce. + * \return The actual size if an IV has been set. + */ +static inline int mbedtls_cipher_get_iv_size( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + if( ctx->iv_size != 0 ) + return (int) ctx->iv_size; + + return (int) ctx->cipher_info->iv_size; +} + +/** + * \brief This function returns the type of the given cipher. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The type of the cipher. + * \return #MBEDTLS_CIPHER_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_cipher_type_t mbedtls_cipher_get_type( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return MBEDTLS_CIPHER_NONE; + + return ctx->cipher_info->type; +} + +/** + * \brief This function returns the name of the given cipher + * as a string. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The name of the cipher. + * \return NULL if \p ctx has not been not initialized. + */ +static inline const char *mbedtls_cipher_get_name( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return 0; + + return ctx->cipher_info->name; +} + +/** + * \brief This function returns the key length of the cipher. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The key length of the cipher in bits. + * \return #MBEDTLS_KEY_LENGTH_NONE if ctx \p has not been + * initialized. + */ +static inline int mbedtls_cipher_get_key_bitlen( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return MBEDTLS_KEY_LENGTH_NONE; + + return (int) ctx->cipher_info->key_bitlen; +} + +/** + * \brief This function returns the operation of the given cipher. + * + * \param ctx The context of the cipher. Must be initialized. + * + * \return The type of operation: #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * \return #MBEDTLS_OPERATION_NONE if \p ctx has not been initialized. + */ +static inline mbedtls_operation_t mbedtls_cipher_get_operation( const mbedtls_cipher_context_t *ctx ) +{ + if( NULL == ctx || NULL == ctx->cipher_info ) + return MBEDTLS_OPERATION_NONE; + + return ctx->operation; +} + +/** + * \brief This function sets the key to use with the given context. + * + * \param ctx The generic cipher context. May not be NULL. Must have + * been initialized using mbedtls_cipher_info_from_type() + * or mbedtls_cipher_info_from_string(). + * \param key The key to use. + * \param key_bitlen The key length to use, in bits. + * \param operation The operation that the key will be used for: + * #MBEDTLS_ENCRYPT or #MBEDTLS_DECRYPT. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_setkey( mbedtls_cipher_context_t *ctx, const unsigned char *key, + int key_bitlen, const mbedtls_operation_t operation ); + +#if defined(MBEDTLS_CIPHER_MODE_WITH_PADDING) +/** + * \brief This function sets the padding mode, for cipher modes + * that use padding. + * + * The default passing mode is PKCS7 padding. + * + * \param ctx The generic cipher context. + * \param mode The padding mode. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE + * if the selected padding mode is not supported. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA if the cipher mode + * does not support padding. + */ +int mbedtls_cipher_set_padding_mode( mbedtls_cipher_context_t *ctx, mbedtls_cipher_padding_t mode ); +#endif /* MBEDTLS_CIPHER_MODE_WITH_PADDING */ + +/** + * \brief This function sets the initialization vector (IV) + * or nonce. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, this function has no effect. + * + * \param ctx The generic cipher context. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + */ +int mbedtls_cipher_set_iv( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len ); + +/** + * \brief This function resets the cipher state. + * + * \param ctx The generic cipher context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + */ +int mbedtls_cipher_reset( mbedtls_cipher_context_t *ctx ); + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/** + * \brief This function adds additional data for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * Must be called exactly once, after mbedtls_cipher_reset(). + * + * \param ctx The generic cipher context. + * \param ad The additional data to use. + * \param ad_len the Length of \p ad. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_update_ad( mbedtls_cipher_context_t *ctx, + const unsigned char *ad, size_t ad_len ); +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/** + * \brief The generic cipher update function. It encrypts or + * decrypts using the given cipher context. Writes as + * many block-sized blocks of data as possible to output. + * Any data that cannot be written immediately is either + * added to the next block, or flushed when + * mbedtls_cipher_finish() is called. + * Exception: For MBEDTLS_MODE_ECB, expects a single block + * in size. For example, 16 Bytes for AES. + * + * \note If the underlying cipher is used in GCM mode, all calls + * to this function, except for the last one before + * mbedtls_cipher_finish(), must have \p ilen as a + * multiple of the block size of the cipher. + * + * \param ctx The generic cipher context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the output data. Must be able to hold at + * least \p ilen + block_size. Must not be the same buffer + * as input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE on an + * unsupported mode for a cipher. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_update( mbedtls_cipher_context_t *ctx, const unsigned char *input, + size_t ilen, unsigned char *output, size_t *olen ); + +/** + * \brief The generic cipher finalization function. If data still + * needs to be flushed from an incomplete block, the data + * contained in it is padded to the size of + * the last block, and written to the \p output buffer. + * + * \param ctx The generic cipher context. + * \param output The buffer to write data to. Needs block_size available. + * \param olen The length of the data written to the \p output buffer. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_GCM_C) || defined(MBEDTLS_CHACHAPOLY_C) +/** + * \brief This function writes a tag for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * Must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. + * \param tag The buffer to write the tag to. + * \param tag_len The length of the tag to write. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_write_tag( mbedtls_cipher_context_t *ctx, + unsigned char *tag, size_t tag_len ); + +/** + * \brief This function checks the tag for AEAD ciphers. + * Currently supported with GCM and ChaCha20+Poly1305. + * Must be called after mbedtls_cipher_finish(). + * + * \param ctx The generic cipher context. + * \param tag The buffer holding the tag. + * \param tag_len The length of the tag to check. + * + * \return \c 0 on success. + * \return A specific error code on failure. + */ +int mbedtls_cipher_check_tag( mbedtls_cipher_context_t *ctx, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_GCM_C || MBEDTLS_CHACHAPOLY_C */ + +/** + * \brief The generic all-in-one encryption/decryption function, + * for all ciphers except AEAD constructs. + * + * \param ctx The generic cipher context. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size + * IV. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the output data. Must be able to hold at + * least \p ilen + block_size. Must not be the same buffer + * as input. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. + * + * \note Some ciphers do not use IVs nor nonce. For these + * ciphers, use \p iv = NULL and \p iv_len = 0. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED on decryption + * expecting a full block but not receiving one. + * \return #MBEDTLS_ERR_CIPHER_INVALID_PADDING on invalid padding + * while decrypting. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_crypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_MODE_AEAD) +/** + * \brief The generic autenticated encryption (AEAD) function. + * + * \param ctx The generic cipher context. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * \param ad The additional data to authenticate. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the output data. + * Must be able to hold at least \p ilen. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. + * \param tag The buffer for the authentication tag. + * \param tag_len The desired length of the authentication tag. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_auth_encrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + unsigned char *tag, size_t tag_len ); + +/** + * \brief The generic autenticated decryption (AEAD) function. + * + * \note If the data is not authentic, then the output buffer + * is zeroed out to prevent the unauthentic plaintext being + * used, making this interface safer. + * + * \param ctx The generic cipher context. + * \param iv The IV to use, or NONCE_COUNTER for CTR-mode ciphers. + * \param iv_len The IV length for ciphers with variable-size IV. + * This parameter is discarded by ciphers with fixed-size IV. + * \param ad The additional data to be authenticated. + * \param ad_len The length of \p ad. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the output data. + * Must be able to hold at least \p ilen. + * \param olen The length of the output data, to be updated with the + * actual number of Bytes written. + * \param tag The buffer holding the authentication tag. + * \param tag_len The length of the authentication tag. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA on + * parameter-verification failure. + * \return #MBEDTLS_ERR_CIPHER_AUTH_FAILED if data is not authentic. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_auth_decrypt( mbedtls_cipher_context_t *ctx, + const unsigned char *iv, size_t iv_len, + const unsigned char *ad, size_t ad_len, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, + const unsigned char *tag, size_t tag_len ); +#endif /* MBEDTLS_CIPHER_MODE_AEAD */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_H */ diff --git a/common/mbedtls/cipher_internal.h b/common/mbedtls/cipher_internal.h new file mode 100644 index 000000000..9f2858aae --- /dev/null +++ b/common/mbedtls/cipher_internal.h @@ -0,0 +1,127 @@ +/** + * \file cipher_internal.h + * + * \brief Cipher wrappers. + * + * \author Adriaan de Jong + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_CIPHER_WRAP_H +#define MBEDTLS_CIPHER_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Base cipher information. The non-mode specific functions and values. + */ +struct mbedtls_cipher_base_t +{ + /** Base Cipher type (e.g. MBEDTLS_CIPHER_ID_AES) */ + mbedtls_cipher_id_t cipher; + + /** Encrypt using ECB */ + int (*ecb_func)( void *ctx, mbedtls_operation_t mode, + const unsigned char *input, unsigned char *output ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /** Encrypt using CBC */ + int (*cbc_func)( void *ctx, mbedtls_operation_t mode, size_t length, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CFB) + /** Encrypt using CFB (Full length) */ + int (*cfb_func)( void *ctx, mbedtls_operation_t mode, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_OFB) + /** Encrypt using OFB (Full length) */ + int (*ofb_func)( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, + const unsigned char *input, + unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_CTR) + /** Encrypt using CTR */ + int (*ctr_func)( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_XTS) + /** Encrypt or decrypt using XTS. */ + int (*xts_func)( void *ctx, mbedtls_operation_t mode, size_t length, + const unsigned char data_unit[16], + const unsigned char *input, unsigned char *output ); +#endif + +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + /** Encrypt using STREAM */ + int (*stream_func)( void *ctx, size_t length, + const unsigned char *input, unsigned char *output ); +#endif + + /** Set key for encryption purposes */ + int (*setkey_enc_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen ); + + /** Set key for decryption purposes */ + int (*setkey_dec_func)( void *ctx, const unsigned char *key, + unsigned int key_bitlen); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + +}; + +typedef struct +{ + mbedtls_cipher_type_t type; + const mbedtls_cipher_info_t *info; +} mbedtls_cipher_definition_t; + +extern const mbedtls_cipher_definition_t mbedtls_cipher_definitions[]; + +extern int mbedtls_cipher_supported[]; + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CIPHER_WRAP_H */ diff --git a/common/mbedtls/cipher_wrap.c b/common/mbedtls/cipher_wrap.c new file mode 100644 index 000000000..3f81729cc --- /dev/null +++ b/common/mbedtls/cipher_wrap.c @@ -0,0 +1,2274 @@ +/** + * \file cipher_wrap.c + * + * \brief Generic cipher wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CIPHER_C) + +#include "mbedtls/cipher_internal.h" + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_ARIA_C) +#include "mbedtls/aria.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_BLOWFISH_C) +#include "mbedtls/blowfish.h" +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_GCM_C) +/* shared by all GCM ciphers */ +static void *gcm_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_gcm_context ) ); + + if( ctx != NULL ) + mbedtls_gcm_init( (mbedtls_gcm_context *) ctx ); + + return( ctx ); +} + +static void gcm_ctx_free( void *ctx ) +{ + mbedtls_gcm_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +/* shared by all CCM ciphers */ +static void *ccm_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ccm_context ) ); + + if( ctx != NULL ) + mbedtls_ccm_init( (mbedtls_ccm_context *) ctx ); + + return( ctx ); +} + +static void ccm_ctx_free( void *ctx ) +{ + mbedtls_ccm_free( ctx ); + mbedtls_free( ctx ); +} +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_AES_C) + +static int aes_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ecb( (mbedtls_aes_context *) ctx, operation, input, output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int aes_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_cbc( (mbedtls_aes_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int aes_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_cfb128( (mbedtls_aes_context *) ctx, operation, length, iv_off, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +static int aes_crypt_ofb_wrap( void *ctx, size_t length, size_t *iv_off, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ofb( (mbedtls_aes_context *) ctx, length, iv_off, + iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int aes_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aes_crypt_ctr( (mbedtls_aes_context *) ctx, length, nc_off, nonce_counter, + stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int aes_crypt_xts_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, + const unsigned char data_unit[16], + const unsigned char *input, + unsigned char *output ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + int mode; + + switch( operation ) + { + case MBEDTLS_ENCRYPT: + mode = MBEDTLS_AES_ENCRYPT; + break; + case MBEDTLS_DECRYPT: + mode = MBEDTLS_AES_DECRYPT; + break; + default: + return MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA; + } + + return mbedtls_aes_crypt_xts( xts_ctx, mode, length, + data_unit, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +static int aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aes_setkey_dec( (mbedtls_aes_context *) ctx, key, key_bitlen ); +} + +static int aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aes_setkey_enc( (mbedtls_aes_context *) ctx, key, key_bitlen ); +} + +static void * aes_ctx_alloc( void ) +{ + mbedtls_aes_context *aes = mbedtls_calloc( 1, sizeof( mbedtls_aes_context ) ); + + if( aes == NULL ) + return( NULL ); + + mbedtls_aes_init( aes ); + + return( aes ); +} + +static void aes_ctx_free( void *ctx ) +{ + mbedtls_aes_free( (mbedtls_aes_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t aes_info = { + MBEDTLS_CIPHER_ID_AES, + aes_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + aes_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + aes_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + aes_crypt_ofb_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + aes_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + aes_setkey_enc_wrap, + aes_setkey_dec_wrap, + aes_ctx_alloc, + aes_ctx_free +}; + +static const mbedtls_cipher_info_t aes_128_ecb_info = { + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "AES-128-ECB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ecb_info = { + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "AES-192-ECB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ecb_info = { + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "AES-256-ECB", + 16, + 0, + 16, + &aes_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t aes_128_cbc_info = { + MBEDTLS_CIPHER_AES_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "AES-128-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_cbc_info = { + MBEDTLS_CIPHER_AES_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "AES-192-CBC", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_cbc_info = { + MBEDTLS_CIPHER_AES_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "AES-256-CBC", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t aes_128_cfb128_info = { + MBEDTLS_CIPHER_AES_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "AES-128-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_cfb128_info = { + MBEDTLS_CIPHER_AES_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "AES-192-CFB128", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_cfb128_info = { + MBEDTLS_CIPHER_AES_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "AES-256-CFB128", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_OFB) +static const mbedtls_cipher_info_t aes_128_ofb_info = { + MBEDTLS_CIPHER_AES_128_OFB, + MBEDTLS_MODE_OFB, + 128, + "AES-128-OFB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ofb_info = { + MBEDTLS_CIPHER_AES_192_OFB, + MBEDTLS_MODE_OFB, + 192, + "AES-192-OFB", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ofb_info = { + MBEDTLS_CIPHER_AES_256_OFB, + MBEDTLS_MODE_OFB, + 256, + "AES-256-OFB", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_OFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t aes_128_ctr_info = { + MBEDTLS_CIPHER_AES_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "AES-128-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ctr_info = { + MBEDTLS_CIPHER_AES_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "AES-192-CTR", + 16, + 0, + 16, + &aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ctr_info = { + MBEDTLS_CIPHER_AES_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "AES-256-CTR", + 16, + 0, + 16, + &aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_CIPHER_MODE_XTS) +static int xts_aes_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + return( mbedtls_aes_xts_setkey_enc( xts_ctx, key, key_bitlen ) ); +} + +static int xts_aes_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + return( mbedtls_aes_xts_setkey_dec( xts_ctx, key, key_bitlen ) ); +} + +static void *xts_aes_ctx_alloc( void ) +{ + mbedtls_aes_xts_context *xts_ctx = mbedtls_calloc( 1, sizeof( *xts_ctx ) ); + + if( xts_ctx != NULL ) + mbedtls_aes_xts_init( xts_ctx ); + + return( xts_ctx ); +} + +static void xts_aes_ctx_free( void *ctx ) +{ + mbedtls_aes_xts_context *xts_ctx = ctx; + + if( xts_ctx == NULL ) + return; + + mbedtls_aes_xts_free( xts_ctx ); + mbedtls_free( xts_ctx ); +} + +static const mbedtls_cipher_base_t xts_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + aes_crypt_xts_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + xts_aes_setkey_enc_wrap, + xts_aes_setkey_dec_wrap, + xts_aes_ctx_alloc, + xts_aes_ctx_free +}; + +static const mbedtls_cipher_info_t aes_128_xts_info = { + MBEDTLS_CIPHER_AES_128_XTS, + MBEDTLS_MODE_XTS, + 256, + "AES-128-XTS", + 16, + 0, + 16, + &xts_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_xts_info = { + MBEDTLS_CIPHER_AES_256_XTS, + MBEDTLS_MODE_XTS, + 512, + "AES-256-XTS", + 16, + 0, + 16, + &xts_aes_info +}; +#endif /* MBEDTLS_CIPHER_MODE_XTS */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_aes_setkey_wrap, + gcm_aes_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_gcm_info = { + MBEDTLS_CIPHER_AES_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "AES-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_gcm_info = { + MBEDTLS_CIPHER_AES_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "AES-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_gcm_info = { + MBEDTLS_CIPHER_AES_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "AES-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aes_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_aes_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_AES, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_aes_info = { + MBEDTLS_CIPHER_ID_AES, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_aes_setkey_wrap, + ccm_aes_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t aes_128_ccm_info = { + MBEDTLS_CIPHER_AES_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "AES-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_192_ccm_info = { + MBEDTLS_CIPHER_AES_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "AES-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; + +static const mbedtls_cipher_info_t aes_256_ccm_info = { + MBEDTLS_CIPHER_AES_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "AES-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aes_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + +static int camellia_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_ecb( (mbedtls_camellia_context *) ctx, operation, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int camellia_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_cbc( (mbedtls_camellia_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int camellia_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_cfb128( (mbedtls_camellia_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int camellia_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_camellia_crypt_ctr( (mbedtls_camellia_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int camellia_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_camellia_setkey_dec( (mbedtls_camellia_context *) ctx, key, key_bitlen ); +} + +static int camellia_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_camellia_setkey_enc( (mbedtls_camellia_context *) ctx, key, key_bitlen ); +} + +static void * camellia_ctx_alloc( void ) +{ + mbedtls_camellia_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_camellia_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_camellia_init( ctx ); + + return( ctx ); +} + +static void camellia_ctx_free( void *ctx ) +{ + mbedtls_camellia_free( (mbedtls_camellia_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + camellia_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + camellia_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + camellia_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + camellia_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + camellia_setkey_enc_wrap, + camellia_setkey_dec_wrap, + camellia_ctx_alloc, + camellia_ctx_free +}; + +static const mbedtls_cipher_info_t camellia_128_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "CAMELLIA-128-ECB", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "CAMELLIA-192-ECB", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ecb_info = { + MBEDTLS_CIPHER_CAMELLIA_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "CAMELLIA-256-ECB", + 16, + 0, + 16, + &camellia_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t camellia_128_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "CAMELLIA-128-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "CAMELLIA-192-CBC", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_cbc_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "CAMELLIA-256-CBC", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t camellia_128_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "CAMELLIA-128-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "CAMELLIA-192-CFB128", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_cfb128_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "CAMELLIA-256-CFB128", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t camellia_128_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "CAMELLIA-128-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "CAMELLIA-192-CTR", + 16, + 0, + 16, + &camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ctr_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "CAMELLIA-256-CTR", + 16, + 0, + 16, + &camellia_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_camellia_setkey_wrap, + gcm_camellia_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t camellia_128_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "CAMELLIA-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "CAMELLIA-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_gcm_info = { + MBEDTLS_CIPHER_CAMELLIA_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "CAMELLIA-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_camellia_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_camellia_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_CAMELLIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_camellia_info = { + MBEDTLS_CIPHER_ID_CAMELLIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_camellia_setkey_wrap, + ccm_camellia_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t camellia_128_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "CAMELLIA-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_192_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "CAMELLIA-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; + +static const mbedtls_cipher_info_t camellia_256_ccm_info = { + MBEDTLS_CIPHER_CAMELLIA_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "CAMELLIA-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_camellia_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_ARIA_C) + +static int aria_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + (void) operation; + return mbedtls_aria_crypt_ecb( (mbedtls_aria_context *) ctx, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int aria_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_cbc( (mbedtls_aria_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int aria_crypt_cfb128_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_cfb128( (mbedtls_aria_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int aria_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_aria_crypt_ctr( (mbedtls_aria_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int aria_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aria_setkey_dec( (mbedtls_aria_context *) ctx, key, key_bitlen ); +} + +static int aria_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_aria_setkey_enc( (mbedtls_aria_context *) ctx, key, key_bitlen ); +} + +static void * aria_ctx_alloc( void ) +{ + mbedtls_aria_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_aria_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_aria_init( ctx ); + + return( ctx ); +} + +static void aria_ctx_free( void *ctx ) +{ + mbedtls_aria_free( (mbedtls_aria_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + aria_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + aria_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + aria_crypt_cfb128_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + aria_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + aria_setkey_enc_wrap, + aria_setkey_dec_wrap, + aria_ctx_alloc, + aria_ctx_free +}; + +static const mbedtls_cipher_info_t aria_128_ecb_info = { + MBEDTLS_CIPHER_ARIA_128_ECB, + MBEDTLS_MODE_ECB, + 128, + "ARIA-128-ECB", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ecb_info = { + MBEDTLS_CIPHER_ARIA_192_ECB, + MBEDTLS_MODE_ECB, + 192, + "ARIA-192-ECB", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ecb_info = { + MBEDTLS_CIPHER_ARIA_256_ECB, + MBEDTLS_MODE_ECB, + 256, + "ARIA-256-ECB", + 16, + 0, + 16, + &aria_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t aria_128_cbc_info = { + MBEDTLS_CIPHER_ARIA_128_CBC, + MBEDTLS_MODE_CBC, + 128, + "ARIA-128-CBC", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_cbc_info = { + MBEDTLS_CIPHER_ARIA_192_CBC, + MBEDTLS_MODE_CBC, + 192, + "ARIA-192-CBC", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_cbc_info = { + MBEDTLS_CIPHER_ARIA_256_CBC, + MBEDTLS_MODE_CBC, + 256, + "ARIA-256-CBC", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t aria_128_cfb128_info = { + MBEDTLS_CIPHER_ARIA_128_CFB128, + MBEDTLS_MODE_CFB, + 128, + "ARIA-128-CFB128", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_cfb128_info = { + MBEDTLS_CIPHER_ARIA_192_CFB128, + MBEDTLS_MODE_CFB, + 192, + "ARIA-192-CFB128", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_cfb128_info = { + MBEDTLS_CIPHER_ARIA_256_CFB128, + MBEDTLS_MODE_CFB, + 256, + "ARIA-256-CFB128", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t aria_128_ctr_info = { + MBEDTLS_CIPHER_ARIA_128_CTR, + MBEDTLS_MODE_CTR, + 128, + "ARIA-128-CTR", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ctr_info = { + MBEDTLS_CIPHER_ARIA_192_CTR, + MBEDTLS_MODE_CTR, + 192, + "ARIA-192-CTR", + 16, + 0, + 16, + &aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ctr_info = { + MBEDTLS_CIPHER_ARIA_256_CTR, + MBEDTLS_MODE_CTR, + 256, + "ARIA-256-CTR", + 16, + 0, + 16, + &aria_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +#if defined(MBEDTLS_GCM_C) +static int gcm_aria_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_gcm_setkey( (mbedtls_gcm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t gcm_aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + gcm_aria_setkey_wrap, + gcm_aria_setkey_wrap, + gcm_ctx_alloc, + gcm_ctx_free, +}; + +static const mbedtls_cipher_info_t aria_128_gcm_info = { + MBEDTLS_CIPHER_ARIA_128_GCM, + MBEDTLS_MODE_GCM, + 128, + "ARIA-128-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; + +static const mbedtls_cipher_info_t aria_192_gcm_info = { + MBEDTLS_CIPHER_ARIA_192_GCM, + MBEDTLS_MODE_GCM, + 192, + "ARIA-192-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; + +static const mbedtls_cipher_info_t aria_256_gcm_info = { + MBEDTLS_CIPHER_ARIA_256_GCM, + MBEDTLS_MODE_GCM, + 256, + "ARIA-256-GCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &gcm_aria_info +}; +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_CCM_C) +static int ccm_aria_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_ccm_setkey( (mbedtls_ccm_context *) ctx, MBEDTLS_CIPHER_ID_ARIA, + key, key_bitlen ); +} + +static const mbedtls_cipher_base_t ccm_aria_info = { + MBEDTLS_CIPHER_ID_ARIA, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + ccm_aria_setkey_wrap, + ccm_aria_setkey_wrap, + ccm_ctx_alloc, + ccm_ctx_free, +}; + +static const mbedtls_cipher_info_t aria_128_ccm_info = { + MBEDTLS_CIPHER_ARIA_128_CCM, + MBEDTLS_MODE_CCM, + 128, + "ARIA-128-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_192_ccm_info = { + MBEDTLS_CIPHER_ARIA_192_CCM, + MBEDTLS_MODE_CCM, + 192, + "ARIA-192-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; + +static const mbedtls_cipher_info_t aria_256_ccm_info = { + MBEDTLS_CIPHER_ARIA_256_CCM, + MBEDTLS_MODE_CCM, + 256, + "ARIA-256-CCM", + 12, + MBEDTLS_CIPHER_VARIABLE_IV_LEN, + 16, + &ccm_aria_info +}; +#endif /* MBEDTLS_CCM_C */ + +#endif /* MBEDTLS_ARIA_C */ + +#if defined(MBEDTLS_DES_C) + +static int des_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return mbedtls_des_crypt_ecb( (mbedtls_des_context *) ctx, input, output ); +} + +static int des3_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + ((void) operation); + return mbedtls_des3_crypt_ecb( (mbedtls_des3_context *) ctx, input, output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int des_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_des_crypt_cbc( (mbedtls_des_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int des3_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, size_t length, + unsigned char *iv, const unsigned char *input, unsigned char *output ) +{ + return mbedtls_des3_crypt_cbc( (mbedtls_des3_context *) ctx, operation, length, iv, input, + output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static int des_setkey_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des_setkey_dec( (mbedtls_des_context *) ctx, key ); +} + +static int des_setkey_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des_setkey_enc( (mbedtls_des_context *) ctx, key ); +} + +static int des3_set2key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set2key_dec( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set2key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set2key_enc( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set3key_dec_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set3key_dec( (mbedtls_des3_context *) ctx, key ); +} + +static int des3_set3key_enc_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) key_bitlen); + + return mbedtls_des3_set3key_enc( (mbedtls_des3_context *) ctx, key ); +} + +static void * des_ctx_alloc( void ) +{ + mbedtls_des_context *des = mbedtls_calloc( 1, sizeof( mbedtls_des_context ) ); + + if( des == NULL ) + return( NULL ); + + mbedtls_des_init( des ); + + return( des ); +} + +static void des_ctx_free( void *ctx ) +{ + mbedtls_des_free( (mbedtls_des_context *) ctx ); + mbedtls_free( ctx ); +} + +static void * des3_ctx_alloc( void ) +{ + mbedtls_des3_context *des3; + des3 = mbedtls_calloc( 1, sizeof( mbedtls_des3_context ) ); + + if( des3 == NULL ) + return( NULL ); + + mbedtls_des3_init( des3 ); + + return( des3 ); +} + +static void des3_ctx_free( void *ctx ) +{ + mbedtls_des3_free( (mbedtls_des3_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t des_info = { + MBEDTLS_CIPHER_ID_DES, + des_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des_setkey_enc_wrap, + des_setkey_dec_wrap, + des_ctx_alloc, + des_ctx_free +}; + +static const mbedtls_cipher_info_t des_ecb_info = { + MBEDTLS_CIPHER_DES_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES, + "DES-ECB", + 8, + 0, + 8, + &des_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_cbc_info = { + MBEDTLS_CIPHER_DES_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES, + "DES-CBC", + 8, + 0, + 8, + &des_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static const mbedtls_cipher_base_t des_ede_info = { + MBEDTLS_CIPHER_ID_DES, + des3_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set2key_enc_wrap, + des3_set2key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +static const mbedtls_cipher_info_t des_ede_ecb_info = { + MBEDTLS_CIPHER_DES_EDE_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES_EDE, + "DES-EDE-ECB", + 8, + 0, + 8, + &des_ede_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_ede_cbc_info = { + MBEDTLS_CIPHER_DES_EDE_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES_EDE, + "DES-EDE-CBC", + 8, + 0, + 8, + &des_ede_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +static const mbedtls_cipher_base_t des_ede3_info = { + MBEDTLS_CIPHER_ID_3DES, + des3_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + des3_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + des3_set3key_enc_wrap, + des3_set3key_dec_wrap, + des3_ctx_alloc, + des3_ctx_free +}; + +static const mbedtls_cipher_info_t des_ede3_ecb_info = { + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_MODE_ECB, + MBEDTLS_KEY_LENGTH_DES_EDE3, + "DES-EDE3-ECB", + 8, + 0, + 8, + &des_ede3_info +}; +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t des_ede3_cbc_info = { + MBEDTLS_CIPHER_DES_EDE3_CBC, + MBEDTLS_MODE_CBC, + MBEDTLS_KEY_LENGTH_DES_EDE3, + "DES-EDE3-CBC", + 8, + 0, + 8, + &des_ede3_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_BLOWFISH_C) + +static int blowfish_crypt_ecb_wrap( void *ctx, mbedtls_operation_t operation, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_ecb( (mbedtls_blowfish_context *) ctx, operation, input, + output ); +} + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static int blowfish_crypt_cbc_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, unsigned char *iv, const unsigned char *input, + unsigned char *output ) +{ + return mbedtls_blowfish_crypt_cbc( (mbedtls_blowfish_context *) ctx, operation, length, iv, + input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static int blowfish_crypt_cfb64_wrap( void *ctx, mbedtls_operation_t operation, + size_t length, size_t *iv_off, unsigned char *iv, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_cfb64( (mbedtls_blowfish_context *) ctx, operation, length, + iv_off, iv, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static int blowfish_crypt_ctr_wrap( void *ctx, size_t length, size_t *nc_off, + unsigned char *nonce_counter, unsigned char *stream_block, + const unsigned char *input, unsigned char *output ) +{ + return mbedtls_blowfish_crypt_ctr( (mbedtls_blowfish_context *) ctx, length, nc_off, + nonce_counter, stream_block, input, output ); +} +#endif /* MBEDTLS_CIPHER_MODE_CTR */ + +static int blowfish_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + return mbedtls_blowfish_setkey( (mbedtls_blowfish_context *) ctx, key, key_bitlen ); +} + +static void * blowfish_ctx_alloc( void ) +{ + mbedtls_blowfish_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_blowfish_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_blowfish_init( ctx ); + + return( ctx ); +} + +static void blowfish_ctx_free( void *ctx ) +{ + mbedtls_blowfish_free( (mbedtls_blowfish_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t blowfish_info = { + MBEDTLS_CIPHER_ID_BLOWFISH, + blowfish_crypt_ecb_wrap, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + blowfish_crypt_cbc_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + blowfish_crypt_cfb64_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + blowfish_crypt_ctr_wrap, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + blowfish_setkey_wrap, + blowfish_setkey_wrap, + blowfish_ctx_alloc, + blowfish_ctx_free +}; + +static const mbedtls_cipher_info_t blowfish_ecb_info = { + MBEDTLS_CIPHER_BLOWFISH_ECB, + MBEDTLS_MODE_ECB, + 128, + "BLOWFISH-ECB", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const mbedtls_cipher_info_t blowfish_cbc_info = { + MBEDTLS_CIPHER_BLOWFISH_CBC, + MBEDTLS_MODE_CBC, + 128, + "BLOWFISH-CBC", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#if defined(MBEDTLS_CIPHER_MODE_CFB) +static const mbedtls_cipher_info_t blowfish_cfb64_info = { + MBEDTLS_CIPHER_BLOWFISH_CFB64, + MBEDTLS_MODE_CFB, + 128, + "BLOWFISH-CFB64", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CFB */ + +#if defined(MBEDTLS_CIPHER_MODE_CTR) +static const mbedtls_cipher_info_t blowfish_ctr_info = { + MBEDTLS_CIPHER_BLOWFISH_CTR, + MBEDTLS_MODE_CTR, + 128, + "BLOWFISH-CTR", + 8, + MBEDTLS_CIPHER_VARIABLE_KEY_LEN, + 8, + &blowfish_info +}; +#endif /* MBEDTLS_CIPHER_MODE_CTR */ +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_ARC4_C) +static int arc4_crypt_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + return( mbedtls_arc4_crypt( (mbedtls_arc4_context *) ctx, length, input, output ) ); +} + +static int arc4_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + /* we get key_bitlen in bits, arc4 expects it in bytes */ + if( key_bitlen % 8 != 0 ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + mbedtls_arc4_setup( (mbedtls_arc4_context *) ctx, key, key_bitlen / 8 ); + return( 0 ); +} + +static void * arc4_ctx_alloc( void ) +{ + mbedtls_arc4_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_arc4_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_arc4_init( ctx ); + + return( ctx ); +} + +static void arc4_ctx_free( void *ctx ) +{ + mbedtls_arc4_free( (mbedtls_arc4_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t arc4_base_info = { + MBEDTLS_CIPHER_ID_ARC4, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + arc4_crypt_stream_wrap, +#endif + arc4_setkey_wrap, + arc4_setkey_wrap, + arc4_ctx_alloc, + arc4_ctx_free +}; + +static const mbedtls_cipher_info_t arc4_128_info = { + MBEDTLS_CIPHER_ARC4_128, + MBEDTLS_MODE_STREAM, + 128, + "ARC4-128", + 0, + 0, + 1, + &arc4_base_info +}; +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_CHACHA20_C) + +static int chacha20_setkey_wrap( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chacha20_setkey( (mbedtls_chacha20_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static int chacha20_stream_wrap( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + + ret = mbedtls_chacha20_update( ctx, length, input, output ); + if( ret == MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( ret ); +} + +static void * chacha20_ctx_alloc( void ) +{ + mbedtls_chacha20_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chacha20_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chacha20_init( ctx ); + + return( ctx ); +} + +static void chacha20_ctx_free( void *ctx ) +{ + mbedtls_chacha20_free( (mbedtls_chacha20_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chacha20_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + chacha20_stream_wrap, +#endif + chacha20_setkey_wrap, + chacha20_setkey_wrap, + chacha20_ctx_alloc, + chacha20_ctx_free +}; +static const mbedtls_cipher_info_t chacha20_info = { + MBEDTLS_CIPHER_CHACHA20, + MBEDTLS_MODE_STREAM, + 256, + "CHACHA20", + 12, + 0, + 1, + &chacha20_base_info +}; +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + +static int chachapoly_setkey_wrap( void *ctx, + const unsigned char *key, + unsigned int key_bitlen ) +{ + if( key_bitlen != 256U ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if ( 0 != mbedtls_chachapoly_setkey( (mbedtls_chachapoly_context*)ctx, key ) ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + return( 0 ); +} + +static void * chachapoly_ctx_alloc( void ) +{ + mbedtls_chachapoly_context *ctx; + ctx = mbedtls_calloc( 1, sizeof( mbedtls_chachapoly_context ) ); + + if( ctx == NULL ) + return( NULL ); + + mbedtls_chachapoly_init( ctx ); + + return( ctx ); +} + +static void chachapoly_ctx_free( void *ctx ) +{ + mbedtls_chachapoly_free( (mbedtls_chachapoly_context *) ctx ); + mbedtls_free( ctx ); +} + +static const mbedtls_cipher_base_t chachapoly_base_info = { + MBEDTLS_CIPHER_ID_CHACHA20, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + NULL, +#endif + chachapoly_setkey_wrap, + chachapoly_setkey_wrap, + chachapoly_ctx_alloc, + chachapoly_ctx_free +}; +static const mbedtls_cipher_info_t chachapoly_info = { + MBEDTLS_CIPHER_CHACHA20_POLY1305, + MBEDTLS_MODE_CHACHAPOLY, + 256, + "CHACHA20-POLY1305", + 12, + 0, + 1, + &chachapoly_base_info +}; +#endif /* MBEDTLS_CHACHAPOLY_C */ + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) +static int null_crypt_stream( void *ctx, size_t length, + const unsigned char *input, + unsigned char *output ) +{ + ((void) ctx); + memmove( output, input, length ); + return( 0 ); +} + +static int null_setkey( void *ctx, const unsigned char *key, + unsigned int key_bitlen ) +{ + ((void) ctx); + ((void) key); + ((void) key_bitlen); + + return( 0 ); +} + +static void * null_ctx_alloc( void ) +{ + return( (void *) 1 ); +} + +static void null_ctx_free( void *ctx ) +{ + ((void) ctx); +} + +static const mbedtls_cipher_base_t null_base_info = { + MBEDTLS_CIPHER_ID_NULL, + NULL, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + NULL, +#endif +#if defined(MBEDTLS_CIPHER_MODE_STREAM) + null_crypt_stream, +#endif + null_setkey, + null_setkey, + null_ctx_alloc, + null_ctx_free +}; + +static const mbedtls_cipher_info_t null_cipher_info = { + MBEDTLS_CIPHER_NULL, + MBEDTLS_MODE_STREAM, + 0, + "NULL", + 0, + 0, + 1, + &null_base_info +}; +#endif /* defined(MBEDTLS_CIPHER_NULL_CIPHER) */ + +const mbedtls_cipher_definition_t mbedtls_cipher_definitions[] = +{ +#if defined(MBEDTLS_AES_C) + { MBEDTLS_CIPHER_AES_128_ECB, &aes_128_ecb_info }, + { MBEDTLS_CIPHER_AES_192_ECB, &aes_192_ecb_info }, + { MBEDTLS_CIPHER_AES_256_ECB, &aes_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_AES_128_CBC, &aes_128_cbc_info }, + { MBEDTLS_CIPHER_AES_192_CBC, &aes_192_cbc_info }, + { MBEDTLS_CIPHER_AES_256_CBC, &aes_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_AES_128_CFB128, &aes_128_cfb128_info }, + { MBEDTLS_CIPHER_AES_192_CFB128, &aes_192_cfb128_info }, + { MBEDTLS_CIPHER_AES_256_CFB128, &aes_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_OFB) + { MBEDTLS_CIPHER_AES_128_OFB, &aes_128_ofb_info }, + { MBEDTLS_CIPHER_AES_192_OFB, &aes_192_ofb_info }, + { MBEDTLS_CIPHER_AES_256_OFB, &aes_256_ofb_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_AES_128_CTR, &aes_128_ctr_info }, + { MBEDTLS_CIPHER_AES_192_CTR, &aes_192_ctr_info }, + { MBEDTLS_CIPHER_AES_256_CTR, &aes_256_ctr_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_XTS) + { MBEDTLS_CIPHER_AES_128_XTS, &aes_128_xts_info }, + { MBEDTLS_CIPHER_AES_256_XTS, &aes_256_xts_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_AES_128_GCM, &aes_128_gcm_info }, + { MBEDTLS_CIPHER_AES_192_GCM, &aes_192_gcm_info }, + { MBEDTLS_CIPHER_AES_256_GCM, &aes_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_AES_128_CCM, &aes_128_ccm_info }, + { MBEDTLS_CIPHER_AES_192_CCM, &aes_192_ccm_info }, + { MBEDTLS_CIPHER_AES_256_CCM, &aes_256_ccm_info }, +#endif +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_ARC4_C) + { MBEDTLS_CIPHER_ARC4_128, &arc4_128_info }, +#endif + +#if defined(MBEDTLS_BLOWFISH_C) + { MBEDTLS_CIPHER_BLOWFISH_ECB, &blowfish_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_BLOWFISH_CBC, &blowfish_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_BLOWFISH_CFB64, &blowfish_cfb64_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_BLOWFISH_CTR, &blowfish_ctr_info }, +#endif +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + { MBEDTLS_CIPHER_CAMELLIA_128_ECB, &camellia_128_ecb_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_ECB, &camellia_192_ecb_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_ECB, &camellia_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_CAMELLIA_128_CBC, &camellia_128_cbc_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CBC, &camellia_192_cbc_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CBC, &camellia_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_CAMELLIA_128_CFB128, &camellia_128_cfb128_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CFB128, &camellia_192_cfb128_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CFB128, &camellia_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_CAMELLIA_128_CTR, &camellia_128_ctr_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CTR, &camellia_192_ctr_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CTR, &camellia_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_CAMELLIA_128_GCM, &camellia_128_gcm_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_GCM, &camellia_192_gcm_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_GCM, &camellia_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_CAMELLIA_128_CCM, &camellia_128_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_192_CCM, &camellia_192_ccm_info }, + { MBEDTLS_CIPHER_CAMELLIA_256_CCM, &camellia_256_ccm_info }, +#endif +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_ARIA_C) + { MBEDTLS_CIPHER_ARIA_128_ECB, &aria_128_ecb_info }, + { MBEDTLS_CIPHER_ARIA_192_ECB, &aria_192_ecb_info }, + { MBEDTLS_CIPHER_ARIA_256_ECB, &aria_256_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_ARIA_128_CBC, &aria_128_cbc_info }, + { MBEDTLS_CIPHER_ARIA_192_CBC, &aria_192_cbc_info }, + { MBEDTLS_CIPHER_ARIA_256_CBC, &aria_256_cbc_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CFB) + { MBEDTLS_CIPHER_ARIA_128_CFB128, &aria_128_cfb128_info }, + { MBEDTLS_CIPHER_ARIA_192_CFB128, &aria_192_cfb128_info }, + { MBEDTLS_CIPHER_ARIA_256_CFB128, &aria_256_cfb128_info }, +#endif +#if defined(MBEDTLS_CIPHER_MODE_CTR) + { MBEDTLS_CIPHER_ARIA_128_CTR, &aria_128_ctr_info }, + { MBEDTLS_CIPHER_ARIA_192_CTR, &aria_192_ctr_info }, + { MBEDTLS_CIPHER_ARIA_256_CTR, &aria_256_ctr_info }, +#endif +#if defined(MBEDTLS_GCM_C) + { MBEDTLS_CIPHER_ARIA_128_GCM, &aria_128_gcm_info }, + { MBEDTLS_CIPHER_ARIA_192_GCM, &aria_192_gcm_info }, + { MBEDTLS_CIPHER_ARIA_256_GCM, &aria_256_gcm_info }, +#endif +#if defined(MBEDTLS_CCM_C) + { MBEDTLS_CIPHER_ARIA_128_CCM, &aria_128_ccm_info }, + { MBEDTLS_CIPHER_ARIA_192_CCM, &aria_192_ccm_info }, + { MBEDTLS_CIPHER_ARIA_256_CCM, &aria_256_ccm_info }, +#endif +#endif /* MBEDTLS_ARIA_C */ + +#if defined(MBEDTLS_DES_C) + { MBEDTLS_CIPHER_DES_ECB, &des_ecb_info }, + { MBEDTLS_CIPHER_DES_EDE_ECB, &des_ede_ecb_info }, + { MBEDTLS_CIPHER_DES_EDE3_ECB, &des_ede3_ecb_info }, +#if defined(MBEDTLS_CIPHER_MODE_CBC) + { MBEDTLS_CIPHER_DES_CBC, &des_cbc_info }, + { MBEDTLS_CIPHER_DES_EDE_CBC, &des_ede_cbc_info }, + { MBEDTLS_CIPHER_DES_EDE3_CBC, &des_ede3_cbc_info }, +#endif +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_CHACHA20_C) + { MBEDTLS_CIPHER_CHACHA20, &chacha20_info }, +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) + { MBEDTLS_CIPHER_CHACHA20_POLY1305, &chachapoly_info }, +#endif + +#if defined(MBEDTLS_CIPHER_NULL_CIPHER) + { MBEDTLS_CIPHER_NULL, &null_cipher_info }, +#endif /* MBEDTLS_CIPHER_NULL_CIPHER */ + + { MBEDTLS_CIPHER_NONE, NULL } +}; + +#define NUM_CIPHERS sizeof mbedtls_cipher_definitions / sizeof mbedtls_cipher_definitions[0] +int mbedtls_cipher_supported[NUM_CIPHERS]; + +#endif /* MBEDTLS_CIPHER_C */ diff --git a/common/mbedtls/cmac.c b/common/mbedtls/cmac.c new file mode 100644 index 000000000..db4a71d72 --- /dev/null +++ b/common/mbedtls/cmac.c @@ -0,0 +1,1080 @@ +/** + * \file cmac.c + * + * \brief NIST SP800-38B compliant CMAC implementation for AES and 3DES + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * References: + * + * - NIST SP 800-38B Recommendation for Block Cipher Modes of Operation: The + * CMAC Mode for Authentication + * http://nvlpubs.nist.gov/nistpubs/SpecialPublications/NIST.SP.800-38b.pdf + * + * - RFC 4493 - The AES-CMAC Algorithm + * https://tools.ietf.org/html/rfc4493 + * + * - RFC 4615 - The Advanced Encryption Standard-Cipher-based Message + * Authentication Code-Pseudo-Random Function-128 (AES-CMAC-PRF-128) + * Algorithm for the Internet Key Exchange Protocol (IKE) + * https://tools.ietf.org/html/rfc4615 + * + * Additional test vectors: ISO/IEC 9797-1 + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CMAC_C) + +#include "mbedtls/cmac.h" +#include "mbedtls/platform_util.h" + +#include + + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#if defined(MBEDTLS_SELF_TEST) +#include +#define mbedtls_printf printf +#endif /* MBEDTLS_SELF_TEST */ +#endif /* MBEDTLS_PLATFORM_C */ + +#if !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) + +/* + * Multiplication by u in the Galois field of GF(2^n) + * + * As explained in NIST SP 800-38B, this can be computed: + * + * If MSB(p) = 0, then p = (p << 1) + * If MSB(p) = 1, then p = (p << 1) ^ R_n + * with R_64 = 0x1B and R_128 = 0x87 + * + * Input and output MUST NOT point to the same buffer + * Block size must be 8 bytes or 16 bytes - the block sizes for DES and AES. + */ +static int cmac_multiply_by_u( unsigned char *output, + const unsigned char *input, + size_t blocksize ) +{ + const unsigned char R_128 = 0x87; + const unsigned char R_64 = 0x1B; + unsigned char R_n, mask; + unsigned char overflow = 0x00; + int i; + + if( blocksize == MBEDTLS_AES_BLOCK_SIZE ) + { + R_n = R_128; + } + else if( blocksize == MBEDTLS_DES3_BLOCK_SIZE ) + { + R_n = R_64; + } + else + { + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + for( i = (int)blocksize - 1; i >= 0; i-- ) + { + output[i] = input[i] << 1 | overflow; + overflow = input[i] >> 7; + } + + /* mask = ( input[0] >> 7 ) ? 0xff : 0x00 + * using bit operations to avoid branches */ + + /* MSVC has a warning about unary minus on unsigned, but this is + * well-defined and precisely what we want to do here */ +#if defined(_MSC_VER) +#pragma warning( push ) +#pragma warning( disable : 4146 ) +#endif + mask = - ( input[0] >> 7 ); +#if defined(_MSC_VER) +#pragma warning( pop ) +#endif + + output[ blocksize - 1 ] ^= R_n & mask; + + return( 0 ); +} + +/* + * Generate subkeys + * + * - as specified by RFC 4493, section 2.3 Subkey Generation Algorithm + */ +static int cmac_generate_subkeys( mbedtls_cipher_context_t *ctx, + unsigned char* K1, unsigned char* K2 ) +{ + int ret; + unsigned char L[MBEDTLS_CIPHER_BLKSIZE_MAX]; + size_t olen, block_size; + + mbedtls_platform_zeroize( L, sizeof( L ) ); + + block_size = ctx->cipher_info->block_size; + + /* Calculate Ek(0) */ + if( ( ret = mbedtls_cipher_update( ctx, L, block_size, L, &olen ) ) != 0 ) + goto exit; + + /* + * Generate K1 and K2 + */ + if( ( ret = cmac_multiply_by_u( K1, L , block_size ) ) != 0 ) + goto exit; + + if( ( ret = cmac_multiply_by_u( K2, K1 , block_size ) ) != 0 ) + goto exit; + +exit: + mbedtls_platform_zeroize( L, sizeof( L ) ); + + return( ret ); +} +#endif /* !defined(MBEDTLS_CMAC_ALT) || defined(MBEDTLS_SELF_TEST) */ + +#if !defined(MBEDTLS_CMAC_ALT) +static void cmac_xor_block( unsigned char *output, const unsigned char *input1, + const unsigned char *input2, + const size_t block_size ) +{ + size_t idx; + + for( idx = 0; idx < block_size; idx++ ) + output[ idx ] = input1[ idx ] ^ input2[ idx ]; +} + +/* + * Create padded last block from (partial) last block. + * + * We can't use the padding option from the cipher layer, as it only works for + * CBC and we use ECB mode, and anyway we need to XOR K1 or K2 in addition. + */ +static void cmac_pad( unsigned char padded_block[MBEDTLS_CIPHER_BLKSIZE_MAX], + size_t padded_block_len, + const unsigned char *last_block, + size_t last_block_len ) +{ + size_t j; + + for( j = 0; j < padded_block_len; j++ ) + { + if( j < last_block_len ) + padded_block[j] = last_block[j]; + else if( j == last_block_len ) + padded_block[j] = 0x80; + else + padded_block[j] = 0x00; + } +} + +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits ) +{ + mbedtls_cipher_type_t type; + mbedtls_cmac_context_t *cmac_ctx; + int retval; + + if( ctx == NULL || ctx->cipher_info == NULL || key == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + if( ( retval = mbedtls_cipher_setkey( ctx, key, (int)keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + return( retval ); + + type = ctx->cipher_info->type; + + switch( type ) + { + case MBEDTLS_CIPHER_AES_128_ECB: + case MBEDTLS_CIPHER_AES_192_ECB: + case MBEDTLS_CIPHER_AES_256_ECB: + case MBEDTLS_CIPHER_DES_EDE3_ECB: + break; + default: + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + } + + /* Allocated and initialise in the cipher context memory for the CMAC + * context */ + cmac_ctx = mbedtls_calloc( 1, sizeof( mbedtls_cmac_context_t ) ); + if( cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_ALLOC_FAILED ); + + ctx->cmac_ctx = cmac_ctx; + + mbedtls_platform_zeroize( cmac_ctx->state, sizeof( cmac_ctx->state ) ); + + return 0; +} + +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state; + int ret = 0; + size_t n, j, olen, block_size; + + if( ctx == NULL || ctx->cipher_info == NULL || input == NULL || + ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = ctx->cmac_ctx->state; + + /* Is there data still to process from the last call, that's greater in + * size than a block? */ + if( cmac_ctx->unprocessed_len > 0 && + ilen > block_size - cmac_ctx->unprocessed_len ) + { + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + block_size - cmac_ctx->unprocessed_len ); + + cmac_xor_block( state, cmac_ctx->unprocessed_block, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + input += block_size - cmac_ctx->unprocessed_len; + ilen -= block_size - cmac_ctx->unprocessed_len; + cmac_ctx->unprocessed_len = 0; + } + + /* n is the number of blocks including any final partial block */ + n = ( ilen + block_size - 1 ) / block_size; + + /* Iterate across the input data in block sized chunks, excluding any + * final partial or complete block */ + for( j = 1; j < n; j++ ) + { + cmac_xor_block( state, input, state, block_size ); + + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + goto exit; + + ilen -= block_size; + input += block_size; + } + + /* If there is data left over that wasn't aligned to a block */ + if( ilen > 0 ) + { + memcpy( &cmac_ctx->unprocessed_block[cmac_ctx->unprocessed_len], + input, + ilen ); + cmac_ctx->unprocessed_len += ilen; + } + +exit: + return( ret ); +} + +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ) +{ + mbedtls_cmac_context_t* cmac_ctx; + unsigned char *state, *last_block; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char M_last[MBEDTLS_CIPHER_BLKSIZE_MAX]; + int ret; + size_t olen, block_size; + + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL || + output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + block_size = ctx->cipher_info->block_size; + state = cmac_ctx->state; + + mbedtls_platform_zeroize( K1, sizeof( K1 ) ); + mbedtls_platform_zeroize( K2, sizeof( K2 ) ); + cmac_generate_subkeys( ctx, K1, K2 ); + + last_block = cmac_ctx->unprocessed_block; + + /* Calculate last block */ + if( cmac_ctx->unprocessed_len < block_size ) + { + cmac_pad( M_last, block_size, last_block, cmac_ctx->unprocessed_len ); + cmac_xor_block( M_last, M_last, K2, block_size ); + } + else + { + /* Last block is complete block */ + cmac_xor_block( M_last, last_block, K1, block_size ); + } + + + cmac_xor_block( state, M_last, state, block_size ); + if( ( ret = mbedtls_cipher_update( ctx, state, block_size, state, + &olen ) ) != 0 ) + { + goto exit; + } + + memcpy( output, state, block_size ); + +exit: + /* Wipe the generated keys on the stack, and any other transients to avoid + * side channel leakage */ + mbedtls_platform_zeroize( K1, sizeof( K1 ) ); + mbedtls_platform_zeroize( K2, sizeof( K2 ) ); + + cmac_ctx->unprocessed_len = 0; + mbedtls_platform_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + + mbedtls_platform_zeroize( state, MBEDTLS_CIPHER_BLKSIZE_MAX ); + return( ret ); +} + +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ) +{ + mbedtls_cmac_context_t* cmac_ctx; + + if( ctx == NULL || ctx->cipher_info == NULL || ctx->cmac_ctx == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cmac_ctx = ctx->cmac_ctx; + + /* Reset the internal state */ + cmac_ctx->unprocessed_len = 0; + mbedtls_platform_zeroize( cmac_ctx->unprocessed_block, + sizeof( cmac_ctx->unprocessed_block ) ); + mbedtls_platform_zeroize( cmac_ctx->state, + sizeof( cmac_ctx->state ) ); + + return( 0 ); +} + +int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_cipher_context_t ctx; + int ret; + + if( cipher_info == NULL || key == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + mbedtls_cipher_init( &ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_starts( &ctx, key, keylen ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_update( &ctx, input, ilen ); + if( ret != 0 ) + goto exit; + + ret = mbedtls_cipher_cmac_finish( &ctx, output ); + +exit: + mbedtls_cipher_free( &ctx ); + + return( ret ); +} + +#if defined(MBEDTLS_AES_C) +/* + * Implementation of AES-CMAC-PRF-128 defined in RFC 4615 + */ +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_length, + const unsigned char *input, size_t in_len, + unsigned char *output ) +{ + int ret; + const mbedtls_cipher_info_t *cipher_info; + unsigned char zero_key[MBEDTLS_AES_BLOCK_SIZE]; + unsigned char int_key[MBEDTLS_AES_BLOCK_SIZE]; + + if( key == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA ); + + cipher_info = mbedtls_cipher_info_from_type( MBEDTLS_CIPHER_AES_128_ECB ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto exit; + } + + if( key_length == MBEDTLS_AES_BLOCK_SIZE ) + { + /* Use key as is */ + memcpy( int_key, key, MBEDTLS_AES_BLOCK_SIZE ); + } + else + { + memset( zero_key, 0, MBEDTLS_AES_BLOCK_SIZE ); + + ret = mbedtls_cipher_cmac( cipher_info, zero_key, 128, key, + key_length, int_key ); + if( ret != 0 ) + goto exit; + } + + ret = mbedtls_cipher_cmac( cipher_info, int_key, 128, input, in_len, + output ); + +exit: + mbedtls_platform_zeroize( int_key, sizeof( int_key ) ); + + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +#endif /* !MBEDTLS_CMAC_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * CMAC test data for SP800-38B + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/AES_CMAC.pdf + * http://csrc.nist.gov/groups/ST/toolkit/documents/Examples/TDES_CMAC.pdf + * + * AES-CMAC-PRF-128 test data from RFC 4615 + * https://tools.ietf.org/html/rfc4615#page-4 + */ + +#define NB_CMAC_TESTS_PER_KEY 4 +#define NB_PRF_TESTS 3 + +#if defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) +/* All CMAC test inputs are truncated from the same 64 byte buffer. */ +static const unsigned char test_message[] = { + /* PT */ + 0x6b, 0xc1, 0xbe, 0xe2, 0x2e, 0x40, 0x9f, 0x96, + 0xe9, 0x3d, 0x7e, 0x11, 0x73, 0x93, 0x17, 0x2a, + 0xae, 0x2d, 0x8a, 0x57, 0x1e, 0x03, 0xac, 0x9c, + 0x9e, 0xb7, 0x6f, 0xac, 0x45, 0xaf, 0x8e, 0x51, + 0x30, 0xc8, 0x1c, 0x46, 0xa3, 0x5c, 0xe4, 0x11, + 0xe5, 0xfb, 0xc1, 0x19, 0x1a, 0x0a, 0x52, 0xef, + 0xf6, 0x9f, 0x24, 0x45, 0xdf, 0x4f, 0x9b, 0x17, + 0xad, 0x2b, 0x41, 0x7b, 0xe6, 0x6c, 0x37, 0x10 +}; +#endif /* MBEDTLS_AES_C || MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* Truncation point of message for AES CMAC tests */ +static const unsigned int aes_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + /* Mlen */ + 0, + 16, + 20, + 64 +}; + +/* CMAC-AES128 Test Data */ +static const unsigned char aes_128_key[16] = { + 0x2b, 0x7e, 0x15, 0x16, 0x28, 0xae, 0xd2, 0xa6, + 0xab, 0xf7, 0x15, 0x88, 0x09, 0xcf, 0x4f, 0x3c +}; +static const unsigned char aes_128_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0xfb, 0xee, 0xd6, 0x18, 0x35, 0x71, 0x33, 0x66, + 0x7c, 0x85, 0xe0, 0x8f, 0x72, 0x36, 0xa8, 0xde + }, + { + /* K2 */ + 0xf7, 0xdd, 0xac, 0x30, 0x6a, 0xe2, 0x66, 0xcc, + 0xf9, 0x0b, 0xc1, 0x1e, 0xe4, 0x6d, 0x51, 0x3b + } +}; +static const unsigned char aes_128_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0xbb, 0x1d, 0x69, 0x29, 0xe9, 0x59, 0x37, 0x28, + 0x7f, 0xa3, 0x7d, 0x12, 0x9b, 0x75, 0x67, 0x46 + }, + { + /* Example #2 */ + 0x07, 0x0a, 0x16, 0xb4, 0x6b, 0x4d, 0x41, 0x44, + 0xf7, 0x9b, 0xdd, 0x9d, 0xd0, 0x4a, 0x28, 0x7c + }, + { + /* Example #3 */ + 0x7d, 0x85, 0x44, 0x9e, 0xa6, 0xea, 0x19, 0xc8, + 0x23, 0xa7, 0xbf, 0x78, 0x83, 0x7d, 0xfa, 0xde + }, + { + /* Example #4 */ + 0x51, 0xf0, 0xbe, 0xbf, 0x7e, 0x3b, 0x9d, 0x92, + 0xfc, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3c, 0xfe + } +}; + +/* CMAC-AES192 Test Data */ +static const unsigned char aes_192_key[24] = { + 0x8e, 0x73, 0xb0, 0xf7, 0xda, 0x0e, 0x64, 0x52, + 0xc8, 0x10, 0xf3, 0x2b, 0x80, 0x90, 0x79, 0xe5, + 0x62, 0xf8, 0xea, 0xd2, 0x52, 0x2c, 0x6b, 0x7b +}; +static const unsigned char aes_192_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0x44, 0x8a, 0x5b, 0x1c, 0x93, 0x51, 0x4b, 0x27, + 0x3e, 0xe6, 0x43, 0x9d, 0xd4, 0xda, 0xa2, 0x96 + }, + { + /* K2 */ + 0x89, 0x14, 0xb6, 0x39, 0x26, 0xa2, 0x96, 0x4e, + 0x7d, 0xcc, 0x87, 0x3b, 0xa9, 0xb5, 0x45, 0x2c + } +}; +static const unsigned char aes_192_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0xd1, 0x7d, 0xdf, 0x46, 0xad, 0xaa, 0xcd, 0xe5, + 0x31, 0xca, 0xc4, 0x83, 0xde, 0x7a, 0x93, 0x67 + }, + { + /* Example #2 */ + 0x9e, 0x99, 0xa7, 0xbf, 0x31, 0xe7, 0x10, 0x90, + 0x06, 0x62, 0xf6, 0x5e, 0x61, 0x7c, 0x51, 0x84 + }, + { + /* Example #3 */ + 0x3d, 0x75, 0xc1, 0x94, 0xed, 0x96, 0x07, 0x04, + 0x44, 0xa9, 0xfa, 0x7e, 0xc7, 0x40, 0xec, 0xf8 + }, + { + /* Example #4 */ + 0xa1, 0xd5, 0xdf, 0x0e, 0xed, 0x79, 0x0f, 0x79, + 0x4d, 0x77, 0x58, 0x96, 0x59, 0xf3, 0x9a, 0x11 + } +}; + +/* CMAC-AES256 Test Data */ +static const unsigned char aes_256_key[32] = { + 0x60, 0x3d, 0xeb, 0x10, 0x15, 0xca, 0x71, 0xbe, + 0x2b, 0x73, 0xae, 0xf0, 0x85, 0x7d, 0x77, 0x81, + 0x1f, 0x35, 0x2c, 0x07, 0x3b, 0x61, 0x08, 0xd7, + 0x2d, 0x98, 0x10, 0xa3, 0x09, 0x14, 0xdf, 0xf4 +}; +static const unsigned char aes_256_subkeys[2][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* K1 */ + 0xca, 0xd1, 0xed, 0x03, 0x29, 0x9e, 0xed, 0xac, + 0x2e, 0x9a, 0x99, 0x80, 0x86, 0x21, 0x50, 0x2f + }, + { + /* K2 */ + 0x95, 0xa3, 0xda, 0x06, 0x53, 0x3d, 0xdb, 0x58, + 0x5d, 0x35, 0x33, 0x01, 0x0c, 0x42, 0xa0, 0xd9 + } +}; +static const unsigned char aes_256_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_AES_BLOCK_SIZE] = { + { + /* Example #1 */ + 0x02, 0x89, 0x62, 0xf6, 0x1b, 0x7b, 0xf8, 0x9e, + 0xfc, 0x6b, 0x55, 0x1f, 0x46, 0x67, 0xd9, 0x83 + }, + { + /* Example #2 */ + 0x28, 0xa7, 0x02, 0x3f, 0x45, 0x2e, 0x8f, 0x82, + 0xbd, 0x4b, 0xf2, 0x8d, 0x8c, 0x37, 0xc3, 0x5c + }, + { + /* Example #3 */ + 0x15, 0x67, 0x27, 0xdc, 0x08, 0x78, 0x94, 0x4a, + 0x02, 0x3c, 0x1f, 0xe0, 0x3b, 0xad, 0x6d, 0x93 + }, + { + /* Example #4 */ + 0xe1, 0x99, 0x21, 0x90, 0x54, 0x9f, 0x6e, 0xd5, + 0x69, 0x6a, 0x2c, 0x05, 0x6c, 0x31, 0x54, 0x10 + } +}; +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_DES_C) +/* Truncation point of message for 3DES CMAC tests */ +static const unsigned int des3_message_lengths[NB_CMAC_TESTS_PER_KEY] = { + 0, + 16, + 20, + 32 +}; + +/* CMAC-TDES (Generation) - 2 Key Test Data */ +static const unsigned char des3_2key_key[24] = { + /* Key1 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, + /* Key2 */ + 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xEF, 0x01, + /* Key3 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef +}; +static const unsigned char des3_2key_subkeys[2][8] = { + { + /* K1 */ + 0x0d, 0xd2, 0xcb, 0x7a, 0x3d, 0x88, 0x88, 0xd9 + }, + { + /* K2 */ + 0x1b, 0xa5, 0x96, 0xf4, 0x7b, 0x11, 0x11, 0xb2 + } +}; +static const unsigned char des3_2key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { + { + /* Sample #1 */ + 0x79, 0xce, 0x52, 0xa7, 0xf7, 0x86, 0xa9, 0x60 + }, + { + /* Sample #2 */ + 0xcc, 0x18, 0xa0, 0xb7, 0x9a, 0xf2, 0x41, 0x3b + }, + { + /* Sample #3 */ + 0xc0, 0x6d, 0x37, 0x7e, 0xcd, 0x10, 0x19, 0x69 + }, + { + /* Sample #4 */ + 0x9c, 0xd3, 0x35, 0x80, 0xf9, 0xb6, 0x4d, 0xfb + } +}; + +/* CMAC-TDES (Generation) - 3 Key Test Data */ +static const unsigned char des3_3key_key[24] = { + /* Key1 */ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xaa, 0xcd, 0xef, + /* Key2 */ + 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, + /* Key3 */ + 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef, 0x01, 0x23 +}; +static const unsigned char des3_3key_subkeys[2][8] = { + { + /* K1 */ + 0x9d, 0x74, 0xe7, 0x39, 0x33, 0x17, 0x96, 0xc0 + }, + { + /* K2 */ + 0x3a, 0xe9, 0xce, 0x72, 0x66, 0x2f, 0x2d, 0x9b + } +}; +static const unsigned char des3_3key_expected_result[NB_CMAC_TESTS_PER_KEY][MBEDTLS_DES3_BLOCK_SIZE] = { + { + /* Sample #1 */ + 0x7d, 0xb0, 0xd3, 0x7d, 0xf9, 0x36, 0xc5, 0x50 + }, + { + /* Sample #2 */ + 0x30, 0x23, 0x9c, 0xf1, 0xf5, 0x2e, 0x66, 0x09 + }, + { + /* Sample #3 */ + 0x6c, 0x9f, 0x3e, 0xe4, 0x92, 0x3f, 0x6b, 0xe2 + }, + { + /* Sample #4 */ + 0x99, 0x42, 0x9b, 0xd0, 0xbF, 0x79, 0x04, 0xe5 + } +}; + +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* AES AES-CMAC-PRF-128 Test Data */ +static const unsigned char PRFK[] = { + /* Key */ + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0xed, 0xcb +}; + +/* Sizes in bytes */ +static const size_t PRFKlen[NB_PRF_TESTS] = { + 18, + 16, + 10 +}; + +/* Message */ +static const unsigned char PRFM[] = { + 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, + 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, + 0x10, 0x11, 0x12, 0x13 +}; + +static const unsigned char PRFT[NB_PRF_TESTS][16] = { + { + 0x84, 0xa3, 0x48, 0xa4, 0xa4, 0x5d, 0x23, 0x5b, + 0xab, 0xff, 0xfc, 0x0d, 0x2b, 0x4d, 0xa0, 0x9a + }, + { + 0x98, 0x0a, 0xe8, 0x7b, 0x5f, 0x4c, 0x9c, 0x52, + 0x14, 0xf5, 0xb6, 0xa8, 0x45, 0x5e, 0x4c, 0x2d + }, + { + 0x29, 0x0d, 0x9e, 0x11, 0x2e, 0xdb, 0x09, 0xee, + 0x14, 0x1f, 0xcf, 0x64, 0xc0, 0xb7, 0x2f, 0x3d + } +}; +#endif /* MBEDTLS_AES_C */ + +static int cmac_test_subkeys( int verbose, + const char* testname, + const unsigned char* key, + int keybits, + const unsigned char* subkeys, + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) +{ + int i, ret = 0; + mbedtls_cipher_context_t ctx; + const mbedtls_cipher_info_t *cipher_info; + unsigned char K1[MBEDTLS_CIPHER_BLKSIZE_MAX]; + unsigned char K2[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + return( MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE ); + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC subkey #%u: ", testname, i + 1 ); + + mbedtls_cipher_init( &ctx ); + + if( ( ret = mbedtls_cipher_setup( &ctx, cipher_info ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto cleanup; + } + + if( ( ret = mbedtls_cipher_setkey( &ctx, key, keybits, + MBEDTLS_ENCRYPT ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "test execution failed\n" ); + + goto cleanup; + } + + ret = cmac_generate_subkeys( &ctx, K1, K2 ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( ( ret = memcmp( K1, subkeys, block_size ) ) != 0 || + ( ret = memcmp( K2, &subkeys[block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + mbedtls_cipher_free( &ctx ); + } + + ret = 0; + goto exit; + +cleanup: + mbedtls_cipher_free( &ctx ); + +exit: + return( ret ); +} + +static int cmac_test_wth_cipher( int verbose, + const char* testname, + const unsigned char* key, + int keybits, + const unsigned char* messages, + const unsigned int message_lengths[4], + const unsigned char* expected_result, + mbedtls_cipher_type_t cipher_type, + int block_size, + int num_tests ) +{ + const mbedtls_cipher_info_t *cipher_info; + int i, ret = 0; + unsigned char output[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + { + /* Failing at this point must be due to a build issue */ + ret = MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE; + goto exit; + } + + for( i = 0; i < num_tests; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " %s CMAC #%u: ", testname, i + 1 ); + + if( ( ret = mbedtls_cipher_cmac( cipher_info, key, keybits, messages, + message_lengths[i], output ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( ( ret = memcmp( output, &expected_result[i * block_size], block_size ) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + ret = 0; + +exit: + return( ret ); +} + +#if defined(MBEDTLS_AES_C) +static int test_aes128_cmac_prf( int verbose ) +{ + int i; + int ret; + unsigned char output[MBEDTLS_AES_BLOCK_SIZE]; + + for( i = 0; i < NB_PRF_TESTS; i++ ) + { + mbedtls_printf( " AES CMAC 128 PRF #%u: ", i ); + ret = mbedtls_aes_cmac_prf_128( PRFK, PRFKlen[i], PRFM, 20, output ); + if( ret != 0 || + memcmp( output, PRFT[i], MBEDTLS_AES_BLOCK_SIZE ) != 0 ) + { + + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + else if( verbose != 0 ) + { + mbedtls_printf( "passed\n" ); + } + } + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +int mbedtls_cmac_self_test( int verbose ) +{ + int ret; + +#if defined(MBEDTLS_AES_C) + /* AES-128 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 128", + aes_128_key, + 128, + (const unsigned char*)aes_128_subkeys, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 128", + aes_128_key, + 128, + test_message, + aes_message_lengths, + (const unsigned char*)aes_128_expected_result, + MBEDTLS_CIPHER_AES_128_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* AES-192 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 192", + aes_192_key, + 192, + (const unsigned char*)aes_192_subkeys, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "AES 192", + aes_192_key, + 192, + test_message, + aes_message_lengths, + (const unsigned char*)aes_192_expected_result, + MBEDTLS_CIPHER_AES_192_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* AES-256 */ + if( ( ret = cmac_test_subkeys( verbose, + "AES 256", + aes_256_key, + 256, + (const unsigned char*)aes_256_subkeys, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher ( verbose, + "AES 256", + aes_256_key, + 256, + test_message, + aes_message_lengths, + (const unsigned char*)aes_256_expected_result, + MBEDTLS_CIPHER_AES_256_ECB, + MBEDTLS_AES_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_DES_C) + /* 3DES 2 key */ + if( ( ret = cmac_test_subkeys( verbose, + "3DES 2 key", + des3_2key_key, + 192, + (const unsigned char*)des3_2key_subkeys, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 2 key", + des3_2key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*)des3_2key_expected_result, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + /* 3DES 3 key */ + if( ( ret = cmac_test_subkeys( verbose, + "3DES 3 key", + des3_3key_key, + 192, + (const unsigned char*)des3_3key_subkeys, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = cmac_test_wth_cipher( verbose, + "3DES 3 key", + des3_3key_key, + 192, + test_message, + des3_message_lengths, + (const unsigned char*)des3_3key_expected_result, + MBEDTLS_CIPHER_DES_EDE3_ECB, + MBEDTLS_DES3_BLOCK_SIZE, + NB_CMAC_TESTS_PER_KEY ) ) != 0 ) + { + return( ret ); + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( ( ret = test_aes128_cmac_prf( verbose ) ) != 0 ) + return( ret ); +#endif /* MBEDTLS_AES_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CMAC_C */ diff --git a/common/mbedtls/cmac.h b/common/mbedtls/cmac.h new file mode 100644 index 000000000..f6fc79b74 --- /dev/null +++ b/common/mbedtls/cmac.h @@ -0,0 +1,208 @@ +/** + * \file cmac.h + * + * \brief This file contains CMAC definitions and functions. + * + * The Cipher-based Message Authentication Code (CMAC) Mode for + * Authentication is defined in RFC-4493: The AES-CMAC Algorithm. + */ +/* + * Copyright (C) 2015-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CMAC_H +#define MBEDTLS_CMAC_H + +#include "cipher.h" + +#ifdef __cplusplus +extern "C" { +#endif + +#define MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED -0x007A /**< CMAC hardware accelerator failed. */ + +#define MBEDTLS_AES_BLOCK_SIZE 16 +#define MBEDTLS_DES3_BLOCK_SIZE 8 + +#if defined(MBEDTLS_AES_C) +#define MBEDTLS_CIPHER_BLKSIZE_MAX 16 /**< The longest block used by CMAC is that of AES. */ +#else +#define MBEDTLS_CIPHER_BLKSIZE_MAX 8 /**< The longest block used by CMAC is that of 3DES. */ +#endif + +#if !defined(MBEDTLS_CMAC_ALT) + +/** + * The CMAC context structure. + */ +struct mbedtls_cmac_context_t +{ + /** The internal state of the CMAC algorithm. */ + unsigned char state[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** Unprocessed data - either data that was not block aligned and is still + * pending processing, or the final block. */ + unsigned char unprocessed_block[MBEDTLS_CIPHER_BLKSIZE_MAX]; + + /** The length of data pending processing. */ + size_t unprocessed_len; +}; + +#else /* !MBEDTLS_CMAC_ALT */ +#include "cmac_alt.h" +#endif /* !MBEDTLS_CMAC_ALT */ + +/** + * \brief This function sets the CMAC key, and prepares to authenticate + * the input data. + * Must be called with an initialized cipher context. + * + * \param ctx The cipher context used for the CMAC operation, initialized + * as one of the following types: MBEDTLS_CIPHER_AES_128_ECB, + * MBEDTLS_CIPHER_AES_192_ECB, MBEDTLS_CIPHER_AES_256_ECB, + * or MBEDTLS_CIPHER_DES_EDE3_ECB. + * \param key The CMAC key. + * \param keybits The length of the CMAC key in bits. + * Must be supported by the cipher. + * + * \return \c 0 on success. + * \return A cipher-specific error code on failure. + */ +int mbedtls_cipher_cmac_starts( mbedtls_cipher_context_t *ctx, + const unsigned char *key, size_t keybits ); + +/** + * \brief This function feeds an input buffer into an ongoing CMAC + * computation. + * + * It is called between mbedtls_cipher_cmac_starts() or + * mbedtls_cipher_cmac_reset(), and mbedtls_cipher_cmac_finish(). + * Can be called repeatedly. + * + * \param ctx The cipher context used for the CMAC operation. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_update( mbedtls_cipher_context_t *ctx, + const unsigned char *input, size_t ilen ); + +/** + * \brief This function finishes the CMAC operation, and writes + * the result to the output buffer. + * + * It is called after mbedtls_cipher_cmac_update(). + * It can be followed by mbedtls_cipher_cmac_reset() and + * mbedtls_cipher_cmac_update(), or mbedtls_cipher_free(). + * + * \param ctx The cipher context used for the CMAC operation. + * \param output The output buffer for the CMAC checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_finish( mbedtls_cipher_context_t *ctx, + unsigned char *output ); + +/** + * \brief This function prepares the authentication of another + * message with the same key as the previous CMAC + * operation. + * + * It is called after mbedtls_cipher_cmac_finish() + * and before mbedtls_cipher_cmac_update(). + * + * \param ctx The cipher context used for the CMAC operation. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac_reset( mbedtls_cipher_context_t *ctx ); + +/** + * \brief This function calculates the full generic CMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The CMAC result is calculated as + * output = generic CMAC(cmac key, input buffer). + * + * + * \param cipher_info The cipher information. + * \param key The CMAC key. + * \param keylen The length of the CMAC key in bits. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The buffer for the generic CMAC result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA + * if parameter verification fails. + */ +int mbedtls_cipher_cmac( const mbedtls_cipher_info_t *cipher_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +#if defined(MBEDTLS_AES_C) +/** + * \brief This function implements the AES-CMAC-PRF-128 pseudorandom + * function, as defined in + * RFC-4615: The Advanced Encryption Standard-Cipher-based + * Message Authentication Code-Pseudo-Random Function-128 + * (AES-CMAC-PRF-128) Algorithm for the Internet Key + * Exchange Protocol (IKE). + * + * \param key The key to use. + * \param key_len The key length in Bytes. + * \param input The buffer holding the input data. + * \param in_len The length of the input data in Bytes. + * \param output The buffer holding the generated 16 Bytes of + * pseudorandom output. + * + * \return \c 0 on success. + */ +int mbedtls_aes_cmac_prf_128( const unsigned char *key, size_t key_len, + const unsigned char *input, size_t in_len, + unsigned char output[16] ); +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_SELF_TEST) && ( defined(MBEDTLS_AES_C) || defined(MBEDTLS_DES_C) ) +/** + * \brief The CMAC checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_cmac_self_test( int verbose ); +#endif /* MBEDTLS_SELF_TEST && ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_CMAC_H */ diff --git a/common/mbedtls/config.h b/common/mbedtls/config.h new file mode 100644 index 000000000..dfda7ca40 --- /dev/null +++ b/common/mbedtls/config.h @@ -0,0 +1,3129 @@ +/** + * \file config.h + * + * \brief Configuration options (set of defines) + * + * This set of compile-time options may be used to enable + * or disable features selectively, and reduce the global + * memory footprint. + */ +/* + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CONFIG_H +#define MBEDTLS_CONFIG_H + +#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) +#define _CRT_SECURE_NO_DEPRECATE 1 +#endif + +/** + * \name SECTION: System support + * + * This section sets system specific settings. + * \{ + */ + +/** + * \def MBEDTLS_HAVE_ASM + * + * The compiler has support for asm(). + * + * Requires support for asm() in compiler. + * + * Used in: + * library/aria.c + * library/timing.c + * include/mbedtls/bn_mul.h + * + * Required by: + * MBEDTLS_AESNI_C + * MBEDTLS_PADLOCK_C + * + * Comment to disable the use of assembly code. + */ +//#define MBEDTLS_HAVE_ASM + +/** + * \def MBEDTLS_NO_UDBL_DIVISION + * + * The platform lacks support for double-width integer division (64-bit + * division on a 32-bit platform, 128-bit division on a 64-bit platform). + * + * Used in: + * include/mbedtls/bignum.h + * library/bignum.c + * + * The bignum code uses double-width division to speed up some operations. + * Double-width division is often implemented in software that needs to + * be linked with the program. The presence of a double-width integer + * type is usually detected automatically through preprocessor macros, + * but the automatic detection cannot know whether the code needs to + * and can be linked with an implementation of division for that type. + * By default division is assumed to be usable if the type is present. + * Uncomment this option to prevent the use of double-width division. + * + * Note that division for the native integer type is always required. + * Furthermore, a 64-bit type is always required even on a 32-bit + * platform, but it need not support multiplication or division. In some + * cases it is also desirable to disable some double-width operations. For + * example, if double-width division is implemented in software, disabling + * it can reduce code size in some embedded targets. + */ +//#define MBEDTLS_NO_UDBL_DIVISION + +/** + * \def MBEDTLS_NO_64BIT_MULTIPLICATION + * + * The platform lacks support for 32x32 -> 64-bit multiplication. + * + * Used in: + * library/poly1305.c + * + * Some parts of the library may use multiplication of two unsigned 32-bit + * operands with a 64-bit result in order to speed up computations. On some + * platforms, this is not available in hardware and has to be implemented in + * software, usually in a library provided by the toolchain. + * + * Sometimes it is not desirable to have to link to that library. This option + * removes the dependency of that library on platforms that lack a hardware + * 64-bit multiplier by embedding a software implementation in Mbed TLS. + * + * Note that depending on the compiler, this may decrease performance compared + * to using the library function provided by the toolchain. + */ +//#define MBEDTLS_NO_64BIT_MULTIPLICATION + +/** + * \def MBEDTLS_HAVE_SSE2 + * + * CPU supports SSE2 instruction set. + * + * Uncomment if the CPU supports SSE2 (IA-32 specific). + */ +//#define MBEDTLS_HAVE_SSE2 + +/** + * \def MBEDTLS_HAVE_TIME + * + * System has time.h and time(). + * The time does not need to be correct, only time differences are used, + * by contrast with MBEDTLS_HAVE_TIME_DATE + * + * Defining MBEDTLS_HAVE_TIME allows you to specify MBEDTLS_PLATFORM_TIME_ALT, + * MBEDTLS_PLATFORM_TIME_MACRO, MBEDTLS_PLATFORM_TIME_TYPE_MACRO and + * MBEDTLS_PLATFORM_STD_TIME. + * + * Comment if your system does not support time functions + */ +//#define MBEDTLS_HAVE_TIME + +/** + * \def MBEDTLS_HAVE_TIME_DATE + * + * System has time.h and time(), gmtime() and the clock is correct. + * The time needs to be correct (not necesarily very accurate, but at least + * the date should be correct). This is used to verify the validity period of + * X.509 certificates. + * + * Comment if your system does not have a correct clock. + */ +//#define MBEDTLS_HAVE_TIME_DATE + +/** + * \def MBEDTLS_PLATFORM_MEMORY + * + * Enable the memory allocation layer. + * + * By default mbed TLS uses the system-provided calloc() and free(). + * This allows different allocators (self-implemented or provided) to be + * provided to the platform abstraction layer. + * + * Enabling MBEDTLS_PLATFORM_MEMORY without the + * MBEDTLS_PLATFORM_{FREE,CALLOC}_MACROs will provide + * "mbedtls_platform_set_calloc_free()" allowing you to set an alternative calloc() and + * free() function pointer at runtime. + * + * Enabling MBEDTLS_PLATFORM_MEMORY and specifying + * MBEDTLS_PLATFORM_{CALLOC,FREE}_MACROs will allow you to specify the + * alternate function at compile time. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Enable this layer to allow use of alternative memory allocators. + */ +//#define MBEDTLS_PLATFORM_MEMORY + +/** + * \def MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + * + * Do not assign standard functions in the platform layer (e.g. calloc() to + * MBEDTLS_PLATFORM_STD_CALLOC and printf() to MBEDTLS_PLATFORM_STD_PRINTF) + * + * This makes sure there are no linking errors on platforms that do not support + * these functions. You will HAVE to provide alternatives, either at runtime + * via the platform_set_xxx() functions or at compile time by setting + * the MBEDTLS_PLATFORM_STD_XXX defines, or enabling a + * MBEDTLS_PLATFORM_XXX_MACRO. + * + * Requires: MBEDTLS_PLATFORM_C + * + * Uncomment to prevent default assignment of standard functions in the + * platform layer. + */ +//#define MBEDTLS_PLATFORM_NO_STD_FUNCTIONS + +/** + * \def MBEDTLS_PLATFORM_EXIT_ALT + * + * MBEDTLS_PLATFORM_XXX_ALT: Uncomment a macro to let mbed TLS support the + * function in the platform abstraction layer. + * + * Example: In case you uncomment MBEDTLS_PLATFORM_PRINTF_ALT, mbed TLS will + * provide a function "mbedtls_platform_set_printf()" that allows you to set an + * alternative printf function pointer. + * + * All these define require MBEDTLS_PLATFORM_C to be defined! + * + * \note MBEDTLS_PLATFORM_SNPRINTF_ALT is required on Windows; + * it will be enabled automatically by check_config.h + * + * \warning MBEDTLS_PLATFORM_XXX_ALT cannot be defined at the same time as + * MBEDTLS_PLATFORM_XXX_MACRO! + * + * Requires: MBEDTLS_PLATFORM_TIME_ALT requires MBEDTLS_HAVE_TIME + * + * Uncomment a macro to enable alternate implementation of specific base + * platform function + */ +//#define MBEDTLS_PLATFORM_EXIT_ALT +//#define MBEDTLS_PLATFORM_TIME_ALT +//#define MBEDTLS_PLATFORM_FPRINTF_ALT +//#define MBEDTLS_PLATFORM_PRINTF_ALT +//#define MBEDTLS_PLATFORM_SNPRINTF_ALT +//#define MBEDTLS_PLATFORM_NV_SEED_ALT +//#define MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT + +/** + * \def MBEDTLS_DEPRECATED_WARNING + * + * Mark deprecated functions so that they generate a warning if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * This only works with GCC and Clang. With other compilers, you may want to + * use MBEDTLS_DEPRECATED_REMOVED + * + * Uncomment to get warnings on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_WARNING + +/** + * \def MBEDTLS_DEPRECATED_REMOVED + * + * Remove deprecated functions so that they generate an error if used. + * Functions deprecated in one version will usually be removed in the next + * version. You can enable this to help you prepare the transition to a new + * major version by making sure your code is not using these functions. + * + * Uncomment to get errors on using deprecated functions. + */ +//#define MBEDTLS_DEPRECATED_REMOVED + +/* \} name SECTION: System support */ + +/** + * \name SECTION: mbed TLS feature support + * + * This section sets support for features that are or are not needed + * within the modules that are enabled. + * \{ + */ + +/** + * \def MBEDTLS_TIMING_ALT + * + * Uncomment to provide your own alternate implementation for mbedtls_timing_hardclock(), + * mbedtls_timing_get_timer(), mbedtls_set_alarm(), mbedtls_set/get_delay() + * + * Only works if you have MBEDTLS_TIMING_C enabled. + * + * You will need to provide a header "timing_alt.h" and an implementation at + * compile time. + */ +//#define MBEDTLS_TIMING_ALT + +/** + * \def MBEDTLS_AES_ALT + * + * MBEDTLS__MODULE_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternate core implementation of a symmetric crypto, an arithmetic or hash + * module (e.g. platform specific assembly optimized implementations). Keep + * in mind that the function prototypes should remain the same. + * + * This replaces the whole module. If you only want to replace one of the + * functions, use one of the MBEDTLS__FUNCTION_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_AES_ALT, mbed TLS will no longer + * provide the "struct mbedtls_aes_context" definition and omit the base + * function declarations and implementations. "aes_alt.h" will be included from + * "aes.h" to include the new function definitions. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * module. + * + * \warning MD2, MD4, MD5, ARC4, DES and SHA-1 are considered weak and their + * use constitutes a security risk. If possible, we recommend + * avoiding dependencies on them, and considering stronger message + * digests and ciphers instead. + * + */ +//#define MBEDTLS_AES_ALT +//#define MBEDTLS_ARC4_ALT +//#define MBEDTLS_ARIA_ALT +//#define MBEDTLS_BLOWFISH_ALT +//#define MBEDTLS_CAMELLIA_ALT +//#define MBEDTLS_CCM_ALT +//#define MBEDTLS_CHACHA20_ALT +//#define MBEDTLS_CHACHAPOLY_ALT +//#define MBEDTLS_CMAC_ALT +//#define MBEDTLS_DES_ALT +//#define MBEDTLS_DHM_ALT +//#define MBEDTLS_ECJPAKE_ALT +//#define MBEDTLS_GCM_ALT +//#define MBEDTLS_NIST_KW_ALT +//#define MBEDTLS_MD2_ALT +//#define MBEDTLS_MD4_ALT +//#define MBEDTLS_MD5_ALT +//#define MBEDTLS_POLY1305_ALT +//#define MBEDTLS_RIPEMD160_ALT +//#define MBEDTLS_RSA_ALT +//#define MBEDTLS_SHA1_ALT +//#define MBEDTLS_SHA256_ALT +//#define MBEDTLS_SHA512_ALT +//#define MBEDTLS_XTEA_ALT + +/* + * When replacing the elliptic curve module, pleace consider, that it is + * implemented with two .c files: + * - ecp.c + * - ecp_curves.c + * You can replace them very much like all the other MBEDTLS__MODULE_NAME__ALT + * macros as described above. The only difference is that you have to make sure + * that you provide functionality for both .c files. + */ +//#define MBEDTLS_ECP_ALT + +/** + * \def MBEDTLS_MD2_PROCESS_ALT + * + * MBEDTLS__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use you + * alternate core implementation of symmetric crypto or hash function. Keep in + * mind that function prototypes should remain the same. + * + * This replaces only one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS__MODULE_NAME__ALT flags. + * + * Example: In case you uncomment MBEDTLS_SHA256_PROCESS_ALT, mbed TLS will + * no longer provide the mbedtls_sha1_process() function, but it will still provide + * the other function (using your mbedtls_sha1_process() function) and the definition + * of mbedtls_sha1_context, so your implementation of mbedtls_sha1_process must be compatible + * with this definition. + * + * \note Because of a signature change, the core AES encryption and decryption routines are + * currently named mbedtls_aes_internal_encrypt and mbedtls_aes_internal_decrypt, + * respectively. When setting up alternative implementations, these functions should + * be overriden, but the wrapper functions mbedtls_aes_decrypt and mbedtls_aes_encrypt + * must stay untouched. + * + * \note If you use the AES_xxx_ALT macros, then is is recommended to also set + * MBEDTLS_AES_ROM_TABLES in order to help the linker garbage-collect the AES + * tables. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + * + * \warning MD2, MD4, MD5, DES and SHA-1 are considered weak and their use + * constitutes a security risk. If possible, we recommend avoiding + * dependencies on them, and considering stronger message digests + * and ciphers instead. + * + */ +//#define MBEDTLS_MD2_PROCESS_ALT +//#define MBEDTLS_MD4_PROCESS_ALT +//#define MBEDTLS_MD5_PROCESS_ALT +//#define MBEDTLS_RIPEMD160_PROCESS_ALT +//#define MBEDTLS_SHA1_PROCESS_ALT +//#define MBEDTLS_SHA256_PROCESS_ALT +//#define MBEDTLS_SHA512_PROCESS_ALT +//#define MBEDTLS_DES_SETKEY_ALT +//#define MBEDTLS_DES_CRYPT_ECB_ALT +//#define MBEDTLS_DES3_CRYPT_ECB_ALT +//#define MBEDTLS_AES_SETKEY_ENC_ALT +//#define MBEDTLS_AES_SETKEY_DEC_ALT +//#define MBEDTLS_AES_ENCRYPT_ALT +//#define MBEDTLS_AES_DECRYPT_ALT +//#define MBEDTLS_ECDH_GEN_PUBLIC_ALT +//#define MBEDTLS_ECDH_COMPUTE_SHARED_ALT +//#define MBEDTLS_ECDSA_VERIFY_ALT +//#define MBEDTLS_ECDSA_SIGN_ALT +//#define MBEDTLS_ECDSA_GENKEY_ALT + +/** + * \def MBEDTLS_ECP_INTERNAL_ALT + * + * Expose a part of the internal interface of the Elliptic Curve Point module. + * + * MBEDTLS_ECP__FUNCTION_NAME__ALT: Uncomment a macro to let mbed TLS use your + * alternative core implementation of elliptic curve arithmetic. Keep in mind + * that function prototypes should remain the same. + * + * This partially replaces one function. The header file from mbed TLS is still + * used, in contrast to the MBEDTLS_ECP_ALT flag. The original implementation + * is still present and it is used for group structures not supported by the + * alternative. + * + * Any of these options become available by defining MBEDTLS_ECP_INTERNAL_ALT + * and implementing the following functions: + * unsigned char mbedtls_internal_ecp_grp_capable( + * const mbedtls_ecp_group *grp ) + * int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ) + * void mbedtls_internal_ecp_deinit( const mbedtls_ecp_group *grp ) + * The mbedtls_internal_ecp_grp_capable function should return 1 if the + * replacement functions implement arithmetic for the given group and 0 + * otherwise. + * The functions mbedtls_internal_ecp_init and mbedtls_internal_ecp_deinit are + * called before and after each point operation and provide an opportunity to + * implement optimized set up and tear down instructions. + * + * Example: In case you uncomment MBEDTLS_ECP_INTERNAL_ALT and + * MBEDTLS_ECP_DOUBLE_JAC_ALT, mbed TLS will still provide the ecp_double_jac + * function, but will use your mbedtls_internal_ecp_double_jac if the group is + * supported (your mbedtls_internal_ecp_grp_capable function returns 1 when + * receives it as an argument). If the group is not supported then the original + * implementation is used. The other functions and the definition of + * mbedtls_ecp_group and mbedtls_ecp_point will not change, so your + * implementation of mbedtls_internal_ecp_double_jac and + * mbedtls_internal_ecp_grp_capable must be compatible with this definition. + * + * Uncomment a macro to enable alternate implementation of the corresponding + * function. + */ +/* Required for all the functions in this section */ +//#define MBEDTLS_ECP_INTERNAL_ALT +/* Support for Weierstrass curves with Jacobi representation */ +//#define MBEDTLS_ECP_RANDOMIZE_JAC_ALT +//#define MBEDTLS_ECP_ADD_MIXED_ALT +//#define MBEDTLS_ECP_DOUBLE_JAC_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT +//#define MBEDTLS_ECP_NORMALIZE_JAC_ALT +/* Support for curves with Montgomery arithmetic */ +//#define MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT +//#define MBEDTLS_ECP_RANDOMIZE_MXZ_ALT +//#define MBEDTLS_ECP_NORMALIZE_MXZ_ALT + +/** + * \def MBEDTLS_TEST_NULL_ENTROPY + * + * Enables testing and use of mbed TLS without any configured entropy sources. + * This permits use of the library on platforms before an entropy source has + * been integrated (see for example the MBEDTLS_ENTROPY_HARDWARE_ALT or the + * MBEDTLS_ENTROPY_NV_SEED switches). + * + * WARNING! This switch MUST be disabled in production builds, and is suitable + * only for development. + * Enabling the switch negates any security provided by the library. + * + * Requires MBEDTLS_ENTROPY_C, MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + */ +//#define MBEDTLS_TEST_NULL_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_HARDWARE_ALT + * + * Uncomment this macro to let mbed TLS use your own implementation of a + * hardware entropy collector. + * + * Your function must be called \c mbedtls_hardware_poll(), have the same + * prototype as declared in entropy_poll.h, and accept NULL as first argument. + * + * Uncomment to use your own hardware entropy collector. + */ +//#define MBEDTLS_ENTROPY_HARDWARE_ALT + +/** + * \def MBEDTLS_AES_ROM_TABLES + * + * Use precomputed AES tables stored in ROM. + * + * Uncomment this macro to use precomputed AES tables stored in ROM. + * Comment this macro to generate AES tables in RAM at runtime. + * + * Tradeoff: Using precomputed ROM tables reduces RAM usage by ~8kb + * (or ~2kb if \c MBEDTLS_AES_FEWER_TABLES is used) and reduces the + * initialization time before the first AES operation can be performed. + * It comes at the cost of additional ~8kb ROM use (resp. ~2kb if \c + * MBEDTLS_AES_FEWER_TABLES below is used), and potentially degraded + * performance if ROM access is slower than RAM access. + * + * This option is independent of \c MBEDTLS_AES_FEWER_TABLES. + * + */ +//#define MBEDTLS_AES_ROM_TABLES + +/** + * \def MBEDTLS_AES_FEWER_TABLES + * + * Use less ROM/RAM for AES tables. + * + * Uncommenting this macro omits 75% of the AES tables from + * ROM / RAM (depending on the value of \c MBEDTLS_AES_ROM_TABLES) + * by computing their values on the fly during operations + * (the tables are entry-wise rotations of one another). + * + * Tradeoff: Uncommenting this reduces the RAM / ROM footprint + * by ~6kb but at the cost of more arithmetic operations during + * runtime. Specifically, one has to compare 4 accesses within + * different tables to 4 accesses with additional arithmetic + * operations within the same table. The performance gain/loss + * depends on the system and memory details. + * + * This option is independent of \c MBEDTLS_AES_ROM_TABLES. + * + */ +//#define MBEDTLS_AES_FEWER_TABLES + +/** + * \def MBEDTLS_CAMELLIA_SMALL_MEMORY + * + * Use less ROM for the Camellia implementation (saves about 768 bytes). + * + * Uncomment this macro to use less memory for Camellia. + */ +//#define MBEDTLS_CAMELLIA_SMALL_MEMORY + +/** + * \def MBEDTLS_CIPHER_MODE_CBC + * + * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CBC + +/** + * \def MBEDTLS_CIPHER_MODE_CFB + * + * Enable Cipher Feedback mode (CFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CFB + +/** + * \def MBEDTLS_CIPHER_MODE_CTR + * + * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_CTR + +/** + * \def MBEDTLS_CIPHER_MODE_OFB + * + * Enable Output Feedback mode (OFB) for symmetric ciphers. + */ +#define MBEDTLS_CIPHER_MODE_OFB + +/** + * \def MBEDTLS_CIPHER_MODE_XTS + * + * Enable Xor-encrypt-xor with ciphertext stealing mode (XTS) for AES. + */ +#define MBEDTLS_CIPHER_MODE_XTS + +/** + * \def MBEDTLS_CIPHER_NULL_CIPHER + * + * Enable NULL cipher. + * Warning: Only do so when you know what you are doing. This allows for + * encryption or channels without any security! + * + * Requires MBEDTLS_ENABLE_WEAK_CIPHERSUITES as well to enable + * the following ciphersuites: + * MBEDTLS_TLS_ECDH_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_WITH_NULL_SHA + * MBEDTLS_TLS_RSA_WITH_NULL_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_NULL_SHA + * MBEDTLS_TLS_PSK_WITH_NULL_SHA384 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA256 + * MBEDTLS_TLS_PSK_WITH_NULL_SHA + * + * Uncomment this macro to enable the NULL cipher and ciphersuites + */ +//#define MBEDTLS_CIPHER_NULL_CIPHER + +/** + * \def MBEDTLS_CIPHER_PADDING_PKCS7 + * + * MBEDTLS_CIPHER_PADDING_XXX: Uncomment or comment macros to add support for + * specific padding modes in the cipher layer with cipher modes that support + * padding (e.g. CBC) + * + * If you disable all padding modes, only full blocks can be used with CBC. + * + * Enable padding modes in the cipher layer. + */ +#define MBEDTLS_CIPHER_PADDING_PKCS7 +#define MBEDTLS_CIPHER_PADDING_ONE_AND_ZEROS +#define MBEDTLS_CIPHER_PADDING_ZEROS_AND_LEN +#define MBEDTLS_CIPHER_PADDING_ZEROS + +/** + * \def MBEDTLS_ENABLE_WEAK_CIPHERSUITES + * + * Enable weak ciphersuites in SSL / TLS. + * Warning: Only do so when you know what you are doing. This allows for + * channels with virtually no security at all! + * + * This enables the following ciphersuites: + * MBEDTLS_TLS_RSA_WITH_DES_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_DES_CBC_SHA + * + * Uncomment this macro to enable weak ciphersuites + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +//#define MBEDTLS_ENABLE_WEAK_CIPHERSUITES + +/** + * \def MBEDTLS_REMOVE_ARC4_CIPHERSUITES + * + * Remove RC4 ciphersuites by default in SSL / TLS. + * This flag removes the ciphersuites based on RC4 from the default list as + * returned by mbedtls_ssl_list_ciphersuites(). However, it is still possible to + * enable (some of) them with mbedtls_ssl_conf_ciphersuites() by including them + * explicitly. + * + * Uncomment this macro to remove RC4 ciphersuites by default. + */ +#define MBEDTLS_REMOVE_ARC4_CIPHERSUITES + +/** + * \def MBEDTLS_ECP_DP_SECP192R1_ENABLED + * + * MBEDTLS_ECP_XXXX_ENABLED: Enables specific curves within the Elliptic Curve + * module. By default all supported curves are enabled. + * + * Comment macros to disable the curve and functions for it + */ +#define MBEDTLS_ECP_DP_SECP192R1_ENABLED +#define MBEDTLS_ECP_DP_SECP224R1_ENABLED +#define MBEDTLS_ECP_DP_SECP256R1_ENABLED +#define MBEDTLS_ECP_DP_SECP384R1_ENABLED +#define MBEDTLS_ECP_DP_SECP521R1_ENABLED +#define MBEDTLS_ECP_DP_SECP192K1_ENABLED +#define MBEDTLS_ECP_DP_SECP224K1_ENABLED +#define MBEDTLS_ECP_DP_SECP256K1_ENABLED +#define MBEDTLS_ECP_DP_BP256R1_ENABLED +#define MBEDTLS_ECP_DP_BP384R1_ENABLED +#define MBEDTLS_ECP_DP_BP512R1_ENABLED +#define MBEDTLS_ECP_DP_CURVE25519_ENABLED +#define MBEDTLS_ECP_DP_CURVE448_ENABLED + +/** + * \def MBEDTLS_ECP_NIST_OPTIM + * + * Enable specific 'modulo p' routines for each NIST prime. + * Depending on the prime and architecture, makes operations 4 to 8 times + * faster on the corresponding curve. + * + * Comment this macro to disable NIST curves optimisation. + */ +#define MBEDTLS_ECP_NIST_OPTIM + +/** + * \def MBEDTLS_ECDSA_DETERMINISTIC + * + * Enable deterministic ECDSA (RFC 6979). + * Standard ECDSA is "fragile" in the sense that lack of entropy when signing + * may result in a compromise of the long-term signing key. This is avoided by + * the deterministic variant. + * + * Requires: MBEDTLS_HMAC_DRBG_C + * + * Comment this macro to disable deterministic ECDSA. + */ +//#define MBEDTLS_ECDSA_DETERMINISTIC + +/** + * \def MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + * + * Enable the PSK based ciphersuite modes in SSL / TLS. + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + * + * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_KEY_EXCHANGE_DHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + * + * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + * + * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_RSA_PSK_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + * + * Enable the RSA-only based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + */ +#define MBEDTLS_KEY_EXCHANGE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + * + * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_DHM_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_KEY_EXCHANGE_DHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + * + * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_RSA_C, MBEDTLS_PKCS1_V15, + * MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + * + * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_ECDSA_C, MBEDTLS_X509_CRT_PARSE_C, + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + */ +#define MBEDTLS_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + * + * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +#define MBEDTLS_KEY_EXCHANGE_ECDH_ECDSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + * + * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. + * + * Requires: MBEDTLS_ECDH_C, MBEDTLS_X509_CRT_PARSE_C + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + */ +#define MBEDTLS_KEY_EXCHANGE_ECDH_RSA_ENABLED + +/** + * \def MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + * + * Enable the ECJPAKE based ciphersuite modes in SSL / TLS. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Requires: MBEDTLS_ECJPAKE_C + * MBEDTLS_SHA256_C + * MBEDTLS_ECP_DP_SECP256R1_ENABLED + * + * This enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECJPAKE_WITH_AES_128_CCM_8 + */ +//#define MBEDTLS_KEY_EXCHANGE_ECJPAKE_ENABLED + +/** + * \def MBEDTLS_PK_PARSE_EC_EXTENDED + * + * Enhance support for reading EC keys using variants of SEC1 not allowed by + * RFC 5915 and RFC 5480. + * + * Currently this means parsing the SpecifiedECDomain choice of EC + * parameters (only known groups are supported, not arbitrary domains, to + * avoid validation issues). + * + * Disable if you only need to support RFC 5915 + 5480 key formats. + */ +#define MBEDTLS_PK_PARSE_EC_EXTENDED + +/** + * \def MBEDTLS_ERROR_STRERROR_DUMMY + * + * Enable a dummy error function to make use of mbedtls_strerror() in + * third party libraries easier when MBEDTLS_ERROR_C is disabled + * (no effect when MBEDTLS_ERROR_C is enabled). + * + * You can safely disable this if MBEDTLS_ERROR_C is enabled, or if you're + * not using mbedtls_strerror() or error_strerror() in your application. + * + * Disable if you run into name conflicts and want to really remove the + * mbedtls_strerror() + */ +#define MBEDTLS_ERROR_STRERROR_DUMMY + +/** + * \def MBEDTLS_GENPRIME + * + * Enable the prime-number generation code. + * + * Requires: MBEDTLS_BIGNUM_C + */ +#define MBEDTLS_GENPRIME + +/** + * \def MBEDTLS_FS_IO + * + * Enable functions that use the filesystem. + */ +#define MBEDTLS_FS_IO + +/** + * \def MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + * + * Do not add default entropy sources. These are the platform specific, + * mbedtls_timing_hardclock and HAVEGE based poll functions. + * + * This is useful to have more control over the added entropy sources in an + * application. + * + * Uncomment this macro to prevent loading of default entropy functions. + */ +//#define MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES + +/** + * \def MBEDTLS_NO_PLATFORM_ENTROPY + * + * Do not use built-in platform entropy functions. + * This is useful if your platform does not support + * standards like the /dev/urandom or Windows CryptoAPI. + * + * Uncomment this macro to disable the built-in platform entropy functions. + */ +//#define MBEDTLS_NO_PLATFORM_ENTROPY + +/** + * \def MBEDTLS_ENTROPY_FORCE_SHA256 + * + * Force the entropy accumulator to use a SHA-256 accumulator instead of the + * default SHA-512 based one (if both are available). + * + * Requires: MBEDTLS_SHA256_C + * + * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option + * if you have performance concerns. + * + * This option is only useful if both MBEDTLS_SHA256_C and + * MBEDTLS_SHA512_C are defined. Otherwise the available hash module is used. + */ +//#define MBEDTLS_ENTROPY_FORCE_SHA256 + +/** + * \def MBEDTLS_ENTROPY_NV_SEED + * + * Enable the non-volatile (NV) seed file-based entropy source. + * (Also enables the NV seed read/write functions in the platform layer) + * + * This is crucial (if not required) on systems that do not have a + * cryptographic entropy source (in hardware or kernel) available. + * + * Requires: MBEDTLS_ENTROPY_C, MBEDTLS_PLATFORM_C + * + * \note The read/write functions that are used by the entropy source are + * determined in the platform layer, and can be modified at runtime and/or + * compile-time depending on the flags (MBEDTLS_PLATFORM_NV_SEED_*) used. + * + * \note If you use the default implementation functions that read a seedfile + * with regular fopen(), please make sure you make a seedfile with the + * proper name (defined in MBEDTLS_PLATFORM_STD_NV_SEED_FILE) and at + * least MBEDTLS_ENTROPY_BLOCK_SIZE bytes in size that can be read from + * and written to or you will get an entropy source error! The default + * implementation will only use the first MBEDTLS_ENTROPY_BLOCK_SIZE + * bytes from the file. + * + * \note The entropy collector will write to the seed file before entropy is + * given to an external source, to update it. + */ +//#define MBEDTLS_ENTROPY_NV_SEED + +/** + * \def MBEDTLS_MEMORY_DEBUG + * + * Enable debugging of buffer allocator memory issues. Automatically prints + * (to stderr) all (fatal) messages on memory allocation issues. Enables + * function for 'debug output' of allocated memory. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Uncomment this macro to let the buffer allocator print out error messages. + */ +//#define MBEDTLS_MEMORY_DEBUG + +/** + * \def MBEDTLS_MEMORY_BACKTRACE + * + * Include backtrace information with each allocated block. + * + * Requires: MBEDTLS_MEMORY_BUFFER_ALLOC_C + * GLIBC-compatible backtrace() an backtrace_symbols() support + * + * Uncomment this macro to include backtrace information + */ +//#define MBEDTLS_MEMORY_BACKTRACE + +/** + * \def MBEDTLS_PK_RSA_ALT_SUPPORT + * + * Support external private RSA keys (eg from a HSM) in the PK layer. + * + * Comment this macro to disable support for external private RSA keys. + */ +#define MBEDTLS_PK_RSA_ALT_SUPPORT + +/** + * \def MBEDTLS_PKCS1_V15 + * + * Enable support for PKCS#1 v1.5 encoding. + * + * Requires: MBEDTLS_RSA_C + * + * This enables support for PKCS#1 v1.5 operations. + */ +#define MBEDTLS_PKCS1_V15 + +/** + * \def MBEDTLS_PKCS1_V21 + * + * Enable support for PKCS#1 v2.1 encoding. + * + * Requires: MBEDTLS_MD_C, MBEDTLS_RSA_C + * + * This enables support for RSAES-OAEP and RSASSA-PSS operations. + */ +#define MBEDTLS_PKCS1_V21 + +/** + * \def MBEDTLS_RSA_NO_CRT + * + * Do not use the Chinese Remainder Theorem + * for the RSA private operation. + * + * Uncomment this macro to disable the use of CRT in RSA. + * + */ +//#define MBEDTLS_RSA_NO_CRT + +/** + * \def MBEDTLS_SELF_TEST + * + * Enable the checkup functions (*_self_test). + */ +#define MBEDTLS_SELF_TEST + +/** + * \def MBEDTLS_SHA256_SMALLER + * + * Enable an implementation of SHA-256 that has lower ROM footprint but also + * lower performance. + * + * The default implementation is meant to be a reasonnable compromise between + * performance and size. This version optimizes more aggressively for size at + * the expense of performance. Eg on Cortex-M4 it reduces the size of + * mbedtls_sha256_process() from ~2KB to ~0.5KB for a performance hit of about + * 30%. + * + * Uncomment to enable the smaller implementation of SHA256. + */ +//#define MBEDTLS_SHA256_SMALLER + +/** + * \def MBEDTLS_SSL_ALL_ALERT_MESSAGES + * + * Enable sending of alert messages in case of encountered errors as per RFC. + * If you choose not to send the alert messages, mbed TLS can still communicate + * with other servers, only debugging of failures is harder. + * + * The advantage of not sending alert messages, is that no information is given + * about reasons for failures thus preventing adversaries of gaining intel. + * + * Enable sending of all alert messages + */ +#define MBEDTLS_SSL_ALL_ALERT_MESSAGES + +/** + * \def MBEDTLS_SSL_ASYNC_PRIVATE + * + * Enable asynchronous external private key operations in SSL. This allows + * you to configure an SSL connection to call an external cryptographic + * module to perform private key operations instead of performing the + * operation inside the library. + * + */ +//#define MBEDTLS_SSL_ASYNC_PRIVATE + +/** + * \def MBEDTLS_SSL_DEBUG_ALL + * + * Enable the debug messages in SSL module for all issues. + * Debug messages have been disabled in some places to prevent timing + * attacks due to (unbalanced) debugging function calls. + * + * If you need all error reporting you should enable this during debugging, + * but remove this for production servers that should log as well. + * + * Uncomment this macro to report all debug messages on errors introducing + * a timing side-channel. + * + */ +//#define MBEDTLS_SSL_DEBUG_ALL + +/** \def MBEDTLS_SSL_ENCRYPT_THEN_MAC + * + * Enable support for Encrypt-then-MAC, RFC 7366. + * + * This allows peers that both support it to use a more robust protection for + * ciphersuites using CBC, providing deep resistance against timing attacks + * on the padding or underlying cipher. + * + * This only affects CBC ciphersuites, and is useless if none is defined. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Encrypt-then-MAC + */ +#define MBEDTLS_SSL_ENCRYPT_THEN_MAC + +/** \def MBEDTLS_SSL_EXTENDED_MASTER_SECRET + * + * Enable support for Extended Master Secret, aka Session Hash + * (draft-ietf-tls-session-hash-02). + * + * This was introduced as "the proper fix" to the Triple Handshake familiy of + * attacks, but it is recommended to always use it (even if you disable + * renegotiation), since it actually fixes a more fundamental issue in the + * original SSL/TLS design, and has implications beyond Triple Handshake. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1 or + * MBEDTLS_SSL_PROTO_TLS1_1 or + * MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for Extended Master Secret. + */ +#define MBEDTLS_SSL_EXTENDED_MASTER_SECRET + +/** + * \def MBEDTLS_SSL_FALLBACK_SCSV + * + * Enable support for FALLBACK_SCSV (draft-ietf-tls-downgrade-scsv-00). + * + * For servers, it is recommended to always enable this, unless you support + * only one version of TLS, or know for sure that none of your clients + * implements a fallback strategy. + * + * For clients, you only need this if you're using a fallback strategy, which + * is not recommended in the first place, unless you absolutely need it to + * interoperate with buggy (version-intolerant) servers. + * + * Comment this macro to disable support for FALLBACK_SCSV + */ +#define MBEDTLS_SSL_FALLBACK_SCSV + +/** + * \def MBEDTLS_SSL_HW_RECORD_ACCEL + * + * Enable hooking functions in SSL module for hardware acceleration of + * individual records. + * + * Uncomment this macro to enable hooking functions. + */ +//#define MBEDTLS_SSL_HW_RECORD_ACCEL + +/** + * \def MBEDTLS_SSL_CBC_RECORD_SPLITTING + * + * Enable 1/n-1 record splitting for CBC mode in SSLv3 and TLS 1.0. + * + * This is a countermeasure to the BEAST attack, which also minimizes the risk + * of interoperability issues compared to sending 0-length records. + * + * Comment this macro to disable 1/n-1 record splitting. + */ +#define MBEDTLS_SSL_CBC_RECORD_SPLITTING + +/** + * \def MBEDTLS_SSL_RENEGOTIATION + * + * Disable support for TLS renegotiation. + * + * The two main uses of renegotiation are (1) refresh keys on long-lived + * connections and (2) client authentication after the initial handshake. + * If you don't need renegotiation, it's probably better to disable it, since + * it has been associated with security issues in the past and is easy to + * misuse/misunderstand. + * + * Comment this to disable support for renegotiation. + * + * \note Even if this option is disabled, both client and server are aware + * of the Renegotiation Indication Extension (RFC 5746) used to + * prevent the SSL renegotiation attack (see RFC 5746 Sect. 1). + * (See \c mbedtls_ssl_conf_legacy_renegotiation for the + * configuration of this extension). + * + */ +#define MBEDTLS_SSL_RENEGOTIATION + +/** + * \def MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + * + * Enable support for receiving and parsing SSLv2 Client Hello messages for the + * SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to enable support for SSLv2 Client Hello messages. + */ +//#define MBEDTLS_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO + +/** + * \def MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + * + * Pick the ciphersuite according to the client's preferences rather than ours + * in the SSL Server module (MBEDTLS_SSL_SRV_C). + * + * Uncomment this macro to respect client's ciphersuite order + */ +//#define MBEDTLS_SSL_SRV_RESPECT_CLIENT_PREFERENCE + +/** + * \def MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + * + * Enable support for RFC 6066 max_fragment_length extension in SSL. + * + * Comment this macro to disable support for the max_fragment_length extension + */ +#define MBEDTLS_SSL_MAX_FRAGMENT_LENGTH + +/** + * \def MBEDTLS_SSL_PROTO_SSL3 + * + * Enable support for SSL 3.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for SSL 3.0 + */ +//#define MBEDTLS_SSL_PROTO_SSL3 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1 + * + * Enable support for TLS 1.0. + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.0 + */ +#define MBEDTLS_SSL_PROTO_TLS1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_1 + * + * Enable support for TLS 1.1 (and DTLS 1.0 if DTLS is enabled). + * + * Requires: MBEDTLS_MD5_C + * MBEDTLS_SHA1_C + * + * Comment this macro to disable support for TLS 1.1 / DTLS 1.0 + */ +#define MBEDTLS_SSL_PROTO_TLS1_1 + +/** + * \def MBEDTLS_SSL_PROTO_TLS1_2 + * + * Enable support for TLS 1.2 (and DTLS 1.2 if DTLS is enabled). + * + * Requires: MBEDTLS_SHA1_C or MBEDTLS_SHA256_C or MBEDTLS_SHA512_C + * (Depends on ciphersuites) + * + * Comment this macro to disable support for TLS 1.2 / DTLS 1.2 + */ +#define MBEDTLS_SSL_PROTO_TLS1_2 + +/** + * \def MBEDTLS_SSL_PROTO_DTLS + * + * Enable support for DTLS (all available versions). + * + * Enable this and MBEDTLS_SSL_PROTO_TLS1_1 to enable DTLS 1.0, + * and/or this and MBEDTLS_SSL_PROTO_TLS1_2 to enable DTLS 1.2. + * + * Requires: MBEDTLS_SSL_PROTO_TLS1_1 + * or MBEDTLS_SSL_PROTO_TLS1_2 + * + * Comment this macro to disable support for DTLS + */ +#define MBEDTLS_SSL_PROTO_DTLS + +/** + * \def MBEDTLS_SSL_ALPN + * + * Enable support for RFC 7301 Application Layer Protocol Negotiation. + * + * Comment this macro to disable support for ALPN. + */ +#define MBEDTLS_SSL_ALPN + +/** + * \def MBEDTLS_SSL_DTLS_ANTI_REPLAY + * + * Enable support for the anti-replay mechanism in DTLS. + * + * Requires: MBEDTLS_SSL_TLS_C + * MBEDTLS_SSL_PROTO_DTLS + * + * \warning Disabling this is often a security risk! + * See mbedtls_ssl_conf_dtls_anti_replay() for details. + * + * Comment this to disable anti-replay in DTLS. + */ +//#define MBEDTLS_SSL_DTLS_ANTI_REPLAY + +/** + * \def MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Enable support for HelloVerifyRequest on DTLS servers. + * + * This feature is highly recommended to prevent DTLS servers being used as + * amplifiers in DoS attacks against other hosts. It should always be enabled + * unless you know for sure amplification cannot be a problem in the + * environment in which your server operates. + * + * \warning Disabling this can ba a security risk! (see above) + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + * + * Comment this to disable support for HelloVerifyRequest. + */ +#define MBEDTLS_SSL_DTLS_HELLO_VERIFY + +/** + * \def MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + * + * Enable server-side support for clients that reconnect from the same port. + * + * Some clients unexpectedly close the connection and try to reconnect using the + * same source port. This needs special support from the server to handle the + * new connection securely, as described in section 4.2.8 of RFC 6347. This + * flag enables that support. + * + * Requires: MBEDTLS_SSL_DTLS_HELLO_VERIFY + * + * Comment this to disable support for clients reusing the source port. + */ +#define MBEDTLS_SSL_DTLS_CLIENT_PORT_REUSE + +/** + * \def MBEDTLS_SSL_DTLS_BADMAC_LIMIT + * + * Enable support for a limit of records with bad MAC. + * + * See mbedtls_ssl_conf_dtls_badmac_limit(). + * + * Requires: MBEDTLS_SSL_PROTO_DTLS + */ +//#define MBEDTLS_SSL_DTLS_BADMAC_LIMIT + +/** + * \def MBEDTLS_SSL_SESSION_TICKETS + * + * Enable support for RFC 5077 session tickets in SSL. + * Client-side, provides full support for session tickets (maintainance of a + * session store remains the responsibility of the application, though). + * Server-side, you also need to provide callbacks for writing and parsing + * tickets, including authenticated encryption and key management. Example + * callbacks are provided by MBEDTLS_SSL_TICKET_C. + * + * Comment this macro to disable support for SSL session tickets + */ +#define MBEDTLS_SSL_SESSION_TICKETS + +/** + * \def MBEDTLS_SSL_EXPORT_KEYS + * + * Enable support for exporting key block and master secret. + * This is required for certain users of TLS, e.g. EAP-TLS. + * + * Comment this macro to disable support for key export + */ +#define MBEDTLS_SSL_EXPORT_KEYS + +/** + * \def MBEDTLS_SSL_SERVER_NAME_INDICATION + * + * Enable support for RFC 6066 server name indication (SNI) in SSL. + * + * Requires: MBEDTLS_X509_CRT_PARSE_C + * + * Comment this macro to disable support for server name indication in SSL + */ +#define MBEDTLS_SSL_SERVER_NAME_INDICATION + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC + * + * Enable support for RFC 6066 truncated HMAC in SSL. + * + * Comment this macro to disable support for truncated HMAC in SSL + */ +#define MBEDTLS_SSL_TRUNCATED_HMAC + +/** + * \def MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + * + * Fallback to old (pre-2.7), non-conforming implementation of the truncated + * HMAC extension which also truncates the HMAC key. Note that this option is + * only meant for a transitory upgrade period and is likely to be removed in + * a future version of the library. + * + * \warning The old implementation is non-compliant and has a security weakness + * (2^80 brute force attack on the HMAC key used for a single, + * uninterrupted connection). This should only be enabled temporarily + * when (1) the use of truncated HMAC is essential in order to save + * bandwidth, and (2) the peer is an Mbed TLS stack that doesn't use + * the fixed implementation yet (pre-2.7). + * + * \deprecated This option is deprecated and will likely be removed in a + * future version of Mbed TLS. + * + * Uncomment to fallback to old, non-compliant truncated HMAC implementation. + * + * Requires: MBEDTLS_SSL_TRUNCATED_HMAC + */ +//#define MBEDTLS_SSL_TRUNCATED_HMAC_COMPAT + +/** + * \def MBEDTLS_THREADING_ALT + * + * Provide your own alternate threading implementation. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to allow your own alternate threading implementation. + */ +//#define MBEDTLS_THREADING_ALT + +/** + * \def MBEDTLS_THREADING_PTHREAD + * + * Enable the pthread wrapper layer for the threading layer. + * + * Requires: MBEDTLS_THREADING_C + * + * Uncomment this to enable pthread mutexes. + */ +//#define MBEDTLS_THREADING_PTHREAD + +/** + * \def MBEDTLS_VERSION_FEATURES + * + * Allow run-time checking of compile-time enabled features. Thus allowing users + * to check at run-time if the library is for instance compiled with threading + * support via mbedtls_version_check_feature(). + * + * Requires: MBEDTLS_VERSION_C + * + * Comment this to disable run-time checking and save ROM space + */ +#define MBEDTLS_VERSION_FEATURES + +/** + * \def MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an extension in a v1 or v2 certificate. + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3 + +/** + * \def MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + * + * If set, the X509 parser will not break-off when parsing an X509 certificate + * and encountering an unknown critical extension. + * + * \warning Depending on your PKI use, enabling this can be a security risk! + * + * Uncomment to prevent an error. + */ +//#define MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION + +/** + * \def MBEDTLS_X509_CHECK_KEY_USAGE + * + * Enable verification of the keyUsage extension (CA and leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused + * (intermediate) CA and leaf certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip keyUsage checking for both CA and leaf certificates. + */ +#define MBEDTLS_X509_CHECK_KEY_USAGE + +/** + * \def MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + * + * Enable verification of the extendedKeyUsage extension (leaf certificates). + * + * Disabling this avoids problems with mis-issued and/or misused certificates. + * + * \warning Depending on your PKI use, disabling this can be a security risk! + * + * Comment to skip extendedKeyUsage checking for certificates. + */ +#define MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE + +/** + * \def MBEDTLS_X509_RSASSA_PSS_SUPPORT + * + * Enable parsing and verification of X.509 certificates, CRLs and CSRS + * signed with RSASSA-PSS (aka PKCS#1 v2.1). + * + * Comment this macro to disallow using RSASSA-PSS in certificates. + */ +#define MBEDTLS_X509_RSASSA_PSS_SUPPORT + +/** + * \def MBEDTLS_ZLIB_SUPPORT + * + * If set, the SSL/TLS module uses ZLIB to support compression and + * decompression of packet data. + * + * \warning TLS-level compression MAY REDUCE SECURITY! See for example the + * CRIME attack. Before enabling this option, you should examine with care if + * CRIME or similar exploits may be a applicable to your use case. + * + * \note Currently compression can't be used with DTLS. + * + * \deprecated This feature is deprecated and will be removed + * in the next major revision of the library. + * + * Used in: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This feature requires zlib library and headers to be present. + * + * Uncomment to enable use of ZLIB + */ +//#define MBEDTLS_ZLIB_SUPPORT +/* \} name SECTION: mbed TLS feature support */ + +/** + * \name SECTION: mbed TLS modules + * + * This section enables or disables entire modules in mbed TLS + * \{ + */ + +/** + * \def MBEDTLS_AESNI_C + * + * Enable AES-NI support on x86-64. + * + * Module: library/aesni.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the AES-NI instructions on x86-64 + */ +//#define MBEDTLS_AESNI_C + +/** + * \def MBEDTLS_AES_C + * + * Enable the AES block cipher. + * + * Module: library/aes.c + * Caller: library/cipher.c + * library/pem.c + * library/ctr_drbg.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_AES_128_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_AES_256_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_AES_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_AES_128_CBC_SHA + * + * PEM_PARSE uses AES for decrypting encrypted keys. + */ +#define MBEDTLS_AES_C + +/** + * \def MBEDTLS_ARC4_C + * + * Enable the ARCFOUR stream cipher. + * + * Module: library/arc4.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_SHA + * MBEDTLS_TLS_RSA_WITH_RC4_128_MD5 + * MBEDTLS_TLS_RSA_PSK_WITH_RC4_128_SHA + * MBEDTLS_TLS_PSK_WITH_RC4_128_SHA + * + * \warning ARC4 is considered a weak cipher and its use constitutes a + * security risk. If possible, we recommend avoidng dependencies on + * it, and considering stronger ciphers instead. + * + */ +#define MBEDTLS_ARC4_C + +/** + * \def MBEDTLS_ASN1_PARSE_C + * + * Enable the generic ASN1 parser. + * + * Module: library/asn1.c + * Caller: library/x509.c + * library/dhm.c + * library/pkcs12.c + * library/pkcs5.c + * library/pkparse.c + */ +#define MBEDTLS_ASN1_PARSE_C + +/** + * \def MBEDTLS_ASN1_WRITE_C + * + * Enable the generic ASN1 writer. + * + * Module: library/asn1write.c + * Caller: library/ecdsa.c + * library/pkwrite.c + * library/x509_create.c + * library/x509write_crt.c + * library/x509write_csr.c + */ +#define MBEDTLS_ASN1_WRITE_C + +/** + * \def MBEDTLS_BASE64_C + * + * Enable the Base64 module. + * + * Module: library/base64.c + * Caller: library/pem.c + * + * This module is required for PEM support (required by X.509). + */ +#define MBEDTLS_BASE64_C + +/** + * \def MBEDTLS_BIGNUM_C + * + * Enable the multi-precision integer library. + * + * Module: library/bignum.c + * Caller: library/dhm.c + * library/ecp.c + * library/ecdsa.c + * library/rsa.c + * library/rsa_internal.c + * library/ssl_tls.c + * + * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. + */ +#define MBEDTLS_BIGNUM_C + +/** + * \def MBEDTLS_BLOWFISH_C + * + * Enable the Blowfish block cipher. + * + * Module: library/blowfish.c + */ +#define MBEDTLS_BLOWFISH_C + +/** + * \def MBEDTLS_CAMELLIA_C + * + * Enable the Camellia block cipher. + * + * Module: library/camellia.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_256_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_CAMELLIA_128_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 + */ +#define MBEDTLS_CAMELLIA_C + +/** + * \def MBEDTLS_ARIA_C + * + * Enable the ARIA block cipher. + * + * Module: library/aria.c + * Caller: library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * + * MBEDTLS_TLS_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_ECDSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDHE_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_ECDH_RSA_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_CBC_SHA384 + * MBEDTLS_TLS_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_DHE_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_128_GCM_SHA256 + * MBEDTLS_TLS_RSA_PSK_WITH_ARIA_256_GCM_SHA384 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_128_CBC_SHA256 + * MBEDTLS_TLS_ECDHE_PSK_WITH_ARIA_256_CBC_SHA384 + */ +//#define MBEDTLS_ARIA_C + +/** + * \def MBEDTLS_CCM_C + * + * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. + * + * Module: library/ccm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-CCM ciphersuites, if other requisites are + * enabled as well. + */ +//#define MBEDTLS_CCM_C + +/** + * \def MBEDTLS_CERTS_C + * + * Enable the test certificates. + * + * Module: library/certs.c + * Caller: + * + * This module is used for testing (ssl_client/server). + */ +#define MBEDTLS_CERTS_C + +/** + * \def MBEDTLS_CHACHA20_C + * + * Enable the ChaCha20 stream cipher. + * + * Module: library/chacha20.c + */ +//#define MBEDTLS_CHACHA20_C + +/** + * \def MBEDTLS_CHACHAPOLY_C + * + * Enable the ChaCha20-Poly1305 AEAD algorithm. + * + * Module: library/chachapoly.c + * + * This module requires: MBEDTLS_CHACHA20_C, MBEDTLS_POLY1305_C + */ +//#define MBEDTLS_CHACHAPOLY_C + +/** + * \def MBEDTLS_CIPHER_C + * + * Enable the generic cipher layer. + * + * Module: library/cipher.c + * Caller: library/ssl_tls.c + * + * Uncomment to enable generic cipher wrappers. + */ +#define MBEDTLS_CIPHER_C + +/** + * \def MBEDTLS_CMAC_C + * + * Enable the CMAC (Cipher-based Message Authentication Code) mode for block + * ciphers. + * + * Module: library/cmac.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_DES_C + * + */ +#define MBEDTLS_CMAC_C + +/** + * \def MBEDTLS_CTR_DRBG_C + * + * Enable the CTR_DRBG AES-256-based random generator. + * + * Module: library/ctr_drbg.c + * Caller: + * + * Requires: MBEDTLS_AES_C + * + * This module provides the CTR_DRBG AES-256 random number generator. + */ +#define MBEDTLS_CTR_DRBG_C + +/** + * \def MBEDTLS_DEBUG_C + * + * Enable the debug functions. + * + * Module: library/debug.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module provides debugging functions. + */ +#define MBEDTLS_DEBUG_C + +/** + * \def MBEDTLS_DES_C + * + * Enable the DES block cipher. + * + * Module: library/des.c + * Caller: library/pem.c + * library/cipher.c + * + * This module enables the following ciphersuites (if other requisites are + * enabled as well): + * MBEDTLS_TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA + * MBEDTLS_TLS_PSK_WITH_3DES_EDE_CBC_SHA + * + * PEM_PARSE uses DES/3DES for decrypting encrypted keys. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers instead. + */ +#define MBEDTLS_DES_C + +/** + * \def MBEDTLS_DHM_C + * + * Enable the Diffie-Hellman-Merkle module. + * + * Module: library/dhm.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * DHE-RSA, DHE-PSK + * + * \warning Using DHE constitutes a security risk as it + * is not possible to validate custom DH parameters. + * If possible, it is recommended users should consider + * preferring other methods of key exchange. + * See dhm.h for more details. + * + */ +//#define MBEDTLS_DHM_C + +/** + * \def MBEDTLS_ECDH_C + * + * Enable the elliptic curve Diffie-Hellman library. + * + * Module: library/ecdh.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK + * + * Requires: MBEDTLS_ECP_C + */ +#define MBEDTLS_ECDH_C + +/** + * \def MBEDTLS_ECDSA_C + * + * Enable the elliptic curve DSA library. + * + * Module: library/ecdsa.c + * Caller: + * + * This module is used by the following key exchanges: + * ECDHE-ECDSA + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_ASN1_WRITE_C, MBEDTLS_ASN1_PARSE_C + */ +#define MBEDTLS_ECDSA_C + +/** + * \def MBEDTLS_ECJPAKE_C + * + * Enable the elliptic curve J-PAKE library. + * + * \warning This is currently experimental. EC J-PAKE support is based on the + * Thread v1.0.0 specification; incompatible changes to the specification + * might still happen. For this reason, this is disabled by default. + * + * Module: library/ecjpake.c + * Caller: + * + * This module is used by the following key exchanges: + * ECJPAKE + * + * Requires: MBEDTLS_ECP_C, MBEDTLS_MD_C + */ +//#define MBEDTLS_ECJPAKE_C + +/** + * \def MBEDTLS_ECP_C + * + * Enable the elliptic curve over GF(p) library. + * + * Module: library/ecp.c + * Caller: library/ecdh.c + * library/ecdsa.c + * library/ecjpake.c + * + * Requires: MBEDTLS_BIGNUM_C and at least one MBEDTLS_ECP_DP_XXX_ENABLED + */ +#define MBEDTLS_ECP_C + +/** + * \def MBEDTLS_ENTROPY_C + * + * Enable the platform-specific entropy code. + * + * Module: library/entropy.c + * Caller: + * + * Requires: MBEDTLS_SHA512_C or MBEDTLS_SHA256_C + * + * This module provides a generic entropy pool + */ +#define MBEDTLS_ENTROPY_C + +/** + * \def MBEDTLS_ERROR_C + * + * Enable error code to error string conversion. + * + * Module: library/error.c + * Caller: + * + * This module enables mbedtls_strerror(). + */ +#define MBEDTLS_ERROR_C + +/** + * \def MBEDTLS_GCM_C + * + * Enable the Galois/Counter Mode (GCM) for AES. + * + * Module: library/gcm.c + * + * Requires: MBEDTLS_AES_C or MBEDTLS_CAMELLIA_C + * + * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other + * requisites are enabled as well. + */ +//#define MBEDTLS_GCM_C + +/** + * \def MBEDTLS_HAVEGE_C + * + * Enable the HAVEGE random generator. + * + * Warning: the HAVEGE random generator is not suitable for virtualized + * environments + * + * Warning: the HAVEGE random generator is dependent on timing and specific + * processor traits. It is therefore not advised to use HAVEGE as + * your applications primary random generator or primary entropy pool + * input. As a secondary input to your entropy pool, it IS able add + * the (limited) extra entropy it provides. + * + * Module: library/havege.c + * Caller: + * + * Requires: MBEDTLS_TIMING_C + * + * Uncomment to enable the HAVEGE random generator. + */ +//#define MBEDTLS_HAVEGE_C + +/** + * \def MBEDTLS_HKDF_C + * + * Enable the HKDF algorithm (RFC 5869). + * + * Module: library/hkdf.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the Hashed Message Authentication Code + * (HMAC)-based key derivation function (HKDF). + */ +//#define MBEDTLS_HKDF_C + +/** + * \def MBEDTLS_HMAC_DRBG_C + * + * Enable the HMAC_DRBG random generator. + * + * Module: library/hmac_drbg.c + * Caller: + * + * Requires: MBEDTLS_MD_C + * + * Uncomment to enable the HMAC_DRBG random number geerator. + */ +//#define MBEDTLS_HMAC_DRBG_C + +/** + * \def MBEDTLS_NIST_KW_C + * + * Enable the Key Wrapping mode for 128-bit block ciphers, + * as defined in NIST SP 800-38F. Only KW and KWP modes + * are supported. At the moment, only AES is approved by NIST. + * + * Module: library/nist_kw.c + * + * Requires: MBEDTLS_AES_C and MBEDTLS_CIPHER_C + */ +//#define MBEDTLS_NIST_KW_C + +/** + * \def MBEDTLS_MD_C + * + * Enable the generic message digest layer. + * + * Module: library/md.c + * Caller: + * + * Uncomment to enable generic message digest wrappers. + */ +#define MBEDTLS_MD_C + +/** + * \def MBEDTLS_MD2_C + * + * Enable the MD2 hash algorithm. + * + * Module: library/md2.c + * Caller: + * + * Uncomment to enable support for (rare) MD2-signed X.509 certs. + * + * \warning MD2 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD2_C + +/** + * \def MBEDTLS_MD4_C + * + * Enable the MD4 hash algorithm. + * + * Module: library/md4.c + * Caller: + * + * Uncomment to enable support for (rare) MD4-signed X.509 certs. + * + * \warning MD4 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +//#define MBEDTLS_MD4_C + +/** + * \def MBEDTLS_MD5_C + * + * Enable the MD5 hash algorithm. + * + * Module: library/md5.c + * Caller: library/md.c + * library/pem.c + * library/ssl_tls.c + * + * This module is required for SSL/TLS up to version 1.1, and for TLS 1.2 + * depending on the handshake parameters. Further, it is used for checking + * MD5-signed certificates, and for PBKDF1 when decrypting PEM-encoded + * encrypted keys. + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. If possible, we recommend avoiding dependencies on + * it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_MD5_C + +/** + * \def MBEDTLS_MEMORY_BUFFER_ALLOC_C + * + * Enable the buffer allocator implementation that makes use of a (stack) + * based buffer to 'allocate' dynamic memory. (replaces calloc() and free() + * calls) + * + * Module: library/memory_buffer_alloc.c + * + * Requires: MBEDTLS_PLATFORM_C + * MBEDTLS_PLATFORM_MEMORY (to use it within mbed TLS) + * + * Enable this module to enable the buffer memory allocator. + */ +//#define MBEDTLS_MEMORY_BUFFER_ALLOC_C + +/** + * \def MBEDTLS_NET_C + * + * Enable the TCP and UDP over IPv6/IPv4 networking routines. + * + * \note This module only works on POSIX/Unix (including Linux, BSD and OS X) + * and Windows. For other platforms, you'll want to disable it, and write your + * own networking callbacks to be passed to \c mbedtls_ssl_set_bio(). + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/net_sockets.c + * + * This module provides networking routines. + */ +//#define MBEDTLS_NET_C + +/** + * \def MBEDTLS_OID_C + * + * Enable the OID database. + * + * Module: library/oid.c + * Caller: library/asn1write.c + * library/pkcs5.c + * library/pkparse.c + * library/pkwrite.c + * library/rsa.c + * library/x509.c + * library/x509_create.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * This modules translates between OIDs and internal values. + */ +#define MBEDTLS_OID_C + +/** + * \def MBEDTLS_PADLOCK_C + * + * Enable VIA Padlock support on x86. + * + * Module: library/padlock.c + * Caller: library/aes.c + * + * Requires: MBEDTLS_HAVE_ASM + * + * This modules adds support for the VIA PadLock on x86. + */ +//#define MBEDTLS_PADLOCK_C + +/** + * \def MBEDTLS_PEM_PARSE_C + * + * Enable PEM decoding / parsing. + * + * Module: library/pem.c + * Caller: library/dhm.c + * library/pkparse.c + * library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for decoding / parsing PEM files. + */ +#define MBEDTLS_PEM_PARSE_C + +/** + * \def MBEDTLS_PEM_WRITE_C + * + * Enable PEM encoding / writing. + * + * Module: library/pem.c + * Caller: library/pkwrite.c + * library/x509write_crt.c + * library/x509write_csr.c + * + * Requires: MBEDTLS_BASE64_C + * + * This modules adds support for encoding / writing PEM files. + */ +#define MBEDTLS_PEM_WRITE_C + +/** + * \def MBEDTLS_PK_C + * + * Enable the generic public (asymetric) key layer. + * + * Module: library/pk.c + * Caller: library/ssl_tls.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_RSA_C or MBEDTLS_ECP_C + * + * Uncomment to enable generic public key wrappers. + */ +#define MBEDTLS_PK_C + +/** + * \def MBEDTLS_PK_PARSE_C + * + * Enable the generic public (asymetric) key parser. + * + * Module: library/pkparse.c + * Caller: library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key parse functions. + */ +#define MBEDTLS_PK_PARSE_C + +/** + * \def MBEDTLS_PK_WRITE_C + * + * Enable the generic public (asymetric) key writer. + * + * Module: library/pkwrite.c + * Caller: library/x509write.c + * + * Requires: MBEDTLS_PK_C + * + * Uncomment to enable generic public key write functions. + */ +#define MBEDTLS_PK_WRITE_C + +/** + * \def MBEDTLS_PKCS5_C + * + * Enable PKCS#5 functions. + * + * Module: library/pkcs5.c + * + * Requires: MBEDTLS_MD_C + * + * This module adds support for the PKCS#5 functions. + */ +#define MBEDTLS_PKCS5_C + +/** + * \def MBEDTLS_PKCS11_C + * + * Enable wrapper for PKCS#11 smartcard support. + * + * Module: library/pkcs11.c + * Caller: library/pk.c + * + * Requires: MBEDTLS_PK_C + * + * This module enables SSL/TLS PKCS #11 smartcard support. + * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) + */ +//#define MBEDTLS_PKCS11_C + +/** + * \def MBEDTLS_PKCS12_C + * + * Enable PKCS#12 PBE functions. + * Adds algorithms for parsing PKCS#8 encrypted private keys + * + * Module: library/pkcs12.c + * Caller: library/pkparse.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * Can use: MBEDTLS_ARC4_C + * + * This module enables PKCS#12 functions. + */ +#define MBEDTLS_PKCS12_C + +/** + * \def MBEDTLS_PLATFORM_C + * + * Enable the platform abstraction layer that allows you to re-assign + * functions like calloc(), free(), snprintf(), printf(), fprintf(), exit(). + * + * Enabling MBEDTLS_PLATFORM_C enables to use of MBEDTLS_PLATFORM_XXX_ALT + * or MBEDTLS_PLATFORM_XXX_MACRO directives, allowing the functions mentioned + * above to be specified at runtime or compile time respectively. + * + * \note This abstraction layer must be enabled on Windows (including MSYS2) + * as other module rely on it for a fixed snprintf implementation. + * + * Module: library/platform.c + * Caller: Most other .c files + * + * This module enables abstraction of common (libc) functions. + */ +#define MBEDTLS_PLATFORM_C + +/** + * \def MBEDTLS_POLY1305_C + * + * Enable the Poly1305 MAC algorithm. + * + * Module: library/poly1305.c + * Caller: library/chachapoly.c + */ +//#define MBEDTLS_POLY1305_C + +/** + * \def MBEDTLS_RIPEMD160_C + * + * Enable the RIPEMD-160 hash algorithm. + * + * Module: library/ripemd160.c + * Caller: library/md.c + * + */ +//#define MBEDTLS_RIPEMD160_C + +/** + * \def MBEDTLS_RSA_C + * + * Enable the RSA public-key cryptosystem. + * + * Module: library/rsa.c + * library/rsa_internal.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509.c + * + * This module is used by the following key exchanges: + * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C + */ +#define MBEDTLS_RSA_C + +/** + * \def MBEDTLS_SHA1_C + * + * Enable the SHA1 cryptographic hash algorithm. + * + * Module: library/sha1.c + * Caller: library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * library/x509write_crt.c + * + * This module is required for SSL/TLS up to version 1.1, for TLS 1.2 + * depending on the handshake parameters, and for SHA1-signed certificates. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_SHA1_C + +/** + * \def MBEDTLS_SHA256_C + * + * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. + * + * Module: library/sha256.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * This module adds support for SHA-224 and SHA-256. + * This module is required for the SSL/TLS 1.2 PRF function. + */ +#define MBEDTLS_SHA256_C + +/** + * \def MBEDTLS_SHA512_C + * + * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. + * + * Module: library/sha512.c + * Caller: library/entropy.c + * library/md.c + * library/ssl_cli.c + * library/ssl_srv.c + * + * This module adds support for SHA-384 and SHA-512. + */ +#define MBEDTLS_SHA512_C + +/** + * \def MBEDTLS_SSL_CACHE_C + * + * Enable simple SSL cache implementation. + * + * Module: library/ssl_cache.c + * Caller: + * + * Requires: MBEDTLS_SSL_CACHE_C + */ +#define MBEDTLS_SSL_CACHE_C + +/** + * \def MBEDTLS_SSL_COOKIE_C + * + * Enable basic implementation of DTLS cookies for hello verification. + * + * Module: library/ssl_cookie.c + * Caller: + */ +#define MBEDTLS_SSL_COOKIE_C + +/** + * \def MBEDTLS_SSL_TICKET_C + * + * Enable an implementation of TLS server-side callbacks for session tickets. + * + * Module: library/ssl_ticket.c + * Caller: + * + * Requires: MBEDTLS_CIPHER_C + */ +#define MBEDTLS_SSL_TICKET_C + +/** + * \def MBEDTLS_SSL_CLI_C + * + * Enable the SSL/TLS client code. + * + * Module: library/ssl_cli.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS client support. + */ +//#define MBEDTLS_SSL_CLI_C + +/** + * \def MBEDTLS_SSL_SRV_C + * + * Enable the SSL/TLS server code. + * + * Module: library/ssl_srv.c + * Caller: + * + * Requires: MBEDTLS_SSL_TLS_C + * + * This module is required for SSL/TLS server support. + */ +//#define MBEDTLS_SSL_SRV_C + +/** + * \def MBEDTLS_SSL_TLS_C + * + * Enable the generic SSL/TLS code. + * + * Module: library/ssl_tls.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * + * Requires: MBEDTLS_CIPHER_C, MBEDTLS_MD_C + * and at least one of the MBEDTLS_SSL_PROTO_XXX defines + * + * This module is required for SSL/TLS. + */ +//#define MBEDTLS_SSL_TLS_C + +/** + * \def MBEDTLS_THREADING_C + * + * Enable the threading abstraction layer. + * By default mbed TLS assumes it is used in a non-threaded environment or that + * contexts are not shared between threads. If you do intend to use contexts + * between threads, you will need to enable this layer to prevent race + * conditions. See also our Knowledge Base article about threading: + * https://tls.mbed.org/kb/development/thread-safety-and-multi-threading + * + * Module: library/threading.c + * + * This allows different threading implementations (self-implemented or + * provided). + * + * You will have to enable either MBEDTLS_THREADING_ALT or + * MBEDTLS_THREADING_PTHREAD. + * + * Enable this layer to allow use of mutexes within mbed TLS + */ +//#define MBEDTLS_THREADING_C + +/** + * \def MBEDTLS_TIMING_C + * + * Enable the semi-portable timing interface. + * + * \note The provided implementation only works on POSIX/Unix (including Linux, + * BSD and OS X) and Windows. On other platforms, you can either disable that + * module and provide your own implementations of the callbacks needed by + * \c mbedtls_ssl_set_timer_cb() for DTLS, or leave it enabled and provide + * your own implementation of the whole module by setting + * \c MBEDTLS_TIMING_ALT in the current file. + * + * \note See also our Knowledge Base article about porting to a new + * environment: + * https://tls.mbed.org/kb/how-to/how-do-i-port-mbed-tls-to-a-new-environment-OS + * + * Module: library/timing.c + * Caller: library/havege.c + * + * This module is used by the HAVEGE random number generator. + */ +#define MBEDTLS_TIMING_C + +/** + * \def MBEDTLS_VERSION_C + * + * Enable run-time version information. + * + * Module: library/version.c + * + * This module provides run-time version information. + */ +#define MBEDTLS_VERSION_C + +/** + * \def MBEDTLS_X509_USE_C + * + * Enable X.509 core for using certificates. + * + * Module: library/x509.c + * Caller: library/x509_crl.c + * library/x509_crt.c + * library/x509_csr.c + * + * Requires: MBEDTLS_ASN1_PARSE_C, MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, + * MBEDTLS_PK_PARSE_C + * + * This module is required for the X.509 parsing modules. + */ +#define MBEDTLS_X509_USE_C + +/** + * \def MBEDTLS_X509_CRT_PARSE_C + * + * Enable X.509 certificate parsing. + * + * Module: library/x509_crt.c + * Caller: library/ssl_cli.c + * library/ssl_srv.c + * library/ssl_tls.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 certificate parsing. + */ +#define MBEDTLS_X509_CRT_PARSE_C + +/** + * \def MBEDTLS_X509_CRL_PARSE_C + * + * Enable X.509 CRL parsing. + * + * Module: library/x509_crl.c + * Caller: library/x509_crt.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is required for X.509 CRL parsing. + */ +#define MBEDTLS_X509_CRL_PARSE_C + +/** + * \def MBEDTLS_X509_CSR_PARSE_C + * + * Enable X.509 Certificate Signing Request (CSR) parsing. + * + * Module: library/x509_csr.c + * Caller: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_USE_C + * + * This module is used for reading X.509 certificate request. + */ +#define MBEDTLS_X509_CSR_PARSE_C + +/** + * \def MBEDTLS_X509_CREATE_C + * + * Enable X.509 core for creating certificates. + * + * Module: library/x509_create.c + * + * Requires: MBEDTLS_BIGNUM_C, MBEDTLS_OID_C, MBEDTLS_PK_WRITE_C + * + * This module is the basis for creating X.509 certificates and CSRs. + */ +#define MBEDTLS_X509_CREATE_C + +/** + * \def MBEDTLS_X509_CRT_WRITE_C + * + * Enable creating X.509 certificates. + * + * Module: library/x509_crt_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate creation. + */ +#define MBEDTLS_X509_CRT_WRITE_C + +/** + * \def MBEDTLS_X509_CSR_WRITE_C + * + * Enable creating X.509 Certificate Signing Requests (CSR). + * + * Module: library/x509_csr_write.c + * + * Requires: MBEDTLS_X509_CREATE_C + * + * This module is required for X.509 certificate request writing. + */ +#define MBEDTLS_X509_CSR_WRITE_C + +/** + * \def MBEDTLS_XTEA_C + * + * Enable the XTEA block cipher. + * + * Module: library/xtea.c + * Caller: + */ +//#define MBEDTLS_XTEA_C + +/* \} name SECTION: mbed TLS modules */ + +/** + * \name SECTION: Module configuration options + * + * This section allows for the setting of module specific sizes and + * configuration options. The default values are already present in the + * relevant header files and should suffice for the regular use cases. + * + * Our advice is to enable options and change their values here + * only if you have a good reason and know the consequences. + * + * Please check the respective header file for documentation on these + * parameters (to prevent duplicate documentation). + * \{ + */ + +/* MPI / BIGNUM options */ +//#define MBEDTLS_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ +//#define MBEDTLS_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ + +/* CTR_DRBG options */ +//#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ +//#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* HMAC_DRBG options */ +//#define MBEDTLS_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ +//#define MBEDTLS_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ +//#define MBEDTLS_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ +//#define MBEDTLS_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ + +/* ECP options */ +//#define MBEDTLS_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ +//#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ +//#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ + +/* Entropy options */ +//#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +//#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +//#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Default minimum number of bytes required for the hardware entropy source mbedtls_hardware_poll() before entropy is released */ + +/* Memory buffer allocator options */ +//#define MBEDTLS_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ + +/* Platform options */ +//#define MBEDTLS_PLATFORM_STD_MEM_HDR /**< Header to include if MBEDTLS_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ +//#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< Default allocator to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT exit /**< Default exit to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_TIME time /**< Default time to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ +/* Note: your snprintf must correclty zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< Default snprintf to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS 0 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE 1 /**< Default exit value to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" /**< Seed file to read/write with default implementation */ + +/* To Use Function Macros MBEDTLS_PLATFORM_C must be enabled */ +/* MBEDTLS_PLATFORM_XXX_MACRO and MBEDTLS_PLATFORM_XXX_ALT cannot both be defined */ +//#define MBEDTLS_PLATFORM_CALLOC_MACRO calloc /**< Default allocator macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_FREE_MACRO free /**< Default free macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_EXIT_MACRO exit /**< Default exit macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_TIME_MACRO time /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_TIME_TYPE_MACRO time_t /**< Default time macro to use, can be undefined. MBEDTLS_HAVE_TIME must be enabled */ +//#define MBEDTLS_PLATFORM_FPRINTF_MACRO fprintf /**< Default fprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_PRINTF_MACRO printf /**< Default printf macro to use, can be undefined */ +/* Note: your snprintf must correclty zero-terminate the buffer! */ +//#define MBEDTLS_PLATFORM_SNPRINTF_MACRO snprintf /**< Default snprintf macro to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_READ_MACRO mbedtls_platform_std_nv_seed_read /**< Default nv_seed_read function to use, can be undefined */ +//#define MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO mbedtls_platform_std_nv_seed_write /**< Default nv_seed_write function to use, can be undefined */ + +/* SSL Cache options */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ +//#define MBEDTLS_SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ + +/* SSL options */ + +/** \def MBEDTLS_SSL_MAX_CONTENT_LEN + * + * Maximum fragment length in bytes. + * + * Determines the size of both the incoming and outgoing TLS I/O buffers. + * + * Uncommenting MBEDTLS_SSL_IN_CONTENT_LEN and/or MBEDTLS_SSL_OUT_CONTENT_LEN + * will override this length by setting maximum incoming and/or outgoing + * fragment length, respectively. + */ +//#define MBEDTLS_SSL_MAX_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_IN_CONTENT_LEN + * + * Maximum incoming fragment length in bytes. + * + * Uncomment to set the size of the inward TLS buffer independently of the + * outward buffer. + */ +//#define MBEDTLS_SSL_IN_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_OUT_CONTENT_LEN + * + * Maximum outgoing fragment length in bytes. + * + * Uncomment to set the size of the outward TLS buffer independently of the + * inward buffer. + * + * It is possible to save RAM by setting a smaller outward buffer, while keeping + * the default inward 16384 byte buffer to conform to the TLS specification. + * + * The minimum required outward buffer size is determined by the handshake + * protocol's usage. Handshaking will fail if the outward buffer is too small. + * The specific size requirement depends on the configured ciphers and any + * certificate data which is sent during the handshake. + * + * For absolute minimum RAM usage, it's best to enable + * MBEDTLS_SSL_MAX_FRAGMENT_LENGTH and reduce MBEDTLS_SSL_MAX_CONTENT_LEN. This + * reduces both incoming and outgoing buffer sizes. However this is only + * guaranteed if the other end of the connection also supports the TLS + * max_fragment_len extension. Otherwise the connection may fail. + */ +//#define MBEDTLS_SSL_OUT_CONTENT_LEN 16384 + +/** \def MBEDTLS_SSL_DTLS_MAX_BUFFERING + * + * Maximum number of heap-allocated bytes for the purpose of + * DTLS handshake message reassembly and future message buffering. + * + * This should be at least 9/8 * MBEDTLSSL_IN_CONTENT_LEN + * to account for a reassembled handshake message of maximum size, + * together with its reassembly bitmap. + * + * A value of 2 * MBEDTLS_SSL_IN_CONTENT_LEN (32768 by default) + * should be sufficient for all practical situations as it allows + * to reassembly a large handshake message (such as a certificate) + * while buffering multiple smaller handshake messages. + * + */ +//#define MBEDTLS_SSL_DTLS_MAX_BUFFERING 32768 + +//#define MBEDTLS_SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ +//#define MBEDTLS_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ +//#define MBEDTLS_SSL_COOKIE_TIMEOUT 60 /**< Default expiration delay of DTLS cookies, in seconds if HAVE_TIME, or in number of cookies issued */ + +/** + * Complete list of ciphersuites to use, in order of preference. + * + * \warning No dependency checking is done on that field! This option can only + * be used to restrict the set of available ciphersuites. It is your + * responsibility to make sure the needed modules are active. + * + * Use this to save a few hundred bytes of ROM (default ordering of all + * available ciphersuites) and a few to a few hundred bytes of RAM. + * + * The value below is only an example, not the default. + */ +//#define MBEDTLS_SSL_CIPHERSUITES MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,MBEDTLS_TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 + +/* X509 options */ +//#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 /**< Maximum number of intermediate CAs in a verification chain. */ +//#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 /**< Maximum length of a path/filename string in bytes including the null terminator character ('\0'). */ + +/** + * Allow SHA-1 in the default TLS configuration for certificate signing. + * Without this build-time option, SHA-1 support must be activated explicitly + * through mbedtls_ssl_conf_cert_profile. Turning on this option is not + * recommended because of it is possible to generate SHA-1 collisions, however + * this may be safe for legacy infrastructure where additional controls apply. + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +// #define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES + +/** + * Allow SHA-1 in the default TLS configuration for TLS 1.2 handshake + * signature and ciphersuite selection. Without this build-time option, SHA-1 + * support must be activated explicitly through mbedtls_ssl_conf_sig_hashes. + * The use of SHA-1 in TLS <= 1.1 and in HMAC-SHA-1 is always allowed by + * default. At the time of writing, there is no practical attack on the use + * of SHA-1 in handshake signatures, hence this option is turned on by default + * to preserve compatibility with existing peers, but the general + * warning applies nonetheless: + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. If possible, we recommend avoiding dependencies + * on it, and considering stronger message digests instead. + * + */ +#define MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_KEY_EXCHANGE + +/** + * Uncomment the macro to let mbed TLS use your alternate implementation of + * mbedtls_platform_zeroize(). This replaces the default implementation in + * platform_util.c. + * + * mbedtls_platform_zeroize() is a widely used function across the library to + * zero a block of memory. The implementation is expected to be secure in the + * sense that it has been written to prevent the compiler from removing calls + * to mbedtls_platform_zeroize() as part of redundant code elimination + * optimizations. However, it is difficult to guarantee that calls to + * mbedtls_platform_zeroize() will not be optimized by the compiler as older + * versions of the C language standards do not provide a secure implementation + * of memset(). Therefore, MBEDTLS_PLATFORM_ZEROIZE_ALT enables users to + * configure their own implementation of mbedtls_platform_zeroize(), for + * example by using directives specific to their compiler, features from newer + * C standards (e.g using memset_s() in C11) or calling a secure memset() from + * their system (e.g explicit_bzero() in BSD). + */ +//#define MBEDTLS_PLATFORM_ZEROIZE_ALT + +/* \} name SECTION: Customisation configuration options */ + +/* Target and application specific configurations */ +//#define YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE "target_config.h" + +#if defined(TARGET_LIKE_MBED) && defined(YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE) +#include YOTTA_CFG_MBEDTLS_TARGET_CONFIG_FILE +#endif + +/* + * Allow user to override any previous default. + * + * Use two macro names for that, as: + * - with yotta the prefix YOTTA_CFG_ is forced + * - without yotta is looks weird to have a YOTTA prefix. + */ +#if defined(YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE) +#include YOTTA_CFG_MBEDTLS_USER_CONFIG_FILE +#elif defined(MBEDTLS_USER_CONFIG_FILE) +#include MBEDTLS_USER_CONFIG_FILE +#endif + +#include "check_config.h" + +#endif /* MBEDTLS_CONFIG_H */ diff --git a/common/mbedtls/ctr_drbg.c b/common/mbedtls/ctr_drbg.c new file mode 100644 index 000000000..ebbba1a7d --- /dev/null +++ b/common/mbedtls/ctr_drbg.c @@ -0,0 +1,652 @@ +/* + * CTR_DRBG implementation based on AES-256 (NIST SP 800-90) + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The NIST SP 800-90 DRBGs are described in the following publication. + * + * http://csrc.nist.gov/publications/nistpubs/800-90/SP800-90revised_March2007.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) + +#include "mbedtls/ctr_drbg.h" +#include "mbedtls/platform_util.h" + +#include + +#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_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +/* + * CTR_DRBG context initialization + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_ctr_drbg_context ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * Non-public function wrapped by mbedtls_ctr_drbg_seed(). Necessary to allow + * NIST tests to succeed (which require known length fixed entropy) + */ +int mbedtls_ctr_drbg_seed_entropy_len( + mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len, + size_t entropy_len ) +{ + int ret; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + + memset( key, 0, MBEDTLS_CTR_DRBG_KEYSIZE ); + + mbedtls_aes_init( &ctx->aes_ctx ); + + ctx->f_entropy = f_entropy; + ctx->p_entropy = p_entropy; + + ctx->entropy_len = entropy_len; + ctx->reseed_interval = MBEDTLS_CTR_DRBG_RESEED_INTERVAL; + + /* + * Initialize with an empty key + */ + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_ctr_drbg_reseed( ctx, custom, len ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ) +{ + return( mbedtls_ctr_drbg_seed_entropy_len( ctx, f_entropy, p_entropy, custom, len, + MBEDTLS_CTR_DRBG_ENTROPY_LEN ) ); +} + +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ) +{ + if( ctx == NULL ) + return; + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif + mbedtls_aes_free( &ctx->aes_ctx ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_ctr_drbg_context ) ); +} + +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, int resistance ) +{ + ctx->prediction_resistance = resistance; +} + +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, size_t len ) +{ + ctx->entropy_len = len; +} + +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, int interval ) +{ + ctx->reseed_interval = interval; +} + +static int block_cipher_df( unsigned char *output, + const unsigned char *data, size_t data_len ) +{ + unsigned char buf[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16]; + unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char key[MBEDTLS_CTR_DRBG_KEYSIZE]; + unsigned char chain[MBEDTLS_CTR_DRBG_BLOCKSIZE]; + unsigned char *p, *iv; + mbedtls_aes_context aes_ctx; + int ret = 0; + + int i, j; + size_t buf_len, use_len; + + if( data_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( buf, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT + MBEDTLS_CTR_DRBG_BLOCKSIZE + 16 ); + mbedtls_aes_init( &aes_ctx ); + + /* + * Construct IV (16 bytes) and S in buffer + * IV = Counter (in 32-bits) padded to 16 with zeroes + * S = Length input string (in 32-bits) || Length of output (in 32-bits) || + * data || 0x80 + * (Total is padded to a multiple of 16-bytes with zeroes) + */ + p = buf + MBEDTLS_CTR_DRBG_BLOCKSIZE; + *p++ = ( data_len >> 24 ) & 0xff; + *p++ = ( data_len >> 16 ) & 0xff; + *p++ = ( data_len >> 8 ) & 0xff; + *p++ = ( data_len ) & 0xff; + p += 3; + *p++ = MBEDTLS_CTR_DRBG_SEEDLEN; + memcpy( p, data, data_len ); + p[data_len] = 0x80; + + buf_len = MBEDTLS_CTR_DRBG_BLOCKSIZE + 8 + data_len + 1; + + for( i = 0; i < MBEDTLS_CTR_DRBG_KEYSIZE; i++ ) + key[i] = i; + + if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, key, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + + /* + * Reduce data to MBEDTLS_CTR_DRBG_SEEDLEN bytes of data + */ + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + p = buf; + memset( chain, 0, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + use_len = buf_len; + + while( use_len > 0 ) + { + for( i = 0; i < MBEDTLS_CTR_DRBG_BLOCKSIZE; i++ ) + chain[i] ^= p[i]; + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + use_len -= ( use_len >= MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? + MBEDTLS_CTR_DRBG_BLOCKSIZE : use_len; + + if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, chain, chain ) ) != 0 ) + { + goto exit; + } + } + + memcpy( tmp + j, chain, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + + /* + * Update IV + */ + buf[3]++; + } + + /* + * Do final encryption with reduced data + */ + if( ( ret = mbedtls_aes_setkey_enc( &aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + goto exit; + } + iv = tmp + MBEDTLS_CTR_DRBG_KEYSIZE; + p = output; + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + if( ( ret = mbedtls_aes_crypt_ecb( &aes_ctx, MBEDTLS_AES_ENCRYPT, iv, iv ) ) != 0 ) + { + goto exit; + } + memcpy( p, iv, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } +exit: + mbedtls_aes_free( &aes_ctx ); + /* + * tidy up the stack + */ + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( chain, sizeof( chain ) ); + if( 0 != ret ) + { + /* + * wipe partial seed from memory + */ + mbedtls_platform_zeroize( output, MBEDTLS_CTR_DRBG_SEEDLEN ); + } + + return( ret ); +} + +static int ctr_drbg_update_internal( mbedtls_ctr_drbg_context *ctx, + const unsigned char data[MBEDTLS_CTR_DRBG_SEEDLEN] ) +{ + unsigned char tmp[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char *p = tmp; + int i, j; + int ret = 0; + + memset( tmp, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); + + for( j = 0; j < MBEDTLS_CTR_DRBG_SEEDLEN; j += MBEDTLS_CTR_DRBG_BLOCKSIZE ) + { + /* + * Increase counter + */ + for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, p ) ) != 0 ) + { + return( ret ); + } + + p += MBEDTLS_CTR_DRBG_BLOCKSIZE; + } + + for( i = 0; i < MBEDTLS_CTR_DRBG_SEEDLEN; i++ ) + tmp[i] ^= data[i]; + + /* + * Update key and counter + */ + if( ( ret = mbedtls_aes_setkey_enc( &ctx->aes_ctx, tmp, MBEDTLS_CTR_DRBG_KEYBITS ) ) != 0 ) + { + return( ret ); + } + memcpy( ctx->counter, tmp + MBEDTLS_CTR_DRBG_KEYSIZE, MBEDTLS_CTR_DRBG_BLOCKSIZE ); + + return( 0 ); +} + +void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t add_len ) +{ + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + + if( add_len > 0 ) + { + /* MAX_INPUT would be more logical here, but we have to match + * block_cipher_df()'s limits since we can't propagate errors */ + if( add_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ) + add_len = MBEDTLS_CTR_DRBG_MAX_SEED_INPUT; + + block_cipher_df( add_input, additional, add_len ); + ctr_drbg_update_internal( ctx, add_input ); + } +} + +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ) +{ + unsigned char seed[MBEDTLS_CTR_DRBG_MAX_SEED_INPUT]; + size_t seedlen = 0; + int ret; + + if( ctx->entropy_len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT || + len > MBEDTLS_CTR_DRBG_MAX_SEED_INPUT - ctx->entropy_len ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( seed, 0, MBEDTLS_CTR_DRBG_MAX_SEED_INPUT ); + + /* + * Gather entropy_len bytes of entropy to seed state + */ + if( 0 != ctx->f_entropy( ctx->p_entropy, seed, + ctx->entropy_len ) ) + { + return( MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED ); + } + + seedlen += ctx->entropy_len; + + /* + * Add additional data + */ + if( additional && len ) + { + memcpy( seed + seedlen, additional, len ); + seedlen += len; + } + + /* + * Reduce to 384 bits + */ + if( ( ret = block_cipher_df( seed, seed, seedlen ) ) != 0 ) + { + return( ret ); + } + + /* + * Update state + */ + if( ( ret = ctr_drbg_update_internal( ctx, seed ) ) != 0 ) + { + return( ret ); + } + ctx->reseed_counter = 1; + + return( 0 ); +} + +int mbedtls_ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ) +{ + int ret = 0; + mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; + unsigned char add_input[MBEDTLS_CTR_DRBG_SEEDLEN]; + unsigned char *p = output; + unsigned char tmp[MBEDTLS_CTR_DRBG_BLOCKSIZE]; + int i; + size_t use_len; + + if( output_len > MBEDTLS_CTR_DRBG_MAX_REQUEST ) + return( MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG ); + + if( add_len > MBEDTLS_CTR_DRBG_MAX_INPUT ) + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + + memset( add_input, 0, MBEDTLS_CTR_DRBG_SEEDLEN ); + + if( ctx->reseed_counter > ctx->reseed_interval || + ctx->prediction_resistance ) + { + if( ( ret = mbedtls_ctr_drbg_reseed( ctx, additional, add_len ) ) != 0 ) + { + return( ret ); + } + add_len = 0; + } + + if( add_len > 0 ) + { + if( ( ret = block_cipher_df( add_input, additional, add_len ) ) != 0 ) + { + return( ret ); + } + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + { + return( ret ); + } + } + + while( output_len > 0 ) + { + /* + * Increase counter + */ + for( i = MBEDTLS_CTR_DRBG_BLOCKSIZE; i > 0; i-- ) + if( ++ctx->counter[i - 1] != 0 ) + break; + + /* + * Crypt counter block + */ + if( ( ret = mbedtls_aes_crypt_ecb( &ctx->aes_ctx, MBEDTLS_AES_ENCRYPT, ctx->counter, tmp ) ) != 0 ) + { + return( ret ); + } + + use_len = ( output_len > MBEDTLS_CTR_DRBG_BLOCKSIZE ) ? MBEDTLS_CTR_DRBG_BLOCKSIZE : + output_len; + /* + * Copy random block to destination + */ + memcpy( p, tmp, use_len ); + p += use_len; + output_len -= use_len; + } + + if( ( ret = ctr_drbg_update_internal( ctx, add_input ) ) != 0 ) + { + return( ret ); + } + + ctx->reseed_counter++; + + return( 0 ); +} + +int mbedtls_ctr_drbg_random( void *p_rng, unsigned char *output, size_t output_len ) +{ + int ret; + mbedtls_ctr_drbg_context *ctx = (mbedtls_ctr_drbg_context *) p_rng; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = mbedtls_ctr_drbg_random_with_add( ctx, output, output_len, NULL, 0 ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + FILE *f; + unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); + + if( ( ret = mbedtls_ctr_drbg_random( ctx, buf, MBEDTLS_CTR_DRBG_MAX_INPUT ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, MBEDTLS_CTR_DRBG_MAX_INPUT, f ) != MBEDTLS_CTR_DRBG_MAX_INPUT ) + ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + else + ret = 0; + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + fclose( f ); + return( ret ); +} + +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ) +{ + int ret = 0; + FILE *f; + size_t n; + unsigned char buf[ MBEDTLS_CTR_DRBG_MAX_INPUT ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > MBEDTLS_CTR_DRBG_MAX_INPUT ) + { + fclose( f ); + return( MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG ); + } + + if( fread( buf, 1, n, f ) != n ) + ret = MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR; + else + mbedtls_ctr_drbg_update( ctx, buf, n ); + + fclose( f ); + + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + if( ret != 0 ) + return( ret ); + + return( mbedtls_ctr_drbg_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) + +static const unsigned char entropy_source_pr[96] = + { 0xc1, 0x80, 0x81, 0xa6, 0x5d, 0x44, 0x02, 0x16, + 0x19, 0xb3, 0xf1, 0x80, 0xb1, 0xc9, 0x20, 0x02, + 0x6a, 0x54, 0x6f, 0x0c, 0x70, 0x81, 0x49, 0x8b, + 0x6e, 0xa6, 0x62, 0x52, 0x6d, 0x51, 0xb1, 0xcb, + 0x58, 0x3b, 0xfa, 0xd5, 0x37, 0x5f, 0xfb, 0xc9, + 0xff, 0x46, 0xd2, 0x19, 0xc7, 0x22, 0x3e, 0x95, + 0x45, 0x9d, 0x82, 0xe1, 0xe7, 0x22, 0x9f, 0x63, + 0x31, 0x69, 0xd2, 0x6b, 0x57, 0x47, 0x4f, 0xa3, + 0x37, 0xc9, 0x98, 0x1c, 0x0b, 0xfb, 0x91, 0x31, + 0x4d, 0x55, 0xb9, 0xe9, 0x1c, 0x5a, 0x5e, 0xe4, + 0x93, 0x92, 0xcf, 0xc5, 0x23, 0x12, 0xd5, 0x56, + 0x2c, 0x4a, 0x6e, 0xff, 0xdc, 0x10, 0xd0, 0x68 }; + +static const unsigned char entropy_source_nopr[64] = + { 0x5a, 0x19, 0x4d, 0x5e, 0x2b, 0x31, 0x58, 0x14, + 0x54, 0xde, 0xf6, 0x75, 0xfb, 0x79, 0x58, 0xfe, + 0xc7, 0xdb, 0x87, 0x3e, 0x56, 0x89, 0xfc, 0x9d, + 0x03, 0x21, 0x7c, 0x68, 0xd8, 0x03, 0x38, 0x20, + 0xf9, 0xe6, 0x5e, 0x04, 0xd8, 0x56, 0xf3, 0xa9, + 0xc4, 0x4a, 0x4c, 0xbd, 0xc1, 0xd0, 0x08, 0x46, + 0xf5, 0x98, 0x3d, 0x77, 0x1c, 0x1b, 0x13, 0x7e, + 0x4e, 0x0f, 0x9d, 0x8e, 0xf4, 0x09, 0xf9, 0x2e }; + +static const unsigned char nonce_pers_pr[16] = + { 0xd2, 0x54, 0xfc, 0xff, 0x02, 0x1e, 0x69, 0xd2, + 0x29, 0xc9, 0xcf, 0xad, 0x85, 0xfa, 0x48, 0x6c }; + +static const unsigned char nonce_pers_nopr[16] = + { 0x1b, 0x54, 0xb8, 0xff, 0x06, 0x42, 0xbf, 0xf5, + 0x21, 0xf1, 0x5c, 0x1c, 0x0b, 0x66, 0x5f, 0x3f }; + +static const unsigned char result_pr[16] = + { 0x34, 0x01, 0x16, 0x56, 0xb4, 0x29, 0x00, 0x8f, + 0x35, 0x63, 0xec, 0xb5, 0xf2, 0x59, 0x07, 0x23 }; + +static const unsigned char result_nopr[16] = + { 0xa0, 0x54, 0x30, 0x3d, 0x8a, 0x7e, 0xa9, 0x88, + 0x9d, 0x90, 0x3e, 0x07, 0x7c, 0x6f, 0x21, 0x8f }; + +static size_t test_offset; +static int ctr_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 + */ +int mbedtls_ctr_drbg_self_test( int verbose ) +{ + mbedtls_ctr_drbg_context ctx; + unsigned char buf[16]; + + mbedtls_ctr_drbg_init( &ctx ); + + /* + * Based on a NIST CTR_DRBG test vector (PR = True) + */ + if( verbose != 0 ) + mbedtls_printf( " CTR_DRBG (PR = TRUE) : " ); + + test_offset = 0; + CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, + (void *) entropy_source_pr, nonce_pers_pr, 16, 32 ) ); + mbedtls_ctr_drbg_set_prediction_resistance( &ctx, MBEDTLS_CTR_DRBG_PR_ON ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); + CHK( memcmp( buf, result_pr, MBEDTLS_CTR_DRBG_BLOCKSIZE ) ); + + mbedtls_ctr_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + /* + * Based on a NIST CTR_DRBG test vector (PR = FALSE) + */ + if( verbose != 0 ) + mbedtls_printf( " CTR_DRBG (PR = FALSE): " ); + + mbedtls_ctr_drbg_init( &ctx ); + + test_offset = 0; + CHK( mbedtls_ctr_drbg_seed_entropy_len( &ctx, ctr_drbg_self_test_entropy, + (void *) entropy_source_nopr, nonce_pers_nopr, 16, 32 ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); + CHK( mbedtls_ctr_drbg_reseed( &ctx, NULL, 0 ) ); + CHK( mbedtls_ctr_drbg_random( &ctx, buf, 16 ) ); + CHK( memcmp( buf, result_nopr, 16 ) ); + + mbedtls_ctr_drbg_free( &ctx ); + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_CTR_DRBG_C */ diff --git a/common/mbedtls/ctr_drbg.h b/common/mbedtls/ctr_drbg.h new file mode 100644 index 000000000..5d62f9bea --- /dev/null +++ b/common/mbedtls/ctr_drbg.h @@ -0,0 +1,332 @@ +/** + * \file ctr_drbg.h + * + * \brief This file contains CTR_DRBG definitions and functions. + * + * CTR_DRBG is a standardized way of building a PRNG from a block-cipher + * in counter mode operation, as defined in NIST SP 800-90A: + * Recommendation for Random Number Generation Using Deterministic Random + * Bit Generators. + * + * The Mbed TLS implementation of CTR_DRBG uses AES-256 as the underlying + * block cipher. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_CTR_DRBG_H +#define MBEDTLS_CTR_DRBG_H + +#include "aes.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#endif + +#define MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED -0x0034 /**< The entropy source failed. */ +#define MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG -0x0036 /**< The requested random buffer length is too big. */ +#define MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG -0x0038 /**< The input (entropy + additional data) is too large. */ +#define MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR -0x003A /**< Read or write error in file. */ + +#define MBEDTLS_CTR_DRBG_BLOCKSIZE 16 /**< The block size used by the cipher. */ +#define MBEDTLS_CTR_DRBG_KEYSIZE 32 /**< The key size used by the cipher. */ +#define MBEDTLS_CTR_DRBG_KEYBITS ( MBEDTLS_CTR_DRBG_KEYSIZE * 8 ) /**< The key size for the DRBG operation, in bits. */ +#define MBEDTLS_CTR_DRBG_SEEDLEN ( MBEDTLS_CTR_DRBG_KEYSIZE + MBEDTLS_CTR_DRBG_BLOCKSIZE ) /**< The seed length, calculated as (counter + AES key). */ + +/** + * \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 using the compiler command + * line. + * \{ + */ + +#if !defined(MBEDTLS_CTR_DRBG_ENTROPY_LEN) +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 48 +/**< The amount of entropy used per seed by default: + *
  • 48 with SHA-512.
  • + *
  • 32 with SHA-256.
+ */ +#else +#define MBEDTLS_CTR_DRBG_ENTROPY_LEN 32 +/**< Amount of entropy used per seed by default: + *
  • 48 with SHA-512.
  • + *
  • 32 with SHA-256.
+ */ +#endif +#endif + +#if !defined(MBEDTLS_CTR_DRBG_RESEED_INTERVAL) +#define MBEDTLS_CTR_DRBG_RESEED_INTERVAL 10000 +/**< The interval before reseed is performed by default. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_INPUT 256 +/**< The maximum number of additional input Bytes. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_REQUEST) +#define MBEDTLS_CTR_DRBG_MAX_REQUEST 1024 +/**< The maximum number of requested Bytes per call. */ +#endif + +#if !defined(MBEDTLS_CTR_DRBG_MAX_SEED_INPUT) +#define MBEDTLS_CTR_DRBG_MAX_SEED_INPUT 384 +/**< The maximum size of seed or reseed buffer. */ +#endif + +/* \} name SECTION: Module settings */ + +#define MBEDTLS_CTR_DRBG_PR_OFF 0 +/**< Prediction resistance is disabled. */ +#define MBEDTLS_CTR_DRBG_PR_ON 1 +/**< Prediction resistance is enabled. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief The CTR_DRBG context structure. + */ +typedef struct mbedtls_ctr_drbg_context +{ + unsigned char counter[16]; /*!< The counter (V). */ + int reseed_counter; /*!< The reseed counter. */ + int prediction_resistance; /*!< This determines whether prediction + resistance is enabled, that is + whether to systematically reseed before + each random generation. */ + size_t entropy_len; /*!< The amount of entropy grabbed on each + seed or reseed operation. */ + int reseed_interval; /*!< The reseed interval. */ + + mbedtls_aes_context aes_ctx; /*!< The AES context. */ + + /* + * Callbacks (Entropy) + */ + int (*f_entropy)(void *, unsigned char *, size_t); + /*!< The entropy callback function. */ + + void *p_entropy; /*!< The context for the entropy function. */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; +#endif +} +mbedtls_ctr_drbg_context; + +/** + * \brief This function initializes the CTR_DRBG context, + * and prepares it for mbedtls_ctr_drbg_seed() + * or mbedtls_ctr_drbg_free(). + * + * \param ctx The CTR_DRBG context to initialize. + */ +void mbedtls_ctr_drbg_init( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function seeds and sets up the CTR_DRBG + * entropy source for future reseeds. + * + * \note Personalization data can be provided in addition to the more generic + * entropy source, to make this instantiation as unique as possible. + * + * \param ctx The CTR_DRBG context to seed. + * \param f_entropy The entropy callback, taking as arguments the + * \p p_entropy context, the buffer to fill, and the + length of the buffer. + * \param p_entropy The entropy context. + * \param custom Personalization data, that is device-specific + identifiers. Can be NULL. + * \param len The length of the personalization data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_seed( mbedtls_ctr_drbg_context *ctx, + int (*f_entropy)(void *, unsigned char *, size_t), + void *p_entropy, + const unsigned char *custom, + size_t len ); + +/** + * \brief This function clears CTR_CRBG context data. + * + * \param ctx The CTR_DRBG context to clear. + */ +void mbedtls_ctr_drbg_free( mbedtls_ctr_drbg_context *ctx ); + +/** + * \brief This function turns prediction resistance on or off. + * The default value is off. + * + * \note If enabled, entropy is gathered at the beginning of + * every call to mbedtls_ctr_drbg_random_with_add(). + * Only use this if your entropy source has sufficient + * throughput. + * + * \param ctx The CTR_DRBG context. + * \param resistance #MBEDTLS_CTR_DRBG_PR_ON or #MBEDTLS_CTR_DRBG_PR_OFF. + */ +void mbedtls_ctr_drbg_set_prediction_resistance( mbedtls_ctr_drbg_context *ctx, + int resistance ); + +/** + * \brief This function sets the amount of entropy grabbed on each + * seed or reseed. The default value is + * #MBEDTLS_CTR_DRBG_ENTROPY_LEN. + * + * \param ctx The CTR_DRBG context. + * \param len The amount of entropy to grab. + */ +void mbedtls_ctr_drbg_set_entropy_len( mbedtls_ctr_drbg_context *ctx, + size_t len ); + +/** + * \brief This function sets the reseed interval. + * The default value is #MBEDTLS_CTR_DRBG_RESEED_INTERVAL. + * + * \param ctx The CTR_DRBG context. + * \param interval The reseed interval. + */ +void mbedtls_ctr_drbg_set_reseed_interval( mbedtls_ctr_drbg_context *ctx, + int interval ); + +/** + * \brief This function reseeds the CTR_DRBG context, that is + * extracts data from the entropy source. + * + * \param ctx The CTR_DRBG context. + * \param additional Additional data to add to the state. Can be NULL. + * \param len The length of the additional data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on failure. + */ +int mbedtls_ctr_drbg_reseed( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t len ); + +/** + * \brief This function updates the state of the CTR_DRBG context. + * + * \note If \p add_len is greater than + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT, only the first + * #MBEDTLS_CTR_DRBG_MAX_SEED_INPUT Bytes are used. + * The remaining Bytes are silently discarded. + * + * \param ctx The CTR_DRBG context. + * \param additional The data to update the state with. + * \param add_len Length of \p additional data. + * + */ +void mbedtls_ctr_drbg_update( mbedtls_ctr_drbg_context *ctx, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function updates a CTR_DRBG instance with additional + * data and uses it to generate random data. + * + * \note The function automatically reseeds if the reseed counter is exceeded. + * + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer. + * \param additional Additional data to update. Can be NULL. + * \param add_len The length of the additional data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random_with_add( void *p_rng, + unsigned char *output, size_t output_len, + const unsigned char *additional, size_t add_len ); + +/** + * \brief This function uses CTR_DRBG to generate random data. + * + * \note The function automatically reseeds if the reseed counter is exceeded. + * + * \param p_rng The CTR_DRBG context. This must be a pointer to a + * #mbedtls_ctr_drbg_context structure. + * \param output The buffer to fill. + * \param output_len The length of the buffer. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_random( void *p_rng, + unsigned char *output, size_t output_len ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function writes a seed file. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED on + * failure. + */ +int mbedtls_ctr_drbg_write_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); + +/** + * \brief This function reads and updates a seed file. The seed + * is added to this instance. + * + * \param ctx The CTR_DRBG context. + * \param path The name of the file. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR on file error. + * \return #MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED or + * #MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG on failure. + */ +int mbedtls_ctr_drbg_update_seed_file( mbedtls_ctr_drbg_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief The CTR_DRBG checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ctr_drbg_self_test( int verbose ); + +/* Internal functions (do not call directly) */ +int mbedtls_ctr_drbg_seed_entropy_len( mbedtls_ctr_drbg_context *, + int (*)(void *, unsigned char *, size_t), void *, + const unsigned char *, size_t, size_t ); + +#ifdef __cplusplus +} +#endif + +#endif /* ctr_drbg.h */ diff --git a/common/mbedtls/des.c b/common/mbedtls/des.c new file mode 100644 index 000000000..5c4e2cc98 --- /dev/null +++ b/common/mbedtls/des.c @@ -0,0 +1,1059 @@ +/* + * FIPS-46-3 compliant Triple-DES implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * DES, on which TDES is based, was originally designed by Horst Feistel + * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). + * + * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_DES_C) + +#include "mbedtls/des.h" +#include "mbedtls/platform_util.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 */ + +#if !defined(MBEDTLS_DES_ALT) + +/* + * 32-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT32_BE +#define GET_UINT32_BE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ + | ( (uint32_t) (b)[(i) + 1] << 16 ) \ + | ( (uint32_t) (b)[(i) + 2] << 8 ) \ + | ( (uint32_t) (b)[(i) + 3] ); \ +} +#endif + +#ifndef PUT_UINT32_BE +#define PUT_UINT32_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) ); \ +} +#endif + +/* + * Expanded DES S-boxes + */ +static const uint32_t SB1[64] = +{ + 0x01010400, 0x00000000, 0x00010000, 0x01010404, + 0x01010004, 0x00010404, 0x00000004, 0x00010000, + 0x00000400, 0x01010400, 0x01010404, 0x00000400, + 0x01000404, 0x01010004, 0x01000000, 0x00000004, + 0x00000404, 0x01000400, 0x01000400, 0x00010400, + 0x00010400, 0x01010000, 0x01010000, 0x01000404, + 0x00010004, 0x01000004, 0x01000004, 0x00010004, + 0x00000000, 0x00000404, 0x00010404, 0x01000000, + 0x00010000, 0x01010404, 0x00000004, 0x01010000, + 0x01010400, 0x01000000, 0x01000000, 0x00000400, + 0x01010004, 0x00010000, 0x00010400, 0x01000004, + 0x00000400, 0x00000004, 0x01000404, 0x00010404, + 0x01010404, 0x00010004, 0x01010000, 0x01000404, + 0x01000004, 0x00000404, 0x00010404, 0x01010400, + 0x00000404, 0x01000400, 0x01000400, 0x00000000, + 0x00010004, 0x00010400, 0x00000000, 0x01010004 +}; + +static const uint32_t SB2[64] = +{ + 0x80108020, 0x80008000, 0x00008000, 0x00108020, + 0x00100000, 0x00000020, 0x80100020, 0x80008020, + 0x80000020, 0x80108020, 0x80108000, 0x80000000, + 0x80008000, 0x00100000, 0x00000020, 0x80100020, + 0x00108000, 0x00100020, 0x80008020, 0x00000000, + 0x80000000, 0x00008000, 0x00108020, 0x80100000, + 0x00100020, 0x80000020, 0x00000000, 0x00108000, + 0x00008020, 0x80108000, 0x80100000, 0x00008020, + 0x00000000, 0x00108020, 0x80100020, 0x00100000, + 0x80008020, 0x80100000, 0x80108000, 0x00008000, + 0x80100000, 0x80008000, 0x00000020, 0x80108020, + 0x00108020, 0x00000020, 0x00008000, 0x80000000, + 0x00008020, 0x80108000, 0x00100000, 0x80000020, + 0x00100020, 0x80008020, 0x80000020, 0x00100020, + 0x00108000, 0x00000000, 0x80008000, 0x00008020, + 0x80000000, 0x80100020, 0x80108020, 0x00108000 +}; + +static const uint32_t SB3[64] = +{ + 0x00000208, 0x08020200, 0x00000000, 0x08020008, + 0x08000200, 0x00000000, 0x00020208, 0x08000200, + 0x00020008, 0x08000008, 0x08000008, 0x00020000, + 0x08020208, 0x00020008, 0x08020000, 0x00000208, + 0x08000000, 0x00000008, 0x08020200, 0x00000200, + 0x00020200, 0x08020000, 0x08020008, 0x00020208, + 0x08000208, 0x00020200, 0x00020000, 0x08000208, + 0x00000008, 0x08020208, 0x00000200, 0x08000000, + 0x08020200, 0x08000000, 0x00020008, 0x00000208, + 0x00020000, 0x08020200, 0x08000200, 0x00000000, + 0x00000200, 0x00020008, 0x08020208, 0x08000200, + 0x08000008, 0x00000200, 0x00000000, 0x08020008, + 0x08000208, 0x00020000, 0x08000000, 0x08020208, + 0x00000008, 0x00020208, 0x00020200, 0x08000008, + 0x08020000, 0x08000208, 0x00000208, 0x08020000, + 0x00020208, 0x00000008, 0x08020008, 0x00020200 +}; + +static const uint32_t SB4[64] = +{ + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802080, 0x00800081, 0x00800001, 0x00002001, + 0x00000000, 0x00802000, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00800080, 0x00800001, + 0x00000001, 0x00002000, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002001, 0x00002080, + 0x00800081, 0x00000001, 0x00002080, 0x00800080, + 0x00002000, 0x00802080, 0x00802081, 0x00000081, + 0x00800080, 0x00800001, 0x00802000, 0x00802081, + 0x00000081, 0x00000000, 0x00000000, 0x00802000, + 0x00002080, 0x00800080, 0x00800081, 0x00000001, + 0x00802001, 0x00002081, 0x00002081, 0x00000080, + 0x00802081, 0x00000081, 0x00000001, 0x00002000, + 0x00800001, 0x00002001, 0x00802080, 0x00800081, + 0x00002001, 0x00002080, 0x00800000, 0x00802001, + 0x00000080, 0x00800000, 0x00002000, 0x00802080 +}; + +static const uint32_t SB5[64] = +{ + 0x00000100, 0x02080100, 0x02080000, 0x42000100, + 0x00080000, 0x00000100, 0x40000000, 0x02080000, + 0x40080100, 0x00080000, 0x02000100, 0x40080100, + 0x42000100, 0x42080000, 0x00080100, 0x40000000, + 0x02000000, 0x40080000, 0x40080000, 0x00000000, + 0x40000100, 0x42080100, 0x42080100, 0x02000100, + 0x42080000, 0x40000100, 0x00000000, 0x42000000, + 0x02080100, 0x02000000, 0x42000000, 0x00080100, + 0x00080000, 0x42000100, 0x00000100, 0x02000000, + 0x40000000, 0x02080000, 0x42000100, 0x40080100, + 0x02000100, 0x40000000, 0x42080000, 0x02080100, + 0x40080100, 0x00000100, 0x02000000, 0x42080000, + 0x42080100, 0x00080100, 0x42000000, 0x42080100, + 0x02080000, 0x00000000, 0x40080000, 0x42000000, + 0x00080100, 0x02000100, 0x40000100, 0x00080000, + 0x00000000, 0x40080000, 0x02080100, 0x40000100 +}; + +static const uint32_t SB6[64] = +{ + 0x20000010, 0x20400000, 0x00004000, 0x20404010, + 0x20400000, 0x00000010, 0x20404010, 0x00400000, + 0x20004000, 0x00404010, 0x00400000, 0x20000010, + 0x00400010, 0x20004000, 0x20000000, 0x00004010, + 0x00000000, 0x00400010, 0x20004010, 0x00004000, + 0x00404000, 0x20004010, 0x00000010, 0x20400010, + 0x20400010, 0x00000000, 0x00404010, 0x20404000, + 0x00004010, 0x00404000, 0x20404000, 0x20000000, + 0x20004000, 0x00000010, 0x20400010, 0x00404000, + 0x20404010, 0x00400000, 0x00004010, 0x20000010, + 0x00400000, 0x20004000, 0x20000000, 0x00004010, + 0x20000010, 0x20404010, 0x00404000, 0x20400000, + 0x00404010, 0x20404000, 0x00000000, 0x20400010, + 0x00000010, 0x00004000, 0x20400000, 0x00404010, + 0x00004000, 0x00400010, 0x20004010, 0x00000000, + 0x20404000, 0x20000000, 0x00400010, 0x20004010 +}; + +static const uint32_t SB7[64] = +{ + 0x00200000, 0x04200002, 0x04000802, 0x00000000, + 0x00000800, 0x04000802, 0x00200802, 0x04200800, + 0x04200802, 0x00200000, 0x00000000, 0x04000002, + 0x00000002, 0x04000000, 0x04200002, 0x00000802, + 0x04000800, 0x00200802, 0x00200002, 0x04000800, + 0x04000002, 0x04200000, 0x04200800, 0x00200002, + 0x04200000, 0x00000800, 0x00000802, 0x04200802, + 0x00200800, 0x00000002, 0x04000000, 0x00200800, + 0x04000000, 0x00200800, 0x00200000, 0x04000802, + 0x04000802, 0x04200002, 0x04200002, 0x00000002, + 0x00200002, 0x04000000, 0x04000800, 0x00200000, + 0x04200800, 0x00000802, 0x00200802, 0x04200800, + 0x00000802, 0x04000002, 0x04200802, 0x04200000, + 0x00200800, 0x00000000, 0x00000002, 0x04200802, + 0x00000000, 0x00200802, 0x04200000, 0x00000800, + 0x04000002, 0x04000800, 0x00000800, 0x00200002 +}; + +static const uint32_t SB8[64] = +{ + 0x10001040, 0x00001000, 0x00040000, 0x10041040, + 0x10000000, 0x10001040, 0x00000040, 0x10000000, + 0x00040040, 0x10040000, 0x10041040, 0x00041000, + 0x10041000, 0x00041040, 0x00001000, 0x00000040, + 0x10040000, 0x10000040, 0x10001000, 0x00001040, + 0x00041000, 0x00040040, 0x10040040, 0x10041000, + 0x00001040, 0x00000000, 0x00000000, 0x10040040, + 0x10000040, 0x10001000, 0x00041040, 0x00040000, + 0x00041040, 0x00040000, 0x10041000, 0x00001000, + 0x00000040, 0x10040040, 0x00001000, 0x00041040, + 0x10001000, 0x00000040, 0x10000040, 0x10040000, + 0x10040040, 0x10000000, 0x00040000, 0x10001040, + 0x00000000, 0x10041040, 0x00040040, 0x10000040, + 0x10040000, 0x10001000, 0x10001040, 0x00000000, + 0x10041040, 0x00041000, 0x00041000, 0x00001040, + 0x00001040, 0x00040040, 0x10000000, 0x10041000 +}; + +/* + * PC1: left and right halves bit-swap + */ +static const uint32_t LHs[16] = +{ + 0x00000000, 0x00000001, 0x00000100, 0x00000101, + 0x00010000, 0x00010001, 0x00010100, 0x00010101, + 0x01000000, 0x01000001, 0x01000100, 0x01000101, + 0x01010000, 0x01010001, 0x01010100, 0x01010101 +}; + +static const uint32_t RHs[16] = +{ + 0x00000000, 0x01000000, 0x00010000, 0x01010000, + 0x00000100, 0x01000100, 0x00010100, 0x01010100, + 0x00000001, 0x01000001, 0x00010001, 0x01010001, + 0x00000101, 0x01000101, 0x00010101, 0x01010101, +}; + +/* + * Initial Permutation macro + */ +#define DES_IP(X,Y) \ +{ \ + T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ + T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ + T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ + T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ + Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \ + T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \ + X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \ +} + +/* + * Final Permutation macro + */ +#define DES_FP(X,Y) \ +{ \ + X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \ + T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \ + Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \ + T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ + T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ + T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ + T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ +} + +/* + * DES round macro + */ +#define DES_ROUND(X,Y) \ +{ \ + T = *SK++ ^ X; \ + Y ^= SB8[ (T ) & 0x3F ] ^ \ + SB6[ (T >> 8) & 0x3F ] ^ \ + SB4[ (T >> 16) & 0x3F ] ^ \ + SB2[ (T >> 24) & 0x3F ]; \ + \ + T = *SK++ ^ ((X << 28) | (X >> 4)); \ + Y ^= SB7[ (T ) & 0x3F ] ^ \ + SB5[ (T >> 8) & 0x3F ] ^ \ + SB3[ (T >> 16) & 0x3F ] ^ \ + SB1[ (T >> 24) & 0x3F ]; \ +} + +#define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; } + +void mbedtls_des_init( mbedtls_des_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_des_context ) ); +} + +void mbedtls_des_free( mbedtls_des_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des_context ) ); +} + +void mbedtls_des3_init( mbedtls_des3_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_des3_context ) ); +} + +void mbedtls_des3_free( mbedtls_des3_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_des3_context ) ); +} + +static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, + 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, + 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, + 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, + 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, + 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, + 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, + 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, + 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, + 254 }; + +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) + key[i] = odd_parity_table[key[i] / 2]; +} + +/* + * Check the given key's parity, returns 1 on failure, 0 on SUCCESS + */ +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < MBEDTLS_DES_KEY_SIZE; i++ ) + if( key[i] != odd_parity_table[key[i] / 2] ) + return( 1 ); + + return( 0 ); +} + +/* + * Table of weak and semi-weak keys + * + * Source: http://en.wikipedia.org/wiki/Weak_key + * + * Weak: + * Alternating ones + zeros (0x0101010101010101) + * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE) + * '0xE0E0E0E0F1F1F1F1' + * '0x1F1F1F1F0E0E0E0E' + * + * Semi-weak: + * 0x011F011F010E010E and 0x1F011F010E010E01 + * 0x01E001E001F101F1 and 0xE001E001F101F101 + * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01 + * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E + * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E + * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1 + * + */ + +#define WEAK_KEY_COUNT 16 + +static const unsigned char weak_key_table[WEAK_KEY_COUNT][MBEDTLS_DES_KEY_SIZE] = +{ + { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, + { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, + { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, + { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 }, + + { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, + { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, + { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, + { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, + { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, + { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, + { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, + { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, + { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, + { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, + { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, + { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } +}; + +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + for( i = 0; i < WEAK_KEY_COUNT; i++ ) + if( memcmp( weak_key_table[i], key, MBEDTLS_DES_KEY_SIZE) == 0 ) + return( 1 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DES_SETKEY_ALT) +void mbedtls_des_setkey( uint32_t SK[32], const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + uint32_t X, Y, T; + + GET_UINT32_BE( X, key, 0 ); + GET_UINT32_BE( Y, key, 4 ); + + /* + * Permuted Choice 1 + */ + T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); + T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); + + X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) + | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) + | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) + | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); + + Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) + | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) + | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) + | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); + + X &= 0x0FFFFFFF; + Y &= 0x0FFFFFFF; + + /* + * calculate subkeys + */ + for( i = 0; i < 16; i++ ) + { + if( i < 2 || i == 8 || i == 15 ) + { + X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; + Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; + } + else + { + X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; + Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; + } + + *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) + | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) + | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) + | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) + | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) + | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) + | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) + | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) + | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) + | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) + | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); + + *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) + | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) + | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) + | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) + | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) + | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) + | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) + | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) + | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) + | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) + | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); + } +} +#endif /* !MBEDTLS_DES_SETKEY_ALT */ + +/* + * DES key schedule (56-bit, encryption) + */ +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + mbedtls_des_setkey( ctx->sk, key ); + + return( 0 ); +} + +/* + * DES key schedule (56-bit, decryption) + */ +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ) +{ + int i; + + mbedtls_des_setkey( ctx->sk, key ); + + for( i = 0; i < 16; i += 2 ) + { + SWAP( ctx->sk[i ], ctx->sk[30 - i] ); + SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); + } + + return( 0 ); +} + +static void des3_set2key( uint32_t esk[96], + uint32_t dsk[96], + const unsigned char key[MBEDTLS_DES_KEY_SIZE*2] ) +{ + int i; + + mbedtls_des_setkey( esk, key ); + mbedtls_des_setkey( dsk + 32, key + 8 ); + + for( i = 0; i < 32; i += 2 ) + { + dsk[i ] = esk[30 - i]; + dsk[i + 1] = esk[31 - i]; + + esk[i + 32] = dsk[62 - i]; + esk[i + 33] = dsk[63 - i]; + + esk[i + 64] = esk[i ]; + esk[i + 65] = esk[i + 1]; + + dsk[i + 64] = dsk[i ]; + dsk[i + 65] = dsk[i + 1]; + } +} + +/* + * Triple-DES key schedule (112-bit, encryption) + */ +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; + + des3_set2key( ctx->sk, sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (112-bit, decryption) + */ +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ) +{ + uint32_t sk[96]; + + des3_set2key( sk, ctx->sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +static void des3_set3key( uint32_t esk[96], + uint32_t dsk[96], + const unsigned char key[24] ) +{ + int i; + + mbedtls_des_setkey( esk, key ); + mbedtls_des_setkey( dsk + 32, key + 8 ); + mbedtls_des_setkey( esk + 64, key + 16 ); + + for( i = 0; i < 32; i += 2 ) + { + dsk[i ] = esk[94 - i]; + dsk[i + 1] = esk[95 - i]; + + esk[i + 32] = dsk[62 - i]; + esk[i + 33] = dsk[63 - i]; + + dsk[i + 64] = esk[30 - i]; + dsk[i + 65] = esk[31 - i]; + } +} + +/* + * Triple-DES key schedule (168-bit, encryption) + */ +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; + + des3_set3key( ctx->sk, sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * Triple-DES key schedule (168-bit, decryption) + */ +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ) +{ + uint32_t sk[96]; + + des3_set3key( sk, ctx->sk, key ); + mbedtls_platform_zeroize( sk, sizeof( sk ) ); + + return( 0 ); +} + +/* + * DES-ECB block encryption/decryption + */ +#if !defined(MBEDTLS_DES_CRYPT_ECB_ALT) +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + uint32_t X, Y, T, *SK; + + SK = ctx->sk; + + GET_UINT32_BE( X, input, 0 ); + GET_UINT32_BE( Y, input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + PUT_UINT32_BE( Y, output, 0 ); + PUT_UINT32_BE( X, output, 4 ); + + return( 0 ); +} +#endif /* !MBEDTLS_DES_CRYPT_ECB_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * DES-CBC buffer encryption/decryption + */ +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_des_crypt_ecb( ctx, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* MBEDTLS_DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + mbedtls_des_crypt_ecb( ctx, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/* + * 3DES-ECB block encryption/decryption + */ +#if !defined(MBEDTLS_DES3_CRYPT_ECB_ALT) +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ) +{ + int i; + uint32_t X, Y, T, *SK; + + SK = ctx->sk; + + GET_UINT32_BE( X, input, 0 ); + GET_UINT32_BE( Y, input, 4 ); + + DES_IP( X, Y ); + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( X, Y ); + DES_ROUND( Y, X ); + } + + for( i = 0; i < 8; i++ ) + { + DES_ROUND( Y, X ); + DES_ROUND( X, Y ); + } + + DES_FP( Y, X ); + + PUT_UINT32_BE( Y, output, 0 ); + PUT_UINT32_BE( X, output, 4 ); + + return( 0 ); +} +#endif /* !MBEDTLS_DES3_CRYPT_ECB_ALT */ + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/* + * 3DES-CBC buffer encryption/decryption + */ +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ) +{ + int i; + unsigned char temp[8]; + + if( length % 8 ) + return( MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH ); + + if( mode == MBEDTLS_DES_ENCRYPT ) + { + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( input[i] ^ iv[i] ); + + mbedtls_des3_crypt_ecb( ctx, output, output ); + memcpy( iv, output, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + else /* MBEDTLS_DES_DECRYPT */ + { + while( length > 0 ) + { + memcpy( temp, input, 8 ); + mbedtls_des3_crypt_ecb( ctx, input, output ); + + for( i = 0; i < 8; i++ ) + output[i] = (unsigned char)( output[i] ^ iv[i] ); + + memcpy( iv, temp, 8 ); + + input += 8; + output += 8; + length -= 8; + } + } + + return( 0 ); +} +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +#endif /* !MBEDTLS_DES_ALT */ + +#if defined(MBEDTLS_SELF_TEST) +/* + * DES and 3DES test vectors from: + * + * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip + */ +static const unsigned char des3_test_keys[24] = +{ + 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, + 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, + 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 +}; + +static const unsigned char des3_test_buf[8] = +{ + 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 +}; + +static const unsigned char des3_test_ecb_dec[3][8] = +{ + { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D }, + { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB }, + { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A } +}; + +static const unsigned char des3_test_ecb_enc[3][8] = +{ + { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B }, + { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 }, + { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 } +}; + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +static const unsigned char des3_test_iv[8] = +{ + 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, +}; + +static const unsigned char des3_test_cbc_dec[3][8] = +{ + { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 }, + { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 }, + { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C } +}; + +static const unsigned char des3_test_cbc_enc[3][8] = +{ + { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 }, + { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D }, + { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 } +}; +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/* + * Checkup routine + */ +int mbedtls_des_self_test( int verbose ) +{ + int i, j, u, v, ret = 0; + mbedtls_des_context ctx; + mbedtls_des3_context ctx3; + unsigned char buf[8]; +#if defined(MBEDTLS_CIPHER_MODE_CBC) + unsigned char prv[8]; + unsigned char iv[8]; +#endif + + mbedtls_des_init( &ctx ); + mbedtls_des3_init( &ctx3 ); + /* + * ECB mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " DES%c-ECB-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + mbedtls_des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + mbedtls_des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + + for( j = 0; j < 10000; j++ ) + { + if( u == 0 ) + mbedtls_des_crypt_ecb( &ctx, buf, buf ); + else + mbedtls_des3_crypt_ecb( &ctx3, buf, buf ); + } + + if( ( v == MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) || + ( v != MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_ecb_enc[u], 8 ) != 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" ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) + /* + * CBC mode + */ + for( i = 0; i < 6; i++ ) + { + u = i >> 1; + v = i & 1; + + if( verbose != 0 ) + mbedtls_printf( " DES%c-CBC-%3d (%s): ", + ( u == 0 ) ? ' ' : '3', 56 + u * 56, + ( v == MBEDTLS_DES_DECRYPT ) ? "dec" : "enc" ); + + memcpy( iv, des3_test_iv, 8 ); + memcpy( prv, des3_test_iv, 8 ); + memcpy( buf, des3_test_buf, 8 ); + + switch( i ) + { + case 0: + mbedtls_des_setkey_dec( &ctx, des3_test_keys ); + break; + + case 1: + mbedtls_des_setkey_enc( &ctx, des3_test_keys ); + break; + + case 2: + mbedtls_des3_set2key_dec( &ctx3, des3_test_keys ); + break; + + case 3: + mbedtls_des3_set2key_enc( &ctx3, des3_test_keys ); + break; + + case 4: + mbedtls_des3_set3key_dec( &ctx3, des3_test_keys ); + break; + + case 5: + mbedtls_des3_set3key_enc( &ctx3, des3_test_keys ); + break; + + default: + return( 1 ); + } + + if( v == MBEDTLS_DES_DECRYPT ) + { + for( j = 0; j < 10000; j++ ) + { + if( u == 0 ) + mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + } + } + else + { + for( j = 0; j < 10000; j++ ) + { + unsigned char tmp[8]; + + if( u == 0 ) + mbedtls_des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); + else + mbedtls_des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); + + memcpy( tmp, prv, 8 ); + memcpy( prv, buf, 8 ); + memcpy( buf, tmp, 8 ); + } + + memcpy( buf, prv, 8 ); + } + + if( ( v == MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) || + ( v != MBEDTLS_DES_DECRYPT && + memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto exit; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +exit: + mbedtls_des_free( &ctx ); + mbedtls_des3_free( &ctx3 ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_DES_C */ diff --git a/common/mbedtls/des.h b/common/mbedtls/des.h new file mode 100644 index 000000000..9406e0ae5 --- /dev/null +++ b/common/mbedtls/des.h @@ -0,0 +1,352 @@ +/** + * \file des.h + * + * \brief DES block cipher + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + */ +#ifndef MBEDTLS_DES_H +#define MBEDTLS_DES_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_DES_ENCRYPT 1 +#define MBEDTLS_DES_DECRYPT 0 + +#define MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ +#define MBEDTLS_ERR_DES_HW_ACCEL_FAILED -0x0033 /**< DES hardware accelerator failed. */ + +#define MBEDTLS_DES_KEY_SIZE 8 + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_DES_ALT) +// Regular implementation +// + +/** + * \brief DES context structure + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +typedef struct mbedtls_des_context +{ + uint32_t sk[32]; /*!< DES subkeys */ +} +mbedtls_des_context; + +/** + * \brief Triple-DES context structure + */ +typedef struct mbedtls_des3_context +{ + uint32_t sk[96]; /*!< 3DES subkeys */ +} +mbedtls_des3_context; + +#else /* MBEDTLS_DES_ALT */ +#include "des_alt.h" +#endif /* MBEDTLS_DES_ALT */ + +/** + * \brief Initialize DES context + * + * \param ctx DES context to be initialized + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_init( mbedtls_des_context *ctx ); + +/** + * \brief Clear DES context + * + * \param ctx DES context to be cleared + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_free( mbedtls_des_context *ctx ); + +/** + * \brief Initialize Triple-DES context + * + * \param ctx DES3 context to be initialized + */ +void mbedtls_des3_init( mbedtls_des3_context *ctx ); + +/** + * \brief Clear Triple-DES context + * + * \param ctx DES3 context to be cleared + */ +void mbedtls_des3_free( mbedtls_des3_context *ctx ); + +/** + * \brief Set key parity on the given key to odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_key_set_parity( unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key parity on the given key is odd. + * + * DES keys are 56 bits long, but each byte is padded with + * a parity bit to allow verification. + * + * \param key 8-byte secret key + * + * \return 0 is parity was ok, 1 if parity was not correct. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_key_check_key_parity( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Check that key is not a weak or semi-weak DES key + * + * \param key 8-byte secret key + * + * \return 0 if no weak key was found, 1 if a weak key was identified. + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_key_check_weak( const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, encryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_setkey_enc( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief DES key schedule (56-bit, decryption) + * + * \param ctx DES context to be initialized + * \param key 8-byte secret key + * + * \return 0 + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_setkey_dec( mbedtls_des_context *ctx, const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Triple-DES key schedule (112-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set2key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (112-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 16-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set2key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 2] ); + +/** + * \brief Triple-DES key schedule (168-bit, encryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_enc( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief Triple-DES key schedule (168-bit, decryption) + * + * \param ctx 3DES context to be initialized + * \param key 24-byte secret key + * + * \return 0 + */ +int mbedtls_des3_set3key_dec( mbedtls_des3_context *ctx, + const unsigned char key[MBEDTLS_DES_KEY_SIZE * 3] ); + +/** + * \brief DES-ECB block encryption/decryption + * + * \param ctx DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_crypt_ecb( mbedtls_des_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +int mbedtls_des_crypt_cbc( mbedtls_des_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief 3DES-ECB block encryption/decryption + * + * \param ctx 3DES context + * \param input 64-bit input block + * \param output 64-bit output block + * + * \return 0 if successful + */ +int mbedtls_des3_crypt_ecb( mbedtls_des3_context *ctx, + const unsigned char input[8], + unsigned char output[8] ); + +#if defined(MBEDTLS_CIPHER_MODE_CBC) +/** + * \brief 3DES-CBC buffer encryption/decryption + * + * \note Upon exit, the content of the IV is updated so that you can + * call the function same function again on the following + * block(s) of data and get the same result as if it was + * encrypted in one call. This allows a "streaming" usage. + * If on the other hand you need to retain the contents of the + * IV, you should either save it manually or use the cipher + * module instead. + * + * \param ctx 3DES context + * \param mode MBEDTLS_DES_ENCRYPT or MBEDTLS_DES_DECRYPT + * \param length length of the input data + * \param iv initialization vector (updated after use) + * \param input buffer holding the input data + * \param output buffer holding the output data + * + * \return 0 if successful, or MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH + */ +int mbedtls_des3_crypt_cbc( mbedtls_des3_context *ctx, + int mode, + size_t length, + unsigned char iv[8], + const unsigned char *input, + unsigned char *output ); +#endif /* MBEDTLS_CIPHER_MODE_CBC */ + +/** + * \brief Internal function for key expansion. + * (Only exposed to allow overriding it, + * see MBEDTLS_DES_SETKEY_ALT) + * + * \param SK Round keys + * \param key Base key + * + * \warning DES is considered a weak cipher and its use constitutes a + * security risk. We recommend considering stronger ciphers + * instead. + */ +void mbedtls_des_setkey( uint32_t SK[32], + const unsigned char key[MBEDTLS_DES_KEY_SIZE] ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_des_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* des.h */ diff --git a/common/mbedtls/ecdsa.c b/common/mbedtls/ecdsa.c new file mode 100644 index 000000000..e97e6cb43 --- /dev/null +++ b/common/mbedtls/ecdsa.c @@ -0,0 +1,463 @@ +/* + * Elliptic curve DSA + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECDSA_C) + +#include "mbedtls/ecdsa.h" +#include "mbedtls/asn1write.h" + +#include + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#include "mbedtls/hmac_drbg.h" +#endif + +/* + * Derive a suitable integer for group grp from a buffer of length len + * SEC1 4.1.3 step 5 aka SEC1 4.1.4 step 3 + */ +static int derive_mpi( const mbedtls_ecp_group *grp, mbedtls_mpi *x, + const unsigned char *buf, size_t blen ) +{ + int ret; + size_t n_size = ( grp->nbits + 7 ) / 8; + size_t use_size = blen > n_size ? n_size : blen; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( x, buf, use_size ) ); + if( use_size * 8 > grp->nbits ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( x, use_size * 8 - grp->nbits ) ); + + /* While at it, reduce modulo N */ + if( mbedtls_mpi_cmp_mpi( x, &grp->N ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( x, x, &grp->N ) ); + +cleanup: + return( ret ); +} + +#if !defined(MBEDTLS_ECDSA_SIGN_ALT) +/* + * Compute ECDSA signature of a hashed message (SEC1 4.1.3) + * Obviously, compared to SEC1 4.1.3, we skip step 4 (hash message) + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, key_tries, sign_tries, blind_tries; + mbedtls_ecp_point R; + mbedtls_mpi k, e, t; + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( grp->N.p == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* Make sure d is in range 1..n-1 */ + if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + mbedtls_ecp_point_init( &R ); + mbedtls_mpi_init( &k ); mbedtls_mpi_init( &e ); mbedtls_mpi_init( &t ); + + sign_tries = 0; + do + { + /* + * Steps 1-3: generate a suitable ephemeral keypair + * and set r = xR mod n + */ + key_tries = 0; + do + { + MBEDTLS_MPI_CHK( mbedtls_ecp_gen_keypair( grp, &k, &R, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( r, &R.X, &grp->N ) ); + + if( key_tries++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + } + while( mbedtls_mpi_cmp_int( r, 0 ) == 0 ); + + /* + * Step 5: derive MPI from hashed message + */ + MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Generate a random value to blind inv_mod in next step, + * avoiding a potential timing leak. + */ + blind_tries = 0; + do + { + size_t n_size = ( grp->nbits + 7 ) / 8; + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &t, n_size, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &t, 8 * n_size - grp->nbits ) ); + + /* See mbedtls_ecp_gen_keypair() */ + if( ++blind_tries > 30 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + } + while( mbedtls_mpi_cmp_int( &t, 1 ) < 0 || + mbedtls_mpi_cmp_mpi( &t, &grp->N ) >= 0 ); + + /* + * Step 6: compute s = (e + r * d) / k = t (e + rd) / (kt) mod n + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, r, d ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &e, &e, s ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &e, &e, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &k, &k, &t ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( s, &k, &grp->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( s, s, &e ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( s, s, &grp->N ) ); + + if( sign_tries++ > 10 ) + { + ret = MBEDTLS_ERR_ECP_RANDOM_FAILED; + goto cleanup; + } + } + while( mbedtls_mpi_cmp_int( s, 0 ) == 0 ); + +cleanup: + mbedtls_ecp_point_free( &R ); + mbedtls_mpi_free( &k ); mbedtls_mpi_free( &e ); mbedtls_mpi_free( &t ); + + return( ret ); +} +#endif /* MBEDTLS_ECDSA_SIGN_ALT */ + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/* + * Deterministic signature wrapper + */ +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ) +{ + int ret; + mbedtls_hmac_drbg_context rng_ctx; + unsigned char data[2 * MBEDTLS_ECP_MAX_BYTES]; + size_t grp_len = ( grp->nbits + 7 ) / 8; + const mbedtls_md_info_t *md_info; + mbedtls_mpi h; + + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &h ); + mbedtls_hmac_drbg_init( &rng_ctx ); + + /* Use private key and message hash (reduced) to initialize HMAC_DRBG */ + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( d, data, grp_len ) ); + MBEDTLS_MPI_CHK( derive_mpi( grp, &h, buf, blen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &h, data + grp_len, grp_len ) ); + mbedtls_hmac_drbg_seed_buf( &rng_ctx, md_info, data, 2 * grp_len ); + + ret = mbedtls_ecdsa_sign( grp, r, s, d, buf, blen, + mbedtls_hmac_drbg_random, &rng_ctx ); + +cleanup: + mbedtls_hmac_drbg_free( &rng_ctx ); + mbedtls_mpi_free( &h ); + + return( ret ); +} +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +#if !defined(MBEDTLS_ECDSA_VERIFY_ALT) +/* + * Verify ECDSA signature of hashed message (SEC1 4.1.4) + * Obviously, compared to SEC1 4.1.3, we skip step 2 (hash message) + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s) +{ + int ret; + mbedtls_mpi e, s_inv, u1, u2; + mbedtls_ecp_point R; + + mbedtls_ecp_point_init( &R ); + mbedtls_mpi_init( &e ); mbedtls_mpi_init( &s_inv ); mbedtls_mpi_init( &u1 ); mbedtls_mpi_init( &u2 ); + + /* Fail cleanly on curves such as Curve25519 that can't be used for ECDSA */ + if( grp->N.p == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Step 1: make sure r and s are in range 1..n-1 + */ + if( mbedtls_mpi_cmp_int( r, 1 ) < 0 || mbedtls_mpi_cmp_mpi( r, &grp->N ) >= 0 || + mbedtls_mpi_cmp_int( s, 1 ) < 0 || mbedtls_mpi_cmp_mpi( s, &grp->N ) >= 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Additional precaution: make sure Q is valid + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_check_pubkey( grp, Q ) ); + + /* + * Step 3: derive MPI from hashed message + */ + MBEDTLS_MPI_CHK( derive_mpi( grp, &e, buf, blen ) ); + + /* + * Step 4: u1 = e / s mod n, u2 = r / s mod n + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &s_inv, s, &grp->N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u1, &e, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u1, &u1, &grp->N ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u2, r, &s_inv ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &u2, &u2, &grp->N ) ); + + /* + * Step 5: R = u1 G + u2 Q + * + * Since we're not using any secret data, no need to pass a RNG to + * mbedtls_ecp_mul() for countermesures. + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_muladd( grp, &R, &u1, &grp->G, &u2, Q ) ); + + if( mbedtls_ecp_is_zero( &R ) ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + + /* + * Step 6: convert xR to an integer (no-op) + * Step 7: reduce xR mod n (gives v) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &R.X, &R.X, &grp->N ) ); + + /* + * Step 8: check if v (that is, R.X) is equal to r + */ + if( mbedtls_mpi_cmp_mpi( &R.X, r ) != 0 ) + { + ret = MBEDTLS_ERR_ECP_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &R ); + mbedtls_mpi_free( &e ); mbedtls_mpi_free( &s_inv ); mbedtls_mpi_free( &u1 ); mbedtls_mpi_free( &u2 ); + + return( ret ); +} +#endif /* MBEDTLS_ECDSA_VERIFY_ALT */ + +/* + * Convert a signature (given by context) to ASN.1 + */ +static int ecdsa_signature_to_asn1( const mbedtls_mpi *r, const mbedtls_mpi *s, + unsigned char *sig, size_t *slen ) +{ + int ret; + unsigned char buf[MBEDTLS_ECDSA_MAX_LEN]; + unsigned char *p = buf + sizeof( buf ); + size_t len = 0; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, s ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &p, buf, r ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &p, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &p, buf, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ); + + memcpy( sig, p, len ); + *slen = len; + + return( 0 ); +} + +/* + * Compute and write signature + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_mpi r, s; + + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) + (void) f_rng; + (void) p_rng; + + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign_det( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, md_alg ) ); +#else + (void) md_alg; + + MBEDTLS_MPI_CHK( mbedtls_ecdsa_sign( &ctx->grp, &r, &s, &ctx->d, + hash, hlen, f_rng, p_rng ) ); +#endif + + MBEDTLS_MPI_CHK( ecdsa_signature_to_asn1( &r, &s, sig, slen ) ); + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + + return( ret ); +} + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) && \ + defined(MBEDTLS_ECDSA_DETERMINISTIC) +int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + mbedtls_md_type_t md_alg ) +{ + return( mbedtls_ecdsa_write_signature( ctx, md_alg, hash, hlen, sig, slen, + NULL, NULL ) ); +} +#endif + +/* + * Read and check signature + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ) +{ + int ret; + unsigned char *p = (unsigned char *) sig; + const unsigned char *end = sig + slen; + size_t len; + mbedtls_mpi r, s; + + mbedtls_mpi_init( &r ); + mbedtls_mpi_init( &s ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + if( p + len != end ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + goto cleanup; + } + + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &r ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &s ) ) != 0 ) + { + ret += MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + + if( ( ret = mbedtls_ecdsa_verify( &ctx->grp, hash, hlen, + &ctx->Q, &r, &s ) ) != 0 ) + goto cleanup; + + /* At this point we know that the buffer starts with a valid signature. + * Return 0 if the buffer just contains the signature, and a specific + * error code if the valid signature is followed by more data. */ + if( p != end ) + ret = MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH; + +cleanup: + mbedtls_mpi_free( &r ); + mbedtls_mpi_free( &s ); + + return( ret ); +} + +#if !defined(MBEDTLS_ECDSA_GENKEY_ALT) +/* + * Generate key pair + */ +int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_ecp_group_load( &ctx->grp, gid ) || + mbedtls_ecp_gen_keypair( &ctx->grp, &ctx->d, &ctx->Q, f_rng, p_rng ) ); +} +#endif /* MBEDTLS_ECDSA_GENKEY_ALT */ + +/* + * Set context from an mbedtls_ecp_keypair + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ) +{ + int ret; + + if( ( ret = mbedtls_ecp_group_copy( &ctx->grp, &key->grp ) ) != 0 || + ( ret = mbedtls_mpi_copy( &ctx->d, &key->d ) ) != 0 || + ( ret = mbedtls_ecp_copy( &ctx->Q, &key->Q ) ) != 0 ) + { + mbedtls_ecdsa_free( ctx ); + } + + return( ret ); +} + +/* + * Initialize context + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ) +{ + mbedtls_ecp_keypair_init( ctx ); +} + +/* + * Free context + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ) +{ + mbedtls_ecp_keypair_free( ctx ); +} + +#endif /* MBEDTLS_ECDSA_C */ diff --git a/common/mbedtls/ecdsa.h b/common/mbedtls/ecdsa.h new file mode 100644 index 000000000..a56cc0a54 --- /dev/null +++ b/common/mbedtls/ecdsa.h @@ -0,0 +1,341 @@ +/** + * \file ecdsa.h + * + * \brief This file contains ECDSA definitions and functions. + * + * The Elliptic Curve Digital Signature Algorithm (ECDSA) is defined in + * Standards for Efficient Cryptography Group (SECG): + * SEC1 Elliptic Curve Cryptography. + * The use of ECDSA for TLS is defined in RFC-4492: Elliptic Curve + * Cryptography (ECC) Cipher Suites for Transport Layer Security (TLS). + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_ECDSA_H +#define MBEDTLS_ECDSA_H + +#include "ecp.h" +#include "md.h" + +/* + * RFC-4492 page 20: + * + * Ecdsa-Sig-Value ::= SEQUENCE { + * r INTEGER, + * s INTEGER + * } + * + * Size is at most + * 1 (tag) + 1 (len) + 1 (initial 0) + ECP_MAX_BYTES for each of r and s, + * twice that + 1 (tag) + 2 (len) for the sequence + * (assuming ECP_MAX_BYTES is less than 126 for r and s, + * and less than 124 (total len <= 255) for the sequence) + */ +#if MBEDTLS_ECP_MAX_BYTES > 124 +#error "MBEDTLS_ECP_MAX_BYTES bigger than expected, please fix MBEDTLS_ECDSA_MAX_LEN" +#endif +/** The maximal size of an ECDSA signature in Bytes. */ +#define MBEDTLS_ECDSA_MAX_LEN ( 3 + 2 * ( 3 + MBEDTLS_ECP_MAX_BYTES ) ) + +/** + * \brief The ECDSA context structure. + */ +typedef mbedtls_ecp_keypair mbedtls_ecdsa_context; + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message. + * + * \note The deterministic version is usually preferred. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated + * as defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The ECP group. + * \param r The first output integer. + * \param s The second output integer. + * \param d The private signing key. + * \param buf The message hash. + * \param blen The length of \p buf. + * \param f_rng The RNG function. + * \param p_rng The RNG context. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX + * or \c MBEDTLS_MPI_XXX error code on failure. + */ +int mbedtls_ecdsa_sign( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +/** + * \brief This function computes the ECDSA signature of a + * previously-hashed message, deterministic version. + * + * For more information, see RFC-6979: Deterministic + * Usage of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param grp The ECP group. + * \param r The first output integer. + * \param s The second output integer. + * \param d The private signing key. + * \param buf The message hash. + * \param blen The length of \p buf. + * \param md_alg The MD algorithm used to hash the message. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure. + */ +int mbedtls_ecdsa_sign_det( mbedtls_ecp_group *grp, mbedtls_mpi *r, mbedtls_mpi *s, + const mbedtls_mpi *d, const unsigned char *buf, size_t blen, + mbedtls_md_type_t md_alg ); +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief This function verifies the ECDSA signature of a + * previously-hashed message. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \see ecp.h + * + * \param grp The ECP group. + * \param buf The message hash. + * \param blen The length of \p buf. + * \param Q The public key to use for verification. + * \param r The first integer of the signature. + * \param s The second integer of the signature. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the signature + * is invalid. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_verify( mbedtls_ecp_group *grp, + const unsigned char *buf, size_t blen, + const mbedtls_ecp_point *Q, const mbedtls_mpi *r, const mbedtls_mpi *s); + +/** + * \brief This function computes the ECDSA signature and writes it + * to a buffer, serialized as defined in RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + * + * \note The deterministic version is used if + * #MBEDTLS_ECDSA_DETERMINISTIC is defined. For more + * information, see RFC-6979: Deterministic Usage + * of the Digital Signature Algorithm (DSA) and Elliptic + * Curve Digital Signature Algorithm (ECDSA). + * + * \note The \p sig buffer must be at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if + * a 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \param ctx The ECDSA context. + * \param md_alg The message digest that was used to hash the message. + * \param hash The message hash. + * \param hlen The length of the hash. + * \param sig The buffer that holds the signature. + * \param slen The length of the signature written. + * \param f_rng The RNG function. + * \param p_rng The RNG context. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature( mbedtls_ecdsa_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_ECDSA_DETERMINISTIC) +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function computes an ECDSA signature and writes + * it to a buffer, serialized as defined in RFC-4492: + * Elliptic Curve Cryptography (ECC) Cipher Suites for + * Transport Layer Security (TLS). + * + * The deterministic version is defined in RFC-6979: + * Deterministic Usage of the Digital Signature Algorithm (DSA) + * and Elliptic Curve Digital Signature Algorithm (ECDSA). + * + * \warning It is not thread-safe to use the same context in + * multiple threads. + * + * \note The \p sig buffer must be at least twice as large as the + * size of the curve used, plus 9. For example, 73 Bytes if a + * 256-bit curve is used. A buffer length of + * #MBEDTLS_ECDSA_MAX_LEN is always safe. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.3, step 5. + * + * \see ecp.h + * + * \deprecated Superseded by mbedtls_ecdsa_write_signature() in + * Mbed TLS version 2.0 and later. + * + * \param ctx The ECDSA context. + * \param hash The message hash. + * \param hlen The length of the hash. + * \param sig The buffer that holds the signature. + * \param slen The length of the signature written. + * \param md_alg The MD algorithm used to hash the message. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX, \c MBEDTLS_ERR_MPI_XXX or + * \c MBEDTLS_ERR_ASN1_XXX error code on failure. + */ +int mbedtls_ecdsa_write_signature_det( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + unsigned char *sig, size_t *slen, + mbedtls_md_type_t md_alg ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ +#endif /* MBEDTLS_ECDSA_DETERMINISTIC */ + +/** + * \brief This function reads and verifies an ECDSA signature. + * + * \note If the bitlength of the message hash is larger than the + * bitlength of the group order, then the hash is truncated as + * defined in Standards for Efficient Cryptography Group + * (SECG): SEC1 Elliptic Curve Cryptography, section + * 4.1.4, step 3. + * + * \see ecp.h + * + * \param ctx The ECDSA context. + * \param hash The message hash. + * \param hlen The size of the hash. + * \param sig The signature to read and verify. + * \param slen The size of \p sig. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if signature is invalid. + * \return #MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH if there is a valid + * signature in \p sig, but its length is less than \p siglen. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_ERR_MPI_XXX + * error code on failure for any other reason. + */ +int mbedtls_ecdsa_read_signature( mbedtls_ecdsa_context *ctx, + const unsigned char *hash, size_t hlen, + const unsigned char *sig, size_t slen ); + +/** + * \brief This function generates an ECDSA keypair on the given curve. + * + * \see ecp.h + * + * \param ctx The ECDSA context to store the keypair in. + * \param gid The elliptic curve to use. One of the various + * \c MBEDTLS_ECP_DP_XXX macros depending on configuration. + * \param f_rng The RNG function. + * \param p_rng The RNG context. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. + */ +int mbedtls_ecdsa_genkey( mbedtls_ecdsa_context *ctx, mbedtls_ecp_group_id gid, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief This function sets an ECDSA context from an EC key pair. + * + * \see ecp.h + * + * \param ctx The ECDSA context to set. + * \param key The EC key to use. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX code on failure. + */ +int mbedtls_ecdsa_from_keypair( mbedtls_ecdsa_context *ctx, const mbedtls_ecp_keypair *key ); + +/** + * \brief This function initializes an ECDSA context. + * + * \param ctx The ECDSA context to initialize. + */ +void mbedtls_ecdsa_init( mbedtls_ecdsa_context *ctx ); + +/** + * \brief This function frees an ECDSA context. + * + * \param ctx The ECDSA context to free. + */ +void mbedtls_ecdsa_free( mbedtls_ecdsa_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* ecdsa.h */ diff --git a/common/mbedtls/ecp.c b/common/mbedtls/ecp.c new file mode 100644 index 000000000..028c7fe30 --- /dev/null +++ b/common/mbedtls/ecp.c @@ -0,0 +1,2209 @@ +/* + * Elliptic curves over GF(p): generic functions + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * References: + * + * SEC1 http://www.secg.org/index.php?action=secg,docs_secg + * GECC = Guide to Elliptic Curve Cryptography - Hankerson, Menezes, Vanstone + * FIPS 186-3 http://csrc.nist.gov/publications/fips/fips186-3/fips_186-3.pdf + * RFC 4492 for the related TLS structures and constants + * RFC 7748 for the Curve448 and Curve25519 curve definitions + * + * [Curve25519] http://cr.yp.to/ecdh/curve25519-20060209.pdf + * + * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECP_C) + +#include "mbedtls/ecp.h" +#include "mbedtls/threading.h" +#include "mbedtls/platform_util.h" + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include "mbedtls/ecp_internal.h" + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * Counts of point addition and doubling, and field multiplications. + * Used to test resistance of point multiplication to simple timing attacks. + */ +static unsigned long add_count, dbl_count, mul_count; +#endif + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +#define ECP_SHORTWEIERSTRASS +#endif + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) || \ + defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +#define ECP_MONTGOMERY +#endif + +/* + * Curve types: internal for now, might be exposed later + */ +typedef enum +{ + ECP_TYPE_NONE = 0, + ECP_TYPE_SHORT_WEIERSTRASS, /* y^2 = x^3 + a x + b */ + ECP_TYPE_MONTGOMERY, /* y^2 = x^3 + a x^2 + x */ +} ecp_curve_type; + +/* + * List of supported curves: + * - internal ID + * - TLS NamedCurve ID (RFC 4492 sec. 5.1.1, RFC 7071 sec. 2) + * - size in bits + * - readable name + * + * Curves are listed in order: largest curves first, and for a given size, + * fastest curves first. This provides the default order for the SSL module. + * + * Reminder: update profiles in x509_crt.c when adding a new curves! + */ +static const mbedtls_ecp_curve_info ecp_supported_curves[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { MBEDTLS_ECP_DP_SECP521R1, 25, 521, "secp521r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { MBEDTLS_ECP_DP_BP512R1, 28, 512, "brainpoolP512r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { MBEDTLS_ECP_DP_SECP384R1, 24, 384, "secp384r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { MBEDTLS_ECP_DP_BP384R1, 27, 384, "brainpoolP384r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { MBEDTLS_ECP_DP_SECP256R1, 23, 256, "secp256r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { MBEDTLS_ECP_DP_SECP256K1, 22, 256, "secp256k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { MBEDTLS_ECP_DP_BP256R1, 26, 256, "brainpoolP256r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { MBEDTLS_ECP_DP_SECP224R1, 21, 224, "secp224r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { MBEDTLS_ECP_DP_SECP224K1, 20, 224, "secp224k1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { MBEDTLS_ECP_DP_SECP192R1, 19, 192, "secp192r1" }, +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { MBEDTLS_ECP_DP_SECP192K1, 18, 192, "secp192k1" }, +#endif + { MBEDTLS_ECP_DP_NONE, 0, 0, NULL }, +}; + +#define ECP_NB_CURVES sizeof( ecp_supported_curves ) / \ + sizeof( ecp_supported_curves[0] ) + +static mbedtls_ecp_group_id ecp_supported_grp_id[ECP_NB_CURVES]; + +/* + * List of supported curves and associated info + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ) +{ + return( ecp_supported_curves ); +} + +/* + * List of supported curves, group ID only + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ) +{ + static int init_done = 0; + + if( ! init_done ) + { + size_t i = 0; + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + ecp_supported_grp_id[i++] = curve_info->grp_id; + } + ecp_supported_grp_id[i] = MBEDTLS_ECP_DP_NONE; + + init_done = 1; + } + + return( ecp_supported_grp_id ); +} + +/* + * Get the curve info for the internal identifier + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->grp_id == grp_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the TLS identifier + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( curve_info->tls_id == tls_id ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the curve info from the name + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ) +{ + const mbedtls_ecp_curve_info *curve_info; + + for( curve_info = mbedtls_ecp_curve_list(); + curve_info->grp_id != MBEDTLS_ECP_DP_NONE; + curve_info++ ) + { + if( strcmp( curve_info->name, name ) == 0 ) + return( curve_info ); + } + + return( NULL ); +} + +/* + * Get the type of a curve + */ +static inline ecp_curve_type ecp_get_type( const mbedtls_ecp_group *grp ) +{ + if( grp->G.X.p == NULL ) + return( ECP_TYPE_NONE ); + + if( grp->G.Y.p == NULL ) + return( ECP_TYPE_MONTGOMERY ); + else + return( ECP_TYPE_SHORT_WEIERSTRASS ); +} + +/* + * Initialize (the components of) a point + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ) +{ + if( pt == NULL ) + return; + + mbedtls_mpi_init( &pt->X ); + mbedtls_mpi_init( &pt->Y ); + mbedtls_mpi_init( &pt->Z ); +} + +/* + * Initialize (the components of) a group + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ) +{ + if( grp == NULL ) + return; + + memset( grp, 0, sizeof( mbedtls_ecp_group ) ); +} + +/* + * Initialize (the components of) a key pair + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ) +{ + if( key == NULL ) + return; + + mbedtls_ecp_group_init( &key->grp ); + mbedtls_mpi_init( &key->d ); + mbedtls_ecp_point_init( &key->Q ); +} + +/* + * Unallocate (the components of) a point + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ) +{ + if( pt == NULL ) + return; + + mbedtls_mpi_free( &( pt->X ) ); + mbedtls_mpi_free( &( pt->Y ) ); + mbedtls_mpi_free( &( pt->Z ) ); +} + +/* + * Unallocate (the components of) a group + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ) +{ + size_t i; + + if( grp == NULL ) + return; + + if( grp->h != 1 ) + { + mbedtls_mpi_free( &grp->P ); + mbedtls_mpi_free( &grp->A ); + mbedtls_mpi_free( &grp->B ); + mbedtls_ecp_point_free( &grp->G ); + mbedtls_mpi_free( &grp->N ); + } + + if( grp->T != NULL ) + { + for( i = 0; i < grp->T_size; i++ ) + mbedtls_ecp_point_free( &grp->T[i] ); + mbedtls_free( grp->T ); + } + + mbedtls_platform_zeroize( grp, sizeof( mbedtls_ecp_group ) ); +} + +/* + * Unallocate (the components of) a key pair + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ) +{ + if( key == NULL ) + return; + + mbedtls_ecp_group_free( &key->grp ); + mbedtls_mpi_free( &key->d ); + mbedtls_ecp_point_free( &key->Q ); +} + +/* + * Copy the contents of a point + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->X, &Q->X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Y, &Q->Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &P->Z, &Q->Z ) ); + +cleanup: + return( ret ); +} + +/* + * Copy the contents of a group object + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ) +{ + return mbedtls_ecp_group_load( dst, src->id ); +} + +/* + * Set point to zero + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->X , 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Y , 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z , 0 ) ); + +cleanup: + return( ret ); +} + +/* + * Tell if a point is zero + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ) +{ + return( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ); +} + +/* + * Compare two points lazyly + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ) +{ + if( mbedtls_mpi_cmp_mpi( &P->X, &Q->X ) == 0 && + mbedtls_mpi_cmp_mpi( &P->Y, &Q->Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->Z, &Q->Z ) == 0 ) + { + return( 0 ); + } + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Import a non-zero point from ASCII strings + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ) +{ + int ret; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->X, radix, x ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &P->Y, radix, y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Export a point into unsigned binary data (SEC1 2.3.3) + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ) +{ + int ret = 0; + size_t plen; + + if( format != MBEDTLS_ECP_PF_UNCOMPRESSED && + format != MBEDTLS_ECP_PF_COMPRESSED ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Common case: P == 0 + */ + if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) + { + if( buflen < 1 ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x00; + *olen = 1; + + return( 0 ); + } + + plen = mbedtls_mpi_size( &grp->P ); + + if( format == MBEDTLS_ECP_PF_UNCOMPRESSED ) + { + *olen = 2 * plen + 1; + + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x04; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->Y, buf + 1 + plen, plen ) ); + } + else if( format == MBEDTLS_ECP_PF_COMPRESSED ) + { + *olen = plen + 1; + + if( buflen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + buf[0] = 0x02 + mbedtls_mpi_get_bit( &P->Y, 0 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &P->X, buf + 1, plen ) ); + } + +cleanup: + return( ret ); +} + +/* + * Import a point from unsigned binary data (SEC1 2.3.4) + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + const unsigned char *buf, size_t ilen ) +{ + int ret; + size_t plen; + + if( ilen < 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( buf[0] == 0x00 ) + { + if( ilen == 1 ) + return( mbedtls_ecp_set_zero( pt ) ); + else + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + plen = mbedtls_mpi_size( &grp->P ); + + if( buf[0] != 0x04 ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + if( ilen != 2 * plen + 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->X, buf + 1, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &pt->Y, buf + 1 + plen, plen ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Import a point from a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + const unsigned char **buf, size_t buf_len ) +{ + unsigned char data_len; + const unsigned char *buf_start; + + /* + * We must have at least two bytes (1 for length, at least one for data) + */ + if( buf_len < 2 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + data_len = *(*buf)++; + if( data_len < 1 || data_len > buf_len - 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Save buffer start for read_binary and update buf + */ + buf_start = *buf; + *buf += data_len; + + return mbedtls_ecp_point_read_binary( grp, pt, buf_start, data_len ); +} + +/* + * Export a point as a TLS ECPoint record (RFC 4492) + * struct { + * opaque point <1..2^8-1>; + * } ECPoint; + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ) +{ + int ret; + + /* + * buffer length must be at least one, for our length byte + */ + if( blen < 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_point_write_binary( grp, pt, format, + olen, buf + 1, blen - 1) ) != 0 ) + return( ret ); + + /* + * write length to the first byte and update total length + */ + buf[0] = (unsigned char) *olen; + ++*olen; + + return( 0 ); +} + +/* + * Set a group from an ECParameters record (RFC 4492) + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ) +{ + uint16_t tls_id; + const mbedtls_ecp_curve_info *curve_info; + + /* + * We expect at least three bytes (see below) + */ + if( len < 3 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * First byte is curve_type; only named_curve is handled + */ + if( *(*buf)++ != MBEDTLS_ECP_TLS_NAMED_CURVE ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Next two bytes are the namedcurve value + */ + tls_id = *(*buf)++; + tls_id <<= 8; + tls_id |= *(*buf)++; + + if( ( curve_info = mbedtls_ecp_curve_info_from_tls_id( tls_id ) ) == NULL ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + return mbedtls_ecp_group_load( grp, curve_info->grp_id ); +} + +/* + * Write the ECParameters record corresponding to a group (RFC 4492) + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen ) +{ + const mbedtls_ecp_curve_info *curve_info; + + if( ( curve_info = mbedtls_ecp_curve_info_from_grp_id( grp->id ) ) == NULL ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * We are going to write 3 bytes (see below) + */ + *olen = 3; + if( blen < *olen ) + return( MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL ); + + /* + * First byte is curve_type, always named_curve + */ + *buf++ = MBEDTLS_ECP_TLS_NAMED_CURVE; + + /* + * Next two bytes are the namedcurve value + */ + buf[0] = curve_info->tls_id >> 8; + buf[1] = curve_info->tls_id & 0xFF; + + return( 0 ); +} + +/* + * Wrapper around fast quasi-modp functions, with fall-back to mbedtls_mpi_mod_mpi. + * See the documentation of struct mbedtls_ecp_group. + * + * This function is in the critial loop for mbedtls_ecp_mul, so pay attention to perf. + */ +static int ecp_modp( mbedtls_mpi *N, const mbedtls_ecp_group *grp ) +{ + int ret; + + if( grp->modp == NULL ) + return( mbedtls_mpi_mod_mpi( N, N, &grp->P ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + if( ( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) || + mbedtls_mpi_bitlen( N ) > 2 * grp->pbits ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + MBEDTLS_MPI_CHK( grp->modp( N ) ); + + /* N->s < 0 is a much faster test, which fails only if N is 0 */ + while( N->s < 0 && mbedtls_mpi_cmp_int( N, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &grp->P ) ); + + while( mbedtls_mpi_cmp_mpi( N, &grp->P ) >= 0 ) + /* we known P, N and the result are positive */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, N, &grp->P ) ); + +cleanup: + return( ret ); +} + +/* + * Fast mod-p functions expect their argument to be in the 0..p^2 range. + * + * In order to guarantee that, we need to ensure that operands of + * mbedtls_mpi_mul_mpi are in the 0..p range. So, after each operation we will + * bring the result back to this range. + * + * The following macros are shortcuts for doing that. + */ + +/* + * Reduce a mbedtls_mpi mod p in-place, general case, to use after mbedtls_mpi_mul_mpi + */ +#if defined(MBEDTLS_SELF_TEST) +#define INC_MUL_COUNT mul_count++; +#else +#define INC_MUL_COUNT +#endif + +#define MOD_MUL( N ) do { MBEDTLS_MPI_CHK( ecp_modp( &N, grp ) ); INC_MUL_COUNT } \ + while( 0 ) + +/* + * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_sub_mpi + * N->s < 0 is a very fast test, which fails only if N is 0 + */ +#define MOD_SUB( N ) \ + while( N.s < 0 && mbedtls_mpi_cmp_int( &N, 0 ) != 0 ) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &N, &N, &grp->P ) ) + +/* + * Reduce a mbedtls_mpi mod p in-place, to use after mbedtls_mpi_add_mpi and mbedtls_mpi_mul_int. + * We known P, N and the result are positive, so sub_abs is correct, and + * a bit faster. + */ +#define MOD_ADD( N ) \ + while( mbedtls_mpi_cmp_mpi( &N, &grp->P ) >= 0 ) \ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( &N, &N, &grp->P ) ) + +#if defined(ECP_SHORTWEIERSTRASS) +/* + * For curves in short Weierstrass form, we do all the internal operations in + * Jacobian coordinates. + * + * For multiplication, we'll use a comb method with coutermeasueres against + * SPA, hence timing attacks. + */ + +/* + * Normalize jacobian coordinates so that Z == 0 || Z == 1 (GECC 3.2.1) + * Cost: 1N := 1I + 3M + 1S + */ +static int ecp_normalize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt ) +{ + int ret; + mbedtls_mpi Zi, ZZi; + + if( mbedtls_mpi_cmp_int( &pt->Z, 0 ) == 0 ) + return( 0 ); + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_normalize_jac( grp, pt ); + } +#endif /* MBEDTLS_ECP_NORMALIZE_JAC_ALT */ + mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); + + /* + * X = X / Z^2 mod p + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &Zi, &pt->Z, &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ZZi ) ); MOD_MUL( pt->X ); + + /* + * Y = Y / Z^3 mod p + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ZZi ) ); MOD_MUL( pt->Y ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &Zi ) ); MOD_MUL( pt->Y ); + + /* + * Z = 1 + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &pt->Z, 1 ) ); + +cleanup: + + mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); + + return( ret ); +} + +/* + * Normalize jacobian coordinates of an array of (pointers to) points, + * using Montgomery's trick to perform only one inversion mod P. + * (See for example Cohen's "A Course in Computational Algebraic Number + * Theory", Algorithm 10.3.4.) + * + * Warning: fails (returning an error) if one of the points is zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * Cost: 1N(t) := 1I + (6t - 3)M + 1S + */ +static int ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], size_t t_len ) +{ + int ret; + size_t i; + mbedtls_mpi *c, u, Zi, ZZi; + + if( t_len < 2 ) + return( ecp_normalize_jac( grp, *T ) ); + +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_normalize_jac_many(grp, T, t_len); + } +#endif + + if( ( c = mbedtls_calloc( t_len, sizeof( mbedtls_mpi ) ) ) == NULL ) + return( MBEDTLS_ERR_ECP_ALLOC_FAILED ); + + mbedtls_mpi_init( &u ); mbedtls_mpi_init( &Zi ); mbedtls_mpi_init( &ZZi ); + + /* + * c[i] = Z_0 * ... * Z_i + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &c[0], &T[0]->Z ) ); + for( i = 1; i < t_len; i++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &c[i], &c[i-1], &T[i]->Z ) ); + MOD_MUL( c[i] ); + } + + /* + * u = 1 / (Z_0 * ... * Z_n) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &u, &c[t_len-1], &grp->P ) ); + + for( i = t_len - 1; ; i-- ) + { + /* + * Zi = 1 / Z_i mod p + * u = 1 / (Z_0 * ... * Z_i) mod P + */ + if( i == 0 ) { + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &Zi, &u ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Zi, &u, &c[i-1] ) ); MOD_MUL( Zi ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &u, &u, &T[i]->Z ) ); MOD_MUL( u ); + } + + /* + * proceed as in normalize() + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ZZi, &Zi, &Zi ) ); MOD_MUL( ZZi ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->X, &T[i]->X, &ZZi ) ); MOD_MUL( T[i]->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &ZZi ) ); MOD_MUL( T[i]->Y ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T[i]->Y, &T[i]->Y, &Zi ) ); MOD_MUL( T[i]->Y ); + + /* + * Post-precessing: reclaim some memory by shrinking coordinates + * - not storing Z (always 1) + * - shrinking other coordinates, but still keeping the same number of + * limbs as P, as otherwise it will too likely be regrown too fast. + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->X, grp->P.n ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shrink( &T[i]->Y, grp->P.n ) ); + mbedtls_mpi_free( &T[i]->Z ); + + if( i == 0 ) + break; + } + +cleanup: + + mbedtls_mpi_free( &u ); mbedtls_mpi_free( &Zi ); mbedtls_mpi_free( &ZZi ); + for( i = 0; i < t_len; i++ ) + mbedtls_mpi_free( &c[i] ); + mbedtls_free( c ); + + return( ret ); +} + +/* + * Conditional point inversion: Q -> -Q = (Q.X, -Q.Y, Q.Z) without leak. + * "inv" must be 0 (don't invert) or 1 (invert) or the result will be invalid + */ +static int ecp_safe_invert_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *Q, + unsigned char inv ) +{ + int ret; + unsigned char nonzero; + mbedtls_mpi mQY; + + mbedtls_mpi_init( &mQY ); + + /* Use the fact that -Q.Y mod P = P - Q.Y unless Q.Y == 0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mQY, &grp->P, &Q->Y ) ); + nonzero = mbedtls_mpi_cmp_int( &Q->Y, 0 ) != 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &Q->Y, &mQY, inv & nonzero ) ); + +cleanup: + mbedtls_mpi_free( &mQY ); + + return( ret ); +} + +/* + * Point doubling R = 2 P, Jacobian coordinates + * + * Based on http://www.hyperelliptic.org/EFD/g1p/auto-shortw-jacobian.html#doubling-dbl-1998-cmo-2 . + * + * We follow the variable naming fairly closely. The formula variations that trade a MUL for a SQR + * (plus a few ADDs) aren't useful as our bignum implementation doesn't distinguish squaring. + * + * Standard optimizations are applied when curve parameter A is one of { 0, -3 }. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + */ +static int ecp_double_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P ) +{ + int ret; + mbedtls_mpi M, S, T, U; + +#if defined(MBEDTLS_SELF_TEST) + dbl_count++; +#endif + +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_double_jac( grp, R, P ); + } +#endif /* MBEDTLS_ECP_DOUBLE_JAC_ALT */ + + mbedtls_mpi_init( &M ); mbedtls_mpi_init( &S ); mbedtls_mpi_init( &T ); mbedtls_mpi_init( &U ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + /* M = 3(X + Z^2)(X - Z^2) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &P->X, &S ) ); MOD_ADD( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &U, &P->X, &S ) ); MOD_SUB( U ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &U ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + } + else + { + /* M = 3.X^2 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &P->X ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &S, 3 ) ); MOD_ADD( M ); + + /* Optimize away for "koblitz" curves with A = 0 */ + if( mbedtls_mpi_cmp_int( &grp->A, 0 ) != 0 ) + { + /* M += A.Z^4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->Z, &P->Z ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &S, &S ) ); MOD_MUL( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &T, &grp->A ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &S ) ); MOD_ADD( M ); + } + } + + /* S = 4.X.Y^2 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &P->Y, &P->Y ) ); MOD_MUL( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &T, 1 ) ); MOD_ADD( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &P->X, &T ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &S, 1 ) ); MOD_ADD( S ); + + /* U = 8.Y^4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &T, &T ) ); MOD_MUL( U ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); + + /* T = M^2 - 2.S */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &M, &M ) ); MOD_MUL( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &T, &S ) ); MOD_SUB( T ); + + /* S = M(S - T) - U */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &T ) ); MOD_SUB( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S, &S, &M ) ); MOD_MUL( S ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S, &S, &U ) ); MOD_SUB( S ); + + /* U = 2.Y.Z */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &U, &P->Y, &P->Z ) ); MOD_MUL( U ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &U, 1 ) ); MOD_ADD( U ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &T ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &S ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &U ) ); + +cleanup: + mbedtls_mpi_free( &M ); mbedtls_mpi_free( &S ); mbedtls_mpi_free( &T ); mbedtls_mpi_free( &U ); + + return( ret ); +} + +/* + * Addition: R = P + Q, mixed affine-Jacobian coordinates (GECC 3.22) + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * Special cases: (1) P or Q is zero, (2) R is zero, (3) P == Q. + * None of these cases can happen as intermediate step in ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base point, the factor + * being less than its order, so none of them is zero; + * - Q is an odd multiple of the base point, P an even multiple, + * due to the choice of precomputed points in the modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as meaning 1. + * + * Cost: 1A := 8M + 3S + */ +static int ecp_add_mixed( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ) +{ + int ret; + mbedtls_mpi T1, T2, T3, T4, X, Y, Z; + +#if defined(MBEDTLS_SELF_TEST) + add_count++; +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_add_mixed( grp, R, P, Q ); + } +#endif /* MBEDTLS_ECP_ADD_MIXED_ALT */ + + /* + * Trivial cases: P == 0 or Q == 0 (case 1) + */ + if( mbedtls_mpi_cmp_int( &P->Z, 0 ) == 0 ) + return( mbedtls_ecp_copy( R, Q ) ); + + if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 0 ) == 0 ) + return( mbedtls_ecp_copy( R, P ) ); + + /* + * Make sure Q coordinates are normalized + */ + if( Q->Z.p != NULL && mbedtls_mpi_cmp_int( &Q->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T1 ); mbedtls_mpi_init( &T2 ); mbedtls_mpi_init( &T3 ); mbedtls_mpi_init( &T4 ); + mbedtls_mpi_init( &X ); mbedtls_mpi_init( &Y ); mbedtls_mpi_init( &Z ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &P->Z, &P->Z ) ); MOD_MUL( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T1, &P->Z ) ); MOD_MUL( T2 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T1, &T1, &Q->X ) ); MOD_MUL( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T2, &T2, &Q->Y ) ); MOD_MUL( T2 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T1, &T1, &P->X ) ); MOD_SUB( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T2, &T2, &P->Y ) ); MOD_SUB( T2 ); + + /* Special cases (2) and (3) */ + if( mbedtls_mpi_cmp_int( &T1, 0 ) == 0 ) + { + if( mbedtls_mpi_cmp_int( &T2, 0 ) == 0 ) + { + ret = ecp_double_jac( grp, R, P ); + goto cleanup; + } + else + { + ret = mbedtls_ecp_set_zero( R ); + goto cleanup; + } + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &Z, &P->Z, &T1 ) ); MOD_MUL( Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T1, &T1 ) ); MOD_MUL( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T3, &T1 ) ); MOD_MUL( T4 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &P->X ) ); MOD_MUL( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &T1, &T3, 2 ) ); MOD_ADD( T1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &X, &T2, &T2 ) ); MOD_MUL( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T1 ) ); MOD_SUB( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &X, &X, &T4 ) ); MOD_SUB( X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T3, &T3, &X ) ); MOD_SUB( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T3, &T3, &T2 ) ); MOD_MUL( T3 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T4, &T4, &P->Y ) ); MOD_MUL( T4 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &Y, &T3, &T4 ) ); MOD_SUB( Y ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->X, &X ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Y, &Y ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &R->Z, &Z ) ); + +cleanup: + + mbedtls_mpi_free( &T1 ); mbedtls_mpi_free( &T2 ); mbedtls_mpi_free( &T3 ); mbedtls_mpi_free( &T4 ); + mbedtls_mpi_free( &X ); mbedtls_mpi_free( &Y ); mbedtls_mpi_free( &Z ); + + return( ret ); +} + +/* + * Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_jac(). + * + * This countermeasure was first suggested in [2]. + */ +static int ecp_randomize_jac( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_mpi l, ll; + size_t p_size; + int count = 0; + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_randomize_jac( grp, pt, f_rng, p_rng ); + } +#endif /* MBEDTLS_ECP_RANDOMIZE_JAC_ALT */ + + p_size = ( grp->pbits + 7 ) / 8; + mbedtls_mpi_init( &l ); mbedtls_mpi_init( &ll ); + + /* Generate l such that 1 < l < p */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + } + while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); + + /* Z = l * Z */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Z, &pt->Z, &l ) ); MOD_MUL( pt->Z ); + + /* X = l^2 * X */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &l, &l ) ); MOD_MUL( ll ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->X, &pt->X, &ll ) ); MOD_MUL( pt->X ); + + /* Y = l^3 * Y */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ll, &ll, &l ) ); MOD_MUL( ll ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &pt->Y, &pt->Y, &ll ) ); MOD_MUL( pt->Y ); + +cleanup: + mbedtls_mpi_free( &l ); mbedtls_mpi_free( &ll ); + + return( ret ); +} + +/* + * Check and define parameters used by the comb method (see below for details) + */ +#if MBEDTLS_ECP_WINDOW_SIZE < 2 || MBEDTLS_ECP_WINDOW_SIZE > 7 +#error "MBEDTLS_ECP_WINDOW_SIZE out of bounds" +#endif + +/* d = ceil( n / w ) */ +#define COMB_MAX_D ( MBEDTLS_ECP_MAX_BITS + 1 ) / 2 + +/* number of precomputed points */ +#define COMB_MAX_PRE ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + +/* + * Compute the representation of m that will be used with our comb method. + * + * The basic comb method is described in GECC 3.44 for example. We use a + * modified version that provides resistance to SPA by avoiding zero + * digits in the representation as in [3]. We modify the method further by + * requiring that all K_i be odd, which has the small cost that our + * representation uses one more K_i, due to carries. + * + * Also, for the sake of compactness, only the seven low-order bits of x[i] + * are used to represent K_i, and the msb of x[i] encodes the the sign (s_i in + * the paper): it is set if and only if if s_i == -1; + * + * Calling conventions: + * - x is an array of size d + 1 + * - w is the size, ie number of teeth, of the comb, and must be between + * 2 and 7 (in practice, between 2 and MBEDTLS_ECP_WINDOW_SIZE) + * - m is the MPI, expected to be odd and such that bitlength(m) <= w * d + * (the result will be incorrect if these assumptions are not satisfied) + */ +static void ecp_comb_fixed( unsigned char x[], size_t d, + unsigned char w, const mbedtls_mpi *m ) +{ + size_t i, j; + unsigned char c, cc, adjust; + + memset( x, 0, d+1 ); + + /* First get the classical comb values (except for x_d = 0) */ + for( i = 0; i < d; i++ ) + for( j = 0; j < w; j++ ) + x[i] |= mbedtls_mpi_get_bit( m, i + d * j ) << j; + + /* Now make sure x_1 .. x_d are odd */ + c = 0; + for( i = 1; i <= d; i++ ) + { + /* Add carry and update it */ + cc = x[i] & c; + x[i] = x[i] ^ c; + c = cc; + + /* Adjust if needed, avoiding branches */ + adjust = 1 - ( x[i] & 0x01 ); + c |= x[i] & ( x[i-1] * adjust ); + x[i] = x[i] ^ ( x[i-1] * adjust ); + x[i-1] |= adjust << 7; + } +} + +/* + * Precompute points for the comb method + * + * If i = i_{w-1} ... i_1 is the binary representation of i, then + * T[i] = i_{w-1} 2^{(w-1)d} P + ... + i_1 2^d P + P + * + * T must be able to hold 2^{w - 1} elements + * + * Cost: d(w-1) D + (2^{w-1} - 1) A + 1 N(w-1) + 1 N(2^{w-1} - 1) + */ +static int ecp_precompute_comb( const mbedtls_ecp_group *grp, + mbedtls_ecp_point T[], const mbedtls_ecp_point *P, + unsigned char w, size_t d ) +{ + int ret; + unsigned char i, k; + size_t j; + mbedtls_ecp_point *cur, *TT[COMB_MAX_PRE - 1]; + + /* + * Set T[0] = P and + * T[2^{l-1}] = 2^{dl} P for l = 1 .. w-1 (this is not the final value) + */ + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &T[0], P ) ); + + k = 0; + for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + { + cur = T + i; + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( cur, T + ( i >> 1 ) ) ); + for( j = 0; j < d; j++ ) + MBEDTLS_MPI_CHK( ecp_double_jac( grp, cur, cur ) ); + + TT[k++] = cur; + } + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); + + /* + * Compute the remaining ones using the minimal number of additions + * Be careful to update T[2^l] only after using it! + */ + k = 0; + for( i = 1; i < ( 1U << ( w - 1 ) ); i <<= 1 ) + { + j = i; + while( j-- ) + { + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, &T[i + j], &T[j], &T[i] ) ); + TT[k++] = &T[i + j]; + } + } + + MBEDTLS_MPI_CHK( ecp_normalize_jac_many( grp, TT, k ) ); + +cleanup: + + return( ret ); +} + +/* + * Select precomputed point: R = sign(i) * T[ abs(i) / 2 ] + */ +static int ecp_select_comb( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point T[], unsigned char t_len, + unsigned char i ) +{ + int ret; + unsigned char ii, j; + + /* Ignore the "sign" bit and scale down */ + ii = ( i & 0x7Fu ) >> 1; + + /* Read the whole table to thwart cache-based timing attacks */ + for( j = 0; j < t_len; j++ ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->X, &T[j].X, j == ii ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &R->Y, &T[j].Y, j == ii ) ); + } + + /* Safely invert result if i is "negative" */ + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, i >> 7 ) ); + +cleanup: + return( ret ); +} + +/* + * Core multiplication algorithm for the (modified) comb method. + * This part is actually common with the basic comb method (GECC 3.44) + * + * Cost: d A + d D + 1 R + */ +static int ecp_mul_comb_core( const mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_ecp_point T[], unsigned char t_len, + const unsigned char x[], size_t d, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + mbedtls_ecp_point Txi; + size_t i; + + mbedtls_ecp_point_init( &Txi ); + + /* Start with a non-zero point and randomize its coordinates */ + i = d; + MBEDTLS_MPI_CHK( ecp_select_comb( grp, R, T, t_len, x[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 1 ) ); + if( f_rng != 0 ) + MBEDTLS_MPI_CHK( ecp_randomize_jac( grp, R, f_rng, p_rng ) ); + + while( i-- != 0 ) + { + MBEDTLS_MPI_CHK( ecp_double_jac( grp, R, R ) ); + MBEDTLS_MPI_CHK( ecp_select_comb( grp, &Txi, T, t_len, x[i] ) ); + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, R, &Txi ) ); + } + +cleanup: + + mbedtls_ecp_point_free( &Txi ); + + return( ret ); +} + +/* + * Multiplication using the comb method, + * for curves in short Weierstrass form + */ +static int ecp_mul_comb( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + unsigned char w, m_is_odd, p_eq_g, pre_len, i; + size_t d; + unsigned char k[COMB_MAX_D + 1]; + mbedtls_ecp_point *T; + mbedtls_mpi M, mm; + + mbedtls_mpi_init( &M ); + mbedtls_mpi_init( &mm ); + + /* we need N to be odd to trnaform m in an odd number, check now */ + if( mbedtls_mpi_get_bit( &grp->N, 0 ) != 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + /* + * Minimize the number of multiplications, that is minimize + * 10 * d * w + 18 * 2^(w-1) + 11 * d + 7 * w, with d = ceil( nbits / w ) + * (see costs of the various parts, with 1S = 1M) + */ + w = grp->nbits >= 384 ? 5 : 4; + + /* + * If P == G, pre-compute a bit more, since this may be re-used later. + * Just adding one avoids upping the cost of the first mul too much, + * and the memory cost too. + */ +#if MBEDTLS_ECP_FIXED_POINT_OPTIM == 1 + p_eq_g = ( mbedtls_mpi_cmp_mpi( &P->Y, &grp->G.Y ) == 0 && + mbedtls_mpi_cmp_mpi( &P->X, &grp->G.X ) == 0 ); + if( p_eq_g ) + w++; +#else + p_eq_g = 0; +#endif + + /* + * Make sure w is within bounds. + * (The last test is useful only for very small curves in the test suite.) + */ + if( w > MBEDTLS_ECP_WINDOW_SIZE ) + w = MBEDTLS_ECP_WINDOW_SIZE; + if( w >= grp->nbits ) + w = 2; + + /* Other sizes that depend on w */ + pre_len = 1U << ( w - 1 ); + d = ( grp->nbits + w - 1 ) / w; + + /* + * Prepare precomputed points: if P == G we want to + * use grp->T if already initialized, or initialize it. + */ + T = p_eq_g ? grp->T : NULL; + + if( T == NULL ) + { + T = mbedtls_calloc( pre_len, sizeof( mbedtls_ecp_point ) ); + if( T == NULL ) + { + ret = MBEDTLS_ERR_ECP_ALLOC_FAILED; + goto cleanup; + } + + MBEDTLS_MPI_CHK( ecp_precompute_comb( grp, T, P, w, d ) ); + + if( p_eq_g ) + { + grp->T = T; + grp->T_size = pre_len; + } + } + + /* + * Make sure M is odd (M = m or M = N - m, since N is odd) + * using the fact that m * P = - (N - m) * P + */ + m_is_odd = ( mbedtls_mpi_get_bit( m, 0 ) == 1 ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &M, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &mm, &grp->N, m ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_assign( &M, &mm, ! m_is_odd ) ); + + /* + * Go for comb multiplication, R = M * P + */ + ecp_comb_fixed( k, d, w, &M ); + MBEDTLS_MPI_CHK( ecp_mul_comb_core( grp, R, T, pre_len, k, d, f_rng, p_rng ) ); + + /* + * Now get m * P from M * P and normalize it + */ + MBEDTLS_MPI_CHK( ecp_safe_invert_jac( grp, R, ! m_is_odd ) ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); + +cleanup: + + /* There are two cases where T is not stored in grp: + * - P != G + * - An intermediate operation failed before setting grp->T + * In either case, T must be freed. + */ + if( T != NULL && T != grp->T ) + { + for( i = 0; i < pre_len; i++ ) + mbedtls_ecp_point_free( &T[i] ); + mbedtls_free( T ); + } + + mbedtls_mpi_free( &M ); + mbedtls_mpi_free( &mm ); + + if( ret != 0 ) + mbedtls_ecp_point_free( R ); + + return( ret ); +} + +#endif /* ECP_SHORTWEIERSTRASS */ + +#if defined(ECP_MONTGOMERY) +/* + * For Montgomery curves, we do all the internal arithmetic in projective + * coordinates. Import/export of points uses only the x coordinates, which is + * internaly represented as X / Z. + * + * For scalar multiplication, we'll use a Montgomery ladder. + */ + +/* + * Normalize Montgomery x/z coordinates: X = X/Z, Z = 1 + * Cost: 1M + 1I + */ +static int ecp_normalize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P ) +{ + int ret; + +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_normalize_mxz( grp, P ); + } +#endif /* MBEDTLS_ECP_NORMALIZE_MXZ_ALT */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &P->Z, &P->Z, &grp->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &P->Z ) ); MOD_MUL( P->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &P->Z, 1 ) ); + +cleanup: + return( ret ); +} + +/* + * Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * This is sort of the reverse operation of ecp_normalize_mxz(). + * + * This countermeasure was first suggested in [2]. + * Cost: 2M + */ +static int ecp_randomize_mxz( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_mpi l; + size_t p_size; + int count = 0; + +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_randomize_mxz( grp, P, f_rng, p_rng ); + } +#endif /* MBEDTLS_ECP_RANDOMIZE_MXZ_ALT */ + + p_size = ( grp->pbits + 7 ) / 8; + mbedtls_mpi_init( &l ); + + /* Generate l such that 1 < l < p */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &l, p_size, f_rng, p_rng ) ); + + while( mbedtls_mpi_cmp_mpi( &l, &grp->P ) >= 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &l, 1 ) ); + + if( count++ > 10 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + } + while( mbedtls_mpi_cmp_int( &l, 1 ) <= 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->X, &P->X, &l ) ); MOD_MUL( P->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &P->Z, &P->Z, &l ) ); MOD_MUL( P->Z ); + +cleanup: + mbedtls_mpi_free( &l ); + + return( ret ); +} + +/* + * Double-and-add: R = 2P, S = P + Q, with d = X(P - Q), + * for Montgomery curves in x/z coordinates. + * + * http://www.hyperelliptic.org/EFD/g1p/auto-code/montgom/xz/ladder/mladd-1987-m.op3 + * with + * d = X1 + * P = (X2, Z2) + * Q = (X3, Z3) + * R = (X4, Z4) + * S = (X5, Z5) + * and eliminating temporary variables tO, ..., t4. + * + * Cost: 5M + 4S + */ +static int ecp_double_add_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, mbedtls_ecp_point *S, + const mbedtls_ecp_point *P, const mbedtls_ecp_point *Q, + const mbedtls_mpi *d ) +{ + int ret; + mbedtls_mpi A, AA, B, BB, E, C, D, DA, CB; + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) + if ( mbedtls_internal_ecp_grp_capable( grp ) ) + { + return mbedtls_internal_ecp_double_add_mxz( grp, R, S, P, Q, d ); + } +#endif /* MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT */ + + mbedtls_mpi_init( &A ); mbedtls_mpi_init( &AA ); mbedtls_mpi_init( &B ); + mbedtls_mpi_init( &BB ); mbedtls_mpi_init( &E ); mbedtls_mpi_init( &C ); + mbedtls_mpi_init( &D ); mbedtls_mpi_init( &DA ); mbedtls_mpi_init( &CB ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &A, &P->X, &P->Z ) ); MOD_ADD( A ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &AA, &A, &A ) ); MOD_MUL( AA ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &B, &P->X, &P->Z ) ); MOD_SUB( B ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &BB, &B, &B ) ); MOD_MUL( BB ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &E, &AA, &BB ) ); MOD_SUB( E ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &C, &Q->X, &Q->Z ) ); MOD_ADD( C ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &D, &Q->X, &Q->Z ) ); MOD_SUB( D ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DA, &D, &A ) ); MOD_MUL( DA ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &CB, &C, &B ) ); MOD_MUL( CB ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &S->X, &DA, &CB ) ); MOD_MUL( S->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->X, &S->X, &S->X ) ); MOD_MUL( S->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &S->Z, &DA, &CB ) ); MOD_SUB( S->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, &S->Z, &S->Z ) ); MOD_MUL( S->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &S->Z, d, &S->Z ) ); MOD_MUL( S->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->X, &AA, &BB ) ); MOD_MUL( R->X ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &grp->A, &E ) ); MOD_MUL( R->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &R->Z, &BB, &R->Z ) ); MOD_ADD( R->Z ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &R->Z, &E, &R->Z ) ); MOD_MUL( R->Z ); + +cleanup: + mbedtls_mpi_free( &A ); mbedtls_mpi_free( &AA ); mbedtls_mpi_free( &B ); + mbedtls_mpi_free( &BB ); mbedtls_mpi_free( &E ); mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &D ); mbedtls_mpi_free( &DA ); mbedtls_mpi_free( &CB ); + + return( ret ); +} + +/* + * Multiplication with Montgomery ladder in x/z coordinates, + * for curves in Montgomery form + */ +static int ecp_mul_mxz( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t i; + unsigned char b; + mbedtls_ecp_point RP; + mbedtls_mpi PX; + + mbedtls_ecp_point_init( &RP ); mbedtls_mpi_init( &PX ); + + /* Save PX and read from P before writing to R, in case P == R */ + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &PX, &P->X ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( &RP, P ) ); + + /* Set R to zero in modified x/z coordinates */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->X, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &R->Z, 0 ) ); + mbedtls_mpi_free( &R->Y ); + + /* RP.X might be sligtly larger than P, so reduce it */ + MOD_ADD( RP.X ); + + /* Randomize coordinates of the starting point */ + if( f_rng != NULL ) + MBEDTLS_MPI_CHK( ecp_randomize_mxz( grp, &RP, f_rng, p_rng ) ); + + /* Loop invariant: R = result so far, RP = R + P */ + i = mbedtls_mpi_bitlen( m ); /* one past the (zero-based) most significant bit */ + while( i-- > 0 ) + { + b = mbedtls_mpi_get_bit( m, i ); + /* + * if (b) R = 2R + P else R = 2R, + * which is: + * if (b) double_add( RP, R, RP, R ) + * else double_add( R, RP, R, RP ) + * but using safe conditional swaps to avoid leaks + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + MBEDTLS_MPI_CHK( ecp_double_add_mxz( grp, R, &RP, R, &RP, &PX ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->X, &RP.X, b ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_safe_cond_swap( &R->Z, &RP.Z, b ) ); + } + + MBEDTLS_MPI_CHK( ecp_normalize_mxz( grp, R ) ); + +cleanup: + mbedtls_ecp_point_free( &RP ); mbedtls_mpi_free( &PX ); + + return( ret ); +} + +#endif /* ECP_MONTGOMERY */ + +/* + * Multiplication R = m * P + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + + /* Common sanity checks */ + if( mbedtls_mpi_cmp_int( &P->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_ecp_check_privkey( grp, m ) ) != 0 || + ( ret = mbedtls_ecp_check_pubkey( grp, P ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) + { + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); + } + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + ret = ecp_mul_mxz( grp, R, m, P, f_rng, p_rng ); + +#endif +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + ret = ecp_mul_comb( grp, R, m, P, f_rng, p_rng ); + +#endif +#if defined(MBEDTLS_ECP_INTERNAL_ALT) +cleanup: + + if ( is_grp_capable ) + { + mbedtls_internal_ecp_free( grp ); + } + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + return( ret ); +} + +#if defined(ECP_SHORTWEIERSTRASS) +/* + * Check that an affine point is valid as a public key, + * short weierstrass curves (SEC1 3.2.3.1) + */ +static int ecp_check_pubkey_sw( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + int ret; + mbedtls_mpi YY, RHS; + + /* pt coordinates must be normalized for our checks */ + if( mbedtls_mpi_cmp_int( &pt->X, 0 ) < 0 || + mbedtls_mpi_cmp_int( &pt->Y, 0 ) < 0 || + mbedtls_mpi_cmp_mpi( &pt->X, &grp->P ) >= 0 || + mbedtls_mpi_cmp_mpi( &pt->Y, &grp->P ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + mbedtls_mpi_init( &YY ); mbedtls_mpi_init( &RHS ); + + /* + * YY = Y^2 + * RHS = X (X^2 + A) + B = X^3 + A X + B + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &YY, &pt->Y, &pt->Y ) ); MOD_MUL( YY ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &pt->X, &pt->X ) ); MOD_MUL( RHS ); + + /* Special case for A = -3 */ + if( grp->A.p == NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &RHS, &RHS, 3 ) ); MOD_SUB( RHS ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->A ) ); MOD_ADD( RHS ); + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &RHS, &RHS, &pt->X ) ); MOD_MUL( RHS ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &RHS, &RHS, &grp->B ) ); MOD_ADD( RHS ); + + if( mbedtls_mpi_cmp_mpi( &YY, &RHS ) != 0 ) + ret = MBEDTLS_ERR_ECP_INVALID_KEY; + +cleanup: + + mbedtls_mpi_free( &YY ); mbedtls_mpi_free( &RHS ); + + return( ret ); +} +#endif /* ECP_SHORTWEIERSTRASS */ + +/* + * R = m * P with shortcuts for m == 1 and m == -1 + * NOT constant-time - ONLY for short Weierstrass! + */ +static int mbedtls_ecp_mul_shortcuts( mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, + const mbedtls_mpi *m, + const mbedtls_ecp_point *P ) +{ + int ret; + + if( mbedtls_mpi_cmp_int( m, 1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); + } + else if( mbedtls_mpi_cmp_int( m, -1 ) == 0 ) + { + MBEDTLS_MPI_CHK( mbedtls_ecp_copy( R, P ) ); + if( mbedtls_mpi_cmp_int( &R->Y, 0 ) != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &R->Y, &grp->P, &R->Y ) ); + } + else + { + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( grp, R, m, P, NULL, NULL ) ); + } + +cleanup: + return( ret ); +} + +/* + * Linear combination + * NOT constant-time + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ) +{ + int ret; + mbedtls_ecp_point mP; +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + char is_grp_capable = 0; +#endif + + if( ecp_get_type( grp ) != ECP_TYPE_SHORT_WEIERSTRASS ) + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + + mbedtls_ecp_point_init( &mP ); + + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, &mP, m, P ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul_shortcuts( grp, R, n, Q ) ); + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if ( is_grp_capable = mbedtls_internal_ecp_grp_capable( grp ) ) + { + MBEDTLS_MPI_CHK( mbedtls_internal_ecp_init( grp ) ); + } + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + MBEDTLS_MPI_CHK( ecp_add_mixed( grp, R, &mP, R ) ); + MBEDTLS_MPI_CHK( ecp_normalize_jac( grp, R ) ); + +cleanup: + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + if ( is_grp_capable ) + { + mbedtls_internal_ecp_free( grp ); + } + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + mbedtls_ecp_point_free( &mP ); + + return( ret ); +} + + +#if defined(ECP_MONTGOMERY) +/* + * Check validity of a public key for Montgomery curves with x-only schemes + */ +static int ecp_check_pubkey_mx( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + /* [Curve25519 p. 5] Just check X is the correct number of bytes */ + /* Allow any public value, if it's too big then we'll just reduce it mod p + * (RFC 7748 sec. 5 para. 3). */ + if( mbedtls_mpi_size( &pt->X ) > ( grp->nbits + 7 ) / 8 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + return( 0 ); +} +#endif /* ECP_MONTGOMERY */ + +/* + * Check that a point is valid as a public key + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ) +{ + /* Must use affine coordinates */ + if( mbedtls_mpi_cmp_int( &pt->Z, 1 ) != 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + return( ecp_check_pubkey_mx( grp, pt ) ); +#endif +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + return( ecp_check_pubkey_sw( grp, pt ) ); +#endif + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Check that an mbedtls_mpi is valid as a private key + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ) +{ +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + { + /* see RFC 7748 sec. 5 para. 5 */ + if( mbedtls_mpi_get_bit( d, 0 ) != 0 || + mbedtls_mpi_get_bit( d, 1 ) != 0 || + mbedtls_mpi_bitlen( d ) - 1 != grp->nbits ) /* mbedtls_mpi_bitlen is one-based! */ + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + /* see [Curve25519] page 5 */ + if( grp->nbits == 254 && mbedtls_mpi_get_bit( d, 2 ) != 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + + return( 0 ); + } +#endif /* ECP_MONTGOMERY */ +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* see SEC1 3.2 */ + if( mbedtls_mpi_cmp_int( d, 1 ) < 0 || + mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ) + return( MBEDTLS_ERR_ECP_INVALID_KEY ); + else + return( 0 ); + } +#endif /* ECP_SHORTWEIERSTRASS */ + + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); +} + +/* + * Generate a keypair with configurable base point + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret; + size_t n_size = ( grp->nbits + 7 ) / 8; + +#if defined(ECP_MONTGOMERY) + if( ecp_get_type( grp ) == ECP_TYPE_MONTGOMERY ) + { + /* [M225] page 5 */ + size_t b; + + do { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); + } while( mbedtls_mpi_bitlen( d ) == 0); + + /* Make sure the most significant bit is nbits */ + b = mbedtls_mpi_bitlen( d ) - 1; /* mbedtls_mpi_bitlen is one-based */ + if( b > grp->nbits ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, b - grp->nbits ) ); + else + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, grp->nbits, 1 ) ); + + /* Make sure the last two bits are unset for Curve448, three bits for + Curve25519 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 0, 0 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 1, 0 ) ); + if( grp->nbits == 254 ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( d, 2, 0 ) ); + } + } + else +#endif /* ECP_MONTGOMERY */ +#if defined(ECP_SHORTWEIERSTRASS) + if( ecp_get_type( grp ) == ECP_TYPE_SHORT_WEIERSTRASS ) + { + /* SEC1 3.2.1: Generate d such that 1 <= n < N */ + int count = 0; + + /* + * Match the procedure given in RFC 6979 (deterministic ECDSA): + * - use the same byte ordering; + * - keep the leftmost nbits bits of the generated octet string; + * - try until result is in the desired range. + * This also avoids any biais, which is especially important for ECDSA. + */ + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( d, n_size, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( d, 8 * n_size - grp->nbits ) ); + + /* + * Each try has at worst a probability 1/2 of failing (the msb has + * a probability 1/2 of being 0, and then the result will be < N), + * so after 30 tries failure probability is a most 2**(-30). + * + * For most curves, 1 try is enough with overwhelming probability, + * since N starts with a lot of 1s in binary, but some curves + * such as secp224k1 are actually very close to the worst case. + */ + if( ++count > 30 ) + return( MBEDTLS_ERR_ECP_RANDOM_FAILED ); + } + while( mbedtls_mpi_cmp_int( d, 1 ) < 0 || + mbedtls_mpi_cmp_mpi( d, &grp->N ) >= 0 ); + } + else +#endif /* ECP_SHORTWEIERSTRASS */ + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + +cleanup: + if( ret != 0 ) + return( ret ); + + return( mbedtls_ecp_mul( grp, Q, d, G, f_rng, p_rng ) ); +} + +/* + * Generate key pair, wrapper for conventional base point + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + return( mbedtls_ecp_gen_keypair_base( grp, &grp->G, d, Q, f_rng, p_rng ) ); +} + +/* + * Generate a keypair, prettier wrapper + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + + if( ( ret = mbedtls_ecp_group_load( &key->grp, grp_id ) ) != 0 ) + return( ret ); + + return( mbedtls_ecp_gen_keypair( &key->grp, &key->d, &key->Q, f_rng, p_rng ) ); +} + +/* + * Check a public-private key pair + */ +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ) +{ + int ret; + mbedtls_ecp_point Q; + mbedtls_ecp_group grp; + + if( pub->grp.id == MBEDTLS_ECP_DP_NONE || + pub->grp.id != prv->grp.id || + mbedtls_mpi_cmp_mpi( &pub->Q.X, &prv->Q.X ) || + mbedtls_mpi_cmp_mpi( &pub->Q.Y, &prv->Q.Y ) || + mbedtls_mpi_cmp_mpi( &pub->Q.Z, &prv->Q.Z ) ) + { + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + } + + mbedtls_ecp_point_init( &Q ); + mbedtls_ecp_group_init( &grp ); + + /* mbedtls_ecp_mul() needs a non-const group... */ + mbedtls_ecp_group_copy( &grp, &prv->grp ); + + /* Also checks d is valid */ + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &Q, &prv->d, &prv->grp.G, NULL, NULL ) ); + + if( mbedtls_mpi_cmp_mpi( &Q.X, &prv->Q.X ) || + mbedtls_mpi_cmp_mpi( &Q.Y, &prv->Q.Y ) || + mbedtls_mpi_cmp_mpi( &Q.Z, &prv->Q.Z ) ) + { + ret = MBEDTLS_ERR_ECP_BAD_INPUT_DATA; + goto cleanup; + } + +cleanup: + mbedtls_ecp_point_free( &Q ); + mbedtls_ecp_group_free( &grp ); + + return( ret ); +} + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Checkup routine + */ +int mbedtls_ecp_self_test( int verbose ) +{ + int ret; + size_t i; + mbedtls_ecp_group grp; + mbedtls_ecp_point R, P; + mbedtls_mpi m; + unsigned long add_c_prev, dbl_c_prev, mul_c_prev; + /* exponents especially adapted for secp192r1 */ + const char *exponents[] = + { + "000000000000000000000000000000000000000000000001", /* one */ + "FFFFFFFFFFFFFFFFFFFFFFFF99DEF836146BC9B1B4D22830", /* N - 1 */ + "5EA6F389A38B8BC81E767753B15AA5569E1782E30ABE7D25", /* random */ + "400000000000000000000000000000000000000000000000", /* one and zeros */ + "7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF", /* all ones */ + "555555555555555555555555555555555555555555555555", /* 101010... */ + }; + + mbedtls_ecp_group_init( &grp ); + mbedtls_ecp_point_init( &R ); + mbedtls_ecp_point_init( &P ); + mbedtls_mpi_init( &m ); + + /* Use secp192r1 if available, or any available curve */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, MBEDTLS_ECP_DP_SECP192R1 ) ); +#else + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &grp, mbedtls_ecp_curve_list()->grp_id ) ); +#endif + + if( verbose != 0 ) + mbedtls_printf( " ECP test #1 (constant op_count, base point G): " ); + + /* Do a dummy multiplication first to trigger precomputation */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &m, 2 ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &P, &m, &grp.G, NULL, NULL ) ); + + add_count = 0; + dbl_count = 0; + mul_count = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); + + for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) + { + add_c_prev = add_count; + dbl_c_prev = dbl_count; + mul_c_prev = mul_count; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &grp.G, NULL, NULL ) ); + + if( add_count != add_c_prev || + dbl_count != dbl_c_prev || + mul_count != mul_c_prev ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (%u)\n", (unsigned int) i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " ECP test #2 (constant op_count, other point): " ); + /* We computed P = 2G last time, use it */ + + add_count = 0; + dbl_count = 0; + mul_count = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[0] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); + + for( i = 1; i < sizeof( exponents ) / sizeof( exponents[0] ); i++ ) + { + add_c_prev = add_count; + dbl_c_prev = dbl_count; + mul_c_prev = mul_count; + add_count = 0; + dbl_count = 0; + mul_count = 0; + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &m, 16, exponents[i] ) ); + MBEDTLS_MPI_CHK( mbedtls_ecp_mul( &grp, &R, &m, &P, NULL, NULL ) ); + + if( add_count != add_c_prev || + dbl_count != dbl_c_prev || + mul_count != mul_c_prev ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (%u)\n", (unsigned int) i ); + + ret = 1; + goto cleanup; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +cleanup: + + if( ret < 0 && verbose != 0 ) + mbedtls_printf( "Unexpected error, return code = %08X\n", ret ); + + mbedtls_ecp_group_free( &grp ); + mbedtls_ecp_point_free( &R ); + mbedtls_ecp_point_free( &P ); + mbedtls_mpi_free( &m ); + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* !MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_C */ diff --git a/common/mbedtls/ecp.h b/common/mbedtls/ecp.h new file mode 100644 index 000000000..1821a72f8 --- /dev/null +++ b/common/mbedtls/ecp.h @@ -0,0 +1,766 @@ +/** + * \file ecp.h + * + * \brief This file provides an API for Elliptic Curves over GF(P) (ECP). + * + * The use of ECP in cryptography and TLS is defined in + * Standards for Efficient Cryptography Group (SECG): SEC1 + * Elliptic Curve Cryptography and + * RFC-4492: Elliptic Curve Cryptography (ECC) Cipher Suites + * for Transport Layer Security (TLS). + * + * RFC-2409: The Internet Key Exchange (IKE) defines ECP + * group types. + * + */ + +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_ECP_H +#define MBEDTLS_ECP_H + +#include "bignum.h" + +/* + * ECP error codes + */ +#define MBEDTLS_ERR_ECP_BAD_INPUT_DATA -0x4F80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL -0x4F00 /**< The buffer is too small to write to. */ +#define MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE -0x4E80 /**< The requested feature is not available, for example, the requested curve is not supported. */ +#define MBEDTLS_ERR_ECP_VERIFY_FAILED -0x4E00 /**< The signature is not valid. */ +#define MBEDTLS_ERR_ECP_ALLOC_FAILED -0x4D80 /**< Memory allocation failed. */ +#define MBEDTLS_ERR_ECP_RANDOM_FAILED -0x4D00 /**< Generation of random value, such as ephemeral key, failed. */ +#define MBEDTLS_ERR_ECP_INVALID_KEY -0x4C80 /**< Invalid private or public key. */ +#define MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH -0x4C00 /**< The buffer contains a valid signature followed by more data. */ +#define MBEDTLS_ERR_ECP_HW_ACCEL_FAILED -0x4B80 /**< The ECP hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Domain-parameter identifiers: curve, subgroup, and generator. + * + * \note Only curves over prime fields are supported. + * + * \warning This library does not support validation of arbitrary domain + * parameters. Therefore, only standardized domain parameters from trusted + * sources should be used. See mbedtls_ecp_group_load(). + */ +typedef enum +{ + MBEDTLS_ECP_DP_NONE = 0, /*!< Curve not defined. */ + MBEDTLS_ECP_DP_SECP192R1, /*!< Domain parameters for the 192-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP224R1, /*!< Domain parameters for the 224-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP256R1, /*!< Domain parameters for the 256-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP384R1, /*!< Domain parameters for the 384-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_SECP521R1, /*!< Domain parameters for the 521-bit curve defined by FIPS 186-4 and SEC1. */ + MBEDTLS_ECP_DP_BP256R1, /*!< Domain parameters for 256-bit Brainpool curve. */ + MBEDTLS_ECP_DP_BP384R1, /*!< Domain parameters for 384-bit Brainpool curve. */ + MBEDTLS_ECP_DP_BP512R1, /*!< Domain parameters for 512-bit Brainpool curve. */ + MBEDTLS_ECP_DP_CURVE25519, /*!< Domain parameters for Curve25519. */ + MBEDTLS_ECP_DP_SECP192K1, /*!< Domain parameters for 192-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_SECP224K1, /*!< Domain parameters for 224-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_SECP256K1, /*!< Domain parameters for 256-bit "Koblitz" curve. */ + MBEDTLS_ECP_DP_CURVE448, /*!< Domain parameters for Curve448. */ +} mbedtls_ecp_group_id; + +/** + * The number of supported curves, plus one for #MBEDTLS_ECP_DP_NONE. + * + * \note Montgomery curves are currently excluded. + */ +#define MBEDTLS_ECP_DP_MAX 12 + +/** + * Curve information, for use by other modules. + */ +typedef struct mbedtls_ecp_curve_info +{ + mbedtls_ecp_group_id grp_id; /*!< An internal identifier. */ + uint16_t tls_id; /*!< The TLS NamedCurve identifier. */ + uint16_t bit_size; /*!< The curve size in bits. */ + const char *name; /*!< A human-friendly name. */ +} mbedtls_ecp_curve_info; + +/** + * \brief The ECP point structure, in Jacobian coordinates. + * + * \note All functions expect and return points satisfying + * the following condition: Z == 0 or + * Z == 1. Other values of \p Z are + * used only by internal functions. + * The point is zero, or "at infinity", if Z == 0. + * Otherwise, \p X and \p Y are its standard (affine) + * coordinates. + */ +typedef struct mbedtls_ecp_point +{ + mbedtls_mpi X; /*!< The X coordinate of the ECP point. */ + mbedtls_mpi Y; /*!< The Y coordinate of the ECP point. */ + mbedtls_mpi Z; /*!< The Z coordinate of the ECP point. */ +} +mbedtls_ecp_point; + +#if !defined(MBEDTLS_ECP_ALT) +/* + * default mbed TLS elliptic curve arithmetic implementation + * + * (in case MBEDTLS_ECP_ALT is defined then the developer has to provide an + * alternative implementation for the whole module and it will replace this + * one.) + */ + +/** + * \brief The ECP group structure. + * + * We consider two types of curve equations: + *
  • Short Weierstrass: y^2 = x^3 + A x + B mod P + * (SEC1 + RFC-4492)
  • + *
  • Montgomery: y^2 = x^3 + A x^2 + x mod P (Curve25519, + * Curve448)
+ * In both cases, the generator (\p G) for a prime-order subgroup is fixed. + * + * For Short Weierstrass, this subgroup is the whole curve, and its + * cardinality is denoted by \p N. Our code requires that \p N is an + * odd prime as mbedtls_ecp_mul() requires an odd number, and + * mbedtls_ecdsa_sign() requires that it is prime for blinding purposes. + * + * For Montgomery curves, we do not store \p A, but (A + 2) / 4, + * which is the quantity used in the formulas. Additionally, \p nbits is + * not the size of \p N but the required size for private keys. + * + * If \p modp is NULL, reduction modulo \p P is done using a generic algorithm. + * Otherwise, \p modp must point to a function that takes an \p mbedtls_mpi in the + * range of 0..2^(2*pbits)-1, and transforms it in-place to an integer + * which is congruent mod \p P to the given MPI, and is close enough to \p pbits + * in size, so that it may be efficiently brought in the 0..P-1 range by a few + * additions or subtractions. Therefore, it is only an approximative modular + * reduction. It must return 0 on success and non-zero on failure. + * + */ +typedef struct mbedtls_ecp_group +{ + mbedtls_ecp_group_id id; /*!< An internal group identifier. */ + mbedtls_mpi P; /*!< The prime modulus of the base field. */ + mbedtls_mpi A; /*!< For Short Weierstrass: \p A in the equation. For + Montgomery curves: (A + 2) / 4. */ + mbedtls_mpi B; /*!< For Short Weierstrass: \p B in the equation. + For Montgomery curves: unused. */ + mbedtls_ecp_point G; /*!< The generator of the subgroup used. */ + mbedtls_mpi N; /*!< The order of \p G. */ + size_t pbits; /*!< The number of bits in \p P.*/ + size_t nbits; /*!< For Short Weierstrass: The number of bits in \p P. + For Montgomery curves: the number of bits in the + private keys. */ + unsigned int h; /*!< \internal 1 if the constants are static. */ + int (*modp)(mbedtls_mpi *); /*!< The function for fast pseudo-reduction + mod \p P (see above).*/ + int (*t_pre)(mbedtls_ecp_point *, void *); /*!< Unused. */ + int (*t_post)(mbedtls_ecp_point *, void *); /*!< Unused. */ + void *t_data; /*!< Unused. */ + mbedtls_ecp_point *T; /*!< Pre-computed points for ecp_mul_comb(). */ + size_t T_size; /*!< The number of pre-computed points. */ +} +mbedtls_ecp_group; + +/** + * \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 using the compiler command line. + * \{ + */ + +#if !defined(MBEDTLS_ECP_MAX_BITS) +/** + * The maximum size of the groups, that is, of \c N and \c P. + */ +#define MBEDTLS_ECP_MAX_BITS 521 /**< The maximum size of groups, in bits. */ +#endif + +#define MBEDTLS_ECP_MAX_BYTES ( ( MBEDTLS_ECP_MAX_BITS + 7 ) / 8 ) +#define MBEDTLS_ECP_MAX_PT_LEN ( 2 * MBEDTLS_ECP_MAX_BYTES + 1 ) + +#if !defined(MBEDTLS_ECP_WINDOW_SIZE) +/* + * Maximum "window" size used for point multiplication. + * Default: 6. + * Minimum value: 2. Maximum value: 7. + * + * Result is an array of at most ( 1 << ( MBEDTLS_ECP_WINDOW_SIZE - 1 ) ) + * points used for point multiplication. This value is directly tied to EC + * peak memory usage, so decreasing it by one should roughly cut memory usage + * by two (if large curves are in use). + * + * Reduction in size may reduce speed, but larger curves are impacted first. + * Sample performances (in ECDHE handshakes/s, with FIXED_POINT_OPTIM = 1): + * w-size: 6 5 4 3 2 + * 521 145 141 135 120 97 + * 384 214 209 198 177 146 + * 256 320 320 303 262 226 + * 224 475 475 453 398 342 + * 192 640 640 633 587 476 + */ +#define MBEDTLS_ECP_WINDOW_SIZE 6 /**< The maximum window size used. */ +#endif /* MBEDTLS_ECP_WINDOW_SIZE */ + +#if !defined(MBEDTLS_ECP_FIXED_POINT_OPTIM) +/* + * Trade memory for speed on fixed-point multiplication. + * + * This speeds up repeated multiplication of the generator (that is, the + * multiplication in ECDSA signatures, and half of the multiplications in + * ECDSA verification and ECDHE) by a factor roughly 3 to 4. + * + * The cost is increasing EC peak memory usage by a factor roughly 2. + * + * Change this value to 0 to reduce peak memory usage. + */ +#define MBEDTLS_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up. */ +#endif /* MBEDTLS_ECP_FIXED_POINT_OPTIM */ + +/* \} name SECTION: Module settings */ + +#else /* MBEDTLS_ECP_ALT */ +#include "ecp_alt.h" +#endif /* MBEDTLS_ECP_ALT */ + +/** + * \brief The ECP key-pair structure. + * + * A generic key-pair that may be used for ECDSA and fixed ECDH, for example. + * + * \note Members are deliberately in the same order as in the + * ::mbedtls_ecdsa_context structure. + */ +typedef struct mbedtls_ecp_keypair +{ + mbedtls_ecp_group grp; /*!< Elliptic curve and base point */ + mbedtls_mpi d; /*!< our secret value */ + mbedtls_ecp_point Q; /*!< our public value */ +} +mbedtls_ecp_keypair; + +/* + * Point formats, from RFC 4492's enum ECPointFormat + */ +#define MBEDTLS_ECP_PF_UNCOMPRESSED 0 /**< Uncompressed point format. */ +#define MBEDTLS_ECP_PF_COMPRESSED 1 /**< Compressed point format. */ + +/* + * Some other constants from RFC 4492 + */ +#define MBEDTLS_ECP_TLS_NAMED_CURVE 3 /**< The named_curve of ECCurveType. */ + +/** + * \brief This function retrieves the information defined in + * mbedtls_ecp_curve_info() for all supported curves in order + * of preference. + * + * \return A statically allocated array. The last entry is 0. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_list( void ); + +/** + * \brief This function retrieves the list of internal group + * identifiers of all supported curves in the order of + * preference. + * + * \return A statically allocated array, + * terminated with MBEDTLS_ECP_DP_NONE. + */ +const mbedtls_ecp_group_id *mbedtls_ecp_grp_id_list( void ); + +/** + * \brief This function retrieves curve information from an internal + * group identifier. + * + * \param grp_id An \c MBEDTLS_ECP_DP_XXX value. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_grp_id( mbedtls_ecp_group_id grp_id ); + +/** + * \brief This function retrieves curve information from a TLS + * NamedCurve value. + * + * \param tls_id An \c MBEDTLS_ECP_DP_XXX value. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_tls_id( uint16_t tls_id ); + +/** + * \brief This function retrieves curve information from a + * human-readable name. + * + * \param name The human-readable name. + * + * \return The associated curve information on success. + * \return NULL on failure. + */ +const mbedtls_ecp_curve_info *mbedtls_ecp_curve_info_from_name( const char *name ); + +/** + * \brief This function initializes a point as zero. + * + * \param pt The point to initialize. + */ +void mbedtls_ecp_point_init( mbedtls_ecp_point *pt ); + +/** + * \brief This function initializes an ECP group context + * without loading any domain parameters. + * + * \note After this function is called, domain parameters + * for various ECP groups can be loaded through the + * mbedtls_ecp_load() or mbedtls_ecp_tls_read_group() + * functions. + */ +void mbedtls_ecp_group_init( mbedtls_ecp_group *grp ); + +/** + * \brief This function initializes a key pair as an invalid one. + * + * \param key The key pair to initialize. + */ +void mbedtls_ecp_keypair_init( mbedtls_ecp_keypair *key ); + +/** + * \brief This function frees the components of a point. + * + * \param pt The point to free. + */ +void mbedtls_ecp_point_free( mbedtls_ecp_point *pt ); + +/** + * \brief This function frees the components of an ECP group. + * \param grp The group to free. + */ +void mbedtls_ecp_group_free( mbedtls_ecp_group *grp ); + +/** + * \brief This function frees the components of a key pair. + * \param key The key pair to free. + */ +void mbedtls_ecp_keypair_free( mbedtls_ecp_keypair *key ); + +/** + * \brief This function copies the contents of point \p Q into + * point \p P. + * + * \param P The destination point. + * \param Q The source point. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + */ +int mbedtls_ecp_copy( mbedtls_ecp_point *P, const mbedtls_ecp_point *Q ); + +/** + * \brief This function copies the contents of group \p src into + * group \p dst. + * + * \param dst The destination group. + * \param src The source group. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + */ +int mbedtls_ecp_group_copy( mbedtls_ecp_group *dst, const mbedtls_ecp_group *src ); + +/** + * \brief This function sets a point to zero. + * + * \param pt The point to set. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + */ +int mbedtls_ecp_set_zero( mbedtls_ecp_point *pt ); + +/** + * \brief This function checks if a point is zero. + * + * \param pt The point to test. + * + * \return \c 1 if the point is zero. + * \return \c 0 if the point is non-zero. + */ +int mbedtls_ecp_is_zero( mbedtls_ecp_point *pt ); + +/** + * \brief This function compares two points. + * + * \note This assumes that the points are normalized. Otherwise, + * they may compare as "not equal" even if they are. + * + * \param P The first point to compare. + * \param Q The second point to compare. + * + * \return \c 0 if the points are equal. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the points are not equal. + */ +int mbedtls_ecp_point_cmp( const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); + +/** + * \brief This function imports a non-zero point from two ASCII + * strings. + * + * \param P The destination point. + * \param radix The numeric base of the input. + * \param x The first affine coordinate, as a null-terminated string. + * \param y The second affine coordinate, as a null-terminated string. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on failure. + */ +int mbedtls_ecp_point_read_string( mbedtls_ecp_point *P, int radix, + const char *x, const char *y ); + +/** + * \brief This function exports a point into unsigned binary data. + * + * \param grp The group to which the point should belong. + * \param P The point to export. + * \param format The point format. Should be an \c MBEDTLS_ECP_PF_XXX macro. + * \param olen The length of the output. + * \param buf The output buffer. + * \param buflen The length of the output buffer. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA + * or #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL on failure. + */ +int mbedtls_ecp_point_write_binary( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *P, + int format, size_t *olen, + unsigned char *buf, size_t buflen ); + +/** + * \brief This function imports a point from unsigned binary data. + * + * \note This function does not check that the point actually + * belongs to the given group, see mbedtls_ecp_check_pubkey() + * for that. + * + * \param grp The group to which the point should belong. + * \param P The point to import. + * \param buf The input buffer. + * \param ilen The length of the input. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE if the point format + * is not implemented. + * + */ +int mbedtls_ecp_point_read_binary( const mbedtls_ecp_group *grp, mbedtls_ecp_point *P, + const unsigned char *buf, size_t ilen ); + +/** + * \brief This function imports a point from a TLS ECPoint record. + * + * \note On function return, \p buf is updated to point to immediately + * after the ECPoint record. + * + * \param grp The ECP group used. + * \param pt The destination point. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization failure. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + */ +int mbedtls_ecp_tls_read_point( const mbedtls_ecp_group *grp, mbedtls_ecp_point *pt, + const unsigned char **buf, size_t len ); + +/** + * \brief This function exports a point as a TLS ECPoint record. + * + * \param grp The ECP group used. + * \param pt The point format to export to. The point format is an + * \c MBEDTLS_ECP_PF_XXX constant. + * \param format The export format. + * \param olen The length of the data written. + * \param buf The buffer to write to. + * \param blen The length of the buffer. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA or + * #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL on failure. + */ +int mbedtls_ecp_tls_write_point( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt, + int format, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief This function sets a group using standardized domain parameters. + * + * \note The index should be a value of the NamedCurve enum, + * as defined in RFC-4492: Elliptic Curve Cryptography + * (ECC) Cipher Suites for Transport Layer Security (TLS), + * usually in the form of an \c MBEDTLS_ECP_DP_XXX macro. + * + * \param grp The destination group. + * \param id The identifier of the domain parameter set to load. + * + * \return \c 0 on success, + * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization failure. + * \return #MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE for unkownn groups. + + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ); + +/** + * \brief This function sets a group from a TLS ECParameters record. + * + * \note \p buf is updated to point right after the ECParameters record + * on exit. + * + * \param grp The destination group. + * \param buf The address of the pointer to the start of the input buffer. + * \param len The length of the buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_MPI_XXX error code on initialization failure. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if input is invalid. + */ +int mbedtls_ecp_tls_read_group( mbedtls_ecp_group *grp, const unsigned char **buf, size_t len ); + +/** + * \brief This function writes the TLS ECParameters record for a group. + * + * \param grp The ECP group used. + * \param olen The number of Bytes written. + * \param buf The buffer to write to. + * \param blen The length of the buffer. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL on failure. + */ +int mbedtls_ecp_tls_write_group( const mbedtls_ecp_group *grp, size_t *olen, + unsigned char *buf, size_t blen ); + +/** + * \brief This function performs multiplication of a point by + * an integer: \p R = \p m * \p P. + * + * It is not thread-safe to use same group in multiple threads. + * + * \note To prevent timing attacks, this function + * executes the exact same sequence of base-field + * operations for any valid \p m. It avoids any if-branch or + * array index depending on the value of \p m. + * + * \note If \p f_rng is not NULL, it is used to randomize + * intermediate results to prevent potential timing attacks + * targeting these results. We recommend always providing + * a non-NULL \p f_rng. The overhead is negligible. + * + * \param grp The ECP group. + * \param R The destination point. + * \param m The integer by which to multiply. + * \param P The point to multiply. + * \param f_rng The RNG function. + * \param p_rng The RNG context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m is not a valid private + * key, or \p P is not a valid public key. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + */ +int mbedtls_ecp_mul( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief This function performs multiplication and addition of two + * points by integers: \p R = \p m * \p P + \p n * \p Q + * + * It is not thread-safe to use same group in multiple threads. + * + * \note In contrast to mbedtls_ecp_mul(), this function does not + * guarantee a constant execution flow and timing. + * + * \param grp The ECP group. + * \param R The destination point. + * \param m The integer by which to multiply \p P. + * \param P The point to multiply by \p m. + * \param n The integer by which to multiply \p Q. + * \param Q The point to be multiplied by \p n. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY if \p m or \p n are not + * valid private keys, or \p P or \p Q are not valid public + * keys. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory-allocation failure. + */ +int mbedtls_ecp_muladd( mbedtls_ecp_group *grp, mbedtls_ecp_point *R, + const mbedtls_mpi *m, const mbedtls_ecp_point *P, + const mbedtls_mpi *n, const mbedtls_ecp_point *Q ); + +/** + * \brief This function checks that a point is a valid public key + * on this curve. + * + * It only checks that the point is non-zero, has + * valid coordinates and lies on the curve. It does not verify + * that it is indeed a multiple of \p G. This additional + * check is computationally more expensive, is not required + * by standards, and should not be necessary if the group + * used has a small cofactor. In particular, it is useless for + * the NIST groups which all have a cofactor of 1. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure, to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The curve the point should lie on. + * \param pt The point to check. + * + * \return \c 0 if the point is a valid public key. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY on failure. + */ +int mbedtls_ecp_check_pubkey( const mbedtls_ecp_group *grp, const mbedtls_ecp_point *pt ); + +/** + * \brief This function checks that an \p mbedtls_mpi is a valid private + * key for this curve. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The group used. + * \param d The integer to check. + * + * \return \c 0 if the point is a valid private key. + * \return #MBEDTLS_ERR_ECP_INVALID_KEY on failure. + */ +int mbedtls_ecp_check_privkey( const mbedtls_ecp_group *grp, const mbedtls_mpi *d ); + +/** + * \brief This function generates a keypair with a configurable base + * point. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group. + * \param G The chosen base point. + * \param d The destination MPI (secret part). + * \param Q The destination point (public part). + * \param f_rng The RNG function. + * \param p_rng The RNG context. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_keypair_base( mbedtls_ecp_group *grp, + const mbedtls_ecp_point *G, + mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates an ECP keypair. + * + * \note This function uses bare components rather than an + * ::mbedtls_ecp_keypair structure to ease use with other + * structures, such as ::mbedtls_ecdh_context or + * ::mbedtls_ecdsa_context. + * + * \param grp The ECP group. + * \param d The destination MPI (secret part). + * \param Q The destination point (public part). + * \param f_rng The RNG function. + * \param p_rng The RNG context. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_keypair( mbedtls_ecp_group *grp, mbedtls_mpi *d, mbedtls_ecp_point *Q, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief This function generates an ECP key. + * + * \param grp_id The ECP group identifier. + * \param key The destination key. + * \param f_rng The RNG function. + * \param p_rng The RNG context. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_ECP_XXX or \c MBEDTLS_MPI_XXX error code + * on failure. + */ +int mbedtls_ecp_gen_key( mbedtls_ecp_group_id grp_id, mbedtls_ecp_keypair *key, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief This function checks that the keypair objects + * \p pub and \p prv have the same group and the + * same public point, and that the private key in + * \p prv is consistent with the public key. + * + * \param pub The keypair structure holding the public key. + * If it contains a private key, that part is ignored. + * \param prv The keypair structure holding the full keypair. + * + * \return \c 0 on success, meaning that the keys are valid and match. + * \return #MBEDTLS_ERR_ECP_BAD_INPUT_DATA if the keys are invalid or do not match. + * \return An \c MBEDTLS_ERR_ECP_XXX or an \c MBEDTLS_ERR_MPI_XXX + * error code on calculation failure. + */ +int mbedtls_ecp_check_pub_priv( const mbedtls_ecp_keypair *pub, const mbedtls_ecp_keypair *prv ); + +#if defined(MBEDTLS_SELF_TEST) + +/** + * \brief The ECP checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_ecp_self_test( int verbose ); + +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* ecp.h */ diff --git a/common/mbedtls/ecp_curves.c b/common/mbedtls/ecp_curves.c new file mode 100644 index 000000000..01efe8ba9 --- /dev/null +++ b/common/mbedtls/ecp_curves.c @@ -0,0 +1,1462 @@ +/* + * Elliptic curves over GF(p): curve-specific data and functions + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ECP_C) + +#include "mbedtls/ecp.h" + +#include + +#if !defined(MBEDTLS_ECP_ALT) + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +/* + * Conversion macros for embedded constants: + * build lists of mbedtls_mpi_uint's from lists of unsigned char's grouped by 8, 4 or 2 + */ +#if defined(MBEDTLS_HAVE_INT32) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + ( (mbedtls_mpi_uint) a << 0 ) | \ + ( (mbedtls_mpi_uint) b << 8 ) | \ + ( (mbedtls_mpi_uint) c << 16 ) | \ + ( (mbedtls_mpi_uint) d << 24 ) + +#define BYTES_TO_T_UINT_2( a, b ) \ + BYTES_TO_T_UINT_4( a, b, 0, 0 ) + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + BYTES_TO_T_UINT_4( a, b, c, d ), \ + BYTES_TO_T_UINT_4( e, f, g, h ) + +#else /* 64-bits */ + +#define BYTES_TO_T_UINT_8( a, b, c, d, e, f, g, h ) \ + ( (mbedtls_mpi_uint) a << 0 ) | \ + ( (mbedtls_mpi_uint) b << 8 ) | \ + ( (mbedtls_mpi_uint) c << 16 ) | \ + ( (mbedtls_mpi_uint) d << 24 ) | \ + ( (mbedtls_mpi_uint) e << 32 ) | \ + ( (mbedtls_mpi_uint) f << 40 ) | \ + ( (mbedtls_mpi_uint) g << 48 ) | \ + ( (mbedtls_mpi_uint) h << 56 ) + +#define BYTES_TO_T_UINT_4( a, b, c, d ) \ + BYTES_TO_T_UINT_8( a, b, c, d, 0, 0, 0, 0 ) + +#define BYTES_TO_T_UINT_2( a, b ) \ + BYTES_TO_T_UINT_8( a, b, 0, 0, 0, 0, 0, 0 ) + +#endif /* bits in mbedtls_mpi_uint */ + +/* + * Note: the constants are in little-endian order + * to be directly usable in MPIs + */ + +/* + * Domain parameters for secp192r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static const mbedtls_mpi_uint secp192r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp192r1_b[] = { + BYTES_TO_T_UINT_8( 0xB1, 0xB9, 0x46, 0xC1, 0xEC, 0xDE, 0xB8, 0xFE ), + BYTES_TO_T_UINT_8( 0x49, 0x30, 0x24, 0x72, 0xAB, 0xE9, 0xA7, 0x0F ), + BYTES_TO_T_UINT_8( 0xE7, 0x80, 0x9C, 0xE5, 0x19, 0x05, 0x21, 0x64 ), +}; +static const mbedtls_mpi_uint secp192r1_gx[] = { + BYTES_TO_T_UINT_8( 0x12, 0x10, 0xFF, 0x82, 0xFD, 0x0A, 0xFF, 0xF4 ), + BYTES_TO_T_UINT_8( 0x00, 0x88, 0xA1, 0x43, 0xEB, 0x20, 0xBF, 0x7C ), + BYTES_TO_T_UINT_8( 0xF6, 0x90, 0x30, 0xB0, 0x0E, 0xA8, 0x8D, 0x18 ), +}; +static const mbedtls_mpi_uint secp192r1_gy[] = { + BYTES_TO_T_UINT_8( 0x11, 0x48, 0x79, 0x1E, 0xA1, 0x77, 0xF9, 0x73 ), + BYTES_TO_T_UINT_8( 0xD5, 0xCD, 0x24, 0x6B, 0xED, 0x11, 0x10, 0x63 ), + BYTES_TO_T_UINT_8( 0x78, 0xDA, 0xC8, 0xFF, 0x95, 0x2B, 0x19, 0x07 ), +}; +static const mbedtls_mpi_uint secp192r1_n[] = { + BYTES_TO_T_UINT_8( 0x31, 0x28, 0xD2, 0xB4, 0xB1, 0xC9, 0x6B, 0x14 ), + BYTES_TO_T_UINT_8( 0x36, 0xF8, 0xDE, 0x99, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +/* + * Domain parameters for secp224r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static const mbedtls_mpi_uint secp224r1_p[] = { + BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224r1_b[] = { + BYTES_TO_T_UINT_8( 0xB4, 0xFF, 0x55, 0x23, 0x43, 0x39, 0x0B, 0x27 ), + BYTES_TO_T_UINT_8( 0xBA, 0xD8, 0xBF, 0xD7, 0xB7, 0xB0, 0x44, 0x50 ), + BYTES_TO_T_UINT_8( 0x56, 0x32, 0x41, 0xF5, 0xAB, 0xB3, 0x04, 0x0C ), + BYTES_TO_T_UINT_4( 0x85, 0x0A, 0x05, 0xB4 ), +}; +static const mbedtls_mpi_uint secp224r1_gx[] = { + BYTES_TO_T_UINT_8( 0x21, 0x1D, 0x5C, 0x11, 0xD6, 0x80, 0x32, 0x34 ), + BYTES_TO_T_UINT_8( 0x22, 0x11, 0xC2, 0x56, 0xD3, 0xC1, 0x03, 0x4A ), + BYTES_TO_T_UINT_8( 0xB9, 0x90, 0x13, 0x32, 0x7F, 0xBF, 0xB4, 0x6B ), + BYTES_TO_T_UINT_4( 0xBD, 0x0C, 0x0E, 0xB7 ), +}; +static const mbedtls_mpi_uint secp224r1_gy[] = { + BYTES_TO_T_UINT_8( 0x34, 0x7E, 0x00, 0x85, 0x99, 0x81, 0xD5, 0x44 ), + BYTES_TO_T_UINT_8( 0x64, 0x47, 0x07, 0x5A, 0xA0, 0x75, 0x43, 0xCD ), + BYTES_TO_T_UINT_8( 0xE6, 0xDF, 0x22, 0x4C, 0xFB, 0x23, 0xF7, 0xB5 ), + BYTES_TO_T_UINT_4( 0x88, 0x63, 0x37, 0xBD ), +}; +static const mbedtls_mpi_uint secp224r1_n[] = { + BYTES_TO_T_UINT_8( 0x3D, 0x2A, 0x5C, 0x5C, 0x45, 0x29, 0xDD, 0x13 ), + BYTES_TO_T_UINT_8( 0x3E, 0xF0, 0xB8, 0xE0, 0xA2, 0x16, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +/* + * Domain parameters for secp256r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static const mbedtls_mpi_uint secp256r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp256r1_b[] = { + BYTES_TO_T_UINT_8( 0x4B, 0x60, 0xD2, 0x27, 0x3E, 0x3C, 0xCE, 0x3B ), + BYTES_TO_T_UINT_8( 0xF6, 0xB0, 0x53, 0xCC, 0xB0, 0x06, 0x1D, 0x65 ), + BYTES_TO_T_UINT_8( 0xBC, 0x86, 0x98, 0x76, 0x55, 0xBD, 0xEB, 0xB3 ), + BYTES_TO_T_UINT_8( 0xE7, 0x93, 0x3A, 0xAA, 0xD8, 0x35, 0xC6, 0x5A ), +}; +static const mbedtls_mpi_uint secp256r1_gx[] = { + BYTES_TO_T_UINT_8( 0x96, 0xC2, 0x98, 0xD8, 0x45, 0x39, 0xA1, 0xF4 ), + BYTES_TO_T_UINT_8( 0xA0, 0x33, 0xEB, 0x2D, 0x81, 0x7D, 0x03, 0x77 ), + BYTES_TO_T_UINT_8( 0xF2, 0x40, 0xA4, 0x63, 0xE5, 0xE6, 0xBC, 0xF8 ), + BYTES_TO_T_UINT_8( 0x47, 0x42, 0x2C, 0xE1, 0xF2, 0xD1, 0x17, 0x6B ), +}; +static const mbedtls_mpi_uint secp256r1_gy[] = { + BYTES_TO_T_UINT_8( 0xF5, 0x51, 0xBF, 0x37, 0x68, 0x40, 0xB6, 0xCB ), + BYTES_TO_T_UINT_8( 0xCE, 0x5E, 0x31, 0x6B, 0x57, 0x33, 0xCE, 0x2B ), + BYTES_TO_T_UINT_8( 0x16, 0x9E, 0x0F, 0x7C, 0x4A, 0xEB, 0xE7, 0x8E ), + BYTES_TO_T_UINT_8( 0x9B, 0x7F, 0x1A, 0xFE, 0xE2, 0x42, 0xE3, 0x4F ), +}; +static const mbedtls_mpi_uint secp256r1_n[] = { + BYTES_TO_T_UINT_8( 0x51, 0x25, 0x63, 0xFC, 0xC2, 0xCA, 0xB9, 0xF3 ), + BYTES_TO_T_UINT_8( 0x84, 0x9E, 0x17, 0xA7, 0xAD, 0xFA, 0xE6, 0xBC ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +/* + * Domain parameters for secp384r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static const mbedtls_mpi_uint secp384r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp384r1_b[] = { + BYTES_TO_T_UINT_8( 0xEF, 0x2A, 0xEC, 0xD3, 0xED, 0xC8, 0x85, 0x2A ), + BYTES_TO_T_UINT_8( 0x9D, 0xD1, 0x2E, 0x8A, 0x8D, 0x39, 0x56, 0xC6 ), + BYTES_TO_T_UINT_8( 0x5A, 0x87, 0x13, 0x50, 0x8F, 0x08, 0x14, 0x03 ), + BYTES_TO_T_UINT_8( 0x12, 0x41, 0x81, 0xFE, 0x6E, 0x9C, 0x1D, 0x18 ), + BYTES_TO_T_UINT_8( 0x19, 0x2D, 0xF8, 0xE3, 0x6B, 0x05, 0x8E, 0x98 ), + BYTES_TO_T_UINT_8( 0xE4, 0xE7, 0x3E, 0xE2, 0xA7, 0x2F, 0x31, 0xB3 ), +}; +static const mbedtls_mpi_uint secp384r1_gx[] = { + BYTES_TO_T_UINT_8( 0xB7, 0x0A, 0x76, 0x72, 0x38, 0x5E, 0x54, 0x3A ), + BYTES_TO_T_UINT_8( 0x6C, 0x29, 0x55, 0xBF, 0x5D, 0xF2, 0x02, 0x55 ), + BYTES_TO_T_UINT_8( 0x38, 0x2A, 0x54, 0x82, 0xE0, 0x41, 0xF7, 0x59 ), + BYTES_TO_T_UINT_8( 0x98, 0x9B, 0xA7, 0x8B, 0x62, 0x3B, 0x1D, 0x6E ), + BYTES_TO_T_UINT_8( 0x74, 0xAD, 0x20, 0xF3, 0x1E, 0xC7, 0xB1, 0x8E ), + BYTES_TO_T_UINT_8( 0x37, 0x05, 0x8B, 0xBE, 0x22, 0xCA, 0x87, 0xAA ), +}; +static const mbedtls_mpi_uint secp384r1_gy[] = { + BYTES_TO_T_UINT_8( 0x5F, 0x0E, 0xEA, 0x90, 0x7C, 0x1D, 0x43, 0x7A ), + BYTES_TO_T_UINT_8( 0x9D, 0x81, 0x7E, 0x1D, 0xCE, 0xB1, 0x60, 0x0A ), + BYTES_TO_T_UINT_8( 0xC0, 0xB8, 0xF0, 0xB5, 0x13, 0x31, 0xDA, 0xE9 ), + BYTES_TO_T_UINT_8( 0x7C, 0x14, 0x9A, 0x28, 0xBD, 0x1D, 0xF4, 0xF8 ), + BYTES_TO_T_UINT_8( 0x29, 0xDC, 0x92, 0x92, 0xBF, 0x98, 0x9E, 0x5D ), + BYTES_TO_T_UINT_8( 0x6F, 0x2C, 0x26, 0x96, 0x4A, 0xDE, 0x17, 0x36 ), +}; +static const mbedtls_mpi_uint secp384r1_n[] = { + BYTES_TO_T_UINT_8( 0x73, 0x29, 0xC5, 0xCC, 0x6A, 0x19, 0xEC, 0xEC ), + BYTES_TO_T_UINT_8( 0x7A, 0xA7, 0xB0, 0x48, 0xB2, 0x0D, 0x1A, 0x58 ), + BYTES_TO_T_UINT_8( 0xDF, 0x2D, 0x37, 0xF4, 0x81, 0x4D, 0x63, 0xC7 ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +/* + * Domain parameters for secp521r1 + */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static const mbedtls_mpi_uint secp521r1_p[] = { + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +static const mbedtls_mpi_uint secp521r1_b[] = { + BYTES_TO_T_UINT_8( 0x00, 0x3F, 0x50, 0x6B, 0xD4, 0x1F, 0x45, 0xEF ), + BYTES_TO_T_UINT_8( 0xF1, 0x34, 0x2C, 0x3D, 0x88, 0xDF, 0x73, 0x35 ), + BYTES_TO_T_UINT_8( 0x07, 0xBF, 0xB1, 0x3B, 0xBD, 0xC0, 0x52, 0x16 ), + BYTES_TO_T_UINT_8( 0x7B, 0x93, 0x7E, 0xEC, 0x51, 0x39, 0x19, 0x56 ), + BYTES_TO_T_UINT_8( 0xE1, 0x09, 0xF1, 0x8E, 0x91, 0x89, 0xB4, 0xB8 ), + BYTES_TO_T_UINT_8( 0xF3, 0x15, 0xB3, 0x99, 0x5B, 0x72, 0xDA, 0xA2 ), + BYTES_TO_T_UINT_8( 0xEE, 0x40, 0x85, 0xB6, 0xA0, 0x21, 0x9A, 0x92 ), + BYTES_TO_T_UINT_8( 0x1F, 0x9A, 0x1C, 0x8E, 0x61, 0xB9, 0x3E, 0x95 ), + BYTES_TO_T_UINT_2( 0x51, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_gx[] = { + BYTES_TO_T_UINT_8( 0x66, 0xBD, 0xE5, 0xC2, 0x31, 0x7E, 0x7E, 0xF9 ), + BYTES_TO_T_UINT_8( 0x9B, 0x42, 0x6A, 0x85, 0xC1, 0xB3, 0x48, 0x33 ), + BYTES_TO_T_UINT_8( 0xDE, 0xA8, 0xFF, 0xA2, 0x27, 0xC1, 0x1D, 0xFE ), + BYTES_TO_T_UINT_8( 0x28, 0x59, 0xE7, 0xEF, 0x77, 0x5E, 0x4B, 0xA1 ), + BYTES_TO_T_UINT_8( 0xBA, 0x3D, 0x4D, 0x6B, 0x60, 0xAF, 0x28, 0xF8 ), + BYTES_TO_T_UINT_8( 0x21, 0xB5, 0x3F, 0x05, 0x39, 0x81, 0x64, 0x9C ), + BYTES_TO_T_UINT_8( 0x42, 0xB4, 0x95, 0x23, 0x66, 0xCB, 0x3E, 0x9E ), + BYTES_TO_T_UINT_8( 0xCD, 0xE9, 0x04, 0x04, 0xB7, 0x06, 0x8E, 0x85 ), + BYTES_TO_T_UINT_2( 0xC6, 0x00 ), +}; +static const mbedtls_mpi_uint secp521r1_gy[] = { + BYTES_TO_T_UINT_8( 0x50, 0x66, 0xD1, 0x9F, 0x76, 0x94, 0xBE, 0x88 ), + BYTES_TO_T_UINT_8( 0x40, 0xC2, 0x72, 0xA2, 0x86, 0x70, 0x3C, 0x35 ), + BYTES_TO_T_UINT_8( 0x61, 0x07, 0xAD, 0x3F, 0x01, 0xB9, 0x50, 0xC5 ), + BYTES_TO_T_UINT_8( 0x40, 0x26, 0xF4, 0x5E, 0x99, 0x72, 0xEE, 0x97 ), + BYTES_TO_T_UINT_8( 0x2C, 0x66, 0x3E, 0x27, 0x17, 0xBD, 0xAF, 0x17 ), + BYTES_TO_T_UINT_8( 0x68, 0x44, 0x9B, 0x57, 0x49, 0x44, 0xF5, 0x98 ), + BYTES_TO_T_UINT_8( 0xD9, 0x1B, 0x7D, 0x2C, 0xB4, 0x5F, 0x8A, 0x5C ), + BYTES_TO_T_UINT_8( 0x04, 0xC0, 0x3B, 0x9A, 0x78, 0x6A, 0x29, 0x39 ), + BYTES_TO_T_UINT_2( 0x18, 0x01 ), +}; +static const mbedtls_mpi_uint secp521r1_n[] = { + BYTES_TO_T_UINT_8( 0x09, 0x64, 0x38, 0x91, 0x1E, 0xB7, 0x6F, 0xBB ), + BYTES_TO_T_UINT_8( 0xAE, 0x47, 0x9C, 0x89, 0xB8, 0xC9, 0xB5, 0x3B ), + BYTES_TO_T_UINT_8( 0xD0, 0xA5, 0x09, 0xF7, 0x48, 0x01, 0xCC, 0x7F ), + BYTES_TO_T_UINT_8( 0x6B, 0x96, 0x2F, 0xBF, 0x83, 0x87, 0x86, 0x51 ), + BYTES_TO_T_UINT_8( 0xFA, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_2( 0xFF, 0x01 ), +}; +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static const mbedtls_mpi_uint secp192k1_p[] = { + BYTES_TO_T_UINT_8( 0x37, 0xEE, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp192k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp192k1_b[] = { + BYTES_TO_T_UINT_2( 0x03, 0x00 ), +}; +static const mbedtls_mpi_uint secp192k1_gx[] = { + BYTES_TO_T_UINT_8( 0x7D, 0x6C, 0xE0, 0xEA, 0xB1, 0xD1, 0xA5, 0x1D ), + BYTES_TO_T_UINT_8( 0x34, 0xF4, 0xB7, 0x80, 0x02, 0x7D, 0xB0, 0x26 ), + BYTES_TO_T_UINT_8( 0xAE, 0xE9, 0x57, 0xC0, 0x0E, 0xF1, 0x4F, 0xDB ), +}; +static const mbedtls_mpi_uint secp192k1_gy[] = { + BYTES_TO_T_UINT_8( 0x9D, 0x2F, 0x5E, 0xD9, 0x88, 0xAA, 0x82, 0x40 ), + BYTES_TO_T_UINT_8( 0x34, 0x86, 0xBE, 0x15, 0xD0, 0x63, 0x41, 0x84 ), + BYTES_TO_T_UINT_8( 0xA7, 0x28, 0x56, 0x9C, 0x6D, 0x2F, 0x2F, 0x9B ), +}; +static const mbedtls_mpi_uint secp192k1_n[] = { + BYTES_TO_T_UINT_8( 0x8D, 0xFD, 0xDE, 0x74, 0x6A, 0x46, 0x69, 0x0F ), + BYTES_TO_T_UINT_8( 0x17, 0xFC, 0xF2, 0x26, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static const mbedtls_mpi_uint secp224k1_p[] = { + BYTES_TO_T_UINT_8( 0x6D, 0xE5, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_4( 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp224k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_b[] = { + BYTES_TO_T_UINT_2( 0x05, 0x00 ), +}; +static const mbedtls_mpi_uint secp224k1_gx[] = { + BYTES_TO_T_UINT_8( 0x5C, 0xA4, 0xB7, 0xB6, 0x0E, 0x65, 0x7E, 0x0F ), + BYTES_TO_T_UINT_8( 0xA9, 0x75, 0x70, 0xE4, 0xE9, 0x67, 0xA4, 0x69 ), + BYTES_TO_T_UINT_8( 0xA1, 0x28, 0xFC, 0x30, 0xDF, 0x99, 0xF0, 0x4D ), + BYTES_TO_T_UINT_4( 0x33, 0x5B, 0x45, 0xA1 ), +}; +static const mbedtls_mpi_uint secp224k1_gy[] = { + BYTES_TO_T_UINT_8( 0xA5, 0x61, 0x6D, 0x55, 0xDB, 0x4B, 0xCA, 0xE2 ), + BYTES_TO_T_UINT_8( 0x59, 0xBD, 0xB0, 0xC0, 0xF7, 0x19, 0xE3, 0xF7 ), + BYTES_TO_T_UINT_8( 0xD6, 0xFB, 0xCA, 0x82, 0x42, 0x34, 0xBA, 0x7F ), + BYTES_TO_T_UINT_4( 0xED, 0x9F, 0x08, 0x7E ), +}; +static const mbedtls_mpi_uint secp224k1_n[] = { + BYTES_TO_T_UINT_8( 0xF7, 0xB1, 0x9F, 0x76, 0x71, 0xA9, 0xF0, 0xCA ), + BYTES_TO_T_UINT_8( 0x84, 0x61, 0xEC, 0xD2, 0xE8, 0xDC, 0x01, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 ), + BYTES_TO_T_UINT_8( 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ), +}; +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static const mbedtls_mpi_uint secp256k1_p[] = { + BYTES_TO_T_UINT_8( 0x2F, 0xFC, 0xFF, 0xFF, 0xFE, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +static const mbedtls_mpi_uint secp256k1_a[] = { + BYTES_TO_T_UINT_2( 0x00, 0x00 ), +}; +static const mbedtls_mpi_uint secp256k1_b[] = { + BYTES_TO_T_UINT_2( 0x07, 0x00 ), +}; +static const mbedtls_mpi_uint secp256k1_gx[] = { + BYTES_TO_T_UINT_8( 0x98, 0x17, 0xF8, 0x16, 0x5B, 0x81, 0xF2, 0x59 ), + BYTES_TO_T_UINT_8( 0xD9, 0x28, 0xCE, 0x2D, 0xDB, 0xFC, 0x9B, 0x02 ), + BYTES_TO_T_UINT_8( 0x07, 0x0B, 0x87, 0xCE, 0x95, 0x62, 0xA0, 0x55 ), + BYTES_TO_T_UINT_8( 0xAC, 0xBB, 0xDC, 0xF9, 0x7E, 0x66, 0xBE, 0x79 ), +}; +static const mbedtls_mpi_uint secp256k1_gy[] = { + BYTES_TO_T_UINT_8( 0xB8, 0xD4, 0x10, 0xFB, 0x8F, 0xD0, 0x47, 0x9C ), + BYTES_TO_T_UINT_8( 0x19, 0x54, 0x85, 0xA6, 0x48, 0xB4, 0x17, 0xFD ), + BYTES_TO_T_UINT_8( 0xA8, 0x08, 0x11, 0x0E, 0xFC, 0xFB, 0xA4, 0x5D ), + BYTES_TO_T_UINT_8( 0x65, 0xC4, 0xA3, 0x26, 0x77, 0xDA, 0x3A, 0x48 ), +}; +static const mbedtls_mpi_uint secp256k1_n[] = { + BYTES_TO_T_UINT_8( 0x41, 0x41, 0x36, 0xD0, 0x8C, 0x5E, 0xD2, 0xBF ), + BYTES_TO_T_UINT_8( 0x3B, 0xA0, 0x48, 0xAF, 0xE6, 0xDC, 0xAE, 0xBA ), + BYTES_TO_T_UINT_8( 0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), + BYTES_TO_T_UINT_8( 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF ), +}; +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +/* + * Domain parameters for brainpoolP256r1 (RFC 5639 3.4) + */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP256r1_p[] = { + BYTES_TO_T_UINT_8( 0x77, 0x53, 0x6E, 0x1F, 0x1D, 0x48, 0x13, 0x20 ), + BYTES_TO_T_UINT_8( 0x28, 0x20, 0x26, 0xD5, 0x23, 0xF6, 0x3B, 0x6E ), + BYTES_TO_T_UINT_8( 0x72, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_a[] = { + BYTES_TO_T_UINT_8( 0xD9, 0xB5, 0x30, 0xF3, 0x44, 0x4B, 0x4A, 0xE9 ), + BYTES_TO_T_UINT_8( 0x6C, 0x5C, 0xDC, 0x26, 0xC1, 0x55, 0x80, 0xFB ), + BYTES_TO_T_UINT_8( 0xE7, 0xFF, 0x7A, 0x41, 0x30, 0x75, 0xF6, 0xEE ), + BYTES_TO_T_UINT_8( 0x57, 0x30, 0x2C, 0xFC, 0x75, 0x09, 0x5A, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_b[] = { + BYTES_TO_T_UINT_8( 0xB6, 0x07, 0x8C, 0xFF, 0x18, 0xDC, 0xCC, 0x6B ), + BYTES_TO_T_UINT_8( 0xCE, 0xE1, 0xF7, 0x5C, 0x29, 0x16, 0x84, 0x95 ), + BYTES_TO_T_UINT_8( 0xBF, 0x7C, 0xD7, 0xBB, 0xD9, 0xB5, 0x30, 0xF3 ), + BYTES_TO_T_UINT_8( 0x44, 0x4B, 0x4A, 0xE9, 0x6C, 0x5C, 0xDC, 0x26 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gx[] = { + BYTES_TO_T_UINT_8( 0x62, 0x32, 0xCE, 0x9A, 0xBD, 0x53, 0x44, 0x3A ), + BYTES_TO_T_UINT_8( 0xC2, 0x23, 0xBD, 0xE3, 0xE1, 0x27, 0xDE, 0xB9 ), + BYTES_TO_T_UINT_8( 0xAF, 0xB7, 0x81, 0xFC, 0x2F, 0x48, 0x4B, 0x2C ), + BYTES_TO_T_UINT_8( 0xCB, 0x57, 0x7E, 0xCB, 0xB9, 0xAE, 0xD2, 0x8B ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_gy[] = { + BYTES_TO_T_UINT_8( 0x97, 0x69, 0x04, 0x2F, 0xC7, 0x54, 0x1D, 0x5C ), + BYTES_TO_T_UINT_8( 0x54, 0x8E, 0xED, 0x2D, 0x13, 0x45, 0x77, 0xC2 ), + BYTES_TO_T_UINT_8( 0xC9, 0x1D, 0x61, 0x14, 0x1A, 0x46, 0xF8, 0x97 ), + BYTES_TO_T_UINT_8( 0xFD, 0xC4, 0xDA, 0xC3, 0x35, 0xF8, 0x7E, 0x54 ), +}; +static const mbedtls_mpi_uint brainpoolP256r1_n[] = { + BYTES_TO_T_UINT_8( 0xA7, 0x56, 0x48, 0x97, 0x82, 0x0E, 0x1E, 0x90 ), + BYTES_TO_T_UINT_8( 0xF7, 0xA6, 0x61, 0xB5, 0xA3, 0x7A, 0x39, 0x8C ), + BYTES_TO_T_UINT_8( 0x71, 0x8D, 0x83, 0x9D, 0x90, 0x0A, 0x66, 0x3E ), + BYTES_TO_T_UINT_8( 0xBC, 0xA9, 0xEE, 0xA1, 0xDB, 0x57, 0xFB, 0xA9 ), +}; +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +/* + * Domain parameters for brainpoolP384r1 (RFC 5639 3.6) + */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP384r1_p[] = { + BYTES_TO_T_UINT_8( 0x53, 0xEC, 0x07, 0x31, 0x13, 0x00, 0x47, 0x87 ), + BYTES_TO_T_UINT_8( 0x71, 0x1A, 0x1D, 0x90, 0x29, 0xA7, 0xD3, 0xAC ), + BYTES_TO_T_UINT_8( 0x23, 0x11, 0xB7, 0x7F, 0x19, 0xDA, 0xB1, 0x12 ), + BYTES_TO_T_UINT_8( 0xB4, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_a[] = { + BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), + BYTES_TO_T_UINT_8( 0xEB, 0xD4, 0x3A, 0x50, 0x4A, 0x81, 0xA5, 0x8A ), + BYTES_TO_T_UINT_8( 0x0F, 0xF9, 0x91, 0xBA, 0xEF, 0x65, 0x91, 0x13 ), + BYTES_TO_T_UINT_8( 0x87, 0x27, 0xB2, 0x4F, 0x8E, 0xA2, 0xBE, 0xC2 ), + BYTES_TO_T_UINT_8( 0xA0, 0xAF, 0x05, 0xCE, 0x0A, 0x08, 0x72, 0x3C ), + BYTES_TO_T_UINT_8( 0x0C, 0x15, 0x8C, 0x3D, 0xC6, 0x82, 0xC3, 0x7B ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_b[] = { + BYTES_TO_T_UINT_8( 0x11, 0x4C, 0x50, 0xFA, 0x96, 0x86, 0xB7, 0x3A ), + BYTES_TO_T_UINT_8( 0x94, 0xC9, 0xDB, 0x95, 0x02, 0x39, 0xB4, 0x7C ), + BYTES_TO_T_UINT_8( 0xD5, 0x62, 0xEB, 0x3E, 0xA5, 0x0E, 0x88, 0x2E ), + BYTES_TO_T_UINT_8( 0xA6, 0xD2, 0xDC, 0x07, 0xE1, 0x7D, 0xB7, 0x2F ), + BYTES_TO_T_UINT_8( 0x7C, 0x44, 0xF0, 0x16, 0x54, 0xB5, 0x39, 0x8B ), + BYTES_TO_T_UINT_8( 0x26, 0x28, 0xCE, 0x22, 0xDD, 0xC7, 0xA8, 0x04 ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gx[] = { + BYTES_TO_T_UINT_8( 0x1E, 0xAF, 0xD4, 0x47, 0xE2, 0xB2, 0x87, 0xEF ), + BYTES_TO_T_UINT_8( 0xAA, 0x46, 0xD6, 0x36, 0x34, 0xE0, 0x26, 0xE8 ), + BYTES_TO_T_UINT_8( 0xE8, 0x10, 0xBD, 0x0C, 0xFE, 0xCA, 0x7F, 0xDB ), + BYTES_TO_T_UINT_8( 0xE3, 0x4F, 0xF1, 0x7E, 0xE7, 0xA3, 0x47, 0x88 ), + BYTES_TO_T_UINT_8( 0x6B, 0x3F, 0xC1, 0xB7, 0x81, 0x3A, 0xA6, 0xA2 ), + BYTES_TO_T_UINT_8( 0xFF, 0x45, 0xCF, 0x68, 0xF0, 0x64, 0x1C, 0x1D ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_gy[] = { + BYTES_TO_T_UINT_8( 0x15, 0x53, 0x3C, 0x26, 0x41, 0x03, 0x82, 0x42 ), + BYTES_TO_T_UINT_8( 0x11, 0x81, 0x91, 0x77, 0x21, 0x46, 0x46, 0x0E ), + BYTES_TO_T_UINT_8( 0x28, 0x29, 0x91, 0xF9, 0x4F, 0x05, 0x9C, 0xE1 ), + BYTES_TO_T_UINT_8( 0x64, 0x58, 0xEC, 0xFE, 0x29, 0x0B, 0xB7, 0x62 ), + BYTES_TO_T_UINT_8( 0x52, 0xD5, 0xCF, 0x95, 0x8E, 0xEB, 0xB1, 0x5C ), + BYTES_TO_T_UINT_8( 0xA4, 0xC2, 0xF9, 0x20, 0x75, 0x1D, 0xBE, 0x8A ), +}; +static const mbedtls_mpi_uint brainpoolP384r1_n[] = { + BYTES_TO_T_UINT_8( 0x65, 0x65, 0x04, 0xE9, 0x02, 0x32, 0x88, 0x3B ), + BYTES_TO_T_UINT_8( 0x10, 0xC3, 0x7F, 0x6B, 0xAF, 0xB6, 0x3A, 0xCF ), + BYTES_TO_T_UINT_8( 0xA7, 0x25, 0x04, 0xAC, 0x6C, 0x6E, 0x16, 0x1F ), + BYTES_TO_T_UINT_8( 0xB3, 0x56, 0x54, 0xED, 0x09, 0x71, 0x2F, 0x15 ), + BYTES_TO_T_UINT_8( 0xDF, 0x41, 0xE6, 0x50, 0x7E, 0x6F, 0x5D, 0x0F ), + BYTES_TO_T_UINT_8( 0x28, 0x6D, 0x38, 0xA3, 0x82, 0x1E, 0xB9, 0x8C ), +}; +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +/* + * Domain parameters for brainpoolP512r1 (RFC 5639 3.7) + */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) +static const mbedtls_mpi_uint brainpoolP512r1_p[] = { + BYTES_TO_T_UINT_8( 0xF3, 0x48, 0x3A, 0x58, 0x56, 0x60, 0xAA, 0x28 ), + BYTES_TO_T_UINT_8( 0x85, 0xC6, 0x82, 0x2D, 0x2F, 0xFF, 0x81, 0x28 ), + BYTES_TO_T_UINT_8( 0xE6, 0x80, 0xA3, 0xE6, 0x2A, 0xA1, 0xCD, 0xAE ), + BYTES_TO_T_UINT_8( 0x42, 0x68, 0xC6, 0x9B, 0x00, 0x9B, 0x4D, 0x7D ), + BYTES_TO_T_UINT_8( 0x71, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_a[] = { + BYTES_TO_T_UINT_8( 0xCA, 0x94, 0xFC, 0x77, 0x4D, 0xAC, 0xC1, 0xE7 ), + BYTES_TO_T_UINT_8( 0xB9, 0xC7, 0xF2, 0x2B, 0xA7, 0x17, 0x11, 0x7F ), + BYTES_TO_T_UINT_8( 0xB5, 0xC8, 0x9A, 0x8B, 0xC9, 0xF1, 0x2E, 0x0A ), + BYTES_TO_T_UINT_8( 0xA1, 0x3A, 0x25, 0xA8, 0x5A, 0x5D, 0xED, 0x2D ), + BYTES_TO_T_UINT_8( 0xBC, 0x63, 0x98, 0xEA, 0xCA, 0x41, 0x34, 0xA8 ), + BYTES_TO_T_UINT_8( 0x10, 0x16, 0xF9, 0x3D, 0x8D, 0xDD, 0xCB, 0x94 ), + BYTES_TO_T_UINT_8( 0xC5, 0x4C, 0x23, 0xAC, 0x45, 0x71, 0x32, 0xE2 ), + BYTES_TO_T_UINT_8( 0x89, 0x3B, 0x60, 0x8B, 0x31, 0xA3, 0x30, 0x78 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_b[] = { + BYTES_TO_T_UINT_8( 0x23, 0xF7, 0x16, 0x80, 0x63, 0xBD, 0x09, 0x28 ), + BYTES_TO_T_UINT_8( 0xDD, 0xE5, 0xBA, 0x5E, 0xB7, 0x50, 0x40, 0x98 ), + BYTES_TO_T_UINT_8( 0x67, 0x3E, 0x08, 0xDC, 0xCA, 0x94, 0xFC, 0x77 ), + BYTES_TO_T_UINT_8( 0x4D, 0xAC, 0xC1, 0xE7, 0xB9, 0xC7, 0xF2, 0x2B ), + BYTES_TO_T_UINT_8( 0xA7, 0x17, 0x11, 0x7F, 0xB5, 0xC8, 0x9A, 0x8B ), + BYTES_TO_T_UINT_8( 0xC9, 0xF1, 0x2E, 0x0A, 0xA1, 0x3A, 0x25, 0xA8 ), + BYTES_TO_T_UINT_8( 0x5A, 0x5D, 0xED, 0x2D, 0xBC, 0x63, 0x98, 0xEA ), + BYTES_TO_T_UINT_8( 0xCA, 0x41, 0x34, 0xA8, 0x10, 0x16, 0xF9, 0x3D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gx[] = { + BYTES_TO_T_UINT_8( 0x22, 0xF8, 0xB9, 0xBC, 0x09, 0x22, 0x35, 0x8B ), + BYTES_TO_T_UINT_8( 0x68, 0x5E, 0x6A, 0x40, 0x47, 0x50, 0x6D, 0x7C ), + BYTES_TO_T_UINT_8( 0x5F, 0x7D, 0xB9, 0x93, 0x7B, 0x68, 0xD1, 0x50 ), + BYTES_TO_T_UINT_8( 0x8D, 0xD4, 0xD0, 0xE2, 0x78, 0x1F, 0x3B, 0xFF ), + BYTES_TO_T_UINT_8( 0x8E, 0x09, 0xD0, 0xF4, 0xEE, 0x62, 0x3B, 0xB4 ), + BYTES_TO_T_UINT_8( 0xC1, 0x16, 0xD9, 0xB5, 0x70, 0x9F, 0xED, 0x85 ), + BYTES_TO_T_UINT_8( 0x93, 0x6A, 0x4C, 0x9C, 0x2E, 0x32, 0x21, 0x5A ), + BYTES_TO_T_UINT_8( 0x64, 0xD9, 0x2E, 0xD8, 0xBD, 0xE4, 0xAE, 0x81 ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_gy[] = { + BYTES_TO_T_UINT_8( 0x92, 0x08, 0xD8, 0x3A, 0x0F, 0x1E, 0xCD, 0x78 ), + BYTES_TO_T_UINT_8( 0x06, 0x54, 0xF0, 0xA8, 0x2F, 0x2B, 0xCA, 0xD1 ), + BYTES_TO_T_UINT_8( 0xAE, 0x63, 0x27, 0x8A, 0xD8, 0x4B, 0xCA, 0x5B ), + BYTES_TO_T_UINT_8( 0x5E, 0x48, 0x5F, 0x4A, 0x49, 0xDE, 0xDC, 0xB2 ), + BYTES_TO_T_UINT_8( 0x11, 0x81, 0x1F, 0x88, 0x5B, 0xC5, 0x00, 0xA0 ), + BYTES_TO_T_UINT_8( 0x1A, 0x7B, 0xA5, 0x24, 0x00, 0xF7, 0x09, 0xF2 ), + BYTES_TO_T_UINT_8( 0xFD, 0x22, 0x78, 0xCF, 0xA9, 0xBF, 0xEA, 0xC0 ), + BYTES_TO_T_UINT_8( 0xEC, 0x32, 0x63, 0x56, 0x5D, 0x38, 0xDE, 0x7D ), +}; +static const mbedtls_mpi_uint brainpoolP512r1_n[] = { + BYTES_TO_T_UINT_8( 0x69, 0x00, 0xA9, 0x9C, 0x82, 0x96, 0x87, 0xB5 ), + BYTES_TO_T_UINT_8( 0xDD, 0xDA, 0x5D, 0x08, 0x81, 0xD3, 0xB1, 0x1D ), + BYTES_TO_T_UINT_8( 0x47, 0x10, 0xAC, 0x7F, 0x19, 0x61, 0x86, 0x41 ), + BYTES_TO_T_UINT_8( 0x19, 0x26, 0xA9, 0x4C, 0x41, 0x5C, 0x3E, 0x55 ), + BYTES_TO_T_UINT_8( 0x70, 0x08, 0x33, 0x70, 0xCA, 0x9C, 0x63, 0xD6 ), + BYTES_TO_T_UINT_8( 0x0E, 0xD2, 0xC9, 0xB3, 0xB3, 0x8D, 0x30, 0xCB ), + BYTES_TO_T_UINT_8( 0x07, 0xFC, 0xC9, 0x33, 0xAE, 0xE6, 0xD4, 0x3F ), + BYTES_TO_T_UINT_8( 0x8B, 0xC4, 0xE9, 0xDB, 0xB8, 0x9D, 0xDD, 0xAA ), +}; +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +/* + * Create an MPI from embedded constants + * (assumes len is an exact multiple of sizeof mbedtls_mpi_uint) + */ +static inline void ecp_mpi_load( mbedtls_mpi *X, const mbedtls_mpi_uint *p, size_t len ) +{ + X->s = 1; + X->n = len / sizeof( mbedtls_mpi_uint ); + X->p = (mbedtls_mpi_uint *) p; +} + +/* + * Set an MPI to static value 1 + */ +static inline void ecp_mpi_set1( mbedtls_mpi *X ) +{ + static mbedtls_mpi_uint one[] = { 1 }; + X->s = 1; + X->n = 1; + X->p = one; +} + +/* + * Make group available from embedded constants + */ +static int ecp_group_load( mbedtls_ecp_group *grp, + const mbedtls_mpi_uint *p, size_t plen, + const mbedtls_mpi_uint *a, size_t alen, + const mbedtls_mpi_uint *b, size_t blen, + const mbedtls_mpi_uint *gx, size_t gxlen, + const mbedtls_mpi_uint *gy, size_t gylen, + const mbedtls_mpi_uint *n, size_t nlen) +{ + ecp_mpi_load( &grp->P, p, plen ); + if( a != NULL ) + ecp_mpi_load( &grp->A, a, alen ); + ecp_mpi_load( &grp->B, b, blen ); + ecp_mpi_load( &grp->N, n, nlen ); + + ecp_mpi_load( &grp->G.X, gx, gxlen ); + ecp_mpi_load( &grp->G.Y, gy, gylen ); + ecp_mpi_set1( &grp->G.Z ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + grp->h = 1; + + return( 0 ); +} + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* Forward declarations */ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +static int ecp_mod_p192( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +static int ecp_mod_p224( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +static int ecp_mod_p256( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +static int ecp_mod_p384( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +static int ecp_mod_p521( mbedtls_mpi * ); +#endif + +#define NIST_MODP( P ) grp->modp = ecp_mod_ ## P; +#else +#define NIST_MODP( P ) +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +/* Additional forward declarations */ +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +static int ecp_mod_p255( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +static int ecp_mod_p448( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +static int ecp_mod_p192k1( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +static int ecp_mod_p224k1( mbedtls_mpi * ); +#endif +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +static int ecp_mod_p256k1( mbedtls_mpi * ); +#endif + +#define LOAD_GROUP_A( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + G ## _a, sizeof( G ## _a ), \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ) ) + +#define LOAD_GROUP( G ) ecp_group_load( grp, \ + G ## _p, sizeof( G ## _p ), \ + NULL, 0, \ + G ## _b, sizeof( G ## _b ), \ + G ## _gx, sizeof( G ## _gx ), \ + G ## _gy, sizeof( G ## _gy ), \ + G ## _n, sizeof( G ## _n ) ) + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) +/* + * Specialized function for creating the Curve25519 group + */ +static int ecp_use_curve25519( mbedtls_ecp_group *grp ) +{ + int ret; + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "01DB42" ) ); + + /* P = 2^255 - 19 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 255 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 19 ) ); + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + /* N = 2^252 + 27742317777372353535851937790883648493 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->N, 16, + "14DEF9DEA2F79CD65812631A5CF5D3ED" ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 252, 1 ) ); + + /* Y intentionally not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 9 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); + mbedtls_mpi_free( &grp->G.Y ); + + /* Actually, the required msb for private keys */ + grp->nbits = 254; + +cleanup: + if( ret != 0 ) + mbedtls_ecp_group_free( grp ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) +/* + * Specialized function for creating the Curve448 group + */ +static int ecp_use_curve448( mbedtls_ecp_group *grp ) +{ + mbedtls_mpi Ns; + int ret; + + mbedtls_mpi_init( &Ns ); + + /* Actually ( A + 2 ) / 4 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &grp->A, 16, "98AA" ) ); + + /* P = 2^448 - 2^224 - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &grp->P, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &grp->P, &grp->P, 1 ) ); + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + /* Y intentionally not set, since we use x/z coordinates. + * This is used as a marker to identify Montgomery curves! */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.X, 5 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &grp->G.Z, 1 ) ); + mbedtls_mpi_free( &grp->G.Y ); + + /* N = 2^446 - 13818066809895115352007386748515426880336692474882178609894547503885 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( &grp->N, 446, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &Ns, 16, + "8335DC163BB124B65129C96FDE933D8D723A70AADC873D6D54A7BB0D" ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &grp->N, &grp->N, &Ns ) ); + + /* Actually, the required msb for private keys */ + grp->nbits = 447; + +cleanup: + mbedtls_mpi_free( &Ns ); + if( ret != 0 ) + mbedtls_ecp_group_free( grp ); + + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + +/* + * Set a group using well-known domain parameters + */ +int mbedtls_ecp_group_load( mbedtls_ecp_group *grp, mbedtls_ecp_group_id id ) +{ + mbedtls_ecp_group_free( grp ); + + grp->id = id; + + switch( id ) + { +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + case MBEDTLS_ECP_DP_SECP192R1: + NIST_MODP( p192 ); + return( LOAD_GROUP( secp192r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + case MBEDTLS_ECP_DP_SECP224R1: + NIST_MODP( p224 ); + return( LOAD_GROUP( secp224r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + case MBEDTLS_ECP_DP_SECP256R1: + NIST_MODP( p256 ); + return( LOAD_GROUP( secp256r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + case MBEDTLS_ECP_DP_SECP384R1: + NIST_MODP( p384 ); + return( LOAD_GROUP( secp384r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + case MBEDTLS_ECP_DP_SECP521R1: + NIST_MODP( p521 ); + return( LOAD_GROUP( secp521r1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + case MBEDTLS_ECP_DP_SECP192K1: + grp->modp = ecp_mod_p192k1; + return( LOAD_GROUP_A( secp192k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + case MBEDTLS_ECP_DP_SECP224K1: + grp->modp = ecp_mod_p224k1; + return( LOAD_GROUP_A( secp224k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + case MBEDTLS_ECP_DP_SECP256K1: + grp->modp = ecp_mod_p256k1; + return( LOAD_GROUP_A( secp256k1 ) ); +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + case MBEDTLS_ECP_DP_BP256R1: + return( LOAD_GROUP_A( brainpoolP256r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + case MBEDTLS_ECP_DP_BP384R1: + return( LOAD_GROUP_A( brainpoolP384r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + case MBEDTLS_ECP_DP_BP512R1: + return( LOAD_GROUP_A( brainpoolP512r1 ) ); +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + case MBEDTLS_ECP_DP_CURVE25519: + grp->modp = ecp_mod_p255; + return( ecp_use_curve25519( grp ) ); +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + case MBEDTLS_ECP_DP_CURVE448: + grp->modp = ecp_mod_p448; + return( ecp_use_curve448( grp ) ); +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + + default: + mbedtls_ecp_group_free( grp ); + return( MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ); + } +} + +#if defined(MBEDTLS_ECP_NIST_OPTIM) +/* + * Fast reduction modulo the primes used by the NIST curves. + * + * These functions are critical for speed, but not needed for correct + * operations. So, we make the choice to heavily rely on the internals of our + * bignum library, which creates a tight coupling between these functions and + * our MPI implementation. However, the coupling between the ECP module and + * MPI remains loose, since these functions can be deactivated at will. + */ + +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) +/* + * Compared to the way things are presented in FIPS 186-3 D.2, + * we proceed in columns, from right (least significant chunk) to left, + * adding chunks to N in place, and keeping a carry for the next chunk. + * This avoids moving things around in memory, and uselessly adding zeros, + * compared to the more straightforward, line-oriented approach. + * + * For this prime we need to handle data in chunks of 64 bits. + * Since this is always a multiple of our basic mbedtls_mpi_uint, we can + * use a mbedtls_mpi_uint * to designate such a chunk, and small loops to handle it. + */ + +/* Add 64-bit chunks (dst += src) and update carry */ +static inline void add64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *src, mbedtls_mpi_uint *carry ) +{ + unsigned char i; + mbedtls_mpi_uint c = 0; + for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++, src++ ) + { + *dst += c; c = ( *dst < c ); + *dst += *src; c += ( *dst < *src ); + } + *carry += c; +} + +/* Add carry to a 64-bit chunk and update carry */ +static inline void carry64( mbedtls_mpi_uint *dst, mbedtls_mpi_uint *carry ) +{ + unsigned char i; + for( i = 0; i < 8 / sizeof( mbedtls_mpi_uint ); i++, dst++ ) + { + *dst += *carry; + *carry = ( *dst < *carry ); + } +} + +#define WIDTH 8 / sizeof( mbedtls_mpi_uint ) +#define A( i ) N->p + i * WIDTH +#define ADD( i ) add64( p, A( i ), &c ) +#define NEXT p += WIDTH; carry64( p, &c ) +#define LAST p += WIDTH; *p = c; while( ++p < end ) *p = 0 + +/* + * Fast quasi-reduction modulo p192 (FIPS 186-3 D.2.1) + */ +static int ecp_mod_p192( mbedtls_mpi *N ) +{ + int ret; + mbedtls_mpi_uint c = 0; + mbedtls_mpi_uint *p, *end; + + /* Make sure we have enough blocks so that A(5) is legal */ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, 6 * WIDTH ) ); + + p = N->p; + end = p + N->n; + + ADD( 3 ); ADD( 5 ); NEXT; // A0 += A3 + A5 + ADD( 3 ); ADD( 4 ); ADD( 5 ); NEXT; // A1 += A3 + A4 + A5 + ADD( 4 ); ADD( 5 ); LAST; // A2 += A4 + A5 + +cleanup: + return( ret ); +} + +#undef WIDTH +#undef A +#undef ADD +#undef NEXT +#undef LAST +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * The reader is advised to first understand ecp_mod_p192() since the same + * general structure is used here, but with additional complications: + * (1) chunks of 32 bits, and (2) subtractions. + */ + +/* + * For these primes, we need to handle data in chunks of 32 bits. + * This makes it more complicated if we use 64 bits limbs in MPI, + * which prevents us from using a uniform access method as for p192. + * + * So, we define a mini abstraction layer to access 32 bit chunks, + * load them in 'cur' for work, and store them back from 'cur' when done. + * + * While at it, also define the size of N in terms of 32-bit chunks. + */ +#define LOAD32 cur = A( i ); + +#if defined(MBEDTLS_HAVE_INT32) /* 32 bit */ + +#define MAX32 N->n +#define A( j ) N->p[j] +#define STORE32 N->p[i] = cur; + +#else /* 64-bit */ + +#define MAX32 N->n * 2 +#define A( j ) j % 2 ? (uint32_t)( N->p[j/2] >> 32 ) : (uint32_t)( N->p[j/2] ) +#define STORE32 \ + if( i % 2 ) { \ + N->p[i/2] &= 0x00000000FFFFFFFF; \ + N->p[i/2] |= ((mbedtls_mpi_uint) cur) << 32; \ + } else { \ + N->p[i/2] &= 0xFFFFFFFF00000000; \ + N->p[i/2] |= (mbedtls_mpi_uint) cur; \ + } + +#endif /* sizeof( mbedtls_mpi_uint ) */ + +/* + * Helpers for addition and subtraction of chunks, with signed carry. + */ +static inline void add32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *dst += src; + *carry += ( *dst < src ); +} + +static inline void sub32( uint32_t *dst, uint32_t src, signed char *carry ) +{ + *carry -= ( *dst < src ); + *dst -= src; +} + +#define ADD( j ) add32( &cur, A( j ), &c ); +#define SUB( j ) sub32( &cur, A( j ), &c ); + +/* + * Helpers for the main 'loop' + * (see fix_negative for the motivation of C) + */ +#define INIT( b ) \ + int ret; \ + signed char c = 0, cc; \ + uint32_t cur; \ + size_t i = 0, bits = b; \ + mbedtls_mpi C; \ + mbedtls_mpi_uint Cp[ b / 8 / sizeof( mbedtls_mpi_uint) + 1 ]; \ + \ + C.s = 1; \ + C.n = b / 8 / sizeof( mbedtls_mpi_uint) + 1; \ + C.p = Cp; \ + memset( Cp, 0, C.n * sizeof( mbedtls_mpi_uint ) ); \ + \ + MBEDTLS_MPI_CHK( mbedtls_mpi_grow( N, b * 2 / 8 / sizeof( mbedtls_mpi_uint ) ) ); \ + LOAD32; + +#define NEXT \ + STORE32; i++; LOAD32; \ + cc = c; c = 0; \ + if( cc < 0 ) \ + sub32( &cur, -cc, &c ); \ + else \ + add32( &cur, cc, &c ); \ + +#define LAST \ + STORE32; i++; \ + cur = c > 0 ? c : 0; STORE32; \ + cur = 0; while( ++i < MAX32 ) { STORE32; } \ + if( c < 0 ) fix_negative( N, c, &C, bits ); + +/* + * If the result is negative, we get it in the form + * c * 2^(bits + 32) + N, with c negative and N positive shorter than 'bits' + */ +static inline int fix_negative( mbedtls_mpi *N, signed char c, mbedtls_mpi *C, size_t bits ) +{ + int ret; + + /* C = - c * 2^(bits + 32) */ +#if !defined(MBEDTLS_HAVE_INT64) + ((void) bits); +#else + if( bits == 224 ) + C->p[ C->n - 1 ] = ((mbedtls_mpi_uint) -c) << 32; + else +#endif + C->p[ C->n - 1 ] = (mbedtls_mpi_uint) -c; + + /* N = - ( C - N ) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_abs( N, C, N ) ); + N->s = -1; + +cleanup: + + return( ret ); +} + +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) +/* + * Fast quasi-reduction modulo p224 (FIPS 186-3 D.2.2) + */ +static int ecp_mod_p224( mbedtls_mpi *N ) +{ + INIT( 224 ); + + SUB( 7 ); SUB( 11 ); NEXT; // A0 += -A7 - A11 + SUB( 8 ); SUB( 12 ); NEXT; // A1 += -A8 - A12 + SUB( 9 ); SUB( 13 ); NEXT; // A2 += -A9 - A13 + SUB( 10 ); ADD( 7 ); ADD( 11 ); NEXT; // A3 += -A10 + A7 + A11 + SUB( 11 ); ADD( 8 ); ADD( 12 ); NEXT; // A4 += -A11 + A8 + A12 + SUB( 12 ); ADD( 9 ); ADD( 13 ); NEXT; // A5 += -A12 + A9 + A13 + SUB( 13 ); ADD( 10 ); LAST; // A6 += -A13 + A10 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) +/* + * Fast quasi-reduction modulo p256 (FIPS 186-3 D.2.3) + */ +static int ecp_mod_p256( mbedtls_mpi *N ) +{ + INIT( 256 ); + + ADD( 8 ); ADD( 9 ); + SUB( 11 ); SUB( 12 ); SUB( 13 ); SUB( 14 ); NEXT; // A0 + + ADD( 9 ); ADD( 10 ); + SUB( 12 ); SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A1 + + ADD( 10 ); ADD( 11 ); + SUB( 13 ); SUB( 14 ); SUB( 15 ); NEXT; // A2 + + ADD( 11 ); ADD( 11 ); ADD( 12 ); ADD( 12 ); ADD( 13 ); + SUB( 15 ); SUB( 8 ); SUB( 9 ); NEXT; // A3 + + ADD( 12 ); ADD( 12 ); ADD( 13 ); ADD( 13 ); ADD( 14 ); + SUB( 9 ); SUB( 10 ); NEXT; // A4 + + ADD( 13 ); ADD( 13 ); ADD( 14 ); ADD( 14 ); ADD( 15 ); + SUB( 10 ); SUB( 11 ); NEXT; // A5 + + ADD( 14 ); ADD( 14 ); ADD( 15 ); ADD( 15 ); ADD( 14 ); ADD( 13 ); + SUB( 8 ); SUB( 9 ); NEXT; // A6 + + ADD( 15 ); ADD( 15 ); ADD( 15 ); ADD( 8 ); + SUB( 10 ); SUB( 11 ); SUB( 12 ); SUB( 13 ); LAST; // A7 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) +/* + * Fast quasi-reduction modulo p384 (FIPS 186-3 D.2.4) + */ +static int ecp_mod_p384( mbedtls_mpi *N ) +{ + INIT( 384 ); + + ADD( 12 ); ADD( 21 ); ADD( 20 ); + SUB( 23 ); NEXT; // A0 + + ADD( 13 ); ADD( 22 ); ADD( 23 ); + SUB( 12 ); SUB( 20 ); NEXT; // A2 + + ADD( 14 ); ADD( 23 ); + SUB( 13 ); SUB( 21 ); NEXT; // A2 + + ADD( 15 ); ADD( 12 ); ADD( 20 ); ADD( 21 ); + SUB( 14 ); SUB( 22 ); SUB( 23 ); NEXT; // A3 + + ADD( 21 ); ADD( 21 ); ADD( 16 ); ADD( 13 ); ADD( 12 ); ADD( 20 ); ADD( 22 ); + SUB( 15 ); SUB( 23 ); SUB( 23 ); NEXT; // A4 + + ADD( 22 ); ADD( 22 ); ADD( 17 ); ADD( 14 ); ADD( 13 ); ADD( 21 ); ADD( 23 ); + SUB( 16 ); NEXT; // A5 + + ADD( 23 ); ADD( 23 ); ADD( 18 ); ADD( 15 ); ADD( 14 ); ADD( 22 ); + SUB( 17 ); NEXT; // A6 + + ADD( 19 ); ADD( 16 ); ADD( 15 ); ADD( 23 ); + SUB( 18 ); NEXT; // A7 + + ADD( 20 ); ADD( 17 ); ADD( 16 ); + SUB( 19 ); NEXT; // A8 + + ADD( 21 ); ADD( 18 ); ADD( 17 ); + SUB( 20 ); NEXT; // A9 + + ADD( 22 ); ADD( 19 ); ADD( 18 ); + SUB( 21 ); NEXT; // A10 + + ADD( 23 ); ADD( 20 ); ADD( 19 ); + SUB( 22 ); LAST; // A11 + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#undef A +#undef LOAD32 +#undef STORE32 +#undef MAX32 +#undef INIT +#undef NEXT +#undef LAST + +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED || + MBEDTLS_ECP_DP_SECP256R1_ENABLED || + MBEDTLS_ECP_DP_SECP384R1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) +/* + * Here we have an actual Mersenne prime, so things are more straightforward. + * However, chunks are aligned on a 'weird' boundary (521 bits). + */ + +/* Size of p521 in terms of mbedtls_mpi_uint */ +#define P521_WIDTH ( 521 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) + +/* Bits to keep in the most significant mbedtls_mpi_uint */ +#define P521_MASK 0x01FF + +/* + * Fast quasi-reduction modulo p521 (FIPS 186-3 D.2.5) + * Write N as A1 + 2^521 A0, return A0 + A1 + */ +static int ecp_mod_p521( mbedtls_mpi *N ) +{ + int ret; + size_t i; + mbedtls_mpi M; + mbedtls_mpi_uint Mp[P521_WIDTH + 1]; + /* Worst case for the size of M is when mbedtls_mpi_uint is 16 bits: + * we need to hold bits 513 to 1056, which is 34 limbs, that is + * P521_WIDTH + 1. Otherwise P521_WIDTH is enough. */ + + if( N->n < P521_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P521_WIDTH - 1 ); + if( M.n > P521_WIDTH + 1 ) + M.n = P521_WIDTH + 1; + M.p = Mp; + memcpy( Mp, N->p + P521_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 521 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); + + /* N = A0 */ + N->p[P521_WIDTH - 1] &= P521_MASK; + for( i = P521_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} + +#undef P521_WIDTH +#undef P521_MASK +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ + +#endif /* MBEDTLS_ECP_NIST_OPTIM */ + +#if defined(MBEDTLS_ECP_DP_CURVE25519_ENABLED) + +/* Size of p255 in terms of mbedtls_mpi_uint */ +#define P255_WIDTH ( 255 / 8 / sizeof( mbedtls_mpi_uint ) + 1 ) + +/* + * Fast quasi-reduction modulo p255 = 2^255 - 19 + * Write N as A0 + 2^255 A1, return A0 + 19 * A1 + */ +static int ecp_mod_p255( mbedtls_mpi *N ) +{ + int ret; + size_t i; + mbedtls_mpi M; + mbedtls_mpi_uint Mp[P255_WIDTH + 2]; + + if( N->n < P255_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P255_WIDTH - 1 ); + if( M.n > P255_WIDTH + 1 ) + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + M.p = Mp; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + P255_WIDTH - 1, M.n * sizeof( mbedtls_mpi_uint ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, 255 % ( 8 * sizeof( mbedtls_mpi_uint ) ) ) ); + M.n++; /* Make room for multiplication by 19 */ + + /* N = A0 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_set_bit( N, 255, 0 ) ); + for( i = P255_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + 19 * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_int( &M, &M, 19 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE25519_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_CURVE448_ENABLED) + +/* Size of p448 in terms of mbedtls_mpi_uint */ +#define P448_WIDTH ( 448 / 8 / sizeof( mbedtls_mpi_uint ) ) + +/* Number of limbs fully occupied by 2^224 (max), and limbs used by it (min) */ +#define DIV_ROUND_UP( X, Y ) ( ( ( X ) + ( Y ) - 1 ) / ( Y ) ) +#define P224_WIDTH_MIN ( 28 / sizeof( mbedtls_mpi_uint ) ) +#define P224_WIDTH_MAX DIV_ROUND_UP( 28, sizeof( mbedtls_mpi_uint ) ) +#define P224_UNUSED_BITS ( ( P224_WIDTH_MAX * sizeof( mbedtls_mpi_uint ) * 8 ) - 224 ) + +/* + * Fast quasi-reduction modulo p448 = 2^448 - 2^224 - 1 + * Write N as A0 + 2^448 A1 and A1 as B0 + 2^224 B1, and return + * A0 + A1 + B1 + (B0 + B1) * 2^224. This is different to the reference + * implementation of Curve448, which uses its own special 56-bit limbs rather + * than a generic bignum library. We could squeeze some extra speed out on + * 32-bit machines by splitting N up into 32-bit limbs and doing the + * arithmetic using the limbs directly as we do for the NIST primes above, + * but for 64-bit targets it should use half the number of operations if we do + * the reduction with 224-bit limbs, since mpi_add_mpi will then use 64-bit adds. + */ +static int ecp_mod_p448( mbedtls_mpi *N ) +{ + int ret; + size_t i; + mbedtls_mpi M, Q; + mbedtls_mpi_uint Mp[P448_WIDTH + 1], Qp[P448_WIDTH]; + + if( N->n <= P448_WIDTH ) + return( 0 ); + + /* M = A1 */ + M.s = 1; + M.n = N->n - ( P448_WIDTH ); + if( M.n > P448_WIDTH ) + /* Shouldn't be called with N larger than 2^896! */ + return( MBEDTLS_ERR_ECP_BAD_INPUT_DATA ); + M.p = Mp; + memset( Mp, 0, sizeof( Mp ) ); + memcpy( Mp, N->p + P448_WIDTH, M.n * sizeof( mbedtls_mpi_uint ) ); + + /* N = A0 */ + for( i = P448_WIDTH; i < N->n; i++ ) + N->p[i] = 0; + + /* N += A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) ); + + /* Q = B1, N += B1 */ + Q = M; + Q.p = Qp; + memcpy( Qp, Mp, sizeof( Qp ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &Q, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &Q ) ); + + /* M = (B0 + B1) * 2^224, N += M */ + if( sizeof( mbedtls_mpi_uint ) > 4 ) + Mp[P224_WIDTH_MIN] &= ( (mbedtls_mpi_uint)-1 ) >> ( P224_UNUSED_BITS ); + for( i = P224_WIDTH_MAX; i < M.n; ++i ) + Mp[i] = 0; + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &M, &M, &Q ) ); + M.n = P448_WIDTH + 1; /* Make room for shifted carry bit from the addition */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l( &M, 224 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_CURVE448_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) || \ + defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo P = 2^s - R, + * with R about 33 bits, used by the Koblitz curves. + * + * Write N as A0 + 2^224 A1, return A0 + R * A1. + * Actually do two passes, since R is big. + */ +#define P_KOBLITZ_MAX ( 256 / 8 / sizeof( mbedtls_mpi_uint ) ) // Max limbs in P +#define P_KOBLITZ_R ( 8 / sizeof( mbedtls_mpi_uint ) ) // Limbs in R +static inline int ecp_mod_koblitz( mbedtls_mpi *N, mbedtls_mpi_uint *Rp, size_t p_limbs, + size_t adjust, size_t shift, mbedtls_mpi_uint mask ) +{ + int ret; + size_t i; + mbedtls_mpi M, R; + mbedtls_mpi_uint Mp[P_KOBLITZ_MAX + P_KOBLITZ_R + 1]; + + if( N->n < p_limbs ) + return( 0 ); + + /* Init R */ + R.s = 1; + R.p = Rp; + R.n = P_KOBLITZ_R; + + /* Common setup for M */ + M.s = 1; + M.p = Mp; + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); + if( shift != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); + M.n += R.n; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + + /* Second pass */ + + /* M = A1 */ + M.n = N->n - ( p_limbs - adjust ); + if( M.n > p_limbs + adjust ) + M.n = p_limbs + adjust; + memset( Mp, 0, sizeof Mp ); + memcpy( Mp, N->p + p_limbs - adjust, M.n * sizeof( mbedtls_mpi_uint ) ); + if( shift != 0 ) + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &M, shift ) ); + M.n += R.n; /* Make room for multiplication by R */ + + /* N = A0 */ + if( mask != 0 ) + N->p[p_limbs - 1] &= mask; + for( i = p_limbs; i < N->n; i++ ) + N->p[i] = 0; + + /* N = A0 + R * A1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &M, &M, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_abs( N, N, &M ) ); + +cleanup: + return( ret ); +} +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED) || + MBEDTLS_ECP_DP_SECP224K1_ENABLED) || + MBEDTLS_ECP_DP_SECP256K1_ENABLED) */ + +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) +/* + * Fast quasi-reduction modulo p192k1 = 2^192 - R, + * with R = 2^32 + 2^12 + 2^8 + 2^7 + 2^6 + 2^3 + 1 = 0x0100001119 + */ +static int ecp_mod_p192k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xC9, 0x11, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + + return( ecp_mod_koblitz( N, Rp, 192 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +} +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) +/* + * Fast quasi-reduction modulo p224k1 = 2^224 - R, + * with R = 2^32 + 2^12 + 2^11 + 2^9 + 2^7 + 2^4 + 2 + 1 = 0x0100001A93 + */ +static int ecp_mod_p224k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0x93, 0x1A, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + +#if defined(MBEDTLS_HAVE_INT64) + return( ecp_mod_koblitz( N, Rp, 4, 1, 32, 0xFFFFFFFF ) ); +#else + return( ecp_mod_koblitz( N, Rp, 224 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +#endif +} + +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ + +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) +/* + * Fast quasi-reduction modulo p256k1 = 2^256 - R, + * with R = 2^32 + 2^9 + 2^8 + 2^7 + 2^6 + 2^4 + 1 = 0x01000003D1 + */ +static int ecp_mod_p256k1( mbedtls_mpi *N ) +{ + static mbedtls_mpi_uint Rp[] = { + BYTES_TO_T_UINT_8( 0xD1, 0x03, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00 ) }; + return( ecp_mod_koblitz( N, Rp, 256 / 8 / sizeof( mbedtls_mpi_uint ), 0, 0, 0 ) ); +} +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ + +#endif /* !MBEDTLS_ECP_ALT */ + +#endif /* MBEDTLS_ECP_C */ diff --git a/common/mbedtls/ecp_internal.h b/common/mbedtls/ecp_internal.h new file mode 100644 index 000000000..73bccd426 --- /dev/null +++ b/common/mbedtls/ecp_internal.h @@ -0,0 +1,295 @@ +/** + * \file ecp_internal.h + * + * \brief Function declarations for alternative implementation of elliptic curve + * point arithmetic. + */ +/* + * Copyright (C) 2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * References: + * + * [1] BERNSTEIN, Daniel J. Curve25519: new Diffie-Hellman speed records. + * + * + * [2] CORON, Jean-S'ebastien. Resistance against differential power analysis + * for elliptic curve cryptosystems. In : Cryptographic Hardware and + * Embedded Systems. Springer Berlin Heidelberg, 1999. p. 292-302. + * + * + * [3] HEDABOU, Mustapha, PINEL, Pierre, et B'EN'ETEAU, Lucien. A comb method to + * render ECC resistant against Side Channel Attacks. IACR Cryptology + * ePrint Archive, 2004, vol. 2004, p. 342. + * + * + * [4] Certicom Research. SEC 2: Recommended Elliptic Curve Domain Parameters. + * + * + * [5] HANKERSON, Darrel, MENEZES, Alfred J., VANSTONE, Scott. Guide to Elliptic + * Curve Cryptography. + * + * [6] Digital Signature Standard (DSS), FIPS 186-4. + * + * + * [7] Elliptic Curve Cryptography (ECC) Cipher Suites for Transport Layer + * Security (TLS), RFC 4492. + * + * + * [8] + * + * [9] COHEN, Henri. A Course in Computational Algebraic Number Theory. + * Springer Science & Business Media, 1 Aug 2000 + */ + +#ifndef MBEDTLS_ECP_INTERNAL_H +#define MBEDTLS_ECP_INTERNAL_H + +#if defined(MBEDTLS_ECP_INTERNAL_ALT) + +/** + * \brief Indicate if the Elliptic Curve Point module extension can + * handle the group. + * + * \param grp The pointer to the elliptic curve group that will be the + * basis of the cryptographic computations. + * + * \return Non-zero if successful. + */ +unsigned char mbedtls_internal_ecp_grp_capable( const mbedtls_ecp_group *grp ); + +/** + * \brief Initialise the Elliptic Curve Point module extension. + * + * If mbedtls_internal_ecp_grp_capable returns true for a + * group, this function has to be able to initialise the + * module for it. + * + * This module can be a driver to a crypto hardware + * accelerator, for which this could be an initialise function. + * + * \param grp The pointer to the group the module needs to be + * initialised for. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_init( const mbedtls_ecp_group *grp ); + +/** + * \brief Frees and deallocates the Elliptic Curve Point module + * extension. + * + * \param grp The pointer to the group the module was initialised for. + */ +void mbedtls_internal_ecp_free( const mbedtls_ecp_group *grp ); + +#if defined(ECP_SHORTWEIERSTRASS) + +#if defined(MBEDTLS_ECP_RANDOMIZE_JAC_ALT) +/** + * \brief Randomize jacobian coordinates: + * (X, Y, Z) -> (l^2 X, l^3 Y, l Z) for random l. + * + * \param grp Pointer to the group representing the curve. + * + * \param pt The point on the curve to be randomised, given with Jacobian + * coordinates. + * + * \param f_rng A function pointer to the random number generator. + * + * \param p_rng A pointer to the random number generator state. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_randomize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt, int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif + +#if defined(MBEDTLS_ECP_ADD_MIXED_ALT) +/** + * \brief Addition: R = P + Q, mixed affine-Jacobian coordinates. + * + * The coordinates of Q must be normalized (= affine), + * but those of P don't need to. R is not normalized. + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Special cases: (1) P or Q is zero, (2) R is zero, + * (3) P == Q. + * None of these cases can happen as intermediate step in + * ecp_mul_comb(): + * - at each step, P, Q and R are multiples of the base + * point, the factor being less than its order, so none of + * them is zero; + * - Q is an odd multiple of the base point, P an even + * multiple, due to the choice of precomputed points in the + * modified comb method. + * So branches for these cases do not leak secret information. + * + * We accept Q->Z being unset (saving memory in tables) as + * meaning 1. + * + * Cost in field operations if done by [5] 3.22: + * 1A := 8M + 3S + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the first summand, given with Jacobian + * coordinates + * + * \param Q Pointer to the second summand, given with affine + * coordinates. + * + * \return 0 if successful. + */ +int mbedtls_internal_ecp_add_mixed( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q ); +#endif + +/** + * \brief Point doubling R = 2 P, Jacobian coordinates. + * + * Cost: 1D := 3M + 4S (A == 0) + * 4M + 4S (A == -3) + * 3M + 6S + 1a otherwise + * when the implementation is based on the "dbl-1998-cmo-2" + * doubling formulas in [8] and standard optimizations are + * applied when curve parameter A is one of { 0, -3 }. + * + * \param grp Pointer to the group representing the curve. + * + * \param R Pointer to a point structure to hold the result. + * + * \param P Pointer to the point that has to be doubled, given with + * Jacobian coordinates. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_DOUBLE_JAC_ALT) +int mbedtls_internal_ecp_double_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, const mbedtls_ecp_point *P ); +#endif + +/** + * \brief Normalize jacobian coordinates of an array of (pointers to) + * points. + * + * Using Montgomery's trick to perform only one inversion mod P + * the cost is: + * 1N(t) := 1I + (6t - 3)M + 1S + * (See for example Algorithm 10.3.4. in [9]) + * + * This function is used only as a subrutine of + * ecp_mul_comb(). + * + * Warning: fails (returning an error) if one of the points is + * zero! + * This should never happen, see choice of w in ecp_mul_comb(). + * + * \param grp Pointer to the group representing the curve. + * + * \param T Array of pointers to the points to normalise. + * + * \param t_len Number of elements in the array. + * + * \return 0 if successful, + * an error if one of the points is zero. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_MANY_ALT) +int mbedtls_internal_ecp_normalize_jac_many( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *T[], size_t t_len ); +#endif + +/** + * \brief Normalize jacobian coordinates so that Z == 0 || Z == 1. + * + * Cost in field operations if done by [5] 3.2.1: + * 1N := 1I + 3M + 1S + * + * \param grp Pointer to the group representing the curve. + * + * \param pt pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful. + */ +#if defined(MBEDTLS_ECP_NORMALIZE_JAC_ALT) +int mbedtls_internal_ecp_normalize_jac( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *pt ); +#endif + +#endif /* ECP_SHORTWEIERSTRASS */ + +#if defined(ECP_MONTGOMERY) + +#if defined(MBEDTLS_ECP_DOUBLE_ADD_MXZ_ALT) +int mbedtls_internal_ecp_double_add_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *R, mbedtls_ecp_point *S, const mbedtls_ecp_point *P, + const mbedtls_ecp_point *Q, const mbedtls_mpi *d ); +#endif + +/** + * \brief Randomize projective x/z coordinates: + * (X, Z) -> (l X, l Z) for random l + * + * \param grp pointer to the group representing the curve + * + * \param P the point on the curve to be randomised given with + * projective coordinates. This is an input/output parameter. + * + * \param f_rng a function pointer to the random number generator + * + * \param p_rng a pointer to the random number generator state + * + * \return 0 if successful + */ +#if defined(MBEDTLS_ECP_RANDOMIZE_MXZ_ALT) +int mbedtls_internal_ecp_randomize_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P, int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif + +/** + * \brief Normalize Montgomery x/z coordinates: X = X/Z, Z = 1. + * + * \param grp pointer to the group representing the curve + * + * \param P pointer to the point to be normalised. This is an + * input/output parameter. + * + * \return 0 if successful + */ +#if defined(MBEDTLS_ECP_NORMALIZE_MXZ_ALT) +int mbedtls_internal_ecp_normalize_mxz( const mbedtls_ecp_group *grp, + mbedtls_ecp_point *P ); +#endif + +#endif /* ECP_MONTGOMERY */ + +#endif /* MBEDTLS_ECP_INTERNAL_ALT */ + +#endif /* ecp_internal.h */ + diff --git a/common/mbedtls/entropy.c b/common/mbedtls/entropy.c new file mode 100644 index 000000000..33f925155 --- /dev/null +++ b/common/mbedtls/entropy.c @@ -0,0 +1,723 @@ +/* + * Entropy accumulator implementation + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ENTROPY_C) + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +#warning "**** WARNING! MBEDTLS_TEST_NULL_ENTROPY defined! " +#warning "**** THIS BUILD HAS NO DEFINED ENTROPY SOURCES " +#warning "**** THIS BUILD IS *NOT* SUITABLE FOR PRODUCTION USE " +#endif + +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#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 */ + +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif + +#define ENTROPY_MAX_LOOP 256 /**< Maximum amount to loop before error */ + +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ) +{ + ctx->source_count = 0; + memset( ctx->source, 0, sizeof( ctx->source ) ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif + + ctx->accumulator_started = 0; +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_init( &ctx->accumulator ); +#else + mbedtls_sha256_init( &ctx->accumulator ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_init( &ctx->havege_data ); +#endif + + /* Reminder: Update ENTROPY_HAVE_STRONG in the test files + * when adding more strong entropy sources here. */ + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_add_source( ctx, mbedtls_null_entropy_poll, NULL, + 1, MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif + +#if !defined(MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES) +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + mbedtls_entropy_add_source( ctx, mbedtls_platform_entropy_poll, NULL, + MBEDTLS_ENTROPY_MIN_PLATFORM, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_TIMING_C) + mbedtls_entropy_add_source( ctx, mbedtls_hardclock_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDCLOCK, + MBEDTLS_ENTROPY_SOURCE_WEAK ); +#endif +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_entropy_add_source( ctx, mbedtls_havege_poll, &ctx->havege_data, + MBEDTLS_ENTROPY_MIN_HAVEGE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + mbedtls_entropy_add_source( ctx, mbedtls_hardware_poll, NULL, + MBEDTLS_ENTROPY_MIN_HARDWARE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + mbedtls_entropy_add_source( ctx, mbedtls_nv_seed_poll, NULL, + MBEDTLS_ENTROPY_BLOCK_SIZE, + MBEDTLS_ENTROPY_SOURCE_STRONG ); + ctx->initial_entropy_run = 0; +#endif +#endif /* MBEDTLS_NO_DEFAULT_ENTROPY_SOURCES */ +} + +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ) +{ +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_free( &ctx->havege_data ); +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_free( &ctx->accumulator ); +#else + mbedtls_sha256_free( &ctx->accumulator ); +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + ctx->initial_entropy_run = 0; +#endif + ctx->source_count = 0; + mbedtls_platform_zeroize( ctx->source, sizeof( ctx->source ) ); + ctx->accumulator_started = 0; +} + +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ) +{ + int idx, ret = 0; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + idx = ctx->source_count; + if( idx >= MBEDTLS_ENTROPY_MAX_SOURCES ) + { + ret = MBEDTLS_ERR_ENTROPY_MAX_SOURCES; + goto exit; + } + + ctx->source[idx].f_source = f_source; + ctx->source[idx].p_source = p_source; + ctx->source[idx].threshold = threshold; + ctx->source[idx].strong = strong; + + ctx->source_count++; + +exit: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Entropy accumulator update + */ +static int entropy_update( mbedtls_entropy_context *ctx, unsigned char source_id, + const unsigned char *data, size_t len ) +{ + unsigned char header[2]; + unsigned char tmp[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = len; + const unsigned char *p = data; + int ret = 0; + + if( use_len > MBEDTLS_ENTROPY_BLOCK_SIZE ) + { +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + if( ( ret = mbedtls_sha512_ret( data, len, tmp, 0 ) ) != 0 ) + goto cleanup; +#else + if( ( ret = mbedtls_sha256_ret( data, len, tmp, 0 ) ) != 0 ) + goto cleanup; +#endif + p = tmp; + use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + } + + header[0] = source_id; + header[1] = use_len & 0xFF; + + /* + * Start the accumulator if this has not already happened. Note that + * it is sufficient to start the accumulator here only because all calls to + * gather entropy eventually execute this code. + */ +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + if( ctx->accumulator_started == 0 && + ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto cleanup; + else + ctx->accumulator_started = 1; + if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) + goto cleanup; + ret = mbedtls_sha512_update_ret( &ctx->accumulator, p, use_len ); +#else + if( ctx->accumulator_started == 0 && + ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto cleanup; + else + ctx->accumulator_started = 1; + if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, header, 2 ) ) != 0 ) + goto cleanup; + ret = mbedtls_sha256_update_ret( &ctx->accumulator, p, use_len ); +#endif + +cleanup: + mbedtls_platform_zeroize( tmp, sizeof( tmp ) ); + + return( ret ); +} + +int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len ) +{ + int ret; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_update( ctx, MBEDTLS_ENTROPY_SOURCE_MANUAL, data, len ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +/* + * Run through the different sources to add entropy to our accumulator + */ +static int entropy_gather_internal( mbedtls_entropy_context *ctx ) +{ + int ret, i, have_one_strong = 0; + unsigned char buf[MBEDTLS_ENTROPY_MAX_GATHER]; + size_t olen; + + if( ctx->source_count == 0 ) + return( MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED ); + + /* + * Run through our entropy sources + */ + for( i = 0; i < ctx->source_count; i++ ) + { + if( ctx->source[i].strong == MBEDTLS_ENTROPY_SOURCE_STRONG ) + have_one_strong = 1; + + olen = 0; + if( ( ret = ctx->source[i].f_source( ctx->source[i].p_source, + buf, MBEDTLS_ENTROPY_MAX_GATHER, &olen ) ) != 0 ) + { + goto cleanup; + } + + /* + * Add if we actually gathered something + */ + if( olen > 0 ) + { + if( ( ret = entropy_update( ctx, (unsigned char) i, + buf, olen ) ) != 0 ) + return( ret ); + ctx->source[i].size += olen; + } + } + + if( have_one_strong == 0 ) + ret = MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE; + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} + +/* + * Thread-safe wrapper for entropy_gather_internal() + */ +int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ) +{ + int ret; + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + ret = entropy_gather_internal( ctx ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ) +{ + int ret, count = 0, i, done; + mbedtls_entropy_context *ctx = (mbedtls_entropy_context *) data; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + if( len > MBEDTLS_ENTROPY_BLOCK_SIZE ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) + /* Update the NV entropy seed before generating any entropy for outside + * use. + */ + if( ctx->initial_entropy_run == 0 ) + { + ctx->initial_entropy_run = 1; + if( ( ret = mbedtls_entropy_update_nv_seed( ctx ) ) != 0 ) + return( ret ); + } +#endif + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* + * Always gather extra entropy before a call + */ + do + { + if( count++ > ENTROPY_MAX_LOOP ) + { + ret = MBEDTLS_ERR_ENTROPY_SOURCE_FAILED; + goto exit; + } + + if( ( ret = entropy_gather_internal( ctx ) ) != 0 ) + goto exit; + + done = 1; + for( i = 0; i < ctx->source_count; i++ ) + if( ctx->source[i].size < ctx->source[i].threshold ) + done = 0; + } + while( ! done ); + + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + /* + * Note that at this stage it is assumed that the accumulator was started + * in a previous call to entropy_update(). If this is not guaranteed, the + * code below will fail. + */ + if( ( ret = mbedtls_sha512_finish_ret( &ctx->accumulator, buf ) ) != 0 ) + goto exit; + + /* + * Reset accumulator and counters and recycle existing entropy + */ + mbedtls_sha512_free( &ctx->accumulator ); + mbedtls_sha512_init( &ctx->accumulator ); + if( ( ret = mbedtls_sha512_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha512_update_ret( &ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + /* + * Perform second SHA-512 on entropy + */ + if( ( ret = mbedtls_sha512_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0 ) ) != 0 ) + goto exit; +#else /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ + if( ( ret = mbedtls_sha256_finish_ret( &ctx->accumulator, buf ) ) != 0 ) + goto exit; + + /* + * Reset accumulator and counters and recycle existing entropy + */ + mbedtls_sha256_free( &ctx->accumulator ); + mbedtls_sha256_init( &ctx->accumulator ); + if( ( ret = mbedtls_sha256_starts_ret( &ctx->accumulator, 0 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_sha256_update_ret( &ctx->accumulator, buf, + MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + /* + * Perform second SHA-256 on entropy + */ + if( ( ret = mbedtls_sha256_ret( buf, MBEDTLS_ENTROPY_BLOCK_SIZE, + buf, 0 ) ) != 0 ) + goto exit; +#endif /* MBEDTLS_ENTROPY_SHA512_ACCUMULATOR */ + + for( i = 0; i < ctx->source_count; i++ ) + ctx->source[i].size = 0; + + memcpy( output, buf, len ); + + ret = 0; + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + return( ret ); +} + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ) +{ + int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + /* Read new seed and write it to NV */ + if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + return( ret ); + + if( mbedtls_nv_seed_write( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + /* Manually update the remaining stream with a separator value to diverge */ + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + ret = mbedtls_entropy_update_manual( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + return( ret ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ) +{ + int ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + FILE *f; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + + if( ( f = fopen( path, "wb" ) ) == NULL ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + if( ( ret = mbedtls_entropy_func( ctx, buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) ) != 0 ) + goto exit; + + if( fwrite( buf, 1, MBEDTLS_ENTROPY_BLOCK_SIZE, f ) != MBEDTLS_ENTROPY_BLOCK_SIZE ) + { + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + goto exit; + } + + ret = 0; + +exit: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + fclose( f ); + return( ret ); +} + +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ) +{ + int ret = 0; + FILE *f; + size_t n; + unsigned char buf[ MBEDTLS_ENTROPY_MAX_SEED_SIZE ]; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + n = (size_t) ftell( f ); + fseek( f, 0, SEEK_SET ); + + if( n > MBEDTLS_ENTROPY_MAX_SEED_SIZE ) + n = MBEDTLS_ENTROPY_MAX_SEED_SIZE; + + if( fread( buf, 1, n, f ) != n ) + ret = MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR; + else + ret = mbedtls_entropy_update_manual( ctx, buf, n ); + + fclose( f ); + + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + if( ret != 0 ) + return( ret ); + + return( mbedtls_entropy_write_seed_file( ctx, path ) ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) +/* + * Dummy source function + */ +static int entropy_dummy_source( void *data, unsigned char *output, + size_t len, size_t *olen ) +{ + ((void) data); + + memset( output, 0x2a, len ); + *olen = len; + + return( 0 ); +} +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + +static int mbedtls_entropy_source_self_test_gather( unsigned char *buf, size_t buf_len ) +{ + int ret = 0; + size_t entropy_len = 0; + size_t olen = 0; + size_t attempts = buf_len; + + while( attempts > 0 && entropy_len < buf_len ) + { + if( ( ret = mbedtls_hardware_poll( NULL, buf + entropy_len, + buf_len - entropy_len, &olen ) ) != 0 ) + return( ret ); + + entropy_len += olen; + attempts--; + } + + if( entropy_len < buf_len ) + { + ret = 1; + } + + return( ret ); +} + + +static int mbedtls_entropy_source_self_test_check_bits( const unsigned char *buf, + size_t buf_len ) +{ + unsigned char set= 0xFF; + unsigned char unset = 0x00; + size_t i; + + for( i = 0; i < buf_len; i++ ) + { + set &= buf[i]; + unset |= buf[i]; + } + + return( set == 0xFF || unset == 0x00 ); +} + +/* + * A test to ensure hat the entropy sources are functioning correctly + * and there is no obvious failure. The test performs the following checks: + * - The entropy source is not providing only 0s (all bits unset) or 1s (all + * bits set). + * - The entropy source is not providing values in a pattern. Because the + * hardware could be providing data in an arbitrary length, this check polls + * the hardware entropy source twice and compares the result to ensure they + * are not equal. + * - The error code returned by the entropy source is not an error. + */ +int mbedtls_entropy_source_self_test( int verbose ) +{ + int ret = 0; + unsigned char buf0[2 * sizeof( unsigned long long int )]; + unsigned char buf1[2 * sizeof( unsigned long long int )]; + + if( verbose != 0 ) + mbedtls_printf( " ENTROPY_BIAS test: " ); + + memset( buf0, 0x00, sizeof( buf0 ) ); + memset( buf1, 0x00, sizeof( buf1 ) ); + + if( ( ret = mbedtls_entropy_source_self_test_gather( buf0, sizeof( buf0 ) ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_entropy_source_self_test_gather( buf1, sizeof( buf1 ) ) ) != 0 ) + goto cleanup; + + /* Make sure that the returned values are not all 0 or 1 */ + if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf0, sizeof( buf0 ) ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_entropy_source_self_test_check_bits( buf1, sizeof( buf1 ) ) ) != 0 ) + goto cleanup; + + /* Make sure that the entropy source is not returning values in a + * pattern */ + ret = memcmp( buf0, buf1, sizeof( buf0 ) ) == 0; + +cleanup: + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed\n" ); + else + mbedtls_printf( "passed\n" ); + + mbedtls_printf( "\n" ); + } + + return( ret != 0 ); +} + +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ + +/* + * The actual entropy quality is hard to test, but we can at least + * test that the functions don't cause errors and write the correct + * amount of data to buffers. + */ +int mbedtls_entropy_self_test( int verbose ) +{ + int ret = 1; +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_context ctx; + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; + unsigned char acc[MBEDTLS_ENTROPY_BLOCK_SIZE] = { 0 }; + size_t i, j; +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + + if( verbose != 0 ) + mbedtls_printf( " ENTROPY test: " ); + +#if !defined(MBEDTLS_TEST_NULL_ENTROPY) + mbedtls_entropy_init( &ctx ); + + /* First do a gather to make sure we have default sources */ + if( ( ret = mbedtls_entropy_gather( &ctx ) ) != 0 ) + goto cleanup; + + ret = mbedtls_entropy_add_source( &ctx, entropy_dummy_source, NULL, 16, + MBEDTLS_ENTROPY_SOURCE_WEAK ); + if( ret != 0 ) + goto cleanup; + + if( ( ret = mbedtls_entropy_update_manual( &ctx, buf, sizeof buf ) ) != 0 ) + goto cleanup; + + /* + * To test that mbedtls_entropy_func writes correct number of bytes: + * - use the whole buffer and rely on ASan to detect overruns + * - collect entropy 8 times and OR the result in an accumulator: + * any byte should then be 0 with probably 2^(-64), so requiring + * each of the 32 or 64 bytes to be non-zero has a false failure rate + * of at most 2^(-58) which is acceptable. + */ + for( i = 0; i < 8; i++ ) + { + if( ( ret = mbedtls_entropy_func( &ctx, buf, sizeof( buf ) ) ) != 0 ) + goto cleanup; + + for( j = 0; j < sizeof( buf ); j++ ) + acc[j] |= buf[j]; + } + + for( j = 0; j < sizeof( buf ); j++ ) + { + if( acc[j] == 0 ) + { + ret = 1; + goto cleanup; + } + } + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) + if( ( ret = mbedtls_entropy_source_self_test( 0 ) ) != 0 ) + goto cleanup; +#endif + +cleanup: + mbedtls_entropy_free( &ctx ); +#endif /* !MBEDTLS_TEST_NULL_ENTROPY */ + + if( verbose != 0 ) + { + if( ret != 0 ) + mbedtls_printf( "failed\n" ); + else + mbedtls_printf( "passed\n" ); + + mbedtls_printf( "\n" ); + } + + return( ret != 0 ); +} +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_ENTROPY_C */ diff --git a/common/mbedtls/entropy.h b/common/mbedtls/entropy.h new file mode 100644 index 000000000..b1e8c4cd5 --- /dev/null +++ b/common/mbedtls/entropy.h @@ -0,0 +1,291 @@ +/** + * \file entropy.h + * + * \brief Entropy accumulator implementation + */ +/* + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ENTROPY_H +#define MBEDTLS_ENTROPY_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_SHA512_C) && !defined(MBEDTLS_ENTROPY_FORCE_SHA256) +#include "sha512.h" +#define MBEDTLS_ENTROPY_SHA512_ACCUMULATOR +#else +#if defined(MBEDTLS_SHA256_C) +#define MBEDTLS_ENTROPY_SHA256_ACCUMULATOR +#include "sha256.h" +#endif +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#endif + +#if defined(MBEDTLS_HAVEGE_C) +#include "havege.h" +#endif + +#define MBEDTLS_ERR_ENTROPY_SOURCE_FAILED -0x003C /**< Critical entropy source failure. */ +#define MBEDTLS_ERR_ENTROPY_MAX_SOURCES -0x003E /**< No more sources can be added. */ +#define MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED -0x0040 /**< No sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE -0x003D /**< No strong sources have been added to poll. */ +#define MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR -0x003F /**< Read/write error in file. */ + +/** + * \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_ENTROPY_MAX_SOURCES) +#define MBEDTLS_ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ +#endif + +#if !defined(MBEDTLS_ENTROPY_MAX_GATHER) +#define MBEDTLS_ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ +#endif + +/* \} name SECTION: Module settings */ + +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) +#define MBEDTLS_ENTROPY_BLOCK_SIZE 64 /**< Block size of entropy accumulator (SHA-512) */ +#else +#define MBEDTLS_ENTROPY_BLOCK_SIZE 32 /**< Block size of entropy accumulator (SHA-256) */ +#endif + +#define MBEDTLS_ENTROPY_MAX_SEED_SIZE 1024 /**< Maximum size of seed we read from seed file */ +#define MBEDTLS_ENTROPY_SOURCE_MANUAL MBEDTLS_ENTROPY_MAX_SOURCES + +#define MBEDTLS_ENTROPY_SOURCE_STRONG 1 /**< Entropy source is strong */ +#define MBEDTLS_ENTROPY_SOURCE_WEAK 0 /**< Entropy source is weak */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Entropy poll callback pointer + * + * \param data Callback-specific data pointer + * \param output Data to fill + * \param len Maximum size to provide + * \param olen The actual amount of bytes put into the buffer (Can be 0) + * + * \return 0 if no critical failures occurred, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED otherwise + */ +typedef int (*mbedtls_entropy_f_source_ptr)(void *data, unsigned char *output, size_t len, + size_t *olen); + +/** + * \brief Entropy source state + */ +typedef struct mbedtls_entropy_source_state +{ + mbedtls_entropy_f_source_ptr f_source; /**< The entropy source callback */ + void * p_source; /**< The callback data pointer */ + size_t size; /**< Amount received in bytes */ + size_t threshold; /**< Minimum bytes required before release */ + int strong; /**< Is the source strong? */ +} +mbedtls_entropy_source_state; + +/** + * \brief Entropy context structure + */ +typedef struct mbedtls_entropy_context +{ + int accumulator_started; +#if defined(MBEDTLS_ENTROPY_SHA512_ACCUMULATOR) + mbedtls_sha512_context accumulator; +#else + mbedtls_sha256_context accumulator; +#endif + int source_count; + mbedtls_entropy_source_state source[MBEDTLS_ENTROPY_MAX_SOURCES]; +#if defined(MBEDTLS_HAVEGE_C) + mbedtls_havege_state havege_data; +#endif +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< mutex */ +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) + int initial_entropy_run; +#endif +} +mbedtls_entropy_context; + +/** + * \brief Initialize the context + * + * \param ctx Entropy context to initialize + */ +void mbedtls_entropy_init( mbedtls_entropy_context *ctx ); + +/** + * \brief Free the data in the context + * + * \param ctx Entropy context to free + */ +void mbedtls_entropy_free( mbedtls_entropy_context *ctx ); + +/** + * \brief Adds an entropy source to poll + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param f_source Entropy function + * \param p_source Function data + * \param threshold Minimum required from source before entropy is released + * ( with mbedtls_entropy_func() ) (in bytes) + * \param strong MBEDTLS_ENTROPY_SOURCE_STRONG or + * MBEDTLS_ENTROPY_SOURCE_WEAK. + * At least one strong source needs to be added. + * Weaker sources (such as the cycle counter) can be used as + * a complement. + * + * \return 0 if successful or MBEDTLS_ERR_ENTROPY_MAX_SOURCES + */ +int mbedtls_entropy_add_source( mbedtls_entropy_context *ctx, + mbedtls_entropy_f_source_ptr f_source, void *p_source, + size_t threshold, int strong ); + +/** + * \brief Trigger an extra gather poll for the accumulator + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_gather( mbedtls_entropy_context *ctx ); + +/** + * \brief Retrieve entropy from the accumulator + * (Maximum length: MBEDTLS_ENTROPY_BLOCK_SIZE) + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param data Entropy context + * \param output Buffer to fill + * \param len Number of bytes desired, must be at most MBEDTLS_ENTROPY_BLOCK_SIZE + * + * \return 0 if successful, or MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_func( void *data, unsigned char *output, size_t len ); + +/** + * \brief Add data to the accumulator manually + * (Thread-safe if MBEDTLS_THREADING_C is enabled) + * + * \param ctx Entropy context + * \param data Data to add + * \param len Length of data + * + * \return 0 if successful + */ +int mbedtls_entropy_update_manual( mbedtls_entropy_context *ctx, + const unsigned char *data, size_t len ); + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Trigger an update of the seed file in NV by using the + * current entropy pool. + * + * \param ctx Entropy context + * + * \return 0 if successful + */ +int mbedtls_entropy_update_nv_seed( mbedtls_entropy_context *ctx ); +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Write a seed file + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, or + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_write_seed_file( mbedtls_entropy_context *ctx, const char *path ); + +/** + * \brief Read and update a seed file. Seed is added to this + * instance. No more than MBEDTLS_ENTROPY_MAX_SEED_SIZE bytes are + * read from the seed file. The rest is ignored. + * + * \param ctx Entropy context + * \param path Name of the file + * + * \return 0 if successful, + * MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR on file error, + * MBEDTLS_ERR_ENTROPY_SOURCE_FAILED + */ +int mbedtls_entropy_update_seed_file( mbedtls_entropy_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * This module self-test also calls the entropy self-test, + * mbedtls_entropy_source_self_test(); + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_self_test( int verbose ); + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Checkup routine + * + * Verifies the integrity of the hardware entropy source + * provided by the function 'mbedtls_hardware_poll()'. + * + * Note this is the only hardware entropy source that is known + * at link time, and other entropy sources configured + * dynamically at runtime by the function + * mbedtls_entropy_add_source() will not be tested. + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_entropy_source_self_test( int verbose ); +#endif /* MBEDTLS_ENTROPY_HARDWARE_ALT */ +#endif /* MBEDTLS_SELF_TEST */ + +#ifdef __cplusplus +} +#endif + +#endif /* entropy.h */ diff --git a/common/mbedtls/entropy_poll.c b/common/mbedtls/entropy_poll.c new file mode 100644 index 000000000..e8b8da86e --- /dev/null +++ b/common/mbedtls/entropy_poll.c @@ -0,0 +1,277 @@ +/* + * Platform-specific and custom entropy polling functions + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if defined(__linux__) +/* Ensure that syscall() is available even when compiling with -std=c99 */ +#define _GNU_SOURCE +#endif + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#if defined(MBEDTLS_ENTROPY_C) + +#include "mbedtls/entropy.h" +#include "mbedtls/entropy_poll.h" + +#if defined(MBEDTLS_TIMING_C) +#include "mbedtls/timing.h" +#endif +#if defined(MBEDTLS_HAVEGE_C) +#include "mbedtls/havege.h" +#endif +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#include "mbedtls/platform.h" +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) +#error "Platform entropy sources only work on Unix and Windows, see MBEDTLS_NO_PLATFORM_ENTROPY in config.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#if !defined(_WIN32_WINNT) +#define _WIN32_WINNT 0x0400 +#endif +#include +#include + +int mbedtls_platform_entropy_poll( void *data, unsigned char *output, size_t len, + size_t *olen ) +{ + HCRYPTPROV provider; + ((void) data); + *olen = 0; + + if( CryptAcquireContext( &provider, NULL, NULL, + PROV_RSA_FULL, CRYPT_VERIFYCONTEXT ) == FALSE ) + { + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + if( CryptGenRandom( provider, (DWORD) len, output ) == FALSE ) + { + CryptReleaseContext( provider, 0 ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + CryptReleaseContext( provider, 0 ); + *olen = len; + + return( 0 ); +} +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Test for Linux getrandom() support. + * Since there is no wrapper in the libc yet, use the generic syscall wrapper + * available in GNU libc and compatible libc's (eg uClibc). + */ +#if defined(__linux__) && defined(__GLIBC__) +#include +#include +#if defined(SYS_getrandom) +#define HAVE_GETRANDOM + +static int getrandom_wrapper( void *buf, size_t buflen, unsigned int flags ) +{ + /* MemSan cannot understand that the syscall writes to the buffer */ +#if defined(__has_feature) +#if __has_feature(memory_sanitizer) + memset( buf, 0, buflen ); +#endif +#endif + + return( syscall( SYS_getrandom, buf, buflen, flags ) ); +} + +#include +/* Check if version is at least 3.17.0 */ +static int check_version_3_17_plus( void ) +{ + int minor; + struct utsname un; + const char *ver; + + /* Get version information */ + uname(&un); + ver = un.release; + + /* Check major version; assume a single digit */ + if( ver[0] < '3' || ver[0] > '9' || ver [1] != '.' ) + return( -1 ); + + if( ver[0] - '0' > 3 ) + return( 0 ); + + /* Ok, so now we know major == 3, check minor. + * Assume 1 or 2 digits. */ + if( ver[2] < '0' || ver[2] > '9' ) + return( -1 ); + + minor = ver[2] - '0'; + + if( ver[3] >= '0' && ver[3] <= '9' ) + minor = 10 * minor + ver[3] - '0'; + else if( ver [3] != '.' ) + return( -1 ); + + if( minor < 17 ) + return( -1 ); + + return( 0 ); +} +static int has_getrandom = -1; +#endif /* SYS_getrandom */ +#endif /* __linux__ */ + +#include + +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + FILE *file; + size_t read_len; + ((void) data); + +#if defined(HAVE_GETRANDOM) + if( has_getrandom == -1 ) + has_getrandom = ( check_version_3_17_plus() == 0 ); + + if( has_getrandom ) + { + int ret; + + if( ( ret = getrandom_wrapper( output, len, 0 ) ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = ret; + return( 0 ); + } +#endif /* HAVE_GETRANDOM */ + + *olen = 0; + + file = fopen( "/dev/urandom", "rb" ); + if( file == NULL ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + read_len = fread( output, 1, len, file ); + if( read_len != len ) + { + fclose( file ); + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + } + + fclose( file ); + *olen = len; + + return( 0 ); +} +#endif /* _WIN32 && !EFIX64 && !EFI32 */ +#endif /* !MBEDTLS_NO_PLATFORM_ENTROPY */ + +#if defined(MBEDTLS_TEST_NULL_ENTROPY) +int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + ((void) data); + ((void) output); + *olen = 0; + + if( len < sizeof(unsigned char) ) + return( 0 ); + + *olen = sizeof(unsigned char); + + return( 0 ); +} +#endif + +#if defined(MBEDTLS_TIMING_C) +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned long timer = mbedtls_timing_hardclock(); + ((void) data); + *olen = 0; + + if( len < sizeof(unsigned long) ) + return( 0 ); + + memcpy( output, &timer, sizeof(unsigned long) ); + *olen = sizeof(unsigned long); + + return( 0 ); +} +#endif /* MBEDTLS_TIMING_C */ + +#if defined(MBEDTLS_HAVEGE_C) +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + mbedtls_havege_state *hs = (mbedtls_havege_state *) data; + *olen = 0; + + if( mbedtls_havege_random( hs, output, len ) != 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + *olen = len; + + return( 0 ); +} +#endif /* MBEDTLS_HAVEGE_C */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ) +{ + unsigned char buf[MBEDTLS_ENTROPY_BLOCK_SIZE]; + size_t use_len = MBEDTLS_ENTROPY_BLOCK_SIZE; + ((void) data); + + memset( buf, 0, MBEDTLS_ENTROPY_BLOCK_SIZE ); + + if( mbedtls_nv_seed_read( buf, MBEDTLS_ENTROPY_BLOCK_SIZE ) < 0 ) + return( MBEDTLS_ERR_ENTROPY_SOURCE_FAILED ); + + if( len < use_len ) + use_len = len; + + memcpy( output, buf, use_len ); + *olen = use_len; + + return( 0 ); +} +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#endif /* MBEDTLS_ENTROPY_C */ diff --git a/common/mbedtls/entropy_poll.h b/common/mbedtls/entropy_poll.h new file mode 100644 index 000000000..d48b8555b --- /dev/null +++ b/common/mbedtls/entropy_poll.h @@ -0,0 +1,112 @@ +/** + * \file entropy_poll.h + * + * \brief Platform-specific and custom entropy polling functions + */ +/* + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ENTROPY_POLL_H +#define MBEDTLS_ENTROPY_POLL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Default thresholds for built-in sources, in bytes + */ +#define MBEDTLS_ENTROPY_MIN_PLATFORM 32 /**< Minimum for platform source */ +#define MBEDTLS_ENTROPY_MIN_HAVEGE 32 /**< Minimum for HAVEGE */ +#define MBEDTLS_ENTROPY_MIN_HARDCLOCK 4 /**< Minimum for mbedtls_timing_hardclock() */ +#if !defined(MBEDTLS_ENTROPY_MIN_HARDWARE) +#define MBEDTLS_ENTROPY_MIN_HARDWARE 32 /**< Minimum for the hardware source */ +#endif + +/** + * \brief Entropy poll callback that provides 0 entropy. + */ +#if defined(MBEDTLS_TEST_NULL_ENTROPY) + int mbedtls_null_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if !defined(MBEDTLS_NO_PLATFORM_ENTROPY) +/** + * \brief Platform-specific entropy poll callback + */ +int mbedtls_platform_entropy_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_HAVEGE_C) +/** + * \brief HAVEGE based entropy poll callback + * + * Requires an HAVEGE state as its data pointer. + */ +int mbedtls_havege_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_TIMING_C) +/** + * \brief mbedtls_timing_hardclock-based entropy poll callback + */ +int mbedtls_hardclock_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_HARDWARE_ALT) +/** + * \brief Entropy poll callback for a hardware source + * + * \warning This is not provided by mbed TLS! + * See \c MBEDTLS_ENTROPY_HARDWARE_ALT in config.h. + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_hardware_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +/** + * \brief Entropy poll callback for a non-volatile seed file + * + * \note This must accept NULL as its first argument. + */ +int mbedtls_nv_seed_poll( void *data, + unsigned char *output, size_t len, size_t *olen ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* entropy_poll.h */ diff --git a/common/mbedtls/error.c b/common/mbedtls/error.c new file mode 100644 index 000000000..d8c0ddc60 --- /dev/null +++ b/common/mbedtls/error.c @@ -0,0 +1,897 @@ +/* + * Error message information + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_ERROR_C) || defined(MBEDTLS_ERROR_STRERROR_DUMMY) +#include "mbedtls/error.h" +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#define mbedtls_time_t time_t +#endif + +#if defined(MBEDTLS_ERROR_C) + +#include + +#if defined(MBEDTLS_AES_C) +#include "mbedtls/aes.h" +#endif + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_ARIA_C) +#include "mbedtls/aria.h" +#endif + +#if defined(MBEDTLS_BASE64_C) +#include "mbedtls/base64.h" +#endif + +#if defined(MBEDTLS_BIGNUM_C) +#include "mbedtls/bignum.h" +#endif + +#if defined(MBEDTLS_BLOWFISH_C) +#include "mbedtls/blowfish.h" +#endif + +#if defined(MBEDTLS_CAMELLIA_C) +#include "mbedtls/camellia.h" +#endif + +#if defined(MBEDTLS_CCM_C) +#include "mbedtls/ccm.h" +#endif + +#if defined(MBEDTLS_CHACHA20_C) +#include "mbedtls/chacha20.h" +#endif + +#if defined(MBEDTLS_CHACHAPOLY_C) +#include "mbedtls/chachapoly.h" +#endif + +#if defined(MBEDTLS_CIPHER_C) +#include "mbedtls/cipher.h" +#endif + +#if defined(MBEDTLS_CMAC_C) +#include "mbedtls/cmac.h" +#endif + +#if defined(MBEDTLS_CTR_DRBG_C) +#include "mbedtls/ctr_drbg.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +#if defined(MBEDTLS_DHM_C) +#include "mbedtls/dhm.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ENTROPY_C) +#include "mbedtls/entropy.h" +#endif + +#if defined(MBEDTLS_GCM_C) +#include "mbedtls/gcm.h" +#endif + +#if defined(MBEDTLS_HKDF_C) +#include "mbedtls/hkdf.h" +#endif + +#if defined(MBEDTLS_HMAC_DRBG_C) +#include "mbedtls/hmac_drbg.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "mbedtls/md.h" +#endif + +#if defined(MBEDTLS_MD2_C) +#include "mbedtls/md2.h" +#endif + +#if defined(MBEDTLS_MD4_C) +#include "mbedtls/md4.h" +#endif + +#if defined(MBEDTLS_MD5_C) +#include "mbedtls/md5.h" +#endif + +#if defined(MBEDTLS_NET_C) +#include "mbedtls/net_sockets.h" +#endif + +#if defined(MBEDTLS_OID_C) +#include "mbedtls/oid.h" +#endif + +#if defined(MBEDTLS_PADLOCK_C) +#include "mbedtls/padlock.h" +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk.h" +#endif + +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif + +#if defined(MBEDTLS_POLY1305_C) +#include "mbedtls/poly1305.h" +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +#include "mbedtls/ripemd160.h" +#endif + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "mbedtls/sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#endif + +#if defined(MBEDTLS_SSL_TLS_C) +#include "mbedtls/ssl.h" +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "mbedtls/x509.h" +#endif + +#if defined(MBEDTLS_XTEA_C) +#include "mbedtls/xtea.h" +#endif + + +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + size_t len; + int use_ret; + + if( buflen == 0 ) + return; + + memset( buf, 0x00, buflen ); + + if( ret < 0 ) + ret = -ret; + + if( ret & 0xFF80 ) + { + use_ret = ret & 0xFF80; + + // High level error codes + // + // BEGIN generated code +#if defined(MBEDTLS_CIPHER_C) + if( use_ret == -(MBEDTLS_ERR_CIPHER_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "CIPHER - The selected feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Bad input parameters" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Failed to allocate memory" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_PADDING) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Input data contains invalid padding and is rejected" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_FULL_BLOCK_EXPECTED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Decryption of block requires a full block" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Authentication failed (for AEAD modes)" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_INVALID_CONTEXT) ) + mbedtls_snprintf( buf, buflen, "CIPHER - The context is invalid. For example, because it was freed" ); + if( use_ret == -(MBEDTLS_ERR_CIPHER_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CIPHER - Cipher hardware accelerator failed" ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_DHM_C) + if( use_ret == -(MBEDTLS_ERR_DHM_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "DHM - Bad input parameters" ); + if( use_ret == -(MBEDTLS_ERR_DHM_READ_PARAMS_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Reading of the DHM parameters failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PARAMS_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Making of the DHM parameters failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_READ_PUBLIC_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Reading of the public values failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_MAKE_PUBLIC_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Making of the public value failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_CALC_SECRET_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Calculation of the DHM secret failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "DHM - The ASN.1 data is not formatted correctly" ); + if( use_ret == -(MBEDTLS_ERR_DHM_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Allocation of memory failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "DHM - Read or write of file failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - DHM hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_DHM_SET_GROUP_FAILED) ) + mbedtls_snprintf( buf, buflen, "DHM - Setting the modulus and generator failed" ); +#endif /* MBEDTLS_DHM_C */ + +#if defined(MBEDTLS_ECP_C) + if( use_ret == -(MBEDTLS_ERR_ECP_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "ECP - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_ECP_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "ECP - The buffer is too small to write to" ); + if( use_ret == -(MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "ECP - The requested feature is not available, for example, the requested curve is not supported" ); + if( use_ret == -(MBEDTLS_ERR_ECP_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - The signature is not valid" ); + if( use_ret == -(MBEDTLS_ERR_ECP_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_ECP_RANDOM_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - Generation of random value, such as ephemeral key, failed" ); + if( use_ret == -(MBEDTLS_ERR_ECP_INVALID_KEY) ) + mbedtls_snprintf( buf, buflen, "ECP - Invalid private or public key" ); + if( use_ret == -(MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "ECP - The buffer contains a valid signature followed by more data" ); + if( use_ret == -(MBEDTLS_ERR_ECP_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "ECP - The ECP hardware accelerator failed" ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) + if( use_ret == -(MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "MD - The selected feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_MD_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "MD - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_MD_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD - Failed to allocate memory" ); + if( use_ret == -(MBEDTLS_ERR_MD_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "MD - Opening or reading of file failed" ); + if( use_ret == -(MBEDTLS_ERR_MD_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD - MD hardware accelerator failed" ); +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + if( use_ret == -(MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT) ) + mbedtls_snprintf( buf, buflen, "PEM - No PEM header or footer found" ); + if( use_ret == -(MBEDTLS_ERR_PEM_INVALID_DATA) ) + mbedtls_snprintf( buf, buflen, "PEM - PEM string is not as expected" ); + if( use_ret == -(MBEDTLS_ERR_PEM_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "PEM - Failed to allocate memory" ); + if( use_ret == -(MBEDTLS_ERR_PEM_INVALID_ENC_IV) ) + mbedtls_snprintf( buf, buflen, "PEM - RSA IV is not in hex-format" ); + if( use_ret == -(MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG) ) + mbedtls_snprintf( buf, buflen, "PEM - Unsupported key encryption algorithm" ); + if( use_ret == -(MBEDTLS_ERR_PEM_PASSWORD_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "PEM - Private key password can't be empty" ); + if( use_ret == -(MBEDTLS_ERR_PEM_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PEM - Given private key password does not allow for correct decryption" ); + if( use_ret == -(MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PEM - Unavailable feature, e.g. hashing/encryption combination" ); + if( use_ret == -(MBEDTLS_ERR_PEM_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PEM - Bad input parameters to function" ); +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ + +#if defined(MBEDTLS_PK_C) + if( use_ret == -(MBEDTLS_ERR_PK_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "PK - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_PK_TYPE_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PK - Type mismatch, eg attempt to encrypt with an ECDSA key" ); + if( use_ret == -(MBEDTLS_ERR_PK_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PK - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_PK_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "PK - Read/write of file failed" ); + if( use_ret == -(MBEDTLS_ERR_PK_KEY_INVALID_VERSION) ) + mbedtls_snprintf( buf, buflen, "PK - Unsupported key version" ); + if( use_ret == -(MBEDTLS_ERR_PK_KEY_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "PK - Invalid key tag or value" ); + if( use_ret == -(MBEDTLS_ERR_PK_UNKNOWN_PK_ALG) ) + mbedtls_snprintf( buf, buflen, "PK - Key algorithm is unsupported (only RSA and EC are supported)" ); + if( use_ret == -(MBEDTLS_ERR_PK_PASSWORD_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "PK - Private key password can't be empty" ); + if( use_ret == -(MBEDTLS_ERR_PK_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PK - Given private key password does not allow for correct decryption" ); + if( use_ret == -(MBEDTLS_ERR_PK_INVALID_PUBKEY) ) + mbedtls_snprintf( buf, buflen, "PK - The pubkey tag or value is invalid (only RSA and EC are supported)" ); + if( use_ret == -(MBEDTLS_ERR_PK_INVALID_ALG) ) + mbedtls_snprintf( buf, buflen, "PK - The algorithm tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE) ) + mbedtls_snprintf( buf, buflen, "PK - Elliptic curve is unsupported (only NIST curves are supported)" ); + if( use_ret == -(MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PK - Unavailable feature, e.g. RSA disabled for RSA key" ); + if( use_ret == -(MBEDTLS_ERR_PK_SIG_LEN_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PK - The buffer contains a valid signature followed by more data" ); + if( use_ret == -(MBEDTLS_ERR_PK_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "PK - PK hardware accelerator failed" ); +#endif /* MBEDTLS_PK_C */ + +#if defined(MBEDTLS_PKCS12_C) + if( use_ret == -(MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - Feature not available, e.g. unsupported encryption scheme" ); + if( use_ret == -(MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - PBE ASN.1 data not as expected" ); + if( use_ret == -(MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PKCS12 - Given private key password does not allow for correct decryption" ); +#endif /* MBEDTLS_PKCS12_C */ + +#if defined(MBEDTLS_PKCS5_C) + if( use_ret == -(MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_PKCS5_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Unexpected ASN.1 data" ); + if( use_ret == -(MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Requested encryption or digest alg not available" ); + if( use_ret == -(MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "PKCS5 - Given private key password does not allow for correct decryption" ); +#endif /* MBEDTLS_PKCS5_C */ + +#if defined(MBEDTLS_RSA_C) + if( use_ret == -(MBEDTLS_ERR_RSA_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "RSA - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_RSA_INVALID_PADDING) ) + mbedtls_snprintf( buf, buflen, "RSA - Input data contains invalid padding and is rejected" ); + if( use_ret == -(MBEDTLS_ERR_RSA_KEY_GEN_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - Something failed during generation of a key" ); + if( use_ret == -(MBEDTLS_ERR_RSA_KEY_CHECK_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - Key failed to pass the validity check of the library" ); + if( use_ret == -(MBEDTLS_ERR_RSA_PUBLIC_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The public key operation failed" ); + if( use_ret == -(MBEDTLS_ERR_RSA_PRIVATE_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The private key operation failed" ); + if( use_ret == -(MBEDTLS_ERR_RSA_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The PKCS#1 verification failed" ); + if( use_ret == -(MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE) ) + mbedtls_snprintf( buf, buflen, "RSA - The output buffer for decryption is not large enough" ); + if( use_ret == -(MBEDTLS_ERR_RSA_RNG_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - The random generator failed to generate non-zeros" ); + if( use_ret == -(MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION) ) + mbedtls_snprintf( buf, buflen, "RSA - The implementation does not offer the requested operation, for example, because of security violations or lack of functionality" ); + if( use_ret == -(MBEDTLS_ERR_RSA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "RSA - RSA hardware accelerator failed" ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_SSL_TLS_C) + if( use_ret == -(MBEDTLS_ERR_SSL_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "SSL - The requested feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "SSL - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_MAC) ) + mbedtls_snprintf( buf, buflen, "SSL - Verification of the message MAC failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_RECORD) ) + mbedtls_snprintf( buf, buflen, "SSL - An invalid SSL record was received" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CONN_EOF) ) + mbedtls_snprintf( buf, buflen, "SSL - The connection indicated an EOF" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_CIPHER) ) + mbedtls_snprintf( buf, buflen, "SSL - An unknown cipher was received" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_CIPHER_CHOSEN) ) + mbedtls_snprintf( buf, buflen, "SSL - The server has no ciphersuites in common with the client" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_RNG) ) + mbedtls_snprintf( buf, buflen, "SSL - No RNG was provided to the SSL module" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_CLIENT_CERTIFICATE) ) + mbedtls_snprintf( buf, buflen, "SSL - No client certification received from the client, but required by the authentication mode" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_TOO_LARGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Our own certificate(s) is/are too large to send in an SSL message" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CERTIFICATE_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - The own certificate is not set, but needed by the server" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PRIVATE_KEY_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - The own private key or pre-shared key is not set, but needed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CA_CHAIN_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - No CA Chain is set, but required to operate" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_MESSAGE) ) + mbedtls_snprintf( buf, buflen, "SSL - An unexpected message was received from our peer" ); + if( use_ret == -(MBEDTLS_ERR_SSL_FATAL_ALERT_MESSAGE) ) + { + mbedtls_snprintf( buf, buflen, "SSL - A fatal alert message was received from our peer" ); + return; + } + if( use_ret == -(MBEDTLS_ERR_SSL_PEER_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Verification of our peer failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY) ) + mbedtls_snprintf( buf, buflen, "SSL - The peer notified us that the connection is going to be closed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_HELLO) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientHello handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHello handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the Certificate handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_REQUEST) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateRequest handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_KEY_EXCHANGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerKeyExchange handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_SERVER_HELLO_DONE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ServerHelloDone handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_RP) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Read Public" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CLIENT_KEY_EXCHANGE_CS) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ClientKeyExchange handshake message failed in DHM / ECDH Calculate Secret" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CERTIFICATE_VERIFY) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the CertificateVerify handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_CHANGE_CIPHER_SPEC) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the ChangeCipherSpec handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_FINISHED) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the Finished handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function returned with error" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HW_ACCEL_FALLTHROUGH) ) + mbedtls_snprintf( buf, buflen, "SSL - Hardware acceleration function skipped / left alone data" ); + if( use_ret == -(MBEDTLS_ERR_SSL_COMPRESSION_FAILED) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the compression / decompression failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_PROTOCOL_VERSION) ) + mbedtls_snprintf( buf, buflen, "SSL - Handshake protocol not within min/max boundaries" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BAD_HS_NEW_SESSION_TICKET) ) + mbedtls_snprintf( buf, buflen, "SSL - Processing of the NewSessionTicket handshake message failed" ); + if( use_ret == -(MBEDTLS_ERR_SSL_SESSION_TICKET_EXPIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - Session ticket has expired" ); + if( use_ret == -(MBEDTLS_ERR_SSL_PK_TYPE_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "SSL - Public key type mismatch (eg, asked for RSA key exchange and presented EC key)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNKNOWN_IDENTITY) ) + mbedtls_snprintf( buf, buflen, "SSL - Unknown identity received (eg, PSK identity)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INTERNAL_ERROR) ) + mbedtls_snprintf( buf, buflen, "SSL - Internal error (eg, unexpected failure in lower-level module)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_COUNTER_WRAPPING) ) + mbedtls_snprintf( buf, buflen, "SSL - A counter would wrap (eg, too many messages exchanged)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WAITING_SERVER_HELLO_RENEGO) ) + mbedtls_snprintf( buf, buflen, "SSL - Unexpected message at ServerHello in renegotiation" ); + if( use_ret == -(MBEDTLS_ERR_SSL_HELLO_VERIFY_REQUIRED) ) + mbedtls_snprintf( buf, buflen, "SSL - DTLS client must retry for hello verification" ); + if( use_ret == -(MBEDTLS_ERR_SSL_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "SSL - A buffer is too small to receive or write a message" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NO_USABLE_CIPHERSUITE) ) + mbedtls_snprintf( buf, buflen, "SSL - None of the common ciphersuites is usable (eg, no suitable certificate, see debug messages)" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WANT_READ) ) + mbedtls_snprintf( buf, buflen, "SSL - No data of requested type currently available on underlying transport" ); + if( use_ret == -(MBEDTLS_ERR_SSL_WANT_WRITE) ) + mbedtls_snprintf( buf, buflen, "SSL - Connection requires a write call" ); + if( use_ret == -(MBEDTLS_ERR_SSL_TIMEOUT) ) + mbedtls_snprintf( buf, buflen, "SSL - The operation timed out" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CLIENT_RECONNECT) ) + mbedtls_snprintf( buf, buflen, "SSL - The client initiated a reconnect from the same port" ); + if( use_ret == -(MBEDTLS_ERR_SSL_UNEXPECTED_RECORD) ) + mbedtls_snprintf( buf, buflen, "SSL - Record header looks valid but is not expected" ); + if( use_ret == -(MBEDTLS_ERR_SSL_NON_FATAL) ) + mbedtls_snprintf( buf, buflen, "SSL - The alert message received indicates a non-fatal error" ); + if( use_ret == -(MBEDTLS_ERR_SSL_INVALID_VERIFY_HASH) ) + mbedtls_snprintf( buf, buflen, "SSL - Couldn't set the hash for verifying CertificateVerify" ); + if( use_ret == -(MBEDTLS_ERR_SSL_CONTINUE_PROCESSING) ) + mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that further message-processing should be done" ); + if( use_ret == -(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS) ) + mbedtls_snprintf( buf, buflen, "SSL - The asynchronous operation is not completed yet" ); + if( use_ret == -(MBEDTLS_ERR_SSL_EARLY_MESSAGE) ) + mbedtls_snprintf( buf, buflen, "SSL - Internal-only message signaling that a message arrived early" ); +#endif /* MBEDTLS_SSL_TLS_C */ + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) + if( use_ret == -(MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "X509 - Unavailable feature, e.g. RSA hashing/encryption combination" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_OID) ) + mbedtls_snprintf( buf, buflen, "X509 - Requested OID is unknown" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_FORMAT) ) + mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR format is invalid, e.g. different type expected" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_VERSION) ) + mbedtls_snprintf( buf, buflen, "X509 - The CRT/CRL/CSR version element is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SERIAL) ) + mbedtls_snprintf( buf, buflen, "X509 - The serial tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_ALG) ) + mbedtls_snprintf( buf, buflen, "X509 - The algorithm tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_NAME) ) + mbedtls_snprintf( buf, buflen, "X509 - The name tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_DATE) ) + mbedtls_snprintf( buf, buflen, "X509 - The date tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_SIGNATURE) ) + mbedtls_snprintf( buf, buflen, "X509 - The signature tag or value invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_INVALID_EXTENSIONS) ) + mbedtls_snprintf( buf, buflen, "X509 - The extension tag or value is invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_VERSION) ) + mbedtls_snprintf( buf, buflen, "X509 - CRT/CRL/CSR has an unsupported version number" ); + if( use_ret == -(MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG) ) + mbedtls_snprintf( buf, buflen, "X509 - Signature algorithm (oid) is unsupported" ); + if( use_ret == -(MBEDTLS_ERR_X509_SIG_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "X509 - Signature algorithms do not match. (see \\c ::mbedtls_x509_crt sig_oid)" ); + if( use_ret == -(MBEDTLS_ERR_X509_CERT_VERIFY_FAILED) ) + mbedtls_snprintf( buf, buflen, "X509 - Certificate verification failed, e.g. CRL, CA or signature check failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT) ) + mbedtls_snprintf( buf, buflen, "X509 - Format not recognized as DER or PEM" ); + if( use_ret == -(MBEDTLS_ERR_X509_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "X509 - Input invalid" ); + if( use_ret == -(MBEDTLS_ERR_X509_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "X509 - Allocation of memory failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "X509 - Read/write of file failed" ); + if( use_ret == -(MBEDTLS_ERR_X509_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "X509 - Destination buffer is too small" ); + if( use_ret == -(MBEDTLS_ERR_X509_FATAL_ERROR) ) + mbedtls_snprintf( buf, buflen, "X509 - A fatal error occured, eg the chain is too long or the vrfy callback failed" ); +#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ + // END generated code + + if( strlen( buf ) == 0 ) + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); + } + + use_ret = ret & ~0xFF80; + + if( use_ret == 0 ) + return; + + // If high level code is present, make a concatenation between both + // error strings. + // + len = strlen( buf ); + + if( len > 0 ) + { + if( buflen - len < 5 ) + return; + + mbedtls_snprintf( buf + len, buflen - len, " : " ); + + buf += len + 3; + buflen -= len + 3; + } + + // Low level error codes + // + // BEGIN generated code +#if defined(MBEDTLS_AES_C) + if( use_ret == -(MBEDTLS_ERR_AES_INVALID_KEY_LENGTH) ) + mbedtls_snprintf( buf, buflen, "AES - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_AES_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "AES - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_AES_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "AES - Invalid input data" ); + if( use_ret == -(MBEDTLS_ERR_AES_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "AES - Feature not available. For example, an unsupported AES key size" ); + if( use_ret == -(MBEDTLS_ERR_AES_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "AES - AES hardware accelerator failed" ); +#endif /* MBEDTLS_AES_C */ + +#if defined(MBEDTLS_ARC4_C) + if( use_ret == -(MBEDTLS_ERR_ARC4_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "ARC4 - ARC4 hardware accelerator failed" ); +#endif /* MBEDTLS_ARC4_C */ + +#if defined(MBEDTLS_ARIA_C) + if( use_ret == -(MBEDTLS_ERR_ARIA_INVALID_KEY_LENGTH) ) + mbedtls_snprintf( buf, buflen, "ARIA - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_ARIA_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "ARIA - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_ARIA_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "ARIA - Feature not available. For example, an unsupported ARIA key size" ); + if( use_ret == -(MBEDTLS_ERR_ARIA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "ARIA - ARIA hardware accelerator failed" ); +#endif /* MBEDTLS_ARIA_C */ + +#if defined(MBEDTLS_ASN1_PARSE_C) + if( use_ret == -(MBEDTLS_ERR_ASN1_OUT_OF_DATA) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Out of data when parsing an ASN1 data structure" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_UNEXPECTED_TAG) ) + mbedtls_snprintf( buf, buflen, "ASN1 - ASN1 tag was of an unexpected value" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_INVALID_LENGTH) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Error when trying to determine the length or invalid length" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_LENGTH_MISMATCH) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Actual length differs from expected length" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_INVALID_DATA) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Data is invalid. (not used)" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Memory allocation failed" ); + if( use_ret == -(MBEDTLS_ERR_ASN1_BUF_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "ASN1 - Buffer too small when writing ASN.1 data structure" ); +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#if defined(MBEDTLS_BASE64_C) + if( use_ret == -(MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "BASE64 - Output buffer too small" ); + if( use_ret == -(MBEDTLS_ERR_BASE64_INVALID_CHARACTER) ) + mbedtls_snprintf( buf, buflen, "BASE64 - Invalid character in input" ); +#endif /* MBEDTLS_BASE64_C */ + +#if defined(MBEDTLS_BIGNUM_C) + if( use_ret == -(MBEDTLS_ERR_MPI_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - An error occurred while reading from or writing to a file" ); + if( use_ret == -(MBEDTLS_ERR_MPI_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_MPI_INVALID_CHARACTER) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - There is an invalid character in the digit string" ); + if( use_ret == -(MBEDTLS_ERR_MPI_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - The buffer is too small to write to" ); + if( use_ret == -(MBEDTLS_ERR_MPI_NEGATIVE_VALUE) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - The input arguments are negative or result in illegal output" ); + if( use_ret == -(MBEDTLS_ERR_MPI_DIVISION_BY_ZERO) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - The input argument for division is zero, which is not allowed" ); + if( use_ret == -(MBEDTLS_ERR_MPI_NOT_ACCEPTABLE) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - The input arguments are not acceptable" ); + if( use_ret == -(MBEDTLS_ERR_MPI_ALLOC_FAILED) ) + mbedtls_snprintf( buf, buflen, "BIGNUM - Memory allocation failed" ); +#endif /* MBEDTLS_BIGNUM_C */ + +#if defined(MBEDTLS_BLOWFISH_C) + if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_KEY_LENGTH) ) + mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_BLOWFISH_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "BLOWFISH - Blowfish hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_BLOWFISH_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "BLOWFISH - Invalid data input length" ); +#endif /* MBEDTLS_BLOWFISH_C */ + +#if defined(MBEDTLS_CAMELLIA_C) + if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_KEY_LENGTH) ) + mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid key length" ); + if( use_ret == -(MBEDTLS_ERR_CAMELLIA_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "CAMELLIA - Invalid data input length" ); + if( use_ret == -(MBEDTLS_ERR_CAMELLIA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CAMELLIA - Camellia hardware accelerator failed" ); +#endif /* MBEDTLS_CAMELLIA_C */ + +#if defined(MBEDTLS_CCM_C) + if( use_ret == -(MBEDTLS_ERR_CCM_BAD_INPUT) ) + mbedtls_snprintf( buf, buflen, "CCM - Bad input parameters to the function" ); + if( use_ret == -(MBEDTLS_ERR_CCM_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "CCM - Authenticated decryption failed" ); + if( use_ret == -(MBEDTLS_ERR_CCM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CCM - CCM hardware accelerator failed" ); +#endif /* MBEDTLS_CCM_C */ + +#if defined(MBEDTLS_CHACHA20_C) + if( use_ret == -(MBEDTLS_ERR_CHACHA20_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "CHACHA20 - Invalid input parameter(s)" ); + if( use_ret == -(MBEDTLS_ERR_CHACHA20_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "CHACHA20 - Feature not available. For example, s part of the API is not implemented" ); + if( use_ret == -(MBEDTLS_ERR_CHACHA20_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CHACHA20 - Chacha20 hardware accelerator failed" ); +#endif /* MBEDTLS_CHACHA20_C */ + +#if defined(MBEDTLS_CHACHAPOLY_C) + if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_BAD_STATE) ) + mbedtls_snprintf( buf, buflen, "CHACHAPOLY - The requested operation is not permitted in the current state" ); + if( use_ret == -(MBEDTLS_ERR_CHACHAPOLY_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "CHACHAPOLY - Authenticated decryption failed: data was not authentic" ); +#endif /* MBEDTLS_CHACHAPOLY_C */ + +#if defined(MBEDTLS_CMAC_C) + if( use_ret == -(MBEDTLS_ERR_CMAC_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "CMAC - CMAC hardware accelerator failed" ); +#endif /* MBEDTLS_CMAC_C */ + +#if defined(MBEDTLS_CTR_DRBG_C) + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_ENTROPY_SOURCE_FAILED) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - The entropy source failed" ); + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_REQUEST_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - The requested random buffer length is too big" ); + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_INPUT_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - The input (entropy + additional data) is too large" ); + if( use_ret == -(MBEDTLS_ERR_CTR_DRBG_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "CTR_DRBG - Read or write error in file" ); +#endif /* MBEDTLS_CTR_DRBG_C */ + +#if defined(MBEDTLS_DES_C) + if( use_ret == -(MBEDTLS_ERR_DES_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "DES - The data input has an invalid length" ); + if( use_ret == -(MBEDTLS_ERR_DES_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "DES - DES hardware accelerator failed" ); +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_ENTROPY_C) + if( use_ret == -(MBEDTLS_ERR_ENTROPY_SOURCE_FAILED) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - Critical entropy source failure" ); + if( use_ret == -(MBEDTLS_ERR_ENTROPY_MAX_SOURCES) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - No more sources can be added" ); + if( use_ret == -(MBEDTLS_ERR_ENTROPY_NO_SOURCES_DEFINED) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - No sources have been added to poll" ); + if( use_ret == -(MBEDTLS_ERR_ENTROPY_NO_STRONG_SOURCE) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - No strong sources have been added to poll" ); + if( use_ret == -(MBEDTLS_ERR_ENTROPY_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "ENTROPY - Read/write error in file" ); +#endif /* MBEDTLS_ENTROPY_C */ + +#if defined(MBEDTLS_GCM_C) + if( use_ret == -(MBEDTLS_ERR_GCM_AUTH_FAILED) ) + mbedtls_snprintf( buf, buflen, "GCM - Authenticated decryption failed" ); + if( use_ret == -(MBEDTLS_ERR_GCM_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "GCM - GCM hardware accelerator failed" ); + if( use_ret == -(MBEDTLS_ERR_GCM_BAD_INPUT) ) + mbedtls_snprintf( buf, buflen, "GCM - Bad input parameters to function" ); +#endif /* MBEDTLS_GCM_C */ + +#if defined(MBEDTLS_HKDF_C) + if( use_ret == -(MBEDTLS_ERR_HKDF_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "HKDF - Bad input parameters to function" ); +#endif /* MBEDTLS_HKDF_C */ + +#if defined(MBEDTLS_HMAC_DRBG_C) + if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_REQUEST_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Too many random requested in single call" ); + if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_INPUT_TOO_BIG) ) + mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Input too large (Entropy + additional)" ); + if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_FILE_IO_ERROR) ) + mbedtls_snprintf( buf, buflen, "HMAC_DRBG - Read/write error in file" ); + if( use_ret == -(MBEDTLS_ERR_HMAC_DRBG_ENTROPY_SOURCE_FAILED) ) + mbedtls_snprintf( buf, buflen, "HMAC_DRBG - The entropy source failed" ); +#endif /* MBEDTLS_HMAC_DRBG_C */ + +#if defined(MBEDTLS_MD2_C) + if( use_ret == -(MBEDTLS_ERR_MD2_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD2 - MD2 hardware accelerator failed" ); +#endif /* MBEDTLS_MD2_C */ + +#if defined(MBEDTLS_MD4_C) + if( use_ret == -(MBEDTLS_ERR_MD4_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD4 - MD4 hardware accelerator failed" ); +#endif /* MBEDTLS_MD4_C */ + +#if defined(MBEDTLS_MD5_C) + if( use_ret == -(MBEDTLS_ERR_MD5_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "MD5 - MD5 hardware accelerator failed" ); +#endif /* MBEDTLS_MD5_C */ + +#if defined(MBEDTLS_NET_C) + if( use_ret == -(MBEDTLS_ERR_NET_SOCKET_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Failed to open a socket" ); + if( use_ret == -(MBEDTLS_ERR_NET_CONNECT_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - The connection to the given server / port failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_BIND_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Binding of the socket failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_LISTEN_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Could not listen on the socket" ); + if( use_ret == -(MBEDTLS_ERR_NET_ACCEPT_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Could not accept the incoming connection" ); + if( use_ret == -(MBEDTLS_ERR_NET_RECV_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Reading information from the socket failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_SEND_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Sending information through the socket failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_CONN_RESET) ) + mbedtls_snprintf( buf, buflen, "NET - Connection was reset by peer" ); + if( use_ret == -(MBEDTLS_ERR_NET_UNKNOWN_HOST) ) + mbedtls_snprintf( buf, buflen, "NET - Failed to get an IP address for the given hostname" ); + if( use_ret == -(MBEDTLS_ERR_NET_BUFFER_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "NET - Buffer is too small to hold the data" ); + if( use_ret == -(MBEDTLS_ERR_NET_INVALID_CONTEXT) ) + mbedtls_snprintf( buf, buflen, "NET - The context is invalid, eg because it was free()ed" ); + if( use_ret == -(MBEDTLS_ERR_NET_POLL_FAILED) ) + mbedtls_snprintf( buf, buflen, "NET - Polling the net context failed" ); + if( use_ret == -(MBEDTLS_ERR_NET_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "NET - Input invalid" ); +#endif /* MBEDTLS_NET_C */ + +#if defined(MBEDTLS_OID_C) + if( use_ret == -(MBEDTLS_ERR_OID_NOT_FOUND) ) + mbedtls_snprintf( buf, buflen, "OID - OID is not found" ); + if( use_ret == -(MBEDTLS_ERR_OID_BUF_TOO_SMALL) ) + mbedtls_snprintf( buf, buflen, "OID - output buffer is too small" ); +#endif /* MBEDTLS_OID_C */ + +#if defined(MBEDTLS_PADLOCK_C) + if( use_ret == -(MBEDTLS_ERR_PADLOCK_DATA_MISALIGNED) ) + mbedtls_snprintf( buf, buflen, "PADLOCK - Input data should be aligned" ); +#endif /* MBEDTLS_PADLOCK_C */ + +#if defined(MBEDTLS_POLY1305_C) + if( use_ret == -(MBEDTLS_ERR_POLY1305_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "POLY1305 - Invalid input parameter(s)" ); + if( use_ret == -(MBEDTLS_ERR_POLY1305_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "POLY1305 - Feature not available. For example, s part of the API is not implemented" ); + if( use_ret == -(MBEDTLS_ERR_POLY1305_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "POLY1305 - Poly1305 hardware accelerator failed" ); +#endif /* MBEDTLS_POLY1305_C */ + +#if defined(MBEDTLS_RIPEMD160_C) + if( use_ret == -(MBEDTLS_ERR_RIPEMD160_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "RIPEMD160 - RIPEMD160 hardware accelerator failed" ); +#endif /* MBEDTLS_RIPEMD160_C */ + +#if defined(MBEDTLS_SHA1_C) + if( use_ret == -(MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SHA1 - SHA-1 hardware accelerator failed" ); +#endif /* MBEDTLS_SHA1_C */ + +#if defined(MBEDTLS_SHA256_C) + if( use_ret == -(MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SHA256 - SHA-256 hardware accelerator failed" ); +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + if( use_ret == -(MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "SHA512 - SHA-512 hardware accelerator failed" ); +#endif /* MBEDTLS_SHA512_C */ + +#if defined(MBEDTLS_THREADING_C) + if( use_ret == -(MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE) ) + mbedtls_snprintf( buf, buflen, "THREADING - The selected feature is not available" ); + if( use_ret == -(MBEDTLS_ERR_THREADING_BAD_INPUT_DATA) ) + mbedtls_snprintf( buf, buflen, "THREADING - Bad input parameters to function" ); + if( use_ret == -(MBEDTLS_ERR_THREADING_MUTEX_ERROR) ) + mbedtls_snprintf( buf, buflen, "THREADING - Locking / unlocking / free failed with error code" ); +#endif /* MBEDTLS_THREADING_C */ + +#if defined(MBEDTLS_XTEA_C) + if( use_ret == -(MBEDTLS_ERR_XTEA_INVALID_INPUT_LENGTH) ) + mbedtls_snprintf( buf, buflen, "XTEA - The data input has an invalid length" ); + if( use_ret == -(MBEDTLS_ERR_XTEA_HW_ACCEL_FAILED) ) + mbedtls_snprintf( buf, buflen, "XTEA - XTEA hardware accelerator failed" ); +#endif /* MBEDTLS_XTEA_C */ + // END generated code + + if( strlen( buf ) != 0 ) + return; + + mbedtls_snprintf( buf, buflen, "UNKNOWN ERROR CODE (%04X)", use_ret ); +} + +#else /* MBEDTLS_ERROR_C */ + +#if defined(MBEDTLS_ERROR_STRERROR_DUMMY) + +/* + * Provide an non-function in case MBEDTLS_ERROR_C is not defined + */ +void mbedtls_strerror( int ret, char *buf, size_t buflen ) +{ + ((void) ret); + + if( buflen > 0 ) + buf[0] = '\0'; +} + +#endif /* MBEDTLS_ERROR_STRERROR_DUMMY */ + +#endif /* MBEDTLS_ERROR_C */ diff --git a/common/mbedtls/error.h b/common/mbedtls/error.h new file mode 100644 index 000000000..432179084 --- /dev/null +++ b/common/mbedtls/error.h @@ -0,0 +1,124 @@ +/** + * \file error.h + * + * \brief Error to string translation + */ +/* + * Copyright (C) 2006-2018, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_ERROR_H +#define MBEDTLS_ERROR_H + +#include + +/** + * Error code layout. + * + * Currently we try to keep all error codes within the negative space of 16 + * bits signed integers to support all platforms (-0x0001 - -0x7FFF). In + * addition we'd like to give two layers of information on the error if + * possible. + * + * For that purpose the error codes are segmented in the following manner: + * + * 16 bit error code bit-segmentation + * + * 1 bit - Unused (sign bit) + * 3 bits - High level module ID + * 5 bits - Module-dependent error code + * 7 bits - Low level module errors + * + * For historical reasons, low-level error codes are divided in even and odd, + * even codes were assigned first, and -1 is reserved for other errors. + * + * Low-level module errors (0x0002-0x007E, 0x0003-0x007F) + * + * Module Nr Codes assigned + * MPI 7 0x0002-0x0010 + * GCM 3 0x0012-0x0014 0x0013-0x0013 + * BLOWFISH 3 0x0016-0x0018 0x0017-0x0017 + * THREADING 3 0x001A-0x001E + * AES 5 0x0020-0x0022 0x0021-0x0025 + * CAMELLIA 3 0x0024-0x0026 0x0027-0x0027 + * XTEA 2 0x0028-0x0028 0x0029-0x0029 + * BASE64 2 0x002A-0x002C + * OID 1 0x002E-0x002E 0x000B-0x000B + * PADLOCK 1 0x0030-0x0030 + * DES 2 0x0032-0x0032 0x0033-0x0033 + * CTR_DBRG 4 0x0034-0x003A + * ENTROPY 3 0x003C-0x0040 0x003D-0x003F + * NET 13 0x0042-0x0052 0x0043-0x0049 + * ARIA 4 0x0058-0x005E + * ASN1 7 0x0060-0x006C + * CMAC 1 0x007A-0x007A + * PBKDF2 1 0x007C-0x007C + * HMAC_DRBG 4 0x0003-0x0009 + * CCM 3 0x000D-0x0011 + * ARC4 1 0x0019-0x0019 + * MD2 1 0x002B-0x002B + * MD4 1 0x002D-0x002D + * MD5 1 0x002F-0x002F + * RIPEMD160 1 0x0031-0x0031 + * SHA1 1 0x0035-0x0035 + * SHA256 1 0x0037-0x0037 + * SHA512 1 0x0039-0x0039 + * CHACHA20 3 0x0051-0x0055 + * POLY1305 3 0x0057-0x005B + * CHACHAPOLY 2 0x0054-0x0056 + * + * High-level module nr (3 bits - 0x0...-0x7...) + * Name ID Nr of Errors + * PEM 1 9 + * PKCS#12 1 4 (Started from top) + * X509 2 20 + * PKCS5 2 4 (Started from top) + * DHM 3 11 + * PK 3 15 (Started from top) + * RSA 4 11 + * ECP 4 9 (Started from top) + * MD 5 5 + * HKDF 5 1 (Started from top) + * CIPHER 6 8 + * SSL 6 22 (Started from top) + * SSL 7 31 + * + * Module dependent error code (5 bits 0x.00.-0x.F8.) + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Translate a mbed TLS error code into a string representation, + * Result is truncated if necessary and always includes a terminating + * null byte. + * + * \param errnum error code + * \param buffer buffer to place representation in + * \param buflen length of the buffer + */ +void mbedtls_strerror( int errnum, char *buffer, size_t buflen ); + +#ifdef __cplusplus +} +#endif + +#endif /* error.h */ diff --git a/common/mbedtls/md.c b/common/mbedtls/md.c new file mode 100644 index 000000000..0530621b0 --- /dev/null +++ b/common/mbedtls/md.c @@ -0,0 +1,477 @@ +/** + * \file mbedtls_md.c + * + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD_C) + +#include "mbedtls/md.h" +#include "mbedtls/md_internal.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include + +#if defined(MBEDTLS_FS_IO) +#include +#endif + +/* + * Reminder: update profiles in x509_crt.c when adding a new hash! + */ +static const int supported_digests[] = { + +#if defined(MBEDTLS_SHA512_C) + MBEDTLS_MD_SHA512, + MBEDTLS_MD_SHA384, +#endif + +#if defined(MBEDTLS_SHA256_C) + MBEDTLS_MD_SHA256, + MBEDTLS_MD_SHA224, +#endif + +#if defined(MBEDTLS_SHA1_C) + MBEDTLS_MD_SHA1, +#endif + +#if defined(MBEDTLS_RIPEMD160_C) + MBEDTLS_MD_RIPEMD160, +#endif + +#if defined(MBEDTLS_MD5_C) + MBEDTLS_MD_MD5, +#endif + +#if defined(MBEDTLS_MD4_C) + MBEDTLS_MD_MD4, +#endif + +#if defined(MBEDTLS_MD2_C) + MBEDTLS_MD_MD2, +#endif + + MBEDTLS_MD_NONE +}; + +const int *mbedtls_md_list( void ) +{ + return( supported_digests ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ) +{ + if( NULL == md_name ) + return( NULL ); + + /* Get the appropriate digest information */ +#if defined(MBEDTLS_MD2_C) + if( !strcmp( "MD2", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD2 ); +#endif +#if defined(MBEDTLS_MD4_C) + if( !strcmp( "MD4", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD4 ); +#endif +#if defined(MBEDTLS_MD5_C) + if( !strcmp( "MD5", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_MD5 ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + if( !strcmp( "RIPEMD160", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_RIPEMD160 ); +#endif +#if defined(MBEDTLS_SHA1_C) + if( !strcmp( "SHA1", md_name ) || !strcmp( "SHA", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); +#endif +#if defined(MBEDTLS_SHA256_C) + if( !strcmp( "SHA224", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA224 ); + if( !strcmp( "SHA256", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA256 ); +#endif +#if defined(MBEDTLS_SHA512_C) + if( !strcmp( "SHA384", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA384 ); + if( !strcmp( "SHA512", md_name ) ) + return mbedtls_md_info_from_type( MBEDTLS_MD_SHA512 ); +#endif + return( NULL ); +} + +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ) +{ + switch( md_type ) + { +#if defined(MBEDTLS_MD2_C) + case MBEDTLS_MD_MD2: + return( &mbedtls_md2_info ); +#endif +#if defined(MBEDTLS_MD4_C) + case MBEDTLS_MD_MD4: + return( &mbedtls_md4_info ); +#endif +#if defined(MBEDTLS_MD5_C) + case MBEDTLS_MD_MD5: + return( &mbedtls_md5_info ); +#endif +#if defined(MBEDTLS_RIPEMD160_C) + case MBEDTLS_MD_RIPEMD160: + return( &mbedtls_ripemd160_info ); +#endif +#if defined(MBEDTLS_SHA1_C) + case MBEDTLS_MD_SHA1: + return( &mbedtls_sha1_info ); +#endif +#if defined(MBEDTLS_SHA256_C) + case MBEDTLS_MD_SHA224: + return( &mbedtls_sha224_info ); + case MBEDTLS_MD_SHA256: + return( &mbedtls_sha256_info ); +#endif +#if defined(MBEDTLS_SHA512_C) + case MBEDTLS_MD_SHA384: + return( &mbedtls_sha384_info ); + case MBEDTLS_MD_SHA512: + return( &mbedtls_sha512_info ); +#endif + default: + return( NULL ); + } +} + +void mbedtls_md_init( mbedtls_md_context_t *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md_context_t ) ); +} + +void mbedtls_md_free( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return; + + if( ctx->md_ctx != NULL ) + ctx->md_info->ctx_free_func( ctx->md_ctx ); + + if( ctx->hmac_ctx != NULL ) + { + mbedtls_platform_zeroize( ctx->hmac_ctx, + 2 * ctx->md_info->block_size ); + mbedtls_free( ctx->hmac_ctx ); + } + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md_context_t ) ); +} + +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ) +{ + if( dst == NULL || dst->md_info == NULL || + src == NULL || src->md_info == NULL || + dst->md_info != src->md_info ) + { + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + } + + dst->md_info->clone_func( dst->md_ctx, src->md_ctx ); + + return( 0 ); +} + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) +{ + return mbedtls_md_setup( ctx, md_info, 1 ); +} +#endif + +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ) +{ + if( md_info == NULL || ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( ( ctx->md_ctx = md_info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + + if( hmac != 0 ) + { + ctx->hmac_ctx = mbedtls_calloc( 2, md_info->block_size ); + if( ctx->hmac_ctx == NULL ) + { + md_info->ctx_free_func( ctx->md_ctx ); + return( MBEDTLS_ERR_MD_ALLOC_FAILED ); + } + } + + ctx->md_info = md_info; + + return( 0 ); +} + +int mbedtls_md_starts( mbedtls_md_context_t *ctx ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( ctx->md_info->starts_func( ctx->md_ctx ) ); +} + +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) ); +} + +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( ctx->md_info->finish_func( ctx->md_ctx, output ) ); +} + +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( md_info->digest_func( input, ilen, output ) ); +} + +#if defined(MBEDTLS_FS_IO) +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, unsigned char *output ) +{ + int ret; + FILE *f; + size_t n; + mbedtls_md_context_t ctx; + unsigned char buf[1024]; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_MD_FILE_IO_ERROR ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 0 ) ) != 0 ) + goto cleanup; + + if( ( ret = md_info->starts_func( ctx.md_ctx ) ) != 0 ) + goto cleanup; + + while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) + if( ( ret = md_info->update_func( ctx.md_ctx, buf, n ) ) != 0 ) + goto cleanup; + + if( ferror( f ) != 0 ) + ret = MBEDTLS_ERR_MD_FILE_IO_ERROR; + else + ret = md_info->finish_func( ctx.md_ctx, output ); + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + fclose( f ); + mbedtls_md_free( &ctx ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, size_t keylen ) +{ + int ret; + unsigned char sum[MBEDTLS_MD_MAX_SIZE]; + unsigned char *ipad, *opad; + size_t i; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + if( keylen > (size_t) ctx->md_info->block_size ) + { + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + goto cleanup; + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, sum ) ) != 0 ) + goto cleanup; + + keylen = ctx->md_info->size; + key = sum; + } + + ipad = (unsigned char *) ctx->hmac_ctx; + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + memset( ipad, 0x36, ctx->md_info->block_size ); + memset( opad, 0x5C, ctx->md_info->block_size ); + + for( i = 0; i < keylen; i++ ) + { + ipad[i] = (unsigned char)( ipad[i] ^ key[i] ); + opad[i] = (unsigned char)( opad[i] ^ key[i] ); + } + + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + goto cleanup; + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, ipad, + ctx->md_info->block_size ) ) != 0 ) + goto cleanup; + +cleanup: + mbedtls_platform_zeroize( sum, sizeof( sum ) ); + + return( ret ); +} + +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ) +{ + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( ctx->md_info->update_func( ctx->md_ctx, input, ilen ) ); +} + +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output ) +{ + int ret; + unsigned char tmp[MBEDTLS_MD_MAX_SIZE]; + unsigned char *opad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + opad = (unsigned char *) ctx->hmac_ctx + ctx->md_info->block_size; + + if( ( ret = ctx->md_info->finish_func( ctx->md_ctx, tmp ) ) != 0 ) + return( ret ); + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + return( ret ); + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, opad, + ctx->md_info->block_size ) ) != 0 ) + return( ret ); + if( ( ret = ctx->md_info->update_func( ctx->md_ctx, tmp, + ctx->md_info->size ) ) != 0 ) + return( ret ); + return( ctx->md_info->finish_func( ctx->md_ctx, output ) ); +} + +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ) +{ + int ret; + unsigned char *ipad; + + if( ctx == NULL || ctx->md_info == NULL || ctx->hmac_ctx == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + ipad = (unsigned char *) ctx->hmac_ctx; + + if( ( ret = ctx->md_info->starts_func( ctx->md_ctx ) ) != 0 ) + return( ret ); + return( ctx->md_info->update_func( ctx->md_ctx, ipad, + ctx->md_info->block_size ) ); +} + +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, + const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + mbedtls_md_context_t ctx; + int ret; + + if( md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + mbedtls_md_init( &ctx ); + + if( ( ret = mbedtls_md_setup( &ctx, md_info, 1 ) ) != 0 ) + goto cleanup; + + if( ( ret = mbedtls_md_hmac_starts( &ctx, key, keylen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_update( &ctx, input, ilen ) ) != 0 ) + goto cleanup; + if( ( ret = mbedtls_md_hmac_finish( &ctx, output ) ) != 0 ) + goto cleanup; + +cleanup: + mbedtls_md_free( &ctx ); + + return( ret ); +} + +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ) +{ + if( ctx == NULL || ctx->md_info == NULL ) + return( MBEDTLS_ERR_MD_BAD_INPUT_DATA ); + + return( ctx->md_info->process_func( ctx->md_ctx, data ) ); +} + +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( 0 ); + + return md_info->size; +} + +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( MBEDTLS_MD_NONE ); + + return md_info->type; +} + +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ) +{ + if( md_info == NULL ) + return( NULL ); + + return md_info->name; +} + +#endif /* MBEDTLS_MD_C */ diff --git a/common/mbedtls/md.h b/common/mbedtls/md.h new file mode 100644 index 000000000..797d5ff3e --- /dev/null +++ b/common/mbedtls/md.h @@ -0,0 +1,468 @@ + /** + * \file md.h + * + * \brief This file contains the generic message-digest wrapper. + * + * \author Adriaan de Jong + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_MD_H +#define MBEDTLS_MD_H + +#include + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#define MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE -0x5080 /**< The selected feature is not available. */ +#define MBEDTLS_ERR_MD_BAD_INPUT_DATA -0x5100 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_MD_ALLOC_FAILED -0x5180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_MD_FILE_IO_ERROR -0x5200 /**< Opening or reading of file failed. */ +#define MBEDTLS_ERR_MD_HW_ACCEL_FAILED -0x5280 /**< MD hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Supported message digests. + * + * \warning MD2, MD4, MD5 and SHA-1 are considered weak message digests and + * their use constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef enum { + MBEDTLS_MD_NONE=0, /**< None. */ + MBEDTLS_MD_MD2, /**< The MD2 message digest. */ + MBEDTLS_MD_MD4, /**< The MD4 message digest. */ + MBEDTLS_MD_MD5, /**< The MD5 message digest. */ + MBEDTLS_MD_SHA1, /**< The SHA-1 message digest. */ + MBEDTLS_MD_SHA224, /**< The SHA-224 message digest. */ + MBEDTLS_MD_SHA256, /**< The SHA-256 message digest. */ + MBEDTLS_MD_SHA384, /**< The SHA-384 message digest. */ + MBEDTLS_MD_SHA512, /**< The SHA-512 message digest. */ + MBEDTLS_MD_RIPEMD160, /**< The RIPEMD-160 message digest. */ +} mbedtls_md_type_t; + +#if defined(MBEDTLS_SHA512_C) +#define MBEDTLS_MD_MAX_SIZE 64 /* longest known is SHA512 */ +#else +#define MBEDTLS_MD_MAX_SIZE 32 /* longest known is SHA256 or less */ +#endif + +/** + * Opaque struct defined in md_internal.h. + */ +typedef struct mbedtls_md_info_t mbedtls_md_info_t; + +/** + * The generic message-digest context. + */ +typedef struct mbedtls_md_context_t +{ + /** Information about the associated message digest. */ + const mbedtls_md_info_t *md_info; + + /** The digest-specific context. */ + void *md_ctx; + + /** The HMAC part of the context. */ + void *hmac_ctx; +} mbedtls_md_context_t; + +/** + * \brief This function returns the list of digests supported by the + * generic digest module. + * + * \return A statically allocated array of digests. Each element + * in the returned list is an integer belonging to the + * message-digest enumeration #mbedtls_md_type_t. + * The last entry is 0. + */ +const int *mbedtls_md_list( void ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest name. + * + * \param md_name The name of the digest to search for. + * + * \return The message-digest information associated with \p md_name. + * \return NULL if the associated message-digest information is not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_string( const char *md_name ); + +/** + * \brief This function returns the message-digest information + * associated with the given digest type. + * + * \param md_type The type of digest to search for. + * + * \return The message-digest information associated with \p md_type. + * \return NULL if the associated message-digest information is not found. + */ +const mbedtls_md_info_t *mbedtls_md_info_from_type( mbedtls_md_type_t md_type ); + +/** + * \brief This function initializes a message-digest context without + * binding it to a particular message-digest algorithm. + * + * This function should always be called first. It prepares the + * context for mbedtls_md_setup() for binding it to a + * message-digest algorithm. + */ +void mbedtls_md_init( mbedtls_md_context_t *ctx ); + +/** + * \brief This function clears the internal structure of \p ctx and + * frees any embedded internal structure, but does not free + * \p ctx itself. + * + * If you have called mbedtls_md_setup() on \p ctx, you must + * call mbedtls_md_free() when you are no longer using the + * context. + * Calling this function if you have previously + * called mbedtls_md_init() and nothing else is optional. + * You must not call this function if you have not called + * mbedtls_md_init(). + */ +void mbedtls_md_free( mbedtls_md_context_t *ctx ); + +#if ! defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or mbedtls_md_free(). + * Makes it necessary to call mbedtls_md_free() later. + * + * \deprecated Superseded by mbedtls_md_setup() in 2.0.0 + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. + */ +int mbedtls_md_init_ctx( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info ) MBEDTLS_DEPRECATED; +#undef MBEDTLS_DEPRECATED +#endif /* MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function selects the message digest algorithm to use, + * and allocates internal structures. + * + * It should be called after mbedtls_md_init() or + * mbedtls_md_free(). Makes it necessary to call + * mbedtls_md_free() later. + * + * \param ctx The context to set up. + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param hmac Defines if HMAC is used. 0: HMAC is not used (saves some memory), + * or non-zero: HMAC is used with this context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + * \return #MBEDTLS_ERR_MD_ALLOC_FAILED on memory-allocation failure. + */ +int mbedtls_md_setup( mbedtls_md_context_t *ctx, const mbedtls_md_info_t *md_info, int hmac ); + +/** + * \brief This function clones the state of an message-digest + * context. + * + * \note You must call mbedtls_md_setup() on \c dst before calling + * this function. + * + * \note The two contexts must have the same type, + * for example, both are SHA-256. + * + * \warning This function clones the message-digest state, not the + * HMAC state. + * + * \param dst The destination context. + * \param src The context to be cloned. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification failure. + */ +int mbedtls_md_clone( mbedtls_md_context_t *dst, + const mbedtls_md_context_t *src ); + +/** + * \brief This function extracts the message-digest size from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The size of the message-digest output in Bytes. + */ +unsigned char mbedtls_md_get_size( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest type from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The type of the message digest. + */ +mbedtls_md_type_t mbedtls_md_get_type( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function extracts the message-digest name from the + * message-digest information structure. + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * + * \return The name of the message digest. + */ +const char *mbedtls_md_get_name( const mbedtls_md_info_t *md_info ); + +/** + * \brief This function starts a message-digest computation. + * + * You must call this function after setting up the context + * with mbedtls_md_setup(), and before passing data with + * mbedtls_md_update(). + * + * \param ctx The generic message-digest context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_starts( mbedtls_md_context_t *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing + * message-digest computation. + * + * You must call mbedtls_md_starts() before calling this + * function. You may call this function multiple times. + * Afterwards, call mbedtls_md_finish(). + * + * \param ctx The generic message-digest context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_update( mbedtls_md_context_t *ctx, const unsigned char *input, size_t ilen ); + +/** + * \brief This function finishes the digest operation, + * and writes the result to the output buffer. + * + * Call this function after a call to mbedtls_md_starts(), + * followed by any number of calls to mbedtls_md_update(). + * Afterwards, you may either clear the context with + * mbedtls_md_free(), or call mbedtls_md_starts() to reuse + * the context for another digest operation with the same + * algorithm. + * + * \param ctx The generic message-digest context. + * \param output The buffer for the generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_finish( mbedtls_md_context_t *ctx, unsigned char *output ); + +/** + * \brief This function calculates the message-digest of a buffer, + * with respect to a configurable message-digest algorithm + * in a single call. + * + * The result is calculated as + * Output = message_digest(input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md( const mbedtls_md_info_t *md_info, const unsigned char *input, size_t ilen, + unsigned char *output ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief This function calculates the message-digest checksum + * result of the contents of the provided file. + * + * The result is calculated as + * Output = message_digest(file contents). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param path The input file name. + * \param output The generic message-digest checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_FILE_IO_ERROR on an I/O error accessing + * the file pointed by \p path. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA if \p md_info was NULL. + */ +int mbedtls_md_file( const mbedtls_md_info_t *md_info, const char *path, + unsigned char *output ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief This function sets the HMAC key and prepares to + * authenticate a new message. + * + * Call this function after mbedtls_md_setup(), to use + * the MD context for an HMAC calculation, then call + * mbedtls_md_hmac_update() to provide the input data, and + * mbedtls_md_hmac_finish() to get the HMAC value. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC key in Bytes. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac_starts( mbedtls_md_context_t *ctx, const unsigned char *key, + size_t keylen ); + +/** + * \brief This function feeds an input buffer into an ongoing HMAC + * computation. + * + * Call mbedtls_md_hmac_starts() or mbedtls_md_hmac_reset() + * before calling this function. + * You may call this function multiple times to pass the + * input piecewise. + * Afterwards, call mbedtls_md_hmac_finish(). + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac_update( mbedtls_md_context_t *ctx, const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the HMAC operation, and writes + * the result to the output buffer. + * + * Call this function after mbedtls_md_hmac_starts() and + * mbedtls_md_hmac_update() to get the HMAC value. Afterwards + * you may either call mbedtls_md_free() to clear the context, + * or call mbedtls_md_hmac_reset() to reuse the context with + * the same HMAC key. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * \param output The generic HMAC checksum result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac_finish( mbedtls_md_context_t *ctx, unsigned char *output); + +/** + * \brief This function prepares to authenticate a new message with + * the same key as the previous HMAC operation. + * + * You may call this function after mbedtls_md_hmac_finish(). + * Afterwards call mbedtls_md_hmac_update() to pass the new + * input. + * + * \param ctx The message digest context containing an embedded HMAC + * context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac_reset( mbedtls_md_context_t *ctx ); + +/** + * \brief This function calculates the full generic HMAC + * on the input buffer with the provided key. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The HMAC result is calculated as + * output = generic HMAC(hmac key, input buffer). + * + * \param md_info The information structure of the message-digest algorithm + * to use. + * \param key The HMAC secret key. + * \param keylen The length of the HMAC secret key in Bytes. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The generic HMAC result. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MD_BAD_INPUT_DATA on parameter-verification + * failure. + */ +int mbedtls_md_hmac( const mbedtls_md_info_t *md_info, const unsigned char *key, size_t keylen, + const unsigned char *input, size_t ilen, + unsigned char *output ); + +/* Internal use */ +int mbedtls_md_process( mbedtls_md_context_t *ctx, const unsigned char *data ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_H */ diff --git a/common/mbedtls/md5.c b/common/mbedtls/md5.c new file mode 100644 index 000000000..e0b4c768b --- /dev/null +++ b/common/mbedtls/md5.c @@ -0,0 +1,497 @@ +/* + * RFC 1321 compliant MD5 implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The MD5 algorithm was designed by Ron Rivest in 1991. + * + * http://www.ietf.org/rfc/rfc1321.txt + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD5_C) + +#include "mbedtls/md5.h" +#include "mbedtls/platform_util.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 */ + +#if !defined(MBEDTLS_MD5_ALT) + +/* + * 32-bit integer manipulation macros (little endian) + */ +#ifndef GET_UINT32_LE +#define GET_UINT32_LE(n,b,i) \ +{ \ + (n) = ( (uint32_t) (b)[(i) ] ) \ + | ( (uint32_t) (b)[(i) + 1] << 8 ) \ + | ( (uint32_t) (b)[(i) + 2] << 16 ) \ + | ( (uint32_t) (b)[(i) + 3] << 24 ); \ +} +#endif + +#ifndef PUT_UINT32_LE +#define PUT_UINT32_LE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( ( (n) ) & 0xFF ); \ + (b)[(i) + 1] = (unsigned char) ( ( (n) >> 8 ) & 0xFF ); \ + (b)[(i) + 2] = (unsigned char) ( ( (n) >> 16 ) & 0xFF ); \ + (b)[(i) + 3] = (unsigned char) ( ( (n) >> 24 ) & 0xFF ); \ +} +#endif + +void mbedtls_md5_init( mbedtls_md5_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_md5_context ) ); +} + +void mbedtls_md5_free( mbedtls_md5_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_md5_context ) ); +} + +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ) +{ + *dst = *src; +} + +/* + * MD5 context setup + */ +int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + ctx->state[0] = 0x67452301; + ctx->state[1] = 0xEFCDAB89; + ctx->state[2] = 0x98BADCFE; + ctx->state[3] = 0x10325476; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_starts( mbedtls_md5_context *ctx ) +{ + mbedtls_md5_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_MD5_PROCESS_ALT) +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ) +{ + uint32_t X[16], A, B, C, D; + + GET_UINT32_LE( X[ 0], data, 0 ); + GET_UINT32_LE( X[ 1], data, 4 ); + GET_UINT32_LE( X[ 2], data, 8 ); + GET_UINT32_LE( X[ 3], data, 12 ); + GET_UINT32_LE( X[ 4], data, 16 ); + GET_UINT32_LE( X[ 5], data, 20 ); + GET_UINT32_LE( X[ 6], data, 24 ); + GET_UINT32_LE( X[ 7], data, 28 ); + GET_UINT32_LE( X[ 8], data, 32 ); + GET_UINT32_LE( X[ 9], data, 36 ); + GET_UINT32_LE( X[10], data, 40 ); + GET_UINT32_LE( X[11], data, 44 ); + GET_UINT32_LE( X[12], data, 48 ); + GET_UINT32_LE( X[13], data, 52 ); + GET_UINT32_LE( X[14], data, 56 ); + GET_UINT32_LE( X[15], data, 60 ); + +#define S(x,n) ((x << n) | ((x & 0xFFFFFFFF) >> (32 - n))) + +#define P(a,b,c,d,k,s,t) \ +{ \ + a += F(b,c,d) + X[k] + t; a = S(a,s) + b; \ +} + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + +#define F(x,y,z) (z ^ (x & (y ^ z))) + + P( A, B, C, D, 0, 7, 0xD76AA478 ); + P( D, A, B, C, 1, 12, 0xE8C7B756 ); + P( C, D, A, B, 2, 17, 0x242070DB ); + P( B, C, D, A, 3, 22, 0xC1BDCEEE ); + P( A, B, C, D, 4, 7, 0xF57C0FAF ); + P( D, A, B, C, 5, 12, 0x4787C62A ); + P( C, D, A, B, 6, 17, 0xA8304613 ); + P( B, C, D, A, 7, 22, 0xFD469501 ); + P( A, B, C, D, 8, 7, 0x698098D8 ); + P( D, A, B, C, 9, 12, 0x8B44F7AF ); + P( C, D, A, B, 10, 17, 0xFFFF5BB1 ); + P( B, C, D, A, 11, 22, 0x895CD7BE ); + P( A, B, C, D, 12, 7, 0x6B901122 ); + P( D, A, B, C, 13, 12, 0xFD987193 ); + P( C, D, A, B, 14, 17, 0xA679438E ); + P( B, C, D, A, 15, 22, 0x49B40821 ); + +#undef F + +#define F(x,y,z) (y ^ (z & (x ^ y))) + + P( A, B, C, D, 1, 5, 0xF61E2562 ); + P( D, A, B, C, 6, 9, 0xC040B340 ); + P( C, D, A, B, 11, 14, 0x265E5A51 ); + P( B, C, D, A, 0, 20, 0xE9B6C7AA ); + P( A, B, C, D, 5, 5, 0xD62F105D ); + P( D, A, B, C, 10, 9, 0x02441453 ); + P( C, D, A, B, 15, 14, 0xD8A1E681 ); + P( B, C, D, A, 4, 20, 0xE7D3FBC8 ); + P( A, B, C, D, 9, 5, 0x21E1CDE6 ); + P( D, A, B, C, 14, 9, 0xC33707D6 ); + P( C, D, A, B, 3, 14, 0xF4D50D87 ); + P( B, C, D, A, 8, 20, 0x455A14ED ); + P( A, B, C, D, 13, 5, 0xA9E3E905 ); + P( D, A, B, C, 2, 9, 0xFCEFA3F8 ); + P( C, D, A, B, 7, 14, 0x676F02D9 ); + P( B, C, D, A, 12, 20, 0x8D2A4C8A ); + +#undef F + +#define F(x,y,z) (x ^ y ^ z) + + P( A, B, C, D, 5, 4, 0xFFFA3942 ); + P( D, A, B, C, 8, 11, 0x8771F681 ); + P( C, D, A, B, 11, 16, 0x6D9D6122 ); + P( B, C, D, A, 14, 23, 0xFDE5380C ); + P( A, B, C, D, 1, 4, 0xA4BEEA44 ); + P( D, A, B, C, 4, 11, 0x4BDECFA9 ); + P( C, D, A, B, 7, 16, 0xF6BB4B60 ); + P( B, C, D, A, 10, 23, 0xBEBFBC70 ); + P( A, B, C, D, 13, 4, 0x289B7EC6 ); + P( D, A, B, C, 0, 11, 0xEAA127FA ); + P( C, D, A, B, 3, 16, 0xD4EF3085 ); + P( B, C, D, A, 6, 23, 0x04881D05 ); + P( A, B, C, D, 9, 4, 0xD9D4D039 ); + P( D, A, B, C, 12, 11, 0xE6DB99E5 ); + P( C, D, A, B, 15, 16, 0x1FA27CF8 ); + P( B, C, D, A, 2, 23, 0xC4AC5665 ); + +#undef F + +#define F(x,y,z) (y ^ (x | ~z)) + + P( A, B, C, D, 0, 6, 0xF4292244 ); + P( D, A, B, C, 7, 10, 0x432AFF97 ); + P( C, D, A, B, 14, 15, 0xAB9423A7 ); + P( B, C, D, A, 5, 21, 0xFC93A039 ); + P( A, B, C, D, 12, 6, 0x655B59C3 ); + P( D, A, B, C, 3, 10, 0x8F0CCC92 ); + P( C, D, A, B, 10, 15, 0xFFEFF47D ); + P( B, C, D, A, 1, 21, 0x85845DD1 ); + P( A, B, C, D, 8, 6, 0x6FA87E4F ); + P( D, A, B, C, 15, 10, 0xFE2CE6E0 ); + P( C, D, A, B, 6, 15, 0xA3014314 ); + P( B, C, D, A, 13, 21, 0x4E0811A1 ); + P( A, B, C, D, 4, 6, 0xF7537E82 ); + P( D, A, B, C, 11, 10, 0xBD3AF235 ); + P( C, D, A, B, 2, 15, 0x2AD7D2BB ); + P( B, C, D, A, 9, 21, 0xEB86D391 ); + +#undef F + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_md5_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_MD5_PROCESS_ALT */ + +/* + * MD5 process buffer + */ +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + uint32_t left; + + if( ilen == 0 ) + return( 0 ); + + 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 ); + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 64 ) + { + if( ( ret = mbedtls_internal_md5_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 64; + ilen -= 64; + } + + if( ilen > 0 ) + { + memcpy( (void *) (ctx->buffer + left), input, ilen ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_md5_update_ret( ctx, input, ilen ); +} +#endif + +/* + * MD5 final digest + */ +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + int ret; + uint32_t used; + uint32_t high, low; + + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 29 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT32_LE( low, ctx->buffer, 56 ); + PUT_UINT32_LE( high, ctx->buffer, 60 ); + + if( ( ret = mbedtls_internal_md5_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + PUT_UINT32_LE( ctx->state[0], output, 0 ); + PUT_UINT32_LE( ctx->state[1], output, 4 ); + PUT_UINT32_LE( ctx->state[2], output, 8 ); + PUT_UINT32_LE( ctx->state[3], output, 12 ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ) +{ + mbedtls_md5_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_MD5_ALT */ + +/* + * output = MD5( input buffer ) + */ +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + int ret; + mbedtls_md5_context ctx; + + mbedtls_md5_init( &ctx ); + + if( ( ret = mbedtls_md5_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md5_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_md5_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ) +{ + mbedtls_md5_ret( input, ilen, output ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) +/* + * RFC 1321 test vectors + */ +static const unsigned char md5_test_buf[7][81] = +{ + { "" }, + { "a" }, + { "abc" }, + { "message digest" }, + { "abcdefghijklmnopqrstuvwxyz" }, + { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789" }, + { "12345678901234567890123456789012345678901234567890123456789012" + "345678901234567890" } +}; + +static const size_t md5_test_buflen[7] = +{ + 0, 1, 3, 14, 26, 62, 80 +}; + +static const unsigned char md5_test_sum[7][16] = +{ + { 0xD4, 0x1D, 0x8C, 0xD9, 0x8F, 0x00, 0xB2, 0x04, + 0xE9, 0x80, 0x09, 0x98, 0xEC, 0xF8, 0x42, 0x7E }, + { 0x0C, 0xC1, 0x75, 0xB9, 0xC0, 0xF1, 0xB6, 0xA8, + 0x31, 0xC3, 0x99, 0xE2, 0x69, 0x77, 0x26, 0x61 }, + { 0x90, 0x01, 0x50, 0x98, 0x3C, 0xD2, 0x4F, 0xB0, + 0xD6, 0x96, 0x3F, 0x7D, 0x28, 0xE1, 0x7F, 0x72 }, + { 0xF9, 0x6B, 0x69, 0x7D, 0x7C, 0xB7, 0x93, 0x8D, + 0x52, 0x5A, 0x2F, 0x31, 0xAA, 0xF1, 0x61, 0xD0 }, + { 0xC3, 0xFC, 0xD3, 0xD7, 0x61, 0x92, 0xE4, 0x00, + 0x7D, 0xFB, 0x49, 0x6C, 0xCA, 0x67, 0xE1, 0x3B }, + { 0xD1, 0x74, 0xAB, 0x98, 0xD2, 0x77, 0xD9, 0xF5, + 0xA5, 0x61, 0x1C, 0x2C, 0x9F, 0x41, 0x9D, 0x9F }, + { 0x57, 0xED, 0xF4, 0xA2, 0x2B, 0xE3, 0xC9, 0x55, + 0xAC, 0x49, 0xDA, 0x2E, 0x21, 0x07, 0xB6, 0x7A } +}; + +/* + * Checkup routine + */ +int mbedtls_md5_self_test( int verbose ) +{ + int i, ret = 0; + unsigned char md5sum[16]; + + for( i = 0; i < 7; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " MD5 test #%d: ", i + 1 ); + + ret = mbedtls_md5_ret( md5_test_buf[i], md5_test_buflen[i], md5sum ); + if( ret != 0 ) + goto fail; + + if( memcmp( md5sum, md5_test_sum[i], 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_MD5_C */ diff --git a/common/mbedtls/md5.h b/common/mbedtls/md5.h new file mode 100644 index 000000000..d3af51fb0 --- /dev/null +++ b/common/mbedtls/md5.h @@ -0,0 +1,308 @@ +/** + * \file md5.h + * + * \brief MD5 message digest algorithm (hash function) + * + * \warning MD5 is considered a weak message digest and its use constitutes a + * security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_MD5_H +#define MBEDTLS_MD5_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_ERR_MD5_HW_ACCEL_FAILED -0x002F /**< MD5 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_MD5_ALT) +// Regular implementation +// + +/** + * \brief MD5 context structure + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_md5_context +{ + uint32_t total[2]; /*!< number of bytes processed */ + uint32_t state[4]; /*!< intermediate digest state */ + unsigned char buffer[64]; /*!< data block being processed */ +} +mbedtls_md5_context; + +#else /* MBEDTLS_MD5_ALT */ +#include "md5_alt.h" +#endif /* MBEDTLS_MD5_ALT */ + +/** + * \brief Initialize MD5 context + * + * \param ctx MD5 context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_init( mbedtls_md5_context *ctx ); + +/** + * \brief Clear MD5 context + * + * \param ctx MD5 context to be cleared + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_free( mbedtls_md5_context *ctx ); + +/** + * \brief Clone (the state of) an MD5 context + * + * \param dst The destination context + * \param src The context to be cloned + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +void mbedtls_md5_clone( mbedtls_md5_context *dst, + const mbedtls_md5_context *src ); + +/** + * \brief MD5 context setup + * + * \param ctx context to be initialized + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_starts_ret( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_update_ret( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_finish_ret( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_internal_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief MD5 context setup + * + * \deprecated Superseded by mbedtls_md5_starts_ret() in 2.7.0 + * + * \param ctx context to be initialized + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_starts( mbedtls_md5_context *ctx ); + +/** + * \brief MD5 process buffer + * + * \deprecated Superseded by mbedtls_md5_update_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param input buffer holding the data + * \param ilen length of the input data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_update( mbedtls_md5_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief MD5 final digest + * + * \deprecated Superseded by mbedtls_md5_finish_ret() in 2.7.0 + * + * \param ctx MD5 context + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_finish( mbedtls_md5_context *ctx, + unsigned char output[16] ); + +/** + * \brief MD5 process data block (internal use only) + * + * \deprecated Superseded by mbedtls_internal_md5_process() in 2.7.0 + * + * \param ctx MD5 context + * \param data buffer holding one block of data + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5_process( mbedtls_md5_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Output = MD5( input buffer ) + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \return 0 if successful + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_ret( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief Output = MD5( input buffer ) + * + * \deprecated Superseded by mbedtls_md5_ret() in 2.7.0 + * + * \param input buffer holding the data + * \param ilen length of the input data + * \param output MD5 checksum result + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +MBEDTLS_DEPRECATED void mbedtls_md5( const unsigned char *input, + size_t ilen, + unsigned char output[16] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + * + * \warning MD5 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +int mbedtls_md5_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_md5.h */ diff --git a/common/mbedtls/md_internal.h b/common/mbedtls/md_internal.h new file mode 100644 index 000000000..b917cf34d --- /dev/null +++ b/common/mbedtls/md_internal.h @@ -0,0 +1,117 @@ +/** + * \file md_internal.h + * + * \brief Message digest wrappers. + * + * \warning This in an internal header. Do not include directly. + * + * \author Adriaan de Jong + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_MD_WRAP_H +#define MBEDTLS_MD_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "md.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * Message digest information. + * Allows message digest functions to be called in a generic way. + */ +struct mbedtls_md_info_t +{ + /** Digest identifier */ + mbedtls_md_type_t type; + + /** Name of the message digest */ + const char * name; + + /** Output length of the digest function in bytes */ + int size; + + /** Block length of the digest function in bytes */ + int block_size; + + /** Digest initialisation function */ + int (*starts_func)( void *ctx ); + + /** Digest update function */ + int (*update_func)( void *ctx, const unsigned char *input, size_t ilen ); + + /** Digest finalisation function */ + int (*finish_func)( void *ctx, unsigned char *output ); + + /** Generic digest function */ + int (*digest_func)( const unsigned char *input, size_t ilen, + unsigned char *output ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + + /** Clone state from a context */ + void (*clone_func)( void *dst, const void *src ); + + /** Internal use only */ + int (*process_func)( void *ctx, const unsigned char *input ); +}; + +#if defined(MBEDTLS_MD2_C) +extern const mbedtls_md_info_t mbedtls_md2_info; +#endif +#if defined(MBEDTLS_MD4_C) +extern const mbedtls_md_info_t mbedtls_md4_info; +#endif +#if defined(MBEDTLS_MD5_C) +extern const mbedtls_md_info_t mbedtls_md5_info; +#endif +#if defined(MBEDTLS_RIPEMD160_C) +extern const mbedtls_md_info_t mbedtls_ripemd160_info; +#endif +#if defined(MBEDTLS_SHA1_C) +extern const mbedtls_md_info_t mbedtls_sha1_info; +#endif +#if defined(MBEDTLS_SHA256_C) +extern const mbedtls_md_info_t mbedtls_sha224_info; +extern const mbedtls_md_info_t mbedtls_sha256_info; +#endif +#if defined(MBEDTLS_SHA512_C) +extern const mbedtls_md_info_t mbedtls_sha384_info; +extern const mbedtls_md_info_t mbedtls_sha512_info; +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_MD_WRAP_H */ diff --git a/common/mbedtls/md_wrap.c b/common/mbedtls/md_wrap.c new file mode 100644 index 000000000..97067b042 --- /dev/null +++ b/common/mbedtls/md_wrap.c @@ -0,0 +1,588 @@ +/** + * \file md_wrap.c + * + * \brief Generic message digest wrapper for mbed TLS + * + * \author Adriaan de Jong + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_MD_C) + +#include "mbedtls/md_internal.h" + +#if defined(MBEDTLS_MD2_C) +#include "mbedtls/md2.h" +#endif + +#if defined(MBEDTLS_MD4_C) +#include "mbedtls/md4.h" +#endif + +#if defined(MBEDTLS_MD5_C) +#include "mbedtls/md5.h" +#endif + +#if defined(MBEDTLS_RIPEMD160_C) +#include "mbedtls/ripemd160.h" +#endif + +#if defined(MBEDTLS_SHA1_C) +#include "mbedtls/sha1.h" +#endif + +#if defined(MBEDTLS_SHA256_C) +#include "mbedtls/sha256.h" +#endif + +#if defined(MBEDTLS_SHA512_C) +#include "mbedtls/sha512.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_MD2_C) + +static int md2_starts_wrap( void *ctx ) +{ + return( mbedtls_md2_starts_ret( (mbedtls_md2_context *) ctx ) ); +} + +static int md2_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_md2_update_ret( (mbedtls_md2_context *) ctx, input, ilen ) ); +} + +static int md2_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_md2_finish_ret( (mbedtls_md2_context *) ctx, output ) ); +} + +static void *md2_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md2_context ) ); + + if( ctx != NULL ) + mbedtls_md2_init( (mbedtls_md2_context *) ctx ); + + return( ctx ); +} + +static void md2_ctx_free( void *ctx ) +{ + mbedtls_md2_free( (mbedtls_md2_context *) ctx ); + mbedtls_free( ctx ); +} + +static void md2_clone_wrap( void *dst, const void *src ) +{ + mbedtls_md2_clone( (mbedtls_md2_context *) dst, + (const mbedtls_md2_context *) src ); +} + +static int md2_process_wrap( void *ctx, const unsigned char *data ) +{ + ((void) data); + + return( mbedtls_internal_md2_process( (mbedtls_md2_context *) ctx ) ); +} + +const mbedtls_md_info_t mbedtls_md2_info = { + MBEDTLS_MD_MD2, + "MD2", + 16, + 16, + md2_starts_wrap, + md2_update_wrap, + md2_finish_wrap, + mbedtls_md2_ret, + md2_ctx_alloc, + md2_ctx_free, + md2_clone_wrap, + md2_process_wrap, +}; + +#endif /* MBEDTLS_MD2_C */ + +#if defined(MBEDTLS_MD4_C) + +static int md4_starts_wrap( void *ctx ) +{ + return( mbedtls_md4_starts_ret( (mbedtls_md4_context *) ctx ) ); +} + +static int md4_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_md4_update_ret( (mbedtls_md4_context *) ctx, input, ilen ) ); +} + +static int md4_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_md4_finish_ret( (mbedtls_md4_context *) ctx, output ) ); +} + +static void *md4_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md4_context ) ); + + if( ctx != NULL ) + mbedtls_md4_init( (mbedtls_md4_context *) ctx ); + + return( ctx ); +} + +static void md4_ctx_free( void *ctx ) +{ + mbedtls_md4_free( (mbedtls_md4_context *) ctx ); + mbedtls_free( ctx ); +} + +static void md4_clone_wrap( void *dst, const void *src ) +{ + mbedtls_md4_clone( (mbedtls_md4_context *) dst, + (const mbedtls_md4_context *) src ); +} + +static int md4_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_md4_process( (mbedtls_md4_context *) ctx, data ) ); +} + +const mbedtls_md_info_t mbedtls_md4_info = { + MBEDTLS_MD_MD4, + "MD4", + 16, + 64, + md4_starts_wrap, + md4_update_wrap, + md4_finish_wrap, + mbedtls_md4_ret, + md4_ctx_alloc, + md4_ctx_free, + md4_clone_wrap, + md4_process_wrap, +}; + +#endif /* MBEDTLS_MD4_C */ + +#if defined(MBEDTLS_MD5_C) + +static int md5_starts_wrap( void *ctx ) +{ + return( mbedtls_md5_starts_ret( (mbedtls_md5_context *) ctx ) ); +} + +static int md5_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_md5_update_ret( (mbedtls_md5_context *) ctx, input, ilen ) ); +} + +static int md5_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_md5_finish_ret( (mbedtls_md5_context *) ctx, output ) ); +} + +static void *md5_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_md5_context ) ); + + if( ctx != NULL ) + mbedtls_md5_init( (mbedtls_md5_context *) ctx ); + + return( ctx ); +} + +static void md5_ctx_free( void *ctx ) +{ + mbedtls_md5_free( (mbedtls_md5_context *) ctx ); + mbedtls_free( ctx ); +} + +static void md5_clone_wrap( void *dst, const void *src ) +{ + mbedtls_md5_clone( (mbedtls_md5_context *) dst, + (const mbedtls_md5_context *) src ); +} + +static int md5_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_md5_process( (mbedtls_md5_context *) ctx, data ) ); +} + +const mbedtls_md_info_t mbedtls_md5_info = { + MBEDTLS_MD_MD5, + "MD5", + 16, + 64, + md5_starts_wrap, + md5_update_wrap, + md5_finish_wrap, + mbedtls_md5_ret, + md5_ctx_alloc, + md5_ctx_free, + md5_clone_wrap, + md5_process_wrap, +}; + +#endif /* MBEDTLS_MD5_C */ + +#if defined(MBEDTLS_RIPEMD160_C) + +static int ripemd160_starts_wrap( void *ctx ) +{ + return( mbedtls_ripemd160_starts_ret( (mbedtls_ripemd160_context *) ctx ) ); +} + +static int ripemd160_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_ripemd160_update_ret( (mbedtls_ripemd160_context *) ctx, + input, ilen ) ); +} + +static int ripemd160_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_ripemd160_finish_ret( (mbedtls_ripemd160_context *) ctx, + output ) ); +} + +static void *ripemd160_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ripemd160_context ) ); + + if( ctx != NULL ) + mbedtls_ripemd160_init( (mbedtls_ripemd160_context *) ctx ); + + return( ctx ); +} + +static void ripemd160_ctx_free( void *ctx ) +{ + mbedtls_ripemd160_free( (mbedtls_ripemd160_context *) ctx ); + mbedtls_free( ctx ); +} + +static void ripemd160_clone_wrap( void *dst, const void *src ) +{ + mbedtls_ripemd160_clone( (mbedtls_ripemd160_context *) dst, + (const mbedtls_ripemd160_context *) src ); +} + +static int ripemd160_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_ripemd160_process( + (mbedtls_ripemd160_context *) ctx, data ) ); +} + +const mbedtls_md_info_t mbedtls_ripemd160_info = { + MBEDTLS_MD_RIPEMD160, + "RIPEMD160", + 20, + 64, + ripemd160_starts_wrap, + ripemd160_update_wrap, + ripemd160_finish_wrap, + mbedtls_ripemd160_ret, + ripemd160_ctx_alloc, + ripemd160_ctx_free, + ripemd160_clone_wrap, + ripemd160_process_wrap, +}; + +#endif /* MBEDTLS_RIPEMD160_C */ + +#if defined(MBEDTLS_SHA1_C) + +static int sha1_starts_wrap( void *ctx ) +{ + return( mbedtls_sha1_starts_ret( (mbedtls_sha1_context *) ctx ) ); +} + +static int sha1_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_sha1_update_ret( (mbedtls_sha1_context *) ctx, + input, ilen ) ); +} + +static int sha1_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_sha1_finish_ret( (mbedtls_sha1_context *) ctx, output ) ); +} + +static void *sha1_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha1_context ) ); + + if( ctx != NULL ) + mbedtls_sha1_init( (mbedtls_sha1_context *) ctx ); + + return( ctx ); +} + +static void sha1_clone_wrap( void *dst, const void *src ) +{ + mbedtls_sha1_clone( (mbedtls_sha1_context *) dst, + (const mbedtls_sha1_context *) src ); +} + +static void sha1_ctx_free( void *ctx ) +{ + mbedtls_sha1_free( (mbedtls_sha1_context *) ctx ); + mbedtls_free( ctx ); +} + +static int sha1_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_sha1_process( (mbedtls_sha1_context *) ctx, + data ) ); +} + +const mbedtls_md_info_t mbedtls_sha1_info = { + MBEDTLS_MD_SHA1, + "SHA1", + 20, + 64, + sha1_starts_wrap, + sha1_update_wrap, + sha1_finish_wrap, + mbedtls_sha1_ret, + sha1_ctx_alloc, + sha1_ctx_free, + sha1_clone_wrap, + sha1_process_wrap, +}; + +#endif /* MBEDTLS_SHA1_C */ + +/* + * Wrappers for generic message digests + */ +#if defined(MBEDTLS_SHA256_C) + +static int sha224_starts_wrap( void *ctx ) +{ + return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 1 ) ); +} + +static int sha224_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_sha256_update_ret( (mbedtls_sha256_context *) ctx, + input, ilen ) ); +} + +static int sha224_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_sha256_finish_ret( (mbedtls_sha256_context *) ctx, + output ) ); +} + +static int sha224_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + return( mbedtls_sha256_ret( input, ilen, output, 1 ) ); +} + +static void *sha224_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha256_context ) ); + + if( ctx != NULL ) + mbedtls_sha256_init( (mbedtls_sha256_context *) ctx ); + + return( ctx ); +} + +static void sha224_ctx_free( void *ctx ) +{ + mbedtls_sha256_free( (mbedtls_sha256_context *) ctx ); + mbedtls_free( ctx ); +} + +static void sha224_clone_wrap( void *dst, const void *src ) +{ + mbedtls_sha256_clone( (mbedtls_sha256_context *) dst, + (const mbedtls_sha256_context *) src ); +} + +static int sha224_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_sha256_process( (mbedtls_sha256_context *) ctx, + data ) ); +} + +const mbedtls_md_info_t mbedtls_sha224_info = { + MBEDTLS_MD_SHA224, + "SHA224", + 28, + 64, + sha224_starts_wrap, + sha224_update_wrap, + sha224_finish_wrap, + sha224_wrap, + sha224_ctx_alloc, + sha224_ctx_free, + sha224_clone_wrap, + sha224_process_wrap, +}; + +static int sha256_starts_wrap( void *ctx ) +{ + return( mbedtls_sha256_starts_ret( (mbedtls_sha256_context *) ctx, 0 ) ); +} + +static int sha256_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + return( mbedtls_sha256_ret( input, ilen, output, 0 ) ); +} + +const mbedtls_md_info_t mbedtls_sha256_info = { + MBEDTLS_MD_SHA256, + "SHA256", + 32, + 64, + sha256_starts_wrap, + sha224_update_wrap, + sha224_finish_wrap, + sha256_wrap, + sha224_ctx_alloc, + sha224_ctx_free, + sha224_clone_wrap, + sha224_process_wrap, +}; + +#endif /* MBEDTLS_SHA256_C */ + +#if defined(MBEDTLS_SHA512_C) + +static int sha384_starts_wrap( void *ctx ) +{ + return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 1 ) ); +} + +static int sha384_update_wrap( void *ctx, const unsigned char *input, + size_t ilen ) +{ + return( mbedtls_sha512_update_ret( (mbedtls_sha512_context *) ctx, + input, ilen ) ); +} + +static int sha384_finish_wrap( void *ctx, unsigned char *output ) +{ + return( mbedtls_sha512_finish_ret( (mbedtls_sha512_context *) ctx, + output ) ); +} + +static int sha384_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + return( mbedtls_sha512_ret( input, ilen, output, 1 ) ); +} + +static void *sha384_ctx_alloc( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_sha512_context ) ); + + if( ctx != NULL ) + mbedtls_sha512_init( (mbedtls_sha512_context *) ctx ); + + return( ctx ); +} + +static void sha384_ctx_free( void *ctx ) +{ + mbedtls_sha512_free( (mbedtls_sha512_context *) ctx ); + mbedtls_free( ctx ); +} + +static void sha384_clone_wrap( void *dst, const void *src ) +{ + mbedtls_sha512_clone( (mbedtls_sha512_context *) dst, + (const mbedtls_sha512_context *) src ); +} + +static int sha384_process_wrap( void *ctx, const unsigned char *data ) +{ + return( mbedtls_internal_sha512_process( (mbedtls_sha512_context *) ctx, + data ) ); +} + +const mbedtls_md_info_t mbedtls_sha384_info = { + MBEDTLS_MD_SHA384, + "SHA384", + 48, + 128, + sha384_starts_wrap, + sha384_update_wrap, + sha384_finish_wrap, + sha384_wrap, + sha384_ctx_alloc, + sha384_ctx_free, + sha384_clone_wrap, + sha384_process_wrap, +}; + +static int sha512_starts_wrap( void *ctx ) +{ + return( mbedtls_sha512_starts_ret( (mbedtls_sha512_context *) ctx, 0 ) ); +} + +static int sha512_wrap( const unsigned char *input, size_t ilen, + unsigned char *output ) +{ + return( mbedtls_sha512_ret( input, ilen, output, 0 ) ); +} + +const mbedtls_md_info_t mbedtls_sha512_info = { + MBEDTLS_MD_SHA512, + "SHA512", + 64, + 128, + sha512_starts_wrap, + sha384_update_wrap, + sha384_finish_wrap, + sha512_wrap, + sha384_ctx_alloc, + sha384_ctx_free, + sha384_clone_wrap, + sha384_process_wrap, +}; + +#endif /* MBEDTLS_SHA512_C */ + +#endif /* MBEDTLS_MD_C */ diff --git a/common/mbedtls/oid.c b/common/mbedtls/oid.c new file mode 100644 index 000000000..962bd189a --- /dev/null +++ b/common/mbedtls/oid.c @@ -0,0 +1,757 @@ +/** + * \file oid.c + * + * \brief Object Identifier (OID) database + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_OID_C) + +#include "mbedtls/oid.h" +#include "mbedtls/rsa.h" + +#include +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "mbedtls/x509.h" +#endif + +/* + * Macro to automatically add the size of #define'd OIDs + */ +#define ADD_LEN(s) s, MBEDTLS_OID_SIZE(s) + +/* + * Macro to generate an internal function for oid_XXX_from_asn1() (used by + * the other functions) + */ +#define FN_OID_TYPED_FROM_ASN1( TYPE_T, NAME, LIST ) \ +static const TYPE_T * oid_ ## NAME ## _from_asn1( const mbedtls_asn1_buf *oid ) \ +{ \ + const TYPE_T *p = LIST; \ + const mbedtls_oid_descriptor_t *cur = (const mbedtls_oid_descriptor_t *) p; \ + if( p == NULL || oid == NULL ) return( NULL ); \ + while( cur->asn1 != NULL ) { \ + if( cur->asn1_len == oid->len && \ + memcmp( cur->asn1, oid->p, oid->len ) == 0 ) { \ + return( p ); \ + } \ + p++; \ + cur = (const mbedtls_oid_descriptor_t *) p; \ + } \ + return( NULL ); \ +} + +/* + * Macro to generate a function for retrieving a single attribute from the + * descriptor of an mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_DESCRIPTOR_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->descriptor.ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving a single attribute from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR1(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving two attributes from an + * mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_ATTR2(FN_NAME, TYPE_T, TYPE_NAME, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( const mbedtls_asn1_buf *oid, ATTR1_TYPE * ATTR1, ATTR2_TYPE * ATTR2 ) \ +{ \ + const TYPE_T *data = oid_ ## TYPE_NAME ## _from_asn1( oid ); \ + if( data == NULL ) return( MBEDTLS_ERR_OID_NOT_FOUND ); \ + *ATTR1 = data->ATTR1; \ + *ATTR2 = data->ATTR2; \ + return( 0 ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on a single + * attribute from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR1(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1) \ +int FN_NAME( ATTR1_TYPE ATTR1, const char **oid, size_t *olen ) \ +{ \ + const TYPE_T *cur = LIST; \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == ATTR1 ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +/* + * Macro to generate a function for retrieving the OID based on two + * attributes from a mbedtls_oid_descriptor_t wrapper. + */ +#define FN_OID_GET_OID_BY_ATTR2(FN_NAME, TYPE_T, LIST, ATTR1_TYPE, ATTR1, \ + ATTR2_TYPE, ATTR2) \ +int FN_NAME( ATTR1_TYPE ATTR1, ATTR2_TYPE ATTR2, const char **oid , \ + size_t *olen ) \ +{ \ + const TYPE_T *cur = LIST; \ + while( cur->descriptor.asn1 != NULL ) { \ + if( cur->ATTR1 == ATTR1 && cur->ATTR2 == ATTR2 ) { \ + *oid = cur->descriptor.asn1; \ + *olen = cur->descriptor.asn1_len; \ + return( 0 ); \ + } \ + cur++; \ + } \ + return( MBEDTLS_ERR_OID_NOT_FOUND ); \ +} + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +/* + * For X520 attribute types + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + const char *short_name; +} oid_x520_attr_t; + +static const oid_x520_attr_t oid_x520_attr_type[] = +{ + { + { ADD_LEN( MBEDTLS_OID_AT_CN ), "id-at-commonName", "Common Name" }, + "CN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_COUNTRY ), "id-at-countryName", "Country" }, + "C", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_LOCALITY ), "id-at-locality", "Locality" }, + "L", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_STATE ), "id-at-state", "State" }, + "ST", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_ORGANIZATION ),"id-at-organizationName", "Organization" }, + "O", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_ORG_UNIT ), "id-at-organizationalUnitName", "Org Unit" }, + "OU", + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS9_EMAIL ), "emailAddress", "E-mail address" }, + "emailAddress", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_SERIAL_NUMBER ),"id-at-serialNumber", "Serial number" }, + "serialNumber", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_POSTAL_ADDRESS ),"id-at-postalAddress", "Postal address" }, + "postalAddress", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_POSTAL_CODE ), "id-at-postalCode", "Postal code" }, + "postalCode", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_SUR_NAME ), "id-at-surName", "Surname" }, + "SN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_GIVEN_NAME ), "id-at-givenName", "Given name" }, + "GN", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_INITIALS ), "id-at-initials", "Initials" }, + "initials", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_GENERATION_QUALIFIER ), "id-at-generationQualifier", "Generation qualifier" }, + "generationQualifier", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_TITLE ), "id-at-title", "Title" }, + "title", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_DN_QUALIFIER ),"id-at-dnQualifier", "Distinguished Name qualifier" }, + "dnQualifier", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_PSEUDONYM ), "id-at-pseudonym", "Pseudonym" }, + "pseudonym", + }, + { + { ADD_LEN( MBEDTLS_OID_DOMAIN_COMPONENT ), "id-domainComponent", "Domain component" }, + "DC", + }, + { + { ADD_LEN( MBEDTLS_OID_AT_UNIQUE_IDENTIFIER ), "id-at-uniqueIdentifier", "Unique Identifier" }, + "uniqueIdentifier", + }, + { + { NULL, 0, NULL, NULL }, + NULL, + } +}; + +FN_OID_TYPED_FROM_ASN1(oid_x520_attr_t, x520_attr, oid_x520_attr_type) +FN_OID_GET_ATTR1(mbedtls_oid_get_attr_short_name, oid_x520_attr_t, x520_attr, const char *, short_name) + +/* + * For X509 extensions + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + int ext_type; +} oid_x509_ext_t; + +static const oid_x509_ext_t oid_x509_ext[] = +{ + { + { ADD_LEN( MBEDTLS_OID_BASIC_CONSTRAINTS ), "id-ce-basicConstraints", "Basic Constraints" }, + MBEDTLS_X509_EXT_BASIC_CONSTRAINTS, + }, + { + { ADD_LEN( MBEDTLS_OID_KEY_USAGE ), "id-ce-keyUsage", "Key Usage" }, + MBEDTLS_X509_EXT_KEY_USAGE, + }, + { + { ADD_LEN( MBEDTLS_OID_EXTENDED_KEY_USAGE ), "id-ce-extKeyUsage", "Extended Key Usage" }, + MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE, + }, + { + { ADD_LEN( MBEDTLS_OID_SUBJECT_ALT_NAME ), "id-ce-subjectAltName", "Subject Alt Name" }, + MBEDTLS_X509_EXT_SUBJECT_ALT_NAME, + }, + { + { ADD_LEN( MBEDTLS_OID_NS_CERT_TYPE ), "id-netscape-certtype", "Netscape Certificate Type" }, + MBEDTLS_X509_EXT_NS_CERT_TYPE, + }, + { + { NULL, 0, NULL, NULL }, + 0, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_x509_ext_t, x509_ext, oid_x509_ext) +FN_OID_GET_ATTR1(mbedtls_oid_get_x509_ext_type, oid_x509_ext_t, x509_ext, int, ext_type) + +static const mbedtls_oid_descriptor_t oid_ext_key_usage[] = +{ + { ADD_LEN( MBEDTLS_OID_SERVER_AUTH ), "id-kp-serverAuth", "TLS Web Server Authentication" }, + { ADD_LEN( MBEDTLS_OID_CLIENT_AUTH ), "id-kp-clientAuth", "TLS Web Client Authentication" }, + { ADD_LEN( MBEDTLS_OID_CODE_SIGNING ), "id-kp-codeSigning", "Code Signing" }, + { ADD_LEN( MBEDTLS_OID_EMAIL_PROTECTION ), "id-kp-emailProtection", "E-mail Protection" }, + { ADD_LEN( MBEDTLS_OID_TIME_STAMPING ), "id-kp-timeStamping", "Time Stamping" }, + { ADD_LEN( MBEDTLS_OID_OCSP_SIGNING ), "id-kp-OCSPSigning", "OCSP Signing" }, + { NULL, 0, NULL, NULL }, +}; + +FN_OID_TYPED_FROM_ASN1(mbedtls_oid_descriptor_t, ext_key_usage, oid_ext_key_usage) +FN_OID_GET_ATTR1(mbedtls_oid_get_extended_key_usage, mbedtls_oid_descriptor_t, ext_key_usage, const char *, description) +#endif /* MBEDTLS_X509_USE_C || MBEDTLS_X509_CREATE_C */ + +#if defined(MBEDTLS_MD_C) +/* + * For SignatureAlgorithmIdentifier + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_pk_type_t pk_alg; +} oid_sig_alg_t; + +static const oid_sig_alg_t oid_sig_alg[] = +{ +#if defined(MBEDTLS_RSA_C) +#if defined(MBEDTLS_MD2_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD2 ), "md2WithRSAEncryption", "RSA with MD2" }, + MBEDTLS_MD_MD2, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD4 ), "md4WithRSAEncryption", "RSA with MD4" }, + MBEDTLS_MD_MD4, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_MD5 ), "md5WithRSAEncryption", "RSA with MD5" }, + MBEDTLS_MD_MD5, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA1 ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA224 ), "sha224WithRSAEncryption", "RSA with SHA-224" }, + MBEDTLS_MD_SHA224, MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA256 ), "sha256WithRSAEncryption", "RSA with SHA-256" }, + MBEDTLS_MD_SHA256, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA384 ), "sha384WithRSAEncryption", "RSA with SHA-384" }, + MBEDTLS_MD_SHA384, MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS1_SHA512 ), "sha512WithRSAEncryption", "RSA with SHA-512" }, + MBEDTLS_MD_SHA512, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_RSA_SHA_OBS ), "sha-1WithRSAEncryption", "RSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_RSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECDSA_C) +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA1 ), "ecdsa-with-SHA1", "ECDSA with SHA1" }, + MBEDTLS_MD_SHA1, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA224 ), "ecdsa-with-SHA224", "ECDSA with SHA224" }, + MBEDTLS_MD_SHA224, MBEDTLS_PK_ECDSA, + }, + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA256 ), "ecdsa-with-SHA256", "ECDSA with SHA256" }, + MBEDTLS_MD_SHA256, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA384 ), "ecdsa-with-SHA384", "ECDSA with SHA384" }, + MBEDTLS_MD_SHA384, MBEDTLS_PK_ECDSA, + }, + { + { ADD_LEN( MBEDTLS_OID_ECDSA_SHA512 ), "ecdsa-with-SHA512", "ECDSA with SHA512" }, + MBEDTLS_MD_SHA512, MBEDTLS_PK_ECDSA, + }, +#endif /* MBEDTLS_SHA512_C */ +#endif /* MBEDTLS_ECDSA_C */ +#if defined(MBEDTLS_RSA_C) + { + { ADD_LEN( MBEDTLS_OID_RSASSA_PSS ), "RSASSA-PSS", "RSASSA-PSS" }, + MBEDTLS_MD_NONE, MBEDTLS_PK_RSASSA_PSS, + }, +#endif /* MBEDTLS_RSA_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_sig_alg_t, sig_alg, oid_sig_alg) +FN_OID_GET_DESCRIPTOR_ATTR1(mbedtls_oid_get_sig_alg_desc, oid_sig_alg_t, sig_alg, const char *, description) +FN_OID_GET_ATTR2(mbedtls_oid_get_sig_alg, oid_sig_alg_t, sig_alg, mbedtls_md_type_t, md_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR2(mbedtls_oid_get_oid_by_sig_alg, oid_sig_alg_t, oid_sig_alg, mbedtls_pk_type_t, pk_alg, mbedtls_md_type_t, md_alg) +#endif /* MBEDTLS_MD_C */ + +/* + * For PublicKeyInfo (PKCS1, RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_pk_type_t pk_alg; +} oid_pk_alg_t; + +static const oid_pk_alg_t oid_pk_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_PKCS1_RSA ), "rsaEncryption", "RSA" }, + MBEDTLS_PK_RSA, + }, + { + { ADD_LEN( MBEDTLS_OID_EC_ALG_UNRESTRICTED ), "id-ecPublicKey", "Generic EC key" }, + MBEDTLS_PK_ECKEY, + }, + { + { ADD_LEN( MBEDTLS_OID_EC_ALG_ECDH ), "id-ecDH", "EC key for ECDH" }, + MBEDTLS_PK_ECKEY_DH, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_PK_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pk_alg_t, pk_alg, oid_pk_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_pk_alg, oid_pk_alg_t, pk_alg, mbedtls_pk_type_t, pk_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_pk_alg, oid_pk_alg_t, oid_pk_alg, mbedtls_pk_type_t, pk_alg) + +#if defined(MBEDTLS_ECP_C) +/* + * For namedCurve (RFC 5480) + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_ecp_group_id grp_id; +} oid_ecp_grp_t; + +static const oid_ecp_grp_t oid_ecp_grp[] = +{ +#if defined(MBEDTLS_ECP_DP_SECP192R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192R1 ), "secp192r1", "secp192r1" }, + MBEDTLS_ECP_DP_SECP192R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224R1 ), "secp224r1", "secp224r1" }, + MBEDTLS_ECP_DP_SECP224R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256R1 ), "secp256r1", "secp256r1" }, + MBEDTLS_ECP_DP_SECP256R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP384R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP384R1 ), "secp384r1", "secp384r1" }, + MBEDTLS_ECP_DP_SECP384R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP521R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP521R1 ), "secp521r1", "secp521r1" }, + MBEDTLS_ECP_DP_SECP521R1, + }, +#endif /* MBEDTLS_ECP_DP_SECP521R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP192K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP192K1 ), "secp192k1", "secp192k1" }, + MBEDTLS_ECP_DP_SECP192K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP192K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP224K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP224K1 ), "secp224k1", "secp224k1" }, + MBEDTLS_ECP_DP_SECP224K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP224K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_SECP256K1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_SECP256K1 ), "secp256k1", "secp256k1" }, + MBEDTLS_ECP_DP_SECP256K1, + }, +#endif /* MBEDTLS_ECP_DP_SECP256K1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP256R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP256R1 ), "brainpoolP256r1","brainpool256r1" }, + MBEDTLS_ECP_DP_BP256R1, + }, +#endif /* MBEDTLS_ECP_DP_BP256R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP384R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP384R1 ), "brainpoolP384r1","brainpool384r1" }, + MBEDTLS_ECP_DP_BP384R1, + }, +#endif /* MBEDTLS_ECP_DP_BP384R1_ENABLED */ +#if defined(MBEDTLS_ECP_DP_BP512R1_ENABLED) + { + { ADD_LEN( MBEDTLS_OID_EC_GRP_BP512R1 ), "brainpoolP512r1","brainpool512r1" }, + MBEDTLS_ECP_DP_BP512R1, + }, +#endif /* MBEDTLS_ECP_DP_BP512R1_ENABLED */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_ECP_DP_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_ecp_grp_t, grp_id, oid_ecp_grp) +FN_OID_GET_ATTR1(mbedtls_oid_get_ec_grp, oid_ecp_grp_t, grp_id, mbedtls_ecp_group_id, grp_id) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_ec_grp, oid_ecp_grp_t, oid_ecp_grp, mbedtls_ecp_group_id, grp_id) +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_CIPHER_C) +/* + * For PKCS#5 PBES2 encryption algorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_cipher_type_t cipher_alg; +} oid_cipher_alg_t; + +static const oid_cipher_alg_t oid_cipher_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_DES_CBC ), "desCBC", "DES-CBC" }, + MBEDTLS_CIPHER_DES_CBC, + }, + { + { ADD_LEN( MBEDTLS_OID_DES_EDE3_CBC ), "des-ede3-cbc", "DES-EDE3-CBC" }, + MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_cipher_alg_t, cipher_alg, oid_cipher_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_cipher_alg, oid_cipher_alg_t, cipher_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_MD_C) +/* + * For digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; +} oid_md_alg_t; + +static const oid_md_alg_t oid_md_alg[] = +{ +#if defined(MBEDTLS_MD2_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD2 ), "id-md2", "MD2" }, + MBEDTLS_MD_MD2, + }, +#endif /* MBEDTLS_MD2_C */ +#if defined(MBEDTLS_MD4_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD4 ), "id-md4", "MD4" }, + MBEDTLS_MD_MD4, + }, +#endif /* MBEDTLS_MD4_C */ +#if defined(MBEDTLS_MD5_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_MD5 ), "id-md5", "MD5" }, + MBEDTLS_MD_MD5, + }, +#endif /* MBEDTLS_MD5_C */ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA1 ), "id-sha1", "SHA-1" }, + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA224 ), "id-sha224", "SHA-224" }, + MBEDTLS_MD_SHA224, + }, + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA256 ), "id-sha256", "SHA-256" }, + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA384 ), "id-sha384", "SHA-384" }, + MBEDTLS_MD_SHA384, + }, + { + { ADD_LEN( MBEDTLS_OID_DIGEST_ALG_SHA512 ), "id-sha512", "SHA-512" }, + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_alg_t, md_alg, oid_md_alg) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_alg, oid_md_alg_t, md_alg, mbedtls_md_type_t, md_alg) +FN_OID_GET_OID_BY_ATTR1(mbedtls_oid_get_oid_by_md, oid_md_alg_t, oid_md_alg, mbedtls_md_type_t, md_alg) + +/* + * For HMAC digestAlgorithm + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_hmac; +} oid_md_hmac_t; + +static const oid_md_hmac_t oid_md_hmac[] = +{ +#if defined(MBEDTLS_SHA1_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA1 ), "hmacSHA1", "HMAC-SHA-1" }, + MBEDTLS_MD_SHA1, + }, +#endif /* MBEDTLS_SHA1_C */ +#if defined(MBEDTLS_SHA256_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA224 ), "hmacSHA224", "HMAC-SHA-224" }, + MBEDTLS_MD_SHA224, + }, + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA256 ), "hmacSHA256", "HMAC-SHA-256" }, + MBEDTLS_MD_SHA256, + }, +#endif /* MBEDTLS_SHA256_C */ +#if defined(MBEDTLS_SHA512_C) + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA384 ), "hmacSHA384", "HMAC-SHA-384" }, + MBEDTLS_MD_SHA384, + }, + { + { ADD_LEN( MBEDTLS_OID_HMAC_SHA512 ), "hmacSHA512", "HMAC-SHA-512" }, + MBEDTLS_MD_SHA512, + }, +#endif /* MBEDTLS_SHA512_C */ + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_md_hmac_t, md_hmac, oid_md_hmac) +FN_OID_GET_ATTR1(mbedtls_oid_get_md_hmac, oid_md_hmac_t, md_hmac, mbedtls_md_type_t, md_hmac) +#endif /* MBEDTLS_MD_C */ + +#if defined(MBEDTLS_PKCS12_C) +/* + * For PKCS#12 PBEs + */ +typedef struct { + mbedtls_oid_descriptor_t descriptor; + mbedtls_md_type_t md_alg; + mbedtls_cipher_type_t cipher_alg; +} oid_pkcs12_pbe_alg_t; + +static const oid_pkcs12_pbe_alg_t oid_pkcs12_pbe_alg[] = +{ + { + { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC ), "pbeWithSHAAnd3-KeyTripleDES-CBC", "PBE with SHA1 and 3-Key 3DES" }, + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE3_CBC, + }, + { + { ADD_LEN( MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC ), "pbeWithSHAAnd2-KeyTripleDES-CBC", "PBE with SHA1 and 2-Key 3DES" }, + MBEDTLS_MD_SHA1, MBEDTLS_CIPHER_DES_EDE_CBC, + }, + { + { NULL, 0, NULL, NULL }, + MBEDTLS_MD_NONE, MBEDTLS_CIPHER_NONE, + }, +}; + +FN_OID_TYPED_FROM_ASN1(oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, oid_pkcs12_pbe_alg) +FN_OID_GET_ATTR2(mbedtls_oid_get_pkcs12_pbe_alg, oid_pkcs12_pbe_alg_t, pkcs12_pbe_alg, mbedtls_md_type_t, md_alg, mbedtls_cipher_type_t, cipher_alg) +#endif /* MBEDTLS_PKCS12_C */ + +#define OID_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +/* Return the x.y.z.... style numeric string for the given OID */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, + const mbedtls_asn1_buf *oid ) +{ + int ret; + size_t i, n; + unsigned int value; + char *p; + + p = buf; + n = size; + + /* First byte contains first two dots */ + if( oid->len > 0 ) + { + ret = mbedtls_snprintf( p, n, "%d.%d", oid->p[0] / 40, oid->p[0] % 40 ); + OID_SAFE_SNPRINTF; + } + + value = 0; + for( i = 1; i < oid->len; i++ ) + { + /* Prevent overflow in value. */ + if( ( ( value << 7 ) >> 7 ) != value ) + return( MBEDTLS_ERR_OID_BUF_TOO_SMALL ); + + value <<= 7; + value += oid->p[i] & 0x7F; + + if( !( oid->p[i] & 0x80 ) ) + { + /* Last byte */ + ret = mbedtls_snprintf( p, n, ".%d", value ); + OID_SAFE_SNPRINTF; + value = 0; + } + } + + return( (int) ( size - n ) ); +} + +#endif /* MBEDTLS_OID_C */ diff --git a/common/mbedtls/oid.h b/common/mbedtls/oid.h new file mode 100644 index 000000000..1ea4a3f16 --- /dev/null +++ b/common/mbedtls/oid.h @@ -0,0 +1,607 @@ +/** + * \file oid.h + * + * \brief Object Identifier (OID) database + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_OID_H +#define MBEDTLS_OID_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "asn1.h" +#include "pk.h" + +#include + +#if defined(MBEDTLS_CIPHER_C) +#include "cipher.h" +#endif + +#if defined(MBEDTLS_MD_C) +#include "md.h" +#endif + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +#include "x509.h" +#endif + +#define MBEDTLS_ERR_OID_NOT_FOUND -0x002E /**< OID is not found. */ +#define MBEDTLS_ERR_OID_BUF_TOO_SMALL -0x000B /**< output buffer is too small */ + +/* + * Top level OID tuples + */ +#define MBEDTLS_OID_ISO_MEMBER_BODIES "\x2a" /* {iso(1) member-body(2)} */ +#define MBEDTLS_OID_ISO_IDENTIFIED_ORG "\x2b" /* {iso(1) identified-organization(3)} */ +#define MBEDTLS_OID_ISO_CCITT_DS "\x55" /* {joint-iso-ccitt(2) ds(5)} */ +#define MBEDTLS_OID_ISO_ITU_COUNTRY "\x60" /* {joint-iso-itu-t(2) country(16)} */ + +/* + * ISO Member bodies OID parts + */ +#define MBEDTLS_OID_COUNTRY_US "\x86\x48" /* {us(840)} */ +#define MBEDTLS_OID_ORG_RSA_DATA_SECURITY "\x86\xf7\x0d" /* {rsadsi(113549)} */ +#define MBEDTLS_OID_RSA_COMPANY MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_RSA_DATA_SECURITY /* {iso(1) member-body(2) us(840) rsadsi(113549)} */ +#define MBEDTLS_OID_ORG_ANSI_X9_62 "\xce\x3d" /* ansi-X9-62(10045) */ +#define MBEDTLS_OID_ANSI_X9_62 MBEDTLS_OID_ISO_MEMBER_BODIES MBEDTLS_OID_COUNTRY_US \ + MBEDTLS_OID_ORG_ANSI_X9_62 + +/* + * ISO Identified organization OID parts + */ +#define MBEDTLS_OID_ORG_DOD "\x06" /* {dod(6)} */ +#define MBEDTLS_OID_ORG_OIW "\x0e" +#define MBEDTLS_OID_OIW_SECSIG MBEDTLS_OID_ORG_OIW "\x03" +#define MBEDTLS_OID_OIW_SECSIG_ALG MBEDTLS_OID_OIW_SECSIG "\x02" +#define MBEDTLS_OID_OIW_SECSIG_SHA1 MBEDTLS_OID_OIW_SECSIG_ALG "\x1a" +#define MBEDTLS_OID_ORG_CERTICOM "\x81\x04" /* certicom(132) */ +#define MBEDTLS_OID_CERTICOM MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_CERTICOM +#define MBEDTLS_OID_ORG_TELETRUST "\x24" /* teletrust(36) */ +#define MBEDTLS_OID_TELETRUST MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_TELETRUST + +/* + * ISO ITU OID parts + */ +#define MBEDTLS_OID_ORGANIZATION "\x01" /* {organization(1)} */ +#define MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ISO_ITU_COUNTRY MBEDTLS_OID_COUNTRY_US MBEDTLS_OID_ORGANIZATION /* {joint-iso-itu-t(2) country(16) us(840) organization(1)} */ + +#define MBEDTLS_OID_ORG_GOV "\x65" /* {gov(101)} */ +#define MBEDTLS_OID_GOV MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_GOV /* {joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101)} */ + +#define MBEDTLS_OID_ORG_NETSCAPE "\x86\xF8\x42" /* {netscape(113730)} */ +#define MBEDTLS_OID_NETSCAPE MBEDTLS_OID_ISO_ITU_US_ORG MBEDTLS_OID_ORG_NETSCAPE /* Netscape OID {joint-iso-itu-t(2) country(16) us(840) organization(1) netscape(113730)} */ + +/* ISO arc for standard certificate and CRL extensions */ +#define MBEDTLS_OID_ID_CE MBEDTLS_OID_ISO_CCITT_DS "\x1D" /**< id-ce OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 29} */ + +#define MBEDTLS_OID_NIST_ALG MBEDTLS_OID_GOV "\x03\x04" /** { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) */ + +/** + * Private Internet Extensions + * { iso(1) identified-organization(3) dod(6) internet(1) + * security(5) mechanisms(5) pkix(7) } + */ +#define MBEDTLS_OID_PKIX MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_ORG_DOD "\x01\x05\x05\x07" + +/* + * Arc for standard naming attributes + */ +#define MBEDTLS_OID_AT MBEDTLS_OID_ISO_CCITT_DS "\x04" /**< id-at OBJECT IDENTIFIER ::= {joint-iso-ccitt(2) ds(5) 4} */ +#define MBEDTLS_OID_AT_CN MBEDTLS_OID_AT "\x03" /**< id-at-commonName AttributeType:= {id-at 3} */ +#define MBEDTLS_OID_AT_SUR_NAME MBEDTLS_OID_AT "\x04" /**< id-at-surName AttributeType:= {id-at 4} */ +#define MBEDTLS_OID_AT_SERIAL_NUMBER MBEDTLS_OID_AT "\x05" /**< id-at-serialNumber AttributeType:= {id-at 5} */ +#define MBEDTLS_OID_AT_COUNTRY MBEDTLS_OID_AT "\x06" /**< id-at-countryName AttributeType:= {id-at 6} */ +#define MBEDTLS_OID_AT_LOCALITY MBEDTLS_OID_AT "\x07" /**< id-at-locality AttributeType:= {id-at 7} */ +#define MBEDTLS_OID_AT_STATE MBEDTLS_OID_AT "\x08" /**< id-at-state AttributeType:= {id-at 8} */ +#define MBEDTLS_OID_AT_ORGANIZATION MBEDTLS_OID_AT "\x0A" /**< id-at-organizationName AttributeType:= {id-at 10} */ +#define MBEDTLS_OID_AT_ORG_UNIT MBEDTLS_OID_AT "\x0B" /**< id-at-organizationalUnitName AttributeType:= {id-at 11} */ +#define MBEDTLS_OID_AT_TITLE MBEDTLS_OID_AT "\x0C" /**< id-at-title AttributeType:= {id-at 12} */ +#define MBEDTLS_OID_AT_POSTAL_ADDRESS MBEDTLS_OID_AT "\x10" /**< id-at-postalAddress AttributeType:= {id-at 16} */ +#define MBEDTLS_OID_AT_POSTAL_CODE MBEDTLS_OID_AT "\x11" /**< id-at-postalCode AttributeType:= {id-at 17} */ +#define MBEDTLS_OID_AT_GIVEN_NAME MBEDTLS_OID_AT "\x2A" /**< id-at-givenName AttributeType:= {id-at 42} */ +#define MBEDTLS_OID_AT_INITIALS MBEDTLS_OID_AT "\x2B" /**< id-at-initials AttributeType:= {id-at 43} */ +#define MBEDTLS_OID_AT_GENERATION_QUALIFIER MBEDTLS_OID_AT "\x2C" /**< id-at-generationQualifier AttributeType:= {id-at 44} */ +#define MBEDTLS_OID_AT_UNIQUE_IDENTIFIER MBEDTLS_OID_AT "\x2D" /**< id-at-uniqueIdentifier AttributType:= {id-at 45} */ +#define MBEDTLS_OID_AT_DN_QUALIFIER MBEDTLS_OID_AT "\x2E" /**< id-at-dnQualifier AttributeType:= {id-at 46} */ +#define MBEDTLS_OID_AT_PSEUDONYM MBEDTLS_OID_AT "\x41" /**< id-at-pseudonym AttributeType:= {id-at 65} */ + +#define MBEDTLS_OID_DOMAIN_COMPONENT "\x09\x92\x26\x89\x93\xF2\x2C\x64\x01\x19" /** id-domainComponent AttributeType:= {itu-t(0) data(9) pss(2342) ucl(19200300) pilot(100) pilotAttributeType(1) domainComponent(25)} */ + +/* + * OIDs for standard certificate extensions + */ +#define MBEDTLS_OID_AUTHORITY_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x23" /**< id-ce-authorityKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 35 } */ +#define MBEDTLS_OID_SUBJECT_KEY_IDENTIFIER MBEDTLS_OID_ID_CE "\x0E" /**< id-ce-subjectKeyIdentifier OBJECT IDENTIFIER ::= { id-ce 14 } */ +#define MBEDTLS_OID_KEY_USAGE MBEDTLS_OID_ID_CE "\x0F" /**< id-ce-keyUsage OBJECT IDENTIFIER ::= { id-ce 15 } */ +#define MBEDTLS_OID_CERTIFICATE_POLICIES MBEDTLS_OID_ID_CE "\x20" /**< id-ce-certificatePolicies OBJECT IDENTIFIER ::= { id-ce 32 } */ +#define MBEDTLS_OID_POLICY_MAPPINGS MBEDTLS_OID_ID_CE "\x21" /**< id-ce-policyMappings OBJECT IDENTIFIER ::= { id-ce 33 } */ +#define MBEDTLS_OID_SUBJECT_ALT_NAME MBEDTLS_OID_ID_CE "\x11" /**< id-ce-subjectAltName OBJECT IDENTIFIER ::= { id-ce 17 } */ +#define MBEDTLS_OID_ISSUER_ALT_NAME MBEDTLS_OID_ID_CE "\x12" /**< id-ce-issuerAltName OBJECT IDENTIFIER ::= { id-ce 18 } */ +#define MBEDTLS_OID_SUBJECT_DIRECTORY_ATTRS MBEDTLS_OID_ID_CE "\x09" /**< id-ce-subjectDirectoryAttributes OBJECT IDENTIFIER ::= { id-ce 9 } */ +#define MBEDTLS_OID_BASIC_CONSTRAINTS MBEDTLS_OID_ID_CE "\x13" /**< id-ce-basicConstraints OBJECT IDENTIFIER ::= { id-ce 19 } */ +#define MBEDTLS_OID_NAME_CONSTRAINTS MBEDTLS_OID_ID_CE "\x1E" /**< id-ce-nameConstraints OBJECT IDENTIFIER ::= { id-ce 30 } */ +#define MBEDTLS_OID_POLICY_CONSTRAINTS MBEDTLS_OID_ID_CE "\x24" /**< id-ce-policyConstraints OBJECT IDENTIFIER ::= { id-ce 36 } */ +#define MBEDTLS_OID_EXTENDED_KEY_USAGE MBEDTLS_OID_ID_CE "\x25" /**< id-ce-extKeyUsage OBJECT IDENTIFIER ::= { id-ce 37 } */ +#define MBEDTLS_OID_CRL_DISTRIBUTION_POINTS MBEDTLS_OID_ID_CE "\x1F" /**< id-ce-cRLDistributionPoints OBJECT IDENTIFIER ::= { id-ce 31 } */ +#define MBEDTLS_OID_INIHIBIT_ANYPOLICY MBEDTLS_OID_ID_CE "\x36" /**< id-ce-inhibitAnyPolicy OBJECT IDENTIFIER ::= { id-ce 54 } */ +#define MBEDTLS_OID_FRESHEST_CRL MBEDTLS_OID_ID_CE "\x2E" /**< id-ce-freshestCRL OBJECT IDENTIFIER ::= { id-ce 46 } */ + +/* + * Netscape certificate extensions + */ +#define MBEDTLS_OID_NS_CERT MBEDTLS_OID_NETSCAPE "\x01" +#define MBEDTLS_OID_NS_CERT_TYPE MBEDTLS_OID_NS_CERT "\x01" +#define MBEDTLS_OID_NS_BASE_URL MBEDTLS_OID_NS_CERT "\x02" +#define MBEDTLS_OID_NS_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x03" +#define MBEDTLS_OID_NS_CA_REVOCATION_URL MBEDTLS_OID_NS_CERT "\x04" +#define MBEDTLS_OID_NS_RENEWAL_URL MBEDTLS_OID_NS_CERT "\x07" +#define MBEDTLS_OID_NS_CA_POLICY_URL MBEDTLS_OID_NS_CERT "\x08" +#define MBEDTLS_OID_NS_SSL_SERVER_NAME MBEDTLS_OID_NS_CERT "\x0C" +#define MBEDTLS_OID_NS_COMMENT MBEDTLS_OID_NS_CERT "\x0D" +#define MBEDTLS_OID_NS_DATA_TYPE MBEDTLS_OID_NETSCAPE "\x02" +#define MBEDTLS_OID_NS_CERT_SEQUENCE MBEDTLS_OID_NS_DATA_TYPE "\x05" + +/* + * OIDs for CRL extensions + */ +#define MBEDTLS_OID_PRIVATE_KEY_USAGE_PERIOD MBEDTLS_OID_ID_CE "\x10" +#define MBEDTLS_OID_CRL_NUMBER MBEDTLS_OID_ID_CE "\x14" /**< id-ce-cRLNumber OBJECT IDENTIFIER ::= { id-ce 20 } */ + +/* + * X.509 v3 Extended key usage OIDs + */ +#define MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE MBEDTLS_OID_EXTENDED_KEY_USAGE "\x00" /**< anyExtendedKeyUsage OBJECT IDENTIFIER ::= { id-ce-extKeyUsage 0 } */ + +#define MBEDTLS_OID_KP MBEDTLS_OID_PKIX "\x03" /**< id-kp OBJECT IDENTIFIER ::= { id-pkix 3 } */ +#define MBEDTLS_OID_SERVER_AUTH MBEDTLS_OID_KP "\x01" /**< id-kp-serverAuth OBJECT IDENTIFIER ::= { id-kp 1 } */ +#define MBEDTLS_OID_CLIENT_AUTH MBEDTLS_OID_KP "\x02" /**< id-kp-clientAuth OBJECT IDENTIFIER ::= { id-kp 2 } */ +#define MBEDTLS_OID_CODE_SIGNING MBEDTLS_OID_KP "\x03" /**< id-kp-codeSigning OBJECT IDENTIFIER ::= { id-kp 3 } */ +#define MBEDTLS_OID_EMAIL_PROTECTION MBEDTLS_OID_KP "\x04" /**< id-kp-emailProtection OBJECT IDENTIFIER ::= { id-kp 4 } */ +#define MBEDTLS_OID_TIME_STAMPING MBEDTLS_OID_KP "\x08" /**< id-kp-timeStamping OBJECT IDENTIFIER ::= { id-kp 8 } */ +#define MBEDTLS_OID_OCSP_SIGNING MBEDTLS_OID_KP "\x09" /**< id-kp-OCSPSigning OBJECT IDENTIFIER ::= { id-kp 9 } */ + +/* + * PKCS definition OIDs + */ + +#define MBEDTLS_OID_PKCS MBEDTLS_OID_RSA_COMPANY "\x01" /**< pkcs OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) 1 } */ +#define MBEDTLS_OID_PKCS1 MBEDTLS_OID_PKCS "\x01" /**< pkcs-1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 1 } */ +#define MBEDTLS_OID_PKCS5 MBEDTLS_OID_PKCS "\x05" /**< pkcs-5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 5 } */ +#define MBEDTLS_OID_PKCS9 MBEDTLS_OID_PKCS "\x09" /**< pkcs-9 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 9 } */ +#define MBEDTLS_OID_PKCS12 MBEDTLS_OID_PKCS "\x0c" /**< pkcs-12 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) pkcs(1) 12 } */ + +/* + * PKCS#1 OIDs + */ +#define MBEDTLS_OID_PKCS1_RSA MBEDTLS_OID_PKCS1 "\x01" /**< rsaEncryption OBJECT IDENTIFIER ::= { pkcs-1 1 } */ +#define MBEDTLS_OID_PKCS1_MD2 MBEDTLS_OID_PKCS1 "\x02" /**< md2WithRSAEncryption ::= { pkcs-1 2 } */ +#define MBEDTLS_OID_PKCS1_MD4 MBEDTLS_OID_PKCS1 "\x03" /**< md4WithRSAEncryption ::= { pkcs-1 3 } */ +#define MBEDTLS_OID_PKCS1_MD5 MBEDTLS_OID_PKCS1 "\x04" /**< md5WithRSAEncryption ::= { pkcs-1 4 } */ +#define MBEDTLS_OID_PKCS1_SHA1 MBEDTLS_OID_PKCS1 "\x05" /**< sha1WithRSAEncryption ::= { pkcs-1 5 } */ +#define MBEDTLS_OID_PKCS1_SHA224 MBEDTLS_OID_PKCS1 "\x0e" /**< sha224WithRSAEncryption ::= { pkcs-1 14 } */ +#define MBEDTLS_OID_PKCS1_SHA256 MBEDTLS_OID_PKCS1 "\x0b" /**< sha256WithRSAEncryption ::= { pkcs-1 11 } */ +#define MBEDTLS_OID_PKCS1_SHA384 MBEDTLS_OID_PKCS1 "\x0c" /**< sha384WithRSAEncryption ::= { pkcs-1 12 } */ +#define MBEDTLS_OID_PKCS1_SHA512 MBEDTLS_OID_PKCS1 "\x0d" /**< sha512WithRSAEncryption ::= { pkcs-1 13 } */ + +#define MBEDTLS_OID_RSA_SHA_OBS "\x2B\x0E\x03\x02\x1D" + +#define MBEDTLS_OID_PKCS9_EMAIL MBEDTLS_OID_PKCS9 "\x01" /**< emailAddress AttributeType ::= { pkcs-9 1 } */ + +/* RFC 4055 */ +#define MBEDTLS_OID_RSASSA_PSS MBEDTLS_OID_PKCS1 "\x0a" /**< id-RSASSA-PSS ::= { pkcs-1 10 } */ +#define MBEDTLS_OID_MGF1 MBEDTLS_OID_PKCS1 "\x08" /**< id-mgf1 ::= { pkcs-1 8 } */ + +/* + * Digest algorithms + */ +#define MBEDTLS_OID_DIGEST_ALG_MD2 MBEDTLS_OID_RSA_COMPANY "\x02\x02" /**< id-mbedtls_md2 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 2 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD4 MBEDTLS_OID_RSA_COMPANY "\x02\x04" /**< id-mbedtls_md4 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_MD5 MBEDTLS_OID_RSA_COMPANY "\x02\x05" /**< id-mbedtls_md5 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 5 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA1 MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_SHA1 /**< id-mbedtls_sha1 OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 26 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA224 MBEDTLS_OID_NIST_ALG "\x02\x04" /**< id-sha224 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 4 } */ +#define MBEDTLS_OID_DIGEST_ALG_SHA256 MBEDTLS_OID_NIST_ALG "\x02\x01" /**< id-mbedtls_sha256 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 1 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA384 MBEDTLS_OID_NIST_ALG "\x02\x02" /**< id-sha384 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 2 } */ + +#define MBEDTLS_OID_DIGEST_ALG_SHA512 MBEDTLS_OID_NIST_ALG "\x02\x03" /**< id-mbedtls_sha512 OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistalgorithm(4) hashalgs(2) 3 } */ + +#define MBEDTLS_OID_HMAC_SHA1 MBEDTLS_OID_RSA_COMPANY "\x02\x07" /**< id-hmacWithSHA1 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 7 } */ + +#define MBEDTLS_OID_HMAC_SHA224 MBEDTLS_OID_RSA_COMPANY "\x02\x08" /**< id-hmacWithSHA224 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 8 } */ + +#define MBEDTLS_OID_HMAC_SHA256 MBEDTLS_OID_RSA_COMPANY "\x02\x09" /**< id-hmacWithSHA256 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 9 } */ + +#define MBEDTLS_OID_HMAC_SHA384 MBEDTLS_OID_RSA_COMPANY "\x02\x0A" /**< id-hmacWithSHA384 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 10 } */ + +#define MBEDTLS_OID_HMAC_SHA512 MBEDTLS_OID_RSA_COMPANY "\x02\x0B" /**< id-hmacWithSHA512 OBJECT IDENTIFIER ::= { iso(1) member-body(2) us(840) rsadsi(113549) digestAlgorithm(2) 11 } */ + +/* + * Encryption algorithms + */ +#define MBEDTLS_OID_DES_CBC MBEDTLS_OID_ISO_IDENTIFIED_ORG MBEDTLS_OID_OIW_SECSIG_ALG "\x07" /**< desCBC OBJECT IDENTIFIER ::= { iso(1) identified-organization(3) oiw(14) secsig(3) algorithms(2) 7 } */ +#define MBEDTLS_OID_DES_EDE3_CBC MBEDTLS_OID_RSA_COMPANY "\x03\x07" /**< des-ede3-cbc OBJECT IDENTIFIER ::= { iso(1) member-body(2) -- us(840) rsadsi(113549) encryptionAlgorithm(3) 7 } */ +#define MBEDTLS_OID_AES MBEDTLS_OID_NIST_ALG "\x01" /** aes OBJECT IDENTIFIER ::= { joint-iso-itu-t(2) country(16) us(840) organization(1) gov(101) csor(3) nistAlgorithm(4) 1 } */ + +/* + * Key Wrapping algorithms + */ +/* + * RFC 5649 + */ +#define MBEDTLS_OID_AES128_KW MBEDTLS_OID_AES "\x05" /** id-aes128-wrap OBJECT IDENTIFIER ::= { aes 5 } */ +#define MBEDTLS_OID_AES128_KWP MBEDTLS_OID_AES "\x08" /** id-aes128-wrap-pad OBJECT IDENTIFIER ::= { aes 8 } */ +#define MBEDTLS_OID_AES192_KW MBEDTLS_OID_AES "\x19" /** id-aes192-wrap OBJECT IDENTIFIER ::= { aes 25 } */ +#define MBEDTLS_OID_AES192_KWP MBEDTLS_OID_AES "\x1c" /** id-aes192-wrap-pad OBJECT IDENTIFIER ::= { aes 28 } */ +#define MBEDTLS_OID_AES256_KW MBEDTLS_OID_AES "\x2d" /** id-aes256-wrap OBJECT IDENTIFIER ::= { aes 45 } */ +#define MBEDTLS_OID_AES256_KWP MBEDTLS_OID_AES "\x30" /** id-aes256-wrap-pad OBJECT IDENTIFIER ::= { aes 48 } */ +/* + * PKCS#5 OIDs + */ +#define MBEDTLS_OID_PKCS5_PBKDF2 MBEDTLS_OID_PKCS5 "\x0c" /**< id-PBKDF2 OBJECT IDENTIFIER ::= {pkcs-5 12} */ +#define MBEDTLS_OID_PKCS5_PBES2 MBEDTLS_OID_PKCS5 "\x0d" /**< id-PBES2 OBJECT IDENTIFIER ::= {pkcs-5 13} */ +#define MBEDTLS_OID_PKCS5_PBMAC1 MBEDTLS_OID_PKCS5 "\x0e" /**< id-PBMAC1 OBJECT IDENTIFIER ::= {pkcs-5 14} */ + +/* + * PKCS#5 PBES1 algorithms + */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_DES_CBC MBEDTLS_OID_PKCS5 "\x01" /**< pbeWithMD2AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 1} */ +#define MBEDTLS_OID_PKCS5_PBE_MD2_RC2_CBC MBEDTLS_OID_PKCS5 "\x04" /**< pbeWithMD2AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 4} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_DES_CBC MBEDTLS_OID_PKCS5 "\x03" /**< pbeWithMD5AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 3} */ +#define MBEDTLS_OID_PKCS5_PBE_MD5_RC2_CBC MBEDTLS_OID_PKCS5 "\x06" /**< pbeWithMD5AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 6} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_DES_CBC MBEDTLS_OID_PKCS5 "\x0a" /**< pbeWithSHA1AndDES-CBC OBJECT IDENTIFIER ::= {pkcs-5 10} */ +#define MBEDTLS_OID_PKCS5_PBE_SHA1_RC2_CBC MBEDTLS_OID_PKCS5 "\x0b" /**< pbeWithSHA1AndRC2-CBC OBJECT IDENTIFIER ::= {pkcs-5 11} */ + +/* + * PKCS#8 OIDs + */ +#define MBEDTLS_OID_PKCS9_CSR_EXT_REQ MBEDTLS_OID_PKCS9 "\x0e" /**< extensionRequest OBJECT IDENTIFIER ::= {pkcs-9 14} */ + +/* + * PKCS#12 PBE OIDs + */ +#define MBEDTLS_OID_PKCS12_PBE MBEDTLS_OID_PKCS12 "\x01" /**< pkcs-12PbeIds OBJECT IDENTIFIER ::= {pkcs-12 1} */ + +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128 MBEDTLS_OID_PKCS12_PBE "\x01" /**< pbeWithSHAAnd128BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 1} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_40 MBEDTLS_OID_PKCS12_PBE "\x02" /**< pbeWithSHAAnd40BitRC4 OBJECT IDENTIFIER ::= {pkcs-12PbeIds 2} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES3_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x03" /**< pbeWithSHAAnd3-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 3} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_DES2_EDE_CBC MBEDTLS_OID_PKCS12_PBE "\x04" /**< pbeWithSHAAnd2-KeyTripleDES-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 4} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_128_CBC MBEDTLS_OID_PKCS12_PBE "\x05" /**< pbeWithSHAAnd128BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 5} */ +#define MBEDTLS_OID_PKCS12_PBE_SHA1_RC2_40_CBC MBEDTLS_OID_PKCS12_PBE "\x06" /**< pbeWithSHAAnd40BitRC2-CBC OBJECT IDENTIFIER ::= {pkcs-12PbeIds 6} */ + +/* + * EC key algorithms from RFC 5480 + */ + +/* id-ecPublicKey OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) keyType(2) 1 } */ +#define MBEDTLS_OID_EC_ALG_UNRESTRICTED MBEDTLS_OID_ANSI_X9_62 "\x02\01" + +/* id-ecDH OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) + * schemes(1) ecdh(12) } */ +#define MBEDTLS_OID_EC_ALG_ECDH MBEDTLS_OID_CERTICOM "\x01\x0c" + +/* + * ECParameters namedCurve identifiers, from RFC 5480, RFC 5639, and SEC2 + */ + +/* secp192r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 1 } */ +#define MBEDTLS_OID_EC_GRP_SECP192R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x01" + +/* secp224r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 33 } */ +#define MBEDTLS_OID_EC_GRP_SECP224R1 MBEDTLS_OID_CERTICOM "\x00\x21" + +/* secp256r1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) curves(3) prime(1) 7 } */ +#define MBEDTLS_OID_EC_GRP_SECP256R1 MBEDTLS_OID_ANSI_X9_62 "\x03\x01\x07" + +/* secp384r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 34 } */ +#define MBEDTLS_OID_EC_GRP_SECP384R1 MBEDTLS_OID_CERTICOM "\x00\x22" + +/* secp521r1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 35 } */ +#define MBEDTLS_OID_EC_GRP_SECP521R1 MBEDTLS_OID_CERTICOM "\x00\x23" + +/* secp192k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 31 } */ +#define MBEDTLS_OID_EC_GRP_SECP192K1 MBEDTLS_OID_CERTICOM "\x00\x1f" + +/* secp224k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 32 } */ +#define MBEDTLS_OID_EC_GRP_SECP224K1 MBEDTLS_OID_CERTICOM "\x00\x20" + +/* secp256k1 OBJECT IDENTIFIER ::= { + * iso(1) identified-organization(3) certicom(132) curve(0) 10 } */ +#define MBEDTLS_OID_EC_GRP_SECP256K1 MBEDTLS_OID_CERTICOM "\x00\x0a" + +/* RFC 5639 4.1 + * ecStdCurvesAndGeneration OBJECT IDENTIFIER::= {iso(1) + * identified-organization(3) teletrust(36) algorithm(3) signature- + * algorithm(3) ecSign(2) 8} + * ellipticCurve OBJECT IDENTIFIER ::= {ecStdCurvesAndGeneration 1} + * versionOne OBJECT IDENTIFIER ::= {ellipticCurve 1} */ +#define MBEDTLS_OID_EC_BRAINPOOL_V1 MBEDTLS_OID_TELETRUST "\x03\x03\x02\x08\x01\x01" + +/* brainpoolP256r1 OBJECT IDENTIFIER ::= {versionOne 7} */ +#define MBEDTLS_OID_EC_GRP_BP256R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x07" + +/* brainpoolP384r1 OBJECT IDENTIFIER ::= {versionOne 11} */ +#define MBEDTLS_OID_EC_GRP_BP384R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0B" + +/* brainpoolP512r1 OBJECT IDENTIFIER ::= {versionOne 13} */ +#define MBEDTLS_OID_EC_GRP_BP512R1 MBEDTLS_OID_EC_BRAINPOOL_V1 "\x0D" + +/* + * SEC1 C.1 + * + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + * id-fieldType OBJECT IDENTIFIER ::= { ansi-X9-62 fieldType(1)} + */ +#define MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE MBEDTLS_OID_ANSI_X9_62 "\x01" +#define MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD MBEDTLS_OID_ANSI_X9_62_FIELD_TYPE "\x01" + +/* + * ECDSA signature identifiers, from RFC 5480 + */ +#define MBEDTLS_OID_ANSI_X9_62_SIG MBEDTLS_OID_ANSI_X9_62 "\x04" /* signatures(4) */ +#define MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 MBEDTLS_OID_ANSI_X9_62_SIG "\x03" /* ecdsa-with-SHA2(3) */ + +/* ecdsa-with-SHA1 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA1 MBEDTLS_OID_ANSI_X9_62_SIG "\x01" + +/* ecdsa-with-SHA224 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 1 } */ +#define MBEDTLS_OID_ECDSA_SHA224 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x01" + +/* ecdsa-with-SHA256 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 2 } */ +#define MBEDTLS_OID_ECDSA_SHA256 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x02" + +/* ecdsa-with-SHA384 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 3 } */ +#define MBEDTLS_OID_ECDSA_SHA384 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x03" + +/* ecdsa-with-SHA512 OBJECT IDENTIFIER ::= { + * iso(1) member-body(2) us(840) ansi-X9-62(10045) signatures(4) + * ecdsa-with-SHA2(3) 4 } */ +#define MBEDTLS_OID_ECDSA_SHA512 MBEDTLS_OID_ANSI_X9_62_SIG_SHA2 "\x04" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Base OID descriptor structure + */ +typedef struct mbedtls_oid_descriptor_t +{ + const char *asn1; /*!< OID ASN.1 representation */ + size_t asn1_len; /*!< length of asn1 */ + const char *name; /*!< official name (e.g. from RFC) */ + const char *description; /*!< human friendly description */ +} mbedtls_oid_descriptor_t; + +/** + * \brief Translate an ASN.1 OID into its numeric representation + * (e.g. "\x2A\x86\x48\x86\xF7\x0D" into "1.2.840.113549") + * + * \param buf buffer to put representation in + * \param size size of the buffer + * \param oid OID to translate + * + * \return Length of the string written (excluding final NULL) or + * MBEDTLS_ERR_OID_BUF_TOO_SMALL in case of error + */ +int mbedtls_oid_get_numeric_string( char *buf, size_t size, const mbedtls_asn1_buf *oid ); + +#if defined(MBEDTLS_X509_USE_C) || defined(MBEDTLS_X509_CREATE_C) +/** + * \brief Translate an X.509 extension OID into local values + * + * \param oid OID to use + * \param ext_type place to store the extension type + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_x509_ext_type( const mbedtls_asn1_buf *oid, int *ext_type ); +#endif + +/** + * \brief Translate an X.509 attribute type OID into the short name + * (e.g. the OID for an X520 Common Name into "CN") + * + * \param oid OID to use + * \param short_name place to store the string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_attr_short_name( const mbedtls_asn1_buf *oid, const char **short_name ); + +/** + * \brief Translate PublicKeyAlgorithm OID into pk_type + * + * \param oid OID to use + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pk_alg( const mbedtls_asn1_buf *oid, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate pk_type into PublicKeyAlgorithm OID + * + * \param pk_alg Public key type to look for + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_type_t pk_alg, + const char **oid, size_t *olen ); + +#if defined(MBEDTLS_ECP_C) +/** + * \brief Translate NamedCurve OID into an EC group identifier + * + * \param oid OID to use + * \param grp_id place to store group id + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_ec_grp( const mbedtls_asn1_buf *oid, mbedtls_ecp_group_id *grp_id ); + +/** + * \brief Translate EC group identifier into NamedCurve OID + * + * \param grp_id EC group identifier + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_ec_grp( mbedtls_ecp_group_id grp_id, + const char **oid, size_t *olen ); +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_MD_C) +/** + * \brief Translate SignatureAlgorithm OID into md_type and pk_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param pk_alg place to store public key algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg( const mbedtls_asn1_buf *oid, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg ); + +/** + * \brief Translate SignatureAlgorithm OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_sig_alg_desc( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type and pk_type into SignatureAlgorithm OID + * + * \param md_alg message digest algorithm + * \param pk_alg public key algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_sig_alg( mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const char **oid, size_t *olen ); + +/** + * \brief Translate hash algorithm OID into md_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg ); + +/** + * \brief Translate hmac algorithm OID into md_type + * + * \param oid OID to use + * \param md_hmac place to store message hmac algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_md_hmac( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_hmac ); +#endif /* MBEDTLS_MD_C */ + +/** + * \brief Translate Extended Key Usage OID into description + * + * \param oid OID to use + * \param desc place to store string pointer + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_extended_key_usage( const mbedtls_asn1_buf *oid, const char **desc ); + +/** + * \brief Translate md_type into hash algorithm OID + * + * \param md_alg message digest algorithm + * \param oid place to store ASN.1 OID string pointer + * \param olen length of the OID + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_oid_by_md( mbedtls_md_type_t md_alg, const char **oid, size_t *olen ); + +#if defined(MBEDTLS_CIPHER_C) +/** + * \brief Translate encryption algorithm OID into cipher_type + * + * \param oid OID to use + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_cipher_alg( const mbedtls_asn1_buf *oid, mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_CIPHER_C */ + +#if defined(MBEDTLS_PKCS12_C) +/** + * \brief Translate PKCS#12 PBE algorithm OID into md_type and + * cipher_type + * + * \param oid OID to use + * \param md_alg place to store message digest algorithm + * \param cipher_alg place to store cipher algorithm + * + * \return 0 if successful, or MBEDTLS_ERR_OID_NOT_FOUND + */ +int mbedtls_oid_get_pkcs12_pbe_alg( const mbedtls_asn1_buf *oid, mbedtls_md_type_t *md_alg, + mbedtls_cipher_type_t *cipher_alg ); +#endif /* MBEDTLS_PKCS12_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* oid.h */ diff --git a/common/mbedtls/pem.c b/common/mbedtls/pem.c new file mode 100644 index 000000000..3436d07ef --- /dev/null +++ b/common/mbedtls/pem.c @@ -0,0 +1,490 @@ +/* + * Privacy Enhanced Mail (PEM) decoding + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) || defined(MBEDTLS_PEM_WRITE_C) + +#include "mbedtls/pem.h" +#include "mbedtls/base64.h" +#include "mbedtls/des.h" +#include "mbedtls/aes.h" +#include "mbedtls/md5.h" +#include "mbedtls/cipher.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +void mbedtls_pem_init( mbedtls_pem_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_pem_context ) ); +} + +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) +/* + * Read a 16-byte hex string and convert it to binary + */ +static int pem_get_iv( const unsigned char *s, unsigned char *iv, + size_t iv_len ) +{ + size_t i, j, k; + + memset( iv, 0, iv_len ); + + for( i = 0; i < iv_len * 2; i++, s++ ) + { + if( *s >= '0' && *s <= '9' ) j = *s - '0'; else + if( *s >= 'A' && *s <= 'F' ) j = *s - '7'; else + if( *s >= 'a' && *s <= 'f' ) j = *s - 'W'; else + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + k = ( ( i & 1 ) != 0 ) ? j : j << 4; + + iv[i >> 1] = (unsigned char)( iv[i >> 1] | k ); + } + + return( 0 ); +} + +static int pem_pbkdf1( unsigned char *key, size_t keylen, + unsigned char *iv, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_md5_context md5_ctx; + unsigned char md5sum[16]; + size_t use_len; + int ret; + + mbedtls_md5_init( &md5_ctx ); + + /* + * key[ 0..15] = MD5(pwd || IV) + */ + if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 ) + goto exit; + + if( keylen <= 16 ) + { + memcpy( key, md5sum, keylen ); + goto exit; + } + + memcpy( key, md5sum, 16 ); + + /* + * key[16..23] = MD5(key[ 0..15] || pwd || IV]) + */ + if( ( ret = mbedtls_md5_starts_ret( &md5_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, md5sum, 16 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, pwd, pwdlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_update_ret( &md5_ctx, iv, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md5_finish_ret( &md5_ctx, md5sum ) ) != 0 ) + goto exit; + + use_len = 16; + if( keylen < 32 ) + use_len = keylen - 16; + + memcpy( key + 16, md5sum, use_len ); + +exit: + mbedtls_md5_free( &md5_ctx ); + mbedtls_platform_zeroize( md5sum, 16 ); + + return( ret ); +} + +#if defined(MBEDTLS_DES_C) +/* + * Decrypt with DES-CBC, using PBKDF1 for key derivation + */ +static int pem_des_decrypt( unsigned char des_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_des_context des_ctx; + unsigned char des_key[8]; + int ret; + + mbedtls_des_init( &des_ctx ); + + if( ( ret = pem_pbkdf1( des_key, 8, des_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_des_setkey_dec( &des_ctx, des_key ) ) != 0 ) + goto exit; + ret = mbedtls_des_crypt_cbc( &des_ctx, MBEDTLS_DES_DECRYPT, buflen, + des_iv, buf, buf ); + +exit: + mbedtls_des_free( &des_ctx ); + mbedtls_platform_zeroize( des_key, 8 ); + + return( ret ); +} + +/* + * Decrypt with 3DES-CBC, using PBKDF1 for key derivation + */ +static int pem_des3_decrypt( unsigned char des3_iv[8], + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_des3_context des3_ctx; + unsigned char des3_key[24]; + int ret; + + mbedtls_des3_init( &des3_ctx ); + + if( ( ret = pem_pbkdf1( des3_key, 24, des3_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_des3_set3key_dec( &des3_ctx, des3_key ) ) != 0 ) + goto exit; + ret = mbedtls_des3_crypt_cbc( &des3_ctx, MBEDTLS_DES_DECRYPT, buflen, + des3_iv, buf, buf ); + +exit: + mbedtls_des3_free( &des3_ctx ); + mbedtls_platform_zeroize( des3_key, 24 ); + + return( ret ); +} +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) +/* + * Decrypt with AES-XXX-CBC, using PBKDF1 for key derivation + */ +static int pem_aes_decrypt( unsigned char aes_iv[16], unsigned int keylen, + unsigned char *buf, size_t buflen, + const unsigned char *pwd, size_t pwdlen ) +{ + mbedtls_aes_context aes_ctx; + unsigned char aes_key[32]; + int ret; + + mbedtls_aes_init( &aes_ctx ); + + if( ( ret = pem_pbkdf1( aes_key, keylen, aes_iv, pwd, pwdlen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_aes_setkey_dec( &aes_ctx, aes_key, keylen * 8 ) ) != 0 ) + goto exit; + ret = mbedtls_aes_crypt_cbc( &aes_ctx, MBEDTLS_AES_DECRYPT, buflen, + aes_iv, buf, buf ); + +exit: + mbedtls_aes_free( &aes_ctx ); + mbedtls_platform_zeroize( aes_key, keylen ); + + return( ret ); +} +#endif /* MBEDTLS_AES_C */ + +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, const unsigned char *pwd, + size_t pwdlen, size_t *use_len ) +{ + int ret, enc; + size_t len; + unsigned char *buf; + const unsigned char *s1, *s2, *end; +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + unsigned char pem_iv[16]; + mbedtls_cipher_type_t enc_alg = MBEDTLS_CIPHER_NONE; +#else + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + + if( ctx == NULL ) + return( MBEDTLS_ERR_PEM_BAD_INPUT_DATA ); + + s1 = (unsigned char *) strstr( (const char *) data, header ); + + if( s1 == NULL ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s2 = (unsigned char *) strstr( (const char *) data, footer ); + + if( s2 == NULL || s2 <= s1 ) + return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + s1 += strlen( header ); + if( *s1 == ' ' ) s1++; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ); + + end = s2; + end += strlen( footer ); + if( *end == ' ' ) end++; + if( *end == '\r' ) end++; + if( *end == '\n' ) end++; + *use_len = end - data; + + enc = 0; + + if( s2 - s1 >= 22 && memcmp( s1, "Proc-Type: 4,ENCRYPTED", 22 ) == 0 ) + { +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + enc++; + + s1 += 22; + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); + + +#if defined(MBEDTLS_DES_C) + if( s2 - s1 >= 23 && memcmp( s1, "DEK-Info: DES-EDE3-CBC,", 23 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_EDE3_CBC; + + s1 += 23; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } + else if( s2 - s1 >= 18 && memcmp( s1, "DEK-Info: DES-CBC,", 18 ) == 0 ) + { + enc_alg = MBEDTLS_CIPHER_DES_CBC; + + s1 += 18; + if( s2 - s1 < 16 || pem_get_iv( s1, pem_iv, 8) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 16; + } +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( s2 - s1 >= 14 && memcmp( s1, "DEK-Info: AES-", 14 ) == 0 ) + { + if( s2 - s1 < 22 ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + else if( memcmp( s1, "DEK-Info: AES-128-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_128_CBC; + else if( memcmp( s1, "DEK-Info: AES-192-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_192_CBC; + else if( memcmp( s1, "DEK-Info: AES-256-CBC,", 22 ) == 0 ) + enc_alg = MBEDTLS_CIPHER_AES_256_CBC; + else + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + + s1 += 22; + if( s2 - s1 < 32 || pem_get_iv( s1, pem_iv, 16 ) != 0 ) + return( MBEDTLS_ERR_PEM_INVALID_ENC_IV ); + + s1 += 32; + } +#endif /* MBEDTLS_AES_C */ + + if( enc_alg == MBEDTLS_CIPHER_NONE ) + return( MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG ); + + if( *s1 == '\r' ) s1++; + if( *s1 == '\n' ) s1++; + else return( MBEDTLS_ERR_PEM_INVALID_DATA ); +#else + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } + + if( s1 >= s2 ) + return( MBEDTLS_ERR_PEM_INVALID_DATA ); + + ret = mbedtls_base64_decode( NULL, 0, &len, s1, s2 - s1 ); + + if( ret == MBEDTLS_ERR_BASE64_INVALID_CHARACTER ) + return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); + + if( ( buf = mbedtls_calloc( 1, len ) ) == NULL ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); + + if( ( ret = mbedtls_base64_decode( buf, len, &len, s1, s2 - s1 ) ) != 0 ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_INVALID_DATA + ret ); + } + + if( enc != 0 ) + { +#if defined(MBEDTLS_MD5_C) && defined(MBEDTLS_CIPHER_MODE_CBC) && \ + ( defined(MBEDTLS_DES_C) || defined(MBEDTLS_AES_C) ) + if( pwd == NULL ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ); + } + + ret = 0; + +#if defined(MBEDTLS_DES_C) + if( enc_alg == MBEDTLS_CIPHER_DES_EDE3_CBC ) + ret = pem_des3_decrypt( pem_iv, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_DES_CBC ) + ret = pem_des_decrypt( pem_iv, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_DES_C */ + +#if defined(MBEDTLS_AES_C) + if( enc_alg == MBEDTLS_CIPHER_AES_128_CBC ) + ret = pem_aes_decrypt( pem_iv, 16, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_192_CBC ) + ret = pem_aes_decrypt( pem_iv, 24, buf, len, pwd, pwdlen ); + else if( enc_alg == MBEDTLS_CIPHER_AES_256_CBC ) + ret = pem_aes_decrypt( pem_iv, 32, buf, len, pwd, pwdlen ); +#endif /* MBEDTLS_AES_C */ + + if( ret != 0 ) + { + mbedtls_free( buf ); + return( ret ); + } + + /* + * The result will be ASN.1 starting with a SEQUENCE tag, with 1 to 3 + * length bytes (allow 4 to be sure) in all known use cases. + * + * Use that as a heuristic to try to detect password mismatches. + */ + if( len <= 2 || buf[0] != 0x30 || buf[1] > 0x83 ) + { + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ); + } +#else + mbedtls_platform_zeroize( buf, len ); + mbedtls_free( buf ); + return( MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_MD5_C && MBEDTLS_CIPHER_MODE_CBC && + ( MBEDTLS_AES_C || MBEDTLS_DES_C ) */ + } + + ctx->buf = buf; + ctx->buflen = len; + + return( 0 ); +} + +void mbedtls_pem_free( mbedtls_pem_context *ctx ) +{ + if( ctx->buf != NULL ) + mbedtls_platform_zeroize( ctx->buf, ctx->buflen ); + mbedtls_free( ctx->buf ); + mbedtls_free( ctx->info ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pem_context ) ); +} +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ) +{ + int ret; + unsigned char *encode_buf = NULL, *c, *p = buf; + size_t len = 0, use_len, add_len = 0; + + mbedtls_base64_encode( NULL, 0, &use_len, der_data, der_len ); + add_len = strlen( header ) + strlen( footer ) + ( use_len / 64 ) + 1; + + if( use_len + add_len > buf_len ) + { + *olen = use_len + add_len; + return( MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL ); + } + + if( use_len != 0 && + ( ( encode_buf = mbedtls_calloc( 1, use_len ) ) == NULL ) ) + return( MBEDTLS_ERR_PEM_ALLOC_FAILED ); + + if( ( ret = mbedtls_base64_encode( encode_buf, use_len, &use_len, der_data, + der_len ) ) != 0 ) + { + mbedtls_free( encode_buf ); + return( ret ); + } + + memcpy( p, header, strlen( header ) ); + p += strlen( header ); + c = encode_buf; + + while( use_len ) + { + len = ( use_len > 64 ) ? 64 : use_len; + memcpy( p, c, len ); + use_len -= len; + p += len; + c += len; + *p++ = '\n'; + } + + memcpy( p, footer, strlen( footer ) ); + p += strlen( footer ); + + *p++ = '\0'; + *olen = p - buf; + + mbedtls_free( encode_buf ); + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PEM_PARSE_C || MBEDTLS_PEM_WRITE_C */ diff --git a/common/mbedtls/pem.h b/common/mbedtls/pem.h new file mode 100644 index 000000000..c0e5e025c --- /dev/null +++ b/common/mbedtls/pem.h @@ -0,0 +1,132 @@ +/** + * \file pem.h + * + * \brief Privacy Enhanced Mail (PEM) decoding + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PEM_H +#define MBEDTLS_PEM_H + +#include + +/** + * \name PEM Error codes + * These error codes are returned in case of errors reading the + * PEM data. + * \{ + */ +#define MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT -0x1080 /**< No PEM header or footer found. */ +#define MBEDTLS_ERR_PEM_INVALID_DATA -0x1100 /**< PEM string is not as expected. */ +#define MBEDTLS_ERR_PEM_ALLOC_FAILED -0x1180 /**< Failed to allocate memory. */ +#define MBEDTLS_ERR_PEM_INVALID_ENC_IV -0x1200 /**< RSA IV is not in hex-format. */ +#define MBEDTLS_ERR_PEM_UNKNOWN_ENC_ALG -0x1280 /**< Unsupported key encryption algorithm. */ +#define MBEDTLS_ERR_PEM_PASSWORD_REQUIRED -0x1300 /**< Private key password can't be empty. */ +#define MBEDTLS_ERR_PEM_PASSWORD_MISMATCH -0x1380 /**< Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PEM_FEATURE_UNAVAILABLE -0x1400 /**< Unavailable feature, e.g. hashing/encryption combination. */ +#define MBEDTLS_ERR_PEM_BAD_INPUT_DATA -0x1480 /**< Bad input parameters to function. */ +/* \} name */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) +/** + * \brief PEM context structure + */ +typedef struct mbedtls_pem_context +{ + unsigned char *buf; /*!< buffer for decoded data */ + size_t buflen; /*!< length of the buffer */ + unsigned char *info; /*!< buffer for extra header information */ +} +mbedtls_pem_context; + +/** + * \brief PEM context setup + * + * \param ctx context to be initialized + */ +void mbedtls_pem_init( mbedtls_pem_context *ctx ); + +/** + * \brief Read a buffer for PEM information and store the resulting + * data into the specified context buffers. + * + * \param ctx context to use + * \param header header string to seek and expect + * \param footer footer string to seek and expect + * \param data source data to look in (must be nul-terminated) + * \param pwd password for decryption (can be NULL) + * \param pwdlen length of password + * \param use_len destination for total length used (set after header is + * correctly read, so unless you get + * MBEDTLS_ERR_PEM_BAD_INPUT_DATA or + * MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT, use_len is + * the length to skip) + * + * \note Attempts to check password correctness by verifying if + * the decrypted text starts with an ASN.1 sequence of + * appropriate length + * + * \return 0 on success, or a specific PEM error code + */ +int mbedtls_pem_read_buffer( mbedtls_pem_context *ctx, const char *header, const char *footer, + const unsigned char *data, + const unsigned char *pwd, + size_t pwdlen, size_t *use_len ); + +/** + * \brief PEM context memory freeing + * + * \param ctx context to be freed + */ +void mbedtls_pem_free( mbedtls_pem_context *ctx ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a buffer of PEM information from a DER encoded + * buffer. + * + * \param header header string to write + * \param footer footer string to write + * \param der_data DER data to write + * \param der_len length of the DER data + * \param buf buffer to write to + * \param buf_len length of output buffer + * \param olen total length written / required (if buf_len is not enough) + * + * \return 0 on success, or a specific PEM or BASE64 error code. On + * MBEDTLS_ERR_BASE64_BUFFER_TOO_SMALL olen is the required + * size. + */ +int mbedtls_pem_write_buffer( const char *header, const char *footer, + const unsigned char *der_data, size_t der_len, + unsigned char *buf, size_t buf_len, size_t *olen ); +#endif /* MBEDTLS_PEM_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* pem.h */ diff --git a/common/mbedtls/pk.c b/common/mbedtls/pk.c new file mode 100644 index 000000000..784b66963 --- /dev/null +++ b/common/mbedtls/pk.c @@ -0,0 +1,381 @@ +/* + * Public Key abstraction layer + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk.h" +#include "mbedtls/pk_internal.h" + +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#include +#include + +/* + * Initialise a mbedtls_pk_context + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ) +{ + if( ctx == NULL ) + return; + + ctx->pk_info = NULL; + ctx->pk_ctx = NULL; +} + +/* + * Free (the components of) a mbedtls_pk_context + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return; + + ctx->pk_info->ctx_free_func( ctx->pk_ctx ); + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_pk_context ) ); +} + +/* + * Get pk_info structure from type + */ +const mbedtls_pk_info_t * mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ) +{ + switch( pk_type ) { +#if defined(MBEDTLS_RSA_C) + case MBEDTLS_PK_RSA: + return( &mbedtls_rsa_info ); +#endif +#if defined(MBEDTLS_ECP_C) + case MBEDTLS_PK_ECKEY: + return( &mbedtls_eckey_info ); + case MBEDTLS_PK_ECKEY_DH: + return( &mbedtls_eckeydh_info ); +#endif +#if defined(MBEDTLS_ECDSA_C) + case MBEDTLS_PK_ECDSA: + return( &mbedtls_ecdsa_info ); +#endif + /* MBEDTLS_PK_RSA_ALT omitted on purpose */ + default: + return( NULL ); + } +} + +/* + * Initialise context + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ) +{ + if( ctx == NULL || info == NULL || ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + return( 0 ); +} + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Initialize an RSA-alt context + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ) +{ + mbedtls_rsa_alt_context *rsa_alt; + const mbedtls_pk_info_t *info = &mbedtls_rsa_alt_info; + + if( ctx == NULL || ctx->pk_info != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ( ctx->pk_ctx = info->ctx_alloc_func() ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + ctx->pk_info = info; + + rsa_alt = (mbedtls_rsa_alt_context *) ctx->pk_ctx; + + rsa_alt->key = key; + rsa_alt->decrypt_func = decrypt_func; + rsa_alt->sign_func = sign_func; + rsa_alt->key_len_func = key_len_func; + + return( 0 ); +} +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/* + * Tell if a PK can do the operations of the given type + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ) +{ + /* null or NONE context can't do anything */ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->can_do( type ) ); +} + +/* + * Helper for mbedtls_pk_sign and mbedtls_pk_verify + */ +static inline int pk_hashlen_helper( mbedtls_md_type_t md_alg, size_t *hash_len ) +{ + const mbedtls_md_info_t *md_info; + + if( *hash_len != 0 ) + return( 0 ); + + if( ( md_info = mbedtls_md_info_from_type( md_alg ) ) == NULL ) + return( -1 ); + + *hash_len = mbedtls_md_get_size( md_info ); + return( 0 ); +} + +/* + * Verify a signature + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + if( ctx == NULL || ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->verify_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->verify_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len ) ); +} + +/* + * Verify a signature with options + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ! mbedtls_pk_can_do( ctx, type ) ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + if( type == MBEDTLS_PK_RSASSA_PSS ) + { +#if defined(MBEDTLS_RSA_C) && defined(MBEDTLS_PKCS1_V21) + int ret; + const mbedtls_pk_rsassa_pss_options *pss_opts; + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( options == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) options; + + if( sig_len < mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + ret = mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_pk_rsa( *ctx ), + NULL, NULL, MBEDTLS_RSA_PUBLIC, + md_alg, (unsigned int) hash_len, hash, + pss_opts->mgf1_hash_id, + pss_opts->expected_salt_len, + sig ); + if( ret != 0 ) + return( ret ); + + if( sig_len > mbedtls_pk_get_len( ctx ) ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +#else + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); +#endif /* MBEDTLS_RSA_C && MBEDTLS_PKCS1_V21 */ + } + + /* General case: no options */ + if( options != NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + return( mbedtls_pk_verify( ctx, md_alg, hash, hash_len, sig, sig_len ) ); +} + +/* + * Make a signature + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + if( ctx == NULL || ctx->pk_info == NULL || + pk_hashlen_helper( md_alg, &hash_len ) != 0 ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->sign_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->sign_func( ctx->pk_ctx, md_alg, hash, hash_len, + sig, sig_len, f_rng, p_rng ) ); +} + +/* + * Decrypt message + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->decrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->decrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Encrypt message + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->encrypt_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + return( ctx->pk_info->encrypt_func( ctx->pk_ctx, input, ilen, + output, olen, osize, f_rng, p_rng ) ); +} + +/* + * Check public-private key pair + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ) +{ + if( pub == NULL || pub->pk_info == NULL || + prv == NULL || prv->pk_info == NULL || + prv->pk_info->check_pair_func == NULL ) + { + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + } + + if( prv->pk_info->type == MBEDTLS_PK_RSA_ALT ) + { + if( pub->pk_info->type != MBEDTLS_PK_RSA ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + else + { + if( pub->pk_info != prv->pk_info ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + } + + return( prv->pk_info->check_pair_func( pub->pk_ctx, prv->pk_ctx ) ); +} + +/* + * Get key size in bits + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( 0 ); + + return( ctx->pk_info->get_bitlen( ctx->pk_ctx ) ); +} + +/* + * Export debug information + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); + + if( ctx->pk_info->debug_func == NULL ) + return( MBEDTLS_ERR_PK_TYPE_MISMATCH ); + + ctx->pk_info->debug_func( ctx->pk_ctx, items ); + return( 0 ); +} + +/* + * Access the PK type name + */ +const char *mbedtls_pk_get_name( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( "invalid PK" ); + + return( ctx->pk_info->name ); +} + +/* + * Access the PK type + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ) +{ + if( ctx == NULL || ctx->pk_info == NULL ) + return( MBEDTLS_PK_NONE ); + + return( ctx->pk_info->type ); +} + +#endif /* MBEDTLS_PK_C */ diff --git a/common/mbedtls/pk.h b/common/mbedtls/pk.h new file mode 100644 index 000000000..f75dc2f8d --- /dev/null +++ b/common/mbedtls/pk.h @@ -0,0 +1,620 @@ +/** + * \file pk.h + * + * \brief Public Key abstraction layer + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_PK_H +#define MBEDTLS_PK_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "md.h" + +#if defined(MBEDTLS_RSA_C) +#include "rsa.h" +#endif + +#if defined(MBEDTLS_ECP_C) +#include "ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "ecdsa.h" +#endif + +#if ( defined(__ARMCC_VERSION) || defined(_MSC_VER) ) && \ + !defined(inline) && !defined(__cplusplus) +#define inline __inline +#endif + +#define MBEDTLS_ERR_PK_ALLOC_FAILED -0x3F80 /**< Memory allocation failed. */ +#define MBEDTLS_ERR_PK_TYPE_MISMATCH -0x3F00 /**< Type mismatch, eg attempt to encrypt with an ECDSA key */ +#define MBEDTLS_ERR_PK_BAD_INPUT_DATA -0x3E80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PK_FILE_IO_ERROR -0x3E00 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_PK_KEY_INVALID_VERSION -0x3D80 /**< Unsupported key version */ +#define MBEDTLS_ERR_PK_KEY_INVALID_FORMAT -0x3D00 /**< Invalid key tag or value. */ +#define MBEDTLS_ERR_PK_UNKNOWN_PK_ALG -0x3C80 /**< Key algorithm is unsupported (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_PASSWORD_REQUIRED -0x3C00 /**< Private key password can't be empty. */ +#define MBEDTLS_ERR_PK_PASSWORD_MISMATCH -0x3B80 /**< Given private key password does not allow for correct decryption. */ +#define MBEDTLS_ERR_PK_INVALID_PUBKEY -0x3B00 /**< The pubkey tag or value is invalid (only RSA and EC are supported). */ +#define MBEDTLS_ERR_PK_INVALID_ALG -0x3A80 /**< The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE -0x3A00 /**< Elliptic curve is unsupported (only NIST curves are supported). */ +#define MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE -0x3980 /**< Unavailable feature, e.g. RSA disabled for RSA key. */ +#define MBEDTLS_ERR_PK_SIG_LEN_MISMATCH -0x3900 /**< The buffer contains a valid signature followed by more data. */ +#define MBEDTLS_ERR_PK_HW_ACCEL_FAILED -0x3880 /**< PK hardware accelerator failed. */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Public key types + */ +typedef enum { + MBEDTLS_PK_NONE=0, + MBEDTLS_PK_RSA, + MBEDTLS_PK_ECKEY, + MBEDTLS_PK_ECKEY_DH, + MBEDTLS_PK_ECDSA, + MBEDTLS_PK_RSA_ALT, + MBEDTLS_PK_RSASSA_PSS, +} mbedtls_pk_type_t; + +/** + * \brief Options for RSASSA-PSS signature verification. + * See \c mbedtls_rsa_rsassa_pss_verify_ext() + */ +typedef struct mbedtls_pk_rsassa_pss_options +{ + mbedtls_md_type_t mgf1_hash_id; + int expected_salt_len; + +} mbedtls_pk_rsassa_pss_options; + +/** + * \brief Types for interfacing with the debug module + */ +typedef enum +{ + MBEDTLS_PK_DEBUG_NONE = 0, + MBEDTLS_PK_DEBUG_MPI, + MBEDTLS_PK_DEBUG_ECP, +} mbedtls_pk_debug_type; + +/** + * \brief Item to send to the debug module + */ +typedef struct mbedtls_pk_debug_item +{ + mbedtls_pk_debug_type type; + const char *name; + void *value; +} mbedtls_pk_debug_item; + +/** Maximum number of item send for debugging, plus 1 */ +#define MBEDTLS_PK_DEBUG_MAX_ITEMS 3 + +/** + * \brief Public key information and operations + */ +typedef struct mbedtls_pk_info_t mbedtls_pk_info_t; + +/** + * \brief Public key container + */ +typedef struct mbedtls_pk_context +{ + const mbedtls_pk_info_t * pk_info; /**< Public key informations */ + void * pk_ctx; /**< Underlying public key context */ +} mbedtls_pk_context; + +#if defined(MBEDTLS_RSA_C) +/** + * Quick access to an RSA context inside a PK context. + * + * \warning You must make sure the PK context actually holds an RSA context + * before using this function! + */ +static inline mbedtls_rsa_context *mbedtls_pk_rsa( const mbedtls_pk_context pk ) +{ + return( (mbedtls_rsa_context *) (pk).pk_ctx ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/** + * Quick access to an EC context inside a PK context. + * + * \warning You must make sure the PK context actually holds an EC context + * before using this function! + */ +static inline mbedtls_ecp_keypair *mbedtls_pk_ec( const mbedtls_pk_context pk ) +{ + return( (mbedtls_ecp_keypair *) (pk).pk_ctx ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Types for RSA-alt abstraction + */ +typedef int (*mbedtls_pk_rsa_alt_decrypt_func)( void *ctx, int mode, size_t *olen, + const unsigned char *input, unsigned char *output, + size_t output_max_len ); +typedef int (*mbedtls_pk_rsa_alt_sign_func)( void *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng, + int mode, mbedtls_md_type_t md_alg, unsigned int hashlen, + const unsigned char *hash, unsigned char *sig ); +typedef size_t (*mbedtls_pk_rsa_alt_key_len_func)( void *ctx ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Return information associated with the given PK type + * + * \param pk_type PK type to search for. + * + * \return The PK info associated with the type or NULL if not found. + */ +const mbedtls_pk_info_t *mbedtls_pk_info_from_type( mbedtls_pk_type_t pk_type ); + +/** + * \brief Initialize a mbedtls_pk_context (as NONE) + */ +void mbedtls_pk_init( mbedtls_pk_context *ctx ); + +/** + * \brief Free a mbedtls_pk_context + */ +void mbedtls_pk_free( mbedtls_pk_context *ctx ); + +/** + * \brief Initialize a PK context with the information given + * and allocates the type-specific PK subcontext. + * + * \param ctx Context to initialize. Must be empty (type NONE). + * \param info Information to use + * + * \return 0 on success, + * MBEDTLS_ERR_PK_BAD_INPUT_DATA on invalid input, + * MBEDTLS_ERR_PK_ALLOC_FAILED on allocation failure. + * + * \note For contexts holding an RSA-alt key, use + * \c mbedtls_pk_setup_rsa_alt() instead. + */ +int mbedtls_pk_setup( mbedtls_pk_context *ctx, const mbedtls_pk_info_t *info ); + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/** + * \brief Initialize an RSA-alt context + * + * \param ctx Context to initialize. Must be empty (type NONE). + * \param key RSA key pointer + * \param decrypt_func Decryption function + * \param sign_func Signing function + * \param key_len_func Function returning key length in bytes + * + * \return 0 on success, or MBEDTLS_ERR_PK_BAD_INPUT_DATA if the + * context wasn't already initialized as RSA_ALT. + * + * \note This function replaces \c mbedtls_pk_setup() for RSA-alt. + */ +int mbedtls_pk_setup_rsa_alt( mbedtls_pk_context *ctx, void * key, + mbedtls_pk_rsa_alt_decrypt_func decrypt_func, + mbedtls_pk_rsa_alt_sign_func sign_func, + mbedtls_pk_rsa_alt_key_len_func key_len_func ); +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +/** + * \brief Get the size in bits of the underlying key + * + * \param ctx Context to use + * + * \return Key size in bits, or 0 on error + */ +size_t mbedtls_pk_get_bitlen( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the length in bytes of the underlying key + * \param ctx Context to use + * + * \return Key length in bytes, or 0 on error + */ +static inline size_t mbedtls_pk_get_len( const mbedtls_pk_context *ctx ) +{ + return( ( mbedtls_pk_get_bitlen( ctx ) + 7 ) / 8 ); +} + +/** + * \brief Tell if a context can do the operation given by type + * + * \param ctx Context to test + * \param type Target type + * + * \return 0 if context can't do the operations, + * 1 otherwise. + */ +int mbedtls_pk_can_do( const mbedtls_pk_context *ctx, mbedtls_pk_type_t type ); + +/** + * \brief Verify signature (including padding if relevant). + * + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, + * or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * Use \c mbedtls_pk_verify_ext( MBEDTLS_PK_RSASSA_PSS, ... ) + * to verify RSASSA_PSS signatures. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + */ +int mbedtls_pk_verify( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Verify signature, with options. + * (Includes verification of the padding depending on type.) + * + * \param type Signature type (inc. possible padding type) to verify + * \param options Pointer to type-specific options, or NULL + * \param ctx PK context to use + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Signature to verify + * \param sig_len Signature length + * + * \return 0 on success (signature is valid), + * #MBEDTLS_ERR_PK_TYPE_MISMATCH if the PK context can't be + * used for this type of signatures, + * #MBEDTLS_ERR_PK_SIG_LEN_MISMATCH if there is a valid + * signature in sig but its length is less than \p siglen, + * or a specific error code. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note md_alg may be MBEDTLS_MD_NONE, only if hash_len != 0 + * + * \note If type is MBEDTLS_PK_RSASSA_PSS, then options must point + * to a mbedtls_pk_rsassa_pss_options structure, + * otherwise it must be NULL. + */ +int mbedtls_pk_verify_ext( mbedtls_pk_type_t type, const void *options, + mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +/** + * \brief Make signature, including padding if relevant. + * + * \param ctx PK context to use - must hold a private key + * \param md_alg Hash algorithm used (see notes) + * \param hash Hash of the message to sign + * \param hash_len Hash length or 0 (see notes) + * \param sig Place to write the signature + * \param sig_len Number of bytes written + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \return 0 on success, or a specific error code. + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * There is no interface in the PK module to make RSASSA-PSS + * signatures yet. + * + * \note If hash_len is 0, then the length associated with md_alg + * is used instead, or an error returned if it is invalid. + * + * \note For RSA, md_alg may be MBEDTLS_MD_NONE if hash_len != 0. + * For ECDSA, md_alg may never be MBEDTLS_MD_NONE. + */ +int mbedtls_pk_sign( mbedtls_pk_context *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Decrypt message (including padding if relevant). + * + * \param ctx PK context to use - must hold a private key + * \param input Input to decrypt + * \param ilen Input size + * \param output Decrypted output + * \param olen Decrypted message length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_decrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Encrypt message (including padding if relevant). + * + * \param ctx PK context to use + * \param input Message to encrypt + * \param ilen Message size + * \param output Encrypted output + * \param olen Encrypted output length + * \param osize Size of the output buffer + * \param f_rng RNG function + * \param p_rng RNG parameter + * + * \note For RSA keys, the default padding type is PKCS#1 v1.5. + * + * \return 0 on success, or a specific error code. + */ +int mbedtls_pk_encrypt( mbedtls_pk_context *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +/** + * \brief Check if a public-private pair of keys matches. + * + * \param pub Context holding a public key. + * \param prv Context holding a private (and public) key. + * + * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA + */ +int mbedtls_pk_check_pair( const mbedtls_pk_context *pub, const mbedtls_pk_context *prv ); + +/** + * \brief Export debug information + * + * \param ctx Context to use + * \param items Place to write debug items + * + * \return 0 on success or MBEDTLS_ERR_PK_BAD_INPUT_DATA + */ +int mbedtls_pk_debug( const mbedtls_pk_context *ctx, mbedtls_pk_debug_item *items ); + +/** + * \brief Access the type name + * + * \param ctx Context to use + * + * \return Type name on success, or "invalid PK" + */ +const char * mbedtls_pk_get_name( const mbedtls_pk_context *ctx ); + +/** + * \brief Get the key type + * + * \param ctx Context to use + * + * \return Type on success, or MBEDTLS_PK_NONE + */ +mbedtls_pk_type_t mbedtls_pk_get_type( const mbedtls_pk_context *ctx ); + +#if defined(MBEDTLS_PK_PARSE_C) +/** \ingroup pk_module */ +/** + * \brief Parse a private key in PEM or DER format + * + * \param ctx key to be initialized + * \param key input buffer + * \param keylen size of the buffer + * (including the terminating null byte for PEM data) + * \param pwd password for decryption (optional) + * \param pwdlen size of the password + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ); + +/** \ingroup pk_module */ +/** + * \brief Parse a public key in PEM or DER format + * + * \param ctx key to be initialized + * \param key input buffer + * \param keylen size of the buffer + * (including the terminating null byte for PEM data) + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ); + +#if defined(MBEDTLS_FS_IO) +/** \ingroup pk_module */ +/** + * \brief Load and parse a private key + * + * \param ctx key to be initialized + * \param path filename to read the private key from + * \param password password to decrypt the file (can be NULL) + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If you need a + * specific key type, check the result with mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *password ); + +/** \ingroup pk_module */ +/** + * \brief Load and parse a public key + * + * \param ctx key to be initialized + * \param path filename to read the public key from + * + * \note On entry, ctx must be empty, either freshly initialised + * with mbedtls_pk_init() or reset with mbedtls_pk_free(). If + * you need a specific key type, check the result with + * mbedtls_pk_can_do(). + * + * \note The key is also checked for correctness. + * + * \return 0 if successful, or a specific PK or PEM error code + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ); +#endif /* MBEDTLS_FS_IO */ +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a private key to a PKCS#1 or SEC1 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx private to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_key_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a public key to a SubjectPublicKeyInfo DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx public key to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return length of data written if successful, or a specific + * error code + */ +int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a public key to a PEM string + * + * \param ctx public key to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); + +/** + * \brief Write a private key to a PKCS#1 or SEC1 PEM string + * + * \param ctx private to write away + * \param buf buffer to write to + * \param size size of the buffer + * + * \return 0 if successful, or a specific error code + */ +int mbedtls_pk_write_key_pem( mbedtls_pk_context *ctx, unsigned char *buf, size_t size ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * WARNING: Low-level functions. You probably do not want to use these unless + * you are certain you do ;) + */ + +#if defined(MBEDTLS_PK_PARSE_C) +/** + * \brief Parse a SubjectPublicKeyInfo DER structure + * + * \param p the position in the ASN.1 data + * \param end end of the buffer + * \param pk the key to fill + * + * \return 0 if successful, or a specific PK error code + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ); +#endif /* MBEDTLS_PK_PARSE_C */ + +#if defined(MBEDTLS_PK_WRITE_C) +/** + * \brief Write a subjectPublicKey to ASN.1 data + * Note: function works backwards in data buffer + * + * \param p reference to current position pointer + * \param start start of the buffer (for bounds-checking) + * \param key public key to write away + * + * \return the length written or a negative error code + */ +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ); +#endif /* MBEDTLS_PK_WRITE_C */ + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +#if defined(MBEDTLS_FS_IO) +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PK_H */ diff --git a/common/mbedtls/pk_internal.h b/common/mbedtls/pk_internal.h new file mode 100644 index 000000000..685cd5757 --- /dev/null +++ b/common/mbedtls/pk_internal.h @@ -0,0 +1,117 @@ +/** + * \file pk_internal.h + * + * \brief Public Key abstraction layer: wrapper functions + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#ifndef MBEDTLS_PK_WRAP_H +#define MBEDTLS_PK_WRAP_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "pk.h" + +struct mbedtls_pk_info_t +{ + /** Public key type */ + mbedtls_pk_type_t type; + + /** Type name */ + const char *name; + + /** Get key size in bits */ + size_t (*get_bitlen)( const void * ); + + /** Tell if the context implements this type (e.g. ECKEY can do ECDSA) */ + int (*can_do)( mbedtls_pk_type_t type ); + + /** Verify signature */ + int (*verify_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + + /** Make signature */ + int (*sign_func)( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Decrypt message */ + int (*decrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Encrypt message */ + int (*encrypt_func)( void *ctx, const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + + /** Check public-private key pair */ + int (*check_pair_func)( const void *pub, const void *prv ); + + /** Allocate a new context */ + void * (*ctx_alloc_func)( void ); + + /** Free the given context */ + void (*ctx_free_func)( void *ctx ); + + /** Interface with the debug module */ + void (*debug_func)( const void *ctx, mbedtls_pk_debug_item *items ); + +}; +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* Container for RSA-alt */ +typedef struct +{ + void *key; + mbedtls_pk_rsa_alt_decrypt_func decrypt_func; + mbedtls_pk_rsa_alt_sign_func sign_func; + mbedtls_pk_rsa_alt_key_len_func key_len_func; +} mbedtls_rsa_alt_context; +#endif + +#if defined(MBEDTLS_RSA_C) +extern const mbedtls_pk_info_t mbedtls_rsa_info; +#endif + +#if defined(MBEDTLS_ECP_C) +extern const mbedtls_pk_info_t mbedtls_eckey_info; +extern const mbedtls_pk_info_t mbedtls_eckeydh_info; +#endif + +#if defined(MBEDTLS_ECDSA_C) +extern const mbedtls_pk_info_t mbedtls_ecdsa_info; +#endif + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +extern const mbedtls_pk_info_t mbedtls_rsa_alt_info; +#endif + +#endif /* MBEDTLS_PK_WRAP_H */ diff --git a/common/mbedtls/pk_wrap.c b/common/mbedtls/pk_wrap.c new file mode 100644 index 000000000..7c4275ec5 --- /dev/null +++ b/common/mbedtls/pk_wrap.c @@ -0,0 +1,525 @@ +/* + * Public Key abstraction layer: wrapper functions + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PK_C) +#include "mbedtls/pk_internal.h" + +/* Even if RSA not activated, for the sake of RSA-alt */ +#include "mbedtls/rsa.h" + +#include + +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif + +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +#include "mbedtls/platform_util.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#include +#include + +#if defined(MBEDTLS_RSA_C) +static int rsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA || + type == MBEDTLS_PK_RSASSA_PSS ); +} + +static size_t rsa_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_context * rsa = (const mbedtls_rsa_context *) ctx; + return( 8 * mbedtls_rsa_get_len( rsa ) ); +} + +static int rsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + size_t rsa_len = mbedtls_rsa_get_len( rsa ); + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + if( sig_len < rsa_len ) + return( MBEDTLS_ERR_RSA_VERIFY_FAILED ); + + if( ( ret = mbedtls_rsa_pkcs1_verify( rsa, NULL, NULL, + MBEDTLS_RSA_PUBLIC, md_alg, + (unsigned int) hash_len, hash, sig ) ) != 0 ) + return( ret ); + + /* The buffer contains a valid signature followed by extra data. + * We have a special error code for that so that so that callers can + * use mbedtls_pk_verify() to check "Does the buffer start with a + * valid signature?" and not just "Does the buffer contain a valid + * signature?". */ + if( sig_len > rsa_len ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( 0 ); +} + +static int rsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( md_alg == MBEDTLS_MD_NONE && UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = mbedtls_rsa_get_len( rsa ); + + return( mbedtls_rsa_pkcs1_sign( rsa, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + + if( ilen != mbedtls_rsa_get_len( rsa ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( mbedtls_rsa_pkcs1_decrypt( rsa, f_rng, p_rng, + MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); +} + +static int rsa_encrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_context * rsa = (mbedtls_rsa_context *) ctx; + *olen = mbedtls_rsa_get_len( rsa ); + + if( *olen > osize ) + return( MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE ); + + return( mbedtls_rsa_pkcs1_encrypt( rsa, f_rng, p_rng, MBEDTLS_RSA_PUBLIC, + ilen, input, output ) ); +} + +static int rsa_check_pair_wrap( const void *pub, const void *prv ) +{ + return( mbedtls_rsa_check_pub_priv( (const mbedtls_rsa_context *) pub, + (const mbedtls_rsa_context *) prv ) ); +} + +static void *rsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_context ) ); + + if( ctx != NULL ) + mbedtls_rsa_init( (mbedtls_rsa_context *) ctx, 0, 0 ); + + return( ctx ); +} + +static void rsa_free_wrap( void *ctx ) +{ + mbedtls_rsa_free( (mbedtls_rsa_context *) ctx ); + mbedtls_free( ctx ); +} + +static void rsa_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.N"; + items->value = &( ((mbedtls_rsa_context *) ctx)->N ); + + items++; + + items->type = MBEDTLS_PK_DEBUG_MPI; + items->name = "rsa.E"; + items->value = &( ((mbedtls_rsa_context *) ctx)->E ); +} + +const mbedtls_pk_info_t mbedtls_rsa_info = { + MBEDTLS_PK_RSA, + "RSA", + rsa_get_bitlen, + rsa_can_do, + rsa_verify_wrap, + rsa_sign_wrap, + rsa_decrypt_wrap, + rsa_encrypt_wrap, + rsa_check_pair_wrap, + rsa_alloc_wrap, + rsa_free_wrap, + rsa_debug, +}; +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Generic EC key + */ +static int eckey_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH || + type == MBEDTLS_PK_ECDSA ); +} + +static size_t eckey_get_bitlen( const void *ctx ) +{ + return( ((mbedtls_ecp_keypair *) ctx)->grp.pbits ); +} + +#if defined(MBEDTLS_ECDSA_C) +/* Forward declarations */ +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ); + +static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ); + +static int eckey_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_verify_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +static int eckey_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret; + mbedtls_ecdsa_context ecdsa; + + mbedtls_ecdsa_init( &ecdsa ); + + if( ( ret = mbedtls_ecdsa_from_keypair( &ecdsa, ctx ) ) == 0 ) + ret = ecdsa_sign_wrap( &ecdsa, md_alg, hash, hash_len, sig, sig_len, + f_rng, p_rng ); + + mbedtls_ecdsa_free( &ecdsa ); + + return( ret ); +} + +#endif /* MBEDTLS_ECDSA_C */ + +static int eckey_check_pair( const void *pub, const void *prv ) +{ + return( mbedtls_ecp_check_pub_priv( (const mbedtls_ecp_keypair *) pub, + (const mbedtls_ecp_keypair *) prv ) ); +} + +static void *eckey_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecp_keypair ) ); + + if( ctx != NULL ) + mbedtls_ecp_keypair_init( ctx ); + + return( ctx ); +} + +static void eckey_free_wrap( void *ctx ) +{ + mbedtls_ecp_keypair_free( (mbedtls_ecp_keypair *) ctx ); + mbedtls_free( ctx ); +} + +static void eckey_debug( const void *ctx, mbedtls_pk_debug_item *items ) +{ + items->type = MBEDTLS_PK_DEBUG_ECP; + items->name = "eckey.Q"; + items->value = &( ((mbedtls_ecp_keypair *) ctx)->Q ); +} + +const mbedtls_pk_info_t mbedtls_eckey_info = { + MBEDTLS_PK_ECKEY, + "EC", + eckey_get_bitlen, + eckey_can_do, +#if defined(MBEDTLS_ECDSA_C) + eckey_verify_wrap, + eckey_sign_wrap, +#else + NULL, + NULL, +#endif + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, + eckey_free_wrap, + eckey_debug, +}; + +/* + * EC key restricted to ECDH + */ +static int eckeydh_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECKEY || + type == MBEDTLS_PK_ECKEY_DH ); +} + +const mbedtls_pk_info_t mbedtls_eckeydh_info = { + MBEDTLS_PK_ECKEY_DH, + "EC_DH", + eckey_get_bitlen, /* Same underlying key structure */ + eckeydh_can_do, + NULL, + NULL, + NULL, + NULL, + eckey_check_pair, + eckey_alloc_wrap, /* Same underlying key structure */ + eckey_free_wrap, /* Same underlying key structure */ + eckey_debug, /* Same underlying key structure */ +}; +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_ECDSA_C) +static int ecdsa_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_ECDSA ); +} + +static int ecdsa_verify_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + const unsigned char *sig, size_t sig_len ) +{ + int ret; + ((void) md_alg); + + ret = mbedtls_ecdsa_read_signature( (mbedtls_ecdsa_context *) ctx, + hash, hash_len, sig, sig_len ); + + if( ret == MBEDTLS_ERR_ECP_SIG_LEN_MISMATCH ) + return( MBEDTLS_ERR_PK_SIG_LEN_MISMATCH ); + + return( ret ); +} + +static int ecdsa_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + return( mbedtls_ecdsa_write_signature( (mbedtls_ecdsa_context *) ctx, + md_alg, hash, hash_len, sig, sig_len, f_rng, p_rng ) ); +} + +static void *ecdsa_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_ecdsa_context ) ); + + if( ctx != NULL ) + mbedtls_ecdsa_init( (mbedtls_ecdsa_context *) ctx ); + + return( ctx ); +} + +static void ecdsa_free_wrap( void *ctx ) +{ + mbedtls_ecdsa_free( (mbedtls_ecdsa_context *) ctx ); + mbedtls_free( ctx ); +} + +const mbedtls_pk_info_t mbedtls_ecdsa_info = { + MBEDTLS_PK_ECDSA, + "ECDSA", + eckey_get_bitlen, /* Compatible key structures */ + ecdsa_can_do, + ecdsa_verify_wrap, + ecdsa_sign_wrap, + NULL, + NULL, + eckey_check_pair, /* Compatible key structures */ + ecdsa_alloc_wrap, + ecdsa_free_wrap, + eckey_debug, /* Compatible key structures */ +}; +#endif /* MBEDTLS_ECDSA_C */ + +#if defined(MBEDTLS_PK_RSA_ALT_SUPPORT) +/* + * Support for alternative RSA-private implementations + */ + +static int rsa_alt_can_do( mbedtls_pk_type_t type ) +{ + return( type == MBEDTLS_PK_RSA ); +} + +static size_t rsa_alt_get_bitlen( const void *ctx ) +{ + const mbedtls_rsa_alt_context *rsa_alt = (const mbedtls_rsa_alt_context *) ctx; + + return( 8 * rsa_alt->key_len_func( rsa_alt->key ) ); +} + +static int rsa_alt_sign_wrap( void *ctx, mbedtls_md_type_t md_alg, + const unsigned char *hash, size_t hash_len, + unsigned char *sig, size_t *sig_len, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + +#if SIZE_MAX > UINT_MAX + if( UINT_MAX < hash_len ) + return( MBEDTLS_ERR_PK_BAD_INPUT_DATA ); +#endif /* SIZE_MAX > UINT_MAX */ + + *sig_len = rsa_alt->key_len_func( rsa_alt->key ); + + return( rsa_alt->sign_func( rsa_alt->key, f_rng, p_rng, MBEDTLS_RSA_PRIVATE, + md_alg, (unsigned int) hash_len, hash, sig ) ); +} + +static int rsa_alt_decrypt_wrap( void *ctx, + const unsigned char *input, size_t ilen, + unsigned char *output, size_t *olen, size_t osize, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + mbedtls_rsa_alt_context *rsa_alt = (mbedtls_rsa_alt_context *) ctx; + + ((void) f_rng); + ((void) p_rng); + + if( ilen != rsa_alt->key_len_func( rsa_alt->key ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + return( rsa_alt->decrypt_func( rsa_alt->key, + MBEDTLS_RSA_PRIVATE, olen, input, output, osize ) ); +} + +#if defined(MBEDTLS_RSA_C) +static int rsa_alt_check_pair( const void *pub, const void *prv ) +{ + unsigned char sig[MBEDTLS_MPI_MAX_SIZE]; + unsigned char hash[32]; + size_t sig_len = 0; + int ret; + + if( rsa_alt_get_bitlen( prv ) != rsa_get_bitlen( pub ) ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + memset( hash, 0x2a, sizeof( hash ) ); + + if( ( ret = rsa_alt_sign_wrap( (void *) prv, MBEDTLS_MD_NONE, + hash, sizeof( hash ), + sig, &sig_len, NULL, NULL ) ) != 0 ) + { + return( ret ); + } + + if( rsa_verify_wrap( (void *) pub, MBEDTLS_MD_NONE, + hash, sizeof( hash ), sig, sig_len ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +static void *rsa_alt_alloc_wrap( void ) +{ + void *ctx = mbedtls_calloc( 1, sizeof( mbedtls_rsa_alt_context ) ); + + if( ctx != NULL ) + memset( ctx, 0, sizeof( mbedtls_rsa_alt_context ) ); + + return( ctx ); +} + +static void rsa_alt_free_wrap( void *ctx ) +{ + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_rsa_alt_context ) ); + mbedtls_free( ctx ); +} + +const mbedtls_pk_info_t mbedtls_rsa_alt_info = { + MBEDTLS_PK_RSA_ALT, + "RSA-alt", + rsa_alt_get_bitlen, + rsa_alt_can_do, + NULL, + rsa_alt_sign_wrap, + rsa_alt_decrypt_wrap, + NULL, +#if defined(MBEDTLS_RSA_C) + rsa_alt_check_pair, +#else + NULL, +#endif + rsa_alt_alloc_wrap, + rsa_alt_free_wrap, + NULL, +}; + +#endif /* MBEDTLS_PK_RSA_ALT_SUPPORT */ + +#endif /* MBEDTLS_PK_C */ diff --git a/common/mbedtls/pkcs12.c b/common/mbedtls/pkcs12.c new file mode 100644 index 000000000..3d93bfe93 --- /dev/null +++ b/common/mbedtls/pkcs12.c @@ -0,0 +1,363 @@ +/* + * PKCS#12 Personal Information Exchange Syntax + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The PKCS #12 Personal Information Exchange Syntax Standard v1.1 + * + * http://www.rsa.com/rsalabs/pkcs/files/h11301-wp-pkcs-12v1-1-personal-information-exchange-syntax.pdf + * ftp://ftp.rsasecurity.com/pub/pkcs/pkcs-12/pkcs-12v1-1.asn + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PKCS12_C) + +#include "mbedtls/pkcs12.h" +#include "mbedtls/asn1.h" +#include "mbedtls/cipher.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_ARC4_C) +#include "mbedtls/arc4.h" +#endif + +#if defined(MBEDTLS_DES_C) +#include "mbedtls/des.h" +#endif + +static int pkcs12_parse_pbe_params( mbedtls_asn1_buf *params, + mbedtls_asn1_buf *salt, int *iterations ) +{ + int ret; + unsigned char **p = ¶ms->p; + const unsigned char *end = params->p + params->len; + + /* + * pkcs-12PbeParams ::= SEQUENCE { + * salt OCTET STRING, + * iterations INTEGER + * } + * + */ + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); + + salt->p = *p; + *p += salt->len; + + if( ( ret = mbedtls_asn1_get_int( p, end, iterations ) ) != 0 ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +#define PKCS12_MAX_PWDLEN 128 + +static int pkcs12_pbe_derive_key_iv( mbedtls_asn1_buf *pbe_params, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + unsigned char *key, size_t keylen, + unsigned char *iv, size_t ivlen ) +{ + int ret, iterations = 0; + mbedtls_asn1_buf salt; + size_t i; + unsigned char unipwd[PKCS12_MAX_PWDLEN * 2 + 2]; + + if( pwdlen > PKCS12_MAX_PWDLEN ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + memset( &salt, 0, sizeof(mbedtls_asn1_buf) ); + memset( &unipwd, 0, sizeof(unipwd) ); + + if( ( ret = pkcs12_parse_pbe_params( pbe_params, &salt, + &iterations ) ) != 0 ) + return( ret ); + + for( i = 0; i < pwdlen; i++ ) + unipwd[i * 2 + 1] = pwd[i]; + + if( ( ret = mbedtls_pkcs12_derivation( key, keylen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + MBEDTLS_PKCS12_DERIVE_KEY, iterations ) ) != 0 ) + { + return( ret ); + } + + if( iv == NULL || ivlen == 0 ) + return( 0 ); + + if( ( ret = mbedtls_pkcs12_derivation( iv, ivlen, unipwd, pwdlen * 2 + 2, + salt.p, salt.len, md_type, + MBEDTLS_PKCS12_DERIVE_IV, iterations ) ) != 0 ) + { + return( ret ); + } + return( 0 ); +} + +#undef PKCS12_MAX_PWDLEN + +int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t len, + unsigned char *output ) +{ +#if !defined(MBEDTLS_ARC4_C) + ((void) pbe_params); + ((void) mode); + ((void) pwd); + ((void) pwdlen); + ((void) data); + ((void) len); + ((void) output); + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); +#else + int ret; + unsigned char key[16]; + mbedtls_arc4_context ctx; + ((void) mode); + + mbedtls_arc4_init( &ctx ); + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, MBEDTLS_MD_SHA1, + pwd, pwdlen, + key, 16, NULL, 0 ) ) != 0 ) + { + return( ret ); + } + + mbedtls_arc4_setup( &ctx, key, 16 ); + if( ( ret = mbedtls_arc4_crypt( &ctx, len, data, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_arc4_free( &ctx ); + + return( ret ); +#endif /* MBEDTLS_ARC4_C */ +} + +int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t len, + unsigned char *output ) +{ + int ret, keylen = 0; + unsigned char key[32]; + unsigned char iv[16]; + const mbedtls_cipher_info_t *cipher_info; + mbedtls_cipher_context_t cipher_ctx; + size_t olen = 0; + + cipher_info = mbedtls_cipher_info_from_type( cipher_type ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + keylen = cipher_info->key_bitlen / 8; + + if( ( ret = pkcs12_pbe_derive_key_iv( pbe_params, md_type, pwd, pwdlen, + key, keylen, + iv, cipher_info->iv_size ) ) != 0 ) + { + return( ret ); + } + + mbedtls_cipher_init( &cipher_ctx ); + + if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_set_iv( &cipher_ctx, iv, cipher_info->iv_size ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_reset( &cipher_ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_update( &cipher_ctx, data, len, + output, &olen ) ) != 0 ) + { + goto exit; + } + + if( ( ret = mbedtls_cipher_finish( &cipher_ctx, output + olen, &olen ) ) != 0 ) + ret = MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH; + +exit: + mbedtls_platform_zeroize( key, sizeof( key ) ); + mbedtls_platform_zeroize( iv, sizeof( iv ) ); + mbedtls_cipher_free( &cipher_ctx ); + + return( ret ); +} + +static void pkcs12_fill_buffer( unsigned char *data, size_t data_len, + const unsigned char *filler, size_t fill_len ) +{ + unsigned char *p = data; + size_t use_len; + + while( data_len > 0 ) + { + use_len = ( data_len > fill_len ) ? fill_len : data_len; + memcpy( p, filler, use_len ); + p += use_len; + data_len -= use_len; + } +} + +int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + mbedtls_md_type_t md_type, int id, int iterations ) +{ + int ret; + unsigned int j; + + unsigned char diversifier[128]; + unsigned char salt_block[128], pwd_block[128], hash_block[128]; + unsigned char hash_output[MBEDTLS_MD_MAX_SIZE]; + unsigned char *p; + unsigned char c; + + size_t hlen, use_len, v, i; + + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + // This version only allows max of 64 bytes of password or salt + if( datalen > 128 || pwdlen > 64 || saltlen > 64 ) + return( MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( md_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE ); + + mbedtls_md_init( &md_ctx ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + return( ret ); + hlen = mbedtls_md_get_size( md_info ); + + if( hlen <= 32 ) + v = 64; + else + v = 128; + + memset( diversifier, (unsigned char) id, v ); + + pkcs12_fill_buffer( salt_block, v, salt, saltlen ); + pkcs12_fill_buffer( pwd_block, v, pwd, pwdlen ); + + p = data; + while( datalen > 0 ) + { + // Calculate hash( diversifier || salt_block || pwd_block ) + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, diversifier, v ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, salt_block, v ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_update( &md_ctx, pwd_block, v ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_md_finish( &md_ctx, hash_output ) ) != 0 ) + goto exit; + + // Perform remaining ( iterations - 1 ) recursive hash calculations + for( i = 1; i < (size_t) iterations; i++ ) + { + if( ( ret = mbedtls_md( md_info, hash_output, hlen, hash_output ) ) != 0 ) + goto exit; + } + + use_len = ( datalen > hlen ) ? hlen : datalen; + memcpy( p, hash_output, use_len ); + datalen -= use_len; + p += use_len; + + if( datalen == 0 ) + break; + + // Concatenating copies of hash_output into hash_block (B) + pkcs12_fill_buffer( hash_block, v, hash_output, hlen ); + + // B += 1 + for( i = v; i > 0; i-- ) + if( ++hash_block[i - 1] != 0 ) + break; + + // salt_block += B + c = 0; + for( i = v; i > 0; i-- ) + { + j = salt_block[i - 1] + hash_block[i - 1] + c; + c = (unsigned char) (j >> 8); + salt_block[i - 1] = j & 0xFF; + } + + // pwd_block += B + c = 0; + for( i = v; i > 0; i-- ) + { + j = pwd_block[i - 1] + hash_block[i - 1] + c; + c = (unsigned char) (j >> 8); + pwd_block[i - 1] = j & 0xFF; + } + } + + ret = 0; + +exit: + mbedtls_platform_zeroize( salt_block, sizeof( salt_block ) ); + mbedtls_platform_zeroize( pwd_block, sizeof( pwd_block ) ); + mbedtls_platform_zeroize( hash_block, sizeof( hash_block ) ); + mbedtls_platform_zeroize( hash_output, sizeof( hash_output ) ); + + mbedtls_md_free( &md_ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_PKCS12_C */ diff --git a/common/mbedtls/pkcs12.h b/common/mbedtls/pkcs12.h new file mode 100644 index 000000000..f2230fa9b --- /dev/null +++ b/common/mbedtls/pkcs12.h @@ -0,0 +1,122 @@ +/** + * \file pkcs12.h + * + * \brief PKCS#12 Personal Information Exchange Syntax + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PKCS12_H +#define MBEDTLS_PKCS12_H + +#include "md.h" +#include "cipher.h" +#include "asn1.h" + +#include + +#define MBEDTLS_ERR_PKCS12_BAD_INPUT_DATA -0x1F80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS12_FEATURE_UNAVAILABLE -0x1F00 /**< Feature not available, e.g. unsupported encryption scheme. */ +#define MBEDTLS_ERR_PKCS12_PBE_INVALID_FORMAT -0x1E80 /**< PBE ASN.1 data not as expected. */ +#define MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH -0x1E00 /**< Given private key password does not allow for correct decryption. */ + +#define MBEDTLS_PKCS12_DERIVE_KEY 1 /**< encryption/decryption key */ +#define MBEDTLS_PKCS12_DERIVE_IV 2 /**< initialization vector */ +#define MBEDTLS_PKCS12_DERIVE_MAC_KEY 3 /**< integrity / MAC key */ + +#define MBEDTLS_PKCS12_PBE_DECRYPT 0 +#define MBEDTLS_PKCS12_PBE_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for pbeWithSHAAnd128BitRC4 + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe_sha1_rc4_128( mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +/** + * \brief PKCS12 Password Based function (encryption / decryption) + * for cipher-based and mbedtls_md-based PBE's + * + * \param pbe_params an ASN1 buffer containing the pkcs-12PbeParams structure + * \param mode either MBEDTLS_PKCS12_PBE_ENCRYPT or MBEDTLS_PKCS12_PBE_DECRYPT + * \param cipher_type the cipher used + * \param md_type the mbedtls_md used + * \param pwd the password used (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param input the input data + * \param len data length + * \param output the output buffer + * + * \return 0 if successful, or a MBEDTLS_ERR_XXX code + */ +int mbedtls_pkcs12_pbe( mbedtls_asn1_buf *pbe_params, int mode, + mbedtls_cipher_type_t cipher_type, mbedtls_md_type_t md_type, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *input, size_t len, + unsigned char *output ); + +/** + * \brief The PKCS#12 derivation function uses a password and a salt + * to produce pseudo-random bits for a particular "purpose". + * + * Depending on the given id, this function can produce an + * encryption/decryption key, an nitialization vector or an + * integrity key. + * + * \param data buffer to store the derived data in + * \param datalen length to fill + * \param pwd password to use (may be NULL if no password is used) + * \param pwdlen length of the password (may be 0) + * \param salt salt buffer to use + * \param saltlen length of the salt + * \param mbedtls_md mbedtls_md type to use during the derivation + * \param id id that describes the purpose (can be MBEDTLS_PKCS12_DERIVE_KEY, + * MBEDTLS_PKCS12_DERIVE_IV or MBEDTLS_PKCS12_DERIVE_MAC_KEY) + * \param iterations number of iterations + * + * \return 0 if successful, or a MD, BIGNUM type error. + */ +int mbedtls_pkcs12_derivation( unsigned char *data, size_t datalen, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *salt, size_t saltlen, + mbedtls_md_type_t mbedtls_md, int id, int iterations ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs12.h */ diff --git a/common/mbedtls/pkcs5.c b/common/mbedtls/pkcs5.c new file mode 100644 index 000000000..e62d663d2 --- /dev/null +++ b/common/mbedtls/pkcs5.c @@ -0,0 +1,428 @@ +/** + * \file pkcs5.c + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * PKCS#5 includes PBKDF2 and more + * + * http://tools.ietf.org/html/rfc2898 (Specification) + * http://tools.ietf.org/html/rfc6070 (Test vectors) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PKCS5_C) + +#include "mbedtls/pkcs5.h" + +#if defined(MBEDTLS_ASN1_PARSE_C) +#include "mbedtls/asn1.h" +#include "mbedtls/cipher.h" +#include "mbedtls/oid.h" +#endif /* MBEDTLS_ASN1_PARSE_C */ + +#include + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if !defined(MBEDTLS_ASN1_PARSE_C) +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ) +{ + ((void) pbe_params); + ((void) mode); + ((void) pwd); + ((void) pwdlen); + ((void) data); + ((void) datalen); + ((void) output); + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); +} +#else +static int pkcs5_parse_pbkdf2_params( const mbedtls_asn1_buf *params, + mbedtls_asn1_buf *salt, int *iterations, + int *keylen, mbedtls_md_type_t *md_type ) +{ + int ret; + mbedtls_asn1_buf prf_alg_oid; + unsigned char *p = params->p; + const unsigned char *end = params->p + params->len; + + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + /* + * PBKDF2-params ::= SEQUENCE { + * salt OCTET STRING, + * iterationCount INTEGER, + * keyLength INTEGER OPTIONAL + * prf AlgorithmIdentifier DEFAULT algid-hmacWithSHA1 + * } + * + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &salt->len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + salt->p = p; + p += salt->len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, iterations ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_int( &p, end, keylen ) ) != 0 ) + { + if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + } + + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_alg_null( &p, end, &prf_alg_oid ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + if( mbedtls_oid_get_md_hmac( &prf_alg_oid, md_type ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( p != end ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ) +{ + int ret, iterations = 0, keylen = 0; + unsigned char *p, *end; + mbedtls_asn1_buf kdf_alg_oid, enc_scheme_oid, kdf_alg_params, enc_scheme_params; + mbedtls_asn1_buf salt; + mbedtls_md_type_t md_type = MBEDTLS_MD_SHA1; + unsigned char key[32], iv[32]; + size_t olen = 0; + const mbedtls_md_info_t *md_info; + const mbedtls_cipher_info_t *cipher_info; + mbedtls_md_context_t md_ctx; + mbedtls_cipher_type_t cipher_alg; + mbedtls_cipher_context_t cipher_ctx; + + p = pbe_params->p; + end = p + pbe_params->len; + + /* + * PBES2-params ::= SEQUENCE { + * keyDerivationFunc AlgorithmIdentifier {{PBES2-KDFs}}, + * encryptionScheme AlgorithmIdentifier {{PBES2-Encs}} + * } + */ + if( pbe_params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &kdf_alg_oid, &kdf_alg_params ) ) != 0 ) + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + + // Only PBKDF2 supported at the moment + // + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBKDF2, &kdf_alg_oid ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = pkcs5_parse_pbkdf2_params( &kdf_alg_params, + &salt, &iterations, &keylen, + &md_type ) ) != 0 ) + { + return( ret ); + } + + md_info = mbedtls_md_info_from_type( md_type ); + if( md_info == NULL ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &enc_scheme_oid, + &enc_scheme_params ) ) != 0 ) + { + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT + ret ); + } + + if( mbedtls_oid_get_cipher_alg( &enc_scheme_oid, &cipher_alg ) != 0 ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + cipher_info = mbedtls_cipher_info_from_type( cipher_alg ); + if( cipher_info == NULL ) + return( MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE ); + + /* + * The value of keylen from pkcs5_parse_pbkdf2_params() is ignored + * since it is optional and we don't know if it was set or not + */ + keylen = cipher_info->key_bitlen / 8; + + if( enc_scheme_params.tag != MBEDTLS_ASN1_OCTET_STRING || + enc_scheme_params.len != cipher_info->iv_size ) + { + return( MBEDTLS_ERR_PKCS5_INVALID_FORMAT ); + } + + mbedtls_md_init( &md_ctx ); + mbedtls_cipher_init( &cipher_ctx ); + + memcpy( iv, enc_scheme_params.p, enc_scheme_params.len ); + + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 1 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_pkcs5_pbkdf2_hmac( &md_ctx, pwd, pwdlen, salt.p, salt.len, + iterations, keylen, key ) ) != 0 ) + { + goto exit; + } + + if( ( ret = mbedtls_cipher_setup( &cipher_ctx, cipher_info ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_setkey( &cipher_ctx, key, 8 * keylen, (mbedtls_operation_t) mode ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_cipher_crypt( &cipher_ctx, iv, enc_scheme_params.len, + data, datalen, output, &olen ) ) != 0 ) + ret = MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH; + +exit: + mbedtls_md_free( &md_ctx ); + mbedtls_cipher_free( &cipher_ctx ); + + return( ret ); +} +#endif /* MBEDTLS_ASN1_PARSE_C */ + +int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ) +{ + int ret, j; + unsigned int i; + unsigned char md1[MBEDTLS_MD_MAX_SIZE]; + unsigned char work[MBEDTLS_MD_MAX_SIZE]; + unsigned char md_size = mbedtls_md_get_size( ctx->md_info ); + size_t use_len; + unsigned char *out_p = output; + unsigned char counter[4]; + + memset( counter, 0, 4 ); + counter[3] = 1; + +#if UINT_MAX > 0xFFFFFFFF + if( iteration_count > 0xFFFFFFFF ) + return( MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA ); +#endif + + while( key_length ) + { + // U1 ends up in work + // + if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_update( ctx, salt, slen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_update( ctx, counter, 4 ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_finish( ctx, work ) ) != 0 ) + return( ret ); + + memcpy( md1, work, md_size ); + + for( i = 1; i < iteration_count; i++ ) + { + // U2 ends up in md1 + // + if( ( ret = mbedtls_md_hmac_starts( ctx, password, plen ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_update( ctx, md1, md_size ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_md_hmac_finish( ctx, md1 ) ) != 0 ) + return( ret ); + + // U1 xor U2 + // + for( j = 0; j < md_size; j++ ) + work[j] ^= md1[j]; + } + + use_len = ( key_length < md_size ) ? key_length : md_size; + memcpy( out_p, work, use_len ); + + key_length -= (uint32_t) use_len; + out_p += use_len; + + for( i = 4; i > 0; i-- ) + if( ++counter[i - 1] != 0 ) + break; + } + + return( 0 ); +} + +#if defined(MBEDTLS_SELF_TEST) + +#if !defined(MBEDTLS_SHA1_C) +int mbedtls_pkcs5_self_test( int verbose ) +{ + if( verbose != 0 ) + mbedtls_printf( " PBKDF2 (SHA1): skipped\n\n" ); + + return( 0 ); +} +#else + +#define MAX_TESTS 6 + +static const size_t plen[MAX_TESTS] = + { 8, 8, 8, 24, 9 }; + +static const unsigned char password[MAX_TESTS][32] = +{ + "password", + "password", + "password", + "passwordPASSWORDpassword", + "pass\0word", +}; + +static const size_t slen[MAX_TESTS] = + { 4, 4, 4, 36, 5 }; + +static const unsigned char salt[MAX_TESTS][40] = +{ + "salt", + "salt", + "salt", + "saltSALTsaltSALTsaltSALTsaltSALTsalt", + "sa\0lt", +}; + +static const uint32_t it_cnt[MAX_TESTS] = + { 1, 2, 4096, 4096, 4096 }; + +static const uint32_t key_len[MAX_TESTS] = + { 20, 20, 20, 25, 16 }; + +static const unsigned char result_key[MAX_TESTS][32] = +{ + { 0x0c, 0x60, 0xc8, 0x0f, 0x96, 0x1f, 0x0e, 0x71, + 0xf3, 0xa9, 0xb5, 0x24, 0xaf, 0x60, 0x12, 0x06, + 0x2f, 0xe0, 0x37, 0xa6 }, + { 0xea, 0x6c, 0x01, 0x4d, 0xc7, 0x2d, 0x6f, 0x8c, + 0xcd, 0x1e, 0xd9, 0x2a, 0xce, 0x1d, 0x41, 0xf0, + 0xd8, 0xde, 0x89, 0x57 }, + { 0x4b, 0x00, 0x79, 0x01, 0xb7, 0x65, 0x48, 0x9a, + 0xbe, 0xad, 0x49, 0xd9, 0x26, 0xf7, 0x21, 0xd0, + 0x65, 0xa4, 0x29, 0xc1 }, + { 0x3d, 0x2e, 0xec, 0x4f, 0xe4, 0x1c, 0x84, 0x9b, + 0x80, 0xc8, 0xd8, 0x36, 0x62, 0xc0, 0xe4, 0x4a, + 0x8b, 0x29, 0x1a, 0x96, 0x4c, 0xf2, 0xf0, 0x70, + 0x38 }, + { 0x56, 0xfa, 0x6a, 0xa7, 0x55, 0x48, 0x09, 0x9d, + 0xcc, 0x37, 0xd7, 0xf0, 0x34, 0x25, 0xe0, 0xc3 }, +}; + +int mbedtls_pkcs5_self_test( int verbose ) +{ + mbedtls_md_context_t sha1_ctx; + const mbedtls_md_info_t *info_sha1; + int ret, i; + unsigned char key[64]; + + mbedtls_md_init( &sha1_ctx ); + + info_sha1 = mbedtls_md_info_from_type( MBEDTLS_MD_SHA1 ); + if( info_sha1 == NULL ) + { + ret = 1; + goto exit; + } + + if( ( ret = mbedtls_md_setup( &sha1_ctx, info_sha1, 1 ) ) != 0 ) + { + ret = 1; + goto exit; + } + + for( i = 0; i < MAX_TESTS; i++ ) + { + if( verbose != 0 ) + mbedtls_printf( " PBKDF2 (SHA1) #%d: ", i ); + + ret = mbedtls_pkcs5_pbkdf2_hmac( &sha1_ctx, password[i], plen[i], salt[i], + slen[i], it_cnt[i], key_len[i], key ); + if( ret != 0 || + memcmp( result_key[i], key, key_len[i] ) != 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_md_free( &sha1_ctx ); + + return( ret ); +} +#endif /* MBEDTLS_SHA1_C */ + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_PKCS5_C */ diff --git a/common/mbedtls/pkcs5.h b/common/mbedtls/pkcs5.h new file mode 100644 index 000000000..7b6acf580 --- /dev/null +++ b/common/mbedtls/pkcs5.h @@ -0,0 +1,97 @@ +/** + * \file pkcs5.h + * + * \brief PKCS#5 functions + * + * \author Mathias Olsson + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PKCS5_H +#define MBEDTLS_PKCS5_H + +#include "asn1.h" +#include "md.h" + +#include +#include + +#define MBEDTLS_ERR_PKCS5_BAD_INPUT_DATA -0x2f80 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_PKCS5_INVALID_FORMAT -0x2f00 /**< Unexpected ASN.1 data. */ +#define MBEDTLS_ERR_PKCS5_FEATURE_UNAVAILABLE -0x2e80 /**< Requested encryption or digest alg not available. */ +#define MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH -0x2e00 /**< Given private key password does not allow for correct decryption. */ + +#define MBEDTLS_PKCS5_DECRYPT 0 +#define MBEDTLS_PKCS5_ENCRYPT 1 + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief PKCS#5 PBES2 function + * + * \param pbe_params the ASN.1 algorithm parameters + * \param mode either MBEDTLS_PKCS5_DECRYPT or MBEDTLS_PKCS5_ENCRYPT + * \param pwd password to use when generating key + * \param pwdlen length of password + * \param data data to process + * \param datalen length of data + * \param output output buffer + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbes2( const mbedtls_asn1_buf *pbe_params, int mode, + const unsigned char *pwd, size_t pwdlen, + const unsigned char *data, size_t datalen, + unsigned char *output ); + +/** + * \brief PKCS#5 PBKDF2 using HMAC + * + * \param ctx Generic HMAC context + * \param password Password to use when generating key + * \param plen Length of password + * \param salt Salt to use when generating key + * \param slen Length of salt + * \param iteration_count Iteration count + * \param key_length Length of generated key in bytes + * \param output Generated key. Must be at least as big as key_length + * + * \returns 0 on success, or a MBEDTLS_ERR_XXX code if verification fails. + */ +int mbedtls_pkcs5_pbkdf2_hmac( mbedtls_md_context_t *ctx, const unsigned char *password, + size_t plen, const unsigned char *salt, size_t slen, + unsigned int iteration_count, + uint32_t key_length, unsigned char *output ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_pkcs5_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* pkcs5.h */ diff --git a/common/mbedtls/pkparse.c b/common/mbedtls/pkparse.c new file mode 100644 index 000000000..a687076b0 --- /dev/null +++ b/common/mbedtls/pkparse.c @@ -0,0 +1,1449 @@ +/* + * Public Key layer for parsing key files and structures + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PK_PARSE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif +#if defined(MBEDTLS_PKCS5_C) +#include "mbedtls/pkcs5.h" +#endif +#if defined(MBEDTLS_PKCS12_C) +#include "mbedtls/pkcs12.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_FS_IO) +/* + * Load all data from a file into a given buffer. + * + * The file is expected to contain either PEM or DER encoded data. + * A terminating null byte is always appended. It is included in the announced + * length only if the data looks like it is PEM encoded. + */ +int mbedtls_pk_load_file( const char *path, unsigned char **buf, size_t *n ) +{ + FILE *f; + long size; + + if( ( f = fopen( path, "rb" ) ) == NULL ) + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + + fseek( f, 0, SEEK_END ); + if( ( size = ftell( f ) ) == -1 ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + fseek( f, 0, SEEK_SET ); + + *n = (size_t) size; + + if( *n + 1 == 0 || + ( *buf = mbedtls_calloc( 1, *n + 1 ) ) == NULL ) + { + fclose( f ); + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + } + + if( fread( *buf, 1, *n, f ) != *n ) + { + fclose( f ); + + mbedtls_platform_zeroize( *buf, *n ); + mbedtls_free( *buf ); + + return( MBEDTLS_ERR_PK_FILE_IO_ERROR ); + } + + fclose( f ); + + (*buf)[*n] = '\0'; + + if( strstr( (const char *) *buf, "-----BEGIN " ) != NULL ) + ++*n; + + return( 0 ); +} + +/* + * Load and parse a private key + */ +int mbedtls_pk_parse_keyfile( mbedtls_pk_context *ctx, + const char *path, const char *pwd ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + if( pwd == NULL ) + ret = mbedtls_pk_parse_key( ctx, buf, n, NULL, 0 ); + else + ret = mbedtls_pk_parse_key( ctx, buf, n, + (const unsigned char *) pwd, strlen( pwd ) ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} + +/* + * Load and parse a public key + */ +int mbedtls_pk_parse_public_keyfile( mbedtls_pk_context *ctx, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_pk_parse_public_key( ctx, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +#if defined(MBEDTLS_ECP_C) +/* Minimally parse an ECParameters buffer to and mbedtls_asn1_buf + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + * } + */ +static int pk_get_ecparams( unsigned char **p, const unsigned char *end, + mbedtls_asn1_buf *params ) +{ + int ret; + + if ( end - *p < 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + /* Tag may be either OID or SEQUENCE */ + params->tag = **p; + if( params->tag != MBEDTLS_ASN1_OID +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + && params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) +#endif + ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } + + if( ( ret = mbedtls_asn1_get_tag( p, end, ¶ms->len, params->tag ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + params->p = *p; + *p += params->len; + + if( *p != end ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and (mostly) fill the group with it. + * WARNING: the resulting group should only be used with + * pk_group_id_from_specified(), since its base point may not be set correctly + * if it was encoded compressed. + * + * SpecifiedECDomain ::= SEQUENCE { + * version SpecifiedECDomainVersion(ecdpVer1 | ecdpVer2 | ecdpVer3, ...), + * fieldID FieldID {{FieldTypes}}, + * curve Curve, + * base ECPoint, + * order INTEGER, + * cofactor INTEGER OPTIONAL, + * hash HashAlgorithm OPTIONAL, + * ... + * } + * + * We only support prime-field as field type, and ignore hash and cofactor. + */ +static int pk_group_from_specified( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) +{ + int ret; + unsigned char *p = params->p; + const unsigned char * const end = params->p + params->len; + const unsigned char *end_field, *end_curve; + size_t len; + int ver; + + /* SpecifiedECDomainVersion ::= INTEGER { 1, 2, 3 } */ + if( ( ret = mbedtls_asn1_get_int( &p, end, &ver ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ver < 1 || ver > 3 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + /* + * FieldID { FIELD-ID:IOSet } ::= SEQUENCE { -- Finite field + * fieldType FIELD-ID.&id({IOSet}), + * parameters FIELD-ID.&Type({IOSet}{@fieldType}) + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_field = p + len; + + /* + * FIELD-ID ::= TYPE-IDENTIFIER + * FieldTypes FIELD-ID ::= { + * { Prime-p IDENTIFIED BY prime-field } | + * { Characteristic-two IDENTIFIED BY characteristic-two-field } + * } + * prime-field OBJECT IDENTIFIER ::= { id-fieldType 1 } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_field, &len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( ret ); + + if( len != MBEDTLS_OID_SIZE( MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD ) || + memcmp( p, MBEDTLS_OID_ANSI_X9_62_PRIME_FIELD, len ) != 0 ) + { + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + } + + p += len; + + /* Prime-p ::= INTEGER -- Field of size p. */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end_field, &grp->P ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + grp->pbits = mbedtls_mpi_bitlen( &grp->P ); + + if( p != end_field ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * Curve ::= SEQUENCE { + * a FieldElement, + * b FieldElement, + * seed BIT STRING OPTIONAL + * -- Shall be present if used in SpecifiedECDomain + * -- with version equal to ecdpVer2 or ecdpVer3 + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( ret ); + + end_curve = p + len; + + /* + * FieldElement ::= OCTET STRING + * containing an integer in the case of a prime field + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->A, p, len ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 || + ( ret = mbedtls_mpi_read_binary( &grp->B, p, len ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + /* Ignore seed BIT STRING OPTIONAL */ + if( ( ret = mbedtls_asn1_get_tag( &p, end_curve, &len, MBEDTLS_ASN1_BIT_STRING ) ) == 0 ) + p += len; + + if( p != end_curve ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * ECPoint ::= OCTET STRING + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_ecp_point_read_binary( grp, &grp->G, + ( const unsigned char *) p, len ) ) != 0 ) + { + /* + * If we can't read the point because it's compressed, cheat by + * reading only the X coordinate and the parity bit of Y. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE || + ( p[0] != 0x02 && p[0] != 0x03 ) || + len != mbedtls_mpi_size( &grp->P ) + 1 || + mbedtls_mpi_read_binary( &grp->G.X, p + 1, len - 1 ) != 0 || + mbedtls_mpi_lset( &grp->G.Y, p[0] - 2 ) != 0 || + mbedtls_mpi_lset( &grp->G.Z, 1 ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + + p += len; + + /* + * order INTEGER + */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &grp->N ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + grp->nbits = mbedtls_mpi_bitlen( &grp->N ); + + /* + * Allow optional elements by purposefully not enforcing p == end here. + */ + + return( 0 ); +} + +/* + * Find the group id associated with an (almost filled) group as generated by + * pk_group_from_specified(), or return an error if unknown. + */ +static int pk_group_id_from_group( const mbedtls_ecp_group *grp, mbedtls_ecp_group_id *grp_id ) +{ + int ret = 0; + mbedtls_ecp_group ref; + const mbedtls_ecp_group_id *id; + + mbedtls_ecp_group_init( &ref ); + + for( id = mbedtls_ecp_grp_id_list(); *id != MBEDTLS_ECP_DP_NONE; id++ ) + { + /* Load the group associated to that id */ + mbedtls_ecp_group_free( &ref ); + MBEDTLS_MPI_CHK( mbedtls_ecp_group_load( &ref, *id ) ); + + /* Compare to the group we were given, starting with easy tests */ + if( grp->pbits == ref.pbits && grp->nbits == ref.nbits && + mbedtls_mpi_cmp_mpi( &grp->P, &ref.P ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->A, &ref.A ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->B, &ref.B ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->N, &ref.N ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.X, &ref.G.X ) == 0 && + mbedtls_mpi_cmp_mpi( &grp->G.Z, &ref.G.Z ) == 0 && + /* For Y we may only know the parity bit, so compare only that */ + mbedtls_mpi_get_bit( &grp->G.Y, 0 ) == mbedtls_mpi_get_bit( &ref.G.Y, 0 ) ) + { + break; + } + + } + +cleanup: + mbedtls_ecp_group_free( &ref ); + + *grp_id = *id; + + if( ret == 0 && *id == MBEDTLS_ECP_DP_NONE ) + ret = MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE; + + return( ret ); +} + +/* + * Parse a SpecifiedECDomain (SEC 1 C.2) and find the associated group ID + */ +static int pk_group_id_from_specified( const mbedtls_asn1_buf *params, + mbedtls_ecp_group_id *grp_id ) +{ + int ret; + mbedtls_ecp_group grp; + + mbedtls_ecp_group_init( &grp ); + + if( ( ret = pk_group_from_specified( params, &grp ) ) != 0 ) + goto cleanup; + + ret = pk_group_id_from_group( &grp, grp_id ); + +cleanup: + mbedtls_ecp_group_free( &grp ); + + return( ret ); +} +#endif /* MBEDTLS_PK_PARSE_EC_EXTENDED */ + +/* + * Use EC parameters to initialise an EC group + * + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * specifiedCurve SpecifiedECDomain -- = SEQUENCE { ... } + * -- implicitCurve NULL + */ +static int pk_use_ecparams( const mbedtls_asn1_buf *params, mbedtls_ecp_group *grp ) +{ + int ret; + mbedtls_ecp_group_id grp_id; + + if( params->tag == MBEDTLS_ASN1_OID ) + { + if( mbedtls_oid_get_ec_grp( params, &grp_id ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_NAMED_CURVE ); + } + else + { +#if defined(MBEDTLS_PK_PARSE_EC_EXTENDED) + if( ( ret = pk_group_id_from_specified( params, &grp_id ) ) != 0 ) + return( ret ); +#else + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +#endif + } + + /* + * grp may already be initilialized; if so, make sure IDs match + */ + if( grp->id != MBEDTLS_ECP_DP_NONE && grp->id != grp_id ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + if( ( ret = mbedtls_ecp_group_load( grp, grp_id ) ) != 0 ) + return( ret ); + + return( 0 ); +} + +/* + * EC public key is an EC point + * + * The caller is responsible for clearing the structure upon failure if + * desired. Take care to pass along the possible ECP_FEATURE_UNAVAILABLE + * return code of mbedtls_ecp_point_read_binary() and leave p in a usable state. + */ +static int pk_get_ecpubkey( unsigned char **p, const unsigned char *end, + mbedtls_ecp_keypair *key ) +{ + int ret; + + if( ( ret = mbedtls_ecp_point_read_binary( &key->grp, &key->Q, + (const unsigned char *) *p, end - *p ) ) == 0 ) + { + ret = mbedtls_ecp_check_pubkey( &key->grp, &key->Q ); + } + + /* + * We know mbedtls_ecp_point_read_binary consumed all bytes or failed + */ + *p = (unsigned char *) end; + + return( ret ); +} +#endif /* MBEDTLS_ECP_C */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_get_rsapubkey( unsigned char **p, + const unsigned char *end, + mbedtls_rsa_context *rsa ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* Import N */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, *p, len, NULL, 0, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + /* Import E */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, MBEDTLS_ASN1_INTEGER ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, *p, len ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + + *p += len; + + if( mbedtls_rsa_complete( rsa ) != 0 || + mbedtls_rsa_check_pubkey( rsa ) != 0 ) + { + return( MBEDTLS_ERR_PK_INVALID_PUBKEY ); + } + + if( *p != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} +#endif /* MBEDTLS_RSA_C */ + +/* Get a PK algorithm identifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +static int pk_get_pk_alg( unsigned char **p, + const unsigned char *end, + mbedtls_pk_type_t *pk_alg, mbedtls_asn1_buf *params ) +{ + int ret; + mbedtls_asn1_buf alg_oid; + + memset( params, 0, sizeof(mbedtls_asn1_buf) ); + + if( ( ret = mbedtls_asn1_get_alg( p, end, &alg_oid, params ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_ALG + ret ); + + if( mbedtls_oid_get_pk_alg( &alg_oid, pk_alg ) != 0 ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + /* + * No parameters with RSA (only for EC) + */ + if( *pk_alg == MBEDTLS_PK_RSA && + ( ( params->tag != MBEDTLS_ASN1_NULL && params->tag != 0 ) || + params->len != 0 ) ) + { + return( MBEDTLS_ERR_PK_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ +int mbedtls_pk_parse_subpubkey( unsigned char **p, const unsigned char *end, + mbedtls_pk_context *pk ) +{ + int ret; + size_t len; + mbedtls_asn1_buf alg_params; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = *p + len; + + if( ( ret = pk_get_pk_alg( p, end, &pk_alg, &alg_params ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_PK_INVALID_PUBKEY + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + ret = pk_get_rsapubkey( p, end, mbedtls_pk_rsa( *pk ) ); + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY_DH || pk_alg == MBEDTLS_PK_ECKEY ) + { + ret = pk_use_ecparams( &alg_params, &mbedtls_pk_ec( *pk )->grp ); + if( ret == 0 ) + ret = pk_get_ecpubkey( p, end, mbedtls_pk_ec( *pk ) ); + } else +#endif /* MBEDTLS_ECP_C */ + ret = MBEDTLS_ERR_PK_UNKNOWN_PK_ALG; + + if( ret == 0 && *p != end ) + ret = MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH; + + if( ret != 0 ) + mbedtls_pk_free( pk ); + + return( ret ); +} + +#if defined(MBEDTLS_RSA_C) +/* + * Parse a PKCS#1 encoded private RSA key + */ +static int pk_parse_key_pkcs1_der( mbedtls_rsa_context *rsa, + const unsigned char *key, + size_t keylen ) +{ + int ret, version; + size_t len; + unsigned char *p, *end; + + mbedtls_mpi T; + mbedtls_mpi_init( &T ); + + p = (unsigned char *) key; + end = p + keylen; + + /* + * This function parses the RSAPrivateKey (PKCS#1) + * + * RSAPrivateKey ::= SEQUENCE { + * version Version, + * modulus INTEGER, -- n + * publicExponent INTEGER, -- e + * privateExponent INTEGER, -- d + * prime1 INTEGER, -- p + * prime2 INTEGER, -- q + * exponent1 INTEGER, -- d mod (p-1) + * exponent2 INTEGER, -- d mod (q-1) + * coefficient INTEGER, -- (inverse of q) mod p + * otherPrimeInfos OtherPrimeInfos OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( version != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + } + + /* Import N */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, p, len, NULL, 0, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + goto cleanup; + p += len; + + /* Import E */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + NULL, 0, p, len ) ) != 0 ) + goto cleanup; + p += len; + + /* Import D */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, NULL, 0, + p, len, NULL, 0 ) ) != 0 ) + goto cleanup; + p += len; + + /* Import P */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, p, len, NULL, 0, + NULL, 0, NULL, 0 ) ) != 0 ) + goto cleanup; + p += len; + + /* Import Q */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_INTEGER ) ) != 0 || + ( ret = mbedtls_rsa_import_raw( rsa, NULL, 0, NULL, 0, p, len, + NULL, 0, NULL, 0 ) ) != 0 ) + goto cleanup; + p += len; + + /* Complete the RSA private key */ + if( ( ret = mbedtls_rsa_complete( rsa ) ) != 0 ) + goto cleanup; + + /* Check optional parameters */ + if( ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 || + ( ret = mbedtls_asn1_get_mpi( &p, end, &T ) ) != 0 ) + goto cleanup; + + if( p != end ) + { + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ; + } + +cleanup: + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + { + /* Wrap error code if it's coming from a lower level */ + if( ( ret & 0xff80 ) == 0 ) + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret; + else + ret = MBEDTLS_ERR_PK_KEY_INVALID_FORMAT; + + mbedtls_rsa_free( rsa ); + } + + return( ret ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * Parse a SEC1 encoded private EC key + */ +static int pk_parse_key_sec1_der( mbedtls_ecp_keypair *eck, + const unsigned char *key, + size_t keylen ) +{ + int ret; + int version, pubkey_done; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + unsigned char *end2; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( version != 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_mpi_read_binary( &eck->d, p, len ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + p += len; + + pubkey_done = 0; + if( p != end ) + { + /* + * Is 'parameters' present? + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + if( ( ret = pk_get_ecparams( &p, p + len, ¶ms) ) != 0 || + ( ret = pk_use_ecparams( ¶ms, &eck->grp ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + } + + if( p != end ) + { + /* + * Is 'publickey' present? If not, or if we can't read it (eg because it + * is compressed), create it from the private key. + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_bitstring_null( &p, end2, &len ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( p + len != end2 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( ( ret = pk_get_ecpubkey( &p, end2, eck ) ) == 0 ) + pubkey_done = 1; + else + { + /* + * The only acceptable failure mode of pk_get_ecpubkey() above + * is if the point format is not recognized. + */ + if( ret != MBEDTLS_ERR_ECP_FEATURE_UNAVAILABLE ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + } + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + } + + if( ! pubkey_done && + ( ret = mbedtls_ecp_mul( &eck->grp, &eck->Q, &eck->d, &eck->grp.G, + NULL, NULL ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_ecp_check_privkey( &eck->grp, &eck->d ) ) != 0 ) + { + mbedtls_ecp_keypair_free( eck ); + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_ECP_C */ + +/* + * Parse an unencrypted PKCS#8 encoded private key + * + * Notes: + * + * - This function does not own the key buffer. It is the + * responsibility of the caller to take care of zeroizing + * and freeing it after use. + * + * - The function is responsible for freeing the provided + * PK context on failure. + * + */ +static int pk_parse_key_pkcs8_unencrypted_der( + mbedtls_pk_context *pk, + const unsigned char* key, + size_t keylen ) +{ + int ret, version; + size_t len; + mbedtls_asn1_buf params; + unsigned char *p = (unsigned char *) key; + unsigned char *end = p + keylen; + mbedtls_pk_type_t pk_alg = MBEDTLS_PK_NONE; + const mbedtls_pk_info_t *pk_info; + + /* + * This function parses the PrivateKeyInfo object (PKCS#8 v1.2 = RFC 5208) + * + * PrivateKeyInfo ::= SEQUENCE { + * version Version, + * privateKeyAlgorithm PrivateKeyAlgorithmIdentifier, + * privateKey PrivateKey, + * attributes [0] IMPLICIT Attributes OPTIONAL } + * + * Version ::= INTEGER + * PrivateKeyAlgorithmIdentifier ::= AlgorithmIdentifier + * PrivateKey ::= OCTET STRING + * + * The PrivateKey OCTET STRING is a SEC1 ECPrivateKey + */ + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end, &version ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( version != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_VERSION + ret ); + + if( ( ret = pk_get_pk_alg( &p, end, &pk_alg, ¶ms ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( len < 1 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( ( pk_info = mbedtls_pk_info_from_type( pk_alg ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA ) + { + if( ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), p, len ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECKEY || pk_alg == MBEDTLS_PK_ECKEY_DH ) + { + if( ( ret = pk_use_ecparams( ¶ms, &mbedtls_pk_ec( *pk )->grp ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), p, len ) ) != 0 ) + { + mbedtls_pk_free( pk ); + return( ret ); + } + } else +#endif /* MBEDTLS_ECP_C */ + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + return( 0 ); +} + +/* + * Parse an encrypted PKCS#8 encoded private key + * + * To save space, the decryption happens in-place on the given key buffer. + * Also, while this function may modify the keybuffer, it doesn't own it, + * and instead it is the responsibility of the caller to zeroize and properly + * free it after use. + * + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) +static int pk_parse_key_pkcs8_encrypted_der( + mbedtls_pk_context *pk, + unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret, decrypted = 0; + size_t len; + unsigned char *buf; + unsigned char *p, *end; + mbedtls_asn1_buf pbe_alg_oid, pbe_params; +#if defined(MBEDTLS_PKCS12_C) + mbedtls_cipher_type_t cipher_alg; + mbedtls_md_type_t md_alg; +#endif + + p = key; + end = p + keylen; + + if( pwdlen == 0 ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + + /* + * This function parses the EncryptedPrivateKeyInfo object (PKCS#8) + * + * EncryptedPrivateKeyInfo ::= SEQUENCE { + * encryptionAlgorithm EncryptionAlgorithmIdentifier, + * encryptedData EncryptedData + * } + * + * EncryptionAlgorithmIdentifier ::= AlgorithmIdentifier + * + * EncryptedData ::= OCTET STRING + * + * The EncryptedData OCTET STRING is a PKCS#8 PrivateKeyInfo + * + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + } + + end = p + len; + + if( ( ret = mbedtls_asn1_get_alg( &p, end, &pbe_alg_oid, &pbe_params ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT + ret ); + + buf = p; + + /* + * Decrypt EncryptedData with appropriate PBE + */ +#if defined(MBEDTLS_PKCS12_C) + if( mbedtls_oid_get_pkcs12_pbe_alg( &pbe_alg_oid, &md_alg, &cipher_alg ) == 0 ) + { + if( ( ret = mbedtls_pkcs12_pbe( &pbe_params, MBEDTLS_PKCS12_PBE_DECRYPT, + cipher_alg, md_alg, + pwd, pwdlen, p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS12_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS12_PBE_SHA1_RC4_128, &pbe_alg_oid ) == 0 ) + { + if( ( ret = mbedtls_pkcs12_pbe_sha1_rc4_128( &pbe_params, + MBEDTLS_PKCS12_PBE_DECRYPT, + pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + return( ret ); + } + + // Best guess for password mismatch when using RC4. If first tag is + // not MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE + // + if( *buf != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS12_C */ +#if defined(MBEDTLS_PKCS5_C) + if( MBEDTLS_OID_CMP( MBEDTLS_OID_PKCS5_PBES2, &pbe_alg_oid ) == 0 ) + { + if( ( ret = mbedtls_pkcs5_pbes2( &pbe_params, MBEDTLS_PKCS5_DECRYPT, pwd, pwdlen, + p, len, buf ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_PKCS5_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + + return( ret ); + } + + decrypted = 1; + } + else +#endif /* MBEDTLS_PKCS5_C */ + { + ((void) pwd); + } + + if( decrypted == 0 ) + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( pk_parse_key_pkcs8_unencrypted_der( pk, buf, len ) ); +} +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + +/* + * Parse a private key + */ +int mbedtls_pk_parse_key( mbedtls_pk_context *pk, + const unsigned char *key, size_t keylen, + const unsigned char *pwd, size_t pwdlen ) +{ + int ret; + const mbedtls_pk_info_t *pk_info; + +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; + + mbedtls_pem_init( &pem ); + +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PRIVATE KEY-----", + "-----END RSA PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + + if( ret == 0 ) + { + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN EC PRIVATE KEY-----", + "-----END EC PRIVATE KEY-----", + key, pwd, pwdlen, &len ); + if( ret == 0 ) + { + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_MISMATCH ) + return( MBEDTLS_ERR_PK_PASSWORD_MISMATCH ); + else if( ret == MBEDTLS_ERR_PEM_PASSWORD_REQUIRED ) + return( MBEDTLS_ERR_PK_PASSWORD_REQUIRED ); + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_ECP_C */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PRIVATE KEY-----", + "-----END PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); + +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN ENCRYPTED PRIVATE KEY-----", + "-----END ENCRYPTED PRIVATE KEY-----", + key, NULL, 0, &len ); + if( ret == 0 ) + { + if( ( ret = pk_parse_key_pkcs8_encrypted_der( pk, + pem.buf, pem.buflen, + pwd, pwdlen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + return( ret ); +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ +#else + ((void) pwd); + ((void) pwdlen); +#endif /* MBEDTLS_PEM_PARSE_C */ + + /* + * At this point we only know it's not a PEM formatted key. Could be any + * of the known DER encoded private key formats + * + * We try the different DER format parsers to see if one passes without + * error + */ +#if defined(MBEDTLS_PKCS12_C) || defined(MBEDTLS_PKCS5_C) + { + unsigned char *key_copy; + + if( keylen == 0 ) + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); + + if( ( key_copy = mbedtls_calloc( 1, keylen ) ) == NULL ) + return( MBEDTLS_ERR_PK_ALLOC_FAILED ); + + memcpy( key_copy, key, keylen ); + + ret = pk_parse_key_pkcs8_encrypted_der( pk, key_copy, keylen, + pwd, pwdlen ); + + mbedtls_platform_zeroize( key_copy, keylen ); + mbedtls_free( key_copy ); + } + + if( ret == 0 ) + return( 0 ); + + mbedtls_pk_free( pk ); + + if( ret == MBEDTLS_ERR_PK_PASSWORD_MISMATCH ) + { + return( ret ); + } +#endif /* MBEDTLS_PKCS12_C || MBEDTLS_PKCS5_C */ + + if( ( ret = pk_parse_key_pkcs8_unencrypted_der( pk, key, keylen ) ) == 0 ) + return( 0 ); + + mbedtls_pk_free( pk ); + +#if defined(MBEDTLS_RSA_C) + + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ); + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_pkcs1_der( mbedtls_pk_rsa( *pk ), + key, keylen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + else + { + return( 0 ); + } + +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) + + pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_ECKEY ); + if( ( ret = mbedtls_pk_setup( pk, pk_info ) ) != 0 || + ( ret = pk_parse_key_sec1_der( mbedtls_pk_ec( *pk ), + key, keylen ) ) != 0 ) + { + mbedtls_pk_free( pk ); + } + else + { + return( 0 ); + } + +#endif /* MBEDTLS_ECP_C */ + + return( MBEDTLS_ERR_PK_KEY_INVALID_FORMAT ); +} + +/* + * Parse a public key + */ +int mbedtls_pk_parse_public_key( mbedtls_pk_context *ctx, + const unsigned char *key, size_t keylen ) +{ + int ret; + unsigned char *p; +#if defined(MBEDTLS_RSA_C) + const mbedtls_pk_info_t *pk_info; +#endif +#if defined(MBEDTLS_PEM_PARSE_C) + size_t len; + mbedtls_pem_context pem; + + mbedtls_pem_init( &pem ); +#if defined(MBEDTLS_RSA_C) + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN RSA PUBLIC KEY-----", + "-----END RSA PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + p = pem.buf; + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + return( ret ); + + if ( ( ret = pk_get_rsapubkey( &p, p + pem.buflen, mbedtls_pk_rsa( *ctx ) ) ) != 0 ) + mbedtls_pk_free( ctx ); + + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ + + /* Avoid calling mbedtls_pem_read_buffer() on non-null-terminated string */ + if( keylen == 0 || key[keylen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN PUBLIC KEY-----", + "-----END PUBLIC KEY-----", + key, NULL, 0, &len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + p = pem.buf; + + ret = mbedtls_pk_parse_subpubkey( &p, p + pem.buflen, ctx ); + mbedtls_pem_free( &pem ); + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + mbedtls_pem_free( &pem ); +#endif /* MBEDTLS_PEM_PARSE_C */ + +#if defined(MBEDTLS_RSA_C) + if( ( pk_info = mbedtls_pk_info_from_type( MBEDTLS_PK_RSA ) ) == NULL ) + return( MBEDTLS_ERR_PK_UNKNOWN_PK_ALG ); + + if( ( ret = mbedtls_pk_setup( ctx, pk_info ) ) != 0 ) + return( ret ); + + p = (unsigned char *)key; + ret = pk_get_rsapubkey( &p, p + keylen, mbedtls_pk_rsa( *ctx ) ); + if( ret == 0 ) + { + return( ret ); + } + mbedtls_pk_free( ctx ); + if( ret != ( MBEDTLS_ERR_PK_INVALID_PUBKEY + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + { + return( ret ); + } +#endif /* MBEDTLS_RSA_C */ + p = (unsigned char *) key; + + ret = mbedtls_pk_parse_subpubkey( &p, p + keylen, ctx ); + + return( ret ); +} + +#endif /* MBEDTLS_PK_PARSE_C */ diff --git a/common/mbedtls/platform.c b/common/mbedtls/platform.c new file mode 100644 index 000000000..3ddb7f7ad --- /dev/null +++ b/common/mbedtls/platform.c @@ -0,0 +1,341 @@ +/* + * Platform abstraction layer + * + * Copyright (C) 2006-2016, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PLATFORM_C) + +#include "mbedtls/platform.h" +#include "mbedtls/platform_util.h" + +#if defined(MBEDTLS_PLATFORM_MEMORY) +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +static void *platform_calloc_uninit( size_t n, size_t size ) +{ + ((void) n); + ((void) size); + return( NULL ); +} + +#define MBEDTLS_PLATFORM_STD_CALLOC platform_calloc_uninit +#endif /* !MBEDTLS_PLATFORM_STD_CALLOC */ + +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +static void platform_free_uninit( void *ptr ) +{ + ((void) ptr); +} + +#define MBEDTLS_PLATFORM_STD_FREE platform_free_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FREE */ + +static void * (*mbedtls_calloc_func)( size_t, size_t ) = MBEDTLS_PLATFORM_STD_CALLOC; +static void (*mbedtls_free_func)( void * ) = MBEDTLS_PLATFORM_STD_FREE; + +void * mbedtls_calloc( size_t nmemb, size_t size ) +{ + return (*mbedtls_calloc_func)( nmemb, size ); +} + +void mbedtls_free( void * ptr ) +{ + (*mbedtls_free_func)( ptr ); +} + +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ) +{ + mbedtls_calloc_func = calloc_func; + mbedtls_free_func = free_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_MEMORY */ + +#if defined(_WIN32) +#include +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ) +{ + int ret; + va_list argp; + + /* Avoid calling the invalid parameter handler by checking ourselves */ + if( s == NULL || n == 0 || fmt == NULL ) + return( -1 ); + + va_start( argp, fmt ); +#if defined(_TRUNCATE) && !defined(__MINGW32__) + ret = _vsnprintf_s( s, n, _TRUNCATE, fmt, argp ); +#else + ret = _vsnprintf( s, n, fmt, argp ); + if( ret < 0 || (size_t) ret == n ) + { + s[n-1] = '\0'; + ret = -1; + } +#endif + va_end( argp ); + + return( ret ); +} +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_snprintf_uninit( char * s, size_t n, + const char * format, ... ) +{ + ((void) s); + ((void) n); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_SNPRINTF platform_snprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_SNPRINTF */ + +int (*mbedtls_snprintf)( char * s, size_t n, + const char * format, + ... ) = MBEDTLS_PLATFORM_STD_SNPRINTF; + +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, + ... ) ) +{ + mbedtls_snprintf = snprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_printf_uninit( const char *format, ... ) +{ + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_PRINTF platform_printf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_PRINTF */ + +int (*mbedtls_printf)( const char *, ... ) = MBEDTLS_PLATFORM_STD_PRINTF; + +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ) +{ + mbedtls_printf = printf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_fprintf_uninit( FILE *stream, const char *format, ... ) +{ + ((void) stream); + ((void) format); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_FPRINTF platform_fprintf_uninit +#endif /* !MBEDTLS_PLATFORM_STD_FPRINTF */ + +int (*mbedtls_fprintf)( FILE *, const char *, ... ) = + MBEDTLS_PLATFORM_STD_FPRINTF; + +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *, const char *, ... ) ) +{ + mbedtls_fprintf = fprintf_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static void platform_exit_uninit( int status ) +{ + ((void) status); +} + +#define MBEDTLS_PLATFORM_STD_EXIT platform_exit_uninit +#endif /* !MBEDTLS_PLATFORM_STD_EXIT */ + +void (*mbedtls_exit)( int status ) = MBEDTLS_PLATFORM_STD_EXIT; + +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ) +{ + mbedtls_exit = exit_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +#if defined(MBEDTLS_HAVE_TIME) + +#if defined(MBEDTLS_PLATFORM_TIME_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static mbedtls_time_t platform_time_uninit( mbedtls_time_t* timer ) +{ + ((void) timer); + return( 0 ); +} + +#define MBEDTLS_PLATFORM_STD_TIME platform_time_uninit +#endif /* !MBEDTLS_PLATFORM_STD_TIME */ + +mbedtls_time_t (*mbedtls_time)( mbedtls_time_t* timer ) = MBEDTLS_PLATFORM_STD_TIME; + +int mbedtls_platform_set_time( mbedtls_time_t (*time_func)( mbedtls_time_t* timer ) ) +{ + mbedtls_time = time_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_TIME_ALT */ + +#endif /* MBEDTLS_HAVE_TIME */ + +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Default implementations for the platform independent seed functions use + * standard libc file functions to read from and write to a pre-defined filename + */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "rb" ) ) == NULL ) + return( -1 ); + + if( ( n = fread( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + mbedtls_platform_zeroize( buf, buf_len ); + return( -1 ); + } + + fclose( file ); + return( (int)n ); +} + +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ) +{ + FILE *file; + size_t n; + + if( ( file = fopen( MBEDTLS_PLATFORM_STD_NV_SEED_FILE, "w" ) ) == NULL ) + return -1; + + if( ( n = fwrite( buf, 1, buf_len, file ) ) != buf_len ) + { + fclose( file ); + return -1; + } + + fclose( file ); + return( (int)n ); +} +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_read_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ platform_nv_seed_read_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_READ */ + +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +/* + * Make dummy function to prevent NULL pointer dereferences + */ +static int platform_nv_seed_write_uninit( unsigned char *buf, size_t buf_len ) +{ + ((void) buf); + ((void) buf_len); + return( -1 ); +} + +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE platform_nv_seed_write_uninit +#endif /* !MBEDTLS_PLATFORM_STD_NV_SEED_WRITE */ + +int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_READ; +int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ) = + MBEDTLS_PLATFORM_STD_NV_SEED_WRITE; + +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) ) +{ + mbedtls_nv_seed_read = nv_seed_read_func; + mbedtls_nv_seed_write = nv_seed_write_func; + return( 0 ); +} +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) +/* + * Placeholder platform setup that does nothing by default + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ) +{ + (void)ctx; + + return( 0 ); +} + +/* + * Placeholder platform teardown that does nothing by default + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ) +{ + (void)ctx; +} +#endif /* MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +#endif /* MBEDTLS_PLATFORM_C */ diff --git a/common/mbedtls/platform.h b/common/mbedtls/platform.h new file mode 100644 index 000000000..818f44d4d --- /dev/null +++ b/common/mbedtls/platform.h @@ -0,0 +1,366 @@ +/** + * \file platform.h + * + * \brief This file contains the definitions and functions of the + * Mbed TLS platform abstraction layer. + * + * The platform abstraction layer removes the need for the library + * to directly link to standard C library functions or operating + * system services, making the library easier to port and embed. + * Application developers and users of the library can provide their own + * implementations of these functions, or implementations specific to + * their platform, which can be statically linked to the library or + * dynamically configured at runtime. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PLATFORM_H +#define MBEDTLS_PLATFORM_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "platform_time.h" +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \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_PLATFORM_NO_STD_FUNCTIONS) +#include +#include +#include +#if !defined(MBEDTLS_PLATFORM_STD_SNPRINTF) +#if defined(_WIN32) +#define MBEDTLS_PLATFORM_STD_SNPRINTF mbedtls_platform_win32_snprintf /**< The default \c snprintf function to use. */ +#else +#define MBEDTLS_PLATFORM_STD_SNPRINTF snprintf /**< The default \c snprintf function to use. */ +#endif +#endif +#if !defined(MBEDTLS_PLATFORM_STD_PRINTF) +#define MBEDTLS_PLATFORM_STD_PRINTF printf /**< The default \c printf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FPRINTF) +#define MBEDTLS_PLATFORM_STD_FPRINTF fprintf /**< The default \c fprintf function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_CALLOC) +#define MBEDTLS_PLATFORM_STD_CALLOC calloc /**< The default \c calloc function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_FREE) +#define MBEDTLS_PLATFORM_STD_FREE free /**< The default \c free function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT) +#define MBEDTLS_PLATFORM_STD_EXIT exit /**< The default \c exit function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_TIME) +#define MBEDTLS_PLATFORM_STD_TIME time /**< The default \c time function to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_PLATFORM_STD_EXIT_SUCCESS EXIT_SUCCESS /**< The default exit value to use. */ +#endif +#if !defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_PLATFORM_STD_EXIT_FAILURE EXIT_FAILURE /**< The default exit value to use. */ +#endif +#if defined(MBEDTLS_FS_IO) +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_READ) +#define MBEDTLS_PLATFORM_STD_NV_SEED_READ mbedtls_platform_std_nv_seed_read +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_WRITE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_WRITE mbedtls_platform_std_nv_seed_write +#endif +#if !defined(MBEDTLS_PLATFORM_STD_NV_SEED_FILE) +#define MBEDTLS_PLATFORM_STD_NV_SEED_FILE "seedfile" +#endif +#endif /* MBEDTLS_FS_IO */ +#else /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ +#if defined(MBEDTLS_PLATFORM_STD_MEM_HDR) +#include MBEDTLS_PLATFORM_STD_MEM_HDR +#endif +#endif /* MBEDTLS_PLATFORM_NO_STD_FUNCTIONS */ + + +/* \} name SECTION: Module settings */ + +/* + * The function pointers for calloc and free. + */ +#if defined(MBEDTLS_PLATFORM_MEMORY) +#if defined(MBEDTLS_PLATFORM_FREE_MACRO) && \ + defined(MBEDTLS_PLATFORM_CALLOC_MACRO) +#define mbedtls_free MBEDTLS_PLATFORM_FREE_MACRO +#define mbedtls_calloc MBEDTLS_PLATFORM_CALLOC_MACRO +#else +/* For size_t */ +#include +extern void *mbedtls_calloc( size_t n, size_t size ); +extern void mbedtls_free( void *ptr ); + +/** + * \brief This function dynamically sets the memory-management + * functions used by the library, during runtime. + * + * \param calloc_func The \c calloc function implementation. + * \param free_func The \c free function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_calloc_free( void * (*calloc_func)( size_t, size_t ), + void (*free_func)( void * ) ); +#endif /* MBEDTLS_PLATFORM_FREE_MACRO && MBEDTLS_PLATFORM_CALLOC_MACRO */ +#else /* !MBEDTLS_PLATFORM_MEMORY */ +#define mbedtls_free free +#define mbedtls_calloc calloc +#endif /* MBEDTLS_PLATFORM_MEMORY && !MBEDTLS_PLATFORM_{FREE,CALLOC}_MACRO */ + +/* + * The function pointers for fprintf + */ +#if defined(MBEDTLS_PLATFORM_FPRINTF_ALT) +/* We need FILE * */ +#include +extern int (*mbedtls_fprintf)( FILE *stream, const char *format, ... ); + +/** + * \brief This function dynamically configures the fprintf + * function that is called when the + * mbedtls_fprintf() function is invoked by the library. + * + * \param fprintf_func The \c fprintf function implementation. + * + * \return \c 0. + */ +int mbedtls_platform_set_fprintf( int (*fprintf_func)( FILE *stream, const char *, + ... ) ); +#else +#if defined(MBEDTLS_PLATFORM_FPRINTF_MACRO) +#define mbedtls_fprintf MBEDTLS_PLATFORM_FPRINTF_MACRO +#else +#define mbedtls_fprintf fprintf +#endif /* MBEDTLS_PLATFORM_FPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_FPRINTF_ALT */ + +/* + * The function pointers for printf + */ +#if defined(MBEDTLS_PLATFORM_PRINTF_ALT) +extern int (*mbedtls_printf)( const char *format, ... ); + +/** + * \brief This function dynamically configures the snprintf + * function that is called when the mbedtls_snprintf() + * function is invoked by the library. + * + * \param printf_func The \c printf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_printf( int (*printf_func)( const char *, ... ) ); +#else /* !MBEDTLS_PLATFORM_PRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_PRINTF_MACRO) +#define mbedtls_printf MBEDTLS_PLATFORM_PRINTF_MACRO +#else +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_PRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_PRINTF_ALT */ + +/* + * The function pointers for snprintf + * + * The snprintf implementation should conform to C99: + * - it *must* always correctly zero-terminate the buffer + * (except when n == 0, then it must leave the buffer untouched) + * - however it is acceptable to return -1 instead of the required length when + * the destination buffer is too short. + */ +#if defined(_WIN32) +/* For Windows (inc. MSYS2), we provide our own fixed implementation */ +int mbedtls_platform_win32_snprintf( char *s, size_t n, const char *fmt, ... ); +#endif + +#if defined(MBEDTLS_PLATFORM_SNPRINTF_ALT) +extern int (*mbedtls_snprintf)( char * s, size_t n, const char * format, ... ); + +/** + * \brief This function allows configuring a custom + * \c snprintf function pointer. + * + * \param snprintf_func The \c snprintf function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_snprintf( int (*snprintf_func)( char * s, size_t n, + const char * format, ... ) ); +#else /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ +#if defined(MBEDTLS_PLATFORM_SNPRINTF_MACRO) +#define mbedtls_snprintf MBEDTLS_PLATFORM_SNPRINTF_MACRO +#else +#define mbedtls_snprintf MBEDTLS_PLATFORM_STD_SNPRINTF +#endif /* MBEDTLS_PLATFORM_SNPRINTF_MACRO */ +#endif /* MBEDTLS_PLATFORM_SNPRINTF_ALT */ + +/* + * The function pointers for exit + */ +#if defined(MBEDTLS_PLATFORM_EXIT_ALT) +extern void (*mbedtls_exit)( int status ); + +/** + * \brief This function dynamically configures the exit + * function that is called when the mbedtls_exit() + * function is invoked by the library. + * + * \param exit_func The \c exit function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_exit( void (*exit_func)( int status ) ); +#else +#if defined(MBEDTLS_PLATFORM_EXIT_MACRO) +#define mbedtls_exit MBEDTLS_PLATFORM_EXIT_MACRO +#else +#define mbedtls_exit exit +#endif /* MBEDTLS_PLATFORM_EXIT_MACRO */ +#endif /* MBEDTLS_PLATFORM_EXIT_ALT */ + +/* + * The default exit values + */ +#if defined(MBEDTLS_PLATFORM_STD_EXIT_SUCCESS) +#define MBEDTLS_EXIT_SUCCESS MBEDTLS_PLATFORM_STD_EXIT_SUCCESS +#else +#define MBEDTLS_EXIT_SUCCESS 0 +#endif +#if defined(MBEDTLS_PLATFORM_STD_EXIT_FAILURE) +#define MBEDTLS_EXIT_FAILURE MBEDTLS_PLATFORM_STD_EXIT_FAILURE +#else +#define MBEDTLS_EXIT_FAILURE 1 +#endif + +/* + * The function pointers for reading from and writing a seed file to + * Non-Volatile storage (NV) in a platform-independent way + * + * Only enabled when the NV seed entropy source is enabled + */ +#if defined(MBEDTLS_ENTROPY_NV_SEED) +#if !defined(MBEDTLS_PLATFORM_NO_STD_FUNCTIONS) && defined(MBEDTLS_FS_IO) +/* Internal standard platform definitions */ +int mbedtls_platform_std_nv_seed_read( unsigned char *buf, size_t buf_len ); +int mbedtls_platform_std_nv_seed_write( unsigned char *buf, size_t buf_len ); +#endif + +#if defined(MBEDTLS_PLATFORM_NV_SEED_ALT) +extern int (*mbedtls_nv_seed_read)( unsigned char *buf, size_t buf_len ); +extern int (*mbedtls_nv_seed_write)( unsigned char *buf, size_t buf_len ); + +/** + * \brief This function allows configuring custom seed file writing and + * reading functions. + * + * \param nv_seed_read_func The seed reading function implementation. + * \param nv_seed_write_func The seed writing function implementation. + * + * \return \c 0 on success. + */ +int mbedtls_platform_set_nv_seed( + int (*nv_seed_read_func)( unsigned char *buf, size_t buf_len ), + int (*nv_seed_write_func)( unsigned char *buf, size_t buf_len ) + ); +#else +#if defined(MBEDTLS_PLATFORM_NV_SEED_READ_MACRO) && \ + defined(MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO) +#define mbedtls_nv_seed_read MBEDTLS_PLATFORM_NV_SEED_READ_MACRO +#define mbedtls_nv_seed_write MBEDTLS_PLATFORM_NV_SEED_WRITE_MACRO +#else +#define mbedtls_nv_seed_read mbedtls_platform_std_nv_seed_read +#define mbedtls_nv_seed_write mbedtls_platform_std_nv_seed_write +#endif +#endif /* MBEDTLS_PLATFORM_NV_SEED_ALT */ +#endif /* MBEDTLS_ENTROPY_NV_SEED */ + +#if !defined(MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT) + +/** + * \brief The platform context structure. + * + * \note This structure may be used to assist platform-specific + * setup or teardown operations. + */ +typedef struct mbedtls_platform_context +{ + char dummy; /**< A placeholder member, as empty structs are not portable. */ +} +mbedtls_platform_context; + +#else +#include "platform_alt.h" +#endif /* !MBEDTLS_PLATFORM_SETUP_TEARDOWN_ALT */ + +/** + * \brief This function performs any platform-specific initialization + * operations. + * + * \note This function should be called before any other library functions. + * + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + * \return \c 0 on success. + */ +int mbedtls_platform_setup( mbedtls_platform_context *ctx ); +/** + * \brief This function performs any platform teardown operations. + * + * \note This function should be called after every other Mbed TLS module + * has been correctly freed using the appropriate free function. + * + * Its implementation is platform-specific, and unless + * platform-specific code is provided, it does nothing. + * + * \note The usage and necessity of this function is dependent on the platform. + * + * \param ctx The platform context. + * + */ +void mbedtls_platform_teardown( mbedtls_platform_context *ctx ); + +#ifdef __cplusplus +} +#endif + +#endif /* platform.h */ diff --git a/common/mbedtls/platform_util.c b/common/mbedtls/platform_util.c new file mode 100644 index 000000000..0be18aca6 --- /dev/null +++ b/common/mbedtls/platform_util.c @@ -0,0 +1,69 @@ +/* + * Common and shared functions used by multiple modules in the Mbed TLS + * library. + * + * Copyright (C) 2018, Arm Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "mbedtls/platform_util.h" + +#include +#include + +#if !defined(MBEDTLS_PLATFORM_ZEROIZE_ALT) +/* + * This implementation should never be optimized out by the compiler + * + * This implementation for mbedtls_platform_zeroize() was inspired from Colin + * Percival's blog article at: + * + * http://www.daemonology.net/blog/2014-09-04-how-to-zero-a-buffer.html + * + * It uses a volatile function pointer to the standard memset(). Because the + * pointer is volatile the compiler expects it to change at + * any time and will not optimize out the call that could potentially perform + * other operations on the input buffer instead of just setting it to 0. + * Nevertheless, as pointed out by davidtgoldblatt on Hacker News + * (refer to http://www.daemonology.net/blog/2014-09-05-erratum.html for + * details), optimizations of the following form are still possible: + * + * if( memset_func != memset ) + * memset_func( buf, 0, len ); + * + * Note that it is extremely difficult to guarantee that + * mbedtls_platform_zeroize() will not be optimized out by aggressive compilers + * in a portable way. For this reason, Mbed TLS also provides the configuration + * option MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for their + * platform and needs. + */ +static void * (* const volatile memset_func)( void *, int, size_t ) = memset; + +void mbedtls_platform_zeroize( void *buf, size_t len ) +{ + memset_func( buf, 0, len ); +} +#endif /* MBEDTLS_PLATFORM_ZEROIZE_ALT */ diff --git a/common/mbedtls/platform_util.h b/common/mbedtls/platform_util.h new file mode 100644 index 000000000..79404ce67 --- /dev/null +++ b/common/mbedtls/platform_util.h @@ -0,0 +1,64 @@ +/** + * \file platform_util.h + * + * \brief Common and shared functions used by multiple modules in the Mbed TLS + * library. + */ +/* + * Copyright (C) 2018, Arm Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_PLATFORM_UTIL_H +#define MBEDTLS_PLATFORM_UTIL_H + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \brief Securely zeroize a buffer + * + * The function is meant to wipe the data contained in a buffer so + * that it can no longer be recovered even if the program memory + * is later compromised. Call this function on sensitive data + * stored on the stack before returning from a function, and on + * sensitive data stored on the heap before freeing the heap + * object. + * + * It is extremely difficult to guarantee that calls to + * mbedtls_platform_zeroize() are not removed by aggressive + * compiler optimizations in a portable way. For this reason, Mbed + * TLS provides the configuration option + * MBEDTLS_PLATFORM_ZEROIZE_ALT, which allows users to configure + * mbedtls_platform_zeroize() to use a suitable implementation for + * their platform and needs + * + * \param buf Buffer to be zeroized + * \param len Length of the buffer in bytes + * + */ +void mbedtls_platform_zeroize( void *buf, size_t len ); + +#ifdef __cplusplus +} +#endif + +#endif /* MBEDTLS_PLATFORM_UTIL_H */ diff --git a/common/mbedtls/rsa.c b/common/mbedtls/rsa.c new file mode 100644 index 000000000..f26cf6a8b --- /dev/null +++ b/common/mbedtls/rsa.c @@ -0,0 +1,2400 @@ +/* + * The RSA public-key cryptosystem + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +/* + * The following sources were referenced in the design of this implementation + * of the RSA algorithm: + * + * [1] A method for obtaining digital signatures and public-key cryptosystems + * R Rivest, A Shamir, and L Adleman + * http://people.csail.mit.edu/rivest/pubs.html#RSA78 + * + * [2] Handbook of Applied Cryptography - 1997, Chapter 8 + * Menezes, van Oorschot and Vanstone + * + * [3] Malware Guard Extension: Using SGX to Conceal Cache Attacks + * Michael Schwarz, Samuel Weiser, Daniel Gruss, Clémentine Maurice and + * Stefan Mangard + * https://arxiv.org/abs/1702.08719v2 + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_RSA_C) + +#include "mbedtls/rsa.h" +#include "mbedtls/rsa_internal.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PKCS1_V21) +#include "mbedtls/md.h" +#endif + +#if defined(MBEDTLS_PKCS1_V15) && !defined(__OpenBSD__) +#include +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if !defined(MBEDTLS_RSA_ALT) + +#if defined(MBEDTLS_PKCS1_V15) +/* constant-time buffer comparison */ +static inline int mbedtls_safer_memcmp( const void *a, const void *b, size_t n ) +{ + size_t i; + const unsigned char *A = (const unsigned char *) a; + const unsigned char *B = (const unsigned char *) b; + unsigned char diff = 0; + + for( i = 0; i < n; i++ ) + diff |= A[i] ^ B[i]; + + return( diff ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ) +{ + int ret; + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( &ctx->N, N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( &ctx->P, P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( &ctx->Q, Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( &ctx->D, D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( &ctx->E, E ) ) != 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + + if( N != NULL ) + ctx->len = mbedtls_mpi_size( &ctx->N ); + + return( 0 ); +} + +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ) +{ + int ret = 0; + + if( N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->N, N, N_len ) ); + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &ctx->E, E, E_len ) ); + +cleanup: + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + + return( 0 ); +} + +/* + * Checks whether the context fields are set in such a way + * that the RSA primitives will be able to execute without error. + * It does *not* make guarantees for consistency of the parameters. + */ +static int rsa_check_context( mbedtls_rsa_context const *ctx, int is_priv, + int blinding_needed ) +{ +#if !defined(MBEDTLS_RSA_NO_CRT) + /* blinding_needed is only used for NO_CRT to decide whether + * P,Q need to be present or not. */ + ((void) blinding_needed); +#endif + + if( ctx->len != mbedtls_mpi_size( &ctx->N ) || + ctx->len > MBEDTLS_MPI_MAX_SIZE ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + /* + * 1. Modular exponentiation needs positive, odd moduli. + */ + + /* Modular exponentiation wrt. N is always used for + * RSA public key operations. */ + if( mbedtls_mpi_cmp_int( &ctx->N, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->N, 0 ) == 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Modular exponentiation for P and Q is only + * used for private key operations and if CRT + * is used. */ + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->P, 0 ) == 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 || + mbedtls_mpi_get_bit( &ctx->Q, 0 ) == 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* !MBEDTLS_RSA_NO_CRT */ + + /* + * 2. Exponents must be positive + */ + + /* Always need E for public key operations */ + if( mbedtls_mpi_cmp_int( &ctx->E, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* For private key operations, use D or DP & DQ + * as (unblinded) exponents. */ + if( is_priv && mbedtls_mpi_cmp_int( &ctx->D, 0 ) <= 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); +#else + if( is_priv && + ( mbedtls_mpi_cmp_int( &ctx->DP, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->DQ, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Blinding shouldn't make exponents negative either, + * so check that P, Q >= 1 if that hasn't yet been + * done as part of 1. */ +#if defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && blinding_needed && + ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) <= 0 || + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) <= 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + /* It wouldn't lead to an error if it wasn't satisfied, + * but check for QP >= 1 nonetheless. */ +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv && + mbedtls_mpi_cmp_int( &ctx->QP, 0 ) <= 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } +#endif + + return( 0 ); +} + +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ) +{ + int ret = 0; + + const int have_N = ( mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 ); + const int have_P = ( mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 ); + const int have_Q = ( mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 ); + const int have_D = ( mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 ); + const int have_E = ( mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0 ); + + /* + * Check whether provided parameters are enough + * to deduce all others. The following incomplete + * parameter sets for private keys are supported: + * + * (1) P, Q missing. + * (2) D and potentially N missing. + * + */ + + const int n_missing = have_P && have_Q && have_D && have_E; + const int pq_missing = have_N && !have_P && !have_Q && have_D && have_E; + const int d_missing = have_P && have_Q && !have_D && have_E; + const int is_pub = have_N && !have_P && !have_Q && !have_D && have_E; + + /* These three alternatives are mutually exclusive */ + const int is_priv = n_missing || pq_missing || d_missing; + + if( !is_priv && !is_pub ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Step 1: Deduce N if P, Q are provided. + */ + + if( !have_N && have_P && have_Q ) + { + if( ( ret = mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, + &ctx->Q ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + + ctx->len = mbedtls_mpi_size( &ctx->N ); + } + + /* + * Step 2: Deduce and verify all remaining core parameters. + */ + + if( pq_missing ) + { + ret = mbedtls_rsa_deduce_primes( &ctx->N, &ctx->E, &ctx->D, + &ctx->P, &ctx->Q ); + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + + } + else if( d_missing ) + { + if( ( ret = mbedtls_rsa_deduce_private_exponent( &ctx->P, + &ctx->Q, + &ctx->E, + &ctx->D ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } + } + + /* + * Step 3: Deduce all additional parameters specific + * to our current RSA implementation. + */ + +#if !defined(MBEDTLS_RSA_NO_CRT) + if( is_priv ) + { + ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ); + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* + * Step 3: Basic sanity checks + */ + + return( rsa_check_context( ctx, is_priv, 1 ) ); +} + +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ) +{ + int ret = 0; + + /* Check if key is private or public */ + const int is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + if( N != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->N, N, N_len ) ); + + if( P != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->P, P, P_len ) ); + + if( Q != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->Q, Q, Q_len ) ); + + if( D != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->D, D, D_len ) ); + + if( E != NULL ) + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &ctx->E, E, E_len ) ); + +cleanup: + + return( ret ); +} + +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ) +{ + int ret; + + /* Check if key is private or public */ + int is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + { + /* If we're trying to export private parameters for a public key, + * something must be wrong. */ + if( P != NULL || Q != NULL || D != NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + } + + /* Export all requested core parameters. */ + + if( ( N != NULL && ( ret = mbedtls_mpi_copy( N, &ctx->N ) ) != 0 ) || + ( P != NULL && ( ret = mbedtls_mpi_copy( P, &ctx->P ) ) != 0 ) || + ( Q != NULL && ( ret = mbedtls_mpi_copy( Q, &ctx->Q ) ) != 0 ) || + ( D != NULL && ( ret = mbedtls_mpi_copy( D, &ctx->D ) ) != 0 ) || + ( E != NULL && ( ret = mbedtls_mpi_copy( E, &ctx->E ) ) != 0 ) ) + { + return( ret ); + } + + return( 0 ); +} + +/* + * Export CRT parameters + * This must also be implemented if CRT is not used, for being able to + * write DER encoded RSA keys. The helper function mbedtls_rsa_deduce_crt + * can be used in this case. + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret; + + /* Check if key is private or public */ + int is_priv = + mbedtls_mpi_cmp_int( &ctx->N, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->P, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->Q, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->D, 0 ) != 0 && + mbedtls_mpi_cmp_int( &ctx->E, 0 ) != 0; + + if( !is_priv ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Export all requested blinding parameters. */ + if( ( DP != NULL && ( ret = mbedtls_mpi_copy( DP, &ctx->DP ) ) != 0 ) || + ( DQ != NULL && ( ret = mbedtls_mpi_copy( DQ, &ctx->DQ ) ) != 0 ) || + ( QP != NULL && ( ret = mbedtls_mpi_copy( QP, &ctx->QP ) ) != 0 ) ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#else + if( ( ret = mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + DP, DQ, QP ) ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA + ret ); + } +#endif + + return( 0 ); +} + +/* + * Initialize an RSA context + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id ) +{ + memset( ctx, 0, sizeof( mbedtls_rsa_context ) ); + + mbedtls_rsa_set_padding( ctx, padding, hash_id ); + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_init( &ctx->mutex ); +#endif +} + +/* + * Set padding for an existing RSA context + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, int hash_id ) +{ + ctx->padding = padding; + ctx->hash_id = hash_id; +} + +/* + * Get length in bytes of RSA modulus + */ + +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ) +{ + return( ctx->len ); +} + + +#if defined(MBEDTLS_GENPRIME) + +/* + * Generate an RSA keypair + * + * This generation method follows the RSA key pair generation procedure of + * FIPS 186-4 if 2^16 < exponent < 2^256 and nbits = 2048 or nbits = 3072. + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ) +{ + int ret; + mbedtls_mpi H, G, L; + + if( f_rng == NULL || nbits < 128 || exponent < 3 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( nbits % 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &H ); + mbedtls_mpi_init( &G ); + mbedtls_mpi_init( &L ); + + /* + * find primes P and Q with Q < P so that: + * 1. |P-Q| > 2^( nbits / 2 - 100 ) + * 2. GCD( E, (P-1)*(Q-1) ) == 1 + * 3. E^-1 mod LCM(P-1, Q-1) > 2^( nbits / 2 ) + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_lset( &ctx->E, exponent ) ); + + do + { + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->P, nbits >> 1, 0, + f_rng, p_rng ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_gen_prime( &ctx->Q, nbits >> 1, 0, + f_rng, p_rng ) ); + + /* make sure the difference between p and q is not too small (FIPS 186-4 §B.3.3 step 5.4) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &H, &ctx->P, &ctx->Q ) ); + if( mbedtls_mpi_bitlen( &H ) <= ( ( nbits >= 200 ) ? ( ( nbits >> 1 ) - 99 ) : 0 ) ) + continue; + + /* not required by any standards, but some users rely on the fact that P > Q */ + if( H.s < 0 ) + mbedtls_mpi_swap( &ctx->P, &ctx->Q ); + + /* Temporarily replace P,Q by P-1, Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &ctx->Q, &ctx->Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &H, &ctx->P, &ctx->Q ) ); + + /* check GCD( E, (P-1)*(Q-1) ) == 1 (FIPS 186-4 §B.3.1 criterion 2(a)) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->E, &H ) ); + if( mbedtls_mpi_cmp_int( &G, 1 ) != 0 ) + continue; + + /* compute smallest possible D = E^-1 mod LCM(P-1, Q-1) (FIPS 186-4 §B.3.1 criterion 3(b)) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &G, &ctx->P, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &L, NULL, &H, &G ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->D, &ctx->E, &L ) ); + + if( mbedtls_mpi_bitlen( &ctx->D ) <= ( ( nbits + 1 ) / 2 ) ) // (FIPS 186-4 §B.3.1 criterion 3(a)) + continue; + + break; + } + while( 1 ); + + /* Restore P,Q */ + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->P, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &ctx->Q, &ctx->Q, 1 ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); + + ctx->len = mbedtls_mpi_size( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* + * DP = D mod (P - 1) + * DQ = D mod (Q - 1) + * QP = Q^-1 mod P + */ + MBEDTLS_MPI_CHK( mbedtls_rsa_deduce_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Double-check */ + MBEDTLS_MPI_CHK( mbedtls_rsa_check_privkey( ctx ) ); + +cleanup: + + mbedtls_mpi_free( &H ); + mbedtls_mpi_free( &G ); + mbedtls_mpi_free( &L ); + + if( ret != 0 ) + { + mbedtls_rsa_free( ctx ); + return( MBEDTLS_ERR_RSA_KEY_GEN_FAILED + ret ); + } + + return( 0 ); +} + +#endif /* MBEDTLS_GENPRIME */ + +/* + * Check a public RSA key + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ) +{ + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) != 0 ) + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + + if( mbedtls_mpi_bitlen( &ctx->N ) < 128 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_mpi_get_bit( &ctx->E, 0 ) == 0 || + mbedtls_mpi_bitlen( &ctx->E ) < 2 || + mbedtls_mpi_cmp_mpi( &ctx->E, &ctx->N ) >= 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Check for the consistency of all fields in an RSA private key context + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ) +{ + if( mbedtls_rsa_check_pubkey( ctx ) != 0 || + rsa_check_context( ctx, 1 /* private */, 1 /* blinding */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_rsa_validate_params( &ctx->N, &ctx->P, &ctx->Q, + &ctx->D, &ctx->E, NULL, NULL ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + else if( mbedtls_rsa_validate_crt( &ctx->P, &ctx->Q, &ctx->D, + &ctx->DP, &ctx->DQ, &ctx->QP ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } +#endif + + return( 0 ); +} + +/* + * Check if contexts holding a public and private key match + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ) +{ + if( mbedtls_rsa_check_pubkey( pub ) != 0 || + mbedtls_rsa_check_privkey( prv ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + if( mbedtls_mpi_cmp_mpi( &pub->N, &prv->N ) != 0 || + mbedtls_mpi_cmp_mpi( &pub->E, &prv->E ) != 0 ) + { + return( MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ); + } + + return( 0 ); +} + +/* + * Do an RSA public key operation + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t olen; + mbedtls_mpi T; + + if( rsa_check_context( ctx, 0 /* public */, 0 /* no blinding */ ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + mbedtls_mpi_init( &T ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &T ); + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_PUBLIC_FAILED + ret ); + + return( 0 ); +} + +/* + * Generate or update blinding values, see section 10 of: + * KOCHER, Paul C. Timing attacks on implementations of Diffie-Hellman, RSA, + * DSS, and other systems. In : Advances in Cryptology-CRYPTO'96. Springer + * Berlin Heidelberg, 1996. p. 104-113. + */ +static int rsa_prepare_blinding( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), void *p_rng ) +{ + int ret, count = 0; + + if( ctx->Vf.p != NULL ) + { + /* We already have blinding values, just update them by squaring */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vi, &ctx->Vi, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vi, &ctx->Vi, &ctx->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &ctx->Vf, &ctx->Vf, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &ctx->Vf, &ctx->Vf, &ctx->N ) ); + + goto cleanup; + } + + /* Unblinding value: Vf = random number, invertible mod N */ + do { + if( count++ > 10 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &ctx->Vf, ctx->len - 1, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( &ctx->Vi, &ctx->Vf, &ctx->N ) ); + } while( mbedtls_mpi_cmp_int( &ctx->Vi, 1 ) != 0 ); + + /* Blinding value: Vi = Vf^(-e) mod N */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( &ctx->Vi, &ctx->Vf, &ctx->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &ctx->Vi, &ctx->Vi, &ctx->E, &ctx->N, &ctx->RN ) ); + + +cleanup: + return( ret ); +} + +/* + * Exponent blinding supposed to prevent side-channel attacks using multiple + * traces of measurements to recover the RSA key. The more collisions are there, + * the more bits of the key can be recovered. See [3]. + * + * Collecting n collisions with m bit long blinding value requires 2^(m-m/n) + * observations on avarage. + * + * For example with 28 byte blinding to achieve 2 collisions the adversary has + * to make 2^112 observations on avarage. + * + * (With the currently (as of 2017 April) known best algorithms breaking 2048 + * bit RSA requires approximately as much time as trying out 2^112 random keys. + * Thus in this sense with 28 byte blinding the security is not reduced by + * side-channel attacks like the one in [3]) + * + * This countermeasure does not help if the key recovery is possible with a + * single trace. + */ +#define RSA_EXPONENT_BLINDING 28 + +/* + * Do an RSA private key operation + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ) +{ + int ret; + size_t olen; + + /* Temporary holding the result */ + mbedtls_mpi T; + + /* Temporaries holding P-1, Q-1 and the + * exponent blinding factor, respectively. */ + mbedtls_mpi P1, Q1, R; + +#if !defined(MBEDTLS_RSA_NO_CRT) + /* Temporaries holding the results mod p resp. mod q. */ + mbedtls_mpi TP, TQ; + + /* Temporaries holding the blinded exponents for + * the mod p resp. mod q computation (if used). */ + mbedtls_mpi DP_blind, DQ_blind; + + /* Pointers to actual exponents to be used - either the unblinded + * or the blinded ones, depending on the presence of a PRNG. */ + mbedtls_mpi *DP = &ctx->DP; + mbedtls_mpi *DQ = &ctx->DQ; +#else + /* Temporary holding the blinded exponent (if used). */ + mbedtls_mpi D_blind; + + /* Pointer to actual exponent to be used - either the unblinded + * or the blinded one, depending on the presence of a PRNG. */ + mbedtls_mpi *D = &ctx->D; +#endif /* MBEDTLS_RSA_NO_CRT */ + + /* Temporaries holding the initial input and the double + * checked result; should be the same in the end. */ + mbedtls_mpi I, C; + + if( rsa_check_context( ctx, 1 /* private key checks */, + f_rng != NULL /* blinding y/n */ ) != 0 ) + { + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &ctx->mutex ) ) != 0 ) + return( ret ); +#endif + + /* MPI Initialization */ + mbedtls_mpi_init( &T ); + + mbedtls_mpi_init( &P1 ); + mbedtls_mpi_init( &Q1 ); + mbedtls_mpi_init( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &D_blind ); +#else + mbedtls_mpi_init( &DP_blind ); + mbedtls_mpi_init( &DQ_blind ); +#endif + } + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_init( &TP ); mbedtls_mpi_init( &TQ ); +#endif + + mbedtls_mpi_init( &I ); + mbedtls_mpi_init( &C ); + + /* End of MPI initialization */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary( &T, input, ctx->len ) ); + if( mbedtls_mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &I, &T ) ); + + if( f_rng != NULL ) + { + /* + * Blinding + * T = T * Vi mod N + */ + MBEDTLS_MPI_CHK( rsa_prepare_blinding( ctx, f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + + /* + * Exponent blinding + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &P1, &ctx->P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &Q1, &ctx->Q, 1 ) ); + +#if defined(MBEDTLS_RSA_NO_CRT) + /* + * D_blind = ( P - 1 ) * ( Q - 1 ) * R + D + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &P1, &Q1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &D_blind, &D_blind, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &D_blind, &D_blind, &ctx->D ) ); + + D = &D_blind; +#else + /* + * DP_blind = ( P - 1 ) * R + DP + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DP_blind, &P1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DP_blind, &DP_blind, + &ctx->DP ) ); + + DP = &DP_blind; + + /* + * DQ_blind = ( Q - 1 ) * R + DQ + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_fill_random( &R, RSA_EXPONENT_BLINDING, + f_rng, p_rng ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &DQ_blind, &Q1, &R ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &DQ_blind, &DQ_blind, + &ctx->DQ ) ); + + DQ = &DQ_blind; +#endif /* MBEDTLS_RSA_NO_CRT */ + } + +#if defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &T, &T, D, &ctx->N, &ctx->RN ) ); +#else + /* + * Faster decryption using the CRT + * + * TP = input ^ dP mod P + * TQ = input ^ dQ mod Q + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TP, &T, DP, &ctx->P, &ctx->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &TQ, &T, DQ, &ctx->Q, &ctx->RQ ) ); + + /* + * T = (TP - TQ) * (Q^-1 mod P) mod P + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &T, &TP, &TQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &TP, &ctx->P ) ); + + /* + * T = TQ + T * Q + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &TP, &T, &ctx->Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_add_mpi( &T, &TQ, &TP ) ); +#endif /* MBEDTLS_RSA_NO_CRT */ + + if( f_rng != NULL ) + { + /* + * Unblind + * T = T * Vf mod N + */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, &T, &ctx->Vf ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &T, &T, &ctx->N ) ); + } + + /* Verify the result to prevent glitching attacks. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &C, &T, &ctx->E, + &ctx->N, &ctx->RN ) ); + if( mbedtls_mpi_cmp_mpi( &C, &I ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + + olen = ctx->len; + MBEDTLS_MPI_CHK( mbedtls_mpi_write_binary( &T, output, olen ) ); + +cleanup: +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &ctx->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); +#endif + + mbedtls_mpi_free( &P1 ); + mbedtls_mpi_free( &Q1 ); + mbedtls_mpi_free( &R ); + + if( f_rng != NULL ) + { +#if defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &D_blind ); +#else + mbedtls_mpi_free( &DP_blind ); + mbedtls_mpi_free( &DQ_blind ); +#endif + } + + mbedtls_mpi_free( &T ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &TP ); mbedtls_mpi_free( &TQ ); +#endif + + mbedtls_mpi_free( &C ); + mbedtls_mpi_free( &I ); + + if( ret != 0 ) + return( MBEDTLS_ERR_RSA_PRIVATE_FAILED + ret ); + + return( 0 ); +} + +#if defined(MBEDTLS_PKCS1_V21) +/** + * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. + * + * \param dst buffer to mask + * \param dlen length of destination buffer + * \param src source of the mask generation + * \param slen length of the source buffer + * \param md_ctx message digest context to use + */ +static int mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, + size_t slen, mbedtls_md_context_t *md_ctx ) +{ + unsigned char mask[MBEDTLS_MD_MAX_SIZE]; + unsigned char counter[4]; + unsigned char *p; + unsigned int hlen; + size_t i, use_len; + int ret = 0; + + memset( mask, 0, MBEDTLS_MD_MAX_SIZE ); + memset( counter, 0, 4 ); + + hlen = mbedtls_md_get_size( md_ctx->md_info ); + + /* Generate and apply dbMask */ + p = dst; + + while( dlen > 0 ) + { + use_len = hlen; + if( dlen < hlen ) + use_len = dlen; + + if( ( ret = mbedtls_md_starts( md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, src, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( md_ctx, counter, 4 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( md_ctx, mask ) ) != 0 ) + goto exit; + + for( i = 0; i < use_len; ++i ) + *p++ ^= mask[i]; + + counter[3]++; + + dlen -= use_len; + } + +exit: + mbedtls_platform_zeroize( mask, sizeof( mask ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t olen; + int ret; + unsigned char *p = output; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + hlen = mbedtls_md_get_size( md_info ); + + /* first comparison checks for overflow */ + if( ilen + 2 * hlen + 2 < ilen || olen < ilen + 2 * hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + memset( output, 0, olen ); + + *p++ = 0; + + /* Generate a random octet string seed */ + if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + p += hlen; + + /* Construct DB */ + if( ( ret = mbedtls_md( md_info, label, label_len, p ) ) != 0 ) + return( ret ); + p += hlen; + p += olen - 2 * hlen - 2 - ilen; + *p++ = 1; + memcpy( p, input, ilen ); + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + /* maskedSeed: Apply seedMask to seed */ + if( ( ret = mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, + &md_ctx ) ) != 0 ) + goto exit; + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, output, output ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + size_t nb_pad, olen; + int ret; + unsigned char *p = output; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + // We don't check p_rng because it won't be dereferenced here + if( f_rng == NULL || input == NULL || output == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + /* first comparison checks for overflow */ + if( ilen + 11 < ilen || olen < ilen + 11 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad = olen - 3 - ilen; + + *p++ = 0; + if( mode == MBEDTLS_RSA_PUBLIC ) + { + *p++ = MBEDTLS_RSA_CRYPT; + + while( nb_pad-- > 0 ) + { + int rng_dl = 100; + + do { + ret = f_rng( p_rng, p, 1 ); + } while( *p == 0 && --rng_dl && ret == 0 ); + + /* Check if RNG failed to generate data */ + if( rng_dl == 0 || ret != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + p++; + } + } + else + { + *p++ = MBEDTLS_RSA_SIGN; + + while( nb_pad-- > 0 ) + *p++ = 0xFF; + } + + *p++ = 0; + memcpy( p, input, ilen ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, output, output ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, output, output ) ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Add the message padding, then do an RSA operation + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ) +{ + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, + input, output ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, + ilen, input, output ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ) +{ + int ret; + size_t ilen, i, pad_len; + unsigned char *p, bad, pad_done; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + unsigned char lhash[MBEDTLS_MD_MAX_SIZE]; + unsigned int hlen; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + /* + * Parameters sanity checks + */ + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + // checking for integer underflow + if( 2 * hlen + 2 > ilen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * RSA operation + */ + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + /* + * Unmask data and generate lHash + */ + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + /* seed: Apply seedMask to maskedSeed */ + if( ( ret = mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, + &md_ctx ) ) != 0 || + /* DB: Apply dbMask to maskedDB */ + ( ret = mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, + &md_ctx ) ) != 0 ) + { + mbedtls_md_free( &md_ctx ); + goto cleanup; + } + + mbedtls_md_free( &md_ctx ); + + /* Generate lHash */ + if( ( ret = mbedtls_md( md_info, label, label_len, lhash ) ) != 0 ) + goto cleanup; + + /* + * Check contents, in "constant-time" + */ + p = buf; + bad = 0; + + bad |= *p++; /* First byte must be 0 */ + + p += hlen; /* Skip seed */ + + /* Check lHash */ + for( i = 0; i < hlen; i++ ) + bad |= lhash[i] ^ *p++; + + /* Get zero-padding len, but always read till end of buffer + * (minus one, for the 01 byte) */ + pad_len = 0; + pad_done = 0; + for( i = 0; i < ilen - 2 * hlen - 2; i++ ) + { + pad_done |= p[i]; + pad_len += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + + p += pad_len; + bad |= *p++ ^ 0x01; + + /* + * The only information "leaked" is whether the padding was correct or not + * (eg, no data is copied if it was not correct). This meets the + * recommendations in PKCS#1 v2.2: an opponent cannot distinguish between + * the different error conditions. + */ + if( bad != 0 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto cleanup; + } + + if( ilen - ( p - buf ) > output_max_len ) + { + ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + goto cleanup; + } + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + ret = 0; + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + mbedtls_platform_zeroize( lhash, sizeof( lhash ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) +{ + int ret; + size_t ilen, pad_count = 0, i; + unsigned char *p, bad, pad_done = 0; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ilen = ctx->len; + + if( ilen < 16 || ilen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, input, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, input, buf ); + + if( ret != 0 ) + goto cleanup; + + p = buf; + bad = 0; + + /* + * Check and get padding len in "constant-time" + */ + bad |= *p++; /* First byte must be 0 */ + + /* This test does not depend on secret data */ + if( mode == MBEDTLS_RSA_PRIVATE ) + { + bad |= *p++ ^ MBEDTLS_RSA_CRYPT; + + /* Get padding len, but always read till end of buffer + * (minus one, for the 00 byte) */ + for( i = 0; i < ilen - 3; i++ ) + { + pad_done |= ((p[i] | (unsigned char)-p[i]) >> 7) ^ 1; + pad_count += ((pad_done | (unsigned char)-pad_done) >> 7) ^ 1; + } + + p += pad_count; + bad |= *p++; /* Must be zero */ + } + else + { + bad |= *p++ ^ MBEDTLS_RSA_SIGN; + + /* Get padding len, but always read till end of buffer + * (minus one, for the 00 byte) */ + for( i = 0; i < ilen - 3; i++ ) + { + pad_done |= ( p[i] != 0xFF ); + pad_count += ( pad_done == 0 ); + } + + p += pad_count; + bad |= *p++; /* Must be zero */ + } + + bad |= ( pad_count < 8 ); + + if( bad ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto cleanup; + } + + if( ilen - ( p - buf ) > output_max_len ) + { + ret = MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE; + goto cleanup; + } + + *olen = ilen - (p - buf); + memcpy( output, p, *olen ); + ret = 0; + +cleanup: + mbedtls_platform_zeroize( buf, sizeof( buf ) ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation, then remove the message padding + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len) +{ + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsaes_pkcs1_v15_decrypt( ctx, f_rng, p_rng, mode, olen, + input, output, output_max_len ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsaes_oaep_decrypt( ctx, f_rng, p_rng, mode, NULL, 0, + olen, input, output, + output_max_len ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + size_t olen; + unsigned char *p = sig; + unsigned char salt[MBEDTLS_MD_MAX_SIZE]; + unsigned int slen, hlen, offset = 0; + int ret; + size_t msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( f_rng == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + olen = ctx->len; + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + } + + md_info = mbedtls_md_info_from_type( (mbedtls_md_type_t) ctx->hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + slen = hlen; + + if( olen < hlen + slen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + memset( sig, 0, olen ); + + /* Generate salt of length slen */ + if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) + return( MBEDTLS_ERR_RSA_RNG_FAILED + ret ); + + /* Note: EMSA-PSS encoding is over the length of N - 1 bits */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + p += olen - hlen * 2 - 2; + *p++ = 0x01; + memcpy( p, salt, slen ); + p += slen; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + /* Generate H = Hash( M' ) */ + if( ( ret = mbedtls_md_starts( &md_ctx ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, p, 8 ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, hash, hashlen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_update( &md_ctx, salt, slen ) ) != 0 ) + goto exit; + if( ( ret = mbedtls_md_finish( &md_ctx, p ) ) != 0 ) + goto exit; + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + offset = 1; + + /* maskedDB: Apply dbMask to DB */ + if( ( ret = mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, + &md_ctx ) ) != 0 ) + goto exit; + + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + sig[0] &= 0xFF >> ( olen * 8 - msb ); + + p += hlen; + *p++ = 0xBC; + + mbedtls_platform_zeroize( salt, sizeof( salt ) ); + +exit: + mbedtls_md_free( &md_ctx ); + + if( ret != 0 ) + return( ret ); + + return( ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, sig ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig ) ); +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function + */ + +/* Construct a PKCS v1.5 encoding of a hashed message + * + * This is used both for signature generation and verification. + * + * Parameters: + * - md_alg: Identifies the hash algorithm used to generate the given hash; + * MBEDTLS_MD_NONE if raw data is signed. + * - hashlen: Length of hash in case hashlen is MBEDTLS_MD_NONE. + * - hash: Buffer containing the hashed message or the raw data. + * - dst_len: Length of the encoded message. + * - dst: Buffer to hold the encoded message. + * + * Assumptions: + * - hash has size hashlen if md_alg == MBEDTLS_MD_NONE. + * - hash has size corresponding to md_alg if md_alg != MBEDTLS_MD_NONE. + * - dst points to a buffer of size at least dst_len. + * + */ +static int rsa_rsassa_pkcs1_v15_encode( mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + size_t dst_len, + unsigned char *dst ) +{ + size_t oid_size = 0; + size_t nb_pad = dst_len; + unsigned char *p = dst; + const char *oid = NULL; + + /* Are we signing hashed or raw data? */ + if( md_alg != MBEDTLS_MD_NONE ) + { + const mbedtls_md_info_t *md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + if( mbedtls_oid_get_oid_by_md( md_alg, &oid, &oid_size ) != 0 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + + /* Double-check that 8 + hashlen + oid_size can be used as a + * 1-byte ASN.1 length encoding and that there's no overflow. */ + if( 8 + hashlen + oid_size >= 0x80 || + 10 + hashlen < hashlen || + 10 + hashlen + oid_size < 10 + hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Static bounds check: + * - Need 10 bytes for five tag-length pairs. + * (Insist on 1-byte length encodings to protect against variants of + * Bleichenbacher's forgery attack against lax PKCS#1v1.5 verification) + * - Need hashlen bytes for hash + * - Need oid_size bytes for hash alg OID. + */ + if( nb_pad < 10 + hashlen + oid_size ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 10 + hashlen + oid_size; + } + else + { + if( nb_pad < hashlen ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + nb_pad -= hashlen; + } + + /* Need space for signature header and padding delimiter (3 bytes), + * and 8 bytes for the minimal padding */ + if( nb_pad < 3 + 8 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + nb_pad -= 3; + + /* Now nb_pad is the amount of memory to be filled + * with padding, and at least 8 bytes long. */ + + /* Write signature header and padding */ + *p++ = 0; + *p++ = MBEDTLS_RSA_SIGN; + memset( p, 0xFF, nb_pad ); + p += nb_pad; + *p++ = 0; + + /* Are we signing raw data? */ + if( md_alg == MBEDTLS_MD_NONE ) + { + memcpy( p, hash, hashlen ); + return( 0 ); + } + + /* Signing hashed data, add corresponding ASN.1 structure + * + * DigestInfo ::= SEQUENCE { + * digestAlgorithm DigestAlgorithmIdentifier, + * digest Digest } + * DigestAlgorithmIdentifier ::= AlgorithmIdentifier + * Digest ::= OCTET STRING + * + * Schematic: + * TAG-SEQ + LEN [ TAG-SEQ + LEN [ TAG-OID + LEN [ OID ] + * TAG-NULL + LEN [ NULL ] ] + * TAG-OCTET + LEN [ HASH ] ] + */ + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x08 + oid_size + hashlen ); + *p++ = MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED; + *p++ = (unsigned char)( 0x04 + oid_size ); + *p++ = MBEDTLS_ASN1_OID; + *p++ = (unsigned char) oid_size; + memcpy( p, oid, oid_size ); + p += oid_size; + *p++ = MBEDTLS_ASN1_NULL; + *p++ = 0x00; + *p++ = MBEDTLS_ASN1_OCTET_STRING; + *p++ = (unsigned char) hashlen; + memcpy( p, hash, hashlen ); + p += hashlen; + + /* Just a sanity-check, should be automatic + * after the initial bounds check. */ + if( p != dst + dst_len ) + { + mbedtls_platform_zeroize( dst, dst_len ); + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + } + + return( 0 ); +} + +/* + * Do an RSA operation to sign the message digest + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + int ret; + unsigned char *sig_try = NULL, *verif = NULL; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Prepare PKCS1-v1.5 encoding (padding and hash identifier) + */ + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, + ctx->len, sig ) ) != 0 ) + return( ret ); + + /* + * Call respective RSA primitive + */ + + if( mode == MBEDTLS_RSA_PUBLIC ) + { + /* Skip verification on a public key operation */ + return( mbedtls_rsa_public( ctx, sig, sig ) ); + } + + /* Private key operation + * + * In order to prevent Lenstra's attack, make the signature in a + * temporary buffer and check it before returning it. + */ + + sig_try = mbedtls_calloc( 1, ctx->len ); + if( sig_try == NULL ) + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + + verif = mbedtls_calloc( 1, ctx->len ); + if( verif == NULL ) + { + mbedtls_free( sig_try ); + return( MBEDTLS_ERR_MPI_ALLOC_FAILED ); + } + + MBEDTLS_MPI_CHK( mbedtls_rsa_private( ctx, f_rng, p_rng, sig, sig_try ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_public( ctx, sig_try, verif ) ); + + if( mbedtls_safer_memcmp( verif, sig, ctx->len ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_PRIVATE_FAILED; + goto cleanup; + } + + memcpy( sig, sig_try, ctx->len ); + +cleanup: + mbedtls_free( sig_try ); + mbedtls_free( verif ); + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation to sign the message digest + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ) +{ + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +#if defined(MBEDTLS_PKCS1_V21) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ) +{ + int ret; + size_t siglen; + unsigned char *p; + unsigned char *hash_start; + unsigned char result[MBEDTLS_MD_MAX_SIZE]; + unsigned char zeros[8]; + unsigned int hlen; + size_t observed_salt_len, msb; + const mbedtls_md_info_t *md_info; + mbedtls_md_context_t md_ctx; + unsigned char buf[MBEDTLS_MPI_MAX_SIZE]; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V21 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + siglen = ctx->len; + + if( siglen < 16 || siglen > sizeof( buf ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, buf ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, buf ); + + if( ret != 0 ) + return( ret ); + + p = buf; + + if( buf[siglen - 1] != 0xBC ) + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + + if( md_alg != MBEDTLS_MD_NONE ) + { + /* Gather length of hash to sign */ + md_info = mbedtls_md_info_from_type( md_alg ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hashlen = mbedtls_md_get_size( md_info ); + } + + md_info = mbedtls_md_info_from_type( mgf1_hash_id ); + if( md_info == NULL ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + hlen = mbedtls_md_get_size( md_info ); + + memset( zeros, 0, 8 ); + + /* + * Note: EMSA-PSS verification is over the length of N - 1 bits + */ + msb = mbedtls_mpi_bitlen( &ctx->N ) - 1; + + if( buf[0] >> ( 8 - siglen * 8 + msb ) ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* Compensate for boundary condition when applying mask */ + if( msb % 8 == 0 ) + { + p++; + siglen -= 1; + } + + if( siglen < hlen + 2 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + hash_start = p + siglen - hlen - 1; + + mbedtls_md_init( &md_ctx ); + if( ( ret = mbedtls_md_setup( &md_ctx, md_info, 0 ) ) != 0 ) + goto exit; + + ret = mgf_mask( p, siglen - hlen - 1, hash_start, hlen, &md_ctx ); + if( ret != 0 ) + goto exit; + + buf[0] &= 0xFF >> ( siglen * 8 - msb ); + + while( p < hash_start - 1 && *p == 0 ) + p++; + + if( *p++ != 0x01 ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + observed_salt_len = hash_start - p; + + if( expected_salt_len != MBEDTLS_RSA_SALT_LEN_ANY && + observed_salt_len != (size_t) expected_salt_len ) + { + ret = MBEDTLS_ERR_RSA_INVALID_PADDING; + goto exit; + } + + /* + * Generate H = Hash( M' ) + */ + ret = mbedtls_md_starts( &md_ctx ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, zeros, 8 ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, hash, hashlen ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_update( &md_ctx, p, observed_salt_len ); + if ( ret != 0 ) + goto exit; + ret = mbedtls_md_finish( &md_ctx, result ); + if ( ret != 0 ) + goto exit; + + if( memcmp( hash_start, result, hlen ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto exit; + } + +exit: + mbedtls_md_free( &md_ctx ); + + return( ret ); +} + +/* + * Simplified PKCS#1 v2.1 RSASSA-PSS-VERIFY function + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + mbedtls_md_type_t mgf1_hash_id = ( ctx->hash_id != MBEDTLS_MD_NONE ) + ? (mbedtls_md_type_t) ctx->hash_id + : md_alg; + + return( mbedtls_rsa_rsassa_pss_verify_ext( ctx, f_rng, p_rng, mode, + md_alg, hashlen, hash, + mgf1_hash_id, MBEDTLS_RSA_SALT_LEN_ANY, + sig ) ); + +} +#endif /* MBEDTLS_PKCS1_V21 */ + +#if defined(MBEDTLS_PKCS1_V15) +/* + * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + int ret = 0; + const size_t sig_len = ctx->len; + unsigned char *encoded = NULL, *encoded_expected = NULL; + + if( mode == MBEDTLS_RSA_PRIVATE && ctx->padding != MBEDTLS_RSA_PKCS_V15 ) + return( MBEDTLS_ERR_RSA_BAD_INPUT_DATA ); + + /* + * Prepare expected PKCS1 v1.5 encoding of hash. + */ + + if( ( encoded = mbedtls_calloc( 1, sig_len ) ) == NULL || + ( encoded_expected = mbedtls_calloc( 1, sig_len ) ) == NULL ) + { + ret = MBEDTLS_ERR_MPI_ALLOC_FAILED; + goto cleanup; + } + + if( ( ret = rsa_rsassa_pkcs1_v15_encode( md_alg, hashlen, hash, sig_len, + encoded_expected ) ) != 0 ) + goto cleanup; + + /* + * Apply RSA primitive to get what should be PKCS1 encoded hash. + */ + + ret = ( mode == MBEDTLS_RSA_PUBLIC ) + ? mbedtls_rsa_public( ctx, sig, encoded ) + : mbedtls_rsa_private( ctx, f_rng, p_rng, sig, encoded ); + if( ret != 0 ) + goto cleanup; + + /* + * Compare + */ + + if( ( ret = mbedtls_safer_memcmp( encoded, encoded_expected, + sig_len ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_VERIFY_FAILED; + goto cleanup; + } + +cleanup: + + if( encoded != NULL ) + { + mbedtls_platform_zeroize( encoded, sig_len ); + mbedtls_free( encoded ); + } + + if( encoded_expected != NULL ) + { + mbedtls_platform_zeroize( encoded_expected, sig_len ); + mbedtls_free( encoded_expected ); + } + + return( ret ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Do an RSA operation and check the message digest + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ) +{ + switch( ctx->padding ) + { +#if defined(MBEDTLS_PKCS1_V15) + case MBEDTLS_RSA_PKCS_V15: + return mbedtls_rsa_rsassa_pkcs1_v15_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + +#if defined(MBEDTLS_PKCS1_V21) + case MBEDTLS_RSA_PKCS_V21: + return mbedtls_rsa_rsassa_pss_verify( ctx, f_rng, p_rng, mode, md_alg, + hashlen, hash, sig ); +#endif + + default: + return( MBEDTLS_ERR_RSA_INVALID_PADDING ); + } +} + +/* + * Copy the components of an RSA key + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ) +{ + int ret; + + dst->ver = src->ver; + dst->len = src->len; + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->N, &src->N ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->E, &src->E ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->D, &src->D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->P, &src->P ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Q, &src->Q ) ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DP, &src->DP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->DQ, &src->DQ ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->QP, &src->QP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RP, &src->RP ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RQ, &src->RQ ) ); +#endif + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->RN, &src->RN ) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vi, &src->Vi ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_copy( &dst->Vf, &src->Vf ) ); + + dst->padding = src->padding; + dst->hash_id = src->hash_id; + +cleanup: + if( ret != 0 ) + mbedtls_rsa_free( dst ); + + return( ret ); +} + +/* + * Free the components of an RSA key + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ) +{ + mbedtls_mpi_free( &ctx->Vi ); mbedtls_mpi_free( &ctx->Vf ); + mbedtls_mpi_free( &ctx->RN ); mbedtls_mpi_free( &ctx->D ); + mbedtls_mpi_free( &ctx->Q ); mbedtls_mpi_free( &ctx->P ); + mbedtls_mpi_free( &ctx->E ); mbedtls_mpi_free( &ctx->N ); + +#if !defined(MBEDTLS_RSA_NO_CRT) + mbedtls_mpi_free( &ctx->RQ ); mbedtls_mpi_free( &ctx->RP ); + mbedtls_mpi_free( &ctx->QP ); mbedtls_mpi_free( &ctx->DQ ); + mbedtls_mpi_free( &ctx->DP ); +#endif /* MBEDTLS_RSA_NO_CRT */ + +#if defined(MBEDTLS_THREADING_C) + mbedtls_mutex_free( &ctx->mutex ); +#endif +} + +#endif /* !MBEDTLS_RSA_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +#include "mbedtls/sha1.h" + +/* + * Example RSA-1024 keypair, for test purposes + */ +#define KEY_LEN 128 + +#define RSA_N "9292758453063D803DD603D5E777D788" \ + "8ED1D5BF35786190FA2F23EBC0848AEA" \ + "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ + "7130B9CED7ACDF54CFC7555AC14EEBAB" \ + "93A89813FBF3C4F8066D2D800F7C38A8" \ + "1AE31942917403FF4946B0A83D3D3E05" \ + "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ + "5E94BB77B07507233A0BC7BAC8F90F79" + +#define RSA_E "10001" + +#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ + "66CA472BC44D253102F8B4A9D3BFA750" \ + "91386C0077937FE33FA3252D28855837" \ + "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ + "DF79C5CE07EE72C7F123142198164234" \ + "CABB724CF78B8173B9F880FC86322407" \ + "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ + "071513A1E85B5DFA031F21ECAE91A34D" + +#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ + "2C01CAD19EA484A87EA4377637E75500" \ + "FCB2005C5C7DD6EC4AC023CDA285D796" \ + "C3D9E75E1EFC42488BB4F1D13AC30A57" + +#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ + "E211C2B9E5DB1ED0BF61D0D9899620F4" \ + "910E4168387E3C30AA1E00C339A79508" \ + "8452DD96A9A5EA5D9DCA68DA636032AF" + +#define PT_LEN 24 +#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ + "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" + +#if defined(MBEDTLS_PKCS1_V15) +static int myrand( void *rng_state, unsigned char *output, size_t len ) +{ +#if !defined(__OpenBSD__) + size_t i; + + if( rng_state != NULL ) + rng_state = NULL; + + for( i = 0; i < len; ++i ) + output[i] = rand(); +#else + if( rng_state != NULL ) + rng_state = NULL; + + arc4random_buf( output, len ); +#endif /* !OpenBSD */ + + return( 0 ); +} +#endif /* MBEDTLS_PKCS1_V15 */ + +/* + * Checkup routine + */ +int mbedtls_rsa_self_test( int verbose ) +{ + int ret = 0; +#if defined(MBEDTLS_PKCS1_V15) + size_t len; + mbedtls_rsa_context rsa; + unsigned char rsa_plaintext[PT_LEN]; + unsigned char rsa_decrypted[PT_LEN]; + unsigned char rsa_ciphertext[KEY_LEN]; +#if defined(MBEDTLS_SHA1_C) + unsigned char sha1sum[20]; +#endif + + mbedtls_mpi K; + + mbedtls_mpi_init( &K ); + mbedtls_rsa_init( &rsa, MBEDTLS_RSA_PKCS_V15, 0 ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_N ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, &K, NULL, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_P ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, &K, NULL, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_Q ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, &K, NULL, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_D ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, &K, NULL ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string( &K, 16, RSA_E ) ); + MBEDTLS_MPI_CHK( mbedtls_rsa_import( &rsa, NULL, NULL, NULL, NULL, &K ) ); + + MBEDTLS_MPI_CHK( mbedtls_rsa_complete( &rsa ) ); + + if( verbose != 0 ) + mbedtls_printf( " RSA key validation: " ); + + if( mbedtls_rsa_check_pubkey( &rsa ) != 0 || + mbedtls_rsa_check_privkey( &rsa ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 encryption : " ); + + memcpy( rsa_plaintext, RSA_PT, PT_LEN ); + + if( mbedtls_rsa_pkcs1_encrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PUBLIC, + PT_LEN, rsa_plaintext, + rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 decryption : " ); + + if( mbedtls_rsa_pkcs1_decrypt( &rsa, myrand, NULL, MBEDTLS_RSA_PRIVATE, + &len, rsa_ciphertext, rsa_decrypted, + sizeof(rsa_decrypted) ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +#if defined(MBEDTLS_SHA1_C) + if( verbose != 0 ) + mbedtls_printf( " PKCS#1 data sign : " ); + + if( mbedtls_sha1_ret( rsa_plaintext, PT_LEN, sha1sum ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( 1 ); + } + + if( mbedtls_rsa_pkcs1_sign( &rsa, myrand, NULL, + MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n PKCS#1 sig. verify: " ); + + if( mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, + MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 0, + sha1sum, rsa_ciphertext ) != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + ret = 1; + goto cleanup; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); +#endif /* MBEDTLS_SHA1_C */ + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + +cleanup: + mbedtls_mpi_free( &K ); + mbedtls_rsa_free( &rsa ); +#else /* MBEDTLS_PKCS1_V15 */ + ((void) verbose); +#endif /* MBEDTLS_PKCS1_V15 */ + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_RSA_C */ diff --git a/common/mbedtls/rsa.h b/common/mbedtls/rsa.h new file mode 100644 index 000000000..7be7863c8 --- /dev/null +++ b/common/mbedtls/rsa.h @@ -0,0 +1,1133 @@ +/** + * \file rsa.h + * + * \brief This file provides an API for the RSA public-key cryptosystem. + * + * The RSA public-key cryptosystem is defined in Public-Key + * Cryptography Standards (PKCS) #1 v1.5: RSA Encryption + * and Public-Key Cryptography Standards (PKCS) #1 v2.1: + * RSA Cryptography Specifications. + * + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_RSA_H +#define MBEDTLS_RSA_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.h" +#include "md.h" + +#if defined(MBEDTLS_THREADING_C) +#include "threading.h" +#endif + +/* + * RSA Error codes + */ +#define MBEDTLS_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ +#define MBEDTLS_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ +#define MBEDTLS_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the validity check of the library. */ +#define MBEDTLS_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ +#define MBEDTLS_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ +#define MBEDTLS_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ +#define MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ +#define MBEDTLS_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ +#define MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION -0x4500 /**< The implementation does not offer the requested operation, for example, because of security violations or lack of functionality. */ +#define MBEDTLS_ERR_RSA_HW_ACCEL_FAILED -0x4580 /**< RSA hardware accelerator failed. */ + +/* + * RSA constants + */ +#define MBEDTLS_RSA_PUBLIC 0 /**< Request private key operation. */ +#define MBEDTLS_RSA_PRIVATE 1 /**< Request public key operation. */ + +#define MBEDTLS_RSA_PKCS_V15 0 /**< Use PKCS#1 v1.5 encoding. */ +#define MBEDTLS_RSA_PKCS_V21 1 /**< Use PKCS#1 v2.1 encoding. */ + +#define MBEDTLS_RSA_SIGN 1 /**< Identifier for RSA signature operations. */ +#define MBEDTLS_RSA_CRYPT 2 /**< Identifier for RSA encryption and decryption operations. */ + +#define MBEDTLS_RSA_SALT_LEN_ANY -1 + +/* + * The above constants may be used even if the RSA module is compile out, + * eg for alternative (PKCS#11) RSA implemenations in the PK layers. + */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_RSA_ALT) +// Regular implementation +// + +/** + * \brief The RSA context structure. + * + * \note Direct manipulation of the members of this structure + * is deprecated. All manipulation should instead be done through + * the public interface functions. + */ +typedef struct mbedtls_rsa_context +{ + int ver; /*!< Always 0.*/ + size_t len; /*!< The size of \p N in Bytes. */ + + mbedtls_mpi N; /*!< The public modulus. */ + mbedtls_mpi E; /*!< The public exponent. */ + + mbedtls_mpi D; /*!< The private exponent. */ + mbedtls_mpi P; /*!< The first prime factor. */ + mbedtls_mpi Q; /*!< The second prime factor. */ + + mbedtls_mpi DP; /*!< D % (P - 1). */ + mbedtls_mpi DQ; /*!< D % (Q - 1). */ + mbedtls_mpi QP; /*!< 1 / (Q % P). */ + + mbedtls_mpi RN; /*!< cached R^2 mod N. */ + + mbedtls_mpi RP; /*!< cached R^2 mod P. */ + mbedtls_mpi RQ; /*!< cached R^2 mod Q. */ + + mbedtls_mpi Vi; /*!< The cached blinding value. */ + mbedtls_mpi Vf; /*!< The cached un-blinding value. */ + + int padding; /*!< Selects padding mode: + #MBEDTLS_RSA_PKCS_V15 for 1.5 padding and + #MBEDTLS_RSA_PKCS_V21 for OAEP or PSS. */ + int hash_id; /*!< Hash identifier of mbedtls_md_type_t type, + as specified in md.h for use in the MGF + mask generating function used in the + EME-OAEP and EMSA-PSS encodings. */ +#if defined(MBEDTLS_THREADING_C) + mbedtls_threading_mutex_t mutex; /*!< Thread-safety mutex. */ +#endif +} +mbedtls_rsa_context; + +#else /* MBEDTLS_RSA_ALT */ +#include "rsa_alt.h" +#endif /* MBEDTLS_RSA_ALT */ + +/** + * \brief This function initializes an RSA context. + * + * \note Set padding to #MBEDTLS_RSA_PKCS_V21 for the RSAES-OAEP + * encryption scheme and the RSASSA-PSS signature scheme. + * + * \note The \p hash_id parameter is ignored when using + * #MBEDTLS_RSA_PKCS_V15 padding. + * + * \note The choice of padding mode is strictly enforced for private key + * operations, since there might be security concerns in + * mixing padding modes. For public key operations it is + * a default value, which can be overriden by calling specific + * \c rsa_rsaes_xxx or \c rsa_rsassa_xxx functions. + * + * \note The hash selected in \p hash_id is always used for OEAP + * encryption. For PSS signatures, it is always used for + * making signatures, but can be overriden for verifying them. + * If set to #MBEDTLS_MD_NONE, it is always overriden. + * + * \param ctx The RSA context to initialize. + * \param padding Selects padding mode: #MBEDTLS_RSA_PKCS_V15 or + * #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The hash identifier of #mbedtls_md_type_t type, if + * \p padding is #MBEDTLS_RSA_PKCS_V21. + */ +void mbedtls_rsa_init( mbedtls_rsa_context *ctx, + int padding, + int hash_id); + +/** + * \brief This function imports a set of core parameters into an + * RSA context. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus, or NULL. + * \param P The first prime factor of \p N, or NULL. + * \param Q The second prime factor of \p N, or NULL. + * \param D The private exponent, or NULL. + * \param E The public exponent, or NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_rsa_import( mbedtls_rsa_context *ctx, + const mbedtls_mpi *N, + const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *E ); + +/** + * \brief This function imports core RSA parameters, in raw big-endian + * binary format, into an RSA context. + * + * \note This function can be called multiple times for successive + * imports, if the parameters are not simultaneously present. + * + * Any sequence of calls to this function should be followed + * by a call to mbedtls_rsa_complete(), which checks and + * completes the provided information to a ready-for-use + * public or private RSA key. + * + * \note See mbedtls_rsa_complete() for more information on which + * parameters are necessary to set up a private or public + * RSA key. + * + * \note The imported parameters are copied and need not be preserved + * for the lifetime of the RSA context being set up. + * + * \param ctx The initialized RSA context to store the parameters in. + * \param N The RSA modulus, or NULL. + * \param N_len The Byte length of \p N, ignored if \p N == NULL. + * \param P The first prime factor of \p N, or NULL. + * \param P_len The Byte length of \p P, ignored if \p P == NULL. + * \param Q The second prime factor of \p N, or NULL. + * \param Q_len The Byte length of \p Q, ignored if \p Q == NULL. + * \param D The private exponent, or NULL. + * \param D_len The Byte length of \p D, ignored if \p D == NULL. + * \param E The public exponent, or NULL. + * \param E_len The Byte length of \p E, ignored if \p E == NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + */ +int mbedtls_rsa_import_raw( mbedtls_rsa_context *ctx, + unsigned char const *N, size_t N_len, + unsigned char const *P, size_t P_len, + unsigned char const *Q, size_t Q_len, + unsigned char const *D, size_t D_len, + unsigned char const *E, size_t E_len ); + +/** + * \brief This function completes an RSA context from + * a set of imported core parameters. + * + * To setup an RSA public key, precisely \p N and \p E + * must have been imported. + * + * To setup an RSA private key, sufficient information must + * be present for the other parameters to be derivable. + * + * The default implementation supports the following: + *
  • Derive \p P, \p Q from \p N, \p D, \p E.
  • + *
  • Derive \p N, \p D from \p P, \p Q, \p E.
+ * Alternative implementations need not support these. + * + * If this function runs successfully, it guarantees that + * the RSA context can be used for RSA operations without + * the risk of failure or crash. + * + * \warning This function need not perform consistency checks + * for the imported parameters. In particular, parameters that + * are not needed by the implementation might be silently + * discarded and left unchecked. To check the consistency + * of the key material, see mbedtls_rsa_check_privkey(). + * + * \param ctx The initialized RSA context holding imported parameters. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_BAD_INPUT_DATA if the attempted derivations + * failed. + * + */ +int mbedtls_rsa_complete( mbedtls_rsa_context *ctx ); + +/** + * \brief This function exports the core parameters of an RSA key. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * + * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \param ctx The initialized RSA context. + * \param N The MPI to hold the RSA modulus, or NULL. + * \param P The MPI to hold the first prime factor of \p N, or NULL. + * \param Q The MPI to hold the second prime factor of \p N, or NULL. + * \param D The MPI to hold the private exponent, or NULL. + * \param E The MPI to hold the public exponent, or NULL. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies. + * \return A non-zero return code on any other failure. + * + */ +int mbedtls_rsa_export( const mbedtls_rsa_context *ctx, + mbedtls_mpi *N, mbedtls_mpi *P, mbedtls_mpi *Q, + mbedtls_mpi *D, mbedtls_mpi *E ); + +/** + * \brief This function exports core parameters of an RSA key + * in raw big-endian binary format. + * + * If this function runs successfully, the non-NULL buffers + * pointed to by \p N, \p P, \p Q, \p D, and \p E are fully + * written, with additional unused space filled leading by + * zero Bytes. + * + * Possible reasons for returning + * #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION:
    + *
  • An alternative RSA implementation is in use, which + * stores the key externally, and either cannot or should + * not export it into RAM.
  • + *
  • A SW or HW implementation might not support a certain + * deduction. For example, \p P, \p Q from \p N, \p D, + * and \p E if the former are not part of the + * implementation.
+ * If the function fails due to an unsupported operation, + * the RSA context stays intact and remains usable. + * + * \note The length parameters are ignored if the corresponding + * buffer pointers are NULL. + * + * \param ctx The initialized RSA context. + * \param N The Byte array to store the RSA modulus, or NULL. + * \param N_len The size of the buffer for the modulus. + * \param P The Byte array to hold the first prime factor of \p N, or + * NULL. + * \param P_len The size of the buffer for the first prime factor. + * \param Q The Byte array to hold the second prime factor of \p N, or + * NULL. + * \param Q_len The size of the buffer for the second prime factor. + * \param D The Byte array to hold the private exponent, or NULL. + * \param D_len The size of the buffer for the private exponent. + * \param E The Byte array to hold the public exponent, or NULL. + * \param E_len The size of the buffer for the public exponent. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION if exporting the + * requested parameters cannot be done due to missing + * functionality or because of security policies. + * \return A non-zero return code on any other failure. + */ +int mbedtls_rsa_export_raw( const mbedtls_rsa_context *ctx, + unsigned char *N, size_t N_len, + unsigned char *P, size_t P_len, + unsigned char *Q, size_t Q_len, + unsigned char *D, size_t D_len, + unsigned char *E, size_t E_len ); + +/** + * \brief This function exports CRT parameters of a private RSA key. + * + * \note Alternative RSA implementations not using CRT-parameters + * internally can implement this function based on + * mbedtls_rsa_deduce_opt(). + * + * \param ctx The initialized RSA context. + * \param DP The MPI to hold D modulo P-1, or NULL. + * \param DQ The MPI to hold D modulo Q-1, or NULL. + * \param QP The MPI to hold modular inverse of Q modulo P, or NULL. + * + * \return \c 0 on success. + * \return A non-zero error code on failure. + * + */ +int mbedtls_rsa_export_crt( const mbedtls_rsa_context *ctx, + mbedtls_mpi *DP, mbedtls_mpi *DQ, mbedtls_mpi *QP ); + +/** + * \brief This function sets padding for an already initialized RSA + * context. See mbedtls_rsa_init() for details. + * + * \param ctx The RSA context to be set. + * \param padding Selects padding mode: #MBEDTLS_RSA_PKCS_V15 or + * #MBEDTLS_RSA_PKCS_V21. + * \param hash_id The #MBEDTLS_RSA_PKCS_V21 hash identifier. + */ +void mbedtls_rsa_set_padding( mbedtls_rsa_context *ctx, int padding, + int hash_id); + +/** + * \brief This function retrieves the length of RSA modulus in Bytes. + * + * \param ctx The initialized RSA context. + * + * \return The length of the RSA modulus in Bytes. + * + */ +size_t mbedtls_rsa_get_len( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function generates an RSA keypair. + * + * \note mbedtls_rsa_init() must be called before this function, + * to set up the RSA context. + * + * \param ctx The RSA context used to hold the key. + * \param f_rng The RNG function. + * \param p_rng The RNG context. + * \param nbits The size of the public key in bits. + * \param exponent The public exponent. For example, 65537. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_gen_key( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + unsigned int nbits, int exponent ); + +/** + * \brief This function checks if a context contains at least an RSA + * public key. + * + * If the function runs successfully, it is guaranteed that + * enough information is present to perform an RSA public key + * operation using mbedtls_rsa_public(). + * + * \param ctx The RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_check_pubkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks if a context contains an RSA private key + * and perform basic consistency checks. + * + * \note The consistency checks performed by this function not only + * ensure that mbedtls_rsa_private() can be called successfully + * on the given context, but that the various parameters are + * mutually consistent with high probability, in the sense that + * mbedtls_rsa_public() and mbedtls_rsa_private() are inverses. + * + * \warning This function should catch accidental misconfigurations + * like swapping of parameters, but it cannot establish full + * trust in neither the quality nor the consistency of the key + * material that was used to setup the given RSA context: + *
  • Consistency: Imported parameters that are irrelevant + * for the implementation might be silently dropped. If dropped, + * the current function does not have access to them, + * and therefore cannot check them. See mbedtls_rsa_complete(). + * If you want to check the consistency of the entire + * content of an PKCS1-encoded RSA private key, for example, you + * should use mbedtls_rsa_validate_params() before setting + * up the RSA context. + * Additionally, if the implementation performs empirical checks, + * these checks substantiate but do not guarantee consistency.
  • + *
  • Quality: This function is not expected to perform + * extended quality assessments like checking that the prime + * factors are safe. Additionally, it is the responsibility of the + * user to ensure the trustworthiness of the source of his RSA + * parameters, which goes beyond what is effectively checkable + * by the library.
+ * + * \param ctx The RSA context to check. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_check_privkey( const mbedtls_rsa_context *ctx ); + +/** + * \brief This function checks a public-private RSA key pair. + * + * It checks each of the contexts, and makes sure they match. + * + * \param pub The RSA context holding the public key. + * \param prv The RSA context holding the private key. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_check_pub_priv( const mbedtls_rsa_context *pub, + const mbedtls_rsa_context *prv ); + +/** + * \brief This function performs an RSA public key operation. + * + * \note This function does not handle message padding. + * + * \note Make sure to set \p input[0] = 0 or ensure that + * input is smaller than \p N. + * + * \note The input and output buffers must be large + * enough. For example, 128 Bytes if RSA-1024 is used. + * + * \param ctx The RSA context. + * \param input The input buffer. + * \param output The output buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_public( mbedtls_rsa_context *ctx, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA private key operation. + * + * \note The input and output buffers must be large + * enough. For example, 128 Bytes if RSA-1024 is used. + * + * \note Blinding is used if and only if a PRNG is provided. + * + * \note If blinding is used, both the base of exponentation + * and the exponent are blinded, providing protection + * against some side-channel attacks. + * + * \warning It is deprecated and a security risk to not provide + * a PRNG here and thereby prevent the use of blinding. + * Future versions of the library may enforce the presence + * of a PRNG. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for blinding. + * \param p_rng The RNG context. + * \param input The input buffer. + * \param output The output buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_private( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function adds the message padding, then performs an RSA + * operation. + * + * It is the generic wrapper for performing a PKCS#1 encryption + * operation using the \p mode from the context. + * + * \note The input and output buffers must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for padding, PKCS#1 v2.1 + * encoding, and #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param ilen The length of the plaintext. + * \param input The buffer holding the data to encrypt. + * \param output The buffer used to hold the ciphertext. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs a PKCS#1 v1.5 encryption operation + * (RSAES-PKCS1-v1_5-ENCRYPT). + * + * \note The output buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for padding and + * #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param ilen The length of the plaintext. + * \param input The buffer holding the data to encrypt. + * \param output The buffer used to hold the ciphertext. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_pkcs1_v15_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP encryption + * operation (RSAES-OAEP-ENCRYPT). + * + * \note The output buffer must be as large as the size + * of ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for padding and PKCS#1 v2.1 + * encoding and #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param label The buffer holding the custom label to use. + * \param label_len The length of the label. + * \param ilen The length of the plaintext. + * \param input The buffer holding the data to encrypt. + * \param output The buffer used to hold the ciphertext. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_oaep_encrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t ilen, + const unsigned char *input, + unsigned char *output ); + +/** + * \brief This function performs an RSA operation, then removes the + * message padding. + * + * It is the generic wrapper for performing a PKCS#1 decryption + * operation using the \p mode from the context. + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N (for example, + * 128 Bytes if RSA-1024 is used) to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns \c MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \note The input buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param olen The length of the plaintext. + * \param input The buffer holding the encrypted data. + * \param output The buffer used to hold the plaintext. + * \param output_max_len The maximum length of the output buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v1.5 decryption + * operation (RSAES-PKCS1-v1_5-DECRYPT). + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for example, + * 128 Bytes if RSA-1024 is used, to be able to hold an + * arbitrary decrypted message. If it is not large enough to + * hold the decryption of the particular ciphertext provided, + * the function returns #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \note The input buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param olen The length of the plaintext. + * \param input The buffer holding the encrypted data. + * \param output The buffer to hold the plaintext. + * \param output_max_len The maximum length of the output buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + * + */ +int mbedtls_rsa_rsaes_pkcs1_v15_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a PKCS#1 v2.1 OAEP decryption + * operation (RSAES-OAEP-DECRYPT). + * + * \note The output buffer length \c output_max_len should be + * as large as the size \p ctx->len of \p ctx->N, for + * example, 128 Bytes if RSA-1024 is used, to be able to + * hold an arbitrary decrypted message. If it is not + * large enough to hold the decryption of the particular + * ciphertext provided, the function returns + * #MBEDTLS_ERR_RSA_OUTPUT_TOO_LARGE. + * + * \note The input buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param label The buffer holding the custom label to use. + * \param label_len The length of the label. + * \param olen The length of the plaintext. + * \param input The buffer holding the encrypted data. + * \param output The buffer to hold the plaintext. + * \param output_max_len The maximum length of the output buffer. + * + * \return \c 0 on success. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsaes_oaep_decrypt( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + const unsigned char *label, size_t label_len, + size_t *olen, + const unsigned char *input, + unsigned char *output, + size_t output_max_len ); + +/** + * \brief This function performs a private RSA operation to sign + * a message digest using PKCS#1. + * + * It is the generic wrapper for performing a PKCS#1 + * signature using the \p mode from the context. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_sign() for details on + * \p md_alg and \p hash_id. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for + * #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer to hold the ciphertext. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v1.5 signature + * operation (RSASSA-PKCS1-v1_5-SIGN). + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer to hold the ciphertext. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS signature + * operation (RSASSA-PSS-SIGN). + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is the one used for the + * encoding. \p md_alg in the function call is the type of hash + * that is encoded. According to RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications it is advised to keep both hashes the + * same. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PUBLIC mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PRIVATE. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PUBLIC and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \param ctx The RSA context. + * \param f_rng The RNG function. Needed for PKCS#1 v2.1 encoding and for + * #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer to hold the ciphertext. + * + * \return \c 0 if the signing operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_sign( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + unsigned char *sig ); + +/** + * \brief This function performs a public RSA operation and checks + * the message digest. + * + * This is the generic wrapper for performing a PKCS#1 + * verification using the mode from the context. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note For PKCS#1 v2.1 encoding, see comments on + * mbedtls_rsa_rsassa_pss_verify() about \p md_alg and + * \p hash_id. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer holding the ciphertext. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_pkcs1_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v1.5 verification + * operation (RSASSA-PKCS1-v1_5-VERIFY). + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer holding the ciphertext. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pkcs1_v15_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * The hash function for the MGF mask generating function + * is that specified in the RSA context. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is the one used for the + * verification. \p md_alg in the function call is the type of + * hash that is verified. According to RFC-3447: Public-Key + * Cryptography Standards (PKCS) #1 v2.1: RSA Cryptography + * Specifications it is advised to keep both hashes the + * same. If \p hash_id in the RSA context is unset, + * the \p md_alg from the function call is used. + * + * \deprecated It is deprecated and discouraged to call this function + * in #MBEDTLS_RSA_PRIVATE mode. Future versions of the library + * are likely to remove the \p mode argument and have it + * implicitly set to #MBEDTLS_RSA_PUBLIC. + * + * \note Alternative implementations of RSA need not support + * mode being set to #MBEDTLS_RSA_PRIVATE and might instead + * return #MBEDTLS_ERR_RSA_UNSUPPORTED_OPERATION. + * + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param sig The buffer holding the ciphertext. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_verify( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + const unsigned char *sig ); + +/** + * \brief This function performs a PKCS#1 v2.1 PSS verification + * operation (RSASSA-PSS-VERIFY). + * + * The hash function for the MGF mask generating function + * is that specified in \p mgf1_hash_id. + * + * \note The \p sig buffer must be as large as the size + * of \p ctx->N. For example, 128 Bytes if RSA-1024 is used. + * + * \note The \p hash_id in the RSA context is ignored. + * + * \param ctx The RSA public key context. + * \param f_rng The RNG function. Only needed for #MBEDTLS_RSA_PRIVATE. + * \param p_rng The RNG context. + * \param mode #MBEDTLS_RSA_PUBLIC or #MBEDTLS_RSA_PRIVATE. + * \param md_alg The message-digest algorithm used to hash the original data. + * Use #MBEDTLS_MD_NONE for signing raw data. + * \param hashlen The length of the message digest. Only used if \p md_alg is + * #MBEDTLS_MD_NONE. + * \param hash The buffer holding the message digest. + * \param mgf1_hash_id The message digest used for mask generation. + * \param expected_salt_len The length of the salt used in padding. Use + * #MBEDTLS_RSA_SALT_LEN_ANY to accept any salt length. + * \param sig The buffer holding the ciphertext. + * + * \return \c 0 if the verify operation was successful. + * \return An \c MBEDTLS_ERR_RSA_XXX error code on failure. + */ +int mbedtls_rsa_rsassa_pss_verify_ext( mbedtls_rsa_context *ctx, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng, + int mode, + mbedtls_md_type_t md_alg, + unsigned int hashlen, + const unsigned char *hash, + mbedtls_md_type_t mgf1_hash_id, + int expected_salt_len, + const unsigned char *sig ); + +/** + * \brief This function copies the components of an RSA context. + * + * \param dst The destination context. + * \param src The source context. + * + * \return \c 0 on success. + * \return #MBEDTLS_ERR_MPI_ALLOC_FAILED on memory allocation failure. + */ +int mbedtls_rsa_copy( mbedtls_rsa_context *dst, const mbedtls_rsa_context *src ); + +/** + * \brief This function frees the components of an RSA key. + * + * \param ctx The RSA Context to free. + */ +void mbedtls_rsa_free( mbedtls_rsa_context *ctx ); + +/** + * \brief The RSA checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_rsa_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* rsa.h */ diff --git a/common/mbedtls/rsa_internal.c b/common/mbedtls/rsa_internal.c new file mode 100644 index 000000000..36c37f893 --- /dev/null +++ b/common/mbedtls/rsa_internal.c @@ -0,0 +1,489 @@ +/* + * Helper functions for the RSA module + * + * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_RSA_C) + +#include "mbedtls/rsa.h" +#include "mbedtls/bignum.h" +#include "mbedtls/rsa_internal.h" + +/* + * Compute RSA prime factors from public and private exponents + * + * Summary of algorithm: + * Setting F := lcm(P-1,Q-1), the idea is as follows: + * + * (a) For any 1 <= X < N with gcd(X,N)=1, we have X^F = 1 modulo N, so X^(F/2) + * is a square root of 1 in Z/NZ. Since Z/NZ ~= Z/PZ x Z/QZ by CRT and the + * square roots of 1 in Z/PZ and Z/QZ are +1 and -1, this leaves the four + * possibilities X^(F/2) = (+-1, +-1). If it happens that X^(F/2) = (-1,+1) + * or (+1,-1), then gcd(X^(F/2) + 1, N) will be equal to one of the prime + * factors of N. + * + * (b) If we don't know F/2 but (F/2) * K for some odd (!) K, then the same + * construction still applies since (-)^K is the identity on the set of + * roots of 1 in Z/NZ. + * + * The public and private key primitives (-)^E and (-)^D are mutually inverse + * bijections on Z/NZ if and only if (-)^(DE) is the identity on Z/NZ, i.e. + * if and only if DE - 1 is a multiple of F, say DE - 1 = F * L. + * Splitting L = 2^t * K with K odd, we have + * + * DE - 1 = FL = (F/2) * (2^(t+1)) * K, + * + * so (F / 2) * K is among the numbers + * + * (DE - 1) >> 1, (DE - 1) >> 2, ..., (DE - 1) >> ord + * + * where ord is the order of 2 in (DE - 1). + * We can therefore iterate through these numbers apply the construction + * of (a) and (b) above to attempt to factor N. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, + mbedtls_mpi const *E, mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ) +{ + int ret = 0; + + uint16_t attempt; /* Number of current attempt */ + uint16_t iter; /* Number of squares computed in the current attempt */ + + uint16_t order; /* Order of 2 in DE - 1 */ + + mbedtls_mpi T; /* Holds largest odd divisor of DE - 1 */ + mbedtls_mpi K; /* Temporary holding the current candidate */ + + const unsigned char primes[] = { 2, + 3, 5, 7, 11, 13, 17, 19, 23, + 29, 31, 37, 41, 43, 47, 53, 59, + 61, 67, 71, 73, 79, 83, 89, 97, + 101, 103, 107, 109, 113, 127, 131, 137, + 139, 149, 151, 157, 163, 167, 173, 179, + 181, 191, 193, 197, 199, 211, 223, 227, + 229, 233, 239, 241, 251 + }; + + const size_t num_primes = sizeof( primes ) / sizeof( *primes ); + + if( P == NULL || Q == NULL || P->p != NULL || Q->p != NULL ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( N, 0 ) <= 0 || + mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + /* + * Initializations and temporary changes + */ + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &T ); + + /* T := DE - 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &T, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &T, &T, 1 ) ); + + if( ( order = (uint16_t) mbedtls_mpi_lsb( &T ) ) == 0 ) + { + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + goto cleanup; + } + + /* After this operation, T holds the largest odd divisor of DE - 1. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_r( &T, order ) ); + + /* + * Actual work + */ + + /* Skip trying 2 if N == 1 mod 8 */ + attempt = 0; + if( N->p[0] % 8 == 1 ) + attempt = 1; + + for( ; attempt < num_primes; ++attempt ) + { + mbedtls_mpi_lset( &K, primes[attempt] ); + + /* Check if gcd(K,N) = 1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + if( mbedtls_mpi_cmp_int( P, 1 ) != 0 ) + continue; + + /* Go through K^T + 1, K^(2T) + 1, K^(4T) + 1, ... + * and check whether they have nontrivial GCD with N. */ + MBEDTLS_MPI_CHK( mbedtls_mpi_exp_mod( &K, &K, &T, N, + Q /* temporarily use Q for storing Montgomery + * multiplication helper values */ ) ); + + for( iter = 1; iter <= order; ++iter ) + { + /* If we reach 1 prematurely, there's no point + * in continuing to square K */ + if( mbedtls_mpi_cmp_int( &K, 1 ) == 0 ) + break; + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( P, &K, N ) ); + + if( mbedtls_mpi_cmp_int( P, 1 ) == 1 && + mbedtls_mpi_cmp_mpi( P, N ) == -1 ) + { + /* + * Have found a nontrivial divisor P of N. + * Set Q := N / P. + */ + + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( Q, NULL, N, P ) ); + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &K ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, N ) ); + } + + /* + * If we get here, then either we prematurely aborted the loop because + * we reached 1, or K holds primes[attempt]^(DE - 1) mod N, which must + * be 1 if D,E,N were consistent. + * Check if that's the case and abort if not, to avoid very long, + * yet eventually failing, computations if N,D,E were not sane. + */ + if( mbedtls_mpi_cmp_int( &K, 1 ) != 0 ) + { + break; + } + } + + ret = MBEDTLS_ERR_MPI_BAD_INPUT_DATA; + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &T ); + return( ret ); +} + +/* + * Given P, Q and the public exponent E, deduce D. + * This is essentially a modular inversion. + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ) +{ + int ret = 0; + mbedtls_mpi K, L; + + if( D == NULL || mbedtls_mpi_cmp_int( D, 0 ) != 0 ) + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 0 ) == 0 ) + { + return( MBEDTLS_ERR_MPI_BAD_INPUT_DATA ); + } + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Temporarily put K := P-1 and L := Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + + /* Temporarily put D := gcd(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_gcd( D, &K, &L ) ); + + /* K := LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, &K, &L ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_div_mpi( &K, NULL, &K, D ) ); + + /* Compute modular inverse of E in LCM(P-1, Q-1) */ + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( D, E, &K ) ); + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +/* + * Check that RSA CRT parameters are in accordance with core parameters. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ) +{ + int ret = 0; + + mbedtls_mpi K, L; + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* Check that DP - D == 0 mod P - 1 */ + if( DP != NULL ) + { + if( P == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DP, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that DQ - D == 0 mod Q - 1 */ + if( DQ != NULL ) + { + if( Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_mpi( &L, DQ, D ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &L, &L, &K ) ); + + if( mbedtls_mpi_cmp_int( &L, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* Check that QP * Q - 1 == 0 mod P */ + if( QP != NULL ) + { + if( P == NULL || Q == NULL ) + { + ret = MBEDTLS_ERR_RSA_BAD_INPUT_DATA; + goto cleanup; + } + + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, QP, Q ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, P ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && + ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED && + ret != MBEDTLS_ERR_RSA_BAD_INPUT_DATA ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + return( ret ); +} + +/* + * Check that core RSA parameters are sane. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ) +{ + int ret = 0; + mbedtls_mpi K, L; + + mbedtls_mpi_init( &K ); + mbedtls_mpi_init( &L ); + + /* + * Step 1: If PRNG provided, check that P and Q are prime + */ + +#if defined(MBEDTLS_GENPRIME) + if( f_rng != NULL && P != NULL && + ( ret = mbedtls_mpi_is_prime( P, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + if( f_rng != NULL && Q != NULL && + ( ret = mbedtls_mpi_is_prime( Q, f_rng, p_rng ) ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } +#else + ((void) f_rng); + ((void) p_rng); +#endif /* MBEDTLS_GENPRIME */ + + /* + * Step 2: Check that 1 < N = P * Q + */ + + if( P != NULL && Q != NULL && N != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, P, Q ) ); + if( mbedtls_mpi_cmp_int( N, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( &K, N ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 3: Check and 1 < D, E < N if present. + */ + + if( N != NULL && D != NULL && E != NULL ) + { + if ( mbedtls_mpi_cmp_int( D, 1 ) <= 0 || + mbedtls_mpi_cmp_int( E, 1 ) <= 0 || + mbedtls_mpi_cmp_mpi( D, N ) >= 0 || + mbedtls_mpi_cmp_mpi( E, N ) >= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + + /* + * Step 4: Check that D, E are inverse modulo P-1 and Q-1 + */ + + if( P != NULL && Q != NULL && D != NULL && E != NULL ) + { + if( mbedtls_mpi_cmp_int( P, 1 ) <= 0 || + mbedtls_mpi_cmp_int( Q, 1 ) <= 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod P-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + + /* Compute DE-1 mod Q-1 */ + MBEDTLS_MPI_CHK( mbedtls_mpi_mul_mpi( &K, D, E ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, &K, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &L, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( &K, &K, &L ) ); + if( mbedtls_mpi_cmp_int( &K, 0 ) != 0 ) + { + ret = MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + goto cleanup; + } + } + +cleanup: + + mbedtls_mpi_free( &K ); + mbedtls_mpi_free( &L ); + + /* Wrap MPI error codes by RSA check failure error code */ + if( ret != 0 && ret != MBEDTLS_ERR_RSA_KEY_CHECK_FAILED ) + { + ret += MBEDTLS_ERR_RSA_KEY_CHECK_FAILED; + } + + return( ret ); +} + +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ) +{ + int ret = 0; + mbedtls_mpi K; + mbedtls_mpi_init( &K ); + + /* DP = D mod P-1 */ + if( DP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, P, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DP, D, &K ) ); + } + + /* DQ = D mod Q-1 */ + if( DQ != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_sub_int( &K, Q, 1 ) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi( DQ, D, &K ) ); + } + + /* QP = Q^{-1} mod P */ + if( QP != NULL ) + { + MBEDTLS_MPI_CHK( mbedtls_mpi_inv_mod( QP, Q, P ) ); + } + +cleanup: + mbedtls_mpi_free( &K ); + + return( ret ); +} + +#endif /* MBEDTLS_RSA_C */ diff --git a/common/mbedtls/rsa_internal.h b/common/mbedtls/rsa_internal.h new file mode 100644 index 000000000..8ee0bfe34 --- /dev/null +++ b/common/mbedtls/rsa_internal.h @@ -0,0 +1,228 @@ +/** + * \file rsa_internal.h + * + * \brief Context-independent RSA helper functions + * + * This module declares some RSA-related helper functions useful when + * implementing the RSA interface. These functions are provided in a separate + * compilation unit in order to make it easy for designers of alternative RSA + * implementations to use them in their own code, as it is conceived that the + * functionality they provide will be necessary for most complete + * implementations. + * + * End-users of Mbed TLS who are not providing their own alternative RSA + * implementations should not use these functions directly, and should instead + * use only the functions declared in rsa.h. + * + * The interface provided by this module will be maintained through LTS (Long + * Term Support) branches of Mbed TLS, but may otherwise be subject to change, + * and must be considered an internal interface of the library. + * + * There are two classes of helper functions: + * + * (1) Parameter-generating helpers. These are: + * - mbedtls_rsa_deduce_primes + * - mbedtls_rsa_deduce_private_exponent + * - mbedtls_rsa_deduce_crt + * Each of these functions takes a set of core RSA parameters and + * generates some other, or CRT related parameters. + * + * (2) Parameter-checking helpers. These are: + * - mbedtls_rsa_validate_params + * - mbedtls_rsa_validate_crt + * They take a set of core or CRT related RSA parameters and check their + * validity. + * + */ +/* + * Copyright (C) 2006-2017, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + * + */ + +#ifndef MBEDTLS_RSA_INTERNAL_H +#define MBEDTLS_RSA_INTERNAL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "bignum.h" + +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * \brief Compute RSA prime moduli P, Q from public modulus N=PQ + * and a pair of private and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ, with P, Q to be found + * \param E RSA public exponent + * \param D RSA private exponent + * \param P Pointer to MPI holding first prime factor of N on success + * \param Q Pointer to MPI holding second prime factor of N on success + * + * \return + * - 0 if successful. In this case, P and Q constitute a + * factorization of N. + * - A non-zero error code otherwise. + * + * \note It is neither checked that P, Q are prime nor that + * D, E are modular inverses wrt. P-1 and Q-1. For that, + * use the helper function \c mbedtls_rsa_validate_params. + * + */ +int mbedtls_rsa_deduce_primes( mbedtls_mpi const *N, mbedtls_mpi const *E, + mbedtls_mpi const *D, + mbedtls_mpi *P, mbedtls_mpi *Q ); + +/** + * \brief Compute RSA private exponent from + * prime moduli and public key. + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param E RSA public exponent + * \param D Pointer to MPI holding the private exponent on success. + * + * \return + * - 0 if successful. In this case, D is set to a simultaneous + * modular inverse of E modulo both P-1 and Q-1. + * - A non-zero error code otherwise. + * + * \note This function does not check whether P and Q are primes. + * + */ +int mbedtls_rsa_deduce_private_exponent( mbedtls_mpi const *P, + mbedtls_mpi const *Q, + mbedtls_mpi const *E, + mbedtls_mpi *D ); + + +/** + * \brief Generate RSA-CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param DP Output variable for D modulo P-1 + * \param DQ Output variable for D modulo Q-1 + * \param QP Output variable for the modular inverse of Q modulo P. + * + * \return 0 on success, non-zero error code otherwise. + * + * \note This function does not check whether P, Q are + * prime and whether D is a valid private exponent. + * + */ +int mbedtls_rsa_deduce_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, mbedtls_mpi *DP, + mbedtls_mpi *DQ, mbedtls_mpi *QP ); + + +/** + * \brief Check validity of core RSA parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param N RSA modulus N = PQ + * \param P First prime factor of N + * \param Q Second prime factor of N + * \param D RSA private exponent + * \param E RSA public exponent + * \param f_rng PRNG to be used for primality check, or NULL + * \param p_rng PRNG context for f_rng, or NULL + * + * \return + * - 0 if the following conditions are satisfied + * if all relevant parameters are provided: + * - P prime if f_rng != NULL (%) + * - Q prime if f_rng != NULL (%) + * - 1 < N = P * Q + * - 1 < D, E < N + * - D and E are modular inverses modulo P-1 and Q-1 + * (%) This is only done if MBEDTLS_GENPRIME is defined. + * - A non-zero error code otherwise. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with + * (-,P,-,-,-) and a PRNG amounts to a primality check for P. + */ +int mbedtls_rsa_validate_params( const mbedtls_mpi *N, const mbedtls_mpi *P, + const mbedtls_mpi *Q, const mbedtls_mpi *D, + const mbedtls_mpi *E, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +/** + * \brief Check validity of RSA CRT parameters + * + * \note This is a 'static' helper function not operating on + * an RSA context. Alternative implementations need not + * overwrite it. + * + * \param P First prime factor of RSA modulus + * \param Q Second prime factor of RSA modulus + * \param D RSA private exponent + * \param DP MPI to check for D modulo P-1 + * \param DQ MPI to check for D modulo P-1 + * \param QP MPI to check for the modular inverse of Q modulo P. + * + * \return + * - 0 if the following conditions are satisfied: + * - D = DP mod P-1 if P, D, DP != NULL + * - Q = DQ mod P-1 if P, D, DQ != NULL + * - QP = Q^-1 mod P if P, Q, QP != NULL + * - \c MBEDTLS_ERR_RSA_KEY_CHECK_FAILED if check failed, + * potentially including \c MBEDTLS_ERR_MPI_XXX if some + * MPI calculations failed. + * - \c MBEDTLS_ERR_RSA_BAD_INPUT_DATA if insufficient + * data was provided to check DP, DQ or QP. + * + * \note The function can be used with a restricted set of arguments + * to perform specific checks only. E.g., calling it with the + * parameters (P, -, D, DP, -, -) will check DP = D mod P-1. + */ +int mbedtls_rsa_validate_crt( const mbedtls_mpi *P, const mbedtls_mpi *Q, + const mbedtls_mpi *D, const mbedtls_mpi *DP, + const mbedtls_mpi *DQ, const mbedtls_mpi *QP ); + +#ifdef __cplusplus +} +#endif + +#endif /* rsa_internal.h */ diff --git a/common/polarssl/sha1.c b/common/mbedtls/sha1.c similarity index 50% rename from common/polarssl/sha1.c rename to common/mbedtls/sha1.c index 3cd2e0555..9981c5a9d 100644 --- a/common/polarssl/sha1.c +++ b/common/mbedtls/sha1.c @@ -1,9 +1,8 @@ /* * FIPS-180-1 compliant SHA-1 implementation * - * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved - * - * This file is part of mbed TLS (https://tls.mbed.org) + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 * * 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 @@ -18,6 +17,8 @@ * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The SHA-1 standard was published by NIST in 1993. @@ -25,39 +26,29 @@ * http://www.itl.nist.gov/fipspubs/fip180-1.htm */ -#if !defined(POLARSSL_CONFIG_FILE) -//#include "polarssl/config.h" -#define POLARSSL_SHA1_C - +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" #else -#include POLARSSL_CONFIG_FILE +#include MBEDTLS_CONFIG_FILE #endif -#if defined(POLARSSL_SHA1_C) +#if defined(MBEDTLS_SHA1_C) -#include "sha1.h" +#include "mbedtls/sha1.h" +#include "mbedtls/platform_util.h" #include -#if defined(POLARSSL_FS_IO) -#include -#endif - -#if defined(POLARSSL_SELF_TEST) -#if defined(POLARSSL_PLATFORM_C) -#include "polarssl/platform.h" +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" #else #include -#define polarssl_printf printf -#endif /* POLARSSL_PLATFORM_C */ -#endif /* POLARSSL_SELF_TEST */ +#define mbedtls_printf printf +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ -/* Implementation that should never be optimized out by the compiler */ -static void polarssl_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -#if !defined(POLARSSL_SHA1_ALT) +#if !defined(MBEDTLS_SHA1_ALT) /* * 32-bit integer manipulation macros (big endian) @@ -82,23 +73,29 @@ static void polarssl_zeroize( void *v, size_t n ) { } #endif -void sha1_init( sha1_context *ctx ) +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ) { - memset( ctx, 0, sizeof( sha1_context ) ); + memset( ctx, 0, sizeof( mbedtls_sha1_context ) ); } -void sha1_free( sha1_context *ctx ) +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ) { if( ctx == NULL ) return; - polarssl_zeroize( ctx, sizeof( sha1_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha1_context ) ); +} + +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ) +{ + *dst = *src; } /* * SHA-1 context setup */ -void sha1_starts( sha1_context *ctx ) +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ) { ctx->total[0] = 0; ctx->total[1] = 0; @@ -108,9 +105,20 @@ void sha1_starts( sha1_context *ctx ) ctx->state[2] = 0x98BADCFE; ctx->state[3] = 0x10325476; ctx->state[4] = 0xC3D2E1F0; + + return( 0 ); } -void sha1_process( sha1_context *ctx, const unsigned char data[64] ) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ) +{ + mbedtls_sha1_starts_ret( ctx ); +} +#endif + +#if !defined(MBEDTLS_SHA1_PROCESS_ALT) +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) { uint32_t temp, W[16], A, B, C, D, E; @@ -264,18 +272,32 @@ void sha1_process( sha1_context *ctx, const unsigned char data[64] ) ctx->state[2] += C; ctx->state[3] += D; ctx->state[4] += E; + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha1_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA1_PROCESS_ALT */ + /* * SHA-1 process buffer */ -void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) { + int ret; size_t fill; uint32_t left; if( ilen == 0 ) - return; + return( 0 ); left = ctx->total[0] & 0x3F; fill = 64 - left; @@ -289,7 +311,10 @@ void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) if( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), input, fill ); - sha1_process( ctx, ctx->buffer ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + input += fill; ilen -= fill; left = 0; @@ -297,184 +322,133 @@ void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ) while( ilen >= 64 ) { - sha1_process( ctx, input ); + if( ( ret = mbedtls_internal_sha1_process( ctx, input ) ) != 0 ) + return( ret ); + input += 64; ilen -= 64; } if( ilen > 0 ) memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); } -static const unsigned char sha1_padding[64] = +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ) { - 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 -}; + mbedtls_sha1_update_ret( ctx, input, ilen ); +} +#endif /* * SHA-1 final digest */ -void sha1_finish( sha1_context *ctx, unsigned char output[20] ) +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ) { - uint32_t last, padn; + int ret; + uint32_t used; uint32_t high, low; - unsigned char msglen[8]; + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ 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 ); + PUT_UINT32_BE( high, ctx->buffer, 56 ); + PUT_UINT32_BE( low, ctx->buffer, 60 ); - last = ctx->total[0] & 0x3F; - padn = ( last < 56 ) ? ( 56 - last ) : ( 120 - last ); - - sha1_update( ctx, sha1_padding, padn ); - sha1_update( ctx, msglen, 8 ); + if( ( ret = mbedtls_internal_sha1_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + /* + * Output final state + */ 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 ); + + return( 0 ); } -#endif /* !POLARSSL_SHA1_ALT */ +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ) +{ + mbedtls_sha1_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA1_ALT */ /* * output = SHA-1( input buffer ) */ -void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ) +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) { - sha1_context ctx; + int ret; + mbedtls_sha1_context ctx; - sha1_init( &ctx ); - sha1_starts( &ctx ); - sha1_update( &ctx, input, ilen ); - sha1_finish( &ctx, output ); - sha1_free( &ctx ); + mbedtls_sha1_init( &ctx ); + + if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha1_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha1_free( &ctx ); + + return( ret ); } -#if defined(POLARSSL_FS_IO) -/* - * output = SHA-1( file contents ) - */ -int sha1_file( const char *path, unsigned char output[20] ) +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ) { - FILE *f; - size_t n; - sha1_context ctx; - unsigned char buf[1024]; - - if( ( f = fopen( path, "rb" ) ) == NULL ) - return( POLARSSL_ERR_SHA1_FILE_IO_ERROR ); - - sha1_init( &ctx ); - sha1_starts( &ctx ); - - while( ( n = fread( buf, 1, sizeof( buf ), f ) ) > 0 ) - sha1_update( &ctx, buf, n ); - - sha1_finish( &ctx, output ); - sha1_free( &ctx ); - - if( ferror( f ) != 0 ) - { - fclose( f ); - return( POLARSSL_ERR_SHA1_FILE_IO_ERROR ); - } - - fclose( f ); - return( 0 ); + mbedtls_sha1_ret( input, ilen, output ); } -#endif /* POLARSSL_FS_IO */ +#endif -/* - * SHA-1 HMAC context setup - */ -void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, - size_t keylen ) -{ - size_t i; - unsigned char sum[20]; - - if( keylen > 64 ) - { - sha1( key, keylen, sum ); - keylen = 20; - key = sum; - } - - memset( ctx->ipad, 0x36, 64 ); - memset( ctx->opad, 0x5C, 64 ); - - for( i = 0; i < keylen; i++ ) - { - ctx->ipad[i] = (unsigned char)( ctx->ipad[i] ^ key[i] ); - ctx->opad[i] = (unsigned char)( ctx->opad[i] ^ key[i] ); - } - - sha1_starts( ctx ); - sha1_update( ctx, ctx->ipad, 64 ); - - polarssl_zeroize( sum, sizeof( sum ) ); -} - -/* - * SHA-1 HMAC process buffer - */ -void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, - size_t ilen ) -{ - sha1_update( ctx, input, ilen ); -} - -/* - * SHA-1 HMAC final digest - */ -void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ) -{ - unsigned char tmpbuf[20]; - - sha1_finish( ctx, tmpbuf ); - sha1_starts( ctx ); - sha1_update( ctx, ctx->opad, 64 ); - sha1_update( ctx, tmpbuf, 20 ); - sha1_finish( ctx, output ); - - polarssl_zeroize( tmpbuf, sizeof( tmpbuf ) ); -} - -/* - * SHA1 HMAC context reset - */ -void sha1_hmac_reset( sha1_context *ctx ) -{ - sha1_starts( ctx ); - sha1_update( ctx, ctx->ipad, 64 ); -} - -/* - * output = HMAC-SHA-1( hmac key, input buffer ) - */ -void sha1_hmac( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char output[20] ) -{ - sha1_context ctx; - - sha1_init( &ctx ); - sha1_hmac_starts( &ctx, key, keylen ); - sha1_hmac_update( &ctx, input, ilen ); - sha1_hmac_finish( &ctx, output ); - sha1_free( &ctx ); -} - -#if defined(POLARSSL_SELF_TEST) +#if defined(MBEDTLS_SELF_TEST) /* * FIPS-180-1 test vectors */ @@ -485,7 +459,7 @@ static const unsigned char sha1_test_buf[3][57] = { "" } }; -static const int sha1_test_buflen[3] = +static const size_t sha1_test_buflen[3] = { 3, 56, 1000 }; @@ -500,83 +474,17 @@ static const unsigned char sha1_test_sum[3][20] = 0xEB, 0x2B, 0xDB, 0xAD, 0x27, 0x31, 0x65, 0x34, 0x01, 0x6F } }; -/* - * RFC 2202 test vectors - */ -static const unsigned char sha1_hmac_test_key[7][26] = -{ - { "\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B\x0B" - "\x0B\x0B\x0B\x0B" }, - { "Jefe" }, - { "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA" - "\xAA\xAA\xAA\xAA" }, - { "\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0A\x0B\x0C\x0D\x0E\x0F\x10" - "\x11\x12\x13\x14\x15\x16\x17\x18\x19" }, - { "\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C\x0C" - "\x0C\x0C\x0C\x0C" }, - { "" }, /* 0xAA 80 times */ - { "" } -}; - -static const int sha1_hmac_test_keylen[7] = -{ - 20, 4, 20, 25, 20, 80, 80 -}; - -static const unsigned char sha1_hmac_test_buf[7][74] = -{ - { "Hi There" }, - { "what do ya want for nothing?" }, - { "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" - "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD" }, - { "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" - "\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD\xCD" }, - { "Test With Truncation" }, - { "Test Using Larger Than Block-Size Key - Hash Key First" }, - { "Test Using Larger Than Block-Size Key and Larger" - " Than One Block-Size Data" } -}; - -static const int sha1_hmac_test_buflen[7] = -{ - 8, 28, 50, 50, 20, 54, 73 -}; - -static const unsigned char sha1_hmac_test_sum[7][20] = -{ - { 0xB6, 0x17, 0x31, 0x86, 0x55, 0x05, 0x72, 0x64, 0xE2, 0x8B, - 0xC0, 0xB6, 0xFB, 0x37, 0x8C, 0x8E, 0xF1, 0x46, 0xBE, 0x00 }, - { 0xEF, 0xFC, 0xDF, 0x6A, 0xE5, 0xEB, 0x2F, 0xA2, 0xD2, 0x74, - 0x16, 0xD5, 0xF1, 0x84, 0xDF, 0x9C, 0x25, 0x9A, 0x7C, 0x79 }, - { 0x12, 0x5D, 0x73, 0x42, 0xB9, 0xAC, 0x11, 0xCD, 0x91, 0xA3, - 0x9A, 0xF4, 0x8A, 0xA1, 0x7B, 0x4F, 0x63, 0xF1, 0x75, 0xD3 }, - { 0x4C, 0x90, 0x07, 0xF4, 0x02, 0x62, 0x50, 0xC6, 0xBC, 0x84, - 0x14, 0xF9, 0xBF, 0x50, 0xC8, 0x6C, 0x2D, 0x72, 0x35, 0xDA }, - { 0x4C, 0x1A, 0x03, 0x42, 0x4B, 0x55, 0xE0, 0x7F, 0xE7, 0xF2, - 0x7B, 0xE1 }, - { 0xAA, 0x4A, 0xE5, 0xE1, 0x52, 0x72, 0xD0, 0x0E, 0x95, 0x70, - 0x56, 0x37, 0xCE, 0x8A, 0x3B, 0x55, 0xED, 0x40, 0x21, 0x12 }, - { 0xE8, 0xE9, 0x9D, 0x0F, 0x45, 0x23, 0x7D, 0x78, 0x6D, 0x6B, - 0xBA, 0xA7, 0x96, 0x5C, 0x78, 0x08, 0xBB, 0xFF, 0x1A, 0x91 } -}; - /* * Checkup routine */ -int sha1_self_test( int verbose ) +int mbedtls_sha1_self_test( int verbose ) { int i, j, buflen, ret = 0; unsigned char buf[1024]; unsigned char sha1sum[20]; - sha1_context ctx; + mbedtls_sha1_context ctx; - sha1_init( &ctx ); + mbedtls_sha1_init( &ctx ); /* * SHA-1 @@ -584,82 +492,58 @@ int sha1_self_test( int verbose ) for( i = 0; i < 3; i++ ) { if( verbose != 0 ) - polarssl_printf( " SHA-1 test #%d: ", i + 1 ); + mbedtls_printf( " SHA-1 test #%d: ", i + 1 ); - sha1_starts( &ctx ); + if( ( ret = mbedtls_sha1_starts_ret( &ctx ) ) != 0 ) + goto fail; if( i == 2 ) { memset( buf, 'a', buflen = 1000 ); for( j = 0; j < 1000; j++ ) - sha1_update( &ctx, buf, buflen ); + { + ret = mbedtls_sha1_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } } else - sha1_update( &ctx, sha1_test_buf[i], - sha1_test_buflen[i] ); + { + ret = mbedtls_sha1_update_ret( &ctx, sha1_test_buf[i], + sha1_test_buflen[i] ); + if( ret != 0 ) + goto fail; + } - sha1_finish( &ctx, sha1sum ); + if( ( ret = mbedtls_sha1_finish_ret( &ctx, sha1sum ) ) != 0 ) + goto fail; if( memcmp( sha1sum, sha1_test_sum[i], 20 ) != 0 ) { - if( verbose != 0 ) - polarssl_printf( "failed\n" ); - ret = 1; - goto exit; + goto fail; } if( verbose != 0 ) - polarssl_printf( "passed\n" ); + mbedtls_printf( "passed\n" ); } if( verbose != 0 ) - polarssl_printf( "\n" ); + mbedtls_printf( "\n" ); - for( i = 0; i < 7; i++ ) - { - if( verbose != 0 ) - polarssl_printf( " HMAC-SHA-1 test #%d: ", i + 1 ); - - if( i == 5 || i == 6 ) - { - memset( buf, 0xAA, buflen = 80 ); - sha1_hmac_starts( &ctx, buf, buflen ); - } - else - sha1_hmac_starts( &ctx, sha1_hmac_test_key[i], - sha1_hmac_test_keylen[i] ); - - sha1_hmac_update( &ctx, sha1_hmac_test_buf[i], - sha1_hmac_test_buflen[i] ); - - sha1_hmac_finish( &ctx, sha1sum ); - - buflen = ( i == 4 ) ? 12 : 20; - - if( memcmp( sha1sum, sha1_hmac_test_sum[i], buflen ) != 0 ) - { - if( verbose != 0 ) - polarssl_printf( "failed\n" ); - - ret = 1; - goto exit; - } - - if( verbose != 0 ) - polarssl_printf( "passed\n" ); - } + goto exit; +fail: if( verbose != 0 ) - polarssl_printf( "\n" ); + mbedtls_printf( "failed\n" ); exit: - sha1_free( &ctx ); + mbedtls_sha1_free( &ctx ); return( ret ); } -#endif /* POLARSSL_SELF_TEST */ +#endif /* MBEDTLS_SELF_TEST */ -#endif /* POLARSSL_SHA1_C */ +#endif /* MBEDTLS_SHA1_C */ diff --git a/common/mbedtls/sha1.h b/common/mbedtls/sha1.h new file mode 100644 index 000000000..872fe1b05 --- /dev/null +++ b/common/mbedtls/sha1.h @@ -0,0 +1,326 @@ +/** + * \file sha1.h + * + * \brief This file contains SHA-1 definitions and functions. + * + * The Secure Hash Algorithm 1 (SHA-1) cryptographic hash function is defined in + * FIPS 180-4: Secure Hash Standard (SHS). + * + * \warning SHA-1 is considered a weak message digest and its use constitutes + * a security risk. We recommend considering stronger message + * digests instead. + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SHA1_H +#define MBEDTLS_SHA1_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_ERR_SHA1_HW_ACCEL_FAILED -0x0035 /**< SHA-1 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA1_ALT) +// Regular implementation +// + +/** + * \brief The SHA-1 context structure. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + */ +typedef struct mbedtls_sha1_context +{ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[5]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ +} +mbedtls_sha1_context; + +#else /* MBEDTLS_SHA1_ALT */ +#include "sha1_alt.h" +#endif /* MBEDTLS_SHA1_ALT */ + +/** + * \brief This function initializes a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. + * + */ +void mbedtls_sha1_init( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clears a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to clear. + * + */ +void mbedtls_sha1_free( mbedtls_sha1_context *ctx ); + +/** + * \brief This function clones the state of a SHA-1 context. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param dst The SHA-1 context to clone to. + * \param src The SHA-1 context to clone from. + * + */ +void mbedtls_sha1_clone( mbedtls_sha1_context *dst, + const mbedtls_sha1_context *src ); + +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context to initialize. + * + * \return \c 0 on success. + * + */ +int mbedtls_sha1_starts_ret( mbedtls_sha1_context *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + */ +int mbedtls_sha1_update_ret( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context. + * \param output The SHA-1 checksum result. + * + * \return \c 0 on success. + */ +int mbedtls_sha1_finish_ret( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param ctx The SHA-1 context. + * \param data The data block being processed. + * + * \return \c 0 on success. + * + */ +int mbedtls_internal_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-1 checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_starts_ret() in 2.7.0. + * + * \param ctx The SHA-1 context to initialize. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_starts( mbedtls_sha1_context *ctx ); + +/** + * \brief This function feeds an input buffer into an ongoing SHA-1 + * checksum calculation. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_update_ret() in 2.7.0. + * + * \param ctx The SHA-1 context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_update( mbedtls_sha1_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-1 operation, and writes + * the result to the output buffer. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_finish_ret() in 2.7.0. + * + * \param ctx The SHA-1 context. + * \param output The SHA-1 checksum result. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_finish( mbedtls_sha1_context *ctx, + unsigned char output[20] ); + +/** + * \brief SHA-1 process data block (internal use only). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_internal_sha1_process() in 2.7.0. + * + * \param ctx The SHA-1 context. + * \param data The data block being processed. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1_process( mbedtls_sha1_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-1 checksum result. + * + * \return \c 0 on success. + * + */ +int mbedtls_sha1_ret( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function calculates the SHA-1 checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-1 result is calculated as + * output = SHA-1(input buffer). + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \deprecated Superseded by mbedtls_sha1_ret() in 2.7.0 + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-1 checksum result. + * + */ +MBEDTLS_DEPRECATED void mbedtls_sha1( const unsigned char *input, + size_t ilen, + unsigned char output[20] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief The SHA-1 checkup routine. + * + * \warning SHA-1 is considered a weak message digest and its use + * constitutes a security risk. We recommend considering + * stronger message digests instead. + * + * \return \c 0 on success. + * \return \c 1 on failure. + * + */ +int mbedtls_sha1_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha1.h */ diff --git a/common/polarssl/sha256.c b/common/mbedtls/sha256.c similarity index 70% rename from common/polarssl/sha256.c rename to common/mbedtls/sha256.c index d5e702218..06b5f7a7b 100644 --- a/common/polarssl/sha256.c +++ b/common/mbedtls/sha256.c @@ -1,9 +1,8 @@ /* * 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) + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 * * 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 @@ -18,6 +17,8 @@ * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) */ /* * The SHA-256 Secure Hash Standard was published by NIST in 2002. @@ -26,7 +27,7 @@ */ #if !defined(MBEDTLS_CONFIG_FILE) -//#include "mbedtls/config.h" +#include "mbedtls/config.h" #else #include MBEDTLS_CONFIG_FILE #endif @@ -34,6 +35,7 @@ #if defined(MBEDTLS_SHA256_C) #include "mbedtls/sha256.h" +#include "mbedtls/platform_util.h" #include @@ -42,15 +44,13 @@ #include "mbedtls/platform.h" #else #include +#include #define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free #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) /* @@ -86,7 +86,7 @@ void mbedtls_sha256_free( mbedtls_sha256_context *ctx ) if( ctx == NULL ) return; - mbedtls_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha256_context ) ); } void mbedtls_sha256_clone( mbedtls_sha256_context *dst, @@ -98,7 +98,7 @@ void mbedtls_sha256_clone( mbedtls_sha256_context *dst, /* * SHA-256 context setup */ -void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ) { ctx->total[0] = 0; ctx->total[1] = 0; @@ -129,8 +129,18 @@ void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, int is224 ) } ctx->is224 = is224; + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ) +{ + mbedtls_sha256_starts_ret( ctx, is224 ); +} +#endif + #if !defined(MBEDTLS_SHA256_PROCESS_ALT) static const uint32_t K[] = { @@ -177,7 +187,8 @@ static const uint32_t K[] = d += temp1; h = temp1 + temp2; \ } -void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char data[64] ) +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) { uint32_t temp1, temp2, W[64]; uint32_t A[8]; @@ -230,20 +241,32 @@ void mbedtls_sha256_process( mbedtls_sha256_context *ctx, const unsigned char da for( i = 0; i < 8; i++ ) ctx->state[i] += A[i]; + + return( 0 ); } + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ) +{ + mbedtls_internal_sha256_process( ctx, data ); +} +#endif #endif /* !MBEDTLS_SHA256_PROCESS_ALT */ /* * SHA-256 process buffer */ -void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *input, - size_t ilen ) +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) { + int ret; size_t fill; uint32_t left; if( ilen == 0 ) - return; + return( 0 ); left = ctx->total[0] & 0x3F; fill = 64 - left; @@ -257,7 +280,10 @@ void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *in if( left && ilen >= fill ) { memcpy( (void *) (ctx->buffer + left), input, fill ); - mbedtls_sha256_process( ctx, ctx->buffer ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + input += fill; ilen -= fill; left = 0; @@ -265,45 +291,77 @@ void mbedtls_sha256_update( mbedtls_sha256_context *ctx, const unsigned char *in while( ilen >= 64 ) { - mbedtls_sha256_process( ctx, input ); + if( ( ret = mbedtls_internal_sha256_process( ctx, input ) ) != 0 ) + return( ret ); + input += 64; ilen -= 64; } if( ilen > 0 ) memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); } -static const unsigned char sha256_padding[64] = +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ) { - 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 -}; + mbedtls_sha256_update_ret( ctx, input, ilen ); +} +#endif /* * SHA-256 final digest */ -void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32] ) +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ) { - uint32_t last, padn; + int ret; + uint32_t used; uint32_t high, low; - unsigned char msglen[8]; + /* + * Add padding: 0x80 then 0x00 until 8 bytes remain for the length + */ + used = ctx->total[0] & 0x3F; + + ctx->buffer[used++] = 0x80; + + if( used <= 56 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 56 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 64 - used ); + + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 56 ); + } + + /* + * Add message length + */ 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 ); + PUT_UINT32_BE( high, ctx->buffer, 56 ); + PUT_UINT32_BE( low, ctx->buffer, 60 ); - 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 ); + if( ( ret = mbedtls_internal_sha256_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + /* + * Output final state + */ PUT_UINT32_BE( ctx->state[0], output, 0 ); PUT_UINT32_BE( ctx->state[1], output, 4 ); PUT_UINT32_BE( ctx->state[2], output, 8 ); @@ -314,25 +372,58 @@ void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, unsigned char output[32 if( ctx->is224 == 0 ) PUT_UINT32_BE( ctx->state[7], output, 28 ); + + return( 0 ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ) +{ + mbedtls_sha256_finish_ret( ctx, output ); +} +#endif + #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 ) +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ) { + int ret; mbedtls_sha256_context ctx; mbedtls_sha256_init( &ctx ); - mbedtls_sha256_starts( &ctx, is224 ); - mbedtls_sha256_update( &ctx, input, ilen ); - mbedtls_sha256_finish( &ctx, output ); + + if( ( ret = mbedtls_sha256_starts_ret( &ctx, is224 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha256_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: mbedtls_sha256_free( &ctx ); + + return( ret ); } +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ) +{ + mbedtls_sha256_ret( input, ilen, output, is224 ); +} +#endif + #if defined(MBEDTLS_SELF_TEST) /* * FIPS-180-2 test vectors @@ -344,7 +435,7 @@ static const unsigned char sha256_test_buf[3][57] = { "" } }; -static const int sha256_test_buflen[3] = +static const size_t sha256_test_buflen[3] = { 3, 56, 1000 }; @@ -390,10 +481,19 @@ static const unsigned char sha256_test_sum[6][32] = int mbedtls_sha256_self_test( int verbose ) { int i, j, k, buflen, ret = 0; - unsigned char buf[1024]; + unsigned char *buf; unsigned char sha256sum[32]; mbedtls_sha256_context ctx; + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); + + return( 1 ); + } + mbedtls_sha256_init( &ctx ); for( i = 0; i < 6; i++ ) @@ -404,28 +504,37 @@ int mbedtls_sha256_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( " SHA-%d test #%d: ", 256 - k * 32, j + 1 ); - mbedtls_sha256_starts( &ctx, k ); + if( ( ret = mbedtls_sha256_starts_ret( &ctx, k ) ) != 0 ) + goto fail; if( j == 2 ) { memset( buf, 'a', buflen = 1000 ); for( j = 0; j < 1000; j++ ) - mbedtls_sha256_update( &ctx, buf, buflen ); + { + ret = mbedtls_sha256_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } else - mbedtls_sha256_update( &ctx, sha256_test_buf[j], - sha256_test_buflen[j] ); + { + ret = mbedtls_sha256_update_ret( &ctx, sha256_test_buf[j], + sha256_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha256_finish_ret( &ctx, sha256sum ) ) != 0 ) + goto fail; - 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; + goto fail; } if( verbose != 0 ) @@ -435,8 +544,15 @@ int mbedtls_sha256_self_test( int verbose ) if( verbose != 0 ) mbedtls_printf( "\n" ); + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + exit: mbedtls_sha256_free( &ctx ); + mbedtls_free( buf ); return( ret ); } diff --git a/common/mbedtls/sha256.h b/common/mbedtls/sha256.h new file mode 100644 index 000000000..0aebdde25 --- /dev/null +++ b/common/mbedtls/sha256.h @@ -0,0 +1,274 @@ +/** + * \file sha256.h + * + * \brief This file contains SHA-224 and SHA-256 definitions and functions. + * + * The Secure Hash Algorithms 224 and 256 (SHA-224 and SHA-256) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SHA256_H +#define MBEDTLS_SHA256_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_ERR_SHA256_HW_ACCEL_FAILED -0x0037 /**< SHA-256 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA256_ALT) +// Regular implementation +// + +/** + * \brief The SHA-256 context structure. + * + * The structure is used both for SHA-256 and for SHA-224 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha256_starts_ret(). + */ +typedef struct mbedtls_sha256_context +{ + uint32_t total[2]; /*!< The number of Bytes processed. */ + uint32_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[64]; /*!< The data block being processed. */ + int is224; /*!< Determines which function to use: + 0: Use SHA-256, or 1: Use SHA-224. */ +} +mbedtls_sha256_context; + +#else /* MBEDTLS_SHA256_ALT */ +#include "sha256_alt.h" +#endif /* MBEDTLS_SHA256_ALT */ + +/** + * \brief This function initializes a SHA-256 context. + * + * \param ctx The SHA-256 context to initialize. + */ +void mbedtls_sha256_init( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clears a SHA-256 context. + * + * \param ctx The SHA-256 context to clear. + */ +void mbedtls_sha256_free( mbedtls_sha256_context *ctx ); + +/** + * \brief This function clones the state of a SHA-256 context. + * + * \param dst The destination context. + * \param src The context to clone. + */ +void mbedtls_sha256_clone( mbedtls_sha256_context *dst, + const mbedtls_sha256_context *src ); + +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * \param ctx The context to initialize. + * \param is224 Determines which function to use: + * 0: Use SHA-256, or 1: Use SHA-224. + * + * \return \c 0 on success. + */ +int mbedtls_sha256_starts_ret( mbedtls_sha256_context *ctx, int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \param ctx The SHA-256 context. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + */ +int mbedtls_sha256_update_ret( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \param ctx The SHA-256 context. + * \param output The SHA-224 or SHA-256 checksum result. + * + * \return \c 0 on success. + */ +int mbedtls_sha256_finish_ret( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \param ctx The SHA-256 context. + * \param data The buffer holding one block of data. + * + * \return \c 0 on success. + */ +int mbedtls_internal_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-224 or SHA-256 checksum + * calculation. + * + * + * \deprecated Superseded by mbedtls_sha256_starts_ret() in 2.7.0. + * + * \param ctx The context to initialize. + * \param is224 Determines which function to use: + * 0: Use SHA-256, or 1: Use SHA-224. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_starts( mbedtls_sha256_context *ctx, + int is224 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-256 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha256_update_ret() in 2.7.0. + * + * \param ctx The SHA-256 context to initialize. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_update( mbedtls_sha256_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-256 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha256_finish_ret() in 2.7.0. + * + * \param ctx The SHA-256 context. + * \param output The SHA-224 or SHA-256 checksum result. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_finish( mbedtls_sha256_context *ctx, + unsigned char output[32] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-256 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha256_process() in 2.7.0. + * + * \param ctx The SHA-256 context. + * \param data The buffer holding one block of data. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256_process( mbedtls_sha256_context *ctx, + const unsigned char data[64] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-224 or SHA-256 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-224 or SHA-256 checksum result. + * \param is224 Determines which function to use: + * 0: Use SHA-256, or 1: Use SHA-224. + */ +int mbedtls_sha256_ret( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif + +/** + * \brief This function calculates the SHA-224 or SHA-256 checksum + * of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-256 result is calculated as + * output = SHA-256(input buffer). + * + * \deprecated Superseded by mbedtls_sha256_ret() in 2.7.0. + * + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The SHA-224 or SHA-256 checksum result. + * \param is224 Determines which function to use: + * 0: Use SHA-256, or 1: Use SHA-224. + */ +MBEDTLS_DEPRECATED void mbedtls_sha256( const unsigned char *input, + size_t ilen, + unsigned char output[32], + int is224 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief The SHA-224 and SHA-256 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha256_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha256.h */ diff --git a/common/mbedtls/sha512.c b/common/mbedtls/sha512.c new file mode 100644 index 000000000..331965dae --- /dev/null +++ b/common/mbedtls/sha512.c @@ -0,0 +1,612 @@ +/* + * FIPS-180-2 compliant SHA-384/512 implementation + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The SHA-512 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_SHA512_C) + +#include "mbedtls/sha512.h" +#include "mbedtls/platform_util.h" + +#if defined(_MSC_VER) || defined(__WATCOMC__) + #define UL64(x) x##ui64 +#else + #define UL64(x) x##ULL +#endif + +#include + +#if defined(MBEDTLS_SELF_TEST) +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_printf printf +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif /* MBEDTLS_PLATFORM_C */ +#endif /* MBEDTLS_SELF_TEST */ + +#if !defined(MBEDTLS_SHA512_ALT) + +/* + * 64-bit integer manipulation macros (big endian) + */ +#ifndef GET_UINT64_BE +#define GET_UINT64_BE(n,b,i) \ +{ \ + (n) = ( (uint64_t) (b)[(i) ] << 56 ) \ + | ( (uint64_t) (b)[(i) + 1] << 48 ) \ + | ( (uint64_t) (b)[(i) + 2] << 40 ) \ + | ( (uint64_t) (b)[(i) + 3] << 32 ) \ + | ( (uint64_t) (b)[(i) + 4] << 24 ) \ + | ( (uint64_t) (b)[(i) + 5] << 16 ) \ + | ( (uint64_t) (b)[(i) + 6] << 8 ) \ + | ( (uint64_t) (b)[(i) + 7] ); \ +} +#endif /* GET_UINT64_BE */ + +#ifndef PUT_UINT64_BE +#define PUT_UINT64_BE(n,b,i) \ +{ \ + (b)[(i) ] = (unsigned char) ( (n) >> 56 ); \ + (b)[(i) + 1] = (unsigned char) ( (n) >> 48 ); \ + (b)[(i) + 2] = (unsigned char) ( (n) >> 40 ); \ + (b)[(i) + 3] = (unsigned char) ( (n) >> 32 ); \ + (b)[(i) + 4] = (unsigned char) ( (n) >> 24 ); \ + (b)[(i) + 5] = (unsigned char) ( (n) >> 16 ); \ + (b)[(i) + 6] = (unsigned char) ( (n) >> 8 ); \ + (b)[(i) + 7] = (unsigned char) ( (n) ); \ +} +#endif /* PUT_UINT64_BE */ + +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ) +{ + memset( ctx, 0, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ) +{ + if( ctx == NULL ) + return; + + mbedtls_platform_zeroize( ctx, sizeof( mbedtls_sha512_context ) ); +} + +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ) +{ + *dst = *src; +} + +/* + * SHA-512 context setup + */ +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ) +{ + ctx->total[0] = 0; + ctx->total[1] = 0; + + if( is384 == 0 ) + { + /* SHA-512 */ + ctx->state[0] = UL64(0x6A09E667F3BCC908); + ctx->state[1] = UL64(0xBB67AE8584CAA73B); + ctx->state[2] = UL64(0x3C6EF372FE94F82B); + ctx->state[3] = UL64(0xA54FF53A5F1D36F1); + ctx->state[4] = UL64(0x510E527FADE682D1); + ctx->state[5] = UL64(0x9B05688C2B3E6C1F); + ctx->state[6] = UL64(0x1F83D9ABFB41BD6B); + ctx->state[7] = UL64(0x5BE0CD19137E2179); + } + else + { + /* SHA-384 */ + ctx->state[0] = UL64(0xCBBB9D5DC1059ED8); + ctx->state[1] = UL64(0x629A292A367CD507); + ctx->state[2] = UL64(0x9159015A3070DD17); + ctx->state[3] = UL64(0x152FECD8F70E5939); + ctx->state[4] = UL64(0x67332667FFC00B31); + ctx->state[5] = UL64(0x8EB44A8768581511); + ctx->state[6] = UL64(0xDB0C2E0D64F98FA7); + ctx->state[7] = UL64(0x47B5481DBEFA4FA4); + } + + ctx->is384 = is384; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ) +{ + mbedtls_sha512_starts_ret( ctx, is384 ); +} +#endif + +#if !defined(MBEDTLS_SHA512_PROCESS_ALT) + +/* + * Round constants + */ +static const uint64_t K[80] = +{ + UL64(0x428A2F98D728AE22), UL64(0x7137449123EF65CD), + UL64(0xB5C0FBCFEC4D3B2F), UL64(0xE9B5DBA58189DBBC), + UL64(0x3956C25BF348B538), UL64(0x59F111F1B605D019), + UL64(0x923F82A4AF194F9B), UL64(0xAB1C5ED5DA6D8118), + UL64(0xD807AA98A3030242), UL64(0x12835B0145706FBE), + UL64(0x243185BE4EE4B28C), UL64(0x550C7DC3D5FFB4E2), + UL64(0x72BE5D74F27B896F), UL64(0x80DEB1FE3B1696B1), + UL64(0x9BDC06A725C71235), UL64(0xC19BF174CF692694), + UL64(0xE49B69C19EF14AD2), UL64(0xEFBE4786384F25E3), + UL64(0x0FC19DC68B8CD5B5), UL64(0x240CA1CC77AC9C65), + UL64(0x2DE92C6F592B0275), UL64(0x4A7484AA6EA6E483), + UL64(0x5CB0A9DCBD41FBD4), UL64(0x76F988DA831153B5), + UL64(0x983E5152EE66DFAB), UL64(0xA831C66D2DB43210), + UL64(0xB00327C898FB213F), UL64(0xBF597FC7BEEF0EE4), + UL64(0xC6E00BF33DA88FC2), UL64(0xD5A79147930AA725), + UL64(0x06CA6351E003826F), UL64(0x142929670A0E6E70), + UL64(0x27B70A8546D22FFC), UL64(0x2E1B21385C26C926), + UL64(0x4D2C6DFC5AC42AED), UL64(0x53380D139D95B3DF), + UL64(0x650A73548BAF63DE), UL64(0x766A0ABB3C77B2A8), + UL64(0x81C2C92E47EDAEE6), UL64(0x92722C851482353B), + UL64(0xA2BFE8A14CF10364), UL64(0xA81A664BBC423001), + UL64(0xC24B8B70D0F89791), UL64(0xC76C51A30654BE30), + UL64(0xD192E819D6EF5218), UL64(0xD69906245565A910), + UL64(0xF40E35855771202A), UL64(0x106AA07032BBD1B8), + UL64(0x19A4C116B8D2D0C8), UL64(0x1E376C085141AB53), + UL64(0x2748774CDF8EEB99), UL64(0x34B0BCB5E19B48A8), + UL64(0x391C0CB3C5C95A63), UL64(0x4ED8AA4AE3418ACB), + UL64(0x5B9CCA4F7763E373), UL64(0x682E6FF3D6B2B8A3), + UL64(0x748F82EE5DEFB2FC), UL64(0x78A5636F43172F60), + UL64(0x84C87814A1F0AB72), UL64(0x8CC702081A6439EC), + UL64(0x90BEFFFA23631E28), UL64(0xA4506CEBDE82BDE9), + UL64(0xBEF9A3F7B2C67915), UL64(0xC67178F2E372532B), + UL64(0xCA273ECEEA26619C), UL64(0xD186B8C721C0C207), + UL64(0xEADA7DD6CDE0EB1E), UL64(0xF57D4F7FEE6ED178), + UL64(0x06F067AA72176FBA), UL64(0x0A637DC5A2C898A6), + UL64(0x113F9804BEF90DAE), UL64(0x1B710B35131C471B), + UL64(0x28DB77F523047D84), UL64(0x32CAAB7B40C72493), + UL64(0x3C9EBE0A15C9BEBC), UL64(0x431D67C49C100D4C), + UL64(0x4CC5D4BECB3E42B6), UL64(0x597F299CFC657E2A), + UL64(0x5FCB6FAB3AD6FAEC), UL64(0x6C44198C4A475817) +}; + +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + int i; + uint64_t temp1, temp2, W[80]; + uint64_t A, B, C, D, E, F, G, H; + +#define SHR(x,n) (x >> n) +#define ROTR(x,n) (SHR(x,n) | (x << (64 - n))) + +#define S0(x) (ROTR(x, 1) ^ ROTR(x, 8) ^ SHR(x, 7)) +#define S1(x) (ROTR(x,19) ^ ROTR(x,61) ^ SHR(x, 6)) + +#define S2(x) (ROTR(x,28) ^ ROTR(x,34) ^ ROTR(x,39)) +#define S3(x) (ROTR(x,14) ^ ROTR(x,18) ^ ROTR(x,41)) + +#define F0(x,y,z) ((x & y) | (z & (x | y))) +#define F1(x,y,z) (z ^ (x & (y ^ z))) + +#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; \ +} + + for( i = 0; i < 16; i++ ) + { + GET_UINT64_BE( W[i], data, i << 3 ); + } + + for( ; i < 80; i++ ) + { + W[i] = S1(W[i - 2]) + W[i - 7] + + S0(W[i - 15]) + W[i - 16]; + } + + A = ctx->state[0]; + B = ctx->state[1]; + C = ctx->state[2]; + D = ctx->state[3]; + E = ctx->state[4]; + F = ctx->state[5]; + G = ctx->state[6]; + H = ctx->state[7]; + i = 0; + + do + { + P( A, B, C, D, E, F, G, H, W[i], K[i] ); i++; + P( H, A, B, C, D, E, F, G, W[i], K[i] ); i++; + P( G, H, A, B, C, D, E, F, W[i], K[i] ); i++; + P( F, G, H, A, B, C, D, E, W[i], K[i] ); i++; + P( E, F, G, H, A, B, C, D, W[i], K[i] ); i++; + P( D, E, F, G, H, A, B, C, W[i], K[i] ); i++; + P( C, D, E, F, G, H, A, B, W[i], K[i] ); i++; + P( B, C, D, E, F, G, H, A, W[i], K[i] ); i++; + } + while( i < 80 ); + + ctx->state[0] += A; + ctx->state[1] += B; + ctx->state[2] += C; + ctx->state[3] += D; + ctx->state[4] += E; + ctx->state[5] += F; + ctx->state[6] += G; + ctx->state[7] += H; + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ) +{ + mbedtls_internal_sha512_process( ctx, data ); +} +#endif +#endif /* !MBEDTLS_SHA512_PROCESS_ALT */ + +/* + * SHA-512 process buffer + */ +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + int ret; + size_t fill; + unsigned int left; + + if( ilen == 0 ) + return( 0 ); + + left = (unsigned int) (ctx->total[0] & 0x7F); + fill = 128 - left; + + ctx->total[0] += (uint64_t) ilen; + + if( ctx->total[0] < (uint64_t) ilen ) + ctx->total[1]++; + + if( left && ilen >= fill ) + { + memcpy( (void *) (ctx->buffer + left), input, fill ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + input += fill; + ilen -= fill; + left = 0; + } + + while( ilen >= 128 ) + { + if( ( ret = mbedtls_internal_sha512_process( ctx, input ) ) != 0 ) + return( ret ); + + input += 128; + ilen -= 128; + } + + if( ilen > 0 ) + memcpy( (void *) (ctx->buffer + left), input, ilen ); + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ) +{ + mbedtls_sha512_update_ret( ctx, input, ilen ); +} +#endif + +/* + * SHA-512 final digest + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + int ret; + unsigned used; + uint64_t high, low; + + /* + * Add padding: 0x80 then 0x00 until 16 bytes remain for the length + */ + used = ctx->total[0] & 0x7F; + + ctx->buffer[used++] = 0x80; + + if( used <= 112 ) + { + /* Enough room for padding + length in current block */ + memset( ctx->buffer + used, 0, 112 - used ); + } + else + { + /* We'll need an extra block */ + memset( ctx->buffer + used, 0, 128 - used ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + memset( ctx->buffer, 0, 112 ); + } + + /* + * Add message length + */ + high = ( ctx->total[0] >> 61 ) + | ( ctx->total[1] << 3 ); + low = ( ctx->total[0] << 3 ); + + PUT_UINT64_BE( high, ctx->buffer, 112 ); + PUT_UINT64_BE( low, ctx->buffer, 120 ); + + if( ( ret = mbedtls_internal_sha512_process( ctx, ctx->buffer ) ) != 0 ) + return( ret ); + + /* + * Output final state + */ + PUT_UINT64_BE( ctx->state[0], output, 0 ); + PUT_UINT64_BE( ctx->state[1], output, 8 ); + PUT_UINT64_BE( ctx->state[2], output, 16 ); + PUT_UINT64_BE( ctx->state[3], output, 24 ); + PUT_UINT64_BE( ctx->state[4], output, 32 ); + PUT_UINT64_BE( ctx->state[5], output, 40 ); + + if( ctx->is384 == 0 ) + { + PUT_UINT64_BE( ctx->state[6], output, 48 ); + PUT_UINT64_BE( ctx->state[7], output, 56 ); + } + + return( 0 ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ) +{ + mbedtls_sha512_finish_ret( ctx, output ); +} +#endif + +#endif /* !MBEDTLS_SHA512_ALT */ + +/* + * output = SHA-512( input buffer ) + */ +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ) +{ + int ret; + mbedtls_sha512_context ctx; + + mbedtls_sha512_init( &ctx ); + + if( ( ret = mbedtls_sha512_starts_ret( &ctx, is384 ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_update_ret( &ctx, input, ilen ) ) != 0 ) + goto exit; + + if( ( ret = mbedtls_sha512_finish_ret( &ctx, output ) ) != 0 ) + goto exit; + +exit: + mbedtls_sha512_free( &ctx ); + + return( ret ); +} + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ) +{ + mbedtls_sha512_ret( input, ilen, output, is384 ); +} +#endif + +#if defined(MBEDTLS_SELF_TEST) + +/* + * FIPS-180-2 test vectors + */ +static const unsigned char sha512_test_buf[3][113] = +{ + { "abc" }, + { "abcdefghbcdefghicdefghijdefghijkefghijklfghijklmghijklmn" + "hijklmnoijklmnopjklmnopqklmnopqrlmnopqrsmnopqrstnopqrstu" }, + { "" } +}; + +static const size_t sha512_test_buflen[3] = +{ + 3, 112, 1000 +}; + +static const unsigned char sha512_test_sum[6][64] = +{ + /* + * SHA-384 test vectors + */ + { 0xCB, 0x00, 0x75, 0x3F, 0x45, 0xA3, 0x5E, 0x8B, + 0xB5, 0xA0, 0x3D, 0x69, 0x9A, 0xC6, 0x50, 0x07, + 0x27, 0x2C, 0x32, 0xAB, 0x0E, 0xDE, 0xD1, 0x63, + 0x1A, 0x8B, 0x60, 0x5A, 0x43, 0xFF, 0x5B, 0xED, + 0x80, 0x86, 0x07, 0x2B, 0xA1, 0xE7, 0xCC, 0x23, + 0x58, 0xBA, 0xEC, 0xA1, 0x34, 0xC8, 0x25, 0xA7 }, + { 0x09, 0x33, 0x0C, 0x33, 0xF7, 0x11, 0x47, 0xE8, + 0x3D, 0x19, 0x2F, 0xC7, 0x82, 0xCD, 0x1B, 0x47, + 0x53, 0x11, 0x1B, 0x17, 0x3B, 0x3B, 0x05, 0xD2, + 0x2F, 0xA0, 0x80, 0x86, 0xE3, 0xB0, 0xF7, 0x12, + 0xFC, 0xC7, 0xC7, 0x1A, 0x55, 0x7E, 0x2D, 0xB9, + 0x66, 0xC3, 0xE9, 0xFA, 0x91, 0x74, 0x60, 0x39 }, + { 0x9D, 0x0E, 0x18, 0x09, 0x71, 0x64, 0x74, 0xCB, + 0x08, 0x6E, 0x83, 0x4E, 0x31, 0x0A, 0x4A, 0x1C, + 0xED, 0x14, 0x9E, 0x9C, 0x00, 0xF2, 0x48, 0x52, + 0x79, 0x72, 0xCE, 0xC5, 0x70, 0x4C, 0x2A, 0x5B, + 0x07, 0xB8, 0xB3, 0xDC, 0x38, 0xEC, 0xC4, 0xEB, + 0xAE, 0x97, 0xDD, 0xD8, 0x7F, 0x3D, 0x89, 0x85 }, + + /* + * SHA-512 test vectors + */ + { 0xDD, 0xAF, 0x35, 0xA1, 0x93, 0x61, 0x7A, 0xBA, + 0xCC, 0x41, 0x73, 0x49, 0xAE, 0x20, 0x41, 0x31, + 0x12, 0xE6, 0xFA, 0x4E, 0x89, 0xA9, 0x7E, 0xA2, + 0x0A, 0x9E, 0xEE, 0xE6, 0x4B, 0x55, 0xD3, 0x9A, + 0x21, 0x92, 0x99, 0x2A, 0x27, 0x4F, 0xC1, 0xA8, + 0x36, 0xBA, 0x3C, 0x23, 0xA3, 0xFE, 0xEB, 0xBD, + 0x45, 0x4D, 0x44, 0x23, 0x64, 0x3C, 0xE8, 0x0E, + 0x2A, 0x9A, 0xC9, 0x4F, 0xA5, 0x4C, 0xA4, 0x9F }, + { 0x8E, 0x95, 0x9B, 0x75, 0xDA, 0xE3, 0x13, 0xDA, + 0x8C, 0xF4, 0xF7, 0x28, 0x14, 0xFC, 0x14, 0x3F, + 0x8F, 0x77, 0x79, 0xC6, 0xEB, 0x9F, 0x7F, 0xA1, + 0x72, 0x99, 0xAE, 0xAD, 0xB6, 0x88, 0x90, 0x18, + 0x50, 0x1D, 0x28, 0x9E, 0x49, 0x00, 0xF7, 0xE4, + 0x33, 0x1B, 0x99, 0xDE, 0xC4, 0xB5, 0x43, 0x3A, + 0xC7, 0xD3, 0x29, 0xEE, 0xB6, 0xDD, 0x26, 0x54, + 0x5E, 0x96, 0xE5, 0x5B, 0x87, 0x4B, 0xE9, 0x09 }, + { 0xE7, 0x18, 0x48, 0x3D, 0x0C, 0xE7, 0x69, 0x64, + 0x4E, 0x2E, 0x42, 0xC7, 0xBC, 0x15, 0xB4, 0x63, + 0x8E, 0x1F, 0x98, 0xB1, 0x3B, 0x20, 0x44, 0x28, + 0x56, 0x32, 0xA8, 0x03, 0xAF, 0xA9, 0x73, 0xEB, + 0xDE, 0x0F, 0xF2, 0x44, 0x87, 0x7E, 0xA6, 0x0A, + 0x4C, 0xB0, 0x43, 0x2C, 0xE5, 0x77, 0xC3, 0x1B, + 0xEB, 0x00, 0x9C, 0x5C, 0x2C, 0x49, 0xAA, 0x2E, + 0x4E, 0xAD, 0xB2, 0x17, 0xAD, 0x8C, 0xC0, 0x9B } +}; + +/* + * Checkup routine + */ +int mbedtls_sha512_self_test( int verbose ) +{ + int i, j, k, buflen, ret = 0; + unsigned char *buf; + unsigned char sha512sum[64]; + mbedtls_sha512_context ctx; + + buf = mbedtls_calloc( 1024, sizeof(unsigned char) ); + if( NULL == buf ) + { + if( verbose != 0 ) + mbedtls_printf( "Buffer allocation failed\n" ); + + return( 1 ); + } + + mbedtls_sha512_init( &ctx ); + + for( i = 0; i < 6; i++ ) + { + j = i % 3; + k = i < 3; + + if( verbose != 0 ) + mbedtls_printf( " SHA-%d test #%d: ", 512 - k * 128, j + 1 ); + + if( ( ret = mbedtls_sha512_starts_ret( &ctx, k ) ) != 0 ) + goto fail; + + if( j == 2 ) + { + memset( buf, 'a', buflen = 1000 ); + + for( j = 0; j < 1000; j++ ) + { + ret = mbedtls_sha512_update_ret( &ctx, buf, buflen ); + if( ret != 0 ) + goto fail; + } + } + else + { + ret = mbedtls_sha512_update_ret( &ctx, sha512_test_buf[j], + sha512_test_buflen[j] ); + if( ret != 0 ) + goto fail; + } + + if( ( ret = mbedtls_sha512_finish_ret( &ctx, sha512sum ) ) != 0 ) + goto fail; + + if( memcmp( sha512sum, sha512_test_sum[i], 64 - k * 16 ) != 0 ) + { + ret = 1; + goto fail; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + } + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + goto exit; + +fail: + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + +exit: + mbedtls_sha512_free( &ctx ); + mbedtls_free( buf ); + + return( ret ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_SHA512_C */ diff --git a/common/mbedtls/sha512.h b/common/mbedtls/sha512.h new file mode 100644 index 000000000..18f6a1802 --- /dev/null +++ b/common/mbedtls/sha512.h @@ -0,0 +1,272 @@ +/** + * \file sha512.h + * \brief This file contains SHA-384 and SHA-512 definitions and functions. + * + * The Secure Hash Algorithms 384 and 512 (SHA-384 and SHA-512) cryptographic + * hash functions are defined in FIPS 180-4: Secure Hash Standard (SHS). + */ +/* + * Copyright (C) 2006-2018, Arm Limited (or its affiliates), All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of Mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_SHA512_H +#define MBEDTLS_SHA512_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include +#include + +#define MBEDTLS_ERR_SHA512_HW_ACCEL_FAILED -0x0039 /**< SHA-512 hardware accelerator failed */ + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_SHA512_ALT) +// Regular implementation +// + +/** + * \brief The SHA-512 context structure. + * + * The structure is used both for SHA-384 and for SHA-512 + * checksum calculations. The choice between these two is + * made in the call to mbedtls_sha512_starts_ret(). + */ +typedef struct mbedtls_sha512_context +{ + uint64_t total[2]; /*!< The number of Bytes processed. */ + uint64_t state[8]; /*!< The intermediate digest state. */ + unsigned char buffer[128]; /*!< The data block being processed. */ + int is384; /*!< Determines which function to use: + 0: Use SHA-512, or 1: Use SHA-384. */ +} +mbedtls_sha512_context; + +#else /* MBEDTLS_SHA512_ALT */ +#include "sha512_alt.h" +#endif /* MBEDTLS_SHA512_ALT */ + +/** + * \brief This function initializes a SHA-512 context. + * + * \param ctx The SHA-512 context to initialize. + */ +void mbedtls_sha512_init( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clears a SHA-512 context. + * + * \param ctx The SHA-512 context to clear. + */ +void mbedtls_sha512_free( mbedtls_sha512_context *ctx ); + +/** + * \brief This function clones the state of a SHA-512 context. + * + * \param dst The destination context. + * \param src The context to clone. + */ +void mbedtls_sha512_clone( mbedtls_sha512_context *dst, + const mbedtls_sha512_context *src ); + +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \param ctx The SHA-512 context to initialize. + * \param is384 Determines which function to use: + * 0: Use SHA-512, or 1: Use SHA-384. + * + * \return \c 0 on success. + */ +int mbedtls_sha512_starts_ret( mbedtls_sha512_context *ctx, int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \param ctx The SHA-512 context. + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * + * \return \c 0 on success. + */ +int mbedtls_sha512_update_ret( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. This function is for + * internal use only. + * + * \param ctx The SHA-512 context. + * \param output The SHA-384 or SHA-512 checksum result. + * + * \return \c 0 on success. + */ +int mbedtls_sha512_finish_ret( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. + * + * \param ctx The SHA-512 context. + * \param data The buffer holding one block of data. + * + * \return \c 0 on success. + */ +int mbedtls_internal_sha512_process( mbedtls_sha512_context *ctx, + const unsigned char data[128] ); +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function starts a SHA-384 or SHA-512 checksum + * calculation. + * + * \deprecated Superseded by mbedtls_sha512_starts_ret() in 2.7.0 + * + * \param ctx The SHA-512 context to initialize. + * \param is384 Determines which function to use: + * 0: Use SHA-512, or 1: Use SHA-384. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_starts( mbedtls_sha512_context *ctx, + int is384 ); + +/** + * \brief This function feeds an input buffer into an ongoing + * SHA-512 checksum calculation. + * + * \deprecated Superseded by mbedtls_sha512_update_ret() in 2.7.0. + * + * \param ctx The SHA-512 context. + * \param input The buffer holding the data. + * \param ilen The length of the input data. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_update( mbedtls_sha512_context *ctx, + const unsigned char *input, + size_t ilen ); + +/** + * \brief This function finishes the SHA-512 operation, and writes + * the result to the output buffer. + * + * \deprecated Superseded by mbedtls_sha512_finish_ret() in 2.7.0. + * + * \param ctx The SHA-512 context. + * \param output The SHA-384 or SHA-512 checksum result. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_finish( mbedtls_sha512_context *ctx, + unsigned char output[64] ); + +/** + * \brief This function processes a single data block within + * the ongoing SHA-512 computation. This function is for + * internal use only. + * + * \deprecated Superseded by mbedtls_internal_sha512_process() in 2.7.0. + * + * \param ctx The SHA-512 context. + * \param data The buffer holding one block of data. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512_process( + mbedtls_sha512_context *ctx, + const unsigned char data[128] ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \param input The buffer holding the input data. + * \param ilen The length of the input data. + * \param output The SHA-384 or SHA-512 checksum result. + * \param is384 Determines which function to use: + * 0: Use SHA-512, or 1: Use SHA-384. + * + * \return \c 0 on success. + */ +int mbedtls_sha512_ret( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#if !defined(MBEDTLS_DEPRECATED_REMOVED) +#if defined(MBEDTLS_DEPRECATED_WARNING) +#define MBEDTLS_DEPRECATED __attribute__((deprecated)) +#else +#define MBEDTLS_DEPRECATED +#endif +/** + * \brief This function calculates the SHA-512 or SHA-384 + * checksum of a buffer. + * + * The function allocates the context, performs the + * calculation, and frees the context. + * + * The SHA-512 result is calculated as + * output = SHA-512(input buffer). + * + * \deprecated Superseded by mbedtls_sha512_ret() in 2.7.0 + * + * \param input The buffer holding the data. + * \param ilen The length of the input data. + * \param output The SHA-384 or SHA-512 checksum result. + * \param is384 Determines which function to use: + * 0: Use SHA-512, or 1: Use SHA-384. + */ +MBEDTLS_DEPRECATED void mbedtls_sha512( const unsigned char *input, + size_t ilen, + unsigned char output[64], + int is384 ); + +#undef MBEDTLS_DEPRECATED +#endif /* !MBEDTLS_DEPRECATED_REMOVED */ + /** + * \brief The SHA-384 or SHA-512 checkup routine. + * + * \return \c 0 on success. + * \return \c 1 on failure. + */ +int mbedtls_sha512_self_test( int verbose ); + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_sha512.h */ diff --git a/common/mbedtls/threading.c b/common/mbedtls/threading.c new file mode 100644 index 000000000..f7997ac95 --- /dev/null +++ b/common/mbedtls/threading.c @@ -0,0 +1,142 @@ +/* + * Threading abstraction layer + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_THREADING_C) + +#include "mbedtls/threading.h" + +#if defined(MBEDTLS_THREADING_PTHREAD) +static void threading_mutex_init_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL ) + return; + + mutex->is_valid = pthread_mutex_init( &mutex->mutex, NULL ) == 0; +} + +static void threading_mutex_free_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || !mutex->is_valid ) + return; + + (void) pthread_mutex_destroy( &mutex->mutex ); + mutex->is_valid = 0; +} + +static int threading_mutex_lock_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || ! mutex->is_valid ) + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_lock( &mutex->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +static int threading_mutex_unlock_pthread( mbedtls_threading_mutex_t *mutex ) +{ + if( mutex == NULL || ! mutex->is_valid ) + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); + + if( pthread_mutex_unlock( &mutex->mutex ) != 0 ) + return( MBEDTLS_ERR_THREADING_MUTEX_ERROR ); + + return( 0 ); +} + +void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_init_pthread; +void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_free_pthread; +int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_lock_pthread; +int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_unlock_pthread; + +/* + * With phtreads we can statically initialize mutexes + */ +#define MUTEX_INIT = { PTHREAD_MUTEX_INITIALIZER, 1 } + +#endif /* MBEDTLS_THREADING_PTHREAD */ + +#if defined(MBEDTLS_THREADING_ALT) +static int threading_mutex_fail( mbedtls_threading_mutex_t *mutex ) +{ + ((void) mutex ); + return( MBEDTLS_ERR_THREADING_BAD_INPUT_DATA ); +} +static void threading_mutex_dummy( mbedtls_threading_mutex_t *mutex ) +{ + ((void) mutex ); + return; +} + +void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; +void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t * ) = threading_mutex_dummy; +int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; +int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t * ) = threading_mutex_fail; + +/* + * Set functions pointers and initialize global mutexes + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ) +{ + mbedtls_mutex_init = mutex_init; + mbedtls_mutex_free = mutex_free; + mbedtls_mutex_lock = mutex_lock; + mbedtls_mutex_unlock = mutex_unlock; + +#if defined(MBEDTLS_FS_IO) + mbedtls_mutex_init( &mbedtls_threading_readdir_mutex ); +#endif +} + +/* + * Free global mutexes + */ +void mbedtls_threading_free_alt( void ) +{ +#if defined(MBEDTLS_FS_IO) + mbedtls_mutex_free( &mbedtls_threading_readdir_mutex ); +#endif +} +#endif /* MBEDTLS_THREADING_ALT */ + +/* + * Define global mutexes + */ +#ifndef MUTEX_INIT +#define MUTEX_INIT +#endif +#if defined(MBEDTLS_FS_IO) +mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex MUTEX_INIT; +#endif + +#endif /* MBEDTLS_THREADING_C */ diff --git a/common/mbedtls/threading.h b/common/mbedtls/threading.h new file mode 100644 index 000000000..bd68d5aa9 --- /dev/null +++ b/common/mbedtls/threading.h @@ -0,0 +1,110 @@ +/** + * \file threading.h + * + * \brief Threading abstraction layer + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_THREADING_H +#define MBEDTLS_THREADING_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#define MBEDTLS_ERR_THREADING_FEATURE_UNAVAILABLE -0x001A /**< The selected feature is not available. */ +#define MBEDTLS_ERR_THREADING_BAD_INPUT_DATA -0x001C /**< Bad input parameters to function. */ +#define MBEDTLS_ERR_THREADING_MUTEX_ERROR -0x001E /**< Locking / unlocking / free failed with error code. */ + +#if defined(MBEDTLS_THREADING_PTHREAD) +#include +typedef struct mbedtls_threading_mutex_t +{ + pthread_mutex_t mutex; + char is_valid; +} mbedtls_threading_mutex_t; +#endif + +#if defined(MBEDTLS_THREADING_ALT) +/* You should define the mbedtls_threading_mutex_t type in your header */ +#include "threading_alt.h" + +/** + * \brief Set your alternate threading implementation function + * pointers and initialize global mutexes. If used, this + * function must be called once in the main thread before any + * other mbed TLS function is called, and + * mbedtls_threading_free_alt() must be called once in the main + * thread after all other mbed TLS functions. + * + * \note mutex_init() and mutex_free() don't return a status code. + * If mutex_init() fails, it should leave its argument (the + * mutex) in a state such that mutex_lock() will fail when + * called with this argument. + * + * \param mutex_init the init function implementation + * \param mutex_free the free function implementation + * \param mutex_lock the lock function implementation + * \param mutex_unlock the unlock function implementation + */ +void mbedtls_threading_set_alt( void (*mutex_init)( mbedtls_threading_mutex_t * ), + void (*mutex_free)( mbedtls_threading_mutex_t * ), + int (*mutex_lock)( mbedtls_threading_mutex_t * ), + int (*mutex_unlock)( mbedtls_threading_mutex_t * ) ); + +/** + * \brief Free global mutexes. + */ +void mbedtls_threading_free_alt( void ); +#endif /* MBEDTLS_THREADING_ALT */ + +#if defined(MBEDTLS_THREADING_C) +/* + * The function pointers for mutex_init, mutex_free, mutex_ and mutex_unlock + * + * All these functions are expected to work or the result will be undefined. + */ +extern void (*mbedtls_mutex_init)( mbedtls_threading_mutex_t *mutex ); +extern void (*mbedtls_mutex_free)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_lock)( mbedtls_threading_mutex_t *mutex ); +extern int (*mbedtls_mutex_unlock)( mbedtls_threading_mutex_t *mutex ); + +/* + * Global mutexes + */ +#if defined(MBEDTLS_FS_IO) +extern mbedtls_threading_mutex_t mbedtls_threading_readdir_mutex; +#endif +#endif /* MBEDTLS_THREADING_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* threading.h */ diff --git a/common/mbedtls/timing.c b/common/mbedtls/timing.c new file mode 100644 index 000000000..fb2519181 --- /dev/null +++ b/common/mbedtls/timing.c @@ -0,0 +1,547 @@ +/* + * Portable interface to the CPU cycle counter + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_SELF_TEST) && defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_printf printf +#endif + +#if defined(MBEDTLS_TIMING_C) + +#include "mbedtls/timing.h" + +#if !defined(MBEDTLS_TIMING_ALT) + +#if !defined(unix) && !defined(__unix__) && !defined(__unix) && \ + !defined(__APPLE__) && !defined(_WIN32) && !defined(__QNXNTO__) && \ + !defined(__HAIKU__) +#error "This module only works on Unix and Windows, see MBEDTLS_TIMING_C in config.h" +#endif + +#ifndef asm +#define asm __asm +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +#include +#include + +struct _hr_time +{ + LARGE_INTEGER start; +}; + +#else + +#include +#include +#include +#include +#include + +struct _hr_time +{ + struct timeval start; +}; + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + ( defined(_MSC_VER) && defined(_M_IX86) ) || defined(__WATCOMC__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tsc; + __asm rdtsc + __asm mov [tsc], eax + return( tsc ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + ( _MSC_VER && _M_IX86 ) || __WATCOMC__ */ + +/* some versions of mingw-64 have 32-bit longs even on x84_64 */ +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__i386__) || ( \ + ( defined(__amd64__) || defined( __x86_64__) ) && __SIZEOF_LONG__ == 4 ) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __i386__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__amd64__) || defined(__x86_64__) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long lo, hi; + asm volatile( "rdtsc" : "=a" (lo), "=d" (hi) ); + return( lo | ( hi << 32 ) ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && ( __amd64__ || __x86_64__ ) */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && ( defined(__powerpc__) || defined(__ppc__) ) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tbl, tbu0, tbu1; + + do + { + asm volatile( "mftbu %0" : "=r" (tbu0) ); + asm volatile( "mftb %0" : "=r" (tbl ) ); + asm volatile( "mftbu %0" : "=r" (tbu1) ); + } + while( tbu0 != tbu1 ); + + return( tbl ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && ( __powerpc__ || __ppc__ ) */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc64__) + +#if defined(__OpenBSD__) +#warning OpenBSD does not allow access to tick register using software version instead +#else +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tick; + asm volatile( "rdpr %%tick, %0;" : "=&r" (tick) ); + return( tick ); +} +#endif /* __OpenBSD__ */ +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __sparc64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__sparc__) && !defined(__sparc64__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long tick; + asm volatile( ".byte 0x83, 0x41, 0x00, 0x00" ); + asm volatile( "mov %%g1, %0" : "=r" (tick) ); + return( tick ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __sparc__ && !__sparc64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__alpha__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long cc; + asm volatile( "rpcc %0" : "=r" (cc) ); + return( cc & 0xFFFFFFFF ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __alpha__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(MBEDTLS_HAVE_ASM) && \ + defined(__GNUC__) && defined(__ia64__) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + unsigned long itc; + asm volatile( "mov %0 = ar.itc" : "=r" (itc) ); + return( itc ); +} +#endif /* !HAVE_HARDCLOCK && MBEDTLS_HAVE_ASM && + __GNUC__ && __ia64__ */ + +#if !defined(HAVE_HARDCLOCK) && defined(_MSC_VER) && \ + !defined(EFIX64) && !defined(EFI32) + +#define HAVE_HARDCLOCK + +unsigned long mbedtls_timing_hardclock( void ) +{ + LARGE_INTEGER offset; + + QueryPerformanceCounter( &offset ); + + return( (unsigned long)( offset.QuadPart ) ); +} +#endif /* !HAVE_HARDCLOCK && _MSC_VER && !EFIX64 && !EFI32 */ + +#if !defined(HAVE_HARDCLOCK) + +#define HAVE_HARDCLOCK + +static int hardclock_init = 0; +static struct timeval tv_init; + +unsigned long mbedtls_timing_hardclock( void ) +{ + struct timeval tv_cur; + + if( hardclock_init == 0 ) + { +#ifdef __MINGW32__ + mingw_gettimeofday( &tv_init, NULL ); +#else + gettimeofday( &tv_init, NULL ); +#endif + hardclock_init = 1; + } + +#ifdef __MINGW32__ + mingw_gettimeofday( &tv_cur, NULL ); +#else + gettimeofday( &tv_cur, NULL ); +#endif + return( ( tv_cur.tv_sec - tv_init.tv_sec ) * 1000000 + + ( tv_cur.tv_usec - tv_init.tv_usec ) ); +} +#endif /* !HAVE_HARDCLOCK */ + +volatile int mbedtls_timing_alarmed = 0; + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + struct _hr_time *t = (struct _hr_time *) val; + + if( reset ) + { + QueryPerformanceCounter( &t->start ); + return( 0 ); + } + else + { + unsigned long delta; + LARGE_INTEGER now, hfreq; + QueryPerformanceCounter( &now ); + QueryPerformanceFrequency( &hfreq ); + delta = (unsigned long)( ( now.QuadPart - t->start.QuadPart ) * 1000ul + / hfreq.QuadPart ); + return( delta ); + } +} + +/* It's OK to use a global because alarm() is supposed to be global anyway */ +static DWORD alarmMs; + +static DWORD WINAPI TimerProc( LPVOID TimerContext ) +{ + ((void) TimerContext); + Sleep( alarmMs ); + mbedtls_timing_alarmed = 1; + return( TRUE ); +} + +void mbedtls_set_alarm( int seconds ) +{ + DWORD ThreadId; + + if( seconds == 0 ) + { + /* No need to create a thread for this simple case. + * Also, this shorcut is more reliable at least on MinGW32 */ + mbedtls_timing_alarmed = 1; + return; + } + + mbedtls_timing_alarmed = 0; + alarmMs = seconds * 1000; + CloseHandle( CreateThread( NULL, 0, TimerProc, NULL, 0, &ThreadId ) ); +} + +#else /* _WIN32 && !EFIX64 && !EFI32 */ + +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ) +{ + struct _hr_time *t = (struct _hr_time *) val; + + if( reset ) + { + gettimeofday( &t->start, NULL ); + return( 0 ); + } + else + { + unsigned long delta; + struct timeval now; + gettimeofday( &now, NULL ); + delta = ( now.tv_sec - t->start.tv_sec ) * 1000ul + + ( now.tv_usec - t->start.tv_usec ) / 1000; + return( delta ); + } +} + +static void sighandler( int signum ) +{ + mbedtls_timing_alarmed = 1; + signal( signum, sighandler ); +} + +void mbedtls_set_alarm( int seconds ) +{ + mbedtls_timing_alarmed = 0; + signal( SIGALRM, sighandler ); + alarm( seconds ); + if( seconds == 0 ) + { + /* alarm(0) cancelled any previous pending alarm, but the + handler won't fire, so raise the flag straight away. */ + mbedtls_timing_alarmed = 1; + } +} + +#endif /* _WIN32 && !EFIX64 && !EFI32 */ + +/* + * Set delays to watch + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + + ctx->int_ms = int_ms; + ctx->fin_ms = fin_ms; + + if( fin_ms != 0 ) + (void) mbedtls_timing_get_timer( &ctx->timer, 1 ); +} + +/* + * Get number of delays expired + */ +int mbedtls_timing_get_delay( void *data ) +{ + mbedtls_timing_delay_context *ctx = (mbedtls_timing_delay_context *) data; + unsigned long elapsed_ms; + + if( ctx->fin_ms == 0 ) + return( -1 ); + + elapsed_ms = mbedtls_timing_get_timer( &ctx->timer, 0 ); + + if( elapsed_ms >= ctx->fin_ms ) + return( 2 ); + + if( elapsed_ms >= ctx->int_ms ) + return( 1 ); + + return( 0 ); +} + +#endif /* !MBEDTLS_TIMING_ALT */ + +#if defined(MBEDTLS_SELF_TEST) + +/* + * Busy-waits for the given number of milliseconds. + * Used for testing mbedtls_timing_hardclock. + */ +static void busy_msleep( unsigned long msec ) +{ + struct mbedtls_timing_hr_time hires; + unsigned long i = 0; /* for busy-waiting */ + volatile unsigned long j; /* to prevent optimisation */ + + (void) mbedtls_timing_get_timer( &hires, 1 ); + + while( mbedtls_timing_get_timer( &hires, 0 ) < msec ) + i++; + + j = i; + (void) j; +} + +#define FAIL do \ + { \ + if( verbose != 0 ) \ + { \ + mbedtls_printf( "failed at line %d\n", __LINE__ ); \ + mbedtls_printf( " cycles=%lu ratio=%lu millisecs=%lu secs=%lu hardfail=%d a=%lu b=%lu\n", \ + cycles, ratio, millisecs, secs, hardfail, \ + (unsigned long) a, (unsigned long) b ); \ + mbedtls_printf( " elapsed(hires)=%lu elapsed(ctx)=%lu status(ctx)=%d\n", \ + mbedtls_timing_get_timer( &hires, 0 ), \ + mbedtls_timing_get_timer( &ctx.timer, 0 ), \ + mbedtls_timing_get_delay( &ctx ) ); \ + } \ + return( 1 ); \ + } while( 0 ) + +/* + * Checkup routine + * + * Warning: this is work in progress, some tests may not be reliable enough + * yet! False positives may happen. + */ +int mbedtls_timing_self_test( int verbose ) +{ + unsigned long cycles = 0, ratio = 0; + unsigned long millisecs = 0, secs = 0; + int hardfail = 0; + struct mbedtls_timing_hr_time hires; + uint32_t a = 0, b = 0; + mbedtls_timing_delay_context ctx; + + if( verbose != 0 ) + mbedtls_printf( " TIMING tests note: will take some time!\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #1 (set_alarm / get_timer): " ); + + { + secs = 1; + + (void) mbedtls_timing_get_timer( &hires, 1 ); + + mbedtls_set_alarm( (int) secs ); + while( !mbedtls_timing_alarmed ) + ; + + millisecs = mbedtls_timing_get_timer( &hires, 0 ); + + /* For some reason on Windows it looks like alarm has an extra delay + * (maybe related to creating a new thread). Allow some room here. */ + if( millisecs < 800 * secs || millisecs > 1200 * secs + 300 ) + FAIL; + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #2 (set/get_delay ): " ); + + { + a = 800; + b = 400; + mbedtls_timing_set_delay( &ctx, a, a + b ); /* T = 0 */ + + busy_msleep( a - a / 4 ); /* T = a - a/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 0 ) + FAIL; + + busy_msleep( a / 4 + b / 4 ); /* T = a + b/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 1 ) + FAIL; + + busy_msleep( b ); /* T = a + b + b/4 */ + if( mbedtls_timing_get_delay( &ctx ) != 2 ) + FAIL; + } + + mbedtls_timing_set_delay( &ctx, 0, 0 ); + busy_msleep( 200 ); + if( mbedtls_timing_get_delay( &ctx ) != -1 ) + FAIL; + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + + if( verbose != 0 ) + mbedtls_printf( " TIMING test #3 (hardclock / get_timer): " ); + + /* + * Allow one failure for possible counter wrapping. + * On a 4Ghz 32-bit machine the cycle counter wraps about once per second; + * since the whole test is about 10ms, it shouldn't happen twice in a row. + */ + +hard_test: + if( hardfail > 1 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed (ignored)\n" ); + + goto hard_test_done; + } + + /* Get a reference ratio cycles/ms */ + millisecs = 1; + cycles = mbedtls_timing_hardclock(); + busy_msleep( millisecs ); + cycles = mbedtls_timing_hardclock() - cycles; + ratio = cycles / millisecs; + + /* Check that the ratio is mostly constant */ + for( millisecs = 2; millisecs <= 4; millisecs++ ) + { + cycles = mbedtls_timing_hardclock(); + busy_msleep( millisecs ); + cycles = mbedtls_timing_hardclock() - cycles; + + /* Allow variation up to 20% */ + if( cycles / millisecs < ratio - ratio / 5 || + cycles / millisecs > ratio + ratio / 5 ) + { + hardfail++; + goto hard_test; + } + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n" ); + +hard_test_done: + + if( verbose != 0 ) + mbedtls_printf( "\n" ); + + return( 0 ); +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_TIMING_C */ diff --git a/common/mbedtls/timing.h b/common/mbedtls/timing.h new file mode 100644 index 000000000..74b5f7108 --- /dev/null +++ b/common/mbedtls/timing.h @@ -0,0 +1,155 @@ +/** + * \file timing.h + * + * \brief Portable interface to timeouts and to the CPU cycle counter + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_TIMING_H +#define MBEDTLS_TIMING_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +#if !defined(MBEDTLS_TIMING_ALT) +// Regular implementation +// + +/** + * \brief timer structure + */ +struct mbedtls_timing_hr_time +{ + unsigned char opaque[32]; +}; + +/** + * \brief Context for mbedtls_timing_set/get_delay() + */ +typedef struct mbedtls_timing_delay_context +{ + struct mbedtls_timing_hr_time timer; + uint32_t int_ms; + uint32_t fin_ms; +} mbedtls_timing_delay_context; + +#else /* MBEDTLS_TIMING_ALT */ +#include "timing_alt.h" +#endif /* MBEDTLS_TIMING_ALT */ + +extern volatile int mbedtls_timing_alarmed; + +/** + * \brief Return the CPU cycle counter value + * + * \warning This is only a best effort! Do not rely on this! + * In particular, it is known to be unreliable on virtual + * machines. + * + * \note This value starts at an unspecified origin and + * may wrap around. + */ +unsigned long mbedtls_timing_hardclock( void ); + +/** + * \brief Return the elapsed time in milliseconds + * + * \param val points to a timer structure + * \param reset If 0, query the elapsed time. Otherwise (re)start the timer. + * + * \return Elapsed time since the previous reset in ms. When + * restarting, this is always 0. + * + * \note To initialize a timer, call this function with reset=1. + * + * Determining the elapsed time and resetting the timer is not + * atomic on all platforms, so after the sequence + * `{ get_timer(1); ...; time1 = get_timer(1); ...; time2 = + * get_timer(0) }` the value time1+time2 is only approximately + * the delay since the first reset. + */ +unsigned long mbedtls_timing_get_timer( struct mbedtls_timing_hr_time *val, int reset ); + +/** + * \brief Setup an alarm clock + * + * \param seconds delay before the "mbedtls_timing_alarmed" flag is set + * (must be >=0) + * + * \warning Only one alarm at a time is supported. In a threaded + * context, this means one for the whole process, not one per + * thread. + */ +void mbedtls_set_alarm( int seconds ); + +/** + * \brief Set a pair of delays to watch + * (See \c mbedtls_timing_get_delay().) + * + * \param data Pointer to timing data. + * Must point to a valid \c mbedtls_timing_delay_context struct. + * \param int_ms First (intermediate) delay in milliseconds. + * The effect if int_ms > fin_ms is unspecified. + * \param fin_ms Second (final) delay in milliseconds. + * Pass 0 to cancel the current delay. + * + * \note To set a single delay, either use \c mbedtls_timing_set_timer + * directly or use this function with int_ms == fin_ms. + */ +void mbedtls_timing_set_delay( void *data, uint32_t int_ms, uint32_t fin_ms ); + +/** + * \brief Get the status of delays + * (Memory helper: number of delays passed.) + * + * \param data Pointer to timing data + * Must point to a valid \c mbedtls_timing_delay_context struct. + * + * \return -1 if cancelled (fin_ms = 0), + * 0 if none of the delays are passed, + * 1 if only the intermediate delay is passed, + * 2 if the final delay is passed. + */ +int mbedtls_timing_get_delay( void *data ); + +#if defined(MBEDTLS_SELF_TEST) +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if a test failed + */ +int mbedtls_timing_self_test( int verbose ); +#endif + +#ifdef __cplusplus +} +#endif + +#endif /* timing.h */ diff --git a/common/mbedtls/x509.c b/common/mbedtls/x509.c new file mode 100644 index 000000000..c2f72a52b --- /dev/null +++ b/common/mbedtls/x509.c @@ -0,0 +1,1073 @@ +/* + * X.509 common functions for parsing and verification + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +/* Ensure gmtime_r is available even with -std=c99; must be included before + * config.h, which pulls in glibc's features.h. Harmless on other platforms. */ +#define _POSIX_C_SOURCE 200112L + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_USE_C) + +#include "mbedtls/x509.h" +#include "mbedtls/asn1.h" +#include "mbedtls/oid.h" + +#include +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_printf printf +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_HAVE_TIME) +#include "mbedtls/platform_time.h" +#endif +#if defined(MBEDTLS_HAVE_TIME_DATE) +#include +#endif + +#define CHECK(code) if( ( ret = code ) != 0 ){ return( ret ); } +#define CHECK_RANGE(min, max, val) if( val < min || val > max ){ return( ret ); } + +/* + * CertificateSerialNumber ::= INTEGER + */ +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ) +{ + int ret; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_PRIMITIVE | 2 ) && + **p != MBEDTLS_ASN1_INTEGER ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + serial->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &serial->len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_SERIAL + ret ); + + serial->p = *p; + *p += serial->len; + + return( 0 ); +} + +/* Get an algorithm identifier without parameters (eg for signatures) + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + */ +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_alg_null( p, end, alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +/* + * Parse an algorithm identifier with (optional) paramaters + */ +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_alg( p, end, alg, params ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + return( 0 ); +} + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +/* + * HashAlgorithm ::= AlgorithmIdentifier + * + * AlgorithmIdentifier ::= SEQUENCE { + * algorithm OBJECT IDENTIFIER, + * parameters ANY DEFINED BY algorithm OPTIONAL } + * + * For HashAlgorithm, parameters MUST be NULL or absent. + */ +static int x509_get_hash_alg( const mbedtls_x509_buf *alg, mbedtls_md_type_t *md_alg ) +{ + int ret; + unsigned char *p; + const unsigned char *end; + mbedtls_x509_buf md_oid; + size_t len; + + /* Make sure we got a SEQUENCE and setup bounds */ + if( alg->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) alg->p; + end = p + alg->len; + + if( p >= end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + /* Parse md_oid */ + md_oid.tag = *p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &md_oid.len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + md_oid.p = p; + p += md_oid.len; + + /* Get md_alg from md_oid */ + if( ( ret = mbedtls_oid_get_md_alg( &md_oid, md_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + /* Make sure params is absent of NULL */ + if( p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, MBEDTLS_ASN1_NULL ) ) != 0 || len != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * RSASSA-PSS-params ::= SEQUENCE { + * hashAlgorithm [0] HashAlgorithm DEFAULT sha1Identifier, + * maskGenAlgorithm [1] MaskGenAlgorithm DEFAULT mgf1SHA1Identifier, + * saltLength [2] INTEGER DEFAULT 20, + * trailerField [3] INTEGER DEFAULT 1 } + * -- Note that the tags in this Sequence are explicit. + * + * RFC 4055 (which defines use of RSASSA-PSS in PKIX) states that the value + * of trailerField MUST be 1, and PKCS#1 v2.2 doesn't even define any other + * option. Enfore this at parsing time. + */ +int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len ) +{ + int ret; + unsigned char *p; + const unsigned char *end, *end2; + size_t len; + mbedtls_x509_buf alg_id, alg_params; + + /* First set everything to defaults */ + *md_alg = MBEDTLS_MD_SHA1; + *mgf_md = MBEDTLS_MD_SHA1; + *salt_len = 20; + + /* Make sure params is a SEQUENCE and setup bounds */ + if( params->tag != ( MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + p = (unsigned char *) params->p; + end = p + params->len; + + if( p == end ) + return( 0 ); + + /* + * HashAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) == 0 ) + { + end2 = p + len; + + /* HashAlgorithm ::= AlgorithmIdentifier (without parameters) */ + if( ( ret = mbedtls_x509_get_alg_null( &p, end2, &alg_id ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_oid_get_md_alg( &alg_id, md_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * MaskGenAlgorithm + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ) == 0 ) + { + end2 = p + len; + + /* MaskGenAlgorithm ::= AlgorithmIdentifier (params = HashAlgorithm) */ + if( ( ret = mbedtls_x509_get_alg( &p, end2, &alg_id, &alg_params ) ) != 0 ) + return( ret ); + + /* Only MFG1 is recognised for now */ + if( MBEDTLS_OID_CMP( MBEDTLS_OID_MGF1, &alg_id ) != 0 ) + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE + + MBEDTLS_ERR_OID_NOT_FOUND ); + + /* Parse HashAlgorithm */ + if( ( ret = x509_get_hash_alg( &alg_params, mgf_md ) ) != 0 ) + return( ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * salt_len + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 2 ) ) == 0 ) + { + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, salt_len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p == end ) + return( 0 ); + + /* + * trailer_field (if present, must be 1) + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 3 ) ) == 0 ) + { + int trailer_field; + + end2 = p + len; + + if( ( ret = mbedtls_asn1_get_int( &p, end2, &trailer_field ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end2 ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + if( trailer_field != 1 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + else if( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( MBEDTLS_ERR_X509_INVALID_ALG + ret ); + + if( p != end ) + return( MBEDTLS_ERR_X509_INVALID_ALG + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + +/* + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + */ +static int x509_get_attr_type_value( unsigned char **p, + const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret; + size_t len; + mbedtls_x509_buf *oid; + mbedtls_x509_buf *val; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + oid = &cur->oid; + oid->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &oid->len, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + oid->p = *p; + *p += oid->len; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + if( **p != MBEDTLS_ASN1_BMP_STRING && **p != MBEDTLS_ASN1_UTF8_STRING && + **p != MBEDTLS_ASN1_T61_STRING && **p != MBEDTLS_ASN1_PRINTABLE_STRING && + **p != MBEDTLS_ASN1_IA5_STRING && **p != MBEDTLS_ASN1_UNIVERSAL_STRING && + **p != MBEDTLS_ASN1_BIT_STRING ) + return( MBEDTLS_ERR_X509_INVALID_NAME + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + val = &cur->val; + val->tag = *(*p)++; + + if( ( ret = mbedtls_asn1_get_len( p, end, &val->len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + val->p = *p; + *p += val->len; + + cur->next = NULL; + + return( 0 ); +} + +/* + * Name ::= CHOICE { -- only one possibility for now -- + * rdnSequence RDNSequence } + * + * RDNSequence ::= SEQUENCE OF RelativeDistinguishedName + * + * RelativeDistinguishedName ::= + * SET OF AttributeTypeAndValue + * + * AttributeTypeAndValue ::= SEQUENCE { + * type AttributeType, + * value AttributeValue } + * + * AttributeType ::= OBJECT IDENTIFIER + * + * AttributeValue ::= ANY DEFINED BY AttributeType + * + * The data structure is optimized for the common case where each RDN has only + * one element, which is represented as a list of AttributeTypeAndValue. + * For the general case we still use a flat list, but we mark elements of the + * same set so that they are "merged" together in the functions that consume + * this list, eg mbedtls_x509_dn_gets(). + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ) +{ + int ret; + size_t set_len; + const unsigned char *end_set; + + /* don't use recursion, we'd risk stack overflow if not optimized */ + while( 1 ) + { + /* + * parse SET + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &set_len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SET ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_NAME + ret ); + + end_set = *p + set_len; + + while( 1 ) + { + if( ( ret = x509_get_attr_type_value( p, end_set, cur ) ) != 0 ) + return( ret ); + + if( *p == end_set ) + break; + + /* Mark this item as being no the only one in a set */ + cur->next_merged = 1; + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } + + /* + * continue until end of SEQUENCE is reached + */ + if( *p == end ) + return( 0 ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_name ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur = cur->next; + } +} + +static int x509_parse_int( unsigned char **p, size_t n, int *res ) +{ + *res = 0; + + for( ; n > 0; --n ) + { + if( ( **p < '0') || ( **p > '9' ) ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + *res *= 10; + *res += ( *(*p)++ - '0' ); + } + + return( 0 ); +} + +static int x509_date_is_valid(const mbedtls_x509_time *t ) +{ + int ret = MBEDTLS_ERR_X509_INVALID_DATE; + int month_len; + + CHECK_RANGE( 0, 9999, t->year ); + CHECK_RANGE( 0, 23, t->hour ); + CHECK_RANGE( 0, 59, t->min ); + CHECK_RANGE( 0, 59, t->sec ); + + switch( t->mon ) + { + case 1: case 3: case 5: case 7: case 8: case 10: case 12: + month_len = 31; + break; + case 4: case 6: case 9: case 11: + month_len = 30; + break; + case 2: + if( ( !( t->year % 4 ) && t->year % 100 ) || + !( t->year % 400 ) ) + month_len = 29; + else + month_len = 28; + break; + default: + return( ret ); + } + CHECK_RANGE( 1, month_len, t->day ); + + return( 0 ); +} + +/* + * Parse an ASN1_UTC_TIME (yearlen=2) or ASN1_GENERALIZED_TIME (yearlen=4) + * field. + */ +static int x509_parse_time( unsigned char **p, size_t len, size_t yearlen, + mbedtls_x509_time *tm ) +{ + int ret; + + /* + * Minimum length is 10 or 12 depending on yearlen + */ + if ( len < yearlen + 8 ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + len -= yearlen + 8; + + /* + * Parse year, month, day, hour, minute + */ + CHECK( x509_parse_int( p, yearlen, &tm->year ) ); + if ( 2 == yearlen ) + { + if ( tm->year < 50 ) + tm->year += 100; + + tm->year += 1900; + } + + CHECK( x509_parse_int( p, 2, &tm->mon ) ); + CHECK( x509_parse_int( p, 2, &tm->day ) ); + CHECK( x509_parse_int( p, 2, &tm->hour ) ); + CHECK( x509_parse_int( p, 2, &tm->min ) ); + + /* + * Parse seconds if present + */ + if ( len >= 2 ) + { + CHECK( x509_parse_int( p, 2, &tm->sec ) ); + len -= 2; + } + else + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + /* + * Parse trailing 'Z' if present + */ + if ( 1 == len && 'Z' == **p ) + { + (*p)++; + len--; + } + + /* + * We should have parsed all characters at this point + */ + if ( 0 != len ) + return ( MBEDTLS_ERR_X509_INVALID_DATE ); + + CHECK( x509_date_is_valid( tm ) ); + + return ( 0 ); +} + +/* + * Time ::= CHOICE { + * utcTime UTCTime, + * generalTime GeneralizedTime } + */ +int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, + mbedtls_x509_time *tm ) +{ + int ret; + size_t len, year_len; + unsigned char tag; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag = **p; + + if( tag == MBEDTLS_ASN1_UTC_TIME ) + year_len = 2; + else if( tag == MBEDTLS_ASN1_GENERALIZED_TIME ) + year_len = 4; + else + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + + (*p)++; + ret = mbedtls_asn1_get_len( p, end, &len ); + + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); + + return x509_parse_time( p, len, year_len, tm ); +} + +int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ) +{ + int ret; + size_t len; + int tag_type; + + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag_type = **p; + + if( ( ret = mbedtls_asn1_get_bitstring_null( p, end, &len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_SIGNATURE + ret ); + + sig->tag = tag_type; + sig->len = len; + sig->p = *p; + + *p += len; + + return( 0 ); +} + +/* + * Get signature algorithm from alg OID and optional parameters + */ +int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts ) +{ + int ret; + + if( *sig_opts != NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + if( ( ret = mbedtls_oid_get_sig_alg( sig_oid, md_alg, pk_alg ) ) != 0 ) + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG + ret ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( *pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + mbedtls_pk_rsassa_pss_options *pss_opts; + + pss_opts = mbedtls_calloc( 1, sizeof( mbedtls_pk_rsassa_pss_options ) ); + if( pss_opts == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + ret = mbedtls_x509_get_rsassa_pss_params( sig_params, + md_alg, + &pss_opts->mgf1_hash_id, + &pss_opts->expected_salt_len ); + if( ret != 0 ) + { + mbedtls_free( pss_opts ); + return( ret ); + } + + *sig_opts = (void *) pss_opts; + } + else +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + { + /* Make sure parameters are absent or NULL */ + if( ( sig_params->tag != MBEDTLS_ASN1_NULL && sig_params->tag != 0 ) || + sig_params->len != 0 ) + return( MBEDTLS_ERR_X509_INVALID_ALG ); + } + + return( 0 ); +} + +/* + * X.509 Extensions (No parsing of extensions, pointer should + * be either manually updated or extensions should be parsed!) + */ +int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag ) +{ + int ret; + size_t len; + + if( *p == end ) + return( 0 ); + + ext->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | tag ) ) != 0 ) + return( ret ); + + ext->p = *p; + end = *p + ext->len; + + /* + * Extensions ::= SEQUENCE SIZE (1..MAX) OF Extension + * + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( end != *p + len ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Store the name in printable form into buf; no more + * than size characters will be written + */ +int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ) +{ + int ret; + size_t i, n; + unsigned char c, merge = 0; + const mbedtls_x509_name *name; + const char *short_name = NULL; + char s[MBEDTLS_X509_MAX_DN_NAME_SIZE], *p; + + memset( s, 0, sizeof( s ) ); + + name = dn; + p = buf; + n = size; + + while( name != NULL ) + { + if( !name->oid.p ) + { + name = name->next; + continue; + } + + if( name != dn ) + { + ret = mbedtls_snprintf( p, n, merge ? " + " : ", " ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + ret = mbedtls_oid_get_attr_short_name( &name->oid, &short_name ); + + if( ret == 0 ) + ret = mbedtls_snprintf( p, n, "%s=", short_name ); + else + ret = mbedtls_snprintf( p, n, "\?\?=" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + for( i = 0; i < name->val.len; i++ ) + { + if( i >= sizeof( s ) - 1 ) + break; + + c = name->val.p[i]; + if( c < 32 || c == 127 || ( c > 128 && c < 160 ) ) + s[i] = '?'; + else s[i] = c; + } + s[i] = '\0'; + ret = mbedtls_snprintf( p, n, "%s", s ); + MBEDTLS_X509_SAFE_SNPRINTF; + + merge = name->next_merged; + name = name->next; + } + + return( (int) ( size - n ) ); +} + +/* + * Store the serial in printable form into buf; no more + * than size characters will be written + */ +int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ) +{ + int ret; + size_t i, n, nr; + char *p; + + p = buf; + n = size; + + nr = ( serial->len <= 32 ) + ? serial->len : 28; + + for( i = 0; i < nr; i++ ) + { + if( i == 0 && nr > 1 && serial->p[i] == 0x0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%02X%s", + serial->p[i], ( i < nr - 1 ) ? ":" : "" ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + if( nr != serial->len ) + { + ret = mbedtls_snprintf( p, n, "...." ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return( (int) ( size - n ) ); +} + +/* + * Helper for writing signature algorithms + */ +int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts ) +{ + int ret; + char *p = buf; + size_t n = size; + const char *desc = NULL; + + ret = mbedtls_oid_get_sig_alg_desc( sig_oid, &desc ); + if( ret != 0 ) + ret = mbedtls_snprintf( p, n, "???" ); + else + ret = mbedtls_snprintf( p, n, "%s", desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + if( pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + const mbedtls_pk_rsassa_pss_options *pss_opts; + const mbedtls_md_info_t *md_info, *mgf_md_info; + + pss_opts = (const mbedtls_pk_rsassa_pss_options *) sig_opts; + + md_info = mbedtls_md_info_from_type( md_alg ); + mgf_md_info = mbedtls_md_info_from_type( pss_opts->mgf1_hash_id ); + + ret = mbedtls_snprintf( p, n, " (%s, MGF1-%s, 0x%02X)", + md_info ? mbedtls_md_get_name( md_info ) : "???", + mgf_md_info ? mbedtls_md_get_name( mgf_md_info ) : "???", + pss_opts->expected_salt_len ); + MBEDTLS_X509_SAFE_SNPRINTF; + } +#else + ((void) pk_alg); + ((void) md_alg); + ((void) sig_opts); +#endif /* MBEDTLS_X509_RSASSA_PSS_SUPPORT */ + + return( (int)( size - n ) ); +} + +/* + * Helper for writing "RSA key size", "EC key size", etc + */ +int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ) +{ + char *p = buf; + size_t n = buf_size; + int ret; + + ret = mbedtls_snprintf( p, n, "%s key size", name ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( 0 ); +} + +#if defined(MBEDTLS_HAVE_TIME_DATE) +/* + * Set the time structure to the current time. + * Return 0 on success, non-zero on failure. + */ +static int x509_get_current_time( mbedtls_x509_time *now ) +{ + struct tm *lt, tm_buf; + mbedtls_time_t tt; + int ret = 0; + + tt = mbedtls_time( NULL ); +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + lt = gmtime_s( &tm_buf, &tt ) == 0 ? &tm_buf : NULL; +#else + lt = gmtime_r( &tt, &tm_buf ); +#endif + + if( lt == NULL ) + ret = -1; + else + { + now->year = lt->tm_year + 1900; + now->mon = lt->tm_mon + 1; + now->day = lt->tm_mday; + now->hour = lt->tm_hour; + now->min = lt->tm_min; + now->sec = lt->tm_sec; + } + + return( ret ); +} + +/* + * Return 0 if before <= after, 1 otherwise + */ +static int x509_check_time( const mbedtls_x509_time *before, const mbedtls_x509_time *after ) +{ + if( before->year > after->year ) + return( 1 ); + + if( before->year == after->year && + before->mon > after->mon ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day > after->day ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour > after->hour ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min > after->min ) + return( 1 ); + + if( before->year == after->year && + before->mon == after->mon && + before->day == after->day && + before->hour == after->hour && + before->min == after->min && + before->sec > after->sec ) + return( 1 ); + + return( 0 ); +} + +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) +{ + mbedtls_x509_time now; + + if( x509_get_current_time( &now ) != 0 ) + return( 1 ); + + return( x509_check_time( &now, to ) ); +} + +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) +{ + mbedtls_x509_time now; + + if( x509_get_current_time( &now ) != 0 ) + return( 1 ); + + return( x509_check_time( from, &now ) ); +} + +#else /* MBEDTLS_HAVE_TIME_DATE */ + +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ) +{ + ((void) to); + return( 0 ); +} + +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ) +{ + ((void) from); + return( 0 ); +} +#endif /* MBEDTLS_HAVE_TIME_DATE */ + +#if defined(MBEDTLS_SELF_TEST) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/certs.h" + +/* + * Checkup routine + */ +int mbedtls_x509_self_test( int verbose ) +{ +#if defined(MBEDTLS_CERTS_C) && defined(MBEDTLS_SHA256_C) + int ret; + uint32_t flags; + mbedtls_x509_crt cacert; + mbedtls_x509_crt clicert; + + if( verbose != 0 ) + mbedtls_printf( " X.509 certificate load: " ); + + mbedtls_x509_crt_init( &clicert ); + + ret = mbedtls_x509_crt_parse( &clicert, (const unsigned char *) mbedtls_test_cli_crt, + mbedtls_test_cli_crt_len ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + + mbedtls_x509_crt_init( &cacert ); + + ret = mbedtls_x509_crt_parse( &cacert, (const unsigned char *) mbedtls_test_ca_crt, + mbedtls_test_ca_crt_len ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n X.509 signature verify: "); + + ret = mbedtls_x509_crt_verify( &clicert, &cacert, NULL, NULL, &flags, NULL, NULL ); + if( ret != 0 ) + { + if( verbose != 0 ) + mbedtls_printf( "failed\n" ); + + return( ret ); + } + + if( verbose != 0 ) + mbedtls_printf( "passed\n\n"); + + mbedtls_x509_crt_free( &cacert ); + mbedtls_x509_crt_free( &clicert ); + + return( 0 ); +#else + ((void) verbose); + return( 0 ); +#endif /* MBEDTLS_CERTS_C && MBEDTLS_SHA1_C */ +} + +#endif /* MBEDTLS_SELF_TEST */ + +#endif /* MBEDTLS_X509_USE_C */ diff --git a/common/mbedtls/x509.h b/common/mbedtls/x509.h new file mode 100644 index 000000000..0f0ef2eed --- /dev/null +++ b/common/mbedtls/x509.h @@ -0,0 +1,335 @@ +/** + * \file x509.h + * + * \brief X.509 generic defines and structures + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_X509_H +#define MBEDTLS_X509_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "asn1.h" +#include "pk.h" + +#if defined(MBEDTLS_RSA_C) +#include "rsa.h" +#endif + +/** + * \addtogroup x509_module + * \{ + */ + +#if !defined(MBEDTLS_X509_MAX_INTERMEDIATE_CA) +/** + * Maximum number of intermediate CAs in a verification chain. + * That is, maximum length of the chain, excluding the end-entity certificate + * and the trusted root certificate. + * + * Set this to a low value to prevent an adversary from making you waste + * resources verifying an overlong certificate chain. + */ +#define MBEDTLS_X509_MAX_INTERMEDIATE_CA 8 +#endif + +/** + * \name X509 Error codes + * \{ + */ +#define MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE -0x2080 /**< Unavailable feature, e.g. RSA hashing/encryption combination. */ +#define MBEDTLS_ERR_X509_UNKNOWN_OID -0x2100 /**< Requested OID is unknown. */ +#define MBEDTLS_ERR_X509_INVALID_FORMAT -0x2180 /**< The CRT/CRL/CSR format is invalid, e.g. different type expected. */ +#define MBEDTLS_ERR_X509_INVALID_VERSION -0x2200 /**< The CRT/CRL/CSR version element is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SERIAL -0x2280 /**< The serial tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_ALG -0x2300 /**< The algorithm tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_NAME -0x2380 /**< The name tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_DATE -0x2400 /**< The date tag or value is invalid. */ +#define MBEDTLS_ERR_X509_INVALID_SIGNATURE -0x2480 /**< The signature tag or value invalid. */ +#define MBEDTLS_ERR_X509_INVALID_EXTENSIONS -0x2500 /**< The extension tag or value is invalid. */ +#define MBEDTLS_ERR_X509_UNKNOWN_VERSION -0x2580 /**< CRT/CRL/CSR has an unsupported version number. */ +#define MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG -0x2600 /**< Signature algorithm (oid) is unsupported. */ +#define MBEDTLS_ERR_X509_SIG_MISMATCH -0x2680 /**< Signature algorithms do not match. (see \c ::mbedtls_x509_crt sig_oid) */ +#define MBEDTLS_ERR_X509_CERT_VERIFY_FAILED -0x2700 /**< Certificate verification failed, e.g. CRL, CA or signature check failed. */ +#define MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT -0x2780 /**< Format not recognized as DER or PEM. */ +#define MBEDTLS_ERR_X509_BAD_INPUT_DATA -0x2800 /**< Input invalid. */ +#define MBEDTLS_ERR_X509_ALLOC_FAILED -0x2880 /**< Allocation of memory failed. */ +#define MBEDTLS_ERR_X509_FILE_IO_ERROR -0x2900 /**< Read/write of file failed. */ +#define MBEDTLS_ERR_X509_BUFFER_TOO_SMALL -0x2980 /**< Destination buffer is too small. */ +#define MBEDTLS_ERR_X509_FATAL_ERROR -0x3000 /**< A fatal error occured, eg the chain is too long or the vrfy callback failed. */ +/* \} name */ + +/** + * \name X509 Verify codes + * \{ + */ +/* Reminder: update x509_crt_verify_strings[] in library/x509_crt.c */ +#define MBEDTLS_X509_BADCERT_EXPIRED 0x01 /**< The certificate validity has expired. */ +#define MBEDTLS_X509_BADCERT_REVOKED 0x02 /**< The certificate has been revoked (is on a CRL). */ +#define MBEDTLS_X509_BADCERT_CN_MISMATCH 0x04 /**< The certificate Common Name (CN) does not match with the expected CN. */ +#define MBEDTLS_X509_BADCERT_NOT_TRUSTED 0x08 /**< The certificate is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_NOT_TRUSTED 0x10 /**< The CRL is not correctly signed by the trusted CA. */ +#define MBEDTLS_X509_BADCRL_EXPIRED 0x20 /**< The CRL is expired. */ +#define MBEDTLS_X509_BADCERT_MISSING 0x40 /**< Certificate was missing. */ +#define MBEDTLS_X509_BADCERT_SKIP_VERIFY 0x80 /**< Certificate verification was skipped. */ +#define MBEDTLS_X509_BADCERT_OTHER 0x0100 /**< Other reason (can be used by verify callback) */ +#define MBEDTLS_X509_BADCERT_FUTURE 0x0200 /**< The certificate validity starts in the future. */ +#define MBEDTLS_X509_BADCRL_FUTURE 0x0400 /**< The CRL is from the future */ +#define MBEDTLS_X509_BADCERT_KEY_USAGE 0x0800 /**< Usage does not match the keyUsage extension. */ +#define MBEDTLS_X509_BADCERT_EXT_KEY_USAGE 0x1000 /**< Usage does not match the extendedKeyUsage extension. */ +#define MBEDTLS_X509_BADCERT_NS_CERT_TYPE 0x2000 /**< Usage does not match the nsCertType extension. */ +#define MBEDTLS_X509_BADCERT_BAD_MD 0x4000 /**< The certificate is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCERT_BAD_PK 0x8000 /**< The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCERT_BAD_KEY 0x010000 /**< The certificate is signed with an unacceptable key (eg bad curve, RSA too short). */ +#define MBEDTLS_X509_BADCRL_BAD_MD 0x020000 /**< The CRL is signed with an unacceptable hash. */ +#define MBEDTLS_X509_BADCRL_BAD_PK 0x040000 /**< The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA). */ +#define MBEDTLS_X509_BADCRL_BAD_KEY 0x080000 /**< The CRL is signed with an unacceptable key (eg bad curve, RSA too short). */ + +/* \} name */ +/* \} addtogroup x509_module */ + +/* + * X.509 v3 Key Usage Extension flags + * Reminder: update x509_info_key_usage() when adding new flags. + */ +#define MBEDTLS_X509_KU_DIGITAL_SIGNATURE (0x80) /* bit 0 */ +#define MBEDTLS_X509_KU_NON_REPUDIATION (0x40) /* bit 1 */ +#define MBEDTLS_X509_KU_KEY_ENCIPHERMENT (0x20) /* bit 2 */ +#define MBEDTLS_X509_KU_DATA_ENCIPHERMENT (0x10) /* bit 3 */ +#define MBEDTLS_X509_KU_KEY_AGREEMENT (0x08) /* bit 4 */ +#define MBEDTLS_X509_KU_KEY_CERT_SIGN (0x04) /* bit 5 */ +#define MBEDTLS_X509_KU_CRL_SIGN (0x02) /* bit 6 */ +#define MBEDTLS_X509_KU_ENCIPHER_ONLY (0x01) /* bit 7 */ +#define MBEDTLS_X509_KU_DECIPHER_ONLY (0x8000) /* bit 8 */ + +/* + * Netscape certificate types + * (http://www.mozilla.org/projects/security/pki/nss/tech-notes/tn3.html) + */ + +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT (0x80) /* bit 0 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER (0x40) /* bit 1 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL (0x20) /* bit 2 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING (0x10) /* bit 3 */ +#define MBEDTLS_X509_NS_CERT_TYPE_RESERVED (0x08) /* bit 4 */ +#define MBEDTLS_X509_NS_CERT_TYPE_SSL_CA (0x04) /* bit 5 */ +#define MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA (0x02) /* bit 6 */ +#define MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA (0x01) /* bit 7 */ + +/* + * X.509 extension types + * + * Comments refer to the status for using certificates. Status can be + * different for writing certificates or reading CRLs or CSRs. + */ +#define MBEDTLS_X509_EXT_AUTHORITY_KEY_IDENTIFIER (1 << 0) +#define MBEDTLS_X509_EXT_SUBJECT_KEY_IDENTIFIER (1 << 1) +#define MBEDTLS_X509_EXT_KEY_USAGE (1 << 2) +#define MBEDTLS_X509_EXT_CERTIFICATE_POLICIES (1 << 3) +#define MBEDTLS_X509_EXT_POLICY_MAPPINGS (1 << 4) +#define MBEDTLS_X509_EXT_SUBJECT_ALT_NAME (1 << 5) /* Supported (DNS) */ +#define MBEDTLS_X509_EXT_ISSUER_ALT_NAME (1 << 6) +#define MBEDTLS_X509_EXT_SUBJECT_DIRECTORY_ATTRS (1 << 7) +#define MBEDTLS_X509_EXT_BASIC_CONSTRAINTS (1 << 8) /* Supported */ +#define MBEDTLS_X509_EXT_NAME_CONSTRAINTS (1 << 9) +#define MBEDTLS_X509_EXT_POLICY_CONSTRAINTS (1 << 10) +#define MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE (1 << 11) +#define MBEDTLS_X509_EXT_CRL_DISTRIBUTION_POINTS (1 << 12) +#define MBEDTLS_X509_EXT_INIHIBIT_ANYPOLICY (1 << 13) +#define MBEDTLS_X509_EXT_FRESHEST_CRL (1 << 14) + +#define MBEDTLS_X509_EXT_NS_CERT_TYPE (1 << 16) + +/* + * Storage format identifiers + * Recognized formats: PEM and DER + */ +#define MBEDTLS_X509_FORMAT_DER 1 +#define MBEDTLS_X509_FORMAT_PEM 2 + +#define MBEDTLS_X509_MAX_DN_NAME_SIZE 256 /**< Maximum value size of a DN entry */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures for parsing X.509 certificates, CRLs and CSRs + * \{ + */ + +/** + * Type-length-value structure that allows for ASN1 using DER. + */ +typedef mbedtls_asn1_buf mbedtls_x509_buf; + +/** + * Container for ASN1 bit strings. + */ +typedef mbedtls_asn1_bitstring mbedtls_x509_bitstring; + +/** + * Container for ASN1 named information objects. + * It allows for Relative Distinguished Names (e.g. cn=localhost,ou=code,etc.). + */ +typedef mbedtls_asn1_named_data mbedtls_x509_name; + +/** + * Container for a sequence of ASN.1 items + */ +typedef mbedtls_asn1_sequence mbedtls_x509_sequence; + +/** Container for date and time (precision in seconds). */ +typedef struct mbedtls_x509_time +{ + int year, mon, day; /**< Date. */ + int hour, min, sec; /**< Time. */ +} +mbedtls_x509_time; + +/** \} name Structures for parsing X.509 certificates, CRLs and CSRs */ +/** \} addtogroup x509_module */ + +/** + * \brief Store the certificate DN in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param dn The X509 name to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_dn_gets( char *buf, size_t size, const mbedtls_x509_name *dn ); + +/** + * \brief Store the certificate serial in printable form into buf; + * no more than size characters will be written. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param serial The X509 serial to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_serial_gets( char *buf, size_t size, const mbedtls_x509_buf *serial ); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the past. + * + * \note Intended usage is "if( is_past( valid_to ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param to mbedtls_x509_time to check + * + * \return 1 if the given time is in the past or an error occured, + * 0 otherwise. + */ +int mbedtls_x509_time_is_past( const mbedtls_x509_time *to ); + +/** + * \brief Check a given mbedtls_x509_time against the system time + * and tell if it's in the future. + * + * \note Intended usage is "if( is_future( valid_from ) ) ERROR". + * Hence the return value of 1 if on internal errors. + * + * \param from mbedtls_x509_time to check + * + * \return 1 if the given time is in the future or an error occured, + * 0 otherwise. + */ +int mbedtls_x509_time_is_future( const mbedtls_x509_time *from ); + +/** + * \brief Checkup routine + * + * \return 0 if successful, or 1 if the test failed + */ +int mbedtls_x509_self_test( int verbose ); + +/* + * Internal module functions. You probably do not want to use these unless you + * know you do. + */ +int mbedtls_x509_get_name( unsigned char **p, const unsigned char *end, + mbedtls_x509_name *cur ); +int mbedtls_x509_get_alg_null( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg ); +int mbedtls_x509_get_alg( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *alg, mbedtls_x509_buf *params ); +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) +int mbedtls_x509_get_rsassa_pss_params( const mbedtls_x509_buf *params, + mbedtls_md_type_t *md_alg, mbedtls_md_type_t *mgf_md, + int *salt_len ); +#endif +int mbedtls_x509_get_sig( unsigned char **p, const unsigned char *end, mbedtls_x509_buf *sig ); +int mbedtls_x509_get_sig_alg( const mbedtls_x509_buf *sig_oid, const mbedtls_x509_buf *sig_params, + mbedtls_md_type_t *md_alg, mbedtls_pk_type_t *pk_alg, + void **sig_opts ); +int mbedtls_x509_get_time( unsigned char **p, const unsigned char *end, + mbedtls_x509_time *t ); +int mbedtls_x509_get_serial( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *serial ); +int mbedtls_x509_get_ext( unsigned char **p, const unsigned char *end, + mbedtls_x509_buf *ext, int tag ); +int mbedtls_x509_sig_alg_gets( char *buf, size_t size, const mbedtls_x509_buf *sig_oid, + mbedtls_pk_type_t pk_alg, mbedtls_md_type_t md_alg, + const void *sig_opts ); +int mbedtls_x509_key_size_helper( char *buf, size_t buf_size, const char *name ); +int mbedtls_x509_string_to_names( mbedtls_asn1_named_data **head, const char *name ); +int mbedtls_x509_set_extension( mbedtls_asn1_named_data **head, const char *oid, size_t oid_len, + int critical, const unsigned char *val, + size_t val_len ); +int mbedtls_x509_write_extensions( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ); +int mbedtls_x509_write_names( unsigned char **p, unsigned char *start, + mbedtls_asn1_named_data *first ); +int mbedtls_x509_write_sig( unsigned char **p, unsigned char *start, + const char *oid, size_t oid_len, + unsigned char *sig, size_t size ); + +#define MBEDTLS_X509_SAFE_SNPRINTF \ + do { \ + if( ret < 0 || (size_t) ret >= n ) \ + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); \ + \ + n -= (size_t) ret; \ + p += (size_t) ret; \ + } while( 0 ) + +#ifdef __cplusplus +} +#endif + +#endif /* x509.h */ diff --git a/common/mbedtls/x509_crl.c b/common/mbedtls/x509_crl.c new file mode 100644 index 000000000..12e196a30 --- /dev/null +++ b/common/mbedtls/x509_crl.c @@ -0,0 +1,775 @@ +/* + * X.509 Certidicate Revocation List (CRL) parsing + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + +#include "mbedtls/x509_crl.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(MBEDTLS_FS_IO) || defined(EFIX64) || defined(EFI32) +#include +#endif + +/* + * Version ::= INTEGER { v1(0), v2(1) } + */ +static int x509_crl_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); + } + + return( 0 ); +} + +/* + * X.509 CRL v2 extensions + * + * We currently don't parse any extension's content, but we do check that the + * list of extensions is well-formed and abort on critical extensions (that + * are unsupported as we don't support any extension so far) + */ +static int x509_get_crl_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *ext ) +{ + int ret; + + /* + * crlExtensions [0] EXPLICIT Extensions OPTIONAL + * -- if present, version MUST be v2 + */ + if( ( ret = mbedtls_x509_get_ext( p, end, ext, 0 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + while( *p < end ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + int is_critical = 0; + const unsigned char *end_ext_data; + size_t len; + + /* Get enclosing sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_data = *p + len; + + /* Get OID (currently ignored) */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OID ) ) != 0 ) + { + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + } + *p += len; + + /* Get optional critical */ + if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, + &is_critical ) ) != 0 && + ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + { + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + } + + /* Data should be octet string type */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Ignore data so far and just check its length */ + *p += len; + if( *p != end_ext_data ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* Abort on (unsupported) critical extensions */ + if( is_critical ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 CRL v2 entry extensions (no extensions parsed yet.) + */ +static int x509_get_crl_entry_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *ext ) +{ + int ret; + size_t len = 0; + + /* OPTIONAL */ + if( end <= *p ) + return( 0 ); + + ext->tag = **p; + ext->p = *p; + + /* + * Get CRL-entry extension sequence header + * crlEntryExtensions Extensions OPTIONAL -- if present, MUST be v2 + */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &ext->len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + ext->p = NULL; + return( 0 ); + } + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + } + + end = *p + ext->len; + + if( end != *p + ext->len ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + *p += len; + } + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 CRL Entries + */ +static int x509_get_entries( unsigned char **p, + const unsigned char *end, + mbedtls_x509_crl_entry *entry ) +{ + int ret; + size_t entry_len; + mbedtls_x509_crl_entry *cur_entry = entry; + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_tag( p, end, &entry_len, + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + end = *p + entry_len; + + while( *p < end ) + { + size_t len2; + const unsigned char *end2; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len2, + MBEDTLS_ASN1_SEQUENCE | MBEDTLS_ASN1_CONSTRUCTED ) ) != 0 ) + { + return( ret ); + } + + cur_entry->raw.tag = **p; + cur_entry->raw.p = *p; + cur_entry->raw.len = len2; + end2 = *p + len2; + + if( ( ret = mbedtls_x509_get_serial( p, end2, &cur_entry->serial ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_x509_get_time( p, end2, + &cur_entry->revocation_date ) ) != 0 ) + return( ret ); + + if( ( ret = x509_get_crl_entry_ext( p, end2, + &cur_entry->entry_ext ) ) != 0 ) + return( ret ); + + if( *p < end ) + { + cur_entry->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl_entry ) ); + + if( cur_entry->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + cur_entry = cur_entry->next; + } + } + + return( 0 ); +} + +/* + * Parse one CRLs in DER format and append it to the chained list + */ +int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, + const unsigned char *buf, size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p = NULL, *end = NULL; + mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; + mbedtls_x509_crl *crl = chain; + + /* + * Check for valid input + */ + if( crl == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Add new CRL on the end of the chain if needed. + */ + while( crl->version != 0 && crl->next != NULL ) + crl = crl->next; + + if( crl->version != 0 && crl->next == NULL ) + { + crl->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crl ) ); + + if( crl->next == NULL ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + } + + mbedtls_x509_crl_init( crl->next ); + crl = crl->next; + } + + /* + * Copy raw DER-encoded CRL + */ + if( buflen == 0 ) + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + + p = mbedtls_calloc( 1, buflen ); + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, buflen ); + + crl->raw.p = p; + crl->raw.len = buflen; + + end = p + buflen; + + /* + * CertificateList ::= SEQUENCE { + * tbsCertList TBSCertList, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len != (size_t) ( end - p ) ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + /* + * TBSCertList ::= SEQUENCE { + */ + crl->tbs.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + crl->tbs.len = end - crl->tbs.p; + + /* + * Version ::= INTEGER OPTIONAL { v1(0), v2(1) } + * -- if present, MUST be v2 + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_crl_get_version( &p, end, &crl->version ) ) != 0 || + ( ret = mbedtls_x509_get_alg( &p, end, &crl->sig_oid, &sig_params1 ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( crl->version < 0 || crl->version > 1 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + crl->version++; + + if( ( ret = mbedtls_x509_get_sig_alg( &crl->sig_oid, &sig_params1, + &crl->sig_md, &crl->sig_pk, + &crl->sig_opts ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_UNKNOWN_SIG_ALG ); + } + + /* + * issuer Name + */ + crl->issuer_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &crl->issuer ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + crl->issuer_raw.len = p - crl->issuer_raw.p; + + /* + * thisUpdate Time + * nextUpdate Time OPTIONAL + */ + if( ( ret = mbedtls_x509_get_time( &p, end, &crl->this_update ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( ( ret = mbedtls_x509_get_time( &p, end, &crl->next_update ) ) != 0 ) + { + if( ret != ( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) && + ret != ( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ) ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + } + + /* + * revokedCertificates SEQUENCE OF SEQUENCE { + * userCertificate CertificateSerialNumber, + * revocationDate Time, + * crlEntryExtensions Extensions OPTIONAL + * -- if present, MUST be v2 + * } OPTIONAL + */ + if( ( ret = x509_get_entries( &p, end, &crl->entry ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + /* + * crlExtensions EXPLICIT Extensions OPTIONAL + * -- if present, MUST be v2 + */ + if( crl->version == 2 ) + { + ret = x509_get_crl_ext( &p, end, &crl->crl_ext ); + + if( ret != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + } + + if( p != end ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + end = crl->raw.p + crl->raw.len; + + /* + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( crl->sig_oid.len != sig_oid2.len || + memcmp( crl->sig_oid.p, sig_oid2.p, crl->sig_oid.len ) != 0 || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &crl->sig ) ) != 0 ) + { + mbedtls_x509_crl_free( crl ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_crl_free( crl ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse one or more CRLs and add them to the chained list + */ +int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int ret; + size_t use_len; + mbedtls_pem_context pem; + int is_pem = 0; + + if( chain == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + do + { + mbedtls_pem_init( &pem ); + + // Avoid calling mbedtls_pem_read_buffer() on non-null-terminated + // string + if( buflen == 0 || buf[buflen - 1] != '\0' ) + ret = MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT; + else + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN X509 CRL-----", + "-----END X509 CRL-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + is_pem = 1; + + buflen -= use_len; + buf += use_len; + + if( ( ret = mbedtls_x509_crl_parse_der( chain, + pem.buf, pem.buflen ) ) != 0 ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + } + else if( is_pem ) + { + mbedtls_pem_free( &pem ); + return( ret ); + } + + mbedtls_pem_free( &pem ); + } + /* In the PEM case, buflen is 1 at the end, for the terminated NULL byte. + * And a valid CRL cannot be less than 1 byte anyway. */ + while( is_pem && buflen > 1 ); + + if( is_pem ) + return( 0 ); + else +#endif /* MBEDTLS_PEM_PARSE_C */ + return( mbedtls_x509_crl_parse_der( chain, buf, buflen ) ); +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more CRLs and add them to the chained list + */ +int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_crl_parse( chain, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 14 +#define BC "14" +/* + * Return an informational string about the CRL. + */ +int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl ) +{ + int ret; + size_t n; + char *p; + const mbedtls_x509_crl_entry *entry; + + p = buf; + n = size; + + ret = mbedtls_snprintf( p, n, "%sCRL version : %d", + prefix, crl->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crl->issuer ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sthis update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->this_update.year, crl->this_update.mon, + crl->this_update.day, crl->this_update.hour, + crl->this_update.min, crl->this_update.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%snext update : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crl->next_update.year, crl->next_update.mon, + crl->next_update.day, crl->next_update.hour, + crl->next_update.min, crl->next_update.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + entry = &crl->entry; + + ret = mbedtls_snprintf( p, n, "\n%sRevoked certificates:", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + while( entry != NULL && entry->raw.len != 0 ) + { + ret = mbedtls_snprintf( p, n, "\n%sserial number: ", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets( p, n, &entry->serial ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, " revocation date: " \ + "%04d-%02d-%02d %02d:%02d:%02d", + entry->revocation_date.year, entry->revocation_date.mon, + entry->revocation_date.day, entry->revocation_date.hour, + entry->revocation_date.min, entry->revocation_date.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + entry = entry->next; + } + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &crl->sig_oid, crl->sig_pk, crl->sig_md, + crl->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +/* + * Initialize a CRL chain + */ +void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ) +{ + memset( crl, 0, sizeof(mbedtls_x509_crl) ); +} + +/* + * Unallocate all CRL data + */ +void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ) +{ + mbedtls_x509_crl *crl_cur = crl; + mbedtls_x509_crl *crl_prv; + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + mbedtls_x509_crl_entry *entry_cur; + mbedtls_x509_crl_entry *entry_prv; + + if( crl == NULL ) + return; + + do + { +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( crl_cur->sig_opts ); +#endif + + name_cur = crl_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + entry_cur = crl_cur->entry.next; + while( entry_cur != NULL ) + { + entry_prv = entry_cur; + entry_cur = entry_cur->next; + mbedtls_platform_zeroize( entry_prv, + sizeof( mbedtls_x509_crl_entry ) ); + mbedtls_free( entry_prv ); + } + + if( crl_cur->raw.p != NULL ) + { + mbedtls_platform_zeroize( crl_cur->raw.p, crl_cur->raw.len ); + mbedtls_free( crl_cur->raw.p ); + } + + crl_cur = crl_cur->next; + } + while( crl_cur != NULL ); + + crl_cur = crl; + do + { + crl_prv = crl_cur; + crl_cur = crl_cur->next; + + mbedtls_platform_zeroize( crl_prv, sizeof( mbedtls_x509_crl ) ); + if( crl_prv != crl ) + mbedtls_free( crl_prv ); + } + while( crl_cur != NULL ); +} + +#endif /* MBEDTLS_X509_CRL_PARSE_C */ diff --git a/common/mbedtls/x509_crl.h b/common/mbedtls/x509_crl.h new file mode 100644 index 000000000..99f6e7126 --- /dev/null +++ b/common/mbedtls/x509_crl.h @@ -0,0 +1,176 @@ +/** + * \file x509_crl.h + * + * \brief X.509 certificate revocation list parsing + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_X509_CRL_H +#define MBEDTLS_X509_CRL_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "x509.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \addtogroup x509_module + * \{ */ + +/** + * \name Structures and functions for parsing CRLs + * \{ + */ + +/** + * Certificate revocation list entry. + * Contains the CA-specific serial numbers and revocation dates. + */ +typedef struct mbedtls_x509_crl_entry +{ + mbedtls_x509_buf raw; + + mbedtls_x509_buf serial; + + mbedtls_x509_time revocation_date; + + mbedtls_x509_buf entry_ext; + + struct mbedtls_x509_crl_entry *next; +} +mbedtls_x509_crl_entry; + +/** + * Certificate revocation list structure. + * Every CRL may have multiple entries. + */ +typedef struct mbedtls_x509_crl +{ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< CRL version (1=v1, 2=v2) */ + mbedtls_x509_buf sig_oid; /**< CRL signature type identifier */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + + mbedtls_x509_time this_update; + mbedtls_x509_time next_update; + + mbedtls_x509_crl_entry entry; /**< The CRL entries containing the certificate revocation times for this CA. */ + + mbedtls_x509_buf crl_ext; + + mbedtls_x509_buf sig_oid2; + mbedtls_x509_buf sig; + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct mbedtls_x509_crl *next; +} +mbedtls_x509_crl; + +/** + * \brief Parse a DER-encoded CRL and append it to the chained list + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse_der( mbedtls_x509_crl *chain, + const unsigned char *buf, size_t buflen ); +/** + * \brief Parse one or more CRLs and append them to the chained list + * + * \note Mutliple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param buf buffer holding the CRL data in PEM or DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse( mbedtls_x509_crl *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more CRLs and append them to the chained list + * + * \note Mutliple CRLs are accepted only if using PEM format + * + * \param chain points to the start of the chain + * \param path filename to read the CRLs from (in PEM or DER encoding) + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crl_parse_file( mbedtls_x509_crl *chain, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the CRL. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crl The X509 CRL to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crl_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crl *crl ); + +/** + * \brief Initialize a CRL (chain) + * + * \param crl CRL chain to initialize + */ +void mbedtls_x509_crl_init( mbedtls_x509_crl *crl ); + +/** + * \brief Unallocate all CRL data + * + * \param crl CRL chain to free + */ +void mbedtls_x509_crl_free( mbedtls_x509_crl *crl ); + +/* \} name */ +/* \} addtogroup x509_module */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crl.h */ diff --git a/common/mbedtls/x509_crt.c b/common/mbedtls/x509_crt.c new file mode 100644 index 000000000..925bddf1c --- /dev/null +++ b/common/mbedtls/x509_crt.c @@ -0,0 +1,2488 @@ +/* + * X.509 certificate parsing and verification + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +/* + * The ITU-T X.509 standard defines a certificate format for PKI. + * + * http://www.ietf.org/rfc/rfc5280.txt (Certificates and CRLs) + * http://www.ietf.org/rfc/rfc3279.txt (Alg IDs for CRLs) + * http://www.ietf.org/rfc/rfc2986.txt (CSRs, aka PKCS#10) + * + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.680-0207.pdf + * http://www.itu.int/ITU-T/studygroups/com17/languages/X.690-0207.pdf + * + * [SIRO] https://cabforum.org/wp-content/uploads/Chunghwatelecom201503cabforumV4.pdf + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_X509_CRT_PARSE_C) + +#include "mbedtls/x509_crt.h" +#include "mbedtls/oid.h" +#include "mbedtls/platform_util.h" + +#include +#include + +#if defined(MBEDTLS_PEM_PARSE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_free free +#define mbedtls_calloc calloc +#define mbedtls_snprintf snprintf +#endif + +#if defined(MBEDTLS_THREADING_C) +#include "mbedtls/threading.h" +#endif + +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) +#include +#else +#include +#endif + +#if defined(MBEDTLS_FS_IO) +#include +#if !defined(_WIN32) || defined(EFIX64) || defined(EFI32) +#include +#include +#include +#endif /* !_WIN32 || EFIX64 || EFI32 */ +#endif + +/* + * Item in a verification chain: cert and flags for it + */ +typedef struct { + mbedtls_x509_crt *crt; + uint32_t flags; +} x509_crt_verify_chain_item; + +/* + * Max size of verification chain: end-entity + intermediates + trusted root + */ +#define X509_MAX_VERIFY_CHAIN_SIZE ( MBEDTLS_X509_MAX_INTERMEDIATE_CA + 2 ) + +/* + * Default profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default = +{ +#if defined(MBEDTLS_TLS_DEFAULT_ALLOW_SHA1_IN_CERTIFICATES) + /* Allow SHA-1 (weak, but still safe in controlled environments) */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA1 ) | +#endif + /* Only SHA-2 hashes */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA224 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ + 0xFFFFFFF, /* Any curve */ + 2048, +}; + +/* + * Next-default profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next = +{ + /* Hashes from SHA-256 and above */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA512 ), + 0xFFFFFFF, /* Any PK alg */ +#if defined(MBEDTLS_ECP_C) + /* Curves at or above 128-bit security level */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP521R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP384R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_BP512R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256K1 ), +#else + 0, +#endif + 2048, +}; + +/* + * NSA Suite B Profile + */ +const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb = +{ + /* Only SHA-256 and 384 */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA256 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_MD_SHA384 ), + /* Only ECDSA */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECDSA ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_PK_ECKEY ), +#if defined(MBEDTLS_ECP_C) + /* Only NIST P-256 and P-384 */ + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP256R1 ) | + MBEDTLS_X509_ID_FLAG( MBEDTLS_ECP_DP_SECP384R1 ), +#else + 0, +#endif + 0, +}; + +/* + * Check md_alg against profile + * Return 0 if md_alg is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_md_alg( const mbedtls_x509_crt_profile *profile, + mbedtls_md_type_t md_alg ) +{ + if( md_alg == MBEDTLS_MD_NONE ) + return( -1 ); + + if( ( profile->allowed_mds & MBEDTLS_X509_ID_FLAG( md_alg ) ) != 0 ) + return( 0 ); + + return( -1 ); +} + +/* + * Check pk_alg against profile + * Return 0 if pk_alg is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_pk_alg( const mbedtls_x509_crt_profile *profile, + mbedtls_pk_type_t pk_alg ) +{ + if( pk_alg == MBEDTLS_PK_NONE ) + return( -1 ); + + if( ( profile->allowed_pks & MBEDTLS_X509_ID_FLAG( pk_alg ) ) != 0 ) + return( 0 ); + + return( -1 ); +} + +/* + * Check key against profile + * Return 0 if pk is acceptable for this profile, -1 otherwise + */ +static int x509_profile_check_key( const mbedtls_x509_crt_profile *profile, + const mbedtls_pk_context *pk ) +{ + const mbedtls_pk_type_t pk_alg = mbedtls_pk_get_type( pk ); + +#if defined(MBEDTLS_RSA_C) + if( pk_alg == MBEDTLS_PK_RSA || pk_alg == MBEDTLS_PK_RSASSA_PSS ) + { + if( mbedtls_pk_get_bitlen( pk ) >= profile->rsa_min_bitlen ) + return( 0 ); + + return( -1 ); + } +#endif + +#if defined(MBEDTLS_ECP_C) + if( pk_alg == MBEDTLS_PK_ECDSA || + pk_alg == MBEDTLS_PK_ECKEY || + pk_alg == MBEDTLS_PK_ECKEY_DH ) + { + const mbedtls_ecp_group_id gid = mbedtls_pk_ec( *pk )->grp.id; + + if( gid == MBEDTLS_ECP_DP_NONE ) + return( -1 ); + + if( ( profile->allowed_curves & MBEDTLS_X509_ID_FLAG( gid ) ) != 0 ) + return( 0 ); + + return( -1 ); + } +#endif + + return( -1 ); +} + +/* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + */ +static int x509_get_version( unsigned char **p, + const unsigned char *end, + int *ver ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + { + *ver = 0; + return( 0 ); + } + + return( ret ); + } + + end = *p + len; + + if( ( ret = mbedtls_asn1_get_int( p, end, ver ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_VERSION + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_VERSION + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + */ +static int x509_get_dates( unsigned char **p, + const unsigned char *end, + mbedtls_x509_time *from, + mbedtls_x509_time *to ) +{ + int ret; + size_t len; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_DATE + ret ); + + end = *p + len; + + if( ( ret = mbedtls_x509_get_time( p, end, from ) ) != 0 ) + return( ret ); + + if( ( ret = mbedtls_x509_get_time( p, end, to ) ) != 0 ) + return( ret ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_DATE + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 v2/v3 unique identifier (not parsed) + */ +static int x509_get_uid( unsigned char **p, + const unsigned char *end, + mbedtls_x509_buf *uid, int n ) +{ + int ret; + + if( *p == end ) + return( 0 ); + + uid->tag = **p; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &uid->len, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | n ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + uid->p = *p; + *p += uid->len; + + return( 0 ); +} + +static int x509_get_basic_constraints( unsigned char **p, + const unsigned char *end, + int *ca_istrue, + int *max_pathlen ) +{ + int ret; + size_t len; + + /* + * BasicConstraints ::= SEQUENCE { + * cA BOOLEAN DEFAULT FALSE, + * pathLenConstraint INTEGER (0..MAX) OPTIONAL } + */ + *ca_istrue = 0; /* DEFAULT FALSE */ + *max_pathlen = 0; /* endless */ + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_bool( p, end, ca_istrue ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + ret = mbedtls_asn1_get_int( p, end, ca_istrue ); + + if( ret != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *ca_istrue != 0 ) + *ca_istrue = 1; + } + + if( *p == end ) + return( 0 ); + + if( ( ret = mbedtls_asn1_get_int( p, end, max_pathlen ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + (*max_pathlen)++; + + return( 0 ); +} + +static int x509_get_ns_cert_type( unsigned char **p, + const unsigned char *end, + unsigned char *ns_cert_type) +{ + int ret; + mbedtls_x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( bs.len != 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + /* Get actual bitstring */ + *ns_cert_type = *bs.p; + return( 0 ); +} + +static int x509_get_key_usage( unsigned char **p, + const unsigned char *end, + unsigned int *key_usage) +{ + int ret; + size_t i; + mbedtls_x509_bitstring bs = { 0, 0, NULL }; + + if( ( ret = mbedtls_asn1_get_bitstring( p, end, &bs ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( bs.len < 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + /* Get actual bitstring */ + *key_usage = 0; + for( i = 0; i < bs.len && i < sizeof( unsigned int ); i++ ) + { + *key_usage |= (unsigned int) bs.p[i] << (8*i); + } + + return( 0 ); +} + +/* + * ExtKeyUsageSyntax ::= SEQUENCE SIZE (1..MAX) OF KeyPurposeId + * + * KeyPurposeId ::= OBJECT IDENTIFIER + */ +static int x509_get_ext_key_usage( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *ext_key_usage) +{ + int ret; + + if( ( ret = mbedtls_asn1_get_sequence_of( p, end, ext_key_usage, MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Sequence length must be >= 1 */ + if( ext_key_usage->buf.p == NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_INVALID_LENGTH ); + + return( 0 ); +} + +/* + * SubjectAltName ::= GeneralNames + * + * GeneralNames ::= SEQUENCE SIZE (1..MAX) OF GeneralName + * + * GeneralName ::= CHOICE { + * otherName [0] OtherName, + * rfc822Name [1] IA5String, + * dNSName [2] IA5String, + * x400Address [3] ORAddress, + * directoryName [4] Name, + * ediPartyName [5] EDIPartyName, + * uniformResourceIdentifier [6] IA5String, + * iPAddress [7] OCTET STRING, + * registeredID [8] OBJECT IDENTIFIER } + * + * OtherName ::= SEQUENCE { + * type-id OBJECT IDENTIFIER, + * value [0] EXPLICIT ANY DEFINED BY type-id } + * + * EDIPartyName ::= SEQUENCE { + * nameAssigner [0] DirectoryString OPTIONAL, + * partyName [1] DirectoryString } + * + * NOTE: we only parse and use dNSName at this point. + */ +static int x509_get_subject_alt_name( unsigned char **p, + const unsigned char *end, + mbedtls_x509_sequence *subject_alt_name ) +{ + int ret; + size_t len, tag_len; + mbedtls_asn1_buf *buf; + unsigned char tag; + mbedtls_asn1_sequence *cur = subject_alt_name; + + /* Get main sequence tag */ + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( *p + len != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + while( *p < end ) + { + if( ( end - *p ) < 1 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_OUT_OF_DATA ); + + tag = **p; + (*p)++; + if( ( ret = mbedtls_asn1_get_len( p, end, &tag_len ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + if( ( tag & MBEDTLS_ASN1_TAG_CLASS_MASK ) != + MBEDTLS_ASN1_CONTEXT_SPECIFIC ) + { + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } + + /* Skip everything but DNS name */ + if( tag != ( MBEDTLS_ASN1_CONTEXT_SPECIFIC | 2 ) ) + { + *p += tag_len; + continue; + } + + /* Allocate and assign next pointer */ + if( cur->buf.p != NULL ) + { + if( cur->next != NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + cur->next = mbedtls_calloc( 1, sizeof( mbedtls_asn1_sequence ) ); + + if( cur->next == NULL ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_ALLOC_FAILED ); + + cur = cur->next; + } + + buf = &(cur->buf); + buf->tag = tag; + buf->p = *p; + buf->len = tag_len; + *p += buf->len; + } + + /* Set final sequence entry's next pointer to NULL */ + cur->next = NULL; + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * X.509 v3 extensions + * + */ +static int x509_get_crt_ext( unsigned char **p, + const unsigned char *end, + mbedtls_x509_crt *crt ) +{ + int ret; + size_t len; + unsigned char *end_ext_data, *end_ext_octet; + + if( ( ret = mbedtls_x509_get_ext( p, end, &crt->v3_ext, 3 ) ) != 0 ) + { + if( ret == MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) + return( 0 ); + + return( ret ); + } + + while( *p < end ) + { + /* + * Extension ::= SEQUENCE { + * extnID OBJECT IDENTIFIER, + * critical BOOLEAN DEFAULT FALSE, + * extnValue OCTET STRING } + */ + mbedtls_x509_buf extn_oid = {0, 0, NULL}; + int is_critical = 0; /* DEFAULT FALSE */ + int ext_type = 0; + + if( ( ret = mbedtls_asn1_get_tag( p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_data = *p + len; + + /* Get extension ID */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &extn_oid.len, + MBEDTLS_ASN1_OID ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + extn_oid.tag = MBEDTLS_ASN1_OID; + extn_oid.p = *p; + *p += extn_oid.len; + + /* Get optional critical */ + if( ( ret = mbedtls_asn1_get_bool( p, end_ext_data, &is_critical ) ) != 0 && + ( ret != MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ) ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + /* Data should be octet string type */ + if( ( ret = mbedtls_asn1_get_tag( p, end_ext_data, &len, + MBEDTLS_ASN1_OCTET_STRING ) ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + ret ); + + end_ext_octet = *p + len; + + if( end_ext_octet != end_ext_data ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + /* + * Detect supported extensions + */ + ret = mbedtls_oid_get_x509_ext_type( &extn_oid, &ext_type ); + + if( ret != 0 ) + { + /* No parser found, skip extension */ + *p = end_ext_octet; + +#if !defined(MBEDTLS_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION) + if( is_critical ) + { + /* Data is marked as critical: fail */ + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_UNEXPECTED_TAG ); + } +#endif + continue; + } + + /* Forbid repeated extensions */ + if( ( crt->ext_types & ext_type ) != 0 ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS ); + + crt->ext_types |= ext_type; + + switch( ext_type ) + { + case MBEDTLS_X509_EXT_BASIC_CONSTRAINTS: + /* Parse basic constraints */ + if( ( ret = x509_get_basic_constraints( p, end_ext_octet, + &crt->ca_istrue, &crt->max_pathlen ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_KEY_USAGE: + /* Parse key usage */ + if( ( ret = x509_get_key_usage( p, end_ext_octet, + &crt->key_usage ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE: + /* Parse extended key usage */ + if( ( ret = x509_get_ext_key_usage( p, end_ext_octet, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_SUBJECT_ALT_NAME: + /* Parse subject alt name */ + if( ( ret = x509_get_subject_alt_name( p, end_ext_octet, + &crt->subject_alt_names ) ) != 0 ) + return( ret ); + break; + + case MBEDTLS_X509_EXT_NS_CERT_TYPE: + /* Parse netscape certificate type */ + if( ( ret = x509_get_ns_cert_type( p, end_ext_octet, + &crt->ns_cert_type ) ) != 0 ) + return( ret ); + break; + + default: + return( MBEDTLS_ERR_X509_FEATURE_UNAVAILABLE ); + } + } + + if( *p != end ) + return( MBEDTLS_ERR_X509_INVALID_EXTENSIONS + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + + return( 0 ); +} + +/* + * Parse and fill a single X.509 certificate in DER format + */ +static int x509_crt_parse_der_core( mbedtls_x509_crt *crt, const unsigned char *buf, + size_t buflen ) +{ + int ret; + size_t len; + unsigned char *p, *end, *crt_end; + mbedtls_x509_buf sig_params1, sig_params2, sig_oid2; + + memset( &sig_params1, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_params2, 0, sizeof( mbedtls_x509_buf ) ); + memset( &sig_oid2, 0, sizeof( mbedtls_x509_buf ) ); + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + // Use the original buffer until we figure out actual length + p = (unsigned char*) buf; + len = buflen; + end = p + len; + + /* + * Certificate ::= SEQUENCE { + * tbsCertificate TBSCertificate, + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING } + */ + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT ); + } + + if( len > (size_t) ( end - p ) ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + crt_end = p + len; + + // Create and populate a new buffer for the raw field + crt->raw.len = crt_end - buf; + crt->raw.p = p = mbedtls_calloc( 1, crt->raw.len ); + if( p == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + memcpy( p, buf, crt->raw.len ); + + // Direct pointers to the new buffer + p += crt->raw.len - len; + end = crt_end = p + len; + + /* + * TBSCertificate ::= SEQUENCE { + */ + crt->tbs.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + end = p + len; + crt->tbs.len = end - crt->tbs.p; + + /* + * Version ::= INTEGER { v1(0), v2(1), v3(2) } + * + * CertificateSerialNumber ::= INTEGER + * + * signature AlgorithmIdentifier + */ + if( ( ret = x509_get_version( &p, end, &crt->version ) ) != 0 || + ( ret = mbedtls_x509_get_serial( &p, end, &crt->serial ) ) != 0 || + ( ret = mbedtls_x509_get_alg( &p, end, &crt->sig_oid, + &sig_params1 ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( crt->version < 0 || crt->version > 2 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_UNKNOWN_VERSION ); + } + + crt->version++; + + if( ( ret = mbedtls_x509_get_sig_alg( &crt->sig_oid, &sig_params1, + &crt->sig_md, &crt->sig_pk, + &crt->sig_opts ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * issuer Name + */ + crt->issuer_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( ( ret = mbedtls_x509_get_name( &p, p + len, &crt->issuer ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->issuer_raw.len = p - crt->issuer_raw.p; + + /* + * Validity ::= SEQUENCE { + * notBefore Time, + * notAfter Time } + * + */ + if( ( ret = x509_get_dates( &p, end, &crt->valid_from, + &crt->valid_to ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * subject Name + */ + crt->subject_raw.p = p; + + if( ( ret = mbedtls_asn1_get_tag( &p, end, &len, + MBEDTLS_ASN1_CONSTRUCTED | MBEDTLS_ASN1_SEQUENCE ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + ret ); + } + + if( len && ( ret = mbedtls_x509_get_name( &p, p + len, &crt->subject ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + crt->subject_raw.len = p - crt->subject_raw.p; + + /* + * SubjectPublicKeyInfo + */ + if( ( ret = mbedtls_pk_parse_subpubkey( &p, end, &crt->pk ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + /* + * issuerUniqueID [1] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * subjectUniqueID [2] IMPLICIT UniqueIdentifier OPTIONAL, + * -- If present, version shall be v2 or v3 + * extensions [3] EXPLICIT Extensions OPTIONAL + * -- If present, version shall be v3 + */ + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->issuer_id, 1 ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( crt->version == 2 || crt->version == 3 ) + { + ret = x509_get_uid( &p, end, &crt->subject_id, 2 ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + +#if !defined(MBEDTLS_X509_ALLOW_EXTENSIONS_NON_V3) + if( crt->version == 3 ) +#endif + { + ret = x509_get_crt_ext( &p, end, crt ); + if( ret != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + } + + if( p != end ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + end = crt_end; + + /* + * } + * -- end of TBSCertificate + * + * signatureAlgorithm AlgorithmIdentifier, + * signatureValue BIT STRING + */ + if( ( ret = mbedtls_x509_get_alg( &p, end, &sig_oid2, &sig_params2 ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( crt->sig_oid.len != sig_oid2.len || + memcmp( crt->sig_oid.p, sig_oid2.p, crt->sig_oid.len ) != 0 || + sig_params1.len != sig_params2.len || + ( sig_params1.len != 0 && + memcmp( sig_params1.p, sig_params2.p, sig_params1.len ) != 0 ) ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_SIG_MISMATCH ); + } + + if( ( ret = mbedtls_x509_get_sig( &p, end, &crt->sig ) ) != 0 ) + { + mbedtls_x509_crt_free( crt ); + return( ret ); + } + + if( p != end ) + { + mbedtls_x509_crt_free( crt ); + return( MBEDTLS_ERR_X509_INVALID_FORMAT + + MBEDTLS_ERR_ASN1_LENGTH_MISMATCH ); + } + + return( 0 ); +} + +/* + * Parse one X.509 certificate in DER format from a buffer and add them to a + * chained list + */ +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, + size_t buflen ) +{ + int ret; + mbedtls_x509_crt *crt = chain, *prev = NULL; + + /* + * Check for valid input + */ + if( crt == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + while( crt->version != 0 && crt->next != NULL ) + { + prev = crt; + crt = crt->next; + } + + /* + * Add new certificate on the end of the chain if needed. + */ + if( crt->version != 0 && crt->next == NULL ) + { + crt->next = mbedtls_calloc( 1, sizeof( mbedtls_x509_crt ) ); + + if( crt->next == NULL ) + return( MBEDTLS_ERR_X509_ALLOC_FAILED ); + + prev = crt; + mbedtls_x509_crt_init( crt->next ); + crt = crt->next; + } + + if( ( ret = x509_crt_parse_der_core( crt, buf, buflen ) ) != 0 ) + { + if( prev ) + prev->next = NULL; + + if( crt != chain ) + mbedtls_free( crt ); + + return( ret ); + } + + return( 0 ); +} + +/* + * Parse one or more PEM certificates from a buffer and add them to the chained + * list + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ) +{ +#if defined(MBEDTLS_PEM_PARSE_C) + int success = 0, first_error = 0, total_failed = 0; + int buf_format = MBEDTLS_X509_FORMAT_DER; +#endif + + /* + * Check for valid input + */ + if( chain == NULL || buf == NULL ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + /* + * Determine buffer content. Buffer contains either one DER certificate or + * one or more PEM certificates. + */ +#if defined(MBEDTLS_PEM_PARSE_C) + if( buflen != 0 && buf[buflen - 1] == '\0' && + strstr( (const char *) buf, "-----BEGIN CERTIFICATE-----" ) != NULL ) + { + buf_format = MBEDTLS_X509_FORMAT_PEM; + } + + if( buf_format == MBEDTLS_X509_FORMAT_DER ) + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#else + return mbedtls_x509_crt_parse_der( chain, buf, buflen ); +#endif + +#if defined(MBEDTLS_PEM_PARSE_C) + if( buf_format == MBEDTLS_X509_FORMAT_PEM ) + { + int ret; + mbedtls_pem_context pem; + + /* 1 rather than 0 since the terminating NULL byte is counted in */ + while( buflen > 1 ) + { + size_t use_len; + mbedtls_pem_init( &pem ); + + /* If we get there, we know the string is null-terminated */ + ret = mbedtls_pem_read_buffer( &pem, + "-----BEGIN CERTIFICATE-----", + "-----END CERTIFICATE-----", + buf, NULL, 0, &use_len ); + + if( ret == 0 ) + { + /* + * Was PEM encoded + */ + buflen -= use_len; + buf += use_len; + } + else if( ret == MBEDTLS_ERR_PEM_BAD_INPUT_DATA ) + { + return( ret ); + } + else if( ret != MBEDTLS_ERR_PEM_NO_HEADER_FOOTER_PRESENT ) + { + mbedtls_pem_free( &pem ); + + /* + * PEM header and footer were found + */ + buflen -= use_len; + buf += use_len; + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + else + break; + + ret = mbedtls_x509_crt_parse_der( chain, pem.buf, pem.buflen ); + + mbedtls_pem_free( &pem ); + + if( ret != 0 ) + { + /* + * Quit parsing on a memory error + */ + if( ret == MBEDTLS_ERR_X509_ALLOC_FAILED ) + return( ret ); + + if( first_error == 0 ) + first_error = ret; + + total_failed++; + continue; + } + + success = 1; + } + } + + if( success ) + return( total_failed ); + else if( first_error ) + return( first_error ); + else + return( MBEDTLS_ERR_X509_CERT_UNKNOWN_FORMAT ); +#endif /* MBEDTLS_PEM_PARSE_C */ +} + +#if defined(MBEDTLS_FS_IO) +/* + * Load one or more certificates and add them to the chained list + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ) +{ + int ret; + size_t n; + unsigned char *buf; + + if( ( ret = mbedtls_pk_load_file( path, &buf, &n ) ) != 0 ) + return( ret ); + + ret = mbedtls_x509_crt_parse( chain, buf, n ); + + mbedtls_platform_zeroize( buf, n ); + mbedtls_free( buf ); + + return( ret ); +} + +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ) +{ + int ret = 0; +#if defined(_WIN32) && !defined(EFIX64) && !defined(EFI32) + int w_ret; + WCHAR szDir[MAX_PATH]; + char filename[MAX_PATH]; + char *p; + size_t len = strlen( path ); + + WIN32_FIND_DATAW file_data; + HANDLE hFind; + + if( len > MAX_PATH - 3 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + memset( szDir, 0, sizeof(szDir) ); + memset( filename, 0, MAX_PATH ); + memcpy( filename, path, len ); + filename[len++] = '\\'; + p = filename + len; + filename[len++] = '*'; + + w_ret = MultiByteToWideChar( CP_ACP, 0, filename, (int)len, szDir, + MAX_PATH - 3 ); + if( w_ret == 0 ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + hFind = FindFirstFileW( szDir, &file_data ); + if( hFind == INVALID_HANDLE_VALUE ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + + len = MAX_PATH - len; + do + { + memset( p, 0, len ); + + if( file_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY ) + continue; + + w_ret = WideCharToMultiByte( CP_ACP, 0, file_data.cFileName, + lstrlenW( file_data.cFileName ), + p, (int) len - 1, + NULL, NULL ); + if( w_ret == 0 ) + { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + w_ret = mbedtls_x509_crt_parse_file( chain, filename ); + if( w_ret < 0 ) + ret++; + else + ret += w_ret; + } + while( FindNextFileW( hFind, &file_data ) != 0 ); + + if( GetLastError() != ERROR_NO_MORE_FILES ) + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + +cleanup: + FindClose( hFind ); +#else /* _WIN32 */ + int t_ret; + int snp_ret; + struct stat sb; + struct dirent *entry; + char entry_name[MBEDTLS_X509_MAX_FILE_PATH_LEN]; + DIR *dir = opendir( path ); + + if( dir == NULL ) + return( MBEDTLS_ERR_X509_FILE_IO_ERROR ); + +#if defined(MBEDTLS_THREADING_C) + if( ( ret = mbedtls_mutex_lock( &mbedtls_threading_readdir_mutex ) ) != 0 ) + { + closedir( dir ); + return( ret ); + } +#endif /* MBEDTLS_THREADING_C */ + + while( ( entry = readdir( dir ) ) != NULL ) + { + snp_ret = mbedtls_snprintf( entry_name, sizeof entry_name, + "%s/%s", path, entry->d_name ); + + if( snp_ret < 0 || (size_t)snp_ret >= sizeof entry_name ) + { + ret = MBEDTLS_ERR_X509_BUFFER_TOO_SMALL; + goto cleanup; + } + else if( stat( entry_name, &sb ) == -1 ) + { + ret = MBEDTLS_ERR_X509_FILE_IO_ERROR; + goto cleanup; + } + + if( !S_ISREG( sb.st_mode ) ) + continue; + + // Ignore parse errors + // + t_ret = mbedtls_x509_crt_parse_file( chain, entry_name ); + if( t_ret < 0 ) + ret++; + else + ret += t_ret; + } + +cleanup: + closedir( dir ); + +#if defined(MBEDTLS_THREADING_C) + if( mbedtls_mutex_unlock( &mbedtls_threading_readdir_mutex ) != 0 ) + ret = MBEDTLS_ERR_THREADING_MUTEX_ERROR; +#endif /* MBEDTLS_THREADING_C */ + +#endif /* _WIN32 */ + + return( ret ); +} +#endif /* MBEDTLS_FS_IO */ + +static int x509_info_subject_alt_name( char **buf, size_t *size, + const mbedtls_x509_sequence *subject_alt_name ) +{ + size_t i; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = subject_alt_name; + const char *sep = ""; + size_t sep_len = 0; + + while( cur != NULL ) + { + if( cur->buf.len + sep_len >= n ) + { + *p = '\0'; + return( MBEDTLS_ERR_X509_BUFFER_TOO_SMALL ); + } + + n -= cur->buf.len + sep_len; + for( i = 0; i < sep_len; i++ ) + *p++ = sep[i]; + for( i = 0; i < cur->buf.len; i++ ) + *p++ = cur->buf.p[i]; + + sep = ", "; + sep_len = 2; + + cur = cur->next; + } + + *p = '\0'; + + *size = n; + *buf = p; + + return( 0 ); +} + +#define PRINT_ITEM(i) \ + { \ + ret = mbedtls_snprintf( p, n, "%s" i, sep ); \ + MBEDTLS_X509_SAFE_SNPRINTF; \ + sep = ", "; \ + } + +#define CERT_TYPE(type,name) \ + if( ns_cert_type & type ) \ + PRINT_ITEM( name ); + +static int x509_info_cert_type( char **buf, size_t *size, + unsigned char ns_cert_type ) +{ + int ret; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT, "SSL Client" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_SERVER, "SSL Server" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL, "Email" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING, "Object Signing" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_RESERVED, "Reserved" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_SSL_CA, "SSL CA" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_EMAIL_CA, "Email CA" ); + CERT_TYPE( MBEDTLS_X509_NS_CERT_TYPE_OBJECT_SIGNING_CA, "Object Signing CA" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +#define KEY_USAGE(code,name) \ + if( key_usage & code ) \ + PRINT_ITEM( name ); + +static int x509_info_key_usage( char **buf, size_t *size, + unsigned int key_usage ) +{ + int ret; + size_t n = *size; + char *p = *buf; + const char *sep = ""; + + KEY_USAGE( MBEDTLS_X509_KU_DIGITAL_SIGNATURE, "Digital Signature" ); + KEY_USAGE( MBEDTLS_X509_KU_NON_REPUDIATION, "Non Repudiation" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_ENCIPHERMENT, "Key Encipherment" ); + KEY_USAGE( MBEDTLS_X509_KU_DATA_ENCIPHERMENT, "Data Encipherment" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_AGREEMENT, "Key Agreement" ); + KEY_USAGE( MBEDTLS_X509_KU_KEY_CERT_SIGN, "Key Cert Sign" ); + KEY_USAGE( MBEDTLS_X509_KU_CRL_SIGN, "CRL Sign" ); + KEY_USAGE( MBEDTLS_X509_KU_ENCIPHER_ONLY, "Encipher Only" ); + KEY_USAGE( MBEDTLS_X509_KU_DECIPHER_ONLY, "Decipher Only" ); + + *size = n; + *buf = p; + + return( 0 ); +} + +static int x509_info_ext_key_usage( char **buf, size_t *size, + const mbedtls_x509_sequence *extended_key_usage ) +{ + int ret; + const char *desc; + size_t n = *size; + char *p = *buf; + const mbedtls_x509_sequence *cur = extended_key_usage; + const char *sep = ""; + + while( cur != NULL ) + { + if( mbedtls_oid_get_extended_key_usage( &cur->buf, &desc ) != 0 ) + desc = "???"; + + ret = mbedtls_snprintf( p, n, "%s%s", sep, desc ); + MBEDTLS_X509_SAFE_SNPRINTF; + + sep = ", "; + + cur = cur->next; + } + + *size = n; + *buf = p; + + return( 0 ); +} + +/* + * Return an informational string about the certificate. + */ +#define BEFORE_COLON 18 +#define BC "18" +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ) +{ + int ret; + size_t n; + char *p; + char key_size_str[BEFORE_COLON]; + + p = buf; + n = size; + + if( NULL == crt ) + { + ret = mbedtls_snprintf( p, n, "\nCertificate is uninitialised!\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); + } + + ret = mbedtls_snprintf( p, n, "%scert. version : %d\n", + prefix, crt->version ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_snprintf( p, n, "%sserial number : ", + prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_serial_gets( p, n, &crt->serial ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissuer name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crt->issuer ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssubject name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + ret = mbedtls_x509_dn_gets( p, n, &crt->subject ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sissued on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_from.year, crt->valid_from.mon, + crt->valid_from.day, crt->valid_from.hour, + crt->valid_from.min, crt->valid_from.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%sexpires on : " \ + "%04d-%02d-%02d %02d:%02d:%02d", prefix, + crt->valid_to.year, crt->valid_to.mon, + crt->valid_to.day, crt->valid_to.hour, + crt->valid_to.min, crt->valid_to.sec ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_snprintf( p, n, "\n%ssigned using : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + ret = mbedtls_x509_sig_alg_gets( p, n, &crt->sig_oid, crt->sig_pk, + crt->sig_md, crt->sig_opts ); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* Key size */ + if( ( ret = mbedtls_x509_key_size_helper( key_size_str, BEFORE_COLON, + mbedtls_pk_get_name( &crt->pk ) ) ) != 0 ) + { + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n%s%-" BC "s: %d bits", prefix, key_size_str, + (int) mbedtls_pk_get_bitlen( &crt->pk ) ); + MBEDTLS_X509_SAFE_SNPRINTF; + + /* + * Optional extensions + */ + + if( crt->ext_types & MBEDTLS_X509_EXT_BASIC_CONSTRAINTS ) + { + ret = mbedtls_snprintf( p, n, "\n%sbasic constraints : CA=%s", prefix, + crt->ca_istrue ? "true" : "false" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( crt->max_pathlen > 0 ) + { + ret = mbedtls_snprintf( p, n, ", max_pathlen=%d", crt->max_pathlen - 1 ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + } + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + ret = mbedtls_snprintf( p, n, "\n%ssubject alt name : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_subject_alt_name( &p, &n, + &crt->subject_alt_names ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_NS_CERT_TYPE ) + { + ret = mbedtls_snprintf( p, n, "\n%scert. type : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_cert_type( &p, &n, crt->ns_cert_type ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) + { + ret = mbedtls_snprintf( p, n, "\n%skey usage : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_key_usage( &p, &n, crt->key_usage ) ) != 0 ) + return( ret ); + } + + if( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) + { + ret = mbedtls_snprintf( p, n, "\n%sext key usage : ", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + + if( ( ret = x509_info_ext_key_usage( &p, &n, + &crt->ext_key_usage ) ) != 0 ) + return( ret ); + } + + ret = mbedtls_snprintf( p, n, "\n" ); + MBEDTLS_X509_SAFE_SNPRINTF; + + return( (int) ( size - n ) ); +} + +struct x509_crt_verify_string { + int code; + const char *string; +}; + +static const struct x509_crt_verify_string x509_crt_verify_strings[] = { + { MBEDTLS_X509_BADCERT_EXPIRED, "The certificate validity has expired" }, + { MBEDTLS_X509_BADCERT_REVOKED, "The certificate has been revoked (is on a CRL)" }, + { MBEDTLS_X509_BADCERT_CN_MISMATCH, "The certificate Common Name (CN) does not match with the expected CN" }, + { MBEDTLS_X509_BADCERT_NOT_TRUSTED, "The certificate is not correctly signed by the trusted CA" }, + { MBEDTLS_X509_BADCRL_NOT_TRUSTED, "The CRL is not correctly signed by the trusted CA" }, + { MBEDTLS_X509_BADCRL_EXPIRED, "The CRL is expired" }, + { MBEDTLS_X509_BADCERT_MISSING, "Certificate was missing" }, + { MBEDTLS_X509_BADCERT_SKIP_VERIFY, "Certificate verification was skipped" }, + { MBEDTLS_X509_BADCERT_OTHER, "Other reason (can be used by verify callback)" }, + { MBEDTLS_X509_BADCERT_FUTURE, "The certificate validity starts in the future" }, + { MBEDTLS_X509_BADCRL_FUTURE, "The CRL is from the future" }, + { MBEDTLS_X509_BADCERT_KEY_USAGE, "Usage does not match the keyUsage extension" }, + { MBEDTLS_X509_BADCERT_EXT_KEY_USAGE, "Usage does not match the extendedKeyUsage extension" }, + { MBEDTLS_X509_BADCERT_NS_CERT_TYPE, "Usage does not match the nsCertType extension" }, + { MBEDTLS_X509_BADCERT_BAD_MD, "The certificate is signed with an unacceptable hash." }, + { MBEDTLS_X509_BADCERT_BAD_PK, "The certificate is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, + { MBEDTLS_X509_BADCERT_BAD_KEY, "The certificate is signed with an unacceptable key (eg bad curve, RSA too short)." }, + { MBEDTLS_X509_BADCRL_BAD_MD, "The CRL is signed with an unacceptable hash." }, + { MBEDTLS_X509_BADCRL_BAD_PK, "The CRL is signed with an unacceptable PK alg (eg RSA vs ECDSA)." }, + { MBEDTLS_X509_BADCRL_BAD_KEY, "The CRL is signed with an unacceptable key (eg bad curve, RSA too short)." }, + { 0, NULL } +}; + +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ) +{ + int ret; + const struct x509_crt_verify_string *cur; + char *p = buf; + size_t n = size; + + for( cur = x509_crt_verify_strings; cur->string != NULL ; cur++ ) + { + if( ( flags & cur->code ) == 0 ) + continue; + + ret = mbedtls_snprintf( p, n, "%s%s\n", prefix, cur->string ); + MBEDTLS_X509_SAFE_SNPRINTF; + flags ^= cur->code; + } + + if( flags != 0 ) + { + ret = mbedtls_snprintf( p, n, "%sUnknown reason " + "(this should not happen)\n", prefix ); + MBEDTLS_X509_SAFE_SNPRINTF; + } + + return( (int) ( size - n ) ); +} + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) +int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, + unsigned int usage ) +{ + unsigned int usage_must, usage_may; + unsigned int may_mask = MBEDTLS_X509_KU_ENCIPHER_ONLY + | MBEDTLS_X509_KU_DECIPHER_ONLY; + + if( ( crt->ext_types & MBEDTLS_X509_EXT_KEY_USAGE ) == 0 ) + return( 0 ); + + usage_must = usage & ~may_mask; + + if( ( ( crt->key_usage & ~may_mask ) & usage_must ) != usage_must ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + usage_may = usage & may_mask; + + if( ( ( crt->key_usage & may_mask ) | usage_may ) != usage_may ) + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); + + return( 0 ); +} +#endif + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) +int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len ) +{ + const mbedtls_x509_sequence *cur; + + /* Extension is not mandatory, absent means no restriction */ + if( ( crt->ext_types & MBEDTLS_X509_EXT_EXTENDED_KEY_USAGE ) == 0 ) + return( 0 ); + + /* + * Look for the requested usage (or wildcard ANY) in our list + */ + for( cur = &crt->ext_key_usage; cur != NULL; cur = cur->next ) + { + const mbedtls_x509_buf *cur_oid = &cur->buf; + + if( cur_oid->len == usage_len && + memcmp( cur_oid->p, usage_oid, usage_len ) == 0 ) + { + return( 0 ); + } + + if( MBEDTLS_OID_CMP( MBEDTLS_OID_ANY_EXTENDED_KEY_USAGE, cur_oid ) == 0 ) + return( 0 ); + } + + return( MBEDTLS_ERR_X509_BAD_INPUT_DATA ); +} +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/* + * Return 1 if the certificate is revoked, or 0 otherwise. + */ +int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ) +{ + const mbedtls_x509_crl_entry *cur = &crl->entry; + + while( cur != NULL && cur->serial.len != 0 ) + { + if( crt->serial.len == cur->serial.len && + memcmp( crt->serial.p, cur->serial.p, crt->serial.len ) == 0 ) + { + if( mbedtls_x509_time_is_past( &cur->revocation_date ) ) + return( 1 ); + } + + cur = cur->next; + } + + return( 0 ); +} + +/* + * Check that the given certificate is not revoked according to the CRL. + * Skip validation if no CRL for the given CA is present. + */ +static int x509_crt_verifycrl( mbedtls_x509_crt *crt, mbedtls_x509_crt *ca, + mbedtls_x509_crl *crl_list, + const mbedtls_x509_crt_profile *profile ) +{ + int flags = 0; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + const mbedtls_md_info_t *md_info; + + if( ca == NULL ) + return( flags ); + + while( crl_list != NULL ) + { + if( crl_list->version == 0 || + crl_list->issuer_raw.len != ca->subject_raw.len || + memcmp( crl_list->issuer_raw.p, ca->subject_raw.p, + crl_list->issuer_raw.len ) != 0 ) + { + crl_list = crl_list->next; + continue; + } + + /* + * Check if the CA is configured to sign CRLs + */ +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( mbedtls_x509_crt_check_key_usage( ca, MBEDTLS_X509_KU_CRL_SIGN ) != 0 ) + { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } +#endif + + /* + * Check if CRL is correctly signed by the trusted CA + */ + if( x509_profile_check_md_alg( profile, crl_list->sig_md ) != 0 ) + flags |= MBEDTLS_X509_BADCRL_BAD_MD; + + if( x509_profile_check_pk_alg( profile, crl_list->sig_pk ) != 0 ) + flags |= MBEDTLS_X509_BADCRL_BAD_PK; + + md_info = mbedtls_md_info_from_type( crl_list->sig_md ); + if( mbedtls_md( md_info, crl_list->tbs.p, crl_list->tbs.len, hash ) != 0 ) + { + /* Note: this can't happen except after an internal error */ + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + if( x509_profile_check_key( profile, &ca->pk ) != 0 ) + flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + if( mbedtls_pk_verify_ext( crl_list->sig_pk, crl_list->sig_opts, &ca->pk, + crl_list->sig_md, hash, mbedtls_md_get_size( md_info ), + crl_list->sig.p, crl_list->sig.len ) != 0 ) + { + flags |= MBEDTLS_X509_BADCRL_NOT_TRUSTED; + break; + } + + /* + * Check for validity of CRL (Do not drop out) + */ + if( mbedtls_x509_time_is_past( &crl_list->next_update ) ) + flags |= MBEDTLS_X509_BADCRL_EXPIRED; + + if( mbedtls_x509_time_is_future( &crl_list->this_update ) ) + flags |= MBEDTLS_X509_BADCRL_FUTURE; + + /* + * Check if certificate is revoked + */ + if( mbedtls_x509_crt_is_revoked( crt, crl_list ) ) + { + flags |= MBEDTLS_X509_BADCERT_REVOKED; + break; + } + + crl_list = crl_list->next; + } + + return( flags ); +} +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/* + * Like memcmp, but case-insensitive and always returns -1 if different + */ +static int x509_memcasecmp( const void *s1, const void *s2, size_t len ) +{ + size_t i; + unsigned char diff; + const unsigned char *n1 = s1, *n2 = s2; + + for( i = 0; i < len; i++ ) + { + diff = n1[i] ^ n2[i]; + + if( diff == 0 ) + continue; + + if( diff == 32 && + ( ( n1[i] >= 'a' && n1[i] <= 'z' ) || + ( n1[i] >= 'A' && n1[i] <= 'Z' ) ) ) + { + continue; + } + + return( -1 ); + } + + return( 0 ); +} + +/* + * Return 0 if name matches wildcard, -1 otherwise + */ +static int x509_check_wildcard( const char *cn, const mbedtls_x509_buf *name ) +{ + size_t i; + size_t cn_idx = 0, cn_len = strlen( cn ); + + /* We can't have a match if there is no wildcard to match */ + if( name->len < 3 || name->p[0] != '*' || name->p[1] != '.' ) + return( -1 ); + + for( i = 0; i < cn_len; ++i ) + { + if( cn[i] == '.' ) + { + cn_idx = i; + break; + } + } + + if( cn_idx == 0 ) + return( -1 ); + + if( cn_len - cn_idx == name->len - 1 && + x509_memcasecmp( name->p + 1, cn + cn_idx, name->len - 1 ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 strings, case-insensitive, and allowing for some encoding + * variations (but not all). + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_string_cmp( const mbedtls_x509_buf *a, const mbedtls_x509_buf *b ) +{ + if( a->tag == b->tag && + a->len == b->len && + memcmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + if( ( a->tag == MBEDTLS_ASN1_UTF8_STRING || a->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + ( b->tag == MBEDTLS_ASN1_UTF8_STRING || b->tag == MBEDTLS_ASN1_PRINTABLE_STRING ) && + a->len == b->len && + x509_memcasecmp( a->p, b->p, b->len ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Compare two X.509 Names (aka rdnSequence). + * + * See RFC 5280 section 7.1, though we don't implement the whole algorithm: + * we sometimes return unequal when the full algorithm would return equal, + * but never the other way. (In particular, we don't do Unicode normalisation + * or space folding.) + * + * Return 0 if equal, -1 otherwise. + */ +static int x509_name_cmp( const mbedtls_x509_name *a, const mbedtls_x509_name *b ) +{ + /* Avoid recursion, it might not be optimised by the compiler */ + while( a != NULL || b != NULL ) + { + if( a == NULL || b == NULL ) + return( -1 ); + + /* type */ + if( a->oid.tag != b->oid.tag || + a->oid.len != b->oid.len || + memcmp( a->oid.p, b->oid.p, b->oid.len ) != 0 ) + { + return( -1 ); + } + + /* value */ + if( x509_string_cmp( &a->val, &b->val ) != 0 ) + return( -1 ); + + /* structure of the list of sets */ + if( a->next_merged != b->next_merged ) + return( -1 ); + + a = a->next; + b = b->next; + } + + /* a == NULL == b */ + return( 0 ); +} + +/* + * Check the signature of a certificate by its parent + */ +static int x509_crt_check_signature( const mbedtls_x509_crt *child, + mbedtls_x509_crt *parent ) +{ + const mbedtls_md_info_t *md_info; + unsigned char hash[MBEDTLS_MD_MAX_SIZE]; + + md_info = mbedtls_md_info_from_type( child->sig_md ); + if( mbedtls_md( md_info, child->tbs.p, child->tbs.len, hash ) != 0 ) + { + /* Note: this can't happen except after an internal error */ + return( -1 ); + } + + if( mbedtls_pk_verify_ext( child->sig_pk, child->sig_opts, &parent->pk, + child->sig_md, hash, mbedtls_md_get_size( md_info ), + child->sig.p, child->sig.len ) != 0 ) + { + return( -1 ); + } + + return( 0 ); +} + +/* + * Check if 'parent' is a suitable parent (signing CA) for 'child'. + * Return 0 if yes, -1 if not. + * + * top means parent is a locally-trusted certificate + */ +static int x509_crt_check_parent( const mbedtls_x509_crt *child, + const mbedtls_x509_crt *parent, + int top ) +{ + int need_ca_bit; + + /* Parent must be the issuer */ + if( x509_name_cmp( &child->issuer, &parent->subject ) != 0 ) + return( -1 ); + + /* Parent must have the basicConstraints CA bit set as a general rule */ + need_ca_bit = 1; + + /* Exception: v1/v2 certificates that are locally trusted. */ + if( top && parent->version < 3 ) + need_ca_bit = 0; + + if( need_ca_bit && ! parent->ca_istrue ) + return( -1 ); + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) + if( need_ca_bit && + mbedtls_x509_crt_check_key_usage( parent, MBEDTLS_X509_KU_KEY_CERT_SIGN ) != 0 ) + { + return( -1 ); + } +#endif + + return( 0 ); +} + +/* + * Find a suitable parent for child in candidates, or return NULL. + * + * Here suitable is defined as: + * 1. subject name matches child's issuer + * 2. if necessary, the CA bit is set and key usage allows signing certs + * 3. for trusted roots, the signature is correct + * 4. pathlen constraints are satisfied + * + * If there's a suitable candidate which is also time-valid, return the first + * such. Otherwise, return the first suitable candidate (or NULL if there is + * none). + * + * The rationale for this rule is that someone could have a list of trusted + * roots with two versions on the same root with different validity periods. + * (At least one user reported having such a list and wanted it to just work.) + * The reason we don't just require time-validity is that generally there is + * only one version, and if it's expired we want the flags to state that + * rather than NOT_TRUSTED, as would be the case if we required it here. + * + * The rationale for rule 3 (signature for trusted roots) is that users might + * have two versions of the same CA with different keys in their list, and the + * way we select the correct one is by checking the signature (as we don't + * rely on key identifier extensions). (This is one way users might choose to + * handle key rollover, another relies on self-issued certs, see [SIRO].) + * + * Arguments: + * - [in] child: certificate for which we're looking for a parent + * - [in] candidates: chained list of potential parents + * - [in] top: 1 if candidates consists of trusted roots, ie we're at the top + * of the chain, 0 otherwise + * - [in] path_cnt: number of intermediates seen so far + * - [in] self_cnt: number of self-signed intermediates seen so far + * (will never be greater than path_cnt) + * + * Return value: + * - the first suitable parent found (see above regarding time-validity) + * - NULL if no suitable parent was found + */ +static mbedtls_x509_crt *x509_crt_find_parent_in( mbedtls_x509_crt *child, + mbedtls_x509_crt *candidates, + int top, + size_t path_cnt, + size_t self_cnt ) +{ + mbedtls_x509_crt *parent, *badtime_parent = NULL; + + for( parent = candidates; parent != NULL; parent = parent->next ) + { + /* basic parenting skills (name, CA bit, key usage) */ + if( x509_crt_check_parent( child, parent, top ) != 0 ) + continue; + + /* +1 because stored max_pathlen is 1 higher that the actual value */ + if( parent->max_pathlen > 0 && + (size_t) parent->max_pathlen < 1 + path_cnt - self_cnt ) + { + continue; + } + + /* Signature */ + if( top && x509_crt_check_signature( child, parent ) != 0 ) + { + continue; + } + + /* optional time check */ + if( mbedtls_x509_time_is_past( &parent->valid_to ) || + mbedtls_x509_time_is_future( &parent->valid_from ) ) + { + if( badtime_parent == NULL ) + badtime_parent = parent; + + continue; + } + + break; + } + + if( parent == NULL ) + parent = badtime_parent; + + return( parent ); +} + +/* + * Find a parent in trusted CAs or the provided chain, or return NULL. + * + * Searches in trusted CAs first, and return the first suitable parent found + * (see find_parent_in() for definition of suitable). + * + * Arguments: + * - [in] child: certificate for which we're looking for a parent, followed + * by a chain of possible intermediates + * - [in] trust_ca: locally trusted CAs + * - [out] 1 if parent was found in trust_ca, 0 if found in provided chain + * - [in] path_cnt: number of intermediates seen so far + * - [in] self_cnt: number of self-signed intermediates seen so far + * (will always be no greater than path_cnt) + * + * Return value: + * - the first suitable parent found (see find_parent_in() for "suitable") + * - NULL if no suitable parent was found + */ +static mbedtls_x509_crt *x509_crt_find_parent( mbedtls_x509_crt *child, + mbedtls_x509_crt *trust_ca, + int *parent_is_trusted, + size_t path_cnt, + size_t self_cnt ) +{ + mbedtls_x509_crt *parent; + + /* Look for a parent in trusted CAs */ + *parent_is_trusted = 1; + parent = x509_crt_find_parent_in( child, trust_ca, 1, path_cnt, self_cnt ); + + if( parent != NULL ) + return( parent ); + + /* Look for a parent upwards the chain */ + *parent_is_trusted = 0; + return( x509_crt_find_parent_in( child, child->next, 0, path_cnt, self_cnt ) ); +} + +/* + * Check if an end-entity certificate is locally trusted + * + * Currently we require such certificates to be self-signed (actually only + * check for self-issued as self-signatures are not checked) + */ +static int x509_crt_check_ee_locally_trusted( + mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca ) +{ + mbedtls_x509_crt *cur; + + /* must be self-issued */ + if( x509_name_cmp( &crt->issuer, &crt->subject ) != 0 ) + return( -1 ); + + /* look for an exact match with trusted cert */ + for( cur = trust_ca; cur != NULL; cur = cur->next ) + { + if( crt->raw.len == cur->raw.len && + memcmp( crt->raw.p, cur->raw.p, crt->raw.len ) == 0 ) + { + return( 0 ); + } + } + + /* too bad */ + return( -1 ); +} + +/* + * Build and verify a certificate chain + * + * Given a peer-provided list of certificates EE, C1, ..., Cn and + * a list of trusted certs R1, ... Rp, try to build and verify a chain + * EE, Ci1, ... Ciq [, Rj] + * such that every cert in the chain is a child of the next one, + * jumping to a trusted root as early as possible. + * + * Verify that chain and return it with flags for all issues found. + * + * Special cases: + * - EE == Rj -> return a one-element list containing it + * - EE, Ci1, ..., Ciq cannot be continued with a trusted root + * -> return that chain with NOT_TRUSTED set on Ciq + * + * Arguments: + * - [in] crt: the cert list EE, C1, ..., Cn + * - [in] trust_ca: the trusted list R1, ..., Rp + * - [in] ca_crl, profile: as in verify_with_profile() + * - [out] ver_chain, chain_len: the built and verified chain + * + * Return value: + * - non-zero if the chain could not be fully built and examined + * - 0 is the chain was successfully built and examined, + * even if it was found to be invalid + */ +static int x509_crt_verify_chain( + mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE], + size_t *chain_len ) +{ + uint32_t *flags; + mbedtls_x509_crt *child; + mbedtls_x509_crt *parent; + int parent_is_trusted = 0; + int child_is_trusted = 0; + size_t self_cnt = 0; + + child = crt; + *chain_len = 0; + + while( 1 ) { + /* Add certificate to the verification chain */ + ver_chain[*chain_len].crt = child; + flags = &ver_chain[*chain_len].flags; + ++*chain_len; + + /* Check time-validity (all certificates) */ + if( mbedtls_x509_time_is_past( &child->valid_to ) ) + *flags |= MBEDTLS_X509_BADCERT_EXPIRED; + + if( mbedtls_x509_time_is_future( &child->valid_from ) ) + *flags |= MBEDTLS_X509_BADCERT_FUTURE; + + /* Stop here for trusted roots (but not for trusted EE certs) */ + if( child_is_trusted ) + return( 0 ); + + /* Check signature algorithm: MD & PK algs */ + if( x509_profile_check_md_alg( profile, child->sig_md ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_MD; + + if( x509_profile_check_pk_alg( profile, child->sig_pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + /* Special case: EE certs that are locally trusted */ + if( *chain_len == 1 && + x509_crt_check_ee_locally_trusted( child, trust_ca ) == 0 ) + { + return( 0 ); + } + + /* Look for a parent in trusted CAs or up the chain */ + parent = x509_crt_find_parent( child, trust_ca, &parent_is_trusted, + *chain_len - 1, self_cnt ); + + /* No parent? We're done here */ + if( parent == NULL ) + { + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + return( 0 ); + } + + /* Count intermediate self-issued (not necessarily self-signed) certs. + * These can occur with some strategies for key rollover, see [SIRO], + * and should be excluded from max_pathlen checks. */ + if( *chain_len != 1 && + x509_name_cmp( &child->issuer, &child->subject ) == 0 ) + { + self_cnt++; + } + + /* path_cnt is 0 for the first intermediate CA, + * and if parent is trusted it's not an intermediate CA */ + if( ! parent_is_trusted && + *chain_len > MBEDTLS_X509_MAX_INTERMEDIATE_CA ) + { + /* return immediately to avoid overflow the chain array */ + return( MBEDTLS_ERR_X509_FATAL_ERROR ); + } + + /* if parent is trusted, the signature was checked by find_parent() */ + if( ! parent_is_trusted && x509_crt_check_signature( child, parent ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_NOT_TRUSTED; + + /* check size of signing key */ + if( x509_profile_check_key( profile, &parent->pk ) != 0 ) + *flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + +#if defined(MBEDTLS_X509_CRL_PARSE_C) + /* Check trusted CA's CRL for the given crt */ + *flags |= x509_crt_verifycrl( child, parent, ca_crl, profile ); +#else + (void) ca_crl; +#endif + + /* prepare for next iteration */ + child = parent; + parent = NULL; + child_is_trusted = parent_is_trusted; + } +} + +/* + * Check for CN match + */ +static int x509_crt_check_cn( const mbedtls_x509_buf *name, + const char *cn, size_t cn_len ) +{ + /* try exact match */ + if( name->len == cn_len && + x509_memcasecmp( cn, name->p, cn_len ) == 0 ) + { + return( 0 ); + } + + /* try wildcard match */ + if( x509_check_wildcard( cn, name ) == 0 ) + { + return( 0 ); + } + + return( -1 ); +} + +/* + * Verify the requested CN - only call this if cn is not NULL! + */ +static void x509_crt_verify_name( const mbedtls_x509_crt *crt, + const char *cn, + uint32_t *flags ) +{ + const mbedtls_x509_name *name; + const mbedtls_x509_sequence *cur; + size_t cn_len = strlen( cn ); + + if( crt->ext_types & MBEDTLS_X509_EXT_SUBJECT_ALT_NAME ) + { + for( cur = &crt->subject_alt_names; cur != NULL; cur = cur->next ) + { + if( x509_crt_check_cn( &cur->buf, cn, cn_len ) == 0 ) + break; + } + + if( cur == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } + else + { + for( name = &crt->subject; name != NULL; name = name->next ) + { + if( MBEDTLS_OID_CMP( MBEDTLS_OID_AT_CN, &name->oid ) == 0 && + x509_crt_check_cn( &name->val, cn, cn_len ) == 0 ) + { + break; + } + } + + if( name == NULL ) + *flags |= MBEDTLS_X509_BADCERT_CN_MISMATCH; + } +} + +/* + * Merge the flags for all certs in the chain, after calling callback + */ +static int x509_crt_merge_flags_with_cb( + uint32_t *flags, + x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE], + size_t chain_len, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + int ret; + size_t i; + uint32_t cur_flags; + + for( i = chain_len; i != 0; --i ) + { + cur_flags = ver_chain[i-1].flags; + + if( NULL != f_vrfy ) + if( ( ret = f_vrfy( p_vrfy, ver_chain[i-1].crt, (int) i-1, &cur_flags ) ) != 0 ) + return( ret ); + + *flags |= cur_flags; + } + + return( 0 ); +} + +/* + * Verify the certificate validity + */ +int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + return( mbedtls_x509_crt_verify_with_profile( crt, trust_ca, ca_crl, + &mbedtls_x509_crt_profile_default, cn, flags, f_vrfy, p_vrfy ) ); +} + +/* + * Verify the certificate validity, with profile + * + * This function: + * - checks the requested CN (if any) + * - checks the type and size of the EE cert's key, + * as that isn't done as part of chain building/verification currently + * - builds and verifies the chain + * - then calls the callback and merges the flags + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ) +{ + int ret; + mbedtls_pk_type_t pk_type; + x509_crt_verify_chain_item ver_chain[X509_MAX_VERIFY_CHAIN_SIZE]; + size_t chain_len; + uint32_t *ee_flags = &ver_chain[0].flags; + + *flags = 0; + memset( ver_chain, 0, sizeof( ver_chain ) ); + chain_len = 0; + + if( profile == NULL ) + { + ret = MBEDTLS_ERR_X509_BAD_INPUT_DATA; + goto exit; + } + + /* check name if requested */ + if( cn != NULL ) + x509_crt_verify_name( crt, cn, ee_flags ); + + /* Check the type and size of the key */ + pk_type = mbedtls_pk_get_type( &crt->pk ); + + if( x509_profile_check_pk_alg( profile, pk_type ) != 0 ) + *ee_flags |= MBEDTLS_X509_BADCERT_BAD_PK; + + if( x509_profile_check_key( profile, &crt->pk ) != 0 ) + *ee_flags |= MBEDTLS_X509_BADCERT_BAD_KEY; + + /* Check the chain */ + ret = x509_crt_verify_chain( crt, trust_ca, ca_crl, profile, + ver_chain, &chain_len ); + if( ret != 0 ) + goto exit; + + /* Build final flags, calling callback on the way if any */ + ret = x509_crt_merge_flags_with_cb( flags, + ver_chain, chain_len, f_vrfy, p_vrfy ); + +exit: + /* prevent misuse of the vrfy callback - VERIFY_FAILED would be ignored by + * the SSL module for authmode optional, but non-zero return from the + * callback means a fatal error so it shouldn't be ignored */ + if( ret == MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ) + ret = MBEDTLS_ERR_X509_FATAL_ERROR; + + if( ret != 0 ) + { + *flags = (uint32_t) -1; + return( ret ); + } + + if( *flags != 0 ) + return( MBEDTLS_ERR_X509_CERT_VERIFY_FAILED ); + + return( 0 ); +} + +/* + * Initialize a certificate chain + */ +void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ) +{ + memset( crt, 0, sizeof(mbedtls_x509_crt) ); +} + +/* + * Unallocate all certificate data + */ +void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ) +{ + mbedtls_x509_crt *cert_cur = crt; + mbedtls_x509_crt *cert_prv; + mbedtls_x509_name *name_cur; + mbedtls_x509_name *name_prv; + mbedtls_x509_sequence *seq_cur; + mbedtls_x509_sequence *seq_prv; + + if( crt == NULL ) + return; + + do + { + mbedtls_pk_free( &cert_cur->pk ); + +#if defined(MBEDTLS_X509_RSASSA_PSS_SUPPORT) + mbedtls_free( cert_cur->sig_opts ); +#endif + + name_cur = cert_cur->issuer.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + name_cur = cert_cur->subject.next; + while( name_cur != NULL ) + { + name_prv = name_cur; + name_cur = name_cur->next; + mbedtls_platform_zeroize( name_prv, sizeof( mbedtls_x509_name ) ); + mbedtls_free( name_prv ); + } + + seq_cur = cert_cur->ext_key_usage.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + seq_cur = cert_cur->subject_alt_names.next; + while( seq_cur != NULL ) + { + seq_prv = seq_cur; + seq_cur = seq_cur->next; + mbedtls_platform_zeroize( seq_prv, + sizeof( mbedtls_x509_sequence ) ); + mbedtls_free( seq_prv ); + } + + if( cert_cur->raw.p != NULL ) + { + mbedtls_platform_zeroize( cert_cur->raw.p, cert_cur->raw.len ); + mbedtls_free( cert_cur->raw.p ); + } + + cert_cur = cert_cur->next; + } + while( cert_cur != NULL ); + + cert_cur = crt; + do + { + cert_prv = cert_cur; + cert_cur = cert_cur->next; + + mbedtls_platform_zeroize( cert_prv, sizeof( mbedtls_x509_crt ) ); + if( cert_prv != crt ) + mbedtls_free( cert_prv ); + } + while( cert_cur != NULL ); +} + +#endif /* MBEDTLS_X509_CRT_PARSE_C */ diff --git a/common/mbedtls/x509_crt.h b/common/mbedtls/x509_crt.h new file mode 100644 index 000000000..4f7f7afb9 --- /dev/null +++ b/common/mbedtls/x509_crt.h @@ -0,0 +1,672 @@ +/** + * \file x509_crt.h + * + * \brief X.509 certificate parsing and writing + */ +/* + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ +#ifndef MBEDTLS_X509_CRT_H +#define MBEDTLS_X509_CRT_H + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#include "x509.h" +#include "x509_crl.h" + +/** + * \addtogroup x509_module + * \{ + */ + +#ifdef __cplusplus +extern "C" { +#endif + +/** + * \name Structures and functions for parsing and writing X.509 certificates + * \{ + */ + +/** + * Container for an X.509 certificate. The certificate may be chained. + */ +typedef struct mbedtls_x509_crt +{ + mbedtls_x509_buf raw; /**< The raw certificate data (DER). */ + mbedtls_x509_buf tbs; /**< The raw certificate body (DER). The part that is To Be Signed. */ + + int version; /**< The X.509 version. (1=v1, 2=v2, 3=v3) */ + mbedtls_x509_buf serial; /**< Unique id for certificate issued by a specific CA. */ + mbedtls_x509_buf sig_oid; /**< Signature algorithm, e.g. sha1RSA */ + + mbedtls_x509_buf issuer_raw; /**< The raw issuer data (DER). Used for quick comparison. */ + mbedtls_x509_buf subject_raw; /**< The raw subject data (DER). Used for quick comparison. */ + + mbedtls_x509_name issuer; /**< The parsed issuer data (named information object). */ + mbedtls_x509_name subject; /**< The parsed subject data (named information object). */ + + mbedtls_x509_time valid_from; /**< Start time of certificate validity. */ + mbedtls_x509_time valid_to; /**< End time of certificate validity. */ + + mbedtls_pk_context pk; /**< Container for the public key context. */ + + mbedtls_x509_buf issuer_id; /**< Optional X.509 v2/v3 issuer unique identifier. */ + mbedtls_x509_buf subject_id; /**< Optional X.509 v2/v3 subject unique identifier. */ + mbedtls_x509_buf v3_ext; /**< Optional X.509 v3 extensions. */ + mbedtls_x509_sequence subject_alt_names; /**< Optional list of Subject Alternative Names (Only dNSName supported). */ + + int ext_types; /**< Bit string containing detected and parsed extensions */ + int ca_istrue; /**< Optional Basic Constraint extension value: 1 if this certificate belongs to a CA, 0 otherwise. */ + int max_pathlen; /**< Optional Basic Constraint extension value: The maximum path length to the root certificate. Path length is 1 higher than RFC 5280 'meaning', so 1+ */ + + unsigned int key_usage; /**< Optional key usage extension value: See the values in x509.h */ + + mbedtls_x509_sequence ext_key_usage; /**< Optional list of extended key usage OIDs. */ + + unsigned char ns_cert_type; /**< Optional Netscape certificate type extension value: See the values in x509.h */ + + mbedtls_x509_buf sig; /**< Signature: hash of the tbs part signed with the private key. */ + mbedtls_md_type_t sig_md; /**< Internal representation of the MD algorithm of the signature algorithm, e.g. MBEDTLS_MD_SHA256 */ + mbedtls_pk_type_t sig_pk; /**< Internal representation of the Public Key algorithm of the signature algorithm, e.g. MBEDTLS_PK_RSA */ + void *sig_opts; /**< Signature options to be passed to mbedtls_pk_verify_ext(), e.g. for RSASSA-PSS */ + + struct mbedtls_x509_crt *next; /**< Next certificate in the CA-chain. */ +} +mbedtls_x509_crt; + +/** + * Build flag from an algorithm/curve identifier (pk, md, ecp) + * Since 0 is always XXX_NONE, ignore it. + */ +#define MBEDTLS_X509_ID_FLAG( id ) ( 1 << ( id - 1 ) ) + +/** + * Security profile for certificate verification. + * + * All lists are bitfields, built by ORing flags from MBEDTLS_X509_ID_FLAG(). + */ +typedef struct mbedtls_x509_crt_profile +{ + uint32_t allowed_mds; /**< MDs for signatures */ + uint32_t allowed_pks; /**< PK algs for signatures */ + uint32_t allowed_curves; /**< Elliptic curves for ECDSA */ + uint32_t rsa_min_bitlen; /**< Minimum size for RSA keys */ +} +mbedtls_x509_crt_profile; + +#define MBEDTLS_X509_CRT_VERSION_1 0 +#define MBEDTLS_X509_CRT_VERSION_2 1 +#define MBEDTLS_X509_CRT_VERSION_3 2 + +#define MBEDTLS_X509_RFC5280_MAX_SERIAL_LEN 32 +#define MBEDTLS_X509_RFC5280_UTC_TIME_LEN 15 + +#if !defined( MBEDTLS_X509_MAX_FILE_PATH_LEN ) +#define MBEDTLS_X509_MAX_FILE_PATH_LEN 512 +#endif + +/** + * Container for writing a certificate (CRT) + */ +typedef struct mbedtls_x509write_cert +{ + int version; + mbedtls_mpi serial; + mbedtls_pk_context *subject_key; + mbedtls_pk_context *issuer_key; + mbedtls_asn1_named_data *subject; + mbedtls_asn1_named_data *issuer; + mbedtls_md_type_t md_alg; + char not_before[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + char not_after[MBEDTLS_X509_RFC5280_UTC_TIME_LEN + 1]; + mbedtls_asn1_named_data *extensions; +} +mbedtls_x509write_cert; + +#if defined(MBEDTLS_X509_CRT_PARSE_C) +/** + * Default security profile. Should provide a good balance between security + * and compatibility with current deployments. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_default; + +/** + * Expected next default profile. Recommended for new deployments. + * Currently targets a 128-bit security level, except for RSA-2048. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_next; + +/** + * NSA Suite B profile. + */ +extern const mbedtls_x509_crt_profile mbedtls_x509_crt_profile_suiteb; + +/** + * \brief Parse a single DER formatted certificate and add it + * to the chained list. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate DER data + * \param buflen size of the buffer + * + * \return 0 if successful, or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_der( mbedtls_x509_crt *chain, const unsigned char *buf, + size_t buflen ); + +/** + * \brief Parse one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param buf buffer holding the certificate data in PEM or DER format + * \param buflen size of the buffer + * (including the terminating null byte for PEM data) + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse( mbedtls_x509_crt *chain, const unsigned char *buf, size_t buflen ); + +#if defined(MBEDTLS_FS_IO) +/** + * \brief Load one or more certificates and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path filename to read the certificates from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_file( mbedtls_x509_crt *chain, const char *path ); + +/** + * \brief Load one or more certificate files from a path and add them + * to the chained list. Parses permissively. If some + * certificates can be parsed, the result is the number + * of failed certificates it encountered. If none complete + * correctly, the first error is returned. + * + * \param chain points to the start of the chain + * \param path directory / folder to read the certificate files from + * + * \return 0 if all certificates parsed successfully, a positive number + * if partly successful or a specific X509 or PEM error code + */ +int mbedtls_x509_crt_parse_path( mbedtls_x509_crt *chain, const char *path ); +#endif /* MBEDTLS_FS_IO */ + +/** + * \brief Returns an informational string about the + * certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param crt The X509 certificate to represent + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_info( char *buf, size_t size, const char *prefix, + const mbedtls_x509_crt *crt ); + +/** + * \brief Returns an informational string about the + * verification status of a certificate. + * + * \param buf Buffer to write to + * \param size Maximum size of buffer + * \param prefix A line prefix + * \param flags Verification flags created by mbedtls_x509_crt_verify() + * + * \return The length of the string written (not including the + * terminated nul byte), or a negative error code. + */ +int mbedtls_x509_crt_verify_info( char *buf, size_t size, const char *prefix, + uint32_t flags ); + +/** + * \brief Verify the certificate signature + * + * The verify callback is a user-supplied callback that + * can clear / modify / add flags for a certificate. If set, + * the verification callback is called for each + * certificate in the chain (from the trust-ca down to the + * presented crt). The parameters for the callback are: + * (void *parameter, mbedtls_x509_crt *crt, int certificate_depth, + * int *flags). With the flags representing current flags for + * that specific certificate and the certificate depth from + * the bottom (Peer cert depth = 0). + * + * All flags left after returning from the callback + * are also returned to the application. The function should + * return 0 for anything (including invalid certificates) + * other than fatal error, as a non-zero return code + * immediately aborts the verification process. For fatal + * errors, a specific error code should be used (different + * from MBEDTLS_ERR_X509_CERT_VERIFY_FAILED which should not + * be returned at this point), or MBEDTLS_ERR_X509_FATAL_ERROR + * can be used if no better code is available. + * + * \note In case verification failed, the results can be displayed + * using \c mbedtls_x509_crt_verify_info() + * + * \note Same as \c mbedtls_x509_crt_verify_with_profile() with the + * default security profile. + * + * \note It is your responsibility to provide up-to-date CRLs for + * all trusted CAs. If no CRL is provided for the CA that was + * used to sign the certificate, CRL verification is skipped + * silently, that is *without* setting any flag. + * + * \note The \c trust_ca list can contain two types of certificates: + * (1) those of trusted root CAs, so that certificates + * chaining up to those CAs will be trusted, and (2) + * self-signed end-entity certificates to be trusted (for + * specific peers you know) - in that case, the self-signed + * certificate doesn't need to have the CA bit set. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs (see note above) + * \param ca_crl the list of CRLs for trusted CAs (see note above) + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * + * \return 0 (and flags set to 0) if the chain was verified and valid, + * MBEDTLS_ERR_X509_CERT_VERIFY_FAILED if the chain was verified + * but found to be invalid, in which case *flags will have one + * or more MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX + * flags set, or another error (and flags set to 0xffffffff) + * in case of a fatal error encountered during the + * verification process. + */ +int mbedtls_x509_crt_verify( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +/** + * \brief Verify the certificate signature according to profile + * + * \note Same as \c mbedtls_x509_crt_verify(), but with explicit + * security profile. + * + * \note The restrictions on keys (RSA minimum size, allowed curves + * for ECDSA) apply to all certificates: trusted root, + * intermediate CAs if any, and end entity certificate. + * + * \param crt a certificate (chain) to be verified + * \param trust_ca the list of trusted CAs + * \param ca_crl the list of CRLs for trusted CAs + * \param profile security profile for verification + * \param cn expected Common Name (can be set to + * NULL if the CN must not be verified) + * \param flags result of the verification + * \param f_vrfy verification function + * \param p_vrfy verification parameter + * + * \return 0 if successful or MBEDTLS_ERR_X509_CERT_VERIFY_FAILED + * in which case *flags will have one or more + * MBEDTLS_X509_BADCERT_XXX or MBEDTLS_X509_BADCRL_XXX flags + * set, + * or another error in case of a fatal error encountered + * during the verification process. + */ +int mbedtls_x509_crt_verify_with_profile( mbedtls_x509_crt *crt, + mbedtls_x509_crt *trust_ca, + mbedtls_x509_crl *ca_crl, + const mbedtls_x509_crt_profile *profile, + const char *cn, uint32_t *flags, + int (*f_vrfy)(void *, mbedtls_x509_crt *, int, uint32_t *), + void *p_vrfy ); + +#if defined(MBEDTLS_X509_CHECK_KEY_USAGE) +/** + * \brief Check usage of certificate against keyUsage extension. + * + * \param crt Leaf certificate used. + * \param usage Intended usage(s) (eg MBEDTLS_X509_KU_KEY_ENCIPHERMENT + * before using the certificate to perform an RSA key + * exchange). + * + * \note Except for decipherOnly and encipherOnly, a bit set in the + * usage argument means this bit MUST be set in the + * certificate. For decipherOnly and encipherOnly, it means + * that bit MAY be set. + * + * \return 0 is these uses of the certificate are allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if the keyUsage extension + * is present but does not match the usage argument. + * + * \note You should only call this function on leaf certificates, on + * (intermediate) CAs the keyUsage extension is automatically + * checked by \c mbedtls_x509_crt_verify(). + */ +int mbedtls_x509_crt_check_key_usage( const mbedtls_x509_crt *crt, + unsigned int usage ); +#endif /* MBEDTLS_X509_CHECK_KEY_USAGE) */ + +#if defined(MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE) +/** + * \brief Check usage of certificate against extendedKeyUsage. + * + * \param crt Leaf certificate used. + * \param usage_oid Intended usage (eg MBEDTLS_OID_SERVER_AUTH or + * MBEDTLS_OID_CLIENT_AUTH). + * \param usage_len Length of usage_oid (eg given by MBEDTLS_OID_SIZE()). + * + * \return 0 if this use of the certificate is allowed, + * MBEDTLS_ERR_X509_BAD_INPUT_DATA if not. + * + * \note Usually only makes sense on leaf certificates. + */ +int mbedtls_x509_crt_check_extended_key_usage( const mbedtls_x509_crt *crt, + const char *usage_oid, + size_t usage_len ); +#endif /* MBEDTLS_X509_CHECK_EXTENDED_KEY_USAGE */ + +#if defined(MBEDTLS_X509_CRL_PARSE_C) +/** + * \brief Verify the certificate revocation status + * + * \param crt a certificate to be verified + * \param crl the CRL to verify against + * + * \return 1 if the certificate is revoked, 0 otherwise + * + */ +int mbedtls_x509_crt_is_revoked( const mbedtls_x509_crt *crt, const mbedtls_x509_crl *crl ); +#endif /* MBEDTLS_X509_CRL_PARSE_C */ + +/** + * \brief Initialize a certificate (chain) + * + * \param crt Certificate chain to initialize + */ +void mbedtls_x509_crt_init( mbedtls_x509_crt *crt ); + +/** + * \brief Unallocate all certificate data + * + * \param crt Certificate chain to free + */ +void mbedtls_x509_crt_free( mbedtls_x509_crt *crt ); +#endif /* MBEDTLS_X509_CRT_PARSE_C */ + +/* \} name */ +/* \} addtogroup x509_module */ + +#if defined(MBEDTLS_X509_CRT_WRITE_C) +/** + * \brief Initialize a CRT writing context + * + * \param ctx CRT context to initialize + */ +void mbedtls_x509write_crt_init( mbedtls_x509write_cert *ctx ); + +/** + * \brief Set the verion for a Certificate + * Default: MBEDTLS_X509_CRT_VERSION_3 + * + * \param ctx CRT context to use + * \param version version to set (MBEDTLS_X509_CRT_VERSION_1, MBEDTLS_X509_CRT_VERSION_2 or + * MBEDTLS_X509_CRT_VERSION_3) + */ +void mbedtls_x509write_crt_set_version( mbedtls_x509write_cert *ctx, int version ); + +/** + * \brief Set the serial number for a Certificate. + * + * \param ctx CRT context to use + * \param serial serial number to set + * + * \return 0 if successful + */ +int mbedtls_x509write_crt_set_serial( mbedtls_x509write_cert *ctx, const mbedtls_mpi *serial ); + +/** + * \brief Set the validity period for a Certificate + * Timestamps should be in string format for UTC timezone + * i.e. "YYYYMMDDhhmmss" + * e.g. "20131231235959" for December 31st 2013 + * at 23:59:59 + * + * \param ctx CRT context to use + * \param not_before not_before timestamp + * \param not_after not_after timestamp + * + * \return 0 if timestamp was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_validity( mbedtls_x509write_cert *ctx, const char *not_before, + const char *not_after ); + +/** + * \brief Set the issuer name for a Certificate + * Issuer names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS CA" + * + * \param ctx CRT context to use + * \param issuer_name issuer name to set + * + * \return 0 if issuer name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_issuer_name( mbedtls_x509write_cert *ctx, + const char *issuer_name ); + +/** + * \brief Set the subject name for a Certificate + * Subject names should contain a comma-separated list + * of OID types and values: + * e.g. "C=UK,O=ARM,CN=mbed TLS Server 1" + * + * \param ctx CRT context to use + * \param subject_name subject name to set + * + * \return 0 if subject name was parsed successfully, or + * a specific error code + */ +int mbedtls_x509write_crt_set_subject_name( mbedtls_x509write_cert *ctx, + const char *subject_name ); + +/** + * \brief Set the subject public key for the certificate + * + * \param ctx CRT context to use + * \param key public key to include + */ +void mbedtls_x509write_crt_set_subject_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the issuer key used for signing the certificate + * + * \param ctx CRT context to use + * \param key private key to sign with + */ +void mbedtls_x509write_crt_set_issuer_key( mbedtls_x509write_cert *ctx, mbedtls_pk_context *key ); + +/** + * \brief Set the MD algorithm to use for the signature + * (e.g. MBEDTLS_MD_SHA1) + * + * \param ctx CRT context to use + * \param md_alg MD algorithm to use + */ +void mbedtls_x509write_crt_set_md_alg( mbedtls_x509write_cert *ctx, mbedtls_md_type_t md_alg ); + +/** + * \brief Generic function to add to or replace an extension in the + * CRT + * + * \param ctx CRT context to use + * \param oid OID of the extension + * \param oid_len length of the OID + * \param critical if the extension is critical (per the RFC's definition) + * \param val value of the extension OCTET STRING + * \param val_len length of the value data + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_extension( mbedtls_x509write_cert *ctx, + const char *oid, size_t oid_len, + int critical, + const unsigned char *val, size_t val_len ); + +/** + * \brief Set the basicConstraints extension for a CRT + * + * \param ctx CRT context to use + * \param is_ca is this a CA certificate + * \param max_pathlen maximum length of certificate chains below this + * certificate (only for CA certificates, -1 is + * inlimited) + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_basic_constraints( mbedtls_x509write_cert *ctx, + int is_ca, int max_pathlen ); + +#if defined(MBEDTLS_SHA1_C) +/** + * \brief Set the subjectKeyIdentifier extension for a CRT + * Requires that mbedtls_x509write_crt_set_subject_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_subject_key_identifier( mbedtls_x509write_cert *ctx ); + +/** + * \brief Set the authorityKeyIdentifier extension for a CRT + * Requires that mbedtls_x509write_crt_set_issuer_key() has been + * called before + * + * \param ctx CRT context to use + * + * \return 0 if successful, or a MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_authority_key_identifier( mbedtls_x509write_cert *ctx ); +#endif /* MBEDTLS_SHA1_C */ + +/** + * \brief Set the Key Usage Extension flags + * (e.g. MBEDTLS_X509_KU_DIGITAL_SIGNATURE | MBEDTLS_X509_KU_KEY_CERT_SIGN) + * + * \param ctx CRT context to use + * \param key_usage key usage flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_key_usage( mbedtls_x509write_cert *ctx, + unsigned int key_usage ); + +/** + * \brief Set the Netscape Cert Type flags + * (e.g. MBEDTLS_X509_NS_CERT_TYPE_SSL_CLIENT | MBEDTLS_X509_NS_CERT_TYPE_EMAIL) + * + * \param ctx CRT context to use + * \param ns_cert_type Netscape Cert Type flags to set + * + * \return 0 if successful, or MBEDTLS_ERR_X509_ALLOC_FAILED + */ +int mbedtls_x509write_crt_set_ns_cert_type( mbedtls_x509write_cert *ctx, + unsigned char ns_cert_type ); + +/** + * \brief Free the contents of a CRT write context + * + * \param ctx CRT context to free + */ +void mbedtls_x509write_crt_free( mbedtls_x509write_cert *ctx ); + +/** + * \brief Write a built up certificate to a X509 DER structure + * Note: data is written at the end of the buffer! Use the + * return value to determine where you should start + * using the buffer + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return length of data written if successful, or a specific + * error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_crt_der( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); + +#if defined(MBEDTLS_PEM_WRITE_C) +/** + * \brief Write a built up certificate to a X509 PEM string + * + * \param ctx certificate to write away + * \param buf buffer to write to + * \param size size of the buffer + * \param f_rng RNG function (for signature, see note) + * \param p_rng RNG parameter + * + * \return 0 if successful, or a specific error code + * + * \note f_rng may be NULL if RSA is used for signature and the + * signature is made offline (otherwise f_rng is desirable + * for countermeasures against timing attacks). + * ECDSA signatures always require a non-NULL f_rng. + */ +int mbedtls_x509write_crt_pem( mbedtls_x509write_cert *ctx, unsigned char *buf, size_t size, + int (*f_rng)(void *, unsigned char *, size_t), + void *p_rng ); +#endif /* MBEDTLS_PEM_WRITE_C */ +#endif /* MBEDTLS_X509_CRT_WRITE_C */ + +#ifdef __cplusplus +} +#endif + +#endif /* mbedtls_x509_crt.h */ diff --git a/common/polarssl/aes.c b/common/polarssl/aes.c deleted file mode 100644 index 36f735d4c..000000000 --- a/common/polarssl/aes.c +++ /dev/null @@ -1,1454 +0,0 @@ -/* - * FIPS-197 compliant AES implementation - * - * Copyright (C) 2006-2014, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * 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 AES block cipher was designed by Vincent Rijmen and Joan Daemen. - * - * http://csrc.nist.gov/encryption/aes/rijndael/Rijndael.pdf - * http://csrc.nist.gov/publications/fips/fips197/fips-197.pdf - */ - -#if !defined(POLARSSL_CONFIG_FILE) -#include "polarssl_config.h" -#else -#include POLARSSL_CONFIG_FILE -#endif - -#if defined(POLARSSL_AES_C) - -#include "aes.h" -#if defined(POLARSSL_PADLOCK_C) -#include "polarssl/padlock.h" -#endif -#if defined(POLARSSL_AESNI_C) -#include "polarssl/aesni.h" -#endif - -#if defined(POLARSSL_PLATFORM_C) -#include "polarssl/platform.h" -#else -#define polarssl_printf printf -#endif - -#if !defined(POLARSSL_AES_ALT) - -/* Implementation that should never be optimized out by the compiler */ -static void polarssl_zeroize( void *v, size_t n ) { - volatile unsigned char *p = v; while( n-- ) *p++ = 0; -} - -/* - * 32-bit integer manipulation macros (little endian) - */ -#ifndef GET_UINT32_LE -#define GET_UINT32_LE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] ) \ - | ( (uint32_t) (b)[(i) + 1] << 8 ) \ - | ( (uint32_t) (b)[(i) + 2] << 16 ) \ - | ( (uint32_t) (b)[(i) + 3] << 24 ); \ -} -#endif - -#ifndef PUT_UINT32_LE -#define PUT_UINT32_LE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) >> 24 ); \ -} -#endif - -#if defined(POLARSSL_PADLOCK_C) && \ - ( defined(POLARSSL_HAVE_X86) || defined(PADLOCK_ALIGN16) ) -static int aes_padlock_ace = -1; -#endif - -#if defined(POLARSSL_AES_ROM_TABLES) -/* - * Forward S-box - */ -static const unsigned char FSb[256] = -{ - 0x63, 0x7C, 0x77, 0x7B, 0xF2, 0x6B, 0x6F, 0xC5, - 0x30, 0x01, 0x67, 0x2B, 0xFE, 0xD7, 0xAB, 0x76, - 0xCA, 0x82, 0xC9, 0x7D, 0xFA, 0x59, 0x47, 0xF0, - 0xAD, 0xD4, 0xA2, 0xAF, 0x9C, 0xA4, 0x72, 0xC0, - 0xB7, 0xFD, 0x93, 0x26, 0x36, 0x3F, 0xF7, 0xCC, - 0x34, 0xA5, 0xE5, 0xF1, 0x71, 0xD8, 0x31, 0x15, - 0x04, 0xC7, 0x23, 0xC3, 0x18, 0x96, 0x05, 0x9A, - 0x07, 0x12, 0x80, 0xE2, 0xEB, 0x27, 0xB2, 0x75, - 0x09, 0x83, 0x2C, 0x1A, 0x1B, 0x6E, 0x5A, 0xA0, - 0x52, 0x3B, 0xD6, 0xB3, 0x29, 0xE3, 0x2F, 0x84, - 0x53, 0xD1, 0x00, 0xED, 0x20, 0xFC, 0xB1, 0x5B, - 0x6A, 0xCB, 0xBE, 0x39, 0x4A, 0x4C, 0x58, 0xCF, - 0xD0, 0xEF, 0xAA, 0xFB, 0x43, 0x4D, 0x33, 0x85, - 0x45, 0xF9, 0x02, 0x7F, 0x50, 0x3C, 0x9F, 0xA8, - 0x51, 0xA3, 0x40, 0x8F, 0x92, 0x9D, 0x38, 0xF5, - 0xBC, 0xB6, 0xDA, 0x21, 0x10, 0xFF, 0xF3, 0xD2, - 0xCD, 0x0C, 0x13, 0xEC, 0x5F, 0x97, 0x44, 0x17, - 0xC4, 0xA7, 0x7E, 0x3D, 0x64, 0x5D, 0x19, 0x73, - 0x60, 0x81, 0x4F, 0xDC, 0x22, 0x2A, 0x90, 0x88, - 0x46, 0xEE, 0xB8, 0x14, 0xDE, 0x5E, 0x0B, 0xDB, - 0xE0, 0x32, 0x3A, 0x0A, 0x49, 0x06, 0x24, 0x5C, - 0xC2, 0xD3, 0xAC, 0x62, 0x91, 0x95, 0xE4, 0x79, - 0xE7, 0xC8, 0x37, 0x6D, 0x8D, 0xD5, 0x4E, 0xA9, - 0x6C, 0x56, 0xF4, 0xEA, 0x65, 0x7A, 0xAE, 0x08, - 0xBA, 0x78, 0x25, 0x2E, 0x1C, 0xA6, 0xB4, 0xC6, - 0xE8, 0xDD, 0x74, 0x1F, 0x4B, 0xBD, 0x8B, 0x8A, - 0x70, 0x3E, 0xB5, 0x66, 0x48, 0x03, 0xF6, 0x0E, - 0x61, 0x35, 0x57, 0xB9, 0x86, 0xC1, 0x1D, 0x9E, - 0xE1, 0xF8, 0x98, 0x11, 0x69, 0xD9, 0x8E, 0x94, - 0x9B, 0x1E, 0x87, 0xE9, 0xCE, 0x55, 0x28, 0xDF, - 0x8C, 0xA1, 0x89, 0x0D, 0xBF, 0xE6, 0x42, 0x68, - 0x41, 0x99, 0x2D, 0x0F, 0xB0, 0x54, 0xBB, 0x16 -}; - -/* - * Forward tables - */ -#define FT \ -\ - V(A5,63,63,C6), V(84,7C,7C,F8), V(99,77,77,EE), V(8D,7B,7B,F6), \ - V(0D,F2,F2,FF), V(BD,6B,6B,D6), V(B1,6F,6F,DE), V(54,C5,C5,91), \ - V(50,30,30,60), V(03,01,01,02), V(A9,67,67,CE), V(7D,2B,2B,56), \ - V(19,FE,FE,E7), V(62,D7,D7,B5), V(E6,AB,AB,4D), V(9A,76,76,EC), \ - V(45,CA,CA,8F), V(9D,82,82,1F), V(40,C9,C9,89), V(87,7D,7D,FA), \ - V(15,FA,FA,EF), V(EB,59,59,B2), V(C9,47,47,8E), V(0B,F0,F0,FB), \ - V(EC,AD,AD,41), V(67,D4,D4,B3), V(FD,A2,A2,5F), V(EA,AF,AF,45), \ - V(BF,9C,9C,23), V(F7,A4,A4,53), V(96,72,72,E4), V(5B,C0,C0,9B), \ - V(C2,B7,B7,75), V(1C,FD,FD,E1), V(AE,93,93,3D), V(6A,26,26,4C), \ - V(5A,36,36,6C), V(41,3F,3F,7E), V(02,F7,F7,F5), V(4F,CC,CC,83), \ - V(5C,34,34,68), V(F4,A5,A5,51), V(34,E5,E5,D1), V(08,F1,F1,F9), \ - V(93,71,71,E2), V(73,D8,D8,AB), V(53,31,31,62), V(3F,15,15,2A), \ - V(0C,04,04,08), V(52,C7,C7,95), V(65,23,23,46), V(5E,C3,C3,9D), \ - V(28,18,18,30), V(A1,96,96,37), V(0F,05,05,0A), V(B5,9A,9A,2F), \ - V(09,07,07,0E), V(36,12,12,24), V(9B,80,80,1B), V(3D,E2,E2,DF), \ - V(26,EB,EB,CD), V(69,27,27,4E), V(CD,B2,B2,7F), V(9F,75,75,EA), \ - V(1B,09,09,12), V(9E,83,83,1D), V(74,2C,2C,58), V(2E,1A,1A,34), \ - V(2D,1B,1B,36), V(B2,6E,6E,DC), V(EE,5A,5A,B4), V(FB,A0,A0,5B), \ - V(F6,52,52,A4), V(4D,3B,3B,76), V(61,D6,D6,B7), V(CE,B3,B3,7D), \ - V(7B,29,29,52), V(3E,E3,E3,DD), V(71,2F,2F,5E), V(97,84,84,13), \ - V(F5,53,53,A6), V(68,D1,D1,B9), V(00,00,00,00), V(2C,ED,ED,C1), \ - V(60,20,20,40), V(1F,FC,FC,E3), V(C8,B1,B1,79), V(ED,5B,5B,B6), \ - V(BE,6A,6A,D4), V(46,CB,CB,8D), V(D9,BE,BE,67), V(4B,39,39,72), \ - V(DE,4A,4A,94), V(D4,4C,4C,98), V(E8,58,58,B0), V(4A,CF,CF,85), \ - V(6B,D0,D0,BB), V(2A,EF,EF,C5), V(E5,AA,AA,4F), V(16,FB,FB,ED), \ - V(C5,43,43,86), V(D7,4D,4D,9A), V(55,33,33,66), V(94,85,85,11), \ - V(CF,45,45,8A), V(10,F9,F9,E9), V(06,02,02,04), V(81,7F,7F,FE), \ - V(F0,50,50,A0), V(44,3C,3C,78), V(BA,9F,9F,25), V(E3,A8,A8,4B), \ - V(F3,51,51,A2), V(FE,A3,A3,5D), V(C0,40,40,80), V(8A,8F,8F,05), \ - V(AD,92,92,3F), V(BC,9D,9D,21), V(48,38,38,70), V(04,F5,F5,F1), \ - V(DF,BC,BC,63), V(C1,B6,B6,77), V(75,DA,DA,AF), V(63,21,21,42), \ - V(30,10,10,20), V(1A,FF,FF,E5), V(0E,F3,F3,FD), V(6D,D2,D2,BF), \ - V(4C,CD,CD,81), V(14,0C,0C,18), V(35,13,13,26), V(2F,EC,EC,C3), \ - V(E1,5F,5F,BE), V(A2,97,97,35), V(CC,44,44,88), V(39,17,17,2E), \ - V(57,C4,C4,93), V(F2,A7,A7,55), V(82,7E,7E,FC), V(47,3D,3D,7A), \ - V(AC,64,64,C8), V(E7,5D,5D,BA), V(2B,19,19,32), V(95,73,73,E6), \ - V(A0,60,60,C0), V(98,81,81,19), V(D1,4F,4F,9E), V(7F,DC,DC,A3), \ - V(66,22,22,44), V(7E,2A,2A,54), V(AB,90,90,3B), V(83,88,88,0B), \ - V(CA,46,46,8C), V(29,EE,EE,C7), V(D3,B8,B8,6B), V(3C,14,14,28), \ - V(79,DE,DE,A7), V(E2,5E,5E,BC), V(1D,0B,0B,16), V(76,DB,DB,AD), \ - V(3B,E0,E0,DB), V(56,32,32,64), V(4E,3A,3A,74), V(1E,0A,0A,14), \ - V(DB,49,49,92), V(0A,06,06,0C), V(6C,24,24,48), V(E4,5C,5C,B8), \ - V(5D,C2,C2,9F), V(6E,D3,D3,BD), V(EF,AC,AC,43), V(A6,62,62,C4), \ - V(A8,91,91,39), V(A4,95,95,31), V(37,E4,E4,D3), V(8B,79,79,F2), \ - V(32,E7,E7,D5), V(43,C8,C8,8B), V(59,37,37,6E), V(B7,6D,6D,DA), \ - V(8C,8D,8D,01), V(64,D5,D5,B1), V(D2,4E,4E,9C), V(E0,A9,A9,49), \ - V(B4,6C,6C,D8), V(FA,56,56,AC), V(07,F4,F4,F3), V(25,EA,EA,CF), \ - V(AF,65,65,CA), V(8E,7A,7A,F4), V(E9,AE,AE,47), V(18,08,08,10), \ - V(D5,BA,BA,6F), V(88,78,78,F0), V(6F,25,25,4A), V(72,2E,2E,5C), \ - V(24,1C,1C,38), V(F1,A6,A6,57), V(C7,B4,B4,73), V(51,C6,C6,97), \ - V(23,E8,E8,CB), V(7C,DD,DD,A1), V(9C,74,74,E8), V(21,1F,1F,3E), \ - V(DD,4B,4B,96), V(DC,BD,BD,61), V(86,8B,8B,0D), V(85,8A,8A,0F), \ - V(90,70,70,E0), V(42,3E,3E,7C), V(C4,B5,B5,71), V(AA,66,66,CC), \ - V(D8,48,48,90), V(05,03,03,06), V(01,F6,F6,F7), V(12,0E,0E,1C), \ - V(A3,61,61,C2), V(5F,35,35,6A), V(F9,57,57,AE), V(D0,B9,B9,69), \ - V(91,86,86,17), V(58,C1,C1,99), V(27,1D,1D,3A), V(B9,9E,9E,27), \ - V(38,E1,E1,D9), V(13,F8,F8,EB), V(B3,98,98,2B), V(33,11,11,22), \ - V(BB,69,69,D2), V(70,D9,D9,A9), V(89,8E,8E,07), V(A7,94,94,33), \ - V(B6,9B,9B,2D), V(22,1E,1E,3C), V(92,87,87,15), V(20,E9,E9,C9), \ - V(49,CE,CE,87), V(FF,55,55,AA), V(78,28,28,50), V(7A,DF,DF,A5), \ - V(8F,8C,8C,03), V(F8,A1,A1,59), V(80,89,89,09), V(17,0D,0D,1A), \ - V(DA,BF,BF,65), V(31,E6,E6,D7), V(C6,42,42,84), V(B8,68,68,D0), \ - V(C3,41,41,82), V(B0,99,99,29), V(77,2D,2D,5A), V(11,0F,0F,1E), \ - V(CB,B0,B0,7B), V(FC,54,54,A8), V(D6,BB,BB,6D), V(3A,16,16,2C) - -#define V(a,b,c,d) 0x##a##b##c##d -static const uint32_t FT0[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##b##c##d##a -static const uint32_t FT1[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##c##d##a##b -static const uint32_t FT2[256] = { FT }; -#undef V - -#define V(a,b,c,d) 0x##d##a##b##c -static const uint32_t FT3[256] = { FT }; -#undef V - -#undef FT - -/* - * Reverse S-box - */ -static const unsigned char RSb[256] = -{ - 0x52, 0x09, 0x6A, 0xD5, 0x30, 0x36, 0xA5, 0x38, - 0xBF, 0x40, 0xA3, 0x9E, 0x81, 0xF3, 0xD7, 0xFB, - 0x7C, 0xE3, 0x39, 0x82, 0x9B, 0x2F, 0xFF, 0x87, - 0x34, 0x8E, 0x43, 0x44, 0xC4, 0xDE, 0xE9, 0xCB, - 0x54, 0x7B, 0x94, 0x32, 0xA6, 0xC2, 0x23, 0x3D, - 0xEE, 0x4C, 0x95, 0x0B, 0x42, 0xFA, 0xC3, 0x4E, - 0x08, 0x2E, 0xA1, 0x66, 0x28, 0xD9, 0x24, 0xB2, - 0x76, 0x5B, 0xA2, 0x49, 0x6D, 0x8B, 0xD1, 0x25, - 0x72, 0xF8, 0xF6, 0x64, 0x86, 0x68, 0x98, 0x16, - 0xD4, 0xA4, 0x5C, 0xCC, 0x5D, 0x65, 0xB6, 0x92, - 0x6C, 0x70, 0x48, 0x50, 0xFD, 0xED, 0xB9, 0xDA, - 0x5E, 0x15, 0x46, 0x57, 0xA7, 0x8D, 0x9D, 0x84, - 0x90, 0xD8, 0xAB, 0x00, 0x8C, 0xBC, 0xD3, 0x0A, - 0xF7, 0xE4, 0x58, 0x05, 0xB8, 0xB3, 0x45, 0x06, - 0xD0, 0x2C, 0x1E, 0x8F, 0xCA, 0x3F, 0x0F, 0x02, - 0xC1, 0xAF, 0xBD, 0x03, 0x01, 0x13, 0x8A, 0x6B, - 0x3A, 0x91, 0x11, 0x41, 0x4F, 0x67, 0xDC, 0xEA, - 0x97, 0xF2, 0xCF, 0xCE, 0xF0, 0xB4, 0xE6, 0x73, - 0x96, 0xAC, 0x74, 0x22, 0xE7, 0xAD, 0x35, 0x85, - 0xE2, 0xF9, 0x37, 0xE8, 0x1C, 0x75, 0xDF, 0x6E, - 0x47, 0xF1, 0x1A, 0x71, 0x1D, 0x29, 0xC5, 0x89, - 0x6F, 0xB7, 0x62, 0x0E, 0xAA, 0x18, 0xBE, 0x1B, - 0xFC, 0x56, 0x3E, 0x4B, 0xC6, 0xD2, 0x79, 0x20, - 0x9A, 0xDB, 0xC0, 0xFE, 0x78, 0xCD, 0x5A, 0xF4, - 0x1F, 0xDD, 0xA8, 0x33, 0x88, 0x07, 0xC7, 0x31, - 0xB1, 0x12, 0x10, 0x59, 0x27, 0x80, 0xEC, 0x5F, - 0x60, 0x51, 0x7F, 0xA9, 0x19, 0xB5, 0x4A, 0x0D, - 0x2D, 0xE5, 0x7A, 0x9F, 0x93, 0xC9, 0x9C, 0xEF, - 0xA0, 0xE0, 0x3B, 0x4D, 0xAE, 0x2A, 0xF5, 0xB0, - 0xC8, 0xEB, 0xBB, 0x3C, 0x83, 0x53, 0x99, 0x61, - 0x17, 0x2B, 0x04, 0x7E, 0xBA, 0x77, 0xD6, 0x26, - 0xE1, 0x69, 0x14, 0x63, 0x55, 0x21, 0x0C, 0x7D -}; - -/* - * Reverse tables - */ -#define RT \ -\ - V(50,A7,F4,51), V(53,65,41,7E), V(C3,A4,17,1A), V(96,5E,27,3A), \ - V(CB,6B,AB,3B), V(F1,45,9D,1F), V(AB,58,FA,AC), V(93,03,E3,4B), \ - V(55,FA,30,20), V(F6,6D,76,AD), V(91,76,CC,88), V(25,4C,02,F5), \ - V(FC,D7,E5,4F), V(D7,CB,2A,C5), V(80,44,35,26), V(8F,A3,62,B5), \ - V(49,5A,B1,DE), V(67,1B,BA,25), V(98,0E,EA,45), V(E1,C0,FE,5D), \ - V(02,75,2F,C3), V(12,F0,4C,81), V(A3,97,46,8D), V(C6,F9,D3,6B), \ - V(E7,5F,8F,03), V(95,9C,92,15), V(EB,7A,6D,BF), V(DA,59,52,95), \ - V(2D,83,BE,D4), V(D3,21,74,58), V(29,69,E0,49), V(44,C8,C9,8E), \ - V(6A,89,C2,75), V(78,79,8E,F4), V(6B,3E,58,99), V(DD,71,B9,27), \ - V(B6,4F,E1,BE), V(17,AD,88,F0), V(66,AC,20,C9), V(B4,3A,CE,7D), \ - V(18,4A,DF,63), V(82,31,1A,E5), V(60,33,51,97), V(45,7F,53,62), \ - V(E0,77,64,B1), V(84,AE,6B,BB), V(1C,A0,81,FE), V(94,2B,08,F9), \ - V(58,68,48,70), V(19,FD,45,8F), V(87,6C,DE,94), V(B7,F8,7B,52), \ - V(23,D3,73,AB), V(E2,02,4B,72), V(57,8F,1F,E3), V(2A,AB,55,66), \ - V(07,28,EB,B2), V(03,C2,B5,2F), V(9A,7B,C5,86), V(A5,08,37,D3), \ - V(F2,87,28,30), V(B2,A5,BF,23), V(BA,6A,03,02), V(5C,82,16,ED), \ - V(2B,1C,CF,8A), V(92,B4,79,A7), V(F0,F2,07,F3), V(A1,E2,69,4E), \ - V(CD,F4,DA,65), V(D5,BE,05,06), V(1F,62,34,D1), V(8A,FE,A6,C4), \ - V(9D,53,2E,34), V(A0,55,F3,A2), V(32,E1,8A,05), V(75,EB,F6,A4), \ - V(39,EC,83,0B), V(AA,EF,60,40), V(06,9F,71,5E), V(51,10,6E,BD), \ - V(F9,8A,21,3E), V(3D,06,DD,96), V(AE,05,3E,DD), V(46,BD,E6,4D), \ - V(B5,8D,54,91), V(05,5D,C4,71), V(6F,D4,06,04), V(FF,15,50,60), \ - V(24,FB,98,19), V(97,E9,BD,D6), V(CC,43,40,89), V(77,9E,D9,67), \ - V(BD,42,E8,B0), V(88,8B,89,07), V(38,5B,19,E7), V(DB,EE,C8,79), \ - V(47,0A,7C,A1), V(E9,0F,42,7C), V(C9,1E,84,F8), V(00,00,00,00), \ - V(83,86,80,09), V(48,ED,2B,32), V(AC,70,11,1E), V(4E,72,5A,6C), \ - V(FB,FF,0E,FD), V(56,38,85,0F), V(1E,D5,AE,3D), V(27,39,2D,36), \ - V(64,D9,0F,0A), V(21,A6,5C,68), V(D1,54,5B,9B), V(3A,2E,36,24), \ - V(B1,67,0A,0C), V(0F,E7,57,93), V(D2,96,EE,B4), V(9E,91,9B,1B), \ - V(4F,C5,C0,80), V(A2,20,DC,61), V(69,4B,77,5A), V(16,1A,12,1C), \ - V(0A,BA,93,E2), V(E5,2A,A0,C0), V(43,E0,22,3C), V(1D,17,1B,12), \ - V(0B,0D,09,0E), V(AD,C7,8B,F2), V(B9,A8,B6,2D), V(C8,A9,1E,14), \ - V(85,19,F1,57), V(4C,07,75,AF), V(BB,DD,99,EE), V(FD,60,7F,A3), \ - V(9F,26,01,F7), V(BC,F5,72,5C), V(C5,3B,66,44), V(34,7E,FB,5B), \ - V(76,29,43,8B), V(DC,C6,23,CB), V(68,FC,ED,B6), V(63,F1,E4,B8), \ - V(CA,DC,31,D7), V(10,85,63,42), V(40,22,97,13), V(20,11,C6,84), \ - V(7D,24,4A,85), V(F8,3D,BB,D2), V(11,32,F9,AE), V(6D,A1,29,C7), \ - V(4B,2F,9E,1D), V(F3,30,B2,DC), V(EC,52,86,0D), V(D0,E3,C1,77), \ - V(6C,16,B3,2B), V(99,B9,70,A9), V(FA,48,94,11), V(22,64,E9,47), \ - V(C4,8C,FC,A8), V(1A,3F,F0,A0), V(D8,2C,7D,56), V(EF,90,33,22), \ - V(C7,4E,49,87), V(C1,D1,38,D9), V(FE,A2,CA,8C), V(36,0B,D4,98), \ - V(CF,81,F5,A6), V(28,DE,7A,A5), V(26,8E,B7,DA), V(A4,BF,AD,3F), \ - V(E4,9D,3A,2C), V(0D,92,78,50), V(9B,CC,5F,6A), V(62,46,7E,54), \ - V(C2,13,8D,F6), V(E8,B8,D8,90), V(5E,F7,39,2E), V(F5,AF,C3,82), \ - V(BE,80,5D,9F), V(7C,93,D0,69), V(A9,2D,D5,6F), V(B3,12,25,CF), \ - V(3B,99,AC,C8), V(A7,7D,18,10), V(6E,63,9C,E8), V(7B,BB,3B,DB), \ - V(09,78,26,CD), V(F4,18,59,6E), V(01,B7,9A,EC), V(A8,9A,4F,83), \ - V(65,6E,95,E6), V(7E,E6,FF,AA), V(08,CF,BC,21), V(E6,E8,15,EF), \ - V(D9,9B,E7,BA), V(CE,36,6F,4A), V(D4,09,9F,EA), V(D6,7C,B0,29), \ - V(AF,B2,A4,31), V(31,23,3F,2A), V(30,94,A5,C6), V(C0,66,A2,35), \ - V(37,BC,4E,74), V(A6,CA,82,FC), V(B0,D0,90,E0), V(15,D8,A7,33), \ - V(4A,98,04,F1), V(F7,DA,EC,41), V(0E,50,CD,7F), V(2F,F6,91,17), \ - V(8D,D6,4D,76), V(4D,B0,EF,43), V(54,4D,AA,CC), V(DF,04,96,E4), \ - V(E3,B5,D1,9E), V(1B,88,6A,4C), V(B8,1F,2C,C1), V(7F,51,65,46), \ - V(04,EA,5E,9D), V(5D,35,8C,01), V(73,74,87,FA), V(2E,41,0B,FB), \ - V(5A,1D,67,B3), V(52,D2,DB,92), V(33,56,10,E9), V(13,47,D6,6D), \ - V(8C,61,D7,9A), V(7A,0C,A1,37), V(8E,14,F8,59), V(89,3C,13,EB), \ - V(EE,27,A9,CE), V(35,C9,61,B7), V(ED,E5,1C,E1), V(3C,B1,47,7A), \ - V(59,DF,D2,9C), V(3F,73,F2,55), V(79,CE,14,18), V(BF,37,C7,73), \ - V(EA,CD,F7,53), V(5B,AA,FD,5F), V(14,6F,3D,DF), V(86,DB,44,78), \ - V(81,F3,AF,CA), V(3E,C4,68,B9), V(2C,34,24,38), V(5F,40,A3,C2), \ - V(72,C3,1D,16), V(0C,25,E2,BC), V(8B,49,3C,28), V(41,95,0D,FF), \ - V(71,01,A8,39), V(DE,B3,0C,08), V(9C,E4,B4,D8), V(90,C1,56,64), \ - V(61,84,CB,7B), V(70,B6,32,D5), V(74,5C,6C,48), V(42,57,B8,D0) - -#define V(a,b,c,d) 0x##a##b##c##d -static const uint32_t RT0[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##b##c##d##a -static const uint32_t RT1[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##c##d##a##b -static const uint32_t RT2[256] = { RT }; -#undef V - -#define V(a,b,c,d) 0x##d##a##b##c -static const uint32_t RT3[256] = { RT }; -#undef V - -#undef RT - -/* - * Round constants - */ -static const uint32_t RCON[10] = -{ - 0x00000001, 0x00000002, 0x00000004, 0x00000008, - 0x00000010, 0x00000020, 0x00000040, 0x00000080, - 0x0000001B, 0x00000036 -}; - -#else /* POLARSSL_AES_ROM_TABLES */ - -/* - * Forward S-box & tables - */ -static unsigned char FSb[256]; -static uint32_t FT0[256]; -static uint32_t FT1[256]; -static uint32_t FT2[256]; -static uint32_t FT3[256]; - -/* - * Reverse S-box & tables - */ -static unsigned char RSb[256]; -static uint32_t RT0[256]; -static uint32_t RT1[256]; -static uint32_t RT2[256]; -static uint32_t RT3[256]; - -/* - * Round constants - */ -static uint32_t RCON[10]; - -/* - * Tables generation code - */ -#define ROTL8(x) ( ( x << 8 ) & 0xFFFFFFFF ) | ( x >> 24 ) -#define XTIME(x) ( ( x << 1 ) ^ ( ( x & 0x80 ) ? 0x1B : 0x00 ) ) -#define MUL(x,y) ( ( x && y ) ? pow[(log[x]+log[y]) % 255] : 0 ) - -static int aes_init_done = 0; - -static void aes_gen_tables( void ) -{ - int i, x, y, z; - int pow[256]; - int log[256]; - - /* - * compute pow and log tables over GF(2^8) - */ - for( i = 0, x = 1; i < 256; i++ ) - { - pow[i] = x; - log[x] = i; - x = ( x ^ XTIME( x ) ) & 0xFF; - } - - /* - * calculate the round constants - */ - for( i = 0, x = 1; i < 10; i++ ) - { - RCON[i] = (uint32_t) x; - x = XTIME( x ) & 0xFF; - } - - /* - * generate the forward and reverse S-boxes - */ - FSb[0x00] = 0x63; - RSb[0x63] = 0x00; - - for( i = 1; i < 256; i++ ) - { - x = pow[255 - log[i]]; - - y = x; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; - x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; - x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; - x ^= y; y = ( ( y << 1 ) | ( y >> 7 ) ) & 0xFF; - x ^= y ^ 0x63; - - FSb[i] = (unsigned char) x; - RSb[x] = (unsigned char) i; - } - - /* - * generate the forward and reverse tables - */ - for( i = 0; i < 256; i++ ) - { - x = FSb[i]; - y = XTIME( x ) & 0xFF; - z = ( y ^ x ) & 0xFF; - - FT0[i] = ( (uint32_t) y ) ^ - ( (uint32_t) x << 8 ) ^ - ( (uint32_t) x << 16 ) ^ - ( (uint32_t) z << 24 ); - - FT1[i] = ROTL8( FT0[i] ); - FT2[i] = ROTL8( FT1[i] ); - FT3[i] = ROTL8( FT2[i] ); - - x = RSb[i]; - - RT0[i] = ( (uint32_t) MUL( 0x0E, x ) ) ^ - ( (uint32_t) MUL( 0x09, x ) << 8 ) ^ - ( (uint32_t) MUL( 0x0D, x ) << 16 ) ^ - ( (uint32_t) MUL( 0x0B, x ) << 24 ); - - RT1[i] = ROTL8( RT0[i] ); - RT2[i] = ROTL8( RT1[i] ); - RT3[i] = ROTL8( RT2[i] ); - } -} - -#endif /* POLARSSL_AES_ROM_TABLES */ - -void aes_init( aes_context *ctx ) -{ - memset( ctx, 0, sizeof( aes_context ) ); -} - -void aes_free( aes_context *ctx ) -{ - if( ctx == NULL ) - return; - - polarssl_zeroize( ctx, sizeof( aes_context ) ); -} - -/* - * AES key schedule (encryption) - */ -int aes_setkey_enc( aes_context *ctx, const unsigned char *key, - unsigned int keysize ) -{ - unsigned int i; - uint32_t *RK; - -#if !defined(POLARSSL_AES_ROM_TABLES) - if( aes_init_done == 0 ) - { - aes_gen_tables(); - aes_init_done = 1; - - } -#endif - - switch( keysize ) - { - case 128: ctx->nr = 10; break; - case 192: ctx->nr = 12; break; - case 256: ctx->nr = 14; break; - default : return( POLARSSL_ERR_AES_INVALID_KEY_LENGTH ); - } - -#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16) - if( aes_padlock_ace == -1 ) - aes_padlock_ace = padlock_supports( PADLOCK_ACE ); - - if( aes_padlock_ace ) - ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf ); - else -#endif - ctx->rk = RK = ctx->buf; - -#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64) - if( aesni_supports( POLARSSL_AESNI_AES ) ) - return( aesni_setkey_enc( (unsigned char *) ctx->rk, key, keysize ) ); -#endif - - for( i = 0; i < ( keysize >> 5 ); i++ ) - { - GET_UINT32_LE( RK[i], key, i << 2 ); - } - - switch( ctx->nr ) - { - case 10: - - for( i = 0; i < 10; i++, RK += 4 ) - { - RK[4] = RK[0] ^ RCON[i] ^ - ( (uint32_t) FSb[ ( RK[3] >> 8 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( RK[3] >> 16 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( RK[3] >> 24 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( RK[3] ) & 0xFF ] << 24 ); - - RK[5] = RK[1] ^ RK[4]; - RK[6] = RK[2] ^ RK[5]; - RK[7] = RK[3] ^ RK[6]; - } - break; - - case 12: - - for( i = 0; i < 8; i++, RK += 6 ) - { - RK[6] = RK[0] ^ RCON[i] ^ - ( (uint32_t) FSb[ ( RK[5] >> 8 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( RK[5] >> 16 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( RK[5] >> 24 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( RK[5] ) & 0xFF ] << 24 ); - - RK[7] = RK[1] ^ RK[6]; - RK[8] = RK[2] ^ RK[7]; - RK[9] = RK[3] ^ RK[8]; - RK[10] = RK[4] ^ RK[9]; - RK[11] = RK[5] ^ RK[10]; - } - break; - - case 14: - - for( i = 0; i < 7; i++, RK += 8 ) - { - RK[8] = RK[0] ^ RCON[i] ^ - ( (uint32_t) FSb[ ( RK[7] >> 8 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( RK[7] >> 16 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( RK[7] >> 24 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( RK[7] ) & 0xFF ] << 24 ); - - RK[9] = RK[1] ^ RK[8]; - RK[10] = RK[2] ^ RK[9]; - RK[11] = RK[3] ^ RK[10]; - - RK[12] = RK[4] ^ - ( (uint32_t) FSb[ ( RK[11] ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( RK[11] >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( RK[11] >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( RK[11] >> 24 ) & 0xFF ] << 24 ); - - RK[13] = RK[5] ^ RK[12]; - RK[14] = RK[6] ^ RK[13]; - RK[15] = RK[7] ^ RK[14]; - } - break; - } - - return( 0 ); -} - -/* - * AES key schedule (decryption) - */ -int aes_setkey_dec( aes_context *ctx, const unsigned char *key, - unsigned int keysize ) -{ - int i, j, ret; - aes_context cty; - uint32_t *RK; - uint32_t *SK; - - aes_init( &cty ); - -#if defined(POLARSSL_PADLOCK_C) && defined(PADLOCK_ALIGN16) - if( aes_padlock_ace == -1 ) - aes_padlock_ace = padlock_supports( PADLOCK_ACE ); - - if( aes_padlock_ace ) - ctx->rk = RK = PADLOCK_ALIGN16( ctx->buf ); - else -#endif - ctx->rk = RK = ctx->buf; - - /* Also checks keysize */ - if( ( ret = aes_setkey_enc( &cty, key, keysize ) ) != 0 ) - goto exit; - - ctx->nr = cty.nr; - -#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64) - if( aesni_supports( POLARSSL_AESNI_AES ) ) - { - aesni_inverse_key( (unsigned char *) ctx->rk, - (const unsigned char *) cty.rk, ctx->nr ); - goto exit; - } -#endif - - SK = cty.rk + cty.nr * 4; - - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - - for( i = ctx->nr - 1, SK -= 8; i > 0; i--, SK -= 8 ) - { - for( j = 0; j < 4; j++, SK++ ) - { - *RK++ = RT0[ FSb[ ( *SK ) & 0xFF ] ] ^ - RT1[ FSb[ ( *SK >> 8 ) & 0xFF ] ] ^ - RT2[ FSb[ ( *SK >> 16 ) & 0xFF ] ] ^ - RT3[ FSb[ ( *SK >> 24 ) & 0xFF ] ]; - } - } - - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - *RK++ = *SK++; - -exit: - aes_free( &cty ); - - return( ret ); -} - -#define AES_FROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - X0 = *RK++ ^ FT0[ ( Y0 ) & 0xFF ] ^ \ - FT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y3 >> 24 ) & 0xFF ]; \ - \ - X1 = *RK++ ^ FT0[ ( Y1 ) & 0xFF ] ^ \ - FT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y0 >> 24 ) & 0xFF ]; \ - \ - X2 = *RK++ ^ FT0[ ( Y2 ) & 0xFF ] ^ \ - FT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y1 >> 24 ) & 0xFF ]; \ - \ - X3 = *RK++ ^ FT0[ ( Y3 ) & 0xFF ] ^ \ - FT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ - FT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ - FT3[ ( Y2 >> 24 ) & 0xFF ]; \ -} - -#define AES_RROUND(X0,X1,X2,X3,Y0,Y1,Y2,Y3) \ -{ \ - X0 = *RK++ ^ RT0[ ( Y0 ) & 0xFF ] ^ \ - RT1[ ( Y3 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y2 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y1 >> 24 ) & 0xFF ]; \ - \ - X1 = *RK++ ^ RT0[ ( Y1 ) & 0xFF ] ^ \ - RT1[ ( Y0 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y3 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y2 >> 24 ) & 0xFF ]; \ - \ - X2 = *RK++ ^ RT0[ ( Y2 ) & 0xFF ] ^ \ - RT1[ ( Y1 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y0 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y3 >> 24 ) & 0xFF ]; \ - \ - X3 = *RK++ ^ RT0[ ( Y3 ) & 0xFF ] ^ \ - RT1[ ( Y2 >> 8 ) & 0xFF ] ^ \ - RT2[ ( Y1 >> 16 ) & 0xFF ] ^ \ - RT3[ ( Y0 >> 24 ) & 0xFF ]; \ -} - -/* - * AES-ECB block encryption/decryption - */ -int aes_crypt_ecb( aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ) -{ - int i; - uint32_t *RK, X0, X1, X2, X3, Y0, Y1, Y2, Y3; - -#if defined(POLARSSL_AESNI_C) && defined(POLARSSL_HAVE_X86_64) - if( aesni_supports( POLARSSL_AESNI_AES ) ) - return( aesni_crypt_ecb( ctx, mode, input, output ) ); -#endif - -#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86) - if( aes_padlock_ace ) - { - if( padlock_xcryptecb( ctx, mode, input, output ) == 0 ) - return( 0 ); - - // If padlock data misaligned, we just fall back to - // unaccelerated mode - // - } -#endif - - RK = ctx->rk; - - GET_UINT32_LE( X0, input, 0 ); X0 ^= *RK++; - GET_UINT32_LE( X1, input, 4 ); X1 ^= *RK++; - GET_UINT32_LE( X2, input, 8 ); X2 ^= *RK++; - GET_UINT32_LE( X3, input, 12 ); X3 ^= *RK++; - - if( mode == AES_DECRYPT ) - { - for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) - { - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - AES_RROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); - } - - AES_RROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - - X0 = *RK++ ^ \ - ( (uint32_t) RSb[ ( Y0 ) & 0xFF ] ) ^ - ( (uint32_t) RSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) RSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) RSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); - - X1 = *RK++ ^ \ - ( (uint32_t) RSb[ ( Y1 ) & 0xFF ] ) ^ - ( (uint32_t) RSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) RSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) RSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); - - X2 = *RK++ ^ \ - ( (uint32_t) RSb[ ( Y2 ) & 0xFF ] ) ^ - ( (uint32_t) RSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) RSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) RSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); - - X3 = *RK++ ^ \ - ( (uint32_t) RSb[ ( Y3 ) & 0xFF ] ) ^ - ( (uint32_t) RSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) RSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) RSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); - } - else /* AES_ENCRYPT */ - { - for( i = ( ctx->nr >> 1 ) - 1; i > 0; i-- ) - { - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - AES_FROUND( X0, X1, X2, X3, Y0, Y1, Y2, Y3 ); - } - - AES_FROUND( Y0, Y1, Y2, Y3, X0, X1, X2, X3 ); - - X0 = *RK++ ^ \ - ( (uint32_t) FSb[ ( Y0 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( Y1 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( Y2 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( Y3 >> 24 ) & 0xFF ] << 24 ); - - X1 = *RK++ ^ \ - ( (uint32_t) FSb[ ( Y1 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( Y2 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( Y3 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( Y0 >> 24 ) & 0xFF ] << 24 ); - - X2 = *RK++ ^ \ - ( (uint32_t) FSb[ ( Y2 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( Y3 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( Y0 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( Y1 >> 24 ) & 0xFF ] << 24 ); - - X3 = *RK++ ^ \ - ( (uint32_t) FSb[ ( Y3 ) & 0xFF ] ) ^ - ( (uint32_t) FSb[ ( Y0 >> 8 ) & 0xFF ] << 8 ) ^ - ( (uint32_t) FSb[ ( Y1 >> 16 ) & 0xFF ] << 16 ) ^ - ( (uint32_t) FSb[ ( Y2 >> 24 ) & 0xFF ] << 24 ); - } - - PUT_UINT32_LE( X0, output, 0 ); - PUT_UINT32_LE( X1, output, 4 ); - PUT_UINT32_LE( X2, output, 8 ); - PUT_UINT32_LE( X3, output, 12 ); - - return( 0 ); -} - -#if defined(POLARSSL_CIPHER_MODE_CBC) -/* - * AES-CBC buffer encryption/decryption - */ -int aes_crypt_cbc( aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[16]; - - if( length % 16 ) - return( POLARSSL_ERR_AES_INVALID_INPUT_LENGTH ); - -#if defined(POLARSSL_PADLOCK_C) && defined(POLARSSL_HAVE_X86) - if( aes_padlock_ace ) - { - if( padlock_xcryptcbc( ctx, mode, length, iv, input, output ) == 0 ) - return( 0 ); - - // If padlock data misaligned, we just fall back to - // unaccelerated mode - // - } -#endif - - if( mode == AES_DECRYPT ) - { - while( length > 0 ) - { - memcpy( temp, input, 16 ); - aes_crypt_ecb( ctx, mode, input, output ); - - for( i = 0; i < 16; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 16 ); - - input += 16; - output += 16; - length -= 16; - } - } - else - { - while( length > 0 ) - { - for( i = 0; i < 16; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - aes_crypt_ecb( ctx, mode, output, output ); - memcpy( iv, output, 16 ); - - input += 16; - output += 16; - length -= 16; - } - } - - return( 0 ); -} -#endif /* POLARSSL_CIPHER_MODE_CBC */ - -#if defined(POLARSSL_CIPHER_MODE_CFB) -/* - * AES-CFB128 buffer encryption/decryption - */ -int aes_crypt_cfb128( aes_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - int c; - size_t n = *iv_off; - - if( mode == AES_DECRYPT ) - { - while( length-- ) - { - if( n == 0 ) - aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); - - c = *input++; - *output++ = (unsigned char)( c ^ iv[n] ); - iv[n] = (unsigned char) c; - - n = ( n + 1 ) & 0x0F; - } - } - else - { - while( length-- ) - { - if( n == 0 ) - aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); - - iv[n] = *output++ = (unsigned char)( iv[n] ^ *input++ ); - - n = ( n + 1 ) & 0x0F; - } - } - - *iv_off = n; - - return( 0 ); -} - -/* - * AES-CFB8 buffer encryption/decryption - */ -#include -int aes_crypt_cfb8( aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ) -{ - unsigned char c; - unsigned char ov[17]; - - while( length-- ) - { - memcpy( ov, iv, 16 ); - aes_crypt_ecb( ctx, AES_ENCRYPT, iv, iv ); - - if( mode == AES_DECRYPT ) - ov[16] = *input; - - c = *output++ = (unsigned char)( iv[0] ^ *input++ ); - - if( mode == AES_ENCRYPT ) - ov[16] = c; - - memcpy( iv, ov + 1, 16 ); - } - - return( 0 ); -} -#endif /*POLARSSL_CIPHER_MODE_CFB */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) -/* - * AES-CTR buffer encryption/decryption - */ -int aes_crypt_ctr( aes_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[16], - unsigned char stream_block[16], - const unsigned char *input, - unsigned char *output ) -{ - int c, i; - size_t n = *nc_off; - - while( length-- ) - { - if( n == 0 ) { - aes_crypt_ecb( ctx, AES_ENCRYPT, nonce_counter, stream_block ); - - for( i = 16; i > 0; i-- ) - if( ++nonce_counter[i - 1] != 0 ) - break; - } - c = *input++; - *output++ = (unsigned char)( c ^ stream_block[n] ); - - n = ( n + 1 ) & 0x0F; - } - - *nc_off = n; - - return( 0 ); -} -#endif /* POLARSSL_CIPHER_MODE_CTR */ - -#endif /* !POLARSSL_AES_ALT */ - -#if defined(POLARSSL_SELF_TEST) - -#include - -/* - * AES test vectors from: - * - * http://csrc.nist.gov/archive/aes/rijndael/rijndael-vals.zip - */ -static const unsigned char aes_test_ecb_dec[3][16] = -{ - { 0x44, 0x41, 0x6A, 0xC2, 0xD1, 0xF5, 0x3C, 0x58, - 0x33, 0x03, 0x91, 0x7E, 0x6B, 0xE9, 0xEB, 0xE0 }, - { 0x48, 0xE3, 0x1E, 0x9E, 0x25, 0x67, 0x18, 0xF2, - 0x92, 0x29, 0x31, 0x9C, 0x19, 0xF1, 0x5B, 0xA4 }, - { 0x05, 0x8C, 0xCF, 0xFD, 0xBB, 0xCB, 0x38, 0x2D, - 0x1F, 0x6F, 0x56, 0x58, 0x5D, 0x8A, 0x4A, 0xDE } -}; - -static const unsigned char aes_test_ecb_enc[3][16] = -{ - { 0xC3, 0x4C, 0x05, 0x2C, 0xC0, 0xDA, 0x8D, 0x73, - 0x45, 0x1A, 0xFE, 0x5F, 0x03, 0xBE, 0x29, 0x7F }, - { 0xF3, 0xF6, 0x75, 0x2A, 0xE8, 0xD7, 0x83, 0x11, - 0x38, 0xF0, 0x41, 0x56, 0x06, 0x31, 0xB1, 0x14 }, - { 0x8B, 0x79, 0xEE, 0xCC, 0x93, 0xA0, 0xEE, 0x5D, - 0xFF, 0x30, 0xB4, 0xEA, 0x21, 0x63, 0x6D, 0xA4 } -}; - -#if defined(POLARSSL_CIPHER_MODE_CBC) -static const unsigned char aes_test_cbc_dec[3][16] = -{ - { 0xFA, 0xCA, 0x37, 0xE0, 0xB0, 0xC8, 0x53, 0x73, - 0xDF, 0x70, 0x6E, 0x73, 0xF7, 0xC9, 0xAF, 0x86 }, - { 0x5D, 0xF6, 0x78, 0xDD, 0x17, 0xBA, 0x4E, 0x75, - 0xB6, 0x17, 0x68, 0xC6, 0xAD, 0xEF, 0x7C, 0x7B }, - { 0x48, 0x04, 0xE1, 0x81, 0x8F, 0xE6, 0x29, 0x75, - 0x19, 0xA3, 0xE8, 0x8C, 0x57, 0x31, 0x04, 0x13 } -}; - -static const unsigned char aes_test_cbc_enc[3][16] = -{ - { 0x8A, 0x05, 0xFC, 0x5E, 0x09, 0x5A, 0xF4, 0x84, - 0x8A, 0x08, 0xD3, 0x28, 0xD3, 0x68, 0x8E, 0x3D }, - { 0x7B, 0xD9, 0x66, 0xD5, 0x3A, 0xD8, 0xC1, 0xBB, - 0x85, 0xD2, 0xAD, 0xFA, 0xE8, 0x7B, 0xB1, 0x04 }, - { 0xFE, 0x3C, 0x53, 0x65, 0x3E, 0x2F, 0x45, 0xB5, - 0x6F, 0xCD, 0x88, 0xB2, 0xCC, 0x89, 0x8F, 0xF0 } -}; -#endif /* POLARSSL_CIPHER_MODE_CBC */ - -#if defined(POLARSSL_CIPHER_MODE_CFB) -/* - * AES-CFB128 test vectors from: - * - * http://csrc.nist.gov/publications/nistpubs/800-38a/sp800-38a.pdf - */ -static const unsigned char aes_test_cfb128_key[3][32] = -{ - { 0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, - 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C }, - { 0x8E, 0x73, 0xB0, 0xF7, 0xDA, 0x0E, 0x64, 0x52, - 0xC8, 0x10, 0xF3, 0x2B, 0x80, 0x90, 0x79, 0xE5, - 0x62, 0xF8, 0xEA, 0xD2, 0x52, 0x2C, 0x6B, 0x7B }, - { 0x60, 0x3D, 0xEB, 0x10, 0x15, 0xCA, 0x71, 0xBE, - 0x2B, 0x73, 0xAE, 0xF0, 0x85, 0x7D, 0x77, 0x81, - 0x1F, 0x35, 0x2C, 0x07, 0x3B, 0x61, 0x08, 0xD7, - 0x2D, 0x98, 0x10, 0xA3, 0x09, 0x14, 0xDF, 0xF4 } -}; - -static const unsigned char aes_test_cfb128_iv[16] = -{ - 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F -}; - -static const unsigned char aes_test_cfb128_pt[64] = -{ - 0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, - 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, - 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, - 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, - 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, - 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, - 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, - 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10 -}; - -static const unsigned char aes_test_cfb128_ct[3][64] = -{ - { 0x3B, 0x3F, 0xD9, 0x2E, 0xB7, 0x2D, 0xAD, 0x20, - 0x33, 0x34, 0x49, 0xF8, 0xE8, 0x3C, 0xFB, 0x4A, - 0xC8, 0xA6, 0x45, 0x37, 0xA0, 0xB3, 0xA9, 0x3F, - 0xCD, 0xE3, 0xCD, 0xAD, 0x9F, 0x1C, 0xE5, 0x8B, - 0x26, 0x75, 0x1F, 0x67, 0xA3, 0xCB, 0xB1, 0x40, - 0xB1, 0x80, 0x8C, 0xF1, 0x87, 0xA4, 0xF4, 0xDF, - 0xC0, 0x4B, 0x05, 0x35, 0x7C, 0x5D, 0x1C, 0x0E, - 0xEA, 0xC4, 0xC6, 0x6F, 0x9F, 0xF7, 0xF2, 0xE6 }, - { 0xCD, 0xC8, 0x0D, 0x6F, 0xDD, 0xF1, 0x8C, 0xAB, - 0x34, 0xC2, 0x59, 0x09, 0xC9, 0x9A, 0x41, 0x74, - 0x67, 0xCE, 0x7F, 0x7F, 0x81, 0x17, 0x36, 0x21, - 0x96, 0x1A, 0x2B, 0x70, 0x17, 0x1D, 0x3D, 0x7A, - 0x2E, 0x1E, 0x8A, 0x1D, 0xD5, 0x9B, 0x88, 0xB1, - 0xC8, 0xE6, 0x0F, 0xED, 0x1E, 0xFA, 0xC4, 0xC9, - 0xC0, 0x5F, 0x9F, 0x9C, 0xA9, 0x83, 0x4F, 0xA0, - 0x42, 0xAE, 0x8F, 0xBA, 0x58, 0x4B, 0x09, 0xFF }, - { 0xDC, 0x7E, 0x84, 0xBF, 0xDA, 0x79, 0x16, 0x4B, - 0x7E, 0xCD, 0x84, 0x86, 0x98, 0x5D, 0x38, 0x60, - 0x39, 0xFF, 0xED, 0x14, 0x3B, 0x28, 0xB1, 0xC8, - 0x32, 0x11, 0x3C, 0x63, 0x31, 0xE5, 0x40, 0x7B, - 0xDF, 0x10, 0x13, 0x24, 0x15, 0xE5, 0x4B, 0x92, - 0xA1, 0x3E, 0xD0, 0xA8, 0x26, 0x7A, 0xE2, 0xF9, - 0x75, 0xA3, 0x85, 0x74, 0x1A, 0xB9, 0xCE, 0xF8, - 0x20, 0x31, 0x62, 0x3D, 0x55, 0xB1, 0xE4, 0x71 } -}; -#endif /* POLARSSL_CIPHER_MODE_CFB */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) -/* - * AES-CTR test vectors from: - * - * http://www.faqs.org/rfcs/rfc3686.html - */ - -static const unsigned char aes_test_ctr_key[3][16] = -{ - { 0xAE, 0x68, 0x52, 0xF8, 0x12, 0x10, 0x67, 0xCC, - 0x4B, 0xF7, 0xA5, 0x76, 0x55, 0x77, 0xF3, 0x9E }, - { 0x7E, 0x24, 0x06, 0x78, 0x17, 0xFA, 0xE0, 0xD7, - 0x43, 0xD6, 0xCE, 0x1F, 0x32, 0x53, 0x91, 0x63 }, - { 0x76, 0x91, 0xBE, 0x03, 0x5E, 0x50, 0x20, 0xA8, - 0xAC, 0x6E, 0x61, 0x85, 0x29, 0xF9, 0xA0, 0xDC } -}; - -static const unsigned char aes_test_ctr_nonce_counter[3][16] = -{ - { 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01 }, - { 0x00, 0x6C, 0xB6, 0xDB, 0xC0, 0x54, 0x3B, 0x59, - 0xDA, 0x48, 0xD9, 0x0B, 0x00, 0x00, 0x00, 0x01 }, - { 0x00, 0xE0, 0x01, 0x7B, 0x27, 0x77, 0x7F, 0x3F, - 0x4A, 0x17, 0x86, 0xF0, 0x00, 0x00, 0x00, 0x01 } -}; - -static const unsigned char aes_test_ctr_pt[3][48] = -{ - { 0x53, 0x69, 0x6E, 0x67, 0x6C, 0x65, 0x20, 0x62, - 0x6C, 0x6F, 0x63, 0x6B, 0x20, 0x6D, 0x73, 0x67 }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F }, - - { 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, - 0x08, 0x09, 0x0A, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F, - 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, - 0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, - 0x20, 0x21, 0x22, 0x23 } -}; - -static const unsigned char aes_test_ctr_ct[3][48] = -{ - { 0xE4, 0x09, 0x5D, 0x4F, 0xB7, 0xA7, 0xB3, 0x79, - 0x2D, 0x61, 0x75, 0xA3, 0x26, 0x13, 0x11, 0xB8 }, - { 0x51, 0x04, 0xA1, 0x06, 0x16, 0x8A, 0x72, 0xD9, - 0x79, 0x0D, 0x41, 0xEE, 0x8E, 0xDA, 0xD3, 0x88, - 0xEB, 0x2E, 0x1E, 0xFC, 0x46, 0xDA, 0x57, 0xC8, - 0xFC, 0xE6, 0x30, 0xDF, 0x91, 0x41, 0xBE, 0x28 }, - { 0xC1, 0xCF, 0x48, 0xA8, 0x9F, 0x2F, 0xFD, 0xD9, - 0xCF, 0x46, 0x52, 0xE9, 0xEF, 0xDB, 0x72, 0xD7, - 0x45, 0x40, 0xA4, 0x2B, 0xDE, 0x6D, 0x78, 0x36, - 0xD5, 0x9A, 0x5C, 0xEA, 0xAE, 0xF3, 0x10, 0x53, - 0x25, 0xB2, 0x07, 0x2F } -}; - -static const int aes_test_ctr_len[3] = - { 16, 32, 36 }; -#endif /* POLARSSL_CIPHER_MODE_CTR */ - -/* - * Checkup routine - */ -int aes_self_test( int verbose ) -{ - int ret = 0, i, j, u, v; - unsigned char key[32]; - unsigned char buf[64]; - unsigned char iv[16]; -#if defined(POLARSSL_CIPHER_MODE_CBC) - unsigned char prv[16]; -#endif -#if defined(POLARSSL_CIPHER_MODE_CTR) || defined(POLARSSL_CIPHER_MODE_CFB) - size_t offset; -#endif -#if defined(POLARSSL_CIPHER_MODE_CTR) - int len; - unsigned char nonce_counter[16]; - unsigned char stream_block[16]; -#endif - aes_context ctx; - - memset( key, 0, 32 ); - aes_init( &ctx ); - - /* - * ECB mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - polarssl_printf( " AES-ECB-%3d (%s): ", 128 + u * 64, - ( v == AES_DECRYPT ) ? "dec" : "enc" ); - - memset( buf, 0, 16 ); - - if( v == AES_DECRYPT ) - { - aes_setkey_dec( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - aes_crypt_ecb( &ctx, v, buf, buf ); - - if( memcmp( buf, aes_test_ecb_dec[u], 16 ) != 0 ) - { - if( verbose != 0 ) - polarssl_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - else - { - aes_setkey_enc( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - aes_crypt_ecb( &ctx, v, buf, buf ); - - if( memcmp( buf, aes_test_ecb_enc[u], 16 ) != 0 ) - { - if( verbose != 0 ) - polarssl_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - - if( verbose != 0 ) - polarssl_printf( "passed\n" ); - } - - if( verbose != 0 ) - polarssl_printf( "\n" ); - -#if defined(POLARSSL_CIPHER_MODE_CBC) - /* - * CBC mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - polarssl_printf( " AES-CBC-%3d (%s): ", 128 + u * 64, - ( v == AES_DECRYPT ) ? "dec" : "enc" ); - - memset( iv , 0, 16 ); - memset( prv, 0, 16 ); - memset( buf, 0, 16 ); - - if( v == AES_DECRYPT ) - { - aes_setkey_dec( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); - - if( memcmp( buf, aes_test_cbc_dec[u], 16 ) != 0 ) - { - if( verbose != 0 ) - polarssl_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - else - { - aes_setkey_enc( &ctx, key, 128 + u * 64 ); - - for( j = 0; j < 10000; j++ ) - { - unsigned char tmp[16]; - - aes_crypt_cbc( &ctx, v, 16, iv, buf, buf ); - - memcpy( tmp, prv, 16 ); - memcpy( prv, buf, 16 ); - memcpy( buf, tmp, 16 ); - } - - if( memcmp( prv, aes_test_cbc_enc[u], 16 ) != 0 ) - { - if( verbose != 0 ) - polarssl_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - - if( verbose != 0 ) - polarssl_printf( "passed\n" ); - } - - if( verbose != 0 ) - polarssl_printf( "\n" ); -#endif /* POLARSSL_CIPHER_MODE_CBC */ - -#if defined(POLARSSL_CIPHER_MODE_CFB) - /* - * CFB128 mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - polarssl_printf( " AES-CFB128-%3d (%s): ", 128 + u * 64, - ( v == AES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( iv, aes_test_cfb128_iv, 16 ); - memcpy( key, aes_test_cfb128_key[u], 16 + u * 8 ); - - offset = 0; - aes_setkey_enc( &ctx, key, 128 + u * 64 ); - - if( v == AES_DECRYPT ) - { - memcpy( buf, aes_test_cfb128_ct[u], 64 ); - aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); - - if( memcmp( buf, aes_test_cfb128_pt, 64 ) != 0 ) - { - if( verbose != 0 ) - polarssl_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - else - { - memcpy( buf, aes_test_cfb128_pt, 64 ); - aes_crypt_cfb128( &ctx, v, 64, &offset, iv, buf, buf ); - - if( memcmp( buf, aes_test_cfb128_ct[u], 64 ) != 0 ) - { - if( verbose != 0 ) - polarssl_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - - if( verbose != 0 ) - polarssl_printf( "passed\n" ); - } - - if( verbose != 0 ) - polarssl_printf( "\n" ); -#endif /* POLARSSL_CIPHER_MODE_CFB */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) - /* - * CTR mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - polarssl_printf( " AES-CTR-128 (%s): ", - ( v == AES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( nonce_counter, aes_test_ctr_nonce_counter[u], 16 ); - memcpy( key, aes_test_ctr_key[u], 16 ); - - offset = 0; - aes_setkey_enc( &ctx, key, 128 ); - - if( v == AES_DECRYPT ) - { - len = aes_test_ctr_len[u]; - memcpy( buf, aes_test_ctr_ct[u], len ); - - aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, - buf, buf ); - - if( memcmp( buf, aes_test_ctr_pt[u], len ) != 0 ) - { - if( verbose != 0 ) - polarssl_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - else - { - len = aes_test_ctr_len[u]; - memcpy( buf, aes_test_ctr_pt[u], len ); - - aes_crypt_ctr( &ctx, len, &offset, nonce_counter, stream_block, - buf, buf ); - - if( memcmp( buf, aes_test_ctr_ct[u], len ) != 0 ) - { - if( verbose != 0 ) - polarssl_printf( "failed\n" ); - - ret = 1; - goto exit; - } - } - - if( verbose != 0 ) - polarssl_printf( "passed\n" ); - } - - if( verbose != 0 ) - polarssl_printf( "\n" ); -#endif /* POLARSSL_CIPHER_MODE_CTR */ - - ret = 0; - -exit: - aes_free( &ctx ); - - return( ret ); -} - -#endif /* POLARSSL_SELF_TEST */ - -#endif /* POLARSSL_AES_C */ diff --git a/common/polarssl/aes.h b/common/polarssl/aes.h deleted file mode 100644 index 299cb4cdf..000000000 --- a/common/polarssl/aes.h +++ /dev/null @@ -1,256 +0,0 @@ -/** - * \file aes.h - * - * \brief AES block cipher - * - * Copyright (C) 2006-2014, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_AES_H -#define POLARSSL_AES_H - -#if !defined(POLARSSL_CONFIG_FILE) -#include "polarssl_config.h" -#else -#include POLARSSL_CONFIG_FILE -#endif - -#include - -#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) -#include -typedef UINT32 uint32_t; -#else -#include -#endif - -/* padlock.c and aesni.c rely on these values! */ -#define AES_ENCRYPT 1 -#define AES_DECRYPT 0 - -#define POLARSSL_ERR_AES_INVALID_KEY_LENGTH -0x0020 /**< Invalid key length. */ -#define POLARSSL_ERR_AES_INVALID_INPUT_LENGTH -0x0022 /**< Invalid data input length. */ - -#if !defined(POLARSSL_AES_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief AES context structure - * - * \note buf is able to hold 32 extra bytes, which can be used: - * - for alignment purposes if VIA padlock is used, and/or - * - to simplify key expansion in the 256-bit case by - * generating an extra round key - */ -typedef struct -{ - int nr; /*!< number of rounds */ - uint32_t *rk; /*!< AES round keys */ - uint32_t buf[68]; /*!< unaligned data */ -} -aes_context; - -/** - * \brief Initialize AES context - * - * \param ctx AES context to be initialized - */ -void aes_init( aes_context *ctx ); - -/** - * \brief Clear AES context - * - * \param ctx AES context to be cleared - */ -void aes_free( aes_context *ctx ); - -/** - * \brief AES key schedule (encryption) - * - * \param ctx AES context to be initialized - * \param key encryption key - * \param keysize must be 128, 192 or 256 - * - * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH - */ -int aes_setkey_enc( aes_context *ctx, const unsigned char *key, - unsigned int keysize ); - -/** - * \brief AES key schedule (decryption) - * - * \param ctx AES context to be initialized - * \param key decryption key - * \param keysize must be 128, 192 or 256 - * - * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_KEY_LENGTH - */ -int aes_setkey_dec( aes_context *ctx, const unsigned char *key, - unsigned int keysize ); - -/** - * \brief AES-ECB block encryption/decryption - * - * \param ctx AES context - * \param mode AES_ENCRYPT or AES_DECRYPT - * \param input 16-byte input block - * \param output 16-byte output block - * - * \return 0 if successful - */ -int aes_crypt_ecb( aes_context *ctx, - int mode, - const unsigned char input[16], - unsigned char output[16] ); -#if defined(POLARSSL_CIPHER_MODE_CBC) -/** - * \brief AES-CBC buffer encryption/decryption - * Length should be a multiple of the block - * size (16 bytes) - * - * \param ctx AES context - * \param mode AES_ENCRYPT or AES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful, or POLARSSL_ERR_AES_INVALID_INPUT_LENGTH - */ -int aes_crypt_cbc( aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); -#endif /* POLARSSL_CIPHER_MODE_CBC */ - -#if defined(POLARSSL_CIPHER_MODE_CFB) -/** - * \brief AES-CFB128 buffer encryption/decryption. - * - * Note: Due to the nature of CFB you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. - * - * \param ctx AES context - * \param mode AES_ENCRYPT or AES_DECRYPT - * \param length length of the input data - * \param iv_off offset in IV (updated after use) - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful - */ -int aes_crypt_cfb128( aes_context *ctx, - int mode, - size_t length, - size_t *iv_off, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); - -/** - * \brief AES-CFB8 buffer encryption/decryption. - * - * Note: Due to the nature of CFB you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. - * - * \param ctx AES context - * \param mode AES_ENCRYPT or AES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful - */ -int aes_crypt_cfb8( aes_context *ctx, - int mode, - size_t length, - unsigned char iv[16], - const unsigned char *input, - unsigned char *output ); -#endif /*POLARSSL_CIPHER_MODE_CFB */ - -#if defined(POLARSSL_CIPHER_MODE_CTR) -/** - * \brief AES-CTR buffer encryption/decryption - * - * Warning: You have to keep the maximum use of your counter in mind! - * - * Note: Due to the nature of CTR you should use the same key schedule for - * both encryption and decryption. So a context initialized with - * aes_setkey_enc() for both AES_ENCRYPT and AES_DECRYPT. - * - * \param ctx AES context - * \param length The length of the data - * \param nc_off The offset in the current stream_block (for resuming - * within current cipher stream). The offset pointer to - * should be 0 at the start of a stream. - * \param nonce_counter The 128-bit nonce and counter. - * \param stream_block The saved stream-block for resuming. Is overwritten - * by the function. - * \param input The input data stream - * \param output The output data stream - * - * \return 0 if successful - */ -int aes_crypt_ctr( aes_context *ctx, - size_t length, - size_t *nc_off, - unsigned char nonce_counter[16], - unsigned char stream_block[16], - const unsigned char *input, - unsigned char *output ); -#endif /* POLARSSL_CIPHER_MODE_CTR */ - -#ifdef __cplusplus -} -#endif - -#else /* POLARSSL_AES_ALT */ -#include "aes_alt.h" -#endif /* POLARSSL_AES_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int aes_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* aes.h */ diff --git a/common/polarssl/aes_cmac128.c b/common/polarssl/aes_cmac128.c deleted file mode 100644 index 595f89b8d..000000000 --- a/common/polarssl/aes_cmac128.c +++ /dev/null @@ -1,322 +0,0 @@ -/* - * AES-CMAC from NIST Special Publication 800-38B Recommendation for block cipher modes of operation: The CMAC mode for authentication. - * - * Copyright (C) 2006-2014, Brainspark B.V. - * Copyright (C) 2014, Anargyros Plemenos - * Tests added Merkok, 2018 - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * 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. - * - * Reference : https://polarssl.org/discussions/generic/authentication-token - * NIST Special Publication 800-38B Recommendation for block cipher modes of operation: The CMAC mode for authentication. - * Tests here: - * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf -*/ - -#include "polarssl/aes_cmac128.h" -#include - -#define MIN(a,b) ((a)<(b)?(a):(b)) -#define _MSB(x) (((x)[0] & 0x80)?1:0) - -#if !defined(POLARSSL_CONFIG_FILE) -#include "polarssl_config.h" -#else -#include POLARSSL_CONFIG_FILE -#endif - -#if defined(POLARSSL_AES_C) -#include "aes.h" -#endif - -#if defined(POLARSSL_PLATFORM_C) -#include "polarssl/platform.h" -#else -#define polarssl_printf printf -#endif - - -/** - * zero a structure - */ -#define ZERO_STRUCT(x) memset((char *)&(x), 0, sizeof(x)) - -/** - * zero a structure given a pointer to the structure - */ -#define ZERO_STRUCTP(x) do{ if((x) != NULL) memset((char *)(x), 0, sizeof(*(x)));} while(0) - - -/* For CMAC Calculation */ -static unsigned char const_Rb[16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x87 -}; -static unsigned char const_Zero[16] = { - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 -}; - -static inline void aes_cmac_128_left_shift_1(const uint8_t in[16], uint8_t out[16]) -{ - uint8_t overflow = 0; - int8_t i; - - for (i = 15; i >= 0; i--) { - out[i] = in[i] << 1; - out[i] |= overflow; - overflow = _MSB(&in[i]); - } -} - -static inline void aes_cmac_128_xor(const uint8_t in1[16], const uint8_t in2[16], - uint8_t out[16]) -{ - uint8_t i; - - for (i = 0; i < 16; i++) { - out[i] = in1[i] ^ in2[i]; - } -} - -/* - * AES-CMAC-128 context setup - */ -void aes_cmac128_starts(aes_cmac128_context *ctx, const uint8_t K[16]) -{ - uint8_t L[16]; - - /* Zero struct of aes_context */ - ZERO_STRUCTP(ctx); - /* Initialize aes_context */ - aes_setkey_enc(&ctx->aes_key, K, 128); - - /* step 1 - generate subkeys k1 and k2 */ - aes_crypt_ecb(&ctx->aes_key, AES_ENCRYPT, const_Zero, L); - - if (_MSB(L) == 0) { - aes_cmac_128_left_shift_1(L, ctx->K1); - } else { - uint8_t tmp_block[16]; - - aes_cmac_128_left_shift_1(L, tmp_block); - aes_cmac_128_xor(tmp_block, const_Rb, ctx->K1); - ZERO_STRUCT(tmp_block); - } - - if (_MSB(ctx->K1) == 0) { - aes_cmac_128_left_shift_1(ctx->K1, ctx->K2); - } else { - uint8_t tmp_block[16]; - - aes_cmac_128_left_shift_1(ctx->K1, tmp_block); - aes_cmac_128_xor(tmp_block, const_Rb, ctx->K2); - ZERO_STRUCT(tmp_block); - } - - ZERO_STRUCT(L); -} - -/* - * AES-CMAC-128 process message - */ -void aes_cmac128_update(aes_cmac128_context *ctx, const uint8_t *_msg, size_t _msg_len) -{ - uint8_t tmp_block[16]; - uint8_t Y[16]; - const uint8_t *msg = _msg; - size_t msg_len = _msg_len; - - /* - * copy the remembered last block - */ - ZERO_STRUCT(tmp_block); - if (ctx->last_len) { - memcpy(tmp_block, ctx->last, ctx->last_len); - } - - /* - * check if we expand the block - */ - if (ctx->last_len < 16) { - size_t len = MIN(16 - ctx->last_len, msg_len); - - memcpy(&tmp_block[ctx->last_len], msg, len); - memcpy(ctx->last, tmp_block, 16); - msg += len; - msg_len -= len; - ctx->last_len += len; - } - - if (msg_len == 0) { - /* if it is still the last block, we are done */ - ZERO_STRUCT(tmp_block); - return; - } - - /* - * It is not the last block anymore - */ - ZERO_STRUCT(ctx->last); - ctx->last_len = 0; - - /* - * now checksum everything but the last block - */ - aes_cmac_128_xor(ctx->X, tmp_block, Y); - aes_crypt_ecb(&ctx->aes_key, AES_ENCRYPT, Y, ctx->X); - - while (msg_len > 16) { - memcpy(tmp_block, msg, 16); - msg += 16; - msg_len -= 16; - - aes_cmac_128_xor(ctx->X, tmp_block, Y); - aes_crypt_ecb(&ctx->aes_key, AES_ENCRYPT, Y, ctx->X); - } - - /* - * copy the last block, it will be processed in - * aes_cmac128_final(). - */ - memcpy(ctx->last, msg, msg_len); - ctx->last_len = msg_len; - - ZERO_STRUCT(tmp_block); - ZERO_STRUCT(Y); -} - -/* - * AES-CMAC-128 compute T - */ -void aes_cmac128_final(aes_cmac128_context *ctx, uint8_t T[16]) -{ - uint8_t tmp_block[16]; - uint8_t Y[16]; - - if (ctx->last_len < 16) { - ctx->last[ctx->last_len] = 0x80; - aes_cmac_128_xor(ctx->last, ctx->K2, tmp_block); - } else { - aes_cmac_128_xor(ctx->last, ctx->K1, tmp_block); - } - - aes_cmac_128_xor(tmp_block, ctx->X, Y); - aes_crypt_ecb(&ctx->aes_key, AES_ENCRYPT, Y, T); - - ZERO_STRUCT(tmp_block); - ZERO_STRUCT(Y); - ZERO_STRUCTP(ctx); -} - -/* - * Checkup routine - * - * https://csrc.nist.gov/projects/cryptographic-standards-and-guidelines/example-values - * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf - */ -int aes_cmac_self_test( int verbose ) -{ - unsigned char key[16] = {0x2B, 0x7E, 0x15, 0x16, 0x28, 0xAE, 0xD2, 0xA6, 0xAB, 0xF7, 0x15, 0x88, 0x09, 0xCF, 0x4F, 0x3C}; - unsigned char mac[16] = {0}; - aes_cmac128_context ctx; - int ret; - - // check Example1: - if( verbose != 0 ) - polarssl_printf( " AES-CMAC-128 zero length data: " ); - unsigned char ex1data[16] = {0}; - aes_cmac128_starts(&ctx, key); - aes_cmac128_update(&ctx, ex1data, 0); - aes_cmac128_final(&ctx, mac); - unsigned char ex1res[16] = {0xBB, 0x1D, 0x69, 0x29, 0xE9, 0x59, 0x37, 0x28, 0x7F, 0xA3, 0x7D, 0x12, 0x9B, 0x75, 0x67, 0x46}; - if(!memcmp(mac, ex1res, 16)) { - if( verbose != 0 ) - polarssl_printf( "passed\n" ); - } else { - polarssl_printf( "failed\n" ); - ret = 1; - goto exit; - } - - // check Example2: - if( verbose != 0 ) - polarssl_printf( " AES-CMAC-128 one block data : " ); - unsigned char ex2data[16] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A}; - aes_cmac128_starts(&ctx, key); - aes_cmac128_update(&ctx, ex2data, sizeof(ex2data)); - aes_cmac128_final(&ctx, mac); - unsigned char ex2res[16] = {0x07, 0x0A, 0x16, 0xB4, 0x6B, 0x4D, 0x41, 0x44, 0xF7, 0x9B, 0xDD, 0x9D, 0xD0, 0x4A, 0x28, 0x7C}; - if(!memcmp(mac, ex2res, 16)) { - if( verbose != 0 ) - polarssl_printf( "passed\n" ); - } else { - polarssl_printf( "failed\n" ); - ret = 1; - goto exit; - } - - // check Example3: - if( verbose != 0 ) - polarssl_printf( " AES-CMAC-128 20 bytes of data: " ); - unsigned char ex3data[20] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, - 0xAE, 0x2D, 0x8A, 0x57}; - aes_cmac128_starts(&ctx, key); - aes_cmac128_update(&ctx, ex3data, sizeof(ex3data)); - aes_cmac128_final(&ctx, mac); - unsigned char ex3res[16] = {0x7D, 0x85, 0x44, 0x9E, 0xA6, 0xEA, 0x19, 0xC8, 0x23, 0xA7, 0xBF, 0x78, 0x83, 0x7D, 0xFA, 0xDE}; - if(!memcmp(mac, ex3res, 16)) { - if( verbose != 0 ) - polarssl_printf( "passed\n" ); - } else { - polarssl_printf( "failed\n" ); - ret = 1; - goto exit; - } - - // check Example4: - if( verbose != 0 ) - polarssl_printf( " AES-CMAC-128 4 blocks of data: " ); - unsigned char ex4data[64] = {0x6B, 0xC1, 0xBE, 0xE2, 0x2E, 0x40, 0x9F, 0x96, 0xE9, 0x3D, 0x7E, 0x11, 0x73, 0x93, 0x17, 0x2A, - 0xAE, 0x2D, 0x8A, 0x57, 0x1E, 0x03, 0xAC, 0x9C, 0x9E, 0xB7, 0x6F, 0xAC, 0x45, 0xAF, 0x8E, 0x51, - 0x30, 0xC8, 0x1C, 0x46, 0xA3, 0x5C, 0xE4, 0x11, 0xE5, 0xFB, 0xC1, 0x19, 0x1A, 0x0A, 0x52, 0xEF, - 0xF6, 0x9F, 0x24, 0x45, 0xDF, 0x4F, 0x9B, 0x17, 0xAD, 0x2B, 0x41, 0x7B, 0xE6, 0x6C, 0x37, 0x10}; - aes_cmac128_starts(&ctx, key); - aes_cmac128_update(&ctx, ex4data, sizeof(ex4data)); - aes_cmac128_final(&ctx, mac); - unsigned char ex4res[16] = {0x51, 0xF0, 0xBE, 0xBF, 0x7E, 0x3B, 0x9D, 0x92, 0xFC, 0x49, 0x74, 0x17, 0x79, 0x36, 0x3C, 0xFE}; - if(!memcmp(mac, ex4res, 16)) { - if( verbose != 0 ) - polarssl_printf( "passed\n" ); - } else { - polarssl_printf( "failed\n" ); - ret = 1; - goto exit; - } - - if( verbose != 0 ) - polarssl_printf( "\n" ); - - ret = 0; - -exit: - return( ret ); -} - diff --git a/common/polarssl/aes_cmac128.h b/common/polarssl/aes_cmac128.h deleted file mode 100644 index b792755fc..000000000 --- a/common/polarssl/aes_cmac128.h +++ /dev/null @@ -1,81 +0,0 @@ -/* - * AES-CMAC from NIST Special Publication 800-38B Recommendation for block cipher modes of operation: The CMAC mode for authentication. - * - * Copyright (C) 2006-2014, Brainspark B.V. - * Copyright (C) 2014, Anargyros Plemenos - * Tests added Merkok, 2018 - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * 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. - * - * Reference : https://polarssl.org/discussions/generic/authentication-token - * NIST Special Publication 800-38B Recommendation for block cipher modes of operation: The CMAC mode for authentication. - * Tests here: - * https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf -*/ - -#include -#include -#include "aes.h" - -typedef struct aes_cmac_128_context { - aes_context aes_key; - - uint8_t K1[16]; - uint8_t K2[16]; - - uint8_t X[16]; - - uint8_t last[16]; - size_t last_len; -} -aes_cmac128_context; - -/* - * \brief AES-CMAC-128 context setup - * - * \param ctx context to be initialized - * \param key secret key for AES-128 - */ -void aes_cmac128_starts(aes_cmac128_context *ctx, const uint8_t K[16]); - -/* - * \brief AES-CMAC-128 process message - * - * \param ctx context to be initialized - * \param _msg the given message - * \param _msg_len the length of message - */ -void aes_cmac128_update(aes_cmac128_context *ctx, const uint8_t *_msg, size_t _msg_len); - -/* - * \brief AES-CMAC-128 compute T - * - * \param ctx context to be initialized - * \param T the generated MAC which is used to validate the message - */ -void aes_cmac128_final(aes_cmac128_context *ctx, uint8_t T[16]); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int aes_cmac_self_test( int verbose ); - diff --git a/common/polarssl/bignum.c b/common/polarssl/bignum.c deleted file mode 100644 index d22dd5c7d..000000000 --- a/common/polarssl/bignum.c +++ /dev/null @@ -1,2143 +0,0 @@ -/* - * Multi-precision integer library - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * 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. - */ -/* - * This MPI implementation is based on: - * - * http://www.cacr.math.uwaterloo.ca/hac/about/chap14.pdf - * http://www.stillhq.com/extracted/gnupg-api/mpi/ - * http://math.libtomcrypt.com/files/tommath.pdf - */ - -#include "polarssl_config.h" - -#if defined(POLARSSL_BIGNUM_C) - -#include "bignum.h" -#include "bn_mul.h" - -#include - -#define ciL (sizeof(t_uint)) /* chars in limb */ -#define biL (ciL << 3) /* bits in limb */ -#define biH (ciL << 2) /* half limb size */ - -/* - * Convert between bits/chars and number of limbs - */ -#define BITS_TO_LIMBS(i) (((i) + biL - 1) / biL) -#define CHARS_TO_LIMBS(i) (((i) + ciL - 1) / ciL) - -/* - * Initialize one MPI - */ -void mpi_init( mpi *X ) -{ - if( X == NULL ) - return; - - X->s = 1; - X->n = 0; - X->p = NULL; -} - -/* - * Unallocate one MPI - */ -void mpi_free( mpi *X ) -{ - if( X == NULL ) - return; - - if( X->p != NULL ) - { - memset( X->p, 0, X->n * ciL ); - free( X->p ); - } - - X->s = 1; - X->n = 0; - X->p = NULL; -} - -/* - * Enlarge to the specified number of limbs - */ -int mpi_grow( mpi *X, size_t nblimbs ) -{ - t_uint *p; - - if( nblimbs > POLARSSL_MPI_MAX_LIMBS ) - return( POLARSSL_ERR_MPI_MALLOC_FAILED ); - - if( X->n < nblimbs ) - { - if( ( p = (t_uint *) malloc( nblimbs * ciL ) ) == NULL ) - return( POLARSSL_ERR_MPI_MALLOC_FAILED ); - - memset( p, 0, nblimbs * ciL ); - - if( X->p != NULL ) - { - memcpy( p, X->p, X->n * ciL ); - memset( X->p, 0, X->n * ciL ); - free( X->p ); - } - - X->n = nblimbs; - X->p = p; - } - - return( 0 ); -} - -/* - * Copy the contents of Y into X - */ -int mpi_copy( mpi *X, const mpi *Y ) -{ - int ret; - size_t i; - - if( X == Y ) - return( 0 ); - - for( i = Y->n - 1; i > 0; i-- ) - if( Y->p[i] != 0 ) - break; - i++; - - X->s = Y->s; - - MPI_CHK( mpi_grow( X, i ) ); - - memset( X->p, 0, X->n * ciL ); - memcpy( X->p, Y->p, i * ciL ); - -cleanup: - - return( ret ); -} - -/* - * Swap the contents of X and Y - */ -void mpi_swap( mpi *X, mpi *Y ) -{ - mpi T; - - memcpy( &T, X, sizeof( mpi ) ); - memcpy( X, Y, sizeof( mpi ) ); - memcpy( Y, &T, sizeof( mpi ) ); -} - -/* - * Set value from integer - */ -int mpi_lset( mpi *X, t_sint z ) -{ - int ret; - - MPI_CHK( mpi_grow( X, 1 ) ); - memset( X->p, 0, X->n * ciL ); - - X->p[0] = ( z < 0 ) ? -z : z; - X->s = ( z < 0 ) ? -1 : 1; - -cleanup: - - return( ret ); -} - -/* - * Get a specific bit - */ -int mpi_get_bit( const mpi *X, size_t pos ) -{ - if( X->n * biL <= pos ) - return( 0 ); - - return ( X->p[pos / biL] >> ( pos % biL ) ) & 0x01; -} - -/* - * Set a bit to a specific value of 0 or 1 - */ -int mpi_set_bit( mpi *X, size_t pos, unsigned char val ) -{ - int ret = 0; - size_t off = pos / biL; - size_t idx = pos % biL; - - if( val != 0 && val != 1 ) - return POLARSSL_ERR_MPI_BAD_INPUT_DATA; - - if( X->n * biL <= pos ) - { - if( val == 0 ) - return ( 0 ); - - MPI_CHK( mpi_grow( X, off + 1 ) ); - } - - X->p[off] = ( X->p[off] & ~( 0x01 << idx ) ) | ( val << idx ); - -cleanup: - - return( ret ); -} - -/* - * Return the number of least significant bits - */ -size_t mpi_lsb( const mpi *X ) -{ - size_t i, j, count = 0; - - for( i = 0; i < X->n; i++ ) - for( j = 0; j < biL; j++, count++ ) - if( ( ( X->p[i] >> j ) & 1 ) != 0 ) - return( count ); - - return( 0 ); -} - -/* - * Return the number of most significant bits - */ -size_t mpi_msb( const mpi *X ) -{ - size_t i, j; - - for( i = X->n - 1; i > 0; i-- ) - if( X->p[i] != 0 ) - break; - - for( j = biL; j > 0; j-- ) - if( ( ( X->p[i] >> ( j - 1 ) ) & 1 ) != 0 ) - break; - - return( ( i * biL ) + j ); -} - -/* - * Return the total size in bytes - */ -size_t mpi_size( const mpi *X ) -{ - return( ( mpi_msb( X ) + 7 ) >> 3 ); -} - -/* - * Convert an ASCII character to digit value - */ -static int mpi_get_digit( t_uint *d, int radix, char c ) -{ - *d = 255; - - if( c >= 0x30 && c <= 0x39 ) *d = c - 0x30; - if( c >= 0x41 && c <= 0x46 ) *d = c - 0x37; - if( c >= 0x61 && c <= 0x66 ) *d = c - 0x57; - - if( *d >= (t_uint) radix ) - return( POLARSSL_ERR_MPI_INVALID_CHARACTER ); - - return( 0 ); -} - -/* - * Import from an ASCII string - */ -int mpi_read_string( mpi *X, int radix, const char *s ) -{ - int ret; - size_t i, j, slen, n; - t_uint d; - mpi T; - - if( radix < 2 || radix > 16 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - mpi_init( &T ); - - slen = strlen( s ); - - if( radix == 16 ) - { - n = BITS_TO_LIMBS( slen << 2 ); - - MPI_CHK( mpi_grow( X, n ) ); - MPI_CHK( mpi_lset( X, 0 ) ); - - for( i = slen, j = 0; i > 0; i--, j++ ) - { - if( i == 1 && s[i - 1] == '-' ) - { - X->s = -1; - break; - } - - MPI_CHK( mpi_get_digit( &d, radix, s[i - 1] ) ); - X->p[j / (2 * ciL)] |= d << ( (j % (2 * ciL)) << 2 ); - } - } - else - { - MPI_CHK( mpi_lset( X, 0 ) ); - - for( i = 0; i < slen; i++ ) - { - if( i == 0 && s[i] == '-' ) - { - X->s = -1; - continue; - } - - MPI_CHK( mpi_get_digit( &d, radix, s[i] ) ); - MPI_CHK( mpi_mul_int( &T, X, radix ) ); - - if( X->s == 1 ) - { - MPI_CHK( mpi_add_int( X, &T, d ) ); - } - else - { - MPI_CHK( mpi_sub_int( X, &T, d ) ); - } - } - } - -cleanup: - - mpi_free( &T ); - - return( ret ); -} - -/* - * Helper to write the digits high-order first - */ -static int mpi_write_hlp( mpi *X, int radix, char **p ) -{ - int ret; - t_uint r; - - if( radix < 2 || radix > 16 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - MPI_CHK( mpi_mod_int( &r, X, radix ) ); - MPI_CHK( mpi_div_int( X, NULL, X, radix ) ); - - if( mpi_cmp_int( X, 0 ) != 0 ) - MPI_CHK( mpi_write_hlp( X, radix, p ) ); - - if( r < 10 ) - *(*p)++ = (char)( r + 0x30 ); - else - *(*p)++ = (char)( r + 0x37 ); - -cleanup: - - return( ret ); -} - -/* - * Export into an ASCII string - */ -int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen ) -{ - int ret = 0; - size_t n; - char *p; - mpi T; - - if( radix < 2 || radix > 16 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - n = mpi_msb( X ); - if( radix >= 4 ) n >>= 1; - if( radix >= 16 ) n >>= 1; - n += 3; - - if( *slen < n ) - { - *slen = n; - return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); - } - - p = s; - mpi_init( &T ); - - if( X->s == -1 ) - *p++ = '-'; - - if( radix == 16 ) - { - int c; - size_t i, j, k; - - for( i = X->n, k = 0; i > 0; i-- ) - { - for( j = ciL; j > 0; j-- ) - { - c = ( X->p[i - 1] >> ( ( j - 1 ) << 3) ) & 0xFF; - - if( c == 0 && k == 0 && ( i + j + 3 ) != 0 ) - continue; - - *(p++) = "0123456789ABCDEF" [c / 16]; - *(p++) = "0123456789ABCDEF" [c % 16]; - k = 1; - } - } - } - else - { - MPI_CHK( mpi_copy( &T, X ) ); - - if( T.s == -1 ) - T.s = 1; - - MPI_CHK( mpi_write_hlp( &T, radix, &p ) ); - } - - *p++ = '\0'; - *slen = p - s; - -cleanup: - - mpi_free( &T ); - - return( ret ); -} - -#if defined(POLARSSL_FS_IO) -/* - * Read X from an opened file - */ -int mpi_read_file( mpi *X, int radix, FILE *fin ) -{ - t_uint d; - size_t slen; - char *p; - /* - * Buffer should have space for (short) label and decimal formatted MPI, - * newline characters and '\0' - */ - char s[ POLARSSL_MPI_RW_BUFFER_SIZE ]; - - memset( s, 0, sizeof( s ) ); - if( fgets( s, sizeof( s ) - 1, fin ) == NULL ) - return( POLARSSL_ERR_MPI_FILE_IO_ERROR ); - - slen = strlen( s ); - if( slen == sizeof( s ) - 2 ) - return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); - - if( s[slen - 1] == '\n' ) { slen--; s[slen] = '\0'; } - if( s[slen - 1] == '\r' ) { slen--; s[slen] = '\0'; } - - p = s + slen; - while( --p >= s ) - if( mpi_get_digit( &d, radix, *p ) != 0 ) - break; - - return( mpi_read_string( X, radix, p + 1 ) ); -} - -/* - * Write X into an opened file (or stdout if fout == NULL) - */ -int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout ) -{ - int ret; - size_t n, slen, plen; - /* - * Buffer should have space for (short) label and decimal formatted MPI, - * newline characters and '\0' - */ - char s[ POLARSSL_MPI_RW_BUFFER_SIZE ]; - - n = sizeof( s ); - memset( s, 0, n ); - n -= 2; - - MPI_CHK( mpi_write_string( X, radix, s, (size_t *) &n ) ); - - if( p == NULL ) p = ""; - - plen = strlen( p ); - slen = strlen( s ); - s[slen++] = '\r'; - s[slen++] = '\n'; - - if( fout != NULL ) - { - if( fwrite( p, 1, plen, fout ) != plen || - fwrite( s, 1, slen, fout ) != slen ) - return( POLARSSL_ERR_MPI_FILE_IO_ERROR ); - } - else - printf( "%s%s", p, s ); - -cleanup: - - return( ret ); -} -#endif /* POLARSSL_FS_IO */ - -/* - * Import X from unsigned binary data, big endian - */ -int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen ) -{ - int ret; - size_t i, j, n; - - for( n = 0; n < buflen; n++ ) - if( buf[n] != 0 ) - break; - - MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( buflen - n ) ) ); - MPI_CHK( mpi_lset( X, 0 ) ); - - for( i = buflen, j = 0; i > n; i--, j++ ) - X->p[j / ciL] |= ((t_uint) buf[i - 1]) << ((j % ciL) << 3); - -cleanup: - - return( ret ); -} - -/* - * Export X into unsigned binary data, big endian - */ -int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen ) -{ - size_t i, j, n; - - n = mpi_size( X ); - - if( buflen < n ) - return( POLARSSL_ERR_MPI_BUFFER_TOO_SMALL ); - - memset( buf, 0, buflen ); - - for( i = buflen - 1, j = 0; n > 0; i--, j++, n-- ) - buf[i] = (unsigned char)( X->p[j / ciL] >> ((j % ciL) << 3) ); - - return( 0 ); -} - -/* - * Left-shift: X <<= count - */ -int mpi_shift_l( mpi *X, size_t count ) -{ - int ret; - size_t i, v0, t1; - t_uint r0 = 0, r1; - - v0 = count / (biL ); - t1 = count & (biL - 1); - - i = mpi_msb( X ) + count; - - if( X->n * biL < i ) - MPI_CHK( mpi_grow( X, BITS_TO_LIMBS( i ) ) ); - - ret = 0; - - /* - * shift by count / limb_size - */ - if( v0 > 0 ) - { - for( i = X->n; i > v0; i-- ) - X->p[i - 1] = X->p[i - v0 - 1]; - - for( ; i > 0; i-- ) - X->p[i - 1] = 0; - } - - /* - * shift by count % limb_size - */ - if( t1 > 0 ) - { - for( i = v0; i < X->n; i++ ) - { - r1 = X->p[i] >> (biL - t1); - X->p[i] <<= t1; - X->p[i] |= r0; - r0 = r1; - } - } - -cleanup: - - return( ret ); -} - -/* - * Right-shift: X >>= count - */ -int mpi_shift_r( mpi *X, size_t count ) -{ - size_t i, v0, v1; - t_uint r0 = 0, r1; - - v0 = count / biL; - v1 = count & (biL - 1); - - if( v0 > X->n || ( v0 == X->n && v1 > 0 ) ) - return mpi_lset( X, 0 ); - - /* - * shift by count / limb_size - */ - if( v0 > 0 ) - { - for( i = 0; i < X->n - v0; i++ ) - X->p[i] = X->p[i + v0]; - - for( ; i < X->n; i++ ) - X->p[i] = 0; - } - - /* - * shift by count % limb_size - */ - if( v1 > 0 ) - { - for( i = X->n; i > 0; i-- ) - { - r1 = X->p[i - 1] << (biL - v1); - X->p[i - 1] >>= v1; - X->p[i - 1] |= r0; - r0 = r1; - } - } - - return( 0 ); -} - -/* - * Compare unsigned values - */ -int mpi_cmp_abs( const mpi *X, const mpi *Y ) -{ - size_t i, j; - - for( i = X->n; i > 0; i-- ) - if( X->p[i - 1] != 0 ) - break; - - for( j = Y->n; j > 0; j-- ) - if( Y->p[j - 1] != 0 ) - break; - - if( i == 0 && j == 0 ) - return( 0 ); - - if( i > j ) return( 1 ); - if( j > i ) return( -1 ); - - for( ; i > 0; i-- ) - { - if( X->p[i - 1] > Y->p[i - 1] ) return( 1 ); - if( X->p[i - 1] < Y->p[i - 1] ) return( -1 ); - } - - return( 0 ); -} - -/* - * Compare signed values - */ -int mpi_cmp_mpi( const mpi *X, const mpi *Y ) -{ - size_t i, j; - - for( i = X->n; i > 0; i-- ) - if( X->p[i - 1] != 0 ) - break; - - for( j = Y->n; j > 0; j-- ) - if( Y->p[j - 1] != 0 ) - break; - - if( i == 0 && j == 0 ) - return( 0 ); - - if( i > j ) return( X->s ); - if( j > i ) return( -Y->s ); - - if( X->s > 0 && Y->s < 0 ) return( 1 ); - if( Y->s > 0 && X->s < 0 ) return( -1 ); - - for( ; i > 0; i-- ) - { - if( X->p[i - 1] > Y->p[i - 1] ) return( X->s ); - if( X->p[i - 1] < Y->p[i - 1] ) return( -X->s ); - } - - return( 0 ); -} - -/* - * Compare signed values - */ -int mpi_cmp_int( const mpi *X, t_sint z ) -{ - mpi Y; - t_uint p[1]; - - *p = ( z < 0 ) ? -z : z; - Y.s = ( z < 0 ) ? -1 : 1; - Y.n = 1; - Y.p = p; - - return( mpi_cmp_mpi( X, &Y ) ); -} - -/* - * Unsigned addition: X = |A| + |B| (HAC 14.7) - */ -int mpi_add_abs( mpi *X, const mpi *A, const mpi *B ) -{ - int ret; - size_t i, j; - t_uint *o, *p, c; - - if( X == B ) - { - const mpi *T = A; A = X; B = T; - } - - if( X != A ) - MPI_CHK( mpi_copy( X, A ) ); - - /* - * X should always be positive as a result of unsigned additions. - */ - X->s = 1; - - for( j = B->n; j > 0; j-- ) - if( B->p[j - 1] != 0 ) - break; - - MPI_CHK( mpi_grow( X, j ) ); - - o = B->p; p = X->p; c = 0; - - for( i = 0; i < j; i++, o++, p++ ) - { - *p += c; c = ( *p < c ); - *p += *o; c += ( *p < *o ); - } - - while( c != 0 ) - { - if( i >= X->n ) - { - MPI_CHK( mpi_grow( X, i + 1 ) ); - p = X->p + i; - } - - *p += c; c = ( *p < c ); i++; p++; - } - -cleanup: - - return( ret ); -} - -/* - * Helper for mpi substraction - */ -static void mpi_sub_hlp( size_t n, t_uint *s, t_uint *d ) -{ - size_t i; - t_uint c, z; - - for( i = c = 0; i < n; i++, s++, d++ ) - { - z = ( *d < c ); *d -= c; - c = ( *d < *s ) + z; *d -= *s; - } - - while( c != 0 ) - { - z = ( *d < c ); *d -= c; - c = z; i++; d++; - } -} - -/* - * Unsigned substraction: X = |A| - |B| (HAC 14.9) - */ -int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B ) -{ - mpi TB; - int ret; - size_t n; - - if( mpi_cmp_abs( A, B ) < 0 ) - return( POLARSSL_ERR_MPI_NEGATIVE_VALUE ); - - mpi_init( &TB ); - - if( X == B ) - { - MPI_CHK( mpi_copy( &TB, B ) ); - B = &TB; - } - - if( X != A ) - MPI_CHK( mpi_copy( X, A ) ); - - /* - * X should always be positive as a result of unsigned substractions. - */ - X->s = 1; - - ret = 0; - - for( n = B->n; n > 0; n-- ) - if( B->p[n - 1] != 0 ) - break; - - mpi_sub_hlp( n, B->p, X->p ); - -cleanup: - - mpi_free( &TB ); - - return( ret ); -} - -/* - * Signed addition: X = A + B - */ -int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B ) -{ - int ret, s = A->s; - - if( A->s * B->s < 0 ) - { - if( mpi_cmp_abs( A, B ) >= 0 ) - { - MPI_CHK( mpi_sub_abs( X, A, B ) ); - X->s = s; - } - else - { - MPI_CHK( mpi_sub_abs( X, B, A ) ); - X->s = -s; - } - } - else - { - MPI_CHK( mpi_add_abs( X, A, B ) ); - X->s = s; - } - -cleanup: - - return( ret ); -} - -/* - * Signed substraction: X = A - B - */ -int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B ) -{ - int ret, s = A->s; - - if( A->s * B->s > 0 ) - { - if( mpi_cmp_abs( A, B ) >= 0 ) - { - MPI_CHK( mpi_sub_abs( X, A, B ) ); - X->s = s; - } - else - { - MPI_CHK( mpi_sub_abs( X, B, A ) ); - X->s = -s; - } - } - else - { - MPI_CHK( mpi_add_abs( X, A, B ) ); - X->s = s; - } - -cleanup: - - return( ret ); -} - -/* - * Signed addition: X = A + b - */ -int mpi_add_int( mpi *X, const mpi *A, t_sint b ) -{ - mpi _B; - t_uint p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mpi_add_mpi( X, A, &_B ) ); -} - -/* - * Signed substraction: X = A - b - */ -int mpi_sub_int( mpi *X, const mpi *A, t_sint b ) -{ - mpi _B; - t_uint p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mpi_sub_mpi( X, A, &_B ) ); -} - -/* - * Helper for mpi multiplication - */ -static -#if defined(__APPLE__) && defined(__arm__) -/* - * Apple LLVM version 4.2 (clang-425.0.24) (based on LLVM 3.2svn) - * appears to need this to prevent bad ARM code generation at -O3. - */ -__attribute__ ((noinline)) -#endif -void mpi_mul_hlp( size_t i, t_uint *s, t_uint *d, t_uint b ) -{ - t_uint c = 0, t = 0; - -#if defined(MULADDC_HUIT) - for( ; i >= 8; i -= 8 ) - { - MULADDC_INIT - MULADDC_HUIT - MULADDC_STOP - } - - for( ; i > 0; i-- ) - { - MULADDC_INIT - MULADDC_CORE - MULADDC_STOP - } -#else - for( ; i >= 16; i -= 16 ) - { - MULADDC_INIT - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_STOP - } - - for( ; i >= 8; i -= 8 ) - { - MULADDC_INIT - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - - MULADDC_CORE MULADDC_CORE - MULADDC_CORE MULADDC_CORE - MULADDC_STOP - } - - for( ; i > 0; i-- ) - { - MULADDC_INIT - MULADDC_CORE - MULADDC_STOP - } -#endif - - t++; - - do { - *d += c; c = ( *d < c ); d++; - } - while( c != 0 ); -} - -/* - * Baseline multiplication: X = A * B (HAC 14.12) - */ -int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B ) -{ - int ret; - size_t i, j; - mpi TA, TB; - - mpi_init( &TA ); mpi_init( &TB ); - - if( X == A ) { MPI_CHK( mpi_copy( &TA, A ) ); A = &TA; } - if( X == B ) { MPI_CHK( mpi_copy( &TB, B ) ); B = &TB; } - - for( i = A->n; i > 0; i-- ) - if( A->p[i - 1] != 0 ) - break; - - for( j = B->n; j > 0; j-- ) - if( B->p[j - 1] != 0 ) - break; - - MPI_CHK( mpi_grow( X, i + j ) ); - MPI_CHK( mpi_lset( X, 0 ) ); - - for( i++; j > 0; j-- ) - mpi_mul_hlp( i - 1, A->p, X->p + j - 1, B->p[j - 1] ); - - X->s = A->s * B->s; - -cleanup: - - mpi_free( &TB ); mpi_free( &TA ); - - return( ret ); -} - -/* - * Baseline multiplication: X = A * b - */ -int mpi_mul_int( mpi *X, const mpi *A, t_sint b ) -{ - mpi _B; - t_uint p[1]; - - _B.s = 1; - _B.n = 1; - _B.p = p; - p[0] = b; - - return( mpi_mul_mpi( X, A, &_B ) ); -} - -/* - * Division by mpi: A = Q * B + R (HAC 14.20) - */ -int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B ) -{ - int ret; - size_t i, n, t, k; - mpi X, Y, Z, T1, T2; - - if( mpi_cmp_int( B, 0 ) == 0 ) - return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO ); - - mpi_init( &X ); mpi_init( &Y ); mpi_init( &Z ); - mpi_init( &T1 ); mpi_init( &T2 ); - - if( mpi_cmp_abs( A, B ) < 0 ) - { - if( Q != NULL ) MPI_CHK( mpi_lset( Q, 0 ) ); - if( R != NULL ) MPI_CHK( mpi_copy( R, A ) ); - return( 0 ); - } - - MPI_CHK( mpi_copy( &X, A ) ); - MPI_CHK( mpi_copy( &Y, B ) ); - X.s = Y.s = 1; - - MPI_CHK( mpi_grow( &Z, A->n + 2 ) ); - MPI_CHK( mpi_lset( &Z, 0 ) ); - MPI_CHK( mpi_grow( &T1, 2 ) ); - MPI_CHK( mpi_grow( &T2, 3 ) ); - - k = mpi_msb( &Y ) % biL; - if( k < biL - 1 ) - { - k = biL - 1 - k; - MPI_CHK( mpi_shift_l( &X, k ) ); - MPI_CHK( mpi_shift_l( &Y, k ) ); - } - else k = 0; - - n = X.n - 1; - t = Y.n - 1; - MPI_CHK( mpi_shift_l( &Y, biL * (n - t) ) ); - - while( mpi_cmp_mpi( &X, &Y ) >= 0 ) - { - Z.p[n - t]++; - mpi_sub_mpi( &X, &X, &Y ); - } - mpi_shift_r( &Y, biL * (n - t) ); - - for( i = n; i > t ; i-- ) - { - if( X.p[i] >= Y.p[t] ) - Z.p[i - t - 1] = ~0; - else - { -#if defined(POLARSSL_HAVE_UDBL) - t_udbl r; - - r = (t_udbl) X.p[i] << biL; - r |= (t_udbl) X.p[i - 1]; - r /= Y.p[t]; - if( r > ((t_udbl) 1 << biL) - 1) - r = ((t_udbl) 1 << biL) - 1; - - Z.p[i - t - 1] = (t_uint) r; -#else - /* - * __udiv_qrnnd_c, from gmp/longlong.h - */ - t_uint q0, q1, r0, r1; - t_uint d0, d1, d, m; - - d = Y.p[t]; - d0 = ( d << biH ) >> biH; - d1 = ( d >> biH ); - - q1 = X.p[i] / d1; - r1 = X.p[i] - d1 * q1; - r1 <<= biH; - r1 |= ( X.p[i - 1] >> biH ); - - m = q1 * d0; - if( r1 < m ) - { - q1--, r1 += d; - while( r1 >= d && r1 < m ) - q1--, r1 += d; - } - r1 -= m; - - q0 = r1 / d1; - r0 = r1 - d1 * q0; - r0 <<= biH; - r0 |= ( X.p[i - 1] << biH ) >> biH; - - m = q0 * d0; - if( r0 < m ) - { - q0--, r0 += d; - while( r0 >= d && r0 < m ) - q0--, r0 += d; - } - r0 -= m; - - Z.p[i - t - 1] = ( q1 << biH ) | q0; -#endif - } - - Z.p[i - t - 1]++; - do - { - Z.p[i - t - 1]--; - - MPI_CHK( mpi_lset( &T1, 0 ) ); - T1.p[0] = (t < 1) ? 0 : Y.p[t - 1]; - T1.p[1] = Y.p[t]; - MPI_CHK( mpi_mul_int( &T1, &T1, Z.p[i - t - 1] ) ); - - MPI_CHK( mpi_lset( &T2, 0 ) ); - T2.p[0] = (i < 2) ? 0 : X.p[i - 2]; - T2.p[1] = (i < 1) ? 0 : X.p[i - 1]; - T2.p[2] = X.p[i]; - } - while( mpi_cmp_mpi( &T1, &T2 ) > 0 ); - - MPI_CHK( mpi_mul_int( &T1, &Y, Z.p[i - t - 1] ) ); - MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) ); - MPI_CHK( mpi_sub_mpi( &X, &X, &T1 ) ); - - if( mpi_cmp_int( &X, 0 ) < 0 ) - { - MPI_CHK( mpi_copy( &T1, &Y ) ); - MPI_CHK( mpi_shift_l( &T1, biL * (i - t - 1) ) ); - MPI_CHK( mpi_add_mpi( &X, &X, &T1 ) ); - Z.p[i - t - 1]--; - } - } - - if( Q != NULL ) - { - mpi_copy( Q, &Z ); - Q->s = A->s * B->s; - } - - if( R != NULL ) - { - mpi_shift_r( &X, k ); - X.s = A->s; - mpi_copy( R, &X ); - - if( mpi_cmp_int( R, 0 ) == 0 ) - R->s = 1; - } - -cleanup: - - mpi_free( &X ); mpi_free( &Y ); mpi_free( &Z ); - mpi_free( &T1 ); mpi_free( &T2 ); - - return( ret ); -} - -/* - * Division by int: A = Q * b + R - */ -int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b ) -{ - mpi _B; - t_uint p[1]; - - p[0] = ( b < 0 ) ? -b : b; - _B.s = ( b < 0 ) ? -1 : 1; - _B.n = 1; - _B.p = p; - - return( mpi_div_mpi( Q, R, A, &_B ) ); -} - -/* - * Modulo: R = A mod B - */ -int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B ) -{ - int ret; - - if( mpi_cmp_int( B, 0 ) < 0 ) - return POLARSSL_ERR_MPI_NEGATIVE_VALUE; - - MPI_CHK( mpi_div_mpi( NULL, R, A, B ) ); - - while( mpi_cmp_int( R, 0 ) < 0 ) - MPI_CHK( mpi_add_mpi( R, R, B ) ); - - while( mpi_cmp_mpi( R, B ) >= 0 ) - MPI_CHK( mpi_sub_mpi( R, R, B ) ); - -cleanup: - - return( ret ); -} - -/* - * Modulo: r = A mod b - */ -int mpi_mod_int( t_uint *r, const mpi *A, t_sint b ) -{ - size_t i; - t_uint x, y, z; - - if( b == 0 ) - return( POLARSSL_ERR_MPI_DIVISION_BY_ZERO ); - - if( b < 0 ) - return POLARSSL_ERR_MPI_NEGATIVE_VALUE; - - /* - * handle trivial cases - */ - if( b == 1 ) - { - *r = 0; - return( 0 ); - } - - if( b == 2 ) - { - *r = A->p[0] & 1; - return( 0 ); - } - - /* - * general case - */ - for( i = A->n, y = 0; i > 0; i-- ) - { - x = A->p[i - 1]; - y = ( y << biH ) | ( x >> biH ); - z = y / b; - y -= z * b; - - x <<= biH; - y = ( y << biH ) | ( x >> biH ); - z = y / b; - y -= z * b; - } - - /* - * If A is negative, then the current y represents a negative value. - * Flipping it to the positive side. - */ - if( A->s < 0 && y != 0 ) - y = b - y; - - *r = y; - - return( 0 ); -} - -/* - * Fast Montgomery initialization (thanks to Tom St Denis) - */ -static void mpi_montg_init( t_uint *mm, const mpi *N ) -{ - t_uint x, m0 = N->p[0]; - - x = m0; - x += ( ( m0 + 2 ) & 4 ) << 1; - x *= ( 2 - ( m0 * x ) ); - - if( biL >= 16 ) x *= ( 2 - ( m0 * x ) ); - if( biL >= 32 ) x *= ( 2 - ( m0 * x ) ); - if( biL >= 64 ) x *= ( 2 - ( m0 * x ) ); - - *mm = ~x + 1; -} - -/* - * Montgomery multiplication: A = A * B * R^-1 mod N (HAC 14.36) - */ -static void mpi_montmul( mpi *A, const mpi *B, const mpi *N, t_uint mm, const mpi *T ) -{ - size_t i, n, m; - t_uint u0, u1, *d; - - memset( T->p, 0, T->n * ciL ); - - d = T->p; - n = N->n; - m = ( B->n < n ) ? B->n : n; - - for( i = 0; i < n; i++ ) - { - /* - * T = (T + u0*B + u1*N) / 2^biL - */ - u0 = A->p[i]; - u1 = ( d[0] + u0 * B->p[0] ) * mm; - - mpi_mul_hlp( m, B->p, d, u0 ); - mpi_mul_hlp( n, N->p, d, u1 ); - - *d++ = u0; d[n + 1] = 0; - } - - memcpy( A->p, d, (n + 1) * ciL ); - - if( mpi_cmp_abs( A, N ) >= 0 ) - mpi_sub_hlp( n, N->p, A->p ); - else - /* prevent timing attacks */ - mpi_sub_hlp( n, A->p, T->p ); -} - -/* - * Montgomery reduction: A = A * R^-1 mod N - */ -static void mpi_montred( mpi *A, const mpi *N, t_uint mm, const mpi *T ) -{ - t_uint z = 1; - mpi U; - - U.n = U.s = (int) z; - U.p = &z; - - mpi_montmul( A, &U, N, mm, T ); -} - -/* - * Sliding-window exponentiation: X = A^E mod N (HAC 14.85) - */ -int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR ) -{ - int ret; - size_t wbits, wsize, one = 1; - size_t i, j, nblimbs; - size_t bufsize, nbits; - t_uint ei, mm, state; - mpi RR, T, W[ 2 << POLARSSL_MPI_WINDOW_SIZE ], Apos; - int neg; - - if( mpi_cmp_int( N, 0 ) < 0 || ( N->p[0] & 1 ) == 0 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - if( mpi_cmp_int( E, 0 ) < 0 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - /* - * Init temps and window size - */ - mpi_montg_init( &mm, N ); - mpi_init( &RR ); mpi_init( &T ); - memset( W, 0, sizeof( W ) ); - - i = mpi_msb( E ); - - wsize = ( i > 671 ) ? 6 : ( i > 239 ) ? 5 : - ( i > 79 ) ? 4 : ( i > 23 ) ? 3 : 1; - - if( wsize > POLARSSL_MPI_WINDOW_SIZE ) - wsize = POLARSSL_MPI_WINDOW_SIZE; - - j = N->n + 1; - MPI_CHK( mpi_grow( X, j ) ); - MPI_CHK( mpi_grow( &W[1], j ) ); - MPI_CHK( mpi_grow( &T, j * 2 ) ); - - /* - * Compensate for negative A (and correct at the end) - */ - neg = ( A->s == -1 ); - - mpi_init( &Apos ); - if( neg ) - { - MPI_CHK( mpi_copy( &Apos, A ) ); - Apos.s = 1; - A = &Apos; - } - - /* - * If 1st call, pre-compute R^2 mod N - */ - if( _RR == NULL || _RR->p == NULL ) - { - MPI_CHK( mpi_lset( &RR, 1 ) ); - MPI_CHK( mpi_shift_l( &RR, N->n * 2 * biL ) ); - MPI_CHK( mpi_mod_mpi( &RR, &RR, N ) ); - - if( _RR != NULL ) - memcpy( _RR, &RR, sizeof( mpi ) ); - } - else - memcpy( &RR, _RR, sizeof( mpi ) ); - - /* - * W[1] = A * R^2 * R^-1 mod N = A * R mod N - */ - if( mpi_cmp_mpi( A, N ) >= 0 ) - mpi_mod_mpi( &W[1], A, N ); - else mpi_copy( &W[1], A ); - - mpi_montmul( &W[1], &RR, N, mm, &T ); - - /* - * X = R^2 * R^-1 mod N = R mod N - */ - MPI_CHK( mpi_copy( X, &RR ) ); - mpi_montred( X, N, mm, &T ); - - if( wsize > 1 ) - { - /* - * W[1 << (wsize - 1)] = W[1] ^ (wsize - 1) - */ - j = one << (wsize - 1); - - MPI_CHK( mpi_grow( &W[j], N->n + 1 ) ); - MPI_CHK( mpi_copy( &W[j], &W[1] ) ); - - for( i = 0; i < wsize - 1; i++ ) - mpi_montmul( &W[j], &W[j], N, mm, &T ); - - /* - * W[i] = W[i - 1] * W[1] - */ - for( i = j + 1; i < (one << wsize); i++ ) - { - MPI_CHK( mpi_grow( &W[i], N->n + 1 ) ); - MPI_CHK( mpi_copy( &W[i], &W[i - 1] ) ); - - mpi_montmul( &W[i], &W[1], N, mm, &T ); - } - } - - nblimbs = E->n; - bufsize = 0; - nbits = 0; - wbits = 0; - state = 0; - - while( 1 ) - { - if( bufsize == 0 ) - { - if( nblimbs-- == 0 ) - break; - - bufsize = sizeof( t_uint ) << 3; - } - - bufsize--; - - ei = (E->p[nblimbs] >> bufsize) & 1; - - /* - * skip leading 0s - */ - if( ei == 0 && state == 0 ) - continue; - - if( ei == 0 && state == 1 ) - { - /* - * out of window, square X - */ - mpi_montmul( X, X, N, mm, &T ); - continue; - } - - /* - * add ei to current window - */ - state = 2; - - nbits++; - wbits |= (ei << (wsize - nbits)); - - if( nbits == wsize ) - { - /* - * X = X^wsize R^-1 mod N - */ - for( i = 0; i < wsize; i++ ) - mpi_montmul( X, X, N, mm, &T ); - - /* - * X = X * W[wbits] R^-1 mod N - */ - mpi_montmul( X, &W[wbits], N, mm, &T ); - - state--; - nbits = 0; - wbits = 0; - } - } - - /* - * process the remaining bits - */ - for( i = 0; i < nbits; i++ ) - { - mpi_montmul( X, X, N, mm, &T ); - - wbits <<= 1; - - if( (wbits & (one << wsize)) != 0 ) - mpi_montmul( X, &W[1], N, mm, &T ); - } - - /* - * X = A^E * R * R^-1 mod N = A^E mod N - */ - mpi_montred( X, N, mm, &T ); - - if( neg ) - { - X->s = -1; - mpi_add_mpi( X, N, X ); - } - -cleanup: - - for( i = (one << (wsize - 1)); i < (one << wsize); i++ ) - mpi_free( &W[i] ); - - mpi_free( &W[1] ); mpi_free( &T ); mpi_free( &Apos ); - - if( _RR == NULL ) - mpi_free( &RR ); - - return( ret ); -} - -/* - * Greatest common divisor: G = gcd(A, B) (HAC 14.54) - */ -int mpi_gcd( mpi *G, const mpi *A, const mpi *B ) -{ - int ret; - size_t lz, lzt; - mpi TG, TA, TB; - - mpi_init( &TG ); mpi_init( &TA ); mpi_init( &TB ); - - MPI_CHK( mpi_copy( &TA, A ) ); - MPI_CHK( mpi_copy( &TB, B ) ); - - lz = mpi_lsb( &TA ); - lzt = mpi_lsb( &TB ); - - if ( lzt < lz ) - lz = lzt; - - MPI_CHK( mpi_shift_r( &TA, lz ) ); - MPI_CHK( mpi_shift_r( &TB, lz ) ); - - TA.s = TB.s = 1; - - while( mpi_cmp_int( &TA, 0 ) != 0 ) - { - MPI_CHK( mpi_shift_r( &TA, mpi_lsb( &TA ) ) ); - MPI_CHK( mpi_shift_r( &TB, mpi_lsb( &TB ) ) ); - - if( mpi_cmp_mpi( &TA, &TB ) >= 0 ) - { - MPI_CHK( mpi_sub_abs( &TA, &TA, &TB ) ); - MPI_CHK( mpi_shift_r( &TA, 1 ) ); - } - else - { - MPI_CHK( mpi_sub_abs( &TB, &TB, &TA ) ); - MPI_CHK( mpi_shift_r( &TB, 1 ) ); - } - } - - MPI_CHK( mpi_shift_l( &TB, lz ) ); - MPI_CHK( mpi_copy( G, &TB ) ); - -cleanup: - - mpi_free( &TG ); mpi_free( &TA ); mpi_free( &TB ); - - return( ret ); -} - -int mpi_fill_random( mpi *X, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - - MPI_CHK( mpi_grow( X, CHARS_TO_LIMBS( size ) ) ); - MPI_CHK( mpi_lset( X, 0 ) ); - - MPI_CHK( f_rng( p_rng, (unsigned char *) X->p, size ) ); - -cleanup: - return( ret ); -} - -/* - * Modular inverse: X = A^-1 mod N (HAC 14.61 / 14.64) - */ -int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N ) -{ - int ret; - mpi G, TA, TU, U1, U2, TB, TV, V1, V2; - - if( mpi_cmp_int( N, 0 ) <= 0 ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - mpi_init( &TA ); mpi_init( &TU ); mpi_init( &U1 ); mpi_init( &U2 ); - mpi_init( &G ); mpi_init( &TB ); mpi_init( &TV ); - mpi_init( &V1 ); mpi_init( &V2 ); - - MPI_CHK( mpi_gcd( &G, A, N ) ); - - if( mpi_cmp_int( &G, 1 ) != 0 ) - { - ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE; - goto cleanup; - } - - MPI_CHK( mpi_mod_mpi( &TA, A, N ) ); - MPI_CHK( mpi_copy( &TU, &TA ) ); - MPI_CHK( mpi_copy( &TB, N ) ); - MPI_CHK( mpi_copy( &TV, N ) ); - - MPI_CHK( mpi_lset( &U1, 1 ) ); - MPI_CHK( mpi_lset( &U2, 0 ) ); - MPI_CHK( mpi_lset( &V1, 0 ) ); - MPI_CHK( mpi_lset( &V2, 1 ) ); - - do - { - while( ( TU.p[0] & 1 ) == 0 ) - { - MPI_CHK( mpi_shift_r( &TU, 1 ) ); - - if( ( U1.p[0] & 1 ) != 0 || ( U2.p[0] & 1 ) != 0 ) - { - MPI_CHK( mpi_add_mpi( &U1, &U1, &TB ) ); - MPI_CHK( mpi_sub_mpi( &U2, &U2, &TA ) ); - } - - MPI_CHK( mpi_shift_r( &U1, 1 ) ); - MPI_CHK( mpi_shift_r( &U2, 1 ) ); - } - - while( ( TV.p[0] & 1 ) == 0 ) - { - MPI_CHK( mpi_shift_r( &TV, 1 ) ); - - if( ( V1.p[0] & 1 ) != 0 || ( V2.p[0] & 1 ) != 0 ) - { - MPI_CHK( mpi_add_mpi( &V1, &V1, &TB ) ); - MPI_CHK( mpi_sub_mpi( &V2, &V2, &TA ) ); - } - - MPI_CHK( mpi_shift_r( &V1, 1 ) ); - MPI_CHK( mpi_shift_r( &V2, 1 ) ); - } - - if( mpi_cmp_mpi( &TU, &TV ) >= 0 ) - { - MPI_CHK( mpi_sub_mpi( &TU, &TU, &TV ) ); - MPI_CHK( mpi_sub_mpi( &U1, &U1, &V1 ) ); - MPI_CHK( mpi_sub_mpi( &U2, &U2, &V2 ) ); - } - else - { - MPI_CHK( mpi_sub_mpi( &TV, &TV, &TU ) ); - MPI_CHK( mpi_sub_mpi( &V1, &V1, &U1 ) ); - MPI_CHK( mpi_sub_mpi( &V2, &V2, &U2 ) ); - } - } - while( mpi_cmp_int( &TU, 0 ) != 0 ); - - while( mpi_cmp_int( &V1, 0 ) < 0 ) - MPI_CHK( mpi_add_mpi( &V1, &V1, N ) ); - - while( mpi_cmp_mpi( &V1, N ) >= 0 ) - MPI_CHK( mpi_sub_mpi( &V1, &V1, N ) ); - - MPI_CHK( mpi_copy( X, &V1 ) ); - -cleanup: - - mpi_free( &TA ); mpi_free( &TU ); mpi_free( &U1 ); mpi_free( &U2 ); - mpi_free( &G ); mpi_free( &TB ); mpi_free( &TV ); - mpi_free( &V1 ); mpi_free( &V2 ); - - return( ret ); -} - -#if defined(POLARSSL_GENPRIME) - -static const int small_prime[] = -{ - 3, 5, 7, 11, 13, 17, 19, 23, - 29, 31, 37, 41, 43, 47, 53, 59, - 61, 67, 71, 73, 79, 83, 89, 97, - 101, 103, 107, 109, 113, 127, 131, 137, - 139, 149, 151, 157, 163, 167, 173, 179, - 181, 191, 193, 197, 199, 211, 223, 227, - 229, 233, 239, 241, 251, 257, 263, 269, - 271, 277, 281, 283, 293, 307, 311, 313, - 317, 331, 337, 347, 349, 353, 359, 367, - 373, 379, 383, 389, 397, 401, 409, 419, - 421, 431, 433, 439, 443, 449, 457, 461, - 463, 467, 479, 487, 491, 499, 503, 509, - 521, 523, 541, 547, 557, 563, 569, 571, - 577, 587, 593, 599, 601, 607, 613, 617, - 619, 631, 641, 643, 647, 653, 659, 661, - 673, 677, 683, 691, 701, 709, 719, 727, - 733, 739, 743, 751, 757, 761, 769, 773, - 787, 797, 809, 811, 821, 823, 827, 829, - 839, 853, 857, 859, 863, 877, 881, 883, - 887, 907, 911, 919, 929, 937, 941, 947, - 953, 967, 971, 977, 983, 991, 997, -103 -}; - -/* - * Miller-Rabin primality test (HAC 4.24) - */ -int mpi_is_prime( mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret, xs; - size_t i, j, n, s; - mpi W, R, T, A, RR; - - if( mpi_cmp_int( X, 0 ) == 0 || - mpi_cmp_int( X, 1 ) == 0 ) - return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); - - if( mpi_cmp_int( X, 2 ) == 0 ) - return( 0 ); - - mpi_init( &W ); mpi_init( &R ); mpi_init( &T ); mpi_init( &A ); - mpi_init( &RR ); - - xs = X->s; X->s = 1; - - /* - * test trivial factors first - */ - if( ( X->p[0] & 1 ) == 0 ) - return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); - - for( i = 0; small_prime[i] > 0; i++ ) - { - t_uint r; - - if( mpi_cmp_int( X, small_prime[i] ) <= 0 ) - return( 0 ); - - MPI_CHK( mpi_mod_int( &r, X, small_prime[i] ) ); - - if( r == 0 ) - return( POLARSSL_ERR_MPI_NOT_ACCEPTABLE ); - } - - /* - * W = |X| - 1 - * R = W >> lsb( W ) - */ - MPI_CHK( mpi_sub_int( &W, X, 1 ) ); - s = mpi_lsb( &W ); - MPI_CHK( mpi_copy( &R, &W ) ); - MPI_CHK( mpi_shift_r( &R, s ) ); - - i = mpi_msb( X ); - /* - * HAC, table 4.4 - */ - n = ( ( i >= 1300 ) ? 2 : ( i >= 850 ) ? 3 : - ( i >= 650 ) ? 4 : ( i >= 350 ) ? 8 : - ( i >= 250 ) ? 12 : ( i >= 150 ) ? 18 : 27 ); - - for( i = 0; i < n; i++ ) - { - /* - * pick a random A, 1 < A < |X| - 1 - */ - MPI_CHK( mpi_fill_random( &A, X->n * ciL, f_rng, p_rng ) ); - - if( mpi_cmp_mpi( &A, &W ) >= 0 ) - { - j = mpi_msb( &A ) - mpi_msb( &W ); - MPI_CHK( mpi_shift_r( &A, j + 1 ) ); - } - A.p[0] |= 3; - - /* - * A = A^R mod |X| - */ - MPI_CHK( mpi_exp_mod( &A, &A, &R, X, &RR ) ); - - if( mpi_cmp_mpi( &A, &W ) == 0 || - mpi_cmp_int( &A, 1 ) == 0 ) - continue; - - j = 1; - while( j < s && mpi_cmp_mpi( &A, &W ) != 0 ) - { - /* - * A = A * A mod |X| - */ - MPI_CHK( mpi_mul_mpi( &T, &A, &A ) ); - MPI_CHK( mpi_mod_mpi( &A, &T, X ) ); - - if( mpi_cmp_int( &A, 1 ) == 0 ) - break; - - j++; - } - - /* - * not prime if A != |X| - 1 or A == 1 - */ - if( mpi_cmp_mpi( &A, &W ) != 0 || - mpi_cmp_int( &A, 1 ) == 0 ) - { - ret = POLARSSL_ERR_MPI_NOT_ACCEPTABLE; - break; - } - } - -cleanup: - - X->s = xs; - - mpi_free( &W ); mpi_free( &R ); mpi_free( &T ); mpi_free( &A ); - mpi_free( &RR ); - - return( ret ); -} - -/* - * Prime number generation - */ -int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ) -{ - int ret; - size_t k, n; - mpi Y; - - if( nbits < 3 || nbits > POLARSSL_MPI_MAX_BITS ) - return( POLARSSL_ERR_MPI_BAD_INPUT_DATA ); - - mpi_init( &Y ); - - n = BITS_TO_LIMBS( nbits ); - - MPI_CHK( mpi_fill_random( X, n * ciL, f_rng, p_rng ) ); - - k = mpi_msb( X ); - if( k < nbits ) MPI_CHK( mpi_shift_l( X, nbits - k ) ); - if( k > nbits ) MPI_CHK( mpi_shift_r( X, k - nbits ) ); - - X->p[0] |= 3; - - if( dh_flag == 0 ) - { - while( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) != 0 ) - { - if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - - MPI_CHK( mpi_add_int( X, X, 2 ) ); - } - } - else - { - MPI_CHK( mpi_sub_int( &Y, X, 1 ) ); - MPI_CHK( mpi_shift_r( &Y, 1 ) ); - - while( 1 ) - { - if( ( ret = mpi_is_prime( X, f_rng, p_rng ) ) == 0 ) - { - if( ( ret = mpi_is_prime( &Y, f_rng, p_rng ) ) == 0 ) - break; - - if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - } - - if( ret != POLARSSL_ERR_MPI_NOT_ACCEPTABLE ) - goto cleanup; - - MPI_CHK( mpi_add_int( &Y, X, 1 ) ); - MPI_CHK( mpi_add_int( X, X, 2 ) ); - MPI_CHK( mpi_shift_r( &Y, 1 ) ); - } - } - -cleanup: - - mpi_free( &Y ); - - return( ret ); -} - -#endif - -#if defined(POLARSSL_SELF_TEST) - -#define GCD_PAIR_COUNT 3 - -static const int gcd_pairs[GCD_PAIR_COUNT][3] = -{ - { 693, 609, 21 }, - { 1764, 868, 28 }, - { 768454923, 542167814, 1 } -}; - -/* - * Checkup routine - */ -int mpi_self_test( int verbose ) -{ - int ret, i; - mpi A, E, N, X, Y, U, V; - - mpi_init( &A ); mpi_init( &E ); mpi_init( &N ); mpi_init( &X ); - mpi_init( &Y ); mpi_init( &U ); mpi_init( &V ); - - MPI_CHK( mpi_read_string( &A, 16, - "EFE021C2645FD1DC586E69184AF4A31E" \ - "D5F53E93B5F123FA41680867BA110131" \ - "944FE7952E2517337780CB0DB80E61AA" \ - "E7C8DDC6C5C6AADEB34EB38A2F40D5E6" ) ); - - MPI_CHK( mpi_read_string( &E, 16, - "B2E7EFD37075B9F03FF989C7C5051C20" \ - "34D2A323810251127E7BF8625A4F49A5" \ - "F3E27F4DA8BD59C47D6DAABA4C8127BD" \ - "5B5C25763222FEFCCFC38B832366C29E" ) ); - - MPI_CHK( mpi_read_string( &N, 16, - "0066A198186C18C10B2F5ED9B522752A" \ - "9830B69916E535C8F047518A889A43A5" \ - "94B6BED27A168D31D4A52F88925AA8F5" ) ); - - MPI_CHK( mpi_mul_mpi( &X, &A, &N ) ); - - MPI_CHK( mpi_read_string( &U, 16, - "602AB7ECA597A3D6B56FF9829A5E8B85" \ - "9E857EA95A03512E2BAE7391688D264A" \ - "A5663B0341DB9CCFD2C4C5F421FEC814" \ - "8001B72E848A38CAE1C65F78E56ABDEF" \ - "E12D3C039B8A02D6BE593F0BBBDA56F1" \ - "ECF677152EF804370C1A305CAF3B5BF1" \ - "30879B56C61DE584A0F53A2447A51E" ) ); - - if( verbose != 0 ) - printf( " MPI test #1 (mul_mpi): " ); - - if( mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - - MPI_CHK( mpi_div_mpi( &X, &Y, &A, &N ) ); - - MPI_CHK( mpi_read_string( &U, 16, - "256567336059E52CAE22925474705F39A94" ) ); - - MPI_CHK( mpi_read_string( &V, 16, - "6613F26162223DF488E9CD48CC132C7A" \ - "0AC93C701B001B092E4E5B9F73BCD27B" \ - "9EE50D0657C77F374E903CDFA4C642" ) ); - - if( verbose != 0 ) - printf( " MPI test #2 (div_mpi): " ); - - if( mpi_cmp_mpi( &X, &U ) != 0 || - mpi_cmp_mpi( &Y, &V ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - - MPI_CHK( mpi_exp_mod( &X, &A, &E, &N, NULL ) ); - - MPI_CHK( mpi_read_string( &U, 16, - "36E139AEA55215609D2816998ED020BB" \ - "BD96C37890F65171D948E9BC7CBAA4D9" \ - "325D24D6A3C12710F10A09FA08AB87" ) ); - - if( verbose != 0 ) - printf( " MPI test #3 (exp_mod): " ); - - if( mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); - -#if defined(POLARSSL_GENPRIME) - MPI_CHK( mpi_inv_mod( &X, &A, &N ) ); - - MPI_CHK( mpi_read_string( &U, 16, - "003A0AAEDD7E784FC07D8F9EC6E3BFD5" \ - "C3DBA76456363A10869622EAC2DD84EC" \ - "C5B8A74DAC4D09E03B5E0BE779F2DF61" ) ); - - if( verbose != 0 ) - printf( " MPI test #4 (inv_mod): " ); - - if( mpi_cmp_mpi( &X, &U ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n" ); -#endif - - if( verbose != 0 ) - printf( " MPI test #5 (simple gcd): " ); - - for ( i = 0; i < GCD_PAIR_COUNT; i++) - { - MPI_CHK( mpi_lset( &X, gcd_pairs[i][0] ) ); - MPI_CHK( mpi_lset( &Y, gcd_pairs[i][1] ) ); - - MPI_CHK( mpi_gcd( &A, &X, &Y ) ); - - if( mpi_cmp_int( &A, gcd_pairs[i][2] ) != 0 ) - { - if( verbose != 0 ) - printf( "failed at %d\n", i ); - - return( 1 ); - } - } - - if( verbose != 0 ) - printf( "passed\n" ); - -cleanup: - - if( ret != 0 && verbose != 0 ) - printf( "Unexpected error, return code = %08X\n", ret ); - - mpi_free( &A ); mpi_free( &E ); mpi_free( &N ); mpi_free( &X ); - mpi_free( &Y ); mpi_free( &U ); mpi_free( &V ); - - if( verbose != 0 ) - printf( "\n" ); - - return( ret ); -} - -#endif - -#endif diff --git a/common/polarssl/bignum.h b/common/polarssl/bignum.h deleted file mode 100644 index 5eaf1a57b..000000000 --- a/common/polarssl/bignum.h +++ /dev/null @@ -1,685 +0,0 @@ -/** - * \file bignum.h - * - * \brief Multi-precision integer library - * - * Copyright (C) 2006-2013, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_BIGNUM_H -#define POLARSSL_BIGNUM_H - -#include -#include - -#include "polarssl_config.h" - -#ifdef _MSC_VER -#include -#if (_MSC_VER <= 1200) -typedef signed short int16_t; -typedef unsigned short uint16_t; -#else -typedef INT16 int16_t; -typedef UINT16 uint16_t; -#endif -typedef INT32 int32_t; -typedef INT64 int64_t; -typedef UINT32 uint32_t; -typedef UINT64 uint64_t; -#else -#include -#endif - -#define POLARSSL_ERR_MPI_FILE_IO_ERROR -0x0002 /**< An error occurred while reading from or writing to a file. */ -#define POLARSSL_ERR_MPI_BAD_INPUT_DATA -0x0004 /**< Bad input parameters to function. */ -#define POLARSSL_ERR_MPI_INVALID_CHARACTER -0x0006 /**< There is an invalid character in the digit string. */ -#define POLARSSL_ERR_MPI_BUFFER_TOO_SMALL -0x0008 /**< The buffer is too small to write to. */ -#define POLARSSL_ERR_MPI_NEGATIVE_VALUE -0x000A /**< The input arguments are negative or result in illegal output. */ -#define POLARSSL_ERR_MPI_DIVISION_BY_ZERO -0x000C /**< The input argument for division is zero, which is not allowed. */ -#define POLARSSL_ERR_MPI_NOT_ACCEPTABLE -0x000E /**< The input arguments are not acceptable. */ -#define POLARSSL_ERR_MPI_MALLOC_FAILED -0x0010 /**< Memory allocation failed. */ - -#define MPI_CHK(f) if( ( ret = f ) != 0 ) goto cleanup - -/* - * Maximum size MPIs are allowed to grow to in number of limbs. - */ -#define POLARSSL_MPI_MAX_LIMBS 10000 - -#if !defined(POLARSSL_CONFIG_OPTIONS) -/* - * Maximum window size used for modular exponentiation. Default: 6 - * Minimum value: 1. Maximum value: 6. - * - * Result is an array of ( 2 << POLARSSL_MPI_WINDOW_SIZE ) MPIs used - * for the sliding window calculation. (So 64 by default) - * - * Reduction in size, reduces speed. - */ -#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ - -/* - * Maximum size of MPIs allowed in bits and bytes for user-MPIs. - * ( Default: 512 bytes => 4096 bits, Maximum tested: 2048 bytes => 16384 bits ) - * - * Note: Calculations can results temporarily in larger MPIs. So the number - * of limbs required (POLARSSL_MPI_MAX_LIMBS) is higher. - */ -#define POLARSSL_MPI_MAX_SIZE 512 /**< Maximum number of bytes for usable MPIs. */ - -#endif /* !POLARSSL_CONFIG_OPTIONS */ - -#define POLARSSL_MPI_MAX_BITS ( 8 * POLARSSL_MPI_MAX_SIZE ) /**< Maximum number of bits for usable MPIs. */ - -/* - * When reading from files with mpi_read_file() and writing to files with - * mpi_write_file() the buffer should have space - * for a (short) label, the MPI (in the provided radix), the newline - * characters and the '\0'. - * - * By default we assume at least a 10 char label, a minimum radix of 10 - * (decimal) and a maximum of 4096 bit numbers (1234 decimal chars). - * Autosized at compile time for at least a 10 char label, a minimum radix - * of 10 (decimal) for a number of POLARSSL_MPI_MAX_BITS size. - * - * This used to be statically sized to 1250 for a maximum of 4096 bit - * numbers (1234 decimal chars). - * - * Calculate using the formula: - * POLARSSL_MPI_RW_BUFFER_SIZE = ceil(POLARSSL_MPI_MAX_BITS / ln(10) * ln(2)) + - * LabelSize + 6 - */ -#define POLARSSL_MPI_MAX_BITS_SCALE100 ( 100 * POLARSSL_MPI_MAX_BITS ) -#define LN_2_DIV_LN_10_SCALE100 332 -#define POLARSSL_MPI_RW_BUFFER_SIZE ( ((POLARSSL_MPI_MAX_BITS_SCALE100 + LN_2_DIV_LN_10_SCALE100 - 1) / LN_2_DIV_LN_10_SCALE100) + 10 + 6 ) - -/* - * Define the base integer type, architecture-wise - */ -#if defined(POLARSSL_HAVE_INT8) -typedef signed char t_sint; -typedef unsigned char t_uint; -typedef uint16_t t_udbl; -#define POLARSSL_HAVE_UDBL -#else -#if defined(POLARSSL_HAVE_INT16) -typedef int16_t t_sint; -typedef uint16_t t_uint; -typedef uint32_t t_udbl; -#define POLARSSL_HAVE_UDBL -#else - #if ( defined(_MSC_VER) && defined(_M_AMD64) ) - typedef int64_t t_sint; - typedef uint64_t t_uint; - #else - #if ( defined(__GNUC__) && ( \ - defined(__amd64__) || defined(__x86_64__) || \ - defined(__ppc64__) || defined(__powerpc64__) || \ - defined(__ia64__) || defined(__alpha__) || \ - (defined(__sparc__) && defined(__arch64__)) || \ - defined(__s390x__) ) ) - typedef int64_t t_sint; - typedef uint64_t t_uint; - typedef unsigned int t_udbl __attribute__((mode(TI))); - #define POLARSSL_HAVE_UDBL - #else - typedef int32_t t_sint; - typedef uint32_t t_uint; - #if ( defined(_MSC_VER) && defined(_M_IX86) ) - typedef uint64_t t_udbl; - #define POLARSSL_HAVE_UDBL - #else - #if defined( POLARSSL_HAVE_LONGLONG ) - typedef unsigned long long t_udbl; - #define POLARSSL_HAVE_UDBL - #endif - #endif - #endif - #endif -#endif /* POLARSSL_HAVE_INT16 */ -#endif /* POLARSSL_HAVE_INT8 */ - -/** - * \brief MPI structure - */ -typedef struct -{ - int s; /*!< integer sign */ - size_t n; /*!< total # of limbs */ - t_uint *p; /*!< pointer to limbs */ -} -mpi; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Initialize one MPI - * - * \param X One MPI to initialize. - */ -void mpi_init( mpi *X ); - -/** - * \brief Unallocate one MPI - * - * \param X One MPI to unallocate. - */ -void mpi_free( mpi *X ); - -/** - * \brief Enlarge to the specified number of limbs - * - * \param X MPI to grow - * \param nblimbs The target number of limbs - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_grow( mpi *X, size_t nblimbs ); - -/** - * \brief Copy the contents of Y into X - * - * \param X Destination MPI - * \param Y Source MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_copy( mpi *X, const mpi *Y ); - -/** - * \brief Swap the contents of X and Y - * - * \param X First MPI value - * \param Y Second MPI value - */ -void mpi_swap( mpi *X, mpi *Y ); - -/** - * \brief Set value from integer - * - * \param X MPI to set - * \param z Value to use - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_lset( mpi *X, t_sint z ); - -/** - * \brief Get a specific bit from X - * - * \param X MPI to use - * \param pos Zero-based index of the bit in X - * - * \return Either a 0 or a 1 - */ -int mpi_get_bit( const mpi *X, size_t pos ); - -/** - * \brief Set a bit of X to a specific value of 0 or 1 - * - * \note Will grow X if necessary to set a bit to 1 in a not yet - * existing limb. Will not grow if bit should be set to 0 - * - * \param X MPI to use - * \param pos Zero-based index of the bit in X - * \param val The value to set the bit to (0 or 1) - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_BAD_INPUT_DATA if val is not 0 or 1 - */ -int mpi_set_bit( mpi *X, size_t pos, unsigned char val ); - -/** - * \brief Return the number of zero-bits before the least significant - * '1' bit - * - * Note: Thus also the zero-based index of the least significant '1' bit - * - * \param X MPI to use - */ -size_t mpi_lsb( const mpi *X ); - -/** - * \brief Return the number of bits up to and including the most - * significant '1' bit' - * - * Note: Thus also the one-based index of the most significant '1' bit - * - * \param X MPI to use - */ -size_t mpi_msb( const mpi *X ); - -/** - * \brief Return the total size in bytes - * - * \param X MPI to use - */ -size_t mpi_size( const mpi *X ); - -/** - * \brief Import from an ASCII string - * - * \param X Destination MPI - * \param radix Input numeric base - * \param s Null-terminated string buffer - * - * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code - */ -int mpi_read_string( mpi *X, int radix, const char *s ); - -/** - * \brief Export into an ASCII string - * - * \param X Source MPI - * \param radix Output numeric base - * \param s String buffer - * \param slen String buffer size - * - * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code. - * *slen is always updated to reflect the amount - * of data that has (or would have) been written. - * - * \note Call this function with *slen = 0 to obtain the - * minimum required buffer size in *slen. - */ -int mpi_write_string( const mpi *X, int radix, char *s, size_t *slen ); - -#if defined(POLARSSL_FS_IO) -/** - * \brief Read X from an opened file - * - * \param X Destination MPI - * \param radix Input numeric base - * \param fin Input file handle - * - * \return 0 if successful, POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if - * the file read buffer is too small or a - * POLARSSL_ERR_MPI_XXX error code - */ -int mpi_read_file( mpi *X, int radix, FILE *fin ); - -/** - * \brief Write X into an opened file, or stdout if fout is NULL - * - * \param p Prefix, can be NULL - * \param X Source MPI - * \param radix Output numeric base - * \param fout Output file handle (can be NULL) - * - * \return 0 if successful, or a POLARSSL_ERR_MPI_XXX error code - * - * \note Set fout == NULL to print X on the console. - */ -int mpi_write_file( const char *p, const mpi *X, int radix, FILE *fout ); -#endif /* POLARSSL_FS_IO */ - -/** - * \brief Import X from unsigned binary data, big endian - * - * \param X Destination MPI - * \param buf Input buffer - * \param buflen Input buffer size - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_read_binary( mpi *X, const unsigned char *buf, size_t buflen ); - -/** - * \brief Export X into unsigned binary data, big endian - * - * \param X Source MPI - * \param buf Output buffer - * \param buflen Output buffer size - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_BUFFER_TOO_SMALL if buf isn't large enough - */ -int mpi_write_binary( const mpi *X, unsigned char *buf, size_t buflen ); - -/** - * \brief Left-shift: X <<= count - * - * \param X MPI to shift - * \param count Amount to shift - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_shift_l( mpi *X, size_t count ); - -/** - * \brief Right-shift: X >>= count - * - * \param X MPI to shift - * \param count Amount to shift - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_shift_r( mpi *X, size_t count ); - -/** - * \brief Compare unsigned values - * - * \param X Left-hand MPI - * \param Y Right-hand MPI - * - * \return 1 if |X| is greater than |Y|, - * -1 if |X| is lesser than |Y| or - * 0 if |X| is equal to |Y| - */ -int mpi_cmp_abs( const mpi *X, const mpi *Y ); - -/** - * \brief Compare signed values - * - * \param X Left-hand MPI - * \param Y Right-hand MPI - * - * \return 1 if X is greater than Y, - * -1 if X is lesser than Y or - * 0 if X is equal to Y - */ -int mpi_cmp_mpi( const mpi *X, const mpi *Y ); - -/** - * \brief Compare signed values - * - * \param X Left-hand MPI - * \param z The integer value to compare to - * - * \return 1 if X is greater than z, - * -1 if X is lesser than z or - * 0 if X is equal to z - */ -int mpi_cmp_int( const mpi *X, t_sint z ); - -/** - * \brief Unsigned addition: X = |A| + |B| - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_add_abs( mpi *X, const mpi *A, const mpi *B ); - -/** - * \brief Unsigned substraction: X = |A| - |B| - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B is greater than A - */ -int mpi_sub_abs( mpi *X, const mpi *A, const mpi *B ); - -/** - * \brief Signed addition: X = A + B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_add_mpi( mpi *X, const mpi *A, const mpi *B ); - -/** - * \brief Signed substraction: X = A - B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_sub_mpi( mpi *X, const mpi *A, const mpi *B ); - -/** - * \brief Signed addition: X = A + b - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to add - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_add_int( mpi *X, const mpi *A, t_sint b ); - -/** - * \brief Signed substraction: X = A - b - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to subtract - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_sub_int( mpi *X, const mpi *A, t_sint b ); - -/** - * \brief Baseline multiplication: X = A * B - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_mul_mpi( mpi *X, const mpi *A, const mpi *B ); - -/** - * \brief Baseline multiplication: X = A * b - * Note: b is an unsigned integer type, thus - * Negative values of b are ignored. - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param b The integer value to multiply with - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_mul_int( mpi *X, const mpi *A, t_sint b ); - -/** - * \brief Division by mpi: A = Q * B + R - * - * \param Q Destination MPI for the quotient - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0 - * - * \note Either Q or R can be NULL. - */ -int mpi_div_mpi( mpi *Q, mpi *R, const mpi *A, const mpi *B ); - -/** - * \brief Division by int: A = Q * b + R - * - * \param Q Destination MPI for the quotient - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param b Integer to divide by - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0 - * - * \note Either Q or R can be NULL. - */ -int mpi_div_int( mpi *Q, mpi *R, const mpi *A, t_sint b ); - -/** - * \brief Modulo: R = A mod B - * - * \param R Destination MPI for the rest value - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if B == 0, - * POLARSSL_ERR_MPI_NEGATIVE_VALUE if B < 0 - */ -int mpi_mod_mpi( mpi *R, const mpi *A, const mpi *B ); - -/** - * \brief Modulo: r = A mod b - * - * \param r Destination t_uint - * \param A Left-hand MPI - * \param b Integer to divide by - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_DIVISION_BY_ZERO if b == 0, - * POLARSSL_ERR_MPI_NEGATIVE_VALUE if b < 0 - */ -int mpi_mod_int( t_uint *r, const mpi *A, t_sint b ); - -/** - * \brief Sliding-window exponentiation: X = A^E mod N - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param E Exponent MPI - * \param N Modular MPI - * \param _RR Speed-up MPI used for recalculations - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or even or if - * E is negative - * - * \note _RR is used to avoid re-computing R*R mod N across - * multiple calls, which speeds up things a bit. It can - * be set to NULL if the extra performance is unneeded. - */ -int mpi_exp_mod( mpi *X, const mpi *A, const mpi *E, const mpi *N, mpi *_RR ); - -/** - * \brief Fill an MPI X with size bytes of random - * - * \param X Destination MPI - * \param size Size in bytes - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_fill_random( mpi *X, size_t size, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Greatest common divisor: G = gcd(A, B) - * - * \param G Destination MPI - * \param A Left-hand MPI - * \param B Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed - */ -int mpi_gcd( mpi *G, const mpi *A, const mpi *B ); - -/** - * \brief Modular inverse: X = A^-1 mod N - * - * \param X Destination MPI - * \param A Left-hand MPI - * \param N Right-hand MPI - * - * \return 0 if successful, - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_BAD_INPUT_DATA if N is negative or nil - POLARSSL_ERR_MPI_NOT_ACCEPTABLE if A has no inverse mod N - */ -int mpi_inv_mod( mpi *X, const mpi *A, const mpi *N ); - -/** - * \brief Miller-Rabin primality test - * - * \param X MPI to check - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful (probably prime), - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_NOT_ACCEPTABLE if X is not prime - */ -int mpi_is_prime( mpi *X, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Prime number generation - * - * \param X Destination MPI - * \param nbits Required size of X in bits ( 3 <= nbits <= POLARSSL_MPI_MAX_BITS ) - * \param dh_flag If 1, then (X-1)/2 will be prime too - * \param f_rng RNG function - * \param p_rng RNG parameter - * - * \return 0 if successful (probably prime), - * POLARSSL_ERR_MPI_MALLOC_FAILED if memory allocation failed, - * POLARSSL_ERR_MPI_BAD_INPUT_DATA if nbits is < 3 - */ -int mpi_gen_prime( mpi *X, size_t nbits, int dh_flag, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int mpi_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* bignum.h */ diff --git a/common/polarssl/bn_mul.h b/common/polarssl/bn_mul.h deleted file mode 100644 index 1c2da136a..000000000 --- a/common/polarssl/bn_mul.h +++ /dev/null @@ -1,864 +0,0 @@ -/** - * \file bn_mul.h - * - * \brief Multi-precision integer library - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * 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. - */ -/* - * Multiply source vector [s] with b, add result - * to destination vector [d] and set carry c. - * - * Currently supports: - * - * . IA-32 (386+) . AMD64 / EM64T - * . IA-32 (SSE2) . Motorola 68000 - * . PowerPC, 32-bit . MicroBlaze - * . PowerPC, 64-bit . TriCore - * . SPARC v8 . ARM v3+ - * . Alpha . MIPS32 - * . C, longlong . C, generic - */ -#ifndef POLARSSL_BN_MUL_H -#define POLARSSL_BN_MUL_H - -#include "bignum.h" - -#if defined(POLARSSL_HAVE_ASM) - -#if defined(__GNUC__) -#if defined(__i386__) - -#define MULADDC_INIT \ - asm( " \ - movl %%ebx, %0; \ - movl %5, %%esi; \ - movl %6, %%edi; \ - movl %7, %%ecx; \ - movl %8, %%ebx; \ - " - -#define MULADDC_CORE \ - " \ - lodsl; \ - mull %%ebx; \ - addl %%ecx, %%eax; \ - adcl $0, %%edx; \ - addl (%%edi), %%eax; \ - adcl $0, %%edx; \ - movl %%edx, %%ecx; \ - stosl; \ - " - -#if defined(POLARSSL_HAVE_SSE2) - -#define MULADDC_HUIT \ - " \ - movd %%ecx, %%mm1; \ - movd %%ebx, %%mm0; \ - movd (%%edi), %%mm3; \ - paddq %%mm3, %%mm1; \ - movd (%%esi), %%mm2; \ - pmuludq %%mm0, %%mm2; \ - movd 4(%%esi), %%mm4; \ - pmuludq %%mm0, %%mm4; \ - movd 8(%%esi), %%mm6; \ - pmuludq %%mm0, %%mm6; \ - movd 12(%%esi), %%mm7; \ - pmuludq %%mm0, %%mm7; \ - paddq %%mm2, %%mm1; \ - movd 4(%%edi), %%mm3; \ - paddq %%mm4, %%mm3; \ - movd 8(%%edi), %%mm5; \ - paddq %%mm6, %%mm5; \ - movd 12(%%edi), %%mm4; \ - paddq %%mm4, %%mm7; \ - movd %%mm1, (%%edi); \ - movd 16(%%esi), %%mm2; \ - pmuludq %%mm0, %%mm2; \ - psrlq $32, %%mm1; \ - movd 20(%%esi), %%mm4; \ - pmuludq %%mm0, %%mm4; \ - paddq %%mm3, %%mm1; \ - movd 24(%%esi), %%mm6; \ - pmuludq %%mm0, %%mm6; \ - movd %%mm1, 4(%%edi); \ - psrlq $32, %%mm1; \ - movd 28(%%esi), %%mm3; \ - pmuludq %%mm0, %%mm3; \ - paddq %%mm5, %%mm1; \ - movd 16(%%edi), %%mm5; \ - paddq %%mm5, %%mm2; \ - movd %%mm1, 8(%%edi); \ - psrlq $32, %%mm1; \ - paddq %%mm7, %%mm1; \ - movd 20(%%edi), %%mm5; \ - paddq %%mm5, %%mm4; \ - movd %%mm1, 12(%%edi); \ - psrlq $32, %%mm1; \ - paddq %%mm2, %%mm1; \ - movd 24(%%edi), %%mm5; \ - paddq %%mm5, %%mm6; \ - movd %%mm1, 16(%%edi); \ - psrlq $32, %%mm1; \ - paddq %%mm4, %%mm1; \ - movd 28(%%edi), %%mm5; \ - paddq %%mm5, %%mm3; \ - movd %%mm1, 20(%%edi); \ - psrlq $32, %%mm1; \ - paddq %%mm6, %%mm1; \ - movd %%mm1, 24(%%edi); \ - psrlq $32, %%mm1; \ - paddq %%mm3, %%mm1; \ - movd %%mm1, 28(%%edi); \ - addl $32, %%edi; \ - addl $32, %%esi; \ - psrlq $32, %%mm1; \ - movd %%mm1, %%ecx; \ - " - -#define MULADDC_STOP \ - " \ - emms; \ - movl %4, %%ebx; \ - movl %%ecx, %1; \ - movl %%edi, %2; \ - movl %%esi, %3; \ - " \ - : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ - : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ - ); - -#else - -#define MULADDC_STOP \ - " \ - movl %4, %%ebx; \ - movl %%ecx, %1; \ - movl %%edi, %2; \ - movl %%esi, %3; \ - " \ - : "=m" (t), "=m" (c), "=m" (d), "=m" (s) \ - : "m" (t), "m" (s), "m" (d), "m" (c), "m" (b) \ - : "eax", "ecx", "edx", "esi", "edi" \ - ); -#endif /* SSE2 */ -#endif /* i386 */ - -#if defined(__amd64__) || defined (__x86_64__) - -#define MULADDC_INIT \ - asm( "movq %0, %%rsi " :: "m" (s)); \ - asm( "movq %0, %%rdi " :: "m" (d)); \ - asm( "movq %0, %%rcx " :: "m" (c)); \ - asm( "movq %0, %%rbx " :: "m" (b)); \ - asm( "xorq %r8, %r8 " ); - -#define MULADDC_CORE \ - asm( "movq (%rsi),%rax " ); \ - asm( "mulq %rbx " ); \ - asm( "addq $8, %rsi " ); \ - asm( "addq %rcx, %rax " ); \ - asm( "movq %r8, %rcx " ); \ - asm( "adcq $0, %rdx " ); \ - asm( "nop " ); \ - asm( "addq %rax, (%rdi) " ); \ - asm( "adcq %rdx, %rcx " ); \ - asm( "addq $8, %rdi " ); - -#define MULADDC_STOP \ - asm( "movq %%rcx, %0 " : "=m" (c)); \ - asm( "movq %%rdi, %0 " : "=m" (d)); \ - asm( "movq %%rsi, %0 " : "=m" (s) :: \ - "rax", "rcx", "rdx", "rbx", "rsi", "rdi", "r8" ); - -#endif /* AMD64 */ - -#if defined(__mc68020__) || defined(__mcpu32__) - -#define MULADDC_INIT \ - asm( "movl %0, %%a2 " :: "m" (s)); \ - asm( "movl %0, %%a3 " :: "m" (d)); \ - asm( "movl %0, %%d3 " :: "m" (c)); \ - asm( "movl %0, %%d2 " :: "m" (b)); \ - asm( "moveq #0, %d0 " ); - -#define MULADDC_CORE \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d4:%d1 " ); \ - asm( "addl %d3, %d1 " ); \ - asm( "addxl %d0, %d4 " ); \ - asm( "moveq #0, %d3 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "addxl %d4, %d3 " ); - -#define MULADDC_STOP \ - asm( "movl %%d3, %0 " : "=m" (c)); \ - asm( "movl %%a3, %0 " : "=m" (d)); \ - asm( "movl %%a2, %0 " : "=m" (s) :: \ - "d0", "d1", "d2", "d3", "d4", "a2", "a3" ); - -#define MULADDC_HUIT \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d4:%d1 " ); \ - asm( "addxl %d3, %d1 " ); \ - asm( "addxl %d0, %d4 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d3:%d1 " ); \ - asm( "addxl %d4, %d1 " ); \ - asm( "addxl %d0, %d3 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d4:%d1 " ); \ - asm( "addxl %d3, %d1 " ); \ - asm( "addxl %d0, %d4 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d3:%d1 " ); \ - asm( "addxl %d4, %d1 " ); \ - asm( "addxl %d0, %d3 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d4:%d1 " ); \ - asm( "addxl %d3, %d1 " ); \ - asm( "addxl %d0, %d4 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d3:%d1 " ); \ - asm( "addxl %d4, %d1 " ); \ - asm( "addxl %d0, %d3 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d4:%d1 " ); \ - asm( "addxl %d3, %d1 " ); \ - asm( "addxl %d0, %d4 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "movel %a2@+, %d1 " ); \ - asm( "mulul %d2, %d3:%d1 " ); \ - asm( "addxl %d4, %d1 " ); \ - asm( "addxl %d0, %d3 " ); \ - asm( "addl %d1, %a3@+ " ); \ - asm( "addxl %d0, %d3 " ); - -#endif /* MC68000 */ - -#if defined(__powerpc__) || defined(__ppc__) -#if defined(__powerpc64__) || defined(__ppc64__) - -#if defined(__MACH__) && defined(__APPLE__) - -#define MULADDC_INIT \ - asm( "ld r3, %0 " :: "m" (s)); \ - asm( "ld r4, %0 " :: "m" (d)); \ - asm( "ld r5, %0 " :: "m" (c)); \ - asm( "ld r6, %0 " :: "m" (b)); \ - asm( "addi r3, r3, -8 " ); \ - asm( "addi r4, r4, -8 " ); \ - asm( "addic r5, r5, 0 " ); - -#define MULADDC_CORE \ - asm( "ldu r7, 8(r3) " ); \ - asm( "mulld r8, r7, r6 " ); \ - asm( "mulhdu r9, r7, r6 " ); \ - asm( "adde r8, r8, r5 " ); \ - asm( "ld r7, 8(r4) " ); \ - asm( "addze r5, r9 " ); \ - asm( "addc r8, r8, r7 " ); \ - asm( "stdu r8, 8(r4) " ); - -#define MULADDC_STOP \ - asm( "addze r5, r5 " ); \ - asm( "addi r4, r4, 8 " ); \ - asm( "addi r3, r3, 8 " ); \ - asm( "std r5, %0 " : "=m" (c)); \ - asm( "std r4, %0 " : "=m" (d)); \ - asm( "std r3, %0 " : "=m" (s) :: \ - "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); - -#else - -#define MULADDC_INIT \ - asm( "ld %%r3, %0 " :: "m" (s)); \ - asm( "ld %%r4, %0 " :: "m" (d)); \ - asm( "ld %%r5, %0 " :: "m" (c)); \ - asm( "ld %%r6, %0 " :: "m" (b)); \ - asm( "addi %r3, %r3, -8 " ); \ - asm( "addi %r4, %r4, -8 " ); \ - asm( "addic %r5, %r5, 0 " ); - -#define MULADDC_CORE \ - asm( "ldu %r7, 8(%r3) " ); \ - asm( "mulld %r8, %r7, %r6 " ); \ - asm( "mulhdu %r9, %r7, %r6 " ); \ - asm( "adde %r8, %r8, %r5 " ); \ - asm( "ld %r7, 8(%r4) " ); \ - asm( "addze %r5, %r9 " ); \ - asm( "addc %r8, %r8, %r7 " ); \ - asm( "stdu %r8, 8(%r4) " ); - -#define MULADDC_STOP \ - asm( "addze %r5, %r5 " ); \ - asm( "addi %r4, %r4, 8 " ); \ - asm( "addi %r3, %r3, 8 " ); \ - asm( "std %%r5, %0 " : "=m" (c)); \ - asm( "std %%r4, %0 " : "=m" (d)); \ - asm( "std %%r3, %0 " : "=m" (s) :: \ - "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); - -#endif - -#else /* PPC32 */ - -#if defined(__MACH__) && defined(__APPLE__) - -#define MULADDC_INIT \ - asm( "lwz r3, %0 " :: "m" (s)); \ - asm( "lwz r4, %0 " :: "m" (d)); \ - asm( "lwz r5, %0 " :: "m" (c)); \ - asm( "lwz r6, %0 " :: "m" (b)); \ - asm( "addi r3, r3, -4 " ); \ - asm( "addi r4, r4, -4 " ); \ - asm( "addic r5, r5, 0 " ); - -#define MULADDC_CORE \ - asm( "lwzu r7, 4(r3) " ); \ - asm( "mullw r8, r7, r6 " ); \ - asm( "mulhwu r9, r7, r6 " ); \ - asm( "adde r8, r8, r5 " ); \ - asm( "lwz r7, 4(r4) " ); \ - asm( "addze r5, r9 " ); \ - asm( "addc r8, r8, r7 " ); \ - asm( "stwu r8, 4(r4) " ); - -#define MULADDC_STOP \ - asm( "addze r5, r5 " ); \ - asm( "addi r4, r4, 4 " ); \ - asm( "addi r3, r3, 4 " ); \ - asm( "stw r5, %0 " : "=m" (c)); \ - asm( "stw r4, %0 " : "=m" (d)); \ - asm( "stw r3, %0 " : "=m" (s) :: \ - "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); - -#else - -#define MULADDC_INIT \ - asm( "lwz %%r3, %0 " :: "m" (s)); \ - asm( "lwz %%r4, %0 " :: "m" (d)); \ - asm( "lwz %%r5, %0 " :: "m" (c)); \ - asm( "lwz %%r6, %0 " :: "m" (b)); \ - asm( "addi %r3, %r3, -4 " ); \ - asm( "addi %r4, %r4, -4 " ); \ - asm( "addic %r5, %r5, 0 " ); - -#define MULADDC_CORE \ - asm( "lwzu %r7, 4(%r3) " ); \ - asm( "mullw %r8, %r7, %r6 " ); \ - asm( "mulhwu %r9, %r7, %r6 " ); \ - asm( "adde %r8, %r8, %r5 " ); \ - asm( "lwz %r7, 4(%r4) " ); \ - asm( "addze %r5, %r9 " ); \ - asm( "addc %r8, %r8, %r7 " ); \ - asm( "stwu %r8, 4(%r4) " ); - -#define MULADDC_STOP \ - asm( "addze %r5, %r5 " ); \ - asm( "addi %r4, %r4, 4 " ); \ - asm( "addi %r3, %r3, 4 " ); \ - asm( "stw %%r5, %0 " : "=m" (c)); \ - asm( "stw %%r4, %0 " : "=m" (d)); \ - asm( "stw %%r3, %0 " : "=m" (s) :: \ - "r3", "r4", "r5", "r6", "r7", "r8", "r9" ); - -#endif - -#endif /* PPC32 */ -#endif /* PPC64 */ - -#if defined(__sparc__) && defined(__sparc64__) - -#define MULADDC_INIT \ - asm( \ - " \ - ldx %3, %%o0; \ - ldx %4, %%o1; \ - ld %5, %%o2; \ - ld %6, %%o3; \ - " - -#define MULADDC_CORE \ - " \ - ld [%%o0], %%o4; \ - inc 4, %%o0; \ - ld [%%o1], %%o5; \ - umul %%o3, %%o4, %%o4; \ - addcc %%o4, %%o2, %%o4; \ - rd %%y, %%g1; \ - addx %%g1, 0, %%g1; \ - addcc %%o4, %%o5, %%o4; \ - st %%o4, [%%o1]; \ - addx %%g1, 0, %%o2; \ - inc 4, %%o1; \ - " - -#define MULADDC_STOP \ - " \ - st %%o2, %0; \ - stx %%o1, %1; \ - stx %%o0, %2; \ - " \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "g1", "o0", "o1", "o2", "o3", "o4", \ - "o5" \ - ); -#endif /* SPARCv9 */ - -#if defined(__sparc__) && !defined(__sparc64__) - -#define MULADDC_INIT \ - asm( \ - " \ - ld %3, %%o0; \ - ld %4, %%o1; \ - ld %5, %%o2; \ - ld %6, %%o3; \ - " - -#define MULADDC_CORE \ - " \ - ld [%%o0], %%o4; \ - inc 4, %%o0; \ - ld [%%o1], %%o5; \ - umul %%o3, %%o4, %%o4; \ - addcc %%o4, %%o2, %%o4; \ - rd %%y, %%g1; \ - addx %%g1, 0, %%g1; \ - addcc %%o4, %%o5, %%o4; \ - st %%o4, [%%o1]; \ - addx %%g1, 0, %%o2; \ - inc 4, %%o1; \ - " - -#define MULADDC_STOP \ - " \ - st %%o2, %0; \ - st %%o1, %1; \ - st %%o0, %2; \ - " \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "g1", "o0", "o1", "o2", "o3", "o4", \ - "o5" \ - ); - -#endif /* SPARCv8 */ - -#if defined(__microblaze__) || defined(microblaze) - -#define MULADDC_INIT \ - asm( "lwi r3, %0 " :: "m" (s)); \ - asm( "lwi r4, %0 " :: "m" (d)); \ - asm( "lwi r5, %0 " :: "m" (c)); \ - asm( "lwi r6, %0 " :: "m" (b)); \ - asm( "andi r7, r6, 0xffff" ); \ - asm( "bsrli r6, r6, 16 " ); - -#define MULADDC_CORE \ - asm( "lhui r8, r3, 0 " ); \ - asm( "addi r3, r3, 2 " ); \ - asm( "lhui r9, r3, 0 " ); \ - asm( "addi r3, r3, 2 " ); \ - asm( "mul r10, r9, r6 " ); \ - asm( "mul r11, r8, r7 " ); \ - asm( "mul r12, r9, r7 " ); \ - asm( "mul r13, r8, r6 " ); \ - asm( "bsrli r8, r10, 16 " ); \ - asm( "bsrli r9, r11, 16 " ); \ - asm( "add r13, r13, r8 " ); \ - asm( "add r13, r13, r9 " ); \ - asm( "bslli r10, r10, 16 " ); \ - asm( "bslli r11, r11, 16 " ); \ - asm( "add r12, r12, r10 " ); \ - asm( "addc r13, r13, r0 " ); \ - asm( "add r12, r12, r11 " ); \ - asm( "addc r13, r13, r0 " ); \ - asm( "lwi r10, r4, 0 " ); \ - asm( "add r12, r12, r10 " ); \ - asm( "addc r13, r13, r0 " ); \ - asm( "add r12, r12, r5 " ); \ - asm( "addc r5, r13, r0 " ); \ - asm( "swi r12, r4, 0 " ); \ - asm( "addi r4, r4, 4 " ); - -#define MULADDC_STOP \ - asm( "swi r5, %0 " : "=m" (c)); \ - asm( "swi r4, %0 " : "=m" (d)); \ - asm( "swi r3, %0 " : "=m" (s) :: \ - "r3", "r4" , "r5" , "r6" , "r7" , "r8" , \ - "r9", "r10", "r11", "r12", "r13" ); - -#endif /* MicroBlaze */ - -#if defined(__tricore__) - -#define MULADDC_INIT \ - asm( "ld.a %%a2, %0 " :: "m" (s)); \ - asm( "ld.a %%a3, %0 " :: "m" (d)); \ - asm( "ld.w %%d4, %0 " :: "m" (c)); \ - asm( "ld.w %%d1, %0 " :: "m" (b)); \ - asm( "xor %d5, %d5 " ); - -#define MULADDC_CORE \ - asm( "ld.w %d0, [%a2+] " ); \ - asm( "madd.u %e2, %e4, %d0, %d1 " ); \ - asm( "ld.w %d0, [%a3] " ); \ - asm( "addx %d2, %d2, %d0 " ); \ - asm( "addc %d3, %d3, 0 " ); \ - asm( "mov %d4, %d3 " ); \ - asm( "st.w [%a3+], %d2 " ); - -#define MULADDC_STOP \ - asm( "st.w %0, %%d4 " : "=m" (c)); \ - asm( "st.a %0, %%a3 " : "=m" (d)); \ - asm( "st.a %0, %%a2 " : "=m" (s) :: \ - "d0", "d1", "e2", "d4", "a2", "a3" ); - -#endif /* TriCore */ - -#if defined(__arm__) - -#if defined(__thumb__) && !defined(__thumb2__) - -#define MULADDC_INIT \ - asm( \ - " \ - ldr r0, %3; \ - ldr r1, %4; \ - ldr r2, %5; \ - ldr r3, %6; \ - lsr r7, r3, #16; \ - mov r9, r7; \ - lsl r7, r3, #16; \ - lsr r7, r7, #16; \ - mov r8, r7; \ - " - -#define MULADDC_CORE \ - " \ - ldmia r0!, {r6}; \ - lsr r7, r6, #16; \ - lsl r6, r6, #16; \ - lsr r6, r6, #16; \ - mov r4, r8; \ - mul r4, r6; \ - mov r3, r9; \ - mul r6, r3; \ - mov r5, r9; \ - mul r5, r7; \ - mov r3, r8; \ - mul r7, r3; \ - lsr r3, r6, #16; \ - add r5, r5, r3; \ - lsr r3, r7, #16; \ - add r5, r5, r3; \ - add r4, r4, r2; \ - mov r2, #0; \ - adc r5, r2; \ - lsl r3, r6, #16; \ - add r4, r4, r3; \ - adc r5, r2; \ - lsl r3, r7, #16; \ - add r4, r4, r3; \ - adc r5, r2; \ - ldr r3, [r1]; \ - add r4, r4, r3; \ - adc r2, r5; \ - stmia r1!, {r4}; \ - " - -#define MULADDC_STOP \ - " \ - str r2, %0; \ - str r1, %1; \ - str r0, %2; \ - " \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r0", "r1", "r2", "r3", "r4", "r5", \ - "r6", "r7", "r8", "r9", "cc" \ - ); - -#else - -#define MULADDC_INIT \ - asm( \ - " \ - ldr r0, %3; \ - ldr r1, %4; \ - ldr r2, %5; \ - ldr r3, %6; \ - " - -#define MULADDC_CORE \ - " \ - ldr r4, [r0], #4; \ - mov r5, #0; \ - ldr r6, [r1]; \ - umlal r2, r5, r3, r4; \ - adds r7, r6, r2; \ - adc r2, r5, #0; \ - str r7, [r1], #4; \ - " - -#define MULADDC_STOP \ - " \ - str r2, %0; \ - str r1, %1; \ - str r0, %2; \ - " \ - : "=m" (c), "=m" (d), "=m" (s) \ - : "m" (s), "m" (d), "m" (c), "m" (b) \ - : "r0", "r1", "r2", "r3", "r4", "r5", \ - "r6", "r7", "cc" \ - ); - -#endif /* Thumb */ - -#endif /* ARMv3 */ - -#if defined(__alpha__) - -#define MULADDC_INIT \ - asm( "ldq $1, %0 " :: "m" (s)); \ - asm( "ldq $2, %0 " :: "m" (d)); \ - asm( "ldq $3, %0 " :: "m" (c)); \ - asm( "ldq $4, %0 " :: "m" (b)); - -#define MULADDC_CORE \ - asm( "ldq $6, 0($1) " ); \ - asm( "addq $1, 8, $1 " ); \ - asm( "mulq $6, $4, $7 " ); \ - asm( "umulh $6, $4, $6 " ); \ - asm( "addq $7, $3, $7 " ); \ - asm( "cmpult $7, $3, $3 " ); \ - asm( "ldq $5, 0($2) " ); \ - asm( "addq $7, $5, $7 " ); \ - asm( "cmpult $7, $5, $5 " ); \ - asm( "stq $7, 0($2) " ); \ - asm( "addq $2, 8, $2 " ); \ - asm( "addq $6, $3, $3 " ); \ - asm( "addq $5, $3, $3 " ); - -#define MULADDC_STOP \ - asm( "stq $3, %0 " : "=m" (c)); \ - asm( "stq $2, %0 " : "=m" (d)); \ - asm( "stq $1, %0 " : "=m" (s) :: \ - "$1", "$2", "$3", "$4", "$5", "$6", "$7" ); - -#endif /* Alpha */ - -#if defined(__mips__) - -#define MULADDC_INIT \ - asm( "lw $10, %0 " :: "m" (s)); \ - asm( "lw $11, %0 " :: "m" (d)); \ - asm( "lw $12, %0 " :: "m" (c)); \ - asm( "lw $13, %0 " :: "m" (b)); - -#define MULADDC_CORE \ - asm( "lw $14, 0($10) " ); \ - asm( "multu $13, $14 " ); \ - asm( "addi $10, $10, 4 " ); \ - asm( "mflo $14 " ); \ - asm( "mfhi $9 " ); \ - asm( "addu $14, $12, $14 " ); \ - asm( "lw $15, 0($11) " ); \ - asm( "sltu $12, $14, $12 " ); \ - asm( "addu $15, $14, $15 " ); \ - asm( "sltu $14, $15, $14 " ); \ - asm( "addu $12, $12, $9 " ); \ - asm( "sw $15, 0($11) " ); \ - asm( "addu $12, $12, $14 " ); \ - asm( "addi $11, $11, 4 " ); - -#define MULADDC_STOP \ - asm( "sw $12, %0 " : "=m" (c)); \ - asm( "sw $11, %0 " : "=m" (d)); \ - asm( "sw $10, %0 " : "=m" (s) :: \ - "$9", "$10", "$11", "$12", "$13", "$14", "$15" ); - -#endif /* MIPS */ -#endif /* GNUC */ - -#if (defined(_MSC_VER) && defined(_M_IX86)) || defined(__WATCOMC__) - -#define MULADDC_INIT \ - __asm mov esi, s \ - __asm mov edi, d \ - __asm mov ecx, c \ - __asm mov ebx, b - -#define MULADDC_CORE \ - __asm lodsd \ - __asm mul ebx \ - __asm add eax, ecx \ - __asm adc edx, 0 \ - __asm add eax, [edi] \ - __asm adc edx, 0 \ - __asm mov ecx, edx \ - __asm stosd - -#if defined(POLARSSL_HAVE_SSE2) - -#define EMIT __asm _emit - -#define MULADDC_HUIT \ - EMIT 0x0F EMIT 0x6E EMIT 0xC9 \ - EMIT 0x0F EMIT 0x6E EMIT 0xC3 \ - EMIT 0x0F EMIT 0x6E EMIT 0x1F \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x6E EMIT 0x16 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x04 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x08 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ - EMIT 0x0F EMIT 0x6E EMIT 0x7E EMIT 0x0C \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF8 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ - EMIT 0x0F EMIT 0x6E EMIT 0x5F EMIT 0x04 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xDC \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x08 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xEE \ - EMIT 0x0F EMIT 0x6E EMIT 0x67 EMIT 0x0C \ - EMIT 0x0F EMIT 0xD4 EMIT 0xFC \ - EMIT 0x0F EMIT 0x7E EMIT 0x0F \ - EMIT 0x0F EMIT 0x6E EMIT 0x56 EMIT 0x10 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD0 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x6E EMIT 0x66 EMIT 0x14 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xE0 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x6E EMIT 0x76 EMIT 0x18 \ - EMIT 0x0F EMIT 0xF4 EMIT 0xF0 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x04 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x6E EMIT 0x5E EMIT 0x1C \ - EMIT 0x0F EMIT 0xF4 EMIT 0xD8 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCD \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x10 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xD5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x08 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCF \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x14 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xE5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x0C \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCA \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x18 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xF5 \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x10 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCC \ - EMIT 0x0F EMIT 0x6E EMIT 0x6F EMIT 0x1C \ - EMIT 0x0F EMIT 0xD4 EMIT 0xDD \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x14 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCE \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x18 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0xD4 EMIT 0xCB \ - EMIT 0x0F EMIT 0x7E EMIT 0x4F EMIT 0x1C \ - EMIT 0x83 EMIT 0xC7 EMIT 0x20 \ - EMIT 0x83 EMIT 0xC6 EMIT 0x20 \ - EMIT 0x0F EMIT 0x73 EMIT 0xD1 EMIT 0x20 \ - EMIT 0x0F EMIT 0x7E EMIT 0xC9 - -#define MULADDC_STOP \ - EMIT 0x0F EMIT 0x77 \ - __asm mov c, ecx \ - __asm mov d, edi \ - __asm mov s, esi \ - -#else - -#define MULADDC_STOP \ - __asm mov c, ecx \ - __asm mov d, edi \ - __asm mov s, esi \ - -#endif /* SSE2 */ -#endif /* MSVC */ - -#endif /* POLARSSL_HAVE_ASM */ - -#if !defined(MULADDC_CORE) -#if defined(POLARSSL_HAVE_UDBL) - -#define MULADDC_INIT \ -{ \ - t_udbl r; \ - t_uint r0, r1; - -#define MULADDC_CORE \ - r = *(s++) * (t_udbl) b; \ - r0 = r; \ - r1 = r >> biL; \ - r0 += c; r1 += (r0 < c); \ - r0 += *d; r1 += (r0 < *d); \ - c = r1; *(d++) = r0; - -#define MULADDC_STOP \ -} - -#else -#define MULADDC_INIT \ -{ \ - t_uint s0, s1, b0, b1; \ - t_uint r0, r1, rx, ry; \ - b0 = ( b << biH ) >> biH; \ - b1 = ( b >> biH ); - -#define MULADDC_CORE \ - s0 = ( *s << biH ) >> biH; \ - s1 = ( *s >> biH ); s++; \ - rx = s0 * b1; r0 = s0 * b0; \ - ry = s1 * b0; r1 = s1 * b1; \ - r1 += ( rx >> biH ); \ - r1 += ( ry >> biH ); \ - rx <<= biH; ry <<= biH; \ - r0 += rx; r1 += (r0 < rx); \ - r0 += ry; r1 += (r0 < ry); \ - r0 += c; r1 += (r0 < c); \ - r0 += *d; r1 += (r0 < *d); \ - c = r1; *(d++) = r0; - -#define MULADDC_STOP \ -} - -#endif /* C (generic) */ -#endif /* C (longlong) */ - -#endif /* bn_mul.h */ diff --git a/common/polarssl/hmac_drbg.c b/common/polarssl/hmac_drbg.c deleted file mode 100644 index 5c4ee6def..000000000 --- a/common/polarssl/hmac_drbg.c +++ /dev/null @@ -1,533 +0,0 @@ -/* - * HMAC_DRBG implementation (NIST SP 800-90) - * - * 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. - */ - -/* - * The NIST SP 800-90A DRBGs are described in the following publication. - * http://csrc.nist.gov/publications/nistpubs/800-90A/SP800-90A.pdf - * References below are based on rev. 1 (January 2012). - */ - -#if !defined(MBEDTLS_CONFIG_FILE) -#include "mbedtls/config.h" -#else -#include MBEDTLS_CONFIG_FILE -#endif - -#if defined(MBEDTLS_HMAC_DRBG_C) - -#include "mbedtls/hmac_drbg.h" - -#include - -#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/polarssl/hmac_drbg.h b/common/polarssl/hmac_drbg.h deleted file mode 100644 index eeac3e320..000000000 --- a/common/polarssl/hmac_drbg.h +++ /dev/null @@ -1,300 +0,0 @@ -/** - * \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/polarssl/libpcrypto.c b/common/polarssl/libpcrypto.c deleted file mode 100644 index 0dea75fac..000000000 --- a/common/polarssl/libpcrypto.c +++ /dev/null @@ -1,78 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2018 Merlok -// Copyright (C) 2018 drHatson -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// crypto commands -//----------------------------------------------------------------------------- - -#include "polarssl/libpcrypto.h" -#include -#include - -// NIST Special Publication 800-38A Recommendation for block cipher modes of operation: methods and techniques, 2001. -int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){ - uint8_t iiv[16] = {0}; - if (iv) - memcpy(iiv, iv, 16); - - aes_context aes; - aes_init(&aes); - if (aes_setkey_enc(&aes, key, 128)) - return 1; - if (aes_crypt_cbc(&aes, AES_ENCRYPT, length, iiv, input, output)) - return 2; - aes_free(&aes); - - return 0; -} - -int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length){ - uint8_t iiv[16] = {0}; - if (iv) - memcpy(iiv, iv, 16); - - aes_context aes; - aes_init(&aes); - if (aes_setkey_dec(&aes, key, 128)) - return 1; - if (aes_crypt_cbc(&aes, AES_DECRYPT, length, iiv, input, output)) - return 2; - aes_free(&aes); - - return 0; -} - -// NIST Special Publication 800-38B Recommendation for block cipher modes of operation: The CMAC mode for authentication. -// https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf -int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length) { - memset(mac, 0x00, 16); - uint8_t iiv[16] = {0}; - if (iv) - memcpy(iiv, iv, 16); - - // NIST 800-38B - aes_cmac128_context ctx; - aes_cmac128_starts(&ctx, key); - aes_cmac128_update(&ctx, input, length); - aes_cmac128_final(&ctx, mac); - - return 0; -} - -int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length) { - uint8_t cmac[16] = {0}; - memset(mac, 0x00, 8); - - int res = aes_cmac(iv, key, input, cmac, length); - if (res) - return res; - - for(int i = 0; i < 8; i++) - mac[i] = cmac[i * 2 + 1]; - - return 0; -} diff --git a/common/polarssl/rsa.c b/common/polarssl/rsa.c deleted file mode 100644 index 9872274ba..000000000 --- a/common/polarssl/rsa.c +++ /dev/null @@ -1,1466 +0,0 @@ -/* - * The RSA public-key cryptosystem - * - * Copyright (C) 2006-2011, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * 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. - */ -/* - * RSA was designed by Ron Rivest, Adi Shamir and Len Adleman. - * - * http://theory.lcs.mit.edu/~rivest/rsapaper.pdf - * http://www.cacr.math.uwaterloo.ca/hac/about/chap8.pdf - */ - -#include "polarssl_config.h" - -#if defined(POLARSSL_RSA_C) - -#include "rsa.h" - -#if defined(POLARSSL_PKCS1_V21) -#include "md.h" -#endif - -#include -#include - -/* - * Initialize an RSA context - */ -void rsa_init( rsa_context *ctx, - int padding, - int hash_id ) -{ - memset( ctx, 0, sizeof( rsa_context ) ); - - ctx->padding = padding; - ctx->hash_id = hash_id; -} - -#if defined(POLARSSL_GENPRIME) - -/* - * Generate an RSA keypair - */ -int rsa_gen_key( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - unsigned int nbits, int exponent ) -{ - int ret; - mpi P1, Q1, H, G; - - if( f_rng == NULL || nbits < 128 || exponent < 3 ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - mpi_init( &P1 ); mpi_init( &Q1 ); mpi_init( &H ); mpi_init( &G ); - - /* - * find primes P and Q with Q < P so that: - * GCD( E, (P-1)*(Q-1) ) == 1 - */ - MPI_CHK( mpi_lset( &ctx->E, exponent ) ); - - do - { - MPI_CHK( mpi_gen_prime( &ctx->P, ( nbits + 1 ) >> 1, 0, - f_rng, p_rng ) ); - - MPI_CHK( mpi_gen_prime( &ctx->Q, ( nbits + 1 ) >> 1, 0, - f_rng, p_rng ) ); - - if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) < 0 ) - mpi_swap( &ctx->P, &ctx->Q ); - - if( mpi_cmp_mpi( &ctx->P, &ctx->Q ) == 0 ) - continue; - - MPI_CHK( mpi_mul_mpi( &ctx->N, &ctx->P, &ctx->Q ) ); - if( mpi_msb( &ctx->N ) != nbits ) - continue; - - MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); - MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); - MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); - MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); - } - while( mpi_cmp_int( &G, 1 ) != 0 ); - - /* - * D = E^-1 mod ((P-1)*(Q-1)) - * DP = D mod (P - 1) - * DQ = D mod (Q - 1) - * QP = Q^-1 mod P - */ - MPI_CHK( mpi_inv_mod( &ctx->D , &ctx->E, &H ) ); - MPI_CHK( mpi_mod_mpi( &ctx->DP, &ctx->D, &P1 ) ); - MPI_CHK( mpi_mod_mpi( &ctx->DQ, &ctx->D, &Q1 ) ); - MPI_CHK( mpi_inv_mod( &ctx->QP, &ctx->Q, &ctx->P ) ); - - ctx->len = ( mpi_msb( &ctx->N ) + 7 ) >> 3; - -cleanup: - - mpi_free( &P1 ); mpi_free( &Q1 ); mpi_free( &H ); mpi_free( &G ); - - if( ret != 0 ) - { - rsa_free( ctx ); - return( POLARSSL_ERR_RSA_KEY_GEN_FAILED + ret ); - } - - return( 0 ); -} - -#endif - -/* - * Check a public RSA key - */ -int rsa_check_pubkey( const rsa_context *ctx ) -{ - if( !ctx->N.p || !ctx->E.p ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); - - if( ( ctx->N.p[0] & 1 ) == 0 || - ( ctx->E.p[0] & 1 ) == 0 ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); - - if( mpi_msb( &ctx->N ) < 128 || - mpi_msb( &ctx->N ) > POLARSSL_MPI_MAX_BITS ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); - - if( mpi_msb( &ctx->E ) < 2 || - mpi_msb( &ctx->E ) > 64 ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); - - return( 0 ); -} - -/* - * Check a private RSA key - */ -int rsa_check_privkey( const rsa_context *ctx ) -{ - int ret; - mpi PQ, DE, P1, Q1, H, I, G, G2, L1, L2, DP, DQ, QP; - - if( ( ret = rsa_check_pubkey( ctx ) ) != 0 ) - return( ret ); - - if( !ctx->P.p || !ctx->Q.p || !ctx->D.p ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED ); - - mpi_init( &PQ ); mpi_init( &DE ); mpi_init( &P1 ); mpi_init( &Q1 ); - mpi_init( &H ); mpi_init( &I ); mpi_init( &G ); mpi_init( &G2 ); - mpi_init( &L1 ); mpi_init( &L2 ); mpi_init( &DP ); mpi_init( &DQ ); - mpi_init( &QP ); - - MPI_CHK( mpi_mul_mpi( &PQ, &ctx->P, &ctx->Q ) ); - MPI_CHK( mpi_mul_mpi( &DE, &ctx->D, &ctx->E ) ); - MPI_CHK( mpi_sub_int( &P1, &ctx->P, 1 ) ); - MPI_CHK( mpi_sub_int( &Q1, &ctx->Q, 1 ) ); - MPI_CHK( mpi_mul_mpi( &H, &P1, &Q1 ) ); - MPI_CHK( mpi_gcd( &G, &ctx->E, &H ) ); - - MPI_CHK( mpi_gcd( &G2, &P1, &Q1 ) ); - MPI_CHK( mpi_div_mpi( &L1, &L2, &H, &G2 ) ); - MPI_CHK( mpi_mod_mpi( &I, &DE, &L1 ) ); - - MPI_CHK( mpi_mod_mpi( &DP, &ctx->D, &P1 ) ); - MPI_CHK( mpi_mod_mpi( &DQ, &ctx->D, &Q1 ) ); - MPI_CHK( mpi_inv_mod( &QP, &ctx->Q, &ctx->P ) ); - /* - * Check for a valid PKCS1v2 private key - */ - if( mpi_cmp_mpi( &PQ, &ctx->N ) != 0 || - mpi_cmp_mpi( &DP, &ctx->DP ) != 0 || - mpi_cmp_mpi( &DQ, &ctx->DQ ) != 0 || - mpi_cmp_mpi( &QP, &ctx->QP ) != 0 || - mpi_cmp_int( &L2, 0 ) != 0 || - mpi_cmp_int( &I, 1 ) != 0 || - mpi_cmp_int( &G, 1 ) != 0 ) - { - ret = POLARSSL_ERR_RSA_KEY_CHECK_FAILED; - } - -cleanup: - mpi_free( &PQ ); mpi_free( &DE ); mpi_free( &P1 ); mpi_free( &Q1 ); - mpi_free( &H ); mpi_free( &I ); mpi_free( &G ); mpi_free( &G2 ); - mpi_free( &L1 ); mpi_free( &L2 ); mpi_free( &DP ); mpi_free( &DQ ); - mpi_free( &QP ); - - if( ret == POLARSSL_ERR_RSA_KEY_CHECK_FAILED ) - return( ret ); - - if( ret != 0 ) - return( POLARSSL_ERR_RSA_KEY_CHECK_FAILED + ret ); - - return( 0 ); -} - -/* - * Do an RSA public key operation - */ -int rsa_public( rsa_context *ctx, - const unsigned char *input, - unsigned char *output ) -{ - int ret; - size_t olen; - mpi T; - - mpi_init( &T ); - - MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); - - if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) - { - mpi_free( &T ); - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - - olen = ctx->len; - MPI_CHK( mpi_exp_mod( &T, &T, &ctx->E, &ctx->N, &ctx->RN ) ); - MPI_CHK( mpi_write_binary( &T, output, olen ) ); - -cleanup: - - mpi_free( &T ); - - if( ret != 0 ) - return( POLARSSL_ERR_RSA_PUBLIC_FAILED + ret ); - - return( 0 ); -} - -/* - * Do an RSA private key operation - */ -int rsa_private( rsa_context *ctx, - const unsigned char *input, - unsigned char *output ) -{ - int ret; - size_t olen; - mpi T, T1, T2; - - mpi_init( &T ); mpi_init( &T1 ); mpi_init( &T2 ); - - MPI_CHK( mpi_read_binary( &T, input, ctx->len ) ); - - if( mpi_cmp_mpi( &T, &ctx->N ) >= 0 ) - { - mpi_free( &T ); - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - -#if defined(POLARSSL_RSA_NO_CRT) - MPI_CHK( mpi_exp_mod( &T, &T, &ctx->D, &ctx->N, &ctx->RN ) ); -#else - /* - * faster decryption using the CRT - * - * T1 = input ^ dP mod P - * T2 = input ^ dQ mod Q - */ - MPI_CHK( mpi_exp_mod( &T1, &T, &ctx->DP, &ctx->P, &ctx->RP ) ); - MPI_CHK( mpi_exp_mod( &T2, &T, &ctx->DQ, &ctx->Q, &ctx->RQ ) ); - - /* - * T = (T1 - T2) * (Q^-1 mod P) mod P - */ - MPI_CHK( mpi_sub_mpi( &T, &T1, &T2 ) ); - MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->QP ) ); - MPI_CHK( mpi_mod_mpi( &T, &T1, &ctx->P ) ); - - /* - * output = T2 + T * Q - */ - MPI_CHK( mpi_mul_mpi( &T1, &T, &ctx->Q ) ); - MPI_CHK( mpi_add_mpi( &T, &T2, &T1 ) ); -#endif - - olen = ctx->len; - MPI_CHK( mpi_write_binary( &T, output, olen ) ); - -cleanup: - - mpi_free( &T ); mpi_free( &T1 ); mpi_free( &T2 ); - - if( ret != 0 ) - return( POLARSSL_ERR_RSA_PRIVATE_FAILED + ret ); - - return( 0 ); -} - -#if defined(POLARSSL_PKCS1_V21) -/** - * Generate and apply the MGF1 operation (from PKCS#1 v2.1) to a buffer. - * - * \param dst buffer to mask - * \param dlen length of destination buffer - * \param src source of the mask generation - * \param slen length of the source buffer - * \param md_ctx message digest context to use - */ -static void mgf_mask( unsigned char *dst, size_t dlen, unsigned char *src, size_t slen, - md_context_t *md_ctx ) -{ - unsigned char mask[POLARSSL_MD_MAX_SIZE]; - unsigned char counter[4]; - unsigned char *p; - unsigned int hlen; - size_t i, use_len; - - memset( mask, 0, POLARSSL_MD_MAX_SIZE ); - memset( counter, 0, 4 ); - - hlen = md_ctx->md_info->size; - - // Generate and apply dbMask - // - p = dst; - - while( dlen > 0 ) - { - use_len = hlen; - if( dlen < hlen ) - use_len = dlen; - - md_starts( md_ctx ); - md_update( md_ctx, src, slen ); - md_update( md_ctx, counter, 4 ); - md_finish( md_ctx, mask ); - - for( i = 0; i < use_len; ++i ) - *p++ ^= mask[i]; - - counter[3]++; - - dlen -= use_len; - } -} -#endif - -#if defined(POLARSSL_PKCS1_V21) -/* - * Implementation of the PKCS#1 v2.1 RSAES-OAEP-ENCRYPT function - */ -int rsa_rsaes_oaep_encrypt( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - const unsigned char *label, size_t label_len, - size_t ilen, - const unsigned char *input, - unsigned char *output ) -{ - size_t olen; - int ret; - unsigned char *p = output; - unsigned int hlen; - const md_info_t *md_info; - md_context_t md_ctx; - - if( ctx->padding != RSA_PKCS_V21 || f_rng == NULL ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - md_info = md_info_from_type( ctx->hash_id ); - - if( md_info == NULL ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - olen = ctx->len; - hlen = md_get_size( md_info ); - - if( olen < ilen + 2 * hlen + 2 || f_rng == NULL ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - memset( output, 0, olen ); - - *p++ = 0; - - // Generate a random octet string seed - // - if( ( ret = f_rng( p_rng, p, hlen ) ) != 0 ) - return( POLARSSL_ERR_RSA_RNG_FAILED + ret ); - - p += hlen; - - // Construct DB - // - md( md_info, label, label_len, p ); - p += hlen; - p += olen - 2 * hlen - 2 - ilen; - *p++ = 1; - memcpy( p, input, ilen ); - - md_init_ctx( &md_ctx, md_info ); - - // maskedDB: Apply dbMask to DB - // - mgf_mask( output + hlen + 1, olen - hlen - 1, output + 1, hlen, - &md_ctx ); - - // maskedSeed: Apply seedMask to seed - // - mgf_mask( output + 1, hlen, output + hlen + 1, olen - hlen - 1, - &md_ctx ); - - md_free_ctx( &md_ctx ); - - return( ( mode == RSA_PUBLIC ) - ? rsa_public( ctx, output, output ) - : rsa_private( ctx, output, output ) ); -} -#endif /* POLARSSL_PKCS1_V21 */ - -/* - * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-ENCRYPT function - */ -int rsa_rsaes_pkcs1_v15_encrypt( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, - const unsigned char *input, - unsigned char *output ) -{ - size_t nb_pad, olen; - int ret; - unsigned char *p = output; - - if( ctx->padding != RSA_PKCS_V15 || f_rng == NULL ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - olen = ctx->len; - - if( olen < ilen + 11 ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - nb_pad = olen - 3 - ilen; - - *p++ = 0; - if( mode == RSA_PUBLIC ) - { - *p++ = RSA_CRYPT; - - while( nb_pad-- > 0 ) - { - int rng_dl = 100; - - do { - ret = f_rng( p_rng, p, 1 ); - } while( *p == 0 && --rng_dl && ret == 0 ); - - // Check if RNG failed to generate data - // - if( rng_dl == 0 || ret != 0) - return POLARSSL_ERR_RSA_RNG_FAILED + ret; - - p++; - } - } - else - { - *p++ = RSA_SIGN; - - while( nb_pad-- > 0 ) - *p++ = 0xFF; - } - - *p++ = 0; - memcpy( p, input, ilen ); - - return( ( mode == RSA_PUBLIC ) - ? rsa_public( ctx, output, output ) - : rsa_private( ctx, output, output ) ); -} - -/* - * Add the message padding, then do an RSA operation - */ -int rsa_pkcs1_encrypt( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, - const unsigned char *input, - unsigned char *output ) -{ - switch( ctx->padding ) - { - case RSA_PKCS_V15: - return rsa_rsaes_pkcs1_v15_encrypt( ctx, f_rng, p_rng, mode, ilen, - input, output ); - -#if defined(POLARSSL_PKCS1_V21) - case RSA_PKCS_V21: - return rsa_rsaes_oaep_encrypt( ctx, f_rng, p_rng, mode, NULL, 0, - ilen, input, output ); -#endif - - default: - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - } -} - -#if defined(POLARSSL_PKCS1_V21) -/* - * Implementation of the PKCS#1 v2.1 RSAES-OAEP-DECRYPT function - */ -int rsa_rsaes_oaep_decrypt( rsa_context *ctx, - int mode, - const unsigned char *label, size_t label_len, - size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ) -{ - int ret; - size_t ilen; - unsigned char *p; - unsigned char buf[POLARSSL_MPI_MAX_SIZE]; - unsigned char lhash[POLARSSL_MD_MAX_SIZE]; - unsigned int hlen; - const md_info_t *md_info; - md_context_t md_ctx; - - if( ctx->padding != RSA_PKCS_V21 ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - ilen = ctx->len; - - if( ilen < 16 || ilen > sizeof( buf ) ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - ret = ( mode == RSA_PUBLIC ) - ? rsa_public( ctx, input, buf ) - : rsa_private( ctx, input, buf ); - - if( ret != 0 ) - return( ret ); - - p = buf; - - if( *p++ != 0 ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - md_info = md_info_from_type( ctx->hash_id ); - if( md_info == NULL ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - hlen = md_get_size( md_info ); - - md_init_ctx( &md_ctx, md_info ); - - // Generate lHash - // - md( md_info, label, label_len, lhash ); - - // seed: Apply seedMask to maskedSeed - // - mgf_mask( buf + 1, hlen, buf + hlen + 1, ilen - hlen - 1, - &md_ctx ); - - // DB: Apply dbMask to maskedDB - // - mgf_mask( buf + hlen + 1, ilen - hlen - 1, buf + 1, hlen, - &md_ctx ); - - p += hlen; - md_free_ctx( &md_ctx ); - - // Check validity - // - if( memcmp( lhash, p, hlen ) != 0 ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - p += hlen; - - while( *p == 0 && p < buf + ilen ) - p++; - - if( p == buf + ilen ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - if( *p++ != 0x01 ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - if (ilen - (p - buf) > output_max_len) - return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); - - *olen = ilen - (p - buf); - memcpy( output, p, *olen ); - - return( 0 ); -} -#endif /* POLARSSL_PKCS1_V21 */ - -/* - * Implementation of the PKCS#1 v2.1 RSAES-PKCS1-V1_5-DECRYPT function - */ -int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len) -{ - int ret, correct = 1; - size_t ilen, pad_count = 0; - unsigned char *p, *q; - unsigned char bt; - unsigned char buf[POLARSSL_MPI_MAX_SIZE]; - - if( ctx->padding != RSA_PKCS_V15 ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - ilen = ctx->len; - - if( ilen < 16 || ilen > sizeof( buf ) ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - ret = ( mode == RSA_PUBLIC ) - ? rsa_public( ctx, input, buf ) - : rsa_private( ctx, input, buf ); - - if( ret != 0 ) - return( ret ); - - p = buf; - - if( *p++ != 0 ) - correct = 0; - - bt = *p++; - if( ( bt != RSA_CRYPT && mode == RSA_PRIVATE ) || - ( bt != RSA_SIGN && mode == RSA_PUBLIC ) ) - { - correct = 0; - } - - if( bt == RSA_CRYPT ) - { - while( *p != 0 && p < buf + ilen - 1 ) - pad_count += ( *p++ != 0 ); - - correct &= ( *p == 0 && p < buf + ilen - 1 ); - - q = p; - - // Also pass over all other bytes to reduce timing differences - // - while ( q < buf + ilen - 1 ) - pad_count += ( *q++ != 0 ); - - // Prevent compiler optimization of pad_count - // - correct |= pad_count & 0x100000; /* Always 0 unless 1M bit keys */ - p++; - } - else - { - while( *p == 0xFF && p < buf + ilen - 1 ) - pad_count += ( *p++ == 0xFF ); - - correct &= ( *p == 0 && p < buf + ilen - 1 ); - - q = p; - - // Also pass over all other bytes to reduce timing differences - // - while ( q < buf + ilen - 1 ) - pad_count += ( *q++ != 0 ); - - // Prevent compiler optimization of pad_count - // - correct |= pad_count & 0x100000; /* Always 0 unless 1M bit keys */ - p++; - } - - if( correct == 0 ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - if (ilen - (p - buf) > output_max_len) - return( POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE ); - - *olen = ilen - (p - buf); - memcpy( output, p, *olen ); - - return( 0 ); -} - -/* - * Do an RSA operation, then remove the message padding - */ -int rsa_pkcs1_decrypt( rsa_context *ctx, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len) -{ - switch( ctx->padding ) - { - case RSA_PKCS_V15: - return rsa_rsaes_pkcs1_v15_decrypt( ctx, mode, olen, input, output, - output_max_len ); - -#if defined(POLARSSL_PKCS1_V21) - case RSA_PKCS_V21: - return rsa_rsaes_oaep_decrypt( ctx, mode, NULL, 0, olen, input, - output, output_max_len ); -#endif - - default: - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - } -} - -#if defined(POLARSSL_PKCS1_V21) -/* - * Implementation of the PKCS#1 v2.1 RSASSA-PSS-SIGN function - */ -int rsa_rsassa_pss_sign( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - size_t olen; - unsigned char *p = sig; - unsigned char salt[POLARSSL_MD_MAX_SIZE]; - unsigned int slen, hlen, offset = 0; - int ret; - size_t msb; - const md_info_t *md_info; - md_context_t md_ctx; - - if( ctx->padding != RSA_PKCS_V21 || f_rng == NULL ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - olen = ctx->len; - - switch( hash_id ) - { - case SIG_RSA_MD2: - case SIG_RSA_MD4: - case SIG_RSA_MD5: - hashlen = 16; - break; - - case SIG_RSA_SHA1: - hashlen = 20; - break; - - case SIG_RSA_SHA224: - hashlen = 28; - break; - - case SIG_RSA_SHA256: - hashlen = 32; - break; - - case SIG_RSA_SHA384: - hashlen = 48; - break; - - case SIG_RSA_SHA512: - hashlen = 64; - break; - - default: - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - - md_info = md_info_from_type( ctx->hash_id ); - if( md_info == NULL ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - hlen = md_get_size( md_info ); - slen = hlen; - - if( olen < hlen + slen + 2 ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - memset( sig, 0, olen ); - - msb = mpi_msb( &ctx->N ) - 1; - - // Generate salt of length slen - // - if( ( ret = f_rng( p_rng, salt, slen ) ) != 0 ) - return( POLARSSL_ERR_RSA_RNG_FAILED + ret ); - - // Note: EMSA-PSS encoding is over the length of N - 1 bits - // - msb = mpi_msb( &ctx->N ) - 1; - p += olen - hlen * 2 - 2; - *p++ = 0x01; - memcpy( p, salt, slen ); - p += slen; - - md_init_ctx( &md_ctx, md_info ); - - // Generate H = Hash( M' ) - // - md_starts( &md_ctx ); - md_update( &md_ctx, p, 8 ); - md_update( &md_ctx, hash, hashlen ); - md_update( &md_ctx, salt, slen ); - md_finish( &md_ctx, p ); - - // Compensate for boundary condition when applying mask - // - if( msb % 8 == 0 ) - offset = 1; - - // maskedDB: Apply dbMask to DB - // - mgf_mask( sig + offset, olen - hlen - 1 - offset, p, hlen, &md_ctx ); - - md_free_ctx( &md_ctx ); - - msb = mpi_msb( &ctx->N ) - 1; - sig[0] &= 0xFF >> ( olen * 8 - msb ); - - p += hlen; - *p++ = 0xBC; - - return( ( mode == RSA_PUBLIC ) - ? rsa_public( ctx, sig, sig ) - : rsa_private( ctx, sig, sig ) ); -} -#endif /* POLARSSL_PKCS1_V21 */ - -/* - * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-V1_5-SIGN function - */ -/* - * Do an RSA operation to sign the message digest - */ -int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - size_t nb_pad, olen; - unsigned char *p = sig; - - if( ctx->padding != RSA_PKCS_V15 ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - olen = ctx->len; - - switch( hash_id ) - { - case SIG_RSA_RAW: - nb_pad = olen - 3 - hashlen; - break; - - case SIG_RSA_MD2: - case SIG_RSA_MD4: - case SIG_RSA_MD5: - nb_pad = olen - 3 - 34; - break; - - case SIG_RSA_SHA1: - nb_pad = olen - 3 - 35; - break; - - case SIG_RSA_SHA224: - nb_pad = olen - 3 - 47; - break; - - case SIG_RSA_SHA256: - nb_pad = olen - 3 - 51; - break; - - case SIG_RSA_SHA384: - nb_pad = olen - 3 - 67; - break; - - case SIG_RSA_SHA512: - nb_pad = olen - 3 - 83; - break; - - - default: - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - - if( ( nb_pad < 8 ) || ( nb_pad > olen ) ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - *p++ = 0; - *p++ = RSA_SIGN; - memset( p, 0xFF, nb_pad ); - p += nb_pad; - *p++ = 0; - - switch( hash_id ) - { - case SIG_RSA_RAW: - memcpy( p, hash, hashlen ); - break; - - case SIG_RSA_MD2: - memcpy( p, ASN1_HASH_MDX, 18 ); - memcpy( p + 18, hash, 16 ); - p[13] = 2; break; - - case SIG_RSA_MD4: - memcpy( p, ASN1_HASH_MDX, 18 ); - memcpy( p + 18, hash, 16 ); - p[13] = 4; break; - - case SIG_RSA_MD5: - memcpy( p, ASN1_HASH_MDX, 18 ); - memcpy( p + 18, hash, 16 ); - p[13] = 5; break; - - case SIG_RSA_SHA1: - memcpy( p, ASN1_HASH_SHA1, 15 ); - memcpy( p + 15, hash, 20 ); - break; - - case SIG_RSA_SHA224: - memcpy( p, ASN1_HASH_SHA2X, 19 ); - memcpy( p + 19, hash, 28 ); - p[1] += 28; p[14] = 4; p[18] += 28; break; - - case SIG_RSA_SHA256: - memcpy( p, ASN1_HASH_SHA2X, 19 ); - memcpy( p + 19, hash, 32 ); - p[1] += 32; p[14] = 1; p[18] += 32; break; - - case SIG_RSA_SHA384: - memcpy( p, ASN1_HASH_SHA2X, 19 ); - memcpy( p + 19, hash, 48 ); - p[1] += 48; p[14] = 2; p[18] += 48; break; - - case SIG_RSA_SHA512: - memcpy( p, ASN1_HASH_SHA2X, 19 ); - memcpy( p + 19, hash, 64 ); - p[1] += 64; p[14] = 3; p[18] += 64; break; - - default: - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - - return( ( mode == RSA_PUBLIC ) - ? rsa_public( ctx, sig, sig ) - : rsa_private( ctx, sig, sig ) ); -} - -/* - * Do an RSA operation to sign the message digest - */ -int rsa_pkcs1_sign( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - switch( ctx->padding ) - { - case RSA_PKCS_V15: - return rsa_rsassa_pkcs1_v15_sign( ctx, mode, hash_id, - hashlen, hash, sig ); - -#if defined(POLARSSL_PKCS1_V21) - case RSA_PKCS_V21: - return rsa_rsassa_pss_sign( ctx, f_rng, p_rng, mode, hash_id, - hashlen, hash, sig ); -#endif - - default: - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - } -} - -#if defined(POLARSSL_PKCS1_V21) -/* - * Implementation of the PKCS#1 v2.1 RSASSA-PSS-VERIFY function - */ -int rsa_rsassa_pss_verify( rsa_context *ctx, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - int ret; - size_t siglen; - unsigned char *p; - unsigned char buf[POLARSSL_MPI_MAX_SIZE]; - unsigned char result[POLARSSL_MD_MAX_SIZE]; - unsigned char zeros[8]; - unsigned int hlen; - size_t slen, msb; - const md_info_t *md_info; - md_context_t md_ctx; - - if( ctx->padding != RSA_PKCS_V21 ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - siglen = ctx->len; - - if( siglen < 16 || siglen > sizeof( buf ) ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - ret = ( mode == RSA_PUBLIC ) - ? rsa_public( ctx, sig, buf ) - : rsa_private( ctx, sig, buf ); - - if( ret != 0 ) - return( ret ); - - p = buf; - - if( buf[siglen - 1] != 0xBC ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - switch( hash_id ) - { - case SIG_RSA_MD2: - case SIG_RSA_MD4: - case SIG_RSA_MD5: - hashlen = 16; - break; - - case SIG_RSA_SHA1: - hashlen = 20; - break; - - case SIG_RSA_SHA224: - hashlen = 28; - break; - - case SIG_RSA_SHA256: - hashlen = 32; - break; - - case SIG_RSA_SHA384: - hashlen = 48; - break; - - case SIG_RSA_SHA512: - hashlen = 64; - break; - - default: - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - } - - md_info = md_info_from_type( ctx->hash_id ); - if( md_info == NULL ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - hlen = md_get_size( md_info ); - slen = siglen - hlen - 1; - - memset( zeros, 0, 8 ); - - // Note: EMSA-PSS verification is over the length of N - 1 bits - // - msb = mpi_msb( &ctx->N ) - 1; - - // Compensate for boundary condition when applying mask - // - if( msb % 8 == 0 ) - { - p++; - siglen -= 1; - } - if( buf[0] >> ( 8 - siglen * 8 + msb ) ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - md_init_ctx( &md_ctx, md_info ); - - mgf_mask( p, siglen - hlen - 1, p + siglen - hlen - 1, hlen, &md_ctx ); - - buf[0] &= 0xFF >> ( siglen * 8 - msb ); - - while( *p == 0 && p < buf + siglen ) - p++; - - if( p == buf + siglen || - *p++ != 0x01 ) - { - md_free_ctx( &md_ctx ); - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - } - - slen -= p - buf; - - // Generate H = Hash( M' ) - // - md_starts( &md_ctx ); - md_update( &md_ctx, zeros, 8 ); - md_update( &md_ctx, hash, hashlen ); - md_update( &md_ctx, p, slen ); - md_finish( &md_ctx, result ); - - md_free_ctx( &md_ctx ); - - if( memcmp( p + slen, result, hlen ) == 0 ) - return( 0 ); - else - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); -} -#endif /* POLARSSL_PKCS1_V21 */ - -/* - * Implementation of the PKCS#1 v2.1 RSASSA-PKCS1-v1_5-VERIFY function - */ -int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - int ret; - size_t len, siglen; - unsigned char *p, c; - unsigned char buf[POLARSSL_MPI_MAX_SIZE]; - - if( ctx->padding != RSA_PKCS_V15 ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - siglen = ctx->len; - - if( siglen < 16 || siglen > sizeof( buf ) ) - return( POLARSSL_ERR_RSA_BAD_INPUT_DATA ); - - ret = ( mode == RSA_PUBLIC ) - ? rsa_public( ctx, sig, buf ) - : rsa_private( ctx, sig, buf ); - - if( ret != 0 ) - return( ret ); - - p = buf; - - if( *p++ != 0 || *p++ != RSA_SIGN ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - - while( *p != 0 ) - { - if( p >= buf + siglen - 1 || *p != 0xFF ) - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - p++; - } - p++; - - len = siglen - ( p - buf ); - - if( len == 33 && hash_id == SIG_RSA_SHA1 ) - { - if( memcmp( p, ASN1_HASH_SHA1_ALT, 13 ) == 0 && - memcmp( p + 13, hash, 20 ) == 0 ) - return( 0 ); - else - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - } - if( len == 34 ) - { - c = p[13]; - p[13] = 0; - - if( memcmp( p, ASN1_HASH_MDX, 18 ) != 0 ) - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - - if( ( c == 2 && hash_id == SIG_RSA_MD2 ) || - ( c == 4 && hash_id == SIG_RSA_MD4 ) || - ( c == 5 && hash_id == SIG_RSA_MD5 ) ) - { - if( memcmp( p + 18, hash, 16 ) == 0 ) - return( 0 ); - else - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - } - } - - if( len == 35 && hash_id == SIG_RSA_SHA1 ) - { - if( memcmp( p, ASN1_HASH_SHA1, 15 ) == 0 && - memcmp( p + 15, hash, 20 ) == 0 ) - return( 0 ); - else - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - } - if( ( len == 19 + 28 && p[14] == 4 && hash_id == SIG_RSA_SHA224 ) || - ( len == 19 + 32 && p[14] == 1 && hash_id == SIG_RSA_SHA256 ) || - ( len == 19 + 48 && p[14] == 2 && hash_id == SIG_RSA_SHA384 ) || - ( len == 19 + 64 && p[14] == 3 && hash_id == SIG_RSA_SHA512 ) ) - { - c = p[1] - 17; - p[1] = 17; - p[14] = 0; - - if( p[18] == c && - memcmp( p, ASN1_HASH_SHA2X, 18 ) == 0 && - memcmp( p + 19, hash, c ) == 0 ) - return( 0 ); - else - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - } - - if( len == hashlen && hash_id == SIG_RSA_RAW ) - { - if( memcmp( p, hash, hashlen ) == 0 ) - return( 0 ); - else - return( POLARSSL_ERR_RSA_VERIFY_FAILED ); - } - - return( POLARSSL_ERR_RSA_INVALID_PADDING ); -} - -/* - * Do an RSA operation and check the message digest - */ -int rsa_pkcs1_verify( rsa_context *ctx, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ) -{ - switch( ctx->padding ) - { - case RSA_PKCS_V15: - return rsa_rsassa_pkcs1_v15_verify( ctx, mode, hash_id, - hashlen, hash, sig ); - -#if defined(POLARSSL_PKCS1_V21) - case RSA_PKCS_V21: - return rsa_rsassa_pss_verify( ctx, mode, hash_id, - hashlen, hash, sig ); -#endif - - default: - return( POLARSSL_ERR_RSA_INVALID_PADDING ); - } -} - -/* - * Free the components of an RSA key - */ -void rsa_free( rsa_context *ctx ) -{ - mpi_free( &ctx->RQ ); mpi_free( &ctx->RP ); mpi_free( &ctx->RN ); - mpi_free( &ctx->QP ); mpi_free( &ctx->DQ ); mpi_free( &ctx->DP ); - mpi_free( &ctx->Q ); mpi_free( &ctx->P ); mpi_free( &ctx->D ); - mpi_free( &ctx->E ); mpi_free( &ctx->N ); -} - -#if defined(POLARSSL_SELF_TEST) - -#include "polarssl/sha1.h" - -/* - * Example RSA-1024 keypair, for test purposes - */ -#define KEY_LEN 128 - -#define RSA_N "9292758453063D803DD603D5E777D788" \ - "8ED1D5BF35786190FA2F23EBC0848AEA" \ - "DDA92CA6C3D80B32C4D109BE0F36D6AE" \ - "7130B9CED7ACDF54CFC7555AC14EEBAB" \ - "93A89813FBF3C4F8066D2D800F7C38A8" \ - "1AE31942917403FF4946B0A83D3D3E05" \ - "EE57C6F5F5606FB5D4BC6CD34EE0801A" \ - "5E94BB77B07507233A0BC7BAC8F90F79" - -#define RSA_E "10001" - -#define RSA_D "24BF6185468786FDD303083D25E64EFC" \ - "66CA472BC44D253102F8B4A9D3BFA750" \ - "91386C0077937FE33FA3252D28855837" \ - "AE1B484A8A9A45F7EE8C0C634F99E8CD" \ - "DF79C5CE07EE72C7F123142198164234" \ - "CABB724CF78B8173B9F880FC86322407" \ - "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ - "071513A1E85B5DFA031F21ECAE91A34D" - -#define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ - "2C01CAD19EA484A87EA4377637E75500" \ - "FCB2005C5C7DD6EC4AC023CDA285D796" \ - "C3D9E75E1EFC42488BB4F1D13AC30A57" - -#define RSA_Q "C000DF51A7C77AE8D7C7370C1FF55B69" \ - "E211C2B9E5DB1ED0BF61D0D9899620F4" \ - "910E4168387E3C30AA1E00C339A79508" \ - "8452DD96A9A5EA5D9DCA68DA636032AF" - -#define RSA_DP "C1ACF567564274FB07A0BBAD5D26E298" \ - "3C94D22288ACD763FD8E5600ED4A702D" \ - "F84198A5F06C2E72236AE490C93F07F8" \ - "3CC559CD27BC2D1CA488811730BB5725" - -#define RSA_DQ "4959CBF6F8FEF750AEE6977C155579C7" \ - "D8AAEA56749EA28623272E4F7D0592AF" \ - "7C1F1313CAC9471B5C523BFE592F517B" \ - "407A1BD76C164B93DA2D32A383E58357" - -#define RSA_QP "9AE7FBC99546432DF71896FC239EADAE" \ - "F38D18D2B2F0E2DD275AA977E2BF4411" \ - "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ - "A74206CEC169D74BF5A8C50D6F48EA08" - -#define PT_LEN 24 -#define RSA_PT "\xAA\xBB\xCC\x03\x02\x01\x00\xFF\xFF\xFF\xFF\xFF" \ - "\x11\x22\x33\x0A\x0B\x0C\xCC\xDD\xDD\xDD\xDD\xDD" - -static int myrand( void *rng_state, unsigned char *output, size_t len ) -{ - size_t i; - - if( rng_state != NULL ) - rng_state = NULL; - - for( i = 0; i < len; ++i ) - output[i] = rand(); - - return( 0 ); -} - -/* - * Checkup routine - */ -int rsa_self_test( int verbose ) -{ - size_t len; - rsa_context rsa; - unsigned char rsa_plaintext[PT_LEN]; - unsigned char rsa_decrypted[PT_LEN]; - unsigned char rsa_ciphertext[KEY_LEN]; -#if defined(POLARSSL_SHA1_C) - unsigned char sha1sum[20]; -#endif - - rsa_init( &rsa, RSA_PKCS_V15, 0 ); - - rsa.len = KEY_LEN; - mpi_read_string( &rsa.N , 16, RSA_N ); - mpi_read_string( &rsa.E , 16, RSA_E ); - mpi_read_string( &rsa.D , 16, RSA_D ); - mpi_read_string( &rsa.P , 16, RSA_P ); - mpi_read_string( &rsa.Q , 16, RSA_Q ); - mpi_read_string( &rsa.DP, 16, RSA_DP ); - mpi_read_string( &rsa.DQ, 16, RSA_DQ ); - mpi_read_string( &rsa.QP, 16, RSA_QP ); - - if( verbose != 0 ) - printf( " RSA key validation: " ); - - if( rsa_check_pubkey( &rsa ) != 0 || - rsa_check_privkey( &rsa ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n PKCS#1 encryption : " ); - - memcpy( rsa_plaintext, RSA_PT, PT_LEN ); - - if( rsa_pkcs1_encrypt( &rsa, &myrand, NULL, RSA_PUBLIC, PT_LEN, - rsa_plaintext, rsa_ciphertext ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n PKCS#1 decryption : " ); - - if( rsa_pkcs1_decrypt( &rsa, RSA_PRIVATE, &len, - rsa_ciphertext, rsa_decrypted, - sizeof(rsa_decrypted) ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( memcmp( rsa_decrypted, rsa_plaintext, len ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - -#if defined(POLARSSL_SHA1_C) - if( verbose != 0 ) - printf( "passed\n PKCS#1 data sign : " ); - - sha1( rsa_plaintext, PT_LEN, sha1sum ); - - if( rsa_pkcs1_sign( &rsa, NULL, NULL, RSA_PRIVATE, SIG_RSA_SHA1, 20, - sha1sum, rsa_ciphertext ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n PKCS#1 sig. verify: " ); - - if( rsa_pkcs1_verify( &rsa, RSA_PUBLIC, SIG_RSA_SHA1, 20, - sha1sum, rsa_ciphertext ) != 0 ) - { - if( verbose != 0 ) - printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - printf( "passed\n\n" ); -#endif /* POLARSSL_SHA1_C */ - - rsa_free( &rsa ); - - return( 0 ); -} - -#endif - -#endif diff --git a/common/polarssl/rsa.h b/common/polarssl/rsa.h deleted file mode 100644 index f9a022026..000000000 --- a/common/polarssl/rsa.h +++ /dev/null @@ -1,597 +0,0 @@ -/** - * \file rsa.h - * - * \brief The RSA public-key cryptosystem - * - * Copyright (C) 2006-2010, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_RSA_H -#define POLARSSL_RSA_H - -#include "bignum.h" - -/* - * RSA Error codes - */ -#define POLARSSL_ERR_RSA_BAD_INPUT_DATA -0x4080 /**< Bad input parameters to function. */ -#define POLARSSL_ERR_RSA_INVALID_PADDING -0x4100 /**< Input data contains invalid padding and is rejected. */ -#define POLARSSL_ERR_RSA_KEY_GEN_FAILED -0x4180 /**< Something failed during generation of a key. */ -#define POLARSSL_ERR_RSA_KEY_CHECK_FAILED -0x4200 /**< Key failed to pass the libraries validity check. */ -#define POLARSSL_ERR_RSA_PUBLIC_FAILED -0x4280 /**< The public key operation failed. */ -#define POLARSSL_ERR_RSA_PRIVATE_FAILED -0x4300 /**< The private key operation failed. */ -#define POLARSSL_ERR_RSA_VERIFY_FAILED -0x4380 /**< The PKCS#1 verification failed. */ -#define POLARSSL_ERR_RSA_OUTPUT_TOO_LARGE -0x4400 /**< The output buffer for decryption is not large enough. */ -#define POLARSSL_ERR_RSA_RNG_FAILED -0x4480 /**< The random generator failed to generate non-zeros. */ - -/* - * PKCS#1 constants - */ -#define SIG_RSA_RAW 0 -#define SIG_RSA_MD2 2 -#define SIG_RSA_MD4 3 -#define SIG_RSA_MD5 4 -#define SIG_RSA_SHA1 5 -#define SIG_RSA_SHA224 14 -#define SIG_RSA_SHA256 11 -#define SIG_RSA_SHA384 12 -#define SIG_RSA_SHA512 13 - -#define RSA_PUBLIC 0 -#define RSA_PRIVATE 1 - -#define RSA_PKCS_V15 0 -#define RSA_PKCS_V21 1 - -#define RSA_SIGN 1 -#define RSA_CRYPT 2 - -#define ASN1_STR_CONSTRUCTED_SEQUENCE "\x30" -#define ASN1_STR_NULL "\x05" -#define ASN1_STR_OID "\x06" -#define ASN1_STR_OCTET_STRING "\x04" - -#define OID_DIGEST_ALG_MDX "\x2A\x86\x48\x86\xF7\x0D\x02\x00" -#define OID_HASH_ALG_SHA1 "\x2b\x0e\x03\x02\x1a" -#define OID_HASH_ALG_SHA2X "\x60\x86\x48\x01\x65\x03\x04\x02\x00" - -#define OID_ISO_MEMBER_BODIES "\x2a" -#define OID_ISO_IDENTIFIED_ORG "\x2b" - -/* - * ISO Member bodies OID parts - */ -#define OID_COUNTRY_US "\x86\x48" -#define OID_RSA_DATA_SECURITY "\x86\xf7\x0d" - -/* - * ISO Identified organization OID parts - */ -#define OID_OIW_SECSIG_SHA1 "\x0e\x03\x02\x1a" - -/* - * DigestInfo ::= SEQUENCE { - * digestAlgorithm DigestAlgorithmIdentifier, - * digest Digest } - * - * DigestAlgorithmIdentifier ::= AlgorithmIdentifier - * - * Digest ::= OCTET STRING - */ -#define ASN1_HASH_MDX \ -( \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x20" \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x0C" \ - ASN1_STR_OID "\x08" \ - OID_DIGEST_ALG_MDX \ - ASN1_STR_NULL "\x00" \ - ASN1_STR_OCTET_STRING "\x10" \ -) - -#define ASN1_HASH_SHA1 \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x21" \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x09" \ - ASN1_STR_OID "\x05" \ - OID_HASH_ALG_SHA1 \ - ASN1_STR_NULL "\x00" \ - ASN1_STR_OCTET_STRING "\x14" - -#define ASN1_HASH_SHA1_ALT \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x1F" \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x07" \ - ASN1_STR_OID "\x05" \ - OID_HASH_ALG_SHA1 \ - ASN1_STR_OCTET_STRING "\x14" - -#define ASN1_HASH_SHA2X \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x11" \ - ASN1_STR_CONSTRUCTED_SEQUENCE "\x0d" \ - ASN1_STR_OID "\x09" \ - OID_HASH_ALG_SHA2X \ - ASN1_STR_NULL "\x00" \ - ASN1_STR_OCTET_STRING "\x00" - -/** - * \brief RSA context structure - */ -typedef struct -{ - int ver; /*!< always 0 */ - size_t len; /*!< size(N) in chars */ - - mpi N; /*!< public modulus */ - mpi E; /*!< public exponent */ - - mpi D; /*!< private exponent */ - mpi P; /*!< 1st prime factor */ - mpi Q; /*!< 2nd prime factor */ - mpi DP; /*!< D % (P - 1) */ - mpi DQ; /*!< D % (Q - 1) */ - mpi QP; /*!< 1 / (Q % P) */ - - mpi RN; /*!< cached R^2 mod N */ - mpi RP; /*!< cached R^2 mod P */ - mpi RQ; /*!< cached R^2 mod Q */ - - int padding; /*!< RSA_PKCS_V15 for 1.5 padding and - RSA_PKCS_v21 for OAEP/PSS */ - int hash_id; /*!< Hash identifier of md_type_t as - specified in the md.h header file - for the EME-OAEP and EMSA-PSS - encoding */ -} -rsa_context; - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Initialize an RSA context - * - * Note: Set padding to RSA_PKCS_V21 for the RSAES-OAEP - * encryption scheme and the RSASSA-PSS signature scheme. - * - * \param ctx RSA context to be initialized - * \param padding RSA_PKCS_V15 or RSA_PKCS_V21 - * \param hash_id RSA_PKCS_V21 hash identifier - * - * \note The hash_id parameter is actually ignored - * when using RSA_PKCS_V15 padding. - */ -void rsa_init( rsa_context *ctx, - int padding, - int hash_id); - -/** - * \brief Generate an RSA keypair - * - * \param ctx RSA context that will hold the key - * \param f_rng RNG function - * \param p_rng RNG parameter - * \param nbits size of the public key in bits - * \param exponent public exponent (e.g., 65537) - * - * \note rsa_init() must be called beforehand to setup - * the RSA context. - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - */ -int rsa_gen_key( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - unsigned int nbits, int exponent ); - -/** - * \brief Check a public RSA key - * - * \param ctx RSA context to be checked - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - */ -int rsa_check_pubkey( const rsa_context *ctx ); - -/** - * \brief Check a private RSA key - * - * \param ctx RSA context to be checked - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - */ -int rsa_check_privkey( const rsa_context *ctx ); - -/** - * \brief Do an RSA public key operation - * - * \param ctx RSA context - * \param input input buffer - * \param output output buffer - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note This function does NOT take care of message - * padding. Also, be sure to set input[0] = 0 or assure that - * input is smaller than N. - * - * \note The input and output buffers must be large - * enough (eg. 128 bytes if RSA-1024 is used). - */ -int rsa_public( rsa_context *ctx, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Do an RSA private key operation - * - * \param ctx RSA context - * \param input input buffer - * \param output output buffer - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note The input and output buffers must be large - * enough (eg. 128 bytes if RSA-1024 is used). - */ -int rsa_private( rsa_context *ctx, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Generic wrapper to perform a PKCS#1 encryption using the - * mode from the context. Add the message padding, then do an - * RSA operation. - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding) - * \param p_rng RNG parameter - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param ilen contains the plaintext length - * \param input buffer holding the data to be encrypted - * \param output buffer that will hold the ciphertext - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int rsa_pkcs1_encrypt( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Perform a PKCS#1 v1.5 encryption (RSAES-PKCS1-v1_5-ENCRYPT) - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for padding) - * \param p_rng RNG parameter - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param ilen contains the plaintext length - * \param input buffer holding the data to be encrypted - * \param output buffer that will hold the ciphertext - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int rsa_rsaes_pkcs1_v15_encrypt( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, size_t ilen, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Perform a PKCS#1 v2.1 OAEP encryption (RSAES-OAEP-ENCRYPT) - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for padding and PKCS#1 v2.1 encoding) - * \param p_rng RNG parameter - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param label buffer holding the custom label to use - * \param label_len contains the label length - * \param ilen contains the plaintext length - * \param input buffer holding the data to be encrypted - * \param output buffer that will hold the ciphertext - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int rsa_rsaes_oaep_encrypt( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - const unsigned char *label, size_t label_len, - size_t ilen, - const unsigned char *input, - unsigned char *output ); - -/** - * \brief Generic wrapper to perform a PKCS#1 decryption using the - * mode from the context. Do an RSA operation, then remove - * the message padding - * - * \param ctx RSA context - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param olen will contain the plaintext length - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param output_max_len maximum length of the output buffer - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise - * an error is thrown. - */ -int rsa_pkcs1_decrypt( rsa_context *ctx, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ); - -/** - * \brief Perform a PKCS#1 v1.5 decryption (RSAES-PKCS1-v1_5-DECRYPT) - * - * \param ctx RSA context - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param olen will contain the plaintext length - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param output_max_len maximum length of the output buffer - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise - * an error is thrown. - */ -int rsa_rsaes_pkcs1_v15_decrypt( rsa_context *ctx, - int mode, size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ); - -/** - * \brief Perform a PKCS#1 v2.1 OAEP decryption (RSAES-OAEP-DECRYPT) - * - * \param ctx RSA context - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param label buffer holding the custom label to use - * \param label_len contains the label length - * \param olen will contain the plaintext length - * \param input buffer holding the encrypted data - * \param output buffer that will hold the plaintext - * \param output_max_len maximum length of the output buffer - * - * \return 0 if successful, or an POLARSSL_ERR_RSA_XXX error code - * - * \note The output buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used) otherwise - * an error is thrown. - */ -int rsa_rsaes_oaep_decrypt( rsa_context *ctx, - int mode, - const unsigned char *label, size_t label_len, - size_t *olen, - const unsigned char *input, - unsigned char *output, - size_t output_max_len ); - -/** - * \brief Generic wrapper to perform a PKCS#1 signature using the - * mode from the context. Do a private RSA operation to sign - * a message digest - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding) - * \param p_rng RNG parameter - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} - * \param hashlen message digest length (for SIG_RSA_RAW only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext - * - * \return 0 if the signing operation was successful, - * or an POLARSSL_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - * - * \note In case of PKCS#1 v2.1 encoding keep in mind that - * the hash_id in the RSA context is the one used for the - * encoding. hash_id in the function call is the type of hash - * that is encoded. According to RFC 3447 it is advised to - * keep both hashes the same. - */ -int rsa_pkcs1_sign( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * \brief Perform a PKCS#1 v1.5 signature (RSASSA-PKCS1-v1_5-SIGN) - * - * \param ctx RSA context - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} - * \param hashlen message digest length (for SIG_RSA_RAW only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext - * - * \return 0 if the signing operation was successful, - * or an POLARSSL_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int rsa_rsassa_pkcs1_v15_sign( rsa_context *ctx, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * \brief Perform a PKCS#1 v2.1 PSS signature (RSASSA-PSS-SIGN) - * - * \param ctx RSA context - * \param f_rng RNG function (Needed for PKCS#1 v2.1 encoding) - * \param p_rng RNG parameter - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} - * \param hashlen message digest length (for SIG_RSA_RAW only) - * \param hash buffer holding the message digest - * \param sig buffer that will hold the ciphertext - * - * \return 0 if the signing operation was successful, - * or an POLARSSL_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - * - * \note In case of PKCS#1 v2.1 encoding keep in mind that - * the hash_id in the RSA context is the one used for the - * encoding. hash_id in the function call is the type of hash - * that is encoded. According to RFC 3447 it is advised to - * keep both hashes the same. - */ -int rsa_rsassa_pss_sign( rsa_context *ctx, - int (*f_rng)(void *, unsigned char *, size_t), - void *p_rng, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * \brief Generic wrapper to perform a PKCS#1 verification using the - * mode from the context. Do a public RSA operation and check - * the message digest - * - * \param ctx points to an RSA public key - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} - * \param hashlen message digest length (for SIG_RSA_RAW only) - * \param hash buffer holding the message digest - * \param sig buffer holding the ciphertext - * - * \return 0 if the verify operation was successful, - * or an POLARSSL_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - * - * \note In case of PKCS#1 v2.1 encoding keep in mind that - * the hash_id in the RSA context is the one used for the - * verification. hash_id in the function call is the type of hash - * that is verified. According to RFC 3447 it is advised to - * keep both hashes the same. - */ -int rsa_pkcs1_verify( rsa_context *ctx, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * \brief Perform a PKCS#1 v1.5 verification (RSASSA-PKCS1-v1_5-VERIFY) - * - * \param ctx points to an RSA public key - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} - * \param hashlen message digest length (for SIG_RSA_RAW only) - * \param hash buffer holding the message digest - * \param sig buffer holding the ciphertext - * - * \return 0 if the verify operation was successful, - * or an POLARSSL_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - */ -int rsa_rsassa_pkcs1_v15_verify( rsa_context *ctx, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * \brief Perform a PKCS#1 v2.1 PSS verification (RSASSA-PSS-VERIFY) - * \brief Do a public RSA and check the message digest - * - * \param ctx points to an RSA public key - * \param mode RSA_PUBLIC or RSA_PRIVATE - * \param hash_id SIG_RSA_RAW, SIG_RSA_MD{2,4,5} or SIG_RSA_SHA{1,224,256,384,512} - * \param hashlen message digest length (for SIG_RSA_RAW only) - * \param hash buffer holding the message digest - * \param sig buffer holding the ciphertext - * - * \return 0 if the verify operation was successful, - * or an POLARSSL_ERR_RSA_XXX error code - * - * \note The "sig" buffer must be as large as the size - * of ctx->N (eg. 128 bytes if RSA-1024 is used). - * - * \note In case of PKCS#1 v2.1 encoding keep in mind that - * the hash_id in the RSA context is the one used for the - * verification. hash_id in the function call is the type of hash - * that is verified. According to RFC 3447 it is advised to - * keep both hashes the same. - */ -int rsa_rsassa_pss_verify( rsa_context *ctx, - int mode, - int hash_id, - unsigned int hashlen, - const unsigned char *hash, - unsigned char *sig ); - -/** - * \brief Free the components of an RSA key - * - * \param ctx RSA Context to free - */ -void rsa_free( rsa_context *ctx ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int rsa_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* rsa.h */ diff --git a/common/polarssl/sha1.h b/common/polarssl/sha1.h deleted file mode 100644 index 99ccb7b63..000000000 --- a/common/polarssl/sha1.h +++ /dev/null @@ -1,213 +0,0 @@ -/** - * \file sha1.h - * - * \brief SHA-1 cryptographic hash function - * - * Copyright (C) 2006-2014, ARM Limited, All Rights Reserved - * - * This file is part of mbed TLS (https://tls.mbed.org) - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_SHA1_H -#define POLARSSL_SHA1_H - -#if !defined(POLARSSL_CONFIG_FILE) -#include "polarssl_config.h" -/** - * \def POLARSSL_SHA1_C - * - * Enable the SHA1 cryptographic hash algorithm. - * - * Module: library/sha1.c - * Caller: library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509write_crt.c - * - * This module is required for SSL/TLS and SHA1-signed certificates. - */ -#define POLARSSL_SHA1_C - -#else -#include POLARSSL_CONFIG_FILE -#endif - -#include - -#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) -#include -typedef UINT32 uint32_t; -#else -#include -#endif - -#define POLARSSL_ERR_SHA1_FILE_IO_ERROR -0x0076 /**< Read/write error in file. */ - -#if !defined(POLARSSL_SHA1_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief SHA-1 context structure - */ -typedef struct -{ - uint32_t total[2]; /*!< number of bytes processed */ - uint32_t state[5]; /*!< intermediate digest state */ - unsigned char buffer[64]; /*!< data block being processed */ - - unsigned char ipad[64]; /*!< HMAC: inner padding */ - unsigned char opad[64]; /*!< HMAC: outer padding */ -} -sha1_context; - -/** - * \brief Initialize SHA-1 context - * - * \param ctx SHA-1 context to be initialized - */ -void sha1_init( sha1_context *ctx ); - -/** - * \brief Clear SHA-1 context - * - * \param ctx SHA-1 context to be cleared - */ -void sha1_free( sha1_context *ctx ); - -/** - * \brief SHA-1 context setup - * - * \param ctx context to be initialized - */ -void sha1_starts( sha1_context *ctx ); - -/** - * \brief SHA-1 process buffer - * - * \param ctx SHA-1 context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void sha1_update( sha1_context *ctx, const unsigned char *input, size_t ilen ); - -/** - * \brief SHA-1 final digest - * - * \param ctx SHA-1 context - * \param output SHA-1 checksum result - */ -void sha1_finish( sha1_context *ctx, unsigned char output[20] ); - -/* Internal use */ -void sha1_process( sha1_context *ctx, const unsigned char data[64] ); - -#ifdef __cplusplus -} -#endif - -#else /* POLARSSL_SHA1_ALT */ -#include "sha1_alt.h" -#endif /* POLARSSL_SHA1_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Output = SHA-1( input buffer ) - * - * \param input buffer holding the data - * \param ilen length of the input data - * \param output SHA-1 checksum result - */ -void sha1( const unsigned char *input, size_t ilen, unsigned char output[20] ); - -/** - * \brief Output = SHA-1( file contents ) - * - * \param path input file name - * \param output SHA-1 checksum result - * - * \return 0 if successful, or POLARSSL_ERR_SHA1_FILE_IO_ERROR - */ -int sha1_file( const char *path, unsigned char output[20] ); - -/** - * \brief SHA-1 HMAC context setup - * - * \param ctx HMAC context to be initialized - * \param key HMAC secret key - * \param keylen length of the HMAC key - */ -void sha1_hmac_starts( sha1_context *ctx, const unsigned char *key, - size_t keylen ); - -/** - * \brief SHA-1 HMAC process buffer - * - * \param ctx HMAC context - * \param input buffer holding the data - * \param ilen length of the input data - */ -void sha1_hmac_update( sha1_context *ctx, const unsigned char *input, - size_t ilen ); - -/** - * \brief SHA-1 HMAC final digest - * - * \param ctx HMAC context - * \param output SHA-1 HMAC checksum result - */ -void sha1_hmac_finish( sha1_context *ctx, unsigned char output[20] ); - -/** - * \brief SHA-1 HMAC context reset - * - * \param ctx HMAC context to be reset - */ -void sha1_hmac_reset( sha1_context *ctx ); - -/** - * \brief Output = HMAC-SHA-1( hmac key, input buffer ) - * - * \param key HMAC secret key - * \param keylen length of the HMAC key - * \param input buffer holding the data - * \param ilen length of the input data - * \param output HMAC-SHA-1 result - */ -void sha1_hmac( const unsigned char *key, size_t keylen, - const unsigned char *input, size_t ilen, - unsigned char output[20] ); - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int sha1_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* sha1.h */ diff --git a/common/polarssl/sha256.h b/common/polarssl/sha256.h deleted file mode 100644 index 0dbc4b256..000000000 --- a/common/polarssl/sha256.h +++ /dev/null @@ -1,142 +0,0 @@ -/** - * \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 */ From aaf7b25c016511ac1b67690bbc912c454c09a9d3 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Nov 2018 18:17:17 +0200 Subject: [PATCH 0134/1938] cmdflashmem fixed for mbedtls --- client/cmdflashmem.c | 34 +++++++++++++++++----------------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index d6d27e6fc..62f341a24 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -9,8 +9,8 @@ //----------------------------------------------------------------------------- #include "cmdflashmem.h" -#include "rsa.h" -#include "sha1.h" +#include "mbedtls/rsa.h" +#include "mbedtls/sha1.h" #define MCK 48000000 //#define FLASH_BAUD 24000000 @@ -358,7 +358,7 @@ int CmdFlashMemWipe(const char *Cmd){ int CmdFlashMemInfo(const char *Cmd){ uint8_t sha_hash[20] = {0}; - rsa_context rsa; + mbedtls_rsa_context rsa; uint8_t cmdp = 0; bool errors = false, shall_write = false, shall_sign = false; @@ -404,7 +404,7 @@ int CmdFlashMemInfo(const char *Cmd){ memcpy(&mem, (rdv40_validation_t *)resp.d.asBytes, sizeof(rdv40_validation_t)); // Flash ID hash (sha1) - sha1( mem.flashid, sizeof(mem.flashid), sha_hash ); + mbedtls_sha1( mem.flashid, sizeof(mem.flashid), sha_hash ); // print header PrintAndLogEx(INFO, "\n--- Flash memory Information ---------"); @@ -471,22 +471,22 @@ int CmdFlashMemInfo(const char *Cmd){ #define KEY_LEN 128 - rsa_init(&rsa, RSA_PKCS_V15, 0); + mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0); rsa.len = KEY_LEN; - mpi_read_string( &rsa.N , 16, RSA_N ); - mpi_read_string( &rsa.E , 16, RSA_E ); - mpi_read_string( &rsa.D , 16, RSA_D ); - mpi_read_string( &rsa.P , 16, RSA_P ); - mpi_read_string( &rsa.Q , 16, RSA_Q ); - mpi_read_string( &rsa.DP, 16, RSA_DP ); - mpi_read_string( &rsa.DQ, 16, RSA_DQ ); - mpi_read_string( &rsa.QP, 16, RSA_QP ); + mbedtls_mpi_read_string( &rsa.N , 16, RSA_N ); + mbedtls_mpi_read_string( &rsa.E , 16, RSA_E ); + mbedtls_mpi_read_string( &rsa.D , 16, RSA_D ); + mbedtls_mpi_read_string( &rsa.P , 16, RSA_P ); + mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q ); + mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP ); + mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ ); + mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ); PrintAndLogEx(INFO, "KEY length | %d", KEY_LEN); - bool is_keyok = ( rsa_check_pubkey( &rsa ) == 0 || rsa_check_privkey( &rsa ) == 0 ); + bool is_keyok = ( mbedtls_rsa_check_pubkey( &rsa ) == 0 || mbedtls_rsa_check_privkey( &rsa ) == 0 ); if (is_keyok) PrintAndLogEx(SUCCESS, "RSA key validation ok"); else @@ -505,7 +505,7 @@ int CmdFlashMemInfo(const char *Cmd){ // Signing (private key) if (shall_sign) { - int is_signed = rsa_pkcs1_sign( &rsa, NULL, NULL, RSA_PRIVATE, SIG_RSA_SHA1, 20, sha_hash, sign ); + int is_signed = mbedtls_rsa_pkcs1_sign( &rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign ); if (is_signed == 0) PrintAndLogEx(SUCCESS, "RSA Signing ok"); else @@ -533,13 +533,13 @@ int CmdFlashMemInfo(const char *Cmd){ } // Verify (public key) - int is_verified = rsa_pkcs1_verify( &rsa, RSA_PUBLIC, SIG_RSA_SHA1, 20, sha_hash, from_device ); + int is_verified = mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device ); if (is_verified == 0) PrintAndLogEx(SUCCESS, "RSA Verification ok"); else PrintAndLogEx(FAILED, "RSA Verification failed"); - rsa_free(&rsa); + mbedtls_rsa_free(&rsa); return 0; } From f0741798e67b5f59a72252f2b0dab8956ccf97bc Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Nov 2018 18:20:24 +0200 Subject: [PATCH 0135/1938] fix scripting --- client/scripting.c | 34 +++++++++++++++++----------------- client/scripting.h | 4 ++-- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/client/scripting.c b/client/scripting.c index 06356293f..f0fa9b2f4 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -331,10 +331,10 @@ static int l_aes128decrypt_cbc(lua_State *L) { aes_key[i / 2] = tmp & 0xFF; } - aes_context ctx; - aes_init(&ctx); - aes_setkey_dec(&ctx, aes_key, 128); - aes_crypt_cbc(&ctx, AES_DECRYPT, sizeof(indata), iv, indata, outdata ); + mbedtls_aes_context ctx; + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_dec(&ctx, aes_key, 128); + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_DECRYPT, sizeof(indata), iv, indata, outdata ); //Push decrypted array as a string lua_pushlstring(L,(const char *)&outdata, sizeof(outdata)); return 1;// return 1 to signal one return value @@ -360,10 +360,10 @@ static int l_aes128decrypt_ecb(lua_State *L) { sscanf(&p_key[i], "%02x", &tmp); aes_key[i / 2] = tmp & 0xFF; } - aes_context ctx; - aes_init(&ctx); - aes_setkey_dec(&ctx, aes_key, 128); - aes_crypt_ecb(&ctx, AES_DECRYPT, indata, outdata ); + mbedtls_aes_context ctx; + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_dec(&ctx, aes_key, 128); + mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_DECRYPT, indata, outdata ); //Push decrypted array as a string lua_pushlstring(L,(const char *)&outdata, sizeof(outdata)); @@ -392,10 +392,10 @@ static int l_aes128encrypt_cbc(lua_State *L) { aes_key[i / 2] = tmp & 0xFF; } - aes_context ctx; - aes_init(&ctx); - aes_setkey_enc(&ctx, aes_key, 128); - aes_crypt_cbc(&ctx, AES_ENCRYPT, sizeof(indata), iv, indata, outdata ); + mbedtls_aes_context ctx; + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, aes_key, 128); + mbedtls_aes_crypt_cbc(&ctx, MBEDTLS_AES_ENCRYPT, sizeof(indata), iv, indata, outdata ); //Push encrypted array as a string lua_pushlstring(L,(const char *)&outdata, sizeof(outdata)); return 1;// return 1 to signal one return value @@ -421,10 +421,10 @@ static int l_aes128encrypt_ecb(lua_State *L) { sscanf(&p_key[i], "%02x", &tmp); aes_key[i / 2] = tmp & 0xFF; } - aes_context ctx; - aes_init(&ctx); - aes_setkey_enc(&ctx, aes_key, 128); - aes_crypt_ecb(&ctx, AES_ENCRYPT, indata, outdata ); + mbedtls_aes_context ctx; + mbedtls_aes_init(&ctx); + mbedtls_aes_setkey_enc(&ctx, aes_key, 128); + mbedtls_aes_crypt_ecb(&ctx, MBEDTLS_AES_ENCRYPT, indata, outdata ); //Push encrypted array as a string lua_pushlstring(L,(const char *)&outdata, sizeof(outdata)); return 1;// return 1 to signal one return value @@ -498,7 +498,7 @@ static int l_sha1(lua_State *L) { size_t size; const char *p_str = luaL_checklstring(L, 1, &size); unsigned char outdata[20] = {0x00}; - sha1( (uint8_t*) p_str, size, outdata); + mbedtls_sha1( (uint8_t*) p_str, size, outdata); lua_pushlstring(L, (const char *)&outdata, sizeof(outdata)); return 1; } diff --git a/client/scripting.h b/client/scripting.h index a6aaf157a..4d39a6c6f 100644 --- a/client/scripting.h +++ b/client/scripting.h @@ -23,8 +23,8 @@ #include "crc.h" #include "crc16.h" #include "crc64.h" -#include "sha1.h" -#include "aes.h" +#include "mbedtls/sha1.h" +#include "mbedtls/aes.h" #include "cmdcrc.h" #include "cmdhfmfhard.h" #include "cmdhfmfu.h" From d0c6889c714a12beb653128eaad0e347790d5fcb Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Nov 2018 18:27:22 +0200 Subject: [PATCH 0136/1938] fix warning in emv_tags.c --- client/emv/emv_tags.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index a1bf3d25e..0cb1e6e64 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -391,7 +391,7 @@ static unsigned long emv_value_numeric(const struct tlv *tlv, unsigned start, un static void emv_tag_dump_numeric(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { PRINT_INDENT(level); - fprintf(f, "\tNumeric value %" PRIu32 " \n", emv_value_numeric(tlv, 0, tlv->len * 2)); + fprintf(f, "\tNumeric value %lu \n", emv_value_numeric(tlv, 0, tlv->len * 2)); } static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { From ec1e04342c966f810b62b10017c58f9cfdb7f9fc Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 7 Nov 2018 18:31:36 +0200 Subject: [PATCH 0137/1938] compiles --- client/Makefile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/Makefile b/client/Makefile index 03c4c1288..38cad33cf 100644 --- a/client/Makefile +++ b/client/Makefile @@ -28,7 +28,7 @@ LUALIB = ../liblua/liblua.a MBEDTLSLIBPATH = ../common/mbedtls MBEDTLSLIB = $(MBEDTLSLIBPATH)/libmbedtls.a LDFLAGS = $(ENV_LDFLAGS) -INCLUDES_CLIENT = -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua +INCLUDES_CLIENT = -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua -I$(MBEDTLSLIBPATH) CFLAGS = $(ENV_CFLAGS) -std=c99 -D_ISOC99_SOURCE -DPRESETS $(INCLUDES_CLIENT) -Wall -g -O3 CXXFLAGS = -I../include -Wall -O3 @@ -261,7 +261,7 @@ all: lua_build mbedtls_build $(BINS) all-static: LDLIBS:=-static $(LDLIBS) all-static: proxmark3 flasher fpga_compress -proxmark3: LDLIBS+=$(LUALIB) $(QTLDLIBS) +proxmark3: LDLIBS+=$(LUALIB) $(QTLDLIBS) $(MBEDTLSLIB) proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) lualibs/usb_cmd.lua lualibs/mf_default_keys.lua $(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) $(LDLIBS) -o $@ From 3731ca19d28e0c1bac3ef02cb2770fd98eaf1e46 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 8 Nov 2018 01:16:27 +0100 Subject: [PATCH 0138/1938] chg: 'hf mf fchk' - filename --- client/cmdhfmf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 8f7004d66..7cdd44af1 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1621,12 +1621,12 @@ out: FILE *fkeys = fopen(fptr,"wb"); if (fkeys == NULL) { - PrintAndLogEx(WARNING, "Could not create file %s", filename); + PrintAndLogEx(WARNING, "Could not create file %s", fptr); free(keyBlock); free(e_sector); return 1; } - PrintAndLogEx(NORMAL, "Printing keys to binary file %s...", filename); + PrintAndLogEx(NORMAL, "Printing keys to binary file %s...", fptr); for (i=0; i 0xffffffffffff has been inserted for unknown keys.", fptr); } free(keyBlock); From affee79b692d28cdaff06d2333065208a59b714d Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 8 Nov 2018 13:45:57 +0100 Subject: [PATCH 0139/1938] fix 'sc raw' - now raw command automatically adjust when getting a 0x6C response code and resend command. --- client/cmdsmartcard.c | 15 +++++++++++++++ 1 file changed, 15 insertions(+) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index fc188b951..675b9a9b7 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -224,6 +224,21 @@ int CmdSmartRaw(const char *Cmd) { free(buf); return 2; } + + if ( buf[0] == 0x6C ) { + data[4] = buf[1]; + + memcpy(c.d.asBytes, data, sizeof(data) ); + clearCommandBuffer(); + SendCommand(&c); + len = smart_response(buf); + + // TLV decoder + if (len > 4) + TLVPrintFromBuffer(buf+1, len-3); + + data[4] = 0; + } if (decodeTLV && len > 4) TLVPrintFromBuffer(buf+1, len-3); From 4fed815b88f0a7e715a9a233b486db75034b25db Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 8 Nov 2018 17:29:58 +0200 Subject: [PATCH 0140/1938] added core files. need to add: 1. jansson (maybe needs jansson-devel) 2. arm and client side of exchangeapdu14a --- client/Makefile | 4 +- client/cmdhf.c | 27 ++- client/cmdhf.h | 1 + client/cmdhffido.c | 550 +++++++++++++++++++++++++++++++++++++++++++ client/cmdhffido.h | 27 +++ client/emv/emvcore.h | 3 + client/emv/emvjson.c | 385 ++++++++++++++++++++++++++++++ client/emv/emvjson.h | 40 ++++ client/util.c | 17 +- 9 files changed, 1031 insertions(+), 23 deletions(-) create mode 100644 client/cmdhffido.c create mode 100644 client/cmdhffido.h create mode 100644 client/emv/emvjson.c create mode 100644 client/emv/emvjson.h diff --git a/client/Makefile b/client/Makefile index a31be08d5..1e6ad4426 100644 --- a/client/Makefile +++ b/client/Makefile @@ -23,7 +23,7 @@ ENV_CFLAGS := $(CFLAGS) VPATH = ../common ../zlib ../uart OBJDIR = obj -LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm +LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm -ljansson LUALIB = ../liblua/liblua.a LDFLAGS = $(ENV_LDFLAGS) INCLUDES_CLIENT = -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua @@ -134,6 +134,7 @@ CMDSRCS = crapto1/crapto1.c \ lfdemod.c \ emv/crypto_polarssl.c\ emv/crypto.c\ + emv/emvjson.c\ emv/emv_pk.c\ emv/emv_pki.c\ emv/emv_pki_priv.c\ @@ -166,6 +167,7 @@ CMDSRCS = crapto1/crapto1.c \ hardnested/hardnested_bruteforce.c \ cmdhfmfdes.c \ cmdhftopaz.c \ + cmdhffido.c \ cmdhffelica.c \ cmdhw.c \ cmdlf.c \ diff --git a/client/cmdhf.c b/client/cmdhf.c index 30669d24d..65b6bd33d 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -108,19 +108,20 @@ int CmdHFSnoop(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"}, - {"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"}, - {"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"}, - {"epa", CmdHFEPA, 1, "{ German Identification Card... }"}, - {"emv", CmdHFEMV, 1, "{ EMV RFIDs... }"}, - {"felica", CmdHFFelica, 1, "{ ISO18092 / Felica RFIDs... }"}, - {"legic", CmdHFLegic, 1, "{ LEGIC RFIDs... }"}, - {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, - {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, - {"mfp", CmdHFMFP, 1, "{ MIFARE Plus RFIDs... }"}, - {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, - {"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"}, - {"topaz", CmdHFTopaz, 1, "{ TOPAZ (NFC Type 1) RFIDs... }"}, + {"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"}, + {"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"}, + {"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"}, + {"epa", CmdHFEPA, 1, "{ German Identification Card... }"}, + {"emv", CmdHFEMV, 1, "{ EMV RFIDs... }"}, + {"felica", CmdHFFelica, 1, "{ ISO18092 / Felica RFIDs... }"}, + {"legic", CmdHFLegic, 1, "{ LEGIC RFIDs... }"}, + {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, + {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, + {"mfp", CmdHFMFP, 1, "{ MIFARE Plus RFIDs... }"}, + {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, + {"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"}, + {"topaz", CmdHFTopaz, 1, "{ TOPAZ (NFC Type 1) RFIDs... }"}, + {"fido", CmdHFFido, 1, "{ FIDO and FIDO2 authenticators... }"}, {"list", CmdTraceList, 0, "List protocol data in trace buffer"}, {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, {"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"}, diff --git a/client/cmdhf.h b/client/cmdhf.h index a4cc2e95c..bd191ead5 100644 --- a/client/cmdhf.h +++ b/client/cmdhf.h @@ -31,6 +31,7 @@ #include "cmdhftopaz.h" // TOPAZ #include "cmdhffelica.h" // ISO18092 / FeliCa #include "emv/cmdemv.h" // EMV +#include "cmdhffido.h" // FIDO authenticators #include "cmdtrace.h" // trace list extern int CmdHF(const char *Cmd); diff --git a/client/cmdhffido.c b/client/cmdhffido.c new file mode 100644 index 000000000..fd97ace54 --- /dev/null +++ b/client/cmdhffido.c @@ -0,0 +1,550 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency MIFARE Plus commands +//----------------------------------------------------------------------------- +// +// Documentation here: +// +// FIDO Alliance specifications +// https://fidoalliance.org/download/ +// FIDO NFC Protocol Specification v1.0 +// https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-nfc-protocol-v1.2-ps-20170411.html +// FIDO U2F Raw Message Formats +// https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html +//----------------------------------------------------------------------------- + + +#include "cmdhffido.h" + +#include +#include +#include +#include +#include +#include +#include +#include "comms.h" +#include "cmdmain.h" +#include "util.h" +#include "ui.h" +#include "proxmark3.h" +#include "cmdhf14a.h" +#include "mifare.h" +#include "emv/emvcore.h" +#include "emv/emvjson.h" +#include "emv/dump.h" +#include "cliparser/cliparser.h" + +static int CmdHelp(const char *Cmd); + +int FIDOSelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + uint8_t data[] = {0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01}; + + return EMVSelect(ActivateField, LeaveFieldON, data, sizeof(data), Result, MaxResultLen, ResultLen, sw, NULL); +} + +int FIDOExchange(sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + int res = EMVExchange(true, apdu, Result, MaxResultLen, ResultLen, sw, NULL); + if (res == 5) // apdu result (sw) not a 0x9000 + res = 0; + // software chaining + while (!res && (*sw >> 8) == 0x61) { + size_t oldlen = *ResultLen; + res = EMVExchange(true, (sAPDU){0x00, 0xC0, 0x00, 0x00, 0x00, NULL}, &Result[oldlen], MaxResultLen - oldlen, ResultLen, sw, NULL); + if (res == 5) // apdu result (sw) not a 0x9000 + res = 0; + + *ResultLen += oldlen; + if (*ResultLen > MaxResultLen) + return 100; + } + return res; +} + +int FIDORegister(uint8_t *params, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + return FIDOExchange((sAPDU){0x00, 0x01, 0x03, 0x00, 64, params}, Result, MaxResultLen, ResultLen, sw); +} + +int FIDOAuthentication(uint8_t *params, uint8_t paramslen, uint8_t controlb, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + return FIDOExchange((sAPDU){0x00, 0x02, controlb, 0x00, paramslen, params}, Result, MaxResultLen, ResultLen, sw); +} + +int FIDO2GetInfo(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + uint8_t data[] = {0x04}; + return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); +} + +int CmdHFFidoInfo(const char *cmd) { + + if (cmd && strlen(cmd) > 0) + PrintAndLog("WARNING: command don't have any parameters.\n"); + + // info about 14a part + CmdHF14AInfo(""); + + // FIDO info + PrintAndLog("--------------------------------------------"); + SetAPDULogging(false); + + uint8_t buf[APDU_RES_LEN] = {0}; + size_t len = 0; + uint16_t sw = 0; + int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); + + if (res) { + DropField(); + return res; + } + + if (sw != 0x9000) { + if (sw) + PrintAndLog("Not a FIDO card! APDU response: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + else + PrintAndLog("APDU exchange error. Card returns 0x0000."); + + DropField(); + return 0; + } + + if (!strncmp((char *)buf, "U2F_V2", 7)) { + if (!strncmp((char *)buf, "FIDO_2_0", 8)) { + PrintAndLog("FIDO2 authenricator detected. Version: %.*s", len, buf); + } else { + PrintAndLog("FIDO authenricator detected (not standard U2F)."); + PrintAndLog("Non U2F authenticator version:"); + dump_buffer((const unsigned char *)buf, len, NULL, 0); + } + } else { + PrintAndLog("FIDO U2F authenricator detected. Version: %.*s", len, buf); + } + + res = FIDO2GetInfo(buf, sizeof(buf), &len, &sw); + DropField(); + if (res) { + return res; + } + if (sw != 0x9000) { + PrintAndLog("FIDO2 version not exists (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + + return 0; + } + + PrintAndLog("FIDO2 version: (%d)", len); + dump_buffer((const unsigned char *)buf, len, NULL, 0); + + return 0; +} + +json_t *OpenJson(int paramnum, char *fname, void* argtable[], bool *err) { + json_t *root = NULL; + json_error_t error; + *err = false; + + uint8_t jsonname[250] ={0}; + char *cjsonname = (char *)jsonname; + int jsonnamelen = 0; + + // CLIGetStrWithReturn(paramnum, jsonname, &jsonnamelen); + if (CLIParamStrToBuf(arg_get_str(paramnum), jsonname, sizeof(jsonname), &jsonnamelen)) { + CLIParserFree(); + return NULL; + } + + // current path + file name + if (!strstr(cjsonname, ".json")) + strcat(cjsonname, ".json"); + + if (jsonnamelen) { + strcpy(fname, get_my_executable_directory()); + strcat(fname, cjsonname); + if (access(fname, F_OK) != -1) { + root = json_load_file(fname, 0, &error); + if (!root) { + PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); + *err = true; + return NULL; + } + + if (!json_is_object(root)) { + PrintAndLog("ERROR: Invalid json format. root must be an object."); + json_decref(root); + *err = true; + return NULL; + } + + } else { + root = json_object(); + } + } + return root; +} + +int CmdHFFidoRegister(const char *cmd) { + uint8_t data[64] = {0}; + int chlen = 0; + uint8_t cdata[250] = {0}; + int applen = 0; + uint8_t adata[250] = {0}; + json_t *root = NULL; + + CLIParserInit("hf fido reg", + "Initiate a U2F token registration. Needs two 32-byte hash number. \nchallenge parameter (32b) and application parameter (32b).", + "Usage:\n\thf fido reg -> execute command with 2 parameters, filled 0x00\n" + "\thf fido reg 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters" + "\thf fido reg -p s0 s1 -> execute command with plain parameters"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_lit0("vV", "verbose", "show technical data"), + arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"), + arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."), + arg_str0(NULL, NULL, "", NULL), + arg_str0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + bool APDULogging = arg_get_lit(1); + bool verbose = arg_get_lit(2); + bool paramsPlain = arg_get_lit(3); + + char fname[250] = {0}; + bool err; + root = OpenJson(4, fname, argtable, &err); + if(err) + return 1; + if (root) { + size_t jlen; + JsonLoadBufAsHex(root, "$.ChallengeParam", data, 32, &jlen); + JsonLoadBufAsHex(root, "$.ApplicationParam", &data[32], 32, &jlen); + } + + if (paramsPlain) { + memset(cdata, 0x00, 32); + CLIGetStrWithReturn(5, cdata, &chlen); + if (chlen && chlen > 16) { + PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", chlen); + return 1; + } + } else { + CLIGetHexWithReturn(5, cdata, &chlen); + if (chlen && chlen != 32) { + PrintAndLog("ERROR: challenge parameter length must be 32 bytes only."); + return 1; + } + } + if (chlen) + memmove(data, cdata, 32); + + + if (paramsPlain) { + memset(adata, 0x00, 32); + CLIGetStrWithReturn(6, adata, &applen); + if (applen && applen > 16) { + PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", applen); + return 1; + } + } else { + CLIGetHexWithReturn(6, adata, &applen); + if (applen && applen != 32) { + PrintAndLog("ERROR: application parameter length must be 32 bytes only."); + return 1; + } + } + if (applen) + memmove(&data[32], adata, 32); + + CLIParserFree(); + + SetAPDULogging(APDULogging); + + // challenge parameter [32 bytes] - The challenge parameter is the SHA-256 hash of the Client Data, a stringified JSON data structure that the FIDO Client prepares + // application parameter [32 bytes] - The application parameter is the SHA-256 hash of the UTF-8 encoding of the application identity + + uint8_t buf[2048] = {0}; + size_t len = 0; + uint16_t sw = 0; + + DropField(); + int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); + + if (res) { + PrintAndLog("Can't select authenticator. res=%x. Exit...", res); + DropField(); + return res; + } + + if (sw != 0x9000) { + PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); + return 2; + } + + res = FIDORegister(data, buf, sizeof(buf), &len, &sw); + DropField(); + if (res) { + PrintAndLog("Can't execute register command. res=%x. Exit...", res); + return res; + } + + if (sw != 0x9000) { + PrintAndLog("ERROR execute register command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + return 3; + } + + PrintAndLog(""); + if (APDULogging) + PrintAndLog("---------------------------------------------------------------"); + PrintAndLog("data len: %d", len); + if (verbose) { + PrintAndLog("--------------data----------------------"); + dump_buffer((const unsigned char *)buf, len, NULL, 0); + PrintAndLog("--------------data----------------------"); + } + + if (buf[0] != 0x05) { + PrintAndLog("ERROR: First byte must be 0x05, but it %2x", buf[0]); + return 5; + } + PrintAndLog("User public key: %s", sprint_hex(&buf[1], 65)); + + uint8_t keyHandleLen = buf[66]; + PrintAndLog("Key handle[%d]: %s", keyHandleLen, sprint_hex(&buf[67], keyHandleLen)); + + int derp = 67 + keyHandleLen; + int derLen = (buf[derp + 2] << 8) + buf[derp + 3] + 4; + // needs to decode DER certificate + if (verbose) { + PrintAndLog("DER certificate[%d]:------------------DER-------------------", derLen); + dump_buffer_simple((const unsigned char *)&buf[67 + keyHandleLen], derLen, NULL); + PrintAndLog("\n----------------DER---------------------"); + } else { + PrintAndLog("DER certificate[%d]: %s...", derLen, sprint_hex(&buf[derp], 20)); + } + + + int hashp = 1 + 65 + 1 + keyHandleLen + derLen; + PrintAndLog("Hash[%d]: %s", len - hashp, sprint_hex(&buf[hashp], len - hashp)); + + // check ANSI X9.62 format ECDSA signature (on P-256) + + PrintAndLog("\nauth command: "); + printf("hf fido auth %s%s", paramsPlain?"-p ":"", sprint_hex_inrow(&buf[67], keyHandleLen)); + if(chlen || applen) + printf(" %s", paramsPlain?(char *)cdata:sprint_hex_inrow(cdata, 32)); + if(applen) + printf(" %s", paramsPlain?(char *)adata:sprint_hex_inrow(adata, 32)); + printf("\n"); + + if (root) { + JsonSaveBufAsHex(root, "ChallengeParam", data, 32); + JsonSaveBufAsHex(root, "ApplicationParam", &data[32], 32); + JsonSaveInt(root, "KeyHandleLen", keyHandleLen); + JsonSaveBufAsHexCompact(root, "KeyHandle", &buf[67], keyHandleLen); + JsonSaveBufAsHexCompact(root, "DER", &buf[67 + keyHandleLen], derLen); + + res = json_dump_file(root, fname, JSON_INDENT(2)); + if (res) { + PrintAndLog("ERROR: can't save the file: %s", fname); + return 200; + } + PrintAndLog("File `%s` saved.", fname); + + // free json object + json_decref(root); + } + + return 0; +}; + +int CmdHFFidoAuthenticate(const char *cmd) { + uint8_t data[512] = {0}; + uint8_t hdata[250] = {0}; + int hdatalen = 0; + uint8_t keyHandleLen = 0; + json_t *root = NULL; + + CLIParserInit("hf fido auth", + "Initiate a U2F token authentication. Needs key handle and two 32-byte hash number. \nkey handle(var 0..255), challenge parameter (32b) and application parameter (32b).", + "Usage:\n\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n" + "\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f " + "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_lit0("vV", "verbose", "show technical data"), + arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"), + arg_rem("default mode:", "dont-enforce-user-presence-and-sign"), + arg_lit0("uU", "user", "mode: enforce-user-presence-and-sign"), + arg_lit0("cC", "check", "mode: check-only"), + arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."), + arg_str0(NULL, NULL, "", NULL), + arg_str0(NULL, NULL, "", NULL), + arg_str0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + bool APDULogging = arg_get_lit(1); + //bool verbose = arg_get_lit(2); + bool paramsPlain = arg_get_lit(3); + uint8_t controlByte = 0x08; + if (arg_get_lit(5)) + controlByte = 0x03; + if (arg_get_lit(6)) + controlByte = 0x07; + + char fname[250] = {0}; + bool err; + root = OpenJson(7, fname, argtable, &err); + if(err) + return 1; + if (root) { + size_t jlen; + JsonLoadBufAsHex(root, "$.ChallengeParam", data, 32, &jlen); + JsonLoadBufAsHex(root, "$.ApplicationParam", &data[32], 32, &jlen); + JsonLoadBufAsHex(root, "$.KeyHandle", &data[65], 512 - 67, &jlen); + keyHandleLen = jlen & 0xff; + data[64] = keyHandleLen; + } + + CLIGetHexWithReturn(8, hdata, &hdatalen); + if (hdatalen > 255) { + PrintAndLog("ERROR: application parameter length must be less than 255."); + return 1; + } + if (hdatalen) { + keyHandleLen = hdatalen; + data[64] = keyHandleLen; + memmove(&data[65], hdata, keyHandleLen); + } + + if (paramsPlain) { + memset(hdata, 0x00, 32); + CLIGetStrWithReturn(9, hdata, &hdatalen); + if (hdatalen && hdatalen > 16) { + PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen); + return 1; + } + } else { + CLIGetHexWithReturn(9, hdata, &hdatalen); + if (hdatalen && hdatalen != 32) { + PrintAndLog("ERROR: challenge parameter length must be 32 bytes only."); + return 1; + } + } + if (hdatalen) + memmove(data, hdata, 32); + + if (paramsPlain) { + memset(hdata, 0x00, 32); + CLIGetStrWithReturn(10, hdata, &hdatalen); + if (hdatalen && hdatalen > 16) { + PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen); + return 1; + } + } else { + CLIGetHexWithReturn(10, hdata, &hdatalen); + if (hdatalen && hdatalen != 32) { + PrintAndLog("ERROR: application parameter length must be 32 bytes only."); + return 1; + } + } + if (hdatalen) + memmove(&data[32], hdata, 32); + + CLIParserFree(); + + SetAPDULogging(APDULogging); + + // (in parameter) conrtol byte 0x07 - check only, 0x03 - user presense + cign. 0x08 - sign only + // challenge parameter [32 bytes] + // application parameter [32 bytes] + // key handle length [1b] = N + // key handle [N] + + uint8_t datalen = 32 + 32 + 1 + keyHandleLen; + + uint8_t buf[2048] = {0}; + size_t len = 0; + uint16_t sw = 0; + + DropField(); + int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); + + if (res) { + PrintAndLog("Can't select authenticator. res=%x. Exit...", res); + DropField(); + return res; + } + + if (sw != 0x9000) { + PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); + return 2; + } + + res = FIDOAuthentication(data, datalen, controlByte, buf, sizeof(buf), &len, &sw); + DropField(); + if (res) { + PrintAndLog("Can't execute authentication command. res=%x. Exit...", res); + return res; + } + + if (sw != 0x9000) { + PrintAndLog("ERROR execute authentication command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + return 3; + } + + PrintAndLog("---------------------------------------------------------------"); + PrintAndLog("User presence: %s", (buf[0]?"verified":"not verified")); + uint32_t cntr = (uint32_t)bytes_to_num(&buf[1], 4); + PrintAndLog("Counter: %d", cntr); + PrintAndLog("Hash[%d]: %s", len - 5, sprint_hex(&buf[5], len - 5)); + + if (root) { + JsonSaveBufAsHex(root, "ChallengeParam", data, 32); + JsonSaveBufAsHex(root, "ApplicationParam", &data[32], 32); + JsonSaveInt(root, "KeyHandleLen", keyHandleLen); + JsonSaveBufAsHexCompact(root, "KeyHandle", &data[65], keyHandleLen); + JsonSaveInt(root, "Counter", cntr); + + res = json_dump_file(root, fname, JSON_INDENT(2)); + if (res) { + PrintAndLog("ERROR: can't save the file: %s", fname); + return 200; + } + PrintAndLog("File `%s` saved.", fname); + + // free json object + json_decref(root); + } + return 0; +}; + +static command_t CommandTable[] = +{ + {"help", CmdHelp, 1, "This help."}, + {"info", CmdHFFidoInfo, 0, "Info about FIDO tag."}, + {"reg", CmdHFFidoRegister, 0, "FIDO U2F Registration Message."}, + {"auth", CmdHFFidoAuthenticate, 0, "FIDO U2F Authentication Message."}, + {NULL, NULL, 0, NULL} +}; + +int CmdHFFido(const char *Cmd) { + (void)WaitForResponseTimeout(CMD_ACK,NULL,100); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdhffido.h b/client/cmdhffido.h new file mode 100644 index 000000000..2460a170f --- /dev/null +++ b/client/cmdhffido.h @@ -0,0 +1,27 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency FIDO U2F and FIDO2 contactless authenticators +//----------------------------------------------------------------------------- +// +// Documentation here: +// +// FIDO Alliance specifications +// https://fidoalliance.org/download/ +// FIDO NFC Protocol Specification v1.0 +// https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-nfc-protocol-v1.2-ps-20170411.html +// FIDO U2F Raw Message Formats +// https://fidoalliance.org/specs/fido-u2f-v1.2-ps-20170411/fido-u2f-raw-message-formats-v1.2-ps-20170411.html +//----------------------------------------------------------------------------- + +#ifndef CMDHFFIDO_H__ +#define CMDHFFIDO_H__ + +extern int CmdHFFido(const char *Cmd); + + +#endif \ No newline at end of file diff --git a/client/emv/emvcore.h b/client/emv/emvcore.h index 94be4fcf3..1e39f696c 100644 --- a/client/emv/emvcore.h +++ b/client/emv/emvcore.h @@ -68,6 +68,9 @@ extern struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2); extern void SetAPDULogging(bool logging); +// exchange +extern int EMVExchange(bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); + // search application extern int EMVSearchPSE(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv); extern int EMVSearch(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv); diff --git a/client/emv/emvjson.c b/client/emv/emvjson.c new file mode 100644 index 000000000..e56ecbb71 --- /dev/null +++ b/client/emv/emvjson.c @@ -0,0 +1,385 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// EMV json logic +//----------------------------------------------------------------------------- + +#include "emvjson.h" +#include +#include +#include +#include +#include +#include "util.h" +#include "ui.h" +#include "proxmark3.h" +#include "emv_tags.h" + +static const ApplicationDataElm ApplicationData[] = { +{0x82, "AIP"}, +{0x94, "AFL"}, + +{0x5A, "PAN"}, +{0x5F34, "PANSeqNo"}, +{0x5F24, "ExpirationDate"}, +{0x5F25, "EffectiveDate"}, +{0x5F28, "IssuerCountryCode"}, + +{0x50, "ApplicationLabel"}, +{0x9F08, "VersionNumber"}, +{0x9F42, "CurrencyCode"}, +{0x5F2D, "LanguagePreference"}, +{0x87, "PriorityIndicator"}, +{0x9F36, "ATC"}, //Application Transaction Counter + +{0x5F20, "CardholderName"}, + +{0x9F38, "PDOL"}, +{0x8C, "CDOL1"}, +{0x8D, "CDOL2"}, + +{0x9F07, "AUC"}, // Application Usage Control +{0x9F6C, "CTQ"}, +{0x8E, "CVMList"}, +{0x9F0D, "IACDefault"}, +{0x9F0E, "IACDeny"}, +{0x9F0F, "IACOnline"}, + +{0x8F, "CertificationAuthorityPublicKeyIndex"}, +{0x9F32, "IssuerPublicKeyExponent"}, +{0x92, "IssuerPublicKeyRemainder"}, +{0x90, "IssuerPublicKeyCertificate"}, +{0x9F47, "ICCPublicKeyExponent"}, +{0x9F46, "ICCPublicKeyCertificate"}, + +{0x00, "end..."} +}; +int ApplicationDataLen = sizeof(ApplicationData) / sizeof(ApplicationDataElm); + +char* GetApplicationDataName(tlv_tag_t tag) { + for (int i = 0; i < ApplicationDataLen; i++) + if (ApplicationData[i].Tag == tag) + return ApplicationData[i].Name; + + return NULL; +} + +int JsonSaveJsonObject(json_t *root, char *path, json_t *value) { + json_error_t error; + + if (strlen(path) < 1) + return 1; + + if (path[0] == '$') { + if (json_path_set(root, path, value, 0, &error)) { + PrintAndLog("ERROR: can't set json path: ", error.text); + return 2; + } else { + return 0; + } + } else { + return json_object_set_new(root, path, value); + } +} + +int JsonSaveInt(json_t *root, char *path, int value) { + return JsonSaveJsonObject(root, path, json_integer(value)); +} + +int JsonSaveStr(json_t *root, char *path, char *value) { + return JsonSaveJsonObject(root, path, json_string(value)); +}; + +int JsonSaveBufAsHexCompact(json_t *elm, char *path, uint8_t *data, size_t datalen) { + char * msg = sprint_hex_inrow(data, datalen); + if (msg && strlen(msg) && msg[strlen(msg) - 1] == ' ') + msg[strlen(msg) - 1] = '\0'; + + return JsonSaveStr(elm, path, msg); +} + +int JsonSaveBufAsHex(json_t *elm, char *path, uint8_t *data, size_t datalen) { + char * msg = sprint_hex(data, datalen); + if (msg && strlen(msg) && msg[strlen(msg) - 1] == ' ') + msg[strlen(msg) - 1] = '\0'; + + return JsonSaveStr(elm, path, msg); +} + +int JsonSaveHex(json_t *elm, char *path, uint64_t data, int datalen) { + uint8_t bdata[8] = {0}; + int len = 0; + if (!datalen) { + for (uint64_t u = 0xffffffffffffffff; u; u = u << 8) { + if (!(data & u)) { + break; + } + len++; + } + if (!len) + len = 1; + } else { + len = datalen; + } + num_to_bytes(data, len, bdata); + + return JsonSaveBufAsHex(elm, path, bdata, len); +} + +int JsonSaveTLVValue(json_t *root, char *path, struct tlvdb *tlvdbelm) { + const struct tlv *tlvelm = tlvdb_get_tlv(tlvdbelm); + if (tlvelm) + return JsonSaveBufAsHex(root, path, (uint8_t *)tlvelm->value, tlvelm->len); + else + return 1; +} + +int JsonSaveTLVElm(json_t *elm, char *path, struct tlv *tlvelm, bool saveName, bool saveValue, bool saveAppDataLink) { + json_error_t error; + + if (strlen(path) < 1 || !tlvelm) + return 1; + + if (path[0] == '$') { + + json_t *obj = json_path_get(elm, path); + if (!obj) { + obj = json_object(); + + if (json_is_array(elm)) { + if (json_array_append_new(elm, obj)) { + PrintAndLog("ERROR: can't append array: %s", path); + return 2; + } + } else { + if (json_path_set(elm, path, obj, 0, &error)) { + PrintAndLog("ERROR: can't set json path: ", error.text); + return 2; + } + } + } + + if (saveAppDataLink) { + char * AppDataName = GetApplicationDataName(tlvelm->tag); + if (AppDataName) + JsonSaveStr(obj, "appdata", AppDataName); + } else { + char * name = emv_get_tag_name(tlvelm); + if (saveName && name && strlen(name) > 0 && strncmp(name, "Unknown", 7)) + JsonSaveStr(obj, "name", emv_get_tag_name(tlvelm)); + JsonSaveHex(obj, "tag", tlvelm->tag, 0); + if (saveValue) { + JsonSaveHex(obj, "length", tlvelm->len, 0); + JsonSaveBufAsHex(obj, "value", (uint8_t *)tlvelm->value, tlvelm->len); + }; + } + } + + return 0; +} + +int JsonSaveTLVTreeElm(json_t *elm, char *path, struct tlvdb *tlvdbelm, bool saveName, bool saveValue, bool saveAppDataLink) { + return JsonSaveTLVElm(elm, path, (struct tlv *)tlvdb_get_tlv(tlvdbelm), saveName, saveValue, saveAppDataLink); +} + +int JsonSaveTLVTree(json_t *root, json_t *elm, char *path, struct tlvdb *tlvdbelm) { + struct tlvdb *tlvp = tlvdbelm; + while (tlvp) { + const struct tlv * tlvpelm = tlvdb_get_tlv(tlvp); + char * AppDataName = NULL; + if (tlvpelm) + AppDataName = GetApplicationDataName(tlvpelm->tag); + + if (AppDataName) { + char appdatalink[200] = {0}; + sprintf(appdatalink, "$.ApplicationData.%s", AppDataName); + JsonSaveBufAsHex(root, appdatalink, (uint8_t *)tlvpelm->value, tlvpelm->len); + } + + json_t *pelm = json_path_get(elm, path); + if (pelm && json_is_array(pelm)) { + json_t *appendelm = json_object(); + json_array_append_new(pelm, appendelm); + JsonSaveTLVTreeElm(appendelm, "$", tlvp, !AppDataName, !tlvdb_elm_get_children(tlvp), AppDataName); + pelm = appendelm; + } else { + JsonSaveTLVTreeElm(elm, path, tlvp, !AppDataName, !tlvdb_elm_get_children(tlvp), AppDataName); + pelm = json_path_get(elm, path); + } + + if (tlvdb_elm_get_children(tlvp)) { + // get path element + if(!pelm) + return 1; + + // check childs element and add it if not found + json_t *chjson = json_path_get(pelm, "$.Childs"); + if (!chjson) { + json_object_set_new(pelm, "Childs", json_array()); + + chjson = json_path_get(pelm, "$.Childs"); + } + + // check + if (!json_is_array(chjson)) { + PrintAndLog("E->Internal logic error. `$.Childs` is not an array."); + break; + } + + // Recursion + JsonSaveTLVTree(root, chjson, "$", tlvdb_elm_get_children(tlvp)); + } + + tlvp = tlvdb_elm_get_next(tlvp); + } + return 0; +} + +bool HexToBuffer(const char *errormsg, const char *hexvalue, uint8_t * buffer, size_t maxbufferlen, size_t *bufferlen) { + int buflen = 0; + + switch(param_gethex_to_eol(hexvalue, 0, buffer, maxbufferlen, &buflen)) { + case 1: + PrintAndLog("%s Invalid HEX value.", errormsg); + return false; + case 2: + PrintAndLog("%s Hex value too large.", errormsg); + return false; + case 3: + PrintAndLog("%s Hex value must have even number of digits.", errormsg); + return false; + } + + if (buflen > maxbufferlen) { + PrintAndLog("%s HEX length (%d) more than %d", errormsg, *bufferlen, maxbufferlen); + return false; + } + + *bufferlen = buflen; + + return true; +} + +int JsonLoadBufAsHex(json_t *elm, char *path, uint8_t *data, size_t maxbufferlen, size_t *datalen) { + if (datalen) + *datalen = 0; + + json_t *jelm = json_path_get((const json_t *)elm, path); + if (!jelm || !json_is_string(jelm)) + return 1; + + if (!HexToBuffer("ERROR load", json_string_value(jelm), data, maxbufferlen, datalen)) + return 2; + + return 0; +}; + +bool ParamLoadFromJson(struct tlvdb *tlv) { + json_t *root; + json_error_t error; + + if (!tlv) { + PrintAndLog("ERROR load params: tlv tree is NULL."); + return false; + } + + // current path + file name + const char *relfname = "emv/defparams.json"; + char fname[strlen(get_my_executable_directory()) + strlen(relfname) + 1]; + strcpy(fname, get_my_executable_directory()); + strcat(fname, relfname); + + root = json_load_file(fname, 0, &error); + if (!root) { + PrintAndLog("Load params: json error on line %d: %s", error.line, error.text); + return false; + } + + if (!json_is_array(root)) { + PrintAndLog("Load params: Invalid json format. root must be array."); + return false; + } + + PrintAndLog("Load params: json(%d) OK", json_array_size(root)); + + for(int i = 0; i < json_array_size(root); i++) { + json_t *data, *jtag, *jlength, *jvalue; + + data = json_array_get(root, i); + if(!json_is_object(data)) + { + PrintAndLog("Load params: data [%d] is not an object", i + 1); + json_decref(root); + return false; + } + + jtag = json_object_get(data, "tag"); + if(!json_is_string(jtag)) + { + PrintAndLog("Load params: data [%d] tag is not a string", i + 1); + json_decref(root); + return false; + } + const char *tlvTag = json_string_value(jtag); + + jvalue = json_object_get(data, "value"); + if(!json_is_string(jvalue)) + { + PrintAndLog("Load params: data [%d] value is not a string", i + 1); + json_decref(root); + return false; + } + const char *tlvValue = json_string_value(jvalue); + + jlength = json_object_get(data, "length"); + if(!json_is_number(jlength)) + { + PrintAndLog("Load params: data [%d] length is not a number", i + 1); + json_decref(root); + return false; + } + + int tlvLength = json_integer_value(jlength); + if (tlvLength > 250) { + PrintAndLog("Load params: data [%d] length more than 250", i + 1); + json_decref(root); + return false; + } + + PrintAndLog("TLV param: %s[%d]=%s", tlvTag, tlvLength, tlvValue); + uint8_t buf[251] = {0}; + size_t buflen = 0; + + // here max length must be 4, but now tlv_tag_t is 2-byte var. so let it be 2 by now... TODO: needs refactoring tlv_tag_t... + if (!HexToBuffer("TLV Error type:", tlvTag, buf, 2, &buflen)) { + json_decref(root); + return false; + } + tlv_tag_t tag = 0; + for (int i = 0; i < buflen; i++) { + tag = (tag << 8) + buf[i]; + } + + if (!HexToBuffer("TLV Error value:", tlvValue, buf, sizeof(buf) - 1, &buflen)) { + json_decref(root); + return false; + } + + if (buflen != tlvLength) { + PrintAndLog("Load params: data [%d] length of HEX must(%d) be identical to length in TLV param(%d)", i + 1, buflen, tlvLength); + json_decref(root); + return false; + } + + tlvdb_change_or_add_node(tlv, tag, tlvLength, (const unsigned char *)buf); + } + + json_decref(root); + + return true; +} + diff --git a/client/emv/emvjson.h b/client/emv/emvjson.h new file mode 100644 index 000000000..9c6eda5ea --- /dev/null +++ b/client/emv/emvjson.h @@ -0,0 +1,40 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// EMV json logic +//----------------------------------------------------------------------------- +#ifndef EMVJSON_H__ +#define EMVJSON_H__ + +#include +#include "tlv.h" + +typedef struct { + tlv_tag_t Tag; + char *Name; +} ApplicationDataElm; + +extern char* GetApplicationDataName(tlv_tag_t tag); + +extern int JsonSaveJsonObject(json_t *root, char *path, json_t *value); +extern int JsonSaveStr(json_t *root, char *path, char *value); +extern int JsonSaveInt(json_t *root, char *path, int value); +extern int JsonSaveBufAsHexCompact(json_t *elm, char *path, uint8_t *data, size_t datalen); +extern int JsonSaveBufAsHex(json_t *elm, char *path, uint8_t *data, size_t datalen); +extern int JsonSaveHex(json_t *elm, char *path, uint64_t data, int datalen); + +extern int JsonSaveTLVValue(json_t *root, char *path, struct tlvdb *tlvdbelm); +extern int JsonSaveTLVElm(json_t *elm, char *path, struct tlv *tlvelm, bool saveName, bool saveValue, bool saveAppDataLink); +extern int JsonSaveTLVTreeElm(json_t *elm, char *path, struct tlvdb *tlvdbelm, bool saveName, bool saveValue, bool saveAppDataLink); + +extern int JsonSaveTLVTree(json_t *root, json_t *elm, char *path, struct tlvdb *tlvdbelm); + +extern int JsonLoadBufAsHex(json_t *elm, char *path, uint8_t *data, size_t maxbufferlen, size_t *datalen); + +extern bool ParamLoadFromJson(struct tlvdb *tlv); + +#endif \ No newline at end of file diff --git a/client/util.c b/client/util.c index 6ed6201fa..3e6c7cdc6 100644 --- a/client/util.c +++ b/client/util.c @@ -9,6 +9,7 @@ //----------------------------------------------------------------------------- #include "util.h" +#define UTIL_BUFFER_SIZE_SPRINT 4097 // global client debug variable uint8_t g_debugMode = 0; @@ -170,13 +171,13 @@ void print_hex_break(const uint8_t *data, const size_t len, uint8_t breaks) { } char *sprint_hex(const uint8_t *data, const size_t len) { - static char buf[1025] = {0}; + static char buf[UTIL_BUFFER_SIZE_SPRINT] = {0}; hex_to_buffer((uint8_t *)buf, data, len, sizeof(buf) - 1, 0, 1, true); return buf; } char *sprint_hex_inrow_ex(const uint8_t *data, const size_t len, const size_t min_str_len) { - static char buf[1025] = {0}; + static char buf[UTIL_BUFFER_SIZE_SPRINT] = {0}; hex_to_buffer((uint8_t *)buf, data, len, sizeof(buf) - 1, min_str_len, 0, true); return buf; } @@ -185,13 +186,11 @@ char *sprint_hex_inrow(const uint8_t *data, const size_t len) { return sprint_hex_inrow_ex(data, len, 0); } char *sprint_hex_inrow_spaces(const uint8_t *data, const size_t len, size_t spaces_between) { - static char buf[1025] = {0}; + static char buf[UTIL_BUFFER_SIZE_SPRINT] = {0}; hex_to_buffer((uint8_t *)buf, data, len, sizeof(buf) - 1, 0, spaces_between, true); return buf; } - - char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks) { // make sure we don't go beyond our char array memory @@ -268,9 +267,9 @@ char *sprint_bin(const uint8_t *data, const size_t len) { } char *sprint_hex_ascii(const uint8_t *data, const size_t len) { - static char buf[1024]; + static char buf[UTIL_BUFFER_SIZE_SPRINT]; char *tmp = buf; - memset(buf, 0x00, 1024); + memset(buf, 0x00, UTIL_BUFFER_SIZE_SPRINT); size_t max_len = (len > 1010) ? 1010 : len; sprintf(tmp, "%s| ", sprint_hex(data, max_len) ); @@ -288,9 +287,9 @@ char *sprint_hex_ascii(const uint8_t *data, const size_t len) { } char *sprint_ascii_ex(const uint8_t *data, const size_t len, const size_t min_str_len) { - static char buf[1024]; + static char buf[UTIL_BUFFER_SIZE_SPRINT]; char *tmp = buf; - memset(buf, 0x00, 1024); + memset(buf, 0x00, UTIL_BUFFER_SIZE_SPRINT); size_t max_len = (len > 1010) ? 1010 : len; size_t i = 0; while(i < max_len){ From f03261be9a8401a1b45fd287ddc4450cfcdc1fb3 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 8 Nov 2018 19:14:30 +0200 Subject: [PATCH 0141/1938] compiled. not linking.... --- client/Makefile | 7 +- client/emv/emvjson.h | 1 + client/jansson/hashtable.h | 176 +++++++++++++++++++++++++++ client/jansson/jansson_private.h | 112 +++++++++++++++++ client/jansson/path.c | 202 +++++++++++++++++++++++++++++++ client/jansson/path.h | 17 +++ client/jansson/strbuffer.h | 34 ++++++ client/obj/jansson/.dummy | 0 8 files changed, 546 insertions(+), 3 deletions(-) create mode 100644 client/jansson/hashtable.h create mode 100644 client/jansson/jansson_private.h create mode 100644 client/jansson/path.c create mode 100644 client/jansson/path.h create mode 100644 client/jansson/strbuffer.h create mode 100644 client/obj/jansson/.dummy diff --git a/client/Makefile b/client/Makefile index 1e6ad4426..5f139bf4e 100644 --- a/client/Makefile +++ b/client/Makefile @@ -23,10 +23,10 @@ ENV_CFLAGS := $(CFLAGS) VPATH = ../common ../zlib ../uart OBJDIR = obj -LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm -ljansson +LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm -L/usr/include LUALIB = ../liblua/liblua.a LDFLAGS = $(ENV_LDFLAGS) -INCLUDES_CLIENT = -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua +INCLUDES_CLIENT = -I/usr/include -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua CFLAGS = $(ENV_CFLAGS) -std=c99 -D_ISOC99_SOURCE -DPRESETS $(INCLUDES_CLIENT) -Wall -g -O3 CXXFLAGS = -I../include -Wall -O3 @@ -103,6 +103,7 @@ CMDSRCS = crapto1/crapto1.c \ crapto1/crypto1.c \ mfkey.c \ tea.c \ + jansson/path.c \ polarssl/des.c \ polarssl/aes.c \ polarssl/aes_cmac128.c \ @@ -134,7 +135,6 @@ CMDSRCS = crapto1/crapto1.c \ lfdemod.c \ emv/crypto_polarssl.c\ emv/crypto.c\ - emv/emvjson.c\ emv/emv_pk.c\ emv/emv_pki.c\ emv/emv_pki_priv.c\ @@ -144,6 +144,7 @@ CMDSRCS = crapto1/crapto1.c \ emv/tlv.c \ emv/emv_tags.c \ emv/dol.c \ + emv/emvjson.c\ emv/emvcore.c \ emv/test/crypto_test.c\ emv/test/sda_test.c\ diff --git a/client/emv/emvjson.h b/client/emv/emvjson.h index 9c6eda5ea..32b2484d2 100644 --- a/client/emv/emvjson.h +++ b/client/emv/emvjson.h @@ -12,6 +12,7 @@ #include #include "tlv.h" +#include "jansson/path.h" typedef struct { tlv_tag_t Tag; diff --git a/client/jansson/hashtable.h b/client/jansson/hashtable.h new file mode 100644 index 000000000..d4c32ae0e --- /dev/null +++ b/client/jansson/hashtable.h @@ -0,0 +1,176 @@ +/* + * Copyright (c) 2009-2016 Petri Lehtinen + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef HASHTABLE_H +#define HASHTABLE_H + +#include +#include "jansson.h" + +struct hashtable_list { + struct hashtable_list *prev; + struct hashtable_list *next; +}; + +/* "pair" may be a bit confusing a name, but think of it as a + key-value pair. In this case, it just encodes some extra data, + too */ +struct hashtable_pair { + struct hashtable_list list; + struct hashtable_list ordered_list; + size_t hash; + json_t *value; + char key[1]; +}; + +struct hashtable_bucket { + struct hashtable_list *first; + struct hashtable_list *last; +}; + +typedef struct hashtable { + size_t size; + struct hashtable_bucket *buckets; + size_t order; /* hashtable has pow(2, order) buckets */ + struct hashtable_list list; + struct hashtable_list ordered_list; +} hashtable_t; + + +#define hashtable_key_to_iter(key_) \ + (&(container_of(key_, struct hashtable_pair, key)->ordered_list)) + + +/** + * hashtable_init - Initialize a hashtable object + * + * @hashtable: The (statically allocated) hashtable object + * + * Initializes a statically allocated hashtable object. The object + * should be cleared with hashtable_close when it's no longer used. + * + * Returns 0 on success, -1 on error (out of memory). + */ +int hashtable_init(hashtable_t *hashtable); + +/** + * hashtable_close - Release all resources used by a hashtable object + * + * @hashtable: The hashtable + * + * Destroys a statically allocated hashtable object. + */ +void hashtable_close(hashtable_t *hashtable); + +/** + * hashtable_set - Add/modify value in hashtable + * + * @hashtable: The hashtable object + * @key: The key + * @serial: For addition order of keys + * @value: The value + * + * If a value with the given key already exists, its value is replaced + * with the new value. Value is "stealed" in the sense that hashtable + * doesn't increment its refcount but decreases the refcount when the + * value is no longer needed. + * + * Returns 0 on success, -1 on failure (out of memory). + */ +int hashtable_set(hashtable_t *hashtable, const char *key, json_t *value); + +/** + * hashtable_get - Get a value associated with a key + * + * @hashtable: The hashtable object + * @key: The key + * + * Returns value if it is found, or NULL otherwise. + */ +void *hashtable_get(hashtable_t *hashtable, const char *key); + +/** + * hashtable_del - Remove a value from the hashtable + * + * @hashtable: The hashtable object + * @key: The key + * + * Returns 0 on success, or -1 if the key was not found. + */ +int hashtable_del(hashtable_t *hashtable, const char *key); + +/** + * hashtable_clear - Clear hashtable + * + * @hashtable: The hashtable object + * + * Removes all items from the hashtable. + */ +void hashtable_clear(hashtable_t *hashtable); + +/** + * hashtable_iter - Iterate over hashtable + * + * @hashtable: The hashtable object + * + * Returns an opaque iterator to the first element in the hashtable. + * The iterator should be passed to hashtable_iter_* functions. + * The hashtable items are not iterated over in any particular order. + * + * There's no need to free the iterator in any way. The iterator is + * valid as long as the item that is referenced by the iterator is not + * deleted. Other values may be added or deleted. In particular, + * hashtable_iter_next() may be called on an iterator, and after that + * the key/value pair pointed by the old iterator may be deleted. + */ +void *hashtable_iter(hashtable_t *hashtable); + +/** + * hashtable_iter_at - Return an iterator at a specific key + * + * @hashtable: The hashtable object + * @key: The key that the iterator should point to + * + * Like hashtable_iter() but returns an iterator pointing to a + * specific key. + */ +void *hashtable_iter_at(hashtable_t *hashtable, const char *key); + +/** + * hashtable_iter_next - Advance an iterator + * + * @hashtable: The hashtable object + * @iter: The iterator + * + * Returns a new iterator pointing to the next element in the + * hashtable or NULL if the whole hastable has been iterated over. + */ +void *hashtable_iter_next(hashtable_t *hashtable, void *iter); + +/** + * hashtable_iter_key - Retrieve the key pointed by an iterator + * + * @iter: The iterator + */ +void *hashtable_iter_key(void *iter); + +/** + * hashtable_iter_value - Retrieve the value pointed by an iterator + * + * @iter: The iterator + */ +void *hashtable_iter_value(void *iter); + +/** + * hashtable_iter_set - Set the value pointed by an iterator + * + * @iter: The iterator + * @value: The value to set + */ +void hashtable_iter_set(void *iter, json_t *value); + +#endif diff --git a/client/jansson/jansson_private.h b/client/jansson/jansson_private.h new file mode 100644 index 000000000..7b0985aa6 --- /dev/null +++ b/client/jansson/jansson_private.h @@ -0,0 +1,112 @@ +/* + * Copyright (c) 2009-2016 Petri Lehtinen + * + * Jansson is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef JANSSON_PRIVATE_H +#define JANSSON_PRIVATE_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include "jansson.h" +#include "hashtable.h" +#include "strbuffer.h" + +#define container_of(ptr_, type_, member_) \ + ((type_ *)((char *)ptr_ - offsetof(type_, member_))) + +/* On some platforms, max() may already be defined */ +#ifndef max +#define max(a, b) ((a) > (b) ? (a) : (b)) +#endif + +/* va_copy is a C99 feature. In C89 implementations, it's sometimes + available as __va_copy. If not, memcpy() should do the trick. */ +#ifndef va_copy +#ifdef __va_copy +#define va_copy __va_copy +#else +#define va_copy(a, b) memcpy(&(a), &(b), sizeof(va_list)) +#endif +#endif + +typedef struct { + json_t json; + hashtable_t hashtable; +} json_object_t; + +typedef struct { + json_t json; + size_t size; + size_t entries; + json_t **table; +} json_array_t; + +typedef struct { + json_t json; + char *value; + size_t length; +} json_string_t; + +typedef struct { + json_t json; + double value; +} json_real_t; + +typedef struct { + json_t json; + json_int_t value; +} json_integer_t; + +#define json_to_object(json_) container_of(json_, json_object_t, json) +#define json_to_array(json_) container_of(json_, json_array_t, json) +#define json_to_string(json_) container_of(json_, json_string_t, json) +#define json_to_real(json_) container_of(json_, json_real_t, json) +#define json_to_integer(json_) container_of(json_, json_integer_t, json) + +/* Create a string by taking ownership of an existing buffer */ +json_t *jsonp_stringn_nocheck_own(const char *value, size_t len); + +/* Error message formatting */ +void jsonp_error_init(json_error_t *error, const char *source); +void jsonp_error_set_source(json_error_t *error, const char *source); +void jsonp_error_set(json_error_t *error, int line, int column, + size_t position, enum json_error_code code, + const char *msg, ...); +void jsonp_error_vset(json_error_t *error, int line, int column, + size_t position, enum json_error_code code, + const char *msg, va_list ap); + +/* Locale independent string<->double conversions */ +int jsonp_strtod(strbuffer_t *strbuffer, double *out); +int jsonp_dtostr(char *buffer, size_t size, double value, int prec); + +/* Wrappers for custom memory functions */ +void* jsonp_malloc(size_t size); +void jsonp_free(void *ptr); +char *jsonp_strndup(const char *str, size_t length); +char *jsonp_strdup(const char *str); +char *jsonp_strndup(const char *str, size_t len); + + +/* Windows compatibility */ +#if defined(_WIN32) || defined(WIN32) +# if defined(_MSC_VER) /* MS compiller */ +# if (_MSC_VER < 1900) && !defined(snprintf) /* snprintf not defined yet & not introduced */ +# define snprintf _snprintf +# endif +# if (_MSC_VER < 1500) && !defined(vsnprintf) /* vsnprintf not defined yet & not introduced */ +# define vsnprintf(b,c,f,a) _vsnprintf(b,c,f,a) +# endif +# else /* Other Windows compiller, old definition */ +# define snprintf _snprintf +# define vsnprintf _vsnprintf +# endif +#endif + +#endif diff --git a/client/jansson/path.c b/client/jansson/path.c new file mode 100644 index 000000000..08f2da9f6 --- /dev/null +++ b/client/jansson/path.c @@ -0,0 +1,202 @@ +/* + * Copyright (c) 2012 Rogerz Zhang + * + * Jansson is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + * + * source here https://github.com/rogerz/jansson/blob/json_path/src/path.c + */ + +#include +#include + +#include +#include "jansson_private.h" + + +json_t *json_path_get(const json_t *json, const char *path) +{ + static const char root_chr = '$', array_open = '['; + static const char *path_delims = ".[", *array_close = "]"; + const json_t *cursor; + char *token, *buf, *peek, *endptr, delim = '\0'; + const char *expect; + + if (!json || !path || path[0] != root_chr) + return NULL; + else + buf = jsonp_strdup(path); + + peek = buf + 1; + cursor = json; + token = NULL; + expect = path_delims; + + while (peek && *peek && cursor) + { + char *last_peek = peek; + peek = strpbrk(peek, expect); + if (peek) { + if (!token && peek != last_peek) + goto fail; + delim = *peek; + *peek++ = '\0'; + } else if (expect != path_delims || !token) { + goto fail; + } + + if (expect == path_delims) { + if (token) { + cursor = json_object_get(cursor, token); + } + expect = (delim == array_open ? array_close : path_delims); + token = peek; + } else if (expect == array_close) { + size_t index = strtol(token, &endptr, 0); + if (*endptr) + goto fail; + cursor = json_array_get(cursor, index); + token = NULL; + expect = path_delims; + } else { + goto fail; + } + } + + jsonp_free(buf); + return (json_t *)cursor; +fail: + jsonp_free(buf); + return NULL; +} + +int json_path_set_new(json_t *json, const char *path, json_t *value, size_t flags, json_error_t *error) +{ + static const char root_chr = '$', array_open = '[', object_delim = '.'; + static const char * const path_delims = ".[", *array_close = "]"; + + json_t *cursor, *parent = NULL; + char *token, *buf = NULL, *peek, delim = '\0'; + const char *expect; + int index_saved = -1; + + jsonp_error_init(error, ""); + + if (!json || !path || flags || !value) { + jsonp_error_set(error, -1, -1, 0, json_error_invalid_argument, "invalid argument"); + goto fail; + } else { + buf = jsonp_strdup(path); + } + + if (buf[0] != root_chr) { + jsonp_error_set(error, -1, -1, 0, json_error_invalid_format, "path should start with $"); + goto fail; + } + + peek = buf + 1; + cursor = json; + token = NULL; + expect = path_delims; + + while (peek && *peek && cursor) + { + char *last_peek = peek; + peek = strpbrk(last_peek, expect); + + if (peek) { + if (!token && peek != last_peek) { + jsonp_error_set(error, -1, -1, last_peek - buf, json_error_invalid_format, "unexpected trailing chars"); + goto fail; + } + delim = *peek; + *peek++ = '\0'; + } else { // end of path + if (expect == path_delims) { + break; + } else { + jsonp_error_set(error, -1, -1, peek - buf, json_error_invalid_format, "missing ']'?"); + goto fail; + } + } + + if (expect == path_delims) { + if (token) { + if (token[0] == '\0') { + jsonp_error_set(error, -1, -1, peek - buf, json_error_invalid_format, "empty token"); + goto fail; + } + + parent = cursor; + cursor = json_object_get(parent, token); + + if (!cursor) { + if (!json_is_object(parent)) { + jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "object expected"); + goto fail; + } + if (delim == object_delim) { + cursor = json_object(); + json_object_set_new(parent, token, cursor); + } else { + jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "new array is not allowed"); + goto fail; + } + } + } + expect = (delim == array_open ? array_close : path_delims); + token = peek; + } else if (expect == array_close) { + char *endptr; + size_t index; + + parent = cursor; + if (!json_is_array(parent)) { + jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "array expected"); + goto fail; + } + index = strtol(token, &endptr, 0); + if (*endptr) { + jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "invalid array index"); + goto fail; + } + cursor = json_array_get(parent, index); + if (!cursor) { + jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "array index out of bound"); + goto fail; + } + index_saved = index; + token = NULL; + expect = path_delims; + } else { + assert(1); + jsonp_error_set(error, -1, -1, peek - buf, json_error_unknown, "unexpected error in path move"); + goto fail; + } + } + + if (token) { + if (json_is_object(cursor)) { + json_object_set(cursor, token, value); + } else { + jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "object expected"); + goto fail; + } + cursor = json_object_get(cursor, token); + } else if (index_saved != -1 && json_is_array(parent)) { + json_array_set(parent, index_saved, value); + cursor = json_array_get(parent, index_saved); + } else { + jsonp_error_set(error, -1, -1, peek - buf, json_error_item_not_found, "invalid path"); + goto fail; + } + + json_decref(value); + jsonp_free(buf); + return 0; + +fail: + json_decref(value); + jsonp_free(buf); + return -1; +} diff --git a/client/jansson/path.h b/client/jansson/path.h new file mode 100644 index 000000000..e6cf31a2b --- /dev/null +++ b/client/jansson/path.h @@ -0,0 +1,17 @@ +/* + * Copyright (c) 2012 Rogerz Zhang + * + * Jansson is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + * + * source here https://github.com/rogerz/jansson/blob/json_path/src/path.c + */ + +json_t *json_path_get(const json_t *json, const char *path); +int json_path_set_new(json_t *json, const char *path, json_t *value, size_t flags, json_error_t *error); + +static JSON_INLINE +int json_path_set(json_t *json, const char *path, json_t *value, size_t flags, json_error_t *error) +{ + return json_path_set_new(json, path, json_incref(value), flags, error); +} diff --git a/client/jansson/strbuffer.h b/client/jansson/strbuffer.h new file mode 100644 index 000000000..615b7f5ff --- /dev/null +++ b/client/jansson/strbuffer.h @@ -0,0 +1,34 @@ +/* + * Copyright (c) 2009-2016 Petri Lehtinen + * + * Jansson is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef STRBUFFER_H +#define STRBUFFER_H + +#include + +typedef struct { + char *value; + size_t length; /* bytes used */ + size_t size; /* bytes allocated */ +} strbuffer_t; + +int strbuffer_init(strbuffer_t *strbuff); +void strbuffer_close(strbuffer_t *strbuff); + +void strbuffer_clear(strbuffer_t *strbuff); + +const char *strbuffer_value(const strbuffer_t *strbuff); + +/* Steal the value and close the strbuffer */ +char *strbuffer_steal_value(strbuffer_t *strbuff); + +int strbuffer_append_byte(strbuffer_t *strbuff, char byte); +int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size); + +char strbuffer_pop(strbuffer_t *strbuff); + +#endif diff --git a/client/obj/jansson/.dummy b/client/obj/jansson/.dummy new file mode 100644 index 000000000..e69de29bb From 074c138de7297d9b4962e1794f43e055c25eed63 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 8 Nov 2018 19:55:51 +0200 Subject: [PATCH 0142/1938] all works except of jansson private symbols linking --- client/Makefile | 2 +- client/emv/emv_tags.c | 18 ++++++++-- client/emv/emv_tags.h | 2 +- client/emv/tlv.c | 83 +++++++++++++++++++++++++++++++++++++++++++ client/emv/tlv.h | 7 ++++ 5 files changed, 108 insertions(+), 4 deletions(-) diff --git a/client/Makefile b/client/Makefile index 5f139bf4e..30a2fa26c 100644 --- a/client/Makefile +++ b/client/Makefile @@ -23,7 +23,7 @@ ENV_CFLAGS := $(CFLAGS) VPATH = ../common ../zlib ../uart OBJDIR = obj -LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm -L/usr/include +LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm -L/usr/lib -ljansson LUALIB = ../liblua/liblua.a LDFLAGS = $(ENV_LDFLAGS) INCLUDES_CLIENT = -I/usr/include -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index a1bf3d25e..cc2897127 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -272,7 +272,7 @@ static const struct emv_tag emv_tags[] = { { 0x9f6a, "Unpredictable Number", EMV_TAG_NUMERIC }, { 0x9f6b, "Track 2 Data" }, { 0x9f6c, "Card Transaction Qualifiers (CTQ)", EMV_TAG_BITMASK, &EMV_CTQ }, - { 0x9f6e, "Form Factor Indicator" }, + { 0x9f6e, "Form Factor Indicator" }, { 0xa5 , "File Control Information (FCI) Proprietary Template" }, { 0xbf0c, "File Control Information (FCI) Issuer Discretionary Data" }, { 0xdf20, "Issuer Proprietary Bitmap (IPB)" }, @@ -391,7 +391,7 @@ static unsigned long emv_value_numeric(const struct tlv *tlv, unsigned start, un static void emv_tag_dump_numeric(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { PRINT_INDENT(level); - fprintf(f, "\tNumeric value %" PRIu32 " \n", emv_value_numeric(tlv, 0, tlv->len * 2)); + fprintf(f, "\tNumeric value %lu\n", emv_value_numeric(tlv, 0, tlv->len * 2)); } static void emv_tag_dump_yymmdd(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { @@ -681,3 +681,17 @@ bool emv_tag_dump(const struct tlv *tlv, FILE *f, int level) return true; } + +char *emv_get_tag_name(const struct tlv *tlv) +{ + static char *defstr = ""; + + if (!tlv) + return defstr; + + const struct emv_tag *tag = emv_get_tag(tlv); + if (tag) + return tag->name; + + return defstr; +} diff --git a/client/emv/emv_tags.h b/client/emv/emv_tags.h index a9d1eea98..246fc72d7 100644 --- a/client/emv/emv_tags.h +++ b/client/emv/emv_tags.h @@ -18,7 +18,6 @@ #include "tlv.h" #include -#include // AC # define EMVAC_AC_MASK 0xC0 @@ -32,5 +31,6 @@ # define EMVCID_REASON_MASK 0x07 bool emv_tag_dump(const struct tlv *tlv, FILE *f, int level); +char *emv_get_tag_name(const struct tlv *tlv); #endif diff --git a/client/emv/tlv.c b/client/emv/tlv.c index 1be917776..540c33e4c 100644 --- a/client/emv/tlv.c +++ b/client/emv/tlv.c @@ -318,6 +318,24 @@ struct tlvdb *tlvdb_find(struct tlvdb *tlvdb, tlv_tag_t tag) { return NULL; } +struct tlvdb *tlvdb_find_full(struct tlvdb *tlvdb, tlv_tag_t tag) { + if (!tlvdb) + return NULL; + + for (; tlvdb; tlvdb = tlvdb->next) { + if (tlvdb->tag.tag == tag) + return tlvdb; + + if (tlvdb->children) { + struct tlvdb * ch = tlvdb_find_full(tlvdb->children, tag); + if (ch) + return ch; + } + } + + return NULL; +} + struct tlvdb *tlvdb_find_path(struct tlvdb *tlvdb, tlv_tag_t tag[]) { int i = 0; struct tlvdb *tnext = tlvdb; @@ -342,6 +360,52 @@ void tlvdb_add(struct tlvdb *tlvdb, struct tlvdb *other) tlvdb->next = other; } +void tlvdb_change_or_add_node(struct tlvdb *tlvdb, tlv_tag_t tag, size_t len, const unsigned char *value) +{ + struct tlvdb *telm = tlvdb_find_full(tlvdb, tag); + if (telm == NULL) { + // new tlv element + tlvdb_add(tlvdb, tlvdb_fixed(tag, len, value)); + } else { + // the same tlv structure + if (telm->tag.tag == tag && telm->tag.len == len && !memcmp(telm->tag.value, value, len)) + return; + + // replace tlv element + struct tlvdb *tnewelm = tlvdb_fixed(tag, len, value); + tnewelm->next = telm->next; + tnewelm->parent = telm->parent; + + // if telm stayed first in children chain + if (telm->parent && telm->parent->children == telm) { + telm->parent->children = tnewelm; + } + + // if telm have previous element + if (telm != tlvdb) { + // elm in root + struct tlvdb *celm = tlvdb; + // elm in child list of node + if (telm->parent && telm->parent->children) + celm = telm->parent->children; + + // find previous element + for (; celm; celm = celm->next) { + if (celm->next == telm) { + celm->next = tnewelm; + break; + } + } + } + + // free old element with childrens + telm->next = NULL; + tlvdb_free(telm); + } + + return; +} + void tlvdb_visit(const struct tlvdb *tlvdb, tlv_cb cb, void *data, int level) { struct tlvdb *next = NULL; @@ -394,6 +458,10 @@ const struct tlv *tlvdb_get_inchild(const struct tlvdb *tlvdb, tlv_tag_t tag, co return tlvdb_get(tlvdb, tag, prev); } +const struct tlv *tlvdb_get_tlv(const struct tlvdb *tlvdb) { + return &tlvdb->tag; +} + unsigned char *tlv_encode(const struct tlv *tlv, size_t *len) { size_t size = tlv->len; @@ -452,3 +520,18 @@ bool tlv_equal(const struct tlv *a, const struct tlv *b) return a->tag == b->tag && a->len == b->len && !memcmp(a->value, b->value, a->len); } + +struct tlvdb *tlvdb_elm_get_next(struct tlvdb *tlvdb) +{ + return tlvdb->next; +} + +struct tlvdb *tlvdb_elm_get_children(struct tlvdb *tlvdb) +{ + return tlvdb->children; +} + +struct tlvdb *tlvdb_elm_get_parent(struct tlvdb *tlvdb) +{ + return tlvdb->parent; +} diff --git a/client/emv/tlv.h b/client/emv/tlv.h index 5b8b68250..b25b51de2 100644 --- a/client/emv/tlv.h +++ b/client/emv/tlv.h @@ -39,15 +39,22 @@ struct tlvdb *tlvdb_parse(const unsigned char *buf, size_t len); struct tlvdb *tlvdb_parse_multi(const unsigned char *buf, size_t len); void tlvdb_free(struct tlvdb *tlvdb); +struct tlvdb *tlvdb_elm_get_next(struct tlvdb *tlvdb); +struct tlvdb *tlvdb_elm_get_children(struct tlvdb *tlvdb); +struct tlvdb *tlvdb_elm_get_parent(struct tlvdb *tlvdb); + +struct tlvdb *tlvdb_find_full(struct tlvdb *tlvdb, tlv_tag_t tag); // search also in childrens struct tlvdb *tlvdb_find(struct tlvdb *tlvdb, tlv_tag_t tag); struct tlvdb *tlvdb_find_next(struct tlvdb *tlvdb, tlv_tag_t tag); struct tlvdb *tlvdb_find_path(struct tlvdb *tlvdb, tlv_tag_t tag[]); void tlvdb_add(struct tlvdb *tlvdb, struct tlvdb *other); +void tlvdb_change_or_add_node(struct tlvdb *tlvdb, tlv_tag_t tag, size_t len, const unsigned char *value); void tlvdb_visit(const struct tlvdb *tlvdb, tlv_cb cb, void *data, int level); const struct tlv *tlvdb_get(const struct tlvdb *tlvdb, tlv_tag_t tag, const struct tlv *prev); const struct tlv *tlvdb_get_inchild(const struct tlvdb *tlvdb, tlv_tag_t tag, const struct tlv *prev); +const struct tlv *tlvdb_get_tlv(const struct tlvdb *tlvdb); bool tlv_parse_tl(const unsigned char **buf, size_t *len, struct tlv *tlv); unsigned char *tlv_encode(const struct tlv *tlv, size_t *len); From 0cfa47e6286854d317dee30e8a45f0a5b166d1c8 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 8 Nov 2018 20:29:08 +0200 Subject: [PATCH 0143/1938] merged iso14 arm side --- armsrc/iso14443a.c | 29 ++++++++++++++++++++--------- armsrc/iso14443a.h | 2 +- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index f6be25a50..20225f416 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2212,15 +2212,21 @@ b8 b7 b6 b5 b4 b3 b2 b1 b5,b6 = 00 - DESELECT 11 - WTX */ -int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) { +int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data, uint8_t *res) { uint8_t parity[MAX_PARITY_SIZE] = {0x00}; - uint8_t real_cmd[cmd_len+4]; + uint8_t real_cmd[cmd_len + 4]; - // ISO 14443 APDU frame: PCB [CID] [NAD] APDU CRC PCB=0x02 - real_cmd[0] = 0x02; // bnr,nad,cid,chn=0; i-block(0x00) - // put block number into the PCB - real_cmd[0] |= iso14_pcb_blocknum; - memcpy(real_cmd + 1, cmd, cmd_len); + if (cmd_len) { + // ISO 14443 APDU frame: PCB [CID] [NAD] APDU CRC PCB=0x02 + real_cmd[0] = 0x02; // bnr,nad,cid,chn=0; i-block(0x00) + // put block number into the PCB + real_cmd[0] |= iso14_pcb_blocknum; + memcpy(real_cmd + 1, cmd, cmd_len); + } else { + // R-block. ACK + real_cmd[0] = 0xA2; // r-block + ACK + real_cmd[0] |= iso14_pcb_blocknum; + } AddCrc14A(real_cmd, cmd_len + 1); ReaderTransmit(real_cmd, cmd_len + 3, NULL); @@ -2259,6 +2265,10 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data) { { iso14_pcb_blocknum ^= 1; } + + // if we received I-block with chaining we need to send ACK and receive another block of data + if (res) + *res = data_bytes[0]; // crc check if (len >=3 && !check_crc(CRC_14443_A, data_bytes, len)) { @@ -2320,8 +2330,9 @@ void ReaderIso14443a(UsbCommand *c) { iso14a_set_timeout(timeout); if ((param & ISO14A_APDU)) { - arg0 = iso14_apdu(cmd, len, buf); - cmd_send(CMD_ACK, arg0, 0, 0, buf, sizeof(buf)); + uint8_t res; + arg0 = iso14_apdu(cmd, len, buf, &res); + cmd_send(CMD_ACK, arg0, res, 0, buf, sizeof(buf)); } if ((param & ISO14A_RAW)) { diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index ff9116d67..ff34fa577 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -114,7 +114,7 @@ extern void ReaderTransmitPar(uint8_t *frame, uint16_t len, uint8_t *par, uint32 extern int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par); extern void iso14443a_setup(uint8_t fpga_minor_mode); -extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data); +extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data, uint8_t *res); extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats); extern int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades); extern void iso14a_set_trigger(bool enable); From 1f1d8bfc0bd3078a47b61a5035b2f6de548132ca Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 8 Nov 2018 20:29:29 +0200 Subject: [PATCH 0144/1938] fixed armside epa.c --- armsrc/epa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/epa.c b/armsrc/epa.c index 5a8fdc8bb..68b2711da 100644 --- a/armsrc/epa.c +++ b/armsrc/epa.c @@ -108,7 +108,7 @@ int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response) switch(iso_type) { case 'a': - return iso14_apdu(apdu, (uint16_t) length, response); + return iso14_apdu(apdu, (uint16_t) length, response, NULL); break; case 'b': return iso14443b_apdu(apdu, length, response); From 00fdac0986a5066270803748874432511f719b35 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Sun, 11 Nov 2018 01:18:14 +0100 Subject: [PATCH 0145/1938] fix legic reading and writing --- client/scripts/legic.lua | 96 ++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 47 deletions(-) diff --git a/client/scripts/legic.lua b/client/scripts/legic.lua index 9c63fdb69..2acf27bc2 100644 --- a/client/scripts/legic.lua +++ b/client/scripts/legic.lua @@ -386,7 +386,7 @@ end -- put bytes into tag-table function bytesToTag(bytes, tag) if istable(tag) == false then return oops("tag is no table in: bytesToTag ("..type(tag)..")") end - + tag.MCD =bytes[1]; tag.MSN0=bytes[2]; tag.MSN1=bytes[3]; @@ -453,8 +453,8 @@ end --- -- read Tag-Table in bytes-table function tagToBytes(tag) - if istable(tag) == false then return oops("tag is no table in tagToBytes ("..type(tag)..")") end - + if istable(tag) == false then return oops("tag is no table in tagToBytes ("..type(tag)..")") end + local bytes = {} local i, i2 -- main token-data @@ -506,8 +506,9 @@ function tagToBytes(tag) function readFromPM3() local tag, bytes, infile infile="legic.temp" - core.console("hf legic reader") - core.console("hf legic esave "..infile) + -- core.console("hf legic reader") + -- core.console("hf legic esave "..infile) + core.console("hf legic dump o "..infile) tag=readFile(infile..".bin") return tag end @@ -558,7 +559,7 @@ function writeToTag(tag) if (bytes) then print("write temp-file '"..filename.."'") print(accyan) - writeFile(bytes, filename) + writeFile(bytes, filename..".bin") --writeToTag(bytes, taglen, 'MylegicClone.hex') print(acoff) end @@ -568,17 +569,18 @@ function writeToTag(tag) WriteBytes = utils.input(acyellow.."enter number of bytes to write?"..acoff, taglen) -- load file into pm3-buffer if (type(filename) ~= "string") then filename=input(acyellow.."filename to load to pm3-buffer?"..acoff,"legic.temp") end - cmd = 'hf legic load '..filename + cmd = 'hf legic eload '..filename core.console(cmd) -- write pm3-buffer to Tag for i=0, WriteBytes do if ( i<5 or i>6) then - cmd = ('hf legic write o 0x%02x d 0x01'):format(i) + cmd = ('hf legic write o %02x d 01'):format(i) + print(cmd) core.console(cmd) --print(cmd) elseif (i == 6) then -- write DCF in reverse order (requires 'mosci-patch') - cmd = 'hf legic write o 0x05 d 0x02' + cmd = 'hf legic write o 05 d 02' print(acgreen..cmd..acoff) core.console(cmd) --print(cmd) @@ -597,10 +599,10 @@ function readFile(filename) print(accyan) local bytes = {} local tag = {} - if file_check(filename) == false then return oops("input file: "..filename.." not found") end - + if file_check(filename) == false then return oops("input file: "..filename.." not found") end + bytes = getInputBytes(filename) - + if bytes == false then return oops('couldnt get input bytes') end -- make plain bytes @@ -611,7 +613,7 @@ function readFile(filename) -- load plain bytes to tag-table print(acoff) tag=bytesToTag(bytes, tag) - + return tag end @@ -704,9 +706,9 @@ end --- -- toggle higligh function toggleHighlight(tbl) - if (tbl['highlight']) then + if (tbl['highlight']) then tbl['highlight'] = false - else + else tbl['highlight'] = true end return tbl @@ -1302,9 +1304,9 @@ function dumpTable(tab, header, tstart, tend) for i=tstart, tend do res=res..tab[i].." " end - if (#header == 0) then + if (#header == 0) then return res - else + else return (header.." #"..(tend-tstart+1).."\n"..res) end end @@ -1351,9 +1353,9 @@ end --- -- dump Legic-Cash data function dumpLegicCash(tag, x) - + if istable(tag.SEG[x]) == false then return end - + io.write("in Segment "..tag.SEG[x].index.." :\n") print("--------------------------------\n\tLegic-Cash Values\n--------------------------------") local limit, curr, balance, rid, tcv @@ -1379,7 +1381,7 @@ function dumpLegicCash(tag, x) function print3rdPartyCash1(tag, x) if istable(tag.SEG[x]) == false then return end - + local uid=tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2 print("\n\t\tStamp : "..dumpTable(tag.SEG[x].data, "", 0 , 2)) print("\t\tBlock 0: "..dumpTable(tag.SEG[x].data, "", 3 , 18)) @@ -1455,11 +1457,11 @@ function makeToken() -- if Master-Token -> calc Master-Token-CRC if (mtq>1) then bytes[22] = calcMtCrc(bytes) end - + local tempTag = createTagTable() -- remove segment if MasterToken if (mtq>1) then tempTag.SEG[0] = nil end - + return bytesToTag(bytes, tempTag) end @@ -1704,7 +1706,7 @@ function editSegmentData(data) for i=0, #data-1 do data[i]=input(accyan.."Data"..i..acoff..": ", data[i]) end - if (lc) then + if (lc) then data = fixLegicCash(data) end return data @@ -2276,7 +2278,7 @@ function modifyMode() -- load file into mainTAG ["lf"] = function(x) - if (type(x)=='string' and file_check(x)) then + if (type(x)=='string' and file_check(x)) then filename = x else filename = input("enter filename: ", "legic.temp") @@ -2382,9 +2384,9 @@ function modifyMode() --- -- dump single segment ["ds"] = function(x) - if (type(x)=="string" and string.len(x)>0) then + if (type(x)=="string" and string.len(x)>0) then sel = tonumber(x,10) - else + else sel = selectSegment(inTAG) end if (sel) then print("\n"..(dumpSegment(inTAG, sel) or acred.."no Segments available") ..acoff.."\n") end @@ -2398,9 +2400,9 @@ function modifyMode() if(istable(inTAG.SEG[0])) then inTAG=editSegment(inTAG, sel) inTAG.SEG[sel]=regenSegmentHeader(inTAG.SEG[sel]) - else + else print(acyellow.."no Segments in Tag"..acoff) - end + end end end, --- @@ -2455,14 +2457,14 @@ function modifyMode() -- toggle kgh-crc-flag on a single segment ["tk"] = function(x) if (istable(inTAG) and istable(inTAG.SEG[0])) then - if (type(x)=="string" and string.len(x)>0) then + if (type(x)=="string" and string.len(x)>0) then sel = tonumber(x,10) - else - sel = selectSegment(inTAG) + else + sel = selectSegment(inTAG) end - if(inTAG.SEG[sel].kgh) then + if(inTAG.SEG[sel].kgh) then inTAG.SEG[sel].kgh = false - else + else inTAG.SEG[sel].kgh = true end end @@ -2486,18 +2488,18 @@ function modifyMode() sel = tonumber(x,10) else sel = selectSegment(inTAG) - end + end print("k "..kghCrcCredentials(inTAG, sel)) end end, --- -- fix legic-cash checksums ["flc"] = function(x) - if (type(x)=="string" and string.len(x)>0) then + if (type(x)=="string" and string.len(x)>0) then x = tonumber(x,10) else x = selectSegment(inTAG) - end + end inTAG.SEG[x].data=fixLegicCash(inTAG.SEG[x].data) end, --- @@ -2531,7 +2533,7 @@ function modifyMode() else -- or try to find match x = autoSelectSegment(inTAG, "3rdparty") - end + end if (istable(inTAG) and istable(inTAG.SEG[x]) and inTAG.SEG[x].len == 100) then uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2 if (check43rdPartyCash1(uid, inTAG.SEG[x].data)) then @@ -2561,11 +2563,11 @@ function modifyMode() if (type(x)=="string" and string.len(x)>0) then x=tonumber(x,10) print(string.format("User-Selected Index %02d", x)) - + else -- or try to find match x = autoSelectSegment(inTAG, "3rdparty") - end + end if (istable(inTAG) and istable(inTAG.SEG[x]) and inTAG.SEG[x].len == 100) then inTAG=edit3rdPartyCash1(inTAG, x) dump3rdPartyCash1(inTAG, x) @@ -2587,7 +2589,7 @@ function modifyMode() --- -- get stamp from single segment ["gs"] = function(x) - if(type(x)=="string" and string.len(x)>=2) then + if(type(x)=="string" and string.len(x)>=2) then x = tonumber(x, 10) else x = selectSegment(inTAG) @@ -2637,7 +2639,7 @@ function modifyMode() actions[string.lower(string.sub(ic,0,2))](string.sub(ic,4)) elseif (type(actions[string.lower(string.sub(ic,0,1))])=='function') then actions[string.lower(string.sub(ic,0,1))](string.sub(ic,3)) - else + else actions.h('') end until (string.sub(ic,0,1)=="q") @@ -2664,25 +2666,25 @@ function main(args) -- dump virtual-Tag if o == "d" then dfs=true end -- interacive modifying - if o == "m" then + if o == "m" then interactive = true modifyMode() end -- xor (e.g. for clone or plain file) - if o == "c" then + if o == "c" then cfs = true crc = a end -- output file - if o == "o" then + if o == "o" then outfile = a ofs = true - end + end end -- file conversion (output to file) if ofs == false then return end - + -- dump infile / tag-read if (dfs) then print("-----------------------------------------") @@ -2714,4 +2716,4 @@ end --- -- script start -main(args) \ No newline at end of file +main(args) From dc693578203a329d2cce322ff2ea0f8132837623 Mon Sep 17 00:00:00 2001 From: David Cumps Date: Sun, 11 Nov 2018 12:34:59 +0100 Subject: [PATCH 0146/1938] skip first 4 bytes of legic writing --- client/scripts/legic.lua | 38 +++++++++++++++++++++++--------------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/client/scripts/legic.lua b/client/scripts/legic.lua index 2acf27bc2..546e5cc1a 100644 --- a/client/scripts/legic.lua +++ b/client/scripts/legic.lua @@ -513,6 +513,14 @@ function readFromPM3() return tag end +function padString(str) + if (str:len() == 1) then + return '0'..str + end + + return str +end + --- -- write virtual Tag to real Tag function writeToTag(tag) @@ -560,32 +568,32 @@ function writeToTag(tag) print("write temp-file '"..filename.."'") print(accyan) writeFile(bytes, filename..".bin") - --writeToTag(bytes, taglen, 'MylegicClone.hex') print(acoff) end end - -- write data to file + + -- write data to file if (taglen > 0) then WriteBytes = utils.input(acyellow.."enter number of bytes to write?"..acoff, taglen) -- load file into pm3-buffer if (type(filename) ~= "string") then filename=input(acyellow.."filename to load to pm3-buffer?"..acoff,"legic.temp") end - cmd = 'hf legic eload '..filename + cmd = 'hf legic eload 2 '..filename core.console(cmd) -- write pm3-buffer to Tag for i=0, WriteBytes do - if ( i<5 or i>6) then - cmd = ('hf legic write o %02x d 01'):format(i) - print(cmd) - core.console(cmd) - --print(cmd) - elseif (i == 6) then - -- write DCF in reverse order (requires 'mosci-patch') - cmd = 'hf legic write o 05 d 02' + if (i > 6) then + cmd = 'hf legic write o '..string.format("%x", i)..' d '..padString(bytes[i]) print(acgreen..cmd..acoff) core.console(cmd) - --print(cmd) - else + elseif (i == 6) then + -- write DCF in reverse order (requires 'mosci-patch') + cmd = 'hf legic write o 05 d '..padString(bytes[i-1])..padString(bytes[i]) + print(acgreen..cmd..acoff) + core.console(cmd) + elseif (i == 5) then print(acgreen.."skip byte 0x05 - will be written next step"..acoff) + else + print(acgreen.."skip byte 0x00-0x04 - unwritable area"..acoff) end utils.Sleep(0.2) end @@ -622,14 +630,14 @@ end function writeFile(bytes, filename) if (filename ~= 'MylegicClone.hex') then if (file_check(filename)) then - local answer = confirm("\nthe output-file "..filename.." alredy exists!\nthis will delete the previous content!\ncontinue?") + local answer = confirm("\nthe output-file "..filename.." already exists!\nthis will delete the previous content!\ncontinue?") if (answer==false) then return print("user abort") end end end local line local bcnt=0 local fho,err = io.open(filename, "w") - if err then oops("OOps ... faild to open output-file ".. filename) end + if err then oops("OOps ... failed to open output-file ".. filename) end bytes=xorBytes(bytes, bytes[5]) for i = 1, #bytes do if (bcnt == 0) then From ab196ad2ee229f8117dcc4d9e93640e72b8651e8 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Nov 2018 15:00:35 +0200 Subject: [PATCH 0147/1938] added jansson --- client/Makefile | 18 +- client/emv/emvjson.h | 1 - client/jansson/Makefile | 64 ++ client/jansson/dump.c | 504 ++++++++++++ client/jansson/error.c | 66 ++ client/jansson/hashtable.c | 356 +++++++++ client/jansson/hashtable_seed.c | 277 +++++++ client/jansson/jansson.def | 75 ++ client/jansson/jansson.h | 372 +++++++++ client/jansson/jansson_config.h | 51 ++ client/jansson/jansson_config.h.in | 51 ++ client/jansson/load.c | 1155 ++++++++++++++++++++++++++++ client/jansson/lookup3.h | 381 +++++++++ client/jansson/memory.c | 69 ++ client/jansson/pack_unpack.c | 909 ++++++++++++++++++++++ client/jansson/path.c | 1 - client/jansson/path.h | 17 - client/jansson/strbuffer.c | 111 +++ client/jansson/strconv.c | 145 ++++ client/jansson/utf.c | 187 +++++ client/jansson/utf.h | 27 + client/jansson/value.c | 1078 ++++++++++++++++++++++++++ 22 files changed, 5890 insertions(+), 25 deletions(-) create mode 100644 client/jansson/Makefile create mode 100644 client/jansson/dump.c create mode 100644 client/jansson/error.c create mode 100644 client/jansson/hashtable.c create mode 100644 client/jansson/hashtable_seed.c create mode 100644 client/jansson/jansson.def create mode 100644 client/jansson/jansson.h create mode 100644 client/jansson/jansson_config.h create mode 100644 client/jansson/jansson_config.h.in create mode 100644 client/jansson/load.c create mode 100644 client/jansson/lookup3.h create mode 100644 client/jansson/memory.c create mode 100644 client/jansson/pack_unpack.c delete mode 100644 client/jansson/path.h create mode 100644 client/jansson/strbuffer.c create mode 100644 client/jansson/strconv.c create mode 100644 client/jansson/utf.c create mode 100644 client/jansson/utf.h create mode 100644 client/jansson/value.c diff --git a/client/Makefile b/client/Makefile index 30a2fa26c..21b43d7f1 100644 --- a/client/Makefile +++ b/client/Makefile @@ -23,11 +23,13 @@ ENV_CFLAGS := $(CFLAGS) VPATH = ../common ../zlib ../uart OBJDIR = obj -LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm -L/usr/lib -ljansson +LDLIBS = -L/opt/local/lib -L/usr/local/lib -lreadline -lpthread -lm LUALIB = ../liblua/liblua.a +JANSSONLIBPATH = ./jansson +JANSSONLIB = $(JANSSONLIBPATH)/libjansson.a LDFLAGS = $(ENV_LDFLAGS) -INCLUDES_CLIENT = -I/usr/include -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua -CFLAGS = $(ENV_CFLAGS) -std=c99 -D_ISOC99_SOURCE -DPRESETS $(INCLUDES_CLIENT) -Wall -g -O3 +INCLUDES_CLIENT = -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua +CFLAGS = $(ENV_CFLAGS) -std=c99 -D_ISOC99_SOURCE -DPRESETS $(INCLUDES_CLIENT) -I$(JANSSONLIBPATH) -Wall -g -O3 CXXFLAGS = -I../include -Wall -O3 LUAPLATFORM = generic @@ -103,7 +105,6 @@ CMDSRCS = crapto1/crapto1.c \ crapto1/crypto1.c \ mfkey.c \ tea.c \ - jansson/path.c \ polarssl/des.c \ polarssl/aes.c \ polarssl/aes_cmac128.c \ @@ -263,12 +264,12 @@ WINBINS = $(patsubst %, %.exe, $(BINS)) CLEAN = $(BINS) $(WINBINS) $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(ZLIBOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(OBJDIR)/*.o *.moc.cpp ui/ui_overlays.h lualibs/usb_cmd.lua lualibs/mf_default_keys.lua # need to assign dependancies to build these first... -all: lua_build $(BINS) +all: lua_build jansson_build $(BINS) all-static: LDLIBS:=-static $(LDLIBS) all-static: proxmark3 flasher fpga_compress -proxmark3: LDLIBS+=$(LUALIB) $(QTLDLIBS) +proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(QTLDLIBS) proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) lualibs/usb_cmd.lua lualibs/mf_default_keys.lua $(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) $(LDLIBS) -o $@ @@ -295,6 +296,7 @@ lualibs/mf_default_keys.lua : default_keys.dic clean: $(RM) $(CLEAN) cd ../liblua && make clean + cd $(JANSSONLIBPATH) && make clean tarbin: $(BINS) $(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%) $(WINBINS:%=client/%) @@ -302,6 +304,10 @@ tarbin: $(BINS) lua_build: @echo Compiling liblua, using platform $(LUAPLATFORM) cd ../liblua && make $(LUAPLATFORM) + +jansson_build: + @echo Compiling jansson + cd $(JANSSONLIBPATH) && make all .PHONY: all clean diff --git a/client/emv/emvjson.h b/client/emv/emvjson.h index 32b2484d2..9c6eda5ea 100644 --- a/client/emv/emvjson.h +++ b/client/emv/emvjson.h @@ -12,7 +12,6 @@ #include #include "tlv.h" -#include "jansson/path.h" typedef struct { tlv_tag_t Tag; diff --git a/client/jansson/Makefile b/client/jansson/Makefile new file mode 100644 index 000000000..e608d7c04 --- /dev/null +++ b/client/jansson/Makefile @@ -0,0 +1,64 @@ + +include_HEADERS = jansson.h +nodist_include_HEADERS = jansson_config.h + +LIB_A = libjansson.a +libjansson_la_SOURCES = \ + dump.c \ + error.c \ + hashtable.c \ + hashtable.h \ + hashtable_seed.c \ + jansson_private.h \ + load.c \ + lookup3.h \ + memory.c \ + pack_unpack.c \ + strbuffer.c \ + strbuffer.h \ + strconv.c \ + utf.c \ + utf.h \ + path.c \ + value.c +libjansson_la_LDFLAGS = \ + -no-undefined \ + -export-symbols-regex '^json_' \ + -version-info 15:0:11 + + +CFILES = $(filter %.c, $(libjansson_la_SOURCES)) +CMDOBJS = $(CFILES:%.c=%.o) +CLEAN = $(CMDOBJS) + +CC= gcc +CFLAGS= -O2 -Wall -Wno-unused-variable -Wno-unused-function +LDFLAGS= $(SYSLDFLAGS) $(libjansson_la_LDFLAGS) +LIBS= -lm $(SYSLIBS) $(MYLIBS) +DEFAULT_INCLUDES = -I. +DEFS = -DHAVE_STDINT_H + +AR= ar rcs +RANLIB= ranlib +RM= rm -f +TST= echo + +SYSLDFLAGS= +SYSLIBS= + +MYLIBS= +MYOBJS= + +all: $(CMDOBJS) + $(AR) $(LIB_A) $(CMDOBJS) + $(RANLIB) $(LIB_A) + +clean: + $(RM) $(CLEAN) + $(RM) $(LIB_A) + +%.o: %.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(CFLAGS) -c -o $@ $< $(LIBS) + +.PHONY: all clean + diff --git a/client/jansson/dump.c b/client/jansson/dump.c new file mode 100644 index 000000000..8e725c934 --- /dev/null +++ b/client/jansson/dump.c @@ -0,0 +1,504 @@ +/* + * Copyright (c) 2009-2016 Petri Lehtinen + * + * Jansson is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include "jansson_private.h" + +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "jansson.h" +#include "strbuffer.h" +#include "utf.h" + +#define MAX_INTEGER_STR_LENGTH 100 +#define MAX_REAL_STR_LENGTH 100 + +#define FLAGS_TO_INDENT(f) ((f) & 0x1F) +#define FLAGS_TO_PRECISION(f) (((f) >> 11) & 0x1F) + +struct buffer { + const size_t size; + size_t used; + char *data; +}; + +static int dump_to_strbuffer(const char *buffer, size_t size, void *data) +{ + return strbuffer_append_bytes((strbuffer_t *)data, buffer, size); +} + +static int dump_to_buffer(const char *buffer, size_t size, void *data) +{ + struct buffer *buf = (struct buffer *)data; + + if(buf->used + size <= buf->size) + memcpy(&buf->data[buf->used], buffer, size); + + buf->used += size; + return 0; +} + +static int dump_to_file(const char *buffer, size_t size, void *data) +{ + FILE *dest = (FILE *)data; + if(fwrite(buffer, size, 1, dest) != 1) + return -1; + return 0; +} + +static int dump_to_fd(const char *buffer, size_t size, void *data) +{ + int *dest = (int *)data; +#ifdef HAVE_UNISTD_H + if(write(*dest, buffer, size) == (ssize_t)size) + return 0; +#endif + return -1; +} + +/* 32 spaces (the maximum indentation size) */ +static const char whitespace[] = " "; + +static int dump_indent(size_t flags, int depth, int space, json_dump_callback_t dump, void *data) +{ + if(FLAGS_TO_INDENT(flags) > 0) + { + unsigned int ws_count = FLAGS_TO_INDENT(flags), n_spaces = depth * ws_count; + + if(dump("\n", 1, data)) + return -1; + + while(n_spaces > 0) + { + int cur_n = n_spaces < sizeof whitespace - 1 ? n_spaces : sizeof whitespace - 1; + + if(dump(whitespace, cur_n, data)) + return -1; + + n_spaces -= cur_n; + } + } + else if(space && !(flags & JSON_COMPACT)) + { + return dump(" ", 1, data); + } + return 0; +} + +static int dump_string(const char *str, size_t len, json_dump_callback_t dump, void *data, size_t flags) +{ + const char *pos, *end, *lim; + int32_t codepoint; + + if(dump("\"", 1, data)) + return -1; + + end = pos = str; + lim = str + len; + while(1) + { + const char *text; + char seq[13]; + int length; + + while(end < lim) + { + end = utf8_iterate(pos, lim - pos, &codepoint); + if(!end) + return -1; + + /* mandatory escape or control char */ + if(codepoint == '\\' || codepoint == '"' || codepoint < 0x20) + break; + + /* slash */ + if((flags & JSON_ESCAPE_SLASH) && codepoint == '/') + break; + + /* non-ASCII */ + if((flags & JSON_ENSURE_ASCII) && codepoint > 0x7F) + break; + + pos = end; + } + + if(pos != str) { + if(dump(str, pos - str, data)) + return -1; + } + + if(end == pos) + break; + + /* handle \, /, ", and control codes */ + length = 2; + switch(codepoint) + { + case '\\': text = "\\\\"; break; + case '\"': text = "\\\""; break; + case '\b': text = "\\b"; break; + case '\f': text = "\\f"; break; + case '\n': text = "\\n"; break; + case '\r': text = "\\r"; break; + case '\t': text = "\\t"; break; + case '/': text = "\\/"; break; + default: + { + /* codepoint is in BMP */ + if(codepoint < 0x10000) + { + snprintf(seq, sizeof(seq), "\\u%04X", (unsigned int)codepoint); + length = 6; + } + + /* not in BMP -> construct a UTF-16 surrogate pair */ + else + { + int32_t first, last; + + codepoint -= 0x10000; + first = 0xD800 | ((codepoint & 0xffc00) >> 10); + last = 0xDC00 | (codepoint & 0x003ff); + + snprintf(seq, sizeof(seq), "\\u%04X\\u%04X", (unsigned int)first, (unsigned int)last); + length = 12; + } + + text = seq; + break; + } + } + + if(dump(text, length, data)) + return -1; + + str = pos = end; + } + + return dump("\"", 1, data); +} + +static int compare_keys(const void *key1, const void *key2) +{ + return strcmp(*(const char **)key1, *(const char **)key2); +} + +static int loop_check(hashtable_t *parents, const json_t *json, char *key, size_t key_size) +{ + snprintf(key, key_size, "%p", json); + if (hashtable_get(parents, key)) + return -1; + + return hashtable_set(parents, key, json_null()); +} + +static int do_dump(const json_t *json, size_t flags, int depth, + hashtable_t *parents, json_dump_callback_t dump, void *data) +{ + int embed = flags & JSON_EMBED; + + flags &= ~JSON_EMBED; + + if(!json) + return -1; + + switch(json_typeof(json)) { + case JSON_NULL: + return dump("null", 4, data); + + case JSON_TRUE: + return dump("true", 4, data); + + case JSON_FALSE: + return dump("false", 5, data); + + case JSON_INTEGER: + { + char buffer[MAX_INTEGER_STR_LENGTH]; + int size; + + size = snprintf(buffer, MAX_INTEGER_STR_LENGTH, + "%" JSON_INTEGER_FORMAT, + json_integer_value(json)); + if(size < 0 || size >= MAX_INTEGER_STR_LENGTH) + return -1; + + return dump(buffer, size, data); + } + + case JSON_REAL: + { + char buffer[MAX_REAL_STR_LENGTH]; + int size; + double value = json_real_value(json); + + size = jsonp_dtostr(buffer, MAX_REAL_STR_LENGTH, value, + FLAGS_TO_PRECISION(flags)); + if(size < 0) + return -1; + + return dump(buffer, size, data); + } + + case JSON_STRING: + return dump_string(json_string_value(json), json_string_length(json), dump, data, flags); + + case JSON_ARRAY: + { + size_t n; + size_t i; + /* Space for "0x", double the sizeof a pointer for the hex and a terminator. */ + char key[2 + (sizeof(json) * 2) + 1]; + + /* detect circular references */ + if (loop_check(parents, json, key, sizeof(key))) + return -1; + + n = json_array_size(json); + + if(!embed && dump("[", 1, data)) + return -1; + if(n == 0) { + hashtable_del(parents, key); + return embed ? 0 : dump("]", 1, data); + } + if(dump_indent(flags, depth + 1, 0, dump, data)) + return -1; + + for(i = 0; i < n; ++i) { + if(do_dump(json_array_get(json, i), flags, depth + 1, + parents, dump, data)) + return -1; + + if(i < n - 1) + { + if(dump(",", 1, data) || + dump_indent(flags, depth + 1, 1, dump, data)) + return -1; + } + else + { + if(dump_indent(flags, depth, 0, dump, data)) + return -1; + } + } + + hashtable_del(parents, key); + return embed ? 0 : dump("]", 1, data); + } + + case JSON_OBJECT: + { + void *iter; + const char *separator; + int separator_length; + /* Space for "0x", double the sizeof a pointer for the hex and a terminator. */ + char key[2 + (sizeof(json) * 2) + 1]; + + if(flags & JSON_COMPACT) { + separator = ":"; + separator_length = 1; + } + else { + separator = ": "; + separator_length = 2; + } + + /* detect circular references */ + if (loop_check(parents, json, key, sizeof(key))) + return -1; + + iter = json_object_iter((json_t *)json); + + if(!embed && dump("{", 1, data)) + return -1; + if(!iter) { + hashtable_del(parents, key); + return embed ? 0 : dump("}", 1, data); + } + if(dump_indent(flags, depth + 1, 0, dump, data)) + return -1; + + if(flags & JSON_SORT_KEYS) + { + const char **keys; + size_t size, i; + + size = json_object_size(json); + keys = jsonp_malloc(size * sizeof(const char *)); + if(!keys) + return -1; + + i = 0; + while(iter) + { + keys[i] = json_object_iter_key(iter); + iter = json_object_iter_next((json_t *)json, iter); + i++; + } + assert(i == size); + + qsort(keys, size, sizeof(const char *), compare_keys); + + for(i = 0; i < size; i++) + { + const char *key; + json_t *value; + + key = keys[i]; + value = json_object_get(json, key); + assert(value); + + dump_string(key, strlen(key), dump, data, flags); + if(dump(separator, separator_length, data) || + do_dump(value, flags, depth + 1, parents, dump, data)) + { + jsonp_free(keys); + return -1; + } + + if(i < size - 1) + { + if(dump(",", 1, data) || + dump_indent(flags, depth + 1, 1, dump, data)) + { + jsonp_free(keys); + return -1; + } + } + else + { + if(dump_indent(flags, depth, 0, dump, data)) + { + jsonp_free(keys); + return -1; + } + } + } + + jsonp_free(keys); + } + else + { + /* Don't sort keys */ + + while(iter) + { + void *next = json_object_iter_next((json_t *)json, iter); + const char *key = json_object_iter_key(iter); + + dump_string(key, strlen(key), dump, data, flags); + if(dump(separator, separator_length, data) || + do_dump(json_object_iter_value(iter), flags, depth + 1, + parents, dump, data)) + return -1; + + if(next) + { + if(dump(",", 1, data) || + dump_indent(flags, depth + 1, 1, dump, data)) + return -1; + } + else + { + if(dump_indent(flags, depth, 0, dump, data)) + return -1; + } + + iter = next; + } + } + + hashtable_del(parents, key); + return embed ? 0 : dump("}", 1, data); + } + + default: + /* not reached */ + return -1; + } +} + +char *json_dumps(const json_t *json, size_t flags) +{ + strbuffer_t strbuff; + char *result; + + if(strbuffer_init(&strbuff)) + return NULL; + + if(json_dump_callback(json, dump_to_strbuffer, (void *)&strbuff, flags)) + result = NULL; + else + result = jsonp_strdup(strbuffer_value(&strbuff)); + + strbuffer_close(&strbuff); + return result; +} + +size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags) +{ + struct buffer buf = { size, 0, buffer }; + + if(json_dump_callback(json, dump_to_buffer, (void *)&buf, flags)) + return 0; + + return buf.used; +} + +int json_dumpf(const json_t *json, FILE *output, size_t flags) +{ + return json_dump_callback(json, dump_to_file, (void *)output, flags); +} + +int json_dumpfd(const json_t *json, int output, size_t flags) +{ + return json_dump_callback(json, dump_to_fd, (void *)&output, flags); +} + +int json_dump_file(const json_t *json, const char *path, size_t flags) +{ + int result; + + FILE *output = fopen(path, "w"); + if(!output) + return -1; + + result = json_dumpf(json, output, flags); + + if(fclose(output) != 0) + return -1; + + return result; +} + +int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags) +{ + int res; + hashtable_t parents_set; + + if(!(flags & JSON_ENCODE_ANY)) { + if(!json_is_array(json) && !json_is_object(json)) + return -1; + } + + if (hashtable_init(&parents_set)) + return -1; + res = do_dump(json, flags, 0, &parents_set, callback, data); + hashtable_close(&parents_set); + + return res; +} diff --git a/client/jansson/error.c b/client/jansson/error.c new file mode 100644 index 000000000..b94b3a3a1 --- /dev/null +++ b/client/jansson/error.c @@ -0,0 +1,66 @@ +#include +#include "jansson_private.h" + +void jsonp_error_init(json_error_t *error, const char *source) +{ + if(error) + { + error->text[0] = '\0'; + error->line = -1; + error->column = -1; + error->position = 0; + if(source) + jsonp_error_set_source(error, source); + else + error->source[0] = '\0'; + } +} + +void jsonp_error_set_source(json_error_t *error, const char *source) +{ + size_t length; + + if(!error || !source) + return; + + length = strlen(source); + if(length < JSON_ERROR_SOURCE_LENGTH) + strncpy(error->source, source, JSON_ERROR_SOURCE_LENGTH); + else { + size_t extra = length - JSON_ERROR_SOURCE_LENGTH + 4; + memcpy(error->source, "...", 3); + strncpy(error->source + 3, source + extra, length - extra + 1); + } +} + +void jsonp_error_set(json_error_t *error, int line, int column, + size_t position, enum json_error_code code, + const char *msg, ...) +{ + va_list ap; + + va_start(ap, msg); + jsonp_error_vset(error, line, column, position, code, msg, ap); + va_end(ap); +} + +void jsonp_error_vset(json_error_t *error, int line, int column, + size_t position, enum json_error_code code, + const char *msg, va_list ap) +{ + if(!error) + return; + + if(error->text[0] != '\0') { + /* error already set */ + return; + } + + error->line = line; + error->column = column; + error->position = (int)position; + + vsnprintf(error->text, JSON_ERROR_TEXT_LENGTH - 1, msg, ap); + error->text[JSON_ERROR_TEXT_LENGTH - 2] = '\0'; + error->text[JSON_ERROR_TEXT_LENGTH - 1] = code; +} diff --git a/client/jansson/hashtable.c b/client/jansson/hashtable.c new file mode 100644 index 000000000..c819319a7 --- /dev/null +++ b/client/jansson/hashtable.c @@ -0,0 +1,356 @@ +/* + * Copyright (c) 2009-2016 Petri Lehtinen + * + * This library is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#if HAVE_CONFIG_H +#include +#endif + +#include +#include + +#if HAVE_STDINT_H +#include +#endif + +#include /* for JSON_INLINE */ +#include "jansson_private.h" /* for container_of() */ +#include "hashtable.h" + +#ifndef INITIAL_HASHTABLE_ORDER +#define INITIAL_HASHTABLE_ORDER 3 +#endif + +typedef struct hashtable_list list_t; +typedef struct hashtable_pair pair_t; +typedef struct hashtable_bucket bucket_t; + +extern volatile uint32_t hashtable_seed; + +/* Implementation of the hash function */ +#include "lookup3.h" + +#define list_to_pair(list_) container_of(list_, pair_t, list) +#define ordered_list_to_pair(list_) container_of(list_, pair_t, ordered_list) +#define hash_str(key) ((size_t)hashlittle((key), strlen(key), hashtable_seed)) + +static JSON_INLINE void list_init(list_t *list) +{ + list->next = list; + list->prev = list; +} + +static JSON_INLINE void list_insert(list_t *list, list_t *node) +{ + node->next = list; + node->prev = list->prev; + list->prev->next = node; + list->prev = node; +} + +static JSON_INLINE void list_remove(list_t *list) +{ + list->prev->next = list->next; + list->next->prev = list->prev; +} + +static JSON_INLINE int bucket_is_empty(hashtable_t *hashtable, bucket_t *bucket) +{ + return bucket->first == &hashtable->list && bucket->first == bucket->last; +} + +static void insert_to_bucket(hashtable_t *hashtable, bucket_t *bucket, + list_t *list) +{ + if(bucket_is_empty(hashtable, bucket)) + { + list_insert(&hashtable->list, list); + bucket->first = bucket->last = list; + } + else + { + list_insert(bucket->first, list); + bucket->first = list; + } +} + +static pair_t *hashtable_find_pair(hashtable_t *hashtable, bucket_t *bucket, + const char *key, size_t hash) +{ + list_t *list; + pair_t *pair; + + if(bucket_is_empty(hashtable, bucket)) + return NULL; + + list = bucket->first; + while(1) + { + pair = list_to_pair(list); + if(pair->hash == hash && strcmp(pair->key, key) == 0) + return pair; + + if(list == bucket->last) + break; + + list = list->next; + } + + return NULL; +} + +/* returns 0 on success, -1 if key was not found */ +static int hashtable_do_del(hashtable_t *hashtable, + const char *key, size_t hash) +{ + pair_t *pair; + bucket_t *bucket; + size_t index; + + index = hash & hashmask(hashtable->order); + bucket = &hashtable->buckets[index]; + + pair = hashtable_find_pair(hashtable, bucket, key, hash); + if(!pair) + return -1; + + if(&pair->list == bucket->first && &pair->list == bucket->last) + bucket->first = bucket->last = &hashtable->list; + + else if(&pair->list == bucket->first) + bucket->first = pair->list.next; + + else if(&pair->list == bucket->last) + bucket->last = pair->list.prev; + + list_remove(&pair->list); + list_remove(&pair->ordered_list); + json_decref(pair->value); + + jsonp_free(pair); + hashtable->size--; + + return 0; +} + +static void hashtable_do_clear(hashtable_t *hashtable) +{ + list_t *list, *next; + pair_t *pair; + + for(list = hashtable->list.next; list != &hashtable->list; list = next) + { + next = list->next; + pair = list_to_pair(list); + json_decref(pair->value); + jsonp_free(pair); + } +} + +static int hashtable_do_rehash(hashtable_t *hashtable) +{ + list_t *list, *next; + pair_t *pair; + size_t i, index, new_size, new_order; + struct hashtable_bucket *new_buckets; + + new_order = hashtable->order + 1; + new_size = hashsize(new_order); + + new_buckets = jsonp_malloc(new_size * sizeof(bucket_t)); + if(!new_buckets) + return -1; + + jsonp_free(hashtable->buckets); + hashtable->buckets = new_buckets; + hashtable->order = new_order; + + for(i = 0; i < hashsize(hashtable->order); i++) + { + hashtable->buckets[i].first = hashtable->buckets[i].last = + &hashtable->list; + } + + list = hashtable->list.next; + list_init(&hashtable->list); + + for(; list != &hashtable->list; list = next) { + next = list->next; + pair = list_to_pair(list); + index = pair->hash % new_size; + insert_to_bucket(hashtable, &hashtable->buckets[index], &pair->list); + } + + return 0; +} + + +int hashtable_init(hashtable_t *hashtable) +{ + size_t i; + + hashtable->size = 0; + hashtable->order = INITIAL_HASHTABLE_ORDER; + hashtable->buckets = jsonp_malloc(hashsize(hashtable->order) * sizeof(bucket_t)); + if(!hashtable->buckets) + return -1; + + list_init(&hashtable->list); + list_init(&hashtable->ordered_list); + + for(i = 0; i < hashsize(hashtable->order); i++) + { + hashtable->buckets[i].first = hashtable->buckets[i].last = + &hashtable->list; + } + + return 0; +} + +void hashtable_close(hashtable_t *hashtable) +{ + hashtable_do_clear(hashtable); + jsonp_free(hashtable->buckets); +} + +int hashtable_set(hashtable_t *hashtable, const char *key, json_t *value) +{ + pair_t *pair; + bucket_t *bucket; + size_t hash, index; + + /* rehash if the load ratio exceeds 1 */ + if(hashtable->size >= hashsize(hashtable->order)) + if(hashtable_do_rehash(hashtable)) + return -1; + + hash = hash_str(key); + index = hash & hashmask(hashtable->order); + bucket = &hashtable->buckets[index]; + pair = hashtable_find_pair(hashtable, bucket, key, hash); + + if(pair) + { + json_decref(pair->value); + pair->value = value; + } + else + { + /* offsetof(...) returns the size of pair_t without the last, + flexible member. This way, the correct amount is + allocated. */ + + size_t len = strlen(key); + if(len >= (size_t)-1 - offsetof(pair_t, key)) { + /* Avoid an overflow if the key is very long */ + return -1; + } + + pair = jsonp_malloc(offsetof(pair_t, key) + len + 1); + if(!pair) + return -1; + + pair->hash = hash; + strncpy(pair->key, key, len + 1); + pair->value = value; + list_init(&pair->list); + list_init(&pair->ordered_list); + + insert_to_bucket(hashtable, bucket, &pair->list); + list_insert(&hashtable->ordered_list, &pair->ordered_list); + + hashtable->size++; + } + return 0; +} + +void *hashtable_get(hashtable_t *hashtable, const char *key) +{ + pair_t *pair; + size_t hash; + bucket_t *bucket; + + hash = hash_str(key); + bucket = &hashtable->buckets[hash & hashmask(hashtable->order)]; + + pair = hashtable_find_pair(hashtable, bucket, key, hash); + if(!pair) + return NULL; + + return pair->value; +} + +int hashtable_del(hashtable_t *hashtable, const char *key) +{ + size_t hash = hash_str(key); + return hashtable_do_del(hashtable, key, hash); +} + +void hashtable_clear(hashtable_t *hashtable) +{ + size_t i; + + hashtable_do_clear(hashtable); + + for(i = 0; i < hashsize(hashtable->order); i++) + { + hashtable->buckets[i].first = hashtable->buckets[i].last = + &hashtable->list; + } + + list_init(&hashtable->list); + list_init(&hashtable->ordered_list); + hashtable->size = 0; +} + +void *hashtable_iter(hashtable_t *hashtable) +{ + return hashtable_iter_next(hashtable, &hashtable->ordered_list); +} + +void *hashtable_iter_at(hashtable_t *hashtable, const char *key) +{ + pair_t *pair; + size_t hash; + bucket_t *bucket; + + hash = hash_str(key); + bucket = &hashtable->buckets[hash & hashmask(hashtable->order)]; + + pair = hashtable_find_pair(hashtable, bucket, key, hash); + if(!pair) + return NULL; + + return &pair->ordered_list; +} + +void *hashtable_iter_next(hashtable_t *hashtable, void *iter) +{ + list_t *list = (list_t *)iter; + if(list->next == &hashtable->ordered_list) + return NULL; + return list->next; +} + +void *hashtable_iter_key(void *iter) +{ + pair_t *pair = ordered_list_to_pair((list_t *)iter); + return pair->key; +} + +void *hashtable_iter_value(void *iter) +{ + pair_t *pair = ordered_list_to_pair((list_t *)iter); + return pair->value; +} + +void hashtable_iter_set(void *iter, json_t *value) +{ + pair_t *pair = ordered_list_to_pair((list_t *)iter); + + json_decref(pair->value); + pair->value = value; +} diff --git a/client/jansson/hashtable_seed.c b/client/jansson/hashtable_seed.c new file mode 100644 index 000000000..8aed54068 --- /dev/null +++ b/client/jansson/hashtable_seed.c @@ -0,0 +1,277 @@ +/* Generate sizeof(uint32_t) bytes of as random data as possible to seed + the hash function. +*/ + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include + +#ifdef HAVE_STDINT_H +#include +#endif + +#ifdef HAVE_FCNTL_H +#include +#endif + +#ifdef HAVE_SCHED_H +#include +#endif + +#ifdef HAVE_UNISTD_H +#include +#endif + +#ifdef HAVE_SYS_STAT_H +#include +#endif + +#ifdef HAVE_SYS_TIME_H +#include +#endif + +#ifdef HAVE_SYS_TYPES_H +#include +#endif + +#if defined(_WIN32) +/* For GetModuleHandle(), GetProcAddress() and GetCurrentProcessId() */ +#include +#endif + +#include "jansson.h" + + +static uint32_t buf_to_uint32(char *data) { + size_t i; + uint32_t result = 0; + + for (i = 0; i < sizeof(uint32_t); i++) + result = (result << 8) | (unsigned char)data[i]; + + return result; +} + + + +/* /dev/urandom */ +#if !defined(_WIN32) && defined(USE_URANDOM) +static int seed_from_urandom(uint32_t *seed) { + /* Use unbuffered I/O if we have open(), close() and read(). Otherwise + fall back to fopen() */ + + char data[sizeof(uint32_t)]; + int ok; + +#if defined(HAVE_OPEN) && defined(HAVE_CLOSE) && defined(HAVE_READ) + int urandom; + urandom = open("/dev/urandom", O_RDONLY); + if (urandom == -1) + return 1; + + ok = read(urandom, data, sizeof(uint32_t)) == sizeof(uint32_t); + close(urandom); +#else + FILE *urandom; + + urandom = fopen("/dev/urandom", "rb"); + if (!urandom) + return 1; + + ok = fread(data, 1, sizeof(uint32_t), urandom) == sizeof(uint32_t); + fclose(urandom); +#endif + + if (!ok) + return 1; + + *seed = buf_to_uint32(data); + return 0; +} +#endif + +/* Windows Crypto API */ +#if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI) +#include + +typedef BOOL (WINAPI *CRYPTACQUIRECONTEXTA)(HCRYPTPROV *phProv, LPCSTR pszContainer, LPCSTR pszProvider, DWORD dwProvType, DWORD dwFlags); +typedef BOOL (WINAPI *CRYPTGENRANDOM)(HCRYPTPROV hProv, DWORD dwLen, BYTE *pbBuffer); +typedef BOOL (WINAPI *CRYPTRELEASECONTEXT)(HCRYPTPROV hProv, DWORD dwFlags); + +static int seed_from_windows_cryptoapi(uint32_t *seed) +{ + HINSTANCE hAdvAPI32 = NULL; + CRYPTACQUIRECONTEXTA pCryptAcquireContext = NULL; + CRYPTGENRANDOM pCryptGenRandom = NULL; + CRYPTRELEASECONTEXT pCryptReleaseContext = NULL; + HCRYPTPROV hCryptProv = 0; + BYTE data[sizeof(uint32_t)]; + int ok; + + hAdvAPI32 = GetModuleHandle(TEXT("advapi32.dll")); + if(hAdvAPI32 == NULL) + return 1; + + pCryptAcquireContext = (CRYPTACQUIRECONTEXTA)GetProcAddress(hAdvAPI32, "CryptAcquireContextA"); + if (!pCryptAcquireContext) + return 1; + + pCryptGenRandom = (CRYPTGENRANDOM)GetProcAddress(hAdvAPI32, "CryptGenRandom"); + if (!pCryptGenRandom) + return 1; + + pCryptReleaseContext = (CRYPTRELEASECONTEXT)GetProcAddress(hAdvAPI32, "CryptReleaseContext"); + if (!pCryptReleaseContext) + return 1; + + if (!pCryptAcquireContext(&hCryptProv, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT)) + return 1; + + ok = pCryptGenRandom(hCryptProv, sizeof(uint32_t), data); + pCryptReleaseContext(hCryptProv, 0); + + if (!ok) + return 1; + + *seed = buf_to_uint32((char *)data); + return 0; +} +#endif + +/* gettimeofday() and getpid() */ +static int seed_from_timestamp_and_pid(uint32_t *seed) { +#ifdef HAVE_GETTIMEOFDAY + /* XOR of seconds and microseconds */ + struct timeval tv; + gettimeofday(&tv, NULL); + *seed = (uint32_t)tv.tv_sec ^ (uint32_t)tv.tv_usec; +#else + /* Seconds only */ + *seed = (uint32_t)time(NULL); +#endif + + /* XOR with PID for more randomness */ +#if defined(_WIN32) + *seed ^= (uint32_t)GetCurrentProcessId(); +#elif defined(HAVE_GETPID) + *seed ^= (uint32_t)getpid(); +#endif + + return 0; +} + +static uint32_t generate_seed() { + uint32_t seed; + int done = 0; + +#if !defined(_WIN32) && defined(USE_URANDOM) + if (seed_from_urandom(&seed) == 0) + done = 1; +#endif + +#if defined(_WIN32) && defined(USE_WINDOWS_CRYPTOAPI) + if (seed_from_windows_cryptoapi(&seed) == 0) + done = 1; +#endif + + if (!done) { + /* Fall back to timestamp and PID if no better randomness is + available */ + seed_from_timestamp_and_pid(&seed); + } + + /* Make sure the seed is never zero */ + if (seed == 0) + seed = 1; + + return seed; +} + + +volatile uint32_t hashtable_seed = 0; + +#if defined(HAVE_ATOMIC_BUILTINS) && (defined(HAVE_SCHED_YIELD) || !defined(_WIN32)) +static volatile char seed_initialized = 0; + +void json_object_seed(size_t seed) { + uint32_t new_seed = (uint32_t)seed; + + if (hashtable_seed == 0) { + if (__atomic_test_and_set(&seed_initialized, __ATOMIC_RELAXED) == 0) { + /* Do the seeding ourselves */ + if (new_seed == 0) + new_seed = generate_seed(); + + __atomic_store_n(&hashtable_seed, new_seed, __ATOMIC_RELEASE); + } else { + /* Wait for another thread to do the seeding */ + do { +#ifdef HAVE_SCHED_YIELD + sched_yield(); +#endif + } while(__atomic_load_n(&hashtable_seed, __ATOMIC_ACQUIRE) == 0); + } + } +} +#elif defined(HAVE_SYNC_BUILTINS) && (defined(HAVE_SCHED_YIELD) || !defined(_WIN32)) +void json_object_seed(size_t seed) { + uint32_t new_seed = (uint32_t)seed; + + if (hashtable_seed == 0) { + if (new_seed == 0) { + /* Explicit synchronization fences are not supported by the + __sync builtins, so every thread getting here has to + generate the seed value. + */ + new_seed = generate_seed(); + } + + do { + if (__sync_bool_compare_and_swap(&hashtable_seed, 0, new_seed)) { + /* We were the first to seed */ + break; + } else { + /* Wait for another thread to do the seeding */ +#ifdef HAVE_SCHED_YIELD + sched_yield(); +#endif + } + } while(hashtable_seed == 0); + } +} +#elif defined(_WIN32) +static long seed_initialized = 0; +void json_object_seed(size_t seed) { + uint32_t new_seed = (uint32_t)seed; + + if (hashtable_seed == 0) { + if (InterlockedIncrement(&seed_initialized) == 1) { + /* Do the seeding ourselves */ + if (new_seed == 0) + new_seed = generate_seed(); + + hashtable_seed = new_seed; + } else { + /* Wait for another thread to do the seeding */ + do { + SwitchToThread(); + } while (hashtable_seed == 0); + } + } +} +#else +/* Fall back to a thread-unsafe version */ +void json_object_seed(size_t seed) { + uint32_t new_seed = (uint32_t)seed; + + if (hashtable_seed == 0) { + if (new_seed == 0) + new_seed = generate_seed(); + + hashtable_seed = new_seed; + } +} +#endif diff --git a/client/jansson/jansson.def b/client/jansson/jansson.def new file mode 100644 index 000000000..15f35c95e --- /dev/null +++ b/client/jansson/jansson.def @@ -0,0 +1,75 @@ +EXPORTS + json_delete + json_true + json_false + json_null + json_sprintf + json_vsprintf + json_string + json_stringn + json_string_nocheck + json_stringn_nocheck + json_string_value + json_string_length + json_string_set + json_string_setn + json_string_set_nocheck + json_string_setn_nocheck + json_integer + json_integer_value + json_integer_set + json_real + json_real_value + json_real_set + json_number_value + json_array + json_array_size + json_array_get + json_array_set_new + json_array_append_new + json_array_insert_new + json_array_remove + json_array_clear + json_array_extend + json_object + json_object_size + json_object_get + json_object_set_new + json_object_set_new_nocheck + json_object_del + json_object_clear + json_object_update + json_object_update_existing + json_object_update_missing + json_object_iter + json_object_iter_at + json_object_iter_next + json_object_iter_key + json_object_iter_value + json_object_iter_set_new + json_object_key_to_iter + json_object_seed + json_dumps + json_dumpb + json_dumpf + json_dumpfd + json_dump_file + json_dump_callback + json_loads + json_loadb + json_loadf + json_loadfd + json_load_file + json_load_callback + json_equal + json_copy + json_deep_copy + json_pack + json_pack_ex + json_vpack_ex + json_unpack + json_unpack_ex + json_vunpack_ex + json_set_alloc_funcs + json_get_alloc_funcs + diff --git a/client/jansson/jansson.h b/client/jansson/jansson.h new file mode 100644 index 000000000..86f23d17e --- /dev/null +++ b/client/jansson/jansson.h @@ -0,0 +1,372 @@ +/* + * Copyright (c) 2009-2016 Petri Lehtinen + * + * Jansson is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef JANSSON_H +#define JANSSON_H + +#include +#include +#include /* for size_t */ +#include + +#include "jansson_config.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* version */ + +#define JANSSON_MAJOR_VERSION 2 +#define JANSSON_MINOR_VERSION 11 +#define JANSSON_MICRO_VERSION 0 + +/* Micro version is omitted if it's 0 */ +#define JANSSON_VERSION "2.11" + +/* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this + for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */ +#define JANSSON_VERSION_HEX ((JANSSON_MAJOR_VERSION << 16) | \ + (JANSSON_MINOR_VERSION << 8) | \ + (JANSSON_MICRO_VERSION << 0)) + +/* If __atomic or __sync builtins are available the library is thread + * safe for all read-only functions plus reference counting. */ +#if JSON_HAVE_ATOMIC_BUILTINS || JSON_HAVE_SYNC_BUILTINS +#define JANSSON_THREAD_SAFE_REFCOUNT 1 +#endif + +/* types */ + +typedef enum { + JSON_OBJECT, + JSON_ARRAY, + JSON_STRING, + JSON_INTEGER, + JSON_REAL, + JSON_TRUE, + JSON_FALSE, + JSON_NULL +} json_type; + +typedef struct json_t { + json_type type; + volatile size_t refcount; +} json_t; + +#ifndef JANSSON_USING_CMAKE /* disabled if using cmake */ +#if JSON_INTEGER_IS_LONG_LONG +#ifdef _WIN32 +#define JSON_INTEGER_FORMAT "I64d" +#else +#define JSON_INTEGER_FORMAT "lld" +#endif +typedef long long json_int_t; +#else +#define JSON_INTEGER_FORMAT "ld" +typedef long json_int_t; +#endif /* JSON_INTEGER_IS_LONG_LONG */ +#endif + +#define json_typeof(json) ((json)->type) +#define json_is_object(json) ((json) && json_typeof(json) == JSON_OBJECT) +#define json_is_array(json) ((json) && json_typeof(json) == JSON_ARRAY) +#define json_is_string(json) ((json) && json_typeof(json) == JSON_STRING) +#define json_is_integer(json) ((json) && json_typeof(json) == JSON_INTEGER) +#define json_is_real(json) ((json) && json_typeof(json) == JSON_REAL) +#define json_is_number(json) (json_is_integer(json) || json_is_real(json)) +#define json_is_true(json) ((json) && json_typeof(json) == JSON_TRUE) +#define json_is_false(json) ((json) && json_typeof(json) == JSON_FALSE) +#define json_boolean_value json_is_true +#define json_is_boolean(json) (json_is_true(json) || json_is_false(json)) +#define json_is_null(json) ((json) && json_typeof(json) == JSON_NULL) + +/* construction, destruction, reference counting */ + +json_t *json_object(void); +json_t *json_array(void); +json_t *json_string(const char *value); +json_t *json_stringn(const char *value, size_t len); +json_t *json_string_nocheck(const char *value); +json_t *json_stringn_nocheck(const char *value, size_t len); +json_t *json_integer(json_int_t value); +json_t *json_real(double value); +json_t *json_true(void); +json_t *json_false(void); +#define json_boolean(val) ((val) ? json_true() : json_false()) +json_t *json_null(void); + +/* do not call JSON_INTERNAL_INCREF or JSON_INTERNAL_DECREF directly */ +#if JSON_HAVE_ATOMIC_BUILTINS +#define JSON_INTERNAL_INCREF(json) __atomic_add_fetch(&json->refcount, 1, __ATOMIC_ACQUIRE) +#define JSON_INTERNAL_DECREF(json) __atomic_sub_fetch(&json->refcount, 1, __ATOMIC_RELEASE) +#elif JSON_HAVE_SYNC_BUILTINS +#define JSON_INTERNAL_INCREF(json) __sync_add_and_fetch(&json->refcount, 1) +#define JSON_INTERNAL_DECREF(json) __sync_sub_and_fetch(&json->refcount, 1) +#else +#define JSON_INTERNAL_INCREF(json) (++json->refcount) +#define JSON_INTERNAL_DECREF(json) (--json->refcount) +#endif + +static JSON_INLINE +json_t *json_incref(json_t *json) +{ + if(json && json->refcount != (size_t)-1) + JSON_INTERNAL_INCREF(json); + return json; +} + +/* do not call json_delete directly */ +void json_delete(json_t *json); + +static JSON_INLINE +void json_decref(json_t *json) +{ + if(json && json->refcount != (size_t)-1 && JSON_INTERNAL_DECREF(json) == 0) + json_delete(json); +} + +#if defined(__GNUC__) || defined(__clang__) +static JSON_INLINE +void json_decrefp(json_t **json) +{ + if(json) { + json_decref(*json); + *json = NULL; + } +} + +#define json_auto_t json_t __attribute__((cleanup(json_decrefp))) +#endif + + +/* error reporting */ + +#define JSON_ERROR_TEXT_LENGTH 160 +#define JSON_ERROR_SOURCE_LENGTH 80 + +typedef struct json_error_t { + int line; + int column; + int position; + char source[JSON_ERROR_SOURCE_LENGTH]; + char text[JSON_ERROR_TEXT_LENGTH]; +} json_error_t; + +enum json_error_code { + json_error_unknown, + json_error_out_of_memory, + json_error_stack_overflow, + json_error_cannot_open_file, + json_error_invalid_argument, + json_error_invalid_utf8, + json_error_premature_end_of_input, + json_error_end_of_input_expected, + json_error_invalid_syntax, + json_error_invalid_format, + json_error_wrong_type, + json_error_null_character, + json_error_null_value, + json_error_null_byte_in_key, + json_error_duplicate_key, + json_error_numeric_overflow, + json_error_item_not_found, + json_error_index_out_of_range +}; + +static JSON_INLINE enum json_error_code json_error_code(const json_error_t *e) { + return (enum json_error_code)e->text[JSON_ERROR_TEXT_LENGTH - 1]; +} + +/* getters, setters, manipulation */ + +void json_object_seed(size_t seed); +size_t json_object_size(const json_t *object); +json_t *json_object_get(const json_t *object, const char *key); +int json_object_set_new(json_t *object, const char *key, json_t *value); +int json_object_set_new_nocheck(json_t *object, const char *key, json_t *value); +int json_object_del(json_t *object, const char *key); +int json_object_clear(json_t *object); +int json_object_update(json_t *object, json_t *other); +int json_object_update_existing(json_t *object, json_t *other); +int json_object_update_missing(json_t *object, json_t *other); +void *json_object_iter(json_t *object); +void *json_object_iter_at(json_t *object, const char *key); +void *json_object_key_to_iter(const char *key); +void *json_object_iter_next(json_t *object, void *iter); +const char *json_object_iter_key(void *iter); +json_t *json_object_iter_value(void *iter); +int json_object_iter_set_new(json_t *object, void *iter, json_t *value); + +#define json_object_foreach(object, key, value) \ + for(key = json_object_iter_key(json_object_iter(object)); \ + key && (value = json_object_iter_value(json_object_key_to_iter(key))); \ + key = json_object_iter_key(json_object_iter_next(object, json_object_key_to_iter(key)))) + +#define json_object_foreach_safe(object, n, key, value) \ + for(key = json_object_iter_key(json_object_iter(object)), \ + n = json_object_iter_next(object, json_object_key_to_iter(key)); \ + key && (value = json_object_iter_value(json_object_key_to_iter(key))); \ + key = json_object_iter_key(n), \ + n = json_object_iter_next(object, json_object_key_to_iter(key))) + +#define json_array_foreach(array, index, value) \ + for(index = 0; \ + index < json_array_size(array) && (value = json_array_get(array, index)); \ + index++) + +static JSON_INLINE +int json_object_set(json_t *object, const char *key, json_t *value) +{ + return json_object_set_new(object, key, json_incref(value)); +} + +static JSON_INLINE +int json_object_set_nocheck(json_t *object, const char *key, json_t *value) +{ + return json_object_set_new_nocheck(object, key, json_incref(value)); +} + +static JSON_INLINE +int json_object_iter_set(json_t *object, void *iter, json_t *value) +{ + return json_object_iter_set_new(object, iter, json_incref(value)); +} + +size_t json_array_size(const json_t *array); +json_t *json_array_get(const json_t *array, size_t index); +int json_array_set_new(json_t *array, size_t index, json_t *value); +int json_array_append_new(json_t *array, json_t *value); +int json_array_insert_new(json_t *array, size_t index, json_t *value); +int json_array_remove(json_t *array, size_t index); +int json_array_clear(json_t *array); +int json_array_extend(json_t *array, json_t *other); + +static JSON_INLINE +int json_array_set(json_t *array, size_t ind, json_t *value) +{ + return json_array_set_new(array, ind, json_incref(value)); +} + +static JSON_INLINE +int json_array_append(json_t *array, json_t *value) +{ + return json_array_append_new(array, json_incref(value)); +} + +static JSON_INLINE +int json_array_insert(json_t *array, size_t ind, json_t *value) +{ + return json_array_insert_new(array, ind, json_incref(value)); +} + +const char *json_string_value(const json_t *string); +size_t json_string_length(const json_t *string); +json_int_t json_integer_value(const json_t *integer); +double json_real_value(const json_t *real); +double json_number_value(const json_t *json); + +int json_string_set(json_t *string, const char *value); +int json_string_setn(json_t *string, const char *value, size_t len); +int json_string_set_nocheck(json_t *string, const char *value); +int json_string_setn_nocheck(json_t *string, const char *value, size_t len); +int json_integer_set(json_t *integer, json_int_t value); +int json_real_set(json_t *real, double value); + +/* pack, unpack */ + +json_t *json_pack(const char *fmt, ...); +json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...); +json_t *json_vpack_ex(json_error_t *error, size_t flags, const char *fmt, va_list ap); + +#define JSON_VALIDATE_ONLY 0x1 +#define JSON_STRICT 0x2 + +int json_unpack(json_t *root, const char *fmt, ...); +int json_unpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, ...); +int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, va_list ap); + +/* sprintf */ + +json_t *json_sprintf(const char *fmt, ...); +json_t *json_vsprintf(const char *fmt, va_list ap); + + +/* equality */ + +int json_equal(const json_t *value1, const json_t *value2); + + +/* copying */ + +json_t *json_copy(json_t *value); +json_t *json_deep_copy(const json_t *value); + +/* path */ + +json_t *json_path_get(const json_t *json, const char *path); +int json_path_set_new(json_t *json, const char *path, json_t *value, size_t flags, json_error_t *error); + +static JSON_INLINE +int json_path_set(json_t *json, const char *path, json_t *value, size_t flags, json_error_t *error) +{ + return json_path_set_new(json, path, json_incref(value), flags, error); +} + +/* decoding */ + +#define JSON_REJECT_DUPLICATES 0x1 +#define JSON_DISABLE_EOF_CHECK 0x2 +#define JSON_DECODE_ANY 0x4 +#define JSON_DECODE_INT_AS_REAL 0x8 +#define JSON_ALLOW_NUL 0x10 + +typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data); + +json_t *json_loads(const char *input, size_t flags, json_error_t *error); +json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error); +json_t *json_loadf(FILE *input, size_t flags, json_error_t *error); +json_t *json_loadfd(int input, size_t flags, json_error_t *error); +json_t *json_load_file(const char *path, size_t flags, json_error_t *error); +json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error); + + +/* encoding */ + +#define JSON_MAX_INDENT 0x1F +#define JSON_INDENT(n) ((n) & JSON_MAX_INDENT) +#define JSON_COMPACT 0x20 +#define JSON_ENSURE_ASCII 0x40 +#define JSON_SORT_KEYS 0x80 +#define JSON_PRESERVE_ORDER 0x100 +#define JSON_ENCODE_ANY 0x200 +#define JSON_ESCAPE_SLASH 0x400 +#define JSON_REAL_PRECISION(n) (((n) & 0x1F) << 11) +#define JSON_EMBED 0x10000 + +typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data); + +char *json_dumps(const json_t *json, size_t flags); +size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags); +int json_dumpf(const json_t *json, FILE *output, size_t flags); +int json_dumpfd(const json_t *json, int output, size_t flags); +int json_dump_file(const json_t *json, const char *path, size_t flags); +int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags); + +/* custom memory allocation */ + +typedef void *(*json_malloc_t)(size_t); +typedef void (*json_free_t)(void *); + +void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn); +void json_get_alloc_funcs(json_malloc_t *malloc_fn, json_free_t *free_fn); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/client/jansson/jansson_config.h b/client/jansson/jansson_config.h new file mode 100644 index 000000000..b34baa551 --- /dev/null +++ b/client/jansson/jansson_config.h @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010-2016 Petri Lehtinen + * + * Jansson is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + * + * + * This file specifies a part of the site-specific configuration for + * Jansson, namely those things that affect the public API in + * jansson.h. + * + * The configure script copies this file to jansson_config.h and + * replaces @var@ substitutions by values that fit your system. If you + * cannot run the configure script, you can do the value substitution + * by hand. + */ + +#ifndef JANSSON_CONFIG_H +#define JANSSON_CONFIG_H + +/* If your compiler supports the inline keyword in C, JSON_INLINE is + defined to `inline', otherwise empty. In C++, the inline is always + supported. */ +#ifdef __cplusplus +#define JSON_INLINE inline +#else +#define JSON_INLINE inline +#endif + +/* If your compiler supports the `long long` type and the strtoll() + library function, JSON_INTEGER_IS_LONG_LONG is defined to 1, + otherwise to 0. */ +#define JSON_INTEGER_IS_LONG_LONG 1 + +/* If locale.h and localeconv() are available, define to 1, + otherwise to 0. */ +#define JSON_HAVE_LOCALECONV 1 + +/* If __atomic builtins are available they will be used to manage + reference counts of json_t. */ +#define JSON_HAVE_ATOMIC_BUILTINS 1 + +/* If __atomic builtins are not available we try using __sync builtins + to manage reference counts of json_t. */ +#define JSON_HAVE_SYNC_BUILTINS 1 + +/* Maximum recursion depth for parsing JSON input. + This limits the depth of e.g. array-within-array constructions. */ +#define JSON_PARSER_MAX_DEPTH 2048 + +#endif diff --git a/client/jansson/jansson_config.h.in b/client/jansson/jansson_config.h.in new file mode 100644 index 000000000..fe692ab4f --- /dev/null +++ b/client/jansson/jansson_config.h.in @@ -0,0 +1,51 @@ +/* + * Copyright (c) 2010-2016 Petri Lehtinen + * + * Jansson is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + * + * + * This file specifies a part of the site-specific configuration for + * Jansson, namely those things that affect the public API in + * jansson.h. + * + * The configure script copies this file to jansson_config.h and + * replaces @var@ substitutions by values that fit your system. If you + * cannot run the configure script, you can do the value substitution + * by hand. + */ + +#ifndef JANSSON_CONFIG_H +#define JANSSON_CONFIG_H + +/* If your compiler supports the inline keyword in C, JSON_INLINE is + defined to `inline', otherwise empty. In C++, the inline is always + supported. */ +#ifdef __cplusplus +#define JSON_INLINE inline +#else +#define JSON_INLINE @json_inline@ +#endif + +/* If your compiler supports the `long long` type and the strtoll() + library function, JSON_INTEGER_IS_LONG_LONG is defined to 1, + otherwise to 0. */ +#define JSON_INTEGER_IS_LONG_LONG @json_have_long_long@ + +/* If locale.h and localeconv() are available, define to 1, + otherwise to 0. */ +#define JSON_HAVE_LOCALECONV @json_have_localeconv@ + +/* If __atomic builtins are available they will be used to manage + reference counts of json_t. */ +#define JSON_HAVE_ATOMIC_BUILTINS @json_have_atomic_builtins@ + +/* If __atomic builtins are not available we try using __sync builtins + to manage reference counts of json_t. */ +#define JSON_HAVE_SYNC_BUILTINS @json_have_sync_builtins@ + +/* Maximum recursion depth for parsing JSON input. + This limits the depth of e.g. array-within-array constructions. */ +#define JSON_PARSER_MAX_DEPTH 2048 + +#endif diff --git a/client/jansson/load.c b/client/jansson/load.c new file mode 100644 index 000000000..4cf3855af --- /dev/null +++ b/client/jansson/load.c @@ -0,0 +1,1155 @@ +/* + * Copyright (c) 2009-2016 Petri Lehtinen + * + * Jansson is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include "jansson_private.h" + +#include +#include +#include +#include +#include +#include +#ifdef HAVE_UNISTD_H +#include +#endif + +#include "jansson.h" +#include "strbuffer.h" +#include "utf.h" + +#define STREAM_STATE_OK 0 +#define STREAM_STATE_EOF -1 +#define STREAM_STATE_ERROR -2 + +#define TOKEN_INVALID -1 +#define TOKEN_EOF 0 +#define TOKEN_STRING 256 +#define TOKEN_INTEGER 257 +#define TOKEN_REAL 258 +#define TOKEN_TRUE 259 +#define TOKEN_FALSE 260 +#define TOKEN_NULL 261 + +/* Locale independent versions of isxxx() functions */ +#define l_isupper(c) ('A' <= (c) && (c) <= 'Z') +#define l_islower(c) ('a' <= (c) && (c) <= 'z') +#define l_isalpha(c) (l_isupper(c) || l_islower(c)) +#define l_isdigit(c) ('0' <= (c) && (c) <= '9') +#define l_isxdigit(c) \ + (l_isdigit(c) || ('A' <= (c) && (c) <= 'F') || ('a' <= (c) && (c) <= 'f')) + +/* Read one byte from stream, convert to unsigned char, then int, and + return. return EOF on end of file. This corresponds to the + behaviour of fgetc(). */ +typedef int (*get_func)(void *data); + +typedef struct { + get_func get; + void *data; + char buffer[5]; + size_t buffer_pos; + int state; + int line; + int column, last_column; + size_t position; +} stream_t; + +typedef struct { + stream_t stream; + strbuffer_t saved_text; + size_t flags; + size_t depth; + int token; + union { + struct { + char *val; + size_t len; + } string; + json_int_t integer; + double real; + } value; +} lex_t; + +#define stream_to_lex(stream) container_of(stream, lex_t, stream) + + +/*** error reporting ***/ + +static void error_set(json_error_t *error, const lex_t *lex, + enum json_error_code code, + const char *msg, ...) +{ + va_list ap; + char msg_text[JSON_ERROR_TEXT_LENGTH]; + char msg_with_context[JSON_ERROR_TEXT_LENGTH + 28]; + + int line = -1, col = -1; + size_t pos = 0; + const char *result = msg_text; + + if(!error) + return; + + va_start(ap, msg); + vsnprintf(msg_text, JSON_ERROR_TEXT_LENGTH, msg, ap); + msg_text[JSON_ERROR_TEXT_LENGTH - 1] = '\0'; + va_end(ap); + + if(lex) + { + const char *saved_text = strbuffer_value(&lex->saved_text); + + line = lex->stream.line; + col = lex->stream.column; + pos = lex->stream.position; + + if(saved_text && saved_text[0]) + { + if(lex->saved_text.length <= 20) { + snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH + 28, + "%s near '%s'", msg_text, saved_text); + msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0'; + result = msg_with_context; + } + } + else + { + if(code == json_error_invalid_syntax) { + /* More specific error code for premature end of file. */ + code = json_error_premature_end_of_input; + } + if(lex->stream.state == STREAM_STATE_ERROR) { + /* No context for UTF-8 decoding errors */ + result = msg_text; + } + else { + snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH + 17, + "%s near end of file", msg_text); + msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0'; + result = msg_with_context; + } + } + } + + jsonp_error_set(error, line, col, pos, code, "%s", result); +} + + +/*** lexical analyzer ***/ + +static void +stream_init(stream_t *stream, get_func get, void *data) +{ + stream->get = get; + stream->data = data; + stream->buffer[0] = '\0'; + stream->buffer_pos = 0; + + stream->state = STREAM_STATE_OK; + stream->line = 1; + stream->column = 0; + stream->position = 0; +} + +static int stream_get(stream_t *stream, json_error_t *error) +{ + int c; + + if(stream->state != STREAM_STATE_OK) + return stream->state; + + if(!stream->buffer[stream->buffer_pos]) + { + c = stream->get(stream->data); + if(c == EOF) { + stream->state = STREAM_STATE_EOF; + return STREAM_STATE_EOF; + } + + stream->buffer[0] = c; + stream->buffer_pos = 0; + + if(0x80 <= c && c <= 0xFF) + { + /* multi-byte UTF-8 sequence */ + size_t i, count; + + count = utf8_check_first(c); + if(!count) + goto out; + + assert(count >= 2); + + for(i = 1; i < count; i++) + stream->buffer[i] = stream->get(stream->data); + + if(!utf8_check_full(stream->buffer, count, NULL)) + goto out; + + stream->buffer[count] = '\0'; + } + else + stream->buffer[1] = '\0'; + } + + c = stream->buffer[stream->buffer_pos++]; + + stream->position++; + if(c == '\n') { + stream->line++; + stream->last_column = stream->column; + stream->column = 0; + } + else if(utf8_check_first(c)) { + /* track the Unicode character column, so increment only if + this is the first character of a UTF-8 sequence */ + stream->column++; + } + + return c; + +out: + stream->state = STREAM_STATE_ERROR; + error_set(error, stream_to_lex(stream), json_error_invalid_utf8, "unable to decode byte 0x%x", c); + return STREAM_STATE_ERROR; +} + +static void stream_unget(stream_t *stream, int c) +{ + if(c == STREAM_STATE_EOF || c == STREAM_STATE_ERROR) + return; + + stream->position--; + if(c == '\n') { + stream->line--; + stream->column = stream->last_column; + } + else if(utf8_check_first(c)) + stream->column--; + + assert(stream->buffer_pos > 0); + stream->buffer_pos--; + assert(stream->buffer[stream->buffer_pos] == c); +} + + +static int lex_get(lex_t *lex, json_error_t *error) +{ + return stream_get(&lex->stream, error); +} + +static void lex_save(lex_t *lex, int c) +{ + strbuffer_append_byte(&lex->saved_text, c); +} + +static int lex_get_save(lex_t *lex, json_error_t *error) +{ + int c = stream_get(&lex->stream, error); + if(c != STREAM_STATE_EOF && c != STREAM_STATE_ERROR) + lex_save(lex, c); + return c; +} + +static void lex_unget(lex_t *lex, int c) +{ + stream_unget(&lex->stream, c); +} + +static void lex_unget_unsave(lex_t *lex, int c) +{ + if(c != STREAM_STATE_EOF && c != STREAM_STATE_ERROR) { + /* Since we treat warnings as errors, when assertions are turned + * off the "d" variable would be set but never used. Which is + * treated as an error by GCC. + */ + #ifndef NDEBUG + char d; + #endif + stream_unget(&lex->stream, c); + #ifndef NDEBUG + d = + #endif + strbuffer_pop(&lex->saved_text); + assert(c == d); + } +} + +static void lex_save_cached(lex_t *lex) +{ + while(lex->stream.buffer[lex->stream.buffer_pos] != '\0') + { + lex_save(lex, lex->stream.buffer[lex->stream.buffer_pos]); + lex->stream.buffer_pos++; + lex->stream.position++; + } +} + +static void lex_free_string(lex_t *lex) +{ + jsonp_free(lex->value.string.val); + lex->value.string.val = NULL; + lex->value.string.len = 0; +} + +/* assumes that str points to 'u' plus at least 4 valid hex digits */ +static int32_t decode_unicode_escape(const char *str) +{ + int i; + int32_t value = 0; + + assert(str[0] == 'u'); + + for(i = 1; i <= 4; i++) { + char c = str[i]; + value <<= 4; + if(l_isdigit(c)) + value += c - '0'; + else if(l_islower(c)) + value += c - 'a' + 10; + else if(l_isupper(c)) + value += c - 'A' + 10; + else + return -1; + } + + return value; +} + +static void lex_scan_string(lex_t *lex, json_error_t *error) +{ + int c; + const char *p; + char *t; + int i; + + lex->value.string.val = NULL; + lex->token = TOKEN_INVALID; + + c = lex_get_save(lex, error); + + while(c != '"') { + if(c == STREAM_STATE_ERROR) + goto out; + + else if(c == STREAM_STATE_EOF) { + error_set(error, lex, json_error_premature_end_of_input, "premature end of input"); + goto out; + } + + else if(0 <= c && c <= 0x1F) { + /* control character */ + lex_unget_unsave(lex, c); + if(c == '\n') + error_set(error, lex, json_error_invalid_syntax, "unexpected newline"); + else + error_set(error, lex, json_error_invalid_syntax, "control character 0x%x", c); + goto out; + } + + else if(c == '\\') { + c = lex_get_save(lex, error); + if(c == 'u') { + c = lex_get_save(lex, error); + for(i = 0; i < 4; i++) { + if(!l_isxdigit(c)) { + error_set(error, lex, json_error_invalid_syntax, "invalid escape"); + goto out; + } + c = lex_get_save(lex, error); + } + } + else if(c == '"' || c == '\\' || c == '/' || c == 'b' || + c == 'f' || c == 'n' || c == 'r' || c == 't') + c = lex_get_save(lex, error); + else { + error_set(error, lex, json_error_invalid_syntax, "invalid escape"); + goto out; + } + } + else + c = lex_get_save(lex, error); + } + + /* the actual value is at most of the same length as the source + string, because: + - shortcut escapes (e.g. "\t") (length 2) are converted to 1 byte + - a single \uXXXX escape (length 6) is converted to at most 3 bytes + - two \uXXXX escapes (length 12) forming an UTF-16 surrogate pair + are converted to 4 bytes + */ + t = jsonp_malloc(lex->saved_text.length + 1); + if(!t) { + /* this is not very nice, since TOKEN_INVALID is returned */ + goto out; + } + lex->value.string.val = t; + + /* + 1 to skip the " */ + p = strbuffer_value(&lex->saved_text) + 1; + + while(*p != '"') { + if(*p == '\\') { + p++; + if(*p == 'u') { + size_t length; + int32_t value; + + value = decode_unicode_escape(p); + if(value < 0) { + error_set(error, lex, json_error_invalid_syntax, "invalid Unicode escape '%.6s'", p - 1); + goto out; + } + p += 5; + + if(0xD800 <= value && value <= 0xDBFF) { + /* surrogate pair */ + if(*p == '\\' && *(p + 1) == 'u') { + int32_t value2 = decode_unicode_escape(++p); + if(value2 < 0) { + error_set(error, lex, json_error_invalid_syntax, "invalid Unicode escape '%.6s'", p - 1); + goto out; + } + p += 5; + + if(0xDC00 <= value2 && value2 <= 0xDFFF) { + /* valid second surrogate */ + value = + ((value - 0xD800) << 10) + + (value2 - 0xDC00) + + 0x10000; + } + else { + /* invalid second surrogate */ + error_set(error, lex, + json_error_invalid_syntax, + "invalid Unicode '\\u%04X\\u%04X'", + value, value2); + goto out; + } + } + else { + /* no second surrogate */ + error_set(error, lex, json_error_invalid_syntax, "invalid Unicode '\\u%04X'", + value); + goto out; + } + } + else if(0xDC00 <= value && value <= 0xDFFF) { + error_set(error, lex, json_error_invalid_syntax, "invalid Unicode '\\u%04X'", value); + goto out; + } + + if(utf8_encode(value, t, &length)) + assert(0); + t += length; + } + else { + switch(*p) { + case '"': case '\\': case '/': + *t = *p; break; + case 'b': *t = '\b'; break; + case 'f': *t = '\f'; break; + case 'n': *t = '\n'; break; + case 'r': *t = '\r'; break; + case 't': *t = '\t'; break; + default: assert(0); + } + t++; + p++; + } + } + else + *(t++) = *(p++); + } + *t = '\0'; + lex->value.string.len = t - lex->value.string.val; + lex->token = TOKEN_STRING; + return; + +out: + lex_free_string(lex); +} + +#ifndef JANSSON_USING_CMAKE /* disabled if using cmake */ +#if JSON_INTEGER_IS_LONG_LONG +#ifdef _MSC_VER /* Microsoft Visual Studio */ +#define json_strtoint _strtoi64 +#else +#define json_strtoint strtoll +#endif +#else +#define json_strtoint strtol +#endif +#endif + +static int lex_scan_number(lex_t *lex, int c, json_error_t *error) +{ + const char *saved_text; + char *end; + double doubleval; + + lex->token = TOKEN_INVALID; + + if(c == '-') + c = lex_get_save(lex, error); + + if(c == '0') { + c = lex_get_save(lex, error); + if(l_isdigit(c)) { + lex_unget_unsave(lex, c); + goto out; + } + } + else if(l_isdigit(c)) { + do + c = lex_get_save(lex, error); + while(l_isdigit(c)); + } + else { + lex_unget_unsave(lex, c); + goto out; + } + + if(!(lex->flags & JSON_DECODE_INT_AS_REAL) && + c != '.' && c != 'E' && c != 'e') + { + json_int_t intval; + + lex_unget_unsave(lex, c); + + saved_text = strbuffer_value(&lex->saved_text); + + errno = 0; + intval = json_strtoint(saved_text, &end, 10); + if(errno == ERANGE) { + if(intval < 0) + error_set(error, lex, json_error_numeric_overflow, "too big negative integer"); + else + error_set(error, lex, json_error_numeric_overflow, "too big integer"); + goto out; + } + + assert(end == saved_text + lex->saved_text.length); + + lex->token = TOKEN_INTEGER; + lex->value.integer = intval; + return 0; + } + + if(c == '.') { + c = lex_get(lex, error); + if(!l_isdigit(c)) { + lex_unget(lex, c); + goto out; + } + lex_save(lex, c); + + do + c = lex_get_save(lex, error); + while(l_isdigit(c)); + } + + if(c == 'E' || c == 'e') { + c = lex_get_save(lex, error); + if(c == '+' || c == '-') + c = lex_get_save(lex, error); + + if(!l_isdigit(c)) { + lex_unget_unsave(lex, c); + goto out; + } + + do + c = lex_get_save(lex, error); + while(l_isdigit(c)); + } + + lex_unget_unsave(lex, c); + + if(jsonp_strtod(&lex->saved_text, &doubleval)) { + error_set(error, lex, json_error_numeric_overflow, "real number overflow"); + goto out; + } + + lex->token = TOKEN_REAL; + lex->value.real = doubleval; + return 0; + +out: + return -1; +} + +static int lex_scan(lex_t *lex, json_error_t *error) +{ + int c; + + strbuffer_clear(&lex->saved_text); + + if(lex->token == TOKEN_STRING) + lex_free_string(lex); + + do + c = lex_get(lex, error); + while(c == ' ' || c == '\t' || c == '\n' || c == '\r'); + + if(c == STREAM_STATE_EOF) { + lex->token = TOKEN_EOF; + goto out; + } + + if(c == STREAM_STATE_ERROR) { + lex->token = TOKEN_INVALID; + goto out; + } + + lex_save(lex, c); + + if(c == '{' || c == '}' || c == '[' || c == ']' || c == ':' || c == ',') + lex->token = c; + + else if(c == '"') + lex_scan_string(lex, error); + + else if(l_isdigit(c) || c == '-') { + if(lex_scan_number(lex, c, error)) + goto out; + } + + else if(l_isalpha(c)) { + /* eat up the whole identifier for clearer error messages */ + const char *saved_text; + + do + c = lex_get_save(lex, error); + while(l_isalpha(c)); + lex_unget_unsave(lex, c); + + saved_text = strbuffer_value(&lex->saved_text); + + if(strcmp(saved_text, "true") == 0) + lex->token = TOKEN_TRUE; + else if(strcmp(saved_text, "false") == 0) + lex->token = TOKEN_FALSE; + else if(strcmp(saved_text, "null") == 0) + lex->token = TOKEN_NULL; + else + lex->token = TOKEN_INVALID; + } + + else { + /* save the rest of the input UTF-8 sequence to get an error + message of valid UTF-8 */ + lex_save_cached(lex); + lex->token = TOKEN_INVALID; + } + +out: + return lex->token; +} + +static char *lex_steal_string(lex_t *lex, size_t *out_len) +{ + char *result = NULL; + if(lex->token == TOKEN_STRING) { + result = lex->value.string.val; + *out_len = lex->value.string.len; + lex->value.string.val = NULL; + lex->value.string.len = 0; + } + return result; +} + +static int lex_init(lex_t *lex, get_func get, size_t flags, void *data) +{ + stream_init(&lex->stream, get, data); + if(strbuffer_init(&lex->saved_text)) + return -1; + + lex->flags = flags; + lex->token = TOKEN_INVALID; + return 0; +} + +static void lex_close(lex_t *lex) +{ + if(lex->token == TOKEN_STRING) + lex_free_string(lex); + strbuffer_close(&lex->saved_text); +} + + +/*** parser ***/ + +static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error); + +static json_t *parse_object(lex_t *lex, size_t flags, json_error_t *error) +{ + json_t *object = json_object(); + if(!object) + return NULL; + + lex_scan(lex, error); + if(lex->token == '}') + return object; + + while(1) { + char *key; + size_t len; + json_t *value; + + if(lex->token != TOKEN_STRING) { + error_set(error, lex, json_error_invalid_syntax, "string or '}' expected"); + goto error; + } + + key = lex_steal_string(lex, &len); + if(!key) + return NULL; + if (memchr(key, '\0', len)) { + jsonp_free(key); + error_set(error, lex, json_error_null_byte_in_key, "NUL byte in object key not supported"); + goto error; + } + + if(flags & JSON_REJECT_DUPLICATES) { + if(json_object_get(object, key)) { + jsonp_free(key); + error_set(error, lex, json_error_duplicate_key, "duplicate object key"); + goto error; + } + } + + lex_scan(lex, error); + if(lex->token != ':') { + jsonp_free(key); + error_set(error, lex, json_error_invalid_syntax, "':' expected"); + goto error; + } + + lex_scan(lex, error); + value = parse_value(lex, flags, error); + if(!value) { + jsonp_free(key); + goto error; + } + + if(json_object_set_new_nocheck(object, key, value)) { + jsonp_free(key); + goto error; + } + + jsonp_free(key); + + lex_scan(lex, error); + if(lex->token != ',') + break; + + lex_scan(lex, error); + } + + if(lex->token != '}') { + error_set(error, lex, json_error_invalid_syntax, "'}' expected"); + goto error; + } + + return object; + +error: + json_decref(object); + return NULL; +} + +static json_t *parse_array(lex_t *lex, size_t flags, json_error_t *error) +{ + json_t *array = json_array(); + if(!array) + return NULL; + + lex_scan(lex, error); + if(lex->token == ']') + return array; + + while(lex->token) { + json_t *elem = parse_value(lex, flags, error); + if(!elem) + goto error; + + if(json_array_append_new(array, elem)) { + goto error; + } + + lex_scan(lex, error); + if(lex->token != ',') + break; + + lex_scan(lex, error); + } + + if(lex->token != ']') { + error_set(error, lex, json_error_invalid_syntax, "']' expected"); + goto error; + } + + return array; + +error: + json_decref(array); + return NULL; +} + +static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error) +{ + json_t *json; + + lex->depth++; + if(lex->depth > JSON_PARSER_MAX_DEPTH) { + error_set(error, lex, json_error_stack_overflow, "maximum parsing depth reached"); + return NULL; + } + + switch(lex->token) { + case TOKEN_STRING: { + const char *value = lex->value.string.val; + size_t len = lex->value.string.len; + + if(!(flags & JSON_ALLOW_NUL)) { + if(memchr(value, '\0', len)) { + error_set(error, lex, json_error_null_character, "\\u0000 is not allowed without JSON_ALLOW_NUL"); + return NULL; + } + } + + json = jsonp_stringn_nocheck_own(value, len); + if(json) { + lex->value.string.val = NULL; + lex->value.string.len = 0; + } + break; + } + + case TOKEN_INTEGER: { + json = json_integer(lex->value.integer); + break; + } + + case TOKEN_REAL: { + json = json_real(lex->value.real); + break; + } + + case TOKEN_TRUE: + json = json_true(); + break; + + case TOKEN_FALSE: + json = json_false(); + break; + + case TOKEN_NULL: + json = json_null(); + break; + + case '{': + json = parse_object(lex, flags, error); + break; + + case '[': + json = parse_array(lex, flags, error); + break; + + case TOKEN_INVALID: + error_set(error, lex, json_error_invalid_syntax, "invalid token"); + return NULL; + + default: + error_set(error, lex, json_error_invalid_syntax, "unexpected token"); + return NULL; + } + + if(!json) + return NULL; + + lex->depth--; + return json; +} + +static json_t *parse_json(lex_t *lex, size_t flags, json_error_t *error) +{ + json_t *result; + + lex->depth = 0; + + lex_scan(lex, error); + if(!(flags & JSON_DECODE_ANY)) { + if(lex->token != '[' && lex->token != '{') { + error_set(error, lex, json_error_invalid_syntax, "'[' or '{' expected"); + return NULL; + } + } + + result = parse_value(lex, flags, error); + if(!result) + return NULL; + + if(!(flags & JSON_DISABLE_EOF_CHECK)) { + lex_scan(lex, error); + if(lex->token != TOKEN_EOF) { + error_set(error, lex, json_error_end_of_input_expected, "end of file expected"); + json_decref(result); + return NULL; + } + } + + if(error) { + /* Save the position even though there was no error */ + error->position = (int)lex->stream.position; + } + + return result; +} + +typedef struct +{ + const char *data; + size_t pos; +} string_data_t; + +static int string_get(void *data) +{ + char c; + string_data_t *stream = (string_data_t *)data; + c = stream->data[stream->pos]; + if(c == '\0') + return EOF; + else + { + stream->pos++; + return (unsigned char)c; + } +} + +json_t *json_loads(const char *string, size_t flags, json_error_t *error) +{ + lex_t lex; + json_t *result; + string_data_t stream_data; + + jsonp_error_init(error, ""); + + if (string == NULL) { + error_set(error, NULL, json_error_invalid_argument, "wrong arguments"); + return NULL; + } + + stream_data.data = string; + stream_data.pos = 0; + + if(lex_init(&lex, string_get, flags, (void *)&stream_data)) + return NULL; + + result = parse_json(&lex, flags, error); + + lex_close(&lex); + return result; +} + +typedef struct +{ + const char *data; + size_t len; + size_t pos; +} buffer_data_t; + +static int buffer_get(void *data) +{ + char c; + buffer_data_t *stream = data; + if(stream->pos >= stream->len) + return EOF; + + c = stream->data[stream->pos]; + stream->pos++; + return (unsigned char)c; +} + +json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error) +{ + lex_t lex; + json_t *result; + buffer_data_t stream_data; + + jsonp_error_init(error, ""); + + if (buffer == NULL) { + error_set(error, NULL, json_error_invalid_argument, "wrong arguments"); + return NULL; + } + + stream_data.data = buffer; + stream_data.pos = 0; + stream_data.len = buflen; + + if(lex_init(&lex, buffer_get, flags, (void *)&stream_data)) + return NULL; + + result = parse_json(&lex, flags, error); + + lex_close(&lex); + return result; +} + +json_t *json_loadf(FILE *input, size_t flags, json_error_t *error) +{ + lex_t lex; + const char *source; + json_t *result; + + if(input == stdin) + source = ""; + else + source = ""; + + jsonp_error_init(error, source); + + if (input == NULL) { + error_set(error, NULL, json_error_invalid_argument, "wrong arguments"); + return NULL; + } + + if(lex_init(&lex, (get_func)fgetc, flags, input)) + return NULL; + + result = parse_json(&lex, flags, error); + + lex_close(&lex); + return result; +} + +static int fd_get_func(int *fd) +{ + uint8_t c; +#ifdef HAVE_UNISTD_H + if (read(*fd, &c, 1) == 1) + return c; +#endif + return EOF; +} + +json_t *json_loadfd(int input, size_t flags, json_error_t *error) +{ + lex_t lex; + const char *source; + json_t *result; + +#ifdef HAVE_UNISTD_H + if(input == STDIN_FILENO) + source = ""; + else +#endif + source = ""; + + jsonp_error_init(error, source); + + if (input < 0) { + error_set(error, NULL, json_error_invalid_argument, "wrong arguments"); + return NULL; + } + + if(lex_init(&lex, (get_func)fd_get_func, flags, &input)) + return NULL; + + result = parse_json(&lex, flags, error); + + lex_close(&lex); + return result; +} + +json_t *json_load_file(const char *path, size_t flags, json_error_t *error) +{ + json_t *result; + FILE *fp; + + jsonp_error_init(error, path); + + if (path == NULL) { + error_set(error, NULL, json_error_invalid_argument, "wrong arguments"); + return NULL; + } + + fp = fopen(path, "rb"); + if(!fp) + { + error_set(error, NULL, json_error_cannot_open_file, "unable to open %s: %s", + path, strerror(errno)); + return NULL; + } + + result = json_loadf(fp, flags, error); + + fclose(fp); + return result; +} + +#define MAX_BUF_LEN 1024 + +typedef struct +{ + char data[MAX_BUF_LEN]; + size_t len; + size_t pos; + json_load_callback_t callback; + void *arg; +} callback_data_t; + +static int callback_get(void *data) +{ + char c; + callback_data_t *stream = data; + + if(stream->pos >= stream->len) { + stream->pos = 0; + stream->len = stream->callback(stream->data, MAX_BUF_LEN, stream->arg); + if(stream->len == 0 || stream->len == (size_t)-1) + return EOF; + } + + c = stream->data[stream->pos]; + stream->pos++; + return (unsigned char)c; +} + +json_t *json_load_callback(json_load_callback_t callback, void *arg, size_t flags, json_error_t *error) +{ + lex_t lex; + json_t *result; + + callback_data_t stream_data; + + memset(&stream_data, 0, sizeof(stream_data)); + stream_data.callback = callback; + stream_data.arg = arg; + + jsonp_error_init(error, ""); + + if (callback == NULL) { + error_set(error, NULL, json_error_invalid_argument, "wrong arguments"); + return NULL; + } + + if(lex_init(&lex, (get_func)callback_get, flags, &stream_data)) + return NULL; + + result = parse_json(&lex, flags, error); + + lex_close(&lex); + return result; +} diff --git a/client/jansson/lookup3.h b/client/jansson/lookup3.h new file mode 100644 index 000000000..2fe4c258f --- /dev/null +++ b/client/jansson/lookup3.h @@ -0,0 +1,381 @@ +/* +------------------------------------------------------------------------------- +lookup3.c, by Bob Jenkins, May 2006, Public Domain. + +These are functions for producing 32-bit hashes for hash table lookup. +hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() +are externally useful functions. Routines to test the hash are included +if SELF_TEST is defined. You can use this free for any purpose. It's in +the public domain. It has no warranty. + +You probably want to use hashlittle(). hashlittle() and hashbig() +hash byte arrays. hashlittle() is is faster than hashbig() on +little-endian machines. Intel and AMD are little-endian machines. +On second thought, you probably want hashlittle2(), which is identical to +hashlittle() except it returns two 32-bit hashes for the price of one. +You could implement hashbig2() if you wanted but I haven't bothered here. + +If you want to find a hash of, say, exactly 7 integers, do + a = i1; b = i2; c = i3; + mix(a,b,c); + a += i4; b += i5; c += i6; + mix(a,b,c); + a += i7; + final(a,b,c); +then use c as the hash value. If you have a variable length array of +4-byte integers to hash, use hashword(). If you have a byte array (like +a character string), use hashlittle(). If you have several byte arrays, or +a mix of things, see the comments above hashlittle(). + +Why is this so big? I read 12 bytes at a time into 3 4-byte integers, +then mix those integers. This is fast (you can do a lot more thorough +mixing with 12*3 instructions on 3 integers than you can with 3 instructions +on 1 byte), but shoehorning those bytes into integers efficiently is messy. +------------------------------------------------------------------------------- +*/ + +#include + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_STDINT_H +#include /* defines uint32_t etc */ +#endif + +#ifdef HAVE_SYS_PARAM_H +#include /* attempt to define endianness */ +#endif + +#ifdef HAVE_ENDIAN_H +# include /* attempt to define endianness */ +#endif + +/* + * My best guess at if you are big-endian or little-endian. This may + * need adjustment. + */ +#if (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && \ + __BYTE_ORDER == __LITTLE_ENDIAN) || \ + (defined(i386) || defined(__i386__) || defined(__i486__) || \ + defined(__i586__) || defined(__i686__) || defined(vax) || defined(MIPSEL)) +# define HASH_LITTLE_ENDIAN 1 +# define HASH_BIG_ENDIAN 0 +#elif (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && \ + __BYTE_ORDER == __BIG_ENDIAN) || \ + (defined(sparc) || defined(POWERPC) || defined(mc68000) || defined(sel)) +# define HASH_LITTLE_ENDIAN 0 +# define HASH_BIG_ENDIAN 1 +#else +# define HASH_LITTLE_ENDIAN 0 +# define HASH_BIG_ENDIAN 0 +#endif + +#define hashsize(n) ((uint32_t)1<<(n)) +#define hashmask(n) (hashsize(n)-1) +#define rot(x,k) (((x)<<(k)) | ((x)>>(32-(k)))) + +/* +------------------------------------------------------------------------------- +mix -- mix 3 32-bit values reversibly. + +This is reversible, so any information in (a,b,c) before mix() is +still in (a,b,c) after mix(). + +If four pairs of (a,b,c) inputs are run through mix(), or through +mix() in reverse, there are at least 32 bits of the output that +are sometimes the same for one pair and different for another pair. +This was tested for: +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that +satisfy this are + 4 6 8 16 19 4 + 9 15 3 18 27 15 + 14 9 3 7 17 3 +Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing +for "differ" defined as + with a one-bit base and a two-bit delta. I +used http://burtleburtle.net/bob/hash/avalanche.html to choose +the operations, constants, and arrangements of the variables. + +This does not achieve avalanche. There are input bits of (a,b,c) +that fail to affect some output bits of (a,b,c), especially of a. The +most thoroughly mixed value is c, but it doesn't really even achieve +avalanche in c. + +This allows some parallelism. Read-after-writes are good at doubling +the number of bits affected, so the goal of mixing pulls in the opposite +direction as the goal of parallelism. I did what I could. Rotates +seem to cost as much as shifts on every machine I could lay my hands +on, and rotates are much kinder to the top and bottom bits, so I used +rotates. +------------------------------------------------------------------------------- +*/ +#define mix(a,b,c) \ +{ \ + a -= c; a ^= rot(c, 4); c += b; \ + b -= a; b ^= rot(a, 6); a += c; \ + c -= b; c ^= rot(b, 8); b += a; \ + a -= c; a ^= rot(c,16); c += b; \ + b -= a; b ^= rot(a,19); a += c; \ + c -= b; c ^= rot(b, 4); b += a; \ +} + +/* +------------------------------------------------------------------------------- +final -- final mixing of 3 32-bit values (a,b,c) into c + +Pairs of (a,b,c) values differing in only a few bits will usually +produce values of c that look totally different. This was tested for +* pairs that differed by one bit, by two bits, in any combination + of top bits of (a,b,c), or in any combination of bottom bits of + (a,b,c). +* "differ" is defined as +, -, ^, or ~^. For + and -, I transformed + the output delta to a Gray code (a^(a>>1)) so a string of 1's (as + is commonly produced by subtraction) look like a single 1-bit + difference. +* the base values were pseudorandom, all zero but one bit set, or + all zero plus a counter that starts at zero. + +These constants passed: + 14 11 25 16 4 14 24 + 12 14 25 16 4 14 24 +and these came close: + 4 8 15 26 3 22 24 + 10 8 15 26 3 22 24 + 11 8 15 26 3 22 24 +------------------------------------------------------------------------------- +*/ +#define final(a,b,c) \ +{ \ + c ^= b; c -= rot(b,14); \ + a ^= c; a -= rot(c,11); \ + b ^= a; b -= rot(a,25); \ + c ^= b; c -= rot(b,16); \ + a ^= c; a -= rot(c,4); \ + b ^= a; b -= rot(a,14); \ + c ^= b; c -= rot(b,24); \ +} + +/* +------------------------------------------------------------------------------- +hashlittle() -- hash a variable-length key into a 32-bit value + k : the key (the unaligned variable-length array of bytes) + length : the length of the key, counting by bytes + initval : can be any 4-byte value +Returns a 32-bit value. Every bit of the key affects every bit of +the return value. Two keys differing by one or two bits will have +totally different hash values. + +The best hash table sizes are powers of 2. There is no need to do +mod a prime (mod is sooo slow!). If you need less than 32 bits, +use a bitmask. For example, if you need only 10 bits, do + h = (h & hashmask(10)); +In which case, the hash table should have hashsize(10) elements. + +If you are hashing n strings (uint8_t **)k, do it like this: + for (i=0, h=0; i 12) + { + a += k[0]; + b += k[1]; + c += k[2]; + mix(a,b,c); + length -= 12; + k += 3; + } + + /*----------------------------- handle the last (probably partial) block */ + /* + * "k[2]&0xffffff" actually reads beyond the end of the string, but + * then masks off the part it's not allowed to read. Because the + * string is aligned, the masked-off tail is in the same word as the + * rest of the string. Every machine with memory protection I've seen + * does it on word boundaries, so is OK with this. But VALGRIND will + * still catch it and complain. The masking trick does make the hash + * noticably faster for short strings (like English words). + */ +#ifndef NO_MASKING_TRICK + + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=k[2]&0xffffff; b+=k[1]; a+=k[0]; break; + case 10: c+=k[2]&0xffff; b+=k[1]; a+=k[0]; break; + case 9 : c+=k[2]&0xff; b+=k[1]; a+=k[0]; break; + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=k[1]&0xffffff; a+=k[0]; break; + case 6 : b+=k[1]&0xffff; a+=k[0]; break; + case 5 : b+=k[1]&0xff; a+=k[0]; break; + case 4 : a+=k[0]; break; + case 3 : a+=k[0]&0xffffff; break; + case 2 : a+=k[0]&0xffff; break; + case 1 : a+=k[0]&0xff; break; + case 0 : return c; /* zero length strings require no mixing */ + } + +#else /* make valgrind happy */ + + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[2]; b+=k[1]; a+=k[0]; break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=((uint32_t)k8[9])<<8; /* fall through */ + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[1]; a+=k[0]; break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=((uint32_t)k8[5])<<8; /* fall through */ + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]; break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=((uint32_t)k8[1])<<8; /* fall through */ + case 1 : a+=k8[0]; break; + case 0 : return c; + } + +#endif /* !valgrind */ + + } else if (HASH_LITTLE_ENDIAN && ((u.i & 0x1) == 0)) { + const uint16_t *k = (const uint16_t *)key; /* read 16-bit chunks */ + const uint8_t *k8; + + /*--------------- all but last block: aligned reads and different mixing */ + while (length > 12) + { + a += k[0] + (((uint32_t)k[1])<<16); + b += k[2] + (((uint32_t)k[3])<<16); + c += k[4] + (((uint32_t)k[5])<<16); + mix(a,b,c); + length -= 12; + k += 6; + } + + /*----------------------------- handle the last (probably partial) block */ + k8 = (const uint8_t *)k; + switch(length) + { + case 12: c+=k[4]+(((uint32_t)k[5])<<16); + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 11: c+=((uint32_t)k8[10])<<16; /* fall through */ + case 10: c+=k[4]; + b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 9 : c+=k8[8]; /* fall through */ + case 8 : b+=k[2]+(((uint32_t)k[3])<<16); + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 7 : b+=((uint32_t)k8[6])<<16; /* fall through */ + case 6 : b+=k[2]; + a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 5 : b+=k8[4]; /* fall through */ + case 4 : a+=k[0]+(((uint32_t)k[1])<<16); + break; + case 3 : a+=((uint32_t)k8[2])<<16; /* fall through */ + case 2 : a+=k[0]; + break; + case 1 : a+=k8[0]; + break; + case 0 : return c; /* zero length requires no mixing */ + } + + } else { /* need to read the key one byte at a time */ + const uint8_t *k = (const uint8_t *)key; + + /*--------------- all but the last block: affect some 32 bits of (a,b,c) */ + while (length > 12) + { + a += k[0]; + a += ((uint32_t)k[1])<<8; + a += ((uint32_t)k[2])<<16; + a += ((uint32_t)k[3])<<24; + b += k[4]; + b += ((uint32_t)k[5])<<8; + b += ((uint32_t)k[6])<<16; + b += ((uint32_t)k[7])<<24; + c += k[8]; + c += ((uint32_t)k[9])<<8; + c += ((uint32_t)k[10])<<16; + c += ((uint32_t)k[11])<<24; + mix(a,b,c); + length -= 12; + k += 12; + } + + /*-------------------------------- last block: affect all 32 bits of (c) */ + switch(length) /* all the case statements fall through */ + { + case 12: c+=((uint32_t)k[11])<<24; /* fall through */ + case 11: c+=((uint32_t)k[10])<<16; /* fall through */ + case 10: c+=((uint32_t)k[9])<<8; /* fall through */ + case 9 : c+=k[8]; /* fall through */ + case 8 : b+=((uint32_t)k[7])<<24; /* fall through */ + case 7 : b+=((uint32_t)k[6])<<16; /* fall through */ + case 6 : b+=((uint32_t)k[5])<<8; /* fall through */ + case 5 : b+=k[4]; /* fall through */ + case 4 : a+=((uint32_t)k[3])<<24; /* fall through */ + case 3 : a+=((uint32_t)k[2])<<16; /* fall through */ + case 2 : a+=((uint32_t)k[1])<<8; /* fall through */ + case 1 : a+=k[0]; + break; + case 0 : return c; + } + } + + final(a,b,c); + return c; +} diff --git a/client/jansson/memory.c b/client/jansson/memory.c new file mode 100644 index 000000000..a2be5d23d --- /dev/null +++ b/client/jansson/memory.c @@ -0,0 +1,69 @@ +/* + * Copyright (c) 2009-2016 Petri Lehtinen + * Copyright (c) 2011-2012 Basile Starynkevitch + * + * Jansson is free software; you can redistribute it and/or modify it + * under the terms of the MIT license. See LICENSE for details. + */ + +#include +#include + +#include "jansson.h" +#include "jansson_private.h" + +/* C89 allows these to be macros */ +#undef malloc +#undef free + +/* memory function pointers */ +static json_malloc_t do_malloc = malloc; +static json_free_t do_free = free; + +void *jsonp_malloc(size_t size) +{ + if(!size) + return NULL; + + return (*do_malloc)(size); +} + +void jsonp_free(void *ptr) +{ + if(!ptr) + return; + + (*do_free)(ptr); +} + +char *jsonp_strdup(const char *str) +{ + return jsonp_strndup(str, strlen(str)); +} + +char *jsonp_strndup(const char *str, size_t len) +{ + char *new_str; + + new_str = jsonp_malloc(len + 1); + if(!new_str) + return NULL; + + memcpy(new_str, str, len); + new_str[len] = '\0'; + return new_str; +} + +void json_set_alloc_funcs(json_malloc_t malloc_fn, json_free_t free_fn) +{ + do_malloc = malloc_fn; + do_free = free_fn; +} + +void json_get_alloc_funcs(json_malloc_t *malloc_fn, json_free_t *free_fn) +{ + if (malloc_fn) + *malloc_fn = do_malloc; + if (free_fn) + *free_fn = do_free; +} diff --git a/client/jansson/pack_unpack.c b/client/jansson/pack_unpack.c new file mode 100644 index 000000000..153f64d19 --- /dev/null +++ b/client/jansson/pack_unpack.c @@ -0,0 +1,909 @@ +/* + * Copyright (c) 2009-2016 Petri Lehtinen + * Copyright (c) 2011-2012 Graeme Smecher + * + * Jansson is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include +#include "jansson.h" +#include "jansson_private.h" +#include "utf.h" + +typedef struct { + int line; + int column; + size_t pos; + char token; +} token_t; + +typedef struct { + const char *start; + const char *fmt; + token_t prev_token; + token_t token; + token_t next_token; + json_error_t *error; + size_t flags; + int line; + int column; + size_t pos; + int has_error; +} scanner_t; + +#define token(scanner) ((scanner)->token.token) + +static const char * const type_names[] = { + "object", + "array", + "string", + "integer", + "real", + "true", + "false", + "null" +}; + +#define type_name(x) type_names[json_typeof(x)] + +static const char unpack_value_starters[] = "{[siIbfFOon"; + +static void scanner_init(scanner_t *s, json_error_t *error, + size_t flags, const char *fmt) +{ + s->error = error; + s->flags = flags; + s->fmt = s->start = fmt; + memset(&s->prev_token, 0, sizeof(token_t)); + memset(&s->token, 0, sizeof(token_t)); + memset(&s->next_token, 0, sizeof(token_t)); + s->line = 1; + s->column = 0; + s->pos = 0; + s->has_error = 0; +} + +static void next_token(scanner_t *s) +{ + const char *t; + s->prev_token = s->token; + + if(s->next_token.line) { + s->token = s->next_token; + s->next_token.line = 0; + return; + } + + t = s->fmt; + s->column++; + s->pos++; + + /* skip space and ignored chars */ + while(*t == ' ' || *t == '\t' || *t == '\n' || *t == ',' || *t == ':') { + if(*t == '\n') { + s->line++; + s->column = 1; + } + else + s->column++; + + s->pos++; + t++; + } + + s->token.token = *t; + s->token.line = s->line; + s->token.column = s->column; + s->token.pos = s->pos; + + t++; + s->fmt = t; +} + +static void prev_token(scanner_t *s) +{ + s->next_token = s->token; + s->token = s->prev_token; +} + +static void set_error(scanner_t *s, const char *source, enum json_error_code code, + const char *fmt, ...) +{ + va_list ap; + va_start(ap, fmt); + + jsonp_error_vset(s->error, s->token.line, s->token.column, s->token.pos, + code, fmt, ap); + + jsonp_error_set_source(s->error, source); + + va_end(ap); +} + +static json_t *pack(scanner_t *s, va_list *ap); + + +/* ours will be set to 1 if jsonp_free() must be called for the result + afterwards */ +static char *read_string(scanner_t *s, va_list *ap, + const char *purpose, size_t *out_len, int *ours) +{ + char t; + strbuffer_t strbuff; + const char *str; + size_t length; + + next_token(s); + t = token(s); + prev_token(s); + + *ours = 0; + if(t != '#' && t != '%' && t != '+') { + /* Optimize the simple case */ + str = va_arg(*ap, const char *); + + if(!str) { + set_error(s, "", json_error_null_value, "NULL string argument"); + return NULL; + } + + length = strlen(str); + + if(!utf8_check_string(str, length)) { + set_error(s, "", json_error_invalid_utf8, "Invalid UTF-8 %s", purpose); + return NULL; + } + + *out_len = length; + return (char *)str; + } + + strbuffer_init(&strbuff); + + while(1) { + str = va_arg(*ap, const char *); + if(!str) { + set_error(s, "", json_error_null_value, "NULL string argument"); + s->has_error = 1; + } + + next_token(s); + + if(token(s) == '#') { + length = va_arg(*ap, int); + } + else if(token(s) == '%') { + length = va_arg(*ap, size_t); + } + else { + prev_token(s); + length = s->has_error ? 0 : strlen(str); + } + + if(!s->has_error && strbuffer_append_bytes(&strbuff, str, length) == -1) { + set_error(s, "", json_error_out_of_memory, "Out of memory"); + s->has_error = 1; + } + + next_token(s); + if(token(s) != '+') { + prev_token(s); + break; + } + } + + if(s->has_error) { + strbuffer_close(&strbuff); + return NULL; + } + + if(!utf8_check_string(strbuff.value, strbuff.length)) { + set_error(s, "", json_error_invalid_utf8, "Invalid UTF-8 %s", purpose); + strbuffer_close(&strbuff); + s->has_error = 1; + return NULL; + } + + *out_len = strbuff.length; + *ours = 1; + return strbuffer_steal_value(&strbuff); +} + +static json_t *pack_object(scanner_t *s, va_list *ap) +{ + json_t *object = json_object(); + next_token(s); + + while(token(s) != '}') { + char *key; + size_t len; + int ours; + json_t *value; + + if(!token(s)) { + set_error(s, "", json_error_invalid_format, "Unexpected end of format string"); + goto error; + } + + if(token(s) != 's') { + set_error(s, "", json_error_invalid_format, "Expected format 's', got '%c'", token(s)); + goto error; + } + + key = read_string(s, ap, "object key", &len, &ours); + if (!key) + s->has_error = 1; + + next_token(s); + + value = pack(s, ap); + if(!value) { + if(ours) + jsonp_free(key); + + if(strchr("soO", token(s)) && s->next_token.token == '*') { + next_token(s); + } else { + s->has_error = 1; + } + + next_token(s); + continue; + } + + if(s->has_error) + json_decref(value); + + if(!s->has_error && json_object_set_new_nocheck(object, key, value)) { + set_error(s, "", json_error_out_of_memory, "Unable to add key \"%s\"", key); + s->has_error = 1; + } + + if(ours) + jsonp_free(key); + + if(strchr("soO", token(s)) && s->next_token.token == '*') + next_token(s); + next_token(s); + } + + if(!s->has_error) + return object; + +error: + json_decref(object); + return NULL; +} + +static json_t *pack_array(scanner_t *s, va_list *ap) +{ + json_t *array = json_array(); + next_token(s); + + while(token(s) != ']') { + json_t *value; + + if(!token(s)) { + set_error(s, "", json_error_invalid_format, "Unexpected end of format string"); + /* Format string errors are unrecoverable. */ + goto error; + } + + value = pack(s, ap); + if(!value) { + if(strchr("soO", token(s)) && s->next_token.token == '*') { + next_token(s); + } else { + s->has_error = 1; + } + + next_token(s); + continue; + } + + if(s->has_error) + json_decref(value); + + if(!s->has_error && json_array_append_new(array, value)) { + set_error(s, "", json_error_out_of_memory, "Unable to append to array"); + s->has_error = 1; + } + + if(strchr("soO", token(s)) && s->next_token.token == '*') + next_token(s); + next_token(s); + } + + if(!s->has_error) + return array; + +error: + json_decref(array); + return NULL; +} + +static json_t *pack_string(scanner_t *s, va_list *ap) +{ + char *str; + size_t len; + int ours; + int nullable; + + next_token(s); + nullable = token(s) == '?'; + if (!nullable) + prev_token(s); + + str = read_string(s, ap, "string", &len, &ours); + if (!str) { + return nullable ? json_null() : NULL; + } else if (ours) { + return jsonp_stringn_nocheck_own(str, len); + } else { + return json_stringn_nocheck(str, len); + } +} + +static json_t *pack(scanner_t *s, va_list *ap) +{ + switch(token(s)) { + case '{': + return pack_object(s, ap); + + case '[': + return pack_array(s, ap); + + case 's': /* string */ + return pack_string(s, ap); + + case 'n': /* null */ + return json_null(); + + case 'b': /* boolean */ + return va_arg(*ap, int) ? json_true() : json_false(); + + case 'i': /* integer from int */ + return json_integer(va_arg(*ap, int)); + + case 'I': /* integer from json_int_t */ + return json_integer(va_arg(*ap, json_int_t)); + + case 'f': /* real */ + return json_real(va_arg(*ap, double)); + + case 'O': /* a json_t object; increments refcount */ + { + int nullable; + json_t *json; + + next_token(s); + nullable = token(s) == '?'; + if (!nullable) + prev_token(s); + + json = va_arg(*ap, json_t *); + if (!json && nullable) { + return json_null(); + } else { + return json_incref(json); + } + } + + case 'o': /* a json_t object; doesn't increment refcount */ + { + int nullable; + json_t *json; + + next_token(s); + nullable = token(s) == '?'; + if (!nullable) + prev_token(s); + + json = va_arg(*ap, json_t *); + if (!json && nullable) { + return json_null(); + } else { + return json; + } + } + + default: + set_error(s, "", json_error_invalid_format, "Unexpected format character '%c'", + token(s)); + s->has_error = 1; + return NULL; + } +} + +static int unpack(scanner_t *s, json_t *root, va_list *ap); + +static int unpack_object(scanner_t *s, json_t *root, va_list *ap) +{ + int ret = -1; + int strict = 0; + int gotopt = 0; + + /* Use a set (emulated by a hashtable) to check that all object + keys are accessed. Checking that the correct number of keys + were accessed is not enough, as the same key can be unpacked + multiple times. + */ + hashtable_t key_set; + + if(hashtable_init(&key_set)) { + set_error(s, "", json_error_out_of_memory, "Out of memory"); + return -1; + } + + if(root && !json_is_object(root)) { + set_error(s, "", json_error_wrong_type, "Expected object, got %s", + type_name(root)); + goto out; + } + next_token(s); + + while(token(s) != '}') { + const char *key; + json_t *value; + int opt = 0; + + if(strict != 0) { + set_error(s, "", json_error_invalid_format, "Expected '}' after '%c', got '%c'", + (strict == 1 ? '!' : '*'), token(s)); + goto out; + } + + if(!token(s)) { + set_error(s, "", json_error_invalid_format, "Unexpected end of format string"); + goto out; + } + + if(token(s) == '!' || token(s) == '*') { + strict = (token(s) == '!' ? 1 : -1); + next_token(s); + continue; + } + + if(token(s) != 's') { + set_error(s, "", json_error_invalid_format, "Expected format 's', got '%c'", token(s)); + goto out; + } + + key = va_arg(*ap, const char *); + if(!key) { + set_error(s, "", json_error_null_value, "NULL object key"); + goto out; + } + + next_token(s); + + if(token(s) == '?') { + opt = gotopt = 1; + next_token(s); + } + + if(!root) { + /* skipping */ + value = NULL; + } + else { + value = json_object_get(root, key); + if(!value && !opt) { + set_error(s, "", json_error_item_not_found, "Object item not found: %s", key); + goto out; + } + } + + if(unpack(s, value, ap)) + goto out; + + hashtable_set(&key_set, key, json_null()); + next_token(s); + } + + if(strict == 0 && (s->flags & JSON_STRICT)) + strict = 1; + + if(root && strict == 1) { + /* We need to check that all non optional items have been parsed */ + const char *key; + int have_unrecognized_keys = 0; + strbuffer_t unrecognized_keys; + json_t *value; + long unpacked = 0; + if (gotopt) { + /* We have optional keys, we need to iter on each key */ + json_object_foreach(root, key, value) { + if(!hashtable_get(&key_set, key)) { + unpacked++; + + /* Save unrecognized keys for the error message */ + if (!have_unrecognized_keys) { + strbuffer_init(&unrecognized_keys); + have_unrecognized_keys = 1; + } else { + strbuffer_append_bytes(&unrecognized_keys, ", ", 2); + } + strbuffer_append_bytes(&unrecognized_keys, key, strlen(key)); + } + } + } else { + /* No optional keys, we can just compare the number of items */ + unpacked = (long)json_object_size(root) - (long)key_set.size; + } + if (unpacked) { + if (!gotopt) { + /* Save unrecognized keys for the error message */ + json_object_foreach(root, key, value) { + if(!hashtable_get(&key_set, key)) { + if (!have_unrecognized_keys) { + strbuffer_init(&unrecognized_keys); + have_unrecognized_keys = 1; + } else { + strbuffer_append_bytes(&unrecognized_keys, ", ", 2); + } + strbuffer_append_bytes(&unrecognized_keys, key, strlen(key)); + } + } + } + set_error(s, "", json_error_end_of_input_expected, + "%li object item(s) left unpacked: %s", + unpacked, strbuffer_value(&unrecognized_keys)); + strbuffer_close(&unrecognized_keys); + goto out; + } + } + + ret = 0; + +out: + hashtable_close(&key_set); + return ret; +} + +static int unpack_array(scanner_t *s, json_t *root, va_list *ap) +{ + size_t i = 0; + int strict = 0; + + if(root && !json_is_array(root)) { + set_error(s, "", json_error_wrong_type, "Expected array, got %s", type_name(root)); + return -1; + } + next_token(s); + + while(token(s) != ']') { + json_t *value; + + if(strict != 0) { + set_error(s, "", json_error_invalid_format, "Expected ']' after '%c', got '%c'", + (strict == 1 ? '!' : '*'), + token(s)); + return -1; + } + + if(!token(s)) { + set_error(s, "", json_error_invalid_format, "Unexpected end of format string"); + return -1; + } + + if(token(s) == '!' || token(s) == '*') { + strict = (token(s) == '!' ? 1 : -1); + next_token(s); + continue; + } + + if(!strchr(unpack_value_starters, token(s))) { + set_error(s, "", json_error_invalid_format, "Unexpected format character '%c'", + token(s)); + return -1; + } + + if(!root) { + /* skipping */ + value = NULL; + } + else { + value = json_array_get(root, i); + if(!value) { + set_error(s, "", json_error_index_out_of_range, "Array index %lu out of range", + (unsigned long)i); + return -1; + } + } + + if(unpack(s, value, ap)) + return -1; + + next_token(s); + i++; + } + + if(strict == 0 && (s->flags & JSON_STRICT)) + strict = 1; + + if(root && strict == 1 && i != json_array_size(root)) { + long diff = (long)json_array_size(root) - (long)i; + set_error(s, "", json_error_end_of_input_expected, "%li array item(s) left unpacked", diff); + return -1; + } + + return 0; +} + +static int unpack(scanner_t *s, json_t *root, va_list *ap) +{ + switch(token(s)) + { + case '{': + return unpack_object(s, root, ap); + + case '[': + return unpack_array(s, root, ap); + + case 's': + if(root && !json_is_string(root)) { + set_error(s, "", json_error_wrong_type, "Expected string, got %s", + type_name(root)); + return -1; + } + + if(!(s->flags & JSON_VALIDATE_ONLY)) { + const char **str_target; + size_t *len_target = NULL; + + str_target = va_arg(*ap, const char **); + if(!str_target) { + set_error(s, "", json_error_null_value, "NULL string argument"); + return -1; + } + + next_token(s); + + if(token(s) == '%') { + len_target = va_arg(*ap, size_t *); + if(!len_target) { + set_error(s, "", json_error_null_value, "NULL string length argument"); + return -1; + } + } + else + prev_token(s); + + if(root) { + *str_target = json_string_value(root); + if(len_target) + *len_target = json_string_length(root); + } + } + return 0; + + case 'i': + if(root && !json_is_integer(root)) { + set_error(s, "", json_error_wrong_type, "Expected integer, got %s", + type_name(root)); + return -1; + } + + if(!(s->flags & JSON_VALIDATE_ONLY)) { + int *target = va_arg(*ap, int*); + if(root) + *target = (int)json_integer_value(root); + } + + return 0; + + case 'I': + if(root && !json_is_integer(root)) { + set_error(s, "", json_error_wrong_type, "Expected integer, got %s", + type_name(root)); + return -1; + } + + if(!(s->flags & JSON_VALIDATE_ONLY)) { + json_int_t *target = va_arg(*ap, json_int_t*); + if(root) + *target = json_integer_value(root); + } + + return 0; + + case 'b': + if(root && !json_is_boolean(root)) { + set_error(s, "", json_error_wrong_type, "Expected true or false, got %s", + type_name(root)); + return -1; + } + + if(!(s->flags & JSON_VALIDATE_ONLY)) { + int *target = va_arg(*ap, int*); + if(root) + *target = json_is_true(root); + } + + return 0; + + case 'f': + if(root && !json_is_real(root)) { + set_error(s, "", json_error_wrong_type, "Expected real, got %s", + type_name(root)); + return -1; + } + + if(!(s->flags & JSON_VALIDATE_ONLY)) { + double *target = va_arg(*ap, double*); + if(root) + *target = json_real_value(root); + } + + return 0; + + case 'F': + if(root && !json_is_number(root)) { + set_error(s, "", json_error_wrong_type, "Expected real or integer, got %s", + type_name(root)); + return -1; + } + + if(!(s->flags & JSON_VALIDATE_ONLY)) { + double *target = va_arg(*ap, double*); + if(root) + *target = json_number_value(root); + } + + return 0; + + case 'O': + if(root && !(s->flags & JSON_VALIDATE_ONLY)) + json_incref(root); + /* Fall through */ + + case 'o': + if(!(s->flags & JSON_VALIDATE_ONLY)) { + json_t **target = va_arg(*ap, json_t**); + if(root) + *target = root; + } + + return 0; + + case 'n': + /* Never assign, just validate */ + if(root && !json_is_null(root)) { + set_error(s, "", json_error_wrong_type, "Expected null, got %s", + type_name(root)); + return -1; + } + return 0; + + default: + set_error(s, "", json_error_invalid_format, "Unexpected format character '%c'", + token(s)); + return -1; + } +} + +json_t *json_vpack_ex(json_error_t *error, size_t flags, + const char *fmt, va_list ap) +{ + scanner_t s; + va_list ap_copy; + json_t *value; + + if(!fmt || !*fmt) { + jsonp_error_init(error, ""); + jsonp_error_set(error, -1, -1, 0, json_error_invalid_argument, "NULL or empty format string"); + return NULL; + } + jsonp_error_init(error, NULL); + + scanner_init(&s, error, flags, fmt); + next_token(&s); + + va_copy(ap_copy, ap); + value = pack(&s, &ap_copy); + va_end(ap_copy); + + if(!value) + return NULL; + + next_token(&s); + if(token(&s)) { + json_decref(value); + set_error(&s, "", json_error_invalid_format, "Garbage after format string"); + return NULL; + } + if(s.has_error) { + json_decref(value); + return NULL; + } + + return value; +} + +json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...) +{ + json_t *value; + va_list ap; + + va_start(ap, fmt); + value = json_vpack_ex(error, flags, fmt, ap); + va_end(ap); + + return value; +} + +json_t *json_pack(const char *fmt, ...) +{ + json_t *value; + va_list ap; + + va_start(ap, fmt); + value = json_vpack_ex(NULL, 0, fmt, ap); + va_end(ap); + + return value; +} + +int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags, + const char *fmt, va_list ap) +{ + scanner_t s; + va_list ap_copy; + + if(!root) { + jsonp_error_init(error, ""); + jsonp_error_set(error, -1, -1, 0, json_error_null_value, "NULL root value"); + return -1; + } + + if(!fmt || !*fmt) { + jsonp_error_init(error, ""); + jsonp_error_set(error, -1, -1, 0, json_error_invalid_argument, "NULL or empty format string"); + return -1; + } + jsonp_error_init(error, NULL); + + scanner_init(&s, error, flags, fmt); + next_token(&s); + + va_copy(ap_copy, ap); + if(unpack(&s, root, &ap_copy)) { + va_end(ap_copy); + return -1; + } + va_end(ap_copy); + + next_token(&s); + if(token(&s)) { + set_error(&s, "", json_error_invalid_format, "Garbage after format string"); + return -1; + } + + return 0; +} + +int json_unpack_ex(json_t *root, json_error_t *error, size_t flags, const char *fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = json_vunpack_ex(root, error, flags, fmt, ap); + va_end(ap); + + return ret; +} + +int json_unpack(json_t *root, const char *fmt, ...) +{ + int ret; + va_list ap; + + va_start(ap, fmt); + ret = json_vunpack_ex(root, NULL, 0, fmt, ap); + va_end(ap); + + return ret; +} diff --git a/client/jansson/path.c b/client/jansson/path.c index 08f2da9f6..e3098f5f4 100644 --- a/client/jansson/path.c +++ b/client/jansson/path.c @@ -13,7 +13,6 @@ #include #include "jansson_private.h" - json_t *json_path_get(const json_t *json, const char *path) { static const char root_chr = '$', array_open = '['; diff --git a/client/jansson/path.h b/client/jansson/path.h deleted file mode 100644 index e6cf31a2b..000000000 --- a/client/jansson/path.h +++ /dev/null @@ -1,17 +0,0 @@ -/* - * Copyright (c) 2012 Rogerz Zhang - * - * Jansson is free software; you can redistribute it and/or modify - * it under the terms of the MIT license. See LICENSE for details. - * - * source here https://github.com/rogerz/jansson/blob/json_path/src/path.c - */ - -json_t *json_path_get(const json_t *json, const char *path); -int json_path_set_new(json_t *json, const char *path, json_t *value, size_t flags, json_error_t *error); - -static JSON_INLINE -int json_path_set(json_t *json, const char *path, json_t *value, size_t flags, json_error_t *error) -{ - return json_path_set_new(json, path, json_incref(value), flags, error); -} diff --git a/client/jansson/strbuffer.c b/client/jansson/strbuffer.c new file mode 100644 index 000000000..5e8c00395 --- /dev/null +++ b/client/jansson/strbuffer.c @@ -0,0 +1,111 @@ +/* + * Copyright (c) 2009-2016 Petri Lehtinen + * + * Jansson is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#include +#include +#include "jansson_private.h" +#include "strbuffer.h" + +#define STRBUFFER_MIN_SIZE 16 +#define STRBUFFER_FACTOR 2 +#define STRBUFFER_SIZE_MAX ((size_t)-1) + +int strbuffer_init(strbuffer_t *strbuff) +{ + strbuff->size = STRBUFFER_MIN_SIZE; + strbuff->length = 0; + + strbuff->value = jsonp_malloc(strbuff->size); + if(!strbuff->value) + return -1; + + /* initialize to empty */ + strbuff->value[0] = '\0'; + return 0; +} + +void strbuffer_close(strbuffer_t *strbuff) +{ + if(strbuff->value) + jsonp_free(strbuff->value); + + strbuff->size = 0; + strbuff->length = 0; + strbuff->value = NULL; +} + +void strbuffer_clear(strbuffer_t *strbuff) +{ + strbuff->length = 0; + strbuff->value[0] = '\0'; +} + +const char *strbuffer_value(const strbuffer_t *strbuff) +{ + return strbuff->value; +} + +char *strbuffer_steal_value(strbuffer_t *strbuff) +{ + char *result = strbuff->value; + strbuff->value = NULL; + return result; +} + +int strbuffer_append_byte(strbuffer_t *strbuff, char byte) +{ + return strbuffer_append_bytes(strbuff, &byte, 1); +} + +int strbuffer_append_bytes(strbuffer_t *strbuff, const char *data, size_t size) +{ + if(size >= strbuff->size - strbuff->length) + { + size_t new_size; + char *new_value; + + /* avoid integer overflow */ + if (strbuff->size > STRBUFFER_SIZE_MAX / STRBUFFER_FACTOR + || size > STRBUFFER_SIZE_MAX - 1 + || strbuff->length > STRBUFFER_SIZE_MAX - 1 - size) + return -1; + + new_size = max(strbuff->size * STRBUFFER_FACTOR, + strbuff->length + size + 1); + + new_value = jsonp_malloc(new_size); + if(!new_value) + return -1; + + memcpy(new_value, strbuff->value, strbuff->length); + + jsonp_free(strbuff->value); + strbuff->value = new_value; + strbuff->size = new_size; + } + + memcpy(strbuff->value + strbuff->length, data, size); + strbuff->length += size; + strbuff->value[strbuff->length] = '\0'; + + return 0; +} + +char strbuffer_pop(strbuffer_t *strbuff) +{ + if(strbuff->length > 0) { + char c = strbuff->value[--strbuff->length]; + strbuff->value[strbuff->length] = '\0'; + return c; + } + else + return '\0'; +} diff --git a/client/jansson/strconv.c b/client/jansson/strconv.c new file mode 100644 index 000000000..8075481e3 --- /dev/null +++ b/client/jansson/strconv.c @@ -0,0 +1,145 @@ +#include +#include +#include +#include +#include +#ifdef __MINGW32__ +#undef __NO_ISOCEXT /* ensure stdlib.h will declare prototypes for mingw own 'strtod' replacement, called '__strtod' */ +#endif +#include "jansson_private.h" +#include "strbuffer.h" + +/* need jansson_private_config.h to get the correct snprintf */ +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef __MINGW32__ +#define strtod __strtod +#endif + +#if JSON_HAVE_LOCALECONV +#include + +/* + - This code assumes that the decimal separator is exactly one + character. + + - If setlocale() is called by another thread between the call to + localeconv() and the call to sprintf() or strtod(), the result may + be wrong. setlocale() is not thread-safe and should not be used + this way. Multi-threaded programs should use uselocale() instead. +*/ + +static void to_locale(strbuffer_t *strbuffer) +{ + const char *point; + char *pos; + + point = localeconv()->decimal_point; + if(*point == '.') { + /* No conversion needed */ + return; + } + + pos = strchr(strbuffer->value, '.'); + if(pos) + *pos = *point; +} + +static void from_locale(char *buffer) +{ + const char *point; + char *pos; + + point = localeconv()->decimal_point; + if(*point == '.') { + /* No conversion needed */ + return; + } + + pos = strchr(buffer, *point); + if(pos) + *pos = '.'; +} +#endif + +int jsonp_strtod(strbuffer_t *strbuffer, double *out) +{ + double value; + char *end; + +#if JSON_HAVE_LOCALECONV + to_locale(strbuffer); +#endif + + errno = 0; + value = strtod(strbuffer->value, &end); + assert(end == strbuffer->value + strbuffer->length); + + if((value == HUGE_VAL || value == -HUGE_VAL) && errno == ERANGE) { + /* Overflow */ + return -1; + } + + *out = value; + return 0; +} + +int jsonp_dtostr(char *buffer, size_t size, double value, int precision) +{ + int ret; + char *start, *end; + size_t length; + + if (precision == 0) + precision = 17; + + ret = snprintf(buffer, size, "%.*g", precision, value); + if(ret < 0) + return -1; + + length = (size_t)ret; + if(length >= size) + return -1; + +#if JSON_HAVE_LOCALECONV + from_locale(buffer); +#endif + + /* Make sure there's a dot or 'e' in the output. Otherwise + a real is converted to an integer when decoding */ + if(strchr(buffer, '.') == NULL && + strchr(buffer, 'e') == NULL) + { + if(length + 3 >= size) { + /* No space to append ".0" */ + return -1; + } + buffer[length] = '.'; + buffer[length + 1] = '0'; + buffer[length + 2] = '\0'; + length += 2; + } + + /* Remove leading '+' from positive exponent. Also remove leading + zeros from exponents (added by some printf() implementations) */ + start = strchr(buffer, 'e'); + if(start) { + start++; + end = start + 1; + + if(*start == '-') + start++; + + while(*end == '0') + end++; + + if(end != start) { + memmove(start, end, length - (size_t)(end - buffer)); + length -= (size_t)(end - start); + } + } + + return (int)length; +} diff --git a/client/jansson/utf.c b/client/jansson/utf.c new file mode 100644 index 000000000..be966cbd8 --- /dev/null +++ b/client/jansson/utf.c @@ -0,0 +1,187 @@ +/* + * Copyright (c) 2009-2016 Petri Lehtinen + * + * Jansson is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#include +#include "utf.h" + +int utf8_encode(int32_t codepoint, char *buffer, size_t *size) +{ + if(codepoint < 0) + return -1; + else if(codepoint < 0x80) + { + buffer[0] = (char)codepoint; + *size = 1; + } + else if(codepoint < 0x800) + { + buffer[0] = 0xC0 + ((codepoint & 0x7C0) >> 6); + buffer[1] = 0x80 + ((codepoint & 0x03F)); + *size = 2; + } + else if(codepoint < 0x10000) + { + buffer[0] = 0xE0 + ((codepoint & 0xF000) >> 12); + buffer[1] = 0x80 + ((codepoint & 0x0FC0) >> 6); + buffer[2] = 0x80 + ((codepoint & 0x003F)); + *size = 3; + } + else if(codepoint <= 0x10FFFF) + { + buffer[0] = 0xF0 + ((codepoint & 0x1C0000) >> 18); + buffer[1] = 0x80 + ((codepoint & 0x03F000) >> 12); + buffer[2] = 0x80 + ((codepoint & 0x000FC0) >> 6); + buffer[3] = 0x80 + ((codepoint & 0x00003F)); + *size = 4; + } + else + return -1; + + return 0; +} + +size_t utf8_check_first(char byte) +{ + unsigned char u = (unsigned char)byte; + + if(u < 0x80) + return 1; + + if(0x80 <= u && u <= 0xBF) { + /* second, third or fourth byte of a multi-byte + sequence, i.e. a "continuation byte" */ + return 0; + } + else if(u == 0xC0 || u == 0xC1) { + /* overlong encoding of an ASCII byte */ + return 0; + } + else if(0xC2 <= u && u <= 0xDF) { + /* 2-byte sequence */ + return 2; + } + + else if(0xE0 <= u && u <= 0xEF) { + /* 3-byte sequence */ + return 3; + } + else if(0xF0 <= u && u <= 0xF4) { + /* 4-byte sequence */ + return 4; + } + else { /* u >= 0xF5 */ + /* Restricted (start of 4-, 5- or 6-byte sequence) or invalid + UTF-8 */ + return 0; + } +} + +size_t utf8_check_full(const char *buffer, size_t size, int32_t *codepoint) +{ + size_t i; + int32_t value = 0; + unsigned char u = (unsigned char)buffer[0]; + + if(size == 2) + { + value = u & 0x1F; + } + else if(size == 3) + { + value = u & 0xF; + } + else if(size == 4) + { + value = u & 0x7; + } + else + return 0; + + for(i = 1; i < size; i++) + { + u = (unsigned char)buffer[i]; + + if(u < 0x80 || u > 0xBF) { + /* not a continuation byte */ + return 0; + } + + value = (value << 6) + (u & 0x3F); + } + + if(value > 0x10FFFF) { + /* not in Unicode range */ + return 0; + } + + else if(0xD800 <= value && value <= 0xDFFF) { + /* invalid code point (UTF-16 surrogate halves) */ + return 0; + } + + else if((size == 2 && value < 0x80) || + (size == 3 && value < 0x800) || + (size == 4 && value < 0x10000)) { + /* overlong encoding */ + return 0; + } + + if(codepoint) + *codepoint = value; + + return 1; +} + +const char *utf8_iterate(const char *buffer, size_t bufsize, int32_t *codepoint) +{ + size_t count; + int32_t value; + + if(!bufsize) + return buffer; + + count = utf8_check_first(buffer[0]); + if(count <= 0) + return NULL; + + if(count == 1) + value = (unsigned char)buffer[0]; + else + { + if(count > bufsize || !utf8_check_full(buffer, count, &value)) + return NULL; + } + + if(codepoint) + *codepoint = value; + + return buffer + count; +} + +int utf8_check_string(const char *string, size_t length) +{ + size_t i; + + for(i = 0; i < length; i++) + { + size_t count = utf8_check_first(string[i]); + if(count == 0) + return 0; + else if(count > 1) + { + if(count > length - i) + return 0; + + if(!utf8_check_full(&string[i], count, NULL)) + return 0; + + i += count - 1; + } + } + + return 1; +} diff --git a/client/jansson/utf.h b/client/jansson/utf.h new file mode 100644 index 000000000..e182df78f --- /dev/null +++ b/client/jansson/utf.h @@ -0,0 +1,27 @@ +/* + * Copyright (c) 2009-2016 Petri Lehtinen + * + * Jansson is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef UTF_H +#define UTF_H + +#ifdef HAVE_CONFIG_H +#include +#endif + +#ifdef HAVE_STDINT_H +#include +#endif + +int utf8_encode(int32_t codepoint, char *buffer, size_t *size); + +size_t utf8_check_first(char byte); +size_t utf8_check_full(const char *buffer, size_t size, int32_t *codepoint); +const char *utf8_iterate(const char *buffer, size_t size, int32_t *codepoint); + +int utf8_check_string(const char *string, size_t length); + +#endif diff --git a/client/jansson/value.c b/client/jansson/value.c new file mode 100644 index 000000000..b3b31412b --- /dev/null +++ b/client/jansson/value.c @@ -0,0 +1,1078 @@ +/* + * Copyright (c) 2009-2016 Petri Lehtinen + * + * Jansson is free software; you can redistribute it and/or modify + * it under the terms of the MIT license. See LICENSE for details. + */ + +#ifndef _GNU_SOURCE +#define _GNU_SOURCE +#endif + +#ifdef HAVE_CONFIG_H +#include +#endif + +#include +#include +#include +#include + +#ifdef HAVE_STDINT_H +#include +#endif + +#include "jansson.h" +#include "hashtable.h" +#include "jansson_private.h" +#include "utf.h" + +/* Work around nonstandard isnan() and isinf() implementations */ +#ifndef isnan +#ifndef __sun +static JSON_INLINE int isnan(double x) { return x != x; } +#endif +#endif +#ifndef isinf +static JSON_INLINE int isinf(double x) { return !isnan(x) && isnan(x - x); } +#endif + +static JSON_INLINE void json_init(json_t *json, json_type type) +{ + json->type = type; + json->refcount = 1; +} + + +/*** object ***/ + +extern volatile uint32_t hashtable_seed; + +json_t *json_object(void) +{ + json_object_t *object = jsonp_malloc(sizeof(json_object_t)); + if(!object) + return NULL; + + if (!hashtable_seed) { + /* Autoseed */ + json_object_seed(0); + } + + json_init(&object->json, JSON_OBJECT); + + if(hashtable_init(&object->hashtable)) + { + jsonp_free(object); + return NULL; + } + + return &object->json; +} + +static void json_delete_object(json_object_t *object) +{ + hashtable_close(&object->hashtable); + jsonp_free(object); +} + +size_t json_object_size(const json_t *json) +{ + json_object_t *object; + + if(!json_is_object(json)) + return 0; + + object = json_to_object(json); + return object->hashtable.size; +} + +json_t *json_object_get(const json_t *json, const char *key) +{ + json_object_t *object; + + if(!key || !json_is_object(json)) + return NULL; + + object = json_to_object(json); + return hashtable_get(&object->hashtable, key); +} + +int json_object_set_new_nocheck(json_t *json, const char *key, json_t *value) +{ + json_object_t *object; + + if(!value) + return -1; + + if(!key || !json_is_object(json) || json == value) + { + json_decref(value); + return -1; + } + object = json_to_object(json); + + if(hashtable_set(&object->hashtable, key, value)) + { + json_decref(value); + return -1; + } + + return 0; +} + +int json_object_set_new(json_t *json, const char *key, json_t *value) +{ + if(!key || !utf8_check_string(key, strlen(key))) + { + json_decref(value); + return -1; + } + + return json_object_set_new_nocheck(json, key, value); +} + +int json_object_del(json_t *json, const char *key) +{ + json_object_t *object; + + if(!key || !json_is_object(json)) + return -1; + + object = json_to_object(json); + return hashtable_del(&object->hashtable, key); +} + +int json_object_clear(json_t *json) +{ + json_object_t *object; + + if(!json_is_object(json)) + return -1; + + object = json_to_object(json); + hashtable_clear(&object->hashtable); + + return 0; +} + +int json_object_update(json_t *object, json_t *other) +{ + const char *key; + json_t *value; + + if(!json_is_object(object) || !json_is_object(other)) + return -1; + + json_object_foreach(other, key, value) { + if(json_object_set_nocheck(object, key, value)) + return -1; + } + + return 0; +} + +int json_object_update_existing(json_t *object, json_t *other) +{ + const char *key; + json_t *value; + + if(!json_is_object(object) || !json_is_object(other)) + return -1; + + json_object_foreach(other, key, value) { + if(json_object_get(object, key)) + json_object_set_nocheck(object, key, value); + } + + return 0; +} + +int json_object_update_missing(json_t *object, json_t *other) +{ + const char *key; + json_t *value; + + if(!json_is_object(object) || !json_is_object(other)) + return -1; + + json_object_foreach(other, key, value) { + if(!json_object_get(object, key)) + json_object_set_nocheck(object, key, value); + } + + return 0; +} + +void *json_object_iter(json_t *json) +{ + json_object_t *object; + + if(!json_is_object(json)) + return NULL; + + object = json_to_object(json); + return hashtable_iter(&object->hashtable); +} + +void *json_object_iter_at(json_t *json, const char *key) +{ + json_object_t *object; + + if(!key || !json_is_object(json)) + return NULL; + + object = json_to_object(json); + return hashtable_iter_at(&object->hashtable, key); +} + +void *json_object_iter_next(json_t *json, void *iter) +{ + json_object_t *object; + + if(!json_is_object(json) || iter == NULL) + return NULL; + + object = json_to_object(json); + return hashtable_iter_next(&object->hashtable, iter); +} + +const char *json_object_iter_key(void *iter) +{ + if(!iter) + return NULL; + + return hashtable_iter_key(iter); +} + +json_t *json_object_iter_value(void *iter) +{ + if(!iter) + return NULL; + + return (json_t *)hashtable_iter_value(iter); +} + +int json_object_iter_set_new(json_t *json, void *iter, json_t *value) +{ + if(!json_is_object(json) || !iter || !value) + { + json_decref(value); + return -1; + } + + hashtable_iter_set(iter, value); + return 0; +} + +void *json_object_key_to_iter(const char *key) +{ + if(!key) + return NULL; + + return hashtable_key_to_iter(key); +} + +static int json_object_equal(const json_t *object1, const json_t *object2) +{ + const char *key; + const json_t *value1, *value2; + + if(json_object_size(object1) != json_object_size(object2)) + return 0; + + json_object_foreach((json_t *)object1, key, value1) { + value2 = json_object_get(object2, key); + + if(!json_equal(value1, value2)) + return 0; + } + + return 1; +} + +static json_t *json_object_copy(json_t *object) +{ + json_t *result; + + const char *key; + json_t *value; + + result = json_object(); + if(!result) + return NULL; + + json_object_foreach(object, key, value) + json_object_set_nocheck(result, key, value); + + return result; +} + +static json_t *json_object_deep_copy(const json_t *object) +{ + json_t *result; + void *iter; + + result = json_object(); + if(!result) + return NULL; + + /* Cannot use json_object_foreach because object has to be cast + non-const */ + iter = json_object_iter((json_t *)object); + while(iter) { + const char *key; + const json_t *value; + key = json_object_iter_key(iter); + value = json_object_iter_value(iter); + + json_object_set_new_nocheck(result, key, json_deep_copy(value)); + iter = json_object_iter_next((json_t *)object, iter); + } + + return result; +} + + +/*** array ***/ + +json_t *json_array(void) +{ + json_array_t *array = jsonp_malloc(sizeof(json_array_t)); + if(!array) + return NULL; + json_init(&array->json, JSON_ARRAY); + + array->entries = 0; + array->size = 8; + + array->table = jsonp_malloc(array->size * sizeof(json_t *)); + if(!array->table) { + jsonp_free(array); + return NULL; + } + + return &array->json; +} + +static void json_delete_array(json_array_t *array) +{ + size_t i; + + for(i = 0; i < array->entries; i++) + json_decref(array->table[i]); + + jsonp_free(array->table); + jsonp_free(array); +} + +size_t json_array_size(const json_t *json) +{ + if(!json_is_array(json)) + return 0; + + return json_to_array(json)->entries; +} + +json_t *json_array_get(const json_t *json, size_t index) +{ + json_array_t *array; + if(!json_is_array(json)) + return NULL; + array = json_to_array(json); + + if(index >= array->entries) + return NULL; + + return array->table[index]; +} + +int json_array_set_new(json_t *json, size_t index, json_t *value) +{ + json_array_t *array; + + if(!value) + return -1; + + if(!json_is_array(json) || json == value) + { + json_decref(value); + return -1; + } + array = json_to_array(json); + + if(index >= array->entries) + { + json_decref(value); + return -1; + } + + json_decref(array->table[index]); + array->table[index] = value; + + return 0; +} + +static void array_move(json_array_t *array, size_t dest, + size_t src, size_t count) +{ + memmove(&array->table[dest], &array->table[src], count * sizeof(json_t *)); +} + +static void array_copy(json_t **dest, size_t dpos, + json_t **src, size_t spos, + size_t count) +{ + memcpy(&dest[dpos], &src[spos], count * sizeof(json_t *)); +} + +static json_t **json_array_grow(json_array_t *array, + size_t amount, + int copy) +{ + size_t new_size; + json_t **old_table, **new_table; + + if(array->entries + amount <= array->size) + return array->table; + + old_table = array->table; + + new_size = max(array->size + amount, array->size * 2); + new_table = jsonp_malloc(new_size * sizeof(json_t *)); + if(!new_table) + return NULL; + + array->size = new_size; + array->table = new_table; + + if(copy) { + array_copy(array->table, 0, old_table, 0, array->entries); + jsonp_free(old_table); + return array->table; + } + + return old_table; +} + +int json_array_append_new(json_t *json, json_t *value) +{ + json_array_t *array; + + if(!value) + return -1; + + if(!json_is_array(json) || json == value) + { + json_decref(value); + return -1; + } + array = json_to_array(json); + + if(!json_array_grow(array, 1, 1)) { + json_decref(value); + return -1; + } + + array->table[array->entries] = value; + array->entries++; + + return 0; +} + +int json_array_insert_new(json_t *json, size_t index, json_t *value) +{ + json_array_t *array; + json_t **old_table; + + if(!value) + return -1; + + if(!json_is_array(json) || json == value) { + json_decref(value); + return -1; + } + array = json_to_array(json); + + if(index > array->entries) { + json_decref(value); + return -1; + } + + old_table = json_array_grow(array, 1, 0); + if(!old_table) { + json_decref(value); + return -1; + } + + if(old_table != array->table) { + array_copy(array->table, 0, old_table, 0, index); + array_copy(array->table, index + 1, old_table, index, + array->entries - index); + jsonp_free(old_table); + } + else + array_move(array, index + 1, index, array->entries - index); + + array->table[index] = value; + array->entries++; + + return 0; +} + +int json_array_remove(json_t *json, size_t index) +{ + json_array_t *array; + + if(!json_is_array(json)) + return -1; + array = json_to_array(json); + + if(index >= array->entries) + return -1; + + json_decref(array->table[index]); + + /* If we're removing the last element, nothing has to be moved */ + if(index < array->entries - 1) + array_move(array, index, index + 1, array->entries - index - 1); + + array->entries--; + + return 0; +} + +int json_array_clear(json_t *json) +{ + json_array_t *array; + size_t i; + + if(!json_is_array(json)) + return -1; + array = json_to_array(json); + + for(i = 0; i < array->entries; i++) + json_decref(array->table[i]); + + array->entries = 0; + return 0; +} + +int json_array_extend(json_t *json, json_t *other_json) +{ + json_array_t *array, *other; + size_t i; + + if(!json_is_array(json) || !json_is_array(other_json)) + return -1; + array = json_to_array(json); + other = json_to_array(other_json); + + if(!json_array_grow(array, other->entries, 1)) + return -1; + + for(i = 0; i < other->entries; i++) + json_incref(other->table[i]); + + array_copy(array->table, array->entries, other->table, 0, other->entries); + + array->entries += other->entries; + return 0; +} + +static int json_array_equal(const json_t *array1, const json_t *array2) +{ + size_t i, size; + + size = json_array_size(array1); + if(size != json_array_size(array2)) + return 0; + + for(i = 0; i < size; i++) + { + json_t *value1, *value2; + + value1 = json_array_get(array1, i); + value2 = json_array_get(array2, i); + + if(!json_equal(value1, value2)) + return 0; + } + + return 1; +} + +static json_t *json_array_copy(json_t *array) +{ + json_t *result; + size_t i; + + result = json_array(); + if(!result) + return NULL; + + for(i = 0; i < json_array_size(array); i++) + json_array_append(result, json_array_get(array, i)); + + return result; +} + +static json_t *json_array_deep_copy(const json_t *array) +{ + json_t *result; + size_t i; + + result = json_array(); + if(!result) + return NULL; + + for(i = 0; i < json_array_size(array); i++) + json_array_append_new(result, json_deep_copy(json_array_get(array, i))); + + return result; +} + +/*** string ***/ + +static json_t *string_create(const char *value, size_t len, int own) +{ + char *v; + json_string_t *string; + + if(!value) + return NULL; + + if(own) + v = (char *)value; + else { + v = jsonp_strndup(value, len); + if(!v) + return NULL; + } + + string = jsonp_malloc(sizeof(json_string_t)); + if(!string) { + if(!own) + jsonp_free(v); + return NULL; + } + json_init(&string->json, JSON_STRING); + string->value = v; + string->length = len; + + return &string->json; +} + +json_t *json_string_nocheck(const char *value) +{ + if(!value) + return NULL; + + return string_create(value, strlen(value), 0); +} + +json_t *json_stringn_nocheck(const char *value, size_t len) +{ + return string_create(value, len, 0); +} + +/* this is private; "steal" is not a public API concept */ +json_t *jsonp_stringn_nocheck_own(const char *value, size_t len) +{ + return string_create(value, len, 1); +} + +json_t *json_string(const char *value) +{ + if(!value) + return NULL; + + return json_stringn(value, strlen(value)); +} + +json_t *json_stringn(const char *value, size_t len) +{ + if(!value || !utf8_check_string(value, len)) + return NULL; + + return json_stringn_nocheck(value, len); +} + +const char *json_string_value(const json_t *json) +{ + if(!json_is_string(json)) + return NULL; + + return json_to_string(json)->value; +} + +size_t json_string_length(const json_t *json) +{ + if(!json_is_string(json)) + return 0; + + return json_to_string(json)->length; +} + +int json_string_set_nocheck(json_t *json, const char *value) +{ + if(!value) + return -1; + + return json_string_setn_nocheck(json, value, strlen(value)); +} + +int json_string_setn_nocheck(json_t *json, const char *value, size_t len) +{ + char *dup; + json_string_t *string; + + if(!json_is_string(json) || !value) + return -1; + + dup = jsonp_strndup(value, len); + if(!dup) + return -1; + + string = json_to_string(json); + jsonp_free(string->value); + string->value = dup; + string->length = len; + + return 0; +} + +int json_string_set(json_t *json, const char *value) +{ + if(!value) + return -1; + + return json_string_setn(json, value, strlen(value)); +} + +int json_string_setn(json_t *json, const char *value, size_t len) +{ + if(!value || !utf8_check_string(value, len)) + return -1; + + return json_string_setn_nocheck(json, value, len); +} + +static void json_delete_string(json_string_t *string) +{ + jsonp_free(string->value); + jsonp_free(string); +} + +static int json_string_equal(const json_t *string1, const json_t *string2) +{ + json_string_t *s1, *s2; + + if(!json_is_string(string1) || !json_is_string(string2)) + return 0; + + s1 = json_to_string(string1); + s2 = json_to_string(string2); + return s1->length == s2->length && !memcmp(s1->value, s2->value, s1->length); +} + +static json_t *json_string_copy(const json_t *string) +{ + json_string_t *s; + + if(!json_is_string(string)) + return NULL; + + s = json_to_string(string); + return json_stringn_nocheck(s->value, s->length); +} + +json_t *json_vsprintf(const char *fmt, va_list ap) { + int length; + char *buf; + va_list aq; + va_copy(aq, ap); + + length = vsnprintf(NULL, 0, fmt, ap); + if (length == 0) + return json_string(""); + + buf = jsonp_malloc(length + 1); + if (!buf) + return NULL; + + vsnprintf(buf, length + 1, fmt, aq); + if (!utf8_check_string(buf, length)) { + jsonp_free(buf); + return NULL; + } + + return jsonp_stringn_nocheck_own(buf, length); +} + +json_t *json_sprintf(const char *fmt, ...) { + json_t *result; + va_list ap; + + va_start(ap, fmt); + result = json_vsprintf(fmt, ap); + va_end(ap); + + return result; +} + + +/*** integer ***/ + +json_t *json_integer(json_int_t value) +{ + json_integer_t *integer = jsonp_malloc(sizeof(json_integer_t)); + if(!integer) + return NULL; + json_init(&integer->json, JSON_INTEGER); + + integer->value = value; + return &integer->json; +} + +json_int_t json_integer_value(const json_t *json) +{ + if(!json_is_integer(json)) + return 0; + + return json_to_integer(json)->value; +} + +int json_integer_set(json_t *json, json_int_t value) +{ + if(!json_is_integer(json)) + return -1; + + json_to_integer(json)->value = value; + + return 0; +} + +static void json_delete_integer(json_integer_t *integer) +{ + jsonp_free(integer); +} + +static int json_integer_equal(const json_t *integer1, const json_t *integer2) +{ + return json_integer_value(integer1) == json_integer_value(integer2); +} + +static json_t *json_integer_copy(const json_t *integer) +{ + return json_integer(json_integer_value(integer)); +} + + +/*** real ***/ + +json_t *json_real(double value) +{ + json_real_t *real; + + if(isnan(value) || isinf(value)) + return NULL; + + real = jsonp_malloc(sizeof(json_real_t)); + if(!real) + return NULL; + json_init(&real->json, JSON_REAL); + + real->value = value; + return &real->json; +} + +double json_real_value(const json_t *json) +{ + if(!json_is_real(json)) + return 0; + + return json_to_real(json)->value; +} + +int json_real_set(json_t *json, double value) +{ + if(!json_is_real(json) || isnan(value) || isinf(value)) + return -1; + + json_to_real(json)->value = value; + + return 0; +} + +static void json_delete_real(json_real_t *real) +{ + jsonp_free(real); +} + +static int json_real_equal(const json_t *real1, const json_t *real2) +{ + return json_real_value(real1) == json_real_value(real2); +} + +static json_t *json_real_copy(const json_t *real) +{ + return json_real(json_real_value(real)); +} + + +/*** number ***/ + +double json_number_value(const json_t *json) +{ + if(json_is_integer(json)) + return (double)json_integer_value(json); + else if(json_is_real(json)) + return json_real_value(json); + else + return 0.0; +} + + +/*** simple values ***/ + +json_t *json_true(void) +{ + static json_t the_true = {JSON_TRUE, (size_t)-1}; + return &the_true; +} + + +json_t *json_false(void) +{ + static json_t the_false = {JSON_FALSE, (size_t)-1}; + return &the_false; +} + + +json_t *json_null(void) +{ + static json_t the_null = {JSON_NULL, (size_t)-1}; + return &the_null; +} + + +/*** deletion ***/ + +void json_delete(json_t *json) +{ + if (!json) + return; + + switch(json_typeof(json)) { + case JSON_OBJECT: + json_delete_object(json_to_object(json)); + break; + case JSON_ARRAY: + json_delete_array(json_to_array(json)); + break; + case JSON_STRING: + json_delete_string(json_to_string(json)); + break; + case JSON_INTEGER: + json_delete_integer(json_to_integer(json)); + break; + case JSON_REAL: + json_delete_real(json_to_real(json)); + break; + default: + return; + } + + /* json_delete is not called for true, false or null */ +} + + +/*** equality ***/ + +int json_equal(const json_t *json1, const json_t *json2) +{ + if(!json1 || !json2) + return 0; + + if(json_typeof(json1) != json_typeof(json2)) + return 0; + + /* this covers true, false and null as they are singletons */ + if(json1 == json2) + return 1; + + switch(json_typeof(json1)) { + case JSON_OBJECT: + return json_object_equal(json1, json2); + case JSON_ARRAY: + return json_array_equal(json1, json2); + case JSON_STRING: + return json_string_equal(json1, json2); + case JSON_INTEGER: + return json_integer_equal(json1, json2); + case JSON_REAL: + return json_real_equal(json1, json2); + default: + return 0; + } +} + + +/*** copying ***/ + +json_t *json_copy(json_t *json) +{ + if(!json) + return NULL; + + switch(json_typeof(json)) { + case JSON_OBJECT: + return json_object_copy(json); + case JSON_ARRAY: + return json_array_copy(json); + case JSON_STRING: + return json_string_copy(json); + case JSON_INTEGER: + return json_integer_copy(json); + case JSON_REAL: + return json_real_copy(json); + case JSON_TRUE: + case JSON_FALSE: + case JSON_NULL: + return json; + default: + return NULL; + } + + return NULL; +} + +json_t *json_deep_copy(const json_t *json) +{ + if(!json) + return NULL; + + switch(json_typeof(json)) { + case JSON_OBJECT: + return json_object_deep_copy(json); + case JSON_ARRAY: + return json_array_deep_copy(json); + /* for the rest of the types, deep copying doesn't differ from + shallow copying */ + case JSON_STRING: + return json_string_copy(json); + case JSON_INTEGER: + return json_integer_copy(json); + case JSON_REAL: + return json_real_copy(json); + case JSON_TRUE: + case JSON_FALSE: + case JSON_NULL: + return (json_t *)json; + default: + return NULL; + } + + return NULL; +} From 7820be1b8a2f1643c35447a97fc0291f9442b7fa Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Nov 2018 16:17:31 +0200 Subject: [PATCH 0148/1938] exchange apdu14a works with chaining --- client/cmdhf14a.c | 77 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 54 insertions(+), 23 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 7880bf38f..56eadc9cc 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -767,20 +767,20 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav return 0; } -int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { +int CmdExchangeAPDU(uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chaining) { uint16_t cmdc = 0; + + *chaining = false; if (activateField) { cmdc |= ISO14A_CONNECT; } - if (leaveSignalON) - cmdc |= ISO14A_NO_DISCONNECT; // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes // https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size // here length USB_CMD_DATA_SIZE=512 // timeout must be authomatically set by "get ATS" - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_APDU | cmdc, (datainlen & 0xFFFF), 0}}; + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, (datainlen & 0xFFFF), 0}}; memcpy(c.d.asBytes, datain, datainlen); SendCommand(&c); @@ -789,11 +789,12 @@ int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool lea if (activateField) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(NORMAL, "APDU ERROR: Proxmark connection timeout."); + PrintAndLogEx(ERR, "APDU: Proxmark connection timeout."); return 1; } if (resp.arg[0] != 1) { - PrintAndLogEx(NORMAL, "APDU ERROR: Proxmark error %d.", resp.arg[0]); + PrintAndLogEx(ERR, "APDU: Proxmark error %d.", resp.arg[0]); + DropField(); return 1; } } @@ -801,45 +802,75 @@ int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool lea if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { recv = resp.d.asBytes; int iLen = resp.arg[0]; + uint8_t res = resp.arg[1]; - *dataoutlen = iLen - 2; - if (*dataoutlen < 0) - *dataoutlen = 0; + int dlen = iLen - 2; + if (dlen < 0) + dlen = 0; + *dataoutlen += dlen; if (maxdataoutlen && *dataoutlen > maxdataoutlen) { - PrintAndLogEx(NORMAL, "APDU ERROR: Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); + PrintAndLogEx(ERR, "APDU: Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); return 2; } - memcpy(dataout, recv, *dataoutlen); - if(!iLen) { - PrintAndLogEx(NORMAL, "APDU ERROR: No APDU response."); + PrintAndLogEx(ERR, "APDU: No APDU response."); return 1; } + // check apdu length + if (iLen < 4 && iLen >= 0) { + PrintAndLogEx(ERR, "APDU: Small APDU response. Len=%d", iLen); + return 2; + } + // check block TODO if (iLen == -2) { - PrintAndLogEx(NORMAL, "APDU ERROR: Block type mismatch."); + PrintAndLogEx(ERR, "APDU: Block type mismatch."); return 2; } + + memcpy(dataout, recv, dlen); + + // chaining + if ((res & 0x10) != 0) { + *chaining = true; + } // CRC Check if (iLen == -1) { - PrintAndLogEx(NORMAL, "APDU ERROR: ISO 14443A CRC error."); + PrintAndLogEx(ERR, "APDU: ISO 14443A CRC error."); return 3; } - - // check apdu length - if (iLen < 4) { - PrintAndLogEx(NORMAL, "APDU ERROR: Small APDU response. Len=%d", iLen); - return 2; - } - } else { - PrintAndLogEx(NORMAL, "APDU ERROR: Reply timeout."); + PrintAndLogEx(ERR, "APDU: Reply timeout."); return 4; } + + return 0; +} + +int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { + *dataoutlen = 0; + bool chaining = false; + + int res = CmdExchangeAPDU(datain, datainlen, activateField, dataout, maxdataoutlen, dataoutlen, &chaining); + + while (chaining) { + // I-block with chaining + res = CmdExchangeAPDU(NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining); + + if (res) { + if (!leaveSignalON) + DropField(); + + return 100; + } + } + + if (!leaveSignalON) + DropField(); return 0; } From efa76c7be40299fe03ca6c1f05b5932f1564ab9d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Nov 2018 16:26:51 +0200 Subject: [PATCH 0149/1938] fix some strange behavior --- client/emv/emvcore.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index c5ffb0483..b7d7df923 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -228,8 +228,10 @@ int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool Includ if (sw) *sw = 0; uint16_t isw = 0; - if (ActivateField) + if (ActivateField) { DropField(); + msleep(50); + } // COMPUTE APDU memcpy(data, &apdu, 5); From 5dda51ed1ca020a1a5392d461c8676665ae07ce6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Nov 2018 19:03:58 +0200 Subject: [PATCH 0150/1938] added FillBuffer function for fill buffers in hash checks --- client/util.c | 30 ++++++++++++++++++++++++++++++ client/util.h | 3 +++ 2 files changed, 33 insertions(+) diff --git a/client/util.c b/client/util.c index 3e6c7cdc6..5ae4ab862 100644 --- a/client/util.c +++ b/client/util.c @@ -23,6 +23,7 @@ uint8_t g_debugMode = 0; #include #include #include +#include int ukbhit(void) { int cnt = 0; @@ -120,6 +121,35 @@ void FillFileNameByUID(char *filenamePrefix, uint8_t *uid, const char *ext, int strcat(filenamePrefix, ext); } +// fill buffer from structure [{uint8_t data, size_t length},...] +int FillBuffer(uint8_t *data, size_t maxDataLength, size_t *dataLength, ...) { + *dataLength = 0; + va_list valist; + va_start(valist, dataLength); + + uint8_t *vdata = NULL; + size_t vlength = 0; + do{ + vdata = va_arg(valist, uint8_t *); + if (!vdata) + break; + + vlength = va_arg(valist, size_t); + if (*dataLength + vlength > maxDataLength) { + va_end(valist); + return 1; + } + + memcpy(&data[*dataLength], vdata, vlength); + *dataLength += vlength; + + } while (vdata); + + va_end(valist); + + return 0; +} + void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, const size_t hex_max_len, const size_t min_str_len, const size_t spaces_between, bool uppercase) { diff --git a/client/util.h b/client/util.h index 637bfb3ca..a069b5012 100644 --- a/client/util.h +++ b/client/util.h @@ -187,6 +187,9 @@ extern void AddLogUint64(char *fileName, char *extData, const uint64_t data); extern void AddLogCurrentDT(char *fileName); extern void FillFileNameByUID(char *filenamePrefix, uint8_t * uid, const char *ext, int uidlen); +// fill buffer from structure [{uint8_t data, size_t length},...] +extern int FillBuffer(uint8_t *data, size_t maxDataLength, size_t *dataLength, ...); + extern void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, const size_t hex_max_len, const size_t min_str_len, const size_t spaces_between, bool uppercase); From 7043435174c99794778e3bfd5c9175174f4b2ecf Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 12 Nov 2018 19:05:05 +0200 Subject: [PATCH 0151/1938] added x9.62 signature decode and ecdsa signature verify --- client/cmdhffido.c | 40 +++++++++++++++++++++++++++++++++++++++- 1 file changed, 39 insertions(+), 1 deletion(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index fd97ace54..ab9afbdca 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -39,6 +39,8 @@ #include "emv/emvjson.h" #include "emv/dump.h" #include "cliparser/cliparser.h" +#include "crypto/asn1utils.h" +#include "crypto/libpcrypto.h" static int CmdHelp(const char *Cmd); @@ -328,11 +330,47 @@ int CmdHFFidoRegister(const char *cmd) { PrintAndLog("DER certificate[%d]: %s...", derLen, sprint_hex(&buf[derp], 20)); } + // check and print DER certificate + uint8_t public_key[65] = {0}; + // get hash int hashp = 1 + 65 + 1 + keyHandleLen + derLen; PrintAndLog("Hash[%d]: %s", len - hashp, sprint_hex(&buf[hashp], len - hashp)); - + // check ANSI X9.62 format ECDSA signature (on P-256) + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; + res = ecdsa_asn1_get_signature(&buf[hashp], len - hashp, rval, sval); + if (!res) { + if (verbose) { + PrintAndLog(" r: %s", sprint_hex(rval, 32)); + PrintAndLog(" s: %s", sprint_hex(sval, 32)); + } + + uint8_t xbuf[4096] = {0}; + size_t xbuflen = 0; + res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, + "\x00", 1, + adata, 32, + cdata, 32, + &buf[67], keyHandleLen, // keyHandle + &buf[1], 65, // user public key + NULL, 0); + //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); + res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[hashp], len - hashp); + if (res) { + if (res == -0x4e00) { + PrintAndLog("Signature is NOT VALID."); + } else { + PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); + } + } else { + PrintAndLog("Signature is OK."); + } + + } else { + PrintAndLog("Invalid signature. res=%d.", res); + } PrintAndLog("\nauth command: "); printf("hf fido auth %s%s", paramsPlain?"-p ":"", sprint_hex_inrow(&buf[67], keyHandleLen)); From 6a21df344376145feb29a62b8436c6b1e6cf48a2 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 12 Nov 2018 22:17:49 +0100 Subject: [PATCH 0152/1938] FIX: 'hf mf cload' - showing helptext instead of loading file. Added support for easy loading of bin/eml files in this patch aswell. --- client/cmdhfmf.c | 442 +++++++++++++++++-------------------- client/loclass/fileutils.c | 138 ++++++++++-- client/loclass/fileutils.h | 66 ++++-- 3 files changed, 377 insertions(+), 269 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 7cdd44af1..03875401c 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -394,7 +394,6 @@ int GetHFMF14AUID(uint8_t *uid, int *uidlen) { SendCommand(&c); UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - //if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); DropField(); return 0; @@ -419,8 +418,7 @@ char * GenerateFilename(const char *prefix, const char *suffix){ } strcpy(fptr, prefix); - FillFileNameByUID(fptr,uid,suffix,uidlen); - + FillFileNameByUID(fptr, uid, suffix, uidlen); return fptr; } @@ -428,13 +426,13 @@ int CmdHF14ADarkside(const char *Cmd) { uint8_t blockno = 0, key_type = MIFARE_AUTH_KEYA; uint64_t key = 0; - char cmdp = param_getchar(Cmd, 0); - if ( cmdp == 'H' || cmdp == 'h') return usage_hf14_mifare(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if ( cmdp == 'h' ) return usage_hf14_mifare(); blockno = param_get8(Cmd, 0); - cmdp = param_getchar(Cmd, 1); - if (cmdp == 'B' || cmdp == 'b') + cmdp = tolower(param_getchar(Cmd, 1)); + if (cmdp == 'b') key_type = MIFARE_AUTH_KEYB; int isOK = mfDarkside(blockno, key_type, &key); @@ -457,10 +455,9 @@ int CmdHF14AMfWrBl(const char *Cmd) { uint8_t keyType = 0; uint8_t key[6] = {0, 0, 0, 0, 0, 0}; uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - char cmdp = 0x00; - if (strlen(Cmd)<3) { + if (strlen(Cmd) < 3) { PrintAndLogEx(NORMAL, "Usage: hf mf wrbl "); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F"); @@ -468,20 +465,25 @@ int CmdHF14AMfWrBl(const char *Cmd) { } blockNo = param_get8(Cmd, 0); - cmdp = param_getchar(Cmd, 1); + cmdp = tolower(param_getchar(Cmd, 1)); if (cmdp == 0x00) { PrintAndLogEx(NORMAL, "Key type must be A or B"); return 1; } - if (cmdp != 'A' && cmdp != 'a') keyType = 1; + + if (cmdp != 'a') + keyType = 1; + if (param_gethex(Cmd, 2, key, 12)) { PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); return 1; } + if (param_gethex(Cmd, 3, bldata, 32)) { PrintAndLogEx(NORMAL, "Block data must include 32 HEX symbols"); return 1; } + PrintAndLogEx(NORMAL, "--block no:%d, key type:%c, key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6)); PrintAndLogEx(NORMAL, "--data: %s", sprint_hex(bldata, 16)); @@ -516,12 +518,15 @@ int CmdHF14AMfRdBl(const char *Cmd) { } blockNo = param_get8(Cmd, 0); - cmdp = param_getchar(Cmd, 1); + cmdp = tolower(param_getchar(Cmd, 1)); if (cmdp == 0x00) { PrintAndLogEx(NORMAL, "Key type must be A or B"); return 1; } - if (cmdp != 'A' && cmdp != 'a') keyType = 1; + + if (cmdp != 'a') + keyType = 1; + if (param_gethex(Cmd, 2, key, 12)) { PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); return 1; @@ -558,7 +563,7 @@ int CmdHF14AMfRdSc(const char *Cmd) { uint8_t *data = NULL; char cmdp = 0x00; - if (strlen(Cmd)<3) { + if (strlen(Cmd) < 3) { PrintAndLogEx(NORMAL, "Usage: hf mf rdsc "); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf rdsc 0 A FFFFFFFFFFFF "); @@ -570,12 +575,16 @@ int CmdHF14AMfRdSc(const char *Cmd) { PrintAndLogEx(NORMAL, "Sector number must be less than 40"); return 1; } - cmdp = param_getchar(Cmd, 1); - if (cmdp != 'a' && cmdp != 'A' && cmdp != 'b' && cmdp != 'B') { + + cmdp = tolower(param_getchar(Cmd, 1)); + if (cmdp != 'a' && cmdp != 'b') { PrintAndLogEx(NORMAL, "Key type must be A or B"); return 1; } - if (cmdp != 'A' && cmdp != 'a') keyType = 1; + + if (cmdp != 'a') + keyType = 1; + if (param_gethex(Cmd, 2, key, 12)) { PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); return 1; @@ -682,15 +691,15 @@ int CmdHF14AMfDump(const char *Cmd) { } } - if (keyFilename[0] == 0x00) - { - fptr = GenerateFilename("hf-mf-","-key.bin"); + if ( keyFilename[0] == 0x00 ) { + fptr = GenerateFilename("hf-mf-", "-key.bin"); if (fptr == NULL) return 1; + strcpy(keyFilename, fptr); } - if ((fin = fopen(keyFilename,"rb")) == NULL) { + if ((fin = fopen(keyFilename, "rb")) == NULL) { PrintAndLogEx(WARNING, "Could not find file %s", keyFilename); return 1; } @@ -828,9 +837,10 @@ int CmdHF14AMfDump(const char *Cmd) { if (isOK) { if (dataFilename[0] == 0x00) { - fptr=GenerateFilename("hf-mf-","-data.bin"); + fptr = GenerateFilename("hf-mf-", "-data.bin"); if (fptr == NULL) return 1; + strcpy(dataFilename, fptr); } @@ -862,12 +872,10 @@ int CmdHF14AMfRestore(const char *Cmd) { FILE *fdump, *fkeys; while(param_getchar(Cmd, cmdp) != 0x00) { - switch(param_getchar(Cmd, cmdp)) { + switch(tolower(param_getchar(Cmd, cmdp))) { case 'h': - case 'H': return usage_hf14_restore(); case 'u': - case 'U': param_getstr(Cmd, cmdp+1, szTemp, FILE_PATH_SIZE); if(keyFilename[0]==0x00) snprintf(keyFilename, FILE_PATH_SIZE, "hf-mf-%s-key.bin", szTemp); @@ -876,38 +884,33 @@ int CmdHF14AMfRestore(const char *Cmd) { cmdp+=2; break; case 'k': - case 'K': param_getstr(Cmd, cmdp+1, keyFilename, FILE_PATH_SIZE); cmdp += 2; break; case 'f': - case 'F': param_getstr(Cmd, cmdp+1, dataFilename, FILE_PATH_SIZE); cmdp += 2; break; default: - if (cmdp==0) - { + if ( cmdp == 0 ) { numSectors = NumOfSectors(param_getchar(Cmd, cmdp)); cmdp++; - } - else - { + } else { PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); return usage_hf14_restore(); } } } - if(keyFilename[0]==0x00) - { - fptr=GenerateFilename("hf-mf-","-key.bin"); + if ( keyFilename[0] == 0x00 ) { + fptr = GenerateFilename("hf-mf-", "-key.bin"); if (fptr == NULL) return 1; - strcpy(keyFilename,fptr); + + strcpy(keyFilename, fptr); } - if ((fkeys = fopen(keyFilename,"rb")) == NULL) { + if ((fkeys = fopen(keyFilename, "rb")) == NULL) { PrintAndLogEx(WARNING, "Could not find file %s", keyFilename); return 1; } @@ -915,7 +918,7 @@ int CmdHF14AMfRestore(const char *Cmd) { size_t bytes_read; for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { bytes_read = fread( keyA[sectorNo], 1, 6, fkeys ); - if ( bytes_read != 6) { + if ( bytes_read != 6 ) { PrintAndLogEx(NORMAL, "File reading error (%s).", keyFilename); fclose(fkeys); return 2; @@ -924,7 +927,7 @@ int CmdHF14AMfRestore(const char *Cmd) { for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { bytes_read = fread( keyB[sectorNo], 1, 6, fkeys ); - if ( bytes_read != 6) { + if ( bytes_read != 6 ) { PrintAndLogEx(NORMAL, "File reading error (%s).", keyFilename); fclose(fkeys); return 2; @@ -933,22 +936,22 @@ int CmdHF14AMfRestore(const char *Cmd) { fclose(fkeys); - if( dataFilename[0]==0x00) - { - fptr=GenerateFilename("hf-mf-","-data.bin"); + if ( dataFilename[0] == 0x00 ) { + fptr = GenerateFilename("hf-mf-", "-data.bin"); if (fptr == NULL) return 1; + strcpy(dataFilename,fptr); } - if ((fdump = fopen(dataFilename,"rb")) == NULL) { + if ((fdump = fopen(dataFilename, "rb")) == NULL) { PrintAndLogEx(WARNING, "Could not find file %s", dataFilename); return 1; } PrintAndLogEx(NORMAL, "Restoring %s to card", dataFilename); for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { - for(blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) { + for (blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) { UsbCommand c = {CMD_MIFARE_WRITEBL, {FirstBlockOfSector(sectorNo) + blockNo, keyType, 0}}; memcpy(c.d.asBytes, key, 6); bytes_read = fread(bldata, 1, 16, fdump); @@ -1011,19 +1014,20 @@ int CmdHF14AMfNested(const char *Cmd) { uint8_t standart[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; uint8_t tempkey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; char *fptr; - if (strlen(Cmd)<3) return usage_hf14_nested(); + + if (strlen(Cmd) < 3) return usage_hf14_nested(); char cmdp, ctmp; - cmdp = param_getchar(Cmd, 0); + cmdp = tolower(param_getchar(Cmd, 0)); blockNo = param_get8(Cmd, 1); - ctmp = param_getchar(Cmd, 2); + ctmp = tolower(param_getchar(Cmd, 2)); - if (ctmp != 'a' && ctmp != 'A' && ctmp != 'b' && ctmp != 'B') { + if (ctmp != 'a' && ctmp != 'b') { PrintAndLogEx(WARNING, "key type must be A or B"); return 1; } - if (ctmp != 'A' && ctmp != 'a') + if (ctmp != 'a') keyType = 1; if (param_gethex(Cmd, 3, key, 12)) { @@ -1031,27 +1035,27 @@ int CmdHF14AMfNested(const char *Cmd) { return 1; } - if (cmdp == 'o' || cmdp == 'O') { - cmdp = 'o'; + if (cmdp == 'o') { trgBlockNo = param_get8(Cmd, 4); - ctmp = param_getchar(Cmd, 5); - if (ctmp != 'a' && ctmp != 'A' && ctmp != 'b' && ctmp != 'B') { + ctmp = tolower(param_getchar(Cmd, 5)); + if (ctmp != 'a' && ctmp != 'b') { PrintAndLogEx(WARNING, "target key type must be A or B"); return 1; } - if (ctmp != 'A' && ctmp != 'a') + if (ctmp != 'a') { trgKeyType = 1; + } } else { SectorsCnt = NumOfSectors(cmdp); } - ctmp = param_getchar(Cmd, 4); - transferToEml |= (ctmp == 't' || ctmp == 'T'); - createDumpFile |= (ctmp == 'd' || ctmp == 'D'); + ctmp = tolower(param_getchar(Cmd, 4)); + transferToEml |= (ctmp == 't'); + createDumpFile |= (ctmp == 'd'); - ctmp = param_getchar(Cmd, 6); - transferToEml |= (ctmp == 't' || ctmp == 'T'); - createDumpFile |= (ctmp == 'd' || ctmp == 'D'); + ctmp = tolower(param_getchar(Cmd, 6)); + transferToEml |= (ctmp == 't'); + createDumpFile |= (ctmp == 'd'); // check if we can authenticate to sector res = mfCheckKeys(blockNo, keyType, true, 1, key, &key64); @@ -1203,7 +1207,7 @@ int CmdHF14AMfNested(const char *Cmd) { // Create dump file if (createDumpFile) { - fptr = GenerateFilename("hf-mf-","-key.bin"); + fptr = GenerateFilename("hf-mf-", "-key.bin"); if (fptr == NULL) return 1; @@ -1286,12 +1290,13 @@ int CmdHF14AMfNestedHard(const char *Cmd) { } blockNo = param_get8(Cmd, cmdp); - ctmp = param_getchar(Cmd, cmdp+1); - if (ctmp != 'a' && ctmp != 'A' && ctmp != 'b' && ctmp != 'B') { + ctmp = tolower(param_getchar(Cmd, cmdp+1)); + if (ctmp != 'a' && ctmp != 'b') { PrintAndLogEx(NORMAL, "Key type must be A or B"); return 1; } - if (ctmp != 'A' && ctmp != 'a') { + + if (ctmp != 'a') { keyType = 1; } @@ -1300,20 +1305,20 @@ int CmdHF14AMfNestedHard(const char *Cmd) { return 1; } - if(param_getchar(Cmd, cmdp+3) == 0x00) + if (param_getchar(Cmd, cmdp+3) == 0x00) { PrintAndLogEx(NORMAL, "Target block number is missing"); return 1; - } + trgBlockNo = param_get8(Cmd, cmdp+3); - ctmp = param_getchar(Cmd, cmdp+4); - if (ctmp != 'a' && ctmp != 'A' && ctmp != 'b' && ctmp != 'B') { + ctmp = tolower(param_getchar(Cmd, cmdp+4)); + if (ctmp != 'a' && ctmp != 'b') { PrintAndLogEx(NORMAL, "Target key type must be A or B"); return 1; } - if (ctmp != 'A' && ctmp != 'a') { + if (ctmp != 'a') { trgKeyType = 1; } cmdp += 5; @@ -1615,11 +1620,11 @@ out: } if (createDumpFile) { - fptr = GenerateFilename("hf-mf-","-key.bin"); + fptr = GenerateFilename("hf-mf-", "-key.bin"); if (fptr == NULL) return 1; - FILE *fkeys = fopen(fptr,"wb"); + FILE *fkeys = fopen(fptr, "wb"); if (fkeys == NULL) { PrintAndLogEx(WARNING, "Could not create file %s", fptr); free(keyBlock); @@ -1902,11 +1907,11 @@ out: } if (createDumpFile) { - fptr = GenerateFilename("hf-mf-","-key.bin"); + fptr = GenerateFilename("hf-mf-", "-key.bin"); if (fptr == NULL) return 1; - FILE *fkeys = fopen(fptr,"wb"); + FILE *fkeys = fopen(fptr, "wb"); if (fkeys == NULL) { PrintAndLogEx(WARNING, "Could not create file %s", fptr); free(keyBlock); @@ -1951,6 +1956,7 @@ static void emptySectorTable(){ k_sector[i].foundKey[1] = false; } } + void showSectorTable(){ if (k_sector != NULL) { printKeyTable(k_sectorsCount, k_sector); @@ -1958,6 +1964,7 @@ void showSectorTable(){ k_sector = NULL; } } + void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose) { uint64_t key = 0; @@ -2002,33 +2009,26 @@ int CmdHF14AMf1kSim(const char *Cmd) { uint8_t flags = (FLAG_UID_IN_EMUL | FLAG_4B_UID_IN_DATA); int uidlen = 0; uint8_t cmdp = 0; - bool errors = false; - bool verbose = false; - bool setEmulatorMem = false; + bool errors = false, verbose = false, setEmulatorMem = false; nonces_t data[1]; while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + switch( tolower(param_getchar(Cmd, cmdp))) { case 'e': - case 'E': setEmulatorMem = true; cmdp++; break; case 'h': - case 'H': return usage_hf14_mf1ksim(); case 'i': - case 'I': flags |= FLAG_INTERACTIVE; cmdp++; break; case 'n': - case 'N': exitAfterNReads = param_get8(Cmd, cmdp+1); cmdp += 2; break; case 'u': - case 'U': param_gethex_ex(Cmd, cmdp+1, uid, &uidlen); switch(uidlen) { case 20: flags = FLAG_10B_UID_IN_DATA; break; @@ -2039,12 +2039,10 @@ int CmdHF14AMf1kSim(const char *Cmd) { cmdp += 2; break; case 'v': - case 'V': verbose = true; cmdp++; break; case 'x': - case 'X': flags |= FLAG_NR_AR_ATTACK; cmdp++; break; @@ -2110,11 +2108,11 @@ int CmdHF14AMfSniff(const char *Cmd){ if ( ctmp == 'h' || ctmp == 'H' ) return usage_hf14_sniff(); for (int i = 0; i < 4; i++) { - ctmp = param_getchar(Cmd, i); - if (ctmp == 'l' || ctmp == 'L') wantLogToFile = true; - if (ctmp == 'd' || ctmp == 'D') wantDecrypt = true; - //if (ctmp == 'e' || ctmp == 'E') wantSaveToEml = true; TODO - if (ctmp == 'f' || ctmp == 'F') wantSaveToEmlFile = true; + ctmp = tolower(param_getchar(Cmd, i)); + if (ctmp == 'l') wantLogToFile = true; + if (ctmp == 'd') wantDecrypt = true; + //if (ctmp == 'e') wantSaveToEml = true; TODO + if (ctmp == 'f') wantSaveToEmlFile = true; } PrintAndLogEx(NORMAL, "-------------------------------------------------------------------------\n"); @@ -2244,8 +2242,8 @@ int CmdHF14AMfSniff(const char *Cmd){ int CmdHF14AMfDbg(const char *Cmd) { - char ctmp = param_getchar(Cmd, 0); - if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_hf14_dbg(); + char ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || ctmp == 'h' ) return usage_hf14_dbg(); uint8_t dbgMode = param_get8ex(Cmd, 0, 0, 10); if (dbgMode > 4) return usage_hf14_dbg(); @@ -2261,15 +2259,15 @@ int CmdHF14AMfKeyBrute(const char *Cmd) { uint8_t key[6] = {0, 0, 0, 0, 0, 0}; uint64_t foundkey = 0; - char cmdp = param_getchar(Cmd, 0); - if ( cmdp == 'H' || cmdp == 'h') return usage_hf14_keybrute(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if ( cmdp == 'h' ) return usage_hf14_keybrute(); // block number blockNo = param_get8(Cmd, 0); // keytype - cmdp = param_getchar(Cmd, 1); - if (cmdp == 'B' || cmdp == 'b') keytype = 1; + cmdp = tolower(param_getchar(Cmd, 1)); + if ( cmdp == 'b' ) keytype = 1; // key if (param_gethex(Cmd, 2, key, 12)) return usage_hf14_keybrute(); @@ -2317,15 +2315,15 @@ void printKeyTable( uint8_t sectorscnt, sector_t *e_sector ){ int CmdHF14AMfEGet(const char *Cmd) { uint8_t blockNo = 0; uint8_t data[16] = {0x00}; - char c = param_getchar(Cmd, 0); + char c = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || c == 'h' || c == 'H') return usage_hf14_eget(); + if (strlen(Cmd) < 1 || c == 'h') return usage_hf14_eget(); blockNo = param_get8(Cmd, 0); PrintAndLogEx(NORMAL, ""); if (!mfEmlGetMem(data, blockNo, 1)) { - PrintAndLogEx(NORMAL, "data[%3d]:%s", blockNo, sprint_hex(data, 16)); + PrintAndLogEx(NORMAL, "data[%3d]:%s", blockNo, sprint_hex(data, sizeof(data))); } else { PrintAndLogEx(WARNING, "Command execute timeout"); } @@ -2333,8 +2331,8 @@ int CmdHF14AMfEGet(const char *Cmd) { } int CmdHF14AMfEClear(const char *Cmd) { - char c = param_getchar(Cmd, 0); - if (c == 'h' || c == 'H') return usage_hf14_eclr(); + char c = tolower(param_getchar(Cmd, 0)); + if (c == 'h') return usage_hf14_eclr(); UsbCommand cmd = {CMD_MIFARE_EML_MEMCLR, {0, 0, 0}}; clearCommandBuffer(); @@ -2343,12 +2341,12 @@ int CmdHF14AMfEClear(const char *Cmd) { } int CmdHF14AMfESet(const char *Cmd) { - char c = param_getchar(Cmd, 0); + char c = tolower(param_getchar(Cmd, 0)); uint8_t memBlock[16]; uint8_t blockNo = 0; memset(memBlock, 0x00, sizeof(memBlock)); - if (strlen(Cmd) < 3 || c == 'h' || c == 'H') + if (strlen(Cmd) < 3 || c == 'h') return usage_hf14_eset(); blockNo = param_get8(Cmd, 0); @@ -2363,91 +2361,70 @@ int CmdHF14AMfESet(const char *Cmd) { } int CmdHF14AMfELoad(const char *Cmd) { - FILE * f; - char filename[FILE_PATH_SIZE]; - char *fnameptr = filename; - char buf[64] = {0x00}; - uint8_t buf8[64] = {0x00}; - int i, len, blockNum, numBlocks; - int nameParamNo = 1; - uint8_t blockWidth = 32; - uint32_t tmp; - char c = param_getchar(Cmd, 0); - - if ( c == 'h' || c == 'H' || c == 0x00) - return usage_hf14_eload(); + size_t counter = 0; + char filename[FILE_PATH_SIZE]; + int blockNum, numBlocks, nameParamNo = 1; + uint8_t blockWidth = 16; + char c = tolower(param_getchar(Cmd, 0)); + + if ( strlen(Cmd) < 2 && c == 'h' ) + return usage_hf14_eload(); + switch (c) { case '0' : numBlocks = 5*4; break; case '1' : 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; + case 'u' : numBlocks = 255; blockWidth = 4; break; default: { numBlocks = 16*4; nameParamNo = 0; } } - uint32_t numblk2 = param_get32ex(Cmd,2,0,10); - if (numblk2 > 0) numBlocks = numblk2; + uint32_t numblk2 = param_get32ex(Cmd, 2, 0, 10); + if (numblk2 > 0) + numBlocks = numblk2; - len = param_getstr(Cmd, nameParamNo, filename, sizeof(filename)); + param_getstr(Cmd, nameParamNo, filename, sizeof(filename)); - if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; - - fnameptr += len; - - sprintf(fnameptr, ".eml"); - - // open file - f = fopen(filename, "r"); - if (f == NULL) { - PrintAndLogEx(WARNING, "File %s not found or locked", filename); + uint8_t *data = calloc(1, 4096); + size_t datalen = 0; + //int res = loadFile(filename, "bin", data, &datalen); + int res = loadFileEML( filename, "eml", data, &datalen); + if ( res ) { + free(data); return 1; } + // 64 or 256 blocks. + if ( (datalen % blockWidth) != 0 ) { + PrintAndLogEx(FAILED, "File content error. Size doesn't match blockwidth "); + free(data); + return 2; + } + + PrintAndLogEx(INFO, "Copying to emulator memory"); + blockNum = 0; - while (!feof(f)){ - memset(buf, 0, sizeof(buf)); + while ( datalen ) { - if (fgets(buf, sizeof(buf), f) == NULL) { - - if (blockNum >= numBlocks) break; - - PrintAndLogEx(WARNING, "File reading error."); - fclose(f); - return 2; - } - - if (strlen(buf) < blockWidth){ - if(strlen(buf) && feof(f)) - break; - PrintAndLogEx(WARNING, "File content error. Block data must include %d HEX symbols", blockWidth); - fclose(f); - return 2; - } - - for (i = 0; i < blockWidth; i += 2) { - sscanf(&buf[i], "%02x", &tmp); - buf8[i / 2] = tmp & 0xFF; - } - if (mfEmlSetMem_xt(buf8, blockNum, 1, blockWidth/2)) { - PrintAndLogEx(WARNING, "Cant set emul block: %3d", blockNum); - fclose(f); + if (mfEmlSetMem_xt(data + counter, blockNum, 1, blockWidth)) { + PrintAndLogEx(FAILED, "Cant set emul block: %3d", blockNum); + free(data); return 3; } printf("."); fflush(stdout); - blockNum++; - if (blockNum >= numBlocks) break; + blockNum++; + counter += blockWidth; + datalen -= blockWidth; } - fclose(f); PrintAndLogEx(NORMAL, "\n"); // Ultralight /Ntag - if ( blockWidth == 8 ) { + if ( blockWidth == 4 ) { if ((blockNum != numBlocks)) { PrintAndLogEx(FAILED, "Warning, Ultralight/Ntag file content, Loaded %d blocks into emulator memory", blockNum); return 0; @@ -2479,7 +2456,7 @@ int CmdHF14AMfESave(const char *Cmd) { blocks = NumOfBlocks(c); bytes = blocks * MFBLOCK_SIZE; - dump = malloc(bytes); + dump = calloc(sizeof(uint8_t), bytes); if (!dump) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return 1; @@ -2511,21 +2488,22 @@ int CmdHF14AMfESave(const char *Cmd) { int CmdHF14AMfECFill(const char *Cmd) { uint8_t keyType = 0; uint8_t numSectors = 16; - char c = param_getchar(Cmd, 0); + char c = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || c == 'h' || c == 'H') + if (strlen(Cmd) < 1 || c == 'h') return usage_hf14_ecfill(); - if (c != 'a' && c != 'A' && c != 'b' && c != 'B') { + if (c != 'a' && c != 'b') { PrintAndLogEx(WARNING, "Key type must be A or B"); return 1; } - if (c != 'A' && c != 'a') keyType = 1; + if (c != 'a') + keyType = 1; - c = param_getchar(Cmd, 1); + c = tolower(param_getchar(Cmd, 1)); numSectors = NumOfSectors(c); - PrintAndLogEx(NORMAL, "--params: numSectors: %d, keyType: %c\n", numSectors, (keyType==0) ? 'A' : 'B'); + PrintAndLogEx(NORMAL, "--params: numSectors: %d, keyType: %c\n", numSectors, (keyType == 0) ? 'A' : 'B'); UsbCommand cmd = {CMD_MIFARE_EML_CARDLOAD, {numSectors, keyType, 0}}; clearCommandBuffer(); SendCommand(&cmd); @@ -2538,9 +2516,8 @@ int CmdHF14AMfEKeyPrn(const char *Cmd) { uint8_t data[16]; uint64_t keyA, keyB; - char c = param_getchar(Cmd, 0); - - if ( c == 'h' || c == 'H' ) + char c = tolower(param_getchar(Cmd, 0)); + if ( c == 'h' ) return usage_hf14_ekeyprn(); numSectors = NumOfSectors(c); @@ -2569,9 +2546,8 @@ int CmdHF14AMfCSetUID(const char *Cmd) { uint8_t atqa[2] = {0x00}; uint8_t sak[1] = {0x00}; uint8_t atqaPresent = 1; - int res; + int res, argi = 0; char ctmp; - int argi=0; if (strlen(Cmd) < 1 || param_getchar(Cmd, argi) == 'h') return usage_hf14_csetuid(); @@ -2581,8 +2557,8 @@ int CmdHF14AMfCSetUID(const char *Cmd) { argi++; - ctmp = param_getchar(Cmd, argi); - if (ctmp == 'w' || ctmp == 'W') { + ctmp = tolower(param_getchar(Cmd, argi)); + if (ctmp == 'w') { wipeCard = 1; atqaPresent = 0; } @@ -2603,9 +2579,9 @@ int CmdHF14AMfCSetUID(const char *Cmd) { atqaPresent = 0; } - if(!wipeCard) { - ctmp = param_getchar(Cmd, argi); - if (ctmp == 'w' || ctmp == 'W') { + if (!wipeCard) { + ctmp = tolower(param_getchar(Cmd, argi)); + if (ctmp == 'w') { wipeCard = 1; } } @@ -2628,16 +2604,16 @@ int CmdHF14AMfCSetBlk(const char *Cmd) { uint8_t blockNo = 0; uint8_t params = MAGIC_SINGLE; int res; - char ctmp = param_getchar(Cmd, 0); + char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_hf14_csetblk(); + if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_csetblk(); blockNo = param_get8(Cmd, 0); if (param_gethex(Cmd, 1, block, 32)) return usage_hf14_csetblk(); - ctmp = param_getchar(Cmd, 2); - if (ctmp == 'w' || ctmp == 'W') + ctmp = tolower(param_getchar(Cmd, 2)); + if (ctmp == 'w') params |= MAGIC_WIPE; PrintAndLogEx(NORMAL, "--block number:%2d data:%s", blockNo, sprint_hex(block, 16)); @@ -2651,21 +2627,16 @@ int CmdHF14AMfCSetBlk(const char *Cmd) { } int CmdHF14AMfCLoad(const char *Cmd) { - FILE * f; - char filename[FILE_PATH_SIZE]; - char * fnameptr = filename; - char buf[35] = {0x00}; // 32+newline chars+1 null terminator + uint8_t buf8[16] = {0x00}; uint8_t fillFromEmulator = 0; - uint32_t tmp; - int i, len, blockNum, flags=0; - - memset(filename, 0, sizeof(filename)); + int blockNum, flags = 0; - char ctmp = param_getchar(Cmd, 0); - - if (ctmp == 'h' || ctmp == 'H' || ctmp == 0x00) return usage_hf14_cload(); - if (ctmp == 'e' || ctmp == 'E') fillFromEmulator = 1; + char ctmp = tolower(param_getchar(Cmd, 0)); + if ( strlen(Cmd) == 1 ) { + if (ctmp == 'h' || ctmp == 0x00) return usage_hf14_cload(); + if (ctmp == 'e' ) fillFromEmulator = 1; + } if (fillFromEmulator) { for (blockNum = 0; blockNum < 16 * 4; blockNum += 1) { @@ -2685,69 +2656,66 @@ int CmdHF14AMfCLoad(const char *Cmd) { } PrintAndLogEx(NORMAL, "\n"); return 0; - } - - len = strlen(Cmd); - if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; + } - memcpy(filename, Cmd, len); - fnameptr += len; - - sprintf(fnameptr, ".eml"); - - // open file - f = fopen(filename, "r"); - if (f == NULL) { - PrintAndLogEx(WARNING, "File not found or locked."); + uint8_t *data = calloc(1, 4096); + size_t datalen = 0; + //int res = loadFile(Cmd, "bin", data, &datalen); + int res = loadFileEML( Cmd, "eml", data, &datalen); + if ( res ) { + free(data); return 1; } - - blockNum = 0; - while (!feof(f)){ - memset(buf, 0, sizeof(buf)); - - if (fgets(buf, sizeof(buf), f) == NULL) { - fclose(f); - PrintAndLogEx(WARNING, "File reading error."); - return 2; - } +// PrintAndLogEx(INFO, "DATA | %s", sprint_hex(data+1000, 24) ); + - if (strlen(buf) < 32) { - if(strlen(buf) && feof(f)) - break; - PrintAndLogEx(WARNING, "File content error. Block data must include 32 HEX symbols"); - fclose(f); - return 2; - } - for (i = 0; i < 32; i += 2) { - sscanf(&buf[i], "%02x", &tmp); - buf8[i / 2] = tmp & 0xFF; - } - - if (blockNum == 0) flags = MAGIC_INIT + MAGIC_WUPC; // switch on field and send magic sequence - if (blockNum == 1) flags = 0; // just write - if (blockNum == 16 * 4 - 1) flags = MAGIC_HALT + MAGIC_OFF; // Done. Switch off field. + // 64 or 256blocks. + if (datalen != 1024 && datalen != 4096) { + PrintAndLogEx(WARNING, "File content error. "); + free(data); + return 2; + } + + PrintAndLogEx(INFO, "Copying to magic card"); + + blockNum = 0; + while ( datalen ) { - if (mfCSetBlock(blockNum, buf8, NULL, flags)) { + // switch on field and send magic sequence + if (blockNum == 0) flags = MAGIC_INIT + MAGIC_WUPC; + + // write + if (blockNum == 1) flags = 0; + + // Switch off field. + if (blockNum == 16 * 4 - 1) flags = MAGIC_HALT + MAGIC_OFF; + + if (mfCSetBlock(blockNum, data + (16 * blockNum), NULL, flags)) { PrintAndLogEx(WARNING, "Can't set magic card block: %d", blockNum); - fclose(f); + free(data); return 3; } + + datalen -= 16; + printf("."); fflush(stdout); blockNum++; - - if (blockNum >= 16 * 4) break; // magic card type - mifare 1K + + // magic card type - mifare 1K + if (blockNum >= 16 * 4) break; } PrintAndLogEx(NORMAL, "\n"); - fclose(f); // 64 or 256blocks. if (blockNum != 16 * 4 && blockNum != 32 * 4 + 8 * 16){ PrintAndLogEx(WARNING, "File content error. There must be 64 blocks"); + free(data); return 4; } - PrintAndLogEx(SUCCESS, "Loaded %d blocks from file: %s", blockNum, filename); + + PrintAndLogEx(SUCCESS, "Card loaded %d blocks from file", blockNum); + free(data); return 0; } diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 71f4e02aa..3706564fd 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -135,26 +135,126 @@ out: return retval; } -/** - * Utility function to print to console. This is used consistently within the library instead - * of printf, but it actually only calls printf (and adds a linebreak). - * The reason to have this method is to - * make it simple to plug this library into proxmark, which has this function already to - * write also to a logfile. When doing so, just delete this function. - * @param fmt - */ - /* -void PrintAndLogDevice(logLevel_t level, char *fmt, ...) { - char buffer[2048] = {0}; - va_list args; - va_start(args, fmt); - vsnprintf(buffer, sizeof(buffer), fmt, args); - va_end(args); - PrintAndLogEx(level, buffer); +int saveFileJSON(const char *preferredName, const char *suffix, uint8_t* data, size_t datalen) { + //stub - for merlokk ;) + return 1; } -*/ + +int loadFile(const char *preferredName, const char *suffix, void* data, size_t* datalen) { + + if ( preferredName == NULL ) return 1; + if ( suffix == NULL ) return 1; + + int retval = 0; + int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10); + char * fileName = calloc(size, sizeof(char)); + sprintf(fileName,"%s.%s", preferredName, suffix); + + FILE *f = fopen(fileName, "rb"); + if ( !f ) { + PrintAndLogDevice(FAILED, "file: %s: not found or locked.", fileName); + retval = 1; + goto out; + } + + // get filesize in order to malloc memory + fseek(f, 0, SEEK_END); + long fsize = ftell(f); + fseek(f, 0, SEEK_SET); + + if ( fsize < 0 ) { + PrintAndLogDevice(FAILED, "error, when getting filesize"); + retval = 1; + goto out; + } + + uint8_t *dump = calloc(fsize, sizeof(uint8_t)); + if ( !dump ) { + PrintAndLogDevice(FAILED, "error, cannot allocate memory"); + retval = 2; + goto out; + } + + size_t bytes_read = fread(dump, 1, fsize, f); + + if ( bytes_read != fsize ) { + PrintAndLogDevice(FAILED, "error, bytes read mismatch file size"); + free(dump); + retval = 3; + goto out; + } + + memcpy(data, dump, bytes_read); + free(dump); + + PrintAndLogDevice(SUCCESS, "loaded %d bytes from binary file %s", bytes_read, fileName); + + *datalen = bytes_read; + +out: + fclose(f); + free(fileName); + return retval; +} + +int loadFileEML(const char *preferredName, const char *suffix, void* data, size_t* datalen) { + + if ( preferredName == NULL ) return 1; + if ( suffix == NULL ) return 1; + + size_t counter = 0; + int retval = 0, hexlen = 0; + int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10); + char * fileName = calloc(size, sizeof(char)); + sprintf(fileName,"%s.%s", preferredName, suffix); + + FILE *f = fopen(fileName, "r"); + if ( !f ) { + PrintAndLogDevice(FAILED, "file: %s: not found or locked.", fileName); + retval = 1; + goto out; + } + + // 128 + 2 newline chars + 1 null terminator + char line[131]; + memset(line, 0, sizeof(line)); + uint8_t buf[64] = {0x00}; + + while ( !feof(f) ) { + + memset(line, 0, sizeof(line)); + + if (fgets(line, sizeof(line), f) == NULL){ + fclose(f); + PrintAndLogEx(FAILED, "File reading error."); + retval = 2; + goto out; + } + + if ( line[0] == '#' ) + continue; + + int res = param_gethex_to_eol(line, 0, buf, sizeof(buf), &hexlen); + if (res == 0 || res == 1) { + memcpy(data + counter, buf, hexlen); + counter += hexlen; + } + } + fclose(f); + PrintAndLogDevice(SUCCESS, "loaded %d bytes from text file %s", counter, fileName); + *datalen = counter; + +out: + free(fileName); + return retval; +} + +int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t* datalen) { + //stub - for merlokk ;) + datalen = 0; + return 1; +} + #else //if we're on ARM -//void PrintAndLogDevice(logLevel_t level, char *fmt, ...) { return; } - #endif diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index bb4393a25..40bd7cfeb 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -48,10 +48,13 @@ #include #include "../ui.h" +int fileExists(const char *filename); + /** * @brief Utility function to save data to a binary file. This method takes a preferred name, but if that * file already exists, it tries with another name until it finds something suitable. * E.g. dumpdata-15.txt + * * @param preferredName * @param suffix the file suffix. Leave out the ".". * @param data The binary data to write to the file @@ -61,9 +64,10 @@ extern int saveFile(const char *preferredName, const char *suffix, const void* data, size_t datalen); /** - * @brief Utility function to save data to a textfile. This method takes a preferred name, but if that + * @brief Utility function to save data to a textfile (EML). This method takes a preferred name, but if that * file already exists, it tries with another name until it finds something suitable. * E.g. dumpdata-15.txt + * * @param preferredName * @param suffix the file suffix. Leave out the ".". * @param data The binary data to write to the file @@ -72,16 +76,55 @@ extern int saveFile(const char *preferredName, const char *suffix, const void* d * @return 0 for ok, 1 for failz */ extern int saveFileEML(const char *preferredName, const char *suffix, uint8_t* data, size_t datalen, size_t blocksize); -/** - * @brief Utility function to save load binary data from a a file. This method takes a filename, - * Should only be used for fixed-size binary files - * @param fileName the name of the file - * @param data a buffer to place data in - * @param datalen the length of the data/data. - * @return - */ -int fileExists(const char *filename); +/** STUB + * @brief Utility function to save JSON data to a file. This method takes a preferred name, but if that + * file already exists, it tries with another name until it finds something suitable. + * E.g. dumpdata-15.json + * + * @param preferredName + * @param suffix the file suffix. Leave out the ".". + * @param data The binary data to write to the file + * @param datalen the length of the data + * @return 0 for ok, 1 for failz + */ +extern int saveFileJSON(const char *preferredName, const char *suffix, uint8_t* data, size_t datalen); + +/** STUB + * @brief Utility function to load data from a binary file. This method takes a preferred name. + * E.g. dumpdata-15.bin + * + * @param preferredName + * @param suffix the file suffix. Leave out the ".". + * @param data The data array to store the loaded bytes from file + * @param datalen the number of bytes loaded from file + * @return 0 for ok, 1 for failz +*/ +extern int loadFile(const char *preferredName, const char *suffix, void* data, size_t* datalen); + +/** + * @brief Utility function to load data from a textfile (EML). This method takes a preferred name. + * E.g. dumpdata-15.txt + * + * @param preferredName + * @param suffix the file suffix. Leave out the ".". + * @param data The data array to store the loaded bytes from file + * @param datalen the number of bytes loaded from file + * @return 0 for ok, 1 for failz +*/ +extern int loadFileEML(const char *preferredName, const char *suffix, void* data, size_t* datalen); + +/** STUB + * @brief Utility function to load data from a JSON textfile. This method takes a preferred name. + * E.g. dumpdata-15.json + * + * @param preferredName + * @param suffix the file suffix. Leave out the ".". + * @param data The data array to store the loaded bytes from file + * @param datalen the number of bytes loaded from file + * @return 0 for ok, 1 for failz +*/ +extern int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t* datalen); #define PrintAndLogDevice(level, format, args...) PrintAndLogEx(level, format , ## args) #else @@ -98,7 +141,4 @@ int fileExists(const char *filename); #endif //ON_DEVICE - -//void PrintAndLogDevice(logLevel_t level, char *fmt, ...); - #endif // FILEUTILS_H From eb4310395e6106e486d1fc1c0c8f1616b9e44bc8 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 12 Nov 2018 22:19:54 +0100 Subject: [PATCH 0153/1938] CHG: 'LF T55XX DETECT' - swapped some demod order. From FSK-PSK-ASK, to FSK-ASK-PSK since PSK is the leasted used modulation --- client/cmdlft55xx.c | 79 +++++++++++++++++++++++---------------------- 1 file changed, 41 insertions(+), 38 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 743d2db9c..bf73d6ff5 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1507,7 +1507,7 @@ int CmdT55xxBruteForce(const char *Cmd) { // load a default pwd file. char line[9]; - char filename[FILE_PATH_SIZE]={0}; + char filename[FILE_PATH_SIZE] = {0}; int keycnt = 0; uint8_t stKeyBlock = 20; uint8_t *keyBlock = NULL, *p = NULL; @@ -1752,9 +1752,10 @@ int CmdT55xxRecoverPW(const char *Cmd) { return 0; } + // note length of data returned is different for different chips. -// some return all page 1 (64 bits) and others return just that block (32 bits) -// unfortunately the 64 bits makes this more likely to get a false positive... +// some return all page 1 (64 bits) and others return just that block (32 bits) +// unfortunately the 64 bits makes this more likely to get a false positive... bool tryDetectP1(bool getData) { uint8_t preamble[] = {1,1,1,0,0,0,0,0,0,0,0,1,0,1,0,1}; size_t startIdx = 0; @@ -1771,7 +1772,7 @@ bool tryDetectP1(bool getData) { ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, &firstClockEdge); if (ans && ((fc1==10 && fc2==8) || (fc1==8 && fc2==5))) { if ( FSKrawDemod("0 0", false) && - preambleSearchEx(DemodBuffer, preamble,sizeof(preamble), &DemodBufferLen, &startIdx, false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64) ) { return true; } @@ -1783,40 +1784,6 @@ bool tryDetectP1(bool getData) { return false; } - // try psk clock detect. if successful it cannot be any other type of modulation... (in theory...) - clk = GetPskClock("", false); - if (clk > 0) { - // allow undo - // save_restoreGB(1); - // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) - //CmdLtrim("160"); - if ( PSKDemod("0 0 6", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && - (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - //save_restoreGB(0); - return true; - } - if ( PSKDemod("0 1 6", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && - (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - //save_restoreGB(0); - return true; - } - // PSK2 - needs a call to psk1TOpsk2. - if ( PSKDemod("0 0 6", false)) { - psk1TOpsk2(DemodBuffer, DemodBufferLen); - if (preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && - (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - //save_restoreGB(0); - return true; - } - } // inverse waves does not affect PSK2 demod - //undo trim samples - //save_restoreGB(0); - // no other modulation clocks = 2 or 4 so quit searching - if (fc1 != 8) return false; - } - // try ask clock detect. it could be another type even if successful. clk = GetAskClock("", false); if (clk>0) { @@ -1857,6 +1824,42 @@ bool tryDetectP1(bool getData) { return true; } } + + // Fewer card uses PSK + // try psk clock detect. if successful it cannot be any other type of modulation... (in theory...) + clk = GetPskClock("", false); + if (clk > 0) { + // allow undo + // save_restoreGB(1); + // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) + //CmdLtrim("160"); + if ( PSKDemod("0 0 6", false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + //save_restoreGB(0); + return true; + } + if ( PSKDemod("0 1 6", false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + //save_restoreGB(0); + return true; + } + // PSK2 - needs a call to psk1TOpsk2. + if ( PSKDemod("0 0 6", false)) { + psk1TOpsk2(DemodBuffer, DemodBufferLen); + if (preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + //save_restoreGB(0); + return true; + } + } // inverse waves does not affect PSK2 demod + //undo trim samples + //save_restoreGB(0); + // no other modulation clocks = 2 or 4 so quit searching + if (fc1 != 8) return false; + } + return false; } // does this need to be a callable command? From 25b07682dc1b258e5eeb05033b8f99b64bac128f Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 12 Nov 2018 22:55:19 +0100 Subject: [PATCH 0154/1938] CHG: 'mem load' - adapted loading files to use new load function. loading binary file can be called with NULL pointer, don't forget to free it. --- client/cmdflashmem.c | 66 +++++++++++++------------------------- client/loclass/fileutils.c | 6 +++- 2 files changed, 27 insertions(+), 45 deletions(-) diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index 62f341a24..1dd3084d9 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -151,20 +151,16 @@ int CmdFlashmemSpiBaudrate(const char *Cmd) { int CmdFlashMemLoad(const char *Cmd){ - FILE *f; - char filename[FILE_PATH_SIZE] = {0}; - uint8_t cmdp = 0; - bool errors = false; uint32_t start_index = 0; + char filename[FILE_PATH_SIZE] = {0}; + bool errors = false; + uint8_t cmdp = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { - case 'o': - start_index = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; + case 'h': + return usage_flashmem_load(); case 'f': - //File handling and reading if ( param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) { PrintAndLogEx(FAILED, "Filename too long"); errors = true; @@ -172,8 +168,10 @@ int CmdFlashMemLoad(const char *Cmd){ } cmdp += 2; break; - case 'h': - return usage_flashmem_load(); + case 'o': + start_index = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -183,52 +181,32 @@ int CmdFlashMemLoad(const char *Cmd){ //Validations if (errors || cmdp == 0 ) return usage_flashmem_load(); - - // load file - f = fopen(filename, "rb"); - if ( !f ){ - PrintAndLogEx(FAILED, "File: %s: not found or locked.", filename); - return 1; - } - // get filesize in order to malloc memory - fseek(f, 0, SEEK_END); - long fsize = ftell(f); - fseek(f, 0, SEEK_SET); - - if (fsize < 0) { - PrintAndLogDevice(WARNING, "error, when getting filesize"); - fclose(f); + uint8_t *data = NULL; + size_t datalen = 0; + int res = loadFile(filename, "bin", &data, &datalen); + //int res = loadFileEML( filename, "eml", data, &datalen); + if ( res ) { + free(data); return 1; } - if (fsize > FLASH_MEM_MAX_SIZE) { + if (datalen > FLASH_MEM_MAX_SIZE) { PrintAndLogDevice(WARNING, "error, filesize is larger than available memory"); - fclose(f); + free(data); return 1; } - uint8_t *dump = calloc(fsize, sizeof(uint8_t)); - if (!dump) { - PrintAndLogDevice(WARNING, "error, cannot allocate memory "); - fclose(f); - return 1; - } - - size_t bytes_read = fread(dump, 1, fsize, f); - if (f) - fclose(f); - //Send to device uint32_t bytes_sent = 0; - uint32_t bytes_remaining = bytes_read; + uint32_t bytes_remaining = datalen; while (bytes_remaining > 0){ uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); UsbCommand c = {CMD_FLASHMEM_WRITE, {start_index + bytes_sent, bytes_in_packet, 0}}; - memcpy(c.d.asBytes, dump + bytes_sent, bytes_in_packet); + memcpy(c.d.asBytes, data + bytes_sent, bytes_in_packet); clearCommandBuffer(); SendCommand(&c); @@ -238,7 +216,7 @@ int CmdFlashMemLoad(const char *Cmd){ UsbCommand resp; if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); - free(dump); + free(data); return 1; } @@ -247,9 +225,9 @@ int CmdFlashMemLoad(const char *Cmd){ PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent); } - free(dump); + free(data); - PrintAndLogEx(SUCCESS, "Wrote %u bytes to offset %u", bytes_read, start_index); + PrintAndLogEx(SUCCESS, "Wrote %u bytes to offset %u", datalen, start_index); return 0; } int CmdFlashMemSave(const char *Cmd){ diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 3706564fd..44bab0193 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -184,7 +184,11 @@ int loadFile(const char *preferredName, const char *suffix, void* data, size_t* goto out; } - memcpy(data, dump, bytes_read); + if ( (data) == NULL) { + (data) = calloc( bytes_read, sizeof(uint8_t)); + } + + memcpy( (data), dump, bytes_read); free(dump); PrintAndLogDevice(SUCCESS, "loaded %d bytes from binary file %s", bytes_read, fileName); From ac12d715f0dade00cd02408fcd7d4d8eb353a29d Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 13 Nov 2018 12:34:09 +0100 Subject: [PATCH 0155/1938] chg: 'sc raw' - no need to tvl decode twice --- client/cmdsmartcard.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 675b9a9b7..a7b45c51d 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -232,10 +232,6 @@ int CmdSmartRaw(const char *Cmd) { clearCommandBuffer(); SendCommand(&c); len = smart_response(buf); - - // TLV decoder - if (len > 4) - TLVPrintFromBuffer(buf+1, len-3); data[4] = 0; } From d7d409d9eb94acfce8eaa6b420b8d918ccd9645c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Nov 2018 14:05:14 +0200 Subject: [PATCH 0156/1938] added check signature in `hf fido auth` command --- client/cmdhffido.c | 59 +++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 56 insertions(+), 3 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index ab9afbdca..86f6bd98b 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -404,6 +404,8 @@ int CmdHFFidoRegister(const char *cmd) { int CmdHFFidoAuthenticate(const char *cmd) { uint8_t data[512] = {0}; uint8_t hdata[250] = {0}; + bool public_key_loaded = false; + uint8_t public_key[65] = {0}; int hdatalen = 0; uint8_t keyHandleLen = 0; json_t *root = NULL; @@ -423,6 +425,7 @@ int CmdHFFidoAuthenticate(const char *cmd) { arg_lit0("uU", "user", "mode: enforce-user-presence-and-sign"), arg_lit0("cC", "check", "mode: check-only"), arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."), + arg_str0("kK", "key", "public key to verify signature", NULL), arg_str0(NULL, NULL, "", NULL), arg_str0(NULL, NULL, "", NULL), arg_str0(NULL, NULL, "", NULL), @@ -431,7 +434,7 @@ int CmdHFFidoAuthenticate(const char *cmd) { CLIExecWithReturn(cmd, argtable, true); bool APDULogging = arg_get_lit(1); - //bool verbose = arg_get_lit(2); + bool verbose = arg_get_lit(2); bool paramsPlain = arg_get_lit(3); uint8_t controlByte = 0x08; if (arg_get_lit(5)) @@ -449,11 +452,25 @@ int CmdHFFidoAuthenticate(const char *cmd) { JsonLoadBufAsHex(root, "$.ChallengeParam", data, 32, &jlen); JsonLoadBufAsHex(root, "$.ApplicationParam", &data[32], 32, &jlen); JsonLoadBufAsHex(root, "$.KeyHandle", &data[65], 512 - 67, &jlen); + JsonLoadBufAsHex(root, "$.PublicKey", public_key, 65, &jlen); + if (jlen > 0) + public_key_loaded = true; keyHandleLen = jlen & 0xff; data[64] = keyHandleLen; } + // public key CLIGetHexWithReturn(8, hdata, &hdatalen); + if (hdatalen && hdatalen != 130) { + PrintAndLog("ERROR: public key length must be 65 bytes only."); + return 1; + } + if (hdatalen) { + memmove(public_key, hdata, hdatalen); + public_key_loaded = true; + } + + CLIGetHexWithReturn(9, hdata, &hdatalen); if (hdatalen > 255) { PrintAndLog("ERROR: application parameter length must be less than 255."); return 1; @@ -472,7 +489,7 @@ int CmdHFFidoAuthenticate(const char *cmd) { return 1; } } else { - CLIGetHexWithReturn(9, hdata, &hdatalen); + CLIGetHexWithReturn(10, hdata, &hdatalen); if (hdatalen && hdatalen != 32) { PrintAndLog("ERROR: challenge parameter length must be 32 bytes only."); return 1; @@ -483,7 +500,7 @@ int CmdHFFidoAuthenticate(const char *cmd) { if (paramsPlain) { memset(hdata, 0x00, 32); - CLIGetStrWithReturn(10, hdata, &hdatalen); + CLIGetStrWithReturn(11, hdata, &hdatalen); if (hdatalen && hdatalen > 16) { PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen); return 1; @@ -547,6 +564,42 @@ int CmdHFFidoAuthenticate(const char *cmd) { PrintAndLog("Counter: %d", cntr); PrintAndLog("Hash[%d]: %s", len - 5, sprint_hex(&buf[5], len - 5)); + // check ANSI X9.62 format ECDSA signature (on P-256) + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; + res = ecdsa_asn1_get_signature(&buf[5], len - 5, rval, sval); + if (!res) { + if (verbose) { + PrintAndLog(" r: %s", sprint_hex(rval, 32)); + PrintAndLog(" s: %s", sprint_hex(sval, 32)); + } + if (public_key_loaded) { + uint8_t xbuf[4096] = {0}; + size_t xbuflen = 0; + res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, + &data[32], 32, // application parameter + &buf[0], 1, // user presence + &buf[1], 4, // counter + data, 32, // challenge parameter + NULL, 0); + PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); + res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[5], len - 5); + if (res) { + if (res == -0x4e00) { + PrintAndLog("Signature is NOT VALID."); + } else { + PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); + } + } else { + PrintAndLog("Signature is OK."); + } + } else { + PrintAndLog("No public key provided. can't check signature."); + } + } else { + PrintAndLog("Invalid signature. res=%d.", res); + } + if (root) { JsonSaveBufAsHex(root, "ChallengeParam", data, 32); JsonSaveBufAsHex(root, "ApplicationParam", &data[32], 32); From 679b5eec5b28e4b499011528c91382b6d19bb319 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Nov 2018 14:55:02 +0200 Subject: [PATCH 0157/1938] small fix. now works --- client/cmdhffido.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 86f6bd98b..5379d2efc 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -383,6 +383,7 @@ int CmdHFFidoRegister(const char *cmd) { if (root) { JsonSaveBufAsHex(root, "ChallengeParam", data, 32); JsonSaveBufAsHex(root, "ApplicationParam", &data[32], 32); + JsonSaveBufAsHexCompact(root, "PublicKey", &buf[1], 65); JsonSaveInt(root, "KeyHandleLen", keyHandleLen); JsonSaveBufAsHexCompact(root, "KeyHandle", &buf[67], keyHandleLen); JsonSaveBufAsHexCompact(root, "DER", &buf[67 + keyHandleLen], derLen); @@ -452,11 +453,10 @@ int CmdHFFidoAuthenticate(const char *cmd) { JsonLoadBufAsHex(root, "$.ChallengeParam", data, 32, &jlen); JsonLoadBufAsHex(root, "$.ApplicationParam", &data[32], 32, &jlen); JsonLoadBufAsHex(root, "$.KeyHandle", &data[65], 512 - 67, &jlen); - JsonLoadBufAsHex(root, "$.PublicKey", public_key, 65, &jlen); - if (jlen > 0) - public_key_loaded = true; keyHandleLen = jlen & 0xff; data[64] = keyHandleLen; + JsonLoadBufAsHex(root, "$.PublicKey", public_key, 65, &jlen); + public_key_loaded = (jlen > 0); } // public key @@ -582,7 +582,7 @@ int CmdHFFidoAuthenticate(const char *cmd) { &buf[1], 4, // counter data, 32, // challenge parameter NULL, 0); - PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); + //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[5], len - 5); if (res) { if (res == -0x4e00) { From fd9fe81ba482527dc53a200f01ea2b09dfda6a86 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 13 Nov 2018 14:08:01 +0100 Subject: [PATCH 0158/1938] fix: 'sc list' - the iso7816-4 annotation now prints. --- client/cmdhflist.c | 15 +++++++++++++-- client/cmdtrace.c | 5 ++++- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index ddda15a2c..2deab204c 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -326,8 +326,19 @@ void annotateIso7816(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ } // I-block else { - - int pos = (cmd[0] == 2 || cmd[0] == 3) ? 2 : 3; + int pos = 0; + switch ( cmd[0] ) { + case 2: + case 3: + pos = 2; + break; + case 0: + pos = 1; + break; + default: + pos = 3; + break; + } switch ( cmd[pos] ){ case ISO7816_READ_BINARY :snprintf(exp, size, "READ BIN");break; case ISO7816_WRITE_BINARY :snprintf(exp, size, "WRITE BIN");break; diff --git a/client/cmdtrace.c b/client/cmdtrace.c index 537786bb4..90c08459f 100644 --- a/client/cmdtrace.c +++ b/client/cmdtrace.c @@ -174,6 +174,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui case ISO_15693: crcStatus = iso15693_CRC_check(frame, data_len); break; + case ISO_7816_4: default: break; } @@ -526,7 +527,9 @@ int CmdTraceList(const char *Cmd) { if ( protocol == ISO_15693 ) PrintAndLogEx(NORMAL, "ISO15693 - Timings are not as accurate"); if ( protocol == FELICA ) - PrintAndLogEx(NORMAL, "ISO18092 / FeliCa - Timings are not as accurate"); + PrintAndLogEx(NORMAL, "ISO18092 / FeliCa - Timings are not as accurate"); + if ( protocol == ISO_7816_4 ) + PrintAndLogEx(NORMAL, "ISO7816-4 / Smartcard - Timings N/A yet"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation"); From 7214c70720ae6f856dc42f74fd07731084f7da9e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Nov 2018 19:02:02 +0200 Subject: [PATCH 0159/1938] fido commands hash checks works. --- client/Makefile | 1 + client/cmdhffido.c | 67 ++++- client/crypto/libpcrypto.c | 26 ++ client/crypto/libpcrypto.h | 2 + client/fido/additional_ca.c | 63 +++++ client/fido/additional_ca.h | 21 ++ client/obj/fido/.dummy | 0 common/mbedtls/Makefile | 1 + common/mbedtls/pkwrite.c | 517 ++++++++++++++++++++++++++++++++++++ 9 files changed, 691 insertions(+), 7 deletions(-) create mode 100644 client/fido/additional_ca.c create mode 100644 client/fido/additional_ca.h create mode 100644 client/obj/fido/.dummy create mode 100644 common/mbedtls/pkwrite.c diff --git a/client/Makefile b/client/Makefile index 7aacebc7a..60217101a 100644 --- a/client/Makefile +++ b/client/Makefile @@ -107,6 +107,7 @@ CMDSRCS = crapto1/crapto1.c \ crapto1/crypto1.c \ mfkey.c \ tea.c \ + fido/additional_ca.c \ polarssl/des.c \ crypto/libpcrypto.c\ crypto/asn1utils.c\ diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 5379d2efc..9a01705fc 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -41,6 +41,10 @@ #include "cliparser/cliparser.h" #include "crypto/asn1utils.h" #include "crypto/libpcrypto.h" +#include "fido/additional_ca.h" +#include "mbedtls/x509_crt.h" +#include "mbedtls/x509.h" +#include "mbedtls/pk.h" static int CmdHelp(const char *Cmd); @@ -203,7 +207,7 @@ int CmdHFFidoRegister(const char *cmd) { void* argtable[] = { arg_param_begin, arg_lit0("aA", "apdu", "show APDU reqests and responses"), - arg_lit0("vV", "verbose", "show technical data"), + arg_lit0("vV", "verbose", "show technical data. vv - show full certificates data"), arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"), arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."), arg_str0(NULL, NULL, "", NULL), @@ -214,6 +218,7 @@ int CmdHFFidoRegister(const char *cmd) { bool APDULogging = arg_get_lit(1); bool verbose = arg_get_lit(2); + bool verbose2 = arg_get_lit(2) > 1; bool paramsPlain = arg_get_lit(3); char fname[250] = {0}; @@ -304,7 +309,7 @@ int CmdHFFidoRegister(const char *cmd) { if (APDULogging) PrintAndLog("---------------------------------------------------------------"); PrintAndLog("data len: %d", len); - if (verbose) { + if (verbose2) { PrintAndLog("--------------data----------------------"); dump_buffer((const unsigned char *)buf, len, NULL, 0); PrintAndLog("--------------data----------------------"); @@ -321,8 +326,7 @@ int CmdHFFidoRegister(const char *cmd) { int derp = 67 + keyHandleLen; int derLen = (buf[derp + 2] << 8) + buf[derp + 3] + 4; - // needs to decode DER certificate - if (verbose) { + if (verbose2) { PrintAndLog("DER certificate[%d]:------------------DER-------------------", derLen); dump_buffer_simple((const unsigned char *)&buf[67 + keyHandleLen], derLen, NULL); PrintAndLog("\n----------------DER---------------------"); @@ -331,7 +335,56 @@ int CmdHFFidoRegister(const char *cmd) { } // check and print DER certificate - uint8_t public_key[65] = {0}; + uint8_t public_key[65] = {0}; + + // TODO: print DER certificate in DER view + + // load CA's + mbedtls_x509_crt cacert; + mbedtls_x509_crt_init(&cacert); + res = mbedtls_x509_crt_parse(&cacert, (const unsigned char *) additional_ca_pem, additional_ca_pem_len); + if (res < 0) { + PrintAndLog("ERROR: CA parse certificate returned -0x%x - %s", -res, ecdsa_get_error(res)); + } + if (verbose) + PrintAndLog("CA load OK. %d skipped", res); + + // load DER certificate from authenticator's data + mbedtls_x509_crt cert; + mbedtls_x509_crt_init(&cert); + res = mbedtls_x509_crt_parse_der(&cert, &buf[67 + keyHandleLen], derLen); + if (res) { + PrintAndLog("ERROR: DER parse returned 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res)); + } + + // get certificate info + char linfo[300] = {0}; + mbedtls_x509_crt_info(linfo, sizeof(linfo), " ", &cert); + PrintAndLog("DER certificate info:\n%s", linfo); + + // verify certificate + uint32_t verifyflags = 0; + memset(linfo, 0x00, sizeof(linfo)); + + res = mbedtls_x509_crt_verify(&cert, &cacert, NULL, NULL, &verifyflags, NULL, NULL); + if (res) { + PrintAndLog("ERROR: DER verify returned 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res)); + } + + mbedtls_x509_crt_verify_info(linfo, sizeof(linfo), " ", verifyflags); + PrintAndLog("Verification info:\n%s", linfo); + + // get public key + res = ecdsa_public_key_from_pk(&cert.pk, public_key, sizeof(public_key)); + if (res) { + PrintAndLog("ERROR: getting public key from certificate 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res)); + } else { + if (verbose) + PrintAndLog("Got a public key from certificate."); + } + + mbedtls_x509_crt_free(&cert); + mbedtls_x509_crt_free(&cacert); // get hash int hashp = 1 + 65 + 1 + keyHandleLen + derLen; @@ -351,8 +404,8 @@ int CmdHFFidoRegister(const char *cmd) { size_t xbuflen = 0; res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, "\x00", 1, - adata, 32, - cdata, 32, + &data[32], 32, // application parameter + &data[0], 32, // challenge parameter &buf[67], keyHandleLen, // keyHandle &buf[1], 65, // user public key NULL, 0); diff --git a/client/crypto/libpcrypto.c b/client/crypto/libpcrypto.c index 030be15a3..896048bf0 100644 --- a/client/crypto/libpcrypto.c +++ b/client/crypto/libpcrypto.c @@ -16,6 +16,7 @@ #include #include #include +#include #include #include #include @@ -208,6 +209,31 @@ char *ecdsa_get_error(int ret) { return retstr; } +int ecdsa_public_key_from_pk(mbedtls_pk_context *pk, uint8_t *key, size_t keylen) { + int res = 0; + size_t realkeylen = 0; + if (keylen < 65) + return 1; + + mbedtls_ecdsa_context ctx; + mbedtls_ecdsa_init(&ctx); + + res = mbedtls_ecp_group_load(&ctx.grp, MBEDTLS_ECP_DP_SECP256R1); // secp256r1 + if (res) + goto exit; + + res = mbedtls_ecdsa_from_keypair(&ctx, mbedtls_pk_ec(*pk) ); + if (res) + goto exit; + + res = mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &realkeylen, key, keylen); + if (realkeylen != 65) + res = 2; +exit: + mbedtls_ecdsa_free(&ctx); + return res; +} + int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen) { int res; *signaturelen = 0; diff --git a/client/crypto/libpcrypto.h b/client/crypto/libpcrypto.h index 8d4b4a0d0..7ac6c3b07 100644 --- a/client/crypto/libpcrypto.h +++ b/client/crypto/libpcrypto.h @@ -14,6 +14,7 @@ #include #include #include +#include extern int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); extern int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int length); @@ -23,6 +24,7 @@ extern int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, in extern int sha256hash(uint8_t *input, int length, uint8_t *hash); extern int ecdsa_key_create(uint8_t * key_d, uint8_t *key_xy); +extern int ecdsa_public_key_from_pk(mbedtls_pk_context *pk, uint8_t *key, size_t keylen); extern int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen); extern int ecdsa_signature_verify(uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t signaturelen); extern char *ecdsa_get_error(int ret); diff --git a/client/fido/additional_ca.c b/client/fido/additional_ca.c new file mode 100644 index 000000000..aeb90aa40 --- /dev/null +++ b/client/fido/additional_ca.c @@ -0,0 +1,63 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// CA PEM certificates +//----------------------------------------------------------------------------- +// + +#include "additional_ca.h" +#include "mbedtls/certs.h" + +#define GLOBALSIGN_CA \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIDdTCCAl2gAwIBAgILBAAAAAABFUtaw5QwDQYJKoZIhvcNAQEFBQAwVzELMAkG\r\n" \ +"A1UEBhMCQkUxGTAXBgNVBAoTEEdsb2JhbFNpZ24gbnYtc2ExEDAOBgNVBAsTB1Jv\r\n" \ +"b3QgQ0ExGzAZBgNVBAMTEkdsb2JhbFNpZ24gUm9vdCBDQTAeFw05ODA5MDExMjAw\r\n" \ +"MDBaFw0yODAxMjgxMjAwMDBaMFcxCzAJBgNVBAYTAkJFMRkwFwYDVQQKExBHbG9i\r\n" \ +"YWxTaWduIG52LXNhMRAwDgYDVQQLEwdSb290IENBMRswGQYDVQQDExJHbG9iYWxT\r\n" \ +"aWduIFJvb3QgQ0EwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDaDuaZ\r\n" \ +"jc6j40+Kfvvxi4Mla+pIH/EqsLmVEQS98GPR4mdmzxzdzxtIK+6NiY6arymAZavp\r\n" \ +"xy0Sy6scTHAHoT0KMM0VjU/43dSMUBUc71DuxC73/OlS8pF94G3VNTCOXkNz8kHp\r\n" \ +"1Wrjsok6Vjk4bwY8iGlbKk3Fp1S4bInMm/k8yuX9ifUSPJJ4ltbcdG6TRGHRjcdG\r\n" \ +"snUOhugZitVtbNV4FpWi6cgKOOvyJBNPc1STE4U6G7weNLWLBYy5d4ux2x8gkasJ\r\n" \ +"U26Qzns3dLlwR5EiUWMWea6xrkEmCMgZK9FGqkjWZCrXgzT/LCrBbBlDSgeF59N8\r\n" \ +"9iFo7+ryUp9/k5DPAgMBAAGjQjBAMA4GA1UdDwEB/wQEAwIBBjAPBgNVHRMBAf8E\r\n" \ +"BTADAQH/MB0GA1UdDgQWBBRge2YaRQ2XyolQL30EzTSo//z9SzANBgkqhkiG9w0B\r\n" \ +"AQUFAAOCAQEA1nPnfE920I2/7LqivjTFKDK1fPxsnCwrvQmeU79rXqoRSLblCKOz\r\n" \ +"yj1hTdNGCbM+w6DjY1Ub8rrvrTnhQ7k4o+YviiY776BQVvnGCv04zcQLcFGUl5gE\r\n" \ +"38NflNUVyRRBnMRddWQVDf9VMOyGj/8N7yy5Y0b2qvzfvGn9LhJIZJrglfCm7ymP\r\n" \ +"AbEVtQwdpf5pLGkkeB6zpxxxYu7KyJesF12KwvhHhm4qxFYxldBniYUr+WymXUad\r\n" \ +"DKqC5JlR3XC321Y9YeRq4VzW9v493kHMB65jUr9TU/Qr6cf9tveCX4XSQRjbgbME\r\n" \ +"HMUfpIBvFSDJ3gyICh3WZlXi/EjJKSZp4A==\r\n" \ +"-----END CERTIFICATE-----\r\n" + +// Name: Yubico U2F Root CA Serial 457200631 +// Issued: 2014-08-01 +#define YUBICO_CA \ +"-----BEGIN CERTIFICATE-----" \ +"MIIDHjCCAgagAwIBAgIEG0BT9zANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZ" \ +"dWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAw" \ +"MDBaGA8yMDUwMDkwNDAwMDAwMFowLjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290" \ +"IENBIFNlcmlhbCA0NTcyMDA2MzEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK" \ +"AoIBAQC/jwYuhBVlqaiYWEMsrWFisgJ+PtM91eSrpI4TK7U53mwCIawSDHy8vUmk" \ +"5N2KAj9abvT9NP5SMS1hQi3usxoYGonXQgfO6ZXyUA9a+KAkqdFnBnlyugSeCOep" \ +"8EdZFfsaRFtMjkwz5Gcz2Py4vIYvCdMHPtwaz0bVuzneueIEz6TnQjE63Rdt2zbw" \ +"nebwTG5ZybeWSwbzy+BJ34ZHcUhPAY89yJQXuE0IzMZFcEBbPNRbWECRKgjq//qT" \ +"9nmDOFVlSRCt2wiqPSzluwn+v+suQEBsUjTGMEd25tKXXTkNW21wIWbxeSyUoTXw" \ +"LvGS6xlwQSgNpk2qXYwf8iXg7VWZAgMBAAGjQjBAMB0GA1UdDgQWBBQgIvz0bNGJ" \ +"hjgpToksyKpP9xv9oDAPBgNVHRMECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAN" \ +"BgkqhkiG9w0BAQsFAAOCAQEAjvjuOMDSa+JXFCLyBKsycXtBVZsJ4Ue3LbaEsPY4" \ +"MYN/hIQ5ZM5p7EjfcnMG4CtYkNsfNHc0AhBLdq45rnT87q/6O3vUEtNMafbhU6kt" \ +"hX7Y+9XFN9NpmYxr+ekVY5xOxi8h9JDIgoMP4VB1uS0aunL1IGqrNooL9mmFnL2k" \ +"LVVee6/VR6C5+KSTCMCWppMuJIZII2v9o4dkoZ8Y7QRjQlLfYzd3qGtKbw7xaF1U" \ +"sG/5xUb/Btwb2X2g4InpiB/yt/3CpQXpiWX/K4mBvUKiGn05ZsqeY1gx4g0xLBqc" \ +"U9psmyPzK+Vsgw2jeRQ5JlKDyqE0hebfC1tvFu0CCrJFcw==" \ +"-----END CERTIFICATE-----" + +/* Concatenation of all additional CA certificates in PEM format if available */ +const char additional_ca_pem[] = YUBICO_CA; ///GLOBALSIGN_CA +const size_t additional_ca_pem_len = sizeof(additional_ca_pem); diff --git a/client/fido/additional_ca.h b/client/fido/additional_ca.h new file mode 100644 index 000000000..856583039 --- /dev/null +++ b/client/fido/additional_ca.h @@ -0,0 +1,21 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// CA PEM certificates +//----------------------------------------------------------------------------- +// + +#ifndef __ADDITIONAL_CA_H__ +#define __ADDITIONAL_CA_H__ + +#include + +// Concatenation of all CA certificates in PEM format if available +extern const char additional_ca_pem[]; +extern const size_t additional_ca_pem_len; + +#endif /* __ADDITIONAL_CA_H__ */ diff --git a/client/obj/fido/.dummy b/client/obj/fido/.dummy new file mode 100644 index 000000000..e69de29bb diff --git a/common/mbedtls/Makefile b/common/mbedtls/Makefile index 3e57fdac2..a9a850989 100644 --- a/common/mbedtls/Makefile +++ b/common/mbedtls/Makefile @@ -29,6 +29,7 @@ mbedtls_SOURCES = \ arc4.c \ pk.c \ pk_wrap.c \ + pkwrite.c \ pkcs5.c \ pkcs12.c \ pkparse.c \ diff --git a/common/mbedtls/pkwrite.c b/common/mbedtls/pkwrite.c new file mode 100644 index 000000000..8e0bb2e60 --- /dev/null +++ b/common/mbedtls/pkwrite.c @@ -0,0 +1,517 @@ +/* + * Public Key layer for writing key files and structures + * + * Copyright (C) 2006-2015, ARM Limited, All Rights Reserved + * SPDX-License-Identifier: GPL-2.0 + * + * 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. + * + * This file is part of mbed TLS (https://tls.mbed.org) + */ + +#if !defined(MBEDTLS_CONFIG_FILE) +#include "mbedtls/config.h" +#else +#include MBEDTLS_CONFIG_FILE +#endif + +#if defined(MBEDTLS_PK_WRITE_C) + +#include "mbedtls/pk.h" +#include "mbedtls/asn1write.h" +#include "mbedtls/oid.h" + +#include + +#if defined(MBEDTLS_RSA_C) +#include "mbedtls/rsa.h" +#endif +#if defined(MBEDTLS_ECP_C) +#include "mbedtls/ecp.h" +#endif +#if defined(MBEDTLS_ECDSA_C) +#include "mbedtls/ecdsa.h" +#endif +#if defined(MBEDTLS_PEM_WRITE_C) +#include "mbedtls/pem.h" +#endif + +#if defined(MBEDTLS_PLATFORM_C) +#include "mbedtls/platform.h" +#else +#include +#define mbedtls_calloc calloc +#define mbedtls_free free +#endif + +#if defined(MBEDTLS_RSA_C) +/* + * RSAPublicKey ::= SEQUENCE { + * modulus INTEGER, -- n + * publicExponent INTEGER -- e + * } + */ +static int pk_write_rsa_pubkey( unsigned char **p, unsigned char *start, + mbedtls_rsa_context *rsa ) +{ + int ret; + size_t len = 0; + mbedtls_mpi T; + + mbedtls_mpi_init( &T ); + + /* Export E */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export N */ + if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( p, start, &T ) ) < 0 ) + goto end_of_export; + len += ret; + +end_of_export: + + mbedtls_mpi_free( &T ); + if( ret < 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( p, start, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( p, start, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * EC public key is an EC point + */ +static int pk_write_ec_pubkey( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret; + size_t len = 0; + unsigned char buf[MBEDTLS_ECP_MAX_PT_LEN]; + + if( ( ret = mbedtls_ecp_point_write_binary( &ec->grp, &ec->Q, + MBEDTLS_ECP_PF_UNCOMPRESSED, + &len, buf, sizeof( buf ) ) ) != 0 ) + { + return( ret ); + } + + if( *p < start || (size_t)( *p - start ) < len ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + *p -= len; + memcpy( *p, buf, len ); + + return( (int) len ); +} + +/* + * ECParameters ::= CHOICE { + * namedCurve OBJECT IDENTIFIER + * } + */ +static int pk_write_ec_param( unsigned char **p, unsigned char *start, + mbedtls_ecp_keypair *ec ) +{ + int ret; + size_t len = 0; + const char *oid; + size_t oid_len; + + if( ( ret = mbedtls_oid_get_oid_by_ec_grp( ec->grp.id, &oid, &oid_len ) ) != 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_oid( p, start, oid, oid_len ) ); + + return( (int) len ); +} +#endif /* MBEDTLS_ECP_C */ + +int mbedtls_pk_write_pubkey( unsigned char **p, unsigned char *start, + const mbedtls_pk_context *key ) +{ + int ret; + size_t len = 0; + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + MBEDTLS_ASN1_CHK_ADD( len, pk_write_rsa_pubkey( p, start, mbedtls_pk_rsa( *key ) ) ); + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + MBEDTLS_ASN1_CHK_ADD( len, pk_write_ec_pubkey( p, start, mbedtls_pk_ec( *key ) ) ); + else +#endif + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +int mbedtls_pk_write_pubkey_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char *c; + size_t len = 0, par_len = 0, oid_len; + const char *oid; + + c = buf + size; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_pk_write_pubkey( &c, buf, key ) ); + + if( c - buf < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + + /* + * SubjectPublicKeyInfo ::= SEQUENCE { + * algorithm AlgorithmIdentifier, + * subjectPublicKey BIT STRING } + */ + *--c = 0; + len += 1; + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); + + if( ( ret = mbedtls_oid_get_oid_by_pk_alg( mbedtls_pk_get_type( key ), + &oid, &oid_len ) ) != 0 ) + { + return( ret ); + } + +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, mbedtls_pk_ec( *key ) ) ); + } +#endif + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_algorithm_identifier( &c, buf, oid, oid_len, + par_len ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + + return( (int) len ); +} + +int mbedtls_pk_write_key_der( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char *c = buf + size; + size_t len = 0; + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + { + mbedtls_mpi T; /* Temporary holding the exported parameters */ + mbedtls_rsa_context *rsa = mbedtls_pk_rsa( *key ); + + /* + * Export the parameters one after another to avoid simultaneous copies. + */ + + mbedtls_mpi_init( &T ); + + /* Export QP */ + if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export DQ */ + if( ( ret = mbedtls_rsa_export_crt( rsa, NULL, &T, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export DP */ + if( ( ret = mbedtls_rsa_export_crt( rsa, &T, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export Q */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + &T, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export P */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, &T, + NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export D */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + NULL, &T, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export E */ + if ( ( ret = mbedtls_rsa_export( rsa, NULL, NULL, + NULL, NULL, &T ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + /* Export N */ + if ( ( ret = mbedtls_rsa_export( rsa, &T, NULL, + NULL, NULL, NULL ) ) != 0 || + ( ret = mbedtls_asn1_write_mpi( &c, buf, &T ) ) < 0 ) + goto end_of_export; + len += ret; + + end_of_export: + + mbedtls_mpi_free( &T ); + if( ret < 0 ) + return( ret ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 0 ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, + buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + } + else +#endif /* MBEDTLS_RSA_C */ +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + mbedtls_ecp_keypair *ec = mbedtls_pk_ec( *key ); + size_t pub_len = 0, par_len = 0; + + /* + * RFC 5915, or SEC1 Appendix C.4 + * + * ECPrivateKey ::= SEQUENCE { + * version INTEGER { ecPrivkeyVer1(1) } (ecPrivkeyVer1), + * privateKey OCTET STRING, + * parameters [0] ECParameters {{ NamedCurve }} OPTIONAL, + * publicKey [1] BIT STRING OPTIONAL + * } + */ + + /* publicKey */ + MBEDTLS_ASN1_CHK_ADD( pub_len, pk_write_ec_pubkey( &c, buf, ec ) ); + + if( c - buf < 1 ) + return( MBEDTLS_ERR_ASN1_BUF_TOO_SMALL ); + *--c = 0; + pub_len += 1; + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_BIT_STRING ) ); + + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_len( &c, buf, pub_len ) ); + MBEDTLS_ASN1_CHK_ADD( pub_len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 1 ) ); + len += pub_len; + + /* parameters */ + MBEDTLS_ASN1_CHK_ADD( par_len, pk_write_ec_param( &c, buf, ec ) ); + + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_len( &c, buf, par_len ) ); + MBEDTLS_ASN1_CHK_ADD( par_len, mbedtls_asn1_write_tag( &c, buf, + MBEDTLS_ASN1_CONTEXT_SPECIFIC | MBEDTLS_ASN1_CONSTRUCTED | 0 ) ); + len += par_len; + + /* privateKey: write as MPI then fix tag */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_mpi( &c, buf, &ec->d ) ); + *c = MBEDTLS_ASN1_OCTET_STRING; + + /* version */ + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_int( &c, buf, 1 ) ); + + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_len( &c, buf, len ) ); + MBEDTLS_ASN1_CHK_ADD( len, mbedtls_asn1_write_tag( &c, buf, MBEDTLS_ASN1_CONSTRUCTED | + MBEDTLS_ASN1_SEQUENCE ) ); + } + else +#endif /* MBEDTLS_ECP_C */ + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + return( (int) len ); +} + +#if defined(MBEDTLS_PEM_WRITE_C) + +#define PEM_BEGIN_PUBLIC_KEY "-----BEGIN PUBLIC KEY-----\n" +#define PEM_END_PUBLIC_KEY "-----END PUBLIC KEY-----\n" + +#define PEM_BEGIN_PRIVATE_KEY_RSA "-----BEGIN RSA PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_RSA "-----END RSA PRIVATE KEY-----\n" +#define PEM_BEGIN_PRIVATE_KEY_EC "-----BEGIN EC PRIVATE KEY-----\n" +#define PEM_END_PRIVATE_KEY_EC "-----END EC PRIVATE KEY-----\n" + +/* + * Max sizes of key per types. Shown as tag + len (+ content). + */ + +#if defined(MBEDTLS_RSA_C) +/* + * RSA public keys: + * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 3 + * algorithm AlgorithmIdentifier, 1 + 1 (sequence) + * + 1 + 1 + 9 (rsa oid) + * + 1 + 1 (params null) + * subjectPublicKey BIT STRING } 1 + 3 + (1 + below) + * RSAPublicKey ::= SEQUENCE { 1 + 3 + * modulus INTEGER, -- n 1 + 3 + MPI_MAX + 1 + * publicExponent INTEGER -- e 1 + 3 + MPI_MAX + 1 + * } + */ +#define RSA_PUB_DER_MAX_BYTES 38 + 2 * MBEDTLS_MPI_MAX_SIZE + +/* + * RSA private keys: + * RSAPrivateKey ::= SEQUENCE { 1 + 3 + * version Version, 1 + 1 + 1 + * modulus INTEGER, 1 + 3 + MPI_MAX + 1 + * publicExponent INTEGER, 1 + 3 + MPI_MAX + 1 + * privateExponent INTEGER, 1 + 3 + MPI_MAX + 1 + * prime1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * prime2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * exponent1 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * exponent2 INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * coefficient INTEGER, 1 + 3 + MPI_MAX / 2 + 1 + * otherPrimeInfos OtherPrimeInfos OPTIONAL 0 (not supported) + * } + */ +#define MPI_MAX_SIZE_2 MBEDTLS_MPI_MAX_SIZE / 2 + \ + MBEDTLS_MPI_MAX_SIZE % 2 +#define RSA_PRV_DER_MAX_BYTES 47 + 3 * MBEDTLS_MPI_MAX_SIZE \ + + 5 * MPI_MAX_SIZE_2 + +#else /* MBEDTLS_RSA_C */ + +#define RSA_PUB_DER_MAX_BYTES 0 +#define RSA_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_RSA_C */ + +#if defined(MBEDTLS_ECP_C) +/* + * EC public keys: + * SubjectPublicKeyInfo ::= SEQUENCE { 1 + 2 + * algorithm AlgorithmIdentifier, 1 + 1 (sequence) + * + 1 + 1 + 7 (ec oid) + * + 1 + 1 + 9 (namedCurve oid) + * subjectPublicKey BIT STRING 1 + 2 + 1 [1] + * + 1 (point format) [1] + * + 2 * ECP_MAX (coords) [1] + * } + */ +#define ECP_PUB_DER_MAX_BYTES 30 + 2 * MBEDTLS_ECP_MAX_BYTES + +/* + * EC private keys: + * ECPrivateKey ::= SEQUENCE { 1 + 2 + * version INTEGER , 1 + 1 + 1 + * privateKey OCTET STRING, 1 + 1 + ECP_MAX + * parameters [0] ECParameters OPTIONAL, 1 + 1 + (1 + 1 + 9) + * publicKey [1] BIT STRING OPTIONAL 1 + 2 + [1] above + * } + */ +#define ECP_PRV_DER_MAX_BYTES 29 + 3 * MBEDTLS_ECP_MAX_BYTES + +#else /* MBEDTLS_ECP_C */ + +#define ECP_PUB_DER_MAX_BYTES 0 +#define ECP_PRV_DER_MAX_BYTES 0 + +#endif /* MBEDTLS_ECP_C */ + +#define PUB_DER_MAX_BYTES RSA_PUB_DER_MAX_BYTES > ECP_PUB_DER_MAX_BYTES ? \ + RSA_PUB_DER_MAX_BYTES : ECP_PUB_DER_MAX_BYTES +#define PRV_DER_MAX_BYTES RSA_PRV_DER_MAX_BYTES > ECP_PRV_DER_MAX_BYTES ? \ + RSA_PRV_DER_MAX_BYTES : ECP_PRV_DER_MAX_BYTES + +int mbedtls_pk_write_pubkey_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[PUB_DER_MAX_BYTES]; + size_t olen = 0; + + if( ( ret = mbedtls_pk_write_pubkey_der( key, output_buf, + sizeof(output_buf) ) ) < 0 ) + { + return( ret ); + } + + if( ( ret = mbedtls_pem_write_buffer( PEM_BEGIN_PUBLIC_KEY, PEM_END_PUBLIC_KEY, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} + +int mbedtls_pk_write_key_pem( mbedtls_pk_context *key, unsigned char *buf, size_t size ) +{ + int ret; + unsigned char output_buf[PRV_DER_MAX_BYTES]; + const char *begin, *end; + size_t olen = 0; + + if( ( ret = mbedtls_pk_write_key_der( key, output_buf, sizeof(output_buf) ) ) < 0 ) + return( ret ); + +#if defined(MBEDTLS_RSA_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_RSA ) + { + begin = PEM_BEGIN_PRIVATE_KEY_RSA; + end = PEM_END_PRIVATE_KEY_RSA; + } + else +#endif +#if defined(MBEDTLS_ECP_C) + if( mbedtls_pk_get_type( key ) == MBEDTLS_PK_ECKEY ) + { + begin = PEM_BEGIN_PRIVATE_KEY_EC; + end = PEM_END_PRIVATE_KEY_EC; + } + else +#endif + return( MBEDTLS_ERR_PK_FEATURE_UNAVAILABLE ); + + if( ( ret = mbedtls_pem_write_buffer( begin, end, + output_buf + sizeof(output_buf) - ret, + ret, buf, size, &olen ) ) != 0 ) + { + return( ret ); + } + + return( 0 ); +} +#endif /* MBEDTLS_PEM_WRITE_C */ + +#endif /* MBEDTLS_PK_WRITE_C */ From 7b64e8d38f08e427c13abcbd05cedc4238f200fc Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Nov 2018 19:06:30 +0200 Subject: [PATCH 0160/1938] small fix --- client/cmdhffido.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 9a01705fc..ab42abc95 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -207,7 +207,7 @@ int CmdHFFidoRegister(const char *cmd) { void* argtable[] = { arg_param_begin, arg_lit0("aA", "apdu", "show APDU reqests and responses"), - arg_lit0("vV", "verbose", "show technical data. vv - show full certificates data"), + arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"), arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."), arg_str0(NULL, NULL, "", NULL), From 1b4e26fc9c0e85f875d2408834011acceedbcb19 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Nov 2018 19:22:10 +0200 Subject: [PATCH 0161/1938] checking certificate works + some changes in print messages --- client/cmdhffido.c | 26 ++++++++++++++++-------- client/fido/additional_ca.c | 40 ++++++++++++++++++------------------- 2 files changed, 38 insertions(+), 28 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index ab42abc95..ffd277bd2 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -327,10 +327,12 @@ int CmdHFFidoRegister(const char *cmd) { int derp = 67 + keyHandleLen; int derLen = (buf[derp + 2] << 8) + buf[derp + 3] + 4; if (verbose2) { - PrintAndLog("DER certificate[%d]:------------------DER-------------------", derLen); + PrintAndLog("DER certificate[%d]:\n------------------DER-------------------", derLen); dump_buffer_simple((const unsigned char *)&buf[67 + keyHandleLen], derLen, NULL); PrintAndLog("\n----------------DER---------------------"); } else { + if (verbose) + PrintAndLog("------------------DER-------------------"); PrintAndLog("DER certificate[%d]: %s...", derLen, sprint_hex(&buf[derp], 20)); } @@ -359,20 +361,25 @@ int CmdHFFidoRegister(const char *cmd) { // get certificate info char linfo[300] = {0}; - mbedtls_x509_crt_info(linfo, sizeof(linfo), " ", &cert); - PrintAndLog("DER certificate info:\n%s", linfo); + if (verbose) { + mbedtls_x509_crt_info(linfo, sizeof(linfo), " ", &cert); + PrintAndLog("DER certificate info:\n%s", linfo); + } // verify certificate uint32_t verifyflags = 0; - memset(linfo, 0x00, sizeof(linfo)); - res = mbedtls_x509_crt_verify(&cert, &cacert, NULL, NULL, &verifyflags, NULL, NULL); if (res) { PrintAndLog("ERROR: DER verify returned 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res)); + } else { + PrintAndLog("Certificate OK."); } - mbedtls_x509_crt_verify_info(linfo, sizeof(linfo), " ", verifyflags); - PrintAndLog("Verification info:\n%s", linfo); + if (verbose) { + memset(linfo, 0x00, sizeof(linfo)); + mbedtls_x509_crt_verify_info(linfo, sizeof(linfo), " ", verifyflags); + PrintAndLog("Verification info:\n%s", linfo); + } // get public key res = ecdsa_public_key_from_pk(&cert.pk, public_key, sizeof(public_key)); @@ -380,9 +387,12 @@ int CmdHFFidoRegister(const char *cmd) { PrintAndLog("ERROR: getting public key from certificate 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res)); } else { if (verbose) - PrintAndLog("Got a public key from certificate."); + PrintAndLog("Got a public key from certificate:\n%s", sprint_hex_inrow(public_key, 65)); } + if (verbose) + PrintAndLog("------------------DER-------------------"); + mbedtls_x509_crt_free(&cert); mbedtls_x509_crt_free(&cacert); diff --git a/client/fido/additional_ca.c b/client/fido/additional_ca.c index aeb90aa40..f529e99b5 100644 --- a/client/fido/additional_ca.c +++ b/client/fido/additional_ca.c @@ -38,26 +38,26 @@ // Name: Yubico U2F Root CA Serial 457200631 // Issued: 2014-08-01 #define YUBICO_CA \ -"-----BEGIN CERTIFICATE-----" \ -"MIIDHjCCAgagAwIBAgIEG0BT9zANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZ" \ -"dWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAw" \ -"MDBaGA8yMDUwMDkwNDAwMDAwMFowLjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290" \ -"IENBIFNlcmlhbCA0NTcyMDA2MzEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK" \ -"AoIBAQC/jwYuhBVlqaiYWEMsrWFisgJ+PtM91eSrpI4TK7U53mwCIawSDHy8vUmk" \ -"5N2KAj9abvT9NP5SMS1hQi3usxoYGonXQgfO6ZXyUA9a+KAkqdFnBnlyugSeCOep" \ -"8EdZFfsaRFtMjkwz5Gcz2Py4vIYvCdMHPtwaz0bVuzneueIEz6TnQjE63Rdt2zbw" \ -"nebwTG5ZybeWSwbzy+BJ34ZHcUhPAY89yJQXuE0IzMZFcEBbPNRbWECRKgjq//qT" \ -"9nmDOFVlSRCt2wiqPSzluwn+v+suQEBsUjTGMEd25tKXXTkNW21wIWbxeSyUoTXw" \ -"LvGS6xlwQSgNpk2qXYwf8iXg7VWZAgMBAAGjQjBAMB0GA1UdDgQWBBQgIvz0bNGJ" \ -"hjgpToksyKpP9xv9oDAPBgNVHRMECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAN" \ -"BgkqhkiG9w0BAQsFAAOCAQEAjvjuOMDSa+JXFCLyBKsycXtBVZsJ4Ue3LbaEsPY4" \ -"MYN/hIQ5ZM5p7EjfcnMG4CtYkNsfNHc0AhBLdq45rnT87q/6O3vUEtNMafbhU6kt" \ -"hX7Y+9XFN9NpmYxr+ekVY5xOxi8h9JDIgoMP4VB1uS0aunL1IGqrNooL9mmFnL2k" \ -"LVVee6/VR6C5+KSTCMCWppMuJIZII2v9o4dkoZ8Y7QRjQlLfYzd3qGtKbw7xaF1U" \ -"sG/5xUb/Btwb2X2g4InpiB/yt/3CpQXpiWX/K4mBvUKiGn05ZsqeY1gx4g0xLBqc" \ -"U9psmyPzK+Vsgw2jeRQ5JlKDyqE0hebfC1tvFu0CCrJFcw==" \ -"-----END CERTIFICATE-----" +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIDHjCCAgagAwIBAgIEG0BT9zANBgkqhkiG9w0BAQsFADAuMSwwKgYDVQQDEyNZ\r\n" \ +"dWJpY28gVTJGIFJvb3QgQ0EgU2VyaWFsIDQ1NzIwMDYzMTAgFw0xNDA4MDEwMDAw\r\n" \ +"MDBaGA8yMDUwMDkwNDAwMDAwMFowLjEsMCoGA1UEAxMjWXViaWNvIFUyRiBSb290\r\n" \ +"IENBIFNlcmlhbCA0NTcyMDA2MzEwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEK\r\n" \ +"AoIBAQC/jwYuhBVlqaiYWEMsrWFisgJ+PtM91eSrpI4TK7U53mwCIawSDHy8vUmk\r\n" \ +"5N2KAj9abvT9NP5SMS1hQi3usxoYGonXQgfO6ZXyUA9a+KAkqdFnBnlyugSeCOep\r\n" \ +"8EdZFfsaRFtMjkwz5Gcz2Py4vIYvCdMHPtwaz0bVuzneueIEz6TnQjE63Rdt2zbw\r\n" \ +"nebwTG5ZybeWSwbzy+BJ34ZHcUhPAY89yJQXuE0IzMZFcEBbPNRbWECRKgjq//qT\r\n" \ +"9nmDOFVlSRCt2wiqPSzluwn+v+suQEBsUjTGMEd25tKXXTkNW21wIWbxeSyUoTXw\r\n" \ +"LvGS6xlwQSgNpk2qXYwf8iXg7VWZAgMBAAGjQjBAMB0GA1UdDgQWBBQgIvz0bNGJ\r\n" \ +"hjgpToksyKpP9xv9oDAPBgNVHRMECDAGAQH/AgEAMA4GA1UdDwEB/wQEAwIBBjAN\r\n" \ +"BgkqhkiG9w0BAQsFAAOCAQEAjvjuOMDSa+JXFCLyBKsycXtBVZsJ4Ue3LbaEsPY4\r\n" \ +"MYN/hIQ5ZM5p7EjfcnMG4CtYkNsfNHc0AhBLdq45rnT87q/6O3vUEtNMafbhU6kt\r\n" \ +"hX7Y+9XFN9NpmYxr+ekVY5xOxi8h9JDIgoMP4VB1uS0aunL1IGqrNooL9mmFnL2k\r\n" \ +"LVVee6/VR6C5+KSTCMCWppMuJIZII2v9o4dkoZ8Y7QRjQlLfYzd3qGtKbw7xaF1U\r\n" \ +"sG/5xUb/Btwb2X2g4InpiB/yt/3CpQXpiWX/K4mBvUKiGn05ZsqeY1gx4g0xLBqc\r\n" \ +"U9psmyPzK+Vsgw2jeRQ5JlKDyqE0hebfC1tvFu0CCrJFcw==\r\n" \ +"-----END CERTIFICATE-----\r\n" /* Concatenation of all additional CA certificates in PEM format if available */ -const char additional_ca_pem[] = YUBICO_CA; ///GLOBALSIGN_CA +const char additional_ca_pem[] = GLOBALSIGN_CA YUBICO_CA; const size_t additional_ca_pem_len = sizeof(additional_ca_pem); From 9b2c457b040f6bec579648deda806adf833ed40e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 13 Nov 2018 19:25:50 +0200 Subject: [PATCH 0162/1938] add changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 9ac0e7328..a57924d70 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -80,6 +80,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added 'hf emv' commands (@merlokk) - lots of bug fixes (many many) - Changed hf mfp security. Now it works in all the modes. (drHatson) + - Added `hf fido` commands that work with FIDO U2F authenticators (@merlokk) + - Added mbedtls instead of old polarssl (@merlokk) + - Added jansson (@merlokk) ### Fixed - Changed driver file proxmark3.inf to support both old and new Product/Vendor IDs (piwi) - Changed start sequence in Qt mode (fix: short commands hangs main Qt thread) (Merlok) From 73230c8d15ada353f6d0bc8cfcf69fde7af6b057 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 13 Nov 2018 22:29:33 +0100 Subject: [PATCH 0163/1938] chg: 'trace list 7816' - missing command chg: 'sc raw' - inverted select logic --- client/cmdhflist.c | 1 + client/cmdsmartcard.c | 4 ++-- include/mifare.h | 2 +- 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 2deab204c..14dcc6039 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -356,6 +356,7 @@ void annotateIso7816(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ case ISO7816_EXTERNAL_AUTHENTICATION :snprintf(exp, size, "EXTERNAL AUTH");break; case ISO7816_GET_CHALLENGE :snprintf(exp, size, "GET CHALLENGE");break; case ISO7816_MANAGE_CHANNEL :snprintf(exp, size, "MANAGE CHANNEL");break; + case ISO7816_GETSTATUS :snprintf(exp, size, "GET RESPONSE");break; default :snprintf(exp,size,"?"); break; } } diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index a7b45c51d..c9997f241 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -200,8 +200,8 @@ int CmdSmartRaw(const char *Cmd) { if (active || active_select) { c.arg[0] |= SC_CONNECT; - if (active) - c.arg[0] |= SC_NO_SELECT; + if (active_select) + c.arg[0] |= SC_SELECT; } if (hexlen > 0) { diff --git a/include/mifare.h b/include/mifare.h index 2ab7e3741..63cdf0fb6 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -109,7 +109,7 @@ typedef enum SMARTCARD_COMMAND { SC_CONNECT = (1 << 0), SC_NO_DISCONNECT = (1 << 1), SC_RAW = (1 << 2), - SC_NO_SELECT = (1 << 3) + SC_SELECT = (1 << 3) } smartcard_command_t; //----------------------------------------------------------------------------- From bac3ad077e9afcef280f5949563f1e0eca832565 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 14 Nov 2018 09:05:08 +0100 Subject: [PATCH 0164/1938] FIX: 'standalone mode colinrun' - buffer overrun (thanks @angelsl) https://github.com/angelsl/proxmark3/commit/1aa974fc705fa98023b5ede677cf6a3e67cdaf4d --- armsrc/Standalone/hf_colin.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index c91c05766..31519080a 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -469,8 +469,8 @@ failtag: else { /* BRACE YOURSELF : AS LONG AS WE TRAP A KNOWN KEY, WE STOP CHECKING AND ENFORCE KNOWN SCHEMES */ - // uint8_t tosendkey[12]; - char tosendkey[12]; + // uint8_t tosendkey[13]; + char tosendkey[13]; num_to_bytes(key64, 6, foundKey[type][sec]); cjSetCursRight(); DbprintfEx(FLAG_NOLOG, "SEC: %02x ; KEY : %012" PRIx64 " ; TYP: %i", sec, key64, type); From b9974e1224076ef0f22ca0e8472b0cd36703d353 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 14 Nov 2018 11:24:21 +0200 Subject: [PATCH 0165/1938] mfu --- client/cmdhfmfu.c | 10 +++++----- client/cmdhfmfu.h | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 7c8ce064a..f1d0d3979 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -2441,10 +2441,10 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ mix[6] = block ^ uid[2]; mix[7] = uid[3]; - des3_context ctx = { 0x00 }; - des3_set2key_enc(&ctx, masterkey); + mbedtls_des3_context ctx = { 0x00 }; + mbedtls_des3_set2key_enc(&ctx, masterkey); - des3_crypt_cbc(&ctx // des3_context + mbedtls_des3_crypt_cbc(&ctx // des3_context , DES_ENCRYPT // int mode , sizeof(mix) // length , iv // iv[8] @@ -2478,9 +2478,9 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ memcpy(dmkey+16, dkeyA, 8); memset(iv, 0x00, 8); - des3_set3key_enc(&ctx, dmkey); + mbedtls_des3_set3key_enc(&ctx, dmkey); - des3_crypt_cbc(&ctx // des3_context + mbedtls_des3_crypt_cbc(&ctx // des3_context , DES_ENCRYPT // int mode , sizeof(newpwd) // length , iv // iv[8] diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index 2e07bae80..491218b1b 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -3,7 +3,7 @@ #include #include -#include "des.h" +#include "mbedtls/des.h" #include "cmdhfmf.h" #include "cmdhf14a.h" #include "mifare.h" From 586cbd2137e48b764f42483c31c5273d2315fdea Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 14 Nov 2018 11:33:45 +0200 Subject: [PATCH 0166/1938] hiclass --- client/cmdhficlass.c | 12 ++++++------ client/cmdhficlass.h | 2 +- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 1f0204ba0..0c9d67d6e 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -766,8 +766,8 @@ int CmdHFiClassDecrypt(const char *Cmd) { hdr->csn[4],hdr->csn[5],hdr->csn[6],hdr->csn[7]); // tripledes - des3_context ctx = { DES_DECRYPT ,{ 0 } }; - des3_set2key_dec( &ctx, key); + mbedtls_des3_context ctx = { 0 }; + mbedtls_des3_set2key_dec( &ctx, key); uint8_t enc_dump[8] = {0}; uint8_t empty[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; @@ -778,7 +778,7 @@ int CmdHFiClassDecrypt(const char *Cmd) { // block 7 or higher, and not empty 0xFF if(blocknum > 6 && memcmp(enc_dump, empty, 8) != 0 ) { - des3_crypt_ecb(&ctx, enc_dump, decrypted + idx ); + mbedtls_des3_crypt_ecb(&ctx, enc_dump, decrypted + idx ); } } @@ -797,10 +797,10 @@ static int iClassEncryptBlkData(uint8_t *blkData) { PrintAndLogEx(SUCCESS, "decryption file found"); uint8_t encryptedData[16]; uint8_t *encrypted = encryptedData; - des3_context ctx = { DES_DECRYPT ,{ 0 } }; - des3_set2key_enc( &ctx, key); + mbedtls_des3_context ctx = { 0 }; + mbedtls_des3_set2key_enc( &ctx, key); - des3_crypt_ecb(&ctx, blkData,encrypted); + mbedtls_des3_crypt_ecb(&ctx, blkData,encrypted); memcpy(blkData,encrypted,8); return 1; } diff --git a/client/cmdhficlass.h b/client/cmdhficlass.h index c53e88f49..f9353ed1f 100644 --- a/client/cmdhficlass.h +++ b/client/cmdhficlass.h @@ -22,7 +22,7 @@ #include "common.h" #include "util.h" #include "comms.h" -#include "des.h" +#include "mbedtls/des.h" #include "loclass/cipherutils.h" #include "loclass/cipher.h" #include "loclass/ikeys.h" From 0ef9b609dc82b33b80b044aa77718679d3543124 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 14 Nov 2018 11:33:59 +0200 Subject: [PATCH 0167/1938] mfu --- client/cmdhfmfu.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index f1d0d3979..72c4be573 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -2445,7 +2445,7 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ mbedtls_des3_set2key_enc(&ctx, masterkey); mbedtls_des3_crypt_cbc(&ctx // des3_context - , DES_ENCRYPT // int mode + , MBEDTLS_DES_ENCRYPT // int mode , sizeof(mix) // length , iv // iv[8] , mix // input @@ -2481,7 +2481,7 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ mbedtls_des3_set3key_enc(&ctx, dmkey); mbedtls_des3_crypt_cbc(&ctx // des3_context - , DES_ENCRYPT // int mode + , MBEDTLS_DES_ENCRYPT // int mode , sizeof(newpwd) // length , iv // iv[8] , zeros // input From 82b6a2cd5b34c29be8204c47943d97fec973527f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 14 Nov 2018 11:34:20 +0200 Subject: [PATCH 0168/1938] ikeys --- client/loclass/ikeys.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/client/loclass/ikeys.c b/client/loclass/ikeys.c index 6436a4e2d..6a68d80b1 100644 --- a/client/loclass/ikeys.c +++ b/client/loclass/ikeys.c @@ -65,12 +65,12 @@ From "Dismantling iclass": #include #include "fileutils.h" #include "cipherutils.h" -#include "des.h" +#include "mbedtls/des.h" uint8_t pi[35] = {0x0F,0x17,0x1B,0x1D,0x1E,0x27,0x2B,0x2D,0x2E,0x33,0x35,0x39,0x36,0x3A,0x3C,0x47,0x4B,0x4D,0x4E,0x53,0x55,0x56,0x59,0x5A,0x5C,0x63,0x65,0x66,0x69,0x6A,0x6C,0x71,0x72,0x74,0x78}; -static des_context ctx_enc = {DES_ENCRYPT,{0}}; -static des_context ctx_dec = {DES_DECRYPT,{0}}; +static mbedtls_des_context ctx_enc = {0}; +static mbedtls_des_context ctx_dec = {0}; static int debug_print = 0; @@ -370,12 +370,12 @@ void hash0(uint64_t c, uint8_t k[8]) void diversifyKey(uint8_t csn[8], uint8_t key[8], uint8_t div_key[8]) { // Prepare the DES key - des_setkey_enc( &ctx_enc, key); + mbedtls_des_setkey_enc( &ctx_enc, key); uint8_t crypted_csn[8] = {0}; // Calculate DES(CSN, KEY) - des_crypt_ecb(&ctx_enc,csn, crypted_csn); + mbedtls_des_crypt_ecb(&ctx_enc,csn, crypted_csn); //Calculate HASH0(DES)) uint64_t crypt_csn = x_bytes_to_num(crypted_csn, 8); @@ -437,13 +437,13 @@ typedef struct uint8_t div_key[8]; } Testcase; -int testDES(Testcase testcase, des_context ctx_enc, des_context ctx_dec) +int testDES(Testcase testcase, mbedtls_des_context ctx_enc, mbedtls_des_context ctx_dec) { uint8_t des_encrypted_csn[8] = {0}; uint8_t decrypted[8] = {0}; uint8_t div_key[8] = {0}; - int retval = des_crypt_ecb(&ctx_enc,testcase.uid,des_encrypted_csn); - retval |= des_crypt_ecb(&ctx_dec,des_encrypted_csn,decrypted); + int retval = mbedtls_des_crypt_ecb(&ctx_enc,testcase.uid,des_encrypted_csn); + retval |= mbedtls_des_crypt_ecb(&ctx_dec,des_encrypted_csn,decrypted); if(memcmp(testcase.uid,decrypted,8) != 0) { @@ -629,7 +629,7 @@ int testDES2(uint64_t csn, uint64_t expected) { print64bits(" csn ", csn); x_num_to_bytes(csn, 8,input); - des_crypt_ecb(&ctx_enc,input, result); + mbedtls_des_crypt_ecb(&ctx_enc,input, result); uint64_t crypt_csn = x_bytes_to_num(result, 8); print64bits(" {csn} ", crypt_csn ); @@ -654,7 +654,7 @@ int doTestsWithKnownInputs() { PrintAndLogDevice(SUCCESS, "Testing DES encryption"); uint8_t key[8] = {0x6c,0x8d,0x44,0xf9,0x2a,0x2d,0x01,0xbf}; - des_setkey_enc( &ctx_enc, key); + mbedtls_des_setkey_enc( &ctx_enc, key); testDES2(0xbbbbaaaabbbbeeee,0xd6ad3ca619659e6b); PrintAndLogDevice(SUCCESS, "Testing hashing algorithm"); @@ -712,8 +712,8 @@ int doKeyTests(uint8_t debuglevel) { PrintAndLogDevice(SUCCESS, "Key present"); PrintAndLogDevice(SUCCESS, "Checking key parity..."); des_checkParity(key); - des_setkey_enc( &ctx_enc, key); - des_setkey_dec( &ctx_dec, key); + mbedtls_des_setkey_enc( &ctx_enc, key); + mbedtls_des_setkey_dec( &ctx_dec, key); // Test hashing functions PrintAndLogDevice(SUCCESS, "The following tests require the correct 8-byte master key"); testKeyDiversificationWithMasterkeyTestcases(); From 500645badffff387118ae091818641c46fc922de Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 14 Nov 2018 11:41:03 +0200 Subject: [PATCH 0169/1938] elite_crack --- client/loclass/elite_crack.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/client/loclass/elite_crack.c b/client/loclass/elite_crack.c index e24a9765e..068fdf59f 100644 --- a/client/loclass/elite_crack.c +++ b/client/loclass/elite_crack.c @@ -45,7 +45,7 @@ #include "ikeys.h" #include "elite_crack.h" #include "fileutils.h" -#include "des.h" +#include "mbedtls/des.h" #include "util_posix.h" /** @@ -172,21 +172,21 @@ void rk(uint8_t *key, uint8_t n, uint8_t *outp_key) { return; } -static des_context ctx_enc = {DES_ENCRYPT,{0}}; -static des_context ctx_dec = {DES_DECRYPT,{0}}; +static mbedtls_des_context ctx_enc = {0}; +static mbedtls_des_context ctx_dec = {0}; void desdecrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) { uint8_t key_std_format[8] = {0}; permutekey_rev(iclass_key, key_std_format); - des_setkey_dec( &ctx_dec, key_std_format); - des_crypt_ecb(&ctx_dec,input,output); + mbedtls_des_setkey_dec( &ctx_dec, key_std_format); + mbedtls_des_crypt_ecb(&ctx_dec,input,output); } void desencrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) { uint8_t key_std_format[8] = {0}; permutekey_rev(iclass_key, key_std_format); - des_setkey_enc( &ctx_enc, key_std_format); - des_crypt_ecb(&ctx_enc,input,output); + mbedtls_des_setkey_enc( &ctx_enc, key_std_format); + mbedtls_des_crypt_ecb(&ctx_enc,input,output); } /** @@ -431,7 +431,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) { * @return 0 for ok, 1 for failz */ int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[] ){ - des_context ctx_e = {DES_ENCRYPT,{0}}; + mbedtls_des_context ctx_e = {0}; uint8_t z_0[8] = {0}; uint8_t y_0[8] = {0}; @@ -450,8 +450,8 @@ int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[] ){ permutekey_rev(z_0, z_0_rev); // ~K_cus = DESenc(z[0], y[0]) - des_setkey_enc( &ctx_e, z_0_rev ); - des_crypt_ecb(&ctx_e, y_0, key64_negated); + mbedtls_des_setkey_enc( &ctx_e, z_0_rev ); + mbedtls_des_crypt_ecb(&ctx_e, y_0, key64_negated); int i; for (i = 0; i < 8 ; i++) @@ -462,8 +462,8 @@ int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[] ){ uint8_t key64_stdformat[8] = {0}; permutekey_rev(key64, key64_stdformat); - des_setkey_enc( &ctx_e, key64_stdformat ); - des_crypt_ecb(&ctx_e, key64_negated, result); + mbedtls_des_setkey_enc( &ctx_e, key64_stdformat ); + mbedtls_des_crypt_ecb(&ctx_e, key64_negated, result); PrintAndLogDevice(NORMAL, "\n"); PrintAndLogDevice(SUCCESS, "-- High security custom key (Kcus) --"); printvar("[+] Standard format ", key64_stdformat, 8); printvar("[+] iClass format ", key64, 8); From 84efb3256be42f5d6a73a03bd420a0a48f397452 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 14 Nov 2018 11:41:18 +0200 Subject: [PATCH 0170/1938] makefile --- client/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/client/Makefile b/client/Makefile index 60217101a..85f1648f1 100644 --- a/client/Makefile +++ b/client/Makefile @@ -108,7 +108,6 @@ CMDSRCS = crapto1/crapto1.c \ mfkey.c \ tea.c \ fido/additional_ca.c \ - polarssl/des.c \ crypto/libpcrypto.c\ crypto/asn1utils.c\ cliparser/argtable3.c\ From 65923701f30cdce8e97d0f843b6e270169971583 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 14 Nov 2018 11:44:33 +0200 Subject: [PATCH 0171/1938] delete old files --- client/obj/polarssl/.dummy | 0 common/polarssl/des.c | 1014 -------------- common/polarssl/des.h | 281 ---- common/polarssl/polarssl_config.h | 2179 ----------------------------- 4 files changed, 3474 deletions(-) delete mode 100644 client/obj/polarssl/.dummy delete mode 100644 common/polarssl/des.c delete mode 100644 common/polarssl/des.h delete mode 100644 common/polarssl/polarssl_config.h diff --git a/client/obj/polarssl/.dummy b/client/obj/polarssl/.dummy deleted file mode 100644 index e69de29bb..000000000 diff --git a/common/polarssl/des.c b/common/polarssl/des.c deleted file mode 100644 index b33deb6c6..000000000 --- a/common/polarssl/des.c +++ /dev/null @@ -1,1014 +0,0 @@ -/* - * FIPS-46-3 compliant Triple-DES implementation - * - * Copyright (C) 2006-2014, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * 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. - */ -/* - * DES, on which TDES is based, was originally designed by Horst Feistel - * at IBM in 1974, and was adopted as a standard by NIST (formerly NBS). - * - * http://csrc.nist.gov/publications/fips/fips46-3/fips46-3.pdf - */ - -#include "polarssl_config.h" -#define POLARSSL_DES_C - -#if defined(POLARSSL_DES_C) - -#include "des.h" - -#if defined(POLARSSL_PLATFORM_C) -#include "polarssl/platform.h" -#else -#define polarssl_printf printf -#endif - -#if !defined(POLARSSL_DES_ALT) - -/* - * 32-bit integer manipulation macros (big endian) - */ -#ifndef GET_UINT32_BE -#define GET_UINT32_BE(n,b,i) \ -{ \ - (n) = ( (uint32_t) (b)[(i) ] << 24 ) \ - | ( (uint32_t) (b)[(i) + 1] << 16 ) \ - | ( (uint32_t) (b)[(i) + 2] << 8 ) \ - | ( (uint32_t) (b)[(i) + 3] ); \ -} -#endif - -#ifndef PUT_UINT32_BE -#define PUT_UINT32_BE(n,b,i) \ -{ \ - (b)[(i) ] = (unsigned char) ( (n) >> 24 ); \ - (b)[(i) + 1] = (unsigned char) ( (n) >> 16 ); \ - (b)[(i) + 2] = (unsigned char) ( (n) >> 8 ); \ - (b)[(i) + 3] = (unsigned char) ( (n) ); \ -} -#endif - -/* - * Expanded DES S-boxes - */ -static const uint32_t SB1[64] = -{ - 0x01010400, 0x00000000, 0x00010000, 0x01010404, - 0x01010004, 0x00010404, 0x00000004, 0x00010000, - 0x00000400, 0x01010400, 0x01010404, 0x00000400, - 0x01000404, 0x01010004, 0x01000000, 0x00000004, - 0x00000404, 0x01000400, 0x01000400, 0x00010400, - 0x00010400, 0x01010000, 0x01010000, 0x01000404, - 0x00010004, 0x01000004, 0x01000004, 0x00010004, - 0x00000000, 0x00000404, 0x00010404, 0x01000000, - 0x00010000, 0x01010404, 0x00000004, 0x01010000, - 0x01010400, 0x01000000, 0x01000000, 0x00000400, - 0x01010004, 0x00010000, 0x00010400, 0x01000004, - 0x00000400, 0x00000004, 0x01000404, 0x00010404, - 0x01010404, 0x00010004, 0x01010000, 0x01000404, - 0x01000004, 0x00000404, 0x00010404, 0x01010400, - 0x00000404, 0x01000400, 0x01000400, 0x00000000, - 0x00010004, 0x00010400, 0x00000000, 0x01010004 -}; - -static const uint32_t SB2[64] = -{ - 0x80108020, 0x80008000, 0x00008000, 0x00108020, - 0x00100000, 0x00000020, 0x80100020, 0x80008020, - 0x80000020, 0x80108020, 0x80108000, 0x80000000, - 0x80008000, 0x00100000, 0x00000020, 0x80100020, - 0x00108000, 0x00100020, 0x80008020, 0x00000000, - 0x80000000, 0x00008000, 0x00108020, 0x80100000, - 0x00100020, 0x80000020, 0x00000000, 0x00108000, - 0x00008020, 0x80108000, 0x80100000, 0x00008020, - 0x00000000, 0x00108020, 0x80100020, 0x00100000, - 0x80008020, 0x80100000, 0x80108000, 0x00008000, - 0x80100000, 0x80008000, 0x00000020, 0x80108020, - 0x00108020, 0x00000020, 0x00008000, 0x80000000, - 0x00008020, 0x80108000, 0x00100000, 0x80000020, - 0x00100020, 0x80008020, 0x80000020, 0x00100020, - 0x00108000, 0x00000000, 0x80008000, 0x00008020, - 0x80000000, 0x80100020, 0x80108020, 0x00108000 -}; - -static const uint32_t SB3[64] = -{ - 0x00000208, 0x08020200, 0x00000000, 0x08020008, - 0x08000200, 0x00000000, 0x00020208, 0x08000200, - 0x00020008, 0x08000008, 0x08000008, 0x00020000, - 0x08020208, 0x00020008, 0x08020000, 0x00000208, - 0x08000000, 0x00000008, 0x08020200, 0x00000200, - 0x00020200, 0x08020000, 0x08020008, 0x00020208, - 0x08000208, 0x00020200, 0x00020000, 0x08000208, - 0x00000008, 0x08020208, 0x00000200, 0x08000000, - 0x08020200, 0x08000000, 0x00020008, 0x00000208, - 0x00020000, 0x08020200, 0x08000200, 0x00000000, - 0x00000200, 0x00020008, 0x08020208, 0x08000200, - 0x08000008, 0x00000200, 0x00000000, 0x08020008, - 0x08000208, 0x00020000, 0x08000000, 0x08020208, - 0x00000008, 0x00020208, 0x00020200, 0x08000008, - 0x08020000, 0x08000208, 0x00000208, 0x08020000, - 0x00020208, 0x00000008, 0x08020008, 0x00020200 -}; - -static const uint32_t SB4[64] = -{ - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802080, 0x00800081, 0x00800001, 0x00002001, - 0x00000000, 0x00802000, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00800080, 0x00800001, - 0x00000001, 0x00002000, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002001, 0x00002080, - 0x00800081, 0x00000001, 0x00002080, 0x00800080, - 0x00002000, 0x00802080, 0x00802081, 0x00000081, - 0x00800080, 0x00800001, 0x00802000, 0x00802081, - 0x00000081, 0x00000000, 0x00000000, 0x00802000, - 0x00002080, 0x00800080, 0x00800081, 0x00000001, - 0x00802001, 0x00002081, 0x00002081, 0x00000080, - 0x00802081, 0x00000081, 0x00000001, 0x00002000, - 0x00800001, 0x00002001, 0x00802080, 0x00800081, - 0x00002001, 0x00002080, 0x00800000, 0x00802001, - 0x00000080, 0x00800000, 0x00002000, 0x00802080 -}; - -static const uint32_t SB5[64] = -{ - 0x00000100, 0x02080100, 0x02080000, 0x42000100, - 0x00080000, 0x00000100, 0x40000000, 0x02080000, - 0x40080100, 0x00080000, 0x02000100, 0x40080100, - 0x42000100, 0x42080000, 0x00080100, 0x40000000, - 0x02000000, 0x40080000, 0x40080000, 0x00000000, - 0x40000100, 0x42080100, 0x42080100, 0x02000100, - 0x42080000, 0x40000100, 0x00000000, 0x42000000, - 0x02080100, 0x02000000, 0x42000000, 0x00080100, - 0x00080000, 0x42000100, 0x00000100, 0x02000000, - 0x40000000, 0x02080000, 0x42000100, 0x40080100, - 0x02000100, 0x40000000, 0x42080000, 0x02080100, - 0x40080100, 0x00000100, 0x02000000, 0x42080000, - 0x42080100, 0x00080100, 0x42000000, 0x42080100, - 0x02080000, 0x00000000, 0x40080000, 0x42000000, - 0x00080100, 0x02000100, 0x40000100, 0x00080000, - 0x00000000, 0x40080000, 0x02080100, 0x40000100 -}; - -static const uint32_t SB6[64] = -{ - 0x20000010, 0x20400000, 0x00004000, 0x20404010, - 0x20400000, 0x00000010, 0x20404010, 0x00400000, - 0x20004000, 0x00404010, 0x00400000, 0x20000010, - 0x00400010, 0x20004000, 0x20000000, 0x00004010, - 0x00000000, 0x00400010, 0x20004010, 0x00004000, - 0x00404000, 0x20004010, 0x00000010, 0x20400010, - 0x20400010, 0x00000000, 0x00404010, 0x20404000, - 0x00004010, 0x00404000, 0x20404000, 0x20000000, - 0x20004000, 0x00000010, 0x20400010, 0x00404000, - 0x20404010, 0x00400000, 0x00004010, 0x20000010, - 0x00400000, 0x20004000, 0x20000000, 0x00004010, - 0x20000010, 0x20404010, 0x00404000, 0x20400000, - 0x00404010, 0x20404000, 0x00000000, 0x20400010, - 0x00000010, 0x00004000, 0x20400000, 0x00404010, - 0x00004000, 0x00400010, 0x20004010, 0x00000000, - 0x20404000, 0x20000000, 0x00400010, 0x20004010 -}; - -static const uint32_t SB7[64] = -{ - 0x00200000, 0x04200002, 0x04000802, 0x00000000, - 0x00000800, 0x04000802, 0x00200802, 0x04200800, - 0x04200802, 0x00200000, 0x00000000, 0x04000002, - 0x00000002, 0x04000000, 0x04200002, 0x00000802, - 0x04000800, 0x00200802, 0x00200002, 0x04000800, - 0x04000002, 0x04200000, 0x04200800, 0x00200002, - 0x04200000, 0x00000800, 0x00000802, 0x04200802, - 0x00200800, 0x00000002, 0x04000000, 0x00200800, - 0x04000000, 0x00200800, 0x00200000, 0x04000802, - 0x04000802, 0x04200002, 0x04200002, 0x00000002, - 0x00200002, 0x04000000, 0x04000800, 0x00200000, - 0x04200800, 0x00000802, 0x00200802, 0x04200800, - 0x00000802, 0x04000002, 0x04200802, 0x04200000, - 0x00200800, 0x00000000, 0x00000002, 0x04200802, - 0x00000000, 0x00200802, 0x04200000, 0x00000800, - 0x04000002, 0x04000800, 0x00000800, 0x00200002 -}; - -static const uint32_t SB8[64] = -{ - 0x10001040, 0x00001000, 0x00040000, 0x10041040, - 0x10000000, 0x10001040, 0x00000040, 0x10000000, - 0x00040040, 0x10040000, 0x10041040, 0x00041000, - 0x10041000, 0x00041040, 0x00001000, 0x00000040, - 0x10040000, 0x10000040, 0x10001000, 0x00001040, - 0x00041000, 0x00040040, 0x10040040, 0x10041000, - 0x00001040, 0x00000000, 0x00000000, 0x10040040, - 0x10000040, 0x10001000, 0x00041040, 0x00040000, - 0x00041040, 0x00040000, 0x10041000, 0x00001000, - 0x00000040, 0x10040040, 0x00001000, 0x00041040, - 0x10001000, 0x00000040, 0x10000040, 0x10040000, - 0x10040040, 0x10000000, 0x00040000, 0x10001040, - 0x00000000, 0x10041040, 0x00040040, 0x10000040, - 0x10040000, 0x10001000, 0x10001040, 0x00000000, - 0x10041040, 0x00041000, 0x00041000, 0x00001040, - 0x00001040, 0x00040040, 0x10000000, 0x10041000 -}; - -/* - * PC1: left and right halves bit-swap - */ -static const uint32_t LHs[16] = -{ - 0x00000000, 0x00000001, 0x00000100, 0x00000101, - 0x00010000, 0x00010001, 0x00010100, 0x00010101, - 0x01000000, 0x01000001, 0x01000100, 0x01000101, - 0x01010000, 0x01010001, 0x01010100, 0x01010101 -}; - -static const uint32_t RHs[16] = -{ - 0x00000000, 0x01000000, 0x00010000, 0x01010000, - 0x00000100, 0x01000100, 0x00010100, 0x01010100, - 0x00000001, 0x01000001, 0x00010001, 0x01010001, - 0x00000101, 0x01000101, 0x00010101, 0x01010101, -}; - -/* - * Initial Permutation macro - */ -#define DES_IP(X,Y) \ -{ \ - T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ - T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ - T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ - T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ - Y = ((Y << 1) | (Y >> 31)) & 0xFFFFFFFF; \ - T = (X ^ Y) & 0xAAAAAAAA; Y ^= T; X ^= T; \ - X = ((X << 1) | (X >> 31)) & 0xFFFFFFFF; \ -} - -/* - * Final Permutation macro - */ -#define DES_FP(X,Y) \ -{ \ - X = ((X << 31) | (X >> 1)) & 0xFFFFFFFF; \ - T = (X ^ Y) & 0xAAAAAAAA; X ^= T; Y ^= T; \ - Y = ((Y << 31) | (Y >> 1)) & 0xFFFFFFFF; \ - T = ((Y >> 8) ^ X) & 0x00FF00FF; X ^= T; Y ^= (T << 8); \ - T = ((Y >> 2) ^ X) & 0x33333333; X ^= T; Y ^= (T << 2); \ - T = ((X >> 16) ^ Y) & 0x0000FFFF; Y ^= T; X ^= (T << 16); \ - T = ((X >> 4) ^ Y) & 0x0F0F0F0F; Y ^= T; X ^= (T << 4); \ -} - -/* - * DES round macro - */ -#define DES_ROUND(X,Y) \ -{ \ - T = *SK++ ^ X; \ - Y ^= SB8[ (T ) & 0x3F ] ^ \ - SB6[ (T >> 8) & 0x3F ] ^ \ - SB4[ (T >> 16) & 0x3F ] ^ \ - SB2[ (T >> 24) & 0x3F ]; \ - \ - T = *SK++ ^ ((X << 28) | (X >> 4)); \ - Y ^= SB7[ (T ) & 0x3F ] ^ \ - SB5[ (T >> 8) & 0x3F ] ^ \ - SB3[ (T >> 16) & 0x3F ] ^ \ - SB1[ (T >> 24) & 0x3F ]; \ -} - -#define SWAP(a,b) { uint32_t t = a; a = b; b = t; t = 0; } - -static const unsigned char odd_parity_table[128] = { 1, 2, 4, 7, 8, - 11, 13, 14, 16, 19, 21, 22, 25, 26, 28, 31, 32, 35, 37, 38, 41, 42, 44, - 47, 49, 50, 52, 55, 56, 59, 61, 62, 64, 67, 69, 70, 73, 74, 76, 79, 81, - 82, 84, 87, 88, 91, 93, 94, 97, 98, 100, 103, 104, 107, 109, 110, 112, - 115, 117, 118, 121, 122, 124, 127, 128, 131, 133, 134, 137, 138, 140, - 143, 145, 146, 148, 151, 152, 155, 157, 158, 161, 162, 164, 167, 168, - 171, 173, 174, 176, 179, 181, 182, 185, 186, 188, 191, 193, 194, 196, - 199, 200, 203, 205, 206, 208, 211, 213, 214, 217, 218, 220, 223, 224, - 227, 229, 230, 233, 234, 236, 239, 241, 242, 244, 247, 248, 251, 253, - 254 }; - -void des_key_set_parity( unsigned char key[DES_KEY_SIZE] ) -{ - int i; - - for( i = 0; i < DES_KEY_SIZE; i++ ) - key[i] = odd_parity_table[key[i] / 2]; -} - -/* - * Check the given key's parity, returns 1 on failure, 0 on SUCCESS - */ -int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] ) -{ - int i; - - for( i = 0; i < DES_KEY_SIZE; i++ ) - if ( key[i] != odd_parity_table[key[i] / 2] ) - return( 1 ); - - return( 0 ); -} - -/* - * Table of weak and semi-weak keys - * - * Source: http://en.wikipedia.org/wiki/Weak_key - * - * Weak: - * Alternating ones + zeros (0x0101010101010101) - * Alternating 'F' + 'E' (0xFEFEFEFEFEFEFEFE) - * '0xE0E0E0E0F1F1F1F1' - * '0x1F1F1F1F0E0E0E0E' - * - * Semi-weak: - * 0x011F011F010E010E and 0x1F011F010E010E01 - * 0x01E001E001F101F1 and 0xE001E001F101F101 - * 0x01FE01FE01FE01FE and 0xFE01FE01FE01FE01 - * 0x1FE01FE00EF10EF1 and 0xE01FE01FF10EF10E - * 0x1FFE1FFE0EFE0EFE and 0xFE1FFE1FFE0EFE0E - * 0xE0FEE0FEF1FEF1FE and 0xFEE0FEE0FEF1FEF1 - * - */ - -#define WEAK_KEY_COUNT 16 - -static const unsigned char weak_key_table[WEAK_KEY_COUNT][DES_KEY_SIZE] = -{ - { 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01 }, - { 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE, 0xFE }, - { 0x1F, 0x1F, 0x1F, 0x1F, 0x0E, 0x0E, 0x0E, 0x0E }, - { 0xE0, 0xE0, 0xE0, 0xE0, 0xF1, 0xF1, 0xF1, 0xF1 }, - - { 0x01, 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E }, - { 0x1F, 0x01, 0x1F, 0x01, 0x0E, 0x01, 0x0E, 0x01 }, - { 0x01, 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1 }, - { 0xE0, 0x01, 0xE0, 0x01, 0xF1, 0x01, 0xF1, 0x01 }, - { 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE }, - { 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01, 0xFE, 0x01 }, - { 0x1F, 0xE0, 0x1F, 0xE0, 0x0E, 0xF1, 0x0E, 0xF1 }, - { 0xE0, 0x1F, 0xE0, 0x1F, 0xF1, 0x0E, 0xF1, 0x0E }, - { 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E, 0xFE }, - { 0xFE, 0x1F, 0xFE, 0x1F, 0xFE, 0x0E, 0xFE, 0x0E }, - { 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1, 0xFE }, - { 0xFE, 0xE0, 0xFE, 0xE0, 0xFE, 0xF1, 0xFE, 0xF1 } -}; - -int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] ) -{ - int i; - - for( i = 0; i < WEAK_KEY_COUNT; i++ ) - if( memcmp( weak_key_table[i], key, DES_KEY_SIZE) == 0) - return( 1 ); - - return( 0 ); -} - -static void des_setkey( uint32_t SK[32], const unsigned char key[DES_KEY_SIZE] ) -{ - int i; - uint32_t X, Y, T; - - GET_UINT32_BE( X, key, 0 ); - GET_UINT32_BE( Y, key, 4 ); - - /* - * Permuted Choice 1 - */ - T = ((Y >> 4) ^ X) & 0x0F0F0F0F; X ^= T; Y ^= (T << 4); - T = ((Y ) ^ X) & 0x10101010; X ^= T; Y ^= (T ); - - X = (LHs[ (X ) & 0xF] << 3) | (LHs[ (X >> 8) & 0xF ] << 2) - | (LHs[ (X >> 16) & 0xF] << 1) | (LHs[ (X >> 24) & 0xF ] ) - | (LHs[ (X >> 5) & 0xF] << 7) | (LHs[ (X >> 13) & 0xF ] << 6) - | (LHs[ (X >> 21) & 0xF] << 5) | (LHs[ (X >> 29) & 0xF ] << 4); - - Y = (RHs[ (Y >> 1) & 0xF] << 3) | (RHs[ (Y >> 9) & 0xF ] << 2) - | (RHs[ (Y >> 17) & 0xF] << 1) | (RHs[ (Y >> 25) & 0xF ] ) - | (RHs[ (Y >> 4) & 0xF] << 7) | (RHs[ (Y >> 12) & 0xF ] << 6) - | (RHs[ (Y >> 20) & 0xF] << 5) | (RHs[ (Y >> 28) & 0xF ] << 4); - - X &= 0x0FFFFFFF; - Y &= 0x0FFFFFFF; - - /* - * calculate subkeys - */ - for( i = 0; i < 16; i++ ) - { - if( i < 2 || i == 8 || i == 15 ) - { - X = ((X << 1) | (X >> 27)) & 0x0FFFFFFF; - Y = ((Y << 1) | (Y >> 27)) & 0x0FFFFFFF; - } - else - { - X = ((X << 2) | (X >> 26)) & 0x0FFFFFFF; - Y = ((Y << 2) | (Y >> 26)) & 0x0FFFFFFF; - } - - *SK++ = ((X << 4) & 0x24000000) | ((X << 28) & 0x10000000) - | ((X << 14) & 0x08000000) | ((X << 18) & 0x02080000) - | ((X << 6) & 0x01000000) | ((X << 9) & 0x00200000) - | ((X >> 1) & 0x00100000) | ((X << 10) & 0x00040000) - | ((X << 2) & 0x00020000) | ((X >> 10) & 0x00010000) - | ((Y >> 13) & 0x00002000) | ((Y >> 4) & 0x00001000) - | ((Y << 6) & 0x00000800) | ((Y >> 1) & 0x00000400) - | ((Y >> 14) & 0x00000200) | ((Y ) & 0x00000100) - | ((Y >> 5) & 0x00000020) | ((Y >> 10) & 0x00000010) - | ((Y >> 3) & 0x00000008) | ((Y >> 18) & 0x00000004) - | ((Y >> 26) & 0x00000002) | ((Y >> 24) & 0x00000001); - - *SK++ = ((X << 15) & 0x20000000) | ((X << 17) & 0x10000000) - | ((X << 10) & 0x08000000) | ((X << 22) & 0x04000000) - | ((X >> 2) & 0x02000000) | ((X << 1) & 0x01000000) - | ((X << 16) & 0x00200000) | ((X << 11) & 0x00100000) - | ((X << 3) & 0x00080000) | ((X >> 6) & 0x00040000) - | ((X << 15) & 0x00020000) | ((X >> 4) & 0x00010000) - | ((Y >> 2) & 0x00002000) | ((Y << 8) & 0x00001000) - | ((Y >> 14) & 0x00000808) | ((Y >> 9) & 0x00000400) - | ((Y ) & 0x00000200) | ((Y << 7) & 0x00000100) - | ((Y >> 7) & 0x00000020) | ((Y >> 3) & 0x00000011) - | ((Y << 2) & 0x00000004) | ((Y >> 21) & 0x00000002); - } -} - -/* - * DES key schedule (56-bit, encryption) - */ -int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] ) -{ - des_setkey( ctx->sk, key ); - - return( 0 ); -} - -/* - * DES key schedule (56-bit, decryption) - */ -int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] ) -{ - int i; - - des_setkey( ctx->sk, key ); - - for( i = 0; i < 16; i += 2 ) - { - SWAP( ctx->sk[i ], ctx->sk[30 - i] ); - SWAP( ctx->sk[i + 1], ctx->sk[31 - i] ); - } - - return( 0 ); -} - -static void des3_set2key( uint32_t esk[96], - uint32_t dsk[96], - const unsigned char key[DES_KEY_SIZE*2] ) -{ - int i; - - des_setkey( esk, key ); - des_setkey( dsk + 32, key + 8 ); - - for( i = 0; i < 32; i += 2 ) - { - dsk[i ] = esk[30 - i]; - dsk[i + 1] = esk[31 - i]; - - esk[i + 32] = dsk[62 - i]; - esk[i + 33] = dsk[63 - i]; - - esk[i + 64] = esk[i ]; - esk[i + 65] = esk[i + 1]; - - dsk[i + 64] = dsk[i ]; - dsk[i + 65] = dsk[i + 1]; - } -} - -/* - * Triple-DES key schedule (112-bit, encryption) - */ -int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] ) -{ - uint32_t sk[96]; - - des3_set2key( ctx->sk, sk, key ); - memset( sk, 0, sizeof( sk ) ); - - return( 0 ); -} - -/* - * Triple-DES key schedule (112-bit, decryption) - */ -int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] ) -{ - uint32_t sk[96]; - - des3_set2key( sk, ctx->sk, key ); - memset( sk, 0, sizeof( sk ) ); - - return( 0 ); -} - -static void des3_set3key( uint32_t esk[96], - uint32_t dsk[96], - const unsigned char key[24] ) -{ - int i; - - des_setkey( esk, key ); - des_setkey( dsk + 32, key + 8 ); - des_setkey( esk + 64, key + 16 ); - - for( i = 0; i < 32; i += 2 ) - { - dsk[i ] = esk[94 - i]; - dsk[i + 1] = esk[95 - i]; - - esk[i + 32] = dsk[62 - i]; - esk[i + 33] = dsk[63 - i]; - - dsk[i + 64] = esk[30 - i]; - dsk[i + 65] = esk[31 - i]; - } -} - -/* - * Triple-DES key schedule (168-bit, encryption) - */ -int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] ) -{ - uint32_t sk[96]; - - des3_set3key( ctx->sk, sk, key ); - memset( sk, 0, sizeof( sk ) ); - - return( 0 ); -} - -/* - * Triple-DES key schedule (168-bit, decryption) - */ -int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] ) -{ - uint32_t sk[96]; - - des3_set3key( sk, ctx->sk, key ); - memset( sk, 0, sizeof( sk ) ); - - return( 0 ); -} - -/* - * DES-ECB block encryption/decryption - */ -int des_crypt_ecb( des_context *ctx, - const unsigned char input[8], - unsigned char output[8] ) -{ - int i; - uint32_t X, Y, T, *SK; - - SK = ctx->sk; - - GET_UINT32_BE( X, input, 0 ); - GET_UINT32_BE( Y, input, 4 ); - - DES_IP( X, Y ); - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( Y, X ); - DES_ROUND( X, Y ); - } - - DES_FP( Y, X ); - - PUT_UINT32_BE( Y, output, 0 ); - PUT_UINT32_BE( X, output, 4 ); - - return( 0 ); -} - -#if defined(POLARSSL_CIPHER_MODE_CBC) -/* - * DES-CBC buffer encryption/decryption - */ -int des_crypt_cbc( des_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[8]; - - if( length % 8 ) - return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH ); - - if( mode == DES_ENCRYPT ) - { - while( length > 0 ) - { - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - des_crypt_ecb( ctx, output, output ); - memcpy( iv, output, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - else /* DES_DECRYPT */ - { - while( length > 0 ) - { - memcpy( temp, input, 8 ); - des_crypt_ecb( ctx, input, output ); - - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - - return( 0 ); -} -#endif /* POLARSSL_CIPHER_MODE_CBC */ - -/* - * 3DES-ECB block encryption/decryption - */ -int des3_crypt_ecb( des3_context *ctx, - const unsigned char input[8], - unsigned char output[8] ) -{ - int i; - uint32_t X, Y, T, *SK; - - SK = ctx->sk; - - GET_UINT32_BE( X, input, 0 ); - GET_UINT32_BE( Y, input, 4 ); - - DES_IP( X, Y ); - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( Y, X ); - DES_ROUND( X, Y ); - } - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( X, Y ); - DES_ROUND( Y, X ); - } - - for( i = 0; i < 8; i++ ) - { - DES_ROUND( Y, X ); - DES_ROUND( X, Y ); - } - - DES_FP( Y, X ); - - PUT_UINT32_BE( Y, output, 0 ); - PUT_UINT32_BE( X, output, 4 ); - - return( 0 ); -} - -#if defined(POLARSSL_CIPHER_MODE_CBC) -/* - * 3DES-CBC buffer encryption/decryption - */ -int des3_crypt_cbc( des3_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ) -{ - int i; - unsigned char temp[8]; - - if( length % 8 ) - return( POLARSSL_ERR_DES_INVALID_INPUT_LENGTH ); - - if( mode == DES_ENCRYPT ) - { - while( length > 0 ) - { - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( input[i] ^ iv[i] ); - - des3_crypt_ecb( ctx, output, output ); - memcpy( iv, output, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - else /* DES_DECRYPT */ - { - while( length > 0 ) - { - memcpy( temp, input, 8 ); - des3_crypt_ecb( ctx, input, output ); - - for( i = 0; i < 8; i++ ) - output[i] = (unsigned char)( output[i] ^ iv[i] ); - - memcpy( iv, temp, 8 ); - - input += 8; - output += 8; - length -= 8; - } - } - - return( 0 ); -} -#endif /* POLARSSL_CIPHER_MODE_CBC */ - -#endif /* !POLARSSL_DES_ALT */ - -#if defined(POLARSSL_SELF_TEST) - -#include - -/* - * DES and 3DES test vectors from: - * - * http://csrc.nist.gov/groups/STM/cavp/documents/des/tripledes-vectors.zip - */ -static const unsigned char des3_test_keys[24] = -{ - 0x01, 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, - 0x23, 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, - 0x45, 0x67, 0x89, 0xAB, 0xCD, 0xEF, 0x01, 0x23 -}; - -static const unsigned char des3_test_buf[8] = -{ - 0x4E, 0x6F, 0x77, 0x20, 0x69, 0x73, 0x20, 0x74 -}; - -static const unsigned char des3_test_ecb_dec[3][8] = -{ - { 0xCD, 0xD6, 0x4F, 0x2F, 0x94, 0x27, 0xC1, 0x5D }, - { 0x69, 0x96, 0xC8, 0xFA, 0x47, 0xA2, 0xAB, 0xEB }, - { 0x83, 0x25, 0x39, 0x76, 0x44, 0x09, 0x1A, 0x0A } -}; - -static const unsigned char des3_test_ecb_enc[3][8] = -{ - { 0x6A, 0x2A, 0x19, 0xF4, 0x1E, 0xCA, 0x85, 0x4B }, - { 0x03, 0xE6, 0x9F, 0x5B, 0xFA, 0x58, 0xEB, 0x42 }, - { 0xDD, 0x17, 0xE8, 0xB8, 0xB4, 0x37, 0xD2, 0x32 } -}; - -#if defined(POLARSSL_CIPHER_MODE_CBC) -static const unsigned char des3_test_iv[8] = -{ - 0x12, 0x34, 0x56, 0x78, 0x90, 0xAB, 0xCD, 0xEF, -}; - -static const unsigned char des3_test_cbc_dec[3][8] = -{ - { 0x12, 0x9F, 0x40, 0xB9, 0xD2, 0x00, 0x56, 0xB3 }, - { 0x47, 0x0E, 0xFC, 0x9A, 0x6B, 0x8E, 0xE3, 0x93 }, - { 0xC5, 0xCE, 0xCF, 0x63, 0xEC, 0xEC, 0x51, 0x4C } -}; - -static const unsigned char des3_test_cbc_enc[3][8] = -{ - { 0x54, 0xF1, 0x5A, 0xF6, 0xEB, 0xE3, 0xA4, 0xB4 }, - { 0x35, 0x76, 0x11, 0x56, 0x5F, 0xA1, 0x8E, 0x4D }, - { 0xCB, 0x19, 0x1F, 0x85, 0xD1, 0xED, 0x84, 0x39 } -}; -#endif /* POLARSSL_CIPHER_MODE_CBC */ - -/* - * Checkup routine - */ -int des_self_test( int verbose ) -{ - int i, j, u, v; - des_context ctx; - des3_context ctx3; - unsigned char key[24]; - unsigned char buf[8]; -#if defined(POLARSSL_CIPHER_MODE_CBC) - unsigned char prv[8]; - unsigned char iv[8]; -#endif - - memset( key, 0, 24 ); - - /* - * ECB mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - polarssl_printf( " DES%c-ECB-%3d (%s): ", - ( u == 0 ) ? ' ' : '3', 56 + u * 56, - ( v == DES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( buf, des3_test_buf, 8 ); - - switch( i ) - { - case 0: - des_setkey_dec( &ctx, des3_test_keys ); - break; - - case 1: - des_setkey_enc( &ctx, des3_test_keys ); - break; - - case 2: - des3_set2key_dec( &ctx3, des3_test_keys ); - break; - - case 3: - des3_set2key_enc( &ctx3, des3_test_keys ); - break; - - case 4: - des3_set3key_dec( &ctx3, des3_test_keys ); - break; - - case 5: - des3_set3key_enc( &ctx3, des3_test_keys ); - break; - - default: - return( 1 ); - } - - for( j = 0; j < 10000; j++ ) - { - if( u == 0 ) - des_crypt_ecb( &ctx, buf, buf ); - else - des3_crypt_ecb( &ctx3, buf, buf ); - } - - if( ( v == DES_DECRYPT && - memcmp( buf, des3_test_ecb_dec[u], 8 ) != 0 ) || - ( v != DES_DECRYPT && - memcmp( buf, des3_test_ecb_enc[u], 8 ) != 0 ) ) - { - if( verbose != 0 ) - polarssl_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - polarssl_printf( "passed\n" ); - } - - if( verbose != 0 ) - polarssl_printf( "\n" ); - -#if defined(POLARSSL_CIPHER_MODE_CBC) - /* - * CBC mode - */ - for( i = 0; i < 6; i++ ) - { - u = i >> 1; - v = i & 1; - - if( verbose != 0 ) - polarssl_printf( " DES%c-CBC-%3d (%s): ", - ( u == 0 ) ? ' ' : '3', 56 + u * 56, - ( v == DES_DECRYPT ) ? "dec" : "enc" ); - - memcpy( iv, des3_test_iv, 8 ); - memcpy( prv, des3_test_iv, 8 ); - memcpy( buf, des3_test_buf, 8 ); - - switch( i ) - { - case 0: - des_setkey_dec( &ctx, des3_test_keys ); - break; - - case 1: - des_setkey_enc( &ctx, des3_test_keys ); - break; - - case 2: - des3_set2key_dec( &ctx3, des3_test_keys ); - break; - - case 3: - des3_set2key_enc( &ctx3, des3_test_keys ); - break; - - case 4: - des3_set3key_dec( &ctx3, des3_test_keys ); - break; - - case 5: - des3_set3key_enc( &ctx3, des3_test_keys ); - break; - - default: - return( 1 ); - } - - if( v == DES_DECRYPT ) - { - for( j = 0; j < 10000; j++ ) - { - if( u == 0 ) - des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); - else - des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); - } - } - else - { - for( j = 0; j < 10000; j++ ) - { - unsigned char tmp[8]; - - if( u == 0 ) - des_crypt_cbc( &ctx, v, 8, iv, buf, buf ); - else - des3_crypt_cbc( &ctx3, v, 8, iv, buf, buf ); - - memcpy( tmp, prv, 8 ); - memcpy( prv, buf, 8 ); - memcpy( buf, tmp, 8 ); - } - - memcpy( buf, prv, 8 ); - } - - if( ( v == DES_DECRYPT && - memcmp( buf, des3_test_cbc_dec[u], 8 ) != 0 ) || - ( v != DES_DECRYPT && - memcmp( buf, des3_test_cbc_enc[u], 8 ) != 0 ) ) - { - if( verbose != 0 ) - polarssl_printf( "failed\n" ); - - return( 1 ); - } - - if( verbose != 0 ) - polarssl_printf( "passed\n" ); - } -#endif /* POLARSSL_CIPHER_MODE_CBC */ - - if( verbose != 0 ) - polarssl_printf( "\n" ); - - return( 0 ); -} - -#endif - -#endif diff --git a/common/polarssl/des.h b/common/polarssl/des.h deleted file mode 100644 index 460beaf0e..000000000 --- a/common/polarssl/des.h +++ /dev/null @@ -1,281 +0,0 @@ -/** - * \file des.h - * - * \brief DES block cipher - * - * Copyright (C) 2006-2013, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - */ -#ifndef POLARSSL_DES_H -#define POLARSSL_DES_H - -//#include "config.h" -/** - * \def POLARSSL_CIPHER_MODE_CBC - * - * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. - */ -#define POLARSSL_CIPHER_MODE_CBC - -#include - -#if defined(_MSC_VER) && !defined(EFIX64) && !defined(EFI32) -#include -typedef UINT32 uint32_t; -#else -#include -#endif - -#define DES_ENCRYPT 1 -#define DES_DECRYPT 0 - -#define POLARSSL_ERR_DES_INVALID_INPUT_LENGTH -0x0032 /**< The data input has an invalid length. */ - -#define DES_KEY_SIZE 8 - -#if !defined(POLARSSL_DES_ALT) -// Regular implementation -// - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief DES context structure - */ -typedef struct -{ - int mode; /*!< encrypt/decrypt */ - uint32_t sk[32]; /*!< DES subkeys */ -} -des_context; - -/** - * \brief Triple-DES context structure - */ -typedef struct -{ - int mode; /*!< encrypt/decrypt */ - uint32_t sk[96]; /*!< 3DES subkeys */ -} -des3_context; -/* - * Triple-DES key schedule (112-bit, encryption) - */ -int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] ); - -/* - * Triple-DES key schedule (112-bit, decryption) - */ -int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] ); - -/* - * Triple-DES key schedule (168-bit, encryption) - */ -int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] ); - -/* - * Triple-DES key schedule (168-bit, decryption) - */ -int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] ); - -/** - * \brief Set key parity on the given key to odd. - * - * DES keys are 56 bits long, but each byte is padded with - * a parity bit to allow verification. - * - * \param key 8-byte secret key - */ -void des_key_set_parity( unsigned char key[DES_KEY_SIZE] ); - -/** - * \brief Check that key parity on the given key is odd. - * - * DES keys are 56 bits long, but each byte is padded with - * a parity bit to allow verification. - * - * \param key 8-byte secret key - * - * \return 0 is parity was ok, 1 if parity was not correct. - */ -int des_key_check_key_parity( const unsigned char key[DES_KEY_SIZE] ); - -/** - * \brief Check that key is not a weak or semi-weak DES key - * - * \param key 8-byte secret key - * - * \return 0 if no weak key was found, 1 if a weak key was identified. - */ -int des_key_check_weak( const unsigned char key[DES_KEY_SIZE] ); - -/** - * \brief DES key schedule (56-bit, encryption) - * - * \param ctx DES context to be initialized - * \param key 8-byte secret key - * - * \return 0 - */ -int des_setkey_enc( des_context *ctx, const unsigned char key[DES_KEY_SIZE] ); - -/** - * \brief DES key schedule (56-bit, decryption) - * - * \param ctx DES context to be initialized - * \param key 8-byte secret key - * - * \return 0 - */ -int des_setkey_dec( des_context *ctx, const unsigned char key[DES_KEY_SIZE] ); - -/** - * \brief Triple-DES key schedule (112-bit, encryption) - * - * \param ctx 3DES context to be initialized - * \param key 16-byte secret key - * - * \return 0 - */ -int des3_set2key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] ); - -/** - * \brief Triple-DES key schedule (112-bit, decryption) - * - * \param ctx 3DES context to be initialized - * \param key 16-byte secret key - * - * \return 0 - */ -int des3_set2key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 2] ); - -/** - * \brief Triple-DES key schedule (168-bit, encryption) - * - * \param ctx 3DES context to be initialized - * \param key 24-byte secret key - * - * \return 0 - */ -int des3_set3key_enc( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] ); - -/** - * \brief Triple-DES key schedule (168-bit, decryption) - * - * \param ctx 3DES context to be initialized - * \param key 24-byte secret key - * - * \return 0 - */ -int des3_set3key_dec( des3_context *ctx, const unsigned char key[DES_KEY_SIZE * 3] ); - -/** - * \brief DES-ECB block encryption/decryption - * - * \param ctx DES context - * \param input 64-bit input block - * \param output 64-bit output block - * - * \return 0 if successful - */ -int des_crypt_ecb( des_context *ctx, - const unsigned char input[8], - unsigned char output[8] ); - -#if defined(POLARSSL_CIPHER_MODE_CBC) -/** - * \brief DES-CBC buffer encryption/decryption - * - * \param ctx DES context - * \param mode DES_ENCRYPT or DES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - */ -int des_crypt_cbc( des_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ); -#endif /* POLARSSL_CIPHER_MODE_CBC */ - -/** - * \brief 3DES-ECB block encryption/decryption - * - * \param ctx 3DES context - * \param input 64-bit input block - * \param output 64-bit output block - * - * \return 0 if successful - */ -int des3_crypt_ecb( des3_context *ctx, - const unsigned char input[8], - unsigned char output[8] ); - -#if defined(POLARSSL_CIPHER_MODE_CBC) -/** - * \brief 3DES-CBC buffer encryption/decryption - * - * \param ctx 3DES context - * \param mode DES_ENCRYPT or DES_DECRYPT - * \param length length of the input data - * \param iv initialization vector (updated after use) - * \param input buffer holding the input data - * \param output buffer holding the output data - * - * \return 0 if successful, or POLARSSL_ERR_DES_INVALID_INPUT_LENGTH - */ -int des3_crypt_cbc( des3_context *ctx, - int mode, - size_t length, - unsigned char iv[8], - const unsigned char *input, - unsigned char *output ); -#endif /* POLARSSL_CIPHER_MODE_CBC */ - -#ifdef __cplusplus -} -#endif - -#else /* POLARSSL_DES_ALT */ -#include "des_alt.h" -#endif /* POLARSSL_DES_ALT */ - -#ifdef __cplusplus -extern "C" { -#endif - -/** - * \brief Checkup routine - * - * \return 0 if successful, or 1 if the test failed - */ -int des_self_test( int verbose ); - -#ifdef __cplusplus -} -#endif - -#endif /* des.h */ diff --git a/common/polarssl/polarssl_config.h b/common/polarssl/polarssl_config.h deleted file mode 100644 index 3d9a2f67d..000000000 --- a/common/polarssl/polarssl_config.h +++ /dev/null @@ -1,2179 +0,0 @@ -/** - * \file config.h - * - * \brief Configuration options (set of defines) - * - * Copyright (C) 2006-2014, Brainspark B.V. - * - * This file is part of PolarSSL (http://www.polarssl.org) - * Lead Maintainer: Paul Bakker - * - * All rights reserved. - * - * 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. - * - * This set of compile-time options may be used to enable - * or disable features selectively, and reduce the global - * memory footprint. - */ -#ifndef POLARSSL_CONFIG_H -#define POLARSSL_CONFIG_H - -#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_DEPRECATE) -#define _CRT_SECURE_NO_DEPRECATE 1 -#endif - -/** - * \name SECTION: System support - * - * This section sets system specific settings. - * \{ - */ - -/** - * \def POLARSSL_HAVE_INT8 - * - * The system uses 8-bit wide native integers. - * - * Uncomment if native integers are 8-bit wide. - */ -//#define POLARSSL_HAVE_INT8 - -/** - * \def POLARSSL_HAVE_INT16 - * - * The system uses 16-bit wide native integers. - * - * Uncomment if native integers are 16-bit wide. - */ -//#define POLARSSL_HAVE_INT16 - -/** - * \def POLARSSL_HAVE_LONGLONG - * - * The compiler supports the 'long long' type. - * (Only used on 32-bit platforms) - */ -#define POLARSSL_HAVE_LONGLONG - -/** - * \def POLARSSL_HAVE_ASM - * - * The compiler has support for asm(). - * - * Requires support for asm() in compiler. - * - * Used in: - * library/timing.c - * library/padlock.c - * include/polarssl/bn_mul.h - * - * Comment to disable the use of assembly code. - */ -//#define POLARSSL_HAVE_ASM - -/** - * \def POLARSSL_HAVE_SSE2 - * - * CPU supports SSE2 instruction set. - * - * Uncomment if the CPU supports SSE2 (IA-32 specific). - */ -//#define POLARSSL_HAVE_SSE2 - -/** - * \def POLARSSL_HAVE_TIME - * - * System has time.h and time() / localtime() / gettimeofday(). - * - * Comment if your system does not support time functions - */ -#define POLARSSL_HAVE_TIME - -/** - * \def POLARSSL_HAVE_IPV6 - * - * System supports the basic socket interface for IPv6 (RFC 3493), - * specifically getaddrinfo(), freeaddrinfo() and struct sockaddr_storage. - * - * Note: on Windows/MingW, XP or higher is required. - * - * Comment if your system does not support the IPv6 socket interface - */ -#define POLARSSL_HAVE_IPV6 - -/** - * \def POLARSSL_PLATFORM_MEMORY - * - * Enable the memory allocation layer. - * - * By default PolarSSL uses the system-provided malloc() and free(). - * This allows different allocators (self-implemented or provided) to be - * provided to the platform abstraction layer. - * - * Enabling POLARSSL_PLATFORM_MEMORY will provide "platform_set_malloc_free()" - * to allow you to set an alternative malloc() and free() function pointer. - * - * Requires: POLARSSL_PLATFORM_C - * - * Enable this layer to allow use of alternative memory allocators. - */ -//#define POLARSSL_PLATFORM_MEMORY - -/** - * \def POLARSSL_PLATFORM_NO_STD_FUNCTIONS - * - * Do not assign standard functions in the platform layer (e.g. malloc() to - * POLARSSL_PLATFORM_STD_MALLOC and printf() to POLARSSL_PLATFORM_STD_PRINTF) - * - * This makes sure there are no linking errors on platforms that do not support - * these functions. You will HAVE to provide alternatives, either at runtime - * via the platform_set_xxx() functions or at compile time by setting - * the POLARSSL_PLATFORM_STD_XXX defines. - * - * Requires: POLARSSL_PLATFORM_C - * - * Uncomment to prevent default assignment of standard functions in the - * platform layer. - */ -//#define POLARSSL_PLATFORM_NO_STD_FUNCTIONS - -/** - * \def POLARSSL_PLATFORM_XXX_ALT - * - * Uncomment a macro to let PolarSSL support the function in the platform - * abstraction layer. - * - * Example: In case you uncomment POLARSSL_PLATFORM_PRINTF_ALT, PolarSSL will - * provide a function "platform_set_printf()" that allows you to set an - * alternative printf function pointer. - * - * All these define require POLARSSL_PLATFORM_C to be defined! - * - * Uncomment a macro to enable alternate implementation of specific base - * platform function - */ -//#define POLARSSL_PLATFORM_PRINTF_ALT -//#define POLARSSL_PLATFORM_FPRINTF_ALT -/* \} name SECTION: System support */ - -/** - * \name SECTION: PolarSSL feature support - * - * This section sets support for features that are or are not needed - * within the modules that are enabled. - * \{ - */ - -/** - * \def POLARSSL_TIMING_ALT - * - * Uncomment to provide your own alternate implementation for hardclock(), - * get_timer(), set_alarm() and m_sleep(). - * - * Only works if you have POLARSSL_TIMING_C enabled. - * - * You will need to provide a header "timing_alt.h" and an implementation at - * compile time. - */ -//#define POLARSSL_TIMING_ALT - -/** - * \def POLARSSL_XXX_ALT - * - * Uncomment a macro to let PolarSSL use your alternate core implementation of - * a symmetric or hash algorithm (e.g. platform specific assembly optimized - * implementations). Keep in mind that the function prototypes should remain - * the same. - * - * Example: In case you uncomment POLARSSL_AES_ALT, PolarSSL will no longer - * provide the "struct aes_context" definition and omit the base function - * declarations and implementations. "aes_alt.h" will be included from - * "aes.h" to include the new function definitions. - * - * Uncomment a macro to enable alternate implementation for core algorithm - * functions - */ -//#define POLARSSL_AES_ALT -//#define POLARSSL_ARC4_ALT -//#define POLARSSL_BLOWFISH_ALT -//#define POLARSSL_CAMELLIA_ALT -//#define POLARSSL_DES_ALT -//#define POLARSSL_XTEA_ALT -//#define POLARSSL_MD2_ALT -//#define POLARSSL_MD4_ALT -//#define POLARSSL_MD5_ALT -//#define POLARSSL_RIPEMD160_ALT -//#define POLARSSL_SHA1_ALT -//#define POLARSSL_SHA256_ALT -//#define POLARSSL_SHA512_ALT - -/** - * \def POLARSSL_AES_ROM_TABLES - * - * Store the AES tables in ROM. - * - * Uncomment this macro to store the AES tables in ROM. - * - */ -//#define POLARSSL_AES_ROM_TABLES - -/** - * \def POLARSSL_CIPHER_MODE_CBC - * - * Enable Cipher Block Chaining mode (CBC) for symmetric ciphers. - */ -#define POLARSSL_CIPHER_MODE_CBC - -/** - * \def POLARSSL_CIPHER_MODE_CFB - * - * Enable Cipher Feedback mode (CFB) for symmetric ciphers. - */ -#define POLARSSL_CIPHER_MODE_CFB - -/** - * \def POLARSSL_CIPHER_MODE_CTR - * - * Enable Counter Block Cipher mode (CTR) for symmetric ciphers. - */ -#define POLARSSL_CIPHER_MODE_CTR - -/** - * \def POLARSSL_CIPHER_NULL_CIPHER - * - * Enable NULL cipher. - * Warning: Only do so when you know what you are doing. This allows for - * encryption or channels without any security! - * - * Requires POLARSSL_ENABLE_WEAK_CIPHERSUITES as well to enable - * the following ciphersuites: - * TLS_ECDH_ECDSA_WITH_NULL_SHA - * TLS_ECDH_RSA_WITH_NULL_SHA - * TLS_ECDHE_ECDSA_WITH_NULL_SHA - * TLS_ECDHE_RSA_WITH_NULL_SHA - * TLS_ECDHE_PSK_WITH_NULL_SHA384 - * TLS_ECDHE_PSK_WITH_NULL_SHA256 - * TLS_ECDHE_PSK_WITH_NULL_SHA - * TLS_DHE_PSK_WITH_NULL_SHA384 - * TLS_DHE_PSK_WITH_NULL_SHA256 - * TLS_DHE_PSK_WITH_NULL_SHA - * TLS_RSA_WITH_NULL_SHA256 - * TLS_RSA_WITH_NULL_SHA - * TLS_RSA_WITH_NULL_MD5 - * TLS_RSA_PSK_WITH_NULL_SHA384 - * TLS_RSA_PSK_WITH_NULL_SHA256 - * TLS_RSA_PSK_WITH_NULL_SHA - * TLS_PSK_WITH_NULL_SHA384 - * TLS_PSK_WITH_NULL_SHA256 - * TLS_PSK_WITH_NULL_SHA - * - * Uncomment this macro to enable the NULL cipher and ciphersuites - */ -//#define POLARSSL_CIPHER_NULL_CIPHER - -/** - * \def POLARSSL_CIPHER_PADDING_XXX - * - * Uncomment or comment macros to add support for specific padding modes - * in the cipher layer with cipher modes that support padding (e.g. CBC) - * - * If you disable all padding modes, only full blocks can be used with CBC. - * - * Enable padding modes in the cipher layer. - */ -#define POLARSSL_CIPHER_PADDING_PKCS7 -#define POLARSSL_CIPHER_PADDING_ONE_AND_ZEROS -#define POLARSSL_CIPHER_PADDING_ZEROS_AND_LEN -#define POLARSSL_CIPHER_PADDING_ZEROS - -/** - * \def POLARSSL_ENABLE_WEAK_CIPHERSUITES - * - * Enable weak ciphersuites in SSL / TLS. - * Warning: Only do so when you know what you are doing. This allows for - * channels with virtually no security at all! - * - * This enables the following ciphersuites: - * TLS_RSA_WITH_DES_CBC_SHA - * TLS_DHE_RSA_WITH_DES_CBC_SHA - * - * Uncomment this macro to enable weak ciphersuites - */ -//#define POLARSSL_ENABLE_WEAK_CIPHERSUITES - -/** - * \def POLARSSL_REMOVE_ARC4_CIPHERSUITES - * - * Remove RC4 ciphersuites by default in SSL / TLS. - * This flag removes the ciphersuites based on RC4 from the default list as - * returned by ssl_list_ciphersuites(). However, it is still possible to - * enable (some of) them with ssl_set_ciphersuites() by including them - * explicitly. - * - * Uncomment this macro to remove RC4 ciphersuites by default. - */ -//#define POLARSSL_REMOVE_ARC4_CIPHERSUITES - -/** - * \def POLARSSL_ECP_XXXX_ENABLED - * - * Enables specific curves within the Elliptic Curve module. - * By default all supported curves are enabled. - * - * Comment macros to disable the curve and functions for it - */ -#define POLARSSL_ECP_DP_SECP192R1_ENABLED -#define POLARSSL_ECP_DP_SECP224R1_ENABLED -#define POLARSSL_ECP_DP_SECP256R1_ENABLED -#define POLARSSL_ECP_DP_SECP384R1_ENABLED -#define POLARSSL_ECP_DP_SECP521R1_ENABLED -#define POLARSSL_ECP_DP_SECP192K1_ENABLED -#define POLARSSL_ECP_DP_SECP224K1_ENABLED -#define POLARSSL_ECP_DP_SECP256K1_ENABLED -#define POLARSSL_ECP_DP_BP256R1_ENABLED -#define POLARSSL_ECP_DP_BP384R1_ENABLED -#define POLARSSL_ECP_DP_BP512R1_ENABLED -//#define POLARSSL_ECP_DP_M221_ENABLED // Not implemented yet! -#define POLARSSL_ECP_DP_M255_ENABLED -//#define POLARSSL_ECP_DP_M383_ENABLED // Not implemented yet! -//#define POLARSSL_ECP_DP_M511_ENABLED // Not implemented yet! - -/** - * \def POLARSSL_ECP_NIST_OPTIM - * - * Enable specific 'modulo p' routines for each NIST prime. - * Depending on the prime and architecture, makes operations 4 to 8 times - * faster on the corresponding curve. - * - * Comment this macro to disable NIST curves optimisation. - */ -#define POLARSSL_ECP_NIST_OPTIM - -/** - * \def POLARSSL_ECDSA_DETERMINISTIC - * - * Enable deterministic ECDSA (RFC 6979). - * Standard ECDSA is "fragile" in the sense that lack of entropy when signing - * may result in a compromise of the long-term signing key. This is avoided by - * the deterministic variant. - * - * Requires: POLARSSL_HMAC_DRBG_C - * - * Comment this macro to disable deterministic ECDSA. - */ -#define POLARSSL_ECDSA_DETERMINISTIC - -/** - * \def POLARSSL_KEY_EXCHANGE_PSK_ENABLED - * - * Enable the PSK based ciphersuite modes in SSL / TLS. - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_PSK_WITH_AES_256_GCM_SHA384 - * TLS_PSK_WITH_AES_256_CBC_SHA384 - * TLS_PSK_WITH_AES_256_CBC_SHA - * TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_PSK_WITH_AES_128_GCM_SHA256 - * TLS_PSK_WITH_AES_128_CBC_SHA256 - * TLS_PSK_WITH_AES_128_CBC_SHA - * TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_PSK_WITH_RC4_128_SHA - */ -#define POLARSSL_KEY_EXCHANGE_PSK_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED - * - * Enable the DHE-PSK based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_DHM_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 - * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_AES_256_CBC_SHA - * TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 - * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 - * TLS_DHE_PSK_WITH_AES_128_CBC_SHA - * TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_DHE_PSK_WITH_RC4_128_SHA - */ -#define POLARSSL_KEY_EXCHANGE_DHE_PSK_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED - * - * Enable the ECDHE-PSK based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_ECDH_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA - * TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA - * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_PSK_WITH_RC4_128_SHA - */ -#define POLARSSL_KEY_EXCHANGE_ECDHE_PSK_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED - * - * Enable the RSA-PSK based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, - * POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 - * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 - * TLS_RSA_PSK_WITH_AES_256_CBC_SHA - * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 - * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 - * TLS_RSA_PSK_WITH_AES_128_CBC_SHA - * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_RSA_PSK_WITH_RC4_128_SHA - */ -#define POLARSSL_KEY_EXCHANGE_RSA_PSK_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_RSA_ENABLED - * - * Enable the RSA-only based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_RSA_C, POLARSSL_PKCS1_V15, - * POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_RSA_WITH_AES_256_GCM_SHA384 - * TLS_RSA_WITH_AES_256_CBC_SHA256 - * TLS_RSA_WITH_AES_256_CBC_SHA - * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA - * TLS_RSA_WITH_AES_128_GCM_SHA256 - * TLS_RSA_WITH_AES_128_CBC_SHA256 - * TLS_RSA_WITH_AES_128_CBC_SHA - * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - * TLS_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_RSA_WITH_RC4_128_SHA - * TLS_RSA_WITH_RC4_128_MD5 - */ -#define POLARSSL_KEY_EXCHANGE_RSA_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED - * - * Enable the DHE-RSA based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_DHM_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, - * POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 - * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - * TLS_DHE_RSA_WITH_AES_256_CBC_SHA - * TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 - * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_AES_128_CBC_SHA - * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - */ -#define POLARSSL_KEY_EXCHANGE_DHE_RSA_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED - * - * Enable the ECDHE-RSA based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_ECDH_C, POLARSSL_RSA_C, POLARSSL_PKCS1_V15, - * POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - * TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_RSA_WITH_RC4_128_SHA - */ -#define POLARSSL_KEY_EXCHANGE_ECDHE_RSA_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - * - * Enable the ECDHE-ECDSA based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_ECDH_C, POLARSSL_ECDSA_C, POLARSSL_X509_CRT_PARSE_C, - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - */ -#define POLARSSL_KEY_EXCHANGE_ECDHE_ECDSA_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED - * - * Enable the ECDH-ECDSA based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_ECDSA_WITH_RC4_128_SHA - * TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA - * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA - * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - */ -#define POLARSSL_KEY_EXCHANGE_ECDH_ECDSA_ENABLED - -/** - * \def POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED - * - * Enable the ECDH-RSA based ciphersuite modes in SSL / TLS. - * - * Requires: POLARSSL_ECDH_C, POLARSSL_X509_CRT_PARSE_C - * - * This enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_RSA_WITH_RC4_128_SHA - * TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA - * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA - * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 - */ -#define POLARSSL_KEY_EXCHANGE_ECDH_RSA_ENABLED - -/** - * \def POLARSSL_PK_PARSE_EC_EXTENDED - * - * Enhance support for reading EC keys using variants of SEC1 not allowed by - * RFC 5915 and RFC 5480. - * - * Currently this means parsing the SpecifiedECDomain choice of EC - * parameters (only known groups are supported, not arbitrary domains, to - * avoid validation issues). - * - * Disable if you only need to support RFC 5915 + 5480 key formats. - */ -#define POLARSSL_PK_PARSE_EC_EXTENDED - -/** - * \def POLARSSL_ERROR_STRERROR_BC - * - * Make available the backward compatible error_strerror() next to the - * current polarssl_strerror(). - * - * For new code, it is recommended to use polarssl_strerror() instead and - * disable this. - * - * Disable if you run into name conflicts and want to really remove the - * error_strerror() - */ -#define POLARSSL_ERROR_STRERROR_BC - -/** - * \def POLARSSL_ERROR_STRERROR_DUMMY - * - * Enable a dummy error function to make use of polarssl_strerror() in - * third party libraries easier when POLARSSL_ERROR_C is disabled - * (no effect when POLARSSL_ERROR_C is enabled). - * - * You can safely disable this if POLARSSL_ERROR_C is enabled, or if you're - * not using polarssl_strerror() or error_strerror() in your application. - * - * Disable if you run into name conflicts and want to really remove the - * polarssl_strerror() - */ -#define POLARSSL_ERROR_STRERROR_DUMMY - -/** - * \def POLARSSL_GENPRIME - * - * Enable the prime-number generation code. - * - * Requires: POLARSSL_BIGNUM_C - */ -#define POLARSSL_GENPRIME - -/** - * \def POLARSSL_FS_IO - * - * Enable functions that use the filesystem. - */ -#define POLARSSL_FS_IO - -/** - * \def POLARSSL_NO_DEFAULT_ENTROPY_SOURCES - * - * Do not add default entropy sources. These are the platform specific, - * hardclock and HAVEGE based poll functions. - * - * This is useful to have more control over the added entropy sources in an - * application. - * - * Uncomment this macro to prevent loading of default entropy functions. - */ -//#define POLARSSL_NO_DEFAULT_ENTROPY_SOURCES - -/** - * \def POLARSSL_NO_PLATFORM_ENTROPY - * - * Do not use built-in platform entropy functions. - * This is useful if your platform does not support - * standards like the /dev/urandom or Windows CryptoAPI. - * - * Uncomment this macro to disable the built-in platform entropy functions. - */ -//#define POLARSSL_NO_PLATFORM_ENTROPY - -/** - * \def POLARSSL_ENTROPY_FORCE_SHA256 - * - * Force the entropy accumulator to use a SHA-256 accumulator instead of the - * default SHA-512 based one (if both are available). - * - * Requires: POLARSSL_SHA256_C - * - * On 32-bit systems SHA-256 can be much faster than SHA-512. Use this option - * if you have performance concerns. - * - * This option is only useful if both POLARSSL_SHA256_C and - * POLARSSL_SHA512_C are defined. Otherwise the available hash module is used. - */ -//#define POLARSSL_ENTROPY_FORCE_SHA256 - -/** - * \def POLARSSL_MEMORY_DEBUG - * - * Enable debugging of buffer allocator memory issues. Automatically prints - * (to stderr) all (fatal) messages on memory allocation issues. Enables - * function for 'debug output' of allocated memory. - * - * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C - * - * Uncomment this macro to let the buffer allocator print out error messages. - */ -//#define POLARSSL_MEMORY_DEBUG - -/** - * \def POLARSSL_MEMORY_BACKTRACE - * - * Include backtrace information with each allocated block. - * - * Requires: POLARSSL_MEMORY_BUFFER_ALLOC_C - * GLIBC-compatible backtrace() an backtrace_symbols() support - * - * Uncomment this macro to include backtrace information - */ -//#define POLARSSL_MEMORY_BACKTRACE - -/** - * \def POLARSSL_PKCS1_V15 - * - * Enable support for PKCS#1 v1.5 encoding. - * - * Requires: POLARSSL_RSA_C - * - * This enables support for PKCS#1 v1.5 operations. - */ -#define POLARSSL_PKCS1_V15 - -/** - * \def POLARSSL_PKCS1_V21 - * - * Enable support for PKCS#1 v2.1 encoding. - * - * Requires: POLARSSL_MD_C, POLARSSL_RSA_C - * - * This enables support for RSAES-OAEP and RSASSA-PSS operations. - */ -//#define POLARSSL_PKCS1_V21 - -/** - * \def POLARSSL_RSA_NO_CRT - * - * Do not use the Chinese Remainder Theorem for the RSA private operation. - * - * Uncomment this macro to disable the use of CRT in RSA. - * - */ -//#define POLARSSL_RSA_NO_CRT - -/** - * \def POLARSSL_SELF_TEST - * - * Enable the checkup functions (*_self_test). - */ -#define POLARSSL_SELF_TEST - -/** - * \def POLARSSL_SSL_ALL_ALERT_MESSAGES - * - * Enable sending of alert messages in case of encountered errors as per RFC. - * If you choose not to send the alert messages, PolarSSL can still communicate - * with other servers, only debugging of failures is harder. - * - * The advantage of not sending alert messages, is that no information is given - * about reasons for failures thus preventing adversaries of gaining intel. - * - * Enable sending of all alert messages - */ -#define POLARSSL_SSL_ALERT_MESSAGES - -/** - * \def POLARSSL_SSL_DEBUG_ALL - * - * Enable the debug messages in SSL module for all issues. - * Debug messages have been disabled in some places to prevent timing - * attacks due to (unbalanced) debugging function calls. - * - * If you need all error reporting you should enable this during debugging, - * but remove this for production servers that should log as well. - * - * Uncomment this macro to report all debug messages on errors introducing - * a timing side-channel. - * - */ -//#define POLARSSL_SSL_DEBUG_ALL - -/** - * \def POLARSSL_SSL_HW_RECORD_ACCEL - * - * Enable hooking functions in SSL module for hardware acceleration of - * individual records. - * - * Uncomment this macro to enable hooking functions. - */ -//#define POLARSSL_SSL_HW_RECORD_ACCEL - -/** - * \def POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO - * - * Enable support for receiving and parsing SSLv2 Client Hello messages for the - * SSL Server module (POLARSSL_SSL_SRV_C). - * - * Comment this macro to disable support for SSLv2 Client Hello messages. - */ -#define POLARSSL_SSL_SRV_SUPPORT_SSLV2_CLIENT_HELLO - -/** - * \def POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE - * - * Pick the ciphersuite according to the client's preferences rather than ours - * in the SSL Server module (POLARSSL_SSL_SRV_C). - * - * Uncomment this macro to respect client's ciphersuite order - */ -//#define POLARSSL_SSL_SRV_RESPECT_CLIENT_PREFERENCE - -/** - * \def POLARSSL_SSL_MAX_FRAGMENT_LENGTH - * - * Enable support for RFC 6066 max_fragment_length extension in SSL. - * - * Comment this macro to disable support for the max_fragment_length extension - */ -#define POLARSSL_SSL_MAX_FRAGMENT_LENGTH - -/** - * \def POLARSSL_SSL_PROTO_SSL3 - * - * Enable support for SSL 3.0. - * - * Requires: POLARSSL_MD5_C - * POLARSSL_SHA1_C - * - * Comment this macro to disable support for SSL 3.0 - */ -#define POLARSSL_SSL_PROTO_SSL3 - -/** - * \def POLARSSL_SSL_PROTO_TLS1 - * - * Enable support for TLS 1.0. - * - * Requires: POLARSSL_MD5_C - * POLARSSL_SHA1_C - * - * Comment this macro to disable support for TLS 1.0 - */ -#define POLARSSL_SSL_PROTO_TLS1 - -/** - * \def POLARSSL_SSL_PROTO_TLS1_1 - * - * Enable support for TLS 1.1. - * - * Requires: POLARSSL_MD5_C - * POLARSSL_SHA1_C - * - * Comment this macro to disable support for TLS 1.1 - */ -#define POLARSSL_SSL_PROTO_TLS1_1 - -/** - * \def POLARSSL_SSL_PROTO_TLS1_2 - * - * Enable support for TLS 1.2. - * - * Requires: POLARSSL_SHA1_C or POLARSSL_SHA256_C or POLARSSL_SHA512_C - * (Depends on ciphersuites) - * - * Comment this macro to disable support for TLS 1.2 - */ -#define POLARSSL_SSL_PROTO_TLS1_2 - -/** - * \def POLARSSL_SSL_ALPN - * - * Enable support for Application Layer Protocol Negotiation. - * draft-ietf-tls-applayerprotoneg-05 - * - * Comment this macro to disable support for ALPN. - */ -#define POLARSSL_SSL_ALPN - -/** - * \def POLARSSL_SSL_SESSION_TICKETS - * - * Enable support for RFC 5077 session tickets in SSL. - * - * Requires: POLARSSL_AES_C - * POLARSSL_SHA256_C - * POLARSSL_CIPHER_MODE_CBC - * - * Comment this macro to disable support for SSL session tickets - */ -#define POLARSSL_SSL_SESSION_TICKETS - -/** - * \def POLARSSL_SSL_SERVER_NAME_INDICATION - * - * Enable support for RFC 6066 server name indication (SNI) in SSL. - * - * Comment this macro to disable support for server name indication in SSL - */ -#define POLARSSL_SSL_SERVER_NAME_INDICATION - -/** - * \def POLARSSL_SSL_TRUNCATED_HMAC - * - * Enable support for RFC 6066 truncated HMAC in SSL. - * - * Comment this macro to disable support for truncated HMAC in SSL - */ -#define POLARSSL_SSL_TRUNCATED_HMAC - -/** - * \def POLARSSL_SSL_SET_CURVES - * - * Enable ssl_set_curves(). - * - * This is disabled by default since it breaks binary compatibility with the - * 1.3.x line. If you choose to enable it, you will need to rebuild your - * application against the new header files, relinking will not be enough. - * It will be enabled by default, or no longer an option, in the 1.4 branch. - * - * Uncomment to make ssl_set_curves() available. - */ -//#define POLARSSL_SSL_SET_CURVES - -/** - * \def POLARSSL_THREADING_ALT - * - * Provide your own alternate threading implementation. - * - * Requires: POLARSSL_THREADING_C - * - * Uncomment this to allow your own alternate threading implementation. - */ -//#define POLARSSL_THREADING_ALT - -/** - * \def POLARSSL_THREADING_PTHREAD - * - * Enable the pthread wrapper layer for the threading layer. - * - * Requires: POLARSSL_THREADING_C - * - * Uncomment this to enable pthread mutexes. - */ -//#define POLARSSL_THREADING_PTHREAD - -/** - * \def POLARSSL_VERSION_FEATURES - * - * Allow run-time checking of compile-time enabled features. Thus allowing users - * to check at run-time if the library is for instance compiled with threading - * support via version_check_feature(). - * - * Requires: POLARSSL_VERSION_C - * - * Comment this to disable run-time checking and save ROM space - */ -#define POLARSSL_VERSION_FEATURES - -/** - * \def POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 - * - * If set, the X509 parser will not break-off when parsing an X509 certificate - * and encountering an extension in a v1 or v2 certificate. - * - * Uncomment to prevent an error. - */ -//#define POLARSSL_X509_ALLOW_EXTENSIONS_NON_V3 - -/** - * \def POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION - * - * If set, the X509 parser will not break-off when parsing an X509 certificate - * and encountering an unknown critical extension. - * - * Uncomment to prevent an error. - */ -//#define POLARSSL_X509_ALLOW_UNSUPPORTED_CRITICAL_EXTENSION - -/** - * \def POLARSSL_X509_CHECK_KEY_USAGE - * - * Enable verification of the keyUsage extension (CA and leaf certificates). - * - * Disabling this avoids problems with mis-issued and/or misused - * (intermediate) CA and leaf certificates. - * - * \warning Depending on your PKI use, disabling this can be a security risk! - * - * Comment to skip keyUsage checking for both CA and leaf certificates. - */ -#define POLARSSL_X509_CHECK_KEY_USAGE - -/** - * \def POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE - * - * Enable verification of the extendedKeyUsage extension (leaf certificates). - * - * Disabling this avoids problems with mis-issued and/or misused certificates. - * - * \warning Depending on your PKI use, disabling this can be a security risk! - * - * Comment to skip extendedKeyUsage checking for certificates. - */ -#define POLARSSL_X509_CHECK_EXTENDED_KEY_USAGE - -/** - * \def POLARSSL_X509_RSASSA_PSS_SUPPORT - * - * Enable parsing and verification of X.509 certificates, CRLs and CSRS - * signed with RSASSA-PSS (aka PKCS#1 v2.1). - * - * Comment this macro to disallow using RSASSA-PSS in certificates. - */ -#define POLARSSL_X509_RSASSA_PSS_SUPPORT - -/** - * \def POLARSSL_ZLIB_SUPPORT - * - * If set, the SSL/TLS module uses ZLIB to support compression and - * decompression of packet data. - * - * \warning TLS-level compression MAY REDUCE SECURITY! See for example the - * CRIME attack. Before enabling this option, you should examine with care if - * CRIME or similar exploits may be a applicable to your use case. - * - * Used in: library/ssl_tls.c - * library/ssl_cli.c - * library/ssl_srv.c - * - * This feature requires zlib library and headers to be present. - * - * Uncomment to enable use of ZLIB - */ -//#define POLARSSL_ZLIB_SUPPORT -/* \} name SECTION: PolarSSL feature support */ - -/** - * \name SECTION: PolarSSL modules - * - * This section enables or disables entire modules in PolarSSL - * \{ - */ - -/** - * \def POLARSSL_AESNI_C - * - * Enable AES-NI support on x86-64. - * - * Module: library/aesni.c - * Caller: library/aes.c - * - * Requires: POLARSSL_HAVE_ASM - * - * This modules adds support for the AES-NI instructions on x86-64 - */ -//#define POLARSSL_AESNI_C - -/** - * \def POLARSSL_AES_C - * - * Enable the AES block cipher. - * - * Module: library/aes.c - * Caller: library/ssl_tls.c - * library/pem.c - * library/ctr_drbg.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA - * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA - * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA - * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA - * TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDH_RSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDH_RSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDH_ECDSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDH_ECDSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDH_RSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDH_RSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384 - * TLS_DHE_RSA_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384 - * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384 - * TLS_DHE_RSA_WITH_AES_256_CBC_SHA256 - * TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA - * TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA - * TLS_DHE_RSA_WITH_AES_256_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 - * TLS_DHE_RSA_WITH_AES_128_GCM_SHA256 - * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA - * TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA - * TLS_DHE_RSA_WITH_AES_128_CBC_SHA - * TLS_DHE_PSK_WITH_AES_256_GCM_SHA384 - * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_AES_256_CBC_SHA384 - * TLS_ECDHE_PSK_WITH_AES_256_CBC_SHA - * TLS_DHE_PSK_WITH_AES_256_CBC_SHA - * TLS_DHE_PSK_WITH_AES_128_GCM_SHA256 - * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA256 - * TLS_DHE_PSK_WITH_AES_128_CBC_SHA256 - * TLS_ECDHE_PSK_WITH_AES_128_CBC_SHA - * TLS_DHE_PSK_WITH_AES_128_CBC_SHA - * TLS_RSA_WITH_AES_256_GCM_SHA384 - * TLS_RSA_WITH_AES_256_CBC_SHA256 - * TLS_RSA_WITH_AES_256_CBC_SHA - * TLS_RSA_WITH_AES_128_GCM_SHA256 - * TLS_RSA_WITH_AES_128_CBC_SHA256 - * TLS_RSA_WITH_AES_128_CBC_SHA - * TLS_RSA_PSK_WITH_AES_256_GCM_SHA384 - * TLS_RSA_PSK_WITH_AES_256_CBC_SHA384 - * TLS_RSA_PSK_WITH_AES_256_CBC_SHA - * TLS_RSA_PSK_WITH_AES_128_GCM_SHA256 - * TLS_RSA_PSK_WITH_AES_128_CBC_SHA256 - * TLS_RSA_PSK_WITH_AES_128_CBC_SHA - * TLS_PSK_WITH_AES_256_GCM_SHA384 - * TLS_PSK_WITH_AES_256_CBC_SHA384 - * TLS_PSK_WITH_AES_256_CBC_SHA - * TLS_PSK_WITH_AES_128_GCM_SHA256 - * TLS_PSK_WITH_AES_128_CBC_SHA256 - * TLS_PSK_WITH_AES_128_CBC_SHA - * - * PEM_PARSE uses AES for decrypting encrypted keys. - */ -#define POLARSSL_AES_C - -/** - * \def POLARSSL_ARC4_C - * - * Enable the ARCFOUR stream cipher. - * - * Module: library/arc4.c - * Caller: library/ssl_tls.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_ECDSA_WITH_RC4_128_SHA - * TLS_ECDH_RSA_WITH_RC4_128_SHA - * TLS_ECDHE_ECDSA_WITH_RC4_128_SHA - * TLS_ECDHE_RSA_WITH_RC4_128_SHA - * TLS_ECDHE_PSK_WITH_RC4_128_SHA - * TLS_DHE_PSK_WITH_RC4_128_SHA - * TLS_RSA_WITH_RC4_128_SHA - * TLS_RSA_WITH_RC4_128_MD5 - * TLS_RSA_PSK_WITH_RC4_128_SHA - * TLS_PSK_WITH_RC4_128_SHA - */ -#define POLARSSL_ARC4_C - -/** - * \def POLARSSL_ASN1_PARSE_C - * - * Enable the generic ASN1 parser. - * - * Module: library/asn1.c - * Caller: library/x509.c - * library/dhm.c - * library/pkcs12.c - * library/pkcs5.c - * library/pkparse.c - */ -#define POLARSSL_ASN1_PARSE_C - -/** - * \def POLARSSL_ASN1_WRITE_C - * - * Enable the generic ASN1 writer. - * - * Module: library/asn1write.c - * Caller: library/ecdsa.c - * library/pkwrite.c - * library/x509_create.c - * library/x509write_crt.c - * library/x509write_csr.c - */ -#define POLARSSL_ASN1_WRITE_C - -/** - * \def POLARSSL_BASE64_C - * - * Enable the Base64 module. - * - * Module: library/base64.c - * Caller: library/pem.c - * - * This module is required for PEM support (required by X.509). - */ -#define POLARSSL_BASE64_C - -/** - * \def POLARSSL_BIGNUM_C - * - * Enable the multi-precision integer library. - * - * Module: library/bignum.c - * Caller: library/dhm.c - * library/ecp.c - * library/ecdsa.c - * library/rsa.c - * library/ssl_tls.c - * - * This module is required for RSA, DHM and ECC (ECDH, ECDSA) support. - */ -#define POLARSSL_BIGNUM_C - -/** - * \def POLARSSL_BLOWFISH_C - * - * Enable the Blowfish block cipher. - * - * Module: library/blowfish.c - */ -#define POLARSSL_BLOWFISH_C - -/** - * \def POLARSSL_CAMELLIA_C - * - * Enable the Camellia block cipher. - * - * Module: library/camellia.c - * Caller: library/ssl_tls.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDH_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDH_RSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDH_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDH_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDH_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_DHE_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_ECDHE_RSA_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_256_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_ECDHE_ECDSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_DHE_RSA_WITH_CAMELLIA_128_CBC_SHA - * TLS_DHE_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_ECDHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_DHE_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_DHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_ECDHE_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_RSA_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA256 - * TLS_RSA_WITH_CAMELLIA_256_CBC_SHA - * TLS_RSA_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_RSA_WITH_CAMELLIA_128_CBC_SHA - * TLS_RSA_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_RSA_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_RSA_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_RSA_PSK_WITH_CAMELLIA_128_CBC_SHA256 - * TLS_PSK_WITH_CAMELLIA_256_GCM_SHA384 - * TLS_PSK_WITH_CAMELLIA_256_CBC_SHA384 - * TLS_PSK_WITH_CAMELLIA_128_GCM_SHA256 - * TLS_PSK_WITH_CAMELLIA_128_CBC_SHA256 - */ -#define POLARSSL_CAMELLIA_C - -/** - * \def POLARSSL_CCM_C - * - * Enable the Counter with CBC-MAC (CCM) mode for 128-bit block cipher. - * - * Module: library/ccm.c - * - * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C - * - * This module enables the AES-CCM ciphersuites, if other requisites are - * enabled as well. - */ -#define POLARSSL_CCM_C - -/** - * \def POLARSSL_CERTS_C - * - * Enable the test certificates. - * - * Module: library/certs.c - * Caller: - * - * Requires: POLARSSL_PEM_PARSE_C - * - * This module is used for testing (ssl_client/server). - */ -#define POLARSSL_CERTS_C - -/** - * \def POLARSSL_CIPHER_C - * - * Enable the generic cipher layer. - * - * Module: library/cipher.c - * Caller: library/ssl_tls.c - * - * Uncomment to enable generic cipher wrappers. - */ -#define POLARSSL_CIPHER_C - -/** - * \def POLARSSL_CTR_DRBG_C - * - * Enable the CTR_DRBG AES-256-based random generator. - * - * Module: library/ctr_drbg.c - * Caller: - * - * Requires: POLARSSL_AES_C - * - * This module provides the CTR_DRBG AES-256 random number generator. - */ -#define POLARSSL_CTR_DRBG_C - -/** - * \def POLARSSL_DEBUG_C - * - * Enable the debug functions. - * - * Module: library/debug.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * This module provides debugging functions. - */ -#define POLARSSL_DEBUG_C - -/** - * \def POLARSSL_DES_C - * - * Enable the DES block cipher. - * - * Module: library/des.c - * Caller: library/pem.c - * library/ssl_tls.c - * - * This module enables the following ciphersuites (if other requisites are - * enabled as well): - * TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_DHE_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_ECDHE_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_DHE_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_RSA_WITH_3DES_EDE_CBC_SHA - * TLS_RSA_PSK_WITH_3DES_EDE_CBC_SHA - * TLS_PSK_WITH_3DES_EDE_CBC_SHA - * - * PEM_PARSE uses DES/3DES for decrypting encrypted keys. - */ -#define POLARSSL_DES_C - -/** - * \def POLARSSL_DHM_C - * - * Enable the Diffie-Hellman-Merkle module. - * - * Module: library/dhm.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * This module is used by the following key exchanges: - * DHE-RSA, DHE-PSK - */ -#define POLARSSL_DHM_C - -/** - * \def POLARSSL_ECDH_C - * - * Enable the elliptic curve Diffie-Hellman library. - * - * Module: library/ecdh.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * This module is used by the following key exchanges: - * ECDHE-ECDSA, ECDHE-RSA, DHE-PSK - * - * Requires: POLARSSL_ECP_C - */ -#define POLARSSL_ECDH_C - -/** - * \def POLARSSL_ECDSA_C - * - * Enable the elliptic curve DSA library. - * - * Module: library/ecdsa.c - * Caller: - * - * This module is used by the following key exchanges: - * ECDHE-ECDSA - * - * Requires: POLARSSL_ECP_C, POLARSSL_ASN1_WRITE_C, POLARSSL_ASN1_PARSE_C - */ -#define POLARSSL_ECDSA_C - -/** - * \def POLARSSL_ECP_C - * - * Enable the elliptic curve over GF(p) library. - * - * Module: library/ecp.c - * Caller: library/ecdh.c - * library/ecdsa.c - * - * Requires: POLARSSL_BIGNUM_C and at least one POLARSSL_ECP_DP_XXX_ENABLED - */ -#define POLARSSL_ECP_C - -/** - * \def POLARSSL_ENTROPY_C - * - * Enable the platform-specific entropy code. - * - * Module: library/entropy.c - * Caller: - * - * Requires: POLARSSL_SHA512_C or POLARSSL_SHA256_C - * - * This module provides a generic entropy pool - */ -#define POLARSSL_ENTROPY_C - -/** - * \def POLARSSL_ERROR_C - * - * Enable error code to error string conversion. - * - * Module: library/error.c - * Caller: - * - * This module enables polarssl_strerror(). - */ -#define POLARSSL_ERROR_C - -/** - * \def POLARSSL_GCM_C - * - * Enable the Galois/Counter Mode (GCM) for AES. - * - * Module: library/gcm.c - * - * Requires: POLARSSL_AES_C or POLARSSL_CAMELLIA_C - * - * This module enables the AES-GCM and CAMELLIA-GCM ciphersuites, if other - * requisites are enabled as well. - */ -#define POLARSSL_GCM_C - -/** - * \def POLARSSL_HAVEGE_C - * - * Enable the HAVEGE random generator. - * - * Warning: the HAVEGE random generator is not suitable for virtualized - * environments - * - * Warning: the HAVEGE random generator is dependent on timing and specific - * processor traits. It is therefore not advised to use HAVEGE as - * your applications primary random generator or primary entropy pool - * input. As a secondary input to your entropy pool, it IS able add - * the (limited) extra entropy it provides. - * - * Module: library/havege.c - * Caller: - * - * Requires: POLARSSL_TIMING_C - * - * Uncomment to enable the HAVEGE random generator. - */ -//#define POLARSSL_HAVEGE_C - -/** - * \def POLARSSL_HMAC_DRBG_C - * - * Enable the HMAC_DRBG random generator. - * - * Module: library/hmac_drbg.c - * Caller: - * - * Requires: POLARSSL_MD_C - * - * Uncomment to enable the HMAC_DRBG random number geerator. - */ -#define POLARSSL_HMAC_DRBG_C - -/** - * \def POLARSSL_MD_C - * - * Enable the generic message digest layer. - * - * Module: library/md.c - * Caller: - * - * Uncomment to enable generic message digest wrappers. - */ -#define POLARSSL_MD_C - -/** - * \def POLARSSL_MD2_C - * - * Enable the MD2 hash algorithm. - * - * Module: library/md2.c - * Caller: - * - * Uncomment to enable support for (rare) MD2-signed X.509 certs. - */ -//#define POLARSSL_MD2_C - -/** - * \def POLARSSL_MD4_C - * - * Enable the MD4 hash algorithm. - * - * Module: library/md4.c - * Caller: - * - * Uncomment to enable support for (rare) MD4-signed X.509 certs. - */ -//#define POLARSSL_MD4_C - -/** - * \def POLARSSL_MD5_C - * - * Enable the MD5 hash algorithm. - * - * Module: library/md5.c - * Caller: library/md.c - * library/pem.c - * library/ssl_tls.c - * - * This module is required for SSL/TLS and X.509. - * PEM_PARSE uses MD5 for decrypting encrypted keys. - */ -#define POLARSSL_MD5_C - -/** - * \def POLARSSL_MEMORY_C - * Deprecated since 1.3.5. Please use POLARSSL_PLATFORM_MEMORY instead. - */ -//#define POLARSSL_MEMORY_C - -/** - * \def POLARSSL_MEMORY_BUFFER_ALLOC_C - * - * Enable the buffer allocator implementation that makes use of a (stack) - * based buffer to 'allocate' dynamic memory. (replaces malloc() and free() - * calls) - * - * Module: library/memory_buffer_alloc.c - * - * Requires: POLARSSL_PLATFORM_C - * POLARSSL_PLATFORM_MEMORY (to use it within PolarSSL) - * - * Enable this module to enable the buffer memory allocator. - */ -//#define POLARSSL_MEMORY_BUFFER_ALLOC_C - -/** - * \def POLARSSL_NET_C - * - * Enable the TCP/IP networking routines. - * - * Module: library/net.c - * - * This module provides TCP/IP networking routines. - */ -#define POLARSSL_NET_C - -/** - * \def POLARSSL_OID_C - * - * Enable the OID database. - * - * Module: library/oid.c - * Caller: library/asn1write.c - * library/pkcs5.c - * library/pkparse.c - * library/pkwrite.c - * library/rsa.c - * library/x509.c - * library/x509_create.c - * library/x509_crl.c - * library/x509_crt.c - * library/x509_csr.c - * library/x509write_crt.c - * library/x509write_csr.c - * - * This modules translates between OIDs and internal values. - */ -#define POLARSSL_OID_C - -/** - * \def POLARSSL_PADLOCK_C - * - * Enable VIA Padlock support on x86. - * - * Module: library/padlock.c - * Caller: library/aes.c - * - * Requires: POLARSSL_HAVE_ASM - * - * This modules adds support for the VIA PadLock on x86. - */ -//#define POLARSSL_PADLOCK_C - -/** - * \def POLARSSL_PBKDF2_C - * - * Enable PKCS#5 PBKDF2 key derivation function. - * DEPRECATED: Use POLARSSL_PKCS5_C instead - * - * Module: library/pbkdf2.c - * - * Requires: POLARSSL_PKCS5_C - * - * This module adds support for the PKCS#5 PBKDF2 key derivation function. - */ -#define POLARSSL_PBKDF2_C - -/** - * \def POLARSSL_PEM_PARSE_C - * - * Enable PEM decoding / parsing. - * - * Module: library/pem.c - * Caller: library/dhm.c - * library/pkparse.c - * library/x509_crl.c - * library/x509_crt.c - * library/x509_csr.c - * - * Requires: POLARSSL_BASE64_C - * - * This modules adds support for decoding / parsing PEM files. - */ -#define POLARSSL_PEM_PARSE_C - -/** - * \def POLARSSL_PEM_WRITE_C - * - * Enable PEM encoding / writing. - * - * Module: library/pem.c - * Caller: library/pkwrite.c - * library/x509write_crt.c - * library/x509write_csr.c - * - * Requires: POLARSSL_BASE64_C - * - * This modules adds support for encoding / writing PEM files. - */ -#define POLARSSL_PEM_WRITE_C - -/** - * \def POLARSSL_PK_C - * - * Enable the generic public (asymetric) key layer. - * - * Module: library/pk.c - * Caller: library/ssl_tls.c - * library/ssl_cli.c - * library/ssl_srv.c - * - * Requires: POLARSSL_RSA_C or POLARSSL_ECP_C - * - * Uncomment to enable generic public key wrappers. - */ -#define POLARSSL_PK_C - -/** - * \def POLARSSL_PK_PARSE_C - * - * Enable the generic public (asymetric) key parser. - * - * Module: library/pkparse.c - * Caller: library/x509_crt.c - * library/x509_csr.c - * - * Requires: POLARSSL_PK_C - * - * Uncomment to enable generic public key parse functions. - */ -#define POLARSSL_PK_PARSE_C - -/** - * \def POLARSSL_PK_WRITE_C - * - * Enable the generic public (asymetric) key writer. - * - * Module: library/pkwrite.c - * Caller: library/x509write.c - * - * Requires: POLARSSL_PK_C - * - * Uncomment to enable generic public key write functions. - */ -#define POLARSSL_PK_WRITE_C - -/** - * \def POLARSSL_PKCS5_C - * - * Enable PKCS#5 functions. - * - * Module: library/pkcs5.c - * - * Requires: POLARSSL_MD_C - * - * This module adds support for the PKCS#5 functions. - */ -#define POLARSSL_PKCS5_C - -/** - * \def POLARSSL_PKCS11_C - * - * Enable wrapper for PKCS#11 smartcard support. - * - * Module: library/pkcs11.c - * Caller: library/pk.c - * - * Requires: POLARSSL_PK_C - * - * This module enables SSL/TLS PKCS #11 smartcard support. - * Requires the presence of the PKCS#11 helper library (libpkcs11-helper) - */ -//#define POLARSSL_PKCS11_C - -/** - * \def POLARSSL_PKCS12_C - * - * Enable PKCS#12 PBE functions. - * Adds algorithms for parsing PKCS#8 encrypted private keys - * - * Module: library/pkcs12.c - * Caller: library/pkparse.c - * - * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_CIPHER_C, POLARSSL_MD_C - * Can use: POLARSSL_ARC4_C - * - * This module enables PKCS#12 functions. - */ -#define POLARSSL_PKCS12_C - -/** - * \def POLARSSL_PLATFORM_C - * - * Enable the platform abstraction layer that allows you to re-assign - * functions like malloc(), free(), printf(), fprintf() - * - * Module: library/platform.c - * Caller: Most other .c files - * - * This module enables abstraction of common (libc) functions. - */ -//#define POLARSSL_PLATFORM_C - -/** - * \def POLARSSL_RIPEMD160_C - * - * Enable the RIPEMD-160 hash algorithm. - * - * Module: library/ripemd160.c - * Caller: library/md.c - * - */ -#define POLARSSL_RIPEMD160_C - -/** - * \def POLARSSL_RSA_C - * - * Enable the RSA public-key cryptosystem. - * - * Module: library/rsa.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509.c - * - * This module is used by the following key exchanges: - * RSA, DHE-RSA, ECDHE-RSA, RSA-PSK - * - * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C - */ -#define POLARSSL_RSA_C - -/** - * \def POLARSSL_SHA1_C - * - * Enable the SHA1 cryptographic hash algorithm. - * - * Module: library/sha1.c - * Caller: library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * library/x509write_crt.c - * - * This module is required for SSL/TLS and SHA1-signed certificates. - */ -#define POLARSSL_SHA1_C - -/** - * \def POLARSSL_SHA256_C - * - * Enable the SHA-224 and SHA-256 cryptographic hash algorithms. - * (Used to be POLARSSL_SHA2_C) - * - * Module: library/sha256.c - * Caller: library/entropy.c - * library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * This module adds support for SHA-224 and SHA-256. - * This module is required for the SSL/TLS 1.2 PRF function. - */ -#define POLARSSL_SHA256_C - -/** - * \def POLARSSL_SHA512_C - * - * Enable the SHA-384 and SHA-512 cryptographic hash algorithms. - * (Used to be POLARSSL_SHA4_C) - * - * Module: library/sha512.c - * Caller: library/entropy.c - * library/md.c - * library/ssl_cli.c - * library/ssl_srv.c - * - * This module adds support for SHA-384 and SHA-512. - */ -#define POLARSSL_SHA512_C - -/** - * \def POLARSSL_SSL_CACHE_C - * - * Enable simple SSL cache implementation. - * - * Module: library/ssl_cache.c - * Caller: - * - * Requires: POLARSSL_SSL_CACHE_C - */ -#define POLARSSL_SSL_CACHE_C - -/** - * \def POLARSSL_SSL_CLI_C - * - * Enable the SSL/TLS client code. - * - * Module: library/ssl_cli.c - * Caller: - * - * Requires: POLARSSL_SSL_TLS_C - * - * This module is required for SSL/TLS client support. - */ -#define POLARSSL_SSL_CLI_C - -/** - * \def POLARSSL_SSL_SRV_C - * - * Enable the SSL/TLS server code. - * - * Module: library/ssl_srv.c - * Caller: - * - * Requires: POLARSSL_SSL_TLS_C - * - * This module is required for SSL/TLS server support. - */ -#define POLARSSL_SSL_SRV_C - -/** - * \def POLARSSL_SSL_TLS_C - * - * Enable the generic SSL/TLS code. - * - * Module: library/ssl_tls.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * - * Requires: POLARSSL_CIPHER_C, POLARSSL_MD_C - * and at least one of the POLARSSL_SSL_PROTO_* defines - * - * This module is required for SSL/TLS. - */ -#define POLARSSL_SSL_TLS_C - -/** - * \def POLARSSL_THREADING_C - * - * Enable the threading abstraction layer. - * By default PolarSSL assumes it is used in a non-threaded environment or that - * contexts are not shared between threads. If you do intend to use contexts - * between threads, you will need to enable this layer to prevent race - * conditions. - * - * Module: library/threading.c - * - * This allows different threading implementations (self-implemented or - * provided). - * - * You will have to enable either POLARSSL_THREADING_ALT or - * POLARSSL_THREADING_PTHREAD. - * - * Enable this layer to allow use of mutexes within PolarSSL - */ -//#define POLARSSL_THREADING_C - -/** - * \def POLARSSL_TIMING_C - * - * Enable the portable timing interface. - * - * Module: library/timing.c - * Caller: library/havege.c - * - * This module is used by the HAVEGE random number generator. - */ -#define POLARSSL_TIMING_C - -/** - * \def POLARSSL_VERSION_C - * - * Enable run-time version information. - * - * Module: library/version.c - * - * This module provides run-time version information. - */ -#define POLARSSL_VERSION_C - -/** - * \def POLARSSL_X509_USE_C - * - * Enable X.509 core for using certificates. - * - * Module: library/x509.c - * Caller: library/x509_crl.c - * library/x509_crt.c - * library/x509_csr.c - * - * Requires: POLARSSL_ASN1_PARSE_C, POLARSSL_BIGNUM_C, POLARSSL_OID_C, - * POLARSSL_PK_PARSE_C - * - * This module is required for the X.509 parsing modules. - */ -#define POLARSSL_X509_USE_C - -/** - * \def POLARSSL_X509_CRT_PARSE_C - * - * Enable X.509 certificate parsing. - * - * Module: library/x509_crt.c - * Caller: library/ssl_cli.c - * library/ssl_srv.c - * library/ssl_tls.c - * - * Requires: POLARSSL_X509_USE_C - * - * This module is required for X.509 certificate parsing. - */ -#define POLARSSL_X509_CRT_PARSE_C - -/** - * \def POLARSSL_X509_CRL_PARSE_C - * - * Enable X.509 CRL parsing. - * - * Module: library/x509_crl.c - * Caller: library/x509_crt.c - * - * Requires: POLARSSL_X509_USE_C - * - * This module is required for X.509 CRL parsing. - */ -#define POLARSSL_X509_CRL_PARSE_C - -/** - * \def POLARSSL_X509_CSR_PARSE_C - * - * Enable X.509 Certificate Signing Request (CSR) parsing. - * - * Module: library/x509_csr.c - * Caller: library/x509_crt_write.c - * - * Requires: POLARSSL_X509_USE_C - * - * This module is used for reading X.509 certificate request. - */ -#define POLARSSL_X509_CSR_PARSE_C - -/** - * \def POLARSSL_X509_CREATE_C - * - * Enable X.509 core for creating certificates. - * - * Module: library/x509_create.c - * - * Requires: POLARSSL_BIGNUM_C, POLARSSL_OID_C, POLARSSL_PK_WRITE_C - * - * This module is the basis for creating X.509 certificates and CSRs. - */ -#define POLARSSL_X509_CREATE_C - -/** - * \def POLARSSL_X509_CRT_WRITE_C - * - * Enable creating X.509 certificates. - * - * Module: library/x509_crt_write.c - * - * Requires: POLARSSL_CREATE_C - * - * This module is required for X.509 certificate creation. - */ -#define POLARSSL_X509_CRT_WRITE_C - -/** - * \def POLARSSL_X509_CSR_WRITE_C - * - * Enable creating X.509 Certificate Signing Requests (CSR). - * - * Module: library/x509_csr_write.c - * - * Requires: POLARSSL_CREATE_C - * - * This module is required for X.509 certificate request writing. - */ -#define POLARSSL_X509_CSR_WRITE_C - -/** - * \def POLARSSL_XTEA_C - * - * Enable the XTEA block cipher. - * - * Module: library/xtea.c - * Caller: - */ -#define POLARSSL_XTEA_C - -/* \} name SECTION: PolarSSL modules */ - -/** - * \name SECTION: Module configuration options - * - * This section allows for the setting of module specific sizes and - * configuration options. The default values are already present in the - * relevant header files and should suffice for the regular use cases. - * - * Our advice is to enable options and change their values here - * only if you have a good reason and know the consequences. - * - * Please check the respective header file for documentation on these - * parameters (to prevent duplicate documentation). - * \{ - */ - -/* MPI / BIGNUM options */ -//#define POLARSSL_MPI_WINDOW_SIZE 6 /**< Maximum windows size used. */ -//#define POLARSSL_MPI_MAX_SIZE 1024 /**< Maximum number of bytes for usable MPIs. */ - -/* CTR_DRBG options */ -//#define CTR_DRBG_ENTROPY_LEN 48 /**< Amount of entropy used per seed by default (48 with SHA-512, 32 with SHA-256) */ -//#define CTR_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ -//#define CTR_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ -//#define CTR_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ -//#define CTR_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ - -/* HMAC_DRBG options */ -//#define POLARSSL_HMAC_DRBG_RESEED_INTERVAL 10000 /**< Interval before reseed is performed by default */ -//#define POLARSSL_HMAC_DRBG_MAX_INPUT 256 /**< Maximum number of additional input bytes */ -//#define POLARSSL_HMAC_DRBG_MAX_REQUEST 1024 /**< Maximum number of requested bytes per call */ -//#define POLARSSL_HMAC_DRBG_MAX_SEED_INPUT 384 /**< Maximum size of (re)seed buffer */ - -/* ECP options */ -//#define POLARSSL_ECP_MAX_BITS 521 /**< Maximum bit size of groups */ -//#define POLARSSL_ECP_WINDOW_SIZE 6 /**< Maximum window size used */ -//#define POLARSSL_ECP_FIXED_POINT_OPTIM 1 /**< Enable fixed-point speed-up */ - -/* Entropy options */ -//#define ENTROPY_MAX_SOURCES 20 /**< Maximum number of sources supported */ -//#define ENTROPY_MAX_GATHER 128 /**< Maximum amount requested from entropy sources */ - -/* Memory buffer allocator options */ -//#define POLARSSL_MEMORY_ALIGN_MULTIPLE 4 /**< Align on multiples of this value */ - -/* Platform options */ -//#define POLARSSL_PLATFORM_STD_MEM_HDR /**< Header to include if POLARSSL_PLATFORM_NO_STD_FUNCTIONS is defined. Don't define if no header is needed. */ -//#define POLARSSL_PLATFORM_STD_MALLOC malloc /**< Default allocator to use, can be undefined */ -//#define POLARSSL_PLATFORM_STD_FREE free /**< Default free to use, can be undefined */ -//#define POLARSSL_PLATFORM_STD_PRINTF printf /**< Default printf to use, can be undefined */ -//#define POLARSSL_PLATFORM_STD_FPRINTF fprintf /**< Default fprintf to use, can be undefined */ - -/* SSL Cache options */ -//#define SSL_CACHE_DEFAULT_TIMEOUT 86400 /**< 1 day */ -//#define SSL_CACHE_DEFAULT_MAX_ENTRIES 50 /**< Maximum entries in cache */ - -/* SSL options */ -//#define SSL_MAX_CONTENT_LEN 16384 /**< Size of the input / output buffer */ -//#define SSL_DEFAULT_TICKET_LIFETIME 86400 /**< Lifetime of session tickets (if enabled) */ -//#define POLARSSL_PSK_MAX_LEN 32 /**< Max size of TLS pre-shared keys, in bytes (default 256 bits) */ - -/** - * Complete list of ciphersuites to use, in order of preference. - * - * \warning No dependency checking is done on that field! This option can only - * be used to restrict the set of available ciphersuites. It is your - * responsibility to make sure the needed modules are active. - * - * Use this to save a few hundred bytes of ROM (default ordering of all - * available ciphersuites) and a few to a few hundred bytes of RAM. - * - * The value below is only an example, not the default. - */ -//#define SSL_CIPHERSUITES TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256 - -/* Debug options */ -//#define POLARSSL_DEBUG_DFL_MODE POLARSSL_DEBUG_LOG_FULL /**< Default log: Full or Raw */ - -/* \} name SECTION: Module configuration options */ - - -#endif /* POLARSSL_CONFIG_H */ From 9bff2ab74f721fb55afc0e9dc4df8517f58a0301 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 14 Nov 2018 15:06:28 +0100 Subject: [PATCH 0172/1938] CHG: cleaning up --- armsrc/Makefile | 1 - 1 file changed, 1 deletion(-) diff --git a/armsrc/Makefile b/armsrc/Makefile index d1895e7fa..a2092ac0b 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -31,7 +31,6 @@ APP_CFLAGS = -DWITH_CRC \ ### IMPORTANT - move the commented variable below this line # -DWITH_LCD \ # -DWITH_EMV \ -# -DWITH_FPC \ # # Standalone Mods #------------------------------------------------------- From e4cb74fedb165ea5d24e1b567d88dd3d29d63893 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 14 Nov 2018 15:07:04 +0100 Subject: [PATCH 0173/1938] chg: i2c comms, first try to recover i2c hangs. --- common/i2c.c | 48 ++++++++++++++++++++++++++++++++++++++++++------ common/i2c.h | 1 + 2 files changed, 43 insertions(+), 6 deletions(-) diff --git a/common/i2c.c b/common/i2c.c index 794564de3..200c8cf27 100644 --- a/common/i2c.c +++ b/common/i2c.c @@ -10,7 +10,6 @@ //----------------------------------------------------------------------------- #include "i2c.h" -// #define GPIO_RST AT91C_PIO_PA1 #define GPIO_SCL AT91C_PIO_PA5 #define GPIO_SDA AT91C_PIO_PA7 @@ -41,13 +40,41 @@ void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) { #define ISO7618_MAX_FRAME 255 +// try i2c bus recovery at 100kHz = 5uS high, 5uS low +void I2C_recovery(void) { + + DbpString("Performing i2c bus recovery"); + + // reset I2C + SDA_H; SCL_H; + + //9nth cycle acts as NACK + for (int i = 0; i < 10; i++) { + SCL_H; WaitUS(5); + SCL_L; WaitUS(5); + } + + //a STOP signal (SDA from low to high while CLK is high) + SDA_L; WaitUS(5); + SCL_H; WaitUS(2); + SDA_H; WaitUS(2); + + bool isok = (SCL_read && SDA_read); + if (!SDA_read) + DbpString("I2C bus recovery error: SDA still LOW"); + if (!SCL_read) + DbpString("I2C bus recovery error: SCL still LOW"); + if (isok) + DbpString("I2C bus recovery complete"); +} + void I2C_init(void) { // Configure reset pin, close up pull up, push-pull output, default high AT91C_BASE_PIOA->PIO_PPUDR = GPIO_RST; AT91C_BASE_PIOA->PIO_MDDR = GPIO_RST; // Configure I2C pin, open up, open leakage - AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_SCL | GPIO_SDA); // Open up the pull up + AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_SCL | GPIO_SDA); AT91C_BASE_PIOA->PIO_MDER |= (GPIO_SCL | GPIO_SDA); // default three lines all pull up @@ -55,6 +82,12 @@ void I2C_init(void) { AT91C_BASE_PIOA->PIO_OER |= (GPIO_SCL | GPIO_SDA | GPIO_RST); AT91C_BASE_PIOA->PIO_PER |= (GPIO_SCL | GPIO_SDA | GPIO_RST); + + + bool isok = (SCL_read && SDA_read); + if ( !isok ) + I2C_recovery(); + } // set the reset state @@ -78,6 +111,8 @@ void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) { // Reset the SIM_Adapter, then enter the main program // Note: the SIM_Adapter will not enter the main program after power up. Please run this function before use SIM_Adapter. void I2C_Reset_EnterMainProgram(void) { + I2C_init(); + I2C_SetResetStatus(0, 0, 0); SpinDelay(30); I2C_SetResetStatus(1, 0, 0); @@ -157,7 +192,7 @@ bool I2C_Start(void) { } bool I2C_WaitForSim() { - // variable delay here. + if (!WaitSCL_L_300ms()) return false; @@ -631,6 +666,7 @@ void SmartCardAtr(void) { LED_D_ON(); clear_trace(); set_tracing(true); + I2C_init(); I2C_Reset_EnterMainProgram(); bool isOK = GetATR( &card ); cmd_send(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t)); @@ -650,12 +686,12 @@ void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) { clear_trace(); set_tracing(true); - - if ((flags & SC_CONNECT)) { + if ((flags & SC_CONNECT)) { + I2C_Reset_EnterMainProgram(); - if ( !(flags & SC_NO_SELECT) ) { + if ((flags & SC_SELECT)) { smart_card_atr_t card; bool gotATR = GetATR( &card ); //cmd_send(CMD_ACK, gotATR, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t)); diff --git a/common/i2c.h b/common/i2c.h index e6350ecfd..8350029bd 100644 --- a/common/i2c.h +++ b/common/i2c.h @@ -19,6 +19,7 @@ #define I2C_DEVICE_CMD_GETVERSION 0x06 +void I2C_recovery(void); void I2C_init(void); void I2C_Reset(void); void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA); From 526f50aa9d42220ced64752d0aa98a0b0c3b1f50 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 14 Nov 2018 15:11:30 +0100 Subject: [PATCH 0174/1938] fix: 'hf iclass loclass' - remove warning on gcc4.9.2 mingw. don't like the declaration. mbedtls_des_context ctx_dec = {0}; chg: 'hf iclass loclass t' - added some path tests for key file. --- client/loclass/cipher.c | 12 +++----- client/loclass/cipherutils.c | 35 +++++++++------------ client/loclass/elite_crack.c | 18 +++++------ client/loclass/ikeys.c | 59 ++++++++++++++++++++---------------- 4 files changed, 60 insertions(+), 64 deletions(-) diff --git a/client/loclass/cipher.c b/client/loclass/cipher.c index 942abd437..af11ce4cc 100644 --- a/client/loclass/cipher.c +++ b/client/loclass/cipher.c @@ -275,18 +275,14 @@ int testMAC() uint8_t calculated_mac[4] = {0}; doMAC(cc_nr,div_key, calculated_mac); - if(memcmp(calculated_mac, correct_MAC,4) == 0) - { + if (memcmp(calculated_mac, correct_MAC,4) == 0) { PrintAndLogDevice(SUCCESS, "MAC calculation OK!"); - - }else - { + } else { PrintAndLogDevice(FAILED, "FAILED: MAC calculation failed:"); printarr(" Calculated_MAC", calculated_mac, 4); printarr(" Correct_MAC ", correct_MAC, 4); - return 1; -} - + return 1; + } return 0; } #endif diff --git a/client/loclass/cipherutils.c b/client/loclass/cipherutils.c index a6f7e92d1..e22c88894 100644 --- a/client/loclass/cipherutils.c +++ b/client/loclass/cipherutils.c @@ -205,19 +205,17 @@ int testBitStream() uint8_t input [] = {0xDE,0xAD,0xBE,0xEF,0xDE,0xAD,0xBE,0xEF}; uint8_t output [] = {0,0,0,0,0,0,0,0}; BitstreamIn in = { input, sizeof(input) * 8,0}; - BitstreamOut out ={ output, 0,0} + BitstreamOut out = { output, 0,0} ; - while(bitsLeft(&in) > 0) - { + while (bitsLeft(&in) > 0) { pushBit(&out, headBit(&in)); //printf("Bits left: %d\n", bitsLeft(&in)); //printf("Bits out: %d\n", numBits(&out)); } - if(memcmp(input, output, sizeof(input)) == 0) - { + + if(memcmp(input, output, sizeof(input)) == 0) { PrintAndLogDevice(SUCCESS, " Bitstream test 1 ok"); - }else - { + } else { PrintAndLogDevice(FAILED, " Bitstream test 1 failed"); uint8_t i; for(i = 0 ; i < sizeof(input) ; i++) @@ -235,27 +233,24 @@ int testReversedBitstream() uint8_t reverse [] = {0,0,0,0,0,0,0,0}; uint8_t output [] = {0,0,0,0,0,0,0,0}; BitstreamIn in = { input, sizeof(input) * 8,0}; - BitstreamOut out ={ output, 0,0}; - BitstreamIn reversed_in ={ reverse, sizeof(input)*8,0}; - BitstreamOut reversed_out ={ reverse,0 ,0}; + BitstreamOut out = { output, 0,0}; + BitstreamIn reversed_in = { reverse, sizeof(input)*8,0}; + BitstreamOut reversed_out = { reverse,0 ,0}; - while(bitsLeft(&in) > 0) - { + while (bitsLeft(&in) > 0) { pushBit(&reversed_out, tailBit(&in)); } - while(bitsLeft(&reversed_in) > 0) - { + + while (bitsLeft(&reversed_in) > 0) { pushBit(&out, tailBit(&reversed_in)); } - if(memcmp(input, output, sizeof(input)) == 0) - { + + if (memcmp(input, output, sizeof(input)) == 0) { PrintAndLogDevice(SUCCESS, " Bitstream test 2 ok"); - }else - { + } else { PrintAndLogDevice(FAILED, " Bitstream test 2 failed"); uint8_t i; - for(i = 0 ; i < sizeof(input) ; i++) - { + for (i = 0 ; i < sizeof(input) ; i++) { PrintAndLogDevice(NORMAL, " IN %02x, MIDDLE: %02x, OUT %02x", input[i],reverse[i], output[i]); } return 1; diff --git a/client/loclass/elite_crack.c b/client/loclass/elite_crack.c index 068fdf59f..2002e348f 100644 --- a/client/loclass/elite_crack.c +++ b/client/loclass/elite_crack.c @@ -108,7 +108,7 @@ void permutekey_rev(uint8_t key[8], uint8_t dest[8]) { * @param val * @return */ -uint8_t rr(uint8_t val) { +inline uint8_t rr(uint8_t val) { return val >> 1 | (( val & 1) << 7); } @@ -118,7 +118,7 @@ uint8_t rr(uint8_t val) { * @param val * @return */ -uint8_t rl(uint8_t val) { +inline uint8_t rl(uint8_t val) { return val << 1 | (( val & 0x80) >> 7); } @@ -128,7 +128,7 @@ uint8_t rl(uint8_t val) { * @param val * @return */ -uint8_t swap(uint8_t val) { +inline uint8_t swap(uint8_t val) { return ((val >> 4) & 0xFF) | ((val &0xFF) << 4); } @@ -172,8 +172,8 @@ void rk(uint8_t *key, uint8_t n, uint8_t *outp_key) { return; } -static mbedtls_des_context ctx_enc = {0}; -static mbedtls_des_context ctx_dec = {0}; +static mbedtls_des_context ctx_enc; +static mbedtls_des_context ctx_dec; void desdecrypt_iclass(uint8_t *iclass_key, uint8_t *input, uint8_t *output) { uint8_t key_std_format[8] = {0}; @@ -431,7 +431,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) { * @return 0 for ok, 1 for failz */ int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[] ){ - mbedtls_des_context ctx_e = {0}; + mbedtls_des_context ctx_e; uint8_t z_0[8] = {0}; uint8_t y_0[8] = {0}; @@ -441,8 +441,8 @@ int calculateMasterKey(uint8_t first16bytes[], uint64_t master_key[] ){ uint8_t result[8] = {0}; // y_0 and z_0 are the first 16 bytes of the keytable - memcpy(y_0,first16bytes,8); - memcpy(z_0,first16bytes+8,8); + memcpy(y_0, first16bytes,8); + memcpy(z_0, first16bytes+8,8); // Our DES-implementation uses the standard NIST // format for keys, thus must translate from iclass @@ -672,8 +672,6 @@ int testElite() { 60 3F 88 6F B8 6C 2C 93 0D 69 2C D5 20 3C C1 61 95 70 43 08 A0 2F FE B3 26 D7 98 0B 34 7B 47 70 A0 AB - - **** The 64-bit HS Custom Key Value = 5B7C62C491C11B39 **** */ uint8_t keytable[128] = {0}; diff --git a/client/loclass/ikeys.c b/client/loclass/ikeys.c index 6a68d80b1..aefbbaf99 100644 --- a/client/loclass/ikeys.c +++ b/client/loclass/ikeys.c @@ -69,8 +69,8 @@ From "Dismantling iclass": uint8_t pi[35] = {0x0F,0x17,0x1B,0x1D,0x1E,0x27,0x2B,0x2D,0x2E,0x33,0x35,0x39,0x36,0x3A,0x3C,0x47,0x4B,0x4D,0x4E,0x53,0x55,0x56,0x59,0x5A,0x5C,0x63,0x65,0x66,0x69,0x6A,0x6C,0x71,0x72,0x74,0x78}; -static mbedtls_des_context ctx_enc = {0}; -static mbedtls_des_context ctx_dec = {0}; +static mbedtls_des_context ctx_enc; +static mbedtls_des_context ctx_dec; static int debug_print = 0; @@ -442,11 +442,10 @@ int testDES(Testcase testcase, mbedtls_des_context ctx_enc, mbedtls_des_context uint8_t des_encrypted_csn[8] = {0}; uint8_t decrypted[8] = {0}; uint8_t div_key[8] = {0}; - int retval = mbedtls_des_crypt_ecb(&ctx_enc,testcase.uid,des_encrypted_csn); - retval |= mbedtls_des_crypt_ecb(&ctx_dec,des_encrypted_csn,decrypted); + int retval = mbedtls_des_crypt_ecb(&ctx_enc, testcase.uid, des_encrypted_csn); + retval |= mbedtls_des_crypt_ecb(&ctx_dec, des_encrypted_csn, decrypted); - if(memcmp(testcase.uid,decrypted,8) != 0) - { + if (memcmp(testcase.uid, decrypted, 8) != 0) { //Decryption fail PrintAndLogDevice(FAILED, "Encryption <-> Decryption FAIL"); printarr("Input", testcase.uid, 8); @@ -454,8 +453,7 @@ int testDES(Testcase testcase, mbedtls_des_context ctx_enc, mbedtls_des_context retval = 1; } - if(memcmp(des_encrypted_csn,testcase.t_key,8) != 0) - { + if (memcmp(des_encrypted_csn, testcase.t_key, 8) != 0) { //Encryption fail PrintAndLogDevice(FAILED, "Encryption != Expected result"); printarr("Output", des_encrypted_csn, 8); @@ -465,8 +463,7 @@ int testDES(Testcase testcase, mbedtls_des_context ctx_enc, mbedtls_des_context uint64_t crypted_csn = x_bytes_to_num(des_encrypted_csn,8); hash0(crypted_csn, div_key); - if(memcmp(div_key, testcase.div_key ,8) != 0) - { + if (memcmp(div_key, testcase.div_key, 8) != 0) { //Key diversification fail PrintAndLogDevice(FAILED, "Div key != expected result"); printarr(" csn ", testcase.uid,8); @@ -575,13 +572,12 @@ Testcase testcases[] ={ }; int testKeyDiversificationWithMasterkeyTestcases() { - int error = 0; - int i; - uint8_t empty[8]={0}; + int i, error = 0; + uint8_t empty[8] = {0}; PrintAndLogDevice(INFO, "Testing encryption/decryption"); - for (i = 0; memcmp(testcases+i, empty, 8); i++) + for (i = 0; memcmp(testcases+i, empty, 8); i++) error += testDES(testcases[i], ctx_enc, ctx_dec); if (error) @@ -592,26 +588,26 @@ int testKeyDiversificationWithMasterkeyTestcases() { } void print64bits(char*name, uint64_t val) { - printf("%s%08x%08x\n",name,(uint32_t) (val >> 32) ,(uint32_t) (val & 0xFFFFFFFF)); + printf("%s%08x%08x\n", name, (uint32_t) (val >> 32) ,(uint32_t) (val & 0xFFFFFFFF)); } uint64_t testCryptedCSN(uint64_t crypted_csn, uint64_t expected) { int retval = 0; uint8_t result[8] = {0}; - if(debug_print) PrintAndLogDevice(DEBUG, "debug_print %d", debug_print); - if(debug_print) print64bits(" {csn} ", crypted_csn ); + if (debug_print) PrintAndLogDevice(DEBUG, "debug_print %d", debug_print); + if (debug_print) print64bits(" {csn} ", crypted_csn ); uint64_t crypted_csn_swapped = swapZvalues(crypted_csn); - if(debug_print) print64bits(" {csn-revz} ", crypted_csn_swapped); + if (debug_print) print64bits(" {csn-revz} ", crypted_csn_swapped); hash0(crypted_csn, result); uint64_t resultbyte = x_bytes_to_num(result,8 ); - if(debug_print) print64bits(" hash0 " , resultbyte ); + if (debug_print) print64bits(" hash0 " , resultbyte ); - if(resultbyte != expected ) { - if(debug_print) { + if (resultbyte != expected ) { + if (debug_print) { PrintAndLogDevice(NORMAL, "\n"); PrintAndLogDevice(FAILED, "FAIL!"); print64bits(" expected " , expected ); } @@ -627,9 +623,9 @@ int testDES2(uint64_t csn, uint64_t expected) { uint8_t input[8] = {0}; print64bits(" csn ", csn); - x_num_to_bytes(csn, 8,input); + x_num_to_bytes(csn, 8, input); - mbedtls_des_crypt_ecb(&ctx_enc,input, result); + mbedtls_des_crypt_ecb(&ctx_enc, input, result); uint64_t crypt_csn = x_bytes_to_num(result, 8); print64bits(" {csn} ", crypt_csn ); @@ -678,10 +674,21 @@ int doTestsWithKnownInputs() { static bool readKeyFile(uint8_t key[8]) { bool retval = false; - FILE *f = fopen("iclass_key.bin", "rb"); + + //Test a few variants + char filename[30]; + if (fileExists("iclass_key.bin")){ + sprintf(filename, "%s.bin", "iclass_key"); + } else if (fileExists("loclass/iclass_key.bin")){ + sprintf(filename, "%s.bin", "loclass/iclass_key"); + } else if (fileExists("client/loclass/iclass_key.bin")){ + sprintf(filename, "%s.bin", "client/loclass/iclass_key"); + } + + FILE *f = fopen(filename, "rb"); if (!f) return retval; - + size_t bytes_read = fread(key, sizeof(uint8_t), 8, f); if ( bytes_read == 8) retval = true; @@ -696,7 +703,7 @@ int doKeyTests(uint8_t debuglevel) { PrintAndLogDevice(INFO, "Checking if the master key is present (iclass_key.bin)..."); uint8_t key[8] = {0}; - if (readKeyFile(key)) { + if (!readKeyFile(key)) { PrintAndLogDevice(FAILED, "Master key not present, will not be able to do all testcases"); } else { From 25292eab2eb75da5cad581a96739ca77af7e719e Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 14 Nov 2018 15:13:17 +0100 Subject: [PATCH 0175/1938] fix: more warnings. --- client/cmdhficlass.c | 4 ++-- client/cmdhfmfu.c | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 0c9d67d6e..368aaad2e 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -766,7 +766,7 @@ int CmdHFiClassDecrypt(const char *Cmd) { hdr->csn[4],hdr->csn[5],hdr->csn[6],hdr->csn[7]); // tripledes - mbedtls_des3_context ctx = { 0 }; + mbedtls_des3_context ctx; mbedtls_des3_set2key_dec( &ctx, key); uint8_t enc_dump[8] = {0}; @@ -797,7 +797,7 @@ static int iClassEncryptBlkData(uint8_t *blkData) { PrintAndLogEx(SUCCESS, "decryption file found"); uint8_t encryptedData[16]; uint8_t *encrypted = encryptedData; - mbedtls_des3_context ctx = { 0 }; + mbedtls_des3_context ctx; mbedtls_des3_set2key_enc( &ctx, key); mbedtls_des3_crypt_ecb(&ctx, blkData,encrypted); diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 72c4be573..327069971 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -2392,10 +2392,10 @@ int CmdHF14AMfucSetUid(const char *Cmd){ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ uint8_t uid[4]; - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_hf_mfu_gendiverse(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_gendiverse(); - if ( cmdp == 'r' || cmdp == 'R') { + if ( cmdp == 'r' ) { // read uid from tag UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0}}; clearCommandBuffer(); @@ -2441,7 +2441,7 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ mix[6] = block ^ uid[2]; mix[7] = uid[3]; - mbedtls_des3_context ctx = { 0x00 }; + mbedtls_des3_context ctx; mbedtls_des3_set2key_enc(&ctx, masterkey); mbedtls_des3_crypt_cbc(&ctx // des3_context @@ -2501,11 +2501,11 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ int CmdHF14AMfuPwdGen(const char *Cmd){ uint8_t uid[7] = {0x00}; - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_hf_mfu_pwdgen(); - if (cmdp == 't' || cmdp == 'T') return ul_ev1_pwdgen_selftest(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_pwdgen(); + if (cmdp == 't') return ul_ev1_pwdgen_selftest(); - if ( cmdp == 'r' || cmdp == 'R') { + if ( cmdp == 'r') { // read uid from tag UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0}}; clearCommandBuffer(); From 3e53c3a5e7d7e70332843321782e248e491f21ba Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 14 Nov 2018 15:14:05 +0100 Subject: [PATCH 0176/1938] chg: some more default keys in the general list. --- client/mifaredefault.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/mifaredefault.h b/client/mifaredefault.h index 78713262c..400463eaf 100644 --- a/client/mifaredefault.h +++ b/client/mifaredefault.h @@ -36,7 +36,10 @@ static const uint64_t g_mifare_default_keys[] = 0x587ee5f9350f, 0xa0478cc39091, 0x533cb6c723f6, - 0x8fd0a4f256e9 + 0x8fd0a4f256e9, + 0x0000014b5c31, + 0xb578f38a5c61, + 0x96a301bce267 }; #endif From 64df44d186a65d03b6f2fa427187356fb7fd2442 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 14 Nov 2018 15:14:31 +0100 Subject: [PATCH 0177/1938] cleaning --- client/cmdlft55xx.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index bf73d6ff5..ed8c0464e 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1517,13 +1517,13 @@ int CmdT55xxBruteForce(const char *Cmd) { memset(line, 0, sizeof(line)); - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_t55xx_bruteforce(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_t55xx_bruteforce(); keyBlock = calloc(stKeyBlock, 4); if (keyBlock == NULL) return 1; - if (cmdp == 'i' || cmdp == 'I') { + if (cmdp == 'i') { int len = strlen(Cmd+2); if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; @@ -1786,7 +1786,7 @@ bool tryDetectP1(bool getData) { // try ask clock detect. it could be another type even if successful. clk = GetAskClock("", false); - if (clk>0) { + if (clk > 0) { if ( ASKDemod_ext("0 0 1", false, false, 1, &st) && preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64) ) { From cc6cd93ea746d3c2ea6cb56f1a8d6c5c51539a72 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 14 Nov 2018 18:11:05 +0200 Subject: [PATCH 0178/1938] save raw --- client/loclass/fileutils.c | 35 +++++++++++++++++++++++++++++++++-- client/loclass/fileutils.h | 1 + 2 files changed, 34 insertions(+), 2 deletions(-) diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 44bab0193..ac3660935 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -136,8 +136,39 @@ out: } int saveFileJSON(const char *preferredName, const char *suffix, uint8_t* data, size_t datalen) { - //stub - for merlokk ;) - return 1; + if ( preferredName == NULL ) return 1; + if ( suffix == NULL ) return 1; + if ( data == NULL ) return 1; + + int retval = 0; + int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10); + char * fileName = calloc(size, sizeof(char)); + int num = 1; + sprintf(fileName,"%s.%s", preferredName, suffix); + while (fileExists(fileName)) { + sprintf(fileName,"%s-%d.%s", preferredName, num, suffix); + num++; + } + + json_t *root = json_object(); + JsonSaveStr(root, "Created", "proxmark3"); + JsonSaveBufAsHexCompact(root, "raw", data, datalen); + + int res = json_dump_file(root, fileName, JSON_INDENT(2)); + if (res) { + PrintAndLog("ERROR: can't save the file: %s", fileName); + json_decref(root); + retval = 200; + goto out; + } + PrintAndLog("File `%s` saved.", fileName); + + // free json object + json_decref(root); + +out: + free(fileName); + return retval; } int loadFile(const char *preferredName, const char *suffix, void* data, size_t* datalen) { diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index 40bd7cfeb..0893e01ea 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -47,6 +47,7 @@ #include #include #include "../ui.h" +#include "../emv/emvjson.h" int fileExists(const char *filename); From 5e3fa42c2315cdd811220d97c31c2e19392073a0 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 14 Nov 2018 18:44:17 +0200 Subject: [PATCH 0179/1938] add der print sketch --- client/cmdhffido.c | 3 +++ client/crypto/asn1utils.c | 2 +- client/crypto/asn1utils.h | 2 +- 3 files changed, 5 insertions(+), 2 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index ffd277bd2..6440554f0 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -340,6 +340,9 @@ int CmdHFFidoRegister(const char *cmd) { uint8_t public_key[65] = {0}; // TODO: print DER certificate in DER view + PrintAndLog("----------------DER TLV-----------------"); + asn1_print(&buf[67 + keyHandleLen], derLen, " "); + PrintAndLog("----------------DER TLV-----------------"); // load CA's mbedtls_x509_crt cacert; diff --git a/client/crypto/asn1utils.c b/client/crypto/asn1utils.c index 2a3fe698b..78677765d 100644 --- a/client/crypto/asn1utils.c +++ b/client/crypto/asn1utils.c @@ -55,7 +55,7 @@ exit: return res; } -int asn1_print(uint8_t *asn1buf, int level) { +int asn1_print(uint8_t *asn1buf, size_t asn1buflen, char *indent) { return 0; } diff --git a/client/crypto/asn1utils.h b/client/crypto/asn1utils.h index 2b00f4501..19f8ded70 100644 --- a/client/crypto/asn1utils.h +++ b/client/crypto/asn1utils.h @@ -15,7 +15,7 @@ #include #include -extern int asn1_print(uint8_t *asn1buf, int level); +extern int asn1_print(uint8_t *asn1buf, size_t asn1buflen, char *indent); extern int ecdsa_asn1_get_signature(uint8_t *signature, size_t signaturelen, uint8_t *rval, uint8_t *sval); #endif /* asn1utils.h */ From 46769838f258ab715ab0520912d50ca6f44e1539 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 14 Nov 2018 19:26:19 +0200 Subject: [PATCH 0180/1938] fix tlv.c --- client/emv/tlv.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/client/emv/tlv.c b/client/emv/tlv.c index 540c33e4c..35bdb5d4c 100644 --- a/client/emv/tlv.c +++ b/client/emv/tlv.c @@ -92,16 +92,15 @@ static size_t tlv_parse_len(const unsigned char **buf, size_t *len) return l; size_t ll = l &~ TLV_LEN_LONG; - if (*len < ll) + if (ll > 5) return TLV_LEN_INVALID; - /* FIXME */ - if (ll != 1) - return TLV_LEN_INVALID; - - l = **buf; - --*len; - ++*buf; + l = 0; + for (int i = 1; i <= ll; i++) { + l = (l << 8) + **buf; + --*len; + ++*buf; + } return l; } From 5eb3181263164035cfaf81050742e43e3a115fed Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 14 Nov 2018 20:44:32 +0200 Subject: [PATCH 0181/1938] added ASN.1 decoder --- client/cmdhffido.c | 6 +- client/crypto/asn1utils.c | 190 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 193 insertions(+), 3 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 6440554f0..5151709af 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -328,7 +328,7 @@ int CmdHFFidoRegister(const char *cmd) { int derLen = (buf[derp + 2] << 8) + buf[derp + 3] + 4; if (verbose2) { PrintAndLog("DER certificate[%d]:\n------------------DER-------------------", derLen); - dump_buffer_simple((const unsigned char *)&buf[67 + keyHandleLen], derLen, NULL); + dump_buffer_simple((const unsigned char *)&buf[derp], derLen, NULL); PrintAndLog("\n----------------DER---------------------"); } else { if (verbose) @@ -341,7 +341,7 @@ int CmdHFFidoRegister(const char *cmd) { // TODO: print DER certificate in DER view PrintAndLog("----------------DER TLV-----------------"); - asn1_print(&buf[67 + keyHandleLen], derLen, " "); + asn1_print(&buf[derp], derLen, " "); PrintAndLog("----------------DER TLV-----------------"); // load CA's @@ -357,7 +357,7 @@ int CmdHFFidoRegister(const char *cmd) { // load DER certificate from authenticator's data mbedtls_x509_crt cert; mbedtls_x509_crt_init(&cert); - res = mbedtls_x509_crt_parse_der(&cert, &buf[67 + keyHandleLen], derLen); + res = mbedtls_x509_crt_parse_der(&cert, &buf[derp], derLen); if (res) { PrintAndLog("ERROR: DER parse returned 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res)); } diff --git a/client/crypto/asn1utils.c b/client/crypto/asn1utils.c index 78677765d..5f66ed022 100644 --- a/client/crypto/asn1utils.c +++ b/client/crypto/asn1utils.c @@ -10,6 +10,11 @@ #include "asn1utils.h" #include +#include +#include "util.h" +#include "emv/tlv.h" +#include "emv/emv_tags.h" +#include "emv/dump.h" int ecdsa_asn1_get_signature(uint8_t *signature, size_t signaturelen, uint8_t *rval, uint8_t *sval) { if (!signature || !signaturelen || !rval || !sval) @@ -55,8 +60,193 @@ exit: return res; } +#define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, " ");} + +enum asn1_tag_t { + ASN1_TAG_GENERIC, + ASN1_TAG_BOOLEAN, + ASN1_TAG_INTEGER, + ASN1_TAG_STRING, + ASN1_TAG_UTC_TIME, + ASN1_TAG_OBJECT_ID, +}; + +struct asn1_tag { + tlv_tag_t tag; + char *name; + enum asn1_tag_t type; + const void *data; +}; + +static const struct asn1_tag asn1_tags[] = { + // internal + { 0x00 , "Unknown ???" }, + + // ASN.1 + { 0x01, "BOOLEAN", ASN1_TAG_BOOLEAN }, + { 0x02, "INTEGER", ASN1_TAG_INTEGER }, + { 0x03, "BIT STRING" }, + { 0x04, "OCTET STRING" }, + { 0x05, "NULL" }, + { 0x06, "OBJECT IDENTIFIER", ASN1_TAG_OBJECT_ID }, + { 0x0C, "UTF8String", ASN1_TAG_STRING }, + { 0x10, "SEQUENCE" }, + { 0x11, "SET" }, + { 0x13, "PrintableString", ASN1_TAG_STRING }, + { 0x14, "T61String", ASN1_TAG_STRING }, + { 0x16, "IA5String", ASN1_TAG_STRING }, + { 0x17, "UTCTime", ASN1_TAG_UTC_TIME }, + { 0x18, "GeneralizedTime", ASN1_TAG_UTC_TIME }, + { 0x30, "SEQUENCE" }, + { 0x31, "SET" }, + { 0xa0, "[0]" }, + { 0xa1, "[1]" }, + { 0xa2, "[2]" }, + { 0xa3, "[3]" }, + { 0xa4, "[4]" }, + { 0xa5, "[5]" }, +}; + +static int asn1_sort_tag(tlv_tag_t tag) { + return (int)(tag >= 0x100 ? tag : tag << 8); +} + +static int asn1_tlv_compare(const void *a, const void *b) { + const struct tlv *tlv = a; + const struct asn1_tag *tag = b; + + return asn1_sort_tag(tlv->tag) - (asn1_sort_tag(tag->tag)); +} + +static const struct asn1_tag *asn1_get_tag(const struct tlv *tlv) { + struct asn1_tag *tag = bsearch(tlv, asn1_tags, sizeof(asn1_tags) / sizeof(asn1_tags[0]), + sizeof(asn1_tags[0]), asn1_tlv_compare); + + return tag ? tag : &asn1_tags[0]; +} + +static void asn1_tag_dump_string(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level){ + fprintf(f, "\tvalue: '"); + fwrite(tlv->value, 1, tlv->len, f); + fprintf(f, "'\n"); +} + +static unsigned long asn1_value_integer(const struct tlv *tlv, unsigned start, unsigned end) { + unsigned long ret = 0; + int i; + + if (end > tlv->len * 2) + return ret; + if (start >= end) + return ret; + + if (start & 1) { + ret += tlv->value[start/2] & 0xf; + i = start + 1; + } else + i = start; + + for (; i < end - 1; i += 2) { + ret *= 10; + ret += tlv->value[i/2] >> 4; + ret *= 10; + ret += tlv->value[i/2] & 0xf; + } + + if (end & 1) { + ret *= 10; + ret += tlv->value[end/2] >> 4; + } + + return ret; +} + +static void asn1_tag_dump_boolean(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level) { + PRINT_INDENT(level); + if (tlv->len > 0) { + fprintf(f, "\tvalue: %s\n", tlv->value[0]?"true":"false"); + } else { + fprintf(f, "n/a\n"); + } +} + +static void asn1_tag_dump_integer(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level) { + PRINT_INDENT(level); + fprintf(f, "\tvalue: %lu\n", asn1_value_integer(tlv, 0, tlv->len * 2)); +} + +static void asn1_tag_dump_object_id(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level) { + PRINT_INDENT(level); + mbedtls_asn1_buf asn1_buf; + asn1_buf.len = tlv->len; + asn1_buf.p = (uint8_t *)tlv->value; + char pstr[300]; + mbedtls_oid_get_numeric_string(pstr, sizeof(pstr), &asn1_buf); + fprintf(f, " %s\n", pstr); +} + +bool asn1_tag_dump(const struct tlv *tlv, FILE *f, int level, bool *candump) { + if (!tlv) { + fprintf(f, "NULL\n"); + return false; + } + + const struct asn1_tag *tag = asn1_get_tag(tlv); + + PRINT_INDENT(level); + fprintf(f, "--%2hx[%02zx] '%s':", tlv->tag, tlv->len, tag->name); + + switch (tag->type) { + case ASN1_TAG_GENERIC: + fprintf(f, "\n"); + break; + case ASN1_TAG_STRING: + asn1_tag_dump_string(tlv, tag, f, level); + *candump = false; + break; + case ASN1_TAG_BOOLEAN: + asn1_tag_dump_boolean(tlv, tag, f, level); + *candump = false; + break; + case ASN1_TAG_INTEGER: + asn1_tag_dump_integer(tlv, tag, f, level); + *candump = false; + break; + case ASN1_TAG_UTC_TIME: +// asn1_tag_dump_utc_time(tlv, tag, f, level); + fprintf(f, "\n"); + break; + case ASN1_TAG_OBJECT_ID: + asn1_tag_dump_object_id(tlv, tag, f, level); + *candump = false; + break; + }; + + return true; +} + +static bool print_cb(void *data, const struct tlv *tlv, int level, bool is_leaf) { + bool candump = true; + asn1_tag_dump(tlv, stdout, level, &candump); + if (is_leaf && candump) { + dump_buffer(tlv->value, tlv->len, stdout, level); + } + + return true; +} + int asn1_print(uint8_t *asn1buf, size_t asn1buflen, char *indent) { + struct tlvdb *t = NULL; + t = tlvdb_parse_multi(asn1buf, asn1buflen); + if (t) { + tlvdb_visit(t, print_cb, NULL, 0); + tlvdb_free(t); + } else { + PrintAndLogEx(ERR, "Can't parse data as TLV tree."); + return 1; + } + return 0; } From 9d420489016472d1f530ec5ee8fad73675258742 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Nov 2018 11:47:09 +0200 Subject: [PATCH 0182/1938] added octet string an dstring datetime --- client/crypto/asn1utils.c | 77 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 75 insertions(+), 2 deletions(-) diff --git a/client/crypto/asn1utils.c b/client/crypto/asn1utils.c index 5f66ed022..b19e27993 100644 --- a/client/crypto/asn1utils.c +++ b/client/crypto/asn1utils.c @@ -9,6 +9,7 @@ //----------------------------------------------------------------------------- #include "asn1utils.h" +#include #include #include #include "util.h" @@ -67,7 +68,9 @@ enum asn1_tag_t { ASN1_TAG_BOOLEAN, ASN1_TAG_INTEGER, ASN1_TAG_STRING, + ASN1_TAG_OCTET_STRING, ASN1_TAG_UTC_TIME, + ASN1_TAG_STR_TIME, ASN1_TAG_OBJECT_ID, }; @@ -86,7 +89,7 @@ static const struct asn1_tag asn1_tags[] = { { 0x01, "BOOLEAN", ASN1_TAG_BOOLEAN }, { 0x02, "INTEGER", ASN1_TAG_INTEGER }, { 0x03, "BIT STRING" }, - { 0x04, "OCTET STRING" }, + { 0x04, "OCTET STRING", ASN1_TAG_OCTET_STRING}, { 0x05, "NULL" }, { 0x06, "OBJECT IDENTIFIER", ASN1_TAG_OBJECT_ID }, { 0x0C, "UTF8String", ASN1_TAG_STRING }, @@ -96,7 +99,7 @@ static const struct asn1_tag asn1_tags[] = { { 0x14, "T61String", ASN1_TAG_STRING }, { 0x16, "IA5String", ASN1_TAG_STRING }, { 0x17, "UTCTime", ASN1_TAG_UTC_TIME }, - { 0x18, "GeneralizedTime", ASN1_TAG_UTC_TIME }, + { 0x18, "GeneralizedTime", ASN1_TAG_STR_TIME }, { 0x30, "SEQUENCE" }, { 0x31, "SET" }, { 0xa0, "[0]" }, @@ -125,12 +128,76 @@ static const struct asn1_tag *asn1_get_tag(const struct tlv *tlv) { return tag ? tag : &asn1_tags[0]; } +static void asn1_tag_dump_str_time(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level, bool *needdump){ + int len = tlv->len; + *needdump = true; + + if (len > 4) { + fprintf(f, "\tvalue: '"); + while (true) { + // year + fwrite(tlv->value, 1, 4, f); + fprintf(f, "-"); + if (len < 6) + break; + // month + fwrite(&tlv->value[4], 1, 2, f); + fprintf(f, "-"); + if (len < 8) + break; + // day + fwrite(&tlv->value[6], 1, 2, f); + fprintf(f, " "); + if (len < 10) + break; + // hour + fwrite(&tlv->value[8], 1, 2, f); + fprintf(f, ":"); + if (len < 12) + break; + // min + fwrite(&tlv->value[10], 1, 2, f); + fprintf(f, ":"); + if (len < 14) + break; + // sec + fwrite(&tlv->value[12], 1, 2, f); + if (len < 15) + break; + // time zone + fprintf(f, " zone: %.*s", len - 14, &tlv->value[14]); + + break; + } + fprintf(f, "'\n"); + } else { + fprintf(f, "\n"); + *needdump = true; + } +} + static void asn1_tag_dump_string(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level){ fprintf(f, "\tvalue: '"); fwrite(tlv->value, 1, tlv->len, f); fprintf(f, "'\n"); } +static void asn1_tag_dump_octet_string(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level, bool *needdump){ + *needdump = false; + for (int i = 0; i < tlv->len; i++) + if (!isspace(tlv->value[i]) && !isprint(tlv->value[i])){ + *needdump = true; + break; + } + + if (*needdump) { + fprintf(f, "'\n"); + } else { + fprintf(f, "\t\t"); + asn1_tag_dump_string(tlv, tag, f, level); + } +} + static unsigned long asn1_value_integer(const struct tlv *tlv, unsigned start, unsigned end) { unsigned long ret = 0; int i; @@ -204,6 +271,9 @@ bool asn1_tag_dump(const struct tlv *tlv, FILE *f, int level, bool *candump) { asn1_tag_dump_string(tlv, tag, f, level); *candump = false; break; + case ASN1_TAG_OCTET_STRING: + asn1_tag_dump_octet_string(tlv, tag, f, level, candump); + break; case ASN1_TAG_BOOLEAN: asn1_tag_dump_boolean(tlv, tag, f, level); *candump = false; @@ -216,6 +286,9 @@ bool asn1_tag_dump(const struct tlv *tlv, FILE *f, int level, bool *candump) { // asn1_tag_dump_utc_time(tlv, tag, f, level); fprintf(f, "\n"); break; + case ASN1_TAG_STR_TIME: + asn1_tag_dump_str_time(tlv, tag, f, level, candump); + break; case ASN1_TAG_OBJECT_ID: asn1_tag_dump_object_id(tlv, tag, f, level); *candump = false; From bd914904612e2739a614c7c1d07a9859668b039b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Nov 2018 13:26:33 +0200 Subject: [PATCH 0183/1938] added tags and all data deserializers works --- client/crypto/asn1utils.c | 56 +++++++++++++++++++++++++-------------- 1 file changed, 36 insertions(+), 20 deletions(-) diff --git a/client/crypto/asn1utils.c b/client/crypto/asn1utils.c index b19e27993..f1e668091 100644 --- a/client/crypto/asn1utils.c +++ b/client/crypto/asn1utils.c @@ -10,6 +10,7 @@ #include "asn1utils.h" #include +#include #include #include #include "util.h" @@ -92,14 +93,26 @@ static const struct asn1_tag asn1_tags[] = { { 0x04, "OCTET STRING", ASN1_TAG_OCTET_STRING}, { 0x05, "NULL" }, { 0x06, "OBJECT IDENTIFIER", ASN1_TAG_OBJECT_ID }, + { 0x07, "OBJECT DESCRIPTOR" }, + { 0x08, "EXTERNAL" }, + { 0x09, "REAL" }, + { 0x0A, "ENUMERATED" }, + { 0x0B, "EMBEDDED_PDV" }, { 0x0C, "UTF8String", ASN1_TAG_STRING }, { 0x10, "SEQUENCE" }, { 0x11, "SET" }, + { 0x12, "NumericString", ASN1_TAG_STRING }, { 0x13, "PrintableString", ASN1_TAG_STRING }, - { 0x14, "T61String", ASN1_TAG_STRING }, - { 0x16, "IA5String", ASN1_TAG_STRING }, + { 0x14, "T61String" }, + { 0x15, "VideotexString" }, + { 0x16, "IA5String" }, { 0x17, "UTCTime", ASN1_TAG_UTC_TIME }, { 0x18, "GeneralizedTime", ASN1_TAG_STR_TIME }, + { 0x19, "GraphicString" }, + { 0x1A, "VisibleString", ASN1_TAG_STRING }, + { 0x1B, "GeneralString", ASN1_TAG_STRING }, + { 0x1C, "UniversalString", ASN1_TAG_STRING }, + { 0x1E, "BMPString" }, { 0x30, "SEQUENCE" }, { 0x31, "SET" }, { 0xa0, "[0]" }, @@ -128,44 +141,48 @@ static const struct asn1_tag *asn1_get_tag(const struct tlv *tlv) { return tag ? tag : &asn1_tags[0]; } -static void asn1_tag_dump_str_time(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level, bool *needdump){ +static void asn1_tag_dump_str_time(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level, bool longyear, bool *needdump){ int len = tlv->len; - *needdump = true; + *needdump = false; + int startindx = longyear ? 4 : 2; + if (len > 4) { fprintf(f, "\tvalue: '"); while (true) { // year - fwrite(tlv->value, 1, 4, f); + if (!longyear) + fprintf(f, "20"); + fwrite(tlv->value, 1, longyear ? 4 : 2, f); fprintf(f, "-"); - if (len < 6) + if (len < startindx + 2) break; // month - fwrite(&tlv->value[4], 1, 2, f); + fwrite(&tlv->value[startindx], 1, 2, f); fprintf(f, "-"); - if (len < 8) + if (len < startindx + 4) break; // day - fwrite(&tlv->value[6], 1, 2, f); + fwrite(&tlv->value[startindx + 2], 1, 2, f); fprintf(f, " "); - if (len < 10) + if (len < startindx + 6) break; // hour - fwrite(&tlv->value[8], 1, 2, f); + fwrite(&tlv->value[startindx + 4], 1, 2, f); fprintf(f, ":"); - if (len < 12) + if (len < startindx + 8) break; // min - fwrite(&tlv->value[10], 1, 2, f); + fwrite(&tlv->value[startindx + 6], 1, 2, f); fprintf(f, ":"); - if (len < 14) + if (len < startindx + 10) break; // sec - fwrite(&tlv->value[12], 1, 2, f); - if (len < 15) + fwrite(&tlv->value[startindx + 8], 1, 2, f); + if (len < startindx + 11) break; // time zone - fprintf(f, " zone: %.*s", len - 14, &tlv->value[14]); + fprintf(f, " zone: %.*s", len - 10 - (longyear ? 4 : 2), &tlv->value[startindx + 10]); break; } @@ -283,11 +300,10 @@ bool asn1_tag_dump(const struct tlv *tlv, FILE *f, int level, bool *candump) { *candump = false; break; case ASN1_TAG_UTC_TIME: -// asn1_tag_dump_utc_time(tlv, tag, f, level); - fprintf(f, "\n"); + asn1_tag_dump_str_time(tlv, tag, f, level, false, candump); break; case ASN1_TAG_STR_TIME: - asn1_tag_dump_str_time(tlv, tag, f, level, candump); + asn1_tag_dump_str_time(tlv, tag, f, level, true, candump); break; case ASN1_TAG_OBJECT_ID: asn1_tag_dump_object_id(tlv, tag, f, level); From 6cd62753612bdf633f3b1eda7dda1fcabbeb2cd4 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Nov 2018 14:37:38 +0200 Subject: [PATCH 0184/1938] refactoring --- client/Makefile | 1 + client/crypto/asn1dump.c | 288 +++++ client/crypto/asn1dump.h | 21 + client/crypto/asn1utils.c | 257 +--- client/crypto/oids.json | 2319 +++++++++++++++++++++++++++++++++++++ 5 files changed, 2631 insertions(+), 255 deletions(-) create mode 100644 client/crypto/asn1dump.c create mode 100644 client/crypto/asn1dump.h create mode 100644 client/crypto/oids.json diff --git a/client/Makefile b/client/Makefile index 85f1648f1..9381cb29a 100644 --- a/client/Makefile +++ b/client/Makefile @@ -108,6 +108,7 @@ CMDSRCS = crapto1/crapto1.c \ mfkey.c \ tea.c \ fido/additional_ca.c \ + crypto/asn1dump.c \ crypto/libpcrypto.c\ crypto/asn1utils.c\ cliparser/argtable3.c\ diff --git a/client/crypto/asn1dump.c b/client/crypto/asn1dump.c new file mode 100644 index 000000000..4241899f6 --- /dev/null +++ b/client/crypto/asn1dump.c @@ -0,0 +1,288 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// asn.1 dumping +//----------------------------------------------------------------------------- + +#include "asn1dump.h" +#include +#include +#include +#include +#include "emv/emv_tags.h" +#include "emv/dump.h" +#include "util.h" + +#define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, " ");} + +enum asn1_tag_t { + ASN1_TAG_GENERIC, + ASN1_TAG_BOOLEAN, + ASN1_TAG_INTEGER, + ASN1_TAG_STRING, + ASN1_TAG_OCTET_STRING, + ASN1_TAG_UTC_TIME, + ASN1_TAG_STR_TIME, + ASN1_TAG_OBJECT_ID, +}; + +struct asn1_tag { + tlv_tag_t tag; + char *name; + enum asn1_tag_t type; + const void *data; +}; + +static const struct asn1_tag asn1_tags[] = { + // internal + { 0x00 , "Unknown ???" }, + + // ASN.1 + { 0x01, "BOOLEAN", ASN1_TAG_BOOLEAN }, + { 0x02, "INTEGER", ASN1_TAG_INTEGER }, + { 0x03, "BIT STRING" }, + { 0x04, "OCTET STRING", ASN1_TAG_OCTET_STRING}, + { 0x05, "NULL" }, + { 0x06, "OBJECT IDENTIFIER", ASN1_TAG_OBJECT_ID }, + { 0x07, "OBJECT DESCRIPTOR" }, + { 0x08, "EXTERNAL" }, + { 0x09, "REAL" }, + { 0x0A, "ENUMERATED" }, + { 0x0B, "EMBEDDED_PDV" }, + { 0x0C, "UTF8String", ASN1_TAG_STRING }, + { 0x10, "SEQUENCE" }, + { 0x11, "SET" }, + { 0x12, "NumericString", ASN1_TAG_STRING }, + { 0x13, "PrintableString", ASN1_TAG_STRING }, + { 0x14, "T61String" }, + { 0x15, "VideotexString" }, + { 0x16, "IA5String" }, + { 0x17, "UTCTime", ASN1_TAG_UTC_TIME }, + { 0x18, "GeneralizedTime", ASN1_TAG_STR_TIME }, + { 0x19, "GraphicString" }, + { 0x1A, "VisibleString", ASN1_TAG_STRING }, + { 0x1B, "GeneralString", ASN1_TAG_STRING }, + { 0x1C, "UniversalString", ASN1_TAG_STRING }, + { 0x1E, "BMPString" }, + { 0x30, "SEQUENCE" }, + { 0x31, "SET" }, + { 0xa0, "[0]" }, + { 0xa1, "[1]" }, + { 0xa2, "[2]" }, + { 0xa3, "[3]" }, + { 0xa4, "[4]" }, + { 0xa5, "[5]" }, +}; + +static int asn1_sort_tag(tlv_tag_t tag) { + return (int)(tag >= 0x100 ? tag : tag << 8); +} + +static int asn1_tlv_compare(const void *a, const void *b) { + const struct tlv *tlv = a; + const struct asn1_tag *tag = b; + + return asn1_sort_tag(tlv->tag) - (asn1_sort_tag(tag->tag)); +} + +static const struct asn1_tag *asn1_get_tag(const struct tlv *tlv) { + struct asn1_tag *tag = bsearch(tlv, asn1_tags, sizeof(asn1_tags) / sizeof(asn1_tags[0]), + sizeof(asn1_tags[0]), asn1_tlv_compare); + + return tag ? tag : &asn1_tags[0]; +} + +static void asn1_tag_dump_str_time(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level, bool longyear, bool *needdump){ + int len = tlv->len; + *needdump = false; + + int startindx = longyear ? 4 : 2; + + if (len > 4) { + fprintf(f, "\tvalue: '"); + while (true) { + // year + if (!longyear) + fprintf(f, "20"); + fwrite(tlv->value, 1, longyear ? 4 : 2, f); + fprintf(f, "-"); + if (len < startindx + 2) + break; + // month + fwrite(&tlv->value[startindx], 1, 2, f); + fprintf(f, "-"); + if (len < startindx + 4) + break; + // day + fwrite(&tlv->value[startindx + 2], 1, 2, f); + fprintf(f, " "); + if (len < startindx + 6) + break; + // hour + fwrite(&tlv->value[startindx + 4], 1, 2, f); + fprintf(f, ":"); + if (len < startindx + 8) + break; + // min + fwrite(&tlv->value[startindx + 6], 1, 2, f); + fprintf(f, ":"); + if (len < startindx + 10) + break; + // sec + fwrite(&tlv->value[startindx + 8], 1, 2, f); + if (len < startindx + 11) + break; + // time zone + fprintf(f, " zone: %.*s", len - 10 - (longyear ? 4 : 2), &tlv->value[startindx + 10]); + + break; + } + fprintf(f, "'\n"); + } else { + fprintf(f, "\n"); + *needdump = true; + } +} + +static void asn1_tag_dump_string(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level){ + fprintf(f, "\tvalue: '"); + fwrite(tlv->value, 1, tlv->len, f); + fprintf(f, "'\n"); +} + +static void asn1_tag_dump_octet_string(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level, bool *needdump){ + *needdump = false; + for (int i = 0; i < tlv->len; i++) + if (!isspace(tlv->value[i]) && !isprint(tlv->value[i])){ + *needdump = true; + break; + } + + if (*needdump) { + fprintf(f, "'\n"); + } else { + fprintf(f, "\t\t"); + asn1_tag_dump_string(tlv, tag, f, level); + } +} + +static unsigned long asn1_value_integer(const struct tlv *tlv, unsigned start, unsigned end) { + unsigned long ret = 0; + int i; + + if (end > tlv->len * 2) + return ret; + if (start >= end) + return ret; + + if (start & 1) { + ret += tlv->value[start/2] & 0xf; + i = start + 1; + } else + i = start; + + for (; i < end - 1; i += 2) { + ret *= 10; + ret += tlv->value[i/2] >> 4; + ret *= 10; + ret += tlv->value[i/2] & 0xf; + } + + if (end & 1) { + ret *= 10; + ret += tlv->value[end/2] >> 4; + } + + return ret; +} + +static void asn1_tag_dump_boolean(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level) { + PRINT_INDENT(level); + if (tlv->len > 0) { + fprintf(f, "\tvalue: %s\n", tlv->value[0]?"true":"false"); + } else { + fprintf(f, "n/a\n"); + } +} + +static void asn1_tag_dump_integer(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level) { + PRINT_INDENT(level); + fprintf(f, "\tvalue: %lu\n", asn1_value_integer(tlv, 0, tlv->len * 2)); +} + +static void asn1_tag_dump_object_id(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level) { + PRINT_INDENT(level); + mbedtls_asn1_buf asn1_buf; + asn1_buf.len = tlv->len; + asn1_buf.p = (uint8_t *)tlv->value; + char pstr[300]; + mbedtls_oid_get_numeric_string(pstr, sizeof(pstr), &asn1_buf); + fprintf(f, " %s", pstr); + const char *ppstr; + mbedtls_oid_get_attr_short_name(&asn1_buf, &ppstr); + if (ppstr && strnlen(ppstr, 1)) { + fprintf(f, " (%s)\n", ppstr); + return; + } + mbedtls_oid_get_sig_alg_desc(&asn1_buf, &ppstr); + if (ppstr && strnlen(ppstr, 1)) { + fprintf(f, " (%s)\n", ppstr); + return; + } + mbedtls_oid_get_extended_key_usage(&asn1_buf, &ppstr); + if (ppstr && strnlen(ppstr, 1)) { + fprintf(f, " (%s)\n", ppstr); + return; + } + + fprintf(f, "\n"); +} + +bool asn1_tag_dump(const struct tlv *tlv, FILE *f, int level, bool *candump) { + if (!tlv) { + fprintf(f, "NULL\n"); + return false; + } + + const struct asn1_tag *tag = asn1_get_tag(tlv); + + PRINT_INDENT(level); + fprintf(f, "--%2hx[%02zx] '%s':", tlv->tag, tlv->len, tag->name); + + switch (tag->type) { + case ASN1_TAG_GENERIC: + fprintf(f, "\n"); + break; + case ASN1_TAG_STRING: + asn1_tag_dump_string(tlv, tag, f, level); + *candump = false; + break; + case ASN1_TAG_OCTET_STRING: + asn1_tag_dump_octet_string(tlv, tag, f, level, candump); + break; + case ASN1_TAG_BOOLEAN: + asn1_tag_dump_boolean(tlv, tag, f, level); + *candump = false; + break; + case ASN1_TAG_INTEGER: + asn1_tag_dump_integer(tlv, tag, f, level); + *candump = false; + break; + case ASN1_TAG_UTC_TIME: + asn1_tag_dump_str_time(tlv, tag, f, level, false, candump); + break; + case ASN1_TAG_STR_TIME: + asn1_tag_dump_str_time(tlv, tag, f, level, true, candump); + break; + case ASN1_TAG_OBJECT_ID: + asn1_tag_dump_object_id(tlv, tag, f, level); + *candump = false; + break; + }; + + return true; +} diff --git a/client/crypto/asn1dump.h b/client/crypto/asn1dump.h new file mode 100644 index 000000000..1aadf487c --- /dev/null +++ b/client/crypto/asn1dump.h @@ -0,0 +1,21 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// asn.1 dumping +//----------------------------------------------------------------------------- +#ifndef ASN1DUMP_H +#define ASN1DUMP_H + +#include +#include +#include +#include +#include "emv/tlv.h" + +extern bool asn1_tag_dump(const struct tlv *tlv, FILE *f, int level, bool *candump); + +#endif /* asn1utils.h */ diff --git a/client/crypto/asn1utils.c b/client/crypto/asn1utils.c index f1e668091..5be323b45 100644 --- a/client/crypto/asn1utils.c +++ b/client/crypto/asn1utils.c @@ -12,11 +12,10 @@ #include #include #include -#include -#include "util.h" #include "emv/tlv.h" -#include "emv/emv_tags.h" #include "emv/dump.h" +#include "asn1dump.h" +#include "util.h" int ecdsa_asn1_get_signature(uint8_t *signature, size_t signaturelen, uint8_t *rval, uint8_t *sval) { if (!signature || !signaturelen || !rval || !sval) @@ -62,258 +61,6 @@ exit: return res; } -#define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, " ");} - -enum asn1_tag_t { - ASN1_TAG_GENERIC, - ASN1_TAG_BOOLEAN, - ASN1_TAG_INTEGER, - ASN1_TAG_STRING, - ASN1_TAG_OCTET_STRING, - ASN1_TAG_UTC_TIME, - ASN1_TAG_STR_TIME, - ASN1_TAG_OBJECT_ID, -}; - -struct asn1_tag { - tlv_tag_t tag; - char *name; - enum asn1_tag_t type; - const void *data; -}; - -static const struct asn1_tag asn1_tags[] = { - // internal - { 0x00 , "Unknown ???" }, - - // ASN.1 - { 0x01, "BOOLEAN", ASN1_TAG_BOOLEAN }, - { 0x02, "INTEGER", ASN1_TAG_INTEGER }, - { 0x03, "BIT STRING" }, - { 0x04, "OCTET STRING", ASN1_TAG_OCTET_STRING}, - { 0x05, "NULL" }, - { 0x06, "OBJECT IDENTIFIER", ASN1_TAG_OBJECT_ID }, - { 0x07, "OBJECT DESCRIPTOR" }, - { 0x08, "EXTERNAL" }, - { 0x09, "REAL" }, - { 0x0A, "ENUMERATED" }, - { 0x0B, "EMBEDDED_PDV" }, - { 0x0C, "UTF8String", ASN1_TAG_STRING }, - { 0x10, "SEQUENCE" }, - { 0x11, "SET" }, - { 0x12, "NumericString", ASN1_TAG_STRING }, - { 0x13, "PrintableString", ASN1_TAG_STRING }, - { 0x14, "T61String" }, - { 0x15, "VideotexString" }, - { 0x16, "IA5String" }, - { 0x17, "UTCTime", ASN1_TAG_UTC_TIME }, - { 0x18, "GeneralizedTime", ASN1_TAG_STR_TIME }, - { 0x19, "GraphicString" }, - { 0x1A, "VisibleString", ASN1_TAG_STRING }, - { 0x1B, "GeneralString", ASN1_TAG_STRING }, - { 0x1C, "UniversalString", ASN1_TAG_STRING }, - { 0x1E, "BMPString" }, - { 0x30, "SEQUENCE" }, - { 0x31, "SET" }, - { 0xa0, "[0]" }, - { 0xa1, "[1]" }, - { 0xa2, "[2]" }, - { 0xa3, "[3]" }, - { 0xa4, "[4]" }, - { 0xa5, "[5]" }, -}; - -static int asn1_sort_tag(tlv_tag_t tag) { - return (int)(tag >= 0x100 ? tag : tag << 8); -} - -static int asn1_tlv_compare(const void *a, const void *b) { - const struct tlv *tlv = a; - const struct asn1_tag *tag = b; - - return asn1_sort_tag(tlv->tag) - (asn1_sort_tag(tag->tag)); -} - -static const struct asn1_tag *asn1_get_tag(const struct tlv *tlv) { - struct asn1_tag *tag = bsearch(tlv, asn1_tags, sizeof(asn1_tags) / sizeof(asn1_tags[0]), - sizeof(asn1_tags[0]), asn1_tlv_compare); - - return tag ? tag : &asn1_tags[0]; -} - -static void asn1_tag_dump_str_time(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level, bool longyear, bool *needdump){ - int len = tlv->len; - *needdump = false; - - int startindx = longyear ? 4 : 2; - - if (len > 4) { - fprintf(f, "\tvalue: '"); - while (true) { - // year - if (!longyear) - fprintf(f, "20"); - fwrite(tlv->value, 1, longyear ? 4 : 2, f); - fprintf(f, "-"); - if (len < startindx + 2) - break; - // month - fwrite(&tlv->value[startindx], 1, 2, f); - fprintf(f, "-"); - if (len < startindx + 4) - break; - // day - fwrite(&tlv->value[startindx + 2], 1, 2, f); - fprintf(f, " "); - if (len < startindx + 6) - break; - // hour - fwrite(&tlv->value[startindx + 4], 1, 2, f); - fprintf(f, ":"); - if (len < startindx + 8) - break; - // min - fwrite(&tlv->value[startindx + 6], 1, 2, f); - fprintf(f, ":"); - if (len < startindx + 10) - break; - // sec - fwrite(&tlv->value[startindx + 8], 1, 2, f); - if (len < startindx + 11) - break; - // time zone - fprintf(f, " zone: %.*s", len - 10 - (longyear ? 4 : 2), &tlv->value[startindx + 10]); - - break; - } - fprintf(f, "'\n"); - } else { - fprintf(f, "\n"); - *needdump = true; - } -} - -static void asn1_tag_dump_string(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level){ - fprintf(f, "\tvalue: '"); - fwrite(tlv->value, 1, tlv->len, f); - fprintf(f, "'\n"); -} - -static void asn1_tag_dump_octet_string(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level, bool *needdump){ - *needdump = false; - for (int i = 0; i < tlv->len; i++) - if (!isspace(tlv->value[i]) && !isprint(tlv->value[i])){ - *needdump = true; - break; - } - - if (*needdump) { - fprintf(f, "'\n"); - } else { - fprintf(f, "\t\t"); - asn1_tag_dump_string(tlv, tag, f, level); - } -} - -static unsigned long asn1_value_integer(const struct tlv *tlv, unsigned start, unsigned end) { - unsigned long ret = 0; - int i; - - if (end > tlv->len * 2) - return ret; - if (start >= end) - return ret; - - if (start & 1) { - ret += tlv->value[start/2] & 0xf; - i = start + 1; - } else - i = start; - - for (; i < end - 1; i += 2) { - ret *= 10; - ret += tlv->value[i/2] >> 4; - ret *= 10; - ret += tlv->value[i/2] & 0xf; - } - - if (end & 1) { - ret *= 10; - ret += tlv->value[end/2] >> 4; - } - - return ret; -} - -static void asn1_tag_dump_boolean(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level) { - PRINT_INDENT(level); - if (tlv->len > 0) { - fprintf(f, "\tvalue: %s\n", tlv->value[0]?"true":"false"); - } else { - fprintf(f, "n/a\n"); - } -} - -static void asn1_tag_dump_integer(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level) { - PRINT_INDENT(level); - fprintf(f, "\tvalue: %lu\n", asn1_value_integer(tlv, 0, tlv->len * 2)); -} - -static void asn1_tag_dump_object_id(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level) { - PRINT_INDENT(level); - mbedtls_asn1_buf asn1_buf; - asn1_buf.len = tlv->len; - asn1_buf.p = (uint8_t *)tlv->value; - char pstr[300]; - mbedtls_oid_get_numeric_string(pstr, sizeof(pstr), &asn1_buf); - fprintf(f, " %s\n", pstr); -} - -bool asn1_tag_dump(const struct tlv *tlv, FILE *f, int level, bool *candump) { - if (!tlv) { - fprintf(f, "NULL\n"); - return false; - } - - const struct asn1_tag *tag = asn1_get_tag(tlv); - - PRINT_INDENT(level); - fprintf(f, "--%2hx[%02zx] '%s':", tlv->tag, tlv->len, tag->name); - - switch (tag->type) { - case ASN1_TAG_GENERIC: - fprintf(f, "\n"); - break; - case ASN1_TAG_STRING: - asn1_tag_dump_string(tlv, tag, f, level); - *candump = false; - break; - case ASN1_TAG_OCTET_STRING: - asn1_tag_dump_octet_string(tlv, tag, f, level, candump); - break; - case ASN1_TAG_BOOLEAN: - asn1_tag_dump_boolean(tlv, tag, f, level); - *candump = false; - break; - case ASN1_TAG_INTEGER: - asn1_tag_dump_integer(tlv, tag, f, level); - *candump = false; - break; - case ASN1_TAG_UTC_TIME: - asn1_tag_dump_str_time(tlv, tag, f, level, false, candump); - break; - case ASN1_TAG_STR_TIME: - asn1_tag_dump_str_time(tlv, tag, f, level, true, candump); - break; - case ASN1_TAG_OBJECT_ID: - asn1_tag_dump_object_id(tlv, tag, f, level); - *candump = false; - break; - }; - - return true; -} - static bool print_cb(void *data, const struct tlv *tlv, int level, bool is_leaf) { bool candump = true; asn1_tag_dump(tlv, stdout, level, &candump); diff --git a/client/crypto/oids.json b/client/crypto/oids.json new file mode 100644 index 000000000..9f65fb34b --- /dev/null +++ b/client/crypto/oids.json @@ -0,0 +1,2319 @@ +{ +"copyright": "https://www.cs.auckland.ac.nz/~pgut001/dumpasn1.cfg", + +"0.2.262.1.10": { "d": "Telesec", "c": "Deutsche Telekom" }, +"0.2.262.1.10.0": { "d": "extension", "c": "Telesec" }, +"0.2.262.1.10.1": { "d": "mechanism", "c": "Telesec" }, +"0.2.262.1.10.1.0": { "d": "authentication", "c": "Telesec mechanism" }, +"0.2.262.1.10.1.0.1": { "d": "passwordAuthentication", "c": "Telesec authentication" }, +"0.2.262.1.10.1.0.2": { "d": "protectedPasswordAuthentication", "c": "Telesec authentication" }, +"0.2.262.1.10.1.0.3": { "d": "oneWayX509Authentication", "c": "Telesec authentication" }, +"0.2.262.1.10.1.0.4": { "d": "twoWayX509Authentication", "c": "Telesec authentication" }, +"0.2.262.1.10.1.0.5": { "d": "threeWayX509Authentication", "c": "Telesec authentication" }, +"0.2.262.1.10.1.0.6": { "d": "oneWayISO9798Authentication", "c": "Telesec authentication" }, +"0.2.262.1.10.1.0.7": { "d": "twoWayISO9798Authentication", "c": "Telesec authentication" }, +"0.2.262.1.10.1.0.8": { "d": "telekomAuthentication", "c": "Telesec authentication" }, +"0.2.262.1.10.1.1": { "d": "signature", "c": "Telesec mechanism" }, +"0.2.262.1.10.1.1.1": { "d": "md4WithRSAAndISO9697", "c": "Telesec mechanism" }, +"0.2.262.1.10.1.1.2": { "d": "md4WithRSAAndTelesecSignatureStandard", "c": "Telesec mechanism" }, +"0.2.262.1.10.1.1.3": { "d": "md5WithRSAAndISO9697", "c": "Telesec mechanism" }, +"0.2.262.1.10.1.1.4": { "d": "md5WithRSAAndTelesecSignatureStandard", "c": "Telesec mechanism" }, +"0.2.262.1.10.1.1.5": { "d": "ripemd160WithRSAAndTelekomSignatureStandard", "c": "Telesec mechanism" }, +"0.2.262.1.10.1.1.9": { "d": "hbciRsaSignature", "c": "Telesec signature" }, +"0.2.262.1.10.1.2": { "d": "encryption", "c": "Telesec mechanism" }, +"0.2.262.1.10.1.2.0": { "d": "none", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.1": { "d": "rsaTelesec", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.2": { "d": "des", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.2.1": { "d": "desECB", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.2.2": { "d": "desCBC", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.2.3": { "d": "desOFB", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.2.4": { "d": "desCFB8", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.2.5": { "d": "desCFB64", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.3": { "d": "des3", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.3.1": { "d": "des3ECB", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.3.2": { "d": "des3CBC", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.3.3": { "d": "des3OFB", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.3.4": { "d": "des3CFB8", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.3.5": { "d": "des3CFB64", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.4": { "d": "magenta", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.5": { "d": "idea", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.5.1": { "d": "ideaECB", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.5.2": { "d": "ideaCBC", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.5.3": { "d": "ideaOFB", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.5.4": { "d": "ideaCFB8", "c": "Telesec encryption" }, +"0.2.262.1.10.1.2.5.5": { "d": "ideaCFB64", "c": "Telesec encryption" }, +"0.2.262.1.10.1.3": { "d": "oneWayFunction", "c": "Telesec mechanism" }, +"0.2.262.1.10.1.3.1": { "d": "md4", "c": "Telesec one-way function" }, +"0.2.262.1.10.1.3.2": { "d": "md5", "c": "Telesec one-way function" }, +"0.2.262.1.10.1.3.3": { "d": "sqModNX509", "c": "Telesec one-way function" }, +"0.2.262.1.10.1.3.4": { "d": "sqModNISO", "c": "Telesec one-way function" }, +"0.2.262.1.10.1.3.5": { "d": "ripemd128", "c": "Telesec one-way function" }, +"0.2.262.1.10.1.3.6": { "d": "hashUsingBlockCipher", "c": "Telesec one-way function" }, +"0.2.262.1.10.1.3.7": { "d": "mac", "c": "Telesec one-way function" }, +"0.2.262.1.10.1.3.8": { "d": "ripemd160", "c": "Telesec one-way function" }, +"0.2.262.1.10.1.4": { "d": "fecFunction", "c": "Telesec mechanism" }, +"0.2.262.1.10.1.4.1": { "d": "reedSolomon", "c": "Telesec mechanism" }, +"0.2.262.1.10.2": { "d": "module", "c": "Telesec" }, +"0.2.262.1.10.2.0": { "d": "algorithms", "c": "Telesec module" }, +"0.2.262.1.10.2.1": { "d": "attributeTypes", "c": "Telesec module" }, +"0.2.262.1.10.2.2": { "d": "certificateTypes", "c": "Telesec module" }, +"0.2.262.1.10.2.3": { "d": "messageTypes", "c": "Telesec module" }, +"0.2.262.1.10.2.4": { "d": "plProtocol", "c": "Telesec module" }, +"0.2.262.1.10.2.5": { "d": "smeAndComponentsOfSme", "c": "Telesec module" }, +"0.2.262.1.10.2.6": { "d": "fec", "c": "Telesec module" }, +"0.2.262.1.10.2.7": { "d": "usefulDefinitions", "c": "Telesec module" }, +"0.2.262.1.10.2.8": { "d": "stefiles", "c": "Telesec module" }, +"0.2.262.1.10.2.9": { "d": "sadmib", "c": "Telesec module" }, +"0.2.262.1.10.2.10": { "d": "electronicOrder", "c": "Telesec module" }, +"0.2.262.1.10.2.11": { "d": "telesecTtpAsymmetricApplication", "c": "Telesec module" }, +"0.2.262.1.10.2.12": { "d": "telesecTtpBasisApplication", "c": "Telesec module" }, +"0.2.262.1.10.2.13": { "d": "telesecTtpMessages", "c": "Telesec module" }, +"0.2.262.1.10.2.14": { "d": "telesecTtpTimeStampApplication", "c": "Telesec module" }, +"0.2.262.1.10.3": { "d": "objectClass", "c": "Telesec" }, +"0.2.262.1.10.3.0": { "d": "telesecOtherName", "c": "Telesec object class" }, +"0.2.262.1.10.3.1": { "d": "directory", "c": "Telesec object class" }, +"0.2.262.1.10.3.2": { "d": "directoryType", "c": "Telesec object class" }, +"0.2.262.1.10.3.3": { "d": "directoryGroup", "c": "Telesec object class" }, +"0.2.262.1.10.3.4": { "d": "directoryUser", "c": "Telesec object class" }, +"0.2.262.1.10.3.5": { "d": "symmetricKeyEntry", "c": "Telesec object class" }, +"0.2.262.1.10.4": { "d": "package", "c": "Telesec" }, +"0.2.262.1.10.5": { "d": "parameter", "c": "Telesec" }, +"0.2.262.1.10.6": { "d": "nameBinding", "c": "Telesec" }, +"0.2.262.1.10.7": { "d": "attribute", "c": "Telesec" }, +"0.2.262.1.10.7.0": { "d": "applicationGroupIdentifier", "c": "Telesec attribute" }, +"0.2.262.1.10.7.1": { "d": "certificateType", "c": "Telesec attribute" }, +"0.2.262.1.10.7.2": { "d": "telesecCertificate", "c": "Telesec attribute" }, +"0.2.262.1.10.7.3": { "d": "certificateNumber", "c": "Telesec attribute" }, +"0.2.262.1.10.7.4": { "d": "certificateRevocationList", "c": "Telesec attribute" }, +"0.2.262.1.10.7.5": { "d": "creationDate", "c": "Telesec attribute" }, +"0.2.262.1.10.7.6": { "d": "issuer", "c": "Telesec attribute" }, +"0.2.262.1.10.7.7": { "d": "namingAuthority", "c": "Telesec attribute" }, +"0.2.262.1.10.7.8": { "d": "publicKeyDirectory", "c": "Telesec attribute" }, +"0.2.262.1.10.7.9": { "d": "securityDomain", "c": "Telesec attribute" }, +"0.2.262.1.10.7.10": { "d": "subject", "c": "Telesec attribute" }, +"0.2.262.1.10.7.11": { "d": "timeOfRevocation", "c": "Telesec attribute" }, +"0.2.262.1.10.7.12": { "d": "userGroupReference", "c": "Telesec attribute" }, +"0.2.262.1.10.7.13": { "d": "validity", "c": "Telesec attribute" }, +"0.2.262.1.10.7.14": { "d": "zert93", "c": "Telesec attribute" }, +"0.2.262.1.10.7.15": { "d": "securityMessEnv", "c": "Telesec attribute" }, +"0.2.262.1.10.7.16": { "d": "anonymizedPublicKeyDirectory", "c": "Telesec attribute" }, +"0.2.262.1.10.7.17": { "d": "telesecGivenName", "c": "Telesec attribute" }, +"0.2.262.1.10.7.18": { "d": "nameAdditions", "c": "Telesec attribute" }, +"0.2.262.1.10.7.19": { "d": "telesecPostalCode", "c": "Telesec attribute" }, +"0.2.262.1.10.7.20": { "d": "nameDistinguisher", "c": "Telesec attribute" }, +"0.2.262.1.10.7.21": { "d": "telesecCertificateList", "c": "Telesec attribute" }, +"0.2.262.1.10.7.22": { "d": "teletrustCertificateList", "c": "Telesec attribute" }, +"0.2.262.1.10.7.23": { "d": "x509CertificateList", "c": "Telesec attribute" }, +"0.2.262.1.10.7.24": { "d": "timeOfIssue", "c": "Telesec attribute" }, +"0.2.262.1.10.7.25": { "d": "physicalCardNumber", "c": "Telesec attribute" }, +"0.2.262.1.10.7.26": { "d": "fileType", "c": "Telesec attribute" }, +"0.2.262.1.10.7.27": { "d": "ctlFileIsArchive", "c": "Telesec attribute" }, +"0.2.262.1.10.7.28": { "d": "emailAddress", "c": "Telesec attribute" }, +"0.2.262.1.10.7.29": { "d": "certificateTemplateList", "c": "Telesec attribute" }, +"0.2.262.1.10.7.30": { "d": "directoryName", "c": "Telesec attribute" }, +"0.2.262.1.10.7.31": { "d": "directoryTypeName", "c": "Telesec attribute" }, +"0.2.262.1.10.7.32": { "d": "directoryGroupName", "c": "Telesec attribute" }, +"0.2.262.1.10.7.33": { "d": "directoryUserName", "c": "Telesec attribute" }, +"0.2.262.1.10.7.34": { "d": "revocationFlag", "c": "Telesec attribute" }, +"0.2.262.1.10.7.35": { "d": "symmetricKeyEntryName", "c": "Telesec attribute" }, +"0.2.262.1.10.7.36": { "d": "glNumber", "c": "Telesec attribute" }, +"0.2.262.1.10.7.37": { "d": "goNumber", "c": "Telesec attribute" }, +"0.2.262.1.10.7.38": { "d": "gKeyData", "c": "Telesec attribute" }, +"0.2.262.1.10.7.39": { "d": "zKeyData", "c": "Telesec attribute" }, +"0.2.262.1.10.7.40": { "d": "ktKeyData", "c": "Telesec attribute" }, +"0.2.262.1.10.7.41": { "d": "ktKeyNumber", "c": "Telesec attribute" }, +"0.2.262.1.10.7.51": { "d": "timeOfRevocationGen", "c": "Telesec attribute" }, +"0.2.262.1.10.7.52": { "d": "liabilityText", "c": "Telesec attribute" }, +"0.2.262.1.10.8": { "d": "attributeGroup", "c": "Telesec" }, +"0.2.262.1.10.9": { "d": "action", "c": "Telesec" }, +"0.2.262.1.10.10": { "d": "notification", "c": "Telesec" }, +"0.2.262.1.10.11": { "d": "snmp-mibs", "c": "Telesec" }, +"0.2.262.1.10.11.1": { "d": "securityApplication", "c": "Telesec SNMP MIBs" }, +"0.2.262.1.10.12": { "d": "certAndCrlExtensionDefinitions", "c": "Telesec" }, +"0.2.262.1.10.12.0": { "d": "liabilityLimitationFlag", "c": "Telesec cert/CRL extension" }, +"0.2.262.1.10.12.1": { "d": "telesecCertIdExt", "c": "Telesec cert/CRL extension" }, +"0.2.262.1.10.12.2": { "d": "Telesec policyIdentifier", "c": "Telesec cert/CRL extension" }, +"0.2.262.1.10.12.3": { "d": "telesecPolicyQualifierID", "c": "Telesec cert/CRL extension" }, +"0.2.262.1.10.12.4": { "d": "telesecCRLFilteredExt", "c": "Telesec cert/CRL extension" }, +"0.2.262.1.10.12.5": { "d": "telesecCRLFilterExt", "c": "Telesec cert/CRL extension" }, +"0.2.262.1.10.12.6": { "d": "telesecNamingAuthorityExt", "c": "Telesec cert/CRL extension" }, +"0.4.0.127.0.7": { "d": "bsi", "c": "BSI TR-03110/TR-03111" }, +"0.4.0.127.0.7.1": { "d": "bsiEcc", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1": { "d": "bsifieldType", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.1": { "d": "bsiPrimeField", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.2": { "d": "bsiCharacteristicTwoField", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.2.2": { "d": "bsiECTLVKeyFormat", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.2.2.1": { "d": "bsiECTLVPublicKey", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.2.3": { "d": "bsiCharacteristicTwoBasis", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.2.3.1": { "d": "bsiGnBasis", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.2.3.2": { "d": "bsiTpBasis", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.2.3.3": { "d": "bsiPpBasis", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.4.1": { "d": "bsiEcdsaSignatures", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.4.1.1": { "d": "bsiEcdsaWithSHA1", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.4.1.2": { "d": "bsiEcdsaWithSHA224", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.4.1.3": { "d": "bsiEcdsaWithSHA256", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.4.1.4": { "d": "bsiEcdsaWithSHA384", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.4.1.5": { "d": "bsiEcdsaWithSHA512", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.4.1.6": { "d": "bsiEcdsaWithRIPEMD160", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.1.1": { "d": "bsiEckaEgX963KDF", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.1.1.1": { "d": "bsiEckaEgX963KDFWithSHA1", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.1.1.2": { "d": "bsiEckaEgX963KDFWithSHA224", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.1.1.3": { "d": "bsiEckaEgX963KDFWithSHA256", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.1.1.4": { "d": "bsiEckaEgX963KDFWithSHA384", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.1.1.5": { "d": "bsiEckaEgX963KDFWithSHA512", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.1.1.6": { "d": "bsiEckaEgX963KDFWithRIPEMD160", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.1.2": { "d": "bsiEckaEgSessionKDF", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.1.2.1": { "d": "bsiEckaEgSessionKDFWith3DES", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.1.2.2": { "d": "bsiEckaEgSessionKDFWithAES128", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.1.2.3": { "d": "bsiEckaEgSessionKDFWithAES192", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.1.2.4": { "d": "bsiEckaEgSessionKDFWithAES256", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.2": { "d": "bsiEckaDH", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.2.1": { "d": "bsiEckaDHX963KDF", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.2.1.1": { "d": "bsiEckaDHX963KDFWithSHA1", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.2.1.2": { "d": "bsiEckaDHX963KDFWithSHA224", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.2.1.3": { "d": "bsiEckaDHX963KDFWithSHA256", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.2.1.4": { "d": "bsiEckaDHX963KDFWithSHA384", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.2.1.5": { "d": "bsiEckaDHX963KDFWithSHA512", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.2.1.6": { "d": "bsiEckaDHX963KDFWithRIPEMD160", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.2.2": { "d": "bsiEckaDHSessionKDF", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.2.2.1": { "d": "bsiEckaDHSessionKDFWith3DES", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.2.2.2": { "d": "bsiEckaDHSessionKDFWithAES128", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.2.2.3": { "d": "bsiEckaDHSessionKDFWithAES192", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.1.5.2.2.4": { "d": "bsiEckaDHSessionKDFWithAES256", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.2": { "d": "bsiEcKeyType", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.2.1": { "d": "bsiEcPublicKey", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.5.1": { "d": "bsiKaeg", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.5.1.1": { "d": "bsiKaegWithX963KDF", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.1.5.1.2": { "d": "bsiKaegWith3DESKDF", "c": "BSI TR-03111" }, +"0.4.0.127.0.7.2.2.1": { "d": "bsiPK", "c": "BSI TR-03110. Formerly known as bsiCA, now moved to ...2.2.3.x" }, +"0.4.0.127.0.7.2.2.1.1": { "d": "bsiPK_DH", "c": "BSI TR-03110. Formerly known as bsiCA_DH, now moved to ...2.2.3.x" }, +"0.4.0.127.0.7.2.2.1.2": { "d": "bsiPK_ECDH", "c": "BSI TR-03110. Formerly known as bsiCA_ECDH, now moved to ...2.2.3.x" }, +"0.4.0.127.0.7.2.2.2": { "d": "bsiTA", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.2.1": { "d": "bsiTA_RSA", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.2.1.1": { "d": "bsiTA_RSAv1_5_SHA1", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.2.1.2": { "d": "bsiTA_RSAv1_5_SHA256", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.2.1.3": { "d": "bsiTA_RSAPSS_SHA1", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.2.1.4": { "d": "bsiTA_RSAPSS_SHA256", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.2.1.5": { "d": "bsiTA_RSAv1_5_SHA512", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.2.1.6": { "d": "bsiTA_RSAPSS_SHA512", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.2.2": { "d": "bsiTA_ECDSA", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.2.2.1": { "d": "bsiTA_ECDSA_SHA1", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.2.2.2": { "d": "bsiTA_ECDSA_SHA224", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.2.2.3": { "d": "bsiTA_ECDSA_SHA256", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.2.2.4": { "d": "bsiTA_ECDSA_SHA384", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.2.2.5": { "d": "bsiTA_ECDSA_SHA512", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.3": { "d": "bsiCA", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.3.1": { "d": "bsiCA_DH", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.3.1.1": { "d": "bsiCA_DH_3DES_CBC_CBC", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.3.1.2": { "d": "bsiCA_DH_AES_CBC_CMAC_128", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.3.1.3": { "d": "bsiCA_DH_AES_CBC_CMAC_192", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.3.1.4": { "d": "bsiCA_DH_AES_CBC_CMAC_256", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.3.2": { "d": "bsiCA_ECDH", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.3.2.1": { "d": "bsiCA_ECDH_3DES_CBC_CBC", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.3.2.2": { "d": "bsiCA_ECDH_AES_CBC_CMAC_128", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.3.2.3": { "d": "bsiCA_ECDH_AES_CBC_CMAC_192", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.3.2.4": { "d": "bsiCA_ECDH_AES_CBC_CMAC_256", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4": { "d": "bsiPACE", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.1": { "d": "bsiPACE_DH_GM", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.1.1": { "d": "bsiPACE_DH_GM_3DES_CBC_CBC", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.1.2": { "d": "bsiPACE_DH_GM_AES_CBC_CMAC_128", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.1.3": { "d": "bsiPACE_DH_GM_AES_CBC_CMAC_192", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.1.4": { "d": "bsiPACE_DH_GM_AES_CBC_CMAC_256", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.2": { "d": "bsiPACE_ECDH_GM", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.2.1": { "d": "bsiPACE_ECDH_GM_3DES_CBC_CBC", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.2.2": { "d": "bsiPACE_ECDH_GM_AES_CBC_CMAC_128", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.2.3": { "d": "bsiPACE_ECDH_GM_AES_CBC_CMAC_192", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.2.4": { "d": "bsiPACE_ECDH_GM_AES_CBC_CMAC_256", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.3": { "d": "bsiPACE_DH_IM", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.3.1": { "d": "bsiPACE_DH_IM_3DES_CBC_CBC", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.3.2": { "d": "bsiPACE_DH_IM_AES_CBC_CMAC_128", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.3.3": { "d": "bsiPACE_DH_IM_AES_CBC_CMAC_192", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.3.4": { "d": "bsiPACE_DH_IM_AES_CBC_CMAC_256", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.4": { "d": "bsiPACE_ECDH_IM", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.4.1": { "d": "bsiPACE_ECDH_IM_3DES_CBC_CBC", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.4.2": { "d": "bsiPACE_ECDH_IM_AES_CBC_CMAC_128", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.4.3": { "d": "bsiPACE_ECDH_IM_AES_CBC_CMAC_192", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.4.4.4": { "d": "bsiPACE_ECDH_IM_AES_CBC_CMAC_256", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.5": { "d": "bsiRI", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.5.1": { "d": "bsiRI_DH", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.5.1.1": { "d": "bsiRI_DH_SHA1", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.5.1.2": { "d": "bsiRI_DH_SHA224", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.5.1.3": { "d": "bsiRI_DH_SHA256", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.5.1.4": { "d": "bsiRI_DH_SHA384", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.5.1.5": { "d": "bsiRI_DH_SHA512", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.5.2": { "d": "bsiRI_ECDH", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.5.2.1": { "d": "bsiRI_ECDH_SHA1", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.5.2.2": { "d": "bsiRI_ECDH_SHA224", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.5.2.3": { "d": "bsiRI_ECDH_SHA256", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.5.2.4": { "d": "bsiRI_ECDH_SHA384", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.5.2.5": { "d": "bsiRI_ECDH_SHA512", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.6": { "d": "bsiCardInfo", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.7": { "d": "bsiEidSecurity", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.2.2.8": { "d": "bsiPT", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.2": { "d": "bsiEACRoles", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.2.1": { "d": "bsiEACRolesIS", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.2.2": { "d": "bsiEACRolesAT", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.2.3": { "d": "bsiEACRolesST", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.3": { "d": "bsiTAv2ce", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.3.1": { "d": "bsiTAv2ceDescription", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.3.1.1": { "d": "bsiTAv2ceDescriptionPlainText", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.3.1.2": { "d": "bsiTAv2ceDescriptionIA5String", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.3.1.3": { "d": "bsiTAv2ceDescriptionOctetString", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.3.2": { "d": "bsiTAv2ceTerminalSector", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.4": { "d": "bsiAuxData", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.4.1": { "d": "bsiAuxDataBirthday", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.4.2": { "d": "bsiAuxDataExpireDate", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.4.3": { "d": "bsiAuxDataCommunityID", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.5": { "d": "bsiDefectList", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.5.1": { "d": "bsiDefectAuthDefect", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.5.1.1": { "d": "bsiDefectCertRevoked", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.5.1.2": { "d": "bsiDefectCertReplaced", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.5.1.3": { "d": "bsiDefectChipAuthKeyRevoked", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.5.1.4": { "d": "bsiDefectActiveAuthKeyRevoked", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.5.2": { "d": "bsiDefectEPassportDefect", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.5.2.1": { "d": "bsiDefectEPassportDGMalformed", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.5.2.2": { "d": "bsiDefectSODInvalid", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.5.3": { "d": "bsiDefectEIDDefect", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.5.3.1": { "d": "bsiDefectEIDDGMalformed", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.5.3.2": { "d": "bsiDefectEIDIntegrity", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.5.4": { "d": "bsiDefectDocumentDefect", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.5.4.1": { "d": "bsiDefectCardSecurityMalformed", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.5.4.2": { "d": "bsiDefectChipSecurityMalformed", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.5.4.3": { "d": "bsiDefectPowerDownReq", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.1.6": { "d": "bsiListContentDescription", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.2.1": { "d": "bsiSecurityObject", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.2.2": { "d": "bsiBlackList", "c": "BSI TR-03110" }, +"0.4.0.127.0.7.3.4.2.2": { "d": "bsiSignedUpdateDeviceAdmin", "c": "BSI TR-03109" }, +"0.4.0.127.0.7.4.1.1.1": { "d": "bsiCertReqMsgs", "c": "BSI TR-03109" }, +"0.4.0.127.0.7.4.1.1.2": { "d": "bsiCertReqMsgswithOuterSignature", "c": "BSI TR-03109" }, +"0.4.0.127.0.7.4.1.1.3": { "d": "bsiAuthorizedCertReqMsgs", "c": "BSI TR-03109" }, +"0.4.0.127.0.7.4.1.2.2": { "d": "bsiSignedRevReqs", "c": "BSI TR-03109" }, +"0.4.0.1862": { "d": "etsiQcsProfile", "c": "ETSI TS 101 862 qualified certificates" }, +"0.4.0.1862.1": { "d": "etsiQcs", "c": "ETSI TS 101 862 qualified certificates" }, +"0.4.0.1862.1.1": { "d": "etsiQcsCompliance", "c": "ETSI TS 101 862 qualified certificates" }, +"0.4.0.1862.1.2": { "d": "etsiQcsLimitValue", "c": "ETSI TS 101 862 qualified certificates" }, +"0.4.0.1862.1.3": { "d": "etsiQcsRetentionPeriod", "c": "ETSI TS 101 862 qualified certificates" }, +"0.4.0.1862.1.4": { "d": "etsiQcsQcSSCD", "c": "ETSI TS 101 862 qualified certificates" }, +"0.9.2342.19200300.100.1.1": { "d": "userID", "c": "Some oddball X.500 attribute collection" }, +"0.9.2342.19200300.100.1.3": { "d": "rfc822Mailbox", "c": "Some oddball X.500 attribute collection" }, +"0.9.2342.19200300.100.1.25": { "d": "domainComponent", "c": "Men are from Mars, this OID is from Pluto" }, +"1.0.10118.3.0.49": { "d": "ripemd160", "c": "ISO 10118-3 hash function" }, +"1.0.10118.3.0.50": { "d": "ripemd128", "c": "ISO 10118-3 hash function" }, +"1.0.10118.3.0.55": { "d": "whirlpool", "c": "ISO 10118-3 hash function" }, +"1.2.36.1.3.1.1.1": { "d": "qgpki", "c": "Queensland Government PKI" }, +"1.2.36.1.3.1.1.1.1": { "d": "qgpkiPolicies", "c": "QGPKI policies" }, +"1.2.36.1.3.1.1.1.1.1": { "d": "qgpkiMedIntermedCA", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.1.1": { "d": "qgpkiMedIntermedIndividual", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.1.2": { "d": "qgpkiMedIntermedDeviceControl", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.1.3": { "d": "qgpkiMedIntermedDevice", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.1.4": { "d": "qgpkiMedIntermedAuthorisedParty", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.1.5": { "d": "qgpkiMedIntermedDeviceSystem", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.2": { "d": "qgpkiMedIssuingCA", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.2.1": { "d": "qgpkiMedIssuingIndividual", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.2.2": { "d": "qgpkiMedIssuingDeviceControl", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.2.3": { "d": "qgpkiMedIssuingDevice", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.2.4": { "d": "qgpkiMedIssuingAuthorisedParty", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.2.5": { "d": "qgpkiMedIssuingClientAuth", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.2.6": { "d": "qgpkiMedIssuingServerAuth", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.2.7": { "d": "qgpkiMedIssuingDataProt", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.2.8": { "d": "qgpkiMedIssuingTokenAuth", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.3": { "d": "qgpkiBasicIntermedCA", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.3.1": { "d": "qgpkiBasicIntermedDeviceSystem", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.4": { "d": "qgpkiBasicIssuingCA", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.4.1": { "d": "qgpkiBasicIssuingClientAuth", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.4.2": { "d": "qgpkiBasicIssuingServerAuth", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.1.4.3": { "d": "qgpkiBasicIssuingDataSigning", "c": "QGPKI policy" }, +"1.2.36.1.3.1.1.1.2": { "d": "qgpkiAssuranceLevel", "c": "QGPKI assurance level" }, +"1.2.36.1.3.1.1.1.2.1": { "d": "qgpkiAssuranceRudimentary", "c": "QGPKI assurance level" }, +"1.2.36.1.3.1.1.1.2.2": { "d": "qgpkiAssuranceBasic", "c": "QGPKI assurance level" }, +"1.2.36.1.3.1.1.1.2.3": { "d": "qgpkiAssuranceMedium", "c": "QGPKI assurance level" }, +"1.2.36.1.3.1.1.1.2.4": { "d": "qgpkiAssuranceHigh", "c": "QGPKI assurance level" }, +"1.2.36.1.3.1.1.1.3": { "d": "qgpkiCertFunction", "c": "QGPKI policies" }, +"1.2.36.1.3.1.1.1.3.1": { "d": "qgpkiFunctionIndividual", "c": "QGPKI policies" }, +"1.2.36.1.3.1.1.1.3.2": { "d": "qgpkiFunctionDevice", "c": "QGPKI policies" }, +"1.2.36.1.3.1.1.1.3.3": { "d": "qgpkiFunctionAuthorisedParty", "c": "QGPKI policies" }, +"1.2.36.1.3.1.1.1.3.4": { "d": "qgpkiFunctionDeviceControl", "c": "QGPKI policies" }, +"1.2.36.1.3.1.2": { "d": "qpspki", "c": "Queensland Police PKI" }, +"1.2.36.1.3.1.2.1": { "d": "qpspkiPolicies", "c": "Queensland Police PKI" }, +"1.2.36.1.3.1.2.1.2": { "d": "qpspkiPolicyBasic", "c": "Queensland Police PKI" }, +"1.2.36.1.3.1.2.1.3": { "d": "qpspkiPolicyMedium", "c": "Queensland Police PKI" }, +"1.2.36.1.3.1.2.1.4": { "d": "qpspkiPolicyHigh", "c": "Queensland Police PKI" }, +"1.2.36.1.3.1.3.2": { "d": "qtmrpki", "c": "Queensland Transport PKI" }, +"1.2.36.1.3.1.3.2.1": { "d": "qtmrpkiPolicies", "c": "Queensland Transport PKI" }, +"1.2.36.1.3.1.3.2.2": { "d": "qtmrpkiPurpose", "c": "Queensland Transport PKI" }, +"1.2.36.1.3.1.3.2.2.1": { "d": "qtmrpkiIndividual", "c": "Queensland Transport PKI purpose" }, +"1.2.36.1.3.1.3.2.2.2": { "d": "qtmrpkiDeviceControl", "c": "Queensland Transport PKI purpose" }, +"1.2.36.1.3.1.3.2.2.3": { "d": "qtmrpkiDevice", "c": "Queensland Transport PKI purpose" }, +"1.2.36.1.3.1.3.2.2.4": { "d": "qtmrpkiAuthorisedParty", "c": "Queensland Transport PKI purpose" }, +"1.2.36.1.3.1.3.2.2.5": { "d": "qtmrpkiDeviceSystem", "c": "Queensland Transport PKI purpose" }, +"1.2.36.1.3.1.3.2.3": { "d": "qtmrpkiDevice", "c": "Queensland Transport PKI" }, +"1.2.36.1.3.1.3.2.3.1": { "d": "qtmrpkiDriverLicense", "c": "Queensland Transport PKI device" }, +"1.2.36.1.3.1.3.2.3.2": { "d": "qtmrpkiIndustryAuthority", "c": "Queensland Transport PKI device" }, +"1.2.36.1.3.1.3.2.3.3": { "d": "qtmrpkiMarineLicense", "c": "Queensland Transport PKI device" }, +"1.2.36.1.3.1.3.2.3.4": { "d": "qtmrpkiAdultProofOfAge", "c": "Queensland Transport PKI device" }, +"1.2.36.1.3.1.3.2.3.5": { "d": "qtmrpkiSam", "c": "Queensland Transport PKI device" }, +"1.2.36.1.3.1.3.2.4": { "d": "qtmrpkiAuthorisedParty", "c": "Queensland Transport PKI" }, +"1.2.36.1.3.1.3.2.4.1": { "d": "qtmrpkiTransportInspector", "c": "Queensland Transport PKI authorised party" }, +"1.2.36.1.3.1.3.2.4.2": { "d": "qtmrpkiPoliceOfficer", "c": "Queensland Transport PKI authorised party" }, +"1.2.36.1.3.1.3.2.4.3": { "d": "qtmrpkiSystem", "c": "Queensland Transport PKI authorised party" }, +"1.2.36.1.3.1.3.2.4.4": { "d": "qtmrpkiLiquorLicensingInspector", "c": "Queensland Transport PKI authorised party" }, +"1.2.36.1.3.1.3.2.4.5": { "d": "qtmrpkiMarineEnforcementOfficer", "c": "Queensland Transport PKI authorised party" }, +"1.2.36.1.333.1": { "d": "australianBusinessNumber", "c": "Australian Government corporate taxpayer ID" }, +"1.2.36.68980861.1.1.2": { "d": "signetPersonal", "c": "Signet CA" }, +"1.2.36.68980861.1.1.3": { "d": "signetBusiness", "c": "Signet CA" }, +"1.2.36.68980861.1.1.4": { "d": "signetLegal", "c": "Signet CA" }, +"1.2.36.68980861.1.1.10": { "d": "signetPilot", "c": "Signet CA" }, +"1.2.36.68980861.1.1.11": { "d": "signetIntraNet", "c": "Signet CA" }, +"1.2.36.68980861.1.1.20": { "d": "signetPolicy", "c": "Signet CA" }, +"1.2.36.75878867.1.100.1.1": { "d": "certificatesAustraliaPolicy", "c": "Certificates Australia CA" }, +"1.2.156.10197.1": { "d": "gmtCryptographicAlgorithm", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.100": { "d": "gmtBlockCipher", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.102": { "d": "sm1Cipher", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.103": { "d": "ssf33Cipher", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.104": { "d": "sm4Cipher", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.200": { "d": "gmtStreamCipher", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.201": { "d": "zucCipher", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.300": { "d": "gmtPublicKeyCryptography", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.301": { "d": "sm2ECC", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.301.1": { "d": "sm2-1DigitalSignature", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.301.2": { "d": "sm2-2KeyExchange", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.301.3": { "d": "sm2-3PublicKeyEncryption", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.302": { "d": "gmtSM9IBE", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.302.1": { "d": "sm9-1DigitalSignature", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.302.2": { "d": "sm9-2KeyExchange", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.302.3": { "d": "sm9-3PublicKeyEncryption", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.400": { "d": "gmtHashAlgorithm", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.401": { "d": "sm3Hash", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.401.1": { "d": "sm3HashWithoutKey", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.401.2": { "d": "sm3HashWithKey", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.500": { "d": "gmtDigestSigning", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.501": { "d": "sm2withSM3", "c": "China GM Standards Committee" }, +"1.2.156.10197.1.504": { "d": "rsaWithSM3", "c": "China GM Standards Committee" }, +"1.2.156.10197.4.3": { "d": "gmtCertificateAuthority", "c": "China GM Standards Committee" }, +"1.2.156.10197.6": { "d": "gmtStandardClass", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.1": { "d": "gmtFoundationClass", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.1.1": { "d": "gmtAlgorithmClass", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.1.1.1": { "d": "zucStandard", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.1.1.2": { "d": "sm4Standard", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.1.1.3": { "d": "sm2Standard", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.1.1.4": { "d": "sm3Standard", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.1.2": { "d": "gmtIDClass", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.1.2.1": { "d": "gmtCryptoID", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.1.3": { "d": "gmtOperationModes", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.1.4": { "d": "gmtSecurityMechanism", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.1.4.1": { "d": "gmtSM2Specification", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.1.4.2": { "d": "gmtSM2CryptographicMessageSyntax", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.2": { "d": "gmtDeviceClass", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.3": { "d": "gmtServiceClass", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.4": { "d": "gmtInfrastructure", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.5": { "d": "gmtTestingClass", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.5.1": { "d": "gmtRandomTestingClass", "c": "China GM Standards Committee" }, +"1.2.156.10197.6.6": { "d": "gmtManagementClass", "c": "China GM Standards Committee" }, +"1.2.392.200011.61.1.1.1": { "d": "mitsubishiSecurityAlgorithm", "c": "Mitsubishi security algorithm" }, +"1.2.392.200011.61.1.1.1.1": { "d": "misty1-cbc", "c": "Mitsubishi security algorithm" }, +"1.2.410.200004.1": { "d": "kisaAlgorithm", "c": "KISA algorithm" }, +"1.2.410.200004.1.1": { "d": "kcdsa", "c": "Korean DSA" }, +"1.2.410.200004.1.2": { "d": "has160", "c": "Korean hash algorithm" }, +"1.2.410.200004.1.3": { "d": "seedECB", "c": "Korean SEED algorithm, ECB mode" }, +"1.2.410.200004.1.4": { "d": "seedCBC", "c": "Korean SEED algorithm, CBC mode" }, +"1.2.410.200004.1.5": { "d": "seedOFB", "c": "Korean SEED algorithm, OFB mode" }, +"1.2.410.200004.1.6": { "d": "seedCFB", "c": "Korean SEED algorithm, CFB mode" }, +"1.2.410.200004.1.7": { "d": "seedMAC", "c": "Korean SEED algorithm, MAC mode" }, +"1.2.410.200004.1.8": { "d": "kcdsaWithHAS160", "c": "Korean signature algorithm" }, +"1.2.410.200004.1.9": { "d": "kcdsaWithSHA1", "c": "Korean signature algorithm" }, +"1.2.410.200004.1.10": { "d": "pbeWithHAS160AndSEED-ECB", "c": "Korean SEED algorithm, PBE key derivation" }, +"1.2.410.200004.1.11": { "d": "pbeWithHAS160AndSEED-CBC", "c": "Korean SEED algorithm, PBE key derivation" }, +"1.2.410.200004.1.12": { "d": "pbeWithHAS160AndSEED-CFB", "c": "Korean SEED algorithm, PBE key derivation" }, +"1.2.410.200004.1.13": { "d": "pbeWithHAS160AndSEED-OFB", "c": "Korean SEED algorithm, PBE key derivation" }, +"1.2.410.200004.1.14": { "d": "pbeWithSHA1AndSEED-ECB", "c": "Korean SEED algorithm, PBE key derivation" }, +"1.2.410.200004.1.15": { "d": "pbeWithSHA1AndSEED-CBC", "c": "Korean SEED algorithm, PBE key derivation" }, +"1.2.410.200004.1.16": { "d": "pbeWithSHA1AndSEED-CFB", "c": "Korean SEED algorithm, PBE key derivation" }, +"1.2.410.200004.1.17": { "d": "pbeWithSHA1AndSEED-OFB", "c": "Korean SEED algorithm, PBE key derivation" }, +"1.2.410.200004.1.20": { "d": "rsaWithHAS160", "c": "Korean signature algorithm" }, +"1.2.410.200004.1.21": { "d": "kcdsa1", "c": "Korean DSA" }, +"1.2.410.200004.2": { "d": "npkiCP", "c": "KISA NPKI certificate policies" }, +"1.2.410.200004.2.1": { "d": "npkiSignaturePolicy", "c": "KISA NPKI certificate policies" }, +"1.2.410.200004.3": { "d": "npkiKP", "c": "KISA NPKI key usage" }, +"1.2.410.200004.4": { "d": "npkiAT", "c": "KISA NPKI attribute" }, +"1.2.410.200004.5": { "d": "npkiLCA", "c": "KISA NPKI licensed CA" }, +"1.2.410.200004.5.1": { "d": "npkiSignKorea", "c": "KISA NPKI licensed CA" }, +"1.2.410.200004.5.2": { "d": "npkiSignGate", "c": "KISA NPKI licensed CA" }, +"1.2.410.200004.5.3": { "d": "npkiNcaSign", "c": "KISA NPKI licensed CA" }, +"1.2.410.200004.6": { "d": "npkiON", "c": "KISA NPKI otherName" }, +"1.2.410.200004.7": { "d": "npkiAPP", "c": "KISA NPKI application" }, +"1.2.410.200004.7.1": { "d": "npkiSMIME", "c": "KISA NPKI application" }, +"1.2.410.200004.7.1.1": { "d": "npkiSMIMEAlgo", "c": "KISA NPKI application" }, +"1.2.410.200004.7.1.1.1": { "d": "npkiCmsSEEDWrap", "c": "KISA NPKI application" }, +"1.2.410.200004.10": { "d": "npki", "c": "KISA NPKI" }, +"1.2.410.200004.10.1": { "d": "npkiAttribute", "c": "KISA NPKI attribute" }, +"1.2.410.200004.10.1.1": { "d": "npkiIdentifyData", "c": "KISA NPKI attribute" }, +"1.2.410.200004.10.1.1.1": { "d": "npkiVID", "c": "KISA NPKI attribute" }, +"1.2.410.200004.10.1.1.2": { "d": "npkiEncryptedVID", "c": "KISA NPKI attribute" }, +"1.2.410.200004.10.1.1.3": { "d": "npkiRandomNum", "c": "KISA NPKI attribute" }, +"1.2.410.200004.10.1.1.4": { "d": "npkiVID", "c": "KISA NPKI attribute" }, +"1.2.410.200046.1.1": { "d": "aria1AlgorithmModes", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.1": { "d": "aria128-ecb", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.2": { "d": "aria128-cbc", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.3": { "d": "aria128-cfb", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.4": { "d": "aria128-ofb", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.5": { "d": "aria128-ctr", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.6": { "d": "aria192-ecb", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.7": { "d": "aria192-cbc", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.8": { "d": "aria192-cfb", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.9": { "d": "aria192-ofb", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.10": { "d": "aria192-ctr", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.11": { "d": "aria256-ecb", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.12": { "d": "aria256-cbc", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.13": { "d": "aria256-cfb", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.14": { "d": "aria256-ofb", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.15": { "d": "aria256-ctr", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.21": { "d": "aria128-cmac", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.22": { "d": "aria192-cmac", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.23": { "d": "aria256-cmac", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.31": { "d": "aria128-ocb2", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.32": { "d": "aria192-ocb2", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.33": { "d": "aria256-ocb2", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.34": { "d": "aria128-gcm", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.35": { "d": "aria192-gcm", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.36": { "d": "aria256-gcm", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.37": { "d": "aria128-ccm", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.38": { "d": "aria192-ccm", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.39": { "d": "aria256-ccm", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.40": { "d": "aria128-keywrap", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.41": { "d": "aria192-keywrap", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.42": { "d": "aria256-keywrap", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.43": { "d": "aria128-keywrapWithPad", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.44": { "d": "aria192-keywrapWithPad", "c": "ARIA algorithm modes" }, +"1.2.410.200046.1.1.45": { "d": "aria256-keywrapWithPad", "c": "ARIA algorithm modes" }, +"1.2.643.2.2.3": { "d": "gostSignature", "c": "GOST R 34.10-2001 + GOST R 34.11-94 signature" }, +"1.2.643.2.2.4": { "d": "gost94Signature", "c": "GOST R 34.10-94 + GOST R 34.11-94 signature. Obsoleted by GOST R 34.10-2001", "w": true }, +"1.2.643.2.2.19": { "d": "gostPublicKey", "c": "GOST R 34.10-2001 (ECC) public key" }, +"1.2.643.2.2.20": { "d": "gost94PublicKey", "c": "GOST R 34.10-94 public key. Obsoleted by GOST R 34.10-2001", "w": true }, +"1.2.643.2.2.21": { "d": "gostCipher", "c": "GOST 28147-89 (symmetric key block cipher)" }, +"1.2.643.2.2.31.0": { "d": "testCipherParams", "c": "Test params for GOST 28147-89" }, +"1.2.643.2.2.31.1": { "d": "cryptoProCipherA", "c": "CryptoPro params A (default, variant 'Verba-O') for GOST 28147-89" }, +"1.2.643.2.2.31.2": { "d": "cryptoProCipherB", "c": "CryptoPro params B (variant 1) for GOST 28147-89" }, +"1.2.643.2.2.31.3": { "d": "cryptoProCipherC", "c": "CryptoPro params C (variant 2) for GOST 28147-89" }, +"1.2.643.2.2.31.4": { "d": "cryptoProCipherD", "c": "CryptoPro params D (variant 3) for GOST 28147-89" }, +"1.2.643.2.2.31.5": { "d": "oscar11Cipher", "c": "Oscar-1.1 params for GOST 28147-89" }, +"1.2.643.2.2.31.6": { "d": "oscar10Cipher", "c": "Oscar-1.0 params for GOST 28147-89" }, +"1.2.643.2.2.31.7": { "d": "ric1Cipher", "c": "RIC-1 params for GOST 28147-89" }, +"1.2.643.2.2.31.12": { "d": "tc26CipherA", "c": "TC26 params 2 for GOST 28147-89" }, +"1.2.643.2.2.31.13": { "d": "tc26CipherB", "c": "TC26 params 1 for GOST 28147-89" }, +"1.2.643.2.2.31.14": { "d": "tc26CipherC", "c": "TC26 params 3 for GOST 28147-89" }, +"1.2.643.2.2.31.15": { "d": "tc26CipherD", "c": "TC26 params 4 for GOST 28147-89" }, +"1.2.643.2.2.31.16": { "d": "tc26CipherE", "c": "TC26 params 5 for GOST 28147-89" }, +"1.2.643.2.2.31.17": { "d": "tc26CipherF", "c": "TC26 params 6 for GOST 28147-89" }, +"1.2.643.7.1.2.5.1.1": { "d": "tc26CipherZ", "c": "TC26 params Z for GOST 28147-89" }, +"1.2.643.2.2.9": { "d": "gostDigest", "c": "GOST R 34.11-94 digest" }, +"1.2.643.2.2.30.0": { "d": "testDigestParams", "c": "Test params for GOST R 34.11-94" }, +"1.2.643.2.2.30.1": { "d": "cryptoProDigestA", "c": "CryptoPro digest params A (default, variant 'Verba-O') for GOST R 34.11-94" }, +"1.2.643.2.2.30.2": { "d": "cryptoProDigestB", "c": "CryptoPro digest params B (variant 1) for GOST R 34.11-94" }, +"1.2.643.2.2.30.3": { "d": "cryptoProDigestC", "c": "CryptoPro digest params C (variant 2) for GOST R 34.11-94" }, +"1.2.643.2.2.30.4": { "d": "cryptoProDigestD", "c": "CryptoPro digest params D (variant 3) for GOST R 34.11-94" }, +"1.2.643.2.2.32.2": { "d": "cryptoPro94SignA", "c": "CryptoPro sign params A (default, variant 'Verba-O') for GOST R 34.10-94" }, +"1.2.643.2.2.32.3": { "d": "cryptoPro94SignB", "c": "CryptoPro sign params B (variant 1) for GOST R 34.10-94" }, +"1.2.643.2.2.32.4": { "d": "cryptoPro94SignC", "c": "CryptoPro sign params C (variant 2) for GOST R 34.10-94" }, +"1.2.643.2.2.32.5": { "d": "cryptoPro94SignD", "c": "CryptoPro sign params D (variant 3) for GOST R 34.10-94" }, +"1.2.643.2.2.33.1": { "d": "cryptoPro94SignXA", "c": "CryptoPro sign params XA (variant 1) for GOST R 34.10-94" }, +"1.2.643.2.2.33.2": { "d": "cryptoPro94SignXB", "c": "CryptoPro sign params XB (variant 2) for GOST R 34.10-94" }, +"1.2.643.2.2.33.3": { "d": "cryptoPro94SignXC", "c": "CryptoPro sign params XC (variant 3) for GOST R 34.10-94" }, +"1.2.643.2.2.35.0": { "d": "testSignParams", "c": "Test elliptic curve for GOST R 34.10-2001" }, +"1.2.643.2.2.35.1": { "d": "cryptoProSignA", "c": "CryptoPro ell.curve A for GOST R 34.10-2001" }, +"1.2.643.2.2.35.2": { "d": "cryptoProSignB", "c": "CryptoPro ell.curve B for GOST R 34.10-2001" }, +"1.2.643.2.2.35.3": { "d": "cryptoProSignC", "c": "CryptoPro ell.curve C for GOST R 34.10-2001" }, +"1.2.643.2.2.36.0": { "d": "cryptoProSignXA", "c": "CryptoPro ell.curve XA for GOST R 34.10-2001" }, +"1.2.643.2.2.36.1": { "d": "cryptoProSignXB", "c": "CryptoPro ell.curve XB for GOST R 34.10-2001" }, +"1.2.643.7.1.2.1.1.1": { "d": "cryptoPro2012Sign256A", "c": "CryptoPro ell.curve A for GOST R 34.10-2012 256 bit" }, +"1.2.643.7.1.2.1.2.1": { "d": "cryptoPro2012Sign512A", "c": "CryptoPro ell.curve A (default) for GOST R 34.10-2012 512 bit" }, +"1.2.643.7.1.2.1.2.2": { "d": "cryptoPro2012Sign512B", "c": "CryptoPro ell.curve B for GOST R 34.10-2012 512 bit" }, +"1.2.643.7.1.2.1.2.3": { "d": "cryptoPro2012Sign512C", "c": "CryptoPro ell.curve C for GOST R 34.10-2012 512 bit" }, +"1.2.643.2.2.14.0": { "d": "nullMeshing", "c": "Do not mesh state of GOST 28147-89 cipher" }, +"1.2.643.2.2.14.1": { "d": "cryptoProMeshing", "c": "CryptoPro meshing of state of GOST 28147-89 cipher" }, +"1.2.643.2.2.10": { "d": "hmacGost", "c": "HMAC with GOST R 34.11-94" }, +"1.2.643.2.2.13.0": { "d": "gostWrap", "c": "Wrap key using GOST 28147-89 key" }, +"1.2.643.2.2.13.1": { "d": "cryptoProWrap", "c": "Wrap key using diversified GOST 28147-89 key" }, +"1.2.643.2.2.96": { "d": "cryptoProECDHWrap", "c": "Wrap key using ECC DH on GOST R 34.10-2001 keys (VKO)" }, +"1.2.643.7.1.1.1.1": { "d": "gost2012PublicKey256", "c": "GOST R 34.10-2012 256 bit public key" }, +"1.2.643.7.1.1.1.2": { "d": "gost2012PublicKey512", "c": "GOST R 34.10-2012 512 bit public key" }, +"1.2.643.7.1.1.2.2": { "d": "gost2012Digest256", "c": "GOST R 34.11-2012 256 bit digest" }, +"1.2.643.7.1.1.2.3": { "d": "gost2012Digest512", "c": "GOST R 34.11-2012 512 bit digest" }, +"1.2.643.7.1.1.3.2": { "d": "gost2012Signature256", "c": "GOST R 34.10-2012 256 bit signature" }, +"1.2.643.7.1.1.3.3": { "d": "gost2012Signature512", "c": "GOST R 34.10-2012 512 bit signature" }, +"1.2.643.7.1.1.6.1": { "d": "cryptoProECDH256", "c": "CryptoPro ECC DH algorithm for GOST R 34.10-2012 256 bit key" }, +"1.2.643.7.1.1.6.2": { "d": "cryptoProECDH512", "c": "CryptoPro ECC DH algorithm for GOST R 34.10-2012 512 bit key" }, +"1.2.752.34.1": { "d": "seis-cp", "c": "SEIS Project" }, +"1.2.752.34.1.1": { "d": "SEIS high-assurance policyIdentifier", "c": "SEIS Project certificate policies" }, +"1.2.752.34.1.2": { "d": "SEIS GAK policyIdentifier", "c": "SEIS Project certificate policies" }, +"1.2.752.34.2": { "d": "SEIS pe", "c": "SEIS Project" }, +"1.2.752.34.3": { "d": "SEIS at", "c": "SEIS Project" }, +"1.2.752.34.3.1": { "d": "SEIS at-personalIdentifier", "c": "SEIS Project attribute" }, +"1.2.840.10040.1": { "d": "module", "c": "ANSI X9.57" }, +"1.2.840.10040.1.1": { "d": "x9f1-cert-mgmt", "c": "ANSI X9.57 module" }, +"1.2.840.10040.2": { "d": "holdinstruction", "c": "ANSI X9.57" }, +"1.2.840.10040.2.1": { "d": "holdinstruction-none", "c": "ANSI X9.57 hold instruction" }, +"1.2.840.10040.2.2": { "d": "callissuer", "c": "ANSI X9.57 hold instruction" }, +"1.2.840.10040.2.3": { "d": "reject", "c": "ANSI X9.57 hold instruction" }, +"1.2.840.10040.2.4": { "d": "pickupToken", "c": "ANSI X9.57 hold instruction" }, +"1.2.840.10040.3": { "d": "attribute", "c": "ANSI X9.57" }, +"1.2.840.10040.3.1": { "d": "countersignature", "c": "ANSI X9.57 attribute" }, +"1.2.840.10040.3.2": { "d": "attribute-cert", "c": "ANSI X9.57 attribute" }, +"1.2.840.10040.4": { "d": "algorithm", "c": "ANSI X9.57" }, +"1.2.840.10040.4.1": { "d": "dsa", "c": "ANSI X9.57 algorithm" }, +"1.2.840.10040.4.2": { "d": "dsa-match", "c": "ANSI X9.57 algorithm" }, +"1.2.840.10040.4.3": { "d": "dsaWithSha1", "c": "ANSI X9.57 algorithm" }, +"1.2.840.10045.1": { "d": "fieldType", "c": "ANSI X9.62. This OID is also assigned as ecdsa-with-SHA1" }, +"1.2.840.10045.1.1": { "d": "prime-field", "c": "ANSI X9.62 field type" }, +"1.2.840.10045.1.2": { "d": "characteristic-two-field", "c": "ANSI X9.62 field type" }, +"1.2.840.10045.1.2.3": { "d": "characteristic-two-basis", "c": "ANSI X9.62 field type" }, +"1.2.840.10045.1.2.3.1": { "d": "onBasis", "c": "ANSI X9.62 field basis" }, +"1.2.840.10045.1.2.3.2": { "d": "tpBasis", "c": "ANSI X9.62 field basis" }, +"1.2.840.10045.1.2.3.3": { "d": "ppBasis", "c": "ANSI X9.62 field basis" }, +"1.2.840.10045.2": { "d": "publicKeyType", "c": "ANSI X9.62" }, +"1.2.840.10045.2.1": { "d": "ecPublicKey", "c": "ANSI X9.62 public key type" }, +"1.2.840.10045.3.0.1": { "d": "c2pnb163v1", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.0.2": { "d": "c2pnb163v2", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.0.3": { "d": "c2pnb163v3", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.0.5": { "d": "c2tnb191v1", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.0.6": { "d": "c2tnb191v2", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.0.7": { "d": "c2tnb191v3", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.0.10": { "d": "c2pnb208w1", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.0.11": { "d": "c2tnb239v1", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.0.12": { "d": "c2tnb239v2", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.0.13": { "d": "c2tnb239v3", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.0.16": { "d": "c2pnb272w1", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.0.18": { "d": "c2tnb359v1", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.0.19": { "d": "c2pnb368w1", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.0.20": { "d": "c2tnb431r1", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.1.1": { "d": "prime192v1", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.1.2": { "d": "prime192v2", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.1.3": { "d": "prime192v3", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.1.4": { "d": "prime239v1", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.1.5": { "d": "prime239v2", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.1.6": { "d": "prime239v3", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.3.1.7": { "d": "prime256v1", "c": "ANSI X9.62 named elliptic curve" }, +"1.2.840.10045.4.1": { "d": "ecdsaWithSHA1", "c": "ANSI X9.62 ECDSA algorithm with SHA1" }, +"1.2.840.10045.4.2": { "d": "ecdsaWithRecommended", "c": "ANSI X9.62 ECDSA algorithm with Recommended" }, +"1.2.840.10045.4.3": { "d": "ecdsaWithSpecified", "c": "ANSI X9.62 ECDSA algorithm with Specified" }, +"1.2.840.10045.4.3.1": { "d": "ecdsaWithSHA224", "c": "ANSI X9.62 ECDSA algorithm with SHA224" }, +"1.2.840.10045.4.3.2": { "d": "ecdsaWithSHA256", "c": "ANSI X9.62 ECDSA algorithm with SHA256" }, +"1.2.840.10045.4.3.3": { "d": "ecdsaWithSHA384", "c": "ANSI X9.62 ECDSA algorithm with SHA384" }, +"1.2.840.10045.4.3.4": { "d": "ecdsaWithSHA512", "c": "ANSI X9.62 ECDSA algorithm with SHA512" }, +"1.2.840.10046.1": { "d": "fieldType", "c": "ANSI X9.42" }, +"1.2.840.10046.1.1": { "d": "gf-prime", "c": "ANSI X9.42 field type" }, +"1.2.840.10046.2": { "d": "numberType", "c": "ANSI X9.42" }, +"1.2.840.10046.2.1": { "d": "dhPublicKey", "c": "ANSI X9.42 number type" }, +"1.2.840.10046.3": { "d": "scheme", "c": "ANSI X9.42" }, +"1.2.840.10046.3.1": { "d": "dhStatic", "c": "ANSI X9.42 scheme" }, +"1.2.840.10046.3.2": { "d": "dhEphem", "c": "ANSI X9.42 scheme" }, +"1.2.840.10046.3.3": { "d": "dhHybrid1", "c": "ANSI X9.42 scheme" }, +"1.2.840.10046.3.4": { "d": "dhHybrid2", "c": "ANSI X9.42 scheme" }, +"1.2.840.10046.3.5": { "d": "mqv2", "c": "ANSI X9.42 scheme" }, +"1.2.840.10046.3.6": { "d": "mqv1", "c": "ANSI X9.42 scheme" }, +"1.2.840.10065.2.2": { "d": "?", "c": "ASTM 31.20" }, +"1.2.840.10065.2.3": { "d": "healthcareLicense", "c": "ASTM 31.20" }, +"1.2.840.10065.2.3.1.1": { "d": "license?", "c": "ASTM 31.20 healthcare license type" }, +"1.2.840.10070": { "d": "iec62351", "c": "IEC 62351" }, +"1.2.840.10070.8": { "d": "iec62351_8", "c": "IEC 62351-8" }, +"1.2.840.10070.8.1": { "d": "iecUserRoles", "c": "IEC 62351-8" }, +"1.2.840.113533.7": { "d": "nsn", "c": "" }, +"1.2.840.113533.7.65": { "d": "nsn-ce", "c": "" }, +"1.2.840.113533.7.65.0": { "d": "entrustVersInfo", "c": "Nortel Secure Networks ce" }, +"1.2.840.113533.7.66": { "d": "nsn-alg", "c": "" }, +"1.2.840.113533.7.66.3": { "d": "cast3CBC", "c": "Nortel Secure Networks alg" }, +"1.2.840.113533.7.66.10": { "d": "cast5CBC", "c": "Nortel Secure Networks alg" }, +"1.2.840.113533.7.66.11": { "d": "cast5MAC", "c": "Nortel Secure Networks alg" }, +"1.2.840.113533.7.66.12": { "d": "pbeWithMD5AndCAST5-CBC", "c": "Nortel Secure Networks alg" }, +"1.2.840.113533.7.66.13": { "d": "passwordBasedMac", "c": "Nortel Secure Networks alg" }, +"1.2.840.113533.7.67": { "d": "nsn-oc", "c": "" }, +"1.2.840.113533.7.67.0": { "d": "entrustUser", "c": "Nortel Secure Networks oc" }, +"1.2.840.113533.7.68": { "d": "nsn-at", "c": "" }, +"1.2.840.113533.7.68.0": { "d": "entrustCAInfo", "c": "Nortel Secure Networks at" }, +"1.2.840.113533.7.68.10": { "d": "attributeCertificate", "c": "Nortel Secure Networks at" }, +"1.2.840.113549.1.1": { "d": "pkcs-1", "c": "" }, +"1.2.840.113549.1.1.1": { "d": "rsaEncryption", "c": "PKCS #1" }, +"1.2.840.113549.1.1.2": { "d": "md2WithRSAEncryption", "c": "PKCS #1" }, +"1.2.840.113549.1.1.3": { "d": "md4WithRSAEncryption", "c": "PKCS #1" }, +"1.2.840.113549.1.1.4": { "d": "md5WithRSAEncryption", "c": "PKCS #1" }, +"1.2.840.113549.1.1.5": { "d": "sha1WithRSAEncryption", "c": "PKCS #1" }, +"1.2.840.113549.1.1.7": { "d": "rsaOAEP", "c": "PKCS #1" }, +"1.2.840.113549.1.1.8": { "d": "pkcs1-MGF", "c": "PKCS #1" }, +"1.2.840.113549.1.1.9": { "d": "rsaOAEP-pSpecified", "c": "PKCS #1" }, +"1.2.840.113549.1.1.10": { "d": "rsaPSS", "c": "PKCS #1" }, +"1.2.840.113549.1.1.11": { "d": "sha256WithRSAEncryption", "c": "PKCS #1" }, +"1.2.840.113549.1.1.12": { "d": "sha384WithRSAEncryption", "c": "PKCS #1" }, +"1.2.840.113549.1.1.13": { "d": "sha512WithRSAEncryption", "c": "PKCS #1" }, +"1.2.840.113549.1.1.14": { "d": "sha224WithRSAEncryption", "c": "PKCS #1" }, +"1.2.840.113549.1.1.6": { "d": "rsaOAEPEncryptionSET", "c": "PKCS #1. This OID may also be assigned as ripemd160WithRSAEncryption" }, +"1.2.840.113549.1.2": { "d": "bsafeRsaEncr", "c": "Obsolete BSAFE OID", "w": true }, +"1.2.840.113549.1.3": { "d": "pkcs-3", "c": "" }, +"1.2.840.113549.1.3.1": { "d": "dhKeyAgreement", "c": "PKCS #3" }, +"1.2.840.113549.1.5": { "d": "pkcs-5", "c": "" }, +"1.2.840.113549.1.5.1": { "d": "pbeWithMD2AndDES-CBC", "c": "PKCS #5" }, +"1.2.840.113549.1.5.3": { "d": "pbeWithMD5AndDES-CBC", "c": "PKCS #5" }, +"1.2.840.113549.1.5.4": { "d": "pbeWithMD2AndRC2-CBC", "c": "PKCS #5" }, +"1.2.840.113549.1.5.6": { "d": "pbeWithMD5AndRC2-CBC", "c": "PKCS #5" }, +"1.2.840.113549.1.5.9": { "d": "pbeWithMD5AndXOR", "c": "PKCS #5, used in BSAFE only", "w": true }, +"1.2.840.113549.1.5.10": { "d": "pbeWithSHAAndDES-CBC", "c": "PKCS #5" }, +"1.2.840.113549.1.5.12": { "d": "pkcs5PBKDF2", "c": "PKCS #5 v2.0" }, +"1.2.840.113549.1.5.13": { "d": "pkcs5PBES2", "c": "PKCS #5 v2.0" }, +"1.2.840.113549.1.5.14": { "d": "pkcs5PBMAC1", "c": "PKCS #5 v2.0" }, +"1.2.840.113549.1.7": { "d": "pkcs-7", "c": "" }, +"1.2.840.113549.1.7.1": { "d": "data", "c": "PKCS #7" }, +"1.2.840.113549.1.7.2": { "d": "signedData", "c": "PKCS #7" }, +"1.2.840.113549.1.7.3": { "d": "envelopedData", "c": "PKCS #7" }, +"1.2.840.113549.1.7.4": { "d": "signedAndEnvelopedData", "c": "PKCS #7" }, +"1.2.840.113549.1.7.5": { "d": "digestedData", "c": "PKCS #7" }, +"1.2.840.113549.1.7.6": { "d": "encryptedData", "c": "PKCS #7" }, +"1.2.840.113549.1.7.7": { "d": "dataWithAttributes", "c": "PKCS #7 experimental", "w": true }, +"1.2.840.113549.1.7.8": { "d": "encryptedPrivateKeyInfo", "c": "PKCS #7 experimental", "w": true }, +"1.2.840.113549.1.9": { "d": "pkcs-9", "c": "" }, +"1.2.840.113549.1.9.1": { "d": "emailAddress", "c": "PKCS #9. Deprecated, use an altName extension instead" }, +"1.2.840.113549.1.9.2": { "d": "unstructuredName", "c": "PKCS #9" }, +"1.2.840.113549.1.9.3": { "d": "contentType", "c": "PKCS #9" }, +"1.2.840.113549.1.9.4": { "d": "messageDigest", "c": "PKCS #9" }, +"1.2.840.113549.1.9.5": { "d": "signingTime", "c": "PKCS #9" }, +"1.2.840.113549.1.9.6": { "d": "countersignature", "c": "PKCS #9" }, +"1.2.840.113549.1.9.7": { "d": "challengePassword", "c": "PKCS #9" }, +"1.2.840.113549.1.9.8": { "d": "unstructuredAddress", "c": "PKCS #9" }, +"1.2.840.113549.1.9.9": { "d": "extendedCertificateAttributes", "c": "PKCS #9" }, +"1.2.840.113549.1.9.10": { "d": "issuerAndSerialNumber", "c": "PKCS #9 experimental", "w": true }, +"1.2.840.113549.1.9.11": { "d": "passwordCheck", "c": "PKCS #9 experimental", "w": true }, +"1.2.840.113549.1.9.12": { "d": "publicKey", "c": "PKCS #9 experimental", "w": true }, +"1.2.840.113549.1.9.13": { "d": "signingDescription", "c": "PKCS #9" }, +"1.2.840.113549.1.9.14": { "d": "extensionRequest", "c": "PKCS #9 via CRMF" }, +"1.2.840.113549.1.9.15": { "d": "sMIMECapabilities", "c": "PKCS #9. This OID was formerly assigned as symmetricCapabilities, then reassigned as SMIMECapabilities, then renamed to the current name" }, +"1.2.840.113549.1.9.15.1": { "d": "preferSignedData", "c": "sMIMECapabilities" }, +"1.2.840.113549.1.9.15.2": { "d": "canNotDecryptAny", "c": "sMIMECapabilities" }, +"1.2.840.113549.1.9.15.3": { "d": "receiptRequest", "c": "sMIMECapabilities. Deprecated, use (1 2 840 113549 1 9 16 2 1) instead", "w": true }, +"1.2.840.113549.1.9.15.4": { "d": "receipt", "c": "sMIMECapabilities. Deprecated, use (1 2 840 113549 1 9 16 1 1) instead", "w": true }, +"1.2.840.113549.1.9.15.5": { "d": "contentHints", "c": "sMIMECapabilities. Deprecated, use (1 2 840 113549 1 9 16 2 4) instead", "w": true }, +"1.2.840.113549.1.9.15.6": { "d": "mlExpansionHistory", "c": "sMIMECapabilities. Deprecated, use (1 2 840 113549 1 9 16 2 3) instead", "w": true }, +"1.2.840.113549.1.9.16": { "d": "id-sMIME", "c": "PKCS #9" }, +"1.2.840.113549.1.9.16.0": { "d": "id-mod", "c": "id-sMIME" }, +"1.2.840.113549.1.9.16.0.1": { "d": "id-mod-cms", "c": "S/MIME Modules" }, +"1.2.840.113549.1.9.16.0.2": { "d": "id-mod-ess", "c": "S/MIME Modules" }, +"1.2.840.113549.1.9.16.0.3": { "d": "id-mod-oid", "c": "S/MIME Modules" }, +"1.2.840.113549.1.9.16.0.4": { "d": "id-mod-msg-v3", "c": "S/MIME Modules" }, +"1.2.840.113549.1.9.16.0.5": { "d": "id-mod-ets-eSignature-88", "c": "S/MIME Modules" }, +"1.2.840.113549.1.9.16.0.6": { "d": "id-mod-ets-eSignature-97", "c": "S/MIME Modules" }, +"1.2.840.113549.1.9.16.0.7": { "d": "id-mod-ets-eSigPolicy-88", "c": "S/MIME Modules" }, +"1.2.840.113549.1.9.16.0.8": { "d": "id-mod-ets-eSigPolicy-88", "c": "S/MIME Modules" }, +"1.2.840.113549.1.9.16.1": { "d": "contentType", "c": "S/MIME" }, +"1.2.840.113549.1.9.16.1.1": { "d": "receipt", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.2": { "d": "authData", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.3": { "d": "publishCert", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.4": { "d": "tSTInfo", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.5": { "d": "tDTInfo", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.6": { "d": "contentInfo", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.7": { "d": "dVCSRequestData", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.8": { "d": "dVCSResponseData", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.9": { "d": "compressedData", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.10": { "d": "scvpCertValRequest", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.11": { "d": "scvpCertValResponse", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.12": { "d": "scvpValPolRequest", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.13": { "d": "scvpValPolResponse", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.14": { "d": "attrCertEncAttrs", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.15": { "d": "tSReq", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.16": { "d": "firmwarePackage", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.17": { "d": "firmwareLoadReceipt", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.18": { "d": "firmwareLoadError", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.19": { "d": "contentCollection", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.20": { "d": "contentWithAttrs", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.21": { "d": "encKeyWithID", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.22": { "d": "encPEPSI", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.23": { "d": "authEnvelopedData", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.24": { "d": "routeOriginAttest", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.25": { "d": "symmetricKeyPackage", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.26": { "d": "rpkiManifest", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.27": { "d": "asciiTextWithCRLF", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.28": { "d": "xml", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.29": { "d": "pdf", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.30": { "d": "postscript", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.31": { "d": "timestampedData", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.32": { "d": "asAdjacencyAttest", "c": "S/MIME Content Types", "w": true }, +"1.2.840.113549.1.9.16.1.33": { "d": "rpkiTrustAnchor", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.1.34": { "d": "trustAnchorList", "c": "S/MIME Content Types" }, +"1.2.840.113549.1.9.16.2": { "d": "authenticatedAttributes", "c": "S/MIME" }, +"1.2.840.113549.1.9.16.2.1": { "d": "receiptRequest", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.2": { "d": "securityLabel", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.3": { "d": "mlExpandHistory", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.4": { "d": "contentHint", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.5": { "d": "msgSigDigest", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.6": { "d": "encapContentType", "c": "S/MIME Authenticated Attributes. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.2.7": { "d": "contentIdentifier", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.8": { "d": "macValue", "c": "S/MIME Authenticated Attributes. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.2.9": { "d": "equivalentLabels", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.10": { "d": "contentReference", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.11": { "d": "encrypKeyPref", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.12": { "d": "signingCertificate", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.13": { "d": "smimeEncryptCerts", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.14": { "d": "timeStampToken", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.15": { "d": "sigPolicyId", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.16": { "d": "commitmentType", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.17": { "d": "signerLocation", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.18": { "d": "signerAttr", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.19": { "d": "otherSigCert", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.20": { "d": "contentTimestamp", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.21": { "d": "certificateRefs", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.22": { "d": "revocationRefs", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.23": { "d": "certValues", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.24": { "d": "revocationValues", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.25": { "d": "escTimeStamp", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.26": { "d": "certCRLTimestamp", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.27": { "d": "archiveTimeStamp", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.28": { "d": "signatureType", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.29": { "d": "dvcsDvc", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.30": { "d": "cekReference", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.31": { "d": "maxCEKDecrypts", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.32": { "d": "kekDerivationAlg", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.33": { "d": "intendedRecipients", "c": "S/MIME Authenticated Attributes. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.2.34": { "d": "cmcUnsignedData", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.35": { "d": "fwPackageID", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.36": { "d": "fwTargetHardwareIDs", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.37": { "d": "fwDecryptKeyID", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.38": { "d": "fwImplCryptAlgs", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.39": { "d": "fwWrappedFirmwareKey", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.40": { "d": "fwCommunityIdentifiers", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.41": { "d": "fwPkgMessageDigest", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.42": { "d": "fwPackageInfo", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.43": { "d": "fwImplCompressAlgs", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.44": { "d": "etsAttrCertificateRefs", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.45": { "d": "etsAttrRevocationRefs", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.46": { "d": "binarySigningTime", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.47": { "d": "signingCertificateV2", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.48": { "d": "etsArchiveTimeStampV2", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.49": { "d": "erInternal", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.50": { "d": "erExternal", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.2.51": { "d": "multipleSignatures", "c": "S/MIME Authenticated Attributes" }, +"1.2.840.113549.1.9.16.3.1": { "d": "esDHwith3DES", "c": "S/MIME Algorithms. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.3.2": { "d": "esDHwithRC2", "c": "S/MIME Algorithms. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.3.3": { "d": "3desWrap", "c": "S/MIME Algorithms. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.3.4": { "d": "rc2Wrap", "c": "S/MIME Algorithms. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.3.5": { "d": "esDH", "c": "S/MIME Algorithms" }, +"1.2.840.113549.1.9.16.3.6": { "d": "cms3DESwrap", "c": "S/MIME Algorithms" }, +"1.2.840.113549.1.9.16.3.7": { "d": "cmsRC2wrap", "c": "S/MIME Algorithms" }, +"1.2.840.113549.1.9.16.3.8": { "d": "zlib", "c": "S/MIME Algorithms" }, +"1.2.840.113549.1.9.16.3.9": { "d": "pwriKEK", "c": "S/MIME Algorithms" }, +"1.2.840.113549.1.9.16.3.10": { "d": "ssDH", "c": "S/MIME Algorithms" }, +"1.2.840.113549.1.9.16.3.11": { "d": "hmacWith3DESwrap", "c": "S/MIME Algorithms" }, +"1.2.840.113549.1.9.16.3.12": { "d": "hmacWithAESwrap", "c": "S/MIME Algorithms" }, +"1.2.840.113549.1.9.16.3.13": { "d": "md5XorExperiment", "c": "S/MIME Algorithms. Experimental", "w": true }, +"1.2.840.113549.1.9.16.3.14": { "d": "rsaKEM", "c": "S/MIME Algorithms" }, +"1.2.840.113549.1.9.16.3.15": { "d": "authEnc128", "c": "S/MIME Algorithms" }, +"1.2.840.113549.1.9.16.3.16": { "d": "authEnc256", "c": "S/MIME Algorithms" }, +"1.2.840.113549.1.9.16.3.19": { "d": "ecdhHKDF-SHA256", "c": "S/MIME Algorithms" }, +"1.2.840.113549.1.9.16.3.20": { "d": "ecdhHKDF-SHA384", "c": "S/MIME Algorithms" }, +"1.2.840.113549.1.9.16.3.21": { "d": "ecdhHKDF-SHA512", "c": "S/MIME Algorithms" }, +"1.2.840.113549.1.9.16.4.1": { "d": "certDist-ldap", "c": "S/MIME Certificate Distribution" }, +"1.2.840.113549.1.9.16.5.1": { "d": "sigPolicyQualifier-spuri x", "c": "S/MIME Signature Policy Qualifiers" }, +"1.2.840.113549.1.9.16.5.2": { "d": "sigPolicyQualifier-spUserNotice", "c": "S/MIME Signature Policy Qualifiers" }, +"1.2.840.113549.1.9.16.6.1": { "d": "proofOfOrigin", "c": "S/MIME Commitment Type Identifiers" }, +"1.2.840.113549.1.9.16.6.2": { "d": "proofOfReceipt", "c": "S/MIME Commitment Type Identifiers" }, +"1.2.840.113549.1.9.16.6.3": { "d": "proofOfDelivery", "c": "S/MIME Commitment Type Identifiers" }, +"1.2.840.113549.1.9.16.6.4": { "d": "proofOfSender", "c": "S/MIME Commitment Type Identifiers" }, +"1.2.840.113549.1.9.16.6.5": { "d": "proofOfApproval", "c": "S/MIME Commitment Type Identifiers" }, +"1.2.840.113549.1.9.16.6.6": { "d": "proofOfCreation", "c": "S/MIME Commitment Type Identifiers" }, +"1.2.840.113549.1.9.16.8.1": { "d": "glUseKEK", "c": "S/MIME Symmetric Key Distribution Attributes" }, +"1.2.840.113549.1.9.16.8.2": { "d": "glDelete", "c": "S/MIME Symmetric Key Distribution Attributes" }, +"1.2.840.113549.1.9.16.8.3": { "d": "glAddMember", "c": "S/MIME Symmetric Key Distribution Attributes" }, +"1.2.840.113549.1.9.16.8.4": { "d": "glDeleteMember", "c": "S/MIME Symmetric Key Distribution Attributes" }, +"1.2.840.113549.1.9.16.8.5": { "d": "glRekey", "c": "S/MIME Symmetric Key Distribution Attributes" }, +"1.2.840.113549.1.9.16.8.6": { "d": "glAddOwner", "c": "S/MIME Symmetric Key Distribution Attributes" }, +"1.2.840.113549.1.9.16.8.7": { "d": "glRemoveOwner", "c": "S/MIME Symmetric Key Distribution Attributes" }, +"1.2.840.113549.1.9.16.8.8": { "d": "glkCompromise", "c": "S/MIME Symmetric Key Distribution Attributes" }, +"1.2.840.113549.1.9.16.8.9": { "d": "glkRefresh", "c": "S/MIME Symmetric Key Distribution Attributes" }, +"1.2.840.113549.1.9.16.8.10": { "d": "glFailInfo", "c": "S/MIME Symmetric Key Distribution Attributes. Obsolete", "w": true }, +"1.2.840.113549.1.9.16.8.11": { "d": "glaQueryRequest", "c": "S/MIME Symmetric Key Distribution Attributes" }, +"1.2.840.113549.1.9.16.8.12": { "d": "glaQueryResponse", "c": "S/MIME Symmetric Key Distribution Attributes" }, +"1.2.840.113549.1.9.16.8.13": { "d": "glProvideCert", "c": "S/MIME Symmetric Key Distribution Attributes" }, +"1.2.840.113549.1.9.16.8.14": { "d": "glUpdateCert", "c": "S/MIME Symmetric Key Distribution Attributes" }, +"1.2.840.113549.1.9.16.8.15": { "d": "glKey", "c": "S/MIME Symmetric Key Distribution Attributes" }, +"1.2.840.113549.1.9.16.9": { "d": "signatureTypeIdentifier", "c": "S/MIME" }, +"1.2.840.113549.1.9.16.9.1": { "d": "originatorSig", "c": "S/MIME Signature Type Identifier" }, +"1.2.840.113549.1.9.16.9.2": { "d": "domainSig", "c": "S/MIME Signature Type Identifier" }, +"1.2.840.113549.1.9.16.9.3": { "d": "additionalAttributesSig", "c": "S/MIME Signature Type Identifier" }, +"1.2.840.113549.1.9.16.9.4": { "d": "reviewSig", "c": "S/MIME Signature Type Identifier" }, +"1.2.840.113549.1.9.16.11": { "d": "capabilities", "c": "S/MIME" }, +"1.2.840.113549.1.9.16.11.1": { "d": "preferBinaryInside", "c": "S/MIME Capability" }, +"1.2.840.113549.1.9.20": { "d": "friendlyName (for PKCS #12)", "c": "PKCS #9 via PKCS #12" }, +"1.2.840.113549.1.9.21": { "d": "localKeyID (for PKCS #12)", "c": "PKCS #9 via PKCS #12" }, +"1.2.840.113549.1.9.22": { "d": "certTypes (for PKCS #12)", "c": "PKCS #9 via PKCS #12" }, +"1.2.840.113549.1.9.22.1": { "d": "x509Certificate (for PKCS #12)", "c": "PKCS #9 via PKCS #12" }, +"1.2.840.113549.1.9.22.2": { "d": "sdsiCertificate (for PKCS #12)", "c": "PKCS #9 via PKCS #12" }, +"1.2.840.113549.1.9.23": { "d": "crlTypes (for PKCS #12)", "c": "PKCS #9 via PKCS #12" }, +"1.2.840.113549.1.9.23.1": { "d": "x509Crl (for PKCS #12)", "c": "PKCS #9 via PKCS #12" }, +"1.2.840.113549.1.9.24": { "d": "pkcs9objectClass", "c": "PKCS #9/RFC 2985" }, +"1.2.840.113549.1.9.25": { "d": "pkcs9attributes", "c": "PKCS #9/RFC 2985" }, +"1.2.840.113549.1.9.25.1": { "d": "pkcs15Token", "c": "PKCS #9/RFC 2985 attribute" }, +"1.2.840.113549.1.9.25.2": { "d": "encryptedPrivateKeyInfo", "c": "PKCS #9/RFC 2985 attribute" }, +"1.2.840.113549.1.9.25.3": { "d": "randomNonce", "c": "PKCS #9/RFC 2985 attribute" }, +"1.2.840.113549.1.9.25.4": { "d": "sequenceNumber", "c": "PKCS #9/RFC 2985 attribute" }, +"1.2.840.113549.1.9.25.5": { "d": "pkcs7PDU", "c": "PKCS #9/RFC 2985 attribute" }, +"1.2.840.113549.1.9.26": { "d": "pkcs9syntax", "c": "PKCS #9/RFC 2985" }, +"1.2.840.113549.1.9.27": { "d": "pkcs9matchingRules", "c": "PKCS #9/RFC 2985" }, +"1.2.840.113549.1.9.52": { "d": "cmsAlgorithmProtection", "c": "RFC 6211" }, +"1.2.840.113549.1.12": { "d": "pkcs-12", "c": "" }, +"1.2.840.113549.1.12.1": { "d": "pkcs-12-PbeIds", "c": "This OID was formerly assigned as PKCS #12 modeID" }, +"1.2.840.113549.1.12.1.1": { "d": "pbeWithSHAAnd128BitRC4", "c": "PKCS #12 PbeIds. This OID was formerly assigned as pkcs-12-OfflineTransportMode" }, +"1.2.840.113549.1.12.1.2": { "d": "pbeWithSHAAnd40BitRC4", "c": "PKCS #12 PbeIds. This OID was formerly assigned as pkcs-12-OnlineTransportMode" }, +"1.2.840.113549.1.12.1.3": { "d": "pbeWithSHAAnd3-KeyTripleDES-CBC", "c": "PKCS #12 PbeIds" }, +"1.2.840.113549.1.12.1.4": { "d": "pbeWithSHAAnd2-KeyTripleDES-CBC", "c": "PKCS #12 PbeIds" }, +"1.2.840.113549.1.12.1.5": { "d": "pbeWithSHAAnd128BitRC2-CBC", "c": "PKCS #12 PbeIds" }, +"1.2.840.113549.1.12.1.6": { "d": "pbeWithSHAAnd40BitRC2-CBC", "c": "PKCS #12 PbeIds" }, +"1.2.840.113549.1.12.2": { "d": "pkcs-12-ESPVKID", "c": "Deprecated", "w": true }, +"1.2.840.113549.1.12.2.1": { "d": "pkcs-12-PKCS8KeyShrouding", "c": "PKCS #12 ESPVKID. Deprecated, use (1 2 840 113549 1 12 3 5) instead", "w": true }, +"1.2.840.113549.1.12.3": { "d": "pkcs-12-BagIds", "c": "" }, +"1.2.840.113549.1.12.3.1": { "d": "pkcs-12-keyBagId", "c": "PKCS #12 BagIds" }, +"1.2.840.113549.1.12.3.2": { "d": "pkcs-12-certAndCRLBagId", "c": "PKCS #12 BagIds" }, +"1.2.840.113549.1.12.3.3": { "d": "pkcs-12-secretBagId", "c": "PKCS #12 BagIds" }, +"1.2.840.113549.1.12.3.4": { "d": "pkcs-12-safeContentsId", "c": "PKCS #12 BagIds" }, +"1.2.840.113549.1.12.3.5": { "d": "pkcs-12-pkcs-8ShroudedKeyBagId", "c": "PKCS #12 BagIds" }, +"1.2.840.113549.1.12.4": { "d": "pkcs-12-CertBagID", "c": "Deprecated", "w": true }, +"1.2.840.113549.1.12.4.1": { "d": "pkcs-12-X509CertCRLBagID", "c": "PKCS #12 CertBagID. This OID was formerly assigned as pkcs-12-X509CertCRLBag" }, +"1.2.840.113549.1.12.4.2": { "d": "pkcs-12-SDSICertBagID", "c": "PKCS #12 CertBagID. This OID was formerly assigned as pkcs-12-SDSICertBag" }, +"1.2.840.113549.1.12.5": { "d": "pkcs-12-OID", "c": "", "w": true }, +"1.2.840.113549.1.12.5.1": { "d": "pkcs-12-PBEID", "c": "PKCS #12 OID. Deprecated, use the partially compatible (1 2 840 113549 1 12 1) OIDs instead", "w": true }, +"1.2.840.113549.1.12.5.1.1": { "d": "pkcs-12-PBEWithSha1And128BitRC4", "c": "PKCS #12 OID PBEID. Deprecated, use (1 2 840 113549 1 12 1 1) instead", "w": true }, +"1.2.840.113549.1.12.5.1.2": { "d": "pkcs-12-PBEWithSha1And40BitRC4", "c": "PKCS #12 OID PBEID. Deprecated, use (1 2 840 113549 1 12 1 2) instead", "w": true }, +"1.2.840.113549.1.12.5.1.3": { "d": "pkcs-12-PBEWithSha1AndTripleDESCBC", "c": "PKCS #12 OID PBEID. Deprecated, use the incompatible but similar (1 2 840 113549 1 12 1 3) or (1 2 840 113549 1 12 1 4) instead", "w": true }, +"1.2.840.113549.1.12.5.1.4": { "d": "pkcs-12-PBEWithSha1And128BitRC2CBC", "c": "PKCS #12 OID PBEID. Deprecated, use (1 2 840 113549 1 12 1 5) instead", "w": true }, +"1.2.840.113549.1.12.5.1.5": { "d": "pkcs-12-PBEWithSha1And40BitRC2CBC", "c": "PKCS #12 OID PBEID. Deprecated, use (1 2 840 113549 1 12 1 6) instead", "w": true }, +"1.2.840.113549.1.12.5.1.6": { "d": "pkcs-12-PBEWithSha1AndRC4", "c": "PKCS #12 OID PBEID. Deprecated, use the incompatible but similar (1 2 840 113549 1 12 1 1) or (1 2 840 113549 1 12 1 2) instead", "w": true }, +"1.2.840.113549.1.12.5.1.7": { "d": "pkcs-12-PBEWithSha1AndRC2CBC", "c": "PKCS #12 OID PBEID. Deprecated, use the incompatible but similar (1 2 840 113549 1 12 1 5) or (1 2 840 113549 1 12 1 6) instead", "w": true }, +"1.2.840.113549.1.12.5.2": { "d": "pkcs-12-EnvelopingID", "c": "PKCS #12 OID. Deprecated, use the conventional PKCS #1 OIDs instead" }, +"1.2.840.113549.1.12.5.2.1": { "d": "pkcs-12-RSAEncryptionWith128BitRC4", "c": "PKCS #12 OID EnvelopingID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": true }, +"1.2.840.113549.1.12.5.2.2": { "d": "pkcs-12-RSAEncryptionWith40BitRC4", "c": "PKCS #12 OID EnvelopingID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": true }, +"1.2.840.113549.1.12.5.2.3": { "d": "pkcs-12-RSAEncryptionWithTripleDES", "c": "PKCS #12 OID EnvelopingID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": true }, +"1.2.840.113549.1.12.5.3": { "d": "pkcs-12-SignatureID", "c": "PKCS #12 OID EnvelopingID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": true }, +"1.2.840.113549.1.12.5.3.1": { "d": "pkcs-12-RSASignatureWithSHA1Digest", "c": "PKCS #12 OID SignatureID. Deprecated, use the conventional PKCS #1 OIDs instead", "w": true }, +"1.2.840.113549.1.12.10": { "d": "pkcs-12Version1", "c": "" }, +"1.2.840.113549.1.12.10.1": { "d": "pkcs-12BadIds", "c": "" }, +"1.2.840.113549.1.12.10.1.1": { "d": "pkcs-12-keyBag", "c": "PKCS #12 BagIds" }, +"1.2.840.113549.1.12.10.1.2": { "d": "pkcs-12-pkcs-8ShroudedKeyBag", "c": "PKCS #12 BagIds" }, +"1.2.840.113549.1.12.10.1.3": { "d": "pkcs-12-certBag", "c": "PKCS #12 BagIds" }, +"1.2.840.113549.1.12.10.1.4": { "d": "pkcs-12-crlBag", "c": "PKCS #12 BagIds" }, +"1.2.840.113549.1.12.10.1.5": { "d": "pkcs-12-secretBag", "c": "PKCS #12 BagIds" }, +"1.2.840.113549.1.12.10.1.6": { "d": "pkcs-12-safeContentsBag", "c": "PKCS #12 BagIds" }, +"1.2.840.113549.1.15.1": { "d": "pkcs15modules", "c": "PKCS #15" }, +"1.2.840.113549.1.15.2": { "d": "pkcs15attributes", "c": "PKCS #15" }, +"1.2.840.113549.1.15.3": { "d": "pkcs15contentType", "c": "PKCS #15" }, +"1.2.840.113549.1.15.3.1": { "d": "pkcs15content", "c": "PKCS #15 content type" }, +"1.2.840.113549.2": { "d": "digestAlgorithm", "c": "" }, +"1.2.840.113549.2.2": { "d": "md2", "c": "RSADSI digestAlgorithm" }, +"1.2.840.113549.2.4": { "d": "md4", "c": "RSADSI digestAlgorithm" }, +"1.2.840.113549.2.5": { "d": "md5", "c": "RSADSI digestAlgorithm" }, +"1.2.840.113549.2.7": { "d": "hmacWithSHA1", "c": "RSADSI digestAlgorithm" }, +"1.2.840.113549.2.8": { "d": "hmacWithSHA224", "c": "RSADSI digestAlgorithm" }, +"1.2.840.113549.2.9": { "d": "hmacWithSHA256", "c": "RSADSI digestAlgorithm" }, +"1.2.840.113549.2.10": { "d": "hmacWithSHA384", "c": "RSADSI digestAlgorithm" }, +"1.2.840.113549.2.11": { "d": "hmacWithSHA512", "c": "RSADSI digestAlgorithm" }, +"1.2.840.113549.3": { "d": "encryptionAlgorithm", "c": "" }, +"1.2.840.113549.3.2": { "d": "rc2CBC", "c": "RSADSI encryptionAlgorithm" }, +"1.2.840.113549.3.3": { "d": "rc2ECB", "c": "RSADSI encryptionAlgorithm" }, +"1.2.840.113549.3.4": { "d": "rc4", "c": "RSADSI encryptionAlgorithm" }, +"1.2.840.113549.3.5": { "d": "rc4WithMAC", "c": "RSADSI encryptionAlgorithm" }, +"1.2.840.113549.3.6": { "d": "desx-CBC", "c": "RSADSI encryptionAlgorithm" }, +"1.2.840.113549.3.7": { "d": "des-EDE3-CBC", "c": "RSADSI encryptionAlgorithm" }, +"1.2.840.113549.3.8": { "d": "rc5CBC", "c": "RSADSI encryptionAlgorithm" }, +"1.2.840.113549.3.9": { "d": "rc5-CBCPad", "c": "RSADSI encryptionAlgorithm" }, +"1.2.840.113549.3.10": { "d": "desCDMF", "c": "RSADSI encryptionAlgorithm. Formerly called CDMFCBCPad" }, +"1.2.840.114021.1.6.1": { "d": "Identrus unknown policyIdentifier", "c": "Identrus" }, +"1.2.840.114021.4.1": { "d": "identrusOCSP", "c": "Identrus" }, +"1.2.840.113556.1.2.241": { "d": "deliveryMechanism", "c": "Microsoft Exchange Server - attribute" }, +"1.2.840.113556.1.2.281": { "d": "ntSecurityDescriptor", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.3.0": { "d": "site-Addressing", "c": "Microsoft Exchange Server - object class" }, +"1.2.840.113556.1.3.13": { "d": "classSchema", "c": "Microsoft Exchange Server - object class" }, +"1.2.840.113556.1.3.14": { "d": "attributeSchema", "c": "Microsoft Exchange Server - object class" }, +"1.2.840.113556.1.3.17": { "d": "mailbox-Agent", "c": "Microsoft Exchange Server - object class" }, +"1.2.840.113556.1.3.22": { "d": "mailbox", "c": "Microsoft Exchange Server - object class" }, +"1.2.840.113556.1.3.23": { "d": "container", "c": "Microsoft Exchange Server - object class" }, +"1.2.840.113556.1.3.46": { "d": "mailRecipient", "c": "Microsoft Exchange Server - object class" }, +"1.2.840.113556.1.4.145": { "d": "revision", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1327": { "d": "pKIDefaultKeySpec", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1328": { "d": "pKIKeyUsage", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1329": { "d": "pKIMaxIssuingDepth", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1330": { "d": "pKICriticalExtensions", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1331": { "d": "pKIExpirationPeriod", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1332": { "d": "pKIOverlapPeriod", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1333": { "d": "pKIExtendedKeyUsage", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1334": { "d": "pKIDefaultCSPs", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1335": { "d": "pKIEnrollmentAccess", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1429": { "d": "msPKI-RA-Signature", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1430": { "d": "msPKI-Enrollment-Flag", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1431": { "d": "msPKI-Private-Key-Flag", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1432": { "d": "msPKI-Certificate-Name-Flag", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1433": { "d": "msPKI-Minimal-Key-Size", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1434": { "d": "msPKI-Template-Schema-Version", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1435": { "d": "msPKI-Template-Minor-Revision", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1436": { "d": "msPKI-Cert-Template-OID", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1437": { "d": "msPKI-Supersede-Templates", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1438": { "d": "msPKI-RA-Policies", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1439": { "d": "msPKI-Certificate-Policy", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1674": { "d": "msPKI-Certificate-Application-Policy", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.1.4.1675": { "d": "msPKI-RA-Application-Policies", "c": "Microsoft Cert Template - attribute" }, +"1.2.840.113556.4.3": { "d": "microsoftExcel", "c": "Microsoft" }, +"1.2.840.113556.4.4": { "d": "titledWithOID", "c": "Microsoft" }, +"1.2.840.113556.4.5": { "d": "microsoftPowerPoint", "c": "Microsoft" }, +"1.2.840.113583.1": { "d": "adobeAcrobat", "c": "Adobe Acrobat" }, +"1.2.840.113583.1.1": { "d": "acrobatSecurity", "c": "Adobe Acrobat security" }, +"1.2.840.113583.1.1.1": { "d": "pdfPassword", "c": "Adobe Acrobat security" }, +"1.2.840.113583.1.1.2": { "d": "pdfDefaultSigningCredential", "c": "Adobe Acrobat security" }, +"1.2.840.113583.1.1.3": { "d": "pdfDefaultEncryptionCredential", "c": "Adobe Acrobat security" }, +"1.2.840.113583.1.1.4": { "d": "pdfPasswordTimeout", "c": "Adobe Acrobat security" }, +"1.2.840.113583.1.1.5": { "d": "pdfAuthenticDocumentsTrust", "c": "Adobe Acrobat security" }, +"1.2.840.113583.1.1.6": { "d": "pdfDynamicContentTrust", "c": "Adobe Acrobat security", "w": true }, +"1.2.840.113583.1.1.7": { "d": "pdfUbiquityTrust", "c": "Adobe Acrobat security" }, +"1.2.840.113583.1.1.8": { "d": "pdfRevocationInfoArchival", "c": "Adobe Acrobat security" }, +"1.2.840.113583.1.1.9": { "d": "pdfX509Extension", "c": "Adobe Acrobat security" }, +"1.2.840.113583.1.1.9.1": { "d": "pdfTimeStamp", "c": "Adobe Acrobat security" }, +"1.2.840.113583.1.1.9.2": { "d": "pdfArchiveRevInfo", "c": "Adobe Acrobat security" }, +"1.2.840.113583.1.1.10": { "d": "pdfPPLKLiteCredential", "c": "Adobe Acrobat security" }, +"1.2.840.113583.1.2": { "d": "acrobatCPS", "c": "Adobe Acrobat CPS" }, +"1.2.840.113583.1.2.1": { "d": "pdfAuthenticDocumentsCPS", "c": "Adobe Acrobat CPS" }, +"1.2.840.113583.1.2.2": { "d": "pdfTestCPS", "c": "Adobe Acrobat CPS" }, +"1.2.840.113583.1.2.3": { "d": "pdfUbiquityCPS", "c": "Adobe Acrobat CPS" }, +"1.2.840.113583.1.2.4": { "d": "pdfAdhocCPS", "c": "Adobe Acrobat CPS" }, +"1.2.840.113583.1.7": { "d": "acrobatUbiquity", "c": "Adobe Acrobat ubiquity" }, +"1.2.840.113583.1.7.1": { "d": "pdfUbiquitySubRights", "c": "Adobe Acrobat ubiquity" }, +"1.2.840.113583.1.9": { "d": "acrobatExtension", "c": "Adobe Acrobat X.509 extension" }, +"1.2.840.113628.114.1.7": { "d": "adobePKCS7", "c": "Adobe" }, +"1.2.840.113635.100": { "d": "appleDataSecurity", "c": "Apple" }, +"1.2.840.113635.100.1": { "d": "appleTrustPolicy", "c": "Apple" }, +"1.2.840.113635.100.1.1": { "d": "appleISignTP", "c": "Apple trust policy" }, +"1.2.840.113635.100.1.2": { "d": "appleX509Basic", "c": "Apple trust policy" }, +"1.2.840.113635.100.1.3": { "d": "appleSSLPolicy", "c": "Apple trust policy" }, +"1.2.840.113635.100.1.4": { "d": "appleLocalCertGenPolicy", "c": "Apple trust policy" }, +"1.2.840.113635.100.1.5": { "d": "appleCSRGenPolicy", "c": "Apple trust policy" }, +"1.2.840.113635.100.1.6": { "d": "appleCRLPolicy", "c": "Apple trust policy" }, +"1.2.840.113635.100.1.7": { "d": "appleOCSPPolicy", "c": "Apple trust policy" }, +"1.2.840.113635.100.1.8": { "d": "appleSMIMEPolicy", "c": "Apple trust policy" }, +"1.2.840.113635.100.1.9": { "d": "appleEAPPolicy", "c": "Apple trust policy" }, +"1.2.840.113635.100.1.10": { "d": "appleSWUpdateSigningPolicy", "c": "Apple trust policy" }, +"1.2.840.113635.100.1.11": { "d": "appleIPSecPolicy", "c": "Apple trust policy" }, +"1.2.840.113635.100.1.12": { "d": "appleIChatPolicy", "c": "Apple trust policy" }, +"1.2.840.113635.100.1.13": { "d": "appleResourceSignPolicy", "c": "Apple trust policy" }, +"1.2.840.113635.100.1.14": { "d": "applePKINITClientPolicy", "c": "Apple trust policy" }, +"1.2.840.113635.100.1.15": { "d": "applePKINITServerPolicy", "c": "Apple trust policy" }, +"1.2.840.113635.100.1.16": { "d": "appleCodeSigningPolicy", "c": "Apple trust policy" }, +"1.2.840.113635.100.1.17": { "d": "applePackageSigningPolicy", "c": "Apple trust policy" }, +"1.2.840.113635.100.2": { "d": "appleSecurityAlgorithm", "c": "Apple" }, +"1.2.840.113635.100.2.1": { "d": "appleFEE", "c": "Apple security algorithm" }, +"1.2.840.113635.100.2.2": { "d": "appleASC", "c": "Apple security algorithm" }, +"1.2.840.113635.100.2.3": { "d": "appleFEE_MD5", "c": "Apple security algorithm" }, +"1.2.840.113635.100.2.4": { "d": "appleFEE_SHA1", "c": "Apple security algorithm" }, +"1.2.840.113635.100.2.5": { "d": "appleFEED", "c": "Apple security algorithm" }, +"1.2.840.113635.100.2.6": { "d": "appleFEEDEXP", "c": "Apple security algorithm" }, +"1.2.840.113635.100.2.7": { "d": "appleECDSA", "c": "Apple security algorithm" }, +"1.2.840.113635.100.3": { "d": "appleDotMacCertificate", "c": "Apple" }, +"1.2.840.113635.100.3.1": { "d": "appleDotMacCertificateRequest", "c": "Apple dotMac certificate" }, +"1.2.840.113635.100.3.2": { "d": "appleDotMacCertificateExtension", "c": "Apple dotMac certificate" }, +"1.2.840.113635.100.3.3": { "d": "appleDotMacCertificateRequestValues", "c": "Apple dotMac certificate" }, +"1.2.840.113635.100.4": { "d": "appleExtendedKeyUsage", "c": "Apple" }, +"1.2.840.113635.100.4.1": { "d": "appleCodeSigning", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.1.1": { "d": "appleCodeSigningDevelopment", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.1.2": { "d": "appleSoftwareUpdateSigning", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.1.3": { "d": "appleCodeSigningThirdParty", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.1.4": { "d": "appleResourceSigning", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.2": { "d": "appleIChatSigning", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.3": { "d": "appleIChatEncryption", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.4": { "d": "appleSystemIdentity", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.5": { "d": "appleCryptoEnv", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.5.1": { "d": "appleCryptoProductionEnv", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.5.2": { "d": "appleCryptoMaintenanceEnv", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.5.3": { "d": "appleCryptoTestEnv", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.5.4": { "d": "appleCryptoDevelopmentEnv", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.6": { "d": "appleCryptoQoS", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.6.1": { "d": "appleCryptoTier0QoS", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.6.2": { "d": "appleCryptoTier1QoS", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.6.3": { "d": "appleCryptoTier2QoS", "c": "Apple extended key usage" }, +"1.2.840.113635.100.4.6.4": { "d": "appleCryptoTier3QoS", "c": "Apple extended key usage" }, +"1.2.840.113635.100.5": { "d": "appleCertificatePolicies", "c": "Apple" }, +"1.2.840.113635.100.5.1": { "d": "appleCertificatePolicyID", "c": "Apple" }, +"1.2.840.113635.100.5.2": { "d": "appleDotMacCertificatePolicyID", "c": "Apple" }, +"1.2.840.113635.100.5.3": { "d": "appleADCCertificatePolicyID", "c": "Apple" }, +"1.2.840.113635.100.6": { "d": "appleCertificateExtensions", "c": "Apple" }, +"1.2.840.113635.100.6.1": { "d": "appleCertificateExtensionCodeSigning", "c": "Apple certificate extension" }, +"1.2.840.113635.100.6.1.1": { "d": "appleCertificateExtensionAppleSigning", "c": "Apple certificate extension" }, +"1.2.840.113635.100.6.1.2": { "d": "appleCertificateExtensionADCDeveloperSigning", "c": "Apple certificate extension" }, +"1.2.840.113635.100.6.1.3": { "d": "appleCertificateExtensionADCAppleSigning", "c": "Apple certificate extension" }, +"1.3.6.1.4.1.311.2.1.4": { "d": "spcIndirectDataContext", "c": "Microsoft code signing" }, +"1.3.6.1.4.1.311.2.1.10": { "d": "spcAgencyInfo", "c": "Microsoft code signing. Also known as policyLink" }, +"1.3.6.1.4.1.311.2.1.11": { "d": "spcStatementType", "c": "Microsoft code signing" }, +"1.3.6.1.4.1.311.2.1.12": { "d": "spcSpOpusInfo", "c": "Microsoft code signing" }, +"1.3.6.1.4.1.311.2.1.14": { "d": "certReqExtensions", "c": "Microsoft" }, +"1.3.6.1.4.1.311.2.1.15": { "d": "spcPEImageData", "c": "Microsoft code signing" }, +"1.3.6.1.4.1.311.2.1.18": { "d": "spcRawFileData", "c": "Microsoft code signing" }, +"1.3.6.1.4.1.311.2.1.19": { "d": "spcStructuredStorageData", "c": "Microsoft code signing" }, +"1.3.6.1.4.1.311.2.1.20": { "d": "spcJavaClassData (type 1)", "c": "Microsoft code signing. Formerly \"link extension\" aka \"glue extension\"" }, +"1.3.6.1.4.1.311.2.1.21": { "d": "individualCodeSigning", "c": "Microsoft" }, +"1.3.6.1.4.1.311.2.1.22": { "d": "commercialCodeSigning", "c": "Microsoft" }, +"1.3.6.1.4.1.311.2.1.25": { "d": "spcLink (type 2)", "c": "Microsoft code signing. Also known as \"glue extension\"" }, +"1.3.6.1.4.1.311.2.1.26": { "d": "spcMinimalCriteriaInfo", "c": "Microsoft code signing" }, +"1.3.6.1.4.1.311.2.1.27": { "d": "spcFinancialCriteriaInfo", "c": "Microsoft code signing" }, +"1.3.6.1.4.1.311.2.1.28": { "d": "spcLink (type 3)", "c": "Microsoft code signing. Also known as \"glue extension\"" }, +"1.3.6.1.4.1.311.2.1.29": { "d": "spcHashInfoObjID", "c": "Microsoft code signing" }, +"1.3.6.1.4.1.311.2.1.30": { "d": "spcSipInfoObjID", "c": "Microsoft code signing" }, +"1.3.6.1.4.1.311.2.2": { "d": "ctl", "c": "Microsoft CTL" }, +"1.3.6.1.4.1.311.2.2.1": { "d": "ctlTrustedCodesigningCAList", "c": "Microsoft CTL" }, +"1.3.6.1.4.1.311.2.2.2": { "d": "ctlTrustedClientAuthCAList", "c": "Microsoft CTL" }, +"1.3.6.1.4.1.311.2.2.3": { "d": "ctlTrustedServerAuthCAList", "c": "Microsoft CTL" }, +"1.3.6.1.4.1.311.3.2.1": { "d": "timestampRequest", "c": "Microsoft code signing" }, +"1.3.6.1.4.1.311.10.1": { "d": "certTrustList", "c": "Microsoft contentType" }, +"1.3.6.1.4.1.311.10.1.1": { "d": "sortedCtl", "c": "Microsoft contentType" }, +"1.3.6.1.4.1.311.10.2": { "d": "nextUpdateLocation", "c": "Microsoft" }, +"1.3.6.1.4.1.311.10.3.1": { "d": "certTrustListSigning", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.3.2": { "d": "timeStampSigning", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.3.3": { "d": "serverGatedCrypto", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.3.3.1": { "d": "serialized", "c": "Microsoft" }, +"1.3.6.1.4.1.311.10.3.4": { "d": "encryptedFileSystem", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.3.5": { "d": "whqlCrypto", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.3.6": { "d": "nt5Crypto", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.3.7": { "d": "oemWHQLCrypto", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.3.8": { "d": "embeddedNTCrypto", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.3.9": { "d": "rootListSigner", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.3.10": { "d": "qualifiedSubordination", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.3.11": { "d": "keyRecovery", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.3.12": { "d": "documentSigning", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.3.13": { "d": "lifetimeSigning", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.3.14": { "d": "mobileDeviceSoftware", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.3.15": { "d": "smartDisplay", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.3.16": { "d": "cspSignature", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.3.4.1": { "d": "efsRecovery", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.4.1": { "d": "yesnoTrustAttr", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.10.5.1": { "d": "drm", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.5.2": { "d": "drmIndividualization", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.6.1": { "d": "licenses", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.6.2": { "d": "licenseServer", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.10.7.1": { "d": "keyidRdn", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.10.8.1": { "d": "removeCertificate", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.10.9.1": { "d": "crossCertDistPoints", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.10.10.1": { "d": "cmcAddAttributes", "c": "Microsoft" }, +"1.3.6.1.4.1.311.10.11": { "d": "certPropIdPrefix", "c": "Microsoft" }, +"1.3.6.1.4.1.311.10.11.4": { "d": "certMd5HashPropId", "c": "Microsoft" }, +"1.3.6.1.4.1.311.10.11.20": { "d": "certKeyIdentifierPropId", "c": "Microsoft" }, +"1.3.6.1.4.1.311.10.11.28": { "d": "certIssuerSerialNumberMd5HashPropId", "c": "Microsoft" }, +"1.3.6.1.4.1.311.10.11.29": { "d": "certSubjectNameMd5HashPropId", "c": "Microsoft" }, +"1.3.6.1.4.1.311.10.12.1": { "d": "anyApplicationPolicy", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.12": { "d": "catalog", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.12.1.1": { "d": "catalogList", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.12.1.2": { "d": "catalogListMember", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.12.2.1": { "d": "catalogNameValueObjID", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.12.2.2": { "d": "catalogMemberInfoObjID", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.13.1": { "d": "renewalCertificate", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.13.2.1": { "d": "enrolmentNameValuePair", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.13.2.2": { "d": "enrolmentCSP", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.13.2.3": { "d": "osVersion", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.16.4": { "d": "microsoftRecipientInfo", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.17.1": { "d": "pkcs12KeyProviderNameAttr", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.17.2": { "d": "localMachineKeyset", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.17.3": { "d": "pkcs12ExtendedAttributes", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.20.1": { "d": "autoEnrollCtlUsage", "c": "Microsoft" }, +"1.3.6.1.4.1.311.20.2": { "d": "enrollCerttypeExtension", "c": "Microsoft CAPICOM certificate template, V1" }, +"1.3.6.1.4.1.311.20.2.1": { "d": "enrollmentAgent", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.20.2.2": { "d": "smartcardLogon", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.20.2.3": { "d": "universalPrincipalName", "c": "Microsoft UPN" }, +"1.3.6.1.4.1.311.20.3": { "d": "certManifold", "c": "Microsoft" }, +"1.3.6.1.4.1.311.21.1": { "d": "cAKeyCertIndexPair", "c": "Microsoft attribute. Also known as certsrvCaVersion" }, +"1.3.6.1.4.1.311.21.2": { "d": "certSrvPreviousCertHash", "c": "Microsoft" }, +"1.3.6.1.4.1.311.21.3": { "d": "crlVirtualBase", "c": "Microsoft" }, +"1.3.6.1.4.1.311.21.4": { "d": "crlNextPublish", "c": "Microsoft" }, +"1.3.6.1.4.1.311.21.5": { "d": "caExchange", "c": "Microsoft extended key usage", "w": true }, +"1.3.6.1.4.1.311.21.6": { "d": "keyRecovery", "c": "Microsoft extended key usage", "w": true }, +"1.3.6.1.4.1.311.21.7": { "d": "certificateTemplate", "c": "Microsoft CAPICOM certificate template, V2" }, +"1.3.6.1.4.1.311.21.9": { "d": "rdnDummySigner", "c": "Microsoft" }, +"1.3.6.1.4.1.311.21.10": { "d": "applicationCertPolicies", "c": "Microsoft" }, +"1.3.6.1.4.1.311.21.11": { "d": "applicationPolicyMappings", "c": "Microsoft" }, +"1.3.6.1.4.1.311.21.12": { "d": "applicationPolicyConstraints", "c": "Microsoft" }, +"1.3.6.1.4.1.311.21.13": { "d": "archivedKey", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.21.14": { "d": "crlSelfCDP", "c": "Microsoft" }, +"1.3.6.1.4.1.311.21.15": { "d": "requireCertChainPolicy", "c": "Microsoft" }, +"1.3.6.1.4.1.311.21.16": { "d": "archivedKeyCertHash", "c": "Microsoft" }, +"1.3.6.1.4.1.311.21.17": { "d": "issuedCertHash", "c": "Microsoft" }, +"1.3.6.1.4.1.311.21.19": { "d": "dsEmailReplication", "c": "Microsoft" }, +"1.3.6.1.4.1.311.21.20": { "d": "requestClientInfo", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.21.21": { "d": "encryptedKeyHash", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.21.22": { "d": "certsrvCrossCaVersion", "c": "Microsoft" }, +"1.3.6.1.4.1.311.25.1": { "d": "ntdsReplication", "c": "Microsoft" }, +"1.3.6.1.4.1.311.31.1": { "d": "productUpdate", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.47.1.1": { "d": "systemHealth", "c": "Microsoft extended key usage" }, +"1.3.6.1.4.1.311.47.1.3": { "d": "systemHealthLoophole", "c": "Microsoft extended key usage" }, +"1.3.6.1.4.1.311.60.1.1": { "d": "rootProgramFlags", "c": "Microsoft policy attribute" }, +"1.3.6.1.4.1.311.61.1.1": { "d": "kernelModeCodeSigning", "c": "Microsoft enhanced key usage" }, +"1.3.6.1.4.1.311.60.2.1.1": { "d": "jurisdictionOfIncorporationL", "c": "Microsoft (???)" }, +"1.3.6.1.4.1.311.60.2.1.2": { "d": "jurisdictionOfIncorporationSP", "c": "Microsoft (???)" }, +"1.3.6.1.4.1.311.60.2.1.3": { "d": "jurisdictionOfIncorporationC", "c": "Microsoft (???)" }, +"1.3.6.1.4.1.311.88": { "d": "capiCom", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.88.1": { "d": "capiComVersion", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.88.2": { "d": "capiComAttribute", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.88.2.1": { "d": "capiComDocumentName", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.88.2.2": { "d": "capiComDocumentDescription", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.88.3": { "d": "capiComEncryptedData", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.311.88.3.1": { "d": "capiComEncryptedContent", "c": "Microsoft attribute" }, +"1.3.6.1.4.1.188.7.1.1": { "d": "ascom", "c": "Ascom Systech" }, +"1.3.6.1.4.1.188.7.1.1.1": { "d": "ideaECB", "c": "Ascom Systech" }, +"1.3.6.1.4.1.188.7.1.1.2": { "d": "ideaCBC", "c": "Ascom Systech" }, +"1.3.6.1.4.1.188.7.1.1.3": { "d": "ideaCFB", "c": "Ascom Systech" }, +"1.3.6.1.4.1.188.7.1.1.4": { "d": "ideaOFB", "c": "Ascom Systech" }, +"1.3.6.1.4.1.2428.10.1.1": { "d": "UNINETT policyIdentifier", "c": "UNINETT PCA" }, +"1.3.6.1.4.1.2712.10": { "d": "ICE-TEL policyIdentifier", "c": "ICE-TEL CA" }, +"1.3.6.1.4.1.2786.1.1.1": { "d": "ICE-TEL Italian policyIdentifier", "c": "ICE-TEL CA policy" }, +"1.3.6.1.4.1.3029.1.1.1": { "d": "blowfishECB", "c": "cryptlib encryption algorithm" }, +"1.3.6.1.4.1.3029.1.1.2": { "d": "blowfishCBC", "c": "cryptlib encryption algorithm" }, +"1.3.6.1.4.1.3029.1.1.3": { "d": "blowfishCFB", "c": "cryptlib encryption algorithm" }, +"1.3.6.1.4.1.3029.1.1.4": { "d": "blowfishOFB", "c": "cryptlib encryption algorithm" }, +"1.3.6.1.4.1.3029.1.2.1": { "d": "elgamal", "c": "cryptlib public-key algorithm" }, +"1.3.6.1.4.1.3029.1.2.1.1": { "d": "elgamalWithSHA-1", "c": "cryptlib public-key algorithm" }, +"1.3.6.1.4.1.3029.1.2.1.2": { "d": "elgamalWithRIPEMD-160", "c": "cryptlib public-key algorithm" }, +"1.3.6.1.4.1.3029.3.1.1": { "d": "cryptlibPresenceCheck", "c": "cryptlib attribute type" }, +"1.3.6.1.4.1.3029.3.1.2": { "d": "pkiBoot", "c": "cryptlib attribute type" }, +"1.3.6.1.4.1.3029.3.1.4": { "d": "crlExtReason", "c": "cryptlib attribute type" }, +"1.3.6.1.4.1.3029.3.1.5": { "d": "keyFeatures", "c": "cryptlib attribute type" }, +"1.3.6.1.4.1.3029.4.1": { "d": "cryptlibContent", "c": "cryptlib" }, +"1.3.6.1.4.1.3029.4.1.1": { "d": "cryptlibConfigData", "c": "cryptlib content type" }, +"1.3.6.1.4.1.3029.4.1.2": { "d": "cryptlibUserIndex", "c": "cryptlib content type" }, +"1.3.6.1.4.1.3029.4.1.3": { "d": "cryptlibUserInfo", "c": "cryptlib content type" }, +"1.3.6.1.4.1.3029.4.1.4": { "d": "rtcsRequest", "c": "cryptlib content type" }, +"1.3.6.1.4.1.3029.4.1.5": { "d": "rtcsResponse", "c": "cryptlib content type" }, +"1.3.6.1.4.1.3029.4.1.6": { "d": "rtcsResponseExt", "c": "cryptlib content type" }, +"1.3.6.1.4.1.3029.42.11172.1": { "d": "mpeg-1", "c": "cryptlib special MPEG-of-cat OID" }, +"1.3.6.1.4.1.3029.54.11940.54": { "d": "TSA policy \"Anything that arrives, we sign\"", "c": "cryptlib TSA policy" }, +"1.3.6.1.4.1.3029.88.89.90.90.89": { "d": "xYZZY policyIdentifier", "c": "cryptlib certificate policy" }, +"1.3.6.1.4.1.3401.8.1.1": { "d": "pgpExtension", "c": "PGP key information" }, +"1.3.6.1.4.1.3576.7": { "d": "eciaAscX12Edi", "c": "TMN EDI for Interactive Agents" }, +"1.3.6.1.4.1.3576.7.1": { "d": "plainEDImessage", "c": "TMN EDI for Interactive Agents" }, +"1.3.6.1.4.1.3576.7.2": { "d": "signedEDImessage", "c": "TMN EDI for Interactive Agents" }, +"1.3.6.1.4.1.3576.7.5": { "d": "integrityEDImessage", "c": "TMN EDI for Interactive Agents" }, +"1.3.6.1.4.1.3576.7.65": { "d": "iaReceiptMessage", "c": "TMN EDI for Interactive Agents" }, +"1.3.6.1.4.1.3576.7.97": { "d": "iaStatusMessage", "c": "TMN EDI for Interactive Agents" }, +"1.3.6.1.4.1.3576.8": { "d": "eciaEdifact", "c": "TMN EDI for Interactive Agents" }, +"1.3.6.1.4.1.3576.9": { "d": "eciaNonEdi", "c": "TMN EDI for Interactive Agents" }, +"1.3.6.1.4.1.4146": { "d": "Globalsign", "c": "Globalsign" }, +"1.3.6.1.4.1.4146.1": { "d": "globalsignPolicy", "c": "Globalsign" }, +"1.3.6.1.4.1.4146.1.10": { "d": "globalsignDVPolicy", "c": "Globalsign policy" }, +"1.3.6.1.4.1.4146.1.20": { "d": "globalsignOVPolicy", "c": "Globalsign policy" }, +"1.3.6.1.4.1.4146.1.30": { "d": "globalsignTSAPolicy", "c": "Globalsign policy" }, +"1.3.6.1.4.1.4146.1.40": { "d": "globalsignClientCertPolicy", "c": "Globalsign policy" }, +"1.3.6.1.4.1.4146.1.50": { "d": "globalsignCodeSignPolicy", "c": "Globalsign policy" }, +"1.3.6.1.4.1.4146.1.60": { "d": "globalsignRootSignPolicy", "c": "Globalsign policy" }, +"1.3.6.1.4.1.4146.1.70": { "d": "globalsignTrustedRootPolicy", "c": "Globalsign policy" }, +"1.3.6.1.4.1.4146.1.80": { "d": "globalsignEDIClientPolicy", "c": "Globalsign policy" }, +"1.3.6.1.4.1.4146.1.81": { "d": "globalsignEDIServerPolicy", "c": "Globalsign policy" }, +"1.3.6.1.4.1.4146.1.90": { "d": "globalsignTPMRootPolicy", "c": "Globalsign policy" }, +"1.3.6.1.4.1.4146.1.95": { "d": "globalsignOCSPPolicy", "c": "Globalsign policy" }, +"1.3.6.1.4.1.5309.1": { "d": "edelWebPolicy", "c": "EdelWeb policy" }, +"1.3.6.1.4.1.5309.1.2": { "d": "edelWebCustomerPolicy", "c": "EdelWeb policy" }, +"1.3.6.1.4.1.5309.1.2.1": { "d": "edelWebClepsydrePolicy", "c": "EdelWeb policy" }, +"1.3.6.1.4.1.5309.1.2.2": { "d": "edelWebExperimentalTSAPolicy", "c": "EdelWeb policy" }, +"1.3.6.1.4.1.5309.1.2.3": { "d": "edelWebOpenEvidenceTSAPolicy", "c": "EdelWeb policy" }, +"1.3.6.1.4.1.5472": { "d": "timeproof", "c": "enterprise" }, +"1.3.6.1.4.1.5472.1": { "d": "tss", "c": "timeproof" }, +"1.3.6.1.4.1.5472.1.1": { "d": "tss80", "c": "timeproof TSS" }, +"1.3.6.1.4.1.5472.1.2": { "d": "tss380", "c": "timeproof TSS" }, +"1.3.6.1.4.1.5472.1.3": { "d": "tss400", "c": "timeproof TSS" }, +"1.3.6.1.4.1.5770.0.3": { "d": "secondaryPractices", "c": "MEDePass" }, +"1.3.6.1.4.1.5770.0.4": { "d": "physicianIdentifiers", "c": "MEDePass" }, +"1.3.6.1.4.1.6449.1.2.1.3.1": { "d": "comodoPolicy", "c": "Comodo CA" }, +"1.3.6.1.4.1.6449.1.2.2.15": { "d": "wotrustPolicy", "c": "WoTrust (Comodo) CA" }, +"1.3.6.1.4.1.6449.1.3.5.2": { "d": "comodoCertifiedDeliveryService", "c": "Comodo CA" }, +"1.3.6.1.4.1.6449.2.1.1": { "d": "comodoTimestampingPolicy", "c": "Comodo CA" }, +"1.3.6.1.4.1.8301.3.5.1": { "d": "validityModelChain", "c": "TU Darmstadt ValidityModel" }, +"1.3.6.1.4.1.8301.3.5.2": { "d": "validityModelShell", "c": "ValidityModel" }, +"1.3.6.1.4.1.8231.1": { "d": "rolUnicoNacional", "c": "Chilean Government national unique roll number" }, +"1.3.6.1.4.1.11591": { "d": "gnu", "c": "GNU Project (see http://www.gnupg.org/oids.html)" }, +"1.3.6.1.4.1.11591.1": { "d": "gnuRadius", "c": "GNU Radius" }, +"1.3.6.1.4.1.11591.3": { "d": "gnuRadar", "c": "GNU Radar" }, +"1.3.6.1.4.1.11591.12": { "d": "gnuDigestAlgorithm", "c": "GNU digest algorithm" }, +"1.3.6.1.4.1.11591.12.2": { "d": "tiger", "c": "GNU digest algorithm" }, +"1.3.6.1.4.1.11591.13": { "d": "gnuEncryptionAlgorithm", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.13.2": { "d": "serpent", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.13.2.1": { "d": "serpent128_ECB", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.13.2.2": { "d": "serpent128_CBC", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.13.2.3": { "d": "serpent128_OFB", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.13.2.4": { "d": "serpent128_CFB", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.13.2.21": { "d": "serpent192_ECB", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.13.2.22": { "d": "serpent192_CBC", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.13.2.23": { "d": "serpent192_OFB", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.13.2.24": { "d": "serpent192_CFB", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.13.2.41": { "d": "serpent256_ECB", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.13.2.42": { "d": "serpent256_CBC", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.13.2.43": { "d": "serpent256_OFB", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.13.2.44": { "d": "serpent256_CFB", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.15.1": { "d": "curve25519", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.15.2": { "d": "curve448", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.15.3": { "d": "curve25519ph", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.11591.15.4": { "d": "curve448ph", "c": "GNU encryption algorithm" }, +"1.3.6.1.4.1.16334.509.1.1": { "d": "Northrop Grumman extKeyUsage?", "c": "Northrop Grumman extended key usage" }, +"1.3.6.1.4.1.16334.509.2.1": { "d": "ngcClass1", "c": "Northrop Grumman policy" }, +"1.3.6.1.4.1.16334.509.2.2": { "d": "ngcClass2", "c": "Northrop Grumman policy" }, +"1.3.6.1.4.1.16334.509.2.3": { "d": "ngcClass3", "c": "Northrop Grumman policy" }, +"1.3.6.1.4.1.23629.1.4.2.1.1": { "d": "safenetUsageLimit", "c": "SafeNet" }, +"1.3.6.1.4.1.23629.1.4.2.1.2": { "d": "safenetEndDate", "c": "SafeNet" }, +"1.3.6.1.4.1.23629.1.4.2.1.3": { "d": "safenetStartDate", "c": "SafeNet" }, +"1.3.6.1.4.1.23629.1.4.2.1.4": { "d": "safenetAdminCert", "c": "SafeNet" }, +"1.3.6.1.4.1.23629.1.4.2.2.1": { "d": "safenetKeyDigest", "c": "SafeNet" }, +"1.3.6.1.5.5.7": { "d": "pkix", "c": "" }, +"1.3.6.1.5.5.7.0.12": { "d": "attributeCert", "c": "PKIX" }, +"1.3.6.1.5.5.7.1": { "d": "privateExtension", "c": "PKIX" }, +"1.3.6.1.5.5.7.1.1": { "d": "authorityInfoAccess", "c": "PKIX private extension" }, +"1.3.6.1.5.5.7.1.2": { "d": "biometricInfo", "c": "PKIX private extension" }, +"1.3.6.1.5.5.7.1.3": { "d": "qcStatements", "c": "PKIX private extension" }, +"1.3.6.1.5.5.7.1.4": { "d": "acAuditIdentity", "c": "PKIX private extension" }, +"1.3.6.1.5.5.7.1.5": { "d": "acTargeting", "c": "PKIX private extension" }, +"1.3.6.1.5.5.7.1.6": { "d": "acAaControls", "c": "PKIX private extension" }, +"1.3.6.1.5.5.7.1.7": { "d": "ipAddrBlocks", "c": "PKIX private extension" }, +"1.3.6.1.5.5.7.1.8": { "d": "autonomousSysIds", "c": "PKIX private extension" }, +"1.3.6.1.5.5.7.1.9": { "d": "routerIdentifier", "c": "PKIX private extension" }, +"1.3.6.1.5.5.7.1.10": { "d": "acProxying", "c": "PKIX private extension" }, +"1.3.6.1.5.5.7.1.11": { "d": "subjectInfoAccess", "c": "PKIX private extension" }, +"1.3.6.1.5.5.7.1.12": { "d": "logoType", "c": "PKIX private extension" }, +"1.3.6.1.5.5.7.1.13": { "d": "wlanSSID", "c": "PKIX private extension" }, +"1.3.6.1.5.5.7.2": { "d": "policyQualifierIds", "c": "PKIX" }, +"1.3.6.1.5.5.7.2.1": { "d": "cps", "c": "PKIX policy qualifier" }, +"1.3.6.1.5.5.7.2.2": { "d": "unotice", "c": "PKIX policy qualifier" }, +"1.3.6.1.5.5.7.2.3": { "d": "textNotice", "c": "PKIX policy qualifier" }, +"1.3.6.1.5.5.7.3": { "d": "keyPurpose", "c": "PKIX" }, +"1.3.6.1.5.5.7.3.1": { "d": "serverAuth", "c": "PKIX key purpose" }, +"1.3.6.1.5.5.7.3.2": { "d": "clientAuth", "c": "PKIX key purpose" }, +"1.3.6.1.5.5.7.3.3": { "d": "codeSigning", "c": "PKIX key purpose" }, +"1.3.6.1.5.5.7.3.4": { "d": "emailProtection", "c": "PKIX key purpose" }, +"1.3.6.1.5.5.7.3.5": { "d": "ipsecEndSystem", "c": "PKIX key purpose" }, +"1.3.6.1.5.5.7.3.6": { "d": "ipsecTunnel", "c": "PKIX key purpose" }, +"1.3.6.1.5.5.7.3.7": { "d": "ipsecUser", "c": "PKIX key purpose" }, +"1.3.6.1.5.5.7.3.8": { "d": "timeStamping", "c": "PKIX key purpose" }, +"1.3.6.1.5.5.7.3.9": { "d": "ocspSigning", "c": "PKIX key purpose" }, +"1.3.6.1.5.5.7.3.10": { "d": "dvcs", "c": "PKIX key purpose" }, +"1.3.6.1.5.5.7.3.11": { "d": "sbgpCertAAServerAuth", "c": "PKIX key purpose" }, +"1.3.6.1.5.5.7.3.13": { "d": "eapOverPPP", "c": "PKIX key purpose" }, +"1.3.6.1.5.5.7.3.14": { "d": "eapOverLAN", "c": "PKIX key purpose" }, +"1.3.6.1.5.5.7.4": { "d": "cmpInformationTypes", "c": "PKIX" }, +"1.3.6.1.5.5.7.4.1": { "d": "caProtEncCert", "c": "PKIX CMP information" }, +"1.3.6.1.5.5.7.4.2": { "d": "signKeyPairTypes", "c": "PKIX CMP information" }, +"1.3.6.1.5.5.7.4.3": { "d": "encKeyPairTypes", "c": "PKIX CMP information" }, +"1.3.6.1.5.5.7.4.4": { "d": "preferredSymmAlg", "c": "PKIX CMP information" }, +"1.3.6.1.5.5.7.4.5": { "d": "caKeyUpdateInfo", "c": "PKIX CMP information" }, +"1.3.6.1.5.5.7.4.6": { "d": "currentCRL", "c": "PKIX CMP information" }, +"1.3.6.1.5.5.7.4.7": { "d": "unsupportedOIDs", "c": "PKIX CMP information" }, +"1.3.6.1.5.5.7.4.10": { "d": "keyPairParamReq", "c": "PKIX CMP information" }, +"1.3.6.1.5.5.7.4.11": { "d": "keyPairParamRep", "c": "PKIX CMP information" }, +"1.3.6.1.5.5.7.4.12": { "d": "revPassphrase", "c": "PKIX CMP information" }, +"1.3.6.1.5.5.7.4.13": { "d": "implicitConfirm", "c": "PKIX CMP information" }, +"1.3.6.1.5.5.7.4.14": { "d": "confirmWaitTime", "c": "PKIX CMP information" }, +"1.3.6.1.5.5.7.4.15": { "d": "origPKIMessage", "c": "PKIX CMP information" }, +"1.3.6.1.5.5.7.4.16": { "d": "suppLangTags", "c": "PKIX CMP information" }, +"1.3.6.1.5.5.7.5": { "d": "crmfRegistration", "c": "PKIX" }, +"1.3.6.1.5.5.7.5.1": { "d": "regCtrl", "c": "PKIX CRMF registration" }, +"1.3.6.1.5.5.7.5.1.1": { "d": "regToken", "c": "PKIX CRMF registration control" }, +"1.3.6.1.5.5.7.5.1.2": { "d": "authenticator", "c": "PKIX CRMF registration control" }, +"1.3.6.1.5.5.7.5.1.3": { "d": "pkiPublicationInfo", "c": "PKIX CRMF registration control" }, +"1.3.6.1.5.5.7.5.1.4": { "d": "pkiArchiveOptions", "c": "PKIX CRMF registration control" }, +"1.3.6.1.5.5.7.5.1.5": { "d": "oldCertID", "c": "PKIX CRMF registration control" }, +"1.3.6.1.5.5.7.5.1.6": { "d": "protocolEncrKey", "c": "PKIX CRMF registration control" }, +"1.3.6.1.5.5.7.5.1.7": { "d": "altCertTemplate", "c": "PKIX CRMF registration control" }, +"1.3.6.1.5.5.7.5.1.8": { "d": "wtlsTemplate", "c": "PKIX CRMF registration control" }, +"1.3.6.1.5.5.7.5.2": { "d": "utf8Pairs", "c": "PKIX CRMF registration" }, +"1.3.6.1.5.5.7.5.2.1": { "d": "utf8Pairs", "c": "PKIX CRMF registration control" }, +"1.3.6.1.5.5.7.5.2.2": { "d": "certReq", "c": "PKIX CRMF registration control" }, +"1.3.6.1.5.5.7.6": { "d": "algorithms", "c": "PKIX" }, +"1.3.6.1.5.5.7.6.1": { "d": "des40", "c": "PKIX algorithm" }, +"1.3.6.1.5.5.7.6.2": { "d": "noSignature", "c": "PKIX algorithm" }, +"1.3.6.1.5.5.7.6.3": { "d": "dh-sig-hmac-sha1", "c": "PKIX algorithm" }, +"1.3.6.1.5.5.7.6.4": { "d": "dh-pop", "c": "PKIX algorithm" }, +"1.3.6.1.5.5.7.7": { "d": "cmcControls", "c": "PKIX" }, +"1.3.6.1.5.5.7.8": { "d": "otherNames", "c": "PKIX" }, +"1.3.6.1.5.5.7.8.1": { "d": "personalData", "c": "PKIX other name" }, +"1.3.6.1.5.5.7.8.2": { "d": "userGroup", "c": "PKIX other name" }, +"1.3.6.1.5.5.7.8.5": { "d": "xmppAddr", "c": "PKIX other name" }, +"1.3.6.1.5.5.7.9": { "d": "personalData", "c": "PKIX qualified certificates" }, +"1.3.6.1.5.5.7.9.1": { "d": "dateOfBirth", "c": "PKIX personal data" }, +"1.3.6.1.5.5.7.9.2": { "d": "placeOfBirth", "c": "PKIX personal data" }, +"1.3.6.1.5.5.7.9.3": { "d": "gender", "c": "PKIX personal data" }, +"1.3.6.1.5.5.7.9.4": { "d": "countryOfCitizenship", "c": "PKIX personal data" }, +"1.3.6.1.5.5.7.9.5": { "d": "countryOfResidence", "c": "PKIX personal data" }, +"1.3.6.1.5.5.7.10": { "d": "attributeCertificate", "c": "PKIX" }, +"1.3.6.1.5.5.7.10.1": { "d": "authenticationInfo", "c": "PKIX attribute certificate extension" }, +"1.3.6.1.5.5.7.10.2": { "d": "accessIdentity", "c": "PKIX attribute certificate extension" }, +"1.3.6.1.5.5.7.10.3": { "d": "chargingIdentity", "c": "PKIX attribute certificate extension" }, +"1.3.6.1.5.5.7.10.4": { "d": "group", "c": "PKIX attribute certificate extension" }, +"1.3.6.1.5.5.7.10.5": { "d": "role", "c": "PKIX attribute certificate extension" }, +"1.3.6.1.5.5.7.10.6": { "d": "wlanSSID", "c": "PKIX attribute-certificate extension" }, +"1.3.6.1.5.5.7.11": { "d": "personalData", "c": "PKIX qualified certificates" }, +"1.3.6.1.5.5.7.11.1": { "d": "pkixQCSyntax-v1", "c": "PKIX qualified certificates" }, +"1.3.6.1.5.5.7.14.2": { "d": "resourceCertificatePolicy", "c": "PKIX policies" }, +"1.3.6.1.5.5.7.20": { "d": "logo", "c": "PKIX qualified certificates" }, +"1.3.6.1.5.5.7.20.1": { "d": "logoLoyalty", "c": "PKIX" }, +"1.3.6.1.5.5.7.20.2": { "d": "logoBackground", "c": "PKIX" }, +"1.3.6.1.5.5.7.48.1": { "d": "ocsp", "c": "PKIX" }, +"1.3.6.1.5.5.7.48.1.1": { "d": "ocspBasic", "c": "OCSP" }, +"1.3.6.1.5.5.7.48.1.2": { "d": "ocspNonce", "c": "OCSP" }, +"1.3.6.1.5.5.7.48.1.3": { "d": "ocspCRL", "c": "OCSP" }, +"1.3.6.1.5.5.7.48.1.4": { "d": "ocspResponse", "c": "OCSP" }, +"1.3.6.1.5.5.7.48.1.5": { "d": "ocspNoCheck", "c": "OCSP" }, +"1.3.6.1.5.5.7.48.1.6": { "d": "ocspArchiveCutoff", "c": "OCSP" }, +"1.3.6.1.5.5.7.48.1.7": { "d": "ocspServiceLocator", "c": "OCSP" }, +"1.3.6.1.5.5.7.48.2": { "d": "caIssuers", "c": "PKIX subject/authority info access descriptor" }, +"1.3.6.1.5.5.7.48.3": { "d": "timeStamping", "c": "PKIX subject/authority info access descriptor" }, +"1.3.6.1.5.5.7.48.4": { "d": "dvcs", "c": "PKIX subject/authority info access descriptor" }, +"1.3.6.1.5.5.7.48.5": { "d": "caRepository", "c": "PKIX subject/authority info access descriptor" }, +"1.3.6.1.5.5.7.48.7": { "d": "signedObjectRepository", "c": "PKIX subject/authority info access descriptor" }, +"1.3.6.1.5.5.7.48.10": { "d": "rpkiManifest", "c": "PKIX subject/authority info access descriptor" }, +"1.3.6.1.5.5.7.48.11": { "d": "signedObject", "c": "PKIX subject/authority info access descriptor" }, +"1.3.6.1.5.5.8.1.1": { "d": "hmacMD5", "c": "ISAKMP HMAC algorithm" }, +"1.3.6.1.5.5.8.1.2": { "d": "hmacSHA", "c": "ISAKMP HMAC algorithm" }, +"1.3.6.1.5.5.8.1.3": { "d": "hmacTiger", "c": "ISAKMP HMAC algorithm" }, +"1.3.6.1.5.5.8.2.2": { "d": "iKEIntermediate", "c": "IKE ???" }, +"1.3.12.2.1011.7.1": { "d": "decEncryptionAlgorithm", "c": "DASS algorithm" }, +"1.3.12.2.1011.7.1.2": { "d": "decDEA", "c": "DASS encryption algorithm" }, +"1.3.12.2.1011.7.2": { "d": "decHashAlgorithm", "c": "DASS algorithm" }, +"1.3.12.2.1011.7.2.1": { "d": "decMD2", "c": "DASS hash algorithm" }, +"1.3.12.2.1011.7.2.2": { "d": "decMD4", "c": "DASS hash algorithm" }, +"1.3.12.2.1011.7.3": { "d": "decSignatureAlgorithm", "c": "DASS algorithm" }, +"1.3.12.2.1011.7.3.1": { "d": "decMD2withRSA", "c": "DASS signature algorithm" }, +"1.3.12.2.1011.7.3.2": { "d": "decMD4withRSA", "c": "DASS signature algorithm" }, +"1.3.12.2.1011.7.3.3": { "d": "decDEAMAC", "c": "DASS signature algorithm" }, +"1.3.14.2.26.5": { "d": "sha", "c": "Unsure about this OID" }, +"1.3.14.3.2.1.1": { "d": "rsa", "c": "X.509. Unsure about this OID" }, +"1.3.14.3.2.2": { "d": "md4WitRSA", "c": "Oddball OIW OID" }, +"1.3.14.3.2.3": { "d": "md5WithRSA", "c": "Oddball OIW OID" }, +"1.3.14.3.2.4": { "d": "md4WithRSAEncryption", "c": "Oddball OIW OID" }, +"1.3.14.3.2.2.1": { "d": "sqmod-N", "c": "X.509. Deprecated", "w": true }, +"1.3.14.3.2.3.1": { "d": "sqmod-NwithRSA", "c": "X.509. Deprecated", "w": true }, +"1.3.14.3.2.6": { "d": "desECB", "c": "" }, +"1.3.14.3.2.7": { "d": "desCBC", "c": "" }, +"1.3.14.3.2.8": { "d": "desOFB", "c": "" }, +"1.3.14.3.2.9": { "d": "desCFB", "c": "" }, +"1.3.14.3.2.10": { "d": "desMAC", "c": "" }, +"1.3.14.3.2.11": { "d": "rsaSignature", "c": "ISO 9796-2, also X9.31 Part 1" }, +"1.3.14.3.2.12": { "d": "dsa", "c": "OIW?, supposedly from an incomplete version of SDN.701 (doesn't match final SDN.701)", "w": true }, +"1.3.14.3.2.13": { "d": "dsaWithSHA", "c": "Oddball OIW OID. Incorrectly used by JDK 1.1 in place of (1 3 14 3 2 27)", "w": true }, +"1.3.14.3.2.14": { "d": "mdc2WithRSASignature", "c": "Oddball OIW OID using 9796-2 padding rules" }, +"1.3.14.3.2.15": { "d": "shaWithRSASignature", "c": "Oddball OIW OID using 9796-2 padding rules" }, +"1.3.14.3.2.16": { "d": "dhWithCommonModulus", "c": "Oddball OIW OID. Deprecated, use a plain DH OID instead", "w": true }, +"1.3.14.3.2.17": { "d": "desEDE", "c": "Oddball OIW OID. Mode is ECB" }, +"1.3.14.3.2.18": { "d": "sha", "c": "Oddball OIW OID" }, +"1.3.14.3.2.19": { "d": "mdc-2", "c": "Oddball OIW OID, DES-based hash, planned for X9.31 Part 2" }, +"1.3.14.3.2.20": { "d": "dsaCommon", "c": "Oddball OIW OID. Deprecated, use a plain DSA OID instead", "w": true }, +"1.3.14.3.2.21": { "d": "dsaCommonWithSHA", "c": "Oddball OIW OID. Deprecated, use a plain dsaWithSHA OID instead", "w": true }, +"1.3.14.3.2.22": { "d": "rsaKeyTransport", "c": "Oddball OIW OID" }, +"1.3.14.3.2.23": { "d": "keyed-hash-seal", "c": "Oddball OIW OID" }, +"1.3.14.3.2.24": { "d": "md2WithRSASignature", "c": "Oddball OIW OID using 9796-2 padding rules" }, +"1.3.14.3.2.25": { "d": "md5WithRSASignature", "c": "Oddball OIW OID using 9796-2 padding rules" }, +"1.3.14.3.2.26": { "d": "sha1", "c": "OIW" }, +"1.3.14.3.2.27": { "d": "dsaWithSHA1", "c": "OIW. This OID may also be assigned as ripemd-160" }, +"1.3.14.3.2.28": { "d": "dsaWithCommonSHA1", "c": "OIW" }, +"1.3.14.3.2.29": { "d": "sha-1WithRSAEncryption", "c": "Oddball OIW OID" }, +"1.3.14.3.3.1": { "d": "simple-strong-auth-mechanism", "c": "Oddball OIW OID" }, +"1.3.14.7.2.1.1": { "d": "ElGamal", "c": "Unsure about this OID" }, +"1.3.14.7.2.3.1": { "d": "md2WithRSA", "c": "Unsure about this OID" }, +"1.3.14.7.2.3.2": { "d": "md2WithElGamal", "c": "Unsure about this OID" }, +"1.3.36.1": { "d": "document", "c": "Teletrust document" }, +"1.3.36.1.1": { "d": "finalVersion", "c": "Teletrust document" }, +"1.3.36.1.2": { "d": "draft", "c": "Teletrust document" }, +"1.3.36.2": { "d": "sio", "c": "Teletrust sio" }, +"1.3.36.2.1": { "d": "sedu", "c": "Teletrust sio" }, +"1.3.36.3": { "d": "algorithm", "c": "Teletrust algorithm" }, +"1.3.36.3.1": { "d": "encryptionAlgorithm", "c": "Teletrust algorithm" }, +"1.3.36.3.1.1": { "d": "des", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.1.1": { "d": "desECB_pad", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.1.1.1": { "d": "desECB_ISOpad", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.1.2.1": { "d": "desCBC_pad", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.1.2.1.1": { "d": "desCBC_ISOpad", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.3": { "d": "des_3", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.3.1.1": { "d": "des_3ECB_pad", "c": "Teletrust encryption algorithm. EDE triple DES" }, +"1.3.36.3.1.3.1.1.1": { "d": "des_3ECB_ISOpad", "c": "Teletrust encryption algorithm. EDE triple DES" }, +"1.3.36.3.1.3.2.1": { "d": "des_3CBC_pad", "c": "Teletrust encryption algorithm. EDE triple DES" }, +"1.3.36.3.1.3.2.1.1": { "d": "des_3CBC_ISOpad", "c": "Teletrust encryption algorithm. EDE triple DES" }, +"1.3.36.3.1.2": { "d": "idea", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.2.1": { "d": "ideaECB", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.2.1.1": { "d": "ideaECB_pad", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.2.1.1.1": { "d": "ideaECB_ISOpad", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.2.2": { "d": "ideaCBC", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.2.2.1": { "d": "ideaCBC_pad", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.2.2.1.1": { "d": "ideaCBC_ISOpad", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.2.3": { "d": "ideaOFB", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.2.4": { "d": "ideaCFB", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.4": { "d": "rsaEncryption", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.4.512.17": { "d": "rsaEncryptionWithlmod512expe17", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.5": { "d": "bsi-1", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.5.1": { "d": "bsi_1ECB_pad", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.5.2": { "d": "bsi_1CBC_pad", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.1.5.2.1": { "d": "bsi_1CBC_PEMpad", "c": "Teletrust encryption algorithm" }, +"1.3.36.3.2": { "d": "hashAlgorithm", "c": "Teletrust algorithm" }, +"1.3.36.3.2.1": { "d": "ripemd160", "c": "Teletrust hash algorithm" }, +"1.3.36.3.2.2": { "d": "ripemd128", "c": "Teletrust hash algorithm" }, +"1.3.36.3.2.3": { "d": "ripemd256", "c": "Teletrust hash algorithm" }, +"1.3.36.3.2.4": { "d": "mdc2singleLength", "c": "Teletrust hash algorithm" }, +"1.3.36.3.2.5": { "d": "mdc2doubleLength", "c": "Teletrust hash algorithm" }, +"1.3.36.3.3": { "d": "signatureAlgorithm", "c": "Teletrust algorithm" }, +"1.3.36.3.3.1": { "d": "rsaSignature", "c": "Teletrust signature algorithm" }, +"1.3.36.3.3.1.1": { "d": "rsaSignatureWithsha1", "c": "Teletrust signature algorithm" }, +"1.3.36.3.3.1.1.1024.11": { "d": "rsaSignatureWithsha1_l1024_l11", "c": "Teletrust signature algorithm" }, +"1.3.36.3.3.1.2": { "d": "rsaSignatureWithripemd160", "c": "Teletrust signature algorithm" }, +"1.3.36.3.3.1.2.1024.11": { "d": "rsaSignatureWithripemd160_l1024_l11", "c": "Teletrust signature algorithm" }, +"1.3.36.3.3.1.3": { "d": "rsaSignatureWithrimpemd128", "c": "Teletrust signature algorithm" }, +"1.3.36.3.3.1.4": { "d": "rsaSignatureWithrimpemd256", "c": "Teletrust signature algorithm" }, +"1.3.36.3.3.2": { "d": "ecsieSign", "c": "Teletrust signature algorithm" }, +"1.3.36.3.3.2.1": { "d": "ecsieSignWithsha1", "c": "Teletrust signature algorithm" }, +"1.3.36.3.3.2.2": { "d": "ecsieSignWithripemd160", "c": "Teletrust signature algorithm" }, +"1.3.36.3.3.2.3": { "d": "ecsieSignWithmd2", "c": "Teletrust signature algorithm" }, +"1.3.36.3.3.2.4": { "d": "ecsieSignWithmd5", "c": "Teletrust signature algorithm" }, +"1.3.36.3.3.2.8.1.1.1": { "d": "brainpoolP160r1", "c": "ECC Brainpool Standard Curves and Curve Generation" }, +"1.3.36.3.3.2.8.1.1.2": { "d": "brainpoolP160t1", "c": "ECC Brainpool Standard Curves and Curve Generation" }, +"1.3.36.3.3.2.8.1.1.3": { "d": "brainpoolP192r1", "c": "ECC Brainpool Standard Curves and Curve Generation" }, +"1.3.36.3.3.2.8.1.1.4": { "d": "brainpoolP192t1", "c": "ECC Brainpool Standard Curves and Curve Generation" }, +"1.3.36.3.3.2.8.1.1.5": { "d": "brainpoolP224r1", "c": "ECC Brainpool Standard Curves and Curve Generation" }, +"1.3.36.3.3.2.8.1.1.6": { "d": "brainpoolP224t1", "c": "ECC Brainpool Standard Curves and Curve Generation" }, +"1.3.36.3.3.2.8.1.1.7": { "d": "brainpoolP256r1", "c": "ECC Brainpool Standard Curves and Curve Generation" }, +"1.3.36.3.3.2.8.1.1.8": { "d": "brainpoolP256t1", "c": "ECC Brainpool Standard Curves and Curve Generation" }, +"1.3.36.3.3.2.8.1.1.9": { "d": "brainpoolP320r1", "c": "ECC Brainpool Standard Curves and Curve Generation" }, +"1.3.36.3.3.2.8.1.1.10": { "d": "brainpoolP320t1", "c": "ECC Brainpool Standard Curves and Curve Generation" }, +"1.3.36.3.3.2.8.1.1.11": { "d": "brainpoolP384r1", "c": "ECC Brainpool Standard Curves and Curve Generation" }, +"1.3.36.3.3.2.8.1.1.12": { "d": "brainpoolP384t1", "c": "ECC Brainpool Standard Curves and Curve Generation" }, +"1.3.36.3.3.2.8.1.1.13": { "d": "brainpoolP512r1", "c": "ECC Brainpool Standard Curves and Curve Generation" }, +"1.3.36.3.3.2.8.1.1.14": { "d": "brainpoolP512t1", "c": "ECC Brainpool Standard Curves and Curve Generation" }, +"1.3.36.3.4": { "d": "signatureScheme", "c": "Teletrust algorithm" }, +"1.3.36.3.4.1": { "d": "sigS_ISO9796-1", "c": "Teletrust signature scheme" }, +"1.3.36.3.4.2": { "d": "sigS_ISO9796-2", "c": "Teletrust signature scheme" }, +"1.3.36.3.4.2.1": { "d": "sigS_ISO9796-2Withred", "c": "Teletrust signature scheme. Unsure what this is supposed to be" }, +"1.3.36.3.4.2.2": { "d": "sigS_ISO9796-2Withrsa", "c": "Teletrust signature scheme. Unsure what this is supposed to be" }, +"1.3.36.3.4.2.3": { "d": "sigS_ISO9796-2Withrnd", "c": "Teletrust signature scheme. 9796-2 with random number in padding field" }, +"1.3.36.4": { "d": "attribute", "c": "Teletrust attribute" }, +"1.3.36.5": { "d": "policy", "c": "Teletrust policy" }, +"1.3.36.6": { "d": "api", "c": "Teletrust API" }, +"1.3.36.6.1": { "d": "manufacturer-specific_api", "c": "Teletrust API" }, +"1.3.36.6.1.1": { "d": "utimaco-api", "c": "Teletrust API" }, +"1.3.36.6.2": { "d": "functionality-specific_api", "c": "Teletrust API" }, +"1.3.36.7": { "d": "keymgmnt", "c": "Teletrust key management" }, +"1.3.36.7.1": { "d": "keyagree", "c": "Teletrust key management" }, +"1.3.36.7.1.1": { "d": "bsiPKE", "c": "Teletrust key management" }, +"1.3.36.7.2": { "d": "keytrans", "c": "Teletrust key management" }, +"1.3.36.7.2.1": { "d": "encISO9796-2Withrsa", "c": "Teletrust key management. 9796-2 with key stored in hash field" }, +"1.3.36.8.1.1": { "d": "Teletrust SigGConform policyIdentifier", "c": "Teletrust policy" }, +"1.3.36.8.2.1": { "d": "directoryService", "c": "Teletrust extended key usage" }, +"1.3.36.8.3.1": { "d": "dateOfCertGen", "c": "Teletrust attribute" }, +"1.3.36.8.3.2": { "d": "procuration", "c": "Teletrust attribute" }, +"1.3.36.8.3.3": { "d": "admission", "c": "Teletrust attribute" }, +"1.3.36.8.3.4": { "d": "monetaryLimit", "c": "Teletrust attribute" }, +"1.3.36.8.3.5": { "d": "declarationOfMajority", "c": "Teletrust attribute" }, +"1.3.36.8.3.6": { "d": "integratedCircuitCardSerialNumber", "c": "Teletrust attribute" }, +"1.3.36.8.3.7": { "d": "pKReference", "c": "Teletrust attribute" }, +"1.3.36.8.3.8": { "d": "restriction", "c": "Teletrust attribute" }, +"1.3.36.8.3.9": { "d": "retrieveIfAllowed", "c": "Teletrust attribute" }, +"1.3.36.8.3.10": { "d": "requestedCertificate", "c": "Teletrust attribute" }, +"1.3.36.8.3.11": { "d": "namingAuthorities", "c": "Teletrust attribute" }, +"1.3.36.8.3.11.1": { "d": "rechtWirtschaftSteuern", "c": "Teletrust naming authorities" }, +"1.3.36.8.3.11.1.1": { "d": "rechtsanwaeltin", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.2": { "d": "rechtsanwalt", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.3": { "d": "rechtsBeistand", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.4": { "d": "steuerBeraterin", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.5": { "d": "steuerBerater", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.6": { "d": "steuerBevollmaechtigte", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.7": { "d": "steuerBevollmaechtigter", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.8": { "d": "notarin", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.9": { "d": "notar", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.10": { "d": "notarVertreterin", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.11": { "d": "notarVertreter", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.12": { "d": "notariatsVerwalterin", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.13": { "d": "notariatsVerwalter", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.14": { "d": "wirtschaftsPrueferin", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.15": { "d": "wirtschaftsPruefer", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.16": { "d": "vereidigteBuchprueferin", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.17": { "d": "vereidigterBuchpruefer", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.18": { "d": "patentAnwaeltin", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.11.1.19": { "d": "patentAnwalt", "c": "Teletrust ProfessionInfo" }, +"1.3.36.8.3.12": { "d": "certInDirSince", "c": "Teletrust OCSP attribute (obsolete)", "w": true }, +"1.3.36.8.3.13": { "d": "certHash", "c": "Teletrust OCSP attribute" }, +"1.3.36.8.3.14": { "d": "nameAtBirth", "c": "Teletrust attribute" }, +"1.3.36.8.3.15": { "d": "additionalInformation", "c": "Teletrust attribute" }, +"1.3.36.8.4.1": { "d": "personalData", "c": "Teletrust OtherName attribute" }, +"1.3.36.8.4.8": { "d": "restriction", "c": "Teletrust attribute certificate attribute" }, +"1.3.36.8.5.1.1.1": { "d": "rsaIndicateSHA1", "c": "Teletrust signature algorithm" }, +"1.3.36.8.5.1.1.2": { "d": "rsaIndicateRIPEMD160", "c": "Teletrust signature algorithm" }, +"1.3.36.8.5.1.1.3": { "d": "rsaWithSHA1", "c": "Teletrust signature algorithm" }, +"1.3.36.8.5.1.1.4": { "d": "rsaWithRIPEMD160", "c": "Teletrust signature algorithm" }, +"1.3.36.8.5.1.2.1": { "d": "dsaExtended", "c": "Teletrust signature algorithm" }, +"1.3.36.8.5.1.2.2": { "d": "dsaWithRIPEMD160", "c": "Teletrust signature algorithm" }, +"1.3.36.8.6.1": { "d": "cert", "c": "Teletrust signature attributes" }, +"1.3.36.8.6.2": { "d": "certRef", "c": "Teletrust signature attributes" }, +"1.3.36.8.6.3": { "d": "attrCert", "c": "Teletrust signature attributes" }, +"1.3.36.8.6.4": { "d": "attrRef", "c": "Teletrust signature attributes" }, +"1.3.36.8.6.5": { "d": "fileName", "c": "Teletrust signature attributes" }, +"1.3.36.8.6.6": { "d": "storageTime", "c": "Teletrust signature attributes" }, +"1.3.36.8.6.7": { "d": "fileSize", "c": "Teletrust signature attributes" }, +"1.3.36.8.6.8": { "d": "location", "c": "Teletrust signature attributes" }, +"1.3.36.8.6.9": { "d": "sigNumber", "c": "Teletrust signature attributes" }, +"1.3.36.8.6.10": { "d": "autoGen", "c": "Teletrust signature attributes" }, +"1.3.36.8.7.1.1": { "d": "ptAdobeILL", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.2": { "d": "ptAmiPro", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.3": { "d": "ptAutoCAD", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.4": { "d": "ptBinary", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.5": { "d": "ptBMP", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.6": { "d": "ptCGM", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.7": { "d": "ptCorelCRT", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.8": { "d": "ptCorelDRW", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.9": { "d": "ptCorelEXC", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.10": { "d": "ptCorelPHT", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.11": { "d": "ptDraw", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.12": { "d": "ptDVI", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.13": { "d": "ptEPS", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.14": { "d": "ptExcel", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.15": { "d": "ptGEM", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.16": { "d": "ptGIF", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.17": { "d": "ptHPGL", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.18": { "d": "ptJPEG", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.19": { "d": "ptKodak", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.20": { "d": "ptLaTeX", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.21": { "d": "ptLotus", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.22": { "d": "ptLotusPIC", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.23": { "d": "ptMacPICT", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.24": { "d": "ptMacWord", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.25": { "d": "ptMSWfD", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.26": { "d": "ptMSWord", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.27": { "d": "ptMSWord2", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.28": { "d": "ptMSWord6", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.29": { "d": "ptMSWord8", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.30": { "d": "ptPDF", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.31": { "d": "ptPIF", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.32": { "d": "ptPostscript", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.33": { "d": "ptRTF", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.34": { "d": "ptSCITEX", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.35": { "d": "ptTAR", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.36": { "d": "ptTarga", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.37": { "d": "ptTeX", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.38": { "d": "ptText", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.39": { "d": "ptTIFF", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.40": { "d": "ptTIFF-FC", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.41": { "d": "ptUID", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.42": { "d": "ptUUEncode", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.43": { "d": "ptWMF", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.44": { "d": "ptWordPerfect", "c": "Teletrust presentation types" }, +"1.3.36.8.7.1.45": { "d": "ptWPGrph", "c": "Teletrust presentation types" }, +"1.3.101.1.4": { "d": "thawte-ce", "c": "Thawte" }, +"1.3.101.1.4.1": { "d": "strongExtranet", "c": "Thawte certificate extension" }, +"1.3.101.110": { "d": "curveX25519", "c": "ECDH 25519 key agreement algorithm" }, +"1.3.101.111": { "d": "curveX448", "c": "ECDH 448 key agreement algorithm" }, +"1.3.101.112": { "d": "curveEd25519", "c": "EdDSA 25519 signature algorithm" }, +"1.3.101.113": { "d": "curveEd448", "c": "EdDSA 448 signature algorithm" }, +"1.3.101.114": { "d": "curveEd25519ph", "c": "EdDSA 25519 pre-hash signature algorithm" }, +"1.3.101.115": { "d": "curveEd448ph", "c": "EdDSA 448 pre-hash signature algorithm" }, +"1.3.132.0.1": { "d": "sect163k1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.2": { "d": "sect163r1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.3": { "d": "sect239k1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.4": { "d": "sect113r1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.5": { "d": "sect113r2", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.6": { "d": "secp112r1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.7": { "d": "secp112r2", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.8": { "d": "secp160r1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.9": { "d": "secp160k1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.10": { "d": "secp256k1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.15": { "d": "sect163r2", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.16": { "d": "sect283k1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.17": { "d": "sect283r1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.22": { "d": "sect131r1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.23": { "d": "sect131r2", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.24": { "d": "sect193r1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.25": { "d": "sect193r2", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.26": { "d": "sect233k1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.27": { "d": "sect233r1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.28": { "d": "secp128r1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.29": { "d": "secp128r2", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.30": { "d": "secp160r2", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.31": { "d": "secp192k1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.32": { "d": "secp224k1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.33": { "d": "secp224r1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.34": { "d": "secp384r1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.35": { "d": "secp521r1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.36": { "d": "sect409k1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.37": { "d": "sect409r1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.38": { "d": "sect571k1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.0.39": { "d": "sect571r1", "c": "SECG (Certicom) named elliptic curve" }, +"1.3.132.1.11.1": { "d": "ecdhX963KDF-SHA256", "c": "SECG (Certicom) elliptic curve key agreement" }, +"1.3.132.1.11.2": { "d": "ecdhX963KDF-SHA384", "c": "SECG (Certicom) elliptic curve key agreement" }, +"1.3.132.1.11.3": { "d": "ecdhX963KDF-SHA512", "c": "SECG (Certicom) elliptic curve key agreement" }, +"1.3.133.16.840.9.84": { "d": "x984", "c": "X9.84" }, +"1.3.133.16.840.9.84.0": { "d": "x984Module", "c": "X9.84" }, +"1.3.133.16.840.9.84.0.1": { "d": "x984Biometrics", "c": "X9.84 Module" }, +"1.3.133.16.840.9.84.0.2": { "d": "x984CMS", "c": "X9.84 Module" }, +"1.3.133.16.840.9.84.0.3": { "d": "x984Identifiers", "c": "X9.84 Module" }, +"1.3.133.16.840.9.84.1": { "d": "x984Biometric", "c": "X9.84" }, +"1.3.133.16.840.9.84.1.0": { "d": "biometricUnknownType", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.1": { "d": "biometricBodyOdor", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.2": { "d": "biometricDNA", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.3": { "d": "biometricEarShape", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.4": { "d": "biometricFacialFeatures", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.5": { "d": "biometricFingerImage", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.6": { "d": "biometricFingerGeometry", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.7": { "d": "biometricHandGeometry", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.8": { "d": "biometricIrisFeatures", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.9": { "d": "biometricKeystrokeDynamics", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.10": { "d": "biometricPalm", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.11": { "d": "biometricRetina", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.12": { "d": "biometricSignature", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.13": { "d": "biometricSpeechPattern", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.14": { "d": "biometricThermalImage", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.15": { "d": "biometricVeinPattern", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.16": { "d": "biometricThermalFaceImage", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.17": { "d": "biometricThermalHandImage", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.18": { "d": "biometricLipMovement", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.1.19": { "d": "biometricGait", "c": "X9.84 Biometric" }, +"1.3.133.16.840.9.84.3": { "d": "x984MatchingMethod", "c": "X9.84" }, +"1.3.133.16.840.9.84.4": { "d": "x984FormatOwner", "c": "X9.84" }, +"1.3.133.16.840.9.84.4.0": { "d": "x984CbeffOwner", "c": "X9.84 Format Owner" }, +"1.3.133.16.840.9.84.4.1": { "d": "x984IbiaOwner", "c": "X9.84 Format Owner" }, +"1.3.133.16.840.9.84.4.1.1": { "d": "ibiaOwnerSAFLINK", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.2": { "d": "ibiaOwnerBioscrypt", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.3": { "d": "ibiaOwnerVisionics", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.4": { "d": "ibiaOwnerInfineonTechnologiesAG", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.5": { "d": "ibiaOwnerIridianTechnologies", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.6": { "d": "ibiaOwnerVeridicom", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.7": { "d": "ibiaOwnerCyberSIGN", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.8": { "d": "ibiaOwnereCryp", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.9": { "d": "ibiaOwnerFingerprintCardsAB", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.10": { "d": "ibiaOwnerSecuGen", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.11": { "d": "ibiaOwnerPreciseBiometric", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.12": { "d": "ibiaOwnerIdentix", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.13": { "d": "ibiaOwnerDERMALOG", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.14": { "d": "ibiaOwnerLOGICO", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.15": { "d": "ibiaOwnerNIST", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.16": { "d": "ibiaOwnerA3Vision", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.17": { "d": "ibiaOwnerNEC", "c": "X9.84 IBIA Format Owner" }, +"1.3.133.16.840.9.84.4.1.18": { "d": "ibiaOwnerSTMicroelectronics", "c": "X9.84 IBIA Format Owner" }, +"2.5.4.0": { "d": "objectClass", "c": "X.520 DN component" }, +"2.5.4.1": { "d": "aliasedEntryName", "c": "X.520 DN component" }, +"2.5.4.2": { "d": "knowledgeInformation", "c": "X.520 DN component" }, +"2.5.4.3": { "d": "commonName", "c": "X.520 DN component" }, +"2.5.4.4": { "d": "surname", "c": "X.520 DN component" }, +"2.5.4.5": { "d": "serialNumber", "c": "X.520 DN component" }, +"2.5.4.6": { "d": "countryName", "c": "X.520 DN component" }, +"2.5.4.7": { "d": "localityName", "c": "X.520 DN component" }, +"2.5.4.7.1": { "d": "collectiveLocalityName", "c": "X.520 DN component" }, +"2.5.4.8": { "d": "stateOrProvinceName", "c": "X.520 DN component" }, +"2.5.4.8.1": { "d": "collectiveStateOrProvinceName", "c": "X.520 DN component" }, +"2.5.4.9": { "d": "streetAddress", "c": "X.520 DN component" }, +"2.5.4.9.1": { "d": "collectiveStreetAddress", "c": "X.520 DN component" }, +"2.5.4.10": { "d": "organizationName", "c": "X.520 DN component" }, +"2.5.4.10.1": { "d": "collectiveOrganizationName", "c": "X.520 DN component" }, +"2.5.4.11": { "d": "organizationalUnitName", "c": "X.520 DN component" }, +"2.5.4.11.1": { "d": "collectiveOrganizationalUnitName", "c": "X.520 DN component" }, +"2.5.4.12": { "d": "title", "c": "X.520 DN component" }, +"2.5.4.13": { "d": "description", "c": "X.520 DN component" }, +"2.5.4.14": { "d": "searchGuide", "c": "X.520 DN component" }, +"2.5.4.15": { "d": "businessCategory", "c": "X.520 DN component" }, +"2.5.4.16": { "d": "postalAddress", "c": "X.520 DN component" }, +"2.5.4.16.1": { "d": "collectivePostalAddress", "c": "X.520 DN component" }, +"2.5.4.17": { "d": "postalCode", "c": "X.520 DN component" }, +"2.5.4.17.1": { "d": "collectivePostalCode", "c": "X.520 DN component" }, +"2.5.4.18": { "d": "postOfficeBox", "c": "X.520 DN component" }, +"2.5.4.18.1": { "d": "collectivePostOfficeBox", "c": "X.520 DN component" }, +"2.5.4.19": { "d": "physicalDeliveryOfficeName", "c": "X.520 DN component" }, +"2.5.4.19.1": { "d": "collectivePhysicalDeliveryOfficeName", "c": "X.520 DN component" }, +"2.5.4.20": { "d": "telephoneNumber", "c": "X.520 DN component" }, +"2.5.4.20.1": { "d": "collectiveTelephoneNumber", "c": "X.520 DN component" }, +"2.5.4.21": { "d": "telexNumber", "c": "X.520 DN component" }, +"2.5.4.21.1": { "d": "collectiveTelexNumber", "c": "X.520 DN component" }, +"2.5.4.22": { "d": "teletexTerminalIdentifier", "c": "X.520 DN component" }, +"2.5.4.22.1": { "d": "collectiveTeletexTerminalIdentifier", "c": "X.520 DN component" }, +"2.5.4.23": { "d": "facsimileTelephoneNumber", "c": "X.520 DN component" }, +"2.5.4.23.1": { "d": "collectiveFacsimileTelephoneNumber", "c": "X.520 DN component" }, +"2.5.4.24": { "d": "x121Address", "c": "X.520 DN component" }, +"2.5.4.25": { "d": "internationalISDNNumber", "c": "X.520 DN component" }, +"2.5.4.25.1": { "d": "collectiveInternationalISDNNumber", "c": "X.520 DN component" }, +"2.5.4.26": { "d": "registeredAddress", "c": "X.520 DN component" }, +"2.5.4.27": { "d": "destinationIndicator", "c": "X.520 DN component" }, +"2.5.4.28": { "d": "preferredDeliveryMehtod", "c": "X.520 DN component" }, +"2.5.4.29": { "d": "presentationAddress", "c": "X.520 DN component" }, +"2.5.4.30": { "d": "supportedApplicationContext", "c": "X.520 DN component" }, +"2.5.4.31": { "d": "member", "c": "X.520 DN component" }, +"2.5.4.32": { "d": "owner", "c": "X.520 DN component" }, +"2.5.4.33": { "d": "roleOccupant", "c": "X.520 DN component" }, +"2.5.4.34": { "d": "seeAlso", "c": "X.520 DN component" }, +"2.5.4.35": { "d": "userPassword", "c": "X.520 DN component" }, +"2.5.4.36": { "d": "userCertificate", "c": "X.520 DN component" }, +"2.5.4.37": { "d": "caCertificate", "c": "X.520 DN component" }, +"2.5.4.38": { "d": "authorityRevocationList", "c": "X.520 DN component" }, +"2.5.4.39": { "d": "certificateRevocationList", "c": "X.520 DN component" }, +"2.5.4.40": { "d": "crossCertificatePair", "c": "X.520 DN component" }, +"2.5.4.41": { "d": "name", "c": "X.520 DN component" }, +"2.5.4.42": { "d": "givenName", "c": "X.520 DN component" }, +"2.5.4.43": { "d": "initials", "c": "X.520 DN component" }, +"2.5.4.44": { "d": "generationQualifier", "c": "X.520 DN component" }, +"2.5.4.45": { "d": "uniqueIdentifier", "c": "X.520 DN component" }, +"2.5.4.46": { "d": "dnQualifier", "c": "X.520 DN component" }, +"2.5.4.47": { "d": "enhancedSearchGuide", "c": "X.520 DN component" }, +"2.5.4.48": { "d": "protocolInformation", "c": "X.520 DN component" }, +"2.5.4.49": { "d": "distinguishedName", "c": "X.520 DN component" }, +"2.5.4.50": { "d": "uniqueMember", "c": "X.520 DN component" }, +"2.5.4.51": { "d": "houseIdentifier", "c": "X.520 DN component" }, +"2.5.4.52": { "d": "supportedAlgorithms", "c": "X.520 DN component" }, +"2.5.4.53": { "d": "deltaRevocationList", "c": "X.520 DN component" }, +"2.5.4.54": { "d": "dmdName", "c": "X.520 DN component" }, +"2.5.4.55": { "d": "clearance", "c": "X.520 DN component" }, +"2.5.4.56": { "d": "defaultDirQop", "c": "X.520 DN component" }, +"2.5.4.57": { "d": "attributeIntegrityInfo", "c": "X.520 DN component" }, +"2.5.4.58": { "d": "attributeCertificate", "c": "X.520 DN component" }, +"2.5.4.59": { "d": "attributeCertificateRevocationList", "c": "X.520 DN component" }, +"2.5.4.60": { "d": "confKeyInfo", "c": "X.520 DN component" }, +"2.5.4.61": { "d": "aACertificate", "c": "X.520 DN component" }, +"2.5.4.62": { "d": "attributeDescriptorCertificate", "c": "X.520 DN component" }, +"2.5.4.63": { "d": "attributeAuthorityRevocationList", "c": "X.520 DN component" }, +"2.5.4.64": { "d": "familyInformation", "c": "X.520 DN component" }, +"2.5.4.65": { "d": "pseudonym", "c": "X.520 DN component" }, +"2.5.4.66": { "d": "communicationsService", "c": "X.520 DN component" }, +"2.5.4.67": { "d": "communicationsNetwork", "c": "X.520 DN component" }, +"2.5.4.68": { "d": "certificationPracticeStmt", "c": "X.520 DN component" }, +"2.5.4.69": { "d": "certificatePolicy", "c": "X.520 DN component" }, +"2.5.4.70": { "d": "pkiPath", "c": "X.520 DN component" }, +"2.5.4.71": { "d": "privPolicy", "c": "X.520 DN component" }, +"2.5.4.72": { "d": "role", "c": "X.520 DN component" }, +"2.5.4.73": { "d": "delegationPath", "c": "X.520 DN component" }, +"2.5.4.74": { "d": "protPrivPolicy", "c": "X.520 DN component" }, +"2.5.4.75": { "d": "xMLPrivilegeInfo", "c": "X.520 DN component" }, +"2.5.4.76": { "d": "xmlPrivPolicy", "c": "X.520 DN component" }, +"2.5.4.82": { "d": "permission", "c": "X.520 DN component" }, +"2.5.6.0": { "d": "top", "c": "X.520 objectClass" }, +"2.5.6.1": { "d": "alias", "c": "X.520 objectClass" }, +"2.5.6.2": { "d": "country", "c": "X.520 objectClass" }, +"2.5.6.3": { "d": "locality", "c": "X.520 objectClass" }, +"2.5.6.4": { "d": "organization", "c": "X.520 objectClass" }, +"2.5.6.5": { "d": "organizationalUnit", "c": "X.520 objectClass" }, +"2.5.6.6": { "d": "person", "c": "X.520 objectClass" }, +"2.5.6.7": { "d": "organizationalPerson", "c": "X.520 objectClass" }, +"2.5.6.8": { "d": "organizationalRole", "c": "X.520 objectClass" }, +"2.5.6.9": { "d": "groupOfNames", "c": "X.520 objectClass" }, +"2.5.6.10": { "d": "residentialPerson", "c": "X.520 objectClass" }, +"2.5.6.11": { "d": "applicationProcess", "c": "X.520 objectClass" }, +"2.5.6.12": { "d": "applicationEntity", "c": "X.520 objectClass" }, +"2.5.6.13": { "d": "dSA", "c": "X.520 objectClass" }, +"2.5.6.14": { "d": "device", "c": "X.520 objectClass" }, +"2.5.6.15": { "d": "strongAuthenticationUser", "c": "X.520 objectClass" }, +"2.5.6.16": { "d": "certificateAuthority", "c": "X.520 objectClass" }, +"2.5.6.17": { "d": "groupOfUniqueNames", "c": "X.520 objectClass" }, +"2.5.6.21": { "d": "pkiUser", "c": "X.520 objectClass" }, +"2.5.6.22": { "d": "pkiCA", "c": "X.520 objectClass" }, +"2.5.8.1.1": { "d": "rsa", "c": "X.500 algorithms. Ambiguous, since no padding rules specified", "w": true }, +"2.5.29.1": { "d": "authorityKeyIdentifier", "c": "X.509 extension. Deprecated, use 2 5 29 35 instead", "w": true }, +"2.5.29.2": { "d": "keyAttributes", "c": "X.509 extension. Obsolete, use keyUsage/extKeyUsage instead", "w": true }, +"2.5.29.3": { "d": "certificatePolicies", "c": "X.509 extension. Deprecated, use 2 5 29 32 instead", "w": true }, +"2.5.29.4": { "d": "keyUsageRestriction", "c": "X.509 extension. Obsolete, use keyUsage/extKeyUsage instead", "w": true }, +"2.5.29.5": { "d": "policyMapping", "c": "X.509 extension. Deprecated, use 2 5 29 33 instead", "w": true }, +"2.5.29.6": { "d": "subtreesConstraint", "c": "X.509 extension. Obsolete, use nameConstraints instead", "w": true }, +"2.5.29.7": { "d": "subjectAltName", "c": "X.509 extension. Deprecated, use 2 5 29 17 instead", "w": true }, +"2.5.29.8": { "d": "issuerAltName", "c": "X.509 extension. Deprecated, use 2 5 29 18 instead", "w": true }, +"2.5.29.9": { "d": "subjectDirectoryAttributes", "c": "X.509 extension" }, +"2.5.29.10": { "d": "basicConstraints", "c": "X.509 extension. Deprecated, use 2 5 29 19 instead", "w": true }, +"2.5.29.11": { "d": "nameConstraints", "c": "X.509 extension. Deprecated, use 2 5 29 30 instead", "w": true }, +"2.5.29.12": { "d": "policyConstraints", "c": "X.509 extension. Deprecated, use 2 5 29 36 instead", "w": true }, +"2.5.29.13": { "d": "basicConstraints", "c": "X.509 extension. Deprecated, use 2 5 29 19 instead", "w": true }, +"2.5.29.14": { "d": "subjectKeyIdentifier", "c": "X.509 extension" }, +"2.5.29.15": { "d": "keyUsage", "c": "X.509 extension" }, +"2.5.29.16": { "d": "privateKeyUsagePeriod", "c": "X.509 extension" }, +"2.5.29.17": { "d": "subjectAltName", "c": "X.509 extension" }, +"2.5.29.18": { "d": "issuerAltName", "c": "X.509 extension" }, +"2.5.29.19": { "d": "basicConstraints", "c": "X.509 extension" }, +"2.5.29.20": { "d": "cRLNumber", "c": "X.509 extension" }, +"2.5.29.21": { "d": "cRLReason", "c": "X.509 extension" }, +"2.5.29.22": { "d": "expirationDate", "c": "X.509 extension. Deprecated, alternative OID uncertain", "w": true }, +"2.5.29.23": { "d": "instructionCode", "c": "X.509 extension" }, +"2.5.29.24": { "d": "invalidityDate", "c": "X.509 extension" }, +"2.5.29.25": { "d": "cRLDistributionPoints", "c": "X.509 extension. Deprecated, use 2 5 29 31 instead", "w": true }, +"2.5.29.26": { "d": "issuingDistributionPoint", "c": "X.509 extension. Deprecated, use 2 5 29 28 instead", "w": true }, +"2.5.29.27": { "d": "deltaCRLIndicator", "c": "X.509 extension" }, +"2.5.29.28": { "d": "issuingDistributionPoint", "c": "X.509 extension" }, +"2.5.29.29": { "d": "certificateIssuer", "c": "X.509 extension" }, +"2.5.29.30": { "d": "nameConstraints", "c": "X.509 extension" }, +"2.5.29.31": { "d": "cRLDistributionPoints", "c": "X.509 extension" }, +"2.5.29.32": { "d": "certificatePolicies", "c": "X.509 extension" }, +"2.5.29.32.0": { "d": "anyPolicy", "c": "X.509 certificate policy" }, +"2.5.29.33": { "d": "policyMappings", "c": "X.509 extension" }, +"2.5.29.34": { "d": "policyConstraints", "c": "X.509 extension. Deprecated, use 2 5 29 36 instead", "w": true }, +"2.5.29.35": { "d": "authorityKeyIdentifier", "c": "X.509 extension" }, +"2.5.29.36": { "d": "policyConstraints", "c": "X.509 extension" }, +"2.5.29.37": { "d": "extKeyUsage", "c": "X.509 extension" }, +"2.5.29.37.0": { "d": "anyExtendedKeyUsage", "c": "X.509 extended key usage" }, +"2.5.29.38": { "d": "authorityAttributeIdentifier", "c": "X.509 extension" }, +"2.5.29.39": { "d": "roleSpecCertIdentifier", "c": "X.509 extension" }, +"2.5.29.40": { "d": "cRLStreamIdentifier", "c": "X.509 extension" }, +"2.5.29.41": { "d": "basicAttConstraints", "c": "X.509 extension" }, +"2.5.29.42": { "d": "delegatedNameConstraints", "c": "X.509 extension" }, +"2.5.29.43": { "d": "timeSpecification", "c": "X.509 extension" }, +"2.5.29.44": { "d": "cRLScope", "c": "X.509 extension" }, +"2.5.29.45": { "d": "statusReferrals", "c": "X.509 extension" }, +"2.5.29.46": { "d": "freshestCRL", "c": "X.509 extension" }, +"2.5.29.47": { "d": "orderedList", "c": "X.509 extension" }, +"2.5.29.48": { "d": "attributeDescriptor", "c": "X.509 extension" }, +"2.5.29.49": { "d": "userNotice", "c": "X.509 extension" }, +"2.5.29.50": { "d": "sOAIdentifier", "c": "X.509 extension" }, +"2.5.29.51": { "d": "baseUpdateTime", "c": "X.509 extension" }, +"2.5.29.52": { "d": "acceptableCertPolicies", "c": "X.509 extension" }, +"2.5.29.53": { "d": "deltaInfo", "c": "X.509 extension" }, +"2.5.29.54": { "d": "inhibitAnyPolicy", "c": "X.509 extension" }, +"2.5.29.55": { "d": "targetInformation", "c": "X.509 extension" }, +"2.5.29.56": { "d": "noRevAvail", "c": "X.509 extension" }, +"2.5.29.57": { "d": "acceptablePrivilegePolicies", "c": "X.509 extension" }, +"2.5.29.58": { "d": "toBeRevoked", "c": "X.509 extension" }, +"2.5.29.59": { "d": "revokedGroups", "c": "X.509 extension" }, +"2.5.29.60": { "d": "expiredCertsOnCRL", "c": "X.509 extension" }, +"2.5.29.61": { "d": "indirectIssuer", "c": "X.509 extension" }, +"2.5.29.62": { "d": "noAssertion", "c": "X.509 extension" }, +"2.5.29.63": { "d": "aAissuingDistributionPoint", "c": "X.509 extension" }, +"2.5.29.64": { "d": "issuedOnBehalfOf", "c": "X.509 extension" }, +"2.5.29.65": { "d": "singleUse", "c": "X.509 extension" }, +"2.5.29.66": { "d": "groupAC", "c": "X.509 extension" }, +"2.5.29.67": { "d": "allowedAttAss", "c": "X.509 extension" }, +"2.5.29.68": { "d": "attributeMappings", "c": "X.509 extension" }, +"2.5.29.69": { "d": "holderNameConstraints", "c": "X.509 extension" }, +"2.16.724.1.2.2.4.1": { "d": "personalDataInfo", "c": "Spanish Government PKI?" }, +"2.16.840.1.101.2.1.1.1": { "d": "sdnsSignatureAlgorithm", "c": "SDN.700 INFOSEC algorithms" }, +"2.16.840.1.101.2.1.1.2": { "d": "fortezzaSignatureAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicSignatureAlgorithm, this OID is better known as dsaWithSHA-1." }, +"2.16.840.1.101.2.1.1.3": { "d": "sdnsConfidentialityAlgorithm", "c": "SDN.700 INFOSEC algorithms" }, +"2.16.840.1.101.2.1.1.4": { "d": "fortezzaConfidentialityAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicConfidentialityAlgorithm" }, +"2.16.840.1.101.2.1.1.5": { "d": "sdnsIntegrityAlgorithm", "c": "SDN.700 INFOSEC algorithms" }, +"2.16.840.1.101.2.1.1.6": { "d": "fortezzaIntegrityAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicIntegrityAlgorithm" }, +"2.16.840.1.101.2.1.1.7": { "d": "sdnsTokenProtectionAlgorithm", "c": "SDN.700 INFOSEC algorithms" }, +"2.16.840.1.101.2.1.1.8": { "d": "fortezzaTokenProtectionAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly know as mosaicTokenProtectionAlgorithm" }, +"2.16.840.1.101.2.1.1.9": { "d": "sdnsKeyManagementAlgorithm", "c": "SDN.700 INFOSEC algorithms" }, +"2.16.840.1.101.2.1.1.10": { "d": "fortezzaKeyManagementAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicKeyManagementAlgorithm" }, +"2.16.840.1.101.2.1.1.11": { "d": "sdnsKMandSigAlgorithm", "c": "SDN.700 INFOSEC algorithms" }, +"2.16.840.1.101.2.1.1.12": { "d": "fortezzaKMandSigAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicKMandSigAlgorithm" }, +"2.16.840.1.101.2.1.1.13": { "d": "suiteASignatureAlgorithm", "c": "SDN.700 INFOSEC algorithms" }, +"2.16.840.1.101.2.1.1.14": { "d": "suiteAConfidentialityAlgorithm", "c": "SDN.700 INFOSEC algorithms" }, +"2.16.840.1.101.2.1.1.15": { "d": "suiteAIntegrityAlgorithm", "c": "SDN.700 INFOSEC algorithms" }, +"2.16.840.1.101.2.1.1.16": { "d": "suiteATokenProtectionAlgorithm", "c": "SDN.700 INFOSEC algorithms" }, +"2.16.840.1.101.2.1.1.17": { "d": "suiteAKeyManagementAlgorithm", "c": "SDN.700 INFOSEC algorithms" }, +"2.16.840.1.101.2.1.1.18": { "d": "suiteAKMandSigAlgorithm", "c": "SDN.700 INFOSEC algorithms" }, +"2.16.840.1.101.2.1.1.19": { "d": "fortezzaUpdatedSigAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicUpdatedSigAlgorithm" }, +"2.16.840.1.101.2.1.1.20": { "d": "fortezzaKMandUpdSigAlgorithms", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicKMandUpdSigAlgorithms" }, +"2.16.840.1.101.2.1.1.21": { "d": "fortezzaUpdatedIntegAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicUpdatedIntegAlgorithm" }, +"2.16.840.1.101.2.1.1.22": { "d": "keyExchangeAlgorithm", "c": "SDN.700 INFOSEC algorithms. Formerly known as mosaicKeyEncryptionAlgorithm" }, +"2.16.840.1.101.2.1.1.23": { "d": "fortezzaWrap80Algorithm", "c": "SDN.700 INFOSEC algorithms" }, +"2.16.840.1.101.2.1.1.24": { "d": "kEAKeyEncryptionAlgorithm", "c": "SDN.700 INFOSEC algorithms" }, +"2.16.840.1.101.2.1.2.1": { "d": "rfc822MessageFormat", "c": "SDN.700 INFOSEC format" }, +"2.16.840.1.101.2.1.2.2": { "d": "emptyContent", "c": "SDN.700 INFOSEC format" }, +"2.16.840.1.101.2.1.2.3": { "d": "cspContentType", "c": "SDN.700 INFOSEC format" }, +"2.16.840.1.101.2.1.2.42": { "d": "mspRev3ContentType", "c": "SDN.700 INFOSEC format" }, +"2.16.840.1.101.2.1.2.48": { "d": "mspContentType", "c": "SDN.700 INFOSEC format" }, +"2.16.840.1.101.2.1.2.49": { "d": "mspRekeyAgentProtocol", "c": "SDN.700 INFOSEC format" }, +"2.16.840.1.101.2.1.2.50": { "d": "mspMMP", "c": "SDN.700 INFOSEC format" }, +"2.16.840.1.101.2.1.2.66": { "d": "mspRev3-1ContentType", "c": "SDN.700 INFOSEC format" }, +"2.16.840.1.101.2.1.2.72": { "d": "forwardedMSPMessageBodyPart", "c": "SDN.700 INFOSEC format" }, +"2.16.840.1.101.2.1.2.73": { "d": "mspForwardedMessageParameters", "c": "SDN.700 INFOSEC format" }, +"2.16.840.1.101.2.1.2.74": { "d": "forwardedCSPMsgBodyPart", "c": "SDN.700 INFOSEC format" }, +"2.16.840.1.101.2.1.2.75": { "d": "cspForwardedMessageParameters", "c": "SDN.700 INFOSEC format" }, +"2.16.840.1.101.2.1.2.76": { "d": "mspMMP2", "c": "SDN.700 INFOSEC format" }, +"2.16.840.1.101.2.1.3.1": { "d": "sdnsSecurityPolicy", "c": "SDN.700 INFOSEC policy" }, +"2.16.840.1.101.2.1.3.2": { "d": "sdnsPRBAC", "c": "SDN.700 INFOSEC policy" }, +"2.16.840.1.101.2.1.3.3": { "d": "mosaicPRBAC", "c": "SDN.700 INFOSEC policy" }, +"2.16.840.1.101.2.1.3.10": { "d": "siSecurityPolicy", "c": "SDN.700 INFOSEC policy" }, +"2.16.840.1.101.2.1.3.10.0": { "d": "siNASP", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.1": { "d": "siELCO", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.2": { "d": "siTK", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.3": { "d": "siDSAP", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.4": { "d": "siSSSS", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.5": { "d": "siDNASP", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.6": { "d": "siBYEMAN", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.7": { "d": "siREL-US", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.8": { "d": "siREL-AUS", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.9": { "d": "siREL-CAN", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.10": { "d": "siREL_UK", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.11": { "d": "siREL-NZ", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.10.12": { "d": "siGeneric", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.11": { "d": "genser", "c": "SDN.700 INFOSEC policy" }, +"2.16.840.1.101.2.1.3.11.0": { "d": "genserNations", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.11.1": { "d": "genserComsec", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.11.2": { "d": "genserAcquisition", "c": "SDN.700 INFOSEC policy (obsolete)", "w": true }, +"2.16.840.1.101.2.1.3.11.3": { "d": "genserSecurityCategories", "c": "SDN.700 INFOSEC policy" }, +"2.16.840.1.101.2.1.3.11.3.0": { "d": "genserTagSetName", "c": "SDN.700 INFOSEC GENSER policy" }, +"2.16.840.1.101.2.1.3.12": { "d": "defaultSecurityPolicy", "c": "SDN.700 INFOSEC policy" }, +"2.16.840.1.101.2.1.3.13": { "d": "capcoMarkings", "c": "SDN.700 INFOSEC policy" }, +"2.16.840.1.101.2.1.3.13.0": { "d": "capcoSecurityCategories", "c": "SDN.700 INFOSEC policy CAPCO markings" }, +"2.16.840.1.101.2.1.3.13.0.1": { "d": "capcoTagSetName1", "c": "SDN.700 INFOSEC policy CAPCO markings" }, +"2.16.840.1.101.2.1.3.13.0.2": { "d": "capcoTagSetName2", "c": "SDN.700 INFOSEC policy CAPCO markings" }, +"2.16.840.1.101.2.1.3.13.0.3": { "d": "capcoTagSetName3", "c": "SDN.700 INFOSEC policy CAPCO markings" }, +"2.16.840.1.101.2.1.3.13.0.4": { "d": "capcoTagSetName4", "c": "SDN.700 INFOSEC policy CAPCO markings" }, +"2.16.840.1.101.2.1.5.1": { "d": "sdnsKeyManagementCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.2": { "d": "sdnsUserSignatureCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.3": { "d": "sdnsKMandSigCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.4": { "d": "fortezzaKeyManagementCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.5": { "d": "fortezzaKMandSigCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.6": { "d": "fortezzaUserSignatureCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.7": { "d": "fortezzaCASignatureCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.8": { "d": "sdnsCASignatureCertificate", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.10": { "d": "auxiliaryVector", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.11": { "d": "mlReceiptPolicy", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.12": { "d": "mlMembership", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.13": { "d": "mlAdministrators", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.14": { "d": "alid", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.20": { "d": "janUKMs", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.21": { "d": "febUKMs", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.22": { "d": "marUKMs", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.23": { "d": "aprUKMs", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.24": { "d": "mayUKMs", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.25": { "d": "junUKMs", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.26": { "d": "julUKMs", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.27": { "d": "augUKMs", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.28": { "d": "sepUKMs", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.29": { "d": "octUKMs", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.30": { "d": "novUKMs", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.31": { "d": "decUKMs", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.40": { "d": "metaSDNSckl", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.41": { "d": "sdnsCKL", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.42": { "d": "metaSDNSsignatureCKL", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.43": { "d": "sdnsSignatureCKL", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.44": { "d": "sdnsCertificateRevocationList", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.45": { "d": "fortezzaCertificateRevocationList", "c": "SDN.700 INFOSEC attributes (superseded)", "w": true }, +"2.16.840.1.101.2.1.5.46": { "d": "fortezzaCKL", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.47": { "d": "alExemptedAddressProcessor", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.48": { "d": "guard", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.49": { "d": "algorithmsSupported", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.50": { "d": "suiteAKeyManagementCertificate", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.51": { "d": "suiteAKMandSigCertificate", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.52": { "d": "suiteAUserSignatureCertificate", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.53": { "d": "prbacInfo", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.54": { "d": "prbacCAConstraints", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.55": { "d": "sigOrKMPrivileges", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.56": { "d": "commPrivileges", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.57": { "d": "labeledAttribute", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.58": { "d": "policyInformationFile", "c": "SDN.700 INFOSEC attributes (obsolete)", "w": true }, +"2.16.840.1.101.2.1.5.59": { "d": "secPolicyInformationFile", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.5.60": { "d": "cAClearanceConstraint", "c": "SDN.700 INFOSEC attributes" }, +"2.16.840.1.101.2.1.7.1": { "d": "cspExtns", "c": "SDN.700 INFOSEC extensions" }, +"2.16.840.1.101.2.1.7.1.0": { "d": "cspCsExtn", "c": "SDN.700 INFOSEC extensions" }, +"2.16.840.1.101.2.1.8.1": { "d": "mISSISecurityCategories", "c": "SDN.700 INFOSEC security category" }, +"2.16.840.1.101.2.1.8.2": { "d": "standardSecurityLabelPrivileges", "c": "SDN.700 INFOSEC security category" }, +"2.16.840.1.101.2.1.10.1": { "d": "sigPrivileges", "c": "SDN.700 INFOSEC privileges" }, +"2.16.840.1.101.2.1.10.2": { "d": "kmPrivileges", "c": "SDN.700 INFOSEC privileges" }, +"2.16.840.1.101.2.1.10.3": { "d": "namedTagSetPrivilege", "c": "SDN.700 INFOSEC privileges" }, +"2.16.840.1.101.2.1.11.1": { "d": "ukDemo", "c": "SDN.700 INFOSEC certificate policy" }, +"2.16.840.1.101.2.1.11.2": { "d": "usDODClass2", "c": "SDN.700 INFOSEC certificate policy" }, +"2.16.840.1.101.2.1.11.3": { "d": "usMediumPilot", "c": "SDN.700 INFOSEC certificate policy" }, +"2.16.840.1.101.2.1.11.4": { "d": "usDODClass4", "c": "SDN.700 INFOSEC certificate policy" }, +"2.16.840.1.101.2.1.11.5": { "d": "usDODClass3", "c": "SDN.700 INFOSEC certificate policy" }, +"2.16.840.1.101.2.1.11.6": { "d": "usDODClass5", "c": "SDN.700 INFOSEC certificate policy" }, +"2.16.840.1.101.2.1.12.0": { "d": "testSecurityPolicy", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.2.1.12.0.1": { "d": "tsp1", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.2.1.12.0.1.0": { "d": "tsp1SecurityCategories", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.2.1.12.0.1.0.0": { "d": "tsp1TagSetZero", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.2.1.12.0.1.0.1": { "d": "tsp1TagSetOne", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.2.1.12.0.1.0.2": { "d": "tsp1TagSetTwo", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.2.1.12.0.2": { "d": "tsp2", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.2.1.12.0.2.0": { "d": "tsp2SecurityCategories", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.2.1.12.0.2.0.0": { "d": "tsp2TagSetZero", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.2.1.12.0.2.0.1": { "d": "tsp2TagSetOne", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.2.1.12.0.2.0.2": { "d": "tsp2TagSetTwo", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.2.1.12.0.3": { "d": "kafka", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.2.1.12.0.3.0": { "d": "kafkaSecurityCategories", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.2.1.12.0.3.0.1": { "d": "kafkaTagSetName1", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.2.1.12.0.3.0.2": { "d": "kafkaTagSetName2", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.2.1.12.0.3.0.3": { "d": "kafkaTagSetName3", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.2.1.12.1.1": { "d": "tcp1", "c": "SDN.700 INFOSEC test objects" }, +"2.16.840.1.101.3.1": { "d": "slabel", "c": "CSOR GAK", "w": true }, +"2.16.840.1.101.3.2": { "d": "pki", "c": "NIST", "w": true }, +"2.16.840.1.101.3.2.1": { "d": "NIST policyIdentifier", "c": "NIST policies", "w": true }, +"2.16.840.1.101.3.2.1.3.1": { "d": "fbcaRudimentaryPolicy", "c": "Federal Bridge CA Policy" }, +"2.16.840.1.101.3.2.1.3.2": { "d": "fbcaBasicPolicy", "c": "Federal Bridge CA Policy" }, +"2.16.840.1.101.3.2.1.3.3": { "d": "fbcaMediumPolicy", "c": "Federal Bridge CA Policy" }, +"2.16.840.1.101.3.2.1.3.4": { "d": "fbcaHighPolicy", "c": "Federal Bridge CA Policy" }, +"2.16.840.1.101.3.2.1.48.1": { "d": "nistTestPolicy1", "c": "NIST PKITS policies" }, +"2.16.840.1.101.3.2.1.48.2": { "d": "nistTestPolicy2", "c": "NIST PKITS policies" }, +"2.16.840.1.101.3.2.1.48.3": { "d": "nistTestPolicy3", "c": "NIST PKITS policies" }, +"2.16.840.1.101.3.2.1.48.4": { "d": "nistTestPolicy4", "c": "NIST PKITS policies" }, +"2.16.840.1.101.3.2.1.48.5": { "d": "nistTestPolicy5", "c": "NIST PKITS policies" }, +"2.16.840.1.101.3.2.1.48.6": { "d": "nistTestPolicy6", "c": "NIST PKITS policies" }, +"2.16.840.1.101.3.2.2": { "d": "gak", "c": "CSOR GAK extended key usage", "w": true }, +"2.16.840.1.101.3.2.2.1": { "d": "kRAKey", "c": "CSOR GAK extended key usage", "w": true }, +"2.16.840.1.101.3.2.3": { "d": "extensions", "c": "CSOR GAK extensions", "w": true }, +"2.16.840.1.101.3.2.3.1": { "d": "kRTechnique", "c": "CSOR GAK extensions", "w": true }, +"2.16.840.1.101.3.2.3.2": { "d": "kRecoveryCapable", "c": "CSOR GAK extensions", "w": true }, +"2.16.840.1.101.3.2.3.3": { "d": "kR", "c": "CSOR GAK extensions", "w": true }, +"2.16.840.1.101.3.2.4": { "d": "keyRecoverySchemes", "c": "CSOR GAK", "w": true }, +"2.16.840.1.101.3.2.5": { "d": "krapola", "c": "CSOR GAK", "w": true }, +"2.16.840.1.101.3.3": { "d": "arpa", "c": "CSOR GAK", "w": true }, +"2.16.840.1.101.3.4": { "d": "nistAlgorithm", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1": { "d": "aes", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.1": { "d": "aes128-ECB", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.2": { "d": "aes128-CBC", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.3": { "d": "aes128-OFB", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.4": { "d": "aes128-CFB", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.5": { "d": "aes128-wrap", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.6": { "d": "aes128-GCM", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.7": { "d": "aes128-CCM", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.8": { "d": "aes128-wrap-pad", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.21": { "d": "aes192-ECB", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.22": { "d": "aes192-CBC", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.23": { "d": "aes192-OFB", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.24": { "d": "aes192-CFB", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.25": { "d": "aes192-wrap", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.26": { "d": "aes192-GCM", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.27": { "d": "aes192-CCM", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.28": { "d": "aes192-wrap-pad", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.41": { "d": "aes256-ECB", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.42": { "d": "aes256-CBC", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.43": { "d": "aes256-OFB", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.44": { "d": "aes256-CFB", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.45": { "d": "aes256-wrap", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.46": { "d": "aes256-GCM", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.47": { "d": "aes256-CCM", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.1.48": { "d": "aes256-wrap-pad", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.2": { "d": "hashAlgos", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.2.1": { "d": "sha-256", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.2.2": { "d": "sha-384", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.2.3": { "d": "sha-512", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.2.4": { "d": "sha-224", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.3.1": { "d": "dsaWithSha224", "c": "NIST Algorithm" }, +"2.16.840.1.101.3.4.3.2": { "d": "dsaWithSha256", "c": "NIST Algorithm" }, +"2.16.840.1.113719.1.2.8": { "d": "novellAlgorithm", "c": "Novell" }, +"2.16.840.1.113719.1.2.8.22": { "d": "desCbcIV8", "c": "Novell encryption algorithm" }, +"2.16.840.1.113719.1.2.8.23": { "d": "desCbcPadIV8", "c": "Novell encryption algorithm" }, +"2.16.840.1.113719.1.2.8.24": { "d": "desEDE2CbcIV8", "c": "Novell encryption algorithm" }, +"2.16.840.1.113719.1.2.8.25": { "d": "desEDE2CbcPadIV8", "c": "Novell encryption algorithm" }, +"2.16.840.1.113719.1.2.8.26": { "d": "desEDE3CbcIV8", "c": "Novell encryption algorithm" }, +"2.16.840.1.113719.1.2.8.27": { "d": "desEDE3CbcPadIV8", "c": "Novell encryption algorithm" }, +"2.16.840.1.113719.1.2.8.28": { "d": "rc5CbcPad", "c": "Novell encryption algorithm" }, +"2.16.840.1.113719.1.2.8.29": { "d": "md2WithRSAEncryptionBSafe1", "c": "Novell signature algorithm" }, +"2.16.840.1.113719.1.2.8.30": { "d": "md5WithRSAEncryptionBSafe1", "c": "Novell signature algorithm" }, +"2.16.840.1.113719.1.2.8.31": { "d": "sha1WithRSAEncryptionBSafe1", "c": "Novell signature algorithm" }, +"2.16.840.1.113719.1.2.8.32": { "d": "lmDigest", "c": "Novell digest algorithm" }, +"2.16.840.1.113719.1.2.8.40": { "d": "md2", "c": "Novell digest algorithm" }, +"2.16.840.1.113719.1.2.8.50": { "d": "md5", "c": "Novell digest algorithm" }, +"2.16.840.1.113719.1.2.8.51": { "d": "ikeHmacWithSHA1-RSA", "c": "Novell signature algorithm" }, +"2.16.840.1.113719.1.2.8.52": { "d": "ikeHmacWithMD5-RSA", "c": "Novell signature algorithm" }, +"2.16.840.1.113719.1.2.8.69": { "d": "rc2CbcPad", "c": "Novell encryption algorithm" }, +"2.16.840.1.113719.1.2.8.82": { "d": "sha-1", "c": "Novell digest algorithm" }, +"2.16.840.1.113719.1.2.8.92": { "d": "rc2BSafe1Cbc", "c": "Novell encryption algorithm" }, +"2.16.840.1.113719.1.2.8.95": { "d": "md4", "c": "Novell digest algorithm" }, +"2.16.840.1.113719.1.2.8.130": { "d": "md4Packet", "c": "Novell keyed hash" }, +"2.16.840.1.113719.1.2.8.131": { "d": "rsaEncryptionBsafe1", "c": "Novell encryption algorithm" }, +"2.16.840.1.113719.1.2.8.132": { "d": "nwPassword", "c": "Novell encryption algorithm" }, +"2.16.840.1.113719.1.2.8.133": { "d": "novellObfuscate-1", "c": "Novell encryption algorithm" }, +"2.16.840.1.113719.1.9": { "d": "pki", "c": "Novell" }, +"2.16.840.1.113719.1.9.4": { "d": "pkiAttributeType", "c": "Novell PKI" }, +"2.16.840.1.113719.1.9.4.1": { "d": "securityAttributes", "c": "Novell PKI attribute type" }, +"2.16.840.1.113719.1.9.4.2": { "d": "relianceLimit", "c": "Novell PKI attribute type" }, +"2.16.840.1.113730.1": { "d": "cert-extension", "c": "Netscape" }, +"2.16.840.1.113730.1.1": { "d": "netscape-cert-type", "c": "Netscape certificate extension" }, +"2.16.840.1.113730.1.2": { "d": "netscape-base-url", "c": "Netscape certificate extension" }, +"2.16.840.1.113730.1.3": { "d": "netscape-revocation-url", "c": "Netscape certificate extension" }, +"2.16.840.1.113730.1.4": { "d": "netscape-ca-revocation-url", "c": "Netscape certificate extension" }, +"2.16.840.1.113730.1.7": { "d": "netscape-cert-renewal-url", "c": "Netscape certificate extension" }, +"2.16.840.1.113730.1.8": { "d": "netscape-ca-policy-url", "c": "Netscape certificate extension" }, +"2.16.840.1.113730.1.9": { "d": "HomePage-url", "c": "Netscape certificate extension" }, +"2.16.840.1.113730.1.10": { "d": "EntityLogo", "c": "Netscape certificate extension" }, +"2.16.840.1.113730.1.11": { "d": "UserPicture", "c": "Netscape certificate extension" }, +"2.16.840.1.113730.1.12": { "d": "netscape-ssl-server-name", "c": "Netscape certificate extension" }, +"2.16.840.1.113730.1.13": { "d": "netscape-comment", "c": "Netscape certificate extension" }, +"2.16.840.1.113730.2": { "d": "data-type", "c": "Netscape" }, +"2.16.840.1.113730.2.1": { "d": "dataGIF", "c": "Netscape data type" }, +"2.16.840.1.113730.2.2": { "d": "dataJPEG", "c": "Netscape data type" }, +"2.16.840.1.113730.2.3": { "d": "dataURL", "c": "Netscape data type" }, +"2.16.840.1.113730.2.4": { "d": "dataHTML", "c": "Netscape data type" }, +"2.16.840.1.113730.2.5": { "d": "certSequence", "c": "Netscape data type" }, +"2.16.840.1.113730.2.6": { "d": "certURL", "c": "Netscape certificate extension" }, +"2.16.840.1.113730.3": { "d": "directory", "c": "Netscape" }, +"2.16.840.1.113730.3.1": { "d": "ldapDefinitions", "c": "Netscape directory" }, +"2.16.840.1.113730.3.1.1": { "d": "carLicense", "c": "Netscape LDAP definitions" }, +"2.16.840.1.113730.3.1.2": { "d": "departmentNumber", "c": "Netscape LDAP definitions" }, +"2.16.840.1.113730.3.1.3": { "d": "employeeNumber", "c": "Netscape LDAP definitions" }, +"2.16.840.1.113730.3.1.4": { "d": "employeeType", "c": "Netscape LDAP definitions" }, +"2.16.840.1.113730.3.2.2": { "d": "inetOrgPerson", "c": "Netscape LDAP definitions" }, +"2.16.840.1.113730.4.1": { "d": "serverGatedCrypto", "c": "Netscape" }, +"2.16.840.1.113733.1.6.3": { "d": "verisignCZAG", "c": "Verisign extension" }, +"2.16.840.1.113733.1.6.6": { "d": "verisignInBox", "c": "Verisign extension" }, +"2.16.840.1.113733.1.6.11": { "d": "verisignOnsiteJurisdictionHash", "c": "Verisign extension" }, +"2.16.840.1.113733.1.6.13": { "d": "Unknown Verisign VPN extension", "c": "Verisign extension" }, +"2.16.840.1.113733.1.6.15": { "d": "verisignServerID", "c": "Verisign extension" }, +"2.16.840.1.113733.1.7.1.1": { "d": "verisignCertPolicies95Qualifier1", "c": "Verisign policy" }, +"2.16.840.1.113733.1.7.1.1.1": { "d": "verisignCPSv1notice", "c": "Verisign policy (obsolete)" }, +"2.16.840.1.113733.1.7.1.1.2": { "d": "verisignCPSv1nsi", "c": "Verisign policy (obsolete)" }, +"2.16.840.1.113733.1.8.1": { "d": "verisignISSStrongCrypto", "c": "Verisign" }, +"2.16.840.1.113733.1": { "d": "pki", "c": "Verisign extension" }, +"2.16.840.1.113733.1.9": { "d": "pkcs7Attribute", "c": "Verisign PKI extension" }, +"2.16.840.1.113733.1.9.2": { "d": "messageType", "c": "Verisign PKCS #7 attribute" }, +"2.16.840.1.113733.1.9.3": { "d": "pkiStatus", "c": "Verisign PKCS #7 attribute" }, +"2.16.840.1.113733.1.9.4": { "d": "failInfo", "c": "Verisign PKCS #7 attribute" }, +"2.16.840.1.113733.1.9.5": { "d": "senderNonce", "c": "Verisign PKCS #7 attribute" }, +"2.16.840.1.113733.1.9.6": { "d": "recipientNonce", "c": "Verisign PKCS #7 attribute" }, +"2.16.840.1.113733.1.9.7": { "d": "transID", "c": "Verisign PKCS #7 attribute" }, +"2.16.840.1.113733.1.9.8": { "d": "extensionReq", "c": "Verisign PKCS #7 attribute. Use PKCS #9 extensionRequest instead", "w": true }, +"2.16.840.1.113741.2": { "d": "intelCDSA", "c": "Intel CDSA" }, +"2.16.840.1.114412.1": { "d": "digiCertNonEVCerts", "c": "Digicert CA policy" }, +"2.16.840.1.114412.1.1": { "d": "digiCertOVCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.1.2": { "d": "digiCertDVCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.1.11": { "d": "digiCertFederatedDeviceCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.1.3.0.1": { "d": "digiCertGlobalCAPolicy", "c": "Digicert CA policy" }, +"2.16.840.1.114412.1.3.0.2": { "d": "digiCertHighAssuranceEVCAPolicy", "c": "Digicert CA policy" }, +"2.16.840.1.114412.1.3.0.3": { "d": "digiCertGlobalRootCAPolicy", "c": "Digicert CA policy" }, +"2.16.840.1.114412.1.3.0.4": { "d": "digiCertAssuredIDRootCAPolicy", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.2": { "d": "digiCertEVCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.3": { "d": "digiCertObjectSigningCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.3.1": { "d": "digiCertCodeSigningCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.3.2": { "d": "digiCertEVCodeSigningCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.3.11": { "d": "digiCertKernelCodeSigningCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.3.21": { "d": "digiCertDocumentSigningCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.4": { "d": "digiCertClientCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.4.1.1": { "d": "digiCertLevel1PersonalClientCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.4.1.2": { "d": "digiCertLevel1EnterpriseClientCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.4.2": { "d": "digiCertLevel2ClientCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.4.3.1": { "d": "digiCertLevel3USClientCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.4.3.2": { "d": "digiCertLevel3CBPClientCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.4.4.1": { "d": "digiCertLevel4USClientCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.4.4.2": { "d": "digiCertLevel4CBPClientCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.4.5.1": { "d": "digiCertPIVHardwareCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.4.5.2": { "d": "digiCertPIVCardAuthCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.2.4.5.3": { "d": "digiCertPIVContentSigningCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.4.31": { "d": "digiCertGridClassicCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.4.31.5": { "d": "digiCertGridIntegratedCert", "c": "Digicert CA policy" }, +"2.16.840.1.114412.31.4.31.1": { "d": "digiCertGridHostCert", "c": "Digicert CA policy" }, +"2.23.42.0": { "d": "contentType", "c": "SET" }, +"2.23.42.0.0": { "d": "panData", "c": "SET contentType" }, +"2.23.42.0.1": { "d": "panToken", "c": "SET contentType" }, +"2.23.42.0.2": { "d": "panOnly", "c": "SET contentType" }, +"2.23.42.1": { "d": "msgExt", "c": "SET" }, +"2.23.42.2": { "d": "field", "c": "SET" }, +"2.23.42.2.0": { "d": "fullName", "c": "SET field" }, +"2.23.42.2.1": { "d": "givenName", "c": "SET field" }, +"2.23.42.2.2": { "d": "familyName", "c": "SET field" }, +"2.23.42.2.3": { "d": "birthFamilyName", "c": "SET field" }, +"2.23.42.2.4": { "d": "placeName", "c": "SET field" }, +"2.23.42.2.5": { "d": "identificationNumber", "c": "SET field" }, +"2.23.42.2.6": { "d": "month", "c": "SET field" }, +"2.23.42.2.7": { "d": "date", "c": "SET field" }, +"2.23.42.2.8": { "d": "address", "c": "SET field" }, +"2.23.42.2.9": { "d": "telephone", "c": "SET field" }, +"2.23.42.2.10": { "d": "amount", "c": "SET field" }, +"2.23.42.2.11": { "d": "accountNumber", "c": "SET field" }, +"2.23.42.2.12": { "d": "passPhrase", "c": "SET field" }, +"2.23.42.3": { "d": "attribute", "c": "SET" }, +"2.23.42.3.0": { "d": "cert", "c": "SET attribute" }, +"2.23.42.3.0.0": { "d": "rootKeyThumb", "c": "SET cert attribute" }, +"2.23.42.3.0.1": { "d": "additionalPolicy", "c": "SET cert attribute" }, +"2.23.42.4": { "d": "algorithm", "c": "SET" }, +"2.23.42.5": { "d": "policy", "c": "SET" }, +"2.23.42.5.0": { "d": "root", "c": "SET policy" }, +"2.23.42.6": { "d": "module", "c": "SET" }, +"2.23.42.7": { "d": "certExt", "c": "SET" }, +"2.23.42.7.0": { "d": "hashedRootKey", "c": "SET cert extension" }, +"2.23.42.7.1": { "d": "certificateType", "c": "SET cert extension" }, +"2.23.42.7.2": { "d": "merchantData", "c": "SET cert extension" }, +"2.23.42.7.3": { "d": "cardCertRequired", "c": "SET cert extension" }, +"2.23.42.7.4": { "d": "tunneling", "c": "SET cert extension" }, +"2.23.42.7.5": { "d": "setExtensions", "c": "SET cert extension" }, +"2.23.42.7.6": { "d": "setQualifier", "c": "SET cert extension" }, +"2.23.42.8": { "d": "brand", "c": "SET" }, +"2.23.42.8.1": { "d": "IATA-ATA", "c": "SET brand" }, +"2.23.42.8.4": { "d": "VISA", "c": "SET brand" }, +"2.23.42.8.5": { "d": "MasterCard", "c": "SET brand" }, +"2.23.42.8.30": { "d": "Diners", "c": "SET brand" }, +"2.23.42.8.34": { "d": "AmericanExpress", "c": "SET brand" }, +"2.23.42.8.6011": { "d": "Novus", "c": "SET brand" }, +"2.23.42.9": { "d": "vendor", "c": "SET" }, +"2.23.42.9.0": { "d": "GlobeSet", "c": "SET vendor" }, +"2.23.42.9.1": { "d": "IBM", "c": "SET vendor" }, +"2.23.42.9.2": { "d": "CyberCash", "c": "SET vendor" }, +"2.23.42.9.3": { "d": "Terisa", "c": "SET vendor" }, +"2.23.42.9.4": { "d": "RSADSI", "c": "SET vendor" }, +"2.23.42.9.5": { "d": "VeriFone", "c": "SET vendor" }, +"2.23.42.9.6": { "d": "TrinTech", "c": "SET vendor" }, +"2.23.42.9.7": { "d": "BankGate", "c": "SET vendor" }, +"2.23.42.9.8": { "d": "GTE", "c": "SET vendor" }, +"2.23.42.9.9": { "d": "CompuSource", "c": "SET vendor" }, +"2.23.42.9.10": { "d": "Griffin", "c": "SET vendor" }, +"2.23.42.9.11": { "d": "Certicom", "c": "SET vendor" }, +"2.23.42.9.12": { "d": "OSS", "c": "SET vendor" }, +"2.23.42.9.13": { "d": "TenthMountain", "c": "SET vendor" }, +"2.23.42.9.14": { "d": "Antares", "c": "SET vendor" }, +"2.23.42.9.15": { "d": "ECC", "c": "SET vendor" }, +"2.23.42.9.16": { "d": "Maithean", "c": "SET vendor" }, +"2.23.42.9.17": { "d": "Netscape", "c": "SET vendor" }, +"2.23.42.9.18": { "d": "Verisign", "c": "SET vendor" }, +"2.23.42.9.19": { "d": "BlueMoney", "c": "SET vendor" }, +"2.23.42.9.20": { "d": "Lacerte", "c": "SET vendor" }, +"2.23.42.9.21": { "d": "Fujitsu", "c": "SET vendor" }, +"2.23.42.9.22": { "d": "eLab", "c": "SET vendor" }, +"2.23.42.9.23": { "d": "Entrust", "c": "SET vendor" }, +"2.23.42.9.24": { "d": "VIAnet", "c": "SET vendor" }, +"2.23.42.9.25": { "d": "III", "c": "SET vendor" }, +"2.23.42.9.26": { "d": "OpenMarket", "c": "SET vendor" }, +"2.23.42.9.27": { "d": "Lexem", "c": "SET vendor" }, +"2.23.42.9.28": { "d": "Intertrader", "c": "SET vendor" }, +"2.23.42.9.29": { "d": "Persimmon", "c": "SET vendor" }, +"2.23.42.9.30": { "d": "NABLE", "c": "SET vendor" }, +"2.23.42.9.31": { "d": "espace-net", "c": "SET vendor" }, +"2.23.42.9.32": { "d": "Hitachi", "c": "SET vendor" }, +"2.23.42.9.33": { "d": "Microsoft", "c": "SET vendor" }, +"2.23.42.9.34": { "d": "NEC", "c": "SET vendor" }, +"2.23.42.9.35": { "d": "Mitsubishi", "c": "SET vendor" }, +"2.23.42.9.36": { "d": "NCR", "c": "SET vendor" }, +"2.23.42.9.37": { "d": "e-COMM", "c": "SET vendor" }, +"2.23.42.9.38": { "d": "Gemplus", "c": "SET vendor" }, +"2.23.42.10": { "d": "national", "c": "SET" }, +"2.23.42.10.392": { "d": "Japan", "c": "SET national" }, +"2.23.43.1.4": { "d": "wTLS-ECC", "c": "WAP WTLS" }, +"2.23.43.1.4.1": { "d": "wTLS-ECC-curve1", "c": "WAP WTLS" }, +"2.23.43.1.4.6": { "d": "wTLS-ECC-curve6", "c": "WAP WTLS" }, +"2.23.43.1.4.8": { "d": "wTLS-ECC-curve8", "c": "WAP WTLS" }, +"2.23.43.1.4.9": { "d": "wTLS-ECC-curve9", "c": "WAP WTLS" }, +"2.23.133": { "d": "tCPA", "c": "TCPA" }, +"2.23.133.1": { "d": "tcpaSpecVersion", "c": "TCPA" }, +"2.23.133.2": { "d": "tcpaAttribute", "c": "TCPA" }, +"2.23.133.2.1": { "d": "tcpaTpmManufacturer", "c": "TCPA Attribute" }, +"2.23.133.2.2": { "d": "tcpaTpmModel", "c": "TCPA Attribute" }, +"2.23.133.2.3": { "d": "tcpaTpmVersion", "c": "TCPA Attribute" }, +"2.23.133.2.4": { "d": "tcpaPlatformManufacturer", "c": "TCPA Attribute" }, +"2.23.133.2.5": { "d": "tcpaPlatformModel", "c": "TCPA Attribute" }, +"2.23.133.2.6": { "d": "tcpaPlatformVersion", "c": "TCPA Attribute" }, +"2.23.133.2.7": { "d": "tcpaComponentManufacturer", "c": "TCPA Attribute" }, +"2.23.133.2.8": { "d": "tcpaComponentModel", "c": "TCPA Attribute" }, +"2.23.133.2.9": { "d": "tcpaComponentVersion", "c": "TCPA Attribute" }, +"2.23.133.2.10": { "d": "tcpaSecurityQualities", "c": "TCPA Attribute" }, +"2.23.133.2.11": { "d": "tcpaTpmProtectionProfile", "c": "TCPA Attribute" }, +"2.23.133.2.12": { "d": "tcpaTpmSecurityTarget", "c": "TCPA Attribute" }, +"2.23.133.2.13": { "d": "tcpaFoundationProtectionProfile", "c": "TCPA Attribute" }, +"2.23.133.2.14": { "d": "tcpaFoundationSecurityTarget", "c": "TCPA Attribute" }, +"2.23.133.2.15": { "d": "tcpaTpmIdLabel", "c": "TCPA Attribute" }, +"2.23.133.3": { "d": "tcpaProtocol", "c": "TCPA" }, +"2.23.133.3.1": { "d": "tcpaPrttTpmIdProtocol", "c": "TCPA Protocol" }, +"2.23.134.1.4.2.1": { "d": "postSignumRootQCA", "c": "PostSignum CA" }, +"2.23.134.1.2.2.3": { "d": "postSignumPublicCA", "c": "PostSignum CA" }, +"2.23.134.1.2.1.8.210": { "d": "postSignumCommercialServerPolicy", "c": "PostSignum CA" }, +"2.23.136.1.1.1": { "d": "mRTDSignatureData", "c": "ICAO MRTD" }, +"2.54.1775.2": { "d": "hashedRootKey", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.3": { "d": "certificateType", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.4": { "d": "merchantData", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.5": { "d": "cardCertRequired", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.6": { "d": "tunneling", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.7": { "d": "setQualifier", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"2.54.1775.99": { "d": "setData", "c": "SET. Deprecated, use (2 23 42 7 0) instead", "w": true }, +"1.2.40.0.17.1.22": { "d": "A-Trust EV policy", "c": "A-Trust CA Root" }, +"1.3.6.1.4.1.34697.2.1": { "d": "AffirmTrust EV policy", "c": "AffirmTrust Commercial" }, +"1.3.6.1.4.1.34697.2.2": { "d": "AffirmTrust EV policy", "c": "AffirmTrust Networking" }, +"1.3.6.1.4.1.34697.2.3": { "d": "AffirmTrust EV policy", "c": "AffirmTrust Premium" }, +"1.3.6.1.4.1.34697.2.4": { "d": "AffirmTrust EV policy", "c": "AffirmTrust Premium ECC" }, +"2.16.578.1.26.1.3.3": { "d": "BuyPass EV policy", "c": "BuyPass Class 3 EV" }, +"1.3.6.1.4.1.17326.10.14.2.1.2": { "d": "Camerfirma EV policy", "c": "Camerfirma CA Root" }, +"1.3.6.1.4.1.17326.10.8.12.1.2": { "d": "Camerfirma EV policy", "c": "Camerfirma CA Root" }, +"1.3.6.1.4.1.22234.2.5.2.3.1": { "d": "CertPlus EV policy", "c": "CertPlus Class 2 Primary CA (formerly Keynectis)" }, +"1.3.6.1.4.1.6449.1.2.1.5.1": { "d": "Comodo EV policy", "c": "COMODO Certification Authority" }, +"1.3.6.1.4.1.6334.1.100.1": { "d": "Cybertrust EV policy", "c": "Cybertrust Global Root (now Verizon Business)" }, +"1.3.6.1.4.1.4788.2.202.1": { "d": "D-TRUST EV policy", "c": "D-TRUST Root Class 3 CA 2 EV 2009" }, +"2.16.840.1.114412.2.1": { "d": "DigiCert EV policy", "c": "DigiCert High Assurance EV Root CA" }, +"2.16.528.1.1001.1.1.1.12.6.1.1.1": { "d": "DigiNotar EV policy", "c": "DigiNotar Root CA" }, +"2.16.840.1.114028.10.1.2": { "d": "Entrust EV policy", "c": "Entrust Root Certification Authority" }, +"1.3.6.1.4.1.14370.1.6": { "d": "GeoTrust EV policy", "c": "GeoTrust Primary Certification Authority (formerly Equifax)" }, +"1.3.6.1.4.1.4146.1.1": { "d": "GlobalSign EV policy", "c": "GlobalSign" }, +"2.16.840.1.114413.1.7.23.3": { "d": "GoDaddy EV policy", "c": "GoDaddy Class 2 Certification Authority (formerly ValiCert)" }, +"1.3.6.1.4.1.14777.6.1.1": { "d": "Izenpe EV policy", "c": "Certificado de Servidor Seguro SSL EV" }, +"1.3.6.1.4.1.14777.6.1.2": { "d": "Izenpe EV policy", "c": "Certificado de Sede Electronica EV" }, +"1.3.6.1.4.1.782.1.2.1.8.1": { "d": "Network Solutions EV policy", "c": "Network Solutions Certificate Authority" }, +"1.3.6.1.4.1.8024.0.2.100.1.2": { "d": "QuoVadis EV policy", "c": "QuoVadis Root CA 2" }, +"1.2.392.200091.100.721.1": { "d": "Security Communication (SECOM) EV policy", "c": "Security Communication RootCA1" }, +"2.16.840.1.114414.1.7.23.3": { "d": "Starfield EV policy", "c": "Starfield Class 2 Certification Authority" }, +"1.3.6.1.4.1.23223.1.1.1": { "d": "StartCom EV policy", "c": "StartCom Certification Authority" }, +"2.16.756.1.89.1.2.1.1": { "d": "SwissSign EV policy", "c": "SwissSign Gold CA - G2" }, +"1.3.6.1.4.1.7879.13.24.1": { "d": "T-TeleSec EV policy", "c": "T-TeleSec GlobalRoot Class 3" }, +"2.16.840.1.113733.1.7.48.1": { "d": "Thawte EV policy", "c": "Thawte Premium Server CA" }, +"2.16.840.1.114404.1.1.2.4.1": { "d": "TrustWave EV policy", "c": "TrustWave CA, formerly SecureTrust, before that XRamp" }, +"1.3.6.1.4.1.40869.1.1.22.3": { "d": "TWCA EV policy", "c": "TWCA Root Certification Authority" }, +"2.16.840.1.113733.1.7.23.6": { "d": "VeriSign EV policy", "c": "VeriSign Class 3 Public Primary Certification Authority" }, +"2.16.840.1.114171.500.9": { "d": "Wells Fargo EV policy", "c": "Wells Fargo WellsSecure Public Root Certificate Authority" }, +"END": "" +} \ No newline at end of file From 9f75ce2a7ee5bb0a8a3d306ea69af512857a69cf Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Nov 2018 16:38:17 +0200 Subject: [PATCH 0185/1938] added sketch for loading OID's descriptions from file --- client/crypto/asn1dump.c | 90 +++++++++++++++++++++++++++++++++------- client/emv/emvjson.c | 17 ++++++++ client/emv/emvjson.h | 1 + 3 files changed, 92 insertions(+), 16 deletions(-) diff --git a/client/crypto/asn1dump.c b/client/crypto/asn1dump.c index 4241899f6..610196563 100644 --- a/client/crypto/asn1dump.c +++ b/client/crypto/asn1dump.c @@ -11,10 +11,12 @@ #include "asn1dump.h" #include #include +#include #include #include #include "emv/emv_tags.h" #include "emv/dump.h" +#include "emv/emvjson.h" #include "util.h" #define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, " ");} @@ -214,6 +216,57 @@ static void asn1_tag_dump_integer(const struct tlv *tlv, const struct asn1_tag * fprintf(f, "\tvalue: %lu\n", asn1_value_integer(tlv, 0, tlv->len * 2)); } +static char *asn1_oid_description(const char *oid, bool with_group_desc) { + static char res[300]; + memset(res, 0x00, sizeof(res)); + +/* + strcpy(fname, get_my_executable_directory()); + strcat(fname, cjsonname); + if (access(fname, F_OK) != -1) { + root = json_load_file(fname, 0, &error); + if (!root) { + PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); + *err = true; + return NULL; + } + +*/ + + + + json_error_t error; + char fname[] = "crypto/oids.json"; + json_t *root = json_load_file(fname, 0, &error); + + if (!root || !json_is_object(root)) { + goto error; + } + + json_t *elm = json_object_get(root, oid); + if (!elm) { + goto error; + } + + if (JsonLoadStr(elm, "$.d", res)) + goto error; + + char strext[300] = {0}; + if (!JsonLoadStr(elm, "$.c", strext)) { + strcat(res, " ("); + strcat(res, strext); + strcat(res, ")"); + } + + json_decref(root); + return res; + +error: + if (root) + json_decref(root); + return NULL; +} + static void asn1_tag_dump_object_id(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level) { PRINT_INDENT(level); mbedtls_asn1_buf asn1_buf; @@ -222,23 +275,28 @@ static void asn1_tag_dump_object_id(const struct tlv *tlv, const struct asn1_tag char pstr[300]; mbedtls_oid_get_numeric_string(pstr, sizeof(pstr), &asn1_buf); fprintf(f, " %s", pstr); - const char *ppstr; - mbedtls_oid_get_attr_short_name(&asn1_buf, &ppstr); - if (ppstr && strnlen(ppstr, 1)) { - fprintf(f, " (%s)\n", ppstr); - return; - } - mbedtls_oid_get_sig_alg_desc(&asn1_buf, &ppstr); - if (ppstr && strnlen(ppstr, 1)) { - fprintf(f, " (%s)\n", ppstr); - return; - } - mbedtls_oid_get_extended_key_usage(&asn1_buf, &ppstr); - if (ppstr && strnlen(ppstr, 1)) { - fprintf(f, " (%s)\n", ppstr); - return; - } + char *jsondesc = asn1_oid_description(pstr, true); + if (jsondesc) { + fprintf(f, " - %s", jsondesc); + } else { + const char *ppstr; + mbedtls_oid_get_attr_short_name(&asn1_buf, &ppstr); + if (ppstr && strnlen(ppstr, 1)) { + fprintf(f, " (%s)\n", ppstr); + return; + } + mbedtls_oid_get_sig_alg_desc(&asn1_buf, &ppstr); + if (ppstr && strnlen(ppstr, 1)) { + fprintf(f, " (%s)\n", ppstr); + return; + } + mbedtls_oid_get_extended_key_usage(&asn1_buf, &ppstr); + if (ppstr && strnlen(ppstr, 1)) { + fprintf(f, " (%s)\n", ppstr); + return; + } + } fprintf(f, "\n"); } diff --git a/client/emv/emvjson.c b/client/emv/emvjson.c index e56ecbb71..116e16da1 100644 --- a/client/emv/emvjson.c +++ b/client/emv/emvjson.c @@ -264,6 +264,23 @@ bool HexToBuffer(const char *errormsg, const char *hexvalue, uint8_t * buffer, s return true; } +int JsonLoadStr(json_t *root, char *path, char *value) { + if (!value) + return 1; + + json_t *jelm = json_path_get((const json_t *)root, path); + if (!jelm || !json_is_string(jelm)) + return 2; + + const char * strval = json_string_value(jelm); + if (!strval) + return 1; + + memcpy(value, strval, strlen(strval)); + + return 0; +} + int JsonLoadBufAsHex(json_t *elm, char *path, uint8_t *data, size_t maxbufferlen, size_t *datalen) { if (datalen) *datalen = 0; diff --git a/client/emv/emvjson.h b/client/emv/emvjson.h index 9c6eda5ea..996b611d5 100644 --- a/client/emv/emvjson.h +++ b/client/emv/emvjson.h @@ -33,6 +33,7 @@ extern int JsonSaveTLVTreeElm(json_t *elm, char *path, struct tlvdb *tlvdbelm, b extern int JsonSaveTLVTree(json_t *root, json_t *elm, char *path, struct tlvdb *tlvdbelm); +extern int JsonLoadStr(json_t *root, char *path, char *value); extern int JsonLoadBufAsHex(json_t *elm, char *path, uint8_t *data, size_t maxbufferlen, size_t *datalen); extern bool ParamLoadFromJson(struct tlvdb *tlv); From 638890cb6a40f6f8a7cb0ed4d556455917ada405 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Nov 2018 17:15:37 +0200 Subject: [PATCH 0186/1938] asn.1 description from json works --- client/crypto/asn1dump.c | 29 ++++++++++++++--------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/client/crypto/asn1dump.c b/client/crypto/asn1dump.c index 610196563..26d2ba737 100644 --- a/client/crypto/asn1dump.c +++ b/client/crypto/asn1dump.c @@ -11,6 +11,8 @@ #include "asn1dump.h" #include #include +#include +#include #include #include #include @@ -18,6 +20,7 @@ #include "emv/dump.h" #include "emv/emvjson.h" #include "util.h" +#include "proxmark3.h" #define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, " ");} @@ -217,26 +220,22 @@ static void asn1_tag_dump_integer(const struct tlv *tlv, const struct asn1_tag * } static char *asn1_oid_description(const char *oid, bool with_group_desc) { + json_error_t error; + char fname[300] = {0}; static char res[300]; memset(res, 0x00, sizeof(res)); -/* + strcpy(fname, get_my_executable_directory()); + strcat(fname, "crypto/oids.json"); + if (access(fname, F_OK) < 0) { strcpy(fname, get_my_executable_directory()); - strcat(fname, cjsonname); - if (access(fname, F_OK) != -1) { - root = json_load_file(fname, 0, &error); - if (!root) { - PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); - *err = true; - return NULL; - } - -*/ - - + strcat(fname, "oids.json"); + if (access(fname, F_OK) < 0) { + goto error; // file not found + } + } - json_error_t error; - char fname[] = "crypto/oids.json"; + // load `oids.json` json_t *root = json_load_file(fname, 0, &error); if (!root || !json_is_object(root)) { From 164b64a61166728fa08d479c6abf4aa85910a42b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Nov 2018 17:42:41 +0200 Subject: [PATCH 0187/1938] add some OIDs from Yubikey --- client/crypto/oids.json | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/client/crypto/oids.json b/client/crypto/oids.json index 9f65fb34b..75d963d3f 100644 --- a/client/crypto/oids.json +++ b/client/crypto/oids.json @@ -1,6 +1,12 @@ { "copyright": "https://www.cs.auckland.ac.nz/~pgut001/dumpasn1.cfg", +"1.3.6.1.4.1.41482": { "d": "Yubico", "c": "FIDO Alliance" }, +"1.3.6.1.4.1.45724": { "d": "FIDO Alliance, Inc.", "c": "FIDO Alliance" }, +"1.3.6.1.4.1.41482.2": { "d": "Device ID", "c": "Yubico" }, +"1.3.6.1.4.1.45724.2.1.1": { "d": "FIDO U2F Transports", "c": "FIDO Alliance" }, +"1.3.6.1.4.1.45724.1.1.4": { "d": "Authenticator Attestation GUID", "c": "FIDO Alliance" }, + "0.2.262.1.10": { "d": "Telesec", "c": "Deutsche Telekom" }, "0.2.262.1.10.0": { "d": "extension", "c": "Telesec" }, "0.2.262.1.10.1": { "d": "mechanism", "c": "Telesec" }, From 736840cce776f05fb9402dad94ecf805fe1c7f02 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Nov 2018 18:14:45 +0200 Subject: [PATCH 0188/1938] fix integer representation --- client/crypto/asn1dump.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/client/crypto/asn1dump.c b/client/crypto/asn1dump.c index 26d2ba737..60799fc8c 100644 --- a/client/crypto/asn1dump.c +++ b/client/crypto/asn1dump.c @@ -216,11 +216,19 @@ static void asn1_tag_dump_boolean(const struct tlv *tlv, const struct asn1_tag * static void asn1_tag_dump_integer(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level) { PRINT_INDENT(level); + if (tlv->len == 4) { + int32_t val = 0; + for (int i = 0; i < tlv->len; i++) + val = (val << 8) + tlv->value[i]; + fprintf(f, "\tvalue4b: %d\n", val); + return; + } fprintf(f, "\tvalue: %lu\n", asn1_value_integer(tlv, 0, tlv->len * 2)); } static char *asn1_oid_description(const char *oid, bool with_group_desc) { json_error_t error; + json_t *root = NULL; char fname[300] = {0}; static char res[300]; memset(res, 0x00, sizeof(res)); @@ -236,7 +244,7 @@ static char *asn1_oid_description(const char *oid, bool with_group_desc) { } // load `oids.json` - json_t *root = json_load_file(fname, 0, &error); + root = json_load_file(fname, 0, &error); if (!root || !json_is_object(root)) { goto error; From da6e2ea7c1fe08c9cf2738f227b2078d02945852 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Nov 2018 18:20:37 +0200 Subject: [PATCH 0189/1938] added to `hf fido reg` option `-t` to show DER certificate in TLV --- client/cmdhffido.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 5151709af..d0ca4322a 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -209,6 +209,7 @@ int CmdHFFidoRegister(const char *cmd) { arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"), + arg_lit0("tT", "tlv", "Show DER certificate contents in TLV representation"), arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."), arg_str0(NULL, NULL, "", NULL), arg_str0(NULL, NULL, "", NULL), @@ -220,10 +221,11 @@ int CmdHFFidoRegister(const char *cmd) { bool verbose = arg_get_lit(2); bool verbose2 = arg_get_lit(2) > 1; bool paramsPlain = arg_get_lit(3); + bool showDERTLV = arg_get_lit(4); char fname[250] = {0}; bool err; - root = OpenJson(4, fname, argtable, &err); + root = OpenJson(5, fname, argtable, &err); if(err) return 1; if (root) { @@ -234,13 +236,13 @@ int CmdHFFidoRegister(const char *cmd) { if (paramsPlain) { memset(cdata, 0x00, 32); - CLIGetStrWithReturn(5, cdata, &chlen); + CLIGetStrWithReturn(6, cdata, &chlen); if (chlen && chlen > 16) { PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", chlen); return 1; } } else { - CLIGetHexWithReturn(5, cdata, &chlen); + CLIGetHexWithReturn(6, cdata, &chlen); if (chlen && chlen != 32) { PrintAndLog("ERROR: challenge parameter length must be 32 bytes only."); return 1; @@ -252,13 +254,13 @@ int CmdHFFidoRegister(const char *cmd) { if (paramsPlain) { memset(adata, 0x00, 32); - CLIGetStrWithReturn(6, adata, &applen); + CLIGetStrWithReturn(7, adata, &applen); if (applen && applen > 16) { PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", applen); return 1; } } else { - CLIGetHexWithReturn(6, adata, &applen); + CLIGetHexWithReturn(7, adata, &applen); if (applen && applen != 32) { PrintAndLog("ERROR: application parameter length must be 32 bytes only."); return 1; @@ -340,9 +342,11 @@ int CmdHFFidoRegister(const char *cmd) { uint8_t public_key[65] = {0}; // TODO: print DER certificate in DER view - PrintAndLog("----------------DER TLV-----------------"); - asn1_print(&buf[derp], derLen, " "); - PrintAndLog("----------------DER TLV-----------------"); + if (showDERTLV) { + PrintAndLog("----------------DER TLV-----------------"); + asn1_print(&buf[derp], derLen, " "); + PrintAndLog("----------------DER TLV-----------------"); + } // load CA's mbedtls_x509_crt cacert; From f4c21da26b10a98b2096ef32d13e22a90986d87e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Nov 2018 18:35:13 +0200 Subject: [PATCH 0190/1938] small fix --- client/cmdhffido.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index d0ca4322a..039384ba0 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -341,7 +341,7 @@ int CmdHFFidoRegister(const char *cmd) { // check and print DER certificate uint8_t public_key[65] = {0}; - // TODO: print DER certificate in DER view + // print DER certificate in DER view if (showDERTLV) { PrintAndLog("----------------DER TLV-----------------"); asn1_print(&buf[derp], derLen, " "); From 89e2f391ca20e7e41941e631d95b03e0f71f0a8f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 15 Nov 2018 18:42:22 +0200 Subject: [PATCH 0191/1938] small fix --- client/cmdhffido.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 039384ba0..e2d6c0917 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -341,7 +341,7 @@ int CmdHFFidoRegister(const char *cmd) { // check and print DER certificate uint8_t public_key[65] = {0}; - // print DER certificate in DER view + // print DER certificate in TLV view if (showDERTLV) { PrintAndLog("----------------DER TLV-----------------"); asn1_print(&buf[derp], derLen, " "); From fd1c0cac79c7aa9052ffbe28e23bb170fa2897e5 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 16 Nov 2018 02:52:42 +0100 Subject: [PATCH 0192/1938] FIX: 'standalone mode MattyRun' - compiles and should even work CHG: 'standalone mode' - generic banner for each mode. Updated the ledshow to @cjbrigato --- armsrc/Makefile | 4 +- armsrc/Standalone/hf_bog.c | 10 +- armsrc/Standalone/hf_colin.c | 10 +- armsrc/Standalone/hf_mattyrun.c | 217 ++++++++++++++++++++++++++----- armsrc/Standalone/hf_mattyrun.h | 1 + armsrc/Standalone/hf_young.c | 1 + armsrc/Standalone/lf_hidbrute.c | 1 + armsrc/Standalone/lf_proxbrute.c | 1 + armsrc/Standalone/lf_samyrun.c | 1 + armsrc/appmain.c | 21 ++- 10 files changed, 210 insertions(+), 57 deletions(-) diff --git a/armsrc/Makefile b/armsrc/Makefile index a2092ac0b..b69e724e0 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -23,9 +23,9 @@ APP_CFLAGS = -DWITH_CRC \ -DWITH_FELICA \ -DWITH_FLASH \ -DWITH_SMARTCARD \ + -DWITH_FPC \ -DWITH_HFSNOOP \ -DWITH_LF_SAMYRUN \ - -DWITH_FPC \ -fno-strict-aliasing -ffunction-sections -fdata-sections ### IMPORTANT - move the commented variable below this line @@ -39,7 +39,7 @@ APP_CFLAGS = -DWITH_CRC \ # -DWITH_LF_PROXBRUTE # -DWITH_LF_HIDBRUTE # -DWITH_HF_YOUNG -# -DWITH_HF_MATTYRUN +# -DWITH_HF_MATTYRUN - # -DWITH_HF_COLIN # -DWITH_HF_BOG diff --git a/armsrc/Standalone/hf_bog.c b/armsrc/Standalone/hf_bog.c index 1cf9a7c51..9079d5df3 100644 --- a/armsrc/Standalone/hf_bog.c +++ b/armsrc/Standalone/hf_bog.c @@ -280,16 +280,11 @@ void RAMFUNC SniffAndStore(uint8_t param) { void RunMod() { + StandAloneMode(); + Dbprintf(">> Bogiton 14a Sniff UL/UL-EV1/NTAG a.k.a BogitoRun Started <<"); Dbprintf("Starting to sniff"); - SpinDown(50); - SpinOff(50); - SpinUp(50); - SpinOff(50); - SpinDown(50); - SpinDelay(500); - // param: // bit 0 - trigger from first card answer // bit 1 - trigger from first reader 7-bit request @@ -297,4 +292,5 @@ void RunMod() { LEDsoff(); SpinDelay(300); Dbprintf("- [ End ] -> You can take shell back ..."); + Dbprintf("- [ ! ] -> use 'script run read_pwd_mem' to print passwords"); } diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index 31519080a..2eabd68d9 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -210,12 +210,14 @@ void WriteTagToFlash(uint8_t index, size_t size) void RunMod() { + StandAloneMode(); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + currline = 20; curlline = 20; currfline = 24; memset(cjuid, 0, sizeof(cjuid)); cjcuid = 0; - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); uint8_t sectorsCnt = (MF1KSZ / MF1KSZSIZE); uint64_t key64; // Defines current key uint8_t *keyBlock = NULL; // Where the keys will be held in memory. @@ -348,12 +350,6 @@ ACCBITS : 796788[00]+VALUE currfline = 24; cjSetCursLeft(); - SpinDown(50); - SpinOff(50); - SpinUp(50); - SpinOff(50); - SpinDown(50); - failtag: vtsend_cursor_position_save(NULL); diff --git a/armsrc/Standalone/hf_mattyrun.c b/armsrc/Standalone/hf_mattyrun.c index e83d13a1d..78f197383 100644 --- a/armsrc/Standalone/hf_mattyrun.c +++ b/armsrc/Standalone/hf_mattyrun.c @@ -35,8 +35,189 @@ on a blank card. #include "hf_mattyrun.h" +uint8_t uid[10]; +uint32_t cuid; + +//----------------------------------------------------------------------------- +// Matt's StandAlone mod. +// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn) +//----------------------------------------------------------------------------- +static int saMifareCSetBlock(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) +{ + // params + uint8_t needWipe = arg0; + // bit 0 - need get UID + // bit 1 - need wupC + // bit 2 - need HALT after sequence + // bit 3 - need init FPGA and field before sequence + // bit 4 - need reset FPGA and LED + uint8_t workFlags = arg1; + uint8_t blockNo = arg2; + + // card commands + uint8_t wupC1[] = {0x40}; + uint8_t wupC2[] = {0x43}; + uint8_t wipeC[] = {0x41}; + + // variables + byte_t isOK = 0; + uint8_t d_block[18] = {0x00}; + + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE]; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE]; + + // reset FPGA and LED + if (workFlags & 0x08) + { + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + set_tracing(false); + } + + while (true) + { + // get UID from chip + if (workFlags & 0x01) + { + if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) + { + DbprintfEx(FLAG_NOLOG, "Can't select card"); + break; + }; + + if (mifare_classic_halt(NULL, cuid)) + { + DbprintfEx(FLAG_NOLOG, "Halt error"); + break; + }; + }; + + // reset chip + if (needWipe) + { + ReaderTransmitBitsPar(wupC1, 7, 0, NULL); + if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) + { + DbprintfEx(FLAG_NOLOG, "wupC1 error"); + break; + }; + + ReaderTransmit(wipeC, sizeof(wipeC), NULL); + if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) + { + DbprintfEx(FLAG_NOLOG, "wipeC error"); + break; + }; + + if (mifare_classic_halt(NULL, cuid)) + { + DbprintfEx(FLAG_NOLOG, "Halt error"); + break; + }; + }; + + // chaud + // write block + if (workFlags & 0x02) + { + ReaderTransmitBitsPar(wupC1, 7, 0, NULL); + if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) + { + DbprintfEx(FLAG_NOLOG, "wupC1 error"); + break; + }; + + ReaderTransmit(wupC2, sizeof(wupC2), NULL); + if (!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) + { + DbprintfEx(FLAG_NOLOG, "wupC2 errorv"); + break; + }; + } + + if ((mifare_sendcmd_short(NULL, 0, 0xA0, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) + { + DbprintfEx(FLAG_NOLOG, "write block send command error"); + break; + }; + + memcpy(d_block, datain, 16); + AddCrc14A(d_block, 16); + ReaderTransmit(d_block, sizeof(d_block), NULL); + if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) + { + DbprintfEx(FLAG_NOLOG, "write block send data error"); + break; + }; + + if (workFlags & 0x04) + { + if (mifare_classic_halt(NULL, cuid)) + { + DbprintfEx(FLAG_NOLOG, "Halt error"); + break; + }; + } + + isOK = 1; + break; + } + + if ((workFlags & 0x10) || (!isOK)) + { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + } + + return isOK; +} + +/* the chk function is a piwi’ed(tm) check that will try all keys for +a particular sector. also no tracing no dbg */ +static int saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, uint8_t keyCount, uint8_t *datain, uint64_t *key) +{ + MF_DBGLEVEL = MF_DBG_NONE; + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + set_tracing(false); + + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + + for (int i = 0; i < keyCount; ++i) + { + + /* no need for anticollision. just verify tag is still here */ + // if (!iso14443a_fast_select_card(cjuid, 0)) { + if (!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) + { + DbprintfEx(FLAG_NOLOG, "FATAL : E_MF_LOSTTAG"); + return -1; + } + + uint64_t ui64Key = bytes_to_num(datain + i * 6, 6); + if (mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) + { + uint8_t dummy_answer = 0; + ReaderTransmit(&dummy_answer, 1, NULL); + // wait for the card to become ready again + SpinDelayUs(AUTHENTICATION_TIMEOUT); + continue; + } + crypto1_destroy(pcs); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + *key = ui64Key; + return i; + } + crypto1_destroy(pcs); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + return -1; +} + + void RunMod() { StandAloneMode(); + Dbprintf(">> Matty mifare chk/dump/sim a.k.a MattyRun Started <<"); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); /* It will check if the keys from the attacked tag are a subset from @@ -51,15 +232,13 @@ void RunMod() { If you're using the proxmark connected to a device that has an OS, and you're not using the proxmark3 client to see the debug messages, you MUST uncomment usb_disable(). */ - - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - // usb_disable(); // Comment this line if you want to see debug messages. - + + // Comment this line below if you want to see debug messages. + // usb_disable(); /* Pseudo-configuration block. */ - char keyTypec = '?'; // 'A'/'B' or both keys '?' bool printKeys = false; // Prints keys bool transferToEml = true; // Transfer keys to emulator memory bool ecfill = true; // Fill emulator memory with cards content. @@ -71,7 +250,7 @@ void RunMod() { uint8_t sectorSize = 64; // 1k's sector size is 64 bytes. uint8_t blockNo = 3; // Security block is number 3 for each sector. uint8_t sectorsCnt = (mifare_size/sectorSize); - uint8_t keyType; // Keytype buffer + uint8_t keyType = 2; // Keytype buffer uint64_t key64; // Defines current key uint8_t *keyBlock = NULL; // Where the keys will be held in memory. uint8_t stKeyBlock = 20; // Set the quantity of keys in the block. @@ -108,24 +287,6 @@ void RunMod() { num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t*)(keyBlock + mfKeyCounter * 6)); } - /* - Simple switch just to handle keytpes. - */ - switch (keyTypec) { - case 'a': case 'A': - keyType = !0; - break; - case 'b': case 'B': - keyType = !1; - break; - case '?': - keyType = 2; - break; - default: - Dbprintf("[!] Key type must be A , B or ?"); - keyType = 2; - } - /* Pretty print of the keys to be checked. */ @@ -191,16 +352,14 @@ void RunMod() { } /* - TODO: This. - - - If at least one key was found, start a nested attack based on that key, and continue. - + TODO: - Get UID from tag and set accordingly in emulator memory and call mifare1ksim with right flags (iceman) */ if (!allKeysFound && keyFound) { Dbprintf("\t✕ There's currently no nested attack in MattyRun, sorry!"); LED_C_ON(); //red LED_A_ON(); //yellow + // no room to run nested attack on device (iceman) // Do nested attack, set allKeysFound = true; // allKeysFound = true; } else { @@ -250,7 +409,7 @@ void RunMod() { LED_B_ON(); // green // assuming arg0==0, use hardcoded uid 0xdeadbeaf - Mifare1ksim( 0, 0, 0, NULL); + Mifare1ksim( FLAG_4B_UID_IN_DATA | FLAG_UID_IN_EMUL, 0, 0, uid); LED_B_OFF(); /* diff --git a/armsrc/Standalone/hf_mattyrun.h b/armsrc/Standalone/hf_mattyrun.h index 508954998..9bf2166ab 100644 --- a/armsrc/Standalone/hf_mattyrun.h +++ b/armsrc/Standalone/hf_mattyrun.h @@ -16,6 +16,7 @@ #include "standalone.h" // standalone definitions #include "apps.h" // debugstatements, lfops? #include "usb_cmd.h" // mifare1ksim flags +#include "mifareutil.h" #define OPTS 2 diff --git a/armsrc/Standalone/hf_young.c b/armsrc/Standalone/hf_young.c index ef41bc64d..f4bc3db4f 100644 --- a/armsrc/Standalone/hf_young.c +++ b/armsrc/Standalone/hf_young.c @@ -20,6 +20,7 @@ typedef struct { void RunMod() { StandAloneMode(); + Dbprintf(">> Craig Young Mifare sniff UID/clone uid 2 magic/sim a.k.a YoungRun Started <<"); FpgaDownloadAndGo(FPGA_BITSTREAM_HF); int selected = 0, playing = 0, iGotoRecord = 0, iGotoClone = 0; diff --git a/armsrc/Standalone/lf_hidbrute.c b/armsrc/Standalone/lf_hidbrute.c index 7ec3aba28..8c6b85f4f 100644 --- a/armsrc/Standalone/lf_hidbrute.c +++ b/armsrc/Standalone/lf_hidbrute.c @@ -29,6 +29,7 @@ // samy's sniff and repeat routine for LF void RunMod() { StandAloneMode(); + Dbprintf(">> LF HID corporate bruteforce a.k.a CorporateBrute Started <<"); FpgaDownloadAndGo(FPGA_BITSTREAM_LF); uint32_t high[OPTS], low[OPTS]; diff --git a/armsrc/Standalone/lf_proxbrute.c b/armsrc/Standalone/lf_proxbrute.c index e0c998d31..69b5f5331 100644 --- a/armsrc/Standalone/lf_proxbrute.c +++ b/armsrc/Standalone/lf_proxbrute.c @@ -14,6 +14,7 @@ // samy's sniff and repeat routine for LF void RunMod() { StandAloneMode(); + Dbprintf(">> LF HID proxII bruteforce a.k.a ProxBrute Started (Brad Antoniewicz) <<"); FpgaDownloadAndGo(FPGA_BITSTREAM_LF); uint32_t high[OPTS], low[OPTS]; diff --git a/armsrc/Standalone/lf_samyrun.c b/armsrc/Standalone/lf_samyrun.c index 88b6e9b15..c94d5fc42 100644 --- a/armsrc/Standalone/lf_samyrun.c +++ b/armsrc/Standalone/lf_samyrun.c @@ -13,6 +13,7 @@ // samy's sniff and repeat routine for LF void RunMod() { StandAloneMode(); + Dbprintf(">> LF HID Read/Clone/Sim a.k.a SamyRun Started <<"); FpgaDownloadAndGo(FPGA_BITSTREAM_LF); uint32_t high[OPTS], low[OPTS]; diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 2a3ae823a..a3b330e84 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -415,22 +415,19 @@ void SendStatus(void) { void StandAloneMode(void) { DbpString("Stand-alone mode! No PC necessary."); - // Oooh pretty -- notify user we're in elite samy mode now - LED(LED_RED, 200); - LED(LED_ORANGE, 200); - LED(LED_GREEN, 200); - LED(LED_ORANGE, 200); - LED(LED_RED, 200); - LED(LED_ORANGE, 200); - LED(LED_GREEN, 200); - LED(LED_ORANGE, 200); - LED(LED_RED, 200); + + SpinDown(50); + SpinOff(50); + SpinUp(50); + SpinOff(50); + SpinDown(50); + SpinDelay(500); } // detection of which Standalone Modes is installed // (iceman) void printStandAloneModes(void) { - DbpString("Installed StandAlone Mods"); + DbpString("Installed StandAlone Mode"); #if defined(WITH_LF_ICERUN) DbpString(" LF sniff/clone/simulation - aka IceRun (iceman)"); @@ -445,7 +442,7 @@ void printStandAloneModes(void) { DbpString(" LF HID ProxII bruteforce - aka Proxbrute (Brad Antoniewicz)"); #endif #if defined(WITH_LF_HIDBRUTE) - DbpString(" LF HID corporate 1000 bruteforce - (Federico dotta & Maurizio Agazzini)"); + DbpString(" LF HID corporate 1000 bruteforce - aka Corporatebrute (Federico dotta & Maurizio Agazzini)"); #endif #if defined(WITH_HF_MATTYRUN) DbpString(" HF Mifare sniff/clone - aka MattyRun (Matías A. Ré Medina)"); From f8c0ec53bd0a9b8782e6532c7fdc218fbb9d109f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 16 Nov 2018 17:05:48 +0200 Subject: [PATCH 0193/1938] added tinycbor --- client/tinycbor/Makefile | 46 + client/tinycbor/cbor.h | 606 +++++++ client/tinycbor/cborencoder.c | 645 ++++++++ .../cborencoder_close_container_checked.c | 57 + client/tinycbor/cborerrorstrings.c | 182 +++ client/tinycbor/cborinternal_p.h | 161 ++ client/tinycbor/cborjson.h | 62 + client/tinycbor/cborparser.c | 1430 +++++++++++++++++ client/tinycbor/cborparser_dup_string.c | 119 ++ client/tinycbor/cborpretty.c | 578 +++++++ client/tinycbor/cborpretty_stdio.c | 87 + client/tinycbor/cbortojson.c | 699 ++++++++ client/tinycbor/cborvalidation.c | 666 ++++++++ client/tinycbor/compilersupport_p.h | 205 +++ client/tinycbor/open_memstream.c | 114 ++ client/tinycbor/tinycbor-version.h | 3 + client/tinycbor/utf8_p.h | 104 ++ 17 files changed, 5764 insertions(+) create mode 100644 client/tinycbor/Makefile create mode 100644 client/tinycbor/cbor.h create mode 100644 client/tinycbor/cborencoder.c create mode 100644 client/tinycbor/cborencoder_close_container_checked.c create mode 100644 client/tinycbor/cborerrorstrings.c create mode 100644 client/tinycbor/cborinternal_p.h create mode 100644 client/tinycbor/cborjson.h create mode 100644 client/tinycbor/cborparser.c create mode 100644 client/tinycbor/cborparser_dup_string.c create mode 100644 client/tinycbor/cborpretty.c create mode 100644 client/tinycbor/cborpretty_stdio.c create mode 100644 client/tinycbor/cbortojson.c create mode 100644 client/tinycbor/cborvalidation.c create mode 100644 client/tinycbor/compilersupport_p.h create mode 100644 client/tinycbor/open_memstream.c create mode 100644 client/tinycbor/tinycbor-version.h create mode 100644 client/tinycbor/utf8_p.h diff --git a/client/tinycbor/Makefile b/client/tinycbor/Makefile new file mode 100644 index 000000000..31fb327cb --- /dev/null +++ b/client/tinycbor/Makefile @@ -0,0 +1,46 @@ + +LIB_A = tinycbor.a +tinycbor_SOURCES = \ + cborencoder.c \ + cborencoder_close_container_checked.c \ + cborerrorstrings.c \ + cborparser.c \ + cborparser_dup_string.c \ + cborpretty.c \ + cbortojson.c \ + cborvalidation.c \ + +CFILES = $(filter %.c, $(tinycbor_SOURCES)) +CMDOBJS = $(CFILES:%.c=%.o) +CLEAN = $(CMDOBJS) + +CC= gcc +CFLAGS= -O2 -Wall -Wno-unused-variable -Wno-unused-function +LIBS= -lm $(SYSLIBS) $(MYLIBS) +DEFAULT_INCLUDES = -I. -I.. +DEFS = -DHAVE_STDINT_H + +AR= ar rcs +RANLIB= ranlib +RM= rm -f +TST= echo + +SYSLDFLAGS= +SYSLIBS= + +MYLIBS= +MYOBJS= + +all: $(CMDOBJS) + $(AR) $(LIB_A) $(CMDOBJS) + $(RANLIB) $(LIB_A) + +clean: + $(RM) $(CLEAN) + $(RM) $(LIB_A) + +%.o: %.c + $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(CFLAGS) -c -o $@ $< $(LIBS) + +.PHONY: all clean + diff --git a/client/tinycbor/cbor.h b/client/tinycbor/cbor.h new file mode 100644 index 000000000..fd145be2e --- /dev/null +++ b/client/tinycbor/cbor.h @@ -0,0 +1,606 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Intel Corporation +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +#ifndef CBOR_H +#define CBOR_H + +#ifndef assert +#include +#endif +#include +#include +#include +#include +#include + +#include "tinycbor-version.h" + +#define TINYCBOR_VERSION ((TINYCBOR_VERSION_MAJOR << 16) | (TINYCBOR_VERSION_MINOR << 8) | TINYCBOR_VERSION_PATCH) + +#ifdef __cplusplus +extern "C" { +#else +#include +#endif + +#ifndef SIZE_MAX +/* Some systems fail to define SIZE_MAX in , even though C99 requires it... + * Conversion from signed to unsigned is defined in 6.3.1.3 (Signed and unsigned integers) p2, + * which says: "the value is converted by repeatedly adding or subtracting one more than the + * maximum value that can be represented in the new type until the value is in the range of the + * new type." + * So -1 gets converted to size_t by adding SIZE_MAX + 1, which results in SIZE_MAX. + */ +# define SIZE_MAX ((size_t)-1) +#endif + +#ifndef CBOR_API +# define CBOR_API +#endif +#ifndef CBOR_PRIVATE_API +# define CBOR_PRIVATE_API +#endif +#ifndef CBOR_INLINE_API +# if defined(__cplusplus) +# define CBOR_INLINE inline +# define CBOR_INLINE_API inline +# else +# define CBOR_INLINE_API static CBOR_INLINE +# if defined(_MSC_VER) +# define CBOR_INLINE __inline +# elif defined(__GNUC__) +# define CBOR_INLINE __inline__ +# elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L +# define CBOR_INLINE inline +# else +# define CBOR_INLINE +# endif +# endif +#endif + +typedef enum CborType { + CborIntegerType = 0x00, + CborByteStringType = 0x40, + CborTextStringType = 0x60, + CborArrayType = 0x80, + CborMapType = 0xa0, + CborTagType = 0xc0, + CborSimpleType = 0xe0, + CborBooleanType = 0xf5, + CborNullType = 0xf6, + CborUndefinedType = 0xf7, + CborHalfFloatType = 0xf9, + CborFloatType = 0xfa, + CborDoubleType = 0xfb, + + CborInvalidType = 0xff /* equivalent to the break byte, so it will never be used */ +} CborType; + +typedef uint64_t CborTag; +typedef enum CborKnownTags { + CborDateTimeStringTag = 0, + CborUnixTime_tTag = 1, + CborPositiveBignumTag = 2, + CborNegativeBignumTag = 3, + CborDecimalTag = 4, + CborBigfloatTag = 5, + CborCOSE_Encrypt0Tag = 16, + CborCOSE_Mac0Tag = 17, + CborCOSE_Sign1Tag = 18, + CborExpectedBase64urlTag = 21, + CborExpectedBase64Tag = 22, + CborExpectedBase16Tag = 23, + CborEncodedCborTag = 24, + CborUrlTag = 32, + CborBase64urlTag = 33, + CborBase64Tag = 34, + CborRegularExpressionTag = 35, + CborMimeMessageTag = 36, + CborCOSE_EncryptTag = 96, + CborCOSE_MacTag = 97, + CborCOSE_SignTag = 98, + CborSignatureTag = 55799 +} CborKnownTags; + +/* #define the constants so we can check with #ifdef */ +#define CborDateTimeStringTag CborDateTimeStringTag +#define CborUnixTime_tTag CborUnixTime_tTag +#define CborPositiveBignumTag CborPositiveBignumTag +#define CborNegativeBignumTag CborNegativeBignumTag +#define CborDecimalTag CborDecimalTag +#define CborBigfloatTag CborBigfloatTag +#define CborCOSE_Encrypt0Tag CborCOSE_Encrypt0Tag +#define CborCOSE_Mac0Tag CborCOSE_Mac0Tag +#define CborCOSE_Sign1Tag CborCOSE_Sign1Tag +#define CborExpectedBase64urlTag CborExpectedBase64urlTag +#define CborExpectedBase64Tag CborExpectedBase64Tag +#define CborExpectedBase16Tag CborExpectedBase16Tag +#define CborEncodedCborTag CborEncodedCborTag +#define CborUrlTag CborUrlTag +#define CborBase64urlTag CborBase64urlTag +#define CborBase64Tag CborBase64Tag +#define CborRegularExpressionTag CborRegularExpressionTag +#define CborMimeMessageTag CborMimeMessageTag +#define CborCOSE_EncryptTag CborCOSE_EncryptTag +#define CborCOSE_MacTag CborCOSE_MacTag +#define CborCOSE_SignTag CborCOSE_SignTag +#define CborSignatureTag CborSignatureTag + +/* Error API */ + +typedef enum CborError { + CborNoError = 0, + + /* errors in all modes */ + CborUnknownError, + CborErrorUnknownLength, /* request for length in array, map, or string with indeterminate length */ + CborErrorAdvancePastEOF, + CborErrorIO, + + /* parser errors streaming errors */ + CborErrorGarbageAtEnd = 256, + CborErrorUnexpectedEOF, + CborErrorUnexpectedBreak, + CborErrorUnknownType, /* can only happen in major type 7 */ + CborErrorIllegalType, /* type not allowed here */ + CborErrorIllegalNumber, + CborErrorIllegalSimpleType, /* types of value less than 32 encoded in two bytes */ + + /* parser errors in strict mode parsing only */ + CborErrorUnknownSimpleType = 512, + CborErrorUnknownTag, + CborErrorInappropriateTagForType, + CborErrorDuplicateObjectKeys, + CborErrorInvalidUtf8TextString, + CborErrorExcludedType, + CborErrorExcludedValue, + CborErrorImproperValue, + CborErrorOverlongEncoding, + CborErrorMapKeyNotString, + CborErrorMapNotSorted, + CborErrorMapKeysNotUnique, + + /* encoder errors */ + CborErrorTooManyItems = 768, + CborErrorTooFewItems, + + /* internal implementation errors */ + CborErrorDataTooLarge = 1024, + CborErrorNestingTooDeep, + CborErrorUnsupportedType, + + /* errors in converting to JSON */ + CborErrorJsonObjectKeyIsAggregate = 1280, + CborErrorJsonObjectKeyNotString, + CborErrorJsonNotImplemented, + + CborErrorOutOfMemory = (int) (~0U / 2 + 1), + CborErrorInternalError = (int) (~0U / 2) /* INT_MAX on two's complement machines */ +} CborError; + +CBOR_API const char *cbor_error_string(CborError error); + +/* Encoder API */ +struct CborEncoder +{ + union { + uint8_t *ptr; + ptrdiff_t bytes_needed; + } data; + const uint8_t *end; + size_t remaining; + int flags; +}; +typedef struct CborEncoder CborEncoder; + +static const size_t CborIndefiniteLength = SIZE_MAX; + +CBOR_API void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags); +CBOR_API CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value); +CBOR_API CborError cbor_encode_int(CborEncoder *encoder, int64_t value); +CBOR_API CborError cbor_encode_negative_int(CborEncoder *encoder, uint64_t absolute_value); +CBOR_API CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value); +CBOR_API CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag); +CBOR_API CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length); +CBOR_INLINE_API CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string) +{ return cbor_encode_text_string(encoder, string, strlen(string)); } +CBOR_API CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length); +CBOR_API CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value); + +CBOR_INLINE_API CborError cbor_encode_boolean(CborEncoder *encoder, bool value) +{ return cbor_encode_simple_value(encoder, (int)value - 1 + (CborBooleanType & 0x1f)); } +CBOR_INLINE_API CborError cbor_encode_null(CborEncoder *encoder) +{ return cbor_encode_simple_value(encoder, CborNullType & 0x1f); } +CBOR_INLINE_API CborError cbor_encode_undefined(CborEncoder *encoder) +{ return cbor_encode_simple_value(encoder, CborUndefinedType & 0x1f); } + +CBOR_INLINE_API CborError cbor_encode_half_float(CborEncoder *encoder, const void *value) +{ return cbor_encode_floating_point(encoder, CborHalfFloatType, value); } +CBOR_INLINE_API CborError cbor_encode_float(CborEncoder *encoder, float value) +{ return cbor_encode_floating_point(encoder, CborFloatType, &value); } +CBOR_INLINE_API CborError cbor_encode_double(CborEncoder *encoder, double value) +{ return cbor_encode_floating_point(encoder, CborDoubleType, &value); } + +CBOR_API CborError cbor_encoder_create_array(CborEncoder *encoder, CborEncoder *arrayEncoder, size_t length); +CBOR_API CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder, size_t length); +CBOR_API CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder); +CBOR_API CborError cbor_encoder_close_container_checked(CborEncoder *encoder, const CborEncoder *containerEncoder); + +CBOR_INLINE_API uint8_t *_cbor_encoder_get_buffer_pointer(const CborEncoder *encoder) +{ + return encoder->data.ptr; +} + +CBOR_INLINE_API size_t cbor_encoder_get_buffer_size(const CborEncoder *encoder, const uint8_t *buffer) +{ + return (size_t)(encoder->data.ptr - buffer); +} + +CBOR_INLINE_API size_t cbor_encoder_get_extra_bytes_needed(const CborEncoder *encoder) +{ + return encoder->end ? 0 : (size_t)encoder->data.bytes_needed; +} + +/* Parser API */ + +enum CborParserIteratorFlags +{ + CborIteratorFlag_IntegerValueTooLarge = 0x01, + CborIteratorFlag_NegativeInteger = 0x02, + CborIteratorFlag_IteratingStringChunks = 0x02, + CborIteratorFlag_UnknownLength = 0x04, + CborIteratorFlag_ContainerIsMap = 0x20 +}; + +struct CborParser +{ + const uint8_t *end; + uint32_t flags; +}; +typedef struct CborParser CborParser; + +struct CborValue +{ + const CborParser *parser; + const uint8_t *ptr; + uint32_t remaining; + uint16_t extra; + uint8_t type; + uint8_t flags; +}; +typedef struct CborValue CborValue; + +CBOR_API CborError cbor_parser_init(const uint8_t *buffer, size_t size, uint32_t flags, CborParser *parser, CborValue *it); + +CBOR_API CborError cbor_value_validate_basic(const CborValue *it); + +CBOR_INLINE_API bool cbor_value_at_end(const CborValue *it) +{ return it->remaining == 0; } +CBOR_INLINE_API const uint8_t *cbor_value_get_next_byte(const CborValue *it) +{ return it->ptr; } +CBOR_API CborError cbor_value_advance_fixed(CborValue *it); +CBOR_API CborError cbor_value_advance(CborValue *it); +CBOR_INLINE_API bool cbor_value_is_container(const CborValue *it) +{ return it->type == CborArrayType || it->type == CborMapType; } +CBOR_API CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed); +CBOR_API CborError cbor_value_leave_container(CborValue *it, const CborValue *recursed); + +CBOR_PRIVATE_API uint64_t _cbor_value_decode_int64_internal(const CborValue *value); +CBOR_INLINE_API uint64_t _cbor_value_extract_int64_helper(const CborValue *value) +{ + return value->flags & CborIteratorFlag_IntegerValueTooLarge ? + _cbor_value_decode_int64_internal(value) : value->extra; +} + +CBOR_INLINE_API bool cbor_value_is_valid(const CborValue *value) +{ return value && value->type != CborInvalidType; } +CBOR_INLINE_API CborType cbor_value_get_type(const CborValue *value) +{ return (CborType)value->type; } + +/* Null & undefined type */ +CBOR_INLINE_API bool cbor_value_is_null(const CborValue *value) +{ return value->type == CborNullType; } +CBOR_INLINE_API bool cbor_value_is_undefined(const CborValue *value) +{ return value->type == CborUndefinedType; } + +/* Booleans */ +CBOR_INLINE_API bool cbor_value_is_boolean(const CborValue *value) +{ return value->type == CborBooleanType; } +CBOR_INLINE_API CborError cbor_value_get_boolean(const CborValue *value, bool *result) +{ + assert(cbor_value_is_boolean(value)); + *result = !!value->extra; + return CborNoError; +} + +/* Simple types */ +CBOR_INLINE_API bool cbor_value_is_simple_type(const CborValue *value) +{ return value->type == CborSimpleType; } +CBOR_INLINE_API CborError cbor_value_get_simple_type(const CborValue *value, uint8_t *result) +{ + assert(cbor_value_is_simple_type(value)); + *result = (uint8_t)value->extra; + return CborNoError; +} + +/* Integers */ +CBOR_INLINE_API bool cbor_value_is_integer(const CborValue *value) +{ return value->type == CborIntegerType; } +CBOR_INLINE_API bool cbor_value_is_unsigned_integer(const CborValue *value) +{ return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger) == 0; } +CBOR_INLINE_API bool cbor_value_is_negative_integer(const CborValue *value) +{ return cbor_value_is_integer(value) && (value->flags & CborIteratorFlag_NegativeInteger); } + +CBOR_INLINE_API CborError cbor_value_get_raw_integer(const CborValue *value, uint64_t *result) +{ + assert(cbor_value_is_integer(value)); + *result = _cbor_value_extract_int64_helper(value); + return CborNoError; +} + +CBOR_INLINE_API CborError cbor_value_get_uint64(const CborValue *value, uint64_t *result) +{ + assert(cbor_value_is_unsigned_integer(value)); + *result = _cbor_value_extract_int64_helper(value); + return CborNoError; +} + +CBOR_INLINE_API CborError cbor_value_get_int64(const CborValue *value, int64_t *result) +{ + assert(cbor_value_is_integer(value)); + *result = (int64_t) _cbor_value_extract_int64_helper(value); + if (value->flags & CborIteratorFlag_NegativeInteger) + *result = -*result - 1; + return CborNoError; +} + +CBOR_INLINE_API CborError cbor_value_get_int(const CborValue *value, int *result) +{ + assert(cbor_value_is_integer(value)); + *result = (int) _cbor_value_extract_int64_helper(value); + if (value->flags & CborIteratorFlag_NegativeInteger) + *result = -*result - 1; + return CborNoError; +} + +CBOR_API CborError cbor_value_get_int64_checked(const CborValue *value, int64_t *result); +CBOR_API CborError cbor_value_get_int_checked(const CborValue *value, int *result); + +CBOR_INLINE_API bool cbor_value_is_length_known(const CborValue *value) +{ return (value->flags & CborIteratorFlag_UnknownLength) == 0; } + +/* Tags */ +CBOR_INLINE_API bool cbor_value_is_tag(const CborValue *value) +{ return value->type == CborTagType; } +CBOR_INLINE_API CborError cbor_value_get_tag(const CborValue *value, CborTag *result) +{ + assert(cbor_value_is_tag(value)); + *result = _cbor_value_extract_int64_helper(value); + return CborNoError; +} +CBOR_API CborError cbor_value_skip_tag(CborValue *it); + +/* Strings */ +CBOR_INLINE_API bool cbor_value_is_byte_string(const CborValue *value) +{ return value->type == CborByteStringType; } +CBOR_INLINE_API bool cbor_value_is_text_string(const CborValue *value) +{ return value->type == CborTextStringType; } + +CBOR_INLINE_API CborError cbor_value_get_string_length(const CborValue *value, size_t *length) +{ + uint64_t v; + assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value)); + if (!cbor_value_is_length_known(value)) + return CborErrorUnknownLength; + v = _cbor_value_extract_int64_helper(value); + *length = (size_t)v; + if (*length != v) + return CborErrorDataTooLarge; + return CborNoError; +} + +CBOR_PRIVATE_API CborError _cbor_value_copy_string(const CborValue *value, void *buffer, + size_t *buflen, CborValue *next); +CBOR_PRIVATE_API CborError _cbor_value_dup_string(const CborValue *value, void **buffer, + size_t *buflen, CborValue *next); + +CBOR_API CborError cbor_value_calculate_string_length(const CborValue *value, size_t *length); + +CBOR_INLINE_API CborError cbor_value_copy_text_string(const CborValue *value, char *buffer, + size_t *buflen, CborValue *next) +{ + assert(cbor_value_is_text_string(value)); + return _cbor_value_copy_string(value, buffer, buflen, next); +} +CBOR_INLINE_API CborError cbor_value_copy_byte_string(const CborValue *value, uint8_t *buffer, + size_t *buflen, CborValue *next) +{ + assert(cbor_value_is_byte_string(value)); + return _cbor_value_copy_string(value, buffer, buflen, next); +} + +CBOR_INLINE_API CborError cbor_value_dup_text_string(const CborValue *value, char **buffer, + size_t *buflen, CborValue *next) +{ + assert(cbor_value_is_text_string(value)); + return _cbor_value_dup_string(value, (void **)buffer, buflen, next); +} +CBOR_INLINE_API CborError cbor_value_dup_byte_string(const CborValue *value, uint8_t **buffer, + size_t *buflen, CborValue *next) +{ + assert(cbor_value_is_byte_string(value)); + return _cbor_value_dup_string(value, (void **)buffer, buflen, next); +} + +CBOR_API CborError cbor_value_text_string_equals(const CborValue *value, const char *string, bool *result); + +/* Maps and arrays */ +CBOR_INLINE_API bool cbor_value_is_array(const CborValue *value) +{ return value->type == CborArrayType; } +CBOR_INLINE_API bool cbor_value_is_map(const CborValue *value) +{ return value->type == CborMapType; } + +CBOR_INLINE_API CborError cbor_value_get_array_length(const CborValue *value, size_t *length) +{ + uint64_t v; + assert(cbor_value_is_array(value)); + if (!cbor_value_is_length_known(value)) + return CborErrorUnknownLength; + v = _cbor_value_extract_int64_helper(value); + *length = (size_t)v; + if (*length != v) + return CborErrorDataTooLarge; + return CborNoError; +} + +CBOR_INLINE_API CborError cbor_value_get_map_length(const CborValue *value, size_t *length) +{ + uint64_t v; + assert(cbor_value_is_map(value)); + if (!cbor_value_is_length_known(value)) + return CborErrorUnknownLength; + v = _cbor_value_extract_int64_helper(value); + *length = (size_t)v; + if (*length != v) + return CborErrorDataTooLarge; + return CborNoError; +} + +CBOR_API CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element); + +/* Floating point */ +CBOR_INLINE_API bool cbor_value_is_half_float(const CborValue *value) +{ return value->type == CborHalfFloatType; } +CBOR_API CborError cbor_value_get_half_float(const CborValue *value, void *result); + +CBOR_INLINE_API bool cbor_value_is_float(const CborValue *value) +{ return value->type == CborFloatType; } +CBOR_INLINE_API CborError cbor_value_get_float(const CborValue *value, float *result) +{ + uint32_t data; + assert(cbor_value_is_float(value)); + assert(value->flags & CborIteratorFlag_IntegerValueTooLarge); + data = (uint32_t)_cbor_value_decode_int64_internal(value); + memcpy(result, &data, sizeof(*result)); + return CborNoError; +} + +CBOR_INLINE_API bool cbor_value_is_double(const CborValue *value) +{ return value->type == CborDoubleType; } +CBOR_INLINE_API CborError cbor_value_get_double(const CborValue *value, double *result) +{ + uint64_t data; + assert(cbor_value_is_double(value)); + assert(value->flags & CborIteratorFlag_IntegerValueTooLarge); + data = _cbor_value_decode_int64_internal(value); + memcpy(result, &data, sizeof(*result)); + return CborNoError; +} + +/* Validation API */ + +enum CborValidationFlags { + /* Bit mapping: + * bits 0-7 (8 bits): canonical format + * bits 8-11 (4 bits): canonical format & strict mode + * bits 12-20 (8 bits): strict mode + * bits 21-31 (10 bits): other + */ + + CborValidateShortestIntegrals = 0x0001, + CborValidateShortestFloatingPoint = 0x0002, + CborValidateShortestNumbers = CborValidateShortestIntegrals | CborValidateShortestFloatingPoint, + CborValidateNoIndeterminateLength = 0x0100, + CborValidateMapIsSorted = 0x0200 | CborValidateNoIndeterminateLength, + + CborValidateCanonicalFormat = 0x0fff, + + CborValidateMapKeysAreUnique = 0x1000 | CborValidateMapIsSorted, + CborValidateTagUse = 0x2000, + CborValidateUtf8 = 0x4000, + + CborValidateStrictMode = 0xfff00, + + CborValidateMapKeysAreString = 0x100000, + CborValidateNoUndefined = 0x200000, + CborValidateNoTags = 0x400000, + CborValidateFiniteFloatingPoint = 0x800000, + /* unused = 0x1000000, */ + /* unused = 0x2000000, */ + + CborValidateNoUnknownSimpleTypesSA = 0x4000000, + CborValidateNoUnknownSimpleTypes = 0x8000000 | CborValidateNoUnknownSimpleTypesSA, + CborValidateNoUnknownTagsSA = 0x10000000, + CborValidateNoUnknownTagsSR = 0x20000000 | CborValidateNoUnknownTagsSA, + CborValidateNoUnknownTags = 0x40000000 | CborValidateNoUnknownTagsSR, + + CborValidateCompleteData = (int)0x80000000, + + CborValidateStrictest = (int)~0U, + CborValidateBasic = 0 +}; + +CBOR_API CborError cbor_value_validate(const CborValue *it, uint32_t flags); + +/* Human-readable (dump) API */ + +enum CborPrettyFlags { + CborPrettyNumericEncodingIndicators = 0x01, + CborPrettyTextualEncodingIndicators = 0, + + CborPrettyIndicateIndeterminateLength = 0x02, + CborPrettyIndicateIndetermineLength = CborPrettyIndicateIndeterminateLength, /* deprecated */ + CborPrettyIndicateOverlongNumbers = 0x04, + + CborPrettyShowStringFragments = 0x100, + CborPrettyMergeStringFragments = 0, + + CborPrettyDefaultFlags = CborPrettyIndicateIndeterminateLength +}; + +typedef CborError (*CborStreamFunction)(void *token, const char *fmt, ...) +#ifdef __GNUC__ + __attribute__((__format__(printf, 2, 3))) +#endif +; + +CBOR_API CborError cbor_value_to_pretty_stream(CborStreamFunction streamFunction, void *token, CborValue *value, int flags); + +/* The following API requires a hosted C implementation (uses FILE*) */ +#if !defined(__STDC_HOSTED__) || __STDC_HOSTED__-0 == 1 +CBOR_API CborError cbor_value_to_pretty_advance_flags(FILE *out, CborValue *value, int flags); +CBOR_API CborError cbor_value_to_pretty_advance(FILE *out, CborValue *value); +CBOR_INLINE_API CborError cbor_value_to_pretty(FILE *out, const CborValue *value) +{ + CborValue copy = *value; + return cbor_value_to_pretty_advance_flags(out, ©, CborPrettyDefaultFlags); +} +#endif /* __STDC_HOSTED__ check */ + +#ifdef __cplusplus +} +#endif + +#endif /* CBOR_H */ + diff --git a/client/tinycbor/cborencoder.c b/client/tinycbor/cborencoder.c new file mode 100644 index 000000000..adb92fd88 --- /dev/null +++ b/client/tinycbor/cborencoder.c @@ -0,0 +1,645 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Intel Corporation +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +#ifndef _BSD_SOURCE +#define _BSD_SOURCE 1 +#endif +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE 1 +#endif +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS 1 +#endif + +#include "cbor.h" +#include "cborinternal_p.h" +#include "compilersupport_p.h" + +#include +#include + +/** + * \defgroup CborEncoding Encoding to CBOR + * \brief Group of functions used to encode data to CBOR. + * + * CborEncoder is used to encode data into a CBOR stream. The outermost + * CborEncoder is initialized by calling cbor_encoder_init(), with the buffer + * where the CBOR stream will be stored. The outermost CborEncoder is usually + * used to encode exactly one item, most often an array or map. It is possible + * to encode more than one item, but care must then be taken on the decoder + * side to ensure the state is reset after each item was decoded. + * + * Nested CborEncoder objects are created using cbor_encoder_create_array() and + * cbor_encoder_create_map(), later closed with cbor_encoder_close_container() + * or cbor_encoder_close_container_checked(). The pairs of creation and closing + * must be exactly matched and their parameters are always the same. + * + * CborEncoder writes directly to the user-supplied buffer, without extra + * buffering. CborEncoder does not allocate memory and CborEncoder objects are + * usually created on the stack of the encoding functions. + * + * The example below initializes a CborEncoder object with a buffer and encodes + * a single integer. + * + * \code + * uint8_t buf[16]; + * CborEncoder encoder; + * cbor_encoder_init(&encoder, &buf, sizeof(buf), 0); + * cbor_encode_int(&encoder, some_value); + * \endcode + * + * As explained before, usually the outermost CborEncoder object is used to add + * one array or map, which in turn contains multiple elements. The example + * below creates a CBOR map with one element: a key "foo" and a boolean value. + * + * \code + * uint8_t buf[16]; + * CborEncoder encoder, mapEncoder; + * cbor_encoder_init(&encoder, &buf, sizeof(buf), 0); + * cbor_encoder_create_map(&encoder, &mapEncoder, 1); + * cbor_encode_text_stringz(&mapEncoder, "foo"); + * cbor_encode_boolean(&mapEncoder, some_value); + * cbor_encoder_close_container(&encoder, &mapEncoder); + * \endcode + * + *

Error checking and buffer size

+ * + * All functions operating on CborEncoder return a condition of type CborError. + * If the encoding was successful, they return CborNoError. Some functions do + * extra checking on the input provided and may return some other error + * conditions (for example, cbor_encode_simple_value() checks that the type is + * of the correct type). + * + * In addition, all functions check whether the buffer has enough bytes to + * encode the item being appended. If that is not possible, they return + * CborErrorOutOfMemory. + * + * It is possible to continue with the encoding of data past the first function + * that returns CborErrorOutOfMemory. CborEncoder functions will not overrun + * the buffer, but will instead count how many more bytes are needed to + * complete the encoding. At the end, you can obtain that count by calling + * cbor_encoder_get_extra_bytes_needed(). + * + * \section1 Finalizing the encoding + * + * Once all items have been appended and the containers have all been properly + * closed, the user-supplied buffer will contain the CBOR stream and may be + * immediately used. To obtain the size of the buffer, call + * cbor_encoder_get_buffer_size() with the original buffer pointer. + * + * The example below illustrates how one can encode an item with error checking + * and then pass on the buffer for network sending. + * + * \code + * uint8_t buf[16]; + * CborError err; + * CborEncoder encoder, mapEncoder; + * cbor_encoder_init(&encoder, &buf, sizeof(buf), 0); + * err = cbor_encoder_create_map(&encoder, &mapEncoder, 1); + * if (!err) + * return err; + * err = cbor_encode_text_stringz(&mapEncoder, "foo"); + * if (!err) + * return err; + * err = cbor_encode_boolean(&mapEncoder, some_value); + * if (!err) + * return err; + * err = cbor_encoder_close_container_checked(&encoder, &mapEncoder); + * if (!err) + * return err; + * + * size_t len = cbor_encoder_get_buffer_size(&encoder, buf); + * send_payload(buf, len); + * return CborNoError; + * \endcode + * + * Finally, the example below expands on the one above and also + * deals with dynamically growing the buffer if the initial allocation wasn't + * big enough. Note the two places where the error checking was replaced with + * an cbor_assertion, showing where the author assumes no error can occur. + * + * \code + * uint8_t *encode_string_array(const char **strings, int n, size_t *bufsize) + * { + * CborError err; + * CborEncoder encoder, arrayEncoder; + * size_t size = 256; + * uint8_t *buf = NULL; + * + * while (1) { + * int i; + * size_t more_bytes; + * uint8_t *nbuf = realloc(buf, size); + * if (nbuf == NULL) + * goto error; + * buf = nbuf; + * + * cbor_encoder_init(&encoder, &buf, size, 0); + * err = cbor_encoder_create_array(&encoder, &arrayEncoder, n); + * cbor_assert(err); // can't fail, the buffer is always big enough + * + * for (i = 0; i < n; ++i) { + * err = cbor_encode_text_stringz(&arrayEncoder, strings[i]); + * if (err && err != CborErrorOutOfMemory) + * goto error; + * } + * + * err = cbor_encoder_close_container_checked(&encoder, &arrayEncoder); + * cbor_assert(err); // shouldn't fail! + * + * more_bytes = cbor_encoder_get_extra_bytes_needed(encoder); + * if (more_size) { + * // buffer wasn't big enough, try again + * size += more_bytes; + * continue; + * } + * + * *bufsize = cbor_encoder_get_buffer_size(encoder, buf); + * return buf; + * } + * error: + * free(buf); + * return NULL; + * } + * \endcode + */ + +/** + * \addtogroup CborEncoding + * @{ + */ + +/** + * \struct CborEncoder + * Structure used to encode to CBOR. + */ + +/** + * Initializes a CborEncoder structure \a encoder by pointing it to buffer \a + * buffer of size \a size. The \a flags field is currently unused and must be + * zero. + */ +void cbor_encoder_init(CborEncoder *encoder, uint8_t *buffer, size_t size, int flags) +{ + encoder->data.ptr = buffer; + encoder->end = buffer + size; + encoder->remaining = 2; + encoder->flags = flags; +} + +static inline void put16(void *where, uint16_t v) +{ + v = cbor_htons(v); + memcpy(where, &v, sizeof(v)); +} + +/* Note: Since this is currently only used in situations where OOM is the only + * valid error, we KNOW this to be true. Thus, this function now returns just 'true', + * but if in the future, any function starts returning a non-OOM error, this will need + * to be changed to the test. At the moment, this is done to prevent more branches + * being created in the tinycbor output */ +static inline bool isOomError(CborError err) +{ + (void) err; + return true; +} + +static inline void put32(void *where, uint32_t v) +{ + v = cbor_htonl(v); + memcpy(where, &v, sizeof(v)); +} + +static inline void put64(void *where, uint64_t v) +{ + v = cbor_htonll(v); + memcpy(where, &v, sizeof(v)); +} + +static inline bool would_overflow(CborEncoder *encoder, size_t len) +{ + ptrdiff_t remaining = (ptrdiff_t)encoder->end; + remaining -= remaining ? (ptrdiff_t)encoder->data.ptr : encoder->data.bytes_needed; + remaining -= (ptrdiff_t)len; + return unlikely(remaining < 0); +} + +static inline void advance_ptr(CborEncoder *encoder, size_t n) +{ + if (encoder->end) + encoder->data.ptr += n; + else + encoder->data.bytes_needed += n; +} + +static inline CborError append_to_buffer(CborEncoder *encoder, const void *data, size_t len) +{ + if (would_overflow(encoder, len)) { + if (encoder->end != NULL) { + len -= encoder->end - encoder->data.ptr; + encoder->end = NULL; + encoder->data.bytes_needed = 0; + } + + advance_ptr(encoder, len); + return CborErrorOutOfMemory; + } + + memcpy(encoder->data.ptr, data, len); + encoder->data.ptr += len; + return CborNoError; +} + +static inline CborError append_byte_to_buffer(CborEncoder *encoder, uint8_t byte) +{ + return append_to_buffer(encoder, &byte, 1); +} + +static inline CborError encode_number_no_update(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType) +{ + /* Little-endian would have been so much more convenient here: + * We could just write at the beginning of buf but append_to_buffer + * only the necessary bytes. + * Since it has to be big endian, do it the other way around: + * write from the end. */ + uint64_t buf[2]; + uint8_t *const bufend = (uint8_t *)buf + sizeof(buf); + uint8_t *bufstart = bufend - 1; + put64(buf + 1, ui); /* we probably have a bunch of zeros in the beginning */ + + if (ui < Value8Bit) { + *bufstart += shiftedMajorType; + } else { + uint8_t more = 0; + if (ui > 0xffU) + ++more; + if (ui > 0xffffU) + ++more; + if (ui > 0xffffffffU) + ++more; + bufstart -= (size_t)1 << more; + *bufstart = shiftedMajorType + Value8Bit + more; + } + + return append_to_buffer(encoder, bufstart, bufend - bufstart); +} + +static inline void saturated_decrement(CborEncoder *encoder) +{ + if (encoder->remaining) + --encoder->remaining; +} + +static inline CborError encode_number(CborEncoder *encoder, uint64_t ui, uint8_t shiftedMajorType) +{ + saturated_decrement(encoder); + return encode_number_no_update(encoder, ui, shiftedMajorType); +} + +/** + * Appends the unsigned 64-bit integer \a value to the CBOR stream provided by + * \a encoder. + * + * \sa cbor_encode_negative_int, cbor_encode_int + */ +CborError cbor_encode_uint(CborEncoder *encoder, uint64_t value) +{ + return encode_number(encoder, value, UnsignedIntegerType << MajorTypeShift); +} + +/** + * Appends the negative 64-bit integer whose absolute value is \a + * absolute_value to the CBOR stream provided by \a encoder. + * + * If the value \a absolute_value is zero, this function encodes -2^64. + * + * \sa cbor_encode_uint, cbor_encode_int + */ +CborError cbor_encode_negative_int(CborEncoder *encoder, uint64_t absolute_value) +{ + return encode_number(encoder, absolute_value - 1, NegativeIntegerType << MajorTypeShift); +} + +/** + * Appends the signed 64-bit integer \a value to the CBOR stream provided by + * \a encoder. + * + * \sa cbor_encode_negative_int, cbor_encode_uint + */ +CborError cbor_encode_int(CborEncoder *encoder, int64_t value) +{ + /* adapted from code in RFC 7049 appendix C (pseudocode) */ + uint64_t ui = value >> 63; /* extend sign to whole length */ + uint8_t majorType = ui & 0x20; /* extract major type */ + ui ^= value; /* complement negatives */ + return encode_number(encoder, ui, majorType); +} + +/** + * Appends the CBOR Simple Type of value \a value to the CBOR stream provided by + * \a encoder. + * + * This function may return error CborErrorIllegalSimpleType if the \a value + * variable contains a number that is not a valid simple type. + */ +CborError cbor_encode_simple_value(CborEncoder *encoder, uint8_t value) +{ +#ifndef CBOR_ENCODER_NO_CHECK_USER + /* check if this is a valid simple type */ + if (value >= HalfPrecisionFloat && value <= Break) + return CborErrorIllegalSimpleType; +#endif + return encode_number(encoder, value, SimpleTypesType << MajorTypeShift); +} + +/** + * Appends the floating-point value of type \a fpType and pointed to by \a + * value to the CBOR stream provided by \a encoder. The value of \a fpType must + * be one of CborHalfFloatType, CborFloatType or CborDoubleType, otherwise the + * behavior of this function is undefined. + * + * This function is useful for code that needs to pass through floating point + * values but does not wish to have the actual floating-point code. + * + * \sa cbor_encode_half_float, cbor_encode_float, cbor_encode_double + */ +CborError cbor_encode_floating_point(CborEncoder *encoder, CborType fpType, const void *value) +{ + unsigned size; + uint8_t buf[1 + sizeof(uint64_t)]; + cbor_assert(fpType == CborHalfFloatType || fpType == CborFloatType || fpType == CborDoubleType); + buf[0] = fpType; + + size = 2U << (fpType - CborHalfFloatType); + if (size == 8) + put64(buf + 1, *(const uint64_t*)value); + else if (size == 4) + put32(buf + 1, *(const uint32_t*)value); + else + put16(buf + 1, *(const uint16_t*)value); + saturated_decrement(encoder); + return append_to_buffer(encoder, buf, size + 1); +} + +/** + * Appends the CBOR tag \a tag to the CBOR stream provided by \a encoder. + * + * \sa CborTag + */ +CborError cbor_encode_tag(CborEncoder *encoder, CborTag tag) +{ + /* tags don't count towards the number of elements in an array or map */ + return encode_number_no_update(encoder, tag, TagType << MajorTypeShift); +} + +static CborError encode_string(CborEncoder *encoder, size_t length, uint8_t shiftedMajorType, const void *string) +{ + CborError err = encode_number(encoder, length, shiftedMajorType); + if (err && !isOomError(err)) + return err; + return append_to_buffer(encoder, string, length); +} + +/** + * \fn CborError cbor_encode_text_stringz(CborEncoder *encoder, const char *string) + * + * Appends the null-terminated text string \a string to the CBOR stream + * provided by \a encoder. CBOR requires that \a string be valid UTF-8, but + * TinyCBOR makes no verification of correctness. The terminating null is not + * included in the stream. + * + * \sa cbor_encode_text_string, cbor_encode_byte_string + */ + +/** + * Appends the text string \a string of length \a length to the CBOR stream + * provided by \a encoder. CBOR requires that \a string be valid UTF-8, but + * TinyCBOR makes no verification of correctness. + * + * \sa CborError cbor_encode_text_stringz, cbor_encode_byte_string + */ +CborError cbor_encode_byte_string(CborEncoder *encoder, const uint8_t *string, size_t length) +{ + return encode_string(encoder, length, ByteStringType << MajorTypeShift, string); +} + +/** + * Appends the byte string \a string of length \a length to the CBOR stream + * provided by \a encoder. CBOR byte strings are arbitrary raw data. + * + * \sa cbor_encode_text_stringz, cbor_encode_text_string + */ +CborError cbor_encode_text_string(CborEncoder *encoder, const char *string, size_t length) +{ + return encode_string(encoder, length, TextStringType << MajorTypeShift, string); +} + +#ifdef __GNUC__ +__attribute__((noinline)) +#endif +static CborError create_container(CborEncoder *encoder, CborEncoder *container, size_t length, uint8_t shiftedMajorType) +{ + CborError err; + container->data.ptr = encoder->data.ptr; + container->end = encoder->end; + saturated_decrement(encoder); + container->remaining = length + 1; /* overflow ok on CborIndefiniteLength */ + + cbor_static_assert(((MapType << MajorTypeShift) & CborIteratorFlag_ContainerIsMap) == CborIteratorFlag_ContainerIsMap); + cbor_static_assert(((ArrayType << MajorTypeShift) & CborIteratorFlag_ContainerIsMap) == 0); + container->flags = shiftedMajorType & CborIteratorFlag_ContainerIsMap; + + if (length == CborIndefiniteLength) { + container->flags |= CborIteratorFlag_UnknownLength; + err = append_byte_to_buffer(container, shiftedMajorType + IndefiniteLength); + } else { + if (shiftedMajorType & CborIteratorFlag_ContainerIsMap) + container->remaining += length; + err = encode_number_no_update(container, length, shiftedMajorType); + } + return err; +} + +/** + * Creates a CBOR array in the CBOR stream provided by \a encoder and + * initializes \a arrayEncoder so that items can be added to the array using + * the CborEncoder functions. The array must be terminated by calling either + * cbor_encoder_close_container() or cbor_encoder_close_container_checked() + * with the same \a encoder and \a arrayEncoder parameters. + * + * The number of items inserted into the array must be exactly \a length items, + * otherwise the stream is invalid. If the number of items is not known when + * creating the array, the constant \ref CborIndefiniteLength may be passed as + * length instead. + * + * \sa cbor_encoder_create_map + */ +CborError cbor_encoder_create_array(CborEncoder *encoder, CborEncoder *arrayEncoder, size_t length) +{ + return create_container(encoder, arrayEncoder, length, ArrayType << MajorTypeShift); +} + +/** + * Creates a CBOR map in the CBOR stream provided by \a encoder and + * initializes \a mapEncoder so that items can be added to the map using + * the CborEncoder functions. The map must be terminated by calling either + * cbor_encoder_close_container() or cbor_encoder_close_container_checked() + * with the same \a encoder and \a mapEncoder parameters. + * + * The number of pair of items inserted into the map must be exactly \a length + * items, otherwise the stream is invalid. If the number is not known + * when creating the map, the constant \ref CborIndefiniteLength may be passed as + * length instead. + * + * \b{Implementation limitation:} TinyCBOR cannot encode more than SIZE_MAX/2 + * key-value pairs in the stream. If the length \a length is larger than this + * value (and is not \ref CborIndefiniteLength), this function returns error + * CborErrorDataTooLarge. + * + * \sa cbor_encoder_create_array + */ +CborError cbor_encoder_create_map(CborEncoder *encoder, CborEncoder *mapEncoder, size_t length) +{ + if (length != CborIndefiniteLength && length > SIZE_MAX / 2) + return CborErrorDataTooLarge; + return create_container(encoder, mapEncoder, length, MapType << MajorTypeShift); +} + +/** + * Closes the CBOR container (array or map) provided by \a containerEncoder and + * updates the CBOR stream provided by \a encoder. Both parameters must be the + * same as were passed to cbor_encoder_create_array() or + * cbor_encoder_create_map(). + * + * Since version 0.5, this function verifies that the number of items (or pairs + * of items, in the case of a map) was correct. It is no longer necessary to call + * cbor_encoder_close_container_checked() instead. + * + * \sa cbor_encoder_create_array(), cbor_encoder_create_map() + */ +CborError cbor_encoder_close_container(CborEncoder *encoder, const CborEncoder *containerEncoder) +{ + if (encoder->end) + encoder->data.ptr = containerEncoder->data.ptr; + else + encoder->data.bytes_needed = containerEncoder->data.bytes_needed; + encoder->end = containerEncoder->end; + if (containerEncoder->flags & CborIteratorFlag_UnknownLength) + return append_byte_to_buffer(encoder, BreakByte); + + if (containerEncoder->remaining != 1) + return containerEncoder->remaining == 0 ? CborErrorTooManyItems : CborErrorTooFewItems; + + if (!encoder->end) + return CborErrorOutOfMemory; /* keep the state */ + return CborNoError; +} + +/** + * \fn CborError cbor_encode_boolean(CborEncoder *encoder, bool value) + * + * Appends the boolean value \a value to the CBOR stream provided by \a encoder. + */ + +/** + * \fn CborError cbor_encode_null(CborEncoder *encoder) + * + * Appends the CBOR type representing a null value to the CBOR stream provided + * by \a encoder. + * + * \sa cbor_encode_undefined() + */ + +/** + * \fn CborError cbor_encode_undefined(CborEncoder *encoder) + * + * Appends the CBOR type representing an undefined value to the CBOR stream + * provided by \a encoder. + * + * \sa cbor_encode_null() + */ + +/** + * \fn CborError cbor_encode_half_float(CborEncoder *encoder, const void *value) + * + * Appends the IEEE 754 half-precision (16-bit) floating point value pointed to + * by \a value to the CBOR stream provided by \a encoder. + * + * \sa cbor_encode_floating_point(), cbor_encode_float(), cbor_encode_double() + */ + +/** + * \fn CborError cbor_encode_float(CborEncoder *encoder, float value) + * + * Appends the IEEE 754 single-precision (32-bit) floating point value \a value + * to the CBOR stream provided by \a encoder. + * + * \sa cbor_encode_floating_point(), cbor_encode_half_float(), cbor_encode_double() + */ + +/** + * \fn CborError cbor_encode_double(CborEncoder *encoder, double value) + * + * Appends the IEEE 754 double-precision (64-bit) floating point value \a value + * to the CBOR stream provided by \a encoder. + * + * \sa cbor_encode_floating_point(), cbor_encode_half_float(), cbor_encode_float() + */ + +/** + * \fn size_t cbor_encoder_get_buffer_size(const CborEncoder *encoder, const uint8_t *buffer) + * + * Returns the total size of the buffer starting at \a buffer after the + * encoding finished without errors. The \a encoder and \a buffer arguments + * must be the same as supplied to cbor_encoder_init(). + * + * If the encoding process had errors, the return value of this function is + * meaningless. If the only errors were CborErrorOutOfMemory, instead use + * cbor_encoder_get_extra_bytes_needed() to find out by how much to grow the + * buffer before encoding again. + * + * See \ref CborEncoding for an example of using this function. + * + * \sa cbor_encoder_init(), cbor_encoder_get_extra_bytes_needed(), CborEncoding + */ + +/** + * \fn size_t cbor_encoder_get_extra_bytes_needed(const CborEncoder *encoder) + * + * Returns how many more bytes the original buffer supplied to + * cbor_encoder_init() needs to be extended by so that no CborErrorOutOfMemory + * condition will happen for the encoding. If the buffer was big enough, this + * function returns 0. The \a encoder must be the original argument as passed + * to cbor_encoder_init(). + * + * This function is usually called after an encoding sequence ended with one or + * more CborErrorOutOfMemory errors, but no other error. If any other error + * happened, the return value of this function is meaningless. + * + * See \ref CborEncoding for an example of using this function. + * + * \sa cbor_encoder_init(), cbor_encoder_get_buffer_size(), CborEncoding + */ + +/** @} */ diff --git a/client/tinycbor/cborencoder_close_container_checked.c b/client/tinycbor/cborencoder_close_container_checked.c new file mode 100644 index 000000000..5661e4d53 --- /dev/null +++ b/client/tinycbor/cborencoder_close_container_checked.c @@ -0,0 +1,57 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Intel Corporation +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +#define _BSD_SOURCE 1 +#define _DEFAULT_SOURCE 1 +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS 1 +#endif + +#include "cbor.h" + +/** + * \addtogroup CborEncoding + * @{ + */ + +/** + * @deprecated + * + * Closes the CBOR container (array or map) provided by \a containerEncoder and + * updates the CBOR stream provided by \a encoder. Both parameters must be the + * same as were passed to cbor_encoder_create_array() or + * cbor_encoder_create_map(). + * + * Prior to version 0.5, cbor_encoder_close_container() did not check the + * number of items added. Since that version, it does and now + * cbor_encoder_close_container_checked() is no longer needed. + * + * \sa cbor_encoder_create_array(), cbor_encoder_create_map() + */ +CborError cbor_encoder_close_container_checked(CborEncoder *encoder, const CborEncoder *containerEncoder) +{ + return cbor_encoder_close_container(encoder, containerEncoder); +} + +/** @} */ diff --git a/client/tinycbor/cborerrorstrings.c b/client/tinycbor/cborerrorstrings.c new file mode 100644 index 000000000..3fe3a9823 --- /dev/null +++ b/client/tinycbor/cborerrorstrings.c @@ -0,0 +1,182 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Intel Corporation +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +#include "cbor.h" + +#ifndef _ +# define _(msg) msg +#endif + +/** + * \enum CborError + * \ingroup CborGlobals + * The CborError enum contains the possible error values used by the CBOR encoder and decoder. + * + * TinyCBOR functions report success by returning CborNoError, or one error + * condition by returning one of the values below. One exception is the + * out-of-memory condition (CborErrorOutOfMemory), which the functions for \ref + * CborEncoding may report in bit-wise OR with other conditions. + * + * This technique allows code to determine whether the only error condition was + * a lack of buffer space, which may not be a fatal condition if the buffer can + * be resized. Additionally, the functions for \ref CborEncoding may continue + * to be used even after CborErrorOutOfMemory is returned, and instead they + * will simply calculate the extra space needed. + * + * \value CborNoError No error occurred + * \omitvalue CborUnknownError + * \value CborErrorUnknownLength Request for the length of an array, map or string whose length is not provided in the CBOR stream + * \value CborErrorAdvancePastEOF Not enough data in the stream to decode item (decoding would advance past end of stream) + * \value CborErrorIO An I/O error occurred, probably due to an out-of-memory situation + * \value CborErrorGarbageAtEnd Bytes exist past the end of the CBOR stream + * \value CborErrorUnexpectedEOF End of stream reached unexpectedly + * \value CborErrorUnexpectedBreak A CBOR break byte was found where not expected + * \value CborErrorUnknownType An unknown type (future extension to CBOR) was found in the stream + * \value CborErrorIllegalType An invalid type was found while parsing a chunked CBOR string + * \value CborErrorIllegalNumber An illegal initial byte (encoding unspecified additional information) was found + * \value CborErrorIllegalSimpleType An illegal encoding of a CBOR Simple Type of value less than 32 was found + * \omitvalue CborErrorUnknownSimpleType + * \omitvalue CborErrorUnknownTag + * \omitvalue CborErrorInappropriateTagForType + * \omitvalue CborErrorDuplicateObjectKeys + * \value CborErrorInvalidUtf8TextString Illegal UTF-8 encoding found while parsing CBOR Text String + * \value CborErrorTooManyItems Too many items were added to CBOR map or array of pre-determined length + * \value CborErrorTooFewItems Too few items were added to CBOR map or array of pre-determined length + * \value CborErrorDataTooLarge Data item size exceeds TinyCBOR's implementation limits + * \value CborErrorNestingTooDeep Data item nesting exceeds TinyCBOR's implementation limits + * \omitvalue CborErrorUnsupportedType + * \value CborErrorJsonObjectKeyIsAggregate Conversion to JSON failed because the key in a map is a CBOR map or array + * \value CborErrorJsonObjectKeyNotString Conversion to JSON failed because the key in a map is not a text string + * \value CborErrorOutOfMemory During CBOR encoding, the buffer provided is insufficient for encoding the data item; + * in other situations, TinyCBOR failed to allocate memory + * \value CborErrorInternalError An internal error occurred in TinyCBOR + */ + +/** + * \ingroup CborGlobals + * Returns the error string corresponding to the CBOR error condition \a error. + */ +const char *cbor_error_string(CborError error) +{ + switch (error) { + case CborNoError: + return ""; + + case CborUnknownError: + return _("unknown error"); + + case CborErrorOutOfMemory: + return _("out of memory/need more memory"); + + case CborErrorUnknownLength: + return _("unknown length (attempted to get the length of a map/array/string of indeterminate length"); + + case CborErrorAdvancePastEOF: + return _("attempted to advance past EOF"); + + case CborErrorIO: + return _("I/O error"); + + case CborErrorGarbageAtEnd: + return _("garbage after the end of the content"); + + case CborErrorUnexpectedEOF: + return _("unexpected end of data"); + + case CborErrorUnexpectedBreak: + return _("unexpected 'break' byte"); + + case CborErrorUnknownType: + return _("illegal byte (encodes future extension type)"); + + case CborErrorIllegalType: + return _("mismatched string type in chunked string"); + + case CborErrorIllegalNumber: + return _("illegal initial byte (encodes unspecified additional information)"); + + case CborErrorIllegalSimpleType: + return _("illegal encoding of simple type smaller than 32"); + + case CborErrorUnknownSimpleType: + return _("unknown simple type"); + + case CborErrorUnknownTag: + return _("unknown tag"); + + case CborErrorInappropriateTagForType: + return _("inappropriate tag for type"); + + case CborErrorDuplicateObjectKeys: + return _("duplicate keys in object"); + + case CborErrorInvalidUtf8TextString: + return _("invalid UTF-8 content in string"); + + case CborErrorExcludedType: + return _("excluded type found"); + + case CborErrorExcludedValue: + return _("excluded value found"); + + case CborErrorImproperValue: + case CborErrorOverlongEncoding: + return _("value encoded in non-canonical form"); + + case CborErrorMapKeyNotString: + case CborErrorJsonObjectKeyNotString: + return _("key in map is not a string"); + + case CborErrorMapNotSorted: + return _("map is not sorted"); + + case CborErrorMapKeysNotUnique: + return _("map keys are not unique"); + + case CborErrorTooManyItems: + return _("too many items added to encoder"); + + case CborErrorTooFewItems: + return _("too few items added to encoder"); + + case CborErrorDataTooLarge: + return _("internal error: data too large"); + + case CborErrorNestingTooDeep: + return _("internal error: too many nested containers found in recursive function"); + + case CborErrorUnsupportedType: + return _("unsupported type"); + + case CborErrorJsonObjectKeyIsAggregate: + return _("conversion to JSON failed: key in object is an array or map"); + + case CborErrorJsonNotImplemented: + return _("conversion to JSON failed: open_memstream unavailable"); + + case CborErrorInternalError: + return _("internal error"); + } + return cbor_error_string(CborUnknownError); +} diff --git a/client/tinycbor/cborinternal_p.h b/client/tinycbor/cborinternal_p.h new file mode 100644 index 000000000..a85a92972 --- /dev/null +++ b/client/tinycbor/cborinternal_p.h @@ -0,0 +1,161 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Intel Corporation +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +#ifndef CBORINTERNAL_P_H +#define CBORINTERNAL_P_H + +#include "compilersupport_p.h" + +#ifndef CBOR_NO_FLOATING_POINT +# include +# include +#else +# ifndef CBOR_NO_HALF_FLOAT_TYPE +# define CBOR_NO_HALF_FLOAT_TYPE 1 +# endif +#endif + +#ifndef CBOR_NO_HALF_FLOAT_TYPE +# ifdef __F16C__ +# include +static inline unsigned short encode_half(double val) +{ + return _cvtss_sh((float)val, 3); +} +static inline double decode_half(unsigned short half) +{ + return _cvtsh_ss(half); +} +# else +/* software implementation of float-to-fp16 conversions */ +static inline unsigned short encode_half(double val) +{ + uint64_t v; + int sign, exp, mant; + memcpy(&v, &val, sizeof(v)); + sign = v >> 63 << 15; + exp = (v >> 52) & 0x7ff; + mant = v << 12 >> 12 >> (53-11); /* keep only the 11 most significant bits of the mantissa */ + exp -= 1023; + if (exp == 1024) { + /* infinity or NaN */ + exp = 16; + mant >>= 1; + } else if (exp >= 16) { + /* overflow, as largest number */ + exp = 15; + mant = 1023; + } else if (exp >= -14) { + /* regular normal */ + } else if (exp >= -24) { + /* subnormal */ + mant |= 1024; + mant >>= -(exp + 14); + exp = -15; + } else { + /* underflow, make zero */ + return 0; + } + + /* safe cast here as bit operations above guarantee not to overflow */ + return (unsigned short)(sign | ((exp + 15) << 10) | mant); +} + +/* this function was copied & adapted from RFC 7049 Appendix D */ +static inline double decode_half(unsigned short half) +{ + int exp = (half >> 10) & 0x1f; + int mant = half & 0x3ff; + double val; + if (exp == 0) val = ldexp(mant, -24); + else if (exp != 31) val = ldexp(mant + 1024, exp - 25); + else val = mant == 0 ? INFINITY : NAN; + return half & 0x8000 ? -val : val; +} +# endif +#endif /* CBOR_NO_HALF_FLOAT_TYPE */ + +#ifndef CBOR_INTERNAL_API +# define CBOR_INTERNAL_API +#endif + +#ifndef CBOR_PARSER_MAX_RECURSIONS +# define CBOR_PARSER_MAX_RECURSIONS 1024 +#endif + +/* + * CBOR Major types + * Encoded in the high 3 bits of the descriptor byte + * See http://tools.ietf.org/html/rfc7049#section-2.1 + */ +typedef enum CborMajorTypes { + UnsignedIntegerType = 0U, + NegativeIntegerType = 1U, + ByteStringType = 2U, + TextStringType = 3U, + ArrayType = 4U, + MapType = 5U, /* a.k.a. object */ + TagType = 6U, + SimpleTypesType = 7U +} CborMajorTypes; + +/* + * CBOR simple and floating point types + * Encoded in the low 8 bits of the descriptor byte when the + * Major Type is 7. + */ +typedef enum CborSimpleTypes { + FalseValue = 20, + TrueValue = 21, + NullValue = 22, + UndefinedValue = 23, + SimpleTypeInNextByte = 24, /* not really a simple type */ + HalfPrecisionFloat = 25, /* ditto */ + SinglePrecisionFloat = 26, /* ditto */ + DoublePrecisionFloat = 27, /* ditto */ + Break = 31 +} CborSimpleTypes; + +enum { + SmallValueBitLength = 5U, + SmallValueMask = (1U << SmallValueBitLength) - 1, /* 31 */ + Value8Bit = 24U, + Value16Bit = 25U, + Value32Bit = 26U, + Value64Bit = 27U, + IndefiniteLength = 31U, + + MajorTypeShift = SmallValueBitLength, + MajorTypeMask = (int) (~0U << MajorTypeShift), + + BreakByte = (unsigned)Break | (SimpleTypesType << MajorTypeShift) +}; + +CBOR_INTERNAL_API CborError CBOR_INTERNAL_API_CC _cbor_value_extract_number(const uint8_t **ptr, const uint8_t *end, uint64_t *len); +CBOR_INTERNAL_API CborError CBOR_INTERNAL_API_CC _cbor_value_prepare_string_iteration(CborValue *it); +CBOR_INTERNAL_API CborError CBOR_INTERNAL_API_CC _cbor_value_get_string_chunk(const CborValue *value, const void **bufferptr, + size_t *len, CborValue *next); + + +#endif /* CBORINTERNAL_P_H */ diff --git a/client/tinycbor/cborjson.h b/client/tinycbor/cborjson.h new file mode 100644 index 000000000..8ff27b920 --- /dev/null +++ b/client/tinycbor/cborjson.h @@ -0,0 +1,62 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Intel Corporation +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +#ifndef CBORJSON_H +#define CBORJSON_H + +#include "cbor.h" + +#ifdef __cplusplus +extern "C" { +#endif + +/* Conversion to JSON */ +enum CborToJsonFlags +{ + CborConvertAddMetadata = 1, + CborConvertTagsToObjects = 2, + CborConvertIgnoreTags = 0, + + CborConvertObeyByteStringTags = 0, + CborConvertByteStringsToBase64Url = 4, + + CborConvertRequireMapStringKeys = 0, + CborConvertStringifyMapKeys = 8, + + CborConvertDefaultFlags = 0 +}; + +CBOR_API CborError cbor_value_to_json_advance(FILE *out, CborValue *value, int flags); +CBOR_INLINE_API CborError cbor_value_to_json(FILE *out, const CborValue *value, int flags) +{ + CborValue copy = *value; + return cbor_value_to_json_advance(out, ©, flags); +} + +#ifdef __cplusplus +} +#endif + +#endif /* CBORJSON_H */ + diff --git a/client/tinycbor/cborparser.c b/client/tinycbor/cborparser.c new file mode 100644 index 000000000..45de2226a --- /dev/null +++ b/client/tinycbor/cborparser.c @@ -0,0 +1,1430 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Intel Corporation +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +#ifndef _BSD_SOURCE +#define _BSD_SOURCE 1 +#endif +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE 1 +#endif +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS 1 +#endif + +#include "cbor.h" +#include "cborinternal_p.h" +#include "compilersupport_p.h" + +#include + +/** + * \defgroup CborParsing Parsing CBOR streams + * \brief Group of functions used to parse CBOR streams. + * + * TinyCBOR provides functions for pull-based stream parsing of a CBOR-encoded + * payload. The main data type for the parsing is a CborValue, which behaves + * like an iterator and can be used to extract the encoded data. It is first + * initialized with a call to cbor_parser_init() and is usually used to extract + * exactly one item, most often an array or map. + * + * Nested CborValue objects can be parsed using cbor_value_enter_container(). + * Each call to cbor_value_enter_container() must be matched by a call to + * cbor_value_leave_container(), with the exact same parameters. + * + * The example below initializes a CborParser object, begins the parsing with a + * CborValue and decodes a single integer: + * + * \code + * int extract_int(const uint8_t *buffer, size_t len) + * { + * CborParser parser; + * CborValue value; + * int result; + * cbor_parser_init(buffer, len, 0, &parser, &value); + * cbor_value_get_int(&value, &result); + * return result; + * } + * \endcode + * + * The code above does no error checking, which means it assumes the data comes + * from a source trusted to send one properly-encoded integer. The following + * example does the exact same operation, but includes error checking and + * returns 0 on parsing failure: + * + * \code + * int extract_int(const uint8_t *buffer, size_t len) + * { + * CborParser parser; + * CborValue value; + * int result; + * if (cbor_parser_init(buffer, len, 0, &parser, &value) != CborNoError) + * return 0; + * if (!cbor_value_is_integer(&value) || + * cbor_value_get_int(&value, &result) != CborNoError) + * return 0; + * return result; + * } + * \endcode + * + * Note, in the example above, that one can't distinguish a parsing failure + * from an encoded value of zero. Reporting a parsing error is left as an + * exercise to the reader. + * + * The code above does not execute a range-check either: it is possible that + * the value decoded from the CBOR stream encodes a number larger than what can + * be represented in a variable of type \c{int}. If detecting that case is + * important, the code should call cbor_value_get_int_checked() instead. + * + *

Memory and parsing constraints

+ * + * TinyCBOR is designed to run with little memory and with minimal overhead. + * Except where otherwise noted, the parser functions always run on constant + * time (O(1)), do not recurse and never allocate memory (thus, stack usage is + * bounded and is O(1)). + * + *

Error handling and preconditions

+ * + * All functions operating on a CborValue return a CborError condition, with + * CborNoError standing for the normal situation in which no parsing error + * occurred. All functions may return parsing errors in case the stream cannot + * be decoded properly, be it due to corrupted data or due to reaching the end + * of the input buffer. + * + * Error conditions must not be ignored. All decoder functions have undefined + * behavior if called after an error has been reported, and may crash. + * + * Some functions are also documented to have preconditions, like + * cbor_value_get_int() requiring that the input be an integral value. + * Violation of preconditions also results in undefined behavior and the + * program may crash. + */ + +/** + * \addtogroup CborParsing + * @{ + */ + +/** + * \struct CborValue + * + * This type contains one value parsed from the CBOR stream. Each CborValue + * behaves as an iterator in a StAX-style parser. + * + * \if privatedocs + * Implementation details: the CborValue contains these fields: + * \list + * \li ptr: pointer to the actual data + * \li flags: flags from the decoder + * \li extra: partially decoded integer value (0, 1 or 2 bytes) + * \li remaining: remaining items in this collection after this item or UINT32_MAX if length is unknown + * \endlist + * \endif + */ + +static inline uint16_t get16(const uint8_t *ptr) +{ + uint16_t result; + memcpy(&result, ptr, sizeof(result)); + return cbor_ntohs(result); +} + +static inline uint32_t get32(const uint8_t *ptr) +{ + uint32_t result; + memcpy(&result, ptr, sizeof(result)); + return cbor_ntohl(result); +} + +static inline uint64_t get64(const uint8_t *ptr) +{ + uint64_t result; + memcpy(&result, ptr, sizeof(result)); + return cbor_ntohll(result); +} + +CborError CBOR_INTERNAL_API_CC _cbor_value_extract_number(const uint8_t **ptr, const uint8_t *end, uint64_t *len) +{ + size_t bytesNeeded; + uint8_t additional_information = **ptr & SmallValueMask; + ++*ptr; + if (additional_information < Value8Bit) { + *len = additional_information; + return CborNoError; + } + if (unlikely(additional_information > Value64Bit)) + return CborErrorIllegalNumber; + + bytesNeeded = (size_t)(1 << (additional_information - Value8Bit)); + if (unlikely(bytesNeeded > (size_t)(end - *ptr))) { + return CborErrorUnexpectedEOF; + } else if (bytesNeeded == 1) { + *len = (uint8_t)(*ptr)[0]; + } else if (bytesNeeded == 2) { + *len = get16(*ptr); + } else if (bytesNeeded == 4) { + *len = get32(*ptr); + } else { + *len = get64(*ptr); + } + *ptr += bytesNeeded; + return CborNoError; +} + +static CborError extract_length(const CborParser *parser, const uint8_t **ptr, size_t *len) +{ + uint64_t v; + CborError err = _cbor_value_extract_number(ptr, parser->end, &v); + if (err) { + *len = 0; + return err; + } + + *len = (size_t)v; + if (v != *len) + return CborErrorDataTooLarge; + return CborNoError; +} + +static bool is_fixed_type(uint8_t type) +{ + return type != CborTextStringType && type != CborByteStringType && type != CborArrayType && + type != CborMapType; +} + +static CborError preparse_value(CborValue *it) +{ + const CborParser *parser = it->parser; + it->type = CborInvalidType; + + /* are we at the end? */ + if (it->ptr == parser->end) + return CborErrorUnexpectedEOF; + + uint8_t descriptor = *it->ptr; + uint8_t type = descriptor & MajorTypeMask; + it->type = type; + it->flags = 0; + it->extra = (descriptor &= SmallValueMask); + + if (descriptor > Value64Bit) { + if (unlikely(descriptor != IndefiniteLength)) + return type == CborSimpleType ? CborErrorUnknownType : CborErrorIllegalNumber; + if (likely(!is_fixed_type(type))) { + /* special case */ + it->flags |= CborIteratorFlag_UnknownLength; + it->type = type; + return CborNoError; + } + return type == CborSimpleType ? CborErrorUnexpectedBreak : CborErrorIllegalNumber; + } + + size_t bytesNeeded = descriptor < Value8Bit ? 0 : (1 << (descriptor - Value8Bit)); + if (bytesNeeded + 1 > (size_t)(parser->end - it->ptr)) + return CborErrorUnexpectedEOF; + + uint8_t majortype = type >> MajorTypeShift; + if (majortype == NegativeIntegerType) { + it->flags |= CborIteratorFlag_NegativeInteger; + it->type = CborIntegerType; + } else if (majortype == SimpleTypesType) { + switch (descriptor) { + case FalseValue: + it->extra = false; + it->type = CborBooleanType; + break; + + case SinglePrecisionFloat: + case DoublePrecisionFloat: + it->flags |= CborIteratorFlag_IntegerValueTooLarge; + /* fall through */ + case TrueValue: + case NullValue: + case UndefinedValue: + case HalfPrecisionFloat: + it->type = *it->ptr; + break; + + case SimpleTypeInNextByte: + it->extra = (uint8_t)it->ptr[1]; +#ifndef CBOR_PARSER_NO_STRICT_CHECKS + if (unlikely(it->extra < 32)) { + it->type = CborInvalidType; + return CborErrorIllegalSimpleType; + } +#endif + break; + + case 28: + case 29: + case 30: + case Break: + cbor_assert(false); /* these conditions can't be reached */ + return CborErrorUnexpectedBreak; + } + return CborNoError; + } + + /* try to decode up to 16 bits */ + if (descriptor < Value8Bit) + return CborNoError; + + if (descriptor == Value8Bit) + it->extra = (uint8_t)it->ptr[1]; + else if (descriptor == Value16Bit) + it->extra = get16(it->ptr + 1); + else + it->flags |= CborIteratorFlag_IntegerValueTooLarge; /* Value32Bit or Value64Bit */ + return CborNoError; +} + +static CborError preparse_next_value_nodecrement(CborValue *it) +{ + if (it->remaining == UINT32_MAX && it->ptr != it->parser->end && *it->ptr == (uint8_t)BreakByte) { + /* end of map or array */ + ++it->ptr; + it->type = CborInvalidType; + it->remaining = 0; + return CborNoError; + } + + return preparse_value(it); +} + +static CborError preparse_next_value(CborValue *it) +{ + if (it->remaining != UINT32_MAX) { + /* don't decrement the item count if the current item is tag: they don't count */ + if (it->type != CborTagType && --it->remaining == 0) { + it->type = CborInvalidType; + return CborNoError; + } + } + return preparse_next_value_nodecrement(it); +} + +static CborError advance_internal(CborValue *it) +{ + uint64_t length; + CborError err = _cbor_value_extract_number(&it->ptr, it->parser->end, &length); + cbor_assert(err == CborNoError); + + if (it->type == CborByteStringType || it->type == CborTextStringType) { + cbor_assert(length == (size_t)length); + cbor_assert((it->flags & CborIteratorFlag_UnknownLength) == 0); + it->ptr += length; + } + + return preparse_next_value(it); +} + +/** \internal + * + * Decodes the CBOR integer value when it is larger than the 16 bits available + * in value->extra. This function requires that value->flags have the + * CborIteratorFlag_IntegerValueTooLarge flag set. + * + * This function is also used to extract single- and double-precision floating + * point values (SinglePrecisionFloat == Value32Bit and DoublePrecisionFloat == + * Value64Bit). + */ +uint64_t _cbor_value_decode_int64_internal(const CborValue *value) +{ + cbor_assert(value->flags & CborIteratorFlag_IntegerValueTooLarge || + value->type == CborFloatType || value->type == CborDoubleType); + + /* since the additional information can only be Value32Bit or Value64Bit, + * we just need to test for the one bit those two options differ */ + cbor_assert((*value->ptr & SmallValueMask) == Value32Bit || (*value->ptr & SmallValueMask) == Value64Bit); + if ((*value->ptr & 1) == (Value32Bit & 1)) + return get32(value->ptr + 1); + + cbor_assert((*value->ptr & SmallValueMask) == Value64Bit); + return get64(value->ptr + 1); +} + +/** + * Initializes the CBOR parser for parsing \a size bytes beginning at \a + * buffer. Parsing will use flags set in \a flags. The iterator to the first + * element is returned in \a it. + * + * The \a parser structure needs to remain valid throughout the decoding + * process. It is not thread-safe to share one CborParser among multiple + * threads iterating at the same time, but the object can be copied so multiple + * threads can iterate. + */ +CborError cbor_parser_init(const uint8_t *buffer, size_t size, uint32_t flags, CborParser *parser, CborValue *it) +{ + memset(parser, 0, sizeof(*parser)); + parser->end = buffer + size; + parser->flags = flags; + it->parser = parser; + it->ptr = buffer; + it->remaining = 1; /* there's one type altogether, usually an array or map */ + return preparse_value(it); +} + +/** + * \fn bool cbor_value_at_end(const CborValue *it) + * + * Returns true if \a it has reached the end of the iteration, usually when + * advancing after the last item in an array or map. + * + * In the case of the outermost CborValue object, this function returns true + * after decoding a single element. A pointer to the first byte of the + * remaining data (if any) can be obtained with cbor_value_get_next_byte(). + * + * \sa cbor_value_advance(), cbor_value_is_valid(), cbor_value_get_next_byte() + */ + +/** + * \fn const uint8_t *cbor_value_get_next_byte(const CborValue *it) + * + * Returns a pointer to the next byte that would be decoded if this CborValue + * object were advanced. + * + * This function is useful if cbor_value_at_end() returns true for the + * outermost CborValue: the pointer returned is the first byte of the data + * remaining in the buffer, if any. Code can decide whether to begin decoding a + * new CBOR data stream from this point, or parse some other data appended to + * the same buffer. + * + * This function may be used even after a parsing error. If that occurred, + * then this function returns a pointer to where the parsing error occurred. + * Note that the error recovery is not precise and the pointer may not indicate + * the exact byte containing bad data. + * + * \sa cbor_value_at_end() + */ + +/** + * \fn bool cbor_value_is_valid(const CborValue *it) + * + * Returns true if the iterator \a it contains a valid value. Invalid iterators + * happen when iteration reaches the end of a container (see \ref + * cbor_value_at_end()) or when a search function resulted in no matches. + * + * \sa cbor_value_advance(), cbor_value_at_end(), cbor_value_get_type() + */ + +/** + * Performs a basic validation of the CBOR stream pointed by \a it and returns + * the error it found. If no error was found, it returns CborNoError and the + * application can iterate over the items with certainty that no other errors + * will appear during parsing. + * + * A basic validation checks for: + * \list + * \li absence of undefined additional information bytes; + * \li well-formedness of all numbers, lengths, and simple values; + * \li string contents match reported sizes; + * \li arrays and maps contain the number of elements they are reported to have; + * \endlist + * + * For further checks, see cbor_value_validate(). + * + * This function has the same timing and memory requirements as + * cbor_value_advance(). + * + * \sa cbor_value_validate(), cbor_value_advance() + */ +CborError cbor_value_validate_basic(const CborValue *it) +{ + CborValue value = *it; + return cbor_value_advance(&value); +} + +/** + * Advances the CBOR value \a it by one fixed-size position. Fixed-size types + * are: integers, tags, simple types (including boolean, null and undefined + * values) and floating point types. + * + * If the type is not of fixed size, this function has undefined behavior. Code + * must be sure that the current type is one of the fixed-size types before + * calling this function. This function is provided because it can guarantee + * that it runs in constant time (O(1)). + * + * If the caller is not able to determine whether the type is fixed or not, code + * can use the cbor_value_advance() function instead. + * + * \sa cbor_value_at_end(), cbor_value_advance(), cbor_value_enter_container(), cbor_value_leave_container() + */ +CborError cbor_value_advance_fixed(CborValue *it) +{ + cbor_assert(it->type != CborInvalidType); + cbor_assert(is_fixed_type(it->type)); + if (!it->remaining) + return CborErrorAdvancePastEOF; + return advance_internal(it); +} + +static CborError advance_recursive(CborValue *it, int nestingLevel) +{ + CborError err; + CborValue recursed; + + if (is_fixed_type(it->type)) + return advance_internal(it); + + if (!cbor_value_is_container(it)) { + size_t len = SIZE_MAX; + return _cbor_value_copy_string(it, NULL, &len, it); + } + + /* map or array */ + if (nestingLevel == 0) + return CborErrorNestingTooDeep; + + err = cbor_value_enter_container(it, &recursed); + if (err) + return err; + while (!cbor_value_at_end(&recursed)) { + err = advance_recursive(&recursed, nestingLevel - 1); + if (err) + return err; + } + return cbor_value_leave_container(it, &recursed); +} + + +/** + * Advances the CBOR value \a it by one element, skipping over containers. + * Unlike cbor_value_advance_fixed(), this function can be called on a CBOR + * value of any type. However, if the type is a container (map or array) or a + * string with a chunked payload, this function will not run in constant time + * and will recurse into itself (it will run on O(n) time for the number of + * elements or chunks and will use O(n) memory for the number of nested + * containers). + * + * The number of recursions can be limited at compile time to avoid stack + * exhaustion in constrained systems. + * + * \sa cbor_value_at_end(), cbor_value_advance_fixed(), cbor_value_enter_container(), cbor_value_leave_container() + */ +CborError cbor_value_advance(CborValue *it) +{ + cbor_assert(it->type != CborInvalidType); + if (!it->remaining) + return CborErrorAdvancePastEOF; + return advance_recursive(it, CBOR_PARSER_MAX_RECURSIONS); +} + +/** + * \fn bool cbor_value_is_tag(const CborValue *value) + * + * Returns true if the iterator \a value is valid and points to a CBOR tag. + * + * \sa cbor_value_get_tag(), cbor_value_skip_tag() + */ + +/** + * \fn CborError cbor_value_get_tag(const CborValue *value, CborTag *result) + * + * Retrieves the CBOR tag value that \a value points to and stores it in \a + * result. If the iterator \a value does not point to a CBOR tag value, the + * behavior is undefined, so checking with \ref cbor_value_get_type or with + * \ref cbor_value_is_tag is recommended. + * + * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_tag() + */ + +/** + * Advances the CBOR value \a it until it no longer points to a tag. If \a it is + * already not pointing to a tag, then this function returns it unchanged. + * + * This function does not run in constant time: it will run on O(n) for n being + * the number of tags. It does use constant memory (O(1) memory requirements). + * + * \sa cbor_value_advance_fixed(), cbor_value_advance() + */ +CborError cbor_value_skip_tag(CborValue *it) +{ + while (cbor_value_is_tag(it)) { + CborError err = cbor_value_advance_fixed(it); + if (err) + return err; + } + return CborNoError; +} + +/** + * \fn bool cbor_value_is_container(const CborValue *it) + * + * Returns true if the \a it value is a container and requires recursion in + * order to decode (maps and arrays), false otherwise. + */ + +/** + * Creates a CborValue iterator pointing to the first element of the container + * represented by \a it and saves it in \a recursed. The \a it container object + * needs to be kept and passed again to cbor_value_leave_container() in order + * to continue iterating past this container. + * + * The \a it CborValue iterator must point to a container. + * + * \sa cbor_value_is_container(), cbor_value_leave_container(), cbor_value_advance() + */ +CborError cbor_value_enter_container(const CborValue *it, CborValue *recursed) +{ + cbor_assert(cbor_value_is_container(it)); + *recursed = *it; + + if (it->flags & CborIteratorFlag_UnknownLength) { + recursed->remaining = UINT32_MAX; + ++recursed->ptr; + } else { + uint64_t len; + CborError err = _cbor_value_extract_number(&recursed->ptr, recursed->parser->end, &len); + cbor_assert(err == CborNoError); + + recursed->remaining = (uint32_t)len; + if (recursed->remaining != len || len == UINT32_MAX) { + /* back track the pointer to indicate where the error occurred */ + recursed->ptr = it->ptr; + return CborErrorDataTooLarge; + } + if (recursed->type == CborMapType) { + /* maps have keys and values, so we need to multiply by 2 */ + if (recursed->remaining > UINT32_MAX / 2) { + /* back track the pointer to indicate where the error occurred */ + recursed->ptr = it->ptr; + return CborErrorDataTooLarge; + } + recursed->remaining *= 2; + } + if (len == 0) { + /* the case of the empty container */ + recursed->type = CborInvalidType; + return CborNoError; + } + } + return preparse_next_value_nodecrement(recursed); +} + +/** + * Updates \a it to point to the next element after the container. The \a + * recursed object needs to point to the element obtained either by advancing + * the last element of the container (via cbor_value_advance(), + * cbor_value_advance_fixed(), a nested cbor_value_leave_container(), or the \c + * next pointer from cbor_value_copy_string() or cbor_value_dup_string()). + * + * The \a it and \a recursed parameters must be the exact same as passed to + * cbor_value_enter_container(). + * + * \sa cbor_value_enter_container(), cbor_value_at_end() + */ +CborError cbor_value_leave_container(CborValue *it, const CborValue *recursed) +{ + cbor_assert(cbor_value_is_container(it)); + cbor_assert(recursed->type == CborInvalidType); + it->ptr = recursed->ptr; + return preparse_next_value(it); +} + + +/** + * \fn CborType cbor_value_get_type(const CborValue *value) + * + * Returns the type of the CBOR value that the iterator \a value points to. If + * \a value does not point to a valid value, this function returns \ref + * CborInvalidType. + * + * TinyCBOR also provides functions to test directly if a given CborValue object + * is of a given type, like cbor_value_is_text_string() and cbor_value_is_null(). + * + * \sa cbor_value_is_valid() + */ + +/** + * \fn bool cbor_value_is_null(const CborValue *value) + * + * Returns true if the iterator \a value is valid and points to a CBOR null type. + * + * \sa cbor_value_is_valid(), cbor_value_is_undefined() + */ + +/** + * \fn bool cbor_value_is_undefined(const CborValue *value) + * + * Returns true if the iterator \a value is valid and points to a CBOR undefined type. + * + * \sa cbor_value_is_valid(), cbor_value_is_null() + */ + +/** + * \fn bool cbor_value_is_boolean(const CborValue *value) + * + * Returns true if the iterator \a value is valid and points to a CBOR boolean + * type (true or false). + * + * \sa cbor_value_is_valid(), cbor_value_get_boolean() + */ + +/** + * \fn CborError cbor_value_get_boolean(const CborValue *value, bool *result) + * + * Retrieves the boolean value that \a value points to and stores it in \a + * result. If the iterator \a value does not point to a boolean value, the + * behavior is undefined, so checking with \ref cbor_value_get_type or with + * \ref cbor_value_is_boolean is recommended. + * + * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_boolean() + */ + +/** + * \fn bool cbor_value_is_simple_type(const CborValue *value) + * + * Returns true if the iterator \a value is valid and points to a CBOR Simple Type + * type (other than true, false, null and undefined). + * + * \sa cbor_value_is_valid(), cbor_value_get_simple_type() + */ + +/** + * \fn CborError cbor_value_get_simple_type(const CborValue *value, uint8_t *result) + * + * Retrieves the CBOR Simple Type value that \a value points to and stores it + * in \a result. If the iterator \a value does not point to a simple_type + * value, the behavior is undefined, so checking with \ref cbor_value_get_type + * or with \ref cbor_value_is_simple_type is recommended. + * + * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_simple_type() + */ + +/** + * \fn bool cbor_value_is_integer(const CborValue *value) + * + * Returns true if the iterator \a value is valid and points to a CBOR integer + * type. + * + * \sa cbor_value_is_valid(), cbor_value_get_int, cbor_value_get_int64, cbor_value_get_uint64, cbor_value_get_raw_integer + */ + +/** + * \fn bool cbor_value_is_unsigned_integer(const CborValue *value) + * + * Returns true if the iterator \a value is valid and points to a CBOR unsigned + * integer type (positive values or zero). + * + * \sa cbor_value_is_valid(), cbor_value_get_uint64() + */ + +/** + * \fn bool cbor_value_is_negative_integer(const CborValue *value) + * + * Returns true if the iterator \a value is valid and points to a CBOR negative + * integer type. + * + * \sa cbor_value_is_valid(), cbor_value_get_int, cbor_value_get_int64, cbor_value_get_raw_integer + */ + +/** + * \fn CborError cbor_value_get_int(const CborValue *value, int *result) + * + * Retrieves the CBOR integer value that \a value points to and stores it in \a + * result. If the iterator \a value does not point to an integer value, the + * behavior is undefined, so checking with \ref cbor_value_get_type or with + * \ref cbor_value_is_integer is recommended. + * + * Note that this function does not do range-checking: integral values that do + * not fit in a variable of type \c{int} are silently truncated to fit. Use + * cbor_value_get_int_checked() if that is not acceptable. + * + * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer() + */ + +/** + * \fn CborError cbor_value_get_int64(const CborValue *value, int64_t *result) + * + * Retrieves the CBOR integer value that \a value points to and stores it in \a + * result. If the iterator \a value does not point to an integer value, the + * behavior is undefined, so checking with \ref cbor_value_get_type or with + * \ref cbor_value_is_integer is recommended. + * + * Note that this function does not do range-checking: integral values that do + * not fit in a variable of type \c{int64_t} are silently truncated to fit. Use + * cbor_value_get_int64_checked() that is not acceptable. + * + * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer() + */ + +/** + * \fn CborError cbor_value_get_uint64(const CborValue *value, uint64_t *result) + * + * Retrieves the CBOR integer value that \a value points to and stores it in \a + * result. If the iterator \a value does not point to an unsigned integer + * value, the behavior is undefined, so checking with \ref cbor_value_get_type + * or with \ref cbor_value_is_unsigned_integer is recommended. + * + * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_unsigned_integer() + */ + +/** + * \fn CborError cbor_value_get_raw_integer(const CborValue *value, uint64_t *result) + * + * Retrieves the CBOR integer value that \a value points to and stores it in \a + * result. If the iterator \a value does not point to an integer value, the + * behavior is undefined, so checking with \ref cbor_value_get_type or with + * \ref cbor_value_is_integer is recommended. + * + * This function is provided because CBOR negative integers can assume values + * that cannot be represented with normal 64-bit integer variables. + * + * If the integer is unsigned (that is, if cbor_value_is_unsigned_integer() + * returns true), then \a result will contain the actual value. If the integer + * is negative, then \a result will contain the absolute value of that integer, + * minus one. That is, \c {actual = -result - 1}. On architectures using two's + * complement for representation of negative integers, it is equivalent to say + * that \a result will contain the bitwise negation of the actual value. + * + * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer() + */ + +/** + * Retrieves the CBOR integer value that \a value points to and stores it in \a + * result. If the iterator \a value does not point to an integer value, the + * behavior is undefined, so checking with \ref cbor_value_get_type or with + * \ref cbor_value_is_integer is recommended. + * + * Unlike \ref cbor_value_get_int64(), this function performs a check to see if the + * stored integer fits in \a result without data loss. If the number is outside + * the valid range for the data type, this function returns the recoverable + * error CborErrorDataTooLarge. In that case, use either + * cbor_value_get_uint64() (if the number is positive) or + * cbor_value_get_raw_integer(). + * + * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer(), cbor_value_get_int64() + */ +CborError cbor_value_get_int64_checked(const CborValue *value, int64_t *result) +{ + uint64_t v; + cbor_assert(cbor_value_is_integer(value)); + v = _cbor_value_extract_int64_helper(value); + + /* Check before converting, as the standard says (C11 6.3.1.3 paragraph 3): + * "[if] the new type is signed and the value cannot be represented in it; either the + * result is implementation-defined or an implementation-defined signal is raised." + * + * The range for int64_t is -2^63 to 2^63-1 (int64_t is required to be + * two's complement, C11 7.20.1.1 paragraph 3), which in CBOR is + * represented the same way, differing only on the "sign bit" (the major + * type). + */ + + if (unlikely(v > (uint64_t)INT64_MAX)) + return CborErrorDataTooLarge; + + *result = v; + if (value->flags & CborIteratorFlag_NegativeInteger) + *result = -*result - 1; + return CborNoError; +} + +/** + * Retrieves the CBOR integer value that \a value points to and stores it in \a + * result. If the iterator \a value does not point to an integer value, the + * behavior is undefined, so checking with \ref cbor_value_get_type or with + * \ref cbor_value_is_integer is recommended. + * + * Unlike \ref cbor_value_get_int(), this function performs a check to see if the + * stored integer fits in \a result without data loss. If the number is outside + * the valid range for the data type, this function returns the recoverable + * error CborErrorDataTooLarge. In that case, use one of the other integer + * functions to obtain the value. + * + * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_integer(), cbor_value_get_int64(), + * cbor_value_get_uint64(), cbor_value_get_int64_checked(), cbor_value_get_raw_integer() + */ +CborError cbor_value_get_int_checked(const CborValue *value, int *result) +{ + uint64_t v; + cbor_assert(cbor_value_is_integer(value)); + v = _cbor_value_extract_int64_helper(value); + + /* Check before converting, as the standard says (C11 6.3.1.3 paragraph 3): + * "[if] the new type is signed and the value cannot be represented in it; either the + * result is implementation-defined or an implementation-defined signal is raised." + * + * But we can convert from signed to unsigned without fault (paragraph 2). + * + * The range for int is implementation-defined and int is not guaranteed to use + * two's complement representation (although int32_t is). + */ + + if (value->flags & CborIteratorFlag_NegativeInteger) { + if (unlikely(v > (unsigned) -(INT_MIN + 1))) + return CborErrorDataTooLarge; + + *result = (int)v; + *result = -*result - 1; + } else { + if (unlikely(v > (uint64_t)INT_MAX)) + return CborErrorDataTooLarge; + + *result = (int)v; + } + return CborNoError; + +} + +/** + * \fn bool cbor_value_is_length_known(const CborValue *value) + * + * Returns true if the length of this type is known without calculation. That + * is, if the length of this CBOR string, map or array is encoded in the data + * stream, this function returns true. If the length is not encoded, it returns + * false. + * + * If the length is known, code can call cbor_value_get_string_length(), + * cbor_value_get_array_length() or cbor_value_get_map_length() to obtain the + * length. If the length is not known but is necessary, code can use the + * cbor_value_calculate_string_length() function (no equivalent function is + * provided for maps and arrays). + */ + +/** + * \fn bool cbor_value_is_text_string(const CborValue *value) + * + * Returns true if the iterator \a value is valid and points to a CBOR text + * string. CBOR text strings are UTF-8 encoded and usually contain + * human-readable text. + * + * \sa cbor_value_is_valid(), cbor_value_get_string_length(), cbor_value_calculate_string_length(), + * cbor_value_copy_text_string(), cbor_value_dup_text_string() + */ + +/** + * \fn bool cbor_value_is_byte_string(const CborValue *value) + * + * Returns true if the iterator \a value is valid and points to a CBOR text + * string. CBOR byte strings are binary data with no specified encoding or + * format. + * + * \sa cbor_value_is_valid(), cbor_value_get_string_length(), cbor_value_calculate_string_length(), + * cbor_value_copy_byte_string(), cbor_value_dup_byte_string() + */ + +/** + * \fn CborError cbor_value_get_string_length(const CborValue *value, size_t *length) + * + * Extracts the length of the byte or text string that \a value points to and + * stores it in \a result. If the iterator \a value does not point to a text + * string or a byte string, the behaviour is undefined, so checking with \ref + * cbor_value_get_type, with \ref cbor_value_is_text_string or \ref + * cbor_value_is_byte_string is recommended. + * + * If the length of this string is not encoded in the CBOR data stream, this + * function will return the recoverable error CborErrorUnknownLength. You may + * also check whether that is the case by using cbor_value_is_length_known(). + * + * If the length of the string is required but the length was not encoded, use + * cbor_value_calculate_string_length(), but note that that function does not + * run in constant time. + * + * \note On 32-bit platforms, this function will return error condition of \ref + * CborErrorDataTooLarge if the stream indicates a length that is too big to + * fit in 32-bit. + * + * \sa cbor_value_is_valid(), cbor_value_is_length_known(), cbor_value_calculate_string_length() + */ + +/** + * Calculates the length of the byte or text string that \a value points to and + * stores it in \a len. If the iterator \a value does not point to a text + * string or a byte string, the behaviour is undefined, so checking with \ref + * cbor_value_get_type, with \ref cbor_value_is_text_string or \ref + * cbor_value_is_byte_string is recommended. + * + * This function is different from cbor_value_get_string_length() in that it + * calculates the length even for strings sent in chunks. For that reason, this + * function may not run in constant time (it will run in O(n) time on the + * number of chunks). It does use constant memory (O(1)). + * + * \note On 32-bit platforms, this function will return error condition of \ref + * CborErrorDataTooLarge if the stream indicates a length that is too big to + * fit in 32-bit. + * + * \sa cbor_value_get_string_length(), cbor_value_copy_text_string(), cbor_value_copy_byte_string(), cbor_value_is_length_known() + */ +CborError cbor_value_calculate_string_length(const CborValue *value, size_t *len) +{ + *len = SIZE_MAX; + return _cbor_value_copy_string(value, NULL, len, NULL); +} + +static inline void prepare_string_iteration(CborValue *it) +{ + if (!cbor_value_is_length_known(it)) { + /* chunked string: we're before the first chunk; + * advance to the first chunk */ + ++it->ptr; + it->flags |= CborIteratorFlag_IteratingStringChunks; + } +} + +CborError CBOR_INTERNAL_API_CC _cbor_value_prepare_string_iteration(CborValue *it) +{ + cbor_assert((it->flags & CborIteratorFlag_IteratingStringChunks) == 0); + prepare_string_iteration(it); + + /* are we at the end? */ + if (it->ptr == it->parser->end) + return CborErrorUnexpectedEOF; + return CborNoError; +} + +static CborError get_string_chunk(CborValue *it, const void **bufferptr, size_t *len) +{ + CborError err; + + /* Possible states: + * length known | iterating | meaning + * no | no | before the first chunk of a chunked string + * yes | no | at a non-chunked string + * no | yes | second or later chunk + * yes | yes | after a non-chunked string + */ + if (it->flags & CborIteratorFlag_IteratingStringChunks) { + /* already iterating */ + if (cbor_value_is_length_known(it)) { + /* if the length was known, it wasn't chunked, so finish iteration */ + goto last_chunk; + } + } else { + prepare_string_iteration(it); + } + + /* are we at the end? */ + if (it->ptr == it->parser->end) + return CborErrorUnexpectedEOF; + + if (*it->ptr == BreakByte) { + /* last chunk */ + ++it->ptr; +last_chunk: + *bufferptr = NULL; + *len = 0; + return preparse_next_value(it); + } else if ((uint8_t)(*it->ptr & MajorTypeMask) == it->type) { + err = extract_length(it->parser, &it->ptr, len); + if (err) + return err; + if (*len > (size_t)(it->parser->end - it->ptr)) + return CborErrorUnexpectedEOF; + + *bufferptr = it->ptr; + it->ptr += *len; + } else { + return CborErrorIllegalType; + } + + it->flags |= CborIteratorFlag_IteratingStringChunks; + return CborNoError; +} + +CborError CBOR_INTERNAL_API_CC +_cbor_value_get_string_chunk(const CborValue *value, const void **bufferptr, + size_t *len, CborValue *next) +{ + CborValue tmp; + if (!next) + next = &tmp; + *next = *value; + return get_string_chunk(next, bufferptr, len); +} + +/* We return uintptr_t so that we can pass memcpy directly as the iteration + * function. The choice is to optimize for memcpy, which is used in the base + * parser API (cbor_value_copy_string), while memcmp is used in convenience API + * only. */ +typedef uintptr_t (*IterateFunction)(char *, const uint8_t *, size_t); + +static uintptr_t iterate_noop(char *dest, const uint8_t *src, size_t len) +{ + (void)dest; + (void)src; + (void)len; + return true; +} + +static uintptr_t iterate_memcmp(char *s1, const uint8_t *s2, size_t len) +{ + return memcmp(s1, (const char *)s2, len) == 0; +} + +static uintptr_t iterate_memcpy(char *dest, const uint8_t *src, size_t len) +{ + return (uintptr_t)memcpy(dest, src, len); +} + +static CborError iterate_string_chunks(const CborValue *value, char *buffer, size_t *buflen, + bool *result, CborValue *next, IterateFunction func) +{ + CborError err; + CborValue tmp; + size_t total = 0; + const void *ptr; + + cbor_assert(cbor_value_is_byte_string(value) || cbor_value_is_text_string(value)); + if (!next) + next = &tmp; + *next = *value; + *result = true; + + while (1) { + size_t newTotal; + size_t chunkLen; + err = get_string_chunk(next, &ptr, &chunkLen); + if (err) + return err; + if (!ptr) + break; + + if (unlikely(add_check_overflow(total, chunkLen, &newTotal))) + return CborErrorDataTooLarge; + + if (*result && *buflen >= newTotal) + *result = !!func(buffer + total, (const uint8_t *)ptr, chunkLen); + else + *result = false; + + total = newTotal; + } + + /* is there enough room for the ending NUL byte? */ + if (*result && *buflen > total) { + uint8_t nul[] = { 0 }; + *result = !!func(buffer + total, nul, 1); + } + *buflen = total; + return CborNoError; +} + +/** + * \fn CborError cbor_value_copy_text_string(const CborValue *value, char *buffer, size_t *buflen, CborValue *next) + * + * Copies the string pointed to by \a value into the buffer provided at \a buffer + * of \a buflen bytes. If \a buffer is a NULL pointer, this function will not + * copy anything and will only update the \a next value. + * + * If the iterator \a value does not point to a text string, the behaviour is + * undefined, so checking with \ref cbor_value_get_type or \ref + * cbor_value_is_text_string is recommended. + * + * If the provided buffer length was too small, this function returns an error + * condition of \ref CborErrorOutOfMemory. If you need to calculate the length + * of the string in order to preallocate a buffer, use + * cbor_value_calculate_string_length(). + * + * On success, this function sets the number of bytes copied to \c{*buflen}. If + * the buffer is large enough, this function will insert a null byte after the + * last copied byte, to facilitate manipulation of text strings. That byte is + * not included in the returned value of \c{*buflen}. If there was no space for + * the terminating null, no error is returned, so callers must check the value + * of *buflen after the call, before relying on the '\0'; if it has not been + * changed by the call, there is no '\0'-termination on the buffer's contents. + * + * The \a next pointer, if not null, will be updated to point to the next item + * after this string. If \a value points to the last item, then \a next will be + * invalid. + * + * This function may not run in constant time (it will run in O(n) time on the + * number of chunks). It requires constant memory (O(1)). + * + * \note This function does not perform UTF-8 validation on the incoming text + * string. + * + * \sa cbor_value_get_text_string_chunk() cbor_value_dup_text_string(), cbor_value_copy_byte_string(), cbor_value_get_string_length(), cbor_value_calculate_string_length() + */ + +/** + * \fn CborError cbor_value_copy_byte_string(const CborValue *value, uint8_t *buffer, size_t *buflen, CborValue *next) + * + * Copies the string pointed by \a value into the buffer provided at \a buffer + * of \a buflen bytes. If \a buffer is a NULL pointer, this function will not + * copy anything and will only update the \a next value. + * + * If the iterator \a value does not point to a byte string, the behaviour is + * undefined, so checking with \ref cbor_value_get_type or \ref + * cbor_value_is_byte_string is recommended. + * + * If the provided buffer length was too small, this function returns an error + * condition of \ref CborErrorOutOfMemory. If you need to calculate the length + * of the string in order to preallocate a buffer, use + * cbor_value_calculate_string_length(). + * + * On success, this function sets the number of bytes copied to \c{*buflen}. If + * the buffer is large enough, this function will insert a null byte after the + * last copied byte, to facilitate manipulation of null-terminated strings. + * That byte is not included in the returned value of \c{*buflen}. + * + * The \a next pointer, if not null, will be updated to point to the next item + * after this string. If \a value points to the last item, then \a next will be + * invalid. + * + * This function may not run in constant time (it will run in O(n) time on the + * number of chunks). It requires constant memory (O(1)). + * + * \sa cbor_value_get_byte_string_chunk(), cbor_value_dup_text_string(), cbor_value_copy_text_string(), cbor_value_get_string_length(), cbor_value_calculate_string_length() + */ + +CborError _cbor_value_copy_string(const CborValue *value, void *buffer, + size_t *buflen, CborValue *next) +{ + bool copied_all; + CborError err = iterate_string_chunks(value, (char*)buffer, buflen, &copied_all, next, + buffer ? iterate_memcpy : iterate_noop); + return err ? err : + copied_all ? CborNoError : CborErrorOutOfMemory; +} + +/** + * Compares the entry \a value with the string \a string and stores the result + * in \a result. If the value is different from \a string \a result will + * contain \c false. + * + * The entry at \a value may be a tagged string. If \a value is not a string or + * a tagged string, the comparison result will be false. + * + * CBOR requires text strings to be encoded in UTF-8, but this function does + * not validate either the strings in the stream or the string \a string to be + * matched. Moreover, comparison is done on strict codepoint comparison, + * without any Unicode normalization. + * + * This function may not run in constant time (it will run in O(n) time on the + * number of chunks). It requires constant memory (O(1)). + * + * \sa cbor_value_skip_tag(), cbor_value_copy_text_string() + */ +CborError cbor_value_text_string_equals(const CborValue *value, const char *string, bool *result) +{ + size_t len; + CborValue copy = *value; + CborError err = cbor_value_skip_tag(©); + if (err) + return err; + if (!cbor_value_is_text_string(©)) { + *result = false; + return CborNoError; + } + + len = strlen(string); + return iterate_string_chunks(©, CONST_CAST(char *, string), &len, result, NULL, iterate_memcmp); +} + +/** + * \fn bool cbor_value_is_array(const CborValue *value) + * + * Returns true if the iterator \a value is valid and points to a CBOR array. + * + * \sa cbor_value_is_valid(), cbor_value_is_map() + */ + +/** + * \fn CborError cbor_value_get_array_length(const CborValue *value, size_t *length) + * + * Extracts the length of the CBOR array that \a value points to and stores it + * in \a result. If the iterator \a value does not point to a CBOR array, the + * behaviour is undefined, so checking with \ref cbor_value_get_type or \ref + * cbor_value_is_array is recommended. + * + * If the length of this array is not encoded in the CBOR data stream, this + * function will return the recoverable error CborErrorUnknownLength. You may + * also check whether that is the case by using cbor_value_is_length_known(). + * + * \note On 32-bit platforms, this function will return error condition of \ref + * CborErrorDataTooLarge if the stream indicates a length that is too big to + * fit in 32-bit. + * + * \sa cbor_value_is_valid(), cbor_value_is_length_known() + */ + +/** + * \fn bool cbor_value_is_map(const CborValue *value) + * + * Returns true if the iterator \a value is valid and points to a CBOR map. + * + * \sa cbor_value_is_valid(), cbor_value_is_array() + */ + +/** + * \fn CborError cbor_value_get_map_length(const CborValue *value, size_t *length) + * + * Extracts the length of the CBOR map that \a value points to and stores it in + * \a result. If the iterator \a value does not point to a CBOR map, the + * behaviour is undefined, so checking with \ref cbor_value_get_type or \ref + * cbor_value_is_map is recommended. + * + * If the length of this map is not encoded in the CBOR data stream, this + * function will return the recoverable error CborErrorUnknownLength. You may + * also check whether that is the case by using cbor_value_is_length_known(). + * + * \note On 32-bit platforms, this function will return error condition of \ref + * CborErrorDataTooLarge if the stream indicates a length that is too big to + * fit in 32-bit. + * + * \sa cbor_value_is_valid(), cbor_value_is_length_known() + */ + +/** + * Attempts to find the value in map \a map that corresponds to the text string + * entry \a string. If the iterator \a value does not point to a CBOR map, the + * behaviour is undefined, so checking with \ref cbor_value_get_type or \ref + * cbor_value_is_map is recommended. + * + * If the item is found, it is stored in \a result. If no item is found + * matching the key, then \a result will contain an element of type \ref + * CborInvalidType. Matching is performed using + * cbor_value_text_string_equals(), so tagged strings will also match. + * + * This function has a time complexity of O(n) where n is the number of + * elements in the map to be searched. In addition, this function is has O(n) + * memory requirement based on the number of nested containers (maps or arrays) + * found as elements of this map. + * + * \sa cbor_value_is_valid(), cbor_value_text_string_equals(), cbor_value_advance() + */ +CborError cbor_value_map_find_value(const CborValue *map, const char *string, CborValue *element) +{ + CborError err; + size_t len = strlen(string); + cbor_assert(cbor_value_is_map(map)); + err = cbor_value_enter_container(map, element); + if (err) + goto error; + + while (!cbor_value_at_end(element)) { + /* find the non-tag so we can compare */ + err = cbor_value_skip_tag(element); + if (err) + goto error; + if (cbor_value_is_text_string(element)) { + bool equals; + size_t dummyLen = len; + err = iterate_string_chunks(element, CONST_CAST(char *, string), &dummyLen, + &equals, element, iterate_memcmp); + if (err) + goto error; + if (equals) + return preparse_value(element); + } else { + /* skip this key */ + err = cbor_value_advance(element); + if (err) + goto error; + } + + /* skip this value */ + err = cbor_value_skip_tag(element); + if (err) + goto error; + err = cbor_value_advance(element); + if (err) + goto error; + } + + /* not found */ + element->type = CborInvalidType; + return CborNoError; + +error: + element->type = CborInvalidType; + return err; +} + +/** + * \fn bool cbor_value_is_float(const CborValue *value) + * + * Returns true if the iterator \a value is valid and points to a CBOR + * single-precision floating point (32-bit). + * + * \sa cbor_value_is_valid(), cbor_value_is_double(), cbor_value_is_half_float() + */ + +/** + * \fn CborError cbor_value_get_float(const CborValue *value, float *result) + * + * Retrieves the CBOR single-precision floating point (32-bit) value that \a + * value points to and stores it in \a result. If the iterator \a value does + * not point to a single-precision floating point value, the behavior is + * undefined, so checking with \ref cbor_value_get_type or with \ref + * cbor_value_is_float is recommended. + * + * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_float(), cbor_value_get_double() + */ + +/** + * \fn bool cbor_value_is_double(const CborValue *value) + * + * Returns true if the iterator \a value is valid and points to a CBOR + * double-precision floating point (64-bit). + * + * \sa cbor_value_is_valid(), cbor_value_is_float(), cbor_value_is_half_float() + */ + +/** + * \fn CborError cbor_value_get_double(const CborValue *value, float *result) + * + * Retrieves the CBOR double-precision floating point (64-bit) value that \a + * value points to and stores it in \a result. If the iterator \a value does + * not point to a double-precision floating point value, the behavior is + * undefined, so checking with \ref cbor_value_get_type or with \ref + * cbor_value_is_double is recommended. + * + * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_double(), cbor_value_get_float() + */ + +/** + * \fn bool cbor_value_is_half_float(const CborValue *value) + * + * Returns true if the iterator \a value is valid and points to a CBOR + * single-precision floating point (16-bit). + * + * \sa cbor_value_is_valid(), cbor_value_is_double(), cbor_value_is_float() + */ + +/** + * Retrieves the CBOR half-precision floating point (16-bit) value that \a + * value points to and stores it in \a result. If the iterator \a value does + * not point to a half-precision floating point value, the behavior is + * undefined, so checking with \ref cbor_value_get_type or with \ref + * cbor_value_is_half_float is recommended. + * + * Note: since the C language does not have a standard type for half-precision + * floating point, this function takes a \c{void *} as a parameter for the + * storage area, which must be at least 16 bits wide. + * + * \sa cbor_value_get_type(), cbor_value_is_valid(), cbor_value_is_half_float(), cbor_value_get_float() + */ +CborError cbor_value_get_half_float(const CborValue *value, void *result) +{ + uint16_t v; + cbor_assert(cbor_value_is_half_float(value)); + + /* size has been computed already */ + v = get16(value->ptr + 1); + memcpy(result, &v, sizeof(v)); + return CborNoError; +} + +/** @} */ diff --git a/client/tinycbor/cborparser_dup_string.c b/client/tinycbor/cborparser_dup_string.c new file mode 100644 index 000000000..061c5ac77 --- /dev/null +++ b/client/tinycbor/cborparser_dup_string.c @@ -0,0 +1,119 @@ +/**************************************************************************** +** +** Copyright (C) 2016 Intel Corporation +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +#ifndef _BSD_SOURCE +#define _BSD_SOURCE 1 +#endif +#ifndef _DEFAULT_SOURCE +#define _DEFAULT_SOURCE 1 +#endif +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS 1 +#endif + +#include "cbor.h" +#include "compilersupport_p.h" +#include + +/** + * \fn CborError cbor_value_dup_text_string(const CborValue *value, char **buffer, size_t *buflen, CborValue *next) + * + * Allocates memory for the string pointed by \a value and copies it into this + * buffer. The pointer to the buffer is stored in \a buffer and the number of + * bytes copied is stored in \a buflen (those variables must not be NULL). + * + * If the iterator \a value does not point to a text string, the behaviour is + * undefined, so checking with \ref cbor_value_get_type or \ref + * cbor_value_is_text_string is recommended. + * + * If \c malloc returns a NULL pointer, this function will return error + * condition \ref CborErrorOutOfMemory. + * + * On success, \c{*buffer} will contain a valid pointer that must be freed by + * calling \c{free()}. This is the case even for zero-length strings. + * + * The \a next pointer, if not null, will be updated to point to the next item + * after this string. If \a value points to the last item, then \a next will be + * invalid. + * + * This function may not run in constant time (it will run in O(n) time on the + * number of chunks). It requires constant memory (O(1)) in addition to the + * malloc'ed block. + * + * \note This function does not perform UTF-8 validation on the incoming text + * string. + * + * \sa cbor_value_get_text_string_chunk(), cbor_value_copy_text_string(), cbor_value_dup_byte_string() + */ + +/** + * \fn CborError cbor_value_dup_byte_string(const CborValue *value, uint8_t **buffer, size_t *buflen, CborValue *next) + * + * Allocates memory for the string pointed by \a value and copies it into this + * buffer. The pointer to the buffer is stored in \a buffer and the number of + * bytes copied is stored in \a buflen (those variables must not be NULL). + * + * If the iterator \a value does not point to a byte string, the behaviour is + * undefined, so checking with \ref cbor_value_get_type or \ref + * cbor_value_is_byte_string is recommended. + * + * If \c malloc returns a NULL pointer, this function will return error + * condition \ref CborErrorOutOfMemory. + * + * On success, \c{*buffer} will contain a valid pointer that must be freed by + * calling \c{free()}. This is the case even for zero-length strings. + * + * The \a next pointer, if not null, will be updated to point to the next item + * after this string. If \a value points to the last item, then \a next will be + * invalid. + * + * This function may not run in constant time (it will run in O(n) time on the + * number of chunks). It requires constant memory (O(1)) in addition to the + * malloc'ed block. + * + * \sa cbor_value_get_text_string_chunk(), cbor_value_copy_byte_string(), cbor_value_dup_text_string() + */ +CborError _cbor_value_dup_string(const CborValue *value, void **buffer, size_t *buflen, CborValue *next) +{ + CborError err; + cbor_assert(buffer); + cbor_assert(buflen); + *buflen = SIZE_MAX; + err = _cbor_value_copy_string(value, NULL, buflen, NULL); + if (err) + return err; + + ++*buflen; + *buffer = malloc(*buflen); + if (!*buffer) { + /* out of memory */ + return CborErrorOutOfMemory; + } + err = _cbor_value_copy_string(value, *buffer, buflen, next); + if (err) { + free(*buffer); + return err; + } + return CborNoError; +} diff --git a/client/tinycbor/cborpretty.c b/client/tinycbor/cborpretty.c new file mode 100644 index 000000000..b8825deee --- /dev/null +++ b/client/tinycbor/cborpretty.c @@ -0,0 +1,578 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Intel Corporation +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +#define _BSD_SOURCE 1 +#define _DEFAULT_SOURCE 1 +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS 1 +#endif + +#include "cbor.h" +#include "cborinternal_p.h" +#include "compilersupport_p.h" +#include "utf8_p.h" + +#include +#include + +/** + * \defgroup CborPretty Converting CBOR to text + * \brief Group of functions used to convert CBOR to text form. + * + * This group contains two functions that can be used to convert a \ref + * CborValue object to a text representation. This module attempts to follow + * the recommendations from RFC 7049 section 6 "Diagnostic Notation", though it + * has a few differences. They are noted below. + * + * TinyCBOR does not provide a way to convert from the text representation back + * to encoded form. To produce a text form meant to be parsed, CborToJson is + * recommended instead. + * + * Either of the functions in this section will attempt to convert exactly one + * CborValue object to text. Those functions may return any error documented + * for the functions for CborParsing. In addition, if the C standard library + * stream functions return with error, the text conversion will return with + * error CborErrorIO. + * + * These functions also perform UTF-8 validation in CBOR text strings. If they + * encounter a sequence of bytes that is not permitted in UTF-8, they will return + * CborErrorInvalidUtf8TextString. That includes encoding of surrogate points + * in UTF-8. + * + * \warning The output type produced by these functions is not guaranteed to + * remain stable. A future update of TinyCBOR may produce different output for + * the same input and parsers may be unable to handle it. + * + * \sa CborParsing, CborToJson, cbor_parser_init() + */ + +/** + * \addtogroup CborPretty + * @{ + *

Text format

+ * + * As described in RFC 7049 section 6 "Diagnostic Notation", the format is + * largely borrowed from JSON, but modified to suit CBOR's different data + * types. TinyCBOR makes further modifications to distinguish different, but + * similar values. + * + * CBOR values are currently encoded as follows: + * \par Integrals (unsigned and negative) + * Base-10 (decimal) text representation of the value + * \par Byte strings: + * "h'" followed by the Base16 (hex) representation of the binary data, followed by an ending quote (') + * \par Text strings: + * C-style escaped string in quotes, with C11/C++11 escaping of Unicode codepoints above U+007F. + * \par Tags: + * Tag value, with the tagged value in parentheses. No special encoding of the tagged value is performed. + * \par Simple types: + * "simple(nn)" where \c nn is the simple value + * \par Null: + * \c null + * \par Undefined: + * \c undefined + * \par Booleans: + * \c true or \c false + * \par Floating point: + * If NaN or infinite, the actual words \c NaN or \c infinite. + * Otherwise, the decimal representation with as many digits as necessary to ensure no loss of information. + * By default, float values are suffixed by "f" and half-float values suffixed by "f16" (doubles have no suffix). + * If the CborPrettyNumericEncodingIndicators flag is active, the values instead are encoded following the + * Section 6 recommended encoding indicators: float values are suffixed with "_2" and half-float with "_1". + * A decimal point is always present. + * \par Arrays: + * Comma-separated list of elements, enclosed in square brackets ("[" and "]"). + * \par Maps: + * Comma-separated list of key-value pairs, with the key and value separated + * by a colon (":"), enclosed in curly braces ("{" and "}"). + * + * The CborPrettyFlags enumerator contains flags to control some aspects of the + * encoding: + * \par String fragmentation + * When the CborPrettyShowStringFragments option is active, text and byte + * strings that are transmitted in fragments are shown instead inside + * parentheses ("(" and ")") with no preceding number and each fragment is + * displayed individually. If a tag precedes the string, then the output + * will contain a double set of parentheses. If the option is not active, + * the fragments are merged together and the display will not show any + * difference from a string transmitted with determinate length. + * \par Encoding indicators + * Numbers and lengths in CBOR can be encoded in multiple representations. + * If the CborPrettyIndicateOverlongNumbers option is active, numbers + * and lengths that are transmitted in a longer encoding than necessary + * will be indicated, by appending an underscore ("_") to either the + * number or the opening bracket or brace, followed by a number + * indicating the CBOR additional information: 0 for 1 byte, 1 for 2 + * bytes, 2 for 4 bytes and 3 for 8 bytes. + * If the CborPrettyIndicateIndeterminateLength option is active, maps, + * arrays and strings encoded with indeterminate length will be marked by + * an underscore after the opening bracket or brace or the string (if not + * showing fragments), without a number after it. + */ + +/** + * \enum CborPrettyFlags + * The CborPrettyFlags enum contains flags that control the conversion of CBOR to text format. + * + * \value CborPrettyNumericEncodingIndicators Use numeric encoding indicators instead of textual for float and half-float. + * \value CborPrettyTextualEncodingIndicators Use textual encoding indicators for float ("f") and half-float ("f16"). + * \value CborPrettyIndicateIndeterminateLength (default) Indicate when a map or array has indeterminate length. + * \value CborPrettyIndicateOverlongNumbers Indicate when a number or length was encoded with more bytes than needed. + * \value CborPrettyShowStringFragments If the byte or text string is transmitted in chunks, show each individually. + * \value CborPrettyMergeStringFragment Merge all chunked byte or text strings and display them in a single entry. + * \value CborPrettyDefaultFlags Default conversion flags. + */ + +#ifndef CBOR_NO_FLOATING_POINT +static inline bool convertToUint64(double v, uint64_t *absolute) +{ + double supremum; + v = fabs(v); + + /* C11 standard section 6.3.1.4 "Real floating and integer" says: + * + * 1 When a finite value of real floating type is converted to an integer + * type other than _Bool, the fractional part is discarded (i.e., the + * value is truncated toward zero). If the value of the integral part + * cannot be represented by the integer type, the behavior is undefined. + * + * So we must perform a range check that v <= UINT64_MAX, but we can't use + * UINT64_MAX + 1.0 because the standard continues: + * + * 2 When a value of integer type is converted to a real floating type, if + * the value being converted can be represented exactly in the new type, + * it is unchanged. If the value being converted is in the range of + * values that can be represented but cannot be represented exactly, the + * result is either the nearest higher or nearest lower representable + * value, chosen in an implementation-defined manner. + */ + supremum = -2.0 * INT64_MIN; /* -2 * (- 2^63) == 2^64 */ + if (v >= supremum) + return false; + + /* Now we can convert, these two conversions cannot be UB */ + *absolute = v; + return *absolute == v; +} +#endif + +static void printRecursionLimit(CborStreamFunction stream, void *out) +{ + stream(out, ""); +} + +static CborError hexDump(CborStreamFunction stream, void *out, const void *ptr, size_t n) +{ + const uint8_t *buffer = (const uint8_t *)ptr; + CborError err = CborNoError; + while (n-- && !err) + err = stream(out, "%02" PRIx8, *buffer++); + + return err; +} + +/* This function decodes buffer as UTF-8 and prints as escaped UTF-16. + * On UTF-8 decoding error, it returns CborErrorInvalidUtf8TextString */ +static CborError utf8EscapedDump(CborStreamFunction stream, void *out, const void *ptr, size_t n) +{ + const uint8_t *buffer = (const uint8_t *)ptr; + const uint8_t * const end = buffer + n; + CborError err = CborNoError; + + while (buffer < end && !err) { + uint32_t uc = get_utf8(&buffer, end); + if (uc == ~0U) + return CborErrorInvalidUtf8TextString; + + if (uc < 0x80) { + /* single-byte UTF-8 */ + unsigned char escaped = (unsigned char)uc; + if (uc < 0x7f && uc >= 0x20 && uc != '\\' && uc != '"') { + err = stream(out, "%c", (char)uc); + continue; + } + + /* print as an escape sequence */ + switch (uc) { + case '"': + case '\\': + break; + case '\b': + escaped = 'b'; + break; + case '\f': + escaped = 'f'; + break; + case '\n': + escaped = 'n'; + break; + case '\r': + escaped = 'r'; + break; + case '\t': + escaped = 't'; + break; + default: + goto print_utf16; + } + err = stream(out, "\\%c", escaped); + continue; + } + + /* now print the sequence */ + if (uc > 0xffffU) { + /* needs surrogate pairs */ + err = stream(out, "\\u%04" PRIX32 "\\u%04" PRIX32, + (uc >> 10) + 0xd7c0, /* high surrogate */ + (uc % 0x0400) + 0xdc00); + } else { +print_utf16: + /* no surrogate pair needed */ + err = stream(out, "\\u%04" PRIX32, uc); + } + } + return err; +} + +static const char *resolve_indicator(const uint8_t *ptr, const uint8_t *end, int flags) +{ + static const char indicators[8][3] = { + "_0", "_1", "_2", "_3", + "", "", "", /* these are not possible */ + "_" + }; + const char *no_indicator = indicators[5]; /* empty string */ + uint8_t additional_information; + uint8_t expected_information; + uint64_t value; + CborError err; + + if (ptr == end) + return NULL; /* CborErrorUnexpectedEOF */ + + additional_information = (*ptr & SmallValueMask); + if (additional_information < Value8Bit) + return no_indicator; + + /* determine whether to show anything */ + if ((flags & CborPrettyIndicateIndeterminateLength) && + additional_information == IndefiniteLength) + return indicators[IndefiniteLength - Value8Bit]; + if ((flags & CborPrettyIndicateOverlongNumbers) == 0) + return no_indicator; + + err = _cbor_value_extract_number(&ptr, end, &value); + if (err) + return NULL; /* CborErrorUnexpectedEOF */ + + expected_information = Value8Bit - 1; + if (value >= Value8Bit) + ++expected_information; + if (value > 0xffU) + ++expected_information; + if (value > 0xffffU) + ++expected_information; + if (value > 0xffffffffU) + ++expected_information; + return expected_information == additional_information ? + no_indicator : + indicators[additional_information - Value8Bit]; +} + +static const char *get_indicator(const CborValue *it, int flags) +{ + return resolve_indicator(it->ptr, it->parser->end, flags); +} + +static CborError value_to_pretty(CborStreamFunction stream, void *out, CborValue *it, int flags, int recursionsLeft); +static CborError container_to_pretty(CborStreamFunction stream, void *out, CborValue *it, CborType containerType, + int flags, int recursionsLeft) +{ + const char *comma = ""; + CborError err = CborNoError; + + if (!recursionsLeft) { + printRecursionLimit(stream, out); + return err; /* do allow the dumping to continue */ + } + + while (!cbor_value_at_end(it) && !err) { + err = stream(out, "%s", comma); + comma = ", "; + + if (!err) + err = value_to_pretty(stream, out, it, flags, recursionsLeft); + + if (containerType == CborArrayType) + continue; + + /* map: that was the key, so get the value */ + if (!err) + err = stream(out, ": "); + if (!err) + err = value_to_pretty(stream, out, it, flags, recursionsLeft); + } + return err; +} + +static CborError value_to_pretty(CborStreamFunction stream, void *out, CborValue *it, int flags, int recursionsLeft) +{ + CborError err = CborNoError; + CborType type = cbor_value_get_type(it); + switch (type) { + case CborArrayType: + case CborMapType: { + /* recursive type */ + CborValue recursed; + const char *indicator = get_indicator(it, flags); + const char *space = *indicator ? " " : indicator; + + err = stream(out, "%c%s%s", type == CborArrayType ? '[' : '{', indicator, space); + if (err) + return err; + + err = cbor_value_enter_container(it, &recursed); + if (err) { + it->ptr = recursed.ptr; + return err; /* parse error */ + } + err = container_to_pretty(stream, out, &recursed, type, flags, recursionsLeft - 1); + if (err) { + it->ptr = recursed.ptr; + return err; /* parse error */ + } + err = cbor_value_leave_container(it, &recursed); + if (err) + return err; /* parse error */ + + return stream(out, type == CborArrayType ? "]" : "}"); + } + + case CborIntegerType: { + uint64_t val; + cbor_value_get_raw_integer(it, &val); /* can't fail */ + + if (cbor_value_is_unsigned_integer(it)) { + err = stream(out, "%" PRIu64, val); + } else { + /* CBOR stores the negative number X as -1 - X + * (that is, -1 is stored as 0, -2 as 1 and so forth) */ + if (++val) { /* unsigned overflow may happen */ + err = stream(out, "-%" PRIu64, val); + } else { + /* overflown + * 0xffff`ffff`ffff`ffff + 1 = + * 0x1`0000`0000`0000`0000 = 18446744073709551616 (2^64) */ + err = stream(out, "-18446744073709551616"); + } + } + if (!err) + err = stream(out, "%s", get_indicator(it, flags)); + break; + } + + case CborByteStringType: + case CborTextStringType: { + size_t n = 0; + const void *ptr; + bool showingFragments = (flags & CborPrettyShowStringFragments) && !cbor_value_is_length_known(it); + const char *separator = ""; + char close = '\''; + char open[3] = "h'"; + const char *indicator = NULL; + + if (type == CborTextStringType) { + close = open[0] = '"'; + open[1] = '\0'; + } + + if (showingFragments) { + err = stream(out, "(_ "); + if (!err) + err = _cbor_value_prepare_string_iteration(it); + } else { + err = stream(out, "%s", open); + } + + while (!err) { + if (showingFragments || indicator == NULL) { + /* any iteration, except the second for a non-chunked string */ + indicator = resolve_indicator(it->ptr, it->parser->end, flags); + } + + err = _cbor_value_get_string_chunk(it, &ptr, &n, it); + if (!ptr) + break; + + if (!err && showingFragments) + err = stream(out, "%s%s", separator, open); + if (!err) + err = (type == CborByteStringType ? + hexDump(stream, out, ptr, n) : + utf8EscapedDump(stream, out, ptr, n)); + if (!err && showingFragments) { + err = stream(out, "%c%s", close, indicator); + separator = ", "; + } + } + + if (!err) { + if (showingFragments) + err = stream(out, ")"); + else + err = stream(out, "%c%s", close, indicator); + } + return err; + } + + case CborTagType: { + CborTag tag; + cbor_value_get_tag(it, &tag); /* can't fail */ + err = stream(out, "%" PRIu64 "%s(", tag, get_indicator(it, flags)); + if (!err) + err = cbor_value_advance_fixed(it); + if (!err && recursionsLeft) + err = value_to_pretty(stream, out, it, flags, recursionsLeft - 1); + else if (!err) + printRecursionLimit(stream, out); + if (!err) + err = stream(out, ")"); + return err; + } + + case CborSimpleType: { + /* simple types can't fail and can't have overlong encoding */ + uint8_t simple_type; + cbor_value_get_simple_type(it, &simple_type); + err = stream(out, "simple(%" PRIu8 ")", simple_type); + break; + } + + case CborNullType: + err = stream(out, "null"); + break; + + case CborUndefinedType: + err = stream(out, "undefined"); + break; + + case CborBooleanType: { + bool val; + cbor_value_get_boolean(it, &val); /* can't fail */ + err = stream(out, val ? "true" : "false"); + break; + } + +#ifndef CBOR_NO_FLOATING_POINT + case CborDoubleType: { + const char *suffix; + double val; + int r; + uint64_t ival; + + if (false) { + float f; + case CborFloatType: + cbor_value_get_float(it, &f); + val = f; + suffix = flags & CborPrettyNumericEncodingIndicators ? "_2" : "f"; + } else if (false) { + uint16_t f16; + case CborHalfFloatType: +#ifndef CBOR_NO_HALF_FLOAT_TYPE + cbor_value_get_half_float(it, &f16); + val = decode_half(f16); + suffix = flags & CborPrettyNumericEncodingIndicators ? "_1" : "f16"; +#else + (void)f16; + err = CborErrorUnsupportedType; + break; +#endif + } else { + cbor_value_get_double(it, &val); + suffix = ""; + } + + if ((flags & CborPrettyNumericEncodingIndicators) == 0) { + r = fpclassify(val); + if (r == FP_NAN || r == FP_INFINITE) + suffix = ""; + } + + if (convertToUint64(val, &ival)) { + /* this double value fits in a 64-bit integer, so show it as such + * (followed by a floating point suffix, to disambiguate) */ + err = stream(out, "%s%" PRIu64 ".%s", val < 0 ? "-" : "", ival, suffix); + } else { + /* this number is definitely not a 64-bit integer */ + err = stream(out, "%." DBL_DECIMAL_DIG_STR "g%s", val, suffix); + } + break; + } +#else + case CborDoubleType: + case CborFloatType: + case CborHalfFloatType: + err = CborErrorUnsupportedType; + break; +#endif /* !CBOR_NO_FLOATING_POINT */ + + case CborInvalidType: + err = stream(out, "invalid"); + if (err) + return err; + return CborErrorUnknownType; + } + + if (!err) + err = cbor_value_advance_fixed(it); + return err; +} + +/** + * Converts the current CBOR type pointed by \a value to its textual + * representation and writes it to the stream by calling the \a streamFunction. + * If an error occurs, this function returns an error code similar to + * \ref CborParsing. + * + * The textual representation can be controlled by the \a flags parameter (see + * \ref CborPrettyFlags for more information). + * + * If no error ocurred, this function advances \a value to the next element. + * Often, concatenating the text representation of multiple elements can be + * done by appending a comma to the output stream in between calls to this + * function. + * + * The \a streamFunction function will be called with the \a token value as the + * first parameter and a printf-style format string as the second, with a variable + * number of further parameters. + * + * \sa cbor_value_to_pretty(), cbor_value_to_json_advance() + */ +CborError cbor_value_to_pretty_stream(CborStreamFunction streamFunction, void *token, CborValue *value, int flags) +{ + return value_to_pretty(streamFunction, token, value, flags, CBOR_PARSER_MAX_RECURSIONS); +} + +/** @} */ diff --git a/client/tinycbor/cborpretty_stdio.c b/client/tinycbor/cborpretty_stdio.c new file mode 100644 index 000000000..20131850c --- /dev/null +++ b/client/tinycbor/cborpretty_stdio.c @@ -0,0 +1,87 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Intel Corporation +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +#include "cbor.h" +#include +#include + +static CborError cbor_fprintf(void *out, const char *fmt, ...) +{ + int n; + + va_list list; + va_start(list, fmt); + n = vfprintf((FILE *)out, fmt, list); + va_end(list); + + return n < 0 ? CborErrorIO : CborNoError; +} + +/** + * \fn CborError cbor_value_to_pretty(FILE *out, const CborValue *value) + * + * Converts the current CBOR type pointed to by \a value to its textual + * representation and writes it to the \a out stream. If an error occurs, this + * function returns an error code similar to CborParsing. + * + * \sa cbor_value_to_pretty_advance(), cbor_value_to_json_advance() + */ + +/** + * Converts the current CBOR type pointed to by \a value to its textual + * representation and writes it to the \a out stream. If an error occurs, this + * function returns an error code similar to CborParsing. + * + * If no error ocurred, this function advances \a value to the next element. + * Often, concatenating the text representation of multiple elements can be + * done by appending a comma to the output stream in between calls to this + * function. + * + * \sa cbor_value_to_pretty(), cbor_value_to_pretty_stream(), cbor_value_to_json_advance() + */ +CborError cbor_value_to_pretty_advance(FILE *out, CborValue *value) +{ + return cbor_value_to_pretty_stream(cbor_fprintf, out, value, CborPrettyDefaultFlags); +} + +/** + * Converts the current CBOR type pointed to by \a value to its textual + * representation and writes it to the \a out stream. If an error occurs, this + * function returns an error code similar to CborParsing. + * + * The textual representation can be controlled by the \a flags parameter (see + * CborPrettyFlags for more information). + * + * If no error ocurred, this function advances \a value to the next element. + * Often, concatenating the text representation of multiple elements can be + * done by appending a comma to the output stream in between calls to this + * function. + * + * \sa cbor_value_to_pretty_stream(), cbor_value_to_pretty(), cbor_value_to_json_advance() + */ +CborError cbor_value_to_pretty_advance_flags(FILE *out, CborValue *value, int flags) +{ + return cbor_value_to_pretty_stream(cbor_fprintf, out, value, flags); +} + diff --git a/client/tinycbor/cbortojson.c b/client/tinycbor/cbortojson.c new file mode 100644 index 000000000..5a1a2e5dc --- /dev/null +++ b/client/tinycbor/cbortojson.c @@ -0,0 +1,699 @@ +/**************************************************************************** +** +** Copyright (C) 2018 Intel Corporation +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +#define _BSD_SOURCE 1 +#define _DEFAULT_SOURCE 1 +#define _GNU_SOURCE 1 +#define _POSIX_C_SOURCE 200809L +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS 1 +#endif + +#include "cbor.h" +#include "cborjson.h" +#include "cborinternal_p.h" +#include "compilersupport_p.h" + +#include +#include +#include +#include + +/** + * \defgroup CborToJson Converting CBOR to JSON + * \brief Group of functions used to convert CBOR to JSON. + * + * This group contains two functions that can be used to convert a \ref + * CborValue object to an equivalent JSON representation. This module attempts + * to follow the recommendations from RFC 7049 section 4.1 "Converting from + * CBOR to JSON", though it has a few differences. They are noted below. + * + * These functions produce a "minified" JSON output, with no spacing, + * indentation or line breaks. If those are necessary, they need to be applied + * in a post-processing phase. + * + * Note that JSON cannot support all CBOR types with fidelity, so the + * conversion is usually lossy. For that reason, TinyCBOR supports adding a set + * of metadata JSON values that can be used by a JSON-to-CBOR converter to + * restore the original data types. + * + * The TinyCBOR library does not provide a way to convert from JSON + * representation back to encoded form. However, it provides a tool called + * \c json2cbor which can be used for that purpose. That tool supports the + * metadata format that these functions may produce. + * + * Either of the functions in this section will attempt to convert exactly one + * CborValue object to JSON. Those functions may return any error documented + * for the functions for CborParsing. In addition, if the C standard library + * stream functions return with error, the text conversion will return with + * error CborErrorIO. + * + * These functions also perform UTF-8 validation in CBOR text strings. If they + * encounter a sequence of bytes that is not permitted in UTF-8, they will return + * CborErrorInvalidUtf8TextString. That includes encoding of surrogate points + * in UTF-8. + * + * \warning The metadata produced by these functions is not guaranteed to + * remain stable. A future update of TinyCBOR may produce different output for + * the same input and parsers may be unable to handle it. + * + * \sa CborParsing, CborPretty, cbor_parser_init() + */ + +/** + * \addtogroup CborToJson + * @{ + *

Conversion limitations

+ * + * When converting from CBOR to JSON, there may be information loss. This + * section lists the possible scenarios. + * + * \par Number precision: + * ALL JSON numbers, due to its JavaScript heritage, are IEEE 754 + * double-precision floating point. This means JSON is not capable of + * representing all integers numbers outside the range [-(253)+1, + * 253-1] and is not capable of representing NaN or infinite. If the + * CBOR data contains a number outside the valid range, the conversion will + * lose precision. If the input was NaN or infinite, the result of the + * conversion will be the JSON null value. In addition, the distinction between + * half-, single- and double-precision is lost. + * + * \par + * If enabled, the original value and original type are stored in the metadata. + * + * \par Non-native types: + * CBOR's type system is richer than JSON's, which means some data values + * cannot be represented when converted to JSON. The conversion silently turns + * them into strings: CBOR simple types become "simple(nn)" where \c nn is the + * simple type's value, with the exception of CBOR undefined, which becomes + * "undefined", while CBOR byte strings are converted to an Base16, Base64, or + * Base64url encoding + * + * \par + * If enabled, the original type is stored in the metadata. + * + * \par Presence of tags: + * JSON has no support for tagged values, so by default tags are dropped when + * converting to JSON. However, if the CborConvertObeyByteStringTags option is + * active (default), then certain known tags are honored and are used to format + * the conversion of the tagged byte string to JSON. + * + * \par + * If the CborConvertTagsToObjects option is active, then the tag and the + * tagged value are converted to a JSON object. Otherwise, if enabled, the + * last (innermost) tag is stored in the metadata. + * + * \par Non-string keys in maps: + * JSON requires all Object keys to be strings, while CBOR does not. By + * default, if a non-string key is found, the conversion fails with error + * CborErrorJsonObjectKeyNotString. If the CborConvertStringifyMapKeys option + * is active, then the conversion attempts to create a string representation + * using CborPretty. Note that the \c json2cbor tool is not able to parse this + * back to the original form. + * + * \par Duplicate keys in maps: + * Neither JSON nor CBOR allow duplicated keys, but current TinyCBOR does not + * validate that this is the case. If there are duplicated keys in the input, + * they will be repeated in the output, which many JSON tools may flag as + * invalid. In addition to that, if the CborConvertStringifyMapKeys option is + * active, it is possible that a non-string key in a CBOR map will be converted + * to a string form that is identical to another key. + * + * \par + * When metadata support is active, the conversion will add extra key-value + * pairs to the JSON output so it can store the metadata. It is possible that + * the keys for the metadata clash with existing keys in the JSON map. + */ + +extern FILE *open_memstream(char **bufptr, size_t *sizeptr); + +enum ConversionStatusFlags { + TypeWasNotNative = 0x100, /* anything but strings, boolean, null, arrays and maps */ + TypeWasTagged = 0x200, + NumberPrecisionWasLost = 0x400, + NumberWasNaN = 0x800, + NumberWasInfinite = 0x1000, + NumberWasNegative = 0x2000, /* only used with NumberWasInifite or NumberWasTooBig */ + + FinalTypeMask = 0xff +}; + +typedef struct ConversionStatus { + CborTag lastTag; + uint64_t originalNumber; + int flags; +} ConversionStatus; + +static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType type, ConversionStatus *status); + +static CborError dump_bytestring_base16(char **result, CborValue *it) +{ + static const char characters[] = "0123456789abcdef"; + size_t i; + size_t n = 0; + uint8_t *buffer; + CborError err = cbor_value_calculate_string_length(it, &n); + if (err) + return err; + + /* a Base16 (hex) output is twice as big as our buffer */ + buffer = (uint8_t *)malloc(n * 2 + 1); + *result = (char *)buffer; + + /* let cbor_value_copy_byte_string know we have an extra byte for the terminating NUL */ + ++n; + err = cbor_value_copy_byte_string(it, buffer + n - 1, &n, it); + cbor_assert(err == CborNoError); + + for (i = 0; i < n; ++i) { + uint8_t byte = buffer[n + i]; + buffer[2*i] = characters[byte >> 4]; + buffer[2*i + 1] = characters[byte & 0xf]; + } + return CborNoError; +} + +static CborError generic_dump_base64(char **result, CborValue *it, const char alphabet[65]) +{ + size_t n = 0, i; + uint8_t *buffer, *out, *in; + CborError err = cbor_value_calculate_string_length(it, &n); + if (err) + return err; + + /* a Base64 output (untruncated) has 4 bytes for every 3 in the input */ + size_t len = (n + 5) / 3 * 4; + out = buffer = (uint8_t *)malloc(len + 1); + *result = (char *)buffer; + + /* we read our byte string at the tail end of the buffer + * so we can do an in-place conversion while iterating forwards */ + in = buffer + len - n; + + /* let cbor_value_copy_byte_string know we have an extra byte for the terminating NUL */ + ++n; + err = cbor_value_copy_byte_string(it, in, &n, it); + cbor_assert(err == CborNoError); + + uint_least32_t val = 0; + for (i = 0; n - i >= 3; i += 3) { + /* read 3 bytes x 8 bits = 24 bits */ + if (false) { +#ifdef __GNUC__ + } else if (i) { + __builtin_memcpy(&val, in + i - 1, sizeof(val)); + val = cbor_ntohl(val); +#endif + } else { + val = (in[i] << 16) | (in[i + 1] << 8) | in[i + 2]; + } + + /* write 4 chars x 6 bits = 24 bits */ + *out++ = alphabet[(val >> 18) & 0x3f]; + *out++ = alphabet[(val >> 12) & 0x3f]; + *out++ = alphabet[(val >> 6) & 0x3f]; + *out++ = alphabet[val & 0x3f]; + } + + /* maybe 1 or 2 bytes left */ + if (n - i) { + /* we can read in[i + 1] even if it's past the end of the string because + * we know (by construction) that it's a NUL byte */ +#ifdef __GNUC__ + uint16_t val16; + __builtin_memcpy(&val16, in + i, sizeof(val16)); + val = cbor_ntohs(val16); +#else + val = (in[i] << 8) | in[i + 1]; +#endif + val <<= 8; + + /* the 65th character in the alphabet is our filler: either '=' or '\0' */ + out[4] = '\0'; + out[3] = alphabet[64]; + if (n - i == 2) { + /* write the third char in 3 chars x 6 bits = 18 bits */ + out[2] = alphabet[(val >> 6) & 0x3f]; + } else { + out[2] = alphabet[64]; /* filler */ + } + out[1] = alphabet[(val >> 12) & 0x3f]; + out[0] = alphabet[(val >> 18) & 0x3f]; + } else { + out[0] = '\0'; + } + + return CborNoError; +} + +static CborError dump_bytestring_base64(char **result, CborValue *it) +{ + static const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef" + "ghijklmn" "opqrstuv" "wxyz0123" "456789+/" "="; + return generic_dump_base64(result, it, alphabet); +} + +static CborError dump_bytestring_base64url(char **result, CborValue *it) +{ + static const char alphabet[] = "ABCDEFGH" "IJKLMNOP" "QRSTUVWX" "YZabcdef" + "ghijklmn" "opqrstuv" "wxyz0123" "456789-_"; + return generic_dump_base64(result, it, alphabet); +} + +static CborError add_value_metadata(FILE *out, CborType type, const ConversionStatus *status) +{ + int flags = status->flags; + if (flags & TypeWasTagged) { + /* extract the tagged type, which may be JSON native */ + type = flags & FinalTypeMask; + flags &= ~(FinalTypeMask | TypeWasTagged); + + if (fprintf(out, "\"tag\":\"%" PRIu64 "\"%s", status->lastTag, + flags & ~TypeWasTagged ? "," : "") < 0) + return CborErrorIO; + } + + if (!flags) + return CborNoError; + + /* print at least the type */ + if (fprintf(out, "\"t\":%d", type) < 0) + return CborErrorIO; + + if (flags & NumberWasNaN) + if (fprintf(out, ",\"v\":\"nan\"") < 0) + return CborErrorIO; + if (flags & NumberWasInfinite) + if (fprintf(out, ",\"v\":\"%sinf\"", flags & NumberWasNegative ? "-" : "") < 0) + return CborErrorIO; + if (flags & NumberPrecisionWasLost) + if (fprintf(out, ",\"v\":\"%c%" PRIx64 "\"", flags & NumberWasNegative ? '-' : '+', + status->originalNumber) < 0) + return CborErrorIO; + if (type == CborSimpleType) + if (fprintf(out, ",\"v\":%d", (int)status->originalNumber) < 0) + return CborErrorIO; + return CborNoError; +} + +static CborError find_tagged_type(CborValue *it, CborTag *tag, CborType *type) +{ + CborError err = CborNoError; + *type = cbor_value_get_type(it); + while (*type == CborTagType) { + cbor_value_get_tag(it, tag); /* can't fail */ + err = cbor_value_advance_fixed(it); + if (err) + return err; + + *type = cbor_value_get_type(it); + } + return err; +} + +static CborError tagged_value_to_json(FILE *out, CborValue *it, int flags, ConversionStatus *status) +{ + CborTag tag; + CborError err; + + if (flags & CborConvertTagsToObjects) { + cbor_value_get_tag(it, &tag); /* can't fail */ + err = cbor_value_advance_fixed(it); + if (err) + return err; + + if (fprintf(out, "{\"tag%" PRIu64 "\":", tag) < 0) + return CborErrorIO; + + CborType type = cbor_value_get_type(it); + err = value_to_json(out, it, flags, type, status); + if (err) + return err; + if (flags & CborConvertAddMetadata && status->flags) { + if (fprintf(out, ",\"tag%" PRIu64 "$cbor\":{", tag) < 0 || + add_value_metadata(out, type, status) != CborNoError || + fputc('}', out) < 0) + return CborErrorIO; + } + if (fputc('}', out) < 0) + return CborErrorIO; + status->flags = TypeWasNotNative | CborTagType; + return CborNoError; + } + + CborType type; + err = find_tagged_type(it, &status->lastTag, &type); + if (err) + return err; + tag = status->lastTag; + + /* special handling of byte strings? */ + if (type == CborByteStringType && (flags & CborConvertByteStringsToBase64Url) == 0 && + (tag == CborNegativeBignumTag || tag == CborExpectedBase16Tag || tag == CborExpectedBase64Tag)) { + char *str; + char *pre = ""; + + if (tag == CborNegativeBignumTag) { + pre = "~"; + err = dump_bytestring_base64url(&str, it); + } else if (tag == CborExpectedBase64Tag) { + err = dump_bytestring_base64(&str, it); + } else { /* tag == CborExpectedBase16Tag */ + err = dump_bytestring_base16(&str, it); + } + if (err) + return err; + err = fprintf(out, "\"%s%s\"", pre, str) < 0 ? CborErrorIO : CborNoError; + free(str); + status->flags = TypeWasNotNative | TypeWasTagged | CborByteStringType; + return err; + } + + /* no special handling */ + err = value_to_json(out, it, flags, type, status); + status->flags |= TypeWasTagged | type; + return err; +} + +static CborError stringify_map_key(char **key, CborValue *it, int flags, CborType type) +{ + (void)flags; /* unused */ + (void)type; /* unused */ +#ifdef WITHOUT_OPEN_MEMSTREAM + (void)key; /* unused */ + (void)it; /* unused */ + return CborErrorJsonNotImplemented; +#else + size_t size; + + FILE *memstream = open_memstream(key, &size); + if (memstream == NULL) + return CborErrorOutOfMemory; /* could also be EMFILE, but it's unlikely */ + CborError err = cbor_value_to_pretty_advance(memstream, it); + + if (unlikely(fclose(memstream) < 0 || *key == NULL)) + return CborErrorInternalError; + return err; +#endif +} + +static CborError array_to_json(FILE *out, CborValue *it, int flags, ConversionStatus *status) +{ + const char *comma = ""; + while (!cbor_value_at_end(it)) { + if (fprintf(out, "%s", comma) < 0) + return CborErrorIO; + comma = ","; + + CborError err = value_to_json(out, it, flags, cbor_value_get_type(it), status); + if (err) + return err; + } + return CborNoError; +} + +static CborError map_to_json(FILE *out, CborValue *it, int flags, ConversionStatus *status) +{ + const char *comma = ""; + CborError err; + while (!cbor_value_at_end(it)) { + char *key; + if (fprintf(out, "%s", comma) < 0) + return CborErrorIO; + comma = ","; + + CborType keyType = cbor_value_get_type(it); + if (likely(keyType == CborTextStringType)) { + size_t n = 0; + err = cbor_value_dup_text_string(it, &key, &n, it); + } else if (flags & CborConvertStringifyMapKeys) { + err = stringify_map_key(&key, it, flags, keyType); + } else { + return CborErrorJsonObjectKeyNotString; + } + if (err) + return err; + + /* first, print the key */ + if (fprintf(out, "\"%s\":", key) < 0) { + free(key); + return CborErrorIO; + } + + /* then, print the value */ + CborType valueType = cbor_value_get_type(it); + err = value_to_json(out, it, flags, valueType, status); + + /* finally, print any metadata we may have */ + if (flags & CborConvertAddMetadata) { + if (!err && keyType != CborTextStringType) { + if (fprintf(out, ",\"%s$keycbordump\":true", key) < 0) + err = CborErrorIO; + } + if (!err && status->flags) { + if (fprintf(out, ",\"%s$cbor\":{", key) < 0 || + add_value_metadata(out, valueType, status) != CborNoError || + fputc('}', out) < 0) + err = CborErrorIO; + } + } + + free(key); + if (err) + return err; + } + return CborNoError; +} + +static CborError value_to_json(FILE *out, CborValue *it, int flags, CborType type, ConversionStatus *status) +{ + CborError err; + status->flags = 0; + + switch (type) { + case CborArrayType: + case CborMapType: { + /* recursive type */ + CborValue recursed; + err = cbor_value_enter_container(it, &recursed); + if (err) { + it->ptr = recursed.ptr; + return err; /* parse error */ + } + if (fputc(type == CborArrayType ? '[' : '{', out) < 0) + return CborErrorIO; + + err = (type == CborArrayType) ? + array_to_json(out, &recursed, flags, status) : + map_to_json(out, &recursed, flags, status); + if (err) { + it->ptr = recursed.ptr; + return err; /* parse error */ + } + + if (fputc(type == CborArrayType ? ']' : '}', out) < 0) + return CborErrorIO; + err = cbor_value_leave_container(it, &recursed); + if (err) + return err; /* parse error */ + + status->flags = 0; /* reset, there are never conversion errors for us */ + return CborNoError; + } + + case CborIntegerType: { + double num; /* JS numbers are IEEE double precision */ + uint64_t val; + cbor_value_get_raw_integer(it, &val); /* can't fail */ + num = (double)val; + + if (cbor_value_is_negative_integer(it)) { + num = -num - 1; /* convert to negative */ + if ((uint64_t)(-num - 1) != val) { + status->flags = NumberPrecisionWasLost | NumberWasNegative; + status->originalNumber = val; + } + } else { + if ((uint64_t)num != val) { + status->flags = NumberPrecisionWasLost; + status->originalNumber = val; + } + } + if (fprintf(out, "%.0f", num) < 0) /* this number has no fraction, so no decimal points please */ + return CborErrorIO; + break; + } + + case CborByteStringType: + case CborTextStringType: { + char *str; + if (type == CborByteStringType) { + err = dump_bytestring_base64url(&str, it); + status->flags = TypeWasNotNative; + } else { + size_t n = 0; + err = cbor_value_dup_text_string(it, &str, &n, it); + } + if (err) + return err; + err = (fprintf(out, "\"%s\"", str) < 0) ? CborErrorIO : CborNoError; + free(str); + return err; + } + + case CborTagType: + return tagged_value_to_json(out, it, flags, status); + + case CborSimpleType: { + uint8_t simple_type; + cbor_value_get_simple_type(it, &simple_type); /* can't fail */ + status->flags = TypeWasNotNative; + status->originalNumber = simple_type; + if (fprintf(out, "\"simple(%" PRIu8 ")\"", simple_type) < 0) + return CborErrorIO; + break; + } + + case CborNullType: + if (fprintf(out, "null") < 0) + return CborErrorIO; + break; + + case CborUndefinedType: + status->flags = TypeWasNotNative; + if (fprintf(out, "\"undefined\"") < 0) + return CborErrorIO; + break; + + case CborBooleanType: { + bool val; + cbor_value_get_boolean(it, &val); /* can't fail */ + if (fprintf(out, val ? "true" : "false") < 0) + return CborErrorIO; + break; + } + +#ifndef CBOR_NO_FLOATING_POINT + case CborDoubleType: { + double val; + if (false) { + float f; + case CborFloatType: + status->flags = TypeWasNotNative; + cbor_value_get_float(it, &f); + val = f; + } else if (false) { + uint16_t f16; + case CborHalfFloatType: +# ifndef CBOR_NO_HALF_FLOAT_TYPE + status->flags = TypeWasNotNative; + cbor_value_get_half_float(it, &f16); + val = decode_half(f16); +# else + (void)f16; + err = CborErrorUnsupportedType; + break; +# endif + } else { + cbor_value_get_double(it, &val); + } + + int r = fpclassify(val); + if (r == FP_NAN || r == FP_INFINITE) { + if (fprintf(out, "null") < 0) + return CborErrorIO; + status->flags |= r == FP_NAN ? NumberWasNaN : + NumberWasInfinite | (val < 0 ? NumberWasNegative : 0); + } else { + uint64_t ival = (uint64_t)fabs(val); + if ((double)ival == fabs(val)) { + /* print as integer so we get the full precision */ + r = fprintf(out, "%s%" PRIu64, val < 0 ? "-" : "", ival); + status->flags |= TypeWasNotNative; /* mark this integer number as a double */ + } else { + /* this number is definitely not a 64-bit integer */ + r = fprintf(out, "%." DBL_DECIMAL_DIG_STR "g", val); + } + if (r < 0) + return CborErrorIO; + } + break; + } +#else + case CborDoubleType: + case CborFloatType: + case CborHalfFloatType: + err = CborErrorUnsupportedType; + break; +#endif /* !CBOR_NO_FLOATING_POINT */ + + case CborInvalidType: + return CborErrorUnknownType; + } + + return cbor_value_advance_fixed(it); +} + +/** + * \enum CborToJsonFlags + * The CborToJsonFlags enum contains flags that control the conversion of CBOR to JSON. + * + * \value CborConvertAddMetadata Adds metadata to facilitate restoration of the original CBOR data. + * \value CborConvertTagsToObjects Converts CBOR tags to JSON objects + * \value CborConvertIgnoreTags (default) Ignore CBOR tags, except for byte strings + * \value CborConvertObeyByteStringTags (default) Honor formatting of CBOR byte strings if so tagged + * \value CborConvertByteStringsToBase64Url Force the conversion of all CBOR byte strings to Base64url encoding, despite any tags + * \value CborConvertRequireMapStringKeys (default) Require CBOR map keys to be strings, failing the conversion if they are not + * \value CborConvertStringifyMapKeys Convert non-string keys in CBOR maps to a string form + * \value CborConvertDefaultFlags Default conversion flags. + */ + +/** + * \fn CborError cbor_value_to_json(FILE *out, const CborValue *value, int flags) + * + * Converts the current CBOR type pointed to by \a value to JSON and writes that + * to the \a out stream. If an error occurs, this function returns an error + * code similar to CborParsing. The \a flags parameter indicates one or more of + * the flags from CborToJsonFlags that control the conversion. + * + * \sa cbor_value_to_json_advance(), cbor_value_to_pretty() + */ + +/** + * Converts the current CBOR type pointed to by \a value to JSON and writes that + * to the \a out stream. If an error occurs, this function returns an error + * code similar to CborParsing. The \a flags parameter indicates one or more of + * the flags from CborToJsonFlags that control the conversion. + * + * If no error ocurred, this function advances \a value to the next element. + * + * \sa cbor_value_to_json(), cbor_value_to_pretty_advance() + */ +CborError cbor_value_to_json_advance(FILE *out, CborValue *value, int flags) +{ + ConversionStatus status; + return value_to_json(out, value, flags, cbor_value_get_type(value), &status); +} + +/** @} */ diff --git a/client/tinycbor/cborvalidation.c b/client/tinycbor/cborvalidation.c new file mode 100644 index 000000000..08c35117b --- /dev/null +++ b/client/tinycbor/cborvalidation.c @@ -0,0 +1,666 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Intel Corporation +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +#define _BSD_SOURCE 1 +#define _DEFAULT_SOURCE 1 +#ifndef __STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS 1 +#endif + +#include "cbor.h" +#include "cborinternal_p.h" +#include "compilersupport_p.h" +#include "utf8_p.h" + +#include + +#ifndef CBOR_NO_FLOATING_POINT +# include +# include +#endif + + +#ifndef CBOR_PARSER_MAX_RECURSIONS +# define CBOR_PARSER_MAX_RECURSIONS 1024 +#endif + +/** + * \addtogroup CborParsing + * @{ + */ + +/** + * \enum CborValidationFlags + * The CborValidationFlags enum contains flags that control the validation of a + * CBOR stream. + * + * \value CborValidateBasic Validates only the syntactic correctedness of the stream. + * \value CborValidateCanonical Validates that the stream is in canonical format, according to + * RFC 7049 section 3.9. + * \value CborValidateStrictMode Performs strict validation, according to RFC 7049 section 3.10. + * \value CborValidateStrictest Attempt to perform the strictest validation we know of. + * + * \value CborValidateShortestIntegrals (Canonical) Validate that integral numbers and lengths are + * enconded in their shortest form possible. + * \value CborValidateShortestFloatingPoint (Canonical) Validate that floating-point numbers are encoded + * in their shortest form possible. + * \value CborValidateShortestNumbers (Canonical) Validate both integral and floating-point numbers + * are in their shortest form possible. + * \value CborValidateNoIndeterminateLength (Canonical) Validate that no string, array or map uses + * indeterminate length encoding. + * \value CborValidateMapIsSorted (Canonical & Strict mode) Validate that map keys appear in + * sorted order. + * \value CborValidateMapKeysAreUnique (Strict mode) Validate that map keys are unique. + * \value CborValidateTagUse (Strict mode) Validate that known tags are used with the + * correct types. This does not validate that the content of + * those types is syntactically correct. For example, this + * option validates that tag 1 (DateTimeString) is used with + * a Text String, but it does not validate that the string is + * a valid date/time representation. + * \value CborValidateUtf8 (Strict mode) Validate that text strings are appropriately + * encoded in UTF-8. + * \value CborValidateMapKeysAreString Validate that all map keys are text strings. + * \value CborValidateNoUndefined Validate that no elements of type "undefined" are present. + * \value CborValidateNoTags Validate that no tags are used. + * \value CborValidateFiniteFloatingPoint Validate that all floating point numbers are finite (no NaN or + * infinities are allowed). + * \value CborValidateCompleteData Validate that the stream is complete and there is no more data + * in the buffer. + * \value CborValidateNoUnknownSimpleTypesSA Validate that all Standards Action simple types are registered + * with IANA. + * \value CborValidateNoUnknownSimpleTypes Validate that all simple types used are registered with IANA. + * \value CborValidateNoUnknownTagsSA Validate that all Standard Actions tags are registered with IANA. + * \value CborValidateNoUnknownTagsSR Validate that all Standard Actions and Specification Required tags + * are registered with IANA (see below for limitations). + * \value CborValidateNoUnkonwnTags Validate that all tags are registered with IANA + * (see below for limitations). + * + * \par Simple type registry + * The CBOR specification requires that registration for use of the first 19 + * simple types must be done by way of Standards Action. The rest of the simple + * types only require a specification. The official list can be obtained from + * https://www.iana.org/assignments/cbor-simple-values/cbor-simple-values.xhtml. + * + * \par + * There are no registered simple types recognized by this release of TinyCBOR + * (beyond those defined by RFC 7049). + * + * \par Tag registry + * The CBOR specification requires that registration for use of the first 23 + * tags must be done by way of Standards Action. The next up to tag 255 only + * require a specification. Finally, all other tags can be registered on a + * first-come-first-serve basis. The official list can be ontained from + * https://www.iana.org/assignments/cbor-tags/cbor-tags.xhtml. + * + * \par + * Given the variability of this list, TinyCBOR cannot recognize all tags + * registered with IANA. Instead, the implementation only recognizes tags + * that are backed by an RFC. + * + * \par + * These are the tags known to the current TinyCBOR release: + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
TagData ItemSemantics
0UTF-8 text stringStandard date/time string
1integerEpoch-based date/time
2byte stringPositive bignum
3byte stringNegative bignum
4arrayDecimal fraction
5arrayBigfloat
16arrayCOSE Single Recipient Encrypted Data Object (RFC 8152)
17arrayCOSE Mac w/o Recipients Object (RFC 8152)
18arrayCOSE Single Signer Data Object (RFC 8162)
21byte string, array, mapExpected conversion to base64url encoding
22byte string, array, mapExpected conversion to base64 encoding
23byte string, array, mapExpected conversion to base16 encoding
24byte stringEncoded CBOR data item
32UTF-8 text stringURI
33UTF-8 text stringbase64url
34UTF-8 text stringbase64
35UTF-8 text stringRegular expression
36UTF-8 text stringMIME message
96arrayCOSE Encrypted Data Object (RFC 8152)
97arrayCOSE MACed Data Object (RFC 8152)
98arrayCOSE Signed Data Object (RFC 8152)
55799anySelf-describe CBOR
+ */ + +struct KnownTagData { uint32_t tag; uint32_t types; }; +static const struct KnownTagData knownTagData[] = { + { 0, (uint32_t)CborTextStringType }, + { 1, (uint32_t)(CborIntegerType+1) }, + { 2, (uint32_t)CborByteStringType }, + { 3, (uint32_t)CborByteStringType }, + { 4, (uint32_t)CborArrayType }, + { 5, (uint32_t)CborArrayType }, + { 16, (uint32_t)CborArrayType }, + { 17, (uint32_t)CborArrayType }, + { 18, (uint32_t)CborArrayType }, + { 21, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) }, + { 22, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) }, + { 23, (uint32_t)CborByteStringType | ((uint32_t)CborArrayType << 8) | ((uint32_t)CborMapType << 16) }, + { 24, (uint32_t)CborByteStringType }, + { 32, (uint32_t)CborTextStringType }, + { 33, (uint32_t)CborTextStringType }, + { 34, (uint32_t)CborTextStringType }, + { 35, (uint32_t)CborTextStringType }, + { 36, (uint32_t)CborTextStringType }, + { 96, (uint32_t)CborArrayType }, + { 97, (uint32_t)CborArrayType }, + { 98, (uint32_t)CborArrayType }, + { 55799, 0U } +}; + +static CborError validate_value(CborValue *it, uint32_t flags, int recursionLeft); + +static inline CborError validate_utf8_string(const void *ptr, size_t n) +{ + const uint8_t *buffer = (const uint8_t *)ptr; + const uint8_t * const end = buffer + n; + while (buffer < end) { + uint32_t uc = get_utf8(&buffer, end); + if (uc == ~0U) + return CborErrorInvalidUtf8TextString; + } + return CborNoError; +} + +static inline CborError validate_simple_type(uint8_t simple_type, uint32_t flags) +{ + /* At current time, all known simple types are those from RFC 7049, + * which are parsed by the parser into different CBOR types. + * That means that if we've got here, the type is unknown */ + if (simple_type < 32) + return (flags & CborValidateNoUnknownSimpleTypesSA) ? CborErrorUnknownSimpleType : CborNoError; + return (flags & CborValidateNoUnknownSimpleTypes) == CborValidateNoUnknownSimpleTypes ? + CborErrorUnknownSimpleType : CborNoError; +} + +static inline CborError validate_number(const CborValue *it, CborType type, uint32_t flags) +{ + CborError err = CborNoError; + const uint8_t *ptr = it->ptr; + size_t bytesUsed, bytesNeeded; + uint64_t value; + + if ((flags & CborValidateShortestIntegrals) == 0) + return err; + if (type >= CborHalfFloatType && type <= CborDoubleType) + return err; /* checked elsewhere */ + + err = _cbor_value_extract_number(&ptr, it->parser->end, &value); + if (err) + return err; + + bytesUsed = (size_t)(ptr - it->ptr - 1); + bytesNeeded = 0; + if (value >= Value8Bit) + ++bytesNeeded; + if (value > 0xffU) + ++bytesNeeded; + if (value > 0xffffU) + bytesNeeded += 2; + if (value > 0xffffffffU) + bytesNeeded += 4; + if (bytesNeeded < bytesUsed) + return CborErrorOverlongEncoding; + return CborNoError; +} + +static inline CborError validate_tag(CborValue *it, CborTag tag, uint32_t flags, int recursionLeft) +{ + CborType type = cbor_value_get_type(it); + const size_t knownTagCount = sizeof(knownTagData) / sizeof(knownTagData[0]); + const struct KnownTagData *tagData = knownTagData; + const struct KnownTagData * const knownTagDataEnd = knownTagData + knownTagCount; + + if (!recursionLeft) + return CborErrorNestingTooDeep; + if (flags & CborValidateNoTags) + return CborErrorExcludedType; + + /* find the tag data, if any */ + for ( ; tagData != knownTagDataEnd; ++tagData) { + if (tagData->tag < tag) + continue; + if (tagData->tag > tag) + tagData = NULL; + break; + } + if (tagData == knownTagDataEnd) + tagData = NULL; + + if (flags & CborValidateNoUnknownTags && !tagData) { + /* tag not found */ + if (flags & CborValidateNoUnknownTagsSA && tag < 24) + return CborErrorUnknownTag; + if ((flags & CborValidateNoUnknownTagsSR) == CborValidateNoUnknownTagsSR && tag < 256) + return CborErrorUnknownTag; + if ((flags & CborValidateNoUnknownTags) == CborValidateNoUnknownTags) + return CborErrorUnknownTag; + } + + if (flags & CborValidateTagUse && tagData && tagData->types) { + uint32_t allowedTypes = tagData->types; + + /* correct Integer so it's not zero */ + if (type == CborIntegerType) + type = (CborType)(type + 1); + + while (allowedTypes) { + if ((uint8_t)(allowedTypes & 0xff) == type) + break; + allowedTypes >>= 8; + } + if (!allowedTypes) + return CborErrorInappropriateTagForType; + } + + return validate_value(it, flags, recursionLeft); +} + +#ifndef CBOR_NO_FLOATING_POINT +static inline CborError validate_floating_point(CborValue *it, CborType type, uint32_t flags) +{ + CborError err; + int r; + double val; + float valf; + uint16_t valf16; + + if (type != CborDoubleType) { + if (type == CborFloatType) { + err = cbor_value_get_float(it, &valf); + val = valf; + } else { +# ifdef CBOR_NO_HALF_FLOAT_TYPE + (void)valf16; + return CborErrorUnsupportedType; +# else + err = cbor_value_get_half_float(it, &valf16); + val = decode_half(valf16); +# endif + } + } else { + err = cbor_value_get_double(it, &val); + } + cbor_assert(err == CborNoError); /* can't fail */ + + r = fpclassify(val); + if (r == FP_NAN || r == FP_INFINITE) { + if (flags & CborValidateFiniteFloatingPoint) + return CborErrorExcludedValue; + if (flags & CborValidateShortestFloatingPoint) { + if (type == CborDoubleType) + return CborErrorOverlongEncoding; +# ifndef CBOR_NO_HALF_FLOAT_TYPE + if (type == CborFloatType) + return CborErrorOverlongEncoding; + if (r == FP_NAN && valf16 != 0x7e00) + return CborErrorImproperValue; + if (r == FP_INFINITE && valf16 != 0x7c00 && valf16 != 0xfc00) + return CborErrorImproperValue; +# endif + } + } + + if (flags & CborValidateShortestFloatingPoint && type > CborHalfFloatType) { + if (type == CborDoubleType) { + valf = (float)val; + if ((double)valf == val) + return CborErrorOverlongEncoding; + } +# ifndef CBOR_NO_HALF_FLOAT_TYPE + if (type == CborFloatType) { + valf16 = encode_half(valf); + if (valf == decode_half(valf16)) + return CborErrorOverlongEncoding; + } +# endif + } + + return CborNoError; +} +#endif + +static CborError validate_container(CborValue *it, int containerType, uint32_t flags, int recursionLeft) +{ + CborError err; + const uint8_t *previous = NULL; + const uint8_t *previous_end = NULL; + + if (!recursionLeft) + return CborErrorNestingTooDeep; + + while (!cbor_value_at_end(it)) { + const uint8_t *current = cbor_value_get_next_byte(it); + + if (containerType == CborMapType) { + if (flags & CborValidateMapKeysAreString) { + CborType type = cbor_value_get_type(it); + if (type == CborTagType) { + /* skip the tags */ + CborValue copy = *it; + err = cbor_value_skip_tag(©); + if (err) + return err; + type = cbor_value_get_type(©); + } + if (type != CborTextStringType) + return CborErrorMapKeyNotString; + } + } + + err = validate_value(it, flags, recursionLeft); + if (err) + return err; + + if (containerType != CborMapType) + continue; + + if (flags & CborValidateMapIsSorted) { + if (previous) { + uint64_t len1, len2; + const uint8_t *ptr; + + /* extract the two lengths */ + ptr = previous; + _cbor_value_extract_number(&ptr, it->parser->end, &len1); + ptr = current; + _cbor_value_extract_number(&ptr, it->parser->end, &len2); + + if (len1 > len2) + return CborErrorMapNotSorted; + if (len1 == len2) { + size_t bytelen1 = (size_t)(previous_end - previous); + size_t bytelen2 = (size_t)(it->ptr - current); + int r = memcmp(previous, current, bytelen1 <= bytelen2 ? bytelen1 : bytelen2); + + if (r == 0 && bytelen1 != bytelen2) + r = bytelen1 < bytelen2 ? -1 : +1; + if (r > 0) + return CborErrorMapNotSorted; + if (r == 0 && (flags & CborValidateMapKeysAreUnique) == CborValidateMapKeysAreUnique) + return CborErrorMapKeysNotUnique; + } + } + + previous = current; + previous_end = it->ptr; + } + + /* map: that was the key, so get the value */ + err = validate_value(it, flags, recursionLeft); + if (err) + return err; + } + return CborNoError; +} + +static CborError validate_value(CborValue *it, uint32_t flags, int recursionLeft) +{ + CborError err; + CborType type = cbor_value_get_type(it); + + if (cbor_value_is_length_known(it)) { + err = validate_number(it, type, flags); + if (err) + return err; + } else { + if (flags & CborValidateNoIndeterminateLength) + return CborErrorUnknownLength; + } + + switch (type) { + case CborArrayType: + case CborMapType: { + /* recursive type */ + CborValue recursed; + err = cbor_value_enter_container(it, &recursed); + if (!err) + err = validate_container(&recursed, type, flags, recursionLeft - 1); + if (err) { + it->ptr = recursed.ptr; + return err; + } + err = cbor_value_leave_container(it, &recursed); + if (err) + return err; + return CborNoError; + } + + case CborIntegerType: { + uint64_t val; + err = cbor_value_get_raw_integer(it, &val); + cbor_assert(err == CborNoError); /* can't fail */ + + break; + } + + case CborByteStringType: + case CborTextStringType: { + size_t n = 0; + const void *ptr; + + err = _cbor_value_prepare_string_iteration(it); + if (err) + return err; + + while (1) { + err = validate_number(it, type, flags); + if (err) + return err; + + err = _cbor_value_get_string_chunk(it, &ptr, &n, it); + if (err) + return err; + if (!ptr) + break; + + if (type == CborTextStringType && flags & CborValidateUtf8) { + err = validate_utf8_string(ptr, n); + if (err) + return err; + } + } + + return CborNoError; + } + + case CborTagType: { + CborTag tag; + err = cbor_value_get_tag(it, &tag); + cbor_assert(err == CborNoError); /* can't fail */ + + err = cbor_value_advance_fixed(it); + if (err) + return err; + err = validate_tag(it, tag, flags, recursionLeft - 1); + if (err) + return err; + + return CborNoError; + } + + case CborSimpleType: { + uint8_t simple_type; + err = cbor_value_get_simple_type(it, &simple_type); + cbor_assert(err == CborNoError); /* can't fail */ + err = validate_simple_type(simple_type, flags); + if (err) + return err; + break; + } + + case CborNullType: + case CborBooleanType: + break; + + case CborUndefinedType: + if (flags & CborValidateNoUndefined) + return CborErrorExcludedType; + break; + + case CborHalfFloatType: + case CborFloatType: + case CborDoubleType: { +#ifdef CBOR_NO_FLOATING_POINT + return CborErrorUnsupportedType; +#else + err = validate_floating_point(it, type, flags); + if (err) + return err; + break; +#endif /* !CBOR_NO_FLOATING_POINT */ + } + + case CborInvalidType: + return CborErrorUnknownType; + } + + err = cbor_value_advance_fixed(it); + return err; +} + +/** + * Performs a full validation, controlled by the \a flags options, of the CBOR + * stream pointed by \a it and returns the error it found. If no error was + * found, it returns CborNoError and the application can iterate over the items + * with certainty that no errors will appear during parsing. + * + * If \a flags is CborValidateBasic, the result should be the same as + * cbor_value_validate_basic(). + * + * This function has the same timing and memory requirements as + * cbor_value_advance() and cbor_value_validate_basic(). + * + * \sa CborValidationFlags, cbor_value_validate_basic(), cbor_value_advance() + */ +CborError cbor_value_validate(const CborValue *it, uint32_t flags) +{ + CborValue value = *it; + CborError err = validate_value(&value, flags, CBOR_PARSER_MAX_RECURSIONS); + if (err) + return err; + if (flags & CborValidateCompleteData && it->ptr != it->parser->end) + return CborErrorGarbageAtEnd; + return CborNoError; +} + +/** + * @} + */ diff --git a/client/tinycbor/compilersupport_p.h b/client/tinycbor/compilersupport_p.h new file mode 100644 index 000000000..bd10efc9c --- /dev/null +++ b/client/tinycbor/compilersupport_p.h @@ -0,0 +1,205 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Intel Corporation +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +#ifndef COMPILERSUPPORT_H +#define COMPILERSUPPORT_H + +#include "cbor.h" + +#ifndef _BSD_SOURCE +# define _BSD_SOURCE +#endif +#ifndef _DEFAULT_SOURCE +# define _DEFAULT_SOURCE +#endif +#ifndef assert +# include +#endif +#include +#include +#include + +#ifndef __cplusplus +# include +#endif + +#if __STDC_VERSION__ >= 201112L || __cplusplus >= 201103L || __cpp_static_assert >= 200410 +# define cbor_static_assert(x) static_assert(x, #x) +#elif !defined(__cplusplus) && defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) && (__STDC_VERSION__ > 199901L) +# define cbor_static_assert(x) _Static_assert(x, #x) +#else +# define cbor_static_assert(x) ((void)sizeof(char[2*!!(x) - 1])) +#endif +#if __STDC_VERSION__ >= 199901L || defined(__cplusplus) +/* inline is a keyword */ +#else +/* use the definition from cbor.h */ +# define inline CBOR_INLINE +#endif + +#ifdef NDEBUG +# define cbor_assert(cond) do { if (!(cond)) unreachable(); } while (0) +#else +# define cbor_assert(cond) assert(cond) +#endif + +#ifndef STRINGIFY +#define STRINGIFY(x) STRINGIFY2(x) +#endif +#define STRINGIFY2(x) #x + +#if !defined(UINT32_MAX) || !defined(INT64_MAX) +/* C89? We can define UINT32_MAX portably, but not INT64_MAX */ +# error "Your system has stdint.h but that doesn't define UINT32_MAX or INT64_MAX" +#endif + +#ifndef DBL_DECIMAL_DIG +/* DBL_DECIMAL_DIG is C11 */ +# define DBL_DECIMAL_DIG 17 +#endif +#define DBL_DECIMAL_DIG_STR STRINGIFY(DBL_DECIMAL_DIG) + +#if defined(__GNUC__) && defined(__i386__) && !defined(__iamcu__) +# define CBOR_INTERNAL_API_CC __attribute__((regparm(3))) +#elif defined(_MSC_VER) && defined(_M_IX86) +# define CBOR_INTERNAL_API_CC __fastcall +#else +# define CBOR_INTERNAL_API_CC +#endif + +#ifndef __has_builtin +# define __has_builtin(x) 0 +#endif + +#if (defined(__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 403)) || \ + (__has_builtin(__builtin_bswap64) && __has_builtin(__builtin_bswap32)) +# if __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__ +# define cbor_ntohll __builtin_bswap64 +# define cbor_htonll __builtin_bswap64 +# define cbor_ntohl __builtin_bswap32 +# define cbor_htonl __builtin_bswap32 +# ifdef __INTEL_COMPILER +# define cbor_ntohs _bswap16 +# define cbor_htons _bswap16 +# elif (__GNUC__ * 100 + __GNUC_MINOR__ >= 608) || __has_builtin(__builtin_bswap16) +# define cbor_ntohs __builtin_bswap16 +# define cbor_htons __builtin_bswap16 +# else +# define cbor_ntohs(x) (((uint16_t)(x) >> 8) | ((uint16_t)(x) << 8)) +# define cbor_htons cbor_ntohs +# endif +# else +# define cbor_ntohll +# define cbor_htonll +# define cbor_ntohl +# define cbor_htonl +# define cbor_ntohs +# define cbor_htons +# endif +#elif defined(__sun) +# include +#elif defined(_MSC_VER) +/* MSVC, which implies Windows, which implies little-endian and sizeof(long) == 4 */ +# include +# define cbor_ntohll _byteswap_uint64 +# define cbor_htonll _byteswap_uint64 +# define cbor_ntohl _byteswap_ulong +# define cbor_htonl _byteswap_ulong +# define cbor_ntohs _byteswap_ushort +# define cbor_htons _byteswap_ushort +#endif +#ifndef cbor_ntohs +# include +# define cbor_ntohs ntohs +# define cbor_htons htons +#endif +#ifndef cbor_ntohl +# include +# define cbor_ntohl ntohl +# define cbor_htonl htonl +#endif +#ifndef cbor_ntohll +# define cbor_ntohll ntohll +# define cbor_htonll htonll +/* ntohll isn't usually defined */ +# ifndef ntohll +# if (defined(__BYTE_ORDER__) && defined(__ORDER_BIG_ENDIAN__) && __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__) || \ + (defined(__BYTE_ORDER) && defined(__BIG_ENDIAN) && __BYTE_ORDER == __BIG_ENDIAN) || \ + (defined(BYTE_ORDER) && defined(BIG_ENDIAN) && BYTE_ORDER == BIG_ENDIAN) || \ + (defined(_BIG_ENDIAN) && !defined(_LITTLE_ENDIAN)) || (defined(__BIG_ENDIAN__) && !defined(__LITTLE_ENDIAN__)) || \ + defined(__ARMEB__) || defined(__MIPSEB__) || defined(__s390__) || defined(__sparc__) +# define ntohll +# define htonll +# elif (defined(__BYTE_ORDER__) && defined(__ORDER_LITTLE_ENDIAN__) && __BYTE_ORDER__ == __ORDER_LITTLE_ENDIAN__) || \ + (defined(__BYTE_ORDER) && defined(__LITTLE_ENDIAN) && __BYTE_ORDER == __LITTLE_ENDIAN) || \ + (defined(BYTE_ORDER) && defined(LITTLE_ENDIAN) && BYTE_ORDER == LITTLE_ENDIAN) || \ + defined(_LITTLE_ENDIAN) || defined(__LITTLE_ENDIAN__) || defined(__ARMEL__) || defined(__MIPSEL__) || \ + defined(__i386) || defined(__i386__) || defined(__x86_64) || defined(__x86_64__) || defined(__amd64) +# define ntohll(x) ((ntohl((uint32_t)(x)) * UINT64_C(0x100000000)) + (ntohl((x) >> 32))) +# define htonll ntohll +# else +# error "Unable to determine byte order!" +# endif +# endif +#endif + + +#ifdef __cplusplus +# define CONST_CAST(t, v) const_cast(v) +#else +/* C-style const_cast without triggering a warning with -Wcast-qual */ +# define CONST_CAST(t, v) (t)(uintptr_t)(v) +#endif + +#ifdef __GNUC__ +#ifndef likely +# define likely(x) __builtin_expect(!!(x), 1) +#endif +#ifndef unlikely +# define unlikely(x) __builtin_expect(!!(x), 0) +#endif +# define unreachable() __builtin_unreachable() +#elif defined(_MSC_VER) +# define likely(x) (x) +# define unlikely(x) (x) +# define unreachable() __assume(0) +#else +# define likely(x) (x) +# define unlikely(x) (x) +# define unreachable() do {} while (0) +#endif + +static inline bool add_check_overflow(size_t v1, size_t v2, size_t *r) +{ +#if ((defined(__GNUC__) && (__GNUC__ >= 5)) && !defined(__INTEL_COMPILER)) || __has_builtin(__builtin_add_overflow) + return __builtin_add_overflow(v1, v2, r); +#else + /* unsigned additions are well-defined */ + *r = v1 + v2; + return v1 > v1 + v2; +#endif +} + +#endif /* COMPILERSUPPORT_H */ + diff --git a/client/tinycbor/open_memstream.c b/client/tinycbor/open_memstream.c new file mode 100644 index 000000000..18f3de8b1 --- /dev/null +++ b/client/tinycbor/open_memstream.c @@ -0,0 +1,114 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Intel Corporation +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +#define _BSD_SOURCE 1 +#define _DEFAULT_SOURCE 1 +#define _GNU_SOURCE 1 + +#include +#include +#include +#include +#include + +#if defined(__unix__) || defined(__APPLE__) +# include +#endif +#ifdef __APPLE__ +typedef int RetType; +typedef int LenType; +#elif __GLIBC__ +typedef ssize_t RetType; +typedef size_t LenType; +#else +# error "Cannot implement open_memstream!" +#endif + +#include "compilersupport_p.h" + +struct Buffer +{ + char **ptr; + size_t *len; + size_t alloc; +}; + +static RetType write_to_buffer(void *cookie, const char *data, LenType len) +{ + struct Buffer *b = (struct Buffer *)cookie; + char *ptr = *b->ptr; + size_t newsize; + + errno = EFBIG; + if (unlikely(add_check_overflow(*b->len, len, &newsize))) + return -1; + + if (newsize >= b->alloc) { // NB! one extra byte is needed to avoid buffer overflow at close_buffer + // make room + size_t newalloc = newsize + newsize / 2 + 1; // give 50% more room + ptr = realloc(ptr, newalloc); + if (ptr == NULL) + return -1; + b->alloc = newalloc; + *b->ptr = ptr; + } + + memcpy(ptr + *b->len, data, len); + *b->len = newsize; + return len; +} + +static int close_buffer(void *cookie) +{ + struct Buffer *b = (struct Buffer *)cookie; + if (*b->ptr) + (*b->ptr)[*b->len] = '\0'; + free(b); + return 0; +} + +FILE *open_memstream(char **bufptr, size_t *lenptr) +{ + struct Buffer *b = (struct Buffer *)malloc(sizeof(struct Buffer)); + if (b == NULL) + return NULL; + b->alloc = 0; + b->len = lenptr; + b->ptr = bufptr; + *bufptr = NULL; + *lenptr = 0; + +#ifdef __APPLE__ + return funopen(b, NULL, write_to_buffer, NULL, close_buffer); +#elif __GLIBC__ + static const cookie_io_functions_t vtable = { + NULL, + write_to_buffer, + NULL, + close_buffer + }; + return fopencookie(b, "w", vtable); +#endif +} + diff --git a/client/tinycbor/tinycbor-version.h b/client/tinycbor/tinycbor-version.h new file mode 100644 index 000000000..29967d025 --- /dev/null +++ b/client/tinycbor/tinycbor-version.h @@ -0,0 +1,3 @@ +#define TINYCBOR_VERSION_MAJOR 0 +#define TINYCBOR_VERSION_MINOR 5 +#define TINYCBOR_VERSION_PATCH 3 diff --git a/client/tinycbor/utf8_p.h b/client/tinycbor/utf8_p.h new file mode 100644 index 000000000..ca438350d --- /dev/null +++ b/client/tinycbor/utf8_p.h @@ -0,0 +1,104 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Intel Corporation +** +** Permission is hereby granted, free of charge, to any person obtaining a copy +** of this software and associated documentation files (the "Software"), to deal +** in the Software without restriction, including without limitation the rights +** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +** copies of the Software, and to permit persons to whom the Software is +** furnished to do so, subject to the following conditions: +** +** The above copyright notice and this permission notice shall be included in +** all copies or substantial portions of the Software. +** +** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +** THE SOFTWARE. +** +****************************************************************************/ + +#ifndef CBOR_UTF8_H +#define CBOR_UTF8_H + +#include "compilersupport_p.h" + +#include + +static inline uint32_t get_utf8(const uint8_t **buffer, const uint8_t *end) +{ + int charsNeeded; + uint32_t uc, min_uc; + uint8_t b; + ptrdiff_t n = end - *buffer; + if (n == 0) + return ~0U; + + uc = *(*buffer)++; + if (uc < 0x80) { + /* single-byte UTF-8 */ + return uc; + } + + /* multi-byte UTF-8, decode it */ + if (unlikely(uc <= 0xC1)) + return ~0U; + if (uc < 0xE0) { + /* two-byte UTF-8 */ + charsNeeded = 2; + min_uc = 0x80; + uc &= 0x1f; + } else if (uc < 0xF0) { + /* three-byte UTF-8 */ + charsNeeded = 3; + min_uc = 0x800; + uc &= 0x0f; + } else if (uc < 0xF5) { + /* four-byte UTF-8 */ + charsNeeded = 4; + min_uc = 0x10000; + uc &= 0x07; + } else { + return ~0U; + } + + if (n < charsNeeded) + return ~0U; + + /* first continuation character */ + b = *(*buffer)++; + if ((b & 0xc0) != 0x80) + return ~0U; + uc <<= 6; + uc |= b & 0x3f; + + if (charsNeeded > 2) { + /* second continuation character */ + b = *(*buffer)++; + if ((b & 0xc0) != 0x80) + return ~0U; + uc <<= 6; + uc |= b & 0x3f; + + if (charsNeeded > 3) { + /* third continuation character */ + b = *(*buffer)++; + if ((b & 0xc0) != 0x80) + return ~0U; + uc <<= 6; + uc |= b & 0x3f; + } + } + + /* overlong sequence? surrogate pair? out or range? */ + if (uc < min_uc || uc - 0xd800U < 2048U || uc > 0x10ffff) + return ~0U; + + return uc; +} + +#endif /* CBOR_UTF8_H */ From cbdb42560cb2775e8ecf9910ff8cf81da53f1f42 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 16 Nov 2018 17:06:13 +0200 Subject: [PATCH 0194/1938] added make --- client/Makefile | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/client/Makefile b/client/Makefile index 9381cb29a..b478102a3 100644 --- a/client/Makefile +++ b/client/Makefile @@ -29,8 +29,11 @@ JANSSONLIBPATH = ./jansson JANSSONLIB = $(JANSSONLIBPATH)/libjansson.a MBEDTLSLIBPATH = ../common/mbedtls MBEDTLSLIB = $(MBEDTLSLIBPATH)/libmbedtls.a +CBORLIBPATH = ./tinycbor +CBORLIB = $(MBEDTLSLIBPATH)/tinycbor.a +LIBS = -I$(MBEDTLSLIBPATH) -I$(JANSSONLIBPATH) -I$(CBORLIBPATH) +INCLUDES_CLIENT = -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua $(LIBS) LDFLAGS = $(ENV_LDFLAGS) -INCLUDES_CLIENT = -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua -I$(MBEDTLSLIBPATH) -I$(JANSSONLIBPATH) CFLAGS = $(ENV_CFLAGS) -std=c99 -D_ISOC99_SOURCE -DPRESETS $(INCLUDES_CLIENT) -Wall -g -O3 CXXFLAGS = -I../include -Wall -O3 @@ -261,7 +264,7 @@ WINBINS = $(patsubst %, %.exe, $(BINS)) CLEAN = $(BINS) $(WINBINS) $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(ZLIBOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(OBJDIR)/*.o *.moc.cpp ui/ui_overlays.h lualibs/usb_cmd.lua lualibs/mf_default_keys.lua # need to assign dependancies to build these first... -all: lua_build jansson_build mbedtls_build $(BINS) +all: lua_build jansson_build mbedtls_build cbor_build $(BINS) all-static: LDLIBS:=-static $(LDLIBS) all-static: proxmark3 flasher fpga_compress @@ -295,6 +298,7 @@ clean: cd ../liblua && make clean cd $(JANSSONLIBPATH) && make clean cd $(MBEDTLSLIBPATH) && make clean + cd $(CBORLIBPATH) && make clean tarbin: $(BINS) $(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%) $(WINBINS:%=client/%) @@ -311,6 +315,10 @@ mbedtls_build: @echo Compiling mbedtls cd $(MBEDTLSLIBPATH) && make all +cbor_build: + @echo Compiling tinycbor + cd $(CBORLIBPATH) && make all + .PHONY: all clean # easy printing of MAKE VARIABLES From 2d17fb172a35c83afdbfe78fcb75e5f2e8bde1a1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 16 Nov 2018 18:33:10 +0200 Subject: [PATCH 0195/1938] added cbor print sketch --- client/Makefile | 9 +++++---- client/cmdhffido.c | 8 +++++--- client/fido/cbortools.c | 41 +++++++++++++++++++++++++++++++++++++++++ client/fido/cbortools.h | 22 ++++++++++++++++++++++ 4 files changed, 73 insertions(+), 7 deletions(-) create mode 100644 client/fido/cbortools.c create mode 100644 client/fido/cbortools.h diff --git a/client/Makefile b/client/Makefile index b478102a3..f97f395e9 100644 --- a/client/Makefile +++ b/client/Makefile @@ -30,9 +30,9 @@ JANSSONLIB = $(JANSSONLIBPATH)/libjansson.a MBEDTLSLIBPATH = ../common/mbedtls MBEDTLSLIB = $(MBEDTLSLIBPATH)/libmbedtls.a CBORLIBPATH = ./tinycbor -CBORLIB = $(MBEDTLSLIBPATH)/tinycbor.a -LIBS = -I$(MBEDTLSLIBPATH) -I$(JANSSONLIBPATH) -I$(CBORLIBPATH) -INCLUDES_CLIENT = -I. -I../include -I../common -I../common/polarssl -I../zlib -I../uart -I/opt/local/include -I../liblua $(LIBS) +CBORLIB = $(CBORLIBPATH)/tinycbor.a +LIBS = -I../zlib -I../uart -I../liblua -I$(MBEDTLSLIBPATH) -I$(JANSSONLIBPATH) -I$(CBORLIBPATH) +INCLUDES_CLIENT = -I. -I../include -I../common -I/opt/local/include $(LIBS) LDFLAGS = $(ENV_LDFLAGS) CFLAGS = $(ENV_CFLAGS) -std=c99 -D_ISOC99_SOURCE -DPRESETS $(INCLUDES_CLIENT) -Wall -g -O3 CXXFLAGS = -I../include -Wall -O3 @@ -111,6 +111,7 @@ CMDSRCS = crapto1/crapto1.c \ mfkey.c \ tea.c \ fido/additional_ca.c \ + fido/cbortools.c \ crypto/asn1dump.c \ crypto/libpcrypto.c\ crypto/asn1utils.c\ @@ -269,7 +270,7 @@ all: lua_build jansson_build mbedtls_build cbor_build $(BINS) all-static: LDLIBS:=-static $(LDLIBS) all-static: proxmark3 flasher fpga_compress -proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(MBEDTLSLIB) $(QTLDLIBS) +proxmark3: LDLIBS+=$(LUALIB) $(JANSSONLIB) $(MBEDTLSLIB) $(CBORLIB) $(QTLDLIBS) proxmark3: $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) lualibs/usb_cmd.lua lualibs/mf_default_keys.lua $(LD) $(LDFLAGS) $(OBJDIR)/proxmark3.o $(COREOBJS) $(CMDOBJS) $(OBJCOBJS) $(QTGUIOBJS) $(MULTIARCHOBJS) $(ZLIBOBJS) $(LDLIBS) -o $@ diff --git a/client/cmdhffido.c b/client/cmdhffido.c index e2d6c0917..faff8e82c 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -28,6 +28,9 @@ #include #include #include +#include +#include +#include #include "comms.h" #include "cmdmain.h" #include "util.h" @@ -42,9 +45,7 @@ #include "crypto/asn1utils.h" #include "crypto/libpcrypto.h" #include "fido/additional_ca.h" -#include "mbedtls/x509_crt.h" -#include "mbedtls/x509.h" -#include "mbedtls/pk.h" +#include "fido/cbortools.h" static int CmdHelp(const char *Cmd); @@ -142,6 +143,7 @@ int CmdHFFidoInfo(const char *cmd) { PrintAndLog("FIDO2 version: (%d)", len); dump_buffer((const unsigned char *)buf, len, NULL, 0); + TinyCborPrintFIDOPackage(buf, len); return 0; } diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c new file mode 100644 index 000000000..4e701b0cd --- /dev/null +++ b/client/fido/cbortools.c @@ -0,0 +1,41 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Tools for work with CBOR format http://cbor.io/spec.html +// via Intel tinycbor (https://github.com/intel/tinycbor) library +//----------------------------------------------------------------------------- +// + +#include "cbortools.h" +#include "cbor.h" + + +int TinyCborParser(uint8_t *data, size_t length, CborValue *cb) { + CborParser parser; + CborError err = cbor_parser_init(data, length, 0, &parser, cb); + // if (!err) + // err = dumprecursive(cb, 0); + + if (err) { + fprintf(stderr, "CBOR parsing failure at offset %d: %s\n", + cb->ptr - data, cbor_error_string(err)); + return 1; + } + + return 0; +} + +int TinyCborPrintFIDOPackage(uint8_t *data, size_t length) { + CborValue cb; + int res; + res = TinyCborParser(data, length, &cb); + if (res) + return res; + + return 0; +} + diff --git a/client/fido/cbortools.h b/client/fido/cbortools.h new file mode 100644 index 000000000..f49751b56 --- /dev/null +++ b/client/fido/cbortools.h @@ -0,0 +1,22 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Tools for work with CBOR format http://cbor.io/spec.html +// via Intel tinycbor (https://github.com/intel/tinycbor) library +//----------------------------------------------------------------------------- +// + + +#ifndef __CBORTOOLS_H__ +#define __CBORTOOLS_H__ + +#include +#include + +extern int TinyCborPrintFIDOPackage(uint8_t *data, size_t length); + +#endif /* __CBORTOOLS_H__ */ From 87f3e1facf781ea1f0b7507df840ff962e50f06f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 16 Nov 2018 19:47:41 +0200 Subject: [PATCH 0196/1938] simple cbor print --- client/fido/cbortools.c | 211 +++++++++++++++++++++++++++++++++++++--- 1 file changed, 200 insertions(+), 11 deletions(-) diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index 4e701b0cd..1744277a5 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -11,20 +11,199 @@ // #include "cbortools.h" +#include #include "cbor.h" +#include "util.h" +static void indent(int nestingLevel) { + while (nestingLevel--) + printf(" "); +} -int TinyCborParser(uint8_t *data, size_t length, CborValue *cb) { +static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) { + CborError err; + *got_next = false; + + CborType type = cbor_value_get_type(it); + indent(nestingLevel); + switch (type) { + case CborMapType: + case CborArrayType: { + printf(type == CborArrayType ? "Array[" : "Map["); + break; + } + + case CborIntegerType: { + int64_t val; + cbor_value_get_int64(it, &val); // can't fail + printf("%lld", (long long)val); + break; + } + + case CborByteStringType: { + uint8_t *buf; + size_t n; + err = cbor_value_dup_byte_string(it, &buf, &n, it); + *got_next = true; + if (err) + return err; // parse error + printf("%s", sprint_hex(buf, n)); + free(buf); + break; + } + + case CborTextStringType: { + char *buf; + size_t n; + err = cbor_value_dup_text_string(it, &buf, &n, it); + *got_next = true; + if (err) + return err; // parse error + printf("%s", buf); + free(buf); + break; + } + + case CborTagType: { + CborTag tag; + cbor_value_get_tag(it, &tag); + printf("Tag(%lld)", (long long)tag); + break; + } + + case CborSimpleType: { + uint8_t type; + cbor_value_get_simple_type(it, &type); + printf("simple(%u)", type); + break; + } + + case CborNullType: + printf("null"); + break; + + case CborUndefinedType: + printf("undefined"); + break; + + case CborBooleanType: { + bool val; + cbor_value_get_boolean(it, &val); // can't fail + printf("%s", val ? "true" : "false"); + break; + } + + case CborDoubleType: { + double val; + if (false) { + float f; + case CborFloatType: + cbor_value_get_float(it, &f); + val = f; + } else { + cbor_value_get_double(it, &val); + } + printf("%g", val); + break; + } + case CborHalfFloatType: { + uint16_t val; + cbor_value_get_half_float(it, &val); + printf("__f16(%04x)", val); + break; + } + + case CborInvalidType: + printf("CborInvalidType!!!"); + break; + } + + return CborNoError; +} + +static CborError dumprecursive(CborValue *it, int nestingLevel) { + while (!cbor_value_at_end(it)) { + CborError err; + CborType type = cbor_value_get_type(it); +//printf("^%x^", type); + bool got_next; + + switch (type) { + case CborMapType: /*{ + // recursive type + CborValue recursed; + assert(cbor_value_is_container(it)); + printf("Map[\n"); + err = cbor_value_enter_container(it, &recursed); + if (err) + return err; // parse error + + // name + err = dumpelm(&recursed, next!!!!, nestingLevel + 1); + if (err) + return err; + + printf(":"); + err = cbor_value_advance_fixed(it); + if (err) + return err; + + // value +printf("*"); + err = dumprecursive(&recursed, nestingLevel + 1); + if (err) + return err; // parse error + + err = cbor_value_leave_container(it, &recursed); + if (err) + return err; // parse error + indent(nestingLevel); + printf("]\n"); + continue; + }*/ + case CborArrayType: { + // recursive type + CborValue recursed; + assert(cbor_value_is_container(it)); + indent(nestingLevel); + printf(type == CborArrayType ? "Array[\n" : "Map[\n"); + err = cbor_value_enter_container(it, &recursed); + if (err) + return err; // parse error + err = dumprecursive(&recursed, nestingLevel + 1); + if (err) + return err; // parse error + err = cbor_value_leave_container(it, &recursed); + if (err) + return err; // parse error + indent(nestingLevel); + printf("]\n"); + continue; + } + + default: { + err = dumpelm(it, &got_next, nestingLevel); + printf("\n"); + if (err) + return err; + break; + } + } + + if (!got_next) { + err = cbor_value_advance_fixed(it); + if (err) + return err; + } + } + return CborNoError; +} + +int TinyCborInit(uint8_t *data, size_t length, CborValue *cb) { CborParser parser; CborError err = cbor_parser_init(data, length, 0, &parser, cb); - // if (!err) - // err = dumprecursive(cb, 0); - - if (err) { - fprintf(stderr, "CBOR parsing failure at offset %d: %s\n", - cb->ptr - data, cbor_error_string(err)); - return 1; - } + if (err) + return err; return 0; } @@ -32,10 +211,20 @@ int TinyCborParser(uint8_t *data, size_t length, CborValue *cb) { int TinyCborPrintFIDOPackage(uint8_t *data, size_t length) { CborValue cb; int res; - res = TinyCborParser(data, length, &cb); + res = TinyCborInit(&data[1], length - 1, &cb); if (res) return res; + + + CborError err = dumprecursive(&cb, 0); + + if (err) { + fprintf(stderr, "CBOR parsing failure at offset %d: %s\n", + cb.ptr - data, cbor_error_string(err)); + return 1; + } + + return 0; } - From faef1a093801d54f423441e0f551c8292fe1fe7d Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 16 Nov 2018 23:57:55 +0100 Subject: [PATCH 0197/1938] chg: lf simulation - trying the new clock for better timings. --- armsrc/lfops.c | 109 ++++++++++++++++++++++++++----------------------- 1 file changed, 57 insertions(+), 52 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 021fc2411..0dac64bd1 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -575,10 +575,13 @@ void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc) // this may destroy the bigbuf so be sure this is called before calling SimulateTagLowFrequencyEx void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycles) { + // start us timer + StartTicks(); + //FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE ); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); - SpinDelay(20); - + WaitMS(20); + int i = 0, x = 0; uint8_t *buf = BigBuf_get_addr(); @@ -617,7 +620,7 @@ void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycle goto OUT; } - if(buf[i]) + if (buf[i]) OPEN_COIL(); else SHORT_COIL(); @@ -631,17 +634,18 @@ void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycle } i++; - if(i == period) { + if (i == period) { i = 0; if (gap) { SHORT_COIL(); - SpinDelayUs(gap); + WaitUS(gap); } } if (ledcontrol) LED_D_OFF(); } OUT: + StopTicks(); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_D_OFF(); } @@ -665,44 +669,44 @@ static void fc(int c, int *n) int idx; // for when we want an fc8 pattern every 4 logical bits - if(c==0) { - dest[((*n)++)]=1; - dest[((*n)++)]=1; - dest[((*n)++)]=1; - dest[((*n)++)]=1; - dest[((*n)++)]=0; - dest[((*n)++)]=0; - dest[((*n)++)]=0; - dest[((*n)++)]=0; + if (c == 0) { + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; } // an fc/8 encoded bit is a bit pattern of 11110000 x6 = 48 samples - if(c==8) { - for (idx=0; idx<6; idx++) { - dest[((*n)++)]=1; - dest[((*n)++)]=1; - dest[((*n)++)]=1; - dest[((*n)++)]=1; - dest[((*n)++)]=0; - dest[((*n)++)]=0; - dest[((*n)++)]=0; - dest[((*n)++)]=0; + if (c == 8) { + for (idx=0; idx < 6; idx++) { + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; } } // an fc/10 encoded bit is a bit pattern of 1111100000 x5 = 50 samples - if(c==10) { - for (idx=0; idx<5; idx++) { - dest[((*n)++)]=1; - dest[((*n)++)]=1; - dest[((*n)++)]=1; - dest[((*n)++)]=1; - dest[((*n)++)]=1; - dest[((*n)++)]=0; - dest[((*n)++)]=0; - dest[((*n)++)]=0; - dest[((*n)++)]=0; - dest[((*n)++)]=0; + if (c == 10) { + for (idx = 0; idx < 5; idx++) { + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; } } } @@ -720,7 +724,7 @@ static void fcSTT(int *n) { static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) { uint8_t *dest = BigBuf_get_addr(); - uint8_t halfFC = fc/2; + uint8_t halfFC = fc >> 1; uint8_t wavesPerClock = clock/fc; uint8_t mod = clock % fc; //modifier uint8_t modAdj = fc/mod; //how often to apply modifier @@ -729,21 +733,22 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) // loop through clock - step field clock for (uint8_t idx=0; idx < wavesPerClock; idx++){ // put 1/2 FC length 1's and 1/2 0's per field clock wave (to create the wave) - memset(dest+(*n), 0, fc-halfFC); //in case of odd number use extra here - memset(dest+(*n)+(fc-halfFC), 1, halfFC); + memset(dest + (*n), 0, fc - halfFC); //in case of odd number use extra here + memset(dest + (*n) + (fc - halfFC), 1, halfFC); *n += fc; } - if (mod>0) (*modCnt)++; - if ((mod>0) && modAdjOk){ //fsk2 + if (mod > 0) (*modCnt)++; + + if ((mod > 0) && modAdjOk){ //fsk2 if ((*modCnt % modAdj) == 0){ //if 4th 8 length wave in a rf/50 add extra 8 length wave - memset(dest+(*n), 0, fc-halfFC); - memset(dest+(*n)+(fc-halfFC), 1, halfFC); + memset(dest + (*n), 0, fc - halfFC); + memset(dest + (*n) + ( fc - halfFC), 1, halfFC); *n += fc; } } - if (mod>0 && !modAdjOk){ //fsk1 - memset(dest+(*n), 0, mod-(mod/2)); - memset(dest+(*n)+(mod-(mod/2)), 1, mod/2); + if (mod > 0 && !modAdjOk){ //fsk1 + memset(dest + (*n), 0, mod - (mod >> 1)); + memset(dest + (*n) + (mod - (mod >> 1)), 1, mod >> 1); *n += mod; } } @@ -781,11 +786,11 @@ void CmdHIDsimTAGEx( uint32_t hi, uint32_t lo, int ledcontrol, int numcycles) { fcSTT(&n); // manchester encode bits 43 to 32 - for (i=11; i>=0; i--) { + for (i = 11; i >= 0; i--) { - if ((i%4)==3) fc(0, &n); + if ((i % 4) == 3) fc(0, &n); - if ((hi>>i) & 1) { + if ((hi >> i) & 1) { fc(10, &n); fc(8, &n); // low-high transition } else { fc(8, &n); fc(10, &n); // high-low transition @@ -793,11 +798,11 @@ void CmdHIDsimTAGEx( uint32_t hi, uint32_t lo, int ledcontrol, int numcycles) { } // manchester encode bits 31 to 0 - for (i=31; i>=0; i--) { + for (i = 31; i >= 0; i--) { - if ((i%4)==3) fc(0, &n); + if ((i % 4) == 3) fc(0, &n); - if ((lo>>i) & 1) { + if (( lo >> i ) & 1) { fc(10, &n); fc(8, &n); // low-high transition } else { fc(8, &n); fc(10, &n); // high-low transition From aa3b322d0f86f9b7e1f7ee8ecfefa8b84f805ab5 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 16 Nov 2018 23:59:14 +0100 Subject: [PATCH 0198/1938] chg: 'analyze a' - some fpc test changes. --- armsrc/appmain.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index a3b330e84..60229868d 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1080,26 +1080,28 @@ void UsbPacketReceived(uint8_t *packet, int len) { static const char* welcome = "Proxmark3 Serial interface ready\n"; strncat(dest, welcome, sizeof(dest) - strlen(dest) - 1); - sprintf(dest + strlen(dest) - 1, "Arg0 | 0x%" PRIx64 " \n", c->arg[0]); - sprintf(dest + strlen(dest) - 1, "Arg1 | 0x%" PRIx64 " \n", c->arg[1]); - sprintf(dest + strlen(dest) - 1, "Arg2 | 0x%" PRIx64 " \n", c->arg[2]); - sprintf(dest + strlen(dest) - 1, "bytes | 0x%02x 0x%02x 0x%02x 0x%02x \n" + sprintf(dest + strlen(dest) - 1, "| Arg0 0x%" PRIx64 " \n", c->arg[0]); + sprintf(dest + strlen(dest) - 1, "| Arg1 0x%" PRIx64 " \n", c->arg[1]); + sprintf(dest + strlen(dest) - 1, "| Arg2 0x%" PRIx64 " \n", c->arg[2]); + sprintf(dest + strlen(dest) - 1, "| bytes 0x%02x 0x%02x 0x%02x 0x%02x \n" ,c->d.asBytes[0], c->d.asBytes[1], c->d.asBytes[2], c->d.asBytes[3]); -/* + UsbCommand txcmd; for (size_t i=0; i < sizeof(UsbCommand); i++) ((uint8_t*)&txcmd)[i] = 0x00; // Compose the outgoing command frame txcmd.cmd = CMD_DEBUG_PRINT_STRING; - txcmd.arg[0] = len; + txcmd.arg[0] = strlen(dest); txcmd.arg[1] = 0; txcmd.arg[2] = 0; memcpy(txcmd.d.asBytes, dest, USB_CMD_DATA_SIZE); + + usart_init(); usart_writebuffer((uint8_t*)&txcmd, sizeof(UsbCommand)); -*/ - DbpString("Starting to listen"); + + DbpString("Justs send to usart"); LED_A_ON(); /* uint8_t rx[sizeof(UsbCommand)]; @@ -1110,7 +1112,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { DbpString("got 544"); } */ - cmd_send(CMD_DEBUG_PRINT_STRING, strlen(dest), 0, 0, dest, strlen(dest)); + //cmd_send(CMD_DEBUG_PRINT_STRING, strlen(dest), 0, 0, dest, strlen(dest)); //DbpString("finished"); LED_A_OFF(); cmd_send(CMD_ACK,0,0,0,0,0); @@ -1196,7 +1198,6 @@ void UsbPacketReceived(uint8_t *packet, int len) { // arg0 = startindex // arg1 = length bytes to transfer // arg2 = RFU - //Dbprintf("transfer to client parameters: %" PRIu32 " | %" PRIu32 " | %" PRIu32, startidx, numofbytes, c->arg[2]); for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); @@ -1231,7 +1232,6 @@ void UsbPacketReceived(uint8_t *packet, int len) { if (!FlashInit()) { break; } - //Flash_CheckBusy(BUSY_TIMEOUT); for(size_t i = 0; i < len; i += size) { len = MIN((len - i), size); From 563086c9352004c89887baa3e5d6e85dd53b1567 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 17 Nov 2018 01:31:08 +0200 Subject: [PATCH 0199/1938] cbor print ok --- client/fido/cbortools.c | 59 +++++++++++++---------------------------- 1 file changed, 19 insertions(+), 40 deletions(-) diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index 1744277a5..dbd02a3d1 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -121,7 +121,8 @@ static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) { return CborNoError; } -static CborError dumprecursive(CborValue *it, int nestingLevel) { +static CborError dumprecursive(CborValue *it, bool isMapType, int nestingLevel) { + int elmCount = 0; while (!cbor_value_at_end(it)) { CborError err; CborType type = cbor_value_get_type(it); @@ -129,63 +130,35 @@ static CborError dumprecursive(CborValue *it, int nestingLevel) { bool got_next; switch (type) { - case CborMapType: /*{ - // recursive type - CborValue recursed; - assert(cbor_value_is_container(it)); - printf("Map[\n"); - err = cbor_value_enter_container(it, &recursed); - if (err) - return err; // parse error - - // name - err = dumpelm(&recursed, next!!!!, nestingLevel + 1); - if (err) - return err; - - printf(":"); - err = cbor_value_advance_fixed(it); - if (err) - return err; - - // value -printf("*"); - err = dumprecursive(&recursed, nestingLevel + 1); - if (err) - return err; // parse error - - err = cbor_value_leave_container(it, &recursed); - if (err) - return err; // parse error - indent(nestingLevel); - printf("]\n"); - continue; - }*/ + case CborMapType: case CborArrayType: { // recursive type CborValue recursed; assert(cbor_value_is_container(it)); - indent(nestingLevel); + if (!(isMapType && (elmCount % 2))) + indent(nestingLevel); printf(type == CborArrayType ? "Array[\n" : "Map[\n"); err = cbor_value_enter_container(it, &recursed); if (err) return err; // parse error - err = dumprecursive(&recursed, nestingLevel + 1); + err = dumprecursive(&recursed, (type == CborMapType), nestingLevel + 1); if (err) return err; // parse error err = cbor_value_leave_container(it, &recursed); if (err) return err; // parse error indent(nestingLevel); - printf("]\n"); - continue; + printf("]"); + got_next = true; + break; } default: { - err = dumpelm(it, &got_next, nestingLevel); - printf("\n"); + err = dumpelm(it, &got_next, (isMapType && (elmCount % 2)) ? 0 : nestingLevel); if (err) return err; +// if (nestingLevel == 1 && isMapType && !(elmCount % 2)) +// printf(" ()"); break; } } @@ -195,6 +168,12 @@ printf("*"); if (err) return err; } + if (isMapType && !(elmCount % 2)) { + printf(": "); + } else { + printf("\n"); + } + elmCount++; } return CborNoError; } @@ -217,7 +196,7 @@ int TinyCborPrintFIDOPackage(uint8_t *data, size_t length) { - CborError err = dumprecursive(&cb, 0); + CborError err = dumprecursive(&cb, false, 0); if (err) { fprintf(stderr, "CBOR parsing failure at offset %d: %s\n", From 8201526f6eb3f469e4ea57fcc1f8046fbed6fb7d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 17 Nov 2018 01:40:27 +0200 Subject: [PATCH 0200/1938] fix fido2 response structure --- client/cmdhffido.c | 7 ++++++- client/fido/cbortools.c | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index faff8e82c..bcac719ae 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -140,10 +140,15 @@ int CmdHFFidoInfo(const char *cmd) { return 0; } + + if(buf[0]) { + PrintAndLog("FIDO2 ger version error: %d", buf[0]); + return 0; + } PrintAndLog("FIDO2 version: (%d)", len); dump_buffer((const unsigned char *)buf, len, NULL, 0); - TinyCborPrintFIDOPackage(buf, len); + TinyCborPrintFIDOPackage(&buf[1], len - 1); return 0; } diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index dbd02a3d1..19f9abc2f 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -190,7 +190,7 @@ int TinyCborInit(uint8_t *data, size_t length, CborValue *cb) { int TinyCborPrintFIDOPackage(uint8_t *data, size_t length) { CborValue cb; int res; - res = TinyCborInit(&data[1], length - 1, &cb); + res = TinyCborInit(data, length, &cb); if (res) return res; From f4bb63a728b88f01ac542b09934e55a3021e90f9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 17 Nov 2018 01:55:29 +0200 Subject: [PATCH 0201/1938] sketch for get cmd code name --- client/cmdhffido.c | 6 ++++-- client/fido/cbortools.c | 21 +++++++++++++++------ client/fido/cbortools.h | 2 +- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index bcac719ae..b3eb47384 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -49,6 +49,8 @@ static int CmdHelp(const char *Cmd); +#define FIDO2_CMD_INFO 0x04 + int FIDOSelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { uint8_t data[] = {0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01}; @@ -82,7 +84,7 @@ int FIDOAuthentication(uint8_t *params, uint8_t paramslen, uint8_t controlb, uin } int FIDO2GetInfo(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - uint8_t data[] = {0x04}; + uint8_t data[] = {FIDO2_CMD_INFO}; return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); } @@ -148,7 +150,7 @@ int CmdHFFidoInfo(const char *cmd) { PrintAndLog("FIDO2 version: (%d)", len); dump_buffer((const unsigned char *)buf, len, NULL, 0); - TinyCborPrintFIDOPackage(&buf[1], len - 1); + TinyCborPrintFIDOPackage(FIDO2_CMD_INFO, &buf[1], len - 1); return 0; } diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index 19f9abc2f..edf881925 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -121,7 +121,11 @@ static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) { return CborNoError; } -static CborError dumprecursive(CborValue *it, bool isMapType, int nestingLevel) { +char *getCmdCodeDescription (uint8_t cmdCode, uint8_t memberNum) { + return NULL; +} + +static CborError dumprecursive(uint8_t cmdCode, CborValue *it, bool isMapType, int nestingLevel) { int elmCount = 0; while (!cbor_value_at_end(it)) { CborError err; @@ -141,7 +145,7 @@ static CborError dumprecursive(CborValue *it, bool isMapType, int nestingLevel) err = cbor_value_enter_container(it, &recursed); if (err) return err; // parse error - err = dumprecursive(&recursed, (type == CborMapType), nestingLevel + 1); + err = dumprecursive(cmdCode, &recursed, (type == CborMapType), nestingLevel + 1); if (err) return err; // parse error err = cbor_value_leave_container(it, &recursed); @@ -157,8 +161,13 @@ static CborError dumprecursive(CborValue *it, bool isMapType, int nestingLevel) err = dumpelm(it, &got_next, (isMapType && (elmCount % 2)) ? 0 : nestingLevel); if (err) return err; -// if (nestingLevel == 1 && isMapType && !(elmCount % 2)) -// printf(" ()"); + if (cmdCode > 0 && nestingLevel == 1 && isMapType && !(elmCount % 2)) { + int64_t val; + cbor_value_get_int64(it, &val); + char *desc = getCmdCodeDescription(cmdCode, val); + if (desc) + printf(" (%s)", desc); + } break; } } @@ -187,7 +196,7 @@ int TinyCborInit(uint8_t *data, size_t length, CborValue *cb) { return 0; } -int TinyCborPrintFIDOPackage(uint8_t *data, size_t length) { +int TinyCborPrintFIDOPackage(uint8_t cmdCode, uint8_t *data, size_t length) { CborValue cb; int res; res = TinyCborInit(data, length, &cb); @@ -196,7 +205,7 @@ int TinyCborPrintFIDOPackage(uint8_t *data, size_t length) { - CborError err = dumprecursive(&cb, false, 0); + CborError err = dumprecursive(cmdCode, &cb, false, 0); if (err) { fprintf(stderr, "CBOR parsing failure at offset %d: %s\n", diff --git a/client/fido/cbortools.h b/client/fido/cbortools.h index f49751b56..93d46209f 100644 --- a/client/fido/cbortools.h +++ b/client/fido/cbortools.h @@ -17,6 +17,6 @@ #include #include -extern int TinyCborPrintFIDOPackage(uint8_t *data, size_t length); +extern int TinyCborPrintFIDOPackage(uint8_t cmdCode, uint8_t *data, size_t length); #endif /* __CBORTOOLS_H__ */ From 8f1c67d5125006d90547dcdc71e536dcb7f1631e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 17 Nov 2018 16:19:09 +0200 Subject: [PATCH 0202/1938] added fidocore --- client/Makefile | 1 + client/cmdhffido.c | 7 +++---- client/fido/cbortools.c | 7 ++----- client/fido/cbortools.h | 1 - client/fido/fidocore.c | 22 ++++++++++++++++++++++ client/fido/fidocore.h | 32 ++++++++++++++++++++++++++++++++ 6 files changed, 60 insertions(+), 10 deletions(-) create mode 100644 client/fido/fidocore.c create mode 100644 client/fido/fidocore.h diff --git a/client/Makefile b/client/Makefile index f97f395e9..1e88e5dc9 100644 --- a/client/Makefile +++ b/client/Makefile @@ -112,6 +112,7 @@ CMDSRCS = crapto1/crapto1.c \ tea.c \ fido/additional_ca.c \ fido/cbortools.c \ + fido/fidocore.c \ crypto/asn1dump.c \ crypto/libpcrypto.c\ crypto/asn1utils.c\ diff --git a/client/cmdhffido.c b/client/cmdhffido.c index b3eb47384..2a61a29c7 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -46,11 +46,10 @@ #include "crypto/libpcrypto.h" #include "fido/additional_ca.h" #include "fido/cbortools.h" +#include "fido/fidocore.h" static int CmdHelp(const char *Cmd); -#define FIDO2_CMD_INFO 0x04 - int FIDOSelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { uint8_t data[] = {0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01}; @@ -84,7 +83,7 @@ int FIDOAuthentication(uint8_t *params, uint8_t paramslen, uint8_t controlb, uin } int FIDO2GetInfo(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - uint8_t data[] = {FIDO2_CMD_INFO}; + uint8_t data[] = {fido2CmdGetInfo}; return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); } @@ -150,7 +149,7 @@ int CmdHFFidoInfo(const char *cmd) { PrintAndLog("FIDO2 version: (%d)", len); dump_buffer((const unsigned char *)buf, len, NULL, 0); - TinyCborPrintFIDOPackage(FIDO2_CMD_INFO, &buf[1], len - 1); + TinyCborPrintFIDOPackage(fido2CmdGetInfo, &buf[1], len - 1); return 0; } diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index edf881925..cd8f905bb 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -14,6 +14,7 @@ #include #include "cbor.h" #include "util.h" +#include "fidocore.h" static void indent(int nestingLevel) { while (nestingLevel--) @@ -121,10 +122,6 @@ static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) { return CborNoError; } -char *getCmdCodeDescription (uint8_t cmdCode, uint8_t memberNum) { - return NULL; -} - static CborError dumprecursive(uint8_t cmdCode, CborValue *it, bool isMapType, int nestingLevel) { int elmCount = 0; while (!cbor_value_at_end(it)) { @@ -164,7 +161,7 @@ static CborError dumprecursive(uint8_t cmdCode, CborValue *it, bool isMapType, i if (cmdCode > 0 && nestingLevel == 1 && isMapType && !(elmCount % 2)) { int64_t val; cbor_value_get_int64(it, &val); - char *desc = getCmdCodeDescription(cmdCode, val); + char *desc = fido2GetCmdMemberDescription(cmdCode, val); if (desc) printf(" (%s)", desc); } diff --git a/client/fido/cbortools.h b/client/fido/cbortools.h index 93d46209f..bb442f1f8 100644 --- a/client/fido/cbortools.h +++ b/client/fido/cbortools.h @@ -10,7 +10,6 @@ //----------------------------------------------------------------------------- // - #ifndef __CBORTOOLS_H__ #define __CBORTOOLS_H__ diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c new file mode 100644 index 000000000..4676aa7d3 --- /dev/null +++ b/client/fido/fidocore.c @@ -0,0 +1,22 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// FIDO2 authenticators core data and commands +// https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html +//----------------------------------------------------------------------------- +// + +#include "fidocore.h" + +char *fido2GetCmdMemberDescription(uint8_t cmdCode, uint8_t memberNum) { + + + + + return NULL; +} + diff --git a/client/fido/fidocore.h b/client/fido/fidocore.h new file mode 100644 index 000000000..10ed65ea0 --- /dev/null +++ b/client/fido/fidocore.h @@ -0,0 +1,32 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// FIDO2 authenticators core data and commands +// https://fidoalliance.org/specs/fido-v2.0-id-20180227/fido-client-to-authenticator-protocol-v2.0-id-20180227.html +//----------------------------------------------------------------------------- +// +#ifndef __FIDOCORE_H__ +#define __FIDOCORE_H__ + +#include +#include + +enum fido2Commands { + fido2CmdMakeCredential = 0x01, + fido2CmdGetAssertion = 0x02, + fido2CmdCancel = 0x03, + fido2CmdGetInfo = 0x04, + fido2CmdClientPIN = 0x06, + fido2CmdReset = 0x07, + fido2CmdGetNextAssertion = 0x08, +}; + + + +extern char *fido2GetCmdMemberDescription(uint8_t cmdCode, uint8_t memberNum); + +#endif /* __FIDOCORE_H__ */ From 23ef267100c2c0617b612035f5741f2d8bdb4953 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 17 Nov 2018 18:11:46 +0200 Subject: [PATCH 0203/1938] added fido2 error codes description --- client/cmdhffido.c | 2 +- client/fido/fidocore.c | 91 ++++++++++++++++++++++++++++++++++++++++++ client/fido/fidocore.h | 2 + 3 files changed, 94 insertions(+), 1 deletion(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 2a61a29c7..e344e4445 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -143,7 +143,7 @@ int CmdHFFidoInfo(const char *cmd) { } if(buf[0]) { - PrintAndLog("FIDO2 ger version error: %d", buf[0]); + PrintAndLog("FIDO2 ger version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); return 0; } diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 4676aa7d3..1263baef9 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -11,6 +11,97 @@ // #include "fidocore.h" +typedef struct { + uint8_t ErrorCode; + char *ShortDescription; + char *Description; +} fido2Error_t; + +fido2Error_t fido2Errors[] = { + {0xFF, "n/a", "n/a"}, + {0x00, "CTAP1_ERR_SUCCESS", "Indicates successful response."}, + {0x01, "CTAP1_ERR_INVALID_COMMAND", "The command is not a valid CTAP command."}, + {0x02, "CTAP1_ERR_INVALID_PARAMETER", "The command included an invalid parameter."}, + {0x03, "CTAP1_ERR_INVALID_LENGTH", "Invalid message or item length."}, + {0x04, "CTAP1_ERR_INVALID_SEQ", "Invalid message sequencing."}, + {0x05, "CTAP1_ERR_TIMEOUT", "Message timed out."}, + {0x06, "CTAP1_ERR_CHANNEL_BUSY", "Channel busy."}, + {0x0A, "CTAP1_ERR_LOCK_REQUIRED", "Command requires channel lock."}, + {0x0B, "CTAP1_ERR_INVALID_CHANNEL", "Command not allowed on this cid."}, + {0x10, "CTAP2_ERR_CBOR_PARSING", "Error while parsing CBOR."}, + {0x11, "CTAP2_ERR_CBOR_UNEXPECTED_TYPE", "Invalid/unexpected CBOR error."}, + {0x12, "CTAP2_ERR_INVALID_CBOR", "Error when parsing CBOR."}, + {0x13, "CTAP2_ERR_INVALID_CBOR_TYPE", "Invalid or unexpected CBOR type."}, + {0x14, "CTAP2_ERR_MISSING_PARAMETER", "Missing non-optional parameter."}, + {0x15, "CTAP2_ERR_LIMIT_EXCEEDED", "Limit for number of items exceeded."}, + {0x16, "CTAP2_ERR_UNSUPPORTED_EXTENSION", "Unsupported extension."}, + {0x17, "CTAP2_ERR_TOO_MANY_ELEMENTS", "Limit for number of items exceeded."}, + {0x18, "CTAP2_ERR_EXTENSION_NOT_SUPPORTED", "Unsupported extension."}, + {0x19, "CTAP2_ERR_CREDENTIAL_EXCLUDED", "Valid credential found in the exludeList."}, + {0x20, "CTAP2_ERR_CREDENTIAL_NOT_VALID", "Credential not valid for authenticator."}, + {0x21, "CTAP2_ERR_PROCESSING", "Processing (Lengthy operation is in progress)."}, + {0x22, "CTAP2_ERR_INVALID_CREDENTIAL", "Credential not valid for the authenticator."}, + {0x23, "CTAP2_ERR_USER_ACTION_PENDING", "Authentication is waiting for user interaction."}, + {0x24, "CTAP2_ERR_OPERATION_PENDING", "Processing, lengthy operation is in progress."}, + {0x25, "CTAP2_ERR_NO_OPERATIONS", "No request is pending."}, + {0x26, "CTAP2_ERR_UNSUPPORTED_ALGORITHM", "Authenticator does not support requested algorithm."}, + {0x27, "CTAP2_ERR_OPERATION_DENIED", "Not authorized for requested operation."}, + {0x28, "CTAP2_ERR_KEY_STORE_FULL", "Internal key storage is full."}, + {0x29, "CTAP2_ERR_NOT_BUSY", "Authenticator cannot cancel as it is not busy."}, + {0x2A, "CTAP2_ERR_NO_OPERATION_PENDING", "No outstanding operations."}, + {0x2B, "CTAP2_ERR_UNSUPPORTED_OPTION", "Unsupported option."}, + {0x2C, "CTAP2_ERR_INVALID_OPTION", "Unsupported option."}, + {0x2D, "CTAP2_ERR_KEEPALIVE_CANCEL", "Pending keep alive was cancelled."}, + {0x2E, "CTAP2_ERR_NO_CREDENTIALS", "No valid credentials provided."}, + {0x2F, "CTAP2_ERR_USER_ACTION_TIMEOUT", "Timeout waiting for user interaction."}, + {0x30, "CTAP2_ERR_NOT_ALLOWED", "Continuation command, such as, authenticatorGetNextAssertion not allowed."}, + {0x31, "CTAP2_ERR_PIN_INVALID", "PIN Blocked."}, + {0x32, "CTAP2_ERR_PIN_BLOCKED", "PIN Blocked."}, + {0x33, "CTAP2_ERR_PIN_AUTH_INVALID", "PIN authentication,pinAuth, verification failed."}, + {0x34, "CTAP2_ERR_PIN_AUTH_BLOCKED", "PIN authentication,pinAuth, blocked. Requires power recycle to reset."}, + {0x35, "CTAP2_ERR_PIN_NOT_SET", "No PIN has been set."}, + {0x36, "CTAP2_ERR_PIN_REQUIRED", "PIN is required for the selected operation."}, + {0x37, "CTAP2_ERR_PIN_POLICY_VIOLATION", "PIN policy violation. Currently only enforces minimum length."}, + {0x38, "CTAP2_ERR_PIN_TOKEN_EXPIRED", "pinToken expired on authenticator."}, + {0x39, "CTAP2_ERR_REQUEST_TOO_LARGE", "Authenticator cannot handle this request due to memory constraints."}, + {0x7F, "CTAP1_ERR_OTHER", "Other unspecified error."}, + {0xDF, "CTAP2_ERR_SPEC_LAST", "CTAP 2 spec last error."}, +}; + +typedef struct { + uint8_t MemberNumber; + char *Description; +} fido2Desc_t; + +typedef fido2Desc_t fido2ArrayDesc_t[]; +/* +typedef struct { + fido2Desc_t Query[]; + fido2Desc_t Resp[]; +} fido2CmdDesc_t; + +fido2CmdDesc_t fido2CmdDesc[] = { // fido2CommandsCount + {fido2CmdGetInfoRespDesc, fido2CmdGetInfoRespDesc}, + {fido2CmdGetInfoRespDesc, fido2CmdGetInfoRespDesc}, +}; +*/ +fido2Desc_t fido2CmdGetInfoRespDesc[] = { + {0x01, "versions"}, + {0x02, "extensions"}, + {0x03, "aaguid"}, + {0x04, "options"}, + {0x05, "maxMsgSize"}, + {0x06, "pinProtocols"}, + {0xff, ""}, +}; + +char *fido2GetCmdErrorDescription(uint8_t errorCode) { + for (int i = 0; i < sizeof(fido2Errors) / sizeof(fido2Error_t); i++) + if (fido2Errors[i].ErrorCode == errorCode) + return fido2Errors[i].Description; + + return fido2Errors[0].Description; +} char *fido2GetCmdMemberDescription(uint8_t cmdCode, uint8_t memberNum) { diff --git a/client/fido/fidocore.h b/client/fido/fidocore.h index 10ed65ea0..252adec90 100644 --- a/client/fido/fidocore.h +++ b/client/fido/fidocore.h @@ -24,9 +24,11 @@ enum fido2Commands { fido2CmdReset = 0x07, fido2CmdGetNextAssertion = 0x08, }; +#define fido2CommandsCount 9 extern char *fido2GetCmdMemberDescription(uint8_t cmdCode, uint8_t memberNum); +extern char *fido2GetCmdErrorDescription(uint8_t errorCode); #endif /* __FIDOCORE_H__ */ From 12b12891914fcd4828ce94d2a07a7546aee344b6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 17 Nov 2018 18:39:21 +0200 Subject: [PATCH 0204/1938] fido info command completed --- client/cmdhffido.c | 16 +++++++++--- client/fido/fidocore.c | 57 +++++++++++++++++++++++++----------------- client/fido/fidocore.h | 10 +++++--- 3 files changed, 52 insertions(+), 31 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index e344e4445..954d96a8a 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -147,10 +147,18 @@ int CmdHFFidoInfo(const char *cmd) { return 0; } - PrintAndLog("FIDO2 version: (%d)", len); - dump_buffer((const unsigned char *)buf, len, NULL, 0); - TinyCborPrintFIDOPackage(fido2CmdGetInfo, &buf[1], len - 1); - + if (len > 1) { +// if (false) { +// PrintAndLog("FIDO2 version: (len=%d)", len); +// dump_buffer((const unsigned char *)buf, len, NULL, 0); +// } + + PrintAndLog("FIDO2 version CBOR decoded:"); + TinyCborPrintFIDOPackage(fido2CmdGetInfo, &buf[1], len - 1); + } else { + PrintAndLog("FIDO2 version length error"); + } + return 0; } diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 1263baef9..1b41d2722 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -11,6 +11,7 @@ // #include "fidocore.h" + typedef struct { uint8_t ErrorCode; char *ShortDescription; @@ -69,30 +70,38 @@ fido2Error_t fido2Errors[] = { }; typedef struct { + fido2Commands Command; + fido2PacketType PckType; uint8_t MemberNumber; char *Description; } fido2Desc_t; -typedef fido2Desc_t fido2ArrayDesc_t[]; -/* -typedef struct { - fido2Desc_t Query[]; - fido2Desc_t Resp[]; -} fido2CmdDesc_t; - -fido2CmdDesc_t fido2CmdDesc[] = { // fido2CommandsCount - {fido2CmdGetInfoRespDesc, fido2CmdGetInfoRespDesc}, - {fido2CmdGetInfoRespDesc, fido2CmdGetInfoRespDesc}, -}; -*/ fido2Desc_t fido2CmdGetInfoRespDesc[] = { - {0x01, "versions"}, - {0x02, "extensions"}, - {0x03, "aaguid"}, - {0x04, "options"}, - {0x05, "maxMsgSize"}, - {0x06, "pinProtocols"}, - {0xff, ""}, + {fido2CmdMakeCredential, ptResponse, 0x01, "fmt"}, + {fido2CmdMakeCredential, ptResponse, 0x02, "authData"}, + {fido2CmdMakeCredential, ptResponse, 0x03, "attStmt"}, + + {fido2CmdGetAssertion, ptResponse, 0x01, "credential"}, + {fido2CmdGetAssertion, ptResponse, 0x02, "authData"}, + {fido2CmdGetAssertion, ptResponse, 0x03, "signature"}, + {fido2CmdGetAssertion, ptResponse, 0x04, "publicKeyCredentialUserEntity"}, + {fido2CmdGetAssertion, ptResponse, 0x05, "numberOfCredentials"}, + + {fido2CmdGetNextAssertion, ptResponse, 0x01, "credential"}, + {fido2CmdGetNextAssertion, ptResponse, 0x02, "authData"}, + {fido2CmdGetNextAssertion, ptResponse, 0x03, "signature"}, + {fido2CmdGetNextAssertion, ptResponse, 0x04, "publicKeyCredentialUserEntity"}, + + {fido2CmdGetInfo, ptResponse, 0x01, "versions"}, + {fido2CmdGetInfo, ptResponse, 0x02, "extensions"}, + {fido2CmdGetInfo, ptResponse, 0x03, "aaguid"}, + {fido2CmdGetInfo, ptResponse, 0x04, "options"}, + {fido2CmdGetInfo, ptResponse, 0x05, "maxMsgSize"}, + {fido2CmdGetInfo, ptResponse, 0x06, "pinProtocols"}, + + {fido2CmdClientPIN, ptResponse, 0x06, "keyAgreement"}, + {fido2CmdClientPIN, ptResponse, 0x06, "pinToken"}, + {fido2CmdClientPIN, ptResponse, 0x06, "retries"}, }; char *fido2GetCmdErrorDescription(uint8_t errorCode) { @@ -104,10 +113,12 @@ char *fido2GetCmdErrorDescription(uint8_t errorCode) { } char *fido2GetCmdMemberDescription(uint8_t cmdCode, uint8_t memberNum) { - - - - + for (int i = 0; i < sizeof(fido2CmdGetInfoRespDesc) / sizeof(fido2Desc_t); i++) + if (fido2CmdGetInfoRespDesc[i].Command == cmdCode && + fido2CmdGetInfoRespDesc[i].PckType == ptResponse && + fido2CmdGetInfoRespDesc[i].MemberNumber == memberNum ) + return fido2CmdGetInfoRespDesc[i].Description; + return NULL; } diff --git a/client/fido/fidocore.h b/client/fido/fidocore.h index 252adec90..1ed5556cf 100644 --- a/client/fido/fidocore.h +++ b/client/fido/fidocore.h @@ -15,7 +15,7 @@ #include #include -enum fido2Commands { +typedef enum { fido2CmdMakeCredential = 0x01, fido2CmdGetAssertion = 0x02, fido2CmdCancel = 0x03, @@ -23,10 +23,12 @@ enum fido2Commands { fido2CmdClientPIN = 0x06, fido2CmdReset = 0x07, fido2CmdGetNextAssertion = 0x08, -}; -#define fido2CommandsCount 9 - +} fido2Commands; +typedef enum { + ptQuery, + ptResponse, +} fido2PacketType; extern char *fido2GetCmdMemberDescription(uint8_t cmdCode, uint8_t memberNum); extern char *fido2GetCmdErrorDescription(uint8_t errorCode); From dc9b3c3a0ee4892bda86044e029e8218d1070f45 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 17 Nov 2018 23:52:36 +0200 Subject: [PATCH 0205/1938] added fido2 base commands --- client/cmdhffido.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 954d96a8a..79df33ddb 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -87,6 +87,20 @@ int FIDO2GetInfo(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16 return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); } +int FIDO2MakeCredential(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + uint8_t data[paramslen + 1]; + data[0] = fido2CmdMakeCredential; + memcpy(&data[1], params, paramslen); + return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); +} + +int FIDO2GetAssertion(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + uint8_t data[paramslen + 1]; + data[0] = fido2CmdGetAssertion; + memcpy(&data[1], params, paramslen); + return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); +} + int CmdHFFidoInfo(const char *cmd) { if (cmd && strlen(cmd) > 0) From dcfd75d1d0bc3fe2d42ee90d1d91d4a6a504494e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 18 Nov 2018 00:03:28 +0200 Subject: [PATCH 0206/1938] added command sketch --- client/cmdhffido.c | 63 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 58 insertions(+), 5 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 79df33ddb..11c63d92e 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -720,13 +720,66 @@ int CmdHFFidoAuthenticate(const char *cmd) { return 0; }; +int CmdHFFido2MakeCredential(const char *cmd) { + + + uint8_t data[2048] = {0}; + size_t datalen = 0; + uint8_t buf[2048] = {0}; + size_t len = 0; + uint16_t sw = 0; + + DropField(); + int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); + + if (res) { + PrintAndLog("Can't select authenticator. res=%x. Exit...", res); + DropField(); + return res; + } + + if (sw != 0x9000) { + PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); + return 2; + } + + res = FIDO2MakeCredential(data, datalen, buf, sizeof(buf), &len, &sw); + DropField(); + if (res) { + PrintAndLog("Can't execute register command. res=%x. Exit...", res); + return res; + } + + if (sw != 0x9000) { + PrintAndLog("ERROR execute register command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + return 3; + } + + if(buf[0]) { + PrintAndLog("FIDO2 ger version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); + return 0; + } + + PrintAndLog("res[%d]: %s", len, sprint_hex(buf, len)); + + return 0; +}; + +int CmdHFFido2GetAssertion(const char *cmd) { + + return 0; +}; + static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help."}, - {"info", CmdHFFidoInfo, 0, "Info about FIDO tag."}, - {"reg", CmdHFFidoRegister, 0, "FIDO U2F Registration Message."}, - {"auth", CmdHFFidoAuthenticate, 0, "FIDO U2F Authentication Message."}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help."}, + {"info", CmdHFFidoInfo, 0, "Info about FIDO tag."}, + {"reg", CmdHFFidoRegister, 0, "FIDO U2F Registration Message."}, + {"auth", CmdHFFidoAuthenticate, 0, "FIDO U2F Authentication Message."}, + {"make", CmdHFFido2MakeCredential, 0, "FIDO2 MakeCredential command."}, + {"accert", CmdHFFido2GetAssertion, 0, "FIDO2 GetAssertion command."}, + {NULL, NULL, 0, NULL} }; int CmdHFFido(const char *Cmd) { From 6d4552540ba5d00fb5cfb48786b028a517a6a136 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 18 Nov 2018 19:18:18 +0200 Subject: [PATCH 0207/1938] added fido2 test json --- client/fido/fido2.json | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 client/fido/fido2.json diff --git a/client/fido/fido2.json b/client/fido/fido2.json new file mode 100644 index 000000000..ceb55bae8 --- /dev/null +++ b/client/fido/fido2.json @@ -0,0 +1,35 @@ +{ + "ClientDataHash": "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f", + "RelyingPartyEntity": { + "isMap": true, + "id": "acme.com", + "name": "Acme" + }, + "UserEntity": { + "isMap": true, + "id": "00000000000000000000000000000000", + "icon": "https://pics.acme.com/00/p/aBjjjpqPb.png", + "name": "johnpsmith@acme.com", + "displayName": "John P. Smith" + }, + "pubKeyCredParams": [ + { + "isMap": true, + "type": "public-key", + "alg": -7, + "name": "ES256" + }, + { + "isMap": true, + "type": "public-key", + "alg": -257, + "name": "RS256" + } + ], + "options": { + "isMap": true, + "up": false, + "uv": false, + "keyStorageDevice": true + } +} \ No newline at end of file From f8c33af1daa417875f8712dc737c00d289d0d514 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 20 Nov 2018 10:58:32 +0100 Subject: [PATCH 0208/1938] CHG: FPC connector tests. Device -> Client communications works. Adjust armsrc/Makefile and client/Makefile to include the -DWITH_FPC flag to compile with FPC enabled. --- armsrc/appmain.c | 81 ++++++++++++++++++++------------ client/comms.c | 18 +++++--- common/cmd.c | 4 +- common/usart.c | 114 +++++++++++++++------------------------------- common/usart.h | 2 +- uart/uart_posix.c | 6 ++- uart/uart_win32.c | 17 ++++++- 7 files changed, 123 insertions(+), 119 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 60229868d..eed443599 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -628,7 +628,7 @@ void ListenReaderField(int limit) { void UsbPacketReceived(uint8_t *packet, int len) { UsbCommand *c = (UsbCommand *)packet; - //Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d",len,c->cmd,c->arg[0],c->arg[1],c->arg[2]); + //Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d", len, c->cmd, c->arg[0], c->arg[1], c->arg[2]); switch(c->cmd) { #ifdef WITH_LF @@ -1075,47 +1075,70 @@ void UsbPacketReceived(uint8_t *packet, int len) { #ifdef WITH_FPC case CMD_FPC_SEND: { + + StartTicks(); + DbpString("Mutual USB/FPC sending from device to client"); + + /* + char at[11] = {'\0'}; + static const char* s_at = "AT+BAUD8\0D\0A"; + strncat(at, s_at, sizeof(at) - strlen(at) - 1); + DbpString("Try AT baud rate setting"); + usart_init(); + int16_t res = usart_writebuffer((uint8_t*)&at, sizeof(at)); + WaitMS(1); + Dbprintf("SEND %d | %c%c%c%c%c%c%c%c%c%c%c", res, at[0], at[1], at[2], at[3], at[4], at[5], at[6], at[7], at[8], at[9], at[10]); + + uint8_t my_rx[20]; + memset(my_rx, 0, sizeof(my_rx)); + res = usart_readbuffer(my_rx, sizeof(my_rx)); + WaitMS(1); + Dbprintf("GOT %d | %c%c%c%c%c%c%c%c", res, my_rx[0], my_rx[1], my_rx[2], my_rx[3], my_rx[4], my_rx[5], my_rx[6], my_rx[7]); + */ + + char dest[USB_CMD_DATA_SIZE] = { '\0' }; - - static const char* welcome = "Proxmark3 Serial interface ready\n"; + static const char* welcome = "Proxmark3 Serial interface via FPC ready\n"; strncat(dest, welcome, sizeof(dest) - strlen(dest) - 1); - - sprintf(dest + strlen(dest) - 1, "| Arg0 0x%" PRIx64 " \n", c->arg[0]); - sprintf(dest + strlen(dest) - 1, "| Arg1 0x%" PRIx64 " \n", c->arg[1]); - sprintf(dest + strlen(dest) - 1, "| Arg2 0x%" PRIx64 " \n", c->arg[2]); sprintf(dest + strlen(dest) - 1, "| bytes 0x%02x 0x%02x 0x%02x 0x%02x \n" - ,c->d.asBytes[0], c->d.asBytes[1], c->d.asBytes[2], c->d.asBytes[3]); + , c->d.asBytes[0] + , c->d.asBytes[1] + , c->d.asBytes[2] + , c->d.asBytes[3] + ); + UsbCommand txcmd = { CMD_DEBUG_PRINT_STRING, { strlen(dest), 0, 0 } }; + memcpy(txcmd.d.asBytes, dest, sizeof(dest)); - UsbCommand txcmd; - for (size_t i=0; i < sizeof(UsbCommand); i++) - ((uint8_t*)&txcmd)[i] = 0x00; - - // Compose the outgoing command frame - txcmd.cmd = CMD_DEBUG_PRINT_STRING; - txcmd.arg[0] = strlen(dest); - txcmd.arg[1] = 0; - txcmd.arg[2] = 0; - memcpy(txcmd.d.asBytes, dest, USB_CMD_DATA_SIZE); - + LED_A_ON(); + usart_init(); usart_writebuffer((uint8_t*)&txcmd, sizeof(UsbCommand)); - - DbpString("Justs send to usart"); - LED_A_ON(); + + //usb + cmd_send(CMD_DEBUG_PRINT_STRING, strlen(dest), 0, 0, dest, strlen(dest)); + LED_A_OFF(); + + /* - uint8_t rx[sizeof(UsbCommand)]; - usart_init(); + uint8_t my_rx[sizeof(UsbCommand)]; while (!BUTTON_PRESS() && !usb_poll_validate_length()) { - WaitMS(1); - if (usart_readbuffer(rx, sizeof(rx)) ) - DbpString("got 544"); + LED_B_INV(); + if (usart_readbuffer(my_rx, sizeof(UsbCommand)) ) { + //UsbPacketReceived(my_rx, sizeof(my_rx)); + + UsbCommand *my = (UsbCommand *)my_rx; + if (mc->cmd > 0 ) { + Dbprintf("received command: 0x%04x and args: %d %d %d", my->cmd, my->arg[0], my->arg[1], my->arg[2]); + } + } } */ + //cmd_send(CMD_DEBUG_PRINT_STRING, strlen(dest), 0, 0, dest, strlen(dest)); - //DbpString("finished"); - LED_A_OFF(); + cmd_send(CMD_ACK,0,0,0,0,0); + StopTicks(); break; } #endif diff --git a/client/comms.c b/client/comms.c index 7204aa1c4..97af830df 100644 --- a/client/comms.c +++ b/client/comms.c @@ -146,7 +146,7 @@ static int getCommand(UsbCommand* response) { // that we weren't necessarily expecting, for example a debug print. //----------------------------------------------------------------------------- static void UsbCommandReceived(UsbCommand* c) { - + switch(c->cmd) { // First check if we are handling a debug message case CMD_DEBUG_PRINT_STRING: { @@ -237,7 +237,7 @@ __attribute__((force_align_arg_pointer)) #endif *uart_communication(void *targ) { communication_arg_t *conn = (communication_arg_t*)targ; - size_t rxlen; + size_t rxlen, totallen = 0; UsbCommand rx; UsbCommand *prx = ℞ @@ -247,22 +247,29 @@ __attribute__((force_align_arg_pointer)) disableAppNap("Proxmark3 polling UART"); #endif - while (conn->run) { rxlen = 0; bool ACK_received = false; + if (uart_receive(sp, (uint8_t *)prx, sizeof(UsbCommand) - (prx - &rx), &rxlen) && rxlen) { prx += rxlen; + totallen += rxlen; - if (prx - &rx < sizeof(UsbCommand)) { - PrintAndLogEx(NORMAL, "Foo %d | %d (will loop)", prx - &rx, rxlen); + if ( totallen < sizeof(UsbCommand)) { + + // iceman: this looping is no working as expected at all. The reassemble of package is nonfunctional. + // solved so far with increasing the timeouts of the serial port configuration. + PrintAndLogEx(NORMAL, "Foo %d | %d (loop)", prx - &rx, rxlen); continue; } + + totallen = 0; UsbCommandReceived(&rx); if (rx.cmd == CMD_ACK) { ACK_received = true; } } + prx = ℞ pthread_mutex_lock(&txBufferMutex); @@ -297,7 +304,6 @@ __attribute__((force_align_arg_pointer)) #if defined(__MACH__) && defined(__APPLE__) enableAppNap(); #endif - pthread_exit(NULL); return NULL; diff --git a/common/cmd.c b/common/cmd.c index 281ff0065..dec095750 100644 --- a/common/cmd.c +++ b/common/cmd.c @@ -56,8 +56,8 @@ uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void sendlen = usb_write( (uint8_t*)&txcmd, sizeof(UsbCommand) ); #ifdef WITH_FPC - usart_init(); - usart_writebuffer( (uint8_t*)&txcmd, sizeof(UsbCommand) ); +// usart_init(); +// usart_writebuffer( (uint8_t*)&txcmd, sizeof(UsbCommand) ); #endif return sendlen; diff --git a/common/usart.c b/common/usart.c index b58a7cbaa..32ccb5ca1 100644 --- a/common/usart.c +++ b/common/usart.c @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- // Iceman, July 2018 -// edists by - Anticat, August 2018 +// edits by - Anticat, August 2018 // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -14,7 +14,7 @@ #define AT91_BAUD_RATE 115200 volatile AT91PS_USART pUS1 = AT91C_BASE_US1; -volatile AT91PS_PIO pPIOA = AT91C_BASE_PIOA; +volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_US1; /* @@ -39,90 +39,53 @@ void usart_close(void) { } */ -static uint8_t outbuf[sizeof(UsbCommand)]; -//static uint8_t inbuf[sizeof(UsbCommand)]; - +static uint8_t us_outbuf[sizeof(UsbCommand)]; /// Reads data from an USART peripheral /// \param data Pointer to the buffer where the received data will be stored. /// \param len Size of the data buffer (in bytes). -inline int usart_readbuffer(uint8_t *data, size_t len) { +inline int16_t usart_readbuffer(uint8_t *data, size_t len) { - pUS1->US_PTSR = AT91C_PDC_TXTEN; - pUS1->US_PTCR = AT91C_PDC_TXTEN; - // Check if the first PDC bank is free if (!(pUS1->US_RCR)) { pUS1->US_RPR = (uint32_t)data; pUS1->US_RCR = len; + + pUS1->US_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTDIS; return 2; } // Check if the second PDC bank is free else if (!(pUS1->US_RNCR)) { pUS1->US_RNPR = (uint32_t)data; pUS1->US_RNCR = len; + + pUS1->US_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTDIS; return 1; } else { return 0; } - - /* - pPDC->PDC_PTSR = AT91C_PDC_RXTEN; - pPDC->PDC_PTCR = AT91C_PDC_RXTEN; - - //check if data is available - if (pPDC->PDC_RCR != 0) return -1; - - memcpy(data, inbuf, len); - - //start next transfer - pPDC->PDC_RNPR = (uint32_t)inbuf; - pPDC->PDC_RNCR = sizeof(inbuf); - - return sizeof(inbuf); - */ } -/* -int16_t usart_writebuffer(uint8_t *data, size_t len) { -// pUS1->US_PTSR = AT91C_PDC_TXTEN; - pUS1->US_PTCR = AT91C_PDC_TXTEN; - - // if buffer is sent - if (pUS1->US_TCR != 0) return -1; - - memcpy(outbuf, data, len); - //start next transfer - pUS1->US_TNPR = (uint32_t)outbuf; - pUS1->US_TNCR = sizeof(outbuf); - - return sizeof(outbuf); -} -*/ - -// works. -// transfer to client +// transfer from device to client inline int16_t usart_writebuffer(uint8_t *data, size_t len) { - pUS1->US_PTSR = AT91C_PDC_TXTEN; - pUS1->US_PTCR = AT91C_PDC_TXTEN; - // Check if the first PDC bank is free if (!(pUS1->US_TCR)) { - - memcpy(outbuf, data, len); - - pUS1->US_TPR = (uint32_t)outbuf; - pUS1->US_TCR = sizeof(outbuf); + memcpy(us_outbuf, data, len); + pUS1->US_TPR = (uint32_t)us_outbuf; + pUS1->US_TCR = sizeof(us_outbuf); + + pUS1->US_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTDIS; return 2; } // Check if the second PDC bank is free else if (!(pUS1->US_TNCR)) { - memcpy(outbuf, data, len); - - pUS1->US_TNPR = (uint32_t)outbuf; - pUS1->US_TNCR = sizeof(outbuf); + memcpy(us_outbuf, data, len); + pUS1->US_TNPR = (uint32_t)us_outbuf; + pUS1->US_TNCR = sizeof(us_outbuf); + + pUS1->US_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTDIS; return 1; } else { return 0; @@ -132,19 +95,20 @@ inline int16_t usart_writebuffer(uint8_t *data, size_t len) { void usart_init(void) { // disable & reset receiver / transmitter for configuration - pUS1->US_CR = (AT91C_US_RSTRX | AT91C_US_RSTTX); + pUS1->US_CR = (AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS); //enable the USART1 Peripheral clock AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US1); // disable PIO control of receive / transmit pins - pPIOA->PIO_PDR |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); + pPIO->PIO_PDR |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); // enable peripheral mode A on receive / transmit pins - pPIOA->PIO_ASR |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); + pPIO->PIO_ASR |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); + pPIO->PIO_BSR = 0; // enable pull-up on receive / transmit pins (see 31.5.1 I/O Lines) - pPIOA->PIO_PPUER |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); + pPIO->PIO_PPUER |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); // set mode pUS1->US_MR = AT91C_US_USMODE_NORMAL | // normal mode @@ -154,8 +118,19 @@ void usart_init(void) { AT91C_US_NBSTOP_1_BIT | // 1 stop bit AT91C_US_CHMODE_NORMAL; // channel mode: normal + // all interrupts disabled + pUS1->US_IDR = 0xFFFF; + + // iceman, setting 115200 doesn't work. Only speed I got to work is 9600. + // something fishy with the AT91SAM7S512 USART.. Or I missed something + // For a nice detailed sample, interrupt driven but still relevant. + // See https://www.sparkfun.com/datasheets/DevTools/SAM7/at91sam7%20serial%20communications.pdf + // set baudrate to 115200 - pUS1->US_BRGR = (48UL*1000*1000) / (115200*16); + // 115200 * 16 == 1843200 + // + //pUS1->US_BRGR = (48UL*1000*1000) / (9600*16); + pUS1->US_BRGR = 48054841 / (9600 << 4); // Write the Timeguard Register pUS1->US_TTGR = 0; @@ -163,23 +138,6 @@ void usart_init(void) { pUS1->US_FIDI = 0; pUS1->US_IF = 0; - /* - //Empty PDC - pUS1->US_RNPR = (uint32_t)(char *)0; - pUS1->US_RNCR = 0; - pUS1->US_RPR = (uint32_t)(char *)0; - pUS1->US_RCR = 0; - - pUS1->US_TNPR = (uint32_t)(char *)0; - pUS1->US_TNCR = 0; - pUS1->US_TPR = (uint32_t)(char *)0; - pUS1->US_TCR = 0; - */ - - //pUS1->US_PTCR = (AT91C_PDC_RXTEN | AT91C_PDC_TXTEN); - //pUS1->US_PTSR = (AT91C_PDC_RXTEN | AT91C_PDC_TXTEN); - // re-enable receiver / transmitter pUS1->US_CR = (AT91C_US_RXEN | AT91C_US_TXEN); - } \ No newline at end of file diff --git a/common/usart.h b/common/usart.h index 271a24ba4..7e8d3eb7b 100644 --- a/common/usart.h +++ b/common/usart.h @@ -7,6 +7,6 @@ void usart_init(void); void usart_close(void); -int usart_readbuffer(uint8_t *data, size_t len); +int16_t usart_readbuffer(uint8_t *data, size_t len); int16_t usart_writebuffer(uint8_t *data, size_t len); #endif diff --git a/uart/uart_posix.c b/uart/uart_posix.c index 20a577ded..b587d6546 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -118,8 +118,12 @@ serial_port uart_open(const char* pcPortName) tcflush(sp->fd, TCIOFLUSH); #ifdef WITH_FPC - uart_set_speed(sp, 115200); + if ( uart_set_speed(sp, 115200) ) { printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n"); + } else { + uart_set_speed(sp, 9600); + printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n"); + } #else // set speed, works for UBUNTU 14.04 bool success = uart_set_speed(sp, 460800); diff --git a/uart/uart_win32.c b/uart/uart_win32.c index eef350cda..11c90f15f 100644 --- a/uart/uart_win32.c +++ b/uart/uart_win32.c @@ -86,12 +86,20 @@ serial_port uart_open(const char* pcPortName) { } // all zero's configure: no timeout for read/write used. // took settings from libnfc/buses/uart.c +#ifdef WITH_FPC + sp->ct.ReadIntervalTimeout = 1000; + sp->ct.ReadTotalTimeoutMultiplier = 0; + sp->ct.ReadTotalTimeoutConstant = 1500; + sp->ct.WriteTotalTimeoutMultiplier = 1000; + sp->ct.WriteTotalTimeoutConstant = 0; +#else sp->ct.ReadIntervalTimeout = 30; sp->ct.ReadTotalTimeoutMultiplier = 0; sp->ct.ReadTotalTimeoutConstant = 30; sp->ct.WriteTotalTimeoutMultiplier = 30; sp->ct.WriteTotalTimeoutConstant = 0; - +#endif + if (!SetCommTimeouts(sp->hPort, &sp->ct)) { uart_close(sp); printf("[!] UART error while setting comm time outs\n"); @@ -101,7 +109,12 @@ serial_port uart_open(const char* pcPortName) { PurgeComm(sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR); #ifdef WITH_FPC - uart_set_speed(sp, 115200); + if ( uart_set_speed(sp, 115200) ) { + printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n"); + } else { + uart_set_speed(sp, 9600); + printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n"); + } #else bool success = uart_set_speed(sp, 460800); if (success) { From e3aebd7985dea1f9337450ccc03c3ea94fc1f08f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 20 Nov 2018 16:25:19 +0200 Subject: [PATCH 0209/1938] get card data --- client/cmdhf14a.c | 40 ++++++++++++++++++++++++++++++++++++++++ client/cmdhf14a.h | 1 + 2 files changed, 41 insertions(+) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 56eadc9cc..77e9473a1 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -190,6 +190,45 @@ int CmdHF14AList(const char *Cmd) { return 0; } +int Hf14443_4aGetCardData(iso14a_card_select_t * card) { + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}}; + SendCommand(&c); + + UsbCommand resp; + WaitForResponse(CMD_ACK,&resp); + + memcpy(card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); + + uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision + + if(select_status == 0) { + PrintAndLog("E->iso14443a card select failed"); + return 1; + } + + if(select_status == 2) { + PrintAndLog("E->Card doesn't support iso14443-4 mode"); + return 1; + } + + if(select_status == 3) { + PrintAndLog("E->Card doesn't support standard iso14443-3 anticollision"); + PrintAndLog("\tATQA : %02x %02x", card->atqa[1], card->atqa[0]); + return 1; + } + + PrintAndLog(" UID: %s", sprint_hex(card->uid, card->uidlen)); + PrintAndLog("ATQA: %02x %02x", card->atqa[1], card->atqa[0]); + PrintAndLog(" SAK: %02x [%" PRIu64 "]", card->sak, resp.arg[0]); + if(card->ats_len < 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes + PrintAndLog("E-> Error ATS length(%d) : %s", card->ats_len, sprint_hex(card->ats, card->ats_len)); + return 1; + } + PrintAndLog(" ATS: %s", sprint_hex(card->ats, card->ats_len)); + + return 0; +} + int CmdHF14AReader(const char *Cmd) { uint32_t cm = ISO14A_CONNECT; @@ -875,6 +914,7 @@ int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool lea return 0; } +// ISO14443-4. 7. Half-duplex block transmission protocol int CmdHF14AAPDU(const char *cmd) { uint8_t data[USB_CMD_DATA_SIZE]; int datalen = 0; diff --git a/client/cmdhf14a.h b/client/cmdhf14a.h index 310a2f7d5..723c31100 100644 --- a/client/cmdhf14a.h +++ b/client/cmdhf14a.h @@ -50,6 +50,7 @@ extern int CmdHF14ACUIDs(const char *Cmd); extern int CmdHF14AAntiFuzz(const char *cmd); extern char* getTagInfo(uint8_t uid); +extern int Hf14443_4aGetCardData(iso14a_card_select_t * card); extern int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); extern int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); From b1091c486b803347ea2ef84879e55c00939311c2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 20 Nov 2018 16:25:54 +0200 Subject: [PATCH 0210/1938] emv_pki --- client/emv/emv_pki.c | 14 +++++++++++--- client/emv/emv_pki.h | 2 ++ 2 files changed, 13 insertions(+), 3 deletions(-) diff --git a/client/emv/emv_pki.c b/client/emv/emv_pki.c index 81918ecb9..be4dfa0a7 100644 --- a/client/emv/emv_pki.c +++ b/client/emv/emv_pki.c @@ -27,6 +27,11 @@ #include #include +static bool strictExecution = true; +void PKISetStrictExecution(bool se) { + strictExecution = se; +} + static const unsigned char empty_tlv_value[] = {}; static const struct tlv empty_tlv = {.tag = 0x0, .len = 0, .value = empty_tlv_value}; @@ -108,9 +113,12 @@ static unsigned char *emv_pki_decode_message(const struct emv_pk *enc_pk, printf("ERROR: Calculated wrong hash\n"); printf("decoded: %s\n",sprint_hex(data + data_len - 1 - hash_len, hash_len)); printf("calculated: %s\n",sprint_hex(crypto_hash_read(ch), hash_len)); - crypto_hash_close(ch); - free(data); - return NULL; + + if (strictExecution) { + crypto_hash_close(ch); + free(data); + return NULL; + } } crypto_hash_close(ch); diff --git a/client/emv/emv_pki.h b/client/emv/emv_pki.h index e37e3c7d2..6fa7b12e9 100644 --- a/client/emv/emv_pki.h +++ b/client/emv/emv_pki.h @@ -21,6 +21,8 @@ #include +extern void PKISetStrictExecution(bool se); + struct emv_pk *emv_pki_recover_issuer_cert(const struct emv_pk *pk, struct tlvdb *db); struct emv_pk *emv_pki_recover_icc_cert(const struct emv_pk *pk, struct tlvdb *db, const struct tlv *sda_tlv); struct emv_pk *emv_pki_recover_icc_pe_cert(const struct emv_pk *pk, struct tlvdb *db); From fb14d665dd90fbe1c58f909262b712c51c5111e0 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 20 Nov 2018 16:26:35 +0200 Subject: [PATCH 0211/1938] emvcore --- client/emv/emvcore.c | 84 +++++++++++++++++++++++++++++++++++++++++--- client/emv/emvcore.h | 4 +++ 2 files changed, 83 insertions(+), 5 deletions(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index b7d7df923..f2acda25c 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -9,6 +9,8 @@ //----------------------------------------------------------------------------- #include "emvcore.h" +#include "emvjson.h" +#include "util_posix.h" // Got from here. Thanks) // https://eftlab.co.uk/index.php/site-map/knowledge-base/211-emv-aid-rid-pix @@ -18,6 +20,13 @@ static const char *PSElist [] = { }; //static const size_t PSElistLen = sizeof(PSElist)/sizeof(char*); +char *TransactionTypeStr[] = { + "MSD", + "VSDC", + "qVCDCMCHIP", + "CDA" +}; + typedef struct { enum CardPSVendor vendor; const char* aid; @@ -257,9 +266,14 @@ int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool Includ *sw = isw; if (isw != 0x9000) { - if (APDULogging) - PrintAndLogEx(WARNING, "APDU(%02x%02x) ERROR: [%4X] %s", apdu.CLA, apdu.INS, isw, GetAPDUCodeDescription(*sw >> 8, *sw & 0xff)); - return 5; + if (APDULogging) { + if (*sw >> 8 == 0x61) { + PrintAndLogEx(ERR, "APDU chaining len:%02x -->", *sw & 0xff); + } else { + PrintAndLogEx(ERR, "APDU(%02x%02x) ERROR: [%4X] %s", apdu.CLA, apdu.INS, isw, GetAPDUCodeDescription(*sw >> 8, *sw & 0xff)); + return 5; + } + } } // add to tlv tree @@ -527,7 +541,7 @@ int trSDA(struct tlvdb *tlv) { if (!sda_tlv || sda_tlv->len < 1) { emv_pk_free(issuer_pk); emv_pk_free(pk); - PrintAndLogEx(WARNING, "Error: Can't find input list for Offline Data Authentication. Exit."); + PrintAndLogEx(WARNING, "Can't find input list for Offline Data Authentication. Exit."); return 3; } @@ -539,7 +553,7 @@ int trSDA(struct tlvdb *tlv) { } else { emv_pk_free(issuer_pk); emv_pk_free(pk); - PrintAndLogEx(WARNING, "Error: SSAD verify error"); + PrintAndLogEx(WARNING, "SSAD verify error"); return 4; } @@ -851,3 +865,63 @@ int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_tlv, st emv_pk_free(icc_pk); return 0; } + +int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root) { + + struct emv_pk *pk = get_ca_pk(tlvRoot); + if (!pk) { + PrintAndLog("ERROR: Key not found. Exit."); + return 1; + } + + struct emv_pk *issuer_pk = emv_pki_recover_issuer_cert(pk, tlvRoot); + if (!issuer_pk) { + emv_pk_free(pk); + PrintAndLog("WARNING: Issuer certificate not found. Exit."); + return 2; + } + PrintAndLog("Issuer PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx", + issuer_pk->rid[0], + issuer_pk->rid[1], + issuer_pk->rid[2], + issuer_pk->rid[3], + issuer_pk->rid[4], + issuer_pk->index, + issuer_pk->serial[0], + issuer_pk->serial[1], + issuer_pk->serial[2] + ); + + JsonSaveBufAsHex(root, "$.ApplicationData.RID", issuer_pk->rid, 5); + + char *issuer_pk_c = emv_pk_dump_pk(issuer_pk); + JsonSaveStr(root, "$.ApplicationData.IssuerPublicKeyDec", issuer_pk_c); + JsonSaveBufAsHex(root, "$.ApplicationData.IssuerPublicKeyModulus", issuer_pk->modulus, issuer_pk->mlen); + free(issuer_pk_c); + + struct emv_pk *icc_pk = emv_pki_recover_icc_cert(issuer_pk, tlvRoot, NULL); + if (!icc_pk) { + emv_pk_free(pk); + emv_pk_free(issuer_pk); + PrintAndLog("WARNING: ICC certificate not found. Exit."); + return 2; + } + printf("ICC PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx\n", + icc_pk->rid[0], + icc_pk->rid[1], + icc_pk->rid[2], + icc_pk->rid[3], + icc_pk->rid[4], + icc_pk->index, + icc_pk->serial[0], + icc_pk->serial[1], + icc_pk->serial[2] + ); + + char *icc_pk_c = emv_pk_dump_pk(icc_pk); + JsonSaveStr(root, "$.ApplicationData.ICCPublicKeyDec", icc_pk_c); + JsonSaveBufAsHex(root, "$.ApplicationData.ICCPublicKeyModulus", icc_pk->modulus, icc_pk->mlen); + free(issuer_pk_c); + + return 0; +} diff --git a/client/emv/emvcore.h b/client/emv/emvcore.h index 1e39f696c..5fb6f202c 100644 --- a/client/emv/emvcore.h +++ b/client/emv/emvcore.h @@ -16,6 +16,7 @@ #include #include #include +#include #include "util.h" #include "common.h" #include "ui.h" @@ -37,6 +38,7 @@ enum TransactionType { TT_QVSDCMCHIP, TT_CDA, }; +extern char *TransactionTypeStr[]; typedef struct { uint8_t CLA; @@ -93,6 +95,8 @@ extern int trSDA(struct tlvdb *tlv); extern int trDDA(bool decodeTLV, struct tlvdb *tlv); extern int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_tlv, struct tlv *ac_data_tlv); +extern int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root); + #endif From 6d896ca6039d102d2b2dfc4314297327d4580b19 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 20 Nov 2018 16:26:54 +0200 Subject: [PATCH 0212/1938] cmdemv merge --- client/emv/cmdemv.c | 1226 ++++++++++++++++++++++++++++++++----------- 1 file changed, 917 insertions(+), 309 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 5ff31770d..21691d0b7 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -8,84 +8,65 @@ // EMV commands //----------------------------------------------------------------------------- +#include +#include "mifare.h" #include "cmdemv.h" +#include "emvjson.h" +#include "emv_pki.h" #include "test/cryptotest.h" +#include "cliparser/cliparser.h" +#include static int CmdHelp(const char *Cmd); -int usage_emv_select(void) { - PrintAndLogEx(NORMAL, "Executes select applet command:\n"); - PrintAndLogEx(NORMAL, "Usage: hf emv select [-s][-k][-a][-t] \n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " -s : select card"); - PrintAndLogEx(NORMAL, " -k : keep field for next command"); - PrintAndLogEx(NORMAL, " -a : show APDU reqests and responses\n"); - PrintAndLogEx(NORMAL, " -t : TLV decode results\n"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv select -s a00000000101 -> select card, select applet"); - PrintAndLogEx(NORMAL, " hf emv select -s -t a00000000101 -> select card, select applet, show result in TLV"); - return 0; +#define TLV_ADD(tag, value)( tlvdb_change_or_add_node(tlvRoot, tag, sizeof(value) - 1, (const unsigned char *)value) ) +void ParamLoadDefaults(struct tlvdb *tlvRoot) { + //9F02:(Amount, authorized (Numeric)) len:6 + TLV_ADD(0x9F02, "\x00\x00\x00\x00\x01\x00"); + //9F1A:(Terminal Country Code) len:2 + TLV_ADD(0x9F1A, "ru"); + //5F2A:(Transaction Currency Code) len:2 + // USD 840, EUR 978, RUR 810, RUB 643, RUR 810(old), UAH 980, AZN 031, n/a 999 + TLV_ADD(0x5F2A, "\x09\x80"); + //9A:(Transaction Date) len:3 + TLV_ADD(0x9A, "\x00\x00\x00"); + //9C:(Transaction Type) len:1 | 00 => Goods and service #01 => Cash + TLV_ADD(0x9C, "\x00"); + // 9F37 Unpredictable Number len:4 + TLV_ADD(0x9F37, "\x01\x02\x03\x04"); + // 9F6A Unpredictable Number (MSD for UDOL) len:4 + TLV_ADD(0x9F6A, "\x01\x02\x03\x04"); + //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4 + TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC } int CmdHFEMVSelect(const char *cmd) { uint8_t data[APDU_AID_LEN] = {0}; int datalen = 0; - bool activateField = false; - bool leaveSignalON = false; - bool decodeTLV = false; - if (strlen(cmd) < 1) - return usage_emv_select(); - - SetAPDULogging(false); - - int cmdp = 0; - while(param_getchar(cmd, cmdp) != 0x00) { - char c = param_getchar(cmd, cmdp); - if ((c == '-') && (param_getlength(cmd, cmdp) == 2)) - switch (param_getchar_indx(cmd, 1, cmdp)) { - case 'h': - case 'H': - return usage_emv_select(); - case 's': - case 'S': - activateField = true; - break; - case 'k': - case 'K': - leaveSignalON = true; - break; - case 'a': - case 'A': - SetAPDULogging(true); - break; - case 't': - case 'T': - decodeTLV = true; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar_indx(cmd, 1, cmdp)); - return 1; - } + CLIParserInit("hf emv select", + "Executes select applet command", + "Usage:\n\thf emv select -s a00000000101 -> select card, select applet\n\thf emv select -st a00000000101 -> select card, select applet, show result in TLV\n"); - if (isxdigit(c)) { - switch(param_gethex_to_eol(cmd, cmdp, data, sizeof(data), &datalen)) { - case 1: - PrintAndLogEx(WARNING, "Invalid HEX value."); - return 1; - case 2: - PrintAndLogEx(WARNING, "AID too large."); - return 1; - case 3: - PrintAndLogEx(WARNING, "Hex must have even number of digits."); - return 1; - } - - // we get all the hex to end of line with spaces - break; - } - cmdp++; - } + void* argtable[] = { + arg_param_begin, + arg_lit0("sS", "select", "activate field and select card"), + arg_lit0("kK", "keep", "keep field for next command"), + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_lit0("tT", "tlv", "TLV decode results"), + arg_strx0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + bool activateField = arg_get_lit(1); + bool leaveSignalON = arg_get_lit(2); + bool APDULogging = arg_get_lit(3); + bool decodeTLV = arg_get_lit(4); + CLIGetHexWithReturn(5, data, &datalen); + CLIParserFree(); + + SetAPDULogging(APDULogging); // exec uint8_t buf[APDU_RES_LEN] = {0}; @@ -94,7 +75,7 @@ int CmdHFEMVSelect(const char *cmd) { int res = EMVSelect(activateField, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL); if (sw) - PrintAndLogEx(NORMAL, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); if (res) return res; @@ -105,62 +86,30 @@ int CmdHFEMVSelect(const char *cmd) { return 0; } -int usage_emv_search(void) { - PrintAndLogEx(NORMAL, "Tries to select all applets from applet list:\n"); - PrintAndLogEx(NORMAL, "Usage: hf emv search [-s][-k][-a][-t]\n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " -s : select card"); - PrintAndLogEx(NORMAL, " -k : keep field for next command"); - PrintAndLogEx(NORMAL, " -a : show APDU reqests and responses\n"); - PrintAndLogEx(NORMAL, " -t : TLV decode results of selected applets\n"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv search -s -> select card and search"); - PrintAndLogEx(NORMAL, " hf emv search -s -t -> select card, search and show result in TLV"); - return 0; -} - int CmdHFEMVSearch(const char *cmd) { - bool activateField = false; - bool leaveSignalON = false; - bool decodeTLV = false; + CLIParserInit("hf emv search", + "Tries to select all applets from applet list:\n", + "Usage:\n\thf emv search -s -> select card and search\n\thf emv search -st -> select card, search and show result in TLV\n"); - if (strlen(cmd) < 1) - return usage_emv_search(); + void* argtable[] = { + arg_param_begin, + arg_lit0("sS", "select", "activate field and select card"), + arg_lit0("kK", "keep", "keep field ON for next command"), + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_lit0("tT", "tlv", "TLV decode results of selected applets"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); - SetAPDULogging(false); + bool activateField = arg_get_lit(1); + bool leaveSignalON = arg_get_lit(2); + bool APDULogging = arg_get_lit(3); + bool decodeTLV = arg_get_lit(4); + CLIParserFree(); + + SetAPDULogging(APDULogging); - int cmdp = 0; - while(param_getchar(cmd, cmdp) != 0x00) { - char c = param_getchar(cmd, cmdp); - if ((c == '-') && (param_getlength(cmd, cmdp) == 2)) - switch (param_getchar_indx(cmd, 1, cmdp)) { - case 'h': - case 'H': - return usage_emv_search(); - case 's': - case 'S': - activateField = true; - break; - case 'k': - case 'K': - leaveSignalON = true; - break; - case 'a': - case 'A': - SetAPDULogging(true); - break; - case 't': - case 'T': - decodeTLV = true; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar_indx(cmd, 1, cmdp)); - return 1; - } - cmdp++; - } - struct tlvdb *t = NULL; const char *al = "Applets list"; t = tlvdb_fixed(1, strlen(al), (const unsigned char *)al); @@ -170,7 +119,7 @@ int CmdHFEMVSearch(const char *cmd) { return 2; } - PrintAndLogEx(NORMAL, "Search completed."); + PrintAndLog("Search completed."); // print list here if (!decodeTLV) { @@ -182,66 +131,36 @@ int CmdHFEMVSearch(const char *cmd) { return 0; } -int usage_emv_ppse(void) { - PrintAndLogEx(NORMAL, "Executes PSE/PPSE select command. It returns list of applet on the card:\n"); - PrintAndLogEx(NORMAL, "Usage: hf emv pse [-s][-k][-1][-2][-a][-t]\n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " -s : select card"); - PrintAndLogEx(NORMAL, " -k : keep field for next command"); - PrintAndLogEx(NORMAL, " -1 : ppse (1PAY.SYS.DDF01)"); - PrintAndLogEx(NORMAL, " -2 : pse (2PAY.SYS.DDF01)"); - PrintAndLogEx(NORMAL, " -a : show APDU reqests and responses\n"); - PrintAndLogEx(NORMAL, " -t : TLV decode results\n"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv pse -s -1 -> select, get pse"); - PrintAndLogEx(NORMAL, " hf emv pse -s -k -2 -> select, get ppse, keep field"); - PrintAndLogEx(NORMAL, " hf emv pse -s -t -2 -> select, get ppse, show result in TLV"); - return 0; -} - int CmdHFEMVPPSE(const char *cmd) { - uint8_t PSENum = 2; - bool activateField = false; - bool leaveSignalON = false; - bool decodeTLV = false; + CLIParserInit("hf emv pse", + "Executes PSE/PPSE select command. It returns list of applet on the card:\n", + "Usage:\n\thf emv pse -s1 -> select, get pse\n\thf emv pse -st2 -> select, get ppse, show result in TLV\n"); - if (strlen(cmd) < 1) - return usage_emv_ppse(); - - SetAPDULogging(false); + void* argtable[] = { + arg_param_begin, + arg_lit0("sS", "select", "activate field and select card"), + arg_lit0("kK", "keep", "keep field ON for next command"), + arg_lit0("1", "pse", "pse (1PAY.SYS.DDF01) mode"), + arg_lit0("2", "ppse", "ppse (2PAY.SYS.DDF01) mode (default mode)"), + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_lit0("tT", "tlv", "TLV decode results of selected applets"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); - int cmdp = 0; - while(param_getchar(cmd, cmdp) != 0x00) { - char c = param_getchar(cmd, cmdp); - if ((c == '-') && (param_getlength(cmd, cmdp) == 2)) - switch (tolower(param_getchar_indx(cmd, 1, cmdp))) { - case 'h': - return usage_emv_ppse(); - case 's': - activateField = true; - break; - case 'k': - leaveSignalON = true; - break; - case 'a': - SetAPDULogging(true); - break; - case 't': - decodeTLV = true; - break; - case '1': - PSENum = 1; - break; - case '2': - PSENum = 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar_indx(cmd, 1, cmdp)); - return 1; - } - cmdp++; - } + bool activateField = arg_get_lit(1); + bool leaveSignalON = arg_get_lit(2); + uint8_t PSENum = 2; + if (arg_get_lit(3)) + PSENum = 1; + if (arg_get_lit(4)) + PSENum = 2; + bool APDULogging = arg_get_lit(5); + bool decodeTLV = arg_get_lit(6); + CLIParserFree(); + + SetAPDULogging(APDULogging); // exec uint8_t buf[APDU_RES_LEN] = {0}; @@ -250,10 +169,11 @@ int CmdHFEMVPPSE(const char *cmd) { int res = EMVSelectPSE(activateField, leaveSignalON, PSENum, buf, sizeof(buf), &len, &sw); if (sw) - PrintAndLogEx(NORMAL, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); if (res) - return res; + return res; + if (decodeTLV) TLVPrintFromBuffer(buf, len); @@ -261,36 +181,457 @@ int CmdHFEMVPPSE(const char *cmd) { return 0; } -int usage_emv_exec(void) { - PrintAndLogEx(NORMAL, "Executes EMV contactless transaction:\n"); - PrintAndLogEx(NORMAL, "Usage: hf emv exec [-s][-a][-t][-f][-v][-c][-x][-g]\n"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " -s : select card"); - PrintAndLogEx(NORMAL, " -a : show APDU reqests and responses\n"); - PrintAndLogEx(NORMAL, " -t : TLV decode results\n"); - PrintAndLogEx(NORMAL, " -f : force search AID. Search AID instead of execute PPSE.\n"); - PrintAndLogEx(NORMAL, " -v : transaction type - qVSDC or M/Chip.\n"); - PrintAndLogEx(NORMAL, " -c : transaction type - qVSDC or M/Chip plus CDA (SDAD generation).\n"); - PrintAndLogEx(NORMAL, " -x : transaction type - VSDC. For test only. Not a standart behavior.\n"); - PrintAndLogEx(NORMAL, " -g : VISA. generate AC from GPO\n"); - PrintAndLogEx(NORMAL, "By default : transaction type - MSD.\n"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv exec -s -a -t -> execute MSD transaction"); - PrintAndLogEx(NORMAL, " hf emv exec -s -a -t -c -> execute CDA transaction"); +int CmdHFEMVGPO(const char *cmd) { + uint8_t data[APDU_RES_LEN] = {0}; + int datalen = 0; + + CLIParserInit("hf emv gpo", + "Executes Get Processing Options command. It returns data in TLV format (0x77 - format2) or plain format (0x80 - format1).\nNeeds a EMV applet to be selected.", + "Usage:\n\thf emv gpo -k -> execute GPO\n" + "\thf emv gpo -t 01020304 -> execute GPO with 4-byte PDOL data, show result in TLV\n" + "\thf emv gpo -pmt 9F 37 04 -> load params from file, make PDOL data from PDOL, execute GPO with PDOL, show result in TLV\n"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("kK", "keep", "keep field ON for next command"), + arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for PDOLdata making from PDOL and parameters"), + arg_lit0("mM", "make", "make PDOLdata from PDOL (tag 9F38) and parameters (by default uses default parameters)"), + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_lit0("tT", "tlv", "TLV decode results of selected applets"), + arg_strx0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + bool leaveSignalON = arg_get_lit(1); + bool paramsLoadFromFile = arg_get_lit(2); + bool dataMakeFromPDOL = arg_get_lit(3); + bool APDULogging = arg_get_lit(4); + bool decodeTLV = arg_get_lit(5); + CLIGetHexWithReturn(6, data, &datalen); + CLIParserFree(); + + SetAPDULogging(APDULogging); + + // Init TLV tree + const char *alr = "Root terminal TLV tree"; + struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr); + + // calc PDOL + struct tlv *pdol_data_tlv = NULL; + struct tlv data_tlv = { + .tag = 0x83, + .len = datalen, + .value = (uint8_t *)data, + }; + if (dataMakeFromPDOL) { + ParamLoadDefaults(tlvRoot); + + if (paramsLoadFromFile) { + PrintAndLog("Params loading from file..."); + ParamLoadFromJson(tlvRoot); + }; + + pdol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x9f38, datalen, data), tlvRoot, 0x83); + if (!pdol_data_tlv){ + PrintAndLog("ERROR: can't create PDOL TLV."); + tlvdb_free(tlvRoot); + return 4; + } + } else { + if (paramsLoadFromFile) { + PrintAndLog("WARNING: don't need to load parameters. Sending plain PDOL data..."); + } + pdol_data_tlv = &data_tlv; + } + + size_t pdol_data_tlv_data_len = 0; + unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len); + if (!pdol_data_tlv_data) { + PrintAndLog("ERROR: can't create PDOL data."); + tlvdb_free(tlvRoot); + return 4; + } + PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); + + // exec + uint8_t buf[APDU_RES_LEN] = {0}; + size_t len = 0; + uint16_t sw = 0; + int res = EMVGPO(leaveSignalON, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot); + + if (pdol_data_tlv != &data_tlv) + free(pdol_data_tlv); + tlvdb_free(tlvRoot); + + if (sw) + PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + + if (res) + return res; + + if (decodeTLV) + TLVPrintFromBuffer(buf, len); + return 0; } -#define TLV_ADD(tag, value)( tlvdb_add(tlvRoot, tlvdb_fixed(tag, sizeof(value) - 1, (const unsigned char *)value)) ) +int CmdHFEMVReadRecord(const char *cmd) { + uint8_t data[APDU_RES_LEN] = {0}; + int datalen = 0; + + CLIParserInit("hf emv readrec", + "Executes Read Record command. It returns data in TLV format.\nNeeds a bank applet to be selected and sometimes needs GPO to be executed.", + "Usage:\n\thf emv readrec -k 0101 -> read file SFI=01, SFIrec=01\n\thf emv readrec -kt 0201-> read file 0201 and show result in TLV\n"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("kK", "keep", "keep field ON for next command"), + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_lit0("tT", "tlv", "TLV decode results of selected applets"), + arg_strx1(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + bool leaveSignalON = arg_get_lit(1); + bool APDULogging = arg_get_lit(2); + bool decodeTLV = arg_get_lit(3); + CLIGetHexWithReturn(4, data, &datalen); + CLIParserFree(); + + if (datalen != 2) { + PrintAndLog("ERROR: Command needs to have 2 bytes of data"); + return 1; + } + + SetAPDULogging(APDULogging); + + // exec + uint8_t buf[APDU_RES_LEN] = {0}; + size_t len = 0; + uint16_t sw = 0; + int res = EMVReadRecord(leaveSignalON, data[0], data[1], buf, sizeof(buf), &len, &sw, NULL); + + if (sw) + PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + + if (res) + return res; + + + if (decodeTLV) + TLVPrintFromBuffer(buf, len); + + return 0; +} + +int CmdHFEMVAC(const char *cmd) { + uint8_t data[APDU_RES_LEN] = {0}; + int datalen = 0; + + CLIParserInit("hf emv genac", + "Generate Application Cryptogram command. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.", + "Usage:\n\thf emv genac -k 0102 -> generate AC with 2-byte CDOLdata and keep field ON after command\n" + "\thf emv genac -t 01020304 -> generate AC with 4-byte CDOL data, show result in TLV\n" + "\thf emv genac -Daac 01020304 -> generate AC with 4-byte CDOL data and terminal decision 'declined'\n" + "\thf emv genac -pmt 9F 37 04 -> load params from file, make CDOL data from CDOL, generate AC with CDOL, show result in TLV"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("kK", "keep", "keep field ON for next command"), + arg_lit0("cC", "cda", "executes CDA transaction. Needs to get SDAD in results."), + arg_str0("dD", "decision", "", "Terminal decision. aac - declined, tc - approved, arqc - online authorisation requested"), + arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for CDOLdata making from CDOL and parameters"), + arg_lit0("mM", "make", "make CDOLdata from CDOL (tag 8C and 8D) and parameters (by default uses default parameters)"), + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_lit0("tT", "tlv", "TLV decode results of selected applets"), + arg_strx1(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, false); + + bool leaveSignalON = arg_get_lit(1); + bool trTypeCDA = arg_get_lit(2); + uint8_t termDecision = 0xff; + if (arg_get_str_len(3)) { + if (!strncmp(arg_get_str(3)->sval[0], "aac", 4)) + termDecision = EMVAC_AAC; + if (!strncmp(arg_get_str(3)->sval[0], "tc", 4)) + termDecision = EMVAC_TC; + if (!strncmp(arg_get_str(3)->sval[0], "arqc", 4)) + termDecision = EMVAC_ARQC; + + if (termDecision == 0xff) { + PrintAndLog("ERROR: can't find terminal decision '%s'", arg_get_str(3)->sval[0]); + return 1; + } + } else { + termDecision = EMVAC_TC; + } + if (trTypeCDA) + termDecision = termDecision | EMVAC_CDAREQ; + bool paramsLoadFromFile = arg_get_lit(4); + bool dataMakeFromCDOL = arg_get_lit(5); + bool APDULogging = arg_get_lit(6); + bool decodeTLV = arg_get_lit(7); + CLIGetHexWithReturn(8, data, &datalen); + CLIParserFree(); + + SetAPDULogging(APDULogging); + + // Init TLV tree + const char *alr = "Root terminal TLV tree"; + struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr); + + // calc CDOL + struct tlv *cdol_data_tlv = NULL; + struct tlv data_tlv = { + .tag = 0x01, + .len = datalen, + .value = (uint8_t *)data, + }; + + if (dataMakeFromCDOL) { + ParamLoadDefaults(tlvRoot); + + if (paramsLoadFromFile) { + PrintAndLog("Params loading from file..."); + ParamLoadFromJson(tlvRoot); + }; + + cdol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x8c, datalen, data), tlvRoot, 0x01); // 0x01 - dummy tag + if (!cdol_data_tlv){ + PrintAndLog("ERROR: can't create CDOL TLV."); + tlvdb_free(tlvRoot); + return 4; + } + } else { + if (paramsLoadFromFile) { + PrintAndLog("WARNING: don't need to load parameters. Sending plain CDOL data..."); + } + cdol_data_tlv = &data_tlv; + } + + PrintAndLog("CDOL data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len)); + + // exec + uint8_t buf[APDU_RES_LEN] = {0}; + size_t len = 0; + uint16_t sw = 0; + int res = EMVAC(leaveSignalON, termDecision, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot); + + if (cdol_data_tlv != &data_tlv) + free(cdol_data_tlv); + tlvdb_free(tlvRoot); + + if (sw) + PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + + if (res) + return res; + + if (decodeTLV) + TLVPrintFromBuffer(buf, len); + + return 0; +} + +int CmdHFEMVGenerateChallenge(const char *cmd) { + + CLIParserInit("hf emv challenge", + "Executes Generate Challenge command. It returns 4 or 8-byte random number from card.\nNeeds a EMV applet to be selected and GPO to be executed.", + "Usage:\n\thf emv challenge -> get challenge\n\thf emv challenge -k -> get challenge, keep fileld ON\n"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("kK", "keep", "keep field ON for next command"), + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + bool leaveSignalON = arg_get_lit(1); + bool APDULogging = arg_get_lit(2); + CLIParserFree(); + + SetAPDULogging(APDULogging); + + // exec + uint8_t buf[APDU_RES_LEN] = {0}; + size_t len = 0; + uint16_t sw = 0; + int res = EMVGenerateChallenge(leaveSignalON, buf, sizeof(buf), &len, &sw, NULL); + + if (sw) + PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + + if (res) + return res; + + PrintAndLog("Challenge: %s", sprint_hex(buf, len)); + + if (len != 4 && len != 8) + PrintAndLog("WARNING: length of challenge must be 4 or 8, but it %d", len); + + return 0; +} + +int CmdHFEMVInternalAuthenticate(const char *cmd) { + uint8_t data[APDU_RES_LEN] = {0}; + int datalen = 0; + + CLIParserInit("hf emv intauth", + "Generate Internal Authenticate command. Usually needs 4-byte random number. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.", + "Usage:\n\thf emv intauth -k 01020304 -> execute Internal Authenticate with 4-byte DDOLdata and keep field ON after command\n" + "\thf emv intauth -t 01020304 -> execute Internal Authenticate with 4-byte DDOL data, show result in TLV\n" + "\thf emv intauth -pmt 9F 37 04 -> load params from file, make DDOL data from DDOL, Internal Authenticate with DDOL, show result in TLV"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("kK", "keep", "keep field ON for next command"), + arg_lit0("pP", "params", "load parameters from `emv/defparams.json` file for DDOLdata making from DDOL and parameters"), + arg_lit0("mM", "make", "make DDOLdata from DDOL (tag 9F49) and parameters (by default uses default parameters)"), + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_lit0("tT", "tlv", "TLV decode results of selected applets"), + arg_strx1(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, false); + + bool leaveSignalON = arg_get_lit(1); + bool paramsLoadFromFile = arg_get_lit(2); + bool dataMakeFromDDOL = arg_get_lit(3); + bool APDULogging = arg_get_lit(4); + bool decodeTLV = arg_get_lit(5); + CLIGetHexWithReturn(6, data, &datalen); + CLIParserFree(); + + SetAPDULogging(APDULogging); + + // Init TLV tree + const char *alr = "Root terminal TLV tree"; + struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr); + + // calc DDOL + struct tlv *ddol_data_tlv = NULL; + struct tlv data_tlv = { + .tag = 0x01, + .len = datalen, + .value = (uint8_t *)data, + }; + + if (dataMakeFromDDOL) { + ParamLoadDefaults(tlvRoot); + + if (paramsLoadFromFile) { + PrintAndLog("Params loading from file..."); + ParamLoadFromJson(tlvRoot); + }; + + ddol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x9f49, datalen, data), tlvRoot, 0x01); // 0x01 - dummy tag + if (!ddol_data_tlv){ + PrintAndLog("ERROR: can't create DDOL TLV."); + tlvdb_free(tlvRoot); + return 4; + } + } else { + if (paramsLoadFromFile) { + PrintAndLog("WARNING: don't need to load parameters. Sending plain DDOL data..."); + } + ddol_data_tlv = &data_tlv; + } + + PrintAndLog("DDOL data[%d]: %s", ddol_data_tlv->len, sprint_hex(ddol_data_tlv->value, ddol_data_tlv->len)); + + // exec + uint8_t buf[APDU_RES_LEN] = {0}; + size_t len = 0; + uint16_t sw = 0; + int res = EMVInternalAuthenticate(leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL); + + if (ddol_data_tlv != &data_tlv) + free(ddol_data_tlv); + tlvdb_free(tlvRoot); + + if (sw) + PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + + if (res) + return res; + + if (decodeTLV) + TLVPrintFromBuffer(buf, len); + + return 0; +} + #define dreturn(n) {free(pdol_data_tlv);tlvdb_free(tlvSelect);tlvdb_free(tlvRoot);DropField();return n;} -int CmdHFEMVExec(const char *cmd) { - bool activateField = false; - bool showAPDU = false; - bool decodeTLV = false; - bool forceSearch = false; - enum TransactionType TrType = TT_MSD; - bool GenACGPO = false; +void InitTransactionParameters(struct tlvdb *tlvRoot, bool paramLoadJSON, enum TransactionType TrType, bool GenACGPO) { + + ParamLoadDefaults(tlvRoot); + if (paramLoadJSON) { + PrintAndLog("* * Transaction parameters loading from JSON..."); + ParamLoadFromJson(tlvRoot); + } + + //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4 + char *qVSDC = "\x26\x00\x00\x00"; + if (GenACGPO) { + qVSDC = "\x26\x80\x00\x00"; + } + switch(TrType) { + case TT_MSD: + TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD + break; + // not standard for contactless. just for test. + case TT_VSDC: + TLV_ADD(0x9F66, "\x46\x00\x00\x00"); // VSDC + break; + case TT_QVSDCMCHIP: + TLV_ADD(0x9F66, qVSDC); // qVSDC + break; + case TT_CDA: + TLV_ADD(0x9F66, qVSDC); // qVSDC (VISA CDA not enabled) + break; + default: + break; + } +} + +void ProcessGPOResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, bool decodeTLV) { + if (buf[0] == 0x80) { + if (decodeTLV){ + PrintAndLog("GPO response format1:"); + TLVPrintFromBuffer(buf, len); + } + + if (len < 4 || (len - 4) % 4) { + PrintAndLog("ERROR: GPO response format1 parsing error. length=%d", len); + } else { + // AIP + struct tlvdb * f1AIP = tlvdb_fixed(0x82, 2, buf + 2); + tlvdb_add(tlvRoot, f1AIP); + if (decodeTLV){ + PrintAndLog("\n* * Decode response format 1 (0x80) AIP and AFL:"); + TLVPrintFromTLV(f1AIP); + } + + // AFL + struct tlvdb * f1AFL = tlvdb_fixed(0x94, len - 4, buf + 2 + 2); + tlvdb_add(tlvRoot, f1AFL); + if (decodeTLV) + TLVPrintFromTLV(f1AFL); + } + } else { + if (decodeTLV) + TLVPrintFromBuffer(buf, len); + } +} + +int CmdHFEMVExec(const char *cmd) { uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; @@ -304,46 +645,46 @@ int CmdHFEMVExec(const char *cmd) { struct tlvdb *tlvSelect = NULL; struct tlvdb *tlvRoot = NULL; struct tlv *pdol_data_tlv = NULL; - if (strlen(cmd) < 1) - return usage_emv_exec(); + + CLIParserInit("hf emv exec", + "Executes EMV contactless transaction", + "Usage:\n\thf emv exec -sat -> select card, execute MSD transaction, show APDU and TLV\n" + "\thf emv exec -satc -> select card, execute CDA transaction, show APDU and TLV\n"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("sS", "select", "activate field and select card."), + arg_lit0("aA", "apdu", "show APDU reqests and responses."), + arg_lit0("tT", "tlv", "TLV decode results."), + arg_lit0("jJ", "jload", "Load transaction parameters from `emv/defparams.json` file."), + arg_lit0("fF", "forceaid", "Force search AID. Search AID instead of execute PPSE."), + arg_rem("By default:", "Transaction type - MSD"), + arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."), + arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."), + arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."), + arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); - int cmdp = 0; - while(param_getchar(cmd, cmdp) != 0x00) { - char c = param_getchar(cmd, cmdp); - if ((c == '-') && (param_getlength(cmd, cmdp) == 2)) - switch (tolower(param_getchar_indx(cmd, 1, cmdp))) { - case 'h': - return usage_emv_exec(); - case 's': - activateField = true; - break; - case 'a': - showAPDU = true; - break; - case 't': - decodeTLV = true; - break; - case 'f': - forceSearch = true; - break; - case 'x': - TrType = TT_VSDC; - break; - case 'v': + bool activateField = arg_get_lit(1); + bool showAPDU = arg_get_lit(2); + bool decodeTLV = arg_get_lit(3); + bool paramLoadJSON = arg_get_lit(4); + bool forceSearch = arg_get_lit(5); + + enum TransactionType TrType = TT_MSD; + if (arg_get_lit(6)) TrType = TT_QVSDCMCHIP; - break; - case 'c': + if (arg_get_lit(7)) TrType = TT_CDA; - break; - case 'g': - GenACGPO = true; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar_indx(cmd, 1, cmdp)); - return 1; - } - cmdp++; - } + if (arg_get_lit(8)) + TrType = TT_VSDC; + + bool GenACGPO = arg_get_lit(9); + CLIParserFree(); + + SetAPDULogging(showAPDU); // init applets list tree const char *al = "Applets list"; @@ -399,50 +740,10 @@ int CmdHFEMVExec(const char *cmd) { if (decodeTLV) TLVPrintFromBuffer(buf, len); + PrintAndLog("* Selected."); - PrintAndLogEx(NORMAL, "* Selected."); - PrintAndLogEx(NORMAL, "\n* Init transaction parameters."); - - //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4 - char *qVSDC = "\x26\x00\x00\x00"; - if (GenACGPO) { - qVSDC = "\x26\x80\x00\x00"; - } - switch(TrType) { - case TT_MSD: - TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD - break; - // not standard for contactless. just for test. - case TT_VSDC: - TLV_ADD(0x9F66, "\x46\x00\x00\x00"); // VSDC - break; - case TT_QVSDCMCHIP: - TLV_ADD(0x9F66, qVSDC); // qVSDC - break; - case TT_CDA: - TLV_ADD(0x9F66, qVSDC); // qVSDC (VISA CDA not enabled) - break; - default: - TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC - break; - } - - //9F02:(Amount, authorized (Numeric)) len:6 - TLV_ADD(0x9F02, "\x00\x00\x00\x00\x01\x00"); - //9F1A:(Terminal Country Code) len:2 - TLV_ADD(0x9F1A, "ru"); - //5F2A:(Transaction Currency Code) len:2 - // USD 840, EUR 978, RUR 810, RUB 643, RUR 810(old), UAH 980, AZN 031, n/a 999 - TLV_ADD(0x5F2A, "\x09\x80"); - //9A:(Transaction Date) len:3 - TLV_ADD(0x9A, "\x00\x00\x00"); - //9C:(Transaction Type) len:1 | 00 => Goods and service #01 => Cash - TLV_ADD(0x9C, "\x00"); - // 9F37 Unpredictable Number len:4 - TLV_ADD(0x9F37, "\x01\x02\x03\x04"); - // 9F6A Unpredictable Number (MSD for UDOL) len:4 - TLV_ADD(0x9F6A, "\x01\x02\x03\x04"); - + PrintAndLog("\n* Init transaction parameters."); + InitTransactionParameters(tlvRoot, paramLoadJSON, TrType, GenACGPO); TLVPrintFromTLV(tlvRoot); // TODO delete!!! PrintAndLogEx(NORMAL, "\n* Calc PDOL."); @@ -472,33 +773,7 @@ int CmdHFEMVExec(const char *cmd) { } // process response template format 1 [id:80 2b AIP + x4b AFL] and format 2 [id:77 TLV] - if (buf[0] == 0x80) { - if (decodeTLV){ - PrintAndLogEx(NORMAL, "GPO response format1:"); - TLVPrintFromBuffer(buf, len); - } - - if (len < 4 || (len - 4) % 4) { - PrintAndLogEx(WARNING, "Error: GPO response format1 parsing error. length=%d", len); - } else { - // AIP - struct tlvdb * f1AIP = tlvdb_fixed(0x82, 2, buf + 2); - tlvdb_add(tlvRoot, f1AIP); - if (decodeTLV){ - PrintAndLogEx(NORMAL, "\n* * Decode response format 1 (0x80) AIP and AFL:"); - TLVPrintFromTLV(f1AIP); - } - - // AFL - struct tlvdb * f1AFL = tlvdb_fixed(0x94, len - 4, buf + 2 + 2); - tlvdb_add(tlvRoot, f1AFL); - if (decodeTLV) - TLVPrintFromTLV(f1AFL); - } - } else { - if (decodeTLV) - TLVPrintFromBuffer(buf, len); - } + ProcessGPOResponseFormat1(tlvRoot, buf, len, decodeTLV); // extract PAN from track2 { @@ -583,7 +858,7 @@ int CmdHFEMVExec(const char *cmd) { struct tlvdb *oda = tlvdb_fixed(0x21, ODAiListLen, ODAiList); // not a standard tag tlvdb_add(tlvRoot, oda); PrintAndLogEx(NORMAL, "* Input list for Offline Data Authentication added to TLV. len=%d \n", ODAiListLen); - } + } // get AIP const struct tlv *AIPtlv = tlvdb_get(tlvRoot, 0x82, NULL); @@ -796,6 +1071,332 @@ int CmdHFEMVExec(const char *cmd) { return 0; } +int CmdHFEMVScan(const char *cmd) { + uint8_t AID[APDU_AID_LEN] = {0}; + size_t AIDlen = 0; + uint8_t buf[APDU_RES_LEN] = {0}; + size_t len = 0; + uint16_t sw = 0; + int res; + json_t *root; + json_error_t error; + + CLIParserInit("hf emv scan", + "Scan EMV card and save it contents to a file.", + "It executes EMV contactless transaction and saves result to a file which can be used for emulation\n" + "Usage:\n\thf emv scan -at -> scan MSD transaction mode and show APDU and TLV\n" + "\thf emv scan -c -> scan CDA transaction mode\n"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("aA", "apdu", "show APDU reqests and responses."), + arg_lit0("tT", "tlv", "TLV decode results."), + arg_lit0("eE", "extract", "Extract TLV elements and fill Application Data"), + arg_lit0("jJ", "jload", "Load transaction parameters from `emv/defparams.json` file."), + arg_rem("By default:", "Transaction type - MSD"), + arg_lit0("vV", "qvsdc", "Transaction type - qVSDC or M/Chip."), + arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."), + arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."), + arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."), + arg_lit0("mM", "merge", "Merge output file with card's data. (warning: the file may be corrupted!)"), + arg_str1(NULL, NULL, "output.json", "JSON output file name"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + bool showAPDU = arg_get_lit(1); + bool decodeTLV = arg_get_lit(2); + bool extractTLVElements = arg_get_lit(3); + bool paramLoadJSON = arg_get_lit(4); + + enum TransactionType TrType = TT_MSD; + if (arg_get_lit(6)) + TrType = TT_QVSDCMCHIP; + if (arg_get_lit(7)) + TrType = TT_CDA; + if (arg_get_lit(8)) + TrType = TT_VSDC; + + bool GenACGPO = arg_get_lit(9); + bool MergeJSON = arg_get_lit(10); + uint8_t relfname[250] ={0}; + char *crelfname = (char *)relfname; + int relfnamelen = 0; + CLIGetStrWithReturn(11, relfname, &relfnamelen); + CLIParserFree(); + + SetAPDULogging(showAPDU); + + // current path + file name + if (!strstr(crelfname, ".json")) + strcat(crelfname, ".json"); + char fname[strlen(get_my_executable_directory()) + strlen(crelfname) + 1]; + strcpy(fname, get_my_executable_directory()); + strcat(fname, crelfname); + + if (MergeJSON) { + root = json_load_file(fname, 0, &error); + if (!root) { + PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); + return 1; + } + + if (!json_is_object(root)) { + PrintAndLog("ERROR: Invalid json format. root must be an object."); + return 1; + } + } else { + root = json_object(); + } + + // drop field at start + DropField(); + + // iso 14443 select + PrintAndLog("--> GET UID, ATS."); + + iso14a_card_select_t card; + if (Hf14443_4aGetCardData(&card)) { + return 2; + } + + JsonSaveStr(root, "$.File.Created", "proxmark3 `hf emv scan`"); + + JsonSaveStr(root, "$.Card.Communication", "iso14443-4a"); + JsonSaveBufAsHex(root, "$.Card.UID", (uint8_t *)&card.uid, card.uidlen); + JsonSaveHex(root, "$.Card.ATQA", card.atqa[0] + (card.atqa[1] << 2), 2); + JsonSaveHex(root, "$.Card.SAK", card.sak, 0); + JsonSaveBufAsHex(root, "$.Card.ATS", (uint8_t *)card.ats, card.ats_len); + + // init applets list tree + const char *al = "Applets list"; + struct tlvdb *tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al); + + // EMV PPSE + PrintAndLog("--> PPSE."); + res = EMVSelectPSE(true, true, 2, buf, sizeof(buf), &len, &sw); + + if (!res && sw == 0x9000){ + if (decodeTLV) + TLVPrintFromBuffer(buf, len); + + JsonSaveBufAsHex(root, "$.PPSE.AID", (uint8_t *)"2PAY.SYS.DDF01", 14); + + struct tlvdb *fci = tlvdb_parse_multi(buf, len); + if (extractTLVElements) + JsonSaveTLVTree(root, root, "$.PPSE.FCITemplate", fci); + else + JsonSaveTLVTreeElm(root, "$.PPSE.FCITemplate", fci, true, true, false); + JsonSaveTLVValue(root, "$.Application.KernelID", tlvdb_find_full(fci, 0x9f2a)); + tlvdb_free(fci); + } + + res = EMVSearchPSE(false, true, decodeTLV, tlvSelect); + + // check PPSE and select application id + if (!res) { + TLVPrintAIDlistFromSelectTLV(tlvSelect); + } else { + // EMV SEARCH with AID list + SetAPDULogging(false); + PrintAndLog("--> AID search."); + if (EMVSearch(false, true, decodeTLV, tlvSelect)) { + PrintAndLog("E->Can't found any of EMV AID. Exit..."); + tlvdb_free(tlvSelect); + DropField(); + return 3; + } + + // check search and select application id + TLVPrintAIDlistFromSelectTLV(tlvSelect); + } + + // EMV SELECT application + SetAPDULogging(showAPDU); + EMVSelectApplication(tlvSelect, AID, &AIDlen); + + tlvdb_free(tlvSelect); + + if (!AIDlen) { + PrintAndLog("Can't select AID. EMV AID not found. Exit..."); + DropField(); + return 4; + } + + JsonSaveBufAsHex(root, "$.Application.AID", AID, AIDlen); + + // Init TLV tree + const char *alr = "Root terminal TLV tree"; + struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr); + + // EMV SELECT applet + + PrintAndLog("\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen)); + SetAPDULogging(showAPDU); + res = EMVSelect(false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot); + + if (res) { + PrintAndLog("E->Can't select AID (%d). Exit...", res); + tlvdb_free(tlvRoot); + DropField(); + return 5; + } + + if (decodeTLV) + TLVPrintFromBuffer(buf, len); + + // save mode + if (tlvdb_get(tlvRoot, 0x9f38, NULL)) { + JsonSaveStr(root, "$.Application.Mode", TransactionTypeStr[TrType]); + } + + struct tlvdb *fci = tlvdb_parse_multi(buf, len); + if (extractTLVElements) + JsonSaveTLVTree(root, root, "$.Application.FCITemplate", fci); + else + JsonSaveTLVTreeElm(root, "$.Application.FCITemplate", fci, true, true, false); + tlvdb_free(fci); + + // create transaction parameters + PrintAndLog("-->Init transaction parameters."); + InitTransactionParameters(tlvRoot, paramLoadJSON, TrType, GenACGPO); + + PrintAndLog("-->Calc PDOL."); + struct tlv *pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83); + if (!pdol_data_tlv){ + PrintAndLog("E->Can't create PDOL TLV."); + tlvdb_free(tlvRoot); + DropField(); + return 6; + } + + size_t pdol_data_tlv_data_len; + unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len); + if (!pdol_data_tlv_data) { + PrintAndLog("E->Can't create PDOL data."); + tlvdb_free(tlvRoot); + DropField(); + return 6; + } + PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); + + PrintAndLog("-->GPO."); + res = EMVGPO(true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot); + + free(pdol_data_tlv_data); + free(pdol_data_tlv); + + if (res) { + PrintAndLog("GPO error(%d): %4x. Exit...", res, sw); + tlvdb_free(tlvRoot); + DropField(); + return 7; + } + ProcessGPOResponseFormat1(tlvRoot, buf, len, decodeTLV); + + struct tlvdb *gpofci = tlvdb_parse_multi(buf, len); + if (extractTLVElements) + JsonSaveTLVTree(root, root, "$.Application.GPO", gpofci); + else + JsonSaveTLVTreeElm(root, "$.Application.GPO", gpofci, true, true, false); + + JsonSaveTLVValue(root, "$.ApplicationData.AIP", tlvdb_find_full(gpofci, 0x82)); + JsonSaveTLVValue(root, "$.ApplicationData.AFL", tlvdb_find_full(gpofci, 0x94)); + + tlvdb_free(gpofci); + + PrintAndLog("-->Read records from AFL."); + const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL); + + while(AFL && AFL->len) { + if (AFL->len % 4) { + PrintAndLog("E->Wrong AFL length: %d", AFL->len); + break; + } + + json_t *sfijson = json_path_get(root, "$.Application.Records"); + if (!sfijson) { + json_t *app = json_path_get(root, "$.Application"); + json_object_set_new(app, "Records", json_array()); + + sfijson = json_path_get(root, "$.Application.Records"); + } + if (!json_is_array(sfijson)) { + PrintAndLog("E->Internal logic error. `$.Application.Records` is not an array."); + break; + } + for (int i = 0; i < AFL->len / 4; i++) { + uint8_t SFI = AFL->value[i * 4 + 0] >> 3; + uint8_t SFIstart = AFL->value[i * 4 + 1]; + uint8_t SFIend = AFL->value[i * 4 + 2]; + uint8_t SFIoffline = AFL->value[i * 4 + 3]; + + PrintAndLog("--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline); + if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) { + PrintAndLog("SFI ERROR! Skipped..."); + continue; + } + + for(int n = SFIstart; n <= SFIend; n++) { + PrintAndLog("---->SFI[%02x] %d", SFI, n); + + res = EMVReadRecord(true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot); + if (res) { + PrintAndLog("E->SFI[%02x]. APDU error %4x", SFI, sw); + continue; + } + + if (decodeTLV) { + TLVPrintFromBuffer(buf, len); + PrintAndLog(""); + } + + json_t *jsonelm = json_object(); + json_array_append_new(sfijson, jsonelm); + + JsonSaveHex(jsonelm, "SFI", SFI, 1); + JsonSaveHex(jsonelm, "RecordNum", n, 1); + JsonSaveHex(jsonelm, "Offline", SFIoffline, 1); + + struct tlvdb *rsfi = tlvdb_parse_multi(buf, len); + if (extractTLVElements) + JsonSaveTLVTree(root, jsonelm, "$.Data", rsfi); + else + JsonSaveTLVTreeElm(jsonelm, "$.Data", rsfi, true, true, false); + tlvdb_free(rsfi); + } + } + + break; + } + + // getting certificates + if (tlvdb_get(tlvRoot, 0x90, NULL)) { + PrintAndLog("-->Recovering certificates."); + PKISetStrictExecution(false); + RecoveryCertificates(tlvRoot, root); + PKISetStrictExecution(true); + } + + // free tlv object + tlvdb_free(tlvRoot); + + // DropField + DropField(); + + res = json_dump_file(root, fname, JSON_INDENT(2)); + if (res) { + PrintAndLog("ERROR: can't save the file: %s", fname); + return 200; + } + PrintAndLog("File `%s` saved.", fname); + + // free json object + json_decref(root); + + return 0; +} + int usage_emv_getrnd(void){ PrintAndLogEx(NORMAL, "retrieve the UN number from a terminal"); PrintAndLogEx(NORMAL, "Usage: hf emv getrnd [h]"); @@ -822,12 +1423,19 @@ int CmdHfEMVList(const char *Cmd) { int CmdHFEMVTest(const char *cmd) { return ExecuteCryptoTests(true); } + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"exec", CmdHFEMVExec, 0, "Executes EMV contactless transaction."}, {"pse", CmdHFEMVPPSE, 0, "Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory."}, {"search", CmdHFEMVSearch, 0, "Try to select all applets from applets list and print installed applets."}, {"select", CmdHFEMVSelect, 0, "Select applet."}, + {"gpo", CmdHFEMVGPO, 0, "Execute GetProcessingOptions."}, + {"readrec", CmdHFEMVReadRecord, 0, "Read files from card."}, + {"genac", CmdHFEMVAC, 0, "Generate ApplicationCryptogram."}, + {"challenge", CmdHFEMVGenerateChallenge, 0, "Generate challenge."}, + {"intauth", CmdHFEMVInternalAuthenticate, 0, "Internal authentication."}, + {"scan", CmdHFEMVScan, 0, "Scan EMV card and save it contents to json file for emulator."}, {"test", CmdHFEMVTest, 0, "Crypto logic test."}, /* {"getrng", CmdHfEMVGetrng, 0, "get random number from terminal"}, From d7d681ab51c74900282ae88df09f79c5ed372ca1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 20 Nov 2018 17:28:41 +0200 Subject: [PATCH 0213/1938] cmdhf apdu move to argtable --- client/cmdhf14a.c | 66 +++++++++++++---------------------------------- 1 file changed, 18 insertions(+), 48 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 77e9473a1..42a941ffa 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -171,13 +171,6 @@ int usage_hf_14a_info(void){ PrintAndLogEx(NORMAL, " n test for nack bug"); return 0; } -int usage_hf_14a_apdu(void) { - PrintAndLogEx(NORMAL, "Usage: hf 14a apdu [-s] [-k] [-t] "); - PrintAndLogEx(NORMAL, " -s activate field and select card"); - PrintAndLogEx(NORMAL, " -k leave the signal field ON after receive response"); - PrintAndLogEx(NORMAL, " -t executes TLV decoder if it possible. TODO!!!!"); - return 0; -} int usage_hf_14a_antifuzz(void) { PrintAndLogEx(NORMAL, "Usage: hf 14a antifuzz [4|7|10]"); PrintAndLogEx(NORMAL, " determine which anticollision phase the command will target."); @@ -921,51 +914,28 @@ int CmdHF14AAPDU(const char *cmd) { bool activateField = false; bool leaveSignalON = false; bool decodeTLV = false; - - if (strlen(cmd) < 2) return usage_hf_14a_apdu(); - int cmdp = 0; - while(param_getchar(cmd, cmdp) != 0x00) { - char c = param_getchar(cmd, cmdp); - if ((c == '-') && (param_getlength(cmd, cmdp) == 2)) - switch (tolower(param_getchar_indx(cmd, 1, cmdp))) { - case 'h': - return usage_hf_14a_apdu(); - case 's': - activateField = true; - break; - case 'k': - leaveSignalON = true; - break; - case 't': - decodeTLV = true; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar_indx(cmd, 1, cmdp)); - return 1; - } + CLIParserInit("hf 14a apdu", + "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL)", + "Sample:\n\thf 14a apdu -st 00A404000E325041592E5359532E444446303100\n"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("sS", "select", "activate field and select card"), + arg_lit0("kK", "keep", "leave the signal field ON after receive response"), + arg_lit0("tT", "tlv", "executes TLV decoder if it possible"), + arg_strx1(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, false); - if (isxdigit(c)) { + activateField = arg_get_lit(1); + leaveSignalON = arg_get_lit(2); + decodeTLV = arg_get_lit(3); // len = data + PCB(1b) + CRC(2b) - switch(param_gethex_to_eol(cmd, cmdp, data, sizeof(data) - 1 - 2, &datalen)) { - case 1: - PrintAndLogEx(WARNING, "invalid HEX value."); - return 1; - case 2: - PrintAndLogEx(WARNING, "APDU too large."); - return 1; - case 3: - PrintAndLogEx(WARNING, "hex must have even number of digits."); - return 1; - } - - // we get all the hex to end of line with spaces - break; - } - - cmdp++; - } + CLIGetHexBLessWithReturn(4, data, &datalen, 1 + 2); +CLIParserFree(); PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s", activateField ? "sel ": "", leaveSignalON ? "keep ": "", decodeTLV ? "TLV": "", sprint_hex(data, datalen)); int res = ExchangeAPDU14a(data, datalen, activateField, leaveSignalON, data, USB_CMD_DATA_SIZE, &datalen); From 9df1d14ca42dbbd272e86f4d5033632e5ac38ebd Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 20 Nov 2018 17:29:17 +0200 Subject: [PATCH 0214/1938] printandlogex in hf emv commands --- client/emv/cmdemv.c | 102 ++++++++++++++++++++++---------------------- 1 file changed, 51 insertions(+), 51 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 21691d0b7..5a64892c4 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -75,7 +75,7 @@ int CmdHFEMVSelect(const char *cmd) { int res = EMVSelect(activateField, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL); if (sw) - PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); if (res) return res; @@ -119,7 +119,7 @@ int CmdHFEMVSearch(const char *cmd) { return 2; } - PrintAndLog("Search completed."); + PrintAndLogEx(SUCCESS, "Search completed."); // print list here if (!decodeTLV) { @@ -169,7 +169,7 @@ int CmdHFEMVPPSE(const char *cmd) { int res = EMVSelectPSE(activateField, leaveSignalON, PSENum, buf, sizeof(buf), &len, &sw); if (sw) - PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); if (res) return res; @@ -228,19 +228,19 @@ int CmdHFEMVGPO(const char *cmd) { ParamLoadDefaults(tlvRoot); if (paramsLoadFromFile) { - PrintAndLog("Params loading from file..."); + PrintAndLogEx(INFO, "Params loading from file..."); ParamLoadFromJson(tlvRoot); }; pdol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x9f38, datalen, data), tlvRoot, 0x83); if (!pdol_data_tlv){ - PrintAndLog("ERROR: can't create PDOL TLV."); + PrintAndLogEx(ERR, "Can't create PDOL TLV."); tlvdb_free(tlvRoot); return 4; } } else { if (paramsLoadFromFile) { - PrintAndLog("WARNING: don't need to load parameters. Sending plain PDOL data..."); + PrintAndLogEx(WARNING, "Don't need to load parameters. Sending plain PDOL data..."); } pdol_data_tlv = &data_tlv; } @@ -248,11 +248,11 @@ int CmdHFEMVGPO(const char *cmd) { size_t pdol_data_tlv_data_len = 0; unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len); if (!pdol_data_tlv_data) { - PrintAndLog("ERROR: can't create PDOL data."); + PrintAndLogEx(ERR, "Can't create PDOL data."); tlvdb_free(tlvRoot); return 4; } - PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); + PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); // exec uint8_t buf[APDU_RES_LEN] = {0}; @@ -265,7 +265,7 @@ int CmdHFEMVGPO(const char *cmd) { tlvdb_free(tlvRoot); if (sw) - PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); if (res) return res; @@ -301,7 +301,7 @@ int CmdHFEMVReadRecord(const char *cmd) { CLIParserFree(); if (datalen != 2) { - PrintAndLog("ERROR: Command needs to have 2 bytes of data"); + PrintAndLogEx(ERR, "Command needs to have 2 bytes of data"); return 1; } @@ -314,7 +314,7 @@ int CmdHFEMVReadRecord(const char *cmd) { int res = EMVReadRecord(leaveSignalON, data[0], data[1], buf, sizeof(buf), &len, &sw, NULL); if (sw) - PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); if (res) return res; @@ -396,24 +396,24 @@ int CmdHFEMVAC(const char *cmd) { ParamLoadDefaults(tlvRoot); if (paramsLoadFromFile) { - PrintAndLog("Params loading from file..."); + PrintAndLogEx(INFO, "Params loading from file..."); ParamLoadFromJson(tlvRoot); }; cdol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x8c, datalen, data), tlvRoot, 0x01); // 0x01 - dummy tag if (!cdol_data_tlv){ - PrintAndLog("ERROR: can't create CDOL TLV."); + PrintAndLogEx(ERR, "Can't create CDOL TLV."); tlvdb_free(tlvRoot); return 4; } } else { if (paramsLoadFromFile) { - PrintAndLog("WARNING: don't need to load parameters. Sending plain CDOL data..."); + PrintAndLogEx(WARNING, "Don't need to load parameters. Sending plain CDOL data..."); } cdol_data_tlv = &data_tlv; } - PrintAndLog("CDOL data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len)); + PrintAndLogEx(INFO, "CDOL data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len)); // exec uint8_t buf[APDU_RES_LEN] = {0}; @@ -426,7 +426,7 @@ int CmdHFEMVAC(const char *cmd) { tlvdb_free(tlvRoot); if (sw) - PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); if (res) return res; @@ -464,15 +464,15 @@ int CmdHFEMVGenerateChallenge(const char *cmd) { int res = EMVGenerateChallenge(leaveSignalON, buf, sizeof(buf), &len, &sw, NULL); if (sw) - PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); if (res) return res; - PrintAndLog("Challenge: %s", sprint_hex(buf, len)); + PrintAndLogEx(SUCCESS, "Challenge: %s", sprint_hex(buf, len)); if (len != 4 && len != 8) - PrintAndLog("WARNING: length of challenge must be 4 or 8, but it %d", len); + PrintAndLogEx(WARNING, "Length of challenge must be 4 or 8, but it %d", len); return 0; } @@ -525,24 +525,24 @@ int CmdHFEMVInternalAuthenticate(const char *cmd) { ParamLoadDefaults(tlvRoot); if (paramsLoadFromFile) { - PrintAndLog("Params loading from file..."); + PrintAndLogEx(INFO, "Params loading from file..."); ParamLoadFromJson(tlvRoot); }; ddol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x9f49, datalen, data), tlvRoot, 0x01); // 0x01 - dummy tag if (!ddol_data_tlv){ - PrintAndLog("ERROR: can't create DDOL TLV."); + PrintAndLogEx(ERR, "Can't create DDOL TLV."); tlvdb_free(tlvRoot); return 4; } } else { if (paramsLoadFromFile) { - PrintAndLog("WARNING: don't need to load parameters. Sending plain DDOL data..."); + PrintAndLogEx(WARNING, "Don't need to load parameters. Sending plain DDOL data..."); } ddol_data_tlv = &data_tlv; } - PrintAndLog("DDOL data[%d]: %s", ddol_data_tlv->len, sprint_hex(ddol_data_tlv->value, ddol_data_tlv->len)); + PrintAndLogEx(INFO, "DDOL data[%d]: %s", ddol_data_tlv->len, sprint_hex(ddol_data_tlv->value, ddol_data_tlv->len)); // exec uint8_t buf[APDU_RES_LEN] = {0}; @@ -555,7 +555,7 @@ int CmdHFEMVInternalAuthenticate(const char *cmd) { tlvdb_free(tlvRoot); if (sw) - PrintAndLog("APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); if (res) return res; @@ -609,13 +609,13 @@ void ProcessGPOResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, } if (len < 4 || (len - 4) % 4) { - PrintAndLog("ERROR: GPO response format1 parsing error. length=%d", len); + PrintAndLogEx(ERR, "GPO response format1 parsing error. length=%d", len); } else { // AIP struct tlvdb * f1AIP = tlvdb_fixed(0x82, 2, buf + 2); tlvdb_add(tlvRoot, f1AIP); if (decodeTLV){ - PrintAndLog("\n* * Decode response format 1 (0x80) AIP and AFL:"); + PrintAndLogEx(INFO, "\n* * Decode response format 1 (0x80) AIP and AFL:"); TLVPrintFromTLV(f1AIP); } @@ -1137,12 +1137,12 @@ int CmdHFEMVScan(const char *cmd) { if (MergeJSON) { root = json_load_file(fname, 0, &error); if (!root) { - PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); + PrintAndLogEx(ERR, "Json error on line %d: %s", error.line, error.text); return 1; } if (!json_is_object(root)) { - PrintAndLog("ERROR: Invalid json format. root must be an object."); + PrintAndLogEx(ERR, "Invalid json format. root must be an object."); return 1; } } else { @@ -1153,7 +1153,7 @@ int CmdHFEMVScan(const char *cmd) { DropField(); // iso 14443 select - PrintAndLog("--> GET UID, ATS."); + PrintAndLogEx(NORMAL, "--> GET UID, ATS."); iso14a_card_select_t card; if (Hf14443_4aGetCardData(&card)) { @@ -1173,7 +1173,7 @@ int CmdHFEMVScan(const char *cmd) { struct tlvdb *tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al); // EMV PPSE - PrintAndLog("--> PPSE."); + PrintAndLogEx(NORMAL, "--> PPSE."); res = EMVSelectPSE(true, true, 2, buf, sizeof(buf), &len, &sw); if (!res && sw == 0x9000){ @@ -1199,9 +1199,9 @@ int CmdHFEMVScan(const char *cmd) { } else { // EMV SEARCH with AID list SetAPDULogging(false); - PrintAndLog("--> AID search."); + PrintAndLogEx(NORMAL, "--> AID search."); if (EMVSearch(false, true, decodeTLV, tlvSelect)) { - PrintAndLog("E->Can't found any of EMV AID. Exit..."); + PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit..."); tlvdb_free(tlvSelect); DropField(); return 3; @@ -1218,7 +1218,7 @@ int CmdHFEMVScan(const char *cmd) { tlvdb_free(tlvSelect); if (!AIDlen) { - PrintAndLog("Can't select AID. EMV AID not found. Exit..."); + PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit..."); DropField(); return 4; } @@ -1231,12 +1231,12 @@ int CmdHFEMVScan(const char *cmd) { // EMV SELECT applet - PrintAndLog("\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen)); + PrintAndLogEx(NORMAL, "\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen)); SetAPDULogging(showAPDU); res = EMVSelect(false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot); if (res) { - PrintAndLog("E->Can't select AID (%d). Exit...", res); + PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res); tlvdb_free(tlvRoot); DropField(); return 5; @@ -1258,13 +1258,13 @@ int CmdHFEMVScan(const char *cmd) { tlvdb_free(fci); // create transaction parameters - PrintAndLog("-->Init transaction parameters."); + PrintAndLogEx(NORMAL, "-->Init transaction parameters."); InitTransactionParameters(tlvRoot, paramLoadJSON, TrType, GenACGPO); - PrintAndLog("-->Calc PDOL."); + PrintAndLogEx(NORMAL, "-->Calc PDOL."); struct tlv *pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83); if (!pdol_data_tlv){ - PrintAndLog("E->Can't create PDOL TLV."); + PrintAndLogEx(ERR, "Can't create PDOL TLV."); tlvdb_free(tlvRoot); DropField(); return 6; @@ -1273,21 +1273,21 @@ int CmdHFEMVScan(const char *cmd) { size_t pdol_data_tlv_data_len; unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len); if (!pdol_data_tlv_data) { - PrintAndLog("E->Can't create PDOL data."); + PrintAndLogEx(ERR, "Can't create PDOL data."); tlvdb_free(tlvRoot); DropField(); return 6; } - PrintAndLog("PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); + PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); - PrintAndLog("-->GPO."); + PrintAndLogEx(INFO, "-->GPO."); res = EMVGPO(true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot); free(pdol_data_tlv_data); free(pdol_data_tlv); if (res) { - PrintAndLog("GPO error(%d): %4x. Exit...", res, sw); + PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw); tlvdb_free(tlvRoot); DropField(); return 7; @@ -1305,12 +1305,12 @@ int CmdHFEMVScan(const char *cmd) { tlvdb_free(gpofci); - PrintAndLog("-->Read records from AFL."); + PrintAndLogEx(INFO, "-->Read records from AFL."); const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL); while(AFL && AFL->len) { if (AFL->len % 4) { - PrintAndLog("E->Wrong AFL length: %d", AFL->len); + PrintAndLogEx(ERR, "Wrong AFL length: %d", AFL->len); break; } @@ -1322,7 +1322,7 @@ int CmdHFEMVScan(const char *cmd) { sfijson = json_path_get(root, "$.Application.Records"); } if (!json_is_array(sfijson)) { - PrintAndLog("E->Internal logic error. `$.Application.Records` is not an array."); + PrintAndLogEx(ERR, "Internal logic error. `$.Application.Records` is not an array."); break; } for (int i = 0; i < AFL->len / 4; i++) { @@ -1333,16 +1333,16 @@ int CmdHFEMVScan(const char *cmd) { PrintAndLog("--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline); if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) { - PrintAndLog("SFI ERROR! Skipped..."); + PrintAndLogEx(ERR, "SFI ERROR! Skipped..."); continue; } for(int n = SFIstart; n <= SFIend; n++) { - PrintAndLog("---->SFI[%02x] %d", SFI, n); + PrintAndLogEx(INFO, "---->SFI[%02x] %d", SFI, n); res = EMVReadRecord(true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot); if (res) { - PrintAndLog("E->SFI[%02x]. APDU error %4x", SFI, sw); + PrintAndLogEx(ERR, "SFI[%02x]. APDU error %4x", SFI, sw); continue; } @@ -1372,7 +1372,7 @@ int CmdHFEMVScan(const char *cmd) { // getting certificates if (tlvdb_get(tlvRoot, 0x90, NULL)) { - PrintAndLog("-->Recovering certificates."); + PrintAndLogEx(INFO, "-->Recovering certificates."); PKISetStrictExecution(false); RecoveryCertificates(tlvRoot, root); PKISetStrictExecution(true); @@ -1386,10 +1386,10 @@ int CmdHFEMVScan(const char *cmd) { res = json_dump_file(root, fname, JSON_INDENT(2)); if (res) { - PrintAndLog("ERROR: can't save the file: %s", fname); + PrintAndLogEx(ERR, "Can't save the file: %s", fname); return 200; } - PrintAndLog("File `%s` saved.", fname); + PrintAndLogEx(SUCCESS, "File `%s` saved.", fname); // free json object json_decref(root); From 291321f01df8de585ebdfff8044bd9e9676b0495 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 20 Nov 2018 17:34:29 +0200 Subject: [PATCH 0215/1938] add changelog --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a57924d70..193d9c2fc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -83,6 +83,9 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added `hf fido` commands that work with FIDO U2F authenticators (@merlokk) - Added mbedtls instead of old polarssl (@merlokk) - Added jansson (@merlokk) + - Added `hf emv scan` - save card's data to json file (@merlokk) + - Added `hf emv` `gpo`, `readrec`, `genac`, `challenge`, `intauth` - separate commands from `hf emc exec` (@merlokk) + ### Fixed - Changed driver file proxmark3.inf to support both old and new Product/Vendor IDs (piwi) - Changed start sequence in Qt mode (fix: short commands hangs main Qt thread) (Merlok) From 38e0d7de322df8d2f531e3a58dcb292342d256a3 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 20 Nov 2018 19:21:36 +0200 Subject: [PATCH 0216/1938] add load json --- client/cmdhffido.c | 50 +++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 45 insertions(+), 5 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 11c63d92e..1d374af00 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -720,8 +720,48 @@ int CmdHFFidoAuthenticate(const char *cmd) { return 0; }; -int CmdHFFido2MakeCredential(const char *cmd) { +int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileName) { + fileName[0] = 0x00; + strcpy(fileName, get_my_executable_directory()); + if (fileName[strlen(fileName) - 1] != '/') + strcat(fileName, "/"); + strcat(fileName, prefixDir); + if (fileName[strlen(fileName) - 1] != '/') + strcat(fileName, "/"); + + strcat(fileName, reqestedFileName); + if (!strstr(fileName, ".json")) + strcat(fileName, ".json"); + + if (access(fileName, F_OK) < 0) { + strcpy(fileName, get_my_executable_directory()); + if (fileName[strlen(fileName) - 1] != '/') + strcat(fileName, "/"); + + strcat(fileName, reqestedFileName); + if (!strstr(fileName, ".json")) + strcat(fileName, ".json"); + + if (access(fileName, F_OK) < 0) { + return 1; // file not found + } + } + return 0; +} + +int CmdHFFido2MakeCredential(const char *cmd) { + + + json_error_t error; + json_t *root = NULL; + char fname[300] = {0}; + + int res = GetExistsFileNameJson("fido", "fido2", fname); + if(res) + return res; + + root = json_load_file(fname, 0, &error); uint8_t data[2048] = {0}; size_t datalen = 0; @@ -730,7 +770,7 @@ int CmdHFFido2MakeCredential(const char *cmd) { uint16_t sw = 0; DropField(); - int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); + res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); if (res) { PrintAndLog("Can't select authenticator. res=%x. Exit...", res); @@ -747,17 +787,17 @@ int CmdHFFido2MakeCredential(const char *cmd) { res = FIDO2MakeCredential(data, datalen, buf, sizeof(buf), &len, &sw); DropField(); if (res) { - PrintAndLog("Can't execute register command. res=%x. Exit...", res); + PrintAndLog("Can't execute make credential command. res=%x. Exit...", res); return res; } if (sw != 0x9000) { - PrintAndLog("ERROR execute register command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLog("ERROR execute make credential command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); return 3; } if(buf[0]) { - PrintAndLog("FIDO2 ger version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); + PrintAndLog("FIDO2 make credential error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); return 0; } From ea3472b0e0e6c590a9a6752ea006350385ec63b3 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 20 Nov 2018 19:31:08 +0200 Subject: [PATCH 0217/1938] load json OK --- client/cmdhffido.c | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 1d374af00..a5ad55536 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -720,15 +720,19 @@ int CmdHFFidoAuthenticate(const char *cmd) { return 0; }; +void CheckSlash(char *fileName) { + if ((fileName[strlen(fileName) - 1] != '/') && + (fileName[strlen(fileName) - 1] != '\\')) + strcat(fileName, "/"); +} + int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileName) { fileName[0] = 0x00; strcpy(fileName, get_my_executable_directory()); - if (fileName[strlen(fileName) - 1] != '/') - strcat(fileName, "/"); + CheckSlash(fileName); strcat(fileName, prefixDir); - if (fileName[strlen(fileName) - 1] != '/') - strcat(fileName, "/"); + CheckSlash(fileName); strcat(fileName, reqestedFileName); if (!strstr(fileName, ".json")) @@ -736,8 +740,7 @@ int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileNam if (access(fileName, F_OK) < 0) { strcpy(fileName, get_my_executable_directory()); - if (fileName[strlen(fileName) - 1] != '/') - strcat(fileName, "/"); + CheckSlash(fileName); strcat(fileName, reqestedFileName); if (!strstr(fileName, ".json")) @@ -758,10 +761,16 @@ int CmdHFFido2MakeCredential(const char *cmd) { char fname[300] = {0}; int res = GetExistsFileNameJson("fido", "fido2", fname); - if(res) + if(res) { + PrintAndLog("ERROR: Can't found json file."); return res; - + } + PrintAndLog("fname: %s\n", fname); root = json_load_file(fname, 0, &error); + if (!root) { + PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); + return 1; + } uint8_t data[2048] = {0}; size_t datalen = 0; From 7b943a4a16218a630a5f1060850df7075ced2f50 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 21 Nov 2018 19:44:31 +0200 Subject: [PATCH 0218/1938] add check string - if string is hex --- client/util.c | 11 +++++++++++ client/util.h | 1 + 2 files changed, 12 insertions(+) diff --git a/client/util.c b/client/util.c index 5ae4ab862..22490f62a 100644 --- a/client/util.c +++ b/client/util.c @@ -150,6 +150,17 @@ int FillBuffer(uint8_t *data, size_t maxDataLength, size_t *dataLength, ...) { return 0; } +bool CheckStringIsHEXValue(const char *value) { + for (int i = 0; i < strlen(value); i++) + if (!isxdigit(value[i])) + return false; + + if (strlen(value) % 2) + return false; + + return true; +} + void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, const size_t hex_max_len, const size_t min_str_len, const size_t spaces_between, bool uppercase) { diff --git a/client/util.h b/client/util.h index a069b5012..c9f13870d 100644 --- a/client/util.h +++ b/client/util.h @@ -190,6 +190,7 @@ extern void FillFileNameByUID(char *filenamePrefix, uint8_t * uid, const char *e // fill buffer from structure [{uint8_t data, size_t length},...] extern int FillBuffer(uint8_t *data, size_t maxDataLength, size_t *dataLength, ...); +extern bool CheckStringIsHEXValue(const char *value); extern void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, const size_t hex_max_len, const size_t min_str_len, const size_t spaces_between, bool uppercase); From dae4ecc60fdb1b058cb07b214dce2b20b63cfad6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 21 Nov 2018 19:45:11 +0200 Subject: [PATCH 0219/1938] removed ismap and added not-writable parameters --- client/fido/fido2.json | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/client/fido/fido2.json b/client/fido/fido2.json index ceb55bae8..5da643558 100644 --- a/client/fido/fido2.json +++ b/client/fido/fido2.json @@ -1,12 +1,10 @@ { "ClientDataHash": "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f", "RelyingPartyEntity": { - "isMap": true, "id": "acme.com", "name": "Acme" }, "UserEntity": { - "isMap": true, "id": "00000000000000000000000000000000", "icon": "https://pics.acme.com/00/p/aBjjjpqPb.png", "name": "johnpsmith@acme.com", @@ -14,20 +12,17 @@ }, "pubKeyCredParams": [ { - "isMap": true, "type": "public-key", "alg": -7, - "name": "ES256" + ".name": "ES256" }, { - "isMap": true, "type": "public-key", "alg": -257, - "name": "RS256" + ".name": "RS256" } ], "options": { - "isMap": true, "up": false, "uv": false, "keyStorageDevice": true From da45b1db390a76d3d62bf9fcf53fe83c72dd50a4 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 21 Nov 2018 19:46:09 +0200 Subject: [PATCH 0220/1938] added jsontocbor function --- client/fido/cbortools.c | 105 ++++++++++++++++++++++++++++++++++++++-- client/fido/cbortools.h | 6 +++ 2 files changed, 107 insertions(+), 4 deletions(-) diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index cd8f905bb..653659dd3 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -12,7 +12,7 @@ #include "cbortools.h" #include -#include "cbor.h" +#include "emv/emvjson.h" #include "util.h" #include "fidocore.h" @@ -199,9 +199,7 @@ int TinyCborPrintFIDOPackage(uint8_t cmdCode, uint8_t *data, size_t length) { res = TinyCborInit(data, length, &cb); if (res) return res; - - - + CborError err = dumprecursive(cmdCode, &cb, false, 0); if (err) { @@ -210,6 +208,105 @@ int TinyCborPrintFIDOPackage(uint8_t cmdCode, uint8_t *data, size_t length) { return 1; } + return 0; +} + +int JsonObjElmCount(json_t *elm) { + int res = 0; + const char *key; + json_t *value; + + if (!json_is_object(elm)) + return 0; + + json_object_foreach(elm, key, value) { + if (strlen(key) > 0 && key[0] != '.') + res++; + } + + return res; +} + +int JsonToCbor(json_t *elm, CborEncoder *encoder) { + if (!elm || !encoder) + return 1; + + int res; + + // CBOR map == JSON object + if (json_is_object(elm)) { + CborEncoder map; + const char *key; + json_t *value; + + res = cbor_encoder_create_map(encoder, &map, JsonObjElmCount(elm)); + cbor_check(res); + + json_object_foreach(elm, key, value) { + if (strlen(key) > 0 && key[0] != '.') { + res = cbor_encode_text_stringz(&map, key); + cbor_check(res); + + // RECURSION! + JsonToCbor(value, &map); + } + } + + res = cbor_encoder_close_container(encoder, &map); + cbor_check(res); + } + + // CBOR array == JSON array + if (json_is_array(elm)) { + size_t index; + json_t *value; + CborEncoder array; + + res = cbor_encoder_create_array(encoder, &array, json_array_size(elm)); + cbor_check(res); + + json_array_foreach(elm, index, value) { + // RECURSION! + JsonToCbor(value, &array); + } + + res = cbor_encoder_close_container(encoder, &array); + cbor_check(res); + } + + if (json_is_boolean(elm)) { + res = cbor_encode_boolean(encoder, json_is_true(elm)); + cbor_check(res); + } + + if (json_is_integer(elm)) { + res = cbor_encode_int(encoder, json_integer_value(elm)); + cbor_check(res); + } + + if (json_is_real(elm)) { + res = cbor_encode_float(encoder, json_real_value(elm)); + cbor_check(res); + } + + if (json_is_string(elm)) { + const char * val = json_string_value(elm); + if (CheckStringIsHEXValue(val)) { + size_t datalen = 0; + uint8_t data[4096] = {0}; + res = JsonLoadBufAsHex(elm, "$", data, sizeof(data), &datalen); + if (res) + return 100; + + res = cbor_encode_byte_string(encoder, data, datalen); + cbor_check(res); + } else { + res = cbor_encode_text_stringz(encoder, val); + cbor_check(res); + } + } + + return 0; } diff --git a/client/fido/cbortools.h b/client/fido/cbortools.h index bb442f1f8..6de69e2eb 100644 --- a/client/fido/cbortools.h +++ b/client/fido/cbortools.h @@ -15,7 +15,13 @@ #include #include +#include +#include + +#define cbor_check_if(r) if ((r) != CborNoError) {return r;} else +#define cbor_check(r) if ((r) != CborNoError) return r; extern int TinyCborPrintFIDOPackage(uint8_t cmdCode, uint8_t *data, size_t length); +extern int JsonToCbor(json_t *elm, CborEncoder *encoder); #endif /* __CBORTOOLS_H__ */ From f705402b7af6c4868795b0f5a0274715e124b26d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 21 Nov 2018 19:46:57 +0200 Subject: [PATCH 0221/1938] make credentional command works. and refactoring --- client/cmdhffido.c | 69 ++++-------------- client/fido/fidocore.c | 157 +++++++++++++++++++++++++++++++++++++++++ client/fido/fidocore.h | 12 ++++ 3 files changed, 182 insertions(+), 56 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index a5ad55536..13fc0eaf8 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -36,7 +36,6 @@ #include "util.h" #include "ui.h" #include "proxmark3.h" -#include "cmdhf14a.h" #include "mifare.h" #include "emv/emvcore.h" #include "emv/emvjson.h" @@ -50,57 +49,6 @@ static int CmdHelp(const char *Cmd); -int FIDOSelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - uint8_t data[] = {0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01}; - - return EMVSelect(ActivateField, LeaveFieldON, data, sizeof(data), Result, MaxResultLen, ResultLen, sw, NULL); -} - -int FIDOExchange(sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - int res = EMVExchange(true, apdu, Result, MaxResultLen, ResultLen, sw, NULL); - if (res == 5) // apdu result (sw) not a 0x9000 - res = 0; - // software chaining - while (!res && (*sw >> 8) == 0x61) { - size_t oldlen = *ResultLen; - res = EMVExchange(true, (sAPDU){0x00, 0xC0, 0x00, 0x00, 0x00, NULL}, &Result[oldlen], MaxResultLen - oldlen, ResultLen, sw, NULL); - if (res == 5) // apdu result (sw) not a 0x9000 - res = 0; - - *ResultLen += oldlen; - if (*ResultLen > MaxResultLen) - return 100; - } - return res; -} - -int FIDORegister(uint8_t *params, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - return FIDOExchange((sAPDU){0x00, 0x01, 0x03, 0x00, 64, params}, Result, MaxResultLen, ResultLen, sw); -} - -int FIDOAuthentication(uint8_t *params, uint8_t paramslen, uint8_t controlb, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - return FIDOExchange((sAPDU){0x00, 0x02, controlb, 0x00, paramslen, params}, Result, MaxResultLen, ResultLen, sw); -} - -int FIDO2GetInfo(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - uint8_t data[] = {fido2CmdGetInfo}; - return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); -} - -int FIDO2MakeCredential(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - uint8_t data[paramslen + 1]; - data[0] = fido2CmdMakeCredential; - memcpy(&data[1], params, paramslen); - return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); -} - -int FIDO2GetAssertion(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - uint8_t data[paramslen + 1]; - data[0] = fido2CmdGetAssertion; - memcpy(&data[1], params, paramslen); - return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); -} - int CmdHFFidoInfo(const char *cmd) { if (cmd && strlen(cmd) > 0) @@ -754,15 +702,13 @@ int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileNam } int CmdHFFido2MakeCredential(const char *cmd) { - - json_error_t error; json_t *root = NULL; char fname[300] = {0}; int res = GetExistsFileNameJson("fido", "fido2", fname); if(res) { - PrintAndLog("ERROR: Can't found json file."); + PrintAndLog("ERROR: Can't found the json file."); return res; } PrintAndLog("fname: %s\n", fname); @@ -793,6 +739,13 @@ int CmdHFFido2MakeCredential(const char *cmd) { return 2; } + res = FIDO2CreateMakeCredentionalReq(root, data, sizeof(data), &datalen); + if (res) + return res; + + PrintAndLog("CBOR make credentional request:"); + TinyCborPrintFIDOPackage(fido2CmdMakeCredential, data, datalen); + res = FIDO2MakeCredential(data, datalen, buf, sizeof(buf), &len, &sw); DropField(); if (res) { @@ -810,7 +763,11 @@ int CmdHFFido2MakeCredential(const char *cmd) { return 0; } - PrintAndLog("res[%d]: %s", len, sprint_hex(buf, len)); + PrintAndLog("MakeCredential result (%d) OK.", len); + PrintAndLog("CBOR make credentional response:"); + TinyCborPrintFIDOPackage(fido2CmdMakeCredential, &buf[1], len - 1); + + json_decref(root); return 0; }; diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 1b41d2722..0e4099a88 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -11,6 +11,10 @@ // #include "fidocore.h" +#include "emv/emvcore.h" +#include "emv/emvjson.h" +#include +#include "cbortools.h" typedef struct { uint8_t ErrorCode; @@ -122,3 +126,156 @@ char *fido2GetCmdMemberDescription(uint8_t cmdCode, uint8_t memberNum) { return NULL; } +int FIDOSelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + uint8_t data[] = {0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01}; + + return EMVSelect(ActivateField, LeaveFieldON, data, sizeof(data), Result, MaxResultLen, ResultLen, sw, NULL); +} + +int FIDOExchange(sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + int res = EMVExchange(true, apdu, Result, MaxResultLen, ResultLen, sw, NULL); + if (res == 5) // apdu result (sw) not a 0x9000 + res = 0; + // software chaining + while (!res && (*sw >> 8) == 0x61) { + size_t oldlen = *ResultLen; + res = EMVExchange(true, (sAPDU){0x00, 0xC0, 0x00, 0x00, 0x00, NULL}, &Result[oldlen], MaxResultLen - oldlen, ResultLen, sw, NULL); + if (res == 5) // apdu result (sw) not a 0x9000 + res = 0; + + *ResultLen += oldlen; + if (*ResultLen > MaxResultLen) + return 100; + } + return res; +} + +int FIDORegister(uint8_t *params, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + return FIDOExchange((sAPDU){0x00, 0x01, 0x03, 0x00, 64, params}, Result, MaxResultLen, ResultLen, sw); +} + +int FIDOAuthentication(uint8_t *params, uint8_t paramslen, uint8_t controlb, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + return FIDOExchange((sAPDU){0x00, 0x02, controlb, 0x00, paramslen, params}, Result, MaxResultLen, ResultLen, sw); +} + +int FIDO2GetInfo(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + uint8_t data[] = {fido2CmdGetInfo}; + return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); +} + +int FIDO2MakeCredential(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + uint8_t data[paramslen + 1]; + data[0] = fido2CmdMakeCredential; + memcpy(&data[1], params, paramslen); + return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); +} + +int FIDO2GetAssertion(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { + uint8_t data[paramslen + 1]; + data[0] = fido2CmdGetAssertion; + memcpy(&data[1], params, paramslen); + return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); +} + +#define fido_check_if(r) if ((r) != CborNoError) {return r;} else +#define fido_check(r) if ((r) != CborNoError) return r; + +int CBOREncodeClientDataHash(json_t *root, CborEncoder *encoder) { + uint8_t buf[100] = {0}; + size_t jlen; + + JsonLoadBufAsHex(root, "$.ClientDataHash", buf, sizeof(buf), &jlen); + + // fill with 0x00 if not found + if (!jlen) + jlen = 32; + + int res = cbor_encode_byte_string(encoder, buf, jlen); + fido_check(res); + + return 0; +} + +int CBOREncodeRp(json_t *root, CborEncoder *encoder) { + json_t *elm = json_object_get(root, "RelyingPartyEntity"); + if (!elm) + return 1; + + JsonToCbor(elm, encoder); + + return 0; +} + +int CBOREncodeUser(json_t *root, CborEncoder *encoder) { + json_t *elm = json_object_get(root, "UserEntity"); + if (!elm) + return 1; + + JsonToCbor(elm, encoder); + + return 0; +} + +int CBOREncodePubKeyParams(json_t *root, CborEncoder *encoder) { + json_t *elm = json_object_get(root, "pubKeyCredParams"); + if (!elm) + return 1; + + JsonToCbor(elm, encoder); + + return 0; +} + +int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen) { + if (datalen) + *datalen = 0; + if (!root || !data || !maxdatalen) + return 1; + + int res; + CborEncoder encoder; + CborEncoder map; + + cbor_encoder_init(&encoder, data, maxdatalen, 0); + + // create main map + res = cbor_encoder_create_map(&encoder, &map, 4); + fido_check_if(res) { + // clientDataHash + res = cbor_encode_uint(&map, 1); + fido_check_if(res) { + res = CBOREncodeClientDataHash(root, &map); + fido_check(res); + } + + // rp + res = cbor_encode_uint(&map, 2); + fido_check_if(res) { + res = CBOREncodeRp(root, &map); + fido_check(res); + } + + // user + res = cbor_encode_uint(&map, 3); + fido_check_if(res) { + res = CBOREncodeUser(root, &map); + fido_check(res); + } + + // pubKeyCredParams + res = cbor_encode_uint(&map, 4); + fido_check_if(res) { + res = CBOREncodePubKeyParams(root, &map); + fido_check(res); + } + + } + res = cbor_encoder_close_container(&encoder, &map); + fido_check(res); + + size_t len = cbor_encoder_get_buffer_size(&encoder, data); + if (datalen) + *datalen = len; + + return 0; +} diff --git a/client/fido/fidocore.h b/client/fido/fidocore.h index 1ed5556cf..d16c42190 100644 --- a/client/fido/fidocore.h +++ b/client/fido/fidocore.h @@ -14,6 +14,8 @@ #include #include +#include +#include "cmdhf14a.h" typedef enum { fido2CmdMakeCredential = 0x01, @@ -30,7 +32,17 @@ typedef enum { ptResponse, } fido2PacketType; +extern int FIDOSelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +extern int FIDOExchange(sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +extern int FIDORegister(uint8_t *params, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +extern int FIDOAuthentication(uint8_t *params, uint8_t paramslen, uint8_t controlb, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +extern int FIDO2GetInfo(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +extern int FIDO2MakeCredential(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +extern int FIDO2GetAssertion(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); + extern char *fido2GetCmdMemberDescription(uint8_t cmdCode, uint8_t memberNum); extern char *fido2GetCmdErrorDescription(uint8_t errorCode); +extern int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen); + #endif /* __FIDOCORE_H__ */ From 979a14d9785791404a615bd2b414dc71a2e8ec87 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 21 Nov 2018 20:11:41 +0200 Subject: [PATCH 0222/1938] added CBOR description for queries --- client/cmdhffido.c | 8 ++++---- client/fido/cbortools.c | 10 +++++----- client/fido/cbortools.h | 2 +- client/fido/fidocore.c | 37 ++++++++++++++++++++++++++++++++----- client/fido/fidocore.h | 2 +- 5 files changed, 43 insertions(+), 16 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 13fc0eaf8..f5f10b70a 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -116,7 +116,7 @@ int CmdHFFidoInfo(const char *cmd) { // } PrintAndLog("FIDO2 version CBOR decoded:"); - TinyCborPrintFIDOPackage(fido2CmdGetInfo, &buf[1], len - 1); + TinyCborPrintFIDOPackage(fido2CmdGetInfo, true, &buf[1], len - 1); } else { PrintAndLog("FIDO2 version length error"); } @@ -744,7 +744,7 @@ int CmdHFFido2MakeCredential(const char *cmd) { return res; PrintAndLog("CBOR make credentional request:"); - TinyCborPrintFIDOPackage(fido2CmdMakeCredential, data, datalen); + TinyCborPrintFIDOPackage(fido2CmdMakeCredential, false, data, datalen); res = FIDO2MakeCredential(data, datalen, buf, sizeof(buf), &len, &sw); DropField(); @@ -763,9 +763,9 @@ int CmdHFFido2MakeCredential(const char *cmd) { return 0; } - PrintAndLog("MakeCredential result (%d) OK.", len); + PrintAndLog("MakeCredential result (%d b) OK.", len); PrintAndLog("CBOR make credentional response:"); - TinyCborPrintFIDOPackage(fido2CmdMakeCredential, &buf[1], len - 1); + TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1); json_decref(root); diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index 653659dd3..51041cefb 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -122,7 +122,7 @@ static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) { return CborNoError; } -static CborError dumprecursive(uint8_t cmdCode, CborValue *it, bool isMapType, int nestingLevel) { +static CborError dumprecursive(uint8_t cmdCode, bool isResponse, CborValue *it, bool isMapType, int nestingLevel) { int elmCount = 0; while (!cbor_value_at_end(it)) { CborError err; @@ -142,7 +142,7 @@ static CborError dumprecursive(uint8_t cmdCode, CborValue *it, bool isMapType, i err = cbor_value_enter_container(it, &recursed); if (err) return err; // parse error - err = dumprecursive(cmdCode, &recursed, (type == CborMapType), nestingLevel + 1); + err = dumprecursive(cmdCode, isResponse, &recursed, (type == CborMapType), nestingLevel + 1); if (err) return err; // parse error err = cbor_value_leave_container(it, &recursed); @@ -161,7 +161,7 @@ static CborError dumprecursive(uint8_t cmdCode, CborValue *it, bool isMapType, i if (cmdCode > 0 && nestingLevel == 1 && isMapType && !(elmCount % 2)) { int64_t val; cbor_value_get_int64(it, &val); - char *desc = fido2GetCmdMemberDescription(cmdCode, val); + char *desc = fido2GetCmdMemberDescription(cmdCode, isResponse, val); if (desc) printf(" (%s)", desc); } @@ -193,14 +193,14 @@ int TinyCborInit(uint8_t *data, size_t length, CborValue *cb) { return 0; } -int TinyCborPrintFIDOPackage(uint8_t cmdCode, uint8_t *data, size_t length) { +int TinyCborPrintFIDOPackage(uint8_t cmdCode, bool isResponse, uint8_t *data, size_t length) { CborValue cb; int res; res = TinyCborInit(data, length, &cb); if (res) return res; - CborError err = dumprecursive(cmdCode, &cb, false, 0); + CborError err = dumprecursive(cmdCode, isResponse, &cb, false, 0); if (err) { fprintf(stderr, "CBOR parsing failure at offset %d: %s\n", diff --git a/client/fido/cbortools.h b/client/fido/cbortools.h index 6de69e2eb..4019f1f70 100644 --- a/client/fido/cbortools.h +++ b/client/fido/cbortools.h @@ -21,7 +21,7 @@ #define cbor_check_if(r) if ((r) != CborNoError) {return r;} else #define cbor_check(r) if ((r) != CborNoError) return r; -extern int TinyCborPrintFIDOPackage(uint8_t cmdCode, uint8_t *data, size_t length); +extern int TinyCborPrintFIDOPackage(uint8_t cmdCode, bool isResponse, uint8_t *data, size_t length); extern int JsonToCbor(json_t *elm, CborEncoder *encoder); #endif /* __CBORTOOLS_H__ */ diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 0e4099a88..572a00022 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -84,12 +84,30 @@ fido2Desc_t fido2CmdGetInfoRespDesc[] = { {fido2CmdMakeCredential, ptResponse, 0x01, "fmt"}, {fido2CmdMakeCredential, ptResponse, 0x02, "authData"}, {fido2CmdMakeCredential, ptResponse, 0x03, "attStmt"}, + + {fido2CmdMakeCredential, ptQuery, 0x01, "clientDataHash"}, + {fido2CmdMakeCredential, ptQuery, 0x02, "rp"}, + {fido2CmdMakeCredential, ptQuery, 0x03, "user"}, + {fido2CmdMakeCredential, ptQuery, 0x04, "pubKeyCredParams"}, + {fido2CmdMakeCredential, ptQuery, 0x05, "excludeList"}, + {fido2CmdMakeCredential, ptQuery, 0x06, "extensions"}, + {fido2CmdMakeCredential, ptQuery, 0x07, "options"}, + {fido2CmdMakeCredential, ptQuery, 0x08, "pinAuth"}, + {fido2CmdMakeCredential, ptQuery, 0x09, "pinProtocol"}, {fido2CmdGetAssertion, ptResponse, 0x01, "credential"}, {fido2CmdGetAssertion, ptResponse, 0x02, "authData"}, {fido2CmdGetAssertion, ptResponse, 0x03, "signature"}, {fido2CmdGetAssertion, ptResponse, 0x04, "publicKeyCredentialUserEntity"}, {fido2CmdGetAssertion, ptResponse, 0x05, "numberOfCredentials"}, + + {fido2CmdGetAssertion, ptQuery, 0x01, "rpId"}, + {fido2CmdGetAssertion, ptQuery, 0x02, "clientDataHash"}, + {fido2CmdGetAssertion, ptQuery, 0x03, "allowList"}, + {fido2CmdGetAssertion, ptQuery, 0x04, "extensions"}, + {fido2CmdGetAssertion, ptQuery, 0x05, "options"}, + {fido2CmdGetAssertion, ptQuery, 0x06, "pinAuth"}, + {fido2CmdGetAssertion, ptQuery, 0x07, "pinProtocol"}, {fido2CmdGetNextAssertion, ptResponse, 0x01, "credential"}, {fido2CmdGetNextAssertion, ptResponse, 0x02, "authData"}, @@ -103,9 +121,18 @@ fido2Desc_t fido2CmdGetInfoRespDesc[] = { {fido2CmdGetInfo, ptResponse, 0x05, "maxMsgSize"}, {fido2CmdGetInfo, ptResponse, 0x06, "pinProtocols"}, - {fido2CmdClientPIN, ptResponse, 0x06, "keyAgreement"}, - {fido2CmdClientPIN, ptResponse, 0x06, "pinToken"}, - {fido2CmdClientPIN, ptResponse, 0x06, "retries"}, + {fido2CmdClientPIN, ptResponse, 0x01, "keyAgreement"}, + {fido2CmdClientPIN, ptResponse, 0x02, "pinToken"}, + {fido2CmdClientPIN, ptResponse, 0x03, "retries"}, + + {fido2CmdClientPIN, ptQuery, 0x01, "pinProtocol"}, + {fido2CmdClientPIN, ptQuery, 0x02, "subCommand"}, + {fido2CmdClientPIN, ptQuery, 0x03, "keyAgreement"}, + {fido2CmdClientPIN, ptQuery, 0x04, "pinAuth"}, + {fido2CmdClientPIN, ptQuery, 0x05, "newPinEnc"}, + {fido2CmdClientPIN, ptQuery, 0x06, "pinHashEnc"}, + {fido2CmdClientPIN, ptQuery, 0x07, "getKeyAgreement"}, + {fido2CmdClientPIN, ptQuery, 0x08, "getRetries"}, }; char *fido2GetCmdErrorDescription(uint8_t errorCode) { @@ -116,10 +143,10 @@ char *fido2GetCmdErrorDescription(uint8_t errorCode) { return fido2Errors[0].Description; } -char *fido2GetCmdMemberDescription(uint8_t cmdCode, uint8_t memberNum) { +char *fido2GetCmdMemberDescription(uint8_t cmdCode, bool isResponse, uint8_t memberNum) { for (int i = 0; i < sizeof(fido2CmdGetInfoRespDesc) / sizeof(fido2Desc_t); i++) if (fido2CmdGetInfoRespDesc[i].Command == cmdCode && - fido2CmdGetInfoRespDesc[i].PckType == ptResponse && + fido2CmdGetInfoRespDesc[i].PckType == (isResponse ? ptResponse : ptQuery) && fido2CmdGetInfoRespDesc[i].MemberNumber == memberNum ) return fido2CmdGetInfoRespDesc[i].Description; diff --git a/client/fido/fidocore.h b/client/fido/fidocore.h index d16c42190..e87de1922 100644 --- a/client/fido/fidocore.h +++ b/client/fido/fidocore.h @@ -40,7 +40,7 @@ extern int FIDO2GetInfo(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, extern int FIDO2MakeCredential(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); extern int FIDO2GetAssertion(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); -extern char *fido2GetCmdMemberDescription(uint8_t cmdCode, uint8_t memberNum); +extern char *fido2GetCmdMemberDescription(uint8_t cmdCode, bool isResponse, uint8_t memberNum); extern char *fido2GetCmdErrorDescription(uint8_t errorCode); extern int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen); From e33ddad40cff5b2bd1c920873ed2cb4c96d3836b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 21 Nov 2018 20:35:57 +0200 Subject: [PATCH 0223/1938] added options and some refactoring --- client/fido/fido2.json | 4 ++-- client/fido/fidocore.c | 44 ++++++++++++++---------------------------- 2 files changed, 17 insertions(+), 31 deletions(-) diff --git a/client/fido/fido2.json b/client/fido/fido2.json index 5da643558..b847e891b 100644 --- a/client/fido/fido2.json +++ b/client/fido/fido2.json @@ -23,8 +23,8 @@ } ], "options": { - "up": false, "uv": false, - "keyStorageDevice": true + ".up": false, + ".keyStorageDevice": true } } \ No newline at end of file diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 572a00022..57a89560a 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -223,34 +223,14 @@ int CBOREncodeClientDataHash(json_t *root, CborEncoder *encoder) { return 0; } -int CBOREncodeRp(json_t *root, CborEncoder *encoder) { - json_t *elm = json_object_get(root, "RelyingPartyEntity"); +int CBOREncodeElm(json_t *root, char *rootElmId, CborEncoder *encoder) { + json_t *elm = json_object_get(root, rootElmId); if (!elm) return 1; - JsonToCbor(elm, encoder); + int res = JsonToCbor(elm, encoder); - return 0; -} - -int CBOREncodeUser(json_t *root, CborEncoder *encoder) { - json_t *elm = json_object_get(root, "UserEntity"); - if (!elm) - return 1; - - JsonToCbor(elm, encoder); - - return 0; -} - -int CBOREncodePubKeyParams(json_t *root, CborEncoder *encoder) { - json_t *elm = json_object_get(root, "pubKeyCredParams"); - if (!elm) - return 1; - - JsonToCbor(elm, encoder); - - return 0; + return res; } int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen) { @@ -266,7 +246,7 @@ int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatale cbor_encoder_init(&encoder, data, maxdatalen, 0); // create main map - res = cbor_encoder_create_map(&encoder, &map, 4); + res = cbor_encoder_create_map(&encoder, &map, 5); fido_check_if(res) { // clientDataHash res = cbor_encode_uint(&map, 1); @@ -278,24 +258,30 @@ int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatale // rp res = cbor_encode_uint(&map, 2); fido_check_if(res) { - res = CBOREncodeRp(root, &map); + res = CBOREncodeElm(root, "RelyingPartyEntity", &map); fido_check(res); } // user res = cbor_encode_uint(&map, 3); fido_check_if(res) { - res = CBOREncodeUser(root, &map); + res = CBOREncodeElm(root, "UserEntity", &map); fido_check(res); } // pubKeyCredParams res = cbor_encode_uint(&map, 4); fido_check_if(res) { - res = CBOREncodePubKeyParams(root, &map); + res = CBOREncodeElm(root, "pubKeyCredParams", &map); + fido_check(res); + } + + // options + res = cbor_encode_uint(&map, 7); + fido_check_if(res) { + res = CBOREncodeElm(root, "options", &map); fido_check(res); } - } res = cbor_encoder_close_container(&encoder, &map); fido_check(res); From 7bb24819adb8c53b8a3ab21c10e78928da03de02 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 21 Nov 2018 20:39:26 +0200 Subject: [PATCH 0224/1938] small fix --- client/fido/fido2.json | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/fido/fido2.json b/client/fido/fido2.json index b847e891b..88abf48e1 100644 --- a/client/fido/fido2.json +++ b/client/fido/fido2.json @@ -5,7 +5,7 @@ "name": "Acme" }, "UserEntity": { - "id": "00000000000000000000000000000000", + "id": "00000000000000000000000000000001", "icon": "https://pics.acme.com/00/p/aBjjjpqPb.png", "name": "johnpsmith@acme.com", "displayName": "John P. Smith" @@ -24,7 +24,6 @@ ], "options": { "uv": false, - ".up": false, - ".keyStorageDevice": true + "rk": false, } } \ No newline at end of file From 156f9b677c060670daf9bb0ac9793b297ae53f20 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 22 Nov 2018 13:41:44 +0200 Subject: [PATCH 0225/1938] refactoring --- client/cmdhffido.c | 56 +--------------------------------- client/fido/fido2.json | 2 +- client/fido/fidocore.c | 69 ++++++++++++++++++++++++++++++++++++++++++ client/fido/fidocore.h | 2 ++ 4 files changed, 73 insertions(+), 56 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index f5f10b70a..19566075f 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -43,7 +43,6 @@ #include "cliparser/cliparser.h" #include "crypto/asn1utils.h" #include "crypto/libpcrypto.h" -#include "fido/additional_ca.h" #include "fido/cbortools.h" #include "fido/fidocore.h" @@ -326,60 +325,7 @@ int CmdHFFidoRegister(const char *cmd) { PrintAndLog("----------------DER TLV-----------------"); } - // load CA's - mbedtls_x509_crt cacert; - mbedtls_x509_crt_init(&cacert); - res = mbedtls_x509_crt_parse(&cacert, (const unsigned char *) additional_ca_pem, additional_ca_pem_len); - if (res < 0) { - PrintAndLog("ERROR: CA parse certificate returned -0x%x - %s", -res, ecdsa_get_error(res)); - } - if (verbose) - PrintAndLog("CA load OK. %d skipped", res); - - // load DER certificate from authenticator's data - mbedtls_x509_crt cert; - mbedtls_x509_crt_init(&cert); - res = mbedtls_x509_crt_parse_der(&cert, &buf[derp], derLen); - if (res) { - PrintAndLog("ERROR: DER parse returned 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res)); - } - - // get certificate info - char linfo[300] = {0}; - if (verbose) { - mbedtls_x509_crt_info(linfo, sizeof(linfo), " ", &cert); - PrintAndLog("DER certificate info:\n%s", linfo); - } - - // verify certificate - uint32_t verifyflags = 0; - res = mbedtls_x509_crt_verify(&cert, &cacert, NULL, NULL, &verifyflags, NULL, NULL); - if (res) { - PrintAndLog("ERROR: DER verify returned 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res)); - } else { - PrintAndLog("Certificate OK."); - } - - if (verbose) { - memset(linfo, 0x00, sizeof(linfo)); - mbedtls_x509_crt_verify_info(linfo, sizeof(linfo), " ", verifyflags); - PrintAndLog("Verification info:\n%s", linfo); - } - - // get public key - res = ecdsa_public_key_from_pk(&cert.pk, public_key, sizeof(public_key)); - if (res) { - PrintAndLog("ERROR: getting public key from certificate 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res)); - } else { - if (verbose) - PrintAndLog("Got a public key from certificate:\n%s", sprint_hex_inrow(public_key, 65)); - } - - if (verbose) - PrintAndLog("------------------DER-------------------"); - - mbedtls_x509_crt_free(&cert); - mbedtls_x509_crt_free(&cacert); + FIDOCheckDERAndGetKey(&buf[derp], derLen, verbose, public_key, sizeof(public_key)); // get hash int hashp = 1 + 65 + 1 + keyHandleLen + derLen; diff --git a/client/fido/fido2.json b/client/fido/fido2.json index 88abf48e1..c158ef117 100644 --- a/client/fido/fido2.json +++ b/client/fido/fido2.json @@ -24,6 +24,6 @@ ], "options": { "uv": false, - "rk": false, + "rk": false } } \ No newline at end of file diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 57a89560a..137b991f3 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -15,6 +15,12 @@ #include "emv/emvjson.h" #include #include "cbortools.h" +#include +#include +#include +#include "crypto/asn1utils.h" +#include "crypto/libpcrypto.h" +#include "fido/additional_ca.h" typedef struct { uint8_t ErrorCode; @@ -204,6 +210,67 @@ int FIDO2GetAssertion(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_ return FIDOExchange((sAPDU){0x80, 0x10, 0x00, 0x00, sizeof(data), data}, Result, MaxResultLen, ResultLen, sw); } +int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint8_t *publicKey, size_t publicKeyMaxLen) { + int res; + + // load CA's + mbedtls_x509_crt cacert; + mbedtls_x509_crt_init(&cacert); + res = mbedtls_x509_crt_parse(&cacert, (const unsigned char *) additional_ca_pem, additional_ca_pem_len); + if (res < 0) { + PrintAndLog("ERROR: CA parse certificate returned -0x%x - %s", -res, ecdsa_get_error(res)); + } + if (verbose) + PrintAndLog("CA load OK. %d skipped", res); + + // load DER certificate from authenticator's data + mbedtls_x509_crt cert; + mbedtls_x509_crt_init(&cert); + res = mbedtls_x509_crt_parse_der(&cert, der, derLen); + if (res) { + PrintAndLog("ERROR: DER parse returned 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res)); + } + + // get certificate info + char linfo[300] = {0}; + if (verbose) { + mbedtls_x509_crt_info(linfo, sizeof(linfo), " ", &cert); + PrintAndLog("DER certificate info:\n%s", linfo); + } + + // verify certificate + uint32_t verifyflags = 0; + res = mbedtls_x509_crt_verify(&cert, &cacert, NULL, NULL, &verifyflags, NULL, NULL); + if (res) { + PrintAndLog("ERROR: DER verify returned 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res)); + } else { + PrintAndLog("Certificate OK."); + } + + if (verbose) { + memset(linfo, 0x00, sizeof(linfo)); + mbedtls_x509_crt_verify_info(linfo, sizeof(linfo), " ", verifyflags); + PrintAndLog("Verification info:\n%s", linfo); + } + + // get public key + res = ecdsa_public_key_from_pk(&cert.pk, publicKey, publicKeyMaxLen); + if (res) { + PrintAndLog("ERROR: getting public key from certificate 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res)); + } else { + if (verbose) + PrintAndLog("Got a public key from certificate:\n%s", sprint_hex_inrow(publicKey, 65)); + } + + if (verbose) + PrintAndLog("------------------DER-------------------"); + + mbedtls_x509_crt_free(&cert); + mbedtls_x509_crt_free(&cacert); + + return 0; +} + #define fido_check_if(r) if ((r) != CborNoError) {return r;} else #define fido_check(r) if ((r) != CborNoError) return r; @@ -292,3 +359,5 @@ int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatale return 0; } + + diff --git a/client/fido/fidocore.h b/client/fido/fidocore.h index e87de1922..97c3f0f06 100644 --- a/client/fido/fidocore.h +++ b/client/fido/fidocore.h @@ -40,6 +40,8 @@ extern int FIDO2GetInfo(uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, extern int FIDO2MakeCredential(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); extern int FIDO2GetAssertion(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +extern int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint8_t *publicKey, size_t publicKeyMaxLen); + extern char *fido2GetCmdMemberDescription(uint8_t cmdCode, bool isResponse, uint8_t memberNum); extern char *fido2GetCmdErrorDescription(uint8_t errorCode); From 7943ba7d91005147944b8e439da031572df65878 Mon Sep 17 00:00:00 2001 From: Jean-Michel Picod Date: Thu, 22 Nov 2018 23:57:30 +0100 Subject: [PATCH 0226/1938] Fix logic op being used instead of bitwise op --- client/cmdsmartcard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index c9997f241..59172b9c8 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -344,7 +344,7 @@ int CmdSmartUpgrade(const char *Cmd) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); return 1; } - if ( (resp.arg[0] && 0xFF ) ) + if ( (resp.arg[0] & 0xFF ) ) PrintAndLogEx(SUCCESS, "Smartcard socket firmware upgraded successful"); else PrintAndLogEx(FAILED, "Smartcard socket firmware updating failed"); From a37082a825079238a891be747e23f346e993a045 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 23 Nov 2018 19:47:30 +0200 Subject: [PATCH 0227/1938] added some cbor tools --- client/fido/cbortools.c | 75 +++++++++++++++++++++++++++++++++++++++++ client/fido/cbortools.h | 5 +++ 2 files changed, 80 insertions(+) diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index 51041cefb..5c35bdae5 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -310,3 +310,78 @@ int JsonToCbor(json_t *elm, CborEncoder *encoder) { return 0; } + +int CborMapGetKeyById(CborParser *parser, CborValue *map, uint8_t *data, size_t dataLen, int key) { + CborValue cb; + + CborError err = cbor_parser_init(data, dataLen, 0, parser, &cb); + cbor_check(err); + + if (cbor_value_get_type(&cb) != CborMapType) + return 1; + + err = cbor_value_enter_container(&cb, map); + cbor_check(err); + + int64_t indx; + while (!cbor_value_at_end(map)) { + // check number + if (cbor_value_get_type(map) != CborIntegerType) + return 1; + + cbor_value_get_int64(map, &indx); + printf("--id %lld\n", (long long)indx); + + err = cbor_value_advance(map); + cbor_check(err); + + if (indx == key) + return 0; + + // pass value + err = cbor_value_advance(map); + cbor_check(err); + } + + err = cbor_value_leave_container(&cb, map); + cbor_check(err); + + return 2; +} + +CborError CborGetBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen) { + if (datalen) + *datalen = 0; + + size_t slen = 0; + + CborError res = cbor_value_copy_byte_string(elm, data, &slen, elm); + cbor_check(res); + + if (datalen) + *datalen = slen; + + return CborNoError; +}; + +CborError CborGetStringValue(CborValue *elm, char *data, size_t maxdatalen, size_t *datalen) { + if (datalen) + *datalen = 0; + + size_t slen = 0; + + CborError res = cbor_value_copy_text_string(elm, data, &slen, elm); + cbor_check(res); + + if (datalen) + *datalen = slen; + + return CborNoError; +}; + +CborError CborGetStringValueBuf(CborValue *elm) { + static char stringBuf[2048]; + memset(stringBuf, 0x00, sizeof(stringBuf)); + + return CborGetStringValue(elm, stringBuf, sizeof(stringBuf), NULL); +}; \ No newline at end of file diff --git a/client/fido/cbortools.h b/client/fido/cbortools.h index 4019f1f70..3d41c7db6 100644 --- a/client/fido/cbortools.h +++ b/client/fido/cbortools.h @@ -24,4 +24,9 @@ extern int TinyCborPrintFIDOPackage(uint8_t cmdCode, bool isResponse, uint8_t *data, size_t length); extern int JsonToCbor(json_t *elm, CborEncoder *encoder); +extern int CborMapGetKeyById(CborParser *parser, CborValue *map, uint8_t *data, size_t dataLen, int key); +extern CborError CborGetBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen); +extern CborError CborGetStringValue(CborValue *elm, char *data, size_t maxdatalen, size_t *datalen); +extern CborError CborGetStringValueBuf(CborValue *elm); + #endif /* __CBORTOOLS_H__ */ From c57a2c2c41c923943fa4a2ce9398eb25e49d4ad2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 23 Nov 2018 19:48:17 +0200 Subject: [PATCH 0228/1938] added map credential parsing. not completed --- client/cmdhffido.c | 137 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 137 insertions(+) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 19566075f..098ae7fa0 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -647,10 +647,144 @@ int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileNam return 0; } +int MakeCredentionalParseRes(uint8_t *data, size_t dataLen, bool verbose) { + CborParser parser; + CborValue map, mapsmt, array; + int res; + char *buf; + uint8_t *ubuf; + size_t n; + + // fmt + res = CborMapGetKeyById(&parser, &map, data, dataLen, 1); + if (res) + return res; + + res = cbor_value_dup_text_string(&map, &buf, &n, &map); + cbor_check(res); + PrintAndLog("format: %s", buf); + free(buf); + + // authData + res = CborMapGetKeyById(&parser, &map, data, dataLen, 2); + if (res) + return res; + res = cbor_value_dup_byte_string(&map, &ubuf, &n, &map); + cbor_check(res); + + PrintAndLog("authData: %s", sprint_hex(ubuf, n)); + + PrintAndLog("RP ID Hash: %s", sprint_hex(ubuf, 32)); + + // check RP ID Hash + + PrintAndLog("Flags 0x%02x:", ubuf[32]); + if (!ubuf[32]) + PrintAndLog("none"); + if (ubuf[32] & 0x01) + PrintAndLog("up - user presence"); + if (ubuf[32] & 0x04) + PrintAndLog("uv - user verification (fingerprint scan or a PIN or ...)"); + if (ubuf[32] & 0x40) + PrintAndLog("at - "); + if (ubuf[32] & 0x80) + PrintAndLog("ed - "); + + uint32_t cntr = (uint32_t)bytes_to_num(&ubuf[33], 4); + PrintAndLog("Counter: %d", cntr); + + // attestation data + PrintAndLog("AAGUID: %s", sprint_hex(&ubuf[37], 16)); + + // Credential ID + uint8_t cridlen = (uint16_t)bytes_to_num(&ubuf[53], 2); + PrintAndLog("Credential id[%d]: %s", cridlen, sprint_hex(&ubuf[55], cridlen)); + + //Credentional public key (COSE_KEY) + uint16_t cplen = n - 55 - cridlen; + PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s", cplen, sprint_hex(&ubuf[55 + cridlen], cplen)); + + free(ubuf); + + // attStmt - we are check only as DER certificate + int64_t alg = 0; + uint8_t sign[128] = {0}; + size_t signLen = 0; + uint8_t der[4097] = {0}; + size_t derLen = 0; + + res = CborMapGetKeyById(&parser, &map, data, dataLen, 3); + if (res) + return res; + + res = cbor_value_enter_container(&map, &mapsmt); + cbor_check(res); + +printf("--1\n"); + while (!cbor_value_at_end(&mapsmt)) { + char key[100] = {0}; + res = CborGetStringValue(&mapsmt, key, sizeof(key), &n); + cbor_check(res); + printf("--key: %s\n", key); + if (!strcmp(key, "alg")) { + cbor_value_get_int64(&mapsmt, &alg); + PrintAndLog("Alg [%lld]", (long long)alg); + res = cbor_value_advance_fixed(&mapsmt); + cbor_check(res); + } + + if (!strcmp(key, "sig")) { + res = CborGetBinStringValue(&mapsmt, sign, sizeof(sign), &signLen); + cbor_check(res); + PrintAndLog("signature [%d] %s", signLen, sprint_hex(sign, signLen)); + } + + if (!strcmp(key, "x5c")) { + res = CborGetBinStringValue(&mapsmt, der, sizeof(der), &derLen); + cbor_check(res); + PrintAndLog("signature [%d] %s", signLen, sprint_hex(der, derLen)); + } + } + res = cbor_value_leave_container(&map, &mapsmt); + cbor_check(res); + + +/* res = cbor_value_enter_container(&map, &array); + cbor_check(res); + CborType type = cbor_value_get_type(&array); + printf("--type:%d\n", type); + while (!cbor_value_at_end(&array)) { + res = cbor_value_dup_text_string(&array, &ubuf, &n, &array); + cbor_check(res); + PrintAndLog("DER: %s", ubuf); + PrintAndLog("DER: %s", sprint_hex(ubuf, n)); + } + res = cbor_value_leave_container(&map, &array); + cbor_check(res); + + PrintAndLog("DER: %s", ubuf); + PrintAndLog("DER: %s", sprint_hex(ubuf, n)); + + uint8_t public_key[65] = {0}; + + // print DER certificate in TLV view + if (true) { // showDERTLV + PrintAndLog("----------------DER TLV-----------------"); + asn1_print(ubuf, n, " "); + PrintAndLog("----------------DER TLV-----------------"); + } + FIDOCheckDERAndGetKey(ubuf, n, verbose, public_key, sizeof(public_key)); +*/ + free(ubuf); + + return 0; +} + int CmdHFFido2MakeCredential(const char *cmd) { json_error_t error; json_t *root = NULL; char fname[300] = {0}; + bool verbose = true; int res = GetExistsFileNameJson("fido", "fido2", fname); if(res) { @@ -713,6 +847,9 @@ int CmdHFFido2MakeCredential(const char *cmd) { PrintAndLog("CBOR make credentional response:"); TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1); + // parse returned cbor + MakeCredentionalParseRes(&buf[1], len - 1, verbose); + json_decref(root); return 0; From 0bbdc7f1500067febd4358a8d2a1fb9fc7ea177a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 24 Nov 2018 14:57:36 +0200 Subject: [PATCH 0229/1938] added CborGetArrayBinStringValue --- client/fido/cbortools.c | 39 +++++++++++++++++++++++++++++++++++---- client/fido/cbortools.h | 1 + 2 files changed, 36 insertions(+), 4 deletions(-) diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index 5c35bdae5..5bfb76b9a 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -329,8 +329,7 @@ int CborMapGetKeyById(CborParser *parser, CborValue *map, uint8_t *data, size_t if (cbor_value_get_type(map) != CborIntegerType) return 1; - cbor_value_get_int64(map, &indx); - printf("--id %lld\n", (long long)indx); + cbor_value_get_int64(map, &indx); err = cbor_value_advance(map); cbor_check(err); @@ -349,11 +348,43 @@ int CborMapGetKeyById(CborParser *parser, CborValue *map, uint8_t *data, size_t return 2; } +CborError CborGetArrayBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen, uint8_t *delimeter) { + CborValue array; + if (datalen) + *datalen = 0; + + size_t slen = maxdatalen; + size_t totallen = 0; + + CborError res = cbor_value_enter_container(elm, &array); + cbor_check(res); + + while (!cbor_value_at_end(&array)) { + res = cbor_value_copy_byte_string(&array, &data[totallen], &slen, &array); + cbor_check(res); + + totallen += slen; + if (delimeter) { + memcpy(&data[totallen], delimeter, 1); // TODO: multibyte + totallen += 1; + } + slen = maxdatalen - totallen; + } + + res = cbor_value_leave_container(elm, &array); + cbor_check(res); + + if (datalen) + *datalen = totallen; + + return CborNoError; +}; + CborError CborGetBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen) { if (datalen) *datalen = 0; - size_t slen = 0; + size_t slen = maxdatalen; CborError res = cbor_value_copy_byte_string(elm, data, &slen, elm); cbor_check(res); @@ -368,7 +399,7 @@ CborError CborGetStringValue(CborValue *elm, char *data, size_t maxdatalen, size if (datalen) *datalen = 0; - size_t slen = 0; + size_t slen = maxdatalen; CborError res = cbor_value_copy_text_string(elm, data, &slen, elm); cbor_check(res); diff --git a/client/fido/cbortools.h b/client/fido/cbortools.h index 3d41c7db6..4d8b023ee 100644 --- a/client/fido/cbortools.h +++ b/client/fido/cbortools.h @@ -25,6 +25,7 @@ extern int TinyCborPrintFIDOPackage(uint8_t cmdCode, bool isResponse, uint8_t *d extern int JsonToCbor(json_t *elm, CborEncoder *encoder); extern int CborMapGetKeyById(CborParser *parser, CborValue *map, uint8_t *data, size_t dataLen, int key); +extern CborError CborGetArrayBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen, uint8_t *delimeter); extern CborError CborGetBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen); extern CborError CborGetStringValue(CborValue *elm, char *data, size_t maxdatalen, size_t *datalen); extern CborError CborGetStringValueBuf(CborValue *elm); From 376abd2d9291534466e90a02d6828e144dcaee01 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 24 Nov 2018 14:57:55 +0200 Subject: [PATCH 0230/1938] get DER works --- client/cmdhffido.c | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 098ae7fa0..4ed0a8e1a 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -720,7 +720,6 @@ int MakeCredentionalParseRes(uint8_t *data, size_t dataLen, bool verbose) { res = cbor_value_enter_container(&map, &mapsmt); cbor_check(res); -printf("--1\n"); while (!cbor_value_at_end(&mapsmt)) { char key[100] = {0}; res = CborGetStringValue(&mapsmt, key, sizeof(key), &n); @@ -736,13 +735,13 @@ printf("--1\n"); if (!strcmp(key, "sig")) { res = CborGetBinStringValue(&mapsmt, sign, sizeof(sign), &signLen); cbor_check(res); - PrintAndLog("signature [%d] %s", signLen, sprint_hex(sign, signLen)); + PrintAndLog("signature [%d]: %s", signLen, sprint_hex(sign, signLen)); } if (!strcmp(key, "x5c")) { - res = CborGetBinStringValue(&mapsmt, der, sizeof(der), &derLen); + res = CborGetArrayBinStringValue(&mapsmt, der, sizeof(der), &derLen, NULL); cbor_check(res); - PrintAndLog("signature [%d] %s", signLen, sprint_hex(der, derLen)); + PrintAndLog("der [%d]: %s", derLen, sprint_hex(der, derLen)); } } res = cbor_value_leave_container(&map, &mapsmt); From 6c63e74ffb3e47d6594d585035ce4227ef1f6ec6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 24 Nov 2018 15:05:08 +0200 Subject: [PATCH 0231/1938] decode DER certificate --- client/cmdhffido.c | 34 ++++++++-------------------------- 1 file changed, 8 insertions(+), 26 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 4ed0a8e1a..9ee4e5f1a 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -647,9 +647,9 @@ int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileNam return 0; } -int MakeCredentionalParseRes(uint8_t *data, size_t dataLen, bool verbose) { +int MakeCredentionalParseRes(uint8_t *data, size_t dataLen, bool verbose, bool showDERTLV) { CborParser parser; - CborValue map, mapsmt, array; + CborValue map, mapsmt; int res; char *buf; uint8_t *ubuf; @@ -741,40 +741,21 @@ int MakeCredentionalParseRes(uint8_t *data, size_t dataLen, bool verbose) { if (!strcmp(key, "x5c")) { res = CborGetArrayBinStringValue(&mapsmt, der, sizeof(der), &derLen, NULL); cbor_check(res); - PrintAndLog("der [%d]: %s", derLen, sprint_hex(der, derLen)); + PrintAndLog("DER [%d]: %s", derLen, sprint_hex(der, derLen)); } } res = cbor_value_leave_container(&map, &mapsmt); cbor_check(res); - -/* res = cbor_value_enter_container(&map, &array); - cbor_check(res); - CborType type = cbor_value_get_type(&array); - printf("--type:%d\n", type); - while (!cbor_value_at_end(&array)) { - res = cbor_value_dup_text_string(&array, &ubuf, &n, &array); - cbor_check(res); - PrintAndLog("DER: %s", ubuf); - PrintAndLog("DER: %s", sprint_hex(ubuf, n)); - } - res = cbor_value_leave_container(&map, &array); - cbor_check(res); - - PrintAndLog("DER: %s", ubuf); - PrintAndLog("DER: %s", sprint_hex(ubuf, n)); - uint8_t public_key[65] = {0}; // print DER certificate in TLV view - if (true) { // showDERTLV + if (showDERTLV) { PrintAndLog("----------------DER TLV-----------------"); - asn1_print(ubuf, n, " "); + asn1_print(der, derLen, " "); PrintAndLog("----------------DER TLV-----------------"); } - FIDOCheckDERAndGetKey(ubuf, n, verbose, public_key, sizeof(public_key)); -*/ - free(ubuf); + FIDOCheckDERAndGetKey(der, derLen, verbose, public_key, sizeof(public_key)); return 0; } @@ -784,6 +765,7 @@ int CmdHFFido2MakeCredential(const char *cmd) { json_t *root = NULL; char fname[300] = {0}; bool verbose = true; + bool showDERTLV = true; int res = GetExistsFileNameJson("fido", "fido2", fname); if(res) { @@ -847,7 +829,7 @@ int CmdHFFido2MakeCredential(const char *cmd) { TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1); // parse returned cbor - MakeCredentionalParseRes(&buf[1], len - 1, verbose); + MakeCredentionalParseRes(&buf[1], len - 1, verbose, showDERTLV); json_decref(root); From 1a0f7e93dec69472042d0af2a7992af559f917f1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 24 Nov 2018 23:36:02 +0200 Subject: [PATCH 0232/1938] refactoring and some functions in cbortools --- client/cmdhffido.c | 2 +- client/fido/cbortools.c | 43 ++++++++++++++++++++++++++++++++++++++--- client/fido/cbortools.h | 4 +++- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 9ee4e5f1a..0e81aca6e 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -739,7 +739,7 @@ int MakeCredentionalParseRes(uint8_t *data, size_t dataLen, bool verbose, bool s } if (!strcmp(key, "x5c")) { - res = CborGetArrayBinStringValue(&mapsmt, der, sizeof(der), &derLen, NULL); + res = CborGetArrayBinStringValue(&mapsmt, der, sizeof(der), &derLen); cbor_check(res); PrintAndLog("DER [%d]: %s", derLen, sprint_hex(der, derLen)); } diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index 5bfb76b9a..cae5cdc7f 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -348,7 +348,11 @@ int CborMapGetKeyById(CborParser *parser, CborValue *map, uint8_t *data, size_t return 2; } -CborError CborGetArrayBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen, uint8_t *delimeter) { +CborError CborGetArrayBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen) { + return CborGetArrayBinStringValueEx(elm, data, maxdatalen, datalen, NULL, 0); +} + +CborError CborGetArrayBinStringValueEx(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen, uint8_t *delimeter, size_t delimeterlen) { CborValue array; if (datalen) *datalen = 0; @@ -365,8 +369,8 @@ CborError CborGetArrayBinStringValue(CborValue *elm, uint8_t *data, size_t maxda totallen += slen; if (delimeter) { - memcpy(&data[totallen], delimeter, 1); // TODO: multibyte - totallen += 1; + memcpy(&data[totallen], delimeter, delimeterlen); + totallen += delimeterlen; } slen = maxdatalen - totallen; } @@ -395,6 +399,39 @@ CborError CborGetBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen return CborNoError; }; +CborError CborGetArrayStringValue(CborValue *elm, char *data, size_t maxdatalen, size_t *datalen, char *delimeter) { + CborValue array; + if (datalen) + *datalen = 0; + + size_t slen = maxdatalen; + size_t totallen = 0; + + CborError res = cbor_value_enter_container(elm, &array); + cbor_check(res); + + while (!cbor_value_at_end(&array)) { + res = cbor_value_copy_text_string(&array, &data[totallen], &slen, &array); + cbor_check(res); + + totallen += slen; + if (delimeter) { + strcat(data, delimeter); + totallen += strlen(delimeter); + } + slen = maxdatalen - totallen; + data[totallen] = 0x00; + } + + res = cbor_value_leave_container(elm, &array); + cbor_check(res); + + if (datalen) + *datalen = totallen; + + return CborNoError; +}; + CborError CborGetStringValue(CborValue *elm, char *data, size_t maxdatalen, size_t *datalen) { if (datalen) *datalen = 0; diff --git a/client/fido/cbortools.h b/client/fido/cbortools.h index 4d8b023ee..a57b4b761 100644 --- a/client/fido/cbortools.h +++ b/client/fido/cbortools.h @@ -25,8 +25,10 @@ extern int TinyCborPrintFIDOPackage(uint8_t cmdCode, bool isResponse, uint8_t *d extern int JsonToCbor(json_t *elm, CborEncoder *encoder); extern int CborMapGetKeyById(CborParser *parser, CborValue *map, uint8_t *data, size_t dataLen, int key); -extern CborError CborGetArrayBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen, uint8_t *delimeter); +extern CborError CborGetArrayBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen); +extern CborError CborGetArrayBinStringValueEx(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen, uint8_t *delimeter, size_t delimeterlen); extern CborError CborGetBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen); +extern CborError CborGetArrayStringValue(CborValue *elm, char *data, size_t maxdatalen, size_t *datalen, char *delimeter); extern CborError CborGetStringValue(CborValue *elm, char *data, size_t maxdatalen, size_t *datalen); extern CborError CborGetStringValueBuf(CborValue *elm); From 9e89da3c0cbf93964ffaeaf84ef50a5170af4826 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 25 Nov 2018 00:12:06 +0200 Subject: [PATCH 0233/1938] remove debug --- client/cmdhffido.c | 1 - client/fido/cbortools.c | 2 +- 2 files changed, 1 insertion(+), 2 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 0e81aca6e..7969b7b94 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -724,7 +724,6 @@ int MakeCredentionalParseRes(uint8_t *data, size_t dataLen, bool verbose, bool s char key[100] = {0}; res = CborGetStringValue(&mapsmt, key, sizeof(key), &n); cbor_check(res); - printf("--key: %s\n", key); if (!strcmp(key, "alg")) { cbor_value_get_int64(&mapsmt, &alg); PrintAndLog("Alg [%lld]", (long long)alg); diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index cae5cdc7f..1693e6858 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -452,4 +452,4 @@ CborError CborGetStringValueBuf(CborValue *elm) { memset(stringBuf, 0x00, sizeof(stringBuf)); return CborGetStringValue(elm, stringBuf, sizeof(stringBuf), NULL); -}; \ No newline at end of file +}; From 3beb14a25c51e51c1c527173ac72ff79fb31f5db Mon Sep 17 00:00:00 2001 From: Chris Date: Sun, 25 Nov 2018 14:35:47 +0100 Subject: [PATCH 0234/1938] chg: 'hf iclass lookup' - its not an online command... --- client/cmdhficlass.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 368aaad2e..6cc2aa191 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -2290,7 +2290,6 @@ int CmdHFiClassLookUp(const char *Cmd) { t1 = msclock() - t1; PrintAndLogEx(NORMAL, "\nTime in iclass : %.0f seconds\n", (float)t1/1000.0); - DropField(); free(prekey); free(keyBlock); PrintAndLogEx(NORMAL, ""); @@ -2527,7 +2526,7 @@ static command_t CommandTable[] = { {"encryptblk", CmdHFiClassEncryptBlk, 1, " Encrypt given block data"}, {"list", CmdHFiClassList, 0, " (Deprecated) List iClass history"}, {"loclass", CmdHFiClass_loclass, 1, "[options..] Use loclass to perform bruteforce of reader attack dump"}, - {"lookup", CmdHFiClassLookUp, 0, "[options..] Uses authentication trace to check for key in dictionary file"}, + {"lookup", CmdHFiClassLookUp, 1, "[options..] Uses authentication trace to check for key in dictionary file"}, {"managekeys", CmdHFiClassManageKeys, 1, "[options..] Manage the keys to use with iClass"}, {"permutekey", CmdHFiClassPermuteKey, 0, " Permute function from 'heart of darkness' paper"}, {"readblk", CmdHFiClass_ReadBlock, 0, "[options..] Authenticate and Read iClass block"}, From 1099c6923d44ba293f84bf78f3c8b19eb9f665a3 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Nov 2018 16:12:28 +0200 Subject: [PATCH 0235/1938] added COSE algorithms --- client/Makefile | 1 + client/cmdhffido.c | 3 +- client/fido/cose.c | 130 +++++++++++++++++++++++++++++++++++++++++ client/fido/cose.h | 23 ++++++++ client/fido/fidocore.c | 2 +- 5 files changed, 157 insertions(+), 2 deletions(-) create mode 100644 client/fido/cose.c create mode 100644 client/fido/cose.h diff --git a/client/Makefile b/client/Makefile index 1e88e5dc9..766163c09 100644 --- a/client/Makefile +++ b/client/Makefile @@ -111,6 +111,7 @@ CMDSRCS = crapto1/crapto1.c \ mfkey.c \ tea.c \ fido/additional_ca.c \ + fido/cose.c \ fido/cbortools.c \ fido/fidocore.c \ crypto/asn1dump.c \ diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 7969b7b94..8b0ceb2f7 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -45,6 +45,7 @@ #include "crypto/libpcrypto.h" #include "fido/cbortools.h" #include "fido/fidocore.h" +#include "fido/cose.h" static int CmdHelp(const char *Cmd); @@ -726,7 +727,7 @@ int MakeCredentionalParseRes(uint8_t *data, size_t dataLen, bool verbose, bool s cbor_check(res); if (!strcmp(key, "alg")) { cbor_value_get_int64(&mapsmt, &alg); - PrintAndLog("Alg [%lld]", (long long)alg); + PrintAndLog("Alg [%lld] %s", (long long)alg, GetCOSEAlgDescription(alg)); res = cbor_value_advance_fixed(&mapsmt); cbor_check(res); } diff --git a/client/fido/cose.c b/client/fido/cose.c new file mode 100644 index 000000000..17f1e71b3 --- /dev/null +++ b/client/fido/cose.c @@ -0,0 +1,130 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Tools for work with COSE (CBOR Object Signing and Encryption) rfc8152 +// https://tools.ietf.org/html/rfc8152 +//----------------------------------------------------------------------------- +// + +#include "cose.h" +#include "util.h" + +static const char COSEEmptyStr[] = ""; + +typedef struct { + int Value; + char *Name; + char *Description; +} COSEValueNameDesc_t; + +typedef struct { + int Value; + char *Type; + char *Name; + char *Description; +} COSEValueTypeNameDesc_t; + +// kty - Key Type Values +COSEValueNameDesc_t COSEKeyTypeValueDesc[] = { + {0, "Reserved", "Reserved"}, + {1, "OKP", "Octet Key Pair"}, + {2, "EC2", "Elliptic Curve Key w/ x- and y-coordinate pair"}, + {4, "Symmetric", "Symmetric Key"}, +}; + +// keys +COSEValueTypeNameDesc_t COSEKeyTypeDesc[] = { + {1, "EC2", "P-256", "NIST P-256 also known as secp256r1"}, + {2, "EC2", "P-384", "NIST P-384 also known as secp384r1"}, + {3, "EC2", "P-521", "NIST P-521 also known as secp521r1"}, + {4, "OKP", "X25519", "X25519 for use w/ ECDH only"}, + {5, "OKP", "X448", "X448 for use w/ ECDH only"}, + {6, "OKP", "Ed25519", "Ed25519 for use w/ EdDSA only"}, + {7, "OKP", "Ed448", "Ed448 for use w/ EdDSA only"}, +}; + +// RFC8152 https://www.iana.org/assignments/cose/cose.xhtml#algorithms +COSEValueNameDesc_t COSEAlg[] = { + {-65536, "Unassigned", "Unassigned"}, + {-65535, "RS1", "RSASSA-PKCS1-v1_5 w/ SHA-1"}, + {-259, "RS512", "RSASSA-PKCS1-v1_5 w/ SHA-512"}, + {-258, "RS384", "RSASSA-PKCS1-v1_5 w/ SHA-384"}, + {-257, "RS256", "RSASSA-PKCS1-v1_5 w/ SHA-256"}, + {-42, "RSAES-OAEP w/ SHA-512", "RSAES-OAEP w/ SHA-512"}, + {-41, "RSAES-OAEP w/ SHA-256", "RSAES-OAEP w/ SHA-256"}, + {-40, "RSAES-OAEP w/ RFC 8017 def param", "RSAES-OAEP w/ SHA-1"}, + {-39, "PS512", "RSASSA-PSS w/ SHA-512"}, + {-38, "PS384", "RSASSA-PSS w/ SHA-384"}, + {-37, "PS256", "RSASSA-PSS w/ SHA-256"}, + {-36, "ES512", "ECDSA w/ SHA-512"}, + {-35, "ES384", "ECDSA w/ SHA-384"}, + {-34, "ECDH-SS + A256KW", "ECDH SS w/ Concat KDF and AES Key Wrap w/ 256-bit key"}, + {-33, "ECDH-SS + A192KW", "ECDH SS w/ Concat KDF and AES Key Wrap w/ 192-bit key"}, + {-32, "ECDH-SS + A128KW", "ECDH SS w/ Concat KDF and AES Key Wrap w/ 128-bit key"}, + {-31, "ECDH-ES + A256KW", "ECDH ES w/ Concat KDF and AES Key Wrap w/ 256-bit key"}, + {-30, "ECDH-ES + A192KW", "ECDH ES w/ Concat KDF and AES Key Wrap w/ 192-bit key"}, + {-29, "ECDH-ES + A128KW", "ECDH ES w/ Concat KDF and AES Key Wrap w/ 128-bit key"}, + {-28, "ECDH-SS + HKDF-512", "ECDH SS w/ HKDF - generate key directly"}, + {-27, "ECDH-SS + HKDF-256", "ECDH SS w/ HKDF - generate key directly"}, + {-26, "ECDH-ES + HKDF-512", "ECDH ES w/ HKDF - generate key directly"}, + {-25, "ECDH-ES + HKDF-256", "ECDH ES w/ HKDF - generate key directly"}, + {-13, "direct+HKDF-AES-256", "Shared secret w/ AES-MAC 256-bit key"}, + {-12, "direct+HKDF-AES-128", "Shared secret w/ AES-MAC 128-bit key"}, + {-11, "direct+HKDF-SHA-512", "Shared secret w/ HKDF and SHA-512"}, + {-10, "direct+HKDF-SHA-256", "Shared secret w/ HKDF and SHA-256"}, + {-8, "EdDSA", "EdDSA"}, + {-7, "ES256", "ECDSA w/ SHA-256"}, + {-6, "direct", "Direct use of CEK"}, + {-5, "A256KW", "AES Key Wrap w/ 256-bit key"}, + {-4, "A192KW", "AES Key Wrap w/ 192-bit key"}, + {-3, "A128KW", "AES Key Wrap w/ 128-bit key"}, + {0, "Reserved", "Reserved"}, + {1, "A128GCM", "AES-GCM mode w/ 128-bit key, 128-bit tag"}, + {2, "A192GCM", "AES-GCM mode w/ 192-bit key, 128-bit tag"}, + {3, "A256GCM", "AES-GCM mode w/ 256-bit key, 128-bit tag"}, + {4, "HMAC 256/64", "HMAC w/ SHA-256 truncated to 64 bits"}, + {5, "HMAC 256/256", "HMAC w/ SHA-256"}, + {6, "HMAC 384/384", "HMAC w/ SHA-384"}, + {7, "HMAC 512/512", "HMAC w/ SHA-512"}, + {10, "AES-CCM-16-64-128", "AES-CCM mode 128-bit key, 64-bit tag, 13-byte nonce"}, + {11, "AES-CCM-16-64-256", "AES-CCM mode 256-bit key, 64-bit tag, 13-byte nonce"}, + {12, "AES-CCM-64-64-128", "AES-CCM mode 128-bit key, 64-bit tag, 7-byte nonce"}, + {13, "AES-CCM-64-64-256", "AES-CCM mode 256-bit key, 64-bit tag, 7-byte nonce"}, + {14, "AES-MAC 128/64", "AES-MAC 128-bit key, 64-bit tag"}, + {15, "AES-MAC 256/64", "AES-MAC 256-bit key, 64-bit tag"}, + {24, "ChaCha20/Poly1305", "ChaCha20/Poly1305 w/ 256-bit key, 128-bit tag"}, + {25, "AES-MAC 128/128", "AES-MAC 128-bit key, 128-bit tag"}, + {26, "AES-MAC 256/128", "AES-MAC 256-bit key, 128-bit tag"}, + {30, "AES-CCM-16-128-128", "AES-CCM mode 128-bit key, 128-bit tag, 13-byte nonce"}, + {31, "AES-CCM-16-128-256", "AES-CCM mode 256-bit key, 128-bit tag, 13-byte nonce"}, + {32, "AES-CCM-64-128-128", "AES-CCM mode 128-bit key, 128-bit tag, 7-byte nonce"}, + {33, "AES-CCM-64-128-256", "AES-CCM mode 256-bit key, 128-bit tag, 7-byte nonce"} +}; + +COSEValueNameDesc_t *GetCOSEAlgElm(int id) { + for (int i = 0; i < ARRAYLEN(COSEAlg); i++) + if (COSEAlg[i].Value == id) + return &COSEAlg[i]; + return NULL; +} + +const char *GetCOSEAlgName(int id) { + COSEValueNameDesc_t *elm = GetCOSEAlgElm(id); + if (elm) + return elm->Name; + return COSEEmptyStr; +} + +const char *GetCOSEAlgDescription(int id) { + COSEValueNameDesc_t *elm = GetCOSEAlgElm(id); + if (elm) + return elm->Description; + return COSEEmptyStr; +} + + + diff --git a/client/fido/cose.h b/client/fido/cose.h new file mode 100644 index 000000000..e8feb6d3f --- /dev/null +++ b/client/fido/cose.h @@ -0,0 +1,23 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2018 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Tools for work with COSE (CBOR Object Signing and Encryption) rfc8152 +// https://tools.ietf.org/html/rfc8152 +//----------------------------------------------------------------------------- +// + +#ifndef __COSE_H__ +#define __COSE_H__ + +#include +#include +#include + +extern const char *GetCOSEAlgName(int id); +extern const char *GetCOSEAlgDescription(int id); + +#endif /* __COSE_H__ */ diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 137b991f3..2df34b5ef 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -29,7 +29,7 @@ typedef struct { } fido2Error_t; fido2Error_t fido2Errors[] = { - {0xFF, "n/a", "n/a"}, + {0xFF, "n/a", "n/a"}, {0x00, "CTAP1_ERR_SUCCESS", "Indicates successful response."}, {0x01, "CTAP1_ERR_INVALID_COMMAND", "The command is not a valid CTAP command."}, {0x02, "CTAP1_ERR_INVALID_PARAMETER", "The command included an invalid parameter."}, From b67bcac28e318a2b57d024cff5ad256b3c983efd Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Nov 2018 17:38:45 +0200 Subject: [PATCH 0236/1938] check rpIdHash and unpack signature ok --- client/cmdhffido.c | 58 ++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 54 insertions(+), 4 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 8b0ceb2f7..d8ead11ad 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -648,7 +648,17 @@ int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileNam return 0; } -int MakeCredentionalParseRes(uint8_t *data, size_t dataLen, bool verbose, bool showDERTLV) { +bool CheckHash(json_t *json, uint8_t *hash) { + char hashval[300] = {0}; + uint8_t hash2[32] = {0}; + + JsonLoadStr(json, "$.RelyingPartyEntity.id", hashval); + sha256hash((uint8_t *)hashval, strlen(hashval), hash2); + + return !memcmp(hash, hash2, 32); +} + +int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool showDERTLV) { CborParser parser; CborValue map, mapsmt; int res; @@ -667,17 +677,26 @@ int MakeCredentionalParseRes(uint8_t *data, size_t dataLen, bool verbose, bool s free(buf); // authData + uint8_t authDataStatic[37] = {0}; res = CborMapGetKeyById(&parser, &map, data, dataLen, 2); if (res) return res; res = cbor_value_dup_byte_string(&map, &ubuf, &n, &map); cbor_check(res); + if (n >= 37) + memcpy(authDataStatic, ubuf, 37); + PrintAndLog("authData: %s", sprint_hex(ubuf, n)); PrintAndLog("RP ID Hash: %s", sprint_hex(ubuf, 32)); // check RP ID Hash + if (CheckHash(root, ubuf)) { + PrintAndLog("rpIdHash OK."); + } else { + PrintAndLog("rpIdHash ERROR!"); + } PrintAndLog("Flags 0x%02x:", ubuf[32]); if (!ubuf[32]) @@ -704,9 +723,9 @@ int MakeCredentionalParseRes(uint8_t *data, size_t dataLen, bool verbose, bool s //Credentional public key (COSE_KEY) uint16_t cplen = n - 55 - cridlen; PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s", cplen, sprint_hex(&ubuf[55 + cridlen], cplen)); - - free(ubuf); + free(ubuf); + // attStmt - we are check only as DER certificate int64_t alg = 0; uint8_t sign[128] = {0}; @@ -756,6 +775,37 @@ int MakeCredentionalParseRes(uint8_t *data, size_t dataLen, bool verbose, bool s PrintAndLog("----------------DER TLV-----------------"); } FIDOCheckDERAndGetKey(der, derLen, verbose, public_key, sizeof(public_key)); + + // check ANSI X9.62 format ECDSA signature (on P-256) + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; + res = ecdsa_asn1_get_signature(sign, signLen, rval, sval); + if (!res) { + if (verbose) { + PrintAndLog(" r: %s", sprint_hex(rval, 32)); + PrintAndLog(" s: %s", sprint_hex(sval, 32)); + } + + uint8_t xbuf[4096] = {0}; + size_t xbuflen = 0; + res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, + authDataStatic, 37, // rpIdHash[32] + flags[1] + signCount[4] + &data[0], 32, // Hash of the serialized client data + NULL, 0); + //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); + res = ecdsa_signature_verify(public_key, xbuf, xbuflen, sign, signLen); + if (res) { + if (res == -0x4e00) { + PrintAndLog("Signature is NOT VALID."); + } else { + PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); + } + } else { + PrintAndLog("Signature is OK."); + } + } else { + PrintAndLog("Invalid signature. res=%d.", res); + } return 0; } @@ -829,7 +879,7 @@ int CmdHFFido2MakeCredential(const char *cmd) { TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1); // parse returned cbor - MakeCredentionalParseRes(&buf[1], len - 1, verbose, showDERTLV); + MakeCredentionalParseRes(root, &buf[1], len - 1, verbose, showDERTLV); json_decref(root); From 705d0b7a6b2ccd4e3a75f15cea589e8fe4519c8d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Nov 2018 17:52:02 +0200 Subject: [PATCH 0237/1938] added signature verify --- client/cmdhffido.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index d8ead11ad..4adc4e60d 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -648,7 +648,7 @@ int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileNam return 0; } -bool CheckHash(json_t *json, uint8_t *hash) { +bool CheckrpIdHash(json_t *json, uint8_t *hash) { char hashval[300] = {0}; uint8_t hash2[32] = {0}; @@ -692,7 +692,7 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v PrintAndLog("RP ID Hash: %s", sprint_hex(ubuf, 32)); // check RP ID Hash - if (CheckHash(root, ubuf)) { + if (CheckrpIdHash(root, ubuf)) { PrintAndLog("rpIdHash OK."); } else { PrintAndLog("rpIdHash ERROR!"); @@ -786,13 +786,21 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v PrintAndLog(" s: %s", sprint_hex(sval, 32)); } + uint8_t clientDataHash[32] = {0}; + size_t clientDataHashLen = 0; + res = JsonLoadBufAsHex(root, "$.ClientDataHash", clientDataHash, sizeof(clientDataHash), &clientDataHashLen); + if (res || clientDataHashLen != 32) { + PrintAndLog("ERROR: Can't get clientDataHash from json!"); + return 2; + } + uint8_t xbuf[4096] = {0}; size_t xbuflen = 0; res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, authDataStatic, 37, // rpIdHash[32] + flags[1] + signCount[4] - &data[0], 32, // Hash of the serialized client data + clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json NULL, 0); - //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); + PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); res = ecdsa_signature_verify(public_key, xbuf, xbuflen, sign, signLen); if (res) { if (res == -0x4e00) { From 44ed826840ad9dedba20a1cde55cbbb6bdde87c0 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Nov 2018 17:54:50 +0200 Subject: [PATCH 0238/1938] added hints --- client/cmdhffido.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 4adc4e60d..1d082f868 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -702,13 +702,13 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v if (!ubuf[32]) PrintAndLog("none"); if (ubuf[32] & 0x01) - PrintAndLog("up - user presence"); + PrintAndLog("up - user presence result"); if (ubuf[32] & 0x04) - PrintAndLog("uv - user verification (fingerprint scan or a PIN or ...)"); + PrintAndLog("uv - user verification (fingerprint scan or a PIN or ...) result"); if (ubuf[32] & 0x40) - PrintAndLog("at - "); + PrintAndLog("at - attested credential data included"); if (ubuf[32] & 0x80) - PrintAndLog("ed - "); + PrintAndLog("ed - extension data included"); uint32_t cntr = (uint32_t)bytes_to_num(&ubuf[33], 4); PrintAndLog("Counter: %d", cntr); From b9c4bd1e0cd9430cc2369363c94ef7a8a97ff0f4 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Nov 2018 18:30:14 +0200 Subject: [PATCH 0239/1938] added showing cose_key in cbor text type --- client/cmdhffido.c | 7 +++++++ client/fido/cose.c | 5 +++++ client/fido/cose.h | 2 ++ client/fido/fidocore.c | 11 +++++++++-- client/fido/fidocore.h | 5 ++++- 5 files changed, 27 insertions(+), 3 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 1d082f868..97e48b3ec 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -721,8 +721,15 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v PrintAndLog("Credential id[%d]: %s", cridlen, sprint_hex(&ubuf[55], cridlen)); //Credentional public key (COSE_KEY) + uint8_t coseKey[65] = {0}; uint16_t cplen = n - 55 - cridlen; PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s", cplen, sprint_hex(&ubuf[55 + cridlen], cplen)); + if (verbose) { + TinyCborPrintFIDOPackage(fido2COSEKey, true, &ubuf[55 + cridlen], cplen); + } + res = COSEGetECDSAKey(&ubuf[55 + cridlen], cplen, verbose, coseKey); + if (res) + PrintAndLog("ERROR: Can't get COSE_KEY."); free(ubuf); diff --git a/client/fido/cose.c b/client/fido/cose.c index 17f1e71b3..90bb66308 100644 --- a/client/fido/cose.c +++ b/client/fido/cose.c @@ -126,5 +126,10 @@ const char *GetCOSEAlgDescription(int id) { return COSEEmptyStr; } +int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public_key) { + + + return 0; +} diff --git a/client/fido/cose.h b/client/fido/cose.h index e8feb6d3f..1b685e4a8 100644 --- a/client/fido/cose.h +++ b/client/fido/cose.h @@ -20,4 +20,6 @@ extern const char *GetCOSEAlgName(int id); extern const char *GetCOSEAlgDescription(int id); +extern int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public_key); + #endif /* __COSE_H__ */ diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 2df34b5ef..c65959eff 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -82,7 +82,7 @@ fido2Error_t fido2Errors[] = { typedef struct { fido2Commands Command; fido2PacketType PckType; - uint8_t MemberNumber; + int MemberNumber; char *Description; } fido2Desc_t; @@ -139,6 +139,13 @@ fido2Desc_t fido2CmdGetInfoRespDesc[] = { {fido2CmdClientPIN, ptQuery, 0x06, "pinHashEnc"}, {fido2CmdClientPIN, ptQuery, 0x07, "getKeyAgreement"}, {fido2CmdClientPIN, ptQuery, 0x08, "getRetries"}, + + {fido2COSEKey, ptResponse, 0x01, "kty"}, + {fido2COSEKey, ptResponse, 0x03, "alg"}, + {fido2COSEKey, ptResponse, -1, "crv"}, + {fido2COSEKey, ptResponse, -2, "x - coordinate"}, + {fido2COSEKey, ptResponse, -3, "y - coordinate"}, + {fido2COSEKey, ptResponse, -4, "d - private key"}, }; char *fido2GetCmdErrorDescription(uint8_t errorCode) { @@ -149,7 +156,7 @@ char *fido2GetCmdErrorDescription(uint8_t errorCode) { return fido2Errors[0].Description; } -char *fido2GetCmdMemberDescription(uint8_t cmdCode, bool isResponse, uint8_t memberNum) { +char *fido2GetCmdMemberDescription(uint8_t cmdCode, bool isResponse, int memberNum) { for (int i = 0; i < sizeof(fido2CmdGetInfoRespDesc) / sizeof(fido2Desc_t); i++) if (fido2CmdGetInfoRespDesc[i].Command == cmdCode && fido2CmdGetInfoRespDesc[i].PckType == (isResponse ? ptResponse : ptQuery) && diff --git a/client/fido/fidocore.h b/client/fido/fidocore.h index 97c3f0f06..5d6dc4be1 100644 --- a/client/fido/fidocore.h +++ b/client/fido/fidocore.h @@ -25,6 +25,9 @@ typedef enum { fido2CmdClientPIN = 0x06, fido2CmdReset = 0x07, fido2CmdGetNextAssertion = 0x08, + + // another data + fido2COSEKey = 0xF0 } fido2Commands; typedef enum { @@ -42,7 +45,7 @@ extern int FIDO2GetAssertion(uint8_t *params, uint8_t paramslen, uint8_t *Result extern int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint8_t *publicKey, size_t publicKeyMaxLen); -extern char *fido2GetCmdMemberDescription(uint8_t cmdCode, bool isResponse, uint8_t memberNum); +extern char *fido2GetCmdMemberDescription(uint8_t cmdCode, bool isResponse, int memberNum); extern char *fido2GetCmdErrorDescription(uint8_t errorCode); extern int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen); From b0e0ccb05fc894fe175677482a7ed248fd6c7e27 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Nov 2018 18:37:21 +0200 Subject: [PATCH 0240/1938] added showCBOR --- client/cmdhffido.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 97e48b3ec..9ad988135 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -658,7 +658,7 @@ bool CheckrpIdHash(json_t *json, uint8_t *hash) { return !memcmp(hash, hash2, 32); } -int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool showDERTLV) { +int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool showCBOR, bool showDERTLV) { CborParser parser; CborValue map, mapsmt; int res; @@ -724,7 +724,7 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v uint8_t coseKey[65] = {0}; uint16_t cplen = n - 55 - cridlen; PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s", cplen, sprint_hex(&ubuf[55 + cridlen], cplen)); - if (verbose) { + if (showCBOR) { TinyCborPrintFIDOPackage(fido2COSEKey, true, &ubuf[55 + cridlen], cplen); } res = COSEGetECDSAKey(&ubuf[55 + cridlen], cplen, verbose, coseKey); @@ -831,6 +831,7 @@ int CmdHFFido2MakeCredential(const char *cmd) { char fname[300] = {0}; bool verbose = true; bool showDERTLV = true; + bool showCBOR = true; int res = GetExistsFileNameJson("fido", "fido2", fname); if(res) { @@ -869,8 +870,10 @@ int CmdHFFido2MakeCredential(const char *cmd) { if (res) return res; - PrintAndLog("CBOR make credentional request:"); - TinyCborPrintFIDOPackage(fido2CmdMakeCredential, false, data, datalen); + if (showCBOR) { + PrintAndLog("CBOR make credentional request:"); + TinyCborPrintFIDOPackage(fido2CmdMakeCredential, false, data, datalen); + } res = FIDO2MakeCredential(data, datalen, buf, sizeof(buf), &len, &sw); DropField(); @@ -890,11 +893,13 @@ int CmdHFFido2MakeCredential(const char *cmd) { } PrintAndLog("MakeCredential result (%d b) OK.", len); - PrintAndLog("CBOR make credentional response:"); - TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1); + if (showCBOR) { + PrintAndLog("CBOR make credentional response:"); + TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1); + } // parse returned cbor - MakeCredentionalParseRes(root, &buf[1], len - 1, verbose, showDERTLV); + MakeCredentionalParseRes(root, &buf[1], len - 1, verbose, showCBOR, showDERTLV); json_decref(root); From 1f3086a028307a8c79ed24f280576cd4ab92adbf Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Nov 2018 18:39:31 +0200 Subject: [PATCH 0241/1938] added json save --- client/cmdhffido.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 9ad988135..e32d5d9ed 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -901,6 +901,15 @@ int CmdHFFido2MakeCredential(const char *cmd) { // parse returned cbor MakeCredentionalParseRes(root, &buf[1], len - 1, verbose, showCBOR, showDERTLV); + if (root) { + res = json_dump_file(root, fname, JSON_INDENT(2)); + if (res) { + PrintAndLog("ERROR: can't save the file: %s", fname); + return 200; + } + PrintAndLog("File `%s` saved.", fname); + } + json_decref(root); return 0; From 56c9270574beefa10b4f568538bb22514b8e0939 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Nov 2018 18:57:44 +0200 Subject: [PATCH 0242/1938] added json save values --- client/cmdhffido.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index e32d5d9ed..378d69227 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -712,24 +712,30 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v uint32_t cntr = (uint32_t)bytes_to_num(&ubuf[33], 4); PrintAndLog("Counter: %d", cntr); + JsonSaveInt(root, "$.AppData.Counter", cntr); // attestation data PrintAndLog("AAGUID: %s", sprint_hex(&ubuf[37], 16)); + JsonSaveBufAsHexCompact(root, "$.AppData.AAGUID", &ubuf[37], 16); // Credential ID uint8_t cridlen = (uint16_t)bytes_to_num(&ubuf[53], 2); PrintAndLog("Credential id[%d]: %s", cridlen, sprint_hex(&ubuf[55], cridlen)); + JsonSaveBufAsHexCompact(root, "$.AppData.CredentialId", &ubuf[55], cridlen); //Credentional public key (COSE_KEY) uint8_t coseKey[65] = {0}; uint16_t cplen = n - 55 - cridlen; PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s", cplen, sprint_hex(&ubuf[55 + cridlen], cplen)); + JsonSaveBufAsHexCompact(root, "$.AppData.COSE_KEY", &ubuf[55 + cridlen], cplen); if (showCBOR) { TinyCborPrintFIDOPackage(fido2COSEKey, true, &ubuf[55 + cridlen], cplen); } res = COSEGetECDSAKey(&ubuf[55 + cridlen], cplen, verbose, coseKey); if (res) PrintAndLog("ERROR: Can't get COSE_KEY."); + else + JsonSaveBufAsHexCompact(root, "$.AppData.COSEPublicKey", coseKey, sizeof(coseKey)); free(ubuf); @@ -768,6 +774,7 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v res = CborGetArrayBinStringValue(&mapsmt, der, sizeof(der), &derLen); cbor_check(res); PrintAndLog("DER [%d]: %s", derLen, sprint_hex(der, derLen)); + JsonSaveBufAsHexCompact(root, "$.AppData.DER", der, derLen); } } res = cbor_value_leave_container(&map, &mapsmt); @@ -782,6 +789,7 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v PrintAndLog("----------------DER TLV-----------------"); } FIDOCheckDERAndGetKey(der, derLen, verbose, public_key, sizeof(public_key)); + JsonSaveBufAsHexCompact(root, "$.AppData.DERPublicKey", public_key, sizeof(public_key)); // check ANSI X9.62 format ECDSA signature (on P-256) uint8_t rval[300] = {0}; From f7354c705d48ef5f5164fe6ede027238a4770b3c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Nov 2018 19:16:47 +0200 Subject: [PATCH 0243/1938] extract some descriptions from cose_key --- client/fido/cose.c | 49 ++++++++++++++++++++++++++++++++++++++++++++++ client/fido/cose.h | 1 + 2 files changed, 50 insertions(+) diff --git a/client/fido/cose.c b/client/fido/cose.c index 90bb66308..bc86fee65 100644 --- a/client/fido/cose.c +++ b/client/fido/cose.c @@ -11,6 +11,8 @@ // #include "cose.h" +#include +#include "cbortools.h" #include "util.h" static const char COSEEmptyStr[] = ""; @@ -126,8 +128,55 @@ const char *GetCOSEAlgDescription(int id) { return COSEEmptyStr; } +COSEValueNameDesc_t *GetCOSEktyElm(int id) { + for (int i = 0; i < ARRAYLEN(COSEKeyTypeValueDesc); i++) + if (COSEKeyTypeValueDesc[i].Value == id) + return &COSEKeyTypeValueDesc[i]; + return NULL; +} + +const char *GetCOSEktyDescription(int id) { + COSEValueNameDesc_t *elm = GetCOSEktyElm(id); + if (elm) + return elm->Description; + return COSEEmptyStr; +} + int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public_key) { + CborParser parser; + CborValue map; + int64_t i64; + + if(verbose) + PrintAndLog("----------- CBOR decode ----------------"); + // kty + int res = CborMapGetKeyById(&parser, &map, data, datalen, 1); + if(!res) { + cbor_value_get_int64(&map, &i64); + if(verbose) + PrintAndLog("kty [%lld] %s", (long long)i64, GetCOSEktyDescription(i64)); + } + + // algorithm + res = CborMapGetKeyById(&parser, &map, data, datalen, 3); + if(!res) { + cbor_value_get_int64(&map, &i64); + if(verbose) + PrintAndLog("algorithm [%lld] %s", (long long)i64, GetCOSEAlgDescription(i64)); + } + + // curve + res = CborMapGetKeyById(&parser, &map, data, datalen, -1); + if(!res) { + cbor_value_get_int64(&map, &i64); + if(verbose) + PrintAndLog("curve [%lld] %s", (long long)i64, GetCOSEAlgDescription(i64)); + } + + + if(verbose) + PrintAndLog("----------- CBOR decode ----------------"); return 0; } diff --git a/client/fido/cose.h b/client/fido/cose.h index 1b685e4a8..209239ec4 100644 --- a/client/fido/cose.h +++ b/client/fido/cose.h @@ -19,6 +19,7 @@ extern const char *GetCOSEAlgName(int id); extern const char *GetCOSEAlgDescription(int id); +extern const char *GetCOSEktyDescription(int id); extern int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public_key); From 0a2f874ac3892121f074aad79fff10a8c30fdc49 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Nov 2018 19:22:44 +0200 Subject: [PATCH 0244/1938] added cose_key descriptions --- client/fido/cose.c | 49 +++++++++++++++++++++++++++++++--------------- client/fido/cose.h | 1 + 2 files changed, 34 insertions(+), 16 deletions(-) diff --git a/client/fido/cose.c b/client/fido/cose.c index bc86fee65..441c8251c 100644 --- a/client/fido/cose.c +++ b/client/fido/cose.c @@ -38,8 +38,22 @@ COSEValueNameDesc_t COSEKeyTypeValueDesc[] = { {4, "Symmetric", "Symmetric Key"}, }; +COSEValueNameDesc_t *GetCOSEktyElm(int id) { + for (int i = 0; i < ARRAYLEN(COSEKeyTypeValueDesc); i++) + if (COSEKeyTypeValueDesc[i].Value == id) + return &COSEKeyTypeValueDesc[i]; + return NULL; +} + +const char *GetCOSEktyDescription(int id) { + COSEValueNameDesc_t *elm = GetCOSEktyElm(id); + if (elm) + return elm->Description; + return COSEEmptyStr; +} + // keys -COSEValueTypeNameDesc_t COSEKeyTypeDesc[] = { +COSEValueTypeNameDesc_t COSECurvesDesc[] = { {1, "EC2", "P-256", "NIST P-256 also known as secp256r1"}, {2, "EC2", "P-384", "NIST P-384 also known as secp384r1"}, {3, "EC2", "P-521", "NIST P-521 also known as secp521r1"}, @@ -49,6 +63,20 @@ COSEValueTypeNameDesc_t COSEKeyTypeDesc[] = { {7, "OKP", "Ed448", "Ed448 for use w/ EdDSA only"}, }; +COSEValueTypeNameDesc_t *GetCOSECurveElm(int id) { + for (int i = 0; i < ARRAYLEN(COSECurvesDesc); i++) + if (COSECurvesDesc[i].Value == id) + return &COSECurvesDesc[i]; + return NULL; +} + +const char *GetCOSECurveDescription(int id) { + COSEValueNameDesc_t *elm = GetCOSECurveElm(id); + if (elm) + return elm->Description; + return COSEEmptyStr; +} + // RFC8152 https://www.iana.org/assignments/cose/cose.xhtml#algorithms COSEValueNameDesc_t COSEAlg[] = { {-65536, "Unassigned", "Unassigned"}, @@ -128,20 +156,6 @@ const char *GetCOSEAlgDescription(int id) { return COSEEmptyStr; } -COSEValueNameDesc_t *GetCOSEktyElm(int id) { - for (int i = 0; i < ARRAYLEN(COSEKeyTypeValueDesc); i++) - if (COSEKeyTypeValueDesc[i].Value == id) - return &COSEKeyTypeValueDesc[i]; - return NULL; -} - -const char *GetCOSEktyDescription(int id) { - COSEValueNameDesc_t *elm = GetCOSEktyElm(id); - if (elm) - return elm->Description; - return COSEEmptyStr; -} - int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public_key) { CborParser parser; CborValue map; @@ -171,9 +185,12 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public if(!res) { cbor_value_get_int64(&map, &i64); if(verbose) - PrintAndLog("curve [%lld] %s", (long long)i64, GetCOSEAlgDescription(i64)); + PrintAndLog("curve [%lld] %s", (long long)i64, GetCOSECurveDescription(i64)); } + // plain key + public_key[0] = 0x04; + if(verbose) PrintAndLog("----------- CBOR decode ----------------"); diff --git a/client/fido/cose.h b/client/fido/cose.h index 209239ec4..850652fc4 100644 --- a/client/fido/cose.h +++ b/client/fido/cose.h @@ -20,6 +20,7 @@ extern const char *GetCOSEAlgName(int id); extern const char *GetCOSEAlgDescription(int id); extern const char *GetCOSEktyDescription(int id); +extern const char *GetCOSECurveDescription(int id); extern int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public_key); From 065773377d52915c47ecda7f50838cc19d9f99ba Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Nov 2018 19:42:37 +0200 Subject: [PATCH 0245/1938] get cose public key and fix some printing --- client/cmdhffido.c | 23 ++++++++++++++++------- client/fido/cose.c | 30 +++++++++++++++++++++++++++++- 2 files changed, 45 insertions(+), 8 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 378d69227..d94f3d967 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -720,22 +720,27 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v // Credential ID uint8_t cridlen = (uint16_t)bytes_to_num(&ubuf[53], 2); - PrintAndLog("Credential id[%d]: %s", cridlen, sprint_hex(&ubuf[55], cridlen)); + PrintAndLog("Credential id[%d]: %s", cridlen, sprint_hex_inrow(&ubuf[55], cridlen)); JsonSaveBufAsHexCompact(root, "$.AppData.CredentialId", &ubuf[55], cridlen); //Credentional public key (COSE_KEY) uint8_t coseKey[65] = {0}; uint16_t cplen = n - 55 - cridlen; - PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s", cplen, sprint_hex(&ubuf[55 + cridlen], cplen)); + PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s", cplen, sprint_hex_inrow(&ubuf[55 + cridlen], cplen)); JsonSaveBufAsHexCompact(root, "$.AppData.COSE_KEY", &ubuf[55 + cridlen], cplen); if (showCBOR) { + PrintAndLog("COSE structure:"); + PrintAndLog("---------------- CBOR ------------------"); TinyCborPrintFIDOPackage(fido2COSEKey, true, &ubuf[55 + cridlen], cplen); + PrintAndLog("---------------- CBOR ------------------"); } res = COSEGetECDSAKey(&ubuf[55 + cridlen], cplen, verbose, coseKey); - if (res) + if (res) { PrintAndLog("ERROR: Can't get COSE_KEY."); - else + } else { + PrintAndLog("COSE public key: %s", sprint_hex_inrow(coseKey, sizeof(coseKey))); JsonSaveBufAsHexCompact(root, "$.AppData.COSEPublicKey", coseKey, sizeof(coseKey)); + } free(ubuf); @@ -767,13 +772,13 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v if (!strcmp(key, "sig")) { res = CborGetBinStringValue(&mapsmt, sign, sizeof(sign), &signLen); cbor_check(res); - PrintAndLog("signature [%d]: %s", signLen, sprint_hex(sign, signLen)); + PrintAndLog("signature [%d]: %s", signLen, sprint_hex_inrow(sign, signLen)); } if (!strcmp(key, "x5c")) { res = CborGetArrayBinStringValue(&mapsmt, der, sizeof(der), &derLen); cbor_check(res); - PrintAndLog("DER [%d]: %s", derLen, sprint_hex(der, derLen)); + PrintAndLog("DER [%d]: %s", derLen, sprint_hex_inrow(der, derLen)); JsonSaveBufAsHexCompact(root, "$.AppData.DER", der, derLen); } } @@ -816,7 +821,7 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json NULL, 0); PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); - res = ecdsa_signature_verify(public_key, xbuf, xbuflen, sign, signLen); + res = ecdsa_signature_verify(coseKey, xbuf, xbuflen, sign, signLen); if (res) { if (res == -0x4e00) { PrintAndLog("Signature is NOT VALID."); @@ -880,7 +885,9 @@ int CmdHFFido2MakeCredential(const char *cmd) { if (showCBOR) { PrintAndLog("CBOR make credentional request:"); + PrintAndLog("---------------- CBOR ------------------"); TinyCborPrintFIDOPackage(fido2CmdMakeCredential, false, data, datalen); + PrintAndLog("---------------- CBOR ------------------"); } res = FIDO2MakeCredential(data, datalen, buf, sizeof(buf), &len, &sw); @@ -903,7 +910,9 @@ int CmdHFFido2MakeCredential(const char *cmd) { PrintAndLog("MakeCredential result (%d b) OK.", len); if (showCBOR) { PrintAndLog("CBOR make credentional response:"); + PrintAndLog("---------------- CBOR ------------------"); TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1); + PrintAndLog("---------------- CBOR ------------------"); } // parse returned cbor diff --git a/client/fido/cose.c b/client/fido/cose.c index 441c8251c..d3656acda 100644 --- a/client/fido/cose.c +++ b/client/fido/cose.c @@ -71,7 +71,7 @@ COSEValueTypeNameDesc_t *GetCOSECurveElm(int id) { } const char *GetCOSECurveDescription(int id) { - COSEValueNameDesc_t *elm = GetCOSECurveElm(id); + COSEValueTypeNameDesc_t *elm = GetCOSECurveElm(id); if (elm) return elm->Description; return COSEEmptyStr; @@ -160,6 +160,7 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public CborParser parser; CborValue map; int64_t i64; + size_t len; if(verbose) PrintAndLog("----------- CBOR decode ----------------"); @@ -191,6 +192,33 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public // plain key public_key[0] = 0x04; + // x - coordinate + res = CborMapGetKeyById(&parser, &map, data, datalen, -2); + if(!res) { + res = CborGetBinStringValue(&map, &public_key[1], 32, &len); + cbor_check(res); + if(verbose) + PrintAndLog("x - coordinate [%d]: %s", len, sprint_hex(&public_key[1], 32)); + } + + // y - coordinate + res = CborMapGetKeyById(&parser, &map, data, datalen, -3); + if(!res) { + res = CborGetBinStringValue(&map, &public_key[33], 32, &len); + cbor_check(res); + if(verbose) + PrintAndLog("y - coordinate [%d]: %s", len, sprint_hex(&public_key[33], 32)); + } + + // d - private key + uint8_t private_key[128] = {0}; + res = CborMapGetKeyById(&parser, &map, data, datalen, -4); + if(!res) { + res = CborGetBinStringValue(&map, private_key, sizeof(private_key), &len); + cbor_check(res); + if(verbose) + PrintAndLog("d - private key [%d]: %s", len, sprint_hex(private_key, len)); + } if(verbose) PrintAndLog("----------- CBOR decode ----------------"); From d36bfd5829bf6fdf86ffdee929dd383436585a00 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Nov 2018 19:49:41 +0200 Subject: [PATCH 0246/1938] add some cose key checks --- client/fido/cose.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/client/fido/cose.c b/client/fido/cose.c index d3656acda..e45f46290 100644 --- a/client/fido/cose.c +++ b/client/fido/cose.c @@ -171,6 +171,8 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public cbor_value_get_int64(&map, &i64); if(verbose) PrintAndLog("kty [%lld] %s", (long long)i64, GetCOSEktyDescription(i64)); + if (i64 != 2) + PrintAndLog("ERROR: kty must be 2."); } // algorithm @@ -179,6 +181,8 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public cbor_value_get_int64(&map, &i64); if(verbose) PrintAndLog("algorithm [%lld] %s", (long long)i64, GetCOSEAlgDescription(i64)); + if (i64 != -7) + PrintAndLog("ERROR: algorithm must be -7."); } // curve @@ -187,6 +191,8 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public cbor_value_get_int64(&map, &i64); if(verbose) PrintAndLog("curve [%lld] %s", (long long)i64, GetCOSECurveDescription(i64)); + if (i64 != 1) + PrintAndLog("ERROR: curve must be 1."); } // plain key @@ -199,6 +205,8 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public cbor_check(res); if(verbose) PrintAndLog("x - coordinate [%d]: %s", len, sprint_hex(&public_key[1], 32)); + if (len != 32) + PrintAndLog("ERROR: x - coordinate length must be 32."); } // y - coordinate @@ -208,6 +216,8 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public cbor_check(res); if(verbose) PrintAndLog("y - coordinate [%d]: %s", len, sprint_hex(&public_key[33], 32)); + if (len != 32) + PrintAndLog("ERROR: y - coordinate length must be 32."); } // d - private key From 66d994920fffb23f84a25a4b1c340222a2912804 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 26 Nov 2018 20:17:50 +0200 Subject: [PATCH 0247/1938] added command and some parameters --- client/cmdhffido.c | 38 +++++++++++++++++++++++++++++++++----- 1 file changed, 33 insertions(+), 5 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index d94f3d967..d4e512bc7 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -687,7 +687,7 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v if (n >= 37) memcpy(authDataStatic, ubuf, 37); - PrintAndLog("authData: %s", sprint_hex(ubuf, n)); + PrintAndLog("authData: %s", sprint_hex_inrow(ubuf, n)); PrintAndLog("RP ID Hash: %s", sprint_hex(ubuf, 32)); @@ -721,6 +721,7 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v // Credential ID uint8_t cridlen = (uint16_t)bytes_to_num(&ubuf[53], 2); PrintAndLog("Credential id[%d]: %s", cridlen, sprint_hex_inrow(&ubuf[55], cridlen)); + JsonSaveInt(root, "$.AppData.CredentialIdLen", cridlen); JsonSaveBufAsHexCompact(root, "$.AppData.CredentialId", &ubuf[55], cridlen); //Credentional public key (COSE_KEY) @@ -821,7 +822,7 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json NULL, 0); PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); - res = ecdsa_signature_verify(coseKey, xbuf, xbuflen, sign, signLen); + res = ecdsa_signature_verify(public_key, xbuf, xbuflen, sign, signLen); if (res) { if (res == -0x4e00) { PrintAndLog("Signature is NOT VALID."); @@ -842,9 +843,36 @@ int CmdHFFido2MakeCredential(const char *cmd) { json_error_t error; json_t *root = NULL; char fname[300] = {0}; - bool verbose = true; - bool showDERTLV = true; - bool showCBOR = true; + + CLIParserInit("hf fido make", + "Execute a FIDO2 Make Credentional command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", + "Usage:\n\thf fido make -> execute command default parameters file `fido2.json`\n" + "\thf fido make test.json -> execute command with parameters file `text.json`"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), + arg_lit0("tT", "tlv", "Show DER certificate contents in TLV representation"), + arg_lit0("cC", "cbor", "show CBOR decoded data"), + arg_str0(NULL, NULL, "fido2.json", "JSON input / output file name for parameters. Default `fido2.json`"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + bool APDULogging = arg_get_lit(1); + bool verbose = arg_get_lit(2); + bool verbose2 = arg_get_lit(2) > 1; + bool showDERTLV = arg_get_lit(3); + bool showCBOR = arg_get_lit(4); + + + + + + CLIParserFree(); + + SetAPDULogging(APDULogging); int res = GetExistsFileNameJson("fido", "fido2", fname); if(res) { From 890173a623d9e1b4756f81a7b14c3a5a99dce72f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 27 Nov 2018 00:11:53 +0200 Subject: [PATCH 0248/1938] verify signature OK, added some logging options --- client/cmdhffido.c | 47 +++++++++++++++++++++++++++++++++------------- 1 file changed, 34 insertions(+), 13 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index d4e512bc7..4af68c8ad 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -658,7 +658,7 @@ bool CheckrpIdHash(json_t *json, uint8_t *hash) { return !memcmp(hash, hash2, 32); } -int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool showCBOR, bool showDERTLV) { +int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR, bool showDERTLV) { CborParser parser; CborValue map, mapsmt; int res; @@ -677,17 +677,22 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v free(buf); // authData - uint8_t authDataStatic[37] = {0}; + uint8_t authData[400] = {0}; + size_t authDataLen = 0; res = CborMapGetKeyById(&parser, &map, data, dataLen, 2); if (res) return res; res = cbor_value_dup_byte_string(&map, &ubuf, &n, &map); cbor_check(res); - if (n >= 37) - memcpy(authDataStatic, ubuf, 37); + authDataLen = n; + memcpy(authData, ubuf, authDataLen); - PrintAndLog("authData: %s", sprint_hex_inrow(ubuf, n)); + if (verbose2) { + PrintAndLog("authData[%d]: %s", n, sprint_hex_inrow(authData, authDataLen)); + } else { + PrintAndLog("authData[%d]: %s...", n, sprint_hex(authData, MIN(authDataLen, 16))); + } PrintAndLog("RP ID Hash: %s", sprint_hex(ubuf, 32)); @@ -727,14 +732,20 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v //Credentional public key (COSE_KEY) uint8_t coseKey[65] = {0}; uint16_t cplen = n - 55 - cridlen; - PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s", cplen, sprint_hex_inrow(&ubuf[55 + cridlen], cplen)); + if (verbose2) { + PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s", cplen, sprint_hex_inrow(&ubuf[55 + cridlen], cplen)); + } else { + PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s...", cplen, sprint_hex(&ubuf[55 + cridlen], MIN(cplen, 16))); + } JsonSaveBufAsHexCompact(root, "$.AppData.COSE_KEY", &ubuf[55 + cridlen], cplen); + if (showCBOR) { PrintAndLog("COSE structure:"); PrintAndLog("---------------- CBOR ------------------"); TinyCborPrintFIDOPackage(fido2COSEKey, true, &ubuf[55 + cridlen], cplen); PrintAndLog("---------------- CBOR ------------------"); } + res = COSEGetECDSAKey(&ubuf[55 + cridlen], cplen, verbose, coseKey); if (res) { PrintAndLog("ERROR: Can't get COSE_KEY."); @@ -773,14 +784,24 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v if (!strcmp(key, "sig")) { res = CborGetBinStringValue(&mapsmt, sign, sizeof(sign), &signLen); cbor_check(res); - PrintAndLog("signature [%d]: %s", signLen, sprint_hex_inrow(sign, signLen)); + if (verbose2) { + PrintAndLog("signature [%d]: %s", signLen, sprint_hex_inrow(sign, signLen)); + } else { + PrintAndLog("signature [%d]: %s...", signLen, sprint_hex(sign, MIN(signLen, 16))); + } } if (!strcmp(key, "x5c")) { res = CborGetArrayBinStringValue(&mapsmt, der, sizeof(der), &derLen); cbor_check(res); - PrintAndLog("DER [%d]: %s", derLen, sprint_hex_inrow(der, derLen)); - JsonSaveBufAsHexCompact(root, "$.AppData.DER", der, derLen); + if (verbose2) { + PrintAndLog("DER certificate[%d]:\n------------------DER-------------------", derLen); + dump_buffer_simple((const unsigned char *)der, derLen, NULL); + PrintAndLog("\n----------------DER---------------------"); + } else { + PrintAndLog("DER [%d]: %s...", derLen, sprint_hex(der, MIN(derLen, 16))); + } + JsonSaveBufAsHexCompact(root, "$.AppData.DER", der, derLen); } } res = cbor_value_leave_container(&map, &mapsmt); @@ -818,10 +839,10 @@ int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool v uint8_t xbuf[4096] = {0}; size_t xbuflen = 0; res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, - authDataStatic, 37, // rpIdHash[32] + flags[1] + signCount[4] - clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json + authData, authDataLen, // rpIdHash[32] + flags[1] + signCount[4] + ... + clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json NULL, 0); - PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); + //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); res = ecdsa_signature_verify(public_key, xbuf, xbuflen, sign, signLen); if (res) { if (res == -0x4e00) { @@ -944,7 +965,7 @@ int CmdHFFido2MakeCredential(const char *cmd) { } // parse returned cbor - MakeCredentionalParseRes(root, &buf[1], len - 1, verbose, showCBOR, showDERTLV); + MakeCredentionalParseRes(root, &buf[1], len - 1, verbose, verbose2, showCBOR, showDERTLV); if (root) { res = json_dump_file(root, fname, JSON_INDENT(2)); From fc9558b18fd39e47606d94c66ef46ebbc713ca51 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 27 Nov 2018 00:18:44 +0200 Subject: [PATCH 0249/1938] get assertion command sketch --- client/cmdhffido.c | 89 +++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 1 deletion(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 4af68c8ad..359fb3660 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -982,7 +982,94 @@ int CmdHFFido2MakeCredential(const char *cmd) { }; int CmdHFFido2GetAssertion(const char *cmd) { + json_error_t error; + json_t *root = NULL; + char fname[300] = {0}; + + + bool APDULogging = false; + bool verbose = true; + bool verbose2 = true; + bool showCBOR = true; + + + + + //CLIParserFree(); + + SetAPDULogging(APDULogging); + + + int res = GetExistsFileNameJson("fido", "fido2", fname); + if(res) { + PrintAndLog("ERROR: Can't found the json file."); + return res; + } + PrintAndLog("fname: %s\n", fname); + root = json_load_file(fname, 0, &error); + if (!root) { + PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); + return 1; + } + + uint8_t data[2048] = {0}; + size_t datalen = 0; + uint8_t buf[2048] = {0}; + size_t len = 0; + uint16_t sw = 0; + + DropField(); + res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); + + if (res) { + PrintAndLog("Can't select authenticator. res=%x. Exit...", res); + DropField(); + return res; + } + + if (sw != 0x9000) { + PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); + return 2; + } +/* + res = FIDO2CreateMakeCredentionalReq(root, data, sizeof(data), &datalen); + if (res) + return res; + + if (showCBOR) { + PrintAndLog("CBOR get assertion request:"); + PrintAndLog("---------------- CBOR ------------------"); + TinyCborPrintFIDOPackage(fido2CmdMakeCredential, false, data, datalen); + PrintAndLog("---------------- CBOR ------------------"); + } +*/ + res = FIDO2GetAssertion(data, datalen, buf, sizeof(buf), &len, &sw); + DropField(); + if (res) { + PrintAndLog("Can't execute get assertion command. res=%x. Exit...", res); + return res; + } + + if (sw != 0x9000) { + PrintAndLog("ERROR execute get assertion command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + return 3; + } + + if(buf[0]) { + PrintAndLog("FIDO2 get assertion error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); + return 0; + } + +/* PrintAndLog("MakeCredential result (%d b) OK.", len); + if (showCBOR) { + PrintAndLog("CBOR get assertion response:"); + PrintAndLog("---------------- CBOR ------------------"); + TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1); + PrintAndLog("---------------- CBOR ------------------"); + } +*/ return 0; }; @@ -993,7 +1080,7 @@ static command_t CommandTable[] = {"reg", CmdHFFidoRegister, 0, "FIDO U2F Registration Message."}, {"auth", CmdHFFidoAuthenticate, 0, "FIDO U2F Authentication Message."}, {"make", CmdHFFido2MakeCredential, 0, "FIDO2 MakeCredential command."}, - {"accert", CmdHFFido2GetAssertion, 0, "FIDO2 GetAssertion command."}, + {"assert", CmdHFFido2GetAssertion, 0, "FIDO2 GetAssertion command."}, {NULL, NULL, 0, NULL} }; From bad7b80036d5914bef9c81c981677515571ed9b1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 27 Nov 2018 12:07:33 +0200 Subject: [PATCH 0250/1938] added file name to fido2 command --- client/cmdhffido.c | 55 +++++++++++++++++++++++++++++++++------------- 1 file changed, 40 insertions(+), 15 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 359fb3660..e2d53560d 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -876,7 +876,7 @@ int CmdHFFido2MakeCredential(const char *cmd) { arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), arg_lit0("tT", "tlv", "Show DER certificate contents in TLV representation"), arg_lit0("cC", "cbor", "show CBOR decoded data"), - arg_str0(NULL, NULL, "fido2.json", "JSON input / output file name for parameters. Default `fido2.json`"), + arg_str0(NULL, NULL, "", "JSON input / output file name for parameters. Default `fido2.json`"), arg_param_end }; CLIExecWithReturn(cmd, argtable, true); @@ -887,15 +887,21 @@ int CmdHFFido2MakeCredential(const char *cmd) { bool showDERTLV = arg_get_lit(3); bool showCBOR = arg_get_lit(4); + uint8_t jsonname[250] ={0}; + char *cjsonname = (char *)jsonname; + int jsonnamelen = 0; + CLIGetStrWithReturn(5, jsonname, &jsonnamelen); + if (!jsonnamelen) { + strcat(cjsonname, "fido2"); + jsonnamelen = strlen(cjsonname); + } - - CLIParserFree(); SetAPDULogging(APDULogging); - int res = GetExistsFileNameJson("fido", "fido2", fname); + int res = GetExistsFileNameJson("fido", cjsonname, fname); if(res) { PrintAndLog("ERROR: Can't found the json file."); return res; @@ -986,21 +992,40 @@ int CmdHFFido2GetAssertion(const char *cmd) { json_t *root = NULL; char fname[300] = {0}; - - bool APDULogging = false; - bool verbose = true; - bool verbose2 = true; - bool showCBOR = true; - - + CLIParserInit("hf fido assert", + "Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", + "Usage:\n\thf fido assert -> execute command default parameters file `fido2.json`\n" + "\thf fido assert test.json -> execute command with parameters file `text.json`"); + void* argtable[] = { + arg_param_begin, + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), + arg_lit0("cC", "cbor", "show CBOR decoded data"), + arg_str0(NULL, NULL, "", "JSON input / output file name for parameters. Default `fido2.json`"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); - - //CLIParserFree(); + bool APDULogging = arg_get_lit(1); + bool verbose = arg_get_lit(2); + bool verbose2 = arg_get_lit(2) > 1; + bool showCBOR = arg_get_lit(3); + + uint8_t jsonname[250] ={0}; + char *cjsonname = (char *)jsonname; + int jsonnamelen = 0; + CLIGetStrWithReturn(4, jsonname, &jsonnamelen); + + if (!jsonnamelen) { + strcat(cjsonname, "fido2"); + jsonnamelen = strlen(cjsonname); + } + + CLIParserFree(); SetAPDULogging(APDULogging); - - + int res = GetExistsFileNameJson("fido", "fido2", fname); if(res) { PrintAndLog("ERROR: Can't found the json file."); From ee92b8a0977fc9be80fb273b383032aaa1e708af Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 27 Nov 2018 12:24:55 +0200 Subject: [PATCH 0251/1938] refactoring make credentials and add some sketch to get assertion --- client/cmdhffido.c | 220 +--------------------------------- client/fido/fido2.json | 6 +- client/fido/fidocore.c | 260 +++++++++++++++++++++++++++++++++++++++++ client/fido/fidocore.h | 3 + 4 files changed, 272 insertions(+), 217 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index e2d53560d..db427236c 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -648,218 +648,6 @@ int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileNam return 0; } -bool CheckrpIdHash(json_t *json, uint8_t *hash) { - char hashval[300] = {0}; - uint8_t hash2[32] = {0}; - - JsonLoadStr(json, "$.RelyingPartyEntity.id", hashval); - sha256hash((uint8_t *)hashval, strlen(hashval), hash2); - - return !memcmp(hash, hash2, 32); -} - -int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR, bool showDERTLV) { - CborParser parser; - CborValue map, mapsmt; - int res; - char *buf; - uint8_t *ubuf; - size_t n; - - // fmt - res = CborMapGetKeyById(&parser, &map, data, dataLen, 1); - if (res) - return res; - - res = cbor_value_dup_text_string(&map, &buf, &n, &map); - cbor_check(res); - PrintAndLog("format: %s", buf); - free(buf); - - // authData - uint8_t authData[400] = {0}; - size_t authDataLen = 0; - res = CborMapGetKeyById(&parser, &map, data, dataLen, 2); - if (res) - return res; - res = cbor_value_dup_byte_string(&map, &ubuf, &n, &map); - cbor_check(res); - - authDataLen = n; - memcpy(authData, ubuf, authDataLen); - - if (verbose2) { - PrintAndLog("authData[%d]: %s", n, sprint_hex_inrow(authData, authDataLen)); - } else { - PrintAndLog("authData[%d]: %s...", n, sprint_hex(authData, MIN(authDataLen, 16))); - } - - PrintAndLog("RP ID Hash: %s", sprint_hex(ubuf, 32)); - - // check RP ID Hash - if (CheckrpIdHash(root, ubuf)) { - PrintAndLog("rpIdHash OK."); - } else { - PrintAndLog("rpIdHash ERROR!"); - } - - PrintAndLog("Flags 0x%02x:", ubuf[32]); - if (!ubuf[32]) - PrintAndLog("none"); - if (ubuf[32] & 0x01) - PrintAndLog("up - user presence result"); - if (ubuf[32] & 0x04) - PrintAndLog("uv - user verification (fingerprint scan or a PIN or ...) result"); - if (ubuf[32] & 0x40) - PrintAndLog("at - attested credential data included"); - if (ubuf[32] & 0x80) - PrintAndLog("ed - extension data included"); - - uint32_t cntr = (uint32_t)bytes_to_num(&ubuf[33], 4); - PrintAndLog("Counter: %d", cntr); - JsonSaveInt(root, "$.AppData.Counter", cntr); - - // attestation data - PrintAndLog("AAGUID: %s", sprint_hex(&ubuf[37], 16)); - JsonSaveBufAsHexCompact(root, "$.AppData.AAGUID", &ubuf[37], 16); - - // Credential ID - uint8_t cridlen = (uint16_t)bytes_to_num(&ubuf[53], 2); - PrintAndLog("Credential id[%d]: %s", cridlen, sprint_hex_inrow(&ubuf[55], cridlen)); - JsonSaveInt(root, "$.AppData.CredentialIdLen", cridlen); - JsonSaveBufAsHexCompact(root, "$.AppData.CredentialId", &ubuf[55], cridlen); - - //Credentional public key (COSE_KEY) - uint8_t coseKey[65] = {0}; - uint16_t cplen = n - 55 - cridlen; - if (verbose2) { - PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s", cplen, sprint_hex_inrow(&ubuf[55 + cridlen], cplen)); - } else { - PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s...", cplen, sprint_hex(&ubuf[55 + cridlen], MIN(cplen, 16))); - } - JsonSaveBufAsHexCompact(root, "$.AppData.COSE_KEY", &ubuf[55 + cridlen], cplen); - - if (showCBOR) { - PrintAndLog("COSE structure:"); - PrintAndLog("---------------- CBOR ------------------"); - TinyCborPrintFIDOPackage(fido2COSEKey, true, &ubuf[55 + cridlen], cplen); - PrintAndLog("---------------- CBOR ------------------"); - } - - res = COSEGetECDSAKey(&ubuf[55 + cridlen], cplen, verbose, coseKey); - if (res) { - PrintAndLog("ERROR: Can't get COSE_KEY."); - } else { - PrintAndLog("COSE public key: %s", sprint_hex_inrow(coseKey, sizeof(coseKey))); - JsonSaveBufAsHexCompact(root, "$.AppData.COSEPublicKey", coseKey, sizeof(coseKey)); - } - - free(ubuf); - - // attStmt - we are check only as DER certificate - int64_t alg = 0; - uint8_t sign[128] = {0}; - size_t signLen = 0; - uint8_t der[4097] = {0}; - size_t derLen = 0; - - res = CborMapGetKeyById(&parser, &map, data, dataLen, 3); - if (res) - return res; - - res = cbor_value_enter_container(&map, &mapsmt); - cbor_check(res); - - while (!cbor_value_at_end(&mapsmt)) { - char key[100] = {0}; - res = CborGetStringValue(&mapsmt, key, sizeof(key), &n); - cbor_check(res); - if (!strcmp(key, "alg")) { - cbor_value_get_int64(&mapsmt, &alg); - PrintAndLog("Alg [%lld] %s", (long long)alg, GetCOSEAlgDescription(alg)); - res = cbor_value_advance_fixed(&mapsmt); - cbor_check(res); - } - - if (!strcmp(key, "sig")) { - res = CborGetBinStringValue(&mapsmt, sign, sizeof(sign), &signLen); - cbor_check(res); - if (verbose2) { - PrintAndLog("signature [%d]: %s", signLen, sprint_hex_inrow(sign, signLen)); - } else { - PrintAndLog("signature [%d]: %s...", signLen, sprint_hex(sign, MIN(signLen, 16))); - } - } - - if (!strcmp(key, "x5c")) { - res = CborGetArrayBinStringValue(&mapsmt, der, sizeof(der), &derLen); - cbor_check(res); - if (verbose2) { - PrintAndLog("DER certificate[%d]:\n------------------DER-------------------", derLen); - dump_buffer_simple((const unsigned char *)der, derLen, NULL); - PrintAndLog("\n----------------DER---------------------"); - } else { - PrintAndLog("DER [%d]: %s...", derLen, sprint_hex(der, MIN(derLen, 16))); - } - JsonSaveBufAsHexCompact(root, "$.AppData.DER", der, derLen); - } - } - res = cbor_value_leave_container(&map, &mapsmt); - cbor_check(res); - - uint8_t public_key[65] = {0}; - - // print DER certificate in TLV view - if (showDERTLV) { - PrintAndLog("----------------DER TLV-----------------"); - asn1_print(der, derLen, " "); - PrintAndLog("----------------DER TLV-----------------"); - } - FIDOCheckDERAndGetKey(der, derLen, verbose, public_key, sizeof(public_key)); - JsonSaveBufAsHexCompact(root, "$.AppData.DERPublicKey", public_key, sizeof(public_key)); - - // check ANSI X9.62 format ECDSA signature (on P-256) - uint8_t rval[300] = {0}; - uint8_t sval[300] = {0}; - res = ecdsa_asn1_get_signature(sign, signLen, rval, sval); - if (!res) { - if (verbose) { - PrintAndLog(" r: %s", sprint_hex(rval, 32)); - PrintAndLog(" s: %s", sprint_hex(sval, 32)); - } - - uint8_t clientDataHash[32] = {0}; - size_t clientDataHashLen = 0; - res = JsonLoadBufAsHex(root, "$.ClientDataHash", clientDataHash, sizeof(clientDataHash), &clientDataHashLen); - if (res || clientDataHashLen != 32) { - PrintAndLog("ERROR: Can't get clientDataHash from json!"); - return 2; - } - - uint8_t xbuf[4096] = {0}; - size_t xbuflen = 0; - res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, - authData, authDataLen, // rpIdHash[32] + flags[1] + signCount[4] + ... - clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json - NULL, 0); - //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); - res = ecdsa_signature_verify(public_key, xbuf, xbuflen, sign, signLen); - if (res) { - if (res == -0x4e00) { - PrintAndLog("Signature is NOT VALID."); - } else { - PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); - } - } else { - PrintAndLog("Signature is OK."); - } - } else { - PrintAndLog("Invalid signature. res=%d.", res); - } - - return 0; -} - int CmdHFFido2MakeCredential(const char *cmd) { json_error_t error; json_t *root = NULL; @@ -1058,18 +846,18 @@ int CmdHFFido2GetAssertion(const char *cmd) { DropField(); return 2; } -/* - res = FIDO2CreateMakeCredentionalReq(root, data, sizeof(data), &datalen); + + res = FIDO2CreateGetAssertionReq(root, data, sizeof(data), &datalen); if (res) return res; if (showCBOR) { PrintAndLog("CBOR get assertion request:"); PrintAndLog("---------------- CBOR ------------------"); - TinyCborPrintFIDOPackage(fido2CmdMakeCredential, false, data, datalen); + TinyCborPrintFIDOPackage(fido2CmdGetAssertion, false, data, datalen); PrintAndLog("---------------- CBOR ------------------"); } -*/ + res = FIDO2GetAssertion(data, datalen, buf, sizeof(buf), &len, &sw); DropField(); if (res) { diff --git a/client/fido/fido2.json b/client/fido/fido2.json index c158ef117..66449144f 100644 --- a/client/fido/fido2.json +++ b/client/fido/fido2.json @@ -25,5 +25,9 @@ "options": { "uv": false, "rk": false + }, + "GetAssertionOptions": { + "up": true, + "uv": false } -} \ No newline at end of file +} diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index c65959eff..22aee7c9f 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -21,6 +21,7 @@ #include "crypto/asn1utils.h" #include "crypto/libpcrypto.h" #include "fido/additional_ca.h" +#include "fido/cose.h" typedef struct { uint8_t ErrorCode; @@ -367,4 +368,263 @@ int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatale return 0; } +bool CheckrpIdHash(json_t *json, uint8_t *hash) { + char hashval[300] = {0}; + uint8_t hash2[32] = {0}; + + JsonLoadStr(json, "$.RelyingPartyEntity.id", hashval); + sha256hash((uint8_t *)hashval, strlen(hashval), hash2); + return !memcmp(hash, hash2, 32); +} + +int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR, bool showDERTLV) { + CborParser parser; + CborValue map, mapsmt; + int res; + char *buf; + uint8_t *ubuf; + size_t n; + + // fmt + res = CborMapGetKeyById(&parser, &map, data, dataLen, 1); + if (res) + return res; + + res = cbor_value_dup_text_string(&map, &buf, &n, &map); + cbor_check(res); + PrintAndLog("format: %s", buf); + free(buf); + + // authData + uint8_t authData[400] = {0}; + size_t authDataLen = 0; + res = CborMapGetKeyById(&parser, &map, data, dataLen, 2); + if (res) + return res; + res = cbor_value_dup_byte_string(&map, &ubuf, &n, &map); + cbor_check(res); + + authDataLen = n; + memcpy(authData, ubuf, authDataLen); + + if (verbose2) { + PrintAndLog("authData[%d]: %s", n, sprint_hex_inrow(authData, authDataLen)); + } else { + PrintAndLog("authData[%d]: %s...", n, sprint_hex(authData, MIN(authDataLen, 16))); + } + + PrintAndLog("RP ID Hash: %s", sprint_hex(ubuf, 32)); + + // check RP ID Hash + if (CheckrpIdHash(root, ubuf)) { + PrintAndLog("rpIdHash OK."); + } else { + PrintAndLog("rpIdHash ERROR!"); + } + + PrintAndLog("Flags 0x%02x:", ubuf[32]); + if (!ubuf[32]) + PrintAndLog("none"); + if (ubuf[32] & 0x01) + PrintAndLog("up - user presence result"); + if (ubuf[32] & 0x04) + PrintAndLog("uv - user verification (fingerprint scan or a PIN or ...) result"); + if (ubuf[32] & 0x40) + PrintAndLog("at - attested credential data included"); + if (ubuf[32] & 0x80) + PrintAndLog("ed - extension data included"); + + uint32_t cntr = (uint32_t)bytes_to_num(&ubuf[33], 4); + PrintAndLog("Counter: %d", cntr); + JsonSaveInt(root, "$.AppData.Counter", cntr); + + // attestation data + PrintAndLog("AAGUID: %s", sprint_hex(&ubuf[37], 16)); + JsonSaveBufAsHexCompact(root, "$.AppData.AAGUID", &ubuf[37], 16); + + // Credential ID + uint8_t cridlen = (uint16_t)bytes_to_num(&ubuf[53], 2); + PrintAndLog("Credential id[%d]: %s", cridlen, sprint_hex_inrow(&ubuf[55], cridlen)); + JsonSaveInt(root, "$.AppData.CredentialIdLen", cridlen); + JsonSaveBufAsHexCompact(root, "$.AppData.CredentialId", &ubuf[55], cridlen); + + //Credentional public key (COSE_KEY) + uint8_t coseKey[65] = {0}; + uint16_t cplen = n - 55 - cridlen; + if (verbose2) { + PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s", cplen, sprint_hex_inrow(&ubuf[55 + cridlen], cplen)); + } else { + PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s...", cplen, sprint_hex(&ubuf[55 + cridlen], MIN(cplen, 16))); + } + JsonSaveBufAsHexCompact(root, "$.AppData.COSE_KEY", &ubuf[55 + cridlen], cplen); + + if (showCBOR) { + PrintAndLog("COSE structure:"); + PrintAndLog("---------------- CBOR ------------------"); + TinyCborPrintFIDOPackage(fido2COSEKey, true, &ubuf[55 + cridlen], cplen); + PrintAndLog("---------------- CBOR ------------------"); + } + + res = COSEGetECDSAKey(&ubuf[55 + cridlen], cplen, verbose, coseKey); + if (res) { + PrintAndLog("ERROR: Can't get COSE_KEY."); + } else { + PrintAndLog("COSE public key: %s", sprint_hex_inrow(coseKey, sizeof(coseKey))); + JsonSaveBufAsHexCompact(root, "$.AppData.COSEPublicKey", coseKey, sizeof(coseKey)); + } + + free(ubuf); + + // attStmt - we are check only as DER certificate + int64_t alg = 0; + uint8_t sign[128] = {0}; + size_t signLen = 0; + uint8_t der[4097] = {0}; + size_t derLen = 0; + + res = CborMapGetKeyById(&parser, &map, data, dataLen, 3); + if (res) + return res; + + res = cbor_value_enter_container(&map, &mapsmt); + cbor_check(res); + + while (!cbor_value_at_end(&mapsmt)) { + char key[100] = {0}; + res = CborGetStringValue(&mapsmt, key, sizeof(key), &n); + cbor_check(res); + if (!strcmp(key, "alg")) { + cbor_value_get_int64(&mapsmt, &alg); + PrintAndLog("Alg [%lld] %s", (long long)alg, GetCOSEAlgDescription(alg)); + res = cbor_value_advance_fixed(&mapsmt); + cbor_check(res); + } + + if (!strcmp(key, "sig")) { + res = CborGetBinStringValue(&mapsmt, sign, sizeof(sign), &signLen); + cbor_check(res); + if (verbose2) { + PrintAndLog("signature [%d]: %s", signLen, sprint_hex_inrow(sign, signLen)); + } else { + PrintAndLog("signature [%d]: %s...", signLen, sprint_hex(sign, MIN(signLen, 16))); + } + } + + if (!strcmp(key, "x5c")) { + res = CborGetArrayBinStringValue(&mapsmt, der, sizeof(der), &derLen); + cbor_check(res); + if (verbose2) { + PrintAndLog("DER certificate[%d]:\n------------------DER-------------------", derLen); + dump_buffer_simple((const unsigned char *)der, derLen, NULL); + PrintAndLog("\n----------------DER---------------------"); + } else { + PrintAndLog("DER [%d]: %s...", derLen, sprint_hex(der, MIN(derLen, 16))); + } + JsonSaveBufAsHexCompact(root, "$.AppData.DER", der, derLen); + } + } + res = cbor_value_leave_container(&map, &mapsmt); + cbor_check(res); + + uint8_t public_key[65] = {0}; + + // print DER certificate in TLV view + if (showDERTLV) { + PrintAndLog("----------------DER TLV-----------------"); + asn1_print(der, derLen, " "); + PrintAndLog("----------------DER TLV-----------------"); + } + FIDOCheckDERAndGetKey(der, derLen, verbose, public_key, sizeof(public_key)); + JsonSaveBufAsHexCompact(root, "$.AppData.DERPublicKey", public_key, sizeof(public_key)); + + // check ANSI X9.62 format ECDSA signature (on P-256) + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; + res = ecdsa_asn1_get_signature(sign, signLen, rval, sval); + if (!res) { + if (verbose) { + PrintAndLog(" r: %s", sprint_hex(rval, 32)); + PrintAndLog(" s: %s", sprint_hex(sval, 32)); + } + + uint8_t clientDataHash[32] = {0}; + size_t clientDataHashLen = 0; + res = JsonLoadBufAsHex(root, "$.ClientDataHash", clientDataHash, sizeof(clientDataHash), &clientDataHashLen); + if (res || clientDataHashLen != 32) { + PrintAndLog("ERROR: Can't get clientDataHash from json!"); + return 2; + } + + uint8_t xbuf[4096] = {0}; + size_t xbuflen = 0; + res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, + authData, authDataLen, // rpIdHash[32] + flags[1] + signCount[4] + ... + clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json + NULL, 0); + //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); + res = ecdsa_signature_verify(public_key, xbuf, xbuflen, sign, signLen); + if (res) { + if (res == -0x4e00) { + PrintAndLog("Signature is NOT VALID."); + } else { + PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); + } + } else { + PrintAndLog("Signature is OK."); + } + } else { + PrintAndLog("Invalid signature. res=%d.", res); + } + + return 0; +} + +int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen) { + if (datalen) + *datalen = 0; + if (!root || !data || !maxdatalen) + return 1; + + int res; + CborEncoder encoder; + CborEncoder map; + + cbor_encoder_init(&encoder, data, maxdatalen, 0); + + // create main map + res = cbor_encoder_create_map(&encoder, &map, 5); + fido_check_if(res) { + // rpId + res = cbor_encode_uint(&map, 1); + fido_check_if(res) { +// char hashval[300] = {0}; +// JsonLoadStr(json, "$.RelyingPartyEntity.id", hashval); + + res = CBOREncodeElm(root, "RelyingPartyEntity", &map); + fido_check(res); + } + + // clientDataHash + res = cbor_encode_uint(&map, 2); + fido_check_if(res) { + res = CBOREncodeClientDataHash(root, &map); + fido_check(res); + } + + // options + res = cbor_encode_uint(&map, 5); + fido_check_if(res) { + res = CBOREncodeElm(root, "GetAssertionOptions", &map); + fido_check(res); + } + } + res = cbor_encoder_close_container(&encoder, &map); + fido_check(res); + + size_t len = cbor_encoder_get_buffer_size(&encoder, data); + if (datalen) + *datalen = len; + + return 0; +} diff --git a/client/fido/fidocore.h b/client/fido/fidocore.h index 5d6dc4be1..4baf029bb 100644 --- a/client/fido/fidocore.h +++ b/client/fido/fidocore.h @@ -48,6 +48,9 @@ extern int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint extern char *fido2GetCmdMemberDescription(uint8_t cmdCode, bool isResponse, int memberNum); extern char *fido2GetCmdErrorDescription(uint8_t errorCode); +extern bool CheckrpIdHash(json_t *json, uint8_t *hash); extern int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen); +extern int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR, bool showDERTLV); +extern int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen); #endif /* __FIDOCORE_H__ */ From 5efc2eced680c9d83f7099c06e6f0965c56ee0cf Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 27 Nov 2018 12:28:36 +0200 Subject: [PATCH 0252/1938] refactoring --- client/fido/cbortools.c | 10 ++++++++++ client/fido/cbortools.h | 2 ++ client/fido/fidocore.c | 10 ---------- 3 files changed, 12 insertions(+), 10 deletions(-) diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index 1693e6858..ad6931030 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -453,3 +453,13 @@ CborError CborGetStringValueBuf(CborValue *elm) { return CborGetStringValue(elm, stringBuf, sizeof(stringBuf), NULL); }; + +int CBOREncodeElm(json_t *root, char *rootElmId, CborEncoder *encoder) { + json_t *elm = json_object_get(root, rootElmId); + if (!elm) + return 1; + + int res = JsonToCbor(elm, encoder); + + return res; +} diff --git a/client/fido/cbortools.h b/client/fido/cbortools.h index a57b4b761..c7ef7658a 100644 --- a/client/fido/cbortools.h +++ b/client/fido/cbortools.h @@ -32,4 +32,6 @@ extern CborError CborGetArrayStringValue(CborValue *elm, char *data, size_t maxd extern CborError CborGetStringValue(CborValue *elm, char *data, size_t maxdatalen, size_t *datalen); extern CborError CborGetStringValueBuf(CborValue *elm); +extern int CBOREncodeElm(json_t *root, char *rootElmId, CborEncoder *encoder); + #endif /* __CBORTOOLS_H__ */ diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 22aee7c9f..651208441 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -298,16 +298,6 @@ int CBOREncodeClientDataHash(json_t *root, CborEncoder *encoder) { return 0; } -int CBOREncodeElm(json_t *root, char *rootElmId, CborEncoder *encoder) { - json_t *elm = json_object_get(root, rootElmId); - if (!elm) - return 1; - - int res = JsonToCbor(elm, encoder); - - return res; -} - int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen) { if (datalen) *datalen = 0; From a9be05dbf72822d68019a9b26119928c8c687cb7 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 27 Nov 2018 12:31:39 +0200 Subject: [PATCH 0253/1938] refactoring --- client/fido/fido2.json | 2 +- client/fido/fidocore.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/fido/fido2.json b/client/fido/fido2.json index 66449144f..8ecd04103 100644 --- a/client/fido/fido2.json +++ b/client/fido/fido2.json @@ -22,7 +22,7 @@ ".name": "RS256" } ], - "options": { + "MakeCredentialOptions": { "uv": false, "rk": false }, diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 651208441..21889cfd6 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -344,7 +344,7 @@ int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatale // options res = cbor_encode_uint(&map, 7); fido_check_if(res) { - res = CBOREncodeElm(root, "options", &map); + res = CBOREncodeElm(root, "MakeCredentialOptions", &map); fido_check(res); } } From 26cf350713771e8b3f386cd573a4626cf80932e0 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 27 Nov 2018 12:34:28 +0200 Subject: [PATCH 0254/1938] refactoring --- client/fido/cbortools.c | 16 ++++++++++++++++ client/fido/cbortools.h | 1 + client/fido/fidocore.c | 16 ---------------- 3 files changed, 17 insertions(+), 16 deletions(-) diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index ad6931030..59dbe9b4d 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -463,3 +463,19 @@ int CBOREncodeElm(json_t *root, char *rootElmId, CborEncoder *encoder) { return res; } + +CborError CBOREncodeClientDataHash(json_t *root, CborEncoder *encoder) { + uint8_t buf[100] = {0}; + size_t jlen; + + JsonLoadBufAsHex(root, "$.ClientDataHash", buf, sizeof(buf), &jlen); + + // fill with 0x00 if not found + if (!jlen) + jlen = 32; + + int res = cbor_encode_byte_string(encoder, buf, jlen); + cbor_check(res); + + return 0; +} diff --git a/client/fido/cbortools.h b/client/fido/cbortools.h index c7ef7658a..1e3fa8c0f 100644 --- a/client/fido/cbortools.h +++ b/client/fido/cbortools.h @@ -33,5 +33,6 @@ extern CborError CborGetStringValue(CborValue *elm, char *data, size_t maxdatale extern CborError CborGetStringValueBuf(CborValue *elm); extern int CBOREncodeElm(json_t *root, char *rootElmId, CborEncoder *encoder); +extern CborError CBOREncodeClientDataHash(json_t *root, CborEncoder *encoder); #endif /* __CBORTOOLS_H__ */ diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 21889cfd6..88d386f02 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -282,22 +282,6 @@ int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint8_t *pu #define fido_check_if(r) if ((r) != CborNoError) {return r;} else #define fido_check(r) if ((r) != CborNoError) return r; -int CBOREncodeClientDataHash(json_t *root, CborEncoder *encoder) { - uint8_t buf[100] = {0}; - size_t jlen; - - JsonLoadBufAsHex(root, "$.ClientDataHash", buf, sizeof(buf), &jlen); - - // fill with 0x00 if not found - if (!jlen) - jlen = 32; - - int res = cbor_encode_byte_string(encoder, buf, jlen); - fido_check(res); - - return 0; -} - int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen) { if (datalen) *datalen = 0; From 317ea305298d8327ecf601815514479ccf04eb59 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 27 Nov 2018 13:45:29 +0200 Subject: [PATCH 0255/1938] refactoring and GetAssertion works --- client/cmdhffido.c | 20 +++++++++++++++++--- client/fido/cbortools.c | 7 ++++++- client/fido/fidocore.c | 15 +++++++++------ client/fido/fidocore.h | 3 ++- 4 files changed, 34 insertions(+), 11 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index db427236c..b63f8582f 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -759,7 +759,7 @@ int CmdHFFido2MakeCredential(const char *cmd) { } // parse returned cbor - MakeCredentionalParseRes(root, &buf[1], len - 1, verbose, verbose2, showCBOR, showDERTLV); + FIDO2MakeCredentionalParseRes(root, &buf[1], len - 1, verbose, verbose2, showCBOR, showDERTLV); if (root) { res = json_dump_file(root, fname, JSON_INDENT(2)); @@ -875,14 +875,28 @@ int CmdHFFido2GetAssertion(const char *cmd) { return 0; } -/* PrintAndLog("MakeCredential result (%d b) OK.", len); + PrintAndLog("GetAssertion result (%d b) OK.", len); if (showCBOR) { PrintAndLog("CBOR get assertion response:"); PrintAndLog("---------------- CBOR ------------------"); - TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1); + TinyCborPrintFIDOPackage(fido2CmdGetAssertion, true, &buf[1], len - 1); PrintAndLog("---------------- CBOR ------------------"); } + + // parse returned cbor + FIDO2GetAssertionParseRes(root, &buf[1], len - 1, verbose, verbose2, showCBOR); + +/* if (root) { + res = json_dump_file(root, fname, JSON_INDENT(2)); + if (res) { + PrintAndLog("ERROR: can't save the file: %s", fname); + return 200; + } + PrintAndLog("File `%s` saved.", fname); + } */ + json_decref(root); + return 0; }; diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index 59dbe9b4d..8ab104a1c 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -455,7 +455,12 @@ CborError CborGetStringValueBuf(CborValue *elm) { }; int CBOREncodeElm(json_t *root, char *rootElmId, CborEncoder *encoder) { - json_t *elm = json_object_get(root, rootElmId); + json_t *elm = NULL; + if (rootElmId && strlen(rootElmId) && rootElmId[0] == '$') + elm = json_path_get(root, rootElmId); + else + elm = json_object_get(root, rootElmId); + if (!elm) return 1; diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 88d386f02..38b147125 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -352,7 +352,7 @@ bool CheckrpIdHash(json_t *json, uint8_t *hash) { return !memcmp(hash, hash2, 32); } -int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR, bool showDERTLV) { +int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR, bool showDERTLV) { CborParser parser; CborValue map, mapsmt; int res; @@ -567,17 +567,15 @@ int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, s cbor_encoder_init(&encoder, data, maxdatalen, 0); // create main map - res = cbor_encoder_create_map(&encoder, &map, 5); + res = cbor_encoder_create_map(&encoder, &map, 3); fido_check_if(res) { // rpId res = cbor_encode_uint(&map, 1); fido_check_if(res) { -// char hashval[300] = {0}; -// JsonLoadStr(json, "$.RelyingPartyEntity.id", hashval); - res = CBOREncodeElm(root, "RelyingPartyEntity", &map); + res = CBOREncodeElm(root, "$.RelyingPartyEntity.id", &map); fido_check(res); - } + } // clientDataHash res = cbor_encode_uint(&map, 2); @@ -602,3 +600,8 @@ int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, s return 0; } + +int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR) { + + return 0; +} diff --git a/client/fido/fidocore.h b/client/fido/fidocore.h index 4baf029bb..092261104 100644 --- a/client/fido/fidocore.h +++ b/client/fido/fidocore.h @@ -50,7 +50,8 @@ extern char *fido2GetCmdErrorDescription(uint8_t errorCode); extern bool CheckrpIdHash(json_t *json, uint8_t *hash); extern int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen); -extern int MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR, bool showDERTLV); +extern int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR, bool showDERTLV); extern int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen); +extern int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR); #endif /* __FIDOCORE_H__ */ From f26d3396e822c2d75ca0ea5b6c178596fe53870b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 27 Nov 2018 14:01:47 +0200 Subject: [PATCH 0256/1938] get credential --- client/fido/fidocore.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 38b147125..5c26785de 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -602,6 +602,46 @@ int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, s } int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR) { + CborParser parser; + CborValue map, mapint; + int res; +// char *buf; +// uint8_t *ubuf; + size_t n; + + // credential + res = CborMapGetKeyById(&parser, &map, data, dataLen, 1); + if (res) + return res; + + res = cbor_value_enter_container(&map, &mapint); + cbor_check(res); + + while (!cbor_value_at_end(&mapint)) { + char key[100] = {0}; + res = CborGetStringValue(&mapint, key, sizeof(key), &n); + cbor_check(res); + + if (!strcmp(key, "type")) { + char ctype[200] = {0}; + res = CborGetStringValue(&mapint, ctype, sizeof(ctype), &n); + cbor_check(res); + PrintAndLog("credential type: %s", ctype); + } + + if (!strcmp(key, "id")) { + uint8_t cid[200] = {0}; + res = CborGetBinStringValue(&mapint, cid, sizeof(cid), &n); + cbor_check(res); + PrintAndLog("credential id [%d]: %s", n, sprint_hex(cid, n)); + } + } + res = cbor_value_leave_container(&map, &mapint); + cbor_check(res); + + + + return 0; } From a0a979abc610bb53b458b3e5b08c727f500e3e71 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 27 Nov 2018 14:34:51 +0200 Subject: [PATCH 0257/1938] added show GetAssertion results --- client/cmdhffido.c | 4 +- client/fido/fidocore.c | 108 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 108 insertions(+), 4 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index b63f8582f..57f8e5f2b 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -886,7 +886,7 @@ int CmdHFFido2GetAssertion(const char *cmd) { // parse returned cbor FIDO2GetAssertionParseRes(root, &buf[1], len - 1, verbose, verbose2, showCBOR); -/* if (root) { + if (root) { res = json_dump_file(root, fname, JSON_INDENT(2)); if (res) { PrintAndLog("ERROR: can't save the file: %s", fname); @@ -894,7 +894,7 @@ int CmdHFFido2GetAssertion(const char *cmd) { } PrintAndLog("File `%s` saved.", fname); } -*/ + json_decref(root); return 0; diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 5c26785de..239c09ea3 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -605,8 +605,7 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool CborParser parser; CborValue map, mapint; int res; -// char *buf; -// uint8_t *ubuf; + uint8_t *ubuf; size_t n; // credential @@ -639,9 +638,114 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool res = cbor_value_leave_container(&map, &mapint); cbor_check(res); + // authData + uint8_t authData[400] = {0}; + size_t authDataLen = 0; + res = CborMapGetKeyById(&parser, &map, data, dataLen, 2); + if (res) + return res; + res = cbor_value_dup_byte_string(&map, &ubuf, &n, &map); + cbor_check(res); + authDataLen = n; + memcpy(authData, ubuf, authDataLen); + if (verbose2) { + PrintAndLog("authData[%d]: %s", n, sprint_hex_inrow(authData, authDataLen)); + } else { + PrintAndLog("authData[%d]: %s...", n, sprint_hex(authData, MIN(authDataLen, 16))); + } + PrintAndLog("RP ID Hash: %s", sprint_hex(ubuf, 32)); + + // check RP ID Hash + if (CheckrpIdHash(root, ubuf)) { + PrintAndLog("rpIdHash OK."); + } else { + PrintAndLog("rpIdHash ERROR!"); + } + + PrintAndLog("Flags 0x%02x:", ubuf[32]); + if (!ubuf[32]) + PrintAndLog("none"); + if (ubuf[32] & 0x01) + PrintAndLog("up - user presence result"); + if (ubuf[32] & 0x04) + PrintAndLog("uv - user verification (fingerprint scan or a PIN or ...) result"); + if (ubuf[32] & 0x40) + PrintAndLog("at - attested credential data included"); + if (ubuf[32] & 0x80) + PrintAndLog("ed - extension data included"); + + uint32_t cntr = (uint32_t)bytes_to_num(&ubuf[33], 4); + PrintAndLog("Counter: %d", cntr); + JsonSaveInt(root, "$.AppData.Counter", cntr); + + free(ubuf); + + // signature + res = CborMapGetKeyById(&parser, &map, data, dataLen, 3); + if (res) + return res; + res = cbor_value_dup_byte_string(&map, &ubuf, &n, &map); + cbor_check(res); + + uint8_t *sign = ubuf; + size_t signLen = n; + + cbor_check(res); + if (verbose2) { + PrintAndLog("signature [%d]: %s", signLen, sprint_hex_inrow(sign, signLen)); + } else { + PrintAndLog("signature [%d]: %s...", signLen, sprint_hex(sign, MIN(signLen, 16))); + } + + // get public key from json + uint8_t PublicKey[65] = {0}; + size_t PublicKeyLen = 0; + JsonLoadBufAsHex(root, "$.AppData.COSEPublicKey", PublicKey, 65, &PublicKeyLen); + PrintAndLog("--pkey[%d]: %s", PublicKeyLen, sprint_hex(PublicKey, PublicKeyLen)); + + // check ANSI X9.62 format ECDSA signature (on P-256) + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; + res = ecdsa_asn1_get_signature(sign, signLen, rval, sval); + if (!res) { + if (verbose) { + PrintAndLog(" r: %s", sprint_hex(rval, 32)); + PrintAndLog(" s: %s", sprint_hex(sval, 32)); + } + + uint8_t clientDataHash[32] = {0}; + size_t clientDataHashLen = 0; + res = JsonLoadBufAsHex(root, "$.ClientDataHash", clientDataHash, sizeof(clientDataHash), &clientDataHashLen); + if (res || clientDataHashLen != 32) { + PrintAndLog("ERROR: Can't get clientDataHash from json!"); + return 2; + } + + uint8_t xbuf[4096] = {0}; + size_t xbuflen = 0; + res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, + authData, authDataLen, // rpIdHash[32] + flags[1] + signCount[4] + clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json + NULL, 0); + PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); + res = ecdsa_signature_verify(PublicKey, xbuf, xbuflen, sign, signLen); + if (res) { + if (res == -0x4e00) { + PrintAndLog("Signature is NOT VALID."); + } else { + PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); + } + } else { + PrintAndLog("Signature is OK."); + } + } else { + PrintAndLog("Invalid signature. res=%d.", res); + } + + free(ubuf); return 0; } From ac5448a117f2d4cbd85a36c9c085f5143d22e738 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 27 Nov 2018 14:57:00 +0200 Subject: [PATCH 0258/1938] GetAssertion works --- client/fido/fidocore.c | 46 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 44 insertions(+), 2 deletions(-) diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 239c09ea3..a423a6434 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -682,6 +682,49 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool JsonSaveInt(root, "$.AppData.Counter", cntr); free(ubuf); + + // publicKeyCredentialUserEntity + res = CborMapGetKeyById(&parser, &map, data, dataLen, 4); + if (res) + return res; + + res = cbor_value_enter_container(&map, &mapint); + cbor_check(res); + + while (!cbor_value_at_end(&mapint)) { + char key[100] = {0}; + res = CborGetStringValue(&mapint, key, sizeof(key), &n); + cbor_check(res); + + if (!strcmp(key, "name") || !strcmp(key, "displayName")) { + char cname[200] = {0}; + res = CborGetStringValue(&mapint, cname, sizeof(cname), &n); + cbor_check(res); + PrintAndLog("UserEntity %s: %s", key, cname); + } + + if (!strcmp(key, "id")) { + uint8_t cid[200] = {0}; + res = CborGetBinStringValue(&mapint, cid, sizeof(cid), &n); + cbor_check(res); + PrintAndLog("UserEntity id [%d]: %s", n, sprint_hex(cid, n)); + + // check + uint8_t idbuf[100] = {0}; + size_t idbuflen; + + JsonLoadBufAsHex(root, "$.UserEntity.id", idbuf, sizeof(idbuf), &idbuflen); + + if (idbuflen == n && !memcmp(idbuf, cid, idbuflen)) { + PrintAndLog("UserEntity id OK."); + } else { + PrintAndLog("ERROR: Wrong UserEntity id (from json: %s)", sprint_hex(idbuf, idbuflen)); + } + } + } + res = cbor_value_leave_container(&map, &mapint); + cbor_check(res); + // signature res = CborMapGetKeyById(&parser, &map, data, dataLen, 3); @@ -704,7 +747,6 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool uint8_t PublicKey[65] = {0}; size_t PublicKeyLen = 0; JsonLoadBufAsHex(root, "$.AppData.COSEPublicKey", PublicKey, 65, &PublicKeyLen); - PrintAndLog("--pkey[%d]: %s", PublicKeyLen, sprint_hex(PublicKey, PublicKeyLen)); // check ANSI X9.62 format ECDSA signature (on P-256) uint8_t rval[300] = {0}; @@ -730,7 +772,7 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool authData, authDataLen, // rpIdHash[32] + flags[1] + signCount[4] clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json NULL, 0); - PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); + //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); res = ecdsa_signature_verify(PublicKey, xbuf, xbuflen, sign, signLen); if (res) { if (res == -0x4e00) { From d253364d2c822bea5e06f78a3a46d207f47f6b6d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 27 Nov 2018 15:47:17 +0200 Subject: [PATCH 0259/1938] added numberOfCredentials --- client/fido/fidocore.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index a423a6434..94bc7e929 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -788,6 +788,16 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool } free(ubuf); + + // numberOfCredentials + res = CborMapGetKeyById(&parser, &map, data, dataLen, 5); + if (res) { + PrintAndLog("numberOfCredentials: 1 by default"); + } else { + int64_t numberOfCredentials = 0; + cbor_value_get_int64(&map, &numberOfCredentials); + PrintAndLog("numberOfCredentials: %lld", (long long)numberOfCredentials); + } return 0; } From 71215aa4c920c2a2b3200de0cd28af0bbac73b8e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 27 Nov 2018 15:49:37 +0200 Subject: [PATCH 0260/1938] added changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a57924d70..221570783 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -83,6 +83,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added `hf fido` commands that work with FIDO U2F authenticators (@merlokk) - Added mbedtls instead of old polarssl (@merlokk) - Added jansson (@merlokk) + - Added `hf fido` `assert` and `make` commands from fido2 protocol (authenticatorMakeCredential and authenticatorGetAssertion) (@merlokk) ### Fixed - Changed driver file proxmark3.inf to support both old and new Product/Vendor IDs (piwi) - Changed start sequence in Qt mode (fix: short commands hangs main Qt thread) (Merlok) From 305c0c099b56a7b4cd92ee6b3c0677b740ed825b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 27 Nov 2018 15:59:28 +0200 Subject: [PATCH 0261/1938] refactoring --- client/fido/fidocore.c | 122 ++++++++++++++++------------------------- 1 file changed, 48 insertions(+), 74 deletions(-) diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 94bc7e929..1792550a4 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -352,6 +352,52 @@ bool CheckrpIdHash(json_t *json, uint8_t *hash) { return !memcmp(hash, hash2, 32); } +// check ANSI X9.62 format ECDSA signature (on P-256) +int FIDO2CheckSignature(json_t *root, uint8_t *publickey, uint8_t *sign, size_t signLen, uint8_t *authData, size_t authDataLen, bool verbose) { + int res; + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; + res = ecdsa_asn1_get_signature(sign, signLen, rval, sval); + if (!res) { + if (verbose) { + PrintAndLog(" r: %s", sprint_hex(rval, 32)); + PrintAndLog(" s: %s", sprint_hex(sval, 32)); + } + + uint8_t clientDataHash[32] = {0}; + size_t clientDataHashLen = 0; + res = JsonLoadBufAsHex(root, "$.ClientDataHash", clientDataHash, sizeof(clientDataHash), &clientDataHashLen); + if (res || clientDataHashLen != 32) { + PrintAndLog("ERROR: Can't get clientDataHash from json!"); + return 2; + } + + uint8_t xbuf[4096] = {0}; + size_t xbuflen = 0; + res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, + authData, authDataLen, // rpIdHash[32] + flags[1] + signCount[4] + clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json + NULL, 0); + //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); + res = ecdsa_signature_verify(publickey, xbuf, xbuflen, sign, signLen); + if (res) { + if (res == -0x4e00) { + PrintAndLog("Signature is NOT VALID."); + } else { + PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); + } + return res; + } else { + PrintAndLog("Signature is OK."); + } + } else { + PrintAndLog("Invalid signature. res=%d.", res); + return res; + } + + return 0; +} + int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR, bool showDERTLV) { CborParser parser; CborValue map, mapsmt; @@ -513,43 +559,7 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b JsonSaveBufAsHexCompact(root, "$.AppData.DERPublicKey", public_key, sizeof(public_key)); // check ANSI X9.62 format ECDSA signature (on P-256) - uint8_t rval[300] = {0}; - uint8_t sval[300] = {0}; - res = ecdsa_asn1_get_signature(sign, signLen, rval, sval); - if (!res) { - if (verbose) { - PrintAndLog(" r: %s", sprint_hex(rval, 32)); - PrintAndLog(" s: %s", sprint_hex(sval, 32)); - } - - uint8_t clientDataHash[32] = {0}; - size_t clientDataHashLen = 0; - res = JsonLoadBufAsHex(root, "$.ClientDataHash", clientDataHash, sizeof(clientDataHash), &clientDataHashLen); - if (res || clientDataHashLen != 32) { - PrintAndLog("ERROR: Can't get clientDataHash from json!"); - return 2; - } - - uint8_t xbuf[4096] = {0}; - size_t xbuflen = 0; - res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, - authData, authDataLen, // rpIdHash[32] + flags[1] + signCount[4] + ... - clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json - NULL, 0); - //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); - res = ecdsa_signature_verify(public_key, xbuf, xbuflen, sign, signLen); - if (res) { - if (res == -0x4e00) { - PrintAndLog("Signature is NOT VALID."); - } else { - PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); - } - } else { - PrintAndLog("Signature is OK."); - } - } else { - PrintAndLog("Invalid signature. res=%d.", res); - } + FIDO2CheckSignature(root, public_key, sign, signLen, authData, authDataLen, verbose); return 0; } @@ -749,43 +759,7 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool JsonLoadBufAsHex(root, "$.AppData.COSEPublicKey", PublicKey, 65, &PublicKeyLen); // check ANSI X9.62 format ECDSA signature (on P-256) - uint8_t rval[300] = {0}; - uint8_t sval[300] = {0}; - res = ecdsa_asn1_get_signature(sign, signLen, rval, sval); - if (!res) { - if (verbose) { - PrintAndLog(" r: %s", sprint_hex(rval, 32)); - PrintAndLog(" s: %s", sprint_hex(sval, 32)); - } - - uint8_t clientDataHash[32] = {0}; - size_t clientDataHashLen = 0; - res = JsonLoadBufAsHex(root, "$.ClientDataHash", clientDataHash, sizeof(clientDataHash), &clientDataHashLen); - if (res || clientDataHashLen != 32) { - PrintAndLog("ERROR: Can't get clientDataHash from json!"); - return 2; - } - - uint8_t xbuf[4096] = {0}; - size_t xbuflen = 0; - res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, - authData, authDataLen, // rpIdHash[32] + flags[1] + signCount[4] - clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json - NULL, 0); - //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); - res = ecdsa_signature_verify(PublicKey, xbuf, xbuflen, sign, signLen); - if (res) { - if (res == -0x4e00) { - PrintAndLog("Signature is NOT VALID."); - } else { - PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); - } - } else { - PrintAndLog("Signature is OK."); - } - } else { - PrintAndLog("Invalid signature. res=%d.", res); - } + FIDO2CheckSignature(root, PublicKey, sign, signLen, authData, authDataLen, verbose); free(ubuf); From c51e0a58f4a100e43c737c9fb070ff24a7e0d187 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 27 Nov 2018 19:33:51 +0200 Subject: [PATCH 0262/1938] added allowList to authenticatorGetAssertion command --- client/cmdhffido.c | 8 ++-- client/fido/fido2.json | 2 +- client/fido/fidocore.c | 102 ++++++++++++++++++++++++++--------------- client/fido/fidocore.h | 2 +- 4 files changed, 72 insertions(+), 42 deletions(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 57f8e5f2b..273982bed 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -783,13 +783,14 @@ int CmdHFFido2GetAssertion(const char *cmd) { CLIParserInit("hf fido assert", "Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", "Usage:\n\thf fido assert -> execute command default parameters file `fido2.json`\n" - "\thf fido assert test.json -> execute command with parameters file `text.json`"); + "\thf fido assert test.json -l -> execute command with parameters file `text.json` and add to request CredentialId"); void* argtable[] = { arg_param_begin, arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), arg_lit0("cC", "cbor", "show CBOR decoded data"), + arg_lit0("lL", "list", "add CredentialId from json to allowList. Needs if `rk` option is `false` (authenticator don't store credential to its memory)"), arg_str0(NULL, NULL, "", "JSON input / output file name for parameters. Default `fido2.json`"), arg_param_end }; @@ -799,11 +800,12 @@ int CmdHFFido2GetAssertion(const char *cmd) { bool verbose = arg_get_lit(2); bool verbose2 = arg_get_lit(2) > 1; bool showCBOR = arg_get_lit(3); + bool createAllowList = arg_get_lit(4); uint8_t jsonname[250] ={0}; char *cjsonname = (char *)jsonname; int jsonnamelen = 0; - CLIGetStrWithReturn(4, jsonname, &jsonnamelen); + CLIGetStrWithReturn(5, jsonname, &jsonnamelen); if (!jsonnamelen) { strcat(cjsonname, "fido2"); @@ -847,7 +849,7 @@ int CmdHFFido2GetAssertion(const char *cmd) { return 2; } - res = FIDO2CreateGetAssertionReq(root, data, sizeof(data), &datalen); + res = FIDO2CreateGetAssertionReq(root, data, sizeof(data), &datalen, createAllowList); if (res) return res; diff --git a/client/fido/fido2.json b/client/fido/fido2.json index 8ecd04103..abbfae5dc 100644 --- a/client/fido/fido2.json +++ b/client/fido/fido2.json @@ -24,7 +24,7 @@ ], "MakeCredentialOptions": { "uv": false, - "rk": false + "rk": true }, "GetAssertionOptions": { "up": true, diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 1792550a4..39c2052f9 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -564,7 +564,7 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b return 0; } -int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen) { +int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen, bool createAllowList) { if (datalen) *datalen = 0; if (!root || !data || !maxdatalen) @@ -572,19 +572,18 @@ int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, s int res; CborEncoder encoder; - CborEncoder map; + CborEncoder map, array, mapint; cbor_encoder_init(&encoder, data, maxdatalen, 0); // create main map - res = cbor_encoder_create_map(&encoder, &map, 3); + res = cbor_encoder_create_map(&encoder, &map, createAllowList ? 4 : 3); fido_check_if(res) { // rpId res = cbor_encode_uint(&map, 1); fido_check_if(res) { - - res = CBOREncodeElm(root, "$.RelyingPartyEntity.id", &map); - fido_check(res); + res = CBOREncodeElm(root, "$.RelyingPartyEntity.id", &map); + fido_check(res); } // clientDataHash @@ -594,6 +593,34 @@ int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, s fido_check(res); } + // allowList + if (createAllowList) { + res = cbor_encode_uint(&map, 3); + fido_check_if(res) { + res = cbor_encoder_create_array(&map, &array, 1); + fido_check_if(res) { + res = cbor_encoder_create_map(&array, &mapint, 2); + fido_check_if(res) { + res = cbor_encode_text_stringz(&mapint, "type"); + fido_check(res); + + res = cbor_encode_text_stringz(&mapint, "public-key"); + fido_check(res); + + res = cbor_encode_text_stringz(&mapint, "id"); + fido_check(res); + + res = CBOREncodeElm(root, "$.AppData.CredentialId", &mapint); + fido_check(res); + } + res = cbor_encoder_close_container(&array, &mapint); + fido_check(res); + } + res = cbor_encoder_close_container(&map, &array); + fido_check(res); + } + } + // options res = cbor_encode_uint(&map, 5); fido_check_if(res) { @@ -695,45 +722,46 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool // publicKeyCredentialUserEntity res = CborMapGetKeyById(&parser, &map, data, dataLen, 4); - if (res) - return res; - - res = cbor_value_enter_container(&map, &mapint); - cbor_check(res); - - while (!cbor_value_at_end(&mapint)) { - char key[100] = {0}; - res = CborGetStringValue(&mapint, key, sizeof(key), &n); + if (res) { + PrintAndLog("UserEntity n/a"); + } else { + res = cbor_value_enter_container(&map, &mapint); cbor_check(res); - - if (!strcmp(key, "name") || !strcmp(key, "displayName")) { - char cname[200] = {0}; - res = CborGetStringValue(&mapint, cname, sizeof(cname), &n); + + while (!cbor_value_at_end(&mapint)) { + char key[100] = {0}; + res = CborGetStringValue(&mapint, key, sizeof(key), &n); cbor_check(res); - PrintAndLog("UserEntity %s: %s", key, cname); - } - if (!strcmp(key, "id")) { - uint8_t cid[200] = {0}; - res = CborGetBinStringValue(&mapint, cid, sizeof(cid), &n); - cbor_check(res); - PrintAndLog("UserEntity id [%d]: %s", n, sprint_hex(cid, n)); - - // check - uint8_t idbuf[100] = {0}; - size_t idbuflen; + if (!strcmp(key, "name") || !strcmp(key, "displayName")) { + char cname[200] = {0}; + res = CborGetStringValue(&mapint, cname, sizeof(cname), &n); + cbor_check(res); + PrintAndLog("UserEntity %s: %s", key, cname); + } - JsonLoadBufAsHex(root, "$.UserEntity.id", idbuf, sizeof(idbuf), &idbuflen); + if (!strcmp(key, "id")) { + uint8_t cid[200] = {0}; + res = CborGetBinStringValue(&mapint, cid, sizeof(cid), &n); + cbor_check(res); + PrintAndLog("UserEntity id [%d]: %s", n, sprint_hex(cid, n)); + + // check + uint8_t idbuf[100] = {0}; + size_t idbuflen; - if (idbuflen == n && !memcmp(idbuf, cid, idbuflen)) { - PrintAndLog("UserEntity id OK."); - } else { - PrintAndLog("ERROR: Wrong UserEntity id (from json: %s)", sprint_hex(idbuf, idbuflen)); + JsonLoadBufAsHex(root, "$.UserEntity.id", idbuf, sizeof(idbuf), &idbuflen); + + if (idbuflen == n && !memcmp(idbuf, cid, idbuflen)) { + PrintAndLog("UserEntity id OK."); + } else { + PrintAndLog("ERROR: Wrong UserEntity id (from json: %s)", sprint_hex(idbuf, idbuflen)); + } } } + res = cbor_value_leave_container(&map, &mapint); + cbor_check(res); } - res = cbor_value_leave_container(&map, &mapint); - cbor_check(res); // signature diff --git a/client/fido/fidocore.h b/client/fido/fidocore.h index 092261104..b0b50e2ac 100644 --- a/client/fido/fidocore.h +++ b/client/fido/fidocore.h @@ -51,7 +51,7 @@ extern char *fido2GetCmdErrorDescription(uint8_t errorCode); extern bool CheckrpIdHash(json_t *json, uint8_t *hash); extern int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen); extern int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR, bool showDERTLV); -extern int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen); +extern int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, size_t *datalen, bool createAllowList); extern int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool verbose, bool verbose2, bool showCBOR); #endif /* __FIDOCORE_H__ */ From 04b436ce5ecf13d1565be3e8e56c217760b6e467 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 27 Nov 2018 19:44:03 +0200 Subject: [PATCH 0263/1938] del annoying comment --- client/loclass/fileutils.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index ac3660935..ea595ad26 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -163,7 +163,6 @@ int saveFileJSON(const char *preferredName, const char *suffix, uint8_t* data, s } PrintAndLog("File `%s` saved.", fileName); - // free json object json_decref(root); out: From 91809c6d9410a718a24d2d3ae7e84a220ebd20bd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 28 Nov 2018 23:53:31 +0100 Subject: [PATCH 0264/1938] FIX: part of https://github.com/Proxmark/proxmark3/pull/723 (@Fl0-0) CHG: remove some warnings when compiling on 32/64 bit systems. Messy messy --- client/crypto/asn1dump.c | 2 ++ client/fido/cbortools.c | 9 +++++++-- client/fpga_compress.c | 9 ++++++++- 3 files changed, 17 insertions(+), 3 deletions(-) diff --git a/client/crypto/asn1dump.c b/client/crypto/asn1dump.c index 60799fc8c..34f4a9fa4 100644 --- a/client/crypto/asn1dump.c +++ b/client/crypto/asn1dump.c @@ -7,12 +7,14 @@ //----------------------------------------------------------------------------- // asn.1 dumping //----------------------------------------------------------------------------- +#define _POSIX_C_SOURCE 200809L // need for strnlen() #include "asn1dump.h" #include #include #include #include +#include #include #include #include diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index 8ab104a1c..01691dad1 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -203,8 +203,13 @@ int TinyCborPrintFIDOPackage(uint8_t cmdCode, bool isResponse, uint8_t *data, si CborError err = dumprecursive(cmdCode, isResponse, &cb, false, 0); if (err) { - fprintf(stderr, "CBOR parsing failure at offset %d: %s\n", - cb.ptr - data, cbor_error_string(err)); + fprintf(stderr, +#if __WORDSIZE == 64 + "CBOR parsing failure at offset %" PRId64 " : %s\n", +#else + "CBOR parsing failure at offset %" PRId32 " : %s\n", +#endif + cb.ptr - data, cbor_error_string(err)); return 1; } diff --git a/client/fpga_compress.c b/client/fpga_compress.c index ce0f41982..ceba6ac64 100644 --- a/client/fpga_compress.c +++ b/client/fpga_compress.c @@ -99,7 +99,14 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardn if (i >= num_infiles * (hardnested_mode ? HARDNESTED_TABLE_SIZE : FPGA_CONFIG_SIZE)) { if (hardnested_mode) { - fprintf(stderr, "Input file too big (> %llu bytes). This is probably not a hardnested bitflip state table.\n", HARDNESTED_TABLE_SIZE); + fprintf(stderr, +#if __WORDSIZE == 64 + "Input file too big (> %" PRIu64 " bytes). This is probably not a hardnested bitflip state table.\n" +#else + "Input file too big (> %lu bytes). This is probably not a hardnested bitflip state table.\n" +#endif + , HARDNESTED_TABLE_SIZE); + } else { fprintf(stderr, "Input files too big (total > %lu bytes). These are probably not PM3 FPGA config files.\n", num_infiles * FPGA_CONFIG_SIZE); } From 5d5e2739829c255c78dc7d56389adf8a03debeb9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 29 Nov 2018 12:00:23 +0200 Subject: [PATCH 0265/1938] jansson update. 2.11 to 2.12 fix warnings --- client/jansson/dump.c | 12 +- client/jansson/error.c | 2 +- client/jansson/hashtable.h | 2 +- client/jansson/hashtable_seed.c | 2 +- client/jansson/jansson.h | 45 +++--- client/jansson/jansson_private.h | 8 +- client/jansson/load.c | 14 +- client/jansson/pack_unpack.c | 231 ++++++++++++++++++------------- client/jansson/strbuffer.h | 2 +- client/jansson/value.c | 30 ++-- 10 files changed, 194 insertions(+), 154 deletions(-) diff --git a/client/jansson/dump.c b/client/jansson/dump.c index 8e725c934..89802c65d 100644 --- a/client/jansson/dump.c +++ b/client/jansson/dump.c @@ -61,8 +61,8 @@ static int dump_to_file(const char *buffer, size_t size, void *data) static int dump_to_fd(const char *buffer, size_t size, void *data) { - int *dest = (int *)data; #ifdef HAVE_UNISTD_H + int *dest = (int *)data; if(write(*dest, buffer, size) == (ssize_t)size) return 0; #endif @@ -101,7 +101,7 @@ static int dump_indent(size_t flags, int depth, int space, json_dump_callback_t static int dump_string(const char *str, size_t len, json_dump_callback_t dump, void *data, size_t flags) { const char *pos, *end, *lim; - int32_t codepoint; + int32_t codepoint = 0; if(dump("\"", 1, data)) return -1; @@ -306,7 +306,7 @@ static int do_dump(const json_t *json, size_t flags, int depth, const char *separator; int separator_length; /* Space for "0x", double the sizeof a pointer for the hex and a terminator. */ - char key[2 + (sizeof(json) * 2) + 1]; + char loop_key[2 + (sizeof(json) * 2) + 1]; if(flags & JSON_COMPACT) { separator = ":"; @@ -318,7 +318,7 @@ static int do_dump(const json_t *json, size_t flags, int depth, } /* detect circular references */ - if (loop_check(parents, json, key, sizeof(key))) + if (loop_check(parents, json, loop_key, sizeof(loop_key))) return -1; iter = json_object_iter((json_t *)json); @@ -326,7 +326,7 @@ static int do_dump(const json_t *json, size_t flags, int depth, if(!embed && dump("{", 1, data)) return -1; if(!iter) { - hashtable_del(parents, key); + hashtable_del(parents, loop_key); return embed ? 0 : dump("}", 1, data); } if(dump_indent(flags, depth + 1, 0, dump, data)) @@ -422,7 +422,7 @@ static int do_dump(const json_t *json, size_t flags, int depth, } } - hashtable_del(parents, key); + hashtable_del(parents, loop_key); return embed ? 0 : dump("}", 1, data); } diff --git a/client/jansson/error.c b/client/jansson/error.c index b94b3a3a1..f5da6b9b0 100644 --- a/client/jansson/error.c +++ b/client/jansson/error.c @@ -25,7 +25,7 @@ void jsonp_error_set_source(json_error_t *error, const char *source) length = strlen(source); if(length < JSON_ERROR_SOURCE_LENGTH) - strncpy(error->source, source, JSON_ERROR_SOURCE_LENGTH); + strncpy(error->source, source, length + 1); else { size_t extra = length - JSON_ERROR_SOURCE_LENGTH + 4; memcpy(error->source, "...", 3); diff --git a/client/jansson/hashtable.h b/client/jansson/hashtable.h index d4c32ae0e..c11283408 100644 --- a/client/jansson/hashtable.h +++ b/client/jansson/hashtable.h @@ -55,7 +55,7 @@ typedef struct hashtable { * * Returns 0 on success, -1 on error (out of memory). */ -int hashtable_init(hashtable_t *hashtable); +int hashtable_init(hashtable_t *hashtable) JANSSON_ATTRS(warn_unused_result); /** * hashtable_close - Release all resources used by a hashtable object diff --git a/client/jansson/hashtable_seed.c b/client/jansson/hashtable_seed.c index 8aed54068..540358ada 100644 --- a/client/jansson/hashtable_seed.c +++ b/client/jansson/hashtable_seed.c @@ -164,7 +164,7 @@ static int seed_from_timestamp_and_pid(uint32_t *seed) { } static uint32_t generate_seed() { - uint32_t seed; + uint32_t seed = 0; int done = 0; #if !defined(_WIN32) && defined(USE_URANDOM) diff --git a/client/jansson/jansson.h b/client/jansson/jansson.h index 86f23d17e..12f638bc3 100644 --- a/client/jansson/jansson.h +++ b/client/jansson/jansson.h @@ -9,7 +9,6 @@ #define JANSSON_H #include -#include #include /* for size_t */ #include @@ -22,11 +21,11 @@ extern "C" { /* version */ #define JANSSON_MAJOR_VERSION 2 -#define JANSSON_MINOR_VERSION 11 +#define JANSSON_MINOR_VERSION 12 #define JANSSON_MICRO_VERSION 0 /* Micro version is omitted if it's 0 */ -#define JANSSON_VERSION "2.11" +#define JANSSON_VERSION "2.12" /* Version as a 3-byte hex number, e.g. 0x010201 == 1.2.1. Use this for numeric comparisons, e.g. #if JANSSON_VERSION_HEX >= ... */ @@ -40,6 +39,12 @@ extern "C" { #define JANSSON_THREAD_SAFE_REFCOUNT 1 #endif +#if defined(__GNUC__) || defined(__clang__) +#define JANSSON_ATTRS(...) __attribute__((__VA_ARGS__)) +#else +#define JANSSON_ATTRS(...) +#endif + /* types */ typedef enum { @@ -186,7 +191,7 @@ static JSON_INLINE enum json_error_code json_error_code(const json_error_t *e) { void json_object_seed(size_t seed); size_t json_object_size(const json_t *object); -json_t *json_object_get(const json_t *object, const char *key); +json_t *json_object_get(const json_t *object, const char *key) JANSSON_ATTRS(warn_unused_result); int json_object_set_new(json_t *object, const char *key, json_t *value); int json_object_set_new_nocheck(json_t *object, const char *key, json_t *value); int json_object_del(json_t *object, const char *key); @@ -238,7 +243,7 @@ int json_object_iter_set(json_t *object, void *iter, json_t *value) } size_t json_array_size(const json_t *array); -json_t *json_array_get(const json_t *array, size_t index); +json_t *json_array_get(const json_t *array, size_t index) JANSSON_ATTRS(warn_unused_result); int json_array_set_new(json_t *array, size_t index, json_t *value); int json_array_append_new(json_t *array, json_t *value); int json_array_insert_new(json_t *array, size_t index, json_t *value); @@ -279,9 +284,9 @@ int json_real_set(json_t *real, double value); /* pack, unpack */ -json_t *json_pack(const char *fmt, ...); -json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...); -json_t *json_vpack_ex(json_error_t *error, size_t flags, const char *fmt, va_list ap); +json_t *json_pack(const char *fmt, ...) JANSSON_ATTRS(warn_unused_result); +json_t *json_pack_ex(json_error_t *error, size_t flags, const char *fmt, ...) JANSSON_ATTRS(warn_unused_result); +json_t *json_vpack_ex(json_error_t *error, size_t flags, const char *fmt, va_list ap) JANSSON_ATTRS(warn_unused_result); #define JSON_VALIDATE_ONLY 0x1 #define JSON_STRICT 0x2 @@ -292,8 +297,8 @@ int json_vunpack_ex(json_t *root, json_error_t *error, size_t flags, const char /* sprintf */ -json_t *json_sprintf(const char *fmt, ...); -json_t *json_vsprintf(const char *fmt, va_list ap); +json_t *json_sprintf(const char *fmt, ...) JANSSON_ATTRS(warn_unused_result, format(printf, 1, 2)); +json_t *json_vsprintf(const char *fmt, va_list ap) JANSSON_ATTRS(warn_unused_result, format(printf, 1, 0)); /* equality */ @@ -303,10 +308,8 @@ int json_equal(const json_t *value1, const json_t *value2); /* copying */ -json_t *json_copy(json_t *value); -json_t *json_deep_copy(const json_t *value); - -/* path */ +json_t *json_copy(json_t *value) JANSSON_ATTRS(warn_unused_result); +json_t *json_deep_copy(const json_t *value) JANSSON_ATTRS(warn_unused_result); json_t *json_path_get(const json_t *json, const char *path); int json_path_set_new(json_t *json, const char *path, json_t *value, size_t flags, json_error_t *error); @@ -327,12 +330,12 @@ int json_path_set(json_t *json, const char *path, json_t *value, size_t flags, j typedef size_t (*json_load_callback_t)(void *buffer, size_t buflen, void *data); -json_t *json_loads(const char *input, size_t flags, json_error_t *error); -json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error); -json_t *json_loadf(FILE *input, size_t flags, json_error_t *error); -json_t *json_loadfd(int input, size_t flags, json_error_t *error); -json_t *json_load_file(const char *path, size_t flags, json_error_t *error); -json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error); +json_t *json_loads(const char *input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); +json_t *json_loadb(const char *buffer, size_t buflen, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); +json_t *json_loadf(FILE *input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); +json_t *json_loadfd(int input, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); +json_t *json_load_file(const char *path, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); +json_t *json_load_callback(json_load_callback_t callback, void *data, size_t flags, json_error_t *error) JANSSON_ATTRS(warn_unused_result); /* encoding */ @@ -350,7 +353,7 @@ json_t *json_load_callback(json_load_callback_t callback, void *data, size_t fla typedef int (*json_dump_callback_t)(const char *buffer, size_t size, void *data); -char *json_dumps(const json_t *json, size_t flags); +char *json_dumps(const json_t *json, size_t flags) JANSSON_ATTRS(warn_unused_result); size_t json_dumpb(const json_t *json, char *buffer, size_t size, size_t flags); int json_dumpf(const json_t *json, FILE *output, size_t flags); int json_dumpfd(const json_t *json, int output, size_t flags); diff --git a/client/jansson/jansson_private.h b/client/jansson/jansson_private.h index 7b0985aa6..083604b4d 100644 --- a/client/jansson/jansson_private.h +++ b/client/jansson/jansson_private.h @@ -87,11 +87,11 @@ int jsonp_strtod(strbuffer_t *strbuffer, double *out); int jsonp_dtostr(char *buffer, size_t size, double value, int prec); /* Wrappers for custom memory functions */ -void* jsonp_malloc(size_t size); +void* jsonp_malloc(size_t size) JANSSON_ATTRS(warn_unused_result); void jsonp_free(void *ptr); -char *jsonp_strndup(const char *str, size_t length); -char *jsonp_strdup(const char *str); -char *jsonp_strndup(const char *str, size_t len); +char *jsonp_strndup(const char *str, size_t length) JANSSON_ATTRS(warn_unused_result); +char *jsonp_strdup(const char *str) JANSSON_ATTRS(warn_unused_result); +char *jsonp_strndup(const char *str, size_t len) JANSSON_ATTRS(warn_unused_result); /* Windows compatibility */ diff --git a/client/jansson/load.c b/client/jansson/load.c index 4cf3855af..8700919fd 100644 --- a/client/jansson/load.c +++ b/client/jansson/load.c @@ -89,7 +89,7 @@ static void error_set(json_error_t *error, const lex_t *lex, { va_list ap; char msg_text[JSON_ERROR_TEXT_LENGTH]; - char msg_with_context[JSON_ERROR_TEXT_LENGTH + 28]; + char msg_with_context[JSON_ERROR_TEXT_LENGTH]; int line = -1, col = -1; size_t pos = 0; @@ -114,7 +114,7 @@ static void error_set(json_error_t *error, const lex_t *lex, if(saved_text && saved_text[0]) { if(lex->saved_text.length <= 20) { - snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH + 28, + snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near '%s'", msg_text, saved_text); msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0'; result = msg_with_context; @@ -131,7 +131,7 @@ static void error_set(json_error_t *error, const lex_t *lex, result = msg_text; } else { - snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH + 17, + snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near end of file", msg_text); msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0'; result = msg_with_context; @@ -829,10 +829,8 @@ static json_t *parse_value(lex_t *lex, size_t flags, json_error_t *error) } json = jsonp_stringn_nocheck_own(value, len); - if(json) { - lex->value.string.val = NULL; - lex->value.string.len = 0; - } + lex->value.string.val = NULL; + lex->value.string.len = 0; break; } @@ -1036,8 +1034,8 @@ json_t *json_loadf(FILE *input, size_t flags, json_error_t *error) static int fd_get_func(int *fd) { - uint8_t c; #ifdef HAVE_UNISTD_H + uint8_t c; if (read(*fd, &c, 1) == 1) return c; #endif diff --git a/client/jansson/pack_unpack.c b/client/jansson/pack_unpack.c index 153f64d19..3b9977667 100644 --- a/client/jansson/pack_unpack.c +++ b/client/jansson/pack_unpack.c @@ -75,6 +75,9 @@ static void next_token(scanner_t *s) return; } + if (!token(s) && !*s->fmt) + return; + t = s->fmt; s->column++; s->pos++; @@ -97,7 +100,7 @@ static void next_token(scanner_t *s) s->token.column = s->column; s->token.pos = s->pos; - t++; + if (*t) t++; s->fmt = t; } @@ -127,7 +130,7 @@ static json_t *pack(scanner_t *s, va_list *ap); /* ours will be set to 1 if jsonp_free() must be called for the result afterwards */ static char *read_string(scanner_t *s, va_list *ap, - const char *purpose, size_t *out_len, int *ours) + const char *purpose, size_t *out_len, int *ours, int optional) { char t; strbuffer_t strbuff; @@ -144,7 +147,10 @@ static char *read_string(scanner_t *s, va_list *ap, str = va_arg(*ap, const char *); if(!str) { - set_error(s, "", json_error_null_value, "NULL string argument"); + if (!optional) { + set_error(s, "", json_error_null_value, "NULL %s", purpose); + s->has_error = 1; + } return NULL; } @@ -152,19 +158,28 @@ static char *read_string(scanner_t *s, va_list *ap, if(!utf8_check_string(str, length)) { set_error(s, "", json_error_invalid_utf8, "Invalid UTF-8 %s", purpose); + s->has_error = 1; return NULL; } *out_len = length; return (char *)str; + } else if (optional) { + set_error(s, "", json_error_invalid_format, "Cannot use '%c' on optional strings", t); + s->has_error = 1; + + return NULL; } - strbuffer_init(&strbuff); + if(strbuffer_init(&strbuff)) { + set_error(s, "", json_error_out_of_memory, "Out of memory"); + s->has_error = 1; + } while(1) { str = va_arg(*ap, const char *); if(!str) { - set_error(s, "", json_error_null_value, "NULL string argument"); + set_error(s, "", json_error_null_value, "NULL %s", purpose); s->has_error = 1; } @@ -220,6 +235,7 @@ static json_t *pack_object(scanner_t *s, va_list *ap) size_t len; int ours; json_t *value; + char valueOptional; if(!token(s)) { set_error(s, "", json_error_invalid_format, "Unexpected end of format string"); @@ -231,20 +247,21 @@ static json_t *pack_object(scanner_t *s, va_list *ap) goto error; } - key = read_string(s, ap, "object key", &len, &ours); - if (!key) - s->has_error = 1; + key = read_string(s, ap, "object key", &len, &ours, 0); next_token(s); + next_token(s); + valueOptional = token(s); + prev_token(s); + value = pack(s, ap); if(!value) { if(ours) jsonp_free(key); - if(strchr("soO", token(s)) && s->next_token.token == '*') { - next_token(s); - } else { + if(valueOptional != '*') { + set_error(s, "", json_error_null_value, "NULL object value"); s->has_error = 1; } @@ -263,8 +280,6 @@ static json_t *pack_object(scanner_t *s, va_list *ap) if(ours) jsonp_free(key); - if(strchr("soO", token(s)) && s->next_token.token == '*') - next_token(s); next_token(s); } @@ -283,6 +298,7 @@ static json_t *pack_array(scanner_t *s, va_list *ap) while(token(s) != ']') { json_t *value; + char valueOptional; if(!token(s)) { set_error(s, "", json_error_invalid_format, "Unexpected end of format string"); @@ -290,11 +306,13 @@ static json_t *pack_array(scanner_t *s, va_list *ap) goto error; } + next_token(s); + valueOptional = token(s); + prev_token(s); + value = pack(s, ap); if(!value) { - if(strchr("soO", token(s)) && s->next_token.token == '*') { - next_token(s); - } else { + if(valueOptional != '*') { s->has_error = 1; } @@ -310,8 +328,6 @@ static json_t *pack_array(scanner_t *s, va_list *ap) s->has_error = 1; } - if(strchr("soO", token(s)) && s->next_token.token == '*') - next_token(s); next_token(s); } @@ -326,23 +342,97 @@ error: static json_t *pack_string(scanner_t *s, va_list *ap) { char *str; + char t; size_t len; int ours; - int nullable; + int optional; next_token(s); - nullable = token(s) == '?'; - if (!nullable) + t = token(s); + optional = t == '?' || t == '*'; + if (!optional) prev_token(s); - str = read_string(s, ap, "string", &len, &ours); - if (!str) { - return nullable ? json_null() : NULL; - } else if (ours) { - return jsonp_stringn_nocheck_own(str, len); - } else { - return json_stringn_nocheck(str, len); + str = read_string(s, ap, "string", &len, &ours, optional); + + if (!str) + return t == '?' && !s->has_error ? json_null() : NULL; + + if (s->has_error) { + /* It's impossible to reach this point if ours != 0, do not free str. */ + return NULL; } + + if (ours) + return jsonp_stringn_nocheck_own(str, len); + + return json_stringn_nocheck(str, len); +} + +static json_t *pack_object_inter(scanner_t *s, va_list *ap, int need_incref) +{ + json_t *json; + char ntoken; + + next_token(s); + ntoken = token(s); + + if (ntoken != '?' && ntoken != '*') + prev_token(s); + + json = va_arg(*ap, json_t *); + + if (json) + return need_incref ? json_incref(json) : json; + + switch (ntoken) { + case '?': + return json_null(); + case '*': + return NULL; + default: + break; + } + + set_error(s, "", json_error_null_value, "NULL object"); + s->has_error = 1; + return NULL; +} + +static json_t *pack_integer(scanner_t *s, json_int_t value) +{ + json_t *json = json_integer(value); + + if (!json) { + set_error(s, "", json_error_out_of_memory, "Out of memory"); + s->has_error = 1; + } + + return json; +} + +static json_t *pack_real(scanner_t *s, double value) +{ + /* Allocate without setting value so we can identify OOM error. */ + json_t *json = json_real(0.0); + + if (!json) { + set_error(s, "", json_error_out_of_memory, "Out of memory"); + s->has_error = 1; + + return NULL; + } + + if (json_real_set(json, value)) { + json_decref(json); + + set_error(s, "", json_error_numeric_overflow, "Invalid floating point value"); + s->has_error = 1; + + return NULL; + } + + return json; } static json_t *pack(scanner_t *s, va_list *ap) @@ -364,49 +454,19 @@ static json_t *pack(scanner_t *s, va_list *ap) return va_arg(*ap, int) ? json_true() : json_false(); case 'i': /* integer from int */ - return json_integer(va_arg(*ap, int)); + return pack_integer(s, va_arg(*ap, int)); case 'I': /* integer from json_int_t */ - return json_integer(va_arg(*ap, json_int_t)); + return pack_integer(s, va_arg(*ap, json_int_t)); case 'f': /* real */ - return json_real(va_arg(*ap, double)); + return pack_real(s, va_arg(*ap, double)); case 'O': /* a json_t object; increments refcount */ - { - int nullable; - json_t *json; - - next_token(s); - nullable = token(s) == '?'; - if (!nullable) - prev_token(s); - - json = va_arg(*ap, json_t *); - if (!json && nullable) { - return json_null(); - } else { - return json_incref(json); - } - } + return pack_object_inter(s, ap, 1); case 'o': /* a json_t object; doesn't increment refcount */ - { - int nullable; - json_t *json; - - next_token(s); - nullable = token(s) == '?'; - if (!nullable) - prev_token(s); - - json = va_arg(*ap, json_t *); - if (!json && nullable) { - return json_null(); - } else { - return json; - } - } + return pack_object_inter(s, ap, 0); default: set_error(s, "", json_error_invalid_format, "Unexpected format character '%c'", @@ -508,48 +568,34 @@ static int unpack_object(scanner_t *s, json_t *root, va_list *ap) if(root && strict == 1) { /* We need to check that all non optional items have been parsed */ const char *key; - int have_unrecognized_keys = 0; + /* keys_res is 1 for uninitialized, 0 for success, -1 for error. */ + int keys_res = 1; strbuffer_t unrecognized_keys; json_t *value; long unpacked = 0; - if (gotopt) { - /* We have optional keys, we need to iter on each key */ + + if (gotopt || json_object_size(root) != key_set.size) { json_object_foreach(root, key, value) { if(!hashtable_get(&key_set, key)) { unpacked++; /* Save unrecognized keys for the error message */ - if (!have_unrecognized_keys) { - strbuffer_init(&unrecognized_keys); - have_unrecognized_keys = 1; - } else { - strbuffer_append_bytes(&unrecognized_keys, ", ", 2); + if (keys_res == 1) { + keys_res = strbuffer_init(&unrecognized_keys); + } else if (!keys_res) { + keys_res = strbuffer_append_bytes(&unrecognized_keys, ", ", 2); } - strbuffer_append_bytes(&unrecognized_keys, key, strlen(key)); + + if (!keys_res) + keys_res = strbuffer_append_bytes(&unrecognized_keys, key, strlen(key)); } } - } else { - /* No optional keys, we can just compare the number of items */ - unpacked = (long)json_object_size(root) - (long)key_set.size; } if (unpacked) { - if (!gotopt) { - /* Save unrecognized keys for the error message */ - json_object_foreach(root, key, value) { - if(!hashtable_get(&key_set, key)) { - if (!have_unrecognized_keys) { - strbuffer_init(&unrecognized_keys); - have_unrecognized_keys = 1; - } else { - strbuffer_append_bytes(&unrecognized_keys, ", ", 2); - } - strbuffer_append_bytes(&unrecognized_keys, key, strlen(key)); - } - } - } set_error(s, "", json_error_end_of_input_expected, "%li object item(s) left unpacked: %s", - unpacked, strbuffer_value(&unrecognized_keys)); + unpacked, + keys_res ? "" : strbuffer_value(&unrecognized_keys)); strbuffer_close(&unrecognized_keys); goto out; } @@ -805,6 +851,7 @@ json_t *json_vpack_ex(json_error_t *error, size_t flags, value = pack(&s, &ap_copy); va_end(ap_copy); + /* This will cover all situations where s.has_error is true */ if(!value) return NULL; @@ -814,10 +861,6 @@ json_t *json_vpack_ex(json_error_t *error, size_t flags, set_error(&s, "", json_error_invalid_format, "Garbage after format string"); return NULL; } - if(s.has_error) { - json_decref(value); - return NULL; - } return value; } diff --git a/client/jansson/strbuffer.h b/client/jansson/strbuffer.h index 615b7f5ff..a0276d4b1 100644 --- a/client/jansson/strbuffer.h +++ b/client/jansson/strbuffer.h @@ -16,7 +16,7 @@ typedef struct { size_t size; /* bytes allocated */ } strbuffer_t; -int strbuffer_init(strbuffer_t *strbuff); +int strbuffer_init(strbuffer_t *strbuff) JANSSON_ATTRS(warn_unused_result); void strbuffer_close(strbuffer_t *strbuff); void strbuffer_clear(strbuffer_t *strbuff); diff --git a/client/jansson/value.c b/client/jansson/value.c index b3b31412b..3f964a041 100644 --- a/client/jansson/value.c +++ b/client/jansson/value.c @@ -652,8 +652,7 @@ static json_t *string_create(const char *value, size_t len, int own) string = jsonp_malloc(sizeof(json_string_t)); if(!string) { - if(!own) - jsonp_free(v); + jsonp_free(v); return NULL; } json_init(&string->json, JSON_STRING); @@ -768,9 +767,6 @@ static int json_string_equal(const json_t *string1, const json_t *string2) { json_string_t *s1, *s2; - if(!json_is_string(string1) || !json_is_string(string2)) - return 0; - s1 = json_to_string(string1); s2 = json_to_string(string2); return s1->length == s2->length && !memcmp(s1->value, s2->value, s1->length); @@ -780,34 +776,38 @@ static json_t *json_string_copy(const json_t *string) { json_string_t *s; - if(!json_is_string(string)) - return NULL; - s = json_to_string(string); return json_stringn_nocheck(s->value, s->length); } json_t *json_vsprintf(const char *fmt, va_list ap) { + json_t *json = NULL; int length; char *buf; va_list aq; va_copy(aq, ap); length = vsnprintf(NULL, 0, fmt, ap); - if (length == 0) - return json_string(""); + if (length == 0) { + json = json_string(""); + goto out; + } buf = jsonp_malloc(length + 1); if (!buf) - return NULL; + goto out; vsnprintf(buf, length + 1, fmt, aq); if (!utf8_check_string(buf, length)) { jsonp_free(buf); - return NULL; + goto out; } - return jsonp_stringn_nocheck_own(buf, length); + json = jsonp_stringn_nocheck_own(buf, length); + +out: + va_end(aq); + return json; } json_t *json_sprintf(const char *fmt, ...) { @@ -1044,8 +1044,6 @@ json_t *json_copy(json_t *json) default: return NULL; } - - return NULL; } json_t *json_deep_copy(const json_t *json) @@ -1073,6 +1071,4 @@ json_t *json_deep_copy(const json_t *json) default: return NULL; } - - return NULL; } From 0ffddd8470eabef829e9e7250ab52a419c719b8f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 29 Nov 2018 13:21:38 +0200 Subject: [PATCH 0266/1938] raw load file --- client/loclass/fileutils.c | 34 +++++++++++++++++++++++++++++++--- client/loclass/fileutils.h | 3 ++- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index ea595ad26..f1431ee52 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -283,10 +283,38 @@ out: return retval; } -int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t* datalen) { - //stub - for merlokk ;) +int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t maxdatalen, size_t* datalen) { datalen = 0; - return 1; + json_t *root; + json_error_t error; + + if ( preferredName == NULL ) return 1; + if ( suffix == NULL ) return 1; + + int retval = 0; + int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10); + char * fileName = calloc(size, sizeof(char)); + sprintf(fileName,"%s.%s", preferredName, suffix); + + root = json_load_file(fileName, 0, &error); + if (!root) { + PrintAndLog("ERROR: json (%s) error on line %d: %s", fileName, error.line, error.text); + retval = 2; + goto out; + } + + if (!json_is_object(root)) { + PrintAndLog("ERROR: Invalid json (%s) format. root must be an object.", fileName); + retval = 3; + goto out; + } + + JsonLoadBufAsHex(root, "$.raw", data, maxdatalen, datalen); + +out: + json_decref(root); + free(fileName); + return retval; } #else //if we're on ARM diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index 0893e01ea..c699be3de 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -122,10 +122,11 @@ extern int loadFileEML(const char *preferredName, const char *suffix, void* data * @param preferredName * @param suffix the file suffix. Leave out the ".". * @param data The data array to store the loaded bytes from file + * @param maxdatalen maximum size of data array in bytes * @param datalen the number of bytes loaded from file * @return 0 for ok, 1 for failz */ -extern int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t* datalen); +extern int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t maxdatalen, size_t* datalen); #define PrintAndLogDevice(level, format, args...) PrintAndLogEx(level, format , ## args) #else From e6d7a0572192f9b1fdc3370810cef5062a043e2e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 29 Nov 2018 13:42:07 +0200 Subject: [PATCH 0267/1938] csave works --- client/cmdhfmf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 03875401c..c90a11968 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2878,6 +2878,7 @@ int CmdHF14AMfCSave(const char *Cmd) { saveFile(filename, "bin", dump, bytes); saveFileEML(filename, "eml", dump, bytes, MFBLOCK_SIZE); + saveFileJSON(filename, "json", dump, bytes); free(dump); return 0; } From 955ced6c28a31eb30fb0eab96d5f4fe8ff0d885f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 29 Nov 2018 16:05:57 +0200 Subject: [PATCH 0268/1938] hf mf csave works --- client/cmdhfmf.c | 2 +- client/loclass/fileutils.c | 55 ++++++++++++++++++++++++++++++++++++-- client/loclass/fileutils.h | 9 ++++++- client/mifare4.c | 46 +++++++++++++++++++++++++++++++ client/mifare4.h | 7 +++++ 5 files changed, 115 insertions(+), 4 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index c90a11968..b14dde768 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2878,7 +2878,7 @@ int CmdHF14AMfCSave(const char *Cmd) { saveFile(filename, "bin", dump, bytes); saveFileEML(filename, "eml", dump, bytes, MFBLOCK_SIZE); - saveFileJSON(filename, "json", dump, bytes); + saveFileJSON(filename, "json", jsfCardMemory, dump, bytes); free(dump); return 0; } diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index f1431ee52..f110e02fc 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -135,7 +135,7 @@ out: return retval; } -int saveFileJSON(const char *preferredName, const char *suffix, uint8_t* data, size_t datalen) { +int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType ftype, uint8_t* data, size_t datalen) { if ( preferredName == NULL ) return 1; if ( suffix == NULL ) return 1; if ( data == NULL ) return 1; @@ -152,7 +152,58 @@ int saveFileJSON(const char *preferredName, const char *suffix, uint8_t* data, s json_t *root = json_object(); JsonSaveStr(root, "Created", "proxmark3"); - JsonSaveBufAsHexCompact(root, "raw", data, datalen); + switch(ftype) { + case jsfRaw: + JsonSaveStr(root, "FileType", "raw"); + JsonSaveBufAsHexCompact(root, "raw", data, datalen); + break; + case jsfCardMemory: + JsonSaveStr(root, "FileType", "mifare card dump"); + for (int i = 0; i < (datalen / 16); i++) { + char path[30] = {0}; + sprintf(path, "$.blocks.%d", i); + JsonSaveBufAsHexCompact(root, path, &data[i * 16], 16); + + if (i == 0) { + JsonSaveBufAsHexCompact(root, "$.Card.UID", &data[0], 4); + JsonSaveBufAsHexCompact(root, "$.Card.SAK", &data[5], 1); + JsonSaveBufAsHexCompact(root, "$.Card.ATQA", &data[6], 2); + } + + if (mfIsSectorTrailer(i)) { + char patha[30] = {0}; + sprintf(patha, "$.SectorKeys.%d.KeyA", mfSectorNum(i)); + JsonSaveBufAsHexCompact(root, patha, &data[i * 16], 6); + + char pathb[30] = {0}; + sprintf(pathb, "$.SectorKeys.%d.KeyB", mfSectorNum(i)); + JsonSaveBufAsHexCompact(root, pathb, &data[i * 16 + 10], 6); + + char pathc[30] = {0}; + uint8_t *adata = &data[i * 16 + 6]; + sprintf(pathc, "$.SectorKeys.%d.AccessConditions", mfSectorNum(i)); + JsonSaveBufAsHexCompact(root, pathc, &data[i * 16 + 6], 4); + + memset(path, 0x00, sizeof(path)); + sprintf(path, "$.SectorKeys.%d.AccessConditionsText.block%d", mfSectorNum(i), i - 3); + JsonSaveStr(root, path, mfGetAccessConditionsDesc(0, adata)); + + memset(path, 0x00, sizeof(path)); + sprintf(path, "$.SectorKeys.%d.AccessConditionsText.block%d", mfSectorNum(i), i - 2); + JsonSaveStr(root, path, mfGetAccessConditionsDesc(1, adata)); + + memset(path, 0x00, sizeof(path)); + sprintf(path, "$.SectorKeys.%d.AccessConditionsText.block%d", mfSectorNum(i), i - 1); + JsonSaveStr(root, path, mfGetAccessConditionsDesc(2, adata)); + + memset(path, 0x00, sizeof(path)); + sprintf(path, "$.SectorKeys.%d.AccessConditionsText.block%d", mfSectorNum(i), i); + JsonSaveStr(root, path, mfGetAccessConditionsDesc(3, adata)); + + } + } + break; + } int res = json_dump_file(root, fileName, JSON_INDENT(2)); if (res) { diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index c699be3de..3852b4bf4 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -48,6 +48,12 @@ #include #include "../ui.h" #include "../emv/emvjson.h" +#include "mifare4.h" + +typedef enum { + jsfRaw, + jsfCardMemory, +} JSONFileType; int fileExists(const char *filename); @@ -85,11 +91,12 @@ extern int saveFileEML(const char *preferredName, const char *suffix, uint8_t* d * * @param preferredName * @param suffix the file suffix. Leave out the ".". + * @param ftype type of file. * @param data The binary data to write to the file * @param datalen the length of the data * @return 0 for ok, 1 for failz */ -extern int saveFileJSON(const char *preferredName, const char *suffix, uint8_t* data, size_t datalen); +extern int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType ftype, uint8_t* data, size_t datalen); /** STUB * @brief Utility function to load data from a binary file. This method takes a preferred name. diff --git a/client/mifare4.c b/client/mifare4.c index 39869ab77..0c53a1f9b 100644 --- a/client/mifare4.c +++ b/client/mifare4.c @@ -17,6 +17,52 @@ #include "ui.h" #include "crypto/libpcrypto.h" +AccessConditions_t MFAccessConditions[] = { + {0x00, "rdAB wrAB incAB dectrAB"}, + {0x01, "rdAB dectrAB"}, + {0x02, "rdAB"}, + {0x03, "rdB wrB"}, + {0x04, "rdAB wrB"}, + {0x05, "rdB"}, + {0x06, "rdAB wrB incB dectrAB"}, + {0x07, "none"} +}; + +AccessConditions_t MFAccessConditionsTrailer[] = { + {0x00, "rdAbyA rdCbyA rdBbyA wrBbyA"}, + {0x01, "wrAbyA rdCbyA wrCbyA rdBbyA wrBbyA"}, + {0x02, "rdCbyA rdBbyA"}, + {0x03, "wrAbyB rdCbyAB wrCbyB wrBbyB"}, + {0x04, "wrAbyB rdCbyAB wrBbyB"}, + {0x05, "rdCbyAB wrCbyB"}, + {0x06, "rdCbyAB"}, + {0x07, "rdCbyAB"} +}; + +char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data) { + static char StaticNone[] = "none"; + + uint8_t data1 = ((data[1] >> 4) & 0x0f) >> blockn; + uint8_t data2 = ((data[2]) & 0x0f) >> blockn; + uint8_t data3 = ((data[2] >> 4) & 0x0f) >> blockn; + + uint8_t cond = (data1 & 0x01) << 2 | (data2 & 0x01) << 1 | (data3 & 0x01); + + if (blockn == 3) { + for (int i = 0; i < ARRAYLEN(MFAccessConditionsTrailer); i++) + if (MFAccessConditionsTrailer[i].cond == cond) { + return MFAccessConditionsTrailer[i].description; + } + } else { + for (int i = 0; i < ARRAYLEN(MFAccessConditions); i++) + if (MFAccessConditions[i].cond == cond) { + return MFAccessConditions[i].description; + } + }; + + return StaticNone; +}; + int CalculateEncIVCommand(mf4Session *session, uint8_t *iv, bool verbose) { memcpy(&iv[0], session->TI, 4); memcpy(&iv[4], &session->R_Ctr, 2); diff --git a/client/mifare4.h b/client/mifare4.h index b85d512f1..011567a1e 100644 --- a/client/mifare4.h +++ b/client/mifare4.h @@ -38,9 +38,16 @@ typedef enum { mtypWriteResp, } MACType_t; +typedef struct { + uint8_t cond; + char *description; +} AccessConditions_t; + extern int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose); extern int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose); +extern char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data); + extern uint8_t mfNumBlocksPerSector(uint8_t sectorNo); extern uint8_t mfFirstBlockOfSector(uint8_t sectorNo); extern uint8_t mfSectorTrailer(uint8_t blockNo); From 6baf579fe082843084641a4f0be99239603047b9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 29 Nov 2018 16:56:57 +0200 Subject: [PATCH 0269/1938] hf mf cload works --- client/cmdhfmf.c | 30 +++++++++++++++++++++++++----- client/loclass/fileutils.c | 37 ++++++++++++++++++++++++++++++++++--- 2 files changed, 59 insertions(+), 8 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index b14dde768..1e43ff81e 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -330,7 +330,9 @@ int usage_hf14_cload(void){ PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " e load card with data from emulator memory"); - PrintAndLogEx(NORMAL, " load card with data from file"); + PrintAndLogEx(NORMAL, " j load card with data from json file"); + PrintAndLogEx(NORMAL, " b load card with data from binary file"); + PrintAndLogEx(NORMAL, " load card with data from eml file"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf cload mydump"); PrintAndLogEx(NORMAL, " hf mf cload e"); @@ -2631,12 +2633,21 @@ int CmdHF14AMfCLoad(const char *Cmd) { uint8_t buf8[16] = {0x00}; uint8_t fillFromEmulator = 0; int blockNum, flags = 0; + bool fillFromJson = false; + bool fillFromBin = false; + char fileName[50] = {0}; char ctmp = tolower(param_getchar(Cmd, 0)); - if ( strlen(Cmd) == 1 ) { + if ( param_getlength(Cmd, 0) == 1 ) { if (ctmp == 'h' || ctmp == 0x00) return usage_hf14_cload(); if (ctmp == 'e' ) fillFromEmulator = 1; + if (ctmp == 'j' ) fillFromJson = true; + if (ctmp == 'b' ) fillFromBin = true; } + + if (fillFromJson || fillFromBin) + param_getstr(Cmd, 1, fileName, sizeof(fileName)); + if (fillFromEmulator) { for (blockNum = 0; blockNum < 16 * 4; blockNum += 1) { @@ -2658,10 +2669,19 @@ int CmdHF14AMfCLoad(const char *Cmd) { return 0; } - uint8_t *data = calloc(1, 4096); + size_t maxdatalen = 4096; + uint8_t *data = calloc(1, maxdatalen); size_t datalen = 0; - //int res = loadFile(Cmd, "bin", data, &datalen); - int res = loadFileEML( Cmd, "eml", data, &datalen); + int res = 0; + if (fillFromBin) { + res = loadFile(fileName, "bin", data, &datalen); + } else { + if (fillFromJson) { + res = loadFileJSON(fileName, "json", data, maxdatalen, &datalen); + } else { + res = loadFileEML( Cmd, "eml", data, &datalen); + } + } if ( res ) { free(data); return 1; diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index f110e02fc..c64da6b22 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -158,7 +158,7 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty JsonSaveBufAsHexCompact(root, "raw", data, datalen); break; case jsfCardMemory: - JsonSaveStr(root, "FileType", "mifare card dump"); + JsonSaveStr(root, "FileType", "mfcard"); for (int i = 0; i < (datalen / 16); i++) { char path[30] = {0}; sprintf(path, "$.blocks.%d", i); @@ -335,7 +335,7 @@ out: } int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t maxdatalen, size_t* datalen) { - datalen = 0; + *datalen = 0; json_t *root; json_error_t error; @@ -360,8 +360,39 @@ int loadFileJSON(const char *preferredName, const char *suffix, void* data, size goto out; } - JsonLoadBufAsHex(root, "$.raw", data, maxdatalen, datalen); + uint8_t *udata = (uint8_t *)data; + char ctype[100] = {0}; + JsonLoadStr(root, "$.FileType", ctype); + if (!strcmp(ctype, "raw")) { + JsonLoadBufAsHex(root, "$.raw", udata, maxdatalen, datalen); + } + + if (!strcmp(ctype, "mfcard")) { + printf("--mfcard--\n"); + size_t sptr = 0; + for (int i = 0; i < 256; i++) { + if (sptr + 16 > maxdatalen) { + retval = 5; + goto out; + } + + char path[30] = {0}; + sprintf(path, "$.blocks.%d", i); + + size_t len = 0; + JsonLoadBufAsHex(root, path, &udata[sptr], 16, &len); + if (!len) + break; + printf("--- (%d) (%d) %s \n", i, len, sprint_hex(&udata[sptr], len)); + + sptr += len; + } + + *datalen = sptr; + } + + PrintAndLog("Loaded JSON: (%s) OK.", fileName); out: json_decref(root); free(fileName); From efabdde2485a5bf2333e03bf48526897e5127653 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 29 Nov 2018 17:09:37 +0200 Subject: [PATCH 0270/1938] small fixes. done --- client/loclass/fileutils.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index c64da6b22..c0b379c78 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -200,6 +200,10 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty sprintf(path, "$.SectorKeys.%d.AccessConditionsText.block%d", mfSectorNum(i), i); JsonSaveStr(root, path, mfGetAccessConditionsDesc(3, adata)); + memset(path, 0x00, sizeof(path)); + sprintf(path, "$.SectorKeys.%d.AccessConditionsText.UserData", mfSectorNum(i)); + JsonSaveBufAsHexCompact(root, path, &adata[3], 1); + } } break; @@ -369,7 +373,6 @@ int loadFileJSON(const char *preferredName, const char *suffix, void* data, size } if (!strcmp(ctype, "mfcard")) { - printf("--mfcard--\n"); size_t sptr = 0; for (int i = 0; i < 256; i++) { if (sptr + 16 > maxdatalen) { @@ -384,7 +387,6 @@ int loadFileJSON(const char *preferredName, const char *suffix, void* data, size JsonLoadBufAsHex(root, path, &udata[sptr], 16, &len); if (!len) break; - printf("--- (%d) (%d) %s \n", i, len, sprint_hex(&udata[sptr], len)); sptr += len; } From 4dece3e30da03e6e9191a75e192bae03e55cc889 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 29 Nov 2018 17:13:00 +0200 Subject: [PATCH 0271/1938] del line --- client/loclass/fileutils.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index c0b379c78..36e16469c 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -203,7 +203,6 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty memset(path, 0x00, sizeof(path)); sprintf(path, "$.SectorKeys.%d.AccessConditionsText.UserData", mfSectorNum(i)); JsonSaveBufAsHexCompact(root, path, &adata[3], 1); - } } break; From b64fdafc4038fcdca783b2e2262acd2ebf87f0dc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 29 Nov 2018 17:53:24 +0100 Subject: [PATCH 0272/1938] ADD: basic iso15693 comms in lua support. Not fully functional --- client/lualibs/read15.lua | 93 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 93 insertions(+) create mode 100644 client/lualibs/read15.lua diff --git a/client/lualibs/read15.lua b/client/lualibs/read15.lua new file mode 100644 index 000000000..b337d22d7 --- /dev/null +++ b/client/lualibs/read15.lua @@ -0,0 +1,93 @@ +--[[ + This is a library to read 15693 tags. It can be used something like this + + local reader = require('read15') + result, err = reader.read15693() + if not result then + print(err) + return + end + print(result.name) + +--]] +-- Loads the commands-library +local cmds = require('commands') +local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds + + +--- Sends a USBpacket to the device +-- @param command - the usb packet to send +-- @param ignoreresponse - if set to true, we don't read the device answer packet +-- which is usually recipe for fail. If not sent, the host will wait 2s for a +-- response of type CMD_ACK +-- @return packet,nil if successfull +-- nil, errormessage if unsuccessfull +local function sendToDevice(command, ignoreresponse) + local err = core.SendCommand(command:getBytes()) + if err then + print(err) + return nil, err + end + if ignoreresponse then return nil,nil end + + local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) + return response,nil +end + +-- This function does a connect and retrieves som einfo +-- @param dont_disconnect - if true, does not disable the field +-- @return if successfull: an table containing card info +-- @return if unsuccessfull : nil, error +local function read15693(slow, dont_readresponse) + local command, result, info, err, data + + command = Command:new{cmd = cmds.CMD_ISO_15693_COMMAND, arg1 = 0, arg2 = 1, arg3 = 1 } + + if slow then + command.arg2 = 0 + end + if dont_readresponse then + command.arg3 = 0 + end + + local result, err = sendToDevice(command, dont_readresponse) + if result then + local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result) + if arg0 == 0 then + return nil, "iso15693 no bytes returned" + end + data = string.sub(result, count) + info, err = bin.unpack('H', data) + print("LEN", arg0, data ) + else + err = "No response from card" + end + + if err then + print(err) + return nil, err + end + return info +end + +--- +-- Waits for a mifare card to be placed within the vicinity of the reader. +-- @return if successfull: an table containing card info +-- @return if unsuccessfull : nil, error +local function waitFor15693() + print("Waiting for card... press any key to quit") + while not core.ukbhit() do + res, err = read15693() + if res then return res end + -- err means that there was no response from card + end + return nil, "Aborted by user" +end +local library = { + read = read15693, + waitFor15693 = waitFor15693, +-- parse15693 = parse15693, + sendToDevice = sendToDevice, +} + +return library From 0b5ee43392fce4891fb9a5ab6d176c6222514b76 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 29 Nov 2018 17:59:46 +0100 Subject: [PATCH 0273/1938] FIX: remove linker directive warnings used with compiler in CLANG, OS X. --- client/jansson/Makefile | 2 +- client/tinycbor/Makefile | 2 +- common/mbedtls/Makefile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/jansson/Makefile b/client/jansson/Makefile index e608d7c04..7657e35f3 100644 --- a/client/jansson/Makefile +++ b/client/jansson/Makefile @@ -34,7 +34,7 @@ CLEAN = $(CMDOBJS) CC= gcc CFLAGS= -O2 -Wall -Wno-unused-variable -Wno-unused-function LDFLAGS= $(SYSLDFLAGS) $(libjansson_la_LDFLAGS) -LIBS= -lm $(SYSLIBS) $(MYLIBS) +LIBS= $(SYSLIBS) $(MYLIBS) DEFAULT_INCLUDES = -I. DEFS = -DHAVE_STDINT_H diff --git a/client/tinycbor/Makefile b/client/tinycbor/Makefile index 31fb327cb..78ef64dc0 100644 --- a/client/tinycbor/Makefile +++ b/client/tinycbor/Makefile @@ -16,7 +16,7 @@ CLEAN = $(CMDOBJS) CC= gcc CFLAGS= -O2 -Wall -Wno-unused-variable -Wno-unused-function -LIBS= -lm $(SYSLIBS) $(MYLIBS) +LIBS= $(SYSLIBS) $(MYLIBS) DEFAULT_INCLUDES = -I. -I.. DEFS = -DHAVE_STDINT_H diff --git a/common/mbedtls/Makefile b/common/mbedtls/Makefile index a9a850989..2a6bca6f4 100644 --- a/common/mbedtls/Makefile +++ b/common/mbedtls/Makefile @@ -57,7 +57,7 @@ CLEAN = $(CMDOBJS) CC= gcc CFLAGS= -O2 -Wall -Wno-unused-variable -Wno-unused-function LDFLAGS= $(SYSLDFLAGS) $(mbedtls_LDFLAGS) -LIBS= -lm $(SYSLIBS) $(MYLIBS) +LIBS= $(SYSLIBS) $(MYLIBS) DEFAULT_INCLUDES = -I. -I.. DEFS = -DHAVE_STDINT_H From 9584074c00a22e4e302eb44858e4ad9dec5b6ca1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 29 Nov 2018 22:06:49 +0200 Subject: [PATCH 0274/1938] fix memory error --- client/loclass/fileutils.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 36e16469c..c18b2fa30 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -36,7 +36,9 @@ ****************************************************************************/ #include "fileutils.h" - #ifndef ON_DEVICE +#ifndef ON_DEVICE + +#define PATH_MAX_LENGTH 100 /** * @brief checks if a file exists @@ -160,7 +162,7 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty case jsfCardMemory: JsonSaveStr(root, "FileType", "mfcard"); for (int i = 0; i < (datalen / 16); i++) { - char path[30] = {0}; + char path[PATH_MAX_LENGTH] = {0}; sprintf(path, "$.blocks.%d", i); JsonSaveBufAsHexCompact(root, path, &data[i * 16], 16); @@ -171,18 +173,18 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty } if (mfIsSectorTrailer(i)) { - char patha[30] = {0}; - sprintf(patha, "$.SectorKeys.%d.KeyA", mfSectorNum(i)); - JsonSaveBufAsHexCompact(root, patha, &data[i * 16], 6); + memset(path, 0x00, sizeof(path)); + sprintf(path, "$.SectorKeys.%d.KeyA", mfSectorNum(i)); + JsonSaveBufAsHexCompact(root, path, &data[i * 16], 6); - char pathb[30] = {0}; - sprintf(pathb, "$.SectorKeys.%d.KeyB", mfSectorNum(i)); - JsonSaveBufAsHexCompact(root, pathb, &data[i * 16 + 10], 6); + memset(path, 0x00, sizeof(path)); + sprintf(path, "$.SectorKeys.%d.KeyB", mfSectorNum(i)); + JsonSaveBufAsHexCompact(root, path, &data[i * 16 + 10], 6); - char pathc[30] = {0}; + memset(path, 0x00, sizeof(path)); uint8_t *adata = &data[i * 16 + 6]; - sprintf(pathc, "$.SectorKeys.%d.AccessConditions", mfSectorNum(i)); - JsonSaveBufAsHexCompact(root, pathc, &data[i * 16 + 6], 4); + sprintf(path, "$.SectorKeys.%d.AccessConditions", mfSectorNum(i)); + JsonSaveBufAsHexCompact(root, path, &data[i * 16 + 6], 4); memset(path, 0x00, sizeof(path)); sprintf(path, "$.SectorKeys.%d.AccessConditionsText.block%d", mfSectorNum(i), i - 3); From 2accb7d3f425b0a833b1e2b143768abb90fee531 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 29 Nov 2018 23:32:59 +0100 Subject: [PATCH 0275/1938] CHG: remove different clocks calls. --- common/i2c.c | 33 +++++++++++++++------------------ 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/common/i2c.c b/common/i2c.c index 200c8cf27..f6ea7e662 100644 --- a/common/i2c.c +++ b/common/i2c.c @@ -111,23 +111,23 @@ void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) { // Reset the SIM_Adapter, then enter the main program // Note: the SIM_Adapter will not enter the main program after power up. Please run this function before use SIM_Adapter. void I2C_Reset_EnterMainProgram(void) { + StartTicks(); I2C_init(); - I2C_SetResetStatus(0, 0, 0); - SpinDelay(30); + WaitMS(30); I2C_SetResetStatus(1, 0, 0); - SpinDelay(30); + WaitMS(30); I2C_SetResetStatus(1, 1, 1); - SpinDelay(10); + WaitMS(10); } // Reset the SIM_Adapter, then enter the bootloader program // Reserve for firmware update. void I2C_Reset_EnterBootloader(void) { I2C_SetResetStatus(0, 1, 1); - SpinDelay(100); + WaitMS(100); I2C_SetResetStatus(1, 1, 1); - SpinDelay(10); + WaitMS(10); } // Wait for the clock to go High. @@ -170,7 +170,7 @@ bool WaitSCL_L_300ms(void){ if (!SCL_read) return true; - SpinDelay(1); + WaitMS(1); } return (delay == 0); } @@ -401,7 +401,7 @@ int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d // extra wait 500us (514us measured) // 200us (xx measured) - SpinDelayUs(600); + WaitUs(600); bool bBreak = true; uint16_t readcount = 0; @@ -572,7 +572,6 @@ bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t d void I2C_print_status(void) { DbpString("Smart card module (ISO 7816)"); uint8_t resp[] = {0,0,0,0}; - I2C_init(); I2C_Reset_EnterMainProgram(); uint8_t len = I2C_BufferRead(resp, sizeof(resp), I2C_DEVICE_CMD_GETVERSION, I2C_DEVICE_ADDRESS_MAIN); if ( len > 0 ) @@ -666,7 +665,6 @@ void SmartCardAtr(void) { LED_D_ON(); clear_trace(); set_tracing(true); - I2C_init(); I2C_Reset_EnterMainProgram(); bool isOK = GetATR( &card ); cmd_send(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t)); @@ -707,12 +705,9 @@ void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) { // Send raw bytes // asBytes = A0 A4 00 00 02 // arg1 = len 5 - I2C_BufferWrite(data, arg1, I2C_DEVICE_CMD_SEND, I2C_DEVICE_ADDRESS_MAIN); - - if ( !I2C_WaitForSim() ) - goto OUT; - - + bool res = I2C_BufferWrite(data, arg1, I2C_DEVICE_CMD_SEND, I2C_DEVICE_ADDRESS_MAIN); + if ( !res && MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); + // read bytes from module len = ISO7618_MAX_FRAME; bool res = sc_rx_bytes(resp, &len); @@ -724,8 +719,9 @@ void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) { } OUT: cmd_send(CMD_ACK, len, 0, 0, resp, len); + BigBuf_free(); set_tracing(false); - LEDsoff(); + LEDsoff(); } void SmartCardUpgrade(uint64_t arg0) { @@ -763,7 +759,7 @@ void SmartCardUpgrade(uint64_t arg0) { } // writing takes time. - SpinDelay(50); + WaitMS(50); // read res = I2C_ReadFW(verfiydata, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT); @@ -785,6 +781,7 @@ void SmartCardUpgrade(uint64_t arg0) { } cmd_send(CMD_ACK, isOK, pos, 0, 0, 0); LED_C_OFF(); + BigBuf_free(); } void SmartCardSetBaud(uint64_t arg0) { From c948911f71389f81554badf2a6bd73487ccaba12 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 29 Nov 2018 23:37:05 +0100 Subject: [PATCH 0276/1938] chg... --- common/i2c.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/common/i2c.c b/common/i2c.c index f6ea7e662..ecf5a5bd9 100644 --- a/common/i2c.c +++ b/common/i2c.c @@ -401,7 +401,7 @@ int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d // extra wait 500us (514us measured) // 200us (xx measured) - WaitUs(600); + WaitUS(600); bool bBreak = true; uint16_t readcount = 0; @@ -710,7 +710,7 @@ void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) { // read bytes from module len = ISO7618_MAX_FRAME; - bool res = sc_rx_bytes(resp, &len); + res = sc_rx_bytes(resp, &len); if ( res ) { LogTrace(resp, len, 0, 0, NULL, false); } else { From bd7ac487cd3a07af455a065f44c954bbb68e016b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 29 Nov 2018 23:44:50 +0100 Subject: [PATCH 0277/1938] FIX: 'hf mf hardnested' - output misalignment --- client/hardnested/hardnested_bruteforce.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/hardnested/hardnested_bruteforce.c b/client/hardnested/hardnested_bruteforce.c index 602453646..55d6bbfbf 100644 --- a/client/hardnested/hardnested_bruteforce.c +++ b/client/hardnested/hardnested_bruteforce.c @@ -178,7 +178,7 @@ crack_states_thread(void* x){ } else { if (!thread_arg->silent) { char progress_text[80]; - sprintf(progress_text, "Brute force phase: %6.02f%%", 100.0*(float)num_keys_tested/(float)(thread_arg->maximum_states)); + sprintf(progress_text, "Brute force phase: %6.02f%%\t", 100.0*(float)num_keys_tested/(float)(thread_arg->maximum_states)); float remaining_bruteforce = thread_arg->nonces[thread_arg->best_first_bytes[0]].expected_num_brute_force - (float)num_keys_tested/2; hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, remaining_bruteforce, 5000); } From ccb0cd23f56f0b19a73da6817bacc4c22a806ddb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 30 Nov 2018 01:19:57 +0100 Subject: [PATCH 0278/1938] FIX: 'lua calc of iso15692 crc' - works better now --- client/scripting.c | 17 +++++++++++++---- 1 file changed, 13 insertions(+), 4 deletions(-) diff --git a/client/scripting.c b/client/scripting.c index f0fa9b2f4..762a9c470 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -280,10 +280,19 @@ static int l_CmdConsole(lua_State *L) { } static int l_iso15693_crc(lua_State *L) { - size_t size; - const char *v = luaL_checklstring(L, 1, &size); - // iceman, should be size / 2 ?!? - lua_pushunsigned(L, crc( CRC_15693, (uint8_t *) v, size)); + uint32_t tmp; + unsigned char buf[USB_CMD_DATA_SIZE] = {0x00}; + size_t size = 0; + const char *data = luaL_checklstring(L, 1, &size); + + for (int i = 0; i < size; i += 2) { + sscanf(&data[i], "%02x", &tmp); + buf[i / 2] = tmp & 0xFF; + } + + size /= 2; + compute_crc(CRC_15693, buf, size, &buf[size], &buf[size+1]); + lua_pushlstring(L, (const char *)&buf, size+2); return 1; } From a5898158c5685b087812ce4545330a486c6104c3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 30 Nov 2018 01:41:39 +0100 Subject: [PATCH 0279/1938] FIX: basic fixes for lua reader14a, reader14b, reader15 ADD: utils got iso15693 crc support --- client/lualibs/hf_reader.lua | 155 +---------------------------------- client/lualibs/read14a.lua | 1 - client/lualibs/read14b.lua | 8 +- client/lualibs/read15.lua | 132 +++++++++++++++++++++++++---- client/lualibs/utils.lua | 14 +++- 5 files changed, 135 insertions(+), 175 deletions(-) diff --git a/client/lualibs/hf_reader.lua b/client/lualibs/hf_reader.lua index da46cebbc..c9970f772 100644 --- a/client/lualibs/hf_reader.lua +++ b/client/lualibs/hf_reader.lua @@ -6,160 +6,7 @@ This library utilises other libraries under the hood, but can be used as a gener local reader14443A = require('read14a') local reader14443B = require('read14b') -local cmds = require('commands') -local TIMEOUT = 2000 - -local function sendToDevice(command, ignoreresponse) - core.clearCommandBuffer() - local err = core.SendCommand(command:getBytes()) - if err then - print(err) - return nil, err - end - if ignoreresponse then return nil,nil end - local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) - return response,nil -end - -------------------------------------------------------- --- This will be moved to a separate 14443B library -------------------------------------------------------- - -local reader14443B = { - read = reader14443B.read14443b() -} -------------------------------------------------------- --- This will be moved to a separate 1593 library -------------------------------------------------------- - -local function errorString15693(number) - local errors = {} - errors[0x01] = "The command is not supported" - errors[0x02] = "The command is not recognised" - errors[0x03] = "The option is not supported." - errors[0x0f] = "Unknown error." - errors[0x10] = "The specified block is not available (doesn’t exist)." - errors[0x11] = "The specified block is already -locked and thus cannot be locked again" - errors[0x12] = "The specified block is locked and its content cannot be changed." - errors[0x13] = "The specified block was not successfully programmed." - errors[0x14] = "The specified block was not successfully locked." - - return errors[number] or "Reserved for Future Use or Custom command error." -end -------------------------------------------------------- --- This will be moved to a separate 1593 library -------------------------------------------------------- - -local function parse15693(data) - -- From common/iso15693tools.h : - --[[ - #define ISO15_CRC_CHECK ((uint16_t)(~0xF0B8 & 0xFFFF)) // use this for checking of a correct crc - --]] - -- But that is very strange. Basically what is says is: - -- define ISO15_CRC_CHECK 0F47 - -- So we can just use that directly... - -- The following code is based on cmdhf15.c around line 666 (NoTB!) and onwards - if core.iso15693_crc(data, string.len(data)) ~= 0xF47 then - return nil, "CRC failed" - elseif data[1] % 2 == 1 then - -- Above is a poor-mans bit check: - -- recv[0] & ISO15_RES_ERROR //(0x01) - local err = "Tag returned error %i: %s" - err = string.format(err, data[1],errorString15693(data[1])) - return nil, err - end - -- Finally, let the parsing begin... - -- the UID is just the data in reverse... almost: - -- 0FC481FF70000104E001001B0301 - -- 8877665544332211 - -- UID = E004010070FF81C4 - -- 1122334455667788 - -- So, cut out the relevant part and reverse it - local uid = data:sub(2,9):reverse() - local uidStr = bin.unpack("H8", uid) - - local _,manufacturer_code = bin.unpack("s",uid:sub(2,2)) - local _,tag_size = bin.unpack(">I",data:sub(12,13)) - local _,micref_modelcode = bin.unpack("s",data:sub(14,14)) - - return { - uid = uidStr, - manufacturer_code = manufacturer_code, - tag_size = tag_size, - micref_modelcode = micref_modelcode, - } -end -------------------------------------------------------- --- This will be moved to a separate 1593 library -------------------------------------------------------- - -local function read15693() - --[[ - - We start by trying this command: - - proxmark3> hf 15 cmd sysinfo -2 u - 0F C4 81 FF 70 00 01 04 E0 01 00 1B 03 01 - UID = E004010070FF81C4 - Philips; IC SL2 ICS20 - DSFID supported, set to 01 - AFI supported, set to 000 - Tag provides info on memory layout (vendor dependent) - 4 (or 3) bytes/page x 28 pages - IC reference given: 01 - - This command is not always present in ISO15693 tags (it is an optional standard command) but if it is present usually the tags contain all the "colored" info above. - - If the above command doesn't give an answer (see example below): - - proxmark3> hf 15 cmd sysinfo -2 u - timeout: no - - we must send the MANDATORY (present in ALL iso15693 tags) command (the example below is sent to a tag different from the above one): - - proxmark3> hf 15 cmd inquiry - UID=E007C1A257394244 - Tag Info: Texas Instrument; Tag-it HF-I Standard; 8x32bit - proxmark3> - - From which we obtain less information than the above one. - --]] - - local command, result, info, err, data - local data = "02" - local datalen = string.len(data) / 2 - local speed = 1 - local recv = 1 - command = Command:new{cmd = cmds.CMD_ISO_15693_COMMAND, - arg1 = datalen,arg2 = speed,arg3 =recv, data=data} - -- These are defined in common/iso15693tools.h - - -- #define ISO15_REQ_SUBCARRIER_SINGLE 0x00 // Tag should respond using one subcarrier (ASK) - -- #define ISO15_REQ_DATARATE_HIGH 0x02 // Tag should respond using high data rate - -- #define ISO15_REQ_NONINVENTORY 0x00 - - local result,err = sendToDevice(command) - - if not result then - print(err) - return nil, "15693 sysinfo: no answer" - end - - local count,cmd,recvlen,arg1,arg2 = bin.unpack('LLLL',result) - data = string.sub(result,recvlen) - info, err = parse15693(data) - - if err then - return nil, err - end - - return info -end - -local reader15693 = { - read = read15693 -} - +local reader15693 = require('read15') --- -- This method library can be set waits or a 13.56 MHz tag, and when one is found, returns info about diff --git a/client/lualibs/read14a.lua b/client/lualibs/read14a.lua index 877a16413..9e53cacca 100644 --- a/client/lualibs/read14a.lua +++ b/client/lualibs/read14a.lua @@ -141,7 +141,6 @@ local function waitFor14443a() end local library = { read = read14443a, - read = read14443a, waitFor14443a = waitFor14443a, parse14443a = parse14443a, sendToDevice = sendToDevice, diff --git a/client/lualibs/read14b.lua b/client/lualibs/read14b.lua index 9d287266a..b92fb0b3b 100644 --- a/client/lualibs/read14b.lua +++ b/client/lualibs/read14b.lua @@ -41,7 +41,7 @@ local function parse1443b(data) --]] local count, uid, uidlen, atqb, chipid, cid = bin.unpack('H10CH7CC',data) - uid = uid:sub(1,2*uidlen) + uid = uid:sub(1, 2*uidlen) return { uid = uid, uidlen = uidlen, atqb = atqb, chipid = chipid, cid = cid } end @@ -96,7 +96,7 @@ local function read14443b(disconnect) end command = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags} - local result,err = sendToDevice(command, false) + local result, err = sendToDevice(command, false) if result then local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result) if arg0 == 0 then @@ -147,9 +147,9 @@ local function waitFor14443b() end local library = { - parse1443b = parse1443b, - read1443b = read14443b, + read = read14443b, waitFor14443b = waitFor14443b, + parse1443b = parse1443b, sendToDevice = sendToDevice, showData = showData, ISO14B_COMMAND = ISO14B_COMMAND, diff --git a/client/lualibs/read15.lua b/client/lualibs/read15.lua index b337d22d7..e8967729c 100644 --- a/client/lualibs/read15.lua +++ b/client/lualibs/read15.lua @@ -12,6 +12,7 @@ --]] -- Loads the commands-library local cmds = require('commands') +local utils = require('utils') local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds @@ -34,15 +35,118 @@ local function sendToDevice(command, ignoreresponse) return response,nil end +local function errorString15693(number) + local errors = {} + errors[0x01] = "The command is not supported" + errors[0x02] = "The command is not recognised" + errors[0x03] = "The option is not supported." + errors[0x0f] = "Unknown error." + errors[0x10] = "The specified block is not available (doesn’t exist)." + errors[0x11] = "The specified block is already -locked and thus cannot be locked again" + errors[0x12] = "The specified block is locked and its content cannot be changed." + errors[0x13] = "The specified block was not successfully programmed." + errors[0x14] = "The specified block was not successfully locked." + + return errors[number] or "Reserved for Future Use or Custom command error." +end + + +local function parse15693(data) + -- From common/iso15693tools.h : + --[[ + #define ISO15_CRC_CHECK ((uint16_t)(~0xF0B8 & 0xFFFF)) // use this for checking of a correct crc + --]] + -- But that is very strange. Basically what is says is: + -- define ISO15_CRC_CHECK 0F47 + -- So we can just use that directly... + -- The following code is based on cmdhf15.c around line 666 (NoTB!) and onwards + if core.iso15693_crc(data, string.len(data)) ~= 0xF47 then + return nil, "CRC failed" + elseif data[1] % 2 == 1 then + -- Above is a poor-mans bit check: + -- recv[0] & ISO15_RES_ERROR //(0x01) + local err = "Tag returned error %i: %s" + err = string.format(err, data[1], errorString15693(data[1])) + return nil, err + end + -- Finally, let the parsing begin... + -- the UID is just the data in reverse... almost: + -- 0FC481FF70000104E001001B0301 + -- 8877665544332211 + -- UID = E004010070FF81C4 + -- 1122334455667788 + -- So, cut out the relevant part and reverse it + -- byte wise reverse.. not string reverse.. + local uid = data:sub(2,9):reverse() + local uidStr = bin.unpack("H8", uid) + + local _, manufacturer_code = bin.unpack("s", uid:sub(2,2)) + local _, tag_size = bin.unpack(">I", data:sub(12,13)) + local _, micref_modelcode = bin.unpack("s", data:sub(14,14)) + + return { + uid = uidStr, + manufacturer_code = manufacturer_code, + tag_size = tag_size, + micref_modelcode = micref_modelcode, + } +end + -- This function does a connect and retrieves som einfo -- @param dont_disconnect - if true, does not disable the field -- @return if successfull: an table containing card info -- @return if unsuccessfull : nil, error local function read15693(slow, dont_readresponse) + +--[[ + + We start by trying this command: + + proxmark3> hf 15 cmd sysinfo -2 u + 0F C4 81 FF 70 00 01 04 E0 01 00 1B 03 01 + UID = E004010070FF81C4 + Philips; IC SL2 ICS20 + DSFID supported, set to 01 + AFI supported, set to 000 + Tag provides info on memory layout (vendor dependent) + 4 (or 3) bytes/page x 28 pages + IC reference given: 01 + + This command is not always present in ISO15693 tags (it is an optional standard command) but if it is present usually the tags contain all the "colored" info above. + + If the above command doesn't give an answer (see example below): + + proxmark3> hf 15 cmd sysinfo -2 u + timeout: no + + we must send the MANDATORY (present in ALL iso15693 tags) command (the example below is sent to a tag different from the above one): + + proxmark3> hf 15 cmd inquiry + UID=E007C1A257394244 + Tag Info: Texas Instrument; Tag-it HF-I Standard; 8x32bit + proxmark3> + + From which we obtain less information than the above one. + --]] + local command, result, info, err, data - command = Command:new{cmd = cmds.CMD_ISO_15693_COMMAND, arg1 = 0, arg2 = 1, arg3 = 1 } + data = "260100" + --add crc + local payload = utils.Crc15(data) + + command = Command:new{cmd = cmds.CMD_ISO_15693_COMMAND, + arg1 = string.len(payload) / 2, + arg2 = 1, + arg3 = 1, + data = payload} + + -- These are defined in common/iso15693tools.h + -- #define ISO15_REQ_SUBCARRIER_SINGLE 0x00 // Tag should respond using one subcarrier (ASK) + -- #define ISO15_REQ_DATARATE_HIGH 0x02 // Tag should respond using high data rate + -- #define ISO15_REQ_NONINVENTORY 0x00 + if slow then command.arg2 = 0 end @@ -51,23 +155,21 @@ local function read15693(slow, dont_readresponse) end local result, err = sendToDevice(command, dont_readresponse) - if result then - local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result) - if arg0 == 0 then - return nil, "iso15693 no bytes returned" - end - data = string.sub(result, count) - info, err = bin.unpack('H', data) - print("LEN", arg0, data ) - else - err = "No response from card" + if not result then + print(err) + return nil, "15693 sysinfo: no answer" end - if err then - print(err) + local count, cmd, recvlen, arg1, arg2 = bin.unpack('LLLL',result) + data = string.sub(result, recvlen) + info, err = parse15693(data) + + if err then + print(err) return nil, err end - return info + + return info end --- @@ -86,7 +188,7 @@ end local library = { read = read15693, waitFor15693 = waitFor15693, --- parse15693 = parse15693, + parse15693 = parse15693, sendToDevice = sendToDevice, } diff --git a/client/lualibs/utils.lua b/client/lualibs/utils.lua index ef6060533..aefd68b4d 100644 --- a/client/lualibs/utils.lua +++ b/client/lualibs/utils.lua @@ -109,7 +109,19 @@ local Utils = end return nil end, - + ----ISO15693 CRC + Crc15 = function(s) + if s == nil then return nil end + if #s == 0 then return nil end + if type(s) == 'string' then + local utils = require('utils') + return utils.ConvertAsciiToHex( + core.iso15693_crc(s) + ) + end + return nil + end, + ------------ CRC-8 Legic checksums -- Takes a hex string and calculates a crc8 Crc8Legic = function(s) From 8bef04f94b2b3392dab1b28d797f553e3a488d11 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 30 Nov 2018 09:03:55 +0100 Subject: [PATCH 0280/1938] ADD: Support TCP ports for proxmark (@phcoder) On ChromeOS Linux apps can't access serial port but they can connect to TCP, so I wrote a simple app to forward TCP to serial. I suppose this can have other uses as well. see: https://github.com/Proxmark/proxmark3/pull/720/commits/538d10d6511d52ec13ace117dcbe49dfeb3287fd --- CHANGELOG.md | 1 + uart/uart_posix.c | 64 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 63 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e342ace0c..296fd14e3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Added TCP ports support (on linux) (@phcoder) - Added HF sniff standalone mode with optional storing of ULC/NTAG/ULEV1 authentication attempts (@bogiton) - Fix 'Lining up plot and control window' (@anticat) - Fix 'annoying focus behaviour' on OSX (@Anticat) diff --git a/uart/uart_posix.c b/uart/uart_posix.c index b587d6546..26e814a3a 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -2,6 +2,7 @@ * Generic uart / rs232/ serial port library * * Copyright (c) 2013, Roel Verdult + * Copyright (c) 2018 Google * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -36,6 +37,7 @@ // Test if we are dealing with posix operating systems #ifndef _WIN32 +#define _DEFAULT_SOURCE #include #include @@ -46,7 +48,12 @@ #include #include #include - +#include +#include +#include +#include +#include +#include typedef struct termios term_info; typedef struct { @@ -58,13 +65,66 @@ typedef struct { // Set time-out on 30 miliseconds const struct timeval timeout = { .tv_sec = 0, // 0 second - .tv_usec = 30000 // 30000 micro seconds + .tv_usec = 300000 // 300 000 micro seconds }; serial_port uart_open(const char* pcPortName) { serial_port_unix* sp = malloc(sizeof(serial_port_unix)); if (sp == 0) return INVALID_SERIAL_PORT; + + if (memcmp(pcPortName, "tcp:", 4) == 0) { + struct addrinfo *addr, *rp; + char *addrstr = strdup(pcPortName + 4); + + if (addrstr == NULL) { + printf("Error: strdup\n"); + return INVALID_SERIAL_PORT; + } + + char *colon = strrchr(addrstr, ':'); + char *portstr; + if (colon) { + portstr = colon + 1; + *colon = '\0'; + } else { + portstr = "7901"; + } + + int s = getaddrinfo(addrstr, portstr, NULL, &addr); + if (s != 0) { + printf("Error: getaddrinfo: %s\n", gai_strerror(s)); + return INVALID_SERIAL_PORT; + } + + int sfd; + for (rp = addr; rp != NULL; rp = rp->ai_next) { + sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + + if (sfd == -1) + continue; + + if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) + break; + + close(sfd); + } + + if (rp == NULL) { /* No address succeeded */ + printf("Error: Could not connect\n"); + return INVALID_SERIAL_PORT; + } + + freeaddrinfo(addr); + free(addrstr); + + sp->fd = sfd; + + int one = 1; + setsockopt(sp->fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)); + return sp; + } + sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); if(sp->fd == -1) { From c5c75d494b8691b873a59b3c74fe1158fae8c3f5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 30 Nov 2018 09:13:09 +0100 Subject: [PATCH 0281/1938] chg.. moved into defined --- uart/uart_posix.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/uart/uart_posix.c b/uart/uart_posix.c index 26e814a3a..0ead61500 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -33,12 +33,12 @@ * proxmark3 project. */ -#include "uart.h" - // Test if we are dealing with posix operating systems #ifndef _WIN32 #define _DEFAULT_SOURCE +#include "uart.h" + #include #include #include From 9f77f2741f4ab88d10558a04963022482cbc7359 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 30 Nov 2018 14:16:34 +0200 Subject: [PATCH 0282/1938] added trailer decoding --- client/cmdhfmf.c | 28 +++++++++++++++++++++++++--- 1 file changed, 25 insertions(+), 3 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 1e43ff81e..48a235ffd 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -545,14 +545,25 @@ int CmdHF14AMfRdBl(const char *Cmd) { uint8_t isOK = resp.arg[0] & 0xff; uint8_t *data = resp.d.asBytes; - if (isOK) + if (isOK) { PrintAndLogEx(NORMAL, "isOk:%02x data:%s", isOK, sprint_hex(data, 16)); - else + } else { PrintAndLogEx(NORMAL, "isOk:%02x", isOK); + return 1; + } + + if (mfIsSectorTrailer(blockNo) && (data[6] || data[7] || data[8])) { + PrintAndLogEx(NORMAL, "Trailer decoded:"); + for (int i = 0; i < 4; i++) { + PrintAndLogEx(NORMAL, "Access block %d: %s", i + mfFirstBlockOfSector(mfSectorNum(blockNo)), mfGetAccessConditionsDesc(i, &data[6])); + } + PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&data[9], 1)); + } } else { PrintAndLogEx(WARNING, "Command execute timeout"); + return 2; } - + return 0; } @@ -2759,6 +2770,17 @@ int CmdHF14AMfCGetBlk(const char *Cmd) { } PrintAndLogEx(NORMAL, "data: %s", sprint_hex(data, sizeof(data))); + + if (mfIsSectorTrailer(blockNo)) { + PrintAndLogEx(NORMAL, "Trailer decoded:"); + PrintAndLogEx(NORMAL, "Key A: %s", sprint_hex_inrow(data, 6)); + PrintAndLogEx(NORMAL, "Key B: %s", sprint_hex_inrow(&data[10], 6)); + for (int i = 0; i < 4; i++) { + PrintAndLogEx(NORMAL, "Access block %d: %s", i + mfFirstBlockOfSector(mfSectorNum(blockNo)), mfGetAccessConditionsDesc(i, &data[6])); + } + PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&data[9], 1)); + } + return 0; } From a10bf3ac05383adea99d6bd59b889a8ad7f7c6f4 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 30 Nov 2018 14:17:46 +0200 Subject: [PATCH 0283/1938] added changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 296fd14e3..64377c383 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -87,6 +87,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added `hf emv scan` - save card's data to json file (@merlokk) - Added `hf emv` `gpo`, `readrec`, `genac`, `challenge`, `intauth` - separate commands from `hf emc exec` (@merlokk) - Added `hf fido` `assert` and `make` commands from fido2 protocol (authenticatorMakeCredential and authenticatorGetAssertion) (@merlokk) + - Added trailer block decoding to `hf mf rdbl` and `hf mf cgetbl` (@merlokk) ### Fixed - Changed driver file proxmark3.inf to support both old and new Product/Vendor IDs (piwi) From 2d932e49ac62d483a97a868d51f1b160c5708c7b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 30 Nov 2018 20:28:34 +0200 Subject: [PATCH 0284/1938] https://github.com/Proxmark/proxmark3/pull/725 --- client/cmdhffido.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 273982bed..9ce554ce2 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -456,7 +456,7 @@ int CmdHFFidoAuthenticate(const char *cmd) { // public key CLIGetHexWithReturn(8, hdata, &hdatalen); - if (hdatalen && hdatalen != 130) { + if (hdatalen && hdatalen != 65) { PrintAndLog("ERROR: public key length must be 65 bytes only."); return 1; } From 7c8377839ebf06f9951eff976930b6ff37ddcf6f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 30 Nov 2018 20:33:46 +0200 Subject: [PATCH 0285/1938] 4k fix --- client/cmdhfmf.c | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 48a235ffd..8653a8994 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -554,8 +554,11 @@ int CmdHF14AMfRdBl(const char *Cmd) { if (mfIsSectorTrailer(blockNo) && (data[6] || data[7] || data[8])) { PrintAndLogEx(NORMAL, "Trailer decoded:"); + int bln = mfFirstBlockOfSector(mfSectorNum(blockNo)); + int blinc = (mfNumBlocksPerSector(mfSectorNum(blockNo)) > 4) ? 5 : 1; for (int i = 0; i < 4; i++) { - PrintAndLogEx(NORMAL, "Access block %d: %s", i + mfFirstBlockOfSector(mfSectorNum(blockNo)), mfGetAccessConditionsDesc(i, &data[6])); + PrintAndLogEx(NORMAL, "Access block %d%s: %s", bln, ((blinc > 1) && (i < 3) ? "+" : "") , mfGetAccessConditionsDesc(i, &data[6])); + bln += blinc; } PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&data[9], 1)); } @@ -2775,8 +2778,11 @@ int CmdHF14AMfCGetBlk(const char *Cmd) { PrintAndLogEx(NORMAL, "Trailer decoded:"); PrintAndLogEx(NORMAL, "Key A: %s", sprint_hex_inrow(data, 6)); PrintAndLogEx(NORMAL, "Key B: %s", sprint_hex_inrow(&data[10], 6)); + int bln = mfFirstBlockOfSector(mfSectorNum(blockNo)); + int blinc = (mfNumBlocksPerSector(mfSectorNum(blockNo)) > 4) ? 5 : 1; for (int i = 0; i < 4; i++) { - PrintAndLogEx(NORMAL, "Access block %d: %s", i + mfFirstBlockOfSector(mfSectorNum(blockNo)), mfGetAccessConditionsDesc(i, &data[6])); + PrintAndLogEx(NORMAL, "Access block %d%s: %s", bln, ((blinc > 1) && (i < 3) ? "+" : "") , mfGetAccessConditionsDesc(i, &data[6])); + bln += blinc; } PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&data[9], 1)); } From 0372cb8a0448fd2713a400c284bba67918055394 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 30 Nov 2018 20:58:47 +0100 Subject: [PATCH 0286/1938] chg: iso15693 lua lib works. --- client/lualibs/read15.lua | 136 +++++++++++++++----------------------- client/lualibs/utils.lua | 16 +++-- 2 files changed, 65 insertions(+), 87 deletions(-) diff --git a/client/lualibs/read15.lua b/client/lualibs/read15.lua index e8967729c..5681fe367 100644 --- a/client/lualibs/read15.lua +++ b/client/lualibs/read15.lua @@ -2,12 +2,12 @@ This is a library to read 15693 tags. It can be used something like this local reader = require('read15') - result, err = reader.read15693() - if not result then + local info, err = reader.read() + if not info then print(err) return end - print(result.name) + print(info.UID) --]] -- Loads the commands-library @@ -29,10 +29,10 @@ local function sendToDevice(command, ignoreresponse) print(err) return nil, err end - if ignoreresponse then return nil,nil end + if ignoreresponse then return nil, nil end local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) - return response,nil + return response, nil end local function errorString15693(number) @@ -52,47 +52,31 @@ end local function parse15693(data) - -- From common/iso15693tools.h : - --[[ - #define ISO15_CRC_CHECK ((uint16_t)(~0xF0B8 & 0xFFFF)) // use this for checking of a correct crc - --]] - -- But that is very strange. Basically what is says is: + local bytes = utils.ConvertAsciiToBytes(data) + local tmp = utils.ConvertAsciiToHex(data) + -- define ISO15_CRC_CHECK 0F47 - -- So we can just use that directly... - -- The following code is based on cmdhf15.c around line 666 (NoTB!) and onwards - if core.iso15693_crc(data, string.len(data)) ~= 0xF47 then + local crcStr = utils.Crc15(tmp, #tmp) + + if string.sub(crcStr, #crcStr - 3) ~= '470F' then + print("CRC", crc ) return nil, "CRC failed" - elseif data[1] % 2 == 1 then + end + + if bytes[1] % 2 == 1 then -- Above is a poor-mans bit check: -- recv[0] & ISO15_RES_ERROR //(0x01) local err = "Tag returned error %i: %s" - err = string.format(err, data[1], errorString15693(data[1])) + err = string.format(err, bytes[1], errorString15693(bytes[1])) return nil, err end - -- Finally, let the parsing begin... - -- the UID is just the data in reverse... almost: - -- 0FC481FF70000104E001001B0301 - -- 8877665544332211 - -- UID = E004010070FF81C4 - -- 1122334455667788 - -- So, cut out the relevant part and reverse it - -- byte wise reverse.. not string reverse.. - local uid = data:sub(2,9):reverse() - local uidStr = bin.unpack("H8", uid) - - local _, manufacturer_code = bin.unpack("s", uid:sub(2,2)) - local _, tag_size = bin.unpack(">I", data:sub(12,13)) - local _, micref_modelcode = bin.unpack("s", data:sub(14,14)) - - return { - uid = uidStr, - manufacturer_code = manufacturer_code, - tag_size = tag_size, - micref_modelcode = micref_modelcode, + local uid = utils.ConvertBytesToHex( bytes, true ) + uid = uid:sub(5, #uid-4) + return { uid = uid, }micref_modelcode = micref_modelcode, } end --- This function does a connect and retrieves som einfo +-- This function does a connect and retrieves som info -- @param dont_disconnect - if true, does not disable the field -- @return if successfull: an table containing card info -- @return if unsuccessfull : nil, error @@ -100,53 +84,37 @@ local function read15693(slow, dont_readresponse) --[[ - We start by trying this command: + We start by trying this command: + MANDATORY (present in ALL iso15693 tags) command (the example below is sent to a tag different from the above one): - proxmark3> hf 15 cmd sysinfo -2 u - 0F C4 81 FF 70 00 01 04 E0 01 00 1B 03 01 - UID = E004010070FF81C4 - Philips; IC SL2 ICS20 - DSFID supported, set to 01 - AFI supported, set to 000 - Tag provides info on memory layout (vendor dependent) - 4 (or 3) bytes/page x 28 pages - IC reference given: 01 - - This command is not always present in ISO15693 tags (it is an optional standard command) but if it is present usually the tags contain all the "colored" info above. - - If the above command doesn't give an answer (see example below): - - proxmark3> hf 15 cmd sysinfo -2 u - timeout: no - - we must send the MANDATORY (present in ALL iso15693 tags) command (the example below is sent to a tag different from the above one): - - proxmark3> hf 15 cmd inquiry + pm3> hf 15 info u UID=E007C1A257394244 Tag Info: Texas Instrument; Tag-it HF-I Standard; 8x32bit - proxmark3> + pm3> - From which we obtain less information than the above one. + From which we obtain less information than the above one. + + "260100" means + 0x26 + -- #define ISO15_REQ_SUBCARRIER_SINGLE 0x00 // Tag should respond using one subcarrier (ASK) + -- #define ISO15_REQ_DATARATE_HIGH 0x02 // Tag should respond using high data rate + -- #define ISO15_REQ_NONINVENTORY 0x00 + 0x01 + inventory + 0x00 + --]] local command, result, info, err, data - data = "260100" - --add crc - local payload = utils.Crc15(data) - + data = utils.Crc15("260100") + command = Command:new{cmd = cmds.CMD_ISO_15693_COMMAND, - arg1 = string.len(payload) / 2, + arg1 = #data / 2, arg2 = 1, arg3 = 1, - data = payload} - - - -- These are defined in common/iso15693tools.h - -- #define ISO15_REQ_SUBCARRIER_SINGLE 0x00 // Tag should respond using one subcarrier (ASK) - -- #define ISO15_REQ_DATARATE_HIGH 0x02 // Tag should respond using high data rate - -- #define ISO15_REQ_NONINVENTORY 0x00 - + data = data} + if slow then command.arg2 = 0 end @@ -157,23 +125,25 @@ local function read15693(slow, dont_readresponse) local result, err = sendToDevice(command, dont_readresponse) if not result then print(err) - return nil, "15693 sysinfo: no answer" + return nil, "15693 identify: no answer" end - - local count, cmd, recvlen, arg1, arg2 = bin.unpack('LLLL',result) - data = string.sub(result, recvlen) - info, err = parse15693(data) - if err then - print(err) - return nil, err + local count, cmd, len, arg2, arg3 = bin.unpack('LLLL', result) + if len > 0 then + data = string.sub(result, count, count+len-1) + info, err = parse15693(data) + if err then + print(err) + return nil, err + end + return info + else + return nil, "Failed to get response" end - - return info end --- --- Waits for a mifare card to be placed within the vicinity of the reader. +-- Waits for a ISO15693 card to be placed within the vicinity of the reader. -- @return if successfull: an table containing card info -- @return if unsuccessfull : nil, error local function waitFor15693() diff --git a/client/lualibs/utils.lua b/client/lualibs/utils.lua index aefd68b4d..ca49c21e9 100644 --- a/client/lualibs/utils.lua +++ b/client/lualibs/utils.lua @@ -257,15 +257,23 @@ local Utils = end, --- -- Convert Byte array to string of hex - ConvertBytesToHex = function(bytes) + ConvertBytesToHex = function(bytes, reverse) if bytes == nil then return '' end if #bytes == 0 then return '' end local s={} - for i = 1, #bytes do - s[i] = string.format("%02X",bytes[i]) + if reverse then + local j=1 + for i = #bytes, 1, -1 do + s[i] = string.format("%02X", bytes[j]) + j = j + 1 + end + else + for i = 1, #bytes do + s[i] = string.format("%02X", bytes[i]) + end end return table.concat(s) - end, + end, -- Convert byte array to string with ascii ConvertBytesToAscii = function(bytes) if bytes == nil then return '' end From 2eee1663df84a6011467864be8bd55a2ddb27467 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 30 Nov 2018 21:04:32 +0100 Subject: [PATCH 0287/1938] chg: iso15693 small fix... --- client/lualibs/read15.lua | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/lualibs/read15.lua b/client/lualibs/read15.lua index 5681fe367..b0089b769 100644 --- a/client/lualibs/read15.lua +++ b/client/lualibs/read15.lua @@ -72,8 +72,7 @@ local function parse15693(data) end local uid = utils.ConvertBytesToHex( bytes, true ) uid = uid:sub(5, #uid-4) - return { uid = uid, }micref_modelcode = micref_modelcode, - } + return { uid = uid, } end -- This function does a connect and retrieves som info From 259dbadbe904bd1de45932a167509dba33cff6f2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 2 Dec 2018 10:05:31 +0100 Subject: [PATCH 0288/1938] chg: output unified --- client/loclass/fileutils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index c18b2fa30..367b19c97 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -212,12 +212,12 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty int res = json_dump_file(root, fileName, JSON_INDENT(2)); if (res) { - PrintAndLog("ERROR: can't save the file: %s", fileName); + PrintAndLogDevice(FAILED, "error: can't save the file: %s", fileName); json_decref(root); retval = 200; goto out; } - PrintAndLog("File `%s` saved.", fileName); + PrintAndLogDevice(SUCCESS, "File `%s` saved.", fileName); json_decref(root); From 47d954c79ff91cb0f9efa5d9f20400640636dd05 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 3 Dec 2018 18:16:25 +0200 Subject: [PATCH 0289/1938] move emv commands to root --- client/cmdhf.c | 1 - client/cmdhf.h | 1 - client/cmdmain.c | 1 + client/cmdmain.h | 1 + client/emv/cmdemv.c | 64 ++++++++++++++++++++++----------------------- client/emv/cmdemv.h | 16 ++++++------ 6 files changed, 42 insertions(+), 42 deletions(-) diff --git a/client/cmdhf.c b/client/cmdhf.c index 65b6bd33d..cb4e424da 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -112,7 +112,6 @@ static command_t CommandTable[] = { {"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"}, {"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"}, {"epa", CmdHFEPA, 1, "{ German Identification Card... }"}, - {"emv", CmdHFEMV, 1, "{ EMV RFIDs... }"}, {"felica", CmdHFFelica, 1, "{ ISO18092 / Felica RFIDs... }"}, {"legic", CmdHFLegic, 1, "{ LEGIC RFIDs... }"}, {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, diff --git a/client/cmdhf.h b/client/cmdhf.h index bd191ead5..b2dcc10f1 100644 --- a/client/cmdhf.h +++ b/client/cmdhf.h @@ -30,7 +30,6 @@ #include "cmdhfmfdes.h" // DESFIRE #include "cmdhftopaz.h" // TOPAZ #include "cmdhffelica.h" // ISO18092 / FeliCa -#include "emv/cmdemv.h" // EMV #include "cmdhffido.h" // FIDO authenticators #include "cmdtrace.h" // trace list diff --git a/client/cmdmain.c b/client/cmdmain.c index 85d7f19c3..5b147e76a 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -22,6 +22,7 @@ static command_t CommandTable[] = { {"hf", CmdHF, 1, "{ High Frequency commands... }"}, {"hw", CmdHW, 1, "{ Hardware commands... }"}, {"lf", CmdLF, 1, "{ Low Frequency commands... }"}, + {"emv", CmdEMV, 1, "{ EMV iso14443 and iso7816... }"}, {"rem", CmdRem, 1, "{ Add text to row in log file }"}, {"reveng", CmdRev, 1, "{ Crc calculations from the software reveng 1.53... }"}, {"script", CmdScript, 1, "{ Scripting commands }"}, diff --git a/client/cmdmain.h b/client/cmdmain.h index 74804300d..629cd98af 100644 --- a/client/cmdmain.h +++ b/client/cmdmain.h @@ -31,6 +31,7 @@ #include "cmdscript.h" #include "cmdcrc.h" #include "cmdanalyse.h" +#include "emv/cmdemv.h" // EMV #ifdef WITH_FLASH #include "cmdflashmem.h" // rdv40 flashmem commands diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 5a64892c4..fef34a863 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -40,7 +40,7 @@ void ParamLoadDefaults(struct tlvdb *tlvRoot) { TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC } -int CmdHFEMVSelect(const char *cmd) { +int CmdEMVSelect(const char *cmd) { uint8_t data[APDU_AID_LEN] = {0}; int datalen = 0; @@ -86,7 +86,7 @@ int CmdHFEMVSelect(const char *cmd) { return 0; } -int CmdHFEMVSearch(const char *cmd) { +int CmdEMVSearch(const char *cmd) { CLIParserInit("hf emv search", "Tries to select all applets from applet list:\n", @@ -131,7 +131,7 @@ int CmdHFEMVSearch(const char *cmd) { return 0; } -int CmdHFEMVPPSE(const char *cmd) { +int CmdEMVPPSE(const char *cmd) { CLIParserInit("hf emv pse", "Executes PSE/PPSE select command. It returns list of applet on the card:\n", @@ -181,7 +181,7 @@ int CmdHFEMVPPSE(const char *cmd) { return 0; } -int CmdHFEMVGPO(const char *cmd) { +int CmdEMVGPO(const char *cmd) { uint8_t data[APDU_RES_LEN] = {0}; int datalen = 0; @@ -276,7 +276,7 @@ int CmdHFEMVGPO(const char *cmd) { return 0; } -int CmdHFEMVReadRecord(const char *cmd) { +int CmdEMVReadRecord(const char *cmd) { uint8_t data[APDU_RES_LEN] = {0}; int datalen = 0; @@ -326,7 +326,7 @@ int CmdHFEMVReadRecord(const char *cmd) { return 0; } -int CmdHFEMVAC(const char *cmd) { +int CmdEMVAC(const char *cmd) { uint8_t data[APDU_RES_LEN] = {0}; int datalen = 0; @@ -437,7 +437,7 @@ int CmdHFEMVAC(const char *cmd) { return 0; } -int CmdHFEMVGenerateChallenge(const char *cmd) { +int CmdEMVGenerateChallenge(const char *cmd) { CLIParserInit("hf emv challenge", "Executes Generate Challenge command. It returns 4 or 8-byte random number from card.\nNeeds a EMV applet to be selected and GPO to be executed.", @@ -477,7 +477,7 @@ int CmdHFEMVGenerateChallenge(const char *cmd) { return 0; } -int CmdHFEMVInternalAuthenticate(const char *cmd) { +int CmdEMVInternalAuthenticate(const char *cmd) { uint8_t data[APDU_RES_LEN] = {0}; int datalen = 0; @@ -631,7 +631,7 @@ void ProcessGPOResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, } } -int CmdHFEMVExec(const char *cmd) { +int CmdEMVExec(const char *cmd) { uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; @@ -1071,7 +1071,7 @@ int CmdHFEMVExec(const char *cmd) { return 0; } -int CmdHFEMVScan(const char *cmd) { +int CmdEMVScan(const char *cmd) { uint8_t AID[APDU_AID_LEN] = {0}; size_t AIDlen = 0; uint8_t buf[APDU_RES_LEN] = {0}; @@ -1409,46 +1409,46 @@ int usage_emv_getrnd(void){ } //retrieve the UN number from a terminal -int CmdHfEMVGetrng(const char *Cmd) { +int CmdEMVGetrng(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); if ( cmdp == 'h' || cmdp == 'H') return usage_emv_getrnd(); return 0; } -int CmdHfEMVList(const char *Cmd) { +int CmdEMVList(const char *Cmd) { return CmdTraceList("7816"); } -int CmdHFEMVTest(const char *cmd) { +int CmdEMVTest(const char *cmd) { return ExecuteCryptoTests(true); } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"exec", CmdHFEMVExec, 0, "Executes EMV contactless transaction."}, - {"pse", CmdHFEMVPPSE, 0, "Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory."}, - {"search", CmdHFEMVSearch, 0, "Try to select all applets from applets list and print installed applets."}, - {"select", CmdHFEMVSelect, 0, "Select applet."}, - {"gpo", CmdHFEMVGPO, 0, "Execute GetProcessingOptions."}, - {"readrec", CmdHFEMVReadRecord, 0, "Read files from card."}, - {"genac", CmdHFEMVAC, 0, "Generate ApplicationCryptogram."}, - {"challenge", CmdHFEMVGenerateChallenge, 0, "Generate challenge."}, - {"intauth", CmdHFEMVInternalAuthenticate, 0, "Internal authentication."}, - {"scan", CmdHFEMVScan, 0, "Scan EMV card and save it contents to json file for emulator."}, - {"test", CmdHFEMVTest, 0, "Crypto logic test."}, + {"help", CmdHelp, 1, "This help"}, + {"exec", CmdEMVExec, 0, "Executes EMV contactless transaction."}, + {"pse", CmdEMVPPSE, 0, "Execute PPSE. It selects 2PAY.SYS.DDF01 or 1PAY.SYS.DDF01 directory."}, + {"search", CmdEMVSearch, 0, "Try to select all applets from applets list and print installed applets."}, + {"select", CmdEMVSelect, 0, "Select applet."}, + {"gpo", CmdEMVGPO, 0, "Execute GetProcessingOptions."}, + {"readrec", CmdEMVReadRecord, 0, "Read files from card."}, + {"genac", CmdEMVAC, 0, "Generate ApplicationCryptogram."}, + {"challenge", CmdEMVGenerateChallenge, 0, "Generate challenge."}, + {"intauth", CmdEMVInternalAuthenticate, 0, "Internal authentication."}, + {"scan", CmdEMVScan, 0, "Scan EMV card and save it contents to json file for emulator."}, + {"test", CmdEMVTest, 0, "Crypto logic test."}, /* - {"getrng", CmdHfEMVGetrng, 0, "get random number from terminal"}, - {"eload", CmdHfEmvELoad, 0, "load EMV tag into device"}, - {"dump", CmdHfEmvDump, 0, "dump EMV tag values"}, - {"sim", CmdHfEmvSim, 0, "simulate EMV tag"}, - {"clone", CmdHfEmvClone, 0, "clone an EMV tag"}, + {"getrng", CmdEMVGetrng, 0, "get random number from terminal"}, + {"eload", CmdEmvELoad, 0, "load EMV tag into device"}, + {"dump", CmdEmvDump, 0, "dump EMV tag values"}, + {"sim", CmdEmvSim, 0, "simulate EMV tag"}, + {"clone", CmdEmvClone, 0, "clone an EMV tag"}, */ - {"list", CmdHfEMVList, 0, "[Deprecated] List ISO7816 history"}, + {"list", CmdEMVList, 0, "[Deprecated] List ISO7816 history"}, {NULL, NULL, 0, NULL} }; -int CmdHFEMV(const char *Cmd) { +int CmdEMV(const char *Cmd) { clearCommandBuffer(); CmdsParse(CommandTable, Cmd); return 0; diff --git a/client/emv/cmdemv.h b/client/emv/cmdemv.h index 76fb89c4b..b4397fd15 100644 --- a/client/emv/cmdemv.h +++ b/client/emv/cmdemv.h @@ -26,13 +26,13 @@ #include "emvcore.h" #include "apduinfo.h" -int CmdHFEMV(const char *Cmd); +int CmdEMV(const char *Cmd); -extern int CmdHFEMVSelect(const char *cmd); -extern int CmdHFEMVSearch(const char *cmd); -extern int CmdHFEMVPPSE(const char *cmd); -extern int CmdHFEMVExec(const char *cmd); -extern int CmdHfEMVGetrng(const char *Cmd); -extern int CmdHfEMVList(const char *Cmd); +extern int CmdEMVSelect(const char *cmd); +extern int CmdEMVSearch(const char *cmd); +extern int CmdEMVPPSE(const char *cmd); +extern int CmdEMVExec(const char *cmd); +extern int CmdEMVGetrng(const char *Cmd); +extern int CmdEMVList(const char *Cmd); -#endif \ No newline at end of file +#endif From 7fd3536b295cbd220fc478f8028bb85db1bb292a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 3 Dec 2018 18:16:39 +0200 Subject: [PATCH 0290/1938] fix appveyor --- appveyor.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/appveyor.yml b/appveyor.yml index a38ff647b..1ebbfea5c 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -304,7 +304,7 @@ test_script: #proxmark crypto tests - ExecTest "hf emv test" "hf emv test" {bash -lc "cd ~/client;./proxmark3 comx -c 'hf emv test'"} "Tests ?OK" + ExecTest "emv test" "emv test" {bash -lc "cd ~/client;./proxmark3 comx -c 'emv test'"} "Tests ?OK" if ($global:TestsPassed) { From e8671e6c18f270b9aa5c494827c85a338db0b489 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 3 Dec 2018 18:21:05 +0200 Subject: [PATCH 0291/1938] fix emv command's help --- client/emv/cmdemv.c | 64 ++++++++++++++++++++++----------------------- 1 file changed, 32 insertions(+), 32 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index fef34a863..29f26b7a7 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -44,9 +44,9 @@ int CmdEMVSelect(const char *cmd) { uint8_t data[APDU_AID_LEN] = {0}; int datalen = 0; - CLIParserInit("hf emv select", + CLIParserInit("emv select", "Executes select applet command", - "Usage:\n\thf emv select -s a00000000101 -> select card, select applet\n\thf emv select -st a00000000101 -> select card, select applet, show result in TLV\n"); + "Usage:\n\temv select -s a00000000101 -> select card, select applet\n\temv select -st a00000000101 -> select card, select applet, show result in TLV\n"); void* argtable[] = { arg_param_begin, @@ -88,9 +88,9 @@ int CmdEMVSelect(const char *cmd) { int CmdEMVSearch(const char *cmd) { - CLIParserInit("hf emv search", + CLIParserInit("emv search", "Tries to select all applets from applet list:\n", - "Usage:\n\thf emv search -s -> select card and search\n\thf emv search -st -> select card, search and show result in TLV\n"); + "Usage:\n\temv search -s -> select card and search\n\temv search -st -> select card, search and show result in TLV\n"); void* argtable[] = { arg_param_begin, @@ -133,9 +133,9 @@ int CmdEMVSearch(const char *cmd) { int CmdEMVPPSE(const char *cmd) { - CLIParserInit("hf emv pse", + CLIParserInit("emv pse", "Executes PSE/PPSE select command. It returns list of applet on the card:\n", - "Usage:\n\thf emv pse -s1 -> select, get pse\n\thf emv pse -st2 -> select, get ppse, show result in TLV\n"); + "Usage:\n\temv pse -s1 -> select, get pse\n\temv pse -st2 -> select, get ppse, show result in TLV\n"); void* argtable[] = { arg_param_begin, @@ -185,11 +185,11 @@ int CmdEMVGPO(const char *cmd) { uint8_t data[APDU_RES_LEN] = {0}; int datalen = 0; - CLIParserInit("hf emv gpo", + CLIParserInit("emv gpo", "Executes Get Processing Options command. It returns data in TLV format (0x77 - format2) or plain format (0x80 - format1).\nNeeds a EMV applet to be selected.", - "Usage:\n\thf emv gpo -k -> execute GPO\n" - "\thf emv gpo -t 01020304 -> execute GPO with 4-byte PDOL data, show result in TLV\n" - "\thf emv gpo -pmt 9F 37 04 -> load params from file, make PDOL data from PDOL, execute GPO with PDOL, show result in TLV\n"); + "Usage:\n\temv gpo -k -> execute GPO\n" + "\temv gpo -t 01020304 -> execute GPO with 4-byte PDOL data, show result in TLV\n" + "\temv gpo -pmt 9F 37 04 -> load params from file, make PDOL data from PDOL, execute GPO with PDOL, show result in TLV\n"); void* argtable[] = { arg_param_begin, @@ -280,9 +280,9 @@ int CmdEMVReadRecord(const char *cmd) { uint8_t data[APDU_RES_LEN] = {0}; int datalen = 0; - CLIParserInit("hf emv readrec", + CLIParserInit("emv readrec", "Executes Read Record command. It returns data in TLV format.\nNeeds a bank applet to be selected and sometimes needs GPO to be executed.", - "Usage:\n\thf emv readrec -k 0101 -> read file SFI=01, SFIrec=01\n\thf emv readrec -kt 0201-> read file 0201 and show result in TLV\n"); + "Usage:\n\temv readrec -k 0101 -> read file SFI=01, SFIrec=01\n\temv readrec -kt 0201-> read file 0201 and show result in TLV\n"); void* argtable[] = { arg_param_begin, @@ -330,12 +330,12 @@ int CmdEMVAC(const char *cmd) { uint8_t data[APDU_RES_LEN] = {0}; int datalen = 0; - CLIParserInit("hf emv genac", + CLIParserInit("emv genac", "Generate Application Cryptogram command. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.", - "Usage:\n\thf emv genac -k 0102 -> generate AC with 2-byte CDOLdata and keep field ON after command\n" - "\thf emv genac -t 01020304 -> generate AC with 4-byte CDOL data, show result in TLV\n" - "\thf emv genac -Daac 01020304 -> generate AC with 4-byte CDOL data and terminal decision 'declined'\n" - "\thf emv genac -pmt 9F 37 04 -> load params from file, make CDOL data from CDOL, generate AC with CDOL, show result in TLV"); + "Usage:\n\temv genac -k 0102 -> generate AC with 2-byte CDOLdata and keep field ON after command\n" + "\temv genac -t 01020304 -> generate AC with 4-byte CDOL data, show result in TLV\n" + "\temv genac -Daac 01020304 -> generate AC with 4-byte CDOL data and terminal decision 'declined'\n" + "\temv genac -pmt 9F 37 04 -> load params from file, make CDOL data from CDOL, generate AC with CDOL, show result in TLV"); void* argtable[] = { arg_param_begin, @@ -439,9 +439,9 @@ int CmdEMVAC(const char *cmd) { int CmdEMVGenerateChallenge(const char *cmd) { - CLIParserInit("hf emv challenge", + CLIParserInit("emv challenge", "Executes Generate Challenge command. It returns 4 or 8-byte random number from card.\nNeeds a EMV applet to be selected and GPO to be executed.", - "Usage:\n\thf emv challenge -> get challenge\n\thf emv challenge -k -> get challenge, keep fileld ON\n"); + "Usage:\n\temv challenge -> get challenge\n\temv challenge -k -> get challenge, keep fileld ON\n"); void* argtable[] = { arg_param_begin, @@ -481,11 +481,11 @@ int CmdEMVInternalAuthenticate(const char *cmd) { uint8_t data[APDU_RES_LEN] = {0}; int datalen = 0; - CLIParserInit("hf emv intauth", + CLIParserInit("emv intauth", "Generate Internal Authenticate command. Usually needs 4-byte random number. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.", - "Usage:\n\thf emv intauth -k 01020304 -> execute Internal Authenticate with 4-byte DDOLdata and keep field ON after command\n" - "\thf emv intauth -t 01020304 -> execute Internal Authenticate with 4-byte DDOL data, show result in TLV\n" - "\thf emv intauth -pmt 9F 37 04 -> load params from file, make DDOL data from DDOL, Internal Authenticate with DDOL, show result in TLV"); + "Usage:\n\temv intauth -k 01020304 -> execute Internal Authenticate with 4-byte DDOLdata and keep field ON after command\n" + "\temv intauth -t 01020304 -> execute Internal Authenticate with 4-byte DDOL data, show result in TLV\n" + "\temv intauth -pmt 9F 37 04 -> load params from file, make DDOL data from DDOL, Internal Authenticate with DDOL, show result in TLV"); void* argtable[] = { arg_param_begin, @@ -646,10 +646,10 @@ int CmdEMVExec(const char *cmd) { struct tlvdb *tlvRoot = NULL; struct tlv *pdol_data_tlv = NULL; - CLIParserInit("hf emv exec", + CLIParserInit("emv exec", "Executes EMV contactless transaction", - "Usage:\n\thf emv exec -sat -> select card, execute MSD transaction, show APDU and TLV\n" - "\thf emv exec -satc -> select card, execute CDA transaction, show APDU and TLV\n"); + "Usage:\n\temv exec -sat -> select card, execute MSD transaction, show APDU and TLV\n" + "\temv exec -satc -> select card, execute CDA transaction, show APDU and TLV\n"); void* argtable[] = { arg_param_begin, @@ -1081,11 +1081,11 @@ int CmdEMVScan(const char *cmd) { json_t *root; json_error_t error; - CLIParserInit("hf emv scan", + CLIParserInit("emv scan", "Scan EMV card and save it contents to a file.", "It executes EMV contactless transaction and saves result to a file which can be used for emulation\n" - "Usage:\n\thf emv scan -at -> scan MSD transaction mode and show APDU and TLV\n" - "\thf emv scan -c -> scan CDA transaction mode\n"); + "Usage:\n\temv scan -at -> scan MSD transaction mode and show APDU and TLV\n" + "\temv scan -c -> scan CDA transaction mode\n"); void* argtable[] = { arg_param_begin, @@ -1160,7 +1160,7 @@ int CmdEMVScan(const char *cmd) { return 2; } - JsonSaveStr(root, "$.File.Created", "proxmark3 `hf emv scan`"); + JsonSaveStr(root, "$.File.Created", "proxmark3 `emv scan`"); JsonSaveStr(root, "$.Card.Communication", "iso14443-4a"); JsonSaveBufAsHex(root, "$.Card.UID", (uint8_t *)&card.uid, card.uidlen); @@ -1399,12 +1399,12 @@ int CmdEMVScan(const char *cmd) { int usage_emv_getrnd(void){ PrintAndLogEx(NORMAL, "retrieve the UN number from a terminal"); - PrintAndLogEx(NORMAL, "Usage: hf emv getrnd [h]"); + PrintAndLogEx(NORMAL, "Usage: emv getrnd [h]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv getrnd"); + PrintAndLogEx(NORMAL, " emv getrnd"); return 0; } From 2245673262aea9d9d8935bae2a0ac6985b31d628 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 3 Dec 2018 18:46:11 +0200 Subject: [PATCH 0292/1938] fix search big loop --- client/emv/emvcore.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index f2acda25c..b0a474fc7 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -260,6 +260,10 @@ int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool Includ if (APDULogging) PrintAndLogEx(NORMAL, "<<<< %s", sprint_hex(Result, *ResultLen)); + if (*ResultLen < 2) { + return 200; + } + *ResultLen -= 2; isw = Result[*ResultLen] * 0x0100 + Result[*ResultLen + 1]; if (sw) @@ -400,8 +404,8 @@ int EMVSearch(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvd if (++retrycnt < 3){ i--; } else { - // card select error, proxmark error - if (res == 1) { + // (1) - card select error, proxmark error OR (200) - result length = 0 + if (res == 1 || res == 200) { PrintAndLogEx(WARNING, "Exit..."); return 1; } From 01a10bade75b75afd0385ef96cb34a1531013bb6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 3 Dec 2018 18:49:54 +0200 Subject: [PATCH 0293/1938] Mastercard compute cryptographic checksum result will print anyway --- client/emv/cmdemv.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 29f26b7a7..7308b8335 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1048,10 +1048,10 @@ int CmdEMVExec(const char *cmd) { dreturn(9); } - if (decodeTLV) { - TLVPrintFromBuffer(buf, len); - PrintAndLogEx(NORMAL, ""); - } + // Mastercard compute cryptographic checksum result + TLVPrintFromBuffer(buf, len); + PrintAndLogEx(NORMAL, ""); + free(udol_data_tlv); } From 4c7e5757f3b3b656be9682bf6d9984ca47655890 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 3 Dec 2018 19:29:31 +0200 Subject: [PATCH 0294/1938] added channel parameter --- client/emv/cmdemv.c | 98 +++++++++++++++++++++++++++++------------- client/emv/emvcore.c | 72 +++++++++++++++++-------------- client/emv/emvcore.h | 29 +++++++------ client/fido/fidocore.c | 6 +-- 4 files changed, 128 insertions(+), 77 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 7308b8335..4ab8a8a56 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -54,6 +54,7 @@ int CmdEMVSelect(const char *cmd) { arg_lit0("kK", "keep", "keep field for next command"), arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("tT", "tlv", "TLV decode results"), + arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_strx0(NULL, NULL, "", NULL), arg_param_end }; @@ -63,7 +64,10 @@ int CmdEMVSelect(const char *cmd) { bool leaveSignalON = arg_get_lit(2); bool APDULogging = arg_get_lit(3); bool decodeTLV = arg_get_lit(4); - CLIGetHexWithReturn(5, data, &datalen); + EMVCommandChannel channel = ECC_CONTACTLESS; + if (arg_get_lit(5)) + channel = ECC_CONTACT; + CLIGetHexWithReturn(6, data, &datalen); CLIParserFree(); SetAPDULogging(APDULogging); @@ -72,7 +76,7 @@ int CmdEMVSelect(const char *cmd) { uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; - int res = EMVSelect(activateField, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL); + int res = EMVSelect(channel, activateField, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL); if (sw) PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); @@ -98,6 +102,7 @@ int CmdEMVSearch(const char *cmd) { arg_lit0("kK", "keep", "keep field ON for next command"), arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"), + arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_param_end }; CLIExecWithReturn(cmd, argtable, true); @@ -106,6 +111,9 @@ int CmdEMVSearch(const char *cmd) { bool leaveSignalON = arg_get_lit(2); bool APDULogging = arg_get_lit(3); bool decodeTLV = arg_get_lit(4); + EMVCommandChannel channel = ECC_CONTACTLESS; + if (arg_get_lit(5)) + channel = ECC_CONTACT; CLIParserFree(); SetAPDULogging(APDULogging); @@ -114,7 +122,7 @@ int CmdEMVSearch(const char *cmd) { const char *al = "Applets list"; t = tlvdb_fixed(1, strlen(al), (const unsigned char *)al); - if (EMVSearch(activateField, leaveSignalON, decodeTLV, t)) { + if (EMVSearch(channel, activateField, leaveSignalON, decodeTLV, t)) { tlvdb_free(t); return 2; } @@ -145,6 +153,7 @@ int CmdEMVPPSE(const char *cmd) { arg_lit0("2", "ppse", "ppse (2PAY.SYS.DDF01) mode (default mode)"), arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"), + arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_param_end }; CLIExecWithReturn(cmd, argtable, true); @@ -158,6 +167,9 @@ int CmdEMVPPSE(const char *cmd) { PSENum = 2; bool APDULogging = arg_get_lit(5); bool decodeTLV = arg_get_lit(6); + EMVCommandChannel channel = ECC_CONTACTLESS; + if (arg_get_lit(7)) + channel = ECC_CONTACT; CLIParserFree(); SetAPDULogging(APDULogging); @@ -166,7 +178,7 @@ int CmdEMVPPSE(const char *cmd) { uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; - int res = EMVSelectPSE(activateField, leaveSignalON, PSENum, buf, sizeof(buf), &len, &sw); + int res = EMVSelectPSE(channel, activateField, leaveSignalON, PSENum, buf, sizeof(buf), &len, &sw); if (sw) PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); @@ -198,6 +210,7 @@ int CmdEMVGPO(const char *cmd) { arg_lit0("mM", "make", "make PDOLdata from PDOL (tag 9F38) and parameters (by default uses default parameters)"), arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"), + arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_strx0(NULL, NULL, "", NULL), arg_param_end }; @@ -208,7 +221,10 @@ int CmdEMVGPO(const char *cmd) { bool dataMakeFromPDOL = arg_get_lit(3); bool APDULogging = arg_get_lit(4); bool decodeTLV = arg_get_lit(5); - CLIGetHexWithReturn(6, data, &datalen); + EMVCommandChannel channel = ECC_CONTACTLESS; + if (arg_get_lit(6)) + channel = ECC_CONTACT; + CLIGetHexWithReturn(7, data, &datalen); CLIParserFree(); SetAPDULogging(APDULogging); @@ -258,7 +274,7 @@ int CmdEMVGPO(const char *cmd) { uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; - int res = EMVGPO(leaveSignalON, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot); + int res = EMVGPO(channel, leaveSignalON, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot); if (pdol_data_tlv != &data_tlv) free(pdol_data_tlv); @@ -289,6 +305,7 @@ int CmdEMVReadRecord(const char *cmd) { arg_lit0("kK", "keep", "keep field ON for next command"), arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"), + arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_strx1(NULL, NULL, "", NULL), arg_param_end }; @@ -297,7 +314,10 @@ int CmdEMVReadRecord(const char *cmd) { bool leaveSignalON = arg_get_lit(1); bool APDULogging = arg_get_lit(2); bool decodeTLV = arg_get_lit(3); - CLIGetHexWithReturn(4, data, &datalen); + EMVCommandChannel channel = ECC_CONTACTLESS; + if (arg_get_lit(4)) + channel = ECC_CONTACT; + CLIGetHexWithReturn(5, data, &datalen); CLIParserFree(); if (datalen != 2) { @@ -311,7 +331,7 @@ int CmdEMVReadRecord(const char *cmd) { uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; - int res = EMVReadRecord(leaveSignalON, data[0], data[1], buf, sizeof(buf), &len, &sw, NULL); + int res = EMVReadRecord(channel, leaveSignalON, data[0], data[1], buf, sizeof(buf), &len, &sw, NULL); if (sw) PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); @@ -346,6 +366,7 @@ int CmdEMVAC(const char *cmd) { arg_lit0("mM", "make", "make CDOLdata from CDOL (tag 8C and 8D) and parameters (by default uses default parameters)"), arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"), + arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_strx1(NULL, NULL, "", NULL), arg_param_end }; @@ -375,7 +396,10 @@ int CmdEMVAC(const char *cmd) { bool dataMakeFromCDOL = arg_get_lit(5); bool APDULogging = arg_get_lit(6); bool decodeTLV = arg_get_lit(7); - CLIGetHexWithReturn(8, data, &datalen); + EMVCommandChannel channel = ECC_CONTACTLESS; + if (arg_get_lit(8)) + channel = ECC_CONTACT; + CLIGetHexWithReturn(9, data, &datalen); CLIParserFree(); SetAPDULogging(APDULogging); @@ -419,7 +443,7 @@ int CmdEMVAC(const char *cmd) { uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; - int res = EMVAC(leaveSignalON, termDecision, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot); + int res = EMVAC(channel, leaveSignalON, termDecision, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot); if (cdol_data_tlv != &data_tlv) free(cdol_data_tlv); @@ -447,12 +471,16 @@ int CmdEMVGenerateChallenge(const char *cmd) { arg_param_begin, arg_lit0("kK", "keep", "keep field ON for next command"), arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_param_end }; CLIExecWithReturn(cmd, argtable, true); bool leaveSignalON = arg_get_lit(1); bool APDULogging = arg_get_lit(2); + EMVCommandChannel channel = ECC_CONTACTLESS; + if (arg_get_lit(3)) + channel = ECC_CONTACT; CLIParserFree(); SetAPDULogging(APDULogging); @@ -461,7 +489,7 @@ int CmdEMVGenerateChallenge(const char *cmd) { uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; - int res = EMVGenerateChallenge(leaveSignalON, buf, sizeof(buf), &len, &sw, NULL); + int res = EMVGenerateChallenge(channel, leaveSignalON, buf, sizeof(buf), &len, &sw, NULL); if (sw) PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); @@ -494,6 +522,7 @@ int CmdEMVInternalAuthenticate(const char *cmd) { arg_lit0("mM", "make", "make DDOLdata from DDOL (tag 9F49) and parameters (by default uses default parameters)"), arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"), + arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_strx1(NULL, NULL, "", NULL), arg_param_end }; @@ -504,7 +533,10 @@ int CmdEMVInternalAuthenticate(const char *cmd) { bool dataMakeFromDDOL = arg_get_lit(3); bool APDULogging = arg_get_lit(4); bool decodeTLV = arg_get_lit(5); - CLIGetHexWithReturn(6, data, &datalen); + EMVCommandChannel channel = ECC_CONTACTLESS; + if (arg_get_lit(6)) + channel = ECC_CONTACT; + CLIGetHexWithReturn(7, data, &datalen); CLIParserFree(); SetAPDULogging(APDULogging); @@ -548,7 +580,7 @@ int CmdEMVInternalAuthenticate(const char *cmd) { uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; - int res = EMVInternalAuthenticate(leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL); + int res = EMVInternalAuthenticate(channel, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL); if (ddol_data_tlv != &data_tlv) free(ddol_data_tlv); @@ -663,6 +695,7 @@ int CmdEMVExec(const char *cmd) { arg_lit0("cC", "qvsdccda", "Transaction type - qVSDC or M/Chip plus CDA (SDAD generation)."), arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."), arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."), + arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_param_end }; CLIExecWithReturn(cmd, argtable, true); @@ -682,6 +715,9 @@ int CmdEMVExec(const char *cmd) { TrType = TT_VSDC; bool GenACGPO = arg_get_lit(9); + EMVCommandChannel channel = ECC_CONTACTLESS; + if (arg_get_lit(10)) + channel = ECC_CONTACT; CLIParserFree(); SetAPDULogging(showAPDU); @@ -696,7 +732,7 @@ int CmdEMVExec(const char *cmd) { // PPSE PrintAndLogEx(NORMAL, "\n* PPSE."); SetAPDULogging(showAPDU); - res = EMVSearchPSE(activateField, true, decodeTLV, tlvSelect); + res = EMVSearchPSE(channel, activateField, true, decodeTLV, tlvSelect); // check PPSE and select application id if (!res) { @@ -709,7 +745,7 @@ int CmdEMVExec(const char *cmd) { if (!AIDlen) { PrintAndLogEx(NORMAL, "\n* Search AID in list."); SetAPDULogging(false); - if (EMVSearch(activateField, true, decodeTLV, tlvSelect)) { + if (EMVSearch(channel, activateField, true, decodeTLV, tlvSelect)) { dreturn(2); } @@ -731,7 +767,7 @@ int CmdEMVExec(const char *cmd) { // Select PrintAndLogEx(NORMAL, "\n* Selecting AID:%s", sprint_hex_inrow(AID, AIDlen)); SetAPDULogging(showAPDU); - res = EMVSelect(false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot); + res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot); if (res) { PrintAndLogEx(WARNING, "Can't select AID (%d). Exit...", res); @@ -762,7 +798,7 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); PrintAndLogEx(NORMAL, "\n* GPO."); - res = EMVGPO(true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot); + res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot); free(pdol_data_tlv_data); //free(pdol_data_tlv); --- free on exit. @@ -818,7 +854,7 @@ int CmdEMVExec(const char *cmd) { for (int n = SFIstart; n <= SFIend; n++) { PrintAndLogEx(NORMAL, "* * * SFI[%02x] %d", SFI, n); - res = EMVReadRecord(true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot); + res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot); if (res) { PrintAndLogEx(WARNING, "Error SFI[%02x]. APDU error %4x", SFI, sw); continue; @@ -874,7 +910,7 @@ int CmdEMVExec(const char *cmd) { // DDA if (AIP & 0x0020) { PrintAndLogEx(NORMAL, "\n* DDA"); - trDDA(decodeTLV, tlvRoot); + trDDA(channel, decodeTLV, tlvRoot); } // transaction check @@ -924,7 +960,7 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "\n--> Mastercard M/Chip transaction."); PrintAndLogEx(NORMAL, "* * Generate challenge"); - res = EMVGenerateChallenge(true, buf, sizeof(buf), &len, &sw, tlvRoot); + res = EMVGenerateChallenge(channel, true, buf, sizeof(buf), &len, &sw, tlvRoot); if (res) { PrintAndLogEx(WARNING, "Error GetChallenge. APDU error %4x", sw); dreturn(6); @@ -952,7 +988,7 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "* * AC1"); // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD - res = EMVAC(true, (TrType == TT_CDA) ? EMVAC_TC + EMVAC_CDAREQ : EMVAC_TC, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot); + res = EMVAC(channel, true, (TrType == TT_CDA) ? EMVAC_TC + EMVAC_CDAREQ : EMVAC_TC, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot); if (res) { PrintAndLogEx(NORMAL, "AC1 error(%d): %4x. Exit...", res, sw); @@ -1041,7 +1077,7 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "\n* Mastercard compute cryptographic checksum(UDOL)"); - res = MSCComputeCryptoChecksum(true, (uint8_t *)udol_data_tlv->value, udol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot); + res = MSCComputeCryptoChecksum(channel, true, (uint8_t *)udol_data_tlv->value, udol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot); if (res) { PrintAndLogEx(WARNING, "Error Compute Crypto Checksum. APDU error %4x", sw); free(udol_data_tlv); @@ -1099,6 +1135,7 @@ int CmdEMVScan(const char *cmd) { arg_lit0("xX", "vsdc", "Transaction type - VSDC. For test only. Not a standart behavior."), arg_lit0("gG", "acgpo", "VISA. generate AC from GPO."), arg_lit0("mM", "merge", "Merge output file with card's data. (warning: the file may be corrupted!)"), + arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_str1(NULL, NULL, "output.json", "JSON output file name"), arg_param_end }; @@ -1119,10 +1156,13 @@ int CmdEMVScan(const char *cmd) { bool GenACGPO = arg_get_lit(9); bool MergeJSON = arg_get_lit(10); + EMVCommandChannel channel = ECC_CONTACTLESS; + if (arg_get_lit(11)) + channel = ECC_CONTACT; uint8_t relfname[250] ={0}; char *crelfname = (char *)relfname; int relfnamelen = 0; - CLIGetStrWithReturn(11, relfname, &relfnamelen); + CLIGetStrWithReturn(12, relfname, &relfnamelen); CLIParserFree(); SetAPDULogging(showAPDU); @@ -1174,7 +1214,7 @@ int CmdEMVScan(const char *cmd) { // EMV PPSE PrintAndLogEx(NORMAL, "--> PPSE."); - res = EMVSelectPSE(true, true, 2, buf, sizeof(buf), &len, &sw); + res = EMVSelectPSE(channel, true, true, 2, buf, sizeof(buf), &len, &sw); if (!res && sw == 0x9000){ if (decodeTLV) @@ -1191,7 +1231,7 @@ int CmdEMVScan(const char *cmd) { tlvdb_free(fci); } - res = EMVSearchPSE(false, true, decodeTLV, tlvSelect); + res = EMVSearchPSE(channel, false, true, decodeTLV, tlvSelect); // check PPSE and select application id if (!res) { @@ -1200,7 +1240,7 @@ int CmdEMVScan(const char *cmd) { // EMV SEARCH with AID list SetAPDULogging(false); PrintAndLogEx(NORMAL, "--> AID search."); - if (EMVSearch(false, true, decodeTLV, tlvSelect)) { + if (EMVSearch(channel, false, true, decodeTLV, tlvSelect)) { PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit..."); tlvdb_free(tlvSelect); DropField(); @@ -1233,7 +1273,7 @@ int CmdEMVScan(const char *cmd) { PrintAndLogEx(NORMAL, "\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen)); SetAPDULogging(showAPDU); - res = EMVSelect(false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot); + res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot); if (res) { PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res); @@ -1281,7 +1321,7 @@ int CmdEMVScan(const char *cmd) { PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); PrintAndLogEx(INFO, "-->GPO."); - res = EMVGPO(true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot); + res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot); free(pdol_data_tlv_data); free(pdol_data_tlv); @@ -1340,7 +1380,7 @@ int CmdEMVScan(const char *cmd) { for(int n = SFIstart; n <= SFIend; n++) { PrintAndLogEx(INFO, "---->SFI[%02x] %d", SFI, n); - res = EMVReadRecord(true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot); + res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot); if (res) { PrintAndLogEx(ERR, "SFI[%02x]. APDU error %4x", SFI, sw); continue; diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index b0a474fc7..aa68b6cdf 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -230,12 +230,13 @@ struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2) { return tlvdb_fixed(0x02, dCVVlen, dCVV); } -int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool IncludeLe, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { +int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool IncludeLe, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { uint8_t data[APDU_RES_LEN] = {0}; *ResultLen = 0; if (sw) *sw = 0; uint16_t isw = 0; + int res = 0; if (ActivateField) { DropField(); @@ -250,11 +251,16 @@ int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool Includ if (APDULogging) PrintAndLogEx(NORMAL, ">>>> %s", sprint_hex(data, (IncludeLe?6:5) + apdu.Lc)); - // 6 byes + data = INS + CLA + P1 + P2 + Lc + + Le(?IncludeLe) - int res = ExchangeAPDU14a(data, (IncludeLe?6:5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); - - if (res) { - return res; + switch(channel) { + case ECC_CONTACTLESS: + // 6 byes + data = INS + CLA + P1 + P2 + Lc + + Le(?IncludeLe) + res = ExchangeAPDU14a(data, (IncludeLe?6:5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); + if (res) { + return res; + } + break; + case ECC_CONTACT: + break; } if (APDULogging) @@ -289,15 +295,15 @@ int EMVExchangeEx(bool ActivateField, bool LeaveFieldON, sAPDU apdu, bool Includ return 0; } -int EMVExchange(bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { - return EMVExchangeEx(false, LeaveFieldON, apdu, true, Result, MaxResultLen, ResultLen, sw, tlv); +int EMVExchange(EMVCommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { + return EMVExchangeEx(channel, false, LeaveFieldON, apdu, true, Result, MaxResultLen, ResultLen, sw, tlv); } -int EMVSelect(bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { - return EMVExchangeEx(ActivateField, LeaveFieldON, (sAPDU){0x00, 0xa4, 0x04, 0x00, AIDLen, AID}, true, Result, MaxResultLen, ResultLen, sw, tlv); +int EMVSelect(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { + return EMVExchangeEx(channel, ActivateField, LeaveFieldON, (sAPDU){0x00, 0xa4, 0x04, 0x00, AIDLen, AID}, true, Result, MaxResultLen, ResultLen, sw, tlv); } -int EMVSelectPSE(bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { +int EMVSelectPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { uint8_t buf[APDU_AID_LEN] = {0}; *ResultLen = 0; int len = 0; @@ -314,19 +320,19 @@ int EMVSelectPSE(bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t } // select - res = EMVSelect(ActivateField, LeaveFieldON, buf, len, Result, MaxResultLen, ResultLen, sw, NULL); + res = EMVSelect(channel, ActivateField, LeaveFieldON, buf, len, Result, MaxResultLen, ResultLen, sw, NULL); return res; } -int EMVSearchPSE(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv) { +int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv) { uint8_t data[APDU_RES_LEN] = {0}; size_t datalen = 0; uint16_t sw = 0; int res; // select PPSE - res = EMVSelectPSE(ActivateField, true, 2, data, sizeof(data), &datalen, &sw); + res = EMVSelectPSE(channel, ActivateField, true, 2, data, sizeof(data), &datalen, &sw); if (!res){ struct tlvdb *t = NULL; @@ -340,7 +346,7 @@ int EMVSearchPSE(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct t while (ttmp) { const struct tlv *tgAID = tlvdb_get_inchild(ttmp, 0x4f, NULL); if (tgAID) { - res = EMVSelect(false, true, (uint8_t *)tgAID->value, tgAID->len, data, sizeof(data), &datalen, &sw, tlv); + res = EMVSelect(channel, false, true, (uint8_t *)tgAID->value, tgAID->len, data, sizeof(data), &datalen, &sw, tlv); // retry if error and not returned sw error if (res && res != 5) { @@ -387,7 +393,7 @@ int EMVSearchPSE(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct t return res; } -int EMVSearch(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv) { +int EMVSearch(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv) { uint8_t aidbuf[APDU_AID_LEN] = {0}; int aidlen = 0; uint8_t data[APDU_RES_LEN] = {0}; @@ -398,7 +404,7 @@ int EMVSearch(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvd int retrycnt = 0; for(int i = 0; i < AIDlistLen; i ++) { param_gethex_to_eol(AIDlist[i].aid, 0, aidbuf, sizeof(aidbuf), &aidlen); - res = EMVSelect((i == 0) ? ActivateField : false, (i == AIDlistLen - 1) ? LeaveFieldON : true, aidbuf, aidlen, data, sizeof(data), &datalen, &sw, tlv); + res = EMVSelect(channel, (i == 0) ? ActivateField : false, (i == AIDlistLen - 1) ? LeaveFieldON : true, aidbuf, aidlen, data, sizeof(data), &datalen, &sw, tlv); // retry if error and not returned sw error if (res && res != 5) { if (++retrycnt < 3){ @@ -468,38 +474,38 @@ int EMVSelectApplication(struct tlvdb *tlv, uint8_t *AID, size_t *AIDlen) { return 0; } -int EMVGPO(bool LeaveFieldON, uint8_t *PDOL, size_t PDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { - return EMVExchange(LeaveFieldON, (sAPDU){0x80, 0xa8, 0x00, 0x00, PDOLLen, PDOL}, Result, MaxResultLen, ResultLen, sw, tlv); +int EMVGPO(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *PDOL, size_t PDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { + return EMVExchange(channel, LeaveFieldON, (sAPDU){0x80, 0xa8, 0x00, 0x00, PDOLLen, PDOL}, Result, MaxResultLen, ResultLen, sw, tlv); } -int EMVReadRecord(bool LeaveFieldON, uint8_t SFI, uint8_t SFIrec, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { - int res = EMVExchange(LeaveFieldON, (sAPDU){0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, Result, MaxResultLen, ResultLen, sw, tlv); +int EMVReadRecord(EMVCommandChannel channel, bool LeaveFieldON, uint8_t SFI, uint8_t SFIrec, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { + int res = EMVExchange(channel, LeaveFieldON, (sAPDU){0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, Result, MaxResultLen, ResultLen, sw, tlv); if (*sw == 0x6700) { PrintAndLogEx(INFO, ">>> trying to reissue command withouth Le..."); - res = EMVExchangeEx(false, LeaveFieldON, (sAPDU){0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, false, Result, MaxResultLen, ResultLen, sw, tlv); + res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU){0x00, 0xb2, SFIrec, (SFI << 3) | 0x04, 0, NULL}, false, Result, MaxResultLen, ResultLen, sw, tlv); } return res; } -int EMVAC(bool LeaveFieldON, uint8_t RefControl, uint8_t *CDOL, size_t CDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { - return EMVExchange(LeaveFieldON, (sAPDU){0x80, 0xae, RefControl, 0x00, CDOLLen, CDOL}, Result, MaxResultLen, ResultLen, sw, tlv); +int EMVAC(EMVCommandChannel channel, bool LeaveFieldON, uint8_t RefControl, uint8_t *CDOL, size_t CDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { + return EMVExchange(channel, LeaveFieldON, (sAPDU){0x80, 0xae, RefControl, 0x00, CDOLLen, CDOL}, Result, MaxResultLen, ResultLen, sw, tlv); } -int EMVGenerateChallenge(bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { - int res = EMVExchange(LeaveFieldON, (sAPDU){0x00, 0x84, 0x00, 0x00, 0x00, NULL}, Result, MaxResultLen, ResultLen, sw, tlv); +int EMVGenerateChallenge(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { + int res = EMVExchange(channel, LeaveFieldON, (sAPDU){0x00, 0x84, 0x00, 0x00, 0x00, NULL}, Result, MaxResultLen, ResultLen, sw, tlv); if (*sw == 0x6700) { PrintAndLogEx(INFO, ">>> trying to reissue command withouth Le..."); - res = EMVExchangeEx(false, LeaveFieldON, (sAPDU){0x00, 0x84, 0x00, 0x00, 0x00, NULL}, false, Result, MaxResultLen, ResultLen, sw, tlv); + res = EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU){0x00, 0x84, 0x00, 0x00, 0x00, NULL}, false, Result, MaxResultLen, ResultLen, sw, tlv); } return res; } -int EMVInternalAuthenticate(bool LeaveFieldON, uint8_t *DDOL, size_t DDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { - return EMVExchange(LeaveFieldON, (sAPDU){0x00, 0x88, 0x00, 0x00, DDOLLen, DDOL}, Result, MaxResultLen, ResultLen, sw, tlv); +int EMVInternalAuthenticate(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *DDOL, size_t DDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { + return EMVExchange(channel, LeaveFieldON, (sAPDU){0x00, 0x88, 0x00, 0x00, DDOLLen, DDOL}, Result, MaxResultLen, ResultLen, sw, tlv); } -int MSCComputeCryptoChecksum(bool LeaveFieldON, uint8_t *UDOL, uint8_t UDOLlen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { - return EMVExchange(LeaveFieldON, (sAPDU){0x80, 0x2a, 0x8e, 0x80, UDOLlen, UDOL}, Result, MaxResultLen, ResultLen, sw, tlv); +int MSCComputeCryptoChecksum(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *UDOL, uint8_t UDOLlen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { + return EMVExchange(channel, LeaveFieldON, (sAPDU){0x80, 0x2a, 0x8e, 0x80, UDOLlen, UDOL}, Result, MaxResultLen, ResultLen, sw, tlv); } // Authentication @@ -569,7 +575,7 @@ int trSDA(struct tlvdb *tlv) { static const unsigned char default_ddol_value[] = {0x9f, 0x37, 0x04}; static struct tlv default_ddol_tlv = {.tag = 0x9f49, .len = 3, .value = default_ddol_value }; -int trDDA(bool decodeTLV, struct tlvdb *tlv) { +int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; @@ -709,7 +715,7 @@ int trDDA(bool decodeTLV, struct tlvdb *tlv) { PrintAndLogEx(NORMAL, "DDOL data[%d]: %s", ddol_data_tlv->len, sprint_hex(ddol_data_tlv->value, ddol_data_tlv->len)); PrintAndLogEx(NORMAL, "\n* Internal Authenticate"); - int res = EMVInternalAuthenticate(true, (uint8_t *)ddol_data_tlv->value, ddol_data_tlv->len, buf, sizeof(buf), &len, &sw, NULL); + int res = EMVInternalAuthenticate(channel, true, (uint8_t *)ddol_data_tlv->value, ddol_data_tlv->len, buf, sizeof(buf), &len, &sw, NULL); if (res) { PrintAndLogEx(WARNING, "Internal Authenticate error(%d): %4x. Exit...", res, sw); free(ddol_data_tlv); diff --git a/client/emv/emvcore.h b/client/emv/emvcore.h index 5fb6f202c..c2b1746e1 100644 --- a/client/emv/emvcore.h +++ b/client/emv/emvcore.h @@ -32,6 +32,11 @@ #define APDU_RES_LEN 260 #define APDU_AID_LEN 50 +typedef enum { + ECC_CONTACTLESS, + ECC_CONTACT +} EMVCommandChannel; + enum TransactionType { TT_MSD, TT_VSDC, // not standart for contactless!!!! @@ -71,28 +76,28 @@ extern struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2); extern void SetAPDULogging(bool logging); // exchange -extern int EMVExchange(bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); +extern int EMVExchange(EMVCommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); // search application -extern int EMVSearchPSE(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv); -extern int EMVSearch(bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv); -extern int EMVSelectPSE(bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); -extern int EMVSelect(bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); +extern int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv); +extern int EMVSearch(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv); +extern int EMVSelectPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); +extern int EMVSelect(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); // select application extern int EMVSelectApplication(struct tlvdb *tlv, uint8_t *AID, size_t *AIDlen); // Get Processing Options -extern int EMVGPO(bool LeaveFieldON, uint8_t *PDOL, size_t PDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); -extern int EMVReadRecord(bool LeaveFieldON, uint8_t SFI, uint8_t SFIrec, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); +extern int EMVGPO(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *PDOL, size_t PDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); +extern int EMVReadRecord(EMVCommandChannel channel, bool LeaveFieldON, uint8_t SFI, uint8_t SFIrec, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); // AC -extern int EMVGenerateChallenge(bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); -extern int EMVAC(bool LeaveFieldON, uint8_t RefControl, uint8_t *CDOL, size_t CDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); +extern int EMVGenerateChallenge(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); +extern int EMVAC(EMVCommandChannel channel, bool LeaveFieldON, uint8_t RefControl, uint8_t *CDOL, size_t CDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); // DDA -extern int EMVInternalAuthenticate(bool LeaveFieldON, uint8_t *DDOL, size_t DDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); +extern int EMVInternalAuthenticate(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *DDOL, size_t DDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); // Mastercard -int MSCComputeCryptoChecksum(bool LeaveFieldON, uint8_t *UDOL, uint8_t UDOLlen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); +int MSCComputeCryptoChecksum(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *UDOL, uint8_t UDOLlen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); // Auth extern int trSDA(struct tlvdb *tlv); -extern int trDDA(bool decodeTLV, struct tlvdb *tlv); +extern int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv); extern int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_tlv, struct tlv *ac_data_tlv); extern int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root); diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 39c2052f9..ee39fbbe9 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -170,17 +170,17 @@ char *fido2GetCmdMemberDescription(uint8_t cmdCode, bool isResponse, int memberN int FIDOSelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { uint8_t data[] = {0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01}; - return EMVSelect(ActivateField, LeaveFieldON, data, sizeof(data), Result, MaxResultLen, ResultLen, sw, NULL); + return EMVSelect(ECC_CONTACTLESS, ActivateField, LeaveFieldON, data, sizeof(data), Result, MaxResultLen, ResultLen, sw, NULL); } int FIDOExchange(sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { - int res = EMVExchange(true, apdu, Result, MaxResultLen, ResultLen, sw, NULL); + int res = EMVExchange(ECC_CONTACTLESS, true, apdu, Result, MaxResultLen, ResultLen, sw, NULL); if (res == 5) // apdu result (sw) not a 0x9000 res = 0; // software chaining while (!res && (*sw >> 8) == 0x61) { size_t oldlen = *ResultLen; - res = EMVExchange(true, (sAPDU){0x00, 0xC0, 0x00, 0x00, 0x00, NULL}, &Result[oldlen], MaxResultLen - oldlen, ResultLen, sw, NULL); + res = EMVExchange(ECC_CONTACTLESS, true, (sAPDU){0x00, 0xC0, 0x00, 0x00, 0x00, NULL}, &Result[oldlen], MaxResultLen - oldlen, ResultLen, sw, NULL); if (res == 5) // apdu result (sw) not a 0x9000 res = 0; From 898484f642aed5ad696690728431bd4419ccce7d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 4 Dec 2018 13:51:28 +0100 Subject: [PATCH 0295/1938] FIX: compilation for OS X, see https://github.com/Proxmark/proxmark3/pull/730/ (@jmichelp) --- uart/uart_posix.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/uart/uart_posix.c b/uart/uart_posix.c index 0ead61500..d857729d6 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -55,6 +55,11 @@ #include #include +// Taken from https://github.com/unbit/uwsgi/commit/b608eb1772641d525bfde268fe9d6d8d0d5efde7 +#ifndef SOL_TCP +# define SOL_TCP IPPROTO_TCP +#endif + typedef struct termios term_info; typedef struct { int fd; // Serial port file descriptor From 312ec79e481b9e71e90f144730e630576fa44ab6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 5 Dec 2018 17:27:28 +0200 Subject: [PATCH 0296/1938] added sketch sc apdu --- client/cmdsmartcard.c | 6 ++++++ client/cmdsmartcard.h | 2 ++ client/emv/emvcore.c | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 59172b9c8..0173e0ca2 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -244,6 +244,12 @@ int CmdSmartRaw(const char *Cmd) { return 0; } +int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { + + return 0; +} + + int CmdSmartUpgrade(const char *Cmd) { PrintAndLogEx(WARNING, "WARNING - Smartcard socket firmware upgrade."); diff --git a/client/cmdsmartcard.h b/client/cmdsmartcard.h index 5ba453e30..8cc0ae851 100644 --- a/client/cmdsmartcard.h +++ b/client/cmdsmartcard.h @@ -32,6 +32,8 @@ extern int CmdSmartUpgrade(const char* cmd); extern int CmdSmartInfo(const char* cmd); extern int CmdSmartReader(const char *Cmd); +extern int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); + extern int usage_sm_raw(void); extern int usage_sm_reader(void); extern int usage_sm_info(void); diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index aa68b6cdf..7df706e8e 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -260,6 +260,11 @@ int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveField } break; case ECC_CONTACT: + //int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); + res = ExchangeAPDU14a(data, (IncludeLe?6:5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); + if (res) { + return res; + } break; } From ec3acc7d8af7b833aab655ce4ae2935a652edc6a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 5 Dec 2018 19:23:13 +0200 Subject: [PATCH 0297/1938] some of emv commands works in test mode --- client/cmdsmartcard.c | 33 +++++++++++++++++++++++++++++++-- client/emv/emvcore.c | 2 +- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 0173e0ca2..d02e93477 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -87,6 +87,14 @@ static bool smart_select(bool silent) { if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); return false; } + + if (!silent) { + smart_card_atr_t card; + memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t)); + + PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len)); + } + return true; } @@ -124,8 +132,8 @@ static int smart_response(uint8_t *data) { goto out; } - PrintAndLogEx(INFO, "Requesting response"); - uint8_t getstatus[] = {0x00, ISO7816_GETSTATUS, 0x00, 0x00, len }; + PrintAndLogEx(INFO, "Requesting response. len=0x%x", len); + uint8_t getstatus[] = {ISO7816_GETSTATUS, 0x00, 0x00, len}; UsbCommand cStatus = {CMD_SMART_RAW, {SC_RAW, sizeof(getstatus), 0}}; memcpy(cStatus.d.asBytes, getstatus, sizeof(getstatus) ); clearCommandBuffer(); @@ -245,6 +253,27 @@ int CmdSmartRaw(const char *Cmd) { } int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { + *dataoutlen = 0; + + if (activateCard) + smart_select(false); + printf("* APDU SC\n"); + + UsbCommand c = {CMD_SMART_RAW, {SC_RAW | SC_CONNECT, datainlen, 0}}; + if (activateCard) { + c.arg[0] |= SC_SELECT; + } + memcpy(c.d.asBytes, datain, datainlen); + clearCommandBuffer(); + SendCommand(&c); + + int len = smart_response(dataout); + + if ( len < 0 ) { + return 2; + } + + *dataoutlen = len; return 0; } diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 7df706e8e..fcf0bf81f 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -261,7 +261,7 @@ int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveField break; case ECC_CONTACT: //int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); - res = ExchangeAPDU14a(data, (IncludeLe?6:5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); + res = ExchangeAPDUSC(data, (IncludeLe?6:5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); if (res) { return res; } From 34b53a5b48ff342fe7ed9c6060467c57c145edcd Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 6 Dec 2018 14:44:55 +0200 Subject: [PATCH 0298/1938] exchange works --- client/cmdsmartcard.c | 86 ++++++++++++++++++++++++++++++++----------- 1 file changed, 65 insertions(+), 21 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index d02e93477..db3c69f0e 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -119,29 +119,56 @@ static int smart_wait(uint8_t *data) { return len; } -static int smart_response(uint8_t *data) { +static int smart_response(uint8_t apduINS, uint8_t *data) { - int len = -1; int datalen = smart_wait(data); + bool needGetData = false; - if ( data[datalen - 2] == 0x61 || data[datalen - 2] == 0x9F ) { - len = data[datalen - 1]; - } - - if (len == -1 ) { + if (datalen < 2 ) { goto out; } - PrintAndLogEx(INFO, "Requesting response. len=0x%x", len); - uint8_t getstatus[] = {ISO7816_GETSTATUS, 0x00, 0x00, len}; - UsbCommand cStatus = {CMD_SMART_RAW, {SC_RAW, sizeof(getstatus), 0}}; - memcpy(cStatus.d.asBytes, getstatus, sizeof(getstatus) ); - clearCommandBuffer(); - SendCommand(&cStatus); - - datalen = smart_wait(data); -out: + if (datalen > 2 && data[0] != apduINS) { + PrintAndLogEx(ERR, "Card ACK error. len=0x%x data[0]=%02x", datalen, data[0]); + datalen = 0; + goto out; + } + if ( data[datalen - 2] == 0x61 || data[datalen - 2] == 0x9F ) { + needGetData = true; + } + + if (needGetData) { + int len = data[datalen - 1]; + PrintAndLogEx(INFO, "Requesting response. len=0x%x", len); + uint8_t getstatus[] = {ISO7816_GETSTATUS, 0x00, 0x00, len}; + UsbCommand cStatus = {CMD_SMART_RAW, {SC_RAW, sizeof(getstatus), 0}}; + memcpy(cStatus.d.asBytes, getstatus, sizeof(getstatus) ); + clearCommandBuffer(); + SendCommand(&cStatus); + + datalen = smart_wait(data); + + if (datalen < 2 ) { + goto out; + } + + if (datalen > 2 && data[0] != ISO7816_GETSTATUS) { + PrintAndLogEx(ERR, "GetResponse ACK error. len=0x%x data[0]=%02x", len, data[0]); + datalen = 0; + goto out; + } + + if (datalen != len + 2 + 1) { // 2 - response, 1 - ACK + PrintAndLogEx(WARNING, "GetResponse wrong length. Must be: 0x%02x but: 0x%02x", len, datalen - 3); + } + } + + if (datalen > 2) { + datalen--; + memmove(data, &data[1], datalen); + } +out: return datalen; } @@ -227,7 +254,7 @@ int CmdSmartRaw(const char *Cmd) { if ( !buf ) return 1; - int len = smart_response(buf); + int len = smart_response(data[1], buf); if ( len < 0 ) { free(buf); return 2; @@ -239,7 +266,7 @@ int CmdSmartRaw(const char *Cmd) { memcpy(c.d.asBytes, data, sizeof(data) ); clearCommandBuffer(); SendCommand(&c); - len = smart_response(buf); + len = smart_response(data[1], buf); data[4] = 0; } @@ -267,12 +294,29 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave clearCommandBuffer(); SendCommand(&c); - int len = smart_response(dataout); + int len = smart_response(datain[1], dataout); if ( len < 0 ) { return 2; } + // retry + if (len > 1 && dataout[len - 2] == 0x6c && datainlen > 4) { + UsbCommand c2 = {CMD_SMART_RAW, {SC_RAW, datainlen, 0}}; + memcpy(c2.d.asBytes, datain, datainlen); + + int vlen = 5 + datain[4]; + if (datainlen == vlen) + datainlen++; + + c2.d.asBytes[vlen] = dataout[len - 1]; + + clearCommandBuffer(); + SendCommand(&c2); + + len = smart_response(datain[1], dataout); + } + *dataoutlen = len; return 0; @@ -569,7 +613,7 @@ int CmdSmartBruteforceSFI(const char *Cmd) { clearCommandBuffer(); SendCommand(&c); - smart_response(buf); + smart_response(data[1], buf); // if 0x6C if ( buf[0] == 0x6C ) { @@ -578,7 +622,7 @@ int CmdSmartBruteforceSFI(const char *Cmd) { memcpy(c.d.asBytes, data, sizeof(data) ); clearCommandBuffer(); SendCommand(&c); - uint8_t len = smart_response(buf); + uint8_t len = smart_response(data[1], buf); // TLV decoder if (len > 4) From 17d0194aeaea402ca09464e0537db99c384bf4d5 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 6 Dec 2018 19:47:57 +0200 Subject: [PATCH 0299/1938] small fix and block scan command --- client/emv/cmdemv.c | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 4ab8a8a56..0ddf4e035 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -707,16 +707,16 @@ int CmdEMVExec(const char *cmd) { bool forceSearch = arg_get_lit(5); enum TransactionType TrType = TT_MSD; - if (arg_get_lit(6)) - TrType = TT_QVSDCMCHIP; if (arg_get_lit(7)) - TrType = TT_CDA; + TrType = TT_QVSDCMCHIP; if (arg_get_lit(8)) + TrType = TT_CDA; + if (arg_get_lit(9)) TrType = TT_VSDC; - bool GenACGPO = arg_get_lit(9); + bool GenACGPO = arg_get_lit(10); EMVCommandChannel channel = ECC_CONTACTLESS; - if (arg_get_lit(10)) + if (arg_get_lit(11)) channel = ECC_CONTACT; CLIParserFree(); @@ -1167,6 +1167,12 @@ int CmdEMVScan(const char *cmd) { SetAPDULogging(showAPDU); + // TODO + if (channel == ECC_CONTACT) { + PrintAndLogEx(ERR, "Do not use contact interface. Exit."); + return 1; + } + // current path + file name if (!strstr(crelfname, ".json")) strcat(crelfname, ".json"); From 80d07bcaac284a936ab50b583d3f594761d53792 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 6 Dec 2018 20:04:28 +0200 Subject: [PATCH 0300/1938] added code if AIP not found --- client/emv/cmdemv.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 0ddf4e035..647123faf 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -895,11 +895,16 @@ int CmdEMVExec(const char *cmd) { tlvdb_add(tlvRoot, oda); PrintAndLogEx(NORMAL, "* Input list for Offline Data Authentication added to TLV. len=%d \n", ODAiListLen); } - + // get AIP + uint16_t AIP = 0; const struct tlv *AIPtlv = tlvdb_get(tlvRoot, 0x82, NULL); - uint16_t AIP = AIPtlv->value[0] + AIPtlv->value[1] * 0x100; - PrintAndLogEx(NORMAL, "* * AIP=%04x", AIP); + if (AIPtlv) { + AIP = AIPtlv->value[0] + AIPtlv->value[1] * 0x100; + PrintAndLogEx(NORMAL, "* * AIP=%04x", AIP); + } else { + PrintAndLogEx(ERR, "Can't found AIP."); + } // SDA if (AIP & 0x0040) { From 04b78600967a0f011827019362d96312012f7a97 Mon Sep 17 00:00:00 2001 From: RFID Research Group Date: Fri, 7 Dec 2018 17:36:50 +0100 Subject: [PATCH 0301/1938] Update default_pwd.dic from https://github.com/Proxmark/proxmark3/pull/735/ --- client/default_pwd.dic | 1 + 1 file changed, 1 insertion(+) diff --git a/client/default_pwd.dic b/client/default_pwd.dic index cdc99b5c4..dd1364385 100644 --- a/client/default_pwd.dic +++ b/client/default_pwd.dic @@ -3,6 +3,7 @@ 51243648, 000D8787, 19920427, +65857569, //chinese "handheld RFID writer" blue cloner from circa 2013 (also sold by xfpga.com) # ref. http://kazus.ru/forums/showpost.php?p=1045937&postcount=77 05D73B9F, # ref. http://www.proxmark.org/forum/viewtopic.php?= From 384a277b43d51100fdc6f510ff4fc18dd9f1e0a9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 7 Dec 2018 19:58:22 +0200 Subject: [PATCH 0302/1938] added basic atr decode --- client/cmdsmartcard.c | 103 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 103 insertions(+) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index db3c69f0e..06846b824 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -72,6 +72,106 @@ int usage_sm_brute(void) { return 0; } +static int PrintATR(uint8_t *atr, size_t atrlen) { + uint8_t vxor = 0; + for (int i = 1; i < atrlen; i++) + vxor ^= atr[i]; + + if (vxor) + PrintAndLogEx(WARNING, "Check summ error. Must be 0 but: 0x%02x", vxor); + else + PrintAndLogEx(INFO, "Check summ OK."); + + if (atr[0] != 0x3b) + PrintAndLogEx(WARNING, "Not a direct convention: 0x%02x", atr[0]); + + uint8_t T0 = atr[1]; + uint8_t K = T0 & 0x0F; + uint8_t TD1 = 0; + + uint8_t T1len = 0; + uint8_t TD1len = 0; + uint8_t TDilen = 0; + + if (T0 & 0x10) { + PrintAndLog("TA1 (Maximum clock frequency, proposed bit duration): 0x%02x", atr[2 + T1len]); + T1len++; + } + if (T0 & 0x20) { + PrintAndLog("TB1 (Deprecated: VPP requirements): 0x%02x", atr[2 + T1len]); + T1len++; + } + if (T0 & 0x40) { + PrintAndLog("TC1 (Extra delay between bytes required by card): 0x%02x", atr[2 + T1len]); + T1len++; + } + if (T0 & 0x80) { + PrintAndLog("TD1 (First offered transmission protocol, presence of TA2..TD2): 0x%02x", atr[2 + T1len]); + TD1 = atr[2 + T1len]; + T1len++; + + if (TD1 & 0x10) { + PrintAndLog("TA2 (Specific protocol and parameters to be used after the ATR): 0x%02x", atr[2 + T1len + TD1len]); + TD1len++; + } + if (TD1 & 0x20) { + PrintAndLog("TB2 (Deprecated: VPP precise voltage requirement): 0x%02x", atr[2 + T1len + TD1len]); + TD1len++; + } + if (TD1 & 0x40) { + PrintAndLog("TC2 (Maximum waiting time for protocol T=0): 0x%02x", atr[2 + T1len + TD1len]); + TD1len++; + } + if (TD1 & 0x80) { + PrintAndLog("TD2 (A supported protocol or more global parameters, presence of TA3..TD3): 0x%02x", atr[2 + T1len + TD1len]); + uint8_t TDi = atr[2 + T1len + TD1len]; + TD1len++; + + bool nextCycle = true; + uint8_t vi = 3; + while (nextCycle) { + nextCycle = false; + if (TDi & 0x10) { + PrintAndLog("TA%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); + TDilen++; + } + if (TDi & 0x20) { + PrintAndLog("TB%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); + TDilen++; + } + if (TDi & 0x40) { + PrintAndLog("TC%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); + TDilen++; + } + if (TDi & 0x80) { + PrintAndLog("TD%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); + TDi = atr[2 + T1len + TD1len + TDilen]; + TDilen++; + + nextCycle = true; + vi++; + } + } + } + } + + uint8_t calen = 2 + T1len + TD1len + TDilen + K; + + if (atrlen != calen && atrlen != calen + 1) // may be CRC + PrintAndLogEx(ERR, "ATR length error. len: %d, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen, T1len, TD1len, TDilen, K); + else + PrintAndLogEx(INFO, "ATR length OK."); + + PrintAndLog("Historical bytes len: 0x%02x", K); + if (K > 0) + PrintAndLog("The format of historical bytes: %02x", atr[2 + T1len + TD1len + TDilen]); + if (K > 1) + PrintAndLog("Historical bytes: %s", sprint_hex(&atr[2 + T1len + TD1len + TDilen], K)); + + return 0; +} + + static bool smart_select(bool silent) { UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}}; clearCommandBuffer(); @@ -475,6 +575,9 @@ int CmdSmartInfo(const char *Cmd){ PrintAndLogEx(INFO, "ISO76183 ATR : %s", sprint_hex(card.atr, card.atr_len)); PrintAndLogEx(INFO, "look up ATR"); PrintAndLogEx(INFO, "http://smartcard-atr.appspot.com/parse?ATR=%s", sprint_hex_inrow(card.atr, card.atr_len) ); + PrintAndLogEx(INFO, ""); + PrintAndLogEx(INFO, "ATR:"); + PrintATR(card.atr, card.atr_len); return 0; } From 7ceac11308a1f1f8a957e83a07ec1378f1c21786 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 7 Dec 2018 20:11:40 +0100 Subject: [PATCH 0303/1938] chg: Added some more Mifare sector trailer decoding (@Fl0-0) --- client/cmdhfmf.c | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 8653a8994..d46344451 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -624,6 +624,15 @@ int CmdHF14AMfRdSc(const char *Cmd) { PrintAndLogEx(NORMAL, "data : %s", sprint_hex(data + i * 16, 16)); } PrintAndLogEx(NORMAL, "trailer: %s", sprint_hex(data + (sectorNo<32?3:15) * 16, 16)); + + PrintAndLogEx(NORMAL, "Trailer decoded:"); + int bln = mfFirstBlockOfSector(sectorNo); + int blinc = (mfNumBlocksPerSector(sectorNo) > 4) ? 5 : 1; + for (i = 0; i < 4; i++) { + PrintAndLogEx(NORMAL, "Access block %d%s: %s", bln, ((blinc > 1) && (i < 3) ? "+" : "") , mfGetAccessConditionsDesc(i, &(data + (sectorNo<32?3:15) * 16)[6])); + bln += blinc; + } + PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&(data + (sectorNo<32?3:15) * 16)[9], 1)); } } else { PrintAndLogEx(WARNING, "Command execute timeout"); From 16bfd49b8d4bcfe33c8e9fae7636ef34c52acc36 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 10 Dec 2018 08:48:39 +0100 Subject: [PATCH 0304/1938] CHG: 'hf 14a' - update to vendors list. (thanks to @horrordash for pointing it out) See also: http://isotc.iso.org/livelink/livelink?func=ll&objId=10432471&objAction=Open&nexturl=%2Flivelink%2Flivelink%3Ffunc%3Dll%26objId%3D8915579%26objAction%3Dbrowse%26viewType%3D1 --- client/cmdhf14a.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 42a941ffa..b9d7bfcae 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -85,7 +85,49 @@ static const manufactureName manufactureMapping[] = { { 0x42, "3Alogics Inc Korea" }, { 0x43, "Top TroniQ Asia Limited Hong Kong" }, { 0x44, "Gentag Inc. USA" }, - { 0x56, "Sensible Object. UK" }, + { 0x45, "Invengo Information Technology Co.Ltd China" }, + { 0x46, "Guangzhou Sysur Microelectronics, Inc China" }, + { 0x47, "CEITEC S.A. Brazil" }, + { 0x48, "Shanghai Quanray Electronics Co. Ltd. China" }, + { 0x49, "MediaTek Inc Taiwan" }, + { 0x4A, "Angstrem PJSC Russia" }, + { 0x4B, "Celisic Semiconductor (Hong Kong) Limited China" }, + { 0x4C, "LEGIC Identsystems AG Switzerland" }, + { 0x4D, "Balluff GmbH Germany" }, + { 0x4E, "Oberthur Technologies France" }, + { 0x4F, "Silterra Malaysia Sdn. Bhd. Malaysia" }, + { 0x50, "DELTA Danish Electronics, Light & Acoustics Denmark" }, + { 0x51, "Giesecke & Devrient GmbH Germany" }, + { 0x52, "Shenzhen China Vision Microelectronics Co., Ltd. China" }, + { 0x53, "Shanghai Feiju Microelectronics Co. Ltd. China" }, + { 0x54, "Intel Corporation USA" }, + { 0x55, "Microsensys GmbH Germany" }, + { 0x56, "Sonix Technology Co., Ltd. Taiwan" }, + { 0x57, "Qualcomm Technologies Inc USA" }, + { 0x58, "Realtek Semiconductor Corp Taiwan" }, + { 0x59, "Freevision Technologies Co. Ltd China" }, + { 0x5A, "Giantec Semiconductor Inc. China" }, + { 0x5B, "JSC Angstrem-T Russia" }, + { 0x5C, "STARCHIP France" }, + { 0x5D, "SPIRTECH France" }, + { 0x5E, "GANTNER Electronic GmbH Austria" }, + { 0x5F, "Nordic Semiconductor Norway" }, + { 0x60, "Verisiti Inc USA" }, + { 0x61, "Wearlinks Technology Inc. China" }, + { 0x62, "Userstar Information Systems Co., Ltd Taiwan" }, + { 0x63, "Pragmatic Printing Ltd. UK" }, + { 0x64, "Associacao do Laboratorio de Sistemas Integraveis Tecnologico – LSI-TEC Brazil" }, + { 0x65, "Tendyron Corporation China" }, + { 0x66, "MUTO Smart Co., Ltd. Korea" }, + { 0x67, "ON Semiconductor USA" }, + { 0x68, "TUBITAK BILGEM Turkey" }, + { 0x69, "Huada Semiconductor Co., Ltd China" }, + { 0x6A, "SEVENEY France" }, + { 0x6B, "ISSM France" }, + { 0x6C, "Wisesec Ltd Israel" }, + { 0x7C, "DB HiTek Co Ltd Korea" }, + { 0x7D, "SATO Vicinity Australia" }, + { 0x7E, "Holtek Taiwan" }, { 0x00, "no tag-info available" } // must be the last entry }; From ec17cade36ddd77edfa10b7b3869802843f33ab8 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 10 Dec 2018 15:01:00 +0200 Subject: [PATCH 0305/1938] added TA1 decoding --- client/cmdsmartcard.c | 115 +++++++++++++++++++++++++++++++++++++++--- client/cmdsmartcard.h | 3 +- 2 files changed, 110 insertions(+), 8 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 06846b824..e05fe2279 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -72,6 +72,91 @@ int usage_sm_brute(void) { return 0; } +uint8_t GetATRTA1(uint8_t *atr, size_t atrlen) { + if (atrlen > 2) { + uint8_t T0 = atr[1]; + if (T0 & 0x10) + return atr[2]; + } + + return 0x11; // default value is 0x11, corresponding to fmax=5 MHz, Fi=372, Di=1. +} + +int DiArray[] = { + 0, // b0000 RFU + 1, // b0001 + 2, + 4, + 8, + 16, + 32, // b0110 + 64, // b0111. This was RFU in ISO/IEC 7816-3:1997 and former. Some card readers or drivers may erroneously reject cards using this value + 12, + 20, + 0, // b1010 RFU + 0, + 0, // ... + 0, + 0, + 0 // b1111 RFU +}; + +int FiArray[] = { + 372, // b0000 Historical note: in ISO/IEC 7816-3:1989, this was assigned to cards with internal clock + 372, // b0001 + 558, // b0010 + 744, // b0011 + 1116, // b0100 + 1488, // b0101 + 1860, // b0110 + 0, // b0111 RFU + 0, // b1000 RFU + 512, // b1001 + 768, // b1010 + 1024, // b1011 + 1536, // b1100 + 2048, // b1101 + 0, // b1110 RFU + 0 // b1111 RFU +}; + +float FArray[] = { + 4, // b0000 Historical note: in ISO/IEC 7816-3:1989, this was assigned to cards with internal clock + 5, // b0001 + 6, // b0010 + 8, // b0011 + 12, // b0100 + 16, // b0101 + 20, // b0110 + 0, // b0111 RFU + 0, // b1000 RFU + 5, // b1001 + 7.5, // b1010 + 10, // b1011 + 15, // b1100 + 20, // b1101 + 0, // b1110 RFU + 0 // b1111 RFU +}; + +int GetATRDi(uint8_t *atr, size_t atrlen) { + uint8_t TA1 = GetATRTA1(atr, atrlen); + + return DiArray[TA1 & 0x0f]; // The 4 low-order bits of TA1 (4th MSbit to 1st LSbit) encode Di +} + +int GetATRFi(uint8_t *atr, size_t atrlen) { + uint8_t TA1 = GetATRTA1(atr, atrlen); + + return FiArray[TA1 >> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi +} + +float GetATRF(uint8_t *atr, size_t atrlen) { + uint8_t TA1 = GetATRTA1(atr, atrlen); + + return FArray[TA1 >> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi +} + static int PrintATR(uint8_t *atr, size_t atrlen) { uint8_t vxor = 0; for (int i = 1; i < atrlen; i++) @@ -106,8 +191,8 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { T1len++; } if (T0 & 0x80) { - PrintAndLog("TD1 (First offered transmission protocol, presence of TA2..TD2): 0x%02x", atr[2 + T1len]); TD1 = atr[2 + T1len]; + PrintAndLog("TD1 (First offered transmission protocol, presence of TA2..TD2): 0x%02x. Protocol T=%d", TD1, TD1 & 0x0f); T1len++; if (TD1 & 0x10) { @@ -123,8 +208,8 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { TD1len++; } if (TD1 & 0x80) { - PrintAndLog("TD2 (A supported protocol or more global parameters, presence of TA3..TD3): 0x%02x", atr[2 + T1len + TD1len]); uint8_t TDi = atr[2 + T1len + TD1len]; + PrintAndLog("TD2 (A supported protocol or more global parameters, presence of TA3..TD3): 0x%02x. Protocol T=%d", TDi, TDi & 0x0f); TD1len++; bool nextCycle = true; @@ -144,8 +229,8 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { TDilen++; } if (TDi & 0x80) { - PrintAndLog("TD%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); TDi = atr[2 + T1len + TD1len + TDilen]; + PrintAndLog("TD%d: 0x%02x. Protocol T=%d", vi, TDi, TDi & 0x0f); TDilen++; nextCycle = true; @@ -165,8 +250,10 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { PrintAndLog("Historical bytes len: 0x%02x", K); if (K > 0) PrintAndLog("The format of historical bytes: %02x", atr[2 + T1len + TD1len + TDilen]); - if (K > 1) - PrintAndLog("Historical bytes: %s", sprint_hex(&atr[2 + T1len + TD1len + TDilen], K)); + if (K > 1) { + PrintAndLog("Historical bytes:"); + dump_buffer(&atr[2 + T1len + TD1len + TDilen], K, NULL, 1); + } return 0; } @@ -575,9 +662,23 @@ int CmdSmartInfo(const char *Cmd){ PrintAndLogEx(INFO, "ISO76183 ATR : %s", sprint_hex(card.atr, card.atr_len)); PrintAndLogEx(INFO, "look up ATR"); PrintAndLogEx(INFO, "http://smartcard-atr.appspot.com/parse?ATR=%s", sprint_hex_inrow(card.atr, card.atr_len) ); - PrintAndLogEx(INFO, ""); - PrintAndLogEx(INFO, "ATR:"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "* ATR:"); PrintATR(card.atr, card.atr_len); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "* D/F (TA1):"); + int Di = GetATRDi(card.atr, card.atr_len); + int Fi = GetATRFi(card.atr, card.atr_len); + float F = GetATRF(card.atr, card.atr_len); + if (GetATRTA1(card.atr, card.atr_len) == 0x11) + PrintAndLogEx(INFO, "Using default values..."); + PrintAndLogEx(NORMAL, "Di=%d", Di); + PrintAndLogEx(NORMAL, "Fi=%d", Fi); + PrintAndLogEx(NORMAL, "F=%.1f MHz", F); + PrintAndLogEx(NORMAL, "Cycles/ETU=%d", Fi/Di); + PrintAndLogEx(NORMAL, "%.1f bits/sec at 4MHz", (float)4000000 / (Fi/Di)); + PrintAndLogEx(NORMAL, "%.1f bits/sec at Fmax=%.1fMHz", (F * 1000000) / (Fi/Di), F); + return 0; } diff --git a/client/cmdsmartcard.h b/client/cmdsmartcard.h index 8cc0ae851..cffaeff98 100644 --- a/client/cmdsmartcard.h +++ b/client/cmdsmartcard.h @@ -21,9 +21,10 @@ #include "common.h" #include "util.h" #include "loclass/fileutils.h" // saveFile -#include "comms.h" // getfromdevice +#include "comms.h" // getfromdevice #include "emv/emvcore.h" // decodeTVL #include "emv/apduinfo.h" // APDUcode description +#include "emv/dump.h" // dump_buffer extern int CmdSmartcard(const char *Cmd); From b06054732bce7e64ac7623d8a58eed393468e15c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 10 Dec 2018 15:04:03 +0200 Subject: [PATCH 0306/1938] code format --- client/cmdsmartcard.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index e05fe2279..d97451e47 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -662,9 +662,13 @@ int CmdSmartInfo(const char *Cmd){ PrintAndLogEx(INFO, "ISO76183 ATR : %s", sprint_hex(card.atr, card.atr_len)); PrintAndLogEx(INFO, "look up ATR"); PrintAndLogEx(INFO, "http://smartcard-atr.appspot.com/parse?ATR=%s", sprint_hex_inrow(card.atr, card.atr_len) ); + + // print ATR PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "* ATR:"); PrintATR(card.atr, card.atr_len); + + // print D/F (brom byte TA1 or defaults) PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "* D/F (TA1):"); int Di = GetATRDi(card.atr, card.atr_len); @@ -672,6 +676,7 @@ int CmdSmartInfo(const char *Cmd){ float F = GetATRF(card.atr, card.atr_len); if (GetATRTA1(card.atr, card.atr_len) == 0x11) PrintAndLogEx(INFO, "Using default values..."); + PrintAndLogEx(NORMAL, "Di=%d", Di); PrintAndLogEx(NORMAL, "Fi=%d", Fi); PrintAndLogEx(NORMAL, "F=%.1f MHz", F); From 1ffddb2578751af93d49cf3e24952689e7526989 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 13 Dec 2018 23:34:30 +0100 Subject: [PATCH 0307/1938] CHG: 'hf mfu dump' - simplify bin saving and added JSON dump format --- client/cmdhfmfu.c | 42 ++++++++++++------------------- client/cmdhfmfu.h | 3 +++ client/loclass/fileutils.c | 51 ++++++++++++++++++++++++++++++++++++++ client/loclass/fileutils.h | 2 ++ 4 files changed, 72 insertions(+), 26 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 327069971..b5be04593 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -1553,7 +1553,6 @@ int usage_hf_mfu_pwdgen(void){ return 0; } -#define DUMP_PREFIX_LENGTH 48 void printMFUdump(mfu_dump_t* card) { printMFUdumpEx(card, 255, 0); } @@ -1659,9 +1658,9 @@ void printMFUdumpEx(mfu_dump_t* card, uint16_t pages, uint8_t startpage) { // Read and Dump Card Contents, using auto detection of tag size. int CmdHF14AMfUDump(const char *Cmd){ - FILE *fout; + uint8_t fileNameLen = 0; char filename[FILE_PATH_SIZE] = {0x00}; - char *fnameptr = filename; + char *fptr = filename; uint8_t data[1024] = {0x00}; memset(data, 0x00, sizeof(data)); @@ -1674,7 +1673,7 @@ int CmdHF14AMfUDump(const char *Cmd){ uint8_t authenticationkey[16] = {0x00}; memset(authenticationkey, 0x00, sizeof(authenticationkey)); uint8_t *authKeyPtr = authenticationkey; - size_t fileNlen = 0; + bool errors = false; bool swapEndian = false; bool manualPages = false; @@ -1703,9 +1702,7 @@ int CmdHF14AMfUDump(const char *Cmd){ cmdp++; break; case 'f': - fileNlen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); - if (!fileNlen) errors = true; - if (fileNlen > FILE_PATH_SIZE-5) fileNlen = FILE_PATH_SIZE-5; + fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); cmdp += 2; break; case 'p': //set start page @@ -1785,9 +1782,9 @@ int CmdHF14AMfUDump(const char *Cmd){ pages = bufferSize/4; - uint8_t get_pack[] = {0,0}; iso14a_card_select_t card; mfu_dump_t dump_file_data; + uint8_t get_pack[] = {0,0}; uint8_t get_version[] = {0,0,0,0,0,0,0,0}; uint8_t get_tearing[] = {0,0,0}; uint8_t get_counter[] = {0,0,0}; @@ -1801,8 +1798,8 @@ int CmdHF14AMfUDump(const char *Cmd){ //attempt to read pack if (!ul_auth_select( &card, tagtype, true, authKeyPtr, get_pack, sizeof(get_pack))) { //reset pack - get_pack[0]=0; - get_pack[1]=0; + get_pack[0] = 0; + get_pack[1] = 0; } DropField(); @@ -1864,23 +1861,16 @@ int CmdHF14AMfUDump(const char *Cmd){ printMFUdumpEx(&dump_file_data, pages, startPage); // user supplied filename? - if (fileNlen < 1) { - // UID = data 0-1-2 4-5-6-7 (skips a beat) - sprintf(fnameptr,"%02X%02X%02X%02X%02X%02X%02X.bin", - data[0],data[1], data[2], data[4],data[5],data[6], data[7]); - } else { - sprintf(fnameptr + fileNlen,".bin"); - } + if (fileNameLen < 1) { - if ((fout = fopen(filename,"wb")) == NULL) { - PrintAndLogEx(WARNING, "Could not create file name %s", filename); - return 1; - } - fwrite( &dump_file_data, 1, pages*4 + DUMP_PREFIX_LENGTH, fout ); - if (fout) - fclose(fout); - - PrintAndLogEx(SUCCESS, "Dumped %d pages, wrote %d bytes to %s", pages + (DUMP_PREFIX_LENGTH/4), pages*4 + DUMP_PREFIX_LENGTH, filename); + PrintAndLogEx(INFO, "Using UID as filename"); + + fptr += sprintf(fptr, "hf-mfu-"); + FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen); + } + uint16_t datalen = pages*4 + DUMP_PREFIX_LENGTH; + saveFile(filename, "bin", (uint8_t*)&dump_file_data, datalen); + saveFileJSON(filename, "json", jsfMfuMemory, (uint8_t*)&dump_file_data, datalen); if ( is_partial ) PrintAndLogEx(WARNING, "Partial dump created. (%d of %d blocks)", pages, card_mem_size); diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index 491218b1b..b03444839 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -10,6 +10,9 @@ #include "util.h" #include "protocols.h" #include "comms.h" +#include "loclass/fileutils.h" + +#define DUMP_PREFIX_LENGTH 48 typedef struct { uint8_t version[8]; diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 367b19c97..b099d6a35 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -208,6 +208,34 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty } } break; + case jsfMfuMemory: + JsonSaveStr(root, "FileType", "mfu"); + + mfu_dump_t* tmp = (mfu_dump_t*)data; + + uint8_t uid[7] = {0}; + memcpy(uid, tmp->data, 3); + memcpy(uid+3, tmp->data+4, 4); + + JsonSaveBufAsHexCompact(root, "$.Card.UID", uid, sizeof(uid)); + JsonSaveBufAsHexCompact(root, "$.Card.Version", tmp->version, sizeof(tmp->version)); + JsonSaveBufAsHexCompact(root, "$.Card.TBO_0", tmp->tbo, sizeof(tmp->tbo)); + JsonSaveBufAsHexCompact(root, "$.Card.Tearing", tmp->tearing, sizeof(tmp->tearing)); + JsonSaveBufAsHexCompact(root, "$.Card.Pack", tmp->pack, sizeof(tmp->pack)); + JsonSaveBufAsHexCompact(root, "$.Card.TBO_1", tmp->tbo1, sizeof(tmp->tbo1)); + JsonSaveBufAsHexCompact(root, "$.Card.Signature", tmp->signature, sizeof(tmp->signature)); + JsonSaveStr(root, "$.Card.Counter", "N/A"); + + // size of header 48b + size_t len = (datalen - DUMP_PREFIX_LENGTH) / 4; + + for (int i = 0; i < len; i++) { + + char path[PATH_MAX_LENGTH] = {0}; + sprintf(path, "$.blocks.%d", i); + JsonSaveBufAsHexCompact(root, path, tmp->data + (i * 4), 4); + } + break; } int res = json_dump_file(root, fileName, JSON_INDENT(2)); @@ -395,6 +423,29 @@ int loadFileJSON(const char *preferredName, const char *suffix, void* data, size *datalen = sptr; } + if (!strcmp(ctype, "mfu")) { + size_t sptr = 0; + for (int i = 0; i < 256; i++) { + if (sptr + 4 > maxdatalen) { + retval = 5; + goto out; + } + + char path[30] = {0}; + sprintf(path, "$.blocks.%d", i); + + size_t len = 0; + JsonLoadBufAsHex(root, path, &udata[sptr], 4, &len); + if (!len) + break; + + sptr += len; + } + + *datalen = sptr; + } + + PrintAndLog("Loaded JSON: (%s) OK.", fileName); out: json_decref(root); diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index 3852b4bf4..b73f5fc30 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -49,10 +49,12 @@ #include "../ui.h" #include "../emv/emvjson.h" #include "mifare4.h" +#include "cmdhfmfu.h" typedef enum { jsfRaw, jsfCardMemory, + jsfMfuMemory, } JSONFileType; int fileExists(const char *filename); From edcb029af3cdf486faac82653a0abde53dc25d4a Mon Sep 17 00:00:00 2001 From: mazodude Date: Fri, 14 Dec 2018 15:31:50 +1000 Subject: [PATCH 0308/1938] Add script to test for MADs --- client/scripts/mifare_ad.lua | 186 +++++++++++++++++++++++++++++++++++ 1 file changed, 186 insertions(+) create mode 100644 client/scripts/mifare_ad.lua diff --git a/client/scripts/mifare_ad.lua b/client/scripts/mifare_ad.lua new file mode 100644 index 000000000..0f9c8219d --- /dev/null +++ b/client/scripts/mifare_ad.lua @@ -0,0 +1,186 @@ + +-- Ability to read what card is there +local getopt = require('getopt') +local cmds = require('commands') +local taglib = require('taglib') + +local desc = +[[This script will automatically check Mifare cards for MADs +(Mifare Application Directory) + +Arguments: + -d debug logging on + -h this help + +]] +local example = "script run xxx" +local author = "Mazodude" +--- +-- PrintAndLog +function prlog(...) + print(...) +end +--- +-- This is only meant to be used when errors occur +function oops(err) + prlog("ERROR: ",err) + return nil,err +end + +--- +-- Usage help +function help() + prlog(desc) + prlog("Example usage") + prlog(example) +end + +function debug(...) + if DEBUG then + prlog("debug:", ...) + end +end + + +local function show(data) + if DEBUG then + local formatString = ("H%d"):format(string.len(data)) + local _,hexdata = bin.unpack(formatString, data) + debug("Hexdata" , hexdata) + end +end +--- Fire up a connection with a tag, return uid +-- @return UID if successfull +-- @return nil, errormessage if unsuccessfull +local function open() + debug("Opening connection") + core.clearCommandBuffer() + local x = string.format("hf 14a raw -r -p -s") + debug(x) + core.console(x) + debug("done") + data, err = waitCmd(true) + if err then return oops(err) end + show(data) + local formatString = ("H%d"):format(string.len(data)) + local _,uid = bin.unpack(formatString, data) + return uid +end +--- Shut down tag communication +-- return no return values +local function close() + debug("Closing connection") + core.clearCommandBuffer() + local x = string.format("hf 14a raw -r") + debug(x) + core.console(x) + debug("done") + --data, err = waitCmd(true) + --data, err = waitCmd(false) + +end + + +-- waits for answer from pm3 device +local function checkCommand(command) + core.clearCommandBuffer() + local usb = command:getBytes() + core.SendCommand(usb) + local result = core.WaitForResponseTimeout(cmds.CMD_ACK, 1500) + + if result then + local count, cmd, arg0 = bin.unpack('LL',result) + if(arg0==1) then + local count, arg1, arg2, data = bin.unpack('LLH511',result,count) + block = data:sub(33,64) + return block + else + return nil + end + else + print("Timeout while waiting for response. Increase TIMEOUT in mifare_ad.lua to wait longer") + return nil, "Timeout while waiting for device to respond" + end +end + +---_ Gets data from a block +-- @return block if successfull +-- @return nil, errormessage if unsuccessfull +local function getBlock(block) + local data, err + + core.clearCommandBuffer() + + -- // params + -- uint8_t sectorNo = arg0; + -- uint8_t keyType = arg1; + -- uint64_t ui64Key = 0; + -- ui64Key = bytes_to_num(datain, 6); + local sectorNo = 0 + local keyType = 0 + local key = "A0A1A2A3A4A5"; + debug(("Testing to auth with key %s"):format(key)) + -- prlog(key); + local command = Command:new{cmd = cmds.CMD_MIFARE_READSC, + arg1 = sectorNo, + arg2 = keyType, + arg3 = 0, + data = key} + local data = checkCommand(command) + -- debug(command) + -- prlog(data) + if (data == nil) then return err, ("Could not auth with card - this tag does not have MADs") end + if string.len(data) < 32 then + return nil, ("Expected at least 32 bytes, got %d - this tag does not have MADs"):format(string.len(data)) + end + -- -- Now, parse out the block data + b0 = string.sub(data,3,4) + return b0 +end + + +--- This function is a lua-implementation of +-- cmdhf14a.c:waitCmd(uint8_t iSelect) +function waitCmd(iSelect) + local response = core.WaitForResponseTimeout(cmds.CMD_ACK,1000) + if response then + local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response) + local iLen = arg0 + if iSelect then iLen = arg1 end + debug(("Received %i octets (arg0:%d, arg1:%d)"):format(iLen, arg0, arg1)) + if iLen == 0 then return nil, "No response from tag" end + local recv = string.sub(response,count, iLen+count-1) + return recv + end + return nil, "No response from device" +end + + + +local function main( args) + debug("script started") + local err, data, data2,k,v,i + -- Read the parameters + for o, a in getopt.getopt(args, 'hd') do + if o == "h" then help() return end + if o == "d" then DEBUG = true end + end + + local uid = open() + if (uid==nil) then oops("No card present") return end + print(("UID: %s"):format(uid)) + + -- First, get block 1 byte 1 + local block, err = getBlock(0) + if err then return oops(err) end + debug(("Checking block 0 sector 1 byte 1")) + debug(("Got byte: %s"):format(block)) + -- prlog(block) + if block == "0F" then + print('Card has MADs v1') + end + + -- Deactivate field + close() +end +main(args) \ No newline at end of file From f77bb94a860e5dfb2a597e3e54e55baf5ed0dce9 Mon Sep 17 00:00:00 2001 From: mazodude Date: Fri, 14 Dec 2018 16:57:51 +1000 Subject: [PATCH 0309/1938] Add changes to script as per iceman's suggestions --- client/scripts/mifare_ad.lua | 55 ++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 28 deletions(-) diff --git a/client/scripts/mifare_ad.lua b/client/scripts/mifare_ad.lua index 0f9c8219d..7b8321eef 100644 --- a/client/scripts/mifare_ad.lua +++ b/client/scripts/mifare_ad.lua @@ -3,6 +3,7 @@ local getopt = require('getopt') local cmds = require('commands') local taglib = require('taglib') +local lib14a = require('read14a') local desc = [[This script will automatically check Mifare cards for MADs @@ -15,29 +16,24 @@ Arguments: ]] local example = "script run xxx" local author = "Mazodude" ---- --- PrintAndLog -function prlog(...) - print(...) -end --- -- This is only meant to be used when errors occur -function oops(err) - prlog("ERROR: ",err) +local function oops(err) + print("ERROR: ",err) return nil,err end --- -- Usage help -function help() - prlog(desc) - prlog("Example usage") - prlog(example) +local function help() + print(desc) + print("Example usage") + print(example) end -function debug(...) +local function debug(...) if DEBUG then - prlog("debug:", ...) + print("debug:", ...) end end @@ -53,18 +49,21 @@ end -- @return UID if successfull -- @return nil, errormessage if unsuccessfull local function open() - debug("Opening connection") + -- debug("Opening connection") + -- core.clearCommandBuffer() + -- local x = string.format("hf 14a raw -r -p -s") + -- debug(x) + -- core.console(x) + -- debug("done") + -- data, err = waitCmd(true) + -- if err then return oops(err) end + -- show(data) + -- local formatString = ("H%d"):format(string.len(data)) + -- local _,uid = bin.unpack(formatString, data) + tag, err = lib14a.read(false, true) + if not tag then return oops(err) end core.clearCommandBuffer() - local x = string.format("hf 14a raw -r -p -s") - debug(x) - core.console(x) - debug("done") - data, err = waitCmd(true) - if err then return oops(err) end - show(data) - local formatString = ("H%d"):format(string.len(data)) - local _,uid = bin.unpack(formatString, data) - return uid + return tag end --- Shut down tag communication -- return no return values @@ -120,7 +119,7 @@ local function getBlock(block) local keyType = 0 local key = "A0A1A2A3A4A5"; debug(("Testing to auth with key %s"):format(key)) - -- prlog(key); + -- print(key); local command = Command:new{cmd = cmds.CMD_MIFARE_READSC, arg1 = sectorNo, arg2 = keyType, @@ -128,7 +127,7 @@ local function getBlock(block) data = key} local data = checkCommand(command) -- debug(command) - -- prlog(data) + -- print(data) if (data == nil) then return err, ("Could not auth with card - this tag does not have MADs") end if string.len(data) < 32 then return nil, ("Expected at least 32 bytes, got %d - this tag does not have MADs"):format(string.len(data)) @@ -141,7 +140,7 @@ end --- This function is a lua-implementation of -- cmdhf14a.c:waitCmd(uint8_t iSelect) -function waitCmd(iSelect) +local function waitCmd(iSelect) local response = core.WaitForResponseTimeout(cmds.CMD_ACK,1000) if response then local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response) @@ -168,7 +167,7 @@ local function main( args) local uid = open() if (uid==nil) then oops("No card present") return end - print(("UID: %s"):format(uid)) + print(("UID: %s"):format(uid.uid)) -- First, get block 1 byte 1 local block, err = getBlock(0) From d36f3d876b30966a24aab79ab999fd63e1ffe3aa Mon Sep 17 00:00:00 2001 From: mazodude Date: Fri, 14 Dec 2018 20:14:47 +1000 Subject: [PATCH 0310/1938] Remove unneeded function and place code in main --- client/scripts/mifare_ad.lua | 28 +++++----------------------- 1 file changed, 5 insertions(+), 23 deletions(-) diff --git a/client/scripts/mifare_ad.lua b/client/scripts/mifare_ad.lua index 7b8321eef..386589068 100644 --- a/client/scripts/mifare_ad.lua +++ b/client/scripts/mifare_ad.lua @@ -45,26 +45,6 @@ local function show(data) debug("Hexdata" , hexdata) end end ---- Fire up a connection with a tag, return uid --- @return UID if successfull --- @return nil, errormessage if unsuccessfull -local function open() - -- debug("Opening connection") - -- core.clearCommandBuffer() - -- local x = string.format("hf 14a raw -r -p -s") - -- debug(x) - -- core.console(x) - -- debug("done") - -- data, err = waitCmd(true) - -- if err then return oops(err) end - -- show(data) - -- local formatString = ("H%d"):format(string.len(data)) - -- local _,uid = bin.unpack(formatString, data) - tag, err = lib14a.read(false, true) - if not tag then return oops(err) end - core.clearCommandBuffer() - return tag -end --- Shut down tag communication -- return no return values local function close() @@ -165,9 +145,11 @@ local function main( args) if o == "d" then DEBUG = true end end - local uid = open() - if (uid==nil) then oops("No card present") return end - print(("UID: %s"):format(uid.uid)) + local tag, err = lib14a.read(false, true) + if not tag then return oops(err) end + core.clearCommandBuffer() + if (tag==nil) then oops("No card present") return end + print(("UID: %s"):format(tag.uid)) -- First, get block 1 byte 1 local block, err = getBlock(0) From cecf709fe7aa75a7b69bad8538d1bce322383ffb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 14 Dec 2018 20:27:11 +0100 Subject: [PATCH 0311/1938] chg: 'script run mifare_ad' - minor fix --- client/scripts/mifare_ad.lua | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/scripts/mifare_ad.lua b/client/scripts/mifare_ad.lua index 386589068..385e34338 100644 --- a/client/scripts/mifare_ad.lua +++ b/client/scripts/mifare_ad.lua @@ -146,9 +146,8 @@ local function main( args) end local tag, err = lib14a.read(false, true) - if not tag then return oops(err) end + if not tag then return oops("No card present") end core.clearCommandBuffer() - if (tag==nil) then oops("No card present") return end print(("UID: %s"):format(tag.uid)) -- First, get block 1 byte 1 @@ -160,6 +159,7 @@ local function main( args) if block == "0F" then print('Card has MADs v1') end + --(iceman) Should be able to detect MAD v2 aswell.. -- Deactivate field close() From a963a7834cf9aa6878cad79a3c448c55f03e4965 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 17 Dec 2018 14:01:18 +0100 Subject: [PATCH 0312/1938] FIX: 'mem load' - bad memory allocation CHG: calloc fixes --- client/cmdflashmem.c | 6 ++++-- client/cmdhfmf.c | 4 ++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index 1dd3084d9..2ff68bd3d 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -182,9 +182,9 @@ int CmdFlashMemLoad(const char *Cmd){ //Validations if (errors || cmdp == 0 ) return usage_flashmem_load(); - uint8_t *data = NULL; + uint8_t *data = calloc(FLASH_MEM_MAX_SIZE, sizeof(uint8_t)); size_t datalen = 0; - int res = loadFile(filename, "bin", &data, &datalen); + int res = loadFile(filename, "bin", data, &datalen); //int res = loadFileEML( filename, "eml", data, &datalen); if ( res ) { free(data); @@ -196,6 +196,8 @@ int CmdFlashMemLoad(const char *Cmd){ free(data); return 1; } + + data = realloc(data, datalen); //Send to device uint32_t bytes_sent = 0; diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index d46344451..1bfbf10eb 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2414,7 +2414,7 @@ int CmdHF14AMfELoad(const char *Cmd) { param_getstr(Cmd, nameParamNo, filename, sizeof(filename)); - uint8_t *data = calloc(1, 4096); + uint8_t *data = calloc(4096, sizeof(uint8_t)); size_t datalen = 0; //int res = loadFile(filename, "bin", data, &datalen); int res = loadFileEML( filename, "eml", data, &datalen); @@ -2693,7 +2693,7 @@ int CmdHF14AMfCLoad(const char *Cmd) { } size_t maxdatalen = 4096; - uint8_t *data = calloc(1, maxdatalen); + uint8_t *data = calloc(maxdatalen, sizeof(uint8_t)); size_t datalen = 0; int res = 0; if (fillFromBin) { From 1941b9ca8b3d1373ed6283d9b3d6ce8f3e03674f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 17 Dec 2018 23:48:05 +0200 Subject: [PATCH 0313/1938] sdd sc raw t0 --- include/mifare.h | 1 + 1 file changed, 1 insertion(+) diff --git a/include/mifare.h b/include/mifare.h index 63cdf0fb6..6f87a0e6d 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -110,6 +110,7 @@ typedef enum SMARTCARD_COMMAND { SC_NO_DISCONNECT = (1 << 1), SC_RAW = (1 << 2), SC_SELECT = (1 << 3) + SC_RAW_T0 = (1 << 4), } smartcard_command_t; //----------------------------------------------------------------------------- From 85729d55e7e356ca20504707bca7c479cdec22ab Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 17 Dec 2018 23:48:30 +0200 Subject: [PATCH 0314/1938] added arm side --- common/i2c.c | 4 ++-- common/i2c.h | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/common/i2c.c b/common/i2c.c index ecf5a5bd9..ea830a1bd 100644 --- a/common/i2c.c +++ b/common/i2c.c @@ -698,14 +698,14 @@ void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) { } } - if ((flags & SC_RAW)) { + if ((flags & SC_RAW) || (flags & SC_RAW_T0)) { LogTrace(data, arg1, 0, 0, NULL, true); // Send raw bytes // asBytes = A0 A4 00 00 02 // arg1 = len 5 - bool res = I2C_BufferWrite(data, arg1, I2C_DEVICE_CMD_SEND, I2C_DEVICE_ADDRESS_MAIN); + bool res = I2C_BufferWrite(data, arg1, ((flags & SC_RAW_T0) ? I2C_DEVICE_CMD_SEND_T0 : I2C_DEVICE_CMD_SEND), I2C_DEVICE_ADDRESS_MAIN); if ( !res && MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); // read bytes from module diff --git a/common/i2c.h b/common/i2c.h index 8350029bd..e5ff26e4d 100644 --- a/common/i2c.h +++ b/common/i2c.h @@ -17,6 +17,7 @@ #define I2C_DEVICE_CMD_SETBAUD 0x04 #define I2C_DEVICE_CMD_SIM_CLC 0x05 #define I2C_DEVICE_CMD_GETVERSION 0x06 +#define I2C_DEVICE_CMD_SEND_T0 0x07 void I2C_recovery(void); From a759e94af0ca06dd64700c0ae5d19861d26b4896 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 17 Dec 2018 23:48:56 +0200 Subject: [PATCH 0315/1938] add client side and get rid of reset --- client/cmdsmartcard.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index d97451e47..e09ca5b48 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -473,9 +473,9 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave smart_select(false); printf("* APDU SC\n"); - UsbCommand c = {CMD_SMART_RAW, {SC_RAW | SC_CONNECT, datainlen, 0}}; + UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, datainlen, 0}}; if (activateCard) { - c.arg[0] |= SC_SELECT; + c.arg[0] |= SC_SELECT | SC_CONNECT; } memcpy(c.d.asBytes, datain, datainlen); clearCommandBuffer(); @@ -489,7 +489,7 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave // retry if (len > 1 && dataout[len - 2] == 0x6c && datainlen > 4) { - UsbCommand c2 = {CMD_SMART_RAW, {SC_RAW, datainlen, 0}}; + UsbCommand c2 = {CMD_SMART_RAW, {SC_RAW_T0, datainlen, 0}}; memcpy(c2.d.asBytes, datain, datainlen); int vlen = 5 + datain[4]; From f32088e25cfa67a4bfe74a6285b84a4bca09e226 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 18 Dec 2018 14:33:28 +0200 Subject: [PATCH 0316/1938] fix states and get rid of INS code in receive (that code checks by controller) --- client/cmdsmartcard.c | 48 +++++++++++++++++++++---------------------- include/mifare.h | 2 +- 2 files changed, 24 insertions(+), 26 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index e09ca5b48..0d4e7a46d 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -306,7 +306,7 @@ static int smart_wait(uint8_t *data) { return len; } -static int smart_response(uint8_t apduINS, uint8_t *data) { +static int smart_response(uint8_t *data) { int datalen = smart_wait(data); bool needGetData = false; @@ -315,12 +315,6 @@ static int smart_response(uint8_t apduINS, uint8_t *data) { goto out; } - if (datalen > 2 && data[0] != apduINS) { - PrintAndLogEx(ERR, "Card ACK error. len=0x%x data[0]=%02x", datalen, data[0]); - datalen = 0; - goto out; - } - if ( data[datalen - 2] == 0x61 || data[datalen - 2] == 0x9F ) { needGetData = true; } @@ -339,22 +333,26 @@ static int smart_response(uint8_t apduINS, uint8_t *data) { if (datalen < 2 ) { goto out; } - - if (datalen > 2 && data[0] != ISO7816_GETSTATUS) { - PrintAndLogEx(ERR, "GetResponse ACK error. len=0x%x data[0]=%02x", len, data[0]); - datalen = 0; - goto out; - } - if (datalen != len + 2 + 1) { // 2 - response, 1 - ACK - PrintAndLogEx(WARNING, "GetResponse wrong length. Must be: 0x%02x but: 0x%02x", len, datalen - 3); + // data wo ACK + if (datalen != len + 2) { + // data with ACK + if (datalen == len + 2 + 1) { // 2 - response, 1 - ACK + if (data[0] != ISO7816_GETSTATUS) { + PrintAndLogEx(ERR, "GetResponse ACK error. len=0x%x data[0]=%02x", len, data[0]); + datalen = 0; + goto out; + } + + datalen--; + memmove(data, &data[1], datalen); + } else { + // wrong length + PrintAndLogEx(WARNING, "GetResponse wrong length. Must be: 0x%02x but: 0x%02x", len, datalen - 3); + } } } - if (datalen > 2) { - datalen--; - memmove(data, &data[1], datalen); - } out: return datalen; } @@ -441,7 +439,7 @@ int CmdSmartRaw(const char *Cmd) { if ( !buf ) return 1; - int len = smart_response(data[1], buf); + int len = smart_response(buf); if ( len < 0 ) { free(buf); return 2; @@ -453,7 +451,7 @@ int CmdSmartRaw(const char *Cmd) { memcpy(c.d.asBytes, data, sizeof(data) ); clearCommandBuffer(); SendCommand(&c); - len = smart_response(data[1], buf); + len = smart_response(buf); data[4] = 0; } @@ -481,7 +479,7 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave clearCommandBuffer(); SendCommand(&c); - int len = smart_response(datain[1], dataout); + int len = smart_response(dataout); if ( len < 0 ) { return 2; @@ -501,7 +499,7 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave clearCommandBuffer(); SendCommand(&c2); - len = smart_response(datain[1], dataout); + len = smart_response(dataout); } *dataoutlen = len; @@ -822,7 +820,7 @@ int CmdSmartBruteforceSFI(const char *Cmd) { clearCommandBuffer(); SendCommand(&c); - smart_response(data[1], buf); + smart_response(buf); // if 0x6C if ( buf[0] == 0x6C ) { @@ -831,7 +829,7 @@ int CmdSmartBruteforceSFI(const char *Cmd) { memcpy(c.d.asBytes, data, sizeof(data) ); clearCommandBuffer(); SendCommand(&c); - uint8_t len = smart_response(data[1], buf); + uint8_t len = smart_response(buf); // TLV decoder if (len > 4) diff --git a/include/mifare.h b/include/mifare.h index 6f87a0e6d..cda7cfe9d 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -109,7 +109,7 @@ typedef enum SMARTCARD_COMMAND { SC_CONNECT = (1 << 0), SC_NO_DISCONNECT = (1 << 1), SC_RAW = (1 << 2), - SC_SELECT = (1 << 3) + SC_SELECT = (1 << 3), SC_RAW_T0 = (1 << 4), } smartcard_command_t; From 8ab9b6d0ea74d7c83463448fc4e9b0c069130cab Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 18 Dec 2018 16:14:52 +0200 Subject: [PATCH 0317/1938] sw 0x6cxx works --- client/cmdsmartcard.c | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 0d4e7a46d..24803035c 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -488,13 +488,10 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave // retry if (len > 1 && dataout[len - 2] == 0x6c && datainlen > 4) { UsbCommand c2 = {CMD_SMART_RAW, {SC_RAW_T0, datainlen, 0}}; - memcpy(c2.d.asBytes, datain, datainlen); + memcpy(c2.d.asBytes, datain, 5); - int vlen = 5 + datain[4]; - if (datainlen == vlen) - datainlen++; - - c2.d.asBytes[vlen] = dataout[len - 1]; + // transfer length via T=0 + c2.d.asBytes[4] = dataout[len - 1]; clearCommandBuffer(); SendCommand(&c2); From b42709837fe3659ab3722a9c84bc48b8b5228977 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 18 Dec 2018 18:55:46 +0200 Subject: [PATCH 0318/1938] fix sending Le over 7816 T=0 --- client/cmdsmartcard.c | 2 +- client/emv/emvcore.c | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 24803035c..8408b03ce 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -322,7 +322,7 @@ static int smart_response(uint8_t *data) { if (needGetData) { int len = data[datalen - 1]; PrintAndLogEx(INFO, "Requesting response. len=0x%x", len); - uint8_t getstatus[] = {ISO7816_GETSTATUS, 0x00, 0x00, len}; + uint8_t getstatus[] = {0x00, ISO7816_GETSTATUS, 0x00, 0x00, len}; UsbCommand cStatus = {CMD_SMART_RAW, {SC_RAW, sizeof(getstatus), 0}}; memcpy(cStatus.d.asBytes, getstatus, sizeof(getstatus) ); clearCommandBuffer(); diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index fcf0bf81f..1b4808410 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -301,11 +301,11 @@ int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveField } int EMVExchange(EMVCommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { - return EMVExchangeEx(channel, false, LeaveFieldON, apdu, true, Result, MaxResultLen, ResultLen, sw, tlv); + return EMVExchangeEx(channel, false, LeaveFieldON, apdu, (channel == ECC_CONTACTLESS), Result, MaxResultLen, ResultLen, sw, tlv); } int EMVSelect(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { - return EMVExchangeEx(channel, ActivateField, LeaveFieldON, (sAPDU){0x00, 0xa4, 0x04, 0x00, AIDLen, AID}, true, Result, MaxResultLen, ResultLen, sw, tlv); + return EMVExchangeEx(channel, ActivateField, LeaveFieldON, (sAPDU){0x00, 0xa4, 0x04, 0x00, AIDLen, AID}, (channel == ECC_CONTACTLESS), Result, MaxResultLen, ResultLen, sw, tlv); } int EMVSelectPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { From 5489d4e55224fd5b05e840488b79553713002f3f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 18 Dec 2018 17:57:22 +0100 Subject: [PATCH 0319/1938] add: magic uid 15 helper script chg: keys --- client/default_keys.dic | 1 + client/scripts/iso15_magic.lua | 110 +++++++++++++++++++++++++++++++++ 2 files changed, 111 insertions(+) create mode 100644 client/scripts/iso15_magic.lua diff --git a/client/default_keys.dic b/client/default_keys.dic index e8f0743d1..f764596ce 100644 --- a/client/default_keys.dic +++ b/client/default_keys.dic @@ -708,3 +708,4 @@ E56AC127DD45, EA0FD73CB149, FC0001877BF7, FD8705E721B0, +00ada2cd516d, \ No newline at end of file diff --git a/client/scripts/iso15_magic.lua b/client/scripts/iso15_magic.lua new file mode 100644 index 000000000..36e8100a8 --- /dev/null +++ b/client/scripts/iso15_magic.lua @@ -0,0 +1,110 @@ +local cmds = require('commands') +local lib15 = require('read15') +local getopt = require('getopt') +local utils = require('utils') + +copyright = 'Copyright (c) 2018 IceSQL AB. All rights reserved.' +author = 'Christian Herrmann' +version = 'v1.0.3' +desc = [[ +This script tries to set UID on a IS15693 SLIX magic card +Remember the UID ->MUST<- start with 0xE0 + ]] +example = [[ + + -- ISO15693 slix magic tag + + script run iso15_magic -u E004013344556677 +]] +usage = [[ +script run iso15_magic -h -u + +Arguments: + -h : this help + -u : UID (16 hexsymbols) +]] + +local DEBUG = true +--- +-- A debug printout-function +local function dbg(args) + if not DEBUG then return end + if type(args) == "table" then + local i = 1 + while args[i] do + dbg(args[i]) + i = i+1 + end + else + print("###", args) + end +end +--- +-- This is only meant to be used when errors occur +local function oops(err) + print("ERROR: ",err) + return nil, err +end +--- +-- Usage help +local function help() + print(copyright) + print(author) + print(version) + print(desc) + print('Example usage') + print(example) +end +-- +--- Set UID on magic command enabled on a ICEMAN based REPO +local function magicUID_iceman(b0, b1) + print('Using backdoor Magic tag function') + core.console("hf 15 raw -2 -c 02213E00000000") + core.console("hf 15 raw -2 -c 02213F69960000") + core.console("hf 15 raw -2 -c 022138"..b1) + core.console("hf 15 raw -2 -c 022139"..b0) +end +-- +--- Set UID on magic command enabled, OFFICAL REPO +local function magicUID_offical(b0, b1) + print('Using backdoor Magic tag function OFFICAL REPO') + core.console("hf 15 cmd raw -c 02213E00000000") + core.console("hf 15 cmd raw -c 02213F69960000") + core.console("hf 15 cmd raw -c 022138"..b1) + core.console("hf 15 cmd raw -c 022139"..b0) +end +--- +-- The main entry point +function main(args) + + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print() + + local uid = 'E004013344556677' + + -- Read the parameters + for o, a in getopt.getopt(args, 'hu:') do + if o == "h" then return help() end + if o == "u" then uid = a end + end + + -- uid string checks + if uid == nil then return oops('empty uid string') end + if #uid == 0 then return oops('empty uid string') end + if #uid ~= 16 then return oops('uid wrong length. Should be 8 hex bytes') end + + local bytes = utils.ConvertHexToBytes(uid) + + local block0 = string.format('%02X%02X%02X%02X', bytes[4], bytes[3], bytes[2], bytes[1]) + local block1 = string.format('%02X%02X%02X%02X', bytes[8], bytes[7], bytes[6], bytes[5]) + + print('new UID | '..uid) + + core.clearCommandBuffer() + + magicUID_iceman(block0, block1) + --magicUID_offical(block0, block1) +end + +main(args) From 4ef59c37717de3ce6671e564e372ce3e7dd48bcc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 18 Dec 2018 18:43:27 +0100 Subject: [PATCH 0320/1938] CHG: uniform output. --- client/emv/emvcore.c | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 1b4808410..058aefe50 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -249,7 +249,7 @@ int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveField memcpy(&data[5], apdu.data, apdu.Lc); if (APDULogging) - PrintAndLogEx(NORMAL, ">>>> %s", sprint_hex(data, (IncludeLe?6:5) + apdu.Lc)); + PrintAndLogEx(SUCCESS, ">>>> %s", sprint_hex(data, (IncludeLe?6:5) + apdu.Lc)); switch(channel) { case ECC_CONTACTLESS: @@ -269,7 +269,7 @@ int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveField } if (APDULogging) - PrintAndLogEx(NORMAL, "<<<< %s", sprint_hex(Result, *ResultLen)); + PrintAndLogEx(SUCCESS, "<<<< %s", sprint_hex(Result, *ResultLen)); if (*ResultLen < 2) { return 200; @@ -422,7 +422,7 @@ int EMVSearch(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, } retrycnt = 0; - PrintAndLogEx(FAILED, "Retry failed [%s]. Skiped...", AIDlist[i].aid); + PrintAndLogEx(FAILED, "Retry failed [%s]. Skipped...", AIDlist[i].aid); } continue; } @@ -431,8 +431,11 @@ int EMVSearch(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, if (res) continue; - if (decodeTLV){ - PrintAndLogEx(NORMAL, "%s:", AIDlist[i].aid); + if (!datalen) + continue; + + if (decodeTLV) { + PrintAndLogEx(SUCCESS, "%s", AIDlist[i].aid); TLVPrintFromBuffer(data, datalen); } } From 94e0d435029a8d9234d6640a50277a9dae975710 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 18 Dec 2018 18:43:49 +0100 Subject: [PATCH 0321/1938] CHG: coloring of ERR --- client/ui.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/ui.c b/client/ui.c index 070f75b7a..3f7e2611f 100644 --- a/client/ui.c +++ b/client/ui.c @@ -58,6 +58,9 @@ void PrintAndLogEx(logLevel_t level, char *fmt, ...) { static char *prefixes[7] = { "", "[+] ", "[=] ", "[-] ", "[!] ", "[!!] ", "[#] "}; switch( level ) { + case ERR: + strncpy(prefix,_RED_([!!] ), sizeof(prefix)-1); + break; case FAILED: strncpy(prefix,_RED_([-] ), sizeof(prefix)-1); break; From dab854e0f03fbab752de07171a84158321cb3424 Mon Sep 17 00:00:00 2001 From: mazodude Date: Wed, 19 Dec 2018 16:51:27 +1000 Subject: [PATCH 0322/1938] Fix detection of MADs so that is checks the correct byte also set up some code for later --- client/scripts/mifare_ad.lua | 90 +++++++++++++++++++++++++++++------- 1 file changed, 73 insertions(+), 17 deletions(-) diff --git a/client/scripts/mifare_ad.lua b/client/scripts/mifare_ad.lua index 385e34338..885c25a81 100644 --- a/client/scripts/mifare_ad.lua +++ b/client/scripts/mifare_ad.lua @@ -37,7 +37,6 @@ local function debug(...) end end - local function show(data) if DEBUG then local formatString = ("H%d"):format(string.len(data)) @@ -45,6 +44,15 @@ local function show(data) debug("Hexdata" , hexdata) end end + +local function bits(num) + local t={} + while num>0 do + rest=num%2 + table.insert(t,1,rest) + num=(num-rest)/2 + end return table.concat(t) +end --- Shut down tag communication -- return no return values local function close() @@ -71,8 +79,8 @@ local function checkCommand(command) local count, cmd, arg0 = bin.unpack('LL',result) if(arg0==1) then local count, arg1, arg2, data = bin.unpack('LLH511',result,count) - block = data:sub(33,64) - return block + sector = data + return sector else return nil end @@ -82,10 +90,10 @@ local function checkCommand(command) end end ----_ Gets data from a block --- @return block if successfull +---_ Gets data from a sector +-- @return sector if successfull -- @return nil, errormessage if unsuccessfull -local function getBlock(block) +local function getSector(sector,typ) local data, err core.clearCommandBuffer() @@ -95,9 +103,12 @@ local function getBlock(block) -- uint8_t keyType = arg1; -- uint64_t ui64Key = 0; -- ui64Key = bytes_to_num(datain, 6); - local sectorNo = 0 + local sectorNo = sector local keyType = 0 - local key = "A0A1A2A3A4A5"; + local key = "" + if typ == 1 then + key = "A0A1A2A3A4A5" + end debug(("Testing to auth with key %s"):format(key)) -- print(key); local command = Command:new{cmd = cmds.CMD_MIFARE_READSC, @@ -112,9 +123,7 @@ local function getBlock(block) if string.len(data) < 32 then return nil, ("Expected at least 32 bytes, got %d - this tag does not have MADs"):format(string.len(data)) end - -- -- Now, parse out the block data - b0 = string.sub(data,3,4) - return b0 + return data end @@ -149,17 +158,64 @@ local function main( args) if not tag then return oops("No card present") end core.clearCommandBuffer() print(("UID: %s"):format(tag.uid)) + print(("SAK: %x"):format(tag.sak)) - -- First, get block 1 byte 1 - local block, err = getBlock(0) + local typ = 1 + if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k + typ = 4 + elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K + typ= 1 + elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k + typ = 0 + elseif 0x10 == sak then-- "NXP MIFARE Plus 2k" + typ = 2 + elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K" + typ = 1 + else + debug("Defaulting to CLASSIC") + end + + -- # | data | Sector | 00/ 0x00 + -- ----+------------------------------------------------ + -- 0 | 5C 71 B0 14 89 88 04 00 C0 8E 3C 90 49 50 12 13 + -- 1 | 80 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 + -- 2 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12 48 + -- 3 | A0 A1 A2 A3 A4 A5 78 77 88 E9 B0 B1 B2 B3 B4 B5 + + -- E9 = 1 1 1010 01 + -- C1 = 1 1 0000 01 + -- 69 = 0 1 1010 01 + -- 99 = 1 0 0110 01 + + -- Need to check the sector trailer GPB + -- First, get Sector 0 block 3 byte 10 + local sector, err = getSector(0,1) if err then return oops(err) end - debug(("Checking block 0 sector 1 byte 1")) - debug(("Got byte: %s"):format(block)) + -- -- Now, parse out the block data + sector = sector:sub(0,128) + debug(sector) + local trailer = sector:sub(97,128) + debug(trailer) + local gpb = string.sub(trailer,19,20) + debug(("Checking block 0 sector 3 byte 10")) + debug(("Got byte: %s"):format(gpb)) + local gpbbits = bits(tonumber(gpb,16)) + debug(gpbbits) + local adv = gpbbits:sub(7,8) + print(("ADV: %s"):format(adv)) + local rfu = gpbbits:sub(3,6) + print(("RFU: %s"):format(rfu)) + local ma = gpbbits:sub(2,2) + print(("MA: %s"):format(ma)) + local da = gpbbits:sub(1,1) + print(("DA: %s"):format(da)) -- prlog(block) - if block == "0F" then + if adv == "01" then print('Card has MADs v1') end - --(iceman) Should be able to detect MAD v2 aswell.. + if adv == "10" then + print('Card has MADs v2') + end -- Deactivate field close() From e567b74fa035f23c48a76988cac33975bde1cdae Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 19 Dec 2018 08:57:59 +0100 Subject: [PATCH 0323/1938] chg... --- client/default_keys.dic | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/default_keys.dic b/client/default_keys.dic index f764596ce..3fb8f07bf 100644 --- a/client/default_keys.dic +++ b/client/default_keys.dic @@ -708,4 +708,7 @@ E56AC127DD45, EA0FD73CB149, FC0001877BF7, FD8705E721B0, -00ada2cd516d, \ No newline at end of file +00ada2cd516d, +# +# +D3F7D3F7D3F7 \ No newline at end of file From f0c34827991b014c4e42ecad2294abab3efc2483 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 19 Dec 2018 20:31:20 +0200 Subject: [PATCH 0324/1938] add T=0 to `sc raw` command --- client/cmdsmartcard.c | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 8408b03ce..953526284 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -15,14 +15,15 @@ int usage_sm_raw(void) { PrintAndLogEx(NORMAL, "Usage: sc raw [h|r|c] d <0A 0B 0C ... hex>"); PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, " r : do not read response"); - PrintAndLogEx(NORMAL, " a : active smartcard without select"); - PrintAndLogEx(NORMAL, " s : active smartcard with select"); + PrintAndLogEx(NORMAL, " a : active smartcard without select (reset sc module)"); + PrintAndLogEx(NORMAL, " s : active smartcard with select (get ATR)"); PrintAndLogEx(NORMAL, " t : executes TLV decoder if it possible"); + PrintAndLogEx(NORMAL, " 0 : use protocol T=0"); PrintAndLogEx(NORMAL, " d : bytes to send"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " sc raw d 00a404000e315041592e5359532e444446303100 - `1PAY.SYS.DDF01` PPSE directory"); - PrintAndLogEx(NORMAL, " sc raw d 00a404000e325041592e5359532e444446303100 - `2PAY.SYS.DDF01` PPSE directory"); + PrintAndLogEx(NORMAL, " sc raw s 0 d 00a404000e315041592e5359532e444446303100 - `1PAY.SYS.DDF01` PPSE directory with get ATR"); + PrintAndLogEx(NORMAL, " sc raw 0 d 00a404000e325041592e5359532e444446303100 - `2PAY.SYS.DDF01` PPSE directory"); return 0; } int usage_sm_reader(void) { @@ -362,6 +363,7 @@ int CmdSmartRaw(const char *Cmd) { int hexlen = 0; bool active = false; bool active_select = false; + bool useT0 = false; uint8_t cmdp = 0; bool errors = false, reply = true, decodeTLV = false, breakloop = false; uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; @@ -385,6 +387,10 @@ int CmdSmartRaw(const char *Cmd) { decodeTLV = true; cmdp++; break; + case '0': + useT0 = true; + cmdp++; + break; case 'd': { switch (param_gethex_to_eol(Cmd, cmdp+1, data, sizeof(data), &hexlen)) { case 1: @@ -425,7 +431,10 @@ int CmdSmartRaw(const char *Cmd) { } if (hexlen > 0) { - c.arg[0] |= SC_RAW; + if (useT0) + c.arg[0] |= SC_RAW_T0; + else + c.arg[0] |= SC_RAW; } memcpy(c.d.asBytes, data, hexlen ); From 0143d3f0e0a240005251f985a3beebbbe7063bca Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 19 Dec 2018 22:50:32 +0100 Subject: [PATCH 0325/1938] chg: 'sc raw' - some more love --- client/cmdsmartcard.c | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 953526284..11988c98b 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -22,8 +22,8 @@ int usage_sm_raw(void) { PrintAndLogEx(NORMAL, " d : bytes to send"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " sc raw s 0 d 00a404000e315041592e5359532e444446303100 - `1PAY.SYS.DDF01` PPSE directory with get ATR"); - PrintAndLogEx(NORMAL, " sc raw 0 d 00a404000e325041592e5359532e444446303100 - `2PAY.SYS.DDF01` PPSE directory"); + PrintAndLogEx(NORMAL, " sc raw s 0 d 00a404000e315041592e5359532e4444463031 - `1PAY.SYS.DDF01` PPSE directory with get ATR"); + PrintAndLogEx(NORMAL, " sc raw 0 d 00a404000e325041592e5359532e4444463031 - `2PAY.SYS.DDF01` PPSE directory"); return 0; } int usage_sm_reader(void) { @@ -289,7 +289,7 @@ static bool smart_select(bool silent) { static int smart_wait(uint8_t *data) { UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - PrintAndLogEx(WARNING, "smart card response failed"); + PrintAndLogEx(WARNING, "smart card response timeout"); return -1; } @@ -299,11 +299,12 @@ static int smart_wait(uint8_t *data) { return -2; } memcpy(data, resp.d.asBytes, len); - PrintAndLogEx(SUCCESS, " %d | %s", len, sprint_hex_inrow_ex(data, len, 32)); - if (len >= 2) { PrintAndLogEx(SUCCESS, "%02X%02X | %s", data[len - 2], data[len - 1], GetAPDUCodeDescription(data[len - 2], data[len - 1])); + } else { + PrintAndLogEx(SUCCESS, " %d | %s", len, sprint_hex_inrow_ex(data, len, 8)); } + return len; } @@ -466,7 +467,7 @@ int CmdSmartRaw(const char *Cmd) { } if (decodeTLV && len > 4) - TLVPrintFromBuffer(buf+1, len-3); + TLVPrintFromBuffer(buf, len-2); free(buf); } @@ -478,7 +479,8 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave if (activateCard) smart_select(false); - printf("* APDU SC\n"); + + PrintAndLogEx(DEBUG, "APDU SC"); UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, datainlen, 0}}; if (activateCard) { @@ -806,8 +808,8 @@ int CmdSmartBruteforceSFI(const char *Cmd) { } PrintAndLogEx(INFO, "Selecting PPSE aid"); - CmdSmartRaw("d 00a404000e325041592e5359532e444446303100"); - CmdSmartRaw("d 00a4040007a000000004101000"); + CmdSmartRaw("s 0 d 00a404000e325041592e5359532e4444463031"); + CmdSmartRaw("0 d 00a4040007a000000004101000"); PrintAndLogEx(INFO, "starting"); From a9b3fd71382f4eec34aa7f5d83bd930ca8572129 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 19 Dec 2018 23:21:59 +0100 Subject: [PATCH 0326/1938] chg: 'sc brute' - now works :) --- client/cmdsmartcard.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 11988c98b..e21704fb3 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -323,7 +323,7 @@ static int smart_response(uint8_t *data) { if (needGetData) { int len = data[datalen - 1]; - PrintAndLogEx(INFO, "Requesting response. len=0x%x", len); + PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len); uint8_t getstatus[] = {0x00, ISO7816_GETSTATUS, 0x00, 0x00, len}; UsbCommand cStatus = {CMD_SMART_RAW, {SC_RAW, sizeof(getstatus), 0}}; memcpy(cStatus.d.asBytes, getstatus, sizeof(getstatus) ); @@ -341,7 +341,7 @@ static int smart_response(uint8_t *data) { // data with ACK if (datalen == len + 2 + 1) { // 2 - response, 1 - ACK if (data[0] != ISO7816_GETSTATUS) { - PrintAndLogEx(ERR, "GetResponse ACK error. len=0x%x data[0]=%02x", len, data[0]); + PrintAndLogEx(ERR, "GetResponse ACK error. len 0x%x | data[0] %02X", len, data[0]); datalen = 0; goto out; } @@ -350,7 +350,7 @@ static int smart_response(uint8_t *data) { memmove(data, &data[1], datalen); } else { // wrong length - PrintAndLogEx(WARNING, "GetResponse wrong length. Must be: 0x%02x but: 0x%02x", len, datalen - 3); + PrintAndLogEx(WARNING, "GetResponse wrong length. Must be 0x%02X got 0x%02X", len, datalen - 3); } } } @@ -808,8 +808,9 @@ int CmdSmartBruteforceSFI(const char *Cmd) { } PrintAndLogEx(INFO, "Selecting PPSE aid"); - CmdSmartRaw("s 0 d 00a404000e325041592e5359532e4444463031"); - CmdSmartRaw("0 d 00a4040007a000000004101000"); + CmdSmartRaw("s 0 t d 00a404000e325041592e5359532e4444463031"); + CmdSmartRaw("0 t d 00a4040007a000000004101000"); // mastercard +// CmdSmartRaw("0 t d 00a4040007a0000000031010"); // visa PrintAndLogEx(INFO, "starting"); @@ -830,7 +831,6 @@ int CmdSmartBruteforceSFI(const char *Cmd) { smart_response(buf); - // if 0x6C if ( buf[0] == 0x6C ) { data[4] = buf[1]; From d4b32f30509911f06a617c990cf5a029ab851e2b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 19 Dec 2018 23:28:01 +0100 Subject: [PATCH 0327/1938] ADD: Sim module firmware upgrade file. v3.10 --- common/i2c.c | 2 +- tools/simmodule/SIM010.BIN | Bin 0 -> 719 bytes 2 files changed, 1 insertion(+), 1 deletion(-) create mode 100644 tools/simmodule/SIM010.BIN diff --git a/common/i2c.c b/common/i2c.c index ea830a1bd..99f8b6e12 100644 --- a/common/i2c.c +++ b/common/i2c.c @@ -575,7 +575,7 @@ void I2C_print_status(void) { I2C_Reset_EnterMainProgram(); uint8_t len = I2C_BufferRead(resp, sizeof(resp), I2C_DEVICE_CMD_GETVERSION, I2C_DEVICE_ADDRESS_MAIN); if ( len > 0 ) - Dbprintf(" version.................v%x.%02x", resp[0], resp[1]); + Dbprintf(" version.................v%x.%02d", resp[0], resp[1]); else DbpString(" version.................FAILED"); } diff --git a/tools/simmodule/SIM010.BIN b/tools/simmodule/SIM010.BIN new file mode 100644 index 0000000000000000000000000000000000000000..dea57a7d8608a34020f7d9e5e40a5b6e915be6fa GIT binary patch literal 719 zcmbVJO=uHA6rS1L$-l5DLa~?K$zPi&EQ<%hi&CM-7^G)Cc=O`ri3c%jCH{bwbYmf* z2XzZliW1uHp@&G~bZdKD268JV2XpY2OEJ|ZaaU8USKl1o_kF{A?|VD}ucL7&IpOTI zGD})h0x#>wDni)!i+zOG{^kG6Sf3s0az&D>s?L!joojZ8)vXrkJUqrdLW$*eSQ(}+ zl9bMadb87X!JVjmY@jfA*tX&f)Jo%)%uI%v$OsFt5DTkj!?>s59LL?d9h7*~Ahr-= zQAi?AAc0iV#;3RdDFhTj+~)y7eQisz`&mdM$VlAlVUuG@e5#rXi78=0HQ&`kB(0iU z^qkg<3C}6&kp!_w(i{9{lABssVqqT9#7j)%(upyRRlyJ&TdEc!PwFABV<5-_#Z+B2 ziB*jID|Zg+Bu*^0!yL|B*IRyD_e^C1kQLy(2p1yUtAj^-uyF;}M_}KC%`NzV;Qa`m zQ+R=3;Tt@ggWWaQots(2uqpq+Hx`G`yvASgGJI-6#f7H^^sj>xf}QX1c?3%WC Date: Wed, 19 Dec 2018 23:46:19 +0100 Subject: [PATCH 0328/1938] CHG: 'sc info' - textual --- client/cmdsmartcard.c | 90 +++++++++++++++++++++---------------------- 1 file changed, 43 insertions(+), 47 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index e21704fb3..1ed46b993 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -159,58 +159,46 @@ float GetATRF(uint8_t *atr, size_t atrlen) { } static int PrintATR(uint8_t *atr, size_t atrlen) { - uint8_t vxor = 0; - for (int i = 1; i < atrlen; i++) - vxor ^= atr[i]; - - if (vxor) - PrintAndLogEx(WARNING, "Check summ error. Must be 0 but: 0x%02x", vxor); - else - PrintAndLogEx(INFO, "Check summ OK."); - - if (atr[0] != 0x3b) - PrintAndLogEx(WARNING, "Not a direct convention: 0x%02x", atr[0]); uint8_t T0 = atr[1]; uint8_t K = T0 & 0x0F; - uint8_t TD1 = 0; - - uint8_t T1len = 0; - uint8_t TD1len = 0; - uint8_t TDilen = 0; + uint8_t TD1 = 0, T1len = 0, TD1len = 0, TDilen = 0; if (T0 & 0x10) { - PrintAndLog("TA1 (Maximum clock frequency, proposed bit duration): 0x%02x", atr[2 + T1len]); + PrintAndLog("\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr[2 + T1len]); T1len++; } + if (T0 & 0x20) { - PrintAndLog("TB1 (Deprecated: VPP requirements): 0x%02x", atr[2 + T1len]); + PrintAndLog("\t- TB1 (Deprecated: VPP requirements) [ 0x%02x ]", atr[2 + T1len]); T1len++; } + if (T0 & 0x40) { - PrintAndLog("TC1 (Extra delay between bytes required by card): 0x%02x", atr[2 + T1len]); + PrintAndLog("\t- TC1 (Extra delay between bytes required by card) [ 0x%02x ]", atr[2 + T1len]); T1len++; } + if (T0 & 0x80) { TD1 = atr[2 + T1len]; - PrintAndLog("TD1 (First offered transmission protocol, presence of TA2..TD2): 0x%02x. Protocol T=%d", TD1, TD1 & 0x0f); + PrintAndLog("\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1, TD1 & 0x0f); T1len++; if (TD1 & 0x10) { - PrintAndLog("TA2 (Specific protocol and parameters to be used after the ATR): 0x%02x", atr[2 + T1len + TD1len]); + PrintAndLog("\t- TA2 (Specific protocol and parameters to be used after the ATR) [ 0x%02x ]", atr[2 + T1len + TD1len]); TD1len++; } if (TD1 & 0x20) { - PrintAndLog("TB2 (Deprecated: VPP precise voltage requirement): 0x%02x", atr[2 + T1len + TD1len]); + PrintAndLog("\t- TB2 (Deprecated: VPP precise voltage requirement) [ 0x%02x ]", atr[2 + T1len + TD1len]); TD1len++; } if (TD1 & 0x40) { - PrintAndLog("TC2 (Maximum waiting time for protocol T=0): 0x%02x", atr[2 + T1len + TD1len]); + PrintAndLog("\t- TC2 (Maximum waiting time for protocol T=0) [ 0x%02x ]", atr[2 + T1len + TD1len]); TD1len++; } if (TD1 & 0x80) { uint8_t TDi = atr[2 + T1len + TD1len]; - PrintAndLog("TD2 (A supported protocol or more global parameters, presence of TA3..TD3): 0x%02x. Protocol T=%d", TDi, TDi & 0x0f); + PrintAndLog("\t- TD2 (A supported protocol or more global parameters, presence of TA3..TD3) [ 0x%02x ] Protocol T%d", TDi, TDi & 0x0f); TD1len++; bool nextCycle = true; @@ -218,20 +206,20 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { while (nextCycle) { nextCycle = false; if (TDi & 0x10) { - PrintAndLog("TA%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); + PrintAndLog("\t- TA%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); TDilen++; } if (TDi & 0x20) { - PrintAndLog("TB%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); + PrintAndLog("\t- TB%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); TDilen++; } if (TDi & 0x40) { - PrintAndLog("TC%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); + PrintAndLog("\t- TC%d: 0x%02x", vi, atr[2 + T1len + TD1len + TDilen]); TDilen++; } if (TDi & 0x80) { TDi = atr[2 + T1len + TD1len + TDilen]; - PrintAndLog("TD%d: 0x%02x. Protocol T=%d", vi, TDi, TDi & 0x0f); + PrintAndLog("\t- TD%d [ 0x%02x ] Protocol T%d", vi, TDi, TDi & 0x0f); TDilen++; nextCycle = true; @@ -240,26 +228,36 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { } } } + + uint8_t vxor = 0; + for (int i = 1; i < atrlen; i++) + vxor ^= atr[i]; + + if (vxor) + PrintAndLogEx(WARNING, "Check summ error. Must be 0 got 0x%02X", vxor); + else + PrintAndLogEx(INFO, "Check summ OK."); + + if (atr[0] != 0x3b) + PrintAndLogEx(WARNING, "Not a direct convention [ 0x%02x ]", atr[0]); + uint8_t calen = 2 + T1len + TD1len + TDilen + K; if (atrlen != calen && atrlen != calen + 1) // may be CRC PrintAndLogEx(ERR, "ATR length error. len: %d, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen, T1len, TD1len, TDilen, K); - else - PrintAndLogEx(INFO, "ATR length OK."); - PrintAndLog("Historical bytes len: 0x%02x", K); if (K > 0) - PrintAndLog("The format of historical bytes: %02x", atr[2 + T1len + TD1len + TDilen]); + PrintAndLogEx(INFO, "\nHistorical bytes | len 0x%02d | format %02x", K, atr[2 + T1len + TD1len + TDilen]); + if (K > 1) { - PrintAndLog("Historical bytes:"); + PrintAndLogEx(INFO, "\tHistorical bytes"); dump_buffer(&atr[2 + T1len + TD1len + TDilen], K, NULL, 1); } return 0; } - static bool smart_select(bool silent) { UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}}; clearCommandBuffer(); @@ -515,7 +513,6 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave return 0; } - int CmdSmartUpgrade(const char *Cmd) { PrintAndLogEx(WARNING, "WARNING - Smartcard socket firmware upgrade."); @@ -663,32 +660,31 @@ int CmdSmartInfo(const char *Cmd){ memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t)); // print header - PrintAndLogEx(INFO, "\n--- Smartcard Information ---------"); + PrintAndLogEx(INFO, "--- Smartcard Information ---------"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); - PrintAndLogEx(INFO, "ISO76183 ATR : %s", sprint_hex(card.atr, card.atr_len)); - PrintAndLogEx(INFO, "look up ATR"); - PrintAndLogEx(INFO, "http://smartcard-atr.appspot.com/parse?ATR=%s", sprint_hex_inrow(card.atr, card.atr_len) ); + PrintAndLogEx(INFO, "ISO7618-3 ATR : %s", sprint_hex(card.atr, card.atr_len)); + PrintAndLogEx(INFO, "\nhttp://smartcard-atr.appspot.com/parse?ATR=%s", sprint_hex_inrow(card.atr, card.atr_len) ); // print ATR PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "* ATR:"); + PrintAndLogEx(INFO, "ATR"); PrintATR(card.atr, card.atr_len); // print D/F (brom byte TA1 or defaults) PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "* D/F (TA1):"); + PrintAndLogEx(INFO, "D/F (TA1)"); int Di = GetATRDi(card.atr, card.atr_len); int Fi = GetATRFi(card.atr, card.atr_len); float F = GetATRF(card.atr, card.atr_len); if (GetATRTA1(card.atr, card.atr_len) == 0x11) PrintAndLogEx(INFO, "Using default values..."); - PrintAndLogEx(NORMAL, "Di=%d", Di); - PrintAndLogEx(NORMAL, "Fi=%d", Fi); - PrintAndLogEx(NORMAL, "F=%.1f MHz", F); - PrintAndLogEx(NORMAL, "Cycles/ETU=%d", Fi/Di); - PrintAndLogEx(NORMAL, "%.1f bits/sec at 4MHz", (float)4000000 / (Fi/Di)); - PrintAndLogEx(NORMAL, "%.1f bits/sec at Fmax=%.1fMHz", (F * 1000000) / (Fi/Di), F); + PrintAndLogEx(NORMAL, "\t- Di %d", Di); + PrintAndLogEx(NORMAL, "\t- Fi %d", Fi); + PrintAndLogEx(NORMAL, "\t- F %.1f MHz", F); + PrintAndLogEx(NORMAL, "\t- Cycles/ETU %d", Fi/Di); + PrintAndLogEx(NORMAL, "\t- %.1f bits/sec at 4 MHz", (float)4000000 / (Fi/Di)); + PrintAndLogEx(NORMAL, "\t- %.1f bits/sec at Fmax (%.1f MHz)", (F * 1000000) / (Fi/Di), F); return 0; } From f7a2af19f8660fe21c02aba86e700f5f02d6cdf0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 20 Dec 2018 12:24:55 +0100 Subject: [PATCH 0329/1938] ADD: sha512, md5 hashes for firmware file. --- tools/simmodule/SIM010.md5.txt | 1 + tools/simmodule/SIM010.sha512.txt | 1 + tools/simmodule/readme.txt | 36 +++++++++++++++++++++++++++++++ 3 files changed, 38 insertions(+) create mode 100644 tools/simmodule/SIM010.md5.txt create mode 100644 tools/simmodule/SIM010.sha512.txt create mode 100644 tools/simmodule/readme.txt diff --git a/tools/simmodule/SIM010.md5.txt b/tools/simmodule/SIM010.md5.txt new file mode 100644 index 000000000..c790101f7 --- /dev/null +++ b/tools/simmodule/SIM010.md5.txt @@ -0,0 +1 @@ +136e157364609e5c395540dc8dadbfd6 *SIM010.BIN diff --git a/tools/simmodule/SIM010.sha512.txt b/tools/simmodule/SIM010.sha512.txt new file mode 100644 index 000000000..b7bab7246 --- /dev/null +++ b/tools/simmodule/SIM010.sha512.txt @@ -0,0 +1 @@ +e6ac5e6f1d7cc86d56f2128f2a495f1395fe044bf6ff3b6ca24ce90d1e361ae835fe273a206f2fc90e4344a13b37b180dd017a2c7f23312f1ed163f10c01ea5a *SIM010.BIN diff --git a/tools/simmodule/readme.txt b/tools/simmodule/readme.txt new file mode 100644 index 000000000..7efa40205 --- /dev/null +++ b/tools/simmodule/readme.txt @@ -0,0 +1,36 @@ + +2018-12-20 Iceman + +======================================= + +The latest firmware for the SIM MODULE is : SIM010.bin + + +You can use it to upgrade you sim module via the pm3 client. + + +pm3 --> sc upgrade -h +pm3 --> sc upgrade f ../tools/simmodule/SIM010.bin + + + +Even its a quite fast command you should be warned. You may brick it if you interrupt it. + + + +Run hw status command to verify that the upgrade went well. + +pm3 --> hw status + + + +If you didn't download this file from the RRG Repo be aware that it might be corrupt or faulty. + +You find to hash text files in this folder. They were generated with the following linux commands. + + +md5sum -b SIM010.bin > SIM010.md5.txt +sha512sum -b SIM010.bin > SIM010.sha512.txt + + +You should validate the SIM010.bin file against these hash files in order to be sure the file is not corrupt or faulty. \ No newline at end of file From d64a48b7fcf218da33f97cba9ec3339e78902e76 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 20 Dec 2018 23:05:02 +0200 Subject: [PATCH 0330/1938] added check Fi and Di --- client/cmdsmartcard.c | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 8408b03ce..e4c161153 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -675,10 +675,14 @@ int CmdSmartInfo(const char *Cmd){ PrintAndLogEx(NORMAL, "Di=%d", Di); PrintAndLogEx(NORMAL, "Fi=%d", Fi); PrintAndLogEx(NORMAL, "F=%.1f MHz", F); - PrintAndLogEx(NORMAL, "Cycles/ETU=%d", Fi/Di); - PrintAndLogEx(NORMAL, "%.1f bits/sec at 4MHz", (float)4000000 / (Fi/Di)); - PrintAndLogEx(NORMAL, "%.1f bits/sec at Fmax=%.1fMHz", (F * 1000000) / (Fi/Di), F); - + if (Di && Fi) { + PrintAndLogEx(NORMAL, "Cycles/ETU=%d", Fi/Di); + PrintAndLogEx(NORMAL, "%.1f bits/sec at 4MHz", (float)4000000 / (Fi/Di)); + PrintAndLogEx(NORMAL, "%.1f bits/sec at Fmax=%.1fMHz", (F * 1000000) / (Fi/Di), F); + } else { + PrintAndLogEx(WARNING, "Di or Fi is RFU."); + }; + return 0; } From acb41a7376ef20bf2ba728f3c661ac8bc07eefda Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 23 Dec 2018 09:48:46 +0100 Subject: [PATCH 0331/1938] CHG: 'sc brute' - now is interruptable, optional tlv decode, --- client/aidlist.json | 1 + client/cmdhffido.c | 2 +- client/cmdsmartcard.c | 325 +++++++++++++++++++++++++++++++++--------- client/emv/cmdemv.c | 1 + client/emv/emv_tags.c | 47 +++--- client/emv/emvcore.c | 4 +- client/emv/emvcore.h | 2 +- 7 files changed, 291 insertions(+), 91 deletions(-) create mode 100644 client/aidlist.json diff --git a/client/aidlist.json b/client/aidlist.json new file mode 100644 index 000000000..7ec139d46 --- /dev/null +++ b/client/aidlist.json @@ -0,0 +1 @@ +[{"Vendor": "Visa International", "Description": "", "Country": "United States", "AID": "315041592E5359532E4444463031", "Type": "", "Name": "Visa Payment System Environment - PSE (1PAY.SYS.DDF01)"}, {"Vendor": "Visa International", "Description": "Visa payWave for Mobile", "Country": "United States", "AID": "325041592E5359532E4444463031", "Type": "", "Name": "Visa Proximity Payment System Environment - PPSE (2PAY.SYS.DDF01)"}, {"Vendor": "DeviceFidelity", "Description": "http://www.nfcworld.com/2010/11/24/35207/devicefidelity-adds-nfc-support-for-android-and-mifare/", "Country": "United States", "AID": "44464D46412E44466172653234313031", "Type": "", "Name": "DeviceFidelity In2Pay DFare applet"}, {"Vendor": "PBS Danmnt A/S", "Description": "(Unlicensed use of this RID. Proposal to use A000000323 instead)", "Country": "Denmark", "AID": "A00000000101", "Type": "", "Name": "MUSCLE Card Applet"}, {"Vendor": "Visa International", "Description": "Used by most GP2.1.1 cards / Oberthur OP201 cards. Visa Proprietary Card Manager AID for OpenPlatform cards (visa.openplatform).", "Country": "United States", "AID": "A000000003000000", "Type": "GP", "Name": "(VISA) Card Manager"}, {"Vendor": "Visa International", "Description": "", "Country": "United States", "AID": "A00000000300037561", "Type": "", "Name": "Bonuscard"}, {"Vendor": "Visa International", "Description": "", "Country": "United States", "AID": "A00000000305076010", "Type": "EMV", "Name": "VISA ELO Credit"}, {"Vendor": "Visa International", "Description": "Standard/Gold VISA credit card", "Country": "United States", "AID": "A0000000031010", "Type": "EMV", "Name": "VISA Debit/Credit (Classic)"}, {"Vendor": "Visa International", "Description": "", "Country": "United States", "AID": "A000000003101001", "Type": "EMV", "Name": "VISA Credit"}, {"Vendor": "Visa International", "Description": "", "Country": "United States", "AID": "A000000003101002", "Type": "EMV", "Name": "VISA Debit"}, {"Vendor": "Visa International", "Description": "VISA Electron (Debit)", "Country": "United States", "AID": "A0000000032010", "Type": "EMV", "Name": "VISA Electron"}, {"Vendor": "Visa International", "Description": "V PAY", "Country": "United States", "AID": "A0000000032020", "Type": "EMV", "Name": "VISA"}, {"Vendor": "Visa International", "Description": "VISA Interlink", "Country": "United States", "AID": "A0000000033010", "Type": "EMV", "Name": "VISA Interlink"}, {"Vendor": "Visa International", "Description": "Visa Specific", "Country": "United States", "AID": "A0000000034010", "Type": "EMV", "Name": "VISA Specific"}, {"Vendor": "Visa International", "Description": "Visa Specific", "Country": "United States", "AID": "A0000000035010", "Type": "EMV", "Name": "VISA Specific"}, {"Vendor": "Visa International", "Description": "", "Country": "United States", "AID": "A000000003534441", "Type": "GP", "Name": "Schlumberger Security Domain"}, {"Vendor": "Visa International", "Description": "OCS Oberthur Card System Security Domain Package AID / VGP Card Manager (for ISD and ASD)", "Country": "United States", "AID": "A0000000035350", "Type": "GP", "Name": "Security Domain"}, {"Vendor": "Visa International", "Description": "OCS Oberthur Card System Security Domain Applet AID / VGP Card Manager (for ISD and ASD)", "Country": "United States", "AID": "A000000003535041", "Type": "GP", "Name": "Security Domain"}, {"Vendor": "Visa International", "Description": "", "Country": "United States", "AID": "A0000000036010", "Type": "EMV", "Name": "Domestic Visa Cash Stored Value"}, {"Vendor": "Visa International", "Description": "", "Country": "United States", "AID": "A0000000036020", "Type": "EMV", "Name": "International Visa Cash Stored Value"}, {"Vendor": "Visa International", "Description": "VISA Auth dynamic passcode authentication (DPA). Used by Barclays/HBOS", "Country": "United States", "AID": "A0000000038002", "Type": "EMV", "Name": "VISA Auth, VisaRemAuthen EMV-CAP (DPA)"}, {"Vendor": "Visa International", "Description": "VISA plus", "Country": "United States", "AID": "A0000000038010", "Type": "EMV", "Name": "VISA Plus"}, {"Vendor": "Visa International", "Description": "", "Country": "United States", "AID": "A0000000039010", "Type": "EMV", "Name": "VISA Loyalty"}, {"Vendor": "Visa International", "Description": "", "Country": "United States", "AID": "A000000003999910", "Type": "EMV", "Name": "VISA Proprietary ATM"}, {"Vendor": "Mastercard International", "Description": "Security Domain", "Country": "United States", "AID": "A0000000040000", "Type": "GP", "Name": "MasterCard Card Manager"}, {"Vendor": "Mastercard International", "Description": "AEPM (Association Europenne Payez Mobile)", "Country": "United States", "AID": "A00000000401", "Type": "EMV", "Name": "MasterCard PayPass"}, {"Vendor": "Mastercard International", "Description": "Standard MasterCard", "Country": "United States", "AID": "A0000000041010", "Type": "EMV", "Name": "MasterCard Credit"}, {"Vendor": "Mastercard International", "Description": "Standard MasterCard", "Country": "United States", "AID": "A00000000410101213", "Type": "EMV", "Name": "MasterCard Credit"}, {"Vendor": "Mastercard International", "Description": "Standard MasterCard", "Country": "United States", "AID": "A00000000410101215", "Type": "EMV", "Name": "MasterCard Credit"}, {"Vendor": "Mastercard International", "Description": "Some co-branded card?", "Country": "United States", "AID": "A0000000041010BB5449435301", "Type": "", "Name": "[UNKNOWN]"}, {"Vendor": "Mastercard International", "Description": "MasterCard Specific", "Country": "United States", "AID": "A0000000042010", "Type": "EMV", "Name": "MasterCard Specific"}, {"Vendor": "Mastercard International", "Description": "MasterCard U.S. Maestro", "Country": "United States", "AID": "A0000000042203", "Type": "", "Name": "MasterCard Specific"}, {"Vendor": "Mastercard International", "Description": "MasterCard Specific", "Country": "United States", "AID": "A0000000043010", "Type": "EMV", "Name": "MasterCard Specific"}, {"Vendor": "Mastercard International", "Description": "Maestro (Debit) Card", "Country": "United States", "AID": "A0000000043060", "Type": "EMV", "Name": "Maestro (Debit)"}, {"Vendor": "Mastercard International", "Description": "Maestro (Debit) Card", "Country": "United States", "AID": "A000000004306001", "Type": "EMV", "Name": "Maestro (Debit)"}, {"Vendor": "Mastercard International", "Description": "MasterCard Specific", "Country": "United States", "AID": "A0000000044010", "Type": "EMV", "Name": "MasterCard Specific"}, {"Vendor": "Mastercard International", "Description": "MasterCard Specific", "Country": "United States", "AID": "A0000000045010", "Type": "EMV", "Name": "MasterCard Specific"}, {"Vendor": "Mastercard International", "Description": "AID on Cirrus Test Card", "Country": "United States", "AID": "A0000000045555", "Type": "", "Name": "APDULogger"}, {"Vendor": "Mastercard International", "Description": "Mastercard Cirrus (Interbank Network) ATM card only", "Country": "United States", "AID": "A0000000046000", "Type": "EMV", "Name": "Cirrus"}, {"Vendor": "Mastercard International", "Description": "Chip Authentication Protocol (CAP). Works with NatWest or SecureCode Aut", "Country": "United States", "AID": "A0000000048002", "Type": "EMV", "Name": "SecureCode Auth EMV-CAP"}, {"Vendor": "Mastercard International", "Description": "", "Country": "United States", "AID": "A0000000049999", "Type": "EMV", "Name": "MasterCard PayPass??"}, {"Vendor": "Switch Card Services Ltd.", "Description": "UK Domestic Maestro - Switch (debit card)", "Country": "United Kingdom", "AID": "A0000000050001", "Type": "EMV", "Name": "Maestro UK"}, {"Vendor": "Switch Card Services Ltd.", "Description": "UK Domestic Maestro - Switch (debit card)", "Country": "United Kingdom", "AID": "A0000000050002", "Type": "EMV", "Name": "Solo"}, {"Vendor": "ETSI", "Description": "Orange UK", "Country": "France", "AID": "A0000000090001FF44FF1289", "Type": "", "Name": "Orange"}, {"Vendor": "Europay International", "Description": "", "Country": "Belgium", "AID": "A0000000101030", "Type": "", "Name": "Maestro-CH"}, {"Vendor": "GEMPLUS", "Description": "", "Country": "France", "AID": "A00000001800", "Type": "", "Name": "Gemplus ?"}, {"Vendor": "GEMPLUS", "Description": "", "Country": "France", "AID": "A0000000181001", "Type": "", "Name": "com.gemplus.javacard.util packages"}, {"Vendor": "GEMPLUS", "Description": "434D = CM (ascii). Security domain for some GCX/GXP cards (GemXpresso Pro) (Gemalto)", "Country": "France", "AID": "A000000018434D", "Type": "GP", "Name": "Gemplus card manager"}, {"Vendor": "GEMPLUS", "Description": "(Gemalto)", "Country": "France", "AID": "A000000018434D00", "Type": "GP", "Name": "Gemplus Security Domain"}, {"Vendor": "Midland Bank Plc", "Description": "", "Country": "United Kingdom", "AID": "A00000002401", "Type": "EMV", "Name": "Self Service"}, {"Vendor": "American Express", "Description": "", "Country": "United Kingdom", "AID": "A000000025", "Type": "EMV", "Name": "American Express"}, {"Vendor": "American Express", "Description": "American Express (Credit/Debit)", "Country": "United Kingdom", "AID": "A0000000250000", "Type": "EMV", "Name": "American Express"}, {"Vendor": "American Express", "Description": "AEIPS-compliant (A-E contact EMV) payment application", "Country": "United Kingdom", "AID": "A00000002501", "Type": "EMV", "Name": "American Express"}, {"Vendor": "American Express", "Description": "", "Country": "United Kingdom", "AID": "A000000025010104", "Type": "", "Name": "American Express"}, {"Vendor": "American Express", "Description": "", "Country": "United Kingdom", "AID": "A000000025010402", "Type": "EMV", "Name": "American Express"}, {"Vendor": "American Express", "Description": "", "Country": "United Kingdom", "AID": "A000000025010701", "Type": "EMV", "Name": "ExpressPay"}, {"Vendor": "American Express", "Description": "", "Country": "United Kingdom", "AID": "A000000025010801", "Type": "EMV", "Name": "American Express"}, {"Vendor": "LINK Interchange Network Ltd", "Description": "Link (UK) ATM Network, or AMEX (Portugal?)", "Country": "United Kingdom", "AID": "A0000000291010", "Type": "EMV", "Name": "Link / American Express"}, {"Vendor": "LINK Interchange Network Ltd", "Description": "", "Country": "United Kingdom", "AID": "A00000002945087510100000", "Type": "", "Name": "CO-OP"}, {"Vendor": "LINK Interchange Network Ltd", "Description": "", "Country": "United Kingdom", "AID": "A00000002949034010100001", "Type": "", "Name": "HSBC"}, {"Vendor": "LINK Interchange Network Ltd", "Description": "", "Country": "United Kingdom", "AID": "A00000002949282010100000", "Type": "", "Name": "Barclay"}, {"Vendor": "LINK Interchange Network Ltd", "Description": "", "Country": "United Kingdom", "AID": "A000000029564182", "Type": "", "Name": "HAFX"}, {"Vendor": "Schlumberger Industries Identif d'Encarteur PR050", "Description": "Schlumberger (Gemalto) RID", "Country": "France", "AID": "A00000003029057000AD13100101FF", "Type": "", "Name": "BelPIC (Belgian Personal Identity Card) JavaCard Applet"}, {"Vendor": "Schlumberger Industries Identif d'Encarteur PR050", "Description": "", "Country": "France", "AID": "A0000000308000000000280101", "Type": "", "Name": "Gemalto .NET Card AID"}, {"Vendor": "Groupement des Cartes Bancaires \"CB\"", "Description": "Groupement des Cartes Bancaires (France)", "Country": "France", "AID": "A0000000421010", "Type": "EMV", "Name": "Cartes Bancaire EMV Card"}, {"Vendor": "Groupement des Cartes Bancaires \"CB\"", "Description": "", "Country": "France", "AID": "A0000000422010", "Type": "EMV", "Name": ""}, {"Vendor": "Groupement des Cartes Bancaires \"CB\"", "Description": "", "Country": "France", "AID": "A0000000423010", "Type": "EMV", "Name": ""}, {"Vendor": "Groupement des Cartes Bancaires \"CB\"", "Description": "", "Country": "France", "AID": "A0000000424010", "Type": "EMV", "Name": ""}, {"Vendor": "Groupement des Cartes Bancaires \"CB\"", "Description": "", "Country": "France", "AID": "A0000000425010", "Type": "EMV", "Name": ""}, {"Vendor": "Zentraler Kreditausschuss (ZKA)", "Description": "", "Country": "Germany", "AID": "A00000005945430100", "Type": "", "Name": "Girocard Electronic Cash"}, {"Vendor": "RSA Laboratories", "Description": "RSA PKCS-15 PKI application (Predecessor to ISO7816-15) / ID-card in Finland", "Country": "United States", "AID": "A000000063504B43532D3135", "Type": "", "Name": "PKCS-15"}, {"Vendor": "RSA Laboratories", "Description": "WAP (Wireless Application Protocol) Identity Module / Wireless Identification Module", "Country": "United States", "AID": "A0000000635741502D57494D", "Type": "", "Name": "WAP-WIM"}, {"Vendor": "JCB CO., LTD.", "Description": "Japan Credit Bureau", "Country": "Japan", "AID": "A00000006510", "Type": "EMV", "Name": "JCB"}, {"Vendor": "JCB CO., LTD.", "Description": "Japan Credit Bureau", "Country": "Japan", "AID": "A0000000651010", "Type": "EMV", "Name": "JCB J Smart Credit"}, {"Vendor": "Socit Europenne de Monnaie Electronique SEME", "Description": "", "Country": "France", "AID": "A00000006900", "Type": "EMV", "Name": "Moneo"}, {"Vendor": "Oberthur Technologies", "Description": "", "Country": "France", "AID": "A000000077010000021000000000003B", "Type": "EMV", "Name": "Visa AEPN"}, {"Vendor": "Activcard Europe S.A.", "Description": "Identity Key", "Country": "France", "AID": "A0000000790100", "Type": "", "Name": "CACv2 PKI ID"}, {"Vendor": "Activcard Europe S.A.", "Description": "Digital Signature Key", "Country": "France", "AID": "A0000000790101", "Type": "", "Name": "CACv2 PKI Sign"}, {"Vendor": "Activcard Europe S.A.", "Description": "Key Management Key", "Country": "France", "AID": "A0000000790102", "Type": "", "Name": "CACv2 PKI Enc"}, {"Vendor": "Activcard Europe S.A.", "Description": "Re-directs to CACv2 PKI Identity key", "Country": "France", "AID": "A00000007901F0", "Type": "", "Name": "CACv1 PKI Identity Key"}, {"Vendor": "Activcard Europe S.A.", "Description": "Re-directs to CACv2 Digital Signature key", "Country": "France", "AID": "A00000007901F1", "Type": "", "Name": "CACv1 PKI Digital Signature Key"}, {"Vendor": "Activcard Europe S.A.", "Description": "Re-directs to CACv2 Key Management key", "Country": "France", "AID": "A00000007901F2", "Type": "", "Name": "CACv1 PKI Key Management Key"}, {"Vendor": "Activcard Europe S.A.", "Description": "DoD Demographic", "Country": "France", "AID": "A0000000790200", "Type": "", "Name": "CACv2 DoD Person"}, {"Vendor": "Activcard Europe S.A.", "Description": "DoD Demographic", "Country": "France", "AID": "A0000000790201", "Type": "", "Name": "CACv2 DoD Personnel"}, {"Vendor": "Activcard Europe S.A.", "Description": "General Configuration", "Country": "France", "AID": "A00000007902FB", "Type": "", "Name": "CACv1 BC"}, {"Vendor": "Activcard Europe S.A.", "Description": "PKI Certificate Attributes", "Country": "France", "AID": "A00000007902FD", "Type": "", "Name": "CACv1 BC"}, {"Vendor": "Activcard Europe S.A.", "Description": "PKI Cert", "Country": "France", "AID": "A00000007902FE", "Type": "", "Name": "CACv1 BC"}, {"Vendor": "Activcard Europe S.A.", "Description": "CAC PIN / ID PIN Management Applet", "Country": "France", "AID": "A0000000790300", "Type": "", "Name": "CACv2 Access Control Applet"}, {"Vendor": "Activcard Europe S.A.", "Description": "Joint Data Model. BCAdmin", "Country": "France", "AID": "A0000000791201", "Type": "", "Name": "CAC JDM"}, {"Vendor": "Activcard Europe S.A.", "Description": "Joint Data Model. BCMedical", "Country": "France", "AID": "A0000000791202", "Type": "", "Name": "CAC JDM"}, {"Vendor": "Third Generation Partnership Project (3GPP)", "Description": "", "Country": "France", "AID": "A0000000871002FF49FF0589", "Type": "USIM", "Name": "Telenor USIM"}, {"Vendor": "Buypass AS", "Description": "Used by norwegian public betting company Norsk-Tipping?", "Country": "Norway", "AID": "A00000008810200105C100", "Type": "BuyPass", "Name": "BuyPass BIDA"}, {"Vendor": "Buypass AS", "Description": "", "Country": "Norway", "AID": "A000000088102201034221", "Type": "BuyPass", "Name": "BuyPass BEID (BuyPass Electronic ID?)"}, {"Vendor": "Buypass AS", "Description": "", "Country": "Norway", "AID": "A000000088102201034321", "Type": "BuyPass", "Name": "BuyPass BEID (BuyPass Electronic ID?)"}, {"Vendor": "Sa Proton World International N.V.", "Description": "Proton, which is owned in part by Visa International and American Express Co., is in three other European countries: the original Proton program in Belgium, Chipknip in the Netherlands, and Cash in Switzerland", "Country": "Belgium", "AID": "A0000000960200", "Type": "GP", "Name": "Proton World International Security Domain"}, {"Vendor": "Visa USA", "Description": "Bank of America Debit Card", "Country": "United States", "AID": "A000000098", "Type": "EMV", "Name": "Debit Card"}, {"Vendor": "Visa USA", "Description": "", "Country": "United States", "AID": "A0000000980840", "Type": "", "Name": "Visa Common Debit"}, {"Vendor": "Visa USA", "Description": "Schwab Bank Debit Card", "Country": "United States", "AID": "A0000000980848", "Type": "EMV", "Name": "Debit Card"}, {"Vendor": "Die Post Postfinance", "Description": "", "Country": "Switzerland", "AID": "A0000001110101", "Type": "", "Name": "Postcard"}, {"Vendor": "GSA - TFCS", "Description": "CHUID", "Country": "United States", "AID": "A0000001160300", "Type": "", "Name": "PIV CHUID"}, {"Vendor": "GSA - TFCS", "Description": "Fingerprints", "Country": "United States", "AID": "A0000001166010", "Type": "", "Name": "PIV Fingerprints"}, {"Vendor": "GSA - TFCS", "Description": "Facial Image", "Country": "United States", "AID": "A0000001166030", "Type": "", "Name": "PIV Facial Image"}, {"Vendor": "GSA - TFCS", "Description": "Security Object", "Country": "United States", "AID": "A0000001169000", "Type": "", "Name": "PIV Security Object"}, {"Vendor": "GSA - TFCS", "Description": "PIV Authentication Key", "Country": "United States", "AID": "A000000116A001", "Type": "", "Name": "PIV Authentication Key"}, {"Vendor": "GSA - TFCS", "Description": "Card Capability Container", "Country": "United States", "AID": "A000000116DB00", "Type": "", "Name": "CCC"}, {"Vendor": "Austria Card", "Description": "Domestic Loyalty Program (Version 1.3)", "Country": "Austria", "AID": "A000000118010000", "Type": "", "Name": "DF_Verkehr"}, {"Vendor": "Austria Card", "Description": "Domestic Loyalty Program (Version 1.3)", "Country": "Austria", "AID": "A000000118020000", "Type": "", "Name": "DF_Partner"}, {"Vendor": "Austria Card", "Description": "Domestic Loyalty Program (Version 1.3)", "Country": "Austria", "AID": "A000000118030000", "Type": "", "Name": "DF_Schlerdaten"}, {"Vendor": "Austria Card", "Description": "Domestic Loyalty Program (Version 1.32)", "Country": "Austria", "AID": "A000000118040000", "Type": "", "Name": "DF_KEP_SIG"}, {"Vendor": "Austria Card", "Description": "Digital Signature Application", "Country": "Austria", "AID": "A0000001184543", "Type": "", "Name": "Digital Signature (SSCA)"}, {"Vendor": "Austria Card", "Description": "Encryption Application (Version 1.10)", "Country": "Austria", "AID": "A000000118454E", "Type": "", "Name": "Encryption Application"}, {"Vendor": "PBS Danmark A/S", "Description": "Danish domestic debit card", "Country": "Denmark", "AID": "A0000001211010", "Type": "EMV", "Name": "Dankort (VISA GEM Vision)"}, {"Vendor": "Java Card Forum", "Description": "", "Country": "United States", "AID": "A0000001320001", "Type": "", "Name": "org.javacardforum.javacard.biometry"}, {"Vendor": "TDS TODOS DATA SYSTEM AB", "Description": "", "Country": "Sweden", "AID": "A0000001408001", "Type": "", "Name": "eCode"}, {"Vendor": "Associazione Bancaria Italiana", "Description": "CoGeBan Consorzio BANCOMAT (Italian domestic debit card)", "Country": "Italy", "AID": "A0000001410001", "Type": "EMV", "Name": "PagoBANCOMAT"}, {"Vendor": "GlobalPlatform, Inc.", "Description": "GP Card Manager", "Country": "United States", "AID": "A0000001510000", "Type": "GP", "Name": "Global Platform Security Domain AID"}, {"Vendor": "GlobalPlatform, Inc.", "Description": "SPCASD", "Country": "United States", "AID": "A00000015153504341534400", "Type": "GP", "Name": "CASD_AID"}, {"Vendor": "Diners Club International Ltd.", "Description": "Discover Card", "Country": "United States", "AID": "A0000001523010", "Type": "EMV", "Name": "Discover, Pulse D Pas"}, {"Vendor": "Diners Club International Ltd.", "Description": "Discover Debit Common Card", "Country": "United States", "AID": "A0000001524010", "Type": "EMV", "Name": "Discover"}, {"Vendor": "Banrisul - Banco do Estado do Rio Grande do SUL - S.A.", "Description": "Banrisul (Brazil)", "Country": "Brazil", "AID": "A0000001544442", "Type": "EMV", "Name": "Banricompras Debito"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A0000001570010", "Type": "", "Name": "AMEX"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A0000001570020", "Type": "", "Name": "MasterCard"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A0000001570021", "Type": "", "Name": "Maestro"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A0000001570022", "Type": "", "Name": "Maestro"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A0000001570023", "Type": "", "Name": "CASH"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A0000001570030", "Type": "", "Name": "VISA"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A0000001570031", "Type": "", "Name": "VISA"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A0000001570040", "Type": "", "Name": "JCB"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A0000001570050", "Type": "", "Name": "Postcard"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A0000001570051", "Type": "", "Name": "Postcard"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A0000001570100", "Type": "", "Name": "MCard"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A0000001570104", "Type": "", "Name": "MyOne"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A0000001570109", "Type": "", "Name": "Mediamarkt Card"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A000000157010A", "Type": "", "Name": "Gift Card"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A000000157010B", "Type": "", "Name": "Bonuscard"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A000000157010C", "Type": "", "Name": "WIRCard"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A000000157010D", "Type": "", "Name": "Power Card"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A0000001574443", "Type": "", "Name": "DINERS CLUB"}, {"Vendor": "Zhlke Engineering AG", "Description": "", "Country": "Switzerland", "AID": "A0000001574444", "Type": "", "Name": "Supercard Plus"}, {"Vendor": "IBM", "Description": "identify in JCOP-tools returns eg 27 34 01 2E 00 00 00 00 4E 58 37 35 31 41 00 03 28 62 B3 6A 82", "Country": "Germany", "AID": "A000000167413000FF", "Type": "JCOP", "Name": "JCOP Identify Applet"}, {"Vendor": "IBM", "Description": "?", "Country": "Germany", "AID": "A000000167413001", "Type": "", "Name": "FIPS 140-2"}, {"Vendor": "Financial Information Service Co. Ltd.", "Description": "The Bankers Association of the Republic of China", "Country": "Taiwan", "AID": "A000000172950001", "Type": "EMV", "Name": "BAROC Financial Application Taiwan"}, {"Vendor": "Ministre de L'Intrieur", "Description": "", "Country": "Belgium", "AID": "A000000177504B43532D3135", "Type": "", "Name": "BelPIC (Belgian Personal Identity Card)"}, {"Vendor": "Post Office Limited", "Description": "", "Country": "United Kingdom", "AID": "A0000001850002", "Type": "EMV", "Name": "UK Post Office Account card"}, {"Vendor": "Diners Club Switzerland Ltd", "Description": "", "Country": "Switzerland", "AID": "A0000001884443", "Type": "", "Name": "DINERS CLUB"}, {"Vendor": "Association for Payment Clearing Services", "Description": "", "Country": "United Kingdom", "AID": "A0000002040000", "Type": "", "Name": "?"}, {"Vendor": "Saudi Arabian Monetary Agency (SAMA)", "Description": "SPAN2 (Saudi Payments Network) - Saudi Arabia domestic credit/debit card (Saudi Arabia Monetary Agency)", "Country": "Kingdom of Saudi Arabia", "AID": "A0000002281010", "Type": "EMV", "Name": "SPAN (M/Chip)"}, {"Vendor": "Saudi Arabian Monetary Agency (SAMA)", "Description": "SPAN2 (Saudi Payments Network) - Saudi Arabia domestic credit/debit card (Saudi Arabia Monetary Agency)", "Country": "Kingdom of Saudi Arabia", "AID": "A0000002282010", "Type": "EMV", "Name": "SPAN (VIS)"}, {"Vendor": "Saudi Arabian Monetary Agency (SAMA)", "Description": "SPAN2 (Saudi Payments Network) - Saudi Arabia domestic credit/debit card (Saudi Arabia Monetary Agency)", "Country": "Kingdom of Saudi Arabia", "AID": "A00000022820101010", "Type": "", "Name": "SPAN"}, {"Vendor": "ISO JTC1/SC17/WG3", "Description": "Electronic (Biometric) Passport. Issuer stored data application (The last three digits of the PIX shall be used to denote future version levels.)", "Country": "United Kingdom", "AID": "A0000002471001", "Type": "MRTD", "Name": "Machine Readable Travel Documents (MRTD)"}, {"Vendor": "ISO JTC1/SC17/WG3", "Description": "Electronic (Biometric) Passport. Application for hashes, digital signature, and certificate (The last three digits of the PIX shall be used to denote future version levels.)", "Country": "United Kingdom", "AID": "A0000002472001", "Type": "MRTD", "Name": "Machine Readable Travel Documents (MRTD)"}, {"Vendor": "Interac Association", "Description": "Canadian domestic credit/debit card", "Country": "Canada", "AID": "A0000002771010", "Type": "EMV", "Name": "INTERAC"}, {"Vendor": "PS/SC Workgroup", "Description": "Possibly not an application...", "Country": "United States", "AID": "A00000030600000000000000", "Type": "", "Name": "PC/SC Initial access data AID"}, {"Vendor": "National Institute of Standards and Technology", "Description": "PIV End Point Applet. Last 2 bytes designate version?", "Country": "United States", "AID": "A000000308000010000100", "Type": "", "Name": "Personal Identity Verification (PIV) / ID-ONE PIV BIO"}, {"Vendor": "Currence Holding/PIN BV", "Description": "", "Country": "The Netherlands", "AID": "A00000031510100528", "Type": "EMV", "Name": "Currence PuC"}, {"Vendor": "Currence Holding/PIN BV", "Description": "", "Country": "The Netherlands", "AID": "A0000003156020", "Type": "EMV", "Name": "Chipknip"}, {"Vendor": "Identity Alliance", "Description": "http://osdir.com/ml/lib.muscle/2005-12/msg00066.html", "Country": "United States", "AID": "A00000032301", "Type": "", "Name": "MUSCLE Applet Package"}, {"Vendor": "Identity Alliance", "Description": "http://osdir.com/ml/lib.muscle/2005-12/msg00066.html", "Country": "United States", "AID": "A0000003230101", "Type": "", "Name": "MUSCLE Applet Instance"}, {"Vendor": "Discover Financial Services LLC", "Description": "", "Country": "United States", "AID": "A0000003241010", "Type": "", "Name": "Discover Expresspay (ZIP)"}, {"Vendor": "China Unionpay Co. Ltd", "Description": "", "Country": "China", "AID": "A000000333010101", "Type": "", "Name": "UnionPay Debit"}, {"Vendor": "China Unionpay Co. Ltd", "Description": "", "Country": "China", "AID": "A000000333010102", "Type": "", "Name": "UnionPay Credit"}, {"Vendor": "China Unionpay Co. Ltd", "Description": "", "Country": "China", "AID": "A000000333010103", "Type": "", "Name": "UnionPay Quasi Credit"}, {"Vendor": "China Unionpay Co. Ltd", "Description": "", "Country": "China", "AID": "A000000333010106", "Type": "", "Name": "UnionPay Electronic Cash"}, {"Vendor": "China Unionpay Co. Ltd", "Description": "", "Country": "China", "AID": "A000000333010108", "Type": "", "Name": "U.S. UnionPay Common Debit AID"}, {"Vendor": "Euro Alliance of Payment Schemes s.c.r.l. - EAPS", "Description": "Unknown", "Country": "Belgium", "AID": "A0000003591010", "Type": "", "Name": ""}, {"Vendor": "Euro Alliance of Payment Schemes s.c.r.l. - EAPS", "Description": "ZKA (Germany)", "Country": "Belgium", "AID": "A0000003591010028001", "Type": "EMV", "Name": "Girocard EAPS"}, {"Vendor": "Euro Alliance of Payment Schemes s.c.r.l. - EAPS", "Description": "PagoBANCOMAT", "Country": "Belgium", "AID": "A00000035910100380", "Type": "", "Name": ""}, {"Vendor": "Poste Italiane S.P.A", "Description": "", "Country": "Italy", "AID": "A0000003660001", "Type": "", "Name": "Postamat"}, {"Vendor": "Poste Italiane S.P.A", "Description": "", "Country": "Italy", "AID": "A0000003660002", "Type": "", "Name": "Postamat VISA"}, {"Vendor": "Interswitch Limited", "Description": "Nigerian local switch company", "Country": "Nigeria", "AID": "A0000003710001", "Type": "EMV", "Name": "InterSwitch Verve Card"}, {"Vendor": "NXP Semiconductors Germany GmbH", "Description": "NXP Mf4M", "Country": "Germany", "AID": "A0000003964D66344D0002", "Type": "", "Name": "MIFARE4MOBILE"}, {"Vendor": "Microsoft Corporation", "Description": "Identity Device With Microsoft Generic Profile application. 2 bytes can be added at the end. This byte must be set to the IDMP specification revision number which is currently 0x01. The second byte (yy) is reserved for use by the card application.", "Country": "United States", "AID": "A00000039742544659", "Type": "", "Name": "Microsoft IDMP AID"}, {"Vendor": "Microsoft Corporation", "Description": "MS Plug and Play", "Country": "United States", "AID": "A0000003974349445F0100", "Type": "", "Name": "Microsoft PNP AID"}, {"Vendor": "Unibanco (Hipercard)", "Description": "", "Country": "Brazil", "AID": "A0000004271010", "Type": "", "Name": "Hiperchip"}, {"Vendor": "100", "Description": "", "Country": "Russia", "AID": "A0000004320001", "Type": "", "Name": "Universal Electronic Card"}, {"Vendor": "Edenred", "Description": "", "Country": "Belgium", "AID": "A0000004360100", "Type": "", "Name": "Ticket Restaurant"}, {"Vendor": "ACCEL/Exchange", "Description": "The Exchange Network ATM Network", "Country": "United States", "AID": "A0000004391010", "Type": "", "Name": "Exchange ATM card"}, {"Vendor": "eTranzact", "Description": "Nigerian local switch company", "Country": "Nigeria", "AID": "A0000004540010", "Type": "EMV", "Name": "Etranzact Genesis Card"}, {"Vendor": "eTranzact", "Description": "Nigerian local switch company", "Country": "Nigeria", "AID": "A0000004540011", "Type": "EMV", "Name": "Etranzact Genesis Card 2"}, {"Vendor": "Google", "Description": "GOOGLE_LOCKET_AID", "Country": "United States", "AID": "A0000004762010", "Type": "", "Name": "GOOGLE_CONTROLLER_AID"}, {"Vendor": "Google", "Description": "", "Country": "United States", "AID": "A0000004763030", "Type": "", "Name": "GOOGLE_MIFARE_MANAGER_AID"}, {"Vendor": "Google", "Description": "", "Country": "United States", "AID": "A0000004766C", "Type": "EMV", "Name": "GOOGLE_PAYMENT_AID"}, {"Vendor": "Google", "Description": "", "Country": "United States", "AID": "A000000476A010", "Type": "GP", "Name": "GSD_MANAGER_AID"}, {"Vendor": "Google", "Description": "", "Country": "United States", "AID": "A000000476A110", "Type": "GP", "Name": "GSD_MANAGER_AID"}, {"Vendor": "JVL Ventures, LLC (Softcard)", "Description": "", "Country": "United States", "AID": "A000000485", "Type": "", "Name": "Softcard SmartTap"}, {"Vendor": "RuPay", "Description": "RuPay (India)", "Country": "India", "AID": "A0000005241010", "Type": "EMV", "Name": "RuPay"}, {"Vendor": "Yubico", "Description": "Universal 2-Factor Proof-of-concept/Demo", "Country": "Sweden", "AID": "A0000005271002", "Type": "YKNEO", "Name": "Yubikey NEO U2F Demo applet"}, {"Vendor": "Yubico", "Description": "Javacard Applet AID", "Country": "Sweden", "AID": "A000000527200101", "Type": "YKNEO", "Name": "Yubikey NEO Yubikey2 applet interface"}, {"Vendor": "Yubico", "Description": "Javacard Applet AID", "Country": "Sweden", "AID": "A000000527210101", "Type": "YKNEO", "Name": "Yubikey NEO OATH Applet"}, {"Vendor": "GSMA (GSM Association)", "Description": "", "Country": "United Kingdom", "AID": "A0000005591010FFFFFFFF8900000100", "Type": "", "Name": "ISD-R Application. Used as TAR."}, {"Vendor": "GSMA (GSM Association)", "Description": "", "Country": "United Kingdom", "AID": "A0000005591010FFFFFFFF8900000200", "Type": "", "Name": "ECASD Application. Used as TAR."}, {"Vendor": "GSMA (GSM Association)", "Description": "", "Country": "United Kingdom", "AID": "A0000005591010FFFFFFFF8900000D00", "Type": "", "Name": "ISD-P Executable Load File."}, {"Vendor": "GSMA (GSM Association)", "Description": "", "Country": "United Kingdom", "AID": "A0000005591010FFFFFFFF8900000E00", "Type": "", "Name": "ISD-P Executable Module."}, {"Vendor": "GSMA (GSM Association)", "Description": "", "Country": "United Kingdom", "AID": "A0000005591010FFFFFFFF8900000F00", "Type": "", "Name": "Reserved value for the Profile's ISD-P"}, {"Vendor": "GSMA (GSM Association)", "Description": "", "Country": "United Kingdom", "AID": "A0000005591010FFFFFFFF8900001000", "Type": "", "Name": "ISD-P Application ('1010FFFFFFFF89000010' to '1010FFFFFFFF8900FFFF'. Used as TAR. The value is allocated during the 'Profile Download and Installation procedure'"}, {"Vendor": "Fidesmo", "Description": "", "Country": "Sweden", "AID": "A00000061700", "Type": "", "Name": "Fidesmo javacard"}, {"Vendor": "Debit Network Alliance (DNA)", "Description": "Common U.S. Debit", "Country": "United States", "AID": "A0000006200620", "Type": "", "Name": "Debit Network Alliance (DNA)"}, {"Vendor": "MIR", "Description": "", "Country": "Russia", "AID": "A0000006581010", "Type": "", "Name": "MIR Credit"}, {"Vendor": "MIR", "Description": "", "Country": "Russia", "AID": "A0000006582010", "Type": "", "Name": "MIR Debit"}, {"Vendor": "TROY", "Description": "Turkey's Payment Method", "Country": "Turkey", "AID": "A0000006723010", "Type": "EMV", "Name": "TROY chip credit card"}, {"Vendor": "TROY", "Description": "Turkey's Payment Method", "Country": "Turkey", "AID": "A0000006723020", "Type": "EMV", "Name": "TROY chip debit card"}, {"Vendor": "Indian Oil Corporation Limited", "Description": "Indian Oils Pre Paid Program", "Country": "India", "AID": "A0000007705850", "Type": "EMV", "Name": "XTRAPOWER Fleet Card Program"}, {"Vendor": "MasterCard International", "Description": "Used for development", "Country": "United States", "AID": "B012345678", "Type": "EMV", "Name": "Maestro TEST"}, {"Vendor": "Paylife", "Description": "Domestic Payment System (Version 2.1)", "Country": "Austria", "AID": "D040000001000002", "Type": "", "Name": "Paylife Quick (IEP). Preloaded Electronic Purse"}, {"Vendor": "Austria Card", "Description": "Domestic Payment System (Version 2.1)", "Country": "Austria", "AID": "D040000002000002", "Type": "", "Name": "RFU"}, {"Vendor": "Austria Card", "Description": "Domestic Payment System (Version 2.1)", "Country": "Austria", "AID": "D040000003000002", "Type": "", "Name": "POS"}, {"Vendor": "Austria Card", "Description": "Domestic Payment System (Version 2.1)", "Country": "Austria", "AID": "D040000004000002", "Type": "", "Name": "ATM"}, {"Vendor": "Austria Card", "Description": "Domestic Loyalty Program (Version 2.1)", "Country": "Austria", "AID": "D04000000B000002", "Type": "", "Name": "Retail"}, {"Vendor": "Austria Card", "Description": "Domestic Loyalty Program (Version 2.1)", "Country": "Austria", "AID": "D04000000C000002", "Type": "", "Name": "Bank_Data"}, {"Vendor": "Austria Card", "Description": "Domestic Loyalty Program (Version 2.1)", "Country": "Austria", "AID": "D04000000D000002", "Type": "", "Name": "Shopping"}, {"Vendor": "Austria Card", "Description": "Domestic Loyalty Program (Version 2.0)", "Country": "Austria", "AID": "D040000013000001", "Type": "", "Name": "DF_UNI_Kepler1"}, {"Vendor": "Austria Card", "Description": "Domestic Loyalty Program (Version 1.3)", "Country": "Austria", "AID": "D040000013000001", "Type": "", "Name": "DF_Schler1"}, {"Vendor": "Austria Card", "Description": "Domestic Loyalty Program (Version 2.0)", "Country": "Austria", "AID": "D040000013000002", "Type": "", "Name": "DF_UNI_Kepler2"}, {"Vendor": "Austria Card", "Description": "Domestic Loyalty Program (Version 1.3)", "Country": "Austria", "AID": "D040000013000002", "Type": "", "Name": "DF_Schler2"}, {"Vendor": "Austria Card", "Description": "Domestic Loyalty Program (Version 2.0)", "Country": "Austria", "AID": "D040000014000001", "Type": "", "Name": "DF_Mensa"}, {"Vendor": "Austria Card", "Description": "Domestic Loyalty Program (Version 2.0)", "Country": "Austria", "AID": "D040000015000001", "Type": "", "Name": "DF_UNI_Ausweis"}, {"Vendor": "Austria Card", "Description": "Domestic Loyalty Program (Version 1.3)", "Country": "Austria", "AID": "D040000015000001", "Type": "", "Name": "DF_Ausweis"}, {"Vendor": "Austria Card", "Description": "Domestic EMV Application (Version 2.1)", "Country": "Austria", "AID": "D0400000190001", "Type": "", "Name": "EMV ATM Maestro"}, {"Vendor": "Austria Card", "Description": "Domestic EMV Application (Version 2.1)", "Country": "Austria", "AID": "D0400000190002", "Type": "", "Name": "EMV POS Maestro"}, {"Vendor": "Austria Card", "Description": "Domestic EMV Application (Version 2.1)", "Country": "Austria", "AID": "D0400000190003", "Type": "", "Name": "EMV ATM MasterCard"}, {"Vendor": "Austria Card", "Description": "Domestic EMV Application (Version 2.1)", "Country": "Austria", "AID": "D0400000190004", "Type": "", "Name": "EMV POS MasterCard"}, {"Vendor": "Austria Card", "Description": "Domestic Payment System (Version 2.1)", "Country": "Austria", "AID": "D0400000190010", "Type": "", "Name": "Digital ID"}, {"Vendor": "Ministry of Finance of Georgia", "Description": "Georgia Revenue Service application for fiscal cash registers", "Country": "Georgia", "AID": "D268000001", "Type": "", "Name": "Fiscal module application"}, {"Vendor": "Giesecke&Devrient", "Description": "Giesecke & Devrient", "Country": "Germany", "AID": "D276000005", "Type": "", "Name": ""}, {"Vendor": "Giesecke&Devrient", "Description": "", "Country": "Germany", "AID": "D276000005AA040360010410", "Type": "", "Name": "G D App Nokia 6212"}, {"Vendor": "Giesecke&Devrient", "Description": "", "Country": "Germany", "AID": "D276000005AA0503E00401", "Type": "", "Name": "G D App Nokia 6212"}, {"Vendor": "Giesecke&Devrient", "Description": "", "Country": "Germany", "AID": "D276000005AA0503E00501", "Type": "", "Name": "G D App Nokia 6212"}, {"Vendor": "Giesecke&Devrient", "Description": "", "Country": "Germany", "AID": "D276000005AA0503E0050101", "Type": "", "Name": "G D App Nokia 6212"}, {"Vendor": "Giesecke&Devrient", "Description": "", "Country": "Germany", "AID": "D276000005AB0503E0040101", "Type": "", "Name": "G D App Nokia 6212"}, {"Vendor": "IBM Laboratories", "Description": "IBM Test card from the book 'Smart Card Application Development Using Java'", "Country": "Germany", "AID": "D27600002200000001", "Type": "", "Name": "SCT LOYALTY"}, {"Vendor": "IBM Laboratories", "Description": "IBM Test card from the book 'Smart Card Application Development Using Java'", "Country": "Germany", "AID": "D27600002200000002", "Type": "", "Name": "BUSINESS CARD"}, {"Vendor": "IBM Laboratories", "Description": "IBM Test card from the book 'Smart Card Application Development Using Java'", "Country": "Germany", "AID": "D27600002200000060", "Type": "", "Name": "PKCS#11 Token"}, {"Vendor": "ZKA", "Description": "Girocard (Geldkarte) in Germany", "Country": "Germany", "AID": "D276000025", "Type": "", "Name": "Girocard"}, {"Vendor": "ZKA", "Description": "Unknown", "Country": "Germany", "AID": "D27600002545410100", "Type": "", "Name": ""}, {"Vendor": "ZKA", "Description": "ZKA Girocard (Geldkarte) (Germany)", "Country": "Germany", "AID": "D27600002545500100", "Type": "EMV", "Name": "Girocard"}, {"Vendor": "ZKA", "Description": "", "Country": "Germany", "AID": "D27600002547410100", "Type": "", "Name": "Girocard ATM"}, {"Vendor": "Wolfgang Rankl", "Description": "", "Country": "Germany", "AID": "D276000060", "Type": "", "Name": ""}, {"Vendor": "NXP Semiconductors / NFC Forum", "Description": "NFC Forum Type 4 Tag", "Country": "Germany", "AID": "D2760000850100", "Type": "", "Name": "NDEF Tag Application / Mifare DESFire Tag Application"}, {"Vendor": "NXP Semiconductors / NFC Forum", "Description": "NFC Tag type 4 tag", "Country": "Germany", "AID": "D2760000850101", "Type": "", "Name": "NDEF Tag Application"}, {"Vendor": "Giesecke&Devrient Java Card Telecommunikation", "Description": "", "Country": "Germany", "AID": "D276000118", "Type": "", "Name": ""}, {"Vendor": "Giesecke&Devrient Java Card Telecommunikation", "Description": "Devrient Test Applet?", "Country": "Germany", "AID": "D2760001180101", "Type": "", "Name": "Giesecke &"}, {"Vendor": "fsfEurope", "Description": "For selection when not knowing the exact full AID", "Country": "Germany", "AID": "D27600012401", "Type": "OpenPGP", "Name": "OpenPGP Card"}, {"Vendor": "fsfEurope", "Description": "Version 1", "Country": "Germany", "AID": "D276000124010101FFFF000000010000", "Type": "OpenPGP", "Name": "OpenPGP Card"}, {"Vendor": "fsfEurope", "Description": "Version 2", "Country": "Germany", "AID": "D2760001240102000000000000010000", "Type": "OpenPGP", "Name": "OpenPGP Card"}, {"Vendor": "fsfEurope", "Description": "http://smartchess.de/englisch/SmartChess_1.0.pdf", "Country": "Germany", "AID": "D27600012402", "Type": "SmartChess", "Name": "SmartChess"}, {"Vendor": "fsfEurope", "Description": "http://smartchess.de/englisch/SmartChess_1.0.pdf", "Country": "Germany", "AID": "D2760001240200010000000000000000", "Type": "SmartChess", "Name": "SmartChess"}, {"Vendor": "", "Description": "", "Country": "Republic of Korea", "AID": "D4100000011010", "Type": "", "Name": ""}, {"Vendor": "", "Description": "(Netherlands)", "Country": "The Netherlands", "AID": "D5280050218002", "Type": "EMV", "Name": "?"}, {"Vendor": "Bankaxept", "Description": "Norwegian domestic debit card", "Country": "Norway", "AID": "D5780000021010", "Type": "EMV", "Name": "Bankaxept"}, {"Vendor": "Swiss Travel Fund (Reka)", "Description": "prepaid functional debit card", "Country": "Switzerland", "AID": "D7560000010101", "Type": "", "Name": "Reka Card"}, {"Vendor": "Migros (FCM, GE Money Bank and MasterCard)", "Description": "", "Country": "Switzerland", "AID": "D7560000300101", "Type": "", "Name": "M Budget"}, {"Vendor": "", "Description": "German eID", "Country": "", "AID": "E80704007F00070302", "Type": "", "Name": "nPA"}, {"Vendor": "", "Description": "", "Country": "", "AID": "E82881C11702", "Type": "", "Name": "AlphaCard application"}, {"Vendor": "", "Description": "Iso adoption of PKCS-15", "Country": "", "AID": "E828BD080F", "Type": "", "Name": "ISO-7816-15 EF.DIR"}, {"Vendor": "", "Description": "Brazilian Bank Banco Bradesco", "Country": "", "AID": "F0000000030001", "Type": "EMV", "Name": "BRADESCO"}] \ No newline at end of file diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 9ce554ce2..6d7741153 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -914,7 +914,7 @@ static command_t CommandTable[] = }; int CmdHFFido(const char *Cmd) { - (void)WaitForResponseTimeout(CMD_ACK,NULL,100); + (void)WaitForResponseTimeout(CMD_ACK, NULL, 100); CmdsParse(CommandTable, Cmd); return 0; } diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 1ba59dced..a5a20f5e2 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -8,6 +8,7 @@ // Proxmark3 RDV40 Smartcard module commands //----------------------------------------------------------------------------- #include "cmdsmartcard.h" +#include "../emv/emvjson.h" static int CmdHelp(const char *Cmd); @@ -24,6 +25,9 @@ int usage_sm_raw(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " sc raw s 0 d 00a404000e315041592e5359532e4444463031 - `1PAY.SYS.DDF01` PPSE directory with get ATR"); PrintAndLogEx(NORMAL, " sc raw 0 d 00a404000e325041592e5359532e4444463031 - `2PAY.SYS.DDF01` PPSE directory"); + PrintAndLogEx(NORMAL, " sc raw 0 t d 00a4040007a000000004101000 - Mastercard"); + PrintAndLogEx(NORMAL, " sc raw 0 t d 00a4040007a0000000031010 - Visa"); + return 0; } int usage_sm_reader(void) { @@ -64,15 +68,48 @@ int usage_sm_setclock(void) { return 0; } int usage_sm_brute(void) { - PrintAndLogEx(NORMAL, "Tries to bruteforce SFI, "); + PrintAndLogEx(NORMAL, "Tries to bruteforce SFI, using a known list of AID's "); PrintAndLogEx(NORMAL, "Usage: sc brute [h]"); PrintAndLogEx(NORMAL, " h : this help"); + PrintAndLogEx(NORMAL, " t : executes TLV decoder if it possible"); +// PrintAndLogEx(NORMAL, " 0 : use protocol T=0"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " sc brute"); + PrintAndLogEx(NORMAL, " sc brute t"); return 0; } +static int smart_loadjson(const char *preferredName, const char *suffix, json_t **root) { + + json_error_t error; + + if ( preferredName == NULL ) return 1; + if ( suffix == NULL ) return 1; + + int retval = 0; + int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10); + char * fileName = calloc(size, sizeof(char)); + sprintf(fileName, "%s.%s", preferredName, suffix); + + *root = json_load_file(fileName, 0, &error); + if (!*root) { + PrintAndLogEx(ERR, "json (%s) error on line %d: %s", fileName, error.line, error.text); + retval = 2; + goto out; + } + + if (!json_is_array(*root)) { + PrintAndLogEx(ERR, "Invalid json (%s) format. root must be an array.", fileName); + retval = 3; + goto out; + } + + PrintAndLogEx(SUCCESS, "Loaded file (%s) OK.", fileName); +out: + free(fileName); + return retval; +} + uint8_t GetATRTA1(uint8_t *atr, size_t atrlen) { if (atrlen > 2) { uint8_t T0 = atr[1]; @@ -142,19 +179,16 @@ float FArray[] = { int GetATRDi(uint8_t *atr, size_t atrlen) { uint8_t TA1 = GetATRTA1(atr, atrlen); - - return DiArray[TA1 & 0x0f]; // The 4 low-order bits of TA1 (4th MSbit to 1st LSbit) encode Di + return DiArray[TA1 & 0x0F]; // The 4 low-order bits of TA1 (4th MSbit to 1st LSbit) encode Di } int GetATRFi(uint8_t *atr, size_t atrlen) { uint8_t TA1 = GetATRTA1(atr, atrlen); - return FiArray[TA1 >> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi } float GetATRF(uint8_t *atr, size_t atrlen) { uint8_t TA1 = GetATRTA1(atr, atrlen); - return FArray[TA1 >> 4]; // The 4 high-order bits of TA1 (8th MSbit to 5th LSbit) encode fmax and Fi } @@ -284,31 +318,31 @@ static bool smart_select(bool silent) { return true; } -static int smart_wait(uint8_t *data) { +static int smart_wait(uint8_t *data, bool silent) { UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - PrintAndLogEx(WARNING, "smart card response timeout"); + if (!silent) PrintAndLogEx(WARNING, "smart card response timeout"); return -1; } uint32_t len = resp.arg[0]; if ( !len ) { - PrintAndLogEx(WARNING, "smart card response failed"); + if (!silent) PrintAndLogEx(WARNING, "smart card response failed"); return -2; } memcpy(data, resp.d.asBytes, len); if (len >= 2) { - PrintAndLogEx(SUCCESS, "%02X%02X | %s", data[len - 2], data[len - 1], GetAPDUCodeDescription(data[len - 2], data[len - 1])); + if (!silent) PrintAndLogEx(SUCCESS, "%02X%02X | %s", data[len - 2], data[len - 1], GetAPDUCodeDescription(data[len - 2], data[len - 1])); } else { - PrintAndLogEx(SUCCESS, " %d | %s", len, sprint_hex_inrow_ex(data, len, 8)); + if (!silent) PrintAndLogEx(SUCCESS, " %d | %s", len, sprint_hex_inrow_ex(data, len, 8)); } return len; } -static int smart_response(uint8_t *data) { +static int smart_responseEx(uint8_t *data, bool silent) { - int datalen = smart_wait(data); + int datalen = smart_wait(data, silent); bool needGetData = false; if (datalen < 2 ) { @@ -321,14 +355,14 @@ static int smart_response(uint8_t *data) { if (needGetData) { int len = data[datalen - 1]; - PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len); + if (!silent) PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len); uint8_t getstatus[] = {0x00, ISO7816_GETSTATUS, 0x00, 0x00, len}; UsbCommand cStatus = {CMD_SMART_RAW, {SC_RAW, sizeof(getstatus), 0}}; memcpy(cStatus.d.asBytes, getstatus, sizeof(getstatus) ); clearCommandBuffer(); SendCommand(&cStatus); - datalen = smart_wait(data); + datalen = smart_wait(data, silent); if (datalen < 2 ) { goto out; @@ -339,7 +373,9 @@ static int smart_response(uint8_t *data) { // data with ACK if (datalen == len + 2 + 1) { // 2 - response, 1 - ACK if (data[0] != ISO7816_GETSTATUS) { - PrintAndLogEx(ERR, "GetResponse ACK error. len 0x%x | data[0] %02X", len, data[0]); + if (!silent) { + PrintAndLogEx(ERR, "GetResponse ACK error. len 0x%x | data[0] %02X", len, data[0]); + } datalen = 0; goto out; } @@ -348,7 +384,9 @@ static int smart_response(uint8_t *data) { memmove(data, &data[1], datalen); } else { // wrong length - PrintAndLogEx(WARNING, "GetResponse wrong length. Must be 0x%02X got 0x%02X", len, datalen - 3); + if (!silent) { + PrintAndLogEx(WARNING, "GetResponse wrong length. Must be 0x%02X got 0x%02X", len, datalen - 3); + } } } } @@ -357,6 +395,10 @@ out: return datalen; } +static int smart_response(uint8_t *data) { + return smart_responseEx(data, false); +} + int CmdSmartRaw(const char *Cmd) { int hexlen = 0; @@ -488,7 +530,7 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave clearCommandBuffer(); SendCommand(&c); - int len = smart_response(dataout); + int len = smart_responseEx(dataout, true); if ( len < 0 ) { return 2; @@ -505,11 +547,10 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave clearCommandBuffer(); SendCommand(&c2); - len = smart_response(dataout); + len = smart_responseEx(dataout, true); } *dataoutlen = len; - return 0; } @@ -679,14 +720,14 @@ int CmdSmartInfo(const char *Cmd){ if (GetATRTA1(card.atr, card.atr_len) == 0x11) PrintAndLogEx(INFO, "Using default values..."); - PrintAndLogEx(NORMAL, "\t- Di=%d", Di); - PrintAndLogEx(NORMAL, "\t- Fi=%d", Fi); - PrintAndLogEx(NORMAL, "\t- F=%.1f MHz", F); + PrintAndLogEx(NORMAL, "\t- Di %d", Di); + PrintAndLogEx(NORMAL, "\t- Fi %d", Fi); + PrintAndLogEx(NORMAL, "\t- F %.1f MHz", F); if (Di && Fi) { - PrintAndLogEx(NORMAL, "\t- Cycles/ETU=%d", Fi/Di); + PrintAndLogEx(NORMAL, "\t- Cycles/ETU %d", Fi/Di); PrintAndLogEx(NORMAL, "\t- %.1f bits/sec at 4MHz", (float)4000000 / (Fi/Di)); - PrintAndLogEx(NORMAL, "\t- %.1f bits/sec at Fmax=%.1fMHz", (F * 1000000) / (Fi/Di), F); + PrintAndLogEx(NORMAL, "\t- %.1f bits/sec at Fmax (%.1fMHz)", (F * 1000000) / (Fi/Di), F); } else { PrintAndLogEx(WARNING, "\t- Di or Fi is RFU."); }; @@ -798,58 +839,210 @@ int CmdSmartList(const char *Cmd) { int CmdSmartBruteforceSFI(const char *Cmd) { - char ctmp = tolower(param_getchar(Cmd, 0)); - if (ctmp == 'h') return usage_sm_brute(); - - uint8_t data[5] = {0x00, 0xB2, 0x00, 0x00, 0x00}; - - PrintAndLogEx(INFO, "Selecting card"); - if ( !smart_select(false) ) { - return 1; + uint8_t cmdp = 0; + bool errors = false, decodeTLV = false; //, useT0 = false; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': return usage_sm_brute(); + case 't': + decodeTLV = true; + cmdp++; + break; +/* + case '0': + useT0 = true; + cmdp++; + break; +*/ + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } } - PrintAndLogEx(INFO, "Selecting PPSE aid"); - CmdSmartRaw("s 0 t d 00a404000e325041592e5359532e4444463031"); - CmdSmartRaw("0 t d 00a4040007a000000004101000"); // mastercard -// CmdSmartRaw("0 t d 00a4040007a0000000031010"); // visa + //Validations + if (errors) return usage_sm_brute(); + + const char *SELECT = "00a40400%02x%s"; - PrintAndLogEx(INFO, "starting"); + uint8_t READ_RECORD[] = {0x00, 0xB2, 0x00, 0x00, 0x00}; + uint8_t GET_PROCESSING_OPTIONS[] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00}; + +// uint8_t GENERATE_AC[] = {0x80, 0xAE}; +// uint8_t GET_CHALLENGE[] = {0x00, 0x84, 0x00}; +// uint8_t GET_DATA[] = {0x80, 0xCA, 0x00, 0x00, 0x00}; +// uint8_t SELECT[] = {0x00, 0xA4, 0x04, 0x00}; +// uint8_t UNBLOCK_PIN[] = {0x84, 0x24, 0x00, 0x00, 0x00}; +// uint8_t VERIFY[] = {0x00, 0x20, 0x00, 0x80}; - UsbCommand c = {CMD_SMART_RAW, {SC_RAW, sizeof(data), 0}}; + + // Select AID command + UsbCommand cAid = {CMD_SMART_RAW, {SC_RAW_T0, 0, 0}}; + + // Get processing options command + UsbCommand cOpt = {CMD_SMART_RAW, {SC_RAW_T0, sizeof(GET_PROCESSING_OPTIONS), 0}}; + memcpy(cOpt.d.asBytes, GET_PROCESSING_OPTIONS, sizeof(GET_PROCESSING_OPTIONS) ); + + // READ RECORD + UsbCommand cSFI = {CMD_SMART_RAW, {SC_RAW_T0, sizeof(READ_RECORD), 0}}; + + + PrintAndLogEx(INFO, "Importing AID list"); + json_t *root = NULL; + smart_loadjson("aidlist", "json", &root); + uint8_t* buf = malloc(USB_CMD_DATA_SIZE); if ( !buf ) return 1; - - for (uint8_t i=1; i < 4; i++) { - for (int p1=1; p1 < 5; p1++) { - - data[2] = p1; - data[3] = (i << 3) + 4; - memcpy(c.d.asBytes, data, sizeof(data) ); - clearCommandBuffer(); - SendCommand(&c); - - smart_response(buf); - - if ( buf[0] == 0x6C ) { - data[4] = buf[1]; - - memcpy(c.d.asBytes, data, sizeof(data) ); - clearCommandBuffer(); - SendCommand(&c); - uint8_t len = smart_response(buf); - - // TLV decoder - if (len > 4) - TLVPrintFromBuffer(buf+1, len-3); + uint8_t* sfibuf = malloc(USB_CMD_DATA_SIZE); + if ( !sfibuf ) + return 1; + + PrintAndLogEx(INFO, "Selecting card"); + if ( !smart_select(false) ) + return 1; + - data[4] = 0; - } - memset(buf, 0x00, USB_CMD_DATA_SIZE); + for (int i = 0; i < json_array_size(root); i++) { + json_t *data, *jaid; + + data = json_array_get(root, i); + if (!json_is_object(data)) { + PrintAndLogEx(ERR, "data %d is not an object\n", i + 1); + json_decref(root); + return 1; } - } + + jaid = json_object_get(data, "AID"); + if (!json_is_string(jaid)) { + PrintAndLogEx(ERR, "AID data [%d] is not a string", i + 1); + json_decref(root); + return 1; + } + + const char* aid = json_string_value(jaid); + if ( !aid ) continue; + + size_t aidlen = strlen(aid); + char* caid = calloc( 8+2+aidlen+1, sizeof(uint8_t)); + snprintf(caid, 8+2+aidlen+1, SELECT, aidlen >> 1, aid); + + int hexlen = 0; + int res = param_gethex_to_eol(caid, 0, cAid.d.asBytes, sizeof(cAid.d.asBytes), &hexlen); + if ( res ) continue; + + cAid.arg[1] = hexlen; + + clearCommandBuffer(); + SendCommand(&cAid); + + int len = smart_responseEx(buf, true); + if ( len < 3 ) { + free(caid); + continue; + } + + json_t *jvendor, *jname; + jvendor = json_object_get(data, "Vendor"); + if (!json_is_string(jvendor)) { + PrintAndLogEx(ERR, "Vendor data [%d] is not a string", i + 1); + continue; + } + + const char* vendor = json_string_value(jvendor); + if ( !vendor ) continue; + + jname = json_object_get(data, "Name"); + if (!json_is_string(jname)) { + PrintAndLogEx(ERR, "Name data [%d] is not a string", i + 1); + continue; + } + const char* name = json_string_value(jname); + if ( !name ) continue; + + PrintAndLogEx(SUCCESS, "AID %s | %s | %s", aid, vendor, name); + + // Get processing options + clearCommandBuffer(); + SendCommand(&cOpt); + + uint8_t optionslen = smart_responseEx(buf, true); + if ( optionslen > 4 ) { + PrintAndLogEx(SUCCESS, "Got processing options"); + if ( decodeTLV ) { + TLVPrintFromBuffer(buf, optionslen-2); + } + } else { + PrintAndLogEx(FAILED, "Getting processing options failed"); + } + + PrintAndLogEx(INFO, "Start SFI brute forcing"); + + for (uint8_t sfi=1; sfi <= 31; sfi++) { + + printf("."); fflush(stdout); + + for (uint16_t rec=1; rec <= 5; rec++) { + + if (ukbhit()) { + int gc = getchar(); (void)gc; + PrintAndLogEx(NORMAL, "\naborted via keyboard!\n"); + free(caid); + goto out; + } + + READ_RECORD[2] = rec; + READ_RECORD[3] = (sfi << 3) | 4; + + memcpy(cSFI.d.asBytes, READ_RECORD, sizeof(READ_RECORD) ); + clearCommandBuffer(); + SendCommand(&cSFI); + + uint8_t sfilen = smart_responseEx(sfibuf, true); + + if ( sfibuf[0] == 0x6C ) { + READ_RECORD[4] = sfibuf[1]; + + memcpy(cSFI.d.asBytes, READ_RECORD, sizeof(READ_RECORD) ); + clearCommandBuffer(); + SendCommand(&cSFI); + sfilen = smart_responseEx(sfibuf, true); + + READ_RECORD[4] = 0; + } + + if ( sfilen > 4 ) { + + PrintAndLogEx(SUCCESS, "\n\t file %02d, record %02d found", sfi, rec); + + uint8_t modifier = (sfibuf[0] == 0xC0) ? 1 : 0; + + if ( decodeTLV ) { + if (!TLVPrintFromBuffer(sfibuf + modifier, sfilen-2-modifier)) { + PrintAndLogEx(SUCCESS, "\tHEX: %s", sprint_hex(sfibuf, sfilen)); + } + } + + } + memset(sfibuf, 0x00, USB_CMD_DATA_SIZE); + } + } + + free(sfibuf); + free(caid); + PrintAndLogEx(SUCCESS, "\nSFI brute force done\n"); + } +out: + if ( sfibuf ) + free(sfibuf); + free(buf); + json_decref(root); + + PrintAndLogEx(SUCCESS, "Search completed."); return 0; } diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 647123faf..13f64a616 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1464,6 +1464,7 @@ int CmdEMVGetrng(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); if ( cmdp == 'h' || cmdp == 'H') return usage_emv_getrnd(); + PrintAndLogEx(INFO, "Not implemented yet"); return 0; } diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index cc2897127..63397f19e 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -259,6 +259,21 @@ static const struct emv_tag emv_tags[] = { { 0x9f4c, "ICC Dynamic Number" }, { 0x9f4d, "Log Entry" }, { 0x9f4f, "Log Format", EMV_TAG_DOL }, + + { 0x9f50, "Offline Accumulator Balance" }, + { 0x9f51, "Application Currency Code" }, + { 0x9f51, "DRDOL" }, + { 0x9f52, "Application Default Action (ADA)" }, + { 0x9f52, "Terminal Compatibility Indicator" }, + { 0x9f55, "Issuer Authentication Flags" }, + { 0x9f56, "Issuer Authentication Indicator" }, + { 0x9f57, "Issuer Country Code" }, + { 0x9f58, "Consecutive Transaction Counter Limit (CTCL)" }, + { 0x9f59, "Consecutive Transaction Counter Upper Limit (CTCUL)" }, + { 0x9f5A, "Application Program Identifier" }, + { 0x9f5b, "Issuer Script Results" }, + { 0x9f5c, "Cumulative Total Transaction Amount Upper Limit (CTTAUL)" }, + { 0x9f60, "CVC3 (Track1)" }, { 0x9f61, "CVC3 (Track2)" }, { 0x9f62, "PCVC3(Track1)" }, @@ -278,21 +293,18 @@ static const struct emv_tag emv_tags[] = { { 0xdf20, "Issuer Proprietary Bitmap (IPB)" }, }; -static int emv_sort_tag(tlv_tag_t tag) -{ +static int emv_sort_tag(tlv_tag_t tag) { return (int)(tag >= 0x100 ? tag : tag << 8); } -static int emv_tlv_compare(const void *a, const void *b) -{ +static int emv_tlv_compare(const void *a, const void *b) { const struct tlv *tlv = a; const struct emv_tag *tag = b; return emv_sort_tag(tlv->tag) - (emv_sort_tag(tag->tag)); } -static const struct emv_tag *emv_get_tag(const struct tlv *tlv) -{ +static const struct emv_tag *emv_get_tag(const struct tlv *tlv) { struct emv_tag *tag = bsearch(tlv, emv_tags, sizeof(emv_tags)/sizeof(emv_tags[0]), sizeof(emv_tags[0]), emv_tlv_compare); @@ -310,8 +322,7 @@ static const char *bitstrings[] = { "1.......", }; -static void emv_tag_dump_bitmask(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) -{ +static void emv_tag_dump_bitmask(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { const struct emv_tag_bit *bits = tag->data; unsigned bit, byte; @@ -331,8 +342,7 @@ static void emv_tag_dump_bitmask(const struct tlv *tlv, const struct emv_tag *ta } } -static void emv_tag_dump_dol(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) -{ +static void emv_tag_dump_dol(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { const unsigned char *buf = tlv->value; size_t left = tlv->len; @@ -353,7 +363,7 @@ static void emv_tag_dump_dol(const struct tlv *tlv, const struct emv_tag *tag, F } } -static void emv_tag_dump_string(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level){ +static void emv_tag_dump_string(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { fprintf(f, "\tString value '"); fwrite(tlv->value, 1, tlv->len, f); fprintf(f, "'\n"); @@ -468,8 +478,6 @@ static void emv_tag_dump_cvr(const struct tlv *tlv, const struct emv_tag *tag, F if (data[0] || data[1] || data[2] || data[3]) emv_tag_dump_bitmask(&bit_tlv, &bit_tag, f, level); - - return; } // EMV Book 3 @@ -512,12 +520,9 @@ static void emv_tag_dump_cid(const struct tlv *tlv, const struct emv_tag *tag, F break; } } - - return; } -static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) -{ +static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { uint32_t X, Y; int i; @@ -615,7 +620,7 @@ static void emv_tag_dump_cvm_list(const struct tlv *tlv, const struct emv_tag *t } } -static void emv_tag_dump_afl(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level){ +static void emv_tag_dump_afl(const struct tlv *tlv, const struct emv_tag *tag, FILE *f, int level) { if (tlv->len < 4 || tlv->len % 4) { PRINT_INDENT(level); fprintf(f, "\tINVALID!\n"); @@ -628,8 +633,7 @@ static void emv_tag_dump_afl(const struct tlv *tlv, const struct emv_tag *tag, F } } -bool emv_tag_dump(const struct tlv *tlv, FILE *f, int level) -{ +bool emv_tag_dump(const struct tlv *tlv, FILE *f, int level) { if (!tlv) { fprintf(f, "NULL\n"); return false; @@ -682,8 +686,7 @@ bool emv_tag_dump(const struct tlv *tlv, FILE *f, int level) return true; } -char *emv_get_tag_name(const struct tlv *tlv) -{ +char *emv_get_tag_name(const struct tlv *tlv) { static char *defstr = ""; if (!tlv) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 058aefe50..0c3bb7626 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -120,7 +120,7 @@ static bool print_cb(void *data, const struct tlv *tlv, int level, bool is_leaf) return true; } -void TLVPrintFromBuffer(uint8_t *data, int datalen) { +bool TLVPrintFromBuffer(uint8_t *data, int datalen) { struct tlvdb *t = NULL; t = tlvdb_parse_multi(data, datalen); if (t) { @@ -128,9 +128,11 @@ void TLVPrintFromBuffer(uint8_t *data, int datalen) { tlvdb_visit(t, print_cb, NULL, 0); tlvdb_free(t); + return true; } else { PrintAndLogEx(WARNING, "TLV ERROR: Can't parse response as TLV tree."); } + return false; } void TLVPrintFromTLVLev(struct tlvdb *tlv, int level) { diff --git a/client/emv/emvcore.h b/client/emv/emvcore.h index c2b1746e1..1117c7f78 100644 --- a/client/emv/emvcore.h +++ b/client/emv/emvcore.h @@ -65,7 +65,7 @@ enum CardPSVendor { }; extern enum CardPSVendor GetCardPSVendor(uint8_t * AID, size_t AIDlen); -extern void TLVPrintFromBuffer(uint8_t *data, int datalen); +extern bool TLVPrintFromBuffer(uint8_t *data, int datalen); extern void TLVPrintFromTLV(struct tlvdb *tlv); extern void TLVPrintFromTLVLev(struct tlvdb *tlv, int level); extern void TLVPrintAIDlistFromSelectTLV(struct tlvdb *tlv); From 5140db2ac63a615b0cbd47486b99561480136ed2 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 25 Dec 2018 18:13:41 +0100 Subject: [PATCH 0332/1938] CHG: some more descriptions --- client/emv/emv_tags.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index 63397f19e..47cc9e79d 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -198,6 +198,9 @@ static const struct emv_tag emv_tags[] = { { 0x61 , "Application Template" }, { 0x6f , "File Control Information (FCI) Template" }, { 0x70 , "READ RECORD Response Message Template" }, + { 0x71 , "Issues Script Template 1" }, + { 0x72 , "Issues Script Template 2" }, + { 0x73 , "Directory Discretionary Template" }, { 0x77 , "Response Message Template Format 2" }, { 0x80 , "Response Message Template Format 1" }, { 0x82 , "Application Interchange Profile", EMV_TAG_BITMASK, &EMV_AIP }, From ddfe58458255b5e8129170bdab4fabd4e4bb6c8e Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 25 Dec 2018 18:16:47 +0100 Subject: [PATCH 0333/1938] CHG: 'sc brute' - nicer output, rearrange code --- client/cmdsmartcard.c | 256 ++++++++++++++++++++++++++---------------- 1 file changed, 159 insertions(+), 97 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index a5a20f5e2..443833ac2 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -25,7 +25,7 @@ int usage_sm_raw(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " sc raw s 0 d 00a404000e315041592e5359532e4444463031 - `1PAY.SYS.DDF01` PPSE directory with get ATR"); PrintAndLogEx(NORMAL, " sc raw 0 d 00a404000e325041592e5359532e4444463031 - `2PAY.SYS.DDF01` PPSE directory"); - PrintAndLogEx(NORMAL, " sc raw 0 t d 00a4040007a000000004101000 - Mastercard"); + PrintAndLogEx(NORMAL, " sc raw 0 t d 00a4040007a0000000041010 - Mastercard"); PrintAndLogEx(NORMAL, " sc raw 0 t d 00a4040007a0000000031010 - Visa"); return 0; @@ -837,6 +837,137 @@ int CmdSmartList(const char *Cmd) { return 0; } +static void smart_brute_prim(){ + + uint8_t* buf = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t)); + if ( !buf ) + return; + + int len = 0; + uint8_t get_card_data[] = { + 0x80, 0xCA, 0x9F, 0x13, 0x00, + 0x80, 0xCA, 0x9F, 0x17, 0x00, + 0x80, 0xCA, 0x9F, 0x36, 0x00, + 0x80, 0xCA, 0x9F, 0x4f, 0x00 + }; + + UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, 5, 0}}; + + PrintAndLogEx(INFO, "Reading primitives"); + + for (int i = 0; i < sizeof(get_card_data); i += 5) { + + memcpy(c.d.asBytes, get_card_data+i, 5 ); + clearCommandBuffer(); + SendCommand(&c); + + len = smart_responseEx(buf, true); + + if ( len > 2 ) { + + //if ( decodeTLV ) { + //if (!TLVPrintFromBuffer(buf, len-2)) { + PrintAndLogEx(SUCCESS, "\tHEX %d |: %s", len, sprint_hex(buf, len)); + //} + //} + } + len = 0; + } + free(buf); +} + +static int smart_brute_sfi(bool decodeTLV){ + + uint8_t* buf = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t)); + if ( !buf ) + return 1; + + int len = 0; + // READ RECORD + uint8_t READ_RECORD[] = {0x00, 0xB2, 0x00, 0x00, 0x00}; + UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, sizeof(READ_RECORD), 0}}; + + PrintAndLogEx(INFO, "Start SFI brute forcing"); + + for (uint8_t sfi=1; sfi <= 3; sfi++) { + + printf("."); fflush(stdout); + + for (uint16_t rec=1; rec <= 3; rec++) { + + if (ukbhit()) { + int gc = getchar(); (void)gc; + PrintAndLogEx(NORMAL, "\naborted via keyboard!\n"); + free(buf); + return 1; + } + + READ_RECORD[2] = rec; + READ_RECORD[3] = (sfi << 3) | 4; + + memcpy(c.d.asBytes, READ_RECORD, sizeof(READ_RECORD) ); + clearCommandBuffer(); + SendCommand(&c); + + len = smart_responseEx(buf, true); + + if ( buf[0] == 0x6C ) { + READ_RECORD[4] = buf[1]; + + memcpy(c.d.asBytes, READ_RECORD, sizeof(READ_RECORD) ); + clearCommandBuffer(); + SendCommand(&c); + len = smart_responseEx(buf, true); + + READ_RECORD[4] = 0; + } + + if ( len > 4 ) { + + PrintAndLogEx(SUCCESS, "\n\t file %02d, record %02d found", sfi, rec); + + uint8_t modifier = (buf[0] == 0xC0) ? 1 : 0; + + if ( decodeTLV ) { + if (!TLVPrintFromBuffer(buf + modifier, len-2-modifier)) { + PrintAndLogEx(SUCCESS, "\tHEX: %s", sprint_hex(buf, len)); + } + } + } + memset(buf, 0x00, USB_CMD_DATA_SIZE); + } + } + free(buf); + return 0; +} + +static void smart_brute_options(bool decodeTLV){ + + uint8_t* buf = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t)); + if ( !buf ) + return; + + uint8_t GET_PROCESSING_OPTIONS[] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00}; + + // Get processing options command + UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, sizeof(GET_PROCESSING_OPTIONS), 0}}; + memcpy(c.d.asBytes, GET_PROCESSING_OPTIONS, sizeof(GET_PROCESSING_OPTIONS) ); + clearCommandBuffer(); + SendCommand(&c); + + int len = smart_responseEx(buf, true); + if ( len > 4 ) { + PrintAndLogEx(SUCCESS, "Got processing options"); + if ( decodeTLV ) { + TLVPrintFromBuffer(buf, len-2); + } + } else { + PrintAndLogEx(FAILED, "Getting processing options failed"); + } + + free(buf); +} + int CmdSmartBruteforceSFI(const char *Cmd) { uint8_t cmdp = 0; @@ -867,27 +998,15 @@ int CmdSmartBruteforceSFI(const char *Cmd) { const char *SELECT = "00a40400%02x%s"; - uint8_t READ_RECORD[] = {0x00, 0xB2, 0x00, 0x00, 0x00}; - uint8_t GET_PROCESSING_OPTIONS[] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00}; - // uint8_t GENERATE_AC[] = {0x80, 0xAE}; // uint8_t GET_CHALLENGE[] = {0x00, 0x84, 0x00}; // uint8_t GET_DATA[] = {0x80, 0xCA, 0x00, 0x00, 0x00}; // uint8_t SELECT[] = {0x00, 0xA4, 0x04, 0x00}; // uint8_t UNBLOCK_PIN[] = {0x84, 0x24, 0x00, 0x00, 0x00}; // uint8_t VERIFY[] = {0x00, 0x20, 0x00, 0x80}; - - - // Select AID command - UsbCommand cAid = {CMD_SMART_RAW, {SC_RAW_T0, 0, 0}}; - // Get processing options command - UsbCommand cOpt = {CMD_SMART_RAW, {SC_RAW_T0, sizeof(GET_PROCESSING_OPTIONS), 0}}; - memcpy(cOpt.d.asBytes, GET_PROCESSING_OPTIONS, sizeof(GET_PROCESSING_OPTIONS) ); - - // READ RECORD - UsbCommand cSFI = {CMD_SMART_RAW, {SC_RAW_T0, sizeof(READ_RECORD), 0}}; - + // Select AID command + UsbCommand cAid = {CMD_SMART_RAW, {SC_RAW_T0, 0, 0}}; PrintAndLogEx(INFO, "Importing AID list"); json_t *root = NULL; @@ -897,16 +1016,19 @@ int CmdSmartBruteforceSFI(const char *Cmd) { if ( !buf ) return 1; - uint8_t* sfibuf = malloc(USB_CMD_DATA_SIZE); - if ( !sfibuf ) - return 1; - PrintAndLogEx(INFO, "Selecting card"); if ( !smart_select(false) ) return 1; + char* caid = NULL; for (int i = 0; i < json_array_size(root); i++) { + + printf("+"); fflush(stdout); + + if (caid) + free(caid); + json_t *data, *jaid; data = json_array_get(root, i); @@ -924,7 +1046,8 @@ int CmdSmartBruteforceSFI(const char *Cmd) { } const char* aid = json_string_value(jaid); - if ( !aid ) continue; + if ( !aid ) + continue; size_t aidlen = strlen(aid); char* caid = calloc( 8+2+aidlen+1, sizeof(uint8_t)); @@ -932,7 +1055,8 @@ int CmdSmartBruteforceSFI(const char *Cmd) { int hexlen = 0; int res = param_gethex_to_eol(caid, 0, cAid.d.asBytes, sizeof(cAid.d.asBytes), &hexlen); - if ( res ) continue; + if ( res ) + continue; cAid.arg[1] = hexlen; @@ -940,10 +1064,8 @@ int CmdSmartBruteforceSFI(const char *Cmd) { SendCommand(&cAid); int len = smart_responseEx(buf, true); - if ( len < 3 ) { - free(caid); + if ( len < 3 ) continue; - } json_t *jvendor, *jname; jvendor = json_object_get(data, "Vendor"); @@ -953,96 +1075,36 @@ int CmdSmartBruteforceSFI(const char *Cmd) { } const char* vendor = json_string_value(jvendor); - if ( !vendor ) continue; - + if ( !vendor ) + continue; + jname = json_object_get(data, "Name"); if (!json_is_string(jname)) { PrintAndLogEx(ERR, "Name data [%d] is not a string", i + 1); continue; } const char* name = json_string_value(jname); - if ( !name ) continue; + if ( !name ) + continue; - PrintAndLogEx(SUCCESS, "AID %s | %s | %s", aid, vendor, name); + PrintAndLogEx(SUCCESS, "\nAID %s | %s | %s", aid, vendor, name); - // Get processing options - clearCommandBuffer(); - SendCommand(&cOpt); - - uint8_t optionslen = smart_responseEx(buf, true); - if ( optionslen > 4 ) { - PrintAndLogEx(SUCCESS, "Got processing options"); - if ( decodeTLV ) { - TLVPrintFromBuffer(buf, optionslen-2); - } - } else { - PrintAndLogEx(FAILED, "Getting processing options failed"); - } - - PrintAndLogEx(INFO, "Start SFI brute forcing"); - - for (uint8_t sfi=1; sfi <= 31; sfi++) { + smart_brute_options(decodeTLV); - printf("."); fflush(stdout); - - for (uint16_t rec=1; rec <= 5; rec++) { + smart_brute_prim(); - if (ukbhit()) { - int gc = getchar(); (void)gc; - PrintAndLogEx(NORMAL, "\naborted via keyboard!\n"); - free(caid); - goto out; - } - - READ_RECORD[2] = rec; - READ_RECORD[3] = (sfi << 3) | 4; + smart_brute_sfi(decodeTLV); - memcpy(cSFI.d.asBytes, READ_RECORD, sizeof(READ_RECORD) ); - clearCommandBuffer(); - SendCommand(&cSFI); - - uint8_t sfilen = smart_responseEx(sfibuf, true); - - if ( sfibuf[0] == 0x6C ) { - READ_RECORD[4] = sfibuf[1]; - - memcpy(cSFI.d.asBytes, READ_RECORD, sizeof(READ_RECORD) ); - clearCommandBuffer(); - SendCommand(&cSFI); - sfilen = smart_responseEx(sfibuf, true); - - READ_RECORD[4] = 0; - } - - if ( sfilen > 4 ) { - - PrintAndLogEx(SUCCESS, "\n\t file %02d, record %02d found", sfi, rec); - - uint8_t modifier = (sfibuf[0] == 0xC0) ? 1 : 0; - - if ( decodeTLV ) { - if (!TLVPrintFromBuffer(sfibuf + modifier, sfilen-2-modifier)) { - PrintAndLogEx(SUCCESS, "\tHEX: %s", sprint_hex(sfibuf, sfilen)); - } - } - - } - memset(sfibuf, 0x00, USB_CMD_DATA_SIZE); - } - } - - free(sfibuf); - free(caid); PrintAndLogEx(SUCCESS, "\nSFI brute force done\n"); } -out: - if ( sfibuf ) - free(sfibuf); + + if (caid) + free(caid); free(buf); json_decref(root); - PrintAndLogEx(SUCCESS, "Search completed."); + PrintAndLogEx(SUCCESS, "\nSearch completed."); return 0; } From ab9048f7c56c0626e470c62ced6548872fce62c8 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 25 Dec 2018 18:18:48 +0100 Subject: [PATCH 0334/1938] CHG: 'sc brute' loop 31, 255 --- client/cmdsmartcard.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 443833ac2..a864e2358 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -889,11 +889,11 @@ static int smart_brute_sfi(bool decodeTLV){ PrintAndLogEx(INFO, "Start SFI brute forcing"); - for (uint8_t sfi=1; sfi <= 3; sfi++) { + for (uint8_t sfi=1; sfi <= 31; sfi++) { printf("."); fflush(stdout); - for (uint16_t rec=1; rec <= 3; rec++) { + for (uint16_t rec=1; rec <= 255; rec++) { if (ukbhit()) { int gc = getchar(); (void)gc; From 33f6439d38ed43172f782cc465d26aa44f1c21c1 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 26 Dec 2018 11:02:00 +0100 Subject: [PATCH 0335/1938] add 'emv roca' - new command, will be able to test for ROCA --- client/emv/cmdemv.c | 98 ++++++++++++++++++++++++++++++++++++++++---- client/emv/cmdemv.h | 1 + client/emv/emvcore.c | 8 ++-- client/emv/emvcore.h | 1 + 4 files changed, 97 insertions(+), 11 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 13f64a616..14616e0f0 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1382,7 +1382,7 @@ int CmdEMVScan(const char *cmd) { uint8_t SFIend = AFL->value[i * 4 + 2]; uint8_t SFIoffline = AFL->value[i * 4 + 3]; - PrintAndLog("--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline); + PrintAndLogEx(INFO, "--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline); if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) { PrintAndLogEx(ERR, "SFI ERROR! Skipped..."); continue; @@ -1476,6 +1476,89 @@ int CmdEMVTest(const char *cmd) { return ExecuteCryptoTests(true); } +int CmdEMVRoca(const char *cmd) { + + CLIParserInit("emv roca", + "Tries to extract public keys and run the ROCA test against them.\n", + "Usage:\n\temv roca -w -> select CONTACT card and run test\n\temv roca -> select CONTACTLESS card and run test\n"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + EMVCommandChannel channel = ECC_CONTACTLESS; + if (arg_get_lit(1)) + channel = ECC_CONTACT; + + // Init TLV tree + const char *alr = "Root terminal TLV tree"; + struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr); + + + + int res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot); + + // getting certificates + if (tlvdb_get(tlvRoot, 0x90, NULL)) { + PrintAndLogEx(INFO, "-->Recovering certificates."); + PKISetStrictExecution(false); + + struct emv_pk *pk = get_ca_pk(tlvRoot); + if (!pk) { + PrintAndLogEx(ERR, "ERROR: Key not found. Exit."); + goto out; + } + + struct emv_pk *issuer_pk = emv_pki_recover_issuer_cert(pk, tlvRoot); + if (!issuer_pk) { + emv_pk_free(pk); + PrintAndLogEx(WARNING, "WARNING: Issuer certificate not found. Exit."); + goto out; + } + + PrintAndLogEx(SUCCESS, "Issuer PK recovered. RID %s IDX %02hhx CSN %s", + sprint_hex(issuer_pk->rid, 5), + issuer_pk->index, + sprint_hex(issuer_pk->serial, 3) + ); + + + struct emv_pk *icc_pk = emv_pki_recover_icc_cert(issuer_pk, tlvRoot, NULL); + if (!icc_pk) { + emv_pk_free(pk); + emv_pk_free(issuer_pk); + PrintAndLogEx(WARNING, "WARNING: ICC certificate not found. Exit."); + goto out; + } + PrintAndLogEx(SUCCESS, "ICC PK recovered. RID %s IDX %02hhx CSN %s\n", + sprint_hex(icc_pk->rid, 5), + icc_pk->index, + sprint_hex(icc_pk->serial, 3) + ); + +// icc_pk->exp, icc_pk->elen +// icc_pk->modulus, icc_pk->mlen + + + PKISetStrictExecution(true); + } + +out: + + // free tlv object + tlvdb_free(tlvRoot); + + if ( channel == ECC_CONTACTLESS) + DropField(); + + + return 0; +} + + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"exec", CmdEMVExec, 0, "Executes EMV contactless transaction."}, @@ -1490,13 +1573,14 @@ static command_t CommandTable[] = { {"scan", CmdEMVScan, 0, "Scan EMV card and save it contents to json file for emulator."}, {"test", CmdEMVTest, 0, "Crypto logic test."}, /* - {"getrng", CmdEMVGetrng, 0, "get random number from terminal"}, - {"eload", CmdEmvELoad, 0, "load EMV tag into device"}, - {"dump", CmdEmvDump, 0, "dump EMV tag values"}, - {"sim", CmdEmvSim, 0, "simulate EMV tag"}, - {"clone", CmdEmvClone, 0, "clone an EMV tag"}, + {"getrng", CmdEMVGetrng, 0, "get random number from terminal"}, + {"eload", CmdEmvELoad, 0, "load EMV tag into device"}, + {"dump", CmdEmvDump, 0, "dump EMV tag values"}, + {"sim", CmdEmvSim, 0, "simulate EMV tag"}, + {"clone", CmdEmvClone, 0, "clone an EMV tag"}, */ - {"list", CmdEMVList, 0, "[Deprecated] List ISO7816 history"}, + {"list", CmdEMVList, 0, "[Deprecated] List ISO7816 history"}, + {"roca", CmdEMVRoca, 0, "Extract public keys and run ROCA test"}, {NULL, NULL, 0, NULL} }; diff --git a/client/emv/cmdemv.h b/client/emv/cmdemv.h index b4397fd15..0b0419b07 100644 --- a/client/emv/cmdemv.h +++ b/client/emv/cmdemv.h @@ -34,5 +34,6 @@ extern int CmdEMVPPSE(const char *cmd); extern int CmdEMVExec(const char *cmd); extern int CmdEMVGetrng(const char *Cmd); extern int CmdEMVList(const char *Cmd); +extern int CmdEMVRoca(const char *Cmd); #endif diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 0c3bb7626..b67e7ac76 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -519,7 +519,7 @@ int MSCComputeCryptoChecksum(EMVCommandChannel channel, bool LeaveFieldON, uint8 } // Authentication -static struct emv_pk *get_ca_pk(struct tlvdb *db) { +struct emv_pk *get_ca_pk(struct tlvdb *db) { const struct tlv *df_tlv = tlvdb_get(db, 0x84, NULL); const struct tlv *caidx_tlv = tlvdb_get(db, 0x8f, NULL); @@ -900,7 +900,7 @@ int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root) { PrintAndLog("WARNING: Issuer certificate not found. Exit."); return 2; } - PrintAndLog("Issuer PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx", + PrintAndLogEx(SUCCESS, "Issuer PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx", issuer_pk->rid[0], issuer_pk->rid[1], issuer_pk->rid[2], @@ -923,10 +923,10 @@ int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root) { if (!icc_pk) { emv_pk_free(pk); emv_pk_free(issuer_pk); - PrintAndLog("WARNING: ICC certificate not found. Exit."); + PrintAndLogEx(WARNING, "WARNING: ICC certificate not found. Exit."); return 2; } - printf("ICC PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx\n", + PrintAndLogEx(SUCCESS, "ICC PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx\n", icc_pk->rid[0], icc_pk->rid[1], icc_pk->rid[2], diff --git a/client/emv/emvcore.h b/client/emv/emvcore.h index 1117c7f78..829107126 100644 --- a/client/emv/emvcore.h +++ b/client/emv/emvcore.h @@ -102,6 +102,7 @@ extern int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_ extern int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root); +extern struct emv_pk *get_ca_pk(struct tlvdb *db); #endif From ed6806810749a93b23758b5a330eed8b205e7032 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 26 Dec 2018 12:50:11 +0100 Subject: [PATCH 0336/1938] chg: 'emv roca' -now compiles --- client/emv/cmdemv.c | 56 +++++++++++++++++++-------------------------- 1 file changed, 23 insertions(+), 33 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 14616e0f0..1029d5a7e 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -306,7 +306,7 @@ int CmdEMVReadRecord(const char *cmd) { arg_lit0("aA", "apdu", "show APDU reqests and responses"), arg_lit0("tT", "tlv", "TLV decode results of selected applets"), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), - arg_strx1(NULL, NULL, "", NULL), + arg_strx1(NULL, NULL, "", NULL), arg_param_end }; CLIExecWithReturn(cmd, argtable, true); @@ -510,8 +510,11 @@ int CmdEMVInternalAuthenticate(const char *cmd) { int datalen = 0; CLIParserInit("emv intauth", - "Generate Internal Authenticate command. Usually needs 4-byte random number. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.", - "Usage:\n\temv intauth -k 01020304 -> execute Internal Authenticate with 4-byte DDOLdata and keep field ON after command\n" + "Generate Internal Authenticate command. Usually needs 4-byte random number. It returns data in TLV format .\n" + "Needs a EMV applet to be selected and GPO to be executed.", + + "Usage:\n" + "\temv intauth -k 01020304 -> execute Internal Authenticate with 4-byte DDOLdata and keep field ON after command\n" "\temv intauth -t 01020304 -> execute Internal Authenticate with 4-byte DDOL data, show result in TLV\n" "\temv intauth -pmt 9F 37 04 -> load params from file, make DDOL data from DDOL, Internal Authenticate with DDOL, show result in TLV"); @@ -680,7 +683,8 @@ int CmdEMVExec(const char *cmd) { CLIParserInit("emv exec", "Executes EMV contactless transaction", - "Usage:\n\temv exec -sat -> select card, execute MSD transaction, show APDU and TLV\n" + "Usage:\n" + "\temv exec -sat -> select card, execute MSD transaction, show APDU and TLV\n" "\temv exec -satc -> select card, execute CDA transaction, show APDU and TLV\n"); void* argtable[] = { @@ -921,7 +925,7 @@ int CmdEMVExec(const char *cmd) { // transaction check // qVSDC - if (TrType == TT_QVSDCMCHIP|| TrType == TT_CDA){ + if (TrType == TT_QVSDCMCHIP || TrType == TT_CDA){ // 9F26: Application Cryptogram const struct tlv *AC = tlvdb_get(tlvRoot, 0x9F26, NULL); if (AC) { @@ -938,7 +942,7 @@ int CmdEMVExec(const char *cmd) { // print AC data PrintAndLogEx(NORMAL, "ATC: %s", sprint_hex(ATC->value, ATC->len)); PrintAndLogEx(NORMAL, "AC: %s", sprint_hex(AC->value, AC->len)); - if (IAD){ + if (IAD) { PrintAndLogEx(NORMAL, "IAD: %s", sprint_hex(IAD->value, IAD->len)); if (IAD->len >= IAD->value[0] + 1) { @@ -978,17 +982,18 @@ int CmdEMVExec(const char *cmd) { // ICC Dynamic Number struct tlvdb * ICCDynN = tlvdb_fixed(0x9f4c, len, buf); tlvdb_add(tlvRoot, ICCDynN); - if (decodeTLV){ + if (decodeTLV) { PrintAndLogEx(NORMAL, "\n* * ICC Dynamic Number:"); TLVPrintFromTLV(ICCDynN); } PrintAndLogEx(NORMAL, "* * Calc CDOL1"); struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag - if (!cdol_data_tlv){ + if (!cdol_data_tlv) { PrintAndLogEx(WARNING, "Error: can't create CDOL1 TLV."); dreturn(6); } + PrintAndLogEx(NORMAL, "CDOL1 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len)); PrintAndLogEx(NORMAL, "* * AC1"); @@ -1010,6 +1015,7 @@ int CmdEMVExec(const char *cmd) { if (res) { PrintAndLogEx(NORMAL, "CDA error (%d)", res); } + free(ac_tlv); free(cdol_data_tlv); @@ -1073,7 +1079,7 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "Use default UDOL."); struct tlv *udol_data_tlv = dol_process(UDOL ? UDOL : &defUDOL, tlvRoot, 0x01); // 0x01 - dummy tag - if (!udol_data_tlv){ + if (!udol_data_tlv) { PrintAndLogEx(WARNING, "Error: can't create UDOL TLV."); dreturn(8); } @@ -1448,25 +1454,6 @@ int CmdEMVScan(const char *cmd) { return 0; } -int usage_emv_getrnd(void){ - PrintAndLogEx(NORMAL, "retrieve the UN number from a terminal"); - PrintAndLogEx(NORMAL, "Usage: emv getrnd [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " emv getrnd"); - return 0; -} - -//retrieve the UN number from a terminal -int CmdEMVGetrng(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if ( cmdp == 'h' || cmdp == 'H') return usage_emv_getrnd(); - - PrintAndLogEx(INFO, "Not implemented yet"); - return 0; -} int CmdEMVList(const char *Cmd) { return CmdTraceList("7816"); @@ -1480,7 +1467,8 @@ int CmdEMVRoca(const char *cmd) { CLIParserInit("emv roca", "Tries to extract public keys and run the ROCA test against them.\n", - "Usage:\n\temv roca -w -> select CONTACT card and run test\n\temv roca -> select CONTACTLESS card and run test\n"); + "Usage:\n" + "\temv roca -w -> select CONTACT card and run test\n\temv roca -> select CONTACTLESS card and run test\n"); void* argtable[] = { arg_param_begin, @@ -1497,9 +1485,12 @@ int CmdEMVRoca(const char *cmd) { const char *alr = "Root terminal TLV tree"; struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr); - - - int res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot); + // select card + uint8_t buf[APDU_RES_LEN] = {0}; + size_t len = 0; + uint16_t sw = 0; + uint8_t psenum = (channel == ECC_CONTACT) ? 1: 2; + int res = EMVSelectPSE(channel, true, true, psenum, buf, sizeof(buf), &len, &sw); // getting certificates if (tlvdb_get(tlvRoot, 0x90, NULL)) { @@ -1558,7 +1549,6 @@ out: return 0; } - static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"exec", CmdEMVExec, 0, "Executes EMV contactless transaction."}, From c6089d7fdb8a58e9cea445f9b9e783f4086f4ab6 Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 26 Dec 2018 17:54:29 +0100 Subject: [PATCH 0337/1938] chg: more definitions --- client/emv/emv_tags.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index 47cc9e79d..81cee89f3 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -237,6 +237,7 @@ static const struct emv_tag emv_tags[] = { { 0x9f17, "Personal Identification Number (PIN) Try Counter" }, { 0x9f1a, "Terminal Country Code" }, { 0x9f1f, "Track 1 Discretionary Data", EMV_TAG_STRING }, + { 0x9f20, "Track 2 Discretionary Data", EMV_TAG_STRING }, { 0x9f21, "Transaction Time" }, { 0x9f26, "Application Cryptogram" }, { 0x9f27, "Cryptogram Information Data", EMV_TAG_CID }, From 92fadc2a9f442ac31433f47bf7fd2e657aa8cbe6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 27 Dec 2018 19:45:53 +0100 Subject: [PATCH 0338/1938] ADD: 'amiitool' - Added @socram8888 's great tool for manipulating amiibo tags. The idea is to build it in the pm3 client. It compiles as is, but the hookup in client is not done. *WORK IN PROGRESS* --- client/amiitool/LICENSE | 21 ++++ client/amiitool/amiibo.c | 180 +++++++++++++++++++++++++++++++++ client/amiitool/amiibo.h | 32 ++++++ client/amiitool/amiitool.c | 175 ++++++++++++++++++++++++++++++++ client/amiitool/drbg.c | 78 ++++++++++++++ client/amiitool/drbg.h | 33 ++++++ client/amiitool/key_retail.bin | Bin 0 -> 160 bytes client/amiitool/keygen.c | 53 ++++++++++ client/amiitool/keygen.h | 34 +++++++ client/obj/amiitool/.dummy | 0 10 files changed, 606 insertions(+) create mode 100644 client/amiitool/LICENSE create mode 100644 client/amiitool/amiibo.c create mode 100644 client/amiitool/amiibo.h create mode 100644 client/amiitool/amiitool.c create mode 100644 client/amiitool/drbg.c create mode 100644 client/amiitool/drbg.h create mode 100644 client/amiitool/key_retail.bin create mode 100644 client/amiitool/keygen.c create mode 100644 client/amiitool/keygen.h create mode 100644 client/obj/amiitool/.dummy diff --git a/client/amiitool/LICENSE b/client/amiitool/LICENSE new file mode 100644 index 000000000..35627b40f --- /dev/null +++ b/client/amiitool/LICENSE @@ -0,0 +1,21 @@ +(c) 2015-2017 Marcos Del Sol Vives +(c) 2016 javiMaD +(c) 2016 Michael Armbruster + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in +all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +THE SOFTWARE. diff --git a/client/amiitool/amiibo.c b/client/amiitool/amiibo.c new file mode 100644 index 000000000..6391ae830 --- /dev/null +++ b/client/amiitool/amiibo.c @@ -0,0 +1,180 @@ +/* + * (c) 2015-2017 Marcos Del Sol Vives + * (c) 2016 javiMaD + * + * SPDX-License-Identifier: MIT + */ + +#include "amiibo.h" +#include "mbedtls/md.h" +#include "mbedtls/aes.h" + +#define HMAC_POS_DATA 0x008 +#define HMAC_POS_TAG 0x1B4 + +void nfc3d_amiibo_calc_seed(const uint8_t * dump, uint8_t * key) { + memcpy(key + 0x00, dump + 0x029, 0x02); + memset(key + 0x02, 0x00, 0x0E); + memcpy(key + 0x10, dump + 0x1D4, 0x08); + memcpy(key + 0x18, dump + 0x1D4, 0x08); + memcpy(key + 0x20, dump + 0x1E8, 0x20); +} + +void nfc3d_amiibo_keygen(const nfc3d_keygen_masterkeys * masterKeys, const uint8_t * dump, nfc3d_keygen_derivedkeys * derivedKeys) { + uint8_t seed[NFC3D_KEYGEN_SEED_SIZE]; + + nfc3d_amiibo_calc_seed(dump, seed); + nfc3d_keygen(masterKeys, seed, derivedKeys); +} + +void nfc3d_amiibo_cipher(const nfc3d_keygen_derivedkeys * keys, const uint8_t * in, uint8_t * out) { + mbedtls_aes_context aes; + size_t nc_off = 0; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; + + mbedtls_aes_setkey_enc( &aes, keys->aesKey, 128 ); + memset(nonce_counter, 0, sizeof(nonce_counter)); + memset(stream_block, 0, sizeof(stream_block)); + memcpy(nonce_counter, keys->aesIV, sizeof(nonce_counter)); + mbedtls_aes_crypt_ctr( &aes, 0x188, &nc_off, nonce_counter, stream_block, in + 0x02C, out + 0x02C ); + + memcpy(out + 0x000, in + 0x000, 0x008); + // Data signature NOT copied + memcpy(out + 0x028, in + 0x028, 0x004); + // Tag signature NOT copied + memcpy(out + 0x1D4, in + 0x1D4, 0x034); +} + +void nfc3d_amiibo_tag_to_internal(const uint8_t * tag, uint8_t * intl) { + memcpy(intl + 0x000, tag + 0x008, 0x008); + memcpy(intl + 0x008, tag + 0x080, 0x020); + memcpy(intl + 0x028, tag + 0x010, 0x024); + memcpy(intl + 0x04C, tag + 0x0A0, 0x168); + memcpy(intl + 0x1B4, tag + 0x034, 0x020); + memcpy(intl + 0x1D4, tag + 0x000, 0x008); + memcpy(intl + 0x1DC, tag + 0x054, 0x02C); +} + +void nfc3d_amiibo_internal_to_tag(const uint8_t * intl, uint8_t * tag) { + memcpy(tag + 0x008, intl + 0x000, 0x008); + memcpy(tag + 0x080, intl + 0x008, 0x020); + memcpy(tag + 0x010, intl + 0x028, 0x024); + memcpy(tag + 0x0A0, intl + 0x04C, 0x168); + memcpy(tag + 0x034, intl + 0x1B4, 0x020); + memcpy(tag + 0x000, intl + 0x1D4, 0x008); + memcpy(tag + 0x054, intl + 0x1DC, 0x02C); +} + +bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * tag, uint8_t * plain) { + uint8_t internal[NFC3D_AMIIBO_SIZE]; + nfc3d_keygen_derivedkeys dataKeys; + nfc3d_keygen_derivedkeys tagKeys; + + // Convert format + nfc3d_amiibo_tag_to_internal(tag, internal); + + // Generate keys + nfc3d_amiibo_keygen(&amiiboKeys->data, internal, &dataKeys); + nfc3d_amiibo_keygen(&amiiboKeys->tag, internal, &tagKeys); + + // Decrypt + nfc3d_amiibo_cipher(&dataKeys, internal, plain); + + // Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC! + mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey), + plain + 0x1D4, 0x34, plain + HMAC_POS_TAG ); + + // Regenerate data HMAC + mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), dataKeys.hmacKey, sizeof(dataKeys.hmacKey), + plain + 0x029, 0x1DF, plain + HMAC_POS_DATA ); + + return + memcmp(plain + HMAC_POS_DATA, internal + HMAC_POS_DATA, 32) == 0 && + memcmp(plain + HMAC_POS_TAG, internal + HMAC_POS_TAG, 32) == 0; +} + +void nfc3d_amiibo_pack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * plain, uint8_t * tag) { + uint8_t cipher[NFC3D_AMIIBO_SIZE]; + nfc3d_keygen_derivedkeys tagKeys; + nfc3d_keygen_derivedkeys dataKeys; + + // Generate keys + nfc3d_amiibo_keygen(&amiiboKeys->tag, plain, &tagKeys); + nfc3d_amiibo_keygen(&amiiboKeys->data, plain, &dataKeys); + + // Generate tag HMAC + mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey), + plain + 0x1D4, 0x34, cipher + HMAC_POS_TAG ); + + // Init mbedtls HMAC context + mbedtls_md_context_t ctx; + mbedtls_md_init( &ctx ); + mbedtls_md_setup( &ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1 ); + + // Generate data HMAC + mbedtls_md_hmac_starts( &ctx, dataKeys.hmacKey, sizeof(dataKeys.hmacKey) ); + mbedtls_md_hmac_update( &ctx, plain + 0x029, 0x18B ); // Data + mbedtls_md_hmac_update( &ctx, cipher + HMAC_POS_TAG, 0x20 ); // Tag HMAC + mbedtls_md_hmac_update( &ctx, plain + 0x1D4, 0x34 ); // Here be dragons + + mbedtls_md_hmac_finish( &ctx, cipher + HMAC_POS_DATA ); + + // HMAC cleanup + mbedtls_md_free( &ctx ); + + // Encrypt + nfc3d_amiibo_cipher(&dataKeys, plain, cipher); + + // Convert back to hardware + nfc3d_amiibo_internal_to_tag(cipher, tag); +} + +bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys * amiiboKeys, const char * path) { + FILE * f = fopen(path, "rb"); + if (!f) { + return false; + } + + if (!fread(amiiboKeys, sizeof(*amiiboKeys), 1, f)) { + fclose(f); + return false; + } + fclose(f); + + if ( + (amiiboKeys->data.magicBytesSize > 16) || + (amiiboKeys->tag.magicBytesSize > 16) + ) { + return false; + } + + return true; +} + +void nfc3d_amiibo_copy_app_data(const uint8_t * src, uint8_t * dst) { + + + //uint16_t *ami_nb_wr = (uint16_t*)(dst + 0x29); + //uint16_t *cfg_nb_wr = (uint16_t*)(dst + 0xB4); + + /* increment write counters */ + //*ami_nb_wr = htobe16(be16toh(*ami_nb_wr) + 1); + //*cfg_nb_wr = htobe16(be16toh(*cfg_nb_wr) + 1); + + uint16_t ami_nb_wr = ((uint16_t)bytes_to_num(dst + 0x29, 2)) + 1; + uint16_t cfg_nb_wr = ((uint16_t)bytes_to_num(dst + 0xB4, 2)) + 1; + + num_to_bytes(ami_nb_wr, 2, dst + 0x29); + num_to_bytes(cfg_nb_wr, 2, dst + 0xB4); + + /* copy flags */ + dst[0x2C] = src[0x2C]; + /* copy programID */ + memcpy(dst + 0xAC, src + 0xAC, 8); + /* copy AppID */ + memcpy(dst + 0xB6, src + 0xB6, 4); + /* copy AppData */ + memcpy(dst + 0xDC, src + 0xDC, 216); +} + diff --git a/client/amiitool/amiibo.h b/client/amiitool/amiibo.h new file mode 100644 index 000000000..3c7dccc70 --- /dev/null +++ b/client/amiitool/amiibo.h @@ -0,0 +1,32 @@ +/* + * (c) 2015-2017 Marcos Del Sol Vives + * (c) 2016 javiMaD + * + * SPDX-License-Identifier: MIT + */ + +#ifndef HAVE_NFC3D_AMIIBO_H +#define HAVE_NFC3D_AMIIBO_H + +#include +#include +#include +#include +#include "keygen.h" +#include "util.h" + +#define NFC3D_AMIIBO_SIZE 520 + +#pragma pack(1) +typedef struct { + nfc3d_keygen_masterkeys data; + nfc3d_keygen_masterkeys tag; +} nfc3d_amiibo_keys; +#pragma pack() + +bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * tag, uint8_t * plain); +void nfc3d_amiibo_pack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * plain, uint8_t * tag); +bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys * amiiboKeys, const char * path); +void nfc3d_amiibo_copy_app_data(const uint8_t * src, uint8_t * dst); + +#endif diff --git a/client/amiitool/amiitool.c b/client/amiitool/amiitool.c new file mode 100644 index 000000000..40e7b05eb --- /dev/null +++ b/client/amiitool/amiitool.c @@ -0,0 +1,175 @@ +/* + * (c) 2015-2017 Marcos Del Sol Vives + * (c) 2016 javiMaD + * + * SPDX-License-Identifier: MIT + */ + +#include +#include +#include +#include "../loclass/fileutil.h" + +#define NTAG215_SIZE 540 + +static char * self; + +void amiitool_usage() { + fprintf(stderr, + "amiitool build %i (commit %s-%08x)\n" + "by Marcos Del Sol Vives \n" + "\n" + "Usage: %s (-e|-d|-c) -k keyfile [-i input] [-s input2] [-o output]\n" + " -e encrypt and sign amiibo\n" + " -d decrypt and test amiibo\n" + " -c decrypt, copy AppData and encrypt amiibo\n" + " -k key set file. For retail amiibo, use \"retail unfixed\" key set\n" + " -i input file. If not specified, stdin will be used.\n" + " -s input save file, save from this file will replace input file ones.\n" + " -o output file. If not specified, stdout will be used.\n" + " -l decrypt files with invalid signatures.\n", + , self + ); +} + +static bool LoadAmiikey(nfc3d_amiibo_keys keys, char* keyfile) { + + if (!nfc3d_amiibo_load_keys(&keys, keyfile)) { + PrintAndLogEx(ERR, "Could not load keys from '%s'", keyfile); + return false; + } + return true; +} + +int main(int argc, char ** argv) { + self = argv[0]; + + char * infile = NULL; + char * savefile = NULL; + char * outfile = NULL; + char * keyfile = NULL; + char op = '\0'; + bool lenient = false; + + char c; + while ((c = getopt(argc, argv, "edci:s:o:k:l")) != -1) { + switch (c) { + case 'e': + case 'd': + case 'c': + op = c; + break; + case 'i': + infile = optarg; + break; + case 's': + savefile = optarg; + break; + case 'o': + outfile = optarg; + break; + case 'l': + lenient = true; + break; + default: + amiitool_usage(); + return 2; + } + } + + if (op == '\0' || keyfile == NULL) { + amiitool_usage(); + return 1; + } + + nfc3d_amiibo_keys amiiboKeys; + + + uint8_t original[NTAG215_SIZE]; + uint8_t modified[NFC3D_AMIIBO_SIZE]; + + FILE * f = stdin; + if (infile) { + f = fopen(infile, "rb"); + if (!f) { + fprintf(stderr, "Could not open input file\n"); + return 3; + } + } + size_t readPages = fread(original, 4, NTAG215_SIZE / 4, f); + if (readPages < NFC3D_AMIIBO_SIZE / 4) { + fprintf(stderr, "Could not read from input\n"); + fclose(f); + return 3; + } + fclose(f); + + + if (op == 'e') { + nfc3d_amiibo_pack(&amiiboKeys, original, modified); + } else if (op == 'd') { + if (!nfc3d_amiibo_unpack(&amiiboKeys, original, modified)) { + fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n"); + if (!lenient) { + return 6; + } + } + } else { /* copy */ + uint8_t plain_base[NFC3D_AMIIBO_SIZE]; + uint8_t plain_save[NFC3D_AMIIBO_SIZE]; + + if (!nfc3d_amiibo_unpack(&amiiboKeys, original, plain_base)) { + fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n"); + if (!lenient) { + return 6; + } + } + if (savefile) { + f = fopen(savefile, "rb"); + if (!f) { + fprintf(stderr, "Could not open save file\n"); + return 3; + } + } + size_t readPages = fread(original, 4, NTAG215_SIZE / 4, f); + if (readPages < NFC3D_AMIIBO_SIZE / 4) { + fprintf(stderr, "Could not read from save\n"); + fclose(f); + return 3; + } + fclose(f); + + if (!nfc3d_amiibo_unpack(&amiiboKeys, original, plain_save)) { + fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n"); + if (!lenient) { + return 6; + } + } + + nfc3d_amiibo_copy_app_data(plain_save, plain_base); + nfc3d_amiibo_pack(&amiiboKeys, plain_base, modified); + } + + f = stdout; + if (outfile) { + f = fopen(outfile, "wb"); + if (!f) { + fprintf(stderr, "Could not open output file\n"); + return 4; + } + } + if (fwrite(modified, NFC3D_AMIIBO_SIZE, 1, f) != 1) { + fprintf(stderr, "Could not write to output\n"); + fclose(f); + return 4; + } + if (readPages > NFC3D_AMIIBO_SIZE / 4) { + if (fwrite(original + NFC3D_AMIIBO_SIZE, readPages * 4 - NFC3D_AMIIBO_SIZE, 1, f) != 1) { + fprintf(stderr, "Could not write to output:\n"); + fclose(f); + return 4; + } + } + fclose(f); + return 0; +} diff --git a/client/amiitool/drbg.c b/client/amiitool/drbg.c new file mode 100644 index 000000000..d56366077 --- /dev/null +++ b/client/amiitool/drbg.c @@ -0,0 +1,78 @@ +/* + * (c) 2015-2017 Marcos Del Sol Vives + * (c) 2016 javiMaD + * + * SPDX-License-Identifier: MIT + */ + +#include "drbg.h" +#include +#include +#include + +void nfc3d_drbg_init(nfc3d_drbg_ctx * ctx, const uint8_t * hmacKey, size_t hmacKeySize, const uint8_t * seed, size_t seedSize) { + assert(ctx != NULL); + assert(hmacKey != NULL); + assert(seed != NULL); + assert(seedSize <= NFC3D_DRBG_MAX_SEED_SIZE); + + // Initialize primitives + ctx->used = false; + ctx->iteration = 0; + ctx->bufferSize = sizeof(ctx->iteration) + seedSize; + + // The 16-bit counter is prepended to the seed when hashing, so we'll leave 2 bytes at the start + memcpy(ctx->buffer + sizeof(uint16_t), seed, seedSize); + + // Initialize underlying HMAC context + mbedtls_md_init(&ctx->hmacCtx); + mbedtls_md_setup(&ctx->hmacCtx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1); + mbedtls_md_hmac_starts(&ctx->hmacCtx, hmacKey, hmacKeySize); +} + +void nfc3d_drbg_step(nfc3d_drbg_ctx * ctx, uint8_t * output) { + assert(ctx != NULL); + assert(output != NULL); + + if (ctx->used) { + // If used at least once, reinitialize the HMAC + mbedtls_md_hmac_reset(&ctx->hmacCtx); + } else { + ctx->used = true; + } + + // Store counter in big endian, and increment it + ctx->buffer[0] = ctx->iteration >> 8; + ctx->buffer[1] = ctx->iteration >> 0; + ctx->iteration++; + + // Do HMAC magic + mbedtls_md_hmac_update(&ctx->hmacCtx, ctx->buffer, ctx->bufferSize); + mbedtls_md_hmac_finish(&ctx->hmacCtx, output); +} + +void nfc3d_drbg_cleanup(nfc3d_drbg_ctx * ctx) { + assert(ctx != NULL); + mbedtls_md_free(&ctx->hmacCtx); +} + +void nfc3d_drbg_generate_bytes(const uint8_t * hmacKey, size_t hmacKeySize, const uint8_t * seed, size_t seedSize, uint8_t * output, size_t outputSize) { + uint8_t temp[NFC3D_DRBG_OUTPUT_SIZE]; + + nfc3d_drbg_ctx rngCtx; + nfc3d_drbg_init(&rngCtx, hmacKey, hmacKeySize, seed, seedSize); + + while (outputSize > 0) { + if (outputSize < NFC3D_DRBG_OUTPUT_SIZE) { + nfc3d_drbg_step(&rngCtx, temp); + memcpy(output, temp, outputSize); + break; + } + + nfc3d_drbg_step(&rngCtx, output); + output += NFC3D_DRBG_OUTPUT_SIZE; + outputSize -= NFC3D_DRBG_OUTPUT_SIZE; + } + + nfc3d_drbg_cleanup(&rngCtx); +} diff --git a/client/amiitool/drbg.h b/client/amiitool/drbg.h new file mode 100644 index 000000000..0e93abfc0 --- /dev/null +++ b/client/amiitool/drbg.h @@ -0,0 +1,33 @@ +/* + * (c) 2015-2017 Marcos Del Sol Vives + * (c) 2016 javiMaD + * + * SPDX-License-Identifier: MIT + */ + +#ifndef HAVE_NFC3D_DRBG_H +#define HAVE_NFC3D_DRBG_H + +#include +#include +#include "mbedtls/md.h" + +#define NFC3D_DRBG_MAX_SEED_SIZE 480 /* Hardcoded max size in 3DS NFC module */ +#define NFC3D_DRBG_OUTPUT_SIZE 32 /* Every iteration generates 32 bytes */ + +typedef struct { + mbedtls_md_context_t hmacCtx; + bool used; + uint16_t iteration; + + uint8_t buffer[sizeof(uint16_t) + NFC3D_DRBG_MAX_SEED_SIZE]; + size_t bufferSize; +} nfc3d_drbg_ctx; + +void nfc3d_drbg_init(nfc3d_drbg_ctx * ctx, const uint8_t * hmacKey, size_t hmacKeySize, const uint8_t * seed, size_t seedSize); +void nfc3d_drbg_step(nfc3d_drbg_ctx * ctx, uint8_t * output); +void nfc3d_drbg_cleanup(nfc3d_drbg_ctx * ctx); +void nfc3d_drbg_generate_bytes(const uint8_t * hmacKey, size_t hmacKeySize, const uint8_t * seed, size_t seedSize, uint8_t * output, size_t outputSize); + +#endif + diff --git a/client/amiitool/key_retail.bin b/client/amiitool/key_retail.bin new file mode 100644 index 0000000000000000000000000000000000000000..9ecc9e35a39e5c28c46891bb1438bca2beac5462 GIT binary patch literal 160 zcmb0Y^EQtzS{kmgQ#NJW;zO*Zd1;vysVNGXd1?8@3=Dj?z317xs`p#g{h#f>b20-1 zi>LUVvMtjbuKlpIoW{TI%6m)wRhvXKRw@1tdFsmQo>pI~t5Lj&LHys37}nAW-nlvX l$=N{Tic^z|QcD;Z1pb~_P&Q@9JRkSVwJ*-alpG{v9ssi +#include +#include + +void nfc3d_keygen_prepare_seed(const nfc3d_keygen_masterkeys * baseKeys, const uint8_t * baseSeed, uint8_t * output, size_t * outputSize) { + assert(baseKeys != NULL); + assert(baseSeed != NULL); + assert(output != NULL); + assert(outputSize != NULL); + + uint8_t * start = output; + + // 1: Copy whole type string + output = memccpy(output, baseKeys->typeString, '\0', sizeof(baseKeys->typeString)); + + // 2: Append (16 - magicBytesSize) from the input seed + size_t leadingSeedBytes = 16 - baseKeys->magicBytesSize; + memcpy(output, baseSeed, leadingSeedBytes); + output += leadingSeedBytes; + + // 3: Append all bytes from magicBytes + memcpy(output, baseKeys->magicBytes, baseKeys->magicBytesSize); + output += baseKeys->magicBytesSize; + + // 4: Append bytes 0x10-0x1F from input seed + memcpy(output, baseSeed + 0x10, 16); + output += 16; + + // 5: Xor last bytes 0x20-0x3F of input seed with AES XOR pad and append them + unsigned int i; + for (i = 0; i < 32; i++) { + output[i] = baseSeed[i + 32] ^ baseKeys->xorPad[i]; + } + output += 32; + + *outputSize = output - start; +} + +void nfc3d_keygen(const nfc3d_keygen_masterkeys * baseKeys, const uint8_t * baseSeed, nfc3d_keygen_derivedkeys * derivedKeys) { + uint8_t preparedSeed[NFC3D_DRBG_MAX_SEED_SIZE]; + size_t preparedSeedSize; + + nfc3d_keygen_prepare_seed(baseKeys, baseSeed, preparedSeed, &preparedSeedSize); + nfc3d_drbg_generate_bytes(baseKeys->hmacKey, sizeof(baseKeys->hmacKey), preparedSeed, preparedSeedSize, (uint8_t *) derivedKeys, sizeof(*derivedKeys)); +} diff --git a/client/amiitool/keygen.h b/client/amiitool/keygen.h new file mode 100644 index 000000000..35595e3ef --- /dev/null +++ b/client/amiitool/keygen.h @@ -0,0 +1,34 @@ +/* + * (c) 2015-2017 Marcos Del Sol Vives + * + * SPDX-License-Identifier: MIT + */ + +#ifndef HAVE_NFC3D_KEYGEN_H +#define HAVE_NFC3D_KEYGEN_H + +#include +#include + +#define NFC3D_KEYGEN_SEED_SIZE 64 + +#pragma pack(1) +typedef struct { + uint8_t hmacKey[16]; + char typeString[14]; + uint8_t rfu; + uint8_t magicBytesSize; + uint8_t magicBytes[16]; + uint8_t xorPad[32]; +} nfc3d_keygen_masterkeys; + +typedef struct { + const uint8_t aesKey[16]; + const uint8_t aesIV[16]; + const uint8_t hmacKey[16]; +} nfc3d_keygen_derivedkeys; +#pragma pack() + +void nfc3d_keygen(const nfc3d_keygen_masterkeys * baseKeys, const uint8_t * baseSeed, nfc3d_keygen_derivedkeys * derivedKeys); + +#endif diff --git a/client/obj/amiitool/.dummy b/client/obj/amiitool/.dummy new file mode 100644 index 000000000..e69de29bb From 88d42a1af5d244387a51508520627740a3a4f6e6 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 13:46:52 +0200 Subject: [PATCH 0339/1938] make --- client/Makefile | 1 + client/emv/emv_roca.c | 117 ++++++++++++++++++++++++++++++++++++++++++ client/emv/emv_roca.h | 41 +++++++++++++++ 3 files changed, 159 insertions(+) create mode 100644 client/emv/emv_roca.c create mode 100644 client/emv/emv_roca.h diff --git a/client/Makefile b/client/Makefile index 766163c09..4f7168fa0 100644 --- a/client/Makefile +++ b/client/Makefile @@ -155,6 +155,7 @@ CMDSRCS = crapto1/crapto1.c \ emv/test/dda_test.c\ emv/test/cda_test.c\ emv/cmdemv.c \ + emv/emv_roca.c \ mifare4.c \ cmdanalyse.c \ cmdhf.c \ diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c new file mode 100644 index 000000000..0dfaa1339 --- /dev/null +++ b/client/emv/emv_roca.c @@ -0,0 +1,117 @@ +/* roca.c - ROCA (CVE-2017-15361) fingerprint checker. + * Written by Rob Stradling (based on https://github.com/crocs-muni/roca/blob/master/roca/detect.py) + * Copyright (C) 2017 COMODO CA Limited + * + * 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 3 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, see . + */ + +#include "emv_roca.h" + +static uint8_t g_primes[ROCA_PRINTS_LENGTH] = { + 11, 13, 17, 19, 37, 53, 61, 71, 73, 79, 97, 103, 107, 109, 127, 151, 157 +}; + +mbedtls_mpi* g_prints[ROCA_PRINTS_LENGTH]; + +void rocacheck_init(void) { + + for (uint8_t i = 0; i < ROCA_PRINTS_LENGTH; i++) + mbedtls_mpi_init(g_prints[i]); + + mbedtls_mpi_read_string(g_prints[0], 10, "1026"); + mbedtls_mpi_read_string(g_prints[1], 10, "5658"); + mbedtls_mpi_read_string(g_prints[2], 10, "107286"); + mbedtls_mpi_read_string(g_prints[3], 10, "199410"); + mbedtls_mpi_read_string(g_prints[4], 10, "67109890"); + mbedtls_mpi_read_string(g_prints[5], 10, "5310023542746834"); + mbedtls_mpi_read_string(g_prints[6], 10, "1455791217086302986"); + mbedtls_mpi_read_string(g_prints[7], 10, "20052041432995567486"); + mbedtls_mpi_read_string(g_prints[8], 10, "6041388139249378920330"); + mbedtls_mpi_read_string(g_prints[9], 10, "207530445072488465666"); + mbedtls_mpi_read_string(g_prints[10], 10, "79228162521181866724264247298"); + mbedtls_mpi_read_string(g_prints[11], 10, "1760368345969468176824550810518"); + mbedtls_mpi_read_string(g_prints[12], 10, "50079290986288516948354744811034"); + mbedtls_mpi_read_string(g_prints[13], 10, "473022961816146413042658758988474"); + mbedtls_mpi_read_string(g_prints[14], 10, "144390480366845522447407333004847678774"); + mbedtls_mpi_read_string(g_prints[15], 10, "1800793591454480341970779146165214289059119882"); + mbedtls_mpi_read_string(g_prints[16], 10, "126304807362733370595828809000324029340048915994"); +} + +void rocacheck_cleanup(void) { + for (uint8_t i = 0; i < ROCA_PRINTS_LENGTH; i++) + mbedtls_mpi_free(g_prints[i]); +} + +int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ) { + + for (int i = 0; i < mbedtls_mpi_bitlen(a); i++) { + + if (mbedtls_mpi_get_bit(a, i) && mbedtls_mpi_get_bit(b, i)) + return 0; + } + return 1; +} + + +bool emv_rocacheck(char *modulus) { + + mbedtls_mpi *t_modulus = NULL; + mbedtls_mpi_init(t_modulus); + + bool ret = true; + + rocacheck_init(); + + // + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(t_modulus, 10, modulus) ); + + + for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) { + + mbedtls_mpi* t_temp = NULL; + mbedtls_mpi* t_prime = NULL; + mbedtls_mpi* g_one = NULL; + + mbedtls_mpi_init(g_one); + mbedtls_mpi_init(t_temp); + mbedtls_mpi_init(t_prime); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(g_one, 10, "1") ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(t_prime, t_prime, g_primes[i]) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi(t_temp, t_modulus, t_prime) ); + + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(g_one, t_temp) ); + + if (bitand_is_zero(t_temp, g_prints[i])) { + PrintAndLogEx(FAILED, "No fingerprint found\n"); + ret = false; + goto cleanup; + } + + mbedtls_mpi_free(g_one); + mbedtls_mpi_free(t_temp); + mbedtls_mpi_free(t_prime); + } + + PrintAndLogEx(SUCCESS, "Fingerprint found!\n"); + +cleanup: + if (t_modulus) + mbedtls_mpi_free(t_modulus); + + rocacheck_cleanup(); + return ret; +} diff --git a/client/emv/emv_roca.h b/client/emv/emv_roca.h new file mode 100644 index 000000000..e2ba0ac51 --- /dev/null +++ b/client/emv/emv_roca.h @@ -0,0 +1,41 @@ + +// ROCA (CVE-2017-15361) fingerprint checker. +// Written by Rob Stradling (based on https://github.com/crocs-muni/roca/blob/master/roca/detect.py) +// Copyright (C) 2017 COMODO CA Limited +// modified 2018 iceman (dropped openssl bignum, now use mbedtls lib) +// +// 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 3 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, see . +// +//----------------------------------------------------------------------------- +// EMV roca commands +//----------------------------------------------------------------------------- + +#ifndef EMV_ROCA_H__ +#define EMV_ROCA_H__ + +#include +#include +#include "mbedtls/bignum.h" +#include "util.h" + +#define ROCA_PRINTS_LENGTH 17 + +void rocacheck_init(void); +void rocacheck_cleanup(void); +int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ); + +extern bool emv_rocacheck( char *modulus ); + +#endif + From b1145ba57771237d5a7b8223f2f5746863b5f418 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 14:50:23 +0200 Subject: [PATCH 0340/1938] mpi_get_uint --- client/emv/emv_roca.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 0dfaa1339..2843cb2c1 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -64,6 +64,15 @@ int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ) { } +mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) { + + if (X->n == 1) { + return X->p[0]; + } + + return 0; +} + bool emv_rocacheck(char *modulus) { mbedtls_mpi *t_modulus = NULL; @@ -93,7 +102,7 @@ bool emv_rocacheck(char *modulus) { MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi(t_temp, t_modulus, t_prime) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(g_one, t_temp) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(g_one, mpi_get_uint(t_temp)) ); if (bitand_is_zero(t_temp, g_prints[i])) { PrintAndLogEx(FAILED, "No fingerprint found\n"); From 9804526dca774c21f617b3b13d431826e3c7a685 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 14:52:24 +0200 Subject: [PATCH 0341/1938] small fix for unsigned int --- client/emv/emv_roca.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 2843cb2c1..48845c99f 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -66,7 +66,7 @@ int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ) { mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) { - if (X->n == 1) { + if (X->n == 1 && X->s > 0) { return X->p[0]; } From ab41b4a991fe4e75c1ebd6c3056ac1667f8d0e2a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 16:40:53 +0200 Subject: [PATCH 0342/1938] emv_rocacheck --- client/emv/cmdemv.h | 1 + client/emv/emv_roca.c | 5 ++--- client/emv/emv_roca.h | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/emv/cmdemv.h b/client/emv/cmdemv.h index 0b0419b07..c91f75606 100644 --- a/client/emv/cmdemv.h +++ b/client/emv/cmdemv.h @@ -25,6 +25,7 @@ #include "cmdmain.h" #include "emvcore.h" #include "apduinfo.h" +#include "emv_roca.h" int CmdEMV(const char *Cmd); diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 48845c99f..fe68b83ce 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -73,7 +73,7 @@ mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) { return 0; } -bool emv_rocacheck(char *modulus) { +bool emv_rocacheck(const unsigned char *buf, size_t buflen) { mbedtls_mpi *t_modulus = NULL; mbedtls_mpi_init(t_modulus); @@ -82,8 +82,7 @@ bool emv_rocacheck(char *modulus) { rocacheck_init(); - // - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(t_modulus, 10, modulus) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(t_modulus, buf, buflen) ); for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) { diff --git a/client/emv/emv_roca.h b/client/emv/emv_roca.h index e2ba0ac51..a42d8349e 100644 --- a/client/emv/emv_roca.h +++ b/client/emv/emv_roca.h @@ -35,7 +35,7 @@ void rocacheck_init(void); void rocacheck_cleanup(void); int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ); -extern bool emv_rocacheck( char *modulus ); +extern bool emv_rocacheck( const unsigned char *buf, size_t buflen ); #endif From 8e5133582d98e3f37cd2e94d5585678f10d456e1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 16:43:15 +0200 Subject: [PATCH 0343/1938] `emv roca` select app --- client/emv/cmdemv.c | 81 +++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 75 insertions(+), 6 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 1029d5a7e..d3ec26c53 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1464,6 +1464,12 @@ int CmdEMVTest(const char *cmd) { } int CmdEMVRoca(const char *cmd) { + uint8_t AID[APDU_AID_LEN] = {0}; + size_t AIDlen = 0; + uint8_t buf[APDU_RES_LEN] = {0}; + size_t len = 0; + uint16_t sw = 0; + int res; CLIParserInit("emv roca", "Tries to extract public keys and run the ROCA test against them.\n", @@ -1481,16 +1487,71 @@ int CmdEMVRoca(const char *cmd) { if (arg_get_lit(1)) channel = ECC_CONTACT; + // select card + uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; + + // init applets list tree + const char *al = "Applets list"; + struct tlvdb *tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al); + + // EMV PPSE + PrintAndLogEx(NORMAL, "--> PPSE."); + res = EMVSelectPSE(channel, true, true, psenum, buf, sizeof(buf), &len, &sw); + + if (!res && sw == 0x9000){ + struct tlvdb *fci = tlvdb_parse_multi(buf, len); + tlvdb_free(fci); + } + + SetAPDULogging(false); + res = EMVSearchPSE(channel, false, true, false, tlvSelect); + + // check PPSE and select application id + if (!res) { + TLVPrintAIDlistFromSelectTLV(tlvSelect); + } else { + // EMV SEARCH with AID list + PrintAndLogEx(NORMAL, "--> AID search."); + if (EMVSearch(channel, false, true, false, tlvSelect)) { + PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit..."); + tlvdb_free(tlvSelect); + DropField(); + return 3; + } + + // check search and select application id + TLVPrintAIDlistFromSelectTLV(tlvSelect); + } + + // EMV SELECT application + SetAPDULogging(false); + EMVSelectApplication(tlvSelect, AID, &AIDlen); + + tlvdb_free(tlvSelect); + + if (!AIDlen) { + PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit..."); + DropField(); + return 4; + } + // Init TLV tree const char *alr = "Root terminal TLV tree"; struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr); - // select card - uint8_t buf[APDU_RES_LEN] = {0}; - size_t len = 0; - uint16_t sw = 0; - uint8_t psenum = (channel == ECC_CONTACT) ? 1: 2; - int res = EMVSelectPSE(channel, true, true, psenum, buf, sizeof(buf), &len, &sw); + // EMV SELECT applet + PrintAndLogEx(NORMAL, "\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen)); + res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot); + + if (res) { + PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res); + tlvdb_free(tlvRoot); + DropField(); + return 5; + } + + + // getting certificates if (tlvdb_get(tlvRoot, 0x90, NULL)) { @@ -1530,8 +1591,16 @@ int CmdEMVRoca(const char *cmd) { sprint_hex(icc_pk->serial, 3) ); + // icc_pk->exp, icc_pk->elen // icc_pk->modulus, icc_pk->mlen + if (icc_pk->elen > 0 && icc_pk->mlen > 0) { + if (emv_rocacheck(icc_pk->modulus, icc_pk->mlen)) { + PrintAndLogEx(INFO, "ICC pk is vulnerable by roca."); + } else { + PrintAndLogEx(INFO, "ICC pk is OK("); + } + } PKISetStrictExecution(true); From b0c1828c1defffeca88b150abfed924fc5125929 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 16:58:11 +0200 Subject: [PATCH 0344/1938] load params --- client/emv/cmdemv.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index d3ec26c53..c058c9913 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1550,6 +1550,8 @@ int CmdEMVRoca(const char *cmd) { return 5; } + PrintAndLog("\n* Init transaction parameters."); + InitTransactionParameters(tlvRoot, true, TT_QVSDCMCHIP, false); From 67b7edeb44756c332cd90f0caf185d2a942b7190 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 17:07:58 +0200 Subject: [PATCH 0345/1938] extract keys works --- client/emv/cmdemv.c | 75 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 71 insertions(+), 4 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index c058c9913..7922bc616 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1553,8 +1553,74 @@ int CmdEMVRoca(const char *cmd) { PrintAndLog("\n* Init transaction parameters."); InitTransactionParameters(tlvRoot, true, TT_QVSDCMCHIP, false); - + PrintAndLogEx(NORMAL, "-->Calc PDOL."); + struct tlv *pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83); + if (!pdol_data_tlv){ + PrintAndLogEx(ERR, "Can't create PDOL TLV."); + tlvdb_free(tlvRoot); + DropField(); + return 6; + } + size_t pdol_data_tlv_data_len; + unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len); + if (!pdol_data_tlv_data) { + PrintAndLogEx(ERR, "Can't create PDOL data."); + tlvdb_free(tlvRoot); + DropField(); + return 6; + } + PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); + + PrintAndLogEx(INFO, "-->GPO."); + res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot); + + free(pdol_data_tlv_data); + free(pdol_data_tlv); + + if (res) { + PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw); + tlvdb_free(tlvRoot); + DropField(); + return 7; + } + ProcessGPOResponseFormat1(tlvRoot, buf, len, false); + + PrintAndLogEx(INFO, "-->Read records from AFL."); + const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL); + + while(AFL && AFL->len) { + if (AFL->len % 4) { + PrintAndLogEx(ERR, "Wrong AFL length: %d", AFL->len); + break; + } + + for (int i = 0; i < AFL->len / 4; i++) { + uint8_t SFI = AFL->value[i * 4 + 0] >> 3; + uint8_t SFIstart = AFL->value[i * 4 + 1]; + uint8_t SFIend = AFL->value[i * 4 + 2]; + uint8_t SFIoffline = AFL->value[i * 4 + 3]; + + PrintAndLogEx(INFO, "--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline); + if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) { + PrintAndLogEx(ERR, "SFI ERROR! Skipped..."); + continue; + } + + for(int n = SFIstart; n <= SFIend; n++) { + PrintAndLogEx(INFO, "---->SFI[%02x] %d", SFI, n); + + res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot); + if (res) { + PrintAndLogEx(ERR, "SFI[%02x]. APDU error %4x", SFI, sw); + continue; + } + } + } + + break; + } + // getting certificates if (tlvdb_get(tlvRoot, 0x90, NULL)) { PrintAndLogEx(INFO, "-->Recovering certificates."); @@ -1593,9 +1659,10 @@ int CmdEMVRoca(const char *cmd) { sprint_hex(icc_pk->serial, 3) ); - -// icc_pk->exp, icc_pk->elen -// icc_pk->modulus, icc_pk->mlen + PrintAndLogEx(INFO, "ICC pk modulus: %s", sprint_hex_inrow(icc_pk->modulus, icc_pk->mlen)); + + // icc_pk->exp, icc_pk->elen + // icc_pk->modulus, icc_pk->mlen if (icc_pk->elen > 0 && icc_pk->mlen > 0) { if (emv_rocacheck(icc_pk->modulus, icc_pk->mlen)) { PrintAndLogEx(INFO, "ICC pk is vulnerable by roca."); From 625b696291d734c14d420bcd55e88ffe1c40e34c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 17:25:11 +0200 Subject: [PATCH 0346/1938] roca works --- client/emv/emv_roca.c | 85 +++++++++++++++++++++---------------------- 1 file changed, 42 insertions(+), 43 deletions(-) diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index fe68b83ce..2aaa10875 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -22,35 +22,35 @@ static uint8_t g_primes[ROCA_PRINTS_LENGTH] = { 11, 13, 17, 19, 37, 53, 61, 71, 73, 79, 97, 103, 107, 109, 127, 151, 157 }; -mbedtls_mpi* g_prints[ROCA_PRINTS_LENGTH]; +mbedtls_mpi g_prints[ROCA_PRINTS_LENGTH]; void rocacheck_init(void) { - for (uint8_t i = 0; i < ROCA_PRINTS_LENGTH; i++) - mbedtls_mpi_init(g_prints[i]); + for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) + mbedtls_mpi_init(&g_prints[i]); - mbedtls_mpi_read_string(g_prints[0], 10, "1026"); - mbedtls_mpi_read_string(g_prints[1], 10, "5658"); - mbedtls_mpi_read_string(g_prints[2], 10, "107286"); - mbedtls_mpi_read_string(g_prints[3], 10, "199410"); - mbedtls_mpi_read_string(g_prints[4], 10, "67109890"); - mbedtls_mpi_read_string(g_prints[5], 10, "5310023542746834"); - mbedtls_mpi_read_string(g_prints[6], 10, "1455791217086302986"); - mbedtls_mpi_read_string(g_prints[7], 10, "20052041432995567486"); - mbedtls_mpi_read_string(g_prints[8], 10, "6041388139249378920330"); - mbedtls_mpi_read_string(g_prints[9], 10, "207530445072488465666"); - mbedtls_mpi_read_string(g_prints[10], 10, "79228162521181866724264247298"); - mbedtls_mpi_read_string(g_prints[11], 10, "1760368345969468176824550810518"); - mbedtls_mpi_read_string(g_prints[12], 10, "50079290986288516948354744811034"); - mbedtls_mpi_read_string(g_prints[13], 10, "473022961816146413042658758988474"); - mbedtls_mpi_read_string(g_prints[14], 10, "144390480366845522447407333004847678774"); - mbedtls_mpi_read_string(g_prints[15], 10, "1800793591454480341970779146165214289059119882"); - mbedtls_mpi_read_string(g_prints[16], 10, "126304807362733370595828809000324029340048915994"); + mbedtls_mpi_read_string(&g_prints[0], 10, "1026"); + mbedtls_mpi_read_string(&g_prints[1], 10, "5658"); + mbedtls_mpi_read_string(&g_prints[2], 10, "107286"); + mbedtls_mpi_read_string(&g_prints[3], 10, "199410"); + mbedtls_mpi_read_string(&g_prints[4], 10, "67109890"); + mbedtls_mpi_read_string(&g_prints[5], 10, "5310023542746834"); + mbedtls_mpi_read_string(&g_prints[6], 10, "1455791217086302986"); + mbedtls_mpi_read_string(&g_prints[7], 10, "20052041432995567486"); + mbedtls_mpi_read_string(&g_prints[8], 10, "6041388139249378920330"); + mbedtls_mpi_read_string(&g_prints[9], 10, "207530445072488465666"); + mbedtls_mpi_read_string(&g_prints[10], 10, "79228162521181866724264247298"); + mbedtls_mpi_read_string(&g_prints[11], 10, "1760368345969468176824550810518"); + mbedtls_mpi_read_string(&g_prints[12], 10, "50079290986288516948354744811034"); + mbedtls_mpi_read_string(&g_prints[13], 10, "473022961816146413042658758988474"); + mbedtls_mpi_read_string(&g_prints[14], 10, "144390480366845522447407333004847678774"); + mbedtls_mpi_read_string(&g_prints[15], 10, "1800793591454480341970779146165214289059119882"); + mbedtls_mpi_read_string(&g_prints[16], 10, "126304807362733370595828809000324029340048915994"); } void rocacheck_cleanup(void) { - for (uint8_t i = 0; i < ROCA_PRINTS_LENGTH; i++) - mbedtls_mpi_free(g_prints[i]); + for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) + mbedtls_mpi_free(&g_prints[i]); } int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ) { @@ -75,50 +75,49 @@ mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) { bool emv_rocacheck(const unsigned char *buf, size_t buflen) { - mbedtls_mpi *t_modulus = NULL; - mbedtls_mpi_init(t_modulus); + mbedtls_mpi t_modulus; + mbedtls_mpi_init(&t_modulus); bool ret = true; rocacheck_init(); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(t_modulus, buf, buflen) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(&t_modulus, buf, buflen) ); + mbedtls_mpi_init(&g_one); + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") ); for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) { +printf("--p:%d\n", i); - mbedtls_mpi* t_temp = NULL; - mbedtls_mpi* t_prime = NULL; - mbedtls_mpi* g_one = NULL; + mbedtls_mpi t_temp; + mbedtls_mpi t_prime; + mbedtls_mpi g_one; - mbedtls_mpi_init(g_one); - mbedtls_mpi_init(t_temp); - mbedtls_mpi_init(t_prime); + mbedtls_mpi_init(&t_temp); + mbedtls_mpi_init(&t_prime); + + MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(&t_prime, &t_prime, g_primes[i]) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(g_one, 10, "1") ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(t_prime, t_prime, g_primes[i]) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi(&t_temp, &t_modulus, &t_prime) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi(t_temp, t_modulus, t_prime) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(&g_one, mpi_get_uint(&t_temp)) ); - MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(g_one, mpi_get_uint(t_temp)) ); - - if (bitand_is_zero(t_temp, g_prints[i])) { + if (bitand_is_zero(&t_temp, &g_prints[i])) { PrintAndLogEx(FAILED, "No fingerprint found\n"); ret = false; goto cleanup; } - mbedtls_mpi_free(g_one); - mbedtls_mpi_free(t_temp); - mbedtls_mpi_free(t_prime); + mbedtls_mpi_free(&g_one); + mbedtls_mpi_free(&t_temp); + mbedtls_mpi_free(&t_prime); } PrintAndLogEx(SUCCESS, "Fingerprint found!\n"); cleanup: - if (t_modulus) - mbedtls_mpi_free(t_modulus); + mbedtls_mpi_free(&t_modulus); rocacheck_cleanup(); return ret; From 6afda099db761b9793a126f3616e33ebad7db315 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 17:46:57 +0200 Subject: [PATCH 0347/1938] added test/ not works --- client/emv/cmdemv.c | 6 ++++++ client/emv/emv_roca.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 7922bc616..a42002c60 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1661,6 +1661,12 @@ int CmdEMVRoca(const char *cmd) { PrintAndLogEx(INFO, "ICC pk modulus: %s", sprint_hex_inrow(icc_pk->modulus, icc_pk->mlen)); + + uint8_t key[] = "944e13208a280c37efc31c3114485e590192adbb8e11c87cad60cdef0037ce99278330d3f471a2538fa667802ed2a3c44a8b7dea826e888d0aa341fd664f7fa7"; + if (emv_rocacheck(key, 64)) + PrintAndLogEx(INFO, "DEMO ICC pk is vulnerable by roca."); + + // icc_pk->exp, icc_pk->elen // icc_pk->modulus, icc_pk->mlen if (icc_pk->elen > 0 && icc_pk->mlen > 0) { diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 2aaa10875..42bcce6db 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -84,6 +84,7 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen) { MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(&t_modulus, buf, buflen) ); + mbedtls_mpi g_one; mbedtls_mpi_init(&g_one); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") ); @@ -92,7 +93,6 @@ printf("--p:%d\n", i); mbedtls_mpi t_temp; mbedtls_mpi t_prime; - mbedtls_mpi g_one; mbedtls_mpi_init(&t_temp); mbedtls_mpi_init(&t_prime); From 18225c7c7f0b466b7d77f500975c3bbb2867926b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 17:48:52 +0200 Subject: [PATCH 0348/1938] some fix --- client/emv/cmdemv.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index a42002c60..c1ae8b1f3 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1662,7 +1662,10 @@ int CmdEMVRoca(const char *cmd) { PrintAndLogEx(INFO, "ICC pk modulus: %s", sprint_hex_inrow(icc_pk->modulus, icc_pk->mlen)); - uint8_t key[] = "944e13208a280c37efc31c3114485e590192adbb8e11c87cad60cdef0037ce99278330d3f471a2538fa667802ed2a3c44a8b7dea826e888d0aa341fd664f7fa7"; + uint8_t key[] = "\x94\x4e\x13\x20\x8a\x28\x0c\x37\xef\xc3\x1c\x31\x14\x48\x5e\x59"\ + "\x01\x92\xad\xbb\x8e\x11\xc8\x7c\xad\x60\xcd\xef\x00\x37\xce\x99"\ + "\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\ + "\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7"; if (emv_rocacheck(key, 64)) PrintAndLogEx(INFO, "DEMO ICC pk is vulnerable by roca."); From 404f23ddbd6ae3df7f8065999250d29f9af442be Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 17:50:51 +0200 Subject: [PATCH 0349/1938] small fix --- client/emv/cmdemv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index c1ae8b1f3..16e5c4765 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1674,7 +1674,7 @@ int CmdEMVRoca(const char *cmd) { // icc_pk->modulus, icc_pk->mlen if (icc_pk->elen > 0 && icc_pk->mlen > 0) { if (emv_rocacheck(icc_pk->modulus, icc_pk->mlen)) { - PrintAndLogEx(INFO, "ICC pk is vulnerable by roca."); + PrintAndLogEx(INFO, "ICC pk is a subject to ROCA vulnerability, insecure.."); } else { PrintAndLogEx(INFO, "ICC pk is OK("); } From 5eafc491ec91ccdf7b98ff33f2daa3cd6352b330 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 18:00:37 +0200 Subject: [PATCH 0350/1938] small add --- client/emv/cmdemv.c | 1 + client/emv/emv_roca.c | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 16e5c4765..adb47b136 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1666,6 +1666,7 @@ int CmdEMVRoca(const char *cmd) { "\x01\x92\xad\xbb\x8e\x11\xc8\x7c\xad\x60\xcd\xef\x00\x37\xce\x99"\ "\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\ "\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7"; + PrintAndLogEx(INFO, "DEMO ICC pk modulus: %s", sprint_hex_inrow(key, 64)); if (emv_rocacheck(key, 64)) PrintAndLogEx(INFO, "DEMO ICC pk is vulnerable by roca."); diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 42bcce6db..88a7b21ad 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -69,7 +69,7 @@ mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) { if (X->n == 1 && X->s > 0) { return X->p[0]; } - + printf("ZERRRRO!!!\n"); return 0; } @@ -89,7 +89,7 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen) { MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") ); for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) { -printf("--p:%d\n", i); +printf("--roca:%d\n", i); mbedtls_mpi t_temp; mbedtls_mpi t_prime; From f1cd108b1a432132c922fe62b6c9966f26fdec43 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 18:09:20 +0200 Subject: [PATCH 0351/1938] move g_one to cycle --- client/emv/emv_roca.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 88a7b21ad..53fd91c15 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -84,18 +84,19 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen) { MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(&t_modulus, buf, buflen) ); - mbedtls_mpi g_one; - mbedtls_mpi_init(&g_one); - MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") ); for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) { printf("--roca:%d\n", i); mbedtls_mpi t_temp; mbedtls_mpi t_prime; + mbedtls_mpi g_one; mbedtls_mpi_init(&t_temp); mbedtls_mpi_init(&t_prime); + mbedtls_mpi_init(&g_one); + + MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(&t_prime, &t_prime, g_primes[i]) ); From 05814fbe75bd9e77dbf589c3fdf0c8c287e6a0dc Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 19:06:51 +0200 Subject: [PATCH 0352/1938] added mpi print --- client/emv/emv_roca.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 53fd91c15..ad39d1043 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -73,6 +73,15 @@ mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) { return 0; } +void print_mpi(const char *msg, int radix, const mbedtls_mpi *X) { + + char Xchar[400] = {0}; + size_t len = 0; + + mbedtls_mpi_write_string(X, radix, Xchar, sizeof(Xchar), &len); + printf("%s[%d] %s\n", msg, len, Xchar); +} + bool emv_rocacheck(const unsigned char *buf, size_t buflen) { mbedtls_mpi t_modulus; @@ -83,6 +92,7 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen) { rocacheck_init(); MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(&t_modulus, buf, buflen) ); + print_mpi("--t_modulus:", 16, &t_modulus); for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) { From 44343d806fa74594ac3f4f4c930599a7be787511 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 19:25:19 +0200 Subject: [PATCH 0353/1938] add some debug --- client/emv/emv_roca.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index ad39d1043..9297ce452 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -109,11 +109,15 @@ printf("--roca:%d\n", i); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(&t_prime, &t_prime, g_primes[i]) ); + print_mpi("--t_prime:", 10, &t_prime); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi(&t_temp, &t_modulus, &t_prime) ); + print_mpi("--t_temp:", 10, &t_temp); MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(&g_one, mpi_get_uint(&t_temp)) ); + print_mpi("--g_one:", 10, &g_one); + print_mpi("--g_prints:", 10, &g_prints[i]); if (bitand_is_zero(&t_temp, &g_prints[i])) { PrintAndLogEx(FAILED, "No fingerprint found\n"); ret = false; From e315328625d9cc632dc8223d0f46e398730cb9bc Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 20:06:18 +0200 Subject: [PATCH 0354/1938] works --- client/emv/emv_roca.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 9297ce452..977584f73 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -92,11 +92,8 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen) { rocacheck_init(); MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(&t_modulus, buf, buflen) ); - print_mpi("--t_modulus:", 16, &t_modulus); - for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) { -printf("--roca:%d\n", i); mbedtls_mpi t_temp; mbedtls_mpi t_prime; @@ -109,17 +106,13 @@ printf("--roca:%d\n", i); MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(&t_prime, &t_prime, g_primes[i]) ); - print_mpi("--t_prime:", 10, &t_prime); MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi(&t_temp, &t_modulus, &t_prime) ); - print_mpi("--t_temp:", 10, &t_temp); MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(&g_one, mpi_get_uint(&t_temp)) ); - print_mpi("--g_one:", 10, &g_one); - print_mpi("--g_prints:", 10, &g_prints[i]); - if (bitand_is_zero(&t_temp, &g_prints[i])) { - PrintAndLogEx(FAILED, "No fingerprint found\n"); + if (bitand_is_zero(&g_one, &g_prints[i])) { + PrintAndLogEx(FAILED, "No fingerprint found.\n"); ret = false; goto cleanup; } From 7401d51ebf256b723e10e3db875feafaefe01c5c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 20:33:24 +0200 Subject: [PATCH 0355/1938] roca works --- client/emv/cmdemv.c | 15 ++--------- client/emv/emv_roca.c | 58 +++++++++++++++++++++++++++++++++++++++---- client/emv/emv_roca.h | 7 ++---- 3 files changed, 57 insertions(+), 23 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index adb47b136..4cbbe2e0b 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1661,26 +1661,15 @@ int CmdEMVRoca(const char *cmd) { PrintAndLogEx(INFO, "ICC pk modulus: %s", sprint_hex_inrow(icc_pk->modulus, icc_pk->mlen)); - - uint8_t key[] = "\x94\x4e\x13\x20\x8a\x28\x0c\x37\xef\xc3\x1c\x31\x14\x48\x5e\x59"\ - "\x01\x92\xad\xbb\x8e\x11\xc8\x7c\xad\x60\xcd\xef\x00\x37\xce\x99"\ - "\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\ - "\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7"; - PrintAndLogEx(INFO, "DEMO ICC pk modulus: %s", sprint_hex_inrow(key, 64)); - if (emv_rocacheck(key, 64)) - PrintAndLogEx(INFO, "DEMO ICC pk is vulnerable by roca."); - - // icc_pk->exp, icc_pk->elen // icc_pk->modulus, icc_pk->mlen if (icc_pk->elen > 0 && icc_pk->mlen > 0) { - if (emv_rocacheck(icc_pk->modulus, icc_pk->mlen)) { + if (emv_rocacheck(icc_pk->modulus, icc_pk->mlen, true)) { PrintAndLogEx(INFO, "ICC pk is a subject to ROCA vulnerability, insecure.."); } else { PrintAndLogEx(INFO, "ICC pk is OK("); } - } - + } PKISetStrictExecution(true); } diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 977584f73..5081ed446 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -82,12 +82,12 @@ void print_mpi(const char *msg, int radix, const mbedtls_mpi *X) { printf("%s[%d] %s\n", msg, len, Xchar); } -bool emv_rocacheck(const unsigned char *buf, size_t buflen) { +bool emv_rocacheck(const unsigned char *buf, size_t buflen, bool verbose) { mbedtls_mpi t_modulus; mbedtls_mpi_init(&t_modulus); - bool ret = true; + bool ret = false; rocacheck_init(); @@ -112,8 +112,8 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen) { MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(&g_one, mpi_get_uint(&t_temp)) ); if (bitand_is_zero(&g_one, &g_prints[i])) { - PrintAndLogEx(FAILED, "No fingerprint found.\n"); - ret = false; + if (verbose) + PrintAndLogEx(FAILED, "No fingerprint found.\n"); goto cleanup; } @@ -122,7 +122,9 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen) { mbedtls_mpi_free(&t_prime); } - PrintAndLogEx(SUCCESS, "Fingerprint found!\n"); + ret = true; + if (verbose) + PrintAndLogEx(SUCCESS, "Fingerprint found!\n"); cleanup: mbedtls_mpi_free(&t_modulus); @@ -130,3 +132,49 @@ cleanup: rocacheck_cleanup(); return ret; } + +int roca_self_test( int verbose ) { + int ret = 0; + + if( verbose != 0 ) + printf( "\nROCA check vulnerability tests\n" ); + + // positive + uint8_t keyp[] = "\x94\x4e\x13\x20\x8a\x28\x0c\x37\xef\xc3\x1c\x31\x14\x48\x5e\x59"\ + "\x01\x92\xad\xbb\x8e\x11\xc8\x7c\xad\x60\xcd\xef\x00\x37\xce\x99"\ + "\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\ + "\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7"; + + if( verbose != 0 ) + printf( " ROCA positive test: " ); + + if (emv_rocacheck(keyp, 64, false)) { + if( verbose != 0 ) + printf( "passed\n" ); + } else { + ret = 1; + if( verbose != 0 ) + printf( "failed\n" ); + } + + // negative + uint8_t keyn[] = "\x84\x4e\x13\x20\x8a\x28\x0c\x37\xef\xc3\x1c\x31\x14\x48\x5e\x59"\ + "\x01\x92\xad\xbb\x8e\x11\xc8\x7c\xad\x60\xcd\xef\x00\x37\xce\x99"\ + "\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\ + "\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7"; + + if( verbose != 0 ) + printf( " ROCA negative test: " ); + + if (emv_rocacheck(keyn, 64, false)) { + ret = 1; + if( verbose != 0 ) + printf( "failed\n" ); + } else { + if( verbose != 0 ) + printf( "passed\n" ); + } + + + return ret; +} diff --git a/client/emv/emv_roca.h b/client/emv/emv_roca.h index a42d8349e..a9559ef79 100644 --- a/client/emv/emv_roca.h +++ b/client/emv/emv_roca.h @@ -31,11 +31,8 @@ #define ROCA_PRINTS_LENGTH 17 -void rocacheck_init(void); -void rocacheck_cleanup(void); -int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ); - -extern bool emv_rocacheck( const unsigned char *buf, size_t buflen ); +extern bool emv_rocacheck( const unsigned char *buf, size_t buflen, bool verbose ); +extern int roca_self_test( int verbose ); #endif From 376ead028a07aa4ff4b4818259d762fb7f6438c9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 20:33:38 +0200 Subject: [PATCH 0356/1938] added tests --- client/emv/test/cryptotest.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/emv/test/cryptotest.c b/client/emv/test/cryptotest.c index 1d5891fe0..b0212a70b 100644 --- a/client/emv/test/cryptotest.c +++ b/client/emv/test/cryptotest.c @@ -31,6 +31,7 @@ #include "dda_test.h" #include "cda_test.h" #include "crypto/libpcrypto.h" +#include "emv/emv_roca.h" int ExecuteCryptoTests(bool verbose) { int res; @@ -90,6 +91,9 @@ int ExecuteCryptoTests(bool verbose) { res = exec_crypto_test(verbose); if (res) TestFail = true; + res = roca_self_test(verbose); + if (res) TestFail = true; + PrintAndLog("\n--------------------------"); if (TestFail) PrintAndLog("Test(s) [ERROR]."); From 392687499591d30437af625d203d8fa90e0dff20 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 28 Dec 2018 20:48:45 +0200 Subject: [PATCH 0357/1938] fix pse channels --- client/emv/cmdemv.c | 18 +++++++----------- client/emv/emvcore.c | 4 ++-- client/emv/emvcore.h | 2 +- 3 files changed, 10 insertions(+), 14 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 4cbbe2e0b..a443f6aad 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -722,6 +722,7 @@ int CmdEMVExec(const char *cmd) { EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(11)) channel = ECC_CONTACT; + uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; CLIParserFree(); SetAPDULogging(showAPDU); @@ -736,7 +737,7 @@ int CmdEMVExec(const char *cmd) { // PPSE PrintAndLogEx(NORMAL, "\n* PPSE."); SetAPDULogging(showAPDU); - res = EMVSearchPSE(channel, activateField, true, decodeTLV, tlvSelect); + res = EMVSearchPSE(channel, activateField, true, psenum, decodeTLV, tlvSelect); // check PPSE and select application id if (!res) { @@ -1170,6 +1171,7 @@ int CmdEMVScan(const char *cmd) { EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(11)) channel = ECC_CONTACT; + uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; uint8_t relfname[250] ={0}; char *crelfname = (char *)relfname; int relfnamelen = 0; @@ -1248,7 +1250,7 @@ int CmdEMVScan(const char *cmd) { tlvdb_free(fci); } - res = EMVSearchPSE(channel, false, true, decodeTLV, tlvSelect); + res = EMVSearchPSE(channel, false, true, psenum, decodeTLV, tlvSelect); // check PPSE and select application id if (!res) { @@ -1490,21 +1492,15 @@ int CmdEMVRoca(const char *cmd) { // select card uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; + SetAPDULogging(false); + // init applets list tree const char *al = "Applets list"; struct tlvdb *tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al); // EMV PPSE PrintAndLogEx(NORMAL, "--> PPSE."); - res = EMVSelectPSE(channel, true, true, psenum, buf, sizeof(buf), &len, &sw); - - if (!res && sw == 0x9000){ - struct tlvdb *fci = tlvdb_parse_multi(buf, len); - tlvdb_free(fci); - } - - SetAPDULogging(false); - res = EMVSearchPSE(channel, false, true, false, tlvSelect); + res = EMVSearchPSE(channel, false, true, psenum, false, tlvSelect); // check PPSE and select application id if (!res) { diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index b67e7ac76..b582792ac 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -332,14 +332,14 @@ int EMVSelectPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO return res; } -int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv) { +int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv) { uint8_t data[APDU_RES_LEN] = {0}; size_t datalen = 0; uint16_t sw = 0; int res; // select PPSE - res = EMVSelectPSE(channel, ActivateField, true, 2, data, sizeof(data), &datalen, &sw); + res = EMVSelectPSE(channel, ActivateField, true, PSENum, data, sizeof(data), &datalen, &sw); if (!res){ struct tlvdb *t = NULL; diff --git a/client/emv/emvcore.h b/client/emv/emvcore.h index 829107126..7d53e83bb 100644 --- a/client/emv/emvcore.h +++ b/client/emv/emvcore.h @@ -79,7 +79,7 @@ extern void SetAPDULogging(bool logging); extern int EMVExchange(EMVCommandChannel channel, bool LeaveFieldON, sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); // search application -extern int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv); +extern int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv); extern int EMVSearch(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, bool decodeTLV, struct tlvdb *tlv); extern int EMVSelectPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw); extern int EMVSelect(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv); From 690a8e604aee614ab6e6ee1b159af9d587f41d38 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sat, 29 Dec 2018 00:31:10 +0200 Subject: [PATCH 0358/1938] updated licanse according to changes https://gist.github.com/robstradling/f525d423c79690b72e650e2ad38a161d#file-roca-c-L138 --- client/emv/emv_roca.c | 9 +++++++-- client/emv/emv_roca.h | 38 +++++++++++++++++++------------------- 2 files changed, 26 insertions(+), 21 deletions(-) diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 5081ed446..a6738ae2f 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -1,10 +1,12 @@ /* roca.c - ROCA (CVE-2017-15361) fingerprint checker. * Written by Rob Stradling (based on https://github.com/crocs-muni/roca/blob/master/roca/detect.py) - * Copyright (C) 2017 COMODO CA Limited + * Copyright (C) 2017-2018 Sectigo Limited + * modified 2018 iceman (dropped openssl bignum, now use mbedtls lib) + * modified 2018 merlok * * 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 3 of the License, or + * 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, @@ -15,6 +17,9 @@ * You should have received a copy of the GNU General Public License * along with this program. If not, see . */ +//----------------------------------------------------------------------------- +// EMV roca commands +//----------------------------------------------------------------------------- #include "emv_roca.h" diff --git a/client/emv/emv_roca.h b/client/emv/emv_roca.h index a9559ef79..26d37d146 100644 --- a/client/emv/emv_roca.h +++ b/client/emv/emv_roca.h @@ -1,22 +1,22 @@ - -// ROCA (CVE-2017-15361) fingerprint checker. -// Written by Rob Stradling (based on https://github.com/crocs-muni/roca/blob/master/roca/detect.py) -// Copyright (C) 2017 COMODO CA Limited -// modified 2018 iceman (dropped openssl bignum, now use mbedtls lib) -// -// 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 3 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, see . -// +/* roca.c - ROCA (CVE-2017-15361) fingerprint checker. + * Written by Rob Stradling (based on https://github.com/crocs-muni/roca/blob/master/roca/detect.py) + * Copyright (C) 2017-2018 Sectigo Limited + * modified 2018 iceman (dropped openssl bignum, now use mbedtls lib) + * modified 2018 merlok + * + * 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, see . + */ //----------------------------------------------------------------------------- // EMV roca commands //----------------------------------------------------------------------------- From 9e07a5c65a9443b9a5db2c403f19f5b864f3c057 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 31 Dec 2018 15:46:32 +0100 Subject: [PATCH 0359/1938] CHG: updated to RevEng v1.6.0 --- client/cmdcrc.c | 17 +- client/reveng/model.c | 2 +- client/reveng/preset.c | 933 +++++++++++++++++++++-------------------- client/reveng/reveng.h | 31 +- client/scripting.c | 2 +- 5 files changed, 523 insertions(+), 462 deletions(-) diff --git a/client/cmdcrc.c b/client/cmdcrc.c index 25653dbab..a34c7d351 100644 --- a/client/cmdcrc.c +++ b/client/cmdcrc.c @@ -39,8 +39,7 @@ int split(char *str, char *arr[MAX_ARGS]){ return wordCnt; } -int CmdCrc(const char *Cmd) -{ +int CmdCrc(const char *Cmd) { char name[] = {"reveng "}; char Cmd2[100 + 7]; memcpy(Cmd2, name, 7); @@ -198,6 +197,11 @@ int GetModels(char *Models[], int *count, uint8_t *width){ pfree(qptr); } } + if(uflags & C_NOBFS && ~rflags & R_HAVEP) { + PrintAndLogEx(WARNING, "no models found"); + return 0; + } + if (!(model.flags & P_REFIN) != !(model.flags & P_REFOUT)){ PrintAndLogEx(WARNING, "cannot search for crossed-endian models"); return 0; @@ -259,8 +263,9 @@ int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *res SETBMP(); //set model - if (!(c = mbynam(&model, inModel))) { - PrintAndLogEx(WARNING, "error: preset model '%s' not found. Use reveng -D to list presets.", inModel); + c = mbynam(&model, inModel); + if (!c) { + PrintAndLogEx(WARNING, "error: preset model '%s' not found. Use reveng -D to list presets. [%d]", inModel, c); return 0; } if (c < 0){ @@ -396,7 +401,7 @@ char *SwapEndianStr(const char *inStr, const size_t len, const uint8_t blockSize // takes hex string in and searches for a matching result (hex string must include checksum) int CmdrevengSearch(const char *Cmd){ -#define NMODELS 103 +#define NMODELS 105 char inHexStr[100] = {0x00}; int dataLen = param_getstr(Cmd, 0, inHexStr, sizeof(inHexStr)); @@ -432,7 +437,7 @@ int CmdrevengSearch(const char *Cmd){ char *outHex = calloc(dataLen-crcChars+1, sizeof(char)); memcpy(outHex, inHexStr, dataLen-crcChars); - // PrintAndLogEx(DEBUG, "DEBUG: dataLen: %d, crcChars: %d, Model: %s, CRC: %s, width: %d, outHex: %s",dataLen, crcChars, Models[i], inCRC, width[i], outHex); + PrintAndLogEx(DEBUG, "DEBUG: dataLen: %d, crcChars: %d, Model: %s, CRC: %s, width: %d, outHex: %s",dataLen, crcChars, Models[i], inCRC, width[i], outHex); ans = RunModel(Models[i], outHex, false, 0, result); if (ans) { // test for match diff --git a/client/reveng/model.c b/client/reveng/model.c index 60870d80a..f99b1ee02 100644 --- a/client/reveng/model.c +++ b/client/reveng/model.c @@ -121,7 +121,7 @@ char * mtostr(const model_t *model) { if ((string = malloc(size))) { sprintf(strbuf, "\"%s\"", model->name); sprintf(string, - "width=%lu" + "width=%lu " "poly=0x%s " "init=0x%s " "refin=%s " diff --git a/client/reveng/preset.c b/client/reveng/preset.c index 9e7b721ff..6dbedaed9 100644 --- a/client/reveng/preset.c +++ b/client/reveng/preset.c @@ -1,5 +1,5 @@ /* preset.c - * Greg Cook, 26/Jul/2018 + * Greg Cook, 21/Nov/2018 */ /* CRC RevEng: arbitrary-precision CRC calculator and algorithm finder @@ -22,7 +22,9 @@ * along with CRC RevEng. If not, see . */ -/* 2018-07-26: added CRC-24/OS-9 +/* 2018-11-21: added CRC-8/NRSC-5, CRC-16/NRSC-5 + * 2018-11-21: renamed algorithms, new aliases, added classes + * 2018-07-26: added CRC-24/OS-9 * 2018-07-26: struct malias.name declared const char *const * 2017-06-19: added CRC-8/BLUETOOTH, CRC-17/CAN-FD, CRC-21/CAN-FD * 2017-02-18: added 8 new GSM algorithms @@ -269,200 +271,203 @@ static const bmp_t b32[] = { BMP_C(0x04c11db7) << (BMP_BIT - 32), /* 8 -- 32,04c11db7 */ BMP_C(0x05890000) << (BMP_BIT - 32), /* 9 -- 16, 0589 */ BMP_C(0x07000000) << (BMP_BIT - 32), /* 10 -- 8, 07 */ - BMP_C(0x09823b6e) << (BMP_BIT - 32), /* 11 -- 31,04c11db7 */ - BMP_C(0x0b3c0000) << (BMP_BIT - 32), /* 12 -- 15, 059e */ - BMP_C(0x0c000000) << (BMP_BIT - 32), /* 13 -- 6, 03 */ - BMP_C(0x0c200000) << (BMP_BIT - 32), /* 14 -- 11, 061 */ - BMP_C(0x0c780000) << (BMP_BIT - 32), /* 15 -- 14, 031e */ - BMP_C(0x0fb30000) << (BMP_BIT - 32), /* 16 -- 16, 0fb3 */ - BMP_C(0x10210000) << (BMP_BIT - 32), /* 17 -- 16, 1021 */ - BMP_C(0x12000000) << (BMP_BIT - 32), /* 18 -- 7, 09 */ - BMP_C(0x130d2afc) << (BMP_BIT - 32), /* 19 -- 30,04c34abf */ - BMP_C(0x144e6300) << (BMP_BIT - 32), /* 20 -- 24, 144e63 */ - BMP_C(0x15000000) << (BMP_BIT - 32), /* 21 -- 8, 15 */ - BMP_C(0x1697d06a) << (BMP_BIT - 32), /* 22 -- 32,1697d06a */ - BMP_C(0x17800000) << (BMP_BIT - 32), /* 23 -- 12, 178 */ - BMP_C(0x18000000) << (BMP_BIT - 32), /* 24 -- 6, 06 */ - BMP_C(0x19d3c8d8) << (BMP_BIT - 32), /* 25 -- 31,0ce9e46c */ - BMP_C(0x1c000000) << (BMP_BIT - 32), /* 26 -- 6, 07 */ - BMP_C(0x1d000000) << (BMP_BIT - 32), /* 27 -- 8, 1d */ - BMP_C(0x1d0f0000) << (BMP_BIT - 32), /* 28 -- 16, 1d0f */ - BMP_C(0x1dcf0000) << (BMP_BIT - 32), /* 29 -- 16, 1dcf */ - BMP_C(0x1edc6f41) << (BMP_BIT - 32), /* 30 -- 32,1edc6f41 */ - BMP_C(0x1f23b800) << (BMP_BIT - 32), /* 31 -- 24, 1f23b8 */ - BMP_C(0x20000000) << (BMP_BIT - 32), /* 32 -- 4, 2 */ - BMP_C(0x200fa500) << (BMP_BIT - 32), /* 33 -- 24, 200fa5 */ - BMP_C(0x20140000) << (BMP_BIT - 32), /* 34 -- 14, 0805 */ - BMP_C(0x20b40000) << (BMP_BIT - 32), /* 35 -- 14, 082d */ - BMP_C(0x20fe0000) << (BMP_BIT - 32), /* 36 -- 16, 20fe */ - BMP_C(0x21890000) << (BMP_BIT - 32), /* 37 -- 16, 2189 */ - BMP_C(0x21cf0200) << (BMP_BIT - 32), /* 38 -- 24, 21cf02 */ - BMP_C(0x23ef5200) << (BMP_BIT - 32), /* 39 -- 24, 23ef52 */ - BMP_C(0x25000000) << (BMP_BIT - 32), /* 40 -- 8, 25 */ - BMP_C(0x26000000) << (BMP_BIT - 32), /* 41 -- 8, 26 */ - BMP_C(0x26b10000) << (BMP_BIT - 32), /* 42 -- 16, 26b1 */ - BMP_C(0x27818000) << (BMP_BIT - 32), /* 43 -- 17, 04f03 */ - BMP_C(0x27d00000) << (BMP_BIT - 32), /* 44 -- 13, 04fa */ - BMP_C(0x28000000) << (BMP_BIT - 32), /* 45 -- 5, 05 */ - BMP_C(0x29b10000) << (BMP_BIT - 32), /* 46 -- 16, 29b1 */ - BMP_C(0x2f000000) << (BMP_BIT - 32), /* 47 -- 8, 2f */ - BMP_C(0x30000000) << (BMP_BIT - 32), /* 48 -- 4, 3/ 5, 6 */ - BMP_C(0x3010bf7f) << (BMP_BIT - 32), /* 49 -- 32,3010bf7f */ - BMP_C(0x31000000) << (BMP_BIT - 32), /* 50 -- 8, 31 */ - BMP_C(0x31800000) << (BMP_BIT - 32), /* 51 -- 10, 0c6 */ - BMP_C(0x31c30000) << (BMP_BIT - 32), /* 52 -- 16, 31c3 */ - BMP_C(0x328b6300) << (BMP_BIT - 32), /* 53 -- 24, 328b63 */ - BMP_C(0x34000000) << (BMP_BIT - 32), /* 54 -- 6, 0d */ - BMP_C(0x340bc6d9) << (BMP_BIT - 32), /* 55 -- 32,340bc6d9 */ - BMP_C(0x37000000) << (BMP_BIT - 32), /* 56 -- 8, 37 */ - BMP_C(0x38000000) << (BMP_BIT - 32), /* 57 -- 5, 07 */ - BMP_C(0x39000000) << (BMP_BIT - 32), /* 58 -- 8, 39 */ - BMP_C(0x3d650000) << (BMP_BIT - 32), /* 59 -- 16, 3d65 */ - BMP_C(0x3e000000) << (BMP_BIT - 32), /* 60 -- 8, 3e */ - BMP_C(0x40000000) << (BMP_BIT - 32), /* 61 -- 3, 2 */ - BMP_C(0x42000000) << (BMP_BIT - 32), /* 62 -- 8, 42 */ - BMP_C(0x44c20000) << (BMP_BIT - 32), /* 63 -- 16, 44c2 */ - BMP_C(0x45270551) << (BMP_BIT - 32), /* 64 -- 32,45270551 */ - BMP_C(0x48000000) << (BMP_BIT - 32), /* 65 -- 5, 09 */ - BMP_C(0x49000000) << (BMP_BIT - 32), /* 66 -- 8, 49 */ - BMP_C(0x4a800000) << (BMP_BIT - 32), /* 67 -- 10, 12a */ - BMP_C(0x4acc0000) << (BMP_BIT - 32), /* 68 -- 15, 2566 */ - BMP_C(0x4b000000) << (BMP_BIT - 32), /* 69 -- 8, 4b */ - BMP_C(0x4b370000) << (BMP_BIT - 32), /* 70 -- 16, 4b37 */ - BMP_C(0x4c000000) << (BMP_BIT - 32), /* 71 -- 6, 13 */ - BMP_C(0x4c060000) << (BMP_BIT - 32), /* 72 -- 16, 4c06 */ - BMP_C(0x53000000) << (BMP_BIT - 32), /* 73 -- 8, 53 */ - BMP_C(0x55000000) << (BMP_BIT - 32), /* 74 -- 8, 55 */ - BMP_C(0x55555500) << (BMP_BIT - 32), /* 75 -- 24, 555555 */ - BMP_C(0x59350000) << (BMP_BIT - 32), /* 76 -- 16, 5935 */ - BMP_C(0x5d380000) << (BMP_BIT - 32), /* 77 -- 16, 5d38 */ - BMP_C(0x5d400000) << (BMP_BIT - 32), /* 78 -- 10, 175 */ - BMP_C(0x5d6dcb00) << (BMP_BIT - 32), /* 79 -- 24, 5d6dcb */ - BMP_C(0x60000000) << (BMP_BIT - 32), /* 80 -- 3, 3 */ - BMP_C(0x60e00000) << (BMP_BIT - 32), /* 81 -- 11, 307 */ - BMP_C(0x63d00000) << (BMP_BIT - 32), /* 82 -- 16, 63d0 */ - BMP_C(0x64000000) << (BMP_BIT - 32), /* 83 -- 6, 19 */ - BMP_C(0x66400000) << (BMP_BIT - 32), /* 84 -- 10, 199 */ - BMP_C(0x66c50000) << (BMP_BIT - 32), /* 85 -- 16, 66c5 */ - BMP_C(0x6f630000) << (BMP_BIT - 32), /* 86 -- 16, 6f63 */ - BMP_C(0x6f910000) << (BMP_BIT - 32), /* 87 -- 16, 6f91 */ - BMP_C(0x70000000) << (BMP_BIT - 32), /* 88 -- 4, 7 */ - BMP_C(0x70a00000) << (BMP_BIT - 32), /* 89 -- 11, 385 */ - BMP_C(0x755b0000) << (BMP_BIT - 32), /* 90 -- 16, 755b */ - BMP_C(0x765e7680) << (BMP_BIT - 32), /* 91 -- 32,765e7680 */ - BMP_C(0x76c20800) << (BMP_BIT - 32), /* 92 -- 32, 0ed841 */ - BMP_C(0x7979bd00) << (BMP_BIT - 32), /* 93 -- 24, 7979bd */ - BMP_C(0x7e000000) << (BMP_BIT - 32), /* 94 -- 8, 7e */ - BMP_C(0x80000000) << (BMP_BIT - 32), /* 95 -- 3, 4 */ - BMP_C(0x80006300) << (BMP_BIT - 32), /* 96 -- 24, 800063 */ - BMP_C(0x80050000) << (BMP_BIT - 32), /* 97 -- 16, 8005 */ - BMP_C(0x800d0000) << (BMP_BIT - 32), /* 98 -- 16, 800d */ - BMP_C(0x800fe300) << (BMP_BIT - 32), /* 99 -- 24, 800fe3 */ - BMP_C(0x80b40000) << (BMP_BIT - 32), /* 100 -- 14, 202d */ - BMP_C(0x80c2e71c) << (BMP_BIT - 32), /* 101 -- 30,2030b9c7 */ - BMP_C(0x80f00000) << (BMP_BIT - 32), /* 102 -- 12, 80f */ - BMP_C(0x814141ab) << (BMP_BIT - 32), /* 103 -- 32,814141ab */ - BMP_C(0x8144c800) << (BMP_BIT - 32), /* 104 -- 21, 102899 */ - BMP_C(0x864cfb00) << (BMP_BIT - 32), /* 105 -- 24, 864cfb */ - BMP_C(0x87315576) << (BMP_BIT - 32), /* 106 -- 32,87315576 */ - BMP_C(0x89ec0000) << (BMP_BIT - 32), /* 107 -- 16, 89ec */ - BMP_C(0x8a000000) << (BMP_BIT - 32), /* 108 -- 7, 45 */ - BMP_C(0x8b320000) << (BMP_BIT - 32), /* 109 -- 15, 4599 */ - BMP_C(0x8bb70000) << (BMP_BIT - 32), /* 110 -- 16, 8bb7 */ - BMP_C(0x8cc00000) << (BMP_BIT - 32), /* 111 -- 10, 233 */ - BMP_C(0x904cddbf) << (BMP_BIT - 32), /* 112 -- 32,904cddbf */ - BMP_C(0x906e0000) << (BMP_BIT - 32), /* 113 -- 16, 906e */ - BMP_C(0x94000000) << (BMP_BIT - 32), /* 114 -- 8, 94 */ - BMP_C(0x97000000) << (BMP_BIT - 32), /* 115 -- 8, 97 */ - BMP_C(0x98000000) << (BMP_BIT - 32), /* 116 -- 6, 26 */ - BMP_C(0x9b000000) << (BMP_BIT - 32), /* 117 -- 8, 9b */ - BMP_C(0x9c000000) << (BMP_BIT - 32), /* 118 -- 6, 27 */ - BMP_C(0x9d5e4de2) << (BMP_BIT - 32), /* 119 -- 31,4eaf26f1 */ - BMP_C(0x9e000000) << (BMP_BIT - 32), /* 120 -- 7, 4f */ - BMP_C(0x9ecf0000) << (BMP_BIT - 32), /* 121 -- 16, 9ecf */ - BMP_C(0xa0970000) << (BMP_BIT - 32), /* 122 -- 16, a097 */ - BMP_C(0xa1000000) << (BMP_BIT - 32), /* 123 -- 8, a1 */ - BMP_C(0xa3660000) << (BMP_BIT - 32), /* 124 -- 16, a366 */ - BMP_C(0xa6000000) << (BMP_BIT - 32), /* 125 -- 7, 53 */ - BMP_C(0xa7000000) << (BMP_BIT - 32), /* 126 -- 8, a7 */ - BMP_C(0xa8000000) << (BMP_BIT - 32), /* 127 -- 5, 15 */ - BMP_C(0xa8190000) << (BMP_BIT - 32), /* 128 -- 16, a819 */ - BMP_C(0xa833982b) << (BMP_BIT - 32), /* 129 -- 32,a833982b */ - BMP_C(0xabcdef00) << (BMP_BIT - 32), /* 130 -- 24, abcdef */ - BMP_C(0xac000000) << (BMP_BIT - 32), /* 131 -- 8, ac */ - BMP_C(0xaee70000) << (BMP_BIT - 32), /* 132 -- 16, aee7 */ - BMP_C(0xb0000000) << (BMP_BIT - 32), /* 133 -- 4, b */ - BMP_C(0xb0010000) << (BMP_BIT - 32), /* 134 -- 16, b001 */ - BMP_C(0xb2aa0000) << (BMP_BIT - 32), /* 135 -- 16, b2aa */ - BMP_C(0xb3400000) << (BMP_BIT - 32), /* 136 -- 12, b34 */ - BMP_C(0xb42d8000) << (BMP_BIT - 32), /* 137 -- 17, 1685b */ - BMP_C(0xb4600000) << (BMP_BIT - 32), /* 138 -- 11, 5a3 */ - BMP_C(0xb4c80000) << (BMP_BIT - 32), /* 139 -- 16, b4c8 */ - BMP_C(0xb4f3e600) << (BMP_BIT - 32), /* 140 -- 24, b4f3e6 */ - BMP_C(0xb704ce00) << (BMP_BIT - 32), /* 141 -- 24, b704ce */ - BMP_C(0xb798b438) << (BMP_BIT - 32), /* 142 -- 32,b798b438 */ - BMP_C(0xbb3d0000) << (BMP_BIT - 32), /* 143 -- 16, bb3d */ - BMP_C(0xbc000000) << (BMP_BIT - 32), /* 144 -- 6,2f/ 8,bc */ - BMP_C(0xbd0be338) << (BMP_BIT - 32), /* 145 -- 32,bd0be338 */ - BMP_C(0xbdf40000) << (BMP_BIT - 32), /* 146 -- 16, bdf4 */ - BMP_C(0xbf050000) << (BMP_BIT - 32), /* 147 -- 16, bf05 */ - BMP_C(0xc0000000) << (BMP_BIT - 32), /* 148 -- 3, 6 */ - BMP_C(0xc2000000) << (BMP_BIT - 32), /* 149 -- 7, 61 */ - BMP_C(0xc25a5600) << (BMP_BIT - 32), /* 150 -- 24, c25a56 */ - BMP_C(0xc2b70000) << (BMP_BIT - 32), /* 151 -- 16, c2b7 */ - BMP_C(0xc2b80000) << (BMP_BIT - 32), /* 152 -- 14, 30ae */ - BMP_C(0xc4000000) << (BMP_BIT - 32), /* 153 -- 8, c4 */ - BMP_C(0xc6c60000) << (BMP_BIT - 32), /* 154 -- 16, c6c6 */ - BMP_C(0xc704dd7b) << (BMP_BIT - 32), /* 155 -- 32,c704dd7b */ - BMP_C(0xc8000000) << (BMP_BIT - 32), /* 156 -- 5, 19 */ - BMP_C(0xc8670000) << (BMP_BIT - 32), /* 157 -- 16, c867 */ - BMP_C(0xcbf43926) << (BMP_BIT - 32), /* 158 -- 32,cbf43926 */ - BMP_C(0xcde70300) << (BMP_BIT - 32), /* 159 -- 24, cde703 */ - BMP_C(0xce3c0000) << (BMP_BIT - 32), /* 160 -- 16, ce3c */ - BMP_C(0xd0000000) << (BMP_BIT - 32), /* 161 -- 8, d0 */ - BMP_C(0xd02a0000) << (BMP_BIT - 32), /* 162 -- 15, 6815 */ - BMP_C(0xd0db0000) << (BMP_BIT - 32), /* 163 -- 16, d0db */ - BMP_C(0xd3100000) << (BMP_BIT - 32), /* 164 -- 12, d31 */ - BMP_C(0xd3be9568) << (BMP_BIT - 32), /* 165 -- 30,34efa55a */ - BMP_C(0xd4d00000) << (BMP_BIT - 32), /* 166 -- 12, d4d */ - BMP_C(0xd5000000) << (BMP_BIT - 32), /* 167 -- 8, d5 */ - BMP_C(0xd64e0000) << (BMP_BIT - 32), /* 168 -- 16, d64e */ - BMP_C(0xda000000) << (BMP_BIT - 32), /* 169 -- 8, da */ - BMP_C(0xdaf00000) << (BMP_BIT - 32), /* 170 -- 12, daf */ - BMP_C(0xdebb20e3) << (BMP_BIT - 32), /* 171 -- 32,debb20e3 */ - BMP_C(0xdf000000) << (BMP_BIT - 32), /* 172 -- 8, df */ - BMP_C(0xe0000000) << (BMP_BIT - 32), /* 173 -- 3, 7 */ - BMP_C(0xe3069283) << (BMP_BIT - 32), /* 174 -- 32,e3069283 */ - BMP_C(0xe3940000) << (BMP_BIT - 32), /* 175 -- 16, e394 */ - BMP_C(0xe5cc0000) << (BMP_BIT - 32), /* 176 -- 16, e5cc */ - BMP_C(0xe7a80000) << (BMP_BIT - 32), /* 177 -- 13, 1cf5 */ - BMP_C(0xe8000000) << (BMP_BIT - 32), /* 178 -- 6, 3a */ - BMP_C(0xea000000) << (BMP_BIT - 32), /* 179 -- 7, 75 */ - BMP_C(0xea820000) << (BMP_BIT - 32), /* 180 -- 16, ea82 */ - BMP_C(0xec000000) << (BMP_BIT - 32), /* 181 -- 6, 3b */ - BMP_C(0xf0000000) << (BMP_BIT - 32), /* 182 -- 4, f */ - BMP_C(0xf0b80000) << (BMP_BIT - 32), /* 183 -- 16, f0b8 */ - BMP_C(0xf1300000) << (BMP_BIT - 32), /* 184 -- 12, f13 */ - BMP_C(0xf4000000) << (BMP_BIT - 32), /* 185 -- 8, f4 */ - BMP_C(0xf4acfb13) << (BMP_BIT - 32), /* 186 -- 32,f4acfb13 */ - BMP_C(0xf5b00000) << (BMP_BIT - 32), /* 187 -- 12, f5b */ - BMP_C(0xf6400000) << (BMP_BIT - 32), /* 188 -- 10, 3d9 */ - BMP_C(0xf8000000) << (BMP_BIT - 32), /* 189 -- 5, 1f */ - BMP_C(0xfc000000) << (BMP_BIT - 32), /* 190 -- 6, 3f */ - BMP_C(0xfc891918) << (BMP_BIT - 32), /* 191 -- 32,fc891918 */ - BMP_C(0xfd000000) << (BMP_BIT - 32), /* 192 -- 8, fd */ - BMP_C(0xfe000000) << (BMP_BIT - 32), /* 193 -- 7, 7f */ - BMP_C(0xfedcba00) << (BMP_BIT - 32), /* 194 -- 24, fedcba */ - BMP_C(0xfee80000) << (BMP_BIT - 32), /* 195 -- 16, fee8 */ - BMP_C(0xff000000) << (BMP_BIT - 32), /* 196 -- 8, ff */ - BMP_C(0xffc00000) << (BMP_BIT - 32), /* 197 -- 10, 3ff */ - BMP_C(0xfff00000) << (BMP_BIT - 32), /* 198 -- 12, fff */ - BMP_C(0xfffc0000) << (BMP_BIT - 32), /* 199 -- 14, 3fff */ - BMP_C(0xffff0000) << (BMP_BIT - 32), /* 200 -- 16, ffff */ - BMP_C(0xffffff00) << (BMP_BIT - 32), /* 201 -- 24, ffffff */ - BMP_C(0xfffffffc) << (BMP_BIT - 32), /* 202 -- 30,3fffffff */ - BMP_C(0xfffffffe) << (BMP_BIT - 32), /* 203 -- 31,7fffffff */ - BMP_C(0xffffffff) << (BMP_BIT - 32), /* 204 -- 32,ffffffff */ + BMP_C(0x080b0000) << (BMP_BIT - 32), /* 11 -- 16, 080b */ + BMP_C(0x09823b6e) << (BMP_BIT - 32), /* 12 -- 31,04c11db7 */ + BMP_C(0x0b3c0000) << (BMP_BIT - 32), /* 13 -- 15, 059e */ + BMP_C(0x0c000000) << (BMP_BIT - 32), /* 14 -- 6, 03 */ + BMP_C(0x0c200000) << (BMP_BIT - 32), /* 15 -- 11, 061 */ + BMP_C(0x0c780000) << (BMP_BIT - 32), /* 16 -- 14, 031e */ + BMP_C(0x0fb30000) << (BMP_BIT - 32), /* 17 -- 16, 0fb3 */ + BMP_C(0x10210000) << (BMP_BIT - 32), /* 18 -- 16, 1021 */ + BMP_C(0x12000000) << (BMP_BIT - 32), /* 19 -- 7, 09 */ + BMP_C(0x130d2afc) << (BMP_BIT - 32), /* 20 -- 30,04c34abf */ + BMP_C(0x144e6300) << (BMP_BIT - 32), /* 21 -- 24, 144e63 */ + BMP_C(0x15000000) << (BMP_BIT - 32), /* 22 -- 8, 15 */ + BMP_C(0x1697d06a) << (BMP_BIT - 32), /* 23 -- 32,1697d06a */ + BMP_C(0x17800000) << (BMP_BIT - 32), /* 24 -- 12, 178 */ + BMP_C(0x18000000) << (BMP_BIT - 32), /* 25 -- 6, 06 */ + BMP_C(0x19d3c8d8) << (BMP_BIT - 32), /* 26 -- 31,0ce9e46c */ + BMP_C(0x1c000000) << (BMP_BIT - 32), /* 27 -- 6, 07 */ + BMP_C(0x1d000000) << (BMP_BIT - 32), /* 28 -- 8, 1d */ + BMP_C(0x1d0f0000) << (BMP_BIT - 32), /* 29 -- 16, 1d0f */ + BMP_C(0x1dcf0000) << (BMP_BIT - 32), /* 30 -- 16, 1dcf */ + BMP_C(0x1edc6f41) << (BMP_BIT - 32), /* 31 -- 32,1edc6f41 */ + BMP_C(0x1f23b800) << (BMP_BIT - 32), /* 32 -- 24, 1f23b8 */ + BMP_C(0x20000000) << (BMP_BIT - 32), /* 33 -- 4, 2 */ + BMP_C(0x200fa500) << (BMP_BIT - 32), /* 34 -- 24, 200fa5 */ + BMP_C(0x20140000) << (BMP_BIT - 32), /* 35 -- 14, 0805 */ + BMP_C(0x20b40000) << (BMP_BIT - 32), /* 36 -- 14, 082d */ + BMP_C(0x20fe0000) << (BMP_BIT - 32), /* 37 -- 16, 20fe */ + BMP_C(0x21890000) << (BMP_BIT - 32), /* 38 -- 16, 2189 */ + BMP_C(0x21cf0200) << (BMP_BIT - 32), /* 39 -- 24, 21cf02 */ + BMP_C(0x23ef5200) << (BMP_BIT - 32), /* 40 -- 24, 23ef52 */ + BMP_C(0x25000000) << (BMP_BIT - 32), /* 41 -- 8, 25 */ + BMP_C(0x26000000) << (BMP_BIT - 32), /* 42 -- 8, 26 */ + BMP_C(0x26b10000) << (BMP_BIT - 32), /* 43 -- 16, 26b1 */ + BMP_C(0x27818000) << (BMP_BIT - 32), /* 44 -- 17, 04f03 */ + BMP_C(0x27d00000) << (BMP_BIT - 32), /* 45 -- 13, 04fa */ + BMP_C(0x28000000) << (BMP_BIT - 32), /* 46 -- 5, 05 */ + BMP_C(0x29b10000) << (BMP_BIT - 32), /* 47 -- 16, 29b1 */ + BMP_C(0x2f000000) << (BMP_BIT - 32), /* 48 -- 8, 2f */ + BMP_C(0x30000000) << (BMP_BIT - 32), /* 49 -- 4, 3/ 5, 6 */ + BMP_C(0x3010bf7f) << (BMP_BIT - 32), /* 50 -- 32,3010bf7f */ + BMP_C(0x31000000) << (BMP_BIT - 32), /* 51 -- 8, 31 */ + BMP_C(0x31800000) << (BMP_BIT - 32), /* 52 -- 10, 0c6 */ + BMP_C(0x31c30000) << (BMP_BIT - 32), /* 53 -- 16, 31c3 */ + BMP_C(0x328b6300) << (BMP_BIT - 32), /* 54 -- 24, 328b63 */ + BMP_C(0x34000000) << (BMP_BIT - 32), /* 55 -- 6, 0d */ + BMP_C(0x340bc6d9) << (BMP_BIT - 32), /* 56 -- 32,340bc6d9 */ + BMP_C(0x37000000) << (BMP_BIT - 32), /* 57 -- 8, 37 */ + BMP_C(0x38000000) << (BMP_BIT - 32), /* 58 -- 5, 07 */ + BMP_C(0x39000000) << (BMP_BIT - 32), /* 59 -- 8, 39 */ + BMP_C(0x3d650000) << (BMP_BIT - 32), /* 60 -- 16, 3d65 */ + BMP_C(0x3e000000) << (BMP_BIT - 32), /* 61 -- 8, 3e */ + BMP_C(0x40000000) << (BMP_BIT - 32), /* 62 -- 3, 2 */ + BMP_C(0x42000000) << (BMP_BIT - 32), /* 63 -- 8, 42 */ + BMP_C(0x44c20000) << (BMP_BIT - 32), /* 64 -- 16, 44c2 */ + BMP_C(0x45270551) << (BMP_BIT - 32), /* 65 -- 32,45270551 */ + BMP_C(0x48000000) << (BMP_BIT - 32), /* 66 -- 5, 09 */ + BMP_C(0x49000000) << (BMP_BIT - 32), /* 67 -- 8, 49 */ + BMP_C(0x4a800000) << (BMP_BIT - 32), /* 68 -- 10, 12a */ + BMP_C(0x4acc0000) << (BMP_BIT - 32), /* 69 -- 15, 2566 */ + BMP_C(0x4b000000) << (BMP_BIT - 32), /* 70 -- 8, 4b */ + BMP_C(0x4b370000) << (BMP_BIT - 32), /* 71 -- 16, 4b37 */ + BMP_C(0x4c000000) << (BMP_BIT - 32), /* 72 -- 6, 13 */ + BMP_C(0x4c060000) << (BMP_BIT - 32), /* 73 -- 16, 4c06 */ + BMP_C(0x53000000) << (BMP_BIT - 32), /* 74 -- 8, 53 */ + BMP_C(0x55000000) << (BMP_BIT - 32), /* 75 -- 8, 55 */ + BMP_C(0x55555500) << (BMP_BIT - 32), /* 76 -- 24, 555555 */ + BMP_C(0x59350000) << (BMP_BIT - 32), /* 77 -- 16, 5935 */ + BMP_C(0x5d380000) << (BMP_BIT - 32), /* 78 -- 16, 5d38 */ + BMP_C(0x5d400000) << (BMP_BIT - 32), /* 79 -- 10, 175 */ + BMP_C(0x5d6dcb00) << (BMP_BIT - 32), /* 80 -- 24, 5d6dcb */ + BMP_C(0x60000000) << (BMP_BIT - 32), /* 81 -- 3, 3 */ + BMP_C(0x60e00000) << (BMP_BIT - 32), /* 82 -- 11, 307 */ + BMP_C(0x63d00000) << (BMP_BIT - 32), /* 83 -- 16, 63d0 */ + BMP_C(0x64000000) << (BMP_BIT - 32), /* 84 -- 6, 19 */ + BMP_C(0x66400000) << (BMP_BIT - 32), /* 85 -- 10, 199 */ + BMP_C(0x66c50000) << (BMP_BIT - 32), /* 86 -- 16, 66c5 */ + BMP_C(0x6f630000) << (BMP_BIT - 32), /* 87 -- 16, 6f63 */ + BMP_C(0x6f910000) << (BMP_BIT - 32), /* 88 -- 16, 6f91 */ + BMP_C(0x70000000) << (BMP_BIT - 32), /* 89 -- 4, 7 */ + BMP_C(0x70a00000) << (BMP_BIT - 32), /* 90 -- 11, 385 */ + BMP_C(0x755b0000) << (BMP_BIT - 32), /* 91 -- 16, 755b */ + BMP_C(0x765e7680) << (BMP_BIT - 32), /* 92 -- 32,765e7680 */ + BMP_C(0x76c20800) << (BMP_BIT - 32), /* 93 -- 32, 0ed841 */ + BMP_C(0x7979bd00) << (BMP_BIT - 32), /* 94 -- 24, 7979bd */ + BMP_C(0x7e000000) << (BMP_BIT - 32), /* 95 -- 8, 7e */ + BMP_C(0x80000000) << (BMP_BIT - 32), /* 96 -- 3, 4 */ + BMP_C(0x80006300) << (BMP_BIT - 32), /* 97 -- 24, 800063 */ + BMP_C(0x80050000) << (BMP_BIT - 32), /* 98 -- 16, 8005 */ + BMP_C(0x800d0000) << (BMP_BIT - 32), /* 99 -- 16, 800d */ + BMP_C(0x800fe300) << (BMP_BIT - 32), /* 100 -- 24, 800fe3 */ + BMP_C(0x80b40000) << (BMP_BIT - 32), /* 101 -- 14, 202d */ + BMP_C(0x80c2e71c) << (BMP_BIT - 32), /* 102 -- 30,2030b9c7 */ + BMP_C(0x80f00000) << (BMP_BIT - 32), /* 103 -- 12, 80f */ + BMP_C(0x814141ab) << (BMP_BIT - 32), /* 104 -- 32,814141ab */ + BMP_C(0x8144c800) << (BMP_BIT - 32), /* 105 -- 21, 102899 */ + BMP_C(0x864cfb00) << (BMP_BIT - 32), /* 106 -- 24, 864cfb */ + BMP_C(0x87315576) << (BMP_BIT - 32), /* 107 -- 32,87315576 */ + BMP_C(0x89ec0000) << (BMP_BIT - 32), /* 108 -- 16, 89ec */ + BMP_C(0x8a000000) << (BMP_BIT - 32), /* 109 -- 7, 45 */ + BMP_C(0x8b320000) << (BMP_BIT - 32), /* 110 -- 15, 4599 */ + BMP_C(0x8bb70000) << (BMP_BIT - 32), /* 111 -- 16, 8bb7 */ + BMP_C(0x8cc00000) << (BMP_BIT - 32), /* 112 -- 10, 233 */ + BMP_C(0x904cddbf) << (BMP_BIT - 32), /* 113 -- 32,904cddbf */ + BMP_C(0x906e0000) << (BMP_BIT - 32), /* 114 -- 16, 906e */ + BMP_C(0x94000000) << (BMP_BIT - 32), /* 115 -- 8, 94 */ + BMP_C(0x97000000) << (BMP_BIT - 32), /* 116 -- 8, 97 */ + BMP_C(0x98000000) << (BMP_BIT - 32), /* 117 -- 6, 26 */ + BMP_C(0x9b000000) << (BMP_BIT - 32), /* 118 -- 8, 9b */ + BMP_C(0x9c000000) << (BMP_BIT - 32), /* 119 -- 6, 27 */ + BMP_C(0x9d5e4de2) << (BMP_BIT - 32), /* 120 -- 31,4eaf26f1 */ + BMP_C(0x9e000000) << (BMP_BIT - 32), /* 121 -- 7, 4f */ + BMP_C(0x9ecf0000) << (BMP_BIT - 32), /* 122 -- 16, 9ecf */ + BMP_C(0xa0660000) << (BMP_BIT - 32), /* 123 -- 16, a066 */ + BMP_C(0xa0970000) << (BMP_BIT - 32), /* 124 -- 16, a097 */ + BMP_C(0xa1000000) << (BMP_BIT - 32), /* 125 -- 8, a1 */ + BMP_C(0xa3660000) << (BMP_BIT - 32), /* 126 -- 16, a366 */ + BMP_C(0xa6000000) << (BMP_BIT - 32), /* 127 -- 7, 53 */ + BMP_C(0xa7000000) << (BMP_BIT - 32), /* 128 -- 8, a7 */ + BMP_C(0xa8000000) << (BMP_BIT - 32), /* 129 -- 5, 15 */ + BMP_C(0xa8190000) << (BMP_BIT - 32), /* 130 -- 16, a819 */ + BMP_C(0xa833982b) << (BMP_BIT - 32), /* 131 -- 32,a833982b */ + BMP_C(0xabcdef00) << (BMP_BIT - 32), /* 132 -- 24, abcdef */ + BMP_C(0xac000000) << (BMP_BIT - 32), /* 133 -- 8, ac */ + BMP_C(0xaee70000) << (BMP_BIT - 32), /* 134 -- 16, aee7 */ + BMP_C(0xb0000000) << (BMP_BIT - 32), /* 135 -- 4, b */ + BMP_C(0xb0010000) << (BMP_BIT - 32), /* 136 -- 16, b001 */ + BMP_C(0xb2aa0000) << (BMP_BIT - 32), /* 137 -- 16, b2aa */ + BMP_C(0xb3400000) << (BMP_BIT - 32), /* 138 -- 12, b34 */ + BMP_C(0xb42d8000) << (BMP_BIT - 32), /* 139 -- 17, 1685b */ + BMP_C(0xb4600000) << (BMP_BIT - 32), /* 140 -- 11, 5a3 */ + BMP_C(0xb4c80000) << (BMP_BIT - 32), /* 141 -- 16, b4c8 */ + BMP_C(0xb4f3e600) << (BMP_BIT - 32), /* 142 -- 24, b4f3e6 */ + BMP_C(0xb704ce00) << (BMP_BIT - 32), /* 143 -- 24, b704ce */ + BMP_C(0xb798b438) << (BMP_BIT - 32), /* 144 -- 32,b798b438 */ + BMP_C(0xbb3d0000) << (BMP_BIT - 32), /* 145 -- 16, bb3d */ + BMP_C(0xbc000000) << (BMP_BIT - 32), /* 146 -- 6,2f/ 8,bc */ + BMP_C(0xbd0be338) << (BMP_BIT - 32), /* 147 -- 32,bd0be338 */ + BMP_C(0xbdf40000) << (BMP_BIT - 32), /* 148 -- 16, bdf4 */ + BMP_C(0xbf050000) << (BMP_BIT - 32), /* 149 -- 16, bf05 */ + BMP_C(0xc0000000) << (BMP_BIT - 32), /* 150 -- 3, 6 */ + BMP_C(0xc2000000) << (BMP_BIT - 32), /* 151 -- 7, 61 */ + BMP_C(0xc25a5600) << (BMP_BIT - 32), /* 152 -- 24, c25a56 */ + BMP_C(0xc2b70000) << (BMP_BIT - 32), /* 153 -- 16, c2b7 */ + BMP_C(0xc2b80000) << (BMP_BIT - 32), /* 154 -- 14, 30ae */ + BMP_C(0xc4000000) << (BMP_BIT - 32), /* 155 -- 8, c4 */ + BMP_C(0xc6c60000) << (BMP_BIT - 32), /* 156 -- 16, c6c6 */ + BMP_C(0xc704dd7b) << (BMP_BIT - 32), /* 157 -- 32,c704dd7b */ + BMP_C(0xc8000000) << (BMP_BIT - 32), /* 158 -- 5, 19 */ + BMP_C(0xc8670000) << (BMP_BIT - 32), /* 159 -- 16, c867 */ + BMP_C(0xcbf43926) << (BMP_BIT - 32), /* 160 -- 32,cbf43926 */ + BMP_C(0xcde70300) << (BMP_BIT - 32), /* 161 -- 24, cde703 */ + BMP_C(0xce3c0000) << (BMP_BIT - 32), /* 162 -- 16, ce3c */ + BMP_C(0xd0000000) << (BMP_BIT - 32), /* 163 -- 8, d0 */ + BMP_C(0xd02a0000) << (BMP_BIT - 32), /* 164 -- 15, 6815 */ + BMP_C(0xd0db0000) << (BMP_BIT - 32), /* 165 -- 16, d0db */ + BMP_C(0xd3100000) << (BMP_BIT - 32), /* 166 -- 12, d31 */ + BMP_C(0xd3be9568) << (BMP_BIT - 32), /* 167 -- 30,34efa55a */ + BMP_C(0xd4d00000) << (BMP_BIT - 32), /* 168 -- 12, d4d */ + BMP_C(0xd5000000) << (BMP_BIT - 32), /* 169 -- 8, d5 */ + BMP_C(0xd64e0000) << (BMP_BIT - 32), /* 170 -- 16, d64e */ + BMP_C(0xda000000) << (BMP_BIT - 32), /* 171 -- 8, da */ + BMP_C(0xdaf00000) << (BMP_BIT - 32), /* 172 -- 12, daf */ + BMP_C(0xdebb20e3) << (BMP_BIT - 32), /* 173 -- 32,debb20e3 */ + BMP_C(0xdf000000) << (BMP_BIT - 32), /* 174 -- 8, df */ + BMP_C(0xe0000000) << (BMP_BIT - 32), /* 175 -- 3, 7 */ + BMP_C(0xe3069283) << (BMP_BIT - 32), /* 176 -- 32,e3069283 */ + BMP_C(0xe3940000) << (BMP_BIT - 32), /* 177 -- 16, e394 */ + BMP_C(0xe5cc0000) << (BMP_BIT - 32), /* 178 -- 16, e5cc */ + BMP_C(0xe7a80000) << (BMP_BIT - 32), /* 179 -- 13, 1cf5 */ + BMP_C(0xe8000000) << (BMP_BIT - 32), /* 180 -- 6, 3a */ + BMP_C(0xea000000) << (BMP_BIT - 32), /* 181 -- 7, 75 */ + BMP_C(0xea820000) << (BMP_BIT - 32), /* 182 -- 16, ea82 */ + BMP_C(0xec000000) << (BMP_BIT - 32), /* 183 -- 6, 3b */ + BMP_C(0xf0000000) << (BMP_BIT - 32), /* 184 -- 4, f */ + BMP_C(0xf0b80000) << (BMP_BIT - 32), /* 185 -- 16, f0b8 */ + BMP_C(0xf1300000) << (BMP_BIT - 32), /* 186 -- 12, f13 */ + BMP_C(0xf4000000) << (BMP_BIT - 32), /* 187 -- 8, f4 */ + BMP_C(0xf4acfb13) << (BMP_BIT - 32), /* 188 -- 32,f4acfb13 */ + BMP_C(0xf5b00000) << (BMP_BIT - 32), /* 189 -- 12, f5b */ + BMP_C(0xf6400000) << (BMP_BIT - 32), /* 190 -- 10, 3d9 */ + BMP_C(0xf7000000) << (BMP_BIT - 32), /* 191 -- 8, f7 */ + BMP_C(0xf8000000) << (BMP_BIT - 32), /* 192 -- 5, 1f */ + BMP_C(0xfc000000) << (BMP_BIT - 32), /* 193 -- 6, 3f */ + BMP_C(0xfc891918) << (BMP_BIT - 32), /* 194 -- 32,fc891918 */ + BMP_C(0xfd000000) << (BMP_BIT - 32), /* 195 -- 8, fd */ + BMP_C(0xfe000000) << (BMP_BIT - 32), /* 196 -- 7, 7f */ + BMP_C(0xfedcba00) << (BMP_BIT - 32), /* 197 -- 24, fedcba */ + BMP_C(0xfee80000) << (BMP_BIT - 32), /* 198 -- 16, fee8 */ + BMP_C(0xff000000) << (BMP_BIT - 32), /* 199 -- 8, ff */ + BMP_C(0xffc00000) << (BMP_BIT - 32), /* 200 -- 10, 3ff */ + BMP_C(0xfff00000) << (BMP_BIT - 32), /* 201 -- 12, fff */ + BMP_C(0xfffc0000) << (BMP_BIT - 32), /* 202 -- 14, 3fff */ + BMP_C(0xffff0000) << (BMP_BIT - 32), /* 203 -- 16, ffff */ + BMP_C(0xffffff00) << (BMP_BIT - 32), /* 204 -- 24, ffffff */ + BMP_C(0xfffffffc) << (BMP_BIT - 32), /* 205 -- 30,3fffffff */ + BMP_C(0xfffffffe) << (BMP_BIT - 32), /* 206 -- 31,7fffffff */ + BMP_C(0xffffffff) << (BMP_BIT - 32), /* 207 -- 32,ffffffff */ }; static const struct malias aliases[]; @@ -471,265 +476,303 @@ static const struct malias aliases[]; * Sorted by left-justified polynomial for bsearch(). */ static const struct mpreset models[] = { - {64UL, b64, b64a, P_LE, b64a, b64b, b64c, aliases+100}, /* 0 */ - {32UL, b32+ 0, 0, P_BE, 0, b32+145, 0, aliases+138}, /* 1 */ - {40UL, b40, 0, P_BE, b40a, b40b, b40c, aliases+ 88}, /* 2 */ - {24UL, b32+ 3, b32+ 75, P_LE, 0, b32+150, 0, aliases+ 60}, /* 3 */ - {32UL, b32+ 8, 0, P_BE, b32+204, b32+ 91, b32+155, aliases+ 82}, /* 4 */ - {32UL, b32+ 8, b32+204, P_BE, 0, b32+ 7, 0, aliases+ 81}, /* 5 */ - {32UL, b32+ 8, b32+204, P_BE, b32+204, b32+191, b32+155, aliases+ 76}, /* 6 */ - {32UL, b32+ 8, b32+204, P_LE, 0, b32+ 55, 0, aliases+130}, /* 7 */ - {32UL, b32+ 8, b32+204, P_LE, b32+204, b32+158, b32+171, aliases+ 72}, /* 8 */ - {16UL, b32+ 9, 0, P_BE, 0, b32+ 5, 0, aliases+ 31}, /* 9 */ - {16UL, b32+ 9, 0, P_BE, b32+ 1, b32+ 4, b32+ 9, aliases+ 30}, /* 10 */ - { 8UL, b32+ 10, 0, P_BE, 0, b32+185, 0, aliases+106}, /* 11 */ - { 8UL, b32+ 10, 0, P_BE, b32+ 74, b32+123, b32+131, aliases+117}, /* 12 */ - { 8UL, b32+ 10, b32+196, P_LE, 0, b32+161, 0, aliases+121}, /* 13 */ - {31UL, b32+ 11, b32+203, P_BE, b32+203, b32+ 25, b32+119, aliases+ 71}, /* 14 */ - { 6UL, b32+ 13, 0, P_LE, 0, b32+ 24, 0, aliases+ 96}, /* 15 */ - {82UL, b82, 0, P_LE, 0, b82a, 0, aliases+124}, /* 16 */ - {16UL, b32+ 17, 0, P_BE, 0, b32+ 52, 0, aliases+139}, /* 17 */ - {16UL, b32+ 17, 0, P_BE, b32+200, b32+160, b32+ 28, aliases+ 36}, /* 18 */ - {16UL, b32+ 17, 0, P_LE, 0, b32+ 37, 0, aliases+131}, /* 19 */ - {16UL, b32+ 17, b32+ 28, P_BE, 0, b32+176, 0, aliases+ 21}, /* 20 */ - {16UL, b32+ 17, b32+107, P_LE, 0, b32+ 42, 0, aliases+ 53}, /* 21 */ - {16UL, b32+ 17, b32+135, P_LE, 0, b32+ 82, 0, aliases+ 49}, /* 22 */ - {16UL, b32+ 17, b32+154, P_LE, 0, b32+147, 0, aliases+125}, /* 23 */ - {16UL, b32+ 17, b32+200, P_BE, 0, b32+ 46, 0, aliases+ 24}, /* 24 */ - {16UL, b32+ 17, b32+200, P_BE, b32+200, b32+168, b32+ 28, aliases+ 35}, /* 25 */ - {16UL, b32+ 17, b32+200, P_LE, 0, b32+ 87, 0, aliases+ 45}, /* 26 */ - {16UL, b32+ 17, b32+200, P_LE, b32+200, b32+113, b32+183, aliases+135}, /* 27 */ - { 7UL, b32+ 18, 0, P_BE, 0, b32+179, 0, aliases+103}, /* 28 */ - { 6UL, b32+ 26, b32+190, P_BE, 0, b32+181, 0, aliases+ 93}, /* 29 */ - { 8UL, b32+ 27, 0, P_BE, 0, b32+ 56, 0, aliases+114}, /* 30 */ - { 8UL, b32+ 27, b32+192, P_BE, 0, b32+ 94, 0, aliases+116}, /* 31 */ - { 8UL, b32+ 27, b32+196, P_BE, b32+196, b32+ 69, b32+153, aliases+122}, /* 32 */ - { 8UL, b32+ 27, b32+196, P_LE, 0, b32+115, 0, aliases+113}, /* 33 */ - {16UL, b32+ 29, b32+200, P_BE, b32+200, b32+128, b32+175, aliases+ 48}, /* 34 */ - {32UL, b32+ 30, b32+204, P_LE, b32+204, b32+174, b32+142, aliases+ 83}, /* 35 */ - {14UL, b32+ 34, 0, P_LE, 0, b32+ 35, 0, aliases+ 14}, /* 36 */ - { 5UL, b32+ 45, b32+189, P_LE, b32+189, b32+156, b32+ 48, aliases+ 91}, /* 37 */ - { 8UL, b32+ 47, 0, P_BE, 0, b32+ 60, 0, aliases+120}, /* 38 */ - { 8UL, b32+ 47, b32+196, P_BE, b32+196, b32+172, b32+ 62, aliases+108}, /* 39 */ - { 4UL, b32+ 48, 0, P_LE, 0, b32+ 88, 0, aliases+ 87}, /* 40 */ - { 4UL, b32+ 48, b32+182, P_BE, b32+182, b32+133, b32+ 32, aliases+ 86}, /* 41 */ - { 8UL, b32+ 50, 0, P_LE, 0, b32+123, 0, aliases+119}, /* 42 */ - {24UL, b32+ 53, b32+201, P_BE, b32+201, b32+140, b32+ 20, aliases+ 63}, /* 43 */ - { 8UL, b32+ 58, 0, P_LE, 0, b32+ 21, 0, aliases+111}, /* 44 */ - {16UL, b32+ 59, 0, P_BE, b32+200, b32+151, b32+124, aliases+ 33}, /* 45 */ - {16UL, b32+ 59, 0, P_LE, b32+200, b32+180, b32+ 85, aliases+ 32}, /* 46 */ - {64UL, b64d, 0, P_BE, 0, b64e, 0, aliases+ 97}, /* 47 */ - {64UL, b64d, b64a, P_BE, b64a, b64f, b64g, aliases+101}, /* 48 */ - {64UL, b64d, b64a, P_LE, b64a, b64h, b64i, aliases+102}, /* 49 */ - { 5UL, b32+ 65, b32+ 65, P_BE, 0, 0, 0, aliases+ 89}, /* 50 */ - { 8UL, b32+ 66, 0, P_BE, b32+196, b32+114, b32+ 73, aliases+115}, /* 51 */ - {16UL, b32+ 76, 0, P_BE, 0, b32+ 77, 0, aliases+ 46}, /* 52 */ - {10UL, b32+ 78, 0, P_BE, b32+197, b32+ 67, b32+ 51, aliases+ 5}, /* 53 */ - {24UL, b32+ 79, b32+130, P_BE, 0, b32+ 31, 0, aliases+ 62}, /* 54 */ - {24UL, b32+ 79, b32+194, P_BE, 0, b32+ 93, 0, aliases+ 61}, /* 55 */ - { 3UL, b32+ 80, 0, P_BE, b32+173, b32+ 95, b32+ 61, aliases+ 68}, /* 56 */ - { 3UL, b32+ 80, b32+173, P_LE, 0, b32+148, 0, aliases+ 69}, /* 57 */ - {11UL, b32+ 81, 0, P_BE, 0, b32+ 14, 0, aliases+ 7}, /* 58 */ - { 6UL, b32+ 83, 0, P_LE, 0, b32+116, 0, aliases+ 94}, /* 59 */ - {16UL, b32+ 86, 0, P_BE, 0, b32+146, 0, aliases+ 42}, /* 60 */ - {11UL, b32+ 89, b32+ 6, P_BE, 0, b32+138, 0, aliases+ 6}, /* 61 */ - {16UL, b32+ 90, 0, P_BE, 0, b32+ 36, 0, aliases+ 47}, /* 62 */ - {24UL, b32+ 96, 0, P_BE, 0, b32+ 39, 0, aliases+ 65}, /* 63 */ - {24UL, b32+ 96, b32+201, P_BE, b32+201, b32+ 33, b32+ 99, aliases+ 67}, /* 64 */ - {16UL, b32+ 97, 0, P_BE, 0, b32+195, 0, aliases+ 22}, /* 65 */ - {16UL, b32+ 97, 0, P_LE, 0, b32+143, 0, aliases+ 0}, /* 66 */ - {16UL, b32+ 97, 0, P_LE, b32+200, b32+ 63, b32+134, aliases+ 44}, /* 67 */ - {16UL, b32+ 97, b32+ 98, P_BE, 0, b32+121, 0, aliases+ 29}, /* 68 */ - {16UL, b32+ 97, b32+200, P_BE, 0, b32+132, 0, aliases+ 27}, /* 69 */ - {16UL, b32+ 97, b32+200, P_LE, 0, b32+ 70, 0, aliases+132}, /* 70 */ - {16UL, b32+ 97, b32+200, P_LE, b32+200, b32+139, b32+134, aliases+ 55}, /* 71 */ - {14UL, b32+100, 0, P_BE, b32+199, b32+152, b32+ 15, aliases+ 15}, /* 72 */ - {30UL, b32+101, b32+202, P_BE, b32+202, b32+ 19, b32+165, aliases+ 70}, /* 73 */ - {12UL, b32+102, 0, P_BE, 0, b32+187, 0, aliases+ 10}, /* 74 */ - {12UL, b32+102, 0, P_BELE, 0, b32+170, 0, aliases+ 12}, /* 75 */ - {32UL, b32+103, 0, P_BE, 0, b32+ 49, 0, aliases+ 85}, /* 76 */ - {21UL, b32+104, 0, P_BE, 0, b32+ 92, 0, aliases+ 58}, /* 77 */ - {24UL, b32+105, 0, P_BE, 0, b32+159, 0, aliases+ 64}, /* 78 */ - {24UL, b32+105, b32+141, P_BE, 0, b32+ 38, 0, aliases+ 59}, /* 79 */ - { 7UL, b32+108, 0, P_BE, 0, b32+149, 0, aliases+105}, /* 80 */ - {15UL, b32+109, 0, P_BE, 0, b32+ 12, 0, aliases+ 16}, /* 81 */ - {16UL, b32+110, 0, P_BE, 0, b32+163, 0, aliases+ 51}, /* 82 */ - {10UL, b32+111, 0, P_BE, 0, b32+ 84, 0, aliases+ 3}, /* 83 */ - { 8UL, b32+117, 0, P_BE, 0, b32+179, 0, aliases+118}, /* 84 */ - { 8UL, b32+117, 0, P_LE, 0, b32+ 40, 0, aliases+123}, /* 85 */ - { 8UL, b32+117, b32+196, P_BE, 0, b32+169, 0, aliases+110}, /* 86 */ - { 6UL, b32+118, b32+190, P_BE, 0, b32+ 54, 0, aliases+ 92}, /* 87 */ - { 7UL, b32+120, b32+193, P_LE, 0, b32+125, 0, aliases+104}, /* 88 */ - {16UL, b32+122, 0, P_BE, 0, b32+ 16, 0, aliases+ 52}, /* 89 */ - { 8UL, b32+126, 0, P_LE, 0, b32+ 41, 0, aliases+109}, /* 90 */ - { 5UL, b32+127, 0, P_LE, 0, b32+ 57, 0, aliases+ 90}, /* 91 */ - {32UL, b32+129, b32+204, P_LE, b32+204, b32+106, b32+ 64, aliases+ 84}, /* 92 */ - {17UL, b32+137, 0, P_BE, 0, b32+ 43, 0, aliases+ 57}, /* 93 */ - { 6UL, b32+144, 0, P_BE, b32+190, b32+ 71, b32+178, aliases+ 95}, /* 94 */ - {16UL, b32+157, b32+200, P_BE, 0, b32+ 72, 0, aliases+ 26}, /* 95 */ - {15UL, b32+162, 0, P_BE, b32+ 2, b32+ 68, b32+162, aliases+ 17}, /* 96 */ - {12UL, b32+164, 0, P_BE, b32+198, b32+136, b32+ 23, aliases+ 11}, /* 97 */ - { 8UL, b32+167, 0, P_BE, 0, b32+144, 0, aliases+112}, /* 98 */ - {13UL, b32+177, 0, P_BE, 0, b32+ 44, 0, aliases+ 13}, /* 99 */ - {12UL, b32+184, b32+198, P_BE, 0, b32+166, 0, aliases+ 9}, /* 100 */ - {32UL, b32+186, b32+204, P_LE, b32+204, b32+ 22, b32+112, aliases+ 75}, /* 101 */ - {10UL, b32+188, b32+197, P_BE, 0, b32+111, 0, aliases+ 4}, /* 102 */ - { 0UL, 0, 0, P_BE, 0, 0, 0, NULL }, /* terminating entry */ + {64UL, b64, b64a, P_LE | P_CONFIR, b64a, b64b, b64c, aliases+130}, /* 0 */ + {32UL, b32+ 0, 0, P_BE | P_CONFIR, 0, b32+147, 0, aliases+107}, /* 1 */ + {40UL, b40, 0, P_BE | P_ACADEM, b40a, b40b, b40c, aliases+115}, /* 2 */ + {24UL, b32+ 3, b32+ 76, P_LE | P_ATTEST, 0, b32+152, 0, aliases+ 77}, /* 3 */ + {32UL, b32+ 8, 0, P_BE | P_ATTEST, b32+207, b32+ 92, b32+157, aliases+ 98}, /* 4 */ + {32UL, b32+ 8, b32+207, P_BE | P_ATTEST, 0, b32+ 7, 0, aliases+104}, /* 5 */ + {32UL, b32+ 8, b32+207, P_BE | P_ATTEST, b32+207, b32+194, b32+157, aliases+ 96}, /* 6 */ + {32UL, b32+ 8, b32+207, P_LE | P_CONFIR, 0, b32+ 56, 0, aliases+103}, /* 7 */ + {32UL, b32+ 8, b32+207, P_LE | P_ATTEST, b32+207, b32+160, b32+173, aliases+102}, /* 8 */ + {16UL, b32+ 9, 0, P_BE | P_ATTEST, 0, b32+ 5, 0, aliases+ 36}, /* 9 */ + {16UL, b32+ 9, 0, P_BE | P_ATTEST, b32+ 1, b32+ 4, b32+ 9, aliases+ 35}, /* 10 */ + { 8UL, b32+ 10, 0, P_BE | P_ATTEST, 0, b32+187, 0, aliases+157}, /* 11 */ + { 8UL, b32+ 10, 0, P_BE | P_ACADEM, b32+ 75, b32+125, b32+133, aliases+147}, /* 12 */ + { 8UL, b32+ 10, b32+199, P_LE | P_ACADEM, 0, b32+163, 0, aliases+155}, /* 13 */ + {16UL, b32+ 11, b32+203, P_LE | P_ATTEST, 0, b32+123, 0, aliases+ 58}, /* 14 */ + {31UL, b32+ 12, b32+206, P_BE | P_CONFIR, b32+206, b32+ 26, b32+120, aliases+ 88}, /* 15 */ + { 6UL, b32+ 14, 0, P_LE | P_ACADEM, 0, b32+ 25, 0, aliases+124}, /* 16 */ + {82UL, b82, 0, P_LE | P_ATTEST, 0, b82a, 0, aliases+160}, /* 17 */ + {16UL, b32+ 18, 0, P_BE | P_ATTEST, 0, b32+ 53, 0, aliases+ 73}, /* 18 */ + {16UL, b32+ 18, 0, P_BE | P_ACADEM, b32+203, b32+162, b32+ 29, aliases+ 42}, /* 19 */ + {16UL, b32+ 18, 0, P_LE | P_ATTEST, 0, b32+ 38, 0, aliases+ 50}, /* 20 */ + {16UL, b32+ 18, b32+ 29, P_BE | P_ATTEST, 0, b32+178, 0, aliases+ 63}, /* 21 */ + {16UL, b32+ 18, b32+108, P_LE | P_ATTEST, 0, b32+ 43, 0, aliases+ 66}, /* 22 */ + {16UL, b32+ 18, b32+137, P_LE | P_THIRDP, 0, b32+ 83, 0, aliases+ 62}, /* 23 */ + {16UL, b32+ 18, b32+156, P_LE | P_ATTEST, 0, b32+149, 0, aliases+ 48}, /* 24 */ + {16UL, b32+ 18, b32+203, P_BE | P_ATTEST, 0, b32+ 47, 0, aliases+ 44}, /* 25 */ + {16UL, b32+ 18, b32+203, P_BE | P_ATTEST, b32+203, b32+170, b32+ 29, aliases+ 41}, /* 26 */ + {16UL, b32+ 18, b32+203, P_LE | P_ATTEST, 0, b32+ 88, 0, aliases+ 56}, /* 27 */ + {16UL, b32+ 18, b32+203, P_LE | P_ATTEST, b32+203, b32+114, b32+185, aliases+ 45}, /* 28 */ + { 7UL, b32+ 19, 0, P_BE | P_ACADEM, 0, b32+181, 0, aliases+134}, /* 29 */ + { 6UL, b32+ 27, b32+193, P_BE | P_ACADEM, 0, b32+183, 0, aliases+122}, /* 30 */ + { 8UL, b32+ 28, 0, P_BE | P_ACADEM, 0, b32+ 57, 0, aliases+145}, /* 31 */ + { 8UL, b32+ 28, b32+195, P_BE | P_ATTEST, 0, b32+ 95, 0, aliases+148}, /* 32 */ + { 8UL, b32+ 28, b32+199, P_BE | P_ATTEST, b32+199, b32+ 70, b32+155, aliases+156}, /* 33 */ + { 8UL, b32+ 28, b32+199, P_LE | P_ATTEST, 0, b32+116, 0, aliases+158}, /* 34 */ + {16UL, b32+ 30, b32+203, P_BE | P_ATTEST, b32+203, b32+130, b32+177, aliases+ 61}, /* 35 */ + {32UL, b32+ 31, b32+207, P_LE | P_ATTEST, b32+207, b32+176, b32+144, aliases+101}, /* 36 */ + {14UL, b32+ 35, 0, P_LE | P_ATTEST, 0, b32+ 36, 0, aliases+ 17}, /* 37 */ + { 5UL, b32+ 46, b32+192, P_LE | P_THIRDP, b32+192, b32+158, b32+ 49, aliases+120}, /* 38 */ + { 8UL, b32+ 48, 0, P_BE | P_ATTEST, 0, b32+ 61, 0, aliases+154}, /* 39 */ + { 8UL, b32+ 48, b32+199, P_BE | P_ATTEST, b32+199, b32+174, b32+ 63, aliases+139}, /* 40 */ + { 4UL, b32+ 49, 0, P_LE | P_ACADEM, 0, b32+ 89, 0, aliases+112}, /* 41 */ + { 4UL, b32+ 49, b32+184, P_BE | P_ACADEM, b32+184, b32+135, b32+ 33, aliases+113}, /* 42 */ + { 8UL, b32+ 51, 0, P_LE | P_ATTEST, 0, b32+125, 0, aliases+152}, /* 43 */ + { 8UL, b32+ 51, b32+199, P_BE | P_ATTEST, 0, b32+191, 0, aliases+153}, /* 44 */ + {24UL, b32+ 54, b32+204, P_BE | P_ACADEM, b32+204, b32+142, b32+ 21, aliases+ 80}, /* 45 */ + { 8UL, b32+ 59, 0, P_LE | P_ATTEST, 0, b32+ 22, 0, aliases+142}, /* 46 */ + {16UL, b32+ 60, 0, P_BE | P_CONFIR, b32+203, b32+153, b32+126, aliases+ 38}, /* 47 */ + {16UL, b32+ 60, 0, P_LE | P_CONFIR, b32+203, b32+182, b32+ 86, aliases+ 37}, /* 48 */ + {64UL, b64d, 0, P_BE | P_ACADEM, 0, b64e, 0, aliases+128}, /* 49 */ + {64UL, b64d, b64a, P_BE | P_CONFIR, b64a, b64f, b64g, aliases+131}, /* 50 */ + {64UL, b64d, b64a, P_LE | P_ATTEST, b64a, b64h, b64i, aliases+132}, /* 51 */ + { 5UL, b32+ 66, b32+ 66, P_BE | P_ATTEST, 0, 0, 0, aliases+117}, /* 52 */ + { 8UL, b32+ 67, 0, P_BE | P_ACADEM, b32+199, b32+115, b32+ 74, aliases+146}, /* 53 */ + {16UL, b32+ 77, 0, P_BE | P_ATTEST, 0, b32+ 78, 0, aliases+ 59}, /* 54 */ + {10UL, b32+ 79, 0, P_BE | P_ACADEM, b32+200, b32+ 68, b32+ 52, aliases+ 6}, /* 55 */ + {24UL, b32+ 80, b32+132, P_BE | P_ATTEST, 0, b32+ 32, 0, aliases+ 79}, /* 56 */ + {24UL, b32+ 80, b32+197, P_BE | P_ATTEST, 0, b32+ 94, 0, aliases+ 78}, /* 57 */ + { 3UL, b32+ 81, 0, P_BE | P_ACADEM, b32+175, b32+ 96, b32+ 62, aliases+ 85}, /* 58 */ + { 3UL, b32+ 81, b32+175, P_LE | P_ACADEM, 0, b32+150, 0, aliases+ 86}, /* 59 */ + {11UL, b32+ 82, 0, P_BE | P_ACADEM, 0, b32+ 15, 0, aliases+ 10}, /* 60 */ + { 6UL, b32+ 84, 0, P_LE | P_ATTEST, 0, b32+117, 0, aliases+123}, /* 61 */ + {16UL, b32+ 87, 0, P_BE | P_THIRDP, 0, b32+148, 0, aliases+ 52}, /* 62 */ + {11UL, b32+ 90, b32+ 6, P_BE | P_ATTEST, 0, b32+140, 0, aliases+ 9}, /* 63 */ + {16UL, b32+ 91, 0, P_BE | P_ATTEST, 0, b32+ 37, 0, aliases+ 60}, /* 64 */ + {24UL, b32+ 97, 0, P_BE | P_ACADEM, 0, b32+ 40, 0, aliases+ 82}, /* 65 */ + {24UL, b32+ 97, b32+204, P_BE | P_ATTEST, b32+204, b32+ 34, b32+100, aliases+ 84}, /* 66 */ + {16UL, b32+ 98, 0, P_BE | P_ATTEST, 0, b32+198, 0, aliases+ 67}, /* 67 */ + {16UL, b32+ 98, 0, P_LE | P_CONFIR, 0, b32+145, 0, aliases+ 24}, /* 68 */ + {16UL, b32+ 98, 0, P_LE | P_ATTEST, b32+203, b32+ 64, b32+136, aliases+ 55}, /* 69 */ + {16UL, b32+ 98, b32+ 99, P_BE | P_ATTEST, 0, b32+122, 0, aliases+ 34}, /* 70 */ + {16UL, b32+ 98, b32+203, P_BE | P_THIRDP, 0, b32+134, 0, aliases+ 32}, /* 71 */ + {16UL, b32+ 98, b32+203, P_LE | P_ATTEST, 0, b32+ 71, 0, aliases+ 57}, /* 72 */ + {16UL, b32+ 98, b32+203, P_LE | P_THIRDP, b32+203, b32+141, b32+136, aliases+ 68}, /* 73 */ + {14UL, b32+101, 0, P_BE | P_ACADEM, b32+202, b32+154, b32+ 16, aliases+ 18}, /* 74 */ + {30UL, b32+102, b32+205, P_BE | P_ACADEM, b32+205, b32+ 20, b32+167, aliases+ 87}, /* 75 */ + {12UL, b32+103, 0, P_BE | P_ACADEM, 0, b32+189, 0, aliases+ 13}, /* 76 */ + {12UL, b32+103, 0, P_BELE | P_ACADEM, 0, b32+172, 0, aliases+ 15}, /* 77 */ + {32UL, b32+104, 0, P_BE | P_ATTEST, 0, b32+ 50, 0, aliases+ 92}, /* 78 */ + {21UL, b32+105, 0, P_BE | P_ACADEM, 0, b32+ 93, 0, aliases+ 75}, /* 79 */ + {24UL, b32+106, 0, P_BE | P_ACADEM, 0, b32+161, 0, aliases+ 81}, /* 80 */ + {24UL, b32+106, b32+143, P_BE | P_ATTEST, 0, b32+ 39, 0, aliases+ 83}, /* 81 */ + { 7UL, b32+109, 0, P_BE | P_ACADEM, 0, b32+151, 0, aliases+136}, /* 82 */ + {15UL, b32+110, 0, P_BE | P_ACADEM, 0, b32+ 13, 0, aliases+ 20}, /* 83 */ + {16UL, b32+111, 0, P_BE | P_ATTEST, 0, b32+165, 0, aliases+ 64}, /* 84 */ + {10UL, b32+112, 0, P_BE | P_ATTEST, 0, b32+ 85, 0, aliases+ 4}, /* 85 */ + { 8UL, b32+118, 0, P_BE | P_ACADEM, 0, b32+181, 0, aliases+150}, /* 86 */ + { 8UL, b32+118, 0, P_LE | P_THIRDP, 0, b32+ 41, 0, aliases+159}, /* 87 */ + { 8UL, b32+118, b32+199, P_BE | P_ACADEM, 0, b32+171, 0, aliases+141}, /* 88 */ + { 6UL, b32+119, b32+193, P_BE | P_ATTEST, 0, b32+ 55, 0, aliases+121}, /* 89 */ + { 7UL, b32+121, b32+196, P_LE | P_ACADEM, 0, b32+127, 0, aliases+135}, /* 90 */ + {16UL, b32+124, 0, P_BE | P_CONFIR, 0, b32+ 17, 0, aliases+ 65}, /* 91 */ + { 8UL, b32+128, 0, P_LE | P_ATTEST, 0, b32+ 42, 0, aliases+140}, /* 92 */ + { 5UL, b32+129, 0, P_LE | P_ACADEM, 0, b32+ 58, 0, aliases+118}, /* 93 */ + {32UL, b32+131, b32+207, P_LE | P_CONFIR, b32+207, b32+107, b32+ 65, aliases+ 95}, /* 94 */ + {17UL, b32+139, 0, P_BE | P_ACADEM, 0, b32+ 44, 0, aliases+ 74}, /* 95 */ + { 6UL, b32+146, 0, P_BE | P_ACADEM, b32+193, b32+ 72, b32+180, aliases+125}, /* 96 */ + {16UL, b32+159, b32+203, P_BE | P_ACADEM, 0, b32+ 73, 0, aliases+ 31}, /* 97 */ + {15UL, b32+164, 0, P_BE | P_ATTEST, b32+ 2, b32+ 69, b32+164, aliases+ 21}, /* 98 */ + {12UL, b32+166, 0, P_BE | P_ACADEM, b32+201, b32+138, b32+ 24, aliases+ 14}, /* 99 */ + { 8UL, b32+169, 0, P_BE | P_ACADEM, 0, b32+146, 0, aliases+143}, /* 100 */ + {13UL, b32+179, 0, P_BE | P_ATTEST, 0, b32+ 45, 0, aliases+ 16}, /* 101 */ + {12UL, b32+186, b32+201, P_BE | P_ACADEM, 0, b32+168, 0, aliases+ 12}, /* 102 */ + {32UL, b32+188, b32+207, P_LE | P_ATTEST, b32+207, b32+ 23, b32+113, aliases+ 93}, /* 103 */ + {10UL, b32+190, b32+200, P_BE | P_ACADEM, 0, b32+112, 0, aliases+ 5}, /* 104 */ + { 0UL, 0, 0, P_BE | P_UNDFCL, 0, 0, 0, NULL }, /* terminating entry */ }; -# define NPRESETS 103 +# define NPRESETS 105 /* List of names with pointers to models, pre-sorted for use with bsearch() */ static const struct malias aliases[] = { - {"ARC", models+ 66}, /* 0 */ - {"B-CRC-32", models+ 6}, /* 1 */ - {"CKSUM", models+ 4}, /* 2 */ - {"CRC-10", models+ 83}, /* 3 */ - {"CRC-10/CDMA2000", models+102}, /* 4 */ - {"CRC-10/GSM", models+ 53}, /* 5 */ - {"CRC-11", models+ 61}, /* 6 */ - {"CRC-11/UMTS", models+ 58}, /* 7 */ - {"CRC-12/3GPP", models+ 75}, /* 8 */ - {"CRC-12/CDMA2000", models+100}, /* 9 */ - {"CRC-12/DECT", models+ 74}, /* 10 */ - {"CRC-12/GSM", models+ 97}, /* 11 */ - {"CRC-12/UMTS", models+ 75}, /* 12 */ - {"CRC-13/BBC", models+ 99}, /* 13 */ - {"CRC-14/DARC", models+ 36}, /* 14 */ - {"CRC-14/GSM", models+ 72}, /* 15 */ - {"CRC-15", models+ 81}, /* 16 */ - {"CRC-15/MPT1327", models+ 96}, /* 17 */ - {"CRC-16", models+ 66}, /* 18 */ - {"CRC-16/ACORN", models+ 17}, /* 19 */ - {"CRC-16/ARC", models+ 66}, /* 20 */ - {"CRC-16/AUG-CCITT", models+ 20}, /* 21 */ - {"CRC-16/BUYPASS", models+ 65}, /* 22 */ - {"CRC-16/CCITT", models+ 19}, /* 23 */ - {"CRC-16/CCITT-FALSE", models+ 24}, /* 24 */ - {"CRC-16/CCITT-TRUE", models+ 19}, /* 25 */ - {"CRC-16/CDMA2000", models+ 95}, /* 26 */ - {"CRC-16/CMS", models+ 69}, /* 27 */ - {"CRC-16/DARC", models+ 25}, /* 28 */ - {"CRC-16/DDS-110", models+ 68}, /* 29 */ - {"CRC-16/DECT-R", models+ 10}, /* 30 */ - {"CRC-16/DECT-X", models+ 9}, /* 31 */ - {"CRC-16/DNP", models+ 46}, /* 32 */ - {"CRC-16/EN-13757", models+ 45}, /* 33 */ - {"CRC-16/EPC", models+ 25}, /* 34 */ - {"CRC-16/GENIBUS", models+ 25}, /* 35 */ - {"CRC-16/GSM", models+ 18}, /* 36 */ - {"CRC-16/I-CODE", models+ 25}, /* 37 */ - {"CRC-16/IBM-SDLC", models+ 27}, /* 38 */ - {"CRC-16/IEC-61158-2", models+ 34}, /* 39 */ - {"CRC-16/ISO-HDLC", models+ 27}, /* 40 */ - {"CRC-16/LHA", models+ 66}, /* 41 */ - {"CRC-16/LJ1200", models+ 60}, /* 42 */ - {"CRC-16/LTE", models+ 17}, /* 43 */ - {"CRC-16/MAXIM", models+ 67}, /* 44 */ - {"CRC-16/MCRF4XX", models+ 26}, /* 45 */ - {"CRC-16/OPENSAFETY-A", models+ 52}, /* 46 */ - {"CRC-16/OPENSAFETY-B", models+ 62}, /* 47 */ - {"CRC-16/PROFIBUS", models+ 34}, /* 48 */ - {"CRC-16/RIELLO", models+ 22}, /* 49 */ - {"CRC-16/SPI-FUJITSU", models+ 20}, /* 50 */ - {"CRC-16/T10-DIF", models+ 82}, /* 51 */ - {"CRC-16/TELEDISK", models+ 89}, /* 52 */ - {"CRC-16/TMS37157", models+ 21}, /* 53 */ - {"CRC-16/UMTS", models+ 65}, /* 54 */ - {"CRC-16/USB", models+ 71}, /* 55 */ - {"CRC-16/VERIFONE", models+ 65}, /* 56 */ - {"CRC-17/CAN-FD", models+ 93}, /* 57 */ - {"CRC-21/CAN-FD", models+ 77}, /* 58 */ - {"CRC-24", models+ 79}, /* 59 */ - {"CRC-24/BLE", models+ 3}, /* 60 */ - {"CRC-24/FLEXRAY-A", models+ 55}, /* 61 */ - {"CRC-24/FLEXRAY-B", models+ 54}, /* 62 */ - {"CRC-24/INTERLAKEN", models+ 43}, /* 63 */ - {"CRC-24/LTE-A", models+ 78}, /* 64 */ - {"CRC-24/LTE-B", models+ 63}, /* 65 */ - {"CRC-24/OPENPGP", models+ 79}, /* 66 */ - {"CRC-24/OS-9", models+ 64}, /* 67 */ - {"CRC-3/GSM", models+ 56}, /* 68 */ - {"CRC-3/ROHC", models+ 57}, /* 69 */ - {"CRC-30/CDMA", models+ 73}, /* 70 */ - {"CRC-31/PHILIPS", models+ 14}, /* 71 */ - {"CRC-32", models+ 8}, /* 72 */ - {"CRC-32/AAL5", models+ 6}, /* 73 */ - {"CRC-32/ADCCP", models+ 8}, /* 74 */ - {"CRC-32/AUTOSAR", models+101}, /* 75 */ - {"CRC-32/BZIP2", models+ 6}, /* 76 */ - {"CRC-32/CASTAGNOLI", models+ 35}, /* 77 */ - {"CRC-32/DECT-B", models+ 6}, /* 78 */ - {"CRC-32/INTERLAKEN", models+ 35}, /* 79 */ - {"CRC-32/ISCSI", models+ 35}, /* 80 */ - {"CRC-32/MPEG-2", models+ 5}, /* 81 */ - {"CRC-32/POSIX", models+ 4}, /* 82 */ - {"CRC-32C", models+ 35}, /* 83 */ - {"CRC-32D", models+ 92}, /* 84 */ - {"CRC-32Q", models+ 76}, /* 85 */ - {"CRC-4/INTERLAKEN", models+ 41}, /* 86 */ - {"CRC-4/ITU", models+ 40}, /* 87 */ - {"CRC-40/GSM", models+ 2}, /* 88 */ - {"CRC-5/EPC", models+ 50}, /* 89 */ - {"CRC-5/ITU", models+ 91}, /* 90 */ - {"CRC-5/USB", models+ 37}, /* 91 */ - {"CRC-6/CDMA2000-A", models+ 87}, /* 92 */ - {"CRC-6/CDMA2000-B", models+ 29}, /* 93 */ - {"CRC-6/DARC", models+ 59}, /* 94 */ - {"CRC-6/GSM", models+ 94}, /* 95 */ - {"CRC-6/ITU", models+ 15}, /* 96 */ - {"CRC-64", models+ 47}, /* 97 */ - {"CRC-64/ECMA-182", models+ 47}, /* 98 */ - {"CRC-64/GO-ECMA", models+ 49}, /* 99 */ - {"CRC-64/GO-ISO", models+ 0}, /* 100 */ - {"CRC-64/WE", models+ 48}, /* 101 */ - {"CRC-64/XZ", models+ 49}, /* 102 */ - {"CRC-7", models+ 28}, /* 103 */ - {"CRC-7/ROHC", models+ 88}, /* 104 */ - {"CRC-7/UMTS", models+ 80}, /* 105 */ - {"CRC-8", models+ 11}, /* 106 */ - {"CRC-8/AES", models+ 33}, /* 107 */ - {"CRC-8/AUTOSAR", models+ 39}, /* 108 */ - {"CRC-8/BLUETOOTH", models+ 90}, /* 109 */ - {"CRC-8/CDMA2000", models+ 86}, /* 110 */ - {"CRC-8/DARC", models+ 44}, /* 111 */ - {"CRC-8/DVB-S2", models+ 98}, /* 112 */ - {"CRC-8/EBU", models+ 33}, /* 113 */ - {"CRC-8/GSM-A", models+ 30}, /* 114 */ - {"CRC-8/GSM-B", models+ 51}, /* 115 */ - {"CRC-8/I-CODE", models+ 31}, /* 116 */ - {"CRC-8/ITU", models+ 12}, /* 117 */ - {"CRC-8/LTE", models+ 84}, /* 118 */ - {"CRC-8/MAXIM", models+ 42}, /* 119 */ - {"CRC-8/OPENSAFETY", models+ 38}, /* 120 */ - {"CRC-8/ROHC", models+ 13}, /* 121 */ - {"CRC-8/SAE-J1850", models+ 32}, /* 122 */ - {"CRC-8/WCDMA", models+ 85}, /* 123 */ - {"CRC-82/DARC", models+ 16}, /* 124 */ - {"CRC-A", models+ 23}, /* 125 */ - {"CRC-B", models+ 27}, /* 126 */ - {"CRC-CCITT", models+ 19}, /* 127 */ - {"CRC-IBM", models+ 66}, /* 128 */ - {"DOW-CRC", models+ 42}, /* 129 */ - {"JAMCRC", models+ 7}, /* 130 */ - {"KERMIT", models+ 19}, /* 131 */ - {"MODBUS", models+ 70}, /* 132 */ - {"PKZIP", models+ 8}, /* 133 */ - {"R-CRC-16", models+ 10}, /* 134 */ - {"X-25", models+ 27}, /* 135 */ - {"X-CRC-12", models+ 74}, /* 136 */ - {"X-CRC-16", models+ 9}, /* 137 */ - {"XFER", models+ 1}, /* 138 */ - {"XMODEM", models+ 17}, /* 139 */ - {"ZMODEM", models+ 17}, /* 140 */ - {NULL, NULL }, /* terminating entry */ + {"ARC", models+ 68}, /* 0 */ + {"B-CRC-32", models+ 6}, /* 1 */ + {"CKSUM", models+ 4}, /* 2 */ + {"CRC-10", models+ 85}, /* 3 */ + {"CRC-10/ATM", models+ 85}, /* 4 */ + {"CRC-10/CDMA2000", models+104}, /* 5 */ + {"CRC-10/GSM", models+ 55}, /* 6 */ + {"CRC-10/I-610", models+ 85}, /* 7 */ + {"CRC-11", models+ 63}, /* 8 */ + {"CRC-11/FLEXRAY", models+ 63}, /* 9 */ + {"CRC-11/UMTS", models+ 60}, /* 10 */ + {"CRC-12/3GPP", models+ 77}, /* 11 */ + {"CRC-12/CDMA2000", models+102}, /* 12 */ + {"CRC-12/DECT", models+ 76}, /* 13 */ + {"CRC-12/GSM", models+ 99}, /* 14 */ + {"CRC-12/UMTS", models+ 77}, /* 15 */ + {"CRC-13/BBC", models+101}, /* 16 */ + {"CRC-14/DARC", models+ 37}, /* 17 */ + {"CRC-14/GSM", models+ 74}, /* 18 */ + {"CRC-15", models+ 83}, /* 19 */ + {"CRC-15/CAN", models+ 83}, /* 20 */ + {"CRC-15/MPT1327", models+ 98}, /* 21 */ + {"CRC-16", models+ 68}, /* 22 */ + {"CRC-16/ACORN", models+ 18}, /* 23 */ + {"CRC-16/ARC", models+ 68}, /* 24 */ + {"CRC-16/AUG-CCITT", models+ 21}, /* 25 */ + {"CRC-16/AUTOSAR", models+ 25}, /* 26 */ + {"CRC-16/BUYPASS", models+ 67}, /* 27 */ + {"CRC-16/CCITT", models+ 20}, /* 28 */ + {"CRC-16/CCITT-FALSE", models+ 25}, /* 29 */ + {"CRC-16/CCITT-TRUE", models+ 20}, /* 30 */ + {"CRC-16/CDMA2000", models+ 97}, /* 31 */ + {"CRC-16/CMS", models+ 71}, /* 32 */ + {"CRC-16/DARC", models+ 26}, /* 33 */ + {"CRC-16/DDS-110", models+ 70}, /* 34 */ + {"CRC-16/DECT-R", models+ 10}, /* 35 */ + {"CRC-16/DECT-X", models+ 9}, /* 36 */ + {"CRC-16/DNP", models+ 48}, /* 37 */ + {"CRC-16/EN-13757", models+ 47}, /* 38 */ + {"CRC-16/EPC", models+ 26}, /* 39 */ + {"CRC-16/EPC-C1G2", models+ 26}, /* 40 */ + {"CRC-16/GENIBUS", models+ 26}, /* 41 */ + {"CRC-16/GSM", models+ 19}, /* 42 */ + {"CRC-16/I-CODE", models+ 26}, /* 43 */ + {"CRC-16/IBM-3740", models+ 25}, /* 44 */ + {"CRC-16/IBM-SDLC", models+ 28}, /* 45 */ + {"CRC-16/IEC-61158-2", models+ 35}, /* 46 */ + {"CRC-16/ISO-HDLC", models+ 28}, /* 47 */ + {"CRC-16/ISO-IEC-14443-3-A", models+ 24}, /* 48 */ + {"CRC-16/ISO-IEC-14443-3-B", models+ 28}, /* 49 */ + {"CRC-16/KERMIT", models+ 20}, /* 50 */ + {"CRC-16/LHA", models+ 68}, /* 51 */ + {"CRC-16/LJ1200", models+ 62}, /* 52 */ + {"CRC-16/LTE", models+ 18}, /* 53 */ + {"CRC-16/MAXIM", models+ 69}, /* 54 */ + {"CRC-16/MAXIM-DOW", models+ 69}, /* 55 */ + {"CRC-16/MCRF4XX", models+ 27}, /* 56 */ + {"CRC-16/MODBUS", models+ 72}, /* 57 */ + {"CRC-16/NRSC-5", models+ 14}, /* 58 */ + {"CRC-16/OPENSAFETY-A", models+ 54}, /* 59 */ + {"CRC-16/OPENSAFETY-B", models+ 64}, /* 60 */ + {"CRC-16/PROFIBUS", models+ 35}, /* 61 */ + {"CRC-16/RIELLO", models+ 23}, /* 62 */ + {"CRC-16/SPI-FUJITSU", models+ 21}, /* 63 */ + {"CRC-16/T10-DIF", models+ 84}, /* 64 */ + {"CRC-16/TELEDISK", models+ 91}, /* 65 */ + {"CRC-16/TMS37157", models+ 22}, /* 66 */ + {"CRC-16/UMTS", models+ 67}, /* 67 */ + {"CRC-16/USB", models+ 73}, /* 68 */ + {"CRC-16/V-41-LSB", models+ 20}, /* 69 */ + {"CRC-16/V-41-MSB", models+ 18}, /* 70 */ + {"CRC-16/VERIFONE", models+ 67}, /* 71 */ + {"CRC-16/X-25", models+ 28}, /* 72 */ + {"CRC-16/XMODEM", models+ 18}, /* 73 */ + {"CRC-17/CAN-FD", models+ 95}, /* 74 */ + {"CRC-21/CAN-FD", models+ 79}, /* 75 */ + {"CRC-24", models+ 81}, /* 76 */ + {"CRC-24/BLE", models+ 3}, /* 77 */ + {"CRC-24/FLEXRAY-A", models+ 57}, /* 78 */ + {"CRC-24/FLEXRAY-B", models+ 56}, /* 79 */ + {"CRC-24/INTERLAKEN", models+ 45}, /* 80 */ + {"CRC-24/LTE-A", models+ 80}, /* 81 */ + {"CRC-24/LTE-B", models+ 65}, /* 82 */ + {"CRC-24/OPENPGP", models+ 81}, /* 83 */ + {"CRC-24/OS-9", models+ 66}, /* 84 */ + {"CRC-3/GSM", models+ 58}, /* 85 */ + {"CRC-3/ROHC", models+ 59}, /* 86 */ + {"CRC-30/CDMA", models+ 75}, /* 87 */ + {"CRC-31/PHILIPS", models+ 15}, /* 88 */ + {"CRC-32", models+ 8}, /* 89 */ + {"CRC-32/AAL5", models+ 6}, /* 90 */ + {"CRC-32/ADCCP", models+ 8}, /* 91 */ + {"CRC-32/AIXM", models+ 78}, /* 92 */ + {"CRC-32/AUTOSAR", models+103}, /* 93 */ + {"CRC-32/BASE91-C", models+ 36}, /* 94 */ + {"CRC-32/BASE91-D", models+ 94}, /* 95 */ + {"CRC-32/BZIP2", models+ 6}, /* 96 */ + {"CRC-32/CASTAGNOLI", models+ 36}, /* 97 */ + {"CRC-32/CKSUM", models+ 4}, /* 98 */ + {"CRC-32/DECT-B", models+ 6}, /* 99 */ + {"CRC-32/INTERLAKEN", models+ 36}, /* 100 */ + {"CRC-32/ISCSI", models+ 36}, /* 101 */ + {"CRC-32/ISO-HDLC", models+ 8}, /* 102 */ + {"CRC-32/JAMCRC", models+ 7}, /* 103 */ + {"CRC-32/MPEG-2", models+ 5}, /* 104 */ + {"CRC-32/POSIX", models+ 4}, /* 105 */ + {"CRC-32/V-42", models+ 8}, /* 106 */ + {"CRC-32/XFER", models+ 1}, /* 107 */ + {"CRC-32/XZ", models+ 8}, /* 108 */ + {"CRC-32C", models+ 36}, /* 109 */ + {"CRC-32D", models+ 94}, /* 110 */ + {"CRC-32Q", models+ 78}, /* 111 */ + {"CRC-4/G-704", models+ 41}, /* 112 */ + {"CRC-4/INTERLAKEN", models+ 42}, /* 113 */ + {"CRC-4/ITU", models+ 41}, /* 114 */ + {"CRC-40/GSM", models+ 2}, /* 115 */ + {"CRC-5/EPC", models+ 52}, /* 116 */ + {"CRC-5/EPC-C1G2", models+ 52}, /* 117 */ + {"CRC-5/G-704", models+ 93}, /* 118 */ + {"CRC-5/ITU", models+ 93}, /* 119 */ + {"CRC-5/USB", models+ 38}, /* 120 */ + {"CRC-6/CDMA2000-A", models+ 89}, /* 121 */ + {"CRC-6/CDMA2000-B", models+ 30}, /* 122 */ + {"CRC-6/DARC", models+ 61}, /* 123 */ + {"CRC-6/G-704", models+ 16}, /* 124 */ + {"CRC-6/GSM", models+ 96}, /* 125 */ + {"CRC-6/ITU", models+ 16}, /* 126 */ + {"CRC-64", models+ 49}, /* 127 */ + {"CRC-64/ECMA-182", models+ 49}, /* 128 */ + {"CRC-64/GO-ECMA", models+ 51}, /* 129 */ + {"CRC-64/GO-ISO", models+ 0}, /* 130 */ + {"CRC-64/WE", models+ 50}, /* 131 */ + {"CRC-64/XZ", models+ 51}, /* 132 */ + {"CRC-7", models+ 29}, /* 133 */ + {"CRC-7/MMC", models+ 29}, /* 134 */ + {"CRC-7/ROHC", models+ 90}, /* 135 */ + {"CRC-7/UMTS", models+ 82}, /* 136 */ + {"CRC-8", models+ 11}, /* 137 */ + {"CRC-8/AES", models+ 34}, /* 138 */ + {"CRC-8/AUTOSAR", models+ 40}, /* 139 */ + {"CRC-8/BLUETOOTH", models+ 92}, /* 140 */ + {"CRC-8/CDMA2000", models+ 88}, /* 141 */ + {"CRC-8/DARC", models+ 46}, /* 142 */ + {"CRC-8/DVB-S2", models+100}, /* 143 */ + {"CRC-8/EBU", models+ 34}, /* 144 */ + {"CRC-8/GSM-A", models+ 31}, /* 145 */ + {"CRC-8/GSM-B", models+ 53}, /* 146 */ + {"CRC-8/I-432-1", models+ 12}, /* 147 */ + {"CRC-8/I-CODE", models+ 32}, /* 148 */ + {"CRC-8/ITU", models+ 12}, /* 149 */ + {"CRC-8/LTE", models+ 86}, /* 150 */ + {"CRC-8/MAXIM", models+ 43}, /* 151 */ + {"CRC-8/MAXIM-DOW", models+ 43}, /* 152 */ + {"CRC-8/NRSC-5", models+ 44}, /* 153 */ + {"CRC-8/OPENSAFETY", models+ 39}, /* 154 */ + {"CRC-8/ROHC", models+ 13}, /* 155 */ + {"CRC-8/SAE-J1850", models+ 33}, /* 156 */ + {"CRC-8/SMBUS", models+ 11}, /* 157 */ + {"CRC-8/TECH-3250", models+ 34}, /* 158 */ + {"CRC-8/WCDMA", models+ 87}, /* 159 */ + {"CRC-82/DARC", models+ 17}, /* 160 */ + {"CRC-A", models+ 24}, /* 161 */ + {"CRC-B", models+ 28}, /* 162 */ + {"CRC-CCITT", models+ 20}, /* 163 */ + {"CRC-IBM", models+ 68}, /* 164 */ + {"DOW-CRC", models+ 43}, /* 165 */ + {"JAMCRC", models+ 7}, /* 166 */ + {"KERMIT", models+ 20}, /* 167 */ + {"MODBUS", models+ 72}, /* 168 */ + {"PKZIP", models+ 8}, /* 169 */ + {"R-CRC-16", models+ 10}, /* 170 */ + {"X-25", models+ 28}, /* 171 */ + {"X-CRC-12", models+ 76}, /* 172 */ + {"X-CRC-16", models+ 9}, /* 173 */ + {"XFER", models+ 1}, /* 174 */ + {"XMODEM", models+ 18}, /* 175 */ + {"ZMODEM", models+ 18}, /* 176 */ + {NULL, NULL }, /* terminating entry */ }; -# define NALIASES 141 +# define NALIASES 177 # endif /* BMP_BIT */ #else /* PRESETS */ static const struct mpreset models[] = { - { 0UL, 0, 0, P_BE, 0, 0, 0, NULL }, /* terminating entry */ + { 0UL, 0, 0, P_BE | P_UNDFCL, 0, 0, 0, NULL }, /* terminating entry */ }; # define NPRESETS 0 diff --git a/client/reveng/reveng.h b/client/reveng/reveng.h index 08a7a6d1a..70f594072 100644 --- a/client/reveng/reveng.h +++ b/client/reveng/reveng.h @@ -1,5 +1,5 @@ /* reveng.h - * Greg Cook, 26/Jul/2018 + * Greg Cook, 21/Nov/2018 */ /* CRC RevEng: arbitrary-precision CRC calculator and algorithm finder @@ -93,7 +93,7 @@ /* Global definitions */ /* CRC RevEng version string */ -#define VERSION "1.5.3" +#define VERSION "1.6.0" /* bmpbit.c */ typedef BMP_T bmp_t; @@ -111,6 +111,19 @@ extern void setbmp(void); #define P_LTLBYT 64 #define P_DIRECT 128 +/* class flags */ +#define P_CLBIT0 256 +#define P_CLBIT1 512 +#define P_SOLID 1024 +#define P_CLMASK (P_SOLID | P_CLBIT1 | P_CLBIT0) + +#define P_UNDFCL 0 +#define P_UNCONF (P_CLBIT0) +#define P_THIRDP (P_CLBIT1) +#define P_ACADEM (P_CLBIT1 | P_CLBIT0) +#define P_CONFIR (P_SOLID | P_CLBIT0) +#define P_ATTEST (P_SOLID | P_CLBIT1) + /* default flags */ #define P_BE (P_RTJUST | P_MULXN) #define P_LE (P_REFIN | P_REFOUT | P_MULXN) @@ -187,7 +200,7 @@ extern void mrev(model_t *model); extern void mnovel(model_t *model); /* preset.c */ -#define M_OVERWR 256 +#define M_OVERWR 1 extern int mbynam(model_t *dest, const char *key); extern void mbynum(model_t *dest, int num); @@ -196,12 +209,12 @@ extern char *mnames(void); extern void mmatch(model_t *model, int flags); /* reveng.c */ -#define R_HAVEP 512 -#define R_HAVEI 1024 -#define R_HAVERI 2048 -#define R_HAVERO 4096 -#define R_HAVEX 8192 -#define R_HAVEQ 16384 +#define R_HAVEP 1 +#define R_HAVEI 2 +#define R_HAVERI 4 +#define R_HAVERO 8 +#define R_HAVEX 16 +#define R_HAVEQ 32 #define R_SPMASK 0x7FFFFFFUL diff --git a/client/scripting.c b/client/scripting.c index 762a9c470..3d3518ced 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -515,7 +515,7 @@ static int l_sha1(lua_State *L) { static int l_reveng_models(lua_State *L){ // This array needs to be adjusted if RevEng adds more crc-models. -#define NMODELS 103 +#define NMODELS 105 int count = 0; uint8_t in_width = luaL_checkunsigned(L, 1); From 0ddda8998e6e50dc617026250c44fa91738f3779 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 1 Jan 2019 10:15:27 +0100 Subject: [PATCH 0360/1938] chg: added info --- client/emv/emv_tags.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index 81cee89f3..74a37aba6 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -292,6 +292,9 @@ static const struct emv_tag emv_tags[] = { { 0x9f6b, "Track 2 Data" }, { 0x9f6c, "Card Transaction Qualifiers (CTQ)", EMV_TAG_BITMASK, &EMV_CTQ }, { 0x9f6e, "Form Factor Indicator" }, + + { 0x9f7c, "Customer Exclusive Data (CED)"}, + { 0xa5 , "File Control Information (FCI) Proprietary Template" }, { 0xbf0c, "File Control Information (FCI) Issuer Discretionary Data" }, { 0xdf20, "Issuer Proprietary Bitmap (IPB)" }, From 75d0b0b06f11cb66581fb0c92f79bcca04cff952 Mon Sep 17 00:00:00 2001 From: Chris Date: Tue, 1 Jan 2019 10:53:41 +0100 Subject: [PATCH 0361/1938] CHG: 'emv roca' - added selftest and textual layouts' DEL: removed unused old emv files --- client/cmdhfemv.c | 351 ----------------------------------- client/cmdhfemv.h | 45 ----- client/emv/cmdemv.c | 9 +- client/emv/emv_roca.c | 30 +-- client/emv/emv_roca.h | 2 +- client/emv/test/cryptotest.c | 7 +- 6 files changed, 22 insertions(+), 422 deletions(-) delete mode 100644 client/cmdhfemv.c delete mode 100644 client/cmdhfemv.h diff --git a/client/cmdhfemv.c b/client/cmdhfemv.c deleted file mode 100644 index ab9396a14..000000000 --- a/client/cmdhfemv.c +++ /dev/null @@ -1,351 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2014 Peter Fillmore -// 2017 iceman -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// High frequency EMV commands -//----------------------------------------------------------------------------- -#include "cmdhfemv.h" - -static int CmdHelp(const char *Cmd); - -int usage_hf_emv_test(void){ - PrintAndLogEx(NORMAL, "EMV test "); - PrintAndLogEx(NORMAL, "Usage: hf emv test [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv test"); - return 0; -} -int usage_hf_emv_readrecord(void){ - PrintAndLogEx(NORMAL, "Read a EMV record "); - PrintAndLogEx(NORMAL, "Usage: hf emv readrecord [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, " : number of records"); - PrintAndLogEx(NORMAL, " : number of SFI records"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv readrecord 1 1"); - return 0; -} -int usage_hf_emv_clone(void){ - PrintAndLogEx(NORMAL, "Usage: hf emv clone [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, " : number of records"); - PrintAndLogEx(NORMAL, " : number of SFI records"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv clone 10 10"); - return 0; -} -int usage_hf_emv_transaction(void){ - PrintAndLogEx(NORMAL, "Performs EMV reader transaction"); - PrintAndLogEx(NORMAL, "Usage: hf emv trans [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv trans"); - return 0; -} -int usage_hf_emv_getrnd(void){ - PrintAndLogEx(NORMAL, "retrieve the UN number from a terminal"); - PrintAndLogEx(NORMAL, "Usage: hf emv getrnd [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv getrnd"); - return 0; -} -int usage_hf_emv_eload(void){ - PrintAndLogEx(NORMAL, "set EMV tags in the device to use in a transaction"); - PrintAndLogEx(NORMAL, "Usage: hf emv eload [h] o "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, " o : filename w/o '.bin'"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv eload o myfile"); - return 0; -} -int usage_hf_emv_dump(void){ - PrintAndLogEx(NORMAL, "Gets EMV contactless tag values."); - PrintAndLogEx(NORMAL, "and saves binary dump into the file `filename.bin` or `cardUID.bin`"); - PrintAndLogEx(NORMAL, "Usage: hf emv dump [h] o "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, " o : filename w/o '.bin' to dump bytes"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv dump"); - PrintAndLogEx(NORMAL, " hf emv dump o myfile"); - return 0; -} -int usage_hf_emv_sim(void){ - PrintAndLogEx(NORMAL, "Simulates a EMV contactless card"); - PrintAndLogEx(NORMAL, "Usage: hf emv sim [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf emv sim"); - return 0; -} - -int CmdHfEmvTest(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if ( cmdp == 'h' || cmdp == 'H') return usage_hf_emv_test(); - - UsbCommand c = {CMD_EMV_TEST, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - PrintAndLogEx(WARNING, "Command execute time-out"); - return 1; - } - uint8_t isOK = resp.arg[0] & 0xff; - PrintAndLogEx(NORMAL, "isOk: %02x", isOK); - return 0; -} - -int CmdHfEmvReadRecord(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if ((strlen(Cmd)<3) || cmdp == 'h' || cmdp == 'H') return usage_hf_emv_readrecord(); - - uint8_t record = param_get8(Cmd, 0); - uint8_t sfi = param_getchar(Cmd, 1); - if(record > 32){ - PrintAndLogEx(WARNING, "Record must be less than 32"); - return 1; - } - PrintAndLogEx(NORMAL, "--record no:%02x SFI:%02x ", record, sfi); - - UsbCommand c = {CMD_EMV_READ_RECORD, {record, sfi, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - PrintAndLogEx(WARNING, "Command execute timeout"); - return 1; - } - uint8_t isOK = resp.arg[0] & 0xff; - PrintAndLogEx(NORMAL, "isOk:%02x", isOK); - return 0; -} - -int CmdHfEmvClone(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if ((strlen(Cmd)<3) || cmdp == 'h' || cmdp == 'H') return usage_hf_emv_clone(); - - uint8_t record = param_get8(Cmd, 0); - uint8_t sfi = param_get8(Cmd, 1); - if(record > 32){ - PrintAndLogEx(WARNING, "Record must be less than 32"); - return 1; - } - UsbCommand c = {CMD_EMV_CLONE, {sfi, record, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - PrintAndLogEx(WARNING, "Command execute timeout"); - return 1; - } - uint8_t isOK = resp.arg[0] & 0xff; - PrintAndLogEx(NORMAL, "isOk:%02x", isOK); - return 0; -} - -int CmdHfEmvTrans(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if ( cmdp == 'h' || cmdp == 'H') return usage_hf_emv_transaction(); - - UsbCommand c = {CMD_EMV_TRANSACTION, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 5000)) { - PrintAndLogEx(WARNING, "Command execute time-out"); - return 1; - } - uint8_t isOK = resp.arg[0] & 0xff; - PrintAndLogEx(NORMAL, "isOk: %02x", isOK); - print_hex_break(resp.d.asBytes, 512, 32); - return 0; -} -//retrieve the UN number from a terminal -int CmdHfEmvGetrng(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if ( cmdp == 'h' || cmdp == 'H') return usage_hf_emv_getrnd(); - UsbCommand c = {CMD_EMV_GET_RANDOM_NUM, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; -} -//Load a dumped EMV tag on to emulator memory -int CmdHfEmvELoad(const char *Cmd) { - FILE * f; - char filename[FILE_PATH_SIZE]; - char *fnameptr = filename; - int len; - bool errors = false; - uint8_t cmdp = 0; - - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { - case 'h': - case 'H': - return usage_hf_emv_eload(); - case 'o': - case 'O': - len = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); - if (!len) - errors = true; - if (len > FILE_PATH_SIZE-5) - len = FILE_PATH_SIZE-5; - sprintf(fnameptr + len,".bin"); - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors || cmdp == 0) return usage_hf_emv_eload(); - - // open file - f = fopen(filename,"r"); - if (!f) { - PrintAndLogEx(WARNING, "File %s not found or locked", filename); - return 1; - } - - char line[512]; - char *token; - uint16_t tag; - - UsbCommand c = {CMD_EMV_LOAD_VALUE, {0,0,0}}; - - // transfer to device - while (fgets(line, sizeof (line), f)) { - PrintAndLogEx(NORMAL, "LINE = %s\n", line); - - token = strtok(line, ":"); - tag = (uint16_t)strtol(token, NULL, 0); - token = strtok(NULL,""); - - c.arg[0] = tag; - memcpy(c.d.asBytes, token, strlen(token)); - - clearCommandBuffer(); - SendCommand(&c); - - PrintAndLogEx(NORMAL, "Loaded TAG = %04x\n", tag); - PrintAndLogEx(NORMAL, "Loaded VALUE = %s\n", token); - } - - fclose(f); - PrintAndLogEx(NORMAL, "loaded %s", filename); - //PrintAndLogEx(NORMAL, "\nLoaded %d bytes from file: %s to emulator memory", numofbytes, filename); - return 0; -} - -int CmdHfEmvDump(const char *Cmd){ - - bool errors = false; - uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { - case 'h': - case 'H': - return usage_hf_emv_dump(); - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors) return usage_hf_emv_dump(); - - UsbCommand c = {CMD_EMV_DUMP_CARD, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { - PrintAndLogEx(WARNING, "Command execute time-out"); - return 1; - } - return 0; -} - -int CmdHfEmvSim(const char *Cmd) { - - bool errors = false; - uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { - case 'h': - case 'H': - return usage_hf_emv_sim(); - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors) return usage_hf_emv_sim(); - - UsbCommand c = {CMD_EMV_SIM, {0,0,0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - PrintAndLogEx(WARNING, "Command execute time-out"); - return 1; - } - uint8_t isOK = resp.arg[0] & 0xff; - PrintAndLogEx(NORMAL, "isOk:%02x", isOK); - return 0; -} - -int CmdHfEmvList(const char *Cmd) { - return CmdTraceList("7816"); -} - -static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"readrecord", CmdHfEmvReadRecord, 0, "EMV Read Record"}, - {"transaction", CmdHfEmvTrans, 0, "Perform EMV Transaction"}, - {"getrng", CmdHfEmvGetrng, 0, "get random number from terminal"}, - {"eload", CmdHfEmvELoad, 0, "load EMV tag into device"}, - {"dump", CmdHfEmvDump, 0, "dump EMV tag values"}, - {"sim", CmdHfEmvSim, 0, "simulate EMV tag"}, - {"clone", CmdHfEmvClone, 0, "clone an EMV tag"}, - {"list", CmdHfEmvList, 0, "[Deprecated] List ISO7816 history"}, - {"test", CmdHfEmvTest, 0, "Test Function"}, - {NULL, NULL, 0, NULL} -}; - -int CmdHFEmv(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; -} - -int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; -} \ No newline at end of file diff --git a/client/cmdhfemv.h b/client/cmdhfemv.h deleted file mode 100644 index 0b68a455c..000000000 --- a/client/cmdhfemv.h +++ /dev/null @@ -1,45 +0,0 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2014 Peter Fillmore -// 2017 iceman -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// High frequency EMV commands -//----------------------------------------------------------------------------- - -#ifndef CMDHFEMV_H__ -#define CMDHFEMV_H__ - -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "cmdparser.h" -#include "cmdmain.h" -#include "util.h" -#include "cmdhf.h" // "hf list" - -int CmdHFEmv(const char *Cmd); - -int CmdHfEmvTest(const char *Cmd); -int CmdHfEmvReadRecord(const char *Cmd); -int CmdHfEmvClone(const char *Cmd); -int CmdHfEmvTrans(const char *Cmd); -int CmdHfEmvGetrng(const char *Cmd); -int CmdHfEmvELoad(const char *Cmd); -int CmdHfEmvDump(const char *Cmd); -int CmdHfEmvSim(const char *Cmd); -int CmdHfEmvList(const char *Cmd); - -int usage_hf_emv_test(void); -int usage_hf_emv_readrecord(void); -int usage_hf_emv_clone(void); -int usage_hf_emv_transaction(void); -int usage_hf_emv_getrnd(void); -int usage_hf_emv_eload(void); -int usage_hf_emv_dump(void); -int usage_hf_emv_sim(void); - -#endif diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index a443f6aad..396918d7e 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1456,7 +1456,6 @@ int CmdEMVScan(const char *cmd) { return 0; } - int CmdEMVList(const char *Cmd) { return CmdTraceList("7816"); } @@ -1476,10 +1475,13 @@ int CmdEMVRoca(const char *cmd) { CLIParserInit("emv roca", "Tries to extract public keys and run the ROCA test against them.\n", "Usage:\n" - "\temv roca -w -> select CONTACT card and run test\n\temv roca -> select CONTACTLESS card and run test\n"); + "\temv roca -w -> select --CONTACT-- card and run test\n" + "\temv roca -> select --CONTACTLESS-- card and run test\n" + ); void* argtable[] = { arg_param_begin, + arg_lit0("tT", "selftest", "self test"), arg_lit0("wW", "wired", "Send data via contact (iso7816) interface. Contactless interface set by default."), arg_param_end }; @@ -1487,6 +1489,9 @@ int CmdEMVRoca(const char *cmd) { EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(1)) + return roca_self_test(); + + if (arg_get_lit(2)) channel = ECC_CONTACT; // select card diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index a6738ae2f..6f90f11b5 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -138,11 +138,10 @@ cleanup: return ret; } -int roca_self_test( int verbose ) { +int roca_self_test(void) { int ret = 0; - if( verbose != 0 ) - printf( "\nROCA check vulnerability tests\n" ); + PrintAndLogEx(INFO, "ROCA check vulnerability tests" ); // positive uint8_t keyp[] = "\x94\x4e\x13\x20\x8a\x28\x0c\x37\xef\xc3\x1c\x31\x14\x48\x5e\x59"\ @@ -150,16 +149,13 @@ int roca_self_test( int verbose ) { "\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\ "\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7"; - if( verbose != 0 ) - printf( " ROCA positive test: " ); if (emv_rocacheck(keyp, 64, false)) { - if( verbose != 0 ) - printf( "passed\n" ); - } else { - ret = 1; - if( verbose != 0 ) - printf( "failed\n" ); + PrintAndLogEx(SUCCESS, "Weak modulus [ %s]", _GREEN_(PASS) ); + } + else { + ret++; + PrintAndLogEx(FAILED, "Weak modulus [ %s]", _RED_(FAIL) ); } // negative @@ -168,18 +164,12 @@ int roca_self_test( int verbose ) { "\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\ "\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7"; - if( verbose != 0 ) - printf( " ROCA negative test: " ); - if (emv_rocacheck(keyn, 64, false)) { - ret = 1; - if( verbose != 0 ) - printf( "failed\n" ); + ret++; + PrintAndLogEx(FAILED, "Strong modulus [ %s]", _RED_(FAIL) ); } else { - if( verbose != 0 ) - printf( "passed\n" ); + PrintAndLogEx(SUCCESS, "Strong modulus [ %s]", _GREEN_(PASS) ); } - return ret; } diff --git a/client/emv/emv_roca.h b/client/emv/emv_roca.h index 26d37d146..9e12e4256 100644 --- a/client/emv/emv_roca.h +++ b/client/emv/emv_roca.h @@ -32,7 +32,7 @@ #define ROCA_PRINTS_LENGTH 17 extern bool emv_rocacheck( const unsigned char *buf, size_t buflen, bool verbose ); -extern int roca_self_test( int verbose ); +extern int roca_self_test( void ); #endif diff --git a/client/emv/test/cryptotest.c b/client/emv/test/cryptotest.c index b0212a70b..4e8df1a25 100644 --- a/client/emv/test/cryptotest.c +++ b/client/emv/test/cryptotest.c @@ -91,14 +91,15 @@ int ExecuteCryptoTests(bool verbose) { res = exec_crypto_test(verbose); if (res) TestFail = true; - res = roca_self_test(verbose); + res = roca_self_test(); if (res) TestFail = true; PrintAndLog("\n--------------------------"); + if (TestFail) - PrintAndLog("Test(s) [ERROR]."); + PrintAndLogEx(FAILED, "\tTest(s) [ %s ]", _RED_(FAIL) ); else - PrintAndLog("Tests [OK]."); + PrintAndLogEx(SUCCESS, "\tTest(s) [ %s ]", _GREEN_(OK) ); return TestFail; } From 0fb0c35308366326b8897382da631a28f238fe23 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 1 Jan 2019 18:01:40 +0100 Subject: [PATCH 0362/1938] CHG: 'mem load' - the possibility to upload default_iclass_keys.dic, default_keys.dic, default_pwd.dic to predefined flashmemory sections. These will be used in pwd / key checking algorithms on device. CHG: 'script run read_pwd_mem.lua' - script now can print those uploaded dictionary files. How to upload pm3 --> mem load f default_iclass_keys i pm3 --> mem load f default_keys m pm3 --> mem load f default_pwd t How to validate / view PM3 -->scr run read_pwd_mem -o 237568 -k 8 pm3 -->scr run read_pwd_mem -o 241664 -k 6 pm3 -->scr run read_pwd_mem -o 245760 -k 4 --- armsrc/appmain.c | 12 ++- armsrc/lfops.c | 2 +- client/cmdflashmem.c | 90 +++++++++++++++++++---- client/cmdflashmem.h | 7 ++ client/cmdhficlass.c | 7 +- client/loclass/fileutils.c | 66 +++++++++++++++++ client/loclass/fileutils.h | 17 ++++- client/scripts/read_pwd_mem.lua | 126 ++++++++++++++++++++++---------- include/common.h | 14 ++-- 9 files changed, 276 insertions(+), 65 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index eed443599..bf4bddef6 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1285,10 +1285,20 @@ void UsbPacketReceived(uint8_t *packet, int len) { if (!FlashInit()) { break; } - + Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); + + if ( startidx == DEFAULT_T55XX_KEYS_OFFSET ) + Flash_Erase4k(3, 0xC); + else if (startidx == DEFAULT_MF_KEYS_OFFSET ) + Flash_Erase4k(3, 0xB); + else if (startidx == DEFAULT_ICLASS_KEYS_OFFSET) + Flash_Erase4k(3, 0xA); + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); + // inside 256b page? if ( (tmp & 0xFF) != 0) { diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 0dac64bd1..e690714df 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -103,7 +103,7 @@ void setT55xxConfig(uint8_t arg0, t55xx_config *c) { Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); - Flash_Erase4k(3, 0xD); + Flash_Erase4k(3, 0xD); res = Flash_Write(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN); if ( res == T55XX_CONFIG_LEN && MF_DBGLEVEL > 1) { diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index 2ff68bd3d..6361d48e3 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -50,13 +50,19 @@ int usage_flashmem_read(void){ } int usage_flashmem_load(void){ PrintAndLogEx(NORMAL, "Loads binary file into flash memory on device"); - PrintAndLogEx(NORMAL, "Usage: mem load o f "); + PrintAndLogEx(NORMAL, "Usage: mem load o f m t i"); PrintAndLogEx(NORMAL, " o : offset in memory"); PrintAndLogEx(NORMAL, " f : file name"); + PrintAndLogEx(NORMAL, " m : upload 6 bytes keys (mifare key dictionary)"); + PrintAndLogEx(NORMAL, " i : upload 8 bytes keys (iClass key dictionary)"); + PrintAndLogEx(NORMAL, " t : upload 4 bytes keys (pwd dictionary)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " mem load f myfile"); // upload file myfile at default offset 0 PrintAndLogEx(NORMAL, " mem load f myfile o 1024"); // upload file myfile at offset 1024 + PrintAndLogEx(NORMAL, " mem load f default_keys m"); + PrintAndLogEx(NORMAL, " mem load f default_pwd t"); + PrintAndLogEx(NORMAL, " mem load f default_iclass_keys i"); return 0; } int usage_flashmem_save(void){ @@ -154,7 +160,8 @@ int CmdFlashMemLoad(const char *Cmd){ uint32_t start_index = 0; char filename[FILE_PATH_SIZE] = {0}; bool errors = false; - uint8_t cmdp = 0; + uint8_t cmdp = 0; + Dictionary_t d = DICTIONARY_NONE; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { @@ -171,7 +178,19 @@ int CmdFlashMemLoad(const char *Cmd){ case 'o': start_index = param_get32ex(Cmd, cmdp+1, 0, 10); cmdp += 2; - break; + break; + case 'm': + d = DICTIONARY_MIFARE; + cmdp++; + break; + case 't': + d = DICTIONARY_T55XX; + cmdp++; + break; + case 'i': + d = DICTIONARY_ICLASS; + cmdp++; + break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -181,20 +200,61 @@ int CmdFlashMemLoad(const char *Cmd){ //Validations if (errors || cmdp == 0 ) return usage_flashmem_load(); - - uint8_t *data = calloc(FLASH_MEM_MAX_SIZE, sizeof(uint8_t)); + size_t datalen = 0; - int res = loadFile(filename, "bin", data, &datalen); - //int res = loadFileEML( filename, "eml", data, &datalen); - if ( res ) { - free(data); - return 1; - } + uint16_t keycount = 0; + int res = 0; + uint8_t *data = calloc(FLASH_MEM_MAX_SIZE, sizeof(uint8_t)); - if (datalen > FLASH_MEM_MAX_SIZE) { - PrintAndLogDevice(WARNING, "error, filesize is larger than available memory"); - free(data); - return 1; + switch (d) { + case DICTIONARY_MIFARE: + start_index = DEFAULT_MF_KEYS_OFFSET; + res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 6, &keycount ); + if ( res || !keycount) { + free(data); + return 1; + } + data[0] = (keycount >> 0) & 0xFF; + data[1] = (keycount >> 8) & 0xFF; + datalen += 2; + break; + case DICTIONARY_T55XX: + start_index = DEFAULT_T55XX_KEYS_OFFSET; + res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 4, &keycount ); + if ( res || !keycount) { + free(data); + return 1; + } + data[0] = (keycount >> 0) & 0xFF; + data[1] = (keycount >> 8) & 0xFF; + datalen += 2; + break; + case DICTIONARY_ICLASS: + start_index = DEFAULT_ICLASS_KEYS_OFFSET; + res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 8, &keycount ); + if ( res || !keycount) { + free(data); + return 1; + } + data[0] = (keycount >> 0) & 0xFF; + data[1] = (keycount >> 8) & 0xFF; + datalen += 2; + break; + default: + + res = loadFile(filename, "bin", data, &datalen); + //int res = loadFileEML( filename, "eml", data, &datalen); + if ( res ) { + free(data); + return 1; + } + + if (datalen > FLASH_MEM_MAX_SIZE) { + PrintAndLogDevice(WARNING, "error, filesize is larger than available memory"); + free(data); + return 1; + } + break; } data = realloc(data, datalen); diff --git a/client/cmdflashmem.h b/client/cmdflashmem.h index 843c17d6f..9f71a4ce0 100644 --- a/client/cmdflashmem.h +++ b/client/cmdflashmem.h @@ -24,6 +24,13 @@ #include "loclass/fileutils.h" //saveFile #include "comms.h" //getfromdevice +typedef enum { + DICTIONARY_NONE = 0, + DICTIONARY_MIFARE, + DICTIONARY_T55XX, + DICTIONARY_ICLASS +} Dictionary_t; + extern int CmdFlashMem(const char *Cmd); extern int CmdFlashMemRead(const char* cmd); diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 6cc2aa191..0e62afaf6 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -2316,7 +2316,8 @@ int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) { while (fgetc(f) != '\n' && !feof(f)) {}; //The line start with # is comment, skip - if( buf[0]=='#' ) continue; + if( buf[0]=='#' ) + continue; // doesn't this only test first char only? if (!isxdigit(buf[0])){ @@ -2329,7 +2330,7 @@ int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) { p = realloc(*keys, 8 * (keyitems += 64)); if (!p) { - PrintAndLogEx(NORMAL, _RED_([!])" cannot allocate memory for default keys"); + PrintAndLogEx(ERR, "cannot allocate memory for default keys"); fclose(f); return 2; } @@ -2341,7 +2342,7 @@ int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) { memset(buf, 0, sizeof(buf)); } fclose(f); - PrintAndLogEx(NORMAL, _BLUE_([+]) "Loaded " _GREEN_(%2d) " keys from %s", *keycnt, filename); + PrintAndLogEx(SUCCESS, "Loaded " _GREEN_(%2d) " keys from %s", *keycnt, filename); return 0; } diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index b099d6a35..5bac3d2cd 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -453,6 +453,72 @@ out: return retval; } +int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data, size_t* datalen, uint8_t keylen, uint16_t* keycnt ) { + + if ( preferredName == NULL ) return 1; + if ( suffix == NULL ) return 1; + + // t5577 == 4bytes + // mifare == 6 bytes + // iclass == 8 bytes + // default to 6 bytes. + if (keylen != 4 && keylen != 6 && keylen != 8) { + keylen = 6; + } + + // double up since its chars + keylen <<= 1; + + char line[255]; + + size_t counter = 0; + int retval = 0; + int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10); + char * fileName = calloc(size, sizeof(char)); + sprintf(fileName,"%s.%s", preferredName, suffix); + + FILE *f = fopen(fileName, "r"); + if ( !f ) { + PrintAndLogDevice(FAILED, "file: %s: not found or locked.", fileName); + retval = 1; + goto out; + } + + // read file + while ( fgets(line, sizeof(line), f) ) { + + // add null terminator + line[keylen] = 0; + + // smaller keys than expected is skipped + if (strlen(line) < keylen) + continue; + + + // The line start with # is comment, skip + if( line[0] == '#' ) + continue; + + if (!isxdigit(line[0])){ + PrintAndLogEx(FAILED, "file content error. '%s' must include " _BLUE_(%2d) "HEX symbols", line, keylen); + continue; + } + + uint64_t key = strtoull(line, NULL, 16); + + num_to_bytes(key, keylen >> 1, data + counter); + (*keycnt)++; + memset(line, 0, sizeof(line)); + counter += (keylen >> 1); + } + fclose(f); + PrintAndLogDevice(SUCCESS, "loaded " _GREEN_(%2d) "keys from dictionary file %s", *keycnt, fileName); + *datalen = counter; +out: + free(fileName); + return retval; +} + #else //if we're on ARM #endif diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index b73f5fc30..3fc781d2e 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -124,7 +124,7 @@ extern int loadFile(const char *preferredName, const char *suffix, void* data, s */ extern int loadFileEML(const char *preferredName, const char *suffix, void* data, size_t* datalen); -/** STUB +/** * @brief Utility function to load data from a JSON textfile. This method takes a preferred name. * E.g. dumpdata-15.json * @@ -137,6 +137,21 @@ extern int loadFileEML(const char *preferredName, const char *suffix, void* data */ extern int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t maxdatalen, size_t* datalen); + +/** + * @brief Utility function to load data from a DICTIONARY textfile. This method takes a preferred name. + * E.g. default_keys.dic + * + * @param preferredName + * @param suffix the file suffix. Leave out the ".". + * @param data The data array to store the loaded bytes from file + * @param maxdatalen maximum size of data array in bytes + * @param datalen the number of bytes loaded from file + * @param keylen the number of bytes a key per row is + * @return 0 for ok, 1 for failz +*/ +extern int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data, size_t* datalen, uint8_t keylen, uint16_t* keycnt ); + #define PrintAndLogDevice(level, format, args...) PrintAndLogEx(level, format , ## args) #else diff --git a/client/scripts/read_pwd_mem.lua b/client/scripts/read_pwd_mem.lua index fbe4d0459..772927c0c 100644 --- a/client/scripts/read_pwd_mem.lua +++ b/client/scripts/read_pwd_mem.lua @@ -1,23 +1,29 @@ local getopt = require('getopt') local bin = require('bin') +copyright = 'Copyright (c) 2018 Bogito. All rights reserved.' author = "Bogito" -version = 'v1.0.0' -desc =[[ +version = 'v1.0.1' +desc = +[[ This script will read the flash memory of RDV4 and print the stored passwords. It was meant to be used as a help tool after using the BogRun standalone mode. + +(Iceman) script adapted to read and print keys in the default dictionary flashmemory sections. ]] -usage = [[ +usage = +[[ Usage: - script run read_pwd_mem -h -o -l + script run read_pwd_mem -h -o -l -k Arguments: - -h : this help - -o : Memory offset. Default is 0. - -l : Length in bytes. Default is 256. + -h : this help + -o : memory offset, default is 0 + -l : length in bytes, default is 256 + -k : key length in bytes <4|6|8> , default is 4 ]] -example =[[ -Examples: +example = +[[ -- This will scan the first 256 bytes of flash memory for stored passwords script run read_pwd_mem @@ -26,61 +32,103 @@ Examples: -- This will scan 32 bytes of flash memory at offset 64 for stored passwords script run read_pwd_mem -o 64 -l 32 + + -- This will print found + script run read_pwd_mem -o 241664 -k 6 ]] - +--- +-- This is only meant to be used when errors occur +local function oops(err) + print("ERROR: ", err) + return nil, err +end +--- -- Usage help local function help() + print(copyright) + print(version) print(desc) print(usage) + print('Example usage:') print(example) end - +--- +-- The main entry point local function main(args) - local data, err, quadlet, pwdcnt + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print() + + local data, err, quadlet + local cnt = 0 local offset = 0 local length = 256 + local keylength = 4 + local usedkey = false - -- Read the parameters - for o, a in getopt.getopt(args, 'ho:l:') do + for o, a in getopt.getopt(args, 'ho:l:k:') do + + -- help if o == "h" then return help() end + + -- offset if o == "o" then offset = tonumber(a) end + + -- num of bytes to read if o == "l" then length = tonumber(a) end + + -- keylength + if o == "k" then keylength = tonumber(a); usedkey = true end end if length < 0 or length > 256 then - return print('Error: Length is not valid. Must be less than 256') + return oops('Error: Length is not valid. Must be less than 256') end - if ((offset < 0) or (offset % 4 ~= 0)) then - return print('Error: Offset is not valid. Mod-4 values are only allowed.') + if (offset < 0) or (offset % 4 ~= 0) then + return oops('Error: Offset is not valid. Mod-4 values are only allowed.') end - print('Offset: ' .. offset) - print('Length: ' .. length) - print() + print('Memory offset', offset) + print('Length ', length) + print('Key length ', keylength) + print( string.rep('--',20) ) - data, err = core.GetFromFlashMem(offset, length) + if usedkey then length = 4096 end + + data, err = core.GetFromFlashMem(offset, length) + if err then return oops(err) end - if err then - print(err) - return + if usedkey then + + _, keys, s = bin.unpack('SH'..length-2, data) + if keys == 0xFFFF then return "No keys found in section" end + + local kl = keylength * 2 + for i = 1, keys do + + key = string.sub(s, (i - 1) * kl + 1, i * kl ) + print(string.format("[%02d] %s",i, key)) + end + print( string.rep('--',20) ) + print( ('[+] found %d passwords'):format(keys)) + else + + _, s = bin.unpack('H'..length, data) + + local cnt = 0, i + for i = 1, (length/keylength) do + + key = string.sub(s, (i-1)*8+1, i*8) + if key == "FFFFFFFF" then break end + print(string.format("[%02d] %s",i, key)) + cnt = cnt + 1 + end + print( string.rep('--',20) ) + print( ('[+] found %d passwords'):format(cnt)) end - - local count, s = bin.unpack('H'..length, data) - - pwdcnt = 0 - for i = 1,(length/4),1 - do - quadlet = string.sub(s, (i-1)*8+1, i*8) - if quadlet == "FFFFFFFF" then break end - print(string.format("[%02d]",i) .. ' ' .. quadlet) - pwdcnt = pwdcnt + 1 - - end - print() - print('Found passwords: ' .. pwdcnt) - + print( string.rep('--',20) ) end main(args) diff --git a/include/common.h b/include/common.h index 90394448c..d3da792aa 100644 --- a/include/common.h +++ b/include/common.h @@ -90,13 +90,17 @@ extern uint32_t FLASHMEM_SPIBAUDRATE; #ifndef T55XX_CONFIG_OFFSET # define T55XX_CONFIG_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x2000) #endif - - #ifndef DEFAULT_MF_KEYS_OFFSET - # define DEFAULT_MF_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x3000) + + #ifndef DEFAULT_T55XX_KEYS_OFFSET + # define DEFAULT_T55XX_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x3000) #endif - #ifndef DEFAULT_LF_KEYS_OFFSET - # define DEFAULT_LF_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x4000) + #ifndef DEFAULT_MF_KEYS_OFFSET + # define DEFAULT_MF_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x4000) + #endif + + #ifndef DEFAULT_ICLASS_KEYS_OFFSET + # define DEFAULT_ICLASS_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x5000) #endif #endif From 6e281a08ed93e664f196aea49f1d922ee2fb5b83 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 2 Jan 2019 11:52:13 +0100 Subject: [PATCH 0363/1938] CHG: 'hf mf fchk' - speed improvments by tweaking implementation. CHG: 'hf mf fchk' - can use dictionary from flashmem if one is uploaded. (faster) --- armsrc/mifarecmd.c | 128 +++++++++++++++++++++++++++++++++----------- client/cmdhfmf.c | 96 +++++++++++++++++++-------------- client/mifarehost.c | 4 +- client/mifarehost.h | 2 +- 4 files changed, 156 insertions(+), 74 deletions(-) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 7d39b3f29..3e1967b4e 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -17,7 +17,7 @@ #include #ifndef HARDNESTED_AUTHENTICATION_TIMEOUT -# define HARDNESTED_AUTHENTICATION_TIMEOUT 848 //848 // card times out 1ms after wrong authentication (according to NXP documentation) +# define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) #endif #ifndef HARDNESTED_PRE_AUTHENTICATION_LEADTIME # define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication @@ -1122,7 +1122,6 @@ uint8_t chkKey_readb(struct chk_t *c, uint8_t *keyb) { } void chkKey_scanA(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { - uint8_t status; for (uint8_t s = 0; s < *sectorcnt; s++) { // skip already found A keys @@ -1130,8 +1129,7 @@ void chkKey_scanA(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, ui continue; c->block = FirstBlockOfSector( s ); - status = chkKey( c ); - if ( status == 0 ) { + if ( chkKey( c ) == 0 ) { num_to_bytes(c->key, 6, k_sector[s].keyA); found[(s*2)] = 1; ++*foundkeys; @@ -1142,7 +1140,6 @@ void chkKey_scanA(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, ui } void chkKey_scanB(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { - uint8_t status; for (uint8_t s = 0; s < *sectorcnt; s++) { // skip already found B keys @@ -1150,8 +1147,7 @@ void chkKey_scanB(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, ui continue; c->block = FirstBlockOfSector( s ); - status = chkKey( c ); - if ( status == 0 ) { + if ( chkKey( c ) == 0 ) { num_to_bytes(c->key, 6, k_sector[s].keyB); found[(s*2)+1] = 1; ++*foundkeys; @@ -1167,7 +1163,12 @@ void chkKey_loopBonly(struct chk_t *c, struct sector_t *k_sector, uint8_t *found // read Block B, if A is found. for (uint8_t s = 0; s < *sectorcnt; ++s) { + + if ( found[(s*2)] && found[(s*2)+1] ) + continue; + c->block = (FirstBlockOfSector( s ) + NumBlocksPerSector( s ) - 1); + // A but not B if ( found[(s*2)] && !found[(s*2)+1] ){ c->key = bytes_to_num(k_sector[s].keyA, 6); @@ -1187,6 +1188,9 @@ void chkKey_loopBonly(struct chk_t *c, struct sector_t *k_sector, uint8_t *found } } } + + + // get Chunks of keys, to test authentication against card. // arg0 = antal sectorer // arg0 = first time @@ -1200,7 +1204,8 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da uint8_t firstchunk = (arg0 >> 8) & 0xF; uint8_t lastchunk = (arg0 >> 12) & 0xF; uint8_t strategy = arg1 & 0xFF; - uint8_t keyCount = arg2 & 0xFF; + uint8_t use_flashmem = (arg1 >> 8) & 0xFF; + uint16_t keyCount = arg2 & 0xFF; uint8_t status = 0; struct Crypto1State mpcs = {0, 0}; @@ -1217,33 +1222,57 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da static uint8_t found[80]; static uint8_t *uid; - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); +#ifdef WITH_FLASH + if ( use_flashmem ) { + BigBuf_free(); + uint16_t isok = 0; + uint8_t size[2] = {0x00, 0x00}; + isok = Flash_ReadData(DEFAULT_MF_KEYS_OFFSET, size, 2); + if ( isok != 2 ) + goto OUT; + + keyCount = size[1] << 8 | size[0]; + + if ( keyCount == 0 && keyCount == 0xFFFF) + goto OUT; + + datain = BigBuf_malloc( keyCount * 6); + if (datain == NULL ) + goto OUT; + + isok = Flash_ReadData(DEFAULT_MF_KEYS_OFFSET+2, datain, keyCount * 6); + if ( isok != keyCount * 6 ) + goto OUT; + + } +#endif if (uid == NULL || firstchunk) { uid = BigBuf_malloc(10); - if (uid == NULL ) { - if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys: uid malloc failed"); + if (uid == NULL ) goto OUT; - } } + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); LEDsoff(); LED_A_ON(); if ( firstchunk ) { - + clear_trace(); set_tracing(false); memset(k_sector, 0x00, 480+10); memset(found, 0x00, sizeof(found)); foundkeys = 0; - + iso14a_card_select_t card_info; if ( !iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (ALL)"); + if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys_fast: Can't select card (ALL)"); goto OUT; } + switch (card_info.uidlen) { case 4 : cascade_levels = 1; break; case 7 : cascade_levels = 2; break; @@ -1262,19 +1291,23 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da chk_data.block = 0; // keychunk loop - depth first one sector. - if ( strategy == 1 ) { + if ( strategy == 1 || use_flashmem) { uint8_t newfound = foundkeys; + uint16_t lastpos = 0; + uint16_t s_point = 0; // Sector main loop // keep track of how many sectors on card. for (uint8_t s = 0; s < sectorcnt; ++s) { - if ( found[(s*2)] && found[(s*2)+1] ) + if ( found[(s*2)] && found[(s*2)+1] ) continue; - for (uint8_t i = 0; i < keyCount; ++i) { - + for (uint16_t i = s_point; i < keyCount; ++i) { + + //if ( i % 100 == 0) Dbprintf("ChkKeys_fast: sector %d | checking %d | %d found | s_point %d", s, i, foundkeys, s_point); + // Allow button press / usb cmd to interrupt device if (BUTTON_PRESS() && !usb_poll_validate_length()) { goto OUT; @@ -1292,8 +1325,6 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da // new key chk_data.key = bytes_to_num(datain + i * 6, 6); - // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector - // skip already found A keys if( !found[(s*2)] ) { chk_data.keyType = 0; @@ -1303,12 +1334,26 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da found[(s*2)] = 1; ++foundkeys; - chkKey_scanA(&chk_data, k_sector, found, §orcnt, &foundkeys); + chkKey_scanA(&chk_data, k_sector, found, §orcnt, &foundkeys); // read Block B, if A is found. chkKey_loopBonly( &chk_data, k_sector, found, §orcnt, &foundkeys); + chk_data.keyType = 1; + chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); + + chk_data.keyType = 0; chk_data.block = FirstBlockOfSector( s ); + + if ( use_flashmem ) { + if ( lastpos != i && lastpos != 0) { + if ( i - lastpos < 0xF) { + s_point = i & 0xFFF0; + } + } else { + lastpos = i; + } + } } } @@ -1322,25 +1367,46 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da ++foundkeys; chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); + + if ( use_flashmem ) { + if ( lastpos != i && lastpos != 0) { + + if ( i - lastpos < 0xF) + s_point = i & 0xFFF0; + } else { + lastpos = i; + } + } } } - + + if ( found[(s*2)] && found[(s*2)+1] ) + break; + } // end keys test loop - depth first // assume1. if no keys found in first sector, get next keychunk from client - if ( newfound-foundkeys == 0 ) + if ( !use_flashmem && (newfound-foundkeys == 0) ) goto OUT; } // end loop - sector } // end strategy 1 + + if ( foundkeys == allkeys ) + goto OUT; - if ( strategy == 2 ) { + if ( strategy == 2 || use_flashmem ) { + // Keychunk loop - for (uint8_t i = 0; i < keyCount; i++) { - + for (uint16_t i = 0; i < keyCount; i++) { + // Allow button press / usb cmd to interrupt device if (BUTTON_PRESS() && !usb_poll_validate_length()) break; + // found all keys? + if ( foundkeys == allkeys ) + goto OUT; + WDT_HIT(); // new key @@ -1349,7 +1415,9 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da // Sector main loop // keep track of how many sectors on card. for (uint8_t s = 0; s < sectorcnt; ++s) { - + + if ( found[(s*2)] && found[(s*2)+1] ) continue; + // found all keys? if ( foundkeys == allkeys ) goto OUT; @@ -1387,8 +1455,6 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); } } - - } // end loop sectors } // end loop keys } // end loop strategy 2 @@ -1416,7 +1482,7 @@ OUT: set_tracing(false); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - BigBuf_free(); BigBuf_Clear_ext(false); + BigBuf_free(); BigBuf_Clear_ext(false); } else { // partial/none keys found cmd_send(CMD_ACK, foundkeys, 0, 0, 0, 0); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 1bfbf10eb..33e1c6f66 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -170,7 +170,7 @@ int usage_hf14_chk(void){ } int usage_hf14_chk_fast(void){ PrintAndLogEx(NORMAL, "This is a improved checkkeys method speedwise. It checks Mifare Classic tags sector keys against a dictionary file with keys"); - PrintAndLogEx(NORMAL, "Usage: hf mf fchk [h] [t|d] [] []"); + PrintAndLogEx(NORMAL, "Usage: hf mf fchk [h] [t|d|f] [] []"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " all sectors based on card memory, other values than below defaults to 1k"); @@ -179,12 +179,16 @@ int usage_hf14_chk_fast(void){ PrintAndLogEx(NORMAL, " 2 - 2K"); PrintAndLogEx(NORMAL, " 4 - 4K"); PrintAndLogEx(NORMAL, " d write keys to binary file"); - PrintAndLogEx(NORMAL, " t write keys to emulator memory\n"); + PrintAndLogEx(NORMAL, " t write keys to emulator memory"); + PrintAndLogEx(NORMAL, " m use dictionary from flashmemory\n"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf fchk 1 1234567890ab keys.dic -- target 1K using key 1234567890ab, using dictionary file"); PrintAndLogEx(NORMAL, " hf mf fchk 1 t -- target 1K, write to emulator memory"); PrintAndLogEx(NORMAL, " hf mf fchk 1 d -- target 1K, write to file"); +#ifdef WITH_FLASH + PrintAndLogEx(NORMAL, " hf mf fchk 1 m -- target 1K, use dictionary from flashmemory"); +#endif return 0; } int usage_hf14_keybrute(void){ @@ -1136,7 +1140,7 @@ int CmdHF14AMfNested(const char *Cmd) { } PrintAndLogEx(SUCCESS, "Testing known keys. Sector count=%d", SectorsCnt); - res = mfCheckKeys_fast( SectorsCnt, true, true, 1, MIFARE_DEFAULTKEYS_SIZE + 1, keyBlock, e_sector); + res = mfCheckKeys_fast( SectorsCnt, true, true, 1, MIFARE_DEFAULTKEYS_SIZE + 1, keyBlock, e_sector, false); uint64_t t2 = msclock() - t1; PrintAndLogEx(SUCCESS, "Time to check %d known keys: %.0f seconds\n", MIFARE_DEFAULTKEYS_SIZE, (float)t2/1000.0 ); @@ -1167,7 +1171,7 @@ int CmdHF14AMfNested(const char *Cmd) { e_sector[sectorNo].foundKey[trgKeyType] = 1; e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6); - res = mfCheckKeys_fast( SectorsCnt, true, true, 2, 1, keyBlock, e_sector); + res = mfCheckKeys_fast( SectorsCnt, true, true, 2, 1, keyBlock, e_sector, false); continue; default : PrintAndLogEx(WARNING, "unknown Error.\n"); @@ -1467,8 +1471,8 @@ void shuffle( uint8_t *array, uint16_t len) { int CmdHF14AMfChk_fast(const char *Cmd) { char ctmp = 0x00; - ctmp = param_getchar(Cmd, 0); - if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_hf14_chk_fast(); + ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_chk_fast(); FILE * f; char filename[FILE_PATH_SIZE]={0}; @@ -1481,6 +1485,7 @@ int CmdHF14AMfChk_fast(const char *Cmd) { int clen = 0; int transferToEml = 0, createDumpFile = 0; uint32_t keyitems = MIFARE_DEFAULTKEYS_SIZE; + bool use_flashmemory = false; sector_t *e_sector = NULL; @@ -1501,7 +1506,7 @@ int CmdHF14AMfChk_fast(const char *Cmd) { for (i = 1; param_getchar(Cmd, i); i++) { - ctmp = param_getchar(Cmd, i); + ctmp = tolower(param_getchar(Cmd, i)); clen = param_getlength(Cmd, i); if (clen == 12) { @@ -1523,8 +1528,11 @@ int CmdHF14AMfChk_fast(const char *Cmd) { PrintAndLogEx(NORMAL, "[%2d] key %s", keycnt, sprint_hex( (keyBlock + 6*keycnt), 6 ) ); keycnt++; } else if ( clen == 1) { - if (ctmp == 't' || ctmp == 'T') { transferToEml = 1; continue; } - if (ctmp == 'd' || ctmp == 'D') { createDumpFile = 1; continue; } + if (ctmp == 't' ) { transferToEml = 1; continue; } + if (ctmp == 'd' ) { createDumpFile = 1; continue; } +#ifdef WITH_FLASH + if (ctmp == 'm' ) { use_flashmemory = true; continue; } +#endif } else { // May be a dic file if ( param_getstr(Cmd, i, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) { @@ -1574,7 +1582,7 @@ int CmdHF14AMfChk_fast(const char *Cmd) { } } - if (keycnt == 0) { + if (keycnt == 0 && !use_flashmemory) { PrintAndLogEx(SUCCESS, "No key specified, trying default keys"); for (;keycnt < MIFARE_DEFAULTKEYS_SIZE; keycnt++) PrintAndLogEx(NORMAL, "[%2d] %02x%02x%02x%02x%02x%02x", keycnt, @@ -1594,37 +1602,45 @@ int CmdHF14AMfChk_fast(const char *Cmd) { // time uint64_t t1 = msclock(); - - // strategys. 1= deep first on sector 0 AB, 2= width first on all sectors - for (uint8_t strategy = 1; strategy < 3; strategy++) { - PrintAndLogEx(SUCCESS, "Running strategy %u", strategy); - // main keychunk loop - for (uint32_t i = 0; i < keycnt; i += chunksize) { - - if (ukbhit()) { - int gc = getchar(); (void)gc; - PrintAndLogEx(NORMAL, "\naborted via keyboard!\n"); - goto out; - } - - uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i; - - // last chunk? - if ( size == keycnt - i) - lastChunk = true; - - int res = mfCheckKeys_fast( sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector); - if ( firstChunk ) - firstChunk = false; - - // all keys, aborted - if ( res == 0 || res == 2 ) - goto out; - } // end chunks of keys - firstChunk = true; - lastChunk = false; - } // end strategy + if ( use_flashmemory ) { + mfCheckKeys_fast( sectorsCnt, true, true, 1, 0, keyBlock, e_sector, use_flashmemory); + } else { + + // strategys. 1= deep first on sector 0 AB, 2= width first on all sectors + for (uint8_t strategy = 1; strategy < 3; strategy++) { + PrintAndLogEx(SUCCESS, "Running strategy %u", strategy); + + + + // main keychunk loop + for (uint32_t i = 0; i < keycnt; i += chunksize) { + + if (ukbhit()) { + int gc = getchar(); (void)gc; + PrintAndLogEx(NORMAL, "\naborted via keyboard!\n"); + goto out; + } + + uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i; + + // last chunk? + if ( size == keycnt - i) + lastChunk = true; + + int res = mfCheckKeys_fast( sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector, false); + + if ( firstChunk ) + firstChunk = false; + + // all keys, aborted + if ( res == 0 || res == 2 ) + goto out; + } // end chunks of keys + firstChunk = true; + lastChunk = false; + } // end strategy + } out: t1 = msclock() - t1; PrintAndLogEx(SUCCESS, "Time in checkkeys (fast): %.1fs\n", (float)(t1/1000.0)); diff --git a/client/mifarehost.c b/client/mifarehost.c index fe2495938..2859fc207 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -138,13 +138,13 @@ int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keyc // 1 == // 2 == Time-out, aborting int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, uint8_t strategy, - uint32_t size, uint8_t *keyBlock, sector_t *e_sector) { + uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory) { uint64_t t2 = msclock(); uint32_t timeout = 0; // send keychunk - UsbCommand c = {CMD_MIFARE_CHKKEYS_FAST, { (sectorsCnt | (firstChunk << 8) | (lastChunk << 12) ), strategy, size}}; + UsbCommand c = {CMD_MIFARE_CHKKEYS_FAST, { (sectorsCnt | (firstChunk << 8) | (lastChunk << 12) ), ((use_flashmemory << 8) | strategy), size}}; memcpy(c.d.asBytes, keyBlock, 6 * size); clearCommandBuffer(); SendCommand(&c); diff --git a/client/mifarehost.h b/client/mifarehost.h index 65500ded8..8f0f3f3bf 100644 --- a/client/mifarehost.h +++ b/client/mifarehost.h @@ -73,7 +73,7 @@ extern int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key); extern int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys, bool calibrate); extern int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key); extern int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, - uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector); + uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory); extern int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey); From e3f4ef498fcf30d904f46e984cf4f2c077dd6cfe Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 2 Jan 2019 12:11:49 +0100 Subject: [PATCH 0364/1938] CHG: 'hf mf fchk' - textual --- client/cmdhfmf.c | 5 ++--- client/mifarehost.c | 2 +- client/scripts/calypso.lua | 4 ++-- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 33e1c6f66..d92b2a1d4 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1604,15 +1604,14 @@ int CmdHF14AMfChk_fast(const char *Cmd) { uint64_t t1 = msclock(); if ( use_flashmemory ) { - mfCheckKeys_fast( sectorsCnt, true, true, 1, 0, keyBlock, e_sector, use_flashmemory); + PrintAndLogEx(SUCCESS, "Using dictionary in flash memory"); + mfCheckKeys_fast( sectorsCnt, true, true, 1, 0, keyBlock, e_sector, use_flashmemory); } else { // strategys. 1= deep first on sector 0 AB, 2= width first on all sectors for (uint8_t strategy = 1; strategy < 3; strategy++) { PrintAndLogEx(SUCCESS, "Running strategy %u", strategy); - - // main keychunk loop for (uint32_t i = 0; i < keycnt; i += chunksize) { diff --git a/client/mifarehost.c b/client/mifarehost.c index 2859fc207..0f37f8a8b 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -166,7 +166,7 @@ int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, // time to convert the returned data. uint8_t curr_keys = resp.arg[0]; - PrintAndLogEx(NORMAL, "\n[-] Chunk: %.1fs | found %u/%u keys (%u)", (float)(t2/1000.0), curr_keys, (sectorsCnt<<1), size); + PrintAndLogEx(SUCCESS, "\nChunk: %.1fs | found %u/%u keys (%u)", (float)(t2/1000.0), curr_keys, (sectorsCnt<<1), size); // all keys? if ( curr_keys == sectorsCnt*2 || lastChunk ) { diff --git a/client/scripts/calypso.lua b/client/scripts/calypso.lua index ad74c8183..ce90a25fd 100644 --- a/client/scripts/calypso.lua +++ b/client/scripts/calypso.lua @@ -68,9 +68,9 @@ end --- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) + print("ERROR: ", err) calypso_switch_off_field() - return nil,err + return nil, err end --- -- Usage help From 0da07fe81c2495125a224eddf339a9c522319467 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 2 Jan 2019 19:31:06 +0200 Subject: [PATCH 0365/1938] get SFI records --- client/emv/emvcore.c | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index b582792ac..8b774eaf0 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -335,6 +335,8 @@ int EMVSelectPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv) { uint8_t data[APDU_RES_LEN] = {0}; size_t datalen = 0; + uint8_t sfidata[APDU_RES_LEN] = {0}; + size_t sfidatalen = 0; uint16_t sw = 0; int res; @@ -342,9 +344,47 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO res = EMVSelectPSE(channel, ActivateField, true, PSENum, data, sizeof(data), &datalen, &sw); if (!res){ + if (sw != 0x9000) { + PrintAndLogEx(FAILED, "Select PSE error. APDU error: %04x.", sw); + return 1; + } + struct tlvdb *t = NULL; t = tlvdb_parse_multi(data, datalen); if (t) { + struct tlvdb *tsfi = tlvdb_find_path(t, (tlv_tag_t[]){0x6f, 0xa5, 0x88, 0x00}); + if (tsfi) { + const struct tlv *tsfi_tlv = tlvdb_get_tlv(tsfi); + uint8_t sfin = tsfi_tlv->value[0]; + PrintAndLogEx(INFO, "* PPSE get SFI: 0x%02x.", sfin); + + for (uint8_t ui = 0x01; ui <= 0x10; ui++) { + PrintAndLogEx(INFO, "* * Get SFI: 0x%02x. num: 0x%02x", sfin, ui); + res = EMVReadRecord(channel, true, sfin, ui, sfidata, sizeof(sfidata), &sfidatalen, &sw, NULL); + + // end of records + if (sw == 0x6a83) { + PrintAndLogEx(INFO, "* * PPSE get SFI. End of records."); + break; + } + + // here must bee an error catch! + if (sw != 0x9000) { + PrintAndLogEx(FAILED, "PPSE get Error. APDU error: %04x.", sw); + break; + } + + if (decodeTLV){ + TLVPrintFromBuffer(sfidata, sfidatalen); + } + + } + + + } + + + int retrycnt = 0; struct tlvdb *ttmp = tlvdb_find_path(t, (tlv_tag_t[]){0x6f, 0xa5, 0xbf0c, 0x61, 0x00}); if (!ttmp) From a5f8454168600d638354ccbe19ff75f599060777 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 3 Jan 2019 13:41:28 +0200 Subject: [PATCH 0366/1938] added pse sfi files get --- client/emv/emvcore.c | 84 +++++++++++++++++++++++++++++++------------- 1 file changed, 60 insertions(+), 24 deletions(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 8b774eaf0..bc2fa1a1a 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -332,11 +332,38 @@ int EMVSelectPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO return res; } +int EMVSelectWithRetry(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t *AID, size_t AIDLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { + int retrycnt = 0; + int res = 0; + do { + res = EMVSelect(channel, false, true, AID, AIDLen, Result, MaxResultLen, ResultLen, sw, tlv); + + // retry if error and not returned sw error + if (res && res != 5) { + if (++retrycnt < 3){ + continue; + } else { + // card select error, proxmark error + if (res == 1) { + PrintAndLogEx(WARNING, "Exit..."); + return 1; + } + + retrycnt = 0; + PrintAndLogEx(NORMAL, "Retry failed [%s]. Skiped...", sprint_hex_inrow(AID, AIDLen)); + return res; + } + } + } while (res && res != 5); + + return res; +} + int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv) { uint8_t data[APDU_RES_LEN] = {0}; size_t datalen = 0; - uint8_t sfidata[APDU_RES_LEN] = {0}; - size_t sfidatalen = 0; + uint8_t sfidata[0x11][APDU_RES_LEN] = {0}; + size_t sfidatalen[0x11] = {0}; uint16_t sw = 0; int res; @@ -360,24 +387,45 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO for (uint8_t ui = 0x01; ui <= 0x10; ui++) { PrintAndLogEx(INFO, "* * Get SFI: 0x%02x. num: 0x%02x", sfin, ui); - res = EMVReadRecord(channel, true, sfin, ui, sfidata, sizeof(sfidata), &sfidatalen, &sw, NULL); + res = EMVReadRecord(channel, true, sfin, ui, sfidata[ui], APDU_RES_LEN, &sfidatalen[ui], &sw, NULL); // end of records if (sw == 0x6a83) { + sfidatalen[ui] = 0; PrintAndLogEx(INFO, "* * PPSE get SFI. End of records."); break; } - // here must bee an error catch! + // error catch! if (sw != 0x9000) { + sfidatalen[ui] = 0; PrintAndLogEx(FAILED, "PPSE get Error. APDU error: %04x.", sw); break; } if (decodeTLV){ - TLVPrintFromBuffer(sfidata, sfidatalen); + TLVPrintFromBuffer(sfidata[ui], sfidatalen[ui]); + } + } + + for (uint8_t ui = 0x01; ui <= 0x10; ui++) { + if (sfidatalen[ui]) { + struct tlvdb *tsfi = NULL; + tsfi = tlvdb_parse_multi(sfidata[ui], sfidatalen[ui]); + if (tsfi) { + struct tlvdb *tsfitmp = tlvdb_find_path(tsfi, (tlv_tag_t[]){0x70, 0x61, 0x00}); + if (!tsfitmp) { + PrintAndLogEx(FAILED, "SFI 0x%02d don't have records.", sfidatalen[ui]); + continue; + } + + // todo: check + PrintAndLogEx(INFO, "OK SFI 0x%02d.", sfidatalen[ui]); + + + } + tlvdb_free(tsfi); } - } @@ -385,7 +433,6 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO - int retrycnt = 0; struct tlvdb *ttmp = tlvdb_find_path(t, (tlv_tag_t[]){0x6f, 0xa5, 0xbf0c, 0x61, 0x00}); if (!ttmp) PrintAndLogEx(FAILED, "PPSE don't have records."); @@ -393,28 +440,17 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO while (ttmp) { const struct tlv *tgAID = tlvdb_get_inchild(ttmp, 0x4f, NULL); if (tgAID) { - res = EMVSelect(channel, false, true, (uint8_t *)tgAID->value, tgAID->len, data, sizeof(data), &datalen, &sw, tlv); + res = EMVSelectWithRetry(channel, false, true, (uint8_t *)tgAID->value, tgAID->len, data, sizeof(data), &datalen, &sw, tlv); - // retry if error and not returned sw error - if (res && res != 5) { - if (++retrycnt < 3){ - continue; - } else { - // card select error, proxmark error - if (res == 1) { - PrintAndLogEx(WARNING, "Exit..."); - return 1; - } - - retrycnt = 0; - PrintAndLogEx(NORMAL, "Retry failed [%s]. Skiped...", sprint_hex_inrow(tgAID->value, tgAID->len)); - } - + // if returned sw error + if (res == 5) { // next element ttmp = tlvdb_find_next(ttmp, 0x61); continue; } - retrycnt = 0; + + if (res) + break; // all is ok if (decodeTLV){ From 723298d00cb2628e3f70375e489c7acb5ba59d12 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 3 Jan 2019 19:42:40 +0200 Subject: [PATCH 0367/1938] added new tlv function --- client/emv/tlv.c | 38 ++++++++++++++++++++++++++++++++++++++ client/emv/tlv.h | 3 +++ 2 files changed, 41 insertions(+) diff --git a/client/emv/tlv.c b/client/emv/tlv.c index 35bdb5d4c..a41d98c95 100644 --- a/client/emv/tlv.c +++ b/client/emv/tlv.c @@ -25,6 +25,7 @@ #include #include #include +#include #define TLV_TAG_CLASS_MASK 0xc0 #define TLV_TAG_COMPLEX 0x20 @@ -534,3 +535,40 @@ struct tlvdb *tlvdb_elm_get_parent(struct tlvdb *tlvdb) { return tlvdb->parent; } + +bool tlv_get_uint8(const struct tlv *etlv, uint8_t *value) +{ + *value = 0; + if (etlv) + { + if (etlv->len == 0) + return true; + + if (etlv->len == 1) + { + *value = etlv->value[0]; + return true; + } + } + return false; +} + +bool tlv_get_int(const struct tlv *etlv, int *value) +{ + *value = 0; + if (etlv) + { + if (etlv->len == 0) + return true; + + if (etlv->len <= 4) + { + for (int i = 0; i < etlv->len; i++) + { + *value += etlv->value[i] * pow(0x100, i); + } + return true; + } + } + return false; +} diff --git a/client/emv/tlv.h b/client/emv/tlv.h index b25b51de2..e3c7c97fa 100644 --- a/client/emv/tlv.h +++ b/client/emv/tlv.h @@ -61,4 +61,7 @@ unsigned char *tlv_encode(const struct tlv *tlv, size_t *len); bool tlv_is_constructed(const struct tlv *tlv); bool tlv_equal(const struct tlv *a, const struct tlv *b); +bool tlv_get_uint8(const struct tlv *etlv, uint8_t *value); +bool tlv_get_int(const struct tlv *etlv, int *value); + #endif From 00d4393af49a5d9a283ae53eaf40545e124adb7e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 3 Jan 2019 19:43:01 +0200 Subject: [PATCH 0368/1938] tlv_get_uint8 --- client/emv/emvcore.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index bc2fa1a1a..80affb6c1 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -381,8 +381,8 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO if (t) { struct tlvdb *tsfi = tlvdb_find_path(t, (tlv_tag_t[]){0x6f, 0xa5, 0x88, 0x00}); if (tsfi) { - const struct tlv *tsfi_tlv = tlvdb_get_tlv(tsfi); - uint8_t sfin = tsfi_tlv->value[0]; + uint8_t sfin = 0; + tlv_get_uint8(tlvdb_get_tlv(tsfi), &sfin); PrintAndLogEx(INFO, "* PPSE get SFI: 0x%02x.", sfin); for (uint8_t ui = 0x01; ui <= 0x10; ui++) { From b5c2ccb78f62d6eb5a5c87aa8c8a61810d514d75 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 3 Jan 2019 20:07:08 +0200 Subject: [PATCH 0369/1938] pse/ppse works --- client/emv/emvcore.c | 77 +++++++++++++++++++++++++------------------- 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 80affb6c1..47705cc60 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -359,6 +359,38 @@ int EMVSelectWithRetry(EMVCommandChannel channel, bool ActivateField, bool Leave return res; } +int EMVCheckAID(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlvdbelm, struct tlvdb *tlv){ + uint8_t data[APDU_RES_LEN] = {0}; + size_t datalen = 0; + int res = 0; + uint16_t sw = 0; + + while (tlvdbelm) { + const struct tlv *tgAID = tlvdb_get_inchild(tlvdbelm, 0x4f, NULL); + if (tgAID) { + res = EMVSelectWithRetry(channel, false, true, (uint8_t *)tgAID->value, tgAID->len, data, sizeof(data), &datalen, &sw, tlv); + + // if returned sw error + if (res == 5) { + // next element + tlvdbelm = tlvdb_find_next(tlvdbelm, 0x61); + continue; + } + + if (res) + break; + + // all is ok + if (decodeTLV){ + PrintAndLogEx(NORMAL, "%s:", sprint_hex_inrow(tgAID->value, tgAID->len)); + TLVPrintFromBuffer(data, datalen); + } + } + tlvdbelm = tlvdb_find_next(tlvdbelm, 0x61); + } + return res; +} + int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv) { uint8_t data[APDU_RES_LEN] = {0}; size_t datalen = 0; @@ -366,6 +398,7 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO size_t sfidatalen[0x11] = {0}; uint16_t sw = 0; int res; + bool fileFound = false; // select PPSE res = EMVSelectPSE(channel, ActivateField, true, PSENum, data, sizeof(data), &datalen, &sw); @@ -379,6 +412,7 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO struct tlvdb *t = NULL; t = tlvdb_parse_multi(data, datalen); if (t) { + // PSE/PPSE with SFI struct tlvdb *tsfi = tlvdb_find_path(t, (tlv_tag_t[]){0x6f, 0xa5, 0x88, 0x00}); if (tsfi) { uint8_t sfin = 0; @@ -418,49 +452,24 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO PrintAndLogEx(FAILED, "SFI 0x%02d don't have records.", sfidatalen[ui]); continue; } - - // todo: check - PrintAndLogEx(INFO, "OK SFI 0x%02d.", sfidatalen[ui]); - - + res = EMVCheckAID(channel, decodeTLV, tsfitmp, tlv); + fileFound = true; } tlvdb_free(tsfi); } } - - } - + // PSE/PPSE plain (wo SFI) struct tlvdb *ttmp = tlvdb_find_path(t, (tlv_tag_t[]){0x6f, 0xa5, 0xbf0c, 0x61, 0x00}); - if (!ttmp) - PrintAndLogEx(FAILED, "PPSE don't have records."); - - while (ttmp) { - const struct tlv *tgAID = tlvdb_get_inchild(ttmp, 0x4f, NULL); - if (tgAID) { - res = EMVSelectWithRetry(channel, false, true, (uint8_t *)tgAID->value, tgAID->len, data, sizeof(data), &datalen, &sw, tlv); - - // if returned sw error - if (res == 5) { - // next element - ttmp = tlvdb_find_next(ttmp, 0x61); - continue; - } - - if (res) - break; - - // all is ok - if (decodeTLV){ - PrintAndLogEx(NORMAL, "%s:", sprint_hex_inrow(tgAID->value, tgAID->len)); - TLVPrintFromBuffer(data, datalen); - } - } - - ttmp = tlvdb_find_next(ttmp, 0x61); + if (ttmp) { + res = EMVCheckAID(channel, decodeTLV, ttmp, tlv); + fileFound = true; } + + if (!fileFound) + PrintAndLogEx(FAILED, "PPSE don't have records."); tlvdb_free(t); } else { From a86c6fa1a8cf10dac8b8d4f4849f455e562e38af Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 3 Jan 2019 21:00:07 +0200 Subject: [PATCH 0370/1938] get rid of math.h ) --- client/emv/tlv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/emv/tlv.c b/client/emv/tlv.c index a41d98c95..013e9735a 100644 --- a/client/emv/tlv.c +++ b/client/emv/tlv.c @@ -25,7 +25,6 @@ #include #include #include -#include #define TLV_TAG_CLASS_MASK 0xc0 #define TLV_TAG_COMPLEX 0x20 @@ -565,7 +564,7 @@ bool tlv_get_int(const struct tlv *etlv, int *value) { for (int i = 0; i < etlv->len; i++) { - *value += etlv->value[i] * pow(0x100, i); + *value += etlv->value[i] * (1 << (i * 8)); } return true; } From f23219f3b8d4dd16f88b8ffbfec8e8ea2d60c325 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 5 Jan 2019 20:45:02 +0100 Subject: [PATCH 0371/1938] FIX: printing percentage char is now standard compliant (@fabled) see https://github.com/iceman1001/proxmark3/pull/272 --- client/cmdhw.c | 2 +- client/ui.c | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/cmdhw.c b/client/cmdhw.c index 49cb0025e..a93a940cc 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -74,7 +74,7 @@ static void lookupChipID(uint32_t iChipID, uint32_t mem_used) { if ( mem_avail > 0 ) mem_left = (mem_avail * 1024) - mem_used; - PrintAndLogEx(NORMAL, " --= Nonvolatile Program Memory Size: %uK bytes, Used: %u bytes (%2.0f\%) Free: %u bytes (%2.0f\%)", + PrintAndLogEx(NORMAL, " --= Nonvolatile Program Memory Size: %uK bytes, Used: %u bytes (%2.0f%%) Free: %u bytes (%2.0f%%)", mem_avail, mem_used, mem_avail == 0 ? 0.0f : (float)mem_used/(mem_avail*1024)*100, diff --git a/client/ui.c b/client/ui.c index 3f7e2611f..868545833 100644 --- a/client/ui.c +++ b/client/ui.c @@ -41,7 +41,7 @@ void PrintAndLogOptions(char *str[][2], size_t size, size_t space) { if (i < size-1) strncat(buff, "\n", sizeof(buff)-strlen(buff) -1); } - PrintAndLogEx(NORMAL, buff); + PrintAndLogEx(NORMAL, "%s", buff); } void PrintAndLogEx(logLevel_t level, char *fmt, ...) { @@ -85,7 +85,7 @@ void PrintAndLogEx(logLevel_t level, char *fmt, ...) { // no prefixes for normal if ( level == NORMAL ) { - PrintAndLog(buffer); + PrintAndLog("%s", buffer); return; } @@ -110,10 +110,10 @@ void PrintAndLogEx(logLevel_t level, char *fmt, ...) { token = strtok(NULL, delim); } - PrintAndLog(buffer2); + PrintAndLog("%s", buffer2); } else { snprintf(buffer2, sizeof(buffer2), "%s%s", prefix, buffer); - PrintAndLog(buffer2); + PrintAndLog("%s", buffer2); } } From 411fad13de4717c17aca0af53d6eec39724b01b3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 5 Jan 2019 20:49:46 +0100 Subject: [PATCH 0372/1938] updates --- CHANGELOG.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 64377c383..622ff0f78 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,9 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Add 'option to use flash memory to upload dictionary files' (RDV40) (@iceman) + - Fix 'printing percentage now standard compliant' (@fabled) + - Add 'emv roca' - command to test for ROCA vuln in public RSA modulus (@merlokk / @iceman) - Added TCP ports support (on linux) (@phcoder) - Added HF sniff standalone mode with optional storing of ULC/NTAG/ULEV1 authentication attempts (@bogiton) - Fix 'Lining up plot and control window' (@anticat) From 38853b111f9b61be6f67e1cbd8eeee567cdba4ac Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 5 Jan 2019 20:59:00 +0100 Subject: [PATCH 0373/1938] FIX: adding directives to reduce size on systems like Gentoo Hardned (see https://github.com/iceman1001/proxmark3/issues/268) --- armsrc/Makefile | 5 +++-- bootrom/Makefile | 4 ++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/armsrc/Makefile b/armsrc/Makefile index b69e724e0..76f3a0173 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -122,8 +122,9 @@ APP_CFLAGS += $(ZLIB_CFLAGS) # zlib includes: APP_CFLAGS += -I../zlib -# stdint.h provided locally until GCC 4.5 becomes C99 compliant -APP_CFLAGS += -I. +# stdint.h provided locally until GCC 4.5 becomes C99 compliant, +# stack-protect , no-pie reduces size on Gentoo Hardened 8.2 gcc +APP_CFLAGS += -I. -fno-stack-protector -fno-pie # Compile these in thumb mode (small size) THUMBSRC = start.c \ diff --git a/bootrom/Makefile b/bootrom/Makefile index a579c46d3..c7e879bda 100644 --- a/bootrom/Makefile +++ b/bootrom/Makefile @@ -25,6 +25,10 @@ VERSIONSRC = version.c # stdint.h provided locally until GCC 4.5 becomes C99 compliant APP_CFLAGS = -I. -fno-strict-aliasing -ffunction-sections -fdata-sections +# stack-protect , no-pie reduces size on Gentoo Hardened 8.2 gcc +APP_CFLAGS += -fno-stack-protector -fno-pie + + # Do not move this inclusion before the definition of {THUMB,ASM,ARM}SRC include ../common/Makefile.common From f99e6a5cae4916166b53109b4b9baea4a119138b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 6 Jan 2019 19:19:30 +0100 Subject: [PATCH 0374/1938] chg: remove warning --- client/emv/emvcore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 47705cc60..621287031 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -394,7 +394,7 @@ int EMVCheckAID(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlvdbel int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t PSENum, bool decodeTLV, struct tlvdb *tlv) { uint8_t data[APDU_RES_LEN] = {0}; size_t datalen = 0; - uint8_t sfidata[0x11][APDU_RES_LEN] = {0}; + uint8_t sfidata[0x11][APDU_RES_LEN]; size_t sfidatalen[0x11] = {0}; uint16_t sw = 0; int res; From 806e5909a73124e7c2db8ce4895fc80e941a7720 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 6 Jan 2019 19:41:29 +0100 Subject: [PATCH 0375/1938] ADD: 'hf felica list' - updated annotation. --- client/cmdhffelica.c | 2 +- client/cmdhflist.c | 41 +++++++++++ common/protocols.h | 169 ++++++++++++++++++++++--------------------- 3 files changed, 128 insertions(+), 84 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index e8eeceb5e..700f7ae8b 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -66,7 +66,7 @@ int usage_hf_felica_raw(void){ int CmdHFFelicaList(const char *Cmd) { //PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list felica' instead"); - CmdTraceList("raw"); + CmdTraceList("felica"); return 0; } diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 14dcc6039..e4a7e27b4 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -535,7 +535,48 @@ void annotateLegic(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ } void annotateFelica(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ + switch(cmd[0]){ + case FELICA_POLL_REQ: snprintf(exp,size ,"POLLING");break; + case FELICA_POLL_ACK: snprintf(exp,size ,"POLL ACK");break; + case FELICA_REQSRV_REQ: snprintf(exp,size ,"REQUEST SERVICE");break; + case FELICA_REQSRV_ACK: snprintf(exp,size ,"REQ SERV ACK");break; + case FELICA_REQRESP_REQ: snprintf(exp,size ,"REQUEST RESPONSE");break; + case FELICA_REQRESP_ACK: snprintf(exp,size ,"REQ RESP ACK");break; + case FELICA_RDBLK_REQ: snprintf(exp,size ,"READ BLK");break; + case FELICA_RDBLK_ACK: snprintf(exp,size ,"READ BLK ACK");break; + case FELICA_WRTBLK_REQ: snprintf(exp,size ,"WRITE BLK");break; + case FELICA_WRTBLK_ACK: snprintf(exp,size ,"WRITE BLK ACK");break; + case FELICA_SRCHSYSCODE_REQ: snprintf(exp,size ,"SEARCH SERVICE CODE");break; + case FELICA_SRCHSYSCODE_ACK: snprintf(exp,size ,"SSC ACK");break; + case FELICA_REQSYSCODE_REQ: snprintf(exp,size ,"REQUEST SYSTEM CODE");break; + case FELICA_REQSYSCODE_ACK: snprintf(exp,size ,"RSC ACK");break; + case FELICA_AUTH1_REQ: snprintf(exp,size ,"AUTH 1");break; + case FELICA_AUTH1_ACK: snprintf(exp,size ,"AUTH 1 ACK");break; + case FELICA_AUTH2_REQ: snprintf(exp,size ,"AUTH 2");break; + case FELICA_AUTH2_ACK: snprintf(exp,size ,"AUTH 2 ACK");break; + case FELICA_RDSEC_REQ: snprintf(exp,size ,"READ");break; + case FELICA_RDSEC_ACK: snprintf(exp,size ,"READ ACK");break; + case FELICA_WRTSEC_REQ: snprintf(exp,size ,"WRITE");break; + case FELICA_WRTSEC_ACK: snprintf(exp,size ,"WRITE ACK");break; + case FELICA_REQSRV2_REQ: snprintf(exp,size ,"REQUEST SERVICE v2");break; + case FELICA_REQSRV2_ACK: snprintf(exp,size ,"REQ SERV v2 ACK");break; + case FELICA_GETSTATUS_REQ: snprintf(exp,size ,"GET STATUS");break; + case FELICA_GETSTATUS_ACK: snprintf(exp,size ,"GET STATUS ACK");break; + case FELICA_OSVER_REQ: snprintf(exp,size ,"REQUEST SPECIFIC VERSION");break; + case FELICA_OSVER_ACK: snprintf(exp,size ,"RSV ACK");break; + case FELICA_RESET_MODE_REQ: snprintf(exp,size ,"RESET MODE");break; + case FELICA_RESET_MODE_ACK: snprintf(exp,size ,"RESET MODE ACK");break; + case FELICA_AUTH1V2_REQ: snprintf(exp,size ,"AUTH 1 v2");break; + case FELICA_AUTH1V2_ACK: snprintf(exp,size ,"AUTH 1 v2 ACK");break; + case FELICA_AUTH2V2_REQ: snprintf(exp,size ,"AUTH 2 v2");break; + case FELICA_AUTH2V2_ACK: snprintf(exp,size ,"AUTH 2 v2 ACK");break; + case FELICA_RDSECV2_REQ: snprintf(exp,size ,"READ v2");break; + case FELICA_RDSECV2_ACK: snprintf(exp,size ,"READ v2 ACK");break; + case FELICA_WRTSECV2_REQ: snprintf(exp,size ,"WRITE v2");break; + case FELICA_WRTSECV2_ACK: snprintf(exp,size ,"WRITE v2 ACK");break; + case FELICA_UPDATE_RNDID_REQ: snprintf(exp,size ,"UPDATE RANDOM ID");break; + case FELICA_UPDATE_RNDID_ACK: snprintf(exp,size ,"URI ACK");break; default : snprintf(exp,size ,"?");break; } } diff --git a/common/protocols.h b/common/protocols.h index 0f3ef3407..8db1d481e 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -310,51 +310,51 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. // 6x xx = ERROR // MIFARE DESFire command set: -#define MFDES_CREATE_APPLICATION 0xca -#define MFDES_DELETE_APPLICATION 0xda -#define MFDES_GET_APPLICATION_IDS 0x6a -#define MFDES_SELECT_APPLICATION 0x5a -#define MFDES_FORMAT_PICC 0xfc -#define MFDES_GET_VERSION 0x60 -#define MFDES_READ_DATA 0xbd -#define MFDES_WRITE_DATA 0x3d -#define MFDES_GET_VALUE 0x6c -#define MFDES_CREDIT 0x0c -#define MFDES_DEBIT 0xdc -#define MFDES_LIMITED_CREDIT 0x1c -#define MFDES_WRITE_RECORD 0x3b -#define MFDES_READ_RECORDS 0xbb -#define MFDES_CLEAR_RECORD_FILE 0xeb -#define MFDES_COMMIT_TRANSACTION 0xc7 -#define MFDES_ABORT_TRANSACTION 0xa7 -#define MFDES_GET_FREE_MEMORY 0x6e -#define MFDES_GET_FILE_IDS 0x6f -#define MFDES_GET_ISOFILE_IDS 0x61 -#define MFDES_GET_FILE_SETTINGS 0xf5 -#define MFDES_CHANGE_FILE_SETTINGS 0x5f -#define MFDES_CREATE_STD_DATA_FILE 0xcd -#define MFDES_CREATE_BACKUP_DATA_FILE 0xcb -#define MFDES_CREATE_VALUE_FILE 0xcc -#define MFDES_CREATE_LINEAR_RECORD_FILE 0xc1 -#define MFDES_CREATE_CYCLIC_RECORD_FILE 0xc0 -#define MFDES_DELETE_FILE 0xdf -#define MFDES_AUTHENTICATE 0x0a // AUTHENTICATE_NATIVE -#define MFDES_AUTHENTICATE_ISO 0x1a // AUTHENTICATE_STANDARD -#define MFDES_AUTHENTICATE_AES 0xaa -#define MFDES_CHANGE_KEY_SETTINGS 0x54 -#define MFDES_GET_KEY_SETTINGS 0x45 -#define MFDES_CHANGE_KEY 0xc4 -#define MFDES_GET_KEY_VERSION 0x64 -#define MFDES_AUTHENTICATION_FRAME 0xAF +#define MFDES_CREATE_APPLICATION 0xca +#define MFDES_DELETE_APPLICATION 0xda +#define MFDES_GET_APPLICATION_IDS 0x6a +#define MFDES_SELECT_APPLICATION 0x5a +#define MFDES_FORMAT_PICC 0xfc +#define MFDES_GET_VERSION 0x60 +#define MFDES_READ_DATA 0xbd +#define MFDES_WRITE_DATA 0x3d +#define MFDES_GET_VALUE 0x6c +#define MFDES_CREDIT 0x0c +#define MFDES_DEBIT 0xdc +#define MFDES_LIMITED_CREDIT 0x1c +#define MFDES_WRITE_RECORD 0x3b +#define MFDES_READ_RECORDS 0xbb +#define MFDES_CLEAR_RECORD_FILE 0xeb +#define MFDES_COMMIT_TRANSACTION 0xc7 +#define MFDES_ABORT_TRANSACTION 0xa7 +#define MFDES_GET_FREE_MEMORY 0x6e +#define MFDES_GET_FILE_IDS 0x6f +#define MFDES_GET_ISOFILE_IDS 0x61 +#define MFDES_GET_FILE_SETTINGS 0xf5 +#define MFDES_CHANGE_FILE_SETTINGS 0x5f +#define MFDES_CREATE_STD_DATA_FILE 0xcd +#define MFDES_CREATE_BACKUP_DATA_FILE 0xcb +#define MFDES_CREATE_VALUE_FILE 0xcc +#define MFDES_CREATE_LINEAR_RECORD_FILE 0xc1 +#define MFDES_CREATE_CYCLIC_RECORD_FILE 0xc0 +#define MFDES_DELETE_FILE 0xdf +#define MFDES_AUTHENTICATE 0x0a // AUTHENTICATE_NATIVE +#define MFDES_AUTHENTICATE_ISO 0x1a // AUTHENTICATE_STANDARD +#define MFDES_AUTHENTICATE_AES 0xaa +#define MFDES_CHANGE_KEY_SETTINGS 0x54 +#define MFDES_GET_KEY_SETTINGS 0x45 +#define MFDES_CHANGE_KEY 0xc4 +#define MFDES_GET_KEY_VERSION 0x64 +#define MFDES_AUTHENTICATION_FRAME 0xAF // LEGIC Commands -#define LEGIC_MIM_22 0x0D -#define LEGIC_MIM_256 0x1D -#define LEGIC_MIM_1024 0x3D -#define LEGIC_ACK_22 0x19 -#define LEGIC_ACK_256 0x39 -#define LEGIC_READ 0x01 -#define LEGIC_WRITE 0x00 +#define LEGIC_MIM_22 0x0D +#define LEGIC_MIM_256 0x1D +#define LEGIC_MIM_1024 0x3D +#define LEGIC_ACK_22 0x19 +#define LEGIC_ACK_256 0x39 +#define LEGIC_READ 0x01 +#define LEGIC_WRITE 0x00 void printIclassDumpInfo(uint8_t* iclass_dump); void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb); @@ -379,7 +379,7 @@ void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t * #define T55x7_MODULATION_MANCHESTER 0x00008000 #define T55x7_MODULATION_BIPHASE 0x00010000 #define T55x7_MODULATION_DIPHASE 0x00018000 -#define T55x7_X_MODE 0x00020000 +#define T55x7_X_MODE 0x00020000 #define T55x7_BITRATE_RF_8 0 #define T55x7_BITRATE_RF_16 0x00040000 #define T55x7_BITRATE_RF_32 0x00080000 @@ -406,9 +406,9 @@ void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t * #define T5555_PSK_RF_8 0x00000200 #define T5555_USE_PWD 0x00000400 #define T5555_USE_AOR 0x00000800 -#define T5555_SET_BITRATE(x) (((x-2)/2)<<12) -#define T5555_GET_BITRATE(x) ((((x >> 12) & 0x3F)*2)+2) -#define T5555_BITRATE_SHIFT 12 //(RF=2n+2) ie 64=2*0x1F+2 or n = (RF-2)/2 +#define T5555_SET_BITRATE(x) (((x-2)/2)<<12) +#define T5555_GET_BITRATE(x) ((((x >> 12) & 0x3F)*2)+2) +#define T5555_BITRATE_SHIFT 12 //(RF=2n+2) ie 64=2*0x1F+2 or n = (RF-2)/2 #define T5555_FAST_WRITE 0x00004000 #define T5555_PAGE_SELECT 0x00008000 @@ -446,58 +446,61 @@ uint32_t GetT55xxClockBit(uint32_t clock); // FeliCa protocol -#define FELICA_POLL_REQ 0x00 -#define FELICA_POLL_ACK 0x01 +#define FELICA_POLL_REQ 0x00 +#define FELICA_POLL_ACK 0x01 -#define FELICA_REQSRV_REQ 0x02 -#define FELICA_REQSRV_ACK 0x03 +#define FELICA_REQSRV_REQ 0x02 +#define FELICA_REQSRV_ACK 0x03 -#define FELICA_RDBLK_REQ 0x06 -#define FELICA_RDBLK_ACK 0x07 +#define FELICA_REQRESP_REQ 0x04 +#define FELICA_REQRESP_ACK 0x05 -#define FELICA_WRTBLK_REQ 0x08 -#define FELICA_WRTBLK_ACK 0x09 +#define FELICA_RDBLK_REQ 0x06 +#define FELICA_RDBLK_ACK 0x07 -#define FELICA_SRCHSYSCODE_REQ 0x0a -#define FELICA_SRCHSYSCODE_ACK 0x0b +#define FELICA_WRTBLK_REQ 0x08 +#define FELICA_WRTBLK_ACK 0x09 -#define FELICA_REQSYSCODE_REQ 0x0c -#define FELICA_REQSYSCODE_ACK 0x0d +#define FELICA_SRCHSYSCODE_REQ 0x0a +#define FELICA_SRCHSYSCODE_ACK 0x0b -#define FELICA_AUTH1_REQ 0x10 -#define FELICA_AUTH1_ACK 0x11 +#define FELICA_REQSYSCODE_REQ 0x0c +#define FELICA_REQSYSCODE_ACK 0x0d -#define FELICA_AUTH2_REQ 0x12 -#define FELICA_AUTH2_ACK 0x13 +#define FELICA_AUTH1_REQ 0x10 +#define FELICA_AUTH1_ACK 0x11 -#define FELICA_RDSEC_REQ 0x14 -#define FELICA_RDSEC_ACK 0x15 +#define FELICA_AUTH2_REQ 0x12 +#define FELICA_AUTH2_ACK 0x13 -#define FELICA_WRTSEC_REQ 0x16 -#define FELICA_WRTSEC_ACK 0x17 +#define FELICA_RDSEC_REQ 0x14 +#define FELICA_RDSEC_ACK 0x15 -#define FELICA_REQSRV2_REQ 0x32 -#define FELICA_REQSRV2_ACK 0x33 +#define FELICA_WRTSEC_REQ 0x16 +#define FELICA_WRTSEC_ACK 0x17 -#define FELICA_GETSTATUS_REQ 0x38 -#define FELICA_GETSTATUS_ACK 0x39 +#define FELICA_REQSRV2_REQ 0x32 +#define FELICA_REQSRV2_ACK 0x33 -#define FELICA_OSVER_REQ 0x3c -#define FELICA_OSVER_ACK 0x3d +#define FELICA_GETSTATUS_REQ 0x38 +#define FELICA_GETSTATUS_ACK 0x39 -#define FELICA_RESET_MODE_REQ 0x3e -#define FELICA_RESET_MODE_ACK 0x3f +#define FELICA_OSVER_REQ 0x3c +#define FELICA_OSVER_ACK 0x3d -#define FELICA_AUTH1V2_REQ 0x40 -#define FELICA_AUTH1V2_ACK 0x41 +#define FELICA_RESET_MODE_REQ 0x3e +#define FELICA_RESET_MODE_ACK 0x3f -#define FELICA_AUTH2V2_REQ 0x42 -#define FELICA_AUTH2V2_ACK 0x43 +#define FELICA_AUTH1V2_REQ 0x40 +#define FELICA_AUTH1V2_ACK 0x41 -#define FELICA_RDSECV2_REQ 0x44 -#define FELICA_RDSECV2_ACK 0x45 -#define FELICA_WRTSECV2_REQ 0x46 -#define FELICA_WRTSECV2_ACK 0x47 +#define FELICA_AUTH2V2_REQ 0x42 +#define FELICA_AUTH2V2_ACK 0x43 + +#define FELICA_RDSECV2_REQ 0x44 +#define FELICA_RDSECV2_ACK 0x45 +#define FELICA_WRTSECV2_REQ 0x46 +#define FELICA_WRTSECV2_ACK 0x47 #define FELICA_UPDATE_RNDID_REQ 0x4C #define FELICA_UPDATE_RNDID_ACK 0x4D From 0dee369a585e9e2b74152798fe18d4de4f385bd5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 6 Jan 2019 20:28:23 +0100 Subject: [PATCH 0376/1938] FIX: 'hf tune' - now works... --- armsrc/appmain.c | 6 +++--- client/comms.c | 47 ++++++++++++++++++----------------------------- include/usb_cmd.h | 11 ++++++----- 3 files changed, 27 insertions(+), 37 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index bf4bddef6..8759f93c4 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -113,7 +113,7 @@ void print_result(char *name, uint8_t *buf, size_t len) { void DbpStringEx(char *str, uint32_t cmd) { #if DEBUG uint8_t len = strlen(str); - cmd_send(CMD_DEBUG_PRINT_STRING, len, cmd, 0, (byte_t*)str, len); + cmd_send(CMD_DEBUG_PRINT_STRING, len, cmd, 0, (uint8_t*)str, len); #endif } @@ -307,10 +307,10 @@ void MeasureAntennaTuningHf(void) { } else { volt = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10; } - DbprintfEx(CMD_MEASURE_ANTENNA_TUNING_HF, "%u mV / %5u V", volt, (uint16_t)(volt/1000)); + DbprintfEx(FLAG_NONEWLINE, "%u mV / %5u V", volt, (uint16_t)(volt/1000)); } FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - DbpString("\n[+] cancelled"); + DbprintfEx(FLAG_NOOPT, "\n[+] cancelled", 1); } void ReadMem(int addr) { diff --git a/client/comms.c b/client/comms.c index 97af830df..3c2b353b3 100644 --- a/client/comms.c +++ b/client/comms.c @@ -154,36 +154,25 @@ static void UsbCommandReceived(UsbCommand* c) { char s[USB_CMD_DATA_SIZE+1]; memset(s, 0x00, sizeof(s)); size_t len = MIN(c->arg[0], USB_CMD_DATA_SIZE); - memcpy(s, c->d.asBytes, len); - - - //#define FLAG_RAWPRINT 0x0111 - //#define FLAG_NOOPT 0x0000 - //#define FLAG_NOLOG 0x0001 - //#define FLAG_NONEWLINE 0x0010 - //#define FLAG_NOPROMPT 0x0100 + memcpy(s, c->d.asBytes, len); uint64_t flag = c->arg[1]; - if (flag > 0) { // FLAG_RAWPRINT) { - switch (flag) { - case FLAG_RAWPRINT: - printf("%s", s); - return; - case FLAG_NONEWLINE: - printf("%s\r", s); - return; - case FLAG_NOLOG: - printf("%s\r\n", s); - return; - } - fflush(stdout); - return; - } - - // print debug line on same row. escape seq \r - if ( c->arg[1] == CMD_MEASURE_ANTENNA_TUNING_HF) { - PrintAndLogEx(NORMAL, "\r#db# %s", s); - } else { - PrintAndLogEx(NORMAL, "#db# %s", s); + + switch (flag) { + case FLAG_RAWPRINT: + printf("%s", s); + break; + case FLAG_NONEWLINE: + printf("\r%s", s); + break; + case FLAG_NOLOG: + printf("%s\r\n", s); + break; + //case FLAG_NOPROMPT: + // break; + case FLAG_NOOPT: + default: + PrintAndLogEx(NORMAL, "#db# %s", s); + break; } fflush(stdout); break; diff --git a/include/usb_cmd.h b/include/usb_cmd.h index d6b240fb6..44d031334 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -300,11 +300,12 @@ typedef struct{ #define FLAG_ICLASS_READER_CEDITKEY 0x40 // Dbprintf flags -#define FLAG_RAWPRINT 0x0111 -#define FLAG_NOOPT 0x0000 -#define FLAG_NOLOG 0x0001 -#define FLAG_NONEWLINE 0x0010 -#define FLAG_NOPROMPT 0x0100 +#define FLAG_RAWPRINT 0x0111 +#define FLAG_NOOPT 0x0000 +#define FLAG_NOLOG 0x0001 +#define FLAG_NONEWLINE 0x0010 +#define FLAG_NOPROMPT 0x0100 + // CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions: /* Whether a bootloader that understands the common_area is present */ From c37cc81c0067c8f1c08f2cdafaa55d5975ac8799 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 6 Jan 2019 20:42:51 +0100 Subject: [PATCH 0377/1938] CHG: FeliCa more details --- armsrc/felica.c | 180 ++++++++++++++++++++++++------------------------ 1 file changed, 90 insertions(+), 90 deletions(-) diff --git a/armsrc/felica.c b/armsrc/felica.c index b25653d80..aa6712268 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -71,114 +71,114 @@ static struct { uint8_t *framebytes; //should be enough. maxlen is 255, 254 for data, 2 for sync, 2 for crc // 0,1 -> SYNC, 2 - len, 3-(len+1)->data, then crc -} NFCFrame; +} FelicaFrame; //b2 4d is SYNC, 45645 in 16-bit notation, 10110010 01001101 binary. Frame will not start filling until this is shifted in //bit order in byte -reverse, I guess? [((bt>>0)&1),((bt>>1)&1),((bt>>2)&1),((bt>>3)&1),((bt>>4)&1),((bt>>5)&1),((bt>>6)&1),((bt>>7)&1)] -at least in the mode that I read those in #ifndef SYNC_16BIT -# define SYNC_16BIT 0x4DB2 +# define SYNC_16BIT 0xB24D #endif -static void NFCFrameReset() { - NFCFrame.state = STATE_UNSYNCD; - NFCFrame.posCnt = 0; - NFCFrame.crc_ok = false; - NFCFrame.byte_offset = 0; +static void FelicaFrameReset() { + FelicaFrame.state = STATE_UNSYNCD; + FelicaFrame.posCnt = 0; + FelicaFrame.crc_ok = false; + FelicaFrame.byte_offset = 0; } static void NFCInit(uint8_t *data) { - NFCFrame.framebytes = data; - NFCFrameReset(); + FelicaFrame.framebytes = data; + FelicaFrameReset(); } //shift byte into frame, reversing it at the same time static void shiftInByte(uint8_t bt) { uint8_t j; - for(j=0; j < NFCFrame.byte_offset; j++) { - NFCFrame.framebytes[NFCFrame.posCnt] = ( NFCFrame.framebytes[NFCFrame.posCnt]<<1 ) + (bt & 1); + for(j=0; j < FelicaFrame.byte_offset; j++) { + FelicaFrame.framebytes[FelicaFrame.posCnt] = ( FelicaFrame.framebytes[FelicaFrame.posCnt]<<1 ) + (bt & 1); bt >>= 1; } - NFCFrame.posCnt++; - NFCFrame.rem_len--; - for(j = NFCFrame.byte_offset; j<8; j++) { - NFCFrame.framebytes[NFCFrame.posCnt] = (NFCFrame.framebytes[NFCFrame.posCnt]<<1 ) + (bt & 1); + FelicaFrame.posCnt++; + FelicaFrame.rem_len--; + for(j = FelicaFrame.byte_offset; j<8; j++) { + FelicaFrame.framebytes[FelicaFrame.posCnt] = (FelicaFrame.framebytes[FelicaFrame.posCnt]<<1 ) + (bt & 1); bt >>= 1; } } static void ProcessNFCByte(uint8_t bt) { - switch (NFCFrame.state) { + switch (FelicaFrame.state) { case STATE_UNSYNCD: { //almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not alsways the case if (bt > 0) { - NFCFrame.shiftReg = reflect8(bt); - NFCFrame.state = STATE_TRYING_SYNC; + FelicaFrame.shiftReg = reflect8(bt); + FelicaFrame.state = STATE_TRYING_SYNC; } break; } case STATE_TRYING_SYNC: { if (bt == 0) { //desync - NFCFrame.shiftReg = bt; - NFCFrame.state = STATE_UNSYNCD; + FelicaFrame.shiftReg = bt; + FelicaFrame.state = STATE_UNSYNCD; } else { for (uint8_t i=0; i<8; i++) { - if (NFCFrame.shiftReg == SYNC_16BIT) { + if (FelicaFrame.shiftReg == SYNC_16BIT) { //SYNC done! - NFCFrame.state = STATE_GET_LENGTH; - NFCFrame.framebytes[0] = 0xb2; - NFCFrame.framebytes[1] = 0x4d; //write SYNC - NFCFrame.byte_offset = i; + FelicaFrame.state = STATE_GET_LENGTH; + FelicaFrame.framebytes[0] = 0xb2; + FelicaFrame.framebytes[1] = 0x4d; //write SYNC + FelicaFrame.byte_offset = i; //shift in remaining byte, slowly... for(uint8_t j=i; j<8; j++) { - NFCFrame.framebytes[2] = (NFCFrame.framebytes[2] << 1) + (bt & 1); + FelicaFrame.framebytes[2] = (FelicaFrame.framebytes[2] << 1) + (bt & 1); bt >>= 1; } - NFCFrame.posCnt = 2; + FelicaFrame.posCnt = 2; if (i==0) break; } - NFCFrame.shiftReg = (NFCFrame.shiftReg << 1) + (bt & 1); + FelicaFrame.shiftReg = (FelicaFrame.shiftReg << 1) + (bt & 1); bt >>= 1; } //that byte was last byte of sync - if (NFCFrame.shiftReg == SYNC_16BIT) { + if (FelicaFrame.shiftReg == SYNC_16BIT) { //Force SYNC on next byte - NFCFrame.state = STATE_GET_LENGTH; - NFCFrame.framebytes[0] = 0xb2; - NFCFrame.framebytes[1] = 0x4d; - NFCFrame.byte_offset = 0; - NFCFrame.posCnt = 1; + FelicaFrame.state = STATE_GET_LENGTH; + FelicaFrame.framebytes[0] = 0xb2; + FelicaFrame.framebytes[1] = 0x4d; + FelicaFrame.byte_offset = 0; + FelicaFrame.posCnt = 1; } } break; } case STATE_GET_LENGTH: { shiftInByte(bt); - NFCFrame.rem_len = NFCFrame.framebytes[2] - 1; - NFCFrame.len = NFCFrame.framebytes[2] + 4; //with crc and sync - NFCFrame.state = STATE_GET_DATA; + FelicaFrame.rem_len = FelicaFrame.framebytes[2] - 1; + FelicaFrame.len = FelicaFrame.framebytes[2] + 4; //with crc and sync + FelicaFrame.state = STATE_GET_DATA; break; } case STATE_GET_DATA: { shiftInByte(bt); - if (NFCFrame.rem_len <= 0) { - NFCFrame.state = STATE_GET_CRC; - NFCFrame.rem_len = 2; + if (FelicaFrame.rem_len <= 0) { + FelicaFrame.state = STATE_GET_CRC; + FelicaFrame.rem_len = 2; } break; } case STATE_GET_CRC: { shiftInByte(bt); - if ( NFCFrame.rem_len <= 0 ) { + if ( FelicaFrame.rem_len <= 0 ) { // skip sync 2bytes. IF ok, residue should be 0x0000 - NFCFrame.crc_ok = check_crc(CRC_FELICA, NFCFrame.framebytes+2, NFCFrame.len-2); - NFCFrame.state = STATE_FULL; - NFCFrame.rem_len = 0; - if (MF_DBGLEVEL > 3) Dbprintf("[+] got 2 crc bytes [%s]", (NFCFrame.crc_ok) ? "OK" : "No" ); + FelicaFrame.crc_ok = check_crc(CRC_FELICA, FelicaFrame.framebytes+2, FelicaFrame.len-2); + FelicaFrame.state = STATE_FULL; + FelicaFrame.rem_len = 0; + if (MF_DBGLEVEL > 3) Dbprintf("[+] got 2 crc bytes [%s]", (FelicaFrame.crc_ok) ? "OK" : "No" ); } break; } @@ -207,7 +207,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) { // b0 = fc/64 (212kbps) // 0x00 = timeslot // 0x09 0x21 = crc - static uint8_t poll[10] = {0xb2,0x4d,0x06,0x00,0xFF,0xFF,0x00,0x00,0x09,0x21}; + static uint8_t poll[10] = {0xb2,0x4d,0x06,FELICA_POLL_REQ,0xFF,0xFF,0x00,0x00,0x09,0x21}; int len = 20; @@ -219,7 +219,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) { TransmitFor18092_AsReader(poll, sizeof(poll), NULL, 1, 0); // polling card, break if success - if (WaitForFelicaReply(512) && NFCFrame.framebytes[3] == FELICA_POLL_ACK) + if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK) break; WDT_HIT(); @@ -231,19 +231,19 @@ static uint8_t felica_select_card(felica_card_select_t *card) { return 1; // wrong answer - if (NFCFrame.framebytes[3] != FELICA_POLL_ACK) + if (FelicaFrame.framebytes[3] != FELICA_POLL_ACK) return 2; // VALIDATE CRC residue is 0, hence if crc is a value it failed. - if (!check_crc(CRC_FELICA, NFCFrame.framebytes+2, NFCFrame.len-2)) + if (!check_crc(CRC_FELICA, FelicaFrame.framebytes+2, FelicaFrame.len-2)) return 3; // copy UID // idm 8 if (card) { - memcpy(card->IDm, NFCFrame.framebytes + 4, 8); - memcpy(card->PMm, NFCFrame.framebytes + 4 + 8, 8); - //memcpy(card->servicecode, NFCFrame.framebytes + 4 + 8 + 8, 2); + memcpy(card->IDm, FelicaFrame.framebytes + 4, 8); + memcpy(card->PMm, FelicaFrame.framebytes + 4 + 8, 8); + //memcpy(card->servicecode, FelicaFrame.framebytes + 4 + 8 + 8, 2); memcpy(card->code, card->IDm, 2); memcpy(card->uid, card->IDm + 2, 6); memcpy(card->iccode, card->PMm, 2); @@ -389,7 +389,7 @@ bool WaitForFelicaReply(uint16_t maxbytes) { // power, no modulation FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); - NFCFrameReset(); + FelicaFrameReset(); // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; @@ -401,7 +401,7 @@ bool WaitForFelicaReply(uint16_t maxbytes) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { b = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); ProcessNFCByte(b); - if (NFCFrame.state == STATE_FULL) { + if (FelicaFrame.state == STATE_FULL) { felica_nexttransfertime = MAX( felica_nexttransfertime, @@ -410,19 +410,19 @@ bool WaitForFelicaReply(uint16_t maxbytes) { ; LogTrace( - NFCFrame.framebytes, - NFCFrame.len, + FelicaFrame.framebytes, + FelicaFrame.len, ((GetCountSspClk() & 0xfffffff8)<<4) - DELAY_AIR2ARM_AS_READER - timeout, ((GetCountSspClk() & 0xfffffff8)<<4) - DELAY_AIR2ARM_AS_READER, NULL, false ); return true; - } else if (c++ > timeout && NFCFrame.state == STATE_UNSYNCD) { + } else if (c++ > timeout && FelicaFrame.state == STATE_UNSYNCD) { return false; - } else if (NFCFrame.state == STATE_GET_CRC) { + } else if (FelicaFrame.state == STATE_GET_CRC) { Dbprintf(" Frame: "); - Dbhexdump(16, NFCFrame.framebytes, 0); + Dbhexdump(16, FelicaFrame.framebytes, 0); //return false; } } @@ -526,7 +526,7 @@ void felica_sendraw(UsbCommand *c) { TransmitFor18092_AsReader(buf, buf[2]+4, NULL, 1, 0); arg0 = !WaitForFelicaReply(1024); - cmd_send(CMD_ACK, arg0, 0, 0, NFCFrame.framebytes+2, NFCFrame.len-2); + cmd_send(CMD_ACK, arg0, 0, 0, FelicaFrame.framebytes+2, FelicaFrame.len-2); } if ((param & FELICA_NO_DISCONNECT)) @@ -566,21 +566,21 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { ProcessNFCByte(dist); //to be sure we are in frame - if (NFCFrame.state == STATE_GET_LENGTH) { + if (FelicaFrame.state == STATE_GET_LENGTH) { //length is after 48 (PRE)+16 (SYNC) - 64 ticks +maybe offset? not 100% - uint16_t distance = GetCountSspClk() - endframe - 64 + (NFCFrame.byte_offset > 0 ? (8-NFCFrame.byte_offset) : 0); + uint16_t distance = GetCountSspClk() - endframe - 64 + (FelicaFrame.byte_offset > 0 ? (8-FelicaFrame.byte_offset) : 0); *dest = distance >> 8; dest++; *dest = (distance & 0xff); dest++; } //crc NOT checked - if (NFCFrame.state == STATE_FULL) { + if (FelicaFrame.state == STATE_FULL) { endframe = GetCountSspClk(); - //*dest = NFCFrame.crc_ok; //kind of wasteful + //*dest = FelicaFrame.crc_ok; //kind of wasteful dest++; - for(int i=0; i < NFCFrame.len; i++) { - *dest = NFCFrame.framebytes[i]; + for(int i=0; i < FelicaFrame.len; i++) { + *dest = FelicaFrame.framebytes[i]; dest++; if (dest >= destend ) break; @@ -590,9 +590,9 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { if (remFrames <= 0) break; if (dest >= destend ) break; - numbts += NFCFrame.len; + numbts += FelicaFrame.len; - NFCFrameReset(); + FelicaFrameReset(); } } } @@ -621,9 +621,9 @@ void felica_sim_lite(uint64_t nfcid) { num_to_bytes(nfcid, 8, ndef); //prepare our 3 responses... - uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2,0x4d,0x12,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; - uint8_t resp_poll1[R_POLL1_LEN] = { 0xb2,0x4d,0x14,0x01,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00, 0x88,0xb4,0xb3,0x7f}; - uint8_t resp_readblk[R_READBLK_LEN] = { 0xb2,0x4d,0x1d,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x04,0x01,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x23,0xcb,0x6e}; + uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2,0x4d,0x12,FELICA_POLL_ACK,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; + uint8_t resp_poll1[R_POLL1_LEN] = { 0xb2,0x4d,0x14,FELICA_POLL_ACK,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00, 0x88,0xb4,0xb3,0x7f}; + uint8_t resp_readblk[R_READBLK_LEN] = { 0xb2,0x4d,0x1d,FELICA_RDBLK_ACK,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x04,0x01,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x23,0xcb,0x6e}; //NFC tag 3/ ISo technically. Many overlapping standards DbpString("Felica Lite-S sim start"); @@ -659,26 +659,26 @@ void felica_sim_lite(uint64_t nfcid) { //frtm = GetCountSspClk(); ProcessNFCByte(dist); - if (NFCFrame.state == STATE_FULL) { + if (FelicaFrame.state == STATE_FULL) { - if (NFCFrame.crc_ok) { + if (FelicaFrame.crc_ok) { - if (NFCFrame.framebytes[2] == 6 && NFCFrame.framebytes[3] == 0) { + if (FelicaFrame.framebytes[2] == 6 && FelicaFrame.framebytes[3] == 0) { //polling... there are two types of polling we answer to - if (NFCFrame.framebytes[6] == 0) { + if (FelicaFrame.framebytes[6] == 0) { curresp = resp_poll0; curlen = R_POLL0_LEN; listenmode = false; } - if (NFCFrame.framebytes[6] == 1) { + if (FelicaFrame.framebytes[6] == 1) { curresp = resp_poll1; curlen = R_POLL1_LEN; listenmode = true; } } - if (NFCFrame.framebytes[2] > 5 && NFCFrame.framebytes[3] == 0x06) { + if (FelicaFrame.framebytes[2] > 5 && FelicaFrame.framebytes[3] == 0x06) { //we should rebuild it depending on page size, but... //Let's see first curresp = resp_readblk; @@ -686,10 +686,10 @@ void felica_sim_lite(uint64_t nfcid) { listenmode = false; } //clear frame - NFCFrameReset(); + FelicaFrameReset(); } else { //frame invalid, clear it out to allow for the next one - NFCFrameReset(); + FelicaFrameReset(); } } } @@ -703,7 +703,7 @@ void felica_sim_lite(uint64_t nfcid) { //switch back FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD); - NFCFrameReset(); + FelicaFrameReset(); listenmode = true; curlen = 0; curresp = NULL; @@ -721,8 +721,8 @@ void felica_sim_lite(uint64_t nfcid) { void felica_dump_lite_s() { uint8_t ndef[8]; - uint8_t poll[10] = { 0xb2,0x4d,0x06,0x00,0xff,0xff,0x00,0x00,0x09,0x21}; - uint16_t liteblks[28] = {0x00, 0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x90,0x91,0x92,0xa0}; + uint8_t poll[10] = { 0xb2,0x4d,0x06,FELICA_POLL_REQ,0xff,0xff,0x00,0x00,0x09,0x21}; + uint16_t liteblks[28] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x90,0x91,0x92,0xa0}; // setup device. felica_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); @@ -740,12 +740,12 @@ void felica_dump_lite_s() { //TransmitFor18092_AsReader(poll, 10, GetCountSspClk()+512, 1, 0); TransmitFor18092_AsReader(poll, 10, NULL, 1, 0); - if (WaitForFelicaReply(512) && NFCFrame.framebytes[3] == FELICA_POLL_ACK) { + if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK) { // copy 8bytes to ndef. - memcpy(ndef, NFCFrame.framebytes + 4, 8); + memcpy(ndef, FelicaFrame.framebytes + 4, 8); // for (c=0; c < 8; c++) - // ndef[c] = NFCFrame.framebytes[c+4]; + // ndef[c] = FelicaFrame.framebytes[c+4]; for (blknum=0; blknum < sizeof(liteblks); ) { @@ -756,15 +756,15 @@ void felica_dump_lite_s() { TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, NULL, 1, 0); // read block - if (WaitForFelicaReply(1024) && NFCFrame.framebytes[3] == FELICA_RDBLK_ACK) { + if (WaitForFelicaReply(1024) && FelicaFrame.framebytes[3] == FELICA_RDBLK_ACK) { dest[cnt++] = liteblks[blknum]; - uint8_t *fb = NFCFrame.framebytes; + uint8_t *fb = FelicaFrame.framebytes; dest[cnt++] = fb[12]; dest[cnt++] = fb[13]; - //memcpy(dest+cnt, NFCFrame.framebytes + 15, 16); + //memcpy(dest+cnt, FelicaFrame.framebytes + 15, 16); //cnt += 16; for(uint8_t j=0; j < 16; j++) dest[cnt++] = fb[15+j]; @@ -773,8 +773,8 @@ void felica_dump_lite_s() { cntfails = 0; // // print raw log. - // Dbprintf("LEN %u | Dump bytes count %u ", NFCFrame.len, cnt); - Dbhexdump(NFCFrame.len, NFCFrame.framebytes+15, 0); + // Dbprintf("LEN %u | Dump bytes count %u ", FelicaFrame.len, cnt); + Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes+15, 0); } else { cntfails++; if (cntfails > 12) { From 064a163c99e521a2e64dff51ead91da4bd438234 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 6 Jan 2019 20:50:19 +0100 Subject: [PATCH 0378/1938] textual --- CHANGELOG.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 622ff0f78..6562f7bc5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Change 'hf felica list' - started with some FeliCa annotations (@iceman) + - Fix 'hf tune' - now works as expected (@iceman) - Add 'option to use flash memory to upload dictionary files' (RDV40) (@iceman) - Fix 'printing percentage now standard compliant' (@fabled) - Add 'emv roca' - command to test for ROCA vuln in public RSA modulus (@merlokk / @iceman) From c1237cfa26986558f7ac6a18f380d242331317a4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 6 Jan 2019 21:05:29 +0100 Subject: [PATCH 0379/1938] FIX: 'lg pcf7931' - improved read code (@sguerrini97) --- CHANGELOG.md | 1 + armsrc/pcf7931.c | 371 +++++++++++++++++++++++++---------------------- armsrc/pcf7931.h | 6 +- 3 files changed, 202 insertions(+), 176 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 6562f7bc5..1c7adf3a6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Change 'lf pcf7931' - improved read code (@sguerrini97) - Change 'hf felica list' - started with some FeliCa annotations (@iceman) - Fix 'hf tune' - now works as expected (@iceman) - Add 'option to use flash memory to upload dictionary files' (RDV40) (@iceman) diff --git a/armsrc/pcf7931.c b/armsrc/pcf7931.c index 8405c96ce..c9a76bb3b 100644 --- a/armsrc/pcf7931.c +++ b/armsrc/pcf7931.c @@ -3,8 +3,7 @@ #define T0_PCF 8 //period for the pcf7931 in us #define ALLOC 16 -int DemodPCF7931(uint8_t **outBlocks) { - +size_t DemodPCF7931(uint8_t **outBlocks) { uint8_t bits[256] = {0x00}; uint8_t blocks[8][16]; uint8_t *dest = BigBuf_get_addr(); @@ -18,7 +17,7 @@ int DemodPCF7931(uint8_t **outBlocks) { int tolerance = clock / 8; int pmc, block_done; int lc, warnings = 0; - int num_blocks = 0; + size_t num_blocks = 0; int lmin=128, lmax=128; uint8_t dir; //clear read buffer @@ -40,8 +39,7 @@ int DemodPCF7931(uint8_t **outBlocks) { i++; } dir = 0; - } - else { + } else { while(i < GraphTraceLen) { if( !(dest[i] < dest[i-1]) && dest[i] < lmin) break; @@ -55,10 +53,8 @@ int DemodPCF7931(uint8_t **outBlocks) { pmc = 0; block_done = 0; - for (bitidx = 0; i < GraphTraceLen; i++) - { - if ( (dest[i-1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i-1] < dest[i] && dir == 0 && dest[i] < lmin)) - { + for (bitidx = 0; i < GraphTraceLen; i++) { + if ((dest[i-1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i-1] < dest[i] && dir == 0 && dest[i] < lmin)) { lc = i - lastval; lastval = i; @@ -72,8 +68,7 @@ int DemodPCF7931(uint8_t **outBlocks) { lastval = i; pmc = 0; block_done = 1; - } - else { + } else { pmc = i; } } else if (ABS(lc-clock/2) < tolerance) { @@ -84,8 +79,7 @@ int DemodPCF7931(uint8_t **outBlocks) { lastval = i; pmc = 0; block_done = 1; - } - else if(half_switch == 1) { + } else if(half_switch == 1) { bits[bitidx++] = 0; half_switch = 0; } @@ -96,26 +90,25 @@ int DemodPCF7931(uint8_t **outBlocks) { bits[bitidx++] = 1; } else { // Error - warnings++; - if (warnings > 10) - { - Dbprintf("Error: too many detection errors, aborting..."); + if (++warnings > 10) { + Dbprintf("Error: too many detection errors, aborting."); return 0; } } if(block_done == 1) { if(bitidx == 128) { - for(j=0; j<16; j++) { - blocks[num_blocks][j] = 128*bits[j*8+7]+ + for(j = 0; j < 16; ++j) { + blocks[num_blocks][j] = + 128 * bits[j*8 + 7]+ 64*bits[j*8+6]+ 32*bits[j*8+5]+ 16*bits[j*8+4]+ 8*bits[j*8+3]+ 4*bits[j*8+2]+ 2*bits[j*8+1]+ - bits[j*8]; - + bits[j*8] + ; } num_blocks++; } @@ -135,185 +128,209 @@ int DemodPCF7931(uint8_t **outBlocks) { return num_blocks; } -int IsBlock0PCF7931(uint8_t *Block) { - // Assume RFU means 0 :) - if((memcmp(Block, "\x00\x00\x00\x00\x00\x00\x00\x01", 8) == 0) && memcmp(Block+9, "\x00\x00\x00\x00\x00\x00\x00", 7) == 0) // PAC enabled - return 1; - if((memcmp(Block+9, "\x00\x00\x00\x00\x00\x00\x00", 7) == 0) && Block[7] == 0) // PAC disabled, can it *really* happen ? - return 1; - return 0; +bool IsBlock0PCF7931(uint8_t *block) { + // assuming all RFU bits are set to 0 + // if PAC is enabled password is set to 0 + if (block[7] == 0x01) + { + if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7) && !memcmp(block+9, "\x00\x00\x00\x00\x00\x00\x00", 7)) + return true; + } + else if (block[7] == 0x00) + { + if (!memcmp(block+9, "\x00\x00\x00\x00\x00\x00\x00", 7)) + return true; + } + return false; } -int IsBlock1PCF7931(uint8_t *Block) { - // Assume RFU means 0 :) - if( Block[10] == 0 && - Block[11] == 0 && - Block[12] == 0 && - Block[13] == 0) - if ( (Block[14] & 0x7f) <= 9 && Block[15] <= 9) - return 1; - return 0; +bool IsBlock1PCF7931(uint8_t *block) { + // assuming all RFU bits are set to 0 + if (block[10] == 0 && block[11] == 0 && block[12] == 0 && block[13] == 0) + if((block[14] & 0x7f) <= 9 && block[15] <= 9) + return true; + + return false; } void ReadPCF7931() { - uint8_t Blocks[8][17]; - uint8_t tmpBlocks[4][16]; - int i, j, ind, ind2, n; - int num_blocks = 0; - int max_blocks = 8; - int ident = 0; - int error = 0; - int tries = 0; + int found_blocks = 0; // successfully read blocks + int max_blocks = 8; // readable blocks + uint8_t memory_blocks[8][17]; // PCF content + + uint8_t single_blocks[8][17]; // PFC blocks with unknown position + int single_blocks_cnt = 0; - memset(Blocks, 0, 8*17*sizeof(uint8_t)); + size_t n = 0; // transmitted blocks + uint8_t tmp_blocks[4][16]; // temporary read buffer + + uint8_t found_0_1 = 0; // flag: blocks 0 and 1 were found + int errors = 0; // error counter + int tries = 0; // tries counter + + memset(memory_blocks, 0, 8*17*sizeof(uint8_t)); + memset(single_blocks, 0, 8*17*sizeof(uint8_t)); + + int i = 0, j = 0; do { - memset(tmpBlocks, 0, 4*16*sizeof(uint8_t)); - n = DemodPCF7931((uint8_t**)tmpBlocks); + i = 0; + + memset(tmp_blocks, 0, 4*16*sizeof(uint8_t)); + n = DemodPCF7931((uint8_t**)tmp_blocks); if(!n) - error++; - if(error==10 && num_blocks == 0) { + ++errors; + + // exit if no block is received + if (errors >= 10 && found_blocks == 0 && single_blocks_cnt == 0) { Dbprintf("Error, no tag or bad tag"); return; } - else if (tries==20 || error==10) { + // exit if too many errors during reading + if (tries > 50 && (2*errors > tries)) { Dbprintf("Error reading the tag"); Dbprintf("Here is the partial content"); goto end; } - for(i=0; i= 0; ind--,ind2--) { - if(ind2 < 0) - ind2 = max_blocks; - if(!Blocks[ind2][ALLOC]) { // Block ind2 not already found - // Dbprintf("Tmp %d -> Block %d", ind, ind2); - memcpy(Blocks[ind2], tmpBlocks[ind], 16); - Blocks[ind2][ALLOC] = 1; - num_blocks++; - if(num_blocks == max_blocks) goto end; - } - } - for(ind=i+1,ind2=j+1; ind < n; ind++,ind2++) { - if(ind2 > max_blocks) - ind2 = 0; - if(!Blocks[ind2][ALLOC]) { // Block ind2 not already found - // Dbprintf("Tmp %d -> Block %d", ind, ind2); - memcpy(Blocks[ind2], tmpBlocks[ind], 16); - Blocks[ind2][ALLOC] = 1; - num_blocks++; - if(num_blocks == max_blocks) goto end; - } - } + ++tries; + continue; + } + + Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (max_blocks == 0 ? found_blocks : max_blocks), tries, errors); + + i = 0; + if(!found_0_1) { + while (i < n - 1) { + if (IsBlock0PCF7931(tmp_blocks[i]) && IsBlock1PCF7931(tmp_blocks[i+1])) { + found_0_1 = 1; + memcpy(memory_blocks[0], tmp_blocks[i], 16); + memcpy(memory_blocks[1], tmp_blocks[i+1], 16); + memory_blocks[0][ALLOC] = memory_blocks[1][ALLOC] = 1; + // block 1 tells how many blocks are going to be sent + max_blocks = MAX((memory_blocks[1][14] & 0x7f), memory_blocks[1][15]) + 1; + found_blocks = 2; + + Dbprintf("Found blocks 0 and 1. PCF is transmitting %d blocks.", max_blocks); + + // handle the following blocks + for (j = i + 2; j < n; ++j) { + memcpy(memory_blocks[found_blocks], tmp_blocks[j], 16); + memory_blocks[found_blocks][ALLOC] = 1; + ++found_blocks; + } + break; + } + ++i; + } + } else { + // Trying to re-order blocks + // Look for identical block in memory blocks + while (i < n-1) { + // skip all zeroes blocks + if (memcmp(tmp_blocks[i], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) { + for (j = 1; j < max_blocks - 1; ++j) { + if (!memcmp(tmp_blocks[i], memory_blocks[j], 16) && !memory_blocks[j+1][ALLOC]) { + memcpy(memory_blocks[j+1], tmp_blocks[i+1], 16); + memory_blocks[j+1][ALLOC] = 1; + if (++found_blocks >= max_blocks) goto end; } } } + if (memcmp(tmp_blocks[i+1], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) { + for (j = 0; j < max_blocks; ++j) { + if (!memcmp(tmp_blocks[i+1], memory_blocks[j], 16) && !memory_blocks[(j == 0 ? max_blocks : j) -1][ALLOC]) { + if (j == 0) { + memcpy(memory_blocks[max_blocks - 1], tmp_blocks[i], 16); + memory_blocks[max_blocks - 1][ALLOC] = 1; + } else { + memcpy(memory_blocks[j-1], tmp_blocks[i], 16); + memory_blocks[j-1][ALLOC] = 1; + } + if (++found_blocks >= max_blocks) goto end; + } + } + } + ++i; } } - tries++; - if (BUTTON_PRESS()) return; - } while (num_blocks != max_blocks); + ++tries; + if (BUTTON_PRESS()) { + Dbprintf("Button pressed, stopping."); + goto end; + } + } + while (found_blocks != max_blocks); + end: Dbprintf("-----------------------------------------"); Dbprintf("Memory content:"); Dbprintf("-----------------------------------------"); - for(i=0; i", i); } Dbprintf("-----------------------------------------"); + if (found_blocks < max_blocks) { + Dbprintf("-----------------------------------------"); + Dbprintf("Blocks with unknown position:"); + Dbprintf("-----------------------------------------"); + for (i = 0; i < single_blocks_cnt; ++i) + print_result("Block", single_blocks[i], 16); + + Dbprintf("-----------------------------------------"); + } cmd_send(CMD_ACK,0,0,0,0,0); } - -/* Write on a byte of a PCF7931 tag - * @param address : address of the block to write - @param byte : address of the byte to write - @param data : data to write - */ -void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) -{ +static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) { uint32_t tab[1024] = {0}; // data times frame uint32_t u = 0; uint8_t parity = 0; bool comp = 0; //BUILD OF THE DATA FRAME - //alimentation of the tag (time for initializing) AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab); - - //PMC - Dbprintf("Initialization delay : %d us", init_delay); AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab); - - Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p); - //password indication bit AddBitPCF7931(1, tab, l, p); - //password (on 56 bits) - Dbprintf("Password (LSB first on each byte) : %02x %02x %02x %02x %02x %02x %02x", pass1,pass2,pass3,pass4,pass5,pass6,pass7); - AddBytePCF7931(pass1, tab, l, p); - AddBytePCF7931(pass2, tab, l, p); - AddBytePCF7931(pass3, tab, l, p); - AddBytePCF7931(pass4, tab, l, p); - AddBytePCF7931(pass5, tab, l, p); - AddBytePCF7931(pass6, tab, l, p); - AddBytePCF7931(pass7, tab, l, p); - - + AddBytePCF7931(pass[0], tab, l, p); + AddBytePCF7931(pass[1], tab, l, p); + AddBytePCF7931(pass[2], tab, l, p); + AddBytePCF7931(pass[3], tab, l, p); + AddBytePCF7931(pass[4], tab, l, p); + AddBytePCF7931(pass[5], tab, l, p); + AddBytePCF7931(pass[6], tab, l, p); //programming mode (0 or 1) AddBitPCF7931(0, tab, l, p); //block adress on 6 bits - Dbprintf("Block address : %02x", address); - for (u=0; u<6; u++) - { + for (u = 0; u < 6; ++u) { if (address&(1< 0xFFFF){ tab[u] -= 0xFFFF; comp = 0; } } - } SendCmdPCF7931(tab); } +/* Write on a byte of a PCF7931 tag + * @param address : address of the block to write + @param byte : address of the byte to write + @param data : data to write + */ +void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) { + Dbprintf("Initialization delay : %d us", init_delay); + Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p); + Dbprintf("Password (LSB first on each byte): %02x %02x %02x %02x %02x %02x %02x", pass1, pass2, pass3, pass4, pass5, pass6, pass7); + Dbprintf("Block address : %02x", address); + Dbprintf("Byte address : %02x", byte); + Dbprintf("Data : %02x", data); + + uint8_t password[7] = {pass1, pass2, pass3, pass4, pass5, pass6, pass7}; + + RealWritePCF7931 (password, init_delay, l, p, address, byte, data); +} /* Send a trame to a PCF7931 tags @@ -386,9 +414,7 @@ void SendCmdPCF7931(uint32_t * tab){ Dbprintf("Sending data frame..."); FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU ); LED_A_ON(); @@ -405,21 +431,22 @@ void SendCmdPCF7931(uint32_t * tab){ AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN; AT91C_BASE_TCB->TCB_BCR = 1; - tempo = AT91C_BASE_TC0->TC_CV; for( u = 0; tab[u] != 0; u += 3){ - // modulate antenna HIGH(GPIO_SSC_DOUT); - while(tempo != tab[u]) tempo = AT91C_BASE_TC0->TC_CV; + while (tempo != tab[u]) + tempo = AT91C_BASE_TC0->TC_CV; // stop modulating antenna LOW(GPIO_SSC_DOUT); - while(tempo != tab[u+1]) tempo = AT91C_BASE_TC0->TC_CV; + while (tempo != tab[u+1]) + tempo = AT91C_BASE_TC0->TC_CV; // modulate antenna HIGH(GPIO_SSC_DOUT); - while(tempo != tab[u+2]) tempo = AT91C_BASE_TC0->TC_CV; + while (tempo != tab[u+2]) + tempo = AT91C_BASE_TC0->TC_CV; } LED_A_OFF(); @@ -437,18 +464,16 @@ void SendCmdPCF7931(uint32_t * tab){ * @param l : offset on low pulse width * @param p : offset on low pulse positioning */ - bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){ - uint32_t u; - for ( u=0; u<8; u++) - { - if (byte&(1< Date: Mon, 7 Jan 2019 09:32:16 +0100 Subject: [PATCH 0380/1938] CHG: 'hf 14a antifuzz' - original implementation by @asfabw, reworked a bit - WORK IN PROGRESS - --- armsrc/iso14443a.c | 146 ++++++++++++++++++++++----------------------- armsrc/iso14443a.h | 2 + client/cmdhf14a.c | 29 ++++++--- 3 files changed, 92 insertions(+), 85 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 20225f416..91db762fc 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -14,7 +14,10 @@ #define MAX_ISO14A_TIMEOUT 524288 static uint32_t iso14a_timeout; +uint8_t colpos = 0; int rsamples = 0; +//int ReqCount; +//char CollisionIndicators[10*8]; uint8_t trigger = 0; // the block number for the ISO14443-4 PCB @@ -103,6 +106,8 @@ static uint32_t LastProxToAirDuration; // Sequence D: 11110000 modulation with subcarrier during first half // Sequence E: 00001111 modulation with subcarrier during second half // Sequence F: 00000000 no modulation with subcarrier +// Sequence COLL: 11111111 load modulation over the full bitlenght. +// Tricks the reader to think that multiple cards answer (at least one card with 1 and at least one card with 0). // READER TO CARD - miller // Sequence X: 00001100 drop after half a period // Sequence Y: 00000000 no drop @@ -110,6 +115,7 @@ static uint32_t LastProxToAirDuration; #define SEC_D 0xf0 #define SEC_E 0x0f #define SEC_F 0x00 +#define SEC_COLL 0xff #define SEC_X 0x0c #define SEC_Y 0x00 #define SEC_Z 0xc0 @@ -643,7 +649,9 @@ void RAMFUNC SniffIso14443a(uint8_t param) { //----------------------------------------------------------------------------- // Prepare tag messages //----------------------------------------------------------------------------- -static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *parity) { +static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *parity, bool collision) { + + uint8_t localCol = 0; ToSendReset(); // Correction bit, might be removed when not needed @@ -651,7 +659,7 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par ToSendStuffBit(0); ToSendStuffBit(0); ToSendStuffBit(0); - ToSendStuffBit(1); // 1 + ToSendStuffBit(1); // <----- ToSendStuffBit(0); ToSendStuffBit(0); ToSendStuffBit(0); @@ -665,12 +673,15 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par // Data bits for(uint16_t j = 0; j < 8; j++) { - if(b & 1) { + if (collision && (localCol >= colpos)){ + ToSend[++ToSendMax] = SEC_COLL; + } else if(b & 1) { ToSend[++ToSendMax] = SEC_D; } else { ToSend[++ToSendMax] = SEC_E; } b >>= 1; + localCol++; } // Get the parity bit @@ -690,10 +701,13 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par ToSendMax++; } -static void CodeIso14443aAsTag(const uint8_t *cmd, uint16_t len) { +static void CodeIso14443aAsTagEx(const uint8_t *cmd, uint16_t len, bool collision) { uint8_t par[MAX_PARITY_SIZE] = {0}; GetParity(cmd, len, par); - CodeIso14443aAsTagPar(cmd, len, par); + CodeIso14443aAsTagPar(cmd, len, par, collision); +} +static void CodeIso14443aAsTag(const uint8_t *cmd, uint16_t len) { + CodeIso14443aAsTagEx(cmd, len, false); } static void Code4bitAnswerAsTag(uint8_t cmd) { @@ -1680,9 +1694,11 @@ int EmSend4bit(uint8_t resp){ par); return res; } - -int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par){ - CodeIso14443aAsTagPar(resp, respLen, par); +int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par) { + return EmSendCmdParEx(resp, respLen, par, false); +} +int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool collision){ + CodeIso14443aAsTagPar(resp, respLen, par, collision); int res = EmSendCmd14443aRaw(ToSend, ToSendMax); // do the tracing for the previous reader request and this tag answer: EmLogTrace(Uart.output, @@ -1697,11 +1713,13 @@ int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par){ par); return res; } - int EmSendCmd(uint8_t *resp, uint16_t respLen){ + return EmSendCmdEx(resp, respLen, false); +} +int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool collision){ uint8_t par[MAX_PARITY_SIZE] = {0x00}; GetParity(resp, respLen, par); - return EmSendCmdPar(resp, respLen, par); + return EmSendCmdParEx(resp, respLen, par, collision); } bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity, @@ -1805,45 +1823,21 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity) { // by fooling the reader there is a collision and forceing the reader to // increase the uid bytes. The might be an overflow, DoS will occure. void iso14443a_antifuzz(uint32_t flags){ - /* - uint8_t uidlen = 4+1+1+2; - if (( flags & 2 ) == 2 ) - uidlen = 7+1+1+2; - if (( flags & 4 ) == 4 ) - uidlen = 10+1+1+2; - - uint8_t *uid = BigBuf_malloc(uidlen); - - // The first response contains the ATQA (note: bytes are transmitted in reverse order). - // Mifare Classic 1K - uint8_t atqa[] = {0x04, 0}; - - if ( (flags & 2) == 2 ) { - uid[0] = 0x88; // Cascade Tag marker - uid[1] = 0x01; - - // Configure the ATQA accordingly - atqa[0] |= 0x40; - } else { - memcpy(response2, data, 4); - // Configure the ATQA accordingly - atqa[0] &= 0xBF; - } // We need to listen to the high-frequency, peak-detected path. iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); - // allocate buffers: - uint8_t *received = BigBuf_malloc(MAX_FRAME_SIZE); - uint8_t *receivedPar = BigBuf_malloc(MAX_PARITY_SIZE); - uint16_t counter = 0; - - int len = 0; - - BigBuf_free(); + BigBuf_free_keep_EM(); clear_trace(); set_tracing(true); + int len = 0; + + // allocate buffers: + uint8_t *received = BigBuf_malloc(MAX_FRAME_SIZE); + uint8_t *receivedPar = BigBuf_malloc(MAX_PARITY_SIZE); + uint8_t *resp = BigBuf_malloc(8); + LED_A_ON(); for (;;) { WDT_HIT(); @@ -1853,47 +1847,47 @@ void iso14443a_antifuzz(uint32_t flags){ Dbprintf("Anti-fuzz stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); break; } - p_response = NULL; + if ( received[0] == ISO14443A_CMD_WUPA || received[0] == ISO14443A_CMD_REQA) { + resp[0] = 0x04; + resp[1] = 0x00; + + if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA ) { + resp[0] = 0x44; + } + + EmSendCmd(resp, 2); + continue; + } - // look at the command now. - if (received[0] == ISO14443A_CMD_REQA) { // Received a REQUEST - p_response = &responses[0]; - } else if (received[0] == ISO14443A_CMD_WUPA) { // Received a WAKEUP - p_response = &responses[0]; - } else if (received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received request for UID (cascade 1) - p_response = &responses[1]; - } else if (received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received request for UID (cascade 2) - p_response = &responses[2]; - } else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received a SELECT (cascade 1) - p_response = &responses[3]; - } else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received a SELECT (cascade 2) - p_response = &responses[4]; - } - if (p_response != NULL) { + // Received request for UID (cascade 1) + if (received[1] >= 0x20 && received[1] <= 0x57 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { + resp[0] = 0x04; + resp[1] = 0x1C; + resp[2] = 0xE1; + resp[3] = 0xCE; + colpos = 0; - EmSendCmd14443aRaw(p_response->modulation, p_response->modulation_n); - // do the tracing for the previous reader request and this tag answer: - uint8_t par[MAX_PARITY_SIZE] = {0x00}; - GetParity(p_response->response, p_response->response_n, par); + if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA ) { + resp[0] = 0x88; + colpos = 8; + } - EmLogTrace(Uart.output, - Uart.len, - Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.parity, - p_response->response, - p_response->response_n, - LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, - (LastTimeProxToAirStart + p_response->ProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, - par); + EmSendCmdEx(resp, 4, true); + if (MF_DBGLEVEL >= 4) Dbprintf("ANTICOLL or SELECT %x", received[1]); + + continue; + } else if (received[1] == 0x20 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received request for UID (cascade 2) + if (MF_DBGLEVEL >= 4) Dbprintf("ANTICOLL or SELECT_2"); + } else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received a SELECT (cascade 1) + } else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received a SELECT (cascade 2) + } else { + Dbprintf("unknown command %x", received[0]); } - counter++; } cmd_send(CMD_ACK,1,0,0,0,0); - switch_off(); - Dbprintf("-[ UID until no response [%d]", counter); -*/ + switch_off(); + BigBuf_free_keep_EM(); } static void iso14a_set_ATS_times(uint8_t *ats) { diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index ff34fa577..7f979e531 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -122,8 +122,10 @@ extern void iso14a_set_trigger(bool enable); extern int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen); extern int EmSend4bit(uint8_t resp); extern int EmSendCmd(uint8_t *resp, uint16_t respLen); +extern int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool collision); extern int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity); extern int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par); +extern int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool collision); extern int EmSendPrecompiledCmd(tag_response_info_t *response_info); bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity, diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index b9d7bfcae..43832e2cf 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -213,11 +213,6 @@ int usage_hf_14a_info(void){ PrintAndLogEx(NORMAL, " n test for nack bug"); return 0; } -int usage_hf_14a_antifuzz(void) { - PrintAndLogEx(NORMAL, "Usage: hf 14a antifuzz [4|7|10]"); - PrintAndLogEx(NORMAL, " determine which anticollision phase the command will target."); - return 0; -} int CmdHF14AList(const char *Cmd) { //PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list 14a' instead"); @@ -1183,11 +1178,27 @@ static int waitCmd(uint8_t iSelect) { int CmdHF14AAntiFuzz(const char *cmd) { - if (strlen(cmd) < 1) return usage_hf_14a_antifuzz(); + CLIParserInit("hf 14a antifuzz", + "Tries to fuzz the ISO14443a anticollision phase", + "Usage:\n" + "\thf 14a antifuzz -4\n"); - // read param length - uint8_t arg0 = 4; - + void* argtable[] = { + arg_param_begin, + arg_lit0("4", NULL, "4 byte uid"), + arg_lit0("7", NULL, "7 byte uid"), + arg_lit0(NULL, "10", "10 byte uid"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, false); + + uint8_t arg0 = FLAG_4B_UID_IN_DATA; + if (arg_get_lit(2)) + arg0 = FLAG_7B_UID_IN_DATA; + if (arg_get_lit(3)) + arg0 = FLAG_10B_UID_IN_DATA; + + CLIParserFree(); UsbCommand c = {CMD_ANTIFUZZ_ISO_14443a, {arg0, 0, 0}}; clearCommandBuffer(); SendCommand(&c); From 5a34550ac5b4e490e99f542ec28be6606e1a2f20 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 7 Jan 2019 17:49:09 +0100 Subject: [PATCH 0381/1938] CHG: printing --- client/comms.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/comms.c b/client/comms.c index 3c2b353b3..5beaa0adb 100644 --- a/client/comms.c +++ b/client/comms.c @@ -178,7 +178,7 @@ static void UsbCommandReceived(UsbCommand* c) { break; } case CMD_DEBUG_PRINT_INTEGERS: { - PrintAndLogEx(NORMAL, "#db# %08x, %08x, %08x", c->arg[0], c->arg[1], c->arg[2]); + PrintAndLogEx(NORMAL, "#db# %" PRIx64 ", %" PRIx64 ", %" PRIx64 "", c->arg[0], c->arg[1], c->arg[2]); break; } // iceman: hw status - down the path on device, runs printusbspeed which starts sending a lot of From 04893371bc61c9a4f4c98262ec6cc331d3fb1688 Mon Sep 17 00:00:00 2001 From: Iceman Date: Tue, 8 Jan 2019 00:05:00 +0100 Subject: [PATCH 0382/1938] Update README.md --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index fdf02f0a2..4a4503b94 100644 --- a/README.md +++ b/README.md @@ -49,7 +49,8 @@ This fork now compiles just fine on ## KALI and ARCHLINUX users Kali and ArchLinux users usually must kill their modem manager in order for the proxmark3 to enumerate properly. - +`sudo apt remove modemmanager` + ## Setup and build for UBUNTU GC made updates to allow this to build easily on Ubuntu 14.04.2 LTS, 15.10 or 16.04 See https://github.com/Proxmark/proxmark3/wiki/Ubuntu%20Linux @@ -88,6 +89,9 @@ https://github.com/RfidResearchGroup/proxmark3/blob/master/install.sh `sudo pacman -Sy base-devel p7zip libusb readline ncurses libjansson-dev arm-none-eabi-newlib --needed` `yaourt -S termcap` +- Remove modemmanager +`sudo apt remove modemmanager` + - Clone fork `git clone https://github.com/RfidResearchGroup/proxmark3.git` From 7271d5afc90bfb1439c6e5c45066b9df5700bd54 Mon Sep 17 00:00:00 2001 From: Iceman Date: Tue, 8 Jan 2019 00:36:33 +0100 Subject: [PATCH 0383/1938] Update README.md --- README.md | 69 +++++++++++++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 65 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 4a4503b94..94f7b94d6 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ The new universial GUI will work. ## Development This fork now compiles just fine on - Windows/mingw environment with Qt5.6.1 & GCC 4.8 - - Ubuntu 1404, 1510, 1604 + - Ubuntu 1404, 1510, 1604, 1804 - Mac OS X / Homebrew - Docker container @@ -159,7 +159,7 @@ Links - https://github.com/Gator96100/ProxSpace/releases/tag/v2.2 (release v2.2 with gcc v5.3.0 arm-none-eabi-gcc v7.1.0) -### 7. Build and run +### Build and run - Clone fork `git clone https://github.com/RfidResearchGroup/proxmark3.git` @@ -181,5 +181,66 @@ Assuming you have Proxmark3 Windows drivers installed you can run the Proxmark s - Run the client `proxmark3.exe comX` -iceman at host iuse.se -July 2018, Sweden + +## Validating proxmark client functionality + +If all went well you should get some information about the firmware and memory usage as well as the prompt, something like this. + +>[=] UART Setting serial baudrate 460800 +> +>Proxmark3 RFID instrument +> +> [ CLIENT ] +> +> client: iceman build for RDV40 with flashmem; smartcard; +> +> [ ARM ] +> +> bootrom: iceman/master/4517531c-dirty-unclean 2018-12-13 15:42:24 +> +> os: iceman/master/5a34550a-dirty-unclean 2019-01-07 23:04:07 +> +> [ FPGA ] +> +> LF image built for 2s30vq100 on 2018/ 9/ 8 at 13:57:51 +> +> HF image built for 2s30vq100 on 2018/ 9/ 3 at 21:40:23 +> +> [ Hardware ] +> +>--= uC: AT91SAM7S512 Rev B +> +>--= Embedded Processor: ARM7TDMI +> +>--= Nonvolatile Program Memory Size: 512K bytes, Used: 247065 bytes (47%) Free: 277223 bytes (53%) +> +>--= Second Nonvolatile Program Memory Size: None +> +>--= Internal SRAM Size: 64K bytes +> +>--= Architecture Identifier: AT91SAM7Sxx Series +> +>--= Nonvolatile Program Memory Type: Embedded Flash Memory +> +> pm3 --> + +### run the following commands + pm3 --> hw status + pm3 --> hw version + pm3 --> hw tune + +You are now ready to use your newly upgraded proxmark3 device. Many commands uses the **h** parameter to show a help text. The client uses a arcaic command structure which will be hard to grasp at first. Here are some commands to start off with. + + pm3 --> hf + pm3 --> hf 14a info + pm3 --> lf + pm3 --> lf search + +### Quit client + pm3 --> quit + + +## the end + +`iceman at host iuse.se` +`July 2018, Sweden` From 9b7089e71f8ce14353a7239bdedaee3b5cf08967 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 8 Jan 2019 02:16:39 +0100 Subject: [PATCH 0384/1938] FIX: remove warning of overwriting --- client/ui.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/ui.c b/client/ui.c index 868545833..a0151a8db 100644 --- a/client/ui.c +++ b/client/ui.c @@ -48,10 +48,10 @@ void PrintAndLogEx(logLevel_t level, char *fmt, ...) { // skip debug messages if client debugging is turned off i.e. 'DATA SETDEBUG 0' if (g_debugMode == 0 && level == DEBUG) return; - + + char prefix[20] = {0}; char buffer[MAX_PRINT_BUFFER] = {0}; - char buffer2[MAX_PRINT_BUFFER] = {0}; - char prefix[20] = {0}; + char buffer2[MAX_PRINT_BUFFER+20] = {0}; char *token = NULL; int size = 0; // {NORMAL, SUCCESS, INFO, FAILED, WARNING, ERR, DEBUG} From 2d5d8c130d9d83276ecf48a6e81fae9d081478c1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 8 Jan 2019 02:22:41 +0100 Subject: [PATCH 0385/1938] chg: 'hf list 14a' - another 7bit command 0x35 --- client/cmdhflist.c | 1 + common/protocols.h | 1 + 2 files changed, 2 insertions(+) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index e4a7e27b4..7791c5e53 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -159,6 +159,7 @@ int applyIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { MifareAuthState = masNone; break; case ISO14443A_CMD_RATS: snprintf(exp,size,"RATS"); break; + case ISO14443A_CMD_OPTS: snprintf(exp,size,"OPTIONAL TIMESLOT"); break; case MIFARE_CMD_INC: snprintf(exp,size,"INC(%d)",cmd[1]); break; case MIFARE_CMD_DEC: snprintf(exp,size,"DEC(%d)",cmd[1]); break; case MIFARE_CMD_RESTORE: snprintf(exp,size,"RESTORE(%d)",cmd[1]); break; diff --git a/common/protocols.h b/common/protocols.h index 8db1d481e..9696c73e0 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -144,6 +144,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define ISO14443A_CMD_REQA 0x26 #define ISO14443A_CMD_READBLOCK 0x30 #define ISO14443A_CMD_WUPA 0x52 +#define ISO14443A_CMD_OPTS 0x35 #define ISO14443A_CMD_ANTICOLL_OR_SELECT 0x93 #define ISO14443A_CMD_ANTICOLL_OR_SELECT_2 0x95 #define ISO14443A_CMD_ANTICOLL_OR_SELECT_3 0x97 From 699a3b71524027bf712a30abdb7af2ea056294c8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 8 Jan 2019 02:23:06 +0100 Subject: [PATCH 0386/1938] FIX: remove overwriting warning --- client/jansson/load.c | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/client/jansson/load.c b/client/jansson/load.c index 8700919fd..9f73ea02c 100644 --- a/client/jansson/load.c +++ b/client/jansson/load.c @@ -89,7 +89,7 @@ static void error_set(json_error_t *error, const lex_t *lex, { va_list ap; char msg_text[JSON_ERROR_TEXT_LENGTH]; - char msg_with_context[JSON_ERROR_TEXT_LENGTH]; + char msg_with_context[JSON_ERROR_TEXT_LENGTH + 20]; int line = -1, col = -1; size_t pos = 0; @@ -114,9 +114,8 @@ static void error_set(json_error_t *error, const lex_t *lex, if(saved_text && saved_text[0]) { if(lex->saved_text.length <= 20) { - snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, - "%s near '%s'", msg_text, saved_text); - msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0'; + snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near '%s'", msg_text, saved_text); + msg_with_context[JSON_ERROR_TEXT_LENGTH + 20 - 1] = '\0'; result = msg_with_context; } } @@ -131,9 +130,8 @@ static void error_set(json_error_t *error, const lex_t *lex, result = msg_text; } else { - snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, - "%s near end of file", msg_text); - msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0'; + snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near end of file", msg_text); + msg_with_context[JSON_ERROR_TEXT_LENGTH + 20 - 1] = '\0'; result = msg_with_context; } } From dac30911a3d69a4c6cd02dd4e774493d465f7e42 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 8 Jan 2019 10:56:56 +0100 Subject: [PATCH 0387/1938] FIX: remove gcc8.2 warnings --- client/cmdhfmf.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index d92b2a1d4..985965d72 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -894,9 +894,9 @@ int CmdHF14AMfRestore(const char *Cmd) { uint8_t keyB[40][6]; uint8_t numSectors = 16; uint8_t cmdp = 0; - char keyFilename[FILE_PATH_SIZE]=""; - char dataFilename[FILE_PATH_SIZE]=""; - char szTemp[FILE_PATH_SIZE]=""; + char keyFilename[FILE_PATH_SIZE] = ""; + char dataFilename[FILE_PATH_SIZE] = ""; + char szTemp[FILE_PATH_SIZE-20] = ""; char *fptr; FILE *fdump, *fkeys; @@ -905,7 +905,7 @@ int CmdHF14AMfRestore(const char *Cmd) { case 'h': return usage_hf14_restore(); case 'u': - param_getstr(Cmd, cmdp+1, szTemp, FILE_PATH_SIZE); + param_getstr(Cmd, cmdp+1, szTemp, FILE_PATH_SIZE-20); if(keyFilename[0]==0x00) snprintf(keyFilename, FILE_PATH_SIZE, "hf-mf-%s-key.bin", szTemp); if(dataFilename[0]==0x00) @@ -1280,7 +1280,7 @@ int CmdHF14AMfNestedHard(const char *Cmd) { uint8_t trgkey[6] = {0, 0, 0, 0, 0, 0}; uint8_t cmdp=0; char filename[FILE_PATH_SIZE], *fptr; - char szTemp[FILE_PATH_SIZE]; + char szTemp[FILE_PATH_SIZE-20]; char ctmp; bool know_target_key = false; @@ -1370,13 +1370,13 @@ int CmdHF14AMfNestedHard(const char *Cmd) { strncpy(filename, fptr, FILE_PATH_SIZE); break; case 'u': - param_getstr(Cmd, cmdp+1, szTemp, FILE_PATH_SIZE); + param_getstr(Cmd, cmdp+1, szTemp, FILE_PATH_SIZE-20); snprintf(filename, FILE_PATH_SIZE, "hf-mf-%s-nonces.bin", szTemp); cmdp++; break; case 'f': - param_getstr(Cmd, cmdp+1, szTemp, FILE_PATH_SIZE); - strncpy(filename, szTemp, FILE_PATH_SIZE); + param_getstr(Cmd, cmdp+1, szTemp, FILE_PATH_SIZE-20); + strncpy(filename, szTemp, FILE_PATH_SIZE-20); cmdp++; break; case 'i': From a17bf8e5592c8336a155b5dc4dd016fa0d08b192 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 8 Jan 2019 11:20:42 +0100 Subject: [PATCH 0388/1938] FIX: remove gcc8.2 warning --- client/util.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/util.c b/client/util.c index 22490f62a..5d7ce0370 100644 --- a/client/util.c +++ b/client/util.c @@ -313,11 +313,11 @@ char *sprint_hex_ascii(const uint8_t *data, const size_t len) { memset(buf, 0x00, UTIL_BUFFER_SIZE_SPRINT); size_t max_len = (len > 1010) ? 1010 : len; - sprintf(tmp, "%s| ", sprint_hex(data, max_len) ); + snprintf(tmp, UTIL_BUFFER_SIZE_SPRINT, "%s| ", sprint_hex(data, max_len) ); size_t i = 0; - size_t pos = (max_len * 3)+2; - while(i < max_len){ + size_t pos = (max_len * 3) + 2; + while (i < max_len){ char c = data[i]; if ( (c < 32) || (c == 127)) c = '.'; From 11e0c09fdd6e2991f96515c3b7f9f9623686a7fa Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 8 Jan 2019 16:48:04 +0100 Subject: [PATCH 0389/1938] CHG: more definitions --- client/emv/emv_tags.c | 150 ++++++++++++++++++++++++++++++++++++++---- 1 file changed, 137 insertions(+), 13 deletions(-) diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index 74a37aba6..521598b67 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -175,7 +175,8 @@ static const struct emv_tag emv_tags[] = { // internal { 0x00 , "Unknown ???" }, { 0x01 , "", EMV_TAG_STRING }, // string for headers - { 0x02 , "Raw data", }, // data + { 0x02 , "Raw data" }, // data + { 0x06 , "Object Identifier (OID)" }, { 0x20 , "Cardholder Verification Results (CVR)", EMV_TAG_CVR }, // not standard! { 0x21 , "Input list for Offline Data Authentication" }, // not standard! data for "Offline Data Authentication" come from "read records" command. (EMV book3 10.3) @@ -184,6 +185,9 @@ static const struct emv_tag emv_tags[] = { { 0x42 , "Issuer Identification Number (IIN)" }, { 0x4f , "Application Dedicated File (ADF) Name" }, { 0x50 , "Application Label", EMV_TAG_STRING }, + { 0x51 , "File reference data element" }, + { 0x52 , "Command APDU" }, + { 0x53 , "Discretionary data (or template)" }, { 0x56 , "Track 1 Data" }, { 0x57 , "Track 2 Equivalent Data" }, { 0x5a , "Application Primary Account Number (PAN)" }, @@ -195,6 +199,13 @@ static const struct emv_tag emv_tags[] = { { 0x5f2d, "Language Preference", EMV_TAG_STRING }, { 0x5f30, "Service Code", EMV_TAG_NUMERIC }, { 0x5f34, "Application Primary Account Number (PAN) Sequence Number", EMV_TAG_NUMERIC }, + { 0x5f36, "Transaction Currency Exponent", EMV_TAG_NUMERIC }, + { 0x5f50, "Issuer URL", EMV_TAG_STRING }, + { 0x5f53, "International Bank Account Number (IBAN)" }, + { 0x5f54, "Bank Identifier Code (BIC)" }, + { 0x5f55, "Issuer Country Code (alpha2 format)", EMV_TAG_STRING }, + { 0x5f56, "Issuer Country Code (alpha3 format)", EMV_TAG_STRING }, + { 0x61 , "Application Template" }, { 0x6f , "File Control Information (FCI) Template" }, { 0x70 , "READ RECORD Response Message Template" }, @@ -203,11 +214,14 @@ static const struct emv_tag emv_tags[] = { { 0x73 , "Directory Discretionary Template" }, { 0x77 , "Response Message Template Format 2" }, { 0x80 , "Response Message Template Format 1" }, + { 0x81 , "Amount, Authorised (Binary)" }, { 0x82 , "Application Interchange Profile", EMV_TAG_BITMASK, &EMV_AIP }, { 0x83 , "Command Template" }, { 0x84 , "Dedicated File (DF) Name" }, + { 0x86 , "Issuer Script Command" }, { 0x87 , "Application Priority Indicator" }, { 0x88 , "Short File Identifier (SFI)" }, + { 0x89 , "Authorisation Code" }, { 0x8a , "Authorisation Response Code" }, { 0x8c , "Card Risk Management Data Object List 1 (CDOL1)", EMV_TAG_DOL }, { 0x8d , "Card Risk Management Data Object List 2 (CDOL2)", EMV_TAG_DOL }, @@ -219,14 +233,25 @@ static const struct emv_tag emv_tags[] = { { 0x93 , "Signed Static Application Data" }, { 0x94 , "Application File Locator (AFL)", EMV_TAG_AFL }, { 0x95 , "Terminal Verification Results" }, + { 0x97 , "Transaction Certificate Data Object List (TDOL)" }, + { 0x98 , "Transaction Certificate (TC) Hash Value" }, + { 0x99 , "Transaction Personal Identification Number (PIN) Data" }, { 0x9a , "Transaction Date", EMV_TAG_YYMMDD }, - { 0x9c , "Transaction Type" }, + { 0x9b , "Transaction Status Information" }, + { 0x9c , "Transaction Type", EMV_TAG_NUMERIC }, + { 0x9d , "Directory Definition File (DDF) Name" }, + + { 0x9f01, "Acquirer Identifier", EMV_TAG_NUMERIC }, { 0x9f02, "Amount, Authorised (Numeric)", EMV_TAG_NUMERIC }, - { 0x9f03, "Amount, Other (Numeric)", EMV_TAG_NUMERIC, }, + { 0x9f03, "Amount, Other (Numeric)", EMV_TAG_NUMERIC }, + { 0x9f04, "Amount, Other (Binary)", EMV_TAG_NUMERIC }, + { 0x9f05, "Application Discretionary Data" }, { 0x9f06, "Application Identifier (AID), Terminal. ISO 7816-5" }, { 0x9f07, "Application Usage Control", EMV_TAG_BITMASK, &EMV_AUC }, { 0x9f08, "Application Version Number" }, + { 0x9f09, "Application Version Number - terminal" }, { 0x9f0a, "Application Selection Registered Proprietary Data" }, // https://blog.ul-ts.com/posts/electronic-card-identifier-one-more-step-for-mif-compliance/ + { 0x9f0b, "Cardholder Name Extended", EMV_TAG_STRING }, { 0x9f0d, "Issuer Action Code - Default", EMV_TAG_BITMASK, &EMV_TVR }, { 0x9f0e, "Issuer Action Code - Denial", EMV_TAG_BITMASK, &EMV_TVR }, { 0x9f0f, "Issuer Action Code - Online", EMV_TAG_BITMASK, &EMV_TVR }, @@ -234,11 +259,21 @@ static const struct emv_tag emv_tags[] = { { 0x9f11, "Issuer Code Table Index", EMV_TAG_NUMERIC }, { 0x9f12, "Application Preferred Name", EMV_TAG_STRING }, { 0x9f13, "Last Online Application Transaction Counter (ATC) Register" }, + { 0x9f14, "Lower Consecutive Offline Limit" }, + { 0x9f15, "Merchant Category Code", EMV_TAG_NUMERIC }, + { 0x9f16, "Merchant Identifier", EMV_TAG_STRING }, { 0x9f17, "Personal Identification Number (PIN) Try Counter" }, + { 0x9f18, "Issuer Script Identifier" }, { 0x9f1a, "Terminal Country Code" }, + { 0x9f1b, "Terminal Floor Limit" }, + { 0x9f1c, "Terminal Identification", EMV_TAG_STRING }, + { 0x9f1d, "Terminal Risk Management Data" }, + { 0x9f1e, "Interface Device (IFD) Serial Number", EMV_TAG_STRING }, { 0x9f1f, "Track 1 Discretionary Data", EMV_TAG_STRING }, { 0x9f20, "Track 2 Discretionary Data", EMV_TAG_STRING }, - { 0x9f21, "Transaction Time" }, + { 0x9f21, "Transaction Time" }, + { 0x9f22, "Certification Authority Public Key Index - Terminal" }, + { 0x9f23, "Upper Consecutive Offline Limit" }, { 0x9f26, "Application Cryptogram" }, { 0x9f27, "Cryptogram Information Data", EMV_TAG_CID }, { 0x9f2a, "Kernel Identifier" }, @@ -246,12 +281,21 @@ static const struct emv_tag emv_tags[] = { { 0x9f2e, "ICC PIN Encipherment Public Key Exponent" }, { 0x9f2f, "ICC PIN Encipherment Public Key Remainder" }, { 0x9f32, "Issuer Public Key Exponent" }, + { 0x9f33, "Terminal Capabilities" }, { 0x9f34, "Cardholder Verification Method (CVM) Results" }, { 0x9f35, "Terminal Type" }, { 0x9f36, "Application Transaction Counter (ATC)" }, { 0x9f37, "Unpredictable Number" }, { 0x9f38, "Processing Options Data Object List (PDOL)", EMV_TAG_DOL }, + { 0x9f39, "Point-of-Service (POS) Entry Mode", EMV_TAG_NUMERIC }, + { 0x9f3a, "Amount, Reference Currency" }, + { 0x9f3b, "Application Reference Currency", EMV_TAG_NUMERIC }, + { 0x9f3c, "Transaction Reference Currency Code", EMV_TAG_NUMERIC }, + { 0x9f3d, "Transaction Reference Currency Exponent", EMV_TAG_NUMERIC }, + { 0x9f40, "Additional Terminal Capabilities" }, + { 0x9f41, "Transaction Sequence Counter", EMV_TAG_NUMERIC }, { 0x9f42, "Application Currency Code", EMV_TAG_NUMERIC }, + { 0x9f43, "Application Reference Currency Exponent", EMV_TAG_NUMERIC }, { 0x9f44, "Application Currency Exponent", EMV_TAG_NUMERIC }, { 0x9f45, "Data Authentication Code" }, { 0x9f46, "ICC Public Key Certificate" }, @@ -262,14 +306,22 @@ static const struct emv_tag emv_tags[] = { { 0x9f4b, "Signed Dynamic Application Data" }, { 0x9f4c, "ICC Dynamic Number" }, { 0x9f4d, "Log Entry" }, + { 0x9f4e, "Merchant Name and Location", EMV_TAG_STRING }, { 0x9f4f, "Log Format", EMV_TAG_DOL }, { 0x9f50, "Offline Accumulator Balance" }, { 0x9f51, "Application Currency Code" }, { 0x9f51, "DRDOL" }, + { 0x9f52, "Application Default Action (ADA)" }, { 0x9f52, "Terminal Compatibility Indicator" }, + + { 0x9f53, "Transaction Category Code" }, + { 0x9f54, "DS ODS Card" }, + + { 0x9f55, "Mobile Support Indicator" }, { 0x9f55, "Issuer Authentication Flags" }, + { 0x9f56, "Issuer Authentication Indicator" }, { 0x9f57, "Issuer Country Code" }, { 0x9f58, "Consecutive Transaction Counter Limit (CTCL)" }, @@ -277,27 +329,99 @@ static const struct emv_tag emv_tags[] = { { 0x9f5A, "Application Program Identifier" }, { 0x9f5b, "Issuer Script Results" }, { 0x9f5c, "Cumulative Total Transaction Amount Upper Limit (CTTAUL)" }, + { 0x9f5d, "Application Capabilities Information" }, + { 0x9f5e, "Data Storage Identifier" }, + { 0x9f5f, "DS Slot Availability" }, { 0x9f60, "CVC3 (Track1)" }, { 0x9f61, "CVC3 (Track2)" }, - { 0x9f62, "PCVC3(Track1)" }, - { 0x9f63, "PUNATC(Track1)" }, - { 0x9f64, "NATC(Track1)" }, - { 0x9f65, "PCVC3(Track2)" }, - { 0x9f66, "PUNATC(Track2) / Terminal Transaction Qualifiers (TTQ)", EMV_TAG_BITMASK, &EMV_TTQ }, - { 0x9f67, "NATC(Track2) / MSD Offset" }, + { 0x9f62, "PCVC3 (Track1)" }, + { 0x9f63, "PUNATC (Track1)" }, + { 0x9f64, "NATC (Track1)" }, + { 0x9f65, "PCVC3 (Track2)" }, + { 0x9f66, "PUNATC (Track2) / Terminal Transaction Qualifiers (TTQ)", EMV_TAG_BITMASK, &EMV_TTQ }, + { 0x9f67, "NATC (Track2) / MSD Offset" }, { 0x9f68, "Cardholder verification method list (PayPass)" }, - { 0x9f69, "Card Authentication Related Data" }, + { 0x9f69, "Card Authentication Related Data (UDOL)" }, { 0x9f6a, "Unpredictable Number", EMV_TAG_NUMERIC }, { 0x9f6b, "Track 2 Data" }, { 0x9f6c, "Card Transaction Qualifiers (CTQ)", EMV_TAG_BITMASK, &EMV_CTQ }, + { 0x9f6d, "Mag-stripe Application Version Number (Reader)" }, { 0x9f6e, "Form Factor Indicator" }, - - { 0x9f7c, "Customer Exclusive Data (CED)"}, + { 0x9f6f, "DS Slot Management Control" }, + + { 0x9f70, "Protected Data Envelope 1" }, + { 0x9f71, "Protected Data Envelope 2" }, + { 0x9f72, "Protected Data Envelope 3" }, + { 0x9f73, "Protected Data Envelope 4" }, + { 0x9f74, "Protected Data Envelope 5" }, + { 0x9f75, "Unprotected Data Envelope 1" }, + { 0x9f76, "Unprotected Data Envelope 2" }, + { 0x9f77, "Unprotected Data Envelope 3" }, + { 0x9f78, "Unprotected Data Envelope 4" }, + { 0x9f79, "Unprotected Data Envelope 5" }, + { 0x9f7c, "Merchant Custom Data / Customer Exclusive Data (CED)" }, + { 0x9f7d, "DS Summary 1" }, + { 0x9f7f, "DS Unpredictable Number" }, { 0xa5 , "File Control Information (FCI) Proprietary Template" }, { 0xbf0c, "File Control Information (FCI) Issuer Discretionary Data" }, { 0xdf20, "Issuer Proprietary Bitmap (IPB)" }, + { 0xdf4b, "POS Cardholder Interaction Information" }, + { 0xdf60, "VISA Log Entry" }, + { 0xdf61, "DS Digest H" }, + { 0xdf62, "DS ODS Info" }, + { 0xdf63, "DS ODS Term" }, + + { 0xdf8104, "Balance Read Before Gen AC" }, + { 0xdf8105, "Balance Read After Gen AC" }, + { 0xdf8106, "Data Needed" }, + { 0xdf8107, "CDOL1 Related Data" }, + { 0xdf8108, "DS AC Type" }, + { 0xdf8109, "DS Input (Term)" }, + { 0xdf810a, "DS ODS Info For Reader" }, + { 0xdf810b, "DS Summary Status" }, + { 0xdf810c, "Kernel ID" }, + { 0xdf810d, "DSVN Term" }, + { 0xdf810e, "Post-Gen AC Put Data Status" }, + { 0xdf810f, "Pre-Gen AC Put Data Status" }, + { 0xdf8110, "Proceed To First Write Flag" }, + { 0xdf8111, "PDOL Related Data" }, + { 0xdf8112, "Tags To Read" }, + { 0xdf8113, "DRDOL Related Data" }, + { 0xdf8114, "Reference Control Parameter" }, + { 0xdf8115, "Error Indication" }, + { 0xdf8116, "User Interface Request Data" }, + { 0xdf8117, "Card Data Input Capability" }, + { 0xdf8118, "CVM Capability - CVM Required" }, + { 0xdf8119, "CVM Capability - No CVM Required" }, + { 0xdf811a, "Default UDOL" }, + { 0xdf811b, "Kernel Configuration" }, + { 0xdf811c, "Max Lifetime of Torn Transaction Log Record" }, + { 0xdf811d, "Max Number of Torn Transaction Log Records" }, + { 0xdf811e, "Mag-stripe CVM Capability – CVM Required" }, + { 0xdf811f, "Security Capability" }, + { 0xdf8120, "Terminal Action Code – Default" }, + { 0xdf8121, "Terminal Action Code – Denial" }, + { 0xdf8122, "Terminal Action Code – Online" }, + { 0xdf8123, "Reader Contactless Floor Limit" }, + { 0xdf8124, "Reader Contactless Transaction Limit (No On-device CVM)" }, + { 0xdf8125, "Reader Contactless Transaction Limit (On-device CVM)" }, + { 0xdf8126, "Reader CVM Required Limit" }, + { 0xdf8127, "TIME_OUT_VALUE" }, + { 0xdf8128, "IDS Status" }, + { 0xdf8129, "Outcome Parameter Set" }, + { 0xdf812a, "DD Card (Track1)" }, + { 0xdf812b, "DD Card (Track2)" }, + { 0xdf812c, "Mag-stripe CVM Capability – No CVM Required" }, + { 0xdf812d, "Message Hold Time" }, + + { 0xff8101, "Torn Record" }, + { 0xff8102, "Tags To Write Before Gen AC" }, + { 0xff8103, "Tags To Write After Gen AC" }, + { 0xff8104, "Data To Send" }, + { 0xff8105, "Data Record" }, + { 0xff8106, "Discretionary Data" }, }; static int emv_sort_tag(tlv_tag_t tag) { From ce6320cdc1d130be3e17fbc4fe9f13287869c9f3 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 8 Jan 2019 19:22:27 +0200 Subject: [PATCH 0390/1938] change sc apdu to be compatible with 14a apdu --- client/cmdsmartcard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index a864e2358..fdc825d38 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -533,7 +533,7 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave int len = smart_responseEx(dataout, true); if ( len < 0 ) { - return 2; + return 1; } // retry From 1fb79486232fc245ddbb0bbfeff226e6eafbe73f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 8 Jan 2019 19:49:31 +0200 Subject: [PATCH 0391/1938] emv commands now prints channel --- client/emv/cmdemv.c | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 396918d7e..206401917 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -40,6 +40,17 @@ void ParamLoadDefaults(struct tlvdb *tlvRoot) { TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC } +void PrintChannel(EMVCommandChannel channel) { + switch(channel) { + case ECC_CONTACTLESS: + PrintAndLogEx(INFO, "Channel: CONTACTLESS"); + break; + case ECC_CONTACT: + PrintAndLogEx(INFO, "Channel: CONTACT"); + break; + } +} + int CmdEMVSelect(const char *cmd) { uint8_t data[APDU_AID_LEN] = {0}; int datalen = 0; @@ -67,6 +78,7 @@ int CmdEMVSelect(const char *cmd) { EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(5)) channel = ECC_CONTACT; + PrintChannel(channel); CLIGetHexWithReturn(6, data, &datalen); CLIParserFree(); @@ -114,6 +126,7 @@ int CmdEMVSearch(const char *cmd) { EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(5)) channel = ECC_CONTACT; + PrintChannel(channel); CLIParserFree(); SetAPDULogging(APDULogging); @@ -170,6 +183,7 @@ int CmdEMVPPSE(const char *cmd) { EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(7)) channel = ECC_CONTACT; + PrintChannel(channel); CLIParserFree(); SetAPDULogging(APDULogging); @@ -224,6 +238,7 @@ int CmdEMVGPO(const char *cmd) { EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(6)) channel = ECC_CONTACT; + PrintChannel(channel); CLIGetHexWithReturn(7, data, &datalen); CLIParserFree(); @@ -317,6 +332,7 @@ int CmdEMVReadRecord(const char *cmd) { EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(4)) channel = ECC_CONTACT; + PrintChannel(channel); CLIGetHexWithReturn(5, data, &datalen); CLIParserFree(); @@ -399,6 +415,7 @@ int CmdEMVAC(const char *cmd) { EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(8)) channel = ECC_CONTACT; + PrintChannel(channel); CLIGetHexWithReturn(9, data, &datalen); CLIParserFree(); @@ -481,6 +498,7 @@ int CmdEMVGenerateChallenge(const char *cmd) { EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(3)) channel = ECC_CONTACT; + PrintChannel(channel); CLIParserFree(); SetAPDULogging(APDULogging); @@ -539,6 +557,7 @@ int CmdEMVInternalAuthenticate(const char *cmd) { EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(6)) channel = ECC_CONTACT; + PrintChannel(channel); CLIGetHexWithReturn(7, data, &datalen); CLIParserFree(); @@ -722,6 +741,7 @@ int CmdEMVExec(const char *cmd) { EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(11)) channel = ECC_CONTACT; + PrintChannel(channel); uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; CLIParserFree(); @@ -1171,6 +1191,7 @@ int CmdEMVScan(const char *cmd) { EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(11)) channel = ECC_CONTACT; + PrintChannel(channel); uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; uint8_t relfname[250] ={0}; char *crelfname = (char *)relfname; @@ -1493,6 +1514,7 @@ int CmdEMVRoca(const char *cmd) { if (arg_get_lit(2)) channel = ECC_CONTACT; + PrintChannel(channel); // select card uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; From 7bb8c629ba67217d13fe19e604732e9c6d145048 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 8 Jan 2019 20:14:46 +0100 Subject: [PATCH 0392/1938] fix: remove warnings --- client/cmdhfmf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 985965d72..00e29105f 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1294,9 +1294,9 @@ int CmdHF14AMfNestedHard(const char *Cmd) { case 'r': fptr = GenerateFilename("hf-mf-","-nonces.bin"); if (fptr == NULL) - strncpy(filename,"nonces.bin", FILE_PATH_SIZE); + strncpy(filename, "nonces.bin", FILE_PATH_SIZE); else - strncpy(filename,fptr, FILE_PATH_SIZE); + strncpy(filename, fptr, FILE_PATH_SIZE-1); nonce_file_read = true; if (!param_gethex(Cmd, cmdp+1, trgkey, 12)) { @@ -1367,7 +1367,7 @@ int CmdHF14AMfNestedHard(const char *Cmd) { fptr = GenerateFilename("hf-mf-","-nonces.bin"); if (fptr == NULL) return 1; - strncpy(filename, fptr, FILE_PATH_SIZE); + strncpy(filename, fptr, FILE_PATH_SIZE-1); break; case 'u': param_getstr(Cmd, cmdp+1, szTemp, FILE_PATH_SIZE-20); From d13541791b1ab4315d7d1aeb1d528bdcc8b6d872 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 8 Jan 2019 20:20:16 +0100 Subject: [PATCH 0393/1938] chg: tlvtag can be 4bytes.. --- client/emv/tlv.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/emv/tlv.h b/client/emv/tlv.h index e3c7c97fa..d2a55525f 100644 --- a/client/emv/tlv.h +++ b/client/emv/tlv.h @@ -22,7 +22,7 @@ #include #include -typedef uint16_t tlv_tag_t; +typedef uint32_t tlv_tag_t; struct tlv { tlv_tag_t tag; From 2612cd006a91538d36ba620aa0a6a1089d8680a2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 9 Jan 2019 12:00:06 +0100 Subject: [PATCH 0394/1938] CHG: bigbuf adaptations --- armsrc/BigBuf.c | 14 +++++----- armsrc/BigBuf.h | 4 +-- armsrc/apps.h | 1 - armsrc/iso14443a.c | 69 +++++++++++++++++++++++++++------------------- armsrc/iso14443b.c | 2 +- 5 files changed, 51 insertions(+), 39 deletions(-) diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index 8f6bf9ca6..7b49c0619 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -30,8 +30,8 @@ static uint16_t BigBuf_hi = BIGBUF_SIZE; static uint8_t *emulator_memory = NULL; // trace related variables -static uint16_t traceLen = 0; -int tracing = 1; //Last global one.. todo static? +static uint32_t traceLen = 0; +static bool tracing = true; //todo static? // get the address of BigBuf uint8_t *BigBuf_get_addr(void) { @@ -112,7 +112,7 @@ uint16_t BigBuf_max_traceLen(void) { void clear_trace(void) { traceLen = 0; } -void set_tracelen(uint16_t value) { +void set_tracelen(uint32_t value) { traceLen = value; } void set_tracing(bool enable) { @@ -127,7 +127,7 @@ bool get_tracing(void) { * Get the number of bytes traced * @return */ -uint16_t BigBuf_get_traceLen(void) { +uint32_t BigBuf_get_traceLen(void) { return traceLen; } @@ -142,8 +142,8 @@ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_ uint8_t *trace = BigBuf_get_addr(); - uint16_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity - uint16_t duration = timestamp_end - timestamp_start; + uint32_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity + uint32_t duration = timestamp_end - timestamp_start; // Return when trace is full if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= BigBuf_max_traceLen()) { @@ -204,7 +204,7 @@ int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwP if (!tracing) return false; uint8_t *trace = BigBuf_get_addr(); - uint16_t iLen = nbytes(iBits); + uint32_t iLen = nbytes(iBits); // Return when trace is full if (traceLen + sizeof(rsamples) + sizeof(dwParity) + sizeof(iBits) + iLen > BigBuf_max_traceLen()) return false; diff --git a/armsrc/BigBuf.h b/armsrc/BigBuf.h index e8c6f5cd4..679eed676 100644 --- a/armsrc/BigBuf.h +++ b/armsrc/BigBuf.h @@ -36,10 +36,10 @@ extern uint8_t *BigBuf_malloc(uint16_t); extern void BigBuf_free(void); extern void BigBuf_free_keep_EM(void); extern void BigBuf_print_status(void); -extern uint16_t BigBuf_get_traceLen(void); +extern uint32_t BigBuf_get_traceLen(void); extern void clear_trace(void); extern void set_tracing(bool enable); -extern void set_tracelen(uint16_t value); +extern void set_tracelen(uint32_t value); extern bool get_tracing(void); extern bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag); extern int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int bReader); diff --git a/armsrc/apps.h b/armsrc/apps.h index 1e8524d57..7e45d5e50 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -34,7 +34,6 @@ extern "C" { extern const uint8_t OddByteParity[256]; extern int rsamples; // = 0; -extern int tracing; // = TRUE; extern uint8_t trigger; // This may be used (sparingly) to declare a function to be copied to diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 91db762fc..257c39b1f 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -651,7 +651,7 @@ void RAMFUNC SniffIso14443a(uint8_t param) { //----------------------------------------------------------------------------- static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *parity, bool collision) { - uint8_t localCol = 0; + //uint8_t localCol = 0; ToSendReset(); // Correction bit, might be removed when not needed @@ -673,24 +673,32 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par // Data bits for(uint16_t j = 0; j < 8; j++) { - if (collision && (localCol >= colpos)){ + //if (collision && (localCol >= colpos)){ + if (collision) { ToSend[++ToSendMax] = SEC_COLL; - } else if(b & 1) { - ToSend[++ToSendMax] = SEC_D; - } else { - ToSend[++ToSendMax] = SEC_E; + //localCol++; + } else { + if (b & 1) { + ToSend[++ToSendMax] = SEC_D; + } else { + ToSend[++ToSendMax] = SEC_E; + } + b >>= 1; } - b >>= 1; - localCol++; } - // Get the parity bit - if (parity[i>>3] & (0x80>>(i&0x0007))) { - ToSend[++ToSendMax] = SEC_D; - LastProxToAirDuration = 8 * ToSendMax - 4; + if (collision) { + ToSend[++ToSendMax] = SEC_COLL; + LastProxToAirDuration = 8 * ToSendMax; } else { - ToSend[++ToSendMax] = SEC_E; - LastProxToAirDuration = 8 * ToSendMax; + // Get the parity bit + if (parity[i>>3] & (0x80>>(i&0x0007))) { + ToSend[++ToSendMax] = SEC_D; + LastProxToAirDuration = 8 * ToSendMax - 4; + } else { + ToSend[++ToSendMax] = SEC_E; + LastProxToAirDuration = 8 * ToSendMax; + } } } @@ -795,12 +803,12 @@ bool prepare_tag_modulation(tag_response_info_t* response_info, size_t max_buffe // Make sure we do not exceed the free buffer space if (ToSendMax > max_buffer_size) { Dbprintf("Out of memory, when modulating bits for tag answer:"); - Dbhexdump(response_info->response_n,response_info->response,false); + Dbhexdump(response_info->response_n, response_info->response, false); return false; } // Copy the byte array, used for this modulation to the buffer position - memcpy(response_info->modulation,ToSend,ToSendMax); + memcpy(response_info->modulation, ToSend, ToSendMax); // Store the number of bytes that were used for encoding/modulation and the time needed to transfer them response_info->modulation_n = ToSendMax; @@ -1047,7 +1055,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { // Clean receive command buffer if (!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) { - Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); + Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen()); break; } p_response = NULL; @@ -1836,15 +1844,17 @@ void iso14443a_antifuzz(uint32_t flags){ // allocate buffers: uint8_t *received = BigBuf_malloc(MAX_FRAME_SIZE); uint8_t *receivedPar = BigBuf_malloc(MAX_PARITY_SIZE); - uint8_t *resp = BigBuf_malloc(8); + uint8_t *resp = BigBuf_malloc(20); + memset(resp, 0xFF , 20); + LED_A_ON(); for (;;) { WDT_HIT(); // Clean receive command buffer if (!GetIso14443aCommandFromReader(received, receivedPar, &len)) { - Dbprintf("Anti-fuzz stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); + Dbprintf("Anti-fuzz stopped. Trace length: %d ", BigBuf_get_traceLen()); break; } if ( received[0] == ISO14443A_CMD_WUPA || received[0] == ISO14443A_CMD_REQA) { @@ -1860,21 +1870,24 @@ void iso14443a_antifuzz(uint32_t flags){ } // Received request for UID (cascade 1) - if (received[1] >= 0x20 && received[1] <= 0x57 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { - resp[0] = 0x04; - resp[1] = 0x1C; - resp[2] = 0xE1; - resp[3] = 0xCE; + //if (received[1] >= 0x20 && received[1] <= 0x57 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { + if (received[1] >= 0x20 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { + resp[0] = 0xFF; + resp[1] = 0xFF; + resp[2] = 0xFF; + resp[3] = 0xFF; + resp[4] = resp[0] ^ resp[1] ^ resp[2] ^ resp[3]; colpos = 0; if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA ) { resp[0] = 0x88; colpos = 8; } - - EmSendCmdEx(resp, 4, true); - if (MF_DBGLEVEL >= 4) Dbprintf("ANTICOLL or SELECT %x", received[1]); + EmSendCmdEx(resp, 5, true); + if (MF_DBGLEVEL >= 4) Dbprintf("ANTICOLL or SELECT %x", received[1]); + LED_D_INV(); + continue; } else if (received[1] == 0x20 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received request for UID (cascade 2) if (MF_DBGLEVEL >= 4) Dbprintf("ANTICOLL or SELECT_2"); @@ -3489,7 +3502,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } if (MF_DBGLEVEL >= 1) - Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); + Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen()); cmd_send(CMD_ACK,1,0,0,0,0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index edf114134..6167ca785 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -710,7 +710,7 @@ void SimulateIso14443bTag(uint32_t pupi) { ++cmdsReceived; } if (MF_DBGLEVEL >= 2) - Dbprintf("Emulator stopped. Tracing: %d trace length: %d ", tracing, BigBuf_get_traceLen()); + Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen()); switch_off(); //simulate } From 6743e45386770e4e171bee638761144f6d8c529e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 9 Jan 2019 12:05:29 +0100 Subject: [PATCH 0395/1938] CHG: name changes --- armsrc/felica.c | 48 +++++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 25 deletions(-) diff --git a/armsrc/felica.c b/armsrc/felica.c index aa6712268..d1e7bc344 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -29,27 +29,25 @@ static uint32_t felica_timeout; static uint32_t felica_nexttransfertime; static uint32_t felica_lasttime_prox2air_start; -static void felica_setup(uint8_t fpga_minor_mode); +static void iso18092_setup(uint8_t fpga_minor_mode); static uint8_t felica_select_card(felica_card_select_t *card); static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed); bool WaitForFelicaReply(uint16_t maxbytes); -void felica_set_timeout(uint32_t timeout) { +void iso18092_set_timeout(uint32_t timeout) { felica_timeout = timeout + (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/(16*8) + 2; } -uint32_t felica_get_timeout(void) { +uint32_t iso18092_get_timeout(void) { return felica_timeout - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/(16*8) - 2; } -//random service RW: 0x0009 -//random service RO: 0x000B -#ifndef NFC_MAX_FRAME_SIZE - #define NFC_MAX_FRAME_SIZE 260 +#ifndef FELICA_MAX_FRAME_SIZE + #define FELICA_MAX_FRAME_SIZE 260 #endif //structure to hold outgoing NFC frame -static uint8_t frameSpace[NFC_MAX_FRAME_SIZE+4]; +static uint8_t frameSpace[FELICA_MAX_FRAME_SIZE+4]; //structure to hold incoming NFC frame, used for ISO/IEC 18092-compatible frames static struct { @@ -85,7 +83,7 @@ static void FelicaFrameReset() { FelicaFrame.crc_ok = false; FelicaFrame.byte_offset = 0; } -static void NFCInit(uint8_t *data) { +static void FelicaFrameinit(uint8_t *data) { FelicaFrame.framebytes = data; FelicaFrameReset(); } @@ -105,7 +103,7 @@ static void shiftInByte(uint8_t bt) { } } -static void ProcessNFCByte(uint8_t bt) { +static void Process18092Byte(uint8_t bt) { switch (FelicaFrame.state) { case STATE_UNSYNCD: { //almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not alsways the case @@ -127,7 +125,7 @@ static void ProcessNFCByte(uint8_t bt) { //SYNC done! FelicaFrame.state = STATE_GET_LENGTH; FelicaFrame.framebytes[0] = 0xb2; - FelicaFrame.framebytes[1] = 0x4d; //write SYNC + FelicaFrame.framebytes[1] = 0x4d; FelicaFrame.byte_offset = i; //shift in remaining byte, slowly... for(uint8_t j=i; j<8; j++) { @@ -269,7 +267,7 @@ static uint8_t felica_select_card(felica_card_select_t *card) { static void BuildFliteRdblk(uint8_t* idm, int blocknum, uint16_t *blocks ) { if (blocknum > 4 || blocknum <= 0) - Dbprintf("Invalid number of blocks, %d. Up to 4 are allowed.", blocknum); + Dbprintf("Invalid number of blocks, %d != 4", blocknum); uint8_t c = 0, i = 0; @@ -394,13 +392,13 @@ bool WaitForFelicaReply(uint16_t maxbytes) { // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - uint32_t timeout = felica_get_timeout(); + uint32_t timeout = iso18092_get_timeout(); for(;;) { WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { b = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); - ProcessNFCByte(b); + Process18092Byte(b); if (FelicaFrame.state == STATE_FULL) { felica_nexttransfertime = MAX( @@ -432,7 +430,7 @@ bool WaitForFelicaReply(uint16_t maxbytes) { // Set up FeliCa communication (similar to iso14443a_setup) // field is setup for "Sending as Reader" -static void felica_setup(uint8_t fpga_minor_mode) { +static void iso18092_setup(uint8_t fpga_minor_mode) { LEDsoff(); FpgaDownloadAndGo(FPGA_BITSTREAM_HF); @@ -442,11 +440,13 @@ static void felica_setup(uint8_t fpga_minor_mode) { // Initialize Demod and Uart structs //DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); - NFCInit(BigBuf_malloc(NFC_MAX_FRAME_SIZE)); + FelicaFrameinit(BigBuf_malloc(FELICA_MAX_FRAME_SIZE)); felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER; - felica_set_timeout(2120); // 106 * 20ms maximum start-up time of card + iso18092_set_timeout(2120); // 106 * 20ms maximum start-up time of card + init_table(CRC_FELICA); + // connect Demodulated Signal to ADC: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); @@ -455,8 +455,6 @@ static void felica_setup(uint8_t fpga_minor_mode) { // LSB transfer. Remember to set it back to MSB with AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - - init_table(CRC_FELICA); // Signal field is on with the appropriate LED FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | fpga_minor_mode); @@ -492,7 +490,7 @@ void felica_sendraw(UsbCommand *c) { set_tracing(true); if ((param & FELICA_CONNECT)) { - felica_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); + iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); // notify client selecting status. // if failed selecting, turn off antenna and quite. @@ -547,7 +545,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { Dbprintf("Snoop FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); - felica_setup( FPGA_HF_ISO18092_FLAG_NOMOD); + iso18092_setup( FPGA_HF_ISO18092_FLAG_NOMOD); //the frame bits are slow enough. int n = BigBuf_max_traceLen() / sizeof(uint8_t); // take all memory @@ -563,7 +561,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); - ProcessNFCByte(dist); + Process18092Byte(dist); //to be sure we are in frame if (FelicaFrame.state == STATE_GET_LENGTH) { @@ -643,7 +641,7 @@ void felica_sim_lite(uint64_t nfcid) { AddCrc(resp_poll1, resp_poll1[2]); AddCrc(resp_readblk, resp_readblk[2]); - felica_setup( FPGA_HF_ISO18092_FLAG_NOMOD); + iso18092_setup( FPGA_HF_ISO18092_FLAG_NOMOD); bool listenmode = true; //uint32_t frtm = GetCountSspClk(); @@ -657,7 +655,7 @@ void felica_sim_lite(uint64_t nfcid) { uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); //frtm = GetCountSspClk(); - ProcessNFCByte(dist); + Process18092Byte(dist); if (FelicaFrame.state == STATE_FULL) { @@ -725,7 +723,7 @@ void felica_dump_lite_s() { uint16_t liteblks[28] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x90,0x91,0x92,0xa0}; // setup device. - felica_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); + iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); uint8_t blknum; bool isOK = false; From 8f18a9abf21b69a91abefb7b949c91dc20abf082 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 9 Jan 2019 12:07:07 +0100 Subject: [PATCH 0396/1938] CHG: tvl tag length adapted --- client/emv/emvjson.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/emv/emvjson.c b/client/emv/emvjson.c index 116e16da1..f8cccddf2 100644 --- a/client/emv/emvjson.c +++ b/client/emv/emvjson.c @@ -372,13 +372,13 @@ bool ParamLoadFromJson(struct tlvdb *tlv) { size_t buflen = 0; // here max length must be 4, but now tlv_tag_t is 2-byte var. so let it be 2 by now... TODO: needs refactoring tlv_tag_t... - if (!HexToBuffer("TLV Error type:", tlvTag, buf, 2, &buflen)) { + if (!HexToBuffer("TLV Error type:", tlvTag, buf, 4, &buflen)) { json_decref(root); return false; } tlv_tag_t tag = 0; for (int i = 0; i < buflen; i++) { - tag = (tag << 8) + buf[i]; + tag = (tag << 8) | buf[i]; } if (!HexToBuffer("TLV Error value:", tlvValue, buf, sizeof(buf) - 1, &buflen)) { From 96361abd973cbccb0576aa200885cb0b176f3dcb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 9 Jan 2019 12:28:56 +0100 Subject: [PATCH 0397/1938] FIX: supress gcc warnings like libjansson https://github.com/akheron/jansson/pull/423/files --- client/jansson/Makefile | 2 +- client/jansson/error.c | 2 +- client/jansson/load.c | 6 +++--- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/jansson/Makefile b/client/jansson/Makefile index 7657e35f3..596c1778c 100644 --- a/client/jansson/Makefile +++ b/client/jansson/Makefile @@ -32,7 +32,7 @@ CMDOBJS = $(CFILES:%.c=%.o) CLEAN = $(CMDOBJS) CC= gcc -CFLAGS= -O2 -Wall -Wno-unused-variable -Wno-unused-function +CFLAGS= -O2 -Wall -Wno-unused-variable -Wno-unused-function -Wno-format-truncation LDFLAGS= $(SYSLDFLAGS) $(libjansson_la_LDFLAGS) LIBS= $(SYSLIBS) $(MYLIBS) DEFAULT_INCLUDES = -I. diff --git a/client/jansson/error.c b/client/jansson/error.c index f5da6b9b0..b94b3a3a1 100644 --- a/client/jansson/error.c +++ b/client/jansson/error.c @@ -25,7 +25,7 @@ void jsonp_error_set_source(json_error_t *error, const char *source) length = strlen(source); if(length < JSON_ERROR_SOURCE_LENGTH) - strncpy(error->source, source, length + 1); + strncpy(error->source, source, JSON_ERROR_SOURCE_LENGTH); else { size_t extra = length - JSON_ERROR_SOURCE_LENGTH + 4; memcpy(error->source, "...", 3); diff --git a/client/jansson/load.c b/client/jansson/load.c index 9f73ea02c..2f123724e 100644 --- a/client/jansson/load.c +++ b/client/jansson/load.c @@ -89,7 +89,7 @@ static void error_set(json_error_t *error, const lex_t *lex, { va_list ap; char msg_text[JSON_ERROR_TEXT_LENGTH]; - char msg_with_context[JSON_ERROR_TEXT_LENGTH + 20]; + char msg_with_context[JSON_ERROR_TEXT_LENGTH]; int line = -1, col = -1; size_t pos = 0; @@ -115,7 +115,7 @@ static void error_set(json_error_t *error, const lex_t *lex, { if(lex->saved_text.length <= 20) { snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near '%s'", msg_text, saved_text); - msg_with_context[JSON_ERROR_TEXT_LENGTH + 20 - 1] = '\0'; + msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0'; result = msg_with_context; } } @@ -131,7 +131,7 @@ static void error_set(json_error_t *error, const lex_t *lex, } else { snprintf(msg_with_context, JSON_ERROR_TEXT_LENGTH, "%s near end of file", msg_text); - msg_with_context[JSON_ERROR_TEXT_LENGTH + 20 - 1] = '\0'; + msg_with_context[JSON_ERROR_TEXT_LENGTH - 1] = '\0'; result = msg_with_context; } } From 4880316ab932d983bda83ff7600b2071e122f24e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 9 Jan 2019 15:20:18 +0200 Subject: [PATCH 0398/1938] fix hash --- client/emv/emv_pki.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/emv/emv_pki.c b/client/emv/emv_pki.c index be4dfa0a7..602dcacce 100644 --- a/client/emv/emv_pki.c +++ b/client/emv/emv_pki.c @@ -109,10 +109,12 @@ static unsigned char *emv_pki_decode_message(const struct emv_pk *enc_pk, } va_end(vl); - if (memcmp(data + data_len - 1 - hash_len, crypto_hash_read(ch), hash_len)) { + uint8_t hash[20] = {0}; + memcpy(hash, crypto_hash_read(ch), hash_len); + if (memcmp(data + data_len - 1 - hash_len, hash, hash_len)) { printf("ERROR: Calculated wrong hash\n"); printf("decoded: %s\n",sprint_hex(data + data_len - 1 - hash_len, hash_len)); - printf("calculated: %s\n",sprint_hex(crypto_hash_read(ch), hash_len)); + printf("calculated: %s\n",sprint_hex(hash, hash_len)); if (strictExecution) { crypto_hash_close(ch); From 010492a87e47326c32040cd5495eb4baf3f2f991 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 9 Jan 2019 17:04:21 +0200 Subject: [PATCH 0399/1938] input list build fixed --- client/emv/cmdemv.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 206401917..a21337d03 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -892,7 +892,7 @@ int CmdEMVExec(const char *cmd) { // Build Input list for Offline Data Authentication // EMV 4.3 book3 10.3, page 96 - if (SFIoffline) { + if (SFIoffline > 0) { if (SFI < 11) { const unsigned char *abuf = buf; size_t elmlen = len; @@ -907,6 +907,8 @@ int CmdEMVExec(const char *cmd) { memcpy(&ODAiList[ODAiListLen], buf, len); ODAiListLen += len; } + + SFIoffline--; } } } From 4a38ab7be4a8c20c761ea5abbb12365ef2734b7b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 9 Jan 2019 17:08:23 +0200 Subject: [PATCH 0400/1938] small fix --- client/emv/cmdemv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index a21337d03..0cc6614d9 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -870,7 +870,7 @@ int CmdEMVExec(const char *cmd) { uint8_t SFIend = AFL->value[i * 4 + 2]; uint8_t SFIoffline = AFL->value[i * 4 + 3]; - PrintAndLogEx(NORMAL, "* * SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline); + PrintAndLogEx(NORMAL, "* * SFI[%02x] start:%02x end:%02x offline count:%02x", SFI, SFIstart, SFIend, SFIoffline); if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) { PrintAndLogEx(NORMAL, "SFI ERROR! Skipped..."); continue; From e276bf1ce326f88ef8bbebd27ae1d77e7e3ca12e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 9 Jan 2019 16:25:49 +0100 Subject: [PATCH 0401/1938] FIX: gcc8.1 warnings --- armsrc/tlv.c | 75 ++++++++++++++++++++++++---------------- armsrc/tlv.h | 13 ++++--- client/crypto/asn1dump.c | 4 ++- client/emv/emvjson.c | 1 - client/util.c | 2 +- 5 files changed, 59 insertions(+), 36 deletions(-) diff --git a/armsrc/tlv.c b/armsrc/tlv.c index 3da03492f..839b34d66 100644 --- a/armsrc/tlv.c +++ b/armsrc/tlv.c @@ -2,7 +2,7 @@ int decode_ber_tlv_item(uint8_t* data, tlvtag* returnedtag) { - uint8_t tag[TAG_LENGTH] = {0x00,0x00}; + uint8_t tag[TAG_LENGTH] = {0x00, 0x00, 0x00, 0x00}; uint16_t length = 0; //uint8_t value[VALUE_LENGTH]; uint8_t lenlen = 0; @@ -10,40 +10,44 @@ int decode_ber_tlv_item(uint8_t* data, tlvtag* returnedtag) int z = 0; //decode tag tag[0] = data[0]; - if((tag[0] & TLV_TAG_NUMBER_MASK) == TLV_TAG_NUMBER_MASK) { //see subsequent bytes + if ((tag[0] & TLV_TAG_NUMBER_MASK) == TLV_TAG_NUMBER_MASK) { //see subsequent bytes i++; - tag[i] = data[i]; - //assume tag is only two bytes long for now - /* - while((data[i] & TLV_TAG_MASK) == TLV_TAG_MASK){ - i++; - tag[i] = data[i]; - } - */ + + tag[i] = data[i]; + + while((data[i] & TLV_TAG_MASK) == TLV_TAG_MASK){ + i++; + tag[i] = data[i]; + } + } i++; //decode length - if((data[i] & TLV_LENGTH_MASK) == TLV_LENGTH_MASK) { + if ((data[i] & TLV_LENGTH_MASK) == TLV_LENGTH_MASK) { lenlen = data[i] ^ TLV_LENGTH_MASK; i++; length = (uint16_t)data[i]; z = 1; - while(z < lenlen){ + while (z < lenlen) { i++; z++; length <<= 8; length += (uint16_t)data[i]; } i++; - } - else { + } else { length = (uint16_t)data[i]; i++; } - //copy results into the structure and return + // copy results into the structure and return memcpy(returnedtag->tag, tag, TAG_LENGTH); - (*returnedtag).valuelength = length; //return length of tag value - (*returnedtag).fieldlength = length + i + 1; //return length of total field + + // return length of tag value + (*returnedtag).valuelength = length; + + // return length of total field + (*returnedtag).fieldlength = length + i + 1; + memcpy(returnedtag->value, &(data[i]), length); return 0; } @@ -51,27 +55,40 @@ int decode_ber_tlv_item(uint8_t* data, tlvtag* returnedtag) //generate a TLV tag off input data int encode_ber_tlv_item(uint8_t* tag, uint8_t taglen, uint8_t* data, uint32_t datalen, uint8_t* outputtag, uint32_t* outputtaglen) { - if(!tag || !data || !outputtag || !outputtaglen) //null pointer check + if (!tag || !data || !outputtag || !outputtaglen) return 0; - uint8_t datafieldlen = (datalen / 128) + 1; //field length of the tag - uint8_t tlvtotallen = taglen + datafieldlen + datalen; //total length of the tag - uint8_t returnedtag[tlvtotallen]; //buffer for the returned tag + // field length of the tag + uint8_t datafieldlen = (datalen / 128) + 1; + + // total length of the tag + uint8_t tlvtotallen = taglen + datafieldlen + datalen; + + // buffer for the returned tag + uint8_t returnedtag[tlvtotallen]; + uint8_t counter = 0; - memcpy(returnedtag, tag, taglen); //copy tag into buffer + + // copy tag into buffer + memcpy(returnedtag, tag, taglen); counter += taglen; - if(datalen < 128){ // 1 byte length value + + // 1 byte length value + if (datalen < 128){ returnedtag[counter++] = datalen; - } - else{ - returnedtag[counter++] = datafieldlen | 0x80; //high bit set and number of length bytes - for(uint8_t i=datafieldlen; i !=0; i--){ - returnedtag[counter++] = (datalen >> (i * 8)) & 0xFF; //get current byte + } else { + + // high bit set and number of length bytes + returnedtag[counter++] = datafieldlen | 0x80; + + for (uint8_t i = datafieldlen; i !=0; i--) { + // get current byte + returnedtag[counter++] = (datalen >> (i * 8)) & 0xFF; } } memcpy(&returnedtag[counter], data, datalen); *outputtaglen = tlvtotallen; - memcpy(outputtag, returnedtag,tlvtotallen); + memcpy(outputtag, returnedtag, tlvtotallen); return 0; } diff --git a/armsrc/tlv.h b/armsrc/tlv.h index c90756168..de8180cab 100644 --- a/armsrc/tlv.h +++ b/armsrc/tlv.h @@ -6,8 +6,13 @@ #include //structure buffer definitions -#define TAG_LENGTH 2 -#define VALUE_LENGTH 1024 +#ifndef TAG_LENGTH +# define TAG_LENGTH 4 +#endif + +#ifndef VALUE_LENGTH +# define VALUE_LENGTH 1024 +#endif //masks //if TLV_TAG_NUMBER_MASK bits are set, refer to the next byte for the tag number @@ -19,13 +24,13 @@ #define TLV_TAG_MASK 0x80 #define TLV_LENGTH_MASK 0x80 -//tlv tag structure, tag can be max of 2 bytes, length up to 65535 and value 1024 bytes long +//tlv tag structure, tag can be max of 4 bytes, length up to 0xFFFFFFFF and value 1024 bytes long typedef struct { uint8_t tag[TAG_LENGTH]; uint16_t fieldlength; uint16_t valuelength; uint8_t value[VALUE_LENGTH]; -}tlvtag; +} tlvtag; //decode a BER TLV extern int decode_ber_tlv_item(uint8_t* data, tlvtag* returnedtag); diff --git a/client/crypto/asn1dump.c b/client/crypto/asn1dump.c index 34f4a9fa4..52814f22b 100644 --- a/client/crypto/asn1dump.c +++ b/client/crypto/asn1dump.c @@ -24,7 +24,9 @@ #include "util.h" #include "proxmark3.h" -#define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, " ");} +#ifndef PRINT_INDENT +# define PRINT_INDENT(level) {for (int i = 0; i < (level); i++) fprintf(f, " ");} +#endif enum asn1_tag_t { ASN1_TAG_GENERIC, diff --git a/client/emv/emvjson.c b/client/emv/emvjson.c index f8cccddf2..45eb1f430 100644 --- a/client/emv/emvjson.c +++ b/client/emv/emvjson.c @@ -371,7 +371,6 @@ bool ParamLoadFromJson(struct tlvdb *tlv) { uint8_t buf[251] = {0}; size_t buflen = 0; - // here max length must be 4, but now tlv_tag_t is 2-byte var. so let it be 2 by now... TODO: needs refactoring tlv_tag_t... if (!HexToBuffer("TLV Error type:", tlvTag, buf, 4, &buflen)) { json_decref(root); return false; diff --git a/client/util.c b/client/util.c index 5d7ce0370..b22258d44 100644 --- a/client/util.c +++ b/client/util.c @@ -212,7 +212,7 @@ void print_hex_break(const uint8_t *data, const size_t len, uint8_t breaks) { } char *sprint_hex(const uint8_t *data, const size_t len) { - static char buf[UTIL_BUFFER_SIZE_SPRINT] = {0}; + static char buf[UTIL_BUFFER_SIZE_SPRINT - 3] = {0}; hex_to_buffer((uint8_t *)buf, data, len, sizeof(buf) - 1, 0, 1, true); return buf; } From 8a514ea8f10f91d7b30dd10017480b5bf20a5868 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 9 Jan 2019 16:28:06 +0100 Subject: [PATCH 0402/1938] REM: remove unused files --- armsrc/tlv.c | 94 ---------------------------------------------------- armsrc/tlv.h | 38 --------------------- 2 files changed, 132 deletions(-) delete mode 100644 armsrc/tlv.c delete mode 100644 armsrc/tlv.h diff --git a/armsrc/tlv.c b/armsrc/tlv.c deleted file mode 100644 index 839b34d66..000000000 --- a/armsrc/tlv.c +++ /dev/null @@ -1,94 +0,0 @@ -#include - -int decode_ber_tlv_item(uint8_t* data, tlvtag* returnedtag) -{ - uint8_t tag[TAG_LENGTH] = {0x00, 0x00, 0x00, 0x00}; - uint16_t length = 0; - //uint8_t value[VALUE_LENGTH]; - uint8_t lenlen = 0; - int i = 0; - int z = 0; - //decode tag - tag[0] = data[0]; - if ((tag[0] & TLV_TAG_NUMBER_MASK) == TLV_TAG_NUMBER_MASK) { //see subsequent bytes - i++; - - tag[i] = data[i]; - - while((data[i] & TLV_TAG_MASK) == TLV_TAG_MASK){ - i++; - tag[i] = data[i]; - } - - } - i++; - //decode length - if ((data[i] & TLV_LENGTH_MASK) == TLV_LENGTH_MASK) { - lenlen = data[i] ^ TLV_LENGTH_MASK; - i++; - length = (uint16_t)data[i]; - z = 1; - while (z < lenlen) { - i++; - z++; - length <<= 8; - length += (uint16_t)data[i]; - } - i++; - } else { - length = (uint16_t)data[i]; - i++; - } - // copy results into the structure and return - memcpy(returnedtag->tag, tag, TAG_LENGTH); - - // return length of tag value - (*returnedtag).valuelength = length; - - // return length of total field - (*returnedtag).fieldlength = length + i + 1; - - memcpy(returnedtag->value, &(data[i]), length); - return 0; -} - -//generate a TLV tag off input data -int encode_ber_tlv_item(uint8_t* tag, uint8_t taglen, uint8_t* data, uint32_t datalen, uint8_t* outputtag, uint32_t* outputtaglen) -{ - if (!tag || !data || !outputtag || !outputtaglen) - return 0; - - // field length of the tag - uint8_t datafieldlen = (datalen / 128) + 1; - - // total length of the tag - uint8_t tlvtotallen = taglen + datafieldlen + datalen; - - // buffer for the returned tag - uint8_t returnedtag[tlvtotallen]; - - uint8_t counter = 0; - - // copy tag into buffer - memcpy(returnedtag, tag, taglen); - counter += taglen; - - // 1 byte length value - if (datalen < 128){ - returnedtag[counter++] = datalen; - } else { - - // high bit set and number of length bytes - returnedtag[counter++] = datafieldlen | 0x80; - - for (uint8_t i = datafieldlen; i !=0; i--) { - // get current byte - returnedtag[counter++] = (datalen >> (i * 8)) & 0xFF; - } - } - memcpy(&returnedtag[counter], data, datalen); - *outputtaglen = tlvtotallen; - memcpy(outputtag, returnedtag, tlvtotallen); - return 0; -} - diff --git a/armsrc/tlv.h b/armsrc/tlv.h deleted file mode 100644 index de8180cab..000000000 --- a/armsrc/tlv.h +++ /dev/null @@ -1,38 +0,0 @@ -#ifndef __TLV_H -#define __TLV_H - -#include -#include -#include - -//structure buffer definitions -#ifndef TAG_LENGTH -# define TAG_LENGTH 4 -#endif - -#ifndef VALUE_LENGTH -# define VALUE_LENGTH 1024 -#endif - -//masks -//if TLV_TAG_NUMBER_MASK bits are set, refer to the next byte for the tag number -//otherwise its located in bits 1-5 -#define TLV_TAG_NUMBER_MASK 0x1f -//if TLV_DATA_MASK set then its a 'constructed data object' -//otherwise a 'primitive data object' -#define TLV_DATA_MASK 0x20 -#define TLV_TAG_MASK 0x80 -#define TLV_LENGTH_MASK 0x80 - -//tlv tag structure, tag can be max of 4 bytes, length up to 0xFFFFFFFF and value 1024 bytes long -typedef struct { - uint8_t tag[TAG_LENGTH]; - uint16_t fieldlength; - uint16_t valuelength; - uint8_t value[VALUE_LENGTH]; -} tlvtag; - -//decode a BER TLV -extern int decode_ber_tlv_item(uint8_t* data, tlvtag* returnedtag); -extern int encode_ber_tlv_item(uint8_t* tag, uint8_t taglen, uint8_t*data, uint32_t datalen, uint8_t* outputtag, uint32_t* outputtaglen); -#endif //__TLV_H From 88b2cf41de9f3793faf942c35de365e6c561f194 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 9 Jan 2019 18:46:55 +0200 Subject: [PATCH 0403/1938] add description --- client/emv/emvcore.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 621287031..b672004c3 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -781,7 +781,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { struct tlvdb *dac_db = emv_pki_recover_dac(issuer_pk, tlv, sda_tlv); if (dac_db) { const struct tlv *dac_tlv = tlvdb_get(dac_db, 0x9f45, NULL); - PrintAndLogEx(NORMAL, "SDA verified OK. (%02hhx:%02hhx)\n", dac_tlv->value[0], dac_tlv->value[1]); + PrintAndLogEx(NORMAL, "SDA verified OK. (Data Authentication Code: %02hhx:%02hhx)\n", dac_tlv->value[0], dac_tlv->value[1]); tlvdb_add(tlv, dac_db); } else { PrintAndLogEx(WARNING, "Error: SSAD verify error"); From 506da60cad7bf9d952deff2bb855add1369123ff Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 9 Jan 2019 18:47:26 +0200 Subject: [PATCH 0404/1938] hash init --- client/emv/emv_pki.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/emv/emv_pki.c b/client/emv/emv_pki.c index 602dcacce..593c8a00c 100644 --- a/client/emv/emv_pki.c +++ b/client/emv/emv_pki.c @@ -109,7 +109,8 @@ static unsigned char *emv_pki_decode_message(const struct emv_pk *enc_pk, } va_end(vl); - uint8_t hash[20] = {0}; + uint8_t hash[hash_len]; + memset(hash, 0, hash_len); memcpy(hash, crypto_hash_read(ch), hash_len); if (memcmp(data + data_len - 1 - hash_len, hash, hash_len)) { printf("ERROR: Calculated wrong hash\n"); From 20d29f35e5f9e0889539479b1ac5f1f3aa077f65 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 9 Jan 2019 19:32:08 +0200 Subject: [PATCH 0405/1938] SDA works --- client/emv/emv_pki.c | 43 +++++++++++++++++++++++++++++++++++++++++++ client/emv/emvcore.c | 2 +- 2 files changed, 44 insertions(+), 1 deletion(-) diff --git a/client/emv/emv_pki.c b/client/emv/emv_pki.c index 593c8a00c..40edc79e4 100644 --- a/client/emv/emv_pki.c +++ b/client/emv/emv_pki.c @@ -313,14 +313,57 @@ struct emv_pk *emv_pki_recover_icc_pe_cert(const struct emv_pk *pk, struct tlvdb NULL); } +unsigned char *emv_pki_sdatl_fill(const struct tlvdb *db, size_t *sdatl_len) { + uint8_t buf[2048] = {0}; + size_t len = 0; + + *sdatl_len = 0; + + const struct tlv *sda_tl = tlvdb_get(db, 0x9f4a, NULL); + if (!sda_tl || sda_tl->len <= 0) + return NULL; + + for (int i = 0; i < sda_tl->len; i++) { + uint32_t tag = sda_tl->value[i]; // here may be multibyte, but now not + const struct tlv *elm = tlvdb_get(db, tag, NULL); + if (elm) { + memcpy(&buf[len], elm->value, elm->len); + len += elm->len; + } + } + + if (len) { + *sdatl_len = len; + unsigned char *value = malloc(len); + memcpy(value, buf, len); + return value; + } + + return NULL; +} + + struct tlvdb *emv_pki_recover_dac_ex(const struct emv_pk *enc_pk, const struct tlvdb *db, const struct tlv *sda_tlv, bool showData) { size_t data_len; + + // Static Data Authentication Tag List + size_t sdatl_len; + unsigned char *sdatl = emv_pki_sdatl_fill(db, &sdatl_len); + struct tlv sda_tdata = { + .tag = 0x00, // dummy tag + .len = sdatl_len, + .value = sdatl + }; + unsigned char *data = emv_pki_decode_message(enc_pk, 3, &data_len, tlvdb_get(db, 0x93, NULL), sda_tlv, + &sda_tdata, NULL); + free(sdatl); // malloc here: emv_pki_sdatl_fill + if (!data || data_len < 5) return NULL; diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index b672004c3..743fa2f9e 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -653,7 +653,7 @@ int trSDA(struct tlvdb *tlv) { struct tlvdb *dac_db = emv_pki_recover_dac(issuer_pk, tlv, sda_tlv); if (dac_db) { const struct tlv *dac_tlv = tlvdb_get(dac_db, 0x9f45, NULL); - PrintAndLogEx(NORMAL, "SDA verified OK. (%02hhx:%02hhx)\n", dac_tlv->value[0], dac_tlv->value[1]); + PrintAndLogEx(NORMAL, "SDA verified OK. (Data Authentication Code: %02hhx:%02hhx)\n", dac_tlv->value[0], dac_tlv->value[1]); tlvdb_add(tlv, dac_db); } else { emv_pk_free(issuer_pk); From 4921308d8465051346065f94a4033f2463f63dfd Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 9 Jan 2019 21:03:56 +0200 Subject: [PATCH 0406/1938] some changes in DDA --- client/emv/emvcore.c | 40 ++++++++++++++++++++++------------------ 1 file changed, 22 insertions(+), 18 deletions(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 743fa2f9e..c4b815715 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -596,7 +596,7 @@ int EMVGenerateChallenge(EMVCommandChannel channel, bool LeaveFieldON, uint8_t * } int EMVInternalAuthenticate(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *DDOL, size_t DDOLLen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { - return EMVExchange(channel, LeaveFieldON, (sAPDU){0x00, 0x88, 0x00, 0x00, DDOLLen, DDOL}, Result, MaxResultLen, ResultLen, sw, tlv); + return EMVExchangeEx(channel, false, LeaveFieldON, (sAPDU){0x00, 0x88, 0x00, 0x00, DDOLLen, DDOL}, true, Result, MaxResultLen, ResultLen, sw, tlv); } int MSCComputeCryptoChecksum(EMVCommandChannel channel, bool LeaveFieldON, uint8_t *UDOL, uint8_t UDOLlen, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw, struct tlvdb *tlv) { @@ -682,12 +682,12 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { } const struct tlv *sda_tlv = tlvdb_get(tlv, 0x21, NULL); - if (!sda_tlv || sda_tlv->len < 1) { +/* if (!sda_tlv || sda_tlv->len < 1) { it may be 0!!!! emv_pk_free(pk); PrintAndLogEx(WARNING, "Error: Can't find input list for Offline Data Authentication. Exit."); return 3; } - +*/ struct emv_pk *issuer_pk = emv_pki_recover_issuer_cert(pk, tlv); if (!issuer_pk) { emv_pk_free(pk); @@ -710,7 +710,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { if (!icc_pk) { emv_pk_free(pk); emv_pk_free(issuer_pk); - PrintAndLogEx(WARNING, "Error: ICC setrificate not found. Exit."); + PrintAndLogEx(WARNING, "Error: ICC certificate not found. Exit."); return 2; } PrintAndLogEx(SUCCESS, "ICC PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx\n", @@ -725,21 +725,25 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { icc_pk->serial[2] ); - struct emv_pk *icc_pe_pk = emv_pki_recover_icc_pe_cert(issuer_pk, tlv); - if (!icc_pe_pk) { - PrintAndLogEx(WARNING, "WARNING: ICC PE PK recover error. "); + if (tlvdb_get(tlv, 0x9f2d, NULL)) { + struct emv_pk *icc_pe_pk = emv_pki_recover_icc_pe_cert(issuer_pk, tlv); + if (!icc_pe_pk) { + PrintAndLogEx(WARNING, "WARNING: ICC PE PK recover error. "); + } else { + PrintAndLogEx(SUCCESS, "ICC PE PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx\n", + icc_pe_pk->rid[0], + icc_pe_pk->rid[1], + icc_pe_pk->rid[2], + icc_pe_pk->rid[3], + icc_pe_pk->rid[4], + icc_pe_pk->index, + icc_pe_pk->serial[0], + icc_pe_pk->serial[1], + icc_pe_pk->serial[2] + ); + } } else { - PrintAndLogEx(SUCCESS, "ICC PE PK recovered. RID %02hhx:%02hhx:%02hhx:%02hhx:%02hhx IDX %02hhx CSN %02hhx:%02hhx:%02hhx\n", - icc_pe_pk->rid[0], - icc_pe_pk->rid[1], - icc_pe_pk->rid[2], - icc_pe_pk->rid[3], - icc_pe_pk->rid[4], - icc_pe_pk->index, - icc_pe_pk->serial[0], - icc_pe_pk->serial[1], - icc_pe_pk->serial[2] - ); + PrintAndLogEx(INFO, "ICC PE PK (PIN Encipherment Public Key Certificate) not found.\n"); } // 9F4B: Signed Dynamic Application Data From 56c0dad966fa7d0340333819dfaa1e87fcc13487 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 9 Jan 2019 21:05:52 +0200 Subject: [PATCH 0407/1938] changes in cert decoding logic --- client/emv/emv_pki.c | 39 +++++++++++++++++++++++++++++++-------- client/emv/emv_pki.h | 1 + 2 files changed, 32 insertions(+), 8 deletions(-) diff --git a/client/emv/emv_pki.c b/client/emv/emv_pki.c index 40edc79e4..84224a957 100644 --- a/client/emv/emv_pki.c +++ b/client/emv/emv_pki.c @@ -41,7 +41,8 @@ static unsigned char *emv_pki_decode_message(const struct emv_pk *enc_pk, uint8_t msgtype, size_t *len, const struct tlv *cert_tlv, - ... /* A list of tlv pointers, end with NULL */ + int tlv_count, + ... /* A list of tlv pointers */ ) { struct crypto_pk *kcp; @@ -99,11 +100,11 @@ static unsigned char *emv_pki_decode_message(const struct emv_pk *enc_pk, size_t hash_len = crypto_hash_get_size(ch); crypto_hash_write(ch, data + 1, data_len - 2 - hash_len); - va_start(vl, cert_tlv); - while (true) { + va_start(vl, tlv_count); + for (int i = 0; i < tlv_count; i++) { const struct tlv *add_tlv = va_arg(vl, const struct tlv *); if (!add_tlv) - break; + continue; crypto_hash_write(ch, add_tlv->value, add_tlv->len); } @@ -168,6 +169,7 @@ static struct emv_pk *emv_pki_decode_key_ex(const struct emv_pk *enc_pk, const struct tlv *exp_tlv, const struct tlv *rem_tlv, const struct tlv *add_tlv, + const struct tlv *sdatl_tlv, bool showData ) { @@ -193,9 +195,11 @@ static struct emv_pk *emv_pki_decode_key_ex(const struct emv_pk *enc_pk, data = emv_pki_decode_message(enc_pk, msgtype, &data_len, cert_tlv, + 5, rem_tlv, exp_tlv, add_tlv, + sdatl_tlv, NULL); if (!data || data_len < 11 + pan_length) { printf("ERROR: Can't decode message\n"); @@ -278,9 +282,10 @@ static struct emv_pk *emv_pki_decode_key(const struct emv_pk *enc_pk, const struct tlv *cert_tlv, const struct tlv *exp_tlv, const struct tlv *rem_tlv, - const struct tlv *add_tlv + const struct tlv *add_tlv, + const struct tlv *sdatl_tlv ) { - return emv_pki_decode_key_ex(enc_pk, msgtype, pan_tlv, cert_tlv, exp_tlv, rem_tlv, add_tlv, false); + return emv_pki_decode_key_ex(enc_pk, msgtype, pan_tlv, cert_tlv, exp_tlv, rem_tlv, add_tlv, sdatl_tlv, false); } struct emv_pk *emv_pki_recover_issuer_cert(const struct emv_pk *pk, struct tlvdb *db) @@ -290,17 +295,30 @@ struct emv_pk *emv_pki_recover_issuer_cert(const struct emv_pk *pk, struct tlvdb tlvdb_get(db, 0x90, NULL), tlvdb_get(db, 0x9f32, NULL), tlvdb_get(db, 0x92, NULL), + NULL, NULL); } struct emv_pk *emv_pki_recover_icc_cert(const struct emv_pk *pk, struct tlvdb *db, const struct tlv *sda_tlv) { - return emv_pki_decode_key(pk, 4, + size_t sdatl_len; + unsigned char *sdatl = emv_pki_sdatl_fill(db, &sdatl_len); + struct tlv sda_tdata = { + .tag = 0x00, // dummy tag + .len = sdatl_len, + .value = sdatl + }; + + struct emv_pk *res = emv_pki_decode_key(pk, 4, tlvdb_get(db, 0x5a, NULL), tlvdb_get(db, 0x9f46, NULL), tlvdb_get(db, 0x9f47, NULL), tlvdb_get(db, 0x9f48, NULL), - sda_tlv); + sda_tlv, + &sda_tdata); + + free(sdatl); // malloc here: emv_pki_sdatl_fill + return res; } struct emv_pk *emv_pki_recover_icc_pe_cert(const struct emv_pk *pk, struct tlvdb *db) @@ -310,6 +328,7 @@ struct emv_pk *emv_pki_recover_icc_pe_cert(const struct emv_pk *pk, struct tlvdb tlvdb_get(db, 0x9f2d, NULL), tlvdb_get(db, 0x9f2e, NULL), tlvdb_get(db, 0x9f2f, NULL), + NULL, NULL); } @@ -358,6 +377,7 @@ struct tlvdb *emv_pki_recover_dac_ex(const struct emv_pk *enc_pk, const struct t unsigned char *data = emv_pki_decode_message(enc_pk, 3, &data_len, tlvdb_get(db, 0x93, NULL), + 3, sda_tlv, &sda_tdata, NULL); @@ -391,6 +411,7 @@ struct tlvdb *emv_pki_recover_idn_ex(const struct emv_pk *enc_pk, const struct t size_t data_len; unsigned char *data = emv_pki_decode_message(enc_pk, 5, &data_len, tlvdb_get(db, 0x9f4b, NULL), + 2, dyn_tlv, NULL); @@ -426,6 +447,7 @@ struct tlvdb *emv_pki_recover_atc_ex(const struct emv_pk *enc_pk, const struct t size_t data_len; unsigned char *data = emv_pki_decode_message(enc_pk, 5, &data_len, tlvdb_get(db, 0x9f4b, NULL), + 5, tlvdb_get(db, 0x9f37, NULL), tlvdb_get(db, 0x9f02, NULL), tlvdb_get(db, 0x5f2a, NULL), @@ -502,6 +524,7 @@ struct tlvdb *emv_pki_perform_cda_ex(const struct emv_pk *enc_pk, const struct t size_t data_len = 0; unsigned char *data = emv_pki_decode_message(enc_pk, 5, &data_len, tlvdb_get(this_db, 0x9f4b, NULL), + 2, un_tlv, NULL); if (!data || data_len < 3) { diff --git a/client/emv/emv_pki.h b/client/emv/emv_pki.h index 6fa7b12e9..f5d80bd6d 100644 --- a/client/emv/emv_pki.h +++ b/client/emv/emv_pki.h @@ -23,6 +23,7 @@ extern void PKISetStrictExecution(bool se); +unsigned char *emv_pki_sdatl_fill(const struct tlvdb *db, size_t *sdatl_len); struct emv_pk *emv_pki_recover_issuer_cert(const struct emv_pk *pk, struct tlvdb *db); struct emv_pk *emv_pki_recover_icc_cert(const struct emv_pk *pk, struct tlvdb *db, const struct tlv *sda_tlv); struct emv_pk *emv_pki_recover_icc_pe_cert(const struct emv_pk *pk, struct tlvdb *db); From 0ac728f0d47ee644120c8e44df68663595b5be99 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 10 Jan 2019 13:06:56 +0200 Subject: [PATCH 0408/1938] VSDC path sketch --- client/emv/cmdemv.c | 11 +++++++++-- client/emv/emvcore.c | 2 +- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 0cc6614d9..708e0d562 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -731,9 +731,9 @@ int CmdEMVExec(const char *cmd) { enum TransactionType TrType = TT_MSD; if (arg_get_lit(7)) - TrType = TT_QVSDCMCHIP; + TrType = TT_QVSDCMCHIP; if (arg_get_lit(8)) - TrType = TT_CDA; + TrType = TT_CDA; if (arg_get_lit(9)) TrType = TT_VSDC; @@ -1130,6 +1130,13 @@ int CmdEMVExec(const char *cmd) { } } + // VSDC + if (GetCardPSVendor(AID, AIDlen) == CV_VISA && (TrType == TT_VSDC)){ + PrintAndLogEx(NORMAL, "\n--> VSDC transaction."); + + + } + DropField(); // Destroy TLV's diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index c4b815715..a7d625af8 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -785,7 +785,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { struct tlvdb *dac_db = emv_pki_recover_dac(issuer_pk, tlv, sda_tlv); if (dac_db) { const struct tlv *dac_tlv = tlvdb_get(dac_db, 0x9f45, NULL); - PrintAndLogEx(NORMAL, "SDA verified OK. (Data Authentication Code: %02hhx:%02hhx)\n", dac_tlv->value[0], dac_tlv->value[1]); + PrintAndLogEx(NORMAL, "SDAD verified OK. (Data Authentication Code: %02hhx:%02hhx)\n", dac_tlv->value[0], dac_tlv->value[1]); tlvdb_add(tlv, dac_db); } else { PrintAndLogEx(WARNING, "Error: SSAD verify error"); From 8240639d73bf1114c414fc2a6dcb190bc6dabe61 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 10 Jan 2019 13:22:27 +0200 Subject: [PATCH 0409/1938] fill VSDC with only AC1 --- client/emv/cmdemv.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 708e0d562..46ed20165 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1134,6 +1134,34 @@ int CmdEMVExec(const char *cmd) { if (GetCardPSVendor(AID, AIDlen) == CV_VISA && (TrType == TT_VSDC)){ PrintAndLogEx(NORMAL, "\n--> VSDC transaction."); + PrintAndLogEx(NORMAL, "* * Calc CDOL1"); + struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag + if (!cdol_data_tlv) { + PrintAndLogEx(WARNING, "Error: can't create CDOL1 TLV."); + dreturn(6); + } + + PrintAndLogEx(NORMAL, "CDOL1 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len)); + + PrintAndLogEx(NORMAL, "* * AC1"); + // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD + res = EMVAC(channel, true, (TrType == TT_CDA) ? EMVAC_TC + EMVAC_CDAREQ : EMVAC_TC, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot); + + if (res) { + PrintAndLogEx(NORMAL, "AC1 error(%d): %4x. Exit...", res, sw); + dreturn(7); + } + + if (decodeTLV) + TLVPrintFromBuffer(buf, len); + + PrintAndLogEx(NORMAL, "\n* * Processing online request\n"); + + // authorization response code from acquirer + const char HostResponse[] = "0"; + PrintAndLogEx(NORMAL, "* * Host Response: `%s`", HostResponse); + tlvdb_change_or_add_node(tlvRoot, 0x8a, sizeof(HostResponse) - 1, (const unsigned char *)HostResponse); + } From 70744d2cbbdf412d97d1624b21c86cf52890c429 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 10 Jan 2019 13:26:15 +0200 Subject: [PATCH 0410/1938] small fix --- client/emv/cmdemv.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 46ed20165..2274f3d69 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1131,7 +1131,7 @@ int CmdEMVExec(const char *cmd) { } // VSDC - if (GetCardPSVendor(AID, AIDlen) == CV_VISA && (TrType == TT_VSDC)){ + if (GetCardPSVendor(AID, AIDlen) == CV_VISA && (TrType == TT_VSDC || TrType == TT_CDA)){ PrintAndLogEx(NORMAL, "\n--> VSDC transaction."); PrintAndLogEx(NORMAL, "* * Calc CDOL1"); @@ -1158,7 +1158,7 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "\n* * Processing online request\n"); // authorization response code from acquirer - const char HostResponse[] = "0"; + const char HostResponse[] = "00"; // 0x3030 PrintAndLogEx(NORMAL, "* * Host Response: `%s`", HostResponse); tlvdb_change_or_add_node(tlvRoot, 0x8a, sizeof(HostResponse) - 1, (const unsigned char *)HostResponse); From 607bef7ffd2be0403b907f7c720e531c5dbe7161 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 10 Jan 2019 16:22:32 +0200 Subject: [PATCH 0411/1938] AC Response Format1 --- client/emv/cmdemv.c | 53 ++++++++++++++++++++++++++++++++++++++++++--- client/emv/tlv.c | 15 +++++++++++-- client/emv/tlv.h | 1 + 3 files changed, 64 insertions(+), 5 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 2274f3d69..a30c22aec 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -38,6 +38,9 @@ void ParamLoadDefaults(struct tlvdb *tlvRoot) { TLV_ADD(0x9F6A, "\x01\x02\x03\x04"); //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4 TLV_ADD(0x9F66, "\x26\x00\x00\x00"); // qVSDC + //95:(Terminal Verification Results) len:5 + // all OK TVR + TLV_ADD(0x95, "\x00\x00\x00\x00\x00"); } void PrintChannel(EMVCommandChannel channel) { @@ -685,6 +688,50 @@ void ProcessGPOResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, } } +void ProcessACResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, bool decodeTLV) { + if (buf[0] == 0x80) { + if (decodeTLV){ + PrintAndLog("GPO response format1:"); + TLVPrintFromBuffer(buf, len); + } + + uint8_t elmlen = len - 2; // wo 0x80XX + + if (len < 4 + 2 || (elmlen - 2) % 4 || elmlen != buf[1]) { + PrintAndLogEx(ERR, "GPO response format1 parsing error. length=%d", len); + } else { + struct tlvdb *tlvElm = NULL; + if (decodeTLV) + PrintAndLog("\n------------ Format1 decoded ------------"); + + // CID (Cryptogram Information Data) + tlvdb_change_or_add_node_ex(tlvRoot, 0x9f27, 1, &buf[2], &tlvElm); + if (decodeTLV) + TLVPrintFromTLV(tlvElm); + + // ATC (Application Transaction Counter) + tlvdb_change_or_add_node_ex(tlvRoot, 0x9f36, 2, &buf[3], &tlvElm); + if (decodeTLV) + TLVPrintFromTLV(tlvElm); + + // AC (Application Cryptogram) + tlvdb_change_or_add_node_ex(tlvRoot, 0x9f26, min(8, elmlen - 3), &buf[5], &tlvElm); + if (decodeTLV) + TLVPrintFromTLV(tlvElm); + + // IAD (Issuer Application Data) - optional + if (len > 11 + 2) { + tlvdb_change_or_add_node_ex(tlvRoot, 0x9f10, elmlen - 11, &buf[13], &tlvElm); + if (decodeTLV) + TLVPrintFromTLV(tlvElm); + } + } + } else { + if (decodeTLV) + TLVPrintFromBuffer(buf, len); + } +} + int CmdEMVExec(const char *cmd) { uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; @@ -1151,9 +1198,9 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "AC1 error(%d): %4x. Exit...", res, sw); dreturn(7); } - - if (decodeTLV) - TLVPrintFromBuffer(buf, len); + + // process Format1 (0x80) anf print Format2 (0x77) + ProcessACResponseFormat1(tlvRoot, buf, len, decodeTLV); PrintAndLogEx(NORMAL, "\n* * Processing online request\n"); diff --git a/client/emv/tlv.c b/client/emv/tlv.c index 013e9735a..9722c9311 100644 --- a/client/emv/tlv.c +++ b/client/emv/tlv.c @@ -359,12 +359,15 @@ void tlvdb_add(struct tlvdb *tlvdb, struct tlvdb *other) tlvdb->next = other; } -void tlvdb_change_or_add_node(struct tlvdb *tlvdb, tlv_tag_t tag, size_t len, const unsigned char *value) +void tlvdb_change_or_add_node_ex(struct tlvdb *tlvdb, tlv_tag_t tag, size_t len, const unsigned char *value, struct tlvdb **tlvdb_elm) { struct tlvdb *telm = tlvdb_find_full(tlvdb, tag); if (telm == NULL) { // new tlv element - tlvdb_add(tlvdb, tlvdb_fixed(tag, len, value)); + struct tlvdb *elm = tlvdb_fixed(tag, len, value); + tlvdb_add(tlvdb, elm); + if (tlvdb_elm) + *tlvdb_elm = elm; } else { // the same tlv structure if (telm->tag.tag == tag && telm->tag.len == len && !memcmp(telm->tag.value, value, len)) @@ -400,11 +403,19 @@ void tlvdb_change_or_add_node(struct tlvdb *tlvdb, tlv_tag_t tag, size_t len, co // free old element with childrens telm->next = NULL; tlvdb_free(telm); + + if (tlvdb_elm) + *tlvdb_elm = tnewelm; } return; } +void tlvdb_change_or_add_node(struct tlvdb *tlvdb, tlv_tag_t tag, size_t len, const unsigned char *value) +{ + tlvdb_change_or_add_node_ex(tlvdb, tag, len, value, NULL); +} + void tlvdb_visit(const struct tlvdb *tlvdb, tlv_cb cb, void *data, int level) { struct tlvdb *next = NULL; diff --git a/client/emv/tlv.h b/client/emv/tlv.h index d2a55525f..1f52e440b 100644 --- a/client/emv/tlv.h +++ b/client/emv/tlv.h @@ -50,6 +50,7 @@ struct tlvdb *tlvdb_find_path(struct tlvdb *tlvdb, tlv_tag_t tag[]); void tlvdb_add(struct tlvdb *tlvdb, struct tlvdb *other); void tlvdb_change_or_add_node(struct tlvdb *tlvdb, tlv_tag_t tag, size_t len, const unsigned char *value); +void tlvdb_change_or_add_node_ex(struct tlvdb *tlvdb, tlv_tag_t tag, size_t len, const unsigned char *value, struct tlvdb **tlvdb_elm); void tlvdb_visit(const struct tlvdb *tlvdb, tlv_cb cb, void *data, int level); const struct tlv *tlvdb_get(const struct tlvdb *tlvdb, tlv_tag_t tag, const struct tlv *prev); From 170cf7c67a49eeb3e976e5621ca6ec778c491d98 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 10 Jan 2019 17:06:59 +0200 Subject: [PATCH 0412/1938] inc timeout of card's response --- common/i2c.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/common/i2c.c b/common/i2c.c index 99f8b6e12..25b17b6bc 100644 --- a/common/i2c.c +++ b/common/i2c.c @@ -161,10 +161,11 @@ bool WaitSCL_L(void) { return WaitSCL_L_delay(15000); } -// Wait max 300ms or until SCL goes LOW. +// Wait max 1800ms or until SCL goes LOW. +// It timeout reading response from card // Which ever comes first -bool WaitSCL_L_300ms(void){ - volatile uint16_t delay = 310; +bool WaitSCL_L_timeout(void){ + volatile uint16_t delay = 1800; while ( delay-- ) { // exit on SCL LOW if (!SCL_read) @@ -193,7 +194,8 @@ bool I2C_Start(void) { bool I2C_WaitForSim() { - if (!WaitSCL_L_300ms()) + // wait for data from card + if (!WaitSCL_L_timeout()) return false; // 8051 speaks with smart card. From cada4e4877a5c311216416c7425c5623ba39f0ae Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 10 Jan 2019 17:24:45 +0200 Subject: [PATCH 0413/1938] DDA works --- client/emv/emvcore.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index a7d625af8..5ea9026c2 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -829,9 +829,16 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { if (len < 3 ) { PrintAndLogEx(WARNING, "Error: Internal Authenticate format1 parsing error. length=%d", len); } else { + // parse response 0x80 + struct tlvdb *t80 = tlvdb_parse_multi(buf, len); + const struct tlv * t80tlv = tlvdb_get_tlv(t80); + // 9f4b Signed Dynamic Application Data - dda_db = tlvdb_fixed(0x9f4b, len - 2, buf + 2); + dda_db = tlvdb_fixed(0x9f4b, t80tlv->len, t80tlv->value); tlvdb_add(tlv, dda_db); + + tlvdb_free(t80); + if (decodeTLV){ PrintAndLogEx(NORMAL, "* * Decode response format 1:"); TLVPrintFromTLV(dda_db); From 628eceb5ed7b56a32cffba38e6c4095a45acba32 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 10 Jan 2019 17:44:51 +0200 Subject: [PATCH 0414/1938] print fix --- client/emv/emvcore.c | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 5ea9026c2..023035a7d 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -795,7 +795,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { return 4; } - PrintAndLogEx(NORMAL, "\n* Calc DDOL"); + PrintAndLogEx(NORMAL, "\n* * Calc DDOL"); const struct tlv *ddol_tlv = tlvdb_get(tlv, 0x9f49, NULL); if (!ddol_tlv) { ddol_tlv = &default_ddol_tlv; @@ -813,7 +813,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { PrintAndLogEx(NORMAL, "DDOL data[%d]: %s", ddol_data_tlv->len, sprint_hex(ddol_data_tlv->value, ddol_data_tlv->len)); - PrintAndLogEx(NORMAL, "\n* Internal Authenticate"); + PrintAndLogEx(NORMAL, "\n* * Internal Authenticate"); int res = EMVInternalAuthenticate(channel, true, (uint8_t *)ddol_data_tlv->value, ddol_data_tlv->len, buf, sizeof(buf), &len, &sw, NULL); if (res) { PrintAndLogEx(WARNING, "Internal Authenticate error(%d): %4x. Exit...", res, sw); @@ -840,7 +840,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { tlvdb_free(t80); if (decodeTLV){ - PrintAndLogEx(NORMAL, "* * Decode response format 1:"); + PrintAndLogEx(NORMAL, "* * * Decode response format 1:"); TLVPrintFromTLV(dda_db); } } @@ -875,12 +875,12 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { // 9f4c ICC Dynamic Number const struct tlv *idn_tlv = tlvdb_get(idn_db, 0x9f4c, NULL); if(idn_tlv) { - PrintAndLogEx(NORMAL, "\nIDN (ICC Dynamic Number) [%zu] %s", idn_tlv->len, sprint_hex_inrow(idn_tlv->value, idn_tlv->len)); - PrintAndLogEx(NORMAL, "DDA verified OK."); + PrintAndLogEx(INFO, "\nIDN (ICC Dynamic Number) [%zu] %s", idn_tlv->len, sprint_hex_inrow(idn_tlv->value, idn_tlv->len)); + PrintAndLogEx(INFO, "DDA verified OK."); tlvdb_add(tlv, idn_db); tlvdb_free(idn_db); } else { - PrintAndLogEx(NORMAL, "\nERROR: DDA verify error"); + PrintAndLogEx(ERR, "\nDDA verify error"); tlvdb_free(idn_db); emv_pk_free(pk); From eaedf7f81101e972887ad749cdb99ef29c3188a2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 10 Jan 2019 18:33:21 +0200 Subject: [PATCH 0415/1938] VSDC up to CDOL2 calc --- client/emv/cmdemv.c | 17 +++++++++++++++++ client/emv/tlv.c | 12 +++++++++++- client/emv/tlv.h | 2 ++ 3 files changed, 30 insertions(+), 1 deletion(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index a30c22aec..114aca322 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1209,6 +1209,23 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "* * Host Response: `%s`", HostResponse); tlvdb_change_or_add_node(tlvRoot, 0x8a, sizeof(HostResponse) - 1, (const unsigned char *)HostResponse); + // needs to send AC2 command (res == ARQC) + uint8_t CID = 0; + tlvdb_get_uint8(tlvRoot, 0x9f27, &CID); + if ((CID & 0xc0) == 0x80) { + PrintAndLogEx(NORMAL, "* * Calc CDOL2"); + struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8d, NULL), tlvRoot, 0x01); // 0x01 - dummy tag + if (!cdol_data_tlv) { + PrintAndLogEx(WARNING, "Error: can't create CDOL2 TLV."); + dreturn(6); + } + + PrintAndLogEx(NORMAL, "CDOL2 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len)); + + PrintAndLogEx(NORMAL, "* * AC2"); + + + } } diff --git a/client/emv/tlv.c b/client/emv/tlv.c index 9722c9311..8d1429640 100644 --- a/client/emv/tlv.c +++ b/client/emv/tlv.c @@ -469,7 +469,10 @@ const struct tlv *tlvdb_get_inchild(const struct tlvdb *tlvdb, tlv_tag_t tag, co } const struct tlv *tlvdb_get_tlv(const struct tlvdb *tlvdb) { - return &tlvdb->tag; + if (tlvdb) + return &tlvdb->tag; + else + return NULL; } unsigned char *tlv_encode(const struct tlv *tlv, size_t *len) @@ -546,6 +549,13 @@ struct tlvdb *tlvdb_elm_get_parent(struct tlvdb *tlvdb) return tlvdb->parent; } +bool tlvdb_get_uint8(struct tlvdb *tlvRoot, tlv_tag_t tag, uint8_t *value) +{ + const struct tlvdb *tlvdb = tlvdb_get(tlvRoot, tag, NULL); + const struct tlv *tlvelm = tlvdb_get_tlv(tlvdb); + return tlv_get_uint8(tlvelm, value); +} + bool tlv_get_uint8(const struct tlv *etlv, uint8_t *value) { *value = 0; diff --git a/client/emv/tlv.h b/client/emv/tlv.h index 1f52e440b..e75bbf986 100644 --- a/client/emv/tlv.h +++ b/client/emv/tlv.h @@ -65,4 +65,6 @@ bool tlv_equal(const struct tlv *a, const struct tlv *b); bool tlv_get_uint8(const struct tlv *etlv, uint8_t *value); bool tlv_get_int(const struct tlv *etlv, int *value); +bool tlvdb_get_uint8(struct tlvdb *tlvRoot, tlv_tag_t tag, uint8_t *value); + #endif From e058d87dc11ec2c3117d8848ea68b54a9c779e65 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 10 Jan 2019 19:28:43 +0200 Subject: [PATCH 0416/1938] fix CDOL generation and add AC1 print result --- client/emv/cmdemv.c | 35 +++++++++++++++++++++++++---------- client/emv/emv_tags.h | 4 ++++ 2 files changed, 29 insertions(+), 10 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 114aca322..07543241c 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1182,17 +1182,17 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "\n--> VSDC transaction."); PrintAndLogEx(NORMAL, "* * Calc CDOL1"); - struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag - if (!cdol_data_tlv) { + struct tlv *cdol1_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag + if (!cdol1_data_tlv) { PrintAndLogEx(WARNING, "Error: can't create CDOL1 TLV."); dreturn(6); } - PrintAndLogEx(NORMAL, "CDOL1 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len)); + PrintAndLogEx(NORMAL, "CDOL1 data[%d]: %s", cdol1_data_tlv->len, sprint_hex(cdol1_data_tlv->value, cdol1_data_tlv->len)); PrintAndLogEx(NORMAL, "* * AC1"); // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD - res = EMVAC(channel, true, (TrType == TT_CDA) ? EMVAC_TC + EMVAC_CDAREQ : EMVAC_TC, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot); + res = EMVAC(channel, true, (TrType == TT_CDA) ? EMVAC_TC + EMVAC_CDAREQ : EMVAC_TC, (uint8_t *)cdol1_data_tlv->value, cdol1_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot); if (res) { PrintAndLogEx(NORMAL, "AC1 error(%d): %4x. Exit...", res, sw); @@ -1201,7 +1201,17 @@ int CmdEMVExec(const char *cmd) { // process Format1 (0x80) anf print Format2 (0x77) ProcessACResponseFormat1(tlvRoot, buf, len, decodeTLV); - + + uint8_t CID = 0; + tlvdb_get_uint8(tlvRoot, 0x9f27, &CID); + + // AC1 print result + PrintAndLog(""); + if ((CID & EMVAC_AC_MASK) == EMVAC_AAC) PrintAndLogEx(INFO, "AC1 result: AAC (Transaction declined)"); + if ((CID & EMVAC_AC_MASK) == EMVAC_TC) PrintAndLogEx(INFO, "AC1 result: TC (Transaction approved)"); + if ((CID & EMVAC_AC_MASK) == EMVAC_ARQC) PrintAndLogEx(INFO, "AC1 result: ARQC (Online authorisation requested)"); + if ((CID & EMVAC_AC_MASK) == EMVAC_AC_MASK) PrintAndLogEx(INFO, "AC1 result: RFU"); + PrintAndLogEx(NORMAL, "\n* * Processing online request\n"); // authorization response code from acquirer @@ -1210,21 +1220,26 @@ int CmdEMVExec(const char *cmd) { tlvdb_change_or_add_node(tlvRoot, 0x8a, sizeof(HostResponse) - 1, (const unsigned char *)HostResponse); // needs to send AC2 command (res == ARQC) - uint8_t CID = 0; - tlvdb_get_uint8(tlvRoot, 0x9f27, &CID); if ((CID & 0xc0) == 0x80) { PrintAndLogEx(NORMAL, "* * Calc CDOL2"); - struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8d, NULL), tlvRoot, 0x01); // 0x01 - dummy tag - if (!cdol_data_tlv) { + struct tlv *cdol2_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8d, NULL), tlvRoot, 0x01); // 0x01 - dummy tag + if (!cdol2_data_tlv) { PrintAndLogEx(WARNING, "Error: can't create CDOL2 TLV."); dreturn(6); } - PrintAndLogEx(NORMAL, "CDOL2 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len)); + PrintAndLogEx(NORMAL, "CDOL2 data[%d]: %s", cdol2_data_tlv->len, sprint_hex(cdol2_data_tlv->value, cdol2_data_tlv->len)); PrintAndLogEx(NORMAL, "* * AC2"); +/* // AC2 + PRINT_INDENT(level); + if ((CID & EMVAC_AC2_MASK) == EMVAC_AAC2) fprintf(f, "\tAC2: AAC (Transaction declined)\n"); + if ((CID & EMVAC_AC2_MASK) == EMVAC_TC2) fprintf(f, "\tAC2: TC (Transaction approved)\n"); + if ((CID & EMVAC_AC2_MASK) == EMVAC_ARQC2) fprintf(f, "\tAC2: not requested (ARQC)\n"); + if ((CID & EMVAC_AC2_MASK) == EMVAC_AC2_MASK) fprintf(f, "\tAC2: RFU\n"); +*/ } } diff --git a/client/emv/emv_tags.h b/client/emv/emv_tags.h index 246fc72d7..f7d9a8476 100644 --- a/client/emv/emv_tags.h +++ b/client/emv/emv_tags.h @@ -25,6 +25,10 @@ # define EMVAC_TC 0x40 # define EMVAC_ARQC 0x80 # define EMVAC_CDAREQ 0x10 +# define EMVAC_AC2_MASK 0x30 +# define EMVAC_AAC2 0x00 +# define EMVAC_TC2 0x10 +# define EMVAC_ARQC2 0x20 // CID # define EMVCID_ADVICE 0x08 From bd0e33fb58151411f56e10da41e112ec528b587e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 10 Jan 2019 18:55:56 +0100 Subject: [PATCH 0417/1938] chg: 'script run read_pwd_mem' - m|t|i params to simplify printing dictionary items --- client/scripts/read_pwd_mem.lua | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/client/scripts/read_pwd_mem.lua b/client/scripts/read_pwd_mem.lua index 772927c0c..a0688a639 100644 --- a/client/scripts/read_pwd_mem.lua +++ b/client/scripts/read_pwd_mem.lua @@ -21,6 +21,9 @@ Arguments: -o : memory offset, default is 0 -l : length in bytes, default is 256 -k : key length in bytes <4|6|8> , default is 4 + -m : print Mifare dictionary keys + -t : print t55xx dictionary passwords + -i : print iClass dictionary keys ]] example = [[ @@ -67,7 +70,7 @@ local function main(args) local keylength = 4 local usedkey = false - for o, a in getopt.getopt(args, 'ho:l:k:') do + for o, a in getopt.getopt(args, 'ho:l:k:mti') do -- help if o == "h" then return help() end @@ -80,6 +83,10 @@ local function main(args) -- keylength if o == "k" then keylength = tonumber(a); usedkey = true end + + if o == "m" then keylength =6; usedkey = true; offset = 0x3F000-0x4000; end + if o == "t" then keylength =4; usedkey = true; offset = 0x3F000-0x3000; end + if o == "i" then keylength =8; usedkey = true; offset = 0x3F000-0x5000; end end if length < 0 or length > 256 then From 43d57855a00232ed2de92212d65031ff3d46443b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 11 Jan 2019 12:56:59 +0100 Subject: [PATCH 0418/1938] CHG: wrong define --- client/emv/cmdemv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index a30c22aec..91a3663f3 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -715,7 +715,7 @@ void ProcessACResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, b TLVPrintFromTLV(tlvElm); // AC (Application Cryptogram) - tlvdb_change_or_add_node_ex(tlvRoot, 0x9f26, min(8, elmlen - 3), &buf[5], &tlvElm); + tlvdb_change_or_add_node_ex(tlvRoot, 0x9f26, MIN(8, elmlen - 3), &buf[5], &tlvElm); if (decodeTLV) TLVPrintFromTLV(tlvElm); From f215ebef80c5875d4d5f1fcbe6c569bf9bb8294d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 11 Jan 2019 14:46:27 +0100 Subject: [PATCH 0419/1938] Refactored 'lf t55xx brute', split it up into two commands. - lf t55xx brute (tries bruteforcing a range of pwds - lf t55xx chk (uses dictionary file or RDV4 flashmem) FIX: adjust lf sim (@marshmellow42) see https://github.com/marshmellow42/proxmark3/commit/7008cf9c15a135a066227635e64f59285eb73a80 "attempt to speed up the loops waiting for carrier signal to go high or low by only checking for a halt (button press or usbpol) every 256th loop iteration. some users were experiencing modulating reactions to be too slow. ADD: 'lf t55xx chk' It uses @marshmellows42 idea behind commit (https://github.com/marshmellow42/proxmark3/commit/6178b085a0374e656cce3849e481fa5800403c2b) With calculating a baseline (read block0 32times and average the signal-ish) and sampling only 1024 signal data. The algo then proceeds to calc the average and keep track of the candidate which is given the most difference in signal data average value. I do some squaring and shifting for this. The candidate is then send back to client to be tested properly with trymodulation like before. This seems to work good on t55xx card which has a ASK configuration. WORK-IN-PROGRESS --- armsrc/appmain.c | 3 + armsrc/apps.h | 2 + armsrc/lfops.c | 153 +++++++++++++++++++++++++++++++++++++++----- client/cmdlft55xx.c | 153 ++++++++++++++++++++++++++++++++------------ client/cmdlft55xx.h | 1 + include/usb_cmd.h | 2 + 6 files changed, 255 insertions(+), 59 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 8759f93c4..0bf9ccb9d 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -724,6 +724,9 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_T55XX_RESET_READ: T55xxResetRead(); break; + case CMD_T55XX_CHKPWDS: + T55xx_ChkPwds(); + break; case CMD_PCF7931_READ: ReadPCF7931(); break; diff --git a/armsrc/apps.h b/armsrc/apps.h index 7e45d5e50..d17d9ef4b 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -103,6 +103,8 @@ void T55xxWriteBlock(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t PwdMode void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t PwdMode); void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd); void T55xxWakeUp(uint32_t Pwd); +void T55xx_ChkPwds(void); + void TurnReadLFOn(uint32_t delay); void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd); void EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index e690714df..47f0cb324 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -598,9 +598,11 @@ void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycle AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK; AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK; + + uint8_t check = 1; for(;;) { - + if ( numcycles > -1 ) { if ( x != numcycles ) { ++x; @@ -616,9 +618,11 @@ void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycle // used as a simple detection of a reader field? while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) { WDT_HIT(); - if ( usb_poll_validate_length() || BUTTON_PRESS() ) - goto OUT; - } + if ( !check ) { + if ( usb_poll_validate_length() || BUTTON_PRESS() ) + goto OUT; + } + ++check; } if (buf[i]) OPEN_COIL(); @@ -628,9 +632,11 @@ void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycle //wait until SSC_CLK goes LOW while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) { WDT_HIT(); - //if ( usb_poll_validate_length() || BUTTON_PRESS() ) - if ( BUTTON_PRESS() ) - goto OUT; + if ( !check ) { + if ( usb_poll_validate_length() || BUTTON_PRESS() ) + goto OUT; + } + ++check; } i++; @@ -1489,11 +1495,22 @@ void T55xxWriteBlock(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) { // Read one card block in page [page] void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { LED_A_ON(); - bool PwdMode = arg0 & 0x1; - uint8_t Page = (arg0 & 0x2) >> 1; - uint32_t i = 0; - bool RegReadMode = (Block == 0xFF);//regular read mode + bool PwdMode = arg0 & 0x1; + uint8_t Page = ( arg0 & 0x2 ) >> 1; + bool brute_mem = arg0 & 0x4; + uint32_t i = 0; + + // regular read mode + bool RegReadMode = (Block == 0xFF); + + uint8_t start_wait = 4; + size_t samples = 12000; + if ( brute_mem ) { + start_wait = 0; + samples = 1024; + } + //clear buffer now so it does not interfere with timing later BigBuf_Clear_keep_EM(); @@ -1505,7 +1522,8 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { // Set up FPGA, 125kHz to power up the tag LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... - WaitMS(4); + WaitMS(start_wait); + // Trigger T55x7 Direct Access Mode with start gap FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(t_config.start_gap); @@ -1529,17 +1547,118 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { // Turn field on to read the response // 137*8 seems to get to the start of data pretty well... - // but we want to go past the start and let the repeating data settle in... + // but we want to go past the start and let the repeating data settle in... TurnReadLFOn(210*8); // Acquisition // Now do the acquisition - DoPartialAcquisition(0, true, 12000, 0); + DoPartialAcquisition(0, true, samples, 0); // Turn the field off - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off - cmd_send(CMD_ACK,0,0,0,0,0); - LED_A_OFF(); + if ( !brute_mem ) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + cmd_send(CMD_ACK,0,0,0,0,0); + LED_A_OFF(); + } +} + +void T55xx_ChkPwds() { + + DbpString("[+] T55XX Check pwds using flashmemory starting"); + + uint8_t ret = 0; + // First get baseline and setup LF mode. + // tends to mess up BigBuf + uint8_t *buf = BigBuf_get_addr(); + + uint32_t b1, baseline = 0; + + // collect baseline for failed attempt + uint8_t x = 32; + while (x--) { + b1 = 0; + T55xxReadBlock(4, 1, 0); + for (uint16_t j=0; j < 1024; ++j) + b1 += buf[j]; + + b1 *= b1; + b1 >>= 8; + baseline += b1; + } + + baseline >>= 5; + Dbprintf("[=] Baseline determined [%u]", baseline); + + + uint8_t *pwds = BigBuf_get_EM_addr(); + bool use_flashmem = true; + uint16_t pwdCount = 0; + uint32_t candidate = 0; + +#ifdef WITH_FLASH + if ( use_flashmem ) { + BigBuf_Clear_EM(); + uint16_t isok = 0; + uint8_t counter[2] = {0x00, 0x00}; + isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET, counter, sizeof(counter) ); + if ( isok != sizeof(counter) ) + goto OUT; + + pwdCount = counter[1] << 8 | counter[0]; + + if ( pwdCount == 0 && pwdCount == 0xFFFF) + goto OUT; + + isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET+2, pwds, pwdCount * 4); + if ( isok != pwdCount * 4 ) + goto OUT; + + Dbprintf("[=] Password dictionary count %d ", pwdCount); + } +#endif + + uint32_t pwd = 0, curr = 0, prev = 0; + for (uint16_t i =0; i< pwdCount; ++i) { + + if (BUTTON_PRESS() && !usb_poll_validate_length()) { + goto OUT; + } + + pwd = bytes_to_num(pwds + i * 4, 4); + + + T55xxReadBlock(5, 0, pwd); + + // calc mean of BigBuf 1024 samples. + uint32_t sum = 0; + for (uint16_t j=0; j<1024; ++j) { + sum += buf[j]; + } + + sum *= sum; + sum >>= 8; + + int32_t tmp = (sum - baseline); + curr = ABS(tmp); + + Dbprintf("[=] Pwd %08X | ABS %u", pwd, curr ); + + if ( curr > prev ) { + + + Dbprintf("[=] --> ABS %u Candidate %08X <--", curr, pwd ); + candidate = pwd; + prev = curr; + } + } + + if ( candidate ) + ret = 1; + +OUT: + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + cmd_send(CMD_ACK,ret,candidate,0,0,0); + LEDsoff(); } void T55xxWakeUp(uint32_t Pwd){ diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index ed8c0464e..29487e026 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -141,21 +141,33 @@ int usage_t55xx_wakup(){ PrintAndLogEx(NORMAL, " lf t55xx wakeup p 11223344 - send wakeup password"); return 0; } -int usage_t55xx_bruteforce(){ - PrintAndLogEx(NORMAL, "This command uses A) bruteforce to scan a number range"); - PrintAndLogEx(NORMAL, " B) a dictionary attack"); +int usage_t55xx_chk(){ + PrintAndLogEx(NORMAL, "This command uses a dictionary attack"); PrintAndLogEx(NORMAL, "press 'enter' to cancel the command"); - PrintAndLogEx(NORMAL, "Usage: lf t55xx bruteforce [h] [i <*.dic>]"); + PrintAndLogEx(NORMAL, "Usage: lf t55xx bruteforce [h] [i <*.dic>]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - this help"); + PrintAndLogEx(NORMAL, " m - use dictionary from flashmemory\n"); + PrintAndLogEx(NORMAL, " i <*.dic> - loads a default keys dictionary file <*.dic>"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx bruteforce m"); + PrintAndLogEx(NORMAL, " lf t55xx bruteforce i default_pwd.dic"); + PrintAndLogEx(NORMAL, ""); + return 0; +} +int usage_t55xx_bruteforce(){ + PrintAndLogEx(NORMAL, "This command uses bruteforce to scan a number range"); + PrintAndLogEx(NORMAL, "press 'enter' to cancel the command"); + PrintAndLogEx(NORMAL, "Usage: lf t55xx bruteforce [h] "); PrintAndLogEx(NORMAL, " password must be 4 bytes (8 hex symbols)"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); PrintAndLogEx(NORMAL, " - 4 byte hex value to start pwd search at"); PrintAndLogEx(NORMAL, " - 4 byte hex value to end pwd search at"); - PrintAndLogEx(NORMAL, " i <*.dic> - loads a default keys dictionary file <*.dic>"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf t55xx bruteforce aaaaaaaa bbbbbbbb"); - PrintAndLogEx(NORMAL, " lf t55xx bruteforce i default_pwd.dic"); PrintAndLogEx(NORMAL, ""); return 0; } @@ -224,10 +236,9 @@ int CmdT55xxSetConfig(const char *Cmd) { uint8_t cmdp = 0; bool errors = false; while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - tmp = param_getchar(Cmd, cmdp); + tmp = tolower(param_getchar(Cmd, cmdp)); switch(tmp) { case 'h': - case 'H': return usage_t55xx_config(); case 'b': errors |= param_getdec(Cmd, cmdp+1, &bitRate); @@ -292,12 +303,10 @@ int CmdT55xxSetConfig(const char *Cmd) { config.offset = offset; cmdp+=2; break; - case 'Q': case 'q': config.Q5 = true; cmdp++; break; - case 'S': case 's': config.ST = true; cmdp++; @@ -343,8 +352,8 @@ int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32 if (!AquireData(page1, block, usepwd, password) ) return 0; if (!DecodeT55xxBlock()) return 0; - char blk[10]={0}; - sprintf(blk,"%02d", block); + char blk[10] = {0}; + sprintf(blk, "%02d", block); printT55xxBlock(blk); return 1; } @@ -358,22 +367,18 @@ int CmdT55xxReadBlock(const char *Cmd) { bool errors = false; uint8_t cmdp = 0; while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + switch ( tolower(param_getchar(Cmd, cmdp))) { case 'h': - case 'H': return usage_t55xx_read(); case 'b': - case 'B': errors |= param_getdec(Cmd, cmdp+1, &block); cmdp += 2; break; case 'o': - case 'O': override = true; cmdp++; break; case 'p': - case 'P': password = param_get32ex(Cmd, cmdp+1, 0, 16); usepwd = true; cmdp += 2; @@ -1503,23 +1508,68 @@ bool IsCancelled(void) { return false; } -int CmdT55xxBruteForce(const char *Cmd) { - +int CmdT55xxChkPwds(const char *Cmd) { // load a default pwd file. char line[9]; char filename[FILE_PATH_SIZE] = {0}; int keycnt = 0; uint8_t stKeyBlock = 20; uint8_t *keyBlock = NULL, *p = NULL; - uint32_t start_password = 0x00000000; //start password - uint32_t end_password = 0xFFFFFFFF; //end password bool found = false; + uint8_t timeout = 0; memset(line, 0, sizeof(line)); char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_t55xx_bruteforce(); + if (cmdp == 'h') return usage_t55xx_chk(); + + /* + if ( T55xxReadBlock(7, 0, 0, 0, 0) ) { + + // now try to validate it.. + PrintAndLogEx(WARNING, "\n Block 7 was readable"); + return 1; + } + */ + + uint64_t t1 = msclock(); + if ( cmdp == 'm' ) { + UsbCommand c = {CMD_T55XX_CHKPWDS, {0,0,0} }; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + + while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + timeout++; + printf("."); fflush(stdout); + if (timeout > 180) { + PrintAndLogEx(WARNING, "\nno response from Proxmark. Aborting..."); + return 2; + } + } + + if ( resp.arg[0] ) { + PrintAndLogEx(SUCCESS, "\nFound a candidate [ %08X ]. Trying to validate", resp.arg[1]); + + if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, resp.arg[1])) { + PrintAndLogEx(NORMAL, "Aquireing data from device failed. Quitting"); + return 2; + } + + found = tryDetectModulation(); + if (found) { + PrintAndLogEx(NORMAL, "Found valid password: [ %08X ]", resp.arg[1]); + } else { + PrintAndLogEx(NORMAL, "Password NOT found."); + } + } else { + PrintAndLogEx(NORMAL, "Password NOT found."); + } + + goto out; + } + keyBlock = calloc(stKeyBlock, 4); if (keyBlock == NULL) return 1; @@ -1569,7 +1619,7 @@ int CmdT55xxBruteForce(const char *Cmd) { num_to_bytes( strtoll(line, NULL, 16), 4, keyBlock + 4*keycnt); - PrintAndLogEx(NORMAL, "chk custom pwd[%2d] %08X", keycnt, bytes_to_num(keyBlock + 4 * keycnt, 4) ); +// PrintAndLogEx(NORMAL, "chk custom pwd[%2d] %08X", keycnt, bytes_to_num(keyBlock + 4 * keycnt, 4) ); keycnt++; memset(line, 0, sizeof(line)); } @@ -1609,60 +1659,78 @@ int CmdT55xxBruteForce(const char *Cmd) { } found = tryDetectModulation(); - if ( found ) { - PrintAndLogEx(NORMAL, "Found valid password: [%08X]", testpwd); - //free(keyBlock); - //return 0; - } + if ( found ) + break; + } - PrintAndLogEx(NORMAL, "Password NOT found."); - free(keyBlock); - return 0; + if ( found ) + PrintAndLogEx(NORMAL, "Found valid password: [ %08X ]", testpwd); + else + PrintAndLogEx(NORMAL, "Password NOT found."); } + free(keyBlock); + +out: + t1 = msclock() - t1; + PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1/1000.0); + return 0; +} + +int CmdT55xxBruteForce(const char *Cmd) { + + uint32_t start_password = 0x00000000; //start password + uint32_t end_password = 0xFFFFFFFF; //end password + uint32_t curr = 0; + bool found = false; + + + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_t55xx_bruteforce(); + + uint64_t t1 = msclock(); + // Try to read Block 7, first :) // incremental pwd range search start_password = param_get32ex(Cmd, 0, 0, 16); end_password = param_get32ex(Cmd, 1, 0, 16); + curr = start_password; + if ( start_password >= end_password ) { - free(keyBlock); return usage_t55xx_bruteforce(); } PrintAndLogEx(NORMAL, "Search password range [%08X -> %08X]", start_password, end_password); - - uint32_t i = start_password; - while ((!found) && (i <= end_password)){ + while ((!found) || (curr <= end_password)){ printf("."); fflush(stdout); if (IsCancelled()) { - free(keyBlock); return 0; } - if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, i)) { + if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, curr)) { PrintAndLogEx(NORMAL, "Aquireing data from device failed. Quitting"); - free(keyBlock); return 0; } found = tryDetectModulation(); if (found) break; - i++; + ++curr; } PrintAndLogEx(NORMAL, ""); if (found) - PrintAndLogEx(NORMAL, "Found valid password: [%08x]", i); + PrintAndLogEx(NORMAL, "Found valid password: [ %08X ]", curr); else - PrintAndLogEx(NORMAL, "Password NOT found. Last tried: [%08x]", --i); + PrintAndLogEx(NORMAL, "Password NOT found. Last tried: [ %08X ]", --curr); - free(keyBlock); + t1 = msclock() - t1; + PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1/1000.0); return 0; } @@ -1959,6 +2027,7 @@ static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"bruteforce", CmdT55xxBruteForce,0, " [i <*.dic>] Simple bruteforce attack to find password"}, {"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"}, + {"chk", CmdT55xxChkPwds, 1, "Check passwords"}, {"detect", CmdT55xxDetect, 1, "[1] Try detecting the tag modulation from reading the configuration block."}, {"deviceconfig", CmdT55xxSetDeviceConfig, 1, "Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap"}, {"p1detect", CmdT55xxDetectPage1,1, "[1] Try detecting if this is a t55xx tag by reading page 1"}, diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index 15adab0b6..46de0c359 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -133,6 +133,7 @@ t55xx_conf_block_t Get_t55xx_Config(void); void Set_t55xx_Config(t55xx_conf_block_t conf); extern int CmdLFT55XX(const char *Cmd); +extern int CmdT55xxChk(const char *Cmd); extern int CmdT55xxBruteForce(const char *Cmd); extern int CmdT55xxSetConfig(const char *Cmd); extern int CmdT55xxReadBlock(const char *Cmd); diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 44d031334..a54b27e0f 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -140,6 +140,8 @@ typedef struct{ #define CMD_COTAG 0x0225 #define CMD_SET_LF_T55XX_CONFIG 0x0226 +#define CMD_T55XX_CHKPWDS 0x0230 + /* CMD_SET_ADC_MUX: ext1 is 0 for lopkd, 1 for loraw, 2 for hipkd, 3 for hiraw */ // For the 13.56 MHz tags From a5833fe39069d2ec50e90ee3637b27ccd76f7d79 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 12 Jan 2019 12:10:31 +0100 Subject: [PATCH 0420/1938] CHG: remove strange thr 0x43 in LF sampling CHG: refactor cotag init --- armsrc/lfops.c | 29 ++++++------------------- armsrc/lfsampling.c | 53 +++++++++++++++++++-------------------------- 2 files changed, 29 insertions(+), 53 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 47f0cb324..c267db36e 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1548,7 +1548,7 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { // Turn field on to read the response // 137*8 seems to get to the start of data pretty well... // but we want to go past the start and let the repeating data settle in... - TurnReadLFOn(210*8); + TurnReadLFOn(200*8); // Acquisition // Now do the acquisition @@ -2089,7 +2089,6 @@ void EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd) { //Wait 20ms for write to complete? WaitMS(7); - //Capture response if one exists DoPartialAcquisition(20, true, 6000, 1000); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); @@ -2113,7 +2112,7 @@ This triggers a COTAG tag to response */ void Cotag(uint32_t arg0) { #ifndef OFF -# define OFF { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(2035); } +# define OFF(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS((x)); } #endif #ifndef ON # define ON(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); WaitUS((x)); } @@ -2122,29 +2121,15 @@ void Cotag(uint32_t arg0) { LED_A_ON(); - // Switching to LF image on FPGA. This might empty BigBuff - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - + LFSetupFPGAForADC(89, true); + //clear buffer now so it does not interfere with timing later BigBuf_Clear_ext(false); - // Set up FPGA, 132kHz to power up the tag - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 89); - 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(); - - // start clock - 1.5ticks is 1us - StartTicks(); - //send COTAG start pulse - ON(740) OFF - ON(3330) OFF - ON(740) OFF + ON(740) OFF(2035) + ON(3330) OFF(2035) + ON(740) OFF(2035) ON(1000) switch(rawsignal) { diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 22171e2c3..96963d389 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -117,21 +117,21 @@ void LFSetupFPGAForADC(int divisor, bool lf_field) { * @return the number of bits occupied by the samples. */ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent, int bufsize, uint32_t cancel_after) { - //bigbuf, to hold the aquired raw data signal + uint8_t *dest = BigBuf_get_addr(); bufsize = (bufsize > 0 && bufsize < BigBuf_max_traceLen()) ? bufsize : BigBuf_max_traceLen(); - if (bits_per_sample < 1) bits_per_sample = 1; if (bits_per_sample > 8) bits_per_sample = 8; if (decimation < 1) decimation = 1; - // Use a bit stream to handle the output + // use a bit stream to handle the output BitstreamOut data = { dest , 0, 0}; int sample_counter = 0; uint8_t sample = 0; - //If we want to do averaging + + // if we want to do averaging uint32_t sample_sum =0 ; uint32_t sample_total_numbers = 0; uint32_t sample_total_saved = 0; @@ -139,13 +139,13 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag while (!BUTTON_PRESS() && !usb_poll_validate_length() ) { WDT_HIT(); - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { - AT91C_BASE_SSC->SSC_THR = 0x43; - LED_D_ON(); - } + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + + // Testpoint 8 (TP8) can be used to trigger oscilliscope LED_D_OFF(); + // threshold either high or low values 128 = center 0. if trigger = 178 if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) { if (cancel_after > 0) { @@ -162,24 +162,26 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag if (averaging) sample_sum += sample; - //Check decimation + // check decimation if (decimation > 1) { sample_counter++; if (sample_counter < decimation) continue; sample_counter = 0; } - //Averaging + // averaging if (averaging && decimation > 1) { sample = sample_sum / decimation; sample_sum =0; } - //Store the sample + // store the sample sample_total_saved ++; - if (bits_per_sample == 8){ + if (bits_per_sample == 8) { dest[sample_total_saved-1] = sample; - data.numbits = sample_total_saved << 3;//Get the return value correct + + // Get the return value correct + data.numbits = sample_total_saved << 3; if (sample_total_saved >= bufsize) break; } else { @@ -190,9 +192,8 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag if (bits_per_sample > 4) pushBit(&data, sample & 0x08); if (bits_per_sample > 5) pushBit(&data, sample & 0x04); if (bits_per_sample > 6) pushBit(&data, sample & 0x02); - //Not needed, 8bps is covered above - //if (bits_per_sample > 7) pushBit(&data, sample & 0x01); - if ((data.numbits >> 3) +1 >= bufsize) break; + + if ((data.numbits >> 3) + 1 >= bufsize) break; } } } @@ -285,10 +286,8 @@ void doT55x7Acquisition(size_t sample_size) { while(!BUTTON_PRESS() && !usb_poll_validate_length() && skipCnt < 1000 && (i < bufsize) ) { WDT_HIT(); - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { - AT91C_BASE_SSC->SSC_THR = 0x43; //43 - LED_D_ON(); - } + + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { curSample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; LED_D_OFF(); @@ -352,11 +351,7 @@ void doCotagAcquisition(size_t sample_size) { while (!BUTTON_PRESS() && !usb_poll_validate_length() && (i < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) { WDT_HIT(); - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { - AT91C_BASE_SSC->SSC_THR = 0x43; - LED_D_ON(); - } - + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; LED_D_OFF(); @@ -406,12 +401,8 @@ uint32_t doCotagAcquisitionManchester() { uint16_t noise_counter = 0; while (!BUTTON_PRESS() && !usb_poll_validate_length() && (sample_counter < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) { - WDT_HIT(); - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { - AT91C_BASE_SSC->SSC_THR = 0x43; - LED_D_ON(); - } - + WDT_HIT(); + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; LED_D_OFF(); From 459ff6149b815e7a7b2e49ff8dc9ec9fa814839a Mon Sep 17 00:00:00 2001 From: Iceman Date: Sat, 12 Jan 2019 18:12:58 +0100 Subject: [PATCH 0421/1938] Update README.md --- README.md | 40 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 40 insertions(+) diff --git a/README.md b/README.md index 94f7b94d6..05b9a007f 100644 --- a/README.md +++ b/README.md @@ -240,6 +240,46 @@ You are now ready to use your newly upgraded proxmark3 device. Many commands us pm3 --> quit +### First things on your RDV40 +You will need to run these commands to make sure your rdv4 is prepared + + pm3 --> mem load f default_keys m + pm3 --> mem load f default_pwd t + pm3 --> mem load f default_iclass_keys i + pm3 --> lf t55xx deviceconfig a 29 b 17 c 15 d 47 e 15 p + +### Verify sim module firmware version +To make sure you got the latest sim module firmware. +_Lastest version is v3.10_ + + pm3 --> hw status + +Find version in the long output, look for these two lines + + #db# Smart card module (ISO 7816) + #db# version.................v2.06 + +This version is obselete. The following command upgrades your device sim module firmware. +Don't not turn of your device during the execution of this command. + + pm3 --> sc upgrade f ../tools/simmodule/SIM010.BIN + +You get the following output, this is a successful execution. + + [!] WARNING - Smartcard socket firmware upgrade. + [!] A dangerous command, do wrong and you will brick the smart card socket + [+] Smartcard socket firmware uploading to PM3 + .. + [+] Smartcard socket firmware updating, don't turn off your PM3! + #db# FW 0000 + #db# FW 0080 + #db# FW 0100 + #db# FW 0180 + #db# FW 0200 + #db# FW 0280 + [+] Smartcard socket firmware upgraded successful + + ## the end `iceman at host iuse.se` From fcfbeb6ac362dfba85d6f7e2ab8df80b403cdadd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 12 Jan 2019 18:33:40 +0100 Subject: [PATCH 0422/1938] textual --- client/cmdlft55xx.c | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 29487e026..f6c0f3ced 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1553,18 +1553,18 @@ int CmdT55xxChkPwds(const char *Cmd) { PrintAndLogEx(SUCCESS, "\nFound a candidate [ %08X ]. Trying to validate", resp.arg[1]); if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, resp.arg[1])) { - PrintAndLogEx(NORMAL, "Aquireing data from device failed. Quitting"); + PrintAndLogEx(INFO, "Aquireing data from device failed. Quitting"); return 2; } found = tryDetectModulation(); if (found) { - PrintAndLogEx(NORMAL, "Found valid password: [ %08X ]", resp.arg[1]); + PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", resp.arg[1]); } else { - PrintAndLogEx(NORMAL, "Password NOT found."); + PrintAndLogEx(WARNING, "Password NOT found."); } } else { - PrintAndLogEx(NORMAL, "Password NOT found."); + PrintAndLogEx(WARNING, "Password NOT found."); } goto out; @@ -1581,7 +1581,7 @@ int CmdT55xxChkPwds(const char *Cmd) { FILE * f = fopen( filename , "r"); if ( !f ) { - PrintAndLogEx(NORMAL, "File: %s: not found or locked.", filename); + PrintAndLogEx(WARNING, "File: %s: not found or locked.", filename); free(keyBlock); return 1; } @@ -1596,7 +1596,7 @@ int CmdT55xxChkPwds(const char *Cmd) { if( line[0]=='#' ) continue; if (!isxdigit(line[0])) { - PrintAndLogEx(NORMAL, "File content error. '%s' must include 8 HEX symbols", line); + PrintAndLogEx(WARNING, "File content error. '%s' must include 8 HEX symbols", line); continue; } @@ -1627,11 +1627,11 @@ int CmdT55xxChkPwds(const char *Cmd) { fclose(f); if (keycnt == 0) { - PrintAndLogEx(NORMAL, "No keys found in file"); + PrintAndLogEx(WARNING, "No keys found in file"); free(keyBlock); return 1; } - PrintAndLogEx(NORMAL, "Loaded %d keys", keycnt); + PrintAndLogEx(SUCCESS, "Loaded %d keys", keycnt); // loop uint64_t testpwd = 0x00; @@ -1650,10 +1650,10 @@ int CmdT55xxChkPwds(const char *Cmd) { testpwd = bytes_to_num(keyBlock + 4*c, 4); - PrintAndLogEx(NORMAL, "Testing %08X", testpwd); + PrintAndLogEx(INFO, "Testing %08X", testpwd); if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, testpwd)) { - PrintAndLogEx(NORMAL, "Aquireing data from device failed. Quitting"); + PrintAndLogEx(INFO, "Aquireing data from device failed. Quitting"); free(keyBlock); return 0; } @@ -1664,9 +1664,9 @@ int CmdT55xxChkPwds(const char *Cmd) { } if ( found ) - PrintAndLogEx(NORMAL, "Found valid password: [ %08X ]", testpwd); + PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", testpwd); else - PrintAndLogEx(NORMAL, "Password NOT found."); + PrintAndLogEx(WARNING, "Password NOT found."); } free(keyBlock); @@ -1702,7 +1702,7 @@ int CmdT55xxBruteForce(const char *Cmd) { return usage_t55xx_bruteforce(); } - PrintAndLogEx(NORMAL, "Search password range [%08X -> %08X]", start_password, end_password); + PrintAndLogEx(INFO, "Search password range [%08X -> %08X]", start_password, end_password); while ((!found) || (curr <= end_password)){ @@ -1713,7 +1713,7 @@ int CmdT55xxBruteForce(const char *Cmd) { } if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, curr)) { - PrintAndLogEx(NORMAL, "Aquireing data from device failed. Quitting"); + PrintAndLogEx(WARNING, "Aquireing data from device failed. Quitting"); return 0; } found = tryDetectModulation(); @@ -1725,9 +1725,9 @@ int CmdT55xxBruteForce(const char *Cmd) { PrintAndLogEx(NORMAL, ""); if (found) - PrintAndLogEx(NORMAL, "Found valid password: [ %08X ]", curr); + PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", curr); else - PrintAndLogEx(NORMAL, "Password NOT found. Last tried: [ %08X ]", --curr); + PrintAndLogEx(WARNING, "Password NOT found. Last tried: [ %08X ]", --curr); t1 = msclock() - t1; PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1/1000.0); From 46cbbe8d05de1704af23f1dda580fddbf6f8efa5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 12 Jan 2019 18:53:11 +0100 Subject: [PATCH 0423/1938] textual --- client/cmdlft55xx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index f6c0f3ced..abf8f04ec 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1814,9 +1814,9 @@ int CmdT55xxRecoverPW(const char *Cmd) { PrintAndLogEx(NORMAL, ""); if (found == 1) - PrintAndLogEx(NORMAL, "Found valid password: [%08x]", curr_password); + PrintAndLogEx(SUCCESS, "Found valid password: [%08x]", curr_password); else - PrintAndLogEx(NORMAL, "Password NOT found."); + PrintAndLogEx(WARNING, "Password NOT found."); return 0; } From 20c3cd5ce3d823f56eac432c7115057246c9e611 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 14 Jan 2019 12:02:26 +0100 Subject: [PATCH 0424/1938] chg: adjusting license according to earlier commits to pm3 offical repo. --- armsrc/optimized_cipher.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/optimized_cipher.c b/armsrc/optimized_cipher.c index 36b25f593..223d73fea 100644 --- a/armsrc/optimized_cipher.c +++ b/armsrc/optimized_cipher.c @@ -22,7 +22,7 @@ * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation. + * by the Free Software Foundation, or, at your option, any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of From adffe298555de6f1c4076fbe7bd7f21e216f3278 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 14 Jan 2019 12:06:05 +0100 Subject: [PATCH 0425/1938] chg: adjusting license accoring match its .c file --- common/iso15693tools.h | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/common/iso15693tools.h b/common/iso15693tools.h index 053ca56ca..70382ce04 100644 --- a/common/iso15693tools.h +++ b/common/iso15693tools.h @@ -1,5 +1,11 @@ -// ISO15693 commons -// Adrian Dabrowski 2010 and others, GPLv2 +//----------------------------------------------------------------------------- +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// ISO15693 other commons +//----------------------------------------------------------------------------- +// Adrian Dabrowski 2010 and otherss // Christian Herrmann 2018 #ifndef ISO15693_H__ From 6f0cc5fa7a8a752b8b93a0ae89ae6379a294f60b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 14 Jan 2019 18:14:15 +0200 Subject: [PATCH 0426/1938] small fix --- client/emv/cmdemv.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 07543241c..71cf542db 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -715,7 +715,7 @@ void ProcessACResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, b TLVPrintFromTLV(tlvElm); // AC (Application Cryptogram) - tlvdb_change_or_add_node_ex(tlvRoot, 0x9f26, min(8, elmlen - 3), &buf[5], &tlvElm); + tlvdb_change_or_add_node_ex(tlvRoot, 0x9f26, MIN(8, elmlen - 3), &buf[5], &tlvElm); if (decodeTLV) TLVPrintFromTLV(tlvElm); @@ -1233,12 +1233,12 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "* * AC2"); -/* // AC2 - PRINT_INDENT(level); - if ((CID & EMVAC_AC2_MASK) == EMVAC_AAC2) fprintf(f, "\tAC2: AAC (Transaction declined)\n"); - if ((CID & EMVAC_AC2_MASK) == EMVAC_TC2) fprintf(f, "\tAC2: TC (Transaction approved)\n"); - if ((CID & EMVAC_AC2_MASK) == EMVAC_ARQC2) fprintf(f, "\tAC2: not requested (ARQC)\n"); - if ((CID & EMVAC_AC2_MASK) == EMVAC_AC2_MASK) fprintf(f, "\tAC2: RFU\n"); +/* // AC2 + PRINT_INDENT(level); + if ((CID & EMVAC_AC2_MASK) == EMVAC_AAC2) fprintf(f, "\tAC2: AAC (Transaction declined)\n"); + if ((CID & EMVAC_AC2_MASK) == EMVAC_TC2) fprintf(f, "\tAC2: TC (Transaction approved)\n"); + if ((CID & EMVAC_AC2_MASK) == EMVAC_ARQC2) fprintf(f, "\tAC2: not requested (ARQC)\n"); + if ((CID & EMVAC_AC2_MASK) == EMVAC_AC2_MASK) fprintf(f, "\tAC2: RFU\n"); */ } From 5a35b0de2aaf1ca9f416603765f456a76ba5a99e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 14 Jan 2019 18:54:18 +0200 Subject: [PATCH 0427/1938] changed `min` to macro `MIN` --- client/emv/cmdemv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index a30c22aec..91a3663f3 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -715,7 +715,7 @@ void ProcessACResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, b TLVPrintFromTLV(tlvElm); // AC (Application Cryptogram) - tlvdb_change_or_add_node_ex(tlvRoot, 0x9f26, min(8, elmlen - 3), &buf[5], &tlvElm); + tlvdb_change_or_add_node_ex(tlvRoot, 0x9f26, MIN(8, elmlen - 3), &buf[5], &tlvElm); if (decodeTLV) TLVPrintFromTLV(tlvElm); From 49fc2a56ab43a9058ef539202c18f9b6e145e8b8 Mon Sep 17 00:00:00 2001 From: Iceman Date: Sun, 20 Jan 2019 23:46:03 +0100 Subject: [PATCH 0428/1938] Update tnp3clone.lua According to post http://www.proxmark.org/forum/viewtopic.php?pid=34046#p34046 Set that ATQA / SAK, set Sector 0 accessrights --- client/scripts/tnp3clone.lua | 64 +++++++++++++++++++++++------------- 1 file changed, 42 insertions(+), 22 deletions(-) diff --git a/client/scripts/tnp3clone.lua b/client/scripts/tnp3clone.lua index 2e1ee7019..fcccc042e 100644 --- a/client/scripts/tnp3clone.lua +++ b/client/scripts/tnp3clone.lua @@ -37,13 +37,12 @@ Arguments: 0020 - Swapforce ]] - -- This is only meant to be used when errors occur -function oops(err) +local function oops(err) print("ERROR: ",err) end -- Usage help -function help() +local function help() print(desc) print("Example usage") print(example) @@ -64,7 +63,7 @@ local function waitCmd() end local function readblock( blocknum, keyA ) - -- Read block 0 + -- Read block N cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blocknum, arg2 = 0, arg3 = 0, data = keyA} err = core.SendCommand(cmd:getBytes()) if err then return nil, err end @@ -72,8 +71,9 @@ local function readblock( blocknum, keyA ) if err then return nil, err end return block0 end + local function readmagicblock( blocknum ) - -- Read block 0 + -- Read block N local CSETBLOCK_SINGLE_OPERATION = 0x1F cmd = Command:new{cmd = cmds.CMD_MIFARE_CGETBLOCK, arg1 = CSETBLOCK_SINGLE_OPERATION, arg2 = 0, arg3 = blocknum} err = core.SendCommand(cmd:getBytes()) @@ -89,11 +89,13 @@ local function main(args) print( string.rep('--',20) ) local numBlocks = 64 - local cset = 'hf mf csetbl ' + local cset = 'hf mf csetbl ' local csetuid = 'hf mf csetuid ' local cget = 'hf mf cgetbl ' local empty = '00000000000000000000000000000000' - local AccAndKeyB = '7F078869000000000000' + local AccAndKeyB = '7F070869000000000000' + local atqa = '0F01' + local sak = '81' -- Defaults to Gusto local toytype = 'C201' local subtype = '0030' @@ -107,42 +109,54 @@ local function main(args) if o == "l" then return toys.List() end end - if #toytype ~= 4 then return oops('Wrong size - toytype. (4hex symbols)') end - if #subtype ~= 4 then return oops('Wrong size - subtype. (4hex symbols)') end + if #toytype ~= 4 then return oops('[!] Wrong size - toytype. (4hex symbols)') end + if #subtype ~= 4 then return oops('[!] Wrong size - subtype. (4hex symbols)') end -- look up type, find & validate types local item = toys.Find( toytype, subtype) if item then - print( (' Looking up input: Found %s - %s (%s)'):format(item[6],item[5], item[4]) ) + print( ('[+] Looking up input: Found %s - %s (%s)'):format(item[6],item[5], item[4]) ) else - print('Didn\'t find item type. If you are sure about it, report it in') + print('[-] Didn\'t find item type. If you are sure about it, post on forum') end --15,16 - --13-14 - + --13-14 -- find tag result, err = lib14a.read(false, true) - if not result then return oops(err) end + if not result then return oops(err) end -- load keys local akeys = pre.GetAll(result.uid) - local keyA = akeys:sub(1, 12 ) + local keyA = akeys:sub(1, 12 ) - local b0 = readblock(0,keyA) + local b0 = readblock(0, keyA) if not b0 then - print('failed reading block with factorydefault key. Trying chinese magic read.') + print('[-] failed reading block with factorydefault key. Trying chinese magic read.') b0, err = readmagicblock(0) if not b0 then - oops(err) - return oops('failed reading block with chinese magic command. quitting...') + oops('[!] '..err) + return oops('[!] failed reading block with chinese magic command. Quitting...') end end + core.clearCommandBuffer() + + local b3 = readblock(3, keyA) + if not b3 then + print('[-] failed reading block with factorydefault key. Trying chinese magic read.') + b3, err = readmagicblock(0) + if not b3 then + oops('[!] '..err) + return oops('[!] failed reading block with chinese magic command. Quitting...') + end + end + core.clearCommandBuffer() -- wipe card. - local cmd = (csetuid..'%s 0004 08 w'):format(result.uid) + local cmd = (csetuid..'%s %s %s w'):format(result.uid, atqa, sak) core.console(cmd) - + core.clearCommandBuffer() + local b1 = toytype..string.rep('00',10)..subtype local calc = utils.Crc16(b0..b1) @@ -150,6 +164,7 @@ local function main(args) local cmd = (cset..'1 %s%04x'):format( b1, calcEndian) core.console(cmd) + core.clearCommandBuffer() local pos, key for blockNo = 2, numBlocks-1, 1 do @@ -161,5 +176,10 @@ local function main(args) end end core.clearCommandBuffer() + + -- Set sector trailer S0, since it has different access rights + cmd = ('%s 3 %s%s'):format(cset, keyA, b3:sub(13) ) + core.console(cmd) + core.clearCommandBuffer() end -main(args) \ No newline at end of file +main(args) From 6e99b1e49bf37702eb2fd52ded8847a7fb18b384 Mon Sep 17 00:00:00 2001 From: Iceman Date: Sun, 20 Jan 2019 23:53:54 +0100 Subject: [PATCH 0429/1938] Update tnp3clone.lua Better to use default template for ST --- client/scripts/tnp3clone.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/scripts/tnp3clone.lua b/client/scripts/tnp3clone.lua index fcccc042e..b0cebaf7f 100644 --- a/client/scripts/tnp3clone.lua +++ b/client/scripts/tnp3clone.lua @@ -178,7 +178,7 @@ local function main(args) core.clearCommandBuffer() -- Set sector trailer S0, since it has different access rights - cmd = ('%s 3 %s%s'):format(cset, keyA, b3:sub(13) ) + cmd = ('%s 3 %s0f0f0f69000000000000'):format(cset, keyA) core.console(cmd) core.clearCommandBuffer() end From 6f3940b22141c0ba53dcdbf1aa605e43e943af86 Mon Sep 17 00:00:00 2001 From: Iceman Date: Sun, 20 Jan 2019 23:55:11 +0100 Subject: [PATCH 0430/1938] Update tnp3clone.lua Cleanup --- client/scripts/tnp3clone.lua | 13 +------------ 1 file changed, 1 insertion(+), 12 deletions(-) diff --git a/client/scripts/tnp3clone.lua b/client/scripts/tnp3clone.lua index b0cebaf7f..514a091b9 100644 --- a/client/scripts/tnp3clone.lua +++ b/client/scripts/tnp3clone.lua @@ -140,18 +140,7 @@ local function main(args) end end core.clearCommandBuffer() - - local b3 = readblock(3, keyA) - if not b3 then - print('[-] failed reading block with factorydefault key. Trying chinese magic read.') - b3, err = readmagicblock(0) - if not b3 then - oops('[!] '..err) - return oops('[!] failed reading block with chinese magic command. Quitting...') - end - end - core.clearCommandBuffer() - + -- wipe card. local cmd = (csetuid..'%s %s %s w'):format(result.uid, atqa, sak) core.console(cmd) From 5f2ecf67cdc5bbe380d353905a55812e5a7b0294 Mon Sep 17 00:00:00 2001 From: Iceman Date: Mon, 21 Jan 2019 00:02:33 +0100 Subject: [PATCH 0431/1938] Update default_pwd.dic --- client/default_pwd.dic | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/default_pwd.dic b/client/default_pwd.dic index dd1364385..87423478b 100644 --- a/client/default_pwd.dic +++ b/client/default_pwd.dic @@ -96,6 +96,7 @@ FABADA11, //china? 69696969, 12121212, 12344321, +1234ABCD, 11112222, 13131313, 10041004, @@ -104,8 +105,8 @@ FABADA11, //china? abcd1234, 20002000, 19721972, -aa55aa55, //amiboo -55aa55aa, //rev amiboo +aa55aa55, // amiboo +55aa55aa, // rev amiboo 4f271149, // seeds ul-ev1 07d7bb0b, // seeds ul-ev1 9636ef8f, // seeds ul-ev1 @@ -113,4 +114,4 @@ b5f44686, // seeds ul-ev1 9E3779B9, // TEA C6EF3720, // TEA 7854794A, // xbox tea constant :) -F1EA5EED, //burtle +F1EA5EED, // burtle From 66c82d16b0671f48b0f2c0b715676099d78b0f35 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 21 Jan 2019 09:02:00 +0100 Subject: [PATCH 0432/1938] chg: calloc calls --- client/cmdhficlass.c | 6 +++--- client/cmdhflegic.c | 4 ++-- client/cmdhfmf.c | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 0e62afaf6..f0bfa18a0 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -2463,7 +2463,7 @@ static void shave(uint8_t *data, uint8_t len){ data[i] &= 0xFE; } static void generate_rev(uint8_t *data, uint8_t len) { - uint8_t *key = calloc(len,1); + uint8_t *key = calloc(len, sizeof(uint8_t)); PrintAndLogEx(SUCCESS, "input permuted key | %s \n", sprint_hex(data, len)); permute_rev(data, len, key); PrintAndLogEx(SUCCESS, " unpermuted key | %s \n", sprint_hex(key, len)); @@ -2472,8 +2472,8 @@ static void generate_rev(uint8_t *data, uint8_t len) { free(key); } static void generate(uint8_t *data, uint8_t len) { - uint8_t *key = calloc(len,1); - uint8_t *pkey = calloc(len,1); + uint8_t *key = calloc(len, sizeof(uint8_t)); + uint8_t *pkey = calloc(len, sizeof(uint8_t)); PrintAndLogEx(SUCCESS, " input key | %s \n", sprint_hex(data, len)); permute(data, len, pkey); PrintAndLogEx(SUCCESS, "permuted key | %s \n", sprint_hex(pkey, len)); diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 393d73ed0..a31dbd1b1 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -483,7 +483,7 @@ int CmdLegicRdmem(const char *Cmd) { PrintAndLogEx(NORMAL, "Reading %d bytes, from offset %d", len, offset); // allocate receiver buffer - uint8_t *data = malloc(len); + uint8_t *data = calloc(len, sizeof(uint8_t)); if ( !data ){ PrintAndLogEx(WARNING, "Cannot allocate memory"); return 2; @@ -923,7 +923,7 @@ int CmdLegicDump(const char *Cmd){ else sprintf(fnameptr + fileNlen,".bin"); - f = fopen(filename,"wb"); + f = fopen(filename, "wb"); if (!f) { PrintAndLogEx(WARNING, "Could not create file name %s", filename); if (data) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 00e29105f..a02302b15 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2496,7 +2496,7 @@ int CmdHF14AMfESave(const char *Cmd) { blocks = NumOfBlocks(c); bytes = blocks * MFBLOCK_SIZE; - dump = calloc(sizeof(uint8_t), bytes); + dump = calloc(bytes, sizeof(uint8_t)); if (!dump) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return 1; From fa889900c0458f94d7f812169fccfc0fea6b7638 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 21 Jan 2019 09:31:37 +0100 Subject: [PATCH 0433/1938] chg: calloc instead of malloc chg: textual chg: extra size checks chg: longer wait for reading mem --- client/cmdhflegic.c | 112 +++++++++++++++++++++++--------------------- 1 file changed, 59 insertions(+), 53 deletions(-) diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index a31dbd1b1..0f580da9f 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -183,12 +183,11 @@ int CmdLegicInfo(const char *Cmd) { PrintAndLogEx(NORMAL, "Reading tag memory %d b...", card.cardsize); // allocate receiver buffer - uint8_t *data = malloc(card.cardsize); + uint8_t *data = calloc(card.cardsize, sizeof(uint8_t)); if (!data) { PrintAndLogEx(WARNING, "Cannot allocate memory"); return 2; } - memset(data, 0, card.cardsize); int status = legic_read_mem(0, card.cardsize, 0x55, data, &datalen); if ( status > 0 ) { @@ -480,15 +479,20 @@ int CmdLegicRdmem(const char *Cmd) { uint16_t datalen = 0; sscanf(Cmd, "%x %x %x", &offset, &len, &iv); - PrintAndLogEx(NORMAL, "Reading %d bytes, from offset %d", len, offset); + // sanity checks + if ( len + offset >= MAX_LENGTH ) { + PrintAndLogEx(WARNING, "Out-of-bounds, Cardsize = %d, [offset+len = %d ]", MAX_LENGTH, len + offset); + return -1; + } + + PrintAndLogEx(SUCCESS, "Reading %d bytes, from offset %d", len, offset); // allocate receiver buffer uint8_t *data = calloc(len, sizeof(uint8_t)); if ( !data ){ PrintAndLogEx(WARNING, "Cannot allocate memory"); - return 2; + return -2; } - memset(data, 0, len); int status = legic_read_mem(offset, len, iv, data, &datalen); if ( status == 0 ) { @@ -540,9 +544,9 @@ int CmdLegicRfWrite(const char *Cmd) { } // limit number of bytes to write. This is not a 'restore' command. - if ( (len>>1) > 100 ){ - PrintAndLogEx(NORMAL, "Max bound on 100bytes to write a one time."); - PrintAndLogEx(NORMAL, "Use the 'hf legic restore' command if you want to write the whole tag at once"); + if ( (len >> 1) > 100 ){ + PrintAndLogEx(WARNING, "Max bound on 100bytes to write a one time."); + PrintAndLogEx(WARNING, "Use the 'hf legic restore' command if you want to write the whole tag at once"); errors = true; } @@ -551,7 +555,7 @@ int CmdLegicRfWrite(const char *Cmd) { if (data) free(data); - data = malloc(len >> 1); + data = calloc(len >> 1, sizeof(uint8_t)); if ( data == NULL ) { PrintAndLogEx(WARNING, "Can't allocate memory. exiting"); errors = true; @@ -598,12 +602,12 @@ int CmdLegicRfWrite(const char *Cmd) { // OUT-OF-BOUNDS checks // UID 4+1 bytes can't be written to. if ( offset < 5 ) { - PrintAndLogEx(NORMAL, "Out-of-bounds, bytes 0-1-2-3-4 can't be written to. Offset = %d", offset); + PrintAndLogEx(WARNING, "Out-of-bounds, bytes 0-1-2-3-4 can't be written to. Offset = %d", offset); return -2; } if ( len + offset >= card.cardsize ) { - PrintAndLogEx(NORMAL, "Out-of-bounds, Cardsize = %d, [offset+len = %d ]", card.cardsize, len + offset); + PrintAndLogEx(WARNING, "Out-of-bounds, Cardsize = %d, [offset+len = %d ]", card.cardsize, len + offset); return -2; } @@ -622,7 +626,7 @@ int CmdLegicRfWrite(const char *Cmd) { legic_chk_iv(&IV); - PrintAndLogEx(NORMAL, "Writing to tag"); + PrintAndLogEx(SUCCESS, "Writing to tag"); UsbCommand c = {CMD_WRITER_LEGIC_RF, {offset, len, IV}}; memcpy(c.d.asBytes, data, len); @@ -673,7 +677,7 @@ int CmdLegicCalcCrc(const char *Cmd){ // it's possible for user to accidentally enter "b" parameter // more than once - we have to clean previous malloc if (data) free(data); - data = malloc(len >> 1); + data = calloc(len >> 1, sizeof(uint8_t) ); if ( data == NULL ) { PrintAndLogEx(WARNING, "Can't allocate memory. exiting"); errors = true; @@ -714,10 +718,10 @@ int CmdLegicCalcCrc(const char *Cmd){ switch (type){ case 16: init_table(CRC_LEGIC); - PrintAndLogEx(NORMAL, "Legic crc16: %X", crc16_legic(data, len, uidcrc)); + PrintAndLogEx(SUCCESS, "Legic crc16: %X", crc16_legic(data, len, uidcrc)); break; default: - PrintAndLogEx(NORMAL, "Legic crc8: %X", CRC8Legic(data, len) ); + PrintAndLogEx(SUCCESS, "Legic crc8: %X", CRC8Legic(data, len) ); break; } @@ -733,11 +737,18 @@ int legic_read_mem(uint32_t offset, uint32_t len, uint32_t iv, uint8_t *out, uin clearCommandBuffer(); SendCommand(&c); UsbCommand resp; - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 3000) ) { - PrintAndLogEx(WARNING, "command execution time out"); - return 1; - } - + + uint8_t timeout = 0; + while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + ++timeout; + printf("."); fflush(stdout); + if (timeout > 7) { + PrintAndLogEx(WARNING, "\ncommand execution time out"); + return 1; + } + } + PrintAndLogEx(NORMAL, "\n"); + uint8_t isOK = resp.arg[0] & 0xFF; *outlen = resp.arg[1]; if ( !isOK ) { @@ -762,13 +773,13 @@ int legic_print_type(uint32_t tagtype, uint8_t spaces){ char *spacer = spc + (10-spaces); if ( tagtype == 22 ) - PrintAndLogEx(NORMAL, "%sTYPE : MIM%d card (outdated)", spacer, tagtype); + PrintAndLogEx(SUCCESS, "%sTYPE : MIM%d card (outdated)", spacer, tagtype); else if ( tagtype == 256 ) - PrintAndLogEx(NORMAL, "%sTYPE : MIM%d card (234 bytes)", spacer, tagtype); + PrintAndLogEx(SUCCESS, "%sTYPE : MIM%d card (234 bytes)", spacer, tagtype); else if ( tagtype == 1024 ) - PrintAndLogEx(NORMAL, "%sTYPE : MIM%d card (1002 bytes)", spacer, tagtype); + PrintAndLogEx(SUCCESS, "%sTYPE : MIM%d card (1002 bytes)", spacer, tagtype); else - PrintAndLogEx(NORMAL, "%sTYPE : Unknown %06x", spacer, tagtype); + PrintAndLogEx(INFO, "%sTYPE : Unknown %06x", spacer, tagtype); return 0; } int legic_get_type(legic_card_select_t *card){ @@ -792,12 +803,12 @@ int legic_get_type(legic_card_select_t *card){ void legic_chk_iv(uint32_t *iv){ if ( (*iv & 0x7F) != *iv ){ *iv &= 0x7F; - PrintAndLogEx(NORMAL, "Truncating IV to 7bits, %u", *iv); + PrintAndLogEx(INFO, "Truncating IV to 7bits, %u", *iv); } // IV must be odd if ( (*iv & 1) == 0 ){ *iv |= 0x01; - PrintAndLogEx(NORMAL, "LSB of IV must be SET %u", *iv); + PrintAndLogEx(INFO, "LSB of IV must be SET %u", *iv); } } void legic_seteml(uint8_t *src, uint32_t offset, uint32_t numofbytes) { @@ -828,11 +839,11 @@ int HFLegicReader(const char *Cmd, bool verbose) { if ( verbose ) PrintAndLogEx(WARNING, "command execution time out"); return 1; case 3: - if ( verbose ) PrintAndLogEx(NORMAL, "legic card select failed"); + if ( verbose ) PrintAndLogEx(WARNING, "legic card select failed"); return 2; default: break; } - PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, sizeof(card.uid))); + PrintAndLogEx(SUCCESS, " UID : %s", sprint_hex(card.uid, sizeof(card.uid))); legic_print_type(card.cardsize, 0); return 0; } @@ -882,14 +893,14 @@ int CmdLegicDump(const char *Cmd){ dumplen = card.cardsize; legic_print_type(dumplen, 0); - PrintAndLogEx(NORMAL, "Reading tag memory %d b...", dumplen); + PrintAndLogEx(SUCCESS, "Reading tag memory %d b...", dumplen); UsbCommand c = {CMD_READER_LEGIC_RF, {0x00, dumplen, 0x55}}; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { - PrintAndLogEx(NORMAL, "Command execute time-out"); + PrintAndLogEx(WARNING, "Command execute time-out"); return 1; } @@ -900,12 +911,11 @@ int CmdLegicDump(const char *Cmd){ } uint16_t readlen = resp.arg[1]; - uint8_t *data = malloc(readlen); + uint8_t *data = calloc(readlen, sizeof(uint8_t)); if (!data) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return 3; } - memset(data, 0, readlen); if ( readlen != dumplen ) PrintAndLogEx(WARNING, "Fail, only managed to read 0x%02X bytes of 0x%02X", readlen, dumplen); @@ -934,7 +944,7 @@ int CmdLegicDump(const char *Cmd){ fflush(f); fclose(f); free(data); - PrintAndLogEx(NORMAL, "Wrote %d bytes to %s", readlen, filename); + PrintAndLogEx(SUCCESS, "Wrote %d bytes to %s", readlen, filename); return 0; } @@ -982,12 +992,11 @@ int CmdLegicRestore(const char *Cmd){ numofbytes = card.cardsize; // set up buffer - uint8_t *data = malloc(numofbytes); + uint8_t *data = calloc(numofbytes, sizeof(uint8_t) ); if (!data) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return 2; } - memset(data, 0, numofbytes); legic_print_type(numofbytes, 0); @@ -997,7 +1006,7 @@ int CmdLegicRestore(const char *Cmd){ f = fopen(filename,"rb"); if (!f) { - PrintAndLogEx(NORMAL, "File %s not found or locked", filename); + PrintAndLogEx(WARNING, "File %s not found or locked", filename); return 3; } @@ -1018,12 +1027,12 @@ int CmdLegicRestore(const char *Cmd){ fclose(f); if ( bytes_read == 0){ - PrintAndLogEx(NORMAL, "File reading error"); + PrintAndLogEx(WARNING, "File reading error"); free(data); return 2; } - PrintAndLogEx(NORMAL, "Restoring to card"); + PrintAndLogEx(SUCCESS, "Restoring to card"); // transfer to device size_t len = 0; @@ -1049,11 +1058,11 @@ int CmdLegicRestore(const char *Cmd){ free(data); return 1; } - PrintAndLogEx(NORMAL, "Wrote chunk [offset %d | len %d | total %d", i, len, i+len); + PrintAndLogEx(SUCCESS, "Wrote chunk [offset %d | len %d | total %d", i, len, i+len); } free(data); - PrintAndLogEx(NORMAL, "\nWrote %d bytes to card from file %s", numofbytes, filename); + PrintAndLogEx(SUCCESS, "\nWrote %d bytes to card from file %s", numofbytes, filename); return 0; } @@ -1077,12 +1086,11 @@ int CmdLegicELoad(const char *Cmd) { } // set up buffer - uint8_t *data = malloc(numofbytes); + uint8_t *data = calloc(numofbytes, sizeof(uint8_t)); if (!data) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return 3; } - memset(data, 0, numofbytes); // set up file len = param_getstr(Cmd, nameParamNo, filename, FILE_PATH_SIZE); @@ -1094,7 +1102,7 @@ int CmdLegicELoad(const char *Cmd) { // open file f = fopen(filename,"rb"); if (!f) { - PrintAndLogEx(NORMAL, "File %s not found or locked", filename); + PrintAndLogEx(WARNING, "File %s not found or locked", filename); free(data); return 1; } @@ -1102,7 +1110,7 @@ int CmdLegicELoad(const char *Cmd) { // load file size_t bytes_read = fread(data, 1, numofbytes, f); if ( bytes_read == 0){ - PrintAndLogEx(NORMAL, "File reading error"); + PrintAndLogEx(WARNING, "File reading error"); free(data); fclose(f); f = NULL; @@ -1115,7 +1123,7 @@ int CmdLegicELoad(const char *Cmd) { legic_seteml(data, 0, numofbytes); free(data); - PrintAndLogEx(NORMAL, "\nLoaded %d bytes from file: %s to emulator memory", numofbytes, filename); + PrintAndLogEx(SUCCESS, "\nLoaded %d bytes from file: %s to emulator memory", numofbytes, filename); return 0; } @@ -1146,15 +1154,14 @@ int CmdLegicESave(const char *Cmd) { fileNlen = FILE_PATH_SIZE - 5; // set up buffer - uint8_t *data = malloc(numofbytes); + uint8_t *data = calloc(numofbytes, sizeof(uint8_t)); if (!data) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return 3; } - memset(data, 0, numofbytes); // download emulator memory - PrintAndLogEx(NORMAL, "Reading emulator memory..."); + PrintAndLogEx(SUCCESS, "Reading emulator memory..."); if (!GetFromDevice( BIG_BUF_EML, data, numofbytes, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); free(data); @@ -1185,16 +1192,15 @@ int CmdLegicWipe(const char *Cmd){ } // set up buffer - uint8_t *data = malloc(card.cardsize); + uint8_t *data = calloc(card.cardsize, sizeof(uint8_t)); if (!data) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return 2; } - memset(data, 0, card.cardsize); legic_print_type(card.cardsize, 0); - PrintAndLogEx(NORMAL, "Erasing"); + PrintAndLogEx(SUCCESS, "Erasing"); // transfer to device size_t len = 0; @@ -1222,7 +1228,7 @@ int CmdLegicWipe(const char *Cmd){ return 4; } } - PrintAndLogEx(NORMAL, "ok\n"); + PrintAndLogEx(SUCCESS, "ok\n"); return 0; } @@ -1236,7 +1242,7 @@ static command_t CommandTable[] = { {"reader", CmdLegicReader, 1, "LEGIC Prime Reader UID and tag info"}, {"info", CmdLegicInfo, 0, "Display deobfuscated and decoded LEGIC Prime tag data"}, {"dump", CmdLegicDump, 0, "Dump LEGIC Prime tag to binary file"}, - {"restore", CmdLegicRestore, 0, "Restore a dump onto a LEGIC Prime tag"}, + {"restore", CmdLegicRestore, 0, "Restore a dump file onto a LEGIC Prime tag"}, {"rdmem", CmdLegicRdmem, 0, "Read bytes from a LEGIC Prime tag"}, {"sim", CmdLegicRfSim, 0, "Start tag simulator"}, {"write", CmdLegicRfWrite, 0, "Write data to a LEGIC Prime tag"}, From 72942624426a7c57b24bea25f37121dbdcea22d1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 21 Jan 2019 09:59:47 +0100 Subject: [PATCH 0434/1938] chg: 'script run iso15_magic' - added switch "-a" to swap between iceman styled vs offical styled iso15 raw commands. In order to run this script on official pm3 repo, you will need to copy this script and /client/lualibs/read15.lua file. Read help text for examples script run iso15_magic -h --- client/scripts/iso15_magic.lua | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/client/scripts/iso15_magic.lua b/client/scripts/iso15_magic.lua index 36e8100a8..3923f2b1e 100644 --- a/client/scripts/iso15_magic.lua +++ b/client/scripts/iso15_magic.lua @@ -5,7 +5,7 @@ local utils = require('utils') copyright = 'Copyright (c) 2018 IceSQL AB. All rights reserved.' author = 'Christian Herrmann' -version = 'v1.0.3' +version = 'v1.0.4' desc = [[ This script tries to set UID on a IS15693 SLIX magic card Remember the UID ->MUST<- start with 0xE0 @@ -15,6 +15,8 @@ example = [[ -- ISO15693 slix magic tag script run iso15_magic -u E004013344556677 + + script run iso15_magic -u E004013344556677 -a ]] usage = [[ script run iso15_magic -h -u @@ -22,6 +24,7 @@ script run iso15_magic -h -u Arguments: -h : this help -u : UID (16 hexsymbols) + -a : use offical pm3 repo ISO15 commands instead of iceman fork. ]] local DEBUG = true @@ -82,11 +85,13 @@ function main(args) print() local uid = 'E004013344556677' + local use_iceman = true -- Read the parameters - for o, a in getopt.getopt(args, 'hu:') do + for o, a in getopt.getopt(args, 'hu:a') do if o == "h" then return help() end if o == "u" then uid = a end + if o == "a" then use_iceman = false end end -- uid string checks @@ -103,8 +108,11 @@ function main(args) core.clearCommandBuffer() - magicUID_iceman(block0, block1) - --magicUID_offical(block0, block1) + if use_iceman then + magicUID_iceman(block0, block1) + else + magicUID_offical(block0, block1) + end end main(args) From 8ee857e4ba6d334ca30beefb4241b385abfefa09 Mon Sep 17 00:00:00 2001 From: Iceman Date: Mon, 21 Jan 2019 17:36:58 +0100 Subject: [PATCH 0435/1938] Update tnp3clone.lua --- client/scripts/tnp3clone.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/scripts/tnp3clone.lua b/client/scripts/tnp3clone.lua index 514a091b9..b17cf2661 100644 --- a/client/scripts/tnp3clone.lua +++ b/client/scripts/tnp3clone.lua @@ -93,7 +93,7 @@ local function main(args) local csetuid = 'hf mf csetuid ' local cget = 'hf mf cgetbl ' local empty = '00000000000000000000000000000000' - local AccAndKeyB = '7F070869000000000000' + local AccAndKeyB = '7F0F0869000000000000' local atqa = '0F01' local sak = '81' -- Defaults to Gusto From 601cb0fe0009c02a85b0c98c5649b92ea5e34c1b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 21 Jan 2019 22:04:44 +0100 Subject: [PATCH 0436/1938] chg: 'hf legic dump' - longer timeout --- client/cmdhflegic.c | 15 +++++++++++---- 1 file changed, 11 insertions(+), 4 deletions(-) diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 0f580da9f..c1677d00a 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -899,10 +899,17 @@ int CmdLegicDump(const char *Cmd){ clearCommandBuffer(); SendCommand(&c); UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { - PrintAndLogEx(WARNING, "Command execute time-out"); - return 1; - } + + uint8_t timeout = 0; + while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + ++timeout; + printf("."); fflush(stdout); + if (timeout > 7) { + PrintAndLogEx(WARNING, "\ncommand execution time out"); + return 1; + } + } + PrintAndLogEx(NORMAL, "\n"); uint8_t isOK = resp.arg[0] & 0xFF; if ( !isOK ) { From 063feeae05a5523c6e943efcd3e3b838d915a9e0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 21 Jan 2019 22:12:43 +0100 Subject: [PATCH 0437/1938] CHG: 'hf legic write' CHG: 'hf legic restore' CHG: 'hf legic wipe' - longer timeout for execution --- client/cmdhflegic.c | 50 ++++++++++++++++++++++++++++++++------------- 1 file changed, 36 insertions(+), 14 deletions(-) diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index c1677d00a..1403060e5 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -634,10 +634,18 @@ int CmdLegicRfWrite(const char *Cmd) { clearCommandBuffer(); SendCommand(&c); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - PrintAndLogEx(WARNING, "command execution time out"); - return 1; - } + + uint8_t timeout = 0; + while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + ++timeout; + printf("."); fflush(stdout); + if (timeout > 7) { + PrintAndLogEx(WARNING, "\ncommand execution time out"); + return 1; + } + } + PrintAndLogEx(NORMAL, "\n"); + uint8_t isOK = resp.arg[0] & 0xFF; if ( !isOK ) { PrintAndLogEx(WARNING, "Failed writing tag"); @@ -1054,11 +1062,18 @@ int CmdLegicRestore(const char *Cmd){ clearCommandBuffer(); SendCommand(&c); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { - PrintAndLogEx(WARNING, "command execution time out"); - free(data); - return 1; - } + uint8_t timeout = 0; + while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + ++timeout; + printf("."); fflush(stdout); + if (timeout > 7) { + PrintAndLogEx(WARNING, "\ncommand execution time out"); + free(data); + return 1; + } + } + PrintAndLogEx(NORMAL, "\n"); + uint8_t isOK = resp.arg[0] & 0xFF; if ( !isOK ) { PrintAndLogEx(WARNING, "Failed writing tag [msg = %u]", resp.arg[1] & 0xFF); @@ -1223,11 +1238,18 @@ int CmdLegicWipe(const char *Cmd){ clearCommandBuffer(); SendCommand(&c); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 4000)) { - PrintAndLogEx(WARNING, "command execution time out"); - free(data); - return 3; - } + uint8_t timeout = 0; + while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + ++timeout; + printf("."); fflush(stdout); + if (timeout > 7) { + PrintAndLogEx(WARNING, "\ncommand execution time out"); + free(data); + return 3; + } + } + PrintAndLogEx(NORMAL, "\n"); + uint8_t isOK = resp.arg[0] & 0xFF; if ( !isOK ) { PrintAndLogEx(WARNING, "Failed writing tag [msg = %u]", resp.arg[1] & 0xFF); From be09793fcda1e2fba280d2ca9bbae5c257092e7a Mon Sep 17 00:00:00 2001 From: Iceman Date: Tue, 22 Jan 2019 09:45:10 +0100 Subject: [PATCH 0438/1938] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 05b9a007f..f21a2efdc 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ I have also added this script to the fork. https://github.com/RfidResearchGroup/proxmark3/blob/master/install.sh - Run -`sudo apt-get install p7zip git build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev libqt4-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi libjansson-dev` +`sudo apt-get install p7zip git build-essential libreadline5 libreadline-dev libusb-0.1-4 libusb-dev libqt4-dev perl pkg-config wget libncurses5-dev gcc-arm-none-eabi` - Clone fork `git clone https://github.com/RfidResearchGroup/proxmark3.git` @@ -86,7 +86,7 @@ https://github.com/RfidResearchGroup/proxmark3/blob/master/install.sh ## Setup and build for ArchLinux - Run -`sudo pacman -Sy base-devel p7zip libusb readline ncurses libjansson-dev arm-none-eabi-newlib --needed` +`sudo pacman -Sy base-devel p7zip libusb readline ncurses arm-none-eabi-newlib --needed` `yaourt -S termcap` - Remove modemmanager From cf006a445fff51e7862fb1c440e22bf67d9d1382 Mon Sep 17 00:00:00 2001 From: Iceman Date: Tue, 22 Jan 2019 11:55:04 +0100 Subject: [PATCH 0439/1938] Update default_keys.dic ADD: more keys --- client/default_keys.dic | 83 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 82 insertions(+), 1 deletion(-) diff --git a/client/default_keys.dic b/client/default_keys.dic index 3fb8f07bf..c7186a154 100644 --- a/client/default_keys.dic +++ b/client/default_keys.dic @@ -711,4 +711,85 @@ FD8705E721B0, 00ada2cd516d, # # -D3F7D3F7D3F7 \ No newline at end of file +D3F7D3F7D3F7 +## +237a4d0d9119, +0ed7846c2bc9, +FFFFD06F83E3, +FFFFAE82366C, +F89C86B2A961, +F83466888612, +ED3A7EFBFF56, +E96246531342, +E1DD284379D4, +DFED39FFBB76, +DB5181C92CBE, +CFC738403AB0, +BCFE01BCFE01, +BA28CFD15EE8, +B0699AD03D17, +AABBCC660429, +A4EF6C3BB692, +A2B2C9D187FB, +9B1DD7C030A1, +9AEDF9931EC1, +8F9B229047AC, +872B71F9D15A, +83BAB5ACAD62, +833FBD3CFE51, +64E2283FCF5E, +64A2EE93B12B, +5D293AFC8D7E, +5554AAA96321, +474249437569, +46868F6D5677, +435330666666, +40E5EA1EFC00, +37D4DCA92451, +2012053082AD, +2011092119F1, +200306202033, +1795902DBAF9, +17505586EF02, +022FE48B3072, +013940233313, +1A2B3C4D5E6F, +123456ABCDEF, +FFFFD06F83E3, +FFFFAE82366C, +F89C86B2A961, +F83466888612, +ED3A7EFBFF56, +E96246531342, +E1DD284379D4, +DFED39FFBB76, +DB5181C92CBE, +CFC738403AB0, +BCFE01BCFE01, +BA28CFD15EE8, +B0699AD03D17, +AABBCC660429, +A4EF6C3BB692, +A2B2C9D187FB, +9B1DD7C030A1, +9AEDF9931EC1, +8F9B229047AC, +872B71F9D15A, +83BAB5ACAD62, +833FBD3CFE51, +64E2283FCF5E, +64A2EE93B12B, +5D293AFC8D7E, +5554AAA96321, +474249437569, +46868F6D5677, +435330666666, +40E5EA1EFC00, +37D4DCA92451, +2012053082AD, +2011092119F1, +200306202033, +1795902DBAF9, +17505586EF02, +022FE48B3072, +013940233313, From e885ec737df6dea50be909b8fe948e39e1e624e4 Mon Sep 17 00:00:00 2001 From: Iceman Date: Tue, 22 Jan 2019 12:03:53 +0100 Subject: [PATCH 0440/1938] Update default_keys.dic --- client/default_keys.dic | 38 -------------------------------------- 1 file changed, 38 deletions(-) diff --git a/client/default_keys.dic b/client/default_keys.dic index c7186a154..ffbdb3cbd 100644 --- a/client/default_keys.dic +++ b/client/default_keys.dic @@ -735,55 +735,17 @@ A2B2C9D187FB, 9AEDF9931EC1, 8F9B229047AC, 872B71F9D15A, -83BAB5ACAD62, 833FBD3CFE51, -64E2283FCF5E, -64A2EE93B12B, 5D293AFC8D7E, 5554AAA96321, 474249437569, -46868F6D5677, 435330666666, -40E5EA1EFC00, -37D4DCA92451, -2012053082AD, -2011092119F1, -200306202033, -1795902DBAF9, -17505586EF02, -022FE48B3072, -013940233313, 1A2B3C4D5E6F, 123456ABCDEF, -FFFFD06F83E3, -FFFFAE82366C, -F89C86B2A961, -F83466888612, -ED3A7EFBFF56, -E96246531342, -E1DD284379D4, -DFED39FFBB76, -DB5181C92CBE, -CFC738403AB0, -BCFE01BCFE01, -BA28CFD15EE8, -B0699AD03D17, -AABBCC660429, -A4EF6C3BB692, -A2B2C9D187FB, -9B1DD7C030A1, -9AEDF9931EC1, -8F9B229047AC, -872B71F9D15A, 83BAB5ACAD62, -833FBD3CFE51, 64E2283FCF5E, 64A2EE93B12B, -5D293AFC8D7E, -5554AAA96321, -474249437569, 46868F6D5677, -435330666666, 40E5EA1EFC00, 37D4DCA92451, 2012053082AD, From 0bec6038b733e1e0221d100c2746c5d4e710612a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 23 Jan 2019 10:57:49 +0100 Subject: [PATCH 0441/1938] CHG: adjusted compiling for older devices --- armsrc/lfops.c | 4 ++-- client/cmdflashmem.h | 4 ++++ client/emv/emvcore.c | 4 ++++ 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index c267db36e..d750fccbe 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -1591,11 +1591,11 @@ void T55xx_ChkPwds() { uint8_t *pwds = BigBuf_get_EM_addr(); - bool use_flashmem = true; uint16_t pwdCount = 0; uint32_t candidate = 0; -#ifdef WITH_FLASH +#ifdef WITH_FLASH + bool use_flashmem = true; if ( use_flashmem ) { BigBuf_Clear_EM(); uint16_t isok = 0; diff --git a/client/cmdflashmem.h b/client/cmdflashmem.h index 9f71a4ce0..ee661bf18 100644 --- a/client/cmdflashmem.h +++ b/client/cmdflashmem.h @@ -8,6 +8,8 @@ // Proxmark3 RDV40 Flash memory commands //----------------------------------------------------------------------------- +#ifdef WITH_FLASH + #ifndef CMDFLASHMEM_H__ #define CMDFLASHMEM_H__ @@ -38,4 +40,6 @@ extern int CmdFlashMemLoad(const char* cmd); extern int CmdFlashMemSave(const char* cmd); extern int CmdFlashMemWipe(const char *Cmd); extern int CmdFlashMemInfo(const char *Cmd); +#endif + #endif \ No newline at end of file diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 5ea9026c2..77d288eaa 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -262,8 +262,12 @@ int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveField } break; case ECC_CONTACT: +#ifdef WITH_SMARTCARD //int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); res = ExchangeAPDUSC(data, (IncludeLe?6:5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); +#else + res = 1; +#endif if (res) { return res; } From 61ebdbde6b65601f997dae4c5f606c75ce3837e8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 23 Jan 2019 11:01:11 +0100 Subject: [PATCH 0442/1938] CHG: adjusting compiling for older devices --- client/cmdflashmem.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index 6361d48e3..d3aaff19e 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -7,6 +7,8 @@ //----------------------------------------------------------------------------- // Proxmark3 RDV40 Flash memory commands //----------------------------------------------------------------------------- +#ifdef WITH_FLASH + #include "cmdflashmem.h" #include "mbedtls/rsa.h" @@ -604,3 +606,5 @@ int CmdHelp(const char *Cmd) { CmdsHelp(CommandTable); return 0; } + +#endif \ No newline at end of file From 5e13c7e58879d3823f5f182ab27ba7b31508e2bb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 23 Jan 2019 12:18:07 +0100 Subject: [PATCH 0443/1938] ADD: Found a bunch more dictionary files, from a link on the forum. --- client/dictionaries/bmp_sort_keys.dic | 1000 ++++++++++++++++++++++ client/dictionaries/icbpm_sort_keys.dic | 1001 +++++++++++++++++++++++ client/dictionaries/mrzd_sort_keys.dic | 57 ++ 3 files changed, 2058 insertions(+) create mode 100644 client/dictionaries/bmp_sort_keys.dic create mode 100644 client/dictionaries/icbpm_sort_keys.dic create mode 100644 client/dictionaries/mrzd_sort_keys.dic diff --git a/client/dictionaries/bmp_sort_keys.dic b/client/dictionaries/bmp_sort_keys.dic new file mode 100644 index 000000000..0f8acdcf3 --- /dev/null +++ b/client/dictionaries/bmp_sort_keys.dic @@ -0,0 +1,1000 @@ +002DE0301481, +004173272D18, +0058A4884CA5, +00BAC32761D8, +00BB79731B00, +00E8C85DB172, +02096124DA70, +024988BC4D5E, +0271B7C4B015, +028137A705DB, +02827C286AB4, +02C10DA600D0, +0340643D5E27, +037A5DA4682B, +037AC43CBD9D, +037B9B8AA219, +037EE3DE21B7, +0380A9A3CBDE, +03D10A75B56A, +03E8CD22E691, +04109ED8EA79, +04361330B35C, +043D8B66D569, +045E5588845C, +048DE5148DE7, +0490921D0194, +04B717BD92EB, +04D49C76623B, +051518B3301E, +0529E8827A52, +052B16064085, +05DC4016B500, +06124317A9A6, +06147D199266, +0670AEB833CE, +0686A9E6D6E0, +06A34E5E6639, +06B78AD0C4BB, +0710E7818AB8, +07121B8C633A, +07176713C0ED, +0793533A5087, +081D1B1C3110, +0849495E1CCA, +09429512046E, +0966C3B28E04, +098A92C3660A, +098B48278122, +099672009EEA, +0A7632943926, +0AEE126549DA, +0B3B8C2833BC, +0B733C13E2C9, +0B764247D00E, +0BE811559D69, +0C208AD4E4B3, +0C270BC0BDDC, +0C5D782CB183, +0C82C94EB11B, +0CCDE948878A, +0CCE39820AAE, +0CDE3E716B32, +0CE06C96DB4C, +0CE87813E389, +0D3385CEA152, +0D5C5B8BCC5B, +0DB0A87AB882, +0DE247593B93, +0E0AD1796003, +0E62E6CAC3D3, +106E2D6E55E6, +1096A7830C82, +11549C141AD9, +116A92C793D6, +116C31526819, +11C68052AAE9, +1234B5BE8E78, +1268C7D104E1, +12A21B5671A8, +13359D5AE9A5, +1426EC62BB6C, +144489B1056E, +14A22C112090, +14C9BBB5361B, +14EB6286AC57, +14EE72B27223, +153BB53ACE71, +157B03405B38, +15A45083D24E, +15DACCE8D5EC, +16124677BBC5, +16373A44D5D7, +1663659384DC, +167828B6105C, +16B25A453093, +1706B1BE25C7, +171B15888483, +17BC8EED9A0C, +17C6299D5A37, +17E9C4C416EB, +1804087C7166, +1841CC4E3E79, +18AB05761CC5, +18ADAAC2B08B, +18E566417E5C, +191390328752, +1A47959E7DB4, +1A9A970CC370, +1B095E78BB33, +1B1717043D2B, +1B1A054566D9, +1B4654AE9454, +1B9CD1ED3420, +1B9E00780953, +1BB6A9CE71E2, +1C1250A36A13, +1C2316079532, +1C2855ED7A10, +1CD1AE73CA8C, +1CD3D4E690B7, +1D0322005969, +1D09B23EB116, +1D67A32045ED, +1D89D900968A, +1DAE8D2CEA5C, +1E1873799CD7, +1E60CE7C5179, +1E6A67909B8D, +1E8516585792, +1EB0864E9134, +1ECE3D04A020, +2009828E4A21, +200A6A3AA65D, +20188A599582, +20267CB20256, +20628CA7D92D, +2077C980EB2E, +2089B5D68B27, +209481EC6256, +20B6691C64B1, +20CC5A00C677, +211473555436, +2170E9D0D448, +219529A90EDD, +21A5B6481B7D, +224A308017D1, +227D16EA455A, +22A1245CA266, +22A95CB798DC, +230E26964171, +231173B68E46, +2332BB9A2452, +234323BC2992, +234E50256146, +235C9338D5B6, +23789D9ADD0D, +23997DD240AB, +23A5BA53AD4D, +23BB58853461, +24CAD4153036, +24CE79506842, +25228ED714BC, +257377227B34, +2584287A0174, +2616192EEB22, +265C03B50877, +26D641E834DC, +27073B57132B, +279060E3DEE9, +284BA0A0A29C, +285C6604C5B4, +28B20331245A, +28D042242A83, +28DDD4C3E9C4, +292C2CCD157E, +299ABB519354, +2A41BE015C1D, +2A4A55052A51, +2A94CBCD7A6E, +2AB6536187C7, +2B2D2DC3D319, +2BD607CA70B2, +2C6C7957EB3E, +2C9E9E4D0895, +2D2A97DD45E3, +2D41850A8AA6, +2DAC030D1AB9, +2E12426D8847, +2E25AD1D6D8D, +2E2E85E0E6C9, +2E4340CC1C63, +2E6803BE2E11, +2EB24B573DCD, +2EC6450A47C7, +2ECDA9A5EA96, +2EDE1C155023, +302D5D37342B, +303645E47667, +303B30A460E8, +3048EBB8A18E, +30BD652BED24, +30CCE5ECB397, +310241E1CB36, +312670228372, +319E8895EAB5, +31E3A933BC4A, +3250D2E661DA, +32560224418D, +32589E221D10, +326657A8E9C0, +329AC7C59311, +32A091B89995, +3312C094BD20, +336C8CBA5AE2, +34240649314A, +3493D84E6317, +349A347186D7, +349BEAC5210E, +34A939B49EDC, +34CC7E36C8C4, +34D71347877E, +34DC25B4D0CE, +35895EB472C4, +358A6A398211, +360A08C66042, +36306A9CA571, +37284428A250, +377EC8A78B8D, +37BD90A68613, +37E602347133, +382DE6AB2D1A, +385D498B5390, +38B67589E47D, +393CCCCCDA4A, +39682B3E10B5, +397619525709, +39A83A32909B, +3A5834C46513, +3A70C7A4BCE4, +3A818D01E093, +3AA5AC1CDC21, +3AAE07339954, +3B4497052B42, +3B784087DB2D, +3B86A20C16EA, +3B8E321AB1B4, +3BC4A3099B0D, +3BC741376E71, +3C4C95D0A0C7, +3C84B55A5E54, +3C888A88C59D, +3D5C8240B2D2, +3DB004172BE7, +3E23271C1C15, +3E3188294ED1, +3E84144A770E, +3EA227893101, +3EB914E70076, +3EE6D4A85643, +40DABA780B41, +4119340759A2, +415210E0C6BB, +416D21717779, +41B1839829A9, +4201A36DE766, +4261A795D5A7, +42AA0B29626E, +430265958BEB, +4317C5C16EAD, +431D799E0C89, +4342794AD7BB, +4387ADE263DB, +43982124C310, +4436CB060568, +44449507B736, +44E858C82975, +459BC12982B1, +45AE5DDA9830, +45C414CDC347, +45CE4E504C06, +461744C8EABD, +46D012CA3BEC, +47170BD112B6, +47C43D5DD234, +47CD4AC26271, +47D410D1C7C4, +4808C5AD0115, +485BEEDBC293, +486001404A80, +488CCC60B70A, +49204E3CA169, +495657C78147, +4970714D53D9, +4AA715A0BBB4, +4B9901AEC16E, +4BE0B912A5A3, +4CBC34D10D83, +4CD3ACABC6A3, +4CE00134DE1E, +4CEB27151C49, +4D02A3D7CE48, +4D13683C7960, +4D1A263BA48B, +4D23919463A3, +4D9763C083D9, +4DAC8EE52C68, +4DCB89C7B2E6, +4DD9D9B637C4, +4DE6CB63A920, +4DEBA10CC85D, +4E232A8C2E30, +4E2879A411E7, +4EA7B0BED74B, +4EB8761372EA, +4EC2B23135AB, +4EC71DB088DE, +4EC9AB4B5519, +50179E461EE6, +50265ED9D468, +5047DC2975BE, +508357498162, +508BE54D326E, +510A8C52AAC4, +511335CC92CD, +518229589A81, +5184D04315D7, +51B4AE31B246, +526EDB918BEE, +529CE44BEBCC, +52A843082BB3, +52AE9A909674, +5313E9079489, +532DE5E7E0E9, +535508AA6C91, +53691569B669, +540A5B789761, +547B86E57596, +54C649075B57, +552249203848, +55430B5318E9, +5570D22DC66B, +55710879E113, +55D2E4AC0446, +56207539825A, +564664475726, +566441C5C28C, +56A7930913C3, +56C944B04618, +56D455A8BBEA, +5726991C8C28, +5726AA3BE37B, +573314090BA5, +577C31903867, +577C528E786C, +57AD9604ED24, +580C377283C7, +587329CE3EBE, +587C34557B36, +58B11E803B58, +5902E4DCC95D, +5A060A64C535, +5A36898CA7C5, +5A4740D952EC, +5A6ED7966868, +5A99578CAA13, +5AAD6814E68B, +5B065568048A, +5B6CE0B3AD0A, +5B70E0B11758, +5B926E3751EB, +5B9CA63C4267, +5BDC1391B289, +5C1D3898D537, +5C34B8E4A456, +5C36456EA1E5, +5C43A75C65A0, +5C5752328A47, +5C9D20250D74, +5CBA3CEE351A, +5CD5E98A2864, +5CE0EB9C01B6, +5D384E6A4145, +5D9DB8445155, +5DE8717BB640, +5E1A4EE98748, +5E45A227B391, +5E8E50B3048B, +5EB0EA0A9412, +6032C47B7676, +60E0C84ADDEE, +612A447A2149, +612D81821854, +616B820EAD01, +616D75A4A022, +61DE2B085AC9, +62312EC272A0, +6232C5262CC6, +62B7C7C9B0D0, +62C531C6E29C, +63E6AAAB4433, +644ABCC3DD12, +64AE7BEA1784, +6515B38077D6, +65972038CC25, +65E120DE5E55, +66141DDE8320, +66718BD91332, +668082242328, +668920AEE063, +6696C4332D46, +66C9880D1DC2, +67150CB11E95, +671737BA0054, +673551D0A99E, +676D682C4336, +678B98AA2E86, +6847808E63EE, +6887A122AA62, +6888C514DEAD, +688BD5B7B4E9, +68A99E258692, +68C312391560, +68C9D33E3735, +6900A069E3D7, +690155BE8D8E, +69174742042D, +69B9CE233517, +6A0B123D7595, +6AB8E2B49E25, +6ABD4C4A72D9, +6B1CC539A1B2, +6B30B6B0925D, +6B638C1C950D, +6BAAAB1D4589, +6BAD01EBE736, +6BB4ED5E1682, +6CA178E036DA, +6CE210B529C4, +6D23D505D2B1, +6D3CBD12BC6D, +6D83563EB521, +6D98AB9CCC71, +6E3D7366E78C, +6E5582237608, +6E6602904925, +6E77B8EB6444, +6E978A7B16C6, +6EEC05EB651C, +70284824B26C, +702CDACE0C14, +704E1B85BED8, +70BB123776D6, +70CCC3A2D7C0, +716A747CB931, +7173E199A420, +71BC9C9E31E4, +71CAEEA3B771, +71D8BA423D55, +72253C7DD951, +7260377CD286, +7280858E8B20, +72913BDAB647, +72B5B87BBC6E, +72C83B1D098A, +72DA8050A38E, +735C2AB60A97, +736B602A93D9, +738D7833E7DE, +73E7B22D6E54, +74133B1E2DED, +74A929877793, +74E3670C045A, +7531E3E2A41C, +7542A9B65EB4, +7564993C91C7, +760ED0AB626E, +762E0E021E38, +763D7E6BB40E, +764B38E2903D, +768016001C8D, +76A616C3D42C, +76AE99D9A294, +76BAAA710D25, +76E3B23696BC, +77322DD2E184, +77B40902B6D9, +77C0AC14972D, +77C1CE0E7674, +77D7B7E2C8BA, +78279397A68E, +7836593AB838, +783859EB51A6, +78CCDB50C193, +7932684154AE, +79604362370E, +796630ED27B3, +799E4E270953, +79A00573947A, +79B798D66B01, +7A0455D0A7EC, +7A33D19B7248, +7B0A8AE18817, +7B0BA045AB35, +7B0DE8504D57, +7B21781EC649, +7B7224C1AB79, +7B90C2BA9B23, +7BB90D382672, +7BBC9DC92836, +7C09DC408C47, +7C418B493454, +7C491D518242, +7C7A86CC727C, +7CE836EBD228, +7D49042C530D, +7E5744EC286C, +7E680A48C383, +7EC45CCEC35A, +7EDADA19EB57, +8005BD088847, +8022E705B640, +8031E3565825, +80499BAA5959, +807466CCBAB5, +810518578380, +810D24CB13CC, +812B02C34A64, +8163A5DDE1CD, +8186CE2B363E, +81DE6062B9D7, +822017D8929A, +8247C78188C5, +8270D538D5E8, +82D8E8DDE296, +831207CA6E8A, +83378A077357, +83A05B477535, +840160379EEE, +84044BAB78A7, +84366C6D7781, +8442CC9AA777, +8470AAD30447, +8498740493BB, +84A35A698E93, +84ABDE484425, +84B24DBB9A67, +84B723B2A237, +852BEB133D74, +854501E98239, +854A0ED2E77D, +85A066D39785, +8619557091AA, +86228C3742A4, +8637BB3BA795, +8642D9310B46, +86538085966D, +86EE9C410811, +870A042C1B34, +873B47C457E6, +873CE44DDC6B, +874D123262E7, +87513C960770, +877641436923, +878A091B74B7, +87927467808B, +88C2E39B5990, +88D252AC1A8A, +891EDA20BDEA, +89267DEE07ED, +892CB89ACCC6, +8A2423E9D100, +8A6BC2E3811B, +8A8EB5771EE9, +8A906B4B3211, +8AB21B524C5C, +8AB823BDC2AE, +8AC3B2ADE77B, +8AC4317D049B, +8ACD6B86EC44, +8AD966CA3B4D, +8B0A3B3DCDD4, +8B1B6C705C1A, +8B1C75E27153, +8B2A5E0332A1, +8B6216E412DB, +8B7CCA9DB004, +8B9999AE9703, +8BABAD9A65C6, +8C32D0AE3DB7, +8C99807368A5, +8CC1133D7D5B, +8CD2C872187A, +8D0563B86DD4, +8D43D81E37B4, +8D96A800B21A, +8D97B475C957, +8DA62EC0C524, +8DACA1BC0636, +8DE3B131D728, +8E55316D3B3D, +8EE497C9A869, +90210DDAB57D, +9026977EB8A6, +903AA4305025, +9083158A49A1, +9092D12E7967, +90D8713352D1, +911E097A27A9, +9140EC087241, +918A67D05479, +919B1D357E91, +9210BBA2AB26, +9224B6555E30, +9226D4D1236A, +922E7955CC67, +929CC86B1B26, +929E1556110E, +9302DEB79C5A, +9384841B4702, +93B4BD1CB47C, +93D985D55712, +940B37939AC6, +94673AE73823, +947A8147E0AE, +94CD6A4B6391, +94CEEAC5A8D7, +95ABD3A7C631, +95E1C233EDE2, +9607AE17AD09, +960C98566E52, +96435BD1D29B, +965D66E19245, +965D72659982, +9695167B4149, +96D0C3996714, +97274C21BD6C, +973186B345BB, +973A28C983A3, +979686C51AB6, +97992CE2DD31, +97E9D0C89DA8, +97EB8A44C49D, +98314DC363C5, +9860DC044565, +988D023C15A5, +9917BDA7B4D7, +9996A233442A, +9A2132B5B625, +9A694755A978, +9A7911ECC275, +9AA1E6CE588C, +9ABCCD2AE7C7, +9B39A60D3841, +9C0630361CC5, +9C4E19AB64B1, +9CE96BADE4D8, +9D442B28BD11, +9D4C35AE1A08, +9E02910C691A, +9E46407C9024, +9E74D104ACEA, +9EDD416A7912, +A026642D13AD, +A12908B38536, +A16EE9666D5A, +A199132A4043, +A1AEC2B58BBA, +A1BE42A15EDE, +A1D0844C2C63, +A1E0103A1879, +A253602B9445, +A2B019B46CB9, +A2BBCC3B546C, +A2C325A73A9C, +A2CB60E815A0, +A314B97C1A6A, +A3647146C335, +A3A580799BB4, +A3D30CC8EB97, +A402B5137D86, +A42158CC74B5, +A435DD64AD17, +A4693D21013B, +A479A91EED49, +A4B30D146A01, +A5142D626200, +A54056E87CBB, +A57DBD287491, +A588C918E327, +A593071D4758, +A5CC0EE7B9E3, +A6375E98A5B5, +A666347B3B4B, +A6A203994202, +A6BAE1A1520D, +A6E9885AA49D, +A705087E89A8, +A7072D4324C7, +A745AD7D6789, +A750456E7C5E, +A783A8774651, +A787C822020C, +A78BB575EAC5, +A7905680A254, +A805534D84E9, +A86C2595A1C3, +A89903B6ADDB, +A9182707A219, +A9391782A846, +A96B08E3A50B, +A98DEB0733C9, +A9C37CE71D23, +AA2D69C757D9, +AA4E4558A9EE, +AA6C835C9124, +AAC0C35C43EB, +AB30CB2CB354, +AB6191DB240A, +AB8953D3560C, +ABBB521319E6, +AC47461358D7, +AC58C25A1559, +AC7D4B201D92, +AD061A23287D, +AD105D52DB36, +AD4EA84D7185, +AD5038D15490, +AD97523144B2, +ADB24E78784B, +ADCBD453B232, +AE516A187825, +AE52116C234C, +AE817239CAB5, +AEA5A5A0E46B, +AECC93678543, +B0452769A83C, +B04D71906C60, +B0805C191424, +B09172DDBE43, +B13AE369390C, +B14080E570D1, +B1419B62772C, +B14775DEA2E2, +B188BA649EA1, +B1BB0DB95C67, +B1BB19BDD424, +B1E8B5054DAD, +B1EBB537CC0D, +B2174092CDC5, +B2554CC8AD6E, +B2C5A2E88304, +B312E56ED250, +B37B48D8C1C5, +B39C699CD208, +B3B121208E34, +B3C3C6E4395B, +B410B958C3B8, +B4204546A74E, +B45171C5A67D, +B4B103E693ED, +B4DACABCAB07, +B506567A2B84, +B51083D5C2BD, +B54D7674CB90, +B570E5EA1DA3, +B598984AD584, +B5D7E1135821, +B60D053A36D9, +B63957593E23, +B64558CAC0C9, +B68175BCA864, +B6CD1A3EC5BC, +B72468A7710D, +B75176C82A8B, +B7AA0CA5D94A, +B7B9D7E523B8, +B808D87AB75C, +B93A6432E51A, +B941A9D99B6C, +B9DA40920237, +BA6C2E10086A, +BA7384AB949E, +BA8DEEE045E8, +BADC2149EC42, +BB1924266B36, +BB41640E6340, +BBB475DB2B03, +BBD4C4699719, +BC0B2C897267, +BC7BEE6B71C4, +BC8B21AD8802, +BCA2D8118631, +BCB7A7006400, +BCBC6637499B, +BCBD2B8BE4B3, +BD213E28C568, +BD32E4EC7080, +BD401D63C3E9, +BD463C3693A4, +BD749E85586A, +BD7CA11B9551, +BD96355CBE36, +BD9E6EB7B524, +BDADE6111218, +BDB576D1E88C, +BDB5DC09C522, +BE19C75D6B7E, +BE5B3ED935AC, +BEA20C972E70, +BEEB4A159B37, +C01E8740DE38, +C0411C28857D, +C045544AD1E4, +C04660B76831, +C0C4CA21B876, +C0E0E092C8B4, +C0EE394D3D95, +C14601C6B411, +C16EBAE928B2, +C189A791A85B, +C1ACDB8C1890, +C1C55A7A99EA, +C1D72A47755A, +C1D8B91D65AA, +C1E6149B386D, +C22D8E2B1E37, +C23E999B6298, +C314E31A670D, +C3D275A9B8C7, +C3EE19B61C89, +C427B93DC2ED, +C443EEC4330D, +C477B966D328, +C4C6CAE4784C, +C55875BCB82C, +C581CA998910, +C5ABC0A455C5, +C5BE33E6B1E2, +C629E0D34581, +C65194543D6B, +C67B8E869D90, +C6BC3B9CCB41, +C7034BC581A6, +C748500B6947, +C757C15E9E0D, +C798A8465ACB, +C7B6702AC17B, +C849133B7CCC, +C870C98A4E91, +C90B7AD266D3, +C90D996C3A2D, +C953797CCE61, +C9639352EEC8, +C983685AA86B, +C9CCA6D095A3, +C9CE81D47EDB, +C9D449AD9970, +CA0D9CCC4C38, +CA277AC09859, +CA56EB045188, +CAB92B865BAD, +CAE8572C2657, +CB1CE185575C, +CB2ECC3D9C22, +CB642A081A89, +CBBAD2DA0EC5, +CC1B5BD45315, +CC2C02300D34, +CC559969D0CC, +CC5646BD7AEB, +CC6A93BD93D1, +CC726DD08765, +CCBBAB6504A4, +CCC1EA3E27B8, +CD16EAB946E9, +CDB4EEE02E14, +CDC21E1E1EC7, +CE09B3870EA2, +CE5AA0C8B5A8, +CE63DE29E069, +D0368B24CA49, +D0489010A72C, +D075379A21A6, +D09893B4EE04, +D0A7A2787570, +D0B8C06C02E4, +D106E94A4C3B, +D11E7D1BBEEA, +D12B25B8DDE2, +D1972D6CE2C3, +D1B91D224946, +D2752E53679D, +D35B2B75CC52, +D40E935117A2, +D4C37528DC05, +D4C818A5455E, +D4CD56DB8AEB, +D5190BD5CED6, +D55E5AA3406D, +D576E9D856D9, +D5E444E9D82D, +D61A3231790D, +D669B3AE1E11, +D6C075899D06, +D6C3503456C4, +D7AC70A05A0C, +D80A37B6D7ED, +D82E6938C58C, +D85E51344EB6, +D8809EB9BA7D, +D8913C2D48E9, +D9109460D912, +D94E36427E20, +D97E55B1816A, +D99425130C1A, +D99C3222A190, +D9A207103ED7, +D9C70CC5818A, +DA3379D12773, +DA705702248C, +DA818C56CE43, +DAE1888DCC0B, +DBA0A2DCA8E0, +DBD9799E15B1, +DC242193D7E3, +DCB5AC62946C, +DCB75AEC61A0, +DD6E0587A821, +DD7B1A7C6A82, +DDA22A189095, +DDDAE53AA711, +DDE7304E78B6, +DE1B4DA681B9, +DEAC67E2D7C1, +DEB7D7E4C62B, +E127434AB3B7, +E1ACC6742AB7, +E1E59574ADBC, +E1EA6BAA03D9, +E222553A59A2, +E2230B8E84C9, +E33E807EC3BA, +E341574B2E32, +E42868808B70, +E43562C624B0, +E43D54DC3511, +E466090D2123, +E47069DA0C44, +E49DD6062901, +E4ACA0ADBA0D, +E4B976AD6687, +E526BB7888DB, +E53354B71B10, +E57581CE8617, +E61A1DA5A60E, +E6293BDA5EDC, +E64C2A07CA9B, +E6600C4D6A44, +E6655B6425DC, +E6BADC631036, +E70143BE0091, +E75E07A010D1, +E76962E3B8B4, +E8028A6DCC90, +E80C5E3E8227, +E8779E40450E, +E8A9E2D87D36, +E8B5A0BDD993, +E933DA9735C4, +E93A2E63189D, +E9447637E40D, +E94836269887, +E94D82A564BA, +E98DC3B561B5, +E9EB2DE57AE9, +EA490920877D, +EA4C494C9353, +EA9B1695DD91, +EAD0E31A6834, +EB16B6462B66, +EB276C9AB68D, +EB3C9732C3BA, +EB44DDC408CE, +EB8536C958B2, +EBC825C186B3, +EC1A55BB58EB, +EC2B12107313, +EC8CB5758097, +ECD4C42EA3D1, +ED22B7115435, +ED2CE17A590C, +ED65A9B6469C, +ED6748113E0D, +ED8CEB8B7102, +EDCE0890472D, +EDD4A2EA7493, +EE17C426D25E, +EE487A4C806E, +EE5931913A8D, +EED56840AEBA, diff --git a/client/dictionaries/icbpm_sort_keys.dic b/client/dictionaries/icbpm_sort_keys.dic new file mode 100644 index 000000000..b4a635d44 --- /dev/null +++ b/client/dictionaries/icbpm_sort_keys.dic @@ -0,0 +1,1001 @@ + +00383D96411D, +005307DB7853, +009A4C4C6C49, +00C447B8A2D2, +01124119AB54, +0117BAE4D8D9, +018861488381, +0267B4922681, +02974B9786C9, +02A46AC9233A, +02BED876BD48, +02D8A7729ED3, +02EB32B92D30, +03C34821DE9A, +03D87397E9A8, +042CDEE5D0BA, +044ED79417E1, +04524659496E, +04602A40C037, +048451A79DA1, +0490AD0C9283, +04E16965C142, +05138E278443, +052B99EC186E, +056D4B5D2915, +0578E317C419, +05865124E5CA, +0599E014139E, +05DB68DB9364, +066C127C208D, +06966B31A285, +06B577E0E480, +071B57D258CE, +072B300309C9, +0759955331EE, +0769855EEC13, +079B8DA54DB1, +082B68A67491, +0832E4783600, +08506533E741, +0853A982D793, +08629D1DD0D6, +087C0CDA3B46, +08AE4ECD7CE3, +0965220D2ECE, +09A14A80754E, +09ACEA48DD0D, +09DB8EE5458C, +09E6CB76C080, +0A44A754B592, +0A7328887DC2, +0A906663EE1C, +0AB08938E3DA, +0AD8AD0739A6, +0B00220EAE75, +0B1960681E79, +0B31815E6A7C, +0B3690D4B122, +0BB8414CB6EA, +0BEC525E3463, +0C296648344D, +0CB6CC83AC45, +0CCAD03DDBC6, +0D6C26AB25CD, +0DC9143735D1, +0DE8A36CBBCC, +0E175033BD77, +0E6478123917, +0E7D4AC83133, +0E8420B04083, +0EA607E1C4E3, +105743704432, +107A6AB6B305, +110BB6D5539D, +1114A47CC39A, +116AA873ACC8, +120616C6208E, +120C83C06317, +12343D71106C, +123A082E2AEA, +12E50BE60524, +133DC845505E, +138153A4351A, +1395C108B6B6, +1428C04BAAD1, +147D93848C70, +14A353C60820, +1504C1846399, +1523A1E39D03, +1532A2511A8B, +157308368E8E, +16065CC411E0, +1637D8ACA71E, +1639134699C7, +167358BB268E, +168DE72B3B5A, +16A05D5C31C3, +16B4442EAE97, +17197B247A4A, +1774DB1A8CA1, +17820DAA47B2, +1782BEDBD347, +17B561AA82B4, +17C548CBC3A6, +17DA5C873BC5, +18025130661E, +184B95B4E3C6, +18A3196D364B, +18A97BD26818, +18BE810A83DD, +18C3AC2A7E90, +194D4E1DE89D, +196E279BE9A9, +1A2C8D855336, +1A3A76ED470A, +1A55D4849951, +1A9872D00EC9, +1ACD5433BBDD, +1ADC527D5BDA, +1AE29C8CD672, +1B14CAC3D0C2, +1B20A6E1D06B, +1B30A7825B23, +1B3E45AEE657, +1B75E7B007DB, +1B9DABDEBAE0, +1BAB19D01495, +1BD3119E0363, +1BDA0D87A575, +1CD38D77090B, +1D12BBB575B1, +1E1A0DB8729C, +1E2DE60A477A, +1E3C71643766, +1E6ED46CE258, +1EE60A4A8D22, +200D45263629, +2013899194BB, +206CE78E0C6C, +20B51C977E54, +2142B57D369D, +2172D827D3E2, +2178ED80D581, +21B4BE97AE07, +21B91A26133A, +21C7650673CD, +220D815D366A, +22C2176E1CD6, +22C3AB41B123, +233D7B324CEE, +2340CBD61A71, +2348251AD23E, +2381B8214025, +23BAE8DA1AC5, +23C317B8D6DA, +243A41574A39, +248EA5E91987, +2491457885A7, +255A9E590BCC, +257192699E32, +25892216C620, +2595E5B1DE76, +25AE69DED1B4, +25BA8775B3C4, +25D967D4DD35, +25DB996D56ED, +25EE21CDE4B9, +2625E408276B, +26B744C673DB, +26C6D38B8257, +26D787613684, +27689527E201, +27743B5A5736, +27D1635ED1B3, +27D5B8D2642E, +28035CA5B300, +2812EB6A427C, +28133B46730A, +281499DD16A0, +281DD9E6C98E, +2870E08CEDBA, +28B8685B1B22, +28C3D17E4DEC, +2953C63E9E58, +295D3C9A8B28, +297B74853CAA, +29ACACC2828E, +29EA97BC4A6B, +29EB3CA1C0DE, +2A079CC2AD37, +2A27E0602400, +2A45A0D8D6EE, +2A47CDD3A322, +2A4C4DB1D71D, +2AA82B4B6711, +2ABD68BDC5A3, +2AE7BDB10CB4, +2B051C90BE82, +2B490231E063, +2BAB94372644, +2C03252C10E7, +2C3EE5E98804, +2CB671E6365D, +2CC55B46705B, +2CD09D3C0A1B, +2CECBC323E31, +2D302827C9B4, +2D716C9C467B, +2D8856109732, +2E15681A4355, +2E79209B9519, +2EEE063290C1, +301C9AA3DECA, +30C520D6A2B9, +30D6324910AB, +3113AADC9D6B, +3124ACA5491C, +315AD0D6E6D2, +31A16DAC864D, +31EC44581294, +32DE3CD81C24, +32E532232C29, +33256E443128, +33293485AD61, +33305B0365AA, +3343B72BAA71, +3372C9C5D4AE, +33754E0D1687, +33A444334869, +33B54345C32E, +34002AAEE45D, +343C556CEE59, +3444DDE6D7E5, +345B62452538, +3495A04A9270, +34EB673C863B, +35123500C1EA, +353A7167576B, +3599856810B2, +35E7DE9899EE, +35EDABB506D8, +36C54912D10E, +36CA0101B6DC, +36D268442846, +373E5827E0B8, +376D6C446746, +37E2EAE635B5, +381B0A70E135, +3862B259DC71, +386676C44A13, +3905679DEEC4, +39070618BB17, +394181105544, +395D38815892, +39A00E856381, +39C0E2ED99B5, +3A1E82E2CDB7, +3A5D13E05B6A, +3A6DE2081CDD, +3A8498924010, +3A9D49E8BEB2, +3AD0EE1031A9, +3B052E65D40A, +3B4986981212, +3B4C51ACC53D, +3B99486097C6, +3BB36BC22CE4, +3BB4B3025B79, +3BBB7BD8D7B7, +3C09C971D835, +3C4A12E7A107, +3C633B3474DD, +3CB9E31D6022, +3CD344A7EB21, +3CD8C6705954, +3CE887B9D091, +3D5EA1C71953, +3D89120EB993, +3D9C3245AE76, +3DED9D496478, +3E0913A96E74, +3E34909990B5, +3E7DD7953DDD, +3EEB33434C1A, +4015D16B5C1C, +401C81A72C56, +40E7B8D60242, +41016C0CB8DE, +4124864B0D40, +415BAA0CAB15, +418184DBB4A0, +419513740558, +4195EE7238CC, +41B727883B27, +41BC44A8C3C6, +41DDC3A48EEA, +420445087613, +42068108DE36, +4245921D73CA, +42A959953C45, +430E67734C18, +4314D9D03B95, +43166BCA83EB, +43400A093A7E, +434CE764DE91, +43595AC786EE, +438099331C1E, +43814087A7B5, +438C3CD95B58, +43B3E895B281, +44074C461042, +444D37149B20, +44A04DAA30CB, +4537282554C5, +4584EACB6087, +45DB3799C150, +45E599AE38EA, +462305611C4A, +4636195CDA2D, +46752993E2E9, +4684316440D6, +46C7246C1958, +4751A5274848, +4761E34CB054, +476388408D8E, +478947735B45, +47AD81972D5B, +47C23398EA52, +47E9D4D4BE35, +4812AEC4B01A, +48276645A4EA, +48644467A214, +489C783B3514, +48C860AA4B74, +495C6639575B, +49681C20A00D, +49E8249DD677, +49E93C110AA1, +4A24470C19C5, +4A4755BC4A2A, +4A4D5E3A9011, +4A65D627625C, +4A6B36C5BCCC, +4AB725ED89B5, +4B39E3923D0D, +4B59316C10E0, +4C275C8BB2DA, +4C2E9455D296, +4C44DB1D0C3A, +4C67059B0006, +4CA30E1A298A, +4CA74DAC7C01, +4CB212D72D57, +4CD3B228EBB4, +4CE1972E090C, +4CEE1794E0EA, +4D06DBCA167E, +4D2CC85EB338, +4D40BC7A44DB, +4D769DA515D3, +4D79C95DAD2D, +4DBAC8ECE167, +4E3CB839E87D, +4E3D548E1267, +4E8250E29617, +4E94C7962769, +5038884E4178, +505B5A8EB20A, +50642C36DA00, +5083664D8C09, +50B77DA96DE2, +511E269A9BAE, +51798AEAAE9E, +51ED5833AB6D, +525335E4CD34, +5261CDDA279E, +526E55542A54, +529C16A720AB, +52A230B1C50E, +52AADA374811, +52D20D6E3E35, +534BB4A6984E, +5352CCC3DCD2, +540B15E8019D, +54AA2915E815, +558DB8891A90, +55A691710B48, +55D1E91B1D35, +55D95774E9A0, +563C6B96D59D, +567032E13B54, +56741B108D22, +57029D991123, +5714E9D33034, +5734CD8A65DA, +5785EE00049E, +57B8B111491D, +57CC9D0AA32B, +57D7D4D746DA, +583C936DCB4B, +586B470A43B3, +5876E1D34183, +58B6AE62DB88, +58C35C8BC9AB, +597E98000ED4, +59DB4DBB5D7A, +5A150653E624, +5A211CE57C4B, +5A6272CDBE9C, +5ACB8043C10C, +5B41CEBC2213, +5B59BCC4321E, +5BA03479BB8C, +5BC64C42281C, +5C9B1A8E31CD, +5C9BD0AC1DB1, +5D223E990AD8, +5D8C3A5C5761, +5DA57EACA38C, +5E41DD5D1154, +5E6ABB51EC75, +5E7CC04C3A58, +5E810C48C8D8, +5E8943D9A836, +5ED616273468, +60100DD0E023, +6033A1C0E431, +6088A566CC60, +60B20ADA0471, +60B8411D876E, +60C742D8D9C0, +6135433CC5EA, +6153ADD80A15, +61718ED2C94D, +6175241B035A, +61780BCB0C57, +61B701698050, +61C4E56629A3, +61D59C284952, +61E57B490A55, +622E5E0812D7, +6251CE7E547A, +62953A89B137, +62D6EAA06CD6, +630228659A47, +632931BE8EC7, +63539BB89DEE, +636CB69BB10C, +63783393E20D, +639DB16995B7, +63AA2A5B076C, +63B636458E94, +6443E64DCC4B, +64695084C575, +6493D06D5710, +649B302A97C5, +64B8632B54D4, +654BACB21C3B, +65A3D5823819, +65DEDABD1B34, +6608944EE186, +665B8B24C20D, +6685D0BE19E0, +66933A9E7982, +674C7BB59A16, +675E35EE359E, +67AA98E362C9, +67D47C1B6425, +67DE22850162, +67E8B986B2A7, +681EA28BA6CD, +6828B52B6507, +6874E54471E8, +6879B1CA44A3, +68C00A810D41, +68C9E8AA5C3E, +697A8ED07418, +69B5357A617A, +6A7B3A7B6735, +6AA40421D23C, +6AB676B4DB9D, +6B00420BE41C, +6B0B7B967871, +6B9D041136B4, +6BB1A14768A8, +6BCAE24D9700, +6C0458728774, +6C57CBD51995, +6C5E10B86CDE, +6CA491A8C7B8, +6CBC25C1DA2E, +6CD430D99958, +6CEC27647CC0, +6D4D29CEB9B5, +6D6E9A6B725D, +6D801AC74572, +6D97408C6D60, +6DDE6E871C64, +6DEA848B6195, +6E05B5C44A54, +6E751666AE9A, +6E7DBCDA05B3, +7004BA1763ED, +7016ECD01559, +7076D48D5E49, +7091621EA016, +709311997549, +70984C14D3DB, +70D73BE22CDD, +70D9461C5E90, +712BC18422CB, +712E6CAA74A4, +7164042BA89E, +7175E14A4D62, +718B39561350, +718BDA352E28, +719B1418323E, +71A8D54D82B3, +71DC30168C27, +7221E016597B, +7234CC6BD65D, +727A80DD5296, +72B393D6E8A9, +732C9BE4DDBA, +736B4A835B2B, +73EA81968900, +740AB5126199, +741A31054E6B, +74498C1D4B3D, +745276053CB6, +74684B0B4B1D, +74772915E24C, +74A24BE33BE2, +74A778236D5A, +74AA58008A31, +74C27A96CB3A, +754AD5773746, +756C15E54212, +759403A563D8, +759D2130312B, +75A0E10D8C84, +75A807E46B96, +75E454785C6C, +76078A25C088, +76140285B768, +763D835BD5ED, +767C33468C72, +76962C07EC9E, +76984E62CCE4, +769AE4646931, +76E5DA67A1EC, +7708D5CAD58B, +77383BAA4D90, +7789E646A556, +779A248E098C, +77DB71037644, +77E0A57DD456, +7853D464E2A4, +78EA6EB04463, +7909427EC8B9, +7910A31ECD19, +79271963B6E8, +793D98517D33, +79B7A4C58DE0, +79B9148761B3, +7A2893B75AD1, +7A4C61A1B48D, +7A7469B69C6A, +7AA84B1A527D, +7B00211CA416, +7B118EABC7BB, +7B1D9A2E22AA, +7B583D350740, +7B9D3A6BD061, +7C2DAC2CC775, +7C4CBBD2DDE1, +7CD52B5B8E77, +7D412100532B, +7D46C149DAD9, +7D4CA630E229, +7DAC0E83D335, +7DC935E220A0, +7DCA66BACA13, +7E30778792D2, +7E43C3BAB3CB, +7E475BA186E6, +7EE2A624851A, +80CED5362B2C, +80D2CC78E10B, +80D62251E20C, +816875D55ED1, +81950D0517AC, +81B519418C3E, +8211571B9D16, +823C7CC6E06A, +826DD63B9032, +827303C574B5, +82C5ADED4B81, +82E344329D34, +83588E140165, +835D33B48113, +8384148AE52D, +8394B57153D6, +83A0184757C0, +83D86835B48B, +8502EE9A7E85, +852C2B72659D, +8534A6CE0911, +85ABD94CD7A9, +85DA8099CD7E, +85E0B6B26945, +864CA2A6BE93, +868A33A44447, +86EDEABCC357, +87DDD5A188EE, +8830379B50B7, +883803A3360C, +883DA78EC87D, +88482A12C2C6, +888EBD3DB945, +88D026793359, +88DD4B7C5991, +8931DC3733D4, +894D8E2DCDEE, +897B845C2680, +89B638BD909E, +89D2C28BE578, +8A1869848D1A, +8A39D09508C9, +8ACCC7290C8C, +8AD8B41EC218, +8B028B7E6D60, +8B6A95C7D2E2, +8BA1226EBA21, +8BD586B21ABC, +8C0EA504B635, +8CA939DC6DE4, +8CAE5D688443, +8CEC639E64DC, +8DECE0DD29DE, +8E0EC762E883, +8E958D8B8C52, +8EB64D710C88, +8ED4A17717D9, +8EE9D9C03A0D, +9014E1430AEB, +90965DEBC8B9, +90E56E616DDD, +912CD8E04437, +912E33563E1B, +918048032247, +919402EC39CB, +91D28E2B126D, +9216EEE5B677, +9232215296B2, +925A070E9096, +925A5521D48D, +92CC200886A2, +932035869655, +937144459949, +93B260DBC70A, +94552B863E37, +95327A0A3600, +954275CDD7E0, +957E6EE3EB55, +95B920CACC84, +96382E1C8E12, +964E8E5338BD, +96706C8D6ECC, +96759A0D5566, +96D5213C5DDB, +97300764797A, +973BDDBE7434, +974838AE17A0, +9752A6B316D5, +97926543783B, +97EB373096CA, +982D6054B83D, +989D127BD496, +98A54AD58A43, +98A92128364C, +98CD5AA2A4DB, +98E8C543688E, +99207A00AA4A, +99243E754CB8, +9925893ABAC7, +9937553A965E, +9976E6ADE0C9, +9982E3E6A4A0, +9984C1A3229E, +99C487AB85EC, +99E2A19C9673, +9A05EBE41D7D, +9A138D1A5CB7, +9A179148B824, +9A6EC0A9ECB8, +9A720CBD7BB1, +9AB22BBDDD87, +9AC43B5A06D8, +9AD8150BE648, +9AD97423190D, +9B4ADDDEB749, +9B7603341727, +9C45237377BE, +9D090AE1A15E, +9D59641E40A5, +9DA4528CEB8C, +9DA728164176, +9DAC62A346B7, +9E0E9D983B9A, +9E5271763D3D, +9EE95586D024, +9EEE39E00CBB, +A04671256EE2, +A091485B4B5D, +A1B5577ED36E, +A1EB280E3901, +A2789E1DD888, +A293A90AE72C, +A309E3AEBDB9, +A3196E77B072, +A31E72DCC826, +A34DEA01690E, +A36031D6ECB2, +A38044A3E18E, +A421D7A04C4B, +A424C686CA39, +A44590A779A5, +A47AD3895C63, +A5041E8B8E22, +A50DC0830AA5, +A52B8929D665, +A5BCBA6BE592, +A61D5137E6B3, +A6344C0418DC, +A690A817B9D9, +A7E3B3459240, +A81E6D3C8E11, +A8C0BE436685, +A8DE205120A8, +A91E2BE6C308, +A9258D6B06B5, +A992B5E070C1, +AAC6E3205D48, +AB101546634E, +AB6EE0761ACA, +AB9BCA200547, +AC4BC5B2D3C0, +AC7A0B47B03E, +AC88B26AC1D0, +ACAEB3456AD9, +ACB906631D8A, +ACE07B45C0C5, +AD1992AE37CA, +AD5586744A60, +AD674E4ADB79, +ADA093B06831, +AE7C3AE5334A, +AE9EB8CAB2C3, +AEAE9E5CE65D, +B002D1BDC29B, +B0463E703098, +B063B209BB20, +B0788BE3BAA4, +B0C3B3299090, +B128298D9073, +B160677E7035, +B19D3D57176A, +B1CCDB7999B9, +B231AA398B90, +B250E9590215, +B28BE0D819ED, +B292C9554CBA, +B2D8485C2460, +B31763D9D0DE, +B328014DDD6A, +B378C424C9E2, +B3D8C03C78E0, +B41D18E3B980, +B46824B972E9, +B50383A32302, +B509D631967C, +B56CA847A7C3, +B56EC9A20D28, +B5B763215C82, +B6550EAC573A, +B66060201705, +B6614EBEAAA2, +B6A18CBD4DA6, +B6ABB62E437E, +B6C6558E58CA, +B7009204D512, +B71D5B22B1C2, +B7392DD1E497, +B7709ED7CE60, +B7A26320A491, +B7A9DA22E9C6, +B7DEC863369D, +B7E9A91174CB, +B8178A34E2DC, +B83092098A7D, +B84C50E56DEC, +B89BD135E935, +B8E87380D361, +B9485A9648C6, +B9ED829C22AE, +BA227EE91818, +BA7BBD9683B1, +BA8224EA7A80, +BA84C974B356, +BAD293A45C8A, +BB850C7E4934, +BBC1256810A4, +BC1CD369549E, +BC5C76E5909C, +BC66E9270049, +BC6AB08B03CC, +BC74CA2C2B06, +BC7C64828C1D, +BCCC3A719013, +BD06E96EB7D7, +BD196D0A74E0, +BE02790E84AC, +BE1266314B9D, +BE518C742B74, +BE5695316117, +BE5D8EBA120D, +BE8286DA7D12, +BE9CE00EE4DD, +C003962B3462, +C0067E095049, +C015A21E0146, +C03BC03AD437, +C06CE7D57A0D, +C07EE1E10B56, +C0885A29251E, +C198163ABECE, +C1EB7337A035, +C225479C7064, +C2740E1665A8, +C27924128A00, +C2A701656B8B, +C2C30D21C53E, +C2CBB2ACD38D, +C38D19A9C8D1, +C3B1BB7E7492, +C3BA2438A981, +C3CD74758DE2, +C4033B3BB1D7, +C404D280640E, +C4467DE80B2D, +C46A048C88DD, +C52877867C05, +C56D005E258E, +C56D052D5533, +C5BB2CCCB9C3, +C5C272694A1E, +C6121BC4A29C, +C65EEAE02433, +C661C4AE1DD1, +C76C94B495CA, +C7BD49777A79, +C7CD131E9B60, +C7E35D6294BA, +C8E173DB04CC, +C95855AE08E8, +C98147E69033, +C99A004E6133, +C9E893C4090B, +CA119C79A197, +CA309D2CBC41, +CA4BAA390BC4, +CA92DD257E21, +CA968EBEB9C7, +CADED0C50AC4, +CB18774EA550, +CB1999D19E10, +CB75C1BAE669, +CC2517AB2346, +CC2AC1AD29CA, +CD11359C7A90, +CD14C8553CB9, +CD333295BBE2, +CD3DB8C27E5C, +CDA811AD5055, +CDABDCA23986, +CDCA8BD7B002, +CE0456AB0DCE, +CE58AE1C51E9, +CE76E8A600DC, +CE95875316C8, +CEB105E65289, +CEB651752D4C, +CEE02D97E5BD, +D023DB35ED05, +D0BE546CC06B, +D0CE7EB0D379, +D10329D366C8, +D15C004DBC8D, +D16E6B668254, +D1CEEC977644, +D1DC0E1CC09E, +D2550925679B, +D28B2D42DE1A, +D2926519AC09, +D313116A45B4, +D3DC10453857, +D431C8C73BDC, +D4C67846791C, +D5629384CE7D, +D5ABE7180600, +D62A4A0E57C2, +D660CE9E3080, +D66AE9282140, +D6A91C14AC47, +D6E23B4E75C6, +D726C4979654, +D76DE12943B4, +D7A405AD9E4E, +D7BD3AE48E93, +D7D49700BBCC, +D7E8A5089E7A, +D84C81EE910D, +D8545199A949, +D86243C1380E, +D88A12EB3622, +D89B5EA419C1, +D8A3690B0115, +D94646A4C65B, +D982B4846A96, +DA303BADB013, +DAD9A48A8C33, +DAEB5D63920B, +DB01A99DD94C, +DB22BB7D6818, +DB37160CBB4B, +DB7E3687E450, +DC7697E37A9B, +DCC44C4E9269, +DCCE477E785E, +DD68DE9CDA5A, +DE1B08C6D94B, +DE41BBD7E68D, +DE6E04AE4475, +DE8CD4277A9E, +DEA8098D6E51, +DEB2BEE8858A, +DEB550958AD9, +E045E6309471, +E0E21213C611, +E0E457054B62, +E1097C69DA4A, +E1EA831EA514, +E20716902884, +E2C9CB14C06C, +E33B66EA2705, +E34C5B12BABA, +E38A1C654E82, +E3905BA54194, +E3E3919444CA, +E4450EC1010C, +E49A03306224, +E5100AC4C6C3, +E5124DB665A6, +E5491B5E3DD6, +E5BE9C989A29, +E5C3A9A27D3E, +E65111EB1E40, +E65792427D4C, +E7004C5EA94A, +E705087DECBB, +E7CB93E68155, +E81512343BAD, +E8428C8B0740, +E859EBC22318, +E87267A508DB, +E886AE7D1BE0, +E8B008239600, +E8C4B4A4E482, +E8D53410B736, +E902964DA28D, +E9203D5BD2DA, +E9526CACA8B2, +E9C11D763BEC, +EA3BDAA4E498, +EA61AC8B4969, +EA8E8ADC26B9, +EB5588EAE5E8, +EBA964C07075, +EC71B679D3AA, +ECB4019ADD97, +ED14D0A14B0C, +ED296C79266C, +EDBA3C943EA8, +EDC7CEBD4000, +EDE2747DA6C3, +EE3029556CEB, +EE49610E6121, +EEB704D69BCA, +EED69A391464, diff --git a/client/dictionaries/mrzd_sort_keys.dic b/client/dictionaries/mrzd_sort_keys.dic new file mode 100644 index 000000000..025f1b995 --- /dev/null +++ b/client/dictionaries/mrzd_sort_keys.dic @@ -0,0 +1,57 @@ +010203040506, +013940233313, +022FE48B3072, +123456789ABC, +123456ABCDEF, +17505586EF02, +1795902DBAF9, +1A2B3C4D5E6F, +1A982C7E459A, +200306202033, +2011092119F1, +2012053082AD, +37D4DCA92451, +40E5EA1EFC00, +435330666666, +46868F6D5677, +474249437569, +4D3A99C351DD, +533CB6C723F6, +5554AAA96321, +587EE5F9350F, +5A1B85FCE20A, +5D293AFC8D7E, +64A2EE93B12B, +64E2283FCF5E, +714C5C886E97, +833FBD3CFE51, +83BAB5ACAD62, +872B71F9D15A, +8F9B229047AC, +8FD0A4F256E9, +9AEDF9931EC1, +9B1DD7C030A1, +A0478CC39091, +A0A1A2A3A4A5, +A2B2C9D187FB, +A4EF6C3BB692, +AABBCC660429, +AABBCCDDEEFF, +ABCDEF123456, +B0699AD03D17, +B0B1B2B3B4B5, +BA28CFD15EE8, +BCFE01BCFE01, +C0C1C2C3C4C5, +CFC738403AB0, +D0D1D2D3D4D5, +D3F7D3F7D3F7, +DB5181C92CBE, +DFED39FFBB76, +E1DD284379D4, +E96246531342, +ED3A7EFBFF56, +F83466888612, +F89C86B2A961, +FFFFAE82366C, +FFFFD06F83E3, From bccdde01236498fa19b4b82e15b5a1a80dc6d6cb Mon Sep 17 00:00:00 2001 From: RFID Research Group Date: Thu, 24 Jan 2019 11:49:04 +0100 Subject: [PATCH 0444/1938] Update issue templates --- .github/ISSUE_TEMPLATE/bug_report.md | 3 +++ .github/ISSUE_TEMPLATE/feature_request.md | 20 ++++++++++++++++++++ 2 files changed, 23 insertions(+) create mode 100644 .github/ISSUE_TEMPLATE/feature_request.md diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md index 3b04ea5f8..940722506 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.md +++ b/.github/ISSUE_TEMPLATE/bug_report.md @@ -1,6 +1,9 @@ --- name: Bug report about: Create a report to help us improve +title: '' +labels: '' +assignees: '' --- diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md new file mode 100644 index 000000000..ff12e62f1 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/feature_request.md @@ -0,0 +1,20 @@ +--- +name: Feature request +about: Suggest an idea for this project +title: "[idea]" +labels: Request, enhancement +assignees: '' + +--- + +**Is your feature request related to a problem? Please describe.** +A clear and concise description of what the problem is. Ex. I'm always frustrated when [...] + +**Describe the solution you'd like** +A clear and concise description of what you want to happen. + +**Describe alternatives you've considered** +A clear and concise description of any alternative solutions or features you've considered. + +**Additional context** +Add any other context or screenshots about the feature request here. From 4fe4d74bfe99dbcb57d98fa93805d7acb0c7f61e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jan 2019 11:42:52 +0100 Subject: [PATCH 0445/1938] FIX: 'emv roca' - not executing when client is compiled without WITH_SMARTCARD functionality, like for old devices see https://github.com/RfidResearchGroup/proxmark3/issues/85 --- client/emv/cmdemv.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 91a3663f3..453d08a20 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1599,6 +1599,14 @@ int CmdEMVRoca(const char *cmd) { if (arg_get_lit(2)) channel = ECC_CONTACT; PrintChannel(channel); + +#ifndef WITH_SMARTCARD + // not compiled with smartcard functionality, we need to exit + if ( channel == ECC_CONTACT ) { + PrintAndLogEx(WARNING, "PM3 Client is not compiled with support for SMARTCARD. Exiting."); + return 0; + } +#endif // select card uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; From 803aab74311d5c61c00247c2268b2a410d79e218 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jan 2019 11:58:00 +0100 Subject: [PATCH 0446/1938] FIX: 'hf legic sim' - longer timeout for writes? (@drandreas) see https://github.com/RfidResearchGroup/proxmark3/issues/83 --- armsrc/legicrf.c | 62 ++++++++++++++++++++++----------------------- armsrc/legicrfsim.c | 2 +- 2 files changed, 32 insertions(+), 32 deletions(-) diff --git a/armsrc/legicrf.c b/armsrc/legicrf.c index 00d284926..958d3421a 100644 --- a/armsrc/legicrf.c +++ b/armsrc/legicrf.c @@ -61,7 +61,7 @@ static inline uint8_t rx_byte_from_fpga() { WDT_HIT(); // wait for byte be become available in rx holding register - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { return AT91C_BASE_SSC->SSC_RHR; } } @@ -81,7 +81,7 @@ static inline uint8_t rx_byte_from_fpga() { // To reduce CPU time the amplitude is approximated by using linear functions: // am = MAX(ABS(i),ABS(q)) + 1/2*MIN(ABS(i),ABSq)) // -// Note: The SSC receiver is never synchronized the calculation my be performed +// Note: The SSC receiver is never synchronized the calculation may be performed // on a i/q pair from two subsequent correlations, but does not matter. static inline int32_t sample_power() { int32_t q = (int8_t)rx_byte_from_fpga(); q = ABS(q); @@ -100,7 +100,7 @@ static inline int32_t sample_power() { static inline bool rx_bit() { int32_t power; - for(size_t i = 0; i<5; ++i) { + for (size_t i = 0; i<5; ++i) { power = sample_power(); } @@ -120,12 +120,12 @@ static inline void tx_bit(bool bit) { // insert pause LOW(GPIO_SSC_DOUT); last_frame_end += RWD_TIME_PAUSE; - while(GET_TICKS < last_frame_end) { }; + while (GET_TICKS < last_frame_end) { }; HIGH(GPIO_SSC_DOUT); // return to high, wait for bit periode to end last_frame_end += (bit ? RWD_TIME_1 : RWD_TIME_0) - RWD_TIME_PAUSE; - while(GET_TICKS < last_frame_end) { }; + while (GET_TICKS < last_frame_end) { }; } //----------------------------------------------------------------------------- @@ -143,13 +143,13 @@ static void tx_frame(uint32_t frame, uint8_t len) { // wait for next tx timeslot last_frame_end += RWD_FRAME_WAIT; - while(GET_TICKS < last_frame_end) { }; + while (GET_TICKS < last_frame_end) { }; // backup ts for trace log uint32_t last_frame_start = last_frame_end; // transmit frame, MSB first - for(uint8_t i = 0; i < len; ++i) { + for (uint8_t i = 0; i < len; ++i) { bool bit = (frame >> i) & 0x01; tx_bit(bit ^ legic_prng_get_bit()); legic_prng_forward(1); @@ -158,7 +158,7 @@ static void tx_frame(uint32_t frame, uint8_t len) { // add pause to mark end of the frame LOW(GPIO_SSC_DOUT); last_frame_end += RWD_TIME_PAUSE; - while(GET_TICKS < last_frame_end) { }; + while (GET_TICKS < last_frame_end) { }; HIGH(GPIO_SSC_DOUT); // log @@ -173,19 +173,19 @@ static uint32_t rx_frame(uint8_t len) { // hold sampling until card is expected to respond last_frame_end += TAG_FRAME_WAIT; - while(GET_TICKS < last_frame_end) { }; + while (GET_TICKS < last_frame_end) { }; // backup ts for trace log uint32_t last_frame_start = last_frame_end; uint32_t frame = 0; - for(uint8_t i = 0; i < len; ++i) { + for (uint8_t i = 0; i < len; ++i) { frame |= (rx_bit() ^ legic_prng_get_bit()) << i; legic_prng_forward(1); // rx_bit runs only 95us, resync to TAG_BIT_PERIOD last_frame_end += TAG_BIT_PERIOD; - while(GET_TICKS < last_frame_end) { }; + while (GET_TICKS < last_frame_end) { }; } // log @@ -203,23 +203,23 @@ static bool rx_ack() { // hold sampling until card is expected to respond last_frame_end += TAG_FRAME_WAIT; - while(GET_TICKS < last_frame_end) { }; + while (GET_TICKS < last_frame_end) { }; // backup ts for trace log uint32_t last_frame_start = last_frame_end; uint32_t ack = 0; - for(uint8_t i = 0; i < TAG_WRITE_TIMEOUT; ++i) { + for (uint8_t i = 0; i < TAG_WRITE_TIMEOUT; ++i) { // sample bit ack = rx_bit(); legic_prng_forward(1); // rx_bit runs only 95us, resync to TAG_BIT_PERIOD last_frame_end += TAG_BIT_PERIOD; - while(GET_TICKS < last_frame_end) { }; + while (GET_TICKS < last_frame_end) { }; // check if it was an ACK - if(ack) { + if (ack) { break; } } @@ -282,7 +282,7 @@ static void init_reader(bool clear_mem) { // reserve a cardmem, meaning we can use the tracelog function in bigbuff easier. legic_mem = BigBuf_get_EM_addr(); - if(legic_mem) { + if (legic_mem) { memset(legic_mem, 0x00, LEGIC_CARD_MEMSIZE); } @@ -309,7 +309,7 @@ static uint32_t setup_phase(uint8_t iv) { // Switch on carrier and let the card charge for 5ms. last_frame_end += 7500; - while(GET_TICKS < last_frame_end) { }; + while (GET_TICKS < last_frame_end) { }; legic_prng_init(0); tx_frame(iv, 7); @@ -359,7 +359,7 @@ static int16_t read_byte(uint16_t index, uint8_t cmd_sz) { // check received against calculated crc uint8_t calc_crc = calc_crc4(cmd, cmd_sz, byte); - if(calc_crc != crc) { + if (calc_crc != crc) { Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc); return -1; } @@ -399,15 +399,15 @@ void LegicRfInfo(void) { // establish shared secret and detect card type uint8_t card_type = setup_phase(0x01); - if(init_card(card_type, &card) != 0) { + if (init_card(card_type, &card) != 0) { cmd_send(CMD_ACK, 0, 0, 0, 0, 0); goto OUT; } // read UID - for(uint8_t i = 0; i < sizeof(card.uid); ++i) { + for (uint8_t i = 0; i < sizeof(card.uid); ++i) { int16_t byte = read_byte(i, card.cmdsize); - if(byte == -1) { + if (byte == -1) { cmd_send(CMD_ACK, 0, 0, 0, 0, 0); goto OUT; } @@ -417,7 +417,7 @@ void LegicRfInfo(void) { // read MCC and check against UID int16_t mcc = read_byte(4, card.cmdsize); int16_t calc_mcc = CRC8Legic(card.uid, 4);; - if(mcc != calc_mcc) { + if (mcc != calc_mcc) { cmd_send(CMD_ACK, 0, 0, 0, 0, 0); goto OUT; } @@ -436,19 +436,19 @@ void LegicRfReader(uint16_t offset, uint16_t len, uint8_t iv) { // establish shared secret and detect card type uint8_t card_type = setup_phase(iv); - if(init_card(card_type, &card) != 0) { + if (init_card(card_type, &card) != 0) { cmd_send(CMD_ACK, 0, 0, 0, 0, 0); goto OUT; } // do not read beyond card memory - if(len + offset > card.cardsize) { + if (len + offset > card.cardsize) { len = card.cardsize - offset; } - for(uint16_t i = 0; i < len; ++i) { + for (uint16_t i = 0; i < len; ++i) { int16_t byte = read_byte(offset + i, card.cmdsize); - if(byte == -1) { + if (byte == -1) { cmd_send(CMD_ACK, 0, 0, 0, 0, 0); goto OUT; } @@ -468,26 +468,26 @@ void LegicRfWriter(uint16_t offset, uint16_t len, uint8_t iv, uint8_t *data) { init_reader(false); // uid is not writeable - if(offset <= WRITE_LOWERLIMIT) { + if (offset <= WRITE_LOWERLIMIT) { cmd_send(CMD_ACK, 0, 0, 0, 0, 0); goto OUT; } // establish shared secret and detect card type uint8_t card_type = setup_phase(iv); - if(init_card(card_type, &card) != 0) { + if (init_card(card_type, &card) != 0) { cmd_send(CMD_ACK, 0, 0, 0, 0, 0); goto OUT; } // do not write beyond card memory - if(len + offset > card.cardsize) { + if (len + offset > card.cardsize) { len = card.cardsize - offset; } // write in reverse order, only then is DCF (decremental field) writable - while(len-- > 0 && !BUTTON_PRESS()) { - if(!write_byte(len + offset, data[len], card.addrsize)) { + while (len-- > 0 && !BUTTON_PRESS()) { + if (!write_byte(len + offset, data[len], card.addrsize)) { Dbprintf("operation failed | %02X | %02X | %02X", len + offset, len, data[len]); cmd_send(CMD_ACK, 0, 0, 0, 0, 0); goto OUT; diff --git a/armsrc/legicrfsim.c b/armsrc/legicrfsim.c index 1816a29ca..d51747555 100644 --- a/armsrc/legicrfsim.c +++ b/armsrc/legicrfsim.c @@ -46,7 +46,7 @@ static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */ #define RWD_TIME_PAUSE 4 /* 18.9us */ #define RWD_TIME_1 21 /* RWD_TIME_PAUSE 18.9us off + 80.2us on = 99.1us */ #define RWD_TIME_0 13 /* RWD_TIME_PAUSE 18.9us off + 42.4us on = 61.3us */ -#define RWD_CMD_TIMEOUT 40 /* 40 * 99.1us (arbitrary value) */ +#define RWD_CMD_TIMEOUT 80 /* 80 * 99.1us (arbitrary value) */ #define RWD_MIN_FRAME_LEN 6 /* Shortest frame is 6 bits */ #define RWD_MAX_FRAME_LEN 23 /* Longest frame is 23 bits */ From 730a7e8044bb08c4df93b7b80d429581864130a3 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 25 Jan 2019 13:48:53 +0100 Subject: [PATCH 0447/1938] FIX: 'hf legic sim' - needed even more timeout. see https://github.com/RfidResearchGroup/proxmark3/issues/83 --- armsrc/legicrfsim.c | 61 ++++++++++++++++++++++----------------------- 1 file changed, 30 insertions(+), 31 deletions(-) diff --git a/armsrc/legicrfsim.c b/armsrc/legicrfsim.c index d51747555..86448275f 100644 --- a/armsrc/legicrfsim.c +++ b/armsrc/legicrfsim.c @@ -46,7 +46,7 @@ static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */ #define RWD_TIME_PAUSE 4 /* 18.9us */ #define RWD_TIME_1 21 /* RWD_TIME_PAUSE 18.9us off + 80.2us on = 99.1us */ #define RWD_TIME_0 13 /* RWD_TIME_PAUSE 18.9us off + 42.4us on = 61.3us */ -#define RWD_CMD_TIMEOUT 80 /* 80 * 99.1us (arbitrary value) */ +#define RWD_CMD_TIMEOUT 120 /* 120 * 99.1us (arbitrary value) */ #define RWD_MIN_FRAME_LEN 6 /* Shortest frame is 6 bits */ #define RWD_MAX_FRAME_LEN 23 /* Longest frame is 23 bits */ @@ -59,8 +59,8 @@ static uint32_t last_frame_end; /* ts of last bit of previews rx or tx frame */ // Returns true if a pulse/pause is received within timeout static inline bool wait_for(bool value, const uint32_t timeout) { - while((bool)(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN) != value) { - if(GetCountSspClk() > timeout) { + while ((bool)(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_DIN) != value) { + if (GetCountSspClk() > timeout) { return false; } } @@ -81,12 +81,12 @@ static inline int8_t rx_bit() { uint32_t bit_start = last_frame_end; // wait for pause to end - if(!wait_for(RWD_PULSE, bit_start + RWD_TIME_1*3/2)) { + if (!wait_for(RWD_PULSE, bit_start + RWD_TIME_1*3/2)) { return -1; } // wait for next pause - if(!wait_for(RWD_PAUSE, bit_start + RWD_TIME_1*3/2)) { + if (!wait_for(RWD_PAUSE, bit_start + RWD_TIME_1*3/2)) { return -1; } @@ -94,7 +94,7 @@ static inline int8_t rx_bit() { last_frame_end = GetCountSspClk(); // check for code violation (bit to short) - if(last_frame_end - bit_start < RWD_TIME_PAUSE) { + if (last_frame_end - bit_start < RWD_TIME_PAUSE) { return -1; } @@ -122,7 +122,7 @@ static inline int8_t rx_bit() { static inline void tx_bit(bool bit) { LED_C_ON(); - if(bit) { + if (bit) { // modulate subcarrier HIGH(GPIO_SSC_DOUT); } else { @@ -132,7 +132,7 @@ static inline void tx_bit(bool bit) { // wait for tx timeslot to end last_frame_end += TAG_BIT_PERIOD; - while(GetCountSspClk() < last_frame_end) { }; + while (GetCountSspClk() < last_frame_end) { }; LED_C_OFF(); } @@ -150,13 +150,13 @@ static void tx_frame(uint32_t frame, uint8_t len) { // wait for next tx timeslot last_frame_end += TAG_FRAME_WAIT; legic_prng_forward(TAG_FRAME_WAIT/TAG_BIT_PERIOD - 1); - while(GetCountSspClk() < last_frame_end) { }; + while (GetCountSspClk() < last_frame_end) { }; // backup ts for trace log uint32_t last_frame_start = last_frame_end; // transmit frame, MSB first - for(uint8_t i = 0; i < len; ++i) { + for (uint8_t i = 0; i < len; ++i) { bool bit = (frame >> i) & 0x01; tx_bit(bit ^ legic_prng_get_bit()); legic_prng_forward(1); @@ -174,7 +174,7 @@ static void tx_ack() { // wait for ack timeslot last_frame_end += TAG_ACK_WAIT; legic_prng_forward(TAG_ACK_WAIT/TAG_BIT_PERIOD - 1); - while(GetCountSspClk() < last_frame_end) { }; + while (GetCountSspClk() < last_frame_end) { }; // backup ts for trace log uint32_t last_frame_start = last_frame_end; @@ -206,19 +206,19 @@ static int32_t rx_frame(uint8_t *len) { last_frame_end -= 2; // wait for first pause (start of frame) - for(uint8_t i = 0; true; ++i) { + for (uint8_t i = 0; true; ++i) { // increment prng every TAG_BIT_PERIOD last_frame_end += TAG_BIT_PERIOD; legic_prng_forward(1); // if start of frame was received exit delay loop - if(wait_for(RWD_PAUSE, last_frame_end)) { + if (wait_for(RWD_PAUSE, last_frame_end)) { last_frame_end = GetCountSspClk(); break; } // check for code violation - if(i > RWD_CMD_TIMEOUT) { + if (i > RWD_CMD_TIMEOUT) { return -1; } } @@ -227,19 +227,19 @@ static int32_t rx_frame(uint8_t *len) { uint32_t last_frame_start = last_frame_end; // receive frame - for(*len = 0; true; ++(*len)) { + for (*len = 0; true; ++(*len)) { // receive next bit LED_B_ON(); int8_t bit = rx_bit(); LED_B_OFF(); // check for code violation and to short / long frame - if((bit < 0) && ((*len < RWD_MIN_FRAME_LEN) || (*len > RWD_MAX_FRAME_LEN))) { + if ((bit < 0) && ((*len < RWD_MIN_FRAME_LEN) || (*len > RWD_MAX_FRAME_LEN))) { return -1; } // check for code violation caused by end of frame - if(bit < 0) { + if (bit < 0) { break; } @@ -256,7 +256,6 @@ static int32_t rx_frame(uint8_t *len) { // log uint8_t cmdbytes[] = {*len, BYTEx(frame, 0), BYTEx(frame, 1), BYTEx(frame, 2)}; LogTrace(cmdbytes, sizeof(cmdbytes), last_frame_start, last_frame_end, NULL, true); - return frame; } @@ -267,7 +266,7 @@ static int32_t rx_frame(uint8_t *len) { static int32_t init_card(uint8_t cardtype, legic_card_select_t *p_card) { p_card->tagtype = cardtype; - switch(p_card->tagtype) { + switch (p_card->tagtype) { case 0: p_card->cmdsize = 6; p_card->addrsize = 5; @@ -338,7 +337,7 @@ static int32_t setup_phase(legic_card_select_t *p_card) { // wait for iv int32_t iv = rx_frame(&len); - if((len != 7) || (iv < 0)) { + if ((len != 7) || (iv < 0)) { return -1; } @@ -346,7 +345,7 @@ static int32_t setup_phase(legic_card_select_t *p_card) { legic_prng_init(iv); // reply with card type - switch(p_card->tagtype) { + switch (p_card->tagtype) { case 0: tx_frame(0x0D, 6); break; @@ -360,12 +359,12 @@ static int32_t setup_phase(legic_card_select_t *p_card) { // wait for ack int32_t ack = rx_frame(&len); - if((len != 6) || (ack < 0)) { + if ((len != 6) || (ack < 0)) { return -1; } // validate data - switch(p_card->tagtype) { + switch (p_card->tagtype) { case 0: if(ack != 0x19) return -1; break; @@ -399,12 +398,12 @@ static int32_t connected_phase(legic_card_select_t *p_card) { // wait for command int32_t cmd = rx_frame(&len); - if(cmd < 0) { + if (cmd < 0) { return -1; } // check if command is LEGIC_READ - if(len == p_card->cmdsize) { + if (len == p_card->cmdsize) { // prepare data uint8_t byte = legic_mem[cmd >> 1]; uint8_t crc = calc_crc4(cmd, p_card->cmdsize, byte); @@ -416,7 +415,7 @@ static int32_t connected_phase(legic_card_select_t *p_card) { } // check if command is LEGIC_WRITE - if(len == p_card->cmdsize + 8 + 4) { + if (len == p_card->cmdsize + 8 + 4) { // decode data uint16_t mask = (1 << p_card->addrsize) - 1; uint16_t addr = (cmd >> 1) & mask; @@ -425,7 +424,7 @@ static int32_t connected_phase(legic_card_select_t *p_card) { // check received against calculated crc uint8_t calc_crc = calc_crc4(addr << 1, p_card->cmdsize, byte); - if(calc_crc != crc) { + if (calc_crc != crc) { Dbprintf("!!! crc mismatch: %x != %x !!!", calc_crc, crc); return -1; } @@ -453,7 +452,7 @@ void LegicRfSimulate(uint8_t cardtype) { init_tag(); // verify command line input - if(init_card(cardtype, &card) != 0) { + if (init_card(cardtype, &card) != 0) { DbpString("Unknown tagtype."); goto OUT; } @@ -464,17 +463,17 @@ void LegicRfSimulate(uint8_t cardtype) { WDT_HIT(); // wait for carrier, restart after timeout - if(!wait_for(RWD_PULSE, GetCountSspClk() + TAG_BIT_PERIOD)) { + if (!wait_for(RWD_PULSE, GetCountSspClk() + TAG_BIT_PERIOD)) { continue; } // wait for connection, restart on error - if(setup_phase(&card)) { + if (setup_phase(&card)) { continue; } // conection is established, process commands until one fails - while(!connected_phase(&card)) { + while (!connected_phase(&card)) { WDT_HIT(); } } From f760ac99e3ed3d0ed9b257a4ae3418ca357bee8b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 26 Jan 2019 10:40:37 +0100 Subject: [PATCH 0448/1938] chg: 'script run ndef_dump' - local functions --- client/scripts/ndef_dump.lua | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/scripts/ndef_dump.lua b/client/scripts/ndef_dump.lua index 3b27cac37..a0eda5b7f 100644 --- a/client/scripts/ndef_dump.lua +++ b/client/scripts/ndef_dump.lua @@ -24,13 +24,13 @@ local example = "script run xxx" local author = "Martin Holst Swende & Asper" --- -- PrintAndLog -function prlog(...) +local function prlog(...) -- TODO; replace this with a call to the proper PrintAndLog print(...) end --- -- This is only meant to be used when errors occur -function oops(err) +local function oops(err) prlog("ERROR: ",err) return nil,err end @@ -70,13 +70,13 @@ local utils = { --- -- Usage help -function help() +local function help() prlog(desc) prlog("Example usage") prlog(example) end -function debug(...) +local function debug(...) if DEBUG then prlog("debug:", ...) end @@ -158,7 +158,7 @@ end --- This function is a lua-implementation of -- cmdhf14a.c:waitCmd(uint8_t iSelect) -function waitCmd(iSelect) +local function waitCmd(iSelect) local response = core.WaitForResponseTimeout(cmds.CMD_ACK,1000) if response then local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response) From f0b70d6a4bafa265db137f2e2bb477f40041178b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 26 Jan 2019 11:09:17 +0100 Subject: [PATCH 0449/1938] CHG: added manufacturers --- client/lualibs/taglib.lua | 185 +++++++++++++++++++++++--------------- 1 file changed, 113 insertions(+), 72 deletions(-) diff --git a/client/lualibs/taglib.lua b/client/lualibs/taglib.lua index f421ab22f..97194714c 100644 --- a/client/lualibs/taglib.lua +++ b/client/lualibs/taglib.lua @@ -1,72 +1,115 @@ -local manufacturer = {} -manufacturer[0x01]='Motorola [UK]' -manufacturer[0x02]='STMicroelectronics SA [France]' -manufacturer[0x03]='Hitachi, Ltd [Japan]' -manufacturer[0x04]='NXP Semiconductors [Germany]' -manufacturer[0x05]='Infineon Technologies AG [Germany]' -manufacturer[0x06]='Cylink [USA]' -manufacturer[0x07]='Texas Instrument [France]' -manufacturer[0x08]='Fujitsu Limited [Japan]' -manufacturer[0x09]='Matsushita Electronics Corporation, Semiconductor Company [Japan]' -manufacturer[0x0A]='NEC [Japan]' -manufacturer[0x0B]='Oki Electric Industry Co. Ltd [Japan]' -manufacturer[0x0C]='Toshiba Corp. [Japan]' -manufacturer[0x0D]='Mitsubishi Electric Corp. [Japan]' -manufacturer[0x0E]='Samsung Electronics Co. Ltd [Korea]' -manufacturer[0x0F]='Hynix [Korea]' -manufacturer[0x10]='LG-Semiconductors Co. Ltd [Korea]' -manufacturer[0x11]='Emosyn-EM Microelectronics [USA]' -manufacturer[0x12]='INSIDE Technology [France]' -manufacturer[0x13]='ORGA Kartensysteme GmbH [Germany]' -manufacturer[0x14]='SHARP Corporation [Japan]' -manufacturer[0x15]='ATMEL [France]' -manufacturer[0x16]='EM Microelectronic-Marin SA [Switzerland]' -manufacturer[0x17]='KSW Microtec GmbH [Germany]' -manufacturer[0x18]='ZMD AG [Germany]' -manufacturer[0x19]='XICOR, Inc. [USA]' -manufacturer[0x1A]='Sony Corporation [Japan]' -manufacturer[0x1B]='Malaysia Microelectronic Solutions Sdn. Bhd [Malaysia]' -manufacturer[0x1C]='Emosyn [USA]' -manufacturer[0x1D]='Shanghai Fudan Microelectronics Co. Ltd. P.R. [China]' -manufacturer[0x1E]='Magellan Technology Pty Limited [Australia]' -manufacturer[0x1F]='Melexis NV BO [Switzerland]' -manufacturer[0x20]='Renesas Technology Corp. [Japan]' -manufacturer[0x21]='TAGSYS [France]' -manufacturer[0x22]='Transcore [USA]' -manufacturer[0x23]='Shanghai belling corp., ltd. [China]' -manufacturer[0x24]='Masktech Germany Gmbh [Germany]' -manufacturer[0x25]='Innovision Research and Technology Plc [UK]' -manufacturer[0x26]='Hitachi ULSI Systems Co., Ltd. [Japan]' -manufacturer[0x27]='Cypak AB [Sweden]' -manufacturer[0x28]='Ricoh [Japan]' -manufacturer[0x29]='ASK [France]' -manufacturer[0x2A]='Unicore Microsystems, LLC [RussianFederation]' -manufacturer[0x2B]='Dallas Semiconductor/Maxim [USA]' -manufacturer[0x2C]='Impinj, Inc. [USA]' -manufacturer[0x2D]='RightPlug Alliance [USA]' -manufacturer[0x2E]='Broadcom Corporation [USA]' -manufacturer[0x2F]='MStar Semiconductor, Inc Taiwan, [ROC]' -manufacturer[0x30]='BeeDar Technology Inc. [USA]' -manufacturer[0x31]='RFIDsec [Denmark]' -manufacturer[0x32]='Schweizer Electronic AG [Germany]' -manufacturer[0x33]='AMIC Technology Corp [Taiwan]' -manufacturer[0x34]='Mikron JSC [Russia]' -manufacturer[0x35]='Fraunhofer Institute for Photonic Microsystems [Germany]' -manufacturer[0x36]='IDS Microchip AG [Switzerland]' -manufacturer[0x37]='Kovio [USA]' -manufacturer[0x38]='HMT Microelectronic Ltd [Switzerland]' -manufacturer[0x39]='Silicon Craft Technology [Thailand]' -manufacturer[0x3A]='Advanced Film Device Inc. [Japan]' -manufacturer[0x3B]='Nitecrest Ltd [UK]' -manufacturer[0x3C]='Verayo Inc. [USA]' -manufacturer[0x3D]='HID Global [USA]' -manufacturer[0x3E]='Productivity Engineering Gmbh [Germany]' -manufacturer[0x3F]='Austriamicrosystems AG (reserved) [Austria]' -manufacturer[0x40]='Gemalto SA [France]' -manufacturer[0x41]='Renesas Electronics Corporation [Japan]' -manufacturer[0x42]='3Alogics Inc [Korea]' -manufacturer[0x43]='Top TroniQ Asia Limited Hong [Kong]' -manufacturer[0x44]='Gentag Inc (USA) [USA]' +local m = {} +m[0x01]='Motorola UK' +m[0x02]='ST Microelectronics SA France' +m[0x03]='Hitachi, Ltd Japan' +m[0x04]='NXP Semiconductors Germany' +m[0x05]='Infineon Technologies AG Germany' +m[0x06]='Cylink USA' +m[0x07]='Texas Instrument France' +m[0x08]='Fujitsu Limited Japan' +m[0x09]='Matsushita Electronics Corporation, Semiconductor Company Japan' +m[0x0A]='NEC Japan' +m[0x0B]='Oki Electric Industry Co. Ltd Japan' +m[0x0C]='Toshiba Corp. Japan' +m[0x0D]='Mitsubishi Electric Corp. Japan' +m[0x0E]='Samsung Electronics Co. Ltd Korea' +m[0x0F]='Hynix / Hyundai, Korea' +m[0x10]='LG-Semiconductors Co. Ltd Korea' +m[0x11]='Emosyn-EM Microelectronics USA' +m[0x12]='INSIDE Technology France' +m[0x13]='ORGA Kartensysteme GmbH Germany' +m[0x14]='SHARP Corporation Japan' +m[0x15]='ATMEL France' +m[0x16]='EM Microelectronic-Marin SA Switzerland' +m[0x17]='KSW Microtec GmbH Germany' +m[0x18]='ZMD AG Germany' +m[0x19]='XICOR, Inc. USA' +m[0x1A]='Sony Corporation Japan' +m[0x1B]='Malaysia Microelectronic Solutions Sdn. Bhd Malaysia' +m[0x1C]='Emosyn USA' +m[0x1D]='Shanghai Fudan Microelectronics Co. Ltd. P.R. China' +m[0x1E]='Magellan Technology Pty Limited Australia' +m[0x1F]='Melexis NV BO Switzerland' +m[0x20]='Renesas Technology Corp. Japan' +m[0x21]='TAGSYS France' +m[0x22]='Transcore USA' +m[0x23]='Shanghai belling corp., ltd. China' +m[0x24]='Masktech Germany Gmbh Germany' +m[0x25]='Innovision Research and Technology Plc UK' +m[0x26]='Hitachi ULSI Systems Co., Ltd. Japan' +m[0x27]='Cypak AB Sweden' +m[0x28]='Ricoh Japan' +m[0x29]='ASK France' +m[0x2A]='Unicore Microsystems, LLC RussianFederation' +m[0x2B]='Dallas Semiconductor/Maxim USA' +m[0x2C]='Impinj, Inc. USA' +m[0x2D]='RightPlug Alliance USA' +m[0x2E]='Broadcom Corporation USA' +m[0x2F]='MStar Semiconductor, Inc Taiwan, ROC' +m[0x30]='BeeDar Technology Inc. USA' +m[0x31]='RFIDsec Denmark' +m[0x32]='Schweizer Electronic AG Germany' +m[0x33]='AMIC Technology Corp Taiwan' +m[0x34]='Mikron JSC Russia' +m[0x35]='Fraunhofer Institute for Photonic Microsystems Germany' +m[0x36]='IDS Microchip AG Switzerland' +m[0x37]='Kovio USA' +m[0x38]='HMT Microelectronic Ltd Switzerland' +m[0x39]='Silicon Craft Technology Thailand' +m[0x3A]='Advanced Film Device Inc. Japan' +m[0x3B]='Nitecrest Ltd UK' +m[0x3C]='Verayo Inc. USA' +m[0x3D]='HID Global USA' +m[0x3E]='Productivity Engineering Gmbh Germany' +m[0x3F]='Austriamicrosystems AG (reserved) Austria' +m[0x40]='Gemalto SA France' +m[0x41]='Renesas Electronics Corporation Japan' +m[0x42]='3Alogics Inc Korea' +m[0x43]='Top TroniQ Asia Limited Hong Kong' +m[0x44]='Gentag Inc USA' +m[0x45]='Invengo Information Technology Co.Ltd China' +m[0x46]='Guangzhou Sysur Microelectronics, Inc China' +m[0x47]='CEITEC S.A. Brazil' +m[0x48]='Shanghai Quanray Electronics Co. Ltd. China' +m[0x49]='MediaTek Inc Taiwan' +m[0x4A]='Angstrem PJSC Russia' +m[0x4B]='Celisic Semiconductor (Hong Kong) Limited China' +m[0x4C]='LEGIC Identsystems AG Switzerland' +m[0x4D]='Balluff GmbH Germany' +m[0x4E]='Oberthur Technologies France' +m[0x4F]='Silterra Malaysia Sdn. Bhd. Malaysia' +m[0x50]='DELTA Danish Electronics, Light & Acoustics Denmark' +m[0x51]='Giesecke & Devrient GmbH Germany' +m[0x52]='Shenzhen China Vision Microelectronics Co., Ltd. China' +m[0x53]='Shanghai Feiju Microelectronics Co. Ltd. China' +m[0x54]='Intel Corporation USA' +m[0x55]='Microsensys GmbH Germany' +m[0x56]='Sonix Technology Co., Ltd. Taiwan' +m[0x57]='Qualcomm Technologies Inc USA' +m[0x58]='Realtek Semiconductor Corp Taiwan' +m[0x59]='Freevision Technologies Co. Ltd China' +m[0x5A]='Giantec Semiconductor Inc. China' +m[0x5B]='JSC Angstrem-T Russia' +m[0x5C]='STARCHIP France' +m[0x5D]='SPIRTECH France' +m[0x5E]='GANTNER Electronic GmbH Austria' +m[0x5F]='Nordic Semiconductor Norway' +m[0x60]='Verisiti Inc USA' +m[0x61]='Wearlinks Technology Inc. China' +m[0x62]='Userstar Information Systems Co., Ltd Taiwan' +m[0x63]='Pragmatic Printing Ltd. UK' +m[0x64]='Associacao do Laboratorio de Sistemas Integraveis Tecnologico – LSI-TEC Brazil' +m[0x65]='Tendyron Corporation China' +m[0x66]='MUTO Smart Co., Ltd. Korea' +m[0x67]='ON Semiconductor USA' +m[0x68]='TUBITAK BILGEM Turkey' +m[0x69]='Huada Semiconductor Co., Ltd China' +m[0x6A]='SEVENEY France' +m[0x6B]='ISSM France' +m[0x6C]='Wisesec Ltd Israel' +m[0x7C]='DB HiTek Co Ltd Korea' +m[0x7D]='SATO Vicinity Australia' +m[0x7E]='Holtek Taiwan' return { lookupManufacturer = function (value) @@ -76,8 +119,6 @@ return { value = v end - return manufacturer[value] or "no tag-info available" + return m[value] or "no tag-info available" end, - - } \ No newline at end of file From 8059f533af019955d9ffc9c2d700cc5ba2f6818b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 26 Jan 2019 11:09:47 +0100 Subject: [PATCH 0450/1938] syntax --- client/loclass/cipherutils.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/loclass/cipherutils.h b/client/loclass/cipherutils.h index 568671791..21d11aac0 100644 --- a/client/loclass/cipherutils.h +++ b/client/loclass/cipherutils.h @@ -52,7 +52,7 @@ typedef struct { uint8_t * buffer; uint8_t numbits; uint8_t position; -}BitstreamOut; +} BitstreamOut; bool headBit( BitstreamIn *stream); bool tailBit( BitstreamIn *stream); From fa3dfa59b97eee7aa1ad2107934162417690bbce Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 26 Jan 2019 19:10:29 +0100 Subject: [PATCH 0451/1938] chg: 'script run legic' - minor adjustments. --- client/scripts/legic.lua | 295 ++++++++++++++++++++------------------- 1 file changed, 155 insertions(+), 140 deletions(-) diff --git a/client/scripts/legic.lua b/client/scripts/legic.lua index 546e5cc1a..264d4dfef 100644 --- a/client/scripts/legic.lua +++ b/client/scripts/legic.lua @@ -513,8 +513,8 @@ function readFromPM3() return tag end -function padString(str) - if (str:len() == 1) then +local function padString(str) + if (#str == 1) then return '0'..str end @@ -524,73 +524,84 @@ end --- -- write virtual Tag to real Tag function writeToTag(tag) - local bytes - local filename='MylegicClone.hex' - local taglen=22 + local bytes + local filename = 'MylegicClone.hex' + local taglen = 22 if(utils.confirm(acred.."\nplace the (empty) Tag onto the PM3\nand confirm writing to this Tag: "..acoff) == false) then - return - end - -- get used bytes / tag-len - if(istable(tag.SEG)) then - if (istable(tag.Bck)) then - for i=0, #tag.SEG do - taglen=taglen+tag.SEG[i].len+5 - end - end - local uid_old=tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2 - -- read new tag into memory so we can xor the new data with the new MCC - outTAG=readFromPM3() - outbytes=tagToBytes(outTAG) - -- copy 'inputbuffer' to 'outputbuffer' - tag.MCD = outbytes[1] - tag.MSN0 = outbytes[2] - tag.MSN1 = outbytes[3] - tag.MSN2 = outbytes[4] - tag.MCC = outbytes[5] - -- recheck all segments-crc/kghcrc (only on a credential) - if(istable(tag.Bck)) then - checkAllSegCrc(tag) - checkAllKghCrc(tag) - local uid_new=tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2 - for i=0, #tag.SEG do - if (check43rdPartyCash1(uid_old, tag.SEG[i].data)) then - io.write(accyan.."\nfixing known checksums"..acoff.." ... ") - if (fix3rdPartyCash1(uid_new, tag.SEG[i].data)) then - io.write(acgreen.." done\n"..acoff) - else oops("\nsomething went wrong at the repair of the 3rd-party-cash-segment") end - end - end - end - bytes=tagToBytes(tag) - -- master-token-crc - if (tag.Type ~= "SAM") then bytes[22] = calcMtCrc(bytes) end - if (bytes) then - print("write temp-file '"..filename.."'") - print(accyan) - writeFile(bytes, filename..".bin") - print(acoff) - end - end + return + end + + -- get used bytes / tag-len + if (istable(tag.SEG)) then + if (istable(tag.Bck)) then + for i=0, #tag.SEG do + taglen = taglen + tag.SEG[i] . len + 5 + end + end + local uid_old = tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2 + + -- read new tag into memory so we can xor the new data with the new MCC + outTAG = readFromPM3() + outbytes = tagToBytes(outTAG) + -- copy 'inputbuffer' to 'outputbuffer' + tag.MCD = outbytes[1] + tag.MSN0 = outbytes[2] + tag.MSN1 = outbytes[3] + tag.MSN2 = outbytes[4] + tag.MCC = outbytes[5] + -- recheck all segments-crc/kghcrc (only on a credential) + if (istable(tag.Bck)) then + checkAllSegCrc(tag) + checkAllKghCrc(tag) + local uid_new = tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2 + for i=0, #tag.SEG do + if (check43rdPartyCash1(uid_old, tag.SEG[i].data)) then + io.write(accyan.."\nfixing known checksums"..acoff.." ... ") + if (fix3rdPartyCash1(uid_new, tag.SEG[i].data)) then + io.write(acgreen.." done\n"..acoff) + else + oops("\nsomething went wrong at the repair of the 3rd-party-cash-segment") + end + end + end + end + bytes = tagToBytes(tag) + -- master-token-crc + if (tag.Type ~= "SAM") then + bytes[22] = calcMtCrc(bytes) + end + if (bytes) then + print("write temp-file '"..filename.."'") + print(accyan) + writeFile(bytes, filename..".bin") + print(acoff) + end + end - -- write data to file + -- write data to file if (taglen > 0) then WriteBytes = utils.input(acyellow.."enter number of bytes to write?"..acoff, taglen) -- load file into pm3-buffer - if (type(filename) ~= "string") then filename=input(acyellow.."filename to load to pm3-buffer?"..acoff,"legic.temp") end + if (type(filename) ~= "string") then + filename = input(acyellow.."filename to load to pm3-buffer?"..acoff, "legic.temp") + end + cmd = 'hf legic eload 2 '..filename core.console(cmd) -- write pm3-buffer to Tag for i=0, WriteBytes do if (i > 6) then - cmd = 'hf legic write o '..string.format("%x", i)..' d '..padString(bytes[i]) - print(acgreen..cmd..acoff) + cmd = ("hf legic write o %x d %s "):format(i, padString(bytes[i])) + print(acgreen..cmd..acoff) core.console(cmd) + core.clearCommandBuffer() elseif (i == 6) then - -- write DCF in reverse order (requires 'mosci-patch') - cmd = 'hf legic write o 05 d '..padString(bytes[i-1])..padString(bytes[i]) - print(acgreen..cmd..acoff) + -- write DCF in reverse order (requires 'mosci-patch') + cmd = ('hf legic write o 05 d %s%s'):format(padString(bytes[i-1]), padString(bytes[i])) + print(acgreen..cmd..acoff) core.console(cmd) - elseif (i == 5) then + core.clearCommandBuffer() + elseif (i == 5) then print(acgreen.."skip byte 0x05 - will be written next step"..acoff) else print(acgreen.."skip byte 0x00-0x04 - unwritable area"..acoff) @@ -603,26 +614,28 @@ end --- File I/O --- --- -- read file into virtual-tag -function readFile(filename) - print(accyan) - local bytes = {} - local tag = {} - if file_check(filename) == false then return oops("input file: "..filename.." not found") end +local function readFile(filename) + print(accyan) + local bytes = {} + local tag = {} + if file_check(filename) == false then + return oops("input file: "..filename.." not found") + end - bytes = getInputBytes(filename) + bytes = getInputBytes(filename) - if bytes == false then return oops('couldnt get input bytes') end + if bytes == false then return oops('couldnt get input bytes') end - -- make plain bytes - bytes = xorBytes(bytes,bytes[5]) - print("create virtual tag from ".. #bytes .. " bytes") - -- create Tag for plain bytes - tag=createTagTable() - -- load plain bytes to tag-table - print(acoff) - tag=bytesToTag(bytes, tag) + -- make plain bytes + bytes = xorBytes(bytes,bytes[5]) + print("create virtual tag from ".. #bytes .. " bytes") + -- create Tag for plain bytes + tag = createTagTable() + -- load plain bytes to tag-table + print(acoff) + tag = bytesToTag(bytes, tag) - return tag + return tag end --- @@ -631,14 +644,16 @@ function writeFile(bytes, filename) if (filename ~= 'MylegicClone.hex') then if (file_check(filename)) then local answer = confirm("\nthe output-file "..filename.." already exists!\nthis will delete the previous content!\ncontinue?") - if (answer==false) then return print("user abort") end + if not answer then return print("user abort") end end end local line - local bcnt=0 - local fho,err = io.open(filename, "w") - if err then oops("OOps ... failed to open output-file ".. filename) end - bytes=xorBytes(bytes, bytes[5]) + local bcnt = 0 + local fho, err = io.open(filename, "w") + if err then + return oops("OOps ... failed to open output-file ".. filename) + end + bytes = xorBytes(bytes, bytes[5]) for i = 1, #bytes do if (bcnt == 0) then line = bytes[i] @@ -662,96 +677,96 @@ end --- Map related --- --- -- make tagMap -function makeTagMap() - local tagMap={} - if (#tagMap == 0) then - tagMap['name'] = input(accyan.."enter Name for this Map: "..acoff , "newTagMap") - tagMap['mappings']={} - tagMap['crc8']={} - -- insert fixed Tag-CRC - table.insert(tagMap.crc8, {name='TAG-CRC', pos=5, seq={1, 4}}) - tagMap['crc16']={} - end - print(accyan.."new tagMap created"..acoff) - return tagMap +local function makeTagMap() + local tagMap = {} + if (#tagMap == 0) then + tagMap['name'] = input(accyan.."enter Name for this Map: "..acoff , "newTagMap") + tagMap['mappings'] = {} + tagMap['crc8'] = {} + -- insert fixed Tag-CRC + table.insert(tagMap.crc8, {name = 'TAG-CRC', pos = 5, seq = {1, 4}}) + tagMap['crc16'] = {} + end + print(accyan.."new tagMap created"..acoff) + return tagMap end --- -- save mapping to file -function saveTagMap(map, filename) - if (string.len(filename)>0) then - if (file_check(filename)) then - local answer = confirm("\nthe output-file "..filename.." alredy exists!\nthis will delete the previous content!\ncontinue?") - if (answer==false) then return print("user abort") end - end - end +local function saveTagMap(map, filename) + if (string.len(filename)>0) then + if (file_check(filename)) then + local answer = confirm("\nthe output-file "..filename.." alredy exists!\nthis will delete the previous content!\ncontinue?") + if not answer then return print("user abort") end + end + end - local line + local line local fho,err = io.open(filename, "w") if err then oops("OOps ... faild to open output-file ".. filename) end - -- write line to new file - for k, v in pairs(map) do - if (istable(v)) then - for k2, v2 in pairs(v) do - if (k=='mappings') then - fho:write(k..","..k2..","..v2['name']..","..v2['start']..","..v2['end']..","..((v2['highlight']) and "1" or "0").."\n") - elseif (k=="crc8") then - local tmp="" - tmp=k..","..k2..","..v2['name']..","..v2['pos'].."," - tmp=tmp..tbl2seqstr(v2['seq']) - fho:write(tmp.."\n") - end - end - else - fho:write(k..","..v.."\n") - end - end + -- write line to new file + for k, v in pairs(map) do + if (istable(v)) then + for k2, v2 in pairs(v) do + if (k == 'mappings') then + fho:write(k..","..k2..","..v2['name']..","..v2['start']..","..v2['end']..","..((v2['highlight']) and "1" or "0").."\n") + elseif (k == "crc8") then + local tmp = "" + tmp = k..","..k2..","..v2['name']..","..v2['pos'].."," + tmp=tmp..tbl2seqstr(v2['seq']) + fho:write(tmp.."\n") + end + end + else + fho:write(k..","..v.."\n") + end + end fho:close() return true end --- -- toggle higligh -function toggleHighlight(tbl) +local function toggleHighlight(tbl) if (tbl['highlight']) then tbl['highlight'] = false else tbl['highlight'] = true end - return tbl + return tbl end --- -- return table od seqence-string -function seqstr2tbl(seqstr) - local s=split(seqstr) - local res={} - if (#s>=1) then - for sk, sv in pairs(s) do - s2=split(sv, '-') - if(#s2==2) then - table.insert(res, s2[1]) - table.insert(res, s2[2]) - end - end - end - return res +local function seqstr2tbl(seqstr) + local s = split(seqstr) + local res = {} + if (#s >= 1) then + for sk, sv in pairs(s) do + s2 = split(sv, '-') + if(#s2 == 2) then + table.insert(res, s2[1]) + table.insert(res, s2[2]) + end + end + end + return res end --- -- return sequence-string from table -function tbl2seqstr(seqtbl) - local res="" - if (istable(seqtbl)) then - for sk, sv in pairs(seqtbl) do - res=res..sv..((sk%2==0) and "," or "-") - end - if (string.sub(res, string.len(res))==",") then - res=string.sub(res, 1, string.len(res)-1) - end - end - return res +local function tbl2seqstr(seqtbl) + local res = "" + if (istable(seqtbl)) then + for sk, sv in pairs(seqtbl) do + res = res..sv..((sk%2==0) and "," or "-") + end + if (string.sub(res, string.len(res))== ",") then + res = string.sub(res, 1, string.len(res)-1) + end + end + return res end --- From 0beb730e043b632972318bc3d1e0a5e8e9934d37 Mon Sep 17 00:00:00 2001 From: Iceman Date: Sun, 27 Jan 2019 20:42:50 +0100 Subject: [PATCH 0452/1938] Update README.md --- README.md | 35 ++++++++++++++++++++++++++++++++--- 1 file changed, 32 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index f21a2efdc..effdc0f6e 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,33 @@ Proxmark3 RDV40 dedicated repo, based on iceman fork ## Notice This repo is based on iceman fork for proxmark3. It is dedicated to bring the most out of the new features for proxmark3 RDV40 device. +# Donations +Nothing says thank you as much as a donation, https://www.patreon.com/iceman1001 + +## ToC + +- Coverity Scan Config & Run +- Whats changed? +- Why didn't you based it on offical PM3 Master? +- Why don't you add this or that functionality? +- PM3 GUI +- Development +- KALI and ARCHLINUX users +- Setup and build for UBUNTU +- Setup and build for ArchLinux +- Homebrew (Mac OS X) +- Upgrading HomeBrew tap formula +- Building on Windows +- Gator96100 distro +- Build and run +- Validating proxmark client functionality +- Run the following commands +- Quit client +- First things on your RDV40 +- Verify sim module firmware version + +- The end + ## Coverity Scan Config & Run Download the Coverity Scan Self-buld and install it. You will need to configure ARM-NON-EABI- Compiler for it to use: @@ -37,14 +64,16 @@ The separation from offical pm3 repo gives us very much freedom to create a firm Give us a hint, and we'll see if we can't merge in the stuff you have. ## PM3 GUI -The official PM3-GUI from Gaucho will not work. -The new universial GUI will work. +The official PM3-GUI from Gaucho will not work. +The new universial GUI will work. [Proxmark3 Univerisal GUI](https://github.com/burma69/PM3UniversalGUI) ## Development This fork now compiles just fine on - Windows/mingw environment with Qt5.6.1 & GCC 4.8 - Ubuntu 1404, 1510, 1604, 1804 - Mac OS X / Homebrew + - ParrotOS + - WSL (Windows subsystem linux) on Windows 10 - Docker container ## KALI and ARCHLINUX users @@ -224,7 +253,7 @@ If all went well you should get some information about the firmware and memory u > > pm3 --> -### run the following commands +### Run the following commands pm3 --> hw status pm3 --> hw version pm3 --> hw tune From 34be8b4d37e5a9cb222370f77efbb113f00d18a6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 29 Jan 2019 15:23:07 +0100 Subject: [PATCH 0453/1938] CHG: wrong iso7816 (@piwi) --- client/cmdhflist.c | 2 +- client/cmdsmartcard.c | 4 ++-- common/protocols.h | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/client/cmdhflist.c b/client/cmdhflist.c index 7791c5e53..b2e0eeecc 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -357,7 +357,7 @@ void annotateIso7816(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ case ISO7816_EXTERNAL_AUTHENTICATION :snprintf(exp, size, "EXTERNAL AUTH");break; case ISO7816_GET_CHALLENGE :snprintf(exp, size, "GET CHALLENGE");break; case ISO7816_MANAGE_CHANNEL :snprintf(exp, size, "MANAGE CHANNEL");break; - case ISO7816_GETSTATUS :snprintf(exp, size, "GET RESPONSE");break; + case ISO7816_GET_RESPONSE :snprintf(exp, size, "GET RESPONSE");break; default :snprintf(exp,size,"?"); break; } } diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index fdc825d38..45957d407 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -356,7 +356,7 @@ static int smart_responseEx(uint8_t *data, bool silent) { if (needGetData) { int len = data[datalen - 1]; if (!silent) PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len); - uint8_t getstatus[] = {0x00, ISO7816_GETSTATUS, 0x00, 0x00, len}; + uint8_t getstatus[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, len}; UsbCommand cStatus = {CMD_SMART_RAW, {SC_RAW, sizeof(getstatus), 0}}; memcpy(cStatus.d.asBytes, getstatus, sizeof(getstatus) ); clearCommandBuffer(); @@ -372,7 +372,7 @@ static int smart_responseEx(uint8_t *data, bool silent) { if (datalen != len + 2) { // data with ACK if (datalen == len + 2 + 1) { // 2 - response, 1 - ACK - if (data[0] != ISO7816_GETSTATUS) { + if (data[0] != ISO7816_GET_RESPONSE) { if (!silent) { PrintAndLogEx(ERR, "GetResponse ACK error. len 0x%x | data[0] %02X", len, data[0]); } diff --git a/common/protocols.h b/common/protocols.h index 9696c73e0..3c2e79a8d 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -302,10 +302,10 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define ISO7816_VERIFY 0x20 #define ISO7816_INTERNAL_AUTHENTICATION 0x88 #define ISO7816_EXTERNAL_AUTHENTICATION 0x82 -#define ISO7816_GET_CHALLENGE 0xB4 +#define ISO7816_GET_CHALLENGE 0x84 #define ISO7816_MANAGE_CHANNEL 0x70 -#define ISO7816_GETSTATUS 0xC0 +#define ISO7816_GET_RESPONSE 0xC0 // ISO7816-4 For response APDU's #define ISO7816_OK 0x9000 // 6x xx = ERROR From c419f7bf37fcaf637136edb830dea0e33fcb5010 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 29 Jan 2019 15:42:31 +0100 Subject: [PATCH 0454/1938] CHG: dropfield when CL is used. --- client/emv/cmdemv.c | 38 +++++++++++++++++--------------------- client/emv/emvcore.c | 4 ++-- client/util.h | 8 ++++++++ 3 files changed, 27 insertions(+), 23 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 453d08a20..f033ad7ba 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -623,7 +623,7 @@ int CmdEMVInternalAuthenticate(const char *cmd) { return 0; } -#define dreturn(n) {free(pdol_data_tlv);tlvdb_free(tlvSelect);tlvdb_free(tlvRoot);DropField();return n;} +#define dreturn(n) {free(pdol_data_tlv); tlvdb_free(tlvSelect); tlvdb_free(tlvRoot); DropFieldEx( channel ); return n;} void InitTransactionParameters(struct tlvdb *tlvRoot, bool paramLoadJSON, enum TransactionType TrType, bool GenACGPO) { @@ -1212,7 +1212,7 @@ int CmdEMVExec(const char *cmd) { } - DropField(); + DropFieldEx( channel ); // Destroy TLV's free(pdol_data_tlv); @@ -1314,7 +1314,7 @@ int CmdEMVScan(const char *cmd) { } // drop field at start - DropField(); + DropFieldEx( channel ); // iso 14443 select PrintAndLogEx(NORMAL, "--> GET UID, ATS."); @@ -1367,7 +1367,7 @@ int CmdEMVScan(const char *cmd) { if (EMVSearch(channel, false, true, decodeTLV, tlvSelect)) { PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit..."); tlvdb_free(tlvSelect); - DropField(); + DropFieldEx( channel ); return 3; } @@ -1383,7 +1383,7 @@ int CmdEMVScan(const char *cmd) { if (!AIDlen) { PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit..."); - DropField(); + DropFieldEx( channel ); return 4; } @@ -1402,7 +1402,7 @@ int CmdEMVScan(const char *cmd) { if (res) { PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res); tlvdb_free(tlvRoot); - DropField(); + DropFieldEx( channel ); return 5; } @@ -1430,7 +1430,7 @@ int CmdEMVScan(const char *cmd) { if (!pdol_data_tlv){ PrintAndLogEx(ERR, "Can't create PDOL TLV."); tlvdb_free(tlvRoot); - DropField(); + DropFieldEx( channel ); return 6; } @@ -1439,7 +1439,7 @@ int CmdEMVScan(const char *cmd) { if (!pdol_data_tlv_data) { PrintAndLogEx(ERR, "Can't create PDOL data."); tlvdb_free(tlvRoot); - DropField(); + DropFieldEx( channel ); return 6; } PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); @@ -1453,7 +1453,7 @@ int CmdEMVScan(const char *cmd) { if (res) { PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw); tlvdb_free(tlvRoot); - DropField(); + DropFieldEx( channel ); return 7; } ProcessGPOResponseFormat1(tlvRoot, buf, len, decodeTLV); @@ -1545,8 +1545,7 @@ int CmdEMVScan(const char *cmd) { // free tlv object tlvdb_free(tlvRoot); - // DropField - DropField(); + DropFieldEx( channel ); res = json_dump_file(root, fname, JSON_INDENT(2)); if (res) { @@ -1630,7 +1629,7 @@ int CmdEMVRoca(const char *cmd) { if (EMVSearch(channel, false, true, false, tlvSelect)) { PrintAndLogEx(ERR, "Can't found any of EMV AID. Exit..."); tlvdb_free(tlvSelect); - DropField(); + DropFieldEx( channel ); return 3; } @@ -1646,7 +1645,7 @@ int CmdEMVRoca(const char *cmd) { if (!AIDlen) { PrintAndLogEx(INFO, "Can't select AID. EMV AID not found. Exit..."); - DropField(); + DropFieldEx( channel ); return 4; } @@ -1661,7 +1660,7 @@ int CmdEMVRoca(const char *cmd) { if (res) { PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res); tlvdb_free(tlvRoot); - DropField(); + DropFieldEx( channel ); return 5; } @@ -1673,7 +1672,7 @@ int CmdEMVRoca(const char *cmd) { if (!pdol_data_tlv){ PrintAndLogEx(ERR, "Can't create PDOL TLV."); tlvdb_free(tlvRoot); - DropField(); + DropFieldEx( channel ); return 6; } @@ -1682,7 +1681,7 @@ int CmdEMVRoca(const char *cmd) { if (!pdol_data_tlv_data) { PrintAndLogEx(ERR, "Can't create PDOL data."); tlvdb_free(tlvRoot); - DropField(); + DropFieldEx( channel ); return 6; } PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); @@ -1696,7 +1695,7 @@ int CmdEMVRoca(const char *cmd) { if (res) { PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw); tlvdb_free(tlvRoot); - DropField(); + DropFieldEx( channel ); return 7; } ProcessGPOResponseFormat1(tlvRoot, buf, len, false); @@ -1794,10 +1793,7 @@ out: // free tlv object tlvdb_free(tlvRoot); - if ( channel == ECC_CONTACTLESS) - DropField(); - - + DropFieldEx( channel ); return 0; } diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 77d288eaa..ae3b0574a 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -241,7 +241,7 @@ int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveField int res = 0; if (ActivateField) { - DropField(); + DropFieldEx( channel ); msleep(50); } @@ -484,7 +484,7 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO } if(!LeaveFieldON) - DropField(); + DropFieldEx( channel ); return res; } diff --git a/client/util.h b/client/util.h index c9f13870d..e10f06497 100644 --- a/client/util.h +++ b/client/util.h @@ -178,6 +178,14 @@ } #endif +#ifndef DropFieldEx +#define DropFieldEx(x) { \ + if ( (x) == ECC_CONTACTLESS) { \ + DropField(); \ + } \ +} +#endif + extern uint8_t g_debugMode; extern int ukbhit(void); From 8991fa172dcb974adb538589dd6b663ca42dcdc4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Tue, 29 Jan 2019 15:47:44 +0100 Subject: [PATCH 0455/1938] FIX: wrong define --- armsrc/lfops.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/armsrc/lfops.c b/armsrc/lfops.c index d750fccbe..96abd9b99 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -80,7 +80,7 @@ void setT55xxConfig(uint8_t arg0, t55xx_config *c) { printT55xxConfig(); -#if WITH_FLASH +#ifdef WITH_FLASH // shall persist to flashmem if (arg0 == 0) { return; @@ -119,7 +119,7 @@ t55xx_config* getT55xxConfig(void) { } void loadT55xxConfig(void) { -#if WITH_FLASH +#ifdef WITH_FLASH if (!FlashInit()) { return; } From 1b3d96ab2dfa32dcd43525b2bf4808414fc26dba Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 29 Jan 2019 19:30:15 +0200 Subject: [PATCH 0456/1938] add apdu chaining to arm side --- armsrc/iso14443a.c | 3 +++ include/mifare.h | 1 + 2 files changed, 4 insertions(+) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 257c39b1f..daeb6b749 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2226,6 +2226,9 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data, uint8_t *res) { if (cmd_len) { // ISO 14443 APDU frame: PCB [CID] [NAD] APDU CRC PCB=0x02 real_cmd[0] = 0x02; // bnr,nad,cid,chn=0; i-block(0x00) + if (param & ISO14A_SEND_CHAINING) { + real_cmd[0] |= 0x10; + } // put block number into the PCB real_cmd[0] |= iso14_pcb_blocknum; memcpy(real_cmd + 1, cmd, cmd_len); diff --git a/include/mifare.h b/include/mifare.h index cda7cfe9d..1373317e7 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -36,6 +36,7 @@ typedef enum ISO14A_COMMAND { ISO14A_NO_SELECT = (1 << 7), ISO14A_TOPAZMODE = (1 << 8), ISO14A_NO_RATS = (1 << 9) + ISO14A_SEND_CHAINING = (1 << 9) } iso14a_command_t; typedef struct { From cf21f046d82d0d85431cec779a668a1b642ca784 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 30 Jan 2019 18:15:47 +0200 Subject: [PATCH 0457/1938] arm side --- armsrc/epa.c | 2 +- armsrc/iso14443a.c | 6 +++--- armsrc/iso14443a.h | 2 +- include/mifare.h | 4 ++-- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/armsrc/epa.c b/armsrc/epa.c index 68b2711da..e97fda7a0 100644 --- a/armsrc/epa.c +++ b/armsrc/epa.c @@ -108,7 +108,7 @@ int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response) switch(iso_type) { case 'a': - return iso14_apdu(apdu, (uint16_t) length, response, NULL); + return iso14_apdu(apdu, (uint16_t) length, false, response, NULL); break; case 'b': return iso14443b_apdu(apdu, length, response); diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index daeb6b749..082d378ac 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2219,14 +2219,14 @@ b8 b7 b6 b5 b4 b3 b2 b1 b5,b6 = 00 - DESELECT 11 - WTX */ -int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data, uint8_t *res) { +int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res) { uint8_t parity[MAX_PARITY_SIZE] = {0x00}; uint8_t real_cmd[cmd_len + 4]; if (cmd_len) { // ISO 14443 APDU frame: PCB [CID] [NAD] APDU CRC PCB=0x02 real_cmd[0] = 0x02; // bnr,nad,cid,chn=0; i-block(0x00) - if (param & ISO14A_SEND_CHAINING) { + if (send_chaining) { real_cmd[0] |= 0x10; } // put block number into the PCB @@ -2341,7 +2341,7 @@ void ReaderIso14443a(UsbCommand *c) { if ((param & ISO14A_APDU)) { uint8_t res; - arg0 = iso14_apdu(cmd, len, buf, &res); + arg0 = iso14_apdu(cmd, len, (param & ISO14A_SEND_CHAINING), buf, &res); cmd_send(CMD_ACK, arg0, res, 0, buf, sizeof(buf)); } diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index 7f979e531..a23b5d7c2 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -114,7 +114,7 @@ extern void ReaderTransmitPar(uint8_t *frame, uint16_t len, uint8_t *par, uint32 extern int ReaderReceive(uint8_t *receivedAnswer, uint8_t *par); extern void iso14443a_setup(uint8_t fpga_minor_mode); -extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, void *data, uint8_t *res); +extern int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res); extern int iso14443a_select_card(uint8_t *uid_ptr, iso14a_card_select_t *resp_data, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats); extern int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades); extern void iso14a_set_trigger(bool enable); diff --git a/include/mifare.h b/include/mifare.h index 1373317e7..14c0e7e27 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -35,8 +35,8 @@ typedef enum ISO14A_COMMAND { ISO14A_SET_TIMEOUT = (1 << 6), ISO14A_NO_SELECT = (1 << 7), ISO14A_TOPAZMODE = (1 << 8), - ISO14A_NO_RATS = (1 << 9) - ISO14A_SEND_CHAINING = (1 << 9) + ISO14A_NO_RATS = (1 << 9), + ISO14A_SEND_CHAINING = (1 << 10) } iso14a_command_t; typedef struct { From 30a6ef19b904492dc3cccc4f1f877a75cd4661e9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 30 Jan 2019 18:16:50 +0200 Subject: [PATCH 0458/1938] added FSC correct calculation in `hf 14a info` --- client/cmdhf14a.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 43832e2cf..4a6b7518d 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -147,6 +147,10 @@ char* getTagInfo(uint8_t uid) { return manufactureMapping[len-1].desc; } +// iso14a apdu input frame length +static uint16_t frameLength = 0; +uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256}; + int usage_hf_14a_sim(void) { // PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"); PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 byte UID\n"); @@ -486,10 +490,7 @@ int CmdHF14AInfo(const char *Cmd) { (tb1 ? "" : " NOT"), (tc1 ? "" : " NOT"), fsci, - fsci < 5 ? (fsci - 2) * 8 : - fsci < 8 ? (fsci - 3) * 32 : - fsci == 8 ? 256 : - -1 + fsci < sizeof(atsFSC) ? atsFSC[fsci] : -1 ); } pos = 2; From 18db34ffb048af75c71c69d8408c661fe220fa51 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 30 Jan 2019 20:18:50 +0100 Subject: [PATCH 0459/1938] chg: use calloc --- client/cmddata.c | 2 +- client/cmdhfepa.c | 2 +- client/cmdhficlass.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index a9f58b962..65fd0d829 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1786,7 +1786,7 @@ int Cmdbin2hex(const char *Cmd) { //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); + uint8_t* arr = (uint8_t *) calloc(bytelen, sizeof(uint8_t)); memset(arr, 0, bytelen); BitstreamOut bout = { arr, 0, 0 }; diff --git a/client/cmdhfepa.c b/client/cmdhfepa.c index b681810ed..dd110c9c0 100644 --- a/client/cmdhfepa.c +++ b/client/cmdhfepa.c @@ -43,7 +43,7 @@ int CmdHFEPACollectPACENonces(const char *Cmd) PrintAndLogEx(FAILED, "Error in step %d, Return code: %d",resp.arg[0],(int)resp.arg[1]); } else { size_t nonce_length = resp.arg[1]; - char *nonce = (char *) malloc(2 * nonce_length + 1); + char *nonce = (char *) calloc(2 * nonce_length + 1, sizeof(uint8_t)); for(int j = 0; j < nonce_length; j++) { sprintf(nonce + (2 * j), "%02X", resp.d.asBytes[j]); } diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index f0bfa18a0..9427acf50 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -404,7 +404,7 @@ int CmdHFiClassSim(const char *Cmd) { break; size_t datalen = NUM_CSNS * 24; - void* dump = malloc(datalen); + void* dump = calloc(datalen, sizeof(uint8_t)); if ( !dump ) { PrintAndLogEx(WARNING, "Failed to allocate memory"); return 2; @@ -456,7 +456,7 @@ int CmdHFiClassSim(const char *Cmd) { break; size_t datalen = NUM_CSNS * 24; - void* dump = malloc(datalen); + void* dump = calloc(datalen, sizeof(uint8_t)); if ( !dump ) { PrintAndLogEx(WARNING, "Failed to allocate memory"); return 2; From ed7122e409907810f65cc0d458a536607fb04590 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 30 Jan 2019 20:21:41 +0100 Subject: [PATCH 0460/1938] chg: use calloc --- client/cmdhfmf.c | 6 +++--- client/cmdhftopaz.c | 6 +++--- client/cmdsmartcard.c | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index a02302b15..a26381930 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -415,7 +415,7 @@ int GetHFMF14AUID(uint8_t *uid, int *uidlen) { char * GenerateFilename(const char *prefix, const char *suffix){ uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; int uidlen=0; - char * fptr = malloc (sizeof (char) * (strlen(prefix) + strlen(suffix)) + sizeof(uid)*2 + 1); + char * fptr = calloc (sizeof (char) * (strlen(prefix) + strlen(suffix)) + sizeof(uid)*2 + 1, sizeof(uint8_t)); GetHFMF14AUID(uid, &uidlen); if (!uidlen) { @@ -2195,7 +2195,7 @@ int CmdHF14AMfSniff(const char *Cmd){ if (traceLen > bufsize || buf == NULL) { uint8_t *p; if (buf == NULL) // not yet allocated - p = malloc(traceLen); + p = calloc(traceLen, sizeof(uint8_t)); else // need more memory p = realloc(buf, traceLen); @@ -2912,7 +2912,7 @@ int CmdHF14AMfCSave(const char *Cmd) { if (errors || cmdp == 0) return usage_hf14_csave(); - dump = malloc(bytes); + dump = calloc(bytes, sizeof(uint8_t)); if (!dump) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return 1; diff --git a/client/cmdhftopaz.c b/client/cmdhftopaz.c index ea4699f1b..a6046cee0 100644 --- a/client/cmdhftopaz.c +++ b/client/cmdhftopaz.c @@ -194,7 +194,7 @@ static int topaz_print_CC(uint8_t *data) { PrintAndLogEx(NORMAL, " %02x: version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f); uint16_t memsize = (data[2] + 1) * 8; topaz_tag.size = memsize; - topaz_tag.dynamic_memory = malloc(memsize - TOPAZ_STATIC_MEMORY); + topaz_tag.dynamic_memory = calloc(memsize - TOPAZ_STATIC_MEMORY, sizeof(uint8_t)); PrintAndLogEx(NORMAL, " %02x: Physical Memory Size of this tag: %d bytes", data[2], memsize); PrintAndLogEx(NORMAL, " %02x: %s / %s", data[3], (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", @@ -278,12 +278,12 @@ static void topaz_print_control_TLVs(uint8_t *memory) { dynamic_lock_area_t *old = topaz_tag.dynamic_lock_areas; dynamic_lock_area_t *new = topaz_tag.dynamic_lock_areas; if (old == NULL) { - new = topaz_tag.dynamic_lock_areas = (dynamic_lock_area_t *)malloc(sizeof(dynamic_lock_area_t)); + new = topaz_tag.dynamic_lock_areas = (dynamic_lock_area_t *) calloc(sizeof(dynamic_lock_area_t, sizeof(uint8_t))); } else { while(old->next != NULL) { old = old->next; } - new = old->next = (dynamic_lock_area_t *)malloc(sizeof(dynamic_lock_area_t)); + new = old->next = (dynamic_lock_area_t *) calloc(sizeof(dynamic_lock_area_t), sizeof(uint8_t)); } new->next = NULL; if (area_start <= next_lockable_byte) { diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 45957d407..23b2b8b3c 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -1012,7 +1012,7 @@ int CmdSmartBruteforceSFI(const char *Cmd) { json_t *root = NULL; smart_loadjson("aidlist", "json", &root); - uint8_t* buf = malloc(USB_CMD_DATA_SIZE); + uint8_t* buf = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t)); if ( !buf ) return 1; From e81b0fa355df3d227a39c717b577a27ad13e40ad Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 30 Jan 2019 20:43:30 +0100 Subject: [PATCH 0461/1938] chg: use calloc --- client/cmdhftopaz.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhftopaz.c b/client/cmdhftopaz.c index a6046cee0..2f80b054c 100644 --- a/client/cmdhftopaz.c +++ b/client/cmdhftopaz.c @@ -278,7 +278,7 @@ static void topaz_print_control_TLVs(uint8_t *memory) { dynamic_lock_area_t *old = topaz_tag.dynamic_lock_areas; dynamic_lock_area_t *new = topaz_tag.dynamic_lock_areas; if (old == NULL) { - new = topaz_tag.dynamic_lock_areas = (dynamic_lock_area_t *) calloc(sizeof(dynamic_lock_area_t, sizeof(uint8_t))); + new = topaz_tag.dynamic_lock_areas = (dynamic_lock_area_t *) calloc(sizeof(dynamic_lock_area_t) , sizeof(uint8_t)); } else { while(old->next != NULL) { old = old->next; From 99b6087b01506320de9a8db5ad70b2cc0f2a520f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 30 Jan 2019 21:16:20 +0100 Subject: [PATCH 0462/1938] chg: use calloc --- client/tinycbor/open_memstream.c | 2 +- client/ui.c | 2 +- client/util.c | 4 ++-- common/crapto1/crapto1.c | 4 ++-- common/radixsort.c | 2 +- uart/uart_posix.c | 2 +- uart/uart_win32.c | 2 +- 7 files changed, 9 insertions(+), 9 deletions(-) diff --git a/client/tinycbor/open_memstream.c b/client/tinycbor/open_memstream.c index 18f3de8b1..f618db8ae 100644 --- a/client/tinycbor/open_memstream.c +++ b/client/tinycbor/open_memstream.c @@ -90,7 +90,7 @@ static int close_buffer(void *cookie) FILE *open_memstream(char **bufptr, size_t *lenptr) { - struct Buffer *b = (struct Buffer *)malloc(sizeof(struct Buffer)); + struct Buffer *b = (struct Buffer *)calloc(sizeof(struct Buffer), sizeof(uint8_t)); if (b == NULL) return NULL; b->alloc = 0; diff --git a/client/ui.c b/client/ui.c index a0151a8db..71603fed6 100644 --- a/client/ui.c +++ b/client/ui.c @@ -196,7 +196,7 @@ void SetFlushAfterWrite(bool value) { int i,j; - int * output = (int* ) malloc(sizeof(int) * len); + int * output = (int* ) calloc(sizeof(int) * len, sizeof(uint8_t)); if ( !output ) return; // clear mem diff --git a/client/util.c b/client/util.c index b22258d44..c4d6ae5a4 100644 --- a/client/util.c +++ b/client/util.c @@ -884,8 +884,8 @@ extern void strcreplace(char *buf, size_t len, char from, char to) { } extern char *strmcopy(char *buf) { - char* str = NULL; - if ((str = (char*) malloc(strlen(buf) + 1)) != NULL) { + char* str = (char*) calloc(strlen(buf) + 1, sizeof(uint8_t)); + if (str != NULL) { memset(str, 0, strlen(buf) + 1); strcpy(str, buf); } diff --git a/common/crapto1/crapto1.c b/common/crapto1/crapto1.c index 8dc8f26c8..af1ed8167 100644 --- a/common/crapto1/crapto1.c +++ b/common/crapto1/crapto1.c @@ -405,7 +405,7 @@ int nonce_distance(uint32_t from, uint32_t to) { uint16_t x, i; if(!dist) { - dist = malloc(2 << 16); + dist = calloc(2 << 16, sizeof(uint8_t)); if(!dist) return -1; for (x = i = 1; i; ++i) { @@ -443,7 +443,7 @@ static uint32_t fastfwd[2][8] = { */ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) { - uint32_t *candidates = malloc(4 << 10); + uint32_t *candidates = calloc(4 << 10, sizeof(uint8_t)); if (!candidates) return 0; uint32_t c, entry; diff --git a/common/radixsort.c b/common/radixsort.c index 91495316c..981c19191 100644 --- a/common/radixsort.c +++ b/common/radixsort.c @@ -3,7 +3,7 @@ uint64_t * radixSort(uint64_t * array, uint32_t size) { rscounts_t counts; memset(&counts, 0, 256 * 8 * sizeof(uint32_t)); - uint64_t * cpy = (uint64_t *)malloc(size * sizeof(uint64_t)); + uint64_t * cpy = (uint64_t *)calloc(size * sizeof(uint64_t), sizeof(uint8_t)); uint32_t o8=0, o7=0, o6=0, o5=0, o4=0, o3=0, o2=0, o1=0; uint32_t t8, t7, t6, t5, t4, t3, t2, t1; uint32_t x; diff --git a/uart/uart_posix.c b/uart/uart_posix.c index d857729d6..cb878a4f0 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -75,7 +75,7 @@ const struct timeval timeout = { serial_port uart_open(const char* pcPortName) { - serial_port_unix* sp = malloc(sizeof(serial_port_unix)); + serial_port_unix* sp = calloc(sizeof(serial_port_unix), sizeof(uint8_t)); if (sp == 0) return INVALID_SERIAL_PORT; if (memcmp(pcPortName, "tcp:", 4) == 0) { diff --git a/uart/uart_win32.c b/uart/uart_win32.c index 11c90f15f..438f586c8 100644 --- a/uart/uart_win32.c +++ b/uart/uart_win32.c @@ -50,7 +50,7 @@ typedef struct { serial_port uart_open(const char* pcPortName) { char acPortName[255]; - serial_port_windows* sp = malloc(sizeof(serial_port_windows)); + serial_port_windows* sp = calloc(sizeof(serial_port_windows), sizeof(uint8_t)); if (sp == 0) { printf("[!] UART failed to allocate memory\n"); From ad72a424ef12b392490fad34f49d1a2d76adab5e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 30 Jan 2019 21:40:50 +0100 Subject: [PATCH 0463/1938] chg: use calloc --- client/cmdhfmfhard.c | 2 +- client/fpga_compress.c | 6 +++--- client/hid-flasher/flash.c | 6 +++--- client/loclass/cipher.c | 4 ++-- client/loclass/elite_crack.c | 2 +- client/proxmark3.c | 8 ++++---- client/reveng/cli.c | 4 +++- client/reveng/model.c | 2 +- client/reveng/poly.c | 2 +- client/reveng/preset.c | 8 ++++++-- client/reveng/reveng.c | 8 +++++--- client/scandir.c | 3 ++- client/tinycbor/cborparser_dup_string.c | 2 +- client/tinycbor/cbortojson.c | 4 ++-- client/util.c | 2 +- 15 files changed, 36 insertions(+), 27 deletions(-) diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 07e05a81e..3547761a5 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -209,7 +209,7 @@ static int compare_count_bitflip_bitarrays(const void *b1, const void *b2) static voidpf inflate_malloc(voidpf opaque, uInt items, uInt size) { - return malloc(items*size); + return calloc(items*size, sizeof(uint8_t)); } diff --git a/client/fpga_compress.c b/client/fpga_compress.c index ceba6ac64..6e6e67be4 100644 --- a/client/fpga_compress.c +++ b/client/fpga_compress.c @@ -59,7 +59,7 @@ static void usage(void) static voidpf fpga_deflate_malloc(voidpf opaque, uInt items, uInt size) { - return malloc(items*size); + return calloc(items*size, sizeof(uint8_t)); } @@ -89,9 +89,9 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardn z_stream compressed_fpga_stream; if (hardnested_mode) { - fpga_config = malloc(num_infiles * HARDNESTED_TABLE_SIZE); + fpga_config = calloc(num_infiles * HARDNESTED_TABLE_SIZE, sizeof(uint8_t)); } else { - fpga_config = malloc(num_infiles * FPGA_CONFIG_SIZE); + fpga_config = calloc(num_infiles * FPGA_CONFIG_SIZE, sizeof(uint8_t)); } // read the input files. Interleave them into fpga_config[] i = 0; diff --git a/client/hid-flasher/flash.c b/client/hid-flasher/flash.c index e74f4ed49..c53e560d5 100644 --- a/client/hid-flasher/flash.c +++ b/client/hid-flasher/flash.c @@ -40,7 +40,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, flash_seg_t *seg; uint32_t last_end = 0; - ctx->segments = malloc(sizeof(flash_seg_t) * num_phdrs); + ctx->segments = calloc(sizeof(flash_seg_t) * num_phdrs, sizeof(uint8_t)); if (!ctx->segments) { fprintf(stderr, "Out of memory\n"); return -1; @@ -90,7 +90,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, uint8_t *data; // make extra space if we need to move the data forward - data = malloc(filesz + BLOCK_SIZE); + data = calloc(filesz + BLOCK_SIZE, sizeof(uint8_t)); if (!data) { fprintf(stderr, "Out of memory\n"); return -1; @@ -226,7 +226,7 @@ int flash_load(flash_file_t *ctx, const char *name, int can_write_bl) } num_phdrs = le16(ehdr.e_phnum); - phdrs = malloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr)); + phdrs = calloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr), sizeof(uint8_t)); if (!phdrs) { fprintf(stderr, "Out of memory\n"); goto fail; diff --git a/client/loclass/cipher.c b/client/loclass/cipher.c index af11ce4cc..e8553ba6c 100644 --- a/client/loclass/cipher.c +++ b/client/loclass/cipher.c @@ -224,7 +224,7 @@ void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) { uint8_t cc_nr[13] = { 0 }; uint8_t div_key[8]; - //cc_nr=(uint8_t*)malloc(length+1); + //cc_nr=(uint8_t*) calloc(length+1, sizeof(uint8_t)); memcpy(cc_nr, cc_nr_p, 12); memcpy(div_key, div_key_p, 8); @@ -244,7 +244,7 @@ void doMAC_N(uint8_t *address_data_p, uint8_t address_data_size, uint8_t *div_ke { uint8_t *address_data; uint8_t div_key[8]; - address_data = (uint8_t*) malloc(address_data_size); + address_data = (uint8_t*) calloc(address_data_size, sizeof(uint8_t)); memcpy(address_data, address_data_p, address_data_size); memcpy(div_key, div_key_p, 8); diff --git a/client/loclass/elite_crack.c b/client/loclass/elite_crack.c index 2002e348f..6619e7aaa 100644 --- a/client/loclass/elite_crack.c +++ b/client/loclass/elite_crack.c @@ -493,7 +493,7 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) { uint64_t t1 = msclock(); - dumpdata* attack = (dumpdata* ) malloc(itemsize); + dumpdata* attack = (dumpdata* ) calloc(itemsize, sizeof(uint8_t)); for (i = 0 ; i * itemsize < dumpsize ; i++ ) { memcpy(attack, dump + i * itemsize, itemsize); diff --git a/client/proxmark3.c b/client/proxmark3.c index ed7fd245d..246da350b 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -215,11 +215,11 @@ const char *get_my_executable_directory(void) { static void set_my_executable_path(void) { int path_length = wai_getExecutablePath(NULL, 0, NULL); if (path_length != -1) { - my_executable_path = (char*)malloc(path_length + 1); + my_executable_path = (char*)calloc(path_length + 1, sizeof(uint8_t)); int dirname_length = 0; if (wai_getExecutablePath(my_executable_path, path_length, &dirname_length) != -1) { my_executable_path[path_length] = '\0'; - my_executable_directory = (char *)malloc(dirname_length + 2); + my_executable_directory = (char *)calloc(dirname_length + 2, sizeof(uint8_t)); strncpy(my_executable_directory, my_executable_path, dirname_length+1); my_executable_directory[dirname_length+1] = '\0'; } @@ -321,9 +321,9 @@ int main(int argc, char* argv[]) { } else { if (addLuaExec){ // add "script run " to command - char *ctmp = NULL; int len = strlen(script_cmd) + 11 + 1; - if ((ctmp = (char*) malloc(len)) != NULL) { + char *ctmp = (char*) calloc(len, sizeof(uint8_t)); + if (ctmp != NULL) { memset(ctmp, 0, len); strcpy(ctmp, "script run "); strcpy(&ctmp[11], script_cmd); diff --git a/client/reveng/cli.c b/client/reveng/cli.c index f4b40856a..6e147ba20 100644 --- a/client/reveng/cli.c +++ b/client/reveng/cli.c @@ -377,7 +377,9 @@ ipqx: /* allocate argument array */ args = argc - optind; - if(!(apolys = malloc(args * sizeof(poly_t)))){ + + apolys = calloc(args * sizeof(poly_t), sizeof(char)); + if ( !apolys ){ uerror("cannot allocate memory for argument list"); return 0; } diff --git a/client/reveng/model.c b/client/reveng/model.c index f99b1ee02..2c58d695a 100644 --- a/client/reveng/model.c +++ b/client/reveng/model.c @@ -118,7 +118,7 @@ char * mtostr(const model_t *model) { + (checkstr && *checkstr ? strlen(checkstr) : 6) + (magicstr && *magicstr ? strlen(magicstr) : 6) + (model->name && *model->name ? 2 + strlen(model->name) : 6); - if ((string = malloc(size))) { + if ((string = calloc(size, sizeof(uint8_t)))) { sprintf(strbuf, "\"%s\"", model->name); sprintf(string, "width=%lu " diff --git a/client/reveng/poly.c b/client/reveng/poly.c index 011a09978..7056c118a 100644 --- a/client/reveng/poly.c +++ b/client/reveng/poly.c @@ -349,7 +349,7 @@ pxsubs(const poly_t poly, int flags, int bperhx, unsigned long start, unsigned l size *= cperhx; if(!size || ~flags & P_SPACE) ++size; /* for trailing null */ - if(!(sptr = string = (char *) malloc(size))) + if(!(sptr = string = (char *) calloc(size, sizeof(char)))) uerror("cannot allocate memory for string"); size = end - start; diff --git a/client/reveng/preset.c b/client/reveng/preset.c index 6dbedaed9..82a18b977 100644 --- a/client/reveng/preset.c +++ b/client/reveng/preset.c @@ -811,7 +811,9 @@ int mbynam(model_t *dest, const char *key) { if (!aliases->name) return(-1); - if (!(ukey = malloc((size_t) 1 + strlen(key) + 1))) { + + ukey = calloc((size_t) 1 + strlen(key) + 1, sizeof(char)); + if (!ukey) { uerror("[!] cannot allocate memory for comparison string"); return(0); } @@ -861,7 +863,9 @@ char * mnames(void) { ++aptr; } if (!size) return(NULL); - if ((string = malloc(size))) { + + string = calloc(size, sizeof(char)); + if (string) { aptr = aliases; sptr = string; while (aptr->name) { diff --git a/client/reveng/reveng.c b/client/reveng/reveng.c index 004a6fc3c..550dc2da5 100644 --- a/client/reveng/reveng.c +++ b/client/reveng/reveng.c @@ -173,8 +173,9 @@ modpol(const poly_t init, int rflags, int args, const poly_t *argpolys) { unsigned long alen, blen; if(args < 2) return(NULL); - - if(!(result = malloc(((((args - 1) * args) >> 1) + 1) * sizeof(poly_t)))) + + result = calloc(((((args - 1) * args) >> 1) + 1) * sizeof(poly_t), sizeof(char)); + if(!result) uerror("cannot allocate memory for codeword table"); rptr = result; @@ -240,7 +241,8 @@ engini(int *resc, model_t **result, const poly_t divisor, int flags, int args, c dlen = plen(divisor); /* Allocate the CRC matrix */ - if(!(mat = (poly_t *) malloc((dlen << 1) * sizeof(poly_t)))) + mat = (poly_t *) calloc((dlen << 1) * sizeof(poly_t), sizeof(char)); + if(!mat) uerror("cannot allocate memory for CRC matrix"); /* Find arguments of the two shortest lengths */ diff --git a/client/scandir.c b/client/scandir.c index 12bbef110..619bd72c6 100644 --- a/client/scandir.c +++ b/client/scandir.c @@ -51,7 +51,8 @@ int scandir (const char *dir, nl = ntmp; } - if (!(etmp = (struct dirent *) malloc (sizeof *ent))) { + etmp = (struct dirent *) calloc (sizeof *ent, sizeof(char)); + if (!etmp) { err_no = 1; break; } diff --git a/client/tinycbor/cborparser_dup_string.c b/client/tinycbor/cborparser_dup_string.c index 061c5ac77..202cd2022 100644 --- a/client/tinycbor/cborparser_dup_string.c +++ b/client/tinycbor/cborparser_dup_string.c @@ -105,7 +105,7 @@ CborError _cbor_value_dup_string(const CborValue *value, void **buffer, size_t * return err; ++*buflen; - *buffer = malloc(*buflen); + *buffer = calloc(*buflen, sizeof(uint8_t)); if (!*buffer) { /* out of memory */ return CborErrorOutOfMemory; diff --git a/client/tinycbor/cbortojson.c b/client/tinycbor/cbortojson.c index 5a1a2e5dc..34b900bab 100644 --- a/client/tinycbor/cbortojson.c +++ b/client/tinycbor/cbortojson.c @@ -178,7 +178,7 @@ static CborError dump_bytestring_base16(char **result, CborValue *it) return err; /* a Base16 (hex) output is twice as big as our buffer */ - buffer = (uint8_t *)malloc(n * 2 + 1); + buffer = (uint8_t *)calloc(n * 2 + 1, sizeof(uint8_t)); *result = (char *)buffer; /* let cbor_value_copy_byte_string know we have an extra byte for the terminating NUL */ @@ -204,7 +204,7 @@ static CborError generic_dump_base64(char **result, CborValue *it, const char al /* a Base64 output (untruncated) has 4 bytes for every 3 in the input */ size_t len = (n + 5) / 3 * 4; - out = buffer = (uint8_t *)malloc(len + 1); + out = buffer = (uint8_t *)calloc(len + 1, sizeof(uint8_t)); *result = (char *)buffer; /* we read our byte string at the tail end of the buffer diff --git a/client/util.c b/client/util.c index c4d6ae5a4..cea42f338 100644 --- a/client/util.c +++ b/client/util.c @@ -280,7 +280,7 @@ void sprint_bin_break_ex(uint8_t *src, size_t srclen, char *dest , uint8_t break printf("(sprint_bin_break) rowlen %d\n", rowlen); // 3072 + end of line characters if broken at 8 bits - dest = (char *)malloc(MAX_BIN_BREAK_LENGTH); + dest = (char *)calloc(MAX_BIN_BREAK_LENGTH, sizeof(uint8_t)); if (dest == NULL) return; //clear memory From 5c231e772ccb7434c58601d1c1f6968621e7a980 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 30 Jan 2019 21:53:10 +0100 Subject: [PATCH 0464/1938] chg: use calloc --- client/flash.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/flash.c b/client/flash.c index de6fdf7e6..2c06311c3 100644 --- a/client/flash.c +++ b/client/flash.c @@ -38,7 +38,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, flash_seg_t *seg; uint32_t last_end = 0; - ctx->segments = malloc(sizeof(flash_seg_t) * num_phdrs); + ctx->segments = calloc(sizeof(flash_seg_t) * num_phdrs, sizeof(uint8_t)); if (!ctx->segments) { fprintf(stderr, "Out of memory\n"); return -1; @@ -88,7 +88,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, uint8_t *data; // make extra space if we need to move the data forward - data = malloc(filesz + BLOCK_SIZE); + data = calloc(filesz + BLOCK_SIZE, sizeof(uint8_t)); if (!data) { fprintf(stderr, "Error: Out of memory\n"); return -1; @@ -111,7 +111,7 @@ static int build_segs_from_phdrs(flash_file_t *ctx, FILE *fd, Elf32_Phdr *phdrs, uint32_t new_length = this_end - prev_seg->start; uint32_t this_offset = paddr - prev_seg->start; uint32_t hole = this_offset - prev_seg->length; - uint8_t *new_data = malloc(new_length); + uint8_t *new_data = calloc(new_length, sizeof(uint8_t)); if (!new_data) { fprintf(stderr, "Error: Out of memory\n"); free(data); @@ -223,7 +223,7 @@ int flash_load(flash_file_t *ctx, const char *name, int can_write_bl) { } num_phdrs = le16(ehdr.e_phnum); - phdrs = malloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr)); + phdrs = calloc(le16(ehdr.e_phnum) * sizeof(Elf32_Phdr), sizeof(uint8_t)); if (!phdrs) { fprintf(stderr, "Out of memory\n"); goto fail; From a01aead732c5a11a8f77bf944610ea2a32b2197e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 31 Jan 2019 16:57:02 +0100 Subject: [PATCH 0465/1938] add: 'make get_xorsearch' - easy download of xorsearch by Didier Stevens, see https://blog.didierstevens.com/programs/xorsearch/ --- tools/Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/tools/Makefile b/tools/Makefile index 0a6e4430e..c750cce26 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -8,4 +8,7 @@ get_crapto1: get_nonce_bf: # git clone https://github.com/J-Run/mf_key_brute.git mf_key_brute - git clone https://github.com/iceman1001/mf_nonce_brute mf_nonce_brute \ No newline at end of file + git clone https://github.com/iceman1001/mf_nonce_brute mf_nonce_brute + +get_xorsearch: + wget -N https://didierstevens.com/files/software/XORSearch_V1_11_2.zip \ No newline at end of file From 673c080ea53ae037495b5b9ec6e17d4a293d6ac1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 18:00:08 +0200 Subject: [PATCH 0466/1938] client part --- client/cmdhf14a.c | 164 +++++++++++++++++++++++++++++++++++++++------- 1 file changed, 141 insertions(+), 23 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 4a6b7518d..d9b829e68 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- // Copyright (C) 2010 iZsh , Hagen Fritsch -// 2011, 2017 Merlok +// 2011, 2017 - 2019 Merlok // 2014, Peter Fillmore // 2015, 2016, 2017 Iceman // @@ -12,6 +12,8 @@ //----------------------------------------------------------------------------- #include "cmdhf14a.h" +bool APDUInFramingEnable = true; + static int CmdHelp(const char *Cmd); static int waitCmd(uint8_t iLen); @@ -837,15 +839,90 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav return 0; } -int CmdExchangeAPDU(uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chaining) { - uint16_t cmdc = 0; +int SelectCard14443_4(bool disconnect, iso14a_card_select_t *card) { + UsbCommand resp; - *chaining = false; + frameLength = 0; + + if (card) + memset(card, 0, sizeof(iso14a_card_select_t)); - if (activateField) { - cmdc |= ISO14A_CONNECT; + DropField(); + + // Anticollision + SELECT card + UsbCommand ca = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; + SendCommand(&ca); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + PrintAndLogEx(ERR, "Proxmark connection timeout."); + return 1; } + // check result + if (resp.arg[0] == 0) { + PrintAndLogEx(ERR, "No card in field."); + return 1; + } + + if (resp.arg[0] != 1 && resp.arg[0] != 2) { + PrintAndLogEx(ERR, "Card not in iso14443-4. res=%d.", resp.arg[0]); + return 1; + } + + if (resp.arg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision + // get ATS + UsbCommand cr = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0}}; + uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 + memcpy(cr.d.asBytes, rats, 2); + SendCommand(&cr); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + PrintAndLogEx(ERR, "Proxmark connection timeout."); + return 1; + } + + if (resp.arg[0] <= 0) { // ats_len + PrintAndLogEx(ERR, "Can't get ATS."); + return 1; + } + + // get frame length from ATS in data field + if (resp.arg[0] > 1) { + uint8_t fsci = resp.d.asBytes[1] & 0x0f; + if (fsci < sizeof(atsFSC)) + frameLength = atsFSC[fsci]; + } + } else { + // get frame length from ATS in card data structure + iso14a_card_select_t *vcard = (iso14a_card_select_t *) resp.d.asBytes; + if (vcard->ats_len > 1) { + uint8_t fsci = vcard->ats[1] & 0x0f; + if (fsci < sizeof(atsFSC)) + frameLength = atsFSC[fsci]; + } + + if (card) + memcpy(card, vcard, sizeof(iso14a_card_select_t)); + } + + if (disconnect) + DropField(); + + return 0; +} + +int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chainingout) { + *chainingout = false; + + if (activateField) { + // select with no disconnect and set frameLength + int selres = SelectCard14443_4(false, NULL); + if (selres) + return selres; + } + + uint16_t cmdc = 0; + if (chainingin) + cmdc = ISO14A_SEND_CHAINING; + // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes // https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size // here length USB_CMD_DATA_SIZE=512 @@ -857,18 +934,6 @@ int CmdExchangeAPDU(uint8_t *datain, int datainlen, bool activateField, uint8_t uint8_t *recv; UsbCommand resp; - if (activateField) { - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(ERR, "APDU: Proxmark connection timeout."); - return 1; - } - if (resp.arg[0] != 1) { - PrintAndLogEx(ERR, "APDU: Proxmark error %d.", resp.arg[0]); - DropField(); - return 1; - } - } - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { recv = resp.d.asBytes; int iLen = resp.arg[0]; @@ -884,13 +949,20 @@ int CmdExchangeAPDU(uint8_t *datain, int datainlen, bool activateField, uint8_t return 2; } + // I-block ACK + if ((res & 0xf2) == 0xa2) { + *dataoutlen = 0; + *chainingout = true; + return 0; + } + if(!iLen) { PrintAndLogEx(ERR, "APDU: No APDU response."); return 1; } // check apdu length - if (iLen < 4 && iLen >= 0) { + if (iLen < 2 && iLen >= 0) { PrintAndLogEx(ERR, "APDU: Small APDU response. Len=%d", iLen); return 2; } @@ -905,7 +977,7 @@ int CmdExchangeAPDU(uint8_t *datain, int datainlen, bool activateField, uint8_t // chaining if ((res & 0x10) != 0) { - *chaining = true; + *chainingout = true; } // CRC Check @@ -924,12 +996,58 @@ int CmdExchangeAPDU(uint8_t *datain, int datainlen, bool activateField, uint8_t int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { *dataoutlen = 0; bool chaining = false; - - int res = CmdExchangeAPDU(datain, datainlen, activateField, dataout, maxdataoutlen, dataoutlen, &chaining); + int res; +printf("framelen=%d datainlen=%d\n", frameLength, datainlen); + // 3 byte here - 1b framing header, 2b crc16 + if (APDUInFramingEnable && + ( (frameLength && (datainlen > frameLength - 3)) || (datainlen > USB_CMD_DATA_SIZE - 3)) ) { + int clen = 0; + + bool vActivateField = activateField; + + do { + int vlen = MIN(frameLength - 3, datainlen - clen); + bool chainBlockNotLast = ((clen + vlen) < datainlen); + + *dataoutlen = 0; + res = CmdExchangeAPDU(chainBlockNotLast, &datain[clen], vlen, vActivateField, dataout, maxdataoutlen, dataoutlen, &chaining); + if (res) { + if (!leaveSignalON) + DropField(); + + return 200; + } + + // check R-block ACK + if ((*dataoutlen == 0) && (*dataoutlen != 0 || chaining != chainBlockNotLast)) { + if (!leaveSignalON) + DropField(); + + return 201; + } + + clen += vlen; + vActivateField = false; + if (*dataoutlen) { + if (clen != datainlen) + PrintAndLogEx(WARNING, "APDU: I-block/R-block sequence error. Data len=%d, Sent=%d, Last packet len=%d", datainlen, clen, *dataoutlen); + break; + } + } while (clen < datainlen); + } else { + res = CmdExchangeAPDU(false, datain, datainlen, activateField, dataout, maxdataoutlen, dataoutlen, &chaining); + if (res) { + if (!leaveSignalON) + DropField(); + + return res; + } + } + while (chaining) { // I-block with chaining - res = CmdExchangeAPDU(NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining); + res = CmdExchangeAPDU(false, NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining); if (res) { if (!leaveSignalON) From 09c5f0ef7638d5d536e72d1276dbb18e7ceb208d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 18:12:01 +0200 Subject: [PATCH 0467/1938] remove debug and small output addon. errors was not visible --- client/cmdhf14a.c | 1 - client/fido/fidocore.c | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index d9b829e68..cff3eb61e 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -998,7 +998,6 @@ int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool lea bool chaining = false; int res; -printf("framelen=%d datainlen=%d\n", frameLength, datainlen); // 3 byte here - 1b framing header, 2b crc16 if (APDUInFramingEnable && ( (frameLength && (datainlen > frameLength - 3)) || (datainlen > USB_CMD_DATA_SIZE - 3)) ) { diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index ee39fbbe9..f83e64944 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -250,9 +250,9 @@ int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint8_t *pu uint32_t verifyflags = 0; res = mbedtls_x509_crt_verify(&cert, &cacert, NULL, NULL, &verifyflags, NULL, NULL); if (res) { - PrintAndLog("ERROR: DER verify returned 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res)); + PrintAndLog("ERROR: DER verify returned 0x%x - %s\n", (res<0)?-res:res, ecdsa_get_error(res)); } else { - PrintAndLog("Certificate OK."); + PrintAndLog("Certificate OK.\n"); } if (verbose) { From 34bae8adcf18d503d36c84c29ad7f27bdb95e877 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 18:51:53 +0200 Subject: [PATCH 0468/1938] add `hf 14a chaining` --- client/cmdhf14a.c | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index cff3eb61e..c38a876e8 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -1323,6 +1323,37 @@ int CmdHF14AAntiFuzz(const char *cmd) { return 0; } +int CmdHF14AChaining(const char *cmd) { + + CLIParserInit("hf 14a chaining", + "Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.", + "Usage:\n" + "\thf 14a chaining disable -> disable chaining\n" + "\thf 14a chaining -> show chaining enable/disable state\n"); + + void* argtable[] = { + arg_param_begin, + arg_str0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + struct arg_str *str = arg_get_str(1); + int len = arg_get_str_len(1); + + if (len && (!strcmp(str->sval[0], "enable") || !strcmp(str->sval[0], "1"))) + APDUInFramingEnable = true; + + if (len && (!strcmp(str->sval[0], "disable") || !strcmp(str->sval[0], "0"))) + APDUInFramingEnable = false; + + CLIParserFree(); + + PrintAndLogEx(INFO, "\nISO 14443-4 input chaining %s.\n", APDUInFramingEnable ? "enabled" : "disabled"); + + return 0; +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"list", CmdHF14AList, 0, "[Deprecated] List ISO 14443-a history"}, @@ -1332,6 +1363,7 @@ static command_t CommandTable[] = { {"sim", CmdHF14ASim, 0, " -- Simulate ISO 14443-a tag"}, {"sniff", CmdHF14ASniff, 0, "sniff ISO 14443-a traffic"}, {"apdu", CmdHF14AAPDU, 0, "Send ISO 14443-4 APDU to tag"}, + {"chaining", CmdHF14AChaining, 0, "Control ISO 14443-4 input chaining"}, {"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"}, {"antifuzz", CmdHF14AAntiFuzz, 0, "Fuzzing the anticollision phase. Warning! Readers may react strange"}, {NULL, NULL, 0, NULL} From 029e75e866b9bb9abd97e4ab170e3ade7f8ecbc8 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Feb 2019 18:54:57 +0200 Subject: [PATCH 0469/1938] formatting --- client/cmdhf14a.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index c38a876e8..9140a3502 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -1358,13 +1358,13 @@ static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"list", CmdHF14AList, 0, "[Deprecated] List ISO 14443-a history"}, {"info", CmdHF14AInfo, 0, "Tag information"}, - {"reader", CmdHF14AReader, 0, "Act like an ISO14443-a reader"}, + {"reader", CmdHF14AReader, 0, "Act like an ISO14443-a reader"}, {"cuids", CmdHF14ACUIDs, 0, " Collect n>0 ISO14443-a UIDs in one go"}, - {"sim", CmdHF14ASim, 0, " -- Simulate ISO 14443-a tag"}, + {"sim", CmdHF14ASim, 0, " -- Simulate ISO 14443-a tag"}, {"sniff", CmdHF14ASniff, 0, "sniff ISO 14443-a traffic"}, {"apdu", CmdHF14AAPDU, 0, "Send ISO 14443-4 APDU to tag"}, {"chaining", CmdHF14AChaining, 0, "Control ISO 14443-4 input chaining"}, - {"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"}, + {"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"}, {"antifuzz", CmdHF14AAntiFuzz, 0, "Fuzzing the anticollision phase. Warning! Readers may react strange"}, {NULL, NULL, 0, NULL} }; From 77f4492433f170db1f1bd06eba0d3bb09be4531b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 2 Feb 2019 19:30:32 +0100 Subject: [PATCH 0470/1938] fix: 'hf 15 write' - faulty string formatter token --- client/cmdhf15.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index d8a212130..a1b55d7c6 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -1241,7 +1241,7 @@ int CmdHF15Write(const char *Cmd) { AddCrc(req, reqlen); c.arg[0] = reqlen+2; - PrintAndLogEx(NORMAL, "iso15693 writing to page %02d (0x&02X) | data ", pagenum, pagenum); + PrintAndLogEx(NORMAL, "iso15693 writing to page %02d (0x%02X) | data ", pagenum, pagenum); clearCommandBuffer(); SendCommand(&c); From 95db68fa30af72786f58cd08d1abdc9084c46669 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 3 Feb 2019 10:18:22 +0100 Subject: [PATCH 0471/1938] FIX: scripts path needed for scripts to call other scripts. --- client/scripting.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/client/scripting.c b/client/scripting.c index 3d3518ced..b6bb80f33 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -758,6 +758,15 @@ int set_pm3_libraries(lua_State *L) { //-- remove the global environment table from the stack lua_pop(L, 1); + + //--add to the LUA_PATH (package.path in lua) + // so we can load scripts from the ./scripts/ - directory + char scripts_path[strlen(get_my_executable_directory()) + strlen(LUA_SCRIPTS_DIRECTORY) + strlen(LUA_LIBRARIES_WILDCARD) + 1]; + strcpy(scripts_path, get_my_executable_directory()); + strcat(scripts_path, LUA_SCRIPTS_DIRECTORY); + strcat(scripts_path, LUA_LIBRARIES_WILDCARD); + setLuaPath(L, scripts_path); + //-- Last but not least, add to the LUA_PATH (package.path in lua) // so we can load libraries from the ./lualib/ - directory char libraries_path[strlen(get_my_executable_directory()) + strlen(LUA_LIBRARIES_DIRECTORY) + strlen(LUA_LIBRARIES_WILDCARD) + 1]; @@ -765,6 +774,5 @@ int set_pm3_libraries(lua_State *L) { strcat(libraries_path, LUA_LIBRARIES_DIRECTORY); strcat(libraries_path, LUA_LIBRARIES_WILDCARD); setLuaPath(L, libraries_path); - return 1; } \ No newline at end of file From 7678ab13e0b2bae4d8a58ae1194ffa6379700d73 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Sun, 3 Feb 2019 22:36:15 +0200 Subject: [PATCH 0472/1938] add slolkey CA root --- client/fido/additional_ca.c | 19 ++++++++++++++++++- 1 file changed, 18 insertions(+), 1 deletion(-) diff --git a/client/fido/additional_ca.c b/client/fido/additional_ca.c index f529e99b5..564eda2ae 100644 --- a/client/fido/additional_ca.c +++ b/client/fido/additional_ca.c @@ -58,6 +58,23 @@ "U9psmyPzK+Vsgw2jeRQ5JlKDyqE0hebfC1tvFu0CCrJFcw==\r\n" \ "-----END CERTIFICATE-----\r\n" +// Name: SoloKey U2F Root CA Serial 14143382635911888524 (0xc44763928ff4be8c) +// Issued: 2018-11-11 +#define SOLOKEY_CA \ +"-----BEGIN CERTIFICATE-----\r\n" \ +"MIIB9DCCAZoCCQDER2OSj/S+jDAKBggqhkjOPQQDAjCBgDELMAkGA1UEBhMCVVMx\r\n" \ +"ETAPBgNVBAgMCE1hcnlsYW5kMRIwEAYDVQQKDAlTb2xvIEtleXMxEDAOBgNVBAsM\r\n" \ +"B1Jvb3QgQ0ExFTATBgNVBAMMDHNvbG9rZXlzLmNvbTEhMB8GCSqGSIb3DQEJARYS\r\n" \ +"aGVsbG9Ac29sb2tleXMuY29tMCAXDTE4MTExMTEyNTE0MloYDzIwNjgxMDI5MTI1\r\n" \ +"MTQyWjCBgDELMAkGA1UEBhMCVVMxETAPBgNVBAgMCE1hcnlsYW5kMRIwEAYDVQQK\r\n" \ +"DAlTb2xvIEtleXMxEDAOBgNVBAsMB1Jvb3QgQ0ExFTATBgNVBAMMDHNvbG9rZXlz\r\n" \ +"LmNvbTEhMB8GCSqGSIb3DQEJARYSaGVsbG9Ac29sb2tleXMuY29tMFkwEwYHKoZI\r\n" \ +"zj0CAQYIKoZIzj0DAQcDQgAEWHAN0CCJVZdMs0oktZ5m93uxmB1iyq8ELRLtqVFL\r\n" \ +"SOiHQEab56qRTB/QzrpGAY++Y2mw+vRuQMNhBiU0KzwjBjAKBggqhkjOPQQDAgNI\r\n" \ +"ADBFAiEAz9SlrAXIlEu87vra54rICPs+4b0qhp3PdzcTg7rvnP0CIGjxzlteQQx+\r\n" \ +"jQGd7rwSZuE5RWUPVygYhUstQO9zNUOs\r\n" \ +"-----END CERTIFICATE-----\r\n" + /* Concatenation of all additional CA certificates in PEM format if available */ -const char additional_ca_pem[] = GLOBALSIGN_CA YUBICO_CA; +const char additional_ca_pem[] = GLOBALSIGN_CA YUBICO_CA SOLOKEY_CA; const size_t additional_ca_pem_len = sizeof(additional_ca_pem); From 75aeec65072b47694d51796aa7581ced2f0b9fda Mon Sep 17 00:00:00 2001 From: bogiton <34060135+bogiton@users.noreply.github.com> Date: Mon, 4 Feb 2019 17:44:29 +0000 Subject: [PATCH 0473/1938] Add led blink on successful flash write --- armsrc/Standalone/hf_bog.c | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/armsrc/Standalone/hf_bog.c b/armsrc/Standalone/hf_bog.c index 9079d5df3..65254bd5c 100644 --- a/armsrc/Standalone/hf_bog.c +++ b/armsrc/Standalone/hf_bog.c @@ -271,6 +271,11 @@ void RAMFUNC SniffAndStore(uint8_t param) { uint16_t writelen = Flash_WriteData(0, total_data, memoffset + 4 * auth_attempts); if (MF_DBGLEVEL > 1) Dbprintf("[!] Wrote %u bytes into flash mem", writelen); + // If pwd saved successfully, blink led A three times + if (writelen > 0) { + SpinErr(0, 200, 5); // blink led A + } + SpinDelay(100); // Reset the SPI Baudrate to the default value (24MHz) From cd44ea27b785d693a03689cb709d5cefd13c0537 Mon Sep 17 00:00:00 2001 From: "osboxes.org" Date: Mon, 4 Feb 2019 22:16:12 +0100 Subject: [PATCH 0474/1938] FIX: 'script run mifare_autopwn' - now doesn't crash --- client/scripts/mifare_autopwn.lua | 46 ++++++++++++++++++++++--------- client/scripts/remagic.lua | 1 + 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/client/scripts/mifare_autopwn.lua b/client/scripts/mifare_autopwn.lua index 9bd149a55..738ca6950 100644 --- a/client/scripts/mifare_autopwn.lua +++ b/client/scripts/mifare_autopwn.lua @@ -12,8 +12,10 @@ This is a script which automates cracking and dumping mifare classic cards. It s place by the device. Arguments: - -d debug logging on - -h this help + -h this help + -d debug logging on + -k known key for Sector 0 , keytype A + Output files from this operation: .eml - emulator file @@ -73,12 +75,12 @@ local function nested(key,sak) if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k typ = 4 elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K - typ= 1 + typ = 1 elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k typ = 0 - elseif 0x10 == sak then-- "NXP MIFARE Plus 2k" + elseif 0x10 == sak then-- "NXP MIFARE Plus 2k" typ = 2 - elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K" + elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K" typ = 1 else print("I don't know how many sectors there are on this type of card, defaulting to 16") @@ -87,22 +89,40 @@ local function nested(key,sak) core.console(cmd) end -local function dump(uid) +local function dump(uid, numsectors) dbg('dumping tag memory') + local typ = 1 + if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k + typ = 4 + elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K + typ = 1 + elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k + typ = 0 + elseif 0x10 == sak then-- "NXP MIFARE Plus 2k" + typ = 2 + elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K" + typ = 1 + end + if utils.confirm('Do you wish to create a memory dump of tag?') then - core.console("hf mf dump") + local dumpfile = 'hf-mf-'..uid..'-data.bin' + + local dmp = ('hf mf dump %s f %s'):format(typ, dumpfile) + core.console(dmp) + -- Save the global args, those are *our* arguments local myargs = args -- Set the arguments for htmldump script - args =("-o %s.html"):format(uid) + args =('-i %s -o %s.html'):format(dumpfile, uid) -- call it - require('../scripts/htmldump') + require('htmldump') - args ="" -- dump to emulator - require('../scripts/dumptoemul') + args =('-i %s -o %s.eml'):format(dumpfile, uid) + require('dumptoemul') + -- Set back args. Not that it's used, just for the karma... args = myargs end @@ -177,9 +197,9 @@ local function main(args) print("Found valid key: "..key); end -- Use nested attack - nested(key,sak) + nested(key, sak) -- Dump info - dump(uid) + dump(uid, sak) if #key == 12 then exit = true end else diff --git a/client/scripts/remagic.lua b/client/scripts/remagic.lua index 5062d8cf4..10e25583a 100644 --- a/client/scripts/remagic.lua +++ b/client/scripts/remagic.lua @@ -72,6 +72,7 @@ local function sendCmds( cmds ) if cmds[i] then print ( cmds[i] ) core.console( cmds[i] ) + core.clearCommandBuffer() end end end From 0e5d8968938199b91c760921ebf1b0428747530a Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 5 Feb 2019 18:27:48 +0200 Subject: [PATCH 0475/1938] fix endless loop --- armsrc/iso14443a.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 082d378ac..e63cd5e74 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2248,7 +2248,7 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, u return 0; //DATA LINK ERROR } else{ // S-Block WTX - while((data_bytes[0] & 0xF2) == 0xF2) { + while(len && ((data_bytes[0] & 0xF2) == 0xF2)) { uint32_t save_iso14a_timeout = iso14a_get_timeout(); // temporarily increase timeout iso14a_set_timeout( MAX((data_bytes[1] & 0x3f) * save_iso14a_timeout, MAX_ISO14A_TIMEOUT) ); From 69f3e65dd0c8a1f1f95c4bbb0b975205f57c40c1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 5 Feb 2019 18:39:03 +0200 Subject: [PATCH 0476/1938] fix memmove if len=0 --- armsrc/iso14443a.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index e63cd5e74..4267d28af 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -2266,32 +2266,34 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, u iso14a_set_timeout(save_iso14a_timeout); } - // if we received an I- or R(ACK)-Block with a block number equal to the - // current block number, toggle the current block number + // if we received an I- or R(ACK)-Block with a block number equal to the + // current block number, toggle the current block number if (len >= 3 // PCB+CRC = 3 bytes && ((data_bytes[0] & 0xC0) == 0 // I-Block || (data_bytes[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0 && (data_bytes[0] & 0x01) == iso14_pcb_blocknum) // equal block numbers - { - iso14_pcb_blocknum ^= 1; - } + { + iso14_pcb_blocknum ^= 1; + } // if we received I-block with chaining we need to send ACK and receive another block of data if (res) *res = data_bytes[0]; // crc check - if (len >=3 && !check_crc(CRC_14443_A, data_bytes, len)) { + if (len >= 3 && !check_crc(CRC_14443_A, data_bytes, len)) { return -1; } } - // cut frame byte - len -= 1; - // memmove(data_bytes, data_bytes + 1, len); - for (int i = 0; i < len; i++) - data_bytes[i] = data_bytes[i + 1]; + if (len) { + // cut frame byte + len -= 1; + // memmove(data_bytes, data_bytes + 1, len); + for (int i = 0; i < len; i++) + data_bytes[i] = data_bytes[i + 1]; + } return len; } From 7934630d2bfa3768e23b0aed43f72ca830a520cd Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 14 Feb 2019 19:27:39 +0100 Subject: [PATCH 0477/1938] FIX: Makefile bad styled calls --- armsrc/Makefile | 4 ++-- client/Makefile | 16 ++++++++-------- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/armsrc/Makefile b/armsrc/Makefile index 76f3a0173..efc443227 100644 --- a/armsrc/Makefile +++ b/armsrc/Makefile @@ -21,7 +21,7 @@ APP_CFLAGS = -DWITH_CRC \ -DWITH_ISO14443a \ -DWITH_ICLASS \ -DWITH_FELICA \ - -DWITH_FLASH \ + -DWITH_FLASH \ -DWITH_SMARTCARD \ -DWITH_FPC \ -DWITH_HFSNOOP \ @@ -191,7 +191,7 @@ $(OBJDIR)/fpga_all.bit.z: $(FPGA_BITSTREAMS) $(FPGA_COMPRESSOR) $(FPGA_COMPRESSOR) $(filter %.bit,$^) $@ $(FPGA_COMPRESSOR): - make -C ../client $(notdir $(FPGA_COMPRESSOR)) + $(MAKE) -C ../client $(notdir $(FPGA_COMPRESSOR)) $(OBJDIR)/fullimage.stage1.elf: $(VERSIONOBJ) $(OBJDIR)/fpga_all.o $(THUMBOBJ) $(ARMOBJ) $(CC) $(LDFLAGS) -Wl,-T,ldscript,-Map,$(patsubst %.elf,%.map,$@) -o $@ $^ $(LIBS) diff --git a/client/Makefile b/client/Makefile index 4f7168fa0..0b19d4599 100644 --- a/client/Makefile +++ b/client/Makefile @@ -299,29 +299,29 @@ lualibs/mf_default_keys.lua : default_keys.dic clean: $(RM) $(CLEAN) - cd ../liblua && make clean - cd $(JANSSONLIBPATH) && make clean - cd $(MBEDTLSLIBPATH) && make clean - cd $(CBORLIBPATH) && make clean + cd ../liblua && $(MAKE) clean + cd $(JANSSONLIBPATH) && $(MAKE) clean + cd $(MBEDTLSLIBPATH) && $(MAKE) clean + cd $(CBORLIBPATH) && $(MAKE) clean tarbin: $(BINS) $(TAR) $(TARFLAGS) ../proxmark3-$(platform)-bin.tar $(BINS:%=client/%) $(WINBINS:%=client/%) lua_build: @echo Compiling liblua, using platform $(LUAPLATFORM) - cd ../liblua && make $(LUAPLATFORM) + cd ../liblua && $(MAKE) $(LUAPLATFORM) jansson_build: @echo Compiling jansson - cd $(JANSSONLIBPATH) && make all + cd $(JANSSONLIBPATH) && $(MAKE) all mbedtls_build: @echo Compiling mbedtls - cd $(MBEDTLSLIBPATH) && make all + cd $(MBEDTLSLIBPATH) && $(MAKE) all cbor_build: @echo Compiling tinycbor - cd $(CBORLIBPATH) && make all + cd $(CBORLIBPATH) && $(MAKE) all .PHONY: all clean From 35df317a2cae5610c9b94fdcd0718916eb9257ad Mon Sep 17 00:00:00 2001 From: vratiskol Date: Fri, 15 Feb 2019 01:08:30 +0100 Subject: [PATCH 0478/1938] Update MAXBLOCK - MF 4K - Modify MAXBLOCK size: 4k => 256 - Typo --- client/cmdhfmf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index a26381930..32fd65872 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -11,7 +11,7 @@ #include "cmdhfmf.h" #include "mifare4.h" -#define MIFARE_4K_MAXBLOCK 255 +#define MIFARE_4K_MAXBLOCK 256 #define MIFARE_2K_MAXBLOCK 128 #define MIFARE_1K_MAXBLOCK 64 #define MIFARE_MINI_MAXBLOCK 20 @@ -2503,7 +2503,7 @@ int CmdHF14AMfESave(const char *Cmd) { } memset(dump, 0, bytes); - PrintAndLogEx(INFO, "dowingloading from emulator memory"); + PrintAndLogEx(INFO, "downloading from emulator memory"); if (!GetFromDevice( BIG_BUF_EML, dump, bytes, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); free(dump); From f8985ed1be1179437b6cf669559585d0b5e0d7f0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 15 Feb 2019 12:38:38 +0100 Subject: [PATCH 0479/1938] chg: remove warning for overflow --- client/cmdhfmf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index a26381930..55f2b03df 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -645,7 +645,7 @@ int CmdHF14AMfRdSc(const char *Cmd) { return 0; } -uint8_t NumOfBlocks(char card){ +uint16_t NumOfBlocks(char card){ switch(card){ case '0' : return MIFARE_MINI_MAXBLOCK; case '1' : return MIFARE_1K_MAXBLOCK; From 8e6b41f513e4aac14845a507a6bf52c6df93c303 Mon Sep 17 00:00:00 2001 From: vratiskol Date: Fri, 15 Feb 2019 15:17:28 +0100 Subject: [PATCH 0480/1938] Use Variable for MIFARE_MINI_MAXSECTOR Modify type uint16_t => 256 --- client/cmdhfmf.c | 41 +++++++++++++++++++++++------------------ 1 file changed, 23 insertions(+), 18 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 32fd65872..8129aceb6 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -16,6 +16,11 @@ #define MIFARE_1K_MAXBLOCK 64 #define MIFARE_MINI_MAXBLOCK 20 +#define MIFARE_MINI_MAXSECTOR 5 +#define MIFARE_1K_MAXSECTOR 16 +#define MIFARE_2K_MAXSECTOR 32 +#define MIFARE_4K_MAXSECTOR 40 + static int CmdHelp(const char *Cmd); int usage_hf14_ice(void){ @@ -591,7 +596,7 @@ int CmdHF14AMfRdSc(const char *Cmd) { } sectorNo = param_get8(Cmd, 0); - if (sectorNo > 39) { + if (sectorNo > MIFARE_4K_MAXSECTOR ) { PrintAndLogEx(NORMAL, "Sector number must be less than 40"); return 1; } @@ -645,7 +650,7 @@ int CmdHF14AMfRdSc(const char *Cmd) { return 0; } -uint8_t NumOfBlocks(char card){ +uint16_t NumOfBlocks(char card){ switch(card){ case '0' : return MIFARE_MINI_MAXBLOCK; case '1' : return MIFARE_1K_MAXBLOCK; @@ -656,11 +661,11 @@ uint8_t NumOfBlocks(char card){ } uint8_t NumOfSectors(char card){ switch(card){ - case '0' : return 5; - case '1' : return 16; - case '2' : return 32; - case '4' : return 40; - default : return 16; + case '0' : return MIFARE_MINI_MAXSECTOR; + case '1' : return MIFARE_1K_MAXSECTOR; + case '2' : return MIFARE_2K_MAXSECTOR; + case '4' : return MIFARE_4K_MAXSECTOR; + default : return MIFARE_1K_MAXSECTOR; } } @@ -1497,11 +1502,11 @@ int CmdHF14AMfChk_fast(const char *Cmd) { // sectors switch(ctmp) { - case '0': sectorsCnt = 5; break; - case '1': sectorsCnt = 16; break; - case '2': sectorsCnt = 32; break; - case '4': sectorsCnt = 40; break; - default: sectorsCnt = 16; + case '0': sectorsCnt = MIFARE_MINI_MAXSECTOR; break; + case '1': sectorsCnt = MIFARE_1K_MAXSECTOR; break; + case '2': sectorsCnt = MIFARE_2K_MAXSECTOR; break; + case '4': sectorsCnt = MIFARE_4K_MAXSECTOR; break; + default: sectorsCnt = MIFARE_1K_MAXSECTOR; } for (i = 1; param_getchar(Cmd, i); i++) { @@ -2412,14 +2417,14 @@ int CmdHF14AMfELoad(const char *Cmd) { return usage_hf14_eload(); switch (c) { - case '0' : numBlocks = 5*4; break; + case '0' : numBlocks = MIFARE_MINI_MAXBLOCK; break; case '1' : - case '\0': numBlocks = 16*4; break; - case '2' : numBlocks = 32*4; break; - case '4' : numBlocks = 256; break; + case '\0': numBlocks = MIFARE_1K_MAXBLOCK; break; + case '2' : numBlocks = MIFARE_2K_MAXBLOCK; break; + case '4' : numBlocks = MIFARE_4K_MAXBLOCK; break; case 'u' : numBlocks = 255; blockWidth = 4; break; default: { - numBlocks = 16*4; + numBlocks = MIFARE_1K_MAXBLOCK; nameParamNo = 0; } } @@ -2761,7 +2766,7 @@ int CmdHF14AMfCLoad(const char *Cmd) { blockNum++; // magic card type - mifare 1K - if (blockNum >= 16 * 4) break; + if (blockNum >= MIFARE_1K_MAXBLOCK ) break; } PrintAndLogEx(NORMAL, "\n"); From 77eaa360930ca3d9efb7db8adaaf5df2b9444894 Mon Sep 17 00:00:00 2001 From: Iceman Date: Sun, 17 Feb 2019 11:07:48 +0100 Subject: [PATCH 0481/1938] Update README.md --- README.md | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index effdc0f6e..c8c04f852 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,14 @@ This fork now compiles just fine on ## KALI and ARCHLINUX users Kali and ArchLinux users usually must kill their modem manager in order for the proxmark3 to enumerate properly. -`sudo apt remove modemmanager` +```sh +sudo apt remove modemmanager +``` +or +```sh +systemctl stop ModemManager +systemctl disable ModemManager +``` ## Setup and build for UBUNTU GC made updates to allow this to build easily on Ubuntu 14.04.2 LTS, 15.10 or 16.04 From 535d4e6ee9e2ab49b130acafe1440aaaab4d1048 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 17 Feb 2019 15:37:20 +0100 Subject: [PATCH 0482/1938] FIX: usb slow for posix systems - https://github.com/Proxmark/proxmark3/pull/787 (@fl0-0) --- uart/uart_posix.c | 543 +++++++++++++++++++++++----------------------- 1 file changed, 273 insertions(+), 270 deletions(-) diff --git a/uart/uart_posix.c b/uart/uart_posix.c index cb878a4f0..88397fa5f 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -70,338 +70,341 @@ typedef struct { // Set time-out on 30 miliseconds const struct timeval timeout = { .tv_sec = 0, // 0 second - .tv_usec = 300000 // 300 000 micro seconds + .tv_usec = 30000 // 30 000 micro seconds }; -serial_port uart_open(const char* pcPortName) -{ - serial_port_unix* sp = calloc(sizeof(serial_port_unix), sizeof(uint8_t)); - if (sp == 0) return INVALID_SERIAL_PORT; +serial_port uart_open(const char* pcPortName) { + serial_port_unix* sp = calloc(sizeof(serial_port_unix), sizeof(uint8_t)); + if (sp == 0) return INVALID_SERIAL_PORT; - if (memcmp(pcPortName, "tcp:", 4) == 0) { - struct addrinfo *addr, *rp; - char *addrstr = strdup(pcPortName + 4); + if (memcmp(pcPortName, "tcp:", 4) == 0) { + struct addrinfo *addr, *rp; + char *addrstr = strdup(pcPortName + 4); - if (addrstr == NULL) { - printf("Error: strdup\n"); - return INVALID_SERIAL_PORT; - } + if (addrstr == NULL) { + printf("Error: strdup\n"); + return INVALID_SERIAL_PORT; + } - char *colon = strrchr(addrstr, ':'); - char *portstr; - if (colon) { - portstr = colon + 1; - *colon = '\0'; - } else { - portstr = "7901"; + timeout.tv_usec = 300000 // 300 000 micro seconds + + char *colon = strrchr(addrstr, ':'); + char *portstr; + if (colon) { + portstr = colon + 1; + *colon = '\0'; + } else { + portstr = "7901"; + } + + int s = getaddrinfo(addrstr, portstr, NULL, &addr); + if (s != 0) { + printf("Error: getaddrinfo: %s\n", gai_strerror(s)); + return INVALID_SERIAL_PORT; + } + + int sfd; + for (rp = addr; rp != NULL; rp = rp->ai_next) { + sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + + if (sfd == -1) + continue; + + if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) + break; + + close(sfd); + } + + if (rp == NULL) { /* No address succeeded */ + printf("Error: Could not connect\n"); + return INVALID_SERIAL_PORT; + } + + freeaddrinfo(addr); + free(addrstr); + + sp->fd = sfd; + + int one = 1; + setsockopt(sp->fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)); + return sp; } - - int s = getaddrinfo(addrstr, portstr, NULL, &addr); - if (s != 0) { - printf("Error: getaddrinfo: %s\n", gai_strerror(s)); - return INVALID_SERIAL_PORT; - } - - int sfd; - for (rp = addr; rp != NULL; rp = rp->ai_next) { - sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - - if (sfd == -1) - continue; - - if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) - break; - - close(sfd); - } - - if (rp == NULL) { /* No address succeeded */ - printf("Error: Could not connect\n"); - return INVALID_SERIAL_PORT; - } - - freeaddrinfo(addr); - free(addrstr); - - sp->fd = sfd; - - int one = 1; - setsockopt(sp->fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)); - return sp; - } - sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); - if(sp->fd == -1) { - uart_close(sp); - return INVALID_SERIAL_PORT; - } + sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); + if(sp->fd == -1) { + uart_close(sp); + return INVALID_SERIAL_PORT; + } - // Finally figured out a way to claim a serial port interface under unix - // We just try to set a (advisory) lock on the file descriptor - struct flock fl; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_pid = getpid(); - - // Does the system allows us to place a lock on this file descriptor - if (fcntl(sp->fd, F_SETLK, &fl) == -1) { - // A conflicting lock is held by another process - free(sp); - return CLAIMED_SERIAL_PORT; - } + // Finally figured out a way to claim a serial port interface under unix + // We just try to set a (advisory) lock on the file descriptor + struct flock fl; + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_pid = getpid(); + + // Does the system allows us to place a lock on this file descriptor + if (fcntl(sp->fd, F_SETLK, &fl) == -1) { + // A conflicting lock is held by another process + free(sp); + return CLAIMED_SERIAL_PORT; + } + + // Try to retrieve the old (current) terminal info struct + if(tcgetattr(sp->fd,&sp->tiOld) == -1) { + uart_close(sp); + return INVALID_SERIAL_PORT; + } + + // Duplicate the (old) terminal info struct + sp->tiNew = sp->tiOld; + + // Configure the serial port + sp->tiNew.c_cflag = CS8 | CLOCAL | CREAD; + sp->tiNew.c_iflag = IGNPAR; + sp->tiNew.c_oflag = 0; + sp->tiNew.c_lflag = 0; + + // Block until n bytes are received + sp->tiNew.c_cc[VMIN] = 0; + // Block until a timer expires (n * 100 mSec.) + sp->tiNew.c_cc[VTIME] = 0; + + // Try to set the new terminal info struct + if(tcsetattr(sp->fd, TCSANOW, &sp->tiNew) == -1) { + uart_close(sp); + return INVALID_SERIAL_PORT; + } - // Try to retrieve the old (current) terminal info struct - if(tcgetattr(sp->fd,&sp->tiOld) == -1) { - uart_close(sp); - return INVALID_SERIAL_PORT; - } - - // Duplicate the (old) terminal info struct - sp->tiNew = sp->tiOld; - - // Configure the serial port - sp->tiNew.c_cflag = CS8 | CLOCAL | CREAD; - sp->tiNew.c_iflag = IGNPAR; - sp->tiNew.c_oflag = 0; - sp->tiNew.c_lflag = 0; - - // Block until n bytes are received - sp->tiNew.c_cc[VMIN] = 0; - // Block until a timer expires (n * 100 mSec.) - sp->tiNew.c_cc[VTIME] = 0; - - // Try to set the new terminal info struct - if(tcsetattr(sp->fd, TCSANOW, &sp->tiNew) == -1) { - uart_close(sp); - return INVALID_SERIAL_PORT; - } - // Flush all lingering data that may exist tcflush(sp->fd, TCIOFLUSH); #ifdef WITH_FPC if ( uart_set_speed(sp, 115200) ) { - printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n"); + printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n"); } else { uart_set_speed(sp, 9600); printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n"); } #else - // set speed, works for UBUNTU 14.04 - bool success = uart_set_speed(sp, 460800); - if (success) { - printf("[=] UART Setting serial baudrate 460800\n"); - } else { - uart_set_speed(sp, 115200); - printf("[=] UART Setting serial baudrate 115200\n"); - } + // set speed, works for UBUNTU 14.04 + bool success = uart_set_speed(sp, 460800); + if (success) { + printf("[=] UART Setting serial baudrate 460800\n"); + } else { + uart_set_speed(sp, 115200); + printf("[=] UART Setting serial baudrate 115200\n"); + } #endif - return sp; + return sp; } void uart_close(const serial_port sp) { - serial_port_unix* spu = (serial_port_unix*)sp; - tcflush(spu->fd, TCIOFLUSH); - tcsetattr(spu->fd, TCSANOW, &(spu->tiOld)); - struct flock fl; - fl.l_type = F_UNLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_pid = getpid(); + serial_port_unix* spu = (serial_port_unix*)sp; + tcflush(spu->fd, TCIOFLUSH); + tcsetattr(spu->fd, TCSANOW, &(spu->tiOld)); + struct flock fl; + fl.l_type = F_UNLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_pid = getpid(); - // Does the system allows us to place a lock on this file descriptor - int err = fcntl(spu->fd, F_SETLK, &fl); - if ( err == -1) { - //perror("fcntl"); - } - close(spu->fd); - free(sp); + // Does the system allows us to place a lock on this file descriptor + int err = fcntl(spu->fd, F_SETLK, &fl); + if ( err == -1) { + //perror("fcntl"); + } + close(spu->fd); + free(sp); } bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen) { - int res; - int byteCount; - fd_set rfds; - struct timeval tv; + int res; + int byteCount; + fd_set rfds; + struct timeval tv; + + // Reset the output count + *pszRxLen = 0; - // Reset the output count - *pszRxLen = 0; - - do { - // Reset file descriptor - FD_ZERO(&rfds); - FD_SET(((serial_port_unix*)sp)->fd, &rfds); - tv = timeout; - res = select(((serial_port_unix*)sp)->fd + 1, &rfds, NULL, NULL, &tv); - - // Read error - if (res < 0) { - return false; - } - - // Read time-out - if (res == 0) { - if (*pszRxLen == 0) { - // Error, we received no data - return false; - } else { - // We received some data, but nothing more is available - return true; - } - } - - // Retrieve the count of the incoming bytes - res = ioctl(((serial_port_unix*)sp)->fd, FIONREAD, &byteCount); - if (res < 0) return false; - - // Cap the number of bytes, so we don't overrun the buffer - if (pszMaxRxLen - (*pszRxLen) < byteCount) { - byteCount = pszMaxRxLen - (*pszRxLen); - } + do { + // Reset file descriptor + FD_ZERO(&rfds); + FD_SET(((serial_port_unix*)sp)->fd, &rfds); + tv = timeout; + res = select(((serial_port_unix*)sp)->fd + 1, &rfds, NULL, NULL, &tv); - // There is something available, read the data - res = read(((serial_port_unix*)sp)->fd, pbtRx + (*pszRxLen), byteCount); + // Read error + if (res < 0) { + return false; + } - // Stop if the OS has some troubles reading the data - if (res <= 0) return false; - - *pszRxLen += res; + // Read time-out + if (res == 0) { + if (*pszRxLen == 0) { + // Error, we received no data + return false; + } else { + // We received some data, but nothing more is available + return true; + } + } - if (*pszRxLen == pszMaxRxLen) { - // We have all the data we wanted. - return true; - } - - } while (byteCount); + // Retrieve the count of the incoming bytes + res = ioctl(((serial_port_unix*)sp)->fd, FIONREAD, &byteCount); + if (res < 0) return false; - return true; + // Cap the number of bytes, so we don't overrun the buffer + if (pszMaxRxLen - (*pszRxLen) < byteCount) { + byteCount = pszMaxRxLen - (*pszRxLen); + } + + // There is something available, read the data + res = read(((serial_port_unix*)sp)->fd, pbtRx + (*pszRxLen), byteCount); + + // Stop if the OS has some troubles reading the data + if (res <= 0) return false; + + *pszRxLen += res; + + if (*pszRxLen == pszMaxRxLen) { + // We have all the data we wanted. + return true; + } + + } while (byteCount); + + return true; } bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t len) { - int32_t res; - size_t pos = 0; - fd_set rfds; - struct timeval tv; + int32_t res; + size_t pos = 0; + fd_set rfds; + struct timeval tv; - while (pos < len) { - // Reset file descriptor - FD_ZERO(&rfds); - FD_SET(((serial_port_unix*)sp)->fd, &rfds); - tv = timeout; - res = select(((serial_port_unix*)sp)->fd+1, NULL, &rfds, NULL, &tv); - - // Write error - if (res < 0) { - printf("UART:: write error (%d)\n", res); - return false; - } - - // Write time-out - if (res == 0) { - printf("UART:: write time-out\n"); - return false; - } - - // Send away the bytes - res = write(((serial_port_unix*)sp)->fd, pbtTx + pos, len - pos); - - // Stop if the OS has some troubles sending the data - if (res <= 0) return false; - - pos += res; - } - return true; + while (pos < len) { + // Reset file descriptor + FD_ZERO(&rfds); + FD_SET(((serial_port_unix*)sp)->fd, &rfds); + tv = timeout; + res = select(((serial_port_unix*)sp)->fd+1, NULL, &rfds, NULL, &tv); + + // Write error + if (res < 0) { + printf("UART:: write error (%d)\n", res); + return false; + } + + // Write time-out + if (res == 0) { + printf("UART:: write time-out\n"); + return false; + } + + // Send away the bytes + res = write(((serial_port_unix*)sp)->fd, pbtTx + pos, len - pos); + + // Stop if the OS has some troubles sending the data + if (res <= 0) return false; + + pos += res; + } + return true; } bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) { - const serial_port_unix* spu = (serial_port_unix*)sp; - speed_t stPortSpeed; - switch (uiPortSpeed) { - case 0: stPortSpeed = B0; break; - case 50: stPortSpeed = B50; break; - case 75: stPortSpeed = B75; break; - case 110: stPortSpeed = B110; break; - case 134: stPortSpeed = B134; break; - case 150: stPortSpeed = B150; break; - case 300: stPortSpeed = B300; break; - case 600: stPortSpeed = B600; break; - case 1200: stPortSpeed = B1200; break; - case 1800: stPortSpeed = B1800; break; - case 2400: stPortSpeed = B2400; break; - case 4800: stPortSpeed = B4800; break; - case 9600: stPortSpeed = B9600; break; - case 19200: stPortSpeed = B19200; break; - case 38400: stPortSpeed = B38400; break; + const serial_port_unix* spu = (serial_port_unix*)sp; + speed_t stPortSpeed; + switch (uiPortSpeed) { + case 0: stPortSpeed = B0; break; + case 50: stPortSpeed = B50; break; + case 75: stPortSpeed = B75; break; + case 110: stPortSpeed = B110; break; + case 134: stPortSpeed = B134; break; + case 150: stPortSpeed = B150; break; + case 300: stPortSpeed = B300; break; + case 600: stPortSpeed = B600; break; + case 1200: stPortSpeed = B1200; break; + case 1800: stPortSpeed = B1800; break; + case 2400: stPortSpeed = B2400; break; + case 4800: stPortSpeed = B4800; break; + case 9600: stPortSpeed = B9600; break; + case 19200: stPortSpeed = B19200; break; + case 38400: stPortSpeed = B38400; break; # ifdef B57600 - case 57600: stPortSpeed = B57600; break; + case 57600: stPortSpeed = B57600; break; # endif # ifdef B115200 - case 115200: stPortSpeed = B115200; break; + case 115200: stPortSpeed = B115200; break; # endif # ifdef B230400 - case 230400: stPortSpeed = B230400; break; + case 230400: stPortSpeed = B230400; break; # endif # ifdef B460800 - case 460800: stPortSpeed = B460800; break; + case 460800: stPortSpeed = B460800; break; # endif # ifdef B921600 - case 921600: stPortSpeed = B921600; break; + case 921600: stPortSpeed = B921600; break; # endif - default: return false; - }; - struct termios ti; - if (tcgetattr(spu->fd,&ti) == -1) return false; - // Set port speed (Input and Output) - cfsetispeed(&ti, stPortSpeed); - cfsetospeed(&ti, stPortSpeed); - return (tcsetattr(spu->fd, TCSANOW, &ti) != -1); + default: return false; + }; + struct termios ti; + if (tcgetattr(spu->fd,&ti) == -1) return false; + // Set port speed (Input and Output) + cfsetispeed(&ti, stPortSpeed); + cfsetospeed(&ti, stPortSpeed); + return (tcsetattr(spu->fd, TCSANOW, &ti) != -1); } uint32_t uart_get_speed(const serial_port sp) { - struct termios ti; - uint32_t uiPortSpeed; - const serial_port_unix* spu = (serial_port_unix*)sp; - if (tcgetattr(spu->fd, &ti) == -1) return 0; - // Set port speed (Input) - speed_t stPortSpeed = cfgetispeed(&ti); - switch (stPortSpeed) { - case B0: uiPortSpeed = 0; break; - case B50: uiPortSpeed = 50; break; - case B75: uiPortSpeed = 75; break; - case B110: uiPortSpeed = 110; break; - case B134: uiPortSpeed = 134; break; - case B150: uiPortSpeed = 150; break; - case B300: uiPortSpeed = 300; break; - case B600: uiPortSpeed = 600; break; - case B1200: uiPortSpeed = 1200; break; - case B1800: uiPortSpeed = 1800; break; - case B2400: uiPortSpeed = 2400; break; - case B4800: uiPortSpeed = 4800; break; - case B9600: uiPortSpeed = 9600; break; - case B19200: uiPortSpeed = 19200; break; - case B38400: uiPortSpeed = 38400; break; + struct termios ti; + uint32_t uiPortSpeed; + const serial_port_unix* spu = (serial_port_unix*)sp; + + if (tcgetattr(spu->fd, &ti) == -1) + return 0; + + // Set port speed (Input) + speed_t stPortSpeed = cfgetispeed(&ti); + switch (stPortSpeed) { + case B0: uiPortSpeed = 0; break; + case B50: uiPortSpeed = 50; break; + case B75: uiPortSpeed = 75; break; + case B110: uiPortSpeed = 110; break; + case B134: uiPortSpeed = 134; break; + case B150: uiPortSpeed = 150; break; + case B300: uiPortSpeed = 300; break; + case B600: uiPortSpeed = 600; break; + case B1200: uiPortSpeed = 1200; break; + case B1800: uiPortSpeed = 1800; break; + case B2400: uiPortSpeed = 2400; break; + case B4800: uiPortSpeed = 4800; break; + case B9600: uiPortSpeed = 9600; break; + case B19200: uiPortSpeed = 19200; break; + case B38400: uiPortSpeed = 38400; break; # ifdef B57600 - case B57600: uiPortSpeed = 57600; break; + case B57600: uiPortSpeed = 57600; break; # endif # ifdef B115200 - case B115200: uiPortSpeed = 115200; break; + case B115200: uiPortSpeed = 115200; break; # endif # ifdef B230400 - case B230400: uiPortSpeed = 230400; break; + case B230400: uiPortSpeed = 230400; break; # endif # ifdef B460800 - case B460800: uiPortSpeed = 460800; break; + case B460800: uiPortSpeed = 460800; break; # endif # ifdef B921600 - case B921600: uiPortSpeed = 921600; break; + case B921600: uiPortSpeed = 921600; break; # endif - default: return 0; - }; - return uiPortSpeed; + default: return 0; + }; + return uiPortSpeed; } - #endif From f05ab29c04e8f6f9d4f4be36d0784f9f6dd7c0d4 Mon Sep 17 00:00:00 2001 From: Fl0-0 Date: Sun, 17 Feb 2019 15:51:37 +0100 Subject: [PATCH 0483/1938] Fix for USB uart slowness See Proxmark#787 --- uart/uart_posix.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/uart/uart_posix.c b/uart/uart_posix.c index cb878a4f0..093aaf363 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -68,9 +68,9 @@ typedef struct { } serial_port_unix; // Set time-out on 30 miliseconds -const struct timeval timeout = { +struct timeval timeout = { .tv_sec = 0, // 0 second - .tv_usec = 300000 // 300 000 micro seconds + .tv_usec = 30000 // 30000 micro seconds }; serial_port uart_open(const char* pcPortName) @@ -89,6 +89,10 @@ serial_port uart_open(const char* pcPortName) char *colon = strrchr(addrstr, ':'); char *portstr; + + // Set time-out to 300 miliseconds only for TCP port + timeout.tv_usec = 300000; + if (colon) { portstr = colon + 1; *colon = '\0'; From 4ea05fc026a5bc92f6f92c057b21da24f9323320 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 17 Feb 2019 15:56:45 +0100 Subject: [PATCH 0484/1938] Fix: 'hf mf fchk' - now reports back correct found keys. --- CHANGELOG.md | 2 ++ armsrc/mifarecmd.c | 20 ++++++++++++-------- client/mifarehost.c | 21 +++++++++++---------- 3 files changed, 25 insertions(+), 18 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 1c7adf3a6..69078a1f7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,8 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fix 'hf mf fchk' (@iceman) + - Fix 'usb slow on posix based systems' (@fl0-0) - Change 'lf pcf7931' - improved read code (@sguerrini97) - Change 'hf felica list' - started with some FeliCa annotations (@iceman) - Fix 'hf tune' - now works as expected (@iceman) diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 3e1967b4e..6b10ddd0d 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1259,7 +1259,6 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da LED_A_ON(); if ( firstchunk ) { - clear_trace(); set_tracing(false); @@ -1458,26 +1457,31 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da } // end loop sectors } // end loop keys } // end loop strategy 2 -OUT: +OUT: LEDsoff(); crypto1_destroy(pcs); // All keys found, send to client, or last keychunk from client if (foundkeys == allkeys || lastchunk ) { - + uint64_t foo = 0; + for (uint8_t m = 0; m < 64; m++) { + foo |= ((uint64_t)(found[m] & 1) << m); + } + uint16_t bar = 0; - for (uint8_t m = 0; m < 64; ++m) - foo |= (found[m] << m); - for (uint8_t m=64; m < sizeof(found); ++m) - bar |= (found[m] << (m-64)); - + uint8_t j = 0; + for (uint8_t m=64; m < sizeof(found); m++) { + bar |= ((uint16_t)(found[m] & 1) << j++); + } + uint8_t *tmp = BigBuf_malloc(480+10); memcpy(tmp, k_sector, sectorcnt * sizeof(sector_t) ); num_to_bytes(foo, 8, tmp+480); tmp[488] = bar & 0xFF; tmp[489] = bar >> 8 & 0xFF; + cmd_send(CMD_ACK, foundkeys, 0, 0, tmp, 480+10); set_tracing(false); diff --git a/client/mifarehost.c b/client/mifarehost.c index 0f37f8a8b..31ed8e39d 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -173,18 +173,19 @@ int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, // success array. each byte is status of key uint8_t arr[80]; - uint64_t foo = bytes_to_num(resp.d.asBytes+480, 8); - for (uint8_t i = 0; i < 64; ++i) { - arr[i] = (foo >> i) & 0x1; - } - foo = bytes_to_num(resp.d.asBytes+488, 2); - for (uint8_t i = 0; i < 16; ++i) { - arr[i+64] = (foo >> i) & 0x1; - } + uint64_t foo = 0; + uint16_t bar = 0; + foo = bytes_to_num(resp.d.asBytes+480, 8); + bar = (resp.d.asBytes[489] << 8 | resp.d.asBytes[488]); + for (uint8_t i = 0; i < 64; i++) + arr[i] = (foo >> i) & 0x1; + + for (uint8_t i = 0; i < 16; i++) + arr[i+64] = (bar >> i) & 0x1; + // initialize storage for found keys - icesector_t *tmp = NULL; - tmp = calloc(sectorsCnt, sizeof(icesector_t)); + icesector_t *tmp = calloc(sectorsCnt, sizeof(icesector_t)); if (tmp == NULL) return 1; memcpy(tmp, resp.d.asBytes, sectorsCnt * sizeof(icesector_t) ); From d6063d677685725490454b0be39400fec3ae73f6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 17 Feb 2019 16:07:31 +0100 Subject: [PATCH 0485/1938] textual --- README.md | 9 ++++++++- tools/Makefile | 7 ++++++- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index effdc0f6e..c8c04f852 100644 --- a/README.md +++ b/README.md @@ -78,7 +78,14 @@ This fork now compiles just fine on ## KALI and ARCHLINUX users Kali and ArchLinux users usually must kill their modem manager in order for the proxmark3 to enumerate properly. -`sudo apt remove modemmanager` +```sh +sudo apt remove modemmanager +``` +or +```sh +systemctl stop ModemManager +systemctl disable ModemManager +``` ## Setup and build for UBUNTU GC made updates to allow this to build easily on Ubuntu 14.04.2 LTS, 15.10 or 16.04 diff --git a/tools/Makefile b/tools/Makefile index c750cce26..b72503158 100644 --- a/tools/Makefile +++ b/tools/Makefile @@ -11,4 +11,9 @@ get_nonce_bf: git clone https://github.com/iceman1001/mf_nonce_brute mf_nonce_brute get_xorsearch: - wget -N https://didierstevens.com/files/software/XORSearch_V1_11_2.zip \ No newline at end of file + mkdir xorsearch + wget -N https://didierstevens.com/files/software/XORSearch_V1_11_2.zip +# Mingw +# unzzip-big XORSearch_V1_11_2.zip +# linux +# gunzip XORSearch_V1_11_2.zip \ No newline at end of file From f80aaa13abc45f081459ee43e167989097bba039 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 17 Feb 2019 16:09:02 +0100 Subject: [PATCH 0486/1938] textual --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 69078a1f7..44a6fc2d6 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Change 'hf 14a antifuzz' - original implementation (@asfabw), reworked a bit - Fix 'hf mf fchk' (@iceman) - Fix 'usb slow on posix based systems' (@fl0-0) - Change 'lf pcf7931' - improved read code (@sguerrini97) From e23d53adc13b1626fcbab13e0b8ac6b7dfd1b46f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 17 Feb 2019 16:48:14 +0100 Subject: [PATCH 0487/1938] chg: 'hf mf hardnested' - speedup for those with good cpus, triggering the bruteforce faster. --- client/cmdhfmfhard.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 3547761a5..4818f480f 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -1038,8 +1038,11 @@ static bool shrink_key_space(float *brute_forces) } *brute_forces = MIN(brute_forces1, brute_forces2); float reduction_rate = update_reduction_rate(*brute_forces, false); - return ((hardnested_stage & CHECK_2ND_BYTES) - && reduction_rate >= 0.0 && reduction_rate < brute_force_per_second * sample_period / 1000.0); + +//iceman 2018 + return ((hardnested_stage & CHECK_2ND_BYTES) && + reduction_rate >= 0.0 && + ( reduction_rate < brute_force_per_second * (float)sample_period / 1000.0 || *brute_forces < 0x1F000000000)); } From f943348a7b5d5a6c1ab05a09bc8e2106a6d9789e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 18 Feb 2019 10:18:55 +0100 Subject: [PATCH 0488/1938] FIX: detection of presence of git on system. ie downloaded a zip file with everything or precompiled distro may not have git installed. On ubuntu/mingw 'env -S' doesn't exist. --- tools/mkversion.pl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/mkversion.pl b/tools/mkversion.pl index 1acca6efa..674c44177 100644 --- a/tools/mkversion.pl +++ b/tools/mkversion.pl @@ -28,7 +28,7 @@ my $clean = 2; # fatal: No names found, cannot describe anything. ## # anyway forcing any kind of shell is at least useless, at worst fatal. -my $commandGIT = "env -S which git"; +my $commandGIT = "env which git"; if ( defined($commandGIT) ) { From 7e601e5285ac7a45bfb94804dbfa7a719d06bcab Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 18 Feb 2019 10:27:14 +0100 Subject: [PATCH 0489/1938] chg: textual --- client/cmdhfmf.c | 2 +- client/cmdhw.c | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 8129aceb6..c5c4ab1d5 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1834,7 +1834,7 @@ int CmdHF14AMfChk(const char *Cmd) { } if (keycnt == 0) { - PrintAndLogEx(NORMAL, "No key specified, trying default keys"); + PrintAndLogEx(INFO, "No key specified, trying default keys"); for (;keycnt < MIFARE_DEFAULTKEYS_SIZE; keycnt++) PrintAndLogEx(NORMAL, "[%2d] %02x%02x%02x%02x%02x%02x", keycnt, (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], diff --git a/client/cmdhw.c b/client/cmdhw.c index a93a940cc..ec7b42a1a 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -257,9 +257,9 @@ int CmdVersion(const char *Cmd) { SendCommand(&c); if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) { #ifdef __WIN32 - PrintAndLogEx(NORMAL, "\nProxmark3 RFID instrument\n"); + PrintAndLogEx(NORMAL, "\n [ Proxmark3 RFID instrument ]\n"); #else - PrintAndLogEx(NORMAL, "\n\e[34mProxmark3 RFID instrument\e[0m\n"); + PrintAndLogEx(NORMAL, "\n\e[34m [ Proxmark3 RFID instrument ]\e[0m\n"); #endif char s[50] = {0}; #if defined(WITH_FLASH) || defined(WITH_SMARTCARD) || defined(WITH_FPC) @@ -275,7 +275,7 @@ int CmdVersion(const char *Cmd) { strncat(s, "fpc; ", sizeof(s) - strlen(s) - 1); #endif PrintAndLogEx(NORMAL, "\n [ CLIENT ]"); - PrintAndLogEx(NORMAL, " client: iceman %s \n", s); + PrintAndLogEx(NORMAL, " client: iceman %s \n", s); PrintAndLogEx(NORMAL, (char*)resp.d.asBytes); lookupChipID(resp.arg[0], resp.arg[1]); From cacba04959347743d842f531977c448ffd97646f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 18 Feb 2019 10:38:49 +0100 Subject: [PATCH 0490/1938] chg: 'hf mf fchk' - better handling when no keys was found. --- client/cmdhfmf.c | 86 ++++++++++++++++++++++++++++-------------------- 1 file changed, 51 insertions(+), 35 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index c5c4ab1d5..58a190f8c 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1649,47 +1649,63 @@ out: t1 = msclock() - t1; PrintAndLogEx(SUCCESS, "Time in checkkeys (fast): %.1fs\n", (float)(t1/1000.0)); - printKeyTable( sectorsCnt, e_sector ); - - if (transferToEml) { - uint8_t block[16] = {0x00}; - for (uint8_t i = 0; i < sectorsCnt; ++i ) { - mfEmlGetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); - if (e_sector[i].foundKey[0]) - num_to_bytes(e_sector[i].Key[0], 6, block); - if (e_sector[i].foundKey[1]) - num_to_bytes(e_sector[i].Key[1], 6, block+10); - mfEmlSetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); - } - PrintAndLogEx(NORMAL, "Found keys have been transferred to the emulator memory"); + // check.. + uint8_t found_keys = 0; + for (uint8_t i = 0; i < sectorsCnt; ++i) { + + if ( e_sector[i].foundKey[0] ) + found_keys++; + + if ( e_sector[i].foundKey[1] ) + found_keys++; } - if (createDumpFile) { - fptr = GenerateFilename("hf-mf-", "-key.bin"); - if (fptr == NULL) - return 1; - - FILE *fkeys = fopen(fptr, "wb"); - if (fkeys == NULL) { - PrintAndLogEx(WARNING, "Could not create file %s", fptr); - free(keyBlock); - free(e_sector); - return 1; - } - PrintAndLogEx(NORMAL, "Printing keys to binary file %s...", fptr); + if ( found_keys == 0 ) { + PrintAndLogEx(WARNING, "No keys found"); + } else { - for (i=0; i 0xffffffffffff has been inserted for unknown keys.", fptr); + FILE *fkeys = fopen(fptr, "wb"); + if (fkeys == NULL) { + PrintAndLogEx(WARNING, "Could not create file %s", fptr); + free(keyBlock); + free(e_sector); + return 1; + } + PrintAndLogEx(NORMAL, "Printing keys to binary file %s...", fptr); + + for (i=0; i 0xffffffffffff has been inserted for unknown keys.", fptr); + } } free(keyBlock); From 06fc95b62d74b89a0df6abf555d714f079dcd167 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 18 Feb 2019 10:41:54 +0100 Subject: [PATCH 0491/1938] chg: 'hf mf fchk' - textual --- client/cmdhfmf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 58a190f8c..03ac49c3d 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1676,7 +1676,7 @@ out: num_to_bytes(e_sector[i].Key[1], 6, block+10); mfEmlSetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); } - PrintAndLogEx(NORMAL, "Found keys have been transferred to the emulator memory"); + PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory"); } if (createDumpFile) { @@ -1691,7 +1691,7 @@ out: free(e_sector); return 1; } - PrintAndLogEx(NORMAL, "Printing keys to binary file %s...", fptr); + PrintAndLogEx(SUCCESS, "Printing keys to binary file %s...", fptr); for (i=0; i 0xffffffffffff has been inserted for unknown keys.", fptr); + PrintAndLogEx(SUCCESS, "Found keys have been dumped to %s --> 0xffffffffffff has been inserted for unknown keys.", fptr); } } From 20ccfb036c2a6bc3b5ba40cdf9c394e52b0e4f47 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 18 Feb 2019 13:12:25 +0100 Subject: [PATCH 0492/1938] chg: more colors --- client/loclass/fileutils.c | 33 ++++++++++++++++----------------- 1 file changed, 16 insertions(+), 17 deletions(-) diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 5bac3d2cd..0751f838b 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -71,14 +71,14 @@ int saveFile(const char *preferredName, const char *suffix, const void* data, si /*Opening file for writing in binary mode*/ FILE *f = fopen(fileName, "wb"); if (!f) { - PrintAndLogDevice(WARNING, "file not found or locked. '%s'", fileName); + PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName); free(fileName); return 1; } fwrite(data, 1, datalen, f); fflush(f); fclose(f); - PrintAndLogDevice(SUCCESS, "saved %u bytes to binary file %s", datalen, fileName); + PrintAndLogDevice(SUCCESS, "saved %u bytes to binary file " _YELLOW_(%s), datalen, fileName); free(fileName); return 0; } @@ -106,8 +106,8 @@ int saveFileEML(const char *preferredName, const char *suffix, uint8_t* data, si /*Opening file for writing in text mode*/ FILE *f = fopen(fileName, "w+"); - if (!f) { - PrintAndLogDevice(WARNING, "file not found or locked. '%s'", fileName); + if (!f) { + PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName); retval = 1; goto out; } @@ -130,7 +130,7 @@ int saveFileEML(const char *preferredName, const char *suffix, uint8_t* data, si } fflush(f); fclose(f); - PrintAndLogDevice(SUCCESS, "saved %d blocks to text file %s", blocks, fileName); + PrintAndLogDevice(SUCCESS, "saved %d blocks to text file " _YELLOW_(%s), blocks, fileName); out: free(fileName); @@ -240,13 +240,12 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty int res = json_dump_file(root, fileName, JSON_INDENT(2)); if (res) { - PrintAndLogDevice(FAILED, "error: can't save the file: %s", fileName); + PrintAndLogDevice(FAILED, "error: can't save the file: " _YELLOW_(%s), fileName); json_decref(root); retval = 200; goto out; } - PrintAndLogDevice(SUCCESS, "File `%s` saved.", fileName); - + PrintAndLogDevice(SUCCESS, "File `" _YELLOW_(%s)"` saved.", fileName); json_decref(root); out: @@ -266,7 +265,7 @@ int loadFile(const char *preferredName, const char *suffix, void* data, size_t* FILE *f = fopen(fileName, "rb"); if ( !f ) { - PrintAndLogDevice(FAILED, "file: %s: not found or locked.", fileName); + PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName); retval = 1; goto out; } @@ -305,7 +304,7 @@ int loadFile(const char *preferredName, const char *suffix, void* data, size_t* memcpy( (data), dump, bytes_read); free(dump); - PrintAndLogDevice(SUCCESS, "loaded %d bytes from binary file %s", bytes_read, fileName); + PrintAndLogDevice(SUCCESS, "loaded %d bytes from binary file " _YELLOW_(%s), bytes_read, fileName); *datalen = bytes_read; @@ -328,7 +327,7 @@ int loadFileEML(const char *preferredName, const char *suffix, void* data, size_ FILE *f = fopen(fileName, "r"); if ( !f ) { - PrintAndLogDevice(FAILED, "file: %s: not found or locked.", fileName); + PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName); retval = 1; goto out; } @@ -359,7 +358,7 @@ int loadFileEML(const char *preferredName, const char *suffix, void* data, size_ } } fclose(f); - PrintAndLogDevice(SUCCESS, "loaded %d bytes from text file %s", counter, fileName); + PrintAndLogDevice(SUCCESS, "loaded %d bytes from text file " _YELLOW_(%s), counter, fileName); *datalen = counter; out: @@ -382,13 +381,13 @@ int loadFileJSON(const char *preferredName, const char *suffix, void* data, size root = json_load_file(fileName, 0, &error); if (!root) { - PrintAndLog("ERROR: json (%s) error on line %d: %s", fileName, error.line, error.text); + PrintAndLog("ERROR: json " _YELLOW_(%s) " error on line %d: %s", fileName, error.line, error.text); retval = 2; goto out; } if (!json_is_object(root)) { - PrintAndLog("ERROR: Invalid json (%s) format. root must be an object.", fileName); + PrintAndLog("ERROR: Invalid json " _YELLOW_(%s) " format. root must be an object.", fileName); retval = 3; goto out; } @@ -446,7 +445,7 @@ int loadFileJSON(const char *preferredName, const char *suffix, void* data, size } - PrintAndLog("Loaded JSON: (%s) OK.", fileName); + PrintAndLog("Loaded JSON: " _YELLOW_(%s) " OK.", fileName); out: json_decref(root); free(fileName); @@ -479,7 +478,7 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data FILE *f = fopen(fileName, "r"); if ( !f ) { - PrintAndLogDevice(FAILED, "file: %s: not found or locked.", fileName); + PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName); retval = 1; goto out; } @@ -512,7 +511,7 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data counter += (keylen >> 1); } fclose(f); - PrintAndLogDevice(SUCCESS, "loaded " _GREEN_(%2d) "keys from dictionary file %s", *keycnt, fileName); + PrintAndLogDevice(SUCCESS, "loaded " _GREEN_(%2d) "keys from dictionary file " _YELLOW_(%s), *keycnt, fileName); *datalen = counter; out: free(fileName); From e6c68645e378a1dc73a7faa3afcaa5a62624ab19 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 18 Feb 2019 13:28:22 +0100 Subject: [PATCH 0493/1938] chg: colors --- client/cmdhf15.c | 30 ++++++++++++------------ client/cmdhflegic.c | 2 +- client/cmdhfmfu.c | 56 ++++++++++++++++++++++----------------------- 3 files changed, 44 insertions(+), 44 deletions(-) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index a1b55d7c6..41d6ee8cd 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -519,21 +519,21 @@ int CmdHF15Info(const char *Cmd) { SendCommand(&c); if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - PrintAndLogEx(NORMAL, "iso15693 card select failed"); + PrintAndLogEx(WARNING, "iso15693 card select failed"); return 1; } uint32_t status = resp.arg[0]; if ( status < 2 ) { - PrintAndLogEx(NORMAL, "iso15693 card doesn't answer to systeminfo command"); + PrintAndLogEx(WARNING, "iso15693 card doesn't answer to systeminfo command"); return 1; } recv = resp.d.asBytes; if ( recv[0] & ISO15_RES_ERROR ) { - PrintAndLogEx(NORMAL, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + PrintAndLogEx(WARNING, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); return 3; } @@ -575,8 +575,8 @@ int CmdHF15Info(const char *Cmd) { // Record Activity without enabeling carrier //helptext int CmdHF15Record(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_15_record(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_15_record(); UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693, {0,0,0}}; clearCommandBuffer(); @@ -598,8 +598,8 @@ int HF15Reader(const char *Cmd, bool verbose) { } int CmdHF15Reader(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_15_reader(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_15_reader(); HF15Reader(Cmd, true); return 0; @@ -608,16 +608,16 @@ int CmdHF15Reader(const char *Cmd) { // Simulation is still not working very good // helptext int CmdHF15Sim(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_15_sim(); + char cmdp =tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_sim(); uint8_t uid[8] = {0,0,0,0,0,0,0,0}; if (param_gethex(Cmd, 0, uid, 16)) { - PrintAndLogEx(NORMAL, "UID must include 16 HEX symbols"); + PrintAndLogEx(WARNING, "UID must include 16 HEX symbols"); return 0; } - PrintAndLogEx(NORMAL, "Starting simulating UID %s", sprint_hex(uid, sizeof(uid)) ); + PrintAndLogEx(SUCCESS, "Starting simulating UID %s", sprint_hex(uid, sizeof(uid)) ); UsbCommand c = {CMD_SIMTAG_ISO_15693, {0, 0, 0}}; memcpy(c.d.asBytes, uid, 8); @@ -630,10 +630,10 @@ int CmdHF15Sim(const char *Cmd) { // (There is no standard way of reading the AFI, allthough some tags support this) // helptext int CmdHF15Afi(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_15_findafi(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_15_findafi(); - PrintAndLogEx(NORMAL, "press pm3-button to cancel"); + PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); UsbCommand c = {CMD_ISO_15693_FIND_AFI, {strtol(Cmd, NULL, 0), 0, 0}}; clearCommandBuffer(); @@ -689,7 +689,7 @@ int CmdHF15Dump(const char*Cmd) { } // detect blocksize from card :) - PrintAndLogEx(NORMAL, "Reading memory from tag UID %s", sprintUID(NULL, uid)); + PrintAndLogEx(NORMAL, "Reading memory from tag UID " _YELLOW_(%s), sprintUID(NULL, uid)); int blocknum = 0; uint8_t *recv = NULL; diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 1403060e5..8c4ef411c 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -180,7 +180,7 @@ int CmdLegicInfo(const char *Cmd) { return 1; } - PrintAndLogEx(NORMAL, "Reading tag memory %d b...", card.cardsize); + PrintAndLogEx(SUCCESS, "Reading tag memory %d b...", card.cardsize); // allocate receiver buffer uint8_t *data = calloc(card.cardsize, sizeof(uint8_t)); diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index b5be04593..0a7e77b1c 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -518,57 +518,57 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces){ char *spacer = spc + (10-spaces); if ( tagtype & UL ) - PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight (MF0ICU1) %s", spacer, (tagtype & MAGIC) ? "" : "" ); + PrintAndLogEx(SUCCESS, "%sTYPE : MIFARE Ultralight (MF0ICU1) %s", spacer, (tagtype & MAGIC) ? "" : "" ); else if ( tagtype & UL_C) - PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight C (MF0ULC) %s", spacer, (tagtype & MAGIC) ? "" : "" ); + PrintAndLogEx(SUCCESS, "%sTYPE : MIFARE Ultralight C (MF0ULC) %s", spacer, (tagtype & MAGIC) ? "" : "" ); else if ( tagtype & UL_NANO_40) - PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight Nano 40bytes (MF0UNH00)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : MIFARE Ultralight Nano 40bytes (MF0UNH00)", spacer); else if ( tagtype & UL_EV1_48) - PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)", spacer); else if ( tagtype & UL_EV1_128) - PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)", spacer); else if ( tagtype & UL_EV1 ) - PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight EV1 UNKNOWN", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : MIFARE Ultralight EV1 UNKNOWN", spacer); else if ( tagtype & NTAG ) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG UNKNOWN", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : NTAG UNKNOWN", spacer); else if ( tagtype & NTAG_203 ) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 203 144bytes (NT2H0301F0DT)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : NTAG 203 144bytes (NT2H0301F0DT)", spacer); else if ( tagtype & NTAG_210 ) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 210 48bytes (NT2L1011G0DU)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : NTAG 210 48bytes (NT2L1011G0DU)", spacer); else if ( tagtype & NTAG_212 ) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 212 128bytes (NT2L1211G0DU)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : NTAG 212 128bytes (NT2L1211G0DU)", spacer); else if ( tagtype & NTAG_213 ) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 213 144bytes (NT2H1311G0DU)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : NTAG 213 144bytes (NT2H1311G0DU)", spacer); else if ( tagtype & NTAG_213_F ) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 213F 144bytes (NT2H1311F0DTL)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : NTAG 213F 144bytes (NT2H1311F0DTL)", spacer); else if ( tagtype & NTAG_215 ) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 215 504bytes (NT2H1511G0DU)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : NTAG 215 504bytes (NT2H1511G0DU)", spacer); else if ( tagtype & NTAG_216 ) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 216 888bytes (NT2H1611G0DU)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : NTAG 216 888bytes (NT2H1611G0DU)", spacer); else if ( tagtype & NTAG_216_F ) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 216F 888bytes (NT2H1611F0DTL)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : NTAG 216F 888bytes (NT2H1611F0DTL)", spacer); else if ( tagtype & NTAG_I2C_1K ) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG I%sC 888bytes (NT3H1101FHK)", spacer, "\xFD"); + PrintAndLogEx(SUCCESS, "%sTYPE : NTAG I%sC 888bytes (NT3H1101FHK)", spacer, "\xFD"); else if ( tagtype & NTAG_I2C_2K ) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG I%sC 1904bytes (NT3H1201FHK)", spacer, "\xFD"); + PrintAndLogEx(SUCCESS, "%sTYPE : NTAG I%sC 1904bytes (NT3H1201FHK)", spacer, "\xFD"); else if ( tagtype & NTAG_I2C_1K_PLUS ) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG I%sC plus 888bytes (NT3H2111FHK)", spacer, "\xFD"); + PrintAndLogEx(SUCCESS, "%sTYPE : NTAG I%sC plus 888bytes (NT3H2111FHK)", spacer, "\xFD"); else if ( tagtype & NTAG_I2C_2K_PLUS ) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG I%sC plus 1912bytes (NT3H2211FHK)", spacer, "\xFD"); + PrintAndLogEx(SUCCESS, "%sTYPE : NTAG I%sC plus 1912bytes (NT3H2211FHK)", spacer, "\xFD"); else if ( tagtype & MY_D ) - PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 (SLE 66RxxS)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : INFINEON my-d\x99 (SLE 66RxxS)", spacer); else if ( tagtype & MY_D_NFC ) - PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 NFC (SLE 66RxxP)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : INFINEON my-d\x99 NFC (SLE 66RxxP)", spacer); else if ( tagtype & MY_D_MOVE ) - PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 move (SLE 66R01P)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : INFINEON my-d\x99 move (SLE 66R01P)", spacer); else if ( tagtype & MY_D_MOVE_NFC ) - PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 move NFC (SLE 66R01P)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : INFINEON my-d\x99 move NFC (SLE 66R01P)", spacer); else if ( tagtype & MY_D_MOVE_LEAN ) - PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 move lean (SLE 66R01L)", spacer); + PrintAndLogEx(SUCCESS, "%sTYPE : INFINEON my-d\x99 move lean (SLE 66R01L)", spacer); else if ( tagtype & FUDAN_UL ) - PrintAndLogEx(NORMAL, "%sTYPE : FUDAN Ultralight Compatible (or other compatible) %s", spacer, (tagtype & MAGIC) ? "" : "" ); + PrintAndLogEx(SUCCESS, "%sTYPE : FUDAN Ultralight Compatible (or other compatible) %s", spacer, (tagtype & MAGIC) ? "" : "" ); else - PrintAndLogEx(NORMAL, "%sTYPE : Unknown %06x", spacer, tagtype); + PrintAndLogEx(SUCCESS, "%sTYPE : Unknown %06x", spacer, tagtype); return 0; } @@ -606,7 +606,7 @@ static int ulc_print_configuration( uint8_t *data){ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t startPage){ - PrintAndLogEx(NORMAL, "\n--- Tag Configuration"); + PrintAndLogEx(SUCCESS, "\n--- Tag Configuration"); bool strg_mod_en = (data[0] & 2); uint8_t authlim = (data[4] & 0x07); @@ -1743,7 +1743,7 @@ int CmdHF14AMfUDump(const char *Cmd){ } } ul_print_type(tagtype, 0); - PrintAndLogEx(NORMAL, "Reading tag memory..."); + PrintAndLogEx(SUCCESS, "Reading tag memory..."); UsbCommand c = {CMD_MIFAREU_READCARD, {startPage, pages}}; if ( hasAuthKey ) { if (tagtype & UL_C) From 23d0b6b1c64c00e9ae4854aa4d619cbf47f8b04b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 18 Feb 2019 14:59:19 +0100 Subject: [PATCH 0494/1938] chg: colors --- client/cmdhfmf.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 03ac49c3d..db2f2b495 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1691,7 +1691,7 @@ out: free(e_sector); return 1; } - PrintAndLogEx(SUCCESS, "Printing keys to binary file %s...", fptr); + PrintAndLogEx(SUCCESS, "Printing keys to binary file " _YELLOW_(%s)"...", fptr); for (i=0; i 0xffffffffffff has been inserted for unknown keys.", fptr); + PrintAndLogEx(SUCCESS, "Found keys have been dumped to " _YELLOW_(%s)" --> 0xffffffffffff has been inserted for unknown keys.", fptr); } } @@ -1964,7 +1964,7 @@ out: num_to_bytes(e_sector[i].Key[1], 6, block+10); mfEmlSetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); } - PrintAndLogEx(NORMAL, "Found keys have been transferred to the emulator memory"); + PrintAndLogEx(INFO, "Found keys have been transferred to the emulator memory"); } if (createDumpFile) { @@ -1979,7 +1979,7 @@ out: free(e_sector); return 1; } - PrintAndLogEx(NORMAL, "Printing keys to binary file %s...", fptr); + PrintAndLogEx(INFO, "Printing keys to binary file " _YELLOW_(%s)"...", fptr); for( i=0; i Date: Mon, 18 Feb 2019 15:37:26 +0100 Subject: [PATCH 0495/1938] chg: more colors --- client/cmdhfmf.c | 62 ++++++++++++++++++++++++------------------------ 1 file changed, 31 insertions(+), 31 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index db2f2b495..691c8678e 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -734,7 +734,7 @@ int CmdHF14AMfDump(const char *Cmd) { } if ((fin = fopen(keyFilename, "rb")) == NULL) { - PrintAndLogEx(WARNING, "Could not find file %s", keyFilename); + PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), keyFilename); return 1; } @@ -743,7 +743,7 @@ int CmdHF14AMfDump(const char *Cmd) { for (sectorNo=0; sectorNo Date: Mon, 18 Feb 2019 15:47:48 +0100 Subject: [PATCH 0496/1938] chg: colors --- client/cmdhfmf.c | 74 +++++++++++++++++++++++------------------------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 691c8678e..e9b1bed10 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -945,7 +945,7 @@ int CmdHF14AMfRestore(const char *Cmd) { } if ((fkeys = fopen(keyFilename, "rb")) == NULL) { - PrintAndLogEx(WARNING, "Could not find file %s", keyFilename); + PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), keyFilename); return 1; } @@ -979,10 +979,10 @@ int CmdHF14AMfRestore(const char *Cmd) { } if ((fdump = fopen(dataFilename, "rb")) == NULL) { - PrintAndLogEx(WARNING, "Could not find file %s", dataFilename); + PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), dataFilename); return 1; } - PrintAndLogEx(INFO, "Restoring %s to card", dataFilename); + PrintAndLogEx(INFO, "Restoring " _YELLOW_(%s)" to card", dataFilename); for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { for (blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) { @@ -1561,7 +1561,7 @@ int CmdHF14AMfChk_fast(const char *Cmd) { if( buf[0]=='#' ) continue; //The line start with # is comment, skip if (!isxdigit(buf[0])){ - PrintAndLogEx(FAILED, "File content error. '%s' must include 12 HEX symbols", buf); + PrintAndLogEx(FAILED, "File content error. '" _YELLOW_(%s)"' must include 12 HEX symbols", buf); continue; } @@ -1622,7 +1622,7 @@ int CmdHF14AMfChk_fast(const char *Cmd) { if (ukbhit()) { int gc = getchar(); (void)gc; - PrintAndLogEx(NORMAL, "\naborted via keyboard!\n"); + PrintAndLogEx(WARNING, "\naborted via keyboard!\n"); goto out; } @@ -1686,7 +1686,7 @@ out: FILE *fkeys = fopen(fptr, "wb"); if (fkeys == NULL) { - PrintAndLogEx(WARNING, "Could not create file %s", fptr); + PrintAndLogEx(WARNING, "Could not create file " _YELLOW_(%s), fptr); free(keyBlock); free(e_sector); return 1; @@ -1750,23 +1750,21 @@ int CmdHF14AMfChk(const char *Cmd) { blockNo = param_get8(Cmd, 0); } - ctmp = param_getchar(Cmd, 1); + ctmp = tolower(param_getchar(Cmd, 1)); clen = param_getlength(Cmd, 1); if (clen == 1) { switch (ctmp) { case 'a': - case 'A': keyType = 0; break; case 'b': - case 'B': keyType = 1; break; case '?': keyType = 2; break; default: - PrintAndLogEx(NORMAL, "Key type must be A , B or ?"); + PrintAndLogEx(FAILED, "Key type must be A , B or ?"); free(keyBlock); return 1; }; @@ -1774,7 +1772,7 @@ int CmdHF14AMfChk(const char *Cmd) { for (i = 2; param_getchar(Cmd, i); i++) { - ctmp = param_getchar(Cmd, i); + ctmp = tolower(param_getchar(Cmd, i)); clen = param_getlength(Cmd, i); if (clen == 12) { @@ -1796,8 +1794,8 @@ int CmdHF14AMfChk(const char *Cmd) { PrintAndLogEx(NORMAL, "[%2d] key %s", keycnt, sprint_hex( (keyBlock + 6*keycnt), 6 ) );; keycnt++; } else if ( clen == 1 ) { - if (ctmp == 't' || ctmp == 'T') { transferToEml = 1; continue; } - if (ctmp == 'd' || ctmp == 'D') { createDumpFile = 1; continue; } + if (ctmp == 't' ) { transferToEml = 1; continue; } + if (ctmp == 'd' ) { createDumpFile = 1; continue; } } else { // May be a dic file if ( param_getstr(Cmd, i, filename, sizeof(filename)) >= FILE_PATH_SIZE ) { @@ -1822,7 +1820,7 @@ int CmdHF14AMfChk(const char *Cmd) { // codesmell, only checks first char? if (!isxdigit(buf[0])){ - PrintAndLogEx(FAILED, "File content error. '%s' must include 12 HEX symbols",buf); + PrintAndLogEx(FAILED, "File content error. '" _YELLOW_(%s)"' must include 12 HEX symbols",buf); continue; } @@ -1964,7 +1962,7 @@ out: num_to_bytes(e_sector[i].Key[1], 6, block+10); mfEmlSetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); } - PrintAndLogEx(INFO, "Found keys have been transferred to the emulator memory"); + PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory"); } if (createDumpFile) { @@ -1974,7 +1972,7 @@ out: FILE *fkeys = fopen(fptr, "wb"); if (fkeys == NULL) { - PrintAndLogEx(WARNING, "Could not create file %s", fptr); + PrintAndLogEx(WARNING, "Could not create file " _YELLOW_(%s), fptr); free(keyBlock); free(e_sector); return 1; @@ -2039,7 +2037,7 @@ void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose) { uint8_t sector = data.sector; uint8_t keytype = data.keytype; - PrintAndLogEx(NORMAL, "Reader is trying authenticate with: Key %s, sector %02d: [%012" PRIx64 "]" + PrintAndLogEx(INFO, "Reader is trying authenticate with: Key %s, sector %02d: [%012" PRIx64 "]" , keytype ? "B" : "A" , sector , key @@ -2054,7 +2052,7 @@ void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose) { num_to_bytes( k_sector[sector].Key[0], 6, memBlock); num_to_bytes( k_sector[sector].Key[1], 6, memBlock+10); //iceman, guessing this will not work so well for 4K tags. - PrintAndLogEx(NORMAL, "Setting Emulator Memory Block %02d: [%s]" + PrintAndLogEx(INFO, "Setting Emulator Memory Block %02d: [%s]" , (sector*4) + 3 , sprint_hex( memBlock, sizeof(memBlock)) ); @@ -2129,7 +2127,7 @@ int CmdHF14AMf1kSim(const char *Cmd) { UsbCommand resp; if(flags & FLAG_INTERACTIVE) { - PrintAndLogEx(NORMAL, "Press pm3-button or send another cmd to abort simulation"); + PrintAndLogEx(INFO, "Press pm3-button or send another cmd to abort simulation"); while( !ukbhit() ){ if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; @@ -2165,8 +2163,8 @@ int CmdHF14AMfSniff(const char *Cmd){ memset(uid, 0x00, sizeof(uid)); - char ctmp = param_getchar(Cmd, 0); - if ( ctmp == 'h' || ctmp == 'H' ) return usage_hf14_sniff(); + char ctmp = tolower(param_getchar(Cmd, 0)); + if ( ctmp == 'h') return usage_hf14_sniff(); for (int i = 0; i < 4; i++) { ctmp = tolower(param_getchar(Cmd, i)); @@ -2193,7 +2191,7 @@ int CmdHF14AMfSniff(const char *Cmd){ printf("."); fflush(stdout); if (ukbhit()) { int gc = getchar(); (void)gc; - PrintAndLogEx(NORMAL, "\n[!] aborted via keyboard!\n"); + PrintAndLogEx(INFO, "\naborted via keyboard!\n"); break; } @@ -2496,7 +2494,7 @@ int CmdHF14AMfELoad(const char *Cmd) { return 4; } } - PrintAndLogEx(SUCCESS, "Loaded %d blocks from file: %s", blockNum, filename); + PrintAndLogEx(SUCCESS, "Loaded %d blocks from file: " _YELLOW_(%s), blockNum, filename); return 0; } @@ -2804,8 +2802,8 @@ int CmdHF14AMfCGetBlk(const char *Cmd) { int res; memset(data, 0x00, sizeof(data)); - char ctmp = param_getchar(Cmd, 0); - if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_hf14_cgetblk(); + char ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_cgetblk(); blockNo = param_get8(Cmd, 0); @@ -2840,8 +2838,8 @@ int CmdHF14AMfCGetSc(const char *Cmd) { uint8_t sector = 0; int i, res, flags; - char ctmp = param_getchar(Cmd, 0); - if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_hf14_cgetsc(); + char ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_cgetsc(); sector = param_get8(Cmd, 0); if (sector > 39) { @@ -2979,8 +2977,8 @@ int CmdHF14AMfCSave(const char *Cmd) { //needs nt, ar, at, Data to decrypt int CmdHf14AMfDecryptBytes(const char *Cmd){ - char ctmp = param_getchar(Cmd, 0); - if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_hf14_decryptbytes(); + char ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_decryptbytes(); uint32_t nt = param_get32ex(Cmd,0,0,16); uint32_t ar_enc = param_get32ex(Cmd,1,0,16); @@ -3031,7 +3029,7 @@ int CmdHf14AMfSetMod(const char *Cmd) { UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { uint8_t ok = resp.arg[0] & 0xff; - PrintAndLogEx(NORMAL, "isOk:%02x", ok); + PrintAndLogEx(SUCCESS, "isOk:%02x", ok); if (!ok) PrintAndLogEx(FAILED, "Failed."); } else { @@ -3044,12 +3042,12 @@ int CmdHf14AMfSetMod(const char *Cmd) { int CmdHf14AMfNack(const char *Cmd) { bool verbose = false; - char ctmp = param_getchar(Cmd, 0); - if ( ctmp == 'h' || ctmp == 'H' ) return usage_hf14_nack(); - if ( ctmp == 'v' || ctmp == 'V' ) verbose = true; + char ctmp = tolower(param_getchar(Cmd, 0)); + if ( ctmp == 'h' ) return usage_hf14_nack(); + if ( ctmp == 'v' ) verbose = true; if ( verbose ) - PrintAndLogEx(NORMAL, "Started testing card for NACK bug. Press key to abort"); + PrintAndLogEx(INFO, "Started testing card for NACK bug. Press key to abort"); detect_classic_nackbug(verbose); return 0; @@ -3107,7 +3105,7 @@ int CmdHF14AMfice(const char *Cmd) { PrintAndLogEx(NORMAL, "Collecting %u nonces \n", limit); if ((fnonces = fopen(filename,"wb")) == NULL) { - PrintAndLogEx(WARNING, "Could not create file %s",filename); + PrintAndLogEx(WARNING, "Could not create file " _YELLOW_(%s),filename); return 3; } @@ -3118,7 +3116,7 @@ int CmdHF14AMfice(const char *Cmd) { do { if (ukbhit()) { int gc = getchar(); (void)gc; - PrintAndLogEx(NORMAL, "\naborted via keyboard!\n"); + PrintAndLogEx(INFO, "\naborted via keyboard!\n"); break; } @@ -3140,7 +3138,7 @@ int CmdHF14AMfice(const char *Cmd) { total_num_nonces += items; if ( total_num_nonces > part_limit ) { - PrintAndLogEx(NORMAL, "Total nonces %u\n", total_num_nonces); + PrintAndLogEx(INFO, "Total nonces %u\n", total_num_nonces); part_limit += 3000; } @@ -3151,7 +3149,7 @@ int CmdHF14AMfice(const char *Cmd) { } while (!acquisition_completed); out: - PrintAndLogEx(NORMAL, "time: %" PRIu64 " seconds\n", (msclock()-t1)/1000); + PrintAndLogEx(SUCCESS, "time: %" PRIu64 " seconds\n", (msclock()-t1)/1000); if ( fnonces ) { fflush(fnonces); From 0997c558004593b255bf0e91393a4cfe7ef8d471 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 18 Feb 2019 16:07:39 +0100 Subject: [PATCH 0497/1938] chg: colors --- client/cmdhfmfu.c | 61 +++++++++++++++++++++-------------------------- 1 file changed, 27 insertions(+), 34 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 0a7e77b1c..6f189fabb 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -980,11 +980,11 @@ int CmdHF14AMfUInfo(const char *Cmd){ if ( hasAuthKey ) return 1; // also try to diversify default keys.. look into CmdHF14AMfuGenDiverseKeys - PrintAndLogEx(NORMAL, "Trying some default 3des keys"); + PrintAndLogEx(INFO, "Trying some default 3des keys"); for (uint8_t i = 0; i < KEYS_3DES_COUNT; ++i ) { key = default_3des_keys[i]; if (ulc_authentication(key, true)) { - PrintAndLogEx(NORMAL, "Found default 3des key: "); + PrintAndLogEx(SUCCESS, "Found default 3des key: "); uint8_t keySwap[16]; memcpy(keySwap, SwapEndian64(key,16,8), 16); ulc_print_3deskey(keySwap); @@ -1079,7 +1079,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ num_to_bytes( ul_ev1_pwdgenA(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(NORMAL, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); goto out; } @@ -1089,7 +1089,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ num_to_bytes( ul_ev1_pwdgenB(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(NORMAL, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); goto out; } @@ -1099,7 +1099,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ num_to_bytes( ul_ev1_pwdgenC(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(NORMAL, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); goto out; } @@ -1109,7 +1109,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ num_to_bytes( ul_ev1_pwdgenD(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(NORMAL, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); goto out; } @@ -1119,13 +1119,13 @@ int CmdHF14AMfUInfo(const char *Cmd){ key = default_pwd_pack[i]; len = ulev1_requestAuthentication(key, pack, sizeof(pack)); if (len > -1) { - PrintAndLogEx(NORMAL, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); + PrintAndLogEx(SUCCESS, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); break; } else { if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; } } - if (len < 1) PrintAndLogEx(NORMAL, "password not known"); + if (len < 1) PrintAndLogEx(WARNING, "password not known"); } } out: @@ -1250,7 +1250,7 @@ int CmdHF14AMfUWrBl(const char *Cmd){ UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { uint8_t isOK = resp.arg[0] & 0xff; - PrintAndLogEx(NORMAL, "isOk:%02x", isOK); + PrintAndLogEx(SUCCESS, "isOk:%02x", isOK); } else { PrintAndLogEx(WARNING, "Command execute timeout"); } @@ -1365,7 +1365,7 @@ int CmdHF14AMfURdBl(const char *Cmd){ PrintAndLogEx(WARNING, "Failed reading block: (%02x)", isOK); } } else { - PrintAndLogEx(NORMAL, "Command execute time-out"); + PrintAndLogEx(WARNING, "Command execute time-out"); } return 0; } @@ -1912,12 +1912,10 @@ int CmdHF14AMfURestore(const char *Cmd){ memset(authkey, 0x00, sizeof(authkey)); while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': - case 'H': return usage_hf_mfu_restore(); case 'k': - case 'K': keylen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (keylen == 32 || keylen == 8) { //ul-c or ev1/ntag key length errors = param_gethex(tempStr, 0, authkey, keylen); @@ -1930,12 +1928,10 @@ int CmdHF14AMfURestore(const char *Cmd){ hasKey = true; break; case 'l': - case 'L': swapEndian = true; cmdp++; break; case 'f': - case 'F': filelen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); if (filelen > FILE_PATH_SIZE-5) @@ -1947,17 +1943,14 @@ int CmdHF14AMfURestore(const char *Cmd){ cmdp += 2; break; case 's': - case 'S': cmdp++; write_special = true; break; case 'e': - case 'E': cmdp++; write_extra = true; break; case 'r': - case 'R': cmdp++; read_key = true; break; @@ -1972,7 +1965,7 @@ int CmdHF14AMfURestore(const char *Cmd){ if (errors || cmdp == 0) return usage_hf_mfu_restore(); if ((f = fopen(filename,"rb")) == NULL) { - PrintAndLogEx(WARNING, "Could not find file %s", filename); + PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), filename); return 1; } @@ -2000,7 +1993,7 @@ int CmdHF14AMfURestore(const char *Cmd){ return 1; } - PrintAndLogEx(NORMAL, "Restoring %s to card", filename); + PrintAndLogEx(INFO, "Restoring " _YELLOW_(%s)" to card", filename); mfu_dump_t *mem = (mfu_dump_t*)dump; uint8_t pages = (bytes_read-48)/4; @@ -2084,7 +2077,7 @@ int CmdHF14AMfURestore(const char *Cmd){ } } - PrintAndLogEx(NORMAL, "Restoring data blocks."); + PrintAndLogEx(INFO, "Restoring data blocks."); // write all other data // Skip block 0,1,2,3 (only magic tags can write to them) // Skip last 5 blocks usually is configuration @@ -2103,7 +2096,7 @@ int CmdHF14AMfURestore(const char *Cmd){ // write special data last if (write_special) { - PrintAndLogEx(NORMAL, "Restoring configuration blocks.\n"); + PrintAndLogEx(INFO, "Restoring configuration blocks.\n"); PrintAndLogEx(NORMAL, "authentication with keytype[%x] %s\n", (uint8_t)(c.arg[1] & 0xff), sprint_hex(p_authkey,4)); @@ -2128,16 +2121,16 @@ int CmdHF14AMfURestore(const char *Cmd){ // Load emulator with dump file // int CmdHF14AMfUeLoad(const char *Cmd){ - char c = param_getchar(Cmd, 0); - if ( c == 'h' || c == 'H' || c == 0x00) return usage_hf_mfu_eload(); + char c = tolower(param_getchar(Cmd, 0)); + if ( c == 'h' || c == 0x00) return usage_hf_mfu_eload(); return CmdHF14AMfELoad(Cmd); } // // Simulate tag // int CmdHF14AMfUSim(const char *Cmd){ - char c = param_getchar(Cmd, 0); - if ( c == 'h' || c == 'H' || c == 0x00) return usage_hf_mfu_sim(); + char c = tolower(param_getchar(Cmd, 0)); + if ( c == 'h' || c == 0x00) return usage_hf_mfu_sim(); return CmdHF14ASim(Cmd); } @@ -2153,16 +2146,16 @@ int CmdHF14AMfucAuth(const char *Cmd){ uint8_t keyNo = 3; bool errors = false; - char cmdp = param_getchar(Cmd, 0); + char cmdp = tolower(param_getchar(Cmd, 0)); //Change key to user defined one - if (cmdp == 'k' || cmdp == 'K'){ + if (cmdp == 'k'){ keyNo = param_get8(Cmd, 1); if(keyNo >= KEYS_3DES_COUNT) errors = true; } - if (cmdp == 'h' || cmdp == 'H') errors = true; + if (cmdp == 'h') errors = true; if (errors) return usage_hf_mfu_ucauth(); @@ -2278,9 +2271,9 @@ int CmdTestDES(const char * cmd) int CmdHF14AMfucSetPwd(const char *Cmd){ uint8_t pwd[16] = {0x00}; - char cmdp = param_getchar(Cmd, 0); + char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_hf_mfu_ucsetpwd(); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_ucsetpwd(); if (param_gethex(Cmd, 0, pwd, 32)) { PrintAndLogEx(WARNING, "Password must include 32 HEX symbols"); @@ -2295,7 +2288,7 @@ int CmdHF14AMfucSetPwd(const char *Cmd){ UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { if ( (resp.arg[0] & 0xff) == 1) { - PrintAndLogEx(NORMAL, "Ultralight-C new password: %s", sprint_hex(pwd,16)); + PrintAndLogEx(INFO, "Ultralight-C new password: %s", sprint_hex(pwd,16)); } else { PrintAndLogEx(WARNING, "Failed writing at block %d", resp.arg[1] & 0xff); return 1; @@ -2315,9 +2308,9 @@ int CmdHF14AMfucSetUid(const char *Cmd){ UsbCommand c = {CMD_MIFAREU_READBL}; UsbCommand resp; uint8_t uid[7] = {0x00}; - char cmdp = param_getchar(Cmd, 0); + char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_hf_mfu_ucsetuid(); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_ucsetuid(); if (param_gethex(Cmd, 0, uid, 14)) { PrintAndLogEx(WARNING, "UID must include 14 HEX symbols"); From a4f6701c85a4e5f3e0438759c5854246938ff9b8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 18 Feb 2019 16:16:24 +0100 Subject: [PATCH 0498/1938] chg: cleaning --- client/cmdhf15.c | 56 ++++++++++++++++++++++++++---------------------- 1 file changed, 30 insertions(+), 26 deletions(-) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 41d6ee8cd..2800b0c9c 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -764,7 +764,7 @@ int CmdHF15Dump(const char*Cmd) { } int CmdHF15Restore(const char*Cmd) { - FILE *file; + FILE *f; uint8_t uid[8]={0x00}; char filename[FILE_PATH_SIZE] = {0x00}; @@ -774,10 +774,10 @@ int CmdHF15Restore(const char*Cmd) { char newCmdPrefix[255] = {0x00}, tmpCmd[255] = {0x00}; char param[FILE_PATH_SIZE]=""; char hex[255]=""; - uint8_t retries = 3, tried = 0; + uint8_t retries = 3, tried = 0, i = 0; int retval=0; size_t bytes_read; - uint8_t i=0; + while(param_getchar(Cmd, cmdp) != 0x00) { switch(tolower(param_getchar(Cmd, cmdp))) { case '-': @@ -785,7 +785,8 @@ int CmdHF15Restore(const char*Cmd) { switch(param[1]) { case '2': - case 'o': strncpy(newCmdPrefix, " ",sizeof(newCmdPrefix)-1); + case 'o': + strncpy(newCmdPrefix, " ", sizeof(newCmdPrefix)-1); strncat(newCmdPrefix, param, sizeof(newCmdPrefix)-1); break; default: @@ -815,18 +816,18 @@ int CmdHF15Restore(const char*Cmd) { default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); return usage_15_restore(); - break; } cmdp++; } + PrintAndLogEx(INFO,"Blocksize: %u",blocksize); - if(filename[0]=='\0') - { + + if ( !strlen(filename)) { PrintAndLogEx(WARNING,"Please provide a filename"); - return 1; + return usage_15_restore(); } - if ((file = fopen(filename,"rb")) == NULL) { + if ((f = fopen(filename, "rb")) == NULL) { PrintAndLogEx(WARNING, "Could not find file %s", filename); return 2; } @@ -835,40 +836,43 @@ int CmdHF15Restore(const char*Cmd) { PrintAndLogEx(WARNING, "No tag found"); return 3; } + while (1) { - tried=0; - hex[0]=0x00; - tmpCmd[0]=0x00; + tried = 0; + hex[0] = 0x00; + tmpCmd[0] = 0x00; - bytes_read = fread( buff, 1, blocksize, file ); + bytes_read = fread( buff, 1, blocksize, f ); if ( bytes_read == 0) { - PrintAndLogEx(SUCCESS, "File reading done (%s).", filename); - fclose(file); + PrintAndLogEx(SUCCESS, "File reading done `%s`", filename); + fclose(f); return 0; - } - else if ( bytes_read != blocksize) { + } else if ( bytes_read != blocksize) { PrintAndLogEx(WARNING, "File reading error (%s), %u bytes read instead of %u bytes.", filename, bytes_read, blocksize); - fclose(file); + fclose(f); return 2; } - for(int j=0;j= retries) return retval; + i++; } - fclose(file); + fclose(f); } int CmdHF15List(const char *Cmd) { From 5ec82a0dc4499cc7daf4f975a10757ca0c640015 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 18 Feb 2019 16:27:56 +0100 Subject: [PATCH 0499/1938] chg: adjustments --- client/cmdhfmfu.c | 54 +++++++++++++++++++++++------------------------ 1 file changed, 27 insertions(+), 27 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 6f189fabb..e583f7f02 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -518,57 +518,57 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces){ char *spacer = spc + (10-spaces); if ( tagtype & UL ) - PrintAndLogEx(SUCCESS, "%sTYPE : MIFARE Ultralight (MF0ICU1) %s", spacer, (tagtype & MAGIC) ? "" : "" ); + PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight (MF0ICU1) %s", spacer, (tagtype & MAGIC) ? "" : "" ); else if ( tagtype & UL_C) - PrintAndLogEx(SUCCESS, "%sTYPE : MIFARE Ultralight C (MF0ULC) %s", spacer, (tagtype & MAGIC) ? "" : "" ); + PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight C (MF0ULC) %s", spacer, (tagtype & MAGIC) ? "" : "" ); else if ( tagtype & UL_NANO_40) - PrintAndLogEx(SUCCESS, "%sTYPE : MIFARE Ultralight Nano 40bytes (MF0UNH00)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight Nano 40bytes (MF0UNH00)", spacer); else if ( tagtype & UL_EV1_48) - PrintAndLogEx(SUCCESS, "%sTYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)", spacer); else if ( tagtype & UL_EV1_128) - PrintAndLogEx(SUCCESS, "%sTYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)", spacer); else if ( tagtype & UL_EV1 ) - PrintAndLogEx(SUCCESS, "%sTYPE : MIFARE Ultralight EV1 UNKNOWN", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight EV1 UNKNOWN", spacer); else if ( tagtype & NTAG ) - PrintAndLogEx(SUCCESS, "%sTYPE : NTAG UNKNOWN", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG UNKNOWN", spacer); else if ( tagtype & NTAG_203 ) - PrintAndLogEx(SUCCESS, "%sTYPE : NTAG 203 144bytes (NT2H0301F0DT)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG 203 144bytes (NT2H0301F0DT)", spacer); else if ( tagtype & NTAG_210 ) - PrintAndLogEx(SUCCESS, "%sTYPE : NTAG 210 48bytes (NT2L1011G0DU)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG 210 48bytes (NT2L1011G0DU)", spacer); else if ( tagtype & NTAG_212 ) - PrintAndLogEx(SUCCESS, "%sTYPE : NTAG 212 128bytes (NT2L1211G0DU)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG 212 128bytes (NT2L1211G0DU)", spacer); else if ( tagtype & NTAG_213 ) - PrintAndLogEx(SUCCESS, "%sTYPE : NTAG 213 144bytes (NT2H1311G0DU)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG 213 144bytes (NT2H1311G0DU)", spacer); else if ( tagtype & NTAG_213_F ) - PrintAndLogEx(SUCCESS, "%sTYPE : NTAG 213F 144bytes (NT2H1311F0DTL)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG 213F 144bytes (NT2H1311F0DTL)", spacer); else if ( tagtype & NTAG_215 ) - PrintAndLogEx(SUCCESS, "%sTYPE : NTAG 215 504bytes (NT2H1511G0DU)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG 215 504bytes (NT2H1511G0DU)", spacer); else if ( tagtype & NTAG_216 ) - PrintAndLogEx(SUCCESS, "%sTYPE : NTAG 216 888bytes (NT2H1611G0DU)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG 216 888bytes (NT2H1611G0DU)", spacer); else if ( tagtype & NTAG_216_F ) - PrintAndLogEx(SUCCESS, "%sTYPE : NTAG 216F 888bytes (NT2H1611F0DTL)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG 216F 888bytes (NT2H1611F0DTL)", spacer); else if ( tagtype & NTAG_I2C_1K ) - PrintAndLogEx(SUCCESS, "%sTYPE : NTAG I%sC 888bytes (NT3H1101FHK)", spacer, "\xFD"); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG I%sC 888bytes (NT3H1101FHK)", spacer, "\xFD"); else if ( tagtype & NTAG_I2C_2K ) - PrintAndLogEx(SUCCESS, "%sTYPE : NTAG I%sC 1904bytes (NT3H1201FHK)", spacer, "\xFD"); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG I%sC 1904bytes (NT3H1201FHK)", spacer, "\xFD"); else if ( tagtype & NTAG_I2C_1K_PLUS ) - PrintAndLogEx(SUCCESS, "%sTYPE : NTAG I%sC plus 888bytes (NT3H2111FHK)", spacer, "\xFD"); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG I%sC plus 888bytes (NT3H2111FHK)", spacer, "\xFD"); else if ( tagtype & NTAG_I2C_2K_PLUS ) - PrintAndLogEx(SUCCESS, "%sTYPE : NTAG I%sC plus 1912bytes (NT3H2211FHK)", spacer, "\xFD"); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG I%sC plus 1912bytes (NT3H2211FHK)", spacer, "\xFD"); else if ( tagtype & MY_D ) - PrintAndLogEx(SUCCESS, "%sTYPE : INFINEON my-d\x99 (SLE 66RxxS)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 (SLE 66RxxS)", spacer); else if ( tagtype & MY_D_NFC ) - PrintAndLogEx(SUCCESS, "%sTYPE : INFINEON my-d\x99 NFC (SLE 66RxxP)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 NFC (SLE 66RxxP)", spacer); else if ( tagtype & MY_D_MOVE ) - PrintAndLogEx(SUCCESS, "%sTYPE : INFINEON my-d\x99 move (SLE 66R01P)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 move (SLE 66R01P)", spacer); else if ( tagtype & MY_D_MOVE_NFC ) - PrintAndLogEx(SUCCESS, "%sTYPE : INFINEON my-d\x99 move NFC (SLE 66R01P)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 move NFC (SLE 66R01P)", spacer); else if ( tagtype & MY_D_MOVE_LEAN ) - PrintAndLogEx(SUCCESS, "%sTYPE : INFINEON my-d\x99 move lean (SLE 66R01L)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 move lean (SLE 66R01L)", spacer); else if ( tagtype & FUDAN_UL ) - PrintAndLogEx(SUCCESS, "%sTYPE : FUDAN Ultralight Compatible (or other compatible) %s", spacer, (tagtype & MAGIC) ? "" : "" ); + PrintAndLogEx(NORMAL, "%sTYPE : FUDAN Ultralight Compatible (or other compatible) %s", spacer, (tagtype & MAGIC) ? "" : "" ); else - PrintAndLogEx(SUCCESS, "%sTYPE : Unknown %06x", spacer, tagtype); + PrintAndLogEx(NORMAL, "%sTYPE : Unknown %06x", spacer, tagtype); return 0; } @@ -606,7 +606,7 @@ static int ulc_print_configuration( uint8_t *data){ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t startPage){ - PrintAndLogEx(SUCCESS, "\n--- Tag Configuration"); + PrintAndLogEx(NORMAL, "\n--- Tag Configuration"); bool strg_mod_en = (data[0] & 2); uint8_t authlim = (data[4] & 0x07); From 1e98c4621d5ea2ee97dcb2247b6c62fbdb2bdc91 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 18 Feb 2019 16:30:57 +0100 Subject: [PATCH 0500/1938] chg: colors --- client/loclass/fileutils.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 0751f838b..6078ec4f9 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -245,7 +245,7 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty retval = 200; goto out; } - PrintAndLogDevice(SUCCESS, "File `" _YELLOW_(%s)"` saved.", fileName); + PrintAndLogDevice(SUCCESS, "Save to json file " _YELLOW_(%s), fileName); json_decref(root); out: @@ -445,7 +445,7 @@ int loadFileJSON(const char *preferredName, const char *suffix, void* data, size } - PrintAndLog("Loaded JSON: " _YELLOW_(%s) " OK.", fileName); + PrintAndLog("loaded from JSON file " _YELLOW_(%s), fileName); out: json_decref(root); free(fileName); From 58f35d50a628cf34977db08b659429db3e4bc10a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 18 Feb 2019 16:32:13 +0100 Subject: [PATCH 0501/1938] chg: textual --- client/loclass/fileutils.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 6078ec4f9..da91b21ec 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -245,7 +245,7 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty retval = 200; goto out; } - PrintAndLogDevice(SUCCESS, "Save to json file " _YELLOW_(%s), fileName); + PrintAndLogDevice(SUCCESS, "saved to json file " _YELLOW_(%s), fileName); json_decref(root); out: From b320ebca7c03d8add91c3d65860fdcaf824103f9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 18 Feb 2019 16:39:39 +0100 Subject: [PATCH 0502/1938] chg: textual --- client/cmdhfmf.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index e9b1bed10..e2dc16efd 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1,4 +1,4 @@ -//----------------------------------------------------------------------------- +1//----------------------------------------------------------------------------- // Copyright (C) 2011,2012 Merlok // // This code is licensed to you under the terms of the GNU GPL, version 2 or, @@ -1235,8 +1235,8 @@ int CmdHF14AMfNested(const char *Cmd) { if (e_sector[i].foundKey[1]) num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]); mfEmlSetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); - PrintAndLogEx(SUCCESS, "key transferred to emulator memory."); - } + } + PrintAndLogEx(SUCCESS, "key transferred to emulator memory."); } // Create dump file From 72cf200df7b0d17f1f38117f71788fefea40edfe Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 18 Feb 2019 16:43:27 +0100 Subject: [PATCH 0503/1938] chg.... --- client/cmdhfmf.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index e2dc16efd..47646852e 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1,4 +1,4 @@ -1//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- // Copyright (C) 2011,2012 Merlok // // This code is licensed to you under the terms of the GNU GPL, version 2 or, From 26bca369292dc7cb6ae39762555c4bbf6e250ff1 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 19 Feb 2019 18:39:05 +0200 Subject: [PATCH 0504/1938] delete comment --- client/emv/emvcore.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 6ccee471c..7af08690c 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -263,7 +263,6 @@ int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveField break; case ECC_CONTACT: #ifdef WITH_SMARTCARD - //int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); res = ExchangeAPDUSC(data, (IncludeLe?6:5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); #else res = 1; From 56c9bcc03a6d4c42e3aea902eb5d7d3c7bfb8651 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 19 Feb 2019 21:15:54 +0200 Subject: [PATCH 0505/1938] added IAD decoding and some improvements --- client/emv/cmdemv.c | 75 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 70 insertions(+), 5 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index d0015ac38..477062d38 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1212,16 +1212,79 @@ int CmdEMVExec(const char *cmd) { if ((CID & EMVAC_AC_MASK) == EMVAC_ARQC) PrintAndLogEx(INFO, "AC1 result: ARQC (Online authorisation requested)"); if ((CID & EMVAC_AC_MASK) == EMVAC_AC_MASK) PrintAndLogEx(INFO, "AC1 result: RFU"); - PrintAndLogEx(NORMAL, "\n* * Processing online request\n"); + // decode Issuer Application Data (IAD) + uint8_t CryptoVersion = 0; + const struct tlv *IAD = tlvdb_get(tlvRoot, 0x9f10, NULL); + if (IAD && (IAD->len > 1)) { + PrintAndLogEx(NORMAL, "\n* * Issuer Application Data (IAD):"); + uint8_t VDDlen = IAD->value[0]; // Visa discretionary data length + uint8_t IDDlen = 0; // Issuer discretionary data length + PrintAndLogEx(NORMAL, "IAD length: %d", IAD->len); + PrintAndLogEx(NORMAL, "VDDlen: %d", VDDlen); + if (VDDlen < IAD->len - 1) + IDDlen = IAD->value[VDDlen + 1]; + PrintAndLogEx(NORMAL, "IDDlen: %d", IDDlen); + + uint8_t DerivKeyIndex = IAD->value[1]; + CryptoVersion = IAD->value[2]; + + PrintAndLogEx(NORMAL, "CryptoVersion: %d", CryptoVersion); + PrintAndLogEx(NORMAL, "DerivKeyIndex: %d", DerivKeyIndex); + + // Card Verification Results (CVR) decode + if ((VDDlen - 2) > 0) { + uint8_t CVRlen = IAD->value[3]; + if (CVRlen == (VDDlen - 2 - 1)) { + PrintAndLogEx(NORMAL, "CVR length: %d", CVRlen); + PrintAndLogEx(NORMAL, "CVR: %s", sprint_hex(&IAD->value[4], CVRlen)); + } else { + PrintAndLogEx(NORMAL, "Wrong CVR length! CVR: %s", sprint_hex(&IAD->value[3], VDDlen - 2)); + } + } + if (IDDlen) + PrintAndLogEx(NORMAL, "IDD: %s", sprint_hex(&IAD->value[VDDlen + 1], IDDlen)); + } else { + PrintAndLogEx(NORMAL, "Issuer Application Data (IAD) not found."); + } + + PrintAndLogEx(NORMAL, "\n* * Processing online request"); // authorization response code from acquirer const char HostResponse[] = "00"; // 0x3030 - PrintAndLogEx(NORMAL, "* * Host Response: `%s`", HostResponse); - tlvdb_change_or_add_node(tlvRoot, 0x8a, sizeof(HostResponse) - 1, (const unsigned char *)HostResponse); + size_t HostResponseLen = sizeof(HostResponse) - 1; + PrintAndLogEx(NORMAL, "Host Response: `%s`", HostResponse); + tlvdb_change_or_add_node(tlvRoot, 0x8a, HostResponseLen, (const unsigned char *)HostResponse); + if (CryptoVersion == 10) { + PrintAndLogEx(NORMAL, "\n* * Generate ARPC"); + + // Application Cryptogram (AC) + const struct tlv *AC = tlvdb_get(tlvRoot, 0x9f26, NULL); + if (AC && (AC->len > 0)) { + PrintAndLogEx(NORMAL, "AC: %s", sprint_hex(AC->value, AC->len)); + + size_t rawARPClen = AC->len; + uint8_t rawARPC[rawARPClen]; + memcpy(rawARPC, AC->value, AC->len); + for (int i = 0; (i < HostResponseLen) && (i < rawARPClen); i++) + rawARPC[i] ^= HostResponse[i]; + PrintAndLogEx(NORMAL, "raw ARPC: %s", sprint_hex(rawARPC, rawARPClen)); + + // here must be calculation of ARPC, but we dont know a bank keys. + PrintAndLogEx(NORMAL, "ARPC: n/a"); + + } else { + PrintAndLogEx(NORMAL, "Application Cryptogram (AC) not found."); + } + + // here must be external authenticate, but we dont know ARPC + + } + + // needs to send AC2 command (res == ARQC) if ((CID & 0xc0) == 0x80) { - PrintAndLogEx(NORMAL, "* * Calc CDOL2"); + PrintAndLogEx(NORMAL, "\n* * Calc CDOL2"); struct tlv *cdol2_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8d, NULL), tlvRoot, 0x01); // 0x01 - dummy tag if (!cdol2_data_tlv) { PrintAndLogEx(WARNING, "Error: can't create CDOL2 TLV."); @@ -1230,9 +1293,11 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "CDOL2 data[%d]: %s", cdol2_data_tlv->len, sprint_hex(cdol2_data_tlv->value, cdol2_data_tlv->len)); - PrintAndLogEx(NORMAL, "* * AC2"); + //PrintAndLogEx(NORMAL, "* * AC2"); + // here must be AC2, but we dont make external authenticate ( + /* // AC2 PRINT_INDENT(level); if ((CID & EMVAC_AC2_MASK) == EMVAC_AAC2) fprintf(f, "\tAC2: AAC (Transaction declined)\n"); From 25d6a1274f33d8cb9a34586ebecc8af29af0236c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 19 Feb 2019 21:19:45 +0200 Subject: [PATCH 0506/1938] small improvement --- client/emv/cmdemv.c | 2 +- client/emv/emvcore.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 477062d38..e2988e1e7 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1283,7 +1283,7 @@ int CmdEMVExec(const char *cmd) { // needs to send AC2 command (res == ARQC) - if ((CID & 0xc0) == 0x80) { + if ((CID & EMVAC_AC_MASK) == EMVAC_ARQC) { PrintAndLogEx(NORMAL, "\n* * Calc CDOL2"); struct tlv *cdol2_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8d, NULL), tlvRoot, 0x01); // 0x01 - dummy tag if (!cdol2_data_tlv) { diff --git a/client/emv/emvcore.h b/client/emv/emvcore.h index 7d53e83bb..9aaaf2e6f 100644 --- a/client/emv/emvcore.h +++ b/client/emv/emvcore.h @@ -39,7 +39,7 @@ typedef enum { enum TransactionType { TT_MSD, - TT_VSDC, // not standart for contactless!!!! + TT_VSDC, // contact only. not standart for contactless TT_QVSDCMCHIP, TT_CDA, }; From e793fa8d73d4cf4e9fe6c16e4447beb4c6e9df74 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 19 Feb 2019 21:28:19 +0200 Subject: [PATCH 0507/1938] fix tlvdb_get_uint8 --- client/emv/tlv.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/emv/tlv.c b/client/emv/tlv.c index 8d1429640..0daedaf47 100644 --- a/client/emv/tlv.c +++ b/client/emv/tlv.c @@ -551,8 +551,7 @@ struct tlvdb *tlvdb_elm_get_parent(struct tlvdb *tlvdb) bool tlvdb_get_uint8(struct tlvdb *tlvRoot, tlv_tag_t tag, uint8_t *value) { - const struct tlvdb *tlvdb = tlvdb_get(tlvRoot, tag, NULL); - const struct tlv *tlvelm = tlvdb_get_tlv(tlvdb); + const struct tlv *tlvelm = tlvdb_get(tlvRoot, tag, NULL); return tlv_get_uint8(tlvelm, value); } From 3d7cf1e9b764dacbdcf39e9b582915eb1a0fe23e Mon Sep 17 00:00:00 2001 From: Chris Date: Wed, 20 Feb 2019 11:29:40 +0100 Subject: [PATCH 0508/1938] chg: text --- client/cmdmain.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdmain.c b/client/cmdmain.c index 5b147e76a..9b71df21d 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -24,14 +24,14 @@ static command_t CommandTable[] = { {"lf", CmdLF, 1, "{ Low Frequency commands... }"}, {"emv", CmdEMV, 1, "{ EMV iso14443 and iso7816... }"}, {"rem", CmdRem, 1, "{ Add text to row in log file }"}, - {"reveng", CmdRev, 1, "{ Crc calculations from the software reveng 1.53... }"}, + {"reveng", CmdRev, 1, "{ Crc calculations from the RevEng software... }"}, {"script", CmdScript, 1, "{ Scripting commands }"}, {"trace", CmdTrace, 1, "{ Trace manipulation... }"}, #ifdef WITH_FLASH - {"mem", CmdFlashMem, 1, "{ RDV40, Flash Memory manipulation... }"}, + {"mem", CmdFlashMem, 1, "{ Flash Memory manipulation... }"}, #endif #ifdef WITH_SMARTCARD - {"sc", CmdSmartcard, 1, "{ RDV40, Smart card ISO7816 commands... }"}, + {"sc", CmdSmartcard, 1, "{ Smart card ISO7816 commands... }"}, #endif {"quit", CmdQuit, 1, ""}, {"exit", CmdQuit, 1, "Exit program"}, From 915c73bcfc9dcd74997d999529e450216d2633f8 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 20 Feb 2019 14:48:52 +0200 Subject: [PATCH 0509/1938] fix possible error --- client/emv/tlv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/emv/tlv.c b/client/emv/tlv.c index 0daedaf47..31b5ea360 100644 --- a/client/emv/tlv.c +++ b/client/emv/tlv.c @@ -353,6 +353,9 @@ struct tlvdb *tlvdb_find_path(struct tlvdb *tlvdb, tlv_tag_t tag[]) { void tlvdb_add(struct tlvdb *tlvdb, struct tlvdb *other) { while (tlvdb->next) { + if (tlvdb->next == other) + return; + tlvdb = tlvdb->next; } From d81478755e23832505af7aeb64dfbc659c432cd7 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 20 Feb 2019 14:50:17 +0200 Subject: [PATCH 0510/1938] 2nd fix --- client/emv/tlv.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/client/emv/tlv.c b/client/emv/tlv.c index 31b5ea360..a309d0659 100644 --- a/client/emv/tlv.c +++ b/client/emv/tlv.c @@ -352,6 +352,9 @@ struct tlvdb *tlvdb_find_path(struct tlvdb *tlvdb, tlv_tag_t tag[]) { void tlvdb_add(struct tlvdb *tlvdb, struct tlvdb *other) { + if (tlvdb == other) + return; + while (tlvdb->next) { if (tlvdb->next == other) return; From 8e199d4c9e67197fb8576132e8f8c056287d6514 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 20 Feb 2019 15:51:55 +0200 Subject: [PATCH 0511/1938] add get ATR to cmdsmartcard --- client/cmdsmartcard.c | 21 +++++++++++++-------- client/cmdsmartcard.h | 1 + 2 files changed, 14 insertions(+), 8 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 23b2b8b3c..9496b5445 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -292,7 +292,10 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { return 0; } -static bool smart_select(bool silent) { +bool smart_select(bool silent, smart_card_atr_t *atr) { + if (atr) + memset(atr, 0, sizeof(smart_card_atr_t)); + UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -308,12 +311,14 @@ static bool smart_select(bool silent) { return false; } - if (!silent) { - smart_card_atr_t card; - memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t)); - + smart_card_atr_t card; + memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t)); + + if (atr) + memcpy(atr, &card, sizeof(smart_card_atr_t)); + + if (!silent) PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len)); - } return true; } @@ -518,7 +523,7 @@ int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leave *dataoutlen = 0; if (activateCard) - smart_select(false); + smart_select(false, NULL); PrintAndLogEx(DEBUG, "APDU SC"); @@ -1017,7 +1022,7 @@ int CmdSmartBruteforceSFI(const char *Cmd) { return 1; PrintAndLogEx(INFO, "Selecting card"); - if ( !smart_select(false) ) + if ( !smart_select(false, NULL) ) return 1; char* caid = NULL; diff --git a/client/cmdsmartcard.h b/client/cmdsmartcard.h index cffaeff98..00bc41ff4 100644 --- a/client/cmdsmartcard.h +++ b/client/cmdsmartcard.h @@ -33,6 +33,7 @@ extern int CmdSmartUpgrade(const char* cmd); extern int CmdSmartInfo(const char* cmd); extern int CmdSmartReader(const char *Cmd); +extern bool smart_select(bool silent, smart_card_atr_t *atr); extern int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); extern int usage_sm_raw(void); From fe66f0fac4f9b6e61b81ac979e43a953f3c6a46b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 20 Feb 2019 15:52:26 +0200 Subject: [PATCH 0512/1938] added contact to `emv scan` --- client/emv/cmdemv.c | 49 ++++++++++++++++++++++++++------------------- 1 file changed, 28 insertions(+), 21 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index e2988e1e7..de86d5343 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1382,12 +1382,6 @@ int CmdEMVScan(const char *cmd) { SetAPDULogging(showAPDU); - // TODO - if (channel == ECC_CONTACT) { - PrintAndLogEx(ERR, "Do not use contact interface. Exit."); - return 1; - } - // current path + file name if (!strstr(crelfname, ".json")) strcat(crelfname, ".json"); @@ -1411,23 +1405,35 @@ int CmdEMVScan(const char *cmd) { } // drop field at start - DropFieldEx( channel ); - - // iso 14443 select - PrintAndLogEx(NORMAL, "--> GET UID, ATS."); - - iso14a_card_select_t card; - if (Hf14443_4aGetCardData(&card)) { - return 2; - } + if (channel == ECC_CONTACTLESS) + DropFieldEx( channel ); JsonSaveStr(root, "$.File.Created", "proxmark3 `emv scan`"); - JsonSaveStr(root, "$.Card.Communication", "iso14443-4a"); - JsonSaveBufAsHex(root, "$.Card.UID", (uint8_t *)&card.uid, card.uidlen); - JsonSaveHex(root, "$.Card.ATQA", card.atqa[0] + (card.atqa[1] << 2), 2); - JsonSaveHex(root, "$.Card.SAK", card.sak, 0); - JsonSaveBufAsHex(root, "$.Card.ATS", (uint8_t *)card.ats, card.ats_len); + if (channel == ECC_CONTACTLESS) { + // iso 14443 select + PrintAndLogEx(NORMAL, "--> GET UID, ATS."); + + iso14a_card_select_t card; + if (Hf14443_4aGetCardData(&card)) { + return 2; + } + + + JsonSaveStr(root, "$.Card.Contactless.Communication", "iso14443-4a"); + JsonSaveBufAsHex(root, "$.Card.Contactless.UID", (uint8_t *)&card.uid, card.uidlen); + JsonSaveHex(root, "$.Card.Contactless.ATQA", card.atqa[0] + (card.atqa[1] << 2), 2); + JsonSaveHex(root, "$.Card.Contactless.SAK", card.sak, 0); + JsonSaveBufAsHex(root, "$.Card.Contactless.ATS", (uint8_t *)card.ats, card.ats_len); + } else { + PrintAndLogEx(NORMAL, "--> GET ATR."); + + smart_card_atr_t card; + smart_select(true, &card); + + JsonSaveStr(root, "$.Card.Contact.Communication", "iso7816"); + JsonSaveBufAsHex(root, "$.Card.Contact.ATR", (uint8_t *)card.atr, card.atr_len); + } // init applets list tree const char *al = "Applets list"; @@ -1642,7 +1648,8 @@ int CmdEMVScan(const char *cmd) { // free tlv object tlvdb_free(tlvRoot); - DropFieldEx( channel ); + if (channel == ECC_CONTACTLESS) + DropFieldEx( channel ); res = json_dump_file(root, fname, JSON_INDENT(2)); if (res) { From ed991e76b4dd638ced3f32485068f84a2a18f528 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 20 Feb 2019 16:04:08 +0200 Subject: [PATCH 0513/1938] add print error if smart card functionality not defined --- client/emv/cmdemv.c | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index de86d5343..6f5917b8d 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -792,6 +792,14 @@ int CmdEMVExec(const char *cmd) { uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; CLIParserFree(); +#ifndef WITH_SMARTCARD + // not compiled with smartcard functionality, we need to exit + if ( channel == ECC_CONTACT ) { + PrintAndLogEx(WARNING, "PM3 Client is not compiled with support for SMARTCARD. Exiting."); + return 0; + } +#endif + SetAPDULogging(showAPDU); // init applets list tree @@ -1380,6 +1388,14 @@ int CmdEMVScan(const char *cmd) { CLIGetStrWithReturn(12, relfname, &relfnamelen); CLIParserFree(); +#ifndef WITH_SMARTCARD + // not compiled with smartcard functionality, we need to exit + if ( channel == ECC_CONTACT ) { + PrintAndLogEx(WARNING, "PM3 Client is not compiled with support for SMARTCARD. Exiting."); + return 0; + } +#endif + SetAPDULogging(showAPDU); // current path + file name @@ -1418,7 +1434,6 @@ int CmdEMVScan(const char *cmd) { if (Hf14443_4aGetCardData(&card)) { return 2; } - JsonSaveStr(root, "$.Card.Contactless.Communication", "iso14443-4a"); JsonSaveBufAsHex(root, "$.Card.Contactless.UID", (uint8_t *)&card.uid, card.uidlen); @@ -1702,6 +1717,7 @@ int CmdEMVRoca(const char *cmd) { if (arg_get_lit(2)) channel = ECC_CONTACT; PrintChannel(channel); + CLIParserFree(); #ifndef WITH_SMARTCARD // not compiled with smartcard functionality, we need to exit From 12582df97657f9fbf7ad8fae431ec5034cd93409 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 20 Feb 2019 16:05:32 +0200 Subject: [PATCH 0514/1938] fix macro --- client/emv/cmdemv.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 6f5917b8d..3e36a4ae6 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1421,8 +1421,7 @@ int CmdEMVScan(const char *cmd) { } // drop field at start - if (channel == ECC_CONTACTLESS) - DropFieldEx( channel ); + DropFieldEx( channel ); JsonSaveStr(root, "$.File.Created", "proxmark3 `emv scan`"); @@ -1663,8 +1662,7 @@ int CmdEMVScan(const char *cmd) { // free tlv object tlvdb_free(tlvRoot); - if (channel == ECC_CONTACTLESS) - DropFieldEx( channel ); + DropFieldEx( channel ); res = json_dump_file(root, fname, JSON_INDENT(2)); if (res) { From 8ddedcb140a73cb04c6106e91b1852d77ef36779 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 20 Feb 2019 17:54:05 +0200 Subject: [PATCH 0515/1938] typo --- client/emv/cmdemv.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index e2988e1e7..3200d84b0 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1199,7 +1199,7 @@ int CmdEMVExec(const char *cmd) { dreturn(7); } - // process Format1 (0x80) anf print Format2 (0x77) + // process Format1 (0x80) and print Format2 (0x77) ProcessACResponseFormat1(tlvRoot, buf, len, decodeTLV); uint8_t CID = 0; From 2c4db1ce7c37528fb343d57841a6c3cddcd4a357 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 20 Feb 2019 19:37:30 +0200 Subject: [PATCH 0516/1938] check ATR length --- client/emv/cmdemv.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 9bb71de76..9728a32b7 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1444,6 +1444,10 @@ int CmdEMVScan(const char *cmd) { smart_card_atr_t card; smart_select(true, &card); + if (!card.atr_len) { + PrintAndLogEx(ERR, "Can't get ATR from a smart card."); + return 1; + } JsonSaveStr(root, "$.Card.Contact.Communication", "iso7816"); JsonSaveBufAsHex(root, "$.Card.Contact.ATR", (uint8_t *)card.atr, card.atr_len); From 54ade5df94eb133486bcc688b45989da847fbab5 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 20 Feb 2019 21:12:06 +0200 Subject: [PATCH 0517/1938] add read sector code --- client/mifarehost.c | 31 +++++++++++++++++++++++++++++++ client/mifarehost.h | 2 +- 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/client/mifarehost.c b/client/mifarehost.c index 31ed8e39d..817f99c93 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -414,6 +414,37 @@ out: return -4; } +// MIFARE +int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data) { + + UsbCommand c = {CMD_MIFARE_READSC, {sectorNo, keyType, 0}}; + memcpy(c.d.asBytes, key, 6); + clearCommandBuffer(); + SendCommand(&c); + + UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + + if (isOK) { + memcpy(data, resp.d.asBytes, mfNumBlocksPerSector(sectorNo) * 16); + for (int i = 0; i < (sectorNo<32?3:15); i++) { + PrintAndLogEx(NORMAL, "data : %s", sprint_hex(data + i * 16, 16)); + } + PrintAndLogEx(NORMAL, "trailer: %s", sprint_hex(data + (sectorNo<32?3:15) * 16, 16)); + + return 0; + } else { + return 1; + } + } else { + PrintAndLogEx(ERR, "Command execute timeout"); + return 2; + } + + return 0; +} + // EMULATOR int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount) { UsbCommand c = {CMD_MIFARE_EML_MEMGET, {blockNum, blocksCount, 0}}; diff --git a/client/mifarehost.h b/client/mifarehost.h index 8f0f3f3bf..69458fdfa 100644 --- a/client/mifarehost.h +++ b/client/mifarehost.h @@ -76,7 +76,7 @@ extern int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t las uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory); extern int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey); - +extern int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data); extern int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount); extern int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount); From f2b600e6e96f34fa5112ffadeb6816b89191b267 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 20 Feb 2019 21:12:28 +0200 Subject: [PATCH 0518/1938] add keys for mad and ndef --- client/mifaredefault.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/mifaredefault.h b/client/mifaredefault.h index 400463eaf..db9c0329d 100644 --- a/client/mifaredefault.h +++ b/client/mifaredefault.h @@ -31,7 +31,7 @@ static const uint64_t g_mifare_default_keys[] = 0xabcdef123456, 0x4d3a99c351dd, 0x1a982c7e459a, - 0xd3f7d3f7d3f7, + 0xd3f7d3f7d3f7, // NDEF public key 0x714c5c886e97, 0x587ee5f9350f, 0xa0478cc39091, @@ -42,4 +42,7 @@ static const uint64_t g_mifare_default_keys[] = 0x96a301bce267 }; +static const uint8_t g_mifare_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5}; +static const uint8_t g_mifare_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}; + #endif From 583b73226810d2f0aa8a72a5e01aeef352ebe8cd Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 20 Feb 2019 21:12:50 +0200 Subject: [PATCH 0519/1938] add `hf mf mad` command --- client/cmdhfmf.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 47646852e..811fa2430 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -3198,6 +3198,39 @@ int CmdHF14AMfAuth4(const char *cmd) { return MifareAuth4(NULL, keyn, key, true, false, true); } +// https://www.nxp.com/docs/en/application-note/AN10787.pdf +int CmdHF14AMfMAD(const char *cmd) { + + CLIParserInit("hf mf mad", + "Checks and prints Mifare Application Directory (MAD)", + "Usage:\n\thf mf mad -> shows MAD if exists\n"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("vV", "verbose", "show technical data"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + bool verbose = arg_get_lit(1); + + CLIParserFree(); + + uint8_t sector[16 * 4] = {0}; + if (mfReadSector(0, 0, (uint8_t *)g_mifare_mad_key, sector)) { + PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); + return 2; + } + + if (verbose) { + for(int i = 0; i < 3; i ++) + PrintAndLogEx(NORMAL, "[i] %s", sprint_hex(§or[i * 16], 16)); + } + +// MADDecodeAndPrint(sector, verbose); + + return 0; +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"darkside", CmdHF14ADarkside, 0, "Darkside attack. read parity error messages."}, @@ -3234,6 +3267,9 @@ static command_t CommandTable[] = { {"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"}, {"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"}, {"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"}, + {"-----------", CmdHelp, 1, ""}, + {"mad", CmdHF14AMfMAD, 0, "Checks and prints MAD"}, +// {"ndef", CmdHF14AMfHDEF, 0, "Checks and prints NDEF records from card"}, {"ice", CmdHF14AMfice, 0, "collect Mifare Classic nonces to file"}, {NULL, NULL, 0, NULL} From 1675b10c009646fddf4b8a384ca3a7bf5f18fb12 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 20 Feb 2019 21:15:44 +0200 Subject: [PATCH 0520/1938] small fix --- client/mifarehost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mifarehost.c b/client/mifarehost.c index 817f99c93..ba5081441 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -435,7 +435,7 @@ int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data) return 0; } else { - return 1; + return isOK; } } else { PrintAndLogEx(ERR, "Command execute timeout"); From 06ade9970a4345430e7349ef5b23f61241ba94e1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Wed, 20 Feb 2019 22:29:39 +0100 Subject: [PATCH 0521/1938] FIX: mem leaks FIX: 'hf mf nested' - params --- client/cmdhf15.c | 1 + client/cmdhfmf.c | 25 ++++++++++++++----------- client/cmdtrace.c | 6 +++--- client/emv/cmdemv.c | 1 + client/loclass/ikeys.c | 3 +++ client/scripting.c | 2 +- 6 files changed, 23 insertions(+), 15 deletions(-) diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 2800b0c9c..097a52704 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -834,6 +834,7 @@ int CmdHF15Restore(const char*Cmd) { if (!getUID(uid)) { PrintAndLogEx(WARNING, "No tag found"); + fclose(f); return 3; } diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 47646852e..9efb79700 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -425,6 +425,7 @@ char * GenerateFilename(const char *prefix, const char *suffix){ GetHFMF14AUID(uid, &uidlen); if (!uidlen) { PrintAndLogEx(WARNING, "No tag found."); + free(fptr); return NULL; } @@ -1082,19 +1083,21 @@ int CmdHF14AMfNested(const char *Cmd) { } else { SectorsCnt = NumOfSectors(cmdp); } - - ctmp = tolower(param_getchar(Cmd, 4)); - transferToEml |= (ctmp == 't'); - createDumpFile |= (ctmp == 'd'); - ctmp = tolower(param_getchar(Cmd, 6)); - transferToEml |= (ctmp == 't'); - createDumpFile |= (ctmp == 'd'); + uint8_t j = 4; + while ( ctmp != 0x00 ) { + + ctmp = tolower(param_getchar(Cmd, j)); + transferToEml |= (ctmp == 't'); + createDumpFile |= (ctmp == 'd'); + + j++; + } // check if we can authenticate to sector res = mfCheckKeys(blockNo, keyType, true, 1, key, &key64); if (res) { - PrintAndLogEx(WARNING, "key is wrong. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A'); + PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A'); return 3; } @@ -1112,9 +1115,9 @@ int CmdHF14AMfNested(const char *Cmd) { if (transferToEml) { uint8_t sectortrailer; if (trgBlockNo < 32*4) { // 4 block sector - sectortrailer = (trgBlockNo & ~0x03) + 3; + sectortrailer = trgBlockNo | 0x03; } else { // 16 block sector - sectortrailer = (trgBlockNo & ~0x0f) + 15; + sectortrailer = trgBlockNo | 0x0f; } mfEmlGetMem(keyBlock, sectortrailer, 1); @@ -1236,7 +1239,7 @@ int CmdHF14AMfNested(const char *Cmd) { num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]); mfEmlSetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); } - PrintAndLogEx(SUCCESS, "key transferred to emulator memory."); + PrintAndLogEx(SUCCESS, "keys transferred to emulator memory."); } // Create dump file diff --git a/client/cmdtrace.c b/client/cmdtrace.c index 90c08459f..56f97ca1d 100644 --- a/client/cmdtrace.c +++ b/client/cmdtrace.c @@ -14,7 +14,6 @@ static int CmdHelp(const char *Cmd); // trace pointer static uint8_t *trace; long traceLen = 0; -bool preRDV40 = true; int usage_trace_list(){ PrintAndLogEx(NORMAL, "List protocol data in trace buffer."); @@ -297,8 +296,9 @@ void printFelica(uint16_t traceLen, uint8_t *trace) { if (tracepos + 3 >= traceLen) break; - uint16_t gap = (uint16_t)trace[tracepos+1] + ((uint16_t)trace[tracepos] >> 8); - uint16_t crc_ok = trace[tracepos+2]; + + uint16_t gap = *((uint16_t *)(trace + tracepos)); + uint8_t crc_ok = trace[tracepos+2]; tracepos += 3; if (tracepos + 3 >= traceLen) break; diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 9728a32b7..4228a03e3 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1204,6 +1204,7 @@ int CmdEMVExec(const char *cmd) { if (res) { PrintAndLogEx(NORMAL, "AC1 error(%d): %4x. Exit...", res, sw); + free(cdol1_data_tlv); dreturn(7); } diff --git a/client/loclass/ikeys.c b/client/loclass/ikeys.c index aefbbaf99..2d14959ca 100644 --- a/client/loclass/ikeys.c +++ b/client/loclass/ikeys.c @@ -685,6 +685,9 @@ static bool readKeyFile(uint8_t key[8]) { sprintf(filename, "%s.bin", "client/loclass/iclass_key"); } + if ( filename == NULL ) + return retval; + FILE *f = fopen(filename, "rb"); if (!f) return retval; diff --git a/client/scripting.c b/client/scripting.c index b6bb80f33..6f6a30f53 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -608,7 +608,7 @@ static int l_hardnested(lua_State *L){ char filename[FILE_PATH_SIZE]="nonces.bin"; const char *p_filename = luaL_checklstring(L, 11, &size); if(size != 0) - strcpy(filename, p_filename); + memcpy(filename, p_filename, FILE_PATH_SIZE-1); uint32_t blockNo = 0, keyType = 0; uint32_t trgBlockNo = 0, trgKeyType = 0; From 91d6836a47778741b3795080e9a6172425b7540f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 21 Feb 2019 15:34:31 +0100 Subject: [PATCH 0522/1938] fix: mem leaks. --- client/cmdhffelica.c | 4 ++-- client/cmdhficlass.c | 4 ++-- client/cmdhflegic.c | 1 + client/cmdhfmfhard.c | 10 ++++++++-- client/emv/cmdemv.c | 2 ++ client/emv/emv_pk.c | 6 ------ client/hardnested/hardnested_bruteforce.c | 9 +++++++-- 7 files changed, 22 insertions(+), 14 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 700f7ae8b..07422f419 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -299,10 +299,10 @@ uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace,uint16_t tracelen) { char idm[20]; char pmm[20]; for (int j = 0; j < 8; j++) - snprintf(idm+( j * 2),20, "%02x", trace[j+3]); + snprintf(idm + (j * 2), 20, "%02x", trace[j+3]); for (int j = 0; j < 8; j++) - snprintf(pmm+( j * 2),20, "%02x", trace[j+11]); + snprintf(pmm + (j * 2), 20, "%02x", trace[j+11]); PrintAndLogEx(NORMAL, "DeviceId: IDm: 0x%s PMm: 0x%s ", idm, pmm); } diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 9427acf50..746146758 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -2162,10 +2162,10 @@ static int cmp_uint32( const void *a, const void *b) { int CmdHFiClassLookUp(const char *Cmd) { uint8_t CSN[8]; - uint8_t EPURSE[8]; + uint8_t EPURSE[8] = { 0,0,0,0,0,0,0,0 }; uint8_t MACS[8]; uint8_t CCNR[12]; - uint8_t MAC_TAG[4] = {0x00,0x00,0x00,0x00}; + uint8_t MAC_TAG[4] = { 0,0,0,0 }; // elite key, raw key, standard key bool use_elite = false; diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 8c4ef411c..41df287a9 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -1022,6 +1022,7 @@ int CmdLegicRestore(const char *Cmd){ f = fopen(filename,"rb"); if (!f) { PrintAndLogEx(WARNING, "File %s not found or locked", filename); + free(data); return 3; } diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 4818f480f..0c661d410 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -266,14 +266,20 @@ static void init_bitflip_bitarrays(void) continue; } else { fseek(statesfile, 0, SEEK_END); - uint32_t filesize = (uint32_t)ftell(statesfile); + int fsize = ftell(statesfile); + if ( fsize == -1 ){ + PrintAndLogEx(WARNING, "File read error with %s. Aborting...\n", state_file_name); + fclose(statesfile); + exit(5); + } + uint32_t filesize = (uint32_t)fsize; rewind(statesfile); uint8_t input_buffer[filesize]; size_t bytesread = fread(input_buffer, 1, filesize, statesfile); if (bytesread != filesize) { PrintAndLogEx(WARNING, "File read error with %s. Aborting...\n", state_file_name); fclose(statesfile); - inflateEnd(&compressed_stream); + //inflateEnd(&compressed_stream); exit(5); } fclose(statesfile); diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 4228a03e3..98bc389f4 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -284,6 +284,7 @@ int CmdEMVGPO(const char *cmd) { if (!pdol_data_tlv_data) { PrintAndLogEx(ERR, "Can't create PDOL data."); tlvdb_free(tlvRoot); + free(pdol_data_tlv); return 4; } PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); @@ -296,6 +297,7 @@ int CmdEMVGPO(const char *cmd) { if (pdol_data_tlv != &data_tlv) free(pdol_data_tlv); + tlvdb_free(tlvRoot); if (sw) diff --git a/client/emv/emv_pk.c b/client/emv/emv_pk.c index b577855e0..091ab8062 100644 --- a/client/emv/emv_pk.c +++ b/client/emv/emv_pk.c @@ -429,9 +429,6 @@ char *emv_pk_get_ca_pk_file(const char *dirname, const unsigned char *rid, unsig if (!dirname) dirname = ".";//openemv_config_get_str("capk.dir", NULL); - if (!dirname) - return NULL; - char *filename; int ret = asprintf(&filename, "%s/%02hhx%02hhx%02hhx%02hhx%02hhx_%02hhx.0", dirname, @@ -453,9 +450,6 @@ char *emv_pk_get_ca_pk_rid_file(const char *dirname, const unsigned char *rid) if (!dirname) dirname = "."; //openemv_config_get_str("capk.dir", NULL); - if (!dirname) - return NULL; - char *filename; int ret = asprintf(&filename, "%s/%02hhx%02hhx%02hhx%02hhx%02hhx.pks", dirname, diff --git a/client/hardnested/hardnested_bruteforce.c b/client/hardnested/hardnested_bruteforce.c index 55d6bbfbf..2a7618a1d 100644 --- a/client/hardnested/hardnested_bruteforce.c +++ b/client/hardnested/hardnested_bruteforce.c @@ -311,6 +311,11 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint uint64_t start_time = msclock(); +#if defined(__linux__) || defined(__APPLE__) + if ( NUM_BRUTE_FORCE_THREADS < 0 ) + return false; +#endif + pthread_t threads[NUM_BRUTE_FORCE_THREADS]; struct args { bool silent; @@ -322,7 +327,7 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint uint8_t *best_first_bytes; } thread_args[NUM_BRUTE_FORCE_THREADS]; - for(uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS; i++){ + for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS; i++){ thread_args[i].thread_ID = i; thread_args[i].silent = silent; thread_args[i].cuid = cuid; @@ -332,7 +337,7 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint thread_args[i].best_first_bytes = best_first_bytes; pthread_create(&threads[i], NULL, crack_states_thread, (void*)&thread_args[i]); } - for(uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS; i++){ + for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS; i++){ pthread_join(threads[i], 0); } From de317d9f4865c4cbafd6691386a52ff4401f1b87 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 21 Feb 2019 15:39:36 +0100 Subject: [PATCH 0523/1938] fix: mem leaks. --- client/cmdhfmf.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 9efb79700..78a9ed138 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1723,7 +1723,7 @@ int CmdHF14AMfChk(const char *Cmd) { if (strlen(Cmd) < 3 || ctmp == 'h') return usage_hf14_chk(); FILE * f; - char filename[FILE_PATH_SIZE]={0}; + char filename[FILE_PATH_SIZE] = {0}; char buf[13]; uint8_t *keyBlock = NULL, *p; sector_t *e_sector = NULL; @@ -1970,8 +1970,10 @@ out: if (createDumpFile) { fptr = GenerateFilename("hf-mf-", "-key.bin"); - if (fptr == NULL) + if (fptr == NULL) { + free(keyBlock); return 1; + } FILE *fkeys = fopen(fptr, "wb"); if (fkeys == NULL) { @@ -2489,15 +2491,18 @@ int CmdHF14AMfELoad(const char *Cmd) { if ( blockWidth == 4 ) { if ((blockNum != numBlocks)) { PrintAndLogEx(FAILED, "Warning, Ultralight/Ntag file content, Loaded %d blocks into emulator memory", blockNum); + free(data); return 0; } } else { if ((blockNum != numBlocks)) { PrintAndLogEx(FAILED, "Error, file content, Only loaded %d blocks, must be %d blocks into emulator memory", blockNum, numBlocks); + free(data); return 4; } } PrintAndLogEx(SUCCESS, "Loaded %d blocks from file: " _YELLOW_(%s), blockNum, filename); + free(data); return 0; } From 00d1fd9d456fc022c7084bb7cf35c59872979dc1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 21 Feb 2019 16:07:14 +0100 Subject: [PATCH 0524/1938] fix: mem leaks --- uart/uart_posix.c | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/uart/uart_posix.c b/uart/uart_posix.c index 093aaf363..49bcb9b8e 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -103,6 +103,8 @@ serial_port uart_open(const char* pcPortName) int s = getaddrinfo(addrstr, portstr, NULL, &addr); if (s != 0) { printf("Error: getaddrinfo: %s\n", gai_strerror(s)); + freeaddrinfo(addr); + free(addrstr); return INVALID_SERIAL_PORT; } @@ -121,6 +123,8 @@ serial_port uart_open(const char* pcPortName) if (rp == NULL) { /* No address succeeded */ printf("Error: Could not connect\n"); + freeaddrinfo(addr); + free(addrstr); return INVALID_SERIAL_PORT; } From 44392c6afcb75aa94e75b4d3a19930c4ed2d52cb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 21 Feb 2019 16:09:27 +0100 Subject: [PATCH 0525/1938] fix: whitespaces --- uart/uart_posix.c | 559 +++++++++++++++++++++++----------------------- 1 file changed, 279 insertions(+), 280 deletions(-) diff --git a/uart/uart_posix.c b/uart/uart_posix.c index 49bcb9b8e..aec19c38a 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -62,354 +62,353 @@ typedef struct termios term_info; typedef struct { - int fd; // Serial port file descriptor - term_info tiOld; // Terminal info before using the port - term_info tiNew; // Terminal info during the transaction + int fd; // Serial port file descriptor + term_info tiOld; // Terminal info before using the port + term_info tiNew; // Terminal info during the transaction } serial_port_unix; // Set time-out on 30 miliseconds struct timeval timeout = { - .tv_sec = 0, // 0 second - .tv_usec = 30000 // 30000 micro seconds + .tv_sec = 0, // 0 second + .tv_usec = 30000 // 30 000 micro seconds }; -serial_port uart_open(const char* pcPortName) -{ - serial_port_unix* sp = calloc(sizeof(serial_port_unix), sizeof(uint8_t)); - if (sp == 0) return INVALID_SERIAL_PORT; +serial_port uart_open(const char* pcPortName) { + serial_port_unix* sp = calloc(sizeof(serial_port_unix), sizeof(uint8_t)); + if (sp == 0) return INVALID_SERIAL_PORT; - if (memcmp(pcPortName, "tcp:", 4) == 0) { - struct addrinfo *addr, *rp; - char *addrstr = strdup(pcPortName + 4); + if (memcmp(pcPortName, "tcp:", 4) == 0) { + struct addrinfo *addr, *rp; + char *addrstr = strdup(pcPortName + 4); - if (addrstr == NULL) { - printf("Error: strdup\n"); - return INVALID_SERIAL_PORT; - } + if (addrstr == NULL) { + printf("Error: strdup\n"); + return INVALID_SERIAL_PORT; + } - char *colon = strrchr(addrstr, ':'); - char *portstr; + timeout.tv_usec = 300000 // 300 000 micro seconds + + char *colon = strrchr(addrstr, ':'); + char *portstr; + if (colon) { + portstr = colon + 1; + *colon = '\0'; + } else { + portstr = "7901"; + } - // Set time-out to 300 miliseconds only for TCP port - timeout.tv_usec = 300000; + int s = getaddrinfo(addrstr, portstr, NULL, &addr); + if (s != 0) { + printf("Error: getaddrinfo: %s\n", gai_strerror(s)); + freeaddrinfo(addr); + free(addrstr); + return INVALID_SERIAL_PORT; + } - if (colon) { - portstr = colon + 1; - *colon = '\0'; - } else { - portstr = "7901"; + int sfd; + for (rp = addr; rp != NULL; rp = rp->ai_next) { + sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + + if (sfd == -1) + continue; + + if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) + break; + + close(sfd); + } + + if (rp == NULL) { /* No address succeeded */ + printf("Error: Could not connect\n"); + freeaddrinfo(addr); + free(addrstr); + return INVALID_SERIAL_PORT; + } + + freeaddrinfo(addr); + free(addrstr); + + sp->fd = sfd; + + int one = 1; + setsockopt(sp->fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)); + return sp; } - - int s = getaddrinfo(addrstr, portstr, NULL, &addr); - if (s != 0) { - printf("Error: getaddrinfo: %s\n", gai_strerror(s)); - freeaddrinfo(addr); - free(addrstr); - return INVALID_SERIAL_PORT; - } - - int sfd; - for (rp = addr; rp != NULL; rp = rp->ai_next) { - sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - - if (sfd == -1) - continue; - - if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) - break; - - close(sfd); - } - - if (rp == NULL) { /* No address succeeded */ - printf("Error: Could not connect\n"); - freeaddrinfo(addr); - free(addrstr); - return INVALID_SERIAL_PORT; - } - - freeaddrinfo(addr); - free(addrstr); - - sp->fd = sfd; - - int one = 1; - setsockopt(sp->fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)); - return sp; - } - sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); - if(sp->fd == -1) { - uart_close(sp); - return INVALID_SERIAL_PORT; - } + sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); + if(sp->fd == -1) { + uart_close(sp); + return INVALID_SERIAL_PORT; + } - // Finally figured out a way to claim a serial port interface under unix - // We just try to set a (advisory) lock on the file descriptor - struct flock fl; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_pid = getpid(); - - // Does the system allows us to place a lock on this file descriptor - if (fcntl(sp->fd, F_SETLK, &fl) == -1) { - // A conflicting lock is held by another process - free(sp); - return CLAIMED_SERIAL_PORT; - } + // Finally figured out a way to claim a serial port interface under unix + // We just try to set a (advisory) lock on the file descriptor + struct flock fl; + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_pid = getpid(); + + // Does the system allows us to place a lock on this file descriptor + if (fcntl(sp->fd, F_SETLK, &fl) == -1) { + // A conflicting lock is held by another process + free(sp); + return CLAIMED_SERIAL_PORT; + } + + // Try to retrieve the old (current) terminal info struct + if(tcgetattr(sp->fd,&sp->tiOld) == -1) { + uart_close(sp); + return INVALID_SERIAL_PORT; + } + + // Duplicate the (old) terminal info struct + sp->tiNew = sp->tiOld; + + // Configure the serial port + sp->tiNew.c_cflag = CS8 | CLOCAL | CREAD; + sp->tiNew.c_iflag = IGNPAR; + sp->tiNew.c_oflag = 0; + sp->tiNew.c_lflag = 0; + + // Block until n bytes are received + sp->tiNew.c_cc[VMIN] = 0; + // Block until a timer expires (n * 100 mSec.) + sp->tiNew.c_cc[VTIME] = 0; + + // Try to set the new terminal info struct + if(tcsetattr(sp->fd, TCSANOW, &sp->tiNew) == -1) { + uart_close(sp); + return INVALID_SERIAL_PORT; + } - // Try to retrieve the old (current) terminal info struct - if(tcgetattr(sp->fd,&sp->tiOld) == -1) { - uart_close(sp); - return INVALID_SERIAL_PORT; - } - - // Duplicate the (old) terminal info struct - sp->tiNew = sp->tiOld; - - // Configure the serial port - sp->tiNew.c_cflag = CS8 | CLOCAL | CREAD; - sp->tiNew.c_iflag = IGNPAR; - sp->tiNew.c_oflag = 0; - sp->tiNew.c_lflag = 0; - - // Block until n bytes are received - sp->tiNew.c_cc[VMIN] = 0; - // Block until a timer expires (n * 100 mSec.) - sp->tiNew.c_cc[VTIME] = 0; - - // Try to set the new terminal info struct - if(tcsetattr(sp->fd, TCSANOW, &sp->tiNew) == -1) { - uart_close(sp); - return INVALID_SERIAL_PORT; - } - // Flush all lingering data that may exist tcflush(sp->fd, TCIOFLUSH); #ifdef WITH_FPC if ( uart_set_speed(sp, 115200) ) { - printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n"); + printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n"); } else { uart_set_speed(sp, 9600); printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n"); } #else - // set speed, works for UBUNTU 14.04 - bool success = uart_set_speed(sp, 460800); - if (success) { - printf("[=] UART Setting serial baudrate 460800\n"); - } else { - uart_set_speed(sp, 115200); - printf("[=] UART Setting serial baudrate 115200\n"); - } + // set speed, works for UBUNTU 14.04 + bool success = uart_set_speed(sp, 460800); + if (success) { + printf("[=] UART Setting serial baudrate 460800\n"); + } else { + uart_set_speed(sp, 115200); + printf("[=] UART Setting serial baudrate 115200\n"); + } #endif - return sp; + return sp; } void uart_close(const serial_port sp) { - serial_port_unix* spu = (serial_port_unix*)sp; - tcflush(spu->fd, TCIOFLUSH); - tcsetattr(spu->fd, TCSANOW, &(spu->tiOld)); - struct flock fl; - fl.l_type = F_UNLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_pid = getpid(); + serial_port_unix* spu = (serial_port_unix*)sp; + tcflush(spu->fd, TCIOFLUSH); + tcsetattr(spu->fd, TCSANOW, &(spu->tiOld)); + struct flock fl; + fl.l_type = F_UNLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_pid = getpid(); - // Does the system allows us to place a lock on this file descriptor - int err = fcntl(spu->fd, F_SETLK, &fl); - if ( err == -1) { - //perror("fcntl"); - } - close(spu->fd); - free(sp); + // Does the system allows us to place a lock on this file descriptor + int err = fcntl(spu->fd, F_SETLK, &fl); + if ( err == -1) { + //perror("fcntl"); + } + close(spu->fd); + free(sp); } bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen) { - int res; - int byteCount; - fd_set rfds; - struct timeval tv; + int res; + int byteCount; + fd_set rfds; + struct timeval tv; + + // Reset the output count + *pszRxLen = 0; - // Reset the output count - *pszRxLen = 0; - - do { - // Reset file descriptor - FD_ZERO(&rfds); - FD_SET(((serial_port_unix*)sp)->fd, &rfds); - tv = timeout; - res = select(((serial_port_unix*)sp)->fd + 1, &rfds, NULL, NULL, &tv); - - // Read error - if (res < 0) { - return false; - } - - // Read time-out - if (res == 0) { - if (*pszRxLen == 0) { - // Error, we received no data - return false; - } else { - // We received some data, but nothing more is available - return true; - } - } - - // Retrieve the count of the incoming bytes - res = ioctl(((serial_port_unix*)sp)->fd, FIONREAD, &byteCount); - if (res < 0) return false; - - // Cap the number of bytes, so we don't overrun the buffer - if (pszMaxRxLen - (*pszRxLen) < byteCount) { - byteCount = pszMaxRxLen - (*pszRxLen); - } + do { + // Reset file descriptor + FD_ZERO(&rfds); + FD_SET(((serial_port_unix*)sp)->fd, &rfds); + tv = timeout; + res = select(((serial_port_unix*)sp)->fd + 1, &rfds, NULL, NULL, &tv); - // There is something available, read the data - res = read(((serial_port_unix*)sp)->fd, pbtRx + (*pszRxLen), byteCount); + // Read error + if (res < 0) { + return false; + } - // Stop if the OS has some troubles reading the data - if (res <= 0) return false; - - *pszRxLen += res; + // Read time-out + if (res == 0) { + if (*pszRxLen == 0) { + // Error, we received no data + return false; + } else { + // We received some data, but nothing more is available + return true; + } + } - if (*pszRxLen == pszMaxRxLen) { - // We have all the data we wanted. - return true; - } - - } while (byteCount); + // Retrieve the count of the incoming bytes + res = ioctl(((serial_port_unix*)sp)->fd, FIONREAD, &byteCount); + if (res < 0) return false; - return true; + // Cap the number of bytes, so we don't overrun the buffer + if (pszMaxRxLen - (*pszRxLen) < byteCount) { + byteCount = pszMaxRxLen - (*pszRxLen); + } + + // There is something available, read the data + res = read(((serial_port_unix*)sp)->fd, pbtRx + (*pszRxLen), byteCount); + + // Stop if the OS has some troubles reading the data + if (res <= 0) return false; + + *pszRxLen += res; + + if (*pszRxLen == pszMaxRxLen) { + // We have all the data we wanted. + return true; + } + + } while (byteCount); + + return true; } bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t len) { - int32_t res; - size_t pos = 0; - fd_set rfds; - struct timeval tv; + int32_t res; + size_t pos = 0; + fd_set rfds; + struct timeval tv; - while (pos < len) { - // Reset file descriptor - FD_ZERO(&rfds); - FD_SET(((serial_port_unix*)sp)->fd, &rfds); - tv = timeout; - res = select(((serial_port_unix*)sp)->fd+1, NULL, &rfds, NULL, &tv); - - // Write error - if (res < 0) { - printf("UART:: write error (%d)\n", res); - return false; - } - - // Write time-out - if (res == 0) { - printf("UART:: write time-out\n"); - return false; - } - - // Send away the bytes - res = write(((serial_port_unix*)sp)->fd, pbtTx + pos, len - pos); - - // Stop if the OS has some troubles sending the data - if (res <= 0) return false; - - pos += res; - } - return true; + while (pos < len) { + // Reset file descriptor + FD_ZERO(&rfds); + FD_SET(((serial_port_unix*)sp)->fd, &rfds); + tv = timeout; + res = select(((serial_port_unix*)sp)->fd+1, NULL, &rfds, NULL, &tv); + + // Write error + if (res < 0) { + printf("UART:: write error (%d)\n", res); + return false; + } + + // Write time-out + if (res == 0) { + printf("UART:: write time-out\n"); + return false; + } + + // Send away the bytes + res = write(((serial_port_unix*)sp)->fd, pbtTx + pos, len - pos); + + // Stop if the OS has some troubles sending the data + if (res <= 0) return false; + + pos += res; + } + return true; } bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) { - const serial_port_unix* spu = (serial_port_unix*)sp; - speed_t stPortSpeed; - switch (uiPortSpeed) { - case 0: stPortSpeed = B0; break; - case 50: stPortSpeed = B50; break; - case 75: stPortSpeed = B75; break; - case 110: stPortSpeed = B110; break; - case 134: stPortSpeed = B134; break; - case 150: stPortSpeed = B150; break; - case 300: stPortSpeed = B300; break; - case 600: stPortSpeed = B600; break; - case 1200: stPortSpeed = B1200; break; - case 1800: stPortSpeed = B1800; break; - case 2400: stPortSpeed = B2400; break; - case 4800: stPortSpeed = B4800; break; - case 9600: stPortSpeed = B9600; break; - case 19200: stPortSpeed = B19200; break; - case 38400: stPortSpeed = B38400; break; + const serial_port_unix* spu = (serial_port_unix*)sp; + speed_t stPortSpeed; + switch (uiPortSpeed) { + case 0: stPortSpeed = B0; break; + case 50: stPortSpeed = B50; break; + case 75: stPortSpeed = B75; break; + case 110: stPortSpeed = B110; break; + case 134: stPortSpeed = B134; break; + case 150: stPortSpeed = B150; break; + case 300: stPortSpeed = B300; break; + case 600: stPortSpeed = B600; break; + case 1200: stPortSpeed = B1200; break; + case 1800: stPortSpeed = B1800; break; + case 2400: stPortSpeed = B2400; break; + case 4800: stPortSpeed = B4800; break; + case 9600: stPortSpeed = B9600; break; + case 19200: stPortSpeed = B19200; break; + case 38400: stPortSpeed = B38400; break; # ifdef B57600 - case 57600: stPortSpeed = B57600; break; + case 57600: stPortSpeed = B57600; break; # endif # ifdef B115200 - case 115200: stPortSpeed = B115200; break; + case 115200: stPortSpeed = B115200; break; # endif # ifdef B230400 - case 230400: stPortSpeed = B230400; break; + case 230400: stPortSpeed = B230400; break; # endif # ifdef B460800 - case 460800: stPortSpeed = B460800; break; + case 460800: stPortSpeed = B460800; break; # endif # ifdef B921600 - case 921600: stPortSpeed = B921600; break; + case 921600: stPortSpeed = B921600; break; # endif - default: return false; - }; - struct termios ti; - if (tcgetattr(spu->fd,&ti) == -1) return false; - // Set port speed (Input and Output) - cfsetispeed(&ti, stPortSpeed); - cfsetospeed(&ti, stPortSpeed); - return (tcsetattr(spu->fd, TCSANOW, &ti) != -1); + default: return false; + }; + struct termios ti; + if (tcgetattr(spu->fd,&ti) == -1) return false; + // Set port speed (Input and Output) + cfsetispeed(&ti, stPortSpeed); + cfsetospeed(&ti, stPortSpeed); + return (tcsetattr(spu->fd, TCSANOW, &ti) != -1); } uint32_t uart_get_speed(const serial_port sp) { - struct termios ti; - uint32_t uiPortSpeed; - const serial_port_unix* spu = (serial_port_unix*)sp; - if (tcgetattr(spu->fd, &ti) == -1) return 0; - // Set port speed (Input) - speed_t stPortSpeed = cfgetispeed(&ti); - switch (stPortSpeed) { - case B0: uiPortSpeed = 0; break; - case B50: uiPortSpeed = 50; break; - case B75: uiPortSpeed = 75; break; - case B110: uiPortSpeed = 110; break; - case B134: uiPortSpeed = 134; break; - case B150: uiPortSpeed = 150; break; - case B300: uiPortSpeed = 300; break; - case B600: uiPortSpeed = 600; break; - case B1200: uiPortSpeed = 1200; break; - case B1800: uiPortSpeed = 1800; break; - case B2400: uiPortSpeed = 2400; break; - case B4800: uiPortSpeed = 4800; break; - case B9600: uiPortSpeed = 9600; break; - case B19200: uiPortSpeed = 19200; break; - case B38400: uiPortSpeed = 38400; break; + struct termios ti; + uint32_t uiPortSpeed; + const serial_port_unix* spu = (serial_port_unix*)sp; + + if (tcgetattr(spu->fd, &ti) == -1) + return 0; + + // Set port speed (Input) + speed_t stPortSpeed = cfgetispeed(&ti); + switch (stPortSpeed) { + case B0: uiPortSpeed = 0; break; + case B50: uiPortSpeed = 50; break; + case B75: uiPortSpeed = 75; break; + case B110: uiPortSpeed = 110; break; + case B134: uiPortSpeed = 134; break; + case B150: uiPortSpeed = 150; break; + case B300: uiPortSpeed = 300; break; + case B600: uiPortSpeed = 600; break; + case B1200: uiPortSpeed = 1200; break; + case B1800: uiPortSpeed = 1800; break; + case B2400: uiPortSpeed = 2400; break; + case B4800: uiPortSpeed = 4800; break; + case B9600: uiPortSpeed = 9600; break; + case B19200: uiPortSpeed = 19200; break; + case B38400: uiPortSpeed = 38400; break; # ifdef B57600 - case B57600: uiPortSpeed = 57600; break; + case B57600: uiPortSpeed = 57600; break; # endif # ifdef B115200 - case B115200: uiPortSpeed = 115200; break; + case B115200: uiPortSpeed = 115200; break; # endif # ifdef B230400 - case B230400: uiPortSpeed = 230400; break; + case B230400: uiPortSpeed = 230400; break; # endif # ifdef B460800 - case B460800: uiPortSpeed = 460800; break; + case B460800: uiPortSpeed = 460800; break; # endif # ifdef B921600 - case B921600: uiPortSpeed = 921600; break; + case B921600: uiPortSpeed = 921600; break; # endif - default: return 0; - }; - return uiPortSpeed; + default: return 0; + }; + return uiPortSpeed; } - #endif From 6d63b3fbed045d851d7741124872da6c82bea029 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 21 Feb 2019 16:17:49 +0100 Subject: [PATCH 0526/1938] fix: mem leaks. --- client/cmdhffelica.c | 6 +++--- client/cmdhficlass.c | 2 +- client/cmdhfmf.c | 9 +++++++-- client/cmdhfmfu.c | 2 ++ client/cmdsmartcard.c | 4 +++- client/emv/cmdemv.c | 1 + client/loclass/elite_crack.c | 5 +++-- client/loclass/fileutils.c | 9 +++++++-- client/loclass/ikeys.c | 2 +- 9 files changed, 28 insertions(+), 12 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 07422f419..acfc68cf2 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -242,7 +242,7 @@ static void printSep() { PrintAndLogEx(NORMAL, "------------------------------------------------------------------------------------"); } -uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace,uint16_t tracelen) { +uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) { if (tracepos+19 >= tracelen) return tracelen; @@ -273,8 +273,8 @@ uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace,uint16_t tracelen) { case 0x0c: PrintAndLogEx(NORMAL, "S_PAD12: %s",line);break; case 0x0d: PrintAndLogEx(NORMAL, "S_PAD13: %s",line);break; case 0x0E: { - uint32_t regA = trace[3] + (trace[4]>>8) + (trace[5]>>16) + (trace[6]>>24); - uint32_t regB = trace[7] + (trace[8]>>8) + (trace[9]>>16) + (trace[10]>>24); + uint32_t regA = trace[3] | trace[4] << 8 | trace[5] << 16 | trace[ 6] << 24; + uint32_t regB = trace[7] | trace[8] << 8 | trace[9] << 16 | trace[10] << 24; line[0] = 0; for (int j = 0; j < 8; j++) snprintf(line+( j * 2),110, "%02x", trace[j+11]); diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 746146758..ddc6fb2c0 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -2163,7 +2163,7 @@ int CmdHFiClassLookUp(const char *Cmd) { uint8_t CSN[8]; uint8_t EPURSE[8] = { 0,0,0,0,0,0,0,0 }; - uint8_t MACS[8]; + uint8_t MACS[8]= { 0,0,0,0,0,0,0,0 }; uint8_t CCNR[12]; uint8_t MAC_TAG[4] = { 0,0,0,0 }; diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 78a9ed138..57cf246da 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1245,8 +1245,10 @@ int CmdHF14AMfNested(const char *Cmd) { // Create dump file if (createDumpFile) { fptr = GenerateFilename("hf-mf-", "-key.bin"); - if (fptr == NULL) + if (fptr == NULL) { + free(e_sector); return 1; + } if ((fkeys = fopen(fptr, "wb")) == NULL) { PrintAndLogEx(WARNING, "could not create file " _YELLOW_(%s), fptr); @@ -1276,6 +1278,8 @@ int CmdHF14AMfNested(const char *Cmd) { } free(e_sector); } + + free(e_sector); return 0; } @@ -1971,7 +1975,8 @@ out: if (createDumpFile) { fptr = GenerateFilename("hf-mf-", "-key.bin"); if (fptr == NULL) { - free(keyBlock); + free(keyBlock); + free(e_sector); return 1; } diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index e583f7f02..d703f980d 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -1982,6 +1982,7 @@ int CmdHF14AMfURestore(const char *Cmd){ uint8_t *dump = calloc(fsize, sizeof(uint8_t)); if ( !dump ) { PrintAndLogEx(WARNING, "Failed to allocate memory"); + fclose(f); return 1; } @@ -1990,6 +1991,7 @@ int CmdHF14AMfURestore(const char *Cmd){ fclose(f); if ( bytes_read < 48 ) { PrintAndLogEx(WARNING, "Error, dump file is too small"); + free(dump); return 1; } diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 9496b5445..3860496de 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -1022,8 +1022,10 @@ int CmdSmartBruteforceSFI(const char *Cmd) { return 1; PrintAndLogEx(INFO, "Selecting card"); - if ( !smart_select(false, NULL) ) + if ( !smart_select(false, NULL) ) { + free(buf); return 1; + } char* caid = NULL; diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 98bc389f4..94df507de 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -1807,6 +1807,7 @@ int CmdEMVRoca(const char *cmd) { PrintAndLogEx(ERR, "Can't create PDOL data."); tlvdb_free(tlvRoot); DropFieldEx( channel ); + free(pdol_data_tlv); return 6; } PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); diff --git a/client/loclass/elite_crack.c b/client/loclass/elite_crack.c index 6619e7aaa..630fa72a6 100644 --- a/client/loclass/elite_crack.c +++ b/client/loclass/elite_crack.c @@ -538,18 +538,19 @@ int bruteforceFile(const char *filename, uint16_t keytable[]) { if (fsize < 0) { PrintAndLogDevice(WARNING, "Error, when getting filesize"); - if (f) fclose(f); + fclose(f); return 1; } uint8_t *dump = calloc(fsize, sizeof(uint8_t)); if ( !dump ) { PrintAndLogDevice(WARNING, "Failed to allocate memory"); + fclose(f); return 2; } size_t bytes_read = fread(dump, 1, fsize, f); - if (f) fclose(f); + fclose(f); if (bytes_read < fsize) { PrintAndLogDevice(WARNING, "Error, could only read %d bytes (should be %d)", bytes_read, fsize ); diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index da91b21ec..6ce7c42ea 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -266,8 +266,8 @@ int loadFile(const char *preferredName, const char *suffix, void* data, size_t* FILE *f = fopen(fileName, "rb"); if ( !f ) { PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName); - retval = 1; - goto out; + free(fileName); + return 1; } // get filesize in order to malloc memory @@ -310,7 +310,12 @@ int loadFile(const char *preferredName, const char *suffix, void* data, size_t* out: fclose(f); + + if (data) + free(data); + free(fileName); + return retval; } diff --git a/client/loclass/ikeys.c b/client/loclass/ikeys.c index 2d14959ca..16b5513b7 100644 --- a/client/loclass/ikeys.c +++ b/client/loclass/ikeys.c @@ -685,7 +685,7 @@ static bool readKeyFile(uint8_t key[8]) { sprintf(filename, "%s.bin", "client/loclass/iclass_key"); } - if ( filename == NULL ) + if ( strlen(filename) == 0 ) return retval; FILE *f = fopen(filename, "rb"); From 265c069edc7b8160fbdc9ac113d97a26030a6480 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 21 Feb 2019 16:19:07 +0100 Subject: [PATCH 0527/1938] chg... missing --- uart/uart_posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/uart/uart_posix.c b/uart/uart_posix.c index aec19c38a..b9df932d6 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -86,7 +86,7 @@ serial_port uart_open(const char* pcPortName) { return INVALID_SERIAL_PORT; } - timeout.tv_usec = 300000 // 300 000 micro seconds + timeout.tv_usec = 300000; // 300 000 micro seconds char *colon = strrchr(addrstr, ':'); char *portstr; From 3b21b175099649f91572953cee1e65100385269e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 21 Feb 2019 19:15:46 +0200 Subject: [PATCH 0528/1938] move mifare stuff to its folder --- client/Makefile | 6 +- client/cmdanalyse.h | 6 +- client/cmdhf14a.h | 2 +- client/cmdhflist.h | 4 +- client/cmdhfmf.c | 22 +- client/cmdhfmf.h | 14 +- client/cmdhfmfp.c | 2 +- client/cmdhfmfp.h | 2 +- client/loclass/fileutils.h | 2 +- client/{ => mifare}/mfkey.c | 0 client/{ => mifare}/mfkey.h | 0 client/{ => mifare}/mifare4.c | 0 client/{ => mifare}/mifare4.h | 0 client/{ => mifare}/mifaredefault.h | 0 client/{ => mifare}/mifarehost.c | 2033 +++++++++++++-------------- client/{ => mifare}/mifarehost.h | 204 +-- client/obj/mifare/.dummy | 0 client/scripting.h | 2 +- include/mifare.h | 6 + 19 files changed, 1158 insertions(+), 1147 deletions(-) rename client/{ => mifare}/mfkey.c (100%) rename client/{ => mifare}/mfkey.h (100%) rename client/{ => mifare}/mifare4.c (100%) rename client/{ => mifare}/mifare4.h (100%) rename client/{ => mifare}/mifaredefault.h (100%) rename client/{ => mifare}/mifarehost.c (95%) rename client/{ => mifare}/mifarehost.h (97%) create mode 100644 client/obj/mifare/.dummy diff --git a/client/Makefile b/client/Makefile index 0b19d4599..9f8055f8e 100644 --- a/client/Makefile +++ b/client/Makefile @@ -108,7 +108,7 @@ CORESRCS = uart_posix.c \ CMDSRCS = crapto1/crapto1.c \ crapto1/crypto1.c \ - mfkey.c \ + mifare/mfkey.c \ tea.c \ fido/additional_ca.c \ fido/cose.c \ @@ -126,7 +126,7 @@ CMDSRCS = crapto1/crapto1.c \ loclass/elite_crack.c \ loclass/fileutils.c \ whereami.c \ - mifarehost.c \ + mifare/mifarehost.c \ parity.c \ crc.c \ crc16.c \ @@ -156,7 +156,7 @@ CMDSRCS = crapto1/crapto1.c \ emv/test/cda_test.c\ emv/cmdemv.c \ emv/emv_roca.c \ - mifare4.c \ + mifare/mifare4.c \ cmdanalyse.c \ cmdhf.c \ cmdhflist.c \ diff --git a/client/cmdanalyse.h b/client/cmdanalyse.h index f834c717d..ab7606f5c 100644 --- a/client/cmdanalyse.h +++ b/client/cmdanalyse.h @@ -16,15 +16,15 @@ #include #include "cmdmain.h" #include "proxmark3.h" -#include "ui.h" // PrintAndLog +#include "ui.h" // PrintAndLog #include "util.h" #include "crc.h" #include "crc16.h" // crc16 ccitt #include "tea.h" #include "legic_prng.h" #include "loclass/elite_crack.h" -#include "mfkey.h" //nonce2key -#include "util_posix.h" // msclock +#include "mifare/mfkey.h" //nonce2key +#include "util_posix.h" // msclock int usage_analyse_lcr(void); diff --git a/client/cmdhf14a.h b/client/cmdhf14a.h index 723c31100..3fe04d26c 100644 --- a/client/cmdhf14a.h +++ b/client/cmdhf14a.h @@ -29,7 +29,7 @@ #include "cmdhfmf.h" #include "cmdhfmfu.h" #include "cmdhf.h" // list cmd -#include "mifarehost.h" +#include "mifare/mifarehost.h" #include "emv/apduinfo.h" #include "emv/emvcore.h" diff --git a/client/cmdhflist.h b/client/cmdhflist.h index 1955119f2..60a0a0dfd 100644 --- a/client/cmdhflist.h +++ b/client/cmdhflist.h @@ -31,8 +31,8 @@ #include "emv/cmdemv.h" // EMV #include "protocols.h" #include "crapto1/crapto1.h" -#include "mifarehost.h" -#include "mifaredefault.h" +#include "mifare/mifarehost.h" +#include "mifare/mifaredefault.h" #include "parity.h" // oddparity #include "iso15693tools.h" // ISO15693 crc diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 811fa2430..a12bc34c2 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -9,7 +9,7 @@ //----------------------------------------------------------------------------- #include "cmdhfmf.h" -#include "mifare4.h" +#include "mifare/mifare4.h" #define MIFARE_4K_MAXBLOCK 256 #define MIFARE_2K_MAXBLOCK 128 @@ -3216,18 +3216,28 @@ int CmdHF14AMfMAD(const char *cmd) { CLIParserFree(); uint8_t sector[16 * 4] = {0}; - if (mfReadSector(0, 0, (uint8_t *)g_mifare_mad_key, sector)) { + if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector)) { PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); return 2; } if (verbose) { - for(int i = 0; i < 3; i ++) - PrintAndLogEx(NORMAL, "[i] %s", sprint_hex(§or[i * 16], 16)); + for(int i = 0; i < 4; i ++) + PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(§or[i * 16], 16)); } + /* + bool haveMAD2 = false; + MAD1DecodeAndPrint(sector, verbose, &haveMAD2); -// MADDecodeAndPrint(sector, verbose); - + if (haveMAD2) { + if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector)) { + PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); + return 2; + } + + MAD2DecodeAndPrint(sector, verbose); + } + */ return 0; } diff --git a/client/cmdhfmf.h b/client/cmdhfmf.h index eeb7a74f6..bdd817e41 100644 --- a/client/cmdhfmf.h +++ b/client/cmdhfmf.h @@ -23,14 +23,14 @@ #include "cmdparser.h" #include "common.h" #include "util.h" -#include "mifare.h" // nonces_t struct -#include "mfkey.h" // mfkey32_moebious +#include "mifare.h" // nonces_t struct +#include "mifare/mfkey.h" // mfkey32_moebious #include "cmdhfmfhard.h" -#include "mifarehost.h" // icesector_t, sector_t -#include "util_posix.h" // msclock -#include "mifaredefault.h" // mifare default key array -#include "cmdhf14a.h" // dropfield -#include "cliparser/cliparser.h" // argtable +#include "mifare/mifarehost.h" // icesector_t, sector_t +#include "util_posix.h" // msclock +#include "mifare/mifaredefault.h" // mifare default key array +#include "cmdhf14a.h" // dropfield +#include "cliparser/cliparser.h" // argtable #include "hardnested/hardnested_bf_core.h" // SetSIMDInstr extern int CmdHFMF(const char *Cmd); diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 0d7a623d4..0917728be 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -22,7 +22,7 @@ #include "ui.h" #include "cmdhf14a.h" #include "mifare.h" -#include "mifare4.h" +#include "mifare/mifare4.h" #include "cliparser/cliparser.h" #include "crypto/libpcrypto.h" diff --git a/client/cmdhfmfp.h b/client/cmdhfmfp.h index b1ac7c349..a5cacb518 100644 --- a/client/cmdhfmfp.h +++ b/client/cmdhfmfp.h @@ -10,7 +10,7 @@ #ifndef CMDHFMFP_H__ #define CMDHFMFP_H__ -#include "mifaredefault.h" +#include "mifare/mifaredefault.h" extern int CmdHFMFP(const char *Cmd); diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index 3fc781d2e..9485707f1 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -48,7 +48,7 @@ #include #include "../ui.h" #include "../emv/emvjson.h" -#include "mifare4.h" +#include "mifare/mifare4.h" #include "cmdhfmfu.h" typedef enum { diff --git a/client/mfkey.c b/client/mifare/mfkey.c similarity index 100% rename from client/mfkey.c rename to client/mifare/mfkey.c diff --git a/client/mfkey.h b/client/mifare/mfkey.h similarity index 100% rename from client/mfkey.h rename to client/mifare/mfkey.h diff --git a/client/mifare4.c b/client/mifare/mifare4.c similarity index 100% rename from client/mifare4.c rename to client/mifare/mifare4.c diff --git a/client/mifare4.h b/client/mifare/mifare4.h similarity index 100% rename from client/mifare4.h rename to client/mifare/mifare4.h diff --git a/client/mifaredefault.h b/client/mifare/mifaredefault.h similarity index 100% rename from client/mifaredefault.h rename to client/mifare/mifaredefault.h diff --git a/client/mifarehost.c b/client/mifare/mifarehost.c similarity index 95% rename from client/mifarehost.c rename to client/mifare/mifarehost.c index ba5081441..cd239d585 100644 --- a/client/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -1,1020 +1,1015 @@ -// Merlok, 2011, 2012 -// people from mifare@nethemba.com, 2010 -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// mifare commands -//----------------------------------------------------------------------------- -#include "mifarehost.h" -#include "cmdmain.h" - -int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { - uint32_t uid = 0; - uint32_t nt = 0, nr = 0, ar = 0; - uint64_t par_list = 0, ks_list = 0; - uint64_t *keylist = NULL, *last_keylist = NULL; - uint32_t keycount = 0; - int16_t isOK = 0; - - UsbCommand c = {CMD_READER_MIFARE, {true, blockno, key_type}}; - - // message - PrintAndLogEx(NORMAL, "--------------------------------------------------------------------------------\n"); - PrintAndLogEx(NORMAL, "executing Darkside attack. Expected execution time: 25sec on average"); - PrintAndLogEx(NORMAL, "press pm3-button on the proxmark3 device to abort both proxmark3 and client."); - PrintAndLogEx(NORMAL, "--------------------------------------------------------------------------------\n"); - - while (true) { - clearCommandBuffer(); - SendCommand(&c); - - //flush queue - while (ukbhit()) { - int gc = getchar(); (void)gc; - return -5; - } - - // wait cycle - while (true) { - printf("."); fflush(stdout); - if (ukbhit()) { - int gc = getchar(); (void)gc; - return -5; - } - - UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - isOK = resp.arg[0]; - if (isOK < 0) - return isOK; - - uid = (uint32_t)bytes_to_num(resp.d.asBytes + 0, 4); - nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4); - par_list = bytes_to_num(resp.d.asBytes + 8, 8); - ks_list = bytes_to_num(resp.d.asBytes + 16, 8); - nr = (uint32_t)bytes_to_num(resp.d.asBytes + 24, 4); - ar = (uint32_t)bytes_to_num(resp.d.asBytes + 28, 4); - break; - } - } - PrintAndLogEx(NORMAL, "\n"); - - if (par_list == 0 && c.arg[0] == true) { - PrintAndLogEx(SUCCESS, "Parity is all zero. Most likely this card sends NACK on every authentication."); - } - c.arg[0] = false; - - keycount = nonce2key(uid, nt, nr, ar, par_list, ks_list, &keylist); - - if (keycount == 0) { - PrintAndLogEx(FAILED, "key not found (lfsr_common_prefix list is null). Nt=%08x", nt); - PrintAndLogEx(FAILED, "this is expected to happen in 25%% of all cases. Trying again with a different reader nonce..."); - continue; - } - - // only parity zero attack - if (par_list == 0 ) { - qsort(keylist, keycount, sizeof(*keylist), compare_uint64); - keycount = intersection(last_keylist, keylist); - if (keycount == 0) { - free(last_keylist); - last_keylist = keylist; - PrintAndLogEx(FAILED, "no candidates found, trying again"); - continue; - } - } - - PrintAndLogEx(SUCCESS, "found %u candidate key%s\n", keycount, (keycount > 1) ? "s." : "."); - - *key = -1; - uint8_t keyBlock[USB_CMD_DATA_SIZE]; - int max_keys = USB_CMD_DATA_SIZE / 6; - for (int i = 0; i < keycount; i += max_keys) { - - int size = keycount - i > max_keys ? max_keys : keycount - i; - for (int j = 0; j < size; j++) { - if (par_list == 0) { - num_to_bytes(last_keylist[i*max_keys + j], 6, keyBlock+(j*6)); - } else { - num_to_bytes(keylist[i*max_keys + j], 6, keyBlock+(j*6)); - } - } - - if (!mfCheckKeys(blockno, key_type - 0x60, false, size, keyBlock, key)) { - break; - } - } - - if (*key != -1) { - break; - } else { - PrintAndLogEx(FAILED, "all candidate keys failed. Restarting darkside attack"); - free(last_keylist); - last_keylist = keylist; - c.arg[0] = true; - } - } - free(last_keylist); - free(keylist); - return 0; -} -int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){ - *key = -1; - UsbCommand c = {CMD_MIFARE_CHKKEYS, { (blockNo | (keyType << 8)), clear_trace, keycnt}}; - memcpy(c.d.asBytes, keyBlock, 6 * keycnt); - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) return 1; - if ((resp.arg[0] & 0xff) != 0x01) return 2; - *key = bytes_to_num(resp.d.asBytes, 6); - return 0; -} - -// Sends chunks of keys to device. -// 0 == ok all keys found -// 1 == -// 2 == Time-out, aborting -int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, uint8_t strategy, - uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory) { - - uint64_t t2 = msclock(); - uint32_t timeout = 0; - - // send keychunk - UsbCommand c = {CMD_MIFARE_CHKKEYS_FAST, { (sectorsCnt | (firstChunk << 8) | (lastChunk << 12) ), ((use_flashmemory << 8) | strategy), size}}; - memcpy(c.d.asBytes, keyBlock, 6 * size); - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - - while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - timeout++; - printf("."); fflush(stdout); - // max timeout for one chunk of 85keys, 60*3sec = 180seconds - // s70 with 40*2 keys to check, 80*85 = 6800 auth. - // takes about 97s, still some margin before abort - if (timeout > 180) { - PrintAndLogEx(WARNING, "\nno response from Proxmark. Aborting..."); - return 2; - } - } - t2 = msclock() - t2; - - // time to convert the returned data. - uint8_t curr_keys = resp.arg[0]; - - PrintAndLogEx(SUCCESS, "\nChunk: %.1fs | found %u/%u keys (%u)", (float)(t2/1000.0), curr_keys, (sectorsCnt<<1), size); - - // all keys? - if ( curr_keys == sectorsCnt*2 || lastChunk ) { - - // success array. each byte is status of key - uint8_t arr[80]; - uint64_t foo = 0; - uint16_t bar = 0; - foo = bytes_to_num(resp.d.asBytes+480, 8); - bar = (resp.d.asBytes[489] << 8 | resp.d.asBytes[488]); - - for (uint8_t i = 0; i < 64; i++) - arr[i] = (foo >> i) & 0x1; - - for (uint8_t i = 0; i < 16; i++) - arr[i+64] = (bar >> i) & 0x1; - - // initialize storage for found keys - icesector_t *tmp = calloc(sectorsCnt, sizeof(icesector_t)); - if (tmp == NULL) - return 1; - memcpy(tmp, resp.d.asBytes, sectorsCnt * sizeof(icesector_t) ); - - for ( int i = 0; i < sectorsCnt; i++) { - // key A - if ( !e_sector[i].foundKey[0] ) { - e_sector[i].Key[0] = bytes_to_num( tmp[i].keyA, 6); - e_sector[i].foundKey[0] = arr[ (i*2) ]; - } - // key B - if ( !e_sector[i].foundKey[1] ) { - e_sector[i].Key[1] = bytes_to_num( tmp[i].keyB, 6); - e_sector[i].foundKey[1] = arr[ (i*2) + 1 ]; - } - } - free(tmp); - - if ( curr_keys == sectorsCnt*2 ) - return 0; - if ( lastChunk ) - return 1; - } - return 1; -} - -// PM3 imp of J-Run mf_key_brute (part 2) -// ref: https://github.com/J-Run/mf_key_brute -int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey){ - - #define KEYS_IN_BLOCK 85 - #define KEYBLOCK_SIZE 510 - #define CANDIDATE_SIZE 0xFFFF * 6 - uint8_t found = false; - uint64_t key64 = 0; - uint8_t candidates[CANDIDATE_SIZE] = {0x00}; - uint8_t keyBlock[KEYBLOCK_SIZE] = {0x00}; - - memset(candidates, 0, sizeof(candidates)); - memset(keyBlock, 0, sizeof(keyBlock)); - - // Generate all possible keys for the first two unknown bytes. - for (uint16_t i = 0; i < 0xFFFF; ++i) { - uint32_t j = i * 6; - candidates[0 + j] = i >> 8; - candidates[1 + j] = i; - candidates[2 + j] = key[2]; - candidates[3 + j] = key[3]; - candidates[4 + j] = key[4]; - candidates[5 + j] = key[5]; - } - uint32_t counter, i; - for ( i = 0, counter = 1; i < CANDIDATE_SIZE; i += KEYBLOCK_SIZE, ++counter){ - - key64 = 0; - - // copy candidatekeys to test key block - memcpy(keyBlock, candidates + i, KEYBLOCK_SIZE); - - // check a block of generated candidate keys. - if (!mfCheckKeys(blockNo, keyType, true, KEYS_IN_BLOCK, keyBlock, &key64)) { - *resultkey = key64; - found = true; - break; - } - - // progress - if ( counter % 20 == 0 ) - PrintAndLogEx(SUCCESS, "tried : %s.. \t %u keys", sprint_hex(candidates + i, 6), counter * KEYS_IN_BLOCK ); - } - return found; -} - -// Compare 16 Bits out of cryptostate -int Compare16Bits(const void * a, const void * b) { - if ((*(uint64_t*)b & 0x00ff000000ff0000) == (*(uint64_t*)a & 0x00ff000000ff0000)) return 0; - if ((*(uint64_t*)b & 0x00ff000000ff0000) > (*(uint64_t*)a & 0x00ff000000ff0000)) return 1; - return -1; -} - -// wrapper function for multi-threaded lfsr_recovery32 -void -#ifdef __has_attribute -#if __has_attribute(force_align_arg_pointer) -__attribute__((force_align_arg_pointer)) -#endif -#endif -*nested_worker_thread(void *arg) { - struct Crypto1State *p1; - StateList_t *statelist = arg; - statelist->head.slhead = lfsr_recovery32(statelist->ks1, statelist->nt ^ statelist->uid); - - for (p1 = statelist->head.slhead; *(uint64_t *)p1 != 0; p1++) {}; - - statelist->len = p1 - statelist->head.slhead; - statelist->tail.sltail = --p1; - qsort(statelist->head.slhead, statelist->len, sizeof(uint64_t), Compare16Bits); - - return statelist->head.slhead; -} - -int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * resultKey, bool calibrate) { - uint16_t i; - uint32_t uid; - UsbCommand resp; - StateList_t statelists[2]; - struct Crypto1State *p1, *p2, *p3, *p4; - - UsbCommand c = {CMD_MIFARE_NESTED, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, calibrate}}; - memcpy(c.d.asBytes, key, 6); - clearCommandBuffer(); - SendCommand(&c); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; - - // error during nested - if (resp.arg[0]) return resp.arg[0]; - - memcpy(&uid, resp.d.asBytes, 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 - pthread_t thread_id[2]; - - // create and run worker threads - for (i = 0; i < 2; i++) - pthread_create(thread_id + i, NULL, nested_worker_thread, &statelists[i]); - - // wait for threads to terminate: - for (i = 0; i < 2; i++) - pthread_join(thread_id[i], (void*)&statelists[i].head.slhead); - - // the first 16 Bits of the cryptostate already contain part of our key. - // Create the intersection of the two lists based on these 16 Bits and - // roll back the cryptostate - p1 = p3 = statelists[0].head.slhead; - p2 = p4 = statelists[1].head.slhead; - - while (p1 <= statelists[0].tail.sltail && p2 <= statelists[1].tail.sltail) { - if (Compare16Bits(p1, p2) == 0) { - - struct Crypto1State savestate, *savep = &savestate; - savestate = *p1; - while(Compare16Bits(p1, savep) == 0 && p1 <= statelists[0].tail.sltail) { - *p3 = *p1; - lfsr_rollback_word(p3, statelists[0].nt ^ statelists[0].uid, 0); - p3++; - p1++; - } - savestate = *p2; - while(Compare16Bits(p2, savep) == 0 && p2 <= statelists[1].tail.sltail) { - *p4 = *p2; - lfsr_rollback_word(p4, statelists[1].nt ^ statelists[1].uid, 0); - p4++; - p2++; - } - } - else { - while (Compare16Bits(p1, p2) == -1) p1++; - while (Compare16Bits(p1, p2) == 1) p2++; - } - } - - *(uint64_t*)p3 = -1; - *(uint64_t*)p4 = -1; - statelists[0].len = p3 - statelists[0].head.slhead; - statelists[1].len = p4 - statelists[1].head.slhead; - statelists[0].tail.sltail = --p3; - statelists[1].tail.sltail = --p4; - - // the statelists now contain possible keys. The key we are searching for must be in the - // intersection of both lists - qsort(statelists[0].head.keyhead, statelists[0].len, sizeof(uint64_t), compare_uint64); - qsort(statelists[1].head.keyhead, statelists[1].len, sizeof(uint64_t), compare_uint64); - // Create the intersection - statelists[0].len = intersection(statelists[0].head.keyhead, statelists[1].head.keyhead); - - //statelists[0].tail.keytail = --p7; - uint32_t keycnt = statelists[0].len; - if ( keycnt == 0 ) goto out; - - memset(resultKey, 0, 6); - uint64_t key64 = -1; - - // The list may still contain several key candidates. Test each of them with mfCheckKeys - uint32_t max_keys = keycnt > (USB_CMD_DATA_SIZE/6) ? (USB_CMD_DATA_SIZE/6) : keycnt; - uint8_t keyBlock[USB_CMD_DATA_SIZE] = {0x00}; - - for (int i = 0; i < keycnt; i += max_keys) { - - int size = keycnt - i > max_keys ? max_keys : keycnt - i; - - for (int j = 0; j < size; j++) { - crypto1_get_lfsr(statelists[0].head.slhead + i, &key64); - num_to_bytes(key64, 6, keyBlock + i * 6); - } - - if (!mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, size, keyBlock, &key64)) { - free(statelists[0].head.slhead); - free(statelists[1].head.slhead); - num_to_bytes(key64, 6, resultKey); - - PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [%012" PRIx64 "]", - (uint16_t)resp.arg[2] & 0xff, - (resp.arg[2] >> 8) ? 'B' : 'A', - key64 - ); - return -5; - } - } - -out: - PrintAndLogEx(SUCCESS, "target block:%3u key type: %c", - (uint16_t)resp.arg[2] & 0xff, - (resp.arg[2] >> 8) ? 'B' : 'A' - ); - - free(statelists[0].head.slhead); - free(statelists[1].head.slhead); - return -4; -} - -// MIFARE -int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data) { - - UsbCommand c = {CMD_MIFARE_READSC, {sectorNo, keyType, 0}}; - memcpy(c.d.asBytes, key, 6); - clearCommandBuffer(); - SendCommand(&c); - - UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - uint8_t isOK = resp.arg[0] & 0xff; - - if (isOK) { - memcpy(data, resp.d.asBytes, mfNumBlocksPerSector(sectorNo) * 16); - for (int i = 0; i < (sectorNo<32?3:15); i++) { - PrintAndLogEx(NORMAL, "data : %s", sprint_hex(data + i * 16, 16)); - } - PrintAndLogEx(NORMAL, "trailer: %s", sprint_hex(data + (sectorNo<32?3:15) * 16, 16)); - - return 0; - } else { - return isOK; - } - } else { - PrintAndLogEx(ERR, "Command execute timeout"); - return 2; - } - - return 0; -} - -// EMULATOR -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); - return 0; -} - -int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) { - 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; -} - -// "MAGIC" CARD -int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_t wipecard) { - - uint8_t params = MAGIC_SINGLE; - uint8_t block0[16]; - memset(block0, 0x00, sizeof(block0)); - - int old = mfCGetBlock(0, block0, params); - if (old == 0) - PrintAndLogEx(SUCCESS, "old block 0: %s", sprint_hex(block0, sizeof(block0))); - else - PrintAndLogEx(FAILED, "couldn't get old data. Will write over the last bytes of Block 0."); - - // fill in the new values - // UID - memcpy(block0, uid, 4); - // Mifare UID BCC - block0[4] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3]; - // mifare classic SAK(byte 5) and ATQA(byte 6 and 7, reversed) - if ( sak != NULL ) - block0[5] = sak[0]; - - if ( atqa != NULL ) { - block0[6] = atqa[1]; - block0[7] = atqa[0]; - } - PrintAndLogEx(SUCCESS, "new block 0: %s", sprint_hex(block0,16)); - - if ( wipecard ) params |= MAGIC_WIPE; - if ( oldUID == NULL) params |= MAGIC_UID; - - return mfCSetBlock(0, block0, oldUID, params); -} - -int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params) { - - uint8_t isOK = 0; - UsbCommand c = {CMD_MIFARE_CSETBLOCK, {params, blockNo, 0}}; - memcpy(c.d.asBytes, data, 16); - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - isOK = resp.arg[0] & 0xff; - if (uid != NULL) - memcpy(uid, resp.d.asBytes, 4); - if (!isOK) - return 2; - } else { - PrintAndLogEx(WARNING, "command execute timeout"); - return 1; - } - return 0; -} - -int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) { - uint8_t isOK = 0; - UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, blockNo, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - isOK = resp.arg[0] & 0xff; - if (!isOK) - return 2; - memcpy(data, resp.d.asBytes, 16); - } else { - PrintAndLogEx(WARNING, "command execute timeout"); - return 1; - } - return 0; -} - -// SNIFFER -// [iceman] so many global variables.... - -// constants -static uint8_t trailerAccessBytes[4] = {0x08, 0x77, 0x8F, 0x00}; - -// variables -char logHexFileName[FILE_PATH_SIZE] = {0x00}; -static uint8_t traceCard[4096] = {0x00}; -static char traceFileName[FILE_PATH_SIZE] = {0x00}; -static int traceState = TRACE_IDLE; -static uint8_t traceCurBlock = 0; -static uint8_t traceCurKey = 0; - -struct Crypto1State *traceCrypto1 = NULL; -struct Crypto1State *revstate = NULL; -uint64_t key = 0; -uint32_t ks2 = 0; -uint32_t ks3 = 0; - -uint32_t cuid = 0; // uid part used for crypto1. -uint32_t nt = 0; // tag challenge -uint32_t nr_enc = 0; // encrypted reader challenge -uint32_t ar_enc = 0; // encrypted reader response -uint32_t at_enc = 0; // encrypted tag response - -int isTraceCardEmpty(void) { - return ((traceCard[0] == 0) && (traceCard[1] == 0) && (traceCard[2] == 0) && (traceCard[3] == 0)); -} - -int isBlockEmpty(int blockN) { - for (int i = 0; i < 16; i++) - if (traceCard[blockN * 16 + i] != 0) return 0; - - return 1; -} - -int isBlockTrailer(int blockN) { - return ((blockN & 0x03) == 0x03); -} - -int loadTraceCard(uint8_t *tuid, uint8_t uidlen) { - FILE * f; - char buf[64] = {0x00}; - uint8_t buf8[64] = {0x00}; - int i, blockNum; - uint32_t tmp; - - if (!isTraceCardEmpty()) - saveTraceCard(); - - memset(traceCard, 0x00, 4096); - memcpy(traceCard, tuid, uidlen); - - FillFileNameByUID(traceFileName, tuid, ".eml", uidlen); - - f = fopen(traceFileName, "r"); - if (!f) return 1; - - blockNum = 0; - - while (!feof(f)){ - - memset(buf, 0, sizeof(buf)); - if (fgets(buf, sizeof(buf), f) == NULL) { - PrintAndLogEx(FAILED, "No trace file found or reading error."); - if (f) { - fclose(f); - } - return 2; - } - - if (strlen(buf) < 32){ - if (feof(f)) break; - PrintAndLogEx(FAILED, "File content error. Block data must include 32 HEX symbols"); - if (f) { - fclose(f); - } - return 2; - } - for (i = 0; i < 32; i += 2) { - sscanf(&buf[i], "%02X", &tmp); - buf8[i / 2] = tmp & 0xFF; - } - - memcpy(traceCard + blockNum * 16, buf8, 16); - - blockNum++; - } - if (f) { - fclose(f); - } - return 0; -} - -int saveTraceCard(void) { - - if ((!strlen(traceFileName)) || (isTraceCardEmpty())) return 0; - - FILE * f; - f = fopen(traceFileName, "w+"); - if ( !f ) return 1; - - // given 4096 tracecard size, these loop will only match a 1024, 1kb card memory - // 4086/16 == 256blocks. - for (uint16_t i = 0; i < 256; i++) { // blocks - for (uint8_t j = 0; j < 16; j++) // bytes - fprintf(f, "%02X", *(traceCard + i * 16 + j)); - - // no extra line in the end - if ( i < 255 ) - fprintf(f, "\n"); - } - fflush(f); - fclose(f); - return 0; -} -// -int mfTraceInit(uint8_t *tuid, uint8_t uidlen, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile) { - - if (traceCrypto1) - crypto1_destroy(traceCrypto1); - - traceCrypto1 = NULL; - - if (wantSaveToEmlFile) - loadTraceCard(tuid, uidlen); - - traceCard[4] = traceCard[0] ^ traceCard[1] ^ traceCard[2] ^ traceCard[3]; - traceCard[5] = sak; - memcpy(&traceCard[6], atqa, 2); - traceCurBlock = 0; - cuid = bytes_to_num(tuid + (uidlen-4), 4); - traceState = TRACE_IDLE; - return 0; -} - -void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted){ - uint8_t bt = 0; - int i; - - if (len != 1) { - for (i = 0; i < len; i++) - data[i] = crypto1_byte(pcs, 0x00, isEncrypted) ^ data[i]; - } else { - bt = 0; - bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 0)) << 0; - bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 1)) << 1; - bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 2)) << 2; - bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 3)) << 3; - data[0] = bt; - } -} - -int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { - - if (traceState == TRACE_ERROR) - return 1; - - if (len > 255) { - traceState = TRACE_ERROR; - return 1; - } - - uint8_t data[255]; - memset(data, 0x00, sizeof(data)); - - memcpy(data, data_src, len); - - if ((traceCrypto1) && ((traceState == TRACE_IDLE) || (traceState > TRACE_AUTH_OK))) { - mf_crypto1_decrypt(traceCrypto1, data, len, 0); - PrintAndLogEx(NORMAL, "DEC| %s", sprint_hex(data, len)); - AddLogHex(logHexFileName, "DEC| ", data, len); - } - - switch (traceState) { - case TRACE_IDLE: - // check packet crc16! - if ((len >= 4) && (!check_crc(CRC_14443_A, data, len))) { - PrintAndLogEx(NORMAL, "DEC| CRC ERROR!!!"); - AddLogLine(logHexFileName, "DEC| ", "CRC ERROR!!!"); - traceState = TRACE_ERROR; // do not decrypt the next commands - return 1; - } - - // AUTHENTICATION - if ((len == 4) && ((data[0] == MIFARE_AUTH_KEYA) || (data[0] == MIFARE_AUTH_KEYB))) { - traceState = TRACE_AUTH1; - traceCurBlock = data[1]; - traceCurKey = data[0] == 60 ? 1:0; - return 0; - } - - // READ - if ((len == 4) && ((data[0] == ISO14443A_CMD_READBLOCK))) { - traceState = TRACE_READ_DATA; - traceCurBlock = data[1]; - return 0; - } - - // WRITE - if ((len == 4) && ((data[0] == ISO14443A_CMD_WRITEBLOCK))) { - traceState = TRACE_WRITE_OK; - traceCurBlock = data[1]; - return 0; - } - - // HALT - if ((len == 4) && ((data[0] == ISO14443A_CMD_HALT) && (data[1] == 0x00))) { - traceState = TRACE_ERROR; // do not decrypt the next commands - return 0; - } - return 0; - - case TRACE_READ_DATA: - if (len == 18) { - traceState = TRACE_IDLE; - - if (isBlockTrailer(traceCurBlock)) { - memcpy(traceCard + traceCurBlock * 16 + 6, data + 6, 4); - } else { - memcpy(traceCard + traceCurBlock * 16, data, 16); - } - if (wantSaveToEmlFile) saveTraceCard(); - return 0; - } else { - traceState = TRACE_ERROR; - return 1; - } - break; - case TRACE_WRITE_OK: - if ((len == 1) && (data[0] == 0x0a)) { - traceState = TRACE_WRITE_DATA; - return 0; - } else { - traceState = TRACE_ERROR; - return 1; - } - break; - case TRACE_WRITE_DATA: - if (len == 18) { - traceState = TRACE_IDLE; - memcpy(traceCard + traceCurBlock * 16, data, 16); - if (wantSaveToEmlFile) saveTraceCard(); - return 0; - } else { - traceState = TRACE_ERROR; - return 1; - } - break; - case TRACE_AUTH1: - if (len == 4) { - traceState = TRACE_AUTH2; - nt = bytes_to_num(data, 4); - return 0; - } else { - traceState = TRACE_ERROR; - return 1; - } - break; - case TRACE_AUTH2: - if (len == 8) { - traceState = TRACE_AUTH_OK; - nr_enc = bytes_to_num(data, 4); - ar_enc = bytes_to_num(data + 4, 4); - return 0; - } else { - traceState = TRACE_ERROR; - return 1; - } - break; - case TRACE_AUTH_OK: - if (len == 4) { - traceState = TRACE_IDLE; - at_enc = bytes_to_num(data, 4); - - // mfkey64 recover key. - ks2 = ar_enc ^ prng_successor(nt, 64); - ks3 = at_enc ^ prng_successor(nt, 96); - revstate = lfsr_recovery64(ks2, ks3); - lfsr_rollback_word(revstate, 0, 0); - lfsr_rollback_word(revstate, 0, 0); - lfsr_rollback_word(revstate, nr_enc, 1); - lfsr_rollback_word(revstate, cuid ^ nt, 0); - crypto1_get_lfsr(revstate, &key); - PrintAndLogEx(SUCCESS, "found Key: [%012" PRIx64 "]", key); - - //if ( tryMfk64(cuid, nt, nr_enc, ar_enc, at_enc, &key) ) - AddLogUint64(logHexFileName, "Found Key: ", key); - - int blockShift = ((traceCurBlock & 0xFC) + 3) * 16; - if (isBlockEmpty((traceCurBlock & 0xFC) + 3)) - memcpy(traceCard + blockShift + 6, trailerAccessBytes, 4); - - // keytype A/B - if (traceCurKey) - num_to_bytes(key, 6, traceCard + blockShift + 10); - else - num_to_bytes(key, 6, traceCard + blockShift); - - if (wantSaveToEmlFile) - saveTraceCard(); - - if (traceCrypto1) - crypto1_destroy(traceCrypto1); - - // set cryptosystem state - traceCrypto1 = lfsr_recovery64(ks2, ks3); - - } else { - PrintAndLogEx(NORMAL, "[!] nested key recovery not implemented!\n"); - at_enc = bytes_to_num(data, 4); - crypto1_destroy(traceCrypto1); - traceState = TRACE_ERROR; - } - break; - default: - traceState = TRACE_ERROR; - return 1; - } - return 0; -} - -int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len){ - PrintAndLogEx(SUCCESS, "\nencrypted data: [%s]", sprint_hex(data, len) ); - struct Crypto1State *s; - ks2 = ar_enc ^ prng_successor(nt, 64); - ks3 = at_enc ^ prng_successor(nt, 96); - s = lfsr_recovery64(ks2, ks3); - mf_crypto1_decrypt(s, data, len, false); - PrintAndLogEx(SUCCESS, "decrypted data: [%s]", sprint_hex(data, len) ); - crypto1_destroy(s); - return 0; -} - -/* Detect Tag Prng, -* function performs a partial AUTH, where it tries to authenticate against block0, key A, but only collects tag nonce. -* the tag nonce is check to see if it has a predictable PRNG. -* @returns -* TRUE if tag uses WEAK prng (ie Now the NACK bug also needs to be present for Darkside attack) -* FALSE is tag uses HARDEND prng (ie hardnested attack possible, with known key) -*/ -int detect_classic_prng(void){ - - UsbCommand resp, respA; - uint8_t cmd[] = {MIFARE_AUTH_KEYA, 0x00}; - uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_RATS; - - UsbCommand c = {CMD_READER_ISO_14443a, {flags, sizeof(cmd), 0}}; - memcpy(c.d.asBytes, cmd, sizeof(cmd)); - - clearCommandBuffer(); - SendCommand(&c); - - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - PrintAndLogEx(WARNING, "PRNG UID: Reply timeout."); - return -1; - } - - // if select tag failed. - if ( resp.arg[0] == 0 ) { - PrintAndLogEx(WARNING, "error: selecting tag failed, can't detect prng\n"); - return -2; - } - if (!WaitForResponseTimeout(CMD_ACK, &respA, 2500)) { - PrintAndLogEx(WARNING, "PRNG data: Reply timeout."); - return -3; - } - - // check respA - if (respA.arg[0] != 4) { - PrintAndLogEx(WARNING, "PRNG data error: Wrong length: %d", respA.arg[0]); - return -4; - } - - uint32_t nonce = bytes_to_num(respA.d.asBytes, respA.arg[0]); - return validate_prng_nonce(nonce); -} -/* Detect Mifare Classic NACK bug - -returns: -0 = error during test / aborted -1 = has nack bug -2 = has not nack bug -3 = always leak nacks (clones) -*/ -int detect_classic_nackbug(bool verbose){ - - UsbCommand c = {CMD_MIFARE_NACK_DETECT, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - - if ( verbose ) - PrintAndLogEx(SUCCESS, "press pm3-button on the proxmark3 device to abort both proxmark3 and client.\n"); - - // for nice animation - bool term = !isatty(STDIN_FILENO); -#if defined(__linux__) || (__APPLE__) - char star[] = {'-', '\\', '|', '/'}; - uint8_t staridx = 0; -#endif - - while (true) { - - if (term) { - printf("."); - } else { - printf( - #if defined(__linux__) || (__APPLE__) - "\e[32m\e[s%c\e[u\e[0m", star[ (staridx++ % 4) ] - #else - "." - #endif - ); - } - fflush(stdout); - if (ukbhit()) { - int gc = getchar(); (void)gc; - return -1; - break; - } - - if (WaitForResponseTimeout(CMD_ACK, &resp, 500)) { - int32_t ok = resp.arg[0]; - uint32_t nacks = resp.arg[1]; - uint32_t auths = resp.arg[2]; - PrintAndLogEx(NORMAL, ""); - - if ( verbose ) { - PrintAndLogEx(SUCCESS, "num of auth requests : %u", auths); - PrintAndLogEx(SUCCESS, "num of received NACK : %u", nacks); - } - switch( ok ) { - case 99 : PrintAndLogEx(WARNING, "button pressed. Aborted."); return 0; - case 96 : - case 98 : { - if (verbose) - PrintAndLogEx(FAILED, "card random number generator is not predictable."); - PrintAndLogEx(WARNING, "detection failed"); - return 2; - } - case 97 : { - if (verbose) { - PrintAndLogEx(FAILED, "card random number generator seems to be based on the well-known generating polynomial"); - PrintAndLogEx(NORMAL, "[- ]with 16 effective bits only, but shows unexpected behavior, try again."); - return 0; - } - } - case 2 : PrintAndLogEx(SUCCESS, "always leak NACK detected"); return 3; - case 1 : PrintAndLogEx(SUCCESS, "NACK bug detected"); return 1; - case 0 : PrintAndLogEx(SUCCESS, "No NACK bug detected"); return 2; - default : PrintAndLogEx(WARNING, "errorcode from device [%i]", ok); return 0; - } - break; - } - } - return 0; -} -/* try to see if card responses to "chinese magic backdoor" commands. */ -void detect_classic_magic(void) { - - uint8_t isGeneration = 0; - UsbCommand resp; - UsbCommand c = {CMD_MIFARE_CIDENT, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) - isGeneration = resp.arg[0] & 0xff; - - switch( isGeneration ){ - case 1: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 1a): YES"); break; - case 2: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 1b): YES"); break; - //case 4: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 2): YES"); break; - default: PrintAndLogEx(INFO, "Answers to magic commands: NO"); break; - } +// Merlok, 2011, 2012 +// people from mifare@nethemba.com, 2010 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// mifare commands +//----------------------------------------------------------------------------- +#include "mifarehost.h" +#include "cmdmain.h" + +int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { + uint32_t uid = 0; + uint32_t nt = 0, nr = 0, ar = 0; + uint64_t par_list = 0, ks_list = 0; + uint64_t *keylist = NULL, *last_keylist = NULL; + uint32_t keycount = 0; + int16_t isOK = 0; + + UsbCommand c = {CMD_READER_MIFARE, {true, blockno, key_type}}; + + // message + PrintAndLogEx(NORMAL, "--------------------------------------------------------------------------------\n"); + PrintAndLogEx(NORMAL, "executing Darkside attack. Expected execution time: 25sec on average"); + PrintAndLogEx(NORMAL, "press pm3-button on the proxmark3 device to abort both proxmark3 and client."); + PrintAndLogEx(NORMAL, "--------------------------------------------------------------------------------\n"); + + while (true) { + clearCommandBuffer(); + SendCommand(&c); + + //flush queue + while (ukbhit()) { + int gc = getchar(); (void)gc; + return -5; + } + + // wait cycle + while (true) { + printf("."); fflush(stdout); + if (ukbhit()) { + int gc = getchar(); (void)gc; + return -5; + } + + UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + isOK = resp.arg[0]; + if (isOK < 0) + return isOK; + + uid = (uint32_t)bytes_to_num(resp.d.asBytes + 0, 4); + nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4); + par_list = bytes_to_num(resp.d.asBytes + 8, 8); + ks_list = bytes_to_num(resp.d.asBytes + 16, 8); + nr = (uint32_t)bytes_to_num(resp.d.asBytes + 24, 4); + ar = (uint32_t)bytes_to_num(resp.d.asBytes + 28, 4); + break; + } + } + PrintAndLogEx(NORMAL, "\n"); + + if (par_list == 0 && c.arg[0] == true) { + PrintAndLogEx(SUCCESS, "Parity is all zero. Most likely this card sends NACK on every authentication."); + } + c.arg[0] = false; + + keycount = nonce2key(uid, nt, nr, ar, par_list, ks_list, &keylist); + + if (keycount == 0) { + PrintAndLogEx(FAILED, "key not found (lfsr_common_prefix list is null). Nt=%08x", nt); + PrintAndLogEx(FAILED, "this is expected to happen in 25%% of all cases. Trying again with a different reader nonce..."); + continue; + } + + // only parity zero attack + if (par_list == 0 ) { + qsort(keylist, keycount, sizeof(*keylist), compare_uint64); + keycount = intersection(last_keylist, keylist); + if (keycount == 0) { + free(last_keylist); + last_keylist = keylist; + PrintAndLogEx(FAILED, "no candidates found, trying again"); + continue; + } + } + + PrintAndLogEx(SUCCESS, "found %u candidate key%s\n", keycount, (keycount > 1) ? "s." : "."); + + *key = -1; + uint8_t keyBlock[USB_CMD_DATA_SIZE]; + int max_keys = USB_CMD_DATA_SIZE / 6; + for (int i = 0; i < keycount; i += max_keys) { + + int size = keycount - i > max_keys ? max_keys : keycount - i; + for (int j = 0; j < size; j++) { + if (par_list == 0) { + num_to_bytes(last_keylist[i*max_keys + j], 6, keyBlock+(j*6)); + } else { + num_to_bytes(keylist[i*max_keys + j], 6, keyBlock+(j*6)); + } + } + + if (!mfCheckKeys(blockno, key_type - 0x60, false, size, keyBlock, key)) { + break; + } + } + + if (*key != -1) { + break; + } else { + PrintAndLogEx(FAILED, "all candidate keys failed. Restarting darkside attack"); + free(last_keylist); + last_keylist = keylist; + c.arg[0] = true; + } + } + free(last_keylist); + free(keylist); + return 0; +} +int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){ + *key = -1; + UsbCommand c = {CMD_MIFARE_CHKKEYS, { (blockNo | (keyType << 8)), clear_trace, keycnt}}; + memcpy(c.d.asBytes, keyBlock, 6 * keycnt); + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) return 1; + if ((resp.arg[0] & 0xff) != 0x01) return 2; + *key = bytes_to_num(resp.d.asBytes, 6); + return 0; +} + +// Sends chunks of keys to device. +// 0 == ok all keys found +// 1 == +// 2 == Time-out, aborting +int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, uint8_t strategy, + uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory) { + + uint64_t t2 = msclock(); + uint32_t timeout = 0; + + // send keychunk + UsbCommand c = {CMD_MIFARE_CHKKEYS_FAST, { (sectorsCnt | (firstChunk << 8) | (lastChunk << 12) ), ((use_flashmemory << 8) | strategy), size}}; + memcpy(c.d.asBytes, keyBlock, 6 * size); + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + + while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + timeout++; + printf("."); fflush(stdout); + // max timeout for one chunk of 85keys, 60*3sec = 180seconds + // s70 with 40*2 keys to check, 80*85 = 6800 auth. + // takes about 97s, still some margin before abort + if (timeout > 180) { + PrintAndLogEx(WARNING, "\nno response from Proxmark. Aborting..."); + return 2; + } + } + t2 = msclock() - t2; + + // time to convert the returned data. + uint8_t curr_keys = resp.arg[0]; + + PrintAndLogEx(SUCCESS, "\nChunk: %.1fs | found %u/%u keys (%u)", (float)(t2/1000.0), curr_keys, (sectorsCnt<<1), size); + + // all keys? + if ( curr_keys == sectorsCnt*2 || lastChunk ) { + + // success array. each byte is status of key + uint8_t arr[80]; + uint64_t foo = 0; + uint16_t bar = 0; + foo = bytes_to_num(resp.d.asBytes+480, 8); + bar = (resp.d.asBytes[489] << 8 | resp.d.asBytes[488]); + + for (uint8_t i = 0; i < 64; i++) + arr[i] = (foo >> i) & 0x1; + + for (uint8_t i = 0; i < 16; i++) + arr[i+64] = (bar >> i) & 0x1; + + // initialize storage for found keys + icesector_t *tmp = calloc(sectorsCnt, sizeof(icesector_t)); + if (tmp == NULL) + return 1; + memcpy(tmp, resp.d.asBytes, sectorsCnt * sizeof(icesector_t) ); + + for ( int i = 0; i < sectorsCnt; i++) { + // key A + if ( !e_sector[i].foundKey[0] ) { + e_sector[i].Key[0] = bytes_to_num( tmp[i].keyA, 6); + e_sector[i].foundKey[0] = arr[ (i*2) ]; + } + // key B + if ( !e_sector[i].foundKey[1] ) { + e_sector[i].Key[1] = bytes_to_num( tmp[i].keyB, 6); + e_sector[i].foundKey[1] = arr[ (i*2) + 1 ]; + } + } + free(tmp); + + if ( curr_keys == sectorsCnt*2 ) + return 0; + if ( lastChunk ) + return 1; + } + return 1; +} + +// PM3 imp of J-Run mf_key_brute (part 2) +// ref: https://github.com/J-Run/mf_key_brute +int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey){ + + #define KEYS_IN_BLOCK 85 + #define KEYBLOCK_SIZE 510 + #define CANDIDATE_SIZE 0xFFFF * 6 + uint8_t found = false; + uint64_t key64 = 0; + uint8_t candidates[CANDIDATE_SIZE] = {0x00}; + uint8_t keyBlock[KEYBLOCK_SIZE] = {0x00}; + + memset(candidates, 0, sizeof(candidates)); + memset(keyBlock, 0, sizeof(keyBlock)); + + // Generate all possible keys for the first two unknown bytes. + for (uint16_t i = 0; i < 0xFFFF; ++i) { + uint32_t j = i * 6; + candidates[0 + j] = i >> 8; + candidates[1 + j] = i; + candidates[2 + j] = key[2]; + candidates[3 + j] = key[3]; + candidates[4 + j] = key[4]; + candidates[5 + j] = key[5]; + } + uint32_t counter, i; + for ( i = 0, counter = 1; i < CANDIDATE_SIZE; i += KEYBLOCK_SIZE, ++counter){ + + key64 = 0; + + // copy candidatekeys to test key block + memcpy(keyBlock, candidates + i, KEYBLOCK_SIZE); + + // check a block of generated candidate keys. + if (!mfCheckKeys(blockNo, keyType, true, KEYS_IN_BLOCK, keyBlock, &key64)) { + *resultkey = key64; + found = true; + break; + } + + // progress + if ( counter % 20 == 0 ) + PrintAndLogEx(SUCCESS, "tried : %s.. \t %u keys", sprint_hex(candidates + i, 6), counter * KEYS_IN_BLOCK ); + } + return found; +} + +// Compare 16 Bits out of cryptostate +int Compare16Bits(const void * a, const void * b) { + if ((*(uint64_t*)b & 0x00ff000000ff0000) == (*(uint64_t*)a & 0x00ff000000ff0000)) return 0; + if ((*(uint64_t*)b & 0x00ff000000ff0000) > (*(uint64_t*)a & 0x00ff000000ff0000)) return 1; + return -1; +} + +// wrapper function for multi-threaded lfsr_recovery32 +void +#ifdef __has_attribute +#if __has_attribute(force_align_arg_pointer) +__attribute__((force_align_arg_pointer)) +#endif +#endif +*nested_worker_thread(void *arg) { + struct Crypto1State *p1; + StateList_t *statelist = arg; + statelist->head.slhead = lfsr_recovery32(statelist->ks1, statelist->nt ^ statelist->uid); + + for (p1 = statelist->head.slhead; *(uint64_t *)p1 != 0; p1++) {}; + + statelist->len = p1 - statelist->head.slhead; + statelist->tail.sltail = --p1; + qsort(statelist->head.slhead, statelist->len, sizeof(uint64_t), Compare16Bits); + + return statelist->head.slhead; +} + +int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * resultKey, bool calibrate) { + uint16_t i; + uint32_t uid; + UsbCommand resp; + StateList_t statelists[2]; + struct Crypto1State *p1, *p2, *p3, *p4; + + UsbCommand c = {CMD_MIFARE_NESTED, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, calibrate}}; + memcpy(c.d.asBytes, key, 6); + clearCommandBuffer(); + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return -1; + + // error during nested + if (resp.arg[0]) return resp.arg[0]; + + memcpy(&uid, resp.d.asBytes, 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 + pthread_t thread_id[2]; + + // create and run worker threads + for (i = 0; i < 2; i++) + pthread_create(thread_id + i, NULL, nested_worker_thread, &statelists[i]); + + // wait for threads to terminate: + for (i = 0; i < 2; i++) + pthread_join(thread_id[i], (void*)&statelists[i].head.slhead); + + // the first 16 Bits of the cryptostate already contain part of our key. + // Create the intersection of the two lists based on these 16 Bits and + // roll back the cryptostate + p1 = p3 = statelists[0].head.slhead; + p2 = p4 = statelists[1].head.slhead; + + while (p1 <= statelists[0].tail.sltail && p2 <= statelists[1].tail.sltail) { + if (Compare16Bits(p1, p2) == 0) { + + struct Crypto1State savestate, *savep = &savestate; + savestate = *p1; + while(Compare16Bits(p1, savep) == 0 && p1 <= statelists[0].tail.sltail) { + *p3 = *p1; + lfsr_rollback_word(p3, statelists[0].nt ^ statelists[0].uid, 0); + p3++; + p1++; + } + savestate = *p2; + while(Compare16Bits(p2, savep) == 0 && p2 <= statelists[1].tail.sltail) { + *p4 = *p2; + lfsr_rollback_word(p4, statelists[1].nt ^ statelists[1].uid, 0); + p4++; + p2++; + } + } + else { + while (Compare16Bits(p1, p2) == -1) p1++; + while (Compare16Bits(p1, p2) == 1) p2++; + } + } + + *(uint64_t*)p3 = -1; + *(uint64_t*)p4 = -1; + statelists[0].len = p3 - statelists[0].head.slhead; + statelists[1].len = p4 - statelists[1].head.slhead; + statelists[0].tail.sltail = --p3; + statelists[1].tail.sltail = --p4; + + // the statelists now contain possible keys. The key we are searching for must be in the + // intersection of both lists + qsort(statelists[0].head.keyhead, statelists[0].len, sizeof(uint64_t), compare_uint64); + qsort(statelists[1].head.keyhead, statelists[1].len, sizeof(uint64_t), compare_uint64); + // Create the intersection + statelists[0].len = intersection(statelists[0].head.keyhead, statelists[1].head.keyhead); + + //statelists[0].tail.keytail = --p7; + uint32_t keycnt = statelists[0].len; + if ( keycnt == 0 ) goto out; + + memset(resultKey, 0, 6); + uint64_t key64 = -1; + + // The list may still contain several key candidates. Test each of them with mfCheckKeys + uint32_t max_keys = keycnt > (USB_CMD_DATA_SIZE/6) ? (USB_CMD_DATA_SIZE/6) : keycnt; + uint8_t keyBlock[USB_CMD_DATA_SIZE] = {0x00}; + + for (int i = 0; i < keycnt; i += max_keys) { + + int size = keycnt - i > max_keys ? max_keys : keycnt - i; + + for (int j = 0; j < size; j++) { + crypto1_get_lfsr(statelists[0].head.slhead + i, &key64); + num_to_bytes(key64, 6, keyBlock + i * 6); + } + + if (!mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, size, keyBlock, &key64)) { + free(statelists[0].head.slhead); + free(statelists[1].head.slhead); + num_to_bytes(key64, 6, resultKey); + + PrintAndLogEx(SUCCESS, "target block:%3u key type: %c -- found valid key [%012" PRIx64 "]", + (uint16_t)resp.arg[2] & 0xff, + (resp.arg[2] >> 8) ? 'B' : 'A', + key64 + ); + return -5; + } + } + +out: + PrintAndLogEx(SUCCESS, "target block:%3u key type: %c", + (uint16_t)resp.arg[2] & 0xff, + (resp.arg[2] >> 8) ? 'B' : 'A' + ); + + free(statelists[0].head.slhead); + free(statelists[1].head.slhead); + return -4; +} + +// MIFARE +int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data) { + + UsbCommand c = {CMD_MIFARE_READSC, {sectorNo, keyType, 0}}; + memcpy(c.d.asBytes, key, 6); + clearCommandBuffer(); + SendCommand(&c); + + UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + + if (isOK) { + memcpy(data, resp.d.asBytes, mfNumBlocksPerSector(sectorNo) * 16); + return 0; + } else { + return 1; + } + } else { + PrintAndLogEx(ERR, "Command execute timeout"); + return 2; + } + + return 0; +} + +// EMULATOR +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); + return 0; +} + +int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) { + 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; +} + +// "MAGIC" CARD +int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_t wipecard) { + + uint8_t params = MAGIC_SINGLE; + uint8_t block0[16]; + memset(block0, 0x00, sizeof(block0)); + + int old = mfCGetBlock(0, block0, params); + if (old == 0) + PrintAndLogEx(SUCCESS, "old block 0: %s", sprint_hex(block0, sizeof(block0))); + else + PrintAndLogEx(FAILED, "couldn't get old data. Will write over the last bytes of Block 0."); + + // fill in the new values + // UID + memcpy(block0, uid, 4); + // Mifare UID BCC + block0[4] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3]; + // mifare classic SAK(byte 5) and ATQA(byte 6 and 7, reversed) + if ( sak != NULL ) + block0[5] = sak[0]; + + if ( atqa != NULL ) { + block0[6] = atqa[1]; + block0[7] = atqa[0]; + } + PrintAndLogEx(SUCCESS, "new block 0: %s", sprint_hex(block0,16)); + + if ( wipecard ) params |= MAGIC_WIPE; + if ( oldUID == NULL) params |= MAGIC_UID; + + return mfCSetBlock(0, block0, oldUID, params); +} + +int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params) { + + uint8_t isOK = 0; + UsbCommand c = {CMD_MIFARE_CSETBLOCK, {params, blockNo, 0}}; + memcpy(c.d.asBytes, data, 16); + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + isOK = resp.arg[0] & 0xff; + if (uid != NULL) + memcpy(uid, resp.d.asBytes, 4); + if (!isOK) + return 2; + } else { + PrintAndLogEx(WARNING, "command execute timeout"); + return 1; + } + return 0; +} + +int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) { + uint8_t isOK = 0; + UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, blockNo, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + isOK = resp.arg[0] & 0xff; + if (!isOK) + return 2; + memcpy(data, resp.d.asBytes, 16); + } else { + PrintAndLogEx(WARNING, "command execute timeout"); + return 1; + } + return 0; +} + +// SNIFFER +// [iceman] so many global variables.... + +// constants +static uint8_t trailerAccessBytes[4] = {0x08, 0x77, 0x8F, 0x00}; + +// variables +char logHexFileName[FILE_PATH_SIZE] = {0x00}; +static uint8_t traceCard[4096] = {0x00}; +static char traceFileName[FILE_PATH_SIZE] = {0x00}; +static int traceState = TRACE_IDLE; +static uint8_t traceCurBlock = 0; +static uint8_t traceCurKey = 0; + +struct Crypto1State *traceCrypto1 = NULL; +struct Crypto1State *revstate = NULL; +uint64_t key = 0; +uint32_t ks2 = 0; +uint32_t ks3 = 0; + +uint32_t cuid = 0; // uid part used for crypto1. +uint32_t nt = 0; // tag challenge +uint32_t nr_enc = 0; // encrypted reader challenge +uint32_t ar_enc = 0; // encrypted reader response +uint32_t at_enc = 0; // encrypted tag response + +int isTraceCardEmpty(void) { + return ((traceCard[0] == 0) && (traceCard[1] == 0) && (traceCard[2] == 0) && (traceCard[3] == 0)); +} + +int isBlockEmpty(int blockN) { + for (int i = 0; i < 16; i++) + if (traceCard[blockN * 16 + i] != 0) return 0; + + return 1; +} + +int isBlockTrailer(int blockN) { + return ((blockN & 0x03) == 0x03); +} + +int loadTraceCard(uint8_t *tuid, uint8_t uidlen) { + FILE * f; + char buf[64] = {0x00}; + uint8_t buf8[64] = {0x00}; + int i, blockNum; + uint32_t tmp; + + if (!isTraceCardEmpty()) + saveTraceCard(); + + memset(traceCard, 0x00, 4096); + memcpy(traceCard, tuid, uidlen); + + FillFileNameByUID(traceFileName, tuid, ".eml", uidlen); + + f = fopen(traceFileName, "r"); + if (!f) return 1; + + blockNum = 0; + + while (!feof(f)){ + + memset(buf, 0, sizeof(buf)); + if (fgets(buf, sizeof(buf), f) == NULL) { + PrintAndLogEx(FAILED, "No trace file found or reading error."); + if (f) { + fclose(f); + } + return 2; + } + + if (strlen(buf) < 32){ + if (feof(f)) break; + PrintAndLogEx(FAILED, "File content error. Block data must include 32 HEX symbols"); + if (f) { + fclose(f); + } + return 2; + } + for (i = 0; i < 32; i += 2) { + sscanf(&buf[i], "%02X", &tmp); + buf8[i / 2] = tmp & 0xFF; + } + + memcpy(traceCard + blockNum * 16, buf8, 16); + + blockNum++; + } + if (f) { + fclose(f); + } + return 0; +} + +int saveTraceCard(void) { + + if ((!strlen(traceFileName)) || (isTraceCardEmpty())) return 0; + + FILE * f; + f = fopen(traceFileName, "w+"); + if ( !f ) return 1; + + // given 4096 tracecard size, these loop will only match a 1024, 1kb card memory + // 4086/16 == 256blocks. + for (uint16_t i = 0; i < 256; i++) { // blocks + for (uint8_t j = 0; j < 16; j++) // bytes + fprintf(f, "%02X", *(traceCard + i * 16 + j)); + + // no extra line in the end + if ( i < 255 ) + fprintf(f, "\n"); + } + fflush(f); + fclose(f); + return 0; +} +// +int mfTraceInit(uint8_t *tuid, uint8_t uidlen, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile) { + + if (traceCrypto1) + crypto1_destroy(traceCrypto1); + + traceCrypto1 = NULL; + + if (wantSaveToEmlFile) + loadTraceCard(tuid, uidlen); + + traceCard[4] = traceCard[0] ^ traceCard[1] ^ traceCard[2] ^ traceCard[3]; + traceCard[5] = sak; + memcpy(&traceCard[6], atqa, 2); + traceCurBlock = 0; + cuid = bytes_to_num(tuid + (uidlen-4), 4); + traceState = TRACE_IDLE; + return 0; +} + +void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted){ + uint8_t bt = 0; + int i; + + if (len != 1) { + for (i = 0; i < len; i++) + data[i] = crypto1_byte(pcs, 0x00, isEncrypted) ^ data[i]; + } else { + bt = 0; + bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 0)) << 0; + bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 1)) << 1; + bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 2)) << 2; + bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 3)) << 3; + data[0] = bt; + } +} + +int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { + + if (traceState == TRACE_ERROR) + return 1; + + if (len > 255) { + traceState = TRACE_ERROR; + return 1; + } + + uint8_t data[255]; + memset(data, 0x00, sizeof(data)); + + memcpy(data, data_src, len); + + if ((traceCrypto1) && ((traceState == TRACE_IDLE) || (traceState > TRACE_AUTH_OK))) { + mf_crypto1_decrypt(traceCrypto1, data, len, 0); + PrintAndLogEx(NORMAL, "DEC| %s", sprint_hex(data, len)); + AddLogHex(logHexFileName, "DEC| ", data, len); + } + + switch (traceState) { + case TRACE_IDLE: + // check packet crc16! + if ((len >= 4) && (!check_crc(CRC_14443_A, data, len))) { + PrintAndLogEx(NORMAL, "DEC| CRC ERROR!!!"); + AddLogLine(logHexFileName, "DEC| ", "CRC ERROR!!!"); + traceState = TRACE_ERROR; // do not decrypt the next commands + return 1; + } + + // AUTHENTICATION + if ((len == 4) && ((data[0] == MIFARE_AUTH_KEYA) || (data[0] == MIFARE_AUTH_KEYB))) { + traceState = TRACE_AUTH1; + traceCurBlock = data[1]; + traceCurKey = data[0] == 60 ? 1:0; + return 0; + } + + // READ + if ((len == 4) && ((data[0] == ISO14443A_CMD_READBLOCK))) { + traceState = TRACE_READ_DATA; + traceCurBlock = data[1]; + return 0; + } + + // WRITE + if ((len == 4) && ((data[0] == ISO14443A_CMD_WRITEBLOCK))) { + traceState = TRACE_WRITE_OK; + traceCurBlock = data[1]; + return 0; + } + + // HALT + if ((len == 4) && ((data[0] == ISO14443A_CMD_HALT) && (data[1] == 0x00))) { + traceState = TRACE_ERROR; // do not decrypt the next commands + return 0; + } + return 0; + + case TRACE_READ_DATA: + if (len == 18) { + traceState = TRACE_IDLE; + + if (isBlockTrailer(traceCurBlock)) { + memcpy(traceCard + traceCurBlock * 16 + 6, data + 6, 4); + } else { + memcpy(traceCard + traceCurBlock * 16, data, 16); + } + if (wantSaveToEmlFile) saveTraceCard(); + return 0; + } else { + traceState = TRACE_ERROR; + return 1; + } + break; + case TRACE_WRITE_OK: + if ((len == 1) && (data[0] == 0x0a)) { + traceState = TRACE_WRITE_DATA; + return 0; + } else { + traceState = TRACE_ERROR; + return 1; + } + break; + case TRACE_WRITE_DATA: + if (len == 18) { + traceState = TRACE_IDLE; + memcpy(traceCard + traceCurBlock * 16, data, 16); + if (wantSaveToEmlFile) saveTraceCard(); + return 0; + } else { + traceState = TRACE_ERROR; + return 1; + } + break; + case TRACE_AUTH1: + if (len == 4) { + traceState = TRACE_AUTH2; + nt = bytes_to_num(data, 4); + return 0; + } else { + traceState = TRACE_ERROR; + return 1; + } + break; + case TRACE_AUTH2: + if (len == 8) { + traceState = TRACE_AUTH_OK; + nr_enc = bytes_to_num(data, 4); + ar_enc = bytes_to_num(data + 4, 4); + return 0; + } else { + traceState = TRACE_ERROR; + return 1; + } + break; + case TRACE_AUTH_OK: + if (len == 4) { + traceState = TRACE_IDLE; + at_enc = bytes_to_num(data, 4); + + // mfkey64 recover key. + ks2 = ar_enc ^ prng_successor(nt, 64); + ks3 = at_enc ^ prng_successor(nt, 96); + revstate = lfsr_recovery64(ks2, ks3); + lfsr_rollback_word(revstate, 0, 0); + lfsr_rollback_word(revstate, 0, 0); + lfsr_rollback_word(revstate, nr_enc, 1); + lfsr_rollback_word(revstate, cuid ^ nt, 0); + crypto1_get_lfsr(revstate, &key); + PrintAndLogEx(SUCCESS, "found Key: [%012" PRIx64 "]", key); + + //if ( tryMfk64(cuid, nt, nr_enc, ar_enc, at_enc, &key) ) + AddLogUint64(logHexFileName, "Found Key: ", key); + + int blockShift = ((traceCurBlock & 0xFC) + 3) * 16; + if (isBlockEmpty((traceCurBlock & 0xFC) + 3)) + memcpy(traceCard + blockShift + 6, trailerAccessBytes, 4); + + // keytype A/B + if (traceCurKey) + num_to_bytes(key, 6, traceCard + blockShift + 10); + else + num_to_bytes(key, 6, traceCard + blockShift); + + if (wantSaveToEmlFile) + saveTraceCard(); + + if (traceCrypto1) + crypto1_destroy(traceCrypto1); + + // set cryptosystem state + traceCrypto1 = lfsr_recovery64(ks2, ks3); + + } else { + PrintAndLogEx(NORMAL, "[!] nested key recovery not implemented!\n"); + at_enc = bytes_to_num(data, 4); + crypto1_destroy(traceCrypto1); + traceState = TRACE_ERROR; + } + break; + default: + traceState = TRACE_ERROR; + return 1; + } + return 0; +} + +int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len){ + PrintAndLogEx(SUCCESS, "\nencrypted data: [%s]", sprint_hex(data, len) ); + struct Crypto1State *s; + ks2 = ar_enc ^ prng_successor(nt, 64); + ks3 = at_enc ^ prng_successor(nt, 96); + s = lfsr_recovery64(ks2, ks3); + mf_crypto1_decrypt(s, data, len, false); + PrintAndLogEx(SUCCESS, "decrypted data: [%s]", sprint_hex(data, len) ); + crypto1_destroy(s); + return 0; +} + +/* Detect Tag Prng, +* function performs a partial AUTH, where it tries to authenticate against block0, key A, but only collects tag nonce. +* the tag nonce is check to see if it has a predictable PRNG. +* @returns +* TRUE if tag uses WEAK prng (ie Now the NACK bug also needs to be present for Darkside attack) +* FALSE is tag uses HARDEND prng (ie hardnested attack possible, with known key) +*/ +int detect_classic_prng(void){ + + UsbCommand resp, respA; + uint8_t cmd[] = {MIFARE_AUTH_KEYA, 0x00}; + uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_RATS; + + UsbCommand c = {CMD_READER_ISO_14443a, {flags, sizeof(cmd), 0}}; + memcpy(c.d.asBytes, cmd, sizeof(cmd)); + + clearCommandBuffer(); + SendCommand(&c); + + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + PrintAndLogEx(WARNING, "PRNG UID: Reply timeout."); + return -1; + } + + // if select tag failed. + if ( resp.arg[0] == 0 ) { + PrintAndLogEx(WARNING, "error: selecting tag failed, can't detect prng\n"); + return -2; + } + if (!WaitForResponseTimeout(CMD_ACK, &respA, 2500)) { + PrintAndLogEx(WARNING, "PRNG data: Reply timeout."); + return -3; + } + + // check respA + if (respA.arg[0] != 4) { + PrintAndLogEx(WARNING, "PRNG data error: Wrong length: %d", respA.arg[0]); + return -4; + } + + uint32_t nonce = bytes_to_num(respA.d.asBytes, respA.arg[0]); + return validate_prng_nonce(nonce); +} +/* Detect Mifare Classic NACK bug + +returns: +0 = error during test / aborted +1 = has nack bug +2 = has not nack bug +3 = always leak nacks (clones) +*/ +int detect_classic_nackbug(bool verbose){ + + UsbCommand c = {CMD_MIFARE_NACK_DETECT, {0, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + + if ( verbose ) + PrintAndLogEx(SUCCESS, "press pm3-button on the proxmark3 device to abort both proxmark3 and client.\n"); + + // for nice animation + bool term = !isatty(STDIN_FILENO); +#if defined(__linux__) || (__APPLE__) + char star[] = {'-', '\\', '|', '/'}; + uint8_t staridx = 0; +#endif + + while (true) { + + if (term) { + printf("."); + } else { + printf( + #if defined(__linux__) || (__APPLE__) + "\e[32m\e[s%c\e[u\e[0m", star[ (staridx++ % 4) ] + #else + "." + #endif + ); + } + fflush(stdout); + if (ukbhit()) { + int gc = getchar(); (void)gc; + return -1; + break; + } + + if (WaitForResponseTimeout(CMD_ACK, &resp, 500)) { + int32_t ok = resp.arg[0]; + uint32_t nacks = resp.arg[1]; + uint32_t auths = resp.arg[2]; + PrintAndLogEx(NORMAL, ""); + + if ( verbose ) { + PrintAndLogEx(SUCCESS, "num of auth requests : %u", auths); + PrintAndLogEx(SUCCESS, "num of received NACK : %u", nacks); + } + switch( ok ) { + case 99 : PrintAndLogEx(WARNING, "button pressed. Aborted."); return 0; + case 96 : + case 98 : { + if (verbose) + PrintAndLogEx(FAILED, "card random number generator is not predictable."); + PrintAndLogEx(WARNING, "detection failed"); + return 2; + } + case 97 : { + if (verbose) { + PrintAndLogEx(FAILED, "card random number generator seems to be based on the well-known generating polynomial"); + PrintAndLogEx(NORMAL, "[- ]with 16 effective bits only, but shows unexpected behavior, try again."); + return 0; + } + } + case 2 : PrintAndLogEx(SUCCESS, "always leak NACK detected"); return 3; + case 1 : PrintAndLogEx(SUCCESS, "NACK bug detected"); return 1; + case 0 : PrintAndLogEx(SUCCESS, "No NACK bug detected"); return 2; + default : PrintAndLogEx(WARNING, "errorcode from device [%i]", ok); return 0; + } + break; + } + } + return 0; +} +/* try to see if card responses to "chinese magic backdoor" commands. */ +void detect_classic_magic(void) { + + uint8_t isGeneration = 0; + UsbCommand resp; + UsbCommand c = {CMD_MIFARE_CIDENT, {0, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) + isGeneration = resp.arg[0] & 0xff; + + switch( isGeneration ){ + case 1: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 1a): YES"); break; + case 2: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 1b): YES"); break; + //case 4: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 2): YES"); break; + default: PrintAndLogEx(INFO, "Answers to magic commands: NO"); break; + } } \ No newline at end of file diff --git a/client/mifarehost.h b/client/mifare/mifarehost.h similarity index 97% rename from client/mifarehost.h rename to client/mifare/mifarehost.h index 69458fdfa..c0633bd35 100644 --- a/client/mifarehost.h +++ b/client/mifare/mifarehost.h @@ -1,103 +1,103 @@ -// Merlok, 2011 -// people from mifare@nethemba.com, 2010 -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// High frequency ISO14443A commands -//----------------------------------------------------------------------------- -#ifndef __MIFARE_HOST_H -#define __MIFARE_HOST_H - -#include -#include -#include -#include -#include - -#include "proxmark3.h" // time_t -#include "common.h" -#include "util.h" // FILE_PATH_SIZE -#include "ui.h" // PrintAndLog... -#include "crapto1/crapto1.h" -#include "crc16.h" -#include "protocols.h" -#include "mifare.h" -#include "mfkey.h" -#include "util_posix.h" // msclock - -#define MIFARE_SECTOR_RETRY 10 - -// mifare tracer flags -#define TRACE_IDLE 0x00 -#define TRACE_AUTH1 0x01 -#define TRACE_AUTH2 0x02 -#define TRACE_AUTH_OK 0x03 -#define TRACE_READ_DATA 0x04 -#define TRACE_WRITE_OK 0x05 -#define TRACE_WRITE_DATA 0x06 -#define TRACE_ERROR 0xFF - -typedef struct { - union { - struct Crypto1State *slhead; - uint64_t *keyhead; - } head; - union { - struct Crypto1State *sltail; - uint64_t *keytail; - } tail; - uint32_t len; - uint32_t uid; - uint32_t blockNo; - uint32_t keyType; - uint32_t nt; - uint32_t ks1; -} StateList_t; - -typedef struct { - uint64_t Key[2]; - uint8_t foundKey[2]; -} sector_t; - -typedef struct { - uint8_t keyA[6]; - uint8_t keyB[6]; - //uint8_t foundKey[2]; -} icesector_t; - -extern char logHexFileName[FILE_PATH_SIZE]; - -extern int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key); -extern int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys, bool calibrate); -extern int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key); -extern int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, - uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory); -extern int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey); - -extern int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data); - -extern int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount); -extern int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount); -extern int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth); - -extern int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_t wipecard); -extern int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params); -extern int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params); - -extern int mfTraceInit(uint8_t *tuid, uint8_t uidlen, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile); -extern int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile); - -extern int isTraceCardEmpty(void); -extern int isBlockEmpty(int blockN); -extern int isBlockTrailer(int blockN); -extern int loadTraceCard(uint8_t *tuid, uint8_t uidlen); -extern int saveTraceCard(void); -extern int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len); - -extern int detect_classic_prng(void); -extern int detect_classic_nackbug(bool verbose); -extern void detect_classic_magic(void); -extern void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted); +// Merlok, 2011 +// people from mifare@nethemba.com, 2010 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency ISO14443A commands +//----------------------------------------------------------------------------- +#ifndef __MIFARE_HOST_H +#define __MIFARE_HOST_H + +#include +#include +#include +#include +#include + +#include "proxmark3.h" // time_t +#include "common.h" +#include "util.h" // FILE_PATH_SIZE +#include "ui.h" // PrintAndLog... +#include "crapto1/crapto1.h" +#include "crc16.h" +#include "protocols.h" +#include "mifare.h" +#include "mfkey.h" +#include "util_posix.h" // msclock + +#define MIFARE_SECTOR_RETRY 10 + +// mifare tracer flags +#define TRACE_IDLE 0x00 +#define TRACE_AUTH1 0x01 +#define TRACE_AUTH2 0x02 +#define TRACE_AUTH_OK 0x03 +#define TRACE_READ_DATA 0x04 +#define TRACE_WRITE_OK 0x05 +#define TRACE_WRITE_DATA 0x06 +#define TRACE_ERROR 0xFF + +typedef struct { + union { + struct Crypto1State *slhead; + uint64_t *keyhead; + } head; + union { + struct Crypto1State *sltail; + uint64_t *keytail; + } tail; + uint32_t len; + uint32_t uid; + uint32_t blockNo; + uint32_t keyType; + uint32_t nt; + uint32_t ks1; +} StateList_t; + +typedef struct { + uint64_t Key[2]; + uint8_t foundKey[2]; +} sector_t; + +typedef struct { + uint8_t keyA[6]; + uint8_t keyB[6]; + //uint8_t foundKey[2]; +} icesector_t; + +extern char logHexFileName[FILE_PATH_SIZE]; + +extern int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key); +extern int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t * ResultKeys, bool calibrate); +extern int mfCheckKeys (uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key); +extern int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, + uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory); +extern int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultkey); + +extern int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data); + +extern int mfEmlGetMem(uint8_t *data, int blockNum, int blocksCount); +extern int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount); +extern int mfEmlSetMem_xt(uint8_t *data, int blockNum, int blocksCount, int blockBtWidth); + +extern int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_t wipecard); +extern int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params); +extern int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params); + +extern int mfTraceInit(uint8_t *tuid, uint8_t uidlen, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile); +extern int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile); + +extern int isTraceCardEmpty(void); +extern int isBlockEmpty(int blockN); +extern int isBlockTrailer(int blockN); +extern int loadTraceCard(uint8_t *tuid, uint8_t uidlen); +extern int saveTraceCard(void); +extern int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, int len); + +extern int detect_classic_prng(void); +extern int detect_classic_nackbug(bool verbose); +extern void detect_classic_magic(void); +extern void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted); #endif \ No newline at end of file diff --git a/client/obj/mifare/.dummy b/client/obj/mifare/.dummy new file mode 100644 index 000000000..e69de29bb diff --git a/client/scripting.h b/client/scripting.h index 4d39a6c6f..81b95cbe0 100644 --- a/client/scripting.h +++ b/client/scripting.h @@ -19,7 +19,7 @@ #include "cmdmain.h" #include "comms.h" #include "util.h" -#include "mifarehost.h" +#include "mifare/mifarehost.h" #include "crc.h" #include "crc16.h" #include "crc64.h" diff --git a/include/mifare.h b/include/mifare.h index 14c0e7e27..90077f60d 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -13,6 +13,12 @@ #include "common.h" +#define MF_KEY_A 0 +#define MF_KEY_B 1 + +#define MF_MAD1_SECTOR 0x00 +#define MF_MAD2_SECTOR 0x10 + //----------------------------------------------------------------------------- // ISO 14443A //----------------------------------------------------------------------------- From db7580203b648be8cb472dc86718dba59318f38f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 21 Feb 2019 19:34:12 +0200 Subject: [PATCH 0529/1938] create mad.c/h --- client/Makefile | 1 + client/cmdhfmf.c | 5 +++-- client/mifare/mad.c | 31 +++++++++++++++++++++++++++++++ client/mifare/mad.h | 26 ++++++++++++++++++++++++++ 4 files changed, 61 insertions(+), 2 deletions(-) create mode 100644 client/mifare/mad.c create mode 100644 client/mifare/mad.h diff --git a/client/Makefile b/client/Makefile index 9f8055f8e..ebbce92dd 100644 --- a/client/Makefile +++ b/client/Makefile @@ -157,6 +157,7 @@ CMDSRCS = crapto1/crapto1.c \ emv/cmdemv.c \ emv/emv_roca.c \ mifare/mifare4.c \ + mifare/mad.c \ cmdanalyse.c \ cmdhf.c \ cmdhflist.c \ diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index a12bc34c2..edc3a662f 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -10,6 +10,7 @@ #include "cmdhfmf.h" #include "mifare/mifare4.h" +#include "mifare/mad.h" #define MIFARE_4K_MAXBLOCK 256 #define MIFARE_2K_MAXBLOCK 128 @@ -3225,7 +3226,7 @@ int CmdHF14AMfMAD(const char *cmd) { for(int i = 0; i < 4; i ++) PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(§or[i * 16], 16)); } - /* + bool haveMAD2 = false; MAD1DecodeAndPrint(sector, verbose, &haveMAD2); @@ -3237,7 +3238,7 @@ int CmdHF14AMfMAD(const char *cmd) { MAD2DecodeAndPrint(sector, verbose); } - */ + return 0; } diff --git a/client/mifare/mad.c b/client/mifare/mad.c new file mode 100644 index 000000000..88fc2c31b --- /dev/null +++ b/client/mifare/mad.c @@ -0,0 +1,31 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2019 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// MIFARE Application Directory (MAD) functions +//----------------------------------------------------------------------------- + +#include "mad.h" +#include "ui.h" + +madAIDDescr madKnownAIDs[] = { + {0x0000, "free"}, + {0x0001, "defect, e.g. access keys are destroyed or unknown"}, + {0x0002, "reserved"}, + {0x0003, "contains additional directory info"}, + {0x0004, "contains card holder information in ASCII format."}, + {0x0005, "not applicable (above memory size)}"} +}; + +int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { + + return 0; +}; + +int MAD2DecodeAndPrint(uint8_t *sector, bool verbose) { + + return 0; +}; diff --git a/client/mifare/mad.h b/client/mifare/mad.h new file mode 100644 index 000000000..dc2b2e3c0 --- /dev/null +++ b/client/mifare/mad.h @@ -0,0 +1,26 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2019 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// MIFARE Application Directory (MAD) functions +//----------------------------------------------------------------------------- + +#ifndef _MAD_H_ +#define _MAD_H_ + +#include +#include + +typedef struct { + uint16_t AID; + const char *Description; +} madAIDDescr; + +int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2); +int MAD2DecodeAndPrint(uint8_t *sector, bool verbose); + + +#endif // _MAD_H_ From b9dc841bf923ef131866c8582e93d31b9839940d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 21 Feb 2019 19:44:07 +0200 Subject: [PATCH 0530/1938] MAD. print GPB --- client/mifare/mad.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/client/mifare/mad.c b/client/mifare/mad.c index 88fc2c31b..03b5b3f77 100644 --- a/client/mifare/mad.c +++ b/client/mifare/mad.c @@ -22,6 +22,37 @@ madAIDDescr madKnownAIDs[] = { int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { + uint8_t GPB = sector[3 * 16 + 9]; + PrintAndLogEx(NORMAL, "GPB: 0x%02x", GPB); + + // DA (MAD available) + if (!(GPB & 0x80)) { + PrintAndLogEx(ERR, "DA=0! MAD not available."); + return 1; + } + + // MA (multi-application card) + if (GPB & 0x40) + PrintAndLogEx(NORMAL, "Multi application card."); + else + PrintAndLogEx(NORMAL, "Single application card."); + + uint8_t MADVer = GPB & 0x03; + + // MAD version + if ((MADVer != 0x01) && (MADVer != 0x02)) { + PrintAndLogEx(ERR, "Wrong MAD version: 0x%02x", MADVer); + return 2; + }; + + if (haveMAD2) + *haveMAD2 = (MADVer == 2); + + + + + + return 0; }; From 01c9325469e0b0a7c75c8652202be17f25fa2b40 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 21 Feb 2019 20:06:53 +0200 Subject: [PATCH 0531/1938] check MAD crc --- client/mifare/mad.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/client/mifare/mad.c b/client/mifare/mad.c index 03b5b3f77..2fbc23e38 100644 --- a/client/mifare/mad.c +++ b/client/mifare/mad.c @@ -10,6 +10,7 @@ #include "mad.h" #include "ui.h" +#include "crc.h" madAIDDescr madKnownAIDs[] = { {0x0000, "free"}, @@ -48,7 +49,11 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { if (haveMAD2) *haveMAD2 = (MADVer == 2); - + uint8_t crc = CRC8Mad(§or[16 + 1], 31); + if (crc != sector[16]) { + PrintAndLogEx(ERR, "Wrong MAD CRC. Calculated crc: 0x%02x, from sector: 0x%02x", crc, sector[16]); + return 3; + }; From 0632918a477a90c3985c76843ce5e5d835866167 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Thu, 21 Feb 2019 20:07:17 +0200 Subject: [PATCH 0532/1938] fix MAD crc calculation (was wrong) --- common/crc.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/common/crc.c b/common/crc.c index b710404cc..4d28d120e 100644 --- a/common/crc.c +++ b/common/crc.c @@ -99,14 +99,15 @@ uint32_t CRC8Maxim(uint8_t *buff, size_t size) { crc_update2(&crc, buff[i], 8); return crc_finish(&crc); } -// width=8 poly=0x1d, reversed poly=0x?? init=0xe3 refin=true refout=true xorout=0x0000 check=0xC6 name="CRC-8/MAD" +// width=8 poly=0x1d, init=0xc7 (0xe3 - WRONG! but it mentioned in MAD datasheet) refin=true refout=true xorout=0x00 name="CRC-8/MAD" // the CRC needs to be reversed before returned. +// init c7, poly 1d, final 0x00. uint32_t CRC8Mad(uint8_t *buff, size_t size) { crc_t crc; - crc_init_ref(&crc, 8, 0x1d, 0xe3, 0, true, true); + crc_init_ref(&crc, 8, 0x1d, 0xc7, 0, false, false); for ( int i = 0; i < size; ++i) crc_update2(&crc, buff[i], 8); - return reflect8(crc_finish(&crc)); + return crc_finish(&crc); } // width=4 poly=0xC, reversed poly=0x7 init=0x5 refin=true refout=true xorout=0x0000 check= name="CRC-4/LEGIC" uint32_t CRC4Legic(uint8_t *cmd, size_t size) { From 421604a3954fe50c05e921387f408bfabab79a4c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 21 Feb 2019 23:20:52 +0100 Subject: [PATCH 0533/1938] fix: sc bruteforce' - wrong assign --- client/cmdsmartcard.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 3860496de..f9b77dad0 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -946,8 +946,8 @@ static int smart_brute_sfi(bool decodeTLV){ return 0; } -static void smart_brute_options(bool decodeTLV){ - +static void smart_brute_options(bool decodeTLV) { + uint8_t* buf = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t)); if ( !buf ) return; @@ -1057,7 +1057,7 @@ int CmdSmartBruteforceSFI(const char *Cmd) { continue; size_t aidlen = strlen(aid); - char* caid = calloc( 8+2+aidlen+1, sizeof(uint8_t)); + caid = calloc( 8+2+aidlen+1, sizeof(uint8_t)); snprintf(caid, 8+2+aidlen+1, SELECT, aidlen >> 1, aid); int hexlen = 0; From 09791638c8eb44f42653ad239f0a4c6de420e97d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 21 Feb 2019 23:21:13 +0100 Subject: [PATCH 0534/1938] fix: 'lf indala' - wrong number of bits --- client/cmdlfindala.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index dd262e0dc..b49455e16 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -377,8 +377,8 @@ int CmdIndalaDemodAlt(const char *Cmd) { int CmdIndalaSim(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_indala_sim(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_indala_sim(); uint8_t bits[224]; size_t size = sizeof(bits); @@ -392,9 +392,9 @@ int CmdIndalaSim(const char *Cmd) { return usage_lf_indala_sim(); // convert to binarray - uint8_t counter = 224; - for (uint8_t i=0; i< len; i++) { - for(uint8_t j=0; j<8; j++) { + uint8_t counter = 223; + for (uint8_t i = 0; i < len; i++) { + for(uint8_t j = 0; j < 8; j++) { bits[counter--] = hexuid[i] & 1; hexuid[i] >>= 1; } From c980ae109aa409fa56dc5f44b94cfcfd3c8f461a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 21 Feb 2019 23:21:39 +0100 Subject: [PATCH 0535/1938] fix: 'lf gprox' - wrong check value --- client/cmdlfguard.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfguard.c b/client/cmdlfguard.c index ea97d6f77..afad96686 100644 --- a/client/cmdlfguard.c +++ b/client/cmdlfguard.c @@ -192,7 +192,7 @@ int CmdGuardDemod(const char *Cmd) { PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII preamble not found"); else if (preambleIndex == -3) PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII size not correct: %d", size); - else if (preambleIndex == -3) + else if (preambleIndex == -5) PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII wrong spacerbits"); else PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII ans: %d", preambleIndex); From b11f767c5530afaf548c9903a649e50fa23cac3f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 21 Feb 2019 23:22:13 +0100 Subject: [PATCH 0536/1938] fix: 'lf em brute' - mem leak --- client/cmdlfem4x.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 762b4fe0b..3260b8d74 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -474,14 +474,14 @@ int CmdEM410xBrute(const char *Cmd) { /* default pause time: 1 second */ uint32_t delay = 1000; - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_lf_em410x_brute(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_lf_em410x_brute(); - cmdp = param_getchar(Cmd, 1); - if (cmdp == 'd' || cmdp == 'D') { + cmdp = tolower(param_getchar(Cmd, 1)); + if (cmdp == 'd') { delay = param_get32ex(Cmd, 2, 1000, 10); param_getdec(Cmd, 4, &clock); - } else if (cmdp == 'c' || cmdp == 'C') { + } else if (cmdp == 'c') { param_getdec(Cmd, 2, &clock); delay = param_get32ex(Cmd, 4, 1000, 10); } @@ -498,7 +498,10 @@ int CmdEM410xBrute(const char *Cmd) { } uidBlock = calloc(stUidBlock, 5); - if (uidBlock == NULL) return 1; + if (uidBlock == NULL) { + fclose(f); + return 1; + } while( fgets(buf, sizeof(buf), f) ) { if (strlen(buf) < 10 || buf[9] == '\n') continue; From 7ea7061ed019782d18b82983e5e83b82c62afa19 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 21 Feb 2019 23:22:39 +0100 Subject: [PATCH 0537/1938] fix: 'hf mf cload' - wrong free --- client/cmdhfmf.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 57cf246da..e69fd6ba3 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2752,10 +2752,9 @@ int CmdHF14AMfCLoad(const char *Cmd) { res = loadFileEML( Cmd, "eml", data, &datalen); } } - if ( res ) { - free(data); + + if ( res ) return 1; - } // PrintAndLogEx(INFO, "DATA | %s", sprint_hex(data+1000, 24) ); From 439f767b4de6e7674a7fc3bcfe2736a4c328567f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 21 Feb 2019 23:35:03 +0100 Subject: [PATCH 0538/1938] fix: mem leak --- uart/uart_posix.c | 1 + 1 file changed, 1 insertion(+) diff --git a/uart/uart_posix.c b/uart/uart_posix.c index b9df932d6..c77457d91 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -102,6 +102,7 @@ serial_port uart_open(const char* pcPortName) { printf("Error: getaddrinfo: %s\n", gai_strerror(s)); freeaddrinfo(addr); free(addrstr); + free(sp); return INVALID_SERIAL_PORT; } From 697af67bf19a425ffe4b5791b070b22edcd959bc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 21 Feb 2019 23:37:18 +0100 Subject: [PATCH 0539/1938] fix: 'hf 14b info' - missing break --- client/cmdhf14b.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index 4077e16e6..92052e02c 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -461,6 +461,7 @@ bool HF14B_Std_Info(bool verbose){ PrintAndLogEx(NORMAL, " CHIPID : %02X", card.chipid); print_atqb_resp(card.atqb, card.cid); isSuccess = true; + break; case 2: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); break; From 954e01c363d8edc52a17e5eb030cb8efbc67584f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 21 Feb 2019 23:38:07 +0100 Subject: [PATCH 0540/1938] fix: bad loop --- client/cmdhf14b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index 92052e02c..11b0aabb3 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -246,7 +246,7 @@ static bool get_14b_UID(iso14b_card_select_t *card) { if (!card) return false; - uint8_t retry = 3; + int8_t retry = 3; UsbCommand resp; UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}}; From 43bd82b7789d93dd94d04cd83dc852d044d0025f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Thu, 21 Feb 2019 23:44:56 +0100 Subject: [PATCH 0541/1938] update --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 44a6fc2d6..90fbd53bb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fix - A lot of bugfixes, like memory leaks (@iceman) - Change 'hf 14a antifuzz' - original implementation (@asfabw), reworked a bit - Fix 'hf mf fchk' (@iceman) - Fix 'usb slow on posix based systems' (@fl0-0) From 140c327cc2fb533ae72d55885cc23f2361a809e2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 22 Feb 2019 09:43:03 +0100 Subject: [PATCH 0542/1938] CHG: 'hf mf list' - readded it. calls trace list mf in the back --- client/cmdhfmf.c | 14 ++++++++++---- client/cmdhfmf.h | 3 ++- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index e69fd6ba3..2412aecee 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -434,7 +434,7 @@ char * GenerateFilename(const char *prefix, const char *suffix){ return fptr; } -int CmdHF14ADarkside(const char *Cmd) { +int CmdHF14AMfDarkside(const char *Cmd) { uint8_t blockno = 0, key_type = MIFARE_AUTH_KEYA; uint64_t key = 0; @@ -3174,7 +3174,7 @@ out: return 0; } -int CmdHF14AMfAuth4(const char *cmd) { +int CmdHF14AMfAuth4(const char *Cmd) { uint8_t keyn[20] = {0}; int keynlen = 0; uint8_t key[16] = {0}; @@ -3191,7 +3191,7 @@ int CmdHF14AMfAuth4(const char *cmd) { arg_str1(NULL, NULL, "", NULL), arg_param_end }; - CLIExecWithReturn(cmd, argtable, true); + CLIExecWithReturn(Cmd, argtable, true); CLIGetHexWithReturn(1, keyn, &keynlen); CLIGetHexWithReturn(2, key, &keylen); @@ -3210,9 +3210,15 @@ int CmdHF14AMfAuth4(const char *cmd) { return MifareAuth4(NULL, keyn, key, true, false, true); } +int CmdHF14AMfList(const char *Cmd) { + CmdTraceList("mf"); + return 0; +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"darkside", CmdHF14ADarkside, 0, "Darkside attack. read parity error messages."}, + {"list", CmdHF14AMfList, 0, "[Deprecated] List ISO 14443-a / Mifare history"}, + {"darkside", CmdHF14AMfDarkside, 0, "Darkside attack. read parity error messages."}, {"nested", CmdHF14AMfNested, 0, "Nested attack. Test nested authentication"}, {"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"}, {"keybrute", CmdHF14AMfKeyBrute, 0, "J_Run's 2nd phase of multiple sector nested authentication key recovery"}, diff --git a/client/cmdhfmf.h b/client/cmdhfmf.h index eeb7a74f6..a87da449f 100644 --- a/client/cmdhfmf.h +++ b/client/cmdhfmf.h @@ -35,6 +35,7 @@ extern int CmdHFMF(const char *Cmd); +extern int CmdHF14AMfList(const char *Cmd); extern int CmdHF14AMfDbg(const char* cmd); extern int CmdHF14AMfRdBl(const char* cmd); extern int CmdHF14AMfURdBl(const char* cmd); @@ -45,7 +46,7 @@ extern int CmdHF14AMfRestore(const char* cmd); extern int CmdHF14AMfWrBl(const char* cmd); extern int CmdHF14AMfUWrBl(const char* cmd); extern int CmdHF14AMfChk(const char* cmd); -extern int CmdHF14ADarkside(const char* cmd); +extern int CmdHF14AMfDarkside(const char* cmd); extern int CmdHF14AMfNested(const char* cmd); extern int CmdHF14AMfNestedHard(const char *Cmd); //extern int CmdHF14AMfSniff(const char* cmd); From 99101e56fd71b19a8a2f0a5fa18c23a9b71bad29 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 22 Feb 2019 09:43:42 +0100 Subject: [PATCH 0543/1938] text --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 90fbd53bb..ce939d980 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Add 'hf mf list' - readded it again (@iceman) - Fix - A lot of bugfixes, like memory leaks (@iceman) - Change 'hf 14a antifuzz' - original implementation (@asfabw), reworked a bit - Fix 'hf mf fchk' (@iceman) From ef9d1fa3786be56c2c46552e9a975d7487abe904 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 22 Feb 2019 15:21:20 +0100 Subject: [PATCH 0544/1938] fix: mem leak, --- uart/uart_posix.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/uart/uart_posix.c b/uart/uart_posix.c index c77457d91..e3d7753a9 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -123,6 +123,7 @@ serial_port uart_open(const char* pcPortName) { printf("Error: Could not connect\n"); freeaddrinfo(addr); free(addrstr); + free(sp); return INVALID_SERIAL_PORT; } @@ -132,13 +133,17 @@ serial_port uart_open(const char* pcPortName) { sp->fd = sfd; int one = 1; - setsockopt(sp->fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)); + int res = setsockopt(sp->fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)); + if ( res != 0) { + free(sp); + return INVALID_SERIAL_PORT; + } return sp; } sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); - if(sp->fd == -1) { + if (sp->fd == -1) { uart_close(sp); return INVALID_SERIAL_PORT; } @@ -160,7 +165,7 @@ serial_port uart_open(const char* pcPortName) { } // Try to retrieve the old (current) terminal info struct - if(tcgetattr(sp->fd,&sp->tiOld) == -1) { + if (tcgetattr(sp->fd,&sp->tiOld) == -1) { uart_close(sp); return INVALID_SERIAL_PORT; } @@ -180,7 +185,7 @@ serial_port uart_open(const char* pcPortName) { sp->tiNew.c_cc[VTIME] = 0; // Try to set the new terminal info struct - if(tcsetattr(sp->fd, TCSANOW, &sp->tiNew) == -1) { + if (tcsetattr(sp->fd, TCSANOW, &sp->tiNew) == -1) { uart_close(sp); return INVALID_SERIAL_PORT; } @@ -359,8 +364,11 @@ bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) { # endif default: return false; }; + struct termios ti; - if (tcgetattr(spu->fd,&ti) == -1) return false; + if (tcgetattr(spu->fd,&ti) == -1) + return false; + // Set port speed (Input and Output) cfsetispeed(&ti, stPortSpeed); cfsetospeed(&ti, stPortSpeed); From 1b64c4cb63470803bb6fa0300fd2b89a58ee485b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 22 Feb 2019 15:23:09 +0100 Subject: [PATCH 0545/1938] fix: overflow was possible since 1000 is type long --- client/util_posix.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/util_posix.c b/client/util_posix.c index 7704e9d4b..a45dc48e9 100644 --- a/client/util_posix.c +++ b/client/util_posix.c @@ -130,7 +130,7 @@ uint64_t msclock(void) { #else struct timespec t; clock_gettime(CLOCK_MONOTONIC, &t); - return (t.tv_sec * 1000 + t.tv_nsec / 1000000); + return ( 1000 * (uint64_t)t.tv_sec + t.tv_nsec / 1000000); #endif } From c5a1b06f25a68d00ef9eb4009e9195f71ac03e83 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 22 Feb 2019 16:58:49 +0200 Subject: [PATCH 0546/1938] mad comment fix --- common/crc.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/common/crc.c b/common/crc.c index 4d28d120e..77bea0b47 100644 --- a/common/crc.c +++ b/common/crc.c @@ -99,9 +99,7 @@ uint32_t CRC8Maxim(uint8_t *buff, size_t size) { crc_update2(&crc, buff[i], 8); return crc_finish(&crc); } -// width=8 poly=0x1d, init=0xc7 (0xe3 - WRONG! but it mentioned in MAD datasheet) refin=true refout=true xorout=0x00 name="CRC-8/MAD" -// the CRC needs to be reversed before returned. -// init c7, poly 1d, final 0x00. +// width=8 poly=0x1d, init=0xc7 (0xe3 - WRONG! but it mentioned in MAD datasheet) refin=false refout=false xorout=0x00 name="CRC-8/MIFARE-MAD" uint32_t CRC8Mad(uint8_t *buff, size_t size) { crc_t crc; crc_init_ref(&crc, 8, 0x1d, 0xc7, 0, false, false); From 8010f2dc5e77b3135037ba2645ca2d52de979265 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 22 Feb 2019 18:05:45 +0200 Subject: [PATCH 0547/1938] MAD1 OK --- client/mifare/mad.c | 131 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 121 insertions(+), 10 deletions(-) diff --git a/client/mifare/mad.c b/client/mifare/mad.c index 2fbc23e38..e7a611384 100644 --- a/client/mifare/mad.c +++ b/client/mifare/mad.c @@ -11,16 +11,119 @@ #include "mad.h" #include "ui.h" #include "crc.h" +#include "util.h" -madAIDDescr madKnownAIDs[] = { +static madAIDDescr madKnownAIDs[] = { {0x0000, "free"}, {0x0001, "defect, e.g. access keys are destroyed or unknown"}, {0x0002, "reserved"}, {0x0003, "contains additional directory info"}, {0x0004, "contains card holder information in ASCII format."}, - {0x0005, "not applicable (above memory size)}"} + {0x0005, "not applicable (above memory size)"}, + + {0x03e1, "NDEF"}, }; +static madAIDDescr madKnownClusterCodes[] = { + {0x00, "cluster: card administration"}, + {0x01, "cluster: miscellaneous applications"}, + {0x02, "cluster: miscellaneous applications"}, + {0x03, "cluster: miscellaneous applications"}, + {0x04, "cluster: miscellaneous applications"}, + {0x05, "cluster: miscellaneous applications"}, + {0x06, "cluster: miscellaneous applications"}, + {0x07, "cluster: miscellaneous applications"}, + {0x08, "cluster: airlines"}, + {0x09, "cluster: ferry traffic"}, + {0x10, "cluster: railway services"}, + {0x11, "cluster: miscellaneous applications"}, + {0x12, "cluster: transport"}, + {0x14, "cluster: security solutions"}, + {0x18, "cluster: city traffic"}, + {0x19, "cluster: Czech Railways"}, + {0x20, "cluster: bus services"}, + {0x21, "cluster: multi modal transit"}, + {0x28, "cluster: taxi"}, + {0x30, "cluster: road toll"}, + {0x31, "cluster: generic transport"}, + {0x38, "cluster: company services"}, + {0x40, "cluster: city card services"}, + {0x47, "cluster: access control & security"}, + {0x48, "cluster: access control & security"}, + {0x49, "cluster: VIGIK"}, + {0x4A, "cluster: Ministry of Defence, Netherlands"}, + {0x4B, "cluster: Bosch Telecom, Germany"}, + {0x4C, "cluster: European Union Institutions"}, + {0x50, "cluster: ski ticketing"}, + {0x51, "cluster: access control & security"}, + {0x52, "cluster: access control & security"}, + {0x53, "cluster: access control & security"}, + {0x54, "cluster: access control & security"}, + {0x55, "cluster: SOAA standard for offline access standard"}, + {0x56, "cluster: access control & security"}, + {0x58, "cluster: academic services"}, + {0x60, "cluster: food"}, + {0x68, "cluster: non-food trade"}, + {0x70, "cluster: hotel"}, + {0x71, "cluster: loyalty"}, + {0x75, "cluster: airport services"}, + {0x78, "cluster: car rental"}, + {0x79, "cluster: Dutch government"}, + {0x80, "cluster: administration services"}, + {0x88, "cluster: electronic purse"}, + {0x90, "cluster: television"}, + {0x91, "cluster: cruise ship"}, + {0x95, "cluster: IOPTA"}, + {0x97, "cluster: metering"}, + {0x98, "cluster: telephone"}, + {0xA0, "cluster: health services"}, + {0xA8, "cluster: warehouse"}, + {0xB0, "cluster: electronic trade"}, + {0xB8, "cluster: banking"}, + {0xC0, "cluster: entertainment & sports"}, + {0xC8, "cluster: car parking"}, + {0xC9, "cluster: fleet management"}, + {0xD0, "cluster: fuel, gasoline"}, + {0xD8, "cluster: info services"}, + {0xE0, "cluster: press"}, + {0xE1, "cluster: NFC Forum"}, + {0xE8, "cluster: computer"}, + {0xF0, "cluster: mail"}, + {0xF8, "cluster: miscellaneous applications"}, +}; + +static const char unknownAID[] = ""; + +static const char *GetAIDDescription(uint16_t AID) { + for(int i = 0; i < ARRAYLEN(madKnownAIDs); i++) + if (madKnownAIDs[i].AID == AID) + return madKnownAIDs[i].Description; + + for(int i = 0; i < ARRAYLEN(madKnownClusterCodes); i++) + if (madKnownClusterCodes[i].AID == AID) + return madKnownClusterCodes[i].Description; + + return unknownAID; +} + +int madCRCCheck(uint8_t *sector, bool verbose, int MADver) { + if (MADver == 1) { + uint8_t crc = CRC8Mad(§or[16 + 1], 31); + if (crc != sector[16]) { + if (verbose) + PrintAndLogEx(ERR, "Wrong MAD%d CRC. Calculated: 0x%02x, from card: 0x%02x", MADver, crc, sector[16]); + return 3; + }; + } else { + } + + return 0; +} + +uint16_t madGetAID(uint8_t *sector, int MADver, int sectorNo) { + return (sector[16 + 2 + (sectorNo - 1) * 2] << 8) + (sector[16 + 2 + (sectorNo - 1) * 2 + 1]); +} + int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { uint8_t GPB = sector[3 * 16 + 9]; @@ -39,6 +142,7 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { PrintAndLogEx(NORMAL, "Single application card."); uint8_t MADVer = GPB & 0x03; + PrintAndLogEx(NORMAL, "MAD version: %d", MADVer); // MAD version if ((MADVer != 0x01) && (MADVer != 0x02)) { @@ -48,20 +152,27 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { if (haveMAD2) *haveMAD2 = (MADVer == 2); + + int res = madCRCCheck(sector, true, 1); + if (res) + return res; - uint8_t crc = CRC8Mad(§or[16 + 1], 31); - if (crc != sector[16]) { - PrintAndLogEx(ERR, "Wrong MAD CRC. Calculated crc: 0x%02x, from sector: 0x%02x", crc, sector[16]); - return 3; + if (verbose) + PrintAndLogEx(NORMAL, "CRC8-MAD OK."); + + for(int i = 1; i < 16; i++) { + uint16_t AID = madGetAID(sector, 1, i); + PrintAndLogEx(NORMAL, "%02d [%04X] %s", i, AID, GetAIDDescription(AID)); }; - - - - + return 0; }; int MAD2DecodeAndPrint(uint8_t *sector, bool verbose) { + int res = madCRCCheck(sector, true, 2); + if (res) + return res; + return 0; }; From 91ed51c673fffb26375e48e02a98bf95c2adad60 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 22 Feb 2019 18:06:37 +0200 Subject: [PATCH 0548/1938] add comment --- client/mifare/mad.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/mifare/mad.c b/client/mifare/mad.c index e7a611384..2b6033588 100644 --- a/client/mifare/mad.c +++ b/client/mifare/mad.c @@ -13,6 +13,7 @@ #include "crc.h" #include "util.h" +// https://www.nxp.com/docs/en/application-note/AN10787.pdf static madAIDDescr madKnownAIDs[] = { {0x0000, "free"}, {0x0001, "defect, e.g. access keys are destroyed or unknown"}, From 5122e1289d584bb7deb9dc46b3febeabe9c1b6a5 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 22 Feb 2019 18:24:22 +0200 Subject: [PATCH 0549/1938] info-byte --- client/mifare/mad.c | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/client/mifare/mad.c b/client/mifare/mad.c index 2b6033588..421b4844f 100644 --- a/client/mifare/mad.c +++ b/client/mifare/mad.c @@ -161,6 +161,17 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { if (verbose) PrintAndLogEx(NORMAL, "CRC8-MAD OK."); + // info byte + uint8_t InfoByte = sector[16 + 1] & 0x3f; + if (InfoByte) { + PrintAndLogEx(NORMAL, "Card publisher sector: 0x%02x", InfoByte); + } else { + if (verbose) + PrintAndLogEx(NORMAL, "Card publisher sector not present."); + } + if (InfoByte == 0x10 || InfoByte >= 0x28) + PrintAndLogEx(WARNING, "Info byte error"); + for(int i = 1; i < 16; i++) { uint16_t AID = madGetAID(sector, 1, i); PrintAndLogEx(NORMAL, "%02d [%04X] %s", i, AID, GetAIDDescription(AID)); From 20be5c5d9f030abae2d122edda8a94947d48ea51 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 22 Feb 2019 19:58:50 +0200 Subject: [PATCH 0550/1938] some of MAD2 code --- client/cmdhfmf.c | 6 +++--- client/mifare/mad.c | 10 +++++++++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index edc3a662f..a7966bee8 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -3230,9 +3230,9 @@ int CmdHF14AMfMAD(const char *cmd) { bool haveMAD2 = false; MAD1DecodeAndPrint(sector, verbose, &haveMAD2); - if (haveMAD2) { - if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector)) { - PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); + if (haveMAD2) { // MF_MAD2_SECTOR + if (mfReadSector(1, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector)) { + PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); return 2; } diff --git a/client/mifare/mad.c b/client/mifare/mad.c index 421b4844f..9f28de394 100644 --- a/client/mifare/mad.c +++ b/client/mifare/mad.c @@ -122,7 +122,10 @@ int madCRCCheck(uint8_t *sector, bool verbose, int MADver) { } uint16_t madGetAID(uint8_t *sector, int MADver, int sectorNo) { - return (sector[16 + 2 + (sectorNo - 1) * 2] << 8) + (sector[16 + 2 + (sectorNo - 1) * 2 + 1]); + if (MADver == 1) + return (sector[16 + 2 + (sectorNo - 1) * 2] << 8) + (sector[16 + 2 + (sectorNo - 1) * 2 + 1]); + else + return (sector[2 + (sectorNo - 1) * 2] << 8) + (sector[2 + (sectorNo - 1) * 2 + 1]); } int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { @@ -185,6 +188,11 @@ int MAD2DecodeAndPrint(uint8_t *sector, bool verbose) { if (res) return res; + for(int i = 1; i < 8 + 8 + 7; i++) { + uint16_t AID = madGetAID(sector, 2, i); + PrintAndLogEx(NORMAL, "%02d [%04X] %s", i + 15, AID, GetAIDDescription(AID)); + }; + return 0; }; From 22510b6f224289e7bd2c9a19218d62282ec9d4d1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 23 Feb 2019 14:15:54 +0100 Subject: [PATCH 0551/1938] CHG: cleanups --- client/cmdhfmfhard.c | 77 ++++++++++---------------- client/hardnested/hardnested_bf_core.c | 6 +- 2 files changed, 32 insertions(+), 51 deletions(-) diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 0c661d410..9d9406c11 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -1048,7 +1048,7 @@ static bool shrink_key_space(float *brute_forces) //iceman 2018 return ((hardnested_stage & CHECK_2ND_BYTES) && reduction_rate >= 0.0 && - ( reduction_rate < brute_force_per_second * (float)sample_period / 1000.0 || *brute_forces < 0x1F000000000)); + ( reduction_rate < brute_force_per_second * (float)sample_period / 1000.0 || *brute_forces < 0x1F00000000)); } @@ -1672,9 +1672,9 @@ static inline bool bitflips_match(uint8_t byte, uint32_t state, odd_even_t odd_e } #endif return false; - } else { - return true; } + + return true; } @@ -1714,11 +1714,13 @@ static bool all_bitflips_match(uint8_t byte, uint32_t state, odd_even_t odd_even #ifdef DEBUG_KEY_ELIMINATION if (known_target_key != -1 && state == test_state[odd_even]) { PrintAndLogEx(NORMAL, "all_bitflips_match() 1st Byte: %s test state (0x%06x): Eliminated. Bytes = %02x, %02x, Common Bits = %d\n", - odd_even==ODD_STATE?"odd":"even", + odd_even == ODD_STATE ? "odd" : "even", test_state[odd_even], - byte, byte2, num_common); + byte, + byte2, + num_common); if (failstr[0] == '\0') { - sprintf(failstr, "Other 1st Byte %s, all_bitflips_match(), no match", odd_even?"odd":"even"); + sprintf(failstr, "Other 1st Byte %s, all_bitflips_match(), no match", odd_even ? "odd" : "even"); } } #endif @@ -1770,12 +1772,10 @@ static void add_matching_states(statelist_t *candidates, uint8_t part_sum_a0, ui uint32_t *bitarray_a8 = part_sum_a8_bitarrays[odd_even][part_sum_a8/2]; uint32_t *bitarray_bitflips = nonces[best_first_bytes[0]].states_bitarray[odd_even]; - // for (uint32_t i = 0; i < (1<<19); i++) { - // candidates_bitarray[i] = bitarray_a0[i] & bitarray_a8[i] & bitarray_bitflips[i]; - // } bitarray_AND4(candidates_bitarray, bitarray_a0, bitarray_a8, bitarray_bitflips); bitarray_to_list(best_first_bytes[0], candidates_bitarray, candidates->states[odd_even], &(candidates->len[odd_even]), odd_even); + if (candidates->len[odd_even] == 0) { free(candidates->states[odd_even]); candidates->states[odd_even] = NULL; @@ -1784,17 +1784,14 @@ static void add_matching_states(statelist_t *candidates, uint8_t part_sum_a0, ui } free_bitarray(candidates_bitarray); - pthread_mutex_lock(&statelist_cache_mutex); sl_cache[part_sum_a0/2][part_sum_a8/2][odd_even].sl = candidates->states[odd_even]; sl_cache[part_sum_a0/2][part_sum_a8/2][odd_even].len = candidates->len[odd_even]; sl_cache[part_sum_a0/2][part_sum_a8/2][odd_even].cache_status = COMPLETED; pthread_mutex_unlock(&statelist_cache_mutex); - return; } - static statelist_t *add_more_candidates(void) { statelist_t *new_candidates = candidates; @@ -1888,7 +1885,6 @@ static bool TestIfKeyExists(uint64_t key) static work_status_t book_of_work[NUM_PART_SUMS][NUM_PART_SUMS][NUM_PART_SUMS][NUM_PART_SUMS]; - static void init_book_of_work(void) { for (uint8_t p = 0; p < NUM_PART_SUMS; p++) { @@ -2052,19 +2048,6 @@ __attribute__((force_align_arg_pointer)) static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) { - // PrintAndLogEx(NORMAL, "Generating crypto1 state candidates... \n"); - - // estimate maximum candidate states - // maximum_states = 0; - // for (uint16_t sum_odd = 0; sum_odd <= 16; sum_odd += 2) { - // for (uint16_t sum_even = 0; sum_even <= 16; sum_even += 2) { - // if (sum_odd*(16-sum_even) + (16-sum_odd)*sum_even == sum_a0) { - // maximum_states += (uint64_t)count_states(part_sum_a0_bitarrays[EVEN_STATE][sum_even/2]) - // * count_states(part_sum_a0_bitarrays[ODD_STATE][sum_odd/2]); - // } - // } - // } - // PrintAndLogEx(NORMAL, "Number of possible keys with Sum(a0) = %d: %" PRIu64 " (2^%1.1f)\n", sum_a0, maximum_states, log(maximum_states)/log(2.0)); init_statelist_cache(); init_book_of_work(); @@ -2111,12 +2094,11 @@ static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) static void free_candidates_memory(statelist_t *sl) { - if (sl == NULL) { + if (sl == NULL) return; - } else { - free_candidates_memory(sl->next); - free(sl); - } + + free_candidates_memory(sl->next); + free(sl); } @@ -2137,7 +2119,6 @@ static void pre_XOR_nonces(void) } } } - static bool brute_force(uint64_t *found_key) { @@ -2147,7 +2128,6 @@ static bool brute_force(uint64_t *found_key) return brute_force_bs(NULL, candidates, cuid, num_acquired_nonces, maximum_states, nonces, best_first_bytes, found_key); } - static uint16_t SumProperty(struct Crypto1State *s) { uint16_t sum_odd = PartialSumProperty(s->odd, ODD_STATE); @@ -2223,11 +2203,11 @@ static void set_test_state(uint8_t byte) int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests, uint64_t *foundkey, char *filename) { - char progress_text[80]; - + char progress_text[80]; char instr_set[12] = {0}; + get_SIMD_instruction_set(instr_set); - PrintAndLog("Using %s SIMD core.", instr_set); + PrintAndLogEx(SUCCESS,"Using %s SIMD core.", instr_set); srand((unsigned) time(NULL)); brute_force_per_second = brute_force_benchmark(); @@ -2241,6 +2221,7 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc PrintAndLogEx(WARNING, "Could not create/open file hardnested_stats.txt"); return 3; } + for (uint32_t i = 0; i < tests; i++) { start_time = msclock(); print_progress_header(); @@ -2282,6 +2263,7 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc float expected_brute_force1 = (float)num_odd * num_even / 2.0; float expected_brute_force2 = nonces[best_first_bytes[0]].expected_num_brute_force; fprintf(fstats, "%1.1f;%1.1f;", log(expected_brute_force1)/log(2.0), log(expected_brute_force2)/log(2.0)); + if (expected_brute_force1 < expected_brute_force2) { hardnested_print_progress(num_acquired_nonces, "(Ignoring Sum(a8) properties)", expected_brute_force1, 0); set_test_state(best_first_byte_smallest_bitarray); @@ -2291,12 +2273,11 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc for (statelist_t *sl = candidates; sl != NULL; sl = sl->next) { maximum_states += (uint64_t)sl->len[ODD_STATE] * sl->len[EVEN_STATE]; } - //PrintAndLogEx(NORMAL, "Number of remaining possible keys: %" PRIu64 " (2^%1.1f)\n", maximum_states, log(maximum_states)/log(2.0)); - // fPrintAndLogEx(NORMAL, "fstats, "%" PRIu64 ";", maximum_states); + best_first_bytes[0] = best_first_byte_smallest_bitarray; pre_XOR_nonces(); prepare_bf_test_nonces(nonces, best_first_bytes[0]); - //hardnested_print_progress(num_acquired_nonces, "Starting brute force...", expected_brute_force1, 0); + key_found = brute_force(foundkey); free(candidates->states[ODD_STATE]); free(candidates->states[EVEN_STATE]); @@ -2313,10 +2294,8 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc sprintf(progress_text, "(Estimated Sum(a8) is WRONG! Correct Sum(a8) = %" PRIu16 ")", real_sum_a8); hardnested_print_progress(num_acquired_nonces, progress_text, expected_brute_force, 0); } - // PrintAndLogEx(NORMAL, "Estimated remaining states: %" PRIu64 " (2^%1.1f)\n", nonces[best_first_bytes[0]].sum_a8_guess[j].num_states, log(nonces[best_first_bytes[0]].sum_a8_guess[j].num_states)/log(2.0)); generate_candidates(first_byte_Sum, nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx); - // PrintAndLogEx(NORMAL, "Time for generating key candidates list: %1.0f sec (%1.1f sec CPU)\n", difftime(time(NULL), start_time), (float)(msclock() - start_clock)/1000.0); - //hardnested_print_progress(num_acquired_nonces, "Starting brute force...", expected_brute_force, 0); + key_found = brute_force(foundkey); free_statelist_cache(); free_candidates_memory(candidates); @@ -2399,40 +2378,44 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc uint32_t num_even = nonces[best_first_byte_smallest_bitarray].num_states_bitarray[EVEN_STATE]; float expected_brute_force1 = (float)num_odd * num_even / 2.0; float expected_brute_force2 = nonces[best_first_bytes[0]].expected_num_brute_force; + if (expected_brute_force1 < expected_brute_force2) { hardnested_print_progress(num_acquired_nonces, "(Ignoring Sum(a8) properties)", expected_brute_force1, 0); set_test_state(best_first_byte_smallest_bitarray); add_bitflip_candidates(best_first_byte_smallest_bitarray); Tests2(); maximum_states = 0; + for (statelist_t *sl = candidates; sl != NULL; sl = sl->next) { maximum_states += (uint64_t)sl->len[ODD_STATE] * sl->len[EVEN_STATE]; } - // PrintAndLogEx(NORMAL, "Number of remaining possible keys: %" PRIu64 " (2^%1.1f)\n", maximum_states, log(maximum_states)/log(2.0)); + best_first_bytes[0] = best_first_byte_smallest_bitarray; pre_XOR_nonces(); prepare_bf_test_nonces(nonces, best_first_bytes[0]); - //hardnested_print_progress(num_acquired_nonces, "Starting brute force...", expected_brute_force1, 0); + key_found = brute_force(foundkey); free(candidates->states[ODD_STATE]); free(candidates->states[EVEN_STATE]); + free_statelist_cache(); free_candidates_memory(candidates); candidates = NULL; } else { + pre_XOR_nonces(); prepare_bf_test_nonces(nonces, best_first_bytes[0]); + for (uint8_t j = 0; j < NUM_SUMS && !key_found; j++) { float expected_brute_force = nonces[best_first_bytes[0]].expected_num_brute_force; sprintf(progress_text, "(%d. guess: Sum(a8) = %" PRIu16 ")", j+1, sums[nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx]); hardnested_print_progress(num_acquired_nonces, progress_text, expected_brute_force, 0); + if (trgkey != NULL && sums[nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx] != real_sum_a8) { sprintf(progress_text, "(Estimated Sum(a8) is WRONG! Correct Sum(a8) = %" PRIu16 ")", real_sum_a8); hardnested_print_progress(num_acquired_nonces, progress_text, expected_brute_force, 0); } - // PrintAndLogEx(NORMAL, "Estimated remaining states: %" PRIu64 " (2^%1.1f)\n", nonces[best_first_bytes[0]].sum_a8_guess[j].num_states, log(nonces[best_first_bytes[0]].sum_a8_guess[j].num_states)/log(2.0)); + generate_candidates(first_byte_Sum, nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx); - // PrintAndLogEx(NORMAL, "Time for generating key candidates list: %1.0f sec (%1.1f sec CPU)\n", difftime(time(NULL), start_time), (float)(msclock() - start_clock)/1000.0); - //hardnested_print_progress(num_acquired_nonces, "Starting brute force...", expected_brute_force, 0); key_found = brute_force(foundkey); free_statelist_cache(); free_candidates_memory(candidates); diff --git a/client/hardnested/hardnested_bf_core.c b/client/hardnested/hardnested_bf_core.c index c00434a52..6bf29b795 100644 --- a/client/hardnested/hardnested_bf_core.c +++ b/client/hardnested/hardnested_bf_core.c @@ -59,6 +59,7 @@ THE SOFTWARE. #include #include "crapto1/crapto1.h" #include "parity.h" +#include "util.h" // bitslice type // while AVX supports 256 bit vector floating point operations, we need integer operations for boolean logic @@ -99,9 +100,6 @@ typedef union { // size of nonce to be decrypted #define KEYSTREAM_SIZE 24 -// endianness conversion -#define rev32(word) ((((word) & 0xff) << 24) | ((((word) >> 8) & 0xff) << 16) | ((((word) >> 16) & 0xff) << 8) | ((((word) >> 24) & 0xff))) - // this needs to be compiled several times for each instruction set. // For each instruction set, define a dedicated function name: #if defined (__AVX512F__) @@ -184,7 +182,7 @@ void BITSLICE_TEST_NONCES(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonce // bitslice nonces' 2nd to 4th byte for (uint32_t i = 0; i < nonces_to_bruteforce; i++) { for(uint32_t bit_idx = 0; bit_idx < KEYSTREAM_SIZE; bit_idx++){ - bool bit = get_bit(KEYSTREAM_SIZE-1-bit_idx, rev32(bf_test_nonce[i] << 8)); + bool bit = get_bit(KEYSTREAM_SIZE-1-bit_idx, BSWAP_32(bf_test_nonce[i] << 8)); if(bit){ bitsliced_encrypted_nonces[i][bit_idx].value = bs_ones.value; } else { From c58f487cab2fce86967f85cc0295a278dda28ab0 Mon Sep 17 00:00:00 2001 From: sh7d Date: Sun, 17 Feb 2019 12:54:44 +0100 Subject: [PATCH 0552/1938] em41 - spoof fix --- client/cmdlfem4x.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 3260b8d74..7b4386fbb 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -404,8 +404,7 @@ int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose) { // this read is the "normal" read, which download lf signal and tries to demod here. int CmdEM410xRead(const char *Cmd) { lf_read(true, 8192); - CmdEM410xDemod(Cmd); - return 0; + return CmdEM410xDemod(Cmd); } // this read loops on device side. From 2dc3bc6af3599f86849d996ae44b7c06713c467f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 23 Feb 2019 15:44:34 +0100 Subject: [PATCH 0553/1938] ADD: 'lf keri' - basic commands. --- client/Makefile | 1 + client/cmdlfkeri.c | 233 +++++++++++++++++++++++++++++++++++++++++++++ client/cmdlfkeri.h | 36 +++++++ 3 files changed, 270 insertions(+) create mode 100644 client/cmdlfkeri.c create mode 100644 client/cmdlfkeri.h diff --git a/client/Makefile b/client/Makefile index 0b19d4599..324aaef01 100644 --- a/client/Makefile +++ b/client/Makefile @@ -187,6 +187,7 @@ CMDSRCS = crapto1/crapto1.c \ cmdlfio.c \ cmdlfindala.c \ cmdlfjablotron.c \ + cmdlfkeri.c \ cmdlfnexwatch.c \ cmdlfnedap.c \ cmdlfnoralsy.c \ diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c new file mode 100644 index 000000000..b5f6fa793 --- /dev/null +++ b/client/cmdlfkeri.c @@ -0,0 +1,233 @@ +//----------------------------------------------------------------------------- +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency KERI tag commands +// PSK1, RF/128, RF/2, 64 bits long +//----------------------------------------------------------------------------- +#include "cmdlfkeri.h" + +static int CmdHelp(const char *Cmd); + +int usage_lf_keri_clone(void){ + PrintAndLogEx(NORMAL, "clone a KERI tag to a T55x7 tag."); + PrintAndLogEx(NORMAL, "Usage: lf keri clone [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " : KERI Internal ID"); + PrintAndLogEx(NORMAL, " : specify write to Q5 (t5555 instead of t55x7)"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf keri clone 112233"); + return 0; +} + +int usage_lf_keri_sim(void) { + PrintAndLogEx(NORMAL, "Enables simulation of KERI card with specified card number."); + PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: lf keri sim [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " : Keri Internal ID"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf keri sim 112233"); + return 0; +} + +// find KERI preamble in already demoded data +int detectKeri(uint8_t *dest, size_t *size, bool *invert) { + + uint8_t preamble[] = {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,1}; + uint8_t preamble_i[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0}; + + // sanity check. + if ( *size < sizeof(preamble) + 100) return -1; + + size_t startIdx = 0; + + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) { + + // if didn't find preamble try again inverting + if (!preambleSearch(DemodBuffer, preamble_i, sizeof(preamble_i), size, &startIdx)) + return -2; + + *invert ^= 1; + } + + if (*size != 64) return -3; //wrong demoded size + + return (int)startIdx; +} + +int CmdKeriDemod(const char *Cmd) { + + if (!PSKDemod("", false)) { + PrintAndLogEx(DEBUG, "DEBUG: Error - KERI: PSK1 Demod failed"); + return 0; + } + bool invert = false; + size_t size = DemodBufferLen; + int idx = detectKeri(DemodBuffer, &size, &invert); + if (idx < 0) { + if (idx == -1) + PrintAndLogEx(DEBUG, "DEBUG: Error - KERI: too few bits found"); + else if (idx == -2) + PrintAndLogEx(DEBUG, "DEBUG: Error - KERI: preamble not found"); + else if (idx == -3) + PrintAndLogEx(DEBUG, "DEBUG: Error - KERI: Size not correct: 64 != %d", size); + else + PrintAndLogEx(DEBUG, "DEBUG: Error - KERI: ans: %d", idx); + + return 0; + } + setDemodBuf(DemodBuffer, size, idx); + setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock)); + + //got a good demod + uint32_t raw1 = bytebits_to_byte(DemodBuffer , 32); + uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); + + //get internal id + uint32_t ID = 0; + for (uint8_t i = 30; i < 59; i++){ + ID = (ID << 1) | DemodBuffer[i]; + } + + /* + 000000000000000000000000000001XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX111 + ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^1###############################^^^ + Preamble block 29 bits of ZEROS + 32 bit Internal ID (First bit always 1) + 3 bit of 1s in the end + + How this is decoded to Facility ID, Card number is unknown + Facility ID = 0-31 (indicates 5 bits) + Card number = up to 10 digits + + Might be a hash of FC & CN to generate Internal ID + */ + + PrintAndLogEx(NORMAL, "KERI Tag Found -- Raw: %08X%08X", raw1 ,raw2); + + PrintAndLogEx(NORMAL, "KERI Internal ID: %d", ID); + + if (invert){ + PrintAndLogEx(NORMAL, "Had to Invert - probably KERI"); + for (size_t i = 0; i < size; i++) + DemodBuffer[i] ^= 1; + } + + CmdPrintDemodBuff("x"); + + return 1; +} + +int CmdKeriRead(const char *Cmd) { + lf_read(true, 10000); + return CmdKeriDemod(Cmd); +} + +int CmdKeriClone(const char *Cmd) { + + PrintAndLogEx(ERR, "TO BE DONE - Cloning KERI is not implemented yet"); + /* + uint32_t internalid = 0; + uint32_t blocks[3] = {T55x7_MODULATION_PSK1 | T55x7_PSKCF_RF_2 | 2 << T55x7_MAXBLOCK_SHIFT | T55x7_BITRATE_RF_16, 0, 0}; + + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_keri_clone(); + + internalid = param_get32ex(Cmd, 0, 0, 10); + + //Q5 + if (tolower(param_getchar(Cmd, 1)) == 'q') + blocks[0] = T5555_MODULATION_PSK1 | T5555_SET_BITRATE(16) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT; + + + // MSB is ONE, and 3 LSB is ONE + uint32_t pre = + internalid &= 0x80000003; + + // + blocks[1] = internalid & 0x + blocks[2] = bytebits_to_byte(bits + 32, 32); + + PrintAndLogEx(NORMAL, "Preparing to clone KERI to T55x7 with Internal Id: %u", id); + print_blocks(blocks, 3); + + UsbCommand resp; + UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}}; + + for (uint8_t i=0; i<3; i++) { + c.arg[0] = blocks[i]; + c.arg[1] = i; + clearCommandBuffer(); + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK, &resp, T55XX_WRITE_TIMEOUT)){ + PrintAndLogEx(WARNING, "Error occurred, device did not respond during write operation."); + return -1; + } + } + */ + return 0; +} + +int CmdKeriSim(const char *Cmd) { + + PrintAndLogEx(ERR, "TO BE DONE - Simulating KERI is not implemented yet"); +/* + uint8_t bits[64]; + uint8_t *bs = bits; + memset(bs, 0, sizeof(bits)); + + uint32_t internalid = 0; + + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_keri_sim(); + + internalid = param_get32ex(Cmd, 0, 0, 10); + + uint8_t clk = 32, encoding = 1, separator = 1, invert = 0; + uint16_t arg1, arg2; + size_t size = 64; + arg1 = clk << 8 | encoding; + arg2 = invert << 8 | separator; + + if ( !getkeriBits(internalid, bs)) { + PrintAndLogEx(WARNING, "Error with tag bitstream generation."); + return 1; + } + + PrintAndLogEx(NORMAL, "Simulating KERI - Internal Id: %u", id); + + UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}}; + memcpy(c.d.asBytes, bs, size); + clearCommandBuffer(); + SendCommand(&c); +*/ + return 0; +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdKeriDemod, 1, "Demodulate an KERI tag from the GraphBuffer"}, + {"read", CmdKeriRead, 0, "Attempt to read and extract tag data from the antenna"}, + {"clone", CmdKeriClone, 0, "clone KERI to T55x7"}, + {"sim", CmdKeriSim, 0, "simulate KERI tag"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFKeri(const char *Cmd) { + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlfkeri.h b/client/cmdlfkeri.h new file mode 100644 index 000000000..ed0629b37 --- /dev/null +++ b/client/cmdlfkeri.h @@ -0,0 +1,36 @@ +//----------------------------------------------------------------------------- +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency Stanley/PAC tag commands +//----------------------------------------------------------------------------- +#ifndef CMDLFKERI_H__ +#define CMDLFKERI_H__ + +#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 "protocols.h" // for T55xx config register definitions +#include "lfdemod.h" // preamble test + +extern int CmdLFKeri(const char *Cmd); +extern int CmdKeriRead(const char *Cmd); +extern int CmdKeriDemod(const char *Cmd); +extern int CmdKeriClone(const char *Cmd); +extern int CmdKeriSim(const char *Cmd); + +extern int detectKeri(uint8_t *dest, size_t *size, bool *invert); + +extern int usage_lf_keri_clone(void); +extern int usage_lf_keri_sim(void); +#endif + From 9851f88139fecd3fc7c5f4dc880de7ddbed63623 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 23 Feb 2019 15:45:22 +0100 Subject: [PATCH 0554/1938] text --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index ce939d980..0c7891297 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Add 'lf keri' - basic support for Keri tags (@iceman) - Add 'hf mf list' - readded it again (@iceman) - Fix - A lot of bugfixes, like memory leaks (@iceman) - Change 'hf 14a antifuzz' - original implementation (@asfabw), reworked a bit From f5f6f5d9162230a669eba99fda15a220a9efff0c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 23 Feb 2019 15:47:37 +0100 Subject: [PATCH 0555/1938] chg: linking in keri --- client/cmdlf.c | 1 + client/cmdlf.h | 9 +++++---- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index 50077add2..4fc877061 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -957,6 +957,7 @@ static command_t CommandTable[] = { {"indala", CmdLFINDALA, 1, "{ Indala RFIDs... }"}, {"io", CmdLFIO, 1, "{ ioProx RFIDs... }"}, {"jablotron", CmdLFJablotron, 1, "{ Jablotron RFIDs... }"}, + {"keri", CmdLFKeri, 1, "{ KERI RFIDs... }"}, {"nedap", CmdLFNedap, 1, "{ Nedap RFIDs... }"}, {"nexwatch", CmdLFNEXWATCH, 1, "{ NexWatch RFIDs... }"}, {"noralsy", CmdLFNoralsy, 1, "{ Noralsy RFIDs... }"}, diff --git a/client/cmdlf.h b/client/cmdlf.h index de216435f..04c7317a1 100644 --- a/client/cmdlf.h +++ b/client/cmdlf.h @@ -42,13 +42,14 @@ #include "cmdlfnoralsy.h" // for NORALSY meny #include "cmdlffdx.h" // for FDX-B meny #include "cmdlfcotag.h" // for COTAG meny -#include "cmdlfindala.h" // for indala menu -#include "cmdlfguard.h"// for gproxii menu -#include "cmdlffdx.h" // for fdx-b menu -#include "cmdlfparadox.h"// for paradox menu +#include "cmdlfindala.h" // for indala menu +#include "cmdlfguard.h" // for gproxii menu +#include "cmdlffdx.h" // for fdx-b menu +#include "cmdlfparadox.h" // for paradox menu #include "cmdlfnexwatch.h" //for nexwatch menu #include "cmdlfsecurakey.h" //for securakey menu #include "cmdlfpac.h" // for pac menu +#include "cmdlfkeri.h" // for keri menu #define T55XX_WRITE_TIMEOUT 1500 From e0bf2e3fbf69b107977caf29908bef5dd767cd65 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 23 Feb 2019 15:56:11 +0100 Subject: [PATCH 0556/1938] chg: 'lf search' - hooked up Keri detection --- client/cmdlf.c | 1 + 1 file changed, 1 insertion(+) diff --git a/client/cmdlf.c b/client/cmdlf.c index 4fc877061..fc0aa5f6e 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -891,6 +891,7 @@ int CmdLFfind(const char *Cmd) { if (CmdLFNedapDemod("")) { PrintAndLogEx(SUCCESS, "\nValid NEDAP ID Found!"); goto out;} if (CmdNexWatchDemod("")) { PrintAndLogEx(SUCCESS, "\nValid NexWatch ID Found!"); goto out;} if (CmdNoralsyDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Noralsy ID Found!"); goto out;} + if (CmdKeriDemod("")) { PrintAndLogEx(SUCCESS, "\nValid KERI ID Found!"); goto out;} if (CmdPacDemod("")) { PrintAndLogEx(SUCCESS, "\nValid PAC/Stanley ID Found!"); goto out;} if (CmdParadoxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Paradox ID Found!"); goto out;} if (CmdPrescoDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Presco ID Found!"); goto out;} From 92b1f417930896e748788ca4511fe36ef28f740a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 23 Feb 2019 16:02:44 +0100 Subject: [PATCH 0557/1938] revert chg, double free... --- client/cmdhfmfhard.c | 1 - 1 file changed, 1 deletion(-) diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 9d9406c11..1ebf2131d 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -2397,7 +2397,6 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc key_found = brute_force(foundkey); free(candidates->states[ODD_STATE]); free(candidates->states[EVEN_STATE]); - free_statelist_cache(); free_candidates_memory(candidates); candidates = NULL; } else { From dc0dc7b00a374aff058b5b3cebe0d28285b90115 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 23 Feb 2019 16:05:24 +0100 Subject: [PATCH 0558/1938] chg: cleanup --- client/cmdlfnexwatch.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmdlfnexwatch.c b/client/cmdlfnexwatch.c index c90557665..4057fe452 100644 --- a/client/cmdlfnexwatch.c +++ b/client/cmdlfnexwatch.c @@ -34,14 +34,13 @@ int detectNexWatch(uint8_t *dest, size_t *size, bool *invert) { int CmdNexWatchDemod(const char *Cmd) { if (!PSKDemod("", false)) { - if (g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: Error - NexWatch can't demod signal"); + PrintAndLogEx(DEBUG, "DEBUG: Error - NexWatch can't demod signal"); return 0; } bool invert = false; size_t size = DemodBufferLen; int idx = detectNexWatch(DemodBuffer, &size, &invert); - if (idx <= 0){ - if (g_debugMode){ + if (idx <= 0) { if (idx == -1) PrintAndLogEx(DEBUG, "DEBUG: Error - NexWatch not enough samples"); // else if (idx == -2) @@ -54,7 +53,7 @@ int CmdNexWatchDemod(const char *Cmd) { // PrintAndLogEx(DEBUG, "DEBUG: Error - NexWatch size not correct: %d", size); else PrintAndLogEx(DEBUG, "DEBUG: Error - NexWatch error %d",idx); - } + return 0; } @@ -101,6 +100,7 @@ static command_t CommandTable[] = { }; int CmdLFNEXWATCH(const char *Cmd) { + clearCommandBuffer(); CmdsParse(CommandTable, Cmd); return 0; } From d1c22d0800034e65f09682a09645d72b2db4c14a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 23 Feb 2019 16:29:00 +0100 Subject: [PATCH 0559/1938] fix: 'lf keri demod' - proper demod now --- client/cmdlfkeri.c | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index b5f6fa793..cfd01fedc 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -92,10 +92,8 @@ int CmdKeriDemod(const char *Cmd) { uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); //get internal id - uint32_t ID = 0; - for (uint8_t i = 30; i < 59; i++){ - ID = (ID << 1) | DemodBuffer[i]; - } + uint32_t ID = bytebits_to_byte(DemodBuffer+29, 32); + ID &= 0x7FFFFFFF; /* 000000000000000000000000000001XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX111 @@ -111,18 +109,16 @@ int CmdKeriDemod(const char *Cmd) { Might be a hash of FC & CN to generate Internal ID */ - PrintAndLogEx(NORMAL, "KERI Tag Found -- Raw: %08X%08X", raw1 ,raw2); - - PrintAndLogEx(NORMAL, "KERI Internal ID: %d", ID); + PrintAndLogEx(NORMAL, "KERI Tag Found -- Raw: %08X%08X", raw1 ,raw2); + PrintAndLogEx(NORMAL, "KERI Internal ID: %u", ID); if (invert){ PrintAndLogEx(NORMAL, "Had to Invert - probably KERI"); for (size_t i = 0; i < size; i++) DemodBuffer[i] ^= 1; + + CmdPrintDemodBuff("x"); } - - CmdPrintDemodBuff("x"); - return 1; } From fe9c65b65fbcbe6cbab97e0d925171a0e19f39f0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 23 Feb 2019 17:19:34 +0100 Subject: [PATCH 0560/1938] chg: 'lf keri clone' - now works --- client/cmdlfkeri.c | 29 ++++++++++++++++++----------- 1 file changed, 18 insertions(+), 11 deletions(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index cfd01fedc..70cdb4ca9 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -129,10 +129,15 @@ int CmdKeriRead(const char *Cmd) { int CmdKeriClone(const char *Cmd) { - PrintAndLogEx(ERR, "TO BE DONE - Cloning KERI is not implemented yet"); - /* + uint32_t internalid = 0; - uint32_t blocks[3] = {T55x7_MODULATION_PSK1 | T55x7_PSKCF_RF_2 | 2 << T55x7_MAXBLOCK_SHIFT | T55x7_BITRATE_RF_16, 0, 0}; + uint32_t blocks[3] = { + T55x7_X_MODE | T55x7_MODULATION_PSK1 | T55x7_PSKCF_RF_2 | 2 << T55x7_MAXBLOCK_SHIFT | T55x7_BITRATE_RF_128, + 0, + 0}; + + // safe key + blocks[0] |= 6 << 28; char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_keri_clone(); @@ -141,18 +146,20 @@ int CmdKeriClone(const char *Cmd) { //Q5 if (tolower(param_getchar(Cmd, 1)) == 'q') - blocks[0] = T5555_MODULATION_PSK1 | T5555_SET_BITRATE(16) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT; + blocks[0] = T5555_MODULATION_PSK1 | T5555_SET_BITRATE(128) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT; - // MSB is ONE, and 3 LSB is ONE - uint32_t pre = - internalid &= 0x80000003; + // MSB is ONE + internalid |= 0x80000000; + // 3 LSB is ONE + uint64_t data = ((uint64_t)internalid << 3 ) + 7; + // - blocks[1] = internalid & 0x - blocks[2] = bytebits_to_byte(bits + 32, 32); + blocks[1] = data >> 32; + blocks[2] = data & 0xFFFFFFFF; - PrintAndLogEx(NORMAL, "Preparing to clone KERI to T55x7 with Internal Id: %u", id); + PrintAndLogEx(NORMAL, "Preparing to clone KERI to T55x7 with Internal Id: %u", internalid); print_blocks(blocks, 3); UsbCommand resp; @@ -168,7 +175,7 @@ int CmdKeriClone(const char *Cmd) { return -1; } } - */ + return 0; } From a07dcf79240e310f7ced60e4f0b819be5b9abb15 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 10:25:53 +0100 Subject: [PATCH 0561/1938] chg: 'lf keri clone' - correct config block (use extended modes bit rates) --- client/cmdlfkeri.c | 56 ++++++++++++++++++++++++++++------------------ common/protocols.h | 1 + 2 files changed, 35 insertions(+), 22 deletions(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 70cdb4ca9..fb4f26703 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -130,14 +130,19 @@ int CmdKeriRead(const char *Cmd) { int CmdKeriClone(const char *Cmd) { + uint32_t internalid = 0; uint32_t blocks[3] = { - T55x7_X_MODE | T55x7_MODULATION_PSK1 | T55x7_PSKCF_RF_2 | 2 << T55x7_MAXBLOCK_SHIFT | T55x7_BITRATE_RF_128, + T55x7_TESTMODE_DISABLED | + T55x7_X_MODE | + T55x7_MODULATION_PSK1 | + T55x7_PSKCF_RF_2 | + 2 << T55x7_MAXBLOCK_SHIFT, 0, 0}; - // safe key - blocks[0] |= 6 << 28; + // dynamic bitrate used + blocks[0] |= 0xF << 18; char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_keri_clone(); @@ -145,8 +150,13 @@ int CmdKeriClone(const char *Cmd) { internalid = param_get32ex(Cmd, 0, 0, 10); //Q5 - if (tolower(param_getchar(Cmd, 1)) == 'q') - blocks[0] = T5555_MODULATION_PSK1 | T5555_SET_BITRATE(128) | T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT; + if (tolower(param_getchar(Cmd, 1)) == 'q') { + blocks[0] = + T5555_MODULATION_PSK1 | + T5555_SET_BITRATE(128) | + T5555_PSK_RF_2 | + 2 << T5555_MAXBLOCK_SHIFT; + } // MSB is ONE @@ -161,11 +171,13 @@ int CmdKeriClone(const char *Cmd) { PrintAndLogEx(NORMAL, "Preparing to clone KERI to T55x7 with Internal Id: %u", internalid); print_blocks(blocks, 3); - + + UsbCommand resp; UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}}; - for (uint8_t i=0; i<3; i++) { + + for (uint8_t i = 0; i < 3; i++) { c.arg[0] = blocks[i]; c.arg[1] = i; clearCommandBuffer(); @@ -181,37 +193,37 @@ int CmdKeriClone(const char *Cmd) { int CmdKeriSim(const char *Cmd) { - PrintAndLogEx(ERR, "TO BE DONE - Simulating KERI is not implemented yet"); -/* + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_keri_sim(); + uint8_t bits[64]; uint8_t *bs = bits; memset(bs, 0, sizeof(bits)); - uint32_t internalid = 0; + uint32_t internalid = param_get32ex(Cmd, 0, 0, 10); - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_keri_sim(); + // loop to bits. + internalid |= 0x80000000; - internalid = param_get32ex(Cmd, 0, 0, 10); + // 3 LSB is ONE + uint64_t data = ((uint64_t)internalid << 3 ) + 7; + - uint8_t clk = 32, encoding = 1, separator = 1, invert = 0; + + uint8_t clk = 32, carrier = 2, invert = 0; uint16_t arg1, arg2; size_t size = 64; - arg1 = clk << 8 | encoding; - arg2 = invert << 8 | separator; + arg1 = clk << 8 | carrier; + arg2 = invert; - if ( !getkeriBits(internalid, bs)) { - PrintAndLogEx(WARNING, "Error with tag bitstream generation."); - return 1; - } - PrintAndLogEx(NORMAL, "Simulating KERI - Internal Id: %u", id); + PrintAndLogEx(NORMAL, "Simulating KERI - Internal Id: %u", internalid); UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}}; memcpy(c.d.asBytes, bs, size); clearCommandBuffer(); SendCommand(&c); -*/ + return 0; } diff --git a/common/protocols.h b/common/protocols.h index 3c2e79a8d..73355c85d 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -389,6 +389,7 @@ void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t * #define T55x7_BITRATE_RF_64 0x00140000 #define T55x7_BITRATE_RF_100 0x00180000 #define T55x7_BITRATE_RF_128 0x001C0000 +#define T55x7_TESTMODE_DISABLED 0x60000000 /* T5555 (Q5) configuration register definitions */ #define T5555_ST_TERMINATOR 0x00000001 From 9f10ff6e1794bea5e7dff43624926bf86737be07 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 10:26:55 +0100 Subject: [PATCH 0562/1938] sugar --- client/cmdhfmfu.c | 31 ++++++++++++++++++++----------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index d703f980d..8b27d9b22 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -2381,7 +2381,7 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_gendiverse(); if ( cmdp == 'r' ) { - // read uid from tag + // read uid from tag UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -2390,8 +2390,13 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ iso14a_card_select_t card; memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - if(select_status == 0) { + uint64_t select_status = resp.arg[0]; + // 0: couldn't read, + // 1: OK, with ATS + // 2: OK, no ATS + // 3: proprietary Anticollision + + if ( select_status == 0 ) { PrintAndLogEx(WARNING, "iso14443a card select failed"); return 1; } @@ -2446,12 +2451,12 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ PrintAndLogEx(NORMAL, "Diversified key: %s", sprint_hex(divkey+1, 6)); for (int i=0; i < sizeof(mifarekeyA); ++i){ - dkeyA[i] = (mifarekeyA[i] << 1) & 0xff; - dkeyA[6] |= ((mifarekeyA[i] >> 7) & 1) << (i+1); + dkeyA[i] = (mifarekeyA[i] << 1) & 0xff; + dkeyA[6] |= ((mifarekeyA[i] >> 7) & 1) << (i+1); } for (int i=0; i < sizeof(mifarekeyB); ++i){ - dkeyB[1] |= ((mifarekeyB[i] >> 7) & 1) << (i+1); + dkeyB[1] |= ((mifarekeyB[i] >> 7) & 1) << (i+1); dkeyB[2+i] = (mifarekeyB[i] << 1) & 0xff; } @@ -2488,6 +2493,7 @@ int CmdHF14AMfuPwdGen(const char *Cmd){ uint8_t uid[7] = {0x00}; char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_pwdgen(); + if (cmdp == 't') return ul_ev1_pwdgen_selftest(); if ( cmdp == 'r') { @@ -2500,8 +2506,12 @@ int CmdHF14AMfuPwdGen(const char *Cmd){ iso14a_card_select_t card; memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - if(select_status == 0) { + uint64_t select_status = resp.arg[0]; + // 0: couldn't read + // 1: OK with ATS + // 2: OK, no ATS + // 3: proprietary Anticollision + if ( select_status == 0 ) { PrintAndLogEx(WARNING, "iso14443a card select failed"); return 1; } @@ -2514,6 +2524,7 @@ int CmdHF14AMfuPwdGen(const char *Cmd){ else { if (param_gethex(Cmd, 0, uid, 14)) return usage_hf_mfu_pwdgen(); } + PrintAndLogEx(NORMAL, "---------------------------------"); PrintAndLogEx(NORMAL, " Using UID : %s", sprint_hex(uid, 7)); PrintAndLogEx(NORMAL, "---------------------------------"); @@ -2531,8 +2542,7 @@ int CmdHF14AMfuPwdGen(const char *Cmd){ //------------------------------------ // Menu Stuff //------------------------------------ -static command_t CommandTable[] = -{ +static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, {"info", CmdHF14AMfUInfo, 0, "Tag information"}, @@ -2552,7 +2562,6 @@ static command_t CommandTable[] = int CmdHFMFUltra(const char *Cmd){ clearCommandBuffer(); - //WaitForResponseTimeout(CMD_ACK,NULL,100); CmdsParse(CommandTable, Cmd); return 0; } From 730b4940f8c19d2cd3631b605bcbc064babcbf31 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 11:14:51 +0100 Subject: [PATCH 0563/1938] chg: 'lf keri sim' - is kind of up, *untested* --- client/cmdlfkeri.c | 29 ++++++++++++----------------- 1 file changed, 12 insertions(+), 17 deletions(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index fb4f26703..ec8020aa2 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -16,7 +16,7 @@ int usage_lf_keri_clone(void){ PrintAndLogEx(NORMAL, "Usage: lf keri clone [h] "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " : KERI Internal ID"); + PrintAndLogEx(NORMAL, " : Keri Internal ID"); PrintAndLogEx(NORMAL, " : specify write to Q5 (t5555 instead of t55x7)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); @@ -128,8 +128,6 @@ int CmdKeriRead(const char *Cmd) { } int CmdKeriClone(const char *Cmd) { - - uint32_t internalid = 0; uint32_t blocks[3] = { @@ -196,19 +194,17 @@ int CmdKeriSim(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_keri_sim(); - uint8_t bits[64]; - uint8_t *bs = bits; - memset(bs, 0, sizeof(bits)); - - uint32_t internalid = param_get32ex(Cmd, 0, 0, 10); - - // loop to bits. + uint64_t internalid = param_get32ex(Cmd, 0, 0, 10); internalid |= 0x80000000; + internalid <<= 3; + internalid += 7; - // 3 LSB is ONE - uint64_t data = ((uint64_t)internalid << 3 ) + 7; - - + uint8_t bits[64] = {0x00}; + // loop to bits + uint8_t j = 0; + for ( int8_t i = 63; i >= 0; --i) { + bits[j++] = ((internalid >> i) & 1 ); + } uint8_t clk = 32, carrier = 2, invert = 0; uint16_t arg1, arg2; @@ -216,14 +212,13 @@ int CmdKeriSim(const char *Cmd) { arg1 = clk << 8 | carrier; arg2 = invert; - PrintAndLogEx(NORMAL, "Simulating KERI - Internal Id: %u", internalid); - + UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}}; memcpy(c.d.asBytes, bs, size); clearCommandBuffer(); SendCommand(&c); - + return 0; } From 1c2dea29bb56f0757d01f029538eeee9328724e0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 14:38:33 +0100 Subject: [PATCH 0564/1938] chg --- client/cmdlfem4x.c | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 7b4386fbb..97e0668cc 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -364,9 +364,7 @@ int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo ) { int ans = Em410xDecode(bits, &size, &idx, hi, lo); if ( ans < 0){ - if (ans == -1) - PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x not only 0|1 in decoded bitstream"); - else if (ans == -2) + if (ans == -2) PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x not enough samples after demod"); else if (ans == -4) PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x preamble not found"); From 8cc9cc312f72ef0bb599f22fc2642893baa0673a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 14:39:20 +0100 Subject: [PATCH 0565/1938] chg... names names..sigh --- client/cmdlfkeri.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index ec8020aa2..884e89933 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -215,7 +215,7 @@ int CmdKeriSim(const char *Cmd) { PrintAndLogEx(NORMAL, "Simulating KERI - Internal Id: %u", internalid); UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}}; - memcpy(c.d.asBytes, bs, size); + memcpy(c.d.asBytes, bits, size); clearCommandBuffer(); SendCommand(&c); From cea5b5214d3ceab5fcf374984f52bd01af3f8758 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 14:51:21 +0100 Subject: [PATCH 0566/1938] chg: colors --- client/cmdhficlass.c | 4 ++-- client/cmdhfmf.c | 2 +- client/cmdlft55xx.c | 27 ++++++++++++++------------- client/cmdsmartcard.c | 2 +- 4 files changed, 18 insertions(+), 17 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index ddc6fb2c0..82e14d5ea 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -626,7 +626,7 @@ int CmdHFiClassELoad(const char *Cmd) { f = fopen(filename, "rb"); if ( !f ){ - PrintAndLogEx(FAILED, "File: %s: not found or locked.", filename); + PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); return 1; } @@ -2304,7 +2304,7 @@ int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) { int keyitems = 0; if ( !(f = fopen( filename , "r")) ) { - PrintAndLogEx(ERR, "file: %s: not found or locked.", filename); + PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); return 1; } diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 2412aecee..76f0fc2b6 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1812,7 +1812,7 @@ int CmdHF14AMfChk(const char *Cmd) { f = fopen( filename , "r"); if ( !f ) { - PrintAndLogEx(FAILED, "File: " _YELLOW_(%s)": not found or locked.", filename); + PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); continue; } diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index abf8f04ec..52240f0db 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -691,7 +691,7 @@ bool tryDetectModulation(){ bool retval = false; if ( hits > 1) { - PrintAndLogEx(NORMAL, "Found [%d] possible matches for modulation.",hits); + PrintAndLogEx(SUCCESS, "Found [%d] possible matches for modulation.", hits); for(int i=0; i>28==6 || b.block0>>28==9))) ); - PrintAndLogEx(NORMAL, "Inverted : %s", (b.inverted) ? "Yes" : "No" ); + PrintAndLogEx(NORMAL, "Inverted : %s", (b.inverted) ? _GREEN_(Yes) : "No" ); PrintAndLogEx(NORMAL, "Offset : %d", b.offset); - PrintAndLogEx(NORMAL, "Seq. Term. : %s", (b.ST) ? "Yes" : "No" ); + PrintAndLogEx(NORMAL, "Seq. Term. : %s", (b.ST) ? _GREEN_(Yes) : "No" ); PrintAndLogEx(NORMAL, "Block0 : 0x%08X", b.block0); PrintAndLogEx(NORMAL, ""); return 0; @@ -1264,24 +1264,25 @@ int CmdT55xxInfo(const char *Cmd){ uint32_t inv = PackBits(si, 1, DemodBuffer); si += 1; uint32_t por = PackBits(si, 1, DemodBuffer); si += 1; - if (config.Q5) PrintAndLogEx(NORMAL, "*** Warning *** Config Info read off a Q5 will not display as expected"); + if (config.Q5) PrintAndLogEx(NORMAL, _RED_(*** Warning ***) " Config Info read off a Q5 will not display as expected"); + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "-- T55x7 Configuration & Tag Information --------------------"); PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); PrintAndLogEx(NORMAL, " Safer key : %s", GetSaferStr(safer)); PrintAndLogEx(NORMAL, " reserved : %d", resv); PrintAndLogEx(NORMAL, " Data bit rate : %s", GetBitRateStr(dbr, extend)); - PrintAndLogEx(NORMAL, " eXtended mode : %s", (extend) ? "Yes - Warning":"No"); + PrintAndLogEx(NORMAL, " eXtended mode : %s", (extend) ? _YELLOW_("Yes - Warning") : "No"); PrintAndLogEx(NORMAL, " Modulation : %s", GetModulationStr(datamod)); PrintAndLogEx(NORMAL, " PSK clock frequency : %d", pskcf); - PrintAndLogEx(NORMAL, " AOR - Answer on Request : %s", (aor) ? "Yes":"No"); - PrintAndLogEx(NORMAL, " OTP - One Time Pad : %s", (otp) ? "Yes - Warning":"No" ); + PrintAndLogEx(NORMAL, " AOR - Answer on Request : %s", (aor) ? _GREEN_(Yes) : "No"); + PrintAndLogEx(NORMAL, " OTP - One Time Pad : %s", (otp) ? _YELLOW_(Yes - Warning) : "No" ); PrintAndLogEx(NORMAL, " Max block : %d", maxblk); - PrintAndLogEx(NORMAL, " Password mode : %s", (pwd) ? "Yes":"No"); - PrintAndLogEx(NORMAL, " Sequence Start Terminator : %s", (sst) ? "Yes":"No"); - PrintAndLogEx(NORMAL, " Fast Write : %s", (fw) ? "Yes":"No"); - PrintAndLogEx(NORMAL, " Inverse data : %s", (inv) ? "Yes":"No"); - PrintAndLogEx(NORMAL, " POR-Delay : %s", (por) ? "Yes":"No"); + PrintAndLogEx(NORMAL, " Password mode : %s", (pwd) ? _GREEN_(Yes) : "No"); + PrintAndLogEx(NORMAL, " Sequence Start Terminator : %s", (sst) ? _GREEN_(Yes) : "No"); + PrintAndLogEx(NORMAL, " Fast Write : %s", (fw) ? _GREEN_(Yes) : "No"); + PrintAndLogEx(NORMAL, " Inverse data : %s", (inv) ? _GREEN_(Yes) : "No"); + PrintAndLogEx(NORMAL, " POR-Delay : %s", (por) ? _GREEN_(Yes) : "No"); PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); PrintAndLogEx(NORMAL, " Raw Data - Page 0"); PrintAndLogEx(NORMAL, " Block 0 : 0x%08X %s", block0, sprint_bin(DemodBuffer + config.offset, 32) ); @@ -1581,7 +1582,7 @@ int CmdT55xxChkPwds(const char *Cmd) { FILE * f = fopen( filename , "r"); if ( !f ) { - PrintAndLogEx(WARNING, "File: %s: not found or locked.", filename); + PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); free(keyBlock); return 1; } diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index f9b77dad0..8b10dc6fe 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -595,7 +595,7 @@ int CmdSmartUpgrade(const char *Cmd) { // load file f = fopen(filename, "rb"); if ( !f ){ - PrintAndLogEx(FAILED, "File: %s: not found or locked.", filename); + PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); return 1; } From 38262389fc29dc4ca6bde51ef1f8db60a6098856 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 14:58:22 +0100 Subject: [PATCH 0567/1938] chg: colors --- client/cmdlft55xx.c | 51 ++++++++++++++++++++------------------------- 1 file changed, 23 insertions(+), 28 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 52240f0db..535b6fa1c 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -954,13 +954,11 @@ int CmdT55xxWakeUp(const char *Cmd) { uint32_t password = 0; uint8_t cmdp = 0; bool errors = false; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': - case 'H': return usage_t55xx_wakup(); case 'p': - case 'P': password = param_get32ex(Cmd, cmdp+1, 0, 16); cmdp += 2; errors = false; @@ -976,7 +974,7 @@ int CmdT55xxWakeUp(const char *Cmd) { UsbCommand c = {CMD_T55XX_WAKEUP, {password, 0, 0}}; clearCommandBuffer(); SendCommand(&c); - PrintAndLogEx(NORMAL, "Wake up command sent. Try read now"); + PrintAndLogEx(SUCCESS, "Wake up command sent. Try read now"); return 0; } @@ -990,30 +988,25 @@ int CmdT55xxWriteBlock(const char *Cmd) { bool testMode = false; bool errors = false; uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': - case 'H': return usage_t55xx_write(); case 'b': - case 'B': errors |= param_getdec(Cmd, cmdp+1, &block); cmdp += 2; break; case 'd': - case 'D': data = param_get32ex(Cmd, cmdp+1, 0, 16); gotdata = true; cmdp += 2; break; case 'p': - case 'P': password = param_get32ex(Cmd, cmdp+1, 0, 16); usepwd = true; cmdp += 2; break; case 't': - case 'T': testMode = true; cmdp++; break; @@ -1030,7 +1023,7 @@ int CmdT55xxWriteBlock(const char *Cmd) { if (errors || !gotdata) return usage_t55xx_write(); if (block > 7) { - PrintAndLogEx(NORMAL, "Block number must be between 0 and 7"); + PrintAndLogEx(WARNING, "Block number must be between 0 and 7"); return 0; } @@ -1042,7 +1035,7 @@ int CmdT55xxWriteBlock(const char *Cmd) { char pwdStr[16] = {0}; snprintf(pwdStr, sizeof(pwdStr), "pwd: 0x%08X", password); - PrintAndLogEx(NORMAL, "Writing page %d block: %02d data: 0x%08X %s", page1, block, data, (usepwd) ? pwdStr : "" ); + PrintAndLogEx(INFO, "Writing page %d block: %02d data: 0x%08X %s", page1, block, data, (usepwd) ? pwdStr : "" ); //Password mode if (usepwd) { @@ -1059,12 +1052,13 @@ int CmdT55xxWriteBlock(const char *Cmd) { } int CmdT55xxReadTrace(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - bool pwdmode = false; - uint32_t password = 0; - if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') return usage_t55xx_trace(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 1 || cmdp == 'h') return usage_t55xx_trace(); - if (strlen(Cmd)==0) { + bool pwdmode = false; + uint32_t password = 0; + + if (strlen(Cmd) == 0) { // sanity check. if (!SanityOfflineCheck(false)) return 1; @@ -1091,7 +1085,7 @@ int CmdT55xxReadTrace(const char *Cmd) { uint32_t hdr = PackBits(si, 9, DemodBuffer); si += 9; if (hdr != 0x1FF) { - PrintAndLogEx(NORMAL, "Invalid Q5 Trace data header (expected 0x1FF, found %X)", hdr); + PrintAndLogEx(FAILED, "Invalid Q5 Trace data header (expected 0x1FF, found %X)", hdr); return 1; } @@ -1130,7 +1124,7 @@ int CmdT55xxReadTrace(const char *Cmd) { data.acl = PackBits(si, 8, DemodBuffer); si += 8; if ( data.acl != 0xE0 ) { - PrintAndLogEx(NORMAL, "The modulation is most likely wrong since the ACL is not 0xE0. "); + PrintAndLogEx(FAILED, "The modulation is most likely wrong since the ACL is not 0xE0. "); return 1; } @@ -1227,11 +1221,11 @@ int CmdT55xxInfo(const char *Cmd){ */ bool pwdmode = false; uint32_t password = 0; - char cmdp = param_getchar(Cmd, 0); + char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 1 || cmdp == 'h' || cmdp == 'H') return usage_t55xx_info(); + if (strlen(Cmd) > 1 || cmdp == 'h') return usage_t55xx_info(); - if (strlen(Cmd)==0){ + if (strlen(Cmd) == 0) { // sanity check. if (!SanityOfflineCheck(false)) return 1; @@ -1264,7 +1258,8 @@ int CmdT55xxInfo(const char *Cmd){ uint32_t inv = PackBits(si, 1, DemodBuffer); si += 1; uint32_t por = PackBits(si, 1, DemodBuffer); si += 1; - if (config.Q5) PrintAndLogEx(NORMAL, _RED_(*** Warning ***) " Config Info read off a Q5 will not display as expected"); + if (config.Q5) + PrintAndLogEx(NORMAL, _RED_(*** Warning ***) " Config Info read off a Q5 will not display as expected"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "-- T55x7 Configuration & Tag Information --------------------"); @@ -1272,7 +1267,7 @@ int CmdT55xxInfo(const char *Cmd){ PrintAndLogEx(NORMAL, " Safer key : %s", GetSaferStr(safer)); PrintAndLogEx(NORMAL, " reserved : %d", resv); PrintAndLogEx(NORMAL, " Data bit rate : %s", GetBitRateStr(dbr, extend)); - PrintAndLogEx(NORMAL, " eXtended mode : %s", (extend) ? _YELLOW_("Yes - Warning") : "No"); + PrintAndLogEx(NORMAL, " eXtended mode : %s", (extend) ? _YELLOW_(Yes - Warning) : "No"); PrintAndLogEx(NORMAL, " Modulation : %s", GetModulationStr(datamod)); PrintAndLogEx(NORMAL, " PSK clock frequency : %d", pskcf); PrintAndLogEx(NORMAL, " AOR - Answer on Request : %s", (aor) ? _GREEN_(Yes) : "No"); @@ -1294,8 +1289,8 @@ int CmdT55xxDump(const char *Cmd){ uint32_t password = 0; bool override = false; - char cmdp = param_getchar(Cmd, 0); - if ( cmdp == 'h' || cmdp == 'H') return usage_t55xx_dump(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if ( cmdp == 'h') return usage_t55xx_dump(); bool usepwd = ( strlen(Cmd) > 0); if ( usepwd ){ From 7bbb2cdb9d55c04ba8fd84a1f4b736862ed0bb7d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 15:07:41 +0100 Subject: [PATCH 0568/1938] chg: 'lf t55xx chk' - logic params. chg: colors --- client/cmdlft55xx.c | 23 +++++++++++------------ 1 file changed, 11 insertions(+), 12 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 535b6fa1c..8d850f5d0 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1475,7 +1475,7 @@ int CmdT55xxWipe(const char *Cmd) { // Try with the default password to reset block 0 // With a pwd should work even if pwd bit not set - PrintAndLogEx(NORMAL, "\nBeginning Wipe of a T55xx tag (assuming the tag is not password protected)\n"); + PrintAndLogEx(INFO, "\nBeginning Wipe of a T55xx tag (assuming the tag is not password protected)\n"); if ( Q5 ) snprintf(ptrData,sizeof(writeData),"b 0 d 6001F004 p 0"); @@ -1490,7 +1490,7 @@ int CmdT55xxWipe(const char *Cmd) { if (!CmdT55xxWriteBlock(ptrData)) PrintAndLogEx(WARNING, "Error writing blk %d", blk); - memset(writeData,0x00, sizeof(writeData)); + memset(writeData, 0x00, sizeof(writeData)); } return 0; } @@ -1517,7 +1517,7 @@ int CmdT55xxChkPwds(const char *Cmd) { memset(line, 0, sizeof(line)); char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_t55xx_chk(); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_t55xx_chk(); /* if ( T55xxReadBlock(7, 0, 0, 0, 0) ) { @@ -1618,7 +1618,8 @@ int CmdT55xxChkPwds(const char *Cmd) { // PrintAndLogEx(NORMAL, "chk custom pwd[%2d] %08X", keycnt, bytes_to_num(keyBlock + 4 * keycnt, 4) ); keycnt++; memset(line, 0, sizeof(line)); - } + } + if (f) fclose(f); @@ -1731,7 +1732,7 @@ int CmdT55xxBruteForce(const char *Cmd) { } int tryOnePassword(uint32_t password) { - PrintAndLogEx(NORMAL, "Trying password %08x", password); + PrintAndLogEx(INFO, "Trying password %08x", password); if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, password)) { PrintAndLogEx(NORMAL, "Acquire data from device failed. Quitting"); return -1; @@ -1750,8 +1751,8 @@ int CmdT55xxRecoverPW(const char *Cmd) { uint32_t prev_password = 0xffffffff; uint32_t mask = 0x0; int found = 0; - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_t55xx_recoverpw(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h' ) return usage_t55xx_recoverpw(); orig_password = param_get32ex(Cmd, 0, 0x51243648, 16); //password used by handheld cloners @@ -1934,13 +1935,11 @@ int CmdT55xxDetectPage1(const char *Cmd){ uint32_t password = 0; uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': - case 'H': return usage_t55xx_detectP1(); case 'p': - case 'P': password = param_get32ex(Cmd, cmdp+1, 0, 16); usepwd = true; cmdp += 2; @@ -1963,7 +1962,7 @@ int CmdT55xxDetectPage1(const char *Cmd){ return false; } bool success = tryDetectP1(false); - if (success) PrintAndLogEx(NORMAL, "T55xx chip found!"); + if (success) PrintAndLogEx(SUCCESS, "T55xx chip found!"); return success; } From 730304ca926a538effa8e3c65269a371ebe84981 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 15:10:19 +0100 Subject: [PATCH 0569/1938] texts --- client/cmdlf.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index fc0aa5f6e..d51dfe7c7 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -819,14 +819,16 @@ int CheckChipType(bool getDeviceData) { //check for em4x05/em4x69 chips first uint32_t word = 0; if (EM4x05IsBlock0(&word)) { - PrintAndLogEx(NORMAL, "\nValid EM4x05/EM4x69 Chip Found\nTry lf em 4x05... commands\n"); + PrintAndLogEx(SUCCESS, "\nValid EM4x05/EM4x69 Chip Found"); + PrintAndLogEx(SUCCESS, "Try lf em 4x05... commands"); save_restoreGB(GRAPH_RESTORE); return 1; } //check for t55xx chip... if (tryDetectP1(true)) { - PrintAndLogEx(NORMAL, "\nValid T55xx Chip Found\nTry `lf t55xx` commands\n"); + PrintAndLogEx(SUCCESS, "\nValid T55xx Chip Found"); + PrintAndLogEx(SUCCESS, "Try `lf t55xx` commands"); save_restoreGB(GRAPH_RESTORE); return 1; } From 8551f811ca0f0dfa620f56f9aa6d804b3ccfc100 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 15:13:31 +0100 Subject: [PATCH 0570/1938] colors --- client/cmdlf.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index d51dfe7c7..f882a7ca3 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -858,9 +858,10 @@ int CmdLFfind(const char *Cmd) { return 0; } - PrintAndLogEx(NORMAL, "NOTE: some demods output possible binary\n if it finds something that looks like a tag"); - PrintAndLogEx(NORMAL, "False Positives ARE possible\n"); - PrintAndLogEx(NORMAL, "\nChecking for known tags:\n"); + PrintAndLogEx(INFO, "NOTE: some demods output possible binary"); + PrintAndLogEx(INFO, "if it finds something that looks like a tag"); + PrintAndLogEx(INFO, "False Positives " _YELLOW_(ARE) "possible\n"); + PrintAndLogEx(INFO, "\nChecking for known tags:\n"); // only run these tests if device is online if (isOnline) { From cc2c440683d4a842745dd77754bfa61841a4014a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 15:16:57 +0100 Subject: [PATCH 0571/1938] chg: 'lf search' - colors --- client/cmdlf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index f882a7ca3..e41f2d6aa 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -820,7 +820,7 @@ int CheckChipType(bool getDeviceData) { uint32_t word = 0; if (EM4x05IsBlock0(&word)) { PrintAndLogEx(SUCCESS, "\nValid EM4x05/EM4x69 Chip Found"); - PrintAndLogEx(SUCCESS, "Try lf em 4x05... commands"); + PrintAndLogEx(SUCCESS, "Try " _YELLOW_(`lf em 4x05`) " commands"); save_restoreGB(GRAPH_RESTORE); return 1; } @@ -828,7 +828,7 @@ int CheckChipType(bool getDeviceData) { //check for t55xx chip... if (tryDetectP1(true)) { PrintAndLogEx(SUCCESS, "\nValid T55xx Chip Found"); - PrintAndLogEx(SUCCESS, "Try `lf t55xx` commands"); + PrintAndLogEx(SUCCESS, "Try " _YELLOW_(`lf t55xx`)" commands"); save_restoreGB(GRAPH_RESTORE); return 1; } From 69b691494d5633a5e040656536599574bdc73e91 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 15:26:31 +0100 Subject: [PATCH 0572/1938] text --- client/cmdlfcotag.c | 2 +- client/cmdlffdx.c | 38 +++++++++++++++++++------------------- client/cmdlfguard.c | 8 ++++---- client/cmdlfviking.c | 4 ++-- 4 files changed, 26 insertions(+), 26 deletions(-) diff --git a/client/cmdlfcotag.c b/client/cmdlfcotag.c index dce160192..ff0167938 100644 --- a/client/cmdlfcotag.c +++ b/client/cmdlfcotag.c @@ -58,7 +58,7 @@ int CmdCOTAGDemod(const char *Cmd) { 0 1001 1100 1100 0001 1000 0101 0000 0000 100001010000000001111011100000011010000010000000000000000000000000000000000000000000000000000000100111001100000110000101000 1001 1100 1100 0001 10000101 */ - PrintAndLogEx(NORMAL, "COTAG Found: FC %u, CN: %u Raw: %08X%08X%08X%08X", fc, cn, raw1 ,raw2, raw3, raw4); + PrintAndLogEx(SUCCESS, "COTAG Found: FC %u, CN: %u Raw: %08X%08X%08X%08X", fc, cn, raw1 ,raw2, raw3, raw4); return 1; } diff --git a/client/cmdlffdx.c b/client/cmdlffdx.c index c2b54b497..8b67358ca 100644 --- a/client/cmdlffdx.c +++ b/client/cmdlffdx.c @@ -196,7 +196,7 @@ int CmdFDXBdemodBI(const char *Cmd){ PrintAndLogEx(DEBUG, "DEBUG: Error - FDXB error removeParity:: %d", size); return 0; } - PrintAndLogEx(NORMAL, "\nFDX-B / ISO 11784/5 Animal Tag ID Found:"); + PrintAndLogEx(SUCCESS, "\nFDX-B / ISO 11784/5 Animal Tag ID Found:"); //got a good demod uint64_t NationalCode = ((uint64_t)(bytebits_to_byteLSBF(BitStream+32,6)) << 32) | bytebits_to_byteLSBF(BitStream,32); @@ -211,17 +211,17 @@ int CmdFDXBdemodBI(const char *Cmd){ uint8_t raw[8]; num_to_bytes(rawid, 8, raw); - PrintAndLogEx(NORMAL, "Raw ID Hex: %s", sprint_hex(raw,8)); + PrintAndLogEx(SUCCESS, "Raw ID Hex: %s", sprint_hex(raw,8)); uint16_t calcCrc = crc16_kermit(raw, 8); - PrintAndLogEx(NORMAL, "Animal ID: %04u-%012" PRIu64, countryCode, NationalCode); - PrintAndLogEx(NORMAL, "National Code: %012" PRIu64, NationalCode); - PrintAndLogEx(NORMAL, "CountryCode: %04u", countryCode); + PrintAndLogEx(SUCCESS, "Animal ID: %04u-%012" PRIu64, countryCode, NationalCode); + PrintAndLogEx(SUCCESS, "National Code: %012" PRIu64, NationalCode); + PrintAndLogEx(SUCCESS, "CountryCode: %04u", countryCode); - PrintAndLogEx(NORMAL, "Reserved/RFU: %u", reservedCode); - PrintAndLogEx(NORMAL, "Animal Tag: %s", animalBit ? "True" : "False"); - PrintAndLogEx(NORMAL, "Has extended data: %s [0x%X]", dataBlockBit ? "True" : "False", extended); - PrintAndLogEx(NORMAL, "CRC: 0x%04X - [%04X] - %s", crc16, calcCrc, (calcCrc == crc16) ? "Passed" : "Failed"); + PrintAndLogEx(SUCCESS, "Reserved/RFU: %u", reservedCode); + PrintAndLogEx(SUCCESS, "Animal Tag: %s", animalBit ? "True" : "False"); + PrintAndLogEx(SUCCESS, "Has extended data: %s [0x%X]", dataBlockBit ? "True" : "False", extended); + PrintAndLogEx(SUCCESS, "CRC: 0x%04X - [%04X] - %s", crc16, calcCrc, (calcCrc == crc16) ? "Passed" : "Failed"); if (g_debugMode) { PrintAndLogEx(DEBUG, "Start marker %d; Size %d", preambleIndex, size); @@ -282,14 +282,14 @@ int CmdFdxDemod(const char *Cmd) { uint16_t calcCrc = crc16_kermit(raw, 8); - PrintAndLogEx(NORMAL, "\nFDX-B / ISO 11784/5 Animal Tag ID Found: Raw : %s", sprint_hex(raw, 8)); - PrintAndLogEx(NORMAL, "Animal ID %04u-%012" PRIu64, countryCode, NationalCode); - PrintAndLogEx(NORMAL, "National Code %012" PRIu64 " (0x%" PRIx64 ")", NationalCode, NationalCode); - PrintAndLogEx(NORMAL, "Country Code %04u", countryCode); - PrintAndLogEx(NORMAL, "Reserved/RFU %u (0x04%X)", reservedCode, reservedCode); - PrintAndLogEx(NORMAL, "Animal Tag %s", animalBit ? "True" : "False"); - PrintAndLogEx(NORMAL, "Has extended data %s [0x%X]", dataBlockBit ? "True" : "False", extended); - PrintAndLogEx(NORMAL, "CRC-16 0x%04X - 0x%04X [%s]", crc16, calcCrc, (calcCrc == crc16) ? "Ok" : "Failed"); + PrintAndLogEx(SUCCESS, "\nFDX-B / ISO 11784/5 Animal Tag ID Found: Raw : %s", sprint_hex(raw, 8)); + PrintAndLogEx(SUCCESS, "Animal ID %04u-%012" PRIu64, countryCode, NationalCode); + PrintAndLogEx(SUCCESS, "National Code %012" PRIu64 " (0x%" PRIx64 ")", NationalCode, NationalCode); + PrintAndLogEx(SUCCESS, "Country Code %04u", countryCode); + PrintAndLogEx(SUCCESS, "Reserved/RFU %u (0x04%X)", reservedCode, reservedCode); + PrintAndLogEx(SUCCESS, "Animal Tag %s", animalBit ? "True" : "False"); + PrintAndLogEx(SUCCESS, "Has extended data %s [0x%X]", dataBlockBit ? "True" : "False", extended); + PrintAndLogEx(SUCCESS, "CRC-16 0x%04X - 0x%04X [%s]", crc16, calcCrc, (calcCrc == crc16) ? "Ok" : "Failed"); if (g_debugMode) { PrintAndLogEx(DEBUG, "Start marker %d; Size %d", preambleIndex, size); @@ -341,7 +341,7 @@ int CmdFdxClone(const char *Cmd) { blocks[3] = bytebits_to_byte(bs + 64, 32); blocks[4] = bytebits_to_byte(bs + 96, 32); - PrintAndLogEx(NORMAL, "Preparing to clone FDX-B to T55x7 with animal ID: %04u-%"PRIu64, countryid, animalid); + PrintAndLogEx(INFO, "Preparing to clone FDX-B to T55x7 with animal ID: %04u-%"PRIu64, countryid, animalid); print_blocks(blocks, 5); UsbCommand resp; @@ -379,7 +379,7 @@ int CmdFdxSim(const char *Cmd) { arg1 = clk << 8 | encoding; arg2 = invert << 8 | separator; - PrintAndLogEx(NORMAL, "Simulating FDX-B animal ID: %04u-%"PRIu64, countryid, animalid); + PrintAndLogEx(SUCCESS, "Simulating FDX-B animal ID: %04u-%"PRIu64, countryid, animalid); UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; diff --git a/client/cmdlfguard.c b/client/cmdlfguard.c index afad96686..593dcf2b8 100644 --- a/client/cmdlfguard.c +++ b/client/cmdlfguard.c @@ -246,9 +246,9 @@ int CmdGuardDemod(const char *Cmd) { break; } if ( !unknown) - PrintAndLogEx(NORMAL, "G-Prox-II Found: Format Len: %ubit - FC: %u - Card: %u, Raw: %08x%08x%08x", fmtLen, FC, Card, raw1, raw2, raw3); + PrintAndLogEx(SUCCESS, "G-Prox-II Found: Format Len: %ubit - FC: %u - Card: %u, Raw: %08x%08x%08x", fmtLen, FC, Card, raw1, raw2, raw3); else - PrintAndLogEx(NORMAL, "Unknown G-Prox-II Fmt Found: Format Len: %u, Raw: %08x%08x%08x", fmtLen, raw1, raw2, raw3); + PrintAndLogEx(SUCCESS, "Unknown G-Prox-II Fmt Found: Format Len: %u, Raw: %08x%08x%08x", fmtLen, raw1, raw2, raw3); return 1; } @@ -290,7 +290,7 @@ int CmdGuardClone(const char *Cmd) { blocks[2] = bytebits_to_byte(bs + 32, 32); blocks[3] = bytebits_to_byte(bs + 64, 32); - PrintAndLogEx(NORMAL, "Preparing to clone Guardall to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber); + PrintAndLogEx(INFO, "Preparing to clone Guardall to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber); print_blocks(blocks, 4); UsbCommand resp; @@ -333,7 +333,7 @@ int CmdGuardSim(const char *Cmd) { return 1; } - PrintAndLogEx(NORMAL, "Simulating Guardall - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber ); + PrintAndLogEx(SUCCESS, "Simulating Guardall - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber ); uint64_t arg1, arg2; arg1 = (clock << 8) | encoding; diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c index 984e5ec83..5ead8ef03 100644 --- a/client/cmdlfviking.c +++ b/client/cmdlfviking.c @@ -118,7 +118,7 @@ int CmdVikingClone(const char *Cmd) { rawID = getVikingBits(id); - PrintAndLogEx(NORMAL, "Cloning - ID: %08X, Raw: %08X%08X",id,(uint32_t)(rawID >> 32),(uint32_t) (rawID & 0xFFFFFFFF)); + PrintAndLogEx(INFO, "Cloning - ID: %08X, Raw: %08X%08X",id,(uint32_t)(rawID >> 32),(uint32_t) (rawID & 0xFFFFFFFF)); UsbCommand c = {CMD_VIKING_CLONE_TAG, {rawID >> 32, rawID & 0xFFFFFFFF, Q5}}; clearCommandBuffer(); @@ -149,7 +149,7 @@ int CmdVikingSim(const char *Cmd) { arg1 = clk << 8 | encoding; arg2 = invert << 8 | separator; - PrintAndLogEx(NORMAL, "Simulating Viking - ID: %08X, Raw: %08X%08X",id,(uint32_t)(rawID >> 32),(uint32_t) (rawID & 0xFFFFFFFF)); + PrintAndLogEx(SUCCESS, "Simulating Viking - ID: %08X, Raw: %08X%08X",id,(uint32_t)(rawID >> 32),(uint32_t) (rawID & 0xFFFFFFFF)); UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; num_to_bytebits(rawID, size, c.d.asBytes); From 9f26c0d6b7faa9d733a2e1eb3990b19e95ee01fb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 15:29:28 +0100 Subject: [PATCH 0573/1938] text --- client/cmdlfkeri.c | 10 +++++----- client/cmdlfnoralsy.c | 10 +++++----- 2 files changed, 10 insertions(+), 10 deletions(-) diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 884e89933..560cd5c96 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -109,11 +109,11 @@ int CmdKeriDemod(const char *Cmd) { Might be a hash of FC & CN to generate Internal ID */ - PrintAndLogEx(NORMAL, "KERI Tag Found -- Raw: %08X%08X", raw1 ,raw2); - PrintAndLogEx(NORMAL, "KERI Internal ID: %u", ID); + PrintAndLogEx(SUCCESS, "KERI Tag Found -- Internal ID: %u", ID); + PrintAndLogEx(SUCCESS, "Raw: %08X%08X", raw1 ,raw2); if (invert){ - PrintAndLogEx(NORMAL, "Had to Invert - probably KERI"); + PrintAndLogEx(INFO, "Had to Invert - probably KERI"); for (size_t i = 0; i < size; i++) DemodBuffer[i] ^= 1; @@ -167,7 +167,7 @@ int CmdKeriClone(const char *Cmd) { blocks[1] = data >> 32; blocks[2] = data & 0xFFFFFFFF; - PrintAndLogEx(NORMAL, "Preparing to clone KERI to T55x7 with Internal Id: %u", internalid); + PrintAndLogEx(INFO, "Preparing to clone KERI to T55x7 with Internal Id: %u", internalid); print_blocks(blocks, 3); @@ -212,7 +212,7 @@ int CmdKeriSim(const char *Cmd) { arg1 = clk << 8 | carrier; arg2 = invert; - PrintAndLogEx(NORMAL, "Simulating KERI - Internal Id: %u", internalid); + PrintAndLogEx(SUCCESS, "Simulating KERI - Internal Id: %u", internalid); UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}}; memcpy(c.d.asBytes, bits, size); diff --git a/client/cmdlfnoralsy.c b/client/cmdlfnoralsy.c index bb28ad5e5..0f61e26ea 100644 --- a/client/cmdlfnoralsy.c +++ b/client/cmdlfnoralsy.c @@ -161,10 +161,10 @@ int CmdNoralsyDemod(const char *Cmd) { return 0; } - PrintAndLogEx(NORMAL, "Noralsy Tag Found: Card ID %u, Year: %u Raw: %08X%08X%08X", cardid, year, raw1 ,raw2, raw3); + PrintAndLogEx(SUCCESS, "Noralsy Tag Found: Card ID %u, Year: %u Raw: %08X%08X%08X", cardid, year, raw1 ,raw2, raw3); if (raw1 != 0xBB0214FF) { - PrintAndLogEx(NORMAL, "Unknown bits set in first block! Expected 0xBB0214FF, Found: 0x%08X", raw1); - PrintAndLogEx(NORMAL, "Please post this output in forum to further research on this format"); + PrintAndLogEx(WARNING, "Unknown bits set in first block! Expected 0xBB0214FF, Found: 0x%08X", raw1); + PrintAndLogEx(WARNING, "Please post this output in forum to further research on this format"); } return 1; } @@ -202,7 +202,7 @@ int CmdNoralsyClone(const char *Cmd) { blocks[2] = bytebits_to_byte(bits + 32, 32); blocks[3] = bytebits_to_byte(bits + 64, 32); - PrintAndLogEx(NORMAL, "Preparing to clone Noralsy to T55x7 with CardId: %u", id); + PrintAndLogEx(INFO, "Preparing to clone Noralsy to T55x7 with CardId: %u", id); print_blocks(blocks, 4); UsbCommand resp; @@ -247,7 +247,7 @@ int CmdNoralsySim(const char *Cmd) { return 1; } - PrintAndLogEx(NORMAL, "Simulating Noralsy - CardId: %u", id); + PrintAndLogEx(SUCCESS, "Simulating Noralsy - CardId: %u", id); UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; memcpy(c.d.asBytes, bs, size); From 49ba54419002f1914fc549ed4a2df50ba9896a0c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 15:33:34 +0100 Subject: [PATCH 0574/1938] fix: 'lf search' - indala wrong identified --- client/cmdlfindala.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index b49455e16..674931159 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -136,7 +136,7 @@ int CmdIndalaDemod(const char *Cmd) { idx = indala224decode(DemodBuffer, &size, &invert); if (idx < 0 || size != 224) { PrintAndLogEx(DEBUG, "DEBUG: Error - Indala wrong size, expected [64|224] got: %d (startindex %i)", size, idx); - return -1; + return 0; } } From 8ddf03b302e617636349f5754f23538b7f9d417b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 16:43:48 +0100 Subject: [PATCH 0575/1938] text --- client/cmdlfawid.c | 62 +++++++++++++++++++++------------------------- 1 file changed, 28 insertions(+), 34 deletions(-) diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index b17864dcf..61f33f636 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -101,7 +101,7 @@ static bool sendPing(void){ static bool sendTry(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint32_t delay, uint8_t *bits, size_t bs_len, bool verbose){ if ( verbose ) - PrintAndLogEx(NORMAL, "Trying FC: %u; CN: %u", fc, cn); + PrintAndLogEx(INFO, "Trying FC: %u; CN: %u", fc, cn); if ( !getAWIDBits(fmtlen, fc, cn, bits)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); @@ -171,7 +171,7 @@ int getAWIDBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *bits) { if (bitLen != 88) return 0; - PrintAndLogEx(NORMAL, "awid raw bits:\n %s \n", sprint_bin(bits, bitLen)); + PrintAndLogEx(SUCCESS, "awid raw bits:\n %s \n", sprint_bin(bits, bitLen)); return 1; } @@ -181,27 +181,27 @@ static void verify_values(uint8_t *fmtlen, uint32_t *fc, uint32_t *cn){ case 50: if ((*fc & 0xFFFF) != *fc) { *fc &= 0xFFFF; - PrintAndLogEx(NORMAL, "Facility-Code Truncated to 16-bits (AWID50): %u", *fc); + PrintAndLogEx(INFO, "Facility-Code Truncated to 16-bits (AWID50): %u", *fc); } break; case 37: if ((*fc & 0x1FFF) != *fc) { *fc &= 0x1FFF; - PrintAndLogEx(NORMAL, "Facility-Code Truncated to 13-bits (AWID37): %u", *fc); + PrintAndLogEx(INFO, "Facility-Code Truncated to 13-bits (AWID37): %u", *fc); } if ((*cn & 0x3FFFF) != *cn) { *cn &= 0x3FFFF; - PrintAndLogEx(NORMAL, "Card Number Truncated to 18-bits (AWID37): %u", *cn); + PrintAndLogEx(INFO, "Card Number Truncated to 18-bits (AWID37): %u", *cn); } break; case 34: if ((*fc & 0xFF) != *fc) { *fc &= 0xFF; - PrintAndLogEx(NORMAL, "Facility-Code Truncated to 8-bits (AWID34): %u", *fc); + PrintAndLogEx(INFO, "Facility-Code Truncated to 8-bits (AWID34): %u", *fc); } if ((*cn & 0xFFFFFF) != *cn) { *cn &= 0xFFFFFF; - PrintAndLogEx(NORMAL, "Card Number Truncated to 24-bits (AWID34): %u", *cn); + PrintAndLogEx(INFO, "Card Number Truncated to 24-bits (AWID34): %u", *cn); } break; case 26: @@ -209,11 +209,11 @@ static void verify_values(uint8_t *fmtlen, uint32_t *fc, uint32_t *cn){ *fmtlen = 26; if ((*fc & 0xFF) != *fc) { *fc &= 0xFF; - PrintAndLogEx(NORMAL, "Facility-Code Truncated to 8-bits (AWID26): %u", *fc); + PrintAndLogEx(INFO, "Facility-Code Truncated to 8-bits (AWID26): %u", *fc); } if ((*cn & 0xFFFF) != *cn) { *cn &= 0xFFFF; - PrintAndLogEx(NORMAL, "Card Number Truncated to 16-bits (AWID26): %u", *cn); + PrintAndLogEx(INFO, "Card Number Truncated to 16-bits (AWID26): %u", *cn); } break; } @@ -323,21 +323,21 @@ int CmdAWIDDemod(const char *Cmd) { fc = bytebits_to_byte(bits + 9, 8); cardnum = bytebits_to_byte(bits + 17, 16); code1 = bytebits_to_byte(bits + 8,fmtLen); - PrintAndLogEx(NORMAL, "AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi2, rawHi, rawLo); + PrintAndLogEx(SUCCESS, "AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi2, rawHi, rawLo); break; case 34: fc = bytebits_to_byte(bits + 9, 8); cardnum = bytebits_to_byte(bits + 17, 24); code1 = bytebits_to_byte(bits + 8, (fmtLen-32) ); code2 = bytebits_to_byte(bits + 8 + (fmtLen-32), 32); - PrintAndLogEx(NORMAL, "AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); + PrintAndLogEx(SUCCESS, "AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); break; case 37: fc = bytebits_to_byte(bits + 9, 13); cardnum = bytebits_to_byte(bits + 22, 18); code1 = bytebits_to_byte(bits + 8, (fmtLen-32) ); code2 = bytebits_to_byte(bits + 8 + (fmtLen-32), 32); - PrintAndLogEx(NORMAL, "AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); + PrintAndLogEx(SUCCESS, "AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); break; // case 40: // break; @@ -346,18 +346,18 @@ int CmdAWIDDemod(const char *Cmd) { cardnum = bytebits_to_byte(bits + 25, 32); code1 = bytebits_to_byte(bits + 8, (fmtLen-32) ); code2 = bytebits_to_byte(bits + 8 + (fmtLen-32), 32); - PrintAndLogEx(NORMAL, "AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); + PrintAndLogEx(SUCCESS, "AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); break; default: if (fmtLen > 32 ) { cardnum = bytebits_to_byte(bits + 8 + (fmtLen-17), 16); code1 = bytebits_to_byte(bits + 8, fmtLen-32); code2 = bytebits_to_byte(bits + 8 + (fmtLen-32), 32); - PrintAndLogEx(NORMAL, "AWID Found - BitLength: %d -unknown BitLength- (%u) - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo); + PrintAndLogEx(SUCCESS, "AWID Found - BitLength: %d -unknown BitLength- (%u) - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo); } else { cardnum = bytebits_to_byte(bits + 8 + (fmtLen-17), 16); code1 = bytebits_to_byte(bits + 8, fmtLen); - PrintAndLogEx(NORMAL, "AWID Found - BitLength: %d -unknown BitLength- (%u) - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo); + PrintAndLogEx(SUCCESS, "AWID Found - BitLength: %d -unknown BitLength- (%u) - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo); } break; } @@ -386,8 +386,8 @@ int CmdAWIDSim(const char *Cmd) { verify_values(&fmtlen, &fc, &cn); - PrintAndLogEx(NORMAL, "Emulating AWID %u -- FC: %u; CN: %u\n", fmtlen, fc, cn); - PrintAndLogEx(NORMAL, "Press pm3-button to abort simulation or run another command"); + PrintAndLogEx(SUCCESS, "Emulating AWID %u -- FC: %u; CN: %u\n", fmtlen, fc, cn); + PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation or run another command"); if (!getAWIDBits(fmtlen, fc, cn, bits)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); @@ -417,8 +417,8 @@ int CmdAWIDClone(const char *Cmd) { uint8_t *bs=bits; memset(bs,0,sizeof(bits)); - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_awid_clone(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_awid_clone(); fmtlen = param_get8(Cmd, 0); fc = param_get32ex(Cmd, 1, 0, 10); @@ -426,7 +426,7 @@ int CmdAWIDClone(const char *Cmd) { if ( !fc || !cn) return usage_lf_awid_clone(); - if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q') + if (tolower(param_getchar(Cmd, 3)) == 'q') //t5555 (Q5) BITRATE = (RF-2)/2 (iceman) blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(50) | 3< Date: Sun, 24 Feb 2019 16:45:18 +0100 Subject: [PATCH 0576/1938] text --- CHANGELOG.md | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0c7891297..a9ebb49b2 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,9 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Fix 'lf search' - false positive indala identification fixed (@iceman) - Add 'lf keri' - basic support for Keri tags (@iceman) - - Add 'hf mf list' - readded it again (@iceman) + - Add 'hf mf list' - re-added it again (@iceman) - Fix - A lot of bugfixes, like memory leaks (@iceman) - Change 'hf 14a antifuzz' - original implementation (@asfabw), reworked a bit - Fix 'hf mf fchk' (@iceman) From c310640b037e254a2b7d6eb53a1a1c3d376291cb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 16:47:43 +0100 Subject: [PATCH 0577/1938] fix: 'lf jabltron clone' - wrong number of blocks --- client/cmdlfjablotron.c | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/client/cmdlfjablotron.c b/client/cmdlfjablotron.c index 39cbc0651..541e7b31b 100644 --- a/client/cmdlfjablotron.c +++ b/client/cmdlfjablotron.c @@ -130,14 +130,14 @@ int CmdJablotronDemod(const char *Cmd) { PrintAndLogEx(SUCCESS, "Jablotron Tag Found: Card ID: %"PRIx64" :: Raw: %08X%08X", id, raw1, raw2); uint8_t chksum = raw2 & 0xFF; - PrintAndLogEx(NORMAL, "Checksum: %02X [%s]", + PrintAndLogEx(INFO, "Checksum: %02X [%s]", chksum, - (chksum == jablontron_chksum(DemodBuffer)) ? "OK":"FAIL" + (chksum == jablontron_chksum(DemodBuffer)) ? _GREEN_(OK) : _RED_(FAIL) ); id = DEC2BCD(id); // Printed format: 1410-nn-nnnn-nnnn - PrintAndLogEx(NORMAL, "Printed: 1410-%02X-%04X-%04X", + PrintAndLogEx(SUCCESS, "Printed: 1410-%02X-%04X-%04X", (uint8_t)(id >> 32) & 0xFF, (uint16_t)(id >> 16) & 0xFFFF, (uint16_t)id & 0xFFFF @@ -158,8 +158,8 @@ int CmdJablotronClone(const char *Cmd) { uint8_t bits[64]; memset(bits, 0, sizeof(bits)); - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_jablotron_clone(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_jablotron_clone(); fullcode = param_get64ex(Cmd, 0, 0, 16); @@ -170,7 +170,7 @@ int CmdJablotronClone(const char *Cmd) { // clearing the topbit needed for the preambl detection. if ((fullcode & 0x7FFFFFFFFF) != fullcode) { fullcode &= 0x7FFFFFFFFF; - PrintAndLogEx(NORMAL, "Card Number Truncated to 39bits: %"PRIx64, fullcode); + PrintAndLogEx(INFO, "Card Number Truncated to 39bits: %"PRIx64, fullcode); } if ( !getJablotronBits(fullcode, bits)) { @@ -181,13 +181,13 @@ int CmdJablotronClone(const char *Cmd) { blocks[1] = bytebits_to_byte(bits, 32); blocks[2] = bytebits_to_byte(bits + 32, 32); - PrintAndLogEx(NORMAL, "Preparing to clone Jablotron to T55x7 with FullCode: %"PRIx64, fullcode); + PrintAndLogEx(INFO, "Preparing to clone Jablotron to T55x7 with FullCode: %"PRIx64, fullcode); print_blocks(blocks, 3); UsbCommand resp; UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}}; - for (uint8_t i=0; i<4; i++) { + for (uint8_t i=0; i<3; i++) { c.arg[0] = blocks[i]; c.arg[1] = i; clearCommandBuffer(); @@ -203,15 +203,15 @@ int CmdJablotronClone(const char *Cmd) { int CmdJablotronSim(const char *Cmd) { uint64_t fullcode = 0; - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_jablotron_sim(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_jablotron_sim(); fullcode = param_get64ex(Cmd, 0, 0, 16); // clearing the topbit needed for the preambl detection. if ((fullcode & 0x7FFFFFFFFF) != fullcode) { fullcode &= 0x7FFFFFFFFF; - PrintAndLogEx(NORMAL, "Card Number Truncated to 39bits: %"PRIx64, fullcode); + PrintAndLogEx(INFO, "Card Number Truncated to 39bits: %"PRIx64, fullcode); } uint8_t clk = 64, encoding = 2, separator = 0, invert = 1; @@ -220,7 +220,7 @@ int CmdJablotronSim(const char *Cmd) { arg1 = clk << 8 | encoding; arg2 = invert << 8 | separator; - PrintAndLogEx(NORMAL, "Simulating Jablotron - FullCode: %"PRIx64, fullcode); + PrintAndLogEx(SUCCESS, "Simulating Jablotron - FullCode: %"PRIx64, fullcode); UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; getJablotronBits(fullcode, c.d.asBytes); From e0579223f0006547e80d80b3c34aaea2d4cd0234 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 16:48:54 +0100 Subject: [PATCH 0578/1938] text --- client/cmdlfpyramid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdlfpyramid.c b/client/cmdlfpyramid.c index 8e7dbd57f..1153fccc3 100644 --- a/client/cmdlfpyramid.c +++ b/client/cmdlfpyramid.c @@ -285,7 +285,7 @@ int CmdPyramidClone(const char *Cmd) { blocks[3] = bytebits_to_byte(bs + 64, 32); blocks[4] = bytebits_to_byte(bs + 96, 32); - PrintAndLogEx(NORMAL, "Preparing to clone Farpointe/Pyramid to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber); + PrintAndLogEx(INFO, "Preparing to clone Farpointe/Pyramid to T55x7 with Facility Code: %u, Card Number: %u", facilitycode, cardnumber); print_blocks(blocks, 5); UsbCommand resp; @@ -331,7 +331,7 @@ int CmdPyramidSim(const char *Cmd) { return 1; } - PrintAndLogEx(NORMAL, "Simulating Farpointe/Pyramid - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber ); + PrintAndLogEx(SUCCESS, "Simulating Farpointe/Pyramid - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber ); UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}}; memcpy(c.d.asBytes, bs, size); From f750ddb2c861a7e52bc499f4c948e9d1547ce76a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 17:06:46 +0100 Subject: [PATCH 0579/1938] text --- client/cmdlfindala.c | 24 +++++++++++++----------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 674931159..3148958ce 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -231,8 +231,8 @@ int CmdIndalaDemodAlt(const char *Cmd) { } if (rawbit > 0){ - PrintAndLogEx(NORMAL, "Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32); - PrintAndLogEx(NORMAL, "worst metric (0=best..7=worst): %d at pos %d", worst, worstPos); + PrintAndLogEx(INFO, "Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32); + PrintAndLogEx(INFO, "worst metric (0=best..7=worst): %d at pos %d", worst, worstPos); } else { return 0; } @@ -262,7 +262,7 @@ int CmdIndalaDemodAlt(const char *Cmd) { } if (start == rawbit - uidlen + 1) { - PrintAndLogEx(NORMAL, "nothing to wait for"); + PrintAndLogEx(FAILED, "nothing to wait for"); return 0; } @@ -288,7 +288,7 @@ int CmdIndalaDemodAlt(const char *Cmd) { showbits[bit] = '.' + bits[bit]; } showbits[bit+1]='\0'; - PrintAndLogEx(NORMAL, "Partial UID=%s", showbits); + PrintAndLogEx(SUCCESS, "Partial UID | %s", showbits); return 0; } else { for (bit = 0; bit < uidlen; bit++) { @@ -313,7 +313,7 @@ int CmdIndalaDemodAlt(const char *Cmd) { uid2 = (uid2<<1) | 1; } } - PrintAndLogEx(NORMAL, "UID=%s (%x%08x)", showbits, uid1, uid2); + PrintAndLogEx(SUCCESS, "UID | %s (%x%08x)", showbits, uid1, uid2); } else { uid3 = uid4 = uid5 = uid6 = uid7 = 0; @@ -331,7 +331,7 @@ int CmdIndalaDemodAlt(const char *Cmd) { else uid7 = (uid7<<1) | 1; } - PrintAndLogEx(NORMAL, "UID=%s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7); + PrintAndLogEx(SUCCESS, "UID | %s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7); } // Checking UID against next occurrences @@ -350,7 +350,7 @@ int CmdIndalaDemodAlt(const char *Cmd) { times += 1; } - PrintAndLogEx(NORMAL, "Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen); + PrintAndLogEx(DEBUG, "Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen); // Remodulating for tag cloning // HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod) @@ -409,8 +409,8 @@ int CmdIndalaSim(const char *Cmd) { // It has to send either 64bits (8bytes) or 224bits (28bytes). Zero padding needed if not. // lf simpsk 1 c 32 r 2 d 0102030405060708 -// PrintAndLogEx(NORMAL, "Emulating Indala UID: %u \n", cn); -// PrintAndLogEx(NORMAL, "Press pm3-button to abort simulation or run another command"); + PrintAndLogEx(SUCCESS, "Simulating Indala UID: %u \n", cn); + PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation or run another command"); UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}}; memcpy(c.d.asBytes, bits, size); @@ -427,6 +427,7 @@ int CmdIndalaClone(const char *Cmd) { uint32_t n = 0, i = 0; if (strchr(Cmd,'l') != 0) { + while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { uid1 = (uid1 << 4) | (uid2 >> 28); uid2 = (uid2 << 4) | (uid3 >> 28); @@ -436,7 +437,8 @@ int CmdIndalaClone(const char *Cmd) { uid6 = (uid6 << 4) | (uid7 >> 28); uid7 = (uid7 << 4) | (n & 0xf); } - PrintAndLogEx(NORMAL, "Cloning 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7); + + PrintAndLogEx(INFO, "Preparing to clone Indala 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7); c.cmd = CMD_INDALA_CLONE_TAG_L; c.d.asDwords[0] = uid1; c.d.asDwords[1] = uid2; @@ -450,7 +452,7 @@ int CmdIndalaClone(const char *Cmd) { uid1 = (uid1 << 4) | (uid2 >> 28); uid2 = (uid2 << 4) | (n & 0xf); } - PrintAndLogEx(NORMAL, "Cloning 64bit tag with UID %x%08x", uid1, uid2); + PrintAndLogEx(INFO, "Preparing to clone Indala 64bit tag with UID %x%08x", uid1, uid2); c.cmd = CMD_INDALA_CLONE_TAG; c.arg[0] = uid1; c.arg[1] = uid2; From 8b33d45016598fb7bb7ed803d268c7d615c3c6ca Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 17:08:58 +0100 Subject: [PATCH 0580/1938] fix --- client/cmdlfindala.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 3148958ce..1707895b0 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -409,7 +409,7 @@ int CmdIndalaSim(const char *Cmd) { // It has to send either 64bits (8bytes) or 224bits (28bytes). Zero padding needed if not. // lf simpsk 1 c 32 r 2 d 0102030405060708 - PrintAndLogEx(SUCCESS, "Simulating Indala UID: %u \n", cn); + PrintAndLogEx(SUCCESS, "Simulating Indala UID: %s", sprint_hex(hexuid, len)); PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation or run another command"); UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}}; From 7de440a8a0203d052878882409066e9df8e7db89 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 17:10:30 +0100 Subject: [PATCH 0581/1938] text --- client/cmdlfpresco.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/client/cmdlfpresco.c b/client/cmdlfpresco.c index 9c8037457..98df02fe5 100644 --- a/client/cmdlfpresco.c +++ b/client/cmdlfpresco.c @@ -12,11 +12,11 @@ static int CmdHelp(const char *Cmd); int usage_lf_presco_clone(void){ PrintAndLogEx(NORMAL, "clone a Presco tag to a T55x7 tag."); - PrintAndLogEx(NORMAL, "Usage: lf presco clone [h] d H "); + PrintAndLogEx(NORMAL, "Usage: lf presco clone [h] d c "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, " d : 9 digit presco card ID"); - PrintAndLogEx(NORMAL, " H : 8 digit hex card number"); + PrintAndLogEx(NORMAL, " c : 8 digit hex card number"); PrintAndLogEx(NORMAL, " : specify write to Q5 (t5555 instead of t55x7)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); @@ -29,11 +29,11 @@ int usage_lf_presco_sim(void) { PrintAndLogEx(NORMAL, "Simulation runs until the button is pressed or another USB command is issued."); PrintAndLogEx(NORMAL, "Per presco format, the card number is 9 digit number and can contain *# chars. Larger values are truncated."); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: lf presco sim [h] d or H "); + PrintAndLogEx(NORMAL, "Usage: lf presco sim [h] d or c "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, " d : 9 digit presco card number"); - PrintAndLogEx(NORMAL, " H : 8 digit hex card number"); + PrintAndLogEx(NORMAL, " c : 8 digit hex card number"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf presco sim d 123456789"); @@ -62,24 +62,22 @@ int GetWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode int stringlen = 0; memset(id, 0x00, sizeof(id)); - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return -1; - case 'H': + case 'c': hex = true; //get hex *fullcode = param_get32ex(Cmd, cmdp+1, 0, 16); cmdp+=2; break; - case 'D': case 'd': //param get string int param_getstr(const char *line, int paramnum, char * str) stringlen = param_getstr(Cmd, cmdp+1, id, sizeof(id)); if (stringlen < 2) return -1; cmdp += 2; break; - case 'Q': case 'q': *Q5 = true; cmdp++; @@ -136,7 +134,6 @@ int CmdPrescoDemod(const char *Cmd) { size_t size = DemodBufferLen; int ans = detectPresco(DemodBuffer, &size); if (ans < 0) { - if (ans == -1) PrintAndLogEx(DEBUG, "DEBUG: Error - Presco: too few bits found"); else if (ans == -2) @@ -163,7 +160,7 @@ int CmdPrescoDemod(const char *Cmd) { char cmd[12] = {0}; sprintf(cmd, "H %08X", cardid); GetWiegandFromPresco(cmd, &sitecode, &usercode, &fullcode, &Q5); - PrintAndLogEx(NORMAL, "SiteCode %u, UserCode %u, FullCode, %08X", sitecode, usercode, fullcode); + PrintAndLogEx(SUCCESS, "SiteCode %u, UserCode %u, FullCode, %08X", sitecode, usercode, fullcode); return 1; } @@ -190,12 +187,12 @@ int CmdPrescoClone(const char *Cmd) { if ((sitecode & 0xFF) != sitecode) { sitecode &= 0xFF; - PrintAndLogEx(NORMAL, "Facility-Code Truncated to 8-bits (Presco): %u", sitecode); + PrintAndLogEx(INFO, "Facility-Code Truncated to 8-bits (Presco): %u", sitecode); } if ((usercode & 0xFFFF) != usercode) { usercode &= 0xFFFF; - PrintAndLogEx(NORMAL, "Card Number Truncated to 16-bits (Presco): %u", usercode); + PrintAndLogEx(INFO, "Card Number Truncated to 16-bits (Presco): %u", usercode); } blocks[1] = 0x10D00000; //preamble @@ -203,7 +200,7 @@ int CmdPrescoClone(const char *Cmd) { blocks[3] = 0x00000000; blocks[4] = fullcode; - PrintAndLogEx(NORMAL, "Preparing to clone Presco to T55x7 with SiteCode: %u, UserCode: %u, FullCode: %08x", sitecode, usercode, fullcode); + PrintAndLogEx(INFO, "Preparing to clone Presco to T55x7 with SiteCode: %u, UserCode: %u, FullCode: %08x", sitecode, usercode, fullcode); print_blocks(blocks, 5); UsbCommand resp; @@ -236,7 +233,7 @@ int CmdPrescoSim(const char *Cmd) { arg1 = clk << 8 | encoding; arg2 = invert << 8 | separator; - PrintAndLogEx(NORMAL, "Simulating Presco - SiteCode: %u, UserCode: %u, FullCode: %08X",sitecode, usercode, fullcode); + PrintAndLogEx(SUCCESS, "Simulating Presco - SiteCode: %u, UserCode: %u, FullCode: %08X",sitecode, usercode, fullcode); UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; GetPrescoBits(fullcode, c.d.asBytes); From b22189b4159b9715f292a5accea761b2d3800fdc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 17:11:59 +0100 Subject: [PATCH 0582/1938] text --- client/cmdlfnedap.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/client/cmdlfnedap.c b/client/cmdlfnedap.c index 19e83d3cc..25f9b624b 100644 --- a/client/cmdlfnedap.c +++ b/client/cmdlfnedap.c @@ -194,15 +194,15 @@ int CmdLFNedapDemod(const char *Cmd) { chksum2 = bytebits_to_byte(DemodBuffer+110, 8); chksum2 |= bytebits_to_byte(DemodBuffer+119, 8) << 8; - PrintAndLogEx(NORMAL, "NEDAP ID Found - Raw: %08x%08x%08x%08x", raw[3], raw[2], raw[1], raw[0]); - PrintAndLogEx(NORMAL, " - UID: %06X", uid); - PrintAndLogEx(NORMAL, " - i: %04X", two); - PrintAndLogEx(NORMAL, " - Checksum2 %04X", chksum2); + PrintAndLogEx(SUCCESS, "NEDAP ID Found - Raw: %08x%08x%08x%08x", raw[3], raw[2], raw[1], raw[0]); + PrintAndLogEx(SUCCESS, " - UID: %06X", uid); + PrintAndLogEx(SUCCESS, " - i: %04X", two); + PrintAndLogEx(SUCCESS, " - Checksum2 %04X", chksum2); if (g_debugMode){ PrintAndLogEx(DEBUG, "DEBUG: idx: %d, Len: %d, Printing Demod Buffer:", idx, 128); printDemodBuff(); - PrintAndLogEx(NORMAL, "BIN:\n%s", sprint_bin_break( DemodBuffer, 128, 64) ); + PrintAndLogEx(DEBUG, "BIN:\n%s", sprint_bin_break( DemodBuffer, 128, 64) ); } return 1; @@ -268,7 +268,7 @@ int CmdLFNedapClone(const char *Cmd) { blocks[3] = bytebits_to_byte(bits + 64, 32); blocks[4] = bytebits_to_byte(bits + 96, 32); - PrintAndLogEx(NORMAL, "Preparing to clone NEDAP to T55x7 with card number: %u", cardnumber); + PrintAndLogEx(INFO, "Preparing to clone NEDAP to T55x7 with card number: %u", cardnumber); print_blocks(blocks, 5); UsbCommand resp; @@ -314,8 +314,8 @@ int CmdLFNedapSim(const char *Cmd) { return 1; } - PrintAndLogEx(NORMAL, "bin %s", sprint_bin_break(bs, 128, 32)); - PrintAndLogEx(NORMAL, "Simulating Nedap - CardNumber: %u", cardnumber ); + PrintAndLogEx(SUCCESS, "bin %s", sprint_bin_break(bs, 128, 32)); + PrintAndLogEx(SUCCESS, "Simulating Nedap - CardNumber: %u", cardnumber ); UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; memcpy(c.d.asBytes, bs, size); @@ -332,7 +332,7 @@ int CmdLFNedapChk(const char *Cmd){ len = ( len == 0 ) ? 5 : len>>1; - PrintAndLogEx(NORMAL, "Input: [%d] %s", len, sprint_hex(data, len)); + PrintAndLogEx(SUCCESS, "Input: [%d] %s", len, sprint_hex(data, len)); //uint8_t last = GetParity(data, EVEN, 62); //PrintAndLogEx(NORMAL, "TEST PARITY:: %d | %d ", DemodBuffer[62], last); @@ -367,7 +367,7 @@ int CmdLFNedapChk(const char *Cmd){ } } - PrintAndLogEx(NORMAL, "Nedap checksum: 0x%X", ((ch << 8) | cl) ); + PrintAndLogEx(SUCCESS, "Nedap checksum: 0x%X", ((ch << 8) | cl) ); return 0; } From 63659fd352c063e816e36a918040cc7193e2d32c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 17:22:03 +0100 Subject: [PATCH 0583/1938] text --- client/cmdlfguard.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/cmdlfguard.c b/client/cmdlfguard.c index 593dcf2b8..5707c78fb 100644 --- a/client/cmdlfguard.c +++ b/client/cmdlfguard.c @@ -107,21 +107,21 @@ int GetGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) { for (i = 0; i < 4; ++i) rawbytes[i+4] = bytebits_to_byte( pre + (i*8), 8); - if (g_debugMode) PrintAndLogEx(NORMAL, " WIE | %s\n", sprint_hex(rawbytes, sizeof(rawbytes))); + PrintAndLogEx(DEBUG, " WIE | %s\n", sprint_hex(rawbytes, sizeof(rawbytes))); // XOR (only works on wiegand stuff) for (i = 1; i < 12; ++i) rawbytes[i] ^= xorKey ; - if (g_debugMode) PrintAndLogEx(NORMAL, " XOR | %s \n", sprint_hex(rawbytes, sizeof(rawbytes))); + PrintAndLogEx(DEBUG, " XOR | %s \n", sprint_hex(rawbytes, sizeof(rawbytes))); // convert rawbytes to bits in pre for (i = 0; i < 12; ++i) num_to_bytebitsLSBF( rawbytes[i], 8, pre + (i*8)); - if (g_debugMode) PrintAndLogEx(NORMAL, "\n Raw | %s \n", sprint_hex(rawbytes, sizeof(rawbytes))); - if (g_debugMode) PrintAndLogEx(NORMAL, " Raw | %s\n", sprint_bin(pre, 64) ); + PrintAndLogEx(DEBUG, "\n Raw | %s \n", sprint_hex(rawbytes, sizeof(rawbytes))); + PrintAndLogEx(DEBUG, " Raw | %s\n", sprint_bin(pre, 64) ); // add spacer bit 0 every 4 bits, starting with index 0, // 12 bytes, 24 nibbles. 24+1 extra bites. 3bytes. ie 9bytes | 1byte xorkey, 8bytes rawdata (64bits, should be enough for a 40bit wiegand) @@ -135,7 +135,7 @@ int GetGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) { guardBits[4] = 1; guardBits[5] = 0; - if (g_debugMode) PrintAndLogEx(NORMAL, " FIN | %s\n", sprint_bin(guardBits, 96) ); + PrintAndLogEx(DEBUG, " FIN | %s\n", sprint_bin(guardBits, 96) ); return 1; } From 528ffd9e66f829a55a28170b6f64cd406c1bda8d Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 17:23:33 +0100 Subject: [PATCH 0584/1938] text --- client/cmdlfawid.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index 61f33f636..3cc56f56c 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -290,7 +290,7 @@ int CmdAWIDDemod(const char *Cmd) { uint32_t rawHi2 = bytebits_to_byte(bits + idx, 32); size = removeParity(bits, idx+8, 4, 1, 88); - if (size != 66){ + if (size != 66) { PrintAndLogEx(DEBUG, "DEBUG: Error - AWID at parity check-tag size does not match AWID format"); return 0; } @@ -386,7 +386,7 @@ int CmdAWIDSim(const char *Cmd) { verify_values(&fmtlen, &fc, &cn); - PrintAndLogEx(SUCCESS, "Emulating AWID %u -- FC: %u; CN: %u\n", fmtlen, fc, cn); + PrintAndLogEx(SUCCESS, "Simulating AWID %u -- FC: %u; CN: %u\n", fmtlen, fc, cn); PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation or run another command"); if (!getAWIDBits(fmtlen, fc, cn, bits)) { From 4b0f13a2e43bf62c22c500aa8518e2a16a4bb3a7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 17:25:40 +0100 Subject: [PATCH 0585/1938] text --- client/cmdlfio.c | 50 +++++++++++++++++++++++------------------------- 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/client/cmdlfio.c b/client/cmdlfio.c index d2cecec4b..61fe9d00d 100644 --- a/client/cmdlfio.c +++ b/client/cmdlfio.c @@ -86,15 +86,15 @@ int CmdIOProxDemod(const char *Cmd) { uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; size_t size = getFromGraphBuf(bits); if (size < 65) { - if (g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox not enough samples in GraphBuffer"); + PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox not enough samples in GraphBuffer"); return 0; } //get binary from fsk wave int waveIdx = 0; idx = detectIOProx(bits, &size, &waveIdx); - if (idx < 0){ - if (g_debugMode){ - if (idx == -1){ + if (idx < 0) { + if (g_debugMode) { + if (idx == -1) { PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox not enough samples"); } else if (idx == -2) { PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox just noise detected"); @@ -115,10 +115,10 @@ int CmdIOProxDemod(const char *Cmd) { setDemodBuf(bits, size, idx); setClockGrid(64, waveIdx + (idx*64)); - if (idx==0){ - if (g_debugMode){ + if (idx == 0) { + if (g_debugMode) { PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox data not found - FSK Bits: %d", size); - if (size > 92) PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, 92, 16)); + if (size > 92) PrintAndLogEx(DEBUG, "%s", sprint_bin_break(bits, 92, 16)); } return retval; } @@ -132,15 +132,13 @@ int CmdIOProxDemod(const char *Cmd) { // //XSF(version)facility:codeone+codetwo (raw) - if (g_debugMode) { - PrintAndLogEx(NORMAL, "%d%d%d%d%d%d%d%d %d", bits[idx], bits[idx+1], bits[idx+2], bits[idx+3], bits[idx+4], bits[idx+5], bits[idx+6], bits[idx+7], bits[idx+8]); - PrintAndLogEx(NORMAL, "%d%d%d%d%d%d%d%d %d", bits[idx+9], bits[idx+10], bits[idx+11],bits[idx+12],bits[idx+13],bits[idx+14],bits[idx+15],bits[idx+16],bits[idx+17]); - PrintAndLogEx(NORMAL, "%d%d%d%d%d%d%d%d %d facility", bits[idx+18], bits[idx+19], bits[idx+20],bits[idx+21],bits[idx+22],bits[idx+23],bits[idx+24],bits[idx+25],bits[idx+26]); - PrintAndLogEx(NORMAL, "%d%d%d%d%d%d%d%d %d version", bits[idx+27], bits[idx+28], bits[idx+29],bits[idx+30],bits[idx+31],bits[idx+32],bits[idx+33],bits[idx+34],bits[idx+35]); - PrintAndLogEx(NORMAL, "%d%d%d%d%d%d%d%d %d code1", bits[idx+36], bits[idx+37], bits[idx+38],bits[idx+39],bits[idx+40],bits[idx+41],bits[idx+42],bits[idx+43],bits[idx+44]); - PrintAndLogEx(NORMAL, "%d%d%d%d%d%d%d%d %d code2", bits[idx+45], bits[idx+46], bits[idx+47],bits[idx+48],bits[idx+49],bits[idx+50],bits[idx+51],bits[idx+52],bits[idx+53]); - PrintAndLogEx(NORMAL, "%d%d%d%d%d%d%d%d %d%d checksum", bits[idx+54],bits[idx+55],bits[idx+56],bits[idx+57],bits[idx+58],bits[idx+59],bits[idx+60],bits[idx+61],bits[idx+62],bits[idx+63]); - } + PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d", bits[idx], bits[idx+1], bits[idx+2], bits[idx+3], bits[idx+4], bits[idx+5], bits[idx+6], bits[idx+7], bits[idx+8]); + PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d", bits[idx+9], bits[idx+10], bits[idx+11],bits[idx+12],bits[idx+13],bits[idx+14],bits[idx+15],bits[idx+16],bits[idx+17]); + PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d facility", bits[idx+18], bits[idx+19], bits[idx+20],bits[idx+21],bits[idx+22],bits[idx+23],bits[idx+24],bits[idx+25],bits[idx+26]); + PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d version", bits[idx+27], bits[idx+28], bits[idx+29],bits[idx+30],bits[idx+31],bits[idx+32],bits[idx+33],bits[idx+34],bits[idx+35]); + PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d code1", bits[idx+36], bits[idx+37], bits[idx+38],bits[idx+39],bits[idx+40],bits[idx+41],bits[idx+42],bits[idx+43],bits[idx+44]); + PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d code2", bits[idx+45], bits[idx+46], bits[idx+47],bits[idx+48],bits[idx+49],bits[idx+50],bits[idx+51],bits[idx+52],bits[idx+53]); + PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d%d checksum", bits[idx+54],bits[idx+55],bits[idx+56],bits[idx+57],bits[idx+58],bits[idx+59],bits[idx+60],bits[idx+61],bits[idx+62],bits[idx+63]); uint32_t code = bytebits_to_byte(bits+idx,32); uint32_t code2 = bytebits_to_byte(bits+idx+32,32); @@ -163,13 +161,13 @@ int CmdIOProxDemod(const char *Cmd) { snprintf(crcStr, 3, "ok"); retval = 1; } else { - if (g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox crc failed"); + PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox crc failed"); snprintf(crcStr, sizeof(crcStr), "failed 0x%02X != 0x%02X", crc, calccrc); retval = 0; } - PrintAndLogEx(NORMAL, "IO Prox XSF(%02d)%02x:%05d (%08x%08x) [crc %s]", version, facilitycode, number, code, code2, crcStr); + PrintAndLogEx(SUCCESS, "IO Prox XSF(%02d)%02x:%05d (%08x%08x) [crc %s]", version, facilitycode, number, code, code2, crcStr); if (g_debugMode){ PrintAndLogEx(DEBUG, "DEBUG: IO prox idx: %d, Len: %d, Printing demod buffer:", idx, size); @@ -241,7 +239,7 @@ int getIOProxBits(uint8_t version, uint8_t fc, uint16_t cn, uint8_t *bits) { memcpy(bits, pre, sizeof(pre)); - PrintAndLogEx(NORMAL, "IO raw bits:\n %s \n", sprint_bin(bits, 64)); + PrintAndLogEx(SUCCESS, "IO raw bits:\n %s \n", sprint_bin(bits, 64)); return 1; } @@ -252,8 +250,8 @@ int CmdIOProxSim(const char *Cmd) { size_t size = sizeof(bits); memset(bits, 0x00, size); - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_io_sim(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_io_sim(); version = param_get8(Cmd, 0); fc = param_get8(Cmd, 1); @@ -263,7 +261,7 @@ int CmdIOProxSim(const char *Cmd) { if ((cn & 0xFFFF) != cn) { cn &= 0xFFFF; - PrintAndLogEx(NORMAL, "Card Number Truncated to 16-bits (IOProx): %u", cn); + PrintAndLogEx(INFO, "Card Number Truncated to 16-bits (IOProx): %u", cn); } // clock 64, FSK2a fcHIGH 10 | fcLOW 8 @@ -272,8 +270,8 @@ int CmdIOProxSim(const char *Cmd) { arg1 = high << 8 | low; arg2 = invert << 8 | clk; - PrintAndLogEx(NORMAL, "Emulating IOProx Version: %u FC: %u; CN: %u\n", version, fc, cn); - PrintAndLogEx(NORMAL, "Press pm3-button to abort simulation or run another command"); + PrintAndLogEx(SUCCESS, "Simulating IOProx version: %u FC: %u; CN: %u\n", version, fc, cn); + PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation or run another command"); if ( !getIOProxBits(version, fc, cn, bits)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); @@ -309,7 +307,7 @@ int CmdIOProxClone(const char *Cmd) { if ((cn & 0xFFFF) != cn) { cn &= 0xFFFF; - PrintAndLogEx(NORMAL, "Card Number Truncated to 16-bits (IOProx): %u", cn); + PrintAndLogEx(INFO, "Card Number Truncated to 16-bits (IOProx): %u", cn); } if ( !getIOProxBits(version, fc, cn, bits)) { @@ -323,7 +321,7 @@ int CmdIOProxClone(const char *Cmd) { blocks[1] = bytebits_to_byte(bits, 32); blocks[2] = bytebits_to_byte(bits + 32, 32); - PrintAndLogEx(NORMAL, "Preparing to clone IOProx to T55x7 with Version: %u FC: %u, CN: %u", version, fc, cn); + PrintAndLogEx(INFO, "Preparing to clone IOProx to T55x7 with Version: %u FC: %u, CN: %u", version, fc, cn); print_blocks(blocks, 3); //UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}}; From 92631bdfb407cbefba23cfe76fbf3a21294a3e66 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 17:25:47 +0100 Subject: [PATCH 0586/1938] text --- client/cmdlfem4x.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 97e0668cc..6d90e550f 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -443,14 +443,14 @@ int CmdEM410xSim(const char *Cmd) { uint8_t clock = 64; if (param_gethex(Cmd, 0, uid, 10)) { - PrintAndLogEx(NORMAL, "UID must include 10 HEX symbols"); + PrintAndLogEx(FAILED, "UID must include 10 HEX symbols"); return 0; } param_getdec(Cmd, 1, &clock); - PrintAndLogEx(NORMAL, "Starting simulating UID %02X%02X%02X%02X%02X clock: %d", uid[0],uid[1],uid[2],uid[3],uid[4],clock); - PrintAndLogEx(NORMAL, "Press pm3-button to abort simulation"); + PrintAndLogEx(SUCCESS, "Starting simulating UID %02X%02X%02X%02X%02X clock: %d", uid[0],uid[1],uid[2],uid[3],uid[4],clock); + PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation"); ConstructEM410xEmulGraph(Cmd, clock); @@ -508,7 +508,7 @@ int CmdEM410xBrute(const char *Cmd) { if( buf[0]=='#' ) continue; if (param_gethex(buf, 0, uid, 10)) { - PrintAndLogEx(NORMAL, "UIDs must include 10 HEX symbols"); + PrintAndLogEx(FAILED, "UIDs must include 10 HEX symbols"); free(uidBlock); fclose(f); return 1; @@ -535,11 +535,12 @@ int CmdEM410xBrute(const char *Cmd) { fclose(f); if (uidcnt == 0) { - PrintAndLogEx(NORMAL, "No UIDs found in file"); + PrintAndLogEx(FAILED, "No UIDs found in file"); free(uidBlock); return 1; } - PrintAndLogEx(NORMAL, "Loaded %d UIDs from %s, pause delay: %d ms", uidcnt, filename, delay); + + PrintAndLogEx(SUCCESS, "Loaded %d UIDs from %s, pause delay: %d ms", uidcnt, filename, delay); // loop for(uint32_t c = 0; c < uidcnt; ++c ) { @@ -599,7 +600,7 @@ int CmdEM410xWatchnSpoof(const char *Cmd) { // loops if the captured ID was in XL-format. CmdEM410xWatch(Cmd); - PrintAndLogEx(NORMAL, "# Replaying captured ID: %010" PRIx64 , g_em410xid); + PrintAndLogEx(SUCCESS, "# Replaying captured ID: %010" PRIx64 , g_em410xid); CmdLFaskSim(""); return 0; } @@ -645,17 +646,17 @@ int CmdEM410xWrite(const char *Cmd) { } if (card == 1) { - PrintAndLogEx(NORMAL, "Writing %s tag with UID 0x%010" PRIx64 " (clock rate: %d)", "T55x7", id, clock); + PrintAndLogEx(SUCCESS, "Writing %s tag with UID 0x%010" PRIx64 " (clock rate: %d)", "T55x7", id, clock); // NOTE: We really should pass the clock in as a separate argument, but to // provide for backwards-compatibility for older firmware, and to avoid // having to add another argument to CMD_EM410X_WRITE_TAG, we just store // the clock rate in bits 8-15 of the card value card = (card & 0xFF) | ((clock << 8) & 0xFF00); } else if (card == 0) { - PrintAndLogEx(NORMAL, "Writing %s tag with UID 0x%010" PRIx64, "T5555", id, clock); + PrintAndLogEx(SUCCESS, "Writing %s tag with UID 0x%010" PRIx64, "T5555", id, clock); card = (card & 0xFF) | ((clock << 8) & 0xFF00); } else { - PrintAndLogEx(WARNING, "Error! Bad card type selected.\n"); + PrintAndLogEx(FAILED, "Error! Bad card type selected.\n"); return 0; } From e2d253f641c3607a7a11bbc5e24797230c9551ba Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 17:25:55 +0100 Subject: [PATCH 0587/1938] text --- client/cmdlffdx.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdlffdx.c b/client/cmdlffdx.c index 8b67358ca..194bb7f32 100644 --- a/client/cmdlffdx.c +++ b/client/cmdlffdx.c @@ -82,11 +82,11 @@ int detectFDXB(uint8_t *dest, size_t *size) { static void verify_values(uint32_t countryid, uint64_t animalid){ if ((animalid & 0x3FFFFFFFFF) != animalid) { animalid &= 0x3FFFFFFFFF; - PrintAndLogEx(NORMAL, "Animal ID Truncated to 38bits: %"PRIx64, animalid); + PrintAndLogEx(INFO, "Animal ID Truncated to 38bits: %"PRIx64, animalid); } if ( (countryid & 0x3ff) != countryid ) { countryid &= 0x3ff; - PrintAndLogEx(NORMAL, "Country ID Truncated to 10bits: %03d", countryid); + PrintAndLogEx(INFO, "Country ID Truncated to 10bits: %03d", countryid); } } From 95f8a48b560dc3feea9cff08ee05501e1e0b24a0 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 17:28:54 +0100 Subject: [PATCH 0588/1938] text --- client/cmdlfhid.c | 34 ++++++++++++++-------------------- 1 file changed, 14 insertions(+), 20 deletions(-) diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index 7bc3bb9e9..7d1bda95c 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -106,7 +106,7 @@ static bool sendTry(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint32_t delay, ui // this should be optional. if ( verbose ) - PrintAndLogEx(NORMAL, "Trying FC: %u; CN: %u", fc, cn); + PrintAndLogEx(INFO, "Trying FC: %u; CN: %u", fc, cn); calcWiegand( fmtlen, fc, cn, bits); @@ -164,7 +164,7 @@ int CmdHIDDemod(const char *Cmd) { } if (hi2 != 0){ //extra large HID tags - PrintAndLogEx(NORMAL, "HID Prox TAG ID: %x%08x%08x (%u)", hi2, hi, lo, (lo>>1) & 0xFFFF); + PrintAndLogEx(SUCCESS, "HID Prox TAG ID: %x%08x%08x (%u)", hi2, hi, lo, (lo>>1) & 0xFFFF); } else { //standard HID tags <38 bits uint8_t fmtLen = 0; uint32_t cc = 0; @@ -209,9 +209,9 @@ int CmdHIDDemod(const char *Cmd) { } } if(fmtLen==32 && (lo & 0x40000000)){//if 32 bit and Kastle bit set - PrintAndLogEx(NORMAL, "HID Prox TAG (Kastle format) ID: %08x (%u) - Format Len: 32bit - CC: %u - FC: %u - Card: %u", lo, (lo >> 1) & 0xFFFF, cc, fc, cardnum); + PrintAndLogEx(SUCCESS, "HID Prox TAG (Kastle format) ID: %08x (%u) - Format Len: 32bit - CC: %u - FC: %u - Card: %u", lo, (lo >> 1) & 0xFFFF, cc, fc, cardnum); }else{ - PrintAndLogEx(NORMAL, "HID Prox TAG ID: %x%08x (%u) - Format Len: %ubit - FC: %u - Card: %u", hi, lo, (lo >> 1) & 0xFFFF, fmtLen, fc, cardnum); + PrintAndLogEx(SUCCESS, "HID Prox TAG ID: %x%08x (%u) - Format Len: %ubit - FC: %u - Card: %u", hi, lo, (lo >> 1) & 0xFFFF, fmtLen, fc, cardnum); } } @@ -244,16 +244,16 @@ int CmdHIDSim(const char *Cmd) { uint32_t hi = 0, lo = 0; uint32_t n = 0, i = 0; - uint8_t ctmp = param_getchar(Cmd, 0); - if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_hid_sim(); + uint8_t ctmp = tolower(param_getchar(Cmd, 0)); + if ( strlen(Cmd) == 0 || ctmp == 'h' ) return usage_lf_hid_sim(); while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { hi = (hi << 4) | (lo >> 28); lo = (lo << 4) | (n & 0xf); } - PrintAndLogEx(NORMAL, "Emulating tag with ID %x%08x", hi, lo); - PrintAndLogEx(NORMAL, "Press pm3-button to abort simulation"); + PrintAndLogEx(SUCCESS, "Simulating HID tag with ID %x%08x", hi, lo); + PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation"); UsbCommand c = {CMD_HID_SIM_TAG, {hi, lo, 0}}; clearCommandBuffer(); @@ -277,7 +277,7 @@ int CmdHIDClone(const char *Cmd) { lo = (lo << 4) | (n & 0xf); } - PrintAndLogEx(NORMAL, "Cloning tag with long ID %x%08x%08x", hi2, hi, lo); + PrintAndLogEx(INFO, "Preparing to clone HID tag with long ID %x%08x%08x", hi2, hi, lo); c.d.asBytes[0] = 1; } else { @@ -285,7 +285,7 @@ int CmdHIDClone(const char *Cmd) { hi = (hi << 4) | (lo >> 28); lo = (lo << 4) | (n & 0xf); } - PrintAndLogEx(NORMAL, "Cloning tag with ID %x%08x", hi, lo); + PrintAndLogEx(INFO, "Preparing to clone HID tag with ID %x%08x", hi, lo); hi2 = 0; c.d.asBytes[0] = 0; } @@ -492,33 +492,28 @@ int CmdHIDBrute(const char *Cmd){ memset(bits, 0, sizeof(bits)); uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': - case 'H': return usage_lf_hid_brute(); case 'f': - case 'F': fc = param_get32ex(Cmd ,cmdp+1, 0, 10); if ( !fc ) errors = true; cmdp += 2; break; case 'd': - case 'D': // delay between attemps, defaults to 1000ms. delay = param_get32ex(Cmd, cmdp+1, 1000, 10); cmdp += 2; break; case 'c': - case 'C': cn = param_get32ex(Cmd, cmdp+1, 0, 10); // truncate cardnumber. cn &= 0xFFFF; cmdp += 2; break; case 'a': - case 'A': fmtlen = param_get8(Cmd, cmdp+1); cmdp += 2; bool is_ftm_ok = false; @@ -532,7 +527,6 @@ int CmdHIDBrute(const char *Cmd){ errors = !is_ftm_ok; break; case 'v': - case 'V': verbose = true; cmdp++; break; @@ -545,8 +539,8 @@ int CmdHIDBrute(const char *Cmd){ if ( fc == 0 ) errors = true; if ( errors ) return usage_lf_hid_brute(); - PrintAndLogEx(NORMAL, "Brute-forcing HID reader"); - PrintAndLogEx(NORMAL, "Press pm3-button to abort simulation or run another command"); + PrintAndLogEx(INFO, "Brute-forcing HID reader"); + PrintAndLogEx(INFO, "Press pm3-button to abort simulation or run another command"); uint16_t up = cn; uint16_t down = cn; From 4b7f6089ae442c92a45cc600b19fa9ac7e7d74ed Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 17:30:05 +0100 Subject: [PATCH 0589/1938] text --- client/cmdlfsecurakey.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/cmdlfsecurakey.c b/client/cmdlfsecurakey.c index 793c30fce..64e491d7f 100644 --- a/client/cmdlfsecurakey.c +++ b/client/cmdlfsecurakey.c @@ -97,12 +97,12 @@ int CmdSecurakeyDemod(const char *Cmd) { // test parities - evenparity32 looks to add an even parity returns 0 if already even... bool parity = !evenparity32(lWiegand) && !oddparity32(rWiegand); - PrintAndLogEx(NORMAL, "Securakey Tag Found--BitLen: %u, Card ID: %u, FC: 0x%X, Raw: %08X%08X%08X", bitLen, cardid, fc, raw1 ,raw2, raw3); + PrintAndLogEx(SUCCESS, "Securakey Tag Found--BitLen: %u, Card ID: %u, FC: 0x%X, Raw: %08X%08X%08X", bitLen, cardid, fc, raw1 ,raw2, raw3); if (bitLen <= 32) - PrintAndLogEx(NORMAL, "Wiegand: %08X, Parity: %s", (lWiegand<<(bitLen/2)) | rWiegand, parity ? "Passed" : "Failed"); - PrintAndLogEx(NORMAL, "\nHow the FC translates to printed FC is unknown"); - PrintAndLogEx(NORMAL, "How the checksum is calculated is unknown"); - PrintAndLogEx(NORMAL, "Help the community identify this format further\n by sharing your tag on the pm3 forum or with forum members"); + PrintAndLogEx(SUCCESS, "Wiegand: %08X, Parity: %s", (lWiegand<<(bitLen/2)) | rWiegand, parity ? "Passed" : "Failed"); + PrintAndLogEx(INFO, "\nHow the FC translates to printed FC is unknown"); + PrintAndLogEx(INFO, "How the checksum is calculated is unknown"); + PrintAndLogEx(INFO, "Help the community identify this format further\n by sharing your tag on the pm3 forum or with forum members"); return 1; } From a47085a7b4461ff15119596474c69cce48eb5ae1 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 17:30:55 +0100 Subject: [PATCH 0590/1938] text --- client/cmdlfviking.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c index 5ead8ef03..33a5588d3 100644 --- a/client/cmdlfviking.c +++ b/client/cmdlfviking.c @@ -118,7 +118,7 @@ int CmdVikingClone(const char *Cmd) { rawID = getVikingBits(id); - PrintAndLogEx(INFO, "Cloning - ID: %08X, Raw: %08X%08X",id,(uint32_t)(rawID >> 32),(uint32_t) (rawID & 0xFFFFFFFF)); + PrintAndLogEx(INFO, "Preparing to clone Viking tag - ID: %08X, Raw: %08X%08X",id,(uint32_t)(rawID >> 32),(uint32_t) (rawID & 0xFFFFFFFF)); UsbCommand c = {CMD_VIKING_CLONE_TAG, {rawID >> 32, rawID & 0xFFFFFFFF, Q5}}; clearCommandBuffer(); From 7b9a5eb7e34ae992052f00e1f2a674d930cb833f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 17:32:01 +0100 Subject: [PATCH 0591/1938] text --- client/cmdlfvisa2000.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdlfvisa2000.c b/client/cmdlfvisa2000.c index 2736934af..02cd5392e 100644 --- a/client/cmdlfvisa2000.c +++ b/client/cmdlfvisa2000.c @@ -165,8 +165,8 @@ int CmdVisa2kClone(const char *Cmd) { uint64_t id = 0; uint32_t blocks[4] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_64 | T55x7_ST_TERMINATOR | 3 << T55x7_MAXBLOCK_SHIFT, BL0CK1, 0}; - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_visa2k_clone(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_visa2k_clone(); id = param_get32ex(Cmd, 0, 0, 10); @@ -210,7 +210,7 @@ int CmdVisa2kSim(const char *Cmd) { arg1 = clk << 8 | encoding; arg2 = invert << 8 | separator; - PrintAndLogEx(NORMAL, "Simulating Visa2000 - CardId: %u", id); + PrintAndLogEx(SUCCESS, "Simulating Visa2000 - CardId: %u", id); UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; From 6b1ae818a50c96be8109cade083dddcd001eb006 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 18:27:56 +0100 Subject: [PATCH 0592/1938] fix: bad break.. --- client/mifarehost.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/mifarehost.c b/client/mifarehost.c index 31ed8e39d..60f3eaa01 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -956,8 +956,8 @@ int detect_classic_nackbug(bool verbose){ if (verbose) { PrintAndLogEx(FAILED, "card random number generator seems to be based on the well-known generating polynomial"); PrintAndLogEx(NORMAL, "[- ]with 16 effective bits only, but shows unexpected behavior, try again."); - return 0; - } +x } + return 2; } case 2 : PrintAndLogEx(SUCCESS, "always leak NACK detected"); return 3; case 1 : PrintAndLogEx(SUCCESS, "NACK bug detected"); return 1; From 8e01c9899f4a12194c99e831cecc31f9c41654a4 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 18:31:59 +0100 Subject: [PATCH 0593/1938] aaaaaa --- client/mifarehost.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mifarehost.c b/client/mifarehost.c index 60f3eaa01..927fb7bc0 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -956,7 +956,7 @@ int detect_classic_nackbug(bool verbose){ if (verbose) { PrintAndLogEx(FAILED, "card random number generator seems to be based on the well-known generating polynomial"); PrintAndLogEx(NORMAL, "[- ]with 16 effective bits only, but shows unexpected behavior, try again."); -x } + } return 2; } case 2 : PrintAndLogEx(SUCCESS, "always leak NACK detected"); return 3; From 8512c0ea093976e13b62fe27cb4965c51a3fa8fc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 19:25:44 +0100 Subject: [PATCH 0594/1938] fix: mem leak --- uart/uart_posix.c | 1 + 1 file changed, 1 insertion(+) diff --git a/uart/uart_posix.c b/uart/uart_posix.c index e3d7753a9..c3ff7dcca 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -83,6 +83,7 @@ serial_port uart_open(const char* pcPortName) { if (addrstr == NULL) { printf("Error: strdup\n"); + free(sp); return INVALID_SERIAL_PORT; } From 01cf818e48296012f408f9c2f076a2a37c049344 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 19:32:14 +0100 Subject: [PATCH 0595/1938] remove a warning --- client/jansson/error.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/client/jansson/error.c b/client/jansson/error.c index b94b3a3a1..96b3b3fac 100644 --- a/client/jansson/error.c +++ b/client/jansson/error.c @@ -3,8 +3,7 @@ void jsonp_error_init(json_error_t *error, const char *source) { - if(error) - { + if (error) { error->text[0] = '\0'; error->line = -1; error->column = -1; @@ -20,13 +19,13 @@ void jsonp_error_set_source(json_error_t *error, const char *source) { size_t length; - if(!error || !source) + if (!error || !source) return; length = strlen(source); - if(length < JSON_ERROR_SOURCE_LENGTH) - strncpy(error->source, source, JSON_ERROR_SOURCE_LENGTH); - else { + if (length < JSON_ERROR_SOURCE_LENGTH) { + strncpy(error->source, source, length); + } else { size_t extra = length - JSON_ERROR_SOURCE_LENGTH + 4; memcpy(error->source, "...", 3); strncpy(error->source + 3, source + extra, length - extra + 1); @@ -38,7 +37,6 @@ void jsonp_error_set(json_error_t *error, int line, int column, const char *msg, ...) { va_list ap; - va_start(ap, msg); jsonp_error_vset(error, line, column, position, code, msg, ap); va_end(ap); @@ -48,10 +46,10 @@ void jsonp_error_vset(json_error_t *error, int line, int column, size_t position, enum json_error_code code, const char *msg, va_list ap) { - if(!error) + if (!error) return; - if(error->text[0] != '\0') { + if (error->text[0] != '\0') { /* error already set */ return; } From f58c47a7b83989655222ec70069fe5a0039807d2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 19:38:16 +0100 Subject: [PATCH 0596/1938] cleanup --- client/cmdhfmf.c | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 76f0fc2b6..f04105c01 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2239,11 +2239,7 @@ int CmdHF14AMfSniff(const char *Cmd){ bufsize = traceLen; memset(buf, 0x00, traceLen); } - if (bufPtr == NULL) { - PrintAndLogEx(FAILED, "Cannot allocate memory for trace"); - free(buf); - return 2; - } + // what happens if LEN is bigger then TRACELEN --iceman memcpy(bufPtr, resp.d.asBytes, len); bufPtr += len; From aaac99fdee55a49f79e3b90e99146783fb501b0c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 19:46:09 +0100 Subject: [PATCH 0597/1938] fix: 'hf mf csave' unused code --- client/cmdhfmf.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index f04105c01..c59dad769 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2749,8 +2749,11 @@ int CmdHF14AMfCLoad(const char *Cmd) { } } - if ( res ) + if ( res ) { + if ( data ) + free(data); return 1; + } // PrintAndLogEx(INFO, "DATA | %s", sprint_hex(data+1000, 24) ); @@ -2922,7 +2925,6 @@ int CmdHF14AMfCSave(const char *Cmd) { errors = true; break; } - if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; useuid = false; hasname = true; From a49b3763ddace55fee8b21339d1914645cfcddeb Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 19:50:05 +0100 Subject: [PATCH 0598/1938] fix: bad check --- client/cmdhf14b.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index 11b0aabb3..4109a999a 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -283,7 +283,7 @@ static bool get_14b_UID(iso14b_card_select_t *card) { } } // retry - if ( !retry ) + if ( retry <= 0 ) PrintAndLogEx(WARNING, "timeout while waiting for reply."); return false; From 47c808fd5cf4f5ce571f8792fbb297521c2a65a9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 19:50:24 +0100 Subject: [PATCH 0599/1938] fix: check return value --- client/fido/fidocore.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index f83e64944..49088ec28 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -347,8 +347,10 @@ bool CheckrpIdHash(json_t *json, uint8_t *hash) { uint8_t hash2[32] = {0}; JsonLoadStr(json, "$.RelyingPartyEntity.id", hashval); - sha256hash((uint8_t *)hashval, strlen(hashval), hash2); - + int res = sha256hash((uint8_t *)hashval, strlen(hashval), hash2); + if (res) + return false; + return !memcmp(hash, hash2, 32); } From c650c238569d5419d0484faf34ff3647b5dc7b0c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 19:57:57 +0100 Subject: [PATCH 0600/1938] fix: 'lf flexdemod' - bad types --- client/cmdlf.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index e41f2d6aa..f644fcc84 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -189,12 +189,15 @@ int CmdFlexdemod(const char *Cmd) { #define LONG_WAIT 100 int i, j, start, bit, sum, phase = 0; - uint8_t data[MAX_GRAPH_TRACE_LEN] = {0}; - size_t size = getFromGraphBuf(data); - if (size == 0) + int data[GraphTraceLen]; + memcpy(data, GraphBuffer, GraphTraceLen); + + if ( GraphTraceLen < 0 ) return 0; - for (i = 0; i < size; ++i) + size_t size = GraphTraceLen; + + for (i = 0; i < GraphTraceLen; ++i) data[i] = (data[i] < 0) ? -1 : 1; for (start = 0; start < size - LONG_WAIT; start++) { From 17fcd8c24bbd090760f33dca7c535967d4bf89d6 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 20:00:41 +0100 Subject: [PATCH 0601/1938] fix: possible bad null ref --- client/emv/emvjson.c | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/client/emv/emvjson.c b/client/emv/emvjson.c index 45eb1f430..fc10f255c 100644 --- a/client/emv/emvjson.c +++ b/client/emv/emvjson.c @@ -242,20 +242,20 @@ int JsonSaveTLVTree(json_t *root, json_t *elm, char *path, struct tlvdb *tlvdbel bool HexToBuffer(const char *errormsg, const char *hexvalue, uint8_t * buffer, size_t maxbufferlen, size_t *bufferlen) { int buflen = 0; - switch(param_gethex_to_eol(hexvalue, 0, buffer, maxbufferlen, &buflen)) { - case 1: - PrintAndLog("%s Invalid HEX value.", errormsg); - return false; - case 2: - PrintAndLog("%s Hex value too large.", errormsg); - return false; - case 3: - PrintAndLog("%s Hex value must have even number of digits.", errormsg); - return false; + switch (param_gethex_to_eol(hexvalue, 0, buffer, maxbufferlen, &buflen)) { + case 1: + PrintAndLog("%s Invalid HEX value.", errormsg); + return false; + case 2: + PrintAndLog("%s Hex value too large.", errormsg); + return false; + case 3: + PrintAndLog("%s Hex value must have even number of digits.", errormsg); + return false; } if (buflen > maxbufferlen) { - PrintAndLog("%s HEX length (%d) more than %d", errormsg, *bufferlen, maxbufferlen); + PrintAndLog("%s HEX length (%d) more than %d", errormsg, (bufferlen) ? *bufferlen : -1, maxbufferlen); return false; } From a0e061fcd10bd3a7e2d11da32ab2efc127d44b9b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 20:11:05 +0100 Subject: [PATCH 0602/1938] fix: rearrange it --- client/cmdlf.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index f644fcc84..240a1d402 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -186,15 +186,18 @@ int CmdLFCommandRead(const char *Cmd) { } int CmdFlexdemod(const char *Cmd) { -#define LONG_WAIT 100 + + if ( GraphTraceLen < 0 ) + return 0; + +#ifndef LONG_WAIT +#define LONG_WAIT 100 +#endif int i, j, start, bit, sum, phase = 0; int data[GraphTraceLen]; memcpy(data, GraphBuffer, GraphTraceLen); - if ( GraphTraceLen < 0 ) - return 0; - size_t size = GraphTraceLen; for (i = 0; i < GraphTraceLen; ++i) From 528e8fe3956b5f9863b2468b3ed9bbda37e7897b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 21:21:56 +0100 Subject: [PATCH 0603/1938] fix: clock can't be zero or negative --- client/graph.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/graph.c b/client/graph.c index 4346a8040..2b2884819 100644 --- a/client/graph.c +++ b/client/graph.c @@ -115,10 +115,13 @@ int GetAskClock(const char *str, bool printAns) { if (st == false) { idx = DetectASKClock(bits, size, &clock, 20); } - setClockGrid(clock, idx); + + if ( clock > 0 ) { + setClockGrid(clock, idx); + } // Only print this message if we're not looping something if (printAns || g_debugMode) - PrintAndLogEx(NORMAL, "Auto-detected clock rate: %d, Best Starting Position: %d", clock, idx); + PrintAndLogEx(DEBUG, "Auto-detected clock rate: %d, Best Starting Position: %d", clock, idx); return clock; } From f59e67c00cc8565b77844463b694728f32ef7e1f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 21:42:30 +0100 Subject: [PATCH 0604/1938] fix: possible overrun --- client/crypto/asn1dump.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/client/crypto/asn1dump.c b/client/crypto/asn1dump.c index 52814f22b..a0abdf3cf 100644 --- a/client/crypto/asn1dump.c +++ b/client/crypto/asn1dump.c @@ -237,10 +237,13 @@ static char *asn1_oid_description(const char *oid, bool with_group_desc) { static char res[300]; memset(res, 0x00, sizeof(res)); - strcpy(fname, get_my_executable_directory()); + size_t len = strlen(get_my_executable_directory()); + if ( len > 300 ) len = 299; + + strncpy(fname, get_my_executable_directory(), len); strcat(fname, "crypto/oids.json"); if (access(fname, F_OK) < 0) { - strcpy(fname, get_my_executable_directory()); + strncpy(fname, get_my_executable_directory(), len); strcat(fname, "oids.json"); if (access(fname, F_OK) < 0) { goto error; // file not found From 99dc51e005b3349a15dc0982619f1616ac943d28 Mon Sep 17 00:00:00 2001 From: vratiskol Date: Fri, 22 Feb 2019 13:21:58 +0100 Subject: [PATCH 0605/1938] Mem Leak --- armsrc/appmain.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 0bf9ccb9d..5002a7138 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -1253,11 +1253,11 @@ void UsbPacketReceived(uint8_t *packet, int len) { size_t size = MIN(USB_CMD_DATA_SIZE, len); - uint8_t *mem = BigBuf_malloc(size); - - if (!FlashInit()) { + if (!FlashInit()) { break; } + + uint8_t *mem = BigBuf_malloc(size); for(size_t i = 0; i < len; i += size) { len = MIN((len - i), size); @@ -1271,6 +1271,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { break; } } + BigBuf_free(); FlashStop(); LED_B_OFF(); break; From 898f2bea5b269c9b9d67f20ed5ff1d9c7da9de8c Mon Sep 17 00:00:00 2001 From: vratiskol Date: Fri, 22 Feb 2019 20:22:12 +0100 Subject: [PATCH 0606/1938] Crapto Clean Up Clean up comment code --- common/crapto1/crapto1.c | 41 +++++++--------------------------------- common/crapto1/crypto1.c | 19 ++----------------- 2 files changed, 9 insertions(+), 51 deletions(-) diff --git a/common/crapto1/crapto1.c b/common/crapto1/crapto1.c index af1ed8167..f0b37dbae 100644 --- a/common/crapto1/crapto1.c +++ b/common/crapto1/crapto1.c @@ -33,21 +33,6 @@ static void __attribute__((constructor)) fill_lut() #define filter(x) (filterlut[(x) & 0xfffff]) #endif -/** binsearch - * Binary search for the first occurence of *stop's MSB in sorted [start,stop] - */ -/* static inline uint32_t* binsearch(uint32_t *start, uint32_t *stop) -{ - uint32_t mid, val = *stop & 0xff000000; - while(start != stop) - if(start[mid = (stop - start) >> 1] > val) - stop = &start[mid]; - else - start += mid + 1; - - return start; -} - */ /** update_contribution * helper, calculates the partial linear feedback contributions and puts in MSB */ @@ -174,7 +159,7 @@ struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in) // allocate memory for out of place bucket_sort bucket_array_t bucket; - + for (uint32_t i = 0; i < 2; i++) { for (uint32_t j = 0; j <= 0xff; j++) { bucket[i][j].head = malloc(sizeof(uint32_t) << 14); @@ -311,7 +296,7 @@ uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb) int out; uint8_t ret; uint32_t t; - + s->odd &= 0xffffff; t = s->odd, s->odd = s->even, s->even = t; @@ -329,12 +314,6 @@ uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb) */ uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb) { - /* - int i, ret=0; - for (i = 7; i >= 0; --i) - ret |= lfsr_rollback_bit(s, BIT(in, i), fb) << i; -*/ -// unfold loop 20160112 uint8_t ret = 0; ret |= lfsr_rollback_bit(s, BIT(in, 7), fb) << 7; ret |= lfsr_rollback_bit(s, BIT(in, 6), fb) << 6; @@ -351,13 +330,7 @@ uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb) */ uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) { - /* - int i; - uint32_t ret = 0; - for (i = 31; i >= 0; --i) - ret |= lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24); -*/ -// unfold loop 20160112 + uint32_t ret = 0; ret |= lfsr_rollback_bit(s, BEBIT(in, 31), fb) << (31 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 30), fb) << (30 ^ 24); @@ -376,7 +349,7 @@ uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) ret |= lfsr_rollback_bit(s, BEBIT(in, 18), fb) << (18 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 17), fb) << (17 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 16), fb) << (16 ^ 24); - + ret |= lfsr_rollback_bit(s, BEBIT(in, 15), fb) << (15 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 14), fb) << (14 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 13), fb) << (13 ^ 24); @@ -385,7 +358,7 @@ uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) ret |= lfsr_rollback_bit(s, BEBIT(in, 10), fb) << (10 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 9), fb) << (9 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 8), fb) << (8 ^ 24); - + ret |= lfsr_rollback_bit(s, BEBIT(in, 7), fb) << (7 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 6), fb) << (6 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 5), fb) << (5 ^ 24); @@ -445,7 +418,7 @@ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) { uint32_t *candidates = calloc(4 << 10, sizeof(uint8_t)); if (!candidates) return 0; - + uint32_t c, entry; int size = 0, i, good; @@ -458,7 +431,7 @@ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) if (good) candidates[size++] = i; } - + candidates[size] = -1; return candidates; diff --git a/common/crapto1/crypto1.c b/common/crapto1/crypto1.c index bc0e7337a..034d92215 100644 --- a/common/crapto1/crypto1.c +++ b/common/crapto1/crypto1.c @@ -48,9 +48,8 @@ struct Crypto1State * crypto1_create(uint64_t key) if ( !s ) return NULL; s->odd = s->even = 0; - + int i; - //for(i = 47;s && i > 0; i -= 2) { for(i = 47; i > 0; i -= 2) { s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7); s->even = s->even << 1 | BIT(key, i ^ 7); @@ -89,13 +88,6 @@ uint8_t crypto1_bit(struct Crypto1State *s, uint8_t in, int is_encrypted) } uint8_t crypto1_byte(struct Crypto1State *s, uint8_t in, int is_encrypted) { - /* - uint8_t i, ret = 0; - - for (i = 0; i < 8; ++i) - ret |= crypto1_bit(s, BIT(in, i), is_encrypted) << i; - */ -// unfold loop 20161012 uint8_t ret = 0; ret |= crypto1_bit(s, BIT(in, 0), is_encrypted) << 0; ret |= crypto1_bit(s, BIT(in, 1), is_encrypted) << 1; @@ -109,13 +101,6 @@ uint8_t crypto1_byte(struct Crypto1State *s, uint8_t in, int is_encrypted) } uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) { - /* - uint32_t i, ret = 0; - - for (i = 0; i < 32; ++i) - ret |= crypto1_bit(s, BEBIT(in, i), is_encrypted) << (i ^ 24); -*/ -//unfold loop 2016012 uint32_t ret = 0; ret |= crypto1_bit(s, BEBIT(in, 0), is_encrypted) << (0 ^ 24); ret |= crypto1_bit(s, BEBIT(in, 1), is_encrypted) << (1 ^ 24); @@ -125,7 +110,7 @@ uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) ret |= crypto1_bit(s, BEBIT(in, 5), is_encrypted) << (5 ^ 24); ret |= crypto1_bit(s, BEBIT(in, 6), is_encrypted) << (6 ^ 24); ret |= crypto1_bit(s, BEBIT(in, 7), is_encrypted) << (7 ^ 24); - + ret |= crypto1_bit(s, BEBIT(in, 8), is_encrypted) << (8 ^ 24); ret |= crypto1_bit(s, BEBIT(in, 9), is_encrypted) << (9 ^ 24); ret |= crypto1_bit(s, BEBIT(in, 10), is_encrypted) << (10 ^ 24); From 157e08f51d7980ba208586398ae849aef036a81c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 22:17:36 +0100 Subject: [PATCH 0607/1938] fix: mem leaks --- client/emv/cmdemv.c | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 94df507de..52033afb4 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -266,9 +266,11 @@ int CmdEMVGPO(const char *cmd) { ParamLoadFromJson(tlvRoot); }; - pdol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x9f38, datalen, data), tlvRoot, 0x83); + struct tlvdb *tmp_ext = tlvdb_external(0x9f38, datalen, data); + pdol_data_tlv = dol_process((const struct tlv *)tmp_ext, tlvRoot, 0x83); if (!pdol_data_tlv){ PrintAndLogEx(ERR, "Can't create PDOL TLV."); + tlvdb_free(tmp_ext); tlvdb_free(tlvRoot); return 4; } @@ -446,9 +448,11 @@ int CmdEMVAC(const char *cmd) { ParamLoadFromJson(tlvRoot); }; - cdol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x8c, datalen, data), tlvRoot, 0x01); // 0x01 - dummy tag + struct tlvdb *tmp_ext = tlvdb_external(0x8c, datalen, data); + cdol_data_tlv = dol_process((const struct tlv *)tmp_ext, tlvRoot, 0x01); // 0x01 - dummy tag if (!cdol_data_tlv){ PrintAndLogEx(ERR, "Can't create CDOL TLV."); + tlvdb_free(tmp_ext); tlvdb_free(tlvRoot); return 4; } @@ -588,9 +592,11 @@ int CmdEMVInternalAuthenticate(const char *cmd) { ParamLoadFromJson(tlvRoot); }; - ddol_data_tlv = dol_process((const struct tlv *)tlvdb_external(0x9f49, datalen, data), tlvRoot, 0x01); // 0x01 - dummy tag + struct tlvdb *tmp_ext = tlvdb_external(0x9f49, datalen, data); + ddol_data_tlv = dol_process((const struct tlv *)tmp_ext, tlvRoot, 0x01); // 0x01 - dummy tag if (!ddol_data_tlv){ PrintAndLogEx(ERR, "Can't create DDOL TLV."); + tlvdb_free(tmp_ext); tlvdb_free(tlvRoot); return 4; } From da9c662b23c1da3bf4c9900ece9e2c641988af34 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 22:31:24 +0100 Subject: [PATCH 0608/1938] text --- client/cmdlffdx.c | 50 +++++++++++++++++++++++------------------------ 1 file changed, 24 insertions(+), 26 deletions(-) diff --git a/client/cmdlffdx.c b/client/cmdlffdx.c index 194bb7f32..647dfe04e 100644 --- a/client/cmdlffdx.c +++ b/client/cmdlffdx.c @@ -159,26 +159,24 @@ int getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t */ int CmdFDXBdemodBI(const char *Cmd){ - int invert = 1; - int clk = 32; - int errCnt = 0; - int offset = 0, maxErr = 0; - uint8_t BitStream[MAX_DEMOD_BUF_LEN]; - size_t size = getFromGraphBuf(BitStream); + int clk = 32; + int invert = 1, errCnt = 0, offset = 0, maxErr = 0; + uint8_t bs[MAX_DEMOD_BUF_LEN]; + size_t size = getFromGraphBuf(bs); - errCnt = askdemod(BitStream, &size, &clk, &invert, maxErr, 0, 0); + errCnt = askdemod(bs, &size, &clk, &invert, maxErr, 0, 0); if ( errCnt < 0 || errCnt > maxErr ) { PrintAndLogEx(DEBUG, "DEBUG: Error - FDXB no data or error found %d, clock: %d", errCnt, clk); return 0; } - errCnt = BiphaseRawDecode(BitStream, &size, &offset, 1); + errCnt = BiphaseRawDecode(bs, &size, &offset, 1); if (errCnt < 0 || errCnt > maxErr ) { PrintAndLogEx(DEBUG, "DEBUG: Error - FDXB BiphaseRawDecode: %d", errCnt); return 0; } - int preambleIndex = detectFDXB(BitStream, &size); + int preambleIndex = detectFDXB(bs, &size); if (preambleIndex < 0){ PrintAndLogEx(DEBUG, "DEBUG: Error - FDXB preamble not found :: %d",preambleIndex); return 0; @@ -188,10 +186,10 @@ int CmdFDXBdemodBI(const char *Cmd){ return 0; } - setDemodBuf(BitStream, 128, preambleIndex); + setDemodBuf(bs, 128, preambleIndex); // remove marker bits (1's every 9th digit after preamble) (pType = 2) - size = removeParity(BitStream, preambleIndex + 11, 9, 2, 117); + size = removeParity(bs, preambleIndex + 11, 9, 2, 117); if ( size != 104 ) { PrintAndLogEx(DEBUG, "DEBUG: Error - FDXB error removeParity:: %d", size); return 0; @@ -199,15 +197,15 @@ int CmdFDXBdemodBI(const char *Cmd){ PrintAndLogEx(SUCCESS, "\nFDX-B / ISO 11784/5 Animal Tag ID Found:"); //got a good demod - uint64_t NationalCode = ((uint64_t)(bytebits_to_byteLSBF(BitStream+32,6)) << 32) | bytebits_to_byteLSBF(BitStream,32); - uint32_t countryCode = bytebits_to_byteLSBF(BitStream+38,10); - uint8_t dataBlockBit = BitStream[48]; - uint32_t reservedCode = bytebits_to_byteLSBF(BitStream+49,14); - uint8_t animalBit = BitStream[63]; - uint32_t crc16 = bytebits_to_byteLSBF(BitStream+64,16); - uint32_t extended = bytebits_to_byteLSBF(BitStream+80,24); + uint64_t NationalCode = ((uint64_t)(bytebits_to_byteLSBF(bs+32, 6)) << 32) | bytebits_to_byteLSBF(bs, 32); + uint32_t countryCode = bytebits_to_byteLSBF(bs+38, 10); + uint8_t dataBlockBit = bs[48]; + uint32_t reservedCode = bytebits_to_byteLSBF(bs+49, 14); + uint8_t animalBit = bs[63]; + uint32_t crc16 = bytebits_to_byteLSBF(bs+64, 16); + uint32_t extended = bytebits_to_byteLSBF(bs+80, 24); - uint64_t rawid = ((uint64_t)bytebits_to_byte(BitStream,32)<<32) | bytebits_to_byte(BitStream+32,32); + uint64_t rawid = ((uint64_t)bytebits_to_byte(bs, 32) << 32) | bytebits_to_byte(bs+32, 32); uint8_t raw[8]; num_to_bytes(rawid, 8, raw); @@ -219,13 +217,13 @@ int CmdFDXBdemodBI(const char *Cmd){ PrintAndLogEx(SUCCESS, "CountryCode: %04u", countryCode); PrintAndLogEx(SUCCESS, "Reserved/RFU: %u", reservedCode); - PrintAndLogEx(SUCCESS, "Animal Tag: %s", animalBit ? "True" : "False"); - PrintAndLogEx(SUCCESS, "Has extended data: %s [0x%X]", dataBlockBit ? "True" : "False", extended); - PrintAndLogEx(SUCCESS, "CRC: 0x%04X - [%04X] - %s", crc16, calcCrc, (calcCrc == crc16) ? "Passed" : "Failed"); + PrintAndLogEx(SUCCESS, "Animal Tag: %s", animalBit ? _YELLOW_(True) : "False"); + PrintAndLogEx(SUCCESS, "Has extended data: %s [0x%X]", dataBlockBit ? _YELLOW_(True) : "False", extended); + PrintAndLogEx(SUCCESS, "CRC: 0x%04X - [%04X] - %s", crc16, calcCrc, (calcCrc == crc16) ? _GREEN_(Passed) : "Failed"); if (g_debugMode) { PrintAndLogEx(DEBUG, "Start marker %d; Size %d", preambleIndex, size); - char *bin = sprint_bin_break(BitStream,size,16); + char *bin = sprint_bin_break(bs, size, 16); PrintAndLogEx(DEBUG, "DEBUG BinStream:\n%s",bin); } return 1; @@ -287,9 +285,9 @@ int CmdFdxDemod(const char *Cmd) { PrintAndLogEx(SUCCESS, "National Code %012" PRIu64 " (0x%" PRIx64 ")", NationalCode, NationalCode); PrintAndLogEx(SUCCESS, "Country Code %04u", countryCode); PrintAndLogEx(SUCCESS, "Reserved/RFU %u (0x04%X)", reservedCode, reservedCode); - PrintAndLogEx(SUCCESS, "Animal Tag %s", animalBit ? "True" : "False"); - PrintAndLogEx(SUCCESS, "Has extended data %s [0x%X]", dataBlockBit ? "True" : "False", extended); - PrintAndLogEx(SUCCESS, "CRC-16 0x%04X - 0x%04X [%s]", crc16, calcCrc, (calcCrc == crc16) ? "Ok" : "Failed"); + PrintAndLogEx(SUCCESS, "Animal Tag %s", animalBit ? _YELLOW_(True) : "False"); + PrintAndLogEx(SUCCESS, "Has extended data %s [0x%X]", dataBlockBit ? _YELLOW_(True) : "False", extended); + PrintAndLogEx(SUCCESS, "CRC-16 0x%04X - 0x%04X [%s]", crc16, calcCrc, (calcCrc == crc16) ? _GREEN_(Ok) : _RED_(Failed); if (g_debugMode) { PrintAndLogEx(DEBUG, "Start marker %d; Size %d", preambleIndex, size); From 34a17f842dd90a3726f953ecde95d63c2066f714 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 22:34:14 +0100 Subject: [PATCH 0609/1938] fix --- client/cmdlffdx.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlffdx.c b/client/cmdlffdx.c index 647dfe04e..4f867b038 100644 --- a/client/cmdlffdx.c +++ b/client/cmdlffdx.c @@ -287,7 +287,7 @@ int CmdFdxDemod(const char *Cmd) { PrintAndLogEx(SUCCESS, "Reserved/RFU %u (0x04%X)", reservedCode, reservedCode); PrintAndLogEx(SUCCESS, "Animal Tag %s", animalBit ? _YELLOW_(True) : "False"); PrintAndLogEx(SUCCESS, "Has extended data %s [0x%X]", dataBlockBit ? _YELLOW_(True) : "False", extended); - PrintAndLogEx(SUCCESS, "CRC-16 0x%04X - 0x%04X [%s]", crc16, calcCrc, (calcCrc == crc16) ? _GREEN_(Ok) : _RED_(Failed); + PrintAndLogEx(SUCCESS, "CRC-16 0x%04X - 0x%04X [%s]", crc16, calcCrc, (calcCrc == crc16) ? _GREEN_(Ok) : "Failed"); if (g_debugMode) { PrintAndLogEx(DEBUG, "Start marker %d; Size %d", preambleIndex, size); From 2e3694aa3b44cbc311159730a52b7793b684faf8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 23:40:11 +0100 Subject: [PATCH 0610/1938] fix: 'trace list' - missing break --- client/cmdtrace.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/cmdtrace.c b/client/cmdtrace.c index 56f97ca1d..cf55970b0 100644 --- a/client/cmdtrace.c +++ b/client/cmdtrace.c @@ -165,7 +165,8 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui crcStatus = iso14443B_CRC_check(frame, data_len); break; case PROTO_MIFARE: - crcStatus = mifare_CRC_check(isResponse, frame, data_len); + crcStatus = mifare_CRC_check(isResponse, frame, data_len); + break; case ISO_14443A: case MFDES: crcStatus = iso14443A_CRC_check(isResponse, frame, data_len); @@ -288,6 +289,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui void printFelica(uint16_t traceLen, uint8_t *trace) { + PrintAndLogEx(NORMAL, "ISO18092 / FeliCa - Timings are not as accurate"); PrintAndLogEx(NORMAL, " Gap | Src | Data | CRC | Annotation |"); PrintAndLogEx(NORMAL, "--------|-----|---------------------------------|----------|-------------------|"); uint16_t tracepos = 0; @@ -511,8 +513,8 @@ int CmdTraceList(const char *Cmd) { } } - PrintAndLogEx(NORMAL, "Recorded Activity (TraceLen = %d bytes)", traceLen); - PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(SUCCESS, "Recorded Activity (TraceLen = %d bytes)", traceLen); + PrintAndLogEx(INFO, ""); if (protocol == FELICA) { printFelica(traceLen, trace); } else { @@ -526,8 +528,6 @@ int CmdTraceList(const char *Cmd) { " Tag Mode: Timings are in sub carrier periods (1/212 kHz == 4.7us)"); if ( protocol == ISO_15693 ) PrintAndLogEx(NORMAL, "ISO15693 - Timings are not as accurate"); - if ( protocol == FELICA ) - PrintAndLogEx(NORMAL, "ISO18092 / FeliCa - Timings are not as accurate"); if ( protocol == ISO_7816_4 ) PrintAndLogEx(NORMAL, "ISO7816-4 / Smartcard - Timings N/A yet"); From 3d84e4dc03f96e477bed27b996b502e097eaebd2 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 23:43:35 +0100 Subject: [PATCH 0611/1938] fix: dead code --- client/cmdlft55xx.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 8d850f5d0..3c7547e34 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1701,7 +1701,7 @@ int CmdT55xxBruteForce(const char *Cmd) { PrintAndLogEx(INFO, "Search password range [%08X -> %08X]", start_password, end_password); - while ((!found) || (curr <= end_password)){ + while ( !found || (curr <= end_password)){ printf("."); fflush(stdout); @@ -1713,9 +1713,9 @@ int CmdT55xxBruteForce(const char *Cmd) { PrintAndLogEx(WARNING, "Aquireing data from device failed. Quitting"); return 0; } + found = tryDetectModulation(); - - if (found) break; + ++curr; } From 0803e532ccdaba7c7b2f89abe62f0072cb1abe7e Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 23:51:23 +0100 Subject: [PATCH 0612/1938] fix: 'hf felica list' - string overflows --- client/cmdhffelica.c | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index acfc68cf2..42c56d900 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -253,7 +253,7 @@ uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) { char line[110] = {0}; for (int j = 0; j < 16; j++) { - snprintf(line+( j * 4),110, "%02x ", trace[j+3]); + snprintf(line + (j * 4), sizeof(line) - 1 - (j*4) , "%02x ", trace[j+3]); } PrintAndLogEx(NORMAL, "block number %02x, status: %02x %02x",blocknum,status1, status2); @@ -277,7 +277,7 @@ uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) { uint32_t regB = trace[7] | trace[8] << 8 | trace[9] << 16 | trace[10] << 24; line[0] = 0; for (int j = 0; j < 8; j++) - snprintf(line+( j * 2),110, "%02x", trace[j+11]); + snprintf(line+( j * 2), sizeof(line)-1-(j*2), "%02x", trace[j+11]); PrintAndLogEx(NORMAL, "REG: regA: %d regB: %d regC: %s ", regA, regB, line); } break; @@ -287,10 +287,10 @@ uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) { char idd[20]; char idm[20]; for (int j = 0; j < 8; j++) - snprintf(idd+( j * 2),20, "%02x", trace[j+3]); + snprintf(idd + (j * 2), sizeof(idd) - 1 - (j*2), "%02x", trace[j+3]); for (int j = 0; j < 6; j++) - snprintf(idm+( j * 2),20, "%02x", trace[j+13]); + snprintf(idm + (j * 2), sizeof(idm) - 1 - (j*2), "%02x", trace[j+13]); PrintAndLogEx(NORMAL, "ID Block, IDd: 0x%s DFC: 0x%02x%02x Arb: %s ", idd, trace[11], trace [12], idm); } From 142b3d8de52f8c7b38c27d62edfdc22c93c129d5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 23:54:24 +0100 Subject: [PATCH 0613/1938] fix: assign --- client/loclass/ikeys.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/loclass/ikeys.c b/client/loclass/ikeys.c index 16b5513b7..c1265dc4d 100644 --- a/client/loclass/ikeys.c +++ b/client/loclass/ikeys.c @@ -428,8 +428,8 @@ void testPermute() printarr("permuted", res, 8); } -//These testcases are -//{ UID , TEMP_KEY, DIV_KEY} using the specific key +// These testcases are +// { UID , TEMP_KEY, DIV_KEY} using the specific key typedef struct { uint8_t uid[8]; @@ -475,7 +475,7 @@ int testDES(Testcase testcase, mbedtls_des_context ctx_enc, mbedtls_des_context return retval; } bool des_getParityBitFromKey(uint8_t key) -{//The top 7 bits is used +{ // The top 7 bits is used bool parity = ((key & 0x80) >> 7) ^ ((key & 0x40) >> 6) ^ ((key & 0x20) >> 5) ^ ((key & 0x10) >> 4) ^ ((key & 0x08) >> 3) @@ -676,7 +676,8 @@ static bool readKeyFile(uint8_t key[8]) { bool retval = false; //Test a few variants - char filename[30]; + char filename[30] = {0}; + if (fileExists("iclass_key.bin")){ sprintf(filename, "%s.bin", "iclass_key"); } else if (fileExists("loclass/iclass_key.bin")){ From 2b9eb401facee8839344c960f2930160779ec806 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 23:54:36 +0100 Subject: [PATCH 0614/1938] fix: more checks --- client/loclass/fileutils.c | 20 ++++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 6ce7c42ea..6f6f1a5a4 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -323,6 +323,7 @@ int loadFileEML(const char *preferredName, const char *suffix, void* data, size_ if ( preferredName == NULL ) return 1; if ( suffix == NULL ) return 1; + if ( data == NULL ) return 1; size_t counter = 0; int retval = 0, hexlen = 0; @@ -364,7 +365,9 @@ int loadFileEML(const char *preferredName, const char *suffix, void* data, size_ } fclose(f); PrintAndLogDevice(SUCCESS, "loaded %d bytes from text file " _YELLOW_(%s), counter, fileName); - *datalen = counter; + + if ( datalen ) + *datalen = counter; out: free(fileName); @@ -372,12 +375,14 @@ out: } int loadFileJSON(const char *preferredName, const char *suffix, void* data, size_t maxdatalen, size_t* datalen) { - *datalen = 0; - json_t *root; - json_error_t error; if ( preferredName == NULL ) return 1; if ( suffix == NULL ) return 1; + if ( data == NULL ) return 1; + + *datalen = 0; + json_t *root; + json_error_t error; int retval = 0; int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10); @@ -461,6 +466,7 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data if ( preferredName == NULL ) return 1; if ( suffix == NULL ) return 1; + if ( data == NULL ) return 1; // t5577 == 4bytes // mifare == 6 bytes @@ -516,8 +522,10 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data counter += (keylen >> 1); } fclose(f); - PrintAndLogDevice(SUCCESS, "loaded " _GREEN_(%2d) "keys from dictionary file " _YELLOW_(%s), *keycnt, fileName); - *datalen = counter; + PrintAndLogDevice(SUCCESS, "loaded " _GREEN_(%2d) "keys from dictionary file " _YELLOW_(%s), *keycnt, fileName); + + if ( datalen ) + *datalen = counter; out: free(fileName); return retval; From bd26794c208e3504a2e7e92959b5751a0fd86081 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sun, 24 Feb 2019 23:57:04 +0100 Subject: [PATCH 0615/1938] revert --- client/cmdflashmem.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index d3aaff19e..34bb89cbc 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -13,6 +13,7 @@ #include "mbedtls/rsa.h" #include "mbedtls/sha1.h" +#include "mbedtls/base64.h" #define MCK 48000000 //#define FLASH_BAUD 24000000 @@ -247,7 +248,6 @@ int CmdFlashMemLoad(const char *Cmd){ res = loadFile(filename, "bin", data, &datalen); //int res = loadFileEML( filename, "eml", data, &datalen); if ( res ) { - free(data); return 1; } From ae4e3b72afe9b58c398fd5349d4c04cb7429b774 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 25 Feb 2019 00:10:02 +0100 Subject: [PATCH 0616/1938] chg: colors --- client/cmdhf14a.c | 6 +++--- client/cmdhflist.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 9140a3502..27f670fac 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -579,11 +579,11 @@ int CmdHF14AInfo(const char *Cmd) { if (isMifareClassic) { int res = detect_classic_prng(); if ( res == 1 ) - PrintAndLogEx(SUCCESS, "Prng detection: WEAK"); + PrintAndLogEx(SUCCESS, "Prng detection: " _GREEN_(WEAK)); else if (res == 0 ) - PrintAndLogEx(SUCCESS, "Prng detection: HARD"); + PrintAndLogEx(SUCCESS, "Prng detection: " _YELLOW_(HARD)); else - PrintAndLogEx(FAILED, "prng detection: failed"); + PrintAndLogEx(FAILED, "prng detection: " _RED_(failed)); if ( do_nack_test ) detect_classic_nackbug(silent); diff --git a/client/cmdhflist.c b/client/cmdhflist.c index b2e0eeecc..faed275cd 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -686,7 +686,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes PrintAndLogEx(NORMAL, " | | * |%49s %012"PRIx64" prng %s | |", "key", mfLastKey, - validate_prng_nonce(AuthData.nt) ? "WEAK": "HARD"); + validate_prng_nonce(AuthData.nt) ? _GREEN_(WEAK): _YELLOW_(HARD)); AuthData.first_auth = false; From 7945b5a805bcb5deeb4285046fd631a0d6722b41 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 25 Feb 2019 00:15:39 +0100 Subject: [PATCH 0617/1938] colors --- client/mifarehost.c | 12 ++++++------ common/lfdemod.c | 4 ++-- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/client/mifarehost.c b/client/mifarehost.c index 927fb7bc0..632ff7c71 100644 --- a/client/mifarehost.c +++ b/client/mifarehost.c @@ -959,8 +959,8 @@ int detect_classic_nackbug(bool verbose){ } return 2; } - case 2 : PrintAndLogEx(SUCCESS, "always leak NACK detected"); return 3; - case 1 : PrintAndLogEx(SUCCESS, "NACK bug detected"); return 1; + case 2 : PrintAndLogEx(SUCCESS, _GREEN_(always leak NACK detected)); return 3; + case 1 : PrintAndLogEx(SUCCESS, _GREEN_(NACK bug detected)); return 1; case 0 : PrintAndLogEx(SUCCESS, "No NACK bug detected"); return 2; default : PrintAndLogEx(WARNING, "errorcode from device [%i]", ok); return 0; } @@ -981,9 +981,9 @@ void detect_classic_magic(void) { isGeneration = resp.arg[0] & 0xff; switch( isGeneration ){ - case 1: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 1a): YES"); break; - case 2: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 1b): YES"); break; - //case 4: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 2): YES"); break; - default: PrintAndLogEx(INFO, "Answers to magic commands: NO"); break; + case 1: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 1a): " _GREEN_(YES)); break; + case 2: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 1b): " _GREEN_(YES)); break; + //case 4: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 2): " _GREEN_(YES)); break; + default: PrintAndLogEx(INFO, "Answers to magic commands: " _YELLOW_(NO)); break; } } \ No newline at end of file diff --git a/common/lfdemod.c b/common/lfdemod.c index 6b755d3dc..1ef5915c9 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -77,7 +77,7 @@ static void resetSignal(void) { signalprop.isnoise = true; } static void printSignal(void) { - prnt("LF Signal properties:"); + prnt("LF signal properties:"); prnt(" high..........%d", signalprop.high); prnt(" low...........%d", signalprop.low); prnt(" mean..........%d", signalprop.mean); @@ -1922,7 +1922,7 @@ int pskRawDemod_ext(uint8_t *dest, size_t *size, int *clock, int *invert, int *s dest[numBits++] = curPhase; } else if (waveLenCnt < fc - 1) { //wave is smaller than field clock (shouldn't happen often) errCnt2++; - if(errCnt2 > 101) return errCnt2; + if (errCnt2 > 101) return errCnt2; avgWaveVal += dest[i+1]; continue; } From e3a0594b98f52d5e40c9519d00b119c2b2ec2f93 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 25 Feb 2019 00:31:00 +0100 Subject: [PATCH 0618/1938] colors --- client/hardnested/hardnested_bruteforce.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/client/hardnested/hardnested_bruteforce.c b/client/hardnested/hardnested_bruteforce.c index 2a7618a1d..98f2785b2 100644 --- a/client/hardnested/hardnested_bruteforce.c +++ b/client/hardnested/hardnested_bruteforce.c @@ -170,7 +170,9 @@ crack_states_thread(void* x){ __atomic_fetch_add(&found_bs_key, key, __ATOMIC_SEQ_CST); char progress_text[80]; - sprintf(progress_text, "Brute force phase completed. Key found: %012" PRIx64, key); + char keystr[18]; + sprintf(keystr, "%012" PRIx64, key); + sprintf(progress_text, "Brute force phase completed. Key found: " _GREEN_(keystr)); hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, 0.0, 0); break; } else if(keys_found){ From a4ecc6d3ce3cb3a1f6be5f90d4fb43903f061e1f Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 25 Feb 2019 00:32:59 +0100 Subject: [PATCH 0619/1938] colors --- client/hardnested/hardnested_bruteforce.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/hardnested/hardnested_bruteforce.c b/client/hardnested/hardnested_bruteforce.c index 98f2785b2..4c820cbc1 100644 --- a/client/hardnested/hardnested_bruteforce.c +++ b/client/hardnested/hardnested_bruteforce.c @@ -172,7 +172,7 @@ crack_states_thread(void* x){ char progress_text[80]; char keystr[18]; sprintf(keystr, "%012" PRIx64, key); - sprintf(progress_text, "Brute force phase completed. Key found: " _GREEN_(keystr)); + sprintf(progress_text, "Brute force phase completed. Key found: " _GREEN_(%s), keystr); hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, 0.0, 0); break; } else if(keys_found){ From a8eb0fd05fa2c31a61720206556579f759dc8d44 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 25 Feb 2019 00:38:48 +0100 Subject: [PATCH 0620/1938] colors --- client/hardnested/hardnested_bruteforce.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/hardnested/hardnested_bruteforce.c b/client/hardnested/hardnested_bruteforce.c index 4c820cbc1..1a09d7a49 100644 --- a/client/hardnested/hardnested_bruteforce.c +++ b/client/hardnested/hardnested_bruteforce.c @@ -171,8 +171,8 @@ crack_states_thread(void* x){ char progress_text[80]; char keystr[18]; - sprintf(keystr, "%012" PRIx64, key); - sprintf(progress_text, "Brute force phase completed. Key found: " _GREEN_(%s), keystr); + sprintf(keystr, "%012" PRIx64 " ", key); + sprintf(progress_text, "Brute force phase completed. Key found: " _YELLOW_(%s), keystr); hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, 0.0, 0); break; } else if(keys_found){ From 711d384e7d2f41823467980ad918fcb27507cbde Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 25 Feb 2019 12:44:21 +0100 Subject: [PATCH 0621/1938] chg: 'data autocorrelate g' - visual with gridclock patter and markup of two tops. Also added a "visual" inspection of peaks with 3% tolerance. This increases usability quite much. --- client/cmddata.c | 48 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 7 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 65fd0d829..62308c39f 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -754,19 +754,53 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph lastmax = i; } } - - if (verbose && ( correlation > 1 ) ) { - PrintAndLogEx(SUCCESS, "possible correlation %4d samples", correlation); - } else { - PrintAndLogEx(FAILED, "no repeating pattern found"); + + // + int hi = 0, idx = 0; + int distance = 0, hi_1 = 0, idx_1 = 0; + for (int i=0; i<=len; ++i){ + if ( CorrelBuffer[i] > hi) { + hi = CorrelBuffer[i]; + idx = i; + } } - if (SaveGrph){ + for (int i=idx+1; i<=window; ++i){ + if ( CorrelBuffer[i] > hi_1 ) { + hi_1 = CorrelBuffer[i]; + idx_1 = i; + } + } + + int foo = ABS(hi-hi_1); + int bar = ((int)(((hi+hi_1) / 2) * 0.03)); + if ( verbose && foo < bar ) { + distance = idx_1 - idx; + PrintAndLogEx(SUCCESS, "possible 3% visible correlation %4d samples", distance); + } else if (verbose && ( correlation > 1 ) ) { + PrintAndLogEx(SUCCESS, "possible correlation %4d samples", correlation); + } else { + PrintAndLogEx(FAILED, "no repeating pattern found, try increasing window size"); + } + + int retval = correlation; + if (SaveGrph) { //GraphTraceLen = GraphTraceLen - window; memcpy(out, CorrelBuffer, len * sizeof(int)); + if ( distance > 0) { + setClockGrid(distance, idx); + retval = distance; + } + else + setClockGrid(correlation, idx); + + CursorCPos = idx_1; + CursorDPos = idx_1+retval; + DemodBufferLen = 0; RepaintGraphWindow(); } - return correlation; + + return retval; } int CmdAutoCorr(const char *Cmd) { From 81f8749caf617734782751b1591e9e27e6972650 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 25 Feb 2019 12:46:06 +0100 Subject: [PATCH 0622/1938] text --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9ebb49b2..673b25f8b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file. This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log... ## [unreleased][unreleased] + - Chg 'data autocorrelate' - better visual representation and added extra peak detection (@iceman) - Fix 'lf search' - false positive indala identification fixed (@iceman) - Add 'lf keri' - basic support for Keri tags (@iceman) - Add 'hf mf list' - re-added it again (@iceman) From 64bae8c8be83810f9e9347d8fd2450fdd834caa5 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 25 Feb 2019 15:07:31 +0100 Subject: [PATCH 0623/1938] fix: 'data detectclock' - now prints clock again... --- client/graph.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/graph.c b/client/graph.c index 2b2884819..42bb79c84 100644 --- a/client/graph.c +++ b/client/graph.c @@ -121,7 +121,7 @@ int GetAskClock(const char *str, bool printAns) { } // Only print this message if we're not looping something if (printAns || g_debugMode) - PrintAndLogEx(DEBUG, "Auto-detected clock rate: %d, Best Starting Position: %d", clock, idx); + PrintAndLogEx(SUCCESS, "Auto-detected clock rate: %d, Best Starting Position: %d", clock, idx); return clock; } @@ -140,7 +140,7 @@ uint8_t GetPskCarrier(const char *str, bool printAns) { if (( fc >> 8) == 10 && carrier == 8) return 0; // Only print this message if we're not looping something if (printAns) - PrintAndLogEx(NORMAL, "Auto-detected PSK carrier rate: %d", carrier); + PrintAndLogEx(SUCCESS, "Auto-detected PSK carrier rate: %d", carrier); return carrier; } @@ -162,7 +162,7 @@ int GetPskClock(const char* str, bool printAns) { setClockGrid(clock, firstPhaseShiftLoc); // Only print this message if we're not looping something if (printAns) - PrintAndLogEx(NORMAL, "Auto-detected clock rate: %d", clock); + PrintAndLogEx(SUCCESS, "Auto-detected clock rate: %d", clock); return clock; } @@ -184,7 +184,7 @@ int GetNrzClock(const char* str, bool printAns) { setClockGrid(clock, clkStartIdx); // Only print this message if we're not looping something if (printAns) - PrintAndLogEx(NORMAL, "Auto-detected clock rate: %d", clock); + PrintAndLogEx(SUCCESS, "Auto-detected clock rate: %d", clock); return clock; } //by marshmellow @@ -203,7 +203,7 @@ int GetFskClock(const char* str, bool printAns) { if ((fc1==10 && fc2==8) || (fc1==8 && fc2==5)){ if (printAns) - PrintAndLogEx(NORMAL, "Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1, fc2, rf1); + PrintAndLogEx(SUCCESS, "Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1, fc2, rf1); setClockGrid(rf1, firstClockEdge); return rf1; } From d929f31eb37d05899012faf4c4846b2413644386 Mon Sep 17 00:00:00 2001 From: 3ldidi94 Date: Mon, 25 Feb 2019 18:52:44 +0100 Subject: [PATCH 0624/1938] Update default_iclass_keys.dic --- client/default_iclass_keys.dic | 1 + 1 file changed, 1 insertion(+) diff --git a/client/default_iclass_keys.dic b/client/default_iclass_keys.dic index 0f7ec2d2c..829ba521e 100644 --- a/client/default_iclass_keys.dic +++ b/client/default_iclass_keys.dic @@ -8,3 +8,4 @@ AEA684A6DAB23278 -- AA1 5b7c62c491c11b39 -- from loclass demo file. F0E1D2C3B4A59687 -- Kd from PicoPass 2k documentation 5CBCF1DA45D5FB4F -- PicoPass Default Exchange Key +31ad7ebd2f282168 -- From HID multiclassSE reader From d6bb8d630a6254ceefa7043e330853295cbfc503 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 25 Feb 2019 19:03:14 +0100 Subject: [PATCH 0625/1938] fix: strings --- client/cmdhffelica.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 42c56d900..efb6b68d7 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -277,7 +277,8 @@ uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) { uint32_t regB = trace[7] | trace[8] << 8 | trace[9] << 16 | trace[10] << 24; line[0] = 0; for (int j = 0; j < 8; j++) - snprintf(line+( j * 2), sizeof(line)-1-(j*2), "%02x", trace[j+11]); + snprintf(line + (j*2), sizeof(line)-1-(j*2), "%02x", trace[j+11]); + PrintAndLogEx(NORMAL, "REG: regA: %d regB: %d regC: %s ", regA, regB, line); } break; @@ -287,10 +288,10 @@ uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) { char idd[20]; char idm[20]; for (int j = 0; j < 8; j++) - snprintf(idd + (j * 2), sizeof(idd) - 1 - (j*2), "%02x", trace[j+3]); + snprintf(idd + (j*2), sizeof(idd)-1-(j*2), "%02x", trace[j+3]); for (int j = 0; j < 6; j++) - snprintf(idm + (j * 2), sizeof(idm) - 1 - (j*2), "%02x", trace[j+13]); + snprintf(idm + (j*2), sizeof(idm)-1-(j*2), "%02x", trace[j+13]); PrintAndLogEx(NORMAL, "ID Block, IDd: 0x%s DFC: 0x%02x%02x Arb: %s ", idd, trace[11], trace [12], idm); } @@ -299,10 +300,10 @@ uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) { char idm[20]; char pmm[20]; for (int j = 0; j < 8; j++) - snprintf(idm + (j * 2), 20, "%02x", trace[j+3]); + snprintf(idm + (j*2), sizeof(idm)-1-(j*2), "%02x", trace[j+3]); for (int j = 0; j < 8; j++) - snprintf(pmm + (j * 2), 20, "%02x", trace[j+11]); + snprintf(pmm + (j*2), sizeof(pmm)-1-(j*2), "%02x", trace[j+11]); PrintAndLogEx(NORMAL, "DeviceId: IDm: 0x%s PMm: 0x%s ", idm, pmm); } From 56a75fbf0b47c15a96ff621e8d7c274136f7a6b9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 25 Feb 2019 19:03:31 +0100 Subject: [PATCH 0626/1938] fix: bad division --- client/cmddata.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 62308c39f..7e037c2e6 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -758,14 +758,14 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph // int hi = 0, idx = 0; int distance = 0, hi_1 = 0, idx_1 = 0; - for (int i=0; i<=len; ++i){ + for (int i = 0; i <= len; ++i){ if ( CorrelBuffer[i] > hi) { hi = CorrelBuffer[i]; idx = i; } } - for (int i=idx+1; i<=window; ++i){ + for (int i = idx+1; i <= window; ++i){ if ( CorrelBuffer[i] > hi_1 ) { hi_1 = CorrelBuffer[i]; idx_1 = i; @@ -773,7 +773,7 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph } int foo = ABS(hi-hi_1); - int bar = ((int)(((hi+hi_1) / 2) * 0.03)); + int bar = (int)(((hi+hi_1) / 2) * 0.03); if ( verbose && foo < bar ) { distance = idx_1 - idx; PrintAndLogEx(SUCCESS, "possible 3% visible correlation %4d samples", distance); From 972f8590e0bfa25a78b3ed19cb623a3c670102f9 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 25 Feb 2019 19:10:00 +0100 Subject: [PATCH 0627/1938] fix dereference --- client/emv/emvjson.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/client/emv/emvjson.c b/client/emv/emvjson.c index fc10f255c..dc409a2a5 100644 --- a/client/emv/emvjson.c +++ b/client/emv/emvjson.c @@ -259,7 +259,8 @@ bool HexToBuffer(const char *errormsg, const char *hexvalue, uint8_t * buffer, s return false; } - *bufferlen = buflen; + if ( bufferlen ) + *bufferlen = buflen; return true; } From 8c6312e2097aa804ef4e9ef5dc9ce1ffeba2e603 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Mon, 25 Feb 2019 19:10:37 +0100 Subject: [PATCH 0628/1938] fix mem leaks --- client/emv/cmdemv.c | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index 52033afb4..f14d23f2d 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -253,6 +253,7 @@ int CmdEMVGPO(const char *cmd) { // calc PDOL struct tlv *pdol_data_tlv = NULL; + struct tlvdb *tmp_ext = NULL; struct tlv data_tlv = { .tag = 0x83, .len = datalen, @@ -266,7 +267,7 @@ int CmdEMVGPO(const char *cmd) { ParamLoadFromJson(tlvRoot); }; - struct tlvdb *tmp_ext = tlvdb_external(0x9f38, datalen, data); + tmp_ext = tlvdb_external(0x9f38, datalen, data); pdol_data_tlv = dol_process((const struct tlv *)tmp_ext, tlvRoot, 0x83); if (!pdol_data_tlv){ PrintAndLogEx(ERR, "Can't create PDOL TLV."); @@ -285,8 +286,8 @@ int CmdEMVGPO(const char *cmd) { unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len); if (!pdol_data_tlv_data) { PrintAndLogEx(ERR, "Can't create PDOL data."); + tlvdb_free(tmp_ext); tlvdb_free(tlvRoot); - free(pdol_data_tlv); return 4; } PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); @@ -299,7 +300,8 @@ int CmdEMVGPO(const char *cmd) { if (pdol_data_tlv != &data_tlv) free(pdol_data_tlv); - + + tlvdb_free(tmp_ext); tlvdb_free(tlvRoot); if (sw) @@ -434,6 +436,7 @@ int CmdEMVAC(const char *cmd) { // calc CDOL struct tlv *cdol_data_tlv = NULL; + struct tlvdb *tmp_ext = NULL; struct tlv data_tlv = { .tag = 0x01, .len = datalen, @@ -448,7 +451,7 @@ int CmdEMVAC(const char *cmd) { ParamLoadFromJson(tlvRoot); }; - struct tlvdb *tmp_ext = tlvdb_external(0x8c, datalen, data); + tmp_ext = tlvdb_external(0x8c, datalen, data); cdol_data_tlv = dol_process((const struct tlv *)tmp_ext, tlvRoot, 0x01); // 0x01 - dummy tag if (!cdol_data_tlv){ PrintAndLogEx(ERR, "Can't create CDOL TLV."); @@ -473,6 +476,8 @@ int CmdEMVAC(const char *cmd) { if (cdol_data_tlv != &data_tlv) free(cdol_data_tlv); + + tlvdb_free(tmp_ext); tlvdb_free(tlvRoot); if (sw) @@ -578,6 +583,7 @@ int CmdEMVInternalAuthenticate(const char *cmd) { // calc DDOL struct tlv *ddol_data_tlv = NULL; + struct tlvdb *tmp_ext = NULL; struct tlv data_tlv = { .tag = 0x01, .len = datalen, @@ -592,7 +598,7 @@ int CmdEMVInternalAuthenticate(const char *cmd) { ParamLoadFromJson(tlvRoot); }; - struct tlvdb *tmp_ext = tlvdb_external(0x9f49, datalen, data); + tmp_ext = tlvdb_external(0x9f49, datalen, data); ddol_data_tlv = dol_process((const struct tlv *)tmp_ext, tlvRoot, 0x01); // 0x01 - dummy tag if (!ddol_data_tlv){ PrintAndLogEx(ERR, "Can't create DDOL TLV."); @@ -617,6 +623,8 @@ int CmdEMVInternalAuthenticate(const char *cmd) { if (ddol_data_tlv != &data_tlv) free(ddol_data_tlv); + + tlvdb_free(tmp_ext); tlvdb_free(tlvRoot); if (sw) From c2046f2e65bf293ea6697793dbf9f33723b63830 Mon Sep 17 00:00:00 2001 From: Chris Date: Mon, 25 Feb 2019 22:33:49 +0100 Subject: [PATCH 0629/1938] CHG: 'hf mf dump' - now saves in BIN/EML/JSON default CHG: 'hf mf esave' - now saves in BIN/EML/JSON default --- client/cmdhfmf.c | 69 ++++++++++++++++++++++++++---------------------- 1 file changed, 37 insertions(+), 32 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index c59dad769..00d5c3176 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -11,6 +11,9 @@ #include "cmdhfmf.h" #include "mifare4.h" + +#define MFBLOCK_SIZE 16 + #define MIFARE_4K_MAXBLOCK 256 #define MIFARE_2K_MAXBLOCK 128 #define MIFARE_1K_MAXBLOCK 64 @@ -697,10 +700,13 @@ int CmdHF14AMfDump(const char *Cmd) { uint8_t cmdp = 0; char keyFilename[FILE_PATH_SIZE] = {0}; - char dataFilename[FILE_PATH_SIZE] = {0}; + char dataFilename[FILE_PATH_SIZE]; char * fptr; - FILE *fin, *fout; + memset(keyFilename, 0, sizeof(keyFilename)); + memset(dataFilename, 0, sizeof(dataFilename)); + + FILE *f; UsbCommand resp; while(param_getchar(Cmd, cmdp) != 0x00) { @@ -734,7 +740,7 @@ int CmdHF14AMfDump(const char *Cmd) { strcpy(keyFilename, fptr); } - if ((fin = fopen(keyFilename, "rb")) == NULL) { + if ((f = fopen(keyFilename, "rb")) == NULL) { PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), keyFilename); return 1; } @@ -742,29 +748,29 @@ int CmdHF14AMfDump(const char *Cmd) { // Read keys A from file size_t bytes_read; for (sectorNo=0; sectorNo Date: Tue, 26 Feb 2019 22:27:33 +0100 Subject: [PATCH 0630/1938] another --- client/default_keys.dic | 1 + 1 file changed, 1 insertion(+) diff --git a/client/default_keys.dic b/client/default_keys.dic index ffbdb3cbd..cd23d9a0d 100644 --- a/client/default_keys.dic +++ b/client/default_keys.dic @@ -98,6 +98,7 @@ fc00018778f7,--VästtrafikenKeyA, RKFÖstgötaTrafikenKeyA 314B49474956,--VIGIK1KeyA 564c505f4d41,--VIGIK1KeyB ba5b895da162,--VIGIK1KeyB +4143414F5250, # # Data from: http://irq5.io/2013/04/13/decoding-bcard-conference-badges/ f4a9ef2afc6d,--BCARD KeyB From ef2fc5b66c37cbc6661cfdbb1f58d2346be5ace9 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 1 Mar 2019 12:09:35 +0100 Subject: [PATCH 0631/1938] fix: 'hw tune' - reset demodplot line and grid clock --- client/cmddata.c | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/client/cmddata.c b/client/cmddata.c index 7e037c2e6..ba3d61156 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1495,6 +1495,13 @@ int CmdTuneSamples(const char *Cmd) { #define HF_UNUSABLE_V 3000 #define HF_MARGINAL_V 5000 #define ANTENNA_ERROR 1.03 // current algo has 3% error margin. + + // hide demod plot line + DemodBufferLen = 0; + setClockGrid(0, 0); + RepaintGraphWindow(); + + int timeout = 0; PrintAndLogEx(INFO, "\nmeasuring antenna characteristics, please wait..."); @@ -1575,6 +1582,7 @@ int CmdTuneSamples(const char *Cmd) { PrintAndLogEx(FAILED, "\nNot showing LF tuning graph since all values is zero.\n\n"); } + return 0; } From 4d79ced1a9bbeb282664efa622089243be144410 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Mar 2019 18:49:53 +0200 Subject: [PATCH 0632/1938] =?UTF-8?q?=D0=B0=D1=88=D1=87=D1=83=D1=8B=20?= =?UTF-8?q?=D1=88=D1=82=20=D1=8C=D1=84=D0=B2=D1=8E=D1=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- client/mifare/mad.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/client/mifare/mad.c b/client/mifare/mad.c index 9f28de394..3973116b4 100644 --- a/client/mifare/mad.c +++ b/client/mifare/mad.c @@ -101,7 +101,7 @@ static const char *GetAIDDescription(uint16_t AID) { return madKnownAIDs[i].Description; for(int i = 0; i < ARRAYLEN(madKnownClusterCodes); i++) - if (madKnownClusterCodes[i].AID == AID) + if (madKnownClusterCodes[i].AID == (AID >> 8)) // high byte - cluster code return madKnownClusterCodes[i].Description; return unknownAID; @@ -175,6 +175,7 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { if (InfoByte == 0x10 || InfoByte >= 0x28) PrintAndLogEx(WARNING, "Info byte error"); + PrintAndLogEx(NORMAL, "00 MAD1"); for(int i = 1; i < 16; i++) { uint16_t AID = madGetAID(sector, 1, i); PrintAndLogEx(NORMAL, "%02d [%04X] %s", i, AID, GetAIDDescription(AID)); @@ -184,15 +185,19 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { }; int MAD2DecodeAndPrint(uint8_t *sector, bool verbose) { + PrintAndLogEx(NORMAL, "16 MAD2"); + int res = madCRCCheck(sector, true, 2); if (res) return res; - for(int i = 1; i < 8 + 8 + 7; i++) { + uint8_t InfoByte = sector[1] & 0x3f; + PrintAndLogEx(NORMAL, "MAD2 Card publisher sector: 0x%02x", InfoByte); + + for(int i = 1; i < 8 + 8 + 7 + 1; i++) { uint16_t AID = madGetAID(sector, 2, i); - PrintAndLogEx(NORMAL, "%02d [%04X] %s", i + 15, AID, GetAIDDescription(AID)); - }; - + PrintAndLogEx(NORMAL, "%02d [%04X] %s", i + 16, AID, GetAIDDescription(AID)); + }; return 0; }; From 6208a6869cdb21b9b4d7330d4b1e0179a72389b8 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Mar 2019 18:50:25 +0200 Subject: [PATCH 0633/1938] added mad decode for mfp --- client/cmdhfmfp.c | 108 ++++++++++++++++++++++++++++++++++ client/mifare/mifaredefault.h | 1 + 2 files changed, 109 insertions(+) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 0917728be..bcbe323a9 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -23,6 +23,7 @@ #include "cmdhf14a.h" #include "mifare.h" #include "mifare/mifare4.h" +#include "mifare/mad.h" #include "cliparser/cliparser.h" #include "crypto/libpcrypto.h" @@ -733,6 +734,112 @@ int CmdHFMFPWrbl(const char *cmd) { return 0; } +int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *dataout, bool verbose){ + uint8_t keyn[2] = {0}; + bool plain = false; + + uint16_t uKeyNum = 0x4000 + sectorNo * 2 + (keyType ? 1 : 0); + keyn[0] = uKeyNum >> 8; + keyn[1] = uKeyNum & 0xff; + if (verbose) + PrintAndLogEx(INFO, "--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNo), sectorNo, uKeyNum); + + mf4Session session; + int res = MifareAuth4(&session, keyn, key, true, true, verbose); + if (res) { + PrintAndLogEx(ERR, "Sector %d authentication error: %d", sectorNo, res); + return res; + } + + uint8_t data[250] = {0}; + int datalen = 0; + uint8_t mac[8] = {0}; + uint8_t firstBlockNo = mfFirstBlockOfSector(sectorNo); + for(int n = firstBlockNo; n < firstBlockNo + mfNumBlocksPerSector(sectorNo); n++) { + res = MFPReadBlock(&session, plain, n & 0xff, 1, false, true, data, sizeof(data), &datalen, mac); + if (res) { + PrintAndLogEx(ERR, "Sector %d read error: %d", sectorNo, res); + DropField(); + return res; + } + + if (datalen && data[0] != 0x90) { + PrintAndLogEx(ERR, "Sector %d card read error: %02x %s", sectorNo, data[0], GetErrorDescription(data[0])); + DropField(); + return 5; + } + if (datalen != 1 + 16 + 8 + 2) { + PrintAndLogEx(ERR, "Sector %d error returned data length:%d", sectorNo, datalen); + DropField(); + return 6; + } + + memcpy(&dataout[(n - firstBlockNo) * 16], &data[1], 16); + + if (verbose) + PrintAndLogEx(INFO, "data[%03d]: %s", n, sprint_hex(&data[1], 16)); + + if (memcmp(&data[1 + 16], mac, 8)) { + PrintAndLogEx(WARNING, "WARNING: mac on block %d not equal...", n); + PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[1 + 16], 8)); + PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8)); + + if (!verbose) + return 7; + } else { + if(verbose) + PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1 + 16], 8)); + } + } + DropField(); + + return 0; +} + +int CmdHFMFPMAD(const char *cmd) { + + CLIParserInit("hf mfp mad", + "Checks and prints Mifare Application Directory (MAD)", + "Usage:\n\thf mfp mad -> shows MAD if exists\n"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("vV", "verbose", "show technical data"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + bool verbose = arg_get_lit(1); + + CLIParserFree(); + + uint8_t sector[16 * 4] = {0}; + if (mfpReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector, verbose)) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); + return 2; + } + + if (verbose) { + for(int i = 0; i < 4; i ++) + PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(§or[i * 16], 16)); + } + + bool haveMAD2 = false; + MAD1DecodeAndPrint(sector, verbose, &haveMAD2); + + if (haveMAD2) { + if (mfpReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector, verbose)) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); + return 2; + } + + MAD2DecodeAndPrint(sector, verbose); + } + + return 0; +} + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, @@ -744,6 +851,7 @@ static command_t CommandTable[] = {"rdbl", CmdHFMFPRdbl, 0, "Read blocks"}, {"rdsc", CmdHFMFPRdsc, 0, "Read sectors"}, {"wrbl", CmdHFMFPWrbl, 0, "Write blocks"}, + {"mad", CmdHFMFPMAD, 0, "Checks and prints MAD"}, {NULL, NULL, 0, NULL} }; diff --git a/client/mifare/mifaredefault.h b/client/mifare/mifaredefault.h index db9c0329d..e7218cbe7 100644 --- a/client/mifare/mifaredefault.h +++ b/client/mifare/mifaredefault.h @@ -44,5 +44,6 @@ static const uint64_t g_mifare_default_keys[] = static const uint8_t g_mifare_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5}; static const uint8_t g_mifare_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}; +static const uint8_t g_mifarep_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7}; #endif From 5cc4bea4e3f44a322902ab4f3553a8490508804b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Mar 2019 19:05:51 +0200 Subject: [PATCH 0634/1938] mfp refactoring --- client/cmdhfmfp.c | 181 +++------------------------------------- client/mifare/mifare4.c | 157 ++++++++++++++++++++++++++++++++++ client/mifare/mifare4.h | 9 ++ 3 files changed, 178 insertions(+), 169 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index bcbe323a9..43c8d645d 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -29,103 +29,8 @@ static const uint8_t DefaultKey[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; -typedef struct { - uint8_t Code; - const char *Description; -} PlusErrorsElm; - -static const PlusErrorsElm PlusErrors[] = { - {0xFF, ""}, - {0x00, "Transfer cannot be granted within the current authentication."}, - {0x06, "Access Conditions not fulfilled. Block does not exist, block is not a value block."}, - {0x07, "Too many read or write commands in the session or in the transaction."}, - {0x08, "Invalid MAC in command or response"}, - {0x09, "Block Number is not valid"}, - {0x0a, "Invalid block number, not existing block number"}, - {0x0b, "The current command code not available at the current card state."}, - {0x0c, "Length error"}, - {0x0f, "General Manipulation Error. Failure in the operation of the PICC (cannot write to the data block), etc."}, - {0x90, "OK"}, -}; -int PlusErrorsLen = sizeof(PlusErrors) / sizeof(PlusErrorsElm); - -const char * GetErrorDescription(uint8_t errorCode) { - for(int i = 0; i < PlusErrorsLen; i++) - if (errorCode == PlusErrors[i].Code) - return PlusErrors[i].Description; - - return PlusErrors[0].Description; -} - static int CmdHelp(const char *Cmd); -static bool VerboseMode = false; -void SetVerboseMode(bool verbose) { - VerboseMode = verbose; -} - -int intExchangeRAW14aPlus(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { - if(VerboseMode) - PrintAndLogEx(INFO, ">>> %s", sprint_hex(datain, datainlen)); - - int res = ExchangeRAW14a(datain, datainlen, activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); - - if(VerboseMode) - PrintAndLogEx(INFO, "<<< %s", sprint_hex(dataout, *dataoutlen)); - - return res; -} - -int MFPWritePerso(uint8_t *keyNum, uint8_t *key, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { - uint8_t rcmd[3 + 16] = {0xa8, keyNum[1], keyNum[0], 0x00}; - memmove(&rcmd[3], key, 16); - - return intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); -} - -int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { - uint8_t rcmd[1] = {0xaa}; - - return intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); -} - -int MFPReadBlock(mf4Session *session, bool plain, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) { - uint8_t rcmd[4 + 8] = {(plain?(0x37):(0x33)), blockNum, 0x00, blockCount}; - if (!plain && session) - CalculateMAC(session, mtypReadCmd, blockNum, blockCount, rcmd, 4, &rcmd[4], VerboseMode); - - int res = intExchangeRAW14aPlus(rcmd, plain?4:sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); - if(res) - return res; - - if (session) - session->R_Ctr++; - - if(session && mac && *dataoutlen > 11) - CalculateMAC(session, mtypReadResp, blockNum, blockCount, dataout, *dataoutlen - 8 - 2, mac, VerboseMode); - - return 0; -} - -int MFPWriteBlock(mf4Session *session, uint8_t blockNum, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) { - uint8_t rcmd[1 + 2 + 16 + 8] = {0xA3, blockNum, 0x00}; - memmove(&rcmd[3], data, 16); - if (session) - CalculateMAC(session, mtypWriteCmd, blockNum, 1, rcmd, 19, &rcmd[19], VerboseMode); - - int res = intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); - if(res) - return res; - - if (session) - session->W_Ctr++; - - if(session && mac && *dataoutlen > 3) - CalculateMAC(session, mtypWriteResp, blockNum, 1, dataout, *dataoutlen, mac, VerboseMode); - - return 0; -} - int CmdHFMFPInfo(const char *cmd) { if (cmd && strlen(cmd) > 0) @@ -230,7 +135,7 @@ int CmdHFMFPWritePerso(const char *cmd) { CLIGetHexWithReturn(3, key, &keyLen); CLIParserFree(); - SetVerboseMode(verbose); + mfpSetVerboseMode(verbose); if (!keyLen) { memmove(key, DefaultKey, 16); @@ -261,7 +166,7 @@ int CmdHFMFPWritePerso(const char *cmd) { } if (data[0] != 0x90) { - PrintAndLogEx(ERR, "Command error: %02x %s", data[0], GetErrorDescription(data[0])); + PrintAndLogEx(ERR, "Command error: %02x %s", data[0], mfpGetErrorDescription(data[0])); return 1; } PrintAndLogEx(INFO, "Write OK."); @@ -305,7 +210,7 @@ int CmdHFMFPInitPerso(const char *cmd) { if (!keyLen) memmove(key, DefaultKey, 16); - SetVerboseMode(verbose2); + mfpSetVerboseMode(verbose2); for (uint16_t sn = 0x4000; sn < 0x4050; sn++) { keyNum[0] = sn >> 8; keyNum[1] = sn & 0xff; @@ -320,7 +225,7 @@ int CmdHFMFPInitPerso(const char *cmd) { } } - SetVerboseMode(verbose); + mfpSetVerboseMode(verbose); for (int i = 0; i < sizeof(CardAddresses) / 2; i++) { keyNum[0] = CardAddresses[i] >> 8; keyNum[1] = CardAddresses[i] & 0xff; @@ -361,7 +266,7 @@ int CmdHFMFPCommitPerso(const char *cmd) { bool verbose = arg_get_lit(1); CLIParserFree(); - SetVerboseMode(verbose); + mfpSetVerboseMode(verbose); uint8_t data[250] = {0}; int datalen = 0; @@ -378,7 +283,7 @@ int CmdHFMFPCommitPerso(const char *cmd) { } if (data[0] != 0x90) { - PrintAndLogEx(ERR, "Command error: %02x %s", data[0], GetErrorDescription(data[0])); + PrintAndLogEx(ERR, "Command error: %02x %s", data[0], mfpGetErrorDescription(data[0])); return 1; } PrintAndLogEx(INFO, "Switch level OK."); @@ -454,7 +359,7 @@ int CmdHFMFPRdbl(const char *cmd) { CLIGetHexWithReturn(6, key, &keylen); CLIParserFree(); - SetVerboseMode(verbose); + mfpSetVerboseMode(verbose); if (!keylen) { memmove(key, DefaultKey, 16); @@ -505,7 +410,7 @@ int CmdHFMFPRdbl(const char *cmd) { } if (datalen && data[0] != 0x90) { - PrintAndLogEx(ERR, "Card read error: %02x %s", data[0], GetErrorDescription(data[0])); + PrintAndLogEx(ERR, "Card read error: %02x %s", data[0], mfpGetErrorDescription(data[0])); return 6; } @@ -564,7 +469,7 @@ int CmdHFMFPRdsc(const char *cmd) { CLIGetHexWithReturn(5, key, &keylen); CLIParserFree(); - SetVerboseMode(verbose); + mfpSetVerboseMode(verbose); if (!keylen) { memmove(key, DefaultKey, 16); @@ -606,7 +511,7 @@ int CmdHFMFPRdsc(const char *cmd) { } if (datalen && data[0] != 0x90) { - PrintAndLogEx(ERR, "Card read error: %02x %s", data[0], GetErrorDescription(data[0])); + PrintAndLogEx(ERR, "Card read error: %02x %s", data[0], mfpGetErrorDescription(data[0])); DropField(); return 6; } @@ -662,7 +567,7 @@ int CmdHFMFPWrbl(const char *cmd) { CLIGetHexWithReturn(5, key, &keylen); CLIParserFree(); - SetVerboseMode(verbose); + mfpSetVerboseMode(verbose); if (!keylen) { memmove(key, DefaultKey, 16); @@ -715,7 +620,7 @@ int CmdHFMFPWrbl(const char *cmd) { } if (datalen && data[0] != 0x90) { - PrintAndLogEx(ERR, "Card write error: %02x %s", data[0], GetErrorDescription(data[0])); + PrintAndLogEx(ERR, "Card write error: %02x %s", data[0], mfpGetErrorDescription(data[0])); DropField(); return 6; } @@ -734,68 +639,6 @@ int CmdHFMFPWrbl(const char *cmd) { return 0; } -int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *dataout, bool verbose){ - uint8_t keyn[2] = {0}; - bool plain = false; - - uint16_t uKeyNum = 0x4000 + sectorNo * 2 + (keyType ? 1 : 0); - keyn[0] = uKeyNum >> 8; - keyn[1] = uKeyNum & 0xff; - if (verbose) - PrintAndLogEx(INFO, "--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNo), sectorNo, uKeyNum); - - mf4Session session; - int res = MifareAuth4(&session, keyn, key, true, true, verbose); - if (res) { - PrintAndLogEx(ERR, "Sector %d authentication error: %d", sectorNo, res); - return res; - } - - uint8_t data[250] = {0}; - int datalen = 0; - uint8_t mac[8] = {0}; - uint8_t firstBlockNo = mfFirstBlockOfSector(sectorNo); - for(int n = firstBlockNo; n < firstBlockNo + mfNumBlocksPerSector(sectorNo); n++) { - res = MFPReadBlock(&session, plain, n & 0xff, 1, false, true, data, sizeof(data), &datalen, mac); - if (res) { - PrintAndLogEx(ERR, "Sector %d read error: %d", sectorNo, res); - DropField(); - return res; - } - - if (datalen && data[0] != 0x90) { - PrintAndLogEx(ERR, "Sector %d card read error: %02x %s", sectorNo, data[0], GetErrorDescription(data[0])); - DropField(); - return 5; - } - if (datalen != 1 + 16 + 8 + 2) { - PrintAndLogEx(ERR, "Sector %d error returned data length:%d", sectorNo, datalen); - DropField(); - return 6; - } - - memcpy(&dataout[(n - firstBlockNo) * 16], &data[1], 16); - - if (verbose) - PrintAndLogEx(INFO, "data[%03d]: %s", n, sprint_hex(&data[1], 16)); - - if (memcmp(&data[1 + 16], mac, 8)) { - PrintAndLogEx(WARNING, "WARNING: mac on block %d not equal...", n); - PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[1 + 16], 8)); - PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8)); - - if (!verbose) - return 7; - } else { - if(verbose) - PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1 + 16], 8)); - } - } - DropField(); - - return 0; -} - int CmdHFMFPMAD(const char *cmd) { CLIParserInit("hf mfp mad", diff --git a/client/mifare/mifare4.c b/client/mifare/mifare4.c index 0c53a1f9b..3fe67077f 100644 --- a/client/mifare/mifare4.c +++ b/client/mifare/mifare4.c @@ -17,6 +17,39 @@ #include "ui.h" #include "crypto/libpcrypto.h" +static bool VerboseMode = false; +void mfpSetVerboseMode(bool verbose) { + VerboseMode = verbose; +} + +typedef struct { + uint8_t Code; + const char *Description; +} PlusErrorsElm; + +static const PlusErrorsElm PlusErrors[] = { + {0xFF, ""}, + {0x00, "Transfer cannot be granted within the current authentication."}, + {0x06, "Access Conditions not fulfilled. Block does not exist, block is not a value block."}, + {0x07, "Too many read or write commands in the session or in the transaction."}, + {0x08, "Invalid MAC in command or response"}, + {0x09, "Block Number is not valid"}, + {0x0a, "Invalid block number, not existing block number"}, + {0x0b, "The current command code not available at the current card state."}, + {0x0c, "Length error"}, + {0x0f, "General Manipulation Error. Failure in the operation of the PICC (cannot write to the data block), etc."}, + {0x90, "OK"}, +}; +int PlusErrorsLen = sizeof(PlusErrors) / sizeof(PlusErrorsElm); + +const char * mfpGetErrorDescription(uint8_t errorCode) { + for(int i = 0; i < PlusErrorsLen; i++) + if (errorCode == PlusErrors[i].Code) + return PlusErrors[i].Description; + + return PlusErrors[0].Description; +} + AccessConditions_t MFAccessConditions[] = { {0x00, "rdAB wrAB incAB dectrAB"}, {0x01, "rdAB dectrAB"}, @@ -274,6 +307,130 @@ int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateF return 0; } +int intExchangeRAW14aPlus(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { + if(VerboseMode) + PrintAndLogEx(INFO, ">>> %s", sprint_hex(datain, datainlen)); + + int res = ExchangeRAW14a(datain, datainlen, activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); + + if(VerboseMode) + PrintAndLogEx(INFO, "<<< %s", sprint_hex(dataout, *dataoutlen)); + + return res; +} + +int MFPWritePerso(uint8_t *keyNum, uint8_t *key, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { + uint8_t rcmd[3 + 16] = {0xa8, keyNum[1], keyNum[0], 0x00}; + memmove(&rcmd[3], key, 16); + + return intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); +} + +int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { + uint8_t rcmd[1] = {0xaa}; + + return intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); +} + +int MFPReadBlock(mf4Session *session, bool plain, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) { + uint8_t rcmd[4 + 8] = {(plain?(0x37):(0x33)), blockNum, 0x00, blockCount}; + if (!plain && session) + CalculateMAC(session, mtypReadCmd, blockNum, blockCount, rcmd, 4, &rcmd[4], VerboseMode); + + int res = intExchangeRAW14aPlus(rcmd, plain?4:sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); + if(res) + return res; + + if (session) + session->R_Ctr++; + + if(session && mac && *dataoutlen > 11) + CalculateMAC(session, mtypReadResp, blockNum, blockCount, dataout, *dataoutlen - 8 - 2, mac, VerboseMode); + + return 0; +} + +int MFPWriteBlock(mf4Session *session, uint8_t blockNum, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) { + uint8_t rcmd[1 + 2 + 16 + 8] = {0xA3, blockNum, 0x00}; + memmove(&rcmd[3], data, 16); + if (session) + CalculateMAC(session, mtypWriteCmd, blockNum, 1, rcmd, 19, &rcmd[19], VerboseMode); + + int res = intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); + if(res) + return res; + + if (session) + session->W_Ctr++; + + if(session && mac && *dataoutlen > 3) + CalculateMAC(session, mtypWriteResp, blockNum, 1, dataout, *dataoutlen, mac, VerboseMode); + + return 0; +} + +int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *dataout, bool verbose){ + uint8_t keyn[2] = {0}; + bool plain = false; + + uint16_t uKeyNum = 0x4000 + sectorNo * 2 + (keyType ? 1 : 0); + keyn[0] = uKeyNum >> 8; + keyn[1] = uKeyNum & 0xff; + if (verbose) + PrintAndLogEx(INFO, "--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNo), sectorNo, uKeyNum); + + mf4Session session; + int res = MifareAuth4(&session, keyn, key, true, true, verbose); + if (res) { + PrintAndLogEx(ERR, "Sector %d authentication error: %d", sectorNo, res); + return res; + } + + uint8_t data[250] = {0}; + int datalen = 0; + uint8_t mac[8] = {0}; + uint8_t firstBlockNo = mfFirstBlockOfSector(sectorNo); + for(int n = firstBlockNo; n < firstBlockNo + mfNumBlocksPerSector(sectorNo); n++) { + res = MFPReadBlock(&session, plain, n & 0xff, 1, false, true, data, sizeof(data), &datalen, mac); + if (res) { + PrintAndLogEx(ERR, "Sector %d read error: %d", sectorNo, res); + DropField(); + return res; + } + + if (datalen && data[0] != 0x90) { + PrintAndLogEx(ERR, "Sector %d card read error: %02x %s", sectorNo, data[0], mfpGetErrorDescription(data[0])); + DropField(); + return 5; + } + if (datalen != 1 + 16 + 8 + 2) { + PrintAndLogEx(ERR, "Sector %d error returned data length:%d", sectorNo, datalen); + DropField(); + return 6; + } + + memcpy(&dataout[(n - firstBlockNo) * 16], &data[1], 16); + + if (verbose) + PrintAndLogEx(INFO, "data[%03d]: %s", n, sprint_hex(&data[1], 16)); + + if (memcmp(&data[1 + 16], mac, 8)) { + PrintAndLogEx(WARNING, "WARNING: mac on block %d not equal...", n); + PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[1 + 16], 8)); + PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8)); + + if (!verbose) + return 7; + } else { + if(verbose) + PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1 + 16], 8)); + } + } + DropField(); + + return 0; +} + // Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards), // plus evtl. 8 sectors with 16 blocks each (4k cards) uint8_t mfNumBlocksPerSector(uint8_t sectorNo) { diff --git a/client/mifare/mifare4.h b/client/mifare/mifare4.h index 011567a1e..e4bf6e386 100644 --- a/client/mifare/mifare4.h +++ b/client/mifare/mifare4.h @@ -43,9 +43,18 @@ typedef struct { char *description; } AccessConditions_t; +extern void mfpSetVerboseMode(bool verbose); +extern const char * mfpGetErrorDescription(uint8_t errorCode); + extern int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose); extern int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose); +extern int MFPWritePerso(uint8_t *keyNum, uint8_t *key, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); +extern int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); +extern int MFPReadBlock(mf4Session *session, bool plain, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac); +extern int MFPWriteBlock(mf4Session *session, uint8_t blockNum, uint8_t *data, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac); +extern int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *dataout, bool verbose); + extern char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data); extern uint8_t mfNumBlocksPerSector(uint8_t sectorNo); From 979aa678ad7c70ea62541bf2019e060f359f23ae Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Mar 2019 19:07:34 +0200 Subject: [PATCH 0635/1938] small fix --- client/cmdhfmf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index a7966bee8..eea26f170 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -3230,8 +3230,8 @@ int CmdHF14AMfMAD(const char *cmd) { bool haveMAD2 = false; MAD1DecodeAndPrint(sector, verbose, &haveMAD2); - if (haveMAD2) { // MF_MAD2_SECTOR - if (mfReadSector(1, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector)) { + if (haveMAD2) { + if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector)) { PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); return 2; } From 3a98c9fcd32cf9b4c6c10705d25df46fe7b57061 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Mar 2019 19:13:59 +0200 Subject: [PATCH 0636/1938] fix mad2 crc8 check --- client/mifare/mad.c | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/client/mifare/mad.c b/client/mifare/mad.c index 3973116b4..ff6991f22 100644 --- a/client/mifare/mad.c +++ b/client/mifare/mad.c @@ -109,13 +109,19 @@ static const char *GetAIDDescription(uint16_t AID) { int madCRCCheck(uint8_t *sector, bool verbose, int MADver) { if (MADver == 1) { - uint8_t crc = CRC8Mad(§or[16 + 1], 31); + uint8_t crc = CRC8Mad(§or[16 + 1], 15 + 16); if (crc != sector[16]) { if (verbose) PrintAndLogEx(ERR, "Wrong MAD%d CRC. Calculated: 0x%02x, from card: 0x%02x", MADver, crc, sector[16]); return 3; }; } else { + uint8_t crc = CRC8Mad(§or[1], 15 + 16 + 16); + if (crc != sector[0]) { + if (verbose) + PrintAndLogEx(ERR, "Wrong MAD%d CRC. Calculated: 0x%02x, from card: 0x%02x", MADver, crc, sector[16]); + return 3; + }; } return 0; @@ -191,6 +197,9 @@ int MAD2DecodeAndPrint(uint8_t *sector, bool verbose) { if (res) return res; + if (verbose) + PrintAndLogEx(NORMAL, "CRC8-MAD OK."); + uint8_t InfoByte = sector[1] & 0x3f; PrintAndLogEx(NORMAL, "MAD2 Card publisher sector: 0x%02x", InfoByte); From e8c0a49d076519b37f05cbe0f0c1d0a3dd91ceb2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Fri, 1 Mar 2019 19:39:17 +0200 Subject: [PATCH 0637/1938] changelog --- CHANGELOG.md | 1 + 1 file changed, 1 insertion(+) diff --git a/CHANGELOG.md b/CHANGELOG.md index 673b25f8b..a99c8c522 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -102,6 +102,7 @@ This project uses the changelog in accordance with [keepchangelog](http://keepac - Added `hf emv` `gpo`, `readrec`, `genac`, `challenge`, `intauth` - separate commands from `hf emc exec` (@merlokk) - Added `hf fido` `assert` and `make` commands from fido2 protocol (authenticatorMakeCredential and authenticatorGetAssertion) (@merlokk) - Added trailer block decoding to `hf mf rdbl` and `hf mf cgetbl` (@merlokk) + - Added `hf mf mad` and `hf mfp mad` MAD decode, check and print commands (@merlokk) ### Fixed - Changed driver file proxmark3.inf to support both old and new Product/Vendor IDs (piwi) From dcdb2ee2182325a9f9652acc30a19853d24d53d8 Mon Sep 17 00:00:00 2001 From: Chris Date: Fri, 1 Mar 2019 19:24:02 +0100 Subject: [PATCH 0638/1938] fix: 'script run ndef_dump.lua' - move function --- client/scripts/ndef_dump.lua | 37 ++++++++++++++++++------------------ 1 file changed, 18 insertions(+), 19 deletions(-) diff --git a/client/scripts/ndef_dump.lua b/client/scripts/ndef_dump.lua index a0eda5b7f..f1bf70ddd 100644 --- a/client/scripts/ndef_dump.lua +++ b/client/scripts/ndef_dump.lua @@ -66,8 +66,6 @@ local utils = { end, } - - --- -- Usage help local function help() @@ -83,6 +81,24 @@ local function debug(...) end +--- This function is a lua-implementation of +-- cmdhf14a.c:waitCmd(uint8_t iSelect) +local function waitCmd(iSelect) + local response = core.WaitForResponseTimeout(cmds.CMD_ACK,1000) + if response then + local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response) + + local iLen = arg0 + if iSelect then iLen = arg1 end + debug(("Received %i octets (arg0:%d, arg1:%d)"):format(iLen, arg0, arg1)) + if iLen == 0 then return nil, "No response from tag" end + local recv = string.sub(response,count, iLen+count-1) + return recv + end + return nil, "No response from device" +end + + local function show(data) if DEBUG then local formatString = ("H%d"):format(string.len(data)) @@ -156,23 +172,6 @@ local function getBlock(block) end ---- This function is a lua-implementation of --- cmdhf14a.c:waitCmd(uint8_t iSelect) -local function waitCmd(iSelect) - local response = core.WaitForResponseTimeout(cmds.CMD_ACK,1000) - if response then - local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response) - - local iLen = arg0 - if iSelect then iLen = arg1 end - debug(("Received %i octets (arg0:%d, arg1:%d)"):format(iLen, arg0, arg1)) - if iLen == 0 then return nil, "No response from tag" end - local recv = string.sub(response,count, iLen+count-1) - return recv - end - return nil, "No response from device" -end - local function main( args) From 2c07bb790c2469cdc9a9577d21c4194717877e04 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 4 Mar 2019 19:18:44 +0200 Subject: [PATCH 0639/1938] `hf mfp mad` read contents by aid --- client/cmdhfmfp.c | 64 ++++++++++++++++++++++++++---- client/mifare/mad.c | 73 ++++++++++++++++++++++++++++++----- client/mifare/mad.h | 6 ++- client/mifare/mifaredefault.h | 5 ++- 4 files changed, 128 insertions(+), 20 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 43c8d645d..e6363d64c 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -643,20 +643,38 @@ int CmdHFMFPMAD(const char *cmd) { CLIParserInit("hf mfp mad", "Checks and prints Mifare Application Directory (MAD)", - "Usage:\n\thf mfp mad -> shows MAD if exists\n"); + "Usage:\n\thf mfp mad -> shows MAD if exists\n" + "\thf mfp mad -a 03e1 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> shows NDEF data if exists\n"); void* argtable[] = { arg_param_begin, arg_lit0("vV", "verbose", "show technical data"), + arg_str0("aA", "aid", "print all sectors with aid", NULL), + arg_str0("kK", "key", "key for printing sectors", NULL), + arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"), arg_param_end }; CLIExecWithReturn(cmd, argtable, true); + bool verbose = arg_get_lit(1); + uint8_t aid[2] = {0}; + int aidlen; + CLIGetHexWithReturn(2, aid, &aidlen); + uint8_t key[16] = {0}; + int keylen; + CLIGetHexWithReturn(3, key, &keylen); + bool keyB = arg_get_lit(4); CLIParserFree(); + + if (aidlen != 2 && keylen > 0) { + PrintAndLogEx(WARNING, "do not need a key without aid."); + } - uint8_t sector[16 * 4] = {0}; - if (mfpReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector, verbose)) { + uint8_t sector0[16 * 4] = {0}; + uint8_t sector10[16 * 4] = {0}; + + if (mfpReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector0, verbose)) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); return 2; @@ -664,20 +682,52 @@ int CmdHFMFPMAD(const char *cmd) { if (verbose) { for(int i = 0; i < 4; i ++) - PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(§or[i * 16], 16)); + PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(§or0[i * 16], 16)); } bool haveMAD2 = false; - MAD1DecodeAndPrint(sector, verbose, &haveMAD2); + MAD1DecodeAndPrint(sector0, verbose, &haveMAD2); if (haveMAD2) { - if (mfpReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector, verbose)) { + if (mfpReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector10, verbose)) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); return 2; } - MAD2DecodeAndPrint(sector, verbose); + MAD2DecodeAndPrint(sector10, verbose); + } + + if (aidlen == 2) { + uint16_t aaid = (aid[0] << 8) + aid[1]; + PrintAndLogEx(NORMAL, "\n-------------- AID 0x%04x ---------------", aaid); + + uint16_t mad[7 + 8 + 8 + 8 + 8] = {0}; + size_t madlen = 0; + if (MADDecode(sector0, sector10, mad, &madlen)) { + PrintAndLogEx(ERR, "can't decode mad."); + return 10; + } + + uint8_t akey[16] = {0}; + memcpy(akey, g_mifarep_ndef_key, 16); + if (keylen == 16) { + memcpy(akey, key, 16); + } + + for (int i = 0; i < madlen; i++) { + if (aaid == mad[i]) { + uint8_t vsector[16 * 4] = {0}; + if (mfpReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, akey, vsector, false)) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(ERR, "read sector %d error.", i + 1); + return 2; + } + + for(int j = 0; j < (verbose ? 4 : 3); j ++) + PrintAndLogEx(NORMAL, "---[%03d] %s", (i + 1) * 4 + j, sprint_hex(&vsector[j * 16], 16)); + } + } } return 0; diff --git a/client/mifare/mad.c b/client/mifare/mad.c index ff6991f22..34ea50cfc 100644 --- a/client/mifare/mad.c +++ b/client/mifare/mad.c @@ -134,10 +134,13 @@ uint16_t madGetAID(uint8_t *sector, int MADver, int sectorNo) { return (sector[2 + (sectorNo - 1) * 2] << 8) + (sector[2 + (sectorNo - 1) * 2 + 1]); } -int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { +int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2) { + if (!sector0) + return 1; - uint8_t GPB = sector[3 * 16 + 9]; - PrintAndLogEx(NORMAL, "GPB: 0x%02x", GPB); + uint8_t GPB = sector0[3 * 16 + 9]; + if (verbose) + PrintAndLogEx(NORMAL, "GPB: 0x%02x", GPB); // DA (MAD available) if (!(GPB & 0x80)) { @@ -146,13 +149,16 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { } // MA (multi-application card) - if (GPB & 0x40) - PrintAndLogEx(NORMAL, "Multi application card."); - else - PrintAndLogEx(NORMAL, "Single application card."); + if (verbose) { + if (GPB & 0x40) + PrintAndLogEx(NORMAL, "Multi application card."); + else + PrintAndLogEx(NORMAL, "Single application card."); + } uint8_t MADVer = GPB & 0x03; - PrintAndLogEx(NORMAL, "MAD version: %d", MADVer); + if (verbose) + PrintAndLogEx(NORMAL, "MAD version: %d", MADVer); // MAD version if ((MADVer != 0x01) && (MADVer != 0x02)) { @@ -163,7 +169,56 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { if (haveMAD2) *haveMAD2 = (MADVer == 2); - int res = madCRCCheck(sector, true, 1); + int res = madCRCCheck(sector0, true, 1); + if (res) + return res; + + if (verbose) + PrintAndLogEx(NORMAL, "CRC8-MAD1 OK."); + + if (MADVer == 2 && sector10) { + int res = madCRCCheck(sector10, true, 2); + if (res) + return res; + + if (verbose) + PrintAndLogEx(NORMAL, "CRC8-MAD2 OK."); + } + + return 0; +} + +int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen) { + *madlen = 0; + bool haveMAD2 = false; + int res = MADCheck(sector0, sector10, false, &haveMAD2); + if (res) + return res; + + for (int i = 1; i < 16; i++) { + mad[*madlen] = madGetAID(sector0, 1, i); + (*madlen)++; + } + + if (haveMAD2) { + // mad2 sector (0x10 == 16dec) here + mad[*madlen] = 0x0005; + (*madlen)++; + + for (int i = 1; i < 24; i++) { + mad[*madlen] = madGetAID(sector10, 2, i); + (*madlen)++; + } + } + + return 0; +} + + +int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { + + // check MAD1 only + int res = MADCheck(sector, NULL, verbose, haveMAD2); if (res) return res; diff --git a/client/mifare/mad.h b/client/mifare/mad.h index dc2b2e3c0..ee362adb6 100644 --- a/client/mifare/mad.h +++ b/client/mifare/mad.h @@ -19,8 +19,10 @@ typedef struct { const char *Description; } madAIDDescr; -int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2); -int MAD2DecodeAndPrint(uint8_t *sector, bool verbose); +extern int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2); +extern int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen); +extern int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2); +extern int MAD2DecodeAndPrint(uint8_t *sector, bool verbose); #endif // _MAD_H_ diff --git a/client/mifare/mifaredefault.h b/client/mifare/mifaredefault.h index e7218cbe7..b12a57c03 100644 --- a/client/mifare/mifaredefault.h +++ b/client/mifare/mifaredefault.h @@ -42,8 +42,9 @@ static const uint64_t g_mifare_default_keys[] = 0x96a301bce267 }; -static const uint8_t g_mifare_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5}; +static const uint8_t g_mifare_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5}; static const uint8_t g_mifare_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}; -static const uint8_t g_mifarep_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7}; +static const uint8_t g_mifarep_mad_key[] = {0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7, 0xa0, 0xa1, 0xa2, 0xa3, 0xa4, 0xa5, 0xa6, 0xa7}; +static const uint8_t g_mifarep_ndef_key[] = {0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7, 0xd3, 0xf7}; #endif From f45c330843546a271f3b089368771f7bb54ed47e Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 4 Mar 2019 19:25:13 +0200 Subject: [PATCH 0640/1938] small visual fixes --- client/cmdhfmfp.c | 2 +- client/mifare/mifare4.c | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index e6363d64c..725dbca04 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -725,7 +725,7 @@ int CmdHFMFPMAD(const char *cmd) { } for(int j = 0; j < (verbose ? 4 : 3); j ++) - PrintAndLogEx(NORMAL, "---[%03d] %s", (i + 1) * 4 + j, sprint_hex(&vsector[j * 16], 16)); + PrintAndLogEx(NORMAL, " [%03d] %s", (i + 1) * 4 + j, sprint_hex(&vsector[j * 16], 16)); } } } diff --git a/client/mifare/mifare4.c b/client/mifare/mifare4.c index 3fe67077f..c95529a84 100644 --- a/client/mifare/mifare4.c +++ b/client/mifare/mifare4.c @@ -302,7 +302,8 @@ int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateF memmove(session->Kmac, kmac, 16); } - PrintAndLogEx(INFO, "Authentication OK"); + if (verbose) + PrintAndLogEx(INFO, "Authentication OK"); return 0; } From 9c8e60cf0338e0a07885b2830fd26052eaff32f2 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 4 Mar 2019 19:44:19 +0200 Subject: [PATCH 0641/1938] added to `hf mf mad` --- client/cmdhfmf.c | 62 ++++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 55 insertions(+), 7 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 6c6bc48e0..8823ea2d9 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -3219,39 +3219,87 @@ int CmdHF14AMfMAD(const char *cmd) { CLIParserInit("hf mf mad", "Checks and prints Mifare Application Directory (MAD)", - "Usage:\n\thf mf mad -> shows MAD if exists\n"); + "Usage:\n\thf mf mad -> shows MAD if exists\n" + "\thf mf mad -a 03e1 -k d3f7d3f7d3f7 -> shows NDEF data if exists\n"); void* argtable[] = { arg_param_begin, arg_lit0("vV", "verbose", "show technical data"), + arg_str0("aA", "aid", "print all sectors with aid", NULL), + arg_str0("kK", "key", "key for printing sectors", NULL), + arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"), arg_param_end }; CLIExecWithReturn(cmd, argtable, true); bool verbose = arg_get_lit(1); + uint8_t aid[2] = {0}; + int aidlen; + CLIGetHexWithReturn(2, aid, &aidlen); + uint8_t key[6] = {0}; + int keylen; + CLIGetHexWithReturn(3, key, &keylen); + bool keyB = arg_get_lit(4); CLIParserFree(); - uint8_t sector[16 * 4] = {0}; - if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector)) { + if (aidlen != 2 && keylen > 0) { + PrintAndLogEx(WARNING, "do not need a key without aid."); + } + + uint8_t sector0[16 * 4] = {0}; + uint8_t sector10[16 * 4] = {0}; + if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0)) { PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); return 2; } if (verbose) { for(int i = 0; i < 4; i ++) - PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(§or[i * 16], 16)); + PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(§or0[i * 16], 16)); } bool haveMAD2 = false; - MAD1DecodeAndPrint(sector, verbose, &haveMAD2); + MAD1DecodeAndPrint(sector0, verbose, &haveMAD2); if (haveMAD2) { - if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector)) { + if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10)) { PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); return 2; } - MAD2DecodeAndPrint(sector, verbose); + MAD2DecodeAndPrint(sector10, verbose); + } + + if (aidlen == 2) { + uint16_t aaid = (aid[0] << 8) + aid[1]; + PrintAndLogEx(NORMAL, "\n-------------- AID 0x%04x ---------------", aaid); + + uint16_t mad[7 + 8 + 8 + 8 + 8] = {0}; + size_t madlen = 0; + if (MADDecode(sector0, sector10, mad, &madlen)) { + PrintAndLogEx(ERR, "can't decode mad."); + return 10; + } + + uint8_t akey[6] = {0}; + memcpy(akey, g_mifare_ndef_key, 6); + if (keylen == 6) { + memcpy(akey, key, 6); + } + + for (int i = 0; i < madlen; i++) { + if (aaid == mad[i]) { + uint8_t vsector[16 * 4] = {0}; + if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, akey, vsector)) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(ERR, "read sector %d error.", i + 1); + return 2; + } + + for(int j = 0; j < (verbose ? 4 : 3); j ++) + PrintAndLogEx(NORMAL, " [%03d] %s", (i + 1) * 4 + j, sprint_hex(&vsector[j * 16], 16)); + } + } } return 0; From 54e81967742b688e98148a14b21db306b70b8e0d Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 4 Mar 2019 20:04:24 +0200 Subject: [PATCH 0642/1938] `hf mfp ndef` sketch --- client/cmdhfmfp.c | 44 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 44 insertions(+) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 725dbca04..ce31ff03a 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -733,6 +733,49 @@ int CmdHFMFPMAD(const char *cmd) { return 0; } +int CmdHFMFPNDEF(const char *cmd) { + + CLIParserInit("hf mfp ndef", + "Prints NFC Data Exchange Format (NDEF)", + "Usage:\n\thf mfp ndef -> shows NDEF data\n" + "\thf mfp ndef -a 03e1 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> shows NDEF data with custom AID and key\n"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("vV", "verbose", "show technical data"), + arg_str0("aA", "aid", "replace default aid for NDEF", NULL), + arg_str0("kK", "key", "replace default key for NDEF", NULL), + arg_lit0("bB", "keyb", "use key B for access sectors (by default: key A)"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + bool verbose = arg_get_lit(1); + uint8_t aid[2] = {0}; + int aidlen; + CLIGetHexWithReturn(2, aid, &aidlen); + uint8_t key[16] = {0}; + int keylen; + CLIGetHexWithReturn(3, key, &keylen); + bool keyB = arg_get_lit(4); + + CLIParserFree(); + + uint16_t ndefAID = 0x03e1; + if (aidlen == 2) + ndefAID = (aid[0] << 8) + aid[1]; + + uint8_t ndefkey[16] = {0}; + memcpy(ndefkey, g_mifarep_ndef_key, 16); + if (keylen == 16) { + memcpy(ndefkey, key, 16); + } + + uint8_t data[4096] = {0}; + int datalen = 0; + + return 0; +} static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, @@ -745,6 +788,7 @@ static command_t CommandTable[] = {"rdsc", CmdHFMFPRdsc, 0, "Read sectors"}, {"wrbl", CmdHFMFPWrbl, 0, "Write blocks"}, {"mad", CmdHFMFPMAD, 0, "Checks and prints MAD"}, + {"ndef", CmdHFMFPNDEF, 0, "Prints NDEF"}, {NULL, NULL, 0, NULL} }; From e191219d8a8f0cee34159167815c93edfe9fdede Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Mon, 4 Mar 2019 20:22:25 +0200 Subject: [PATCH 0643/1938] reading NDEF data from card --- client/cmdhfmfp.c | 57 +++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 57 insertions(+) diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index ce31ff03a..de47d9865 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -26,6 +26,7 @@ #include "mifare/mad.h" #include "cliparser/cliparser.h" #include "crypto/libpcrypto.h" +#include "emv/dump.h" static const uint8_t DefaultKey[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; @@ -771,9 +772,65 @@ int CmdHFMFPNDEF(const char *cmd) { memcpy(ndefkey, key, 16); } + uint8_t sector0[16 * 4] = {0}; + uint8_t sector10[16 * 4] = {0}; uint8_t data[4096] = {0}; int datalen = 0; + + PrintAndLogEx(NORMAL, ""); + if (mfpReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector0, verbose)) { + PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); + return 2; + } + + bool haveMAD2 = false; + int res = MADCheck(sector0, NULL, verbose, &haveMAD2); + if (res) { + PrintAndLogEx(ERR, "MAD error %d.", res); + return res; + } + + if (haveMAD2) { + if (mfpReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector10, verbose)) { + PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); + return 2; + } + } + + uint16_t mad[7 + 8 + 8 + 8 + 8] = {0}; + size_t madlen = 0; + if (MADDecode(sector0, (haveMAD2 ? sector10 : NULL), mad, &madlen)) { + PrintAndLogEx(ERR, "can't decode mad."); + return 10; + } + + printf("data reading:"); + for (int i = 0; i < madlen; i++) { + if (ndefAID == mad[i]) { + uint8_t vsector[16 * 4] = {0}; + if (mfpReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, ndefkey, vsector, false)) { + PrintAndLogEx(ERR, "read sector %d error.", i + 1); + return 2; + } + + memcpy(&data[datalen], vsector, 16 * 3); + datalen += 16 * 3; + + printf("."); + } + } + printf(" OK\n"); + + if (!datalen) { + PrintAndLogEx(ERR, "no NDEF data."); + return 11; + } + +// if (verbose) + PrintAndLogEx(NORMAL, "NDEF data:"); + dump_buffer(data, datalen, stdout, 1); + return 0; } static command_t CommandTable[] = From 0944a12744e3e0d30aa5e38b3f4fa4bbe8b03c6e Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Mon, 4 Mar 2019 20:27:52 +0100 Subject: [PATCH 0644/1938] Add missing header --- client/mifare/mad.h | 1 + 1 file changed, 1 insertion(+) diff --git a/client/mifare/mad.h b/client/mifare/mad.h index ee362adb6..6289982d9 100644 --- a/client/mifare/mad.h +++ b/client/mifare/mad.h @@ -13,6 +13,7 @@ #include #include +#include typedef struct { uint16_t AID; From 59bae84531e630837e7165c95b9a7cb723017303 Mon Sep 17 00:00:00 2001 From: sh7d <47714037+sh7d@users.noreply.github.com> Date: Mon, 4 Mar 2019 22:06:27 +0100 Subject: [PATCH 0645/1938] Mifare mad - do not exit if checksum is shitty --- client/mifare/mad.c | 16 +++++----------- 1 file changed, 5 insertions(+), 11 deletions(-) diff --git a/client/mifare/mad.c b/client/mifare/mad.c index 34ea50cfc..46a95f89d 100644 --- a/client/mifare/mad.c +++ b/client/mifare/mad.c @@ -112,14 +112,14 @@ int madCRCCheck(uint8_t *sector, bool verbose, int MADver) { uint8_t crc = CRC8Mad(§or[16 + 1], 15 + 16); if (crc != sector[16]) { if (verbose) - PrintAndLogEx(ERR, "Wrong MAD%d CRC. Calculated: 0x%02x, from card: 0x%02x", MADver, crc, sector[16]); + PrintAndLogEx(WARNING, "Wrong MAD%d CRC. Calculated: 0x%02x, from card: 0x%02x", MADver, crc, sector[16]); return 3; }; } else { uint8_t crc = CRC8Mad(§or[1], 15 + 16 + 16); if (crc != sector[0]) { if (verbose) - PrintAndLogEx(ERR, "Wrong MAD%d CRC. Calculated: 0x%02x, from card: 0x%02x", MADver, crc, sector[16]); + PrintAndLogEx(WARNING, "Wrong MAD%d CRC. Calculated: 0x%02x, from card: 0x%02x", MADver, crc, sector[16]); return 3; }; } @@ -191,9 +191,7 @@ int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2) int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen) { *madlen = 0; bool haveMAD2 = false; - int res = MADCheck(sector0, sector10, false, &haveMAD2); - if (res) - return res; + MADCheck(sector0, sector10, false, &haveMAD2); for (int i = 1; i < 16; i++) { mad[*madlen] = madGetAID(sector0, 1, i); @@ -219,10 +217,8 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { // check MAD1 only int res = MADCheck(sector, NULL, verbose, haveMAD2); - if (res) - return res; - if (verbose) + if (verbose && !res) PrintAndLogEx(NORMAL, "CRC8-MAD OK."); // info byte @@ -249,10 +245,8 @@ int MAD2DecodeAndPrint(uint8_t *sector, bool verbose) { PrintAndLogEx(NORMAL, "16 MAD2"); int res = madCRCCheck(sector, true, 2); - if (res) - return res; - if (verbose) + if (verbose && !res) PrintAndLogEx(NORMAL, "CRC8-MAD OK."); uint8_t InfoByte = sector[1] & 0x3f; From 760cd7b87cd0168c76321a31ed13730b42076af0 Mon Sep 17 00:00:00 2001 From: mazodude Date: Tue, 5 Mar 2019 08:36:04 +1100 Subject: [PATCH 0646/1938] Delete MAD script as merlokk has implemented it --- client/scripts/mifare_ad.lua | 223 ----------------------------------- 1 file changed, 223 deletions(-) delete mode 100644 client/scripts/mifare_ad.lua diff --git a/client/scripts/mifare_ad.lua b/client/scripts/mifare_ad.lua deleted file mode 100644 index 885c25a81..000000000 --- a/client/scripts/mifare_ad.lua +++ /dev/null @@ -1,223 +0,0 @@ - --- Ability to read what card is there -local getopt = require('getopt') -local cmds = require('commands') -local taglib = require('taglib') -local lib14a = require('read14a') - -local desc = -[[This script will automatically check Mifare cards for MADs -(Mifare Application Directory) - -Arguments: - -d debug logging on - -h this help - -]] -local example = "script run xxx" -local author = "Mazodude" ---- --- This is only meant to be used when errors occur -local function oops(err) - print("ERROR: ",err) - return nil,err -end - ---- --- Usage help -local function help() - print(desc) - print("Example usage") - print(example) -end - -local function debug(...) - if DEBUG then - print("debug:", ...) - end -end - -local function show(data) - if DEBUG then - local formatString = ("H%d"):format(string.len(data)) - local _,hexdata = bin.unpack(formatString, data) - debug("Hexdata" , hexdata) - end -end - -local function bits(num) - local t={} - while num>0 do - rest=num%2 - table.insert(t,1,rest) - num=(num-rest)/2 - end return table.concat(t) -end ---- Shut down tag communication --- return no return values -local function close() - debug("Closing connection") - core.clearCommandBuffer() - local x = string.format("hf 14a raw -r") - debug(x) - core.console(x) - debug("done") - --data, err = waitCmd(true) - --data, err = waitCmd(false) - -end - - --- waits for answer from pm3 device -local function checkCommand(command) - core.clearCommandBuffer() - local usb = command:getBytes() - core.SendCommand(usb) - local result = core.WaitForResponseTimeout(cmds.CMD_ACK, 1500) - - if result then - local count, cmd, arg0 = bin.unpack('LL',result) - if(arg0==1) then - local count, arg1, arg2, data = bin.unpack('LLH511',result,count) - sector = data - return sector - else - return nil - end - else - print("Timeout while waiting for response. Increase TIMEOUT in mifare_ad.lua to wait longer") - return nil, "Timeout while waiting for device to respond" - end -end - ----_ Gets data from a sector --- @return sector if successfull --- @return nil, errormessage if unsuccessfull -local function getSector(sector,typ) - local data, err - - core.clearCommandBuffer() - - -- // params - -- uint8_t sectorNo = arg0; - -- uint8_t keyType = arg1; - -- uint64_t ui64Key = 0; - -- ui64Key = bytes_to_num(datain, 6); - local sectorNo = sector - local keyType = 0 - local key = "" - if typ == 1 then - key = "A0A1A2A3A4A5" - end - debug(("Testing to auth with key %s"):format(key)) - -- print(key); - local command = Command:new{cmd = cmds.CMD_MIFARE_READSC, - arg1 = sectorNo, - arg2 = keyType, - arg3 = 0, - data = key} - local data = checkCommand(command) - -- debug(command) - -- print(data) - if (data == nil) then return err, ("Could not auth with card - this tag does not have MADs") end - if string.len(data) < 32 then - return nil, ("Expected at least 32 bytes, got %d - this tag does not have MADs"):format(string.len(data)) - end - return data -end - - ---- This function is a lua-implementation of --- cmdhf14a.c:waitCmd(uint8_t iSelect) -local function waitCmd(iSelect) - local response = core.WaitForResponseTimeout(cmds.CMD_ACK,1000) - if response then - local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response) - local iLen = arg0 - if iSelect then iLen = arg1 end - debug(("Received %i octets (arg0:%d, arg1:%d)"):format(iLen, arg0, arg1)) - if iLen == 0 then return nil, "No response from tag" end - local recv = string.sub(response,count, iLen+count-1) - return recv - end - return nil, "No response from device" -end - - - -local function main( args) - debug("script started") - local err, data, data2,k,v,i - -- Read the parameters - for o, a in getopt.getopt(args, 'hd') do - if o == "h" then help() return end - if o == "d" then DEBUG = true end - end - - local tag, err = lib14a.read(false, true) - if not tag then return oops("No card present") end - core.clearCommandBuffer() - print(("UID: %s"):format(tag.uid)) - print(("SAK: %x"):format(tag.sak)) - - local typ = 1 - if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k - typ = 4 - elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K - typ= 1 - elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k - typ = 0 - elseif 0x10 == sak then-- "NXP MIFARE Plus 2k" - typ = 2 - elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K" - typ = 1 - else - debug("Defaulting to CLASSIC") - end - - -- # | data | Sector | 00/ 0x00 - -- ----+------------------------------------------------ - -- 0 | 5C 71 B0 14 89 88 04 00 C0 8E 3C 90 49 50 12 13 - -- 1 | 80 0F 00 00 00 00 00 00 00 00 00 00 00 00 00 00 - -- 2 | 00 00 00 00 00 00 00 00 00 00 00 00 00 00 12 48 - -- 3 | A0 A1 A2 A3 A4 A5 78 77 88 E9 B0 B1 B2 B3 B4 B5 - - -- E9 = 1 1 1010 01 - -- C1 = 1 1 0000 01 - -- 69 = 0 1 1010 01 - -- 99 = 1 0 0110 01 - - -- Need to check the sector trailer GPB - -- First, get Sector 0 block 3 byte 10 - local sector, err = getSector(0,1) - if err then return oops(err) end - -- -- Now, parse out the block data - sector = sector:sub(0,128) - debug(sector) - local trailer = sector:sub(97,128) - debug(trailer) - local gpb = string.sub(trailer,19,20) - debug(("Checking block 0 sector 3 byte 10")) - debug(("Got byte: %s"):format(gpb)) - local gpbbits = bits(tonumber(gpb,16)) - debug(gpbbits) - local adv = gpbbits:sub(7,8) - print(("ADV: %s"):format(adv)) - local rfu = gpbbits:sub(3,6) - print(("RFU: %s"):format(rfu)) - local ma = gpbbits:sub(2,2) - print(("MA: %s"):format(ma)) - local da = gpbbits:sub(1,1) - print(("DA: %s"):format(da)) - -- prlog(block) - if adv == "01" then - print('Card has MADs v1') - end - if adv == "10" then - print('Card has MADs v2') - end - - -- Deactivate field - close() -end -main(args) \ No newline at end of file From cbe25f48328a1dd856db1b739097f3026b005b29 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 5 Mar 2019 00:11:31 +0200 Subject: [PATCH 0647/1938] add ndef.c/h --- client/Makefile | 1 + client/cmdhfmfp.c | 9 +++++++-- client/mifare/ndef.c | 16 ++++++++++++++++ client/mifare/ndef.h | 19 +++++++++++++++++++ 4 files changed, 43 insertions(+), 2 deletions(-) create mode 100644 client/mifare/ndef.c create mode 100644 client/mifare/ndef.h diff --git a/client/Makefile b/client/Makefile index 051468ba9..d83fbff5f 100644 --- a/client/Makefile +++ b/client/Makefile @@ -158,6 +158,7 @@ CMDSRCS = crapto1/crapto1.c \ emv/emv_roca.c \ mifare/mifare4.c \ mifare/mad.c \ + mifare/ndef.c \ cmdanalyse.c \ cmdhf.c \ cmdhflist.c \ diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index de47d9865..20b6d0fce 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -24,6 +24,7 @@ #include "mifare.h" #include "mifare/mifare4.h" #include "mifare/mad.h" +#include "mifare/ndef.h" #include "cliparser/cliparser.h" #include "crypto/libpcrypto.h" #include "emv/dump.h" @@ -743,7 +744,7 @@ int CmdHFMFPNDEF(const char *cmd) { void* argtable[] = { arg_param_begin, - arg_lit0("vV", "verbose", "show technical data"), + arg_litn("vV", "verbose", 0, 2, "show technical data"), arg_str0("aA", "aid", "replace default aid for NDEF", NULL), arg_str0("kK", "key", "replace default key for NDEF", NULL), arg_lit0("bB", "keyb", "use key B for access sectors (by default: key A)"), @@ -752,6 +753,7 @@ int CmdHFMFPNDEF(const char *cmd) { CLIExecWithReturn(cmd, argtable, true); bool verbose = arg_get_lit(1); + bool verbose2 = arg_get_lit(1) > 1; uint8_t aid[2] = {0}; int aidlen; CLIGetHexWithReturn(2, aid, &aidlen); @@ -827,9 +829,12 @@ int CmdHFMFPNDEF(const char *cmd) { return 11; } -// if (verbose) + if (verbose2) { PrintAndLogEx(NORMAL, "NDEF data:"); dump_buffer(data, datalen, stdout, 1); + } + + NDEFDecodeAndPrint(data, datalen, verbose); return 0; } diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c new file mode 100644 index 000000000..22deb0809 --- /dev/null +++ b/client/mifare/ndef.c @@ -0,0 +1,16 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2019 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// NFC Data Exchange Format (NDEF) functions +//----------------------------------------------------------------------------- + +#include "ndef.h" + +int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { + + return 0; +} diff --git a/client/mifare/ndef.h b/client/mifare/ndef.h new file mode 100644 index 000000000..6e79887ee --- /dev/null +++ b/client/mifare/ndef.h @@ -0,0 +1,19 @@ +//----------------------------------------------------------------------------- +// Copyright (C) 2019 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// NFC Data Exchange Format (NDEF) functions +//----------------------------------------------------------------------------- + +#ifndef _NDEF_H_ +#define _NDEF_H_ + +#include +#include + +extern int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose); + +#endif // _NDEF_H_ From 0a30e03aaf2102532db9f37384fd26caae0564f9 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 5 Mar 2019 00:13:01 +0200 Subject: [PATCH 0648/1938] add header --- client/mifare/ndef.h | 1 + 1 file changed, 1 insertion(+) diff --git a/client/mifare/ndef.h b/client/mifare/ndef.h index 6e79887ee..0aa4cca27 100644 --- a/client/mifare/ndef.h +++ b/client/mifare/ndef.h @@ -13,6 +13,7 @@ #include #include +#include extern int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose); From a2f8f0628c02c79cae965bbf35f5ab93fa7d83b0 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 5 Mar 2019 00:48:02 +0200 Subject: [PATCH 0649/1938] added ndef tlv parsing --- client/mifare/ndef.c | 58 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 58 insertions(+) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index 22deb0809..e5ce5fe11 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -9,8 +9,66 @@ //----------------------------------------------------------------------------- #include "ndef.h" +#include "ui.h" + +uint16_t ndefTLVGetLength(uint8_t *data, size_t *indx) { + uint16_t len = 0; + if (data[0] == 0xff) { + len = (data[1] << 8) + data[2]; + *indx += 3; + } else { + len = data[0]; + *indx += 1; + } + + return len; +} int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { + size_t indx = 0; + + while (indx < ndefLen) { + switch (ndef[indx]) { + case 0x00: { + indx++; + uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); + PrintAndLogEx(INFO, "NDEF NULL block."); + if (len) + PrintAndLogEx(WARNING, "NDEF NULL block size must be 0 instead of %d.", len); + indx += len; + break; + } + case 0x03: { + indx++; + uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); + PrintAndLogEx(INFO, "NDEF message. len: %d", len); + + // ndef decode + + + + indx += len; + break; + } + case 0xfd: { + indx++; + uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); + PrintAndLogEx(INFO, "NDEF proprietary info. Skipped %d bytes.", len); + indx += len; + break; + } + case 0xfe: { + PrintAndLogEx(INFO, "NDEF Terminator. Done."); + return 0; + break; + } + default: { + PrintAndLogEx(ERR, "unknown tag 0x%02x", ndef[indx]); + return 1; + } + } + } + return 0; } From 64a5b355b5ae336669814d98c49319db716095fd Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 5 Mar 2019 00:51:32 +0200 Subject: [PATCH 0650/1938] added ndef record parse sketch --- client/mifare/ndef.c | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index e5ce5fe11..f827eb5a7 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -24,6 +24,14 @@ uint16_t ndefTLVGetLength(uint8_t *data, size_t *indx) { return len; } +int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { + + + + + return 0; +} + int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { size_t indx = 0; @@ -44,9 +52,9 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); PrintAndLogEx(INFO, "NDEF message. len: %d", len); - // ndef decode - - + int res = ndefRecordDecodeAndPrint(&ndef[indx], len); + if (res) + return res; indx += len; break; From 3bf618ca563fc9b64f76673c80a09f35f9257978 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 5 Mar 2019 00:54:45 +0200 Subject: [PATCH 0651/1938] log structure --- client/mifare/ndef.c | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index f827eb5a7..a4c5332eb 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -36,12 +36,13 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { size_t indx = 0; + PrintAndLogEx(INFO, "NDEF decoding:"); while (indx < ndefLen) { switch (ndef[indx]) { case 0x00: { indx++; uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); - PrintAndLogEx(INFO, "NDEF NULL block."); + PrintAndLogEx(INFO, "-- NDEF NULL block."); if (len) PrintAndLogEx(WARNING, "NDEF NULL block size must be 0 instead of %d.", len); indx += len; @@ -50,7 +51,7 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { case 0x03: { indx++; uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); - PrintAndLogEx(INFO, "NDEF message. len: %d", len); + PrintAndLogEx(INFO, "-- NDEF message. len: %d", len); int res = ndefRecordDecodeAndPrint(&ndef[indx], len); if (res) @@ -62,12 +63,12 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { case 0xfd: { indx++; uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); - PrintAndLogEx(INFO, "NDEF proprietary info. Skipped %d bytes.", len); + PrintAndLogEx(INFO, "-- NDEF proprietary info. Skipped %d bytes.", len); indx += len; break; } case 0xfe: { - PrintAndLogEx(INFO, "NDEF Terminator. Done."); + PrintAndLogEx(INFO, "-- NDEF Terminator. Done."); return 0; break; } From 34a133451e011acc91afde4104af4f58becf41e5 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 5 Mar 2019 01:02:54 +0200 Subject: [PATCH 0652/1938] small addon --- client/mifare/ndef.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index a4c5332eb..4923b0081 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -24,7 +24,7 @@ uint16_t ndefTLVGetLength(uint8_t *data, size_t *indx) { return len; } -int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { +int ndefRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { @@ -53,7 +53,7 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); PrintAndLogEx(INFO, "-- NDEF message. len: %d", len); - int res = ndefRecordDecodeAndPrint(&ndef[indx], len); + int res = ndefRecordsDecodeAndPrint(&ndef[indx], len); if (res) return res; From fffa921aa04bf1b73e639fb93ffca4b32b73cd64 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 5 Mar 2019 16:41:20 +0200 Subject: [PATCH 0653/1938] ndef record decode OK --- client/mifare/ndef.c | 123 ++++++++++++++++++++++++++++++++++++++++++- client/mifare/ndef.h | 24 +++++++++ 2 files changed, 145 insertions(+), 2 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index 4923b0081..4dd200759 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -10,6 +10,20 @@ #include "ndef.h" #include "ui.h" +#include "emv/dump.h" + +#define STRBOOL(p) ((p) ? "+" : "-") + +static const char *TypeNameFormat_s[] = { + "Empty Record", + "Well Known Record", + "MIME Media Record", + "Absolute URI Record", + "External Record", + "Unknown Record", + "Unchanged Record" + "n/a" +}; uint16_t ndefTLVGetLength(uint8_t *data, size_t *indx) { uint16_t len = 0; @@ -24,10 +38,115 @@ uint16_t ndefTLVGetLength(uint8_t *data, size_t *indx) { return len; } +int ndefDecodeHeader(uint8_t *data, size_t datalen, NDEFHeader_t *header) { + header->MessageBegin = data[0] & 0x80; + header->MessageEnd = data[0] & 0x40; + header->ChunkFlag = data[0] & 0x20; + header->ShortRecordBit = data[0] & 0x10; + header->IDLenPresent = data[0] & 0x08; + header->TypeNameFormat = data[0] & 0x07; + header->len = 1 + 1 + (header->ShortRecordBit ? 1 : 4) + (header->IDLenPresent ? 1 : 0); // header + typelen + payloadlen + idlen + if (header->len > datalen) + return 1; + + header->TypeLen = data[1]; + + header->PayloadLen = (header->ShortRecordBit ? (data[2]) : ((data[2] << 24) + (data[3] << 16) + (data[4] << 8) + data[5])); + + if (header->IDLenPresent) + header->IDLen = (header->ShortRecordBit ? (data[3]) : (data[6])); + else + header->IDLen = 0; + + header->RecLen = header->len + header->TypeLen + header->PayloadLen + header->IDLen; + + if (header->RecLen > datalen) + return 3; + + return 0; +} + +int ndefPrintHeader(NDEFHeader_t *header) { + PrintAndLogEx(INFO, "Header:"); + + PrintAndLogEx(NORMAL, "\tMessage Begin: %s", STRBOOL(header->MessageBegin)); + PrintAndLogEx(NORMAL, "\tMessage End: %s", STRBOOL(header->MessageEnd)); + PrintAndLogEx(NORMAL, "\tChunk Flag: %s", STRBOOL(header->ChunkFlag)); + PrintAndLogEx(NORMAL, "\tShort Record Bit: %s", STRBOOL(header->ShortRecordBit)); + PrintAndLogEx(NORMAL, "\tID Len Present: %s", STRBOOL(header->IDLenPresent)); + PrintAndLogEx(NORMAL, "\tType Name Format: [0x%02x] %s", header->TypeNameFormat, TypeNameFormat_s[header->TypeNameFormat]); + + PrintAndLogEx(NORMAL, "\tHeader length : %d", header->len); + PrintAndLogEx(NORMAL, "\tType length : %d", header->TypeLen); + PrintAndLogEx(NORMAL, "\tPayload length : %d", header->PayloadLen); + PrintAndLogEx(NORMAL, "\tID length : %d", header->IDLen); + PrintAndLogEx(NORMAL, "\tRecord length : %d", header->RecLen); + + return 0; +} + +int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { + + NDEFHeader_t NDEFHeader = {0}; + int res = ndefDecodeHeader(ndefRecord, ndefRecordLen, &NDEFHeader); + if (res) + return res; + + ndefPrintHeader(&NDEFHeader); + + size_t indx = NDEFHeader.len; + if (NDEFHeader.TypeLen) { + PrintAndLogEx(INFO, "Type data:"); + dump_buffer(&ndefRecord[indx], NDEFHeader.TypeLen, stdout, 1); + + indx += NDEFHeader.TypeLen; + } + if (NDEFHeader.IDLen) { + PrintAndLogEx(INFO, "ID data:"); + dump_buffer(&ndefRecord[indx], NDEFHeader.IDLen, stdout, 1); + + indx += NDEFHeader.IDLen; + } + if (NDEFHeader.PayloadLen) { + PrintAndLogEx(INFO, "Payload data:"); + dump_buffer(&ndefRecord[indx], NDEFHeader.PayloadLen, stdout, 1); + + indx += NDEFHeader.PayloadLen; + } + + return 0; +} + int ndefRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { + bool firstRec = true; + size_t len = 0; - - + while (len < ndefRecordLen) { + NDEFHeader_t NDEFHeader = {0}; + int res = ndefDecodeHeader(&ndefRecord[len], ndefRecordLen - len, &NDEFHeader); + if (res) + return res; + + if (firstRec) { + if (!NDEFHeader.MessageBegin) { + PrintAndLogEx(ERR, "NDEF first record have MessageBegin=false!"); + return 1; + } + firstRec = false; + } + + if (NDEFHeader.MessageEnd && len + NDEFHeader.RecLen != ndefRecordLen) { + PrintAndLogEx(ERR, "NDEF records have wrong length. Must be %d, calculated %d", ndefRecordLen, len + NDEFHeader.RecLen); + return 1; + } + + ndefRecordDecodeAndPrint(&ndefRecord[len], NDEFHeader.RecLen); + + len += NDEFHeader.len + NDEFHeader.TypeLen + NDEFHeader.PayloadLen + NDEFHeader.IDLen; + + if (NDEFHeader.MessageEnd) + break; + } return 0; } diff --git a/client/mifare/ndef.h b/client/mifare/ndef.h index 0aa4cca27..25723158c 100644 --- a/client/mifare/ndef.h +++ b/client/mifare/ndef.h @@ -15,6 +15,30 @@ #include #include +typedef enum { + tnfEmptyRecord = 0x00, + tnfWellKnownRecord = 0x01, + tnfMIMEMediaRecord = 0x02, + tnfAbsoluteURIRecord = 0x03, + tnfExternalRecord = 0x04, + tnfUnknownRecord = 0x05, + tnfUnchangedRecord = 0x06 +} TypeNameFormat_t; + +typedef struct { + bool MessageBegin; + bool MessageEnd; + bool ChunkFlag; + bool ShortRecordBit; + bool IDLenPresent; + TypeNameFormat_t TypeNameFormat; + size_t TypeLen; + size_t PayloadLen; + size_t IDLen; + size_t len; + size_t RecLen; +} NDEFHeader_t; + extern int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose); #endif // _NDEF_H_ From 7003783c089160015f83f4aa2bf1d893a49a765f Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 5 Mar 2019 16:43:13 +0200 Subject: [PATCH 0654/1938] refactoring --- client/mifare/ndef.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index 4dd200759..15a7292c3 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -142,7 +142,7 @@ int ndefRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { ndefRecordDecodeAndPrint(&ndefRecord[len], NDEFHeader.RecLen); - len += NDEFHeader.len + NDEFHeader.TypeLen + NDEFHeader.PayloadLen + NDEFHeader.IDLen; + len += NDEFHeader.RecLen; if (NDEFHeader.MessageEnd) break; From c7c97d35b55b316b52196a1097b8c68dec8fda1c Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 5 Mar 2019 17:25:11 +0200 Subject: [PATCH 0655/1938] some code to decoding payload --- client/mifare/ndef.c | 66 +++++++++++++++++++++++++++++++++----------- client/mifare/ndef.h | 3 ++ 2 files changed, 53 insertions(+), 16 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index 15a7292c3..f6d7f5c15 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -39,6 +39,10 @@ uint16_t ndefTLVGetLength(uint8_t *data, size_t *indx) { } int ndefDecodeHeader(uint8_t *data, size_t datalen, NDEFHeader_t *header) { + header->Type = NULL; + header->Payload = NULL; + header->ID = NULL; + header->MessageBegin = data[0] & 0x80; header->MessageEnd = data[0] & 0x40; header->ChunkFlag = data[0] & 0x20; @@ -49,16 +53,21 @@ int ndefDecodeHeader(uint8_t *data, size_t datalen, NDEFHeader_t *header) { if (header->len > datalen) return 1; - header->TypeLen = data[1]; + header->TypeLen = data[1]; + header->Type = data + header->len; - header->PayloadLen = (header->ShortRecordBit ? (data[2]) : ((data[2] << 24) + (data[3] << 16) + (data[4] << 8) + data[5])); + header->PayloadLen = (header->ShortRecordBit ? (data[2]) : ((data[2] << 24) + (data[3] << 16) + (data[4] << 8) + data[5])); - if (header->IDLenPresent) + if (header->IDLenPresent) { header->IDLen = (header->ShortRecordBit ? (data[3]) : (data[6])); - else + header->Payload = header->Type + header->TypeLen; + } else { header->IDLen = 0; + } + + header->Payload = header->Type + header->TypeLen + header->IDLen; - header->RecLen = header->len + header->TypeLen + header->PayloadLen + header->IDLen; + header->RecLen = header->len + header->TypeLen + header->PayloadLen + header->IDLen; if (header->RecLen > datalen) return 3; @@ -85,8 +94,38 @@ int ndefPrintHeader(NDEFHeader_t *header) { return 0; } -int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { +int ndefDecodePayload(NDEFHeader_t *ndef) { + switch(ndef->TypeNameFormat) { + case tnfWellKnownRecord: + PrintAndLogEx(INFO, "Well Known Record"); + PrintAndLogEx(NORMAL, "\ttype: %.*s", ndef->TypeLen, ndef->Type); + + if (!strncmp((char *)ndef->Type, "T", ndef->TypeLen)) { + PrintAndLogEx(NORMAL, "\ttext : %.*s", ndef->PayloadLen, ndef->Payload); + } + + if (!strncmp((char *)ndef->Type, "U", ndef->TypeLen)) { + PrintAndLogEx(NORMAL, "\turi : %.*s", ndef->PayloadLen, ndef->Payload); + } + + if (!strncmp((char *)ndef->Type, "Sig", ndef->TypeLen)) { + printf("--sig\n"); + } + + break; + case tnfAbsoluteURIRecord: + PrintAndLogEx(INFO, "Absolute URI Record"); + PrintAndLogEx(NORMAL, "\ttype: %.*s", ndef->TypeLen, ndef->Type); + PrintAndLogEx(NORMAL, "\tpayload: %.*s", ndef->PayloadLen, ndef->Payload); + break; + default: + break; + } + return 0; +} + +int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { NDEFHeader_t NDEFHeader = {0}; int res = ndefDecodeHeader(ndefRecord, ndefRecordLen, &NDEFHeader); if (res) @@ -94,24 +133,19 @@ int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { ndefPrintHeader(&NDEFHeader); - size_t indx = NDEFHeader.len; if (NDEFHeader.TypeLen) { PrintAndLogEx(INFO, "Type data:"); - dump_buffer(&ndefRecord[indx], NDEFHeader.TypeLen, stdout, 1); - - indx += NDEFHeader.TypeLen; + dump_buffer(NDEFHeader.Type, NDEFHeader.TypeLen, stdout, 1); } if (NDEFHeader.IDLen) { PrintAndLogEx(INFO, "ID data:"); - dump_buffer(&ndefRecord[indx], NDEFHeader.IDLen, stdout, 1); - - indx += NDEFHeader.IDLen; + dump_buffer(NDEFHeader.ID, NDEFHeader.IDLen, stdout, 1); } if (NDEFHeader.PayloadLen) { PrintAndLogEx(INFO, "Payload data:"); - dump_buffer(&ndefRecord[indx], NDEFHeader.PayloadLen, stdout, 1); - - indx += NDEFHeader.PayloadLen; + dump_buffer(NDEFHeader.Payload, NDEFHeader.PayloadLen, stdout, 1); + if (NDEFHeader.TypeLen) + ndefDecodePayload(&NDEFHeader); } return 0; diff --git a/client/mifare/ndef.h b/client/mifare/ndef.h index 25723158c..35a589602 100644 --- a/client/mifare/ndef.h +++ b/client/mifare/ndef.h @@ -37,6 +37,9 @@ typedef struct { size_t IDLen; size_t len; size_t RecLen; + uint8_t *Type; + uint8_t *Payload; + uint8_t *ID; } NDEFHeader_t; extern int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose); From 4ffeebc19310cd2d4eafdab6c2ae3f5cc92e778d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 5 Mar 2019 16:39:26 +0100 Subject: [PATCH 0656/1938] Fix return code check for iso14443b_select_card in hf epa --- armsrc/epa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/epa.c b/armsrc/epa.c index e97fda7a0..71ecc29a3 100644 --- a/armsrc/epa.c +++ b/armsrc/epa.c @@ -544,7 +544,7 @@ int EPA_Setup() iso14443b_setup(); // select the card return_code = iso14443b_select_card( &card_b_info ); - if (return_code == 1) { + if (return_code == 0) { Dbprintf("ISO 14443 Type B"); iso_type = 'b'; return 0; From a2be59db25ab065efb92c000a676168d7c96c167 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 5 Mar 2019 17:50:51 +0200 Subject: [PATCH 0657/1938] URI decode --- client/mifare/ndef.c | 54 ++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 52 insertions(+), 2 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index f6d7f5c15..cacc0c9c4 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -25,6 +25,45 @@ static const char *TypeNameFormat_s[] = { "n/a" }; +static const char *URI_s[] = { + "", // 0x00 + "http://www.", // 0x01 + "https://www.", // 0x02 + "http://", // 0x03 + "https://", // 0x04 + "tel:", // 0x05 + "mailto:", // 0x06 + "ftp://anonymous:anonymous@", // 0x07 + "ftp://ftp.", // 0x08 + "ftps://", // 0x09 + "sftp://", // 0x0A + "smb://", // 0x0B + "nfs://", // 0x0C + "ftp://", // 0x0D + "dav://", // 0x0E + "news:", // 0x0F + "telnet://", // 0x10 + "imap:", // 0x11 + "rtsp://", // 0x12 + "urn:", // 0x13 + "pop:", // 0x14 + "sip:", // 0x15 + "sips:", // 0x16 + "tftp:", // 0x17 + "btspp://", // 0x18 + "btl2cap://", // 0x19 + "btgoep://", // 0x1A + "tcpobex://", // 0x1B + "irdaobex://", // 0x1C + "file://", // 0x1D + "urn:epc:id:", // 0x1E + "urn:epc:tag:", // 0x1F + "urn:epc:pat:", // 0x20 + "urn:epc:raw:", // 0x21 + "urn:epc:", // 0x22 + "urn:nfc:" // 0x23 +}; + uint16_t ndefTLVGetLength(uint8_t *data, size_t *indx) { uint16_t len = 0; if (data[0] == 0xff) { @@ -94,6 +133,17 @@ int ndefPrintHeader(NDEFHeader_t *header) { return 0; } +int ndefDecodeSig(uint8_t *sig, size_t siglen) { + PrintAndLogEx(NORMAL, "\tsignature version: 0x%02x", sig[0]); + if (sig[0] != 0x01) { + PrintAndLogEx(ERR, "signature version unknown."); + return 1; + } + + + return 0; +}; + int ndefDecodePayload(NDEFHeader_t *ndef) { switch(ndef->TypeNameFormat) { @@ -106,11 +156,11 @@ int ndefDecodePayload(NDEFHeader_t *ndef) { } if (!strncmp((char *)ndef->Type, "U", ndef->TypeLen)) { - PrintAndLogEx(NORMAL, "\turi : %.*s", ndef->PayloadLen, ndef->Payload); + PrintAndLogEx(NORMAL, "\turi : %s%.*s", (ndef->Payload[0] <= 0x23 ? URI_s[ndef->Payload[0]] : "[err]"), ndef->PayloadLen, &ndef->Payload[1]); } if (!strncmp((char *)ndef->Type, "Sig", ndef->TypeLen)) { - printf("--sig\n"); + ndefDecodeSig(ndef->Payload, ndef->PayloadLen); } break; From 581fe408ba793af8f3b578b6939203681e6a6b0b Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 5 Mar 2019 18:14:30 +0200 Subject: [PATCH 0658/1938] ndef `sig` decoding --- client/mifare/ndef.c | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index cacc0c9c4..96911f607 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -11,6 +11,7 @@ #include "ndef.h" #include "ui.h" #include "emv/dump.h" +#include "crypto/asn1utils.h" #define STRBOOL(p) ((p) ? "+" : "-") @@ -134,13 +135,44 @@ int ndefPrintHeader(NDEFHeader_t *header) { } int ndefDecodeSig(uint8_t *sig, size_t siglen) { + size_t indx = 0; PrintAndLogEx(NORMAL, "\tsignature version: 0x%02x", sig[0]); if (sig[0] != 0x01) { PrintAndLogEx(ERR, "signature version unknown."); return 1; } + indx++; - + while (indx < siglen) { + if (sig[indx] == 0x04) { + size_t intsiglen = (sig[indx + 1] << 8) + sig[indx + 2]; + indx += 3; + PrintAndLogEx(NORMAL, "\tsignature [%d]: %s", intsiglen, sprint_hex_inrow(&sig[indx], intsiglen)); + + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; + int res = ecdsa_asn1_get_signature(&sig[indx], intsiglen, rval, sval); + if (!res) { + PrintAndLogEx(NORMAL ,"\t\tr: %s", sprint_hex(rval, 32)); + PrintAndLogEx(NORMAL ,"\t\ts: %s", sprint_hex(sval, 32)); + } + + indx += intsiglen; + continue; + } + + if (sig[indx] == 0x80) { + size_t intchainlen = (sig[indx + 1] << 8) + sig[indx + 2]; + indx += 3; + PrintAndLogEx(NORMAL, "\tchain [%d]: %.*s", intchainlen, intchainlen, &sig[indx]); + indx += intchainlen; + continue; + } + + size_t skiplen = (sig[indx + 1] << 8) + sig[indx + 2]; + indx += skiplen; + } + return 0; }; From 04a6a634270356d1f654f42763785a0f7d19d237 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 5 Mar 2019 18:43:12 +0200 Subject: [PATCH 0659/1938] rename --- client/mifare/ndef.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index 96911f607..dbb4a7bd2 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -162,10 +162,10 @@ int ndefDecodeSig(uint8_t *sig, size_t siglen) { } if (sig[indx] == 0x80) { - size_t intchainlen = (sig[indx + 1] << 8) + sig[indx + 2]; + size_t inturilen = (sig[indx + 1] << 8) + sig[indx + 2]; indx += 3; - PrintAndLogEx(NORMAL, "\tchain [%d]: %.*s", intchainlen, intchainlen, &sig[indx]); - indx += intchainlen; + PrintAndLogEx(NORMAL, "\tsignature uri [%d]: %.*s", inturilen, inturilen, &sig[indx]); + indx += inturilen; continue; } From 53e0d030985574e30189288ebf228aea9a052402 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 5 Mar 2019 19:41:50 +0200 Subject: [PATCH 0660/1938] ndef cert right decode. https://github.com/skjolber/ndef-tools-for-android/blob/master/ndeftools/src/org/ndeftools/wellknown/SignatureRecord.java https://github.com/nfcpy/ndeflib/blob/master/src/ndef/signature.py --- client/mifare/ndef.c | 91 +++++++++++++++++++++++++++++++------------- client/mifare/ndef.h | 15 ++++++++ 2 files changed, 80 insertions(+), 26 deletions(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index dbb4a7bd2..13a793725 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -26,6 +26,21 @@ static const char *TypeNameFormat_s[] = { "n/a" }; +static const char *ndefSigType_s[] = { + "Not present", // No signature present + "RSASSA_PSS_SHA_1", // PKCS_1 + "RSASSA_PKCS1_v1_5_WITH_SHA_1", // PKCS_1 + "DSA", + "ECDSA", + "n/a" +}; + +static const char *ndefCertificateFormat_s[] = { + "X_509", + "X9_68", + "n/a" +}; + static const char *URI_s[] = { "", // 0x00 "http://www.", // 0x01 @@ -143,36 +158,60 @@ int ndefDecodeSig(uint8_t *sig, size_t siglen) { } indx++; - while (indx < siglen) { - if (sig[indx] == 0x04) { - size_t intsiglen = (sig[indx + 1] << 8) + sig[indx + 2]; - indx += 3; - PrintAndLogEx(NORMAL, "\tsignature [%d]: %s", intsiglen, sprint_hex_inrow(&sig[indx], intsiglen)); - - uint8_t rval[300] = {0}; - uint8_t sval[300] = {0}; - int res = ecdsa_asn1_get_signature(&sig[indx], intsiglen, rval, sval); - if (!res) { - PrintAndLogEx(NORMAL ,"\t\tr: %s", sprint_hex(rval, 32)); - PrintAndLogEx(NORMAL ,"\t\ts: %s", sprint_hex(sval, 32)); - } - - indx += intsiglen; - continue; - } + uint8_t sigType = sig[indx] & 0x7f; + bool sigURI = sig[indx] & 0x80; - if (sig[indx] == 0x80) { - size_t inturilen = (sig[indx + 1] << 8) + sig[indx + 2]; - indx += 3; - PrintAndLogEx(NORMAL, "\tsignature uri [%d]: %.*s", inturilen, inturilen, &sig[indx]); - indx += inturilen; - continue; - } + PrintAndLogEx(NORMAL, "\tsignature type: %s", ((sigType < stNA) ? ndefSigType_s[sigType] : ndefSigType_s[stNA])); + PrintAndLogEx(NORMAL, "\tsignature uri: %s", (sigURI ? "present" : "not present")); + + size_t intsiglen = (sig[indx + 1] << 8) + sig[indx + 2]; + // ecdsa 0x04 + if (sigType == stECDSA) { + indx += 3; + PrintAndLogEx(NORMAL, "\tsignature [%d]: %s", intsiglen, sprint_hex_inrow(&sig[indx], intsiglen)); - size_t skiplen = (sig[indx + 1] << 8) + sig[indx + 2]; - indx += skiplen; + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; + int res = ecdsa_asn1_get_signature(&sig[indx], intsiglen, rval, sval); + if (!res) { + PrintAndLogEx(NORMAL ,"\t\tr: %s", sprint_hex(rval, 32)); + PrintAndLogEx(NORMAL ,"\t\ts: %s", sprint_hex(sval, 32)); + } + } + indx += intsiglen; + + if (sigURI) { + size_t intsigurilen = (sig[indx] << 8) + sig[indx + 1]; + indx += 2; + PrintAndLogEx(NORMAL, "\tsignature uri [%d]: %.*s", intsigurilen, intsigurilen, &sig[indx]); + indx += intsigurilen; + } + + uint8_t certFormat = (sig[indx] >> 4) & 0x07; + uint8_t certCount = sig[indx] & 0x0f; + bool certURI = sig[indx] & 0x80; + + PrintAndLogEx(NORMAL, "\tcertificate format: %s", ((certFormat < sfNA) ? ndefCertificateFormat_s[certFormat] : ndefCertificateFormat_s[sfNA])); + PrintAndLogEx(NORMAL, "\tcertificates count: %d", certCount); + + // print certificates + indx++; + for (int i = 0; i < certCount; i++) { + size_t intcertlen = (sig[indx + 1] << 8) + sig[indx + 2]; + indx += 2; + + PrintAndLogEx(NORMAL, "\tcertificate %d [%d]: %s", i + 1, intcertlen, sprint_hex_inrow(&sig[indx], intcertlen)); + indx += intcertlen; } + // have certificate uri + if ((indx <= siglen) && certURI) { + size_t inturilen = (sig[indx] << 8) + sig[indx + 1]; + indx += 2; + PrintAndLogEx(NORMAL, "\tcertificate uri [%d]: %.*s", inturilen, inturilen, &sig[indx]); + indx += inturilen; + } + return 0; }; diff --git a/client/mifare/ndef.h b/client/mifare/ndef.h index 35a589602..ca16fecd3 100644 --- a/client/mifare/ndef.h +++ b/client/mifare/ndef.h @@ -25,6 +25,21 @@ typedef enum { tnfUnchangedRecord = 0x06 } TypeNameFormat_t; +typedef enum { + stNotPresent = 0x00, + stRSASSA_PSS_SHA_1 = 0x01, + stRSASSA_PKCS1_v1_5_WITH_SHA_1 = 0x02, + stDSA = 0x03, + stECDSA = 0x04, + stNA = 0x05 +} ndefSigType_t; + +typedef enum { + sfX_509 = 0x00, + sfX9_68 = 0x01, + sfNA = 0x02 +} ndefCertificateFormat_t; + typedef struct { bool MessageBegin; bool MessageEnd; From 2e8771d7a33a37aa56cfbf93cc70f15eb49b9777 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Tue, 5 Mar 2019 19:57:08 +0200 Subject: [PATCH 0661/1938] added `hf mf ndef` --- client/cmdhfmf.c | 109 +++++++++++++++++++++++++++++++++++++++++++++- client/cmdhfmfp.c | 3 +- 2 files changed, 109 insertions(+), 3 deletions(-) diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 8823ea2d9..fbd128bf4 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -11,6 +11,7 @@ #include "cmdhfmf.h" #include "mifare/mifare4.h" #include "mifare/mad.h" +#include "mifare/ndef.h" #define MFBLOCK_SIZE 16 @@ -3220,7 +3221,7 @@ int CmdHF14AMfMAD(const char *cmd) { CLIParserInit("hf mf mad", "Checks and prints Mifare Application Directory (MAD)", "Usage:\n\thf mf mad -> shows MAD if exists\n" - "\thf mf mad -a 03e1 -k d3f7d3f7d3f7 -> shows NDEF data if exists\n"); + "\thf mf mad -a 03e1 -k ffffffffffff -b -> shows NDEF data if exists. read card with custom key and key B\n"); void* argtable[] = { arg_param_begin, @@ -3305,6 +3306,110 @@ int CmdHF14AMfMAD(const char *cmd) { return 0; } +int CmdHFMFNDEF(const char *cmd) { + + CLIParserInit("hf mf ndef", + "Prints NFC Data Exchange Format (NDEF)", + "Usage:\n\thf mf ndef -> shows NDEF data\n" + "\thf mf ndef -a 03e1 -k ffffffffffff -b -> shows NDEF data with custom AID, key and with key B\n"); + + void* argtable[] = { + arg_param_begin, + arg_litn("vV", "verbose", 0, 2, "show technical data"), + arg_str0("aA", "aid", "replace default aid for NDEF", NULL), + arg_str0("kK", "key", "replace default key for NDEF", NULL), + arg_lit0("bB", "keyb", "use key B for access sectors (by default: key A)"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + bool verbose = arg_get_lit(1); + bool verbose2 = arg_get_lit(1) > 1; + uint8_t aid[2] = {0}; + int aidlen; + CLIGetHexWithReturn(2, aid, &aidlen); + uint8_t key[6] = {0}; + int keylen; + CLIGetHexWithReturn(3, key, &keylen); + bool keyB = arg_get_lit(4); + + CLIParserFree(); + + uint16_t ndefAID = 0x03e1; + if (aidlen == 2) + ndefAID = (aid[0] << 8) + aid[1]; + + uint8_t ndefkey[6] = {0}; + memcpy(ndefkey, g_mifare_ndef_key, 6); + if (keylen == 6) { + memcpy(ndefkey, key, 6); + } + + uint8_t sector0[16 * 4] = {0}; + uint8_t sector10[16 * 4] = {0}; + uint8_t data[4096] = {0}; + int datalen = 0; + + PrintAndLogEx(NORMAL, ""); + + if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0)) { + PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); + return 2; + } + + bool haveMAD2 = false; + int res = MADCheck(sector0, NULL, verbose, &haveMAD2); + if (res) { + PrintAndLogEx(ERR, "MAD error %d.", res); + return res; + } + + if (haveMAD2) { + if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10)) { + PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); + return 2; + } + } + + uint16_t mad[7 + 8 + 8 + 8 + 8] = {0}; + size_t madlen = 0; + if (MADDecode(sector0, (haveMAD2 ? sector10 : NULL), mad, &madlen)) { + PrintAndLogEx(ERR, "can't decode mad."); + return 10; + } + + printf("data reading:"); + for (int i = 0; i < madlen; i++) { + if (ndefAID == mad[i]) { + uint8_t vsector[16 * 4] = {0}; + if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, ndefkey, vsector)) { + PrintAndLogEx(ERR, "read sector %d error.", i + 1); + return 2; + } + + memcpy(&data[datalen], vsector, 16 * 3); + datalen += 16 * 3; + + printf("."); + } + } + printf(" OK\n"); + + if (!datalen) { + PrintAndLogEx(ERR, "no NDEF data."); + return 11; + } + + if (verbose2) { + PrintAndLogEx(NORMAL, "NDEF data:"); + dump_buffer(data, datalen, stdout, 1); + } + + NDEFDecodeAndPrint(data, datalen, verbose); + + return 0; +} + int CmdHF14AMfList(const char *Cmd) { CmdTraceList("mf"); return 0; @@ -3349,7 +3454,7 @@ static command_t CommandTable[] = { {"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"}, {"-----------", CmdHelp, 1, ""}, {"mad", CmdHF14AMfMAD, 0, "Checks and prints MAD"}, -// {"ndef", CmdHF14AMfHDEF, 0, "Checks and prints NDEF records from card"}, + {"ndef", CmdHFMFNDEF, 0, "Prints NDEF records from card"}, {"ice", CmdHF14AMfice, 0, "collect Mifare Classic nonces to file"}, {NULL, NULL, 0, NULL} diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 20b6d0fce..348a4a9c9 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -838,6 +838,7 @@ int CmdHFMFPNDEF(const char *cmd) { return 0; } + static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, @@ -850,7 +851,7 @@ static command_t CommandTable[] = {"rdsc", CmdHFMFPRdsc, 0, "Read sectors"}, {"wrbl", CmdHFMFPWrbl, 0, "Write blocks"}, {"mad", CmdHFMFPMAD, 0, "Checks and prints MAD"}, - {"ndef", CmdHFMFPNDEF, 0, "Prints NDEF"}, + {"ndef", CmdHFMFPNDEF, 0, "Prints NDEF records from card"}, {NULL, NULL, 0, NULL} }; From 2e884db1005cc0c674dce890d825776b0d6dddf6 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 5 Mar 2019 19:44:02 +0100 Subject: [PATCH 0662/1938] Add missing i2c init in sc upgrade --- common/i2c.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/common/i2c.c b/common/i2c.c index 25b17b6bc..53627966e 100644 --- a/common/i2c.c +++ b/common/i2c.c @@ -124,6 +124,8 @@ void I2C_Reset_EnterMainProgram(void) { // Reset the SIM_Adapter, then enter the bootloader program // Reserve for firmware update. void I2C_Reset_EnterBootloader(void) { + StartTicks(); + I2C_init(); I2C_SetResetStatus(0, 1, 1); WaitMS(100); I2C_SetResetStatus(1, 1, 1); @@ -801,4 +803,4 @@ void SmartCardSetClock(uint64_t arg0) { cmd_send(CMD_ACK, 1, 0, 0, 0, 0); set_tracing(false); LEDsoff(); -} \ No newline at end of file +} From 581043bc900b6082fd86bce1a5d9beaa69de0fad Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 5 Mar 2019 20:33:18 +0100 Subject: [PATCH 0663/1938] Look for aidlist.json in the client dir --- client/cmdsmartcard.c | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 8b10dc6fe..f371c87ce 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -87,10 +87,9 @@ static int smart_loadjson(const char *preferredName, const char *suffix, json_t if ( suffix == NULL ) return 1; int retval = 0; - int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10); + int size = sizeof(char) * (strlen(get_my_executable_directory()) + strlen(preferredName) + strlen(suffix) + 10); char * fileName = calloc(size, sizeof(char)); - sprintf(fileName, "%s.%s", preferredName, suffix); - + sprintf(fileName, "%s%s.%s", get_my_executable_directory(), preferredName, suffix); *root = json_load_file(fileName, 0, &error); if (!*root) { PrintAndLogEx(ERR, "json (%s) error on line %d: %s", fileName, error.line, error.text); From 4dfcb727afefecc42cb708b73b92d3f2f037cb8b Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Tue, 5 Mar 2019 21:14:30 +0100 Subject: [PATCH 0664/1938] cmds history: don't push to history if last command is replayed --- client/proxmark3.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/client/proxmark3.c b/client/proxmark3.c index 246da350b..072fec427 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -167,7 +167,9 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { if (cmd[0] != 0x00) { int ret = CommandReceived(cmd); - add_history(cmd); + HIST_ENTRY * entry = history_get(history_length); + if ((!entry) || (strcmp(entry->line, cmd) != 0)) + add_history(cmd); // exit or quit if (ret == 99) @@ -384,4 +386,4 @@ int main(int argc, char* argv[]) { } exit(0); -} \ No newline at end of file +} From 05f5fb3e47e4c46711afed39638ffb0c49084755 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 6 Mar 2019 00:43:59 +0200 Subject: [PATCH 0665/1938] del verbose on warning --- client/mifare/mad.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/client/mifare/mad.c b/client/mifare/mad.c index 46a95f89d..3f44fdbbf 100644 --- a/client/mifare/mad.c +++ b/client/mifare/mad.c @@ -111,15 +111,13 @@ int madCRCCheck(uint8_t *sector, bool verbose, int MADver) { if (MADver == 1) { uint8_t crc = CRC8Mad(§or[16 + 1], 15 + 16); if (crc != sector[16]) { - if (verbose) - PrintAndLogEx(WARNING, "Wrong MAD%d CRC. Calculated: 0x%02x, from card: 0x%02x", MADver, crc, sector[16]); + PrintAndLogEx(WARNING, "Wrong MAD%d CRC. Calculated: 0x%02x, from card: 0x%02x", MADver, crc, sector[16]); return 3; }; } else { uint8_t crc = CRC8Mad(§or[1], 15 + 16 + 16); if (crc != sector[0]) { - if (verbose) - PrintAndLogEx(WARNING, "Wrong MAD%d CRC. Calculated: 0x%02x, from card: 0x%02x", MADver, crc, sector[16]); + PrintAndLogEx(WARNING, "Wrong MAD%d CRC. Calculated: 0x%02x, from card: 0x%02x", MADver, crc, sector[16]); return 3; }; } From cfcdbcdceeca53ca019e42514284cf066442acd5 Mon Sep 17 00:00:00 2001 From: merlokk <807634+merlokk@users.noreply.github.com> Date: Wed, 6 Mar 2019 00:50:12 +0200 Subject: [PATCH 0666/1938] added some checks into `madcheck` --- client/mifare/mad.c | 27 ++++++++++++--------------- 1 file changed, 12 insertions(+), 15 deletions(-) diff --git a/client/mifare/mad.c b/client/mifare/mad.c index 3f44fdbbf..96a4bf152 100644 --- a/client/mifare/mad.c +++ b/client/mifare/mad.c @@ -133,6 +133,8 @@ uint16_t madGetAID(uint8_t *sector, int MADver, int sectorNo) { } int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2) { + int res = 0; + if (!sector0) return 1; @@ -167,23 +169,21 @@ int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2) if (haveMAD2) *haveMAD2 = (MADVer == 2); - int res = madCRCCheck(sector0, true, 1); - if (res) - return res; + res = madCRCCheck(sector0, true, 1); - if (verbose) + if (verbose && !res) PrintAndLogEx(NORMAL, "CRC8-MAD1 OK."); if (MADVer == 2 && sector10) { - int res = madCRCCheck(sector10, true, 2); - if (res) - return res; + int res2 = madCRCCheck(sector10, true, 2); + if (!res) + res = res2; - if (verbose) + if (verbose & !res2) PrintAndLogEx(NORMAL, "CRC8-MAD2 OK."); } - return 0; + return res; } int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen) { @@ -214,11 +214,8 @@ int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { // check MAD1 only - int res = MADCheck(sector, NULL, verbose, haveMAD2); - - if (verbose && !res) - PrintAndLogEx(NORMAL, "CRC8-MAD OK."); - + MADCheck(sector, NULL, verbose, haveMAD2); + // info byte uint8_t InfoByte = sector[16 + 1] & 0x3f; if (InfoByte) { @@ -245,7 +242,7 @@ int MAD2DecodeAndPrint(uint8_t *sector, bool verbose) { int res = madCRCCheck(sector, true, 2); if (verbose && !res) - PrintAndLogEx(NORMAL, "CRC8-MAD OK."); + PrintAndLogEx(NORMAL, "CRC8-MAD2 OK."); uint8_t InfoByte = sector[1] & 0x3f; PrintAndLogEx(NORMAL, "MAD2 Card publisher sector: 0x%02x", InfoByte); From c5e1f9989c7134b74805d4b200701c5d4e29e139 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Wed, 6 Mar 2019 20:15:19 +0100 Subject: [PATCH 0667/1938] analyse nuid: fix crc -> selftest ok now --- client/cmdanalyse.c | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c index f756a44c0..4f7ec5661 100644 --- a/client/cmdanalyse.c +++ b/client/cmdanalyse.c @@ -850,15 +850,9 @@ void generate4bNUID(uint8_t *uid, uint8_t *nuid){ compute_crc(CRC_14443_A, uid, 3, &b1, &b2); nuid[0] |= (b2 & 0xE0) | 0xF; nuid[1] = b1; - crc = b1; crc |= b2 << 8; - - crc = update_crc16(uid[3], crc); - crc = update_crc16(uid[4], crc); - crc = update_crc16(uid[5], crc); - crc = update_crc16(uid[6], crc); - + crc = crc16_fast(&uid[3], 4, reflect16(crc), true, true); nuid[2] = (crc >> 8) & 0xFF ; nuid[3] = crc & 0xFF; } @@ -870,6 +864,7 @@ int CmdAnalyseNuid(const char *Cmd){ char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0|| cmdp == 'h') return usage_analyse_nuid(); + /* src: http://www.gorferay.com/mifare-and-handling-of-uids/ */ /* selftest UID 040D681AB52281 -> NUID 8F430FEF */ if (cmdp == 't' || cmdp == 'T') { memcpy(uid, "\x04\x0d\x68\x1a\xb5\x22\x81", 7); From 259a561a6921ab88485d3321887feb5081ddf734 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 7 Mar 2019 15:55:53 +0100 Subject: [PATCH 0668/1938] analyse nuid: better ref and selftest from ref + little fix --- client/cmdanalyse.c | 17 ++++++++++++----- 1 file changed, 12 insertions(+), 5 deletions(-) diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c index 4f7ec5661..07b64f34f 100644 --- a/client/cmdanalyse.c +++ b/client/cmdanalyse.c @@ -848,7 +848,7 @@ void generate4bNUID(uint8_t *uid, uint8_t *nuid){ uint8_t b1, b2; compute_crc(CRC_14443_A, uid, 3, &b1, &b2); - nuid[0] |= (b2 & 0xE0) | 0xF; + nuid[0] = (b2 & 0xE0) | 0xF; nuid[1] = b1; crc = b1; crc |= b2 << 8; @@ -864,15 +864,22 @@ int CmdAnalyseNuid(const char *Cmd){ char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0|| cmdp == 'h') return usage_analyse_nuid(); - /* src: http://www.gorferay.com/mifare-and-handling-of-uids/ */ - /* selftest UID 040D681AB52281 -> NUID 8F430FEF */ + /* src: https://www.nxp.com/docs/en/application-note/AN10927.pdf */ + /* selftest1 UID 040D681AB52281 -> NUID 8F430FEF */ + /* selftest2 UID 04183F09321B85 -> NUID 4F505D7D */ if (cmdp == 't' || cmdp == 'T') { memcpy(uid, "\x04\x0d\x68\x1a\xb5\x22\x81", 7); generate4bNUID(uid, nuid); if ( 0 == memcmp(nuid, "\x8f\x43\x0f\xef", 4)) - PrintAndLogEx(SUCCESS, "Selftest OK\n"); + PrintAndLogEx(SUCCESS, "Selftest1 OK\n"); else - PrintAndLogEx(FAILED, "Selftest Failed\n"); + PrintAndLogEx(FAILED, "Selftest1 Failed\n"); + memcpy(uid, "\x04\x18\x3f\x09\x32\x1b\x85", 7); + generate4bNUID(uid, nuid); + if ( 0 == memcmp(nuid, "\x4f\x50\x5d\x7d", 4)) + PrintAndLogEx(SUCCESS, "Selftest2 OK\n"); + else + PrintAndLogEx(FAILED, "Selftest2 Failed\n"); return 0; } From 2a761e80db6d38566443f2d6d86cf3779fecacf1 Mon Sep 17 00:00:00 2001 From: Chris Date: Thu, 7 Mar 2019 19:48:20 +0100 Subject: [PATCH 0669/1938] chg: analyse nuid' - added colors --- client/cmdanalyse.c | 16 +++++++--------- 1 file changed, 7 insertions(+), 9 deletions(-) diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c index 07b64f34f..fea907206 100644 --- a/client/cmdanalyse.c +++ b/client/cmdanalyse.c @@ -867,19 +867,17 @@ int CmdAnalyseNuid(const char *Cmd){ /* src: https://www.nxp.com/docs/en/application-note/AN10927.pdf */ /* selftest1 UID 040D681AB52281 -> NUID 8F430FEF */ /* selftest2 UID 04183F09321B85 -> NUID 4F505D7D */ - if (cmdp == 't' || cmdp == 'T') { + if (cmdp == 't') { memcpy(uid, "\x04\x0d\x68\x1a\xb5\x22\x81", 7); generate4bNUID(uid, nuid); - if ( 0 == memcmp(nuid, "\x8f\x43\x0f\xef", 4)) - PrintAndLogEx(SUCCESS, "Selftest1 OK\n"); - else - PrintAndLogEx(FAILED, "Selftest1 Failed\n"); + + bool test1 = (0 == memcmp(nuid, "\x8f\x43\x0f\xef", 4)); + PrintAndLogEx(SUCCESS, "Selftest1 %s\n", test1 ? _GREEN_(OK): _RED_(Fail)); + memcpy(uid, "\x04\x18\x3f\x09\x32\x1b\x85", 7); generate4bNUID(uid, nuid); - if ( 0 == memcmp(nuid, "\x4f\x50\x5d\x7d", 4)) - PrintAndLogEx(SUCCESS, "Selftest2 OK\n"); - else - PrintAndLogEx(FAILED, "Selftest2 Failed\n"); + bool test2 = (0 == memcmp(nuid, "\x4f\x50\x5d\x7d", 4)); + PrintAndLogEx(SUCCESS, "Selftest2 %s\n", test2 ? _GREEN_(OK) : _RED_(Fail)); return 0; } From 1f0c1dff5e123ddbe8291ec57c55b5fd4e8d3dd5 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Thu, 7 Mar 2019 21:13:58 +0100 Subject: [PATCH 0670/1938] Fix issue #118 for better FSK on saturated signals --- common/lfdemod.c | 27 +++++++++++++++++---------- 1 file changed, 17 insertions(+), 10 deletions(-) diff --git a/common/lfdemod.c b/common/lfdemod.c index 1ef5915c9..1fd69d1b9 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -106,16 +106,23 @@ int32_t compute_mean_int(int *in, size_t N) { } void zeromean(uint8_t* data, size_t size) { - + // zero mean data int i, accum = 0; for (i = 10; i < size; ++i) - accum += data[i]; - - accum /= (size - 10); - - for (i = 0; i < size; ++i) - data[i] -= accum; + accum += data[i] - 128; + accum /= (int)(size - 10); + + for (i = 0; i < size; ++i) { + if (accum > 0) { + data[i] = (data[i] >= accum)? data[i] - accum : 0; + } + if (accum < 0) { + data[i] = (255 - data[i] >= -accum)? data[i] - accum : 255; + } + } + // recompute signal characteristics: + isNoise(data, size); } //test samples are not just noise @@ -1668,11 +1675,11 @@ size_t fsk_wave_demod(uint8_t *dest, size_t size, uint8_t fchigh, uint8_t fclow, size_t last_transition = 0; size_t idx = 1; size_t numBits = 0; - + //find start of modulating data in trace idx = findModStart(dest, size, fchigh); // Need to threshold first sample - dest[0] = (dest[idx] < signalprop.mean) ? 0 : 1; + dest[idx] = (dest[idx] < signalprop.mean) ? 0 : 1; last_transition = idx; idx++; @@ -2119,4 +2126,4 @@ int detectIOProx(uint8_t *dest, size_t *size, int *waveStartIdx) { return (int) start_idx; } return -6; -} \ No newline at end of file +} From 9764381aa447802752d7598e827683be9b547457 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Fri, 8 Mar 2019 17:25:36 +0100 Subject: [PATCH 0671/1938] fix: ndef - missing comma --- client/mifare/ndef.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index 13a793725..6c7e12229 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -22,7 +22,7 @@ static const char *TypeNameFormat_s[] = { "Absolute URI Record", "External Record", "Unknown Record", - "Unchanged Record" + "Unchanged Record", "n/a" }; From 4160e32b0ae050383c56529c3d45a62881b52e86 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 8 Mar 2019 19:06:55 +0100 Subject: [PATCH 0672/1938] Replace isNoise by computeSignalProperties and removeSignalOffset --- armsrc/lfsampling.c | 7 +-- client/cmddata.c | 66 +++++++++++++------------- client/cmdlfem4x.c | 11 +++-- client/cmdlft55xx.c | 6 ++- client/comms.c | 2 +- common/lfdemod.c | 111 ++++++++++++-------------------------------- common/lfdemod.h | 18 ++++--- 7 files changed, 92 insertions(+), 129 deletions(-) diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 96963d389..4b036d088 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -204,8 +204,9 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); } - // Ensure that noise check is performed for any device-side processing - isNoise(dest, bufsize); + // Ensure that DC offset removal and noise check is performed for any device-side processing + removeSignalOffset(dest, bufsize); + computeSignalProperties(dest, bufsize); return data.numbits; } @@ -451,4 +452,4 @@ uint32_t doCotagAcquisitionManchester() { } } return sample_counter; -} \ No newline at end of file +} diff --git a/client/cmddata.c b/client/cmddata.c index ba3d61156..285b4d189 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1393,15 +1393,13 @@ int CmdHide(const char *Cmd) { //zero mean GraphBuffer int CmdHpf(const char *Cmd) { - int i, accum = 0; - - for (i = 10; i < GraphTraceLen; ++i) - accum += GraphBuffer[i]; - - accum /= (GraphTraceLen - 10); - - for (i = 0; i < GraphTraceLen; ++i) - GraphBuffer[i] -= accum; + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + removeSignalOffset(bits, size); + // push it back to graph + setGraphBuf(bits, size); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(bits, size); RepaintGraphWindow(); return 0; @@ -1471,12 +1469,15 @@ int getSamples(int n, bool silent) { GraphTraceLen = n; } - //ICEMAN todo uint8_t bits[GraphTraceLen]; size_t size = getFromGraphBuf(bits); - // set signal properties low/high/mean/amplitude and is_noice detection - isNoise(bits, size); - + // TODO now DC removal is done already on device, right ? + // removeSignalOffset(bits, size); + // push it back to graph + // setGraphBuf(bits, size); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(bits, size); + setClockGrid(0, 0); DemodBufferLen = 0; RepaintGraphWindow(); @@ -1610,15 +1611,19 @@ int CmdLoad(const char *Cmd) { fclose(f); PrintAndLogEx(SUCCESS, "loaded %d samples", GraphTraceLen); + + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + // set signal properties low/high/mean/amplitude and is_noise detection + removeSignalOffset(bits, size); + // push it back to graph + setGraphBuf(bits, size); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(bits, size); + setClockGrid(0,0); DemodBufferLen = 0; RepaintGraphWindow(); - - //ICEMAN todo - // set signal properties low/high/mean/amplitude and isnoice detection - uint8_t bits[GraphTraceLen]; - size_t size = getFromGraphBuf(bits); - isNoise(bits, size); return 0; } @@ -1683,11 +1688,11 @@ int CmdNorm(const char *Cmd) { } } - //ICEMAN todo - // set signal properties low/high/mean/amplitude and isnoice detection uint8_t bits[GraphTraceLen]; size_t size = getFromGraphBuf(bits); - isNoise(bits, size); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(bits, size); + RepaintGraphWindow(); return 0; } @@ -1773,11 +1778,11 @@ int CmdDirectionalThreshold(const char *Cmd) { directionalThreshold(GraphBuffer, GraphBuffer, GraphTraceLen, up, down); - //ICEMAN todo // set signal properties low/high/mean/amplitude and isnoice detection uint8_t bits[GraphTraceLen]; size_t size = getFromGraphBuf(bits); - isNoise(bits, size); + // set signal properties low/high/mean/amplitude and is_noice detection + computeSignalProperties(bits, size); RepaintGraphWindow(); return 0; @@ -1805,11 +1810,10 @@ int CmdZerocrossings(const char *Cmd) { } } - //ICEMAN todo - // set signal properties low/high/mean/amplitude and isnoice detection uint8_t bits[GraphTraceLen]; size_t size = getFromGraphBuf(bits); - isNoise(bits, size); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(bits, size); RepaintGraphWindow(); return 0; @@ -2063,13 +2067,11 @@ int CmdDataIIR(const char *Cmd){ //iceIIR_Butterworth(GraphBuffer, GraphTraceLen); iceSimple_Filter(GraphBuffer, GraphTraceLen, k); - //ICEMAN todo - // set signal properties low/high/mean/amplitude and isnoice detection uint8_t bits[GraphTraceLen]; size_t size = getFromGraphBuf(bits); - isNoise(bits, size); - - RepaintGraphWindow(); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(bits, size); + RepaintGraphWindow(); return 0; } diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 6d90e550f..e4909ace9 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -800,7 +800,7 @@ int EM4x50Read(const char *Cmd, bool verbose) { uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; size_t size = getFromGraphBuf(bits); - isNoise(bits, size); + computeSignalProperties(bits, size); signal_t *sp = getSignalProperties(); high = sp->high; @@ -999,9 +999,14 @@ bool downloadSamplesEM(){ PrintAndLogEx(WARNING, "command execution time out"); return false; } - setGraphBuf(got, sizeof(got)); - if (isNoise(got, sizeof(got))) { + // TODO now DC removal is done already on device, right ? + // removeSignalOffset(got, sizeof(got)); + setGraphBuf(got, sizeof(got)); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(got, sizeof(got)); + RepaintGraphWindow(); + if (getSignalProperties()->isnoise) { PrintAndLogEx(DEBUG, "No tag found"); return false; } diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 3c7547e34..446e440ce 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1330,8 +1330,12 @@ bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ) PrintAndLogEx(WARNING, "command execution time out"); return false; } + // set signal properties low/high/mean/amplitude and is_noise detection + removeSignalOffset(got, sizeof(got)); + computeSignalProperties(got, sizeof(got)); setGraphBuf(got, sizeof(got)); - return !isNoise(got, sizeof(got)); + RepaintGraphWindow(); + return !getSignalProperties()->isnoise; } char * GetBitRateStr(uint32_t id, bool xmode) { diff --git a/client/comms.c b/client/comms.c index 5beaa0adb..f08c5f413 100644 --- a/client/comms.c +++ b/client/comms.c @@ -463,7 +463,7 @@ bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint3 return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_FLASHMEM_DOWNLOADED); } case SIM_MEM: { - //UsbCommand c = {CMD_DOWNLOAND_SIM_MEM, {start_index, bytes, 0}}; + //UsbCommand c = {CMD_DOWNLOAD_SIM_MEM, {start_index, bytes, 0}}; //SendCommand(&c); //return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_DOWNLOADED_SIMMEM); return false; diff --git a/common/lfdemod.c b/common/lfdemod.c index 1fd69d1b9..b9807ff8f 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -47,8 +47,7 @@ //********************************************************************************************** #define LOWEST_DEFAULT_CLOCK 32 #define FSK_PSK_THRESHOLD 123 -//might not be high enough for noisy environments -#define NOICE_AMPLITUDE_THRESHOLD 10 + //to allow debug print calls when used not on dev //void dummy(char *fmt, ...){} @@ -76,6 +75,7 @@ static void resetSignal(void) { signalprop.amplitude = 0; signalprop.isnoise = true; } + static void printSignal(void) { prnt("LF signal properties:"); prnt(" high..........%d", signalprop.high); @@ -83,94 +83,47 @@ static void printSignal(void) { prnt(" mean..........%d", signalprop.mean); prnt(" amplitude.....%d", signalprop.amplitude); prnt(" is Noise......%s", (signalprop.isnoise) ? "Yes" : "No"); - prnt(" THRESHOLD noice amplitude......%d" , NOICE_AMPLITUDE_THRESHOLD); + prnt(" THRESHOLD noise amplitude......%d" , NOISE_AMPLITUDE_THRESHOLD); } -// Function to compute mean for a series -// rounded to integer.. -uint32_t compute_mean_uint(uint8_t *in, size_t N) { - uint32_t mean = 0; - for (size_t i = 0; i < N; i++) - mean += in[i]; - - return mean / N; -} -// Function to compute mean for a series -// rounded to integer.. -int32_t compute_mean_int(int *in, size_t N) { - int32_t mean = 0; - for (size_t i = 0; i < N; i++) - mean += in[i]; - - return mean / (int)N; -} - -void zeromean(uint8_t* data, size_t size) { - - // zero mean data - int i, accum = 0; - for (i = 10; i < size; ++i) - accum += data[i] - 128; - accum /= (int)(size - 10); - - for (i = 0; i < size; ++i) { - if (accum > 0) { - data[i] = (data[i] >= accum)? data[i] - accum : 0; - } - if (accum < 0) { - data[i] = (255 - data[i] >= -accum)? data[i] - accum : 255; - } - } - // recompute signal characteristics: - isNoise(data, size); -} - -//test samples are not just noise -// By measuring mean and look at amplitude of signal from HIGH / LOW, we can detect noise -bool isNoise_int(int *bits, uint32_t size) { +void computeSignalProperties(uint8_t *samples, uint32_t size) { resetSignal(); - if ( bits == NULL || size < 100 ) return true; - - int32_t sum = 0; - for ( size_t i = 0; i < size; i++) { - if ( bits[i] < signalprop.low ) signalprop.low = bits[i]; - if ( bits[i] > signalprop.high ) signalprop.high = bits[i]; - sum += bits[i]; - } - // measure amplitude of signal - signalprop.mean = sum / (int)size; - signalprop.amplitude = ABS(signalprop.high - signalprop.mean); - signalprop.isnoise = signalprop.amplitude < NOICE_AMPLITUDE_THRESHOLD; - - if (g_debugMode) - printSignal(); - - return signalprop.isnoise; -} -//test samples are not just noise -// By measuring mean and look at amplitude of signal from HIGH / LOW, -// we can detect noise -bool isNoise(uint8_t *bits, uint32_t size) { - resetSignal(); - if ( bits == NULL || size < 100 ) return true; - uint32_t sum = 0; for ( uint32_t i = 0; i < size; i++) { - if ( bits[i] < signalprop.low ) signalprop.low = bits[i]; - if ( bits[i] > signalprop.high ) signalprop.high = bits[i]; - sum += bits[i]; + if ( samples[i] < signalprop.low ) signalprop.low = samples[i]; + if ( samples[i] > signalprop.high ) signalprop.high = samples[i]; + sum += samples[i]; } // measure amplitude of signal signalprop.mean = sum / size; signalprop.amplitude = signalprop.high - signalprop.mean; - signalprop.isnoise = signalprop.amplitude < NOICE_AMPLITUDE_THRESHOLD; - + // By measuring mean and look at amplitude of signal from HIGH / LOW, + // we can detect noise + signalprop.isnoise = signalprop.amplitude < NOISE_AMPLITUDE_THRESHOLD; + if (g_debugMode) printSignal(); +} - return signalprop.isnoise; +void removeSignalOffset(uint8_t *samples, uint32_t size) { + if ( samples == NULL || size < SIGNAL_MIN_SAMPLES ) return; + + int acc_off = 0; + for (uint32_t i = SIGNAL_IGNORE_FIRST_SAMPLES; i < size; i++) + acc_off += samples[i] - 128; + acc_off /= (int)(size - SIGNAL_IGNORE_FIRST_SAMPLES); + + // shift and saturate samples to center the mean + for ( uint32_t i = 0; i < size; i++) { + if (acc_off > 0) { + samples[i] = (samples[i] >= acc_off)? samples[i] - acc_off : 0; + } + if (acc_off < 0) { + samples[i] = (255 - samples[i] >= -acc_off)? samples[i] - acc_off : 255; + } + } } //by marshmellow @@ -1962,8 +1915,6 @@ int detectAWID(uint8_t *dest, size_t *size, int *waveStartIdx) { if (signalprop.isnoise) return -2; - zeromean(dest, *size); - // FSK2a demodulator clock 50, invert 1, fcHigh 10, fcLow 8 *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); //awid fsk2a @@ -2029,8 +1980,6 @@ int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32 if (signalprop.isnoise) return -2; - zeromean(dest, *size); - // FSK demodulator fsk2a so invert and fc/10/8 *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); //hid fsk2a @@ -2090,8 +2039,6 @@ int detectIOProx(uint8_t *dest, size_t *size, int *waveStartIdx) { if (signalprop.isnoise) return -2; - zeromean(dest, *size); - // FSK demodulator RF/64, fsk2a so invert, and fc/10/8 *size = fskdemod(dest, *size, 64, 1, 10, 8, waveStartIdx); //io fsk2a diff --git a/common/lfdemod.h b/common/lfdemod.h index 43537b18b..a6542059e 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -20,6 +20,14 @@ #include // for bool #include "parity.h" // for parity test #include "util.h" // for ARRAYLEN + +//might not be high enough for noisy environments +#define NOISE_AMPLITUDE_THRESHOLD 10 +//ignore buffer with less than x samples +#define SIGNAL_MIN_SAMPLES 100 +//ignore first x samples of the buffer +#define SIGNAL_IGNORE_FIRST_SAMPLES 10 + //generic typedef struct { int low; @@ -28,14 +36,10 @@ typedef struct { int amplitude; bool isnoise; } signal_t; -extern signal_t* getSignalProperties(void); +signal_t* getSignalProperties(void); -extern uint32_t compute_mean_uint(uint8_t *in, size_t N); -extern int32_t compute_mean_int(int *in, size_t N); -bool isNoise_int(int *bits, uint32_t size); -bool isNoise(uint8_t *bits, uint32_t size); -extern void zeromean(uint8_t* data, size_t size); - +void computeSignalProperties(uint8_t *bits, uint32_t size); +void removeSignalOffset(uint8_t *samples, uint32_t size); void getNextLow(uint8_t *samples, size_t size, int low, size_t *i); void getNextHigh(uint8_t *samples, size_t size, int high, size_t *i); bool loadWaveCounters(uint8_t *samples, size_t size, int lowToLowWaveLen[], int highToLowWaveLen[], int *waveCnt, int *skip, int *minClk, int *high, int *low); From abddff513e5ab3d8edc89bb120f2019ae7893223 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 8 Mar 2019 19:49:12 +0100 Subject: [PATCH 0673/1938] loadFile: fix double free --- client/cmdflashmem.c | 3 ++- client/cmdhfmf.c | 2 +- client/loclass/fileutils.c | 13 +++---------- 3 files changed, 6 insertions(+), 12 deletions(-) diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index 34bb89cbc..cedb9516d 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -248,6 +248,7 @@ int CmdFlashMemLoad(const char *Cmd){ res = loadFile(filename, "bin", data, &datalen); //int res = loadFileEML( filename, "eml", data, &datalen); if ( res ) { + free(data); return 1; } @@ -607,4 +608,4 @@ int CmdHelp(const char *Cmd) { return 0; } -#endif \ No newline at end of file +#endif diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index fbd128bf4..4dd3b4b3e 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -2768,7 +2768,7 @@ int CmdHF14AMfCLoad(const char *Cmd) { // 64 or 256blocks. if (datalen != 1024 && datalen != 4096) { PrintAndLogEx(WARNING, "File content error. "); - free(data); + free(data); return 2; } diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index 6f6f1a5a4..f9d4db8d1 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -257,6 +257,7 @@ int loadFile(const char *preferredName, const char *suffix, void* data, size_t* if ( preferredName == NULL ) return 1; if ( suffix == NULL ) return 1; + if ( data == NULL ) return 1; int retval = 0; int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10); @@ -275,7 +276,7 @@ int loadFile(const char *preferredName, const char *suffix, void* data, size_t* long fsize = ftell(f); fseek(f, 0, SEEK_SET); - if ( fsize < 0 ) { + if ( fsize < 0 ) { PrintAndLogDevice(FAILED, "error, when getting filesize"); retval = 1; goto out; @@ -294,11 +295,7 @@ int loadFile(const char *preferredName, const char *suffix, void* data, size_t* PrintAndLogDevice(FAILED, "error, bytes read mismatch file size"); free(dump); retval = 3; - goto out; - } - - if ( (data) == NULL) { - (data) = calloc( bytes_read, sizeof(uint8_t)); + goto out; } memcpy( (data), dump, bytes_read); @@ -310,10 +307,6 @@ int loadFile(const char *preferredName, const char *suffix, void* data, size_t* out: fclose(f); - - if (data) - free(data); - free(fileName); return retval; From ae719c3b05c90f6479ba4f67f15c261a52ea55fb Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 8 Mar 2019 20:10:16 +0100 Subject: [PATCH 0674/1938] Fix CmdT55xxBruteForce infinite loop --- client/cmdlft55xx.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 3c7547e34..ac92c119b 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1701,7 +1701,7 @@ int CmdT55xxBruteForce(const char *Cmd) { PrintAndLogEx(INFO, "Search password range [%08X -> %08X]", start_password, end_password); - while ( !found || (curr <= end_password)){ + while ( !found ){ printf("."); fflush(stdout); @@ -1710,13 +1710,15 @@ int CmdT55xxBruteForce(const char *Cmd) { } if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, curr)) { - PrintAndLogEx(WARNING, "Aquireing data from device failed. Quitting"); + PrintAndLogEx(WARNING, "Aquiring data from device failed. Quitting"); return 0; } found = tryDetectModulation(); - ++curr; + if (curr == end_password) + break; + curr++; } PrintAndLogEx(NORMAL, ""); From 1cba26decfc6997b3501f45acec2f85746a2c80a Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Fri, 8 Mar 2019 20:30:54 +0100 Subject: [PATCH 0675/1938] remove redundant removeSignalOffset --- client/cmddata.c | 4 ---- client/cmdlfem4x.c | 2 -- client/cmdlft55xx.c | 5 ++--- 3 files changed, 2 insertions(+), 9 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 285b4d189..fc34f3e80 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1471,10 +1471,6 @@ int getSamples(int n, bool silent) { uint8_t bits[GraphTraceLen]; size_t size = getFromGraphBuf(bits); - // TODO now DC removal is done already on device, right ? - // removeSignalOffset(bits, size); - // push it back to graph - // setGraphBuf(bits, size); // set signal properties low/high/mean/amplitude and is_noise detection computeSignalProperties(bits, size); diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index e4909ace9..8b9530957 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -1000,8 +1000,6 @@ bool downloadSamplesEM(){ return false; } - // TODO now DC removal is done already on device, right ? - // removeSignalOffset(got, sizeof(got)); setGraphBuf(got, sizeof(got)); // set signal properties low/high/mean/amplitude and is_noise detection computeSignalProperties(got, sizeof(got)); diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 446e440ce..b9256fc29 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1330,10 +1330,9 @@ bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ) PrintAndLogEx(WARNING, "command execution time out"); return false; } - // set signal properties low/high/mean/amplitude and is_noise detection - removeSignalOffset(got, sizeof(got)); - computeSignalProperties(got, sizeof(got)); setGraphBuf(got, sizeof(got)); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(got, sizeof(got)); RepaintGraphWindow(); return !getSignalProperties()->isnoise; } From 1cf3e1b581a35fb3aedcde5e6659b8414a793b4a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 08:14:42 +0100 Subject: [PATCH 0676/1938] fix: 'lf visa' - use defines instead --- client/cmdlfvisa2000.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) diff --git a/client/cmdlfvisa2000.c b/client/cmdlfvisa2000.c index 02cd5392e..7d7cddb4d 100644 --- a/client/cmdlfvisa2000.c +++ b/client/cmdlfvisa2000.c @@ -95,9 +95,8 @@ int detectVisa2k(uint8_t *dest, size_t *size) { **/ //see ASKDemod for what args are accepted int CmdVisa2kDemod(const char *Cmd) { - - // save GraphBuffer - to restore it later - save_restoreGB(1); + + save_restoreGB(GRAPH_SAVE); //sCmdAskEdgeDetect(""); @@ -105,7 +104,7 @@ int CmdVisa2kDemod(const char *Cmd) { bool st = true; if (!ASKDemod_ext("64 0 0", false, false, 1, &st)) { PrintAndLogEx(DEBUG, "DEBUG: Error - Visa2k: ASK/Manchester Demod failed"); - save_restoreGB(0); + save_restoreGB(GRAPH_RESTORE); return 0; } size_t size = DemodBufferLen; @@ -120,7 +119,7 @@ int CmdVisa2kDemod(const char *Cmd) { else PrintAndLogEx(DEBUG, "DEBUG: Error - Visa2k: ans: %d", ans); - save_restoreGB(0); + save_restoreGB(GRAPH_RESTORE); return 0; } setDemodBuf(DemodBuffer, 96, ans); @@ -138,7 +137,7 @@ int CmdVisa2kDemod(const char *Cmd) { // test checksums if ( chk != calc ) { PrintAndLogEx(DEBUG, "DEBUG: error: Visa2000 checksum failed %x - %x\n", chk, calc); - save_restoreGB(0); + save_restoreGB(GRAPH_RESTORE); return 0; } // parity @@ -146,17 +145,16 @@ int CmdVisa2kDemod(const char *Cmd) { uint8_t chk_par = (raw3 & 0xFF0) >> 4; if ( calc_par != chk_par) { PrintAndLogEx(DEBUG, "DEBUG: error: Visa2000 parity failed %x - %x\n", chk_par, calc_par); - save_restoreGB(0); + save_restoreGB(GRAPH_RESTORE); return 0; } PrintAndLogEx(SUCCESS, "Visa2000 Tag Found: Card ID %u, Raw: %08X%08X%08X", raw2, raw1 ,raw2, raw3); - save_restoreGB(0); return 1; } // 64*96*2=12288 samples just in case we just missed the first preamble we can still catch 2 of them int CmdVisa2kRead(const char *Cmd) { - lf_read(true, 12500); + lf_read(true, 14000); return CmdVisa2kDemod(Cmd); } @@ -225,21 +223,21 @@ int CmdVisa2kSim(const char *Cmd) { } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, + {"help", CmdHelp, 1, "This help"}, {"demod", CmdVisa2kDemod, 1, "demodulate an VISA2000 tag from the GraphBuffer"}, {"read", CmdVisa2kRead, 0, "attempt to read and extract tag data from the antenna"}, {"clone", CmdVisa2kClone, 0, "clone Visa2000 to t55x7"}, {"sim", CmdVisa2kSim, 0, "simulate Visa2000 tag"}, - {NULL, NULL, 0, NULL} + {NULL, NULL, 0, NULL} }; int CmdLFVisa2k(const char *Cmd) { clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } From 810f92dbab05edbdc4e9a7e04e7e4ed05decf089 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 08:29:37 +0100 Subject: [PATCH 0677/1938] FIX: 'lf visa read' - increase samples solves #123 --- client/cmdlfvisa2000.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfvisa2000.c b/client/cmdlfvisa2000.c index 7d7cddb4d..031894728 100644 --- a/client/cmdlfvisa2000.c +++ b/client/cmdlfvisa2000.c @@ -154,7 +154,7 @@ int CmdVisa2kDemod(const char *Cmd) { // 64*96*2=12288 samples just in case we just missed the first preamble we can still catch 2 of them int CmdVisa2kRead(const char *Cmd) { - lf_read(true, 14000); + lf_read(true, 20000); return CmdVisa2kDemod(Cmd); } From d8788bb3761efa3d6418de1177ca926a65587d01 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 08:43:28 +0100 Subject: [PATCH 0678/1938] appease coverity --- client/cmddata.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmddata.c b/client/cmddata.c index fc34f3e80..0403c4f28 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -773,7 +773,7 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph } int foo = ABS(hi-hi_1); - int bar = (int)(((hi+hi_1) / 2) * 0.03); + int bar = (int)((int)((hi+hi_1) / 2) * 0.03); if ( verbose && foo < bar ) { distance = idx_1 - idx; PrintAndLogEx(SUCCESS, "possible 3% visible correlation %4d samples", distance); From edc19f202a7cec42045203cceb3ccac198de9e5b Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 08:49:41 +0100 Subject: [PATCH 0679/1938] Convert the few files with still Windows carriage returns --- armsrc/legicrf.h | 2 +- armsrc/legicrfsim.h | 2 +- armsrc/mifarecmd.c | 4138 +++++++++++----------- armsrc/mifarecmd.h | 54 +- armsrc/mifaresniff.c | 646 ++-- armsrc/mifaresniff.h | 82 +- armsrc/mifareutil.c | 1378 ++++---- armsrc/mifareutil.h | 186 +- client/cmdhfmf.c | 6944 ++++++++++++++++++------------------- client/cmdhfmf.h | 152 +- client/cmdlft55xx.c | 4112 +++++++++++----------- client/cmdlft55xx.h | 342 +- common/cmd.c | 126 +- common/cmd.h | 90 +- common/usb_cdc.c | 1894 +++++----- common/usb_cdc.h | 126 +- tools/mfkey/crapto1.c | 1148 +++--- tools/nonce2key/crapto1.c | 1146 +++--- 18 files changed, 11284 insertions(+), 11284 deletions(-) diff --git a/armsrc/legicrf.h b/armsrc/legicrf.h index 639687558..1c275a1ed 100644 --- a/armsrc/legicrf.h +++ b/armsrc/legicrf.h @@ -1,4 +1,4 @@ -//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- // (c) 2009 Henryk Plötz // 2018 AntiCat // diff --git a/armsrc/legicrfsim.h b/armsrc/legicrfsim.h index c1c8a86e2..da70bff0c 100644 --- a/armsrc/legicrfsim.h +++ b/armsrc/legicrfsim.h @@ -1,4 +1,4 @@ -//----------------------------------------------------------------------------- +//----------------------------------------------------------------------------- // (c) 2009 Henryk Plötz // 2018 AntiCat // diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 6b10ddd0d..5e7375d3d 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -1,2070 +1,2070 @@ -//----------------------------------------------------------------------------- -// Merlok - June 2011, 2012 -// Gerhard de Koning Gans - May 2008 -// Hagen Fritsch - June 2010 -// Midnitesnake - Dec 2013 -// Andy Davies - Apr 2014 -// Iceman - May 2014,2015,2016 -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Routines to support ISO 14443 type A. -//----------------------------------------------------------------------------- - -#include "mifarecmd.h" -#include - -#ifndef HARDNESTED_AUTHENTICATION_TIMEOUT -# define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) -#endif -#ifndef HARDNESTED_PRE_AUTHENTICATION_LEADTIME -# define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication -#endif - -// send an incomplete dummy response in order to trigger the card's authentication failure timeout -#ifndef CHK_TIMEOUT -# define CHK_TIMEOUT() { \ - ReaderTransmit(&dummy_answer, 1, NULL); \ - uint32_t timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT; \ - while (GetCountSspClk() < timeout) {}; \ - } -#endif - -static uint8_t dummy_answer = 0; - -//----------------------------------------------------------------------------- -// Select, Authenticate, Read a MIFARE tag. -// read block -//----------------------------------------------------------------------------- -void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) -{ - // params - uint8_t blockNo = arg0; - uint8_t keyType = arg1; - uint64_t ui64Key = 0; - ui64Key = bytes_to_num(datain, 6); - - // variables - byte_t isOK = 0; - byte_t dataoutbuf[16] = {0x00}; - uint8_t uid[10] = {0x00}; - uint32_t cuid = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - clear_trace(); - set_tracing(true); - - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); - - while (true) { - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - break; - }; - - if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); - break; - }; - - if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Read block error"); - break; - }; - - if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - break; - }; - - isOK = 1; - break; - } - - crypto1_destroy(pcs); - - if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED"); - - LED_B_ON(); - cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16); - LED_B_OFF(); - - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); -} - -void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){ - - bool turnOffField = (arg0 == 1); - - LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - clear_trace(); - set_tracing(true); - - if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); - OnError(0); - return; - }; - - if(!mifare_ultra_auth(keybytes)){ - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed"); - OnError(1); - return; - } - - if (turnOffField) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - } - cmd_send(CMD_ACK,1,0,0,0,0); -} - -// Arg0 = BlockNo, -// Arg1 = UsePwd bool -// datain = PWD bytes, -void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) -{ - uint8_t blockNo = arg0; - byte_t dataout[16] = {0x00}; - bool useKey = (arg1 == 1); //UL_C - bool usePwd = (arg1 == 2); //UL_EV1/NTAG - - LEDsoff(); - LED_A_ON(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - clear_trace(); - set_tracing(true); - - int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true); - if(!len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len); - OnError(1); - return; - } - - // UL-C authentication - if ( useKey ) { - uint8_t key[16] = {0x00}; - memcpy(key, datain, sizeof(key) ); - - if ( !mifare_ultra_auth(key) ) { - OnError(1); - return; - } - } - - // UL-EV1 / NTAG authentication - if ( usePwd ) { - uint8_t pwd[4] = {0x00}; - memcpy(pwd, datain, 4); - uint8_t pack[4] = {0,0,0,0}; - if (!mifare_ul_ev1_auth(pwd, pack)) { - OnError(1); - return; - } - } - - if( mifare_ultra_readblock(blockNo, dataout) ) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error"); - OnError(2); - return; - } - - if( mifare_ultra_halt() ) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); - OnError(3); - return; - } - - cmd_send(CMD_ACK,1,0,0,dataout,16); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); -} - -//----------------------------------------------------------------------------- -// Select, Authenticate, Read a MIFARE tag. -// read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes) -//----------------------------------------------------------------------------- -void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) -{ - // params - uint8_t sectorNo = arg0; - uint8_t keyType = arg1; - uint64_t ui64Key = 0; - ui64Key = bytes_to_num(datain, 6); - - // variables - byte_t isOK = 0; - byte_t dataoutbuf[16 * 16]; - uint8_t uid[10] = {0x00}; - uint32_t cuid = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - clear_trace(); - set_tracing(true); - - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); - - isOK = 1; - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - isOK = 0; - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - } - - - if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { - isOK = 0; - if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); - } - - for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { - if(mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) { - isOK = 0; - if (MF_DBGLEVEL >= 1) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo); - break; - } - } - - if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - } - - if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED"); - - crypto1_destroy(pcs); - - LED_B_ON(); - cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16*NumBlocksPerSector(sectorNo)); - LED_B_OFF(); - - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); -} - -// arg0 = blockNo (start) -// arg1 = Pages (number of blocks) -// arg2 = useKey -// datain = KEY bytes -void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) -{ - LEDsoff(); - LED_A_ON(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - // free eventually allocated BigBuf memory - BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); - set_tracing(true); - - // params - uint8_t blockNo = arg0; - uint16_t blocks = arg1; - bool useKey = (arg2 == 1); //UL_C - bool usePwd = (arg2 == 2); //UL_EV1/NTAG - uint32_t countblocks = 0; - uint8_t *dataout = BigBuf_malloc(CARD_MEMORY_SIZE); - if (dataout == NULL){ - Dbprintf("out of memory"); - OnError(1); - return; - } - - int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true); - if (!len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%d)",len); - OnError(1); - return; - } - - // UL-C authentication - if ( useKey ) { - uint8_t key[16] = {0x00}; - memcpy(key, datain, sizeof(key) ); - - if ( !mifare_ultra_auth(key) ) { - OnError(1); - return; - } - } - - // UL-EV1 / NTAG authentication - if (usePwd) { - uint8_t pwd[4] = {0x00}; - memcpy(pwd, datain, sizeof(pwd)); - uint8_t pack[4] = {0,0,0,0}; - - if (!mifare_ul_ev1_auth(pwd, pack)){ - OnError(1); - return; - } - } - - for (int i = 0; i < blocks; i++){ - if ((i*4) + 4 >= CARD_MEMORY_SIZE) { - Dbprintf("Data exceeds buffer!!"); - break; - } - - len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i); - - if (len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i); - // if no blocks read - error out - if (i == 0) { - OnError(2); - return; - } else { - //stop at last successful read block and return what we got - break; - } - } else { - countblocks++; - } - } - - len = mifare_ultra_halt(); - if (len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); - OnError(3); - return; - } - - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Blocks read %d", countblocks); - - countblocks *= 4; - - cmd_send(CMD_ACK, 1, countblocks, BigBuf_max_traceLen(), 0, 0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - BigBuf_free(); - set_tracing(false); -} - -//----------------------------------------------------------------------------- -// Select, Authenticate, Write a MIFARE tag. -// read block -//----------------------------------------------------------------------------- -void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) -{ - // params - uint8_t blockNo = arg0; - uint8_t keyType = arg1; - uint64_t ui64Key = 0; - byte_t blockdata[16] = {0x00}; - - ui64Key = bytes_to_num(datain, 6); - memcpy(blockdata, datain + 10, 16); - - // variables - byte_t isOK = 0; - uint8_t uid[10] = {0x00}; - uint32_t cuid = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - clear_trace(); - set_tracing(true); - - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); - - while (true) { - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - break; - }; - - if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); - break; - }; - - if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); - break; - }; - - if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - break; - }; - - isOK = 1; - break; - } - - crypto1_destroy(pcs); - - if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); - - cmd_send(CMD_ACK,isOK,0,0,0,0); - - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); -} - -/* // Command not needed but left for future testing -void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain) -{ - uint8_t blockNo = arg0; - byte_t blockdata[16] = {0x00}; - - memcpy(blockdata, datain, 16); - - uint8_t uid[10] = {0x00}; - - LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - - clear_trace(); - set_tracing(true); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - if(!iso14443a_select_card(uid, NULL, NULL, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - OnError(0); - return; - }; - - if(mifare_ultra_writeblock_compat(blockNo, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); - OnError(0); - return; }; - - if(mifare_ultra_halt()) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - OnError(0); - return; - }; - - if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); - - cmd_send(CMD_ACK,1,0,0,0,0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); -} -*/ - -// Arg0 : Block to write to. -// Arg1 : 0 = use no authentication. -// 1 = use 0x1A authentication. -// 2 = use 0x1B authentication. -// datain : 4 first bytes is data to be written. -// : 4/16 next bytes is authentication key. -void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) -{ - uint8_t blockNo = arg0; - bool useKey = (arg1 == 1); //UL_C - bool usePwd = (arg1 == 2); //UL_EV1/NTAG - byte_t blockdata[4] = {0x00}; - - memcpy(blockdata, datain, 4); - - LEDsoff(); - LED_A_ON(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - clear_trace(); - set_tracing(true); - - if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - OnError(0); - return; - }; - - // UL-C authentication - if ( useKey ) { - uint8_t key[16] = {0x00}; - memcpy(key, datain+4, sizeof(key) ); - - if ( !mifare_ultra_auth(key) ) { - OnError(1); - return; - } - } - - // UL-EV1 / NTAG authentication - if (usePwd) { - uint8_t pwd[4] = {0x00}; - memcpy(pwd, datain+4, 4); - uint8_t pack[4] = {0,0,0,0}; - if (!mifare_ul_ev1_auth(pwd, pack)) { - OnError(1); - return; - } - } - - if (mifare_ultra_writeblock(blockNo, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); - OnError(0); - return; - }; - - if (mifare_ultra_halt()) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - OnError(0); - return; - }; - - if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); - - cmd_send(CMD_ACK,1,0,0,0,0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); -} - -void MifareUSetPwd(uint8_t arg0, uint8_t *datain){ - - uint8_t pwd[16] = {0x00}; - byte_t blockdata[4] = {0x00}; - - memcpy(pwd, datain, 16); - - LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - clear_trace(); - set_tracing(true); - - if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - OnError(0); - return; - }; - - blockdata[0] = pwd[7]; - blockdata[1] = pwd[6]; - blockdata[2] = pwd[5]; - blockdata[3] = pwd[4]; - if (mifare_ultra_writeblock( 44, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); - OnError(44); - return; - }; - - blockdata[0] = pwd[3]; - blockdata[1] = pwd[2]; - blockdata[2] = pwd[1]; - blockdata[3] = pwd[0]; - if (mifare_ultra_writeblock( 45, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); - OnError(45); - return; - }; - - blockdata[0] = pwd[15]; - blockdata[1] = pwd[14]; - blockdata[2] = pwd[13]; - blockdata[3] = pwd[12]; - if (mifare_ultra_writeblock( 46, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); - OnError(46); - return; - }; - - blockdata[0] = pwd[11]; - blockdata[1] = pwd[10]; - blockdata[2] = pwd[9]; - blockdata[3] = pwd[8]; - if (mifare_ultra_writeblock( 47, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); - OnError(47); - return; - }; - - if (mifare_ultra_halt()) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - OnError(0); - return; - }; - - cmd_send(CMD_ACK,1,0,0,0,0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); -} - -// Return 1 if the nonce is invalid else return 0 -int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) { - return ((oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \ - (oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \ - (oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0; -} - -void MifareAcquireNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain) { - - uint8_t uid[10] = {0x00}; - uint8_t answer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t par[1] = {0x00}; - uint8_t buf[USB_CMD_DATA_SIZE] = {0x00}; - uint32_t cuid = 0; - int16_t isOK = 0; - uint16_t num_nonces = 0; - uint8_t cascade_levels = 0; - uint8_t blockNo = arg0 & 0xff; - uint8_t keyType = (arg0 >> 8) & 0xff; - bool initialize = flags & 0x0001; - bool field_off = flags & 0x0004; - bool have_uid = false; - - LED_A_ON(); - LED_C_OFF(); - - BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); - set_tracing(true); - - if (initialize) - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - LED_C_ON(); - - for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE-4; i += 4 ) { - - // Test if the action was cancelled - if (BUTTON_PRESS()) { - isOK = 2; - field_off = true; - break; - } - - if (!have_uid) { // need a full select cycle to get the uid first - iso14a_card_select_t card_info; - if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); - continue; - } - switch (card_info.uidlen) { - case 4 : cascade_levels = 1; break; - case 7 : cascade_levels = 2; break; - case 10: cascade_levels = 3; break; - default: break; - } - have_uid = true; - } else { // no need for anticollision. We can directly select the card - if (!iso14443a_fast_select_card(uid, cascade_levels)) { - if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); - continue; - } - } - - // Transmit MIFARE_CLASSIC_AUTH - uint8_t dcmd[4] = {0x60 + (keyType & 0x01), blockNo, 0x00, 0x00}; - AddCrc14A(dcmd, 2); - ReaderTransmit(dcmd, sizeof(dcmd), NULL); - int len = ReaderReceive(answer, par); - - // wait for the card to become ready again - CHK_TIMEOUT(); - - if (len != 4) { - if (MF_DBGLEVEL >= 2) Dbprintf("AcquireNonces: Auth1 error"); - continue; - } - - num_nonces++; - - // Save the tag nonce (nt) - buf[i] = answer[0]; - buf[i+1] = answer[1]; - buf[i+2] = answer[2]; - buf[i+3] = answer[3]; - } - - LED_C_OFF(); - LED_B_ON(); - cmd_send(CMD_ACK, isOK, cuid, num_nonces-1, buf, sizeof(buf)); - LED_B_OFF(); - - if (MF_DBGLEVEL >= 3) DbpString("AcquireNonces finished"); - - if (field_off) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); - } -} - -//----------------------------------------------------------------------------- -// acquire encrypted nonces in order to perform the attack described in -// Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened -// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on -// Computer and Communications Security, 2015 -//----------------------------------------------------------------------------- -void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain) { - - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - - uint8_t uid[10] = {0x00}; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t par_enc[1] = {0x00}; - uint8_t buf[USB_CMD_DATA_SIZE] = {0x00}; - - uint64_t ui64Key = bytes_to_num(datain, 6); - uint32_t cuid = 0; - int16_t isOK = 0; - uint16_t num_nonces = 0; - uint8_t nt_par_enc = 0; - uint8_t cascade_levels = 0; - uint8_t blockNo = arg0 & 0xff; - uint8_t keyType = (arg0 >> 8) & 0xff; - uint8_t targetBlockNo = arg1 & 0xff; - uint8_t targetKeyType = (arg1 >> 8) & 0xff; - bool initialize = flags & 0x0001; - bool slow = flags & 0x0002; - bool field_off = flags & 0x0004; - bool have_uid = false; - - LED_A_ON(); - LED_C_OFF(); - - BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); - set_tracing(false); - - if (initialize) - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - LED_C_ON(); - - for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE - 9; ) { - - // Test if the action was cancelled - if(BUTTON_PRESS()) { - isOK = 2; - field_off = true; - break; - } - - if (!have_uid) { // need a full select cycle to get the uid first - iso14a_card_select_t card_info; - if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); - continue; - } - switch (card_info.uidlen) { - case 4 : cascade_levels = 1; break; - case 7 : cascade_levels = 2; break; - case 10: cascade_levels = 3; break; - default: break; - } - have_uid = true; - } else { // no need for anticollision. We can directly select the card - if (!iso14443a_fast_select_card(uid, cascade_levels)) { - if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); - continue; - } - } - - if (slow) - SpinDelayUs(HARDNESTED_PRE_AUTHENTICATION_LEADTIME); - - uint32_t nt1; - if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) { - if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error"); - continue; - } - - // nested authentication - uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL); - - // wait for the card to become ready again - CHK_TIMEOUT(); - - if (len != 4) { - if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len); - continue; - } - - num_nonces++; - if (num_nonces % 2) { - memcpy(buf+i, receivedAnswer, 4); - nt_par_enc = par_enc[0] & 0xf0; - } else { - nt_par_enc |= par_enc[0] >> 4; - memcpy(buf+i+4, receivedAnswer, 4); - memcpy(buf+i+8, &nt_par_enc, 1); - i += 9; - } - } - - LED_C_OFF(); - crypto1_destroy(pcs); - LED_B_ON(); - cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf)); - LED_B_OFF(); - - if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished"); - - if (field_off) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); - } -} - - -//----------------------------------------------------------------------------- -// MIFARE nested authentication. -// -//----------------------------------------------------------------------------- -void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *datain) -{ - // params - uint8_t blockNo = arg0 & 0xff; - uint8_t keyType = (arg0 >> 8) & 0xff; - uint8_t targetBlockNo = arg1 & 0xff; - uint8_t targetKeyType = (arg1 >> 8) & 0xff; - uint64_t ui64Key = 0; - - ui64Key = bytes_to_num(datain, 6); - - // variables - uint16_t rtr, i, j, len; - uint16_t davg = 0; - static uint16_t dmin, dmax; - uint8_t uid[10] = {0x00}; - uint32_t cuid = 0, nt1, nt2, nttmp, nttest, ks1; - uint8_t par[1] = {0x00}; - uint32_t target_nt[2] = {0x00}, target_ks[2] = {0x00}; - - uint8_t par_array[4] = {0x00}; - uint16_t ncount = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - - uint32_t auth1_time, auth2_time; - static uint16_t delta_time = 0; - - LED_A_ON(); - LED_C_OFF(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - // free eventually allocated BigBuf memory - BigBuf_free(); BigBuf_Clear_ext(false); - - if (calibrate) clear_trace(); - set_tracing(true); - - // statistics on nonce distance - int16_t isOK = 0; - #define NESTED_MAX_TRIES 12 - uint16_t unsuccessfull_tries = 0; - if (calibrate) { // for first call only. Otherwise reuse previous calibration - LED_B_ON(); - WDT_HIT(); - - davg = dmax = 0; - dmin = 2000; - delta_time = 0; - - for (rtr = 0; rtr < 17; rtr++) { - - // Test if the action was cancelled - if(BUTTON_PRESS()) { - isOK = -2; - break; - } - - // prepare next select. No need to power down the card. - if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Halt error"); - rtr--; - continue; - } - - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Can't select card"); - rtr--; - continue; - }; - - auth1_time = 0; - if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) { - if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth1 error"); - rtr--; - continue; - }; - auth2_time = (delta_time) ? auth1_time + delta_time : 0; - - if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2, &auth2_time)) { - if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth2 error"); - rtr--; - continue; - }; - - nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160 - for (i = 101; i < 1200; i++) { - nttmp = prng_successor(nttmp, 1); - if (nttmp == nt2) break; - } - - if (i != 1200) { - if (rtr != 0) { - davg += i; - dmin = MIN(dmin, i); - dmax = MAX(dmax, i); - } - else { - delta_time = auth2_time - auth1_time + 32; // allow some slack for proper timing - } - if (MF_DBGLEVEL >= 3) Dbprintf("Nested: calibrating... ntdist=%d", i); - } else { - unsuccessfull_tries++; - if (unsuccessfull_tries > NESTED_MAX_TRIES) { // card isn't vulnerable to nested attack (random numbers are not predictable) - isOK = -3; - } - } - } - - davg = (davg + (rtr - 1)/2) / (rtr - 1); - - if (MF_DBGLEVEL >= 3) Dbprintf("rtr=%d isOK=%d min=%d max=%d avg=%d, delta_time=%d", rtr, isOK, dmin, dmax, davg, delta_time); - - dmin = davg - 2; - dmax = davg + 2; - - LED_B_OFF(); - } -// ------------------------------------------------------------------------------------------------- - - LED_C_ON(); - - // get crypted nonces for target sector - for(i=0; i < 2 && !isOK; i++) { // look for exactly two different nonces - - target_nt[i] = 0; - while(target_nt[i] == 0) { // continue until we have an unambiguous nonce - - // prepare next select. No need to power down the card. - if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Halt error"); - continue; - } - - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Can't select card"); - continue; - }; - - auth1_time = 0; - if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) { - if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth1 error"); - continue; - }; - - // nested authentication - auth2_time = auth1_time + delta_time; - - len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time); - if (len != 4) { - if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth2 error len=%d", len); - continue; - }; - - nt2 = bytes_to_num(receivedAnswer, 4); - if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: Testing nt1=%08x nt2enc=%08x nt2par=%02x", i+1, nt1, nt2, par[0]); - - // Parity validity check - for (j = 0; j < 4; j++) { - par_array[j] = (oddparity8(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01)); - } - - ncount = 0; - nttest = prng_successor(nt1, dmin - 1); - for (j = dmin; j < dmax + 1; j++) { - nttest = prng_successor(nttest, 1); - ks1 = nt2 ^ nttest; - - if (valid_nonce(nttest, nt2, ks1, par_array)){ - if (ncount > 0) { // we are only interested in disambiguous nonces, try again - if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (ambigous), ntdist=%d", i+1, j); - target_nt[i] = 0; - break; - } - target_nt[i] = nttest; - target_ks[i] = ks1; - ncount++; - if (i == 1 && target_nt[1] == target_nt[0]) { // we need two different nonces - target_nt[i] = 0; - if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#2: dismissed (= nonce#1), ntdist=%d", j); - break; - } - if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: valid, ntdist=%d", i+1, j); - } - } - if (target_nt[i] == 0 && j == dmax+1 && MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (all invalid)", i+1); - } - } - - LED_C_OFF(); - - crypto1_destroy(pcs); - - uint8_t buf[4 + 4 * 4] = {0}; - memcpy(buf, &cuid, 4); - memcpy(buf+4, &target_nt[0], 4); - memcpy(buf+8, &target_ks[0], 4); - memcpy(buf+12, &target_nt[1], 4); - memcpy(buf+16, &target_ks[1], 4); - - LED_B_ON(); - cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf)); - LED_B_OFF(); - - if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED"); - - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); -} - -//----------------------------------------------------------------------------- -// MIFARE check keys. key count up to 85. -// -//----------------------------------------------------------------------------- -typedef struct sector_t { - uint8_t keyA[6]; - uint8_t keyB[6]; -} sector_t; - -typedef struct chk_t { - uint64_t key; - uint32_t cuid; - uint8_t cl; - uint8_t block; - uint8_t keyType; - uint8_t *uid; - struct Crypto1State *pcs; -} chk_t; - -// checks one key. -// fast select, tries 5 times to select -// -// return: -// 2 = failed to select. -// 1 = wrong key -// 0 = correct key -uint8_t chkKey( struct chk_t *c ) { - uint8_t i = 0, res = 2; - while( i < 5 ) { - // this part is from Piwi's faster nonce collecting part in Hardnested. - // assume: fast select - if (!iso14443a_fast_select_card(c->uid, c->cl)) { - ++i; - continue; - } - res = mifare_classic_authex(c->pcs, c->cuid, c->block, c->keyType, c->key, AUTH_FIRST, NULL, NULL); - - CHK_TIMEOUT(); - - // if successfull auth, send HALT - // if ( !res ) - // mifare_classic_halt_ex(c->pcs); - break; - } - return res; -} - -uint8_t chkKey_readb(struct chk_t *c, uint8_t *keyb) { - - if (!iso14443a_fast_select_card(c->uid, c->cl)) - return 2; - - if ( mifare_classic_authex(c->pcs, c->cuid, c->block, 0, c->key, AUTH_FIRST, NULL, NULL) ) - return 1; - - uint8_t data[16] = {0x00}; - uint8_t res = mifare_classic_readblock(c->pcs, c->cuid, c->block, data); - - // successful read - if ( !res ) { - // data was something else than zeros. - if ( memcmp(data+10, "\x00\x00\x00\x00\x00\x00", 6) != 0) { - memcpy(keyb, data+10, 6); - res = 0; - } else { - res = 3; - } - mifare_classic_halt_ex(c->pcs); - } - return res; -} - -void chkKey_scanA(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { - for (uint8_t s = 0; s < *sectorcnt; s++) { - - // skip already found A keys - if ( found[(s*2)] ) - continue; - - c->block = FirstBlockOfSector( s ); - if ( chkKey( c ) == 0 ) { - num_to_bytes(c->key, 6, k_sector[s].keyA); - found[(s*2)] = 1; - ++*foundkeys; - - if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan A found (%d)", c->block); - } - } -} - -void chkKey_scanB(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { - for (uint8_t s = 0; s < *sectorcnt; s++) { - - // skip already found B keys - if ( found[(s*2)+1] ) - continue; - - c->block = FirstBlockOfSector( s ); - if ( chkKey( c ) == 0 ) { - num_to_bytes(c->key, 6, k_sector[s].keyB); - found[(s*2)+1] = 1; - ++*foundkeys; - - if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan B found (%d)", c->block); - } - } -} - -// loop all A keys, -// when A is found but not B, try to read B. -void chkKey_loopBonly(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { - - // read Block B, if A is found. - for (uint8_t s = 0; s < *sectorcnt; ++s) { - - if ( found[(s*2)] && found[(s*2)+1] ) - continue; - - c->block = (FirstBlockOfSector( s ) + NumBlocksPerSector( s ) - 1); - - // A but not B - if ( found[(s*2)] && !found[(s*2)+1] ){ - c->key = bytes_to_num(k_sector[s].keyA, 6); - uint8_t status = chkKey_readb(c, k_sector[s].keyB); - if ( status == 0 ){ - found[(s*2)+1] = 1; - ++*foundkeys; - - if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Reading B found (%d)", c->block); - - // try quick find all B? - // assume: keys comes in groups. Find one B, test against all B. - c->key = bytes_to_num( k_sector[s].keyB, 6); - c->keyType = 1; - chkKey_scanB(c, k_sector, found, sectorcnt, foundkeys); - } - } - } -} - - - -// get Chunks of keys, to test authentication against card. -// arg0 = antal sectorer -// arg0 = first time -// arg1 = clear trace -// arg2 = antal nycklar i keychunk -// datain = keys as array -void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { - - // first call or - uint8_t sectorcnt = arg0 & 0xFF; // 16; - uint8_t firstchunk = (arg0 >> 8) & 0xF; - uint8_t lastchunk = (arg0 >> 12) & 0xF; - uint8_t strategy = arg1 & 0xFF; - uint8_t use_flashmem = (arg1 >> 8) & 0xFF; - uint16_t keyCount = arg2 & 0xFF; - uint8_t status = 0; - - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - struct chk_t chk_data; - - uint8_t allkeys = sectorcnt << 1; - - static uint32_t cuid = 0; - static uint8_t cascade_levels = 0; - static uint8_t foundkeys = 0; - static sector_t k_sector[80]; - static uint8_t found[80]; - static uint8_t *uid; - -#ifdef WITH_FLASH - if ( use_flashmem ) { - BigBuf_free(); - uint16_t isok = 0; - uint8_t size[2] = {0x00, 0x00}; - isok = Flash_ReadData(DEFAULT_MF_KEYS_OFFSET, size, 2); - if ( isok != 2 ) - goto OUT; - - keyCount = size[1] << 8 | size[0]; - - if ( keyCount == 0 && keyCount == 0xFFFF) - goto OUT; - - datain = BigBuf_malloc( keyCount * 6); - if (datain == NULL ) - goto OUT; - - isok = Flash_ReadData(DEFAULT_MF_KEYS_OFFSET+2, datain, keyCount * 6); - if ( isok != keyCount * 6 ) - goto OUT; - - } -#endif - - if (uid == NULL || firstchunk) { - uid = BigBuf_malloc(10); - if (uid == NULL ) - goto OUT; - } - - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - LEDsoff(); - LED_A_ON(); - - if ( firstchunk ) { - clear_trace(); - set_tracing(false); - - memset(k_sector, 0x00, 480+10); - memset(found, 0x00, sizeof(found)); - foundkeys = 0; - - iso14a_card_select_t card_info; - if ( !iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys_fast: Can't select card (ALL)"); - goto OUT; - } - - switch (card_info.uidlen) { - case 4 : cascade_levels = 1; break; - case 7 : cascade_levels = 2; break; - case 10: cascade_levels = 3; break; - default: break; - } - - CHK_TIMEOUT(); - } - - // set check struct. - chk_data.uid = uid; - chk_data.cuid = cuid; - chk_data.cl = cascade_levels; - chk_data.pcs = pcs; - chk_data.block = 0; - - // keychunk loop - depth first one sector. - if ( strategy == 1 || use_flashmem) { - - uint8_t newfound = foundkeys; - - uint16_t lastpos = 0; - uint16_t s_point = 0; - // Sector main loop - // keep track of how many sectors on card. - for (uint8_t s = 0; s < sectorcnt; ++s) { - - if ( found[(s*2)] && found[(s*2)+1] ) - continue; - - for (uint16_t i = s_point; i < keyCount; ++i) { - - //if ( i % 100 == 0) Dbprintf("ChkKeys_fast: sector %d | checking %d | %d found | s_point %d", s, i, foundkeys, s_point); - - // Allow button press / usb cmd to interrupt device - if (BUTTON_PRESS() && !usb_poll_validate_length()) { - goto OUT; - } - - // found all keys? - if ( foundkeys == allkeys ) - goto OUT; - - WDT_HIT(); - - // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector - chk_data.block = FirstBlockOfSector( s ); - - // new key - chk_data.key = bytes_to_num(datain + i * 6, 6); - - // skip already found A keys - if( !found[(s*2)] ) { - chk_data.keyType = 0; - status = chkKey( &chk_data); - if ( status == 0 ) { - memcpy(k_sector[s].keyA, datain + i * 6, 6); - found[(s*2)] = 1; - ++foundkeys; - - chkKey_scanA(&chk_data, k_sector, found, §orcnt, &foundkeys); - - // read Block B, if A is found. - chkKey_loopBonly( &chk_data, k_sector, found, §orcnt, &foundkeys); - - chk_data.keyType = 1; - chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); - - chk_data.keyType = 0; - chk_data.block = FirstBlockOfSector( s ); - - if ( use_flashmem ) { - if ( lastpos != i && lastpos != 0) { - if ( i - lastpos < 0xF) { - s_point = i & 0xFFF0; - } - } else { - lastpos = i; - } - } - } - } - - // skip already found B keys - if( !found[(s*2)+1] ) { - chk_data.keyType = 1; - status = chkKey( &chk_data); - if ( status == 0 ) { - memcpy(k_sector[s].keyB, datain + i * 6, 6); - found[(s*2)+1] = 1; - ++foundkeys; - - chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); - - if ( use_flashmem ) { - if ( lastpos != i && lastpos != 0) { - - if ( i - lastpos < 0xF) - s_point = i & 0xFFF0; - } else { - lastpos = i; - } - } - } - } - - if ( found[(s*2)] && found[(s*2)+1] ) - break; - - } // end keys test loop - depth first - - // assume1. if no keys found in first sector, get next keychunk from client - if ( !use_flashmem && (newfound-foundkeys == 0) ) - goto OUT; - - } // end loop - sector - } // end strategy 1 - - if ( foundkeys == allkeys ) - goto OUT; - - if ( strategy == 2 || use_flashmem ) { - - // Keychunk loop - for (uint16_t i = 0; i < keyCount; i++) { - - // Allow button press / usb cmd to interrupt device - if (BUTTON_PRESS() && !usb_poll_validate_length()) break; - - // found all keys? - if ( foundkeys == allkeys ) - goto OUT; - - WDT_HIT(); - - // new key - chk_data.key = bytes_to_num(datain + i * 6, 6); - - // Sector main loop - // keep track of how many sectors on card. - for (uint8_t s = 0; s < sectorcnt; ++s) { - - if ( found[(s*2)] && found[(s*2)+1] ) continue; - - // found all keys? - if ( foundkeys == allkeys ) - goto OUT; - - // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector - chk_data.block = FirstBlockOfSector( s ); - - // skip already found A keys - if( !found[(s*2)] ) { - chk_data.keyType = 0; - status = chkKey( &chk_data); - if ( status == 0 ) { - memcpy(k_sector[s].keyA, datain + i * 6, 6); - found[(s*2)] = 1; - ++foundkeys; - - chkKey_scanA( &chk_data, k_sector, found, §orcnt, &foundkeys); - - // read Block B, if A is found. - chkKey_loopBonly( &chk_data, k_sector, found, §orcnt, &foundkeys); - - chk_data.block = FirstBlockOfSector( s ); - } - } - - // skip already found B keys - if( !found[(s*2)+1] ) { - chk_data.keyType = 1; - status = chkKey( &chk_data); - if ( status == 0 ) { - memcpy(k_sector[s].keyB, datain + i * 6, 6); - found[(s*2)+1] = 1; - ++foundkeys; - - chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); - } - } - } // end loop sectors - } // end loop keys - } // end loop strategy 2 -OUT: - LEDsoff(); - - crypto1_destroy(pcs); - - // All keys found, send to client, or last keychunk from client - if (foundkeys == allkeys || lastchunk ) { - - uint64_t foo = 0; - for (uint8_t m = 0; m < 64; m++) { - foo |= ((uint64_t)(found[m] & 1) << m); - } - - uint16_t bar = 0; - uint8_t j = 0; - for (uint8_t m=64; m < sizeof(found); m++) { - bar |= ((uint16_t)(found[m] & 1) << j++); - } - - uint8_t *tmp = BigBuf_malloc(480+10); - memcpy(tmp, k_sector, sectorcnt * sizeof(sector_t) ); - num_to_bytes(foo, 8, tmp+480); - tmp[488] = bar & 0xFF; - tmp[489] = bar >> 8 & 0xFF; - - cmd_send(CMD_ACK, foundkeys, 0, 0, tmp, 480+10); - - set_tracing(false); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - BigBuf_free(); BigBuf_Clear_ext(false); - } else { - // partial/none keys found - cmd_send(CMD_ACK, foundkeys, 0, 0, 0, 0); - } -} - -void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { - - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - - uint8_t uid[10] = {0x00}; - - uint64_t key = 0; - uint32_t cuid = 0; - int i, res; - uint8_t blockNo = arg0 & 0xFF; - uint8_t keyType = (arg0 >> 8) & 0xFF; - uint8_t keyCount = arg2; - uint8_t cascade_levels = 0; - uint8_t isOK = 0; - bool have_uid = false; - bool clearTrace = arg1 & 0xFF; - - LEDsoff(); - LED_A_ON(); - - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - if (clearTrace) - clear_trace(); - - set_tracing(true); - - for (i = 0; i < keyCount; i++) { - - // Iceman: use piwi's faster nonce collecting part in hardnested. - if (!have_uid) { // need a full select cycle to get the uid first - iso14a_card_select_t card_info; - if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (ALL)"); - --i; // try same key once again - continue; - } - switch (card_info.uidlen) { - case 4 : cascade_levels = 1; break; - case 7 : cascade_levels = 2; break; - case 10: cascade_levels = 3; break; - default: break; - } - have_uid = true; - } else { // no need for anticollision. We can directly select the card - if (!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (UID)"); - --i; // try same key once again - continue; - } - } - - key = bytes_to_num(datain + i * 6, 6); - res = mifare_classic_auth(pcs, cuid, blockNo, keyType, key, AUTH_FIRST); - - CHK_TIMEOUT(); - - if (res) - continue; - - isOK = 1; - break; - } - - LED_B_ON(); - cmd_send(CMD_ACK, isOK, 0, 0, datain + i * 6, 6); - - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - - set_tracing(false); - crypto1_destroy(pcs); -} - -//----------------------------------------------------------------------------- -// MIFARE commands set debug level -// -//----------------------------------------------------------------------------- -void MifareSetDbgLvl(uint16_t arg0){ - MF_DBGLEVEL = arg0; - Dbprintf("Debug level: %d", MF_DBGLEVEL); -} - -//----------------------------------------------------------------------------- -// Work with emulator memory -// -// Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not -// involved in dealing with emulator memory. But if it is called later, it might -// destroy the Emulator Memory. -//----------------------------------------------------------------------------- - -void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - emlClearMem(); -} - -void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - if (arg2==0) arg2 = 16; // backwards compat... default bytewidth - 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){ - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - byte_t buf[USB_CMD_DATA_SIZE] = {0x00}; - emlGetMem(buf, arg0, arg1); // data, block num, blocks count (max 4) - - LED_B_ON(); - cmd_send(CMD_ACK,arg0,arg1,0,buf,USB_CMD_DATA_SIZE); - LED_B_OFF(); -} - -//----------------------------------------------------------------------------- -// Load a card into the emulator memory -// -//----------------------------------------------------------------------------- -void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ - uint8_t numSectors = arg0; - uint8_t keyType = arg1; - uint64_t ui64Key = 0; - uint32_t cuid = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - - // variables - byte_t dataoutbuf[16] = {0x00}; - byte_t dataoutbuf2[16] = {0x00}; - uint8_t uid[10] = {0x00}; - - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - clear_trace(); - set_tracing(true); - - bool isOK = true; - - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - isOK = false; - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - } - - for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) { - ui64Key = emlGetKey(sectorNo, keyType); - if (sectorNo == 0){ - if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { - isOK = false; - if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo); - break; - } - } else { - if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) { - isOK = false; - if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth nested error", sectorNo); - break; - } - } - - for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { - if(isOK && mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) { - isOK = false; - if (MF_DBGLEVEL >= 1) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo); - break; - } - if (isOK) { - if (blockNo < NumBlocksPerSector(sectorNo) - 1) { - emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1); - } else { // sector trailer, keep the keys, set only the AC - emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); - memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4); - emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); - } - } - } - - } - - if(mifare_classic_halt(pcs, cuid)) - if (MF_DBGLEVEL >= 1) - Dbprintf("Halt error"); - - // ----------------------------- crypto1 destroy - crypto1_destroy(pcs); - - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - - if (MF_DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED"); - - set_tracing(false); -} - - -//----------------------------------------------------------------------------- -// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn) -// -// PARAMS - workFlags -// bit 0 - need get UID -// bit 1 - need wupC -// bit 2 - need HALT after sequence -// bit 3 - need turn on FPGA before sequence -// bit 4 - need turn off FPGA -// bit 5 - need to set datain instead of issuing USB reply (called via ARM for StandAloneMode14a) -// bit 6 - wipe tag. -//----------------------------------------------------------------------------- -// magic uid card generation 1 commands -uint8_t wupC1[] = { MIFARE_MAGICWUPC1 }; -uint8_t wupC2[] = { MIFARE_MAGICWUPC2 }; -uint8_t wipeC[] = { MIFARE_MAGICWIPEC }; - -void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){ - - // params - uint8_t workFlags = arg0; - uint8_t blockNo = arg1; - - // detect 1a/1b - bool is1b = false; - - // variables - bool isOK = false; //assume we will get an error - uint8_t errormsg = 0x00; - uint8_t uid[10] = {0x00}; - uint8_t data[18] = {0x00}; - uint32_t cuid = 0; - - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - - if (workFlags & MAGIC_INIT) { - LED_A_ON(); - LED_B_OFF(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); - } - - //loop doesn't loop just breaks out if error - while (true) { - // read UID and return to client with write - if (workFlags & MAGIC_UID) { - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); - errormsg = MAGIC_UID; - } - mifare_classic_halt_ex(NULL); - break; - } - - // wipe tag, fill it with zeros - if (workFlags & MAGIC_WIPE){ - ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC1 error"); - errormsg = MAGIC_WIPE; - break; - } - - ReaderTransmit(wipeC, sizeof(wipeC), NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wipeC error"); - errormsg = MAGIC_WIPE; - break; - } - - mifare_classic_halt_ex(NULL); - } - - // write block - if (workFlags & MAGIC_WUPC) { - ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC1 error"); - errormsg = MAGIC_WUPC; - break; - } - - if ( !is1b ) { - ReaderTransmit(wupC2, sizeof(wupC2), NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Assuming Magic Gen 1B tag. [wupC2 failed]"); - is1b = true; - continue; - } - } - } - - if ((mifare_sendcmd_short(NULL, 0, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("write block send command error"); - errormsg = 4; - break; - } - - memcpy(data, datain, 16); - AddCrc14A(data, 16); - - ReaderTransmit(data, sizeof(data), NULL); - if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("write block send data error"); - errormsg = 0; - break; - } - - if (workFlags & MAGIC_HALT) - mifare_classic_halt_ex(NULL); - - isOK = true; - break; - - } // end while - - if (isOK ) - cmd_send(CMD_ACK,1,0,0,uid,sizeof(uid)); - else - OnErrorMagic(errormsg); - - if (workFlags & MAGIC_OFF) - OnSuccessMagic(); -} - -void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){ - - uint8_t workFlags = arg0; - uint8_t blockNo = arg1; - uint8_t errormsg = 0x00; - bool isOK = false; //assume we will get an error - - // detect 1a/1b - bool is1b = false; - - // variables - uint8_t data[MAX_MIFARE_FRAME_SIZE]; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - - memset(data, 0x00, sizeof(data)); - - if (workFlags & MAGIC_INIT) { - LED_A_ON(); - LED_B_OFF(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); - } - - //loop doesn't loop just breaks out if error or done - while (true) { - if (workFlags & MAGIC_WUPC) { - ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC1 error"); - errormsg = MAGIC_WUPC; - break; - } - - if ( !is1b ) { - ReaderTransmit(wupC2, sizeof(wupC2), NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Assuming Magic Gen 1B tag. [wupC2 failed]"); - is1b = true; - continue; - } - } - } - - // read block - if ((mifare_sendcmd_short(NULL, 0, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("read block send command error"); - errormsg = 0; - break; - } - - memcpy(data, receivedAnswer, sizeof(data)); - - // send HALT - if (workFlags & MAGIC_HALT) - mifare_classic_halt_ex(NULL); - - isOK = true; - break; - } - // if MAGIC_DATAIN, the data stays on device side. - if (workFlags & MAGIC_DATAIN) { - if (isOK) - memcpy(datain, data, sizeof(data)); - } else { - if (isOK) - cmd_send(CMD_ACK,1,0,0,data,sizeof(data)); - else - OnErrorMagic(errormsg); - } - - if (workFlags & MAGIC_OFF) - OnSuccessMagic(); -} - -void MifareCIdent(){ - #define GEN_1A 1 - #define GEN_1B 2 - #define GEN_2 4 - // variables - uint8_t isGen = 0; - uint8_t rec[1] = {0x00}; - uint8_t recpar[1] = {0x00}; - - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - // Generation 1 test - ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); - if(!ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) { - goto TEST2; - }; - isGen = GEN_1B; - - ReaderTransmit(wupC2, sizeof(wupC2), NULL); - if(!ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) { - goto OUT; - }; - isGen = GEN_1A; - goto OUT; - -TEST2:; -/* - // Generation 2 test - - // halt previous. - mifare_classic_halt(NULL, 0); - - //select - if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { - goto OUT; - }; - - // MIFARE_CLASSIC_WRITEBLOCK 0xA0 - // ACK 0x0a - uint16_t len = mifare_sendcmd_short(null, 1, 0xA0, 0, rec, recpar, NULL); - if ((len != 1) || (rec[0] != 0x0A)) { - isGen = GEN_2; - }; - */ -OUT:; - // removed the if, since some magic tags misbehavies and send an answer to it. - mifare_classic_halt_ex(NULL); - cmd_send(CMD_ACK, isGen, 0, 0, 0, 0); - // turns off - OnSuccessMagic(); -} - -void OnSuccessMagic(){ - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); -} -void OnErrorMagic(uint8_t reason){ - // ACK, ISOK, reason,0,0,0 - cmd_send(CMD_ACK,0,reason,0,0,0); - OnSuccessMagic(); -} - -void MifareSetMod(uint8_t mod, uint8_t *key) { - uint64_t ui64Key = bytes_to_num(key, 6); - - // variables - uint8_t isOK = 0; - uint8_t uid[10] = {0}; - uint32_t cuid = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs = &mpcs; - int respLen = 0; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0}; - - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - - clear_trace(); - set_tracing(true); - - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); - - while (true) { - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - break; - } - - if(mifare_classic_auth(pcs, cuid, 0, 0, ui64Key, AUTH_FIRST)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); - break; - } - - if (((respLen = mifare_sendcmd_short(pcs, 1, 0x43, mod, receivedAnswer, receivedAnswerPar, NULL)) != 1) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) Dbprintf("SetMod error; response[0]: %hhX, len: %d", receivedAnswer[0], respLen); - break; - } - - if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - break; - } - - isOK = 1; - break; - } - - crypto1_destroy(pcs); - - LED_B_ON(); - cmd_send(CMD_ACK, isOK, 0, 0, 0, 0); - LED_B_OFF(); - - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); -} - -// -// DESFIRE -// -void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){ - byte_t dataout[12] = {0x00}; - uint8_t uid[10] = {0x00}; - uint32_t cuid = 0; - - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); - - int len = iso14443a_select_card(uid, NULL, &cuid, true, 0, false); - if(!len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); - OnError(1); - return; - }; - - if(mifare_desfire_des_auth1(cuid, dataout)){ - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part1: Fail."); - OnError(4); - return; - } - - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED"); - cmd_send(CMD_ACK, 1, cuid, 0, dataout, sizeof(dataout)); -} - -void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){ - uint32_t cuid = arg0; - uint8_t key[16] = {0x00}; - byte_t dataout[12] = {0x00}; - byte_t isOK = 0; - - memcpy(key, datain, 16); - - isOK = mifare_desfire_des_auth2(cuid, key, dataout); - - if( isOK) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed"); - OnError(4); - return; - } - - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED"); - - cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout)); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); +//----------------------------------------------------------------------------- +// Merlok - June 2011, 2012 +// Gerhard de Koning Gans - May 2008 +// Hagen Fritsch - June 2010 +// Midnitesnake - Dec 2013 +// Andy Davies - Apr 2014 +// Iceman - May 2014,2015,2016 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Routines to support ISO 14443 type A. +//----------------------------------------------------------------------------- + +#include "mifarecmd.h" +#include + +#ifndef HARDNESTED_AUTHENTICATION_TIMEOUT +# define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) +#endif +#ifndef HARDNESTED_PRE_AUTHENTICATION_LEADTIME +# define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication +#endif + +// send an incomplete dummy response in order to trigger the card's authentication failure timeout +#ifndef CHK_TIMEOUT +# define CHK_TIMEOUT() { \ + ReaderTransmit(&dummy_answer, 1, NULL); \ + uint32_t timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT; \ + while (GetCountSspClk() < timeout) {}; \ + } +#endif + +static uint8_t dummy_answer = 0; + +//----------------------------------------------------------------------------- +// Select, Authenticate, Read a MIFARE tag. +// read block +//----------------------------------------------------------------------------- +void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) +{ + // params + uint8_t blockNo = arg0; + uint8_t keyType = arg1; + uint64_t ui64Key = 0; + ui64Key = bytes_to_num(datain, 6); + + // variables + byte_t isOK = 0; + byte_t dataoutbuf[16] = {0x00}; + uint8_t uid[10] = {0x00}; + uint32_t cuid = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + clear_trace(); + set_tracing(true); + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + + while (true) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + break; + }; + + if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); + break; + }; + + if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Read block error"); + break; + }; + + if(mifare_classic_halt(pcs, cuid)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + break; + }; + + isOK = 1; + break; + } + + crypto1_destroy(pcs); + + if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED"); + + LED_B_ON(); + cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16); + LED_B_OFF(); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); +} + +void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){ + + bool turnOffField = (arg0 == 1); + + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + clear_trace(); + set_tracing(true); + + if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); + OnError(0); + return; + }; + + if(!mifare_ultra_auth(keybytes)){ + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed"); + OnError(1); + return; + } + + if (turnOffField) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + } + cmd_send(CMD_ACK,1,0,0,0,0); +} + +// Arg0 = BlockNo, +// Arg1 = UsePwd bool +// datain = PWD bytes, +void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) +{ + uint8_t blockNo = arg0; + byte_t dataout[16] = {0x00}; + bool useKey = (arg1 == 1); //UL_C + bool usePwd = (arg1 == 2); //UL_EV1/NTAG + + LEDsoff(); + LED_A_ON(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + clear_trace(); + set_tracing(true); + + int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true); + if(!len) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len); + OnError(1); + return; + } + + // UL-C authentication + if ( useKey ) { + uint8_t key[16] = {0x00}; + memcpy(key, datain, sizeof(key) ); + + if ( !mifare_ultra_auth(key) ) { + OnError(1); + return; + } + } + + // UL-EV1 / NTAG authentication + if ( usePwd ) { + uint8_t pwd[4] = {0x00}; + memcpy(pwd, datain, 4); + uint8_t pack[4] = {0,0,0,0}; + if (!mifare_ul_ev1_auth(pwd, pack)) { + OnError(1); + return; + } + } + + if( mifare_ultra_readblock(blockNo, dataout) ) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error"); + OnError(2); + return; + } + + if( mifare_ultra_halt() ) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); + OnError(3); + return; + } + + cmd_send(CMD_ACK,1,0,0,dataout,16); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); +} + +//----------------------------------------------------------------------------- +// Select, Authenticate, Read a MIFARE tag. +// read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes) +//----------------------------------------------------------------------------- +void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) +{ + // params + uint8_t sectorNo = arg0; + uint8_t keyType = arg1; + uint64_t ui64Key = 0; + ui64Key = bytes_to_num(datain, 6); + + // variables + byte_t isOK = 0; + byte_t dataoutbuf[16 * 16]; + uint8_t uid[10] = {0x00}; + uint32_t cuid = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + clear_trace(); + set_tracing(true); + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + + isOK = 1; + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + isOK = 0; + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + } + + + if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { + isOK = 0; + if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); + } + + for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { + if(mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) { + isOK = 0; + if (MF_DBGLEVEL >= 1) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo); + break; + } + } + + if(mifare_classic_halt(pcs, cuid)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + } + + if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED"); + + crypto1_destroy(pcs); + + LED_B_ON(); + cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16*NumBlocksPerSector(sectorNo)); + LED_B_OFF(); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); +} + +// arg0 = blockNo (start) +// arg1 = Pages (number of blocks) +// arg2 = useKey +// datain = KEY bytes +void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) +{ + LEDsoff(); + LED_A_ON(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + // free eventually allocated BigBuf memory + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); + + // params + uint8_t blockNo = arg0; + uint16_t blocks = arg1; + bool useKey = (arg2 == 1); //UL_C + bool usePwd = (arg2 == 2); //UL_EV1/NTAG + uint32_t countblocks = 0; + uint8_t *dataout = BigBuf_malloc(CARD_MEMORY_SIZE); + if (dataout == NULL){ + Dbprintf("out of memory"); + OnError(1); + return; + } + + int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true); + if (!len) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%d)",len); + OnError(1); + return; + } + + // UL-C authentication + if ( useKey ) { + uint8_t key[16] = {0x00}; + memcpy(key, datain, sizeof(key) ); + + if ( !mifare_ultra_auth(key) ) { + OnError(1); + return; + } + } + + // UL-EV1 / NTAG authentication + if (usePwd) { + uint8_t pwd[4] = {0x00}; + memcpy(pwd, datain, sizeof(pwd)); + uint8_t pack[4] = {0,0,0,0}; + + if (!mifare_ul_ev1_auth(pwd, pack)){ + OnError(1); + return; + } + } + + for (int i = 0; i < blocks; i++){ + if ((i*4) + 4 >= CARD_MEMORY_SIZE) { + Dbprintf("Data exceeds buffer!!"); + break; + } + + len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i); + + if (len) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i); + // if no blocks read - error out + if (i == 0) { + OnError(2); + return; + } else { + //stop at last successful read block and return what we got + break; + } + } else { + countblocks++; + } + } + + len = mifare_ultra_halt(); + if (len) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); + OnError(3); + return; + } + + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Blocks read %d", countblocks); + + countblocks *= 4; + + cmd_send(CMD_ACK, 1, countblocks, BigBuf_max_traceLen(), 0, 0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + BigBuf_free(); + set_tracing(false); +} + +//----------------------------------------------------------------------------- +// Select, Authenticate, Write a MIFARE tag. +// read block +//----------------------------------------------------------------------------- +void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) +{ + // params + uint8_t blockNo = arg0; + uint8_t keyType = arg1; + uint64_t ui64Key = 0; + byte_t blockdata[16] = {0x00}; + + ui64Key = bytes_to_num(datain, 6); + memcpy(blockdata, datain + 10, 16); + + // variables + byte_t isOK = 0; + uint8_t uid[10] = {0x00}; + uint32_t cuid = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + clear_trace(); + set_tracing(true); + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + + while (true) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + break; + }; + + if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); + break; + }; + + if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + break; + }; + + if(mifare_classic_halt(pcs, cuid)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + break; + }; + + isOK = 1; + break; + } + + crypto1_destroy(pcs); + + if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); + + cmd_send(CMD_ACK,isOK,0,0,0,0); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); +} + +/* // Command not needed but left for future testing +void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain) +{ + uint8_t blockNo = arg0; + byte_t blockdata[16] = {0x00}; + + memcpy(blockdata, datain, 16); + + uint8_t uid[10] = {0x00}; + + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); + + clear_trace(); + set_tracing(true); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + if(!iso14443a_select_card(uid, NULL, NULL, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + OnError(0); + return; + }; + + if(mifare_ultra_writeblock_compat(blockNo, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(0); + return; }; + + if(mifare_ultra_halt()) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + OnError(0); + return; + }; + + if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); + + cmd_send(CMD_ACK,1,0,0,0,0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); +} +*/ + +// Arg0 : Block to write to. +// Arg1 : 0 = use no authentication. +// 1 = use 0x1A authentication. +// 2 = use 0x1B authentication. +// datain : 4 first bytes is data to be written. +// : 4/16 next bytes is authentication key. +void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) +{ + uint8_t blockNo = arg0; + bool useKey = (arg1 == 1); //UL_C + bool usePwd = (arg1 == 2); //UL_EV1/NTAG + byte_t blockdata[4] = {0x00}; + + memcpy(blockdata, datain, 4); + + LEDsoff(); + LED_A_ON(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + clear_trace(); + set_tracing(true); + + if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + OnError(0); + return; + }; + + // UL-C authentication + if ( useKey ) { + uint8_t key[16] = {0x00}; + memcpy(key, datain+4, sizeof(key) ); + + if ( !mifare_ultra_auth(key) ) { + OnError(1); + return; + } + } + + // UL-EV1 / NTAG authentication + if (usePwd) { + uint8_t pwd[4] = {0x00}; + memcpy(pwd, datain+4, 4); + uint8_t pack[4] = {0,0,0,0}; + if (!mifare_ul_ev1_auth(pwd, pack)) { + OnError(1); + return; + } + } + + if (mifare_ultra_writeblock(blockNo, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(0); + return; + }; + + if (mifare_ultra_halt()) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + OnError(0); + return; + }; + + if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); + + cmd_send(CMD_ACK,1,0,0,0,0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); +} + +void MifareUSetPwd(uint8_t arg0, uint8_t *datain){ + + uint8_t pwd[16] = {0x00}; + byte_t blockdata[4] = {0x00}; + + memcpy(pwd, datain, 16); + + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + clear_trace(); + set_tracing(true); + + if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + OnError(0); + return; + }; + + blockdata[0] = pwd[7]; + blockdata[1] = pwd[6]; + blockdata[2] = pwd[5]; + blockdata[3] = pwd[4]; + if (mifare_ultra_writeblock( 44, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(44); + return; + }; + + blockdata[0] = pwd[3]; + blockdata[1] = pwd[2]; + blockdata[2] = pwd[1]; + blockdata[3] = pwd[0]; + if (mifare_ultra_writeblock( 45, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(45); + return; + }; + + blockdata[0] = pwd[15]; + blockdata[1] = pwd[14]; + blockdata[2] = pwd[13]; + blockdata[3] = pwd[12]; + if (mifare_ultra_writeblock( 46, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(46); + return; + }; + + blockdata[0] = pwd[11]; + blockdata[1] = pwd[10]; + blockdata[2] = pwd[9]; + blockdata[3] = pwd[8]; + if (mifare_ultra_writeblock( 47, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(47); + return; + }; + + if (mifare_ultra_halt()) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + OnError(0); + return; + }; + + cmd_send(CMD_ACK,1,0,0,0,0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); +} + +// Return 1 if the nonce is invalid else return 0 +int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) { + return ((oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \ + (oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \ + (oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0; +} + +void MifareAcquireNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain) { + + uint8_t uid[10] = {0x00}; + uint8_t answer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t par[1] = {0x00}; + uint8_t buf[USB_CMD_DATA_SIZE] = {0x00}; + uint32_t cuid = 0; + int16_t isOK = 0; + uint16_t num_nonces = 0; + uint8_t cascade_levels = 0; + uint8_t blockNo = arg0 & 0xff; + uint8_t keyType = (arg0 >> 8) & 0xff; + bool initialize = flags & 0x0001; + bool field_off = flags & 0x0004; + bool have_uid = false; + + LED_A_ON(); + LED_C_OFF(); + + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); + + if (initialize) + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + LED_C_ON(); + + for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE-4; i += 4 ) { + + // Test if the action was cancelled + if (BUTTON_PRESS()) { + isOK = 2; + field_off = true; + break; + } + + if (!have_uid) { // need a full select cycle to get the uid first + iso14a_card_select_t card_info; + if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); + continue; + } + switch (card_info.uidlen) { + case 4 : cascade_levels = 1; break; + case 7 : cascade_levels = 2; break; + case 10: cascade_levels = 3; break; + default: break; + } + have_uid = true; + } else { // no need for anticollision. We can directly select the card + if (!iso14443a_fast_select_card(uid, cascade_levels)) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); + continue; + } + } + + // Transmit MIFARE_CLASSIC_AUTH + uint8_t dcmd[4] = {0x60 + (keyType & 0x01), blockNo, 0x00, 0x00}; + AddCrc14A(dcmd, 2); + ReaderTransmit(dcmd, sizeof(dcmd), NULL); + int len = ReaderReceive(answer, par); + + // wait for the card to become ready again + CHK_TIMEOUT(); + + if (len != 4) { + if (MF_DBGLEVEL >= 2) Dbprintf("AcquireNonces: Auth1 error"); + continue; + } + + num_nonces++; + + // Save the tag nonce (nt) + buf[i] = answer[0]; + buf[i+1] = answer[1]; + buf[i+2] = answer[2]; + buf[i+3] = answer[3]; + } + + LED_C_OFF(); + LED_B_ON(); + cmd_send(CMD_ACK, isOK, cuid, num_nonces-1, buf, sizeof(buf)); + LED_B_OFF(); + + if (MF_DBGLEVEL >= 3) DbpString("AcquireNonces finished"); + + if (field_off) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); + } +} + +//----------------------------------------------------------------------------- +// acquire encrypted nonces in order to perform the attack described in +// Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened +// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on +// Computer and Communications Security, 2015 +//----------------------------------------------------------------------------- +void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain) { + + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + + uint8_t uid[10] = {0x00}; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t par_enc[1] = {0x00}; + uint8_t buf[USB_CMD_DATA_SIZE] = {0x00}; + + uint64_t ui64Key = bytes_to_num(datain, 6); + uint32_t cuid = 0; + int16_t isOK = 0; + uint16_t num_nonces = 0; + uint8_t nt_par_enc = 0; + uint8_t cascade_levels = 0; + uint8_t blockNo = arg0 & 0xff; + uint8_t keyType = (arg0 >> 8) & 0xff; + uint8_t targetBlockNo = arg1 & 0xff; + uint8_t targetKeyType = (arg1 >> 8) & 0xff; + bool initialize = flags & 0x0001; + bool slow = flags & 0x0002; + bool field_off = flags & 0x0004; + bool have_uid = false; + + LED_A_ON(); + LED_C_OFF(); + + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(false); + + if (initialize) + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + LED_C_ON(); + + for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE - 9; ) { + + // Test if the action was cancelled + if(BUTTON_PRESS()) { + isOK = 2; + field_off = true; + break; + } + + if (!have_uid) { // need a full select cycle to get the uid first + iso14a_card_select_t card_info; + if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); + continue; + } + switch (card_info.uidlen) { + case 4 : cascade_levels = 1; break; + case 7 : cascade_levels = 2; break; + case 10: cascade_levels = 3; break; + default: break; + } + have_uid = true; + } else { // no need for anticollision. We can directly select the card + if (!iso14443a_fast_select_card(uid, cascade_levels)) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); + continue; + } + } + + if (slow) + SpinDelayUs(HARDNESTED_PRE_AUTHENTICATION_LEADTIME); + + uint32_t nt1; + if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error"); + continue; + } + + // nested authentication + uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL); + + // wait for the card to become ready again + CHK_TIMEOUT(); + + if (len != 4) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len); + continue; + } + + num_nonces++; + if (num_nonces % 2) { + memcpy(buf+i, receivedAnswer, 4); + nt_par_enc = par_enc[0] & 0xf0; + } else { + nt_par_enc |= par_enc[0] >> 4; + memcpy(buf+i+4, receivedAnswer, 4); + memcpy(buf+i+8, &nt_par_enc, 1); + i += 9; + } + } + + LED_C_OFF(); + crypto1_destroy(pcs); + LED_B_ON(); + cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf)); + LED_B_OFF(); + + if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished"); + + if (field_off) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); + } +} + + +//----------------------------------------------------------------------------- +// MIFARE nested authentication. +// +//----------------------------------------------------------------------------- +void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *datain) +{ + // params + uint8_t blockNo = arg0 & 0xff; + uint8_t keyType = (arg0 >> 8) & 0xff; + uint8_t targetBlockNo = arg1 & 0xff; + uint8_t targetKeyType = (arg1 >> 8) & 0xff; + uint64_t ui64Key = 0; + + ui64Key = bytes_to_num(datain, 6); + + // variables + uint16_t rtr, i, j, len; + uint16_t davg = 0; + static uint16_t dmin, dmax; + uint8_t uid[10] = {0x00}; + uint32_t cuid = 0, nt1, nt2, nttmp, nttest, ks1; + uint8_t par[1] = {0x00}; + uint32_t target_nt[2] = {0x00}, target_ks[2] = {0x00}; + + uint8_t par_array[4] = {0x00}; + uint16_t ncount = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + + uint32_t auth1_time, auth2_time; + static uint16_t delta_time = 0; + + LED_A_ON(); + LED_C_OFF(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + // free eventually allocated BigBuf memory + BigBuf_free(); BigBuf_Clear_ext(false); + + if (calibrate) clear_trace(); + set_tracing(true); + + // statistics on nonce distance + int16_t isOK = 0; + #define NESTED_MAX_TRIES 12 + uint16_t unsuccessfull_tries = 0; + if (calibrate) { // for first call only. Otherwise reuse previous calibration + LED_B_ON(); + WDT_HIT(); + + davg = dmax = 0; + dmin = 2000; + delta_time = 0; + + for (rtr = 0; rtr < 17; rtr++) { + + // Test if the action was cancelled + if(BUTTON_PRESS()) { + isOK = -2; + break; + } + + // prepare next select. No need to power down the card. + if(mifare_classic_halt(pcs, cuid)) { + if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Halt error"); + rtr--; + continue; + } + + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Can't select card"); + rtr--; + continue; + }; + + auth1_time = 0; + if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) { + if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth1 error"); + rtr--; + continue; + }; + auth2_time = (delta_time) ? auth1_time + delta_time : 0; + + if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2, &auth2_time)) { + if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth2 error"); + rtr--; + continue; + }; + + nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160 + for (i = 101; i < 1200; i++) { + nttmp = prng_successor(nttmp, 1); + if (nttmp == nt2) break; + } + + if (i != 1200) { + if (rtr != 0) { + davg += i; + dmin = MIN(dmin, i); + dmax = MAX(dmax, i); + } + else { + delta_time = auth2_time - auth1_time + 32; // allow some slack for proper timing + } + if (MF_DBGLEVEL >= 3) Dbprintf("Nested: calibrating... ntdist=%d", i); + } else { + unsuccessfull_tries++; + if (unsuccessfull_tries > NESTED_MAX_TRIES) { // card isn't vulnerable to nested attack (random numbers are not predictable) + isOK = -3; + } + } + } + + davg = (davg + (rtr - 1)/2) / (rtr - 1); + + if (MF_DBGLEVEL >= 3) Dbprintf("rtr=%d isOK=%d min=%d max=%d avg=%d, delta_time=%d", rtr, isOK, dmin, dmax, davg, delta_time); + + dmin = davg - 2; + dmax = davg + 2; + + LED_B_OFF(); + } +// ------------------------------------------------------------------------------------------------- + + LED_C_ON(); + + // get crypted nonces for target sector + for(i=0; i < 2 && !isOK; i++) { // look for exactly two different nonces + + target_nt[i] = 0; + while(target_nt[i] == 0) { // continue until we have an unambiguous nonce + + // prepare next select. No need to power down the card. + if(mifare_classic_halt(pcs, cuid)) { + if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Halt error"); + continue; + } + + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Can't select card"); + continue; + }; + + auth1_time = 0; + if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) { + if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth1 error"); + continue; + }; + + // nested authentication + auth2_time = auth1_time + delta_time; + + len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time); + if (len != 4) { + if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth2 error len=%d", len); + continue; + }; + + nt2 = bytes_to_num(receivedAnswer, 4); + if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: Testing nt1=%08x nt2enc=%08x nt2par=%02x", i+1, nt1, nt2, par[0]); + + // Parity validity check + for (j = 0; j < 4; j++) { + par_array[j] = (oddparity8(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01)); + } + + ncount = 0; + nttest = prng_successor(nt1, dmin - 1); + for (j = dmin; j < dmax + 1; j++) { + nttest = prng_successor(nttest, 1); + ks1 = nt2 ^ nttest; + + if (valid_nonce(nttest, nt2, ks1, par_array)){ + if (ncount > 0) { // we are only interested in disambiguous nonces, try again + if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (ambigous), ntdist=%d", i+1, j); + target_nt[i] = 0; + break; + } + target_nt[i] = nttest; + target_ks[i] = ks1; + ncount++; + if (i == 1 && target_nt[1] == target_nt[0]) { // we need two different nonces + target_nt[i] = 0; + if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#2: dismissed (= nonce#1), ntdist=%d", j); + break; + } + if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: valid, ntdist=%d", i+1, j); + } + } + if (target_nt[i] == 0 && j == dmax+1 && MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (all invalid)", i+1); + } + } + + LED_C_OFF(); + + crypto1_destroy(pcs); + + uint8_t buf[4 + 4 * 4] = {0}; + memcpy(buf, &cuid, 4); + memcpy(buf+4, &target_nt[0], 4); + memcpy(buf+8, &target_ks[0], 4); + memcpy(buf+12, &target_nt[1], 4); + memcpy(buf+16, &target_ks[1], 4); + + LED_B_ON(); + cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf)); + LED_B_OFF(); + + if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED"); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); +} + +//----------------------------------------------------------------------------- +// MIFARE check keys. key count up to 85. +// +//----------------------------------------------------------------------------- +typedef struct sector_t { + uint8_t keyA[6]; + uint8_t keyB[6]; +} sector_t; + +typedef struct chk_t { + uint64_t key; + uint32_t cuid; + uint8_t cl; + uint8_t block; + uint8_t keyType; + uint8_t *uid; + struct Crypto1State *pcs; +} chk_t; + +// checks one key. +// fast select, tries 5 times to select +// +// return: +// 2 = failed to select. +// 1 = wrong key +// 0 = correct key +uint8_t chkKey( struct chk_t *c ) { + uint8_t i = 0, res = 2; + while( i < 5 ) { + // this part is from Piwi's faster nonce collecting part in Hardnested. + // assume: fast select + if (!iso14443a_fast_select_card(c->uid, c->cl)) { + ++i; + continue; + } + res = mifare_classic_authex(c->pcs, c->cuid, c->block, c->keyType, c->key, AUTH_FIRST, NULL, NULL); + + CHK_TIMEOUT(); + + // if successfull auth, send HALT + // if ( !res ) + // mifare_classic_halt_ex(c->pcs); + break; + } + return res; +} + +uint8_t chkKey_readb(struct chk_t *c, uint8_t *keyb) { + + if (!iso14443a_fast_select_card(c->uid, c->cl)) + return 2; + + if ( mifare_classic_authex(c->pcs, c->cuid, c->block, 0, c->key, AUTH_FIRST, NULL, NULL) ) + return 1; + + uint8_t data[16] = {0x00}; + uint8_t res = mifare_classic_readblock(c->pcs, c->cuid, c->block, data); + + // successful read + if ( !res ) { + // data was something else than zeros. + if ( memcmp(data+10, "\x00\x00\x00\x00\x00\x00", 6) != 0) { + memcpy(keyb, data+10, 6); + res = 0; + } else { + res = 3; + } + mifare_classic_halt_ex(c->pcs); + } + return res; +} + +void chkKey_scanA(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { + for (uint8_t s = 0; s < *sectorcnt; s++) { + + // skip already found A keys + if ( found[(s*2)] ) + continue; + + c->block = FirstBlockOfSector( s ); + if ( chkKey( c ) == 0 ) { + num_to_bytes(c->key, 6, k_sector[s].keyA); + found[(s*2)] = 1; + ++*foundkeys; + + if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan A found (%d)", c->block); + } + } +} + +void chkKey_scanB(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { + for (uint8_t s = 0; s < *sectorcnt; s++) { + + // skip already found B keys + if ( found[(s*2)+1] ) + continue; + + c->block = FirstBlockOfSector( s ); + if ( chkKey( c ) == 0 ) { + num_to_bytes(c->key, 6, k_sector[s].keyB); + found[(s*2)+1] = 1; + ++*foundkeys; + + if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan B found (%d)", c->block); + } + } +} + +// loop all A keys, +// when A is found but not B, try to read B. +void chkKey_loopBonly(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { + + // read Block B, if A is found. + for (uint8_t s = 0; s < *sectorcnt; ++s) { + + if ( found[(s*2)] && found[(s*2)+1] ) + continue; + + c->block = (FirstBlockOfSector( s ) + NumBlocksPerSector( s ) - 1); + + // A but not B + if ( found[(s*2)] && !found[(s*2)+1] ){ + c->key = bytes_to_num(k_sector[s].keyA, 6); + uint8_t status = chkKey_readb(c, k_sector[s].keyB); + if ( status == 0 ){ + found[(s*2)+1] = 1; + ++*foundkeys; + + if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Reading B found (%d)", c->block); + + // try quick find all B? + // assume: keys comes in groups. Find one B, test against all B. + c->key = bytes_to_num( k_sector[s].keyB, 6); + c->keyType = 1; + chkKey_scanB(c, k_sector, found, sectorcnt, foundkeys); + } + } + } +} + + + +// get Chunks of keys, to test authentication against card. +// arg0 = antal sectorer +// arg0 = first time +// arg1 = clear trace +// arg2 = antal nycklar i keychunk +// datain = keys as array +void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { + + // first call or + uint8_t sectorcnt = arg0 & 0xFF; // 16; + uint8_t firstchunk = (arg0 >> 8) & 0xF; + uint8_t lastchunk = (arg0 >> 12) & 0xF; + uint8_t strategy = arg1 & 0xFF; + uint8_t use_flashmem = (arg1 >> 8) & 0xFF; + uint16_t keyCount = arg2 & 0xFF; + uint8_t status = 0; + + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + struct chk_t chk_data; + + uint8_t allkeys = sectorcnt << 1; + + static uint32_t cuid = 0; + static uint8_t cascade_levels = 0; + static uint8_t foundkeys = 0; + static sector_t k_sector[80]; + static uint8_t found[80]; + static uint8_t *uid; + +#ifdef WITH_FLASH + if ( use_flashmem ) { + BigBuf_free(); + uint16_t isok = 0; + uint8_t size[2] = {0x00, 0x00}; + isok = Flash_ReadData(DEFAULT_MF_KEYS_OFFSET, size, 2); + if ( isok != 2 ) + goto OUT; + + keyCount = size[1] << 8 | size[0]; + + if ( keyCount == 0 && keyCount == 0xFFFF) + goto OUT; + + datain = BigBuf_malloc( keyCount * 6); + if (datain == NULL ) + goto OUT; + + isok = Flash_ReadData(DEFAULT_MF_KEYS_OFFSET+2, datain, keyCount * 6); + if ( isok != keyCount * 6 ) + goto OUT; + + } +#endif + + if (uid == NULL || firstchunk) { + uid = BigBuf_malloc(10); + if (uid == NULL ) + goto OUT; + } + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + LEDsoff(); + LED_A_ON(); + + if ( firstchunk ) { + clear_trace(); + set_tracing(false); + + memset(k_sector, 0x00, 480+10); + memset(found, 0x00, sizeof(found)); + foundkeys = 0; + + iso14a_card_select_t card_info; + if ( !iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys_fast: Can't select card (ALL)"); + goto OUT; + } + + switch (card_info.uidlen) { + case 4 : cascade_levels = 1; break; + case 7 : cascade_levels = 2; break; + case 10: cascade_levels = 3; break; + default: break; + } + + CHK_TIMEOUT(); + } + + // set check struct. + chk_data.uid = uid; + chk_data.cuid = cuid; + chk_data.cl = cascade_levels; + chk_data.pcs = pcs; + chk_data.block = 0; + + // keychunk loop - depth first one sector. + if ( strategy == 1 || use_flashmem) { + + uint8_t newfound = foundkeys; + + uint16_t lastpos = 0; + uint16_t s_point = 0; + // Sector main loop + // keep track of how many sectors on card. + for (uint8_t s = 0; s < sectorcnt; ++s) { + + if ( found[(s*2)] && found[(s*2)+1] ) + continue; + + for (uint16_t i = s_point; i < keyCount; ++i) { + + //if ( i % 100 == 0) Dbprintf("ChkKeys_fast: sector %d | checking %d | %d found | s_point %d", s, i, foundkeys, s_point); + + // Allow button press / usb cmd to interrupt device + if (BUTTON_PRESS() && !usb_poll_validate_length()) { + goto OUT; + } + + // found all keys? + if ( foundkeys == allkeys ) + goto OUT; + + WDT_HIT(); + + // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector + chk_data.block = FirstBlockOfSector( s ); + + // new key + chk_data.key = bytes_to_num(datain + i * 6, 6); + + // skip already found A keys + if( !found[(s*2)] ) { + chk_data.keyType = 0; + status = chkKey( &chk_data); + if ( status == 0 ) { + memcpy(k_sector[s].keyA, datain + i * 6, 6); + found[(s*2)] = 1; + ++foundkeys; + + chkKey_scanA(&chk_data, k_sector, found, §orcnt, &foundkeys); + + // read Block B, if A is found. + chkKey_loopBonly( &chk_data, k_sector, found, §orcnt, &foundkeys); + + chk_data.keyType = 1; + chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); + + chk_data.keyType = 0; + chk_data.block = FirstBlockOfSector( s ); + + if ( use_flashmem ) { + if ( lastpos != i && lastpos != 0) { + if ( i - lastpos < 0xF) { + s_point = i & 0xFFF0; + } + } else { + lastpos = i; + } + } + } + } + + // skip already found B keys + if( !found[(s*2)+1] ) { + chk_data.keyType = 1; + status = chkKey( &chk_data); + if ( status == 0 ) { + memcpy(k_sector[s].keyB, datain + i * 6, 6); + found[(s*2)+1] = 1; + ++foundkeys; + + chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); + + if ( use_flashmem ) { + if ( lastpos != i && lastpos != 0) { + + if ( i - lastpos < 0xF) + s_point = i & 0xFFF0; + } else { + lastpos = i; + } + } + } + } + + if ( found[(s*2)] && found[(s*2)+1] ) + break; + + } // end keys test loop - depth first + + // assume1. if no keys found in first sector, get next keychunk from client + if ( !use_flashmem && (newfound-foundkeys == 0) ) + goto OUT; + + } // end loop - sector + } // end strategy 1 + + if ( foundkeys == allkeys ) + goto OUT; + + if ( strategy == 2 || use_flashmem ) { + + // Keychunk loop + for (uint16_t i = 0; i < keyCount; i++) { + + // Allow button press / usb cmd to interrupt device + if (BUTTON_PRESS() && !usb_poll_validate_length()) break; + + // found all keys? + if ( foundkeys == allkeys ) + goto OUT; + + WDT_HIT(); + + // new key + chk_data.key = bytes_to_num(datain + i * 6, 6); + + // Sector main loop + // keep track of how many sectors on card. + for (uint8_t s = 0; s < sectorcnt; ++s) { + + if ( found[(s*2)] && found[(s*2)+1] ) continue; + + // found all keys? + if ( foundkeys == allkeys ) + goto OUT; + + // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector + chk_data.block = FirstBlockOfSector( s ); + + // skip already found A keys + if( !found[(s*2)] ) { + chk_data.keyType = 0; + status = chkKey( &chk_data); + if ( status == 0 ) { + memcpy(k_sector[s].keyA, datain + i * 6, 6); + found[(s*2)] = 1; + ++foundkeys; + + chkKey_scanA( &chk_data, k_sector, found, §orcnt, &foundkeys); + + // read Block B, if A is found. + chkKey_loopBonly( &chk_data, k_sector, found, §orcnt, &foundkeys); + + chk_data.block = FirstBlockOfSector( s ); + } + } + + // skip already found B keys + if( !found[(s*2)+1] ) { + chk_data.keyType = 1; + status = chkKey( &chk_data); + if ( status == 0 ) { + memcpy(k_sector[s].keyB, datain + i * 6, 6); + found[(s*2)+1] = 1; + ++foundkeys; + + chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); + } + } + } // end loop sectors + } // end loop keys + } // end loop strategy 2 +OUT: + LEDsoff(); + + crypto1_destroy(pcs); + + // All keys found, send to client, or last keychunk from client + if (foundkeys == allkeys || lastchunk ) { + + uint64_t foo = 0; + for (uint8_t m = 0; m < 64; m++) { + foo |= ((uint64_t)(found[m] & 1) << m); + } + + uint16_t bar = 0; + uint8_t j = 0; + for (uint8_t m=64; m < sizeof(found); m++) { + bar |= ((uint16_t)(found[m] & 1) << j++); + } + + uint8_t *tmp = BigBuf_malloc(480+10); + memcpy(tmp, k_sector, sectorcnt * sizeof(sector_t) ); + num_to_bytes(foo, 8, tmp+480); + tmp[488] = bar & 0xFF; + tmp[489] = bar >> 8 & 0xFF; + + cmd_send(CMD_ACK, foundkeys, 0, 0, tmp, 480+10); + + set_tracing(false); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + BigBuf_free(); BigBuf_Clear_ext(false); + } else { + // partial/none keys found + cmd_send(CMD_ACK, foundkeys, 0, 0, 0, 0); + } +} + +void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + + uint8_t uid[10] = {0x00}; + + uint64_t key = 0; + uint32_t cuid = 0; + int i, res; + uint8_t blockNo = arg0 & 0xFF; + uint8_t keyType = (arg0 >> 8) & 0xFF; + uint8_t keyCount = arg2; + uint8_t cascade_levels = 0; + uint8_t isOK = 0; + bool have_uid = false; + bool clearTrace = arg1 & 0xFF; + + LEDsoff(); + LED_A_ON(); + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + if (clearTrace) + clear_trace(); + + set_tracing(true); + + for (i = 0; i < keyCount; i++) { + + // Iceman: use piwi's faster nonce collecting part in hardnested. + if (!have_uid) { // need a full select cycle to get the uid first + iso14a_card_select_t card_info; + if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (ALL)"); + --i; // try same key once again + continue; + } + switch (card_info.uidlen) { + case 4 : cascade_levels = 1; break; + case 7 : cascade_levels = 2; break; + case 10: cascade_levels = 3; break; + default: break; + } + have_uid = true; + } else { // no need for anticollision. We can directly select the card + if (!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (UID)"); + --i; // try same key once again + continue; + } + } + + key = bytes_to_num(datain + i * 6, 6); + res = mifare_classic_auth(pcs, cuid, blockNo, keyType, key, AUTH_FIRST); + + CHK_TIMEOUT(); + + if (res) + continue; + + isOK = 1; + break; + } + + LED_B_ON(); + cmd_send(CMD_ACK, isOK, 0, 0, datain + i * 6, 6); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + + set_tracing(false); + crypto1_destroy(pcs); +} + +//----------------------------------------------------------------------------- +// MIFARE commands set debug level +// +//----------------------------------------------------------------------------- +void MifareSetDbgLvl(uint16_t arg0){ + MF_DBGLEVEL = arg0; + Dbprintf("Debug level: %d", MF_DBGLEVEL); +} + +//----------------------------------------------------------------------------- +// Work with emulator memory +// +// Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not +// involved in dealing with emulator memory. But if it is called later, it might +// destroy the Emulator Memory. +//----------------------------------------------------------------------------- + +void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + emlClearMem(); +} + +void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + if (arg2==0) arg2 = 16; // backwards compat... default bytewidth + 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){ + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + byte_t buf[USB_CMD_DATA_SIZE] = {0x00}; + emlGetMem(buf, arg0, arg1); // data, block num, blocks count (max 4) + + LED_B_ON(); + cmd_send(CMD_ACK,arg0,arg1,0,buf,USB_CMD_DATA_SIZE); + LED_B_OFF(); +} + +//----------------------------------------------------------------------------- +// Load a card into the emulator memory +// +//----------------------------------------------------------------------------- +void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ + uint8_t numSectors = arg0; + uint8_t keyType = arg1; + uint64_t ui64Key = 0; + uint32_t cuid = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + + // variables + byte_t dataoutbuf[16] = {0x00}; + byte_t dataoutbuf2[16] = {0x00}; + uint8_t uid[10] = {0x00}; + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + clear_trace(); + set_tracing(true); + + bool isOK = true; + + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + isOK = false; + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + } + + for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) { + ui64Key = emlGetKey(sectorNo, keyType); + if (sectorNo == 0){ + if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { + isOK = false; + if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo); + break; + } + } else { + if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) { + isOK = false; + if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth nested error", sectorNo); + break; + } + } + + for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { + if(isOK && mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) { + isOK = false; + if (MF_DBGLEVEL >= 1) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo); + break; + } + if (isOK) { + if (blockNo < NumBlocksPerSector(sectorNo) - 1) { + emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1); + } else { // sector trailer, keep the keys, set only the AC + emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); + memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4); + emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); + } + } + } + + } + + if(mifare_classic_halt(pcs, cuid)) + if (MF_DBGLEVEL >= 1) + Dbprintf("Halt error"); + + // ----------------------------- crypto1 destroy + crypto1_destroy(pcs); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + + if (MF_DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED"); + + set_tracing(false); +} + + +//----------------------------------------------------------------------------- +// Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn) +// +// PARAMS - workFlags +// bit 0 - need get UID +// bit 1 - need wupC +// bit 2 - need HALT after sequence +// bit 3 - need turn on FPGA before sequence +// bit 4 - need turn off FPGA +// bit 5 - need to set datain instead of issuing USB reply (called via ARM for StandAloneMode14a) +// bit 6 - wipe tag. +//----------------------------------------------------------------------------- +// magic uid card generation 1 commands +uint8_t wupC1[] = { MIFARE_MAGICWUPC1 }; +uint8_t wupC2[] = { MIFARE_MAGICWUPC2 }; +uint8_t wipeC[] = { MIFARE_MAGICWIPEC }; + +void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){ + + // params + uint8_t workFlags = arg0; + uint8_t blockNo = arg1; + + // detect 1a/1b + bool is1b = false; + + // variables + bool isOK = false; //assume we will get an error + uint8_t errormsg = 0x00; + uint8_t uid[10] = {0x00}; + uint8_t data[18] = {0x00}; + uint32_t cuid = 0; + + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + + if (workFlags & MAGIC_INIT) { + LED_A_ON(); + LED_B_OFF(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + clear_trace(); + set_tracing(true); + } + + //loop doesn't loop just breaks out if error + while (true) { + // read UID and return to client with write + if (workFlags & MAGIC_UID) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); + errormsg = MAGIC_UID; + } + mifare_classic_halt_ex(NULL); + break; + } + + // wipe tag, fill it with zeros + if (workFlags & MAGIC_WIPE){ + ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC1 error"); + errormsg = MAGIC_WIPE; + break; + } + + ReaderTransmit(wipeC, sizeof(wipeC), NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wipeC error"); + errormsg = MAGIC_WIPE; + break; + } + + mifare_classic_halt_ex(NULL); + } + + // write block + if (workFlags & MAGIC_WUPC) { + ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC1 error"); + errormsg = MAGIC_WUPC; + break; + } + + if ( !is1b ) { + ReaderTransmit(wupC2, sizeof(wupC2), NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Assuming Magic Gen 1B tag. [wupC2 failed]"); + is1b = true; + continue; + } + } + } + + if ((mifare_sendcmd_short(NULL, 0, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("write block send command error"); + errormsg = 4; + break; + } + + memcpy(data, datain, 16); + AddCrc14A(data, 16); + + ReaderTransmit(data, sizeof(data), NULL); + if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("write block send data error"); + errormsg = 0; + break; + } + + if (workFlags & MAGIC_HALT) + mifare_classic_halt_ex(NULL); + + isOK = true; + break; + + } // end while + + if (isOK ) + cmd_send(CMD_ACK,1,0,0,uid,sizeof(uid)); + else + OnErrorMagic(errormsg); + + if (workFlags & MAGIC_OFF) + OnSuccessMagic(); +} + +void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){ + + uint8_t workFlags = arg0; + uint8_t blockNo = arg1; + uint8_t errormsg = 0x00; + bool isOK = false; //assume we will get an error + + // detect 1a/1b + bool is1b = false; + + // variables + uint8_t data[MAX_MIFARE_FRAME_SIZE]; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + + memset(data, 0x00, sizeof(data)); + + if (workFlags & MAGIC_INIT) { + LED_A_ON(); + LED_B_OFF(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + clear_trace(); + set_tracing(true); + } + + //loop doesn't loop just breaks out if error or done + while (true) { + if (workFlags & MAGIC_WUPC) { + ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC1 error"); + errormsg = MAGIC_WUPC; + break; + } + + if ( !is1b ) { + ReaderTransmit(wupC2, sizeof(wupC2), NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Assuming Magic Gen 1B tag. [wupC2 failed]"); + is1b = true; + continue; + } + } + } + + // read block + if ((mifare_sendcmd_short(NULL, 0, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("read block send command error"); + errormsg = 0; + break; + } + + memcpy(data, receivedAnswer, sizeof(data)); + + // send HALT + if (workFlags & MAGIC_HALT) + mifare_classic_halt_ex(NULL); + + isOK = true; + break; + } + // if MAGIC_DATAIN, the data stays on device side. + if (workFlags & MAGIC_DATAIN) { + if (isOK) + memcpy(datain, data, sizeof(data)); + } else { + if (isOK) + cmd_send(CMD_ACK,1,0,0,data,sizeof(data)); + else + OnErrorMagic(errormsg); + } + + if (workFlags & MAGIC_OFF) + OnSuccessMagic(); +} + +void MifareCIdent(){ + #define GEN_1A 1 + #define GEN_1B 2 + #define GEN_2 4 + // variables + uint8_t isGen = 0; + uint8_t rec[1] = {0x00}; + uint8_t recpar[1] = {0x00}; + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + // Generation 1 test + ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); + if(!ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) { + goto TEST2; + }; + isGen = GEN_1B; + + ReaderTransmit(wupC2, sizeof(wupC2), NULL); + if(!ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) { + goto OUT; + }; + isGen = GEN_1A; + goto OUT; + +TEST2:; +/* + // Generation 2 test + + // halt previous. + mifare_classic_halt(NULL, 0); + + //select + if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { + goto OUT; + }; + + // MIFARE_CLASSIC_WRITEBLOCK 0xA0 + // ACK 0x0a + uint16_t len = mifare_sendcmd_short(null, 1, 0xA0, 0, rec, recpar, NULL); + if ((len != 1) || (rec[0] != 0x0A)) { + isGen = GEN_2; + }; + */ +OUT:; + // removed the if, since some magic tags misbehavies and send an answer to it. + mifare_classic_halt_ex(NULL); + cmd_send(CMD_ACK, isGen, 0, 0, 0, 0); + // turns off + OnSuccessMagic(); +} + +void OnSuccessMagic(){ + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); +} +void OnErrorMagic(uint8_t reason){ + // ACK, ISOK, reason,0,0,0 + cmd_send(CMD_ACK,0,reason,0,0,0); + OnSuccessMagic(); +} + +void MifareSetMod(uint8_t mod, uint8_t *key) { + uint64_t ui64Key = bytes_to_num(key, 6); + + // variables + uint8_t isOK = 0; + uint8_t uid[10] = {0}; + uint32_t cuid = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs = &mpcs; + int respLen = 0; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0}; + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + + clear_trace(); + set_tracing(true); + + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + + while (true) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + break; + } + + if(mifare_classic_auth(pcs, cuid, 0, 0, ui64Key, AUTH_FIRST)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); + break; + } + + if (((respLen = mifare_sendcmd_short(pcs, 1, 0x43, mod, receivedAnswer, receivedAnswerPar, NULL)) != 1) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= 1) Dbprintf("SetMod error; response[0]: %hhX, len: %d", receivedAnswer[0], respLen); + break; + } + + if(mifare_classic_halt(pcs, cuid)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + break; + } + + isOK = 1; + break; + } + + crypto1_destroy(pcs); + + LED_B_ON(); + cmd_send(CMD_ACK, isOK, 0, 0, 0, 0); + LED_B_OFF(); + + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); +} + +// +// DESFIRE +// +void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){ + byte_t dataout[12] = {0x00}; + uint8_t uid[10] = {0x00}; + uint32_t cuid = 0; + + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + clear_trace(); + set_tracing(true); + + int len = iso14443a_select_card(uid, NULL, &cuid, true, 0, false); + if(!len) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); + OnError(1); + return; + }; + + if(mifare_desfire_des_auth1(cuid, dataout)){ + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part1: Fail."); + OnError(4); + return; + } + + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED"); + cmd_send(CMD_ACK, 1, cuid, 0, dataout, sizeof(dataout)); +} + +void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){ + uint32_t cuid = arg0; + uint8_t key[16] = {0x00}; + byte_t dataout[12] = {0x00}; + byte_t isOK = 0; + + memcpy(key, datain, 16); + + isOK = mifare_desfire_des_auth2(cuid, key, dataout); + + if( isOK) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed"); + OnError(4); + return; + } + + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED"); + + cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout)); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); } \ No newline at end of file diff --git a/armsrc/mifarecmd.h b/armsrc/mifarecmd.h index d73b124cb..595d46395 100644 --- a/armsrc/mifarecmd.h +++ b/armsrc/mifarecmd.h @@ -1,28 +1,28 @@ -//----------------------------------------------------------------------------- -// Merlok - June 2011 -// Gerhard de Koning Gans - May 2008 -// Hagen Fritsch - June 2010 -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Routines to support ISO 14443 type A. -//----------------------------------------------------------------------------- - -#ifndef __MIFARECMD_H -#define __MIFARECMD_H - -#include "proxmark3.h" -#include "apps.h" -#include "util.h" -#include "string.h" -#include "iso14443crc.h" -#include "iso14443a.h" -#include "crapto1/crapto1.h" -#include "mifareutil.h" -#include "common.h" -#include "crc.h" -#include "protocols.h" -#include "parity.h" +//----------------------------------------------------------------------------- +// Merlok - June 2011 +// Gerhard de Koning Gans - May 2008 +// Hagen Fritsch - June 2010 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Routines to support ISO 14443 type A. +//----------------------------------------------------------------------------- + +#ifndef __MIFARECMD_H +#define __MIFARECMD_H + +#include "proxmark3.h" +#include "apps.h" +#include "util.h" +#include "string.h" +#include "iso14443crc.h" +#include "iso14443a.h" +#include "crapto1/crapto1.h" +#include "mifareutil.h" +#include "common.h" +#include "crc.h" +#include "protocols.h" +#include "parity.h" #endif \ No newline at end of file diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff.c index 3e6255354..e832c76cf 100644 --- a/armsrc/mifaresniff.c +++ b/armsrc/mifaresniff.c @@ -1,324 +1,324 @@ -//----------------------------------------------------------------------------- -// Merlok - 2012 -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Routines to support mifare classic sniffer. -//----------------------------------------------------------------------------- - -#include "mifaresniff.h" - -//static int sniffState = SNF_INIT; -static uint8_t sniffUIDType = 0; -static uint8_t sniffUID[10] = {0,0,0,0,0,0,0,0,0,0}; -static uint8_t sniffATQA[2] = {0,0}; -static uint8_t sniffSAK = 0; -static uint8_t sniffBuf[17]; -static uint32_t timerData = 0; - -//----------------------------------------------------------------------------- -// MIFARE sniffer. -// -// if no activity for 2sec, it sends the collected data to the client. -//----------------------------------------------------------------------------- -// "hf mf sniff" -void RAMFUNC SniffMifare(uint8_t param) { - // param: - // bit 0 - trigger from first card answer - // bit 1 - trigger from first reader 7-bit request - - // C(red) A(yellow) B(green) - LEDsoff(); - iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); - - // Allocate memory from BigBuf for some buffers - // free all previous allocations first - BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); - set_tracing(true); - - // The command (reader -> tag) that we're receiving. - uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedCmdPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - - // The response (tag -> reader) that we're receiving. - uint8_t receivedResp[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedRespPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - - // allocate the DMA buffer, used to stream samples from the FPGA - uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); - uint8_t *data = dmaBuf; - uint8_t previous_data = 0; - int maxDataLen = 0; - int dataLen = 0; - bool ReaderIsActive = false; - bool TagIsActive = false; - - // We won't start recording the frames that we acquire until we trigger; - // a good trigger condition to get started is probably when we see a - // response from the tag. - // triggered == false -- to wait first for card - //bool triggered = !(param & 0x03); - - - // Set up the demodulator for tag -> reader responses. - DemodInit(receivedResp, receivedRespPar); - - // Set up the demodulator for the reader -> tag commands - UartInit(receivedCmd, receivedCmdPar); - - // Setup and start DMA. - // set transfer address and number of bytes. Start transfer. - if ( !FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE) ){ - if (MF_DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting"); - return; - } - - tUart* uart = GetUart(); - tDemod* demod = GetDemod(); - - MfSniffInit(); - - uint32_t sniffCounter = 0; - // loop and listen - while (!BUTTON_PRESS()) { - WDT_HIT(); - LED_A_ON(); -/* - if ((sniffCounter & 0x0000FFFF) == 0) { // from time to time - // check if a transaction is completed (timeout after 2000ms). - // if yes, stop the DMA transfer and send what we have so far to the client - if (BigBuf_get_traceLen()) { - MfSniffSend(); - // Reset everything - we missed some sniffed data anyway while the DMA was stopped - sniffCounter = 0; - dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); - data = dmaBuf; - maxDataLen = 0; - ReaderIsActive = false; - TagIsActive = false; - FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); // set transfer address and number of bytes. Start transfer. - } - } - */ - - // number of bytes we have processed so far - int register readBufDataP = data - dmaBuf; - // number of bytes already transferred - int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; - if (readBufDataP <= dmaBufDataP) // we are processing the same block of data which is currently being transferred - dataLen = dmaBufDataP - readBufDataP; // number of bytes still to be processed - else - dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; // number of bytes still to be processed - - // test for length of buffer - if (dataLen > maxDataLen) { // we are more behind than ever... - maxDataLen = dataLen; - if (dataLen > (9 * DMA_BUFFER_SIZE / 10)) { - Dbprintf("[!] blew circular buffer! | datalen %u", dataLen); - break; - } - } - if (dataLen < 1) continue; - - // primary buffer was stopped ( <-- we lost data! - if (!AT91C_BASE_PDC_SSC->PDC_RCR) { - AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t)dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE; - Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary - } - // secondary buffer sets as primary, secondary buffer was stopped - if (!AT91C_BASE_PDC_SSC->PDC_RNCR) { - AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; - } - - LED_A_OFF(); - - // Need two samples to feed Miller and Manchester-Decoder - if (sniffCounter & 0x01) { - - // no need to try decoding tag data if the reader is sending - if (!TagIsActive) { - uint8_t readerbyte = (previous_data & 0xF0) | (*data >> 4); - if (MillerDecoding(readerbyte, (sniffCounter-1)*4)) { - LogTrace(receivedCmd, uart->len, 0, 0, NULL, true); - DemodReset(); - UartReset(); - } - ReaderIsActive = (uart->state != STATE_UNSYNCD); - } - - // no need to try decoding tag data if the reader is sending - if (!ReaderIsActive) { - uint8_t tagbyte = (previous_data << 4) | (*data & 0x0F); - if (ManchesterDecoding(tagbyte, 0, (sniffCounter-1)*4)) { - LogTrace(receivedResp, demod->len, 0, 0, NULL, false); - DemodReset(); - UartReset(); - } - TagIsActive = (demod->state != DEMOD_UNSYNCD); - } - } - previous_data = *data; - sniffCounter++; - data++; - - if (data == dmaBuf + DMA_BUFFER_SIZE) - data = dmaBuf; - - } // main cycle - - MfSniffEnd(); - switch_off(); -} - -void MfSniffInit(void){ - memset(sniffUID, 0x00, sizeof(sniffUID)); - memset(sniffATQA, 0x00, sizeof(sniffATQA)); - memset(sniffBuf, 0x00, sizeof(sniffBuf)); - sniffSAK = 0; - sniffUIDType = SNF_UID_4; - timerData = 0; -} - -void MfSniffEnd(void){ - LED_B_ON(); - cmd_send(CMD_ACK,0,0,0,0,0); - LED_B_OFF(); -} - -/* -bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader) { - - // reset on 7-Bit commands from reader - if (reader && (len == 1) && (bitCnt == 7)) { - sniffState = SNF_INIT; - } - - - - switch (sniffState) { - case SNF_INIT:{ - // REQA,WUPA or MAGICWUP from reader - if ((len == 1) && (reader) && (bitCnt == 7) ) { - MfSniffInit(); - sniffState = (data[0] == MIFARE_MAGICWUPC1) ? SNF_MAGIC_WUPC2 : SNF_ATQA; - } - break; - } - case SNF_MAGIC_WUPC2: { - if ((len == 1) && (reader) && (data[0] == MIFARE_MAGICWUPC2) ) { - sniffState = SNF_CARD_IDLE; - } - break; - } - case SNF_ATQA:{ - // ATQA from tag - if ((!reader) && (len == 2)) { - sniffATQA[0] = data[0]; - sniffATQA[1] = data[1]; - sniffState = SNF_UID; - } - break; - } - case SNF_UID: { - - if ( !reader ) break; - if ( len != 9 ) break; - if ( !CheckCrc14443(CRC_14443_A, data, 9)) break; - if ( data[1] != 0x70 ) break; - - Dbprintf("[!] UID | %x", data[0]); - - if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT)) { - // UID_4 - select 4 Byte UID from reader - memcpy(sniffUID, data+2, 4); - sniffUIDType = SNF_UID_4; - sniffState = SNF_SAK; - } else if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2)) { - // UID_7 - Select 2nd part of 7 Byte UID - - // get rid of 0x88 - sniffUID[0] = sniffUID[1]; - sniffUID[1] = sniffUID[2]; - sniffUID[2] = sniffUID[3]; - //new uid bytes - memcpy(sniffUID+3, data+2, 4); - sniffUIDType = SNF_UID_7; - sniffState = SNF_SAK; - } else if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3)) { - // UID_10 - Select 3nd part of 10 Byte UID - // 3+3+4 = 10. - // get ride of previous 0x88 - sniffUID[3] = sniffUID[4]; - sniffUID[4] = sniffUID[5]; - sniffUID[5] = sniffUID[6]; - // new uid bytes - memcpy(sniffUID+6, data+2, 4); - sniffUIDType = SNF_UID_10; - sniffState = SNF_SAK; - } - break; - } - case SNF_SAK:{ - // SAK from card? - if ((!reader) && (len == 3) && (CheckCrc14443(CRC_14443_A, data, 3))) { - sniffSAK = data[0]; - // CL2 UID part to be expected - if (( sniffSAK == 0x04) && (sniffUIDType == SNF_UID_4)) { - sniffState = SNF_UID; - // CL3 UID part to be expected - } else if ((sniffSAK == 0x04) && (sniffUIDType == SNF_UID_7)) { - sniffState = SNF_UID; - } else { - // select completed - sniffState = SNF_CARD_IDLE; - } - } - break; - } - case SNF_CARD_IDLE:{ // trace the card select sequence - sniffBuf[0] = 0xFF; - sniffBuf[1] = 0xFF; - memcpy(sniffBuf + 2, sniffUID, sizeof(sniffUID)); - memcpy(sniffBuf + 12, sniffATQA, sizeof(sniffATQA)); - sniffBuf[14] = sniffSAK; - sniffBuf[15] = 0xFF; - sniffBuf[16] = 0xFF; - LogTrace(sniffBuf, sizeof(sniffBuf), 0, 0, NULL, true); - sniffState = SNF_CARD_CMD; - } // intentionally no break; - case SNF_CARD_CMD:{ - LogTrace(data, len, 0, 0, NULL, reader); - timerData = GetTickCount(); - break; - } - default: - sniffState = SNF_INIT; - break; - } - return false; -} -*/ - -void RAMFUNC MfSniffSend() { - uint16_t tracelen = BigBuf_get_traceLen(); - uint16_t chunksize = 0; - int packlen = tracelen; // total number of bytes to send - uint8_t *data = BigBuf_get_addr(); - - while (packlen > 0) { - LED_B_ON(); - chunksize = MIN(USB_CMD_DATA_SIZE, packlen); // chunk size 512 - cmd_send(CMD_ACK, 1, tracelen, chunksize, data + tracelen - packlen, chunksize); - packlen -= chunksize; - LED_B_OFF(); - } - - LED_B_ON(); - cmd_send(CMD_ACK, 2, 0, 0, 0, 0); // 2 == data transfer finished. - LED_B_OFF(); +//----------------------------------------------------------------------------- +// Merlok - 2012 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Routines to support mifare classic sniffer. +//----------------------------------------------------------------------------- + +#include "mifaresniff.h" + +//static int sniffState = SNF_INIT; +static uint8_t sniffUIDType = 0; +static uint8_t sniffUID[10] = {0,0,0,0,0,0,0,0,0,0}; +static uint8_t sniffATQA[2] = {0,0}; +static uint8_t sniffSAK = 0; +static uint8_t sniffBuf[17]; +static uint32_t timerData = 0; + +//----------------------------------------------------------------------------- +// MIFARE sniffer. +// +// if no activity for 2sec, it sends the collected data to the client. +//----------------------------------------------------------------------------- +// "hf mf sniff" +void RAMFUNC SniffMifare(uint8_t param) { + // param: + // bit 0 - trigger from first card answer + // bit 1 - trigger from first reader 7-bit request + + // C(red) A(yellow) B(green) + LEDsoff(); + iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); + + // Allocate memory from BigBuf for some buffers + // free all previous allocations first + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); + + // The command (reader -> tag) that we're receiving. + uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedCmdPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + + // The response (tag -> reader) that we're receiving. + uint8_t receivedResp[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedRespPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + + // allocate the DMA buffer, used to stream samples from the FPGA + uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); + uint8_t *data = dmaBuf; + uint8_t previous_data = 0; + int maxDataLen = 0; + int dataLen = 0; + bool ReaderIsActive = false; + bool TagIsActive = false; + + // We won't start recording the frames that we acquire until we trigger; + // a good trigger condition to get started is probably when we see a + // response from the tag. + // triggered == false -- to wait first for card + //bool triggered = !(param & 0x03); + + + // Set up the demodulator for tag -> reader responses. + DemodInit(receivedResp, receivedRespPar); + + // Set up the demodulator for the reader -> tag commands + UartInit(receivedCmd, receivedCmdPar); + + // Setup and start DMA. + // set transfer address and number of bytes. Start transfer. + if ( !FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE) ){ + if (MF_DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting"); + return; + } + + tUart* uart = GetUart(); + tDemod* demod = GetDemod(); + + MfSniffInit(); + + uint32_t sniffCounter = 0; + // loop and listen + while (!BUTTON_PRESS()) { + WDT_HIT(); + LED_A_ON(); +/* + if ((sniffCounter & 0x0000FFFF) == 0) { // from time to time + // check if a transaction is completed (timeout after 2000ms). + // if yes, stop the DMA transfer and send what we have so far to the client + if (BigBuf_get_traceLen()) { + MfSniffSend(); + // Reset everything - we missed some sniffed data anyway while the DMA was stopped + sniffCounter = 0; + dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); + data = dmaBuf; + maxDataLen = 0; + ReaderIsActive = false; + TagIsActive = false; + FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); // set transfer address and number of bytes. Start transfer. + } + } + */ + + // number of bytes we have processed so far + int register readBufDataP = data - dmaBuf; + // number of bytes already transferred + int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; + if (readBufDataP <= dmaBufDataP) // we are processing the same block of data which is currently being transferred + dataLen = dmaBufDataP - readBufDataP; // number of bytes still to be processed + else + dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; // number of bytes still to be processed + + // test for length of buffer + if (dataLen > maxDataLen) { // we are more behind than ever... + maxDataLen = dataLen; + if (dataLen > (9 * DMA_BUFFER_SIZE / 10)) { + Dbprintf("[!] blew circular buffer! | datalen %u", dataLen); + break; + } + } + if (dataLen < 1) continue; + + // primary buffer was stopped ( <-- we lost data! + if (!AT91C_BASE_PDC_SSC->PDC_RCR) { + AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t)dmaBuf; + AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE; + Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary + } + // secondary buffer sets as primary, secondary buffer was stopped + if (!AT91C_BASE_PDC_SSC->PDC_RNCR) { + AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)dmaBuf; + AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; + } + + LED_A_OFF(); + + // Need two samples to feed Miller and Manchester-Decoder + if (sniffCounter & 0x01) { + + // no need to try decoding tag data if the reader is sending + if (!TagIsActive) { + uint8_t readerbyte = (previous_data & 0xF0) | (*data >> 4); + if (MillerDecoding(readerbyte, (sniffCounter-1)*4)) { + LogTrace(receivedCmd, uart->len, 0, 0, NULL, true); + DemodReset(); + UartReset(); + } + ReaderIsActive = (uart->state != STATE_UNSYNCD); + } + + // no need to try decoding tag data if the reader is sending + if (!ReaderIsActive) { + uint8_t tagbyte = (previous_data << 4) | (*data & 0x0F); + if (ManchesterDecoding(tagbyte, 0, (sniffCounter-1)*4)) { + LogTrace(receivedResp, demod->len, 0, 0, NULL, false); + DemodReset(); + UartReset(); + } + TagIsActive = (demod->state != DEMOD_UNSYNCD); + } + } + previous_data = *data; + sniffCounter++; + data++; + + if (data == dmaBuf + DMA_BUFFER_SIZE) + data = dmaBuf; + + } // main cycle + + MfSniffEnd(); + switch_off(); +} + +void MfSniffInit(void){ + memset(sniffUID, 0x00, sizeof(sniffUID)); + memset(sniffATQA, 0x00, sizeof(sniffATQA)); + memset(sniffBuf, 0x00, sizeof(sniffBuf)); + sniffSAK = 0; + sniffUIDType = SNF_UID_4; + timerData = 0; +} + +void MfSniffEnd(void){ + LED_B_ON(); + cmd_send(CMD_ACK,0,0,0,0,0); + LED_B_OFF(); +} + +/* +bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader) { + + // reset on 7-Bit commands from reader + if (reader && (len == 1) && (bitCnt == 7)) { + sniffState = SNF_INIT; + } + + + + switch (sniffState) { + case SNF_INIT:{ + // REQA,WUPA or MAGICWUP from reader + if ((len == 1) && (reader) && (bitCnt == 7) ) { + MfSniffInit(); + sniffState = (data[0] == MIFARE_MAGICWUPC1) ? SNF_MAGIC_WUPC2 : SNF_ATQA; + } + break; + } + case SNF_MAGIC_WUPC2: { + if ((len == 1) && (reader) && (data[0] == MIFARE_MAGICWUPC2) ) { + sniffState = SNF_CARD_IDLE; + } + break; + } + case SNF_ATQA:{ + // ATQA from tag + if ((!reader) && (len == 2)) { + sniffATQA[0] = data[0]; + sniffATQA[1] = data[1]; + sniffState = SNF_UID; + } + break; + } + case SNF_UID: { + + if ( !reader ) break; + if ( len != 9 ) break; + if ( !CheckCrc14443(CRC_14443_A, data, 9)) break; + if ( data[1] != 0x70 ) break; + + Dbprintf("[!] UID | %x", data[0]); + + if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT)) { + // UID_4 - select 4 Byte UID from reader + memcpy(sniffUID, data+2, 4); + sniffUIDType = SNF_UID_4; + sniffState = SNF_SAK; + } else if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2)) { + // UID_7 - Select 2nd part of 7 Byte UID + + // get rid of 0x88 + sniffUID[0] = sniffUID[1]; + sniffUID[1] = sniffUID[2]; + sniffUID[2] = sniffUID[3]; + //new uid bytes + memcpy(sniffUID+3, data+2, 4); + sniffUIDType = SNF_UID_7; + sniffState = SNF_SAK; + } else if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3)) { + // UID_10 - Select 3nd part of 10 Byte UID + // 3+3+4 = 10. + // get ride of previous 0x88 + sniffUID[3] = sniffUID[4]; + sniffUID[4] = sniffUID[5]; + sniffUID[5] = sniffUID[6]; + // new uid bytes + memcpy(sniffUID+6, data+2, 4); + sniffUIDType = SNF_UID_10; + sniffState = SNF_SAK; + } + break; + } + case SNF_SAK:{ + // SAK from card? + if ((!reader) && (len == 3) && (CheckCrc14443(CRC_14443_A, data, 3))) { + sniffSAK = data[0]; + // CL2 UID part to be expected + if (( sniffSAK == 0x04) && (sniffUIDType == SNF_UID_4)) { + sniffState = SNF_UID; + // CL3 UID part to be expected + } else if ((sniffSAK == 0x04) && (sniffUIDType == SNF_UID_7)) { + sniffState = SNF_UID; + } else { + // select completed + sniffState = SNF_CARD_IDLE; + } + } + break; + } + case SNF_CARD_IDLE:{ // trace the card select sequence + sniffBuf[0] = 0xFF; + sniffBuf[1] = 0xFF; + memcpy(sniffBuf + 2, sniffUID, sizeof(sniffUID)); + memcpy(sniffBuf + 12, sniffATQA, sizeof(sniffATQA)); + sniffBuf[14] = sniffSAK; + sniffBuf[15] = 0xFF; + sniffBuf[16] = 0xFF; + LogTrace(sniffBuf, sizeof(sniffBuf), 0, 0, NULL, true); + sniffState = SNF_CARD_CMD; + } // intentionally no break; + case SNF_CARD_CMD:{ + LogTrace(data, len, 0, 0, NULL, reader); + timerData = GetTickCount(); + break; + } + default: + sniffState = SNF_INIT; + break; + } + return false; +} +*/ + +void RAMFUNC MfSniffSend() { + uint16_t tracelen = BigBuf_get_traceLen(); + uint16_t chunksize = 0; + int packlen = tracelen; // total number of bytes to send + uint8_t *data = BigBuf_get_addr(); + + while (packlen > 0) { + LED_B_ON(); + chunksize = MIN(USB_CMD_DATA_SIZE, packlen); // chunk size 512 + cmd_send(CMD_ACK, 1, tracelen, chunksize, data + tracelen - packlen, chunksize); + packlen -= chunksize; + LED_B_OFF(); + } + + LED_B_ON(); + cmd_send(CMD_ACK, 2, 0, 0, 0, 0); // 2 == data transfer finished. + LED_B_OFF(); } \ No newline at end of file diff --git a/armsrc/mifaresniff.h b/armsrc/mifaresniff.h index 537fa2941..efd34fdeb 100644 --- a/armsrc/mifaresniff.h +++ b/armsrc/mifaresniff.h @@ -1,42 +1,42 @@ -//----------------------------------------------------------------------------- -// Merlok - June 2012 -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Routines to support mifare classic sniffer. -//----------------------------------------------------------------------------- - -#ifndef __MIFARESNIFF_H -#define __MIFARESNIFF_H - -#include "proxmark3.h" -#include "apps.h" -#include "util.h" -#include "string.h" -#include "iso14443crc.h" -#include "iso14443a.h" -#include "crapto1/crapto1.h" -#include "mifareutil.h" -#include "common.h" - -#define SNF_INIT 0 -#define SNF_NO_FIELD 1 -#define SNF_ATQA 2 -#define SNF_UID 3 -#define SNF_SAK 4 -#define SNF_CARD_IDLE 5 -#define SNF_CARD_CMD 6 -#define SNF_MAGIC_WUPC2 7 - -#define SNF_UID_4 0 -#define SNF_UID_7 0 -#define SNF_UID_10 0 - -void MfSniffInit(void); -bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader); -void RAMFUNC MfSniffSend(void); -void MfSniffEnd(void); - +//----------------------------------------------------------------------------- +// Merlok - June 2012 +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Routines to support mifare classic sniffer. +//----------------------------------------------------------------------------- + +#ifndef __MIFARESNIFF_H +#define __MIFARESNIFF_H + +#include "proxmark3.h" +#include "apps.h" +#include "util.h" +#include "string.h" +#include "iso14443crc.h" +#include "iso14443a.h" +#include "crapto1/crapto1.h" +#include "mifareutil.h" +#include "common.h" + +#define SNF_INIT 0 +#define SNF_NO_FIELD 1 +#define SNF_ATQA 2 +#define SNF_UID 3 +#define SNF_SAK 4 +#define SNF_CARD_IDLE 5 +#define SNF_CARD_CMD 6 +#define SNF_MAGIC_WUPC2 7 + +#define SNF_UID_4 0 +#define SNF_UID_7 0 +#define SNF_UID_10 0 + +void MfSniffInit(void); +bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader); +void RAMFUNC MfSniffSend(void); +void MfSniffEnd(void); + #endif \ No newline at end of file diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 179b9c51e..df85f6cbd 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -1,689 +1,689 @@ -//----------------------------------------------------------------------------- -// Merlok, May 2011, 2012 -// Many authors, whom made it possible -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Work with mifare cards. -//----------------------------------------------------------------------------- -#include "mifareutil.h" - -int MF_DBGLEVEL = MF_DBG_ERROR; - -// crypto1 helpers -void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out){ - uint8_t bt = 0; - int i; - - if (len != 1) { - for (i = 0; i < len; i++) - data_out[i] = crypto1_byte(pcs, 0x00, 0) ^ data_in[i]; - } else { - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 0)) << 0; - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 1)) << 1; - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 2)) << 2; - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 3)) << 3; - data_out[0] = bt; - } - return; -} - -void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len){ - mf_crypto1_decryptEx(pcs, data, len, data); -} - -void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par) { - uint8_t bt = 0; - int i; - par[0] = 0; - - for (i = 0; i < len; i++) { - bt = data[i]; - data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i]; - if ( ( i & 0x0007 ) == 0) - par[ i >> 3 ] = 0; - par[ i >> 3 ] |= (((filter(pcs->odd) ^ oddparity8(bt)) & 0x01)<<(7-(i&0x0007))); - } -} - -uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) { - uint8_t bt = 0; - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 0)) << 0; - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 1)) << 1; - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 2)) << 2; - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 3)) << 3; - return bt; -} - -// send X byte basic commands -int mifare_sendcmd(uint8_t cmd, uint8_t* data, uint8_t data_size, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing) { - uint8_t dcmd[data_size+3]; - dcmd[0] = cmd; - memcpy(dcmd+1, data, data_size); - AddCrc14A(dcmd, data_size+1); - ReaderTransmit(dcmd, sizeof(dcmd), timing); - int len = ReaderReceive(answer, answer_parity); - if(!len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%02X Cmd failed. Card timeout.", cmd); - len = ReaderReceive(answer,answer_parity); - } - return len; -} - -// send 2 byte commands -int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) { - uint16_t pos, res; - uint8_t dcmd[4] = {cmd, data, 0x00, 0x00}; - uint8_t ecmd[4] = {0x00, 0x00, 0x00, 0x00}; - uint8_t par[1] = {0x00}; // 1 Byte parity is enough here - AddCrc14A(dcmd, 2); - memcpy(ecmd, dcmd, sizeof(dcmd)); - - if (crypted) { - par[0] = 0; - for (pos = 0; pos < 4; pos++) { - ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos]; - par[0] |= (((filter(pcs->odd) ^ oddparity8(dcmd[pos])) & 0x01) << (7-pos)); - } - ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing); - } else { - ReaderTransmit(dcmd, sizeof(dcmd), timing); - } - - int len = ReaderReceive(answer, par); - - if (answer_parity) *answer_parity = par[0]; - - if (crypted == CRYPT_ALL) { - if (len == 1) { - res = 0; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 0)) << 0; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 1)) << 1; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 2)) << 2; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 3)) << 3; - answer[0] = res; - } else { - for (pos = 0; pos < len; pos++) - answer[pos] = crypto1_byte(pcs, 0x00, 0) ^ answer[pos]; - } - } - return len; -} - -// mifare classic commands -int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested) { - return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL); -} - -int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { - int len; - uint32_t pos, nt, ntpp; // Supplied tag nonce - uint8_t par[1] = {0x00}; - uint8_t nr[4]; - uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - - // "random" reader nonce: - num_to_bytes( prng_successor( GetTickCount(), 32), 4, nr); - - // Transmit MIFARE_CLASSIC_AUTH - len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing); - if (len != 4) return 1; - - // Save the tag nonce (nt) - nt = bytes_to_num(receivedAnswer, 4); - - // ----------------------------- crypto1 create - if (isNested) - crypto1_destroy(pcs); - - // Init cipher with key - crypto1_create(pcs, ui64Key); - - if (isNested == AUTH_NESTED) { - // decrypt nt with help of new key - nt = crypto1_word(pcs, nt ^ uid, 1) ^ nt; - } else { - // Load (plain) uid^nt into the cipher - crypto1_word(pcs, nt ^ uid, 0); - } - - // some statistic - if (!ntptr && (MF_DBGLEVEL >= MF_DBG_EXTENDED)) - Dbprintf("auth uid: %08x | nr: %08x | nt: %08x", uid, nr, nt); - - // save Nt - if (ntptr) - *ntptr = nt; - - // Generate (encrypted) nr+parity by loading it into the cipher (Nr) - par[0] = 0; - for (pos = 0; pos < 4; pos++) { - mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos]; - par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7-pos)); - } - - // Skip 32 bits in pseudo random generator - nt = prng_successor(nt, 32); - - // ar+parity - for (pos = 4; pos < 8; pos++) { - nt = prng_successor(nt,8); - mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff); - par[0] |= (((filter(pcs->odd) ^ oddparity8(nt & 0xff)) & 0x01) << (7-pos)); - } - - // Transmit reader nonce and reader answer - ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); - - // Receive 4 byte tag answer - len = ReaderReceive(receivedAnswer, receivedAnswerPar); - if (!len) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication failed. Card timeout."); - return 2; - } - - ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0,0); - - if (ntpp != bytes_to_num(receivedAnswer, 4)) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication failed. Error card response."); - return 3; - } - return 0; -} - -int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) { - - int len; - uint8_t bt[2] = {0x00, 0x00}; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - - len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); - if (len == 1) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); - return 1; - } - if (len != 18) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: wrong response len: %x (expected 18)", len); - return 2; - } - - memcpy(bt, receivedAnswer + 16, 2); - AddCrc14A(receivedAnswer, 16); - if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { - if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Cmd CRC response error."); - return 3; - } - - memcpy(blockData, receivedAnswer, 16); - return 0; -} - -// mifare ultralight commands -int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack){ - - uint16_t len = 0; - uint8_t resp[4] = {0x00, 0x00, 0x00, 0x00}; - uint8_t respPar[1] = {0x00}; - uint8_t key[4] = {0x00, 0x00, 0x00, 0x00}; - memcpy(key, keybytes, 4); - - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) - Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]); - - len = mifare_sendcmd(MIFARE_ULEV1_AUTH, key, sizeof(key), resp, respPar, NULL); - - if (len != 4) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len); - return 0; - } - - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) - Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0],resp[1],resp[2],resp[3]); - - memcpy(pack, resp, 4); - return 1; -} - -int mifare_ultra_auth(uint8_t *keybytes){ - - /// 3des2k - uint8_t random_a[8] = {1,1,1,1,1,1,1,1}; - uint8_t random_b[8] = {0x00}; - uint8_t enc_random_b[8] = {0x00}; - uint8_t rnd_ab[16] = {0x00}; - uint8_t IV[8] = {0x00}; - uint8_t key[16] = {0x00}; - memcpy(key, keybytes, 16); - - uint16_t len = 0; - uint8_t resp[19] = {0x00}; - uint8_t respPar[3] = {0,0,0}; - - // REQUEST AUTHENTICATION - len = mifare_sendcmd_short(NULL, 1, MIFARE_ULC_AUTH_1, 0x00, resp, respPar ,NULL); - if (len != 11) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); - return 0; - } - - // tag nonce. - memcpy(enc_random_b,resp+1,8); - - // decrypt nonce. - tdes_2key_dec((void*)random_b, (void*)enc_random_b, sizeof(random_b), (const void*)key, IV ); - rol(random_b,8); - memcpy(rnd_ab ,random_a,8); - memcpy(rnd_ab+8,random_b,8); - - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x", - enc_random_b[0],enc_random_b[1],enc_random_b[2],enc_random_b[3],enc_random_b[4],enc_random_b[5],enc_random_b[6],enc_random_b[7]); - - Dbprintf(" B: %02x %02x %02x %02x %02x %02x %02x %02x", - random_b[0],random_b[1],random_b[2],random_b[3],random_b[4],random_b[5],random_b[6],random_b[7]); - - Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", - rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3],rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); - - Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", - rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11],rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15] ); - } - - // encrypt out, in, length, key, iv - tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b); - - len = mifare_sendcmd(MIFARE_ULC_AUTH_2, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL); - if (len != 11) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); - return 0; - } - - uint8_t enc_resp[8] = { 0,0,0,0,0,0,0,0 }; - uint8_t resp_random_a[8] = { 0,0,0,0,0,0,0,0 }; - memcpy(enc_resp, resp+1, 8); - - // decrypt out, in, length, key, iv - tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b); - if ( memcmp(resp_random_a, random_a, 8) != 0 ) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("failed authentication"); - return 0; - } - - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", - rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3], - rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); - - Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", - rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11], - rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15]); - - Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x", - random_a[0],random_a[1],random_a[2],random_a[3], - random_a[4],random_a[5],random_a[6],random_a[7]); - - Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x", - resp_random_a[0],resp_random_a[1],resp_random_a[2],resp_random_a[3], - resp_random_a[4],resp_random_a[5],resp_random_a[6],resp_random_a[7]); - } - return 1; -} - -int mifare_ultra_readblockEx(uint8_t blockNo, uint8_t *blockData) { - uint16_t len = 0; - uint8_t bt[2] = {0x00, 0x00}; - uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; - - len = mifare_sendcmd_short(NULL, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); - if (len == 1) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); - return 1; - } - if (len != 18) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: card timeout. len: %x", len); - return 2; - } - - memcpy(bt, receivedAnswer + 16, 2); - AddCrc14A(receivedAnswer, 16); - if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd CRC response error."); - return 3; - } - - memcpy(blockData, receivedAnswer, 14); - return 0; -} -int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) { - #define MFU_MAX_RETRIES 5 - uint8_t res; - - for (uint8_t retries = 0; retries < MFU_MAX_RETRIES; ++retries) { - res = mifare_ultra_readblockEx(blockNo, blockData); - - // break if OK, or NACK. - switch ( res ) { - case 0: - case 1: - return res; - default: - continue; - } - } - return res; -} - -int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) { - // variables - uint16_t len = 0; - uint32_t pos = 0; - uint8_t par[3] = {0x00, 0x00, 0x00}; // enough for 18 Bytes to send - byte_t res = 0; - - uint8_t d_block[18], d_block_enc[18]; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - - // command MIFARE_CLASSIC_WRITEBLOCK - len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); - - if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); - return 1; - } - - memcpy(d_block, blockData, 16); - AddCrc14A(d_block, 16); - - // crypto - for (pos = 0; pos < 18; pos++) { - d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos]; - par[pos>>3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos&0x0007))); - } - - ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL); - - // Receive the response - len = ReaderReceive(receivedAnswer, receivedAnswerPar); - - res = 0; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 1)) << 1; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3; - - if ((len != 1) || (res != 0x0A)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd send data2 Error: %02x", res); - return 2; - } - return 0; -} - -/* // command not needed, but left for future testing -int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) { - uint16_t len; - uint8_t par[3] = {0}; // enough for 18 parity bits - uint8_t d_block[18] = {0x00}; - uint8_t receivedAnswer[MAX_FRAME_SIZE]; - uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; - - len = mifare_sendcmd_short(NULL, true, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); - - if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]); - return 1; - } - - memcpy(d_block, blockData, 16); - AddCrc14A(d_block, 16); - - ReaderTransmitPar(d_block, sizeof(d_block), par, NULL); - - len = ReaderReceive(receivedAnswer, receivedAnswerPar); - - if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len); - return 2; - } - return 0; -} -*/ - -int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) { - uint16_t len = 0; - uint8_t block[5] = {blockNo, 0x00, 0x00, 0x00, 0x00 }; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - - // command MIFARE_CLASSIC_WRITEBLOCK - memcpy(block+1, blockData, 4); - - len = mifare_sendcmd( MIFARE_ULC_WRITE, block, sizeof(block), receivedAnswer, receivedAnswerPar, NULL); - - if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len); - return 1; - } - return 0; -} -int mifare_classic_halt_ex(struct Crypto1State *pcs) { - uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00}; - uint16_t len = mifare_sendcmd_short(pcs, (pcs == NULL) ? CRYPT_NONE : CRYPT_ALL, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL); - if (len != 0) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len); - return 1; - } - return 0; -} -int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) { - return mifare_classic_halt_ex(pcs); -} - -int mifare_ultra_halt() { - uint16_t len = 0; - uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00}; - len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL); - if (len != 0) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len); - return 1; - } - return 0; -} - - -// Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards), -// plus evtl. 8 sectors with 16 blocks each (4k cards) -uint8_t NumBlocksPerSector(uint8_t sectorNo) { - return (sectorNo < 32) ? 4 : 16; -} - -uint8_t FirstBlockOfSector(uint8_t sectorNo) { - if (sectorNo < 32) - return sectorNo * 4; - else - return 32*4 + (sectorNo - 32) * 16; - -} - -// 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 * blockBtWidth, data, blocksCount * blockBtWidth); -} - -void emlGetMem(uint8_t *data, int blockNum, int blocksCount) { - uint8_t* emCARD = BigBuf_get_EM_addr(); - memcpy(data, emCARD + blockNum * 16, blocksCount * 16); -} - -void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount) { - uint8_t* emCARD = BigBuf_get_EM_addr(); - memcpy(data, emCARD + bytePtr, byteCount); -} - -int emlCheckValBl(int blockNum) { - uint8_t* emCARD = BigBuf_get_EM_addr(); - uint8_t* data = emCARD + blockNum * 16; - - if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) || - (data[1] != (data[5] ^ 0xff)) || (data[1] != data[9]) || - (data[2] != (data[6] ^ 0xff)) || (data[2] != data[10]) || - (data[3] != (data[7] ^ 0xff)) || (data[3] != data[11]) || - (data[12] != (data[13] ^ 0xff)) || (data[12] != data[14]) || - (data[12] != (data[15] ^ 0xff)) - ) - return 1; - return 0; -} - -int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) { - uint8_t* emCARD = BigBuf_get_EM_addr(); - uint8_t* data = emCARD + blockNum * 16; - - if (emlCheckValBl(blockNum)) - return 1; - - memcpy(blReg, data, 4); - *blBlock = data[12]; - return 0; -} - -int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) { - uint8_t* emCARD = BigBuf_get_EM_addr(); - uint8_t* data = emCARD + blockNum * 16; - - memcpy(data + 0, &blReg, 4); - memcpy(data + 8, &blReg, 4); - blReg = blReg ^ 0xffffffff; - memcpy(data + 4, &blReg, 4); - - data[12] = blBlock; - data[13] = blBlock ^ 0xff; - data[14] = blBlock; - data[15] = blBlock ^ 0xff; - - return 0; -} - -uint64_t emlGetKey(int sectorNum, int keyType) { - uint8_t key[6] = {0x00}; - uint8_t* emCARD = BigBuf_get_EM_addr(); - memcpy(key, emCARD + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6); - return bytes_to_num(key, 6); -} - -void emlClearMem(void) { - const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04}; - uint8_t* emCARD = BigBuf_get_EM_addr(); - memset(emCARD, 0, CARD_MEMORY_SIZE); - - // fill sectors trailer data - for(uint16_t b = 3; b < 256; ((b < 127) ? (b += 4) : (b += 16))) - emlSetMem((uint8_t *)trailer, b, 1); - - // uid - emlSetMem((uint8_t *)uid, 0, 1); - return; -} - - -// Mifare desfire commands -int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing) { - uint8_t dcmd[5] = {cmd, data[0], data[1], 0x00, 0x00}; - AddCrc14A(dcmd, 3); - - ReaderTransmit(dcmd, sizeof(dcmd), NULL); - int len = ReaderReceive(answer, answer_parity); - if(!len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout."); - return 1; - } - return len; -} - -int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer,uint8_t *answer_parity, uint32_t *timing) { - uint8_t dcmd[20] = {0x00}; - dcmd[0] = cmd; - memcpy(dcmd+1,data,17); - AddCrc14A(dcmd, 18); - - ReaderTransmit(dcmd, sizeof(dcmd), NULL); - int len = ReaderReceive(answer, answer_parity); - if(!len){ - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout."); - return 1; - } - return len; -} - -int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){ - - int len; - // load key, keynumber - uint8_t data[2]={MFDES_AUTHENTICATE, 0x00}; - uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; - - len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer,receivedAnswerPar,NULL); - if (len == 1) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Cmd Error: %02x", receivedAnswer[0]); - return 1; - } - - if (len == 12) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4], - receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9], - receivedAnswer[10],receivedAnswer[11]); - } - memcpy(blockData, receivedAnswer, 12); - return 0; - } - return 1; -} - -int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){ - - int len; - uint8_t data[17] = {MFDES_AUTHENTICATION_FRAME}; - memcpy(data+1,key,16); - - uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; - - len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar ,NULL); - - if ((receivedAnswer[0] == 0x03) && (receivedAnswer[1] == 0xae)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Auth Error: %02x %02x", receivedAnswer[0], receivedAnswer[1]); - return 1; - } - - if (len == 12){ - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4], - receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9], - receivedAnswer[10],receivedAnswer[11]); - } - memcpy(blockData, receivedAnswer, 12); - return 0; - } - return 1; -} +//----------------------------------------------------------------------------- +// Merlok, May 2011, 2012 +// Many authors, whom made it possible +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Work with mifare cards. +//----------------------------------------------------------------------------- +#include "mifareutil.h" + +int MF_DBGLEVEL = MF_DBG_ERROR; + +// crypto1 helpers +void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out){ + uint8_t bt = 0; + int i; + + if (len != 1) { + for (i = 0; i < len; i++) + data_out[i] = crypto1_byte(pcs, 0x00, 0) ^ data_in[i]; + } else { + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 0)) << 0; + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 1)) << 1; + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 2)) << 2; + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 3)) << 3; + data_out[0] = bt; + } + return; +} + +void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len){ + mf_crypto1_decryptEx(pcs, data, len, data); +} + +void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par) { + uint8_t bt = 0; + int i; + par[0] = 0; + + for (i = 0; i < len; i++) { + bt = data[i]; + data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i]; + if ( ( i & 0x0007 ) == 0) + par[ i >> 3 ] = 0; + par[ i >> 3 ] |= (((filter(pcs->odd) ^ oddparity8(bt)) & 0x01)<<(7-(i&0x0007))); + } +} + +uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) { + uint8_t bt = 0; + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 0)) << 0; + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 1)) << 1; + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 2)) << 2; + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 3)) << 3; + return bt; +} + +// send X byte basic commands +int mifare_sendcmd(uint8_t cmd, uint8_t* data, uint8_t data_size, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing) { + uint8_t dcmd[data_size+3]; + dcmd[0] = cmd; + memcpy(dcmd+1, data, data_size); + AddCrc14A(dcmd, data_size+1); + ReaderTransmit(dcmd, sizeof(dcmd), timing); + int len = ReaderReceive(answer, answer_parity); + if(!len) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%02X Cmd failed. Card timeout.", cmd); + len = ReaderReceive(answer,answer_parity); + } + return len; +} + +// send 2 byte commands +int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) { + uint16_t pos, res; + uint8_t dcmd[4] = {cmd, data, 0x00, 0x00}; + uint8_t ecmd[4] = {0x00, 0x00, 0x00, 0x00}; + uint8_t par[1] = {0x00}; // 1 Byte parity is enough here + AddCrc14A(dcmd, 2); + memcpy(ecmd, dcmd, sizeof(dcmd)); + + if (crypted) { + par[0] = 0; + for (pos = 0; pos < 4; pos++) { + ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos]; + par[0] |= (((filter(pcs->odd) ^ oddparity8(dcmd[pos])) & 0x01) << (7-pos)); + } + ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing); + } else { + ReaderTransmit(dcmd, sizeof(dcmd), timing); + } + + int len = ReaderReceive(answer, par); + + if (answer_parity) *answer_parity = par[0]; + + if (crypted == CRYPT_ALL) { + if (len == 1) { + res = 0; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 0)) << 0; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 1)) << 1; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 2)) << 2; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 3)) << 3; + answer[0] = res; + } else { + for (pos = 0; pos < len; pos++) + answer[pos] = crypto1_byte(pcs, 0x00, 0) ^ answer[pos]; + } + } + return len; +} + +// mifare classic commands +int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested) { + return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL); +} + +int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { + int len; + uint32_t pos, nt, ntpp; // Supplied tag nonce + uint8_t par[1] = {0x00}; + uint8_t nr[4]; + uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + + // "random" reader nonce: + num_to_bytes( prng_successor( GetTickCount(), 32), 4, nr); + + // Transmit MIFARE_CLASSIC_AUTH + len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing); + if (len != 4) return 1; + + // Save the tag nonce (nt) + nt = bytes_to_num(receivedAnswer, 4); + + // ----------------------------- crypto1 create + if (isNested) + crypto1_destroy(pcs); + + // Init cipher with key + crypto1_create(pcs, ui64Key); + + if (isNested == AUTH_NESTED) { + // decrypt nt with help of new key + nt = crypto1_word(pcs, nt ^ uid, 1) ^ nt; + } else { + // Load (plain) uid^nt into the cipher + crypto1_word(pcs, nt ^ uid, 0); + } + + // some statistic + if (!ntptr && (MF_DBGLEVEL >= MF_DBG_EXTENDED)) + Dbprintf("auth uid: %08x | nr: %08x | nt: %08x", uid, nr, nt); + + // save Nt + if (ntptr) + *ntptr = nt; + + // Generate (encrypted) nr+parity by loading it into the cipher (Nr) + par[0] = 0; + for (pos = 0; pos < 4; pos++) { + mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos]; + par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7-pos)); + } + + // Skip 32 bits in pseudo random generator + nt = prng_successor(nt, 32); + + // ar+parity + for (pos = 4; pos < 8; pos++) { + nt = prng_successor(nt,8); + mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff); + par[0] |= (((filter(pcs->odd) ^ oddparity8(nt & 0xff)) & 0x01) << (7-pos)); + } + + // Transmit reader nonce and reader answer + ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); + + // Receive 4 byte tag answer + len = ReaderReceive(receivedAnswer, receivedAnswerPar); + if (!len) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication failed. Card timeout."); + return 2; + } + + ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0,0); + + if (ntpp != bytes_to_num(receivedAnswer, 4)) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication failed. Error card response."); + return 3; + } + return 0; +} + +int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) { + + int len; + uint8_t bt[2] = {0x00, 0x00}; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + + len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); + if (len == 1) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + return 1; + } + if (len != 18) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: wrong response len: %x (expected 18)", len); + return 2; + } + + memcpy(bt, receivedAnswer + 16, 2); + AddCrc14A(receivedAnswer, 16); + if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { + if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Cmd CRC response error."); + return 3; + } + + memcpy(blockData, receivedAnswer, 16); + return 0; +} + +// mifare ultralight commands +int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack){ + + uint16_t len = 0; + uint8_t resp[4] = {0x00, 0x00, 0x00, 0x00}; + uint8_t respPar[1] = {0x00}; + uint8_t key[4] = {0x00, 0x00, 0x00, 0x00}; + memcpy(key, keybytes, 4); + + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) + Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]); + + len = mifare_sendcmd(MIFARE_ULEV1_AUTH, key, sizeof(key), resp, respPar, NULL); + + if (len != 4) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len); + return 0; + } + + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) + Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0],resp[1],resp[2],resp[3]); + + memcpy(pack, resp, 4); + return 1; +} + +int mifare_ultra_auth(uint8_t *keybytes){ + + /// 3des2k + uint8_t random_a[8] = {1,1,1,1,1,1,1,1}; + uint8_t random_b[8] = {0x00}; + uint8_t enc_random_b[8] = {0x00}; + uint8_t rnd_ab[16] = {0x00}; + uint8_t IV[8] = {0x00}; + uint8_t key[16] = {0x00}; + memcpy(key, keybytes, 16); + + uint16_t len = 0; + uint8_t resp[19] = {0x00}; + uint8_t respPar[3] = {0,0,0}; + + // REQUEST AUTHENTICATION + len = mifare_sendcmd_short(NULL, 1, MIFARE_ULC_AUTH_1, 0x00, resp, respPar ,NULL); + if (len != 11) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); + return 0; + } + + // tag nonce. + memcpy(enc_random_b,resp+1,8); + + // decrypt nonce. + tdes_2key_dec((void*)random_b, (void*)enc_random_b, sizeof(random_b), (const void*)key, IV ); + rol(random_b,8); + memcpy(rnd_ab ,random_a,8); + memcpy(rnd_ab+8,random_b,8); + + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x", + enc_random_b[0],enc_random_b[1],enc_random_b[2],enc_random_b[3],enc_random_b[4],enc_random_b[5],enc_random_b[6],enc_random_b[7]); + + Dbprintf(" B: %02x %02x %02x %02x %02x %02x %02x %02x", + random_b[0],random_b[1],random_b[2],random_b[3],random_b[4],random_b[5],random_b[6],random_b[7]); + + Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", + rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3],rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); + + Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", + rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11],rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15] ); + } + + // encrypt out, in, length, key, iv + tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b); + + len = mifare_sendcmd(MIFARE_ULC_AUTH_2, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL); + if (len != 11) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); + return 0; + } + + uint8_t enc_resp[8] = { 0,0,0,0,0,0,0,0 }; + uint8_t resp_random_a[8] = { 0,0,0,0,0,0,0,0 }; + memcpy(enc_resp, resp+1, 8); + + // decrypt out, in, length, key, iv + tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b); + if ( memcmp(resp_random_a, random_a, 8) != 0 ) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("failed authentication"); + return 0; + } + + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", + rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3], + rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); + + Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", + rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11], + rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15]); + + Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x", + random_a[0],random_a[1],random_a[2],random_a[3], + random_a[4],random_a[5],random_a[6],random_a[7]); + + Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x", + resp_random_a[0],resp_random_a[1],resp_random_a[2],resp_random_a[3], + resp_random_a[4],resp_random_a[5],resp_random_a[6],resp_random_a[7]); + } + return 1; +} + +int mifare_ultra_readblockEx(uint8_t blockNo, uint8_t *blockData) { + uint16_t len = 0; + uint8_t bt[2] = {0x00, 0x00}; + uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; + + len = mifare_sendcmd_short(NULL, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); + if (len == 1) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + return 1; + } + if (len != 18) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: card timeout. len: %x", len); + return 2; + } + + memcpy(bt, receivedAnswer + 16, 2); + AddCrc14A(receivedAnswer, 16); + if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd CRC response error."); + return 3; + } + + memcpy(blockData, receivedAnswer, 14); + return 0; +} +int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) { + #define MFU_MAX_RETRIES 5 + uint8_t res; + + for (uint8_t retries = 0; retries < MFU_MAX_RETRIES; ++retries) { + res = mifare_ultra_readblockEx(blockNo, blockData); + + // break if OK, or NACK. + switch ( res ) { + case 0: + case 1: + return res; + default: + continue; + } + } + return res; +} + +int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) { + // variables + uint16_t len = 0; + uint32_t pos = 0; + uint8_t par[3] = {0x00, 0x00, 0x00}; // enough for 18 Bytes to send + byte_t res = 0; + + uint8_t d_block[18], d_block_enc[18]; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + + // command MIFARE_CLASSIC_WRITEBLOCK + len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); + + if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + return 1; + } + + memcpy(d_block, blockData, 16); + AddCrc14A(d_block, 16); + + // crypto + for (pos = 0; pos < 18; pos++) { + d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos]; + par[pos>>3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos&0x0007))); + } + + ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL); + + // Receive the response + len = ReaderReceive(receivedAnswer, receivedAnswerPar); + + res = 0; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 1)) << 1; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3; + + if ((len != 1) || (res != 0x0A)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd send data2 Error: %02x", res); + return 2; + } + return 0; +} + +/* // command not needed, but left for future testing +int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) { + uint16_t len; + uint8_t par[3] = {0}; // enough for 18 parity bits + uint8_t d_block[18] = {0x00}; + uint8_t receivedAnswer[MAX_FRAME_SIZE]; + uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; + + len = mifare_sendcmd_short(NULL, true, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); + + if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK + if (MF_DBGLEVEL >= MF_DBG_ERROR) + Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]); + return 1; + } + + memcpy(d_block, blockData, 16); + AddCrc14A(d_block, 16); + + ReaderTransmitPar(d_block, sizeof(d_block), par, NULL); + + len = ReaderReceive(receivedAnswer, receivedAnswerPar); + + if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK + if (MF_DBGLEVEL >= MF_DBG_ERROR) + Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len); + return 2; + } + return 0; +} +*/ + +int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) { + uint16_t len = 0; + uint8_t block[5] = {blockNo, 0x00, 0x00, 0x00, 0x00 }; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + + // command MIFARE_CLASSIC_WRITEBLOCK + memcpy(block+1, blockData, 4); + + len = mifare_sendcmd( MIFARE_ULC_WRITE, block, sizeof(block), receivedAnswer, receivedAnswerPar, NULL); + + if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK + if (MF_DBGLEVEL >= MF_DBG_ERROR) + Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len); + return 1; + } + return 0; +} +int mifare_classic_halt_ex(struct Crypto1State *pcs) { + uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00}; + uint16_t len = mifare_sendcmd_short(pcs, (pcs == NULL) ? CRYPT_NONE : CRYPT_ALL, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL); + if (len != 0) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len); + return 1; + } + return 0; +} +int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) { + return mifare_classic_halt_ex(pcs); +} + +int mifare_ultra_halt() { + uint16_t len = 0; + uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00}; + len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL); + if (len != 0) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len); + return 1; + } + return 0; +} + + +// Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards), +// plus evtl. 8 sectors with 16 blocks each (4k cards) +uint8_t NumBlocksPerSector(uint8_t sectorNo) { + return (sectorNo < 32) ? 4 : 16; +} + +uint8_t FirstBlockOfSector(uint8_t sectorNo) { + if (sectorNo < 32) + return sectorNo * 4; + else + return 32*4 + (sectorNo - 32) * 16; + +} + +// 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 * blockBtWidth, data, blocksCount * blockBtWidth); +} + +void emlGetMem(uint8_t *data, int blockNum, int blocksCount) { + uint8_t* emCARD = BigBuf_get_EM_addr(); + memcpy(data, emCARD + blockNum * 16, blocksCount * 16); +} + +void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount) { + uint8_t* emCARD = BigBuf_get_EM_addr(); + memcpy(data, emCARD + bytePtr, byteCount); +} + +int emlCheckValBl(int blockNum) { + uint8_t* emCARD = BigBuf_get_EM_addr(); + uint8_t* data = emCARD + blockNum * 16; + + if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) || + (data[1] != (data[5] ^ 0xff)) || (data[1] != data[9]) || + (data[2] != (data[6] ^ 0xff)) || (data[2] != data[10]) || + (data[3] != (data[7] ^ 0xff)) || (data[3] != data[11]) || + (data[12] != (data[13] ^ 0xff)) || (data[12] != data[14]) || + (data[12] != (data[15] ^ 0xff)) + ) + return 1; + return 0; +} + +int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) { + uint8_t* emCARD = BigBuf_get_EM_addr(); + uint8_t* data = emCARD + blockNum * 16; + + if (emlCheckValBl(blockNum)) + return 1; + + memcpy(blReg, data, 4); + *blBlock = data[12]; + return 0; +} + +int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) { + uint8_t* emCARD = BigBuf_get_EM_addr(); + uint8_t* data = emCARD + blockNum * 16; + + memcpy(data + 0, &blReg, 4); + memcpy(data + 8, &blReg, 4); + blReg = blReg ^ 0xffffffff; + memcpy(data + 4, &blReg, 4); + + data[12] = blBlock; + data[13] = blBlock ^ 0xff; + data[14] = blBlock; + data[15] = blBlock ^ 0xff; + + return 0; +} + +uint64_t emlGetKey(int sectorNum, int keyType) { + uint8_t key[6] = {0x00}; + uint8_t* emCARD = BigBuf_get_EM_addr(); + memcpy(key, emCARD + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6); + return bytes_to_num(key, 6); +} + +void emlClearMem(void) { + const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04}; + uint8_t* emCARD = BigBuf_get_EM_addr(); + memset(emCARD, 0, CARD_MEMORY_SIZE); + + // fill sectors trailer data + for(uint16_t b = 3; b < 256; ((b < 127) ? (b += 4) : (b += 16))) + emlSetMem((uint8_t *)trailer, b, 1); + + // uid + emlSetMem((uint8_t *)uid, 0, 1); + return; +} + + +// Mifare desfire commands +int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing) { + uint8_t dcmd[5] = {cmd, data[0], data[1], 0x00, 0x00}; + AddCrc14A(dcmd, 3); + + ReaderTransmit(dcmd, sizeof(dcmd), NULL); + int len = ReaderReceive(answer, answer_parity); + if(!len) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout."); + return 1; + } + return len; +} + +int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer,uint8_t *answer_parity, uint32_t *timing) { + uint8_t dcmd[20] = {0x00}; + dcmd[0] = cmd; + memcpy(dcmd+1,data,17); + AddCrc14A(dcmd, 18); + + ReaderTransmit(dcmd, sizeof(dcmd), NULL); + int len = ReaderReceive(answer, answer_parity); + if(!len){ + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout."); + return 1; + } + return len; +} + +int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){ + + int len; + // load key, keynumber + uint8_t data[2]={MFDES_AUTHENTICATE, 0x00}; + uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; + + len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer,receivedAnswerPar,NULL); + if (len == 1) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) + Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + return 1; + } + + if (len == 12) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4], + receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9], + receivedAnswer[10],receivedAnswer[11]); + } + memcpy(blockData, receivedAnswer, 12); + return 0; + } + return 1; +} + +int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){ + + int len; + uint8_t data[17] = {MFDES_AUTHENTICATION_FRAME}; + memcpy(data+1,key,16); + + uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; + + len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar ,NULL); + + if ((receivedAnswer[0] == 0x03) && (receivedAnswer[1] == 0xae)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) + Dbprintf("Auth Error: %02x %02x", receivedAnswer[0], receivedAnswer[1]); + return 1; + } + + if (len == 12){ + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4], + receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9], + receivedAnswer[10],receivedAnswer[11]); + } + memcpy(blockData, receivedAnswer, 12); + return 0; + } + return 1; +} diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 268149f60..2406f9068 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -1,106 +1,106 @@ -//----------------------------------------------------------------------------- -// Merlok, May 2011 -// Many authors, that makes it possible -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// code for work with mifare cards. -//----------------------------------------------------------------------------- - -#ifndef __MIFAREUTIL_H -#define __MIFAREUTIL_H - -#include "proxmark3.h" -#include "apps.h" -#include "parity.h" -#include "util.h" -#include "string.h" -#include "iso14443crc.h" -#include "iso14443a.h" -#include "crapto1/crapto1.h" -#include "des.h" -#include "random.h" // fast_prand, prand - -// mifare authentication -#define CRYPT_NONE 0 -#define CRYPT_ALL 1 -#define CRYPT_REQUEST 2 -#define AUTH_FIRST 0 -#define AUTH_NESTED 2 - -#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) -#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication - -// mifare 4bit card answers -#define CARD_ACK 0x0A // 1010 - ACK -#define CARD_NACK_NA 0x04 // 0100 - NACK, not allowed (command not allowed) -#define CARD_NACK_TR 0x05 // 0101 - NACK, transmission error - - - -//mifare emulator states -#define MFEMUL_NOFIELD 0 -#define MFEMUL_IDLE 1 -#define MFEMUL_SELECT1 2 -#define MFEMUL_SELECT2 3 -#define MFEMUL_SELECT3 4 -#define MFEMUL_AUTH1 5 -#define MFEMUL_AUTH2 6 -#define MFEMUL_WORK 7 -#define MFEMUL_WRITEBL2 8 -#define MFEMUL_INTREG_INC 9 -#define MFEMUL_INTREG_DEC 10 -#define MFEMUL_INTREG_REST 11 -#define MFEMUL_HALTED 12 - -#define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF(); - +//----------------------------------------------------------------------------- +// Merlok, May 2011 +// Many authors, that makes it possible +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// code for work with mifare cards. +//----------------------------------------------------------------------------- + +#ifndef __MIFAREUTIL_H +#define __MIFAREUTIL_H + +#include "proxmark3.h" +#include "apps.h" +#include "parity.h" +#include "util.h" +#include "string.h" +#include "iso14443crc.h" +#include "iso14443a.h" +#include "crapto1/crapto1.h" +#include "des.h" +#include "random.h" // fast_prand, prand + +// mifare authentication +#define CRYPT_NONE 0 +#define CRYPT_ALL 1 +#define CRYPT_REQUEST 2 +#define AUTH_FIRST 0 +#define AUTH_NESTED 2 + +#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) +#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication + +// mifare 4bit card answers +#define CARD_ACK 0x0A // 1010 - ACK +#define CARD_NACK_NA 0x04 // 0100 - NACK, not allowed (command not allowed) +#define CARD_NACK_TR 0x05 // 0101 - NACK, transmission error + + + +//mifare emulator states +#define MFEMUL_NOFIELD 0 +#define MFEMUL_IDLE 1 +#define MFEMUL_SELECT1 2 +#define MFEMUL_SELECT2 3 +#define MFEMUL_SELECT3 4 +#define MFEMUL_AUTH1 5 +#define MFEMUL_AUTH2 6 +#define MFEMUL_WORK 7 +#define MFEMUL_WRITEBL2 8 +#define MFEMUL_INTREG_INC 9 +#define MFEMUL_INTREG_DEC 10 +#define MFEMUL_INTREG_REST 11 +#define MFEMUL_HALTED 12 + +#define cardSTATE_TO_IDLE() cardSTATE = MFEMUL_IDLE; LED_B_OFF(); LED_C_OFF(); + //functions -int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); +int mifare_sendcmd(uint8_t cmd, uint8_t *data, uint8_t data_size, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); -// mifare classic -int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested); +// mifare classic +int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested); int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing); -int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); -int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); -int mifare_classic_halt_ex(struct Crypto1State *pcs); -int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); - -// Ultralight/NTAG... -int mifare_ul_ev1_auth(uint8_t *key, uint8_t *pack); -int mifare_ultra_auth(uint8_t *key); -int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData); +int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); +int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); +int mifare_classic_halt_ex(struct Crypto1State *pcs); +int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); + +// Ultralight/NTAG... +int mifare_ul_ev1_auth(uint8_t *key, uint8_t *pack); +int mifare_ultra_auth(uint8_t *key); +int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData); //int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData); int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData); int mifare_ultra_halt(); - -// desfire -int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); -int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer,uint8_t *answer_parity, uint32_t *timing); -int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData); -int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData); + +// desfire +int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing); +int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer,uint8_t *answer_parity, uint32_t *timing); +int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData); +int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData); // crypto functions void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *receivedCmd, int len); -void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out); -void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par); -uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data); - -// Mifare memory structure -uint8_t NumBlocksPerSector(uint8_t sectorNo); -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); -int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum); +void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out); +void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par); +uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data); + +// Mifare memory structure +uint8_t NumBlocksPerSector(uint8_t sectorNo); +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); +int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum); int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum); int emlCheckValBl(int blockNum); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index 4dd3b4b3e..da027aad6 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -1,3472 +1,3472 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2011,2012 Merlok -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// High frequency MIFARE commands -//----------------------------------------------------------------------------- - -#include "cmdhfmf.h" -#include "mifare/mifare4.h" -#include "mifare/mad.h" -#include "mifare/ndef.h" - - -#define MFBLOCK_SIZE 16 - -#define MIFARE_4K_MAXBLOCK 256 -#define MIFARE_2K_MAXBLOCK 128 -#define MIFARE_1K_MAXBLOCK 64 -#define MIFARE_MINI_MAXBLOCK 20 - -#define MIFARE_MINI_MAXSECTOR 5 -#define MIFARE_1K_MAXSECTOR 16 -#define MIFARE_2K_MAXSECTOR 32 -#define MIFARE_4K_MAXSECTOR 40 - -static int CmdHelp(const char *Cmd); - -int usage_hf14_ice(void){ - PrintAndLogEx(NORMAL, "Usage: hf mf ice [l] [f] "); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " l nonces to be collected"); - PrintAndLogEx(NORMAL, " f save nonces to instead of hf-mf--nonces.bin"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf ice"); - PrintAndLogEx(NORMAL, " hf mf ice f nonces.bin"); - return 0; -} - -int usage_hf14_dump(void){ - PrintAndLogEx(NORMAL, "Usage: hf mf dump [card memory] k f "); - PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); - PrintAndLogEx(NORMAL, " k : key filename, if no given, UID will be used as filename"); - PrintAndLogEx(NORMAL, " f : data filename, if no given, UID will be used as filename"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf dump"); - PrintAndLogEx(NORMAL, " hf mf dump 4"); - return 0; -} - -int usage_hf14_mifare(void){ - PrintAndLogEx(NORMAL, "Usage: hf mf darkside [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " (Optional) target other block"); - PrintAndLogEx(NORMAL, " (optional) target key type"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf darkside"); - PrintAndLogEx(NORMAL, " hf mf darkside 16"); - PrintAndLogEx(NORMAL, " hf mf darkside 16 B"); - return 0; -} -int usage_hf14_mf1ksim(void){ - PrintAndLogEx(NORMAL, "Usage: hf mf sim [h] u n [i] [x] [e] [v]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " u (Optional) UID 4,7 or 10bytes. If not specified, the UID 4b from emulator memory will be used"); - PrintAndLogEx(NORMAL, " n (Optional) Automatically exit simulation after blocks have been read by reader. 0 = infinite"); - PrintAndLogEx(NORMAL, " i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted"); - PrintAndLogEx(NORMAL, " x (Optional) Crack, performs the 'reader attack', nr/ar attack against a reader"); - PrintAndLogEx(NORMAL, " e (Optional) Fill simulator keys from found keys"); - PrintAndLogEx(NORMAL, " v (Optional) Verbose"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf sim u 0a0a0a0a"); - PrintAndLogEx(NORMAL, " hf mf sim u 11223344556677"); - PrintAndLogEx(NORMAL, " hf mf sim u 112233445566778899AA"); - PrintAndLogEx(NORMAL, " hf mf sim u 11223344 i x"); - return 0; -} -int usage_hf14_dbg(void){ - PrintAndLogEx(NORMAL, "Usage: hf mf dbg [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " (Optional) see list for valid levels"); - PrintAndLogEx(NORMAL, " 0 - no debug messages"); - PrintAndLogEx(NORMAL, " 1 - error messages"); - PrintAndLogEx(NORMAL, " 2 - plus information messages"); - PrintAndLogEx(NORMAL, " 3 - plus debug messages"); - PrintAndLogEx(NORMAL, " 4 - print even debug messages in timing critical functions"); - PrintAndLogEx(NORMAL, " Note: this option therefore may cause malfunction itself"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf dbg 3"); - return 0; -} -int usage_hf14_sniff(void){ - PrintAndLogEx(NORMAL, "It continuously gets data from the field and saves it to: log, emulator, emulator file."); - PrintAndLogEx(NORMAL, "Usage: hf mf sniff [h] [l] [d] [f]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " l save encrypted sequence to logfile `uid.log`"); - PrintAndLogEx(NORMAL, " d decrypt sequence and put it to log file `uid.log`"); -// PrintAndLogEx(NORMAL, " n/a e decrypt sequence, collect read and write commands and save the result of the sequence to emulator memory"); - PrintAndLogEx(NORMAL, " f decrypt sequence, collect read and write commands and save the result of the sequence to emulator dump file `uid.eml`"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " hf mf sniff l d f"); - return 0; -} -int usage_hf14_nested(void){ - PrintAndLogEx(NORMAL, "Usage:"); - PrintAndLogEx(NORMAL, " all sectors: hf mf nested [t,d]"); - PrintAndLogEx(NORMAL, " one sector: hf mf nested o "); - PrintAndLogEx(NORMAL, " [t]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); - PrintAndLogEx(NORMAL, " t transfer keys into emulator memory"); - PrintAndLogEx(NORMAL, " d write keys to binary file `hf-mf--key.bin`"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf nested 1 0 A FFFFFFFFFFFF "); - PrintAndLogEx(NORMAL, " hf mf nested 1 0 A FFFFFFFFFFFF t "); - PrintAndLogEx(NORMAL, " hf mf nested 1 0 A FFFFFFFFFFFF d "); - PrintAndLogEx(NORMAL, " hf mf nested o 0 A FFFFFFFFFFFF 4 A"); - return 0; -} -int usage_hf14_hardnested(void){ - PrintAndLogEx(NORMAL, "Usage:"); - PrintAndLogEx(NORMAL, " hf mf hardnested "); - PrintAndLogEx(NORMAL, " [known target key (12 hex symbols)] [w] [s]"); - PrintAndLogEx(NORMAL, " or hf mf hardnested r [known target key]"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " w acquire nonces and UID, and write them to binary file with default name hf-mf--nonces.bin"); - PrintAndLogEx(NORMAL, " s slower acquisition (required by some non standard cards)"); - PrintAndLogEx(NORMAL, " r read hf-mf--nonces.bin if tag present, otherwise read nonces.bin, then start attack"); - PrintAndLogEx(NORMAL, " u read/write hf-mf--nonces.bin instead of default name"); - PrintAndLogEx(NORMAL, " f read/write instead of default name"); - PrintAndLogEx(NORMAL, " t tests?"); - PrintAndLogEx(NORMAL, " i set type of SIMD instructions. Without this flag programs autodetect it."); - PrintAndLogEx(NORMAL, " i 5 = AVX512"); - PrintAndLogEx(NORMAL, " i 2 = AVX2"); - PrintAndLogEx(NORMAL, " i a = AVX"); - PrintAndLogEx(NORMAL, " i s = SSE2"); - PrintAndLogEx(NORMAL, " i m = MMX"); - PrintAndLogEx(NORMAL, " i n = none (use CPU regular instruction set)"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf hardnested 0 A FFFFFFFFFFFF 4 A"); - PrintAndLogEx(NORMAL, " hf mf hardnested 0 A FFFFFFFFFFFF 4 A w"); - PrintAndLogEx(NORMAL, " hf mf hardnested 0 A FFFFFFFFFFFF 4 A f nonces.bin w s"); - PrintAndLogEx(NORMAL, " hf mf hardnested r"); - PrintAndLogEx(NORMAL, " hf mf hardnested r a0a1a2a3a4a5"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Add the known target key to check if it is present in the remaining key space:"); - PrintAndLogEx(NORMAL, " hf mf hardnested 0 A A0A1A2A3A4A5 4 A FFFFFFFFFFFF"); - return 0; -} -int usage_hf14_chk(void){ - PrintAndLogEx(NORMAL, "Usage: hf mf chk [h] |<*card memory> [t|d] [] []"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " * all sectors based on card memory, other values then below defaults to 1k"); - PrintAndLogEx(NORMAL, " 0 - MINI(320 bytes)"); - PrintAndLogEx(NORMAL, " 1 - 1K"); - PrintAndLogEx(NORMAL, " 2 - 2K"); - PrintAndLogEx(NORMAL, " 4 - 4K"); - PrintAndLogEx(NORMAL, " d write keys to binary file"); - PrintAndLogEx(NORMAL, " t write keys to emulator memory\n"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf chk 0 A 1234567890ab keys.dic -- target block 0, Key A"); - PrintAndLogEx(NORMAL, " hf mf chk *1 ? t -- target all blocks, all keys, 1K, write to emul"); - PrintAndLogEx(NORMAL, " hf mf chk *1 ? d -- target all blocks, all keys, 1K, write to file"); - return 0; -} -int usage_hf14_chk_fast(void){ - PrintAndLogEx(NORMAL, "This is a improved checkkeys method speedwise. It checks Mifare Classic tags sector keys against a dictionary file with keys"); - PrintAndLogEx(NORMAL, "Usage: hf mf fchk [h] [t|d|f] [] []"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " all sectors based on card memory, other values than below defaults to 1k"); - PrintAndLogEx(NORMAL, " 0 - MINI(320 bytes)"); - PrintAndLogEx(NORMAL, " 1 - 1K "); - PrintAndLogEx(NORMAL, " 2 - 2K"); - PrintAndLogEx(NORMAL, " 4 - 4K"); - PrintAndLogEx(NORMAL, " d write keys to binary file"); - PrintAndLogEx(NORMAL, " t write keys to emulator memory"); - PrintAndLogEx(NORMAL, " m use dictionary from flashmemory\n"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf fchk 1 1234567890ab keys.dic -- target 1K using key 1234567890ab, using dictionary file"); - PrintAndLogEx(NORMAL, " hf mf fchk 1 t -- target 1K, write to emulator memory"); - PrintAndLogEx(NORMAL, " hf mf fchk 1 d -- target 1K, write to file"); -#ifdef WITH_FLASH - PrintAndLogEx(NORMAL, " hf mf fchk 1 m -- target 1K, use dictionary from flashmemory"); -#endif - return 0; -} -int usage_hf14_keybrute(void){ - PrintAndLogEx(NORMAL, "J_Run's 2nd phase of multiple sector nested authentication key recovery"); - PrintAndLogEx(NORMAL, "You have a known 4 last bytes of a key recovered with mf_nonce_brute tool."); - PrintAndLogEx(NORMAL, "First 2 bytes of key will be bruteforced"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " ---[ This attack is obsolete, try hardnested instead ]---"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf keybrute [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " target block number"); - PrintAndLogEx(NORMAL, " target key type"); - PrintAndLogEx(NORMAL, " candidate key from mf_nonce_brute tool"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf keybrute 1 A 000011223344"); - return 0; -} -int usage_hf14_restore(void){ - PrintAndLogEx(NORMAL, "Usage: hf mf restore [card memory] u k f "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); - PrintAndLogEx(NORMAL, " u : uid, try to restore from hf-mf--key.bin and hf-mf--data.bin"); - PrintAndLogEx(NORMAL, " k : key filename, specific the full filename of key file"); - PrintAndLogEx(NORMAL, " f : data filename, specific the full filename of data file"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf restore -- read the UID from tag first, then restore from hf-mf--key.bin and and hf-mf--data.bin"); - PrintAndLogEx(NORMAL, " hf mf restore 1 u 12345678 -- restore from hf-mf-12345678-key.bin and hf-mf-12345678-data.bin"); - PrintAndLogEx(NORMAL, " hf mf restore 1 u 12345678 k dumpkey.bin -- restore from dumpkey.bin and hf-mf-12345678-data.bin"); - PrintAndLogEx(NORMAL, " hf mf restore 4 -- read the UID from tag with 4K memory first, then restore from hf-mf--key.bin and and hf-mf--data.bin"); - return 0; -} -int usage_hf14_decryptbytes(void){ - PrintAndLogEx(NORMAL, "Decrypt Crypto-1 encrypted bytes given some known state of crypto. See tracelog to gather needed values\n"); - PrintAndLogEx(NORMAL, "Usage: hf mf decrypt [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " reader nonce"); - PrintAndLogEx(NORMAL, " encrypted reader response"); - PrintAndLogEx(NORMAL, " encrypted tag response"); - PrintAndLogEx(NORMAL, " encrypted data, taken directly after at_enc and forward"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf decrypt b830049b 9248314a 9280e203 41e586f9\n"); - PrintAndLogEx(NORMAL, " this sample decrypts 41e586f9 -> 3003999a Annotated: 30 03 [99 9a] auth block 3 [crc]"); - return 0; -} - -int usage_hf14_eget(void){ - PrintAndLogEx(NORMAL, "Usage: hf mf eget "); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf eget 0 "); - return 0; -} -int usage_hf14_eclr(void){ - PrintAndLogEx(NORMAL, "It set card emulator memory to empty data blocks and key A/B FFFFFFFFFFFF \n"); - PrintAndLogEx(NORMAL, "Usage: hf mf eclr"); - return 0; -} -int usage_hf14_eset(void){ - PrintAndLogEx(NORMAL, "Usage: hf mf eset "); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf eset 1 000102030405060708090a0b0c0d0e0f "); - return 0; -} -int usage_hf14_eload(void){ - PrintAndLogEx(NORMAL, "It loads emul dump from the file `filename.eml`"); - PrintAndLogEx(NORMAL, "Usage: hf mf eload [card memory] [numblocks]"); - PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K, u = UL"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf eload filename"); - PrintAndLogEx(NORMAL, " hf mf eload 4 filename"); - return 0; -} -int usage_hf14_esave(void){ - PrintAndLogEx(NORMAL, "It saves emul dump into the file `filename.eml` or `cardID.eml`"); - PrintAndLogEx(NORMAL, " Usage: hf mf esave [card memory] [file name w/o `.eml`]"); - PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf esave "); - PrintAndLogEx(NORMAL, " hf mf esave 4"); - PrintAndLogEx(NORMAL, " hf mf esave 4 filename"); - return 0; -} -int usage_hf14_ecfill(void){ - PrintAndLogEx(NORMAL, "Read card and transfer its data to emulator memory."); - PrintAndLogEx(NORMAL, "Keys must be laid in the emulator memory. \n"); - PrintAndLogEx(NORMAL, "Usage: hf mf ecfill [card memory]"); - PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf ecfill A"); - PrintAndLogEx(NORMAL, " hf mf ecfill A 4"); - return 0; -} -int usage_hf14_ekeyprn(void){ - PrintAndLogEx(NORMAL, "It prints the keys loaded in the emulator memory"); - PrintAndLogEx(NORMAL, "Usage: hf mf ekeyprn [card memory]"); - PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf ekeyprn 1"); - return 0; -} - -int usage_hf14_csetuid(void){ - PrintAndLogEx(NORMAL, "Set UID, ATQA, and SAK for magic Chinese card. Only works with magic cards"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf csetuid [h] [ATQA 4 hex symbols] [SAK 2 hex symbols] [w]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " w wipe card before writing"); - PrintAndLogEx(NORMAL, " UID 8 hex symbols"); - PrintAndLogEx(NORMAL, " ATQA 4 hex symbols"); - PrintAndLogEx(NORMAL, " SAK 2 hex symbols"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf csetuid 01020304"); - PrintAndLogEx(NORMAL, " hf mf csetuid 01020304 0004 08 w"); - return 0; -} -int usage_hf14_csetblk(void){ - PrintAndLogEx(NORMAL, "Set block data for magic Chinese card. Only works with magic cards"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf csetblk [h] [w]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " w wipe card before writing"); - PrintAndLogEx(NORMAL, " block number"); - PrintAndLogEx(NORMAL, " block data to write (32 hex symbols)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf csetblk 1 01020304050607080910111213141516"); - PrintAndLogEx(NORMAL, " hf mf csetblk 1 01020304050607080910111213141516 w"); - return 0; -} -int usage_hf14_cload(void){ - PrintAndLogEx(NORMAL, "It loads magic Chinese card from the file `filename.eml`"); - PrintAndLogEx(NORMAL, "or from emulator memory"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf cload [h] [e] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " e load card with data from emulator memory"); - PrintAndLogEx(NORMAL, " j load card with data from json file"); - PrintAndLogEx(NORMAL, " b load card with data from binary file"); - PrintAndLogEx(NORMAL, " load card with data from eml file"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf cload mydump"); - PrintAndLogEx(NORMAL, " hf mf cload e"); - return 0; -} -int usage_hf14_cgetblk(void){ - PrintAndLogEx(NORMAL, "Get block data from magic Chinese card. Only works with magic cards\n"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf cgetblk [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " block number"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf cgetblk 1"); - return 0; -} -int usage_hf14_cgetsc(void){ - PrintAndLogEx(NORMAL, "Get sector data from magic Chinese card. Only works with magic cards\n"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf cgetsc [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " sector number"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf cgetsc 0"); - return 0; -} -int usage_hf14_csave(void){ - PrintAndLogEx(NORMAL, "It saves `magic Chinese` card dump into the file `filename.eml` or `cardID.eml`"); - PrintAndLogEx(NORMAL, "or into emulator memory"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf csave [h] [e] [u] [card memory] i "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " e save data to emulator memory"); - PrintAndLogEx(NORMAL, " u save data to file, use carduid as filename"); - PrintAndLogEx(NORMAL, " card memory 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); - PrintAndLogEx(NORMAL, " o save data to file"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf csave u 1"); - PrintAndLogEx(NORMAL, " hf mf csave e 1"); - PrintAndLogEx(NORMAL, " hf mf csave 4 o filename"); - return 0; -} -int usage_hf14_nack(void) { - PrintAndLogEx(NORMAL, "Test a mifare classic based card for the NACK bug."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: hf mf nack [h] [v]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " v verbose"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf nack"); - return 0; -} - -int GetHFMF14AUID(uint8_t *uid, int *uidlen) { - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - PrintAndLogEx(WARNING, "iso14443a card select failed"); - DropField(); - return 0; - } - - iso14a_card_select_t card; - memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - memcpy(uid, card.uid, card.uidlen * sizeof(uint8_t)); - *uidlen = card.uidlen; - return 1; -} - -char * GenerateFilename(const char *prefix, const char *suffix){ - uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; - int uidlen=0; - char * fptr = calloc (sizeof (char) * (strlen(prefix) + strlen(suffix)) + sizeof(uid)*2 + 1, sizeof(uint8_t)); - - GetHFMF14AUID(uid, &uidlen); - if (!uidlen) { - PrintAndLogEx(WARNING, "No tag found."); - free(fptr); - return NULL; - } - - strcpy(fptr, prefix); - FillFileNameByUID(fptr, uid, suffix, uidlen); - return fptr; -} - -int CmdHF14AMfDarkside(const char *Cmd) { - uint8_t blockno = 0, key_type = MIFARE_AUTH_KEYA; - uint64_t key = 0; - - char cmdp = tolower(param_getchar(Cmd, 0)); - if ( cmdp == 'h' ) return usage_hf14_mifare(); - - blockno = param_get8(Cmd, 0); - - cmdp = tolower(param_getchar(Cmd, 1)); - if (cmdp == 'b') - key_type = MIFARE_AUTH_KEYB; - - int isOK = mfDarkside(blockno, key_type, &key); - PrintAndLogEx(NORMAL, ""); - switch (isOK) { - case -1 : PrintAndLogEx(WARNING, "button pressed. Aborted."); return 1; - case -2 : PrintAndLogEx(FAILED, "card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests)."); return 1; - case -3 : PrintAndLogEx(FAILED, "card is not vulnerable to Darkside attack (its random number generator is not predictable)."); return 1; - case -4 : PrintAndLogEx(FAILED, "card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown"); - PrintAndLogEx(FAILED, "generating polynomial with 16 effective bits only, but shows unexpected behaviour."); return 1; - case -5 : PrintAndLogEx(WARNING, "aborted via keyboard."); return 1; - default : PrintAndLogEx(SUCCESS, "found valid key: %012" PRIx64 "\n", key); break; - } - PrintAndLogEx(NORMAL, ""); - return 0; -} - -int CmdHF14AMfWrBl(const char *Cmd) { - uint8_t blockNo = 0; - uint8_t keyType = 0; - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - char cmdp = 0x00; - - if (strlen(Cmd) < 3) { - PrintAndLogEx(NORMAL, "Usage: hf mf wrbl "); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F"); - return 0; - } - - blockNo = param_get8(Cmd, 0); - cmdp = tolower(param_getchar(Cmd, 1)); - if (cmdp == 0x00) { - PrintAndLogEx(NORMAL, "Key type must be A or B"); - return 1; - } - - if (cmdp != 'a') - keyType = 1; - - if (param_gethex(Cmd, 2, key, 12)) { - PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); - return 1; - } - - if (param_gethex(Cmd, 3, bldata, 32)) { - PrintAndLogEx(NORMAL, "Block data must include 32 HEX symbols"); - return 1; - } - - PrintAndLogEx(NORMAL, "--block no:%d, key type:%c, key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6)); - PrintAndLogEx(NORMAL, "--data: %s", sprint_hex(bldata, 16)); - - UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}}; - memcpy(c.d.asBytes, key, 6); - memcpy(c.d.asBytes + 10, bldata, 16); - clearCommandBuffer(); - SendCommand(&c); - - UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - uint8_t isOK = resp.arg[0] & 0xff; - PrintAndLogEx(NORMAL, "isOk:%02x", isOK); - } else { - PrintAndLogEx(NORMAL, "Command execute timeout"); - } - - return 0; -} - -int CmdHF14AMfRdBl(const char *Cmd) { - uint8_t blockNo = 0; - uint8_t keyType = 0; - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - char cmdp = 0x00; - - if (strlen(Cmd)<3) { - PrintAndLogEx(NORMAL, "Usage: hf mf rdbl "); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf rdbl 0 A FFFFFFFFFFFF "); - return 0; - } - - blockNo = param_get8(Cmd, 0); - cmdp = tolower(param_getchar(Cmd, 1)); - if (cmdp == 0x00) { - PrintAndLogEx(NORMAL, "Key type must be A or B"); - return 1; - } - - if (cmdp != 'a') - keyType = 1; - - if (param_gethex(Cmd, 2, key, 12)) { - PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); - return 1; - } - PrintAndLogEx(NORMAL, "--block no:%d, key type:%c, key:%s ", blockNo, keyType?'B':'A', sprint_hex(key, 6)); - - UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}}; - memcpy(c.d.asBytes, key, 6); - clearCommandBuffer(); - SendCommand(&c); - - UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - uint8_t isOK = resp.arg[0] & 0xff; - uint8_t *data = resp.d.asBytes; - - if (isOK) { - PrintAndLogEx(NORMAL, "isOk:%02x data:%s", isOK, sprint_hex(data, 16)); - } else { - PrintAndLogEx(NORMAL, "isOk:%02x", isOK); - return 1; - } - - if (mfIsSectorTrailer(blockNo) && (data[6] || data[7] || data[8])) { - PrintAndLogEx(NORMAL, "Trailer decoded:"); - int bln = mfFirstBlockOfSector(mfSectorNum(blockNo)); - int blinc = (mfNumBlocksPerSector(mfSectorNum(blockNo)) > 4) ? 5 : 1; - for (int i = 0; i < 4; i++) { - PrintAndLogEx(NORMAL, "Access block %d%s: %s", bln, ((blinc > 1) && (i < 3) ? "+" : "") , mfGetAccessConditionsDesc(i, &data[6])); - bln += blinc; - } - PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&data[9], 1)); - } - } else { - PrintAndLogEx(WARNING, "Command execute timeout"); - return 2; - } - - return 0; -} - -int CmdHF14AMfRdSc(const char *Cmd) { - int i; - uint8_t sectorNo = 0; - uint8_t keyType = 0; - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - uint8_t isOK = 0; - uint8_t *data = NULL; - char cmdp = 0x00; - - if (strlen(Cmd) < 3) { - PrintAndLogEx(NORMAL, "Usage: hf mf rdsc "); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf rdsc 0 A FFFFFFFFFFFF "); - return 0; - } - - sectorNo = param_get8(Cmd, 0); - if (sectorNo > MIFARE_4K_MAXSECTOR ) { - PrintAndLogEx(NORMAL, "Sector number must be less than 40"); - return 1; - } - - cmdp = tolower(param_getchar(Cmd, 1)); - if (cmdp != 'a' && cmdp != 'b') { - PrintAndLogEx(NORMAL, "Key type must be A or B"); - return 1; - } - - if (cmdp != 'a') - keyType = 1; - - if (param_gethex(Cmd, 2, key, 12)) { - PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); - return 1; - } - PrintAndLogEx(NORMAL, "--sector no:%d key type:%c key:%s ", sectorNo, keyType?'B':'A', sprint_hex(key, 6)); - - UsbCommand c = {CMD_MIFARE_READSC, {sectorNo, keyType, 0}}; - memcpy(c.d.asBytes, key, 6); - clearCommandBuffer(); - SendCommand(&c); - PrintAndLogEx(NORMAL, ""); - - UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - isOK = resp.arg[0] & 0xff; - data = resp.d.asBytes; - - PrintAndLogEx(NORMAL, "isOk:%02x", isOK); - if (isOK) { - for (i = 0; i < (sectorNo<32?3:15); i++) { - PrintAndLogEx(NORMAL, "data : %s", sprint_hex(data + i * 16, 16)); - } - PrintAndLogEx(NORMAL, "trailer: %s", sprint_hex(data + (sectorNo<32?3:15) * 16, 16)); - - PrintAndLogEx(NORMAL, "Trailer decoded:"); - int bln = mfFirstBlockOfSector(sectorNo); - int blinc = (mfNumBlocksPerSector(sectorNo) > 4) ? 5 : 1; - for (i = 0; i < 4; i++) { - PrintAndLogEx(NORMAL, "Access block %d%s: %s", bln, ((blinc > 1) && (i < 3) ? "+" : "") , mfGetAccessConditionsDesc(i, &(data + (sectorNo<32?3:15) * 16)[6])); - bln += blinc; - } - PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&(data + (sectorNo<32?3:15) * 16)[9], 1)); - } - } else { - PrintAndLogEx(WARNING, "Command execute timeout"); - } - - return 0; -} - -uint16_t NumOfBlocks(char card){ - switch(card){ - case '0' : return MIFARE_MINI_MAXBLOCK; - case '1' : return MIFARE_1K_MAXBLOCK; - case '2' : return MIFARE_2K_MAXBLOCK; - case '4' : return MIFARE_4K_MAXBLOCK; - default : return MIFARE_1K_MAXBLOCK; - } -} -uint8_t NumOfSectors(char card){ - switch(card){ - case '0' : return MIFARE_MINI_MAXSECTOR; - case '1' : return MIFARE_1K_MAXSECTOR; - case '2' : return MIFARE_2K_MAXSECTOR; - case '4' : return MIFARE_4K_MAXSECTOR; - default : return MIFARE_1K_MAXSECTOR; - } -} - -uint8_t FirstBlockOfSector(uint8_t sectorNo) { - if (sectorNo < 32) { - return sectorNo * 4; - } else { - return 32 * 4 + (sectorNo - 32) * 16; - } -} - -uint8_t NumBlocksPerSector(uint8_t sectorNo) { - if (sectorNo < 32) { - return 4; - } else { - return 16; - } -} - -int CmdHF14AMfDump(const char *Cmd) { - - uint8_t sectorNo, blockNo; - uint8_t keyA[40][6]; - uint8_t keyB[40][6]; - uint8_t rights[40][4]; - uint8_t carddata[256][16]; - uint8_t numSectors = 16; - uint8_t cmdp = 0; - - char keyFilename[FILE_PATH_SIZE] = {0}; - char dataFilename[FILE_PATH_SIZE]; - char * fptr; - - memset(keyFilename, 0, sizeof(keyFilename)); - memset(dataFilename, 0, sizeof(dataFilename)); - - FILE *f; - UsbCommand resp; - - while(param_getchar(Cmd, cmdp) != 0x00) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf14_dump(); - case 'k': - param_getstr(Cmd, cmdp+1, keyFilename, FILE_PATH_SIZE); - cmdp += 2; - break; - case 'f': - param_getstr(Cmd, cmdp+1, dataFilename, FILE_PATH_SIZE); - cmdp += 2; - break; - default: - if (cmdp == 0) { - numSectors = NumOfSectors(param_getchar(Cmd, cmdp)); - cmdp++; - } else { - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - return usage_hf14_dump(); - } - } - } - - if ( keyFilename[0] == 0x00 ) { - fptr = GenerateFilename("hf-mf-", "-key.bin"); - if (fptr == NULL) - return 1; - - strcpy(keyFilename, fptr); - } - - if ((f = fopen(keyFilename, "rb")) == NULL) { - PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), keyFilename); - return 1; - } - - // Read keys A from file - size_t bytes_read; - for (sectorNo=0; sectorNo> 2) | ((data[8] & 0x1) << 1) | ((data[8] & 0x10) >> 4); // C1C2C3 for data area 0 - rights[sectorNo][1] = ((data[7] & 0x20) >> 3) | ((data[8] & 0x2) << 0) | ((data[8] & 0x20) >> 5); // C1C2C3 for data area 1 - rights[sectorNo][2] = ((data[7] & 0x40) >> 4) | ((data[8] & 0x4) >> 1) | ((data[8] & 0x40) >> 6); // C1C2C3 for data area 2 - rights[sectorNo][3] = ((data[7] & 0x80) >> 5) | ((data[8] & 0x8) >> 2) | ((data[8] & 0x80) >> 7); // C1C2C3 for sector trailer - break; - } else if (tries == 2) { // on last try set defaults - PrintAndLogEx(FAILED, "could not get access rights for sector %2d. Trying with defaults...", sectorNo); - rights[sectorNo][0] = rights[sectorNo][1] = rights[sectorNo][2] = 0x00; - rights[sectorNo][3] = 0x01; - } - } else { - PrintAndLogEx(FAILED, "command execute timeout when trying to read access rights for sector %2d. Trying with defaults...", sectorNo); - rights[sectorNo][0] = rights[sectorNo][1] = rights[sectorNo][2] = 0x00; - rights[sectorNo][3] = 0x01; - } - } - } - - PrintAndLogEx(SUCCESS, "Finished reading sector access bits"); - PrintAndLogEx(INFO, "Dumping all blocks from card..."); - - bool isOK = true; - for (sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) { - for (blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { - bool received = false; - - for (tries = 0; tries < MIFARE_SECTOR_RETRY; tries++) { - if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer. At least the Access Conditions can always be read with key A. - UsbCommand c = {CMD_MIFARE_READBL, {FirstBlockOfSector(sectorNo) + blockNo, 0, 0}}; - memcpy(c.d.asBytes, keyA[sectorNo], 6); - clearCommandBuffer(); - SendCommand(&c); - received = WaitForResponseTimeout(CMD_ACK, &resp, 1500); - } else { // data block. Check if it can be read with key A or key B - uint8_t data_area = (sectorNo < 32) ? blockNo : blockNo/5; - if ((rights[sectorNo][data_area] == 0x03) || (rights[sectorNo][data_area] == 0x05)) { // only key B would work - UsbCommand c = {CMD_MIFARE_READBL, {FirstBlockOfSector(sectorNo) + blockNo, 1, 0}}; - memcpy(c.d.asBytes, keyB[sectorNo], 6); - SendCommand(&c); - received = WaitForResponseTimeout(CMD_ACK, &resp, 1500); - } else if (rights[sectorNo][data_area] == 0x07) { // no key would work - isOK = false; - PrintAndLogEx(WARNING, "access rights do not allow reading of sector %2d block %3d", sectorNo, blockNo); - tries = MIFARE_SECTOR_RETRY; - } else { // key A would work - UsbCommand c = {CMD_MIFARE_READBL, {FirstBlockOfSector(sectorNo) + blockNo, 0, 0}}; - memcpy(c.d.asBytes, keyA[sectorNo], 6); - clearCommandBuffer(); - SendCommand(&c); - received = WaitForResponseTimeout(CMD_ACK, &resp, 1500); - } - } - if (received) { - isOK = resp.arg[0] & 0xff; - if (isOK) break; - } - } - - if (received) { - isOK = resp.arg[0] & 0xff; - uint8_t *data = resp.d.asBytes; - if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer. Fill in the keys. - data[0] = (keyA[sectorNo][0]); - data[1] = (keyA[sectorNo][1]); - data[2] = (keyA[sectorNo][2]); - data[3] = (keyA[sectorNo][3]); - data[4] = (keyA[sectorNo][4]); - data[5] = (keyA[sectorNo][5]); - data[10] = (keyB[sectorNo][0]); - data[11] = (keyB[sectorNo][1]); - data[12] = (keyB[sectorNo][2]); - data[13] = (keyB[sectorNo][3]); - data[14] = (keyB[sectorNo][4]); - data[15] = (keyB[sectorNo][5]); - } - if (isOK) { - memcpy(carddata[FirstBlockOfSector(sectorNo) + blockNo], data, 16); - PrintAndLogEx(SUCCESS, "successfully read block %2d of sector %2d.", blockNo, sectorNo); - } else { - PrintAndLogEx(FAILED, "could not read block %2d of sector %2d", blockNo, sectorNo); - break; - } - } - else { - isOK = false; - PrintAndLogEx(WARNING, "command execute timeout when trying to read block %2d of sector %2d.", blockNo, sectorNo); - break; - } - } - } - - if (isOK == 0) { - PrintAndLogEx(FAILED, "Something went wrong"); - return 0; - } - - PrintAndLogEx(SUCCESS, "\nSuccedded in dumping all blocks"); - - if ( strlen(dataFilename) < 1 ) { - fptr = dataFilename; - fptr += sprintf(fptr, "hf-mf-"); - FillFileNameByUID(fptr, (uint8_t *)carddata, "-data", 4); - } - - uint16_t bytes = 16*(FirstBlockOfSector(numSectors - 1) + NumBlocksPerSector(numSectors - 1)); - - saveFile(dataFilename, "bin", (uint8_t *)carddata, bytes); - saveFileEML(dataFilename, "eml", (uint8_t *)carddata, bytes, MFBLOCK_SIZE); - saveFileJSON(dataFilename, "json", jsfCardMemory, (uint8_t *)carddata, bytes); - return 0; -} - -int CmdHF14AMfRestore(const char *Cmd) { - uint8_t sectorNo,blockNo; - uint8_t keyType = 0; - uint8_t key[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; - uint8_t bldata[16] = {0x00}; - uint8_t keyA[40][6]; - uint8_t keyB[40][6]; - uint8_t numSectors = 16; - uint8_t cmdp = 0; - char keyFilename[FILE_PATH_SIZE] = ""; - char dataFilename[FILE_PATH_SIZE] = ""; - char szTemp[FILE_PATH_SIZE-20] = ""; - char *fptr; - FILE *fdump, *fkeys; - - while(param_getchar(Cmd, cmdp) != 0x00) { - switch(tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf14_restore(); - case 'u': - param_getstr(Cmd, cmdp+1, szTemp, FILE_PATH_SIZE-20); - if(keyFilename[0]==0x00) - snprintf(keyFilename, FILE_PATH_SIZE, "hf-mf-%s-key.bin", szTemp); - if(dataFilename[0]==0x00) - snprintf(dataFilename, FILE_PATH_SIZE, "hf-mf-%s-data.bin", szTemp); - cmdp+=2; - break; - case 'k': - param_getstr(Cmd, cmdp+1, keyFilename, FILE_PATH_SIZE); - cmdp += 2; - break; - case 'f': - param_getstr(Cmd, cmdp+1, dataFilename, FILE_PATH_SIZE); - cmdp += 2; - break; - default: - if ( cmdp == 0 ) { - numSectors = NumOfSectors(param_getchar(Cmd, cmdp)); - cmdp++; - } else { - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - return usage_hf14_restore(); - } - } - } - - if ( keyFilename[0] == 0x00 ) { - fptr = GenerateFilename("hf-mf-", "-key.bin"); - if (fptr == NULL) - return 1; - - strcpy(keyFilename, fptr); - } - - if ((fkeys = fopen(keyFilename, "rb")) == NULL) { - PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), keyFilename); - return 1; - } - - size_t bytes_read; - for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { - bytes_read = fread( keyA[sectorNo], 1, 6, fkeys ); - if ( bytes_read != 6 ) { - PrintAndLogEx(WARNING, "File reading error " _YELLOW_(%s), keyFilename); - fclose(fkeys); - return 2; - } - } - - for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { - bytes_read = fread( keyB[sectorNo], 1, 6, fkeys ); - if ( bytes_read != 6 ) { - PrintAndLogEx(WARNING, "File reading error " _YELLOW_(%s), keyFilename); - fclose(fkeys); - return 2; - } - } - - fclose(fkeys); - - if ( dataFilename[0] == 0x00 ) { - fptr = GenerateFilename("hf-mf-", "-data.bin"); - if (fptr == NULL) - return 1; - - strcpy(dataFilename,fptr); - } - - if ((fdump = fopen(dataFilename, "rb")) == NULL) { - PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), dataFilename); - return 1; - } - PrintAndLogEx(INFO, "Restoring " _YELLOW_(%s)" to card", dataFilename); - - for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { - for (blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) { - UsbCommand c = {CMD_MIFARE_WRITEBL, {FirstBlockOfSector(sectorNo) + blockNo, keyType, 0}}; - memcpy(c.d.asBytes, key, 6); - bytes_read = fread(bldata, 1, 16, fdump); - if ( bytes_read != 16) { - PrintAndLogEx(WARNING, "File reading error " _YELLOW_(%s), dataFilename); - fclose(fdump); - fdump = NULL; - return 2; - } - - if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer - bldata[0] = (keyA[sectorNo][0]); - bldata[1] = (keyA[sectorNo][1]); - bldata[2] = (keyA[sectorNo][2]); - bldata[3] = (keyA[sectorNo][3]); - bldata[4] = (keyA[sectorNo][4]); - bldata[5] = (keyA[sectorNo][5]); - bldata[10] = (keyB[sectorNo][0]); - bldata[11] = (keyB[sectorNo][1]); - bldata[12] = (keyB[sectorNo][2]); - bldata[13] = (keyB[sectorNo][3]); - bldata[14] = (keyB[sectorNo][4]); - bldata[15] = (keyB[sectorNo][5]); - } - - PrintAndLogEx(NORMAL, "Writing to block %3d: %s", FirstBlockOfSector(sectorNo) + blockNo, sprint_hex(bldata, 16)); - - memcpy(c.d.asBytes + 10, bldata, 16); - clearCommandBuffer(); - SendCommand(&c); - - UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { - uint8_t isOK = resp.arg[0] & 0xff; - PrintAndLogEx(SUCCESS, "isOk:%02x", isOK); - } else { - PrintAndLogEx(WARNING, "Command execute timeout"); - } - } - } - - fclose(fdump); - return 0; -} - -int CmdHF14AMfNested(const char *Cmd) { - int i, res, iterations; - sector_t *e_sector = NULL; - uint8_t blockNo = 0; - uint8_t keyType = 0; - uint8_t trgBlockNo = 0; - uint8_t trgKeyType = 0; - uint8_t SectorsCnt = 0; - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - uint8_t keyBlock[(MIFARE_DEFAULTKEYS_SIZE + 1) *6]; - uint64_t key64 = 0; - bool transferToEml = false; - bool createDumpFile = false; - FILE *fkeys; - uint8_t standart[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - uint8_t tempkey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - char *fptr; - - if (strlen(Cmd) < 3) return usage_hf14_nested(); - - char cmdp, ctmp; - cmdp = tolower(param_getchar(Cmd, 0)); - blockNo = param_get8(Cmd, 1); - ctmp = tolower(param_getchar(Cmd, 2)); - - if (ctmp != 'a' && ctmp != 'b') { - PrintAndLogEx(WARNING, "key type must be A or B"); - return 1; - } - - if (ctmp != 'a') - keyType = 1; - - if (param_gethex(Cmd, 3, key, 12)) { - PrintAndLogEx(WARNING, "key must include 12 HEX symbols"); - return 1; - } - - if (cmdp == 'o') { - trgBlockNo = param_get8(Cmd, 4); - ctmp = tolower(param_getchar(Cmd, 5)); - if (ctmp != 'a' && ctmp != 'b') { - PrintAndLogEx(WARNING, "target key type must be A or B"); - return 1; - } - if (ctmp != 'a') { - trgKeyType = 1; - } - } else { - SectorsCnt = NumOfSectors(cmdp); - } - - uint8_t j = 4; - while ( ctmp != 0x00 ) { - - ctmp = tolower(param_getchar(Cmd, j)); - transferToEml |= (ctmp == 't'); - createDumpFile |= (ctmp == 'd'); - - j++; - } - - // check if we can authenticate to sector - res = mfCheckKeys(blockNo, keyType, true, 1, key, &key64); - if (res) { - PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A'); - return 3; - } - - if (cmdp == 'o') { - int16_t isOK = mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, true); - switch (isOK) { - case -1 : PrintAndLogEx(WARNING, "Error: No response from Proxmark.\n"); break; - case -2 : PrintAndLogEx(WARNING, "Button pressed. Aborted.\n"); break; - case -3 : PrintAndLogEx(FAILED, "Tag isn't vulnerable to Nested Attack (PRNG is not predictable).\n"); break; - case -4 : PrintAndLogEx(FAILED, "No valid key found"); break; - case -5 : - key64 = bytes_to_num(keyBlock, 6); - - // transfer key to the emulator - if (transferToEml) { - uint8_t sectortrailer; - if (trgBlockNo < 32*4) { // 4 block sector - sectortrailer = trgBlockNo | 0x03; - } else { // 16 block sector - sectortrailer = trgBlockNo | 0x0f; - } - mfEmlGetMem(keyBlock, sectortrailer, 1); - - if (!trgKeyType) - num_to_bytes(key64, 6, keyBlock); - else - num_to_bytes(key64, 6, &keyBlock[10]); - mfEmlSetMem(keyBlock, sectortrailer, 1); - PrintAndLogEx(SUCCESS, "Key transferred to emulator memory."); - } - return 0; - default : PrintAndLogEx(WARNING, "Unknown Error.\n"); - } - return 2; - } - else { // ------------------------------------ multiple sectors working - uint64_t t1 = msclock(); - - e_sector = calloc(SectorsCnt, sizeof(sector_t)); - if (e_sector == NULL) return 1; - - //test current key and additional standard keys first - // add parameter key - memcpy( keyBlock + (MIFARE_DEFAULTKEYS_SIZE * 6), key, 6 ); - - for (int cnt = 0; cnt < MIFARE_DEFAULTKEYS_SIZE; cnt++){ - num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t*)(keyBlock + cnt * 6)); - } - - PrintAndLogEx(SUCCESS, "Testing known keys. Sector count=%d", SectorsCnt); - res = mfCheckKeys_fast( SectorsCnt, true, true, 1, MIFARE_DEFAULTKEYS_SIZE + 1, keyBlock, e_sector, false); - - uint64_t t2 = msclock() - t1; - PrintAndLogEx(SUCCESS, "Time to check %d known keys: %.0f seconds\n", MIFARE_DEFAULTKEYS_SIZE, (float)t2/1000.0 ); - PrintAndLogEx(SUCCESS, "enter nested attack"); - - // nested sectors - iterations = 0; - bool calibrate = true; - - for (i = 0; i < MIFARE_SECTOR_RETRY; i++) { - for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; ++sectorNo) { - for (trgKeyType = 0; trgKeyType < 2; ++trgKeyType) { - - if (e_sector[sectorNo].foundKey[trgKeyType]) continue; - - int16_t isOK = mfnested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate); - switch (isOK) { - case -1 : PrintAndLogEx(WARNING, "error: No response from Proxmark.\n"); break; - case -2 : PrintAndLogEx(WARNING, "button pressed. Aborted.\n"); break; - case -3 : PrintAndLogEx(FAILED, "Tag isn't vulnerable to Nested Attack (PRNG is not predictable).\n"); break; - case -4 : //key not found - calibrate = false; - iterations++; - continue; - case -5 : - calibrate = false; - iterations++; - e_sector[sectorNo].foundKey[trgKeyType] = 1; - e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6); - - res = mfCheckKeys_fast( SectorsCnt, true, true, 2, 1, keyBlock, e_sector, false); - continue; - - default : PrintAndLogEx(WARNING, "unknown Error.\n"); - } - free(e_sector); - return 2; - } - } - } - - t1 = msclock() - t1; - PrintAndLogEx(SUCCESS, "time in nested: %.0f seconds\n", (float)t1/1000.0); - - - // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? - PrintAndLogEx(INFO, "trying to read key B..."); - for (i = 0; i < SectorsCnt; i++) { - // KEY A but not KEY B - if ( e_sector[i].foundKey[0] && !e_sector[i].foundKey[1] ) { - - uint8_t sectrail = (FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); - - PrintAndLogEx(SUCCESS, "reading block %d", sectrail); - - UsbCommand c = {CMD_MIFARE_READBL, {sectrail, 0, 0}}; - num_to_bytes(e_sector[i].Key[0], 6, c.d.asBytes); // KEY A - clearCommandBuffer(); - SendCommand(&c); - - UsbCommand resp; - if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) continue; - - uint8_t isOK = resp.arg[0] & 0xff; - if (!isOK) continue; - - uint8_t *data = resp.d.asBytes; - key64 = bytes_to_num(data+10, 6); - if (key64) { - PrintAndLogEx(SUCCESS, "data: %s", sprint_hex(data+10, 6)); - e_sector[i].foundKey[1] = true; - e_sector[i].Key[1] = key64; - } - } - } - - - //print them - printKeyTable( SectorsCnt, e_sector ); - - // transfer them to the emulator - if (transferToEml) { - for (i = 0; i < SectorsCnt; i++) { - mfEmlGetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); - if (e_sector[i].foundKey[0]) - num_to_bytes(e_sector[i].Key[0], 6, keyBlock); - if (e_sector[i].foundKey[1]) - num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]); - mfEmlSetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); - } - PrintAndLogEx(SUCCESS, "keys transferred to emulator memory."); - } - - // Create dump file - if (createDumpFile) { - fptr = GenerateFilename("hf-mf-", "-key.bin"); - if (fptr == NULL) { - free(e_sector); - return 1; - } - - if ((fkeys = fopen(fptr, "wb")) == NULL) { - PrintAndLogEx(WARNING, "could not create file " _YELLOW_(%s), fptr); - free(e_sector); - return 1; - } - - PrintAndLogEx(SUCCESS, "saving keys to binary file " _YELLOW_(%s), fptr); - for (i=0; i= FILE_PATH_SIZE ) { - PrintAndLogEx(FAILED, "Filename too long"); - continue; - } - - f = fopen( filename, "r"); - if ( !f ){ - PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); - continue; - } - - // read file - while( fgets(buf, sizeof(buf), f) ){ - if (strlen(buf) < 12 || buf[11] == '\n') - continue; - - while (fgetc(f) != '\n' && !feof(f)) ; //goto next line - - if( buf[0]=='#' ) continue; //The line start with # is comment, skip - - if (!isxdigit(buf[0])){ - PrintAndLogEx(FAILED, "File content error. '" _YELLOW_(%s)"' must include 12 HEX symbols", buf); - continue; - } - - buf[12] = 0; - if ( keyitems - keycnt < 2) { - p = realloc(keyBlock, 6 * (keyitems += 64)); - if (!p) { - PrintAndLogEx(FAILED, "Cannot allocate memory for default keys"); - free(keyBlock); - fclose(f); - return 2; - } - keyBlock = p; - } - int pos = 6 * keycnt; - memset(keyBlock + pos, 0, 6); - num_to_bytes(strtoll(buf, NULL, 16), 6, keyBlock + pos); - keycnt++; - memset(buf, 0, sizeof(buf)); - } - fclose(f); - PrintAndLogEx(SUCCESS, "Loaded %2d keys from " _YELLOW_(%s), keycnt, filename); - } - } - - if (keycnt == 0 && !use_flashmemory) { - PrintAndLogEx(SUCCESS, "No key specified, trying default keys"); - for (;keycnt < MIFARE_DEFAULTKEYS_SIZE; keycnt++) - PrintAndLogEx(NORMAL, "[%2d] %02x%02x%02x%02x%02x%02x", keycnt, - (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], - (keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5]); - } - - // // initialize storage for found keys - e_sector = calloc(sectorsCnt, sizeof(sector_t)); - if (e_sector == NULL) { - free(keyBlock); - return 1; - } - - uint32_t chunksize = keycnt > (USB_CMD_DATA_SIZE/6) ? (USB_CMD_DATA_SIZE/6) : keycnt; - bool firstChunk = true, lastChunk = false; - - // time - uint64_t t1 = msclock(); - - if ( use_flashmemory ) { - PrintAndLogEx(SUCCESS, "Using dictionary in flash memory"); - mfCheckKeys_fast( sectorsCnt, true, true, 1, 0, keyBlock, e_sector, use_flashmemory); - } else { - - // strategys. 1= deep first on sector 0 AB, 2= width first on all sectors - for (uint8_t strategy = 1; strategy < 3; strategy++) { - PrintAndLogEx(SUCCESS, "Running strategy %u", strategy); - - // main keychunk loop - for (uint32_t i = 0; i < keycnt; i += chunksize) { - - if (ukbhit()) { - int gc = getchar(); (void)gc; - PrintAndLogEx(WARNING, "\naborted via keyboard!\n"); - goto out; - } - - uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i; - - // last chunk? - if ( size == keycnt - i) - lastChunk = true; - - int res = mfCheckKeys_fast( sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector, false); - - if ( firstChunk ) - firstChunk = false; - - // all keys, aborted - if ( res == 0 || res == 2 ) - goto out; - } // end chunks of keys - firstChunk = true; - lastChunk = false; - } // end strategy - } -out: - t1 = msclock() - t1; - PrintAndLogEx(SUCCESS, "Time in checkkeys (fast): %.1fs\n", (float)(t1/1000.0)); - - // check.. - uint8_t found_keys = 0; - for (uint8_t i = 0; i < sectorsCnt; ++i) { - - if ( e_sector[i].foundKey[0] ) - found_keys++; - - if ( e_sector[i].foundKey[1] ) - found_keys++; - } - - if ( found_keys == 0 ) { - PrintAndLogEx(WARNING, "No keys found"); - } else { - - printKeyTable( sectorsCnt, e_sector ); - - if (transferToEml) { - uint8_t block[16] = {0x00}; - for (uint8_t i = 0; i < sectorsCnt; ++i ) { - mfEmlGetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); - if (e_sector[i].foundKey[0]) - num_to_bytes(e_sector[i].Key[0], 6, block); - if (e_sector[i].foundKey[1]) - num_to_bytes(e_sector[i].Key[1], 6, block+10); - mfEmlSetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); - } - PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory"); - } - - if (createDumpFile) { - fptr = GenerateFilename("hf-mf-", "-key.bin"); - if (fptr == NULL) - return 1; - - FILE *fkeys = fopen(fptr, "wb"); - if (fkeys == NULL) { - PrintAndLogEx(WARNING, "Could not create file " _YELLOW_(%s), fptr); - free(keyBlock); - free(e_sector); - return 1; - } - PrintAndLogEx(SUCCESS, "Printing keys to binary file " _YELLOW_(%s)"...", fptr); - - for (i=0; i 0xffffffffffff has been inserted for unknown keys.", fptr); - } - } - - free(keyBlock); - free(e_sector); - PrintAndLogEx(NORMAL, ""); - return 0; -} - -int CmdHF14AMfChk(const char *Cmd) { - - char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 3 || ctmp == 'h') return usage_hf14_chk(); - - FILE * f; - char filename[FILE_PATH_SIZE] = {0}; - char buf[13]; - uint8_t *keyBlock = NULL, *p; - sector_t *e_sector = NULL; - - uint8_t blockNo = 0; - uint8_t SectorsCnt = 1; - uint8_t keyType = 0; - uint32_t keyitems = MIFARE_DEFAULTKEYS_SIZE; - uint64_t key64 = 0; - uint8_t tempkey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; - char *fptr; - int clen = 0; - int transferToEml = 0; - int createDumpFile = 0; - int i, res, keycnt = 0; - - keyBlock = calloc(MIFARE_DEFAULTKEYS_SIZE, 6); - if (keyBlock == NULL) return 1; - - for (int cnt = 0; cnt < MIFARE_DEFAULTKEYS_SIZE; cnt++) - num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t*)(keyBlock + cnt * 6)); - - if (param_getchar(Cmd, 0)=='*') { - blockNo = 3; - SectorsCnt = NumOfSectors( param_getchar(Cmd+1, 0) ); - } else { - blockNo = param_get8(Cmd, 0); - } - - ctmp = tolower(param_getchar(Cmd, 1)); - clen = param_getlength(Cmd, 1); - if (clen == 1) { - switch (ctmp) { - case 'a': - keyType = 0; - break; - case 'b': - keyType = 1; - break; - case '?': - keyType = 2; - break; - default: - PrintAndLogEx(FAILED, "Key type must be A , B or ?"); - free(keyBlock); - return 1; - }; - } - - for (i = 2; param_getchar(Cmd, i); i++) { - - ctmp = tolower(param_getchar(Cmd, i)); - clen = param_getlength(Cmd, i); - - if (clen == 12) { - - if ( param_gethex(Cmd, i, keyBlock + 6 * keycnt, 12) ){ - PrintAndLogEx(FAILED, "not hex, skipping"); - continue; - } - - if ( keyitems - keycnt < 2) { - p = realloc(keyBlock, 6 * (keyitems += 64)); - if (!p) { - PrintAndLogEx(FAILED, "cannot allocate memory for Keys"); - free(keyBlock); - return 2; - } - keyBlock = p; - } - PrintAndLogEx(NORMAL, "[%2d] key %s", keycnt, sprint_hex( (keyBlock + 6*keycnt), 6 ) );; - keycnt++; - } else if ( clen == 1 ) { - if (ctmp == 't' ) { transferToEml = 1; continue; } - if (ctmp == 'd' ) { createDumpFile = 1; continue; } - } else { - // May be a dic file - if ( param_getstr(Cmd, i, filename, sizeof(filename)) >= FILE_PATH_SIZE ) { - PrintAndLogEx(FAILED, "File name too long"); - continue; - } - - f = fopen( filename , "r"); - if ( !f ) { - PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); - continue; - } - - // load keys from dictionary file - while( fgets(buf, sizeof(buf), f) ){ - if (strlen(buf) < 12 || buf[11] == '\n') - continue; - - while (fgetc(f) != '\n' && !feof(f)) ; //goto next line - - if( buf[0]=='#' ) continue; //The line start with # is comment, skip - - // codesmell, only checks first char? - if (!isxdigit(buf[0])){ - PrintAndLogEx(FAILED, "File content error. '" _YELLOW_(%s)"' must include 12 HEX symbols",buf); - continue; - } - - buf[12] = 0; - - if ( keyitems - keycnt < 2) { - p = realloc(keyBlock, 6 * (keyitems += 64)); - if (!p) { - PrintAndLogEx(FAILED, "Cannot allocate memory for defKeys"); - free(keyBlock); - fclose(f); - return 2; - } - keyBlock = p; - } - memset(keyBlock + 6 * keycnt, 0, 6); - num_to_bytes(strtoll(buf, NULL, 16), 6, keyBlock + 6*keycnt); - //PrintAndLogEx(NORMAL, "check key[%2d] %012" PRIx64, keycnt, bytes_to_num(keyBlock + 6*keycnt, 6)); - keycnt++; - memset(buf, 0, sizeof(buf)); - } - fclose(f); - PrintAndLogEx(SUCCESS, "Loaded %2d keys from " _YELLOW_(%s), keycnt, filename); - } - } - - if (keycnt == 0) { - PrintAndLogEx(INFO, "No key specified, trying default keys"); - for (;keycnt < MIFARE_DEFAULTKEYS_SIZE; keycnt++) - PrintAndLogEx(NORMAL, "[%2d] %02x%02x%02x%02x%02x%02x", keycnt, - (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], - (keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6); - } - - // initialize storage for found keys - e_sector = calloc(SectorsCnt, sizeof(sector_t)); - if (e_sector == NULL) { - free(keyBlock); - return 1; - } - - // empty e_sector - for(int i = 0; i < SectorsCnt; ++i){ - e_sector[i].Key[0] = 0xffffffffffff; - e_sector[i].Key[1] = 0xffffffffffff; - e_sector[i].foundKey[0] = false; - e_sector[i].foundKey[1] = false; - } - - - uint8_t trgKeyType = 0; - uint32_t max_keys = keycnt > (USB_CMD_DATA_SIZE/6) ? (USB_CMD_DATA_SIZE/6) : keycnt; - - // time - uint64_t t1 = msclock(); - - - // check keys. - for (trgKeyType = (keyType==2)?0:keyType; trgKeyType < 2; (keyType==2) ? (++trgKeyType) : (trgKeyType=2) ) { - - int b = blockNo; - for (int i = 0; i < SectorsCnt; ++i) { - - // skip already found keys. - if (e_sector[i].foundKey[trgKeyType]) continue; - - for (uint32_t c = 0; c < keycnt; c += max_keys) { - - printf("."); fflush(stdout); - if (ukbhit()) { - int gc = getchar(); (void)gc; - PrintAndLogEx(INFO, "\naborted via keyboard!\n"); - goto out; - } - - uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c; - - res = mfCheckKeys(b, trgKeyType, true, size, &keyBlock[6*c], &key64); - if (!res) { - e_sector[i].Key[trgKeyType] = key64; - e_sector[i].foundKey[trgKeyType] = true; - break; - } - - - } - b < 127 ? ( b +=4 ) : ( b += 16 ); - } - } - t1 = msclock() - t1; - PrintAndLogEx(SUCCESS, "\nTime in checkkeys: %.0f seconds\n", (float)t1/1000.0); - - - // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? - if ( keyType != 1 ) { - PrintAndLogEx(INFO, "testing to read key B..."); - for (i = 0; i < SectorsCnt; i++) { - // KEY A but not KEY B - if ( e_sector[i].foundKey[0] && !e_sector[i].foundKey[1] ) { - - uint8_t sectrail = (FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); - - PrintAndLogEx(NORMAL, "Reading block %d", sectrail); - - UsbCommand c = {CMD_MIFARE_READBL, {sectrail, 0, 0}}; - num_to_bytes(e_sector[i].Key[0], 6, c.d.asBytes); // KEY A - clearCommandBuffer(); - SendCommand(&c); - - UsbCommand resp; - if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) continue; - - uint8_t isOK = resp.arg[0] & 0xff; - if (!isOK) continue; - - uint8_t *data = resp.d.asBytes; - key64 = bytes_to_num(data+10, 6); - if (key64) { - PrintAndLogEx(NORMAL, "Data:%s", sprint_hex(data+10, 6)); - e_sector[i].foundKey[1] = 1; - e_sector[i].Key[1] = key64; - } - } - } - } - -out: - - //print keys - printKeyTable( SectorsCnt, e_sector ); - - if (transferToEml) { - uint8_t block[16] = {0x00}; - for (uint8_t i = 0; i < SectorsCnt; ++i ) { - mfEmlGetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); - if (e_sector[i].foundKey[0]) - num_to_bytes(e_sector[i].Key[0], 6, block); - if (e_sector[i].foundKey[1]) - num_to_bytes(e_sector[i].Key[1], 6, block+10); - mfEmlSetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); - } - PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory"); - } - - if (createDumpFile) { - fptr = GenerateFilename("hf-mf-", "-key.bin"); - if (fptr == NULL) { - free(keyBlock); - free(e_sector); - return 1; - } - - FILE *fkeys = fopen(fptr, "wb"); - if (fkeys == NULL) { - PrintAndLogEx(WARNING, "Could not create file " _YELLOW_(%s), fptr); - free(keyBlock); - free(e_sector); - return 1; - } - PrintAndLogEx(INFO, "Printing keys to binary file " _YELLOW_(%s)"...", fptr); - - for( i=0; i>1) - , exitAfterNReads - , flags - , flags); - - UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads, 0}}; - memcpy(c.d.asBytes, uid, sizeof(uid)); - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - - if(flags & FLAG_INTERACTIVE) { - PrintAndLogEx(INFO, "Press pm3-button or send another cmd to abort simulation"); - - while( !ukbhit() ){ - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; - if ( !(flags & FLAG_NR_AR_ATTACK) ) break; - if ( (resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD ) break; - - memcpy(data, resp.d.asBytes, sizeof(data)); - readerAttack(data[0], setEmulatorMem, verbose); - } - showSectorTable(); - } - return 0; -} - -int CmdHF14AMfSniff(const char *Cmd){ - bool wantLogToFile = false; - bool wantDecrypt = false; - //bool wantSaveToEml = false; TODO - bool wantSaveToEmlFile = false; - - //var - int res = 0, len = 0, blockLen = 0; - int pckNum = 0, num = 0; - uint8_t sak = 0; - uint8_t uid[10]; - uint8_t uid_len = 0; - uint8_t atqa[2] = {0x00, 0x00}; - bool isTag = false; - uint8_t *buf = NULL; - uint16_t bufsize = 0; - uint8_t *bufPtr = NULL; - uint16_t traceLen = 0; - - memset(uid, 0x00, sizeof(uid)); - - char ctmp = tolower(param_getchar(Cmd, 0)); - if ( ctmp == 'h') return usage_hf14_sniff(); - - for (int i = 0; i < 4; i++) { - ctmp = tolower(param_getchar(Cmd, i)); - if (ctmp == 'l') wantLogToFile = true; - if (ctmp == 'd') wantDecrypt = true; - //if (ctmp == 'e') wantSaveToEml = true; TODO - if (ctmp == 'f') wantSaveToEmlFile = true; - } - - PrintAndLogEx(NORMAL, "-------------------------------------------------------------------------\n"); - PrintAndLogEx(NORMAL, "Executing mifare sniffing command. \n"); - PrintAndLogEx(NORMAL, "Press the key on the proxmark3 device to abort both proxmark3 and client.\n"); - PrintAndLogEx(NORMAL, "Press the key on pc keyboard to abort the client.\n"); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------------------\n"); - - UsbCommand c = {CMD_MIFARE_SNIFFER, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - - UsbCommand resp; - - // wait cycle - while (true) { - printf("."); fflush(stdout); - if (ukbhit()) { - int gc = getchar(); (void)gc; - PrintAndLogEx(INFO, "\naborted via keyboard!\n"); - break; - } - - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - continue; - } - - res = resp.arg[0] & 0xff; - traceLen = resp.arg[1]; - len = resp.arg[2]; - - if (res == 0) { - PrintAndLogEx(SUCCESS, "hf mifare sniff finished"); - free(buf); - return 0; - } - - if (res == 1) { // there is (more) data to be transferred - if (pckNum == 0) { // first packet, (re)allocate necessary buffer - if (traceLen > bufsize || buf == NULL) { - uint8_t *p; - if (buf == NULL) // not yet allocated - p = calloc(traceLen, sizeof(uint8_t)); - else // need more memory - p = realloc(buf, traceLen); - - if (p == NULL) { - PrintAndLogEx(FAILED, "Cannot allocate memory for trace"); - free(buf); - return 2; - } - buf = p; - } - bufPtr = buf; - bufsize = traceLen; - memset(buf, 0x00, traceLen); - } - - // what happens if LEN is bigger then TRACELEN --iceman - memcpy(bufPtr, resp.d.asBytes, len); - bufPtr += len; - pckNum++; - } - - if (res == 2) { // received all data, start displaying - blockLen = bufPtr - buf; - bufPtr = buf; - PrintAndLogEx(NORMAL, ">\n"); - PrintAndLogEx(SUCCESS, "received trace len: %d packages: %d", blockLen, pckNum); - while (bufPtr - buf < blockLen) { - bufPtr += 6; // skip (void) timing information - len = *((uint16_t *)bufPtr); - if(len & 0x8000) { - isTag = true; - len &= 0x7fff; - } else { - isTag = false; - } - bufPtr += 2; - - // the uid identification package - // 0xFF 0xFF xx xx xx xx xx xx xx xx xx xx aa aa cc 0xFF 0xFF - // x = uid, a = atqa, c = sak - if ((len == 17) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[15] == 0xff) && (bufPtr[16] == 0xff)) { - memcpy(uid, bufPtr + 2, 10); - memcpy(atqa, bufPtr + 2 + 10, 2); - switch (atqa[0] & 0xC0) { - case 0x80: uid_len = 10; break; - case 0x40: uid_len = 7; break; - default: uid_len = 4; break; - } - sak = bufPtr[14]; - PrintAndLogEx(SUCCESS, "UID %s | ATQA %02x %02x | SAK 0x%02x", - sprint_hex(uid, uid_len), - atqa[1], - atqa[0], - sak); - if (wantLogToFile || wantDecrypt) { - FillFileNameByUID(logHexFileName, uid, ".log", uid_len); - AddLogCurrentDT(logHexFileName); - PrintAndLogEx(SUCCESS, "Trace saved to %s", logHexFileName); - } - if (wantDecrypt) - mfTraceInit(uid, uid_len, atqa, sak, wantSaveToEmlFile); - } else { - PrintAndLogEx(NORMAL, "%03d| %s |%s", num, isTag ? "TAG" : "RDR", sprint_hex(bufPtr, len)); - if (wantLogToFile) - AddLogHex(logHexFileName, isTag ? "TAG| ":"RDR| ", bufPtr, len); - if (wantDecrypt) - mfTraceDecode(bufPtr, len, wantSaveToEmlFile); - num++; - } - bufPtr += len; - bufPtr += ((len-1)/8+1); // ignore parity - } - pckNum = 0; - } - } // while (true) - - free(buf); - return 0; -} - -int CmdHF14AMfDbg(const char *Cmd) { - - char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || ctmp == 'h' ) return usage_hf14_dbg(); - - uint8_t dbgMode = param_get8ex(Cmd, 0, 0, 10); - if (dbgMode > 4) return usage_hf14_dbg(); - - UsbCommand c = {CMD_MIFARE_SET_DBGMODE, {dbgMode, 0, 0}}; - SendCommand(&c); - return 0; -} - -int CmdHF14AMfKeyBrute(const char *Cmd) { - - uint8_t blockNo = 0, keytype = 0; - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - uint64_t foundkey = 0; - - char cmdp = tolower(param_getchar(Cmd, 0)); - if ( cmdp == 'h' ) return usage_hf14_keybrute(); - - // block number - blockNo = param_get8(Cmd, 0); - - // keytype - cmdp = tolower(param_getchar(Cmd, 1)); - if ( cmdp == 'b' ) keytype = 1; - - // key - if (param_gethex(Cmd, 2, key, 12)) return usage_hf14_keybrute(); - - uint64_t t1 = msclock(); - - if (mfKeyBrute( blockNo, keytype, key, &foundkey)) - PrintAndLogEx(SUCCESS, "found valid key: %012" PRIx64 " \n", foundkey); - else - PrintAndLogEx(FAILED, "key not found"); - - t1 = msclock() - t1; - PrintAndLogEx(SUCCESS, "\ntime in keybrute: %.0f seconds\n", (float)t1/1000.0); - return 0; -} - -void printKeyTable( uint8_t sectorscnt, sector_t *e_sector ){ - char strA[12+1] = {0}; - char strB[12+1] = {0}; - PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); - PrintAndLogEx(NORMAL, "|sec|key A |res|key B |res|"); - PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); - for (uint8_t i = 0; i < sectorscnt; ++i) { - - snprintf(strA, sizeof(strA), "------------"); - snprintf(strB, sizeof(strB), "------------"); - - if ( e_sector[i].foundKey[0] ) - snprintf(strA, sizeof(strA), "%012" PRIx64, e_sector[i].Key[0]); - - if ( e_sector[i].foundKey[1] ) - snprintf(strB, sizeof(strB), "%012" PRIx64, e_sector[i].Key[1]); - - - PrintAndLogEx(NORMAL, "|%03d| %s | %d | %s | %d |" - , i - , strA, e_sector[i].foundKey[0] - , strB, e_sector[i].foundKey[1] - ); - } - PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); -} - -// EMULATOR COMMANDS -int CmdHF14AMfEGet(const char *Cmd) { - uint8_t blockNo = 0; - uint8_t data[16] = {0x00}; - char c = tolower(param_getchar(Cmd, 0)); - - if (strlen(Cmd) < 1 || c == 'h') return usage_hf14_eget(); - - blockNo = param_get8(Cmd, 0); - - PrintAndLogEx(NORMAL, ""); - if (!mfEmlGetMem(data, blockNo, 1)) { - PrintAndLogEx(NORMAL, "data[%3d]:%s", blockNo, sprint_hex(data, sizeof(data))); - } else { - PrintAndLogEx(WARNING, "Command execute timeout"); - } - return 0; -} - -int CmdHF14AMfEClear(const char *Cmd) { - char c = tolower(param_getchar(Cmd, 0)); - if (c == 'h') return usage_hf14_eclr(); - - UsbCommand cmd = {CMD_MIFARE_EML_MEMCLR, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&cmd); - return 0; -} - -int CmdHF14AMfESet(const char *Cmd) { - char c = tolower(param_getchar(Cmd, 0)); - uint8_t memBlock[16]; - uint8_t blockNo = 0; - memset(memBlock, 0x00, sizeof(memBlock)); - - if (strlen(Cmd) < 3 || c == 'h') - return usage_hf14_eset(); - - blockNo = param_get8(Cmd, 0); - - if (param_gethex(Cmd, 1, memBlock, 32)) { - PrintAndLogEx(WARNING, "block data must include 32 HEX symbols"); - return 1; - } - - // 1 - blocks count - return mfEmlSetMem(memBlock, blockNo, 1); -} - -int CmdHF14AMfELoad(const char *Cmd) { - - size_t counter = 0; - char filename[FILE_PATH_SIZE]; - int blockNum, numBlocks, nameParamNo = 1; - uint8_t blockWidth = 16; - char c = tolower(param_getchar(Cmd, 0)); - - if ( strlen(Cmd) < 2 && c == 'h' ) - return usage_hf14_eload(); - - switch (c) { - case '0' : numBlocks = MIFARE_MINI_MAXBLOCK; break; - case '1' : - case '\0': numBlocks = MIFARE_1K_MAXBLOCK; break; - case '2' : numBlocks = MIFARE_2K_MAXBLOCK; break; - case '4' : numBlocks = MIFARE_4K_MAXBLOCK; break; - case 'u' : numBlocks = 255; blockWidth = 4; break; - default: { - numBlocks = MIFARE_1K_MAXBLOCK; - nameParamNo = 0; - } - } - uint32_t numblk2 = param_get32ex(Cmd, 2, 0, 10); - if (numblk2 > 0) - numBlocks = numblk2; - - param_getstr(Cmd, nameParamNo, filename, sizeof(filename)); - - uint8_t *data = calloc(4096, sizeof(uint8_t)); - size_t datalen = 0; - //int res = loadFile(filename, "bin", data, &datalen); - int res = loadFileEML( filename, "eml", data, &datalen); - if ( res ) { - free(data); - return 1; - } - - // 64 or 256 blocks. - if ( (datalen % blockWidth) != 0 ) { - PrintAndLogEx(FAILED, "File content error. Size doesn't match blockwidth "); - free(data); - return 2; - } - - PrintAndLogEx(INFO, "Copying to emulator memory"); - - blockNum = 0; - while ( datalen ) { - - if (mfEmlSetMem_xt(data + counter, blockNum, 1, blockWidth)) { - PrintAndLogEx(FAILED, "Cant set emul block: %3d", blockNum); - free(data); - return 3; - } - printf("."); fflush(stdout); - - blockNum++; - counter += blockWidth; - datalen -= blockWidth; - } - PrintAndLogEx(NORMAL, "\n"); - - // Ultralight /Ntag - if ( blockWidth == 4 ) { - if ((blockNum != numBlocks)) { - PrintAndLogEx(FAILED, "Warning, Ultralight/Ntag file content, Loaded %d blocks into emulator memory", blockNum); - free(data); - return 0; - } - } else { - if ((blockNum != numBlocks)) { - PrintAndLogEx(FAILED, "Error, file content, Only loaded %d blocks, must be %d blocks into emulator memory", blockNum, numBlocks); - free(data); - return 4; - } - } - PrintAndLogEx(SUCCESS, "Loaded %d blocks from file: " _YELLOW_(%s), blockNum, filename); - free(data); - return 0; -} - -int CmdHF14AMfESave(const char *Cmd) { - - char filename[FILE_PATH_SIZE]; - char * fnameptr = filename; - uint8_t *dump; - int len, bytes, nameParamNo = 1; - uint16_t blocks; - - memset(filename, 0, sizeof(filename)); - - char c = tolower(param_getchar(Cmd, 0)); - if (c == 'h') return usage_hf14_esave(); - - blocks = NumOfBlocks(c); - bytes = blocks * MFBLOCK_SIZE; - - dump = calloc(bytes, sizeof(uint8_t)); - if (!dump) { - PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); - return 1; - } - memset(dump, 0, bytes); - - PrintAndLogEx(INFO, "downloading from emulator memory"); - if (!GetFromDevice( BIG_BUF_EML, dump, bytes, 0, NULL, 2500, false)) { - PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); - free(dump); - return 2; - } - - len = param_getstr(Cmd, nameParamNo, filename, sizeof(filename)); - if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; - - // user supplied filename? - if (len < 1) { - fnameptr += sprintf(fnameptr, "hf-mf-"); - FillFileNameByUID(fnameptr, dump, "-dump", 4); - } - - saveFile(filename, "bin", dump, bytes); - saveFileEML(filename, "eml", dump, bytes, MFBLOCK_SIZE); - saveFileJSON(filename, "json", jsfCardMemory, dump, bytes); - free(dump); - return 0; -} - -int CmdHF14AMfECFill(const char *Cmd) { - uint8_t keyType = 0; - uint8_t numSectors = 16; - char c = tolower(param_getchar(Cmd, 0)); - - if (strlen(Cmd) < 1 || c == 'h') - return usage_hf14_ecfill(); - - if (c != 'a' && c != 'b') { - PrintAndLogEx(WARNING, "Key type must be A or B"); - return 1; - } - if (c != 'a') - keyType = 1; - - c = tolower(param_getchar(Cmd, 1)); - numSectors = NumOfSectors(c); - - PrintAndLogEx(NORMAL, "--params: numSectors: %d, keyType: %c\n", numSectors, (keyType == 0) ? 'A' : 'B'); - UsbCommand cmd = {CMD_MIFARE_EML_CARDLOAD, {numSectors, keyType, 0}}; - clearCommandBuffer(); - SendCommand(&cmd); - return 0; -} - -int CmdHF14AMfEKeyPrn(const char *Cmd) { - int i; - uint8_t numSectors; - uint8_t data[16]; - uint64_t keyA, keyB; - - char c = tolower(param_getchar(Cmd, 0)); - if ( c == 'h' ) - return usage_hf14_ekeyprn(); - - numSectors = NumOfSectors(c); - - PrintAndLogEx(NORMAL, "|---|----------------|----------------|"); - PrintAndLogEx(NORMAL, "|sec|key A |key B |"); - PrintAndLogEx(NORMAL, "|---|----------------|----------------|"); - for (i = 0; i < numSectors; i++) { - if (mfEmlGetMem(data, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1)) { - PrintAndLogEx(WARNING, "error get block %d", FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); - break; - } - keyA = bytes_to_num(data, 6); - keyB = bytes_to_num(data + 10, 6); - PrintAndLogEx(NORMAL, "|%03d| %012" PRIx64 " | %012" PRIx64 " |", i, keyA, keyB); - } - PrintAndLogEx(NORMAL, "|---|----------------|----------------|"); - return 0; -} - -// CHINESE MAGIC COMMANDS -int CmdHF14AMfCSetUID(const char *Cmd) { - uint8_t wipeCard = 0; - uint8_t uid[8] = {0x00}; - uint8_t oldUid[8] = {0x00}; - uint8_t atqa[2] = {0x00}; - uint8_t sak[1] = {0x00}; - uint8_t atqaPresent = 1; - int res, argi = 0; - char ctmp; - - if (strlen(Cmd) < 1 || param_getchar(Cmd, argi) == 'h') - return usage_hf14_csetuid(); - - if (param_getchar(Cmd, argi) && param_gethex(Cmd, argi, uid, 8)) - return usage_hf14_csetuid(); - - argi++; - - ctmp = tolower(param_getchar(Cmd, argi)); - if (ctmp == 'w') { - wipeCard = 1; - atqaPresent = 0; - } - - if (atqaPresent) { - if (param_getchar(Cmd, argi)) { - if (param_gethex(Cmd, argi, atqa, 4)) { - PrintAndLogEx(WARNING, "ATQA must include 4 HEX symbols"); - return 1; - } - argi++; - if (!param_getchar(Cmd, argi) || param_gethex(Cmd, argi, sak, 2)) { - PrintAndLogEx(WARNING, "SAK must include 2 HEX symbols"); - return 1; - } - argi++; - } else - atqaPresent = 0; - } - - if (!wipeCard) { - ctmp = tolower(param_getchar(Cmd, argi)); - if (ctmp == 'w') { - wipeCard = 1; - } - } - - PrintAndLogEx(NORMAL, "--wipe card:%s uid:%s", (wipeCard)?"YES":"NO", sprint_hex(uid, 4)); - - res = mfCSetUID(uid, (atqaPresent) ? atqa : NULL, (atqaPresent) ? sak : NULL, oldUid, wipeCard); - if (res) { - PrintAndLogEx(WARNING, "Can't set UID. error=%d", res); - return 1; - } - - PrintAndLogEx(SUCCESS, "old UID:%s", sprint_hex(oldUid, 4)); - PrintAndLogEx(SUCCESS, "new UID:%s", sprint_hex(uid, 4)); - return 0; -} - -int CmdHF14AMfCSetBlk(const char *Cmd) { - uint8_t block[16] = {0x00}; - uint8_t blockNo = 0; - uint8_t params = MAGIC_SINGLE; - int res; - char ctmp = tolower(param_getchar(Cmd, 0)); - - if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_csetblk(); - - blockNo = param_get8(Cmd, 0); - - if (param_gethex(Cmd, 1, block, 32)) return usage_hf14_csetblk(); - - ctmp = tolower(param_getchar(Cmd, 2)); - if (ctmp == 'w') - params |= MAGIC_WIPE; - - PrintAndLogEx(NORMAL, "--block number:%2d data:%s", blockNo, sprint_hex(block, 16)); - - res = mfCSetBlock(blockNo, block, NULL, params); - if (res) { - PrintAndLogEx(WARNING, "Can't write block. error=%d", res); - return 1; - } - return 0; -} - -int CmdHF14AMfCLoad(const char *Cmd) { - - uint8_t buf8[16] = {0x00}; - uint8_t fillFromEmulator = 0; - int blockNum, flags = 0; - bool fillFromJson = false; - bool fillFromBin = false; - char fileName[50] = {0}; - - char ctmp = tolower(param_getchar(Cmd, 0)); - if ( param_getlength(Cmd, 0) == 1 ) { - if (ctmp == 'h' || ctmp == 0x00) return usage_hf14_cload(); - if (ctmp == 'e' ) fillFromEmulator = 1; - if (ctmp == 'j' ) fillFromJson = true; - if (ctmp == 'b' ) fillFromBin = true; - } - - if (fillFromJson || fillFromBin) - param_getstr(Cmd, 1, fileName, sizeof(fileName)); - - - if (fillFromEmulator) { - for (blockNum = 0; blockNum < 16 * 4; blockNum += 1) { - if (mfEmlGetMem(buf8, blockNum, 1)) { - PrintAndLogEx(WARNING, "Cant get block: %d", blockNum); - return 2; - } - if (blockNum == 0) flags = MAGIC_INIT + MAGIC_WUPC; // switch on field and send magic sequence - if (blockNum == 1) flags = 0; // just write - if (blockNum == 16 * 4 - 1) flags = MAGIC_HALT + MAGIC_OFF; // Done. Magic Halt and switch off field. - - if (mfCSetBlock(blockNum, buf8, NULL, flags)) { - PrintAndLogEx(WARNING, "Cant set magic card block: %d", blockNum); - return 3; - } - printf("."); fflush(stdout); - } - PrintAndLogEx(NORMAL, "\n"); - return 0; - } - - size_t maxdatalen = 4096; - uint8_t *data = calloc(maxdatalen, sizeof(uint8_t)); - size_t datalen = 0; - int res = 0; - if (fillFromBin) { - res = loadFile(fileName, "bin", data, &datalen); - } else { - if (fillFromJson) { - res = loadFileJSON(fileName, "json", data, maxdatalen, &datalen); - } else { - res = loadFileEML( Cmd, "eml", data, &datalen); - } - } - - if ( res ) { - if ( data ) - free(data); - return 1; - } - -// PrintAndLogEx(INFO, "DATA | %s", sprint_hex(data+1000, 24) ); - - - // 64 or 256blocks. - if (datalen != 1024 && datalen != 4096) { - PrintAndLogEx(WARNING, "File content error. "); - free(data); - return 2; - } - - PrintAndLogEx(INFO, "Copying to magic card"); - - blockNum = 0; - while ( datalen ) { - - // switch on field and send magic sequence - if (blockNum == 0) flags = MAGIC_INIT + MAGIC_WUPC; - - // write - if (blockNum == 1) flags = 0; - - // Switch off field. - if (blockNum == 16 * 4 - 1) flags = MAGIC_HALT + MAGIC_OFF; - - if (mfCSetBlock(blockNum, data + (16 * blockNum), NULL, flags)) { - PrintAndLogEx(WARNING, "Can't set magic card block: %d", blockNum); - free(data); - return 3; - } - - datalen -= 16; - - printf("."); fflush(stdout); - blockNum++; - - // magic card type - mifare 1K - if (blockNum >= MIFARE_1K_MAXBLOCK ) break; - } - PrintAndLogEx(NORMAL, "\n"); - - // 64 or 256blocks. - if (blockNum != 16 * 4 && blockNum != 32 * 4 + 8 * 16){ - PrintAndLogEx(WARNING, "File content error. There must be 64 blocks"); - free(data); - return 4; - } - - PrintAndLogEx(SUCCESS, "Card loaded %d blocks from file", blockNum); - free(data); - return 0; -} - -int CmdHF14AMfCGetBlk(const char *Cmd) { - uint8_t data[16] = {0}; - uint8_t blockNo = 0; - int res; - memset(data, 0x00, sizeof(data)); - - char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_cgetblk(); - - blockNo = param_get8(Cmd, 0); - - PrintAndLogEx(NORMAL, "--block number:%2d ", blockNo); - - res = mfCGetBlock(blockNo, data, MAGIC_SINGLE); - if (res) { - PrintAndLogEx(WARNING, "Can't read block. error=%d", res); - return 1; - } - - PrintAndLogEx(NORMAL, "data: %s", sprint_hex(data, sizeof(data))); - - if (mfIsSectorTrailer(blockNo)) { - PrintAndLogEx(NORMAL, "Trailer decoded:"); - PrintAndLogEx(NORMAL, "Key A: %s", sprint_hex_inrow(data, 6)); - PrintAndLogEx(NORMAL, "Key B: %s", sprint_hex_inrow(&data[10], 6)); - int bln = mfFirstBlockOfSector(mfSectorNum(blockNo)); - int blinc = (mfNumBlocksPerSector(mfSectorNum(blockNo)) > 4) ? 5 : 1; - for (int i = 0; i < 4; i++) { - PrintAndLogEx(NORMAL, "Access block %d%s: %s", bln, ((blinc > 1) && (i < 3) ? "+" : "") , mfGetAccessConditionsDesc(i, &data[6])); - bln += blinc; - } - PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&data[9], 1)); - } - - return 0; -} - -int CmdHF14AMfCGetSc(const char *Cmd) { - uint8_t data[16] = {0}; - uint8_t sector = 0; - int i, res, flags; - - char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_cgetsc(); - - sector = param_get8(Cmd, 0); - if (sector > 39) { - PrintAndLogEx(WARNING, "Sector number must be less then 40"); - return 1; - } - - PrintAndLogEx(NORMAL, "\n # | data | Sector | %02d/ 0x%02X ", sector, sector); - PrintAndLogEx(NORMAL, "----+------------------------------------------------"); - uint8_t blocks = 4; - uint8_t start = sector * 4; - if ( sector > 32 ) { - blocks = 16; - start = 128 + ( sector - 32 ) * 16; - } - - flags = MAGIC_INIT + MAGIC_WUPC; - - for (i = 0; i < blocks; i++) { - if (i == 1) flags = 0; - if (i == blocks-1) flags = MAGIC_HALT + MAGIC_OFF; - - res = mfCGetBlock( start + i, data, flags); - if (res) { - PrintAndLogEx(WARNING, "Can't read block. %d error=%d", start + i, res); - return 1; - } - PrintAndLogEx(NORMAL, "%3d | %s", start + i, sprint_hex(data, 16)); - } - return 0; -} - -int CmdHF14AMfCSave(const char *Cmd) { - - char filename[FILE_PATH_SIZE]; - char * fnameptr = filename; - uint8_t *dump; - bool fillEmulator = false; - bool errors = false, hasname = false, useuid = false; - int i, len, flags; - uint8_t numblocks = 0, cmdp = 0; - uint16_t bytes = 0; - char ctmp; - - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - ctmp = tolower(param_getchar(Cmd, cmdp)); - switch (ctmp) { - case 'e': - useuid = true; - fillEmulator = true; - cmdp++; - break; - case 'h': - return usage_hf14_csave(); - case '0': - case '1': - case '2': - case '4': - numblocks = NumOfBlocks(ctmp); - bytes = numblocks * MFBLOCK_SIZE; - PrintAndLogEx(SUCCESS, "Saving magic mifare %cK", ctmp); - cmdp++; - break; - case 'u': - useuid = true; - hasname = true; - cmdp++; - break; - case 'o': - len = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); - if (len < 1) { - errors = true; - break; - } - - useuid = false; - hasname = true; - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - - if (!hasname && !fillEmulator) errors = true; - - if (errors || cmdp == 0) return usage_hf14_csave(); - - dump = calloc(bytes, sizeof(uint8_t)); - if (!dump) { - PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); - return 1; - } - memset(dump, 0, bytes); - - flags = MAGIC_INIT + MAGIC_WUPC; - for (i = 0; i < numblocks; i++) { - if (i == 1) flags = 0; - if (i == numblocks - 1) flags = MAGIC_HALT + MAGIC_OFF; - - if (mfCGetBlock(i, dump + (i*MFBLOCK_SIZE), flags)) { - PrintAndLogEx(WARNING, "Cant get block: %d", i); - free(dump); - return 2; - } - } - - if ( useuid ){ - fnameptr += sprintf(fnameptr, "hf-mf-"); - FillFileNameByUID(fnameptr, dump, "-dump", 4); - } - - if (fillEmulator) { - PrintAndLogEx(INFO, "uploading to emulator memory"); - for (i = 0; i < numblocks; i += 5) { - if (mfEmlSetMem(dump + (i*MFBLOCK_SIZE), i, 5)) { - PrintAndLogEx(WARNING, "Cant set emul block: %d", i); - } - printf("."); fflush(stdout); - } - PrintAndLogEx(NORMAL, "\n"); - PrintAndLogEx(SUCCESS, "uploaded %d bytes to emulator memory", bytes); - } - - saveFile(filename, "bin", dump, bytes); - saveFileEML(filename, "eml", dump, bytes, MFBLOCK_SIZE); - saveFileJSON(filename, "json", jsfCardMemory, dump, bytes); - free(dump); - return 0; -} - -//needs nt, ar, at, Data to decrypt -int CmdHf14AMfDecryptBytes(const char *Cmd){ - - char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_decryptbytes(); - - uint32_t nt = param_get32ex(Cmd,0,0,16); - uint32_t ar_enc = param_get32ex(Cmd,1,0,16); - uint32_t at_enc = param_get32ex(Cmd,2,0,16); - - int len = param_getlength(Cmd, 3); - if (len & 1 ) { - PrintAndLogEx(WARNING, "Uneven hex string length. LEN=%d", len); - return 1; - } - - PrintAndLogEx(NORMAL, "nt\t%08X", nt); - PrintAndLogEx(NORMAL, "ar enc\t%08X", ar_enc); - PrintAndLogEx(NORMAL, "at enc\t%08X", at_enc); - - uint8_t *data = calloc(len, sizeof(uint8_t)); - param_gethex_ex(Cmd, 3, data, &len); - len >>= 1; - tryDecryptWord( nt, ar_enc, at_enc, data, len); - free (data); - return 0; -} - -int CmdHf14AMfSetMod(const char *Cmd) { - uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - uint8_t mod = 2; - - char ctmp = param_getchar(Cmd, 0); - if (ctmp == '0') { - mod = 0; - } else if (ctmp == '1') { - mod = 1; - } - int gethexfail = param_gethex(Cmd, 1, key, 12); - if (mod == 2 || gethexfail) { - PrintAndLogEx(NORMAL, "Sets the load modulation strength of a MIFARE Classic EV1 card."); - PrintAndLogEx(NORMAL, "Usage: hf mf setmod <0|1> "); - PrintAndLogEx(NORMAL, " 0 = normal modulation"); - PrintAndLogEx(NORMAL, " 1 = strong modulation (default)"); - return 1; - } - - UsbCommand c = {CMD_MIFARE_SETMOD, {mod, 0, 0}}; - memcpy(c.d.asBytes, key, 6); - clearCommandBuffer(); - SendCommand(&c); - - UsbCommand resp; - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - uint8_t ok = resp.arg[0] & 0xff; - PrintAndLogEx(SUCCESS, "isOk:%02x", ok); - if (!ok) - PrintAndLogEx(FAILED, "Failed."); - } else { - PrintAndLogEx(WARNING, "Command execute timeout"); - } - return 0; -} - -// Mifare NACK bug detection -int CmdHf14AMfNack(const char *Cmd) { - - bool verbose = false; - char ctmp = tolower(param_getchar(Cmd, 0)); - if ( ctmp == 'h' ) return usage_hf14_nack(); - if ( ctmp == 'v' ) verbose = true; - - if ( verbose ) - PrintAndLogEx(INFO, "Started testing card for NACK bug. Press key to abort"); - - detect_classic_nackbug(verbose); - return 0; -} - -int CmdHF14AMfice(const char *Cmd) { - - uint8_t blockNo = 0; - uint8_t keyType = 0; - uint8_t trgBlockNo = 0; - uint8_t trgKeyType = 1; - bool slow = false; - bool initialize = true; - bool acquisition_completed = false; - uint8_t cmdp=0; - uint32_t flags = 0; - uint32_t total_num_nonces = 0; - char ctmp; - char filename[FILE_PATH_SIZE], *fptr; - FILE *fnonces = NULL; - UsbCommand resp; - - uint32_t part_limit = 3000; - uint32_t limit = 50000; - - while ((ctmp = param_getchar(Cmd, cmdp))) { - switch(tolower(ctmp)) - { - case 'h': - return usage_hf14_ice(); - case 'f': - param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); - cmdp++; - break; - case 'l': - limit = param_get32ex(Cmd, cmdp+1, 50000, 10); - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", ctmp); - usage_hf14_ice(); - return 1; - } - cmdp++; - } - - if(filename[0]=='\0') - { - fptr = GenerateFilename("hf-mf-","-nonces.bin"); - if (fptr == NULL) - return 1; - strcpy(filename, fptr); - } - - PrintAndLogEx(NORMAL, "Collecting %u nonces \n", limit); - - if ((fnonces = fopen(filename,"wb")) == NULL) { - PrintAndLogEx(WARNING, "Could not create file " _YELLOW_(%s),filename); - return 3; - } - - clearCommandBuffer(); - - uint64_t t1 = msclock(); - - do { - if (ukbhit()) { - int gc = getchar(); (void)gc; - PrintAndLogEx(INFO, "\naborted via keyboard!\n"); - break; - } - - flags = 0; - flags |= initialize ? 0x0001 : 0; - flags |= slow ? 0x0002 : 0; - UsbCommand c = {CMD_MIFARE_ACQUIRE_NONCES, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, flags}}; - clearCommandBuffer(); - SendCommand(&c); - - if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) goto out; - if (resp.arg[0]) goto out; - - uint32_t items = resp.arg[2]; - if (fnonces) { - fwrite(resp.d.asBytes, 1, items*4, fnonces); - fflush(fnonces); - } - - total_num_nonces += items; - if ( total_num_nonces > part_limit ) { - PrintAndLogEx(INFO, "Total nonces %u\n", total_num_nonces); - part_limit += 3000; - } - - acquisition_completed = ( total_num_nonces > limit); - - initialize = false; - - } while (!acquisition_completed); - -out: - PrintAndLogEx(SUCCESS, "time: %" PRIu64 " seconds\n", (msclock()-t1)/1000); - - if ( fnonces ) { - fflush(fnonces); - fclose(fnonces); - } - - UsbCommand c = {CMD_MIFARE_ACQUIRE_NONCES, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, 4}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; -} - -int CmdHF14AMfAuth4(const char *Cmd) { - uint8_t keyn[20] = {0}; - int keynlen = 0; - uint8_t key[16] = {0}; - int keylen = 0; - - CLIParserInit("hf mf auth4", - "Executes AES authentication command in ISO14443-4", - "Usage:\n\thf mf auth4 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n" - "\thf mf auth4 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -> executes authentication\n"); - - void* argtable[] = { - arg_param_begin, - arg_str1(NULL, NULL, "", NULL), - arg_str1(NULL, NULL, "", NULL), - arg_param_end - }; - CLIExecWithReturn(Cmd, argtable, true); - - CLIGetHexWithReturn(1, keyn, &keynlen); - CLIGetHexWithReturn(2, key, &keylen); - CLIParserFree(); - - if (keynlen != 2) { - PrintAndLogEx(ERR, " must be 2 bytes long instead of: %d", keynlen); - return 1; - } - - if (keylen != 16) { - PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); - return 1; - } - - return MifareAuth4(NULL, keyn, key, true, false, true); -} - -// https://www.nxp.com/docs/en/application-note/AN10787.pdf -int CmdHF14AMfMAD(const char *cmd) { - - CLIParserInit("hf mf mad", - "Checks and prints Mifare Application Directory (MAD)", - "Usage:\n\thf mf mad -> shows MAD if exists\n" - "\thf mf mad -a 03e1 -k ffffffffffff -b -> shows NDEF data if exists. read card with custom key and key B\n"); - - void* argtable[] = { - arg_param_begin, - arg_lit0("vV", "verbose", "show technical data"), - arg_str0("aA", "aid", "print all sectors with aid", NULL), - arg_str0("kK", "key", "key for printing sectors", NULL), - arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, true); - bool verbose = arg_get_lit(1); - uint8_t aid[2] = {0}; - int aidlen; - CLIGetHexWithReturn(2, aid, &aidlen); - uint8_t key[6] = {0}; - int keylen; - CLIGetHexWithReturn(3, key, &keylen); - bool keyB = arg_get_lit(4); - - CLIParserFree(); - - if (aidlen != 2 && keylen > 0) { - PrintAndLogEx(WARNING, "do not need a key without aid."); - } - - uint8_t sector0[16 * 4] = {0}; - uint8_t sector10[16 * 4] = {0}; - if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0)) { - PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); - return 2; - } - - if (verbose) { - for(int i = 0; i < 4; i ++) - PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(§or0[i * 16], 16)); - } - - bool haveMAD2 = false; - MAD1DecodeAndPrint(sector0, verbose, &haveMAD2); - - if (haveMAD2) { - if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10)) { - PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); - return 2; - } - - MAD2DecodeAndPrint(sector10, verbose); - } - - if (aidlen == 2) { - uint16_t aaid = (aid[0] << 8) + aid[1]; - PrintAndLogEx(NORMAL, "\n-------------- AID 0x%04x ---------------", aaid); - - uint16_t mad[7 + 8 + 8 + 8 + 8] = {0}; - size_t madlen = 0; - if (MADDecode(sector0, sector10, mad, &madlen)) { - PrintAndLogEx(ERR, "can't decode mad."); - return 10; - } - - uint8_t akey[6] = {0}; - memcpy(akey, g_mifare_ndef_key, 6); - if (keylen == 6) { - memcpy(akey, key, 6); - } - - for (int i = 0; i < madlen; i++) { - if (aaid == mad[i]) { - uint8_t vsector[16 * 4] = {0}; - if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, akey, vsector)) { - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(ERR, "read sector %d error.", i + 1); - return 2; - } - - for(int j = 0; j < (verbose ? 4 : 3); j ++) - PrintAndLogEx(NORMAL, " [%03d] %s", (i + 1) * 4 + j, sprint_hex(&vsector[j * 16], 16)); - } - } - } - - return 0; -} - -int CmdHFMFNDEF(const char *cmd) { - - CLIParserInit("hf mf ndef", - "Prints NFC Data Exchange Format (NDEF)", - "Usage:\n\thf mf ndef -> shows NDEF data\n" - "\thf mf ndef -a 03e1 -k ffffffffffff -b -> shows NDEF data with custom AID, key and with key B\n"); - - void* argtable[] = { - arg_param_begin, - arg_litn("vV", "verbose", 0, 2, "show technical data"), - arg_str0("aA", "aid", "replace default aid for NDEF", NULL), - arg_str0("kK", "key", "replace default key for NDEF", NULL), - arg_lit0("bB", "keyb", "use key B for access sectors (by default: key A)"), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, true); - - bool verbose = arg_get_lit(1); - bool verbose2 = arg_get_lit(1) > 1; - uint8_t aid[2] = {0}; - int aidlen; - CLIGetHexWithReturn(2, aid, &aidlen); - uint8_t key[6] = {0}; - int keylen; - CLIGetHexWithReturn(3, key, &keylen); - bool keyB = arg_get_lit(4); - - CLIParserFree(); - - uint16_t ndefAID = 0x03e1; - if (aidlen == 2) - ndefAID = (aid[0] << 8) + aid[1]; - - uint8_t ndefkey[6] = {0}; - memcpy(ndefkey, g_mifare_ndef_key, 6); - if (keylen == 6) { - memcpy(ndefkey, key, 6); - } - - uint8_t sector0[16 * 4] = {0}; - uint8_t sector10[16 * 4] = {0}; - uint8_t data[4096] = {0}; - int datalen = 0; - - PrintAndLogEx(NORMAL, ""); - - if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0)) { - PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); - return 2; - } - - bool haveMAD2 = false; - int res = MADCheck(sector0, NULL, verbose, &haveMAD2); - if (res) { - PrintAndLogEx(ERR, "MAD error %d.", res); - return res; - } - - if (haveMAD2) { - if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10)) { - PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); - return 2; - } - } - - uint16_t mad[7 + 8 + 8 + 8 + 8] = {0}; - size_t madlen = 0; - if (MADDecode(sector0, (haveMAD2 ? sector10 : NULL), mad, &madlen)) { - PrintAndLogEx(ERR, "can't decode mad."); - return 10; - } - - printf("data reading:"); - for (int i = 0; i < madlen; i++) { - if (ndefAID == mad[i]) { - uint8_t vsector[16 * 4] = {0}; - if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, ndefkey, vsector)) { - PrintAndLogEx(ERR, "read sector %d error.", i + 1); - return 2; - } - - memcpy(&data[datalen], vsector, 16 * 3); - datalen += 16 * 3; - - printf("."); - } - } - printf(" OK\n"); - - if (!datalen) { - PrintAndLogEx(ERR, "no NDEF data."); - return 11; - } - - if (verbose2) { - PrintAndLogEx(NORMAL, "NDEF data:"); - dump_buffer(data, datalen, stdout, 1); - } - - NDEFDecodeAndPrint(data, datalen, verbose); - - return 0; -} - -int CmdHF14AMfList(const char *Cmd) { - CmdTraceList("mf"); - return 0; -} - -static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"list", CmdHF14AMfList, 0, "[Deprecated] List ISO 14443-a / Mifare history"}, - {"darkside", CmdHF14AMfDarkside, 0, "Darkside attack. read parity error messages."}, - {"nested", CmdHF14AMfNested, 0, "Nested attack. Test nested authentication"}, - {"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"}, - {"keybrute", CmdHF14AMfKeyBrute, 0, "J_Run's 2nd phase of multiple sector nested authentication key recovery"}, - {"nack", CmdHf14AMfNack, 0, "Test for Mifare NACK bug"}, - {"chk", CmdHF14AMfChk, 0, "Check keys"}, - {"fchk", CmdHF14AMfChk_fast, 0, "Check keys fast, targets all keys on card"}, - {"decrypt", CmdHf14AMfDecryptBytes, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"}, - {"-----------", CmdHelp, 1, ""}, - {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, - {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"}, - {"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"}, - {"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"}, - {"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"}, - {"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"}, - {"setmod", CmdHf14AMfSetMod, 0, "Set MIFARE Classic EV1 load modulation strength"}, - {"auth4", CmdHF14AMfAuth4, 0, "ISO14443-4 AES authentication"}, -// {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"}, - {"-----------", CmdHelp, 1, ""}, - {"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE card"}, - {"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory block"}, - {"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"}, - {"eset", CmdHF14AMfESet, 0, "Set simulator memory block"}, - {"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"}, - {"esave", CmdHF14AMfESave, 0, "Save to file emul dump"}, - {"ecfill", CmdHF14AMfECFill, 0, "Fill simulator memory with help of keys from simulator"}, - {"ekeyprn", CmdHF14AMfEKeyPrn, 0, "Print keys from simulator memory"}, - {"-----------", CmdHelp, 1, ""}, - {"csetuid", CmdHF14AMfCSetUID, 0, "Set UID for magic Chinese card"}, - {"csetblk", CmdHF14AMfCSetBlk, 0, "Write block - Magic Chinese card"}, - {"cgetblk", CmdHF14AMfCGetBlk, 0, "Read block - Magic Chinese card"}, - {"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"}, - {"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"}, - {"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"}, - {"-----------", CmdHelp, 1, ""}, - {"mad", CmdHF14AMfMAD, 0, "Checks and prints MAD"}, - {"ndef", CmdHFMFNDEF, 0, "Prints NDEF records from card"}, - - {"ice", CmdHF14AMfice, 0, "collect Mifare Classic nonces to file"}, - {NULL, NULL, 0, NULL} -}; - -int CmdHFMF(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; -} - -int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; -} +//----------------------------------------------------------------------------- +// Copyright (C) 2011,2012 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency MIFARE commands +//----------------------------------------------------------------------------- + +#include "cmdhfmf.h" +#include "mifare/mifare4.h" +#include "mifare/mad.h" +#include "mifare/ndef.h" + + +#define MFBLOCK_SIZE 16 + +#define MIFARE_4K_MAXBLOCK 256 +#define MIFARE_2K_MAXBLOCK 128 +#define MIFARE_1K_MAXBLOCK 64 +#define MIFARE_MINI_MAXBLOCK 20 + +#define MIFARE_MINI_MAXSECTOR 5 +#define MIFARE_1K_MAXSECTOR 16 +#define MIFARE_2K_MAXSECTOR 32 +#define MIFARE_4K_MAXSECTOR 40 + +static int CmdHelp(const char *Cmd); + +int usage_hf14_ice(void){ + PrintAndLogEx(NORMAL, "Usage: hf mf ice [l] [f] "); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " l nonces to be collected"); + PrintAndLogEx(NORMAL, " f save nonces to instead of hf-mf--nonces.bin"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf ice"); + PrintAndLogEx(NORMAL, " hf mf ice f nonces.bin"); + return 0; +} + +int usage_hf14_dump(void){ + PrintAndLogEx(NORMAL, "Usage: hf mf dump [card memory] k f "); + PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); + PrintAndLogEx(NORMAL, " k : key filename, if no given, UID will be used as filename"); + PrintAndLogEx(NORMAL, " f : data filename, if no given, UID will be used as filename"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf dump"); + PrintAndLogEx(NORMAL, " hf mf dump 4"); + return 0; +} + +int usage_hf14_mifare(void){ + PrintAndLogEx(NORMAL, "Usage: hf mf darkside [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " (Optional) target other block"); + PrintAndLogEx(NORMAL, " (optional) target key type"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf darkside"); + PrintAndLogEx(NORMAL, " hf mf darkside 16"); + PrintAndLogEx(NORMAL, " hf mf darkside 16 B"); + return 0; +} +int usage_hf14_mf1ksim(void){ + PrintAndLogEx(NORMAL, "Usage: hf mf sim [h] u n [i] [x] [e] [v]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " u (Optional) UID 4,7 or 10bytes. If not specified, the UID 4b from emulator memory will be used"); + PrintAndLogEx(NORMAL, " n (Optional) Automatically exit simulation after blocks have been read by reader. 0 = infinite"); + PrintAndLogEx(NORMAL, " i (Optional) Interactive, means that console will not be returned until simulation finishes or is aborted"); + PrintAndLogEx(NORMAL, " x (Optional) Crack, performs the 'reader attack', nr/ar attack against a reader"); + PrintAndLogEx(NORMAL, " e (Optional) Fill simulator keys from found keys"); + PrintAndLogEx(NORMAL, " v (Optional) Verbose"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf sim u 0a0a0a0a"); + PrintAndLogEx(NORMAL, " hf mf sim u 11223344556677"); + PrintAndLogEx(NORMAL, " hf mf sim u 112233445566778899AA"); + PrintAndLogEx(NORMAL, " hf mf sim u 11223344 i x"); + return 0; +} +int usage_hf14_dbg(void){ + PrintAndLogEx(NORMAL, "Usage: hf mf dbg [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " (Optional) see list for valid levels"); + PrintAndLogEx(NORMAL, " 0 - no debug messages"); + PrintAndLogEx(NORMAL, " 1 - error messages"); + PrintAndLogEx(NORMAL, " 2 - plus information messages"); + PrintAndLogEx(NORMAL, " 3 - plus debug messages"); + PrintAndLogEx(NORMAL, " 4 - print even debug messages in timing critical functions"); + PrintAndLogEx(NORMAL, " Note: this option therefore may cause malfunction itself"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf dbg 3"); + return 0; +} +int usage_hf14_sniff(void){ + PrintAndLogEx(NORMAL, "It continuously gets data from the field and saves it to: log, emulator, emulator file."); + PrintAndLogEx(NORMAL, "Usage: hf mf sniff [h] [l] [d] [f]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " l save encrypted sequence to logfile `uid.log`"); + PrintAndLogEx(NORMAL, " d decrypt sequence and put it to log file `uid.log`"); +// PrintAndLogEx(NORMAL, " n/a e decrypt sequence, collect read and write commands and save the result of the sequence to emulator memory"); + PrintAndLogEx(NORMAL, " f decrypt sequence, collect read and write commands and save the result of the sequence to emulator dump file `uid.eml`"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " hf mf sniff l d f"); + return 0; +} +int usage_hf14_nested(void){ + PrintAndLogEx(NORMAL, "Usage:"); + PrintAndLogEx(NORMAL, " all sectors: hf mf nested [t,d]"); + PrintAndLogEx(NORMAL, " one sector: hf mf nested o "); + PrintAndLogEx(NORMAL, " [t]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " card memory - 0 - MINI(320 bytes), 1 - 1K, 2 - 2K, 4 - 4K, - 1K"); + PrintAndLogEx(NORMAL, " t transfer keys into emulator memory"); + PrintAndLogEx(NORMAL, " d write keys to binary file `hf-mf--key.bin`"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf nested 1 0 A FFFFFFFFFFFF "); + PrintAndLogEx(NORMAL, " hf mf nested 1 0 A FFFFFFFFFFFF t "); + PrintAndLogEx(NORMAL, " hf mf nested 1 0 A FFFFFFFFFFFF d "); + PrintAndLogEx(NORMAL, " hf mf nested o 0 A FFFFFFFFFFFF 4 A"); + return 0; +} +int usage_hf14_hardnested(void){ + PrintAndLogEx(NORMAL, "Usage:"); + PrintAndLogEx(NORMAL, " hf mf hardnested "); + PrintAndLogEx(NORMAL, " [known target key (12 hex symbols)] [w] [s]"); + PrintAndLogEx(NORMAL, " or hf mf hardnested r [known target key]"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " w acquire nonces and UID, and write them to binary file with default name hf-mf--nonces.bin"); + PrintAndLogEx(NORMAL, " s slower acquisition (required by some non standard cards)"); + PrintAndLogEx(NORMAL, " r read hf-mf--nonces.bin if tag present, otherwise read nonces.bin, then start attack"); + PrintAndLogEx(NORMAL, " u read/write hf-mf--nonces.bin instead of default name"); + PrintAndLogEx(NORMAL, " f read/write instead of default name"); + PrintAndLogEx(NORMAL, " t tests?"); + PrintAndLogEx(NORMAL, " i set type of SIMD instructions. Without this flag programs autodetect it."); + PrintAndLogEx(NORMAL, " i 5 = AVX512"); + PrintAndLogEx(NORMAL, " i 2 = AVX2"); + PrintAndLogEx(NORMAL, " i a = AVX"); + PrintAndLogEx(NORMAL, " i s = SSE2"); + PrintAndLogEx(NORMAL, " i m = MMX"); + PrintAndLogEx(NORMAL, " i n = none (use CPU regular instruction set)"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf hardnested 0 A FFFFFFFFFFFF 4 A"); + PrintAndLogEx(NORMAL, " hf mf hardnested 0 A FFFFFFFFFFFF 4 A w"); + PrintAndLogEx(NORMAL, " hf mf hardnested 0 A FFFFFFFFFFFF 4 A f nonces.bin w s"); + PrintAndLogEx(NORMAL, " hf mf hardnested r"); + PrintAndLogEx(NORMAL, " hf mf hardnested r a0a1a2a3a4a5"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Add the known target key to check if it is present in the remaining key space:"); + PrintAndLogEx(NORMAL, " hf mf hardnested 0 A A0A1A2A3A4A5 4 A FFFFFFFFFFFF"); + return 0; +} +int usage_hf14_chk(void){ + PrintAndLogEx(NORMAL, "Usage: hf mf chk [h] |<*card memory> [t|d] [] []"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " * all sectors based on card memory, other values then below defaults to 1k"); + PrintAndLogEx(NORMAL, " 0 - MINI(320 bytes)"); + PrintAndLogEx(NORMAL, " 1 - 1K"); + PrintAndLogEx(NORMAL, " 2 - 2K"); + PrintAndLogEx(NORMAL, " 4 - 4K"); + PrintAndLogEx(NORMAL, " d write keys to binary file"); + PrintAndLogEx(NORMAL, " t write keys to emulator memory\n"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf chk 0 A 1234567890ab keys.dic -- target block 0, Key A"); + PrintAndLogEx(NORMAL, " hf mf chk *1 ? t -- target all blocks, all keys, 1K, write to emul"); + PrintAndLogEx(NORMAL, " hf mf chk *1 ? d -- target all blocks, all keys, 1K, write to file"); + return 0; +} +int usage_hf14_chk_fast(void){ + PrintAndLogEx(NORMAL, "This is a improved checkkeys method speedwise. It checks Mifare Classic tags sector keys against a dictionary file with keys"); + PrintAndLogEx(NORMAL, "Usage: hf mf fchk [h] [t|d|f] [] []"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " all sectors based on card memory, other values than below defaults to 1k"); + PrintAndLogEx(NORMAL, " 0 - MINI(320 bytes)"); + PrintAndLogEx(NORMAL, " 1 - 1K "); + PrintAndLogEx(NORMAL, " 2 - 2K"); + PrintAndLogEx(NORMAL, " 4 - 4K"); + PrintAndLogEx(NORMAL, " d write keys to binary file"); + PrintAndLogEx(NORMAL, " t write keys to emulator memory"); + PrintAndLogEx(NORMAL, " m use dictionary from flashmemory\n"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf fchk 1 1234567890ab keys.dic -- target 1K using key 1234567890ab, using dictionary file"); + PrintAndLogEx(NORMAL, " hf mf fchk 1 t -- target 1K, write to emulator memory"); + PrintAndLogEx(NORMAL, " hf mf fchk 1 d -- target 1K, write to file"); +#ifdef WITH_FLASH + PrintAndLogEx(NORMAL, " hf mf fchk 1 m -- target 1K, use dictionary from flashmemory"); +#endif + return 0; +} +int usage_hf14_keybrute(void){ + PrintAndLogEx(NORMAL, "J_Run's 2nd phase of multiple sector nested authentication key recovery"); + PrintAndLogEx(NORMAL, "You have a known 4 last bytes of a key recovered with mf_nonce_brute tool."); + PrintAndLogEx(NORMAL, "First 2 bytes of key will be bruteforced"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " ---[ This attack is obsolete, try hardnested instead ]---"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: hf mf keybrute [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " target block number"); + PrintAndLogEx(NORMAL, " target key type"); + PrintAndLogEx(NORMAL, " candidate key from mf_nonce_brute tool"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf keybrute 1 A 000011223344"); + return 0; +} +int usage_hf14_restore(void){ + PrintAndLogEx(NORMAL, "Usage: hf mf restore [card memory] u k f "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); + PrintAndLogEx(NORMAL, " u : uid, try to restore from hf-mf--key.bin and hf-mf--data.bin"); + PrintAndLogEx(NORMAL, " k : key filename, specific the full filename of key file"); + PrintAndLogEx(NORMAL, " f : data filename, specific the full filename of data file"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf restore -- read the UID from tag first, then restore from hf-mf--key.bin and and hf-mf--data.bin"); + PrintAndLogEx(NORMAL, " hf mf restore 1 u 12345678 -- restore from hf-mf-12345678-key.bin and hf-mf-12345678-data.bin"); + PrintAndLogEx(NORMAL, " hf mf restore 1 u 12345678 k dumpkey.bin -- restore from dumpkey.bin and hf-mf-12345678-data.bin"); + PrintAndLogEx(NORMAL, " hf mf restore 4 -- read the UID from tag with 4K memory first, then restore from hf-mf--key.bin and and hf-mf--data.bin"); + return 0; +} +int usage_hf14_decryptbytes(void){ + PrintAndLogEx(NORMAL, "Decrypt Crypto-1 encrypted bytes given some known state of crypto. See tracelog to gather needed values\n"); + PrintAndLogEx(NORMAL, "Usage: hf mf decrypt [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " reader nonce"); + PrintAndLogEx(NORMAL, " encrypted reader response"); + PrintAndLogEx(NORMAL, " encrypted tag response"); + PrintAndLogEx(NORMAL, " encrypted data, taken directly after at_enc and forward"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf decrypt b830049b 9248314a 9280e203 41e586f9\n"); + PrintAndLogEx(NORMAL, " this sample decrypts 41e586f9 -> 3003999a Annotated: 30 03 [99 9a] auth block 3 [crc]"); + return 0; +} + +int usage_hf14_eget(void){ + PrintAndLogEx(NORMAL, "Usage: hf mf eget "); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf eget 0 "); + return 0; +} +int usage_hf14_eclr(void){ + PrintAndLogEx(NORMAL, "It set card emulator memory to empty data blocks and key A/B FFFFFFFFFFFF \n"); + PrintAndLogEx(NORMAL, "Usage: hf mf eclr"); + return 0; +} +int usage_hf14_eset(void){ + PrintAndLogEx(NORMAL, "Usage: hf mf eset "); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf eset 1 000102030405060708090a0b0c0d0e0f "); + return 0; +} +int usage_hf14_eload(void){ + PrintAndLogEx(NORMAL, "It loads emul dump from the file `filename.eml`"); + PrintAndLogEx(NORMAL, "Usage: hf mf eload [card memory] [numblocks]"); + PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K, u = UL"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf eload filename"); + PrintAndLogEx(NORMAL, " hf mf eload 4 filename"); + return 0; +} +int usage_hf14_esave(void){ + PrintAndLogEx(NORMAL, "It saves emul dump into the file `filename.eml` or `cardID.eml`"); + PrintAndLogEx(NORMAL, " Usage: hf mf esave [card memory] [file name w/o `.eml`]"); + PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf esave "); + PrintAndLogEx(NORMAL, " hf mf esave 4"); + PrintAndLogEx(NORMAL, " hf mf esave 4 filename"); + return 0; +} +int usage_hf14_ecfill(void){ + PrintAndLogEx(NORMAL, "Read card and transfer its data to emulator memory."); + PrintAndLogEx(NORMAL, "Keys must be laid in the emulator memory. \n"); + PrintAndLogEx(NORMAL, "Usage: hf mf ecfill [card memory]"); + PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf ecfill A"); + PrintAndLogEx(NORMAL, " hf mf ecfill A 4"); + return 0; +} +int usage_hf14_ekeyprn(void){ + PrintAndLogEx(NORMAL, "It prints the keys loaded in the emulator memory"); + PrintAndLogEx(NORMAL, "Usage: hf mf ekeyprn [card memory]"); + PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf ekeyprn 1"); + return 0; +} + +int usage_hf14_csetuid(void){ + PrintAndLogEx(NORMAL, "Set UID, ATQA, and SAK for magic Chinese card. Only works with magic cards"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: hf mf csetuid [h] [ATQA 4 hex symbols] [SAK 2 hex symbols] [w]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " w wipe card before writing"); + PrintAndLogEx(NORMAL, " UID 8 hex symbols"); + PrintAndLogEx(NORMAL, " ATQA 4 hex symbols"); + PrintAndLogEx(NORMAL, " SAK 2 hex symbols"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf csetuid 01020304"); + PrintAndLogEx(NORMAL, " hf mf csetuid 01020304 0004 08 w"); + return 0; +} +int usage_hf14_csetblk(void){ + PrintAndLogEx(NORMAL, "Set block data for magic Chinese card. Only works with magic cards"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: hf mf csetblk [h] [w]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " w wipe card before writing"); + PrintAndLogEx(NORMAL, " block number"); + PrintAndLogEx(NORMAL, " block data to write (32 hex symbols)"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf csetblk 1 01020304050607080910111213141516"); + PrintAndLogEx(NORMAL, " hf mf csetblk 1 01020304050607080910111213141516 w"); + return 0; +} +int usage_hf14_cload(void){ + PrintAndLogEx(NORMAL, "It loads magic Chinese card from the file `filename.eml`"); + PrintAndLogEx(NORMAL, "or from emulator memory"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: hf mf cload [h] [e] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " e load card with data from emulator memory"); + PrintAndLogEx(NORMAL, " j load card with data from json file"); + PrintAndLogEx(NORMAL, " b load card with data from binary file"); + PrintAndLogEx(NORMAL, " load card with data from eml file"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf cload mydump"); + PrintAndLogEx(NORMAL, " hf mf cload e"); + return 0; +} +int usage_hf14_cgetblk(void){ + PrintAndLogEx(NORMAL, "Get block data from magic Chinese card. Only works with magic cards\n"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: hf mf cgetblk [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " block number"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf cgetblk 1"); + return 0; +} +int usage_hf14_cgetsc(void){ + PrintAndLogEx(NORMAL, "Get sector data from magic Chinese card. Only works with magic cards\n"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: hf mf cgetsc [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " sector number"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf cgetsc 0"); + return 0; +} +int usage_hf14_csave(void){ + PrintAndLogEx(NORMAL, "It saves `magic Chinese` card dump into the file `filename.eml` or `cardID.eml`"); + PrintAndLogEx(NORMAL, "or into emulator memory"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: hf mf csave [h] [e] [u] [card memory] i "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " e save data to emulator memory"); + PrintAndLogEx(NORMAL, " u save data to file, use carduid as filename"); + PrintAndLogEx(NORMAL, " card memory 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); + PrintAndLogEx(NORMAL, " o save data to file"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf csave u 1"); + PrintAndLogEx(NORMAL, " hf mf csave e 1"); + PrintAndLogEx(NORMAL, " hf mf csave 4 o filename"); + return 0; +} +int usage_hf14_nack(void) { + PrintAndLogEx(NORMAL, "Test a mifare classic based card for the NACK bug."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: hf mf nack [h] [v]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " v verbose"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf nack"); + return 0; +} + +int GetHFMF14AUID(uint8_t *uid, int *uidlen) { + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { + PrintAndLogEx(WARNING, "iso14443a card select failed"); + DropField(); + return 0; + } + + iso14a_card_select_t card; + memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); + memcpy(uid, card.uid, card.uidlen * sizeof(uint8_t)); + *uidlen = card.uidlen; + return 1; +} + +char * GenerateFilename(const char *prefix, const char *suffix){ + uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; + int uidlen=0; + char * fptr = calloc (sizeof (char) * (strlen(prefix) + strlen(suffix)) + sizeof(uid)*2 + 1, sizeof(uint8_t)); + + GetHFMF14AUID(uid, &uidlen); + if (!uidlen) { + PrintAndLogEx(WARNING, "No tag found."); + free(fptr); + return NULL; + } + + strcpy(fptr, prefix); + FillFileNameByUID(fptr, uid, suffix, uidlen); + return fptr; +} + +int CmdHF14AMfDarkside(const char *Cmd) { + uint8_t blockno = 0, key_type = MIFARE_AUTH_KEYA; + uint64_t key = 0; + + char cmdp = tolower(param_getchar(Cmd, 0)); + if ( cmdp == 'h' ) return usage_hf14_mifare(); + + blockno = param_get8(Cmd, 0); + + cmdp = tolower(param_getchar(Cmd, 1)); + if (cmdp == 'b') + key_type = MIFARE_AUTH_KEYB; + + int isOK = mfDarkside(blockno, key_type, &key); + PrintAndLogEx(NORMAL, ""); + switch (isOK) { + case -1 : PrintAndLogEx(WARNING, "button pressed. Aborted."); return 1; + case -2 : PrintAndLogEx(FAILED, "card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests)."); return 1; + case -3 : PrintAndLogEx(FAILED, "card is not vulnerable to Darkside attack (its random number generator is not predictable)."); return 1; + case -4 : PrintAndLogEx(FAILED, "card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown"); + PrintAndLogEx(FAILED, "generating polynomial with 16 effective bits only, but shows unexpected behaviour."); return 1; + case -5 : PrintAndLogEx(WARNING, "aborted via keyboard."); return 1; + default : PrintAndLogEx(SUCCESS, "found valid key: %012" PRIx64 "\n", key); break; + } + PrintAndLogEx(NORMAL, ""); + return 0; +} + +int CmdHF14AMfWrBl(const char *Cmd) { + uint8_t blockNo = 0; + uint8_t keyType = 0; + uint8_t key[6] = {0, 0, 0, 0, 0, 0}; + uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; + char cmdp = 0x00; + + if (strlen(Cmd) < 3) { + PrintAndLogEx(NORMAL, "Usage: hf mf wrbl "); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F"); + return 0; + } + + blockNo = param_get8(Cmd, 0); + cmdp = tolower(param_getchar(Cmd, 1)); + if (cmdp == 0x00) { + PrintAndLogEx(NORMAL, "Key type must be A or B"); + return 1; + } + + if (cmdp != 'a') + keyType = 1; + + if (param_gethex(Cmd, 2, key, 12)) { + PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); + return 1; + } + + if (param_gethex(Cmd, 3, bldata, 32)) { + PrintAndLogEx(NORMAL, "Block data must include 32 HEX symbols"); + return 1; + } + + PrintAndLogEx(NORMAL, "--block no:%d, key type:%c, key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6)); + PrintAndLogEx(NORMAL, "--data: %s", sprint_hex(bldata, 16)); + + UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}}; + memcpy(c.d.asBytes, key, 6); + memcpy(c.d.asBytes + 10, bldata, 16); + clearCommandBuffer(); + SendCommand(&c); + + UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + PrintAndLogEx(NORMAL, "isOk:%02x", isOK); + } else { + PrintAndLogEx(NORMAL, "Command execute timeout"); + } + + return 0; +} + +int CmdHF14AMfRdBl(const char *Cmd) { + uint8_t blockNo = 0; + uint8_t keyType = 0; + uint8_t key[6] = {0, 0, 0, 0, 0, 0}; + char cmdp = 0x00; + + if (strlen(Cmd)<3) { + PrintAndLogEx(NORMAL, "Usage: hf mf rdbl "); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf rdbl 0 A FFFFFFFFFFFF "); + return 0; + } + + blockNo = param_get8(Cmd, 0); + cmdp = tolower(param_getchar(Cmd, 1)); + if (cmdp == 0x00) { + PrintAndLogEx(NORMAL, "Key type must be A or B"); + return 1; + } + + if (cmdp != 'a') + keyType = 1; + + if (param_gethex(Cmd, 2, key, 12)) { + PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); + return 1; + } + PrintAndLogEx(NORMAL, "--block no:%d, key type:%c, key:%s ", blockNo, keyType?'B':'A', sprint_hex(key, 6)); + + UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}}; + memcpy(c.d.asBytes, key, 6); + clearCommandBuffer(); + SendCommand(&c); + + UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + uint8_t *data = resp.d.asBytes; + + if (isOK) { + PrintAndLogEx(NORMAL, "isOk:%02x data:%s", isOK, sprint_hex(data, 16)); + } else { + PrintAndLogEx(NORMAL, "isOk:%02x", isOK); + return 1; + } + + if (mfIsSectorTrailer(blockNo) && (data[6] || data[7] || data[8])) { + PrintAndLogEx(NORMAL, "Trailer decoded:"); + int bln = mfFirstBlockOfSector(mfSectorNum(blockNo)); + int blinc = (mfNumBlocksPerSector(mfSectorNum(blockNo)) > 4) ? 5 : 1; + for (int i = 0; i < 4; i++) { + PrintAndLogEx(NORMAL, "Access block %d%s: %s", bln, ((blinc > 1) && (i < 3) ? "+" : "") , mfGetAccessConditionsDesc(i, &data[6])); + bln += blinc; + } + PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&data[9], 1)); + } + } else { + PrintAndLogEx(WARNING, "Command execute timeout"); + return 2; + } + + return 0; +} + +int CmdHF14AMfRdSc(const char *Cmd) { + int i; + uint8_t sectorNo = 0; + uint8_t keyType = 0; + uint8_t key[6] = {0, 0, 0, 0, 0, 0}; + uint8_t isOK = 0; + uint8_t *data = NULL; + char cmdp = 0x00; + + if (strlen(Cmd) < 3) { + PrintAndLogEx(NORMAL, "Usage: hf mf rdsc "); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf mf rdsc 0 A FFFFFFFFFFFF "); + return 0; + } + + sectorNo = param_get8(Cmd, 0); + if (sectorNo > MIFARE_4K_MAXSECTOR ) { + PrintAndLogEx(NORMAL, "Sector number must be less than 40"); + return 1; + } + + cmdp = tolower(param_getchar(Cmd, 1)); + if (cmdp != 'a' && cmdp != 'b') { + PrintAndLogEx(NORMAL, "Key type must be A or B"); + return 1; + } + + if (cmdp != 'a') + keyType = 1; + + if (param_gethex(Cmd, 2, key, 12)) { + PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); + return 1; + } + PrintAndLogEx(NORMAL, "--sector no:%d key type:%c key:%s ", sectorNo, keyType?'B':'A', sprint_hex(key, 6)); + + UsbCommand c = {CMD_MIFARE_READSC, {sectorNo, keyType, 0}}; + memcpy(c.d.asBytes, key, 6); + clearCommandBuffer(); + SendCommand(&c); + PrintAndLogEx(NORMAL, ""); + + UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + isOK = resp.arg[0] & 0xff; + data = resp.d.asBytes; + + PrintAndLogEx(NORMAL, "isOk:%02x", isOK); + if (isOK) { + for (i = 0; i < (sectorNo<32?3:15); i++) { + PrintAndLogEx(NORMAL, "data : %s", sprint_hex(data + i * 16, 16)); + } + PrintAndLogEx(NORMAL, "trailer: %s", sprint_hex(data + (sectorNo<32?3:15) * 16, 16)); + + PrintAndLogEx(NORMAL, "Trailer decoded:"); + int bln = mfFirstBlockOfSector(sectorNo); + int blinc = (mfNumBlocksPerSector(sectorNo) > 4) ? 5 : 1; + for (i = 0; i < 4; i++) { + PrintAndLogEx(NORMAL, "Access block %d%s: %s", bln, ((blinc > 1) && (i < 3) ? "+" : "") , mfGetAccessConditionsDesc(i, &(data + (sectorNo<32?3:15) * 16)[6])); + bln += blinc; + } + PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&(data + (sectorNo<32?3:15) * 16)[9], 1)); + } + } else { + PrintAndLogEx(WARNING, "Command execute timeout"); + } + + return 0; +} + +uint16_t NumOfBlocks(char card){ + switch(card){ + case '0' : return MIFARE_MINI_MAXBLOCK; + case '1' : return MIFARE_1K_MAXBLOCK; + case '2' : return MIFARE_2K_MAXBLOCK; + case '4' : return MIFARE_4K_MAXBLOCK; + default : return MIFARE_1K_MAXBLOCK; + } +} +uint8_t NumOfSectors(char card){ + switch(card){ + case '0' : return MIFARE_MINI_MAXSECTOR; + case '1' : return MIFARE_1K_MAXSECTOR; + case '2' : return MIFARE_2K_MAXSECTOR; + case '4' : return MIFARE_4K_MAXSECTOR; + default : return MIFARE_1K_MAXSECTOR; + } +} + +uint8_t FirstBlockOfSector(uint8_t sectorNo) { + if (sectorNo < 32) { + return sectorNo * 4; + } else { + return 32 * 4 + (sectorNo - 32) * 16; + } +} + +uint8_t NumBlocksPerSector(uint8_t sectorNo) { + if (sectorNo < 32) { + return 4; + } else { + return 16; + } +} + +int CmdHF14AMfDump(const char *Cmd) { + + uint8_t sectorNo, blockNo; + uint8_t keyA[40][6]; + uint8_t keyB[40][6]; + uint8_t rights[40][4]; + uint8_t carddata[256][16]; + uint8_t numSectors = 16; + uint8_t cmdp = 0; + + char keyFilename[FILE_PATH_SIZE] = {0}; + char dataFilename[FILE_PATH_SIZE]; + char * fptr; + + memset(keyFilename, 0, sizeof(keyFilename)); + memset(dataFilename, 0, sizeof(dataFilename)); + + FILE *f; + UsbCommand resp; + + while(param_getchar(Cmd, cmdp) != 0x00) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_hf14_dump(); + case 'k': + param_getstr(Cmd, cmdp+1, keyFilename, FILE_PATH_SIZE); + cmdp += 2; + break; + case 'f': + param_getstr(Cmd, cmdp+1, dataFilename, FILE_PATH_SIZE); + cmdp += 2; + break; + default: + if (cmdp == 0) { + numSectors = NumOfSectors(param_getchar(Cmd, cmdp)); + cmdp++; + } else { + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + return usage_hf14_dump(); + } + } + } + + if ( keyFilename[0] == 0x00 ) { + fptr = GenerateFilename("hf-mf-", "-key.bin"); + if (fptr == NULL) + return 1; + + strcpy(keyFilename, fptr); + } + + if ((f = fopen(keyFilename, "rb")) == NULL) { + PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), keyFilename); + return 1; + } + + // Read keys A from file + size_t bytes_read; + for (sectorNo=0; sectorNo> 2) | ((data[8] & 0x1) << 1) | ((data[8] & 0x10) >> 4); // C1C2C3 for data area 0 + rights[sectorNo][1] = ((data[7] & 0x20) >> 3) | ((data[8] & 0x2) << 0) | ((data[8] & 0x20) >> 5); // C1C2C3 for data area 1 + rights[sectorNo][2] = ((data[7] & 0x40) >> 4) | ((data[8] & 0x4) >> 1) | ((data[8] & 0x40) >> 6); // C1C2C3 for data area 2 + rights[sectorNo][3] = ((data[7] & 0x80) >> 5) | ((data[8] & 0x8) >> 2) | ((data[8] & 0x80) >> 7); // C1C2C3 for sector trailer + break; + } else if (tries == 2) { // on last try set defaults + PrintAndLogEx(FAILED, "could not get access rights for sector %2d. Trying with defaults...", sectorNo); + rights[sectorNo][0] = rights[sectorNo][1] = rights[sectorNo][2] = 0x00; + rights[sectorNo][3] = 0x01; + } + } else { + PrintAndLogEx(FAILED, "command execute timeout when trying to read access rights for sector %2d. Trying with defaults...", sectorNo); + rights[sectorNo][0] = rights[sectorNo][1] = rights[sectorNo][2] = 0x00; + rights[sectorNo][3] = 0x01; + } + } + } + + PrintAndLogEx(SUCCESS, "Finished reading sector access bits"); + PrintAndLogEx(INFO, "Dumping all blocks from card..."); + + bool isOK = true; + for (sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) { + for (blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { + bool received = false; + + for (tries = 0; tries < MIFARE_SECTOR_RETRY; tries++) { + if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer. At least the Access Conditions can always be read with key A. + UsbCommand c = {CMD_MIFARE_READBL, {FirstBlockOfSector(sectorNo) + blockNo, 0, 0}}; + memcpy(c.d.asBytes, keyA[sectorNo], 6); + clearCommandBuffer(); + SendCommand(&c); + received = WaitForResponseTimeout(CMD_ACK, &resp, 1500); + } else { // data block. Check if it can be read with key A or key B + uint8_t data_area = (sectorNo < 32) ? blockNo : blockNo/5; + if ((rights[sectorNo][data_area] == 0x03) || (rights[sectorNo][data_area] == 0x05)) { // only key B would work + UsbCommand c = {CMD_MIFARE_READBL, {FirstBlockOfSector(sectorNo) + blockNo, 1, 0}}; + memcpy(c.d.asBytes, keyB[sectorNo], 6); + SendCommand(&c); + received = WaitForResponseTimeout(CMD_ACK, &resp, 1500); + } else if (rights[sectorNo][data_area] == 0x07) { // no key would work + isOK = false; + PrintAndLogEx(WARNING, "access rights do not allow reading of sector %2d block %3d", sectorNo, blockNo); + tries = MIFARE_SECTOR_RETRY; + } else { // key A would work + UsbCommand c = {CMD_MIFARE_READBL, {FirstBlockOfSector(sectorNo) + blockNo, 0, 0}}; + memcpy(c.d.asBytes, keyA[sectorNo], 6); + clearCommandBuffer(); + SendCommand(&c); + received = WaitForResponseTimeout(CMD_ACK, &resp, 1500); + } + } + if (received) { + isOK = resp.arg[0] & 0xff; + if (isOK) break; + } + } + + if (received) { + isOK = resp.arg[0] & 0xff; + uint8_t *data = resp.d.asBytes; + if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer. Fill in the keys. + data[0] = (keyA[sectorNo][0]); + data[1] = (keyA[sectorNo][1]); + data[2] = (keyA[sectorNo][2]); + data[3] = (keyA[sectorNo][3]); + data[4] = (keyA[sectorNo][4]); + data[5] = (keyA[sectorNo][5]); + data[10] = (keyB[sectorNo][0]); + data[11] = (keyB[sectorNo][1]); + data[12] = (keyB[sectorNo][2]); + data[13] = (keyB[sectorNo][3]); + data[14] = (keyB[sectorNo][4]); + data[15] = (keyB[sectorNo][5]); + } + if (isOK) { + memcpy(carddata[FirstBlockOfSector(sectorNo) + blockNo], data, 16); + PrintAndLogEx(SUCCESS, "successfully read block %2d of sector %2d.", blockNo, sectorNo); + } else { + PrintAndLogEx(FAILED, "could not read block %2d of sector %2d", blockNo, sectorNo); + break; + } + } + else { + isOK = false; + PrintAndLogEx(WARNING, "command execute timeout when trying to read block %2d of sector %2d.", blockNo, sectorNo); + break; + } + } + } + + if (isOK == 0) { + PrintAndLogEx(FAILED, "Something went wrong"); + return 0; + } + + PrintAndLogEx(SUCCESS, "\nSuccedded in dumping all blocks"); + + if ( strlen(dataFilename) < 1 ) { + fptr = dataFilename; + fptr += sprintf(fptr, "hf-mf-"); + FillFileNameByUID(fptr, (uint8_t *)carddata, "-data", 4); + } + + uint16_t bytes = 16*(FirstBlockOfSector(numSectors - 1) + NumBlocksPerSector(numSectors - 1)); + + saveFile(dataFilename, "bin", (uint8_t *)carddata, bytes); + saveFileEML(dataFilename, "eml", (uint8_t *)carddata, bytes, MFBLOCK_SIZE); + saveFileJSON(dataFilename, "json", jsfCardMemory, (uint8_t *)carddata, bytes); + return 0; +} + +int CmdHF14AMfRestore(const char *Cmd) { + uint8_t sectorNo,blockNo; + uint8_t keyType = 0; + uint8_t key[6] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; + uint8_t bldata[16] = {0x00}; + uint8_t keyA[40][6]; + uint8_t keyB[40][6]; + uint8_t numSectors = 16; + uint8_t cmdp = 0; + char keyFilename[FILE_PATH_SIZE] = ""; + char dataFilename[FILE_PATH_SIZE] = ""; + char szTemp[FILE_PATH_SIZE-20] = ""; + char *fptr; + FILE *fdump, *fkeys; + + while(param_getchar(Cmd, cmdp) != 0x00) { + switch(tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_hf14_restore(); + case 'u': + param_getstr(Cmd, cmdp+1, szTemp, FILE_PATH_SIZE-20); + if(keyFilename[0]==0x00) + snprintf(keyFilename, FILE_PATH_SIZE, "hf-mf-%s-key.bin", szTemp); + if(dataFilename[0]==0x00) + snprintf(dataFilename, FILE_PATH_SIZE, "hf-mf-%s-data.bin", szTemp); + cmdp+=2; + break; + case 'k': + param_getstr(Cmd, cmdp+1, keyFilename, FILE_PATH_SIZE); + cmdp += 2; + break; + case 'f': + param_getstr(Cmd, cmdp+1, dataFilename, FILE_PATH_SIZE); + cmdp += 2; + break; + default: + if ( cmdp == 0 ) { + numSectors = NumOfSectors(param_getchar(Cmd, cmdp)); + cmdp++; + } else { + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + return usage_hf14_restore(); + } + } + } + + if ( keyFilename[0] == 0x00 ) { + fptr = GenerateFilename("hf-mf-", "-key.bin"); + if (fptr == NULL) + return 1; + + strcpy(keyFilename, fptr); + } + + if ((fkeys = fopen(keyFilename, "rb")) == NULL) { + PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), keyFilename); + return 1; + } + + size_t bytes_read; + for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { + bytes_read = fread( keyA[sectorNo], 1, 6, fkeys ); + if ( bytes_read != 6 ) { + PrintAndLogEx(WARNING, "File reading error " _YELLOW_(%s), keyFilename); + fclose(fkeys); + return 2; + } + } + + for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { + bytes_read = fread( keyB[sectorNo], 1, 6, fkeys ); + if ( bytes_read != 6 ) { + PrintAndLogEx(WARNING, "File reading error " _YELLOW_(%s), keyFilename); + fclose(fkeys); + return 2; + } + } + + fclose(fkeys); + + if ( dataFilename[0] == 0x00 ) { + fptr = GenerateFilename("hf-mf-", "-data.bin"); + if (fptr == NULL) + return 1; + + strcpy(dataFilename,fptr); + } + + if ((fdump = fopen(dataFilename, "rb")) == NULL) { + PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), dataFilename); + return 1; + } + PrintAndLogEx(INFO, "Restoring " _YELLOW_(%s)" to card", dataFilename); + + for (sectorNo = 0; sectorNo < numSectors; sectorNo++) { + for (blockNo = 0; blockNo < NumBlocksPerSector(sectorNo); blockNo++) { + UsbCommand c = {CMD_MIFARE_WRITEBL, {FirstBlockOfSector(sectorNo) + blockNo, keyType, 0}}; + memcpy(c.d.asBytes, key, 6); + bytes_read = fread(bldata, 1, 16, fdump); + if ( bytes_read != 16) { + PrintAndLogEx(WARNING, "File reading error " _YELLOW_(%s), dataFilename); + fclose(fdump); + fdump = NULL; + return 2; + } + + if (blockNo == NumBlocksPerSector(sectorNo) - 1) { // sector trailer + bldata[0] = (keyA[sectorNo][0]); + bldata[1] = (keyA[sectorNo][1]); + bldata[2] = (keyA[sectorNo][2]); + bldata[3] = (keyA[sectorNo][3]); + bldata[4] = (keyA[sectorNo][4]); + bldata[5] = (keyA[sectorNo][5]); + bldata[10] = (keyB[sectorNo][0]); + bldata[11] = (keyB[sectorNo][1]); + bldata[12] = (keyB[sectorNo][2]); + bldata[13] = (keyB[sectorNo][3]); + bldata[14] = (keyB[sectorNo][4]); + bldata[15] = (keyB[sectorNo][5]); + } + + PrintAndLogEx(NORMAL, "Writing to block %3d: %s", FirstBlockOfSector(sectorNo) + blockNo, sprint_hex(bldata, 16)); + + memcpy(c.d.asBytes + 10, bldata, 16); + clearCommandBuffer(); + SendCommand(&c); + + UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK,&resp,1500)) { + uint8_t isOK = resp.arg[0] & 0xff; + PrintAndLogEx(SUCCESS, "isOk:%02x", isOK); + } else { + PrintAndLogEx(WARNING, "Command execute timeout"); + } + } + } + + fclose(fdump); + return 0; +} + +int CmdHF14AMfNested(const char *Cmd) { + int i, res, iterations; + sector_t *e_sector = NULL; + uint8_t blockNo = 0; + uint8_t keyType = 0; + uint8_t trgBlockNo = 0; + uint8_t trgKeyType = 0; + uint8_t SectorsCnt = 0; + uint8_t key[6] = {0, 0, 0, 0, 0, 0}; + uint8_t keyBlock[(MIFARE_DEFAULTKEYS_SIZE + 1) *6]; + uint64_t key64 = 0; + bool transferToEml = false; + bool createDumpFile = false; + FILE *fkeys; + uint8_t standart[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + uint8_t tempkey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + char *fptr; + + if (strlen(Cmd) < 3) return usage_hf14_nested(); + + char cmdp, ctmp; + cmdp = tolower(param_getchar(Cmd, 0)); + blockNo = param_get8(Cmd, 1); + ctmp = tolower(param_getchar(Cmd, 2)); + + if (ctmp != 'a' && ctmp != 'b') { + PrintAndLogEx(WARNING, "key type must be A or B"); + return 1; + } + + if (ctmp != 'a') + keyType = 1; + + if (param_gethex(Cmd, 3, key, 12)) { + PrintAndLogEx(WARNING, "key must include 12 HEX symbols"); + return 1; + } + + if (cmdp == 'o') { + trgBlockNo = param_get8(Cmd, 4); + ctmp = tolower(param_getchar(Cmd, 5)); + if (ctmp != 'a' && ctmp != 'b') { + PrintAndLogEx(WARNING, "target key type must be A or B"); + return 1; + } + if (ctmp != 'a') { + trgKeyType = 1; + } + } else { + SectorsCnt = NumOfSectors(cmdp); + } + + uint8_t j = 4; + while ( ctmp != 0x00 ) { + + ctmp = tolower(param_getchar(Cmd, j)); + transferToEml |= (ctmp == 't'); + createDumpFile |= (ctmp == 'd'); + + j++; + } + + // check if we can authenticate to sector + res = mfCheckKeys(blockNo, keyType, true, 1, key, &key64); + if (res) { + PrintAndLogEx(WARNING, "Wrong key. Can't authenticate to block:%3d key type:%c", blockNo, keyType ? 'B' : 'A'); + return 3; + } + + if (cmdp == 'o') { + int16_t isOK = mfnested(blockNo, keyType, key, trgBlockNo, trgKeyType, keyBlock, true); + switch (isOK) { + case -1 : PrintAndLogEx(WARNING, "Error: No response from Proxmark.\n"); break; + case -2 : PrintAndLogEx(WARNING, "Button pressed. Aborted.\n"); break; + case -3 : PrintAndLogEx(FAILED, "Tag isn't vulnerable to Nested Attack (PRNG is not predictable).\n"); break; + case -4 : PrintAndLogEx(FAILED, "No valid key found"); break; + case -5 : + key64 = bytes_to_num(keyBlock, 6); + + // transfer key to the emulator + if (transferToEml) { + uint8_t sectortrailer; + if (trgBlockNo < 32*4) { // 4 block sector + sectortrailer = trgBlockNo | 0x03; + } else { // 16 block sector + sectortrailer = trgBlockNo | 0x0f; + } + mfEmlGetMem(keyBlock, sectortrailer, 1); + + if (!trgKeyType) + num_to_bytes(key64, 6, keyBlock); + else + num_to_bytes(key64, 6, &keyBlock[10]); + mfEmlSetMem(keyBlock, sectortrailer, 1); + PrintAndLogEx(SUCCESS, "Key transferred to emulator memory."); + } + return 0; + default : PrintAndLogEx(WARNING, "Unknown Error.\n"); + } + return 2; + } + else { // ------------------------------------ multiple sectors working + uint64_t t1 = msclock(); + + e_sector = calloc(SectorsCnt, sizeof(sector_t)); + if (e_sector == NULL) return 1; + + //test current key and additional standard keys first + // add parameter key + memcpy( keyBlock + (MIFARE_DEFAULTKEYS_SIZE * 6), key, 6 ); + + for (int cnt = 0; cnt < MIFARE_DEFAULTKEYS_SIZE; cnt++){ + num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t*)(keyBlock + cnt * 6)); + } + + PrintAndLogEx(SUCCESS, "Testing known keys. Sector count=%d", SectorsCnt); + res = mfCheckKeys_fast( SectorsCnt, true, true, 1, MIFARE_DEFAULTKEYS_SIZE + 1, keyBlock, e_sector, false); + + uint64_t t2 = msclock() - t1; + PrintAndLogEx(SUCCESS, "Time to check %d known keys: %.0f seconds\n", MIFARE_DEFAULTKEYS_SIZE, (float)t2/1000.0 ); + PrintAndLogEx(SUCCESS, "enter nested attack"); + + // nested sectors + iterations = 0; + bool calibrate = true; + + for (i = 0; i < MIFARE_SECTOR_RETRY; i++) { + for (uint8_t sectorNo = 0; sectorNo < SectorsCnt; ++sectorNo) { + for (trgKeyType = 0; trgKeyType < 2; ++trgKeyType) { + + if (e_sector[sectorNo].foundKey[trgKeyType]) continue; + + int16_t isOK = mfnested(blockNo, keyType, key, FirstBlockOfSector(sectorNo), trgKeyType, keyBlock, calibrate); + switch (isOK) { + case -1 : PrintAndLogEx(WARNING, "error: No response from Proxmark.\n"); break; + case -2 : PrintAndLogEx(WARNING, "button pressed. Aborted.\n"); break; + case -3 : PrintAndLogEx(FAILED, "Tag isn't vulnerable to Nested Attack (PRNG is not predictable).\n"); break; + case -4 : //key not found + calibrate = false; + iterations++; + continue; + case -5 : + calibrate = false; + iterations++; + e_sector[sectorNo].foundKey[trgKeyType] = 1; + e_sector[sectorNo].Key[trgKeyType] = bytes_to_num(keyBlock, 6); + + res = mfCheckKeys_fast( SectorsCnt, true, true, 2, 1, keyBlock, e_sector, false); + continue; + + default : PrintAndLogEx(WARNING, "unknown Error.\n"); + } + free(e_sector); + return 2; + } + } + } + + t1 = msclock() - t1; + PrintAndLogEx(SUCCESS, "time in nested: %.0f seconds\n", (float)t1/1000.0); + + + // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? + PrintAndLogEx(INFO, "trying to read key B..."); + for (i = 0; i < SectorsCnt; i++) { + // KEY A but not KEY B + if ( e_sector[i].foundKey[0] && !e_sector[i].foundKey[1] ) { + + uint8_t sectrail = (FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); + + PrintAndLogEx(SUCCESS, "reading block %d", sectrail); + + UsbCommand c = {CMD_MIFARE_READBL, {sectrail, 0, 0}}; + num_to_bytes(e_sector[i].Key[0], 6, c.d.asBytes); // KEY A + clearCommandBuffer(); + SendCommand(&c); + + UsbCommand resp; + if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) continue; + + uint8_t isOK = resp.arg[0] & 0xff; + if (!isOK) continue; + + uint8_t *data = resp.d.asBytes; + key64 = bytes_to_num(data+10, 6); + if (key64) { + PrintAndLogEx(SUCCESS, "data: %s", sprint_hex(data+10, 6)); + e_sector[i].foundKey[1] = true; + e_sector[i].Key[1] = key64; + } + } + } + + + //print them + printKeyTable( SectorsCnt, e_sector ); + + // transfer them to the emulator + if (transferToEml) { + for (i = 0; i < SectorsCnt; i++) { + mfEmlGetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); + if (e_sector[i].foundKey[0]) + num_to_bytes(e_sector[i].Key[0], 6, keyBlock); + if (e_sector[i].foundKey[1]) + num_to_bytes(e_sector[i].Key[1], 6, &keyBlock[10]); + mfEmlSetMem(keyBlock, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); + } + PrintAndLogEx(SUCCESS, "keys transferred to emulator memory."); + } + + // Create dump file + if (createDumpFile) { + fptr = GenerateFilename("hf-mf-", "-key.bin"); + if (fptr == NULL) { + free(e_sector); + return 1; + } + + if ((fkeys = fopen(fptr, "wb")) == NULL) { + PrintAndLogEx(WARNING, "could not create file " _YELLOW_(%s), fptr); + free(e_sector); + return 1; + } + + PrintAndLogEx(SUCCESS, "saving keys to binary file " _YELLOW_(%s), fptr); + for (i=0; i= FILE_PATH_SIZE ) { + PrintAndLogEx(FAILED, "Filename too long"); + continue; + } + + f = fopen( filename, "r"); + if ( !f ){ + PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); + continue; + } + + // read file + while( fgets(buf, sizeof(buf), f) ){ + if (strlen(buf) < 12 || buf[11] == '\n') + continue; + + while (fgetc(f) != '\n' && !feof(f)) ; //goto next line + + if( buf[0]=='#' ) continue; //The line start with # is comment, skip + + if (!isxdigit(buf[0])){ + PrintAndLogEx(FAILED, "File content error. '" _YELLOW_(%s)"' must include 12 HEX symbols", buf); + continue; + } + + buf[12] = 0; + if ( keyitems - keycnt < 2) { + p = realloc(keyBlock, 6 * (keyitems += 64)); + if (!p) { + PrintAndLogEx(FAILED, "Cannot allocate memory for default keys"); + free(keyBlock); + fclose(f); + return 2; + } + keyBlock = p; + } + int pos = 6 * keycnt; + memset(keyBlock + pos, 0, 6); + num_to_bytes(strtoll(buf, NULL, 16), 6, keyBlock + pos); + keycnt++; + memset(buf, 0, sizeof(buf)); + } + fclose(f); + PrintAndLogEx(SUCCESS, "Loaded %2d keys from " _YELLOW_(%s), keycnt, filename); + } + } + + if (keycnt == 0 && !use_flashmemory) { + PrintAndLogEx(SUCCESS, "No key specified, trying default keys"); + for (;keycnt < MIFARE_DEFAULTKEYS_SIZE; keycnt++) + PrintAndLogEx(NORMAL, "[%2d] %02x%02x%02x%02x%02x%02x", keycnt, + (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], + (keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5]); + } + + // // initialize storage for found keys + e_sector = calloc(sectorsCnt, sizeof(sector_t)); + if (e_sector == NULL) { + free(keyBlock); + return 1; + } + + uint32_t chunksize = keycnt > (USB_CMD_DATA_SIZE/6) ? (USB_CMD_DATA_SIZE/6) : keycnt; + bool firstChunk = true, lastChunk = false; + + // time + uint64_t t1 = msclock(); + + if ( use_flashmemory ) { + PrintAndLogEx(SUCCESS, "Using dictionary in flash memory"); + mfCheckKeys_fast( sectorsCnt, true, true, 1, 0, keyBlock, e_sector, use_flashmemory); + } else { + + // strategys. 1= deep first on sector 0 AB, 2= width first on all sectors + for (uint8_t strategy = 1; strategy < 3; strategy++) { + PrintAndLogEx(SUCCESS, "Running strategy %u", strategy); + + // main keychunk loop + for (uint32_t i = 0; i < keycnt; i += chunksize) { + + if (ukbhit()) { + int gc = getchar(); (void)gc; + PrintAndLogEx(WARNING, "\naborted via keyboard!\n"); + goto out; + } + + uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i; + + // last chunk? + if ( size == keycnt - i) + lastChunk = true; + + int res = mfCheckKeys_fast( sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector, false); + + if ( firstChunk ) + firstChunk = false; + + // all keys, aborted + if ( res == 0 || res == 2 ) + goto out; + } // end chunks of keys + firstChunk = true; + lastChunk = false; + } // end strategy + } +out: + t1 = msclock() - t1; + PrintAndLogEx(SUCCESS, "Time in checkkeys (fast): %.1fs\n", (float)(t1/1000.0)); + + // check.. + uint8_t found_keys = 0; + for (uint8_t i = 0; i < sectorsCnt; ++i) { + + if ( e_sector[i].foundKey[0] ) + found_keys++; + + if ( e_sector[i].foundKey[1] ) + found_keys++; + } + + if ( found_keys == 0 ) { + PrintAndLogEx(WARNING, "No keys found"); + } else { + + printKeyTable( sectorsCnt, e_sector ); + + if (transferToEml) { + uint8_t block[16] = {0x00}; + for (uint8_t i = 0; i < sectorsCnt; ++i ) { + mfEmlGetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); + if (e_sector[i].foundKey[0]) + num_to_bytes(e_sector[i].Key[0], 6, block); + if (e_sector[i].foundKey[1]) + num_to_bytes(e_sector[i].Key[1], 6, block+10); + mfEmlSetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); + } + PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory"); + } + + if (createDumpFile) { + fptr = GenerateFilename("hf-mf-", "-key.bin"); + if (fptr == NULL) + return 1; + + FILE *fkeys = fopen(fptr, "wb"); + if (fkeys == NULL) { + PrintAndLogEx(WARNING, "Could not create file " _YELLOW_(%s), fptr); + free(keyBlock); + free(e_sector); + return 1; + } + PrintAndLogEx(SUCCESS, "Printing keys to binary file " _YELLOW_(%s)"...", fptr); + + for (i=0; i 0xffffffffffff has been inserted for unknown keys.", fptr); + } + } + + free(keyBlock); + free(e_sector); + PrintAndLogEx(NORMAL, ""); + return 0; +} + +int CmdHF14AMfChk(const char *Cmd) { + + char ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 3 || ctmp == 'h') return usage_hf14_chk(); + + FILE * f; + char filename[FILE_PATH_SIZE] = {0}; + char buf[13]; + uint8_t *keyBlock = NULL, *p; + sector_t *e_sector = NULL; + + uint8_t blockNo = 0; + uint8_t SectorsCnt = 1; + uint8_t keyType = 0; + uint32_t keyitems = MIFARE_DEFAULTKEYS_SIZE; + uint64_t key64 = 0; + uint8_t tempkey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; + char *fptr; + int clen = 0; + int transferToEml = 0; + int createDumpFile = 0; + int i, res, keycnt = 0; + + keyBlock = calloc(MIFARE_DEFAULTKEYS_SIZE, 6); + if (keyBlock == NULL) return 1; + + for (int cnt = 0; cnt < MIFARE_DEFAULTKEYS_SIZE; cnt++) + num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t*)(keyBlock + cnt * 6)); + + if (param_getchar(Cmd, 0)=='*') { + blockNo = 3; + SectorsCnt = NumOfSectors( param_getchar(Cmd+1, 0) ); + } else { + blockNo = param_get8(Cmd, 0); + } + + ctmp = tolower(param_getchar(Cmd, 1)); + clen = param_getlength(Cmd, 1); + if (clen == 1) { + switch (ctmp) { + case 'a': + keyType = 0; + break; + case 'b': + keyType = 1; + break; + case '?': + keyType = 2; + break; + default: + PrintAndLogEx(FAILED, "Key type must be A , B or ?"); + free(keyBlock); + return 1; + }; + } + + for (i = 2; param_getchar(Cmd, i); i++) { + + ctmp = tolower(param_getchar(Cmd, i)); + clen = param_getlength(Cmd, i); + + if (clen == 12) { + + if ( param_gethex(Cmd, i, keyBlock + 6 * keycnt, 12) ){ + PrintAndLogEx(FAILED, "not hex, skipping"); + continue; + } + + if ( keyitems - keycnt < 2) { + p = realloc(keyBlock, 6 * (keyitems += 64)); + if (!p) { + PrintAndLogEx(FAILED, "cannot allocate memory for Keys"); + free(keyBlock); + return 2; + } + keyBlock = p; + } + PrintAndLogEx(NORMAL, "[%2d] key %s", keycnt, sprint_hex( (keyBlock + 6*keycnt), 6 ) );; + keycnt++; + } else if ( clen == 1 ) { + if (ctmp == 't' ) { transferToEml = 1; continue; } + if (ctmp == 'd' ) { createDumpFile = 1; continue; } + } else { + // May be a dic file + if ( param_getstr(Cmd, i, filename, sizeof(filename)) >= FILE_PATH_SIZE ) { + PrintAndLogEx(FAILED, "File name too long"); + continue; + } + + f = fopen( filename , "r"); + if ( !f ) { + PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); + continue; + } + + // load keys from dictionary file + while( fgets(buf, sizeof(buf), f) ){ + if (strlen(buf) < 12 || buf[11] == '\n') + continue; + + while (fgetc(f) != '\n' && !feof(f)) ; //goto next line + + if( buf[0]=='#' ) continue; //The line start with # is comment, skip + + // codesmell, only checks first char? + if (!isxdigit(buf[0])){ + PrintAndLogEx(FAILED, "File content error. '" _YELLOW_(%s)"' must include 12 HEX symbols",buf); + continue; + } + + buf[12] = 0; + + if ( keyitems - keycnt < 2) { + p = realloc(keyBlock, 6 * (keyitems += 64)); + if (!p) { + PrintAndLogEx(FAILED, "Cannot allocate memory for defKeys"); + free(keyBlock); + fclose(f); + return 2; + } + keyBlock = p; + } + memset(keyBlock + 6 * keycnt, 0, 6); + num_to_bytes(strtoll(buf, NULL, 16), 6, keyBlock + 6*keycnt); + //PrintAndLogEx(NORMAL, "check key[%2d] %012" PRIx64, keycnt, bytes_to_num(keyBlock + 6*keycnt, 6)); + keycnt++; + memset(buf, 0, sizeof(buf)); + } + fclose(f); + PrintAndLogEx(SUCCESS, "Loaded %2d keys from " _YELLOW_(%s), keycnt, filename); + } + } + + if (keycnt == 0) { + PrintAndLogEx(INFO, "No key specified, trying default keys"); + for (;keycnt < MIFARE_DEFAULTKEYS_SIZE; keycnt++) + PrintAndLogEx(NORMAL, "[%2d] %02x%02x%02x%02x%02x%02x", keycnt, + (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], + (keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6); + } + + // initialize storage for found keys + e_sector = calloc(SectorsCnt, sizeof(sector_t)); + if (e_sector == NULL) { + free(keyBlock); + return 1; + } + + // empty e_sector + for(int i = 0; i < SectorsCnt; ++i){ + e_sector[i].Key[0] = 0xffffffffffff; + e_sector[i].Key[1] = 0xffffffffffff; + e_sector[i].foundKey[0] = false; + e_sector[i].foundKey[1] = false; + } + + + uint8_t trgKeyType = 0; + uint32_t max_keys = keycnt > (USB_CMD_DATA_SIZE/6) ? (USB_CMD_DATA_SIZE/6) : keycnt; + + // time + uint64_t t1 = msclock(); + + + // check keys. + for (trgKeyType = (keyType==2)?0:keyType; trgKeyType < 2; (keyType==2) ? (++trgKeyType) : (trgKeyType=2) ) { + + int b = blockNo; + for (int i = 0; i < SectorsCnt; ++i) { + + // skip already found keys. + if (e_sector[i].foundKey[trgKeyType]) continue; + + for (uint32_t c = 0; c < keycnt; c += max_keys) { + + printf("."); fflush(stdout); + if (ukbhit()) { + int gc = getchar(); (void)gc; + PrintAndLogEx(INFO, "\naborted via keyboard!\n"); + goto out; + } + + uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c; + + res = mfCheckKeys(b, trgKeyType, true, size, &keyBlock[6*c], &key64); + if (!res) { + e_sector[i].Key[trgKeyType] = key64; + e_sector[i].foundKey[trgKeyType] = true; + break; + } + + + } + b < 127 ? ( b +=4 ) : ( b += 16 ); + } + } + t1 = msclock() - t1; + PrintAndLogEx(SUCCESS, "\nTime in checkkeys: %.0f seconds\n", (float)t1/1000.0); + + + // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? + if ( keyType != 1 ) { + PrintAndLogEx(INFO, "testing to read key B..."); + for (i = 0; i < SectorsCnt; i++) { + // KEY A but not KEY B + if ( e_sector[i].foundKey[0] && !e_sector[i].foundKey[1] ) { + + uint8_t sectrail = (FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); + + PrintAndLogEx(NORMAL, "Reading block %d", sectrail); + + UsbCommand c = {CMD_MIFARE_READBL, {sectrail, 0, 0}}; + num_to_bytes(e_sector[i].Key[0], 6, c.d.asBytes); // KEY A + clearCommandBuffer(); + SendCommand(&c); + + UsbCommand resp; + if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) continue; + + uint8_t isOK = resp.arg[0] & 0xff; + if (!isOK) continue; + + uint8_t *data = resp.d.asBytes; + key64 = bytes_to_num(data+10, 6); + if (key64) { + PrintAndLogEx(NORMAL, "Data:%s", sprint_hex(data+10, 6)); + e_sector[i].foundKey[1] = 1; + e_sector[i].Key[1] = key64; + } + } + } + } + +out: + + //print keys + printKeyTable( SectorsCnt, e_sector ); + + if (transferToEml) { + uint8_t block[16] = {0x00}; + for (uint8_t i = 0; i < SectorsCnt; ++i ) { + mfEmlGetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); + if (e_sector[i].foundKey[0]) + num_to_bytes(e_sector[i].Key[0], 6, block); + if (e_sector[i].foundKey[1]) + num_to_bytes(e_sector[i].Key[1], 6, block+10); + mfEmlSetMem(block, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1); + } + PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory"); + } + + if (createDumpFile) { + fptr = GenerateFilename("hf-mf-", "-key.bin"); + if (fptr == NULL) { + free(keyBlock); + free(e_sector); + return 1; + } + + FILE *fkeys = fopen(fptr, "wb"); + if (fkeys == NULL) { + PrintAndLogEx(WARNING, "Could not create file " _YELLOW_(%s), fptr); + free(keyBlock); + free(e_sector); + return 1; + } + PrintAndLogEx(INFO, "Printing keys to binary file " _YELLOW_(%s)"...", fptr); + + for( i=0; i>1) + , exitAfterNReads + , flags + , flags); + + UsbCommand c = {CMD_SIMULATE_MIFARE_CARD, {flags, exitAfterNReads, 0}}; + memcpy(c.d.asBytes, uid, sizeof(uid)); + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + + if(flags & FLAG_INTERACTIVE) { + PrintAndLogEx(INFO, "Press pm3-button or send another cmd to abort simulation"); + + while( !ukbhit() ){ + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; + if ( !(flags & FLAG_NR_AR_ATTACK) ) break; + if ( (resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD ) break; + + memcpy(data, resp.d.asBytes, sizeof(data)); + readerAttack(data[0], setEmulatorMem, verbose); + } + showSectorTable(); + } + return 0; +} + +int CmdHF14AMfSniff(const char *Cmd){ + bool wantLogToFile = false; + bool wantDecrypt = false; + //bool wantSaveToEml = false; TODO + bool wantSaveToEmlFile = false; + + //var + int res = 0, len = 0, blockLen = 0; + int pckNum = 0, num = 0; + uint8_t sak = 0; + uint8_t uid[10]; + uint8_t uid_len = 0; + uint8_t atqa[2] = {0x00, 0x00}; + bool isTag = false; + uint8_t *buf = NULL; + uint16_t bufsize = 0; + uint8_t *bufPtr = NULL; + uint16_t traceLen = 0; + + memset(uid, 0x00, sizeof(uid)); + + char ctmp = tolower(param_getchar(Cmd, 0)); + if ( ctmp == 'h') return usage_hf14_sniff(); + + for (int i = 0; i < 4; i++) { + ctmp = tolower(param_getchar(Cmd, i)); + if (ctmp == 'l') wantLogToFile = true; + if (ctmp == 'd') wantDecrypt = true; + //if (ctmp == 'e') wantSaveToEml = true; TODO + if (ctmp == 'f') wantSaveToEmlFile = true; + } + + PrintAndLogEx(NORMAL, "-------------------------------------------------------------------------\n"); + PrintAndLogEx(NORMAL, "Executing mifare sniffing command. \n"); + PrintAndLogEx(NORMAL, "Press the key on the proxmark3 device to abort both proxmark3 and client.\n"); + PrintAndLogEx(NORMAL, "Press the key on pc keyboard to abort the client.\n"); + PrintAndLogEx(NORMAL, "-------------------------------------------------------------------------\n"); + + UsbCommand c = {CMD_MIFARE_SNIFFER, {0, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + + UsbCommand resp; + + // wait cycle + while (true) { + printf("."); fflush(stdout); + if (ukbhit()) { + int gc = getchar(); (void)gc; + PrintAndLogEx(INFO, "\naborted via keyboard!\n"); + break; + } + + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + continue; + } + + res = resp.arg[0] & 0xff; + traceLen = resp.arg[1]; + len = resp.arg[2]; + + if (res == 0) { + PrintAndLogEx(SUCCESS, "hf mifare sniff finished"); + free(buf); + return 0; + } + + if (res == 1) { // there is (more) data to be transferred + if (pckNum == 0) { // first packet, (re)allocate necessary buffer + if (traceLen > bufsize || buf == NULL) { + uint8_t *p; + if (buf == NULL) // not yet allocated + p = calloc(traceLen, sizeof(uint8_t)); + else // need more memory + p = realloc(buf, traceLen); + + if (p == NULL) { + PrintAndLogEx(FAILED, "Cannot allocate memory for trace"); + free(buf); + return 2; + } + buf = p; + } + bufPtr = buf; + bufsize = traceLen; + memset(buf, 0x00, traceLen); + } + + // what happens if LEN is bigger then TRACELEN --iceman + memcpy(bufPtr, resp.d.asBytes, len); + bufPtr += len; + pckNum++; + } + + if (res == 2) { // received all data, start displaying + blockLen = bufPtr - buf; + bufPtr = buf; + PrintAndLogEx(NORMAL, ">\n"); + PrintAndLogEx(SUCCESS, "received trace len: %d packages: %d", blockLen, pckNum); + while (bufPtr - buf < blockLen) { + bufPtr += 6; // skip (void) timing information + len = *((uint16_t *)bufPtr); + if(len & 0x8000) { + isTag = true; + len &= 0x7fff; + } else { + isTag = false; + } + bufPtr += 2; + + // the uid identification package + // 0xFF 0xFF xx xx xx xx xx xx xx xx xx xx aa aa cc 0xFF 0xFF + // x = uid, a = atqa, c = sak + if ((len == 17) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[15] == 0xff) && (bufPtr[16] == 0xff)) { + memcpy(uid, bufPtr + 2, 10); + memcpy(atqa, bufPtr + 2 + 10, 2); + switch (atqa[0] & 0xC0) { + case 0x80: uid_len = 10; break; + case 0x40: uid_len = 7; break; + default: uid_len = 4; break; + } + sak = bufPtr[14]; + PrintAndLogEx(SUCCESS, "UID %s | ATQA %02x %02x | SAK 0x%02x", + sprint_hex(uid, uid_len), + atqa[1], + atqa[0], + sak); + if (wantLogToFile || wantDecrypt) { + FillFileNameByUID(logHexFileName, uid, ".log", uid_len); + AddLogCurrentDT(logHexFileName); + PrintAndLogEx(SUCCESS, "Trace saved to %s", logHexFileName); + } + if (wantDecrypt) + mfTraceInit(uid, uid_len, atqa, sak, wantSaveToEmlFile); + } else { + PrintAndLogEx(NORMAL, "%03d| %s |%s", num, isTag ? "TAG" : "RDR", sprint_hex(bufPtr, len)); + if (wantLogToFile) + AddLogHex(logHexFileName, isTag ? "TAG| ":"RDR| ", bufPtr, len); + if (wantDecrypt) + mfTraceDecode(bufPtr, len, wantSaveToEmlFile); + num++; + } + bufPtr += len; + bufPtr += ((len-1)/8+1); // ignore parity + } + pckNum = 0; + } + } // while (true) + + free(buf); + return 0; +} + +int CmdHF14AMfDbg(const char *Cmd) { + + char ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || ctmp == 'h' ) return usage_hf14_dbg(); + + uint8_t dbgMode = param_get8ex(Cmd, 0, 0, 10); + if (dbgMode > 4) return usage_hf14_dbg(); + + UsbCommand c = {CMD_MIFARE_SET_DBGMODE, {dbgMode, 0, 0}}; + SendCommand(&c); + return 0; +} + +int CmdHF14AMfKeyBrute(const char *Cmd) { + + uint8_t blockNo = 0, keytype = 0; + uint8_t key[6] = {0, 0, 0, 0, 0, 0}; + uint64_t foundkey = 0; + + char cmdp = tolower(param_getchar(Cmd, 0)); + if ( cmdp == 'h' ) return usage_hf14_keybrute(); + + // block number + blockNo = param_get8(Cmd, 0); + + // keytype + cmdp = tolower(param_getchar(Cmd, 1)); + if ( cmdp == 'b' ) keytype = 1; + + // key + if (param_gethex(Cmd, 2, key, 12)) return usage_hf14_keybrute(); + + uint64_t t1 = msclock(); + + if (mfKeyBrute( blockNo, keytype, key, &foundkey)) + PrintAndLogEx(SUCCESS, "found valid key: %012" PRIx64 " \n", foundkey); + else + PrintAndLogEx(FAILED, "key not found"); + + t1 = msclock() - t1; + PrintAndLogEx(SUCCESS, "\ntime in keybrute: %.0f seconds\n", (float)t1/1000.0); + return 0; +} + +void printKeyTable( uint8_t sectorscnt, sector_t *e_sector ){ + char strA[12+1] = {0}; + char strB[12+1] = {0}; + PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); + PrintAndLogEx(NORMAL, "|sec|key A |res|key B |res|"); + PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); + for (uint8_t i = 0; i < sectorscnt; ++i) { + + snprintf(strA, sizeof(strA), "------------"); + snprintf(strB, sizeof(strB), "------------"); + + if ( e_sector[i].foundKey[0] ) + snprintf(strA, sizeof(strA), "%012" PRIx64, e_sector[i].Key[0]); + + if ( e_sector[i].foundKey[1] ) + snprintf(strB, sizeof(strB), "%012" PRIx64, e_sector[i].Key[1]); + + + PrintAndLogEx(NORMAL, "|%03d| %s | %d | %s | %d |" + , i + , strA, e_sector[i].foundKey[0] + , strB, e_sector[i].foundKey[1] + ); + } + PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); +} + +// EMULATOR COMMANDS +int CmdHF14AMfEGet(const char *Cmd) { + uint8_t blockNo = 0; + uint8_t data[16] = {0x00}; + char c = tolower(param_getchar(Cmd, 0)); + + if (strlen(Cmd) < 1 || c == 'h') return usage_hf14_eget(); + + blockNo = param_get8(Cmd, 0); + + PrintAndLogEx(NORMAL, ""); + if (!mfEmlGetMem(data, blockNo, 1)) { + PrintAndLogEx(NORMAL, "data[%3d]:%s", blockNo, sprint_hex(data, sizeof(data))); + } else { + PrintAndLogEx(WARNING, "Command execute timeout"); + } + return 0; +} + +int CmdHF14AMfEClear(const char *Cmd) { + char c = tolower(param_getchar(Cmd, 0)); + if (c == 'h') return usage_hf14_eclr(); + + UsbCommand cmd = {CMD_MIFARE_EML_MEMCLR, {0, 0, 0}}; + clearCommandBuffer(); + SendCommand(&cmd); + return 0; +} + +int CmdHF14AMfESet(const char *Cmd) { + char c = tolower(param_getchar(Cmd, 0)); + uint8_t memBlock[16]; + uint8_t blockNo = 0; + memset(memBlock, 0x00, sizeof(memBlock)); + + if (strlen(Cmd) < 3 || c == 'h') + return usage_hf14_eset(); + + blockNo = param_get8(Cmd, 0); + + if (param_gethex(Cmd, 1, memBlock, 32)) { + PrintAndLogEx(WARNING, "block data must include 32 HEX symbols"); + return 1; + } + + // 1 - blocks count + return mfEmlSetMem(memBlock, blockNo, 1); +} + +int CmdHF14AMfELoad(const char *Cmd) { + + size_t counter = 0; + char filename[FILE_PATH_SIZE]; + int blockNum, numBlocks, nameParamNo = 1; + uint8_t blockWidth = 16; + char c = tolower(param_getchar(Cmd, 0)); + + if ( strlen(Cmd) < 2 && c == 'h' ) + return usage_hf14_eload(); + + switch (c) { + case '0' : numBlocks = MIFARE_MINI_MAXBLOCK; break; + case '1' : + case '\0': numBlocks = MIFARE_1K_MAXBLOCK; break; + case '2' : numBlocks = MIFARE_2K_MAXBLOCK; break; + case '4' : numBlocks = MIFARE_4K_MAXBLOCK; break; + case 'u' : numBlocks = 255; blockWidth = 4; break; + default: { + numBlocks = MIFARE_1K_MAXBLOCK; + nameParamNo = 0; + } + } + uint32_t numblk2 = param_get32ex(Cmd, 2, 0, 10); + if (numblk2 > 0) + numBlocks = numblk2; + + param_getstr(Cmd, nameParamNo, filename, sizeof(filename)); + + uint8_t *data = calloc(4096, sizeof(uint8_t)); + size_t datalen = 0; + //int res = loadFile(filename, "bin", data, &datalen); + int res = loadFileEML( filename, "eml", data, &datalen); + if ( res ) { + free(data); + return 1; + } + + // 64 or 256 blocks. + if ( (datalen % blockWidth) != 0 ) { + PrintAndLogEx(FAILED, "File content error. Size doesn't match blockwidth "); + free(data); + return 2; + } + + PrintAndLogEx(INFO, "Copying to emulator memory"); + + blockNum = 0; + while ( datalen ) { + + if (mfEmlSetMem_xt(data + counter, blockNum, 1, blockWidth)) { + PrintAndLogEx(FAILED, "Cant set emul block: %3d", blockNum); + free(data); + return 3; + } + printf("."); fflush(stdout); + + blockNum++; + counter += blockWidth; + datalen -= blockWidth; + } + PrintAndLogEx(NORMAL, "\n"); + + // Ultralight /Ntag + if ( blockWidth == 4 ) { + if ((blockNum != numBlocks)) { + PrintAndLogEx(FAILED, "Warning, Ultralight/Ntag file content, Loaded %d blocks into emulator memory", blockNum); + free(data); + return 0; + } + } else { + if ((blockNum != numBlocks)) { + PrintAndLogEx(FAILED, "Error, file content, Only loaded %d blocks, must be %d blocks into emulator memory", blockNum, numBlocks); + free(data); + return 4; + } + } + PrintAndLogEx(SUCCESS, "Loaded %d blocks from file: " _YELLOW_(%s), blockNum, filename); + free(data); + return 0; +} + +int CmdHF14AMfESave(const char *Cmd) { + + char filename[FILE_PATH_SIZE]; + char * fnameptr = filename; + uint8_t *dump; + int len, bytes, nameParamNo = 1; + uint16_t blocks; + + memset(filename, 0, sizeof(filename)); + + char c = tolower(param_getchar(Cmd, 0)); + if (c == 'h') return usage_hf14_esave(); + + blocks = NumOfBlocks(c); + bytes = blocks * MFBLOCK_SIZE; + + dump = calloc(bytes, sizeof(uint8_t)); + if (!dump) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); + return 1; + } + memset(dump, 0, bytes); + + PrintAndLogEx(INFO, "downloading from emulator memory"); + if (!GetFromDevice( BIG_BUF_EML, dump, bytes, 0, NULL, 2500, false)) { + PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); + free(dump); + return 2; + } + + len = param_getstr(Cmd, nameParamNo, filename, sizeof(filename)); + if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; + + // user supplied filename? + if (len < 1) { + fnameptr += sprintf(fnameptr, "hf-mf-"); + FillFileNameByUID(fnameptr, dump, "-dump", 4); + } + + saveFile(filename, "bin", dump, bytes); + saveFileEML(filename, "eml", dump, bytes, MFBLOCK_SIZE); + saveFileJSON(filename, "json", jsfCardMemory, dump, bytes); + free(dump); + return 0; +} + +int CmdHF14AMfECFill(const char *Cmd) { + uint8_t keyType = 0; + uint8_t numSectors = 16; + char c = tolower(param_getchar(Cmd, 0)); + + if (strlen(Cmd) < 1 || c == 'h') + return usage_hf14_ecfill(); + + if (c != 'a' && c != 'b') { + PrintAndLogEx(WARNING, "Key type must be A or B"); + return 1; + } + if (c != 'a') + keyType = 1; + + c = tolower(param_getchar(Cmd, 1)); + numSectors = NumOfSectors(c); + + PrintAndLogEx(NORMAL, "--params: numSectors: %d, keyType: %c\n", numSectors, (keyType == 0) ? 'A' : 'B'); + UsbCommand cmd = {CMD_MIFARE_EML_CARDLOAD, {numSectors, keyType, 0}}; + clearCommandBuffer(); + SendCommand(&cmd); + return 0; +} + +int CmdHF14AMfEKeyPrn(const char *Cmd) { + int i; + uint8_t numSectors; + uint8_t data[16]; + uint64_t keyA, keyB; + + char c = tolower(param_getchar(Cmd, 0)); + if ( c == 'h' ) + return usage_hf14_ekeyprn(); + + numSectors = NumOfSectors(c); + + PrintAndLogEx(NORMAL, "|---|----------------|----------------|"); + PrintAndLogEx(NORMAL, "|sec|key A |key B |"); + PrintAndLogEx(NORMAL, "|---|----------------|----------------|"); + for (i = 0; i < numSectors; i++) { + if (mfEmlGetMem(data, FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1, 1)) { + PrintAndLogEx(WARNING, "error get block %d", FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); + break; + } + keyA = bytes_to_num(data, 6); + keyB = bytes_to_num(data + 10, 6); + PrintAndLogEx(NORMAL, "|%03d| %012" PRIx64 " | %012" PRIx64 " |", i, keyA, keyB); + } + PrintAndLogEx(NORMAL, "|---|----------------|----------------|"); + return 0; +} + +// CHINESE MAGIC COMMANDS +int CmdHF14AMfCSetUID(const char *Cmd) { + uint8_t wipeCard = 0; + uint8_t uid[8] = {0x00}; + uint8_t oldUid[8] = {0x00}; + uint8_t atqa[2] = {0x00}; + uint8_t sak[1] = {0x00}; + uint8_t atqaPresent = 1; + int res, argi = 0; + char ctmp; + + if (strlen(Cmd) < 1 || param_getchar(Cmd, argi) == 'h') + return usage_hf14_csetuid(); + + if (param_getchar(Cmd, argi) && param_gethex(Cmd, argi, uid, 8)) + return usage_hf14_csetuid(); + + argi++; + + ctmp = tolower(param_getchar(Cmd, argi)); + if (ctmp == 'w') { + wipeCard = 1; + atqaPresent = 0; + } + + if (atqaPresent) { + if (param_getchar(Cmd, argi)) { + if (param_gethex(Cmd, argi, atqa, 4)) { + PrintAndLogEx(WARNING, "ATQA must include 4 HEX symbols"); + return 1; + } + argi++; + if (!param_getchar(Cmd, argi) || param_gethex(Cmd, argi, sak, 2)) { + PrintAndLogEx(WARNING, "SAK must include 2 HEX symbols"); + return 1; + } + argi++; + } else + atqaPresent = 0; + } + + if (!wipeCard) { + ctmp = tolower(param_getchar(Cmd, argi)); + if (ctmp == 'w') { + wipeCard = 1; + } + } + + PrintAndLogEx(NORMAL, "--wipe card:%s uid:%s", (wipeCard)?"YES":"NO", sprint_hex(uid, 4)); + + res = mfCSetUID(uid, (atqaPresent) ? atqa : NULL, (atqaPresent) ? sak : NULL, oldUid, wipeCard); + if (res) { + PrintAndLogEx(WARNING, "Can't set UID. error=%d", res); + return 1; + } + + PrintAndLogEx(SUCCESS, "old UID:%s", sprint_hex(oldUid, 4)); + PrintAndLogEx(SUCCESS, "new UID:%s", sprint_hex(uid, 4)); + return 0; +} + +int CmdHF14AMfCSetBlk(const char *Cmd) { + uint8_t block[16] = {0x00}; + uint8_t blockNo = 0; + uint8_t params = MAGIC_SINGLE; + int res; + char ctmp = tolower(param_getchar(Cmd, 0)); + + if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_csetblk(); + + blockNo = param_get8(Cmd, 0); + + if (param_gethex(Cmd, 1, block, 32)) return usage_hf14_csetblk(); + + ctmp = tolower(param_getchar(Cmd, 2)); + if (ctmp == 'w') + params |= MAGIC_WIPE; + + PrintAndLogEx(NORMAL, "--block number:%2d data:%s", blockNo, sprint_hex(block, 16)); + + res = mfCSetBlock(blockNo, block, NULL, params); + if (res) { + PrintAndLogEx(WARNING, "Can't write block. error=%d", res); + return 1; + } + return 0; +} + +int CmdHF14AMfCLoad(const char *Cmd) { + + uint8_t buf8[16] = {0x00}; + uint8_t fillFromEmulator = 0; + int blockNum, flags = 0; + bool fillFromJson = false; + bool fillFromBin = false; + char fileName[50] = {0}; + + char ctmp = tolower(param_getchar(Cmd, 0)); + if ( param_getlength(Cmd, 0) == 1 ) { + if (ctmp == 'h' || ctmp == 0x00) return usage_hf14_cload(); + if (ctmp == 'e' ) fillFromEmulator = 1; + if (ctmp == 'j' ) fillFromJson = true; + if (ctmp == 'b' ) fillFromBin = true; + } + + if (fillFromJson || fillFromBin) + param_getstr(Cmd, 1, fileName, sizeof(fileName)); + + + if (fillFromEmulator) { + for (blockNum = 0; blockNum < 16 * 4; blockNum += 1) { + if (mfEmlGetMem(buf8, blockNum, 1)) { + PrintAndLogEx(WARNING, "Cant get block: %d", blockNum); + return 2; + } + if (blockNum == 0) flags = MAGIC_INIT + MAGIC_WUPC; // switch on field and send magic sequence + if (blockNum == 1) flags = 0; // just write + if (blockNum == 16 * 4 - 1) flags = MAGIC_HALT + MAGIC_OFF; // Done. Magic Halt and switch off field. + + if (mfCSetBlock(blockNum, buf8, NULL, flags)) { + PrintAndLogEx(WARNING, "Cant set magic card block: %d", blockNum); + return 3; + } + printf("."); fflush(stdout); + } + PrintAndLogEx(NORMAL, "\n"); + return 0; + } + + size_t maxdatalen = 4096; + uint8_t *data = calloc(maxdatalen, sizeof(uint8_t)); + size_t datalen = 0; + int res = 0; + if (fillFromBin) { + res = loadFile(fileName, "bin", data, &datalen); + } else { + if (fillFromJson) { + res = loadFileJSON(fileName, "json", data, maxdatalen, &datalen); + } else { + res = loadFileEML( Cmd, "eml", data, &datalen); + } + } + + if ( res ) { + if ( data ) + free(data); + return 1; + } + +// PrintAndLogEx(INFO, "DATA | %s", sprint_hex(data+1000, 24) ); + + + // 64 or 256blocks. + if (datalen != 1024 && datalen != 4096) { + PrintAndLogEx(WARNING, "File content error. "); + free(data); + return 2; + } + + PrintAndLogEx(INFO, "Copying to magic card"); + + blockNum = 0; + while ( datalen ) { + + // switch on field and send magic sequence + if (blockNum == 0) flags = MAGIC_INIT + MAGIC_WUPC; + + // write + if (blockNum == 1) flags = 0; + + // Switch off field. + if (blockNum == 16 * 4 - 1) flags = MAGIC_HALT + MAGIC_OFF; + + if (mfCSetBlock(blockNum, data + (16 * blockNum), NULL, flags)) { + PrintAndLogEx(WARNING, "Can't set magic card block: %d", blockNum); + free(data); + return 3; + } + + datalen -= 16; + + printf("."); fflush(stdout); + blockNum++; + + // magic card type - mifare 1K + if (blockNum >= MIFARE_1K_MAXBLOCK ) break; + } + PrintAndLogEx(NORMAL, "\n"); + + // 64 or 256blocks. + if (blockNum != 16 * 4 && blockNum != 32 * 4 + 8 * 16){ + PrintAndLogEx(WARNING, "File content error. There must be 64 blocks"); + free(data); + return 4; + } + + PrintAndLogEx(SUCCESS, "Card loaded %d blocks from file", blockNum); + free(data); + return 0; +} + +int CmdHF14AMfCGetBlk(const char *Cmd) { + uint8_t data[16] = {0}; + uint8_t blockNo = 0; + int res; + memset(data, 0x00, sizeof(data)); + + char ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_cgetblk(); + + blockNo = param_get8(Cmd, 0); + + PrintAndLogEx(NORMAL, "--block number:%2d ", blockNo); + + res = mfCGetBlock(blockNo, data, MAGIC_SINGLE); + if (res) { + PrintAndLogEx(WARNING, "Can't read block. error=%d", res); + return 1; + } + + PrintAndLogEx(NORMAL, "data: %s", sprint_hex(data, sizeof(data))); + + if (mfIsSectorTrailer(blockNo)) { + PrintAndLogEx(NORMAL, "Trailer decoded:"); + PrintAndLogEx(NORMAL, "Key A: %s", sprint_hex_inrow(data, 6)); + PrintAndLogEx(NORMAL, "Key B: %s", sprint_hex_inrow(&data[10], 6)); + int bln = mfFirstBlockOfSector(mfSectorNum(blockNo)); + int blinc = (mfNumBlocksPerSector(mfSectorNum(blockNo)) > 4) ? 5 : 1; + for (int i = 0; i < 4; i++) { + PrintAndLogEx(NORMAL, "Access block %d%s: %s", bln, ((blinc > 1) && (i < 3) ? "+" : "") , mfGetAccessConditionsDesc(i, &data[6])); + bln += blinc; + } + PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&data[9], 1)); + } + + return 0; +} + +int CmdHF14AMfCGetSc(const char *Cmd) { + uint8_t data[16] = {0}; + uint8_t sector = 0; + int i, res, flags; + + char ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_cgetsc(); + + sector = param_get8(Cmd, 0); + if (sector > 39) { + PrintAndLogEx(WARNING, "Sector number must be less then 40"); + return 1; + } + + PrintAndLogEx(NORMAL, "\n # | data | Sector | %02d/ 0x%02X ", sector, sector); + PrintAndLogEx(NORMAL, "----+------------------------------------------------"); + uint8_t blocks = 4; + uint8_t start = sector * 4; + if ( sector > 32 ) { + blocks = 16; + start = 128 + ( sector - 32 ) * 16; + } + + flags = MAGIC_INIT + MAGIC_WUPC; + + for (i = 0; i < blocks; i++) { + if (i == 1) flags = 0; + if (i == blocks-1) flags = MAGIC_HALT + MAGIC_OFF; + + res = mfCGetBlock( start + i, data, flags); + if (res) { + PrintAndLogEx(WARNING, "Can't read block. %d error=%d", start + i, res); + return 1; + } + PrintAndLogEx(NORMAL, "%3d | %s", start + i, sprint_hex(data, 16)); + } + return 0; +} + +int CmdHF14AMfCSave(const char *Cmd) { + + char filename[FILE_PATH_SIZE]; + char * fnameptr = filename; + uint8_t *dump; + bool fillEmulator = false; + bool errors = false, hasname = false, useuid = false; + int i, len, flags; + uint8_t numblocks = 0, cmdp = 0; + uint16_t bytes = 0; + char ctmp; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + ctmp = tolower(param_getchar(Cmd, cmdp)); + switch (ctmp) { + case 'e': + useuid = true; + fillEmulator = true; + cmdp++; + break; + case 'h': + return usage_hf14_csave(); + case '0': + case '1': + case '2': + case '4': + numblocks = NumOfBlocks(ctmp); + bytes = numblocks * MFBLOCK_SIZE; + PrintAndLogEx(SUCCESS, "Saving magic mifare %cK", ctmp); + cmdp++; + break; + case 'u': + useuid = true; + hasname = true; + cmdp++; + break; + case 'o': + len = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); + if (len < 1) { + errors = true; + break; + } + + useuid = false; + hasname = true; + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + if (!hasname && !fillEmulator) errors = true; + + if (errors || cmdp == 0) return usage_hf14_csave(); + + dump = calloc(bytes, sizeof(uint8_t)); + if (!dump) { + PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); + return 1; + } + memset(dump, 0, bytes); + + flags = MAGIC_INIT + MAGIC_WUPC; + for (i = 0; i < numblocks; i++) { + if (i == 1) flags = 0; + if (i == numblocks - 1) flags = MAGIC_HALT + MAGIC_OFF; + + if (mfCGetBlock(i, dump + (i*MFBLOCK_SIZE), flags)) { + PrintAndLogEx(WARNING, "Cant get block: %d", i); + free(dump); + return 2; + } + } + + if ( useuid ){ + fnameptr += sprintf(fnameptr, "hf-mf-"); + FillFileNameByUID(fnameptr, dump, "-dump", 4); + } + + if (fillEmulator) { + PrintAndLogEx(INFO, "uploading to emulator memory"); + for (i = 0; i < numblocks; i += 5) { + if (mfEmlSetMem(dump + (i*MFBLOCK_SIZE), i, 5)) { + PrintAndLogEx(WARNING, "Cant set emul block: %d", i); + } + printf("."); fflush(stdout); + } + PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(SUCCESS, "uploaded %d bytes to emulator memory", bytes); + } + + saveFile(filename, "bin", dump, bytes); + saveFileEML(filename, "eml", dump, bytes, MFBLOCK_SIZE); + saveFileJSON(filename, "json", jsfCardMemory, dump, bytes); + free(dump); + return 0; +} + +//needs nt, ar, at, Data to decrypt +int CmdHf14AMfDecryptBytes(const char *Cmd){ + + char ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_decryptbytes(); + + uint32_t nt = param_get32ex(Cmd,0,0,16); + uint32_t ar_enc = param_get32ex(Cmd,1,0,16); + uint32_t at_enc = param_get32ex(Cmd,2,0,16); + + int len = param_getlength(Cmd, 3); + if (len & 1 ) { + PrintAndLogEx(WARNING, "Uneven hex string length. LEN=%d", len); + return 1; + } + + PrintAndLogEx(NORMAL, "nt\t%08X", nt); + PrintAndLogEx(NORMAL, "ar enc\t%08X", ar_enc); + PrintAndLogEx(NORMAL, "at enc\t%08X", at_enc); + + uint8_t *data = calloc(len, sizeof(uint8_t)); + param_gethex_ex(Cmd, 3, data, &len); + len >>= 1; + tryDecryptWord( nt, ar_enc, at_enc, data, len); + free (data); + return 0; +} + +int CmdHf14AMfSetMod(const char *Cmd) { + uint8_t key[6] = {0, 0, 0, 0, 0, 0}; + uint8_t mod = 2; + + char ctmp = param_getchar(Cmd, 0); + if (ctmp == '0') { + mod = 0; + } else if (ctmp == '1') { + mod = 1; + } + int gethexfail = param_gethex(Cmd, 1, key, 12); + if (mod == 2 || gethexfail) { + PrintAndLogEx(NORMAL, "Sets the load modulation strength of a MIFARE Classic EV1 card."); + PrintAndLogEx(NORMAL, "Usage: hf mf setmod <0|1> "); + PrintAndLogEx(NORMAL, " 0 = normal modulation"); + PrintAndLogEx(NORMAL, " 1 = strong modulation (default)"); + return 1; + } + + UsbCommand c = {CMD_MIFARE_SETMOD, {mod, 0, 0}}; + memcpy(c.d.asBytes, key, 6); + clearCommandBuffer(); + SendCommand(&c); + + UsbCommand resp; + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + uint8_t ok = resp.arg[0] & 0xff; + PrintAndLogEx(SUCCESS, "isOk:%02x", ok); + if (!ok) + PrintAndLogEx(FAILED, "Failed."); + } else { + PrintAndLogEx(WARNING, "Command execute timeout"); + } + return 0; +} + +// Mifare NACK bug detection +int CmdHf14AMfNack(const char *Cmd) { + + bool verbose = false; + char ctmp = tolower(param_getchar(Cmd, 0)); + if ( ctmp == 'h' ) return usage_hf14_nack(); + if ( ctmp == 'v' ) verbose = true; + + if ( verbose ) + PrintAndLogEx(INFO, "Started testing card for NACK bug. Press key to abort"); + + detect_classic_nackbug(verbose); + return 0; +} + +int CmdHF14AMfice(const char *Cmd) { + + uint8_t blockNo = 0; + uint8_t keyType = 0; + uint8_t trgBlockNo = 0; + uint8_t trgKeyType = 1; + bool slow = false; + bool initialize = true; + bool acquisition_completed = false; + uint8_t cmdp=0; + uint32_t flags = 0; + uint32_t total_num_nonces = 0; + char ctmp; + char filename[FILE_PATH_SIZE], *fptr; + FILE *fnonces = NULL; + UsbCommand resp; + + uint32_t part_limit = 3000; + uint32_t limit = 50000; + + while ((ctmp = param_getchar(Cmd, cmdp))) { + switch(tolower(ctmp)) + { + case 'h': + return usage_hf14_ice(); + case 'f': + param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); + cmdp++; + break; + case 'l': + limit = param_get32ex(Cmd, cmdp+1, 50000, 10); + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", ctmp); + usage_hf14_ice(); + return 1; + } + cmdp++; + } + + if(filename[0]=='\0') + { + fptr = GenerateFilename("hf-mf-","-nonces.bin"); + if (fptr == NULL) + return 1; + strcpy(filename, fptr); + } + + PrintAndLogEx(NORMAL, "Collecting %u nonces \n", limit); + + if ((fnonces = fopen(filename,"wb")) == NULL) { + PrintAndLogEx(WARNING, "Could not create file " _YELLOW_(%s),filename); + return 3; + } + + clearCommandBuffer(); + + uint64_t t1 = msclock(); + + do { + if (ukbhit()) { + int gc = getchar(); (void)gc; + PrintAndLogEx(INFO, "\naborted via keyboard!\n"); + break; + } + + flags = 0; + flags |= initialize ? 0x0001 : 0; + flags |= slow ? 0x0002 : 0; + UsbCommand c = {CMD_MIFARE_ACQUIRE_NONCES, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, flags}}; + clearCommandBuffer(); + SendCommand(&c); + + if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) goto out; + if (resp.arg[0]) goto out; + + uint32_t items = resp.arg[2]; + if (fnonces) { + fwrite(resp.d.asBytes, 1, items*4, fnonces); + fflush(fnonces); + } + + total_num_nonces += items; + if ( total_num_nonces > part_limit ) { + PrintAndLogEx(INFO, "Total nonces %u\n", total_num_nonces); + part_limit += 3000; + } + + acquisition_completed = ( total_num_nonces > limit); + + initialize = false; + + } while (!acquisition_completed); + +out: + PrintAndLogEx(SUCCESS, "time: %" PRIu64 " seconds\n", (msclock()-t1)/1000); + + if ( fnonces ) { + fflush(fnonces); + fclose(fnonces); + } + + UsbCommand c = {CMD_MIFARE_ACQUIRE_NONCES, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, 4}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; +} + +int CmdHF14AMfAuth4(const char *Cmd) { + uint8_t keyn[20] = {0}; + int keynlen = 0; + uint8_t key[16] = {0}; + int keylen = 0; + + CLIParserInit("hf mf auth4", + "Executes AES authentication command in ISO14443-4", + "Usage:\n\thf mf auth4 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n" + "\thf mf auth4 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -> executes authentication\n"); + + void* argtable[] = { + arg_param_begin, + arg_str1(NULL, NULL, "", NULL), + arg_str1(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(Cmd, argtable, true); + + CLIGetHexWithReturn(1, keyn, &keynlen); + CLIGetHexWithReturn(2, key, &keylen); + CLIParserFree(); + + if (keynlen != 2) { + PrintAndLogEx(ERR, " must be 2 bytes long instead of: %d", keynlen); + return 1; + } + + if (keylen != 16) { + PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); + return 1; + } + + return MifareAuth4(NULL, keyn, key, true, false, true); +} + +// https://www.nxp.com/docs/en/application-note/AN10787.pdf +int CmdHF14AMfMAD(const char *cmd) { + + CLIParserInit("hf mf mad", + "Checks and prints Mifare Application Directory (MAD)", + "Usage:\n\thf mf mad -> shows MAD if exists\n" + "\thf mf mad -a 03e1 -k ffffffffffff -b -> shows NDEF data if exists. read card with custom key and key B\n"); + + void* argtable[] = { + arg_param_begin, + arg_lit0("vV", "verbose", "show technical data"), + arg_str0("aA", "aid", "print all sectors with aid", NULL), + arg_str0("kK", "key", "key for printing sectors", NULL), + arg_lit0("bB", "keyb", "use key B for access printing sectors (by default: key A)"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + bool verbose = arg_get_lit(1); + uint8_t aid[2] = {0}; + int aidlen; + CLIGetHexWithReturn(2, aid, &aidlen); + uint8_t key[6] = {0}; + int keylen; + CLIGetHexWithReturn(3, key, &keylen); + bool keyB = arg_get_lit(4); + + CLIParserFree(); + + if (aidlen != 2 && keylen > 0) { + PrintAndLogEx(WARNING, "do not need a key without aid."); + } + + uint8_t sector0[16 * 4] = {0}; + uint8_t sector10[16 * 4] = {0}; + if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0)) { + PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); + return 2; + } + + if (verbose) { + for(int i = 0; i < 4; i ++) + PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(§or0[i * 16], 16)); + } + + bool haveMAD2 = false; + MAD1DecodeAndPrint(sector0, verbose, &haveMAD2); + + if (haveMAD2) { + if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10)) { + PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); + return 2; + } + + MAD2DecodeAndPrint(sector10, verbose); + } + + if (aidlen == 2) { + uint16_t aaid = (aid[0] << 8) + aid[1]; + PrintAndLogEx(NORMAL, "\n-------------- AID 0x%04x ---------------", aaid); + + uint16_t mad[7 + 8 + 8 + 8 + 8] = {0}; + size_t madlen = 0; + if (MADDecode(sector0, sector10, mad, &madlen)) { + PrintAndLogEx(ERR, "can't decode mad."); + return 10; + } + + uint8_t akey[6] = {0}; + memcpy(akey, g_mifare_ndef_key, 6); + if (keylen == 6) { + memcpy(akey, key, 6); + } + + for (int i = 0; i < madlen; i++) { + if (aaid == mad[i]) { + uint8_t vsector[16 * 4] = {0}; + if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, akey, vsector)) { + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(ERR, "read sector %d error.", i + 1); + return 2; + } + + for(int j = 0; j < (verbose ? 4 : 3); j ++) + PrintAndLogEx(NORMAL, " [%03d] %s", (i + 1) * 4 + j, sprint_hex(&vsector[j * 16], 16)); + } + } + } + + return 0; +} + +int CmdHFMFNDEF(const char *cmd) { + + CLIParserInit("hf mf ndef", + "Prints NFC Data Exchange Format (NDEF)", + "Usage:\n\thf mf ndef -> shows NDEF data\n" + "\thf mf ndef -a 03e1 -k ffffffffffff -b -> shows NDEF data with custom AID, key and with key B\n"); + + void* argtable[] = { + arg_param_begin, + arg_litn("vV", "verbose", 0, 2, "show technical data"), + arg_str0("aA", "aid", "replace default aid for NDEF", NULL), + arg_str0("kK", "key", "replace default key for NDEF", NULL), + arg_lit0("bB", "keyb", "use key B for access sectors (by default: key A)"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); + + bool verbose = arg_get_lit(1); + bool verbose2 = arg_get_lit(1) > 1; + uint8_t aid[2] = {0}; + int aidlen; + CLIGetHexWithReturn(2, aid, &aidlen); + uint8_t key[6] = {0}; + int keylen; + CLIGetHexWithReturn(3, key, &keylen); + bool keyB = arg_get_lit(4); + + CLIParserFree(); + + uint16_t ndefAID = 0x03e1; + if (aidlen == 2) + ndefAID = (aid[0] << 8) + aid[1]; + + uint8_t ndefkey[6] = {0}; + memcpy(ndefkey, g_mifare_ndef_key, 6); + if (keylen == 6) { + memcpy(ndefkey, key, 6); + } + + uint8_t sector0[16 * 4] = {0}; + uint8_t sector10[16 * 4] = {0}; + uint8_t data[4096] = {0}; + int datalen = 0; + + PrintAndLogEx(NORMAL, ""); + + if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0)) { + PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); + return 2; + } + + bool haveMAD2 = false; + int res = MADCheck(sector0, NULL, verbose, &haveMAD2); + if (res) { + PrintAndLogEx(ERR, "MAD error %d.", res); + return res; + } + + if (haveMAD2) { + if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10)) { + PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); + return 2; + } + } + + uint16_t mad[7 + 8 + 8 + 8 + 8] = {0}; + size_t madlen = 0; + if (MADDecode(sector0, (haveMAD2 ? sector10 : NULL), mad, &madlen)) { + PrintAndLogEx(ERR, "can't decode mad."); + return 10; + } + + printf("data reading:"); + for (int i = 0; i < madlen; i++) { + if (ndefAID == mad[i]) { + uint8_t vsector[16 * 4] = {0}; + if (mfReadSector(i + 1, keyB ? MF_KEY_B : MF_KEY_A, ndefkey, vsector)) { + PrintAndLogEx(ERR, "read sector %d error.", i + 1); + return 2; + } + + memcpy(&data[datalen], vsector, 16 * 3); + datalen += 16 * 3; + + printf("."); + } + } + printf(" OK\n"); + + if (!datalen) { + PrintAndLogEx(ERR, "no NDEF data."); + return 11; + } + + if (verbose2) { + PrintAndLogEx(NORMAL, "NDEF data:"); + dump_buffer(data, datalen, stdout, 1); + } + + NDEFDecodeAndPrint(data, datalen, verbose); + + return 0; +} + +int CmdHF14AMfList(const char *Cmd) { + CmdTraceList("mf"); + return 0; +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"list", CmdHF14AMfList, 0, "[Deprecated] List ISO 14443-a / Mifare history"}, + {"darkside", CmdHF14AMfDarkside, 0, "Darkside attack. read parity error messages."}, + {"nested", CmdHF14AMfNested, 0, "Nested attack. Test nested authentication"}, + {"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"}, + {"keybrute", CmdHF14AMfKeyBrute, 0, "J_Run's 2nd phase of multiple sector nested authentication key recovery"}, + {"nack", CmdHf14AMfNack, 0, "Test for Mifare NACK bug"}, + {"chk", CmdHF14AMfChk, 0, "Check keys"}, + {"fchk", CmdHF14AMfChk_fast, 0, "Check keys fast, targets all keys on card"}, + {"decrypt", CmdHf14AMfDecryptBytes, 1, "[nt] [ar_enc] [at_enc] [data] - to decrypt snoop or trace"}, + {"-----------", CmdHelp, 1, ""}, + {"dbg", CmdHF14AMfDbg, 0, "Set default debug mode"}, + {"rdbl", CmdHF14AMfRdBl, 0, "Read MIFARE classic block"}, + {"rdsc", CmdHF14AMfRdSc, 0, "Read MIFARE classic sector"}, + {"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"}, + {"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"}, + {"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"}, + {"setmod", CmdHf14AMfSetMod, 0, "Set MIFARE Classic EV1 load modulation strength"}, + {"auth4", CmdHF14AMfAuth4, 0, "ISO14443-4 AES authentication"}, +// {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"}, + {"-----------", CmdHelp, 1, ""}, + {"sim", CmdHF14AMf1kSim, 0, "Simulate MIFARE card"}, + {"eclr", CmdHF14AMfEClear, 0, "Clear simulator memory block"}, + {"eget", CmdHF14AMfEGet, 0, "Get simulator memory block"}, + {"eset", CmdHF14AMfESet, 0, "Set simulator memory block"}, + {"eload", CmdHF14AMfELoad, 0, "Load from file emul dump"}, + {"esave", CmdHF14AMfESave, 0, "Save to file emul dump"}, + {"ecfill", CmdHF14AMfECFill, 0, "Fill simulator memory with help of keys from simulator"}, + {"ekeyprn", CmdHF14AMfEKeyPrn, 0, "Print keys from simulator memory"}, + {"-----------", CmdHelp, 1, ""}, + {"csetuid", CmdHF14AMfCSetUID, 0, "Set UID for magic Chinese card"}, + {"csetblk", CmdHF14AMfCSetBlk, 0, "Write block - Magic Chinese card"}, + {"cgetblk", CmdHF14AMfCGetBlk, 0, "Read block - Magic Chinese card"}, + {"cgetsc", CmdHF14AMfCGetSc, 0, "Read sector - Magic Chinese card"}, + {"cload", CmdHF14AMfCLoad, 0, "Load dump into magic Chinese card"}, + {"csave", CmdHF14AMfCSave, 0, "Save dump from magic Chinese card into file or emulator"}, + {"-----------", CmdHelp, 1, ""}, + {"mad", CmdHF14AMfMAD, 0, "Checks and prints MAD"}, + {"ndef", CmdHFMFNDEF, 0, "Prints NDEF records from card"}, + + {"ice", CmdHF14AMfice, 0, "collect Mifare Classic nonces to file"}, + {NULL, NULL, 0, NULL} +}; + +int CmdHFMF(const char *Cmd) { + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdhfmf.h b/client/cmdhfmf.h index c819d5bef..a8e622cc7 100644 --- a/client/cmdhfmf.h +++ b/client/cmdhfmf.h @@ -1,76 +1,76 @@ -//----------------------------------------------------------------------------- -// Copyright (C) 2011 Merlok -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// High frequency MIFARE commands -//----------------------------------------------------------------------------- - -#ifndef CMDHFMF_H__ -#define CMDHFMF_H__ - -#include -#include -#include -#include -#include -#include -#include "proxmark3.h" -#include "iso14443crc.h" -#include "ui.h" -#include "cmdparser.h" -#include "common.h" -#include "util.h" -#include "mifare.h" // nonces_t struct -#include "mifare/mfkey.h" // mfkey32_moebious -#include "cmdhfmfhard.h" -#include "mifare/mifarehost.h" // icesector_t, sector_t -#include "util_posix.h" // msclock -#include "mifare/mifaredefault.h" // mifare default key array -#include "cmdhf14a.h" // dropfield -#include "cliparser/cliparser.h" // argtable -#include "hardnested/hardnested_bf_core.h" // SetSIMDInstr - -extern int CmdHFMF(const char *Cmd); - -extern int CmdHF14AMfList(const char *Cmd); -extern int CmdHF14AMfDbg(const char* cmd); -extern int CmdHF14AMfRdBl(const char* cmd); -extern int CmdHF14AMfURdBl(const char* cmd); -extern int CmdHF14AMfRdSc(const char* cmd); -extern int CmdHF14SMfURdCard(const char* cmd); -extern int CmdHF14AMfDump(const char* cmd); -extern int CmdHF14AMfRestore(const char* cmd); -extern int CmdHF14AMfWrBl(const char* cmd); -extern int CmdHF14AMfUWrBl(const char* cmd); -extern int CmdHF14AMfChk(const char* cmd); -extern int CmdHF14AMfDarkside(const char* cmd); -extern int CmdHF14AMfNested(const char* cmd); -extern int CmdHF14AMfNestedHard(const char *Cmd); -//extern int CmdHF14AMfSniff(const char* cmd); -extern int CmdHF14AMf1kSim(const char* cmd); -extern int CmdHF14AMfKeyBrute(const char *Cmd); -extern int CmdHF14AMfEClear(const char* cmd); -extern int CmdHF14AMfEGet(const char* cmd); -extern int CmdHF14AMfESet(const char* cmd); -extern int CmdHF14AMfELoad(const char* cmd); -extern int CmdHF14AMfESave(const char* cmd); -extern int CmdHF14AMfECFill(const char* cmd); -extern int CmdHF14AMfEKeyPrn(const char* cmd); -extern int CmdHF14AMfCSetUID(const char* cmd); -extern int CmdHF14AMfCSetBlk(const char* cmd); -extern int CmdHF14AMfCGetBlk(const char* cmd); -extern int CmdHF14AMfCGetSc(const char* cmd); -extern int CmdHF14AMfCLoad(const char* cmd); -extern int CmdHF14AMfCSave(const char* cmd); -extern int CmdHf14MfDecryptBytes(const char *Cmd); -extern int CmdHf14AMfSetMod(const char *Cmd); -extern int CmdHf14AMfNack(const char *Cmd); - -void showSectorTable(void); -void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose); -void printKeyTable( uint8_t sectorscnt, sector_t *e_sector ); -void printKeyTable_fast( uint8_t sectorscnt, icesector_t *e_sector, uint64_t bar, uint64_t foo ); -#endif +//----------------------------------------------------------------------------- +// Copyright (C) 2011 Merlok +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// High frequency MIFARE commands +//----------------------------------------------------------------------------- + +#ifndef CMDHFMF_H__ +#define CMDHFMF_H__ + +#include +#include +#include +#include +#include +#include +#include "proxmark3.h" +#include "iso14443crc.h" +#include "ui.h" +#include "cmdparser.h" +#include "common.h" +#include "util.h" +#include "mifare.h" // nonces_t struct +#include "mifare/mfkey.h" // mfkey32_moebious +#include "cmdhfmfhard.h" +#include "mifare/mifarehost.h" // icesector_t, sector_t +#include "util_posix.h" // msclock +#include "mifare/mifaredefault.h" // mifare default key array +#include "cmdhf14a.h" // dropfield +#include "cliparser/cliparser.h" // argtable +#include "hardnested/hardnested_bf_core.h" // SetSIMDInstr + +extern int CmdHFMF(const char *Cmd); + +extern int CmdHF14AMfList(const char *Cmd); +extern int CmdHF14AMfDbg(const char* cmd); +extern int CmdHF14AMfRdBl(const char* cmd); +extern int CmdHF14AMfURdBl(const char* cmd); +extern int CmdHF14AMfRdSc(const char* cmd); +extern int CmdHF14SMfURdCard(const char* cmd); +extern int CmdHF14AMfDump(const char* cmd); +extern int CmdHF14AMfRestore(const char* cmd); +extern int CmdHF14AMfWrBl(const char* cmd); +extern int CmdHF14AMfUWrBl(const char* cmd); +extern int CmdHF14AMfChk(const char* cmd); +extern int CmdHF14AMfDarkside(const char* cmd); +extern int CmdHF14AMfNested(const char* cmd); +extern int CmdHF14AMfNestedHard(const char *Cmd); +//extern int CmdHF14AMfSniff(const char* cmd); +extern int CmdHF14AMf1kSim(const char* cmd); +extern int CmdHF14AMfKeyBrute(const char *Cmd); +extern int CmdHF14AMfEClear(const char* cmd); +extern int CmdHF14AMfEGet(const char* cmd); +extern int CmdHF14AMfESet(const char* cmd); +extern int CmdHF14AMfELoad(const char* cmd); +extern int CmdHF14AMfESave(const char* cmd); +extern int CmdHF14AMfECFill(const char* cmd); +extern int CmdHF14AMfEKeyPrn(const char* cmd); +extern int CmdHF14AMfCSetUID(const char* cmd); +extern int CmdHF14AMfCSetBlk(const char* cmd); +extern int CmdHF14AMfCGetBlk(const char* cmd); +extern int CmdHF14AMfCGetSc(const char* cmd); +extern int CmdHF14AMfCLoad(const char* cmd); +extern int CmdHF14AMfCSave(const char* cmd); +extern int CmdHf14MfDecryptBytes(const char *Cmd); +extern int CmdHf14AMfSetMod(const char *Cmd); +extern int CmdHf14AMfNack(const char *Cmd); + +void showSectorTable(void); +void readerAttack(nonces_t data, bool setEmulatorMem, bool verbose); +void printKeyTable( uint8_t sectorscnt, sector_t *e_sector ); +void printKeyTable_fast( uint8_t sectorscnt, icesector_t *e_sector, uint64_t bar, uint64_t foo ); +#endif diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 9a1e6cc71..e94ec84fe 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1,2056 +1,2056 @@ -//----------------------------------------------------------------------------- -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Low frequency T55xx commands -//----------------------------------------------------------------------------- -#include "cmdlft55xx.h" - -// Default configuration -t55xx_conf_block_t config = { .modulation = DEMOD_ASK, .inverted = false, .offset = 0x00, .block0 = 0x00, .Q5 = false }; - -t55xx_conf_block_t Get_t55xx_Config(){ - return config; -} -void Set_t55xx_Config(t55xx_conf_block_t conf){ - config = conf; -} - -int usage_t55xx_config(){ - PrintAndLogEx(NORMAL, "Usage: lf t55xx config [d ] [i 1] [o ] [Q5]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - This help"); - PrintAndLogEx(NORMAL, " b <8|16|32|40|50|64|100|128> - Set bitrate"); - PrintAndLogEx(NORMAL, " d - Set demodulation FSK / ASK / PSK / NRZ / Biphase / Biphase A"); - PrintAndLogEx(NORMAL, " i [1] - Invert data signal, defaults to normal"); - PrintAndLogEx(NORMAL, " o [offset] - Set offset, where data should start decode in bitstream"); - PrintAndLogEx(NORMAL, " Q5 - Set as Q5(T5555) chip instead of T55x7"); - PrintAndLogEx(NORMAL, " ST - Set Sequence Terminator on"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx config d FSK - FSK demodulation"); - PrintAndLogEx(NORMAL, " lf t55xx config d FSK i 1 - FSK demodulation, inverse data"); - PrintAndLogEx(NORMAL, " lf t55xx config d FSK i 1 o 3 - FSK demodulation, inverse data, offset=3,start from position 3 to decode data"); - PrintAndLogEx(NORMAL, ""); - return 0; -} -int usage_t55xx_read(){ - PrintAndLogEx(NORMAL, "Usage: lf t55xx read [b ] [p ] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " b - block number to read. Between 0-7"); - PrintAndLogEx(NORMAL, " p - OPTIONAL password (8 hex characters)"); - PrintAndLogEx(NORMAL, " o - OPTIONAL override safety check"); - PrintAndLogEx(NORMAL, " 1 - OPTIONAL read Page 1 instead of Page 0"); - PrintAndLogEx(NORMAL, " ****WARNING****"); - PrintAndLogEx(NORMAL, " Use of read with password on a tag not configured for a pwd"); - PrintAndLogEx(NORMAL, " can damage the tag"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx read b 0 - read data from block 0"); - PrintAndLogEx(NORMAL, " lf t55xx read b 0 p feedbeef - read data from block 0 password feedbeef"); - PrintAndLogEx(NORMAL, " lf t55xx read b 0 p feedbeef o - read data from block 0 password feedbeef safety check"); - PrintAndLogEx(NORMAL, ""); - return 0; -} -int usage_t55xx_write(){ - PrintAndLogEx(NORMAL, "Usage: lf t55xx write [b ] [d ] [p ] [1] [t]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " b - block number to write. Between 0-7"); - PrintAndLogEx(NORMAL, " d - 4 bytes of data to write (8 hex characters)"); - PrintAndLogEx(NORMAL, " p - OPTIONAL password 4bytes (8 hex characters)"); - PrintAndLogEx(NORMAL, " 1 - OPTIONAL write Page 1 instead of Page 0"); - PrintAndLogEx(NORMAL, " t - OPTIONAL test mode write - ****DANGER****"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx write b 3 d 11223344 - write 11223344 to block 3"); - PrintAndLogEx(NORMAL, " lf t55xx write b 3 d 11223344 p feedbeef - write 11223344 to block 3 password feedbeef"); - PrintAndLogEx(NORMAL, ""); - return 0; -} -int usage_t55xx_trace() { - PrintAndLogEx(NORMAL, "Usage: lf t55xx trace [1]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx trace"); - PrintAndLogEx(NORMAL, " lf t55xx trace 1"); - PrintAndLogEx(NORMAL, ""); - return 0; -} -int usage_t55xx_info() { - PrintAndLogEx(NORMAL, "Usage: lf t55xx info [1]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx info"); - PrintAndLogEx(NORMAL, " lf t55xx info 1"); - PrintAndLogEx(NORMAL, ""); - return 0; -} -int usage_t55xx_dump(){ - PrintAndLogEx(NORMAL, "Usage: lf t55xx dump [o]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " - OPTIONAL password 4bytes (8 hex symbols)"); - PrintAndLogEx(NORMAL, " o - OPTIONAL override, force pwd read despite danger to card"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx dump"); - PrintAndLogEx(NORMAL, " lf t55xx dump feedbeef o"); - PrintAndLogEx(NORMAL, ""); - return 0; -} -int usage_t55xx_detect(){ - PrintAndLogEx(NORMAL, "Usage: lf t55xx detect [1] [p ]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag."); - PrintAndLogEx(NORMAL, " p - OPTIONAL password (8 hex characters)"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx detect"); - PrintAndLogEx(NORMAL, " lf t55xx detect 1"); - PrintAndLogEx(NORMAL, " lf t55xx detect p 11223344"); - PrintAndLogEx(NORMAL, ""); - return 0; -} -int usage_t55xx_detectP1(){ - PrintAndLogEx(NORMAL, "Command: Detect Page 1 of a t55xx chip"); - PrintAndLogEx(NORMAL, "Usage: lf t55xx p1detect [1] [p ]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag."); - PrintAndLogEx(NORMAL, " p - OPTIONAL password (8 hex characters)"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx p1detect"); - PrintAndLogEx(NORMAL, " lf t55xx p1detect 1"); - PrintAndLogEx(NORMAL, " lf t55xx p1detect p 11223344"); - PrintAndLogEx(NORMAL, ""); - return 0; -} -int usage_t55xx_wakup(){ - PrintAndLogEx(NORMAL, "Usage: lf t55xx wakeup [h] p "); - PrintAndLogEx(NORMAL, "This commands send the Answer-On-Request command and leaves the readerfield ON afterwards."); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " p - password 4bytes (8 hex symbols)"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx wakeup p 11223344 - send wakeup password"); - return 0; -} -int usage_t55xx_chk(){ - PrintAndLogEx(NORMAL, "This command uses a dictionary attack"); - PrintAndLogEx(NORMAL, "press 'enter' to cancel the command"); - PrintAndLogEx(NORMAL, "Usage: lf t55xx bruteforce [h] [i <*.dic>]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " m - use dictionary from flashmemory\n"); - PrintAndLogEx(NORMAL, " i <*.dic> - loads a default keys dictionary file <*.dic>"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx bruteforce m"); - PrintAndLogEx(NORMAL, " lf t55xx bruteforce i default_pwd.dic"); - PrintAndLogEx(NORMAL, ""); - return 0; -} -int usage_t55xx_bruteforce(){ - PrintAndLogEx(NORMAL, "This command uses bruteforce to scan a number range"); - PrintAndLogEx(NORMAL, "press 'enter' to cancel the command"); - PrintAndLogEx(NORMAL, "Usage: lf t55xx bruteforce [h] "); - PrintAndLogEx(NORMAL, " password must be 4 bytes (8 hex symbols)"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " - 4 byte hex value to start pwd search at"); - PrintAndLogEx(NORMAL, " - 4 byte hex value to end pwd search at"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx bruteforce aaaaaaaa bbbbbbbb"); - PrintAndLogEx(NORMAL, ""); - return 0; -} -int usage_t55xx_recoverpw(){ - PrintAndLogEx(NORMAL, "This command uses a few tricks to try to recover mangled password"); - PrintAndLogEx(NORMAL, "press 'enter' to cancel the command"); - PrintAndLogEx(NORMAL, "WARNING: this may brick non-password protected chips!"); - PrintAndLogEx(NORMAL, "Usage: lf t55xx recoverpw [password]"); - PrintAndLogEx(NORMAL, " password must be 4 bytes (8 hex symbols)"); - PrintAndLogEx(NORMAL, " default password is 51243648, used by many cloners"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " [password] - 4 byte hex value of password written by cloner"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx recoverpw"); - PrintAndLogEx(NORMAL, " lf t55xx recoverpw 51243648"); - PrintAndLogEx(NORMAL, ""); - return 0; -}int usage_t55xx_wipe(){ - PrintAndLogEx(NORMAL, "Usage: lf t55xx wipe [h] [Q5]"); - PrintAndLogEx(NORMAL, "This commands wipes a tag, fills blocks 1-7 with zeros and a default configuration block"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " Q5 - indicates to use the T5555 (Q5) default configuration block"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx wipe - wipes a t55x7 tag, config block 0x000880E0"); - PrintAndLogEx(NORMAL, " lf t55xx wipe Q5 - wipes a t5555 Q5 tag, config block 0x6001F004"); - return 0; -} -int usage_lf_deviceconfig(){ - PrintAndLogEx(NORMAL, "Sets t55x7 timings for direkt commands. The timings are set here in Field Clocks (FC), \nwhich is converted to (US) on device"); - PrintAndLogEx(NORMAL, "Usage: lf t55xx deviceconfig a b c d e p"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - This help"); - PrintAndLogEx(NORMAL, " a <8..255> - Set start gap"); - PrintAndLogEx(NORMAL, " b <8..255> - Set write gap"); - PrintAndLogEx(NORMAL, " c <8..255> - Set write ZERO gap"); - PrintAndLogEx(NORMAL, " d <8..255> - Set write ONE gap"); - PrintAndLogEx(NORMAL, " e <8..255> - Set read gap"); - PrintAndLogEx(NORMAL, " p - persist to flashmemory"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 29 b 17 c 15 d 47 e 15 - default T55XX"); - PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 55 b 14 c 21 d 30 - default EM4305"); - PrintAndLogEx(NORMAL, ""); - return 0; -} - -int CmdHelp(const char *Cmd); - -void printT5xxHeader(uint8_t page){ - PrintAndLogEx(NORMAL, "Reading Page %d:", page); - PrintAndLogEx(NORMAL, "blk | hex data | binary | ascii"); - PrintAndLogEx(NORMAL, "----+----------+----------------------------------+-------"); -} - -int CmdT55xxSetConfig(const char *Cmd) { - - uint8_t offset = 0; - char modulation[6] = {0x00}; - char tmp = 0x00; - uint8_t bitRate = 0; - uint8_t rates[9] = {8,16,32,40,50,64,100,128,0}; - uint8_t cmdp = 0; - bool errors = false; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - tmp = tolower(param_getchar(Cmd, cmdp)); - switch(tmp) { - case 'h': - return usage_t55xx_config(); - case 'b': - errors |= param_getdec(Cmd, cmdp+1, &bitRate); - if ( !errors){ - uint8_t i = 0; - for (; i < 9; i++){ - if (rates[i]==bitRate) { - config.bitrate = i; - break; - } - } - if (i==9) errors = true; - } - cmdp+=2; - break; - case 'd': - param_getstr(Cmd, cmdp+1, modulation, sizeof(modulation)); - cmdp += 2; - - if ( strcmp(modulation, "FSK" ) == 0) { - config.modulation = DEMOD_FSK; - } else if ( strcmp(modulation, "FSK1" ) == 0) { - config.modulation = DEMOD_FSK1; - config.inverted=1; - } else if ( strcmp(modulation, "FSK1a" ) == 0) { - config.modulation = DEMOD_FSK1a; - config.inverted=0; - } else if ( strcmp(modulation, "FSK2" ) == 0) { - config.modulation = DEMOD_FSK2; - config.inverted=0; - } else if ( strcmp(modulation, "FSK2a" ) == 0) { - config.modulation = DEMOD_FSK2a; - config.inverted=1; - } else if ( strcmp(modulation, "ASK" ) == 0) { - config.modulation = DEMOD_ASK; - } else if ( strcmp(modulation, "NRZ" ) == 0) { - config.modulation = DEMOD_NRZ; - } else if ( strcmp(modulation, "PSK1" ) == 0) { - config.modulation = DEMOD_PSK1; - } else if ( strcmp(modulation, "PSK2" ) == 0) { - config.modulation = DEMOD_PSK2; - } else if ( strcmp(modulation, "PSK3" ) == 0) { - config.modulation = DEMOD_PSK3; - } else if ( strcmp(modulation, "BIa" ) == 0) { - config.modulation = DEMOD_BIa; - config.inverted=1; - } else if ( strcmp(modulation, "BI" ) == 0) { - config.modulation = DEMOD_BI; - config.inverted=0; - } else { - PrintAndLogEx(WARNING, "Unknown modulation '%s'", modulation); - errors = true; - } - break; - case 'i': - config.inverted = param_getchar(Cmd,cmdp+1) == '1'; - cmdp+=2; - break; - case 'o': - errors |= param_getdec(Cmd, cmdp+1, &offset); - if ( !errors ) - config.offset = offset; - cmdp+=2; - break; - case 'q': - config.Q5 = true; - cmdp++; - break; - case 's': - config.ST = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - - // No args - if (cmdp == 0) return printConfiguration( config ); - - //Validations - if (errors) return usage_t55xx_config(); - - config.block0 = 0; - return printConfiguration ( config ); -} - -int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32_t password){ - //Password mode - if ( usepwd ) { - // try reading the config block and verify that PWD bit is set before doing this! - if ( !override ) { - - if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, false, 0 ) ) return 0; - - if ( !tryDetectModulation() ) { - PrintAndLogEx(NORMAL, "Safety Check: Could not detect if PWD bit is set in config block. Exits."); - return 0; - } else { - PrintAndLogEx(NORMAL, "Safety Check: PWD bit is NOT set in config block. Reading without password..."); - usepwd = false; - page1 = false; - } - } else { - PrintAndLogEx(NORMAL, "Safety Check Overriden - proceeding despite risk"); - } - } - - if (!AquireData(page1, block, usepwd, password) ) return 0; - if (!DecodeT55xxBlock()) return 0; - - char blk[10] = {0}; - sprintf(blk, "%02d", block); - printT55xxBlock(blk); - return 1; -} - -int CmdT55xxReadBlock(const char *Cmd) { - uint8_t block = REGULAR_READ_MODE_BLOCK; - uint32_t password = 0; //default to blank Block 7 - bool usepwd = false; - bool override = false; - bool page1 = false; - bool errors = false; - uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch ( tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_t55xx_read(); - case 'b': - errors |= param_getdec(Cmd, cmdp+1, &block); - cmdp += 2; - break; - case 'o': - override = true; - cmdp++; - break; - case 'p': - password = param_get32ex(Cmd, cmdp+1, 0, 16); - usepwd = true; - cmdp += 2; - break; - case '1': - page1 = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - if (errors) return usage_t55xx_read(); - - if (block > 7 && block != REGULAR_READ_MODE_BLOCK ) { - PrintAndLogEx(NORMAL, "Block must be between 0 and 7"); - return 0; - } - - printT5xxHeader(page1); - return T55xxReadBlock(block, page1, usepwd, override, password); -} - -bool DecodeT55xxBlock(){ - - char buf[30] = {0x00}; - char *cmdStr = buf; - int ans = 0; - bool ST = config.ST; - uint8_t bitRate[8] = {8,16,32,40,50,64,100,128}; - DemodBufferLen = 0x00; - - switch( config.modulation ){ - case DEMOD_FSK: - snprintf(cmdStr, sizeof(buf),"%d %d", bitRate[config.bitrate], config.inverted ); - ans = FSKrawDemod(cmdStr, false); - break; - case DEMOD_FSK1: - case DEMOD_FSK1a: - snprintf(cmdStr, sizeof(buf),"%d %d 8 5", bitRate[config.bitrate], config.inverted ); - ans = FSKrawDemod(cmdStr, false); - break; - case DEMOD_FSK2: - case DEMOD_FSK2a: - snprintf(cmdStr, sizeof(buf),"%d %d 10 8", bitRate[config.bitrate], config.inverted ); - ans = FSKrawDemod(cmdStr, false); - break; - case DEMOD_ASK: - snprintf(cmdStr, sizeof(buf),"%d %d 1", bitRate[config.bitrate], config.inverted ); - ans = ASKDemod_ext(cmdStr, false, false, 1, &ST); - break; - case DEMOD_PSK1: - // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) - save_restoreGB(GRAPH_SAVE); - CmdLtrim("160"); - snprintf(cmdStr, sizeof(buf),"%d %d 6", bitRate[config.bitrate], config.inverted ); - ans = PSKDemod(cmdStr, false); - //undo trim samples - save_restoreGB(GRAPH_RESTORE); - break; - case DEMOD_PSK2: //inverted won't affect this - case DEMOD_PSK3: //not fully implemented - // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) - save_restoreGB(GRAPH_SAVE); - CmdLtrim("160"); - snprintf(cmdStr, sizeof(buf),"%d 0 6", bitRate[config.bitrate] ); - ans = PSKDemod(cmdStr, false); - psk1TOpsk2(DemodBuffer, DemodBufferLen); - //undo trim samples - save_restoreGB(GRAPH_RESTORE); - break; - case DEMOD_NRZ: - snprintf(cmdStr, sizeof(buf),"%d %d 1", bitRate[config.bitrate], config.inverted ); - ans = NRZrawDemod(cmdStr, false); - break; - case DEMOD_BI: - case DEMOD_BIa: - snprintf(cmdStr, sizeof(buf),"0 %d %d 1", bitRate[config.bitrate], config.inverted ); - ans = ASKbiphaseDemod(cmdStr, false); - break; - default: - return false; - } - return (bool) ans; -} - -bool DecodeT5555TraceBlock() { - DemodBufferLen = 0x00; - - // According to datasheet. Always: RF/64, not inverted, Manchester - return (bool) ASKDemod("64 0 1", false, false, 1); -} - -// sanity check. Don't use proxmark if it is offline and you didn't specify useGraphbuf -static int SanityOfflineCheck( bool useGraphBuffer ){ - if ( !useGraphBuffer && IsOffline() ) { - PrintAndLogEx(NORMAL, "Your proxmark3 device is offline. Specify [1] to use graphbuffer data instead"); - return 0; - } - return 1; -} - -int CmdT55xxDetect(const char *Cmd){ - bool errors = false; - bool useGB = false, usepwd = false; - uint32_t password = 0; - uint8_t cmdp = 0; - - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch ( tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_t55xx_detect(); - case 'p': - password = param_get32ex(Cmd, cmdp+1, 0, 16); - usepwd = true; - cmdp += 2; - break; - case '1': - // use Graphbuffer data - useGB = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - if (errors) return usage_t55xx_detect(); - - // sanity check. - if (!SanityOfflineCheck(useGB)) return 1; - - if ( !useGB) { - if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password) ) - return 1; - } - - if ( !tryDetectModulation() ) - PrintAndLogEx(WARNING, "Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'"); - - return 0; -} - -// detect configuration? -bool tryDetectModulation(){ - - t55xx_conf_block_t tests[15]; - int bitRate = 0, clk = 0, firstClockEdge = 0; - uint8_t hits = 0, fc1 = 0, fc2 = 0, ans = 0; - - ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, &firstClockEdge); - - if (ans && ((fc1==10 && fc2==8) || (fc1==8 && fc2==5))) { - if ( FSKrawDemod("0 0", false) && test(DEMOD_FSK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)){ - tests[hits].modulation = DEMOD_FSK; - if (fc1==8 && fc2 == 5) - tests[hits].modulation = DEMOD_FSK1a; - else if (fc1==10 && fc2 == 8) - tests[hits].modulation = DEMOD_FSK2; - tests[hits].bitrate = bitRate; - tests[hits].inverted = false; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - tests[hits].ST = false; - ++hits; - } - if ( FSKrawDemod("0 1", false) && test(DEMOD_FSK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { - tests[hits].modulation = DEMOD_FSK; - if (fc1 == 8 && fc2 == 5) - tests[hits].modulation = DEMOD_FSK1; - else if (fc1 == 10 && fc2 == 8) - tests[hits].modulation = DEMOD_FSK2a; - tests[hits].bitrate = bitRate; - tests[hits].inverted = true; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - tests[hits].ST = false; - ++hits; - } - } else { - clk = GetAskClock("", false); - if (clk > 0) { - tests[hits].ST = true; - // "0 0 1 " == clock auto, invert false, maxError 1. - // false = no verbose - // false = no emSearch - // 1 = Ask/Man - // st = true - if ( ASKDemod_ext("0 0 1", false, false, 1, &tests[hits].ST) && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { - tests[hits].modulation = DEMOD_ASK; - tests[hits].bitrate = bitRate; - tests[hits].inverted = false; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - ++hits; - } - tests[hits].ST = true; - // "0 0 1 " == clock auto, invert true, maxError 1. - // false = no verbose - // false = no emSearch - // 1 = Ask/Man - // st = true - if ( ASKDemod_ext("0 1 1", false, false, 1, &tests[hits].ST) && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { - tests[hits].modulation = DEMOD_ASK; - tests[hits].bitrate = bitRate; - tests[hits].inverted = true; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - ++hits; - } - if ( ASKbiphaseDemod("0 0 0 2", false) && test(DEMOD_BI, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5) ) { - tests[hits].modulation = DEMOD_BI; - tests[hits].bitrate = bitRate; - tests[hits].inverted = false; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - tests[hits].ST = false; - ++hits; - } - if ( ASKbiphaseDemod("0 0 1 2", false) && test(DEMOD_BIa, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5) ) { - tests[hits].modulation = DEMOD_BIa; - tests[hits].bitrate = bitRate; - tests[hits].inverted = true; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - tests[hits].ST = false; - ++hits; - } - } - clk = GetNrzClock("", false); - if (clk > 8) { //clock of rf/8 is likely a false positive, so don't use it. - if ( NRZrawDemod("0 0 1", false) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { - tests[hits].modulation = DEMOD_NRZ; - tests[hits].bitrate = bitRate; - tests[hits].inverted = false; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - tests[hits].ST = false; - ++hits; - } - - if ( NRZrawDemod("0 1 1", false) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { - tests[hits].modulation = DEMOD_NRZ; - tests[hits].bitrate = bitRate; - tests[hits].inverted = true; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - tests[hits].ST = false; - ++hits; - } - } - - clk = GetPskClock("", false); - if (clk > 0) { - // allow undo - save_restoreGB(GRAPH_SAVE); - // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) - CmdLtrim("160"); - if ( PSKDemod("0 0 6", false) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { - tests[hits].modulation = DEMOD_PSK1; - tests[hits].bitrate = bitRate; - tests[hits].inverted = false; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - tests[hits].ST = false; - ++hits; - } - if ( PSKDemod("0 1 6", false) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { - tests[hits].modulation = DEMOD_PSK1; - tests[hits].bitrate = bitRate; - tests[hits].inverted = true; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - tests[hits].ST = false; - ++hits; - } - //ICEMAN: are these PSKDemod calls needed? - // PSK2 - needs a call to psk1TOpsk2. - if ( PSKDemod("0 0 6", false)) { - psk1TOpsk2(DemodBuffer, DemodBufferLen); - if (test(DEMOD_PSK2, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)){ - tests[hits].modulation = DEMOD_PSK2; - tests[hits].bitrate = bitRate; - tests[hits].inverted = false; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - tests[hits].ST = false; - ++hits; - } - } // inverse waves does not affect this demod - // PSK3 - needs a call to psk1TOpsk2. - if ( PSKDemod("0 0 6", false)) { - psk1TOpsk2(DemodBuffer, DemodBufferLen); - if (test(DEMOD_PSK3, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)){ - tests[hits].modulation = DEMOD_PSK3; - tests[hits].bitrate = bitRate; - tests[hits].inverted = false; - tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); - tests[hits].ST = false; - ++hits; - } - } // inverse waves does not affect this demod - //undo trim samples - save_restoreGB(GRAPH_RESTORE); - } - } - if ( hits == 1) { - config.modulation = tests[0].modulation; - config.bitrate = tests[0].bitrate; - config.inverted = tests[0].inverted; - config.offset = tests[0].offset; - config.block0 = tests[0].block0; - config.Q5 = tests[0].Q5; - config.ST = tests[0].ST; - printConfiguration( config ); - return true; - } - - bool retval = false; - if ( hits > 1) { - PrintAndLogEx(SUCCESS, "Found [%d] possible matches for modulation.", hits); - for(int i=0; i= DEMOD_FSK1 && modread <= DEMOD_FSK2a) return true; - break; - case DEMOD_ASK: - if (modread == DEMOD_ASK) return true; - break; - case DEMOD_PSK1: - if (modread == DEMOD_PSK1) return true; - break; - case DEMOD_PSK2: - if (modread == DEMOD_PSK2) return true; - break; - case DEMOD_PSK3: - if (modread == DEMOD_PSK3) return true; - break; - case DEMOD_NRZ: - if (modread == DEMOD_NRZ) return true; - break; - case DEMOD_BI: - if (modread == DEMOD_BI) return true; - break; - case DEMOD_BIa: - if (modread == DEMOD_BIa) return true; - break; - default: - return false; - } - return false; -} - -bool testQ5Modulation(uint8_t mode, uint8_t modread){ - switch( mode ){ - case DEMOD_FSK: - if (modread >= 4 && modread <= 5) return true; - break; - case DEMOD_ASK: - if (modread == 0) return true; - break; - case DEMOD_PSK1: - if (modread == 1) return true; - break; - case DEMOD_PSK2: - if (modread == 2) return true; - break; - case DEMOD_PSK3: - if (modread == 3) return true; - break; - case DEMOD_NRZ: - if (modread == 7) return true; - break; - case DEMOD_BI: - if (modread == 6) return true; - break; - default: - return false; - } - return false; -} - -int convertQ5bitRate(uint8_t bitRateRead) { - uint8_t expected[] = {8, 16, 32, 40, 50, 64, 100, 128}; - for (int i=0; i<8; i++) - if (expected[i] == bitRateRead) - return i; - - return -1; -} - -bool testQ5(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk){ - - if ( DemodBufferLen < 64 ) return false; - uint8_t si = 0; - for (uint8_t idx = 28; idx < 64; idx++){ - si = idx; - if ( PackBits(si, 28, DemodBuffer) == 0x00 ) continue; - - uint8_t safer = PackBits(si, 4, DemodBuffer); si += 4; //master key - uint8_t resv = PackBits(si, 8, DemodBuffer); si += 8; - // 2nibble must be zeroed. - if (safer != 0x6 && safer != 0x9) continue; - if ( resv > 0x00) continue; - //uint8_t pageSel = PackBits(si, 1, DemodBuffer); si += 1; - //uint8_t fastWrite = PackBits(si, 1, DemodBuffer); si += 1; - si += 1+1; - int bitRate = PackBits(si, 6, DemodBuffer)*2 + 2; si += 6; //bit rate - if (bitRate > 128 || bitRate < 8) continue; - - //uint8_t AOR = PackBits(si, 1, DemodBuffer); si += 1; - //uint8_t PWD = PackBits(si, 1, DemodBuffer); si += 1; - //uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2; //could check psk cr - //uint8_t inverse = PackBits(si, 1, DemodBuffer); si += 1; - si += 1+1+2+1; - uint8_t modread = PackBits(si, 3, DemodBuffer); si += 3; - uint8_t maxBlk = PackBits(si, 3, DemodBuffer); si += 3; - //uint8_t ST = PackBits(si, 1, DemodBuffer); si += 1; - if (maxBlk == 0) continue; - //test modulation - if (!testQ5Modulation(mode, modread)) continue; - if (bitRate != clk) continue; - *fndBitRate = convertQ5bitRate(bitRate); - if (*fndBitRate < 0) continue; - *offset = idx; - - return true; - } - return false; -} - -bool testBitRate(uint8_t readRate, uint8_t clk){ - uint8_t expected[] = {8, 16, 32, 40, 50, 64, 100, 128}; - if (expected[readRate] == clk) - return true; - - return false; -} - -bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5){ - - if ( DemodBufferLen < 64 ) return false; - uint8_t si = 0; - for (uint8_t idx = 28; idx < 64; idx++){ - si = idx; - if ( PackBits(si, 28, DemodBuffer) == 0x00 ) continue; - - uint8_t safer = PackBits(si, 4, DemodBuffer); si += 4; //master key - uint8_t resv = PackBits(si, 4, DemodBuffer); si += 4; //was 7 & +=7+3 //should be only 4 bits if extended mode - // 2nibble must be zeroed. - // moved test to here, since this gets most faults first. - if ( resv > 0x00) continue; - - int bitRate = PackBits(si, 6, DemodBuffer); si += 6; //bit rate (includes extended mode part of rate) - uint8_t extend = PackBits(si, 1, DemodBuffer); si += 1; //bit 15 extended mode - uint8_t modread = PackBits(si, 5, DemodBuffer); si += 5+2+1; - //uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2+1; //could check psk cr - //uint8_t nml01 = PackBits(si, 1, DemodBuffer); si += 1+5; //bit 24, 30, 31 could be tested for 0 if not extended mode - //uint8_t nml02 = PackBits(si, 2, DemodBuffer); si += 2; - - //if extended mode - bool extMode =( (safer == 0x6 || safer == 0x9) && extend) ? true : false; - - if (!extMode){ - if (bitRate > 7) continue; - if (!testBitRate(bitRate, clk)) continue; - } else { //extended mode bitrate = same function to calc bitrate as em4x05 - if (EM4x05_GET_BITRATE(bitRate) != clk) continue; - - } - //test modulation - if (!testModulation(mode, modread)) continue; - *fndBitRate = bitRate; - *offset = idx; - *Q5 = false; - return true; - } - if (testQ5(mode, offset, fndBitRate, clk)) { - *Q5 = true; - return true; - } - return false; -} - -void printT55xxBlock(const char *blockNum){ - - uint8_t i = config.offset; - uint8_t endpos = 32 + i; - uint32_t blockData = 0; - uint8_t bits[64] = {0x00}; - - if ( !DemodBufferLen) return; - - if ( endpos > DemodBufferLen){ - PrintAndLogEx(NORMAL, "The configured offset %d is too big. Possible offset: %d)", i, DemodBufferLen-32); - return; - } - - for (; i < endpos; ++i) - bits[i - config.offset] = DemodBuffer[i]; - - blockData = PackBits(0, 32, bits); - uint8_t bytes[4] = {0}; - num_to_bytes(blockData, 4, bytes); - - PrintAndLogEx(NORMAL, " %s | %08X | %s | %s", blockNum, blockData, sprint_bin(bits,32), sprint_ascii(bytes,4)); -} - -int special(const char *Cmd) { - uint32_t blockData = 0; - uint8_t bits[32] = {0x00}; - - PrintAndLogEx(NORMAL, "OFFSET | DATA | BINARY | ASCII"); - PrintAndLogEx(NORMAL, "-------+-------+-------------------------------------+------"); - int i,j = 0; - for (; j < 64; ++j){ - - for (i = 0; i < 32; ++i) - bits[i]=DemodBuffer[j+i]; - - blockData = PackBits(0, 32, bits); - - PrintAndLogEx(NORMAL, "%02d | 0x%08X | %s",j , blockData, sprint_bin(bits,32)); - } - return 0; -} - -int printConfiguration( t55xx_conf_block_t b){ - PrintAndLogEx(NORMAL, "Chip Type : %s", (b.Q5) ? "T5555(Q5)" : "T55x7"); - PrintAndLogEx(NORMAL, "Modulation : %s", GetSelectedModulationStr(b.modulation) ); - PrintAndLogEx(NORMAL, "Bit Rate : %s", GetBitRateStr(b.bitrate, (b.block0 & T55x7_X_MODE && (b.block0>>28==6 || b.block0>>28==9))) ); - PrintAndLogEx(NORMAL, "Inverted : %s", (b.inverted) ? _GREEN_(Yes) : "No" ); - PrintAndLogEx(NORMAL, "Offset : %d", b.offset); - PrintAndLogEx(NORMAL, "Seq. Term. : %s", (b.ST) ? _GREEN_(Yes) : "No" ); - PrintAndLogEx(NORMAL, "Block0 : 0x%08X", b.block0); - PrintAndLogEx(NORMAL, ""); - return 0; -} - -int CmdT55xxWakeUp(const char *Cmd) { - uint32_t password = 0; - uint8_t cmdp = 0; - bool errors = false; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_t55xx_wakup(); - case 'p': - password = param_get32ex(Cmd, cmdp+1, 0, 16); - cmdp += 2; - errors = false; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - if (errors) return usage_t55xx_wakup(); - - UsbCommand c = {CMD_T55XX_WAKEUP, {password, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - PrintAndLogEx(SUCCESS, "Wake up command sent. Try read now"); - return 0; -} - -int CmdT55xxWriteBlock(const char *Cmd) { - uint8_t block = 0xFF; //default to invalid block - uint32_t data = 0; //default to blank Block - uint32_t password = 0; //default to blank Block 7 - bool usepwd = false; - bool page1 = false; - bool gotdata = false; - bool testMode = false; - bool errors = false; - uint8_t cmdp = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_t55xx_write(); - case 'b': - errors |= param_getdec(Cmd, cmdp+1, &block); - cmdp += 2; - break; - case 'd': - data = param_get32ex(Cmd, cmdp+1, 0, 16); - gotdata = true; - cmdp += 2; - break; - case 'p': - password = param_get32ex(Cmd, cmdp+1, 0, 16); - usepwd = true; - cmdp += 2; - break; - case 't': - testMode = true; - cmdp++; - break; - case '1': - page1 = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - if (errors || !gotdata) return usage_t55xx_write(); - - if (block > 7) { - PrintAndLogEx(WARNING, "Block number must be between 0 and 7"); - return 0; - } - - UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {data, block, 0}}; - UsbCommand resp; - c.d.asBytes[0] = (page1) ? 0x2 : 0; - c.d.asBytes[0] |= (testMode) ? 0x4 : 0; - - char pwdStr[16] = {0}; - snprintf(pwdStr, sizeof(pwdStr), "pwd: 0x%08X", password); - - PrintAndLogEx(INFO, "Writing page %d block: %02d data: 0x%08X %s", page1, block, data, (usepwd) ? pwdStr : "" ); - - //Password mode - if (usepwd) { - c.arg[2] = password; - c.d.asBytes[0] |= 0x1; - } - clearCommandBuffer(); - SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500 )){ - PrintAndLogEx(WARNING, "Error occurred, device did not ACK write operation. (May be due to old firmware)"); - return 0; - } - return 1; -} - -int CmdT55xxReadTrace(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 1 || cmdp == 'h') return usage_t55xx_trace(); - - bool pwdmode = false; - uint32_t password = 0; - - if (strlen(Cmd) == 0) { - // sanity check. - if (!SanityOfflineCheck(false)) return 1; - - if ( !AquireData( T55x7_PAGE1, REGULAR_READ_MODE_BLOCK, pwdmode, password ) ) - return 1; - } - - if ( config.Q5 ){ - if (!DecodeT5555TraceBlock()) return 1; - } else { - if (!DecodeT55xxBlock()) return 1; - } - - if ( !DemodBufferLen ) return 1; - - RepaintGraphWindow(); - uint8_t repeat = (config.offset > 5) ? 32 : 0; - - uint8_t si = config.offset + repeat; - uint32_t bl1 = PackBits(si, 32, DemodBuffer); - uint32_t bl2 = PackBits(si+32, 32, DemodBuffer); - - if (config.Q5) { - uint32_t hdr = PackBits(si, 9, DemodBuffer); si += 9; - - if (hdr != 0x1FF) { - PrintAndLogEx(FAILED, "Invalid Q5 Trace data header (expected 0x1FF, found %X)", hdr); - return 1; - } - - t5555_tracedata_t data = {.bl1 = bl1, .bl2 = bl2, .icr = 0, .lotidc = '?', .lotid = 0, .wafer = 0, .dw =0}; - - data.icr = PackBits(si, 2, DemodBuffer); si += 2; - data.lotidc = 'Z' - PackBits(si, 2, DemodBuffer); si += 3; - - data.lotid = PackBits(si, 4, DemodBuffer); si += 5; - data.lotid <<= 4; - data.lotid |= PackBits(si, 4, DemodBuffer); si += 5; - data.lotid <<= 4; - data.lotid |= PackBits(si, 4, DemodBuffer); si += 5; - data.lotid <<= 4; - data.lotid |= PackBits(si, 4, DemodBuffer); si += 5; - data.lotid <<= 1; - data.lotid |= PackBits(si, 1, DemodBuffer); si += 1; - - data.wafer = PackBits(si, 3, DemodBuffer); si += 4; - data.wafer <<= 2; - data.wafer |= PackBits(si, 2, DemodBuffer); si += 2; - - data.dw = PackBits(si, 2, DemodBuffer); si += 3; - data.dw <<= 4; - data.dw |= PackBits(si, 4, DemodBuffer); si += 5; - data.dw <<= 4; - data.dw |= PackBits(si, 4, DemodBuffer); si += 5; - data.dw <<= 4; - data.dw |= PackBits(si, 4, DemodBuffer); si += 5; - - printT5555Trace(data, repeat); - - } else { - - t55x7_tracedata_t data = {.bl1 = bl1, .bl2 = bl2, .acl = 0, .mfc = 0, .cid = 0, .year = 0, .quarter = 0, .icr = 0, .lotid = 0, .wafer = 0, .dw = 0}; - - data.acl = PackBits(si, 8, DemodBuffer); si += 8; - if ( data.acl != 0xE0 ) { - PrintAndLogEx(FAILED, "The modulation is most likely wrong since the ACL is not 0xE0. "); - return 1; - } - - data.mfc = PackBits(si, 8, DemodBuffer); si += 8; - data.cid = PackBits(si, 5, DemodBuffer); si += 5; - data.icr = PackBits(si, 3, DemodBuffer); si += 3; - data.year = PackBits(si, 4, DemodBuffer); si += 4; - data.quarter = PackBits(si, 2, DemodBuffer); si += 2; - data.lotid = PackBits(si, 14, DemodBuffer); si += 14; - data.wafer = PackBits(si, 5, DemodBuffer); si += 5; - data.dw = PackBits(si, 15, DemodBuffer); - - time_t t = time(NULL); - struct tm tm = *localtime(&t); - if ( data.year > tm.tm_year-110) - data.year += 2000; - else - data.year += 2010; - - printT55x7Trace(data, repeat); - } - return 0; -} - -void printT55x7Trace( t55x7_tracedata_t data, uint8_t repeat ){ - PrintAndLogEx(NORMAL, "-- T55x7 Trace Information ----------------------------------"); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - PrintAndLogEx(NORMAL, " ACL Allocation class (ISO/IEC 15963-1) : 0x%02X (%d)", data.acl, data.acl); - PrintAndLogEx(NORMAL, " MFC Manufacturer ID (ISO/IEC 7816-6) : 0x%02X (%d) - %s", data.mfc, data.mfc, getTagInfo(data.mfc)); - PrintAndLogEx(NORMAL, " CID : 0x%02X (%d) - %s", data.cid, data.cid, GetModelStrFromCID(data.cid)); - PrintAndLogEx(NORMAL, " ICR IC Revision : %d", data.icr ); - PrintAndLogEx(NORMAL, " Manufactured"); - PrintAndLogEx(NORMAL, " Year/Quarter : %d/%d", data.year, data.quarter); - PrintAndLogEx(NORMAL, " Lot ID : %d", data.lotid ); - PrintAndLogEx(NORMAL, " Wafer number : %d", data.wafer); - PrintAndLogEx(NORMAL, " Die Number : %d", data.dw); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - PrintAndLogEx(NORMAL, " Raw Data - Page 1"); - PrintAndLogEx(NORMAL, " Block 1 : 0x%08X %s", data.bl1, sprint_bin(DemodBuffer+config.offset+repeat,32) ); - PrintAndLogEx(NORMAL, " Block 2 : 0x%08X %s", data.bl2, sprint_bin(DemodBuffer+config.offset+repeat+32,32) ); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - - /* - TRACE - BLOCK O - Bits Definition HEX - 1-8 ACL Allocation class (ISO/IEC 15963-1) 0xE0 - 9-16 MFC Manufacturer ID (ISO/IEC 7816-6) 0x15 Atmel Corporation - 17-21 CID 0x1 = Atmel ATA5577M1 0x2 = Atmel ATA5577M2 - 22-24 ICR IC revision - 25-28 YEAR (BCD encoded) 9 (= 2009) - 29-30 QUARTER 1,2,3,4 - 31-32 LOT ID - - TRACE - BLOCK 1 - 1-12 LOT ID - 13-17 Wafer number - 18-32 DW, die number sequential - */ -} - -void printT5555Trace( t5555_tracedata_t data, uint8_t repeat ){ - PrintAndLogEx(NORMAL, "-- T5555 (Q5) Trace Information -----------------------------"); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - PrintAndLogEx(NORMAL, " ICR IC Revision : %d", data.icr ); - PrintAndLogEx(NORMAL, " Lot : %c%d", data.lotidc, data.lotid); - PrintAndLogEx(NORMAL, " Wafer number : %d", data.wafer); - PrintAndLogEx(NORMAL, " Die Number : %d", data.dw); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - PrintAndLogEx(NORMAL, " Raw Data - Page 1"); - PrintAndLogEx(NORMAL, " Block 1 : 0x%08X %s", data.bl1, sprint_bin(DemodBuffer+config.offset+repeat,32) ); - PrintAndLogEx(NORMAL, " Block 2 : 0x%08X %s", data.bl2, sprint_bin(DemodBuffer+config.offset+repeat+32,32) ); - - /* - ** Q5 ** - TRACE - BLOCK O and BLOCK1 - Bits Definition HEX - 1-9 Header 0x1FF - 10-11 IC Revision - 12-13 Lot ID char - 15-35 Lot ID (NB parity) - 36-41 Wafer number (NB parity) - 42-58 DW, die number sequential (NB parity) - 60-63 Parity bits - 64 Always zero - */ -} - -//need to add Q5 info... -int CmdT55xxInfo(const char *Cmd){ - /* - Page 0 Block 0 Configuration data. - Normal mode - Extended mode - */ - bool pwdmode = false; - uint32_t password = 0; - char cmdp = tolower(param_getchar(Cmd, 0)); - - if (strlen(Cmd) > 1 || cmdp == 'h') return usage_t55xx_info(); - - if (strlen(Cmd) == 0) { - // sanity check. - if (!SanityOfflineCheck(false)) return 1; - - if ( !AquireData( T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, pwdmode, password ) ) - return 1; - } - - if (!DecodeT55xxBlock()) return 1; - - // too little space to start with - if ( DemodBufferLen < 32) return 1; - - // - //PrintAndLogEx(NORMAL, "Offset+32 ==%d\n DemodLen == %d", config.offset + 32, DemodBufferLen); - - uint8_t si = config.offset; - uint32_t block0 = PackBits(si, 32, DemodBuffer); - uint32_t safer = PackBits(si, 4, DemodBuffer); si += 4; - uint32_t resv = PackBits(si, 7, DemodBuffer); si += 7; - uint32_t dbr = PackBits(si, 3, DemodBuffer); si += 3; - uint32_t extend = PackBits(si, 1, DemodBuffer); si += 1; - uint32_t datamod = PackBits(si, 5, DemodBuffer); si += 5; - uint32_t pskcf = PackBits(si, 2, DemodBuffer); si += 2; - uint32_t aor = PackBits(si, 1, DemodBuffer); si += 1; - uint32_t otp = PackBits(si, 1, DemodBuffer); si += 1; - uint32_t maxblk = PackBits(si, 3, DemodBuffer); si += 3; - uint32_t pwd = PackBits(si, 1, DemodBuffer); si += 1; - uint32_t sst = PackBits(si, 1, DemodBuffer); si += 1; - uint32_t fw = PackBits(si, 1, DemodBuffer); si += 1; - uint32_t inv = PackBits(si, 1, DemodBuffer); si += 1; - uint32_t por = PackBits(si, 1, DemodBuffer); si += 1; - - if (config.Q5) - PrintAndLogEx(NORMAL, _RED_(*** Warning ***) " Config Info read off a Q5 will not display as expected"); - - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "-- T55x7 Configuration & Tag Information --------------------"); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - PrintAndLogEx(NORMAL, " Safer key : %s", GetSaferStr(safer)); - PrintAndLogEx(NORMAL, " reserved : %d", resv); - PrintAndLogEx(NORMAL, " Data bit rate : %s", GetBitRateStr(dbr, extend)); - PrintAndLogEx(NORMAL, " eXtended mode : %s", (extend) ? _YELLOW_(Yes - Warning) : "No"); - PrintAndLogEx(NORMAL, " Modulation : %s", GetModulationStr(datamod)); - PrintAndLogEx(NORMAL, " PSK clock frequency : %d", pskcf); - PrintAndLogEx(NORMAL, " AOR - Answer on Request : %s", (aor) ? _GREEN_(Yes) : "No"); - PrintAndLogEx(NORMAL, " OTP - One Time Pad : %s", (otp) ? _YELLOW_(Yes - Warning) : "No" ); - PrintAndLogEx(NORMAL, " Max block : %d", maxblk); - PrintAndLogEx(NORMAL, " Password mode : %s", (pwd) ? _GREEN_(Yes) : "No"); - PrintAndLogEx(NORMAL, " Sequence Start Terminator : %s", (sst) ? _GREEN_(Yes) : "No"); - PrintAndLogEx(NORMAL, " Fast Write : %s", (fw) ? _GREEN_(Yes) : "No"); - PrintAndLogEx(NORMAL, " Inverse data : %s", (inv) ? _GREEN_(Yes) : "No"); - PrintAndLogEx(NORMAL, " POR-Delay : %s", (por) ? _GREEN_(Yes) : "No"); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - PrintAndLogEx(NORMAL, " Raw Data - Page 0"); - PrintAndLogEx(NORMAL, " Block 0 : 0x%08X %s", block0, sprint_bin(DemodBuffer + config.offset, 32) ); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - return 0; -} - -int CmdT55xxDump(const char *Cmd){ - - uint32_t password = 0; - bool override = false; - char cmdp = tolower(param_getchar(Cmd, 0)); - if ( cmdp == 'h') return usage_t55xx_dump(); - - bool usepwd = ( strlen(Cmd) > 0); - if ( usepwd ){ - password = param_get32ex(Cmd, 0, 0, 16); - if (param_getchar(Cmd, 1) =='o' ) - override = true; - } - - printT5xxHeader(0); - for ( uint8_t i = 0; i < 8; ++i) - T55xxReadBlock(i, 0, usepwd, override, password); - - printT5xxHeader(1); - for ( uint8_t i = 0; i < 4; i++) - T55xxReadBlock(i, 1, usepwd, override, password); - - return 1; -} - -bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ) { - // arg0 bitmodes: - // bit0 = pwdmode - // bit1 = page to read from - // arg1: which block to read - // arg2: password - uint8_t arg0 = (page<<1) | pwdmode; - UsbCommand c = {CMD_T55XX_READ_BLOCK, {arg0, block, password}}; - clearCommandBuffer(); - SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500) ) { - PrintAndLogEx(WARNING, "command execution time out"); - return false; - } - - uint8_t got[8000]; - if ( !GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 4000, true)) { - PrintAndLogEx(WARNING, "command execution time out"); - return false; - } - setGraphBuf(got, sizeof(got)); - // set signal properties low/high/mean/amplitude and is_noise detection - computeSignalProperties(got, sizeof(got)); - RepaintGraphWindow(); - return !getSignalProperties()->isnoise; -} - -char * GetBitRateStr(uint32_t id, bool xmode) { - static char buf[25]; - - char *retStr = buf; - if (xmode) { //xmode bitrate calc is same as em4x05 calc - snprintf(retStr,sizeof(buf),"%d - RF/%d", id, EM4x05_GET_BITRATE(id)); - } else { - switch (id){ - case 0: snprintf(retStr,sizeof(buf),"%d - RF/8",id); break; - case 1: snprintf(retStr,sizeof(buf),"%d - RF/16",id); break; - case 2: snprintf(retStr,sizeof(buf),"%d - RF/32",id); break; - case 3: snprintf(retStr,sizeof(buf),"%d - RF/40",id); break; - case 4: snprintf(retStr,sizeof(buf),"%d - RF/50",id); break; - case 5: snprintf(retStr,sizeof(buf),"%d - RF/64",id); break; - case 6: snprintf(retStr,sizeof(buf),"%d - RF/100",id); break; - case 7: snprintf(retStr,sizeof(buf),"%d - RF/128",id); break; - default: snprintf(retStr,sizeof(buf),"%d - (Unknown)",id); break; - } - } - return buf; -} - -char * GetSaferStr(uint32_t id){ - static char buf[40]; - char *retStr = buf; - - snprintf(retStr,sizeof(buf),"%d",id); - if (id == 6) { - snprintf(retStr,sizeof(buf),"%d - passwd",id); - } - if (id == 9 ){ - snprintf(retStr,sizeof(buf),"%d - testmode",id); - } - - return buf; -} - -char * GetModulationStr( uint32_t id){ - static char buf[60]; - char *retStr = buf; - - switch (id){ - case 0: snprintf(retStr,sizeof(buf),"%d - DIRECT (ASK/NRZ)",id); break; - case 1: snprintf(retStr,sizeof(buf),"%d - PSK 1 phase change when input changes",id); break; - case 2: snprintf(retStr,sizeof(buf),"%d - PSK 2 phase change on bitclk if input high",id); break; - case 3: snprintf(retStr,sizeof(buf),"%d - PSK 3 phase change on rising edge of input",id); break; - case 4: snprintf(retStr,sizeof(buf),"%d - FSK 1 RF/8 RF/5",id); break; - case 5: snprintf(retStr,sizeof(buf),"%d - FSK 2 RF/8 RF/10",id); break; - case 6: snprintf(retStr,sizeof(buf),"%d - FSK 1a RF/5 RF/8",id); break; - case 7: snprintf(retStr,sizeof(buf),"%d - FSK 2a RF/10 RF/8",id); break; - case 8: snprintf(retStr,sizeof(buf),"%d - Manchester",id); break; - case 16: snprintf(retStr,sizeof(buf),"%d - Biphase",id); break; - case 0x18:snprintf(retStr,sizeof(buf),"%d - Biphase a - AKA Conditional Dephase Encoding(CDP)",id); break; - case 17: snprintf(retStr,sizeof(buf),"%d - Reserved",id); break; - default: snprintf(retStr,sizeof(buf),"0x%02X (Unknown)",id); break; - } - return buf; -} - -char * GetModelStrFromCID(uint32_t cid){ - - static char buf[10]; - char *retStr = buf; - - if (cid == 1) snprintf(retStr, sizeof(buf),"ATA5577M1"); - if (cid == 2) snprintf(retStr, sizeof(buf),"ATA5577M2"); - return buf; -} - -char * GetSelectedModulationStr( uint8_t id){ - - static char buf[20]; - char *retStr = buf; - - switch (id){ - case DEMOD_FSK: snprintf(retStr,sizeof(buf),"FSK"); break; - case DEMOD_FSK1: snprintf(retStr,sizeof(buf),"FSK1"); break; - case DEMOD_FSK1a: snprintf(retStr,sizeof(buf),"FSK1a"); break; - case DEMOD_FSK2: snprintf(retStr,sizeof(buf),"FSK2"); break; - case DEMOD_FSK2a: snprintf(retStr,sizeof(buf),"FSK2a"); break; - case DEMOD_ASK: snprintf(retStr,sizeof(buf),"ASK"); break; - case DEMOD_NRZ: snprintf(retStr,sizeof(buf),"DIRECT/NRZ"); break; - case DEMOD_PSK1: snprintf(retStr,sizeof(buf),"PSK1"); break; - case DEMOD_PSK2: snprintf(retStr,sizeof(buf),"PSK2"); break; - case DEMOD_PSK3: snprintf(retStr,sizeof(buf),"PSK3"); break; - case DEMOD_BI: snprintf(retStr,sizeof(buf),"BIPHASE"); break; - case DEMOD_BIa: snprintf(retStr,sizeof(buf),"BIPHASEa - (CDP)"); break; - default: snprintf(retStr,sizeof(buf),"(Unknown)"); break; - } - return buf; -} - -void t55x7_create_config_block( int tagtype ){ - - /* - T55X7_DEFAULT_CONFIG_BLOCK, T55X7_RAW_CONFIG_BLOCK - T55X7_EM_UNIQUE_CONFIG_BLOCK, T55X7_FDXB_CONFIG_BLOCK, - T55X7_FDXB_CONFIG_BLOCK, T55X7_HID_26_CONFIG_BLOCK, T55X7_INDALA_64_CONFIG_BLOCK, T55X7_INDALA_224_CONFIG_BLOCK - T55X7_GUARDPROXII_CONFIG_BLOCK, T55X7_VIKING_CONFIG_BLOCK, T55X7_NORALYS_CONFIG_BLOCK, T55X7_IOPROX_CONFIG_BLOCK - */ - static char buf[60]; - char *retStr = buf; - - switch (tagtype){ - case 0: snprintf(retStr, sizeof(buf),"%08X - T55X7 Default", T55X7_DEFAULT_CONFIG_BLOCK); break; - case 1: snprintf(retStr, sizeof(buf),"%08X - T55X7 Raw", T55X7_RAW_CONFIG_BLOCK); break; - case 2: snprintf(retStr, sizeof(buf),"%08X - T5555 Q5 Default", T5555_DEFAULT_CONFIG_BLOCK); break; - default: - break; - } - PrintAndLogEx(NORMAL, buf); -} - -int CmdResetRead(const char *Cmd) { - UsbCommand c = {CMD_T55XX_RESET_READ, {0,0,0}}; - clearCommandBuffer(); - SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500) ) { - PrintAndLogEx(WARNING, "command execution time out"); - return 0; - } - - uint8_t got[BIGBUF_SIZE-1]; - if ( !GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 2500, false)) { - PrintAndLogEx(WARNING, "command execution time out"); - return 0; - } - setGraphBuf(got, sizeof(got)); - return 1; -} - -int CmdT55xxWipe(const char *Cmd) { - char writeData[20] = {0}; - char *ptrData = writeData; - char cmdp = param_getchar(Cmd, 0); - if ( cmdp == 'h' || cmdp == 'H') return usage_t55xx_wipe(); - - bool Q5 = (cmdp == 'q' || cmdp == 'Q'); - - // Try with the default password to reset block 0 - // With a pwd should work even if pwd bit not set - PrintAndLogEx(INFO, "\nBeginning Wipe of a T55xx tag (assuming the tag is not password protected)\n"); - - if ( Q5 ) - snprintf(ptrData,sizeof(writeData),"b 0 d 6001F004 p 0"); - else - snprintf(ptrData,sizeof(writeData),"b 0 d 000880E0 p 0"); - - if (!CmdT55xxWriteBlock(ptrData)) PrintAndLogEx(WARNING, "Error writing blk 0"); - - for (uint8_t blk = 1; blk<8; blk++) { - - snprintf(ptrData,sizeof(writeData),"b %d d 0", blk); - - if (!CmdT55xxWriteBlock(ptrData)) PrintAndLogEx(WARNING, "Error writing blk %d", blk); - - memset(writeData, 0x00, sizeof(writeData)); - } - return 0; -} - -bool IsCancelled(void) { - if (ukbhit()) { - int gc = getchar(); (void)gc; - PrintAndLogEx(NORMAL, "\naborted via keyboard!\n"); - return true; - } - return false; -} - -int CmdT55xxChkPwds(const char *Cmd) { - // load a default pwd file. - char line[9]; - char filename[FILE_PATH_SIZE] = {0}; - int keycnt = 0; - uint8_t stKeyBlock = 20; - uint8_t *keyBlock = NULL, *p = NULL; - bool found = false; - uint8_t timeout = 0; - - memset(line, 0, sizeof(line)); - - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) == 0 || cmdp == 'h') return usage_t55xx_chk(); - - /* - if ( T55xxReadBlock(7, 0, 0, 0, 0) ) { - - // now try to validate it.. - PrintAndLogEx(WARNING, "\n Block 7 was readable"); - return 1; - } - */ - - uint64_t t1 = msclock(); - - if ( cmdp == 'm' ) { - UsbCommand c = {CMD_T55XX_CHKPWDS, {0,0,0} }; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - - while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - timeout++; - printf("."); fflush(stdout); - if (timeout > 180) { - PrintAndLogEx(WARNING, "\nno response from Proxmark. Aborting..."); - return 2; - } - } - - if ( resp.arg[0] ) { - PrintAndLogEx(SUCCESS, "\nFound a candidate [ %08X ]. Trying to validate", resp.arg[1]); - - if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, resp.arg[1])) { - PrintAndLogEx(INFO, "Aquireing data from device failed. Quitting"); - return 2; - } - - found = tryDetectModulation(); - if (found) { - PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", resp.arg[1]); - } else { - PrintAndLogEx(WARNING, "Password NOT found."); - } - } else { - PrintAndLogEx(WARNING, "Password NOT found."); - } - - goto out; - } - - keyBlock = calloc(stKeyBlock, 4); - if (keyBlock == NULL) return 1; - - if (cmdp == 'i') { - - int len = strlen(Cmd+2); - if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; - memcpy(filename, Cmd+2, len); - - FILE * f = fopen( filename , "r"); - if ( !f ) { - PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); - free(keyBlock); - return 1; - } - - while( fgets(line, sizeof(line), f) ){ - if (strlen(line) < 8 || line[7] == '\n') continue; - - //goto next line - while (fgetc(f) != '\n' && !feof(f)) ; - - //The line start with # is comment, skip - if( line[0]=='#' ) continue; - - if (!isxdigit(line[0])) { - PrintAndLogEx(WARNING, "File content error. '%s' must include 8 HEX symbols", line); - continue; - } - - line[8] = 0; - - // realloc keyblock array size. - if ( stKeyBlock - keycnt < 2) { - p = realloc(keyBlock, 4 * (stKeyBlock += 10)); - if (!p) { - PrintAndLogEx(WARNING, "Cannot allocate memory for defaultKeys"); - free(keyBlock); - if (f) - fclose(f); - return 2; - } - keyBlock = p; - } - // clear mem - memset(keyBlock + 4 * keycnt, 0, 4); - - num_to_bytes( strtoll(line, NULL, 16), 4, keyBlock + 4*keycnt); - -// PrintAndLogEx(NORMAL, "chk custom pwd[%2d] %08X", keycnt, bytes_to_num(keyBlock + 4 * keycnt, 4) ); - keycnt++; - memset(line, 0, sizeof(line)); - } - - if (f) - fclose(f); - - if (keycnt == 0) { - PrintAndLogEx(WARNING, "No keys found in file"); - free(keyBlock); - return 1; - } - PrintAndLogEx(SUCCESS, "Loaded %d keys", keycnt); - - // loop - uint64_t testpwd = 0x00; - for (uint16_t c = 0; c < keycnt; ++c ) { - - if ( IsOffline() ) { - PrintAndLogEx(WARNING, "Device offline\n"); - free(keyBlock); - return 2; - } - - if (IsCancelled()) { - free(keyBlock); - return 0; - } - - testpwd = bytes_to_num(keyBlock + 4*c, 4); - - PrintAndLogEx(INFO, "Testing %08X", testpwd); - - if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, testpwd)) { - PrintAndLogEx(INFO, "Aquireing data from device failed. Quitting"); - free(keyBlock); - return 0; - } - - found = tryDetectModulation(); - if ( found ) - break; - - } - if ( found ) - PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", testpwd); - else - PrintAndLogEx(WARNING, "Password NOT found."); - } - - free(keyBlock); - -out: - t1 = msclock() - t1; - PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1/1000.0); - return 0; -} - -int CmdT55xxBruteForce(const char *Cmd) { - - uint32_t start_password = 0x00000000; //start password - uint32_t end_password = 0xFFFFFFFF; //end password - uint32_t curr = 0; - bool found = false; - - - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_t55xx_bruteforce(); - - uint64_t t1 = msclock(); - - // Try to read Block 7, first :) - - // incremental pwd range search - start_password = param_get32ex(Cmd, 0, 0, 16); - end_password = param_get32ex(Cmd, 1, 0, 16); - - curr = start_password; - - if ( start_password >= end_password ) { - return usage_t55xx_bruteforce(); - } - - PrintAndLogEx(INFO, "Search password range [%08X -> %08X]", start_password, end_password); - - while ( !found ){ - - printf("."); fflush(stdout); - - if (IsCancelled()) { - return 0; - } - - if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, curr)) { - PrintAndLogEx(WARNING, "Aquiring data from device failed. Quitting"); - return 0; - } - - found = tryDetectModulation(); - - if (curr == end_password) - break; - curr++; - } - - PrintAndLogEx(NORMAL, ""); - - if (found) - PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", curr); - else - PrintAndLogEx(WARNING, "Password NOT found. Last tried: [ %08X ]", --curr); - - t1 = msclock() - t1; - PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1/1000.0); - return 0; -} - -int tryOnePassword(uint32_t password) { - PrintAndLogEx(INFO, "Trying password %08x", password); - if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, password)) { - PrintAndLogEx(NORMAL, "Acquire data from device failed. Quitting"); - return -1; - } - - if (tryDetectModulation()) - return 1; - else - return 0; -} - -int CmdT55xxRecoverPW(const char *Cmd) { - int bit = 0; - uint32_t orig_password = 0x0; - uint32_t curr_password = 0x0; - uint32_t prev_password = 0xffffffff; - uint32_t mask = 0x0; - int found = 0; - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h' ) return usage_t55xx_recoverpw(); - - orig_password = param_get32ex(Cmd, 0, 0x51243648, 16); //password used by handheld cloners - - // first try fliping each bit in the expected password - while (bit < 32) { - curr_password = orig_password ^ ( 1 << bit ); - found = tryOnePassword(curr_password); - if (found == -1) return 0; - bit++; - - if (IsCancelled()) return 0; - } - - // now try to use partial original password, since block 7 should have been completely - // erased during the write sequence and it is possible that only partial password has been - // written - // not sure from which end the bit bits are written, so try from both ends - // from low bit to high bit - bit = 0; - while (bit < 32) { - mask += ( 1 << bit ); - curr_password = orig_password & mask; - // if updated mask didn't change the password, don't try it again - if (prev_password == curr_password) { - bit++; - continue; - } - found = tryOnePassword(curr_password); - if (found == -1) return 0; - bit++; - prev_password = curr_password; - - if (IsCancelled()) return 0; - } - - // from high bit to low - bit = 0; - mask = 0xffffffff; - while (bit < 32) { - mask -= ( 1 << bit ); - curr_password = orig_password & mask; - // if updated mask didn't change the password, don't try it again - if (prev_password == curr_password) { - bit++; - continue; - } - found = tryOnePassword(curr_password); - if (found == -1) - return 0; - bit++; - prev_password = curr_password; - - if (IsCancelled()) return 0; - } - - PrintAndLogEx(NORMAL, ""); - - if (found == 1) - PrintAndLogEx(SUCCESS, "Found valid password: [%08x]", curr_password); - else - PrintAndLogEx(WARNING, "Password NOT found."); - - return 0; -} - -// note length of data returned is different for different chips. -// some return all page 1 (64 bits) and others return just that block (32 bits) -// unfortunately the 64 bits makes this more likely to get a false positive... -bool tryDetectP1(bool getData) { - uint8_t preamble[] = {1,1,1,0,0,0,0,0,0,0,0,1,0,1,0,1}; - size_t startIdx = 0; - uint8_t fc1 = 0, fc2 = 0, ans = 0; - int clk = 0, firstClockEdge = 0; - bool st = true; - - if ( getData ) { - if ( !AquireData(T55x7_PAGE1, 1, false, 0) ) - return false; - } - - // try fsk clock detect. if successful it cannot be any other type of modulation... (in theory...) - ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, &firstClockEdge); - if (ans && ((fc1==10 && fc2==8) || (fc1==8 && fc2==5))) { - if ( FSKrawDemod("0 0", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && - (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - return true; - } - if ( FSKrawDemod("0 1", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && - (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - return true; - } - return false; - } - - // try ask clock detect. it could be another type even if successful. - clk = GetAskClock("", false); - if (clk > 0) { - if ( ASKDemod_ext("0 0 1", false, false, 1, &st) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && - (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - return true; - } - st = true; - if ( ASKDemod_ext("0 1 1", false, false, 1, &st) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && - (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - return true; - } - if ( ASKbiphaseDemod("0 0 0 2", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && - (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - return true; - } - if ( ASKbiphaseDemod("0 0 1 2", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && - (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - return true; - } - } - - // try NRZ clock detect. it could be another type even if successful. - clk = GetNrzClock("", false); //has the most false positives :( - if (clk > 0) { - if ( NRZrawDemod("0 0 1", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && - (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - return true; - } - if ( NRZrawDemod("0 1 1", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && - (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - return true; - } - } - - // Fewer card uses PSK - // try psk clock detect. if successful it cannot be any other type of modulation... (in theory...) - clk = GetPskClock("", false); - if (clk > 0) { - // allow undo - // save_restoreGB(1); - // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) - //CmdLtrim("160"); - if ( PSKDemod("0 0 6", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && - (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - //save_restoreGB(0); - return true; - } - if ( PSKDemod("0 1 6", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && - (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - //save_restoreGB(0); - return true; - } - // PSK2 - needs a call to psk1TOpsk2. - if ( PSKDemod("0 0 6", false)) { - psk1TOpsk2(DemodBuffer, DemodBufferLen); - if (preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && - (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - //save_restoreGB(0); - return true; - } - } // inverse waves does not affect PSK2 demod - //undo trim samples - //save_restoreGB(0); - // no other modulation clocks = 2 or 4 so quit searching - if (fc1 != 8) return false; - } - - return false; -} -// does this need to be a callable command? -int CmdT55xxDetectPage1(const char *Cmd){ - bool errors = false; - bool useGB = false; - bool usepwd = false; - uint32_t password = 0; - uint8_t cmdp = 0; - - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_t55xx_detectP1(); - case 'p': - password = param_get32ex(Cmd, cmdp+1, 0, 16); - usepwd = true; - cmdp += 2; - break; - case '1': - // use Graphbuffer data - useGB = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - if (errors) return usage_t55xx_detectP1(); - - if ( !useGB ) { - if ( !AquireData(T55x7_PAGE1, 1, usepwd, password) ) - return false; - } - bool success = tryDetectP1(false); - if (success) PrintAndLogEx(SUCCESS, "T55xx chip found!"); - return success; -} - -int CmdT55xxSetDeviceConfig(const char *Cmd){ - uint8_t startgap = 0, writegap = 0; - uint8_t write0 = 0, write1 = 0, readgap = 0; - bool errors = false, shall_persist = false; - uint8_t cmdp = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_lf_deviceconfig(); - case 'a': - errors |= param_getdec(Cmd, cmdp+1, &startgap); - cmdp += 2; - break; - case 'b': - errors |= param_getdec(Cmd, cmdp+1, &writegap); - cmdp += 2; - break; - case 'c': - errors |= param_getdec(Cmd, cmdp+1, &write0); - cmdp += 2; - break; - case 'd': - errors |= param_getdec(Cmd, cmdp+1, &write1); - cmdp += 2; - break; - case 'e': - errors |= param_getdec(Cmd, cmdp+1, &readgap); - cmdp += 2; - break; - case 'p': - shall_persist = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = 1; - break; - } - } - - //Validations - if (errors || cmdp == 0) return usage_lf_deviceconfig(); - - t55xx_config config = { startgap*8, writegap*8, write0*8, write1*8, readgap*8 }; - - UsbCommand c = {CMD_SET_LF_T55XX_CONFIG, {shall_persist,0,0} }; - memcpy(c.d.asBytes, &config, sizeof(t55xx_config)); - clearCommandBuffer(); - SendCommand(&c); - return 0; -} - -static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"bruteforce", CmdT55xxBruteForce,0, " [i <*.dic>] Simple bruteforce attack to find password"}, - {"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"}, - {"chk", CmdT55xxChkPwds, 1, "Check passwords"}, - {"detect", CmdT55xxDetect, 1, "[1] Try detecting the tag modulation from reading the configuration block."}, - {"deviceconfig", CmdT55xxSetDeviceConfig, 1, "Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap"}, - {"p1detect", CmdT55xxDetectPage1,1, "[1] Try detecting if this is a t55xx tag by reading page 1"}, - {"dump", CmdT55xxDump, 0, "[password] [o] Dump T55xx card block 0-7. Optional [password], [override]"}, - {"info", CmdT55xxInfo, 1, "[1] Show T55x7 configuration data (page 0/ blk 0)"}, - {"read", CmdT55xxReadBlock, 0, "b p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]"}, - {"resetread", CmdResetRead, 0, "Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)"}, - {"recoverpw", CmdT55xxRecoverPW, 0, "[password] Try to recover from bad password write from a cloner. Only use on PW protected chips!"}, - {"special", special, 0, "Show block changes with 64 different offsets"}, - {"trace", CmdT55xxReadTrace, 1, "[1] Show T55x7 traceability data (page 1/ blk 0-1)"}, - {"wakeup", CmdT55xxWakeUp, 0, "Send AOR wakeup command"}, - {"wipe", CmdT55xxWipe, 0, "[q] Wipe a T55xx tag and set defaults (will destroy any data on tag)"}, - {"write", CmdT55xxWriteBlock,0, "b d p [password] [1] -- Write T55xx block data. Optional [p password], [page1]"}, - {NULL, NULL, 0, NULL} -}; - -int CmdLFT55XX(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; -} - -int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; -} +//----------------------------------------------------------------------------- +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency T55xx commands +//----------------------------------------------------------------------------- +#include "cmdlft55xx.h" + +// Default configuration +t55xx_conf_block_t config = { .modulation = DEMOD_ASK, .inverted = false, .offset = 0x00, .block0 = 0x00, .Q5 = false }; + +t55xx_conf_block_t Get_t55xx_Config(){ + return config; +} +void Set_t55xx_Config(t55xx_conf_block_t conf){ + config = conf; +} + +int usage_t55xx_config(){ + PrintAndLogEx(NORMAL, "Usage: lf t55xx config [d ] [i 1] [o ] [Q5]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - This help"); + PrintAndLogEx(NORMAL, " b <8|16|32|40|50|64|100|128> - Set bitrate"); + PrintAndLogEx(NORMAL, " d - Set demodulation FSK / ASK / PSK / NRZ / Biphase / Biphase A"); + PrintAndLogEx(NORMAL, " i [1] - Invert data signal, defaults to normal"); + PrintAndLogEx(NORMAL, " o [offset] - Set offset, where data should start decode in bitstream"); + PrintAndLogEx(NORMAL, " Q5 - Set as Q5(T5555) chip instead of T55x7"); + PrintAndLogEx(NORMAL, " ST - Set Sequence Terminator on"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx config d FSK - FSK demodulation"); + PrintAndLogEx(NORMAL, " lf t55xx config d FSK i 1 - FSK demodulation, inverse data"); + PrintAndLogEx(NORMAL, " lf t55xx config d FSK i 1 o 3 - FSK demodulation, inverse data, offset=3,start from position 3 to decode data"); + PrintAndLogEx(NORMAL, ""); + return 0; +} +int usage_t55xx_read(){ + PrintAndLogEx(NORMAL, "Usage: lf t55xx read [b ] [p ] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " b - block number to read. Between 0-7"); + PrintAndLogEx(NORMAL, " p - OPTIONAL password (8 hex characters)"); + PrintAndLogEx(NORMAL, " o - OPTIONAL override safety check"); + PrintAndLogEx(NORMAL, " 1 - OPTIONAL read Page 1 instead of Page 0"); + PrintAndLogEx(NORMAL, " ****WARNING****"); + PrintAndLogEx(NORMAL, " Use of read with password on a tag not configured for a pwd"); + PrintAndLogEx(NORMAL, " can damage the tag"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx read b 0 - read data from block 0"); + PrintAndLogEx(NORMAL, " lf t55xx read b 0 p feedbeef - read data from block 0 password feedbeef"); + PrintAndLogEx(NORMAL, " lf t55xx read b 0 p feedbeef o - read data from block 0 password feedbeef safety check"); + PrintAndLogEx(NORMAL, ""); + return 0; +} +int usage_t55xx_write(){ + PrintAndLogEx(NORMAL, "Usage: lf t55xx write [b ] [d ] [p ] [1] [t]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " b - block number to write. Between 0-7"); + PrintAndLogEx(NORMAL, " d - 4 bytes of data to write (8 hex characters)"); + PrintAndLogEx(NORMAL, " p - OPTIONAL password 4bytes (8 hex characters)"); + PrintAndLogEx(NORMAL, " 1 - OPTIONAL write Page 1 instead of Page 0"); + PrintAndLogEx(NORMAL, " t - OPTIONAL test mode write - ****DANGER****"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx write b 3 d 11223344 - write 11223344 to block 3"); + PrintAndLogEx(NORMAL, " lf t55xx write b 3 d 11223344 p feedbeef - write 11223344 to block 3 password feedbeef"); + PrintAndLogEx(NORMAL, ""); + return 0; +} +int usage_t55xx_trace() { + PrintAndLogEx(NORMAL, "Usage: lf t55xx trace [1]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx trace"); + PrintAndLogEx(NORMAL, " lf t55xx trace 1"); + PrintAndLogEx(NORMAL, ""); + return 0; +} +int usage_t55xx_info() { + PrintAndLogEx(NORMAL, "Usage: lf t55xx info [1]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx info"); + PrintAndLogEx(NORMAL, " lf t55xx info 1"); + PrintAndLogEx(NORMAL, ""); + return 0; +} +int usage_t55xx_dump(){ + PrintAndLogEx(NORMAL, "Usage: lf t55xx dump [o]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " - OPTIONAL password 4bytes (8 hex symbols)"); + PrintAndLogEx(NORMAL, " o - OPTIONAL override, force pwd read despite danger to card"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx dump"); + PrintAndLogEx(NORMAL, " lf t55xx dump feedbeef o"); + PrintAndLogEx(NORMAL, ""); + return 0; +} +int usage_t55xx_detect(){ + PrintAndLogEx(NORMAL, "Usage: lf t55xx detect [1] [p ]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag."); + PrintAndLogEx(NORMAL, " p - OPTIONAL password (8 hex characters)"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx detect"); + PrintAndLogEx(NORMAL, " lf t55xx detect 1"); + PrintAndLogEx(NORMAL, " lf t55xx detect p 11223344"); + PrintAndLogEx(NORMAL, ""); + return 0; +} +int usage_t55xx_detectP1(){ + PrintAndLogEx(NORMAL, "Command: Detect Page 1 of a t55xx chip"); + PrintAndLogEx(NORMAL, "Usage: lf t55xx p1detect [1] [p ]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " 1 - if set, use Graphbuffer otherwise read data from tag."); + PrintAndLogEx(NORMAL, " p - OPTIONAL password (8 hex characters)"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx p1detect"); + PrintAndLogEx(NORMAL, " lf t55xx p1detect 1"); + PrintAndLogEx(NORMAL, " lf t55xx p1detect p 11223344"); + PrintAndLogEx(NORMAL, ""); + return 0; +} +int usage_t55xx_wakup(){ + PrintAndLogEx(NORMAL, "Usage: lf t55xx wakeup [h] p "); + PrintAndLogEx(NORMAL, "This commands send the Answer-On-Request command and leaves the readerfield ON afterwards."); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - this help"); + PrintAndLogEx(NORMAL, " p - password 4bytes (8 hex symbols)"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx wakeup p 11223344 - send wakeup password"); + return 0; +} +int usage_t55xx_chk(){ + PrintAndLogEx(NORMAL, "This command uses a dictionary attack"); + PrintAndLogEx(NORMAL, "press 'enter' to cancel the command"); + PrintAndLogEx(NORMAL, "Usage: lf t55xx bruteforce [h] [i <*.dic>]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - this help"); + PrintAndLogEx(NORMAL, " m - use dictionary from flashmemory\n"); + PrintAndLogEx(NORMAL, " i <*.dic> - loads a default keys dictionary file <*.dic>"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx bruteforce m"); + PrintAndLogEx(NORMAL, " lf t55xx bruteforce i default_pwd.dic"); + PrintAndLogEx(NORMAL, ""); + return 0; +} +int usage_t55xx_bruteforce(){ + PrintAndLogEx(NORMAL, "This command uses bruteforce to scan a number range"); + PrintAndLogEx(NORMAL, "press 'enter' to cancel the command"); + PrintAndLogEx(NORMAL, "Usage: lf t55xx bruteforce [h] "); + PrintAndLogEx(NORMAL, " password must be 4 bytes (8 hex symbols)"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - this help"); + PrintAndLogEx(NORMAL, " - 4 byte hex value to start pwd search at"); + PrintAndLogEx(NORMAL, " - 4 byte hex value to end pwd search at"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx bruteforce aaaaaaaa bbbbbbbb"); + PrintAndLogEx(NORMAL, ""); + return 0; +} +int usage_t55xx_recoverpw(){ + PrintAndLogEx(NORMAL, "This command uses a few tricks to try to recover mangled password"); + PrintAndLogEx(NORMAL, "press 'enter' to cancel the command"); + PrintAndLogEx(NORMAL, "WARNING: this may brick non-password protected chips!"); + PrintAndLogEx(NORMAL, "Usage: lf t55xx recoverpw [password]"); + PrintAndLogEx(NORMAL, " password must be 4 bytes (8 hex symbols)"); + PrintAndLogEx(NORMAL, " default password is 51243648, used by many cloners"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - this help"); + PrintAndLogEx(NORMAL, " [password] - 4 byte hex value of password written by cloner"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx recoverpw"); + PrintAndLogEx(NORMAL, " lf t55xx recoverpw 51243648"); + PrintAndLogEx(NORMAL, ""); + return 0; +}int usage_t55xx_wipe(){ + PrintAndLogEx(NORMAL, "Usage: lf t55xx wipe [h] [Q5]"); + PrintAndLogEx(NORMAL, "This commands wipes a tag, fills blocks 1-7 with zeros and a default configuration block"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - this help"); + PrintAndLogEx(NORMAL, " Q5 - indicates to use the T5555 (Q5) default configuration block"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx wipe - wipes a t55x7 tag, config block 0x000880E0"); + PrintAndLogEx(NORMAL, " lf t55xx wipe Q5 - wipes a t5555 Q5 tag, config block 0x6001F004"); + return 0; +} +int usage_lf_deviceconfig(){ + PrintAndLogEx(NORMAL, "Sets t55x7 timings for direkt commands. The timings are set here in Field Clocks (FC), \nwhich is converted to (US) on device"); + PrintAndLogEx(NORMAL, "Usage: lf t55xx deviceconfig a b c d e p"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - This help"); + PrintAndLogEx(NORMAL, " a <8..255> - Set start gap"); + PrintAndLogEx(NORMAL, " b <8..255> - Set write gap"); + PrintAndLogEx(NORMAL, " c <8..255> - Set write ZERO gap"); + PrintAndLogEx(NORMAL, " d <8..255> - Set write ONE gap"); + PrintAndLogEx(NORMAL, " e <8..255> - Set read gap"); + PrintAndLogEx(NORMAL, " p - persist to flashmemory"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 29 b 17 c 15 d 47 e 15 - default T55XX"); + PrintAndLogEx(NORMAL, " lf t55xx deviceconfig a 55 b 14 c 21 d 30 - default EM4305"); + PrintAndLogEx(NORMAL, ""); + return 0; +} + +int CmdHelp(const char *Cmd); + +void printT5xxHeader(uint8_t page){ + PrintAndLogEx(NORMAL, "Reading Page %d:", page); + PrintAndLogEx(NORMAL, "blk | hex data | binary | ascii"); + PrintAndLogEx(NORMAL, "----+----------+----------------------------------+-------"); +} + +int CmdT55xxSetConfig(const char *Cmd) { + + uint8_t offset = 0; + char modulation[6] = {0x00}; + char tmp = 0x00; + uint8_t bitRate = 0; + uint8_t rates[9] = {8,16,32,40,50,64,100,128,0}; + uint8_t cmdp = 0; + bool errors = false; + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + tmp = tolower(param_getchar(Cmd, cmdp)); + switch(tmp) { + case 'h': + return usage_t55xx_config(); + case 'b': + errors |= param_getdec(Cmd, cmdp+1, &bitRate); + if ( !errors){ + uint8_t i = 0; + for (; i < 9; i++){ + if (rates[i]==bitRate) { + config.bitrate = i; + break; + } + } + if (i==9) errors = true; + } + cmdp+=2; + break; + case 'd': + param_getstr(Cmd, cmdp+1, modulation, sizeof(modulation)); + cmdp += 2; + + if ( strcmp(modulation, "FSK" ) == 0) { + config.modulation = DEMOD_FSK; + } else if ( strcmp(modulation, "FSK1" ) == 0) { + config.modulation = DEMOD_FSK1; + config.inverted=1; + } else if ( strcmp(modulation, "FSK1a" ) == 0) { + config.modulation = DEMOD_FSK1a; + config.inverted=0; + } else if ( strcmp(modulation, "FSK2" ) == 0) { + config.modulation = DEMOD_FSK2; + config.inverted=0; + } else if ( strcmp(modulation, "FSK2a" ) == 0) { + config.modulation = DEMOD_FSK2a; + config.inverted=1; + } else if ( strcmp(modulation, "ASK" ) == 0) { + config.modulation = DEMOD_ASK; + } else if ( strcmp(modulation, "NRZ" ) == 0) { + config.modulation = DEMOD_NRZ; + } else if ( strcmp(modulation, "PSK1" ) == 0) { + config.modulation = DEMOD_PSK1; + } else if ( strcmp(modulation, "PSK2" ) == 0) { + config.modulation = DEMOD_PSK2; + } else if ( strcmp(modulation, "PSK3" ) == 0) { + config.modulation = DEMOD_PSK3; + } else if ( strcmp(modulation, "BIa" ) == 0) { + config.modulation = DEMOD_BIa; + config.inverted=1; + } else if ( strcmp(modulation, "BI" ) == 0) { + config.modulation = DEMOD_BI; + config.inverted=0; + } else { + PrintAndLogEx(WARNING, "Unknown modulation '%s'", modulation); + errors = true; + } + break; + case 'i': + config.inverted = param_getchar(Cmd,cmdp+1) == '1'; + cmdp+=2; + break; + case 'o': + errors |= param_getdec(Cmd, cmdp+1, &offset); + if ( !errors ) + config.offset = offset; + cmdp+=2; + break; + case 'q': + config.Q5 = true; + cmdp++; + break; + case 's': + config.ST = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + + // No args + if (cmdp == 0) return printConfiguration( config ); + + //Validations + if (errors) return usage_t55xx_config(); + + config.block0 = 0; + return printConfiguration ( config ); +} + +int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32_t password){ + //Password mode + if ( usepwd ) { + // try reading the config block and verify that PWD bit is set before doing this! + if ( !override ) { + + if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, false, 0 ) ) return 0; + + if ( !tryDetectModulation() ) { + PrintAndLogEx(NORMAL, "Safety Check: Could not detect if PWD bit is set in config block. Exits."); + return 0; + } else { + PrintAndLogEx(NORMAL, "Safety Check: PWD bit is NOT set in config block. Reading without password..."); + usepwd = false; + page1 = false; + } + } else { + PrintAndLogEx(NORMAL, "Safety Check Overriden - proceeding despite risk"); + } + } + + if (!AquireData(page1, block, usepwd, password) ) return 0; + if (!DecodeT55xxBlock()) return 0; + + char blk[10] = {0}; + sprintf(blk, "%02d", block); + printT55xxBlock(blk); + return 1; +} + +int CmdT55xxReadBlock(const char *Cmd) { + uint8_t block = REGULAR_READ_MODE_BLOCK; + uint32_t password = 0; //default to blank Block 7 + bool usepwd = false; + bool override = false; + bool page1 = false; + bool errors = false; + uint8_t cmdp = 0; + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch ( tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_t55xx_read(); + case 'b': + errors |= param_getdec(Cmd, cmdp+1, &block); + cmdp += 2; + break; + case 'o': + override = true; + cmdp++; + break; + case 'p': + password = param_get32ex(Cmd, cmdp+1, 0, 16); + usepwd = true; + cmdp += 2; + break; + case '1': + page1 = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + if (errors) return usage_t55xx_read(); + + if (block > 7 && block != REGULAR_READ_MODE_BLOCK ) { + PrintAndLogEx(NORMAL, "Block must be between 0 and 7"); + return 0; + } + + printT5xxHeader(page1); + return T55xxReadBlock(block, page1, usepwd, override, password); +} + +bool DecodeT55xxBlock(){ + + char buf[30] = {0x00}; + char *cmdStr = buf; + int ans = 0; + bool ST = config.ST; + uint8_t bitRate[8] = {8,16,32,40,50,64,100,128}; + DemodBufferLen = 0x00; + + switch( config.modulation ){ + case DEMOD_FSK: + snprintf(cmdStr, sizeof(buf),"%d %d", bitRate[config.bitrate], config.inverted ); + ans = FSKrawDemod(cmdStr, false); + break; + case DEMOD_FSK1: + case DEMOD_FSK1a: + snprintf(cmdStr, sizeof(buf),"%d %d 8 5", bitRate[config.bitrate], config.inverted ); + ans = FSKrawDemod(cmdStr, false); + break; + case DEMOD_FSK2: + case DEMOD_FSK2a: + snprintf(cmdStr, sizeof(buf),"%d %d 10 8", bitRate[config.bitrate], config.inverted ); + ans = FSKrawDemod(cmdStr, false); + break; + case DEMOD_ASK: + snprintf(cmdStr, sizeof(buf),"%d %d 1", bitRate[config.bitrate], config.inverted ); + ans = ASKDemod_ext(cmdStr, false, false, 1, &ST); + break; + case DEMOD_PSK1: + // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) + save_restoreGB(GRAPH_SAVE); + CmdLtrim("160"); + snprintf(cmdStr, sizeof(buf),"%d %d 6", bitRate[config.bitrate], config.inverted ); + ans = PSKDemod(cmdStr, false); + //undo trim samples + save_restoreGB(GRAPH_RESTORE); + break; + case DEMOD_PSK2: //inverted won't affect this + case DEMOD_PSK3: //not fully implemented + // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) + save_restoreGB(GRAPH_SAVE); + CmdLtrim("160"); + snprintf(cmdStr, sizeof(buf),"%d 0 6", bitRate[config.bitrate] ); + ans = PSKDemod(cmdStr, false); + psk1TOpsk2(DemodBuffer, DemodBufferLen); + //undo trim samples + save_restoreGB(GRAPH_RESTORE); + break; + case DEMOD_NRZ: + snprintf(cmdStr, sizeof(buf),"%d %d 1", bitRate[config.bitrate], config.inverted ); + ans = NRZrawDemod(cmdStr, false); + break; + case DEMOD_BI: + case DEMOD_BIa: + snprintf(cmdStr, sizeof(buf),"0 %d %d 1", bitRate[config.bitrate], config.inverted ); + ans = ASKbiphaseDemod(cmdStr, false); + break; + default: + return false; + } + return (bool) ans; +} + +bool DecodeT5555TraceBlock() { + DemodBufferLen = 0x00; + + // According to datasheet. Always: RF/64, not inverted, Manchester + return (bool) ASKDemod("64 0 1", false, false, 1); +} + +// sanity check. Don't use proxmark if it is offline and you didn't specify useGraphbuf +static int SanityOfflineCheck( bool useGraphBuffer ){ + if ( !useGraphBuffer && IsOffline() ) { + PrintAndLogEx(NORMAL, "Your proxmark3 device is offline. Specify [1] to use graphbuffer data instead"); + return 0; + } + return 1; +} + +int CmdT55xxDetect(const char *Cmd){ + bool errors = false; + bool useGB = false, usepwd = false; + uint32_t password = 0; + uint8_t cmdp = 0; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch ( tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_t55xx_detect(); + case 'p': + password = param_get32ex(Cmd, cmdp+1, 0, 16); + usepwd = true; + cmdp += 2; + break; + case '1': + // use Graphbuffer data + useGB = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + if (errors) return usage_t55xx_detect(); + + // sanity check. + if (!SanityOfflineCheck(useGB)) return 1; + + if ( !useGB) { + if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password) ) + return 1; + } + + if ( !tryDetectModulation() ) + PrintAndLogEx(WARNING, "Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'"); + + return 0; +} + +// detect configuration? +bool tryDetectModulation(){ + + t55xx_conf_block_t tests[15]; + int bitRate = 0, clk = 0, firstClockEdge = 0; + uint8_t hits = 0, fc1 = 0, fc2 = 0, ans = 0; + + ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, &firstClockEdge); + + if (ans && ((fc1==10 && fc2==8) || (fc1==8 && fc2==5))) { + if ( FSKrawDemod("0 0", false) && test(DEMOD_FSK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)){ + tests[hits].modulation = DEMOD_FSK; + if (fc1==8 && fc2 == 5) + tests[hits].modulation = DEMOD_FSK1a; + else if (fc1==10 && fc2 == 8) + tests[hits].modulation = DEMOD_FSK2; + tests[hits].bitrate = bitRate; + tests[hits].inverted = false; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + tests[hits].ST = false; + ++hits; + } + if ( FSKrawDemod("0 1", false) && test(DEMOD_FSK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { + tests[hits].modulation = DEMOD_FSK; + if (fc1 == 8 && fc2 == 5) + tests[hits].modulation = DEMOD_FSK1; + else if (fc1 == 10 && fc2 == 8) + tests[hits].modulation = DEMOD_FSK2a; + tests[hits].bitrate = bitRate; + tests[hits].inverted = true; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + tests[hits].ST = false; + ++hits; + } + } else { + clk = GetAskClock("", false); + if (clk > 0) { + tests[hits].ST = true; + // "0 0 1 " == clock auto, invert false, maxError 1. + // false = no verbose + // false = no emSearch + // 1 = Ask/Man + // st = true + if ( ASKDemod_ext("0 0 1", false, false, 1, &tests[hits].ST) && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { + tests[hits].modulation = DEMOD_ASK; + tests[hits].bitrate = bitRate; + tests[hits].inverted = false; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + ++hits; + } + tests[hits].ST = true; + // "0 0 1 " == clock auto, invert true, maxError 1. + // false = no verbose + // false = no emSearch + // 1 = Ask/Man + // st = true + if ( ASKDemod_ext("0 1 1", false, false, 1, &tests[hits].ST) && test(DEMOD_ASK, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { + tests[hits].modulation = DEMOD_ASK; + tests[hits].bitrate = bitRate; + tests[hits].inverted = true; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + ++hits; + } + if ( ASKbiphaseDemod("0 0 0 2", false) && test(DEMOD_BI, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5) ) { + tests[hits].modulation = DEMOD_BI; + tests[hits].bitrate = bitRate; + tests[hits].inverted = false; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + tests[hits].ST = false; + ++hits; + } + if ( ASKbiphaseDemod("0 0 1 2", false) && test(DEMOD_BIa, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5) ) { + tests[hits].modulation = DEMOD_BIa; + tests[hits].bitrate = bitRate; + tests[hits].inverted = true; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + tests[hits].ST = false; + ++hits; + } + } + clk = GetNrzClock("", false); + if (clk > 8) { //clock of rf/8 is likely a false positive, so don't use it. + if ( NRZrawDemod("0 0 1", false) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { + tests[hits].modulation = DEMOD_NRZ; + tests[hits].bitrate = bitRate; + tests[hits].inverted = false; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + tests[hits].ST = false; + ++hits; + } + + if ( NRZrawDemod("0 1 1", false) && test(DEMOD_NRZ, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { + tests[hits].modulation = DEMOD_NRZ; + tests[hits].bitrate = bitRate; + tests[hits].inverted = true; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + tests[hits].ST = false; + ++hits; + } + } + + clk = GetPskClock("", false); + if (clk > 0) { + // allow undo + save_restoreGB(GRAPH_SAVE); + // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) + CmdLtrim("160"); + if ( PSKDemod("0 0 6", false) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { + tests[hits].modulation = DEMOD_PSK1; + tests[hits].bitrate = bitRate; + tests[hits].inverted = false; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + tests[hits].ST = false; + ++hits; + } + if ( PSKDemod("0 1 6", false) && test(DEMOD_PSK1, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)) { + tests[hits].modulation = DEMOD_PSK1; + tests[hits].bitrate = bitRate; + tests[hits].inverted = true; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + tests[hits].ST = false; + ++hits; + } + //ICEMAN: are these PSKDemod calls needed? + // PSK2 - needs a call to psk1TOpsk2. + if ( PSKDemod("0 0 6", false)) { + psk1TOpsk2(DemodBuffer, DemodBufferLen); + if (test(DEMOD_PSK2, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)){ + tests[hits].modulation = DEMOD_PSK2; + tests[hits].bitrate = bitRate; + tests[hits].inverted = false; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + tests[hits].ST = false; + ++hits; + } + } // inverse waves does not affect this demod + // PSK3 - needs a call to psk1TOpsk2. + if ( PSKDemod("0 0 6", false)) { + psk1TOpsk2(DemodBuffer, DemodBufferLen); + if (test(DEMOD_PSK3, &tests[hits].offset, &bitRate, clk, &tests[hits].Q5)){ + tests[hits].modulation = DEMOD_PSK3; + tests[hits].bitrate = bitRate; + tests[hits].inverted = false; + tests[hits].block0 = PackBits(tests[hits].offset, 32, DemodBuffer); + tests[hits].ST = false; + ++hits; + } + } // inverse waves does not affect this demod + //undo trim samples + save_restoreGB(GRAPH_RESTORE); + } + } + if ( hits == 1) { + config.modulation = tests[0].modulation; + config.bitrate = tests[0].bitrate; + config.inverted = tests[0].inverted; + config.offset = tests[0].offset; + config.block0 = tests[0].block0; + config.Q5 = tests[0].Q5; + config.ST = tests[0].ST; + printConfiguration( config ); + return true; + } + + bool retval = false; + if ( hits > 1) { + PrintAndLogEx(SUCCESS, "Found [%d] possible matches for modulation.", hits); + for(int i=0; i= DEMOD_FSK1 && modread <= DEMOD_FSK2a) return true; + break; + case DEMOD_ASK: + if (modread == DEMOD_ASK) return true; + break; + case DEMOD_PSK1: + if (modread == DEMOD_PSK1) return true; + break; + case DEMOD_PSK2: + if (modread == DEMOD_PSK2) return true; + break; + case DEMOD_PSK3: + if (modread == DEMOD_PSK3) return true; + break; + case DEMOD_NRZ: + if (modread == DEMOD_NRZ) return true; + break; + case DEMOD_BI: + if (modread == DEMOD_BI) return true; + break; + case DEMOD_BIa: + if (modread == DEMOD_BIa) return true; + break; + default: + return false; + } + return false; +} + +bool testQ5Modulation(uint8_t mode, uint8_t modread){ + switch( mode ){ + case DEMOD_FSK: + if (modread >= 4 && modread <= 5) return true; + break; + case DEMOD_ASK: + if (modread == 0) return true; + break; + case DEMOD_PSK1: + if (modread == 1) return true; + break; + case DEMOD_PSK2: + if (modread == 2) return true; + break; + case DEMOD_PSK3: + if (modread == 3) return true; + break; + case DEMOD_NRZ: + if (modread == 7) return true; + break; + case DEMOD_BI: + if (modread == 6) return true; + break; + default: + return false; + } + return false; +} + +int convertQ5bitRate(uint8_t bitRateRead) { + uint8_t expected[] = {8, 16, 32, 40, 50, 64, 100, 128}; + for (int i=0; i<8; i++) + if (expected[i] == bitRateRead) + return i; + + return -1; +} + +bool testQ5(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk){ + + if ( DemodBufferLen < 64 ) return false; + uint8_t si = 0; + for (uint8_t idx = 28; idx < 64; idx++){ + si = idx; + if ( PackBits(si, 28, DemodBuffer) == 0x00 ) continue; + + uint8_t safer = PackBits(si, 4, DemodBuffer); si += 4; //master key + uint8_t resv = PackBits(si, 8, DemodBuffer); si += 8; + // 2nibble must be zeroed. + if (safer != 0x6 && safer != 0x9) continue; + if ( resv > 0x00) continue; + //uint8_t pageSel = PackBits(si, 1, DemodBuffer); si += 1; + //uint8_t fastWrite = PackBits(si, 1, DemodBuffer); si += 1; + si += 1+1; + int bitRate = PackBits(si, 6, DemodBuffer)*2 + 2; si += 6; //bit rate + if (bitRate > 128 || bitRate < 8) continue; + + //uint8_t AOR = PackBits(si, 1, DemodBuffer); si += 1; + //uint8_t PWD = PackBits(si, 1, DemodBuffer); si += 1; + //uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2; //could check psk cr + //uint8_t inverse = PackBits(si, 1, DemodBuffer); si += 1; + si += 1+1+2+1; + uint8_t modread = PackBits(si, 3, DemodBuffer); si += 3; + uint8_t maxBlk = PackBits(si, 3, DemodBuffer); si += 3; + //uint8_t ST = PackBits(si, 1, DemodBuffer); si += 1; + if (maxBlk == 0) continue; + //test modulation + if (!testQ5Modulation(mode, modread)) continue; + if (bitRate != clk) continue; + *fndBitRate = convertQ5bitRate(bitRate); + if (*fndBitRate < 0) continue; + *offset = idx; + + return true; + } + return false; +} + +bool testBitRate(uint8_t readRate, uint8_t clk){ + uint8_t expected[] = {8, 16, 32, 40, 50, 64, 100, 128}; + if (expected[readRate] == clk) + return true; + + return false; +} + +bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5){ + + if ( DemodBufferLen < 64 ) return false; + uint8_t si = 0; + for (uint8_t idx = 28; idx < 64; idx++){ + si = idx; + if ( PackBits(si, 28, DemodBuffer) == 0x00 ) continue; + + uint8_t safer = PackBits(si, 4, DemodBuffer); si += 4; //master key + uint8_t resv = PackBits(si, 4, DemodBuffer); si += 4; //was 7 & +=7+3 //should be only 4 bits if extended mode + // 2nibble must be zeroed. + // moved test to here, since this gets most faults first. + if ( resv > 0x00) continue; + + int bitRate = PackBits(si, 6, DemodBuffer); si += 6; //bit rate (includes extended mode part of rate) + uint8_t extend = PackBits(si, 1, DemodBuffer); si += 1; //bit 15 extended mode + uint8_t modread = PackBits(si, 5, DemodBuffer); si += 5+2+1; + //uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2+1; //could check psk cr + //uint8_t nml01 = PackBits(si, 1, DemodBuffer); si += 1+5; //bit 24, 30, 31 could be tested for 0 if not extended mode + //uint8_t nml02 = PackBits(si, 2, DemodBuffer); si += 2; + + //if extended mode + bool extMode =( (safer == 0x6 || safer == 0x9) && extend) ? true : false; + + if (!extMode){ + if (bitRate > 7) continue; + if (!testBitRate(bitRate, clk)) continue; + } else { //extended mode bitrate = same function to calc bitrate as em4x05 + if (EM4x05_GET_BITRATE(bitRate) != clk) continue; + + } + //test modulation + if (!testModulation(mode, modread)) continue; + *fndBitRate = bitRate; + *offset = idx; + *Q5 = false; + return true; + } + if (testQ5(mode, offset, fndBitRate, clk)) { + *Q5 = true; + return true; + } + return false; +} + +void printT55xxBlock(const char *blockNum){ + + uint8_t i = config.offset; + uint8_t endpos = 32 + i; + uint32_t blockData = 0; + uint8_t bits[64] = {0x00}; + + if ( !DemodBufferLen) return; + + if ( endpos > DemodBufferLen){ + PrintAndLogEx(NORMAL, "The configured offset %d is too big. Possible offset: %d)", i, DemodBufferLen-32); + return; + } + + for (; i < endpos; ++i) + bits[i - config.offset] = DemodBuffer[i]; + + blockData = PackBits(0, 32, bits); + uint8_t bytes[4] = {0}; + num_to_bytes(blockData, 4, bytes); + + PrintAndLogEx(NORMAL, " %s | %08X | %s | %s", blockNum, blockData, sprint_bin(bits,32), sprint_ascii(bytes,4)); +} + +int special(const char *Cmd) { + uint32_t blockData = 0; + uint8_t bits[32] = {0x00}; + + PrintAndLogEx(NORMAL, "OFFSET | DATA | BINARY | ASCII"); + PrintAndLogEx(NORMAL, "-------+-------+-------------------------------------+------"); + int i,j = 0; + for (; j < 64; ++j){ + + for (i = 0; i < 32; ++i) + bits[i]=DemodBuffer[j+i]; + + blockData = PackBits(0, 32, bits); + + PrintAndLogEx(NORMAL, "%02d | 0x%08X | %s",j , blockData, sprint_bin(bits,32)); + } + return 0; +} + +int printConfiguration( t55xx_conf_block_t b){ + PrintAndLogEx(NORMAL, "Chip Type : %s", (b.Q5) ? "T5555(Q5)" : "T55x7"); + PrintAndLogEx(NORMAL, "Modulation : %s", GetSelectedModulationStr(b.modulation) ); + PrintAndLogEx(NORMAL, "Bit Rate : %s", GetBitRateStr(b.bitrate, (b.block0 & T55x7_X_MODE && (b.block0>>28==6 || b.block0>>28==9))) ); + PrintAndLogEx(NORMAL, "Inverted : %s", (b.inverted) ? _GREEN_(Yes) : "No" ); + PrintAndLogEx(NORMAL, "Offset : %d", b.offset); + PrintAndLogEx(NORMAL, "Seq. Term. : %s", (b.ST) ? _GREEN_(Yes) : "No" ); + PrintAndLogEx(NORMAL, "Block0 : 0x%08X", b.block0); + PrintAndLogEx(NORMAL, ""); + return 0; +} + +int CmdT55xxWakeUp(const char *Cmd) { + uint32_t password = 0; + uint8_t cmdp = 0; + bool errors = false; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_t55xx_wakup(); + case 'p': + password = param_get32ex(Cmd, cmdp+1, 0, 16); + cmdp += 2; + errors = false; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + if (errors) return usage_t55xx_wakup(); + + UsbCommand c = {CMD_T55XX_WAKEUP, {password, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + PrintAndLogEx(SUCCESS, "Wake up command sent. Try read now"); + return 0; +} + +int CmdT55xxWriteBlock(const char *Cmd) { + uint8_t block = 0xFF; //default to invalid block + uint32_t data = 0; //default to blank Block + uint32_t password = 0; //default to blank Block 7 + bool usepwd = false; + bool page1 = false; + bool gotdata = false; + bool testMode = false; + bool errors = false; + uint8_t cmdp = 0; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_t55xx_write(); + case 'b': + errors |= param_getdec(Cmd, cmdp+1, &block); + cmdp += 2; + break; + case 'd': + data = param_get32ex(Cmd, cmdp+1, 0, 16); + gotdata = true; + cmdp += 2; + break; + case 'p': + password = param_get32ex(Cmd, cmdp+1, 0, 16); + usepwd = true; + cmdp += 2; + break; + case 't': + testMode = true; + cmdp++; + break; + case '1': + page1 = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + if (errors || !gotdata) return usage_t55xx_write(); + + if (block > 7) { + PrintAndLogEx(WARNING, "Block number must be between 0 and 7"); + return 0; + } + + UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {data, block, 0}}; + UsbCommand resp; + c.d.asBytes[0] = (page1) ? 0x2 : 0; + c.d.asBytes[0] |= (testMode) ? 0x4 : 0; + + char pwdStr[16] = {0}; + snprintf(pwdStr, sizeof(pwdStr), "pwd: 0x%08X", password); + + PrintAndLogEx(INFO, "Writing page %d block: %02d data: 0x%08X %s", page1, block, data, (usepwd) ? pwdStr : "" ); + + //Password mode + if (usepwd) { + c.arg[2] = password; + c.d.asBytes[0] |= 0x1; + } + clearCommandBuffer(); + SendCommand(&c); + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 1500 )){ + PrintAndLogEx(WARNING, "Error occurred, device did not ACK write operation. (May be due to old firmware)"); + return 0; + } + return 1; +} + +int CmdT55xxReadTrace(const char *Cmd) { + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 1 || cmdp == 'h') return usage_t55xx_trace(); + + bool pwdmode = false; + uint32_t password = 0; + + if (strlen(Cmd) == 0) { + // sanity check. + if (!SanityOfflineCheck(false)) return 1; + + if ( !AquireData( T55x7_PAGE1, REGULAR_READ_MODE_BLOCK, pwdmode, password ) ) + return 1; + } + + if ( config.Q5 ){ + if (!DecodeT5555TraceBlock()) return 1; + } else { + if (!DecodeT55xxBlock()) return 1; + } + + if ( !DemodBufferLen ) return 1; + + RepaintGraphWindow(); + uint8_t repeat = (config.offset > 5) ? 32 : 0; + + uint8_t si = config.offset + repeat; + uint32_t bl1 = PackBits(si, 32, DemodBuffer); + uint32_t bl2 = PackBits(si+32, 32, DemodBuffer); + + if (config.Q5) { + uint32_t hdr = PackBits(si, 9, DemodBuffer); si += 9; + + if (hdr != 0x1FF) { + PrintAndLogEx(FAILED, "Invalid Q5 Trace data header (expected 0x1FF, found %X)", hdr); + return 1; + } + + t5555_tracedata_t data = {.bl1 = bl1, .bl2 = bl2, .icr = 0, .lotidc = '?', .lotid = 0, .wafer = 0, .dw =0}; + + data.icr = PackBits(si, 2, DemodBuffer); si += 2; + data.lotidc = 'Z' - PackBits(si, 2, DemodBuffer); si += 3; + + data.lotid = PackBits(si, 4, DemodBuffer); si += 5; + data.lotid <<= 4; + data.lotid |= PackBits(si, 4, DemodBuffer); si += 5; + data.lotid <<= 4; + data.lotid |= PackBits(si, 4, DemodBuffer); si += 5; + data.lotid <<= 4; + data.lotid |= PackBits(si, 4, DemodBuffer); si += 5; + data.lotid <<= 1; + data.lotid |= PackBits(si, 1, DemodBuffer); si += 1; + + data.wafer = PackBits(si, 3, DemodBuffer); si += 4; + data.wafer <<= 2; + data.wafer |= PackBits(si, 2, DemodBuffer); si += 2; + + data.dw = PackBits(si, 2, DemodBuffer); si += 3; + data.dw <<= 4; + data.dw |= PackBits(si, 4, DemodBuffer); si += 5; + data.dw <<= 4; + data.dw |= PackBits(si, 4, DemodBuffer); si += 5; + data.dw <<= 4; + data.dw |= PackBits(si, 4, DemodBuffer); si += 5; + + printT5555Trace(data, repeat); + + } else { + + t55x7_tracedata_t data = {.bl1 = bl1, .bl2 = bl2, .acl = 0, .mfc = 0, .cid = 0, .year = 0, .quarter = 0, .icr = 0, .lotid = 0, .wafer = 0, .dw = 0}; + + data.acl = PackBits(si, 8, DemodBuffer); si += 8; + if ( data.acl != 0xE0 ) { + PrintAndLogEx(FAILED, "The modulation is most likely wrong since the ACL is not 0xE0. "); + return 1; + } + + data.mfc = PackBits(si, 8, DemodBuffer); si += 8; + data.cid = PackBits(si, 5, DemodBuffer); si += 5; + data.icr = PackBits(si, 3, DemodBuffer); si += 3; + data.year = PackBits(si, 4, DemodBuffer); si += 4; + data.quarter = PackBits(si, 2, DemodBuffer); si += 2; + data.lotid = PackBits(si, 14, DemodBuffer); si += 14; + data.wafer = PackBits(si, 5, DemodBuffer); si += 5; + data.dw = PackBits(si, 15, DemodBuffer); + + time_t t = time(NULL); + struct tm tm = *localtime(&t); + if ( data.year > tm.tm_year-110) + data.year += 2000; + else + data.year += 2010; + + printT55x7Trace(data, repeat); + } + return 0; +} + +void printT55x7Trace( t55x7_tracedata_t data, uint8_t repeat ){ + PrintAndLogEx(NORMAL, "-- T55x7 Trace Information ----------------------------------"); + PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(NORMAL, " ACL Allocation class (ISO/IEC 15963-1) : 0x%02X (%d)", data.acl, data.acl); + PrintAndLogEx(NORMAL, " MFC Manufacturer ID (ISO/IEC 7816-6) : 0x%02X (%d) - %s", data.mfc, data.mfc, getTagInfo(data.mfc)); + PrintAndLogEx(NORMAL, " CID : 0x%02X (%d) - %s", data.cid, data.cid, GetModelStrFromCID(data.cid)); + PrintAndLogEx(NORMAL, " ICR IC Revision : %d", data.icr ); + PrintAndLogEx(NORMAL, " Manufactured"); + PrintAndLogEx(NORMAL, " Year/Quarter : %d/%d", data.year, data.quarter); + PrintAndLogEx(NORMAL, " Lot ID : %d", data.lotid ); + PrintAndLogEx(NORMAL, " Wafer number : %d", data.wafer); + PrintAndLogEx(NORMAL, " Die Number : %d", data.dw); + PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(NORMAL, " Raw Data - Page 1"); + PrintAndLogEx(NORMAL, " Block 1 : 0x%08X %s", data.bl1, sprint_bin(DemodBuffer+config.offset+repeat,32) ); + PrintAndLogEx(NORMAL, " Block 2 : 0x%08X %s", data.bl2, sprint_bin(DemodBuffer+config.offset+repeat+32,32) ); + PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + + /* + TRACE - BLOCK O + Bits Definition HEX + 1-8 ACL Allocation class (ISO/IEC 15963-1) 0xE0 + 9-16 MFC Manufacturer ID (ISO/IEC 7816-6) 0x15 Atmel Corporation + 17-21 CID 0x1 = Atmel ATA5577M1 0x2 = Atmel ATA5577M2 + 22-24 ICR IC revision + 25-28 YEAR (BCD encoded) 9 (= 2009) + 29-30 QUARTER 1,2,3,4 + 31-32 LOT ID + + TRACE - BLOCK 1 + 1-12 LOT ID + 13-17 Wafer number + 18-32 DW, die number sequential + */ +} + +void printT5555Trace( t5555_tracedata_t data, uint8_t repeat ){ + PrintAndLogEx(NORMAL, "-- T5555 (Q5) Trace Information -----------------------------"); + PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(NORMAL, " ICR IC Revision : %d", data.icr ); + PrintAndLogEx(NORMAL, " Lot : %c%d", data.lotidc, data.lotid); + PrintAndLogEx(NORMAL, " Wafer number : %d", data.wafer); + PrintAndLogEx(NORMAL, " Die Number : %d", data.dw); + PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(NORMAL, " Raw Data - Page 1"); + PrintAndLogEx(NORMAL, " Block 1 : 0x%08X %s", data.bl1, sprint_bin(DemodBuffer+config.offset+repeat,32) ); + PrintAndLogEx(NORMAL, " Block 2 : 0x%08X %s", data.bl2, sprint_bin(DemodBuffer+config.offset+repeat+32,32) ); + + /* + ** Q5 ** + TRACE - BLOCK O and BLOCK1 + Bits Definition HEX + 1-9 Header 0x1FF + 10-11 IC Revision + 12-13 Lot ID char + 15-35 Lot ID (NB parity) + 36-41 Wafer number (NB parity) + 42-58 DW, die number sequential (NB parity) + 60-63 Parity bits + 64 Always zero + */ +} + +//need to add Q5 info... +int CmdT55xxInfo(const char *Cmd){ + /* + Page 0 Block 0 Configuration data. + Normal mode + Extended mode + */ + bool pwdmode = false; + uint32_t password = 0; + char cmdp = tolower(param_getchar(Cmd, 0)); + + if (strlen(Cmd) > 1 || cmdp == 'h') return usage_t55xx_info(); + + if (strlen(Cmd) == 0) { + // sanity check. + if (!SanityOfflineCheck(false)) return 1; + + if ( !AquireData( T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, pwdmode, password ) ) + return 1; + } + + if (!DecodeT55xxBlock()) return 1; + + // too little space to start with + if ( DemodBufferLen < 32) return 1; + + // + //PrintAndLogEx(NORMAL, "Offset+32 ==%d\n DemodLen == %d", config.offset + 32, DemodBufferLen); + + uint8_t si = config.offset; + uint32_t block0 = PackBits(si, 32, DemodBuffer); + uint32_t safer = PackBits(si, 4, DemodBuffer); si += 4; + uint32_t resv = PackBits(si, 7, DemodBuffer); si += 7; + uint32_t dbr = PackBits(si, 3, DemodBuffer); si += 3; + uint32_t extend = PackBits(si, 1, DemodBuffer); si += 1; + uint32_t datamod = PackBits(si, 5, DemodBuffer); si += 5; + uint32_t pskcf = PackBits(si, 2, DemodBuffer); si += 2; + uint32_t aor = PackBits(si, 1, DemodBuffer); si += 1; + uint32_t otp = PackBits(si, 1, DemodBuffer); si += 1; + uint32_t maxblk = PackBits(si, 3, DemodBuffer); si += 3; + uint32_t pwd = PackBits(si, 1, DemodBuffer); si += 1; + uint32_t sst = PackBits(si, 1, DemodBuffer); si += 1; + uint32_t fw = PackBits(si, 1, DemodBuffer); si += 1; + uint32_t inv = PackBits(si, 1, DemodBuffer); si += 1; + uint32_t por = PackBits(si, 1, DemodBuffer); si += 1; + + if (config.Q5) + PrintAndLogEx(NORMAL, _RED_(*** Warning ***) " Config Info read off a Q5 will not display as expected"); + + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "-- T55x7 Configuration & Tag Information --------------------"); + PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(NORMAL, " Safer key : %s", GetSaferStr(safer)); + PrintAndLogEx(NORMAL, " reserved : %d", resv); + PrintAndLogEx(NORMAL, " Data bit rate : %s", GetBitRateStr(dbr, extend)); + PrintAndLogEx(NORMAL, " eXtended mode : %s", (extend) ? _YELLOW_(Yes - Warning) : "No"); + PrintAndLogEx(NORMAL, " Modulation : %s", GetModulationStr(datamod)); + PrintAndLogEx(NORMAL, " PSK clock frequency : %d", pskcf); + PrintAndLogEx(NORMAL, " AOR - Answer on Request : %s", (aor) ? _GREEN_(Yes) : "No"); + PrintAndLogEx(NORMAL, " OTP - One Time Pad : %s", (otp) ? _YELLOW_(Yes - Warning) : "No" ); + PrintAndLogEx(NORMAL, " Max block : %d", maxblk); + PrintAndLogEx(NORMAL, " Password mode : %s", (pwd) ? _GREEN_(Yes) : "No"); + PrintAndLogEx(NORMAL, " Sequence Start Terminator : %s", (sst) ? _GREEN_(Yes) : "No"); + PrintAndLogEx(NORMAL, " Fast Write : %s", (fw) ? _GREEN_(Yes) : "No"); + PrintAndLogEx(NORMAL, " Inverse data : %s", (inv) ? _GREEN_(Yes) : "No"); + PrintAndLogEx(NORMAL, " POR-Delay : %s", (por) ? _GREEN_(Yes) : "No"); + PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(NORMAL, " Raw Data - Page 0"); + PrintAndLogEx(NORMAL, " Block 0 : 0x%08X %s", block0, sprint_bin(DemodBuffer + config.offset, 32) ); + PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + return 0; +} + +int CmdT55xxDump(const char *Cmd){ + + uint32_t password = 0; + bool override = false; + char cmdp = tolower(param_getchar(Cmd, 0)); + if ( cmdp == 'h') return usage_t55xx_dump(); + + bool usepwd = ( strlen(Cmd) > 0); + if ( usepwd ){ + password = param_get32ex(Cmd, 0, 0, 16); + if (param_getchar(Cmd, 1) =='o' ) + override = true; + } + + printT5xxHeader(0); + for ( uint8_t i = 0; i < 8; ++i) + T55xxReadBlock(i, 0, usepwd, override, password); + + printT5xxHeader(1); + for ( uint8_t i = 0; i < 4; i++) + T55xxReadBlock(i, 1, usepwd, override, password); + + return 1; +} + +bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ) { + // arg0 bitmodes: + // bit0 = pwdmode + // bit1 = page to read from + // arg1: which block to read + // arg2: password + uint8_t arg0 = (page<<1) | pwdmode; + UsbCommand c = {CMD_T55XX_READ_BLOCK, {arg0, block, password}}; + clearCommandBuffer(); + SendCommand(&c); + if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500) ) { + PrintAndLogEx(WARNING, "command execution time out"); + return false; + } + + uint8_t got[8000]; + if ( !GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 4000, true)) { + PrintAndLogEx(WARNING, "command execution time out"); + return false; + } + setGraphBuf(got, sizeof(got)); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(got, sizeof(got)); + RepaintGraphWindow(); + return !getSignalProperties()->isnoise; +} + +char * GetBitRateStr(uint32_t id, bool xmode) { + static char buf[25]; + + char *retStr = buf; + if (xmode) { //xmode bitrate calc is same as em4x05 calc + snprintf(retStr,sizeof(buf),"%d - RF/%d", id, EM4x05_GET_BITRATE(id)); + } else { + switch (id){ + case 0: snprintf(retStr,sizeof(buf),"%d - RF/8",id); break; + case 1: snprintf(retStr,sizeof(buf),"%d - RF/16",id); break; + case 2: snprintf(retStr,sizeof(buf),"%d - RF/32",id); break; + case 3: snprintf(retStr,sizeof(buf),"%d - RF/40",id); break; + case 4: snprintf(retStr,sizeof(buf),"%d - RF/50",id); break; + case 5: snprintf(retStr,sizeof(buf),"%d - RF/64",id); break; + case 6: snprintf(retStr,sizeof(buf),"%d - RF/100",id); break; + case 7: snprintf(retStr,sizeof(buf),"%d - RF/128",id); break; + default: snprintf(retStr,sizeof(buf),"%d - (Unknown)",id); break; + } + } + return buf; +} + +char * GetSaferStr(uint32_t id){ + static char buf[40]; + char *retStr = buf; + + snprintf(retStr,sizeof(buf),"%d",id); + if (id == 6) { + snprintf(retStr,sizeof(buf),"%d - passwd",id); + } + if (id == 9 ){ + snprintf(retStr,sizeof(buf),"%d - testmode",id); + } + + return buf; +} + +char * GetModulationStr( uint32_t id){ + static char buf[60]; + char *retStr = buf; + + switch (id){ + case 0: snprintf(retStr,sizeof(buf),"%d - DIRECT (ASK/NRZ)",id); break; + case 1: snprintf(retStr,sizeof(buf),"%d - PSK 1 phase change when input changes",id); break; + case 2: snprintf(retStr,sizeof(buf),"%d - PSK 2 phase change on bitclk if input high",id); break; + case 3: snprintf(retStr,sizeof(buf),"%d - PSK 3 phase change on rising edge of input",id); break; + case 4: snprintf(retStr,sizeof(buf),"%d - FSK 1 RF/8 RF/5",id); break; + case 5: snprintf(retStr,sizeof(buf),"%d - FSK 2 RF/8 RF/10",id); break; + case 6: snprintf(retStr,sizeof(buf),"%d - FSK 1a RF/5 RF/8",id); break; + case 7: snprintf(retStr,sizeof(buf),"%d - FSK 2a RF/10 RF/8",id); break; + case 8: snprintf(retStr,sizeof(buf),"%d - Manchester",id); break; + case 16: snprintf(retStr,sizeof(buf),"%d - Biphase",id); break; + case 0x18:snprintf(retStr,sizeof(buf),"%d - Biphase a - AKA Conditional Dephase Encoding(CDP)",id); break; + case 17: snprintf(retStr,sizeof(buf),"%d - Reserved",id); break; + default: snprintf(retStr,sizeof(buf),"0x%02X (Unknown)",id); break; + } + return buf; +} + +char * GetModelStrFromCID(uint32_t cid){ + + static char buf[10]; + char *retStr = buf; + + if (cid == 1) snprintf(retStr, sizeof(buf),"ATA5577M1"); + if (cid == 2) snprintf(retStr, sizeof(buf),"ATA5577M2"); + return buf; +} + +char * GetSelectedModulationStr( uint8_t id){ + + static char buf[20]; + char *retStr = buf; + + switch (id){ + case DEMOD_FSK: snprintf(retStr,sizeof(buf),"FSK"); break; + case DEMOD_FSK1: snprintf(retStr,sizeof(buf),"FSK1"); break; + case DEMOD_FSK1a: snprintf(retStr,sizeof(buf),"FSK1a"); break; + case DEMOD_FSK2: snprintf(retStr,sizeof(buf),"FSK2"); break; + case DEMOD_FSK2a: snprintf(retStr,sizeof(buf),"FSK2a"); break; + case DEMOD_ASK: snprintf(retStr,sizeof(buf),"ASK"); break; + case DEMOD_NRZ: snprintf(retStr,sizeof(buf),"DIRECT/NRZ"); break; + case DEMOD_PSK1: snprintf(retStr,sizeof(buf),"PSK1"); break; + case DEMOD_PSK2: snprintf(retStr,sizeof(buf),"PSK2"); break; + case DEMOD_PSK3: snprintf(retStr,sizeof(buf),"PSK3"); break; + case DEMOD_BI: snprintf(retStr,sizeof(buf),"BIPHASE"); break; + case DEMOD_BIa: snprintf(retStr,sizeof(buf),"BIPHASEa - (CDP)"); break; + default: snprintf(retStr,sizeof(buf),"(Unknown)"); break; + } + return buf; +} + +void t55x7_create_config_block( int tagtype ){ + + /* + T55X7_DEFAULT_CONFIG_BLOCK, T55X7_RAW_CONFIG_BLOCK + T55X7_EM_UNIQUE_CONFIG_BLOCK, T55X7_FDXB_CONFIG_BLOCK, + T55X7_FDXB_CONFIG_BLOCK, T55X7_HID_26_CONFIG_BLOCK, T55X7_INDALA_64_CONFIG_BLOCK, T55X7_INDALA_224_CONFIG_BLOCK + T55X7_GUARDPROXII_CONFIG_BLOCK, T55X7_VIKING_CONFIG_BLOCK, T55X7_NORALYS_CONFIG_BLOCK, T55X7_IOPROX_CONFIG_BLOCK + */ + static char buf[60]; + char *retStr = buf; + + switch (tagtype){ + case 0: snprintf(retStr, sizeof(buf),"%08X - T55X7 Default", T55X7_DEFAULT_CONFIG_BLOCK); break; + case 1: snprintf(retStr, sizeof(buf),"%08X - T55X7 Raw", T55X7_RAW_CONFIG_BLOCK); break; + case 2: snprintf(retStr, sizeof(buf),"%08X - T5555 Q5 Default", T5555_DEFAULT_CONFIG_BLOCK); break; + default: + break; + } + PrintAndLogEx(NORMAL, buf); +} + +int CmdResetRead(const char *Cmd) { + UsbCommand c = {CMD_T55XX_RESET_READ, {0,0,0}}; + clearCommandBuffer(); + SendCommand(&c); + if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2500) ) { + PrintAndLogEx(WARNING, "command execution time out"); + return 0; + } + + uint8_t got[BIGBUF_SIZE-1]; + if ( !GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 2500, false)) { + PrintAndLogEx(WARNING, "command execution time out"); + return 0; + } + setGraphBuf(got, sizeof(got)); + return 1; +} + +int CmdT55xxWipe(const char *Cmd) { + char writeData[20] = {0}; + char *ptrData = writeData; + char cmdp = param_getchar(Cmd, 0); + if ( cmdp == 'h' || cmdp == 'H') return usage_t55xx_wipe(); + + bool Q5 = (cmdp == 'q' || cmdp == 'Q'); + + // Try with the default password to reset block 0 + // With a pwd should work even if pwd bit not set + PrintAndLogEx(INFO, "\nBeginning Wipe of a T55xx tag (assuming the tag is not password protected)\n"); + + if ( Q5 ) + snprintf(ptrData,sizeof(writeData),"b 0 d 6001F004 p 0"); + else + snprintf(ptrData,sizeof(writeData),"b 0 d 000880E0 p 0"); + + if (!CmdT55xxWriteBlock(ptrData)) PrintAndLogEx(WARNING, "Error writing blk 0"); + + for (uint8_t blk = 1; blk<8; blk++) { + + snprintf(ptrData,sizeof(writeData),"b %d d 0", blk); + + if (!CmdT55xxWriteBlock(ptrData)) PrintAndLogEx(WARNING, "Error writing blk %d", blk); + + memset(writeData, 0x00, sizeof(writeData)); + } + return 0; +} + +bool IsCancelled(void) { + if (ukbhit()) { + int gc = getchar(); (void)gc; + PrintAndLogEx(NORMAL, "\naborted via keyboard!\n"); + return true; + } + return false; +} + +int CmdT55xxChkPwds(const char *Cmd) { + // load a default pwd file. + char line[9]; + char filename[FILE_PATH_SIZE] = {0}; + int keycnt = 0; + uint8_t stKeyBlock = 20; + uint8_t *keyBlock = NULL, *p = NULL; + bool found = false; + uint8_t timeout = 0; + + memset(line, 0, sizeof(line)); + + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_t55xx_chk(); + + /* + if ( T55xxReadBlock(7, 0, 0, 0, 0) ) { + + // now try to validate it.. + PrintAndLogEx(WARNING, "\n Block 7 was readable"); + return 1; + } + */ + + uint64_t t1 = msclock(); + + if ( cmdp == 'm' ) { + UsbCommand c = {CMD_T55XX_CHKPWDS, {0,0,0} }; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + + while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + timeout++; + printf("."); fflush(stdout); + if (timeout > 180) { + PrintAndLogEx(WARNING, "\nno response from Proxmark. Aborting..."); + return 2; + } + } + + if ( resp.arg[0] ) { + PrintAndLogEx(SUCCESS, "\nFound a candidate [ %08X ]. Trying to validate", resp.arg[1]); + + if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, resp.arg[1])) { + PrintAndLogEx(INFO, "Aquireing data from device failed. Quitting"); + return 2; + } + + found = tryDetectModulation(); + if (found) { + PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", resp.arg[1]); + } else { + PrintAndLogEx(WARNING, "Password NOT found."); + } + } else { + PrintAndLogEx(WARNING, "Password NOT found."); + } + + goto out; + } + + keyBlock = calloc(stKeyBlock, 4); + if (keyBlock == NULL) return 1; + + if (cmdp == 'i') { + + int len = strlen(Cmd+2); + if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; + memcpy(filename, Cmd+2, len); + + FILE * f = fopen( filename , "r"); + if ( !f ) { + PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); + free(keyBlock); + return 1; + } + + while( fgets(line, sizeof(line), f) ){ + if (strlen(line) < 8 || line[7] == '\n') continue; + + //goto next line + while (fgetc(f) != '\n' && !feof(f)) ; + + //The line start with # is comment, skip + if( line[0]=='#' ) continue; + + if (!isxdigit(line[0])) { + PrintAndLogEx(WARNING, "File content error. '%s' must include 8 HEX symbols", line); + continue; + } + + line[8] = 0; + + // realloc keyblock array size. + if ( stKeyBlock - keycnt < 2) { + p = realloc(keyBlock, 4 * (stKeyBlock += 10)); + if (!p) { + PrintAndLogEx(WARNING, "Cannot allocate memory for defaultKeys"); + free(keyBlock); + if (f) + fclose(f); + return 2; + } + keyBlock = p; + } + // clear mem + memset(keyBlock + 4 * keycnt, 0, 4); + + num_to_bytes( strtoll(line, NULL, 16), 4, keyBlock + 4*keycnt); + +// PrintAndLogEx(NORMAL, "chk custom pwd[%2d] %08X", keycnt, bytes_to_num(keyBlock + 4 * keycnt, 4) ); + keycnt++; + memset(line, 0, sizeof(line)); + } + + if (f) + fclose(f); + + if (keycnt == 0) { + PrintAndLogEx(WARNING, "No keys found in file"); + free(keyBlock); + return 1; + } + PrintAndLogEx(SUCCESS, "Loaded %d keys", keycnt); + + // loop + uint64_t testpwd = 0x00; + for (uint16_t c = 0; c < keycnt; ++c ) { + + if ( IsOffline() ) { + PrintAndLogEx(WARNING, "Device offline\n"); + free(keyBlock); + return 2; + } + + if (IsCancelled()) { + free(keyBlock); + return 0; + } + + testpwd = bytes_to_num(keyBlock + 4*c, 4); + + PrintAndLogEx(INFO, "Testing %08X", testpwd); + + if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, testpwd)) { + PrintAndLogEx(INFO, "Aquireing data from device failed. Quitting"); + free(keyBlock); + return 0; + } + + found = tryDetectModulation(); + if ( found ) + break; + + } + if ( found ) + PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", testpwd); + else + PrintAndLogEx(WARNING, "Password NOT found."); + } + + free(keyBlock); + +out: + t1 = msclock() - t1; + PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1/1000.0); + return 0; +} + +int CmdT55xxBruteForce(const char *Cmd) { + + uint32_t start_password = 0x00000000; //start password + uint32_t end_password = 0xFFFFFFFF; //end password + uint32_t curr = 0; + bool found = false; + + + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_t55xx_bruteforce(); + + uint64_t t1 = msclock(); + + // Try to read Block 7, first :) + + // incremental pwd range search + start_password = param_get32ex(Cmd, 0, 0, 16); + end_password = param_get32ex(Cmd, 1, 0, 16); + + curr = start_password; + + if ( start_password >= end_password ) { + return usage_t55xx_bruteforce(); + } + + PrintAndLogEx(INFO, "Search password range [%08X -> %08X]", start_password, end_password); + + while ( !found ){ + + printf("."); fflush(stdout); + + if (IsCancelled()) { + return 0; + } + + if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, curr)) { + PrintAndLogEx(WARNING, "Aquiring data from device failed. Quitting"); + return 0; + } + + found = tryDetectModulation(); + + if (curr == end_password) + break; + curr++; + } + + PrintAndLogEx(NORMAL, ""); + + if (found) + PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", curr); + else + PrintAndLogEx(WARNING, "Password NOT found. Last tried: [ %08X ]", --curr); + + t1 = msclock() - t1; + PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1/1000.0); + return 0; +} + +int tryOnePassword(uint32_t password) { + PrintAndLogEx(INFO, "Trying password %08x", password); + if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, password)) { + PrintAndLogEx(NORMAL, "Acquire data from device failed. Quitting"); + return -1; + } + + if (tryDetectModulation()) + return 1; + else + return 0; +} + +int CmdT55xxRecoverPW(const char *Cmd) { + int bit = 0; + uint32_t orig_password = 0x0; + uint32_t curr_password = 0x0; + uint32_t prev_password = 0xffffffff; + uint32_t mask = 0x0; + int found = 0; + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h' ) return usage_t55xx_recoverpw(); + + orig_password = param_get32ex(Cmd, 0, 0x51243648, 16); //password used by handheld cloners + + // first try fliping each bit in the expected password + while (bit < 32) { + curr_password = orig_password ^ ( 1 << bit ); + found = tryOnePassword(curr_password); + if (found == -1) return 0; + bit++; + + if (IsCancelled()) return 0; + } + + // now try to use partial original password, since block 7 should have been completely + // erased during the write sequence and it is possible that only partial password has been + // written + // not sure from which end the bit bits are written, so try from both ends + // from low bit to high bit + bit = 0; + while (bit < 32) { + mask += ( 1 << bit ); + curr_password = orig_password & mask; + // if updated mask didn't change the password, don't try it again + if (prev_password == curr_password) { + bit++; + continue; + } + found = tryOnePassword(curr_password); + if (found == -1) return 0; + bit++; + prev_password = curr_password; + + if (IsCancelled()) return 0; + } + + // from high bit to low + bit = 0; + mask = 0xffffffff; + while (bit < 32) { + mask -= ( 1 << bit ); + curr_password = orig_password & mask; + // if updated mask didn't change the password, don't try it again + if (prev_password == curr_password) { + bit++; + continue; + } + found = tryOnePassword(curr_password); + if (found == -1) + return 0; + bit++; + prev_password = curr_password; + + if (IsCancelled()) return 0; + } + + PrintAndLogEx(NORMAL, ""); + + if (found == 1) + PrintAndLogEx(SUCCESS, "Found valid password: [%08x]", curr_password); + else + PrintAndLogEx(WARNING, "Password NOT found."); + + return 0; +} + +// note length of data returned is different for different chips. +// some return all page 1 (64 bits) and others return just that block (32 bits) +// unfortunately the 64 bits makes this more likely to get a false positive... +bool tryDetectP1(bool getData) { + uint8_t preamble[] = {1,1,1,0,0,0,0,0,0,0,0,1,0,1,0,1}; + size_t startIdx = 0; + uint8_t fc1 = 0, fc2 = 0, ans = 0; + int clk = 0, firstClockEdge = 0; + bool st = true; + + if ( getData ) { + if ( !AquireData(T55x7_PAGE1, 1, false, 0) ) + return false; + } + + // try fsk clock detect. if successful it cannot be any other type of modulation... (in theory...) + ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, &firstClockEdge); + if (ans && ((fc1==10 && fc2==8) || (fc1==8 && fc2==5))) { + if ( FSKrawDemod("0 0", false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + if ( FSKrawDemod("0 1", false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + return false; + } + + // try ask clock detect. it could be another type even if successful. + clk = GetAskClock("", false); + if (clk > 0) { + if ( ASKDemod_ext("0 0 1", false, false, 1, &st) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + st = true; + if ( ASKDemod_ext("0 1 1", false, false, 1, &st) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + if ( ASKbiphaseDemod("0 0 0 2", false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + if ( ASKbiphaseDemod("0 0 1 2", false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + } + + // try NRZ clock detect. it could be another type even if successful. + clk = GetNrzClock("", false); //has the most false positives :( + if (clk > 0) { + if ( NRZrawDemod("0 0 1", false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + if ( NRZrawDemod("0 1 1", false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + return true; + } + } + + // Fewer card uses PSK + // try psk clock detect. if successful it cannot be any other type of modulation... (in theory...) + clk = GetPskClock("", false); + if (clk > 0) { + // allow undo + // save_restoreGB(1); + // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) + //CmdLtrim("160"); + if ( PSKDemod("0 0 6", false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + //save_restoreGB(0); + return true; + } + if ( PSKDemod("0 1 6", false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + //save_restoreGB(0); + return true; + } + // PSK2 - needs a call to psk1TOpsk2. + if ( PSKDemod("0 0 6", false)) { + psk1TOpsk2(DemodBuffer, DemodBufferLen); + if (preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + (DemodBufferLen == 32 || DemodBufferLen == 64) ) { + //save_restoreGB(0); + return true; + } + } // inverse waves does not affect PSK2 demod + //undo trim samples + //save_restoreGB(0); + // no other modulation clocks = 2 or 4 so quit searching + if (fc1 != 8) return false; + } + + return false; +} +// does this need to be a callable command? +int CmdT55xxDetectPage1(const char *Cmd){ + bool errors = false; + bool useGB = false; + bool usepwd = false; + uint32_t password = 0; + uint8_t cmdp = 0; + + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_t55xx_detectP1(); + case 'p': + password = param_get32ex(Cmd, cmdp+1, 0, 16); + usepwd = true; + cmdp += 2; + break; + case '1': + // use Graphbuffer data + useGB = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + if (errors) return usage_t55xx_detectP1(); + + if ( !useGB ) { + if ( !AquireData(T55x7_PAGE1, 1, usepwd, password) ) + return false; + } + bool success = tryDetectP1(false); + if (success) PrintAndLogEx(SUCCESS, "T55xx chip found!"); + return success; +} + +int CmdT55xxSetDeviceConfig(const char *Cmd){ + uint8_t startgap = 0, writegap = 0; + uint8_t write0 = 0, write1 = 0, readgap = 0; + bool errors = false, shall_persist = false; + uint8_t cmdp = 0; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_lf_deviceconfig(); + case 'a': + errors |= param_getdec(Cmd, cmdp+1, &startgap); + cmdp += 2; + break; + case 'b': + errors |= param_getdec(Cmd, cmdp+1, &writegap); + cmdp += 2; + break; + case 'c': + errors |= param_getdec(Cmd, cmdp+1, &write0); + cmdp += 2; + break; + case 'd': + errors |= param_getdec(Cmd, cmdp+1, &write1); + cmdp += 2; + break; + case 'e': + errors |= param_getdec(Cmd, cmdp+1, &readgap); + cmdp += 2; + break; + case 'p': + shall_persist = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = 1; + break; + } + } + + //Validations + if (errors || cmdp == 0) return usage_lf_deviceconfig(); + + t55xx_config config = { startgap*8, writegap*8, write0*8, write1*8, readgap*8 }; + + UsbCommand c = {CMD_SET_LF_T55XX_CONFIG, {shall_persist,0,0} }; + memcpy(c.d.asBytes, &config, sizeof(t55xx_config)); + clearCommandBuffer(); + SendCommand(&c); + return 0; +} + +static command_t CommandTable[] = { + {"help", CmdHelp, 1, "This help"}, + {"bruteforce", CmdT55xxBruteForce,0, " [i <*.dic>] Simple bruteforce attack to find password"}, + {"config", CmdT55xxSetConfig, 1, "Set/Get T55XX configuration (modulation, inverted, offset, rate)"}, + {"chk", CmdT55xxChkPwds, 1, "Check passwords"}, + {"detect", CmdT55xxDetect, 1, "[1] Try detecting the tag modulation from reading the configuration block."}, + {"deviceconfig", CmdT55xxSetDeviceConfig, 1, "Set/Get T55XX device configuration (startgap, writegap, write0, write1, readgap"}, + {"p1detect", CmdT55xxDetectPage1,1, "[1] Try detecting if this is a t55xx tag by reading page 1"}, + {"dump", CmdT55xxDump, 0, "[password] [o] Dump T55xx card block 0-7. Optional [password], [override]"}, + {"info", CmdT55xxInfo, 1, "[1] Show T55x7 configuration data (page 0/ blk 0)"}, + {"read", CmdT55xxReadBlock, 0, "b p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]"}, + {"resetread", CmdResetRead, 0, "Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)"}, + {"recoverpw", CmdT55xxRecoverPW, 0, "[password] Try to recover from bad password write from a cloner. Only use on PW protected chips!"}, + {"special", special, 0, "Show block changes with 64 different offsets"}, + {"trace", CmdT55xxReadTrace, 1, "[1] Show T55x7 traceability data (page 1/ blk 0-1)"}, + {"wakeup", CmdT55xxWakeUp, 0, "Send AOR wakeup command"}, + {"wipe", CmdT55xxWipe, 0, "[q] Wipe a T55xx tag and set defaults (will destroy any data on tag)"}, + {"write", CmdT55xxWriteBlock,0, "b d p [password] [1] -- Write T55xx block data. Optional [p password], [page1]"}, + {NULL, NULL, 0, NULL} +}; + +int CmdLFT55XX(const char *Cmd) { + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; +} + +int CmdHelp(const char *Cmd) { + CmdsHelp(CommandTable); + return 0; +} diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index 46de0c359..775f7ccca 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -1,171 +1,171 @@ -//----------------------------------------------------------------------------- -// -// This code is licensed to you under the terms of the GNU GPL, version 2 or, -// at your option, any later version. See the LICENSE.txt file for the text of -// the license. -//----------------------------------------------------------------------------- -// Low frequency T55xx commands -//----------------------------------------------------------------------------- - -#ifndef CMDLFT55XX_H__ -#define CMDLFT55XX_H__ - -#include -#include -#include -#include -#include -#include "proxmark3.h" -#include "ui.h" -#include "graph.h" -#include "comms.h" -#include "cmdparser.h" -#include "cmddata.h" -#include "cmdlf.h" -#include "util.h" -#include "lfdemod.h" -#include "cmdhf14a.h" //for getTagInfo - - -#define T55x7_CONFIGURATION_BLOCK 0x00 -#define T55x7_PAGE0 0x00 -#define T55x7_PAGE1 0x01 -#define T55x7_PWD 0x00000010 -#define REGULAR_READ_MODE_BLOCK 0xFF - -// config blocks -#define T55X7_DEFAULT_CONFIG_BLOCK 0x000880E8 // ASK, compat mode, data rate 32, manchester, STT, 7 data blocks -#define T55X7_RAW_CONFIG_BLOCK 0x000880E0 // ASK, compat mode, data rate 32, manchester, 7 data blocks -#define T55X7_EM_UNIQUE_CONFIG_BLOCK 0x00148040 // ASK, 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_PYRAMID_CONFIG_BLOCK 0x00107080 // Pyramid 26 bit - compat mode, FSK2a, data rate 50, 4 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 // ASK, compat mode, data rate 32, Manchester, 2 data blocks -#define T55X7_NORALYS_CONFIG_BLOCK 0x00088C6A // ASK, compat mode, (NORALYS - KCP3000) -#define T55X7_IOPROX_CONFIG_BLOCK 0x00147040 // ioprox - FSK2a, data rate 64, 2 data blocks -#define T55X7_PRESCO_CONFIG_BLOCK 0x00088088 // ASK, data rate 32, Manchester, 5 data blocks, STT -#define T55X7_NEDAP_64_CONFIG_BLOCK 0x907f0042 // BiPhase, data rate 64, 3 data blocks -#define T55X7_NEDAP_128_CONFIG_BLOCK 0x907f0082 // BiPhase, data rate 64, 5 data blocks -#define T55X7_bin 0b0010 - -#define T5555_DEFAULT_CONFIG_BLOCK 0x6001F004 // data rate 64 , ask, manchester, 2 data blocks? -enum { - T55x7_RAW = 0x00, - T55x7_DEFAULT = 0x00, - T5555_DEFAULT = 0x01, - EM_UNIQUE = 0x0, - FDBX = 0x02, - HID_26 = 0x03, - INDALA_64 = 0x04, - INDALA_224 = 0x05, - GUARDPROXXII = 0x06, - VIKING = 0x07, - NORALSYS = 0x08, - IOPROX = 0x09, - NEDAP_64 = 0x0A, - NEDAP_128 = 0x0B, -} t55xx_tag; - -typedef struct { - uint32_t bl1; - uint32_t bl2; - uint32_t acl; - uint32_t mfc; - uint32_t cid; - uint32_t year; - uint32_t quarter; - uint32_t icr; - uint32_t lotid; - uint32_t wafer; - uint32_t dw; -} t55x7_tracedata_t; - -typedef struct { - uint32_t bl1; - uint32_t bl2; - uint32_t icr; - char lotidc; - uint32_t lotid; - uint32_t wafer; - uint32_t dw; -} t5555_tracedata_t; - -typedef struct { - enum { - DEMOD_NRZ = 0x00, - DEMOD_PSK1 = 0x01, - DEMOD_PSK2 = 0x02, - DEMOD_PSK3 = 0x03, - DEMOD_FSK1 = 0x04, - DEMOD_FSK1a = 0x05, - DEMOD_FSK2 = 0x06, - DEMOD_FSK2a = 0x07, - DEMOD_FSK = 0xF0, //generic FSK (auto detect FCs) - DEMOD_ASK = 0x08, - DEMOD_BI = 0x10, - DEMOD_BIa = 0x18, - } modulation; - bool inverted; - uint8_t offset; - uint32_t block0; - enum { - RF_8 = 0x00, - RF_16 = 0x01, - RF_32 = 0x02, - RF_40 = 0x03, - RF_50 = 0x04, - RF_64 = 0x05, - RF_100 = 0x06, - RF_128 = 0x07, - } bitrate; - bool Q5; - bool ST; -} t55xx_conf_block_t; - -t55xx_conf_block_t Get_t55xx_Config(void); -void Set_t55xx_Config(t55xx_conf_block_t conf); - -extern int CmdLFT55XX(const char *Cmd); -extern int CmdT55xxChk(const char *Cmd); -extern int CmdT55xxBruteForce(const char *Cmd); -extern int CmdT55xxSetConfig(const char *Cmd); -extern int CmdT55xxReadBlock(const char *Cmd); -extern int CmdT55xxWriteBlock(const char *Cmd); -extern int CmdT55xxReadTrace(const char *Cmd); -extern int CmdT55xxInfo(const char *Cmd); -extern int CmdT55xxDetect(const char *Cmd); -extern int CmdResetRead(const char *Cmd); -extern int CmdT55xxWipe(const char *Cmd); - -char * GetBitRateStr(uint32_t id, bool xmode); -char * GetSaferStr(uint32_t id); -char * GetModulationStr( uint32_t id); -char * GetModelStrFromCID(uint32_t cid); -char * GetSelectedModulationStr( uint8_t id); -uint32_t PackBits(uint8_t start, uint8_t len, uint8_t *bitstream); -void printT5xxHeader(uint8_t page); -void printT55xxBlock(const char *demodStr); -int printConfiguration( t55xx_conf_block_t b); - -bool DecodeT55xxBlock(void); -bool tryDetectModulation(void); -bool testKnownConfigBlock(uint32_t block0); -extern bool tryDetectP1(bool getData); -bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5); -int special(const char *Cmd); -bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ); -bool AquireDataEx( uint8_t page, uint8_t block, bool pwdmode, uint32_t password, uint32_t timing ) ; - -bool detectPassword(int password); - -void printT55x7Trace( t55x7_tracedata_t data, uint8_t repeat ); -void printT5555Trace( t5555_tracedata_t data, uint8_t repeat ); - -#endif +//----------------------------------------------------------------------------- +// +// This code is licensed to you under the terms of the GNU GPL, version 2 or, +// at your option, any later version. See the LICENSE.txt file for the text of +// the license. +//----------------------------------------------------------------------------- +// Low frequency T55xx commands +//----------------------------------------------------------------------------- + +#ifndef CMDLFT55XX_H__ +#define CMDLFT55XX_H__ + +#include +#include +#include +#include +#include +#include "proxmark3.h" +#include "ui.h" +#include "graph.h" +#include "comms.h" +#include "cmdparser.h" +#include "cmddata.h" +#include "cmdlf.h" +#include "util.h" +#include "lfdemod.h" +#include "cmdhf14a.h" //for getTagInfo + + +#define T55x7_CONFIGURATION_BLOCK 0x00 +#define T55x7_PAGE0 0x00 +#define T55x7_PAGE1 0x01 +#define T55x7_PWD 0x00000010 +#define REGULAR_READ_MODE_BLOCK 0xFF + +// config blocks +#define T55X7_DEFAULT_CONFIG_BLOCK 0x000880E8 // ASK, compat mode, data rate 32, manchester, STT, 7 data blocks +#define T55X7_RAW_CONFIG_BLOCK 0x000880E0 // ASK, compat mode, data rate 32, manchester, 7 data blocks +#define T55X7_EM_UNIQUE_CONFIG_BLOCK 0x00148040 // ASK, 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_PYRAMID_CONFIG_BLOCK 0x00107080 // Pyramid 26 bit - compat mode, FSK2a, data rate 50, 4 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 // ASK, compat mode, data rate 32, Manchester, 2 data blocks +#define T55X7_NORALYS_CONFIG_BLOCK 0x00088C6A // ASK, compat mode, (NORALYS - KCP3000) +#define T55X7_IOPROX_CONFIG_BLOCK 0x00147040 // ioprox - FSK2a, data rate 64, 2 data blocks +#define T55X7_PRESCO_CONFIG_BLOCK 0x00088088 // ASK, data rate 32, Manchester, 5 data blocks, STT +#define T55X7_NEDAP_64_CONFIG_BLOCK 0x907f0042 // BiPhase, data rate 64, 3 data blocks +#define T55X7_NEDAP_128_CONFIG_BLOCK 0x907f0082 // BiPhase, data rate 64, 5 data blocks +#define T55X7_bin 0b0010 + +#define T5555_DEFAULT_CONFIG_BLOCK 0x6001F004 // data rate 64 , ask, manchester, 2 data blocks? +enum { + T55x7_RAW = 0x00, + T55x7_DEFAULT = 0x00, + T5555_DEFAULT = 0x01, + EM_UNIQUE = 0x0, + FDBX = 0x02, + HID_26 = 0x03, + INDALA_64 = 0x04, + INDALA_224 = 0x05, + GUARDPROXXII = 0x06, + VIKING = 0x07, + NORALSYS = 0x08, + IOPROX = 0x09, + NEDAP_64 = 0x0A, + NEDAP_128 = 0x0B, +} t55xx_tag; + +typedef struct { + uint32_t bl1; + uint32_t bl2; + uint32_t acl; + uint32_t mfc; + uint32_t cid; + uint32_t year; + uint32_t quarter; + uint32_t icr; + uint32_t lotid; + uint32_t wafer; + uint32_t dw; +} t55x7_tracedata_t; + +typedef struct { + uint32_t bl1; + uint32_t bl2; + uint32_t icr; + char lotidc; + uint32_t lotid; + uint32_t wafer; + uint32_t dw; +} t5555_tracedata_t; + +typedef struct { + enum { + DEMOD_NRZ = 0x00, + DEMOD_PSK1 = 0x01, + DEMOD_PSK2 = 0x02, + DEMOD_PSK3 = 0x03, + DEMOD_FSK1 = 0x04, + DEMOD_FSK1a = 0x05, + DEMOD_FSK2 = 0x06, + DEMOD_FSK2a = 0x07, + DEMOD_FSK = 0xF0, //generic FSK (auto detect FCs) + DEMOD_ASK = 0x08, + DEMOD_BI = 0x10, + DEMOD_BIa = 0x18, + } modulation; + bool inverted; + uint8_t offset; + uint32_t block0; + enum { + RF_8 = 0x00, + RF_16 = 0x01, + RF_32 = 0x02, + RF_40 = 0x03, + RF_50 = 0x04, + RF_64 = 0x05, + RF_100 = 0x06, + RF_128 = 0x07, + } bitrate; + bool Q5; + bool ST; +} t55xx_conf_block_t; + +t55xx_conf_block_t Get_t55xx_Config(void); +void Set_t55xx_Config(t55xx_conf_block_t conf); + +extern int CmdLFT55XX(const char *Cmd); +extern int CmdT55xxChk(const char *Cmd); +extern int CmdT55xxBruteForce(const char *Cmd); +extern int CmdT55xxSetConfig(const char *Cmd); +extern int CmdT55xxReadBlock(const char *Cmd); +extern int CmdT55xxWriteBlock(const char *Cmd); +extern int CmdT55xxReadTrace(const char *Cmd); +extern int CmdT55xxInfo(const char *Cmd); +extern int CmdT55xxDetect(const char *Cmd); +extern int CmdResetRead(const char *Cmd); +extern int CmdT55xxWipe(const char *Cmd); + +char * GetBitRateStr(uint32_t id, bool xmode); +char * GetSaferStr(uint32_t id); +char * GetModulationStr( uint32_t id); +char * GetModelStrFromCID(uint32_t cid); +char * GetSelectedModulationStr( uint8_t id); +uint32_t PackBits(uint8_t start, uint8_t len, uint8_t *bitstream); +void printT5xxHeader(uint8_t page); +void printT55xxBlock(const char *demodStr); +int printConfiguration( t55xx_conf_block_t b); + +bool DecodeT55xxBlock(void); +bool tryDetectModulation(void); +bool testKnownConfigBlock(uint32_t block0); +extern bool tryDetectP1(bool getData); +bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5); +int special(const char *Cmd); +bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ); +bool AquireDataEx( uint8_t page, uint8_t block, bool pwdmode, uint32_t password, uint32_t timing ) ; + +bool detectPassword(int password); + +void printT55x7Trace( t55x7_tracedata_t data, uint8_t repeat ); +void printT5555Trace( t5555_tracedata_t data, uint8_t repeat ); + +#endif diff --git a/common/cmd.c b/common/cmd.c index dec095750..bed968c2c 100644 --- a/common/cmd.c +++ b/common/cmd.c @@ -1,64 +1,64 @@ -/* - * Proxmark send and receive commands - * - * Copyright (c) 2012, Roel Verdult - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * @file cmd.c - * @brief - */ -#include "cmd.h" - -uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void* data, size_t len) { - UsbCommand txcmd; - - for (size_t i=0; i < sizeof(UsbCommand); i++) - ((uint8_t*)&txcmd)[i] = 0x00; - - // Compose the outgoing command frame - txcmd.cmd = cmd; - txcmd.arg[0] = arg0; - txcmd.arg[1] = arg1; - txcmd.arg[2] = arg2; - - // Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE - if (data && len) { - len = MIN(len, USB_CMD_DATA_SIZE); - for (size_t i=0; iUDP_CSR[(endpoint)]; \ - reg |= REG_NO_EFFECT_1_ALL; \ - reg &= ~(flags); \ - pUdp->UDP_CSR[(endpoint)] = reg; \ -} \ - -// reset flags in the UDP_CSR register and waits for synchronization -#define UDP_SET_EP_FLAGS(endpoint, flags) { \ - volatile unsigned int reg; \ - reg = pUdp->UDP_CSR[(endpoint)]; \ - reg |= REG_NO_EFFECT_1_ALL; \ - reg |= (flags); \ - pUdp->UDP_CSR[(endpoint)] = reg; \ -} \ - - -typedef struct { - uint32_t BitRate; - uint8_t Format; - uint8_t ParityType; - uint8_t DataBits; -} AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING; - -AT91S_CDC_LINE_CODING line = { - 115200, // baudrate - 0, // 1 Stop Bit - 0, // None Parity - 8}; // 8 Data bits - -static void SpinDelay(int ms) { - int us = ms * 1000; - int ticks = (48 * us) >> 10; - - // Borrow a PWM unit for my real-time clock - AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0); - - // 48 MHz / 1024 gives 46.875 kHz - AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); - AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; - AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; - - uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; - - for(;;) { - uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; - if (now == (uint16_t)(start + ticks)) - return; - - WDT_HIT(); - } -} - -//*---------------------------------------------------------------------------- -//* \fn usb_disable -//* \brief This function deactivates the USB device -//*---------------------------------------------------------------------------- -void usb_disable() { - // Disconnect the USB device - AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU; - - // Clear all lingering interrupts - if (pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES) { - pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES; - } -} - -//*---------------------------------------------------------------------------- -//* \fn usb_enable -//* \brief This function Activates the USB device -//*---------------------------------------------------------------------------- -void usb_enable() { - // Set the PLL USB Divider - AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ; - - // Specific Chip USB Initialisation - // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock - AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_UDP; - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP); - - AT91C_BASE_UDP->UDP_FADDR = 0; - AT91C_BASE_UDP->UDP_GLBSTATE = 0; - - // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO - // Set in PIO mode and Configure in Output - AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode - AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output - - // Clear for set the Pullup resistor - AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU; - - // Disconnect and reconnect USB controller for 100ms - usb_disable(); - - SpinDelay(100); - // Wait for a short while - //for (volatile size_t i=0; i<0x100000; i++) {}; - - // Reconnect USB reconnect - AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU; - AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; -} - -//*---------------------------------------------------------------------------- -//* \fn usb_check -//* \brief Test if the device is configured and handle enumeration -//*---------------------------------------------------------------------------- -static int usb_reconnect = 0; -static int usb_configured = 0; -void SetUSBreconnect(int value) { - usb_reconnect = value; -} -int GetUSBreconnect(void) { - return usb_reconnect; -} -void SetUSBconfigured(int value) { - usb_configured = value; -} -int GetUSBconfigured(void){ - return usb_configured; -} - -bool usb_check() { - - /* - // reconnected ONCE and - if ( !USB_ATTACHED() ){ - usb_reconnect = 1; - return false; - } - - // only one time after USB been disengaged and re-engaged - if ( USB_ATTACHED() && usb_reconnect == 1 ) { - - if ( usb_configured == 0) { - usb_disable(); - usb_enable(); - - AT91F_CDC_Enumerate(); - - usb_configured = 1; - return false; - } - } - */ - - // interrupt status register - AT91_REG isr = pUdp->UDP_ISR; - - // end of bus reset - if (isr & AT91C_UDP_ENDBUSRES) { - pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES; - // reset all endpoints - pUdp->UDP_RSTEP = (unsigned int)-1; - pUdp->UDP_RSTEP = 0; - // Enable the function - pUdp->UDP_FADDR = AT91C_UDP_FEN; - // Configure endpoint 0 (enable control endpoint) - pUdp->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL); - } - else if (isr & AT91C_UDP_EPINT0) { - pUdp->UDP_ICR = AT91C_UDP_EPINT0; - AT91F_CDC_Enumerate(); - } - /* - else if (isr & AT91C_UDP_EPINT3 ) { - pUdp->UDP_ICR = AT91C_UDP_EPINT3; - AT91F_CDC_Enumerate(); - //pUdp->UDP_ICR |= AT91C_UDP_EPINT3; - } - */ - return (btConfiguration) ? true : false; -} - -bool usb_poll() { - if (!usb_check()) return false; - return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank); -} - -/** - In github PR #129, some users appears to get a false positive from - usb_poll, which returns true, but the usb_read operation - still returns 0. - This check is basically the same as above, but also checks - that the length available to read is non-zero, thus hopefully fixes the - bug. -**/ -bool usb_poll_validate_length() { - if (!usb_check()) return false; - if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false; - return ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) > 0; -} - -//*---------------------------------------------------------------------------- -//* \fn usb_read -//* \brief Read available data from Endpoint 1 OUT (host to device) -//*---------------------------------------------------------------------------- -uint32_t usb_read(byte_t* data, size_t len) { - - if ( len == 0 ) return 0; - - uint8_t bank = btReceiveBank; - uint32_t packetSize, nbBytesRcv = 0; - uint32_t time_out = 0; - - while (len) { - if (!usb_check()) break; - - if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) { - - packetSize = (pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16; - packetSize = MIN( packetSize, len); - len -= packetSize; - while (packetSize--) - data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT]; - - // flip bank - UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank) - - if (bank == AT91C_UDP_RX_DATA_BK0) - bank = AT91C_UDP_RX_DATA_BK1; - else - bank = AT91C_UDP_RX_DATA_BK0; - } - if (time_out++ == 0x1fff) break; - } - - btReceiveBank = bank; - return nbBytesRcv; -} - -//*---------------------------------------------------------------------------- -//* \fn usb_write -//* \brief Send through endpoint 2 (device to host) -//*---------------------------------------------------------------------------- -uint32_t usb_write(const byte_t* data, const size_t len) { - - if (!len) return 0; - if (!usb_check()) return 0; - - // can we write? - if ( (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) != 0 ) return 0; - - size_t length = len; - uint32_t cpt = 0; - - - // send first chunk - cpt = MIN(length, AT91C_EP_IN_SIZE); - length -= cpt; - while (cpt--) { - pUdp->UDP_FDR[AT91C_EP_IN] = *data++; - } - - UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); - - while (length) { - // Send next chunk - cpt = MIN(length, AT91C_EP_IN_SIZE); - length -= cpt; - while (cpt--) { - pUdp->UDP_FDR[AT91C_EP_IN] = *data++; - } - - // Wait for previous chunk to be sent - // (iceman) when is the bankswapping done? - while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { - if (!usb_check()) return length; - } - - UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); - while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP); - UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); - - } - - // Wait for the end of transfer - while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { - if (!usb_check()) return length; - } - - UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); - while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP); - - return length; -} - -//*---------------------------------------------------------------------------- -//* \fn AT91F_USB_SendData -//* \brief Send Data through the control endpoint -//*---------------------------------------------------------------------------- -void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) { - uint32_t cpt = 0; - AT91_REG csr; - - do { - cpt = MIN(length, AT91C_EP_CONTROL_SIZE); - length -= cpt; - - while (cpt--) - pUdp->UDP_FDR[AT91C_EP_CONTROL] = *pData++; - - if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) { - UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP); - while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP); - } - - UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY); - - do { - csr = pUdp->UDP_CSR[AT91C_EP_CONTROL]; - // Data IN stage has been stopped by a status OUT - if ( csr & AT91C_UDP_RX_DATA_BK0) { - - UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0) - return; - } - } while ( !(csr & AT91C_UDP_TXCOMP) ); - - } while (length); - - if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) { - UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP); - while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP); - } -} - - -//*---------------------------------------------------------------------------- -//* \fn AT91F_USB_SendZlp -//* \brief Send zero length packet through the control endpoint -//*---------------------------------------------------------------------------- -void AT91F_USB_SendZlp(AT91PS_UDP pUdp) { - UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY); - while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) ); - UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP); - while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP); -} - -//*---------------------------------------------------------------------------- -//* \fn AT91F_USB_SendStall -//* \brief Stall the control endpoint -//*---------------------------------------------------------------------------- -void AT91F_USB_SendStall(AT91PS_UDP pUdp) { - UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL); - while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_ISOERROR) ); - UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR) ); - while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR)); -} - -//*---------------------------------------------------------------------------- -//* \fn AT91F_CDC_Enumerate -//* \brief This function is a callback invoked when a SETUP packet is received -//* problem: -//* 1. this is for USB endpoint0. the control endpoint. -//* 2. mixed with CDC ACM endpoint3 , interrupt, control endpoint -//*---------------------------------------------------------------------------- -void AT91F_CDC_Enumerate() { - byte_t bmRequestType, bRequest; - uint16_t wValue, wIndex, wLength, wStatus; - - if ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) ) - return; - - bmRequestType = pUdp->UDP_FDR[AT91C_EP_CONTROL]; - bRequest = pUdp->UDP_FDR[AT91C_EP_CONTROL]; - wValue = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF); - wValue |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8); - wIndex = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF); - wIndex |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8); - wLength = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF); - wLength |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8); - - if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host - UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR); - while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR) ); - } - UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RXSETUP); - while ( (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) ); - - /* - if ( bRequest == MS_VENDOR_CODE) { - if ( bmRequestType == MS_WCID_GET_DESCRIPTOR ) { // C0 - if ( wIndex == MS_EXTENDED_COMPAT_ID ) { // 4 - //AT91F_USB_SendData(pUdp, CompatIDFeatureDescriptor, MIN(sizeof(CompatIDFeatureDescriptor), wLength)); - //return; - } - } - - if ( bmRequestType == MS_WCID_GET_FEATURE_DESCRIPTOR ) { //C1 - // if ( wIndex == MS_EXTENDED_PROPERTIES ) { // 5 - winusb bug with wIndex == interface index, so I just send it always) - //AT91F_USB_SendData(pUdp, OSprop, MIN(sizeof(OSprop), wLength)); - //return; - // } - } - } - */ - - // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1 - switch ((bRequest << 8) | bmRequestType) { - case STD_GET_DESCRIPTOR: { - - if ( wValue == 0x100 ) // Return Device Descriptor - AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength)); - else if ( wValue == 0x200 ) // Return Configuration Descriptor - AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength)); - else if ( (wValue & 0xF00) == 0xF00) // Return BOS Descriptor - AT91F_USB_SendData(pUdp, bosDescriptor, MIN(sizeof(bosDescriptor), wLength)); - else if ( (wValue & 0x300) == 0x300) { // Return String Descriptor - - const char *strDescriptor = getStringDescriptor(wValue & 0xff); - if (strDescriptor != NULL) { - AT91F_USB_SendData(pUdp, strDescriptor, MIN(strDescriptor[0], wLength)); - } else { - AT91F_USB_SendStall(pUdp); - } - } else { - AT91F_USB_SendStall(pUdp); - } - } - break; - case STD_SET_ADDRESS: - AT91F_USB_SendZlp(pUdp); - pUdp->UDP_FADDR = (AT91C_UDP_FEN | (wValue & 0x7F) ); - pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0; - break; - case STD_SET_CONFIGURATION: - - /* - * Set or clear the device "configured" state. - * The LSB of wValue is the "Configuration Number". If this value is non-zero, - * it should be the same number as defined in the Configuration Descriptor; - * otherwise an error must have occurred. - * This device has only one configuration and its Config Number is CONF_NB (= 1). - */ - AT91F_USB_SendZlp(pUdp); - btConfiguration = wValue; - pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN; - - // make sure we are not stalled - /* - UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT , AT91C_UDP_FORCESTALL); - UDP_CLEAR_EP_FLAGS(AT91C_EP_IN , AT91C_UDP_FORCESTALL); - UDP_CLEAR_EP_FLAGS(AT91C_EP_NOTIFY, AT91C_UDP_FORCESTALL); - */ - - // enable endpoints - pUdp->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0; - pUdp->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0; - pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0; - break; - case STD_GET_CONFIGURATION: - AT91F_USB_SendData(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration)); - break; - case STD_GET_STATUS_ZERO: - wStatus = 0; // Device is Bus powered, remote wakeup disabled - AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); - break; - case STD_GET_STATUS_INTERFACE: - wStatus = 0; // reserved for future use - AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); - break; - case STD_GET_STATUS_ENDPOINT: - wStatus = 0; - wIndex &= 0x0F; - if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) { - wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1; - AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); - } - else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) { - wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1; - AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); - } else { - AT91F_USB_SendStall(pUdp); - } - break; - case STD_SET_FEATURE_ZERO: - AT91F_USB_SendStall(pUdp); - break; - case STD_SET_FEATURE_INTERFACE: - AT91F_USB_SendZlp(pUdp); - break; - case STD_SET_FEATURE_ENDPOINT: - wIndex &= 0x0F; - if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) { - pUdp->UDP_CSR[wIndex] = 0; - AT91F_USB_SendZlp(pUdp); - } else { - AT91F_USB_SendStall(pUdp); - } - break; - case STD_CLEAR_FEATURE_ZERO: - AT91F_USB_SendStall(pUdp); - break; - case STD_CLEAR_FEATURE_INTERFACE: - AT91F_USB_SendZlp(pUdp); - break; - case STD_CLEAR_FEATURE_ENDPOINT: - wIndex &= 0x0F; - if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) { - - if (wIndex == AT91C_EP_OUT) pUdp->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT); - else if (wIndex == AT91C_EP_IN) pUdp->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN); - else if (wIndex == AT91C_EP_NOTIFY) pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN); - - AT91F_USB_SendZlp(pUdp); - } else { - AT91F_USB_SendStall(pUdp); - } - break; - - // handle CDC class requests - case SET_LINE_CODING: { - /* - uint8_t i; - for ( i = 0 ; i < 7 ; i++ ) { - ((uint8_t*)&line)[i] = pUdp->UDP_FDR[AT91C_EP_CONTROL]; - } */ - // ignore SET_LINE_CODING... - while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RX_DATA_BK0) ); - UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0); - AT91F_USB_SendZlp(pUdp); - break; - } - case GET_LINE_CODING: - AT91F_USB_SendData(pUdp, (char *) &line, MIN(sizeof(line), wLength)); - break; - case SET_CONTROL_LINE_STATE: - btConnection = wValue; - AT91F_USB_SendZlp(pUdp); - break; - default: - AT91F_USB_SendStall(pUdp); - break; - } +/* + * at91sam7s USB CDC device implementation + * + * Copyright (c) 2012, Roel Verdult + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * based on the "Basic USB Example" from ATMEL (doc6123.pdf) + * + * @file usb_cdc.c + * @brief + */ + +#include "usb_cdc.h" +/* +AT91SAM7S256 USB Device Port +• Embedded 328-byte dual-port RAM for endpoints +• Four endpoints +– Endpoint 0: 8 bytes +– Endpoint 1 and 2: 64 bytes ping-pong +– Endpoint 3: 64 bytes +– Ping-pong Mode (two memory banks) for bulk endpoints +*/ + +// +#define AT91C_EP_CONTROL 0 +#define AT91C_EP_OUT 1 // cfg bulk out +#define AT91C_EP_IN 2 // cfg bulk in +#define AT91C_EP_NOTIFY 3 // cfg cdc notification interrup + +#define AT91C_EP_CONTROL_SIZE 8 +#define AT91C_EP_OUT_SIZE 64 +#define AT91C_EP_IN_SIZE 64 + + +// Section: USB Descriptors +#define USB_DESCRIPTOR_DEVICE 0x01 // DescriptorType for a Device Descriptor. +#define USB_DESCRIPTOR_CONFIGURATION 0x02 // DescriptorType for a Configuration Descriptor. +#define USB_DESCRIPTOR_STRING 0x03 // DescriptorType for a String Descriptor. +#define USB_DESCRIPTOR_INTERFACE 0x04 // DescriptorType for an Interface Descriptor. +#define USB_DESCRIPTOR_ENDPOINT 0x05 // DescriptorType for an Endpoint Descriptor. +#define USB_DESCRIPTOR_DEVICE_QUALIFIER 0x06 // DescriptorType for a Device Qualifier. +#define USB_DESCRIPTOR_OTHER_SPEED 0x07 // DescriptorType for a Other Speed Configuration. +#define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // DescriptorType for Interface Power. +#define USB_DESCRIPTOR_OTG 0x09 // DescriptorType for an OTG Descriptor. +#define USB_DESCRIPTOR_IAD 0x0B // DescriptorType for a Interface Association Descriptor +#define USB_DESCRIPTOR_TYPE_BO 0x0F // DescriptorType for a BOS Descriptor. + +/* Configuration Attributes */ +#define _DEFAULT (0x01<<7) //Default Value (Bit 7 is set) +#define _SELF (0x01<<6) //Self-powered (Supports if set) +#define _RWU (0x01<<5) //Remote Wakeup (Supports if set) +#define _HNP (0x01 << 1) //HNP (Supports if set) +#define _SRP (0x01) //SRP (Supports if set) + +/* Endpoint Transfer Type */ +#define _CTRL 0x00 //Control Transfer +#define _ISO 0x01 //Isochronous Transfer +#define _BULK 0x02 //Bulk Transfer +#define _INTERRUPT 0x03 //Interrupt Transfer + +// (bit7 | 0 = OUT, 1 = IN) +#define _EP_IN 0x80 +#define _EP_OUT 0x00 +#define _EP01_OUT 0x01 +#define _EP01_IN 0x81 +#define _EP02_OUT 0x02 +#define _EP02_IN 0x82 +#define _EP03_OUT 0x03 +#define _EP03_IN 0x83 + + +/* WCID specific Request Code */ +#define MS_OS_DESCRIPTOR_INDEX 0xEE +#define MS_VENDOR_CODE 0x1C +#define MS_EXTENDED_COMPAT_ID 0x04 +#define MS_EXTENDED_PROPERTIES 0x05 +#define MS_WCID_GET_DESCRIPTOR 0xC0 +#define MS_WCID_GET_FEATURE_DESCRIPTOR 0xC1 + +/* USB standard request code */ +#define STD_GET_STATUS_ZERO 0x0080 +#define STD_GET_STATUS_INTERFACE 0x0081 +#define STD_GET_STATUS_ENDPOINT 0x0082 + +#define STD_CLEAR_FEATURE_ZERO 0x0100 +#define STD_CLEAR_FEATURE_INTERFACE 0x0101 +#define STD_CLEAR_FEATURE_ENDPOINT 0x0102 + +#define STD_SET_FEATURE_ZERO 0x0300 +#define STD_SET_FEATURE_INTERFACE 0x0301 +#define STD_SET_FEATURE_ENDPOINT 0x0302 + +#define STD_SET_ADDRESS 0x0500 +#define STD_GET_DESCRIPTOR 0x0680 +#define STD_SET_DESCRIPTOR 0x0700 +#define STD_GET_CONFIGURATION 0x0880 +#define STD_SET_CONFIGURATION 0x0900 +#define STD_GET_INTERFACE 0x0A81 +#define STD_SET_INTERFACE 0x0B01 +#define STD_SYNCH_FRAME 0x0C82 + +/* CDC Class Specific Request Code */ +#define GET_LINE_CODING 0x21A1 +#define SET_LINE_CODING 0x2021 +#define SET_CONTROL_LINE_STATE 0x2221 + +AT91PS_UDP pUdp = AT91C_BASE_UDP; +uint8_t btConfiguration = 0; +uint8_t btConnection = 0; +uint8_t btReceiveBank = AT91C_UDP_RX_DATA_BK0; + +static const char devDescriptor[] = { + /* Device descriptor */ + 0x12, // Length + USB_DESCRIPTOR_DEVICE, // Descriptor Type (DEVICE) + 0x00,0x02, // Complies with USB Spec. Release (0200h = release 2.00) 0210 == release 2.10 + 2, // Device Class: Communication Device Class + 0, // Device Subclass: CDC class sub code ACM [ice 0x02 = win10 virtual comport ] + 0, // Device Protocol: CDC Device protocol (unused) + AT91C_EP_CONTROL_SIZE, // MaxPacketSize0 + 0xc4,0x9a, // Vendor ID [0x9ac4 = J. Westhues] + 0x8f,0x4b, // Product ID [0x4b8f = Proxmark-3 RFID Instrument] + 0x00,0x01, // BCD Device release number (1.00) + 1, // index Manufacturer + 2, // index Product + 3, // index SerialNumber + 1 // Number of Configs +}; + +static const char cfgDescriptor[] = { + + /* Configuration 1 descriptor */ + // ----------------------------- + 9, // Length + USB_DESCRIPTOR_CONFIGURATION, // Descriptor Type + (9+9+5+5+4+5+7+9+7+7), 0, // Total Length 2 EP + Control + 2, // Number of Interfaces + 1, // Index value of this Configuration (used in SetConfiguration from Host) + 0, // Configuration string index + _DEFAULT, // Attributes 0xA0 + 0xFA, // Max Power consumption + + // IAD to associate the one CDC interface + // -------------------------------------- +/* + 8, // Length + USB_DESCRIPTOR_IAD, // IAD_DESCRIPTOR (0x0B) + 0, // CDC_INT_INTERFACE NUMBER ( + 2, // IAD INTERFACE COUNT (two interfaces) + 2, // Function Class: CDC_CLASS + 2, // Function SubClass: ACM + 1, // Function Protocol: v.25term + 0, // iInterface +*/ + + /* Interface 0 Descriptor */ + /* CDC Communication Class Interface Descriptor Requirement for Notification*/ + // ----------------------------------------------------------- + 9, // Length + USB_DESCRIPTOR_INTERFACE, // Descriptor Type + 0, // Interface Number + 0, // Alternate Setting + 1, // Number of Endpoints in this interface + 2, // Interface Class code (Communication Interface Class) + 2, // Interface Subclass code (Abstract Control Model) + 1, // InterfaceProtocol (Common AT Commands, V.25term) + 0, // iInterface + + /* Header Functional Descriptor */ + 5, // Function Length + 0x24, // Descriptor type: CS_INTERFACE + 0, // Descriptor subtype: Header Functional Descriptor + 0x10,0x01, // bcd CDC:1.1 + + /* ACM Functional Descriptor */ + 4, // Function Length + 0x24, // Descriptor Type: CS_INTERFACE + 2, // Descriptor Subtype: Abstract Control Management Functional Descriptor + 2, // Capabilities D1, Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State + + /* Union Functional Descriptor */ + 5, // Function Length + 0x24, // Descriptor Type: CS_INTERFACE + 6, // Descriptor Subtype: Union Functional Descriptor + 0, // MasterInterface: Communication Class Interface + 1, // SlaveInterface0: Data Class Interface + + /* Call Management Functional Descriptor */ + 5, // Function Length + 0x24, // Descriptor Type: CS_INTERFACE + 1, // Descriptor Subtype: Call Management Functional Descriptor + 0, // Capabilities: Device sends/receives call management information only over the Communication Class interface. Device does not handle call management itself + 1, // Data Interface: Data Class Interface + + /* Protocol Functional Descriptor */ + /* + 6, + 0x24, // Descriptor Type: CS_INTERFACE + 0x0B, // Descriptor Subtype: Protocol Unit functional Descriptor + 0xDD, // constant uniq ID of unit + 0xFE, // protocol + */ + + /* CDC Notification Endpoint descriptor */ + // --------------------------------------- + 7, // Length + USB_DESCRIPTOR_ENDPOINT, // Descriptor Type + _EP03_IN, // EndpointAddress: Endpoint 03 - IN + _INTERRUPT, // Attributes + AT91C_EP_CONTROL_SIZE, 0x00, // MaxPacket Size: EP0 - 8 + 0xFF, // Interval polling + + + /* Interface 1 Descriptor */ + /* CDC Data Class Interface 1 Descriptor Requirement */ + 9, // Length + USB_DESCRIPTOR_INTERFACE, // Descriptor Type + 1, // Interface Number + 0, // Alternate Setting + 2, // Number of Endpoints + 0x0A, // Interface Class: CDC Data interface class + 0, // Interface Subclass: not used + 0, // Interface Protocol: No class specific protocol required (usb spec) + 0, // Interface + + /* Endpoint descriptor */ + 7, // Length + USB_DESCRIPTOR_ENDPOINT, // Descriptor Type + _EP01_OUT, // Endpoint Address: Endpoint 01 - OUT + _BULK, // Attributes: BULK + AT91C_EP_OUT_SIZE, 0x00, // MaxPacket Size: 64 bytes + 0, // Interval: ignored for bulk + + /* Endpoint descriptor */ + 7, // Length + USB_DESCRIPTOR_ENDPOINT, // Descriptor Type + _EP02_IN, // Endpoint Address: Endpoint 02 - IN + _BULK, // Attribute: BULK + AT91C_EP_IN_SIZE, 0x00, // MaxPacket Size: 64 bytes + 0 // Interval: ignored for bulk +}; + +// BOS descriptor +static const char bosDescriptor[] = { + 0x5, + USB_DESCRIPTOR_TYPE_BO, + 0xC, + 0x0, + 0x1, // 1 device capability + 0x7, + 0x10, //USB_DEVICE_CAPABITY_TYPE, + 0x2, + 0x2, // LPM capability bit set + 0x0, + 0x0, + 0x0 +}; + +// Microsoft OS Extended Configuration Compatible ID Descriptor +/* +static const char CompatIDFeatureDescriptor[] = { + 0x28, 0x00, 0x00, 0x00, // Descriptor Length 40bytes (0x28) + 0x00, 0x01, // Version ('1.0') + MS_EXTENDED_COMPAT_ID, 0x00, // Compatibility ID Descriptor Index 0x0004 + 0x01, // Number of sections. 0x1 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved (7bytes) + //-----function section 1------ + 0x00, // Interface Number #0 + 0x01, // reserved (0x1) + 0x57, 0x49, 0x4E, 0x55, 0x53, 0x42, 0x00, 0x00, // Compatible ID ('WINUSB\0\0') (8bytes) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sub-Compatible ID (8byte) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Reserved (6bytes) +}; +*/ + +// Microsoft Extended Properties Feature Descriptor +/* +static const char OSprop[] = { + // u32 Descriptor Length (10+132+64+102 == 308 + 0x34, 0x01, 0, 0, + // u16 Version ('1.0') + 0, 1, + // u16 wIndex + MS_EXTENDED_PROPERTIES, 0, + // u16 wCount -- three section + 3, 0, + + //-----property section 1------ + // u32 size ( 14+40+78 == 132) + 132, 0, 0, 0, + // u32 type + 1, 0, 0, 0, // unicode string + // u16 namelen (20*2 = 40) + 40, 0, + // name DeviceInterfaceGUID + 'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,'I',0,'n',0,'t',0,'e',0,'r',0,'f',0,'a',0,'c',0,'e',0,'G',0,'U',0,'I',0,'D',0,0,0, + // u32 datalen (39*2 = 78) + 78, 0, 0, 0, + // data {4D36E978-E325-11CE-BFC1-08002BE10318} + '{',0,'4',0,'d',0,'3',0,'6',0,'e',0,'9',0,'7',0,'8',0,'-',0,'e',0,'3',0,'2',0,'5',0, + '-',0,'1',0,'1',0,'c',0,'e',0,'-',0,'b',0,'f',0,'c',0,'1',0,'-',0,'0',0,'8',0,'0',0, + '0',0,'2',0,'b',0,'e',0,'1',0,'0',0,'3',0,'1',0,'8',0,'}',0,0,0, + + //-----property section 2------ + // u32 size ( 14+12+38 == 64) + 64, 0, 0, 0, + // u32 type + 1, 0, 0, 0, // unicode string + // u16 namelen (12) + 12, 0, + // name Label + 'L',0,'a',0,'b',0,'e',0,'l',0,0,0, + // u32 datalen ( 19*2 = 38 ) + 38, 0, 0, 0, + // data 'Awesome PM3 Device' + 'A',0,'w',0,'e',0,'s',0,'o',0,'m',0,'e',0,' ',0,'P',0,'M',0,'3',0,' ',0,'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,0,0, + + //-----property section 3------ + // u32 size ( 14+12+76 == 102) + 102, 0, 0, 0, + // u32 type + 2, 0, 0, 0, //Unicode string with environment variables + // u16 namelen (12) + 12, 0, + // name Icons + 'I',0,'c',0,'o',0,'n',0,'s',0,0,0, + // u32 datalen ( 38*2 == 76) + 76, 0, 0, 0, + // data '%SystemRoot%\\system32\\Shell32.dll,-13' + '%',0,'S',0,'y',0,'s',0,'t',0,'e',0,'m',0,'R',0,'o',0,'o',0,'t',0,'%',0, + '\\',0,'s',0,'y',0,'s',0,'t',0,'e',0,'m',0,'3',0,'2',0,'\\',0, + 'S',0,'h',0,'e',0,'l',0,'l',0,'3',0,'2',0,'.',0,'d',0,'l',0,'l',0,',',0, + '-',0,'1',0,'3',0,0,0 +}; + +*/ + +static const char StrLanguageCodes[] = { + 4, // Length + 0x03, // Type is string + 0x09, 0x04 // supported language Code 0 = 0x0409 (English) +}; + +// Note: ModemManager (Linux) ignores Proxmark3 devices by matching the +// manufacturer string "proxmark.org". Don't change this. +// or use the blacklisting file. +static const char StrManufacturer[] = { + 26, // Length + 0x03, // Type is string + 'p',0,'r',0,'o',0,'x',0,'m',0,'a',0,'r',0,'k',0,'.',0,'o',0,'r',0,'g',0, +}; + +static const char StrProduct[] = { + 20, // Length + 0x03, // Type is string + 'p',0,'r',0,'o',0,'x',0,'m',0,'a',0,'r',0,'k',0,'3',0 +}; + +static const char StrSerialNumber[] = { + 14, // Length + 0x03, // Type is string + 'i',0,'c',0,'e',0,'m',0,'a',0,'n',0 +}; + +// size includes their own field. +static const char StrMS_OSDescriptor[] = { + 18, // length 0x12 + 0x03, // Type is string + 'M',0,'S',0,'F',0,'T',0,'1',0,'0',0,'0',0,MS_VENDOR_CODE,0 +}; + +const char* getStringDescriptor(uint8_t idx) { + switch(idx) { + case 0: return StrLanguageCodes; + case 1: return StrManufacturer; + case 2: return StrProduct; + case 3: return StrSerialNumber; + case MS_OS_DESCRIPTOR_INDEX: return StrMS_OSDescriptor; + default: + return(NULL); + } +} + +// Bitmap for all status bits in CSR which must be written as 1 to cause no effect +#define REG_NO_EFFECT_1_ALL AT91C_UDP_RX_DATA_BK0 | AT91C_UDP_RX_DATA_BK1 \ + |AT91C_UDP_STALLSENT | AT91C_UDP_RXSETUP \ + |AT91C_UDP_TXCOMP + +// Clear flags in the UDP_CSR register and waits for synchronization +#define UDP_CLEAR_EP_FLAGS(endpoint, flags) { \ + volatile unsigned int reg; \ + reg = pUdp->UDP_CSR[(endpoint)]; \ + reg |= REG_NO_EFFECT_1_ALL; \ + reg &= ~(flags); \ + pUdp->UDP_CSR[(endpoint)] = reg; \ +} \ + +// reset flags in the UDP_CSR register and waits for synchronization +#define UDP_SET_EP_FLAGS(endpoint, flags) { \ + volatile unsigned int reg; \ + reg = pUdp->UDP_CSR[(endpoint)]; \ + reg |= REG_NO_EFFECT_1_ALL; \ + reg |= (flags); \ + pUdp->UDP_CSR[(endpoint)] = reg; \ +} \ + + +typedef struct { + uint32_t BitRate; + uint8_t Format; + uint8_t ParityType; + uint8_t DataBits; +} AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING; + +AT91S_CDC_LINE_CODING line = { + 115200, // baudrate + 0, // 1 Stop Bit + 0, // None Parity + 8}; // 8 Data bits + +static void SpinDelay(int ms) { + int us = ms * 1000; + int ticks = (48 * us) >> 10; + + // Borrow a PWM unit for my real-time clock + AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0); + + // 48 MHz / 1024 gives 46.875 kHz + AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); + AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; + AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; + + uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; + + for(;;) { + uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; + if (now == (uint16_t)(start + ticks)) + return; + + WDT_HIT(); + } +} + +//*---------------------------------------------------------------------------- +//* \fn usb_disable +//* \brief This function deactivates the USB device +//*---------------------------------------------------------------------------- +void usb_disable() { + // Disconnect the USB device + AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU; + + // Clear all lingering interrupts + if (pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES) { + pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES; + } +} + +//*---------------------------------------------------------------------------- +//* \fn usb_enable +//* \brief This function Activates the USB device +//*---------------------------------------------------------------------------- +void usb_enable() { + // Set the PLL USB Divider + AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ; + + // Specific Chip USB Initialisation + // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock + AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_UDP; + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP); + + AT91C_BASE_UDP->UDP_FADDR = 0; + AT91C_BASE_UDP->UDP_GLBSTATE = 0; + + // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO + // Set in PIO mode and Configure in Output + AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode + AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output + + // Clear for set the Pullup resistor + AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU; + + // Disconnect and reconnect USB controller for 100ms + usb_disable(); + + SpinDelay(100); + // Wait for a short while + //for (volatile size_t i=0; i<0x100000; i++) {}; + + // Reconnect USB reconnect + AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU; + AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; +} + +//*---------------------------------------------------------------------------- +//* \fn usb_check +//* \brief Test if the device is configured and handle enumeration +//*---------------------------------------------------------------------------- +static int usb_reconnect = 0; +static int usb_configured = 0; +void SetUSBreconnect(int value) { + usb_reconnect = value; +} +int GetUSBreconnect(void) { + return usb_reconnect; +} +void SetUSBconfigured(int value) { + usb_configured = value; +} +int GetUSBconfigured(void){ + return usb_configured; +} + +bool usb_check() { + + /* + // reconnected ONCE and + if ( !USB_ATTACHED() ){ + usb_reconnect = 1; + return false; + } + + // only one time after USB been disengaged and re-engaged + if ( USB_ATTACHED() && usb_reconnect == 1 ) { + + if ( usb_configured == 0) { + usb_disable(); + usb_enable(); + + AT91F_CDC_Enumerate(); + + usb_configured = 1; + return false; + } + } + */ + + // interrupt status register + AT91_REG isr = pUdp->UDP_ISR; + + // end of bus reset + if (isr & AT91C_UDP_ENDBUSRES) { + pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES; + // reset all endpoints + pUdp->UDP_RSTEP = (unsigned int)-1; + pUdp->UDP_RSTEP = 0; + // Enable the function + pUdp->UDP_FADDR = AT91C_UDP_FEN; + // Configure endpoint 0 (enable control endpoint) + pUdp->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL); + } + else if (isr & AT91C_UDP_EPINT0) { + pUdp->UDP_ICR = AT91C_UDP_EPINT0; + AT91F_CDC_Enumerate(); + } + /* + else if (isr & AT91C_UDP_EPINT3 ) { + pUdp->UDP_ICR = AT91C_UDP_EPINT3; + AT91F_CDC_Enumerate(); + //pUdp->UDP_ICR |= AT91C_UDP_EPINT3; + } + */ + return (btConfiguration) ? true : false; +} + +bool usb_poll() { + if (!usb_check()) return false; + return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank); +} + +/** + In github PR #129, some users appears to get a false positive from + usb_poll, which returns true, but the usb_read operation + still returns 0. + This check is basically the same as above, but also checks + that the length available to read is non-zero, thus hopefully fixes the + bug. +**/ +bool usb_poll_validate_length() { + if (!usb_check()) return false; + if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false; + return ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) > 0; +} + +//*---------------------------------------------------------------------------- +//* \fn usb_read +//* \brief Read available data from Endpoint 1 OUT (host to device) +//*---------------------------------------------------------------------------- +uint32_t usb_read(byte_t* data, size_t len) { + + if ( len == 0 ) return 0; + + uint8_t bank = btReceiveBank; + uint32_t packetSize, nbBytesRcv = 0; + uint32_t time_out = 0; + + while (len) { + if (!usb_check()) break; + + if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) { + + packetSize = (pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16; + packetSize = MIN( packetSize, len); + len -= packetSize; + while (packetSize--) + data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT]; + + // flip bank + UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank) + + if (bank == AT91C_UDP_RX_DATA_BK0) + bank = AT91C_UDP_RX_DATA_BK1; + else + bank = AT91C_UDP_RX_DATA_BK0; + } + if (time_out++ == 0x1fff) break; + } + + btReceiveBank = bank; + return nbBytesRcv; +} + +//*---------------------------------------------------------------------------- +//* \fn usb_write +//* \brief Send through endpoint 2 (device to host) +//*---------------------------------------------------------------------------- +uint32_t usb_write(const byte_t* data, const size_t len) { + + if (!len) return 0; + if (!usb_check()) return 0; + + // can we write? + if ( (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) != 0 ) return 0; + + size_t length = len; + uint32_t cpt = 0; + + + // send first chunk + cpt = MIN(length, AT91C_EP_IN_SIZE); + length -= cpt; + while (cpt--) { + pUdp->UDP_FDR[AT91C_EP_IN] = *data++; + } + + UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); + + while (length) { + // Send next chunk + cpt = MIN(length, AT91C_EP_IN_SIZE); + length -= cpt; + while (cpt--) { + pUdp->UDP_FDR[AT91C_EP_IN] = *data++; + } + + // Wait for previous chunk to be sent + // (iceman) when is the bankswapping done? + while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { + if (!usb_check()) return length; + } + + UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); + while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP); + UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); + + } + + // Wait for the end of transfer + while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { + if (!usb_check()) return length; + } + + UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); + while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP); + + return length; +} + +//*---------------------------------------------------------------------------- +//* \fn AT91F_USB_SendData +//* \brief Send Data through the control endpoint +//*---------------------------------------------------------------------------- +void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) { + uint32_t cpt = 0; + AT91_REG csr; + + do { + cpt = MIN(length, AT91C_EP_CONTROL_SIZE); + length -= cpt; + + while (cpt--) + pUdp->UDP_FDR[AT91C_EP_CONTROL] = *pData++; + + if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) { + UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP); + while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP); + } + + UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY); + + do { + csr = pUdp->UDP_CSR[AT91C_EP_CONTROL]; + // Data IN stage has been stopped by a status OUT + if ( csr & AT91C_UDP_RX_DATA_BK0) { + + UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0) + return; + } + } while ( !(csr & AT91C_UDP_TXCOMP) ); + + } while (length); + + if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) { + UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP); + while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP); + } +} + + +//*---------------------------------------------------------------------------- +//* \fn AT91F_USB_SendZlp +//* \brief Send zero length packet through the control endpoint +//*---------------------------------------------------------------------------- +void AT91F_USB_SendZlp(AT91PS_UDP pUdp) { + UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY); + while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) ); + UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP); + while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP); +} + +//*---------------------------------------------------------------------------- +//* \fn AT91F_USB_SendStall +//* \brief Stall the control endpoint +//*---------------------------------------------------------------------------- +void AT91F_USB_SendStall(AT91PS_UDP pUdp) { + UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL); + while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_ISOERROR) ); + UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR) ); + while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR)); +} + +//*---------------------------------------------------------------------------- +//* \fn AT91F_CDC_Enumerate +//* \brief This function is a callback invoked when a SETUP packet is received +//* problem: +//* 1. this is for USB endpoint0. the control endpoint. +//* 2. mixed with CDC ACM endpoint3 , interrupt, control endpoint +//*---------------------------------------------------------------------------- +void AT91F_CDC_Enumerate() { + byte_t bmRequestType, bRequest; + uint16_t wValue, wIndex, wLength, wStatus; + + if ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) ) + return; + + bmRequestType = pUdp->UDP_FDR[AT91C_EP_CONTROL]; + bRequest = pUdp->UDP_FDR[AT91C_EP_CONTROL]; + wValue = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF); + wValue |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8); + wIndex = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF); + wIndex |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8); + wLength = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF); + wLength |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8); + + if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host + UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR); + while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR) ); + } + UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RXSETUP); + while ( (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) ); + + /* + if ( bRequest == MS_VENDOR_CODE) { + if ( bmRequestType == MS_WCID_GET_DESCRIPTOR ) { // C0 + if ( wIndex == MS_EXTENDED_COMPAT_ID ) { // 4 + //AT91F_USB_SendData(pUdp, CompatIDFeatureDescriptor, MIN(sizeof(CompatIDFeatureDescriptor), wLength)); + //return; + } + } + + if ( bmRequestType == MS_WCID_GET_FEATURE_DESCRIPTOR ) { //C1 + // if ( wIndex == MS_EXTENDED_PROPERTIES ) { // 5 - winusb bug with wIndex == interface index, so I just send it always) + //AT91F_USB_SendData(pUdp, OSprop, MIN(sizeof(OSprop), wLength)); + //return; + // } + } + } + */ + + // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1 + switch ((bRequest << 8) | bmRequestType) { + case STD_GET_DESCRIPTOR: { + + if ( wValue == 0x100 ) // Return Device Descriptor + AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength)); + else if ( wValue == 0x200 ) // Return Configuration Descriptor + AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength)); + else if ( (wValue & 0xF00) == 0xF00) // Return BOS Descriptor + AT91F_USB_SendData(pUdp, bosDescriptor, MIN(sizeof(bosDescriptor), wLength)); + else if ( (wValue & 0x300) == 0x300) { // Return String Descriptor + + const char *strDescriptor = getStringDescriptor(wValue & 0xff); + if (strDescriptor != NULL) { + AT91F_USB_SendData(pUdp, strDescriptor, MIN(strDescriptor[0], wLength)); + } else { + AT91F_USB_SendStall(pUdp); + } + } else { + AT91F_USB_SendStall(pUdp); + } + } + break; + case STD_SET_ADDRESS: + AT91F_USB_SendZlp(pUdp); + pUdp->UDP_FADDR = (AT91C_UDP_FEN | (wValue & 0x7F) ); + pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0; + break; + case STD_SET_CONFIGURATION: + + /* + * Set or clear the device "configured" state. + * The LSB of wValue is the "Configuration Number". If this value is non-zero, + * it should be the same number as defined in the Configuration Descriptor; + * otherwise an error must have occurred. + * This device has only one configuration and its Config Number is CONF_NB (= 1). + */ + AT91F_USB_SendZlp(pUdp); + btConfiguration = wValue; + pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN; + + // make sure we are not stalled + /* + UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT , AT91C_UDP_FORCESTALL); + UDP_CLEAR_EP_FLAGS(AT91C_EP_IN , AT91C_UDP_FORCESTALL); + UDP_CLEAR_EP_FLAGS(AT91C_EP_NOTIFY, AT91C_UDP_FORCESTALL); + */ + + // enable endpoints + pUdp->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0; + pUdp->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0; + pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0; + break; + case STD_GET_CONFIGURATION: + AT91F_USB_SendData(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration)); + break; + case STD_GET_STATUS_ZERO: + wStatus = 0; // Device is Bus powered, remote wakeup disabled + AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); + break; + case STD_GET_STATUS_INTERFACE: + wStatus = 0; // reserved for future use + AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); + break; + case STD_GET_STATUS_ENDPOINT: + wStatus = 0; + wIndex &= 0x0F; + if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) { + wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1; + AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); + } + else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) { + wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1; + AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); + } else { + AT91F_USB_SendStall(pUdp); + } + break; + case STD_SET_FEATURE_ZERO: + AT91F_USB_SendStall(pUdp); + break; + case STD_SET_FEATURE_INTERFACE: + AT91F_USB_SendZlp(pUdp); + break; + case STD_SET_FEATURE_ENDPOINT: + wIndex &= 0x0F; + if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) { + pUdp->UDP_CSR[wIndex] = 0; + AT91F_USB_SendZlp(pUdp); + } else { + AT91F_USB_SendStall(pUdp); + } + break; + case STD_CLEAR_FEATURE_ZERO: + AT91F_USB_SendStall(pUdp); + break; + case STD_CLEAR_FEATURE_INTERFACE: + AT91F_USB_SendZlp(pUdp); + break; + case STD_CLEAR_FEATURE_ENDPOINT: + wIndex &= 0x0F; + if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) { + + if (wIndex == AT91C_EP_OUT) pUdp->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT); + else if (wIndex == AT91C_EP_IN) pUdp->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN); + else if (wIndex == AT91C_EP_NOTIFY) pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN); + + AT91F_USB_SendZlp(pUdp); + } else { + AT91F_USB_SendStall(pUdp); + } + break; + + // handle CDC class requests + case SET_LINE_CODING: { + /* + uint8_t i; + for ( i = 0 ; i < 7 ; i++ ) { + ((uint8_t*)&line)[i] = pUdp->UDP_FDR[AT91C_EP_CONTROL]; + } */ + // ignore SET_LINE_CODING... + while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RX_DATA_BK0) ); + UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0); + AT91F_USB_SendZlp(pUdp); + break; + } + case GET_LINE_CODING: + AT91F_USB_SendData(pUdp, (char *) &line, MIN(sizeof(line), wLength)); + break; + case SET_CONTROL_LINE_STATE: + btConnection = wValue; + AT91F_USB_SendZlp(pUdp); + break; + default: + AT91F_USB_SendStall(pUdp); + break; + } } \ No newline at end of file diff --git a/common/usb_cdc.h b/common/usb_cdc.h index 6d471db92..fcac556fd 100644 --- a/common/usb_cdc.h +++ b/common/usb_cdc.h @@ -1,63 +1,63 @@ -/* - * at91sam7s USB CDC device implementation - * - * Copyright (c) 2012, Roel Verdult - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. Neither the name of the copyright holders nor the - * names of its contributors may be used to endorse or promote products - * derived from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY - * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY - * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND - * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - * - * based on the "Basic USB Example" from ATMEL (doc6123.pdf) - * - * @file usb_cdc.c - * @brief - */ - -#ifndef _USB_CDC_H_ -#define _USB_CDC_H_ - -#include -#include "at91sam7s512.h" -#include "config_gpio.h" -#include "proxmark3.h" // USB_CONNECT() -#include "common.h" - -extern void usb_disable(); -extern void usb_enable(); -extern bool usb_check(); -extern bool usb_poll(); -extern bool usb_poll_validate_length(); -extern uint32_t usb_read(byte_t* data, size_t len); -extern uint32_t usb_write(const byte_t* data, const size_t len); - -extern void SetUSBreconnect(int value); -extern int GetUSBreconnect(void); -extern void SetUSBconfigured(int value); -extern int GetUSBconfigured(void); - -extern void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length); -extern void AT91F_USB_SendZlp(AT91PS_UDP pUdp); -extern void AT91F_USB_SendStall(AT91PS_UDP pUdp); -extern void AT91F_CDC_Enumerate(); - -#endif // _USB_CDC_H_ - +/* + * at91sam7s USB CDC device implementation + * + * Copyright (c) 2012, Roel Verdult + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holders nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * based on the "Basic USB Example" from ATMEL (doc6123.pdf) + * + * @file usb_cdc.c + * @brief + */ + +#ifndef _USB_CDC_H_ +#define _USB_CDC_H_ + +#include +#include "at91sam7s512.h" +#include "config_gpio.h" +#include "proxmark3.h" // USB_CONNECT() +#include "common.h" + +extern void usb_disable(); +extern void usb_enable(); +extern bool usb_check(); +extern bool usb_poll(); +extern bool usb_poll_validate_length(); +extern uint32_t usb_read(byte_t* data, size_t len); +extern uint32_t usb_write(const byte_t* data, const size_t len); + +extern void SetUSBreconnect(int value); +extern int GetUSBreconnect(void); +extern void SetUSBconfigured(int value); +extern int GetUSBconfigured(void); + +extern void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length); +extern void AT91F_USB_SendZlp(AT91PS_UDP pUdp); +extern void AT91F_USB_SendStall(AT91PS_UDP pUdp); +extern void AT91F_CDC_Enumerate(); + +#endif // _USB_CDC_H_ + diff --git a/tools/mfkey/crapto1.c b/tools/mfkey/crapto1.c index ea7f60bba..203efeb4f 100755 --- a/tools/mfkey/crapto1.c +++ b/tools/mfkey/crapto1.c @@ -1,574 +1,574 @@ -/* crapto1.c - - 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, US$ - - Copyright (C) 2008-2014 bla -*/ -#include "crapto1.h" -#include - -#if !defined LOWMEM && defined __GNUC__ -static uint8_t filterlut[1 << 20]; -static void __attribute__((constructor)) fill_lut() -{ - uint32_t i; - for(i = 0; i < 1 << 20; ++i) - filterlut[i] = filter(i); -} -#define filter(x) (filterlut[(x) & 0xfffff]) -#endif - - - -typedef struct bucket { - uint32_t *head; - uint32_t *bp; -} bucket_t; - -typedef bucket_t bucket_array_t[2][0x100]; - -typedef struct bucket_info { - struct { - uint32_t *head, *tail; - } bucket_info[2][0x100]; - uint32_t numbuckets; - } bucket_info_t; - - -static void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop, - uint32_t* const ostart, uint32_t* const ostop, - bucket_info_t *bucket_info, bucket_array_t bucket) -{ - uint32_t *p1, *p2; - uint32_t *start[2]; - uint32_t *stop[2]; - - start[0] = estart; - stop[0] = estop; - start[1] = ostart; - stop[1] = ostop; - - // init buckets to be empty - for (uint32_t i = 0; i < 2; i++) { - for (uint32_t j = 0x00; j <= 0xff; j++) { - bucket[i][j].bp = bucket[i][j].head; - } - } - - // sort the lists into the buckets based on the MSB (contribution bits) - for (uint32_t i = 0; i < 2; i++) { - for (p1 = start[i]; p1 <= stop[i]; p1++) { - uint32_t bucket_index = (*p1 & 0xff000000) >> 24; - *(bucket[i][bucket_index].bp++) = *p1; - } - } - - - // write back intersecting buckets as sorted list. - // fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets. - uint32_t nonempty_bucket; - for (uint32_t i = 0; i < 2; i++) { - p1 = start[i]; - nonempty_bucket = 0; - for (uint32_t j = 0x00; j <= 0xff; j++) { - if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only - bucket_info->bucket_info[i][nonempty_bucket].head = p1; - for (p2 = bucket[i][j].head; p2 < bucket[i][j].bp; *p1++ = *p2++); - bucket_info->bucket_info[i][nonempty_bucket].tail = p1 - 1; - nonempty_bucket++; - } - } - bucket_info->numbuckets = nonempty_bucket; - } -} - - -/** update_contribution - * helper, calculates the partial linear feedback contributions and puts in MSB - */ -static inline void update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2) -{ - uint32_t p = *item >> 25; - - p = p << 1 | parity(*item & mask1); - p = p << 1 | parity(*item & mask2); - *item = p << 24 | (*item & 0xffffff); -} - -/** extend_table - * using a bit of the keystream extend the table of possible lfsr states - */ -static inline void extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in) -{ - in <<= 24; - for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) - if(filter(*tbl) ^ filter(*tbl | 1)) { - *tbl |= filter(*tbl) ^ bit; - update_contribution(tbl, m1, m2); - *tbl ^= in; - } else if(filter(*tbl) == bit) { - *++*end = tbl[1]; - tbl[1] = tbl[0] | 1; - update_contribution(tbl, m1, m2); - *tbl++ ^= in; - update_contribution(tbl, m1, m2); - *tbl ^= in; - } else - *tbl-- = *(*end)--; -} -/** extend_table_simple - * using a bit of the keystream extend the table of possible lfsr states - */ -static inline void extend_table_simple(uint32_t *tbl, uint32_t **end, int bit) -{ - for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) { - if(filter(*tbl) ^ filter(*tbl | 1)) { // replace - *tbl |= filter(*tbl) ^ bit; - } else if(filter(*tbl) == bit) { // insert - *++*end = *++tbl; - *tbl = tbl[-1] | 1; - } else { // drop - *tbl-- = *(*end)--; - } - } -} -/** recover - * recursively narrow down the search space, 4 bits of keystream at a time - */ -static struct Crypto1State* -recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks, - uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem, - struct Crypto1State *sl, uint32_t in, bucket_array_t bucket) -{ - uint32_t *o, *e; - bucket_info_t bucket_info; - - if(rem == -1) { - for(e = e_head; e <= e_tail; ++e) { - *e = *e << 1 ^ parity(*e & LF_POLY_EVEN) ^ !!(in & 4); - for(o = o_head; o <= o_tail; ++o, ++sl) { - sl->even = *o; - sl->odd = *e ^ parity(*o & LF_POLY_ODD); - sl[1].odd = sl[1].even = 0; - } - } - return sl; - } - - for(uint32_t i = 0; i < 4 && rem--; i++) { - oks >>= 1; - eks >>= 1; - in >>= 2; - extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0); - if(o_head > o_tail) - return sl; - - extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, in & 3); - if(e_head > e_tail) - return sl; - } - - bucket_sort_intersect(e_head, e_tail, o_head, o_tail, &bucket_info, bucket); - - for (int i = bucket_info.numbuckets - 1; i >= 0; i--) { - sl = recover(bucket_info.bucket_info[1][i].head, bucket_info.bucket_info[1][i].tail, oks, - bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks, - rem, sl, in, bucket); - } - - return sl; -} -/** lfsr_recovery - * recover the state of the lfsr given 32 bits of the keystream - * additionally you can use the in parameter to specify the value - * that was fed into the lfsr at the time the keystream was generated - */ -struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in) -{ - struct Crypto1State *statelist; - uint32_t *odd_head = 0, *odd_tail = 0, oks = 0; - uint32_t *even_head = 0, *even_tail = 0, eks = 0; - int i; - - // split the keystream into an odd and even part - for(i = 31; i >= 0; i -= 2) - oks = oks << 1 | BEBIT(ks2, i); - for(i = 30; i >= 0; i -= 2) - eks = eks << 1 | BEBIT(ks2, i); - - odd_head = odd_tail = malloc(sizeof(uint32_t) << 21); - even_head = even_tail = malloc(sizeof(uint32_t) << 21); - statelist = malloc(sizeof(struct Crypto1State) << 18); - if(!odd_tail-- || !even_tail-- || !statelist) { - free(statelist); - statelist = 0; - goto out; - } - - statelist->odd = statelist->even = 0; - - // allocate memory for out of place bucket_sort - bucket_array_t bucket; - - for (uint32_t i = 0; i < 2; i++) { - for (uint32_t j = 0; j <= 0xff; j++) { - bucket[i][j].head = malloc(sizeof(uint32_t)<<14); - if (!bucket[i][j].head) { - goto out; - } - } - } - - // initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream - for(i = 1 << 20; i >= 0; --i) { - if(filter(i) == (oks & 1)) - *++odd_tail = i; - if(filter(i) == (eks & 1)) - *++even_tail = i; - } - - // extend the statelists. Look at the next 8 Bits of the keystream (4 Bit each odd and even): - for(i = 0; i < 4; i++) { - extend_table_simple(odd_head, &odd_tail, (oks >>= 1) & 1); - extend_table_simple(even_head, &even_tail, (eks >>= 1) & 1); - } - - // the statelists now contain all states which could have generated the last 10 Bits of the keystream. - // 22 bits to go to recover 32 bits in total. From now on, we need to take the "in" - // parameter into account. - in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping - recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket); - -out: - for (uint32_t i = 0; i < 2; i++) - for (uint32_t j = 0; j <= 0xff; j++) - free(bucket[i][j].head); - free(odd_head); - free(even_head); - return statelist; -} - -static const uint32_t S1[] = { 0x62141, 0x310A0, 0x18850, 0x0C428, 0x06214, - 0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83, - 0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA}; -static const uint32_t S2[] = { 0x3A557B00, 0x5D2ABD80, 0x2E955EC0, 0x174AAF60, - 0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8, - 0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20, - 0x7EC7EE90, 0x7F63F748, 0x79117020}; -static const uint32_t T1[] = { - 0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66, - 0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B, - 0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615, - 0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C}; -static const uint32_t T2[] = { 0x3C88B810, 0x5E445C08, 0x2982A580, 0x14C152C0, - 0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268, - 0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0, - 0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0, - 0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950, - 0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0}; -static const uint32_t C1[] = { 0x846B5, 0x4235A, 0x211AD}; -static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0}; -/** Reverse 64 bits of keystream into possible cipher states - * Variation mentioned in the paper. Somewhat optimized version - */ -struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3) -{ - struct Crypto1State *statelist, *sl; - uint8_t oks[32], eks[32], hi[32]; - uint32_t low = 0, win = 0; - uint32_t *tail, table[1 << 16]; - int i, j; - - sl = statelist = malloc(sizeof(struct Crypto1State) << 4); - if(!sl) - return 0; - sl->odd = sl->even = 0; - - for(i = 30; i >= 0; i -= 2) { - oks[i >> 1] = BEBIT(ks2, i); - oks[16 + (i >> 1)] = BEBIT(ks3, i); - } - for(i = 31; i >= 0; i -= 2) { - eks[i >> 1] = BEBIT(ks2, i); - eks[16 + (i >> 1)] = BEBIT(ks3, i); - } - - for(i = 0xfffff; i >= 0; --i) { - if (filter(i) != oks[0]) - continue; - - *(tail = table) = i; - for(j = 1; tail >= table && j < 29; ++j) - extend_table_simple(table, &tail, oks[j]); - - if(tail < table) - continue; - - for(j = 0; j < 19; ++j) - low = low << 1 | parity(i & S1[j]); - for(j = 0; j < 32; ++j) - hi[j] = parity(i & T1[j]); - - for(; tail >= table; --tail) { - for(j = 0; j < 3; ++j) { - *tail = *tail << 1; - *tail |= parity((i & C1[j]) ^ (*tail & C2[j])); - if(filter(*tail) != oks[29 + j]) - goto continue2; - } - - for(j = 0; j < 19; ++j) - win = win << 1 | parity(*tail & S2[j]); - - win ^= low; - for(j = 0; j < 32; ++j) { - win = win << 1 ^ hi[j] ^ parity(*tail & T2[j]); - if(filter(win) != eks[j]) - goto continue2; - } - - *tail = *tail << 1 | parity(LF_POLY_EVEN & *tail); - sl->odd = *tail ^ parity(LF_POLY_ODD & win); - sl->even = win; - ++sl; - sl->odd = sl->even = 0; - continue2:; - } - } - return statelist; -} - -/** lfsr_rollback_bit - * Rollback the shift register in order to get previous states - */ -uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb) -{ - int out; - uint8_t ret; - uint32_t t; - - s->odd &= 0xffffff; - t = s->odd, s->odd = s->even, s->even = t; - - out = s->even & 1; - out ^= LF_POLY_EVEN & (s->even >>= 1); - out ^= LF_POLY_ODD & s->odd; - out ^= !!in; - out ^= (ret = filter(s->odd)) & !!fb; - - s->even |= parity(out) << 23; - return ret; -} -/** lfsr_rollback_byte - * Rollback the shift register in order to get previous states - */ -uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb) -{ - /* - int i, ret = 0; - for (i = 7; i >= 0; --i) - ret |= lfsr_rollback_bit(s, BIT(in, i), fb) << i; -*/ -// unfold loop 20160112 - uint8_t ret = 0; - ret |= lfsr_rollback_bit(s, BIT(in, 7), fb) << 7; - ret |= lfsr_rollback_bit(s, BIT(in, 6), fb) << 6; - ret |= lfsr_rollback_bit(s, BIT(in, 5), fb) << 5; - ret |= lfsr_rollback_bit(s, BIT(in, 4), fb) << 4; - ret |= lfsr_rollback_bit(s, BIT(in, 3), fb) << 3; - ret |= lfsr_rollback_bit(s, BIT(in, 2), fb) << 2; - ret |= lfsr_rollback_bit(s, BIT(in, 1), fb) << 1; - ret |= lfsr_rollback_bit(s, BIT(in, 0), fb) << 0; - return ret; -} -/** lfsr_rollback_word - * Rollback the shift register in order to get previous states - */ -uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) -{ - /* - int i; - uint32_t ret = 0; - for (i = 31; i >= 0; --i) - ret |= lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24); -*/ -// unfold loop 20160112 - uint32_t ret = 0; - ret |= lfsr_rollback_bit(s, BEBIT(in, 31), fb) << (31 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 30), fb) << (30 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 29), fb) << (29 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 28), fb) << (28 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 27), fb) << (27 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 26), fb) << (26 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 25), fb) << (25 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 24), fb) << (24 ^ 24); - - ret |= lfsr_rollback_bit(s, BEBIT(in, 23), fb) << (23 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 22), fb) << (22 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 21), fb) << (21 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 20), fb) << (20 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 19), fb) << (19 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 18), fb) << (18 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 17), fb) << (17 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 16), fb) << (16 ^ 24); - - ret |= lfsr_rollback_bit(s, BEBIT(in, 15), fb) << (15 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 14), fb) << (14 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 13), fb) << (13 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 12), fb) << (12 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 11), fb) << (11 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 10), fb) << (10 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 9), fb) << (9 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 8), fb) << (8 ^ 24); - - ret |= lfsr_rollback_bit(s, BEBIT(in, 7), fb) << (7 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 6), fb) << (6 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 5), fb) << (5 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 4), fb) << (4 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 3), fb) << (3 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 2), fb) << (2 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 1), fb) << (1 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 0), fb) << (0 ^ 24); - return ret; -} - -/** nonce_distance - * x,y valid tag nonces, then prng_successor(x, nonce_distance(x, y)) = y - */ -static uint16_t *dist = 0; -int nonce_distance(uint32_t from, uint32_t to) -{ - uint16_t x, i; - if(!dist) { - dist = malloc(2 << 16); - if(!dist) - return -1; - for (x = i = 1; i; ++i) { - dist[(x & 0xff) << 8 | x >> 8] = i; - x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; - } - } - return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535; -} - - -static uint32_t fastfwd[2][8] = { - { 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB}, - { 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}}; - - -/** lfsr_prefix_ks - * - * Is an exported helper function from the common prefix attack - * Described in the "dark side" paper. It returns an -1 terminated array - * of possible partial(21 bit) secret state. - * The required keystream(ks) needs to contain the keystream that was used to - * encrypt the NACK which is observed when varying only the 3 last bits of Nr - * only correct iff [NR_3] ^ NR_3 does not depend on Nr_3 - */ -uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) -{ - uint32_t *candidates = malloc(4 << 10); - if(!candidates) return 0; - - uint32_t c, entry; - int size = 0, i, good; - - for(i = 0; i < 1 << 21; ++i) { - for(c = 0, good = 1; good && c < 8; ++c) { - entry = i ^ fastfwd[isodd][c]; - good &= (BIT(ks[c], isodd) == filter(entry >> 1)); - good &= (BIT(ks[c], isodd + 2) == filter(entry)); - } - if(good) - candidates[size++] = i; - } - - candidates[size] = -1; - - return candidates; -} - -/** check_pfx_parity - * helper function which eliminates possible secret states using parity bits - */ -static struct Crypto1State* check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8], uint32_t odd, uint32_t even, struct Crypto1State* sl) -{ - uint32_t ks1, nr, ks2, rr, ks3, c, good = 1; - - for(c = 0; good && c < 8; ++c) { - sl->odd = odd ^ fastfwd[1][c]; - sl->even = even ^ fastfwd[0][c]; - - lfsr_rollback_bit(sl, 0, 0); - lfsr_rollback_bit(sl, 0, 0); - - ks3 = lfsr_rollback_bit(sl, 0, 0); - ks2 = lfsr_rollback_word(sl, 0, 0); - ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1); - - nr = ks1 ^ (prefix | c << 5); - rr = ks2 ^ rresp; - - good &= parity(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); - good &= parity(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); - good &= parity(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8); - good &= parity(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0); - good &= parity(rr & 0x000000ff) ^ parities[c][7] ^ ks3; - } - - return sl + good; -} - -/** lfsr_common_prefix - * Implentation of the common prefix attack. - * Requires the 28 bit constant prefix used as reader nonce (pfx) - * The reader response used (rr) - * The keystream used to encrypt the observed NACK's (ks) - * The parity bits (par) - * It returns a zero terminated list of possible cipher states after the - * tag nonce was fed in - */ - -struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]) -{ - struct Crypto1State *statelist, *s; - uint32_t *odd, *even, *o, *e, top; - - odd = lfsr_prefix_ks(ks, 1); - even = lfsr_prefix_ks(ks, 0); - - s = statelist = malloc((sizeof *statelist) << 24); - if(!s || !odd || !even) { - free(statelist); - statelist = 0; - goto out; - } - - for(o = odd; *o + 1; ++o) - for(e = even; *e + 1; ++e) - for(top = 0; top < 64; ++top) { - *o += 1 << 21; - *e += (!(top & 7) + 1) << 21; - s = check_pfx_parity(pfx, rr, par, *o, *e, s); - } - - s->odd = s->even = 0; -out: - free(odd); - free(even); - return statelist; -} +/* crapto1.c + + 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, US$ + + Copyright (C) 2008-2014 bla +*/ +#include "crapto1.h" +#include + +#if !defined LOWMEM && defined __GNUC__ +static uint8_t filterlut[1 << 20]; +static void __attribute__((constructor)) fill_lut() +{ + uint32_t i; + for(i = 0; i < 1 << 20; ++i) + filterlut[i] = filter(i); +} +#define filter(x) (filterlut[(x) & 0xfffff]) +#endif + + + +typedef struct bucket { + uint32_t *head; + uint32_t *bp; +} bucket_t; + +typedef bucket_t bucket_array_t[2][0x100]; + +typedef struct bucket_info { + struct { + uint32_t *head, *tail; + } bucket_info[2][0x100]; + uint32_t numbuckets; + } bucket_info_t; + + +static void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop, + uint32_t* const ostart, uint32_t* const ostop, + bucket_info_t *bucket_info, bucket_array_t bucket) +{ + uint32_t *p1, *p2; + uint32_t *start[2]; + uint32_t *stop[2]; + + start[0] = estart; + stop[0] = estop; + start[1] = ostart; + stop[1] = ostop; + + // init buckets to be empty + for (uint32_t i = 0; i < 2; i++) { + for (uint32_t j = 0x00; j <= 0xff; j++) { + bucket[i][j].bp = bucket[i][j].head; + } + } + + // sort the lists into the buckets based on the MSB (contribution bits) + for (uint32_t i = 0; i < 2; i++) { + for (p1 = start[i]; p1 <= stop[i]; p1++) { + uint32_t bucket_index = (*p1 & 0xff000000) >> 24; + *(bucket[i][bucket_index].bp++) = *p1; + } + } + + + // write back intersecting buckets as sorted list. + // fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets. + uint32_t nonempty_bucket; + for (uint32_t i = 0; i < 2; i++) { + p1 = start[i]; + nonempty_bucket = 0; + for (uint32_t j = 0x00; j <= 0xff; j++) { + if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only + bucket_info->bucket_info[i][nonempty_bucket].head = p1; + for (p2 = bucket[i][j].head; p2 < bucket[i][j].bp; *p1++ = *p2++); + bucket_info->bucket_info[i][nonempty_bucket].tail = p1 - 1; + nonempty_bucket++; + } + } + bucket_info->numbuckets = nonempty_bucket; + } +} + + +/** update_contribution + * helper, calculates the partial linear feedback contributions and puts in MSB + */ +static inline void update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2) +{ + uint32_t p = *item >> 25; + + p = p << 1 | parity(*item & mask1); + p = p << 1 | parity(*item & mask2); + *item = p << 24 | (*item & 0xffffff); +} + +/** extend_table + * using a bit of the keystream extend the table of possible lfsr states + */ +static inline void extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in) +{ + in <<= 24; + for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) + if(filter(*tbl) ^ filter(*tbl | 1)) { + *tbl |= filter(*tbl) ^ bit; + update_contribution(tbl, m1, m2); + *tbl ^= in; + } else if(filter(*tbl) == bit) { + *++*end = tbl[1]; + tbl[1] = tbl[0] | 1; + update_contribution(tbl, m1, m2); + *tbl++ ^= in; + update_contribution(tbl, m1, m2); + *tbl ^= in; + } else + *tbl-- = *(*end)--; +} +/** extend_table_simple + * using a bit of the keystream extend the table of possible lfsr states + */ +static inline void extend_table_simple(uint32_t *tbl, uint32_t **end, int bit) +{ + for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) { + if(filter(*tbl) ^ filter(*tbl | 1)) { // replace + *tbl |= filter(*tbl) ^ bit; + } else if(filter(*tbl) == bit) { // insert + *++*end = *++tbl; + *tbl = tbl[-1] | 1; + } else { // drop + *tbl-- = *(*end)--; + } + } +} +/** recover + * recursively narrow down the search space, 4 bits of keystream at a time + */ +static struct Crypto1State* +recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks, + uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem, + struct Crypto1State *sl, uint32_t in, bucket_array_t bucket) +{ + uint32_t *o, *e; + bucket_info_t bucket_info; + + if(rem == -1) { + for(e = e_head; e <= e_tail; ++e) { + *e = *e << 1 ^ parity(*e & LF_POLY_EVEN) ^ !!(in & 4); + for(o = o_head; o <= o_tail; ++o, ++sl) { + sl->even = *o; + sl->odd = *e ^ parity(*o & LF_POLY_ODD); + sl[1].odd = sl[1].even = 0; + } + } + return sl; + } + + for(uint32_t i = 0; i < 4 && rem--; i++) { + oks >>= 1; + eks >>= 1; + in >>= 2; + extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0); + if(o_head > o_tail) + return sl; + + extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, in & 3); + if(e_head > e_tail) + return sl; + } + + bucket_sort_intersect(e_head, e_tail, o_head, o_tail, &bucket_info, bucket); + + for (int i = bucket_info.numbuckets - 1; i >= 0; i--) { + sl = recover(bucket_info.bucket_info[1][i].head, bucket_info.bucket_info[1][i].tail, oks, + bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks, + rem, sl, in, bucket); + } + + return sl; +} +/** lfsr_recovery + * recover the state of the lfsr given 32 bits of the keystream + * additionally you can use the in parameter to specify the value + * that was fed into the lfsr at the time the keystream was generated + */ +struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in) +{ + struct Crypto1State *statelist; + uint32_t *odd_head = 0, *odd_tail = 0, oks = 0; + uint32_t *even_head = 0, *even_tail = 0, eks = 0; + int i; + + // split the keystream into an odd and even part + for(i = 31; i >= 0; i -= 2) + oks = oks << 1 | BEBIT(ks2, i); + for(i = 30; i >= 0; i -= 2) + eks = eks << 1 | BEBIT(ks2, i); + + odd_head = odd_tail = malloc(sizeof(uint32_t) << 21); + even_head = even_tail = malloc(sizeof(uint32_t) << 21); + statelist = malloc(sizeof(struct Crypto1State) << 18); + if(!odd_tail-- || !even_tail-- || !statelist) { + free(statelist); + statelist = 0; + goto out; + } + + statelist->odd = statelist->even = 0; + + // allocate memory for out of place bucket_sort + bucket_array_t bucket; + + for (uint32_t i = 0; i < 2; i++) { + for (uint32_t j = 0; j <= 0xff; j++) { + bucket[i][j].head = malloc(sizeof(uint32_t)<<14); + if (!bucket[i][j].head) { + goto out; + } + } + } + + // initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream + for(i = 1 << 20; i >= 0; --i) { + if(filter(i) == (oks & 1)) + *++odd_tail = i; + if(filter(i) == (eks & 1)) + *++even_tail = i; + } + + // extend the statelists. Look at the next 8 Bits of the keystream (4 Bit each odd and even): + for(i = 0; i < 4; i++) { + extend_table_simple(odd_head, &odd_tail, (oks >>= 1) & 1); + extend_table_simple(even_head, &even_tail, (eks >>= 1) & 1); + } + + // the statelists now contain all states which could have generated the last 10 Bits of the keystream. + // 22 bits to go to recover 32 bits in total. From now on, we need to take the "in" + // parameter into account. + in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping + recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket); + +out: + for (uint32_t i = 0; i < 2; i++) + for (uint32_t j = 0; j <= 0xff; j++) + free(bucket[i][j].head); + free(odd_head); + free(even_head); + return statelist; +} + +static const uint32_t S1[] = { 0x62141, 0x310A0, 0x18850, 0x0C428, 0x06214, + 0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83, + 0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA}; +static const uint32_t S2[] = { 0x3A557B00, 0x5D2ABD80, 0x2E955EC0, 0x174AAF60, + 0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8, + 0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20, + 0x7EC7EE90, 0x7F63F748, 0x79117020}; +static const uint32_t T1[] = { + 0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66, + 0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B, + 0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615, + 0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C}; +static const uint32_t T2[] = { 0x3C88B810, 0x5E445C08, 0x2982A580, 0x14C152C0, + 0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268, + 0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0, + 0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0, + 0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950, + 0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0}; +static const uint32_t C1[] = { 0x846B5, 0x4235A, 0x211AD}; +static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0}; +/** Reverse 64 bits of keystream into possible cipher states + * Variation mentioned in the paper. Somewhat optimized version + */ +struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3) +{ + struct Crypto1State *statelist, *sl; + uint8_t oks[32], eks[32], hi[32]; + uint32_t low = 0, win = 0; + uint32_t *tail, table[1 << 16]; + int i, j; + + sl = statelist = malloc(sizeof(struct Crypto1State) << 4); + if(!sl) + return 0; + sl->odd = sl->even = 0; + + for(i = 30; i >= 0; i -= 2) { + oks[i >> 1] = BEBIT(ks2, i); + oks[16 + (i >> 1)] = BEBIT(ks3, i); + } + for(i = 31; i >= 0; i -= 2) { + eks[i >> 1] = BEBIT(ks2, i); + eks[16 + (i >> 1)] = BEBIT(ks3, i); + } + + for(i = 0xfffff; i >= 0; --i) { + if (filter(i) != oks[0]) + continue; + + *(tail = table) = i; + for(j = 1; tail >= table && j < 29; ++j) + extend_table_simple(table, &tail, oks[j]); + + if(tail < table) + continue; + + for(j = 0; j < 19; ++j) + low = low << 1 | parity(i & S1[j]); + for(j = 0; j < 32; ++j) + hi[j] = parity(i & T1[j]); + + for(; tail >= table; --tail) { + for(j = 0; j < 3; ++j) { + *tail = *tail << 1; + *tail |= parity((i & C1[j]) ^ (*tail & C2[j])); + if(filter(*tail) != oks[29 + j]) + goto continue2; + } + + for(j = 0; j < 19; ++j) + win = win << 1 | parity(*tail & S2[j]); + + win ^= low; + for(j = 0; j < 32; ++j) { + win = win << 1 ^ hi[j] ^ parity(*tail & T2[j]); + if(filter(win) != eks[j]) + goto continue2; + } + + *tail = *tail << 1 | parity(LF_POLY_EVEN & *tail); + sl->odd = *tail ^ parity(LF_POLY_ODD & win); + sl->even = win; + ++sl; + sl->odd = sl->even = 0; + continue2:; + } + } + return statelist; +} + +/** lfsr_rollback_bit + * Rollback the shift register in order to get previous states + */ +uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb) +{ + int out; + uint8_t ret; + uint32_t t; + + s->odd &= 0xffffff; + t = s->odd, s->odd = s->even, s->even = t; + + out = s->even & 1; + out ^= LF_POLY_EVEN & (s->even >>= 1); + out ^= LF_POLY_ODD & s->odd; + out ^= !!in; + out ^= (ret = filter(s->odd)) & !!fb; + + s->even |= parity(out) << 23; + return ret; +} +/** lfsr_rollback_byte + * Rollback the shift register in order to get previous states + */ +uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb) +{ + /* + int i, ret = 0; + for (i = 7; i >= 0; --i) + ret |= lfsr_rollback_bit(s, BIT(in, i), fb) << i; +*/ +// unfold loop 20160112 + uint8_t ret = 0; + ret |= lfsr_rollback_bit(s, BIT(in, 7), fb) << 7; + ret |= lfsr_rollback_bit(s, BIT(in, 6), fb) << 6; + ret |= lfsr_rollback_bit(s, BIT(in, 5), fb) << 5; + ret |= lfsr_rollback_bit(s, BIT(in, 4), fb) << 4; + ret |= lfsr_rollback_bit(s, BIT(in, 3), fb) << 3; + ret |= lfsr_rollback_bit(s, BIT(in, 2), fb) << 2; + ret |= lfsr_rollback_bit(s, BIT(in, 1), fb) << 1; + ret |= lfsr_rollback_bit(s, BIT(in, 0), fb) << 0; + return ret; +} +/** lfsr_rollback_word + * Rollback the shift register in order to get previous states + */ +uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) +{ + /* + int i; + uint32_t ret = 0; + for (i = 31; i >= 0; --i) + ret |= lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24); +*/ +// unfold loop 20160112 + uint32_t ret = 0; + ret |= lfsr_rollback_bit(s, BEBIT(in, 31), fb) << (31 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 30), fb) << (30 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 29), fb) << (29 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 28), fb) << (28 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 27), fb) << (27 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 26), fb) << (26 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 25), fb) << (25 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 24), fb) << (24 ^ 24); + + ret |= lfsr_rollback_bit(s, BEBIT(in, 23), fb) << (23 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 22), fb) << (22 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 21), fb) << (21 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 20), fb) << (20 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 19), fb) << (19 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 18), fb) << (18 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 17), fb) << (17 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 16), fb) << (16 ^ 24); + + ret |= lfsr_rollback_bit(s, BEBIT(in, 15), fb) << (15 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 14), fb) << (14 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 13), fb) << (13 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 12), fb) << (12 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 11), fb) << (11 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 10), fb) << (10 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 9), fb) << (9 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 8), fb) << (8 ^ 24); + + ret |= lfsr_rollback_bit(s, BEBIT(in, 7), fb) << (7 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 6), fb) << (6 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 5), fb) << (5 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 4), fb) << (4 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 3), fb) << (3 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 2), fb) << (2 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 1), fb) << (1 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 0), fb) << (0 ^ 24); + return ret; +} + +/** nonce_distance + * x,y valid tag nonces, then prng_successor(x, nonce_distance(x, y)) = y + */ +static uint16_t *dist = 0; +int nonce_distance(uint32_t from, uint32_t to) +{ + uint16_t x, i; + if(!dist) { + dist = malloc(2 << 16); + if(!dist) + return -1; + for (x = i = 1; i; ++i) { + dist[(x & 0xff) << 8 | x >> 8] = i; + x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; + } + } + return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535; +} + + +static uint32_t fastfwd[2][8] = { + { 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB}, + { 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}}; + + +/** lfsr_prefix_ks + * + * Is an exported helper function from the common prefix attack + * Described in the "dark side" paper. It returns an -1 terminated array + * of possible partial(21 bit) secret state. + * The required keystream(ks) needs to contain the keystream that was used to + * encrypt the NACK which is observed when varying only the 3 last bits of Nr + * only correct iff [NR_3] ^ NR_3 does not depend on Nr_3 + */ +uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) +{ + uint32_t *candidates = malloc(4 << 10); + if(!candidates) return 0; + + uint32_t c, entry; + int size = 0, i, good; + + for(i = 0; i < 1 << 21; ++i) { + for(c = 0, good = 1; good && c < 8; ++c) { + entry = i ^ fastfwd[isodd][c]; + good &= (BIT(ks[c], isodd) == filter(entry >> 1)); + good &= (BIT(ks[c], isodd + 2) == filter(entry)); + } + if(good) + candidates[size++] = i; + } + + candidates[size] = -1; + + return candidates; +} + +/** check_pfx_parity + * helper function which eliminates possible secret states using parity bits + */ +static struct Crypto1State* check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8], uint32_t odd, uint32_t even, struct Crypto1State* sl) +{ + uint32_t ks1, nr, ks2, rr, ks3, c, good = 1; + + for(c = 0; good && c < 8; ++c) { + sl->odd = odd ^ fastfwd[1][c]; + sl->even = even ^ fastfwd[0][c]; + + lfsr_rollback_bit(sl, 0, 0); + lfsr_rollback_bit(sl, 0, 0); + + ks3 = lfsr_rollback_bit(sl, 0, 0); + ks2 = lfsr_rollback_word(sl, 0, 0); + ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1); + + nr = ks1 ^ (prefix | c << 5); + rr = ks2 ^ rresp; + + good &= parity(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); + good &= parity(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); + good &= parity(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8); + good &= parity(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0); + good &= parity(rr & 0x000000ff) ^ parities[c][7] ^ ks3; + } + + return sl + good; +} + +/** lfsr_common_prefix + * Implentation of the common prefix attack. + * Requires the 28 bit constant prefix used as reader nonce (pfx) + * The reader response used (rr) + * The keystream used to encrypt the observed NACK's (ks) + * The parity bits (par) + * It returns a zero terminated list of possible cipher states after the + * tag nonce was fed in + */ + +struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]) +{ + struct Crypto1State *statelist, *s; + uint32_t *odd, *even, *o, *e, top; + + odd = lfsr_prefix_ks(ks, 1); + even = lfsr_prefix_ks(ks, 0); + + s = statelist = malloc((sizeof *statelist) << 24); + if(!s || !odd || !even) { + free(statelist); + statelist = 0; + goto out; + } + + for(o = odd; *o + 1; ++o) + for(e = even; *e + 1; ++e) + for(top = 0; top < 64; ++top) { + *o += 1 << 21; + *e += (!(top & 7) + 1) << 21; + s = check_pfx_parity(pfx, rr, par, *o, *e, s); + } + + s->odd = s->even = 0; +out: + free(odd); + free(even); + return statelist; +} diff --git a/tools/nonce2key/crapto1.c b/tools/nonce2key/crapto1.c index 1d854d96b..fcfa931c4 100644 --- a/tools/nonce2key/crapto1.c +++ b/tools/nonce2key/crapto1.c @@ -1,573 +1,573 @@ -/* crapto1.c - - 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, US$ - - Copyright (C) 2008-2014 bla -*/ -#include "crapto1.h" -#include - -#if !defined LOWMEM && defined __GNUC__ -static uint8_t filterlut[1 << 20]; -static void __attribute__((constructor)) fill_lut() -{ - uint32_t i; - for(i = 0; i < 1 << 20; ++i) - filterlut[i] = filter(i); -} -#define filter(x) (filterlut[(x) & 0xfffff]) -#endif - - - -typedef struct bucket { - uint32_t *head; - uint32_t *bp; -} bucket_t; - -typedef bucket_t bucket_array_t[2][0x100]; - -typedef struct bucket_info { - struct { - uint32_t *head, *tail; - } bucket_info[2][0x100]; - uint32_t numbuckets; - } bucket_info_t; - - -static void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop, - uint32_t* const ostart, uint32_t* const ostop, - bucket_info_t *bucket_info, bucket_array_t bucket) -{ - uint32_t *p1, *p2; - uint32_t *start[2]; - uint32_t *stop[2]; - - start[0] = estart; - stop[0] = estop; - start[1] = ostart; - stop[1] = ostop; - - // init buckets to be empty - for (uint32_t i = 0; i < 2; i++) { - for (uint32_t j = 0x00; j <= 0xff; j++) { - bucket[i][j].bp = bucket[i][j].head; - } - } - - // sort the lists into the buckets based on the MSB (contribution bits) - for (uint32_t i = 0; i < 2; i++) { - for (p1 = start[i]; p1 <= stop[i]; p1++) { - uint32_t bucket_index = (*p1 & 0xff000000) >> 24; - *(bucket[i][bucket_index].bp++) = *p1; - } - } - - - // write back intersecting buckets as sorted list. - // fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets. - uint32_t nonempty_bucket; - for (uint32_t i = 0; i < 2; i++) { - p1 = start[i]; - nonempty_bucket = 0; - for (uint32_t j = 0x00; j <= 0xff; j++) { - if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only - bucket_info->bucket_info[i][nonempty_bucket].head = p1; - for (p2 = bucket[i][j].head; p2 < bucket[i][j].bp; *p1++ = *p2++); - bucket_info->bucket_info[i][nonempty_bucket].tail = p1 - 1; - nonempty_bucket++; - } - } - bucket_info->numbuckets = nonempty_bucket; - } -} - -/** update_contribution - * helper, calculates the partial linear feedback contributions and puts in MSB - */ -static inline void update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2) -{ - uint32_t p = *item >> 25; - - p = p << 1 | parity(*item & mask1); - p = p << 1 | parity(*item & mask2); - *item = p << 24 | (*item & 0xffffff); -} - -/** extend_table - * using a bit of the keystream extend the table of possible lfsr states - */ -static inline void extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in) -{ - in <<= 24; - for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) - if(filter(*tbl) ^ filter(*tbl | 1)) { - *tbl |= filter(*tbl) ^ bit; - update_contribution(tbl, m1, m2); - *tbl ^= in; - } else if(filter(*tbl) == bit) { - *++*end = tbl[1]; - tbl[1] = tbl[0] | 1; - update_contribution(tbl, m1, m2); - *tbl++ ^= in; - update_contribution(tbl, m1, m2); - *tbl ^= in; - } else - *tbl-- = *(*end)--; -} -/** extend_table_simple - * using a bit of the keystream extend the table of possible lfsr states - */ -static inline void extend_table_simple(uint32_t *tbl, uint32_t **end, int bit) -{ - for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) { - if(filter(*tbl) ^ filter(*tbl | 1)) { // replace - *tbl |= filter(*tbl) ^ bit; - } else if(filter(*tbl) == bit) { // insert - *++*end = *++tbl; - *tbl = tbl[-1] | 1; - } else { // drop - *tbl-- = *(*end)--; - } - } -} -/** recover - * recursively narrow down the search space, 4 bits of keystream at a time - */ -static struct Crypto1State* -recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks, - uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem, - struct Crypto1State *sl, uint32_t in, bucket_array_t bucket) -{ - uint32_t *o, *e; - bucket_info_t bucket_info; - - if(rem == -1) { - for(e = e_head; e <= e_tail; ++e) { - *e = *e << 1 ^ parity(*e & LF_POLY_EVEN) ^ !!(in & 4); - for(o = o_head; o <= o_tail; ++o, ++sl) { - sl->even = *o; - sl->odd = *e ^ parity(*o & LF_POLY_ODD); - sl[1].odd = sl[1].even = 0; - } - } - return sl; - } - - for(uint32_t i = 0; i < 4 && rem--; i++) { - oks >>= 1; - eks >>= 1; - in >>= 2; - extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0); - if(o_head > o_tail) - return sl; - - extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, in & 3); - if(e_head > e_tail) - return sl; - } - - bucket_sort_intersect(e_head, e_tail, o_head, o_tail, &bucket_info, bucket); - - for (int i = bucket_info.numbuckets - 1; i >= 0; i--) { - sl = recover(bucket_info.bucket_info[1][i].head, bucket_info.bucket_info[1][i].tail, oks, - bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks, - rem, sl, in, bucket); - } - - return sl; -} -/** lfsr_recovery - * recover the state of the lfsr given 32 bits of the keystream - * additionally you can use the in parameter to specify the value - * that was fed into the lfsr at the time the keystream was generated - */ -struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in) -{ - struct Crypto1State *statelist; - uint32_t *odd_head = 0, *odd_tail = 0, oks = 0; - uint32_t *even_head = 0, *even_tail = 0, eks = 0; - int i; - - // split the keystream into an odd and even part - for(i = 31; i >= 0; i -= 2) - oks = oks << 1 | BEBIT(ks2, i); - for(i = 30; i >= 0; i -= 2) - eks = eks << 1 | BEBIT(ks2, i); - - odd_head = odd_tail = malloc(sizeof(uint32_t) << 21); - even_head = even_tail = malloc(sizeof(uint32_t) << 21); - statelist = malloc(sizeof(struct Crypto1State) << 18); - if(!odd_tail-- || !even_tail-- || !statelist) { - free(statelist); - statelist = 0; - goto out; - } - - statelist->odd = statelist->even = 0; - - // allocate memory for out of place bucket_sort - bucket_array_t bucket; - - for (uint32_t i = 0; i < 2; i++) { - for (uint32_t j = 0; j <= 0xff; j++) { - bucket[i][j].head = malloc(sizeof(uint32_t)<<14); - if (!bucket[i][j].head) { - goto out; - } - } - } - - // initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream - for(i = 1 << 20; i >= 0; --i) { - if(filter(i) == (oks & 1)) - *++odd_tail = i; - if(filter(i) == (eks & 1)) - *++even_tail = i; - } - - // extend the statelists. Look at the next 8 Bits of the keystream (4 Bit each odd and even): - for(i = 0; i < 4; i++) { - extend_table_simple(odd_head, &odd_tail, (oks >>= 1) & 1); - extend_table_simple(even_head, &even_tail, (eks >>= 1) & 1); - } - - // the statelists now contain all states which could have generated the last 10 Bits of the keystream. - // 22 bits to go to recover 32 bits in total. From now on, we need to take the "in" - // parameter into account. - in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping - recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket); - -out: - for (uint32_t i = 0; i < 2; i++) - for (uint32_t j = 0; j <= 0xff; j++) - free(bucket[i][j].head); - free(odd_head); - free(even_head); - return statelist; -} - -static const uint32_t S1[] = { 0x62141, 0x310A0, 0x18850, 0x0C428, 0x06214, - 0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83, - 0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA}; -static const uint32_t S2[] = { 0x3A557B00, 0x5D2ABD80, 0x2E955EC0, 0x174AAF60, - 0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8, - 0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20, - 0x7EC7EE90, 0x7F63F748, 0x79117020}; -static const uint32_t T1[] = { - 0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66, - 0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B, - 0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615, - 0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C}; -static const uint32_t T2[] = { 0x3C88B810, 0x5E445C08, 0x2982A580, 0x14C152C0, - 0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268, - 0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0, - 0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0, - 0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950, - 0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0}; -static const uint32_t C1[] = { 0x846B5, 0x4235A, 0x211AD}; -static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0}; -/** Reverse 64 bits of keystream into possible cipher states - * Variation mentioned in the paper. Somewhat optimized version - */ -struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3) -{ - struct Crypto1State *statelist, *sl; - uint8_t oks[32], eks[32], hi[32]; - uint32_t low = 0, win = 0; - uint32_t *tail, table[1 << 16]; - int i, j; - - sl = statelist = malloc(sizeof(struct Crypto1State) << 4); - if(!sl) - return 0; - sl->odd = sl->even = 0; - - for(i = 30; i >= 0; i -= 2) { - oks[i >> 1] = BEBIT(ks2, i); - oks[16 + (i >> 1)] = BEBIT(ks3, i); - } - for(i = 31; i >= 0; i -= 2) { - eks[i >> 1] = BEBIT(ks2, i); - eks[16 + (i >> 1)] = BEBIT(ks3, i); - } - - for(i = 0xfffff; i >= 0; --i) { - if (filter(i) != oks[0]) - continue; - - *(tail = table) = i; - for(j = 1; tail >= table && j < 29; ++j) - extend_table_simple(table, &tail, oks[j]); - - if(tail < table) - continue; - - for(j = 0; j < 19; ++j) - low = low << 1 | parity(i & S1[j]); - for(j = 0; j < 32; ++j) - hi[j] = parity(i & T1[j]); - - for(; tail >= table; --tail) { - for(j = 0; j < 3; ++j) { - *tail = *tail << 1; - *tail |= parity((i & C1[j]) ^ (*tail & C2[j])); - if(filter(*tail) != oks[29 + j]) - goto continue2; - } - - for(j = 0; j < 19; ++j) - win = win << 1 | parity(*tail & S2[j]); - - win ^= low; - for(j = 0; j < 32; ++j) { - win = win << 1 ^ hi[j] ^ parity(*tail & T2[j]); - if(filter(win) != eks[j]) - goto continue2; - } - - *tail = *tail << 1 | parity(LF_POLY_EVEN & *tail); - sl->odd = *tail ^ parity(LF_POLY_ODD & win); - sl->even = win; - ++sl; - sl->odd = sl->even = 0; - continue2:; - } - } - return statelist; -} - -/** lfsr_rollback_bit - * Rollback the shift register in order to get previous states - */ -uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb) -{ - int out; - uint8_t ret; - uint32_t t; - - s->odd &= 0xffffff; - t = s->odd, s->odd = s->even, s->even = t; - - out = s->even & 1; - out ^= LF_POLY_EVEN & (s->even >>= 1); - out ^= LF_POLY_ODD & s->odd; - out ^= !!in; - out ^= (ret = filter(s->odd)) & !!fb; - - s->even |= parity(out) << 23; - return ret; -} -/** lfsr_rollback_byte - * Rollback the shift register in order to get previous states - */ -uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb) -{ - /* - int i, ret = 0; - for (i = 7; i >= 0; --i) - ret |= lfsr_rollback_bit(s, BIT(in, i), fb) << i; -*/ -// unfold loop 20160112 - uint8_t ret = 0; - ret |= lfsr_rollback_bit(s, BIT(in, 7), fb) << 7; - ret |= lfsr_rollback_bit(s, BIT(in, 6), fb) << 6; - ret |= lfsr_rollback_bit(s, BIT(in, 5), fb) << 5; - ret |= lfsr_rollback_bit(s, BIT(in, 4), fb) << 4; - ret |= lfsr_rollback_bit(s, BIT(in, 3), fb) << 3; - ret |= lfsr_rollback_bit(s, BIT(in, 2), fb) << 2; - ret |= lfsr_rollback_bit(s, BIT(in, 1), fb) << 1; - ret |= lfsr_rollback_bit(s, BIT(in, 0), fb) << 0; - return ret; -} -/** lfsr_rollback_word - * Rollback the shift register in order to get previous states - */ -uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) -{ - /* - int i; - uint32_t ret = 0; - for (i = 31; i >= 0; --i) - ret |= lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24); -*/ -// unfold loop 20160112 - uint32_t ret = 0; - ret |= lfsr_rollback_bit(s, BEBIT(in, 31), fb) << (31 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 30), fb) << (30 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 29), fb) << (29 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 28), fb) << (28 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 27), fb) << (27 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 26), fb) << (26 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 25), fb) << (25 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 24), fb) << (24 ^ 24); - - ret |= lfsr_rollback_bit(s, BEBIT(in, 23), fb) << (23 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 22), fb) << (22 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 21), fb) << (21 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 20), fb) << (20 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 19), fb) << (19 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 18), fb) << (18 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 17), fb) << (17 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 16), fb) << (16 ^ 24); - - ret |= lfsr_rollback_bit(s, BEBIT(in, 15), fb) << (15 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 14), fb) << (14 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 13), fb) << (13 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 12), fb) << (12 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 11), fb) << (11 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 10), fb) << (10 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 9), fb) << (9 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 8), fb) << (8 ^ 24); - - ret |= lfsr_rollback_bit(s, BEBIT(in, 7), fb) << (7 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 6), fb) << (6 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 5), fb) << (5 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 4), fb) << (4 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 3), fb) << (3 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 2), fb) << (2 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 1), fb) << (1 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 0), fb) << (0 ^ 24); - return ret; -} - -/** nonce_distance - * x,y valid tag nonces, then prng_successor(x, nonce_distance(x, y)) = y - */ -static uint16_t *dist = 0; -int nonce_distance(uint32_t from, uint32_t to) -{ - uint16_t x, i; - if(!dist) { - dist = malloc(2 << 16); - if(!dist) - return -1; - for (x = i = 1; i; ++i) { - dist[(x & 0xff) << 8 | x >> 8] = i; - x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; - } - } - return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535; -} - - -static uint32_t fastfwd[2][8] = { - { 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB}, - { 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}}; - - -/** lfsr_prefix_ks - * - * Is an exported helper function from the common prefix attack - * Described in the "dark side" paper. It returns an -1 terminated array - * of possible partial(21 bit) secret state. - * The required keystream(ks) needs to contain the keystream that was used to - * encrypt the NACK which is observed when varying only the 3 last bits of Nr - * only correct iff [NR_3] ^ NR_3 does not depend on Nr_3 - */ -uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) -{ - uint32_t *candidates = malloc(4 << 10); - if(!candidates) return 0; - - uint32_t c, entry; - int size = 0, i, good; - - for(i = 0; i < 1 << 21; ++i) { - for(c = 0, good = 1; good && c < 8; ++c) { - entry = i ^ fastfwd[isodd][c]; - good &= (BIT(ks[c], isodd) == filter(entry >> 1)); - good &= (BIT(ks[c], isodd + 2) == filter(entry)); - } - if(good) - candidates[size++] = i; - } - - candidates[size] = -1; - - return candidates; -} - -/** check_pfx_parity - * helper function which eliminates possible secret states using parity bits - */ -static struct Crypto1State* check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8], uint32_t odd, uint32_t even, struct Crypto1State* sl) -{ - uint32_t ks1, nr, ks2, rr, ks3, c, good = 1; - - for(c = 0; good && c < 8; ++c) { - sl->odd = odd ^ fastfwd[1][c]; - sl->even = even ^ fastfwd[0][c]; - - lfsr_rollback_bit(sl, 0, 0); - lfsr_rollback_bit(sl, 0, 0); - - ks3 = lfsr_rollback_bit(sl, 0, 0); - ks2 = lfsr_rollback_word(sl, 0, 0); - ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1); - - nr = ks1 ^ (prefix | c << 5); - rr = ks2 ^ rresp; - - good &= parity(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); - good &= parity(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); - good &= parity(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8); - good &= parity(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0); - good &= parity(rr & 0x000000ff) ^ parities[c][7] ^ ks3; - } - - return sl + good; -} - -/** lfsr_common_prefix - * Implentation of the common prefix attack. - * Requires the 28 bit constant prefix used as reader nonce (pfx) - * The reader response used (rr) - * The keystream used to encrypt the observed NACK's (ks) - * The parity bits (par) - * It returns a zero terminated list of possible cipher states after the - * tag nonce was fed in - */ - -struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]) -{ - struct Crypto1State *statelist, *s; - uint32_t *odd, *even, *o, *e, top; - - odd = lfsr_prefix_ks(ks, 1); - even = lfsr_prefix_ks(ks, 0); - - s = statelist = malloc((sizeof *statelist) << 20); - if(!s || !odd || !even) { - free(statelist); - statelist = 0; - goto out; - } - - for(o = odd; *o + 1; ++o) - for(e = even; *e + 1; ++e) - for(top = 0; top < 64; ++top) { - *o += 1 << 21; - *e += (!(top & 7) + 1) << 21; - s = check_pfx_parity(pfx, rr, par, *o, *e, s); - } - - s->odd = s->even = 0; -out: - free(odd); - free(even); - return statelist; -} +/* crapto1.c + + 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, US$ + + Copyright (C) 2008-2014 bla +*/ +#include "crapto1.h" +#include + +#if !defined LOWMEM && defined __GNUC__ +static uint8_t filterlut[1 << 20]; +static void __attribute__((constructor)) fill_lut() +{ + uint32_t i; + for(i = 0; i < 1 << 20; ++i) + filterlut[i] = filter(i); +} +#define filter(x) (filterlut[(x) & 0xfffff]) +#endif + + + +typedef struct bucket { + uint32_t *head; + uint32_t *bp; +} bucket_t; + +typedef bucket_t bucket_array_t[2][0x100]; + +typedef struct bucket_info { + struct { + uint32_t *head, *tail; + } bucket_info[2][0x100]; + uint32_t numbuckets; + } bucket_info_t; + + +static void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop, + uint32_t* const ostart, uint32_t* const ostop, + bucket_info_t *bucket_info, bucket_array_t bucket) +{ + uint32_t *p1, *p2; + uint32_t *start[2]; + uint32_t *stop[2]; + + start[0] = estart; + stop[0] = estop; + start[1] = ostart; + stop[1] = ostop; + + // init buckets to be empty + for (uint32_t i = 0; i < 2; i++) { + for (uint32_t j = 0x00; j <= 0xff; j++) { + bucket[i][j].bp = bucket[i][j].head; + } + } + + // sort the lists into the buckets based on the MSB (contribution bits) + for (uint32_t i = 0; i < 2; i++) { + for (p1 = start[i]; p1 <= stop[i]; p1++) { + uint32_t bucket_index = (*p1 & 0xff000000) >> 24; + *(bucket[i][bucket_index].bp++) = *p1; + } + } + + + // write back intersecting buckets as sorted list. + // fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets. + uint32_t nonempty_bucket; + for (uint32_t i = 0; i < 2; i++) { + p1 = start[i]; + nonempty_bucket = 0; + for (uint32_t j = 0x00; j <= 0xff; j++) { + if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only + bucket_info->bucket_info[i][nonempty_bucket].head = p1; + for (p2 = bucket[i][j].head; p2 < bucket[i][j].bp; *p1++ = *p2++); + bucket_info->bucket_info[i][nonempty_bucket].tail = p1 - 1; + nonempty_bucket++; + } + } + bucket_info->numbuckets = nonempty_bucket; + } +} + +/** update_contribution + * helper, calculates the partial linear feedback contributions and puts in MSB + */ +static inline void update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2) +{ + uint32_t p = *item >> 25; + + p = p << 1 | parity(*item & mask1); + p = p << 1 | parity(*item & mask2); + *item = p << 24 | (*item & 0xffffff); +} + +/** extend_table + * using a bit of the keystream extend the table of possible lfsr states + */ +static inline void extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in) +{ + in <<= 24; + for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) + if(filter(*tbl) ^ filter(*tbl | 1)) { + *tbl |= filter(*tbl) ^ bit; + update_contribution(tbl, m1, m2); + *tbl ^= in; + } else if(filter(*tbl) == bit) { + *++*end = tbl[1]; + tbl[1] = tbl[0] | 1; + update_contribution(tbl, m1, m2); + *tbl++ ^= in; + update_contribution(tbl, m1, m2); + *tbl ^= in; + } else + *tbl-- = *(*end)--; +} +/** extend_table_simple + * using a bit of the keystream extend the table of possible lfsr states + */ +static inline void extend_table_simple(uint32_t *tbl, uint32_t **end, int bit) +{ + for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) { + if(filter(*tbl) ^ filter(*tbl | 1)) { // replace + *tbl |= filter(*tbl) ^ bit; + } else if(filter(*tbl) == bit) { // insert + *++*end = *++tbl; + *tbl = tbl[-1] | 1; + } else { // drop + *tbl-- = *(*end)--; + } + } +} +/** recover + * recursively narrow down the search space, 4 bits of keystream at a time + */ +static struct Crypto1State* +recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks, + uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem, + struct Crypto1State *sl, uint32_t in, bucket_array_t bucket) +{ + uint32_t *o, *e; + bucket_info_t bucket_info; + + if(rem == -1) { + for(e = e_head; e <= e_tail; ++e) { + *e = *e << 1 ^ parity(*e & LF_POLY_EVEN) ^ !!(in & 4); + for(o = o_head; o <= o_tail; ++o, ++sl) { + sl->even = *o; + sl->odd = *e ^ parity(*o & LF_POLY_ODD); + sl[1].odd = sl[1].even = 0; + } + } + return sl; + } + + for(uint32_t i = 0; i < 4 && rem--; i++) { + oks >>= 1; + eks >>= 1; + in >>= 2; + extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0); + if(o_head > o_tail) + return sl; + + extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, in & 3); + if(e_head > e_tail) + return sl; + } + + bucket_sort_intersect(e_head, e_tail, o_head, o_tail, &bucket_info, bucket); + + for (int i = bucket_info.numbuckets - 1; i >= 0; i--) { + sl = recover(bucket_info.bucket_info[1][i].head, bucket_info.bucket_info[1][i].tail, oks, + bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks, + rem, sl, in, bucket); + } + + return sl; +} +/** lfsr_recovery + * recover the state of the lfsr given 32 bits of the keystream + * additionally you can use the in parameter to specify the value + * that was fed into the lfsr at the time the keystream was generated + */ +struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in) +{ + struct Crypto1State *statelist; + uint32_t *odd_head = 0, *odd_tail = 0, oks = 0; + uint32_t *even_head = 0, *even_tail = 0, eks = 0; + int i; + + // split the keystream into an odd and even part + for(i = 31; i >= 0; i -= 2) + oks = oks << 1 | BEBIT(ks2, i); + for(i = 30; i >= 0; i -= 2) + eks = eks << 1 | BEBIT(ks2, i); + + odd_head = odd_tail = malloc(sizeof(uint32_t) << 21); + even_head = even_tail = malloc(sizeof(uint32_t) << 21); + statelist = malloc(sizeof(struct Crypto1State) << 18); + if(!odd_tail-- || !even_tail-- || !statelist) { + free(statelist); + statelist = 0; + goto out; + } + + statelist->odd = statelist->even = 0; + + // allocate memory for out of place bucket_sort + bucket_array_t bucket; + + for (uint32_t i = 0; i < 2; i++) { + for (uint32_t j = 0; j <= 0xff; j++) { + bucket[i][j].head = malloc(sizeof(uint32_t)<<14); + if (!bucket[i][j].head) { + goto out; + } + } + } + + // initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream + for(i = 1 << 20; i >= 0; --i) { + if(filter(i) == (oks & 1)) + *++odd_tail = i; + if(filter(i) == (eks & 1)) + *++even_tail = i; + } + + // extend the statelists. Look at the next 8 Bits of the keystream (4 Bit each odd and even): + for(i = 0; i < 4; i++) { + extend_table_simple(odd_head, &odd_tail, (oks >>= 1) & 1); + extend_table_simple(even_head, &even_tail, (eks >>= 1) & 1); + } + + // the statelists now contain all states which could have generated the last 10 Bits of the keystream. + // 22 bits to go to recover 32 bits in total. From now on, we need to take the "in" + // parameter into account. + in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping + recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket); + +out: + for (uint32_t i = 0; i < 2; i++) + for (uint32_t j = 0; j <= 0xff; j++) + free(bucket[i][j].head); + free(odd_head); + free(even_head); + return statelist; +} + +static const uint32_t S1[] = { 0x62141, 0x310A0, 0x18850, 0x0C428, 0x06214, + 0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83, + 0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA}; +static const uint32_t S2[] = { 0x3A557B00, 0x5D2ABD80, 0x2E955EC0, 0x174AAF60, + 0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8, + 0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20, + 0x7EC7EE90, 0x7F63F748, 0x79117020}; +static const uint32_t T1[] = { + 0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66, + 0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B, + 0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615, + 0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C}; +static const uint32_t T2[] = { 0x3C88B810, 0x5E445C08, 0x2982A580, 0x14C152C0, + 0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268, + 0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0, + 0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0, + 0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950, + 0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0}; +static const uint32_t C1[] = { 0x846B5, 0x4235A, 0x211AD}; +static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0}; +/** Reverse 64 bits of keystream into possible cipher states + * Variation mentioned in the paper. Somewhat optimized version + */ +struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3) +{ + struct Crypto1State *statelist, *sl; + uint8_t oks[32], eks[32], hi[32]; + uint32_t low = 0, win = 0; + uint32_t *tail, table[1 << 16]; + int i, j; + + sl = statelist = malloc(sizeof(struct Crypto1State) << 4); + if(!sl) + return 0; + sl->odd = sl->even = 0; + + for(i = 30; i >= 0; i -= 2) { + oks[i >> 1] = BEBIT(ks2, i); + oks[16 + (i >> 1)] = BEBIT(ks3, i); + } + for(i = 31; i >= 0; i -= 2) { + eks[i >> 1] = BEBIT(ks2, i); + eks[16 + (i >> 1)] = BEBIT(ks3, i); + } + + for(i = 0xfffff; i >= 0; --i) { + if (filter(i) != oks[0]) + continue; + + *(tail = table) = i; + for(j = 1; tail >= table && j < 29; ++j) + extend_table_simple(table, &tail, oks[j]); + + if(tail < table) + continue; + + for(j = 0; j < 19; ++j) + low = low << 1 | parity(i & S1[j]); + for(j = 0; j < 32; ++j) + hi[j] = parity(i & T1[j]); + + for(; tail >= table; --tail) { + for(j = 0; j < 3; ++j) { + *tail = *tail << 1; + *tail |= parity((i & C1[j]) ^ (*tail & C2[j])); + if(filter(*tail) != oks[29 + j]) + goto continue2; + } + + for(j = 0; j < 19; ++j) + win = win << 1 | parity(*tail & S2[j]); + + win ^= low; + for(j = 0; j < 32; ++j) { + win = win << 1 ^ hi[j] ^ parity(*tail & T2[j]); + if(filter(win) != eks[j]) + goto continue2; + } + + *tail = *tail << 1 | parity(LF_POLY_EVEN & *tail); + sl->odd = *tail ^ parity(LF_POLY_ODD & win); + sl->even = win; + ++sl; + sl->odd = sl->even = 0; + continue2:; + } + } + return statelist; +} + +/** lfsr_rollback_bit + * Rollback the shift register in order to get previous states + */ +uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb) +{ + int out; + uint8_t ret; + uint32_t t; + + s->odd &= 0xffffff; + t = s->odd, s->odd = s->even, s->even = t; + + out = s->even & 1; + out ^= LF_POLY_EVEN & (s->even >>= 1); + out ^= LF_POLY_ODD & s->odd; + out ^= !!in; + out ^= (ret = filter(s->odd)) & !!fb; + + s->even |= parity(out) << 23; + return ret; +} +/** lfsr_rollback_byte + * Rollback the shift register in order to get previous states + */ +uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb) +{ + /* + int i, ret = 0; + for (i = 7; i >= 0; --i) + ret |= lfsr_rollback_bit(s, BIT(in, i), fb) << i; +*/ +// unfold loop 20160112 + uint8_t ret = 0; + ret |= lfsr_rollback_bit(s, BIT(in, 7), fb) << 7; + ret |= lfsr_rollback_bit(s, BIT(in, 6), fb) << 6; + ret |= lfsr_rollback_bit(s, BIT(in, 5), fb) << 5; + ret |= lfsr_rollback_bit(s, BIT(in, 4), fb) << 4; + ret |= lfsr_rollback_bit(s, BIT(in, 3), fb) << 3; + ret |= lfsr_rollback_bit(s, BIT(in, 2), fb) << 2; + ret |= lfsr_rollback_bit(s, BIT(in, 1), fb) << 1; + ret |= lfsr_rollback_bit(s, BIT(in, 0), fb) << 0; + return ret; +} +/** lfsr_rollback_word + * Rollback the shift register in order to get previous states + */ +uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) +{ + /* + int i; + uint32_t ret = 0; + for (i = 31; i >= 0; --i) + ret |= lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24); +*/ +// unfold loop 20160112 + uint32_t ret = 0; + ret |= lfsr_rollback_bit(s, BEBIT(in, 31), fb) << (31 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 30), fb) << (30 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 29), fb) << (29 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 28), fb) << (28 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 27), fb) << (27 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 26), fb) << (26 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 25), fb) << (25 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 24), fb) << (24 ^ 24); + + ret |= lfsr_rollback_bit(s, BEBIT(in, 23), fb) << (23 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 22), fb) << (22 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 21), fb) << (21 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 20), fb) << (20 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 19), fb) << (19 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 18), fb) << (18 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 17), fb) << (17 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 16), fb) << (16 ^ 24); + + ret |= lfsr_rollback_bit(s, BEBIT(in, 15), fb) << (15 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 14), fb) << (14 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 13), fb) << (13 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 12), fb) << (12 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 11), fb) << (11 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 10), fb) << (10 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 9), fb) << (9 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 8), fb) << (8 ^ 24); + + ret |= lfsr_rollback_bit(s, BEBIT(in, 7), fb) << (7 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 6), fb) << (6 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 5), fb) << (5 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 4), fb) << (4 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 3), fb) << (3 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 2), fb) << (2 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 1), fb) << (1 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 0), fb) << (0 ^ 24); + return ret; +} + +/** nonce_distance + * x,y valid tag nonces, then prng_successor(x, nonce_distance(x, y)) = y + */ +static uint16_t *dist = 0; +int nonce_distance(uint32_t from, uint32_t to) +{ + uint16_t x, i; + if(!dist) { + dist = malloc(2 << 16); + if(!dist) + return -1; + for (x = i = 1; i; ++i) { + dist[(x & 0xff) << 8 | x >> 8] = i; + x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; + } + } + return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535; +} + + +static uint32_t fastfwd[2][8] = { + { 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB}, + { 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}}; + + +/** lfsr_prefix_ks + * + * Is an exported helper function from the common prefix attack + * Described in the "dark side" paper. It returns an -1 terminated array + * of possible partial(21 bit) secret state. + * The required keystream(ks) needs to contain the keystream that was used to + * encrypt the NACK which is observed when varying only the 3 last bits of Nr + * only correct iff [NR_3] ^ NR_3 does not depend on Nr_3 + */ +uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) +{ + uint32_t *candidates = malloc(4 << 10); + if(!candidates) return 0; + + uint32_t c, entry; + int size = 0, i, good; + + for(i = 0; i < 1 << 21; ++i) { + for(c = 0, good = 1; good && c < 8; ++c) { + entry = i ^ fastfwd[isodd][c]; + good &= (BIT(ks[c], isodd) == filter(entry >> 1)); + good &= (BIT(ks[c], isodd + 2) == filter(entry)); + } + if(good) + candidates[size++] = i; + } + + candidates[size] = -1; + + return candidates; +} + +/** check_pfx_parity + * helper function which eliminates possible secret states using parity bits + */ +static struct Crypto1State* check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8], uint32_t odd, uint32_t even, struct Crypto1State* sl) +{ + uint32_t ks1, nr, ks2, rr, ks3, c, good = 1; + + for(c = 0; good && c < 8; ++c) { + sl->odd = odd ^ fastfwd[1][c]; + sl->even = even ^ fastfwd[0][c]; + + lfsr_rollback_bit(sl, 0, 0); + lfsr_rollback_bit(sl, 0, 0); + + ks3 = lfsr_rollback_bit(sl, 0, 0); + ks2 = lfsr_rollback_word(sl, 0, 0); + ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1); + + nr = ks1 ^ (prefix | c << 5); + rr = ks2 ^ rresp; + + good &= parity(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); + good &= parity(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); + good &= parity(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8); + good &= parity(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0); + good &= parity(rr & 0x000000ff) ^ parities[c][7] ^ ks3; + } + + return sl + good; +} + +/** lfsr_common_prefix + * Implentation of the common prefix attack. + * Requires the 28 bit constant prefix used as reader nonce (pfx) + * The reader response used (rr) + * The keystream used to encrypt the observed NACK's (ks) + * The parity bits (par) + * It returns a zero terminated list of possible cipher states after the + * tag nonce was fed in + */ + +struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]) +{ + struct Crypto1State *statelist, *s; + uint32_t *odd, *even, *o, *e, top; + + odd = lfsr_prefix_ks(ks, 1); + even = lfsr_prefix_ks(ks, 0); + + s = statelist = malloc((sizeof *statelist) << 20); + if(!s || !odd || !even) { + free(statelist); + statelist = 0; + goto out; + } + + for(o = odd; *o + 1; ++o) + for(e = even; *e + 1; ++e) + for(top = 0; top < 64; ++top) { + *o += 1 << 21; + *e += (!(top & 7) + 1) << 21; + s = check_pfx_parity(pfx, rr, par, *o, *e, s); + } + + s->odd = s->even = 0; +out: + free(odd); + free(even); + return statelist; +} From 60f292b18e3862b5dbb6387425bfb1447f03731e Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 08:59:13 +0100 Subject: [PATCH 0680/1938] remove spurious spaces & tabs at end of lines --- armsrc/BigBuf.c | 12 +- armsrc/BigBuf.h | 2 +- armsrc/LCD.c | 4 +- armsrc/Standalone/hf_bog.c | 114 +-- armsrc/Standalone/hf_colin.c | 6 +- armsrc/Standalone/hf_mattyrun.c | 34 +- armsrc/Standalone/hf_young.c | 40 +- armsrc/Standalone/hf_young.h | 2 +- armsrc/Standalone/lf_hidbrute.c | 74 +- armsrc/Standalone/lf_proxbrute.c | 24 +- armsrc/Standalone/lf_samyrun.c | 30 +- armsrc/appmain.c | 274 +++---- armsrc/apps.h | 4 +- armsrc/buzzer.c | 20 +- armsrc/des.c | 88 +-- armsrc/des.h | 22 +- armsrc/desfire_crypto.c | 24 +- armsrc/desfire_key.c | 6 +- armsrc/epa.c | 2 +- armsrc/felica.c | 226 +++--- armsrc/flashmem.c | 86 +-- armsrc/fpgaloader.c | 28 +- armsrc/fpgaloader.h | 6 +- armsrc/hfsnoop.c | 22 +- armsrc/hitag2.c | 288 +++---- armsrc/hitagS.c | 84 +- armsrc/iclass.c | 394 +++++----- armsrc/iso14443a.c | 756 +++++++++--------- armsrc/iso14443a.h | 4 +- armsrc/iso14443b.c | 388 +++++----- armsrc/iso15693.c | 254 +++---- armsrc/lfops.c | 82 +- armsrc/lfsampling.c | 106 +-- armsrc/mifarecmd.c | 508 ++++++------- armsrc/mifaredesfire.c | 206 ++--- armsrc/mifaresniff.c | 76 +- armsrc/mifareutil.c | 112 +-- armsrc/mifareutil.h | 4 +- armsrc/optimized_cipher.c | 24 +- armsrc/pcf7931.c | 52 +- armsrc/start.c | 8 +- armsrc/ticks.c | 34 +- armsrc/util.c | 6 +- bootrom/bootrom.c | 48 +- client/amiitool/amiibo.c | 10 +- client/amiitool/amiitool.c | 4 +- client/cliparser/argtable3.c | 22 +- client/cliparser/argtable3.h | 4 +- client/cliparser/cliparser.c | 54 +- client/cliparser/getopt.h | 2 +- client/cmdanalyse.c | 232 +++--- client/cmdanalyse.h | 2 +- client/cmdcrc.c | 50 +- client/cmddata.c | 292 +++---- client/cmdflashmem.c | 140 ++-- client/cmdhf.c | 18 +- client/cmdhf14a.c | 288 +++---- client/cmdhf14a.h | 10 +- client/cmdhf14b.c | 282 +++---- client/cmdhf14b.h | 2 +- client/cmdhf15.c | 384 +++++----- client/cmdhfepa.c | 4 +- client/cmdhffelica.c | 120 +-- client/cmdhffido.c | 252 +++--- client/cmdhficlass.c | 440 +++++------ client/cmdhflegic.c | 314 ++++---- client/cmdhflist.c | 142 ++-- client/cmdhfmf.c | 758 +++++++++---------- client/cmdhfmfdes.c | 200 ++--- client/cmdhfmfdes.h | 4 +- client/cmdhfmfdesfire.c | 38 +- client/cmdhfmfhard.c | 312 ++++---- client/cmdhfmfp.c | 222 +++--- client/cmdhfmfu.c | 450 +++++------ client/cmdhfmfu.h | 4 +- client/cmdhftopaz.c | 104 +-- client/cmdhw.c | 50 +- client/cmdlf.c | 162 ++-- client/cmdlf.h | 2 +- client/cmdlfawid.c | 100 +-- client/cmdlfcotag.c | 28 +- client/cmdlfcotag.h | 2 +- client/cmdlfem4x.c | 228 +++--- client/cmdlfem4x.h | 2 +- client/cmdlffdx.c | 72 +- client/cmdlffdx.h | 2 +- client/cmdlfguard.c | 78 +- client/cmdlfhid.c | 92 +-- client/cmdlfhid.h | 2 +- client/cmdlfhitag.c | 32 +- client/cmdlfindala.c | 70 +- client/cmdlfio.c | 76 +- client/cmdlfjablotron.c | 30 +- client/cmdlfkeri.c | 76 +- client/cmdlfnedap.c | 82 +- client/cmdlfnexwatch.c | 16 +- client/cmdlfnexwatch.h | 2 +- client/cmdlfnoralsy.c | 42 +- client/cmdlfpac.c | 4 +- client/cmdlfparadox.c | 50 +- client/cmdlfpcf7931.c | 30 +- client/cmdlfpresco.c | 24 +- client/cmdlfpyramid.c | 34 +- client/cmdlft55xx.c | 332 ++++---- client/cmdlft55xx.h | 30 +- client/cmdlfti.c | 8 +- client/cmdlfviking.c | 30 +- client/cmdlfvisa2000.c | 34 +- client/cmdmain.c | 2 +- client/cmdmain.h | 2 +- client/cmdparser.c | 8 +- client/cmdparser.h | 2 +- client/cmdscript.c | 4 +- client/cmdsmartcard.c | 390 +++++----- client/cmdtrace.c | 106 +-- client/cmdtrace.h | 4 +- client/comms.c | 112 +-- client/comms.h | 6 +- client/crypto/asn1dump.c | 46 +- client/crypto/asn1utils.c | 12 +- client/crypto/libpcrypto.c | 128 ++-- client/emv/apduinfo.c | 16 +- client/emv/apduinfo.h | 2 +- client/emv/cmdemv.c | 554 +++++++------- client/emv/crypto.c | 2 +- client/emv/crypto_polarssl.c | 34 +- client/emv/emv_pk.c | 2 +- client/emv/emv_pki.c | 28 +- client/emv/emv_roca.c | 42 +- client/emv/emv_roca.h | 2 +- client/emv/emv_tags.c | 42 +- client/emv/emvcore.c | 194 ++--- client/emv/emvjson.c | 86 +-- client/emv/test/cda_test.c | 2 +- client/emv/test/cda_test.h | 4 +- client/emv/test/cryptotest.c | 20 +- client/emv/test/dda_test.h | 4 +- client/emv/test/sda_test.h | 2 +- client/emv/tlv.c | 46 +- client/emv/tlv.h | 2 +- client/fido/additional_ca.c | 2 +- client/fido/additional_ca.h | 4 +- client/fido/cbortools.c | 94 +-- client/fido/cose.c | 24 +- client/fido/fidocore.c | 154 ++-- client/fido/fidocore.h | 2 +- client/flasher.c | 6 +- client/fpga_compress.c | 72 +- client/graph.c | 40 +- client/hardnested/hardnested_bf_core.c | 72 +- client/hardnested/hardnested_bf_core.h | 4 +- client/hardnested/hardnested_bitarray_core.c | 42 +- client/hardnested/hardnested_bitarray_core.h | 4 +- client/hardnested/hardnested_bruteforce.c | 62 +- client/hardnested/hardnested_bruteforce.h | 4 +- client/hardnested/hardnested_tables.c | 82 +- client/hid-flasher/proxusb.c | 2 +- client/hid-flasher/usb_cmd.h | 4 +- client/jansson/lookup3.h | 18 +- client/jansson/path.c | 2 +- client/loclass/cipher.c | 24 +- client/loclass/cipher.h | 20 +- client/loclass/cipherutils.c | 26 +- client/loclass/cipherutils.h | 20 +- client/loclass/elite_crack.c | 40 +- client/loclass/elite_crack.h | 20 +- client/loclass/fileutils.c | 130 ++-- client/loclass/fileutils.h | 24 +- client/loclass/hash1_brute.c | 6 +- client/loclass/ikeys.c | 36 +- client/loclass/ikeys.h | 20 +- client/loclass/main.c | 20 +- client/mifare/mad.c | 48 +- client/mifare/mad.h | 2 +- client/mifare/mfkey.c | 14 +- client/mifare/mifare4.c | 104 +-- client/mifare/mifare4.h | 4 +- client/mifare/mifarehost.c | 268 +++---- client/mifare/mifarehost.h | 2 +- client/mifare/ndef.c | 88 +-- client/proxguiqt.h | 4 +- client/proxmark3.c | 92 +-- client/proxmark3.h | 2 +- client/reveng/cli.c | 2 +- client/reveng/getopt.c | 6 +- client/reveng/preset.c | 4 +- client/reveng/reveng.c | 4 +- client/scandir.c | 2 +- client/scripting.c | 102 +-- client/ui.c | 70 +- client/ui.h | 2 +- client/util.c | 138 ++-- client/util.h | 4 +- client/util_posix.c | 4 +- client/whereami.c | 2 +- common/cmd.c | 6 +- common/crapto1/crapto1.h | 2 +- common/crc.c | 26 +- common/crc.h | 4 +- common/crc16.c | 66 +- common/crc16.h | 2 +- common/default_version.c | 6 +- common/desfire.h | 2 +- common/emvtags.h | 230 +++--- common/i2c.c | 186 ++--- common/iso14443crc.c | 2 +- common/iso15693tools.c | 2 +- common/iso15693tools.h | 4 +- common/legic_prng.c | 8 +- common/lfdemod.c | 420 +++++----- common/lfdemod.h | 4 +- common/parity.h | 6 +- common/prng.c | 2 +- common/prng.h | 10 +- common/protocols.c | 16 +- common/protocols.h | 12 +- common/radixsort.c | 14 +- common/random.c | 6 +- common/random.h | 2 +- common/tea.c | 8 +- common/usart.c | 18 +- common/usb_cdc.c | 142 ++-- common/usb_cdc.h | 2 +- common/wiegand.c | 46 +- include/common.h | 10 +- include/hitag2.h | 2 +- include/hitagS.h | 2 +- include/legic.h | 2 +- include/mifare.h | 10 +- include/proxmark3.h | 8 +- include/usb_cmd.h | 8 +- liblua/lgc.c | 2 +- tools/mfkey/crapto1.c | 10 +- tools/mfkey/crapto1.h | 4 +- tools/mfkey/crypto1.c | 6 +- tools/mfkey/mfkey32.c | 4 +- tools/mfkey/mfkey32v2.c | 8 +- tools/mfkey/mfkey64.c | 12 +- tools/nonce2key/crapto1.c | 10 +- tools/nonce2key/crapto1.h | 4 +- tools/nonce2key/crypto1.c | 6 +- tools/nonce2key/nonce2key.c | 4 +- uart/uart.h | 2 +- uart/uart_posix.c | 30 +- uart/uart_win32.c | 22 +- zlib/deflate.c | 8 +- zlib/inflate.c | 6 +- zlib/trees.c | 6 +- zlib/zlib.h | 2 +- 249 files changed, 8481 insertions(+), 8481 deletions(-) diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index 7b49c0619..b6c9e544d 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -19,7 +19,7 @@ static uint32_t BigBuf[BIGBUF_SIZE/sizeof(uint32_t)]; Pointer to highest available memory: BigBuf_hi high BIGBUF_SIZE - reserved = BigBuf_malloc() subtracts amount from BigBuf_hi, + reserved = BigBuf_malloc() subtracts amount from BigBuf_hi, low 0x00 */ @@ -43,7 +43,7 @@ uint8_t *BigBuf_get_EM_addr(void) { // not yet allocated if (emulator_memory == NULL) emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE); - + return emulator_memory; } @@ -55,7 +55,7 @@ void BigBuf_Clear(void) { // clear ALL of BigBuf void BigBuf_Clear_ext(bool verbose) { memset(BigBuf, 0, BIGBUF_SIZE); - if (verbose) + if (verbose) Dbprintf("Buffer cleared (%i bytes)", BIGBUF_SIZE); } @@ -74,7 +74,7 @@ uint8_t *BigBuf_malloc(uint16_t chunksize) { return NULL; // no memory left chunksize = (chunksize + 3) & 0xfffc; // round to next multiple of 4 - BigBuf_hi -= chunksize; // aligned to 4 Byte boundary + BigBuf_hi -= chunksize; // aligned to 4 Byte boundary return (uint8_t *)BigBuf + BigBuf_hi; } @@ -91,7 +91,7 @@ void BigBuf_free_keep_EM(void) { BigBuf_hi = emulator_memory - (uint8_t *)BigBuf; else BigBuf_hi = BIGBUF_SIZE; - + // shouldn't this empty BigBuf also? } @@ -242,7 +242,7 @@ uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){ if (offset + length < CARD_MEMORY_SIZE) { memcpy(mem+offset, data, length); return 0; - } + } Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset + length), CARD_MEMORY_SIZE); return 1; } diff --git a/armsrc/BigBuf.h b/armsrc/BigBuf.h index 679eed676..9b7b33e47 100644 --- a/armsrc/BigBuf.h +++ b/armsrc/BigBuf.h @@ -22,7 +22,7 @@ #define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 7) / 8) #define MAX_MIFARE_FRAME_SIZE 18 // biggest Mifare frame is answer to a read (one block = 16 Bytes) + 2 Bytes CRC #define MAX_MIFARE_PARITY_SIZE 3 // need 18 parity bits for the 18 Byte above. 3 Bytes are enough to store these -#define CARD_MEMORY_SIZE 4096 +#define CARD_MEMORY_SIZE 4096 #define DMA_BUFFER_SIZE 256 //128 (how big is the dma?!? extern uint8_t *BigBuf_get_addr(void); diff --git a/armsrc/LCD.c b/armsrc/LCD.c index b40dba0f7..3e74c77fa 100644 --- a/armsrc/LCD.c +++ b/armsrc/LCD.c @@ -125,7 +125,7 @@ void LCDInit(void) LCDSend(PRAMWR); // Write to display i=LCD_XRES*LCD_YRES; while(i--) LCDSend(WHITE); - + // test text on different colored backgrounds LCDString(" The quick brown fox ", (char *)&FONT6x8,1,1+8*0,WHITE ,BLACK ); LCDString(" jumped over the ", (char *)&FONT6x8,1,1+8*1,BLACK ,WHITE ); @@ -135,7 +135,7 @@ void LCDInit(void) LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8,1,1+8*5,BLUE ,YELLOW); LCDString("`-=[]_;',./~!@#$%^&*()", (char *)&FONT6x8,1,1+8*6,BLACK ,CYAN ); LCDString(" _+{}|:\\\"<>? ",(char *)&FONT6x8,1,1+8*7,BLUE ,MAGENTA); - + // color bands LCDFill(0, 1+8* 8, 132, 8, BLACK); LCDFill(0, 1+8* 9, 132, 8, WHITE); diff --git a/armsrc/Standalone/hf_bog.c b/armsrc/Standalone/hf_bog.c index 65254bd5c..1f62e4c0c 100644 --- a/armsrc/Standalone/hf_bog.c +++ b/armsrc/Standalone/hf_bog.c @@ -8,20 +8,20 @@ /* This can actually be used in two separate ways. -It can either be used to just HF 14a sniff on the go and/or grab the +It can either be used to just HF 14a sniff on the go and/or grab the authentication attempts for ULC/NTAG/ULEV1 into the flash mem (RDV4). The retrieved sniffing session can be acquired by connecting the device to a client that supports the reconnect capability and issue 'hf 14a list'. In order to view the grabbed authentication attempts in the flash mem, -you can simply run 'script run read_pwd_mem' or just 'mem read l 256' +you can simply run 'script run read_pwd_mem' or just 'mem read l 256' from the client to view the stored quadlets. */ #include "hf_bog.h" -#define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8) +#define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8) #define DELAY_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8) // Maximum number of auth attempts per standalone session @@ -31,7 +31,7 @@ uint8_t FindOffsetInFlash() { uint8_t mem[4] = { 0x00, 0x00, 0x00, 0x00 }; uint8_t eom[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; uint8_t memcnt = 0; - + while (memcnt < 0xFF) { Flash_ReadData(memcnt, mem, 4); @@ -40,7 +40,7 @@ uint8_t FindOffsetInFlash() { } memcnt += 4; } - + return 0; // wrap-around } @@ -48,7 +48,7 @@ void EraseMemory() { if (!FlashInit()){ return; } - + Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); Flash_Erase4k(0,0); @@ -60,26 +60,26 @@ void EraseMemory() { // This is actually copied from SniffIso14443a void RAMFUNC SniffAndStore(uint8_t param) { - + iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); - + // Allocate memory from BigBuf for some buffers // free all previous allocations first BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); set_tracing(true); - + // Array to store the authpwds uint8_t *capturedPwds = BigBuf_malloc(4 * MAX_PWDS_PER_SESSION); - + // The command (reader -> tag) that we're receiving. uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE); - + // The response (tag -> reader) that we're receiving. uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE); uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE); - + // The DMA buffer, used to stream samples from the FPGA uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); uint8_t *data = dmaBuf; @@ -88,47 +88,47 @@ void RAMFUNC SniffAndStore(uint8_t param) { int dataLen = 0; bool TagIsActive = false; bool ReaderIsActive = false; - + // Set up the demodulator for tag -> reader responses. DemodInit(receivedResp, receivedRespPar); - + // Set up the demodulator for the reader -> tag commands UartInit(receivedCmd, receivedCmdPar); - + // Setup and start DMA. if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE) ){ - if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); + if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); return; } - + tUart* uart = GetUart(); tDemod* demod = GetDemod(); - + // We won't start recording the frames that we acquire until we trigger; // a good trigger condition to get started is probably when we see a // response from the tag. // triggered == false -- to wait first for card - bool triggered = !(param & 0x03); - + bool triggered = !(param & 0x03); + uint32_t rsamples = 0; - + // Current captured passwords counter uint8_t auth_attempts = 0; SpinDelay(50); - + // loop and listen while (!BUTTON_PRESS()) { WDT_HIT(); LED_A_ON(); - + int register readBufDataP = data - dmaBuf; int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; if (readBufDataP <= dmaBufDataP) dataLen = dmaBufDataP - readBufDataP; else dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; - + // test for length of buffer if (dataLen > DMA_BUFFER_SIZE) { // TODO: Check if this works properly Dbprintf("[!] blew circular buffer! | datalen %u", dataLen); @@ -149,7 +149,7 @@ void RAMFUNC SniffAndStore(uint8_t param) { } LED_A_OFF(); - + // Need two samples to feed Miller and Manchester-Decoder if (rsamples & 0x01) { @@ -164,17 +164,17 @@ void RAMFUNC SniffAndStore(uint8_t param) { if (triggered) { if ((receivedCmd) && ((receivedCmd[0] == MIFARE_ULEV1_AUTH) || (receivedCmd[0] == MIFARE_ULC_AUTH_1))) { if (MF_DBGLEVEL > 1) Dbprintf("PWD-AUTH KEY: 0x%02x%02x%02x%02x", receivedCmd[1], receivedCmd[2], receivedCmd[3], receivedCmd[4]); - + // temporarily save the captured pwd in our array memcpy(&capturedPwds[4 * auth_attempts], receivedCmd+1, 4); auth_attempts++; } - - if (!LogTrace(receivedCmd, - uart->len, + + if (!LogTrace(receivedCmd, + uart->len, uart->startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, uart->endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, - uart->parity, + uart->parity, true)) break; } /* ready to receive another command. */ @@ -188,14 +188,14 @@ void RAMFUNC SniffAndStore(uint8_t param) { } // no need to try decoding tag data if the reader is sending - and we cannot afford the time - if (!ReaderIsActive) { + if (!ReaderIsActive) { uint8_t tagdata = (previous_data << 4) | (*data & 0x0F); if (ManchesterDecoding(tagdata, 0, (rsamples-1)*4)) { LED_B_ON(); - if (!LogTrace(receivedResp, - demod->len, - demod->startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, + if (!LogTrace(receivedResp, + demod->len, + demod->startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, demod->endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, demod->parity, false)) break; @@ -208,7 +208,7 @@ void RAMFUNC SniffAndStore(uint8_t param) { UartReset(); //UartInit(receivedCmd, receivedCmdPar); LED_C_OFF(); - } + } TagIsActive = (demod->state != DEMOD_UNSYNCD); } } @@ -223,29 +223,29 @@ void RAMFUNC SniffAndStore(uint8_t param) { FpgaDisableSscDma(); set_tracing(false); - + Dbprintf("Stopped sniffing"); - + SpinDelay(200); - + // Write stuff to flash if (auth_attempts > 0) { if (MF_DBGLEVEL > 1) Dbprintf("[!] Authentication attempts = %u", auth_attempts); - + // Setting the SPI Baudrate to 48MHz to avoid the bit-flip issue (https://github.com/RfidResearchGroup/proxmark3/issues/34) FlashmemSetSpiBaudrate(48000000); - + // Find the offset in flash mem to continue writing the auth attempts uint8_t memoffset = FindOffsetInFlash(); if (MF_DBGLEVEL > 1) Dbprintf("[!] Memory offset = %u", memoffset); - + if ((memoffset + 4 * auth_attempts) > 0xFF) { // We opt to keep the new data only memoffset = 0; if (MF_DBGLEVEL > 1) Dbprintf("[!] Size of total data > 256 bytes. Discarding the old data."); } - + // Get previous data from flash mem uint8_t *previousdata = BigBuf_malloc(memoffset); if (memoffset > 0) @@ -253,49 +253,49 @@ void RAMFUNC SniffAndStore(uint8_t param) { uint16_t readlen = Flash_ReadData(0, previousdata, memoffset); if (MF_DBGLEVEL > 1) Dbprintf("[!] Read %u bytes from flash mem", readlen); } - + // create new bigbuf to hold all data size_t total_size = memoffset + 4 * auth_attempts; uint8_t *total_data = BigBuf_malloc(total_size); - + // Add the previousdata array into total_data array memcpy(total_data, previousdata, memoffset); - + // Copy bytes of capturedPwds immediately following bytes of previousdata memcpy(total_data + memoffset, capturedPwds, 4 * auth_attempts); - + // Erase first page of flash mem EraseMemory(); - + // Write total data to flash mem uint16_t writelen = Flash_WriteData(0, total_data, memoffset + 4 * auth_attempts); if (MF_DBGLEVEL > 1) Dbprintf("[!] Wrote %u bytes into flash mem", writelen); - + // If pwd saved successfully, blink led A three times if (writelen > 0) { SpinErr(0, 200, 5); // blink led A } - + SpinDelay(100); - + // Reset the SPI Baudrate to the default value (24MHz) FlashmemSetSpiBaudrate(24000000); } } void RunMod() { - + StandAloneMode(); - + Dbprintf(">> Bogiton 14a Sniff UL/UL-EV1/NTAG a.k.a BogitoRun Started <<"); Dbprintf("Starting to sniff"); - + // param: // bit 0 - trigger from first card answer - // bit 1 - trigger from first reader 7-bit request - SniffAndStore(0); - LEDsoff(); + // bit 1 - trigger from first reader 7-bit request + SniffAndStore(0); + LEDsoff(); SpinDelay(300); Dbprintf("- [ End ] -> You can take shell back ..."); - Dbprintf("- [ ! ] -> use 'script run read_pwd_mem' to print passwords"); + Dbprintf("- [ ! ] -> use 'script run read_pwd_mem' to print passwords"); } diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index 2eabd68d9..c1b8d65ab 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -161,7 +161,7 @@ void WriteTagToFlash(uint8_t index, size_t size) if (!FlashInit()){ return; } - + Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); Flash_Erase4k(0,0); @@ -212,7 +212,7 @@ void RunMod() { StandAloneMode(); FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - + currline = 20; curlline = 20; currfline = 24; @@ -328,7 +328,7 @@ ACCBITS : 796788[00]+VALUE foundKey[t][sectorNo][2] = 0xFF; foundKey[t][sectorNo][3] = 0xFF; foundKey[t][sectorNo][4] = 0xFF; - foundKey[t][sectorNo][5] = 0xFF; + foundKey[t][sectorNo][5] = 0xFF; } } diff --git a/armsrc/Standalone/hf_mattyrun.c b/armsrc/Standalone/hf_mattyrun.c index 78f197383..1f3d4b70c 100644 --- a/armsrc/Standalone/hf_mattyrun.c +++ b/armsrc/Standalone/hf_mattyrun.c @@ -13,7 +13,7 @@ I've personally recoded the image of the ARM in order to automate the attack and simulation on Mifare cards. I've moved some of the implementation on the client side to the ARM such as *chk*, *ecfill*, *sim* -and *clone* commands. +and *clone* commands. ### What it does now: It will check if the keys from the attacked tag are a subset from @@ -218,7 +218,7 @@ void RunMod() { StandAloneMode(); Dbprintf(">> Matty mifare chk/dump/sim a.k.a MattyRun Started <<"); FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - + /* It will check if the keys from the attacked tag are a subset from the hardcoded set of keys inside of the ARM. If this is the case @@ -232,9 +232,9 @@ void RunMod() { If you're using the proxmark connected to a device that has an OS, and you're not using the proxmark3 client to see the debug messages, you MUST uncomment usb_disable(). */ - + // Comment this line below if you want to see debug messages. - // usb_disable(); + // usb_disable(); /* Pseudo-configuration block. @@ -323,7 +323,7 @@ void RunMod() { bool err = 0; bool allKeysFound = true; uint32_t size = mfKeysCnt; - + for (int type = !keyType; type < 2 && !err; keyType == 2 ? (type++) : (type = 2)) { block = blockNo; for (int sec = 0; sec < sectorsCnt && !err; ++sec) { @@ -341,18 +341,18 @@ void RunMod() { num_to_bytes(key64, 6, foundKey[type][sec]); validKey[type][sec] = true; keyFound = true; - Dbprintf("\t✓ Found valid key: [%02x%02x%02x%02x%02x%02x]\n", + Dbprintf("\t✓ Found valid key: [%02x%02x%02x%02x%02x%02x]\n", (keyBlock + 6*key)[0], (keyBlock + 6*key)[1], (keyBlock + 6*key)[2], (keyBlock + 6*key)[3], (keyBlock + 6*key)[4], (keyBlock + 6*key)[5] ); } - + block < 127 ? (block += 4) : (block += 16); } } /* - TODO: + TODO: - Get UID from tag and set accordingly in emulator memory and call mifare1ksim with right flags (iceman) */ if (!allKeysFound && keyFound) { @@ -371,9 +371,9 @@ void RunMod() { If enabled, transfers found keys to memory and loads target content in emulator memory. Then it simulates to be the tag it has basically cloned. */ if ((transferToEml) && (allKeysFound)) { - + emlClearMem(); - + uint8_t mblock[16]; for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { if (validKey[0][sectorNo] || validKey[1][sectorNo]) { @@ -388,25 +388,25 @@ void RunMod() { } Dbprintf("\t✓ Found keys have been transferred to the emulator memory."); if (ecfill) { - + Dbprintf("\tFilling in with key A."); - MifareECardLoad(sectorsCnt, 0, 0, &filled); + MifareECardLoad(sectorsCnt, 0, 0, &filled); if (filled != 1) { Dbprintf("\t✕ Failed filling with A."); } - + Dbprintf("\tFilling in with key B."); MifareECardLoad(sectorsCnt, 1, 0, &filled); if (filled != 1) { Dbprintf("\t✕ Failed filling with B."); } - + if ((filled == 1) && simulation) { Dbprintf("\t✓ Filled, simulation started."); - + // This will tell the fpga to emulate using previous keys and current target tag content. Dbprintf("\t Press button to abort simulation at anytime."); - + LED_B_ON(); // green // assuming arg0==0, use hardcoded uid 0xdeadbeaf Mifare1ksim( FLAG_4B_UID_IN_DATA | FLAG_UID_IN_EMUL, 0, 0, uid); @@ -454,5 +454,5 @@ void RunMod() { LED_C_ON(); } } - } + } } \ No newline at end of file diff --git a/armsrc/Standalone/hf_young.c b/armsrc/Standalone/hf_young.c index f4bc3db4f..3feb77a94 100644 --- a/armsrc/Standalone/hf_young.c +++ b/armsrc/Standalone/hf_young.c @@ -29,7 +29,7 @@ void RunMod() { card_clone_t uids[OPTS]; iso14a_card_select_t card[OPTS]; uint8_t params = (MAGIC_SINGLE | MAGIC_DATAIN); - + LED(selected + 1, 0); for (;;) { @@ -54,7 +54,7 @@ void RunMod() { for (;;) { // exit from Standalone Mode, send a usbcommand. if (usb_poll_validate_length()) return; - + if (BUTTON_PRESS()) { if (cardRead[selected]) { Dbprintf("Button press detected -- replaying card in bank[%d]", selected); @@ -68,21 +68,21 @@ void RunMod() { SpinDelay(300); } } - + if (!iso14443a_select_card(NULL, &card[selected], NULL, true, 0, true)) { continue; } else { - Dbprintf("Read UID:"); + Dbprintf("Read UID:"); Dbhexdump(card[selected].uidlen, card[selected].uid, 0); - + if (memcmp(uids[(selected+1)%OPTS].uid, card[selected].uid, card[selected].uidlen ) == 0 ) { Dbprintf("Card selected has same UID as what is stored in the other bank. Skipping."); - } else { + } else { uids[selected].sak = card[selected].sak; - uids[selected].uidlen = card[selected].uidlen; - memcpy(uids[selected].uid , card[selected].uid, uids[selected].uidlen); + uids[selected].uidlen = card[selected].uidlen; + memcpy(uids[selected].uid , card[selected].uid, uids[selected].uidlen); memcpy(uids[selected].atqa, card[selected].atqa, 2); - + if (uids[selected].uidlen > 4) Dbprintf("Bank[%d] received a 7-byte UID", selected); else @@ -91,7 +91,7 @@ void RunMod() { } } } - + Dbprintf("ATQA = %02X%02X", uids[selected].atqa[0], uids[selected].atqa[1]); Dbprintf("SAK = %02X", uids[selected].sak); LEDsoff(); @@ -108,7 +108,7 @@ void RunMod() { cardRead[selected] = 1; } - + /* MF Classic UID clone */ else if (iGotoClone==1) { iGotoClone=0; @@ -118,7 +118,7 @@ void RunMod() { // magiccards holds 4bytes uid. *usually* uint32_t tmpuid = bytes_to_num(uids[selected].uid, 4); - + // record Dbprintf("Preparing to Clone card [Bank: %d]; uid: %08x", selected, tmpuid); @@ -175,7 +175,7 @@ void RunMod() { // arg0 = workFlags, arg1 = blockNo, datain MifareCSetBlock(params, 0, newBlock0); MifareCGetBlock(params, 0, testBlock0); - + if (memcmp(testBlock0, newBlock0, 16)==0) { DbpString("Cloned successfull!"); cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it @@ -190,9 +190,9 @@ void RunMod() { LEDsoff(); LED(selected + 1, 0); } - + // Change where to record (or begin playing) - // button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected]) + // button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected]) else if (playing==1) { LEDsoff(); LED(selected + 1, 0); @@ -203,7 +203,7 @@ void RunMod() { for ( ; ; ) { // exit from Standalone Mode, send a usbcommand. if (usb_poll_validate_length()) return; - + int button_action = BUTTON_HELD(1000); if ( button_action == 0) { // No button action, proceed with sim @@ -211,16 +211,16 @@ void RunMod() { uint8_t data[USB_CMD_DATA_SIZE] = {0}; // in case there is a read command received we shouldn't break memcpy(data, uids[selected].uid, uids[selected].uidlen); - + uint64_t tmpuid = bytes_to_num(uids[selected].uid, uids[selected].uidlen); - + if ( uids[selected].uidlen == 7 ) { flags = FLAG_7B_UID_IN_DATA; Dbprintf("Simulating ISO14443a tag with uid: %014" PRIx64 " [Bank: %d]", tmpuid, selected); } else { Dbprintf("Simulating ISO14443a tag with uid: %08" PRIx64 " [Bank: %d]", tmpuid, selected); } - + if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0) { DbpString("Mifare Classic 1k"); SimulateIso14443aTag(1, flags, data); @@ -240,7 +240,7 @@ void RunMod() { Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation"); SimulateIso14443aTag(1, flags, data); } - + } else if (button_action == BUTTON_SINGLE_CLICK) { selected = (selected + 1) % OPTS; Dbprintf("Done playing. Switching to record mode on bank %d", selected); diff --git a/armsrc/Standalone/hf_young.h b/armsrc/Standalone/hf_young.h index 3ccd08b72..46c0d1361 100644 --- a/armsrc/Standalone/hf_young.h +++ b/armsrc/Standalone/hf_young.h @@ -16,7 +16,7 @@ #include "standalone.h" // standalone definitions #include "iso14443a.h" #include "protocols.h" - + #define OPTS 2 #endif /* __HF_YOUNG_H */ \ No newline at end of file diff --git a/armsrc/Standalone/lf_hidbrute.c b/armsrc/Standalone/lf_hidbrute.c index 8c6b85f4f..f8b41771c 100644 --- a/armsrc/Standalone/lf_hidbrute.c +++ b/armsrc/Standalone/lf_hidbrute.c @@ -9,16 +9,16 @@ // the license. // // PROXMARK3 - HID CORPORATE 1000 BRUTEFORCER (STAND-ALONE MODE) -// +// // This version of Proxmark3 firmware adds one extra stand-alone mode to proxmark3 firmware. // The new stand-alone mode allows to execute a bruteforce on HID Corporate 1000 readers, by // reading a specific badge and bruteforcing the Card Number (incrementing and decrementing it), // mainteining the same Facility Code of the original badge. // -// Based on an idea of Brad Antoniewicz of McAfee® Foundstone® Professional Services (ProxBrute), +// Based on an idea of Brad Antoniewicz of McAfee® Foundstone® Professional Services (ProxBrute), // the stand-alone mode has been rewritten in order to overcome some limitations of ProxBrute firmware, // that does not consider parity bits. -// +// // https://github.com/federicodotta/proxmark3 // //----------------------------------------------------------------------------------- @@ -29,7 +29,7 @@ // samy's sniff and repeat routine for LF void RunMod() { StandAloneMode(); - Dbprintf(">> LF HID corporate bruteforce a.k.a CorporateBrute Started <<"); + Dbprintf(">> LF HID corporate bruteforce a.k.a CorporateBrute Started <<"); FpgaDownloadAndGo(FPGA_BITSTREAM_LF); uint32_t high[OPTS], low[OPTS]; @@ -40,9 +40,9 @@ void RunMod() { // Turn on selected LED LED(selected + 1, 0); - for (;;) { + for (;;) { WDT_HIT(); - + // exit from SamyRun, send a usbcommand. if (usb_poll_validate_length()) break; @@ -74,8 +74,8 @@ void RunMod() { // Finished recording // If we were previously playing, set playing off // so next button push begins playing what we recorded - playing = 0; - cardRead = 1; + playing = 0; + cardRead = 1; } else if (button_pressed > 0 && cardRead == 1) { LEDsoff(); @@ -101,8 +101,8 @@ void RunMod() { // If we were previously playing, set playing off // so next button push begins playing what we recorded - playing = 0; - cardRead = 0; + playing = 0; + cardRead = 0; } // Change where to record (or begin playing) @@ -110,7 +110,7 @@ void RunMod() { // Next option if we were previously playing if (playing) selected = (selected + 1) % OPTS; - + playing = !playing; LEDsoff(); @@ -121,15 +121,15 @@ void RunMod() { LED(LED_GREEN, 0); DbpString("[=] playing"); - + // wait for button to be released while (BUTTON_PRESS()) WDT_HIT(); - + Dbprintf("[=] %x %x %08x", selected, high[selected], low[selected]); - CmdHIDsimTAG(high[selected], low[selected], 0); + CmdHIDsimTAG(high[selected], low[selected], 0); DbpString("[=] done playing"); - + if (BUTTON_HELD(1000) > 0) goto out; @@ -144,9 +144,9 @@ void RunMod() { } else if (playing && selected == 2) { - // Now it work only with HID Corporate 1000 (35bit), but is easily extensible to others RFID. - // It is necessary only to calculate the correct parity. - + // Now it work only with HID Corporate 1000 (35bit), but is easily extensible to others RFID. + // It is necessary only to calculate the correct parity. + // Brute force code // Check if the badge is an HID Corporate 1000 if( (high[selected] & 0xFFFFFFF8) != 0x28 ) { @@ -159,7 +159,7 @@ void RunMod() { // wait for button to be released while (BUTTON_PRESS()) WDT_HIT(); - + // Calculate Facility Code and Card Number from high and low uint32_t cardnum = (low[selected] >> 1) & 0xFFFFF; uint32_t fc = ((high[selected] & 1 ) << 11 ) | (low[selected] >> 21); @@ -168,13 +168,13 @@ void RunMod() { Dbprintf("[=] Proxbrute - starting decrementing card number"); while (cardnum >= 0) { - + // Needed for exiting from proxbrute when button is pressed if (BUTTON_PRESS()) { if (BUTTON_HELD(1000) > 0) { - goto out; + goto out; } else { - while (BUTTON_PRESS()) { + while (BUTTON_PRESS()) { WDT_HIT(); } break; @@ -189,7 +189,7 @@ void RunMod() { // Print actual code to brute Dbprintf("[=] TAG ID: %x%08x (%d) - FC: %u - Card: %u", high[selected], low[selected], (low[selected] >> 1) & 0xFFFF, fc, cardnum); - + CmdHIDsimTAGEx(high[selected], low[selected], 1, 50000); } @@ -198,12 +198,12 @@ void RunMod() { Dbprintf("[=] Proxbrute - starting incrementing card number"); while (cardnum <= 0xFFFFF) { - + // Needed for exiting from proxbrute when button is pressed if (BUTTON_PRESS()) { if (BUTTON_HELD(1000) > 0) { goto out; - } else { + } else { while (BUTTON_PRESS()) { WDT_HIT(); } break; } @@ -233,32 +233,32 @@ void RunMod() { playing = !playing; LEDsoff(); LED(selected + 1, 0); - + } else { while(BUTTON_PRESS()) WDT_HIT(); } } } - -out: + +out: DbpString("[=] exiting"); - LEDsoff(); + LEDsoff(); } // Function that calculate next value for the brutforce of HID corporate 1000 void hid_corporate_1000_calculate_checksum_and_set( uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc) { uint32_t new_high = 0; - uint32_t new_low = 0; + uint32_t new_low = 0; // Calculate new high and low base value from card number and facility code, without parity - new_low = (fc << 21) | (cardnum << 1); + new_low = (fc << 21) | (cardnum << 1); new_high = 0x28 | ((fc >> 11) & 1); // 0x28 is 101000 int n_ones; uint32_t i; - + // Calculating and setting parity bit 34 // Select only bit used for parity bit 34 in low number (10110110110110110110110110110110) uint32_t parity_bit_34_low = new_low & 0xB6DB6DB6; @@ -271,7 +271,7 @@ void hid_corporate_1000_calculate_checksum_and_set( uint32_t *high, uint32_t *lo // Calculate number of ones in high number if (new_high & 1) n_ones++; - + // Set parity bit (Even parity) if (n_ones % 2) new_high = new_high | 0x2; @@ -289,14 +289,14 @@ void hid_corporate_1000_calculate_checksum_and_set( uint32_t *high, uint32_t *lo // Calculate number of ones in high number if ( new_high & 0x1) n_ones++; - + if ( new_high & 0x2) n_ones++; - + // Set parity bit (Odd parity) if (!(n_ones % 2)) new_low = new_low | 0x1; - + // Calculating and setting parity bit 35 n_ones = 0; // Calculate number of ones in low number (all bit of low, bitmask unnecessary) @@ -307,7 +307,7 @@ void hid_corporate_1000_calculate_checksum_and_set( uint32_t *high, uint32_t *lo // Calculate number of ones in high number if ( new_high & 0x1) n_ones++; - + if ( new_high & 0x2) n_ones++; diff --git a/armsrc/Standalone/lf_proxbrute.c b/armsrc/Standalone/lf_proxbrute.c index 69b5f5331..268a96eec 100644 --- a/armsrc/Standalone/lf_proxbrute.c +++ b/armsrc/Standalone/lf_proxbrute.c @@ -7,14 +7,14 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// main code for LF aka Proxbrute by Brad antoniewicz +// main code for LF aka Proxbrute by Brad antoniewicz //----------------------------------------------------------------------------- #include "lf_proxbrute.h" // samy's sniff and repeat routine for LF void RunMod() { StandAloneMode(); - Dbprintf(">> LF HID proxII bruteforce a.k.a ProxBrute Started (Brad Antoniewicz) <<"); + Dbprintf(">> LF HID proxII bruteforce a.k.a ProxBrute Started (Brad Antoniewicz) <<"); FpgaDownloadAndGo(FPGA_BITSTREAM_LF); uint32_t high[OPTS], low[OPTS]; @@ -25,9 +25,9 @@ void RunMod() { // Turn on selected LED LED(selected + 1, 0); - for (;;) { + for (;;) { WDT_HIT(); - + // exit from SamyRun, send a usbcommand. if (usb_poll_validate_length()) break; @@ -59,8 +59,8 @@ void RunMod() { // Finished recording // If we were previously playing, set playing off // so next button push begins playing what we recorded - playing = 0; - cardRead = 1; + playing = 0; + cardRead = 1; } else if (button_pressed > 0 && cardRead == 1) { LEDsoff(); @@ -86,8 +86,8 @@ void RunMod() { // If we were previously playing, set playing off // so next button push begins playing what we recorded - playing = 0; - cardRead = 0; + playing = 0; + cardRead = 0; } // Change where to record (or begin playing) @@ -107,7 +107,7 @@ void RunMod() { // wait for button to be released while (BUTTON_PRESS()) WDT_HIT(); - + /* START PROXBRUTE */ /* @@ -144,7 +144,7 @@ void RunMod() { /* END PROXBRUTE */ - + if (BUTTON_HELD(1000) > 0) goto out; @@ -163,7 +163,7 @@ void RunMod() { } } } -out: +out: DbpString("[=] exiting"); - LEDsoff(); + LEDsoff(); } \ No newline at end of file diff --git a/armsrc/Standalone/lf_samyrun.c b/armsrc/Standalone/lf_samyrun.c index c94d5fc42..c96a2ced6 100644 --- a/armsrc/Standalone/lf_samyrun.c +++ b/armsrc/Standalone/lf_samyrun.c @@ -6,14 +6,14 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// main code for LF aka SamyRun by Samy Kamkar +// main code for LF aka SamyRun by Samy Kamkar //----------------------------------------------------------------------------- #include "lf_samyrun.h" // samy's sniff and repeat routine for LF void RunMod() { StandAloneMode(); - Dbprintf(">> LF HID Read/Clone/Sim a.k.a SamyRun Started <<"); + Dbprintf(">> LF HID Read/Clone/Sim a.k.a SamyRun Started <<"); FpgaDownloadAndGo(FPGA_BITSTREAM_LF); uint32_t high[OPTS], low[OPTS]; @@ -24,15 +24,15 @@ void RunMod() { // Turn on selected LED LED(selected + 1, 0); - for (;;) { + for (;;) { WDT_HIT(); - + // exit from SamyRun, send a usbcommand. if (usb_poll_validate_length()) break; // Was our button held down or pressed? int button_pressed = BUTTON_HELD(1000); - + Dbprintf("button %d", button_pressed); SpinDelay(300); @@ -60,7 +60,7 @@ void RunMod() { // Finished recording // If we were previously playing, set playing off // so next button push begins playing what we recorded - playing = 0; + playing = 0; cardRead = 1; gotCard = true; @@ -89,8 +89,8 @@ void RunMod() { // If we were previously playing, set playing off // so next button push begins playing what we recorded - playing = 0; - cardRead = 0; + playing = 0; + cardRead = 0; } // Change where to record (or begin playing) @@ -98,7 +98,7 @@ void RunMod() { // Next option if we were previously playing if (playing) selected = (selected + 1) % OPTS; - + playing = !playing; LEDsoff(); @@ -106,18 +106,18 @@ void RunMod() { // Begin transmitting if (playing) { - + LED(LED_GREEN, 0); DbpString("[=] playing"); - + // wait for button to be released while (BUTTON_PRESS()) WDT_HIT(); - + Dbprintf("[=] %x %x %08x", selected, high[selected], low[selected]); - CmdHIDsimTAG(high[selected], low[selected], false); + CmdHIDsimTAG(high[selected], low[selected], false); DbpString("[=] done playing"); - + if (BUTTON_HELD(1000) > 0) goto out; @@ -137,7 +137,7 @@ void RunMod() { } } -out: +out: DbpString("[=] exiting"); LEDsoff(); } \ No newline at end of file diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 5002a7138..68b51913f 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -48,7 +48,7 @@ // is the order in which they go out on the wire. //============================================================================= -#define TOSEND_BUFFER_SIZE (9*MAX_FRAME_SIZE + 1 + 1 + 2) // 8 data bits and 1 parity bit per payload byte, 1 correction bit, 1 SOC bit, 2 EOC bits +#define TOSEND_BUFFER_SIZE (9*MAX_FRAME_SIZE + 1 + 1 + 2) // 8 data bits and 1 parity bit per payload byte, 1 correction bit, 1 SOC bit, 2 EOC bits uint8_t ToSend[TOSEND_BUFFER_SIZE]; int ToSendMax = -1; static int ToSendBit; @@ -114,13 +114,13 @@ void DbpStringEx(char *str, uint32_t cmd) { #if DEBUG uint8_t len = strlen(str); cmd_send(CMD_DEBUG_PRINT_STRING, len, cmd, 0, (uint8_t*)str, len); -#endif +#endif } void DbpString(char *str) { #if DEBUG DbpStringEx(str, 0); -#endif +#endif } #if 0 @@ -138,7 +138,7 @@ void DbprintfEx(uint32_t cmd, const char *fmt, ...) { va_end(ap); DbpStringEx(output_string, cmd); -#endif +#endif } void Dbprintf(const char *fmt, ...) { @@ -152,7 +152,7 @@ void Dbprintf(const char *fmt, ...) { va_end(ap); DbpString(output_string); -#endif +#endif } // prints HEX & ASCII @@ -160,30 +160,30 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci) { #if DEBUG int l=0, i; char ascii[9]; - + while (len > 0) { l = (len > 8) ? 8 : len; - + memcpy(ascii, d, l); ascii[l] = 0; - + // filter safe ascii for (i=0; i 126) { ascii[i] = '.'; } } - + if (bAsci) Dbprintf("%-8s %*D", ascii, l, d, " "); else Dbprintf("%*D", l, d, " "); - + len -= 8; - d += 8; + d += 8; } -#endif +#endif } //----------------------------------------------------------------------------- @@ -193,17 +193,17 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci) { //----------------------------------------------------------------------------- static uint16_t ReadAdc(int ch) { - // Note: ADC_MODE_PRESCALE and ADC_MODE_SAMPLE_HOLD_TIME are set to the maximum allowed value. + // Note: ADC_MODE_PRESCALE and ADC_MODE_SAMPLE_HOLD_TIME are set to the maximum allowed value. // AMPL_HI is are high impedance (10MOhm || 1MOhm) output, the input capacitance of the ADC is 12pF (typical). This results in a time constant - // of RC = (0.91MOhm) * 12pF = 10.9us. Even after the maximum configurable sample&hold time of 40us the input capacitor will not be fully charged. - // + // of RC = (0.91MOhm) * 12pF = 10.9us. Even after the maximum configurable sample&hold time of 40us the input capacitor will not be fully charged. + // // The maths are: // If there is a voltage v_in at the input, the voltage v_cap at the capacitor (this is what we are measuring) will be // // v_cap = v_in * (1 - exp(-SHTIM/RC)) = v_in * (1 - exp(-40us/10.9us)) = v_in * 0,97 (i.e. an error of 3%) AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST; - AT91C_BASE_ADC->ADC_MR = + AT91C_BASE_ADC->ADC_MR = ADC_MODE_PRESCALE(63) // ADC_CLK = MCK / ((63+1) * 2) = 48MHz / 128 = 375kHz | ADC_MODE_STARTUP_TIME(1) // Startup Time = (1+1) * 8 / ADC_CLK = 16 / 375kHz = 42,7us Note: must be > 20us | ADC_MODE_SAMPLE_HOLD_TIME(15); // Sample & Hold Time SHTIM = 15 / ADC_CLK = 15 / 375kHz = 40us @@ -216,7 +216,7 @@ static uint16_t ReadAdc(int ch) { return (AT91C_BASE_ADC->ADC_CDR[ch] & 0x3FF); } -// was static - merlok +// was static - merlok uint16_t AvgAdc(int ch) { uint16_t a = 0; for(uint8_t i = 0; i < 32; i++) @@ -243,11 +243,11 @@ void MeasureAntennaTuning(void) { * the resonating frequency of your LF antenna * ( hopefully around 95 if it is tuned to 125kHz!) */ - + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); SpinDelay(50); - + for (i = 255; i >= 19; i--) { WDT_HIT(); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i); @@ -262,10 +262,10 @@ void MeasureAntennaTuning(void) { if(LF_Results[i] > peak) { peakv = adcval; peakf = i; - peak = LF_Results[i]; + peak = LF_Results[i]; } - } - + } + LED_A_ON(); // Let the FPGA drive the high-frequency antenna around 13.56 MHz. FpgaDownloadAndGo(FPGA_BITSTREAM_HF); @@ -277,15 +277,15 @@ void MeasureAntennaTuning(void) { if ( v_hf > MAX_ADC_HF_VOLTAGE-300 ) { v_hf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10; } - + uint64_t arg0 = v_lf134; arg0 <<= 32; arg0 |= v_lf125; - + uint64_t arg2 = peakv; arg2 <<= 32; arg2 |= peakf; - + cmd_send(CMD_MEASURED_ANTENNA_TUNING, arg0, v_hf, arg2, LF_Results, 256); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); @@ -299,7 +299,7 @@ void MeasureAntennaTuningHf(void) { SpinDelay(50); volt = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; bool use_high = ( volt > MAX_ADC_HF_VOLTAGE-300 ); - + while( !BUTTON_PRESS() ){ SpinDelay(20); if ( !use_high ) { @@ -334,7 +334,7 @@ void SendVersion(void) { char *bootrom_version = *(char**)&_bootphase1_version_pointer; strncat(VersionString, " [ ARM ]\n", sizeof(VersionString) - strlen(VersionString) - 1); - + if( bootrom_version < &_flash_start || bootrom_version >= &_flash_end ) { strcat(VersionString, "bootrom version information appears invalid\n"); } else { @@ -346,7 +346,7 @@ void SendVersion(void) { strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1); strncat(VersionString, "\n [ FPGA ]\n", sizeof(VersionString) - strlen(VersionString) - 1); - + for (int i = 0; i < fpga_bitstream_num; i++) { strncat(VersionString, fpga_version_information[i], sizeof(VersionString) - strlen(VersionString) - 1); if (i < fpga_bitstream_num - 1) { @@ -384,23 +384,23 @@ void printUSBSpeed(void) { 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(void) { BigBuf_print_status(); Fpga_print_status(); -#ifdef WITH_FLASH +#ifdef WITH_FLASH Flashmem_print_status(); #endif -#ifdef WITH_SMARTCARD +#ifdef WITH_SMARTCARD I2C_print_status(); -#endif +#endif #ifdef WITH_LF printConfig(); // LF Sampling config printT55xxConfig(); // LF T55XX Config -#endif +#endif printUSBSpeed(); Dbprintf("Various"); Dbprintf(" MF_DBGLEVEL.............%d", MF_DBGLEVEL); @@ -413,9 +413,9 @@ void SendStatus(void) { // Show some leds in a pattern to identify StandAlone mod is running void StandAloneMode(void) { - + DbpString("Stand-alone mode! No PC necessary."); - + SpinDown(50); SpinOff(50); SpinUp(50); @@ -428,7 +428,7 @@ void StandAloneMode(void) { void printStandAloneModes(void) { DbpString("Installed StandAlone Mode"); - + #if defined(WITH_LF_ICERUN) DbpString(" LF sniff/clone/simulation - aka IceRun (iceman)"); #endif @@ -440,13 +440,13 @@ void printStandAloneModes(void) { #endif #if defined(WITH_LF_PROXBRUTE) DbpString(" LF HID ProxII bruteforce - aka Proxbrute (Brad Antoniewicz)"); -#endif +#endif #if defined(WITH_LF_HIDBRUTE) DbpString(" LF HID corporate 1000 bruteforce - aka Corporatebrute (Federico dotta & Maurizio Agazzini)"); -#endif +#endif #if defined(WITH_HF_MATTYRUN) DbpString(" HF Mifare sniff/clone - aka MattyRun (Matías A. Ré Medina)"); -#endif +#endif #if defined(WITH_HF_COLIN) DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN (Colin Brigato)"); #endif @@ -454,16 +454,16 @@ void printStandAloneModes(void) { DbpString(" HF 14a sniff standalone with ULC/ULEV1/NTAG auth storing in flashmem - aka BogitoRun (Bogito)"); #endif - //DbpString("Running "); - //Dbprintf(" Is Device attached to USB| %s", USB_ATTACHED() ? "Yes" : "No"); - //Dbprintf(" Is Device attached to FPC| %s", 0 ? "Yes" : "No"); + //DbpString("Running "); + //Dbprintf(" Is Device attached to USB| %s", USB_ATTACHED() ? "Yes" : "No"); + //Dbprintf(" Is Device attached to FPC| %s", 0 ? "Yes" : "No"); //Dbprintf(" Is USB_reconnect value | %d", GetUSBreconnect() ); //Dbprintf(" Is USB_configured value | %d", GetUSBconfigured() ); - + //.. add your own standalone detection based on with compiler directive you are used. // don't "reuse" the already taken ones, this will make things easier when trying to detect the different modes // 2017-08-06 must adapt the makefile and have individual compilation flags for all mods - // + // } /* @@ -529,7 +529,7 @@ void ListenReaderField(int limit) { hf_av = hf_max = AvgAdc(ADC_CHAN_HF); // iceman, useless, since we are measuring readerfield, not our field. My tests shows a max of 20v from a reader. - // RDV40 will hit the roof, try other ADC channel used in that hardware revision. + // RDV40 will hit the roof, try other ADC channel used in that hardware revision. bool use_high = ( ((MAX_ADC_HF_VOLTAGE * hf_max) >> 10) > MAX_ADC_HF_VOLTAGE-300 ); if ( use_high ) { hf_av = hf_max = AvgAdc(ADC_CHAN_HF_RDV40); @@ -561,7 +561,7 @@ void ListenReaderField(int limit) { if (limit != HF_ONLY) { if(mode == 1) { - if (ABS(lf_av - lf_baseline) > REPORT_CHANGE) + if (ABS(lf_av - lf_baseline) > REPORT_CHANGE) LED_D_ON(); else LED_D_OFF(); @@ -579,7 +579,7 @@ void ListenReaderField(int limit) { if (limit != LF_ONLY) { if (mode == 1){ - if (ABS(hf_av - hf_baseline) > REPORT_CHANGE) + if (ABS(hf_av - hf_baseline) > REPORT_CHANGE) LED_B_ON(); else LED_B_OFF(); @@ -620,7 +620,7 @@ void ListenReaderField(int limit) { if (LIGHT_SCHEME[i] & 0x8) LED_D_ON(); else LED_D_OFF(); break; } - } + } } } } @@ -629,12 +629,12 @@ void UsbPacketReceived(uint8_t *packet, int len) { UsbCommand *c = (UsbCommand *)packet; //Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d", len, c->cmd, c->arg[0], c->arg[1], c->arg[2]); - + switch(c->cmd) { #ifdef WITH_LF case CMD_SET_LF_T55XX_CONFIG: setT55xxConfig( c->arg[0], (t55xx_config *) c->d.asBytes); - break; + break; case CMD_SET_LF_SAMPLING_CONFIG: setSamplingConfig((sample_config *) c->d.asBytes); break; @@ -695,7 +695,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { WriteTItag(c->arg[0],c->arg[1],c->arg[2]); break; case CMD_SIMULATE_TAG_125K: - LED_A_ON(); + LED_A_ON(); SimulateTagLowFrequency(c->arg[0], c->arg[1], 1); LED_A_OFF(); break; @@ -703,7 +703,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]); break; case CMD_INDALA_CLONE_TAG: - CopyIndala64toT55x7(c->arg[0], c->arg[1]); + CopyIndala64toT55x7(c->arg[0], c->arg[1]); break; case CMD_INDALA_CLONE_TAG_L: CopyIndala224toT55x7( @@ -711,11 +711,11 @@ void UsbPacketReceived(uint8_t *packet, int len) { c->d.asDwords[4], c->d.asDwords[5], c->d.asDwords[6] ); break; - case CMD_T55XX_READ_BLOCK: { + case CMD_T55XX_READ_BLOCK: { T55xxReadBlock(c->arg[0], c->arg[1], c->arg[2]); break; } - case CMD_T55XX_WRITE_BLOCK: + case CMD_T55XX_WRITE_BLOCK: T55xxWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]); break; case CMD_T55XX_WAKEUP: @@ -732,11 +732,11 @@ void UsbPacketReceived(uint8_t *packet, int len) { break; case CMD_PCF7931_WRITE: WritePCF7931( - c->d.asBytes[0], c->d.asBytes[1], c->d.asBytes[2], c->d.asBytes[3], + c->d.asBytes[0], c->d.asBytes[1], c->d.asBytes[2], c->d.asBytes[3], c->d.asBytes[4], c->d.asBytes[5], c->d.asBytes[6], c->d.asBytes[9], - c->d.asBytes[7] - 128, c->d.asBytes[8] - 128, - c->arg[0], - c->arg[1], + c->d.asBytes[7] - 128, c->d.asBytes[8] - 128, + c->arg[0], + c->arg[1], c->arg[2] ); break; @@ -800,7 +800,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { break; case CMD_ISO_15693_FIND_AFI: BruteforceIso15693Afi(c->arg[0]); - break; + break; case CMD_READER_ISO_15693: ReaderIso15693(c->arg[0]); break; @@ -818,7 +818,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { break; case CMD_READER_LEGIC_RF: LegicRfReader(c->arg[0], c->arg[1], c->arg[2]); - break; + break; case CMD_LEGIC_INFO: LegicRfInfo(); break; @@ -878,7 +878,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { break; case CMD_ANTIFUZZ_ISO_14443a: iso14443a_antifuzz(c->arg[0]); - break; + break; case CMD_EPA_PACE_COLLECT_NONCE: EPA_PACE_Collect_Nonce(c); break; @@ -900,7 +900,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_MIFAREU_READCARD: MifareUReadCard(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; - case CMD_MIFAREUC_SETPWD: + case CMD_MIFAREUC_SETPWD: MifareUSetPwd(c->arg[0], c->d.asBytes); break; case CMD_MIFARE_READSC: @@ -935,7 +935,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_SIMULATE_MIFARE_CARD: Mifare1ksim(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; - + // emulator case CMD_MIFARE_SET_DBGMODE: MifareSetDbgLvl(c->arg[0]); @@ -952,7 +952,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_MIFARE_EML_CARDLOAD: MifareECardLoad(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); break; - + // Work with "magic Chinese" card case CMD_MIFARE_CSETBLOCK: MifareCSetBlock(c->arg[0], c->arg[1], c->d.asBytes); @@ -1071,35 +1071,35 @@ void UsbPacketReceived(uint8_t *packet, int len) { } case CMD_SMART_UPGRADE: { SmartCardUpgrade(c->arg[0]); - break; + break; } -#endif +#endif #ifdef WITH_FPC case CMD_FPC_SEND: { - + StartTicks(); DbpString("Mutual USB/FPC sending from device to client"); - + /* char at[11] = {'\0'}; static const char* s_at = "AT+BAUD8\0D\0A"; - strncat(at, s_at, sizeof(at) - strlen(at) - 1); + strncat(at, s_at, sizeof(at) - strlen(at) - 1); DbpString("Try AT baud rate setting"); usart_init(); int16_t res = usart_writebuffer((uint8_t*)&at, sizeof(at)); WaitMS(1); Dbprintf("SEND %d | %c%c%c%c%c%c%c%c%c%c%c", res, at[0], at[1], at[2], at[3], at[4], at[5], at[6], at[7], at[8], at[9], at[10]); - + uint8_t my_rx[20]; memset(my_rx, 0, sizeof(my_rx)); res = usart_readbuffer(my_rx, sizeof(my_rx)); WaitMS(1); Dbprintf("GOT %d | %c%c%c%c%c%c%c%c", res, my_rx[0], my_rx[1], my_rx[2], my_rx[3], my_rx[4], my_rx[5], my_rx[6], my_rx[7]); */ - - + + char dest[USB_CMD_DATA_SIZE] = { '\0' }; static const char* welcome = "Proxmark3 Serial interface via FPC ready\n"; strncat(dest, welcome, sizeof(dest) - strlen(dest) - 1); @@ -1109,27 +1109,27 @@ void UsbPacketReceived(uint8_t *packet, int len) { , c->d.asBytes[2] , c->d.asBytes[3] ); - + UsbCommand txcmd = { CMD_DEBUG_PRINT_STRING, { strlen(dest), 0, 0 } }; - memcpy(txcmd.d.asBytes, dest, sizeof(dest)); + memcpy(txcmd.d.asBytes, dest, sizeof(dest)); LED_A_ON(); - - usart_init(); + + usart_init(); usart_writebuffer((uint8_t*)&txcmd, sizeof(UsbCommand)); - + //usb cmd_send(CMD_DEBUG_PRINT_STRING, strlen(dest), 0, 0, dest, strlen(dest)); LED_A_OFF(); - - + + /* uint8_t my_rx[sizeof(UsbCommand)]; while (!BUTTON_PRESS() && !usb_poll_validate_length()) { LED_B_INV(); if (usart_readbuffer(my_rx, sizeof(UsbCommand)) ) { //UsbPacketReceived(my_rx, sizeof(my_rx)); - + UsbCommand *my = (UsbCommand *)my_rx; if (mc->cmd > 0 ) { Dbprintf("received command: 0x%04x and args: %d %d %d", my->cmd, my->arg[0], my->arg[1], my->arg[2]); @@ -1179,11 +1179,11 @@ void UsbPacketReceived(uint8_t *packet, int len) { // arg1 = length bytes to transfer // arg2 = BigBuf tracelen //Dbprintf("transfer to client parameters: %" PRIu32 " | %" PRIu32 " | %" PRIu32, startidx, numofbytes, c->arg[2]); - + for(size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { len = MIN( (numofbytes - i), USB_CMD_DATA_SIZE); isok = cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, i, len, BigBuf_get_traceLen(), mem + startidx + i, len); - if (isok != 0) + if (isok != 0) Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len); } // Trigger a finish downloading signal with an ACK frame @@ -1196,18 +1196,18 @@ void UsbPacketReceived(uint8_t *packet, int len) { LED_B_OFF(); break; } -#endif +#endif case CMD_UPLOAD_SIM_SAMPLES_125K: { // iceman; since changing fpga_bitstreams clears bigbuff, Its better to call it before. - // to be able to use this one for uploading data to device - // arg1 = 0 upload for LF usage + // to be able to use this one for uploading data to device + // arg1 = 0 upload for LF usage // 1 upload for HF usage #define FPGA_LF 1 if ( c->arg[1] == FPGA_LF ) FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - else + else FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - + uint8_t *mem = BigBuf_get_addr(); memcpy( mem + c->arg[0], c->d.asBytes, USB_CMD_DATA_SIZE); cmd_send(CMD_ACK,1,0,0,0,0); @@ -1216,7 +1216,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_DOWNLOAD_EML_BIGBUF: { LED_B_ON(); uint8_t *mem = BigBuf_get_EM_addr(); - bool isok = false; + bool isok = false; size_t len = 0; uint32_t startidx = c->arg[0]; uint32_t numofbytes = c->arg[1]; @@ -1228,7 +1228,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); isok = cmd_send(CMD_DOWNLOADED_EML_BIGBUF, i, len, 0, mem + startidx + i, len); - if (isok != 0) + if (isok != 0) Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len); } // Trigger a finish downloading signal with an ACK frame @@ -1239,7 +1239,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { case CMD_READ_MEM: ReadMem(c->arg[0]); break; -#ifdef WITH_FLASH +#ifdef WITH_FLASH case CMD_FLASHMEM_SET_SPIBAUDRATE: FlashmemSetSpiBaudrate(c->arg[0]); break; @@ -1248,20 +1248,20 @@ void UsbPacketReceived(uint8_t *packet, int len) { uint16_t isok = 0; uint32_t startidx = c->arg[0]; uint16_t len = c->arg[1]; - + Dbprintf("FlashMem read | %d - %d | ", startidx, len); - + size_t size = MIN(USB_CMD_DATA_SIZE, len); - + if (!FlashInit()) { break; } uint8_t *mem = BigBuf_malloc(size); - + for(size_t i = 0; i < len; i += size) { len = MIN((len - i), size); - + Dbprintf("FlashMem reading | %d | %d | %d |", startidx + i, i, len); isok = Flash_ReadDataCont(startidx + i, mem, len); if ( isok == len ) { @@ -1283,16 +1283,16 @@ void UsbPacketReceived(uint8_t *packet, int len) { uint32_t startidx = c->arg[0]; uint16_t len = c->arg[1]; uint8_t* data = c->d.asBytes; - + uint32_t tmp = startidx + len; - + if (!FlashInit()) { break; } Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); - + if ( startidx == DEFAULT_T55XX_KEYS_OFFSET ) Flash_Erase4k(3, 0xC); else if (startidx == DEFAULT_MF_KEYS_OFFSET ) @@ -1301,33 +1301,33 @@ void UsbPacketReceived(uint8_t *packet, int len) { Flash_Erase4k(3, 0xA); Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); - + Flash_WriteEnable(); + // inside 256b page? - if ( (tmp & 0xFF) != 0) { - + if ( (tmp & 0xFF) != 0) { + // is offset+len larger than a page tmp = (startidx & 0xFF ) + len; if (tmp > 0xFF ) { - + // data spread over two pages. - - // offset xxxx10, + + // offset xxxx10, uint8_t first_len = (~startidx & 0xFF)+1; - - // first mem page + + // first mem page res = Flash_WriteDataCont(startidx, data, first_len); - + // second mem page res = Flash_WriteDataCont(startidx + first_len, data + first_len, len - first_len); - + isok = (res == (len - first_len)) ? 1 : 0; - + } else { res = Flash_WriteDataCont(startidx, data, len); isok = (res == len) ? 1 : 0; - } - } else { + } + } else { res = Flash_WriteDataCont(startidx, data, len); isok = (res == len) ? 1 : 0; } @@ -1350,7 +1350,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { } if ( page < 3) isok = Flash_WipeMemoryPage(page); - + cmd_send(CMD_ACK, isok, 0, 0, 0, 0); LED_B_OFF(); break; @@ -1359,14 +1359,14 @@ void UsbPacketReceived(uint8_t *packet, int len) { LED_B_ON(); uint8_t *mem = BigBuf_malloc(USB_CMD_DATA_SIZE); - bool isok = false; + bool isok = false; size_t len = 0; uint32_t startidx = c->arg[0]; uint32_t numofbytes = c->arg[1]; // arg0 = startindex // arg1 = length bytes to transfer // arg2 = RFU - + if (!FlashInit()) { break; } @@ -1383,7 +1383,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); } FlashStop(); - + cmd_send(CMD_ACK, 1, 0, 0, 0, 0); LED_B_OFF(); break; @@ -1392,7 +1392,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { LED_B_ON(); rdv40_validation_t *info = (rdv40_validation_t*)BigBuf_malloc( sizeof(rdv40_validation_t) ); - + bool isok = Flash_ReadData(FLASH_MEM_SIGNATURE_OFFSET, info->signature, FLASH_MEM_SIGNATURE_LEN); if (FlashInit()) { @@ -1401,8 +1401,8 @@ void UsbPacketReceived(uint8_t *packet, int len) { } cmd_send(CMD_ACK, isok, 0, 0, info, sizeof(rdv40_validation_t)); BigBuf_free(); - - LED_B_OFF(); + + LED_B_OFF(); break; } #endif @@ -1445,7 +1445,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { usb_disable(); // (iceman) why this wait? - SpinDelay(1000); + SpinDelay(1000); AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; // We're going to reset, and the bootrom will take control. for(;;) {} @@ -1458,7 +1458,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { usb_disable(); AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; // We're going to flash, and the bootrom will take control. - for(;;) {} + for(;;) {} break; case CMD_DEVICE_INFO: { @@ -1466,7 +1466,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { if (common_area.flags.bootrom_present) { dev_info |= DEVICE_INFO_FLAG_BOOTROM_PRESENT; } - cmd_send(CMD_DEVICE_INFO,dev_info,0,0,0,0); + cmd_send(CMD_DEVICE_INFO,dev_info,0,0,0,0); break; } default: @@ -1479,7 +1479,7 @@ void __attribute__((noreturn)) AppMain(void) { SpinDelay(100); clear_trace(); - + if(common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) { /* Initialize common area */ memset(&common_area, 0, sizeof(common_area)); @@ -1489,7 +1489,7 @@ void __attribute__((noreturn)) AppMain(void) { common_area.flags.osimage_present = 1; LEDsoff(); - + // The FPGA gets its clock from us from PCK0 output, so set that up. AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0; AT91C_BASE_PIOA->PIO_PDR = GPIO_PCK0; @@ -1501,19 +1501,19 @@ void __attribute__((noreturn)) AppMain(void) { // Reset SPI AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; // errata says it needs twice to be correctly set. - + // Reset SSC AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; // Configure MUX SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - + // Load the FPGA image, which we have stored in our flash. // (the HF version by default) FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - + StartTickCount(); - + #ifdef WITH_LCD LCDInit(); #endif @@ -1524,22 +1524,22 @@ void __attribute__((noreturn)) AppMain(void) { #ifdef WITH_FPC usart_init(); -#endif +#endif #ifdef WITH_FLASH loadT55xxConfig(); #endif // This is made as late as possible to ensure enumeration without timeout - // against device such as http://www.hobbytronics.co.uk/usb-host-board-v2 + // against device such as http://www.hobbytronics.co.uk/usb-host-board-v2 usb_disable(); usb_enable(); uint8_t rx[sizeof(UsbCommand)]; - + for(;;) { WDT_HIT(); - + // Check if there is a usb packet available if (usb_poll_validate_length()) { if (usb_read(rx, sizeof(rx)) ) @@ -1554,19 +1554,19 @@ void __attribute__((noreturn)) AppMain(void) { */ #endif - + // Press button for one second to enter a possible standalone mode if (BUTTON_HELD(1000) > 0) { - + /* * So this is the trigger to execute a standalone mod. Generic entrypoint by following the standalone/standalone.h headerfile * All standalone mod "main loop" should be the RunMod() function. -* Since the standalone is either LF or HF, the somewhat bisarr defines below exists. -*/ +* Since the standalone is either LF or HF, the somewhat bisarr defines below exists. +*/ #if defined (WITH_LF) && ( defined (WITH_LF_SAMYRUN) || defined (WITH_LF_HIDBRUTE) || defined (WITH_LF_PROXBRUTE) ) RunMod(); #endif - + #if defined (WITH_ISO14443a) && ( defined (WITH_HF_YOUNG) || defined(WITH_HF_COLIN) || defined(WITH_HF_MATTYRUN) || defined(WITH_HF_BOG) ) RunMod(); #endif diff --git a/armsrc/apps.h b/armsrc/apps.h index d17d9ef4b..276331575 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -174,7 +174,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ); //desfire void Mifare_DES_Auth1(uint8_t arg0,uint8_t *datain); -void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain); +void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain); // mifaredesfire.h bool InitDesfireCard(); @@ -205,7 +205,7 @@ void AcquireRawAdcSamplesIso15693(void); void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - greg void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox -void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox +void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox void Iso15693InitReader(void); // iclass.h diff --git a/armsrc/buzzer.c b/armsrc/buzzer.c index 23e7e05d6..5f29c6472 100644 --- a/armsrc/buzzer.c +++ b/armsrc/buzzer.c @@ -1,6 +1,6 @@ #include "buzzer.h" -void Ring_BEE_ONCE(uint16_t music_note) { +void Ring_BEE_ONCE(uint16_t music_note) { BEE_ON(); SpinDelayUs(music_note); BEE_OFF(); @@ -12,7 +12,7 @@ void ring_2_7khz(uint16_t count) { } void Ring_BEE_TIME(uint16_t music_note,uint16_t count) { - for(uint16_t i=0 ; i < count; i++) + for(uint16_t i=0 ; i < count; i++) Ring_BEE_ONCE(music_note); SpinDelay(9); } @@ -28,15 +28,15 @@ void Ring_ALL(uint16_t count) { SpinDelay(10); } -void Ring_Little_Star(uint16_t count) { - Ring_BEE_TIME(note_1,count); - Ring_BEE_TIME(note_1,count); +void Ring_Little_Star(uint16_t count) { + Ring_BEE_TIME(note_1,count); + Ring_BEE_TIME(note_1,count); Ring_BEE_TIME(note_5,count); Ring_BEE_TIME(note_5,count); Ring_BEE_TIME(note_6,count); Ring_BEE_TIME(note_6,count); Ring_BEE_TIME(note_5,2*count); - LED_A_ON(); + LED_A_ON(); /* Ring_BEE_TIME(note_4,count); Ring_BEE_TIME(note_4,count); @@ -45,7 +45,7 @@ void Ring_Little_Star(uint16_t count) { Ring_BEE_TIME(note_2,count); Ring_BEE_TIME(note_2,count); Ring_BEE_TIME(note_1,2*count); - LED_A_OFF(); + LED_A_OFF(); Ring_BEE_TIME(note_5,count); Ring_BEE_TIME(note_5,count); @@ -54,7 +54,7 @@ void Ring_Little_Star(uint16_t count) { Ring_BEE_TIME(note_3,count); Ring_BEE_TIME(note_3,count); Ring_BEE_TIME(note_2,2*count); - LED_A_ON(); + LED_A_ON(); Ring_BEE_TIME(note_5,count); Ring_BEE_TIME(note_5,count); @@ -63,7 +63,7 @@ void Ring_Little_Star(uint16_t count) { Ring_BEE_TIME(note_3,count); Ring_BEE_TIME(note_3,count); Ring_BEE_TIME(note_2,2*count); - LED_A_OFF(); + LED_A_OFF(); Ring_BEE_TIME(note_1,count); Ring_BEE_TIME(note_1,count); @@ -72,7 +72,7 @@ void Ring_Little_Star(uint16_t count) { Ring_BEE_TIME(note_6,count); Ring_BEE_TIME(note_6,count); Ring_BEE_TIME(note_5,2*count); - LED_A_ON(); + LED_A_ON(); Ring_BEE_TIME(note_4,count); Ring_BEE_TIME(note_4,count); diff --git a/armsrc/des.c b/armsrc/des.c index 78ae87447..be5670e69 100644 --- a/armsrc/des.c +++ b/armsrc/des.c @@ -23,7 +23,7 @@ * \date 2007-06-16 * \brief DES and EDE-DES implementation * \license GPLv3 or later - * + * */ #include "des.h" @@ -145,25 +145,25 @@ const uint8_t pc2_permtab[] ={ const uint8_t splitin6bitword_permtab[] = { 8, 8, /* 64 bit -> 64 bit */ - 64, 64, 1, 6, 2, 3, 4, 5, - 64, 64, 7, 12, 8, 9, 10, 11, - 64, 64, 13, 18, 14, 15, 16, 17, - 64, 64, 19, 24, 20, 21, 22, 23, - 64, 64, 25, 30, 26, 27, 28, 29, - 64, 64, 31, 36, 32, 33, 34, 35, - 64, 64, 37, 42, 38, 39, 40, 41, - 64, 64, 43, 48, 44, 45, 46, 47 + 64, 64, 1, 6, 2, 3, 4, 5, + 64, 64, 7, 12, 8, 9, 10, 11, + 64, 64, 13, 18, 14, 15, 16, 17, + 64, 64, 19, 24, 20, 21, 22, 23, + 64, 64, 25, 30, 26, 27, 28, 29, + 64, 64, 31, 36, 32, 33, 34, 35, + 64, 64, 37, 42, 38, 39, 40, 41, + 64, 64, 43, 48, 44, 45, 46, 47 }; const uint8_t shiftkey_permtab[] = { 7, 7, /* 56 bit -> 56 bit */ 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 1, - 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, + 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 1, + 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 29 }; @@ -173,9 +173,9 @@ const uint8_t shiftkeyinv_permtab[] = { 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, - 56, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, + 56, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55 }; @@ -198,7 +198,7 @@ const uint8_t shiftkeyinv_permtab[] = { 2 1 1 0 */ -#define ROTTABLE 0x7EFC +#define ROTTABLE 0x7EFC #define ROTTABLE_INV 0x3F7E /******************************************************************************/ @@ -234,7 +234,7 @@ static inline void shiftkey(uint8_t *key){ uint8_t k[7]; memcpy(k, key, 7); - permute((uint8_t*)shiftkey_permtab, k, key); + permute((uint8_t*)shiftkey_permtab, k, key); } /******************************************************************************/ @@ -243,7 +243,7 @@ void shiftkey_inv(uint8_t *key){ uint8_t k[7]; memcpy(k, key, 7); permute((uint8_t*)shiftkeyinv_permtab, k, key); - + } /******************************************************************************/ @@ -251,7 +251,7 @@ static inline uint64_t splitin6bitwords(uint64_t a){ uint64_t ret=0; a &= 0x0000ffffffffffffLL; - permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret); + permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret); return ret; } @@ -259,11 +259,11 @@ uint64_t splitin6bitwords(uint64_t a){ static inline uint8_t substitute(uint8_t a, uint8_t * sbp){ - uint8_t x; + uint8_t x; x = sbp[a>>1]; x = (a&1)?x&0x0F:x>>4; return x; - + } /******************************************************************************/ @@ -272,11 +272,11 @@ uint32_t des_f(uint32_t r, uint8_t* kr){ uint8_t i; uint32_t t=0,ret; uint64_t data; - uint8_t *sbp; /* sboxpointer */ + uint8_t *sbp; /* sboxpointer */ permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data); for(i=0; i<6; ++i) ((uint8_t*)&data)[i] ^= kr[i]; - + /* Sbox substitution */ data = splitin6bitwords(data); sbp=(uint8_t*)sbox; @@ -288,7 +288,7 @@ uint32_t des_f(uint32_t r, uint8_t* kr){ sbp += 32; } changeendian32(&t); - + permute((uint8_t*)p_permtab,(uint8_t*)&t, (uint8_t*)&ret); return ret; @@ -310,7 +310,7 @@ void des_enc(void* out, const void* in, const void* key){ uint8_t kr[6], k[7]; uint8_t i; data_t data; - + permute((uint8_t*)ip_permtab, (uint8_t*)in, data.d.v8); permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); @@ -320,7 +320,7 @@ void des_enc(void* out, const void* in, const void* key){ shiftkey(k); permute((uint8_t*)pc2_permtab, k, kr); L ^= des_f(R, kr); - + shiftkey(k); if(ROTTABLE&((1<<((i<<1)+1))) ) shiftkey(k); @@ -332,7 +332,7 @@ void des_enc(void* out, const void* in, const void* key){ R ^= L; L ^= R; R ^= L; - + permute((uint8_t*)inv_ip_permtab, data.d.v8, (uint8_t*)out); } @@ -343,11 +343,11 @@ void des_dec(void* out, const void* in, const uint8_t* key){ uint8_t kr[6],k[7]; int8_t i; data_t data; - + permute((uint8_t*)ip_permtab, (uint8_t*)in, data.d.v8); permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); for(i=7; i>=0; --i){ - + permute((uint8_t*)pc2_permtab, k, kr); L ^= des_f(R, kr); shiftkey_inv(k); @@ -367,7 +367,7 @@ void des_dec(void* out, const void* in, const uint8_t* key){ R ^= L; L ^= R; R ^= L; - + permute((uint8_t*)inv_ip_permtab, data.d.v8, (uint8_t*)out); } @@ -389,51 +389,51 @@ void tdes_dec(void* out, void* in, const uint8_t* key){ void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){ - if( length % 8 ) return; + if( length % 8 ) return; uint8_t i; uint8_t* tin = (uint8_t*) in; uint8_t* tout = (uint8_t*) out; - + while( length > 0 ) { for( i = 0; i < 8; i++ ) tout[i] = (unsigned char)( tin[i] ^ iv[i] ); - + des_enc(tout, tin, (uint8_t*)key + 0); des_dec(tout, tout, (uint8_t*)key + 8); des_enc(tout, tout, (uint8_t*)key + 0); - + memcpy( iv, tout, 8 ); - + tin += 8; tout += 8; length -= 8; } } - + void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){ - - if( length % 8 ) return; + + if( length % 8 ) return; uint8_t i; unsigned char temp[8]; uint8_t* tin = (uint8_t*) in; uint8_t* tout = (uint8_t*) out; - + while( length > 0 ) { memcpy( temp, tin, 8 ); - + des_dec(tout, tin, (uint8_t*)key + 0); des_enc(tout, tout, (uint8_t*)key + 8); - des_dec(tout, tout, (uint8_t*)key + 0); + des_dec(tout, tout, (uint8_t*)key + 0); for( i = 0; i < 8; i++ ) tout[i] = (unsigned char)( tout[i] ^ iv[i] ); memcpy( iv, temp, 8 ); - + tin += 8; tout += 8; length -= 8; diff --git a/armsrc/des.h b/armsrc/des.h index 03b9f6469..22735f2f3 100644 --- a/armsrc/des.h +++ b/armsrc/des.h @@ -18,11 +18,11 @@ */ /** * \file des.h - * \author Daniel Otte + * \author Daniel Otte * \date 2007-06-16 * \brief des and tdes declarations * \license GPLv3 or later - * + * */ #ifndef __DES_H_ #define __DES_H_ @@ -46,12 +46,12 @@ /** \fn void des_enc(void* out, const void* in, const void* key) * \brief encrypt a block with DES - * + * * This function encrypts a block of 64 bits (8 bytes) with the DES algorithm. * Key expansion is done automatically. The key is 64 bits long, but note that * only 56 bits are used (the LSB of each byte is dropped). The input and output * blocks may overlap. - * + * * \param out pointer to the block (64 bit = 8 byte) where the ciphertext is written to * \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from * \param key pointer to the key (64 bit = 8 byte) @@ -60,12 +60,12 @@ void des_enc(void* out, const void* in, const void* key); /** \fn void des_dec(void* out, const void* in, const void* key) * \brief decrypt a block with DES - * + * * This function decrypts a block of 64 bits (8 bytes) with the DES algorithm. * Key expansion is done automatically. The key is 64 bits long, but note that * only 56 bits are used (the LSB of each byte is dropped). The input and output * blocks may overlap. - * + * * \param out pointer to the block (64 bit = 8 byte) where the plaintext is written to * \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from * \param key pointer to the key (64 bit = 8 byte) @@ -75,12 +75,12 @@ void des_dec(void* out, const void* in, const uint8_t* key); /** \fn void tdes_enc(void* out, const void* in, const void* key) * \brief encrypt a block with Tripple-DES - * + * * This function encrypts a block of 64 bits (8 bytes) with the Tripple-DES (EDE) * algorithm. Key expansion is done automatically. The key is 192 bits long, but * note that only 178 bits are used (the LSB of each byte is dropped). The input * and output blocks may overlap. - * + * * \param out pointer to the block (64 bit = 8 byte) where the ciphertext is written to * \param in pointer to the block (64 bit = 8 byte) where the plaintext is read from * \param key pointer to the key (192 bit = 24 byte) @@ -90,19 +90,19 @@ void tdes_enc(void* out, void* in, const void* key); /** \fn void tdes_dec(void* out, const void* in, const void* key) * \brief decrypt a block with Tripple-DES - * + * * This function decrypts a block of 64 bits (8 bytes) with the Tripple-DES (EDE) * algorithm. Key expansion is done automatically. The key is 192 bits long, but * note that only 178 bits are used (the LSB of each byte is dropped). The input * and output blocks may overlap. - * + * * \param out pointer to the block (64 bit = 8 byte) where the plaintext is written to * \param in pointer to the block (64 bit = 8 byte) where the ciphertext is read from * \param key pointer to the key (192 bit = 24 byte) */ //void tdes_dec(void* out, const void* in, const void* key); void tdes_dec(void* out, void* in, const uint8_t* key); - + void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]); void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]); diff --git a/armsrc/desfire_crypto.c b/armsrc/desfire_crypto.c index 5cb36054c..d79ecc8e3 100644 --- a/armsrc/desfire_crypto.c +++ b/armsrc/desfire_crypto.c @@ -1,11 +1,11 @@ /*- * Copyright (C) 2010, Romain Tartiere. - * + * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation, either version 3 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 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see - * + * * $Id$ */ @@ -447,10 +447,10 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte switch (DESFIRE (tag)->authentication_scheme) { case AS_LEGACY: AddCrc14A( (uint8_t*)res, end_crc_pos); - end_crc_pos = crc_pos + 2; - // - - + end_crc_pos = crc_pos + 2; + // + + crc = crc16; break; case AS_NEW: @@ -539,7 +539,7 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect break; case T_3DES: switch (operation) { - case MCO_ENCYPHER: + case MCO_ENCYPHER: // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); @@ -562,7 +562,7 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT); break; case MCO_DECYPHER: - tdes_dec(data, edata, key->data); + tdes_dec(data, edata, key->data); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_DECRYPT); // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); @@ -570,19 +570,19 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect } break; case T_AES: - switch (operation) + switch (operation) { case MCO_ENCYPHER: { AesCtx ctx; - AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); + AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); AesEncrypt(&ctx, data, edata, sizeof(edata) ); break; } case MCO_DECYPHER: { AesCtx ctx; - AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); + AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); AesDecrypt(&ctx, edata, data, sizeof(edata)); break; } diff --git a/armsrc/desfire_key.c b/armsrc/desfire_key.c index 800ff6da6..a4ed05f68 100644 --- a/armsrc/desfire_key.c +++ b/armsrc/desfire_key.c @@ -1,11 +1,11 @@ /*- * Copyright (C) 2010, Romain Tartiere. - * + * * This program is free software: you can redistribute it and/or modify it * under the terms of the GNU Lesser General Public License as published by the * Free Software Foundation, either version 3 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 @@ -13,7 +13,7 @@ * * You should have received a copy of the GNU Lesser General Public License * along with this program. If not, see - * + * * $Id$ */ diff --git a/armsrc/epa.c b/armsrc/epa.c index 71ecc29a3..80d51e553 100644 --- a/armsrc/epa.c +++ b/armsrc/epa.c @@ -289,7 +289,7 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c) // set up communication func_return = EPA_Setup(); - if (func_return != 0) { + if (func_return != 0) { EPA_PACE_Collect_Nonce_Abort(1, func_return); return; } diff --git a/armsrc/felica.c b/armsrc/felica.c index d1e7bc344..6b2bb5bfb 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -16,7 +16,7 @@ # define FELICA_FRAME_DELAY_TIME (2672/16 + 1) #endif #ifndef DELAY_AIR2ARM_AS_READER -#define DELAY_AIR2ARM_AS_READER (3 + 16 + 8 + 8*16 + 4*16 - 8*16) +#define DELAY_AIR2ARM_AS_READER (3 + 16 + 8 + 8*16 + 4*16 - 8*16) #endif #ifndef DELAY_ARM2AIR_AS_READER #define DELAY_ARM2AIR_AS_READER (4*16 + 8*16 + 8 + 8 + 1) @@ -46,7 +46,7 @@ uint32_t iso18092_get_timeout(void) { #define FELICA_MAX_FRAME_SIZE 260 #endif -//structure to hold outgoing NFC frame +//structure to hold outgoing NFC frame static uint8_t frameSpace[FELICA_MAX_FRAME_SIZE+4]; //structure to hold incoming NFC frame, used for ISO/IEC 18092-compatible frames @@ -89,10 +89,10 @@ static void FelicaFrameinit(uint8_t *data) { } //shift byte into frame, reversing it at the same time -static void shiftInByte(uint8_t bt) { +static void shiftInByte(uint8_t bt) { uint8_t j; for(j=0; j < FelicaFrame.byte_offset; j++) { - FelicaFrame.framebytes[FelicaFrame.posCnt] = ( FelicaFrame.framebytes[FelicaFrame.posCnt]<<1 ) + (bt & 1); + FelicaFrame.framebytes[FelicaFrame.posCnt] = ( FelicaFrame.framebytes[FelicaFrame.posCnt]<<1 ) + (bt & 1); bt >>= 1; } FelicaFrame.posCnt++; @@ -120,7 +120,7 @@ static void Process18092Byte(uint8_t bt) { FelicaFrame.state = STATE_UNSYNCD; } else { for (uint8_t i=0; i<8; i++) { - + if (FelicaFrame.shiftReg == SYNC_16BIT) { //SYNC done! FelicaFrame.state = STATE_GET_LENGTH; @@ -132,7 +132,7 @@ static void Process18092Byte(uint8_t bt) { FelicaFrame.framebytes[2] = (FelicaFrame.framebytes[2] << 1) + (bt & 1); bt >>= 1; } - + FelicaFrame.posCnt = 2; if (i==0) break; @@ -146,7 +146,7 @@ static void Process18092Byte(uint8_t bt) { //Force SYNC on next byte FelicaFrame.state = STATE_GET_LENGTH; FelicaFrame.framebytes[0] = 0xb2; - FelicaFrame.framebytes[1] = 0x4d; + FelicaFrame.framebytes[1] = 0x4d; FelicaFrame.byte_offset = 0; FelicaFrame.posCnt = 1; } @@ -176,12 +176,12 @@ static void Process18092Byte(uint8_t bt) { FelicaFrame.crc_ok = check_crc(CRC_FELICA, FelicaFrame.framebytes+2, FelicaFrame.len-2); FelicaFrame.state = STATE_FULL; FelicaFrame.rem_len = 0; - if (MF_DBGLEVEL > 3) Dbprintf("[+] got 2 crc bytes [%s]", (FelicaFrame.crc_ok) ? "OK" : "No" ); + if (MF_DBGLEVEL > 3) Dbprintf("[+] got 2 crc bytes [%s]", (FelicaFrame.crc_ok) ? "OK" : "No" ); } break; } - case STATE_FULL: //ignore byte. Don't forget to clear frame to receive next one... - default: + case STATE_FULL: //ignore byte. Don't forget to clear frame to receive next one... + default: break; } } @@ -196,19 +196,19 @@ static uint8_t felica_select_card(felica_card_select_t *card) { // 0xB2 0x4B = sync code // 0x06 = len // 0x00 = rfu - // 0xff = system service + // 0xff = system service // 0xff = system service // 0x00 = // b7 = automatic switching of data rate // b6-b2 = reserved // b1 = fc/32 (414kbps) - // b0 = fc/64 (212kbps) + // b0 = fc/64 (212kbps) // 0x00 = timeslot // 0x09 0x21 = crc static uint8_t poll[10] = {0xb2,0x4d,0x06,FELICA_POLL_REQ,0xFF,0xFF,0x00,0x00,0x09,0x21}; - + int len = 20; - + // We try 20 times, or if answer was received. do { // end-of-reception response packet data, wait approx. 501μs @@ -219,23 +219,23 @@ static uint8_t felica_select_card(felica_card_select_t *card) { // polling card, break if success if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK) break; - + WDT_HIT(); - + } while (--len); - + // timed-out if ( len == 0 ) return 1; - - // wrong answer + + // wrong answer if (FelicaFrame.framebytes[3] != FELICA_POLL_ACK) return 2; - + // VALIDATE CRC residue is 0, hence if crc is a value it failed. if (!check_crc(CRC_FELICA, FelicaFrame.framebytes+2, FelicaFrame.len-2)) return 3; - + // copy UID // idm 8 if (card) { @@ -246,9 +246,9 @@ static uint8_t felica_select_card(felica_card_select_t *card) { memcpy(card->uid, card->IDm + 2, 6); memcpy(card->iccode, card->PMm, 2); memcpy(card->mrt, card->PMm+2, 6); - + } - // more status bytes? + // more status bytes? return 0; } @@ -257,42 +257,42 @@ static uint8_t felica_select_card(felica_card_select_t *card) { // poll-1 (reply with available system codes - NFC Tag3 specs, IIRC): 0xb2,0x4d,0x06,0x00,0xff,0xff,0x01,0x00,0x3a,0x10 // resp: 0xb2,0x4d,0x14,0x01, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00, 0x88,0xb4,0x0c,0xe2, // page-req: 0xb2,0x4d,0x10,0x06, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x01, 0x0b,0x00, 0x01, 0x80,0x00, 0x2e,0xb3, -// page-req: 0x06, IDm(8), ServiceNum(1),Slist(2*num) BLocknum (1) BLockids(2-3*num) +// page-req: 0x06, IDm(8), ServiceNum(1),Slist(2*num) BLocknum (1) BLockids(2-3*num) // page-resp: 0xb2,0x4d,0x1d,0x07, 0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX,0xXX, 0x00, 0x00, 0x01, 0x10,0x04,0x01,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x23, 0xcb,0x6e, -// builds a readblock frame for felica lite(s). Using SERVICE: SERVICE_FELICA_LITE_READONLY -// Felica standard has a different file system, AFAIK, +// builds a readblock frame for felica lite(s). Using SERVICE: SERVICE_FELICA_LITE_READONLY +// Felica standard has a different file system, AFAIK, // 8-byte IDm, number of blocks, blocks numbers // number of blocks limited to 4 for FelicaLite(S) static void BuildFliteRdblk(uint8_t* idm, int blocknum, uint16_t *blocks ) { if (blocknum > 4 || blocknum <= 0) Dbprintf("Invalid number of blocks, %d != 4", blocknum); - + uint8_t c = 0, i = 0; - + frameSpace[c++] = 0xb2; frameSpace[c++] = 0x4d; - + c++; //set length later - + frameSpace[c++] = FELICA_RDBLK_REQ; //command number - + //card IDm, from poll frameSpace[c++] = idm[0]; frameSpace[c++] = idm[1]; frameSpace[c++] = idm[2]; frameSpace[c++] = idm[3]; frameSpace[c++] = idm[4]; - frameSpace[c++] = idm[5]; + frameSpace[c++] = idm[5]; frameSpace[c++] = idm[6]; frameSpace[c++] = idm[7]; - //number of services - frameSpace[c++] = 0x01; - + //number of services + frameSpace[c++] = 0x01; + //service code - frameSpace[c++] = (SERVICE_FELICA_LITE_READONLY >> 8); + frameSpace[c++] = (SERVICE_FELICA_LITE_READONLY >> 8); frameSpace[c++] = SERVICE_FELICA_LITE_READONLY & 0xFF; //number of blocks @@ -304,20 +304,20 @@ static void BuildFliteRdblk(uint8_t* idm, int blocknum, uint16_t *blocks ) { if (blocks[i] >= 256) { frameSpace[c++] = 0x00; frameSpace[c++] = (blocks[i] >> 8); //block number, little endian.... - frameSpace[c++] = (blocks[i] & 0xff); + frameSpace[c++] = (blocks[i] & 0xff); } else { frameSpace[c++] = 0x80; frameSpace[c++] = blocks[i]; } } - - //set length - frameSpace[2] = c-2; + + //set length + frameSpace[2] = c-2; AddCrc(frameSpace, c-2); } static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed) { - + uint8_t flags = FPGA_MAJOR_MODE_ISO18092; if ( power ) @@ -326,19 +326,19 @@ static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t *timing flags |= FPGA_HF_ISO18092_FLAG_424K; FpgaWriteConfWord(flags); - + uint32_t curr_transfer_time = ((MAX(felica_nexttransfertime, GetCountSspClk()) & 0xfffffff8) + 8); while (GetCountSspClk() < curr_transfer_time) {}; felica_lasttime_prox2air_start = curr_transfer_time; - + // preamble // sending 0x00 0x00 0x00 0x00 0x00 0x00 - uint16_t c = 0; + uint16_t c = 0; while (c < 6) { - // keep tx buffer in a defined state anyway. + // keep tx buffer in a defined state anyway. if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = 0x00; c++; @@ -350,16 +350,16 @@ static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t *timing c = 0; while (c < len) { - // Put byte into tx holding register as soon as it is ready + // Put byte into tx holding register as soon as it is ready if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = frame[c++]; } } -/**/ +/**/ while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {}; AT91C_BASE_SSC->SSC_THR = 0x00; //minimum delay - + while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {}; AT91C_BASE_SSC->SSC_THR = 0x00; //spin /**/ @@ -373,7 +373,7 @@ static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t *timing NULL, true ); - + felica_nexttransfertime = MAX(felica_nexttransfertime ,felica_lasttime_prox2air_start + FELICA_REQUEST_GUARD_TIME); } @@ -383,7 +383,7 @@ static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t *timing bool WaitForFelicaReply(uint16_t maxbytes) { uint32_t c = 0; - + // power, no modulation FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); @@ -391,22 +391,22 @@ bool WaitForFelicaReply(uint16_t maxbytes) { // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - + uint32_t timeout = iso18092_get_timeout(); for(;;) { - WDT_HIT(); - + WDT_HIT(); + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - b = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); - Process18092Byte(b); + b = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); + Process18092Byte(b); if (FelicaFrame.state == STATE_FULL) { - felica_nexttransfertime = + felica_nexttransfertime = MAX( felica_nexttransfertime, (GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/16 + FELICA_FRAME_DELAY_TIME ) - ; - + ; + LogTrace( FelicaFrame.framebytes, FelicaFrame.len, @@ -417,13 +417,13 @@ bool WaitForFelicaReply(uint16_t maxbytes) { ); return true; } else if (c++ > timeout && FelicaFrame.state == STATE_UNSYNCD) { - return false; + return false; } else if (FelicaFrame.state == STATE_GET_CRC) { Dbprintf(" Frame: "); Dbhexdump(16, FelicaFrame.framebytes, 0); //return false; } - } + } } return false; } @@ -437,34 +437,34 @@ static void iso18092_setup(uint8_t fpga_minor_mode) { // allocate command receive buffer BigBuf_free(); BigBuf_Clear_ext(false); - + // Initialize Demod and Uart structs //DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); FelicaFrameinit(BigBuf_malloc(FELICA_MAX_FRAME_SIZE)); felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER; iso18092_set_timeout(2120); // 106 * 20ms maximum start-up time of card - + init_table(CRC_FELICA); - + // connect Demodulated Signal to ADC: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); // Set up the synchronous serial port FpgaSetupSsc(); - + // LSB transfer. Remember to set it back to MSB with AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - + // Signal field is on with the appropriate LED FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | fpga_minor_mode); - + //20.4 ms generate field, start sending polling command afterwars. SpinDelay(100); // Start the timer StartCountSspClk(); - + LED_D_ON(); } //----------------------------------------------------------------------------- @@ -472,7 +472,7 @@ static void iso18092_setup(uint8_t fpga_minor_mode) { //----------------------------------------------------------------------------- // arg0 FeliCa flags // arg1 len of commandbytes -// d.asBytes command bytes to send +// d.asBytes command bytes to send void felica_sendraw(UsbCommand *c) { if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Enter"); @@ -481,9 +481,9 @@ void felica_sendraw(UsbCommand *c) { size_t len = c->arg[1] & 0xffff; uint8_t *cmd = c->d.asBytes; uint32_t arg0 = 0; - + felica_card_select_t card; - + if ((param & FELICA_CONNECT)) clear_trace(); @@ -501,19 +501,19 @@ void felica_sendraw(UsbCommand *c) { goto OUT; } } - + if ((param & FELICA_RAW)) { - + // 2 sync, 1 len, 2crc == 5 uint8_t *buf = BigBuf_malloc(len+5); // add sync bits buf[0] = 0xb2; buf[1] = 0x4d; buf[2] = len; - + // copy command memcpy(buf+2, cmd, len); - + if ((param & FELICA_APPEND_CRC)) { // Don't append crc on empty bytearray... if ( len > 0 ) { @@ -530,24 +530,24 @@ void felica_sendraw(UsbCommand *c) { if ((param & FELICA_NO_DISCONNECT)) return; -OUT: +OUT: switch_off(); - - //Resetting Frame mode (First set in fpgaloader.c) + + //Resetting Frame mode (First set in fpgaloader.c) AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - + if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Exit"); } void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { - + int remFrames = (samplesToSkip) ? samplesToSkip : 0; Dbprintf("Snoop FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); - + iso18092_setup( FPGA_HF_ISO18092_FLAG_NOMOD); - //the frame bits are slow enough. + //the frame bits are slow enough. int n = BigBuf_max_traceLen() / sizeof(uint8_t); // take all memory int numbts = 0; uint8_t *dest = (uint8_t *)BigBuf_get_addr(); @@ -558,14 +558,14 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { while (dest <= destend) { WDT_HIT(); if( BUTTON_PRESS()) break; - + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); Process18092Byte(dist); - + //to be sure we are in frame if (FelicaFrame.state == STATE_GET_LENGTH) { - //length is after 48 (PRE)+16 (SYNC) - 64 ticks +maybe offset? not 100% + //length is after 48 (PRE)+16 (SYNC) - 64 ticks +maybe offset? not 100% uint16_t distance = GetCountSspClk() - endframe - 64 + (FelicaFrame.byte_offset > 0 ? (8-FelicaFrame.byte_offset) : 0); *dest = distance >> 8; dest++; @@ -587,16 +587,16 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { remFrames--; if (remFrames <= 0) break; if (dest >= destend ) break; - + numbts += FelicaFrame.len; - + FelicaFrameReset(); } } } switch_off(); - + //reset framing AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); set_tracelen(numbts); @@ -622,13 +622,13 @@ void felica_sim_lite(uint64_t nfcid) { uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2,0x4d,0x12,FELICA_POLL_ACK,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; uint8_t resp_poll1[R_POLL1_LEN] = { 0xb2,0x4d,0x14,FELICA_POLL_ACK,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00, 0x88,0xb4,0xb3,0x7f}; uint8_t resp_readblk[R_READBLK_LEN] = { 0xb2,0x4d,0x1d,FELICA_RDBLK_ACK,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x04,0x01,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x23,0xcb,0x6e}; - + //NFC tag 3/ ISo technically. Many overlapping standards - DbpString("Felica Lite-S sim start"); + DbpString("Felica Lite-S sim start"); Dbprintf("NDEF2 UID: %02x %02x %02x %02x %02x %02x %02x %02x", ndef[0], ndef[1], ndef[2], ndef[3], ndef[4], ndef[5], ndef[6], ndef[7] ); - + //fill in blanks for( i=0; i<8; i++) { resp_poll0[i+4] = ndef[i]; @@ -656,11 +656,11 @@ void felica_sim_lite(uint64_t nfcid) { uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); //frtm = GetCountSspClk(); Process18092Byte(dist); - + if (FelicaFrame.state == STATE_FULL) { if (FelicaFrame.crc_ok) { - + if (FelicaFrame.framebytes[2] == 6 && FelicaFrame.framebytes[3] == 0) { //polling... there are two types of polling we answer to @@ -675,7 +675,7 @@ void felica_sim_lite(uint64_t nfcid) { listenmode = true; } } - + if (FelicaFrame.framebytes[2] > 5 && FelicaFrame.framebytes[3] == 0x06) { //we should rebuild it depending on page size, but... //Let's see first @@ -707,7 +707,7 @@ void felica_sim_lite(uint64_t nfcid) { curresp = NULL; } } - + switch_off(); //reset framing @@ -721,38 +721,38 @@ void felica_dump_lite_s() { uint8_t ndef[8]; uint8_t poll[10] = { 0xb2,0x4d,0x06,FELICA_POLL_REQ,0xff,0xff,0x00,0x00,0x09,0x21}; uint16_t liteblks[28] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x90,0x91,0x92,0xa0}; - + // setup device. iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); - + uint8_t blknum; bool isOK = false; uint16_t cnt = 0, cntfails = 0; uint8_t *dest = BigBuf_get_addr(); while (!BUTTON_PRESS() && !usb_poll_validate_length()) { - + WDT_HIT(); - - // polling? + + // polling? //TransmitFor18092_AsReader(poll, 10, GetCountSspClk()+512, 1, 0); TransmitFor18092_AsReader(poll, 10, NULL, 1, 0); - + if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK) { - + // copy 8bytes to ndef. memcpy(ndef, FelicaFrame.framebytes + 4, 8); // for (c=0; c < 8; c++) // ndef[c] = FelicaFrame.framebytes[c+4]; - - for (blknum=0; blknum < sizeof(liteblks); ) { - // block to read. + for (blknum=0; blknum < sizeof(liteblks); ) { + + // block to read. BuildFliteRdblk(ndef, 1, &liteblks[blknum]); - + //TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, GetCountSspClk()+512, 1, 0); TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, NULL, 1, 0); - + // read block if (WaitForFelicaReply(1024) && FelicaFrame.framebytes[3] == FELICA_RDBLK_ACK) { @@ -766,10 +766,10 @@ void felica_dump_lite_s() { //cnt += 16; for(uint8_t j=0; j < 16; j++) dest[cnt++] = fb[15+j]; - + blknum++; cntfails = 0; - + // // print raw log. // Dbprintf("LEN %u | Dump bytes count %u ", FelicaFrame.len, cnt); Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes+15, 0); @@ -782,15 +782,15 @@ void felica_dump_lite_s() { } } isOK = true; - break; - } + break; + } } - + switch_off(); - //Resetting Frame mode (First set in fpgaloader.c) + //Resetting Frame mode (First set in fpgaloader.c) AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - + //setting tracelen - important! it was set by buffer overflow before set_tracelen(cnt); cmd_send(CMD_ACK, isOK, cnt, 0, 0, 0); diff --git a/armsrc/flashmem.c b/armsrc/flashmem.c index 92204baff..c3b7a6e82 100644 --- a/armsrc/flashmem.c +++ b/armsrc/flashmem.c @@ -4,9 +4,9 @@ #define SPI_CSR_NUM 2 #define SPI_PCS(npcs) ((~(1 << (npcs)) & 0xF) << 16) /// Calculates the value of the CSR SCBR field given the baudrate and MCK. -#define SPI_SCBR(baudrate, masterClock) ((uint32_t) ((masterClock) / (baudrate)) << 8) +#define SPI_SCBR(baudrate, masterClock) ((uint32_t) ((masterClock) / (baudrate)) << 8) /// Calculates the value of the CSR DLYBS field given the desired delay (in ns) -#define SPI_DLYBS(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 1000) << 16) +#define SPI_DLYBS(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 1000) << 16) /// Calculates the value of the CSR DLYBCT field given the desired delay (in ns) #define SPI_DLYBCT(delay, masterClock) ((uint32_t) ((((masterClock) / 1000000) * (delay)) / 32000) << 24) @@ -67,7 +67,7 @@ void FlashSetup(uint32_t baudrate){ // NPCS2 Mode 0 AT91C_BASE_SPI->SPI_MR = - (0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT: + (0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT: // If DLYBCS is less than or equal to six, six MCK periods // will be inserted by default. SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10) @@ -88,10 +88,10 @@ void FlashSetup(uint32_t baudrate){ AT91C_BASE_SPI->SPI_CSR[2] = SPI_DLYBCT(dlybct,MCK) | // Delay between Consecutive Transfers (32 MCK periods) - SPI_DLYBS(0,MCK) | // Delay Beforce SPCK CLock + SPI_DLYBS(0,MCK) | // Delay Beforce SPCK CLock SPI_SCBR(baudrate,MCK) | // SPI Baudrate Selection AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits) - //AT91C_SPI_CSAAT | // Chip Select inactive after transfer + //AT91C_SPI_CSAAT | // Chip Select inactive after transfer // 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1 // If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on // the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been @@ -140,17 +140,17 @@ void FlashStop(void) { // Disable all interrupts AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF; - + // SPI disable AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS; if ( MF_DBGLEVEL > 3 ) Dbprintf("FlashStop"); - + StopTicks(); } // send one byte over SPI -uint16_t FlashSendByte(uint32_t data) { +uint16_t FlashSendByte(uint32_t data) { // wait until SPI is ready for transfer //if you are checking for incoming data returned then the TXEMPTY flag is redundant @@ -176,7 +176,7 @@ uint16_t FlashSendLastByte(uint32_t data) { // read state register 1 uint8_t Flash_ReadStat1(void) { FlashSendByte(READSTAT1); - return FlashSendLastByte(0xFF); + return FlashSendLastByte(0xFF); } bool Flash_CheckBusy(uint32_t timeout) @@ -215,10 +215,10 @@ uint8_t Flash_ReadID(void) { FlashSendByte(0x00); uint8_t man_id = FlashSendByte(0xFF); - uint8_t dev_id = FlashSendLastByte(0xFF); + uint8_t dev_id = FlashSendLastByte(0xFF); if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash ReadID | Man ID %02x | Device ID %02x", man_id, dev_id); - + if ( (man_id == WINBOND_MANID ) && (dev_id == WINBOND_DEVID) ) return dev_id; @@ -248,9 +248,9 @@ void Flash_UniqueID(uint8_t *uid) { } uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) { - + if (!FlashInit()) return 0; - + // length should never be zero if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0; @@ -268,8 +268,8 @@ uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) { out[i] = FlashSendByte(0xFF); out[i] = FlashSendLastByte(0xFF); - FlashStop(); - return len; + FlashStop(); + return len; } void Flash_TransferAdresse(uint32_t address){ @@ -280,10 +280,10 @@ void Flash_TransferAdresse(uint32_t address){ /* This ensure we can ReadData without having to cycle through initialization everytime */ uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) { - + // length should never be zero if (!len) return 0; - + uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA; FlashSendByte(cmd); @@ -292,31 +292,31 @@ uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) { if (FASTFLASH){ FlashSendByte(DUMMYBYTE); } - + uint16_t i = 0; for (; i < (len - 1); i++) out[i] = FlashSendByte(0xFF); out[i] = FlashSendLastByte(0xFF); - return len; + return len; } //////////////////////////////////////// -// Write data can only program one page. A page has 256 bytes. +// Write data can only program one page. A page has 256 bytes. // if len > 256, it might wrap around and overwrite pos 0. uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { // length should never be zero if (!len) return 0; - + // Max 256 bytes write if (((address & 0xFF) + len) > 256) { Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len ); return 0; } - + // out-of-range if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) { Dbprintf("Flash_WriteData, block out-of-range"); @@ -327,11 +327,11 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); return 0; } - + Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); - + FlashSendByte(PAGEPROG); FlashSendByte((address >> 16) & 0xFF); FlashSendByte((address >> 8) & 0xFF); @@ -344,7 +344,7 @@ uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { FlashSendLastByte(in[i]); FlashStop(); - return len; + return len; } @@ -355,12 +355,12 @@ uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) { if (!len) return 0; - + if (((address & 0xFF) + len) > 256) { Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len ); return 0; } - + if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) { Dbprintf("Flash_WriteDataCont, block out-of-range"); return 0; @@ -376,7 +376,7 @@ uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) { FlashSendByte(in[i]); FlashSendLastByte(in[i]); - return len; + return len; } // assumes valid start 256 based 00 address @@ -418,12 +418,12 @@ bool Flash_WipeMemoryPage(uint8_t page) { return false; } Flash_ReadStat1(); - + // Each block is 64Kb. One block erase takes 1s ( 1000ms ) - Flash_WriteEnable(); Flash_Erase64k(page); Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); Flash_Erase64k(page); Flash_CheckBusy(BUSY_TIMEOUT); FlashStop(); - return true; + return true; } // Wipes flash memory completely, fills with 0xFF bool Flash_WipeMemory() { @@ -432,22 +432,22 @@ bool Flash_WipeMemory() { return false; } Flash_ReadStat1(); - + // Each block is 64Kb. Four blocks // one block erase takes 1s ( 1000ms ) - Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); Flash_Erase64k(3); Flash_CheckBusy(BUSY_TIMEOUT); - + FlashStop(); return true; } // enable the flash write void Flash_WriteEnable() { - FlashSendLastByte(WRITEENABLE); - if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash Write enabled"); + FlashSendLastByte(WRITEENABLE); + if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash Write enabled"); } // erase 4K at one time @@ -488,9 +488,9 @@ bool Flash_Erase32k(uint32_t address) { // 0x02 00 00 -- 0x 02 FF FF == block 2 // 0x03 00 00 -- 0x 03 FF FF == block 3 bool Flash_Erase64k(uint8_t block) { - + if (block > MAX_BLOCKS) return false; - + FlashSendByte(BLOCK64ERASE); FlashSendByte(block); FlashSendByte(0x00); @@ -512,7 +512,7 @@ void Flashmem_print_status(void) { return; } DbpString(" Init....................OK"); - + uint8_t dev_id = Flash_ReadID(); switch (dev_id) { case 0x11 : @@ -528,13 +528,13 @@ void Flashmem_print_status(void) { DbpString(" Device ID............... --> Unknown <--"); break; } - + uint8_t uid[8] = {0,0,0,0,0,0,0,0}; - Flash_UniqueID(uid); + Flash_UniqueID(uid); Dbprintf(" Unique ID...............0x%02x%02x%02x%02x%02x%02x%02x%02x", - uid[7], uid[6], uid[5], uid[4], + uid[7], uid[6], uid[5], uid[4], uid[3], uid[2], uid[1], uid[0] ); - + FlashStop(); } diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index e4ab1ab0b..6f8489026 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -28,7 +28,7 @@ static uint32_t uncompressed_bytes_cnt; // Used to write the FPGA config word // May also be used to write to other SPI attached devices like an LCD //----------------------------------------------------------------------------- -static void DisableSpi(void) { +static void DisableSpi(void) { //* Reset all the Chip Select register AT91C_BASE_SPI->SPI_CSR[0] = 0; AT91C_BASE_SPI->SPI_CSR[1] = 0; @@ -40,7 +40,7 @@ static void DisableSpi(void) { // Disable all interrupts AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF; - + // SPI disable AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS; } @@ -77,7 +77,7 @@ void SetupSpi(int mode) { ( 0 << 2) | // Chip selects connected directly to peripheral AT91C_SPI_PS_FIXED | // Fixed Peripheral Select AT91C_SPI_MSTR; // Master Mode - + AT91C_BASE_SPI->SPI_CSR[0] = ( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods) ( 1 << 16) | // Delay Before SPCK (1 MCK period) @@ -97,7 +97,7 @@ void SetupSpi(int mode) { ( 0 << 2) | // Chip selects connected directly to peripheral ( 0 << 1) | // Fixed Peripheral Select ( 1 << 0); // Master Mode - + AT91C_BASE_SPI->SPI_CSR[2] = ( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods) ( 1 << 16) | // Delay Before SPCK (1 MCK period) @@ -107,9 +107,9 @@ void SetupSpi(int mode) { ( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge ( 0 << 0); // Clock Polarity inactive state is logic 0 break; -*/ +*/ default: - DisableSpi(); + DisableSpi(); break; } } @@ -134,7 +134,7 @@ void FpgaSetupSscExt(uint8_t clearPCER) { // Now set up the SSC proper, starting from a known state. AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; - + // RX clock comes from TX clock, RX starts when TX starts, data changes // on RX clock rising edge, sampled on falling edge AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(1) | SSC_CLOCK_MODE_START(1); @@ -396,12 +396,12 @@ void FpgaDownloadAndGo(int bitstream_version) { // check whether or not the bitstream is already loaded if (downloaded_bitstream == bitstream_version) return; - + z_stream compressed_fpga_stream; uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00}; bool verbose = (MF_DBGLEVEL > 3); - + // make sure that we have enough memory to decompress BigBuf_free(); BigBuf_Clear_ext(verbose); @@ -418,7 +418,7 @@ void FpgaDownloadAndGo(int bitstream_version) { // turn off antenna FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - + // free eventually allocated BigBuf memory BigBuf_free(); BigBuf_Clear_ext(false); } @@ -466,7 +466,7 @@ void SetAdcMuxFor(uint32_t whichGpio) { #ifndef WITH_FPC LOW(GPIO_MUXSEL_HIRAW); LOW(GPIO_MUXSEL_LORAW); -#endif +#endif HIGH(whichGpio); } @@ -480,15 +480,15 @@ int FpgaGetCurrent(void) { return downloaded_bitstream; } -// Turns off the antenna, +// Turns off the antenna, // log message // if HF, Disable SSC DMA // turn off trace and leds off. -void switch_off(void) { +void switch_off(void) { if (MF_DBGLEVEL > 3) Dbprintf("switch_off"); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); if (downloaded_bitstream == FPGA_BITSTREAM_HF ) FpgaDisableSscDma(); set_tracing(false); - LEDsoff(); + LEDsoff(); } diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index a1e0d1ee0..852d66dfa 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -83,7 +83,7 @@ extern void switch_off(void); #define FPGA_HF_SIMULATOR_MODULATE_212K 0x2 // 0010 #define FPGA_HF_SIMULATOR_MODULATE_424K 0x4 // 0100 #define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5 // 0101 -// no 848K +// no 848K // Options for ISO14443A #define FPGA_HF_ISO14443A_SNIFFER (0<<0) @@ -92,10 +92,10 @@ extern void switch_off(void); #define FPGA_HF_ISO14443A_READER_LISTEN (3<<0) #define FPGA_HF_ISO14443A_READER_MOD (4<<0) -//options for Felica. +//options for Felica. #define FPGA_MAJOR_MODE_ISO18092 (5<<5) // 01010 0000 #define FPGA_HF_ISO18092_FLAG_NOMOD (1<<0) // 0001 disable modulation module #define FPGA_HF_ISO18092_FLAG_424K (2<<0) // 0010 should enable 414k mode (untested). No autodetect #define FPGA_HF_ISO18092_FLAG_READER (4<<0) // 0100 enables antenna power, to act as a reader instead of tag - + #endif \ No newline at end of file diff --git a/armsrc/hfsnoop.c b/armsrc/hfsnoop.c index 06ec03ed6..cc72c7176 100644 --- a/armsrc/hfsnoop.c +++ b/armsrc/hfsnoop.c @@ -27,43 +27,43 @@ static void RAMFUNC optimizedSnoop(void) void HfSnoop(int samplesToSkip, int triggersToSkip) { BigBuf_free(); BigBuf_Clear(); - + Dbprintf("Skipping first %d sample pairs, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); int trigger_cnt = 0; LED_D_ON(); FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - + // Set up the synchronous serial port FpgaSetupSsc(); - // Setting Frame Mode For better performance on high speed data transfer. + // Setting Frame Mode For better performance on high speed data transfer. AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16); - + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNOOP); SpinDelay(100); - + uint16_t r = 0; while (!BUTTON_PRESS() && !usb_poll_validate_length() ) { WDT_HIT(); - + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { r = (uint16_t)AT91C_BASE_SSC->SSC_RHR; - r = MAX(r & 0xff, r >> 8); + r = MAX(r & 0xff, r >> 8); if (r >= 180) { // 0xB4 ?? if (++trigger_cnt > triggersToSkip) break; - } + } } } if (!BUTTON_PRESS()) { int waitcount = samplesToSkip; // lets wait 40000 ticks of pck0 while(waitcount != 0) { - + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) waitcount--; } @@ -72,7 +72,7 @@ void HfSnoop(int samplesToSkip, int triggersToSkip) } //Resetting Frame mode (First set in fpgaloader.c) - AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); + AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); DbpString("HF Snoop end"); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 6095d1639..32db10190 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -66,9 +66,9 @@ static enum { WRITE_STATE_PAGENUM_WRITTEN, WRITE_STATE_PROG } writestate; - -// ToDo: define a meaningful maximum size for auth_table. The bigger this is, the lower will be the available memory for traces. + +// ToDo: define a meaningful maximum size for auth_table. The bigger this is, the lower will be the available memory for traces. // Historically it used to be FREE_BUFFER_SIZE, which was 2744. #define AUTH_TABLE_LENGTH 2744 static uint8_t* auth_table; @@ -237,23 +237,23 @@ static int hitag2_cipher_transcrypt(uint64_t* cs, uint8_t *data, unsigned int by #define HITAG_T_TAG_ONE_HALF_PERIOD 10 #define HITAG_T_TAG_TWO_HALF_PERIOD 25 -#define HITAG_T_TAG_THREE_HALF_PERIOD 41 -#define HITAG_T_TAG_FOUR_HALF_PERIOD 57 +#define HITAG_T_TAG_THREE_HALF_PERIOD 41 +#define HITAG_T_TAG_FOUR_HALF_PERIOD 57 #define HITAG_T_TAG_HALF_PERIOD 16 #define HITAG_T_TAG_FULL_PERIOD 32 #define HITAG_T_TAG_CAPTURE_ONE_HALF 13 #define HITAG_T_TAG_CAPTURE_TWO_HALF 25 -#define HITAG_T_TAG_CAPTURE_THREE_HALF 41 -#define HITAG_T_TAG_CAPTURE_FOUR_HALF 57 +#define HITAG_T_TAG_CAPTURE_THREE_HALF 41 +#define HITAG_T_TAG_CAPTURE_FOUR_HALF 57 static void hitag_send_bit(int bit) { LED_A_ON(); - // Reset clock for the next bit + // Reset clock for the next bit AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - + // Fixed modulation, earlier proxmark version used inverted signal if(bit == 0) { // Manchester: Unloaded, then loaded |__--| @@ -291,20 +291,20 @@ static void hitag_send_frame(const uint8_t* frame, size_t frame_len) static void hitag2_handle_reader_command(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen) { uint8_t rx_air[HITAG_FRAME_LEN]; - + // Copy the (original) received frame how it is send over the air memcpy(rx_air,rx,nbytes(rxlen)); if(tag.crypto_active) { hitag2_cipher_transcrypt(&(tag.cs),rx,rxlen/8,rxlen%8); } - - // Reset the transmission frame length + + // Reset the transmission frame length *txlen = 0; - + // Try to find out which command was send by selecting on length (in bits) switch (rxlen) { - // Received 11000 from the reader, request for UID, send UID + // Received 11000 from the reader, request for UID, send UID case 05: { // Always send over the air in the clear plaintext mode if(rx_air[0] != 0xC0) { @@ -317,7 +317,7 @@ static void hitag2_handle_reader_command(uint8_t* rx, const size_t rxlen, uint8_ } break; - // Read/Write command: ..xx x..y yy with yyy == ~xxx, xxx is sector number + // Read/Write command: ..xx x..y yy with yyy == ~xxx, xxx is sector number case 10: { unsigned int sector = (~( ((rx[0]<<2)&0x04) | ((rx[1]>>6)&0x03) ) & 0x07); // Verify complement of sector index @@ -332,7 +332,7 @@ static void hitag2_handle_reader_command(uint8_t* rx, const size_t rxlen, uint8_ memcpy(tx,tag.sectors[sector],4); *txlen = 32; break; - + // Inverted Read command: 01xx x10y case 0x44: for (size_t i=0; i<4; i++) { @@ -349,7 +349,7 @@ static void hitag2_handle_reader_command(uint8_t* rx, const size_t rxlen, uint8_ tag.active_sector = sector; tag.state=TAG_STATE_WRITING; break; - + // Unknown command default: Dbprintf("Unknown command: %02x %02x",rx[0],rx[1]); @@ -409,7 +409,7 @@ static void hitag2_handle_reader_command(uint8_t* rx, const size_t rxlen, uint8_ // LogTraceHitag(rx,rxlen,0,0,false); // LogTraceHitag(tx,*txlen,0,0,true); - + if(tag.crypto_active) { hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen/8, *txlen%8); } @@ -417,22 +417,22 @@ static void hitag2_handle_reader_command(uint8_t* rx, const size_t rxlen, uint8_ static void hitag_reader_send_bit(int bit) { LED_A_ON(); - // Reset clock for the next bit + // Reset clock for the next bit AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - + // Binary puls length modulation (BPLM) is used to encode the data stream // This means that a transmission of a one takes longer than that of a zero - + // Enable modulation, which means, drop the field HIGH(GPIO_SSC_DOUT); - + // Wait for 4-10 times the carrier period while(AT91C_BASE_TC0->TC_CV < T0*6); // SpinDelayUs(8*8); - + // Disable modulation, just activates the field again LOW(GPIO_SSC_DOUT); - + if(bit == 0) { // Zero bit: |_-| while (AT91C_BASE_TC0->TC_CV < T0*22) {}; @@ -451,7 +451,7 @@ static void hitag_reader_send_frame(const uint8_t* frame, size_t frame_len) for(size_t i=0; i> (7-(i%8)))&1); } - // Send EOF + // Send EOF AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; // Enable modulation, which means, drop the field HIGH(GPIO_SSC_DOUT); @@ -466,7 +466,7 @@ size_t blocknr; static bool hitag2_password(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen) { // Reset the transmission frame length *txlen = 0; - + // Try to find out which command was send by selecting on length (in bits) switch (rxlen) { // No answer, try to resurrect @@ -479,7 +479,7 @@ static bool hitag2_password(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t *txlen = 5; memcpy(tx,"\xc0",nbytes(*txlen)); } break; - + // Received UID, tag password case 32: { if (!bPwd) { @@ -489,14 +489,14 @@ static bool hitag2_password(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t memcpy(tag.sectors[blocknr],rx,4); blocknr++; } else { - + if(blocknr == 1){ //store password in block1, the TAG answers with Block3, but we need the password in memory memcpy(tag.sectors[blocknr],tx,4); } else { memcpy(tag.sectors[blocknr],rx,4); } - + blocknr++; if (blocknr > 7) { DbpString("Read succesful!"); @@ -508,7 +508,7 @@ static bool hitag2_password(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t tx[1] = ((blocknr^7) << 6); } } break; - + // Unexpected response default: { Dbprintf("Uknown frame length: %d",rxlen); @@ -563,7 +563,7 @@ static bool hitag2_write_page(uint8_t* rx, const size_t rxlen, uint8_t* tx, size static bool hitag2_crypto(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen, bool write) { // Reset the transmission frame length *txlen = 0; - + if(bCrypto) { hitag2_cipher_transcrypt(&cipher_state,rx,rxlen/8,rxlen%8); } @@ -647,7 +647,7 @@ static bool hitag2_crypto(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* } } } break; - + // Unexpected response default: { Dbprintf("Uknown frame length: %d",rxlen); @@ -655,7 +655,7 @@ static bool hitag2_crypto(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* } break; } } - + if(bCrypto) { // We have to return now to avoid double encryption if (!bAuthenticating) { @@ -668,9 +668,9 @@ static bool hitag2_crypto(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* static bool hitag2_authenticate(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen) { - // Reset the transmission frame length + // Reset the transmission frame length *txlen = 0; - + // Try to find out which command was send by selecting on length (in bits) switch (rxlen) { // No answer, try to resurrect @@ -683,7 +683,7 @@ static bool hitag2_authenticate(uint8_t* rx, const size_t rxlen, uint8_t* tx, si *txlen = 5; memcpy(tx,"\xc0", nbytes(*txlen)); } break; - + // Received UID, crypto tag answer case 32: { if (!bCrypto) { @@ -695,23 +695,23 @@ static bool hitag2_authenticate(uint8_t* rx, const size_t rxlen, uint8_t* tx, si return true; } } break; - + // Unexpected response default: { Dbprintf("Uknown frame length: %d", rxlen); return false; } break; } - + return true; } static bool hitag2_test_auth_attempts(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen) { - // Reset the transmission frame length + // Reset the transmission frame length *txlen = 0; - + // Try to find out which command was send by selecting on length (in bits) switch (rxlen) { // No answer, try to resurrect @@ -736,7 +736,7 @@ static bool hitag2_test_auth_attempts(uint8_t* rx, const size_t rxlen, uint8_t* *txlen = 5; memcpy(tx,"\xc0",nbytes(*txlen)); } break; - + // Received UID, crypto tag answer, or read block response case 32: { if (!bCrypto) { @@ -753,13 +753,13 @@ static bool hitag2_test_auth_attempts(uint8_t* rx, const size_t rxlen, uint8_t* memcpy(NrAr,auth_table+auth_table_pos,8); } } break; - + default: { Dbprintf("Uknown frame length: %d",rxlen); return false; } break; } - + return true; } @@ -811,54 +811,54 @@ void SnoopHitag(uint32_t type) { int tag_sof; uint8_t rx[HITAG_FRAME_LEN]; size_t rxlen=0; - + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - + // free eventually allocated BigBuf memory BigBuf_free(); BigBuf_Clear_ext(false); - + // Clean up trace and prepare it for storing frames clear_trace(); set_tracing(true); - + auth_table_len = 0; auth_table_pos = 0; auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); memset(auth_table, 0x00, AUTH_TABLE_LENGTH); - + DbpString("Starting Hitag2 snoop"); LED_D_ON(); - + // Set up eavesdropping mode, frequency divisor which will drive the FPGA // and analog mux selection. FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); RELAY_OFF(); - + // Configure output pin that is connected to the FPGA (for modulating) AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; // Disable modulation, we are going to eavesdrop, not modulate ;) LOW(GPIO_SSC_DOUT); - + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - - // Disable timer during configuration + + // Disable timer during configuration AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - + // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on rising edge of TIOA. uint32_t t1_channel_mode = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH; AT91C_BASE_TC1->TC_CMR = t1_channel_mode; - + // Enable and reset counter AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - + // Reset the received frame, frame count and timing info memset(rx, 0x00, sizeof(rx)); frame_count = 0; @@ -868,18 +868,18 @@ void SnoopHitag(uint32_t type) { lastbit = 1; bSkip = true; tag_sof = 4; - + while(!BUTTON_PRESS() && !usb_poll_validate_length()) { // Watchdog hit WDT_HIT(); - + // Receive frame, watch for at most T0*EOF periods while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_EOF) { // Check if rising edge in modulation is detected if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values + // Retrieve the new timing values int ra = (AT91C_BASE_TC1->TC_RA/T0); - + // Find out if we are dealing with a rising or falling edge rising_edge = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME) > 0; @@ -891,17 +891,17 @@ void SnoopHitag(uint32_t type) { memset(rx,0x00,sizeof(rx)); rxlen = 0; } - + // Only handle if reader frame and rising edge, or tag frame and falling edge if (reader_frame != rising_edge) { overflow += ra; continue; } - + // Add the buffered timing values of earlier captured edges which were skipped ra += overflow; overflow = 0; - + if (reader_frame) { LED_B_ON(); // Capture reader frame @@ -912,11 +912,11 @@ void SnoopHitag(uint32_t type) { // Capture the T0 periods that have passed since last communication or field drop (reset) response = (ra - HITAG_T_LOW); } else if(ra >= HITAG_T_1_MIN ) { - // '1' bit + // '1' bit rx[rxlen / 8] |= 1 << (7-(rxlen%8)); rxlen++; } else if(ra >= HITAG_T_0_MIN) { - // '0' bit + // '0' bit rx[rxlen / 8] |= 0 << (7-(rxlen%8)); rxlen++; } else { @@ -942,7 +942,7 @@ void SnoopHitag(uint32_t type) { // Manchester coding example |_-|...|_-|-_| (0...01) rx[rxlen / 8] |= 0 << (7-(rxlen%8)); rxlen++; - // We have to skip this half period at start and add the 'one' the second time + // We have to skip this half period at start and add the 'one' the second time if (!bSkip) { rx[rxlen / 8] |= 1 << (7-(rxlen%8)); rxlen++; @@ -965,7 +965,7 @@ void SnoopHitag(uint32_t type) { } } } - + // Check if frame was captured if(rxlen > 0) { frame_count++; @@ -982,7 +982,7 @@ void SnoopHitag(uint32_t type) { auth_table_len += 8; } } - + // Reset the received frame and response timing info memset(rx,0x00,sizeof(rx)); response = 0; @@ -991,7 +991,7 @@ void SnoopHitag(uint32_t type) { bSkip = true; tag_sof = 4; overflow = 0; - + LED_B_OFF(); LED_C_OFF(); } else { @@ -1027,7 +1027,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data) { size_t txlen=0; bool bQuitTraceFull = false; bQuiet = false; - + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); // free eventually allocated BigBuf memory @@ -1036,7 +1036,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data) { // Clean up trace and prepare it for storing frames clear_trace(); set_tracing(true); - + auth_table_len = 0; auth_table_pos = 0; uint8_t* auth_table; @@ -1047,7 +1047,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data) { DbpString("Starting Hitag2 simulation"); LED_D_ON(); hitag2_init(); - + if (tag_mem_supplied) { DbpString("Loading hitag2 memory..."); memcpy((uint8_t*)tag.sectors,data,48); @@ -1061,7 +1061,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data) { } Dbprintf("| %d | %08x |",i,block); } - + // Set up simulator mode, frequency divisor which will drive the FPGA // and analog mux selection. FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); @@ -1076,21 +1076,21 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data) { // Disable modulation at default, which means release resistance LOW(GPIO_SSC_DOUT); - + // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); - + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - - // Disable timer during configuration + + // Disable timer during configuration AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on rising edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; - + // Reset the received frame, frame count and timing info memset(rx,0x00,sizeof(rx)); frame_count = 0; @@ -1099,24 +1099,24 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data) { // Enable and reset counter AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - + while(!BUTTON_PRESS() && !usb_poll_validate_length()) { // Watchdog hit WDT_HIT(); - + // Receive frame, watch for at most T0*EOF periods while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_EOF) { // Check if rising edge in modulation is detected if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values + // Retrieve the new timing values int ra = (AT91C_BASE_TC1->TC_RA/T0) + overflow; overflow = 0; // Reset timer every frame, we have to capture the last edge for timing AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - + LED_B_ON(); - + // Capture reader frame if(ra >= HITAG_T_STOP) { if (rxlen != 0) { @@ -1125,11 +1125,11 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data) { // Capture the T0 periods that have passed since last communication or field drop (reset) response = (ra - HITAG_T_LOW); } else if(ra >= HITAG_T_1_MIN ) { - // '1' bit + // '1' bit rx[rxlen / 8] |= 1 << (7-(rxlen%8)); rxlen++; } else if(ra >= HITAG_T_0_MIN) { - // '0' bit + // '0' bit rx[rxlen / 8] |= 0 << (7-(rxlen%8)); rxlen++; } else { @@ -1137,7 +1137,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data) { } } } - + // Check if frame was captured if(rxlen > 4) { frame_count++; @@ -1151,17 +1151,17 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data) { } } } - + // Disable timer 1 with external trigger to avoid triggers during our own modulation AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // Process the incoming frame (rx) and prepare the outgoing frame (tx) hitag2_handle_reader_command(rx,rxlen,tx,&txlen); - + // Wait for HITAG_T_WAIT_1 carrier periods after the last reader bit, // not that since the clock counts since the rising edge, but T_Wait1 is // with respect to the falling edge, we need to wait actually (T_Wait1 - T_Low) - // periods. The gap time T_Low varies (4..10). All timer values are in + // periods. The gap time T_Low varies (4..10). All timer values are in // terms of T0 units while(AT91C_BASE_TC0->TC_CV < T0*(HITAG_T_WAIT_1-HITAG_T_LOW)); @@ -1181,11 +1181,11 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data) { } } } - + // Reset the received frame and response timing info memset(rx,0x00,sizeof(rx)); response = 0; - + // Enable and reset external trigger in timer for capturing future frames AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; LED_B_OFF(); @@ -1202,7 +1202,7 @@ void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data) { AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - + DbpString("Sim Stopped"); set_tracing(false); } @@ -1217,20 +1217,20 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { size_t txlen = 0; int lastbit = 1; bool bSkip; - int reset_sof; + int reset_sof; int tag_sof; int t_wait = HITAG_T_WAIT_MAX; bool bStop = false; bool bQuitTraceFull = false; - + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); // Reset the return status bSuccessful = false; - + // Clean up trace and prepare it for storing frames clear_trace(); set_tracing(true); - + //DbpString("Starting Hitag reader family"); // Check configuration @@ -1243,7 +1243,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { bQuiet = false; bPwd = false; } break; - + case RHT2F_AUTHENTICATE: { DbpString("Authenticating using nr,ar pair:"); memcpy(NrAr,htd->auth.NrAr, 8); @@ -1253,7 +1253,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { bAuthenticating = false; bQuitTraceFull = true; } break; - + case RHT2F_CRYPTO: { DbpString("Authenticating using key:"); memcpy(key,htd->crypto.key, 6); //HACK; 4 or 6?? I read both in the code. @@ -1286,18 +1286,18 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { return; } break; } - + LED_D_ON(); hitag2_init(); - + // Configure output and enable pin that is connected to the FPGA (for modulating) AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - + // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); SpinDelay(20); - + // Set Frequency divisor which will drive the FPGA and analog mux selection FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); @@ -1308,21 +1308,21 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { // Give it a bit of time for the resonant antenna to settle. SpinDelay(30); - + // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - - // Disable timer during configuration + + // Disable timer during configuration AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - + // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on falling edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; - + // Enable and reset counters AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; @@ -1345,7 +1345,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { // DbpString("Configured for hitag2 reader"); } else { Dbprintf("Error, unknown hitag reader type: %d",htf); - set_tracing(false); + set_tracing(false); LED_D_OFF(); return; } @@ -1353,7 +1353,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { while (!bStop && !BUTTON_PRESS()) { // Watchdog hit WDT_HIT(); - + // Check if frame was captured and store it if (rxlen > 0) { frame_count++; @@ -1367,7 +1367,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { } } } - + // By default reset the transmission buffer tx = txbuf; switch (htf) { @@ -1396,18 +1396,18 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { return; } break; } - + // Send and store the reader command // Disable timer 1 with external trigger to avoid triggers during our own modulation AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - + // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, // Since the clock counts since the last falling edge, a 'one' means that the // falling edge occured halfway the period. with respect to this falling edge, // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. // All timer values are in terms of T0 units while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))); - + // Transmit the reader frame hitag_reader_send_frame(tx, txlen); @@ -1428,7 +1428,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { } } } - + // Reset values for receiving frames memset(rx, 0x00, sizeof(rx)); rxlen = 0; @@ -1437,19 +1437,19 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { tag_sof = reset_sof; response = 0; uint32_t errorCount = 0; - + // Receive frame, watch for at most T0*EOF periods while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { // Check if falling edge in tag modulation is detected if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values + // Retrieve the new timing values int ra = (AT91C_BASE_TC1->TC_RA/T0); - + // Reset timer every frame, we have to capture the last edge for timing AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - + LED_B_ON(); - + // Capture tag frame (manchester decoding using only falling edges) if (ra >= HITAG_T_EOF) { // Capture the T0 periods that have passed since last communication or field drop (reset) @@ -1465,7 +1465,7 @@ void ReaderHitag(hitag_function htf, hitag_data* htd) { // Manchester coding example |_-|...|_-|-_| (0...01) rx[rxlen / 8] |= 0 << (7-(rxlen%8)); rxlen++; - // We have to skip this half period at start and add the 'one' the second time + // We have to skip this half period at start and add the 'one' the second time if (!bSkip) { rx[rxlen / 8] |= 1 << (7-(rxlen%8)); rxlen++; @@ -1519,16 +1519,16 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { size_t txlen=0; int lastbit; bool bSkip; - int reset_sof; + int reset_sof; int tag_sof; int t_wait = HITAG_T_WAIT_MAX; bool bStop; bool bQuitTraceFull = false; - + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); // Reset the return status bSuccessful = false; - + // Clean up trace and prepare it for storing frames set_tracing(true); clear_trace(); @@ -1554,14 +1554,14 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { return; } break; } - + LED_D_ON(); hitag2_init(); - + // Configure output and enable pin that is connected to the FPGA (for modulating) AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - + // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); @@ -1575,21 +1575,21 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { // Give it a bit of time for the resonant antenna to settle. SpinDelay(30); - + // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - - // Disable timer during configuration + + // Disable timer during configuration AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - + // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on falling edge of TIOA. AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; - + // Enable and reset counters AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; @@ -1623,7 +1623,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { while(!bStop && !BUTTON_PRESS()) { // Watchdog hit WDT_HIT(); - + // Check if frame was captured and store it if(rxlen > 0) { frame_count++; @@ -1638,7 +1638,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { } } } - + // By default reset the transmission buffer tx = txbuf; switch(htf) { @@ -1650,20 +1650,20 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { return; } break; } - + // Send and store the reader command // Disable timer 1 with external trigger to avoid triggers during our own modulation AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - + // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, // Since the clock counts since the last falling edge, a 'one' means that the // falling edge occured halfway the period. with respect to this falling edge, // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. // All timer values are in terms of T0 units while(AT91C_BASE_TC0->TC_CV < T0*(t_wait+(HITAG_T_TAG_HALF_PERIOD*lastbit))); - + // Dbprintf("DEBUG: Sending reader frame"); - + // Transmit the reader frame hitag_reader_send_frame(tx,txlen); @@ -1699,14 +1699,14 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_WAIT_MAX) { // Check if falling edge in tag modulation is detected if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values + // Retrieve the new timing values int ra = (AT91C_BASE_TC1->TC_RA/T0); - + // Reset timer every frame, we have to capture the last edge for timing AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - + LED_B_ON(); - + // Capture tag frame (manchester decoding using only falling edges) if(ra >= HITAG_T_EOF) { if (rxlen != 0) { @@ -1728,14 +1728,14 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { rxlen++; } else if(ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { // Manchester coding example |_-|...|_-|-_| (0...01) - + // need to test to verify we don't exceed memory... // if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { // break; // } rx[rxlen / 8] |= 0 << (7-(rxlen%8)); rxlen++; - // We have to skip this half period at start and add the 'one' the second time + // We have to skip this half period at start and add the 'one' the second time if (!bSkip) { rx[rxlen / 8] |= 1 << (7-(rxlen%8)); rxlen++; @@ -1770,7 +1770,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { if (rxlen>0) break; } } - + // Wait some extra time for flash to be programmed if ((rxlen == 0) && (writestate == WRITE_STATE_PROG)) { @@ -1779,7 +1779,7 @@ void WriterHitag(hitag_function htf, hitag_data* htd, int page) { } } // Dbprintf("DEBUG: Done waiting for frame"); - + LED_B_OFF(); LED_D_OFF(); AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 59e2694e5..489cf9f7e 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -63,7 +63,7 @@ static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1 #define ht2bs_4a(a,b,c,d) (~(((a|b)&c)^(a|d)^b)) #define ht2bs_4b(a,b,c,d) (~(((d|c)&(a^b))^(d|a|b))) #define ht2bs_5c(a,b,c,d,e) (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c)))) -#define uf20bs u32 +#define uf20bs u32 static u32 f20(const u64 x) { u32 i5; @@ -127,12 +127,12 @@ static u32 hitag2_byte(u64 *x) { #define HITAG_T_TAG_ONE_HALF_PERIOD 10 #define HITAG_T_TAG_TWO_HALF_PERIOD 25 -#define HITAG_T_TAG_THREE_HALF_PERIOD 41 +#define HITAG_T_TAG_THREE_HALF_PERIOD 41 #define HITAG_T_TAG_FOUR_HALF_PERIOD 57 - + #define HITAG_T_TAG_HALF_PERIOD 16 #define HITAG_T_TAG_FULL_PERIOD 32 - + #define HITAG_T_TAG_CAPTURE_ONE_HALF 13 #define HITAG_T_TAG_CAPTURE_TWO_HALF 25 #define HITAG_T_TAG_CAPTURE_THREE_HALF 41 @@ -168,24 +168,24 @@ static void hitag_send_bit(int bit) { // AC Coding --__ HIGH(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 32) {}; - + LOW(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 64) {}; - + } else { // AC coding -_-_ HIGH(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; - + LOW(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 32) {}; - + HIGH(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 48) {}; - + LOW(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 64) {}; - + } LED_A_OFF(); break; @@ -194,21 +194,21 @@ static void hitag_send_bit(int bit) { // AC Coding --__ HIGH(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_HALF_PERIOD) {}; - + LOW(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_FULL_PERIOD) {}; - + } else { // AC coding -_-_ HIGH(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 8) {}; - + LOW(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; - + HIGH(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 24) {}; - + LOW(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 32) {}; } @@ -219,18 +219,18 @@ static void hitag_send_bit(int bit) { // Manchester: Unloaded, then loaded |__--| LOW(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; - + HIGH(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 32) {}; - + } else { // Manchester: Loaded, then unloaded |--__| HIGH(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; - + LOW(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 32) {}; - + } LED_A_OFF(); break; @@ -239,18 +239,18 @@ static void hitag_send_bit(int bit) { // Manchester: Unloaded, then loaded |__--| LOW(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 8) {}; - + HIGH(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; - + } else { // Manchester: Loaded, then unloaded |--__| HIGH(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 8) {}; - + LOW(GPIO_SSC_DOUT); while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; - + } LED_A_OFF(); break; @@ -288,7 +288,7 @@ static void hitag_reader_send_bit(int bit) { if (test == 1) { // Wait for 4-10 times the carrier period while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; - + // SpinDelayUs(8*8); // Disable modulation, just activates the field again @@ -297,18 +297,18 @@ static void hitag_reader_send_bit(int bit) { if (bit == 0) { // Zero bit: |_-| while (AT91C_BASE_TC0->TC_CV < T0 * 11) {}; - + // SpinDelayUs(16*8); } else { // One bit: |_--| while (AT91C_BASE_TC0->TC_CV < T0 * 14) {}; - + // SpinDelayUs(22*8); } } else { // Wait for 4-10 times the carrier period while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; - + // SpinDelayUs(8*8); // Disable modulation, just activates the field again @@ -317,12 +317,12 @@ static void hitag_reader_send_bit(int bit) { if (bit == 0) { // Zero bit: |_-| while (AT91C_BASE_TC0->TC_CV < T0 * 22) {}; - + // SpinDelayUs(16*8); } else { // One bit: |_--| while (AT91C_BASE_TC0->TC_CV < T0 * 28) {}; - + // SpinDelayUs(22*8); } } @@ -344,7 +344,7 @@ static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len) { HIGH(GPIO_SSC_DOUT); // Wait for 4-10 times the carrier period while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; - + // Disable modulation, just activates the field again LOW(GPIO_SSC_DOUT); } @@ -891,7 +891,7 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr } else if (tag.auth == 0) { tag.pstate = HT_SELECTED; } - + } else if (tag.pstate == HT_AUTHENTICATE && rxlen == 44) { //encrypted con2,password received. crc = CRC_PRESET; @@ -924,7 +924,7 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr if (DEBUG) Dbprintf("pwdh0 %02X pwdl0 %02X pwdl1 %02X", pwdh0, pwdl0, pwdl1); - + //Dbprintf("%X %02X", rnd, ((rx[4] & 0x0f) * 16) + ((rx[5] & 0xf0) / 16)); //rnd += 1; @@ -932,7 +932,7 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr tag.pstate = HT_SELECTED; //tag is now ready for read/write commands } return 0; - + } /* @@ -1185,7 +1185,7 @@ void ReadHitagS(hitag_function htf, hitag_data* htd) { unsigned char crc; unsigned char pageData[32]; page_to_be_written = 0; - + //read given key/challenge byte_t NrAr_[8]; uint64_t key = 0; @@ -1255,10 +1255,10 @@ void ReadHitagS(hitag_function htf, hitag_data* htd) { // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on falling edge of TIOA. - AT91C_BASE_TC1->TC_CMR = + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | - AT91C_TC_ETRGEDG_FALLING | - AT91C_TC_ABETRG | + AT91C_TC_ETRGEDG_FALLING | + AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; // Enable and reset counters @@ -1497,7 +1497,7 @@ void ReadHitagS(hitag_function htf, hitag_data* htd) { AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - + cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); } @@ -1523,7 +1523,7 @@ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) { int page = page_; unsigned char crc; byte_t data[4]= {0,0,0,0}; - + //read given key/challenge, the page and the data byte_t NrAr_[8]; uint64_t key=0; @@ -1541,7 +1541,7 @@ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) { case 04: { //WHTS_KEY memcpy(data,htd->crypto.data,4); DbpString("Authenticating using key:"); - memcpy(key_,htd->crypto.key,6); + memcpy(key_,htd->crypto.key,6); Dbhexdump(6,key_,false); key=key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40; } break; @@ -1639,7 +1639,7 @@ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) { //check for valid input if (page == 0) { Dbprintf( - "usage: lf hitag writer [03 | 04] [CHALLENGE | KEY] [page] [byte0] [byte1] [byte2] [byte3]"); + "usage: lf hitag writer [03 | 04] [CHALLENGE | KEY] [page] [byte0] [byte1] [byte2] [byte3]"); bStop = !false; } @@ -1863,7 +1863,7 @@ void check_challenges(bool file_given, byte_t* data) { // Set fpga in edge detect with reader field, we can modulate as reader now FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); SpinDelay(50); - + // Set Frequency divisor which will drive the FPGA and analog mux selection FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz SetAdcMuxFor(GPIO_MUXSEL_LOPKD); diff --git a/armsrc/iclass.c b/armsrc/iclass.c index 21cb9f299..af85c18fc 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -12,7 +12,7 @@ //----------------------------------------------------------------------------- // Based on ISO14443a implementation. Still in experimental phase. // Contribution made during a security research at Radboud University Nijmegen -// +// // Please feel free to contribute and extend iClass support!! //----------------------------------------------------------------------------- // @@ -21,7 +21,7 @@ // We still have sometimes a demodulation error when snooping iClass communication. // The resulting trace of a read-block-03 command may look something like this: // -// + 22279: : 0c 03 e8 01 +// + 22279: : 0c 03 e8 01 // // ...with an incorrect answer... // @@ -31,8 +31,8 @@ // // A correct trace should look like this: // -// + 21112: : 0c 03 e8 01 -// + 85: 0: TAG ff ff ff ff ff ff ff ff ea f5 +// + 21112: : 0c 03 e8 01 +// + 85: 0: TAG ff ff ff ff ff ff ff ff ea f5 // //----------------------------------------------------------------------------- @@ -60,7 +60,7 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf); // The length of a received command will in most cases be no more than 18 bytes. // 32 should be enough! -#ifndef ICLASS_BUFFER_SIZE +#ifndef ICLASS_BUFFER_SIZE #define ICLASS_BUFFER_SIZE 32 #endif @@ -172,7 +172,7 @@ static void uart_bit(uint8_t bit) { switch (buf) { case 0xbf: // 0 - 1011 1111 break; - case 0xef: // 1 - 1110 1111 + case 0xef: // 1 - 1110 1111 msg_byte |= (1<<6); break; case 0xfb: // 2 - 1111 1011 @@ -289,7 +289,7 @@ static RAMFUNC int OutOfNDecoding(int bit) { Uart.bitBuffer <<= 4; Uart.bitBuffer ^= bit; } - + // if (Uart.swapper) { // Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF; // Uart.byteCnt++; @@ -307,16 +307,16 @@ static RAMFUNC int OutOfNDecoding(int bit) { bit = 0; else bit = 1; - + if (((Uart.bitBuffer << 1) & Uart.syncBit) ^ Uart.syncBit) bitright = 0; else bitright = 1; - - if(bit != bitright) + + if(bit != bitright) bit = bitright; - + // So, now we only have to deal with *bit*, lets see... if (Uart.posCnt == 1) { // measurement first half bitperiod @@ -347,7 +347,7 @@ static RAMFUNC int OutOfNDecoding(int bit) { // measurement second half bitperiod // Count the bitslot we are in... (ISO 15693) Uart.nOutOfCnt++; - + if (!bit) { if (Uart.dropPosition) { if (Uart.state == STATE_START_OF_COMMUNICATION) { @@ -363,10 +363,10 @@ static RAMFUNC int OutOfNDecoding(int bit) { } } Uart.posCnt = 0; - + if (Uart.nOutOfCnt == Uart.OutOfCnt && Uart.OutOfCnt == 4) { Uart.nOutOfCnt = 0; - + if (Uart.state == STATE_START_OF_COMMUNICATION) { if (Uart.dropPosition == 4) { Uart.state = STATE_RECEIVING; @@ -390,12 +390,12 @@ static RAMFUNC int OutOfNDecoding(int bit) { //error = 9; } else { Uart.shiftReg >>= 2; - + // Swap bit order Uart.dropPosition--; //if(Uart.dropPosition == 1) { Uart.dropPosition = 2; } //else if(Uart.dropPosition == 2) { Uart.dropPosition = 1; } - + Uart.shiftReg ^= ((Uart.dropPosition & 0x03) << 6); Uart.bitCnt += 2; Uart.dropPosition = 0; @@ -459,13 +459,13 @@ static RAMFUNC int OutOfNDecoding(int bit) { Uart.posCnt = 1; // apparently we are busy with our first half bit period Uart.syncBit = bit & 8; Uart.samples = 3; - + if (!Uart.syncBit) { Uart.syncBit = bit & 4; Uart.samples = 2; } else if (bit & 4) { Uart.syncBit = bit & 4; Uart.samples = 2; bit <<= 2; } - + if (!Uart.syncBit) { Uart.syncBit = bit & 2; Uart.samples = 1; } else if (bit & 2) { Uart.syncBit = bit & 2; Uart.samples = 1; bit <<= 1; } - + if (!Uart.syncBit) { Uart.syncBit = bit & 1; Uart.samples = 0; if (Uart.syncBit && (Uart.bitBuffer & 8)) { Uart.syncBit = 8; @@ -519,7 +519,7 @@ static void DemodInit(uint8_t *data) { DemodReset(); } -// UART debug +// UART debug // it adds the debug values which will be put in the tracelog, // visible on client when running 'hf list iclass' /* @@ -562,11 +562,11 @@ static void uart_debug(int error, int bit) { /* * CARD TO READER -* in ISO15693-2 mode - Manchester +* in ISO15693-2 mode - Manchester * in ISO 14443b - BPSK coding * * Timings: -* ISO 15693-2 +* ISO 15693-2 * Tout = 330 µs, Tprog 1 = 4 to 15 ms, Tslot = 330 µs + (number of slots x 160 µs) * ISO 14443a * Tout = 100 µs, Tprog = 4 to 15 ms, Tslot = 100 µs+ (number of slots x 80 µs) @@ -645,7 +645,7 @@ static RAMFUNC int ManchesterDecoding_iclass( uint32_t v) { error = 0x88; uart_debug(error, bit); return false; - } + } } error = 0; } @@ -653,7 +653,7 @@ static RAMFUNC int ManchesterDecoding_iclass( uint32_t v) { } // state is DEMOD is in SYNC from here on. - + modulation = bit & Demod.syncBit; modulation |= ((bit << 1) ^ ((Demod.buffer & 0x08) >> 3)) & Demod.syncBit; Demod.samples += 4; @@ -667,13 +667,13 @@ static RAMFUNC int ManchesterDecoding_iclass( uint32_t v) { Demod.posCount = 0; if (modulation) { - + if (Demod.sub == SUB_FIRST_HALF) Demod.sub = SUB_BOTH; else Demod.sub = SUB_SECOND_HALF; } - + if (Demod.sub == SUB_NONE) { if (Demod.state == DEMOD_SOF_COMPLETE) { Demod.output[Demod.len] = 0x0f; @@ -687,7 +687,7 @@ static RAMFUNC int ManchesterDecoding_iclass( uint32_t v) { } switch (Demod.state) { - + case DEMOD_START_OF_COMMUNICATION: if (Demod.sub == SUB_BOTH) { @@ -700,7 +700,7 @@ static RAMFUNC int ManchesterDecoding_iclass( uint32_t v) { error = 0xd2; } break; - + case DEMOD_START_OF_COMMUNICATION2: if (Demod.sub == SUB_SECOND_HALF) { Demod.state = DEMOD_START_OF_COMMUNICATION3; @@ -710,7 +710,7 @@ static RAMFUNC int ManchesterDecoding_iclass( uint32_t v) { error = 0xd3; } break; - + case DEMOD_START_OF_COMMUNICATION3: if (Demod.sub == SUB_SECOND_HALF) { Demod.state = DEMOD_SOF_COMPLETE; @@ -720,7 +720,7 @@ static RAMFUNC int ManchesterDecoding_iclass( uint32_t v) { error = 0xd4; } break; - + case DEMOD_SOF_COMPLETE: case DEMOD_MANCHESTER_D: case DEMOD_MANCHESTER_E: @@ -782,7 +782,7 @@ static RAMFUNC int ManchesterDecoding_iclass( uint32_t v) { uart_debug(error, bit); return true; } - + return false; } @@ -796,7 +796,7 @@ static void iclass_setup_sniff(void){ LEDsoff(); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); // connect Demodulated Signal to ADC: @@ -805,7 +805,7 @@ static void iclass_setup_sniff(void){ // Set up the synchronous serial port FpgaSetupSsc(); - BigBuf_free(); BigBuf_Clear_ext(false); + BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); set_tracing(true); @@ -828,10 +828,10 @@ static void iclass_setup_sniff(void){ // put the FPGA in the appropriate mode FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER); SpinDelay(200); - + // Start the SSP timer StartCountSspClk(); - + LED_A_ON(); if (MF_DBGLEVEL > 3) Dbprintf("[+] iclass_setup_sniff Exit"); } @@ -844,15 +844,15 @@ static void iclass_setup_sniff(void){ // turn off afterwards void RAMFUNC SniffIClass(void) { - //int datalen = 0; - uint32_t previous_data = 0; + //int datalen = 0; + uint32_t previous_data = 0; uint32_t time_0 = 0, time_start = 0, time_stop = 0; uint32_t sniffCounter = 0; bool TagIsActive = false; bool ReaderIsActive = false; - + iclass_setup_sniff(); - + // The DMA buffer, used to stream samples from the FPGA // *dmaBuf is the start reference. uint8_t *dmaBuf = BigBuf_malloc(ICLASS_DMA_BUFFER_SIZE); @@ -861,7 +861,7 @@ void RAMFUNC SniffIClass(void) { // Setup and start DMA. if ( !FpgaSetupSscDma(dmaBuf, ICLASS_DMA_BUFFER_SIZE) ){ - if (MF_DBGLEVEL > 1) DbpString("[-] FpgaSetupSscDma failed. Exiting"); + if (MF_DBGLEVEL > 1) DbpString("[-] FpgaSetupSscDma failed. Exiting"); return; } @@ -881,8 +881,8 @@ void RAMFUNC SniffIClass(void) { previous_data <<= 8; previous_data |= *data; - - sniffCounter++; + + sniffCounter++; data++; if (data == dmaBuf + ICLASS_DMA_BUFFER_SIZE) { @@ -890,15 +890,15 @@ void RAMFUNC SniffIClass(void) { AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; AT91C_BASE_PDC_SSC->PDC_RNCR = ICLASS_DMA_BUFFER_SIZE; } - - if ( *data & 0xF) { + + if ( *data & 0xF) { //tag_byte <<= 1; tag_byte ^= (1 << 4); foo ^= (1 << (3 - div)); Dbprintf(" %d|%x == %d|%x", tag_byte, tag_byte, foo, foo); } div++; - + // every odd sample if (sniffCounter & 0x01) { // no need to try decoding reader data if the tag is sending @@ -928,23 +928,23 @@ void RAMFUNC SniffIClass(void) { LED_C_INV(); // LOW nibble is always tag data. /* - - - uint32_t tag_byte = + + + uint32_t tag_byte = ((previous_data & 0x0F000000) >> 8 ) | ((previous_data & 0x000F0000) >> 4 ) | ((previous_data & 0x00000F00) ) | ((previous_data & 0x0000000F) << 4 ) | (*data & 0xF); */ - - + + //uint8_t tag_byte = ((previous_data & 0xF) << 4 ) | (*data & 0xF); if (ManchesterDecoding_iclass(foo)) { time_stop = GetCountSspClk() - time_0; LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false); DemodReset(); - uart_reset(); + uart_reset(); } else { time_start = GetCountSspClk() - time_0; } @@ -956,16 +956,16 @@ void RAMFUNC SniffIClass(void) { } } // end main loop - if (MF_DBGLEVEL >= 1) { - DbpString("[+] Sniff statistics:"); + if (MF_DBGLEVEL >= 1) { + DbpString("[+] Sniff statistics:"); Dbhexdump(ICLASS_DMA_BUFFER_SIZE, data, false); } - - switch_off(); + + switch_off(); } void rotateCSN(uint8_t* originalCSN, uint8_t* rotatedCSN) { - int i; + int i; for(i = 0; i < 8; i++) rotatedCSN[i] = (originalCSN[i] >> 3) | (originalCSN[(i+1)%8] << 5); } @@ -976,13 +976,13 @@ void rotateCSN(uint8_t* originalCSN, uint8_t* rotatedCSN) { // Stop when button is pressed // Or return TRUE when command is captured //----------------------------------------------------------------------------- -static bool GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen) { +static bool GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen) { // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen // only, since we are receiving, not transmitting). // Signal field is off with the appropriate LED LED_D_OFF(); uart_init(received); - + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; @@ -1069,7 +1069,7 @@ static void CodeIClassTagAnswer(const uint8_t *cmd, int len) { * - A 1-bit input to the FPGA becomes 8 pulses on 423.5kHz (fc/32) (18.88us). * - A 0-bit input to the FPGA becomes an unmodulated time of 18.88us * - * In this mode + * In this mode * SOF can be written as 00011101 = 0x1D * EOF can be written as 10111000 = 0xb8 * logic 1 be written as 01 = 0x1 @@ -1080,7 +1080,7 @@ static void CodeIClassTagAnswer(const uint8_t *cmd, int len) { // Send SOF ToSend[++ToSendMax] = 0x1D; - + int i; for(i = 0; i < len; i++) { uint8_t b = cmd[i]; @@ -1095,7 +1095,7 @@ static void CodeIClassTagAnswer(const uint8_t *cmd, int len) { ToSendMax++; } -// Only SOF +// Only SOF static void CodeIClassTagSOF() { //So far a dummy implementation, not used //int lastProxToAirDuration =0; @@ -1133,7 +1133,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain FpgaDownloadAndGo(FPGA_BITSTREAM_HF); FpgaSetupSsc(); SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - + // Enable and clear the trace clear_trace(); set_tracing(true); @@ -1144,7 +1144,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain //Use the emulator memory for SIM uint8_t *emulator = BigBuf_get_EM_addr(); uint8_t mac_responses[USB_CMD_DATA_SIZE] = { 0 }; - + if (simType == 0) { // Use the CSN from commandline memcpy(emulator, datain, 8); @@ -1167,7 +1167,7 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain // The usb data is 512 bytes, fitting 65 8-byte CSNs in there. memcpy(emulator, datain + (i*8), 8); - + if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses+i * EPURSE_MAC_SIZE)) { // Button pressed cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i * EPURSE_MAC_SIZE); @@ -1185,12 +1185,12 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain // This is the KEYROLL version of sim 2. // the collected data (mac_response) is doubled out since we are trying to collect both keys in the keyroll process. // Keyroll iceman 9 csns * 8 * 2 = 144 - // keyroll CARL55 15csns * 8 * 2 = 15 * 8 * 2 = 240 + // keyroll CARL55 15csns * 8 * 2 = 15 * 8 * 2 = 240 Dbprintf("[+] going into attack keyroll mode, %d CSNS sent", numberOfCSNS); // In this mode, a number of csns are within datain. We'll simulate each one, one at a time // in order to collect MAC's from the reader. This can later be used in an offlne-attack // in order to obtain the keys, as in the "dismantling iclass"-paper. - + // keyroll mode, reader swaps between old key and new key alternatively when fail a authentication. // attack below is same as SIM 2, but we run the CSN twice to collected the mac for both keys. int i = 0; @@ -1198,32 +1198,32 @@ void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain for (; i < numberOfCSNS && i * EPURSE_MAC_SIZE + 8 < USB_CMD_DATA_SIZE; i++) { memcpy(emulator, datain + (i*8), 8); - - // keyroll 1 + + // keyroll 1 if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE )) { cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2); // Button pressed - goto out; + goto out; } // keyroll 2 if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + (i + numberOfCSNS) * EPURSE_MAC_SIZE )) { cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * EPURSE_MAC_SIZE* 2); // Button pressed - goto out; - } + goto out; + } } // double the amount of collected data. cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2 ); - + } else { // We may want a mode here where we hardcode the csns to use (from proxclone). // That will speed things up a little, but not required just yet. DbpString("[-] the mode is not implemented, reserved for future use"); } -out: - switch_off(); +out: + switch_off(); BigBuf_free_keep_EM(); } @@ -1236,13 +1236,13 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { // free eventually allocated BigBuf memory BigBuf_free_keep_EM(); - + State cipher_state; uint8_t *csn = BigBuf_get_EM_addr(); uint8_t *emulator = csn; uint8_t sof_data[] = { 0x0F} ; - + // CSN followed by two CRC bytes uint8_t anticoll_data[10] = { 0 }; uint8_t csn_data[10] = { 0 }; @@ -1254,7 +1254,7 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { // Compute CRC on both CSNs AddCrc(anticoll_data, 8); AddCrc(csn_data, 8); - + uint8_t diversified_key[8] = { 0 }; // e-Purse uint8_t card_challenge_data[8] = { 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; @@ -1272,8 +1272,8 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { // set epurse of sim2,4 attack if (reader_mac_buf != NULL) { memcpy(reader_mac_buf, card_challenge_data, 8); - } - + } + int exitLoop = 0; // Reader 0a // Tag 0f @@ -1306,13 +1306,13 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { int resp_conf_len; uint8_t conf_data[10] = {0x12,0xFF,0xFF,0xFF,0x7F,0x1F,0xFF,0x3C,0x00,0x00}; AddCrc(conf_data, 8); - + // e-Purse // 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/bit) uint8_t *resp_cc = BigBuf_malloc(28); int resp_cc_len; - // Application Issuer Area + // Application Issuer Area uint8_t *resp_aia = BigBuf_malloc(28); int resp_aia_len; uint8_t aia_data[10] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00}; @@ -1328,11 +1328,11 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { // First card answer: SOF CodeIClassTagSOF(); memcpy(resp_sof, ToSend, ToSendMax); resp_sof_Len = ToSendMax; - + // Anticollision CSN CodeIClassTagAnswer(anticoll_data, sizeof(anticoll_data)); memcpy(resp_anticoll, ToSend, ToSendMax); resp_anticoll_len = ToSendMax; - + // CSN CodeIClassTagAnswer(csn_data, sizeof(csn_data)); memcpy(resp_csn, ToSend, ToSendMax); resp_csn_len = ToSendMax; @@ -1340,7 +1340,7 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { // Configuration CodeIClassTagAnswer(conf_data, sizeof(conf_data)); memcpy(resp_conf, ToSend, ToSendMax); resp_conf_len = ToSendMax; - + // e-Purse CodeIClassTagAnswer(card_challenge_data, sizeof(card_challenge_data)); memcpy(resp_cc, ToSend, ToSendMax); resp_cc_len = ToSendMax; @@ -1374,7 +1374,7 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { //Signal tracer, can be used to get a trigger for an oscilloscope.. LED_B_OFF(); LED_C_OFF(); - + r2t_stime = (GetCountSspClk() - time_0) << 4; if (!GetIClassCommandFromReader(receivedCmd, &len, 0)) { buttonPressed = true; @@ -1382,7 +1382,7 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { continue; } r2t_etime = ((GetCountSspClk() - time_0) << 4 ) - r2t_stime; - + // 330us normal wait, adjusted for our execution LED_C_ON(); //Signal tracer @@ -1392,7 +1392,7 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { modulated_response = resp_sof; modulated_response_size = resp_sof_Len; //order = 1; trace_data = sof_data; trace_data_size = sizeof(sof_data); - // adjusted for 330 + (160*num of slot) + // adjusted for 330 + (160*num of slot) goto send; } else if (receivedCmd[0] == ICLASS_CMD_READ_OR_IDENTIFY) { // 0x0C if (len == 1) { @@ -1400,9 +1400,9 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { modulated_response = resp_anticoll; modulated_response_size = resp_anticoll_len; //order = 2; trace_data = anticoll_data; trace_data_size = sizeof(anticoll_data); - goto send; + goto send; } - if (len == 4){ + if (len == 4){ // block0,1,2,5 is always readable. switch (receivedCmd[1]){ case 0: // csn (0c 00) @@ -1415,7 +1415,7 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { trace_data = conf_data; trace_data_size = sizeof(conf_data); break; - case 2: // e-purse (0c 02) + case 2: // e-purse (0c 02) modulated_response = resp_cc; modulated_response_size = resp_cc_len; trace_data = card_challenge_data; trace_data_size = sizeof(card_challenge_data); @@ -1431,30 +1431,30 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { break; default: break; } - goto send; + goto send; } - + } else if (receivedCmd[0] == ICLASS_CMD_SELECT) { // 0x81 // Reader selects anticollission CSN. // Tag sends the corresponding real CSN modulated_response = resp_csn; modulated_response_size = resp_csn_len; //order = 3; trace_data = csn_data; trace_data_size = sizeof(csn_data); - goto send; + goto send; } else if (receivedCmd[0] == ICLASS_CMD_READCHECK_KD) { // 0x88 // Read e-purse (88 02) modulated_response = resp_cc; modulated_response_size = resp_cc_len; //order = 4; trace_data = card_challenge_data; trace_data_size = sizeof(card_challenge_data); LED_B_ON(); - goto send; + goto send; } else if (receivedCmd[0] == ICLASS_CMD_READCHECK_KC) { // 0x18 // Read e-purse (18 02) modulated_response = resp_cc; modulated_response_size = resp_cc_len; //order = 4; trace_data = card_challenge_data; trace_data_size = sizeof(card_challenge_data); LED_B_ON(); - goto send; + goto send; } else if (receivedCmd[0] == ICLASS_CMD_CHECK) { // 0x05 // Reader random and reader MAC!!! if (simulationMode == MODE_FULLSIM) { @@ -1473,9 +1473,9 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { modulated_response = resp_sof; modulated_response_size = 0; trace_data = NULL; trace_data_size = 0; - + if (simulationMode == MODE_EXIT_AFTER_MAC) { - + if ( MF_DBGLEVEL == MF_DBG_EXTENDED) { Dbprintf("[+] CSN: %02x %02x %02x %02x %02x %02x %02x %02x", csn[0], csn[1], csn[2], csn[3], csn[4], csn[5], csn[6], csn[7]); Dbprintf("[+] RDR: (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x", len, @@ -1512,7 +1512,7 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { modulated_response_size = ToSendMax; goto send; } else if (simulationMode == MODE_FULLSIM && receivedCmd[0] == ICLASS_CMD_UPDATE) { - + //Probably the reader wants to update the nonce. Let's just ignore that for now. // OBS! If this is implemented, don't forget to regenerate the cipher_state //We're expected to respond with the data+crc, exactly what's already in the receivedcmd @@ -1524,10 +1524,10 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { trace_data = data_generic_trace; trace_data_size = 10; CodeIClassTagAnswer(trace_data, trace_data_size); - + memcpy(data_response, ToSend, ToSendMax); modulated_response = data_response; - modulated_response_size = ToSendMax; + modulated_response_size = ToSendMax; // response_delay = 4600 * 1.5; // tPROG 4-15ms goto send; // } else if(receivedCmd[0] == ICLASS_CMD_PAGESEL) { // 0x84 @@ -1542,7 +1542,7 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { // Never seen this command before if ( MF_DBGLEVEL == MF_DBG_EXTENDED) print_result("[-] Unhandled command received ", receivedCmd, len); - + // Do not respond modulated_response = resp_sof; modulated_response_size = 0; //order = 0; @@ -1550,7 +1550,7 @@ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { trace_data_size = 0; } -send: +send: /** A legit tag has about 330us delay between reader EOT and tag SOF. **/ @@ -1561,21 +1561,21 @@ send: } LogTrace(receivedCmd, len, r2t_stime, r2t_etime, NULL, true); - + if (trace_data != NULL) LogTrace(trace_data, trace_data_size, t2r_stime, t2r_etime, NULL, false); } LEDsoff(); - + if (buttonPressed) DbpString("[+] button pressed"); - + return buttonPressed; } /** - * @brief sends our simulated tag answer + * @brief sends our simulated tag answer * @param resp * @param respLen * @param delay @@ -1584,12 +1584,12 @@ static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay) { int i = 0; volatile uint8_t b = 0; - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K_8BIT); - + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K_8BIT); + AT91C_BASE_SSC->SSC_THR = 0x00; - + while (!BUTTON_PRESS()) { - + // Prevent rx holding register from overflowing if ( (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)){ b = AT91C_BASE_SSC->SSC_RHR; (void) b; @@ -1626,7 +1626,7 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); AT91C_BASE_SSC->SSC_THR = 0x00; - + // make sure we timeout previous comms. if ( *wait ) SpinDelayUs(*wait); @@ -1640,7 +1640,7 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int // DOUBLE THE SAMPLES! if (firstpart) { - sendbyte = (cmd[c] & 0xf0) | (cmd[c] >> 4); + sendbyte = (cmd[c] & 0xf0) | (cmd[c] >> 4); } else { sendbyte = (cmd[c] & 0x0f) | (cmd[c] << 4); c++; @@ -1658,14 +1658,14 @@ static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int // Prevent rx holding register from overflowing if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { b = AT91C_BASE_SSC->SSC_RHR; (void)b; - } + } } if (samples) { if (wait) *samples = (c + *wait) << 3; else - *samples = c << 3; + *samples = c << 3; } } @@ -1684,7 +1684,7 @@ void CodeIClassCommand(const uint8_t* cmd, int len) { ToSend[++ToSendMax] = 0x0f; ToSend[++ToSendMax] = 0x00; - // Modulate the bytes + // Modulate the bytes for (i = 0; i < len; i++) { b = cmd[i]; for (j = 0; j < 4; j++) { @@ -1693,7 +1693,7 @@ void CodeIClassCommand(const uint8_t* cmd, int len) { if (k == (b & 3)) ToSend[++ToSendMax] = 0xf0; else - ToSend[++ToSendMax] = 0x00; + ToSend[++ToSendMax] = 0x00; } b >>= 2; } @@ -1720,9 +1720,9 @@ void ReaderTransmitIClass_ext(uint8_t* frame, int len, int wait) { TransmitIClassCommand(ToSend, ToSendMax, &samples, &wait); if (trigger) LED_A_ON(); - + rsamples += samples; - + LogTrace(frame, len, rsamples, rsamples, NULL, true); } void ReaderTransmitIClass(uint8_t* frame, int len) { @@ -1741,7 +1741,7 @@ static int GetIClassAnswer(uint8_t* receivedResponse, int maxLen, int *samples, int c = 0; bool skip = false; - // Setup UART/DEMOD to receive + // Setup UART/DEMOD to receive DemodInit(receivedResponse); if (elapsed) *elapsed = 0; @@ -1759,7 +1759,7 @@ static int GetIClassAnswer(uint8_t* receivedResponse, int maxLen, int *samples, // keep tx buffer in a defined state anyway. if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x00; + AT91C_BASE_SSC->SSC_THR = 0x00; // To make use of exact timing of next command from reader!! if (elapsed) (*elapsed)++; } @@ -1769,14 +1769,14 @@ static int GetIClassAnswer(uint8_t* receivedResponse, int maxLen, int *samples, if (c >= timeout) return false; c++; - + b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - - skip = !skip; + + skip = !skip; if (skip) continue; - + if (ManchesterDecoding_iclass(b & 0x0f)) { - if (samples) + if (samples) *samples = c << 3; return true; } @@ -1788,16 +1788,16 @@ static int GetIClassAnswer(uint8_t* receivedResponse, int maxLen, int *samples, int ReaderReceiveIClass(uint8_t* receivedAnswer) { int samples = 0; - if (!GetIClassAnswer(receivedAnswer, 0, &samples, NULL)) + if (!GetIClassAnswer(receivedAnswer, 0, &samples, NULL)) return false; rsamples += samples; LogTrace(receivedAnswer, Demod.len, rsamples, rsamples, NULL, false); - if (samples == 0) + if (samples == 0) return false; - + return Demod.len; } @@ -1808,9 +1808,9 @@ void setupIclassReader() { // Start from off (no field generated) // Signal field is off with the appropriate LED FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - + FpgaSetupSsc(); SetAdcMuxFor(GPIO_MUXSEL_HIPKD); @@ -1822,28 +1822,28 @@ void setupIclassReader() { // Signal field is on with the appropriate LED FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); SpinDelay(300); - + StartCountSspClk(); - + LED_A_ON(); } bool sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, uint8_t expected_size, uint8_t retries) { uint8_t got_n = 0; while (retries-- > 0) { - + ReaderTransmitIClass(command, cmdsize); - + //iceman - if received size is bigger than expected, we smash the stack here // since its called with fixed sized arrays got_n = ReaderReceiveIClass(resp); - + // 0xBB is the internal debug separator byte.. if ( expected_size != got_n|| (resp[0] == 0xBB || resp[7] == 0xBB || resp[2] == 0xBB)) { //try again continue; } - + if (got_n == expected_size) return true; } @@ -1865,7 +1865,7 @@ uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key) { static uint8_t select[] = { ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK_KD, 0x02 }; - if (use_credit_key) + if (use_credit_key) readcheck_cc[0] = ICLASS_CMD_READCHECK_KC; uint8_t resp[ICLASS_BUFFER_SIZE] = {0}; @@ -1873,7 +1873,7 @@ uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key) { // Send act_all ReaderTransmitIClass_ext(act_all, 1, 330+160); - // Card present? + // Card present? if (!ReaderReceiveIClass(resp)) return read_status;//Fail //Send Identify @@ -1885,10 +1885,10 @@ uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key) { //Copy the Anti-collision CSN to our select-packet memcpy(&select[1], resp, 8); - + //Select the card ReaderTransmitIClass(select, sizeof(select)); - + //We expect a 10-byte response here, 8 byte CSN and 2 byte CRC len = ReaderReceiveIClass(resp); if (len != 10) return read_status;//Fail @@ -1907,10 +1907,10 @@ uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key) { // memcpy(card_data+8, resp, 8); // read_status++; // } - + bool isOK = sendCmdGetResponseWithRetries(readcheck_cc, sizeof(readcheck_cc), resp, 8, 3); if (!isOK) return read_status; - + //Save CC (e-purse) in response data memcpy(card_data+8, resp, 8); read_status++; @@ -1930,17 +1930,17 @@ void ReaderIClass(uint8_t arg0) { memset(card_data, 0xFF, sizeof(card_data)); memset(resp, 0xFF, sizeof(resp)); - + //Read conf block CRC(0x01) => 0xfa 0x22 uint8_t readConf[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x01, 0xfa, 0x22}; - + //Read App Issuer Area block CRC(0x05) => 0xde 0x64 uint8_t readAA[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64}; int read_status = 0; uint16_t tryCnt = 0; uint8_t result_status = 0; - + bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; // flag to read until one tag is found successfully bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY; // flag to not to loop continuously, looking for tag bool use_credit_key = arg0 & FLAG_ICLASS_READER_CEDITKEY; // flag to use credit key @@ -1958,9 +1958,9 @@ void ReaderIClass(uint8_t arg0) { // if only looking for one card try 2 times if we missed it the first time if (try_once && tryCnt > 2) { if (MF_DBGLEVEL > 1) DbpString("Failed to find a tag"); - break; + break; } - + tryCnt++; result_status = 0; @@ -1998,7 +1998,7 @@ void ReaderIClass(uint8_t arg0) { // 0 : CSN // 1 : Configuration // 2 : e-purse - // 3 : kd / debit / aa2 (write-only) + // 3 : kd / debit / aa2 (write-only) // 4 : kc / credit / aa1 (write-only) // 5 : AIA, Application issuer area // @@ -2006,8 +2006,8 @@ void ReaderIClass(uint8_t arg0) { // with 0xFF:s in block 3 and 4. LED_B_ON(); - //Send back to client, but don't bother if we already sent this - - // only useful if looping in arm (not try_once && not abort_after_read) + //Send back to client, but don't bother if we already sent this - + // only useful if looping in arm (not try_once && not abort_after_read) if (memcmp(last_csn, card_data, 8) != 0) { // If caller requires that we get Conf, CC, AA, continue until we got it if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { @@ -2016,7 +2016,7 @@ void ReaderIClass(uint8_t arg0) { (result_status & FLAG_ICLASS_READER_CSN) ? 'Y':'N', (result_status & FLAG_ICLASS_READER_CONF)? 'Y':'N', (result_status & FLAG_ICLASS_READER_CC) ? 'Y':'N', - (result_status & FLAG_ICLASS_READER_AIA) ? 'Y':'N' + (result_status & FLAG_ICLASS_READER_AIA) ? 'Y':'N' ); Dbprintf(" aar %c | to %c, | uc %c | frc %c | fra %c | cc %c", abort_after_read ? 'Y':'N', @@ -2027,7 +2027,7 @@ void ReaderIClass(uint8_t arg0) { flagReadCC ? 'Y':'N' ); } - + bool send = (result_status & FLAG_ICLASS_READER_CSN ); if (flagReadCC) send |= (result_status & FLAG_ICLASS_READER_CC ); @@ -2035,9 +2035,9 @@ void ReaderIClass(uint8_t arg0) { send |= (result_status & FLAG_ICLASS_READER_AIA ); if (flagReadConfig) send |= (result_status & FLAG_ICLASS_READER_CONF ); - + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SEND %c", send?'y':'n'); - + if ( send ) { cmd_send(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data) ); if (abort_after_read) { @@ -2051,7 +2051,7 @@ void ReaderIClass(uint8_t arg0) { LED_B_OFF(); userCancelled = BUTTON_PRESS() || usb_poll_validate_length(); } - + if (userCancelled) { cmd_send(CMD_ACK, 0xFF, 0, 0, card_data, 0); switch_off(); @@ -2076,14 +2076,14 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { int k2; int lockauth; int keyaccess; - } memory; - + } memory; + setupIclassReader(); while (!BUTTON_PRESS()) { - + WDT_HIT(); - + uint8_t read_status = handshakeIclassTag(card_data); if (read_status < 2) continue; @@ -2176,7 +2176,7 @@ void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { card_data, 0 ); - switch_off(); + switch_off(); } // not used. ?!? ( CMD_ICLASS_READCHECK) @@ -2187,10 +2187,10 @@ void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType) { size_t isOK = 0; isOK = sendCmdGetResponseWithRetries(readcheck, sizeof(readcheck), resp, sizeof(resp), 6); cmd_send(CMD_ACK,isOK,0,0,0,0); - switch_off(); + switch_off(); } -// used with function select_and_auth (cmdhficlass.c) +// used with function select_and_auth (cmdhficlass.c) // which needs to authenticate before doing more things like read/write void iClass_Authentication(uint8_t *mac) { uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; @@ -2202,8 +2202,8 @@ void iClass_Authentication(uint8_t *mac) { check[7] = mac[2]; check[8] = mac[3]; //memcpy(check+5, mac, 4); - - // 6 retries + + // 6 retries bool isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 6); cmd_send(CMD_ACK,isOK,0,0,0,0); } @@ -2213,7 +2213,7 @@ typedef struct iclass_premac { } iclass_premac_t; /* this function works on the following assumptions. -* - one select first, to get CSN / CC (e-purse) +* - one select first, to get CSN / CC (e-purse) * - calculate before diversified keys and precalc mac based on CSN/KEY. * - data in contains of diversified keys, mac * - key loop only test one type of authtication key. Ie two calls needed @@ -2225,77 +2225,77 @@ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) { bool use_credit_key =((arg0 >> 16) & 0xFF); uint8_t keyCount = arg1 & 0xFF; uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t resp[ICLASS_BUFFER_SIZE]; + uint8_t resp[ICLASS_BUFFER_SIZE]; uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK_KD, 0x02 }; - if (use_credit_key) + if (use_credit_key) readcheck_cc[0] = ICLASS_CMD_READCHECK_KC; - + // select card / e-purse uint8_t card_data[6 * 8] = {0}; - + iclass_premac_t *keys = (iclass_premac_t *)datain; - + LED_A_ON(); - + switch_off(); SpinDelay(20); - + setupIclassReader(); int read_status = 0; uint8_t startup_limit = 10; while ( read_status != 2) { - + if (BUTTON_PRESS() && !usb_poll_validate_length()) goto out; - + read_status = handshakeIclassTag_ext(card_data, use_credit_key); if ( startup_limit-- == 0 ) { Dbprintf("[-] Handshake status | %d (fail 10)", read_status); - isOK = 99; + isOK = 99; goto out; } }; // since handshakeIclassTag_ext call sends s readcheck, we start with sending first response. - + // Keychunk loop for (i = 0; i < keyCount; i++) { - + // Allow button press / usb cmd to interrupt device if (BUTTON_PRESS() && !usb_poll_validate_length()) break; WDT_HIT(); - LED_B_ON(); - + LED_B_ON(); + // copy MAC to check command (readersignature) check[5] = keys[i].mac[0]; check[6] = keys[i].mac[1]; check[7] = keys[i].mac[2]; check[8] = keys[i].mac[3]; - + // expect 4bytes, 3 retries times.. isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 3); if ( isOK ) goto out; - + SpinDelayUs(400); //iClass (iso15693-2) should timeout after 330us. - // Auth Sequence MUST begin with reading e-purse. (block2) - // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC) - ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); - - LED_B_OFF(); + // Auth Sequence MUST begin with reading e-purse. (block2) + // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC) + ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); + + LED_B_OFF(); } - -out: + +out: // send keyindex. cmd_send(CMD_ACK, isOK, i, 0, 0, 0); - + if ( isOK >= 1 || lastChunk ) { switch_off(); LED_A_OFF(); } - + LED_B_OFF(); LED_C_OFF(); } @@ -2318,7 +2318,7 @@ void iClass_ReadBlk(uint8_t blockno) { uint8_t data[] = {0,0,0,0,0,0,0,0,0,0}; bool isOK = iClass_ReadBlock(blockno, data, sizeof(data)); cmd_send(CMD_ACK, isOK, 0, 0, data, sizeof(data)); - switch_off(); + switch_off(); } // turn off afterwards @@ -2339,7 +2339,7 @@ void iClass_Dump(uint8_t blockno, uint8_t numblks) { for (;blkCnt < numblks; blkCnt++) { isOK = iClass_ReadBlock(blockno + blkCnt, blockdata, sizeof(blockdata)); - + // 0xBB is the internal debug separator byte.. if (!isOK || (blockdata[0] == 0xBB || blockdata[7] == 0xBB || blockdata[2] == 0xBB)) { //try again isOK = iClass_ReadBlock(blockno + blkCnt, blockdata, sizeof(blockdata)); @@ -2352,7 +2352,7 @@ void iClass_Dump(uint8_t blockno, uint8_t numblks) { } //return pointer to dump memory in arg3 cmd_send(CMD_ACK, isOK, blkCnt, BigBuf_max_traceLen(), 0, 0); - switch_off(); + switch_off(); BigBuf_free(); } @@ -2372,7 +2372,7 @@ bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) { //if not programming key areas (note key blocks don't get programmed with actual key data it is xor data) if (blockNo != 3 && blockNo != 4) { isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 5); - } + } } } return isOK; @@ -2382,7 +2382,7 @@ bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) { void iClass_WriteBlock(uint8_t blockNo, uint8_t *data) { bool isOK = iClass_WriteBlock_ext(blockNo, data); cmd_send(CMD_ACK,isOK,0,0,0,0); - switch_off(); + switch_off(); } // turn off afterwards @@ -2406,8 +2406,8 @@ void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) { if (written == total_block) DbpString("Clone complete"); else - DbpString("Clone incomplete"); + DbpString("Clone incomplete"); cmd_send(CMD_ACK,1,0,0,0,0); - switch_off(); + switch_off(); } \ No newline at end of file diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 4267d28af..9e415fcdb 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -29,8 +29,8 @@ static uint8_t* free_buffer_pointer; // // minimum time between the start bits of consecutive transfers from reader to tag: 7000 carrier (13.56Mhz) cycles #define REQUEST_GUARD_TIME (7000/16 + 1) -// minimum time between last modulation of tag and next start bit from reader to tag: 1172 carrier cycles -#define FRAME_DELAY_TIME_PICC_TO_PCD (1172/16 + 1) +// minimum time between last modulation of tag and next start bit from reader to tag: 1172 carrier cycles +#define FRAME_DELAY_TIME_PICC_TO_PCD (1172/16 + 1) // bool LastCommandWasRequest = false; // @@ -42,8 +42,8 @@ static uint8_t* free_buffer_pointer; // 8 ticks until bit_to_arm is assigned from curbit // 8*16 ticks for the transfer from FPGA to ARM // 4*16 ticks until we measure the time -// - 8*16 ticks because we measure the time of the previous transfer -#define DELAY_AIR2ARM_AS_READER (3 + 16 + 8 + 8*16 + 4*16 - 8*16) +// - 8*16 ticks because we measure the time of the previous transfer +#define DELAY_AIR2ARM_AS_READER (3 + 16 + 8 + 8*16 + 4*16 - 8*16) // When the PM acts as a reader and is sending, it takes // 4*16 ticks until we can write data to the sending hold register @@ -60,10 +60,10 @@ static uint8_t* free_buffer_pointer; // 8 ticks until the SSC samples the first data // 7*16 ticks to complete the transfer from FPGA to ARM // 8 ticks until the next ssp_clk rising edge -// 4*16 ticks until we measure the time -// - 8*16 ticks because we measure the time of the previous transfer +// 4*16 ticks until we measure the time +// - 8*16 ticks because we measure the time of the previous transfer #define DELAY_AIR2ARM_AS_TAG (2 + 3 + 8 + 8 + 7*16 + 8 + 4*16 - 8*16) - + // The FPGA will report its internal sending delay in uint16_t FpgaSendQueueDelay; // the 5 first bits are the number of bits buffered in mod_sig_buf @@ -85,16 +85,16 @@ uint16_t FpgaSendQueueDelay; // 8 ticks (on average) until the result is stored in to_arm // + the delays in transferring data - which is the same for // sniffing reader and tag data and therefore not relevant -#define DELAY_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8) - +#define DELAY_TAG_AIR2ARM_AS_SNIFFER (3 + 14 + 8) + // When the PM acts as sniffer and is receiving reader data, it takes -// 2 ticks delay in analogue RF receiver (for the falling edge of the +// 2 ticks delay in analogue RF receiver (for the falling edge of the // start bit, which marks the start of the communication) // 3 ticks A/D conversion // 8 ticks on average until the data is stored in to_arm. // + the delays in transferring data - which is the same for // sniffing reader and tag data and therefore not relevant -#define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8) +#define DELAY_READER_AIR2ARM_AS_SNIFFER (2 + 3 + 8) //variables used for timing purposes: //these are in ssp_clk cycles: @@ -106,7 +106,7 @@ static uint32_t LastProxToAirDuration; // Sequence D: 11110000 modulation with subcarrier during first half // Sequence E: 00001111 modulation with subcarrier during second half // Sequence F: 00000000 no modulation with subcarrier -// Sequence COLL: 11111111 load modulation over the full bitlenght. +// Sequence COLL: 11111111 load modulation over the full bitlenght. // Tricks the reader to think that multiple cards answer (at least one card with 1 and at least one card with 0). // READER TO CARD - miller // Sequence X: 00001100 drop after half a period @@ -154,7 +154,7 @@ void GetParity(const uint8_t *pbtCmd, uint16_t iLen, uint8_t *par) { } // save remaining parity bits - par[paritybyte_cnt] = parityBits; + par[paritybyte_cnt] = parityBits; } @@ -163,8 +163,8 @@ void GetParity(const uint8_t *pbtCmd, uint16_t iLen, uint8_t *par) { //============================================================================= // Basics: // This decoder is used when the PM3 acts as a tag. -// The reader will generate "pauses" by temporarily switching of the field. -// At the PM3 antenna we will therefore measure a modulated antenna voltage. +// The reader will generate "pauses" by temporarily switching of the field. +// At the PM3 antenna we will therefore measure a modulated antenna voltage. // The FPGA does a comparison with a threshold and would deliver e.g.: // ........ 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 ....... // The Miller decoder needs to identify the following sequences: @@ -216,17 +216,17 @@ void UartInit(uint8_t *data, uint8_t *parity) { // use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) { Uart.fourBits = (Uart.fourBits << 8) | bit; - + if (Uart.state == STATE_UNSYNCD) { // not yet synced Uart.syncBit = 9999; // not set - + // 00x11111 2|3 ticks pause followed by 6|5 ticks unmodulated Sequence Z (a "0" or "start of communication") // 11111111 8 ticks unmodulation Sequence Y (a "0" or "end of communication" or "no information") // 111100x1 4 ticks unmodulated followed by 2|3 ticks pause Sequence X (a "1") // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111) - // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern + // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's) #define ISO14443A_STARTBIT_MASK 0x07FFEF80 // mask is 00000111 11111111 11101111 10000000 #define ISO14443A_STARTBIT_PATTERN 0x07FF8F80 // pattern is 00000111 11111111 10001111 10000000 @@ -247,7 +247,7 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) { } } else { - if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) { + if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) { if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation in both halves - error UartReset(); } else { // Modulation in first half = Sequence Z = logic "0" @@ -329,8 +329,8 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) { } } } - } - } + } + } return false; // not finished yet, need more data } @@ -369,12 +369,12 @@ void DemodReset(void) { Demod.len = 0; // number of decoded data bytes Demod.parityLen = 0; Demod.shiftReg = 0; // shiftreg to hold decoded data bits - Demod.parityBits = 0; // + Demod.parityBits = 0; // Demod.collisionPos = 0; // Position of collision bit Demod.twoBits = 0xFFFF; // buffer for 2 Bits Demod.highCnt = 0; Demod.startTime = 0; - Demod.endTime = 0; + Demod.endTime = 0; Demod.bitCount = 0; Demod.syncBit = 0xFFFF; Demod.samples = 0; @@ -389,7 +389,7 @@ void DemodInit(uint8_t *data, uint8_t *parity) { // use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time) { Demod.twoBits = (Demod.twoBits << 8) | bit; - + if (Demod.state == DEMOD_UNSYNCD) { if (Demod.highCnt < 2) { // wait for a stable unmodulated signal @@ -400,7 +400,7 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t } } else { Demod.syncBit = 0xFFFF; // not set - if ((Demod.twoBits & 0x7700) == 0x7000) Demod.syncBit = 7; + if ((Demod.twoBits & 0x7700) == 0x7000) Demod.syncBit = 7; else if ((Demod.twoBits & 0x3B80) == 0x3800) Demod.syncBit = 6; else if ((Demod.twoBits & 0x1DC0) == 0x1C00) Demod.syncBit = 5; else if ((Demod.twoBits & 0x0EE0) == 0x0E00) Demod.syncBit = 4; @@ -493,21 +493,21 @@ void RAMFUNC SniffIso14443a(uint8_t param) { // bit 0 - trigger from first card answer // bit 1 - trigger from first reader 7-bit request iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); - + // Allocate memory from BigBuf for some buffers // free all previous allocations first BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); set_tracing(true); - + // The command (reader -> tag) that we're receiving. uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE); - + // The response (tag -> reader) that we're receiving. uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE); uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE); - + // The DMA buffer, used to stream samples from the FPGA uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); uint8_t *data = dmaBuf; @@ -517,29 +517,29 @@ void RAMFUNC SniffIso14443a(uint8_t param) { int dataLen = 0; bool TagIsActive = false; bool ReaderIsActive = false; - + // Set up the demodulator for tag -> reader responses. DemodInit(receivedResp, receivedRespPar); - + // Set up the demodulator for the reader -> tag commands UartInit(receivedCmd, receivedCmdPar); - + // Setup and start DMA. if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE) ){ - if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); + if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); return; } - + // We won't start recording the frames that we acquire until we trigger; // a good trigger condition to get started is probably when we see a // response from the tag. // triggered == false -- to wait first for card - bool triggered = !(param & 0x03); - + bool triggered = !(param & 0x03); + uint32_t rsamples = 0; DbpString("Starting to sniff"); - + // loop and listen while (!BUTTON_PRESS()) { WDT_HIT(); @@ -551,7 +551,7 @@ void RAMFUNC SniffIso14443a(uint8_t param) { dataLen = dmaBufDataP - readBufDataP; else dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; - + // test for length of buffer if (dataLen > maxDataLen) { maxDataLen = dataLen; @@ -575,7 +575,7 @@ void RAMFUNC SniffIso14443a(uint8_t param) { } LED_A_OFF(); - + // Need two samples to feed Miller and Manchester-Decoder if (rsamples & 0x01) { @@ -588,11 +588,11 @@ void RAMFUNC SniffIso14443a(uint8_t param) { if ((!triggered) && (param & 0x02) && (Uart.len == 1) && (Uart.bitCount == 7)) triggered = true; if (triggered) { - if (!LogTrace(receivedCmd, - Uart.len, + if (!LogTrace(receivedCmd, + Uart.len, Uart.startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, - Uart.parity, + Uart.parity, true)) break; } /* ready to receive another command. */ @@ -606,14 +606,14 @@ void RAMFUNC SniffIso14443a(uint8_t param) { } // no need to try decoding tag data if the reader is sending - and we cannot afford the time - if (!ReaderIsActive) { + if (!ReaderIsActive) { uint8_t tagdata = (previous_data << 4) | (*data & 0x0F); if (ManchesterDecoding(tagdata, 0, (rsamples-1)*4)) { LED_B_ON(); - if (!LogTrace(receivedResp, - Demod.len, - Demod.startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, + if (!LogTrace(receivedResp, + Demod.len, + Demod.startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, Demod.endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, Demod.parity, false)) break; @@ -626,7 +626,7 @@ void RAMFUNC SniffIso14443a(uint8_t param) { UartReset(); //UartInit(receivedCmd, receivedCmdPar); LED_C_OFF(); - } + } TagIsActive = (Demod.state != DEMOD_UNSYNCD); } } @@ -643,14 +643,14 @@ void RAMFUNC SniffIso14443a(uint8_t param) { Dbprintf("maxDataLen=%d, Uart.state=%x, Uart.len=%d", maxDataLen, Uart.state, Uart.len); Dbprintf("traceLen=%d, Uart.output[0]=%08x", BigBuf_get_traceLen(), (uint32_t)Uart.output[0]); } - switch_off(); + switch_off(); } //----------------------------------------------------------------------------- // Prepare tag messages //----------------------------------------------------------------------------- static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *parity, bool collision) { - + //uint8_t localCol = 0; ToSendReset(); @@ -663,7 +663,7 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par ToSendStuffBit(0); ToSendStuffBit(0); ToSendStuffBit(0); - + // Send startbit ToSend[++ToSendMax] = SEC_D; LastProxToAirDuration = 8 * ToSendMax - 4; @@ -676,7 +676,7 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par //if (collision && (localCol >= colpos)){ if (collision) { ToSend[++ToSendMax] = SEC_COLL; - //localCol++; + //localCol++; } else { if (b & 1) { ToSend[++ToSendMax] = SEC_D; @@ -689,7 +689,7 @@ static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *par if (collision) { ToSend[++ToSendMax] = SEC_COLL; - LastProxToAirDuration = 8 * ToSendMax; + LastProxToAirDuration = 8 * ToSendMax; } else { // Get the parity bit if (parity[i>>3] & (0x80>>(i&0x0007))) { @@ -817,12 +817,12 @@ bool prepare_tag_modulation(tag_response_info_t* response_info, size_t max_buffe } // "precompile" responses. There are 7 predefined responses with a total of 28 bytes data to transmit. -// Coded responses need one byte per bit to transfer (data, parity, start, stop, correction) +// Coded responses need one byte per bit to transfer (data, parity, start, stop, correction) // 28 * 8 data bits, 28 * 1 parity bits, 7 start bits, 7 stop bits, 7 correction bits // -> need 273 bytes buffer // 44 * 8 data bits, 44 * 1 parity bits, 9 start bits, 9 stop bits, 9 correction bits --370 -// 47 * 8 data bits, 47 * 1 parity bits, 10 start bits, 10 stop bits, 10 correction bits -#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 453 +// 47 * 8 data bits, 47 * 1 parity bits, 10 start bits, 10 stop bits, 10 correction bits +#define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 453 bool prepare_allocated_tag_modulation(tag_response_info_t* response_info) { // Retrieve and store the current buffer index @@ -851,14 +851,14 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { #define ATTACK_KEY_COUNT 8 // keep same as define in cmdhfmf.c -> readerAttack() uint8_t sak = 0; - uint32_t cuid = 0; + uint32_t cuid = 0; uint32_t nonce = 0; - + // PACK response to PWD AUTH for EV1/NTAG uint8_t response8[4] = {0,0,0,0}; // Counter for EV1/NTAG uint32_t counters[] = {0,0,0}; - + // The first response contains the ATQA (note: bytes are transmitted in reverse order). uint8_t response1[] = {0,0}; @@ -871,9 +871,9 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { nonces_t ar_nr_nonces[ATTACK_KEY_COUNT]; // for attack types moebius memset(ar_nr_nonces, 0x00, sizeof(ar_nr_nonces)); uint8_t moebius_count = 0; - + switch (tagType) { - case 1: { // MIFARE Classic 1k + case 1: { // MIFARE Classic 1k response1[0] = 0x04; sak = 0x08; } break; @@ -908,14 +908,14 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { compute_crc(CRC_14443_A, response8, 2, &response8[2], &response8[3]); // uid not supplied then get from emulator memory if (data[0]==0) { - uint16_t start = 4 * (0+12); + uint16_t start = 4 * (0+12); uint8_t emdata[8]; emlGetMemBt( emdata, start, sizeof(emdata)); memcpy(data, emdata, 3); // uid bytes 0-2 memcpy(data+3, emdata+4, 4); // uid bytes 3-7 flags |= FLAG_7B_UID_IN_DATA; } - } break; + } break; case 8: { // MIFARE Classic 4k response1[0] = 0x02; sak = 0x18; @@ -930,13 +930,13 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { return; } break; } - + // The second response contains the (mandatory) first 24 bits of the UID uint8_t response2[5] = {0x00}; - // For UID size 7, + // For UID size 7, uint8_t response2a[5] = {0x00}; - + if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA ) { response2[0] = 0x88; // Cascade Tag marker response2[1] = data[0]; @@ -952,7 +952,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { // Configure the ATQA and SAK accordingly response1[0] |= 0x40; sak |= 0x04; - + cuid = bytes_to_num(data+3, 4); } else { memcpy(response2, data, 4); @@ -975,22 +975,22 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { compute_crc(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); // Tag NONCE. - uint8_t response5[4]; - - 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, + uint8_t response5[4]; + + 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 // TB(1) = not present. Defaults: FWI = 4 (FWT = 256 * 16 * 2^4 * 1/fc = 4833us), SFGI = 0 (SFG = 256 * 16 * 2^0 * 1/fc = 302us) // TC(1) = 0x02: CID supported, NAD not supported compute_crc(CRC_14443_A, response6, 4, &response6[4], &response6[5]); - + // Prepare GET_VERSION (different for UL EV-1 / NTAG) // uint8_t response7_EV1[] = {0x00, 0x04, 0x03, 0x01, 0x01, 0x00, 0x0b, 0x03, 0xfd, 0xf7}; //EV1 48bytes VERSION. - // uint8_t response7_NTAG[] = {0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x11, 0x03, 0x01, 0x9e}; //NTAG 215 + // uint8_t response7_NTAG[] = {0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x11, 0x03, 0x01, 0x9e}; //NTAG 215 // Prepare CHK_TEARING // uint8_t response9[] = {0xBD,0x90,0x3f}; - + #define TAG_RESPONSE_COUNT 10 tag_response_info_t responses[TAG_RESPONSE_COUNT] = { { .response = response1, .response_n = sizeof(response1) }, // Answer to request - respond with card type @@ -1002,10 +1002,10 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { { .response = response6, .response_n = sizeof(response6) }, // dummy ATS (pseudo-ATR), answer to RATS { .response = response8, .response_n = sizeof(response8) } // EV1/NTAG PACK response - }; + }; // { .response = response7_NTAG, .response_n = sizeof(response7_NTAG)}, // EV1/NTAG GET_VERSION response // { .response = response9, .response_n = sizeof(response9) } // EV1/NTAG CHK_TEAR response - + // Allocate 512 bytes for the dynamic modulation, created when the reader queries for it // Such a response is less time critical, so we can prepare them on the fly @@ -1019,7 +1019,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { .modulation = dynamic_modulation_buffer, .modulation_n = 0 }; - + // We need to listen to the high-frequency, peak-detected path. iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); @@ -1050,16 +1050,16 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { tag_response_info_t* p_response; LED_A_ON(); - for (;;) { + for (;;) { WDT_HIT(); - + // Clean receive command buffer if (!GetIso14443aCommandFromReader(receivedCmd, receivedCmdPar, &len)) { Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen()); break; - } + } p_response = NULL; - + // Okay, look at the command now. lastorder = order; if (receivedCmd[0] == ISO14443A_CMD_REQA) { // Received a REQUEST @@ -1073,13 +1073,13 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received a SELECT (cascade 1) p_response = &responses[3]; order = 3; } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received a SELECT (cascade 2) - p_response = &responses[4]; order = 30; + p_response = &responses[4]; order = 30; } else if (receivedCmd[0] == ISO14443A_CMD_READBLOCK) { // Received a (plain) READ uint8_t block = receivedCmd[1]; // if Ultralight or NTAG (4 byte blocks) if ( tagType == 7 || tagType == 2 ) { // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] - uint16_t start = 4 * (block+12); + uint16_t start = 4 * (block+12); uint8_t emdata[MAX_MIFARE_FRAME_SIZE]; emlGetMemBt( emdata, start, 16); AddCrc14A(emdata, 16); @@ -1101,24 +1101,24 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { // We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below p_response = NULL; } - } else if (receivedCmd[0] == MIFARE_ULEV1_FASTREAD) { // Received a FAST READ (ranged read) + } else if (receivedCmd[0] == MIFARE_ULEV1_FASTREAD) { // Received a FAST READ (ranged read) uint8_t emdata[MAX_FRAME_SIZE]; // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] - int start = (receivedCmd[1]+12) * 4; + int start = (receivedCmd[1]+12) * 4; int len = (receivedCmd[2] - receivedCmd[1] + 1) * 4; emlGetMemBt( emdata, start, len); AddCrc14A(emdata, len); - EmSendCmd(emdata, len+2); - p_response = NULL; - } else if (receivedCmd[0] == MIFARE_ULEV1_READSIG && tagType == 7) { // Received a READ SIGNATURE -- + EmSendCmd(emdata, len+2); + p_response = NULL; + } else if (receivedCmd[0] == MIFARE_ULEV1_READSIG && tagType == 7) { // Received a READ SIGNATURE -- // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] uint16_t start = 4 * 4; uint8_t emdata[34]; emlGetMemBt( emdata, start, 32); AddCrc14A(emdata, 32); EmSendCmd(emdata, sizeof(emdata)); - p_response = NULL; - } else if (receivedCmd[0] == MIFARE_ULEV1_READ_CNT && tagType == 7) { // Received a READ COUNTER -- + p_response = NULL; + } else if (receivedCmd[0] == MIFARE_ULEV1_READ_CNT && tagType == 7) { // Received a READ COUNTER -- uint8_t index = receivedCmd[1]; if (index > 2) { // send NACK 0x0 == invalid argument @@ -1128,10 +1128,10 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { uint8_t cmd[] = {0x00,0x00,0x00,0x14,0xa5}; num_to_bytes(counters[index], 3, cmd); AddCrc14A(cmd, sizeof(cmd)-2); - EmSendCmd(cmd,sizeof(cmd)); + EmSendCmd(cmd,sizeof(cmd)); } p_response = NULL; - } else if (receivedCmd[0] == MIFARE_ULEV1_INCR_CNT && tagType == 7) { // Received a INC COUNTER -- + } else if (receivedCmd[0] == MIFARE_ULEV1_INCR_CNT && tagType == 7) { // Received a INC COUNTER -- uint8_t index = receivedCmd[1]; if ( index > 2) { // send NACK 0x0 == invalid argument @@ -1140,21 +1140,21 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { } else { uint32_t val = bytes_to_num(receivedCmd+2,4); - + // if new value + old value is bigger 24bits, fail if ( val + counters[index] > 0xFFFFFF ) { // send NACK 0x4 == counter overflow uint8_t nack[] = {0x04}; EmSendCmd(nack,sizeof(nack)); - } else { - counters[index] = val; + } else { + counters[index] = val; // send ACK uint8_t ack[] = {0x0a}; EmSendCmd(ack,sizeof(ack)); } } - p_response = NULL; - } else if (receivedCmd[0] == MIFARE_ULEV1_CHECKTEAR && tagType == 7) { // Received a CHECK_TEARING_EVENT -- + p_response = NULL; + } else if (receivedCmd[0] == MIFARE_ULEV1_CHECKTEAR && tagType == 7) { // Received a CHECK_TEARING_EVENT -- // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] uint8_t emdata[3]; uint8_t index = receivedCmd[1]; @@ -1162,16 +1162,16 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { // send NACK 0x0 == invalid argument uint8_t nack[] = {0x00}; EmSendCmd(nack,sizeof(nack)); - } else { + } else { emlGetMemBt( emdata, 10+index, 1); AddCrc14A(emdata, sizeof(emdata)-2); - EmSendCmd(emdata, sizeof(emdata)); + EmSendCmd(emdata, sizeof(emdata)); } - p_response = NULL; + p_response = NULL; } else if (receivedCmd[0] == ISO14443A_CMD_HALT) { // Received a HALT LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); p_response = NULL; - } else if (receivedCmd[0] == MIFARE_AUTH_KEYA || receivedCmd[0] == MIFARE_AUTH_KEYB) { // Received an authentication request + } else if (receivedCmd[0] == MIFARE_AUTH_KEYA || receivedCmd[0] == MIFARE_AUTH_KEYB) { // Received an authentication request if ( tagType == 7 ) { // IF NTAG /EV1 0x60 == GET_VERSION, not a authentication request. uint8_t emdata[10]; emlGetMemBt( emdata, 0, 8 ); @@ -1179,20 +1179,20 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { EmSendCmd(emdata, sizeof(emdata)); p_response = NULL; } else { - + cardAUTHKEY = receivedCmd[0] - 0x60; cardAUTHSC = receivedCmd[1] / 4; // received block num - - // incease nonce at AUTH requests. this is time consuming. + + // incease nonce at AUTH requests. this is time consuming. nonce = prng_successor( GetTickCount(), 32 ); //num_to_bytes(nonce, 4, response5); - num_to_bytes(nonce, 4, dynamic_response_info.response); + num_to_bytes(nonce, 4, dynamic_response_info.response); dynamic_response_info.response_n = 4; //prepare_tag_modulation(&responses[5], DYNAMIC_MODULATION_BUFFER_SIZE); prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE); p_response = &dynamic_response_info; - //p_response = &responses[5]; + //p_response = &responses[5]; order = 7; } } else if (receivedCmd[0] == ISO14443A_CMD_RATS) { // Received a RATS request @@ -1206,15 +1206,15 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); uint32_t nr = bytes_to_num(receivedCmd,4); uint32_t ar = bytes_to_num(receivedCmd+4,4); - + // Collect AR/NR per keytype & sector if ( (flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK ) { - + int8_t index = -1; int8_t empty = -1; for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { // find which index to use - if ( (cardAUTHSC == ar_nr_nonces[i].sector) && (cardAUTHKEY == ar_nr_nonces[i].keytype)) + if ( (cardAUTHSC == ar_nr_nonces[i].sector) && (cardAUTHKEY == ar_nr_nonces[i].keytype)) index = i; // keep track of empty slots. @@ -1242,8 +1242,8 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { ar_nr_nonces[index].ar = ar; ar_nr_nonces[index].state = FIRST; break; - } - case FIRST : { + } + case FIRST : { // second nonce collect ar_nr_nonces[index].nonce2 = nonce; ar_nr_nonces[index].nr2 = nr; @@ -1252,11 +1252,11 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { // send to client cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, 0, 0, &ar_nr_nonces[index], sizeof(nonces_t)); - + ar_nr_nonces[index].state = EMPTY; ar_nr_nonces[index].sector = 0; ar_nr_nonces[index].keytype = 0; - + moebius_count++; break; } @@ -1264,7 +1264,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { } } p_response = NULL; - + } else if (receivedCmd[0] == MIFARE_ULC_AUTH_1 ) { // ULC authentication, or Desfire Authentication } else if (receivedCmd[0] == MIFARE_ULEV1_AUTH) { // NTAG / EV-1 authentication if ( tagType == 7 ) { @@ -1275,8 +1275,8 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { EmSendCmd(emdata, sizeof(emdata)); p_response = NULL; uint32_t pwd = bytes_to_num(receivedCmd+1,4); - - if ( MF_DBGLEVEL >= 3) Dbprintf("Auth attempt: %08x", pwd); + + if ( MF_DBGLEVEL >= 3) Dbprintf("Auth attempt: %08x", pwd); } } else { // Check for ISO 14443A-4 compliant commands, look at left nibble @@ -1308,7 +1308,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { dynamic_response_info.response[0] = receivedCmd[0] ^ 0x11; dynamic_response_info.response_n = 2; } break; - + case 0xBA: { // ping / pong dynamic_response_info.response[0] = 0xAB; dynamic_response_info.response[1] = 0x00; @@ -1331,7 +1331,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { dynamic_response_info.response_n = 0; } break; } - + if (dynamic_response_info.response_n > 0) { // Copy the CID from the reader query dynamic_response_info.response[1] = receivedCmd[1]; @@ -1339,7 +1339,7 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { // Add CRC bytes, always used in ISO 14443A-4 compliant cards AddCrc14A(dynamic_response_info.response, dynamic_response_info.response_n); dynamic_response_info.response_n += 2; - + if (prepare_tag_modulation(&dynamic_response_info,DYNAMIC_MODULATION_BUFFER_SIZE) == false) { DbpString("Error preparing tag response"); LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); @@ -1362,25 +1362,25 @@ void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { // do the tracing for the previous reader request and this tag answer: uint8_t par[MAX_PARITY_SIZE] = {0x00}; GetParity(p_response->response, p_response->response_n, par); - - EmLogTrace(Uart.output, - Uart.len, - Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, + + EmLogTrace(Uart.output, + Uart.len, + Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, + Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, - p_response->response, + p_response->response, p_response->response_n, LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, - (LastTimeProxToAirStart + p_response->ProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, + (LastTimeProxToAirStart + p_response->ProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, par); } } cmd_send(CMD_ACK,1,0,0,0,0); - switch_off(); - + switch_off(); + BigBuf_free_keep_EM(); - + if (MF_DBGLEVEL >= 4){ Dbprintf("-[ Wake ups after halt [%d]", happened); Dbprintf("-[ Messages after halt [%d]", happened2); @@ -1431,13 +1431,13 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing *timing = (GetCountSspClk() + 8) & 0xfffffff8; else PrepareDelayedTransfer(*timing & 0x00000007); // Delay transfer (fine tuning - up to 7 MF clock ticks) - + if(MF_DBGLEVEL >= 4 && GetCountSspClk() >= (*timing & 0xfffffff8)) Dbprintf("TransmitFor14443a: Missed timing"); while (GetCountSspClk() < (*timing & 0xfffffff8)) {}; // Delay transfer (multiple of 8 MF clock ticks) LastTimeProxToAirStart = *timing; } else { - + uint32_t ThisTransferTime = 0; ThisTransferTime = ((MAX(NextTransferTime, GetCountSspClk()) & 0xfffffff8) + 8); @@ -1445,12 +1445,12 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing LastTimeProxToAirStart = ThisTransferTime; } - + // clear TXRDY AT91C_BASE_SSC->SSC_THR = SEC_Y; volatile uint8_t b; - uint16_t c = 0; + uint16_t c = 0; while (c < len) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = cmd[c++]; @@ -1458,9 +1458,9 @@ static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing //iceman test if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); (void)b; - } + } } - + NextTransferTime = MAX(NextTransferTime, LastTimeProxToAirStart + REQUEST_GUARD_TIME); } @@ -1577,13 +1577,13 @@ int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) { AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ADC_CHAN_HF); // start ADC AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; - + // Now run a 'software UART' on the stream of incoming samples. UartInit(received, parity); // Clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - + for(;;) { WDT_HIT(); @@ -1623,7 +1623,7 @@ int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) { uint16_t i = 0; uint32_t ThisTransferTime; bool correctionNeeded; - + // Modulate Manchester FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD); @@ -1646,7 +1646,7 @@ int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) { b = AT91C_BASE_SSC->SSC_RHR; (void) b; while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)); b = AT91C_BASE_SSC->SSC_RHR; (void) b; - + // wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line) for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)); @@ -1664,15 +1664,15 @@ int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) { AT91C_BASE_SSC->SSC_THR = resp[i++]; FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR; } - + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); (void)b; - } + } if(BUTTON_PRESS()) break; } // Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again: - uint8_t fpga_queued_bits = FpgaSendQueueDelay >> 3; + uint8_t fpga_queued_bits = FpgaSendQueueDelay >> 3; for (i = 0; i <= fpga_queued_bits/8 + 1; ) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = SEC_F; @@ -1690,15 +1690,15 @@ int EmSend4bit(uint8_t resp){ // do the tracing for the previous reader request and this tag answer: uint8_t par[1] = {0x00}; GetParity(&resp, 1, par); - EmLogTrace(Uart.output, - Uart.len, - Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, + EmLogTrace(Uart.output, + Uart.len, + Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, + Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, - &resp, - 1, + &resp, + 1, LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, - (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, + (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, par); return res; } @@ -1709,15 +1709,15 @@ int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool collision CodeIso14443aAsTagPar(resp, respLen, par, collision); int res = EmSendCmd14443aRaw(ToSend, ToSendMax); // do the tracing for the previous reader request and this tag answer: - EmLogTrace(Uart.output, - Uart.len, - Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, + EmLogTrace(Uart.output, + Uart.len, + Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, + Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, - resp, - respLen, + resp, + respLen, LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, - (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, + (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, par); return res; } @@ -1741,10 +1741,10 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start uint16_t exact_fdt = (approx_fdt - 20 + 32)/64 * 64 + 20; reader_EndTime = tag_StartTime - exact_fdt; reader_StartTime = reader_EndTime - reader_modlen; - + if (!LogTrace(reader_data, reader_len, reader_StartTime, reader_EndTime, reader_Parity, true)) return false; - else + else return(!LogTrace(tag_data, tag_len, tag_StartTime, tag_EndTime, tag_Parity, false)); } @@ -1756,13 +1756,13 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start //----------------------------------------------------------------------------- static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset) { uint32_t c = 0; - + // Set FPGA mode to "reader listen mode", no modulation (listen // only, since we are receiving, not transmitting). // Signal field is on with the appropriate LED LED_D_ON(); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN); - + // Now get the answer from the card DemodInit(receivedResponse, receivedResponsePar); @@ -1779,7 +1779,7 @@ static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receive NextTransferTime = MAX(NextTransferTime, Demod.endTime - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/16 + FRAME_DELAY_TIME_PICC_TO_PCD); return true; } else if (c++ > timeout && Demod.state == DEMOD_UNSYNCD) { - return false; + return false; } } } @@ -1791,7 +1791,7 @@ void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t // Send command to tag TransmitFor14443a(ToSend, ToSendMax, timing); if(trigger) LED_A_ON(); - + LogTrace(frame, nbytes(bits), (LastTimeProxToAirStart<<4) + DELAY_ARM2AIR_AS_READER, ((LastTimeProxToAirStart + LastProxToAirDuration)<<4) + DELAY_ARM2AIR_AS_READER, par, true); } @@ -1802,7 +1802,7 @@ void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *tim void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing) { // Generate parity and redirect uint8_t par[MAX_PARITY_SIZE] = {0x00}; - GetParity(frame, len/8, par); + GetParity(frame, len/8, par); ReaderTransmitBitsPar(frame, len, par, timing); } @@ -1828,30 +1828,30 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity) { } // This function misstreats the ISO 14443a anticollision procedure. -// by fooling the reader there is a collision and forceing the reader to +// by fooling the reader there is a collision and forceing the reader to // increase the uid bytes. The might be an overflow, DoS will occure. void iso14443a_antifuzz(uint32_t flags){ - + // We need to listen to the high-frequency, peak-detected path. iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); BigBuf_free_keep_EM(); clear_trace(); set_tracing(true); - + int len = 0; - + // allocate buffers: uint8_t *received = BigBuf_malloc(MAX_FRAME_SIZE); uint8_t *receivedPar = BigBuf_malloc(MAX_PARITY_SIZE); uint8_t *resp = BigBuf_malloc(20); memset(resp, 0xFF , 20); - + LED_A_ON(); - for (;;) { + for (;;) { WDT_HIT(); - + // Clean receive command buffer if (!GetIso14443aCommandFromReader(received, receivedPar, &len)) { Dbprintf("Anti-fuzz stopped. Trace length: %d ", BigBuf_get_traceLen()); @@ -1860,15 +1860,15 @@ void iso14443a_antifuzz(uint32_t flags){ if ( received[0] == ISO14443A_CMD_WUPA || received[0] == ISO14443A_CMD_REQA) { resp[0] = 0x04; resp[1] = 0x00; - + if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA ) { resp[0] = 0x44; } - + EmSendCmd(resp, 2); continue; } - + // Received request for UID (cascade 1) //if (received[1] >= 0x20 && received[1] <= 0x57 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { if (received[1] >= 0x20 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { @@ -1878,23 +1878,23 @@ void iso14443a_antifuzz(uint32_t flags){ resp[3] = 0xFF; resp[4] = resp[0] ^ resp[1] ^ resp[2] ^ resp[3]; colpos = 0; - + if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA ) { - resp[0] = 0x88; + resp[0] = 0x88; colpos = 8; } - + EmSendCmdEx(resp, 5, true); if (MF_DBGLEVEL >= 4) Dbprintf("ANTICOLL or SELECT %x", received[1]); LED_D_INV(); - + continue; } else if (received[1] == 0x20 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received request for UID (cascade 2) if (MF_DBGLEVEL >= 4) Dbprintf("ANTICOLL or SELECT_2"); - } else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received a SELECT (cascade 1) - } else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received a SELECT (cascade 2) + } else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received a SELECT (cascade 1) + } else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received a SELECT (cascade 2) } else { - Dbprintf("unknown command %x", received[0]); + Dbprintf("unknown command %x", received[0]); } } @@ -1906,9 +1906,9 @@ void iso14443a_antifuzz(uint32_t flags){ static void iso14a_set_ATS_times(uint8_t *ats) { uint8_t tb1; - uint8_t fwi, sfgi; + uint8_t fwi, sfgi; uint32_t fwt, sfgt; - + if (ats[0] > 1) { // there is a format byte T0 if ((ats[1] & 0x20) == 0x20) { // there is an interface byte TB(1) if ((ats[1] & 0x10) == 0x10) { // there is an interface byte TA(1) preceding TB(1) @@ -1937,10 +1937,10 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par) { uint32_t save_iso14a_timeout = iso14a_get_timeout(); iso14a_set_timeout(1236/(16*8)+1); // response to WUPA is expected at exactly 1236/fc. No need to wait longer. - + uint32_t start_time = GetTickCount(); int len; - + // we may need several tries if we did send an unknown command or a wrong authentication before... do { // Broadcast for a card, WUPA (0x52) will force response from all cards in the field @@ -1948,7 +1948,7 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par) { // Receive the ATQA len = ReaderReceive(resp, resp_par); } while (len == 0 && GetTickCount() <= start_time + WUPA_RETRY_TIMEOUT); - + iso14a_set_timeout(save_iso14a_timeout); return len; } @@ -1956,11 +1956,11 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par) { // performs iso14443a anticollision (optional) and card select procedure // fills the uid and cuid pointer unless NULL // fills the card info record unless NULL -// if anticollision is false, then the UID must be provided in uid_ptr[] +// if anticollision is false, then the UID must be provided in uid_ptr[] // and num_cascades must be set (1: 4 Byte UID, 2: 7 Byte UID, 3: 10 Byte UID) // requests ATS unless no_rats is true int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) { - + uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT,0x20 }; uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t rats[] = { ISO14443A_CMD_RATS,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0 @@ -1978,14 +1978,14 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_card, uint32_ memset(p_card->uid, 0, 10); p_card->ats_len = 0; } - + if (!GetATQA(resp, resp_par)) { return 0; } if (p_card) { p_card->atqa[0] = resp[0]; - p_card->atqa[1] = resp[1]; + p_card->atqa[1] = resp[1]; } if (anticollision) { @@ -1993,10 +1993,10 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_card, uint32_ if (uid_ptr) memset(uid_ptr, 0, 10); } - + // check for proprietary anticollision: if ((resp[0] & 0x1F) == 0) return 3; - + // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in // which case we need to make a cascade 2 request and select - this is a long UID // While the UID is not complete, the 3nd bit (from the right) is set in the SAK. @@ -2040,7 +2040,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_card, uint32_ } else { // no collision, use the response to SELECT_ALL as current uid memcpy(uid_resp, resp, 4); } - + } else { if (cascade_level < num_cascades - 1) { uid_resp[0] = 0x88; @@ -2064,7 +2064,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_card, uint32_ // Receive the SAK if (!ReaderReceive(resp, resp_par)) return 0; - + sak = resp[0]; // Test if more parts of the uid are coming @@ -2073,7 +2073,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_card, uint32_ // http://www.nxp.com/documents/application_note/AN10927.pdf uid_resp[0] = uid_resp[1]; uid_resp[1] = uid_resp[2]; - uid_resp[2] = uid_resp[3]; + uid_resp[2] = uid_resp[3]; uid_resp_len = 3; } @@ -2091,7 +2091,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_card, uint32_ } // PICC compilant with iso14443a-4 ---> (SAK & 0x20 != 0) - if( (sak & 0x20) == 0) return 2; + if( (sak & 0x20) == 0) return 2; // RATS, Request for answer to select if ( !no_rats ) { @@ -2099,7 +2099,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_card, uint32_ AddCrc14A(rats, 2); ReaderTransmit(rats, sizeof(rats), NULL); len = ReaderReceive(resp, resp_par); - + if (!len) return 0; if (p_card) { @@ -2113,7 +2113,7 @@ int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_card, uint32_ // set default timeout and delay next transfer based on ATS iso14a_set_ATS_times(resp); } - return 1; + return 1; } int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades) { @@ -2129,14 +2129,14 @@ int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades) { if (!GetATQA(resp, resp_par)) { return 0; } - + // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in // which case we need to make a cascade 2 request and select - this is a long UID // While the UID is not complete, the 3nd bit (from the right) is set in the SAK. for(; sak & 0x04; cascade_level++) { // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97) sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2; - + if (cascade_level < num_cascades - 1) { uid_resp[0] = 0x88; memcpy(uid_resp+1, uid_ptr+cascade_level*3, 3); @@ -2153,7 +2153,7 @@ int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades) { // Receive the SAK if (!ReaderReceive(resp, resp_par)) return 0; - + sak = resp[0]; // Test if more parts of the uid are coming @@ -2162,10 +2162,10 @@ int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades) { // http://www.nxp.com/documents/application_note/AN10927.pdf uid_resp[0] = uid_resp[1]; uid_resp[1] = uid_resp[2]; - uid_resp[2] = uid_resp[3]; + uid_resp[2] = uid_resp[3]; } } - return 1; + return 1; } void iso14443a_setup(uint8_t fpga_minor_mode) { @@ -2184,15 +2184,15 @@ void iso14443a_setup(uint8_t fpga_minor_mode) { FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode); SpinDelay(100); - + // Start the timer StartCountSspClk(); - + // Prepare the demodulation functions DemodReset(); UartReset(); NextTransferTime = 2 * DELAY_ARM2AIR_AS_READER; - iso14a_set_timeout(1060); // 106 * 10ms default + iso14a_set_timeout(1060); // 106 * 10ms default } /* Peter Fillmore 2015 @@ -2215,17 +2215,17 @@ b8 b7 b6 b5 b4 b3 b2 b1 b5 = ACK/NACK Coding of S-block: b8 b7 b6 b5 b4 b3 b2 b1 -1 1 x x x 0 1 0 +1 1 x x x 0 1 0 b5,b6 = 00 - DESELECT - 11 - WTX -*/ + 11 - WTX +*/ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res) { uint8_t parity[MAX_PARITY_SIZE] = {0x00}; uint8_t real_cmd[cmd_len + 4]; - + if (cmd_len) { // ISO 14443 APDU frame: PCB [CID] [NAD] APDU CRC PCB=0x02 - real_cmd[0] = 0x02; // bnr,nad,cid,chn=0; i-block(0x00) + real_cmd[0] = 0x02; // bnr,nad,cid,chn=0; i-block(0x00) if (send_chaining) { real_cmd[0] |= 0x10; } @@ -2234,11 +2234,11 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, u memcpy(real_cmd + 1, cmd, cmd_len); } else { // R-block. ACK - real_cmd[0] = 0xA2; // r-block + ACK + real_cmd[0] = 0xA2; // r-block + ACK real_cmd[0] |= iso14_pcb_blocknum; } AddCrc14A(real_cmd, cmd_len + 1); - + ReaderTransmit(real_cmd, cmd_len + 3, NULL); size_t len = ReaderReceive(data, parity); @@ -2247,19 +2247,19 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, u if (!len) { return 0; //DATA LINK ERROR } else{ - // S-Block WTX + // S-Block WTX while(len && ((data_bytes[0] & 0xF2) == 0xF2)) { uint32_t save_iso14a_timeout = iso14a_get_timeout(); // temporarily increase timeout iso14a_set_timeout( MAX((data_bytes[1] & 0x3f) * save_iso14a_timeout, MAX_ISO14A_TIMEOUT) ); - // Transmit WTX back + // Transmit WTX back // byte1 - WTXM [1..59]. command FWT=FWT*WTXM data_bytes[1] = data_bytes[1] & 0x3f; // 2 high bits mandatory set to 0b // now need to fix CRC. AddCrc14A(data_bytes, len - 2); // transmit S-Block ReaderTransmit(data_bytes, len, NULL); - // retrieve the result again (with increased timeout) + // retrieve the result again (with increased timeout) len = ReaderReceive(data, parity); data_bytes = data; // restore timeout @@ -2275,7 +2275,7 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, u { iso14_pcb_blocknum ^= 1; } - + // if we received I-block with chaining we need to send ACK and receive another block of data if (res) *res = data_bytes[0]; @@ -2284,9 +2284,9 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, u if (len >= 3 && !check_crc(CRC_14443_A, data_bytes, len)) { return -1; } - + } - + if (len) { // cut frame byte len -= 1; @@ -2294,7 +2294,7 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, u for (int i = 0; i < len; i++) data_bytes[i] = data_bytes[i + 1]; } - + return len; } @@ -2304,8 +2304,8 @@ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, u // arg0 iso_14a flags // arg1 high :: number of bits, if you want to send 7bits etc // low :: len of commandbytes -// arg2 timeout -// d.asBytes command bytes to send +// arg2 timeout +// d.asBytes command bytes to send void ReaderIso14443a(UsbCommand *c) { iso14a_command_t param = c->arg[0]; size_t len = c->arg[1] & 0xffff; @@ -2315,7 +2315,7 @@ void ReaderIso14443a(UsbCommand *c) { uint32_t arg0 = 0; uint8_t buf[USB_CMD_DATA_SIZE] = {0x00}; uint8_t par[MAX_PARITY_SIZE] = {0x00}; - + if ((param & ISO14A_CONNECT)) clear_trace(); @@ -2348,7 +2348,7 @@ void ReaderIso14443a(UsbCommand *c) { } if ((param & ISO14A_RAW)) { - + if ((param & ISO14A_APPEND_CRC)) { // Don't append crc on empty bytearray... if ( len > 0 ) { @@ -2361,7 +2361,7 @@ void ReaderIso14443a(UsbCommand *c) { if (lenbits) lenbits += 16; } } - + if (lenbits > 0) { // want to send a specific number of bits (e.g. short commands) if ((param & ISO14A_TOPAZMODE)) { int bits_to_send = lenbits; @@ -2397,7 +2397,7 @@ void ReaderIso14443a(UsbCommand *c) { if ((param & ISO14A_NO_DISCONNECT)) return; -OUT: +OUT: FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); set_tracing(false); LEDsoff(); @@ -2409,22 +2409,22 @@ OUT: int32_t dist_nt(uint32_t nt1, uint32_t nt2) { if (nt1 == nt2) return 0; - + uint32_t nttmp1 = nt1; uint32_t nttmp2 = nt2; for (uint16_t i = 1; i < 32768; i++) { nttmp1 = prng_successor(nttmp1, 1); if (nttmp1 == nt2) return i; - + nttmp2 = prng_successor(nttmp2, 1); if (nttmp2 == nt1) return -i; } - + return(-99999); // either nt1 or nt2 are invalid nonces } - + #define PRNG_SEQUENCE_LENGTH (1 << 16) #define MAX_UNEXPECTED_RANDOM 4 // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up. #define MAX_SYNC_TRIES 32 @@ -2436,13 +2436,13 @@ int32_t dist_nt(uint32_t nt1, uint32_t nt2) { // (article by Nicolas T. Courtois, 2009) //----------------------------------------------------------------------------- void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { - + iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); - BigBuf_free(); BigBuf_Clear_ext(false); + BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); set_tracing(true); - + uint8_t mf_auth[] = { keytype, block, 0x00, 0x00 }; uint8_t mf_nr_ar[] = {0,0,0,0,0,0,0,0}; uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; @@ -2455,47 +2455,47 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { uint32_t nt = 0, previous_nt = 0, cuid = 0; uint32_t sync_time = GetCountSspClk() & 0xfffffff8; - + int32_t catch_up_cycles = 0; int32_t last_catch_up = 0; int32_t isOK = 0; - + uint16_t elapsed_prng_sequences = 1; uint16_t consecutive_resyncs = 0; uint16_t unexpected_random = 0; uint16_t sync_tries = 0; - bool have_uid = false; + bool have_uid = false; bool received_nack; uint8_t cascade_levels = 0; - + // static variables here, is re-used in the next call - static uint32_t nt_attacked = 0; + static uint32_t nt_attacked = 0; static int32_t sync_cycles = 0; static uint8_t par_low = 0; static uint8_t mf_nr_ar3 = 0; - + AddCrc14A(mf_auth, 2); - + if (first_try) { sync_cycles = PRNG_SEQUENCE_LENGTH; // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). nt_attacked = 0; mf_nr_ar3 = 0; par_low = 0; } else { - // we were unsuccessful on a previous call. + // we were unsuccessful on a previous call. // Try another READER nonce (first 3 parity bits remain the same) mf_nr_ar3++; mf_nr_ar[3] = mf_nr_ar3; par[0] = par_low; } - LED_C_ON(); + LED_C_ON(); uint16_t i; for (i = 0; true; ++i) { received_nack = false; - + WDT_HIT(); // Test if the action was cancelled @@ -2503,10 +2503,10 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { isOK = -1; break; } - + // this part is from Piwi's faster nonce collecting part in Hardnested. if (!have_uid) { // need a full select cycle to get the uid first - iso14a_card_select_t card_info; + iso14a_card_select_t card_info; if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card (ALL)"); continue; @@ -2517,7 +2517,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { case 10: cascade_levels = 3; break; default: break; } - have_uid = true; + have_uid = true; } else { // no need for anticollision. We can directly select the card if (!iso14443a_fast_select_card(uid, cascade_levels)) { if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card (UID)"); @@ -2526,29 +2526,29 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { } elapsed_prng_sequences = 1; - - // Sending timeslot of ISO14443a frame + + // Sending timeslot of ISO14443a frame sync_time = (sync_time & 0xfffffff8 ) + sync_cycles + catch_up_cycles; catch_up_cycles = 0; #define SYNC_TIME_BUFFER 16 // if there is only SYNC_TIME_BUFFER left before next planned sync, wait for next PRNG cycle - + // if we missed the sync time already or are about to miss it, advance to the next nonce repeat while ( sync_time < GetCountSspClk() + SYNC_TIME_BUFFER) { ++elapsed_prng_sequences; 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); - // Receive the (4 Byte) "random" TAG nonce + // Receive the (4 Byte) "random" TAG nonce if (!ReaderReceive(receivedAnswer, receivedAnswerPar)) continue; previous_nt = nt; nt = bytes_to_num(receivedAnswer, 4); - + // Transmit reader nonce with fake par ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); @@ -2558,10 +2558,10 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { // we didn't calibrate our clock yet, // iceman: has to be calibrated every time. - if (previous_nt && !nt_attacked) { + if (previous_nt && !nt_attacked) { int nt_distance = dist_nt(previous_nt, nt); - + // if no distance between, then we are in sync. if (nt_distance == 0) { nt_attacked = nt; @@ -2569,20 +2569,20 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { if (nt_distance == -99999) { // invalid nonce received unexpected_random++; if (unexpected_random > MAX_UNEXPECTED_RANDOM) { - isOK = -3; // Card has an unpredictable PRNG. Give up + isOK = -3; // Card has an unpredictable PRNG. Give up break; - } else { + } else { continue; // continue trying... } } - + if (++sync_tries > MAX_SYNC_TRIES) { isOK = -4; // Card's PRNG runs at an unexpected frequency or resets unexpectedly break; } - + sync_cycles = (sync_cycles - nt_distance)/elapsed_prng_sequences; - + // no negative sync_cycles if (sync_cycles <= 0) sync_cycles += PRNG_SEQUENCE_LENGTH; @@ -2591,7 +2591,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { sync_cycles = PRNG_SEQUENCE_LENGTH; sync_time = GetCountSspClk() & 0xfffffff8; } - + if (MF_DBGLEVEL >= 4) Dbprintf("calibrating in cycle %d. nt_distance=%d, elapsed_prng_sequences=%d, new sync_cycles: %d\n", i, nt_distance, elapsed_prng_sequences, sync_cycles); @@ -2602,30 +2602,30 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { LED_B_OFF(); if ( (nt != nt_attacked) && nt_attacked) { // we somehow lost sync. Try to catch up again... - + catch_up_cycles = -dist_nt(nt_attacked, nt); if (catch_up_cycles == 99999) { // invalid nonce received. Don't resync on that one. catch_up_cycles = 0; continue; - } - // average? + } + // average? catch_up_cycles /= elapsed_prng_sequences; - + if (catch_up_cycles == last_catch_up) { consecutive_resyncs++; } else { last_catch_up = catch_up_cycles; consecutive_resyncs = 0; - } - + } + if (consecutive_resyncs < 3) { if (MF_DBGLEVEL >= 4) { Dbprintf("Lost sync in cycle %d. nt_distance=%d. Consecutive Resyncs = %d. Trying one time catch up...\n", i, catch_up_cycles, consecutive_resyncs); } - } else { + } else { sync_cycles += catch_up_cycles; - - if (MF_DBGLEVEL >= 4) + + if (MF_DBGLEVEL >= 4) Dbprintf("Lost sync in cycle %d for the fourth time consecutively (nt_distance = %d). Adjusting sync_cycles to %d.\n", i, catch_up_cycles, sync_cycles); last_catch_up = 0; @@ -2634,11 +2634,11 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { } continue; } - + // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding if (received_nack) { catch_up_cycles = 8; // the PRNG is delayed by 8 cycles due to the NAC (4Bits = 0x05 encrypted) transfer - + if (nt_diff == 0) par_low = par[0] & 0xE0; // there is no need to check all parities for other nt_diff. Parity Bits for mf_nr_ar[0..2] won't change @@ -2654,9 +2654,9 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { nt_diff = (nt_diff + 1) & 0x07; mf_nr_ar[3] = (mf_nr_ar[3] & 0x1F) | (nt_diff << 5); par[0] = par_low; - + } else { - // No NACK. + // No NACK. if (nt_diff == 0 && first_try) { par[0]++; if (par[0] == 0) { // tried all 256 possible parities without success. Card doesn't send NACK. @@ -2668,7 +2668,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { par[0] = ((par[0] & 0x1F) + 1) | par_low; } } - + // reset the resyncs since we got a complete transaction on right time. consecutive_resyncs = 0; } // end for loop @@ -2676,7 +2676,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { mf_nr_ar[3] &= 0x1F; if (MF_DBGLEVEL >= 4) Dbprintf("Number of sent auth requestes: %u", i); - + uint8_t buf[32] = {0x00}; memset(buf, 0x00, sizeof(buf)); num_to_bytes(cuid, 4, buf); @@ -2684,7 +2684,7 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { memcpy(buf + 8, par_list, 8); memcpy(buf + 16, ks_list, 8); memcpy(buf + 24, mf_nr_ar, 8); - + cmd_send(CMD_ACK, isOK, 0, 0, buf, sizeof(buf) ); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); @@ -2714,29 +2714,29 @@ void DetectNACKbug() { uint32_t sync_time = 0; bool have_uid = false; bool received_nack; - - // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). + + // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). uint32_t sync_cycles = PRNG_SEQUENCE_LENGTH; - BigBuf_free(); BigBuf_Clear_ext(false); + BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); - set_tracing(true); + set_tracing(true); iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); - sync_time = GetCountSspClk() & 0xfffffff8; - - LED_C_ON(); + sync_time = GetCountSspClk() & 0xfffffff8; + + LED_C_ON(); uint16_t i; for (i = 1; true; ++i) { received_nack = false; - + // Cards always leaks a NACK, no matter the parity if ((i==10) && (num_nacks == i-1)) { isOK = 2; break; } - + WDT_HIT(); // Test if the action was cancelled @@ -2744,10 +2744,10 @@ void DetectNACKbug() { isOK = 99; break; } - + // this part is from Piwi's faster nonce collecting part in Hardnested. if (!have_uid) { // need a full select cycle to get the uid first - iso14a_card_select_t card_info; + iso14a_card_select_t card_info; if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card (ALL)"); continue; @@ -2758,7 +2758,7 @@ void DetectNACKbug() { case 10: cascade_levels = 3; break; default: break; } - have_uid = true; + have_uid = true; } else { // no need for anticollision. We can directly select the card if (!iso14443a_fast_select_card(uid, cascade_levels)) { if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card (UID)"); @@ -2767,16 +2767,16 @@ void DetectNACKbug() { } elapsed_prng_sequences = 1; - - // Sending timeslot of ISO14443a frame + + // Sending timeslot of ISO14443a frame 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) { ++elapsed_prng_sequences; 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); @@ -2784,13 +2784,13 @@ void DetectNACKbug() { // Receive the (4 Byte) "random" TAG nonce if (!ReaderReceive(receivedAnswer, receivedAnswerPar)) continue; - + previous_nt = nt; nt = bytes_to_num(receivedAnswer, 4); - + // Transmit reader nonce with fake par ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); - + if (ReaderReceive(receivedAnswer, receivedAnswerPar)) { received_nack = true; num_nacks++; @@ -2798,14 +2798,14 @@ void DetectNACKbug() { if ( i == num_nacks ) { continue; } - } + } // we didn't calibrate our clock yet, // iceman: has to be calibrated every time. - if (previous_nt && !nt_attacked) { + if (previous_nt && !nt_attacked) { int nt_distance = dist_nt(previous_nt, nt); - + // if no distance between, then we are in sync. if (nt_distance == 0) { nt_attacked = nt; @@ -2813,32 +2813,32 @@ void DetectNACKbug() { if (nt_distance == -99999) { // invalid nonce received unexpected_random++; if (unexpected_random > MAX_UNEXPECTED_RANDOM ) { - // Card has an unpredictable PRNG. Give up + // Card has an unpredictable PRNG. Give up isOK = 98; break; - } else { + } else { if (sync_cycles <= 0) { sync_cycles += PRNG_SEQUENCE_LENGTH; } continue; } } - + if (++sync_tries > MAX_SYNC_TRIES) { isOK = 97; // Card's PRNG runs at an unexpected frequency or resets unexpectedly break; } - + sync_cycles = (sync_cycles - nt_distance)/elapsed_prng_sequences; - + if (sync_cycles <= 0) sync_cycles += PRNG_SEQUENCE_LENGTH; - + if (sync_cycles > PRNG_SEQUENCE_LENGTH * 2 ) { isOK = 96; // Card's PRNG runs at an unexpected frequency or resets unexpectedly break; } - + if (MF_DBGLEVEL >= 4) Dbprintf("calibrating in cycle %d. nt_distance=%d, elapsed_prng_sequences=%d, new sync_cycles: %d\n", i, nt_distance, elapsed_prng_sequences, sync_cycles); @@ -2846,32 +2846,32 @@ void DetectNACKbug() { } } - if ( (nt != nt_attacked) && nt_attacked) { - // we somehow lost sync. Try to catch up again... + if ( (nt != nt_attacked) && nt_attacked) { + // we somehow lost sync. Try to catch up again... catch_up_cycles = -dist_nt(nt_attacked, nt); - + if (catch_up_cycles == 99999) { // invalid nonce received. Don't resync on that one. catch_up_cycles = 0; continue; - } - // average? + } + // average? catch_up_cycles /= elapsed_prng_sequences; - + if (catch_up_cycles == last_catch_up) { consecutive_resyncs++; } else { last_catch_up = catch_up_cycles; consecutive_resyncs = 0; - } - + } + if (consecutive_resyncs < 3) { if (MF_DBGLEVEL >= 4) { Dbprintf("Lost sync in cycle %d. nt_distance=%d. Consecutive Resyncs = %d. Trying one time catch up...\n", i, catch_up_cycles, consecutive_resyncs); } - } else { + } else { sync_cycles += catch_up_cycles; - + if (MF_DBGLEVEL >= 4) { Dbprintf("Lost sync in cycle %d for the fourth time consecutively (nt_distance = %d). Adjusting sync_cycles to %d.\n", i, catch_up_cycles, sync_cycles); Dbprintf("nt [%08x] attacted [%08x]", nt, nt_attacked ); @@ -2882,14 +2882,14 @@ void DetectNACKbug() { } continue; } - + // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding if (received_nack) - catch_up_cycles = 8; // the PRNG is delayed by 8 cycles due to the NAC (4Bits = 0x05 encrypted) transfer + catch_up_cycles = 8; // the PRNG is delayed by 8 cycles due to the NAC (4Bits = 0x05 encrypted) transfer - // we are testing all 256 possibilities. + // we are testing all 256 possibilities. par[0]++; - + // tried all 256 possible parities without success. if (par[0] == 0) { if ( num_nacks == 1 ) @@ -2924,7 +2924,7 @@ void DetectNACKbug() { * (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attmpted) */ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain) { - + int cardSTATE = MFEMUL_NOFIELD; int _UID_LEN = 0; // 4, 7, 10 int vHf = 0; // in mV @@ -2947,25 +2947,25 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * uint8_t receivedCmd_par[MAX_MIFARE_PARITY_SIZE] = {0x00}; uint8_t response[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t response_par[MAX_MIFARE_PARITY_SIZE] = {0x00}; - + uint8_t atqa[] = {0x04, 0x00}; // Mifare classic 1k uint8_t sak_4[] = {0x0C, 0x00, 0x00}; // CL1 - 4b uid uint8_t sak_7[] = {0x0C, 0x00, 0x00}; // CL2 - 7b uid uint8_t sak_10[] = {0x0C, 0x00, 0x00}; // CL3 - 10b uid - // uint8_t sak[] = {0x09, 0x3f, 0xcc }; // Mifare Mini - - uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; - uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; + // uint8_t sak[] = {0x09, 0x3f, 0xcc }; // Mifare Mini + + uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; + uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; uint8_t rUIDBCC3[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; // TAG Nonce - Authenticate response uint8_t rAUTH_NT[4]; uint32_t nonce = prng_successor( GetTickCount(), 32 ); num_to_bytes(nonce, 4, rAUTH_NT); - + // uint8_t rAUTH_NT[] = {0x55, 0x41, 0x49, 0x92};// nonce from nested? why this? uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00}; - + // Here, we collect CUID, NT, NR, AR, CUID2, NT2, NR2, AR2 // This can be used in a reader-only attack. nonces_t ar_nr_nonces[ATTACK_KEY_COUNT]; @@ -2976,7 +2976,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // Length: 4,7,or 10 bytes if ( (flags & FLAG_UID_IN_EMUL) == FLAG_UID_IN_EMUL) emlGetMemBt(datain, 0, 10); // load 10bytes from EMUL to the datain pointer. to be used below. - + if ( (flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) { memcpy(rUIDBCC1, datain, 4); _UID_LEN = 4; @@ -2993,13 +2993,13 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * switch (_UID_LEN) { case 4: - sak_4[0] &= 0xFB; + sak_4[0] &= 0xFB; // save CUID cuid = bytes_to_num(rUIDBCC1, 4); // BCC rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; if (MF_DBGLEVEL >= 2) { - Dbprintf("4B UID: %02x%02x%02x%02x", + Dbprintf("4B UID: %02x%02x%02x%02x", rUIDBCC1[0], rUIDBCC1[1], rUIDBCC1[2], @@ -3009,14 +3009,14 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * break; case 7: atqa[0] |= 0x40; - sak_7[0] &= 0xFB; + sak_7[0] &= 0xFB; // save CUID - cuid = bytes_to_num(rUIDBCC2, 4); + cuid = bytes_to_num(rUIDBCC2, 4); // CascadeTag, CT rUIDBCC1[0] = 0x88; // BCC - rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; - rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; + rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; + rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; if (MF_DBGLEVEL >= 2) { Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x", rUIDBCC1[1], @@ -3031,7 +3031,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * break; case 10: atqa[0] |= 0x80; - sak_10[0] &= 0xFB; + sak_10[0] &= 0xFB; // save CUID cuid = bytes_to_num(rUIDBCC3, 4); // CascadeTag, CT @@ -3057,14 +3057,14 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * ); } break; - default: + default: break; } // calc some crcs compute_crc(CRC_14443_A, sak_4, 1, &sak_4[1], &sak_4[2]); compute_crc(CRC_14443_A, sak_7, 1, &sak_7[1], &sak_7[2]); compute_crc(CRC_14443_A, sak_10, 1, &sak_10[1], &sak_10[2]); - + // We need to listen to the high-frequency, peak-detected path. iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); @@ -3080,13 +3080,13 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // find reader field if (cardSTATE == MFEMUL_NOFIELD) { - + vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; if (vHf > MF_MINFIELDV) { cardSTATE_TO_IDLE(); LED_A_ON(); } - } + } if (cardSTATE == MFEMUL_NOFIELD) continue; // Now, get data @@ -3098,7 +3098,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } else if (res == 1) { break; // return value 1 means button press } - + // REQ or WUP request in ANY state and WUP in HALTED state // this if-statement doesn't match the specification above. (iceman) if (len == 1 && ((receivedCmd[0] == ISO14443A_CMD_REQA && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == ISO14443A_CMD_WUPA)) { @@ -3107,10 +3107,10 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * cardSTATE = MFEMUL_SELECT1; crypto1_destroy(pcs); cardAUTHKEY = 0xff; - nonce = prng_successor(selTimer, 32); + nonce = prng_successor(selTimer, 32); continue; } - + switch (cardSTATE) { case MFEMUL_NOFIELD: case MFEMUL_HALTED: @@ -3125,12 +3125,12 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * break; } // select card - if (len == 9 && + if (len == 9 && ( receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && - receivedCmd[1] == 0x70 && + receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) { - - // SAK 4b + + // SAK 4b EmSendCmd(sak_4, sizeof(sak_4)); switch(_UID_LEN){ case 4: @@ -3150,7 +3150,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * break; } case MFEMUL_SELECT2:{ - if (!len) { + if (!len) { LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); break; } @@ -3158,11 +3158,11 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * EmSendCmd(rUIDBCC2, sizeof(rUIDBCC2)); break; } - if (len == 9 && + if (len == 9 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && - receivedCmd[1] == 0x70 && + receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC2, 4) == 0) ) { - + EmSendCmd(sak_7, sizeof(sak_7)); switch(_UID_LEN){ case 7: @@ -3175,12 +3175,12 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * continue; default:break; } - } + } cardSTATE_TO_IDLE(); break; } case MFEMUL_SELECT3:{ - if (!len) { + if (!len) { LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); break; } @@ -3188,9 +3188,9 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * EmSendCmd(rUIDBCC3, sizeof(rUIDBCC3)); break; } - if (len == 9 && + if (len == 9 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && - receivedCmd[1] == 0x70 && + receivedCmd[1] == 0x70 && memcmp(&receivedCmd[2], rUIDBCC3, 4) == 0) ) { EmSendCmd(sak_10, sizeof(sak_10)); @@ -3214,12 +3214,12 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // Collect AR/NR per keytype & sector if ( (flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK ) { - + int8_t index = -1; int8_t empty = -1; for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { // find which index to use - if ( (cardAUTHSC == ar_nr_nonces[i].sector) && (cardAUTHKEY == ar_nr_nonces[i].keytype)) + if ( (cardAUTHSC == ar_nr_nonces[i].sector) && (cardAUTHKEY == ar_nr_nonces[i].keytype)) index = i; // keep track of empty slots. @@ -3247,8 +3247,8 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * ar_nr_nonces[index].ar = ar; ar_nr_nonces[index].state = FIRST; break; - } - case FIRST : { + } + case FIRST : { // second nonce collect ar_nr_nonces[index].nonce2 = nonce; ar_nr_nonces[index].nr2 = nr; @@ -3257,7 +3257,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * // send to client cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, 0, 0, &ar_nr_nonces[index], sizeof(nonces_t)); - + ar_nr_nonces[index].state = EMPTY; ar_nr_nonces[index].sector = 0; ar_nr_nonces[index].keytype = 0; @@ -3269,10 +3269,10 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * crypto1_word(pcs, nr , 1); uint32_t cardRr = ar ^ crypto1_word(pcs, 0, 0); - + //test if auth OK if (cardRr != prng_successor(nonce, 64)){ - + if (MF_DBGLEVEL >= 3) { Dbprintf("AUTH FAILED for sector %d with key %c. [nr=%08x cardRr=%08x] [nt=%08x succ=%08x]" , cardAUTHSC @@ -3291,15 +3291,15 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); break; } - + ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0); num_to_bytes(ans, 4, rAUTH_AT); EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); LED_C_ON(); - + if (MF_DBGLEVEL >= 3) { - Dbprintf("AUTH COMPLETED for sector %d with key %c. time=%d", - cardAUTHSC, + Dbprintf("AUTH COMPLETED for sector %d with key %c. time=%d", + cardAUTHSC, cardAUTHKEY == 0 ? 'A' : 'B', GetTickCount() - authTimer ); @@ -3311,20 +3311,20 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * if (len == 0) { LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); break; - } + } bool encrypted_data = (cardAUTHKEY != 0xFF) ; if(encrypted_data) mf_crypto1_decrypt(pcs, receivedCmd, len); - - if (len == 4 && (receivedCmd[0] == MIFARE_AUTH_KEYA || + + if (len == 4 && (receivedCmd[0] == MIFARE_AUTH_KEYA || receivedCmd[0] == MIFARE_AUTH_KEYB) ) { authTimer = GetTickCount(); cardAUTHSC = receivedCmd[1] / 4; // received block -> sector cardAUTHKEY = receivedCmd[0] & 0x1; crypto1_destroy(pcs); - + // load key into crypto crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY)); @@ -3335,7 +3335,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * num_to_bytes(nonce, 4, rAUTH_AT); } else { // nested authentication - ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0); + ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0); num_to_bytes(ans, 4, rAUTH_AT); if (MF_DBGLEVEL >= 3) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %c", receivedCmd[1], receivedCmd[1], cardAUTHKEY == 0 ? 'A' : 'B'); @@ -3345,20 +3345,20 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * cardSTATE = MFEMUL_AUTH1; break; } - + // rule 13 of 7.5.3. in ISO 14443-4. chaining shall be continued // BUT... ACK --> NACK if (len == 1 && receivedCmd[0] == CARD_ACK) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); break; } - + // rule 12 of 7.5.3. in ISO 14443-4. R(NAK) --> R(ACK) if (len == 1 && receivedCmd[0] == CARD_NACK_NA) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); break; } - + if(len != 4) { LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); break; @@ -3370,7 +3370,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * receivedCmd[0] == MIFARE_CMD_DEC || receivedCmd[0] == MIFARE_CMD_RESTORE || receivedCmd[0] == MIFARE_CMD_TRANSFER ) { - + if (receivedCmd[1] >= 16 * 4) { EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate (0x%02) on out of range block: %d (0x%02x), nacking",receivedCmd[0],receivedCmd[1],receivedCmd[1]); @@ -3407,8 +3407,8 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * break; } // increment, decrement, restore - if ( receivedCmd[0] == MIFARE_CMD_INC || - receivedCmd[0] == MIFARE_CMD_DEC || + if ( receivedCmd[0] == MIFARE_CMD_INC || + receivedCmd[0] == MIFARE_CMD_DEC || receivedCmd[0] == MIFARE_CMD_RESTORE) { if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)",receivedCmd[0], receivedCmd[1], receivedCmd[1]); @@ -3472,7 +3472,7 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); cardSTATE_TO_IDLE(); break; - } + } LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); cardINTREG = cardINTREG + ans; cardSTATE = MFEMUL_WORK; @@ -3506,9 +3506,9 @@ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t * } } - if (MF_DBGLEVEL >= 1) + if (MF_DBGLEVEL >= 1) Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen()); - + cmd_send(CMD_ACK,1,0,0,0,0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); set_tracing(false); diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index a23b5d7c2..c5e1e62f1 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -16,7 +16,7 @@ #ifdef __cplusplus extern "C" { #endif - + #include "usb_cmd.h" #include "cmd.h" #include "apps.h" @@ -138,6 +138,6 @@ void DetectNACKbug(); #ifdef __cplusplus } -#endif +#endif #endif /* __ISO14443A_H */ diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index 6167ca785..f093fb1a7 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -38,7 +38,7 @@ // 4sample #define SEND4STUFFBIT(x) ToSendStuffBit(x);ToSendStuffBit(x);ToSendStuffBit(x);ToSendStuffBit(x); //#define SEND4STUFFBIT(x) ToSendStuffBit(x); - // iceman, this threshold value, what makes 8 a good amplitude for this IQ values? + // iceman, this threshold value, what makes 8 a good amplitude for this IQ values? #ifndef SUBCARRIER_DETECT_THRESHOLD # define SUBCARRIER_DETECT_THRESHOLD 8 #endif @@ -130,29 +130,29 @@ static void DemodReset() { Demod.sumI = 0; Demod.sumQ = 0; Demod.startTime = 0; - Demod.endTime = 0; + Demod.endTime = 0; } static void DemodInit(uint8_t *data) { Demod.output = data; DemodReset(); - // memset(Demod.output, 0x00, MAX_FRAME_SIZE); + // memset(Demod.output, 0x00, MAX_FRAME_SIZE); } /* * 9.4395 us = 1 ETU and clock is about 1.5 us -* 13560000Hz +* 13560000Hz * 1000ms/s * timeout in ETUs (time to transfer 1 bit, 9.4395 us) * * Formula to calculate FWT (in ETUs) by timeout (in ms): -* fwt = 13560000 * 1000 / (8*16) * timeout; +* fwt = 13560000 * 1000 / (8*16) * timeout; * Sample: 3sec == 3000ms -* 13560000 * 1000 / (8*16) * 3000 == +* 13560000 * 1000 / (8*16) * 3000 == * 13560000000 / 384000 = 35312 FWT * @param timeout is in frame wait time, fwt, measured in ETUs -*/ +*/ static void iso14b_set_timeout(uint32_t timeout) { #define MAX_TIMEOUT 40542464 // 13560000Hz * 1000ms / (2^32-1) * (8*16) if(timeout > MAX_TIMEOUT) @@ -164,7 +164,7 @@ static void iso14b_set_timeout(uint32_t timeout) { static void iso14b_set_maxframesize(uint16_t size) { if (size > 256) size = MAX_FRAME_SIZE; - + Uart.byteCntMax = size; if(MF_DBGLEVEL >= 3) Dbprintf("ISO14443B Max frame size set to %d bytes", Uart.byteCntMax); } @@ -186,7 +186,7 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { * TR2 - PICC to PCD Frame Delay Time (per 14443-3 Amendment 1) * * Elementary Time Unit (ETU) is - * - 128 Carrier Cycles (9.4395 µS) = 8 Subcarrier Units + * - 128 Carrier Cycles (9.4395 µS) = 8 Subcarrier Units * - 1 ETU = 1 bit * - 10 ETU = 1 startbit, 8 databits, 1 stopbit (10bits length) * - startbit is a 0 @@ -194,19 +194,19 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { * * Start of frame (SOF) is * - [10-11] ETU of ZEROS, unmodulated time - * - [2-3] ETU of ONES, + * - [2-3] ETU of ONES, * * End of frame (EOF) is * - [10-11] ETU of ZEROS, unmodulated time * * -TO VERIFY THIS BELOW- * The mode FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK which we use to simulate tag - * works like this: + * works like this: * - A 1-bit input to the FPGA becomes 8 pulses at 847.5kHz (1.18µS / pulse) == 9.44us * - A 0-bit input to the FPGA becomes an unmodulated time of 1.18µS or does it become 8 nonpulses for 9.44us * * FPGA doesn't seem to work with ETU. It seems to work with pulse / duration instead. - * + * * Card sends data ub 847.e kHz subcarrier * subcar |duration| FC division * -------+--------+------------ @@ -236,17 +236,17 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { * things practical for the ARM (fc/32, 423.8 kbits/s, ~50 kbytes/s) * */ - + int i,j; uint8_t b; - + ToSendReset(); // Transmit a burst of ones, as the initial thing that lets the - // reader get phase sync. + // reader get phase sync. // This loop is TR1, per specification // TR1 minimum must be > 80/fs - // TR1 maximum 200/fs + // TR1 maximum 200/fs // 80/fs < TR1 < 200/fs // 10 ETU < TR1 < 24 ETU @@ -254,14 +254,14 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { // 10-11 ETU * 4times samples ZEROS for(i = 0; i < 10; i++) { SEND4STUFFBIT(0); } //for(i = 0; i < 10; i++) { ToSendStuffBit(0); } - + // 2-3 ETU * 4times samples ONES for(i = 0; i < 3; i++) { SEND4STUFFBIT(1); } //for(i = 0; i < 3; i++) { ToSendStuffBit(1); } - + // data for(i = 0; i < len; ++i) { - + // Start bit SEND4STUFFBIT(0); //ToSendStuffBit(0); @@ -269,8 +269,8 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { // Data bits b = cmd[i]; for(j = 0; j < 8; ++j) { - // if(b & 1) { - // SEND4STUFFBIT(1); + // if(b & 1) { + // SEND4STUFFBIT(1); // //ToSendStuffBit(1); // } else { // SEND4STUFFBIT(0); @@ -283,7 +283,7 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { // Stop bit SEND4STUFFBIT(1); //ToSendStuffBit(1); - + // Extra Guard bit // For PICC it ranges 0-18us (1etu = 9us) SEND4STUFFBIT(1); @@ -294,11 +294,11 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { // 10-11 ETU * 4 sample rate = ZEROS for(i = 0; i < 10; i++) { SEND4STUFFBIT(0); } //for(i = 0; i < 10; i++) { ToSendStuffBit(0); } - + // why this? for(i = 0; i < 40; i++) { SEND4STUFFBIT(1); } //for(i = 0; i < 40; i++) { ToSendStuffBit(1); } - + // Convert from last byte pos to length ++ToSendMax; } @@ -407,7 +407,7 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) { Uart.state = STATE_UNSYNCD; if (Uart.byteCnt != 0) return true; - + } else { // this is an error LED_A_OFF(); @@ -439,18 +439,18 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) { // Signal field is off with the appropriate LED LED_D_OFF(); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION); - + StartCountSspClk(); - + volatile uint8_t b = 0; // clear receiving shift register and holding register // What does this loop do? Is it TR1? - // loop is a wait/delay ? + // loop is a wait/delay ? /* for(uint8_t c = 0; c < 10;) { - // keep tx buffer in a defined state anyway. + // keep tx buffer in a defined state anyway. if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = 0xFF; ++c; @@ -471,9 +471,9 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) { // Wait for byte be become available in rx holding register if ( AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY ) { - + b = (uint8_t) AT91C_BASE_SSC->SSC_RHR; - + for ( mask = 0x80; mask != 0; mask >>= 1) { if ( Handle14443bReaderUartBit(b & mask)) { *len = Uart.byteCnt; @@ -481,7 +481,7 @@ static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) { } } } - } + } return false; } @@ -497,20 +497,20 @@ void ClearFpgaShiftingRegisters(void){ while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {}; b = AT91C_BASE_SSC->SSC_RHR; (void) b; - + // wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line) for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {}; if (AT91C_BASE_SSC->SSC_RHR) break; } - + // Clear TXRDY: //AT91C_BASE_SSC->SSC_THR = 0xFF; } void WaitForFpgaDelayQueueIsEmpty( uint16_t delay ){ // Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again: - uint8_t fpga_queued_bits = delay >> 3; // twich /8 ?? >>3, + uint8_t fpga_queued_bits = delay >> 3; // twich /8 ?? >>3, for (uint8_t i = 0; i <= fpga_queued_bits/8 + 1; ) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = 0xFF; @@ -522,36 +522,36 @@ void WaitForFpgaDelayQueueIsEmpty( uint16_t delay ){ static void TransmitFor14443b_AsTag( uint8_t *response, uint16_t len) { volatile uint32_t b; - + // Signal field is off with the appropriate LED LED_D_OFF(); //uint16_t fpgasendQueueDelay = 0; - + // Modulate BPSK FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK); SpinDelay(40); - + ClearFpgaShiftingRegisters(); - + FpgaSetupSsc(); // Transmit the response. for(uint16_t i = 0; i < len;) { - + // Put byte into tx holding register as soon as it is ready if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { AT91C_BASE_SSC->SSC_THR = response[++i]; } - + // Prevent rx holding register from overflowing if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { b = AT91C_BASE_SSC->SSC_RHR;(void)b; - } + } } - + //WaitForFpgaDelayQueueIsEmpty(fpgasendQueueDelay); - AT91C_BASE_SSC->SSC_THR = 0xFF; -} + AT91C_BASE_SSC->SSC_THR = 0xFF; +} //----------------------------------------------------------------------------- // Main loop of simulated tag: receive commands from reader, decide what // response to send, and send it. @@ -564,7 +564,7 @@ void SimulateIso14443bTag(uint32_t pupi) { SetAdcMuxFor(GPIO_MUXSEL_HIPKD); // Set up the synchronous serial port FpgaSetupSsc(); - + // allocate command receive buffer BigBuf_free(); BigBuf_Clear_ext(false); @@ -577,8 +577,8 @@ void SimulateIso14443bTag(uint32_t pupi) { // uint32_t time_0 = 0; // uint32_t t2r_time = 0; // uint32_t r2t_time = 0; - uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); - + uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); + // the only commands we understand is WUPB, AFI=0, Select All, N=1: // static const uint8_t cmdWUPB[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 }; // WUPB // ... and REQB, AFI=0, Normal Request, N=1: @@ -589,9 +589,9 @@ void SimulateIso14443bTag(uint32_t pupi) { // ... if not PUPI/UID is supplied we always respond with ATQB, PUPI = 820de174, Application Data = 0x20381922, // supports only 106kBit/s in both directions, max frame size = 32Bytes, // supports ISO14443-4, FWI=8 (77ms), NAD supported, CID not supported: - uint8_t respATQB[] = { 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, + uint8_t respATQB[] = { 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, 0x22, 0x00, 0x21, 0x85, 0x5e, 0xd7 }; - + // response to HLTB and ATTRIB static const uint8_t respOK[] = {0x00, 0x78, 0xF0}; @@ -605,15 +605,15 @@ void SimulateIso14443bTag(uint32_t pupi) { CodeIso14443bAsTag(respATQB, sizeof(respATQB)); uint8_t *encodedATQB = BigBuf_malloc(ToSendMax); uint16_t encodedATQBLen = ToSendMax; - memcpy(encodedATQB, ToSend, ToSendMax); + memcpy(encodedATQB, ToSend, ToSendMax); + - // prepare "OK" tag answer (encoded): CodeIso14443bAsTag(respOK, sizeof(respOK)); uint8_t *encodedOK = BigBuf_malloc(ToSendMax); - uint16_t encodedOKLen = ToSendMax; - memcpy(encodedOK, ToSend, ToSendMax); - + uint16_t encodedOKLen = ToSendMax; + memcpy(encodedOK, ToSend, ToSendMax); + // Simulation loop while (!BUTTON_PRESS() && !usb_poll_validate_length()) { WDT_HIT(); @@ -622,10 +622,10 @@ void SimulateIso14443bTag(uint32_t pupi) { if (cardSTATE == SIM_NOFIELD) { vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; if ( vHf > MF_MINFIELDV ) { - cardSTATE = SIM_IDLE; + cardSTATE = SIM_IDLE; LED_A_ON(); } - } + } if (cardSTATE == SIM_NOFIELD) continue; // Get reader command @@ -635,31 +635,31 @@ void SimulateIso14443bTag(uint32_t pupi) { } // ISO14443-B protocol states: - // REQ or WUP request in ANY state + // REQ or WUP request in ANY state // WUP in HALTED state if (len == 5 ) { if ( (receivedCmd[0] == ISO14443B_REQB && (receivedCmd[2] & 0x8)== 0x8 && cardSTATE == SIM_HALTED) || receivedCmd[0] == ISO14443B_REQB ){ - LogTrace(receivedCmd, len, 0, 0, NULL, true); + LogTrace(receivedCmd, len, 0, 0, NULL, true); cardSTATE = SIM_SELECTING; } } - + /* * How should this flow go? * REQB or WUPB * send response ( waiting for Attrib) * ATTRIB - * send response ( waiting for commands 7816) + * send response ( waiting for commands 7816) * HALT send halt response ( waiting for wupb ) */ - + switch (cardSTATE) { //case SIM_NOFIELD: case SIM_HALTED: case SIM_IDLE: { - LogTrace(receivedCmd, len, 0, 0, NULL, true); + LogTrace(receivedCmd, len, 0, 0, NULL, true); break; } case SIM_SELECTING: { @@ -677,7 +677,7 @@ void SimulateIso14443bTag(uint32_t pupi) { case SIM_ACKNOWLEDGE: { TransmitFor14443b_AsTag( encodedOK, encodedOKLen ); LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false); - cardSTATE = SIM_IDLE; + cardSTATE = SIM_IDLE; break; } case SIM_WORK: { @@ -694,22 +694,22 @@ void SimulateIso14443bTag(uint32_t pupi) { // CRC Check if (len >= 3){ // if crc exists - + if (!check_crc(CRC_14443_B, receivedCmd, len)) DbpString("+++CRC fail"); else DbpString("CRC passes"); } - cardSTATE = SIM_IDLE; + cardSTATE = SIM_IDLE; } break; } default: break; } - + ++cmdsReceived; } - if (MF_DBGLEVEL >= 2) + if (MF_DBGLEVEL >= 2) Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen()); switch_off(); //simulate } @@ -794,9 +794,9 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { case DEMOD_UNSYNCD: CHECK_FOR_SUBCARRIER(); - + // subcarrier detected - + if (v > SUBCARRIER_DETECT_THRESHOLD) { Demod.state = DEMOD_PHASE_REF_TRAINING; Demod.sumI = ci; @@ -809,14 +809,14 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { if (Demod.posCount < 8) { CHECK_FOR_SUBCARRIER(); - + if (v > SUBCARRIER_DETECT_THRESHOLD) { // set the reference phase (will code a logic '1') by averaging over 32 1/fs. // note: synchronization time > 80 1/fs Demod.sumI += ci; Demod.sumQ += cq; Demod.posCount++; - } else { + } else { // subcarrier lost Demod.state = DEMOD_UNSYNCD; } @@ -826,9 +826,9 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { break; case DEMOD_AWAITING_FALLING_EDGE_OF_SOF: - + MAKE_SOFT_DECISION(); - + if (v < 0) { // logic '0' detected Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF; Demod.posCount = 0; // start of SOF sequence @@ -841,12 +841,12 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { case DEMOD_GOT_FALLING_EDGE_OF_SOF: Demod.posCount++; - + MAKE_SOFT_DECISION(); - + if (v > 0) { // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges - if (Demod.posCount < 9*2) { + if (Demod.posCount < 9*2) { Demod.state = DEMOD_UNSYNCD; } else { LED_C_ON(); // Got SOF @@ -856,7 +856,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { } } else { // low phase of SOF too long (> 12 etu) - if (Demod.posCount > 14*2) { + if (Demod.posCount > 14*2) { Demod.state = DEMOD_UNSYNCD; LED_C_OFF(); } @@ -865,9 +865,9 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { case DEMOD_AWAITING_START_BIT: Demod.posCount++; - + MAKE_SOFT_DECISION(); - + if (v > 0) { if (Demod.posCount > 6*2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs Demod.state = DEMOD_UNSYNCD; @@ -883,10 +883,10 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { break; case DEMOD_RECEIVING_DATA: - + MAKE_SOFT_DECISION(); - if (Demod.posCount == 0) { + if (Demod.posCount == 0) { // first half of bit Demod.thisBit = v; Demod.posCount = 1; @@ -896,18 +896,18 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { Demod.shiftReg >>= 1; // OR in a logic '1' - if (Demod.thisBit > 0) + if (Demod.thisBit > 0) Demod.shiftReg |= 0x200; Demod.bitCount++; - + // 1 start 8 data 1 stop = 10 if (Demod.bitCount == 10) { - + uint16_t s = Demod.shiftReg; - + // stop bit == '1', start bit == '0' - if ((s & 0x200) && (s & 0x001) == 0 ) { + if ((s & 0x200) && (s & 0x001) == 0 ) { // left shift to drop the startbit uint8_t b = (s >> 1); Demod.output[Demod.len] = b; @@ -917,7 +917,7 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { // this one is a bit hard, either its a correc byte or its unsynced. Demod.state = DEMOD_UNSYNCD; LED_C_OFF(); - + // This is EOF (start, stop and all data bits == '0' if (s == 0) return true; } @@ -946,17 +946,17 @@ static void GetTagSamplesFor14443bDemod() { uint32_t time_0 = 0, time_stop = 0; BigBuf_free(); - + // Set up the demodulator for tag -> reader responses. DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); - + // The DMA buffer, used to stream samples from the FPGA int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); int8_t *upTo = dmaBuf; - + // Setup and start DMA. if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE) ){ - if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); + if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); return; } @@ -965,7 +965,7 @@ static void GetTagSamplesFor14443bDemod() { // get current clock time_0 = GetCountSspClk(); - + // rx counter - dma counter? (how much?) & (mod) mask > 2. (since 2bytes at the time is read) while ( !finished ) { @@ -992,12 +992,12 @@ static void GetTagSamplesFor14443bDemod() { finished = (time_stop > iso14b_timeout || gotFrame); } - + FpgaDisableSscDma(); - - if ( upTo ) + + if ( upTo ) upTo = NULL; - + if ( Demod.len > 0 ) LogTrace(Demod.output, Demod.len, time_0, time_stop, NULL, false); } @@ -1006,28 +1006,28 @@ static void GetTagSamplesFor14443bDemod() { // Transmit the command (to the tag) that was placed in ToSend[]. //----------------------------------------------------------------------------- static void TransmitFor14443b_AsReader(void) { - int c; - + int c; + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); SpinDelay(60); - + // What does this loop do? Is it TR1? - // 0xFF = 8 bits of 1. 1 bit == 1Etu,.. + // 0xFF = 8 bits of 1. 1 bit == 1Etu,.. // loop 10 * 8 = 80 ETU of delay, with a non modulated signal. why? // 80*9 = 720us. for(c = 0; c < 50;) { - + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = 0xFF; c++; } } - + // Send frame loop for(c = 0; c < ToSendMax;) { - - // Put byte into tx holding register as soon as it is ready + + // Put byte into tx holding register as soon as it is ready if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = ToSend[c++]; } @@ -1056,25 +1056,25 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) { */ int i; uint8_t b; - + ToSendReset(); // Send SOF - // 10-11 ETUs of ZERO + // 10-11 ETUs of ZERO for(i = 0; i < 10; ++i) ToSendStuffBit(0); - + // 2-3 ETUs of ONE ToSendStuffBit(1); ToSendStuffBit(1); // ToSendStuffBit(1); - + // Sending cmd, LSB // from here we add BITS for(i = 0; i < len; ++i) { // Start bit ToSendStuffBit(0); // Data bits - b = cmd[i]; + b = cmd[i]; // if ( b & 1 ) ToSendStuffBit(1); else ToSendStuffBit(0); // if ( (b>>1) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); // if ( (b>>2) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); @@ -1082,17 +1082,17 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) { // if ( (b>>4) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); // if ( (b>>5) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); // if ( (b>>6) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - // if ( (b>>7) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + // if ( (b>>7) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + + ToSendStuffBit( b & 1); + ToSendStuffBit( (b>>1) & 1); + ToSendStuffBit( (b>>2) & 1); + ToSendStuffBit( (b>>3) & 1); + ToSendStuffBit( (b>>4) & 1); + ToSendStuffBit( (b>>5) & 1); + ToSendStuffBit( (b>>6) & 1); + ToSendStuffBit( (b>>7) & 1); - ToSendStuffBit( b & 1); - ToSendStuffBit( (b>>1) & 1); - ToSendStuffBit( (b>>2) & 1); - ToSendStuffBit( (b>>3) & 1); - ToSendStuffBit( (b>>4) & 1); - ToSendStuffBit( (b>>5) & 1); - ToSendStuffBit( (b>>6) & 1); - ToSendStuffBit( (b>>7) & 1); - // Stop bit ToSendStuffBit(1); // EGT extra guard time @@ -1101,17 +1101,17 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) { ToSendStuffBit(1); ToSendStuffBit(1); } - + // Send EOF // 10-11 ETUs of ZERO for(i = 0; i < 10; ++i) ToSendStuffBit(0); // Transition time. TR0 - guard time // 8ETUS minum? - // Per specification, Subcarrier must be stopped no later than 2 ETUs after EOF. + // Per specification, Subcarrier must be stopped no later than 2 ETUs after EOF. // I'm guessing this is for the FPGA to be able to send all bits before we switch to listening mode for(i = 0; i < 24 ; ++i) ToSendStuffBit(1); - + // TR1 - Synchronization time // Convert from last character reference to length ToSendMax++; @@ -1123,7 +1123,7 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) { static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) { uint32_t time_start = GetCountSspClk(); - + CodeIso14443bAsReader(cmd, len); TransmitFor14443b_AsReader(); @@ -1154,7 +1154,7 @@ uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *r GetTagSamplesFor14443bDemod(); //no if(Demod.len < 3) return 0; - + // VALIDATE CRC if (!check_crc(CRC_14443_B, Demod.output, Demod.len)){ if (MF_DBGLEVEL > 3) Dbprintf("crc fail ICE"); @@ -1175,32 +1175,32 @@ uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card ) { static const uint8_t init_srx[] = { ISO14443B_INITIATE, 0x00, 0x97, 0x5b }; // SELECT command (with space for CRC) uint8_t select_srx[] = { ISO14443B_SELECT, 0x00, 0x00, 0x00}; - + CodeAndTransmit14443bAsReader(init_srx, sizeof(init_srx)); GetTagSamplesFor14443bDemod(); //no if (Demod.len == 0) return 2; - // Randomly generated Chip ID + // Randomly generated Chip ID if (card) card->chipid = Demod.output[0]; - + select_srx[1] = Demod.output[0]; - + AddCrc14B(select_srx, 2); - + CodeAndTransmit14443bAsReader(select_srx, sizeof(select_srx)); GetTagSamplesFor14443bDemod(); //no - + if (Demod.len != 3) return 2; - + // Check the CRC of the answer: if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) return 3; - + // Check response from the tag: should be the same UID as the command we just sent: - if (select_srx[1] != Demod.output[0]) + if (select_srx[1] != Demod.output[0]) return 1; // First get the tag's UID: @@ -1212,8 +1212,8 @@ uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card ) { if (Demod.len != 10) return 2; - - // The check the CRC of the answer + + // The check the CRC of the answer if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) return 3; @@ -1236,19 +1236,19 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) { static const uint8_t wupb[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 }; // ATTRIB command (with space for CRC) uint8_t attrib[] = { ISO14443B_ATTRIB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}; - + // first, wake up the tag CodeAndTransmit14443bAsReader(wupb, sizeof(wupb)); GetTagSamplesFor14443bDemod(); //select_card - + // ATQB too short? if (Demod.len < 14) return 2; - + // VALIDATE CRC if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) return 3; - + if (card) { card->uidlen = 4; memcpy(card->uid, Demod.output+1, 4); @@ -1257,7 +1257,7 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) { // copy the PUPI to ATTRIB ( PUPI == UID ) memcpy(attrib + 1, Demod.output + 1, 4); - + // copy the protocol info from ATQB (Protocol Info -> Protocol_Type) into ATTRIB (Param 3) attrib[7] = Demod.output[10] & 0x0F; AddCrc14B(attrib, 9); @@ -1273,8 +1273,8 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) { if (!check_crc(CRC_14443_B, Demod.output, Demod.len) ) return 3; - if (card) { - + if (card) { + // CID card->cid = Demod.output[0]; @@ -1287,8 +1287,8 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) { else if (maxFrame == 8) maxFrame = 256; else maxFrame = 257; iso14b_set_maxframesize(maxFrame); - - // FWT + + // FWT uint8_t fwt = card->atqb[6] >> 4; if ( fwt < 16 ){ uint32_t fwt_time = (302 << fwt); @@ -1305,7 +1305,7 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) { void iso14443b_setup() { LEDsoff(); FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - + // Initialize Demod and Uart structs DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); UartInit(BigBuf_malloc(MAX_FRAME_SIZE)); @@ -1315,14 +1315,14 @@ void iso14443b_setup() { // Set up the synchronous serial port FpgaSetupSsc(); - + // Signal field is on with the appropriate LED FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); SpinDelay(100); // Start the timer StartCountSspClk(); - + LED_D_ON(); } @@ -1342,7 +1342,7 @@ static bool ReadSTBlock(uint8_t block) { GetTagSamplesFor14443bDemod(); // Check if we got an answer from the tag - if (Demod.len != 6) { + if (Demod.len != 6) { DbpString("[!] expected 6 bytes from tag, got less..."); return false; } @@ -1357,22 +1357,22 @@ void ReadSTMemoryIso14443b(uint8_t numofblocks) { // Make sure that we start from off, since the tags are stateful; // confusing things will happen if we don't reset them between reads. //switch_off(); - + uint8_t i = 0x00; uint8_t *buf = BigBuf_malloc(sizeof(iso14b_card_select_t)); iso14443b_setup(); - + iso14b_card_select_t *card = (iso14b_card_select_t*)buf; uint8_t res = iso14443b_select_srx_card(card); // 0: OK 2: attrib fail, 3:crc fail, if ( res > 0 ) goto out; - + Dbprintf("[+] Tag memory dump, block 0 to %d", numofblocks); ++numofblocks; - + for (;;) { if (i == numofblocks) { DbpString("System area block (0xFF):"); @@ -1383,11 +1383,11 @@ void ReadSTMemoryIso14443b(uint8_t numofblocks) { do { res = ReadSTBlock(i); } while (!res && --retries); - + if (!res && !retries) { goto out; } - + // Now print out the memory location: Dbprintf("Address=%02x, Contents=%08x, CRC=%04x", i, (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0], @@ -1396,10 +1396,10 @@ void ReadSTMemoryIso14443b(uint8_t numofblocks) { if (i == 0xff) break; ++i; } - -out: + +out: switch_off(); // disconnect raw - SpinDelay(20); + SpinDelay(20); } static void iso1444b_setup_sniff(void){ @@ -1407,7 +1407,7 @@ static void iso1444b_setup_sniff(void){ LEDsoff(); FpgaDownloadAndGo(FPGA_BITSTREAM_HF); BigBuf_free(); - BigBuf_Clear_ext(false); + BigBuf_Clear_ext(false); clear_trace();//setup snoop set_tracing(true); @@ -1432,7 +1432,7 @@ static void iso1444b_setup_sniff(void){ // Set FPGA in the appropriate mode FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP); - SpinDelay(20); + SpinDelay(20); // Start the SSP timer StartCountSspClk(); @@ -1467,40 +1467,40 @@ void RAMFUNC SniffIso14443b(void) { bool ReaderIsActive = false; iso1444b_setup_sniff(); - + // The DMA buffer, used to stream samples from the FPGA int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); int8_t *data = dmaBuf; // Setup and start DMA. if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE) ){ - if (MF_DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting"); + if (MF_DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting"); BigBuf_free(); return; } - // time ZERO, the point from which it all is calculated. + // time ZERO, the point from which it all is calculated. time_0 = GetCountSspClk(); - + // loop and listen while (!BUTTON_PRESS()) { WDT_HIT(); ci = data[0]; cq = data[1]; - data += 2; - + data += 2; + if (data >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { data = dmaBuf; AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; + AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; } // no need to try decoding reader data if the tag is sending - if (!TagIsActive) { - + if (!TagIsActive) { + LED_A_INV(); - + if (Handle14443bReaderUartBit(ci & 0x01)) { time_stop = GetCountSspClk() - time_0; LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true); @@ -1509,8 +1509,8 @@ void RAMFUNC SniffIso14443b(void) { } else { time_start = GetCountSspClk() - time_0; } - - if (Handle14443bReaderUartBit(cq & 0x01)) { + + if (Handle14443bReaderUartBit(cq & 0x01)) { time_stop = GetCountSspClk() - time_0; LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true); UartReset(); @@ -1520,30 +1520,30 @@ void RAMFUNC SniffIso14443b(void) { } ReaderIsActive = (Uart.state > STATE_GOT_FALLING_EDGE_OF_SOF); } - + // no need to try decoding tag data if the reader is sending - and we cannot afford the time if (!ReaderIsActive) { // is this | 0x01 the error? & 0xfe in https://github.com/Proxmark/proxmark3/issues/103 // LSB is a fpga signal bit. - if (Handle14443bTagSamplesDemod(ci, cq)) { - time_stop = GetCountSspClk() - time_0; + if (Handle14443bTagSamplesDemod(ci, cq)) { + time_stop = GetCountSspClk() - time_0; LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false); - UartReset(); - DemodReset(); + UartReset(); + DemodReset(); } else { time_start = GetCountSspClk() - time_0; } TagIsActive = (Demod.state > DEMOD_GOT_FALLING_EDGE_OF_SOF); } } - + if (MF_DBGLEVEL >= 2) { DbpString("[+] Sniff statistics:"); Dbprintf("[+] uart State: %x ByteCount: %i ByteCountMax: %i", Uart.state, Uart.byteCnt, Uart.byteCntMax); Dbprintf("[+] trace length: %i", BigBuf_get_traceLen()); } - + switch_off(); } @@ -1571,54 +1571,54 @@ void SendRawCommand14443B_Ex(UsbCommand *c) { uint8_t buf[USB_CMD_DATA_SIZE] = {0x00}; if (MF_DBGLEVEL > 3) Dbprintf("14b raw: param, %04x", param ); - + // turn on trigger (LED_A) if ((param & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER) iso14b_set_trigger(true); - + if ((param & ISO14B_CONNECT) == ISO14B_CONNECT) { iso14443b_setup(); clear_trace(); } - + set_tracing(true); if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) { iso14b_card_select_t *card = (iso14b_card_select_t*)buf; - status = iso14443b_select_card(card); + status = iso14443b_select_card(card); cmd_send(CMD_ACK, status, sendlen, 0, buf, sendlen); // 0: OK 2: attrib fail, 3:crc fail, if ( status > 0 ) goto out; - } - + } + if ((param & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) { iso14b_card_select_t *card = (iso14b_card_select_t*)buf; status = iso14443b_select_srx_card(card); cmd_send(CMD_ACK, status, sendlen, 0, buf, sendlen); // 0: OK 2: demod fail, 3:crc fail, if ( status > 0 ) goto out; - } - + } + if ((param & ISO14B_APDU) == ISO14B_APDU) { status = iso14443b_apdu(cmd, len, buf); cmd_send(CMD_ACK, status, status, 0, buf, status); } - + if ((param & ISO14B_RAW) == ISO14B_RAW) { if((param & ISO14B_APPEND_CRC) == ISO14B_APPEND_CRC) { AddCrc14B(cmd, len); len += 2; } - - CodeAndTransmit14443bAsReader(cmd, len); // raw + + CodeAndTransmit14443bAsReader(cmd, len); // raw GetTagSamplesFor14443bDemod(); // raw - + sendlen = MIN(Demod.len, USB_CMD_DATA_SIZE); status = (Demod.len > 0) ? 0 : 1; cmd_send(CMD_ACK, status, sendlen, 0, Demod.output, sendlen); } - -out: + +out: // turn off trigger (LED_A) if ((param & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER) iso14b_set_trigger(false); @@ -1627,6 +1627,6 @@ out: // we don't send a HALT command. if ((param & ISO14B_DISCONNECT) == ISO14B_DISCONNECT) { switch_off(); // disconnect raw - SpinDelay(20); + SpinDelay(20); } } \ No newline at end of file diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 285ac226d..61e0e1130 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -14,22 +14,22 @@ // Modified to perform modulation onboard in arm rather than on PC // Also added additional reader commands (SELECT, READ etc.) //----------------------------------------------------------------------------- -// The ISO 15693 describes two transmission modes from reader to tag, and 4 -// transmission modes from tag to reader. As of Mar 2010 this code only -// supports one of each: "1of4" mode from reader to tag, and the highspeed +// The ISO 15693 describes two transmission modes from reader to tag, and 4 +// transmission modes from tag to reader. As of Mar 2010 this code only +// supports one of each: "1of4" mode from reader to tag, and the highspeed // variant with one subcarrier from card to reader. -// As long, as the card fully support ISO 15693 this is no problem, since the -// reader chooses both data rates, but some non-standard tags do not. Further for +// As long, as the card fully support ISO 15693 this is no problem, since the +// reader chooses both data rates, but some non-standard tags do not. Further for // the simulation to work, we will need to support all data rates. // // VCD (reader) -> VICC (tag) // 1 out of 256: -// data rate: 1,66 kbit/s (fc/8192) +// data rate: 1,66 kbit/s (fc/8192) // used for long range // 1 out of 4: // data rate: 26,48 kbit/s (fc/512) // used for short range, high speed -// +// // VICC (tag) -> VCD (reader) // Modulation: // ASK / one subcarrier (423,75 khz) @@ -49,11 +49,11 @@ // TODO / BUGS / ISSUES: // *) writing to tags takes longer: we miss the answer from the tag in most cases // -> tweak the read-timeout times -// *) signal decoding from the card is still a bit shaky. +// *) signal decoding from the card is still a bit shaky. // *) signal decoding is unable to detect collissions. -// *) add anti-collission support for inventory-commands +// *) add anti-collission support for inventory-commands // *) read security status of a block -// *) sniffing and simulation do only support one transmission mode. need to support +// *) sniffing and simulation do only support one transmission mode. need to support // all 8 transmission combinations // *) remove or refactor code under "depricated" // *) document all the functions @@ -70,7 +70,7 @@ // This section basicly contains transmission and receiving of bits /////////////////////////////////////////////////////////////////////// -// 32 + 2 crc + 1 +// 32 + 2 crc + 1 #define ISO15_MAX_FRAME 35 #define CMD_ID_RESP 5 #define CMD_READ_RESP 13 @@ -92,7 +92,7 @@ static void BuildIdentifyRequest(uint8_t *cmdout); static void BuildInventoryResponse(uint8_t *cmdout, uint8_t *uid); // --------------------------- -// Signal Processing +// Signal Processing // --------------------------- // prepare data using "1 out of 4" code for later transmission @@ -176,7 +176,7 @@ static void CodeIso15693AsReader(uint8_t *cmd, int n) { } // encode data using "1 out of 256" sheme -// data rate is 1,66 kbit/s (fc/8192) +// data rate is 1,66 kbit/s (fc/8192) // is designed for more robust communication over longer distances static void CodeIso15693AsReader256(uint8_t *cmd, int n) { int i, j; @@ -196,7 +196,7 @@ static void CodeIso15693AsReader256(uint8_t *cmd, int n) { ToSendStuffBit(1); ToSendStuffBit(1); ToSendStuffBit(0); - + for(i = 0; i < n; i++) { for (j = 0; j <= 255; j++) { if (cmd[i] == j) { @@ -205,8 +205,8 @@ static void CodeIso15693AsReader256(uint8_t *cmd, int n) { } else { ToSendStuffBit(1); ToSendStuffBit(1); - } - } + } + } } // EOF ToSendStuffBit(1); @@ -236,19 +236,19 @@ static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *w } c = 0; - for(;;) { + for(;;) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = cmd[c]; if( ++c >= len) break; } - WDT_HIT(); + WDT_HIT(); } - + if (samples) { if (wait) *samples = (c + *wait) << 3; else - *samples = c << 3; + *samples = c << 3; } } @@ -258,7 +258,7 @@ static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *w static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int *wait) { int c = 0; FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K); - + if (wait) { for (c = 0; c < *wait;) { if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { @@ -269,19 +269,19 @@ static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int } } - c = 0; + c = 0; for(;;) { if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = cmd[c]; if( ++c >= len) break; } - WDT_HIT(); + WDT_HIT(); } if (samples) { if (wait) *samples = (c + *wait) << 3; else - *samples = c << 3; + *samples = c << 3; } } @@ -289,7 +289,7 @@ static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int // DEMODULATE tag answer //----------------------------------------------------------------------------- static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) { - + int i, j; int max = 0, maxPos = 0, skip = 4; int k = 0; // this will be our return value @@ -308,9 +308,9 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) { // DbpString("SOF at %d, correlation %d", maxPos,max/(ARRAYLEN(FrameSOF)/skip)); // greg - If correlation is less than 1 then there's little point in continuing - if ((max / (ARRAYLEN(FrameSOF)/skip) ) < 1) + if ((max / (ARRAYLEN(FrameSOF)/skip) ) < 1) return k; - + i = maxPos + ARRAYLEN(FrameSOF) / skip; uint8_t outBuf[ISO15_MAX_FRAME]; @@ -335,31 +335,31 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) { if (corrEOF > corr1 && corrEOF > corr0) break; - + if (corr1 > corr0) { i += ARRAYLEN(Logic1) / skip; outBuf[k] |= mask; } else { i += ARRAYLEN(Logic0) / skip; } - + mask <<= 1; - + if (mask == 0) { k++; mask = 0x01; } - + if ( ( i + (int)ARRAYLEN(FrameEOF)) >= samplecount-1) { //Dbprintf("[!] ran off end! %d | %d",( i + (int)ARRAYLEN(FrameEOF)), samplecount-1); break; } } - + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("ice: demod bytes %u", k); - + if (mask != 0x01) { // this happens, when we miss the EOF - + // TODO: for some reason this happens quite often if (MF_DBGLEVEL >= MF_DBG_ERROR && k != 0) Dbprintf("[!] error, uneven octet! (extra bits!) mask %02x", mask); //if (mask < 0x08) k--; // discard the last uneven octet; @@ -378,7 +378,7 @@ static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) { // received // samples // elapsed -// returns: +// returns: // number of decoded bytes // logging enabled static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) { @@ -392,7 +392,7 @@ static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) { uint8_t *buf = BigBuf_malloc(SIGNAL_BUFF_SIZE); if (elapsed) *elapsed = 0; - + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); for(;;) { @@ -414,9 +414,9 @@ static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) { // close to what we want. // iceman 2016, amplitude sqrt(abs(i) + abs(q)) if (getNext) { - + buf[counter++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1)); - + if (counter >= SIGNAL_BUFF_SIZE) break; } else { @@ -424,11 +424,11 @@ static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) { } getNext = !getNext; } - } - time_stop = GetCountSspClk() - time_0 ; - int len = DemodAnswer(received, buf, counter); + } + time_stop = GetCountSspClk() - time_0 ; + int len = DemodAnswer(received, buf, counter); LogTrace(received, len, time_0 << 4, time_stop << 4, NULL, false); - BigBuf_free(); + BigBuf_free(); return len; } @@ -444,9 +444,9 @@ static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elap // get current clock time_0 = GetCountSspClk(); - + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); - + for(;;) { WDT_HIT(); @@ -454,7 +454,7 @@ static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elap ci = (int8_t)AT91C_BASE_SSC->SSC_RHR; ci = ABS(ci); - + // The samples are correlations against I and Q versions of the // tone that the tag AM-modulates, so every other sample is I, // every other is Q. We just want power, so abs(I) + abs(Q) is @@ -471,11 +471,11 @@ static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elap getNext = !getNext; } } - + time_stop = GetCountSspClk() - time_0; - int k = DemodAnswer(received, buf, counter); - LogTrace(received, k, time_0 << 4, time_stop << 4, NULL, false); - return k; + int k = DemodAnswer(received, buf, counter); + LogTrace(received, k, time_0 << 4, time_stop << 4, NULL, false); + return k; } //----------------------------------------------------------------------------- @@ -486,26 +486,26 @@ static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elap void AcquireRawAdcSamplesIso15693(void) { int c = 0, getNext = false; int ci = 0, cq = 0; - + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); SetAdcMuxFor(GPIO_MUXSEL_HIPKD); FpgaSetupSsc(); - + // Now send the command FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX); SpinDelay(200); uint8_t *buf = BigBuf_get_addr(); - + uint32_t time_start = GetCountSspClk(); uint8_t cmd[CMD_ID_RESP] = {0}; BuildIdentifyRequest(cmd); - + // sending command c = 0; for(;;) { WDT_HIT(); - + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = ToSend[c]; c++; @@ -515,31 +515,31 @@ void AcquireRawAdcSamplesIso15693(void) { } } - + LogTrace(cmd, CMD_ID_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true); - + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); c = 0; for(;;) { WDT_HIT(); - + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { ci = (int8_t)AT91C_BASE_SSC->SSC_RHR; ci = ABS(ci); - + // The samples are correlations against I and Q versions of the // tone that the tag AM-modulates, so every other sample is I, // every other is Q. We just want power, so abs(I) + abs(Q) is // close to what we want. // iceman 2016, amplitude sqrt(abs(i) + abs(q)) if (getNext) { - + buf[c++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1)); - + if (c >= 7000) break; - + } else { cq = ci; } @@ -553,24 +553,24 @@ void RecordRawAdcSamplesIso15693(void) { int c = 0, getNext = false; int ci = 0, cq = 0; - + Iso15693InitReader(); uint8_t *buf = BigBuf_get_addr(); - for(;;) { + for(;;) { WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - ci = (int8_t)AT91C_BASE_SSC->SSC_RHR; + ci = (int8_t)AT91C_BASE_SSC->SSC_RHR; ci = ABS(ci); // The samples are correlations against I and Q versions of the // tone that the tag AM-modulates, so every other sample is I, // every other is Q. We just want power, so abs(I) + abs(Q) is // close to what we want. if (getNext) { - + buf[c++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1)); if(c >= 7000) @@ -582,18 +582,18 @@ void RecordRawAdcSamplesIso15693(void) { getNext = !getNext; } } - + Dbprintf("done"); switch_off(); } -// Initialize the proxmark as iso15k reader +// Initialize the proxmark as iso15k reader // (this might produces glitches that confuse some tags void Iso15693InitReader(void) { LEDsoff(); clear_trace(); set_tracing(true); - + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); // Start from off (no field generated) @@ -601,13 +601,13 @@ void Iso15693InitReader(void) { SpinDelay(10); SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - + FpgaSetupSsc(); // Give the tags time to energize FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); SpinDelay(200); - + // Start the timer StartCountSspClk(); @@ -672,7 +672,7 @@ static void BuildInventoryResponse(uint8_t *out, uint8_t *uid) { // one sub-carrier, inventory, 1 slot, fast rate // AFI is at bit 5 (1<<4) when doing an INVENTORY //(1 << 2) | (1 << 5) | (1 << 1); - cmd[0] = 0; // + cmd[0] = 0; // cmd[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported // 64-bit UID cmd[2] = uid[7]; //0x32; @@ -691,19 +691,19 @@ static void BuildInventoryResponse(uint8_t *out, uint8_t *uid) { // Universal Method for sending to and recv bytes from a tag // init ... should we initialize the reader? -// speed ... 0 low speed, 1 hi speed +// speed ... 0 low speed, 1 hi speed // **recv will return you a pointer to the received data -// If you do not need the answer use NULL for *recv[] +// If you do not need the answer use NULL for *recv[] // return: lenght of received data // logging enabled int SendDataTag(uint8_t *send, int sendlen, bool init, int speed, uint8_t *outdata) { int t_samples = 0, wait = 0, elapsed = 0, answer_len = 0; - + LEDsoff(); - + if (init) Iso15693InitReader(); - + LED_A_ON(); if (!speed) @@ -712,15 +712,15 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, int speed, uint8_t *outda CodeIso15693AsReader(send, sendlen); // high speed (1 out of 4) LED_A_INV(); - + uint32_t time_start = GetCountSspClk(); TransmitTo15693Tag(ToSend, ToSendMax, &t_samples, &wait); LogTrace(send, sendlen, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true); - + // Now wait for a response if (outdata != NULL) { - LED_B_INV(); + LED_B_INV(); answer_len = GetIso15693AnswerFromTag(outdata, &elapsed); } @@ -729,7 +729,7 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, int speed, uint8_t *outda } // -------------------------------------------------------------------- -// Debug Functions +// Debug Functions // -------------------------------------------------------------------- // Decodes a message from a tag and displays its metadata and content @@ -738,37 +738,37 @@ void DbdecodeIso15693Answer(int len, uint8_t *d) { char status[DBD15STATLEN+1] = {0}; if (len > 3) { - if (d[0] & ( 1 << 3 )) + if (d[0] & ( 1 << 3 )) strncat(status, "ProtExt ", DBD15STATLEN); - if (d[0] & 1) { + if (d[0] & 1) { // error strncat(status, "Error ", DBD15STATLEN); switch (d[1]) { - case 0x01: + case 0x01: strncat(status, "01: not supported", DBD15STATLEN); break; - case 0x02: + case 0x02: strncat(status, "02: not recognized", DBD15STATLEN); break; - case 0x03: + case 0x03: strncat(status, "03: opt not supported", DBD15STATLEN); break; - case 0x0f: + case 0x0f: strncat(status, "0F: no info", DBD15STATLEN); break; - case 0x10: + case 0x10: strncat(status, "10: dont exist", DBD15STATLEN); break; - case 0x11: + case 0x11: strncat(status, "11: lock again", DBD15STATLEN); break; - case 0x12: + case 0x12: strncat(status, "12: locked", DBD15STATLEN); break; - case 0x13: + case 0x13: strncat(status, "13: program error", DBD15STATLEN); break; - case 0x14: + case 0x14: strncat(status, "14: lock error", DBD15STATLEN); break; default: @@ -778,7 +778,7 @@ void DbdecodeIso15693Answer(int len, uint8_t *d) { } else { strncat(status ,"No error ", DBD15STATLEN); } - + if (CheckCrc(d, len)) strncat(status, "[+] crc OK", DBD15STATLEN); else @@ -801,12 +801,12 @@ void DbdecodeIso15693Answer(int len, uint8_t *d) { void ReaderIso15693(uint32_t parameter) { int answerLen1 = 0; int tsamples = 0, wait = 0, elapsed = 0; - + uint8_t uid[8] = {0,0,0,0,0,0,0,0}; - // set up device/fpga + // set up device/fpga Iso15693InitReader(); - + uint8_t *answer1 = BigBuf_malloc(50); uint8_t *answer2 = BigBuf_malloc(50); @@ -822,7 +822,7 @@ void ReaderIso15693(uint32_t parameter) { BuildIdentifyRequest( cmd ); TransmitTo15693Tag(ToSend, ToSendMax, &tsamples, &wait); LogTrace(cmd, CMD_ID_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true); - + // Now wait for a response answerLen1 = GetIso15693AnswerFromTag(answer1, &elapsed) ; @@ -834,10 +834,10 @@ void ReaderIso15693(uint32_t parameter) { uid[3] = answer1[6]; uid[4] = answer1[5]; uid[5] = answer1[4]; - uid[6] = answer1[3]; + uid[6] = answer1[3]; uid[7] = answer1[2]; - - if ( MF_DBGLEVEL >= MF_DBG_EXTENDED) { + + if ( MF_DBGLEVEL >= MF_DBG_EXTENDED) { Dbprintf("[+] UID = %02X%02X%02X%02X%02X%02X%02X%02X", uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[5], uid[6] @@ -863,15 +863,15 @@ void ReaderIso15693(uint32_t parameter) { // Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands // all demodulation performed in arm rather than host. - greg void SimTagIso15693(uint32_t parameter, uint8_t *uid) { - + LEDsoff(); - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); SetAdcMuxFor(GPIO_MUXSEL_HIPKD); FpgaSetupSsc(); // Start from off (no field generated) FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); SpinDelay(200); - + LED_A_ON(); uint32_t time_start = 0; @@ -886,23 +886,23 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid) { LED_C_ON(); // Build a suitable reponse to the reader INVENTORY cocmmand - // not so obsvious, but in the call to BuildInventoryResponse, the command is copied to the global ToSend buffer used below. + // not so obsvious, but in the call to BuildInventoryResponse, the command is copied to the global ToSend buffer used below. uint8_t cmd[CMD_INV_RESP] = {0}; BuildInventoryResponse(cmd, uid); - + while (!BUTTON_PRESS() && !usb_poll_validate_length() ) { WDT_HIT(); - + // Listen to reader ans = GetIso15693AnswerFromSniff(buf, &samples, &elapsed) ; // we should do a better check than this if (ans >= 1 ) { - + time_start = GetCountSspClk(); TransmitTo15693Reader(ToSend, ToSendMax, &tsamples, &wait); - LogTrace(cmd, CMD_INV_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true); - + LogTrace(cmd, CMD_INV_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { Dbprintf("[+] %d octets read from reader command: %x %x %x %x %x %x %x %x", ans, buf[0], buf[1], buf[2], buf[3], @@ -916,38 +916,38 @@ void SimTagIso15693(uint32_t parameter, uint8_t *uid) { // Since there is no standardized way of reading the AFI out of a tag, we will brute force it // (some manufactures offer a way to read the AFI, though) -void BruteforceIso15693Afi(uint32_t speed) { +void BruteforceIso15693Afi(uint32_t speed) { uint8_t data[7] = {0,0,0,0,0,0,0}; uint8_t buf[ISO15_MAX_FRAME]; memset(buf, 0x00, sizeof(buf)); int datalen = 0, recvlen = 0; - + Iso15693InitReader(); - + // first without AFI // Tags should respond wihtout AFI and with AFI=0 even when AFI is active - + data[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; data[1] = ISO15_CMD_INVENTORY; data[2] = 0; // mask length AddCrc(data, 3); datalen += 2; - + recvlen = SendDataTag(data, datalen, false, speed, buf); - + WDT_HIT(); - + if (recvlen >= 12) { Dbprintf("NoAFI UID = %s", sprintUID(NULL, buf + 2) ); } - + // now with AFI data[0] |= ISO15_REQINV_AFI; //data[1] = ISO15_CMD_INVENTORY; data[2] = 0; // AFI data[3] = 0; // mask length - + for (uint16_t i = 0; i < 256; i++) { data[2] = i & 0xFF; AddCrc(data, 4); @@ -957,19 +957,19 @@ void BruteforceIso15693Afi(uint32_t speed) { if (recvlen >= 12) { Dbprintf("AFI = %i UID = %s", i, sprintUID(NULL, buf + 2) ); } - + if (BUTTON_PRESS()) { DbpString("button pressed, aborting.."); break; } - } - + } + DbpString("AFI Bruteforcing done."); switch_off(); } // Allows to directly send commands to the tag via the client -// Has to increase dialog between device and client. +// Has to increase dialog between device and client. void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data) { bool init = true; @@ -981,16 +981,16 @@ void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint DbpString("[+] SEND"); Dbhexdump(datalen, data, true); } - + buflen = SendDataTag(data, datalen, init, speed, (recv ? buf : NULL)); - - if (recv) { + + if (recv) { buflen = (buflen > ISO15_MAX_FRAME) ? ISO15_MAX_FRAME : buflen; - + LED_B_ON(); cmd_send(CMD_ACK, buflen, 0, 0, buf, buflen); - LED_B_OFF(); - + LED_B_OFF(); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { DbpString("[+] RECV"); DbdecodeIso15693Answer(buflen, buf); diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 96abd9b99..3296aff8c 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -85,11 +85,11 @@ void setT55xxConfig(uint8_t arg0, t55xx_config *c) { if (arg0 == 0) { return; } - + if (!FlashInit()) { return; } - + uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN); Flash_CheckBusy(BUSY_TIMEOUT); uint16_t res = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN); @@ -98,9 +98,9 @@ void setT55xxConfig(uint8_t arg0, t55xx_config *c) { BigBuf_free(); return; } - + memcpy(buf, &t_config, T55XX_CONFIG_LEN); - + Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); Flash_Erase4k(3, 0xD); @@ -109,8 +109,8 @@ void setT55xxConfig(uint8_t arg0, t55xx_config *c) { if ( res == T55XX_CONFIG_LEN && MF_DBGLEVEL > 1) { DbpString("T55XX Config save success"); } - - BigBuf_free(); + + BigBuf_free(); #endif } @@ -125,11 +125,11 @@ void loadT55xxConfig(void) { } uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN); - + Flash_CheckBusy(BUSY_TIMEOUT); uint16_t isok = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN); FlashStop(); - + // verify read mem is actual data. uint8_t cntA = T55XX_CONFIG_LEN, cntB = T55XX_CONFIG_LEN; for (int i=0; i< T55XX_CONFIG_LEN; i++) { @@ -140,9 +140,9 @@ void loadT55xxConfig(void) { BigBuf_free(); return; } - + memcpy((uint8_t *)&t_config, buf, T55XX_CONFIG_LEN); - + if ( isok == T55XX_CONFIG_LEN) { if (MF_DBGLEVEL > 1) DbpString("T55XX Config load success"); } @@ -581,7 +581,7 @@ void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycle //FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE ); FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); WaitMS(20); - + int i = 0, x = 0; uint8_t *buf = BigBuf_get_addr(); @@ -598,11 +598,11 @@ void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycle AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK; AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK; - + uint8_t check = 1; for(;;) { - + if ( numcycles > -1 ) { if ( x != numcycles ) { ++x; @@ -744,7 +744,7 @@ static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) *n += fc; } if (mod > 0) (*modCnt)++; - + if ((mod > 0) && modAdjOk){ //fsk2 if ((*modCnt % modAdj) == 0){ //if 4th 8 length wave in a rf/50 add extra 8 length wave memset(dest + (*n), 0, fc - halfFC); @@ -1500,9 +1500,9 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { bool brute_mem = arg0 & 0x4; uint32_t i = 0; - + // regular read mode - bool RegReadMode = (Block == 0xFF); + bool RegReadMode = (Block == 0xFF); uint8_t start_wait = 4; size_t samples = 12000; @@ -1510,7 +1510,7 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { start_wait = 0; samples = 1024; } - + //clear buffer now so it does not interfere with timing later BigBuf_Clear_keep_EM(); @@ -1523,7 +1523,7 @@ void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { LFSetupFPGAForADC(95, true); // make sure tag is fully powered up... WaitMS(start_wait); - + // Trigger T55x7 Direct Access Mode with start gap FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS(t_config.start_gap); @@ -1570,9 +1570,9 @@ void T55xx_ChkPwds() { // First get baseline and setup LF mode. // tends to mess up BigBuf uint8_t *buf = BigBuf_get_addr(); - + uint32_t b1, baseline = 0; - + // collect baseline for failed attempt uint8_t x = 32; while (x--) { @@ -1580,16 +1580,16 @@ void T55xx_ChkPwds() { T55xxReadBlock(4, 1, 0); for (uint16_t j=0; j < 1024; ++j) b1 += buf[j]; - + b1 *= b1; - b1 >>= 8; + b1 >>= 8; baseline += b1; } baseline >>= 5; - Dbprintf("[=] Baseline determined [%u]", baseline); + Dbprintf("[=] Baseline determined [%u]", baseline); + - uint8_t *pwds = BigBuf_get_EM_addr(); uint16_t pwdCount = 0; uint32_t candidate = 0; @@ -1599,20 +1599,20 @@ void T55xx_ChkPwds() { if ( use_flashmem ) { BigBuf_Clear_EM(); uint16_t isok = 0; - uint8_t counter[2] = {0x00, 0x00}; + uint8_t counter[2] = {0x00, 0x00}; isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET, counter, sizeof(counter) ); if ( isok != sizeof(counter) ) goto OUT; - + pwdCount = counter[1] << 8 | counter[0]; - - if ( pwdCount == 0 && pwdCount == 0xFFFF) + + if ( pwdCount == 0 && pwdCount == 0xFFFF) goto OUT; isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET+2, pwds, pwdCount * 4); if ( isok != pwdCount * 4 ) goto OUT; - + Dbprintf("[=] Password dictionary count %d ", pwdCount); } #endif @@ -1623,38 +1623,38 @@ void T55xx_ChkPwds() { if (BUTTON_PRESS() && !usb_poll_validate_length()) { goto OUT; } - + pwd = bytes_to_num(pwds + i * 4, 4); - + T55xxReadBlock(5, 0, pwd); - + // calc mean of BigBuf 1024 samples. uint32_t sum = 0; for (uint16_t j=0; j<1024; ++j) { sum += buf[j]; } - + sum *= sum; sum >>= 8; - + int32_t tmp = (sum - baseline); curr = ABS(tmp); - + Dbprintf("[=] Pwd %08X | ABS %u", pwd, curr ); - + if ( curr > prev ) { - - + + Dbprintf("[=] --> ABS %u Candidate %08X <--", curr, pwd ); candidate = pwd; prev = curr; } } - + if ( candidate ) ret = 1; - + OUT: FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); cmd_send(CMD_ACK,ret,candidate,0,0,0); @@ -2122,7 +2122,7 @@ void Cotag(uint32_t arg0) { LED_A_ON(); LFSetupFPGAForADC(89, true); - + //clear buffer now so it does not interfere with timing later BigBuf_Clear_ext(false); diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 4b036d088..80d95bb4a 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -42,7 +42,7 @@ void setSamplingConfig(sample_config *sc) { if(sc->divisor != 0) config.divisor = sc->divisor; if(sc->bits_per_sample != 0) config.bits_per_sample = sc->bits_per_sample; if(sc->trigger_threshold != -1) config.trigger_threshold = sc->trigger_threshold; - + config.decimation = (sc->decimation != 0) ? sc->decimation : 1; config.averaging = sc->averaging; if(config.bits_per_sample > 8) config.bits_per_sample = 8; @@ -136,17 +136,17 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag uint32_t sample_total_numbers = 0; uint32_t sample_total_saved = 0; uint32_t cancel_counter = 0; - + while (!BUTTON_PRESS() && !usb_poll_validate_length() ) { WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - - // Testpoint 8 (TP8) can be used to trigger oscilliscope + + // Testpoint 8 (TP8) can be used to trigger oscilliscope LED_D_OFF(); - - // threshold either high or low values 128 = center 0. if trigger = 178 + + // threshold either high or low values 128 = center 0. if trigger = 178 if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) { if (cancel_after > 0) { cancel_counter++; @@ -155,7 +155,7 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag } continue; } - + trigger_threshold = 0; sample_total_numbers++; @@ -168,22 +168,22 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag if (sample_counter < decimation) continue; sample_counter = 0; } - + // averaging if (averaging && decimation > 1) { sample = sample_sum / decimation; sample_sum =0; } - + // store the sample sample_total_saved ++; if (bits_per_sample == 8) { dest[sample_total_saved-1] = sample; - - // Get the return value correct - data.numbits = sample_total_saved << 3; + + // Get the return value correct + data.numbits = sample_total_saved << 3; if (sample_total_saved >= bufsize) break; - + } else { pushBit(&data, sample & 0x80); if (bits_per_sample > 1) pushBit(&data, sample & 0x40); @@ -203,11 +203,11 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...", dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); } - + // Ensure that DC offset removal and noise check is performed for any device-side processing removeSignalOffset(dest, bufsize); computeSignalProperties(dest, bufsize); - + return data.numbits; } /** @@ -250,7 +250,7 @@ uint32_t SampleLF(bool printCfg, int sample_size) { BigBuf_Clear_ext(false); uint32_t ret = ReadLF(true, printCfg, sample_size); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - return ret; + return ret; } /** * Initializes the FPGA for snoop-mode (field off), and acquires the samples. @@ -260,7 +260,7 @@ uint32_t SnoopLF() { BigBuf_Clear_ext(false); uint32_t ret = ReadLF(false, true, 0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - return ret; + return ret; } /** @@ -272,10 +272,10 @@ void doT55x7Acquisition(size_t sample_size) { #define T55xx_READ_UPPER_THRESHOLD 128+60 // 60 grph #define T55xx_READ_LOWER_THRESHOLD 128-60 // -60 grph #define T55xx_READ_TOL 5 - + uint8_t *dest = BigBuf_get_addr(); uint16_t bufsize = BigBuf_max_traceLen(); - + if ( bufsize > sample_size ) bufsize = sample_size; @@ -284,18 +284,18 @@ void doT55x7Acquisition(size_t sample_size) { bool startFound = false; bool highFound = false; bool lowFound = false; - - while(!BUTTON_PRESS() && !usb_poll_validate_length() && skipCnt < 1000 && (i < bufsize) ) { - WDT_HIT(); - + while(!BUTTON_PRESS() && !usb_poll_validate_length() && skipCnt < 1000 && (i < bufsize) ) { + WDT_HIT(); + + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - curSample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + curSample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; LED_D_OFF(); - + // skip until the first high sample above threshold if (!startFound && curSample > T55xx_READ_UPPER_THRESHOLD) { - //if (curSample > lastSample) + //if (curSample > lastSample) // lastSample = curSample; highFound = true; } else if (!highFound) { @@ -304,7 +304,7 @@ void doT55x7Acquisition(size_t sample_size) { } // skip until the first low sample below threshold if (!startFound && curSample < T55xx_READ_LOWER_THRESHOLD) { - //if (curSample > lastSample) + //if (curSample > lastSample) lastSample = curSample; lowFound = true; } else if (!lowFound) { @@ -341,22 +341,22 @@ void doCotagAcquisition(size_t sample_size) { uint8_t *dest = BigBuf_get_addr(); uint16_t bufsize = BigBuf_max_traceLen(); - + if ( bufsize > sample_size ) bufsize = sample_size; - dest[0] = 0; - uint8_t sample = 0, firsthigh = 0, firstlow = 0; + dest[0] = 0; + uint8_t sample = 0, firsthigh = 0, firstlow = 0; uint16_t i = 0; uint16_t noise_counter = 0; - + while (!BUTTON_PRESS() && !usb_poll_validate_length() && (i < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) { - WDT_HIT(); + WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; LED_D_OFF(); - + // find first peak if ( !firsthigh ) { if (sample < COTAG_ONE_THRESHOLD) { @@ -375,14 +375,14 @@ void doCotagAcquisition(size_t sample_size) { firstlow = 1; } - ++i; - + ++i; + if ( sample > COTAG_ONE_THRESHOLD) dest[i] = 255; - else if ( sample < COTAG_ZERO_THRESHOLD) + else if ( sample < COTAG_ZERO_THRESHOLD) dest[i] = 0; - else - dest[i] = dest[i-1]; + else + dest[i] = dest[i-1]; } } } @@ -391,12 +391,12 @@ uint32_t doCotagAcquisitionManchester() { uint8_t *dest = BigBuf_get_addr(); uint16_t bufsize = BigBuf_max_traceLen(); - + if ( bufsize > COTAG_BITS ) bufsize = COTAG_BITS; - dest[0] = 0; - uint8_t sample = 0, firsthigh = 0, firstlow = 0; + dest[0] = 0; + uint8_t sample = 0, firsthigh = 0, firstlow = 0; uint16_t sample_counter = 0, period = 0; uint8_t curr = 0, prev = 0; uint16_t noise_counter = 0; @@ -405,29 +405,29 @@ uint32_t doCotagAcquisitionManchester() { WDT_HIT(); if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; LED_D_OFF(); - + // find first peak if ( !firsthigh ) { if (sample < COTAG_ONE_THRESHOLD) { noise_counter++; continue; - } + } noise_counter = 0; firsthigh = 1; } - + if ( !firstlow ){ if (sample > COTAG_ZERO_THRESHOLD ) { - noise_counter++; + noise_counter++; continue; } - noise_counter = 0; + noise_counter = 0; firstlow = 1; } - - // set sample 255, 0, or previous + + // set sample 255, 0, or previous if ( sample > COTAG_ONE_THRESHOLD){ prev = curr; curr = 1; @@ -438,14 +438,14 @@ uint32_t doCotagAcquisitionManchester() { } else { curr = prev; - } + } - // full T1 periods, + // full T1 periods, if ( period > 0 ) { --period; continue; } - + dest[sample_counter] = curr; ++sample_counter; period = COTAG_T1; diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index 5e7375d3d..a10925da7 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -20,8 +20,8 @@ # define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) #endif #ifndef HARDNESTED_PRE_AUTHENTICATION_LEADTIME -# define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication -#endif +# define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication +#endif // send an incomplete dummy response in order to trigger the card's authentication failure timeout #ifndef CHK_TIMEOUT @@ -29,13 +29,13 @@ ReaderTransmit(&dummy_answer, 1, NULL); \ uint32_t timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT; \ while (GetCountSspClk() < timeout) {}; \ - } + } #endif static uint8_t dummy_answer = 0; //----------------------------------------------------------------------------- -// Select, Authenticate, Read a MIFARE tag. +// Select, Authenticate, Read a MIFARE tag. // read block //----------------------------------------------------------------------------- void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) @@ -45,7 +45,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) uint8_t keyType = arg1; uint64_t ui64Key = 0; ui64Key = bytes_to_num(datain, 6); - + // variables byte_t isOK = 0; byte_t dataoutbuf[16] = {0x00}; @@ -74,7 +74,7 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); break; }; - + if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) { if (MF_DBGLEVEL >= 1) Dbprintf("Read block error"); break; @@ -84,13 +84,13 @@ void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); break; }; - + isOK = 1; break; } - + crypto1_destroy(pcs); - + if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED"); LED_B_ON(); @@ -117,7 +117,7 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){ OnError(0); return; }; - + if(!mifare_ultra_auth(keybytes)){ if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed"); OnError(1); @@ -175,7 +175,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) OnError(1); return; } - } + } if( mifare_ultra_readblock(blockNo, dataout) ) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error"); @@ -195,7 +195,7 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) } //----------------------------------------------------------------------------- -// Select, Authenticate, Read a MIFARE tag. +// Select, Authenticate, Read a MIFARE tag. // read sector (data = 4 x 16 bytes = 64 bytes, or 16 x 16 bytes = 256 bytes) //----------------------------------------------------------------------------- void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) @@ -205,7 +205,7 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) uint8_t keyType = arg1; uint64_t ui64Key = 0; ui64Key = bytes_to_num(datain, 6); - + // variables byte_t isOK = 0; byte_t dataoutbuf[16 * 16]; @@ -219,7 +219,7 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) clear_trace(); set_tracing(true); - + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); @@ -229,13 +229,13 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) isOK = 0; if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); } - - + + if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { isOK = 0; if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); } - + for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { if(mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) { isOK = 0; @@ -243,7 +243,7 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) break; } } - + if(mifare_classic_halt(pcs, cuid)) { if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); } @@ -275,7 +275,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); set_tracing(true); - + // params uint8_t blockNo = arg0; uint16_t blocks = arg1; @@ -315,7 +315,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) if (!mifare_ul_ev1_auth(pwd, pack)){ OnError(1); - return; + return; } } @@ -326,7 +326,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) } len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i); - + if (len) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i); // if no blocks read - error out @@ -361,7 +361,7 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) } //----------------------------------------------------------------------------- -// Select, Authenticate, Write a MIFARE tag. +// Select, Authenticate, Write a MIFARE tag. // read block //----------------------------------------------------------------------------- void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) @@ -374,7 +374,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) ui64Key = bytes_to_num(datain, 6); memcpy(blockdata, datain + 10, 16); - + // variables byte_t isOK = 0; uint8_t uid[10] = {0x00}; @@ -387,7 +387,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) clear_trace(); set_tracing(true); - + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); @@ -402,7 +402,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); break; }; - + if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) { if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); break; @@ -412,13 +412,13 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); break; }; - + isOK = 1; break; } - + crypto1_destroy(pcs); - + if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); cmd_send(CMD_ACK,isOK,0,0,0,0); @@ -428,7 +428,7 @@ void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) set_tracing(false); } -/* // Command not needed but left for future testing +/* // Command not needed but left for future testing void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain) { uint8_t blockNo = arg0; @@ -483,14 +483,14 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) byte_t blockdata[4] = {0x00}; memcpy(blockdata, datain, 4); - + LEDsoff(); LED_A_ON(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); set_tracing(true); - + if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); OnError(0); @@ -499,26 +499,26 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) // UL-C authentication if ( useKey ) { - uint8_t key[16] = {0x00}; + uint8_t key[16] = {0x00}; memcpy(key, datain+4, sizeof(key) ); if ( !mifare_ultra_auth(key) ) { OnError(1); - return; + return; } } - + // UL-EV1 / NTAG authentication - if (usePwd) { + if (usePwd) { uint8_t pwd[4] = {0x00}; memcpy(pwd, datain+4, 4); uint8_t pack[4] = {0,0,0,0}; if (!mifare_ul_ev1_auth(pwd, pack)) { OnError(1); - return; + return; } } - + if (mifare_ultra_writeblock(blockNo, blockdata)) { if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); OnError(0); @@ -540,18 +540,18 @@ void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) } void MifareUSetPwd(uint8_t arg0, uint8_t *datain){ - + uint8_t pwd[16] = {0x00}; byte_t blockdata[4] = {0x00}; - + memcpy(pwd, datain, 16); - + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); set_tracing(true); - + if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); OnError(0); @@ -596,7 +596,7 @@ void MifareUSetPwd(uint8_t arg0, uint8_t *datain){ if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); OnError(47); return; - }; + }; if (mifare_ultra_halt()) { if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); @@ -626,25 +626,25 @@ void MifareAcquireNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t * uint32_t cuid = 0; int16_t isOK = 0; uint16_t num_nonces = 0; - uint8_t cascade_levels = 0; + uint8_t cascade_levels = 0; uint8_t blockNo = arg0 & 0xff; uint8_t keyType = (arg0 >> 8) & 0xff; bool initialize = flags & 0x0001; bool field_off = flags & 0x0004; bool have_uid = false; - + LED_A_ON(); LED_C_OFF(); - BigBuf_free(); BigBuf_Clear_ext(false); + BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); set_tracing(true); - + if (initialize) iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - + LED_C_ON(); - + for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE-4; i += 4 ) { // Test if the action was cancelled @@ -655,7 +655,7 @@ void MifareAcquireNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t * } if (!have_uid) { // need a full select cycle to get the uid first - iso14a_card_select_t card_info; + iso14a_card_select_t card_info; if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); continue; @@ -666,31 +666,31 @@ void MifareAcquireNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t * case 10: cascade_levels = 3; break; default: break; } - have_uid = true; + have_uid = true; } else { // no need for anticollision. We can directly select the card if (!iso14443a_fast_select_card(uid, cascade_levels)) { if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); continue; } } - - // Transmit MIFARE_CLASSIC_AUTH + + // Transmit MIFARE_CLASSIC_AUTH uint8_t dcmd[4] = {0x60 + (keyType & 0x01), blockNo, 0x00, 0x00}; AddCrc14A(dcmd, 2); ReaderTransmit(dcmd, sizeof(dcmd), NULL); - int len = ReaderReceive(answer, par); + int len = ReaderReceive(answer, par); // wait for the card to become ready again CHK_TIMEOUT(); - + if (len != 4) { if (MF_DBGLEVEL >= 2) Dbprintf("AcquireNonces: Auth1 error"); continue; } - + num_nonces++; - - // Save the tag nonce (nt) + + // Save the tag nonce (nt) buf[i] = answer[0]; buf[i+1] = answer[1]; buf[i+2] = answer[2]; @@ -714,7 +714,7 @@ void MifareAcquireNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t * //----------------------------------------------------------------------------- // acquire encrypted nonces in order to perform the attack described in // Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened -// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on +// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on // Computer and Communications Security, 2015 //----------------------------------------------------------------------------- void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain) { @@ -737,7 +737,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t blockNo = arg0 & 0xff; uint8_t keyType = (arg0 >> 8) & 0xff; uint8_t targetBlockNo = arg1 & 0xff; - uint8_t targetKeyType = (arg1 >> 8) & 0xff; + uint8_t targetKeyType = (arg1 >> 8) & 0xff; bool initialize = flags & 0x0001; bool slow = flags & 0x0002; bool field_off = flags & 0x0004; @@ -746,15 +746,15 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, LED_A_ON(); LED_C_OFF(); - BigBuf_free(); BigBuf_Clear_ext(false); + BigBuf_free(); BigBuf_Clear_ext(false); clear_trace(); set_tracing(false); - + if (initialize) iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - + LED_C_ON(); - + for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE - 9; ) { // Test if the action was cancelled @@ -765,7 +765,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, } if (!have_uid) { // need a full select cycle to get the uid first - iso14a_card_select_t card_info; + iso14a_card_select_t card_info; if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); continue; @@ -776,14 +776,14 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, case 10: cascade_levels = 3; break; default: break; } - have_uid = true; + have_uid = true; } else { // no need for anticollision. We can directly select the card if (!iso14443a_fast_select_card(uid, cascade_levels)) { if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); continue; } } - + if (slow) SpinDelayUs(HARDNESTED_PRE_AUTHENTICATION_LEADTIME); @@ -803,7 +803,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len); continue; } - + num_nonces++; if (num_nonces % 2) { memcpy(buf+i, receivedAnswer, 4); @@ -817,7 +817,7 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, } LED_C_OFF(); - crypto1_destroy(pcs); + crypto1_destroy(pcs); LED_B_ON(); cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf)); LED_B_OFF(); @@ -833,8 +833,8 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, //----------------------------------------------------------------------------- -// MIFARE nested authentication. -// +// MIFARE nested authentication. +// //----------------------------------------------------------------------------- void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *datain) { @@ -846,7 +846,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat uint64_t ui64Key = 0; ui64Key = bytes_to_num(datain, 6); - + // variables uint16_t rtr, i, j, len; uint16_t davg = 0; @@ -855,7 +855,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat uint32_t cuid = 0, nt1, nt2, nttmp, nttest, ks1; uint8_t par[1] = {0x00}; uint32_t target_nt[2] = {0x00}, target_ks[2] = {0x00}; - + uint8_t par_array[4] = {0x00}; uint16_t ncount = 0; struct Crypto1State mpcs = {0, 0}; @@ -872,7 +872,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat // free eventually allocated BigBuf memory BigBuf_free(); BigBuf_Clear_ext(false); - + if (calibrate) clear_trace(); set_tracing(true); @@ -887,7 +887,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat davg = dmax = 0; dmin = 2000; delta_time = 0; - + for (rtr = 0; rtr < 17; rtr++) { // Test if the action was cancelled @@ -948,16 +948,16 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat } davg = (davg + (rtr - 1)/2) / (rtr - 1); - + if (MF_DBGLEVEL >= 3) Dbprintf("rtr=%d isOK=%d min=%d max=%d avg=%d, delta_time=%d", rtr, isOK, dmin, dmax, davg, delta_time); dmin = davg - 2; dmax = davg + 2; - + LED_B_OFF(); } -// ------------------------------------------------------------------------------------------------- - +// ------------------------------------------------------------------------------------------------- + LED_C_ON(); // get crypted nonces for target sector @@ -965,7 +965,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat target_nt[i] = 0; while(target_nt[i] == 0) { // continue until we have an unambiguous nonce - + // prepare next select. No need to power down the card. if(mifare_classic_halt(pcs, cuid)) { if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Halt error"); @@ -976,7 +976,7 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Can't select card"); continue; }; - + auth1_time = 0; if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) { if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth1 error"); @@ -991,15 +991,15 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth2 error len=%d", len); continue; }; - - nt2 = bytes_to_num(receivedAnswer, 4); + + nt2 = bytes_to_num(receivedAnswer, 4); if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: Testing nt1=%08x nt2enc=%08x nt2par=%02x", i+1, nt1, nt2, par[0]); - + // Parity validity check for (j = 0; j < 4; j++) { par_array[j] = (oddparity8(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01)); } - + ncount = 0; nttest = prng_successor(nt1, dmin - 1); for (j = dmin; j < dmax + 1; j++) { @@ -1028,16 +1028,16 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat } LED_C_OFF(); - + crypto1_destroy(pcs); - + uint8_t buf[4 + 4 * 4] = {0}; memcpy(buf, &cuid, 4); memcpy(buf+4, &target_nt[0], 4); memcpy(buf+8, &target_ks[0], 4); memcpy(buf+12, &target_nt[1], 4); memcpy(buf+16, &target_ks[1], 4); - + LED_B_ON(); cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf)); LED_B_OFF(); @@ -1050,9 +1050,9 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat } //----------------------------------------------------------------------------- -// MIFARE check keys. key count up to 85. -// -//----------------------------------------------------------------------------- +// MIFARE check keys. key count up to 85. +// +//----------------------------------------------------------------------------- typedef struct sector_t { uint8_t keyA[6]; uint8_t keyB[6]; @@ -1060,23 +1060,23 @@ typedef struct sector_t { typedef struct chk_t { uint64_t key; - uint32_t cuid; + uint32_t cuid; uint8_t cl; uint8_t block; uint8_t keyType; - uint8_t *uid; + uint8_t *uid; struct Crypto1State *pcs; } chk_t; // checks one key. // fast select, tries 5 times to select -// +// // return: // 2 = failed to select. // 1 = wrong key // 0 = correct key uint8_t chkKey( struct chk_t *c ) { - uint8_t i = 0, res = 2; + uint8_t i = 0, res = 2; while( i < 5 ) { // this part is from Piwi's faster nonce collecting part in Hardnested. // assume: fast select @@ -1087,26 +1087,26 @@ uint8_t chkKey( struct chk_t *c ) { res = mifare_classic_authex(c->pcs, c->cuid, c->block, c->keyType, c->key, AUTH_FIRST, NULL, NULL); CHK_TIMEOUT(); - + // if successfull auth, send HALT - // if ( !res ) + // if ( !res ) // mifare_classic_halt_ex(c->pcs); break; } return res; } -uint8_t chkKey_readb(struct chk_t *c, uint8_t *keyb) { - +uint8_t chkKey_readb(struct chk_t *c, uint8_t *keyb) { + if (!iso14443a_fast_select_card(c->uid, c->cl)) return 2; - + if ( mifare_classic_authex(c->pcs, c->cuid, c->block, 0, c->key, AUTH_FIRST, NULL, NULL) ) return 1; - uint8_t data[16] = {0x00}; + uint8_t data[16] = {0x00}; uint8_t res = mifare_classic_readblock(c->pcs, c->cuid, c->block, data); - + // successful read if ( !res ) { // data was something else than zeros. @@ -1121,40 +1121,40 @@ uint8_t chkKey_readb(struct chk_t *c, uint8_t *keyb) { return res; } -void chkKey_scanA(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { - for (uint8_t s = 0; s < *sectorcnt; s++) { +void chkKey_scanA(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { + for (uint8_t s = 0; s < *sectorcnt; s++) { - // skip already found A keys - if ( found[(s*2)] ) + // skip already found A keys + if ( found[(s*2)] ) continue; c->block = FirstBlockOfSector( s ); - if ( chkKey( c ) == 0 ) { + if ( chkKey( c ) == 0 ) { num_to_bytes(c->key, 6, k_sector[s].keyA); - found[(s*2)] = 1; - ++*foundkeys; - + found[(s*2)] = 1; + ++*foundkeys; + if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan A found (%d)", c->block); } - } + } } -void chkKey_scanB(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { - for (uint8_t s = 0; s < *sectorcnt; s++) { +void chkKey_scanB(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { + for (uint8_t s = 0; s < *sectorcnt; s++) { - // skip already found B keys + // skip already found B keys if ( found[(s*2)+1] ) continue; c->block = FirstBlockOfSector( s ); - if ( chkKey( c ) == 0 ) { - num_to_bytes(c->key, 6, k_sector[s].keyB); - found[(s*2)+1] = 1; - ++*foundkeys; - + if ( chkKey( c ) == 0 ) { + num_to_bytes(c->key, 6, k_sector[s].keyB); + found[(s*2)+1] = 1; + ++*foundkeys; + if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan B found (%d)", c->block); } - } + } } // loop all A keys, @@ -1163,21 +1163,21 @@ void chkKey_loopBonly(struct chk_t *c, struct sector_t *k_sector, uint8_t *found // read Block B, if A is found. for (uint8_t s = 0; s < *sectorcnt; ++s) { - + if ( found[(s*2)] && found[(s*2)+1] ) continue; - + c->block = (FirstBlockOfSector( s ) + NumBlocksPerSector( s ) - 1); // A but not B - if ( found[(s*2)] && !found[(s*2)+1] ){ + if ( found[(s*2)] && !found[(s*2)+1] ){ c->key = bytes_to_num(k_sector[s].keyA, 6); uint8_t status = chkKey_readb(c, k_sector[s].keyB); - if ( status == 0 ){ + if ( status == 0 ){ found[(s*2)+1] = 1; ++*foundkeys; - if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Reading B found (%d)", c->block); + if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Reading B found (%d)", c->block); // try quick find all B? // assume: keys comes in groups. Find one B, test against all B. @@ -1199,10 +1199,10 @@ void chkKey_loopBonly(struct chk_t *c, struct sector_t *k_sector, uint8_t *found // datain = keys as array void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { - // first call or + // first call or uint8_t sectorcnt = arg0 & 0xFF; // 16; - uint8_t firstchunk = (arg0 >> 8) & 0xF; - uint8_t lastchunk = (arg0 >> 12) & 0xF; + uint8_t firstchunk = (arg0 >> 8) & 0xF; + uint8_t lastchunk = (arg0 >> 12) & 0xF; uint8_t strategy = arg1 & 0xFF; uint8_t use_flashmem = (arg1 >> 8) & 0xFF; uint16_t keyCount = arg2 & 0xFF; @@ -1212,7 +1212,7 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da struct Crypto1State *pcs; pcs = &mpcs; struct chk_t chk_data; - + uint8_t allkeys = sectorcnt << 1; static uint32_t cuid = 0; @@ -1222,20 +1222,20 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da static uint8_t found[80]; static uint8_t *uid; -#ifdef WITH_FLASH +#ifdef WITH_FLASH if ( use_flashmem ) { BigBuf_free(); uint16_t isok = 0; - uint8_t size[2] = {0x00, 0x00}; + uint8_t size[2] = {0x00, 0x00}; isok = Flash_ReadData(DEFAULT_MF_KEYS_OFFSET, size, 2); if ( isok != 2 ) goto OUT; - + keyCount = size[1] << 8 | size[0]; - - if ( keyCount == 0 && keyCount == 0xFFFF) + + if ( keyCount == 0 && keyCount == 0xFFFF) goto OUT; - + datain = BigBuf_malloc( keyCount * 6); if (datain == NULL ) goto OUT; @@ -1243,10 +1243,10 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da isok = Flash_ReadData(DEFAULT_MF_KEYS_OFFSET+2, datain, keyCount * 6); if ( isok != keyCount * 6 ) goto OUT; - + } #endif - + if (uid == NULL || firstchunk) { uid = BigBuf_malloc(10); if (uid == NULL ) @@ -1254,31 +1254,31 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da } iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - + LEDsoff(); LED_A_ON(); - + if ( firstchunk ) { clear_trace(); set_tracing(false); - + memset(k_sector, 0x00, 480+10); memset(found, 0x00, sizeof(found)); - foundkeys = 0; - - iso14a_card_select_t card_info; + foundkeys = 0; + + iso14a_card_select_t card_info; if ( !iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys_fast: Can't select card (ALL)"); goto OUT; } - + switch (card_info.uidlen) { case 4 : cascade_levels = 1; break; case 7 : cascade_levels = 2; break; case 10: cascade_levels = 3; break; default: break; } - + CHK_TIMEOUT(); } @@ -1287,8 +1287,8 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da chk_data.cuid = cuid; chk_data.cl = cascade_levels; chk_data.pcs = pcs; - chk_data.block = 0; - + chk_data.block = 0; + // keychunk loop - depth first one sector. if ( strategy == 1 || use_flashmem) { @@ -1304,9 +1304,9 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da continue; for (uint16_t i = s_point; i < keyCount; ++i) { - + //if ( i % 100 == 0) Dbprintf("ChkKeys_fast: sector %d | checking %d | %d found | s_point %d", s, i, foundkeys, s_point); - + // Allow button press / usb cmd to interrupt device if (BUTTON_PRESS() && !usb_poll_validate_length()) { goto OUT; @@ -1317,14 +1317,14 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da goto OUT; WDT_HIT(); - + // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector chk_data.block = FirstBlockOfSector( s ); // new key chk_data.key = bytes_to_num(datain + i * 6, 6); - // skip already found A keys + // skip already found A keys if( !found[(s*2)] ) { chk_data.keyType = 0; status = chkKey( &chk_data); @@ -1332,31 +1332,31 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da memcpy(k_sector[s].keyA, datain + i * 6, 6); found[(s*2)] = 1; ++foundkeys; - - chkKey_scanA(&chk_data, k_sector, found, §orcnt, &foundkeys); - + + chkKey_scanA(&chk_data, k_sector, found, §orcnt, &foundkeys); + // read Block B, if A is found. chkKey_loopBonly( &chk_data, k_sector, found, §orcnt, &foundkeys); - + chk_data.keyType = 1; chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); - - chk_data.keyType = 0; + + chk_data.keyType = 0; chk_data.block = FirstBlockOfSector( s ); - + if ( use_flashmem ) { - if ( lastpos != i && lastpos != 0) { + if ( lastpos != i && lastpos != 0) { if ( i - lastpos < 0xF) { s_point = i & 0xFFF0; } } else { - lastpos = i; + lastpos = i; } } } } - - // skip already found B keys + + // skip already found B keys if( !found[(s*2)+1] ) { chk_data.keyType = 1; status = chkKey( &chk_data); @@ -1364,25 +1364,25 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da memcpy(k_sector[s].keyB, datain + i * 6, 6); found[(s*2)+1] = 1; ++foundkeys; - + chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); - if ( use_flashmem ) { + if ( use_flashmem ) { if ( lastpos != i && lastpos != 0) { - + if ( i - lastpos < 0xF) s_point = i & 0xFFF0; } else { - lastpos = i; + lastpos = i; } } } } - + if ( found[(s*2)] && found[(s*2)+1] ) break; - - } // end keys test loop - depth first + + } // end keys test loop - depth first // assume1. if no keys found in first sector, get next keychunk from client if ( !use_flashmem && (newfound-foundkeys == 0) ) @@ -1390,41 +1390,41 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da } // end loop - sector } // end strategy 1 - - if ( foundkeys == allkeys ) + + if ( foundkeys == allkeys ) goto OUT; if ( strategy == 2 || use_flashmem ) { - + // Keychunk loop for (uint16_t i = 0; i < keyCount; i++) { - + // Allow button press / usb cmd to interrupt device if (BUTTON_PRESS() && !usb_poll_validate_length()) break; // found all keys? if ( foundkeys == allkeys ) goto OUT; - + WDT_HIT(); - + // new key chk_data.key = bytes_to_num(datain + i * 6, 6); - + // Sector main loop // keep track of how many sectors on card. for (uint8_t s = 0; s < sectorcnt; ++s) { - + if ( found[(s*2)] && found[(s*2)+1] ) continue; - + // found all keys? if ( foundkeys == allkeys ) goto OUT; // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector chk_data.block = FirstBlockOfSector( s ); - - // skip already found A keys + + // skip already found A keys if( !found[(s*2)] ) { chk_data.keyType = 0; status = chkKey( &chk_data); @@ -1432,17 +1432,17 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da memcpy(k_sector[s].keyA, datain + i * 6, 6); found[(s*2)] = 1; ++foundkeys; - + chkKey_scanA( &chk_data, k_sector, found, §orcnt, &foundkeys); - + // read Block B, if A is found. chkKey_loopBonly( &chk_data, k_sector, found, §orcnt, &foundkeys); chk_data.block = FirstBlockOfSector( s ); } } - - // skip already found B keys + + // skip already found B keys if( !found[(s*2)+1] ) { chk_data.keyType = 1; status = chkKey( &chk_data); @@ -1450,12 +1450,12 @@ void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *da memcpy(k_sector[s].keyB, datain + i * 6, 6); found[(s*2)+1] = 1; ++foundkeys; - + chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); } } - } // end loop sectors - } // end loop keys + } // end loop sectors + } // end loop keys } // end loop strategy 2 OUT: LEDsoff(); @@ -1475,16 +1475,16 @@ OUT: for (uint8_t m=64; m < sizeof(found); m++) { bar |= ((uint16_t)(found[m] & 1) << j++); } - + uint8_t *tmp = BigBuf_malloc(480+10); memcpy(tmp, k_sector, sectorcnt * sizeof(sector_t) ); - num_to_bytes(foo, 8, tmp+480); + num_to_bytes(foo, 8, tmp+480); tmp[488] = bar & 0xFF; tmp[489] = bar >> 8 & 0xFF; - + cmd_send(CMD_ACK, foundkeys, 0, 0, tmp, 480+10); - set_tracing(false); + set_tracing(false); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); BigBuf_free(); BigBuf_Clear_ext(false); } else { @@ -1509,26 +1509,26 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { uint8_t blockNo = arg0 & 0xFF; uint8_t keyType = (arg0 >> 8) & 0xFF; uint8_t keyCount = arg2; - uint8_t cascade_levels = 0; + uint8_t cascade_levels = 0; uint8_t isOK = 0; bool have_uid = false; bool clearTrace = arg1 & 0xFF; - + LEDsoff(); LED_A_ON(); - + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - if (clearTrace) + if (clearTrace) clear_trace(); - + set_tracing(true); - + for (i = 0; i < keyCount; i++) { // Iceman: use piwi's faster nonce collecting part in hardnested. if (!have_uid) { // need a full select cycle to get the uid first - iso14a_card_select_t card_info; + iso14a_card_select_t card_info; if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (ALL)"); --i; // try same key once again @@ -1540,7 +1540,7 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { case 10: cascade_levels = 3; break; default: break; } - have_uid = true; + have_uid = true; } else { // no need for anticollision. We can directly select the card if (!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) { if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (UID)"); @@ -1548,7 +1548,7 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { continue; } } - + key = bytes_to_num(datain + i * 6, 6); res = mifare_classic_auth(pcs, cuid, blockNo, keyType, key, AUTH_FIRST); @@ -1560,20 +1560,20 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { isOK = 1; break; } - + LED_B_ON(); cmd_send(CMD_ACK, isOK, 0, 0, datain + i * 6, 6); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); - + set_tracing(false); crypto1_destroy(pcs); } //----------------------------------------------------------------------------- // MIFARE commands set debug level -// +// //----------------------------------------------------------------------------- void MifareSetDbgLvl(uint16_t arg0){ MF_DBGLEVEL = arg0; @@ -1582,7 +1582,7 @@ void MifareSetDbgLvl(uint16_t arg0){ //----------------------------------------------------------------------------- // Work with emulator memory -// +// // Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not // involved in dealing with emulator memory. But if it is called later, it might // destroy the Emulator Memory. @@ -1611,7 +1611,7 @@ void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) //----------------------------------------------------------------------------- // Load a card into the emulator memory -// +// //----------------------------------------------------------------------------- void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ uint8_t numSectors = arg0; @@ -1631,17 +1631,17 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai LED_B_OFF(); LED_C_OFF(); iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - + clear_trace(); set_tracing(true); - + bool isOK = true; if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { isOK = false; if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); } - + for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) { ui64Key = emlGetKey(sectorNo, keyType); if (sectorNo == 0){ @@ -1657,7 +1657,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai break; } } - + for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { if(isOK && mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) { isOK = false; @@ -1686,7 +1686,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); - + if (MF_DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED"); set_tracing(false); @@ -1695,7 +1695,7 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai //----------------------------------------------------------------------------- // Work with "magic Chinese" card (email him: ouyangweidaxian@live.cn) -// +// // PARAMS - workFlags // bit 0 - need get UID // bit 1 - need wupC @@ -1706,26 +1706,26 @@ void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datai // bit 6 - wipe tag. //----------------------------------------------------------------------------- // magic uid card generation 1 commands -uint8_t wupC1[] = { MIFARE_MAGICWUPC1 }; -uint8_t wupC2[] = { MIFARE_MAGICWUPC2 }; -uint8_t wipeC[] = { MIFARE_MAGICWIPEC }; - +uint8_t wupC1[] = { MIFARE_MAGICWUPC1 }; +uint8_t wupC2[] = { MIFARE_MAGICWUPC2 }; +uint8_t wipeC[] = { MIFARE_MAGICWIPEC }; + void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){ - + // params uint8_t workFlags = arg0; uint8_t blockNo = arg1; // detect 1a/1b bool is1b = false; - + // variables bool isOK = false; //assume we will get an error uint8_t errormsg = 0x00; uint8_t uid[10] = {0x00}; uint8_t data[18] = {0x00}; uint32_t cuid = 0; - + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; @@ -1748,7 +1748,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){ mifare_classic_halt_ex(NULL); break; } - + // wipe tag, fill it with zeros if (workFlags & MAGIC_WIPE){ ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); @@ -1766,7 +1766,7 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){ } mifare_classic_halt_ex(NULL); - } + } // write block if (workFlags & MAGIC_WUPC) { @@ -1792,24 +1792,24 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){ errormsg = 4; break; } - + memcpy(data, datain, 16); AddCrc14A(data, 16); - + ReaderTransmit(data, sizeof(data), NULL); if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("write block send data error"); errormsg = 0; break; - } - - if (workFlags & MAGIC_HALT) + } + + if (workFlags & MAGIC_HALT) mifare_classic_halt_ex(NULL); - + isOK = true; break; - } // end while + } // end while if (isOK ) cmd_send(CMD_ACK,1,0,0,uid,sizeof(uid)); @@ -1821,26 +1821,26 @@ void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){ } void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){ - + uint8_t workFlags = arg0; uint8_t blockNo = arg1; uint8_t errormsg = 0x00; bool isOK = false; //assume we will get an error - + // detect 1a/1b bool is1b = false; - + // variables uint8_t data[MAX_MIFARE_FRAME_SIZE]; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - + memset(data, 0x00, sizeof(data)); - + if (workFlags & MAGIC_INIT) { LED_A_ON(); LED_B_OFF(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); set_tracing(true); } @@ -1861,19 +1861,19 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){ if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Assuming Magic Gen 1B tag. [wupC2 failed]"); is1b = true; continue; - } + } } } - // read block + // read block if ((mifare_sendcmd_short(NULL, 0, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("read block send command error"); errormsg = 0; break; } - + memcpy(data, receivedAnswer, sizeof(data)); - + // send HALT if (workFlags & MAGIC_HALT) mifare_classic_halt_ex(NULL); @@ -1886,12 +1886,12 @@ void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){ if (isOK) memcpy(datain, data, sizeof(data)); } else { - if (isOK) - cmd_send(CMD_ACK,1,0,0,data,sizeof(data)); - else - OnErrorMagic(errormsg); + if (isOK) + cmd_send(CMD_ACK,1,0,0,data,sizeof(data)); + else + OnErrorMagic(errormsg); } - + if (workFlags & MAGIC_OFF) OnSuccessMagic(); } @@ -1906,18 +1906,18 @@ void MifareCIdent(){ uint8_t recpar[1] = {0x00}; iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - + // Generation 1 test ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); if(!ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) { goto TEST2; }; isGen = GEN_1B; - + ReaderTransmit(wupC2, sizeof(wupC2), NULL); if(!ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) { goto OUT; - }; + }; isGen = GEN_1A; goto OUT; @@ -1927,17 +1927,17 @@ TEST2:; // halt previous. mifare_classic_halt(NULL, 0); - + //select if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { goto OUT; }; - + // MIFARE_CLASSIC_WRITEBLOCK 0xA0 // ACK 0x0a uint16_t len = mifare_sendcmd_short(null, 1, 0xA0, 0, rec, recpar, NULL); - if ((len != 1) || (rec[0] != 0x0A)) { - isGen = GEN_2; + if ((len != 1) || (rec[0] != 0x0A)) { + isGen = GEN_2; }; */ OUT:; @@ -1951,7 +1951,7 @@ OUT:; void OnSuccessMagic(){ FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LEDsoff(); - set_tracing(false); + set_tracing(false); } void OnErrorMagic(uint8_t reason){ // ACK, ISOK, reason,0,0,0 @@ -2023,7 +2023,7 @@ void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){ byte_t dataout[12] = {0x00}; uint8_t uid[10] = {0x00}; uint32_t cuid = 0; - + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); clear_trace(); set_tracing(true); @@ -2050,13 +2050,13 @@ void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){ uint8_t key[16] = {0x00}; byte_t dataout[12] = {0x00}; byte_t isOK = 0; - + memcpy(key, datain, 16); - + isOK = mifare_desfire_des_auth2(cuid, key, dataout); - + if( isOK) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed"); OnError(4); return; } diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index 81a29578b..4cafca16c 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -19,7 +19,7 @@ static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4}; bool InitDesfireCard(){ iso14a_card_select_t card; - + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); set_tracing(true); @@ -41,7 +41,7 @@ enum { } CmdOptions ; void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){ - + /* ARG0 contains flags. 0x01 = init card. 0x02 = Disconnect @@ -51,21 +51,21 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){ size_t datalen = arg1; uint8_t resp[RECEIVE_SIZE]; memset(resp,0,sizeof(resp)); - + if (MF_DBGLEVEL >= 4) { Dbprintf(" flags : %02X", flags); Dbprintf(" len : %02X", datalen); print_result(" RX : ", datain, datalen); } - + if ( flags & CLEARTRACE ) clear_trace(); - + if ( flags & INIT ){ if ( !InitDesfireCard() ) return; } - + int len = DesfireAPDU(datain, datalen, resp); if (MF_DBGLEVEL >= 4) print_result("ERR <--: ", resp, len); @@ -74,31 +74,31 @@ void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){ OnError(2); return; } - + // reset the pcb_blocknum, pcb_blocknum = 0; - + if ( flags & DISCONNECT ) OnSuccess(); - + cmd_send(CMD_ACK,1,len,0,resp,len); } void MifareDesfireGetInformation(){ - + int len = 0; iso14a_card_select_t card; uint8_t resp[USB_CMD_DATA_SIZE] = {0x00}; uint8_t dataout[USB_CMD_DATA_SIZE] = {0x00}; - + /* 1 = PCB 1 2 = cid 2 - 3 = desfire command 3 + 3 = desfire command 3 4-5 = crc 4 key - 5-6 crc + 5-6 crc PCB == 0x0A because sending CID byte. - CID == 0x00 first card? + CID == 0x00 first card? */ clear_trace(); set_tracing(true); @@ -110,42 +110,42 @@ void MifareDesfireGetInformation(){ OnError(1); return; } - + if ( card.uidlen != 7 ) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Wrong UID size. Expected 7byte got %d", card.uidlen); OnError(2); - return; + return; } - + memcpy(dataout, card.uid, 7); LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - - uint8_t cmd[] = {GET_VERSION}; + + uint8_t cmd[] = {GET_VERSION}; size_t cmd_len = sizeof(cmd); - + len = DesfireAPDU(cmd, cmd_len, resp); if ( !len ) { - print_result("ERROR <--: ", resp, len); + print_result("ERROR <--: ", resp, len); OnError(3); return; } - + LED_A_OFF(); LED_B_ON(); memcpy(dataout+7,resp+3,7); - + // ADDITION_FRAME 1 cmd[0] = ADDITIONAL_FRAME; len = DesfireAPDU(cmd, cmd_len, resp); if ( !len ) { - print_result("ERROR <--: ", resp, len); + print_result("ERROR <--: ", resp, len); OnError(3); return; - } - + } + LED_B_OFF(); LED_C_ON(); memcpy(dataout+7+7,resp+3,7); @@ -153,15 +153,15 @@ void MifareDesfireGetInformation(){ // ADDITION_FRAME 2 len = DesfireAPDU(cmd, cmd_len, resp); if ( !len ) { - print_result("ERROR <--: ", resp, len); + print_result("ERROR <--: ", resp, len); OnError(3); return; } - + memcpy(dataout+7+7+7,resp+3,14); - + cmd_send(CMD_ACK,1,0,0,dataout,sizeof(dataout)); - + // reset the pcb_blocknum, pcb_blocknum = 0; OnSuccess(); @@ -173,7 +173,7 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain //uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47}; uint8_t PICC_MASTER_KEY16[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f }; uint8_t null_key_data8[8] = {0x00}; - //uint8_t null_key_data16[16] = {0x00}; + //uint8_t null_key_data16[16] = {0x00}; //uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; //uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF}; @@ -181,7 +181,7 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain uint8_t IV[16] = {0x00}; size_t datalen = datain[0]; - + uint8_t cmd[40] = {0x00}; uint8_t encRndB[16] = {0x00}; uint8_t decRndB[16] = {0x00}; @@ -190,22 +190,22 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain uint8_t encBoth[32] = {0x00}; InitDesfireCard(); - + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - + // 3 olika stt att authenticera. AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) // 4 olika crypto algo DES, 3DES, 3K3DES, AES // 3 olika kommunikations stt, PLAIN,MAC,CRYPTO - - // des, nyckel 0, + + // des, nyckel 0, switch (mode){ case 1:{ uint8_t keybytes[16]; uint8_t RndA[8] = {0x00}; uint8_t RndB[8] = {0x00}; - + if (algo == 2) { if (datain[1] == 0xff){ memcpy(keybytes,PICC_MASTER_KEY16,16); @@ -221,15 +221,15 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain } } } - + struct desfire_key defaultkey = {0}; desfirekey_t key = &defaultkey; - + if (algo == 2) Desfire_3des_key_new_with_version(keybytes, key); else if (algo ==1) Desfire_des_key_new(keybytes, key); - + cmd[0] = AUTHENTICATE; cmd[1] = keyno; //keynumber len = DesfireAPDU(cmd, 2, resp); @@ -240,50 +240,50 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain OnError(3); return; } - + if ( resp[2] == 0xaf ){ } else { DbpString("Authentication failed. Invalid key number."); OnError(3); return; } - + memcpy( encRndB, resp+3, 8); if (algo == 2) tdes_dec(&decRndB, &encRndB, key->data); else if (algo == 1) des_dec(&decRndB, &encRndB, key->data); - + memcpy(RndB, decRndB, 8); rol(decRndB,8); - + // This should be random uint8_t decRndA[8] = {0x00}; memcpy(RndA, decRndA, 8); uint8_t encRndA[8] = {0x00}; - + if (algo == 2) tdes_dec(&encRndA, &decRndA, key->data); else if (algo == 1) des_dec(&encRndA, &decRndA, key->data); - + memcpy(both, encRndA, 8); - + for (int x = 0; x < 8; x++) { decRndB[x] = decRndB[x] ^ encRndA[x]; - + } - + if (algo == 2) tdes_dec(&encRndB, &decRndB, key->data); else if (algo == 1) des_dec(&encRndB, &decRndB, key->data); - + memcpy(both + 8, encRndB, 8); - + cmd[0] = ADDITIONAL_FRAME; memcpy(cmd+1, both, 16 ); - + len = DesfireAPDU(cmd, 17, resp); if ( !len ) { if (MF_DBGLEVEL >= MF_DBG_ERROR) { @@ -292,21 +292,21 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain OnError(3); return; } - + if ( resp[2] == 0x00 ){ - + struct desfire_key sessionKey = {0}; desfirekey_t skey = &sessionKey; Desfire_session_key_new( RndA, RndB , key, skey ); //print_result("SESSION : ", skey->data, 8); - + memcpy(encRndA, resp+3, 8); - + if (algo == 2) tdes_dec(&encRndA, &encRndA, key->data); else if (algo == 1) des_dec(&encRndA, &encRndA, key->data); - + rol(decRndA,8); for (int x = 0; x < 8; x++) { if (decRndA[x] != encRndA[x]) { @@ -315,86 +315,86 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain return; } } - + //Change the selected key to a new value. /* - + // Current key is a 3DES key, change it to a DES key if (algo == 2) { cmd[0] = CHANGE_KEY; cmd[1] = keyno; - + uint8_t newKey[16] = {0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; - + uint8_t first, second; uint8_t buff1[8] = {0x00}; uint8_t buff2[8] = {0x00}; uint8_t buff3[8] = {0x00}; - + memcpy(buff1,newKey, 8); memcpy(buff2,newKey + 8, 8); - + compute_crc(CRC_14443_A, newKey, 16, &first, &second); memcpy(buff3, &first, 1); memcpy(buff3 + 1, &second, 1); - + tdes_dec(&buff1, &buff1, skey->data); memcpy(cmd+2,buff1,8); - + for (int x = 0; x < 8; x++) { buff2[x] = buff2[x] ^ buff1[x]; } tdes_dec(&buff2, &buff2, skey->data); memcpy(cmd+10,buff2,8); - + for (int x = 0; x < 8; x++) { buff3[x] = buff3[x] ^ buff2[x]; } tdes_dec(&buff3, &buff3, skey->data); memcpy(cmd+18,buff3,8); - + // The command always times out on the first attempt, this will retry until a response // is recieved. len = 0; while(!len) { len = DesfireAPDU(cmd,26,resp); } - + } else { // Current key is a DES key, change it to a 3DES key if (algo == 1) { cmd[0] = CHANGE_KEY; cmd[1] = keyno; - + uint8_t newKey[16] = {0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f}; - + uint8_t first, second; uint8_t buff1[8] = {0x00}; uint8_t buff2[8] = {0x00}; uint8_t buff3[8] = {0x00}; - + memcpy(buff1,newKey, 8); memcpy(buff2,newKey + 8, 8); - + compute_crc(CRC_14443_A, newKey, 16, &first, &second); memcpy(buff3, &first, 1); memcpy(buff3 + 1, &second, 1); - + des_dec(&buff1, &buff1, skey->data); memcpy(cmd+2,buff1,8); - + for (int x = 0; x < 8; x++) { buff2[x] = buff2[x] ^ buff1[x]; } des_dec(&buff2, &buff2, skey->data); memcpy(cmd+10,buff2,8); - + for (int x = 0; x < 8; x++) { buff3[x] = buff3[x] ^ buff2[x]; } des_dec(&buff3, &buff3, skey->data); memcpy(cmd+18,buff3,8); - + // The command always times out on the first attempt, this will retry until a response // is recieved. len = 0; @@ -404,7 +404,7 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain } } */ - + OnSuccess(); if (algo == 2) cmd_send(CMD_ACK,1,0,0,skey->data,16); @@ -421,19 +421,19 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain //SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp); break; case 3:{ - + //defaultkey uint8_t keybytes[16] = {0x00}; if (datain[1] == 0xff){ - memcpy(keybytes,PICC_MASTER_KEY16,16); + memcpy(keybytes,PICC_MASTER_KEY16,16); } else{ memcpy(keybytes, datain+1, datalen); } - + struct desfire_key defaultkey = {0x00}; desfirekey_t key = &defaultkey; Desfire_aes_key_new( keybytes, key); - + AesCtx ctx; if ( AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0 ){ if( MF_DBGLEVEL >= 4) { @@ -442,7 +442,7 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain OnError(7); return; } - + cmd[0] = AUTHENTICATE_AES; cmd[1] = 0x00; //keynumber len = DesfireAPDU(cmd, 2, resp); @@ -453,19 +453,19 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain OnError(3); return; } - + memcpy( encRndB, resp+3, 16); - + // dekryptera tagnonce. AesDecrypt(&ctx, encRndB, decRndB, 16); rol(decRndB,16); memcpy(both, nonce,16); memcpy(both+16, decRndB ,16 ); AesEncrypt(&ctx, both, encBoth, 32 ); - + cmd[0] = ADDITIONAL_FRAME; memcpy(cmd+1, encBoth, 32 ); - + len = DesfireAPDU(cmd, 33, resp); // 1 + 32 == 33 if ( !len ) { if (MF_DBGLEVEL >= MF_DBG_ERROR) { @@ -474,9 +474,9 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain OnError(3); return; } - + if ( resp[2] == 0x00 ){ - // Create AES Session key + // Create AES Session key struct desfire_key sessionKey = {0}; desfirekey_t skey = &sessionKey; Desfire_session_key_new( nonce, decRndB , key, skey ); @@ -486,11 +486,11 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain OnError(7); return; } - + break; - } + } } - + OnSuccess(); cmd_send(CMD_ACK,1,len,0,resp,len); } @@ -506,11 +506,11 @@ int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){ uint8_t wCmd[USB_CMD_DATA_SIZE] = {0x00}; uint8_t resp[MAX_FRAME_SIZE]; uint8_t par[MAX_PARITY_SIZE]; - + wrappedLen = CreateAPDU( cmd, cmd_len, wCmd); - + if (MF_DBGLEVEL >= 4) - print_result("WCMD <--: ", wCmd, wrappedLen); + print_result("WCMD <--: ", wCmd, wrappedLen); ReaderTransmit( wCmd, wrappedLen, NULL); @@ -526,30 +526,30 @@ int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){ || (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0 && (resp[0] & 0x01) == pcb_blocknum) // equal block numbers { - pcb_blocknum ^= 1; //toggle next block + pcb_blocknum ^= 1; //toggle next block } memcpy(dataout, resp, len); return len; -} +} // CreateAPDU size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout){ - + size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1); uint8_t cmd[cmdlen]; memset(cmd, 0, cmdlen); - + cmd[0] = 0x0A; // 0x0A = skicka cid, 0x02 = ingen cid. Srskilda bitar // - cmd[0] |= pcb_blocknum; // OR the block number into the PCB + cmd[0] |= pcb_blocknum; // OR the block number into the PCB cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards - + memcpy(cmd+2, datain, len); AddCrc14A(cmd, len+2); - + memcpy(dataout, cmd, cmdlen); - + return cmdlen; } @@ -562,7 +562,7 @@ void OnSuccess(){ pcb_blocknum = 0; ReaderTransmit(deselect_cmd, 3 , NULL); mifare_ultra_halt(); - switch_off(); + switch_off(); } void OnError(uint8_t reason){ diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff.c index e832c76cf..43e416086 100644 --- a/armsrc/mifaresniff.c +++ b/armsrc/mifaresniff.c @@ -19,8 +19,8 @@ static uint8_t sniffBuf[17]; static uint32_t timerData = 0; //----------------------------------------------------------------------------- -// MIFARE sniffer. -// +// MIFARE sniffer. +// // if no activity for 2sec, it sends the collected data to the client. //----------------------------------------------------------------------------- // "hf mf sniff" @@ -32,7 +32,7 @@ void RAMFUNC SniffMifare(uint8_t param) { // C(red) A(yellow) B(green) LEDsoff(); iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); - + // Allocate memory from BigBuf for some buffers // free all previous allocations first BigBuf_free(); BigBuf_Clear_ext(false); @@ -40,7 +40,7 @@ void RAMFUNC SniffMifare(uint8_t param) { set_tracing(true); // The command (reader -> tag) that we're receiving. - uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedCmdPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; // The response (tag -> reader) that we're receiving. @@ -60,9 +60,9 @@ void RAMFUNC SniffMifare(uint8_t param) { // a good trigger condition to get started is probably when we see a // response from the tag. // triggered == false -- to wait first for card - //bool triggered = !(param & 0x03); - - + //bool triggered = !(param & 0x03); + + // Set up the demodulator for tag -> reader responses. DemodInit(receivedResp, receivedRespPar); @@ -72,15 +72,15 @@ void RAMFUNC SniffMifare(uint8_t param) { // Setup and start DMA. // set transfer address and number of bytes. Start transfer. if ( !FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE) ){ - if (MF_DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting"); + if (MF_DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting"); return; } tUart* uart = GetUart(); tDemod* demod = GetDemod(); - + MfSniffInit(); - + uint32_t sniffCounter = 0; // loop and listen while (!BUTTON_PRESS()) { @@ -93,7 +93,7 @@ void RAMFUNC SniffMifare(uint8_t param) { if (BigBuf_get_traceLen()) { MfSniffSend(); // Reset everything - we missed some sniffed data anyway while the DMA was stopped - sniffCounter = 0; + sniffCounter = 0; dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); data = dmaBuf; maxDataLen = 0; @@ -103,10 +103,10 @@ void RAMFUNC SniffMifare(uint8_t param) { } } */ - - // number of bytes we have processed so far - int register readBufDataP = data - dmaBuf; - // number of bytes already transferred + + // number of bytes we have processed so far + int register readBufDataP = data - dmaBuf; + // number of bytes already transferred int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; if (readBufDataP <= dmaBufDataP) // we are processing the same block of data which is currently being transferred dataLen = dmaBufDataP - readBufDataP; // number of bytes still to be processed @@ -115,9 +115,9 @@ void RAMFUNC SniffMifare(uint8_t param) { // test for length of buffer if (dataLen > maxDataLen) { // we are more behind than ever... - maxDataLen = dataLen; + maxDataLen = dataLen; if (dataLen > (9 * DMA_BUFFER_SIZE / 10)) { - Dbprintf("[!] blew circular buffer! | datalen %u", dataLen); + Dbprintf("[!] blew circular buffer! | datalen %u", dataLen); break; } } @@ -141,7 +141,7 @@ void RAMFUNC SniffMifare(uint8_t param) { if (sniffCounter & 0x01) { // no need to try decoding tag data if the reader is sending - if (!TagIsActive) { + if (!TagIsActive) { uint8_t readerbyte = (previous_data & 0xF0) | (*data >> 4); if (MillerDecoding(readerbyte, (sniffCounter-1)*4)) { LogTrace(receivedCmd, uart->len, 0, 0, NULL, true); @@ -150,9 +150,9 @@ void RAMFUNC SniffMifare(uint8_t param) { } ReaderIsActive = (uart->state != STATE_UNSYNCD); } - + // no need to try decoding tag data if the reader is sending - if (!ReaderIsActive) { + if (!ReaderIsActive) { uint8_t tagbyte = (previous_data << 4) | (*data & 0x0F); if (ManchesterDecoding(tagbyte, 0, (sniffCounter-1)*4)) { LogTrace(receivedResp, demod->len, 0, 0, NULL, false); @@ -170,9 +170,9 @@ void RAMFUNC SniffMifare(uint8_t param) { data = dmaBuf; } // main cycle - + MfSniffEnd(); - switch_off(); + switch_off(); } void MfSniffInit(void){ @@ -194,15 +194,15 @@ void MfSniffEnd(void){ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader) { // reset on 7-Bit commands from reader - if (reader && (len == 1) && (bitCnt == 7)) { + if (reader && (len == 1) && (bitCnt == 7)) { sniffState = SNF_INIT; } - - + + switch (sniffState) { case SNF_INIT:{ - // REQA,WUPA or MAGICWUP from reader + // REQA,WUPA or MAGICWUP from reader if ((len == 1) && (reader) && (bitCnt == 7) ) { MfSniffInit(); sniffState = (data[0] == MIFARE_MAGICWUPC1) ? SNF_MAGIC_WUPC2 : SNF_ATQA; @@ -210,7 +210,7 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui break; } case SNF_MAGIC_WUPC2: { - if ((len == 1) && (reader) && (data[0] == MIFARE_MAGICWUPC2) ) { + if ((len == 1) && (reader) && (data[0] == MIFARE_MAGICWUPC2) ) { sniffState = SNF_CARD_IDLE; } break; @@ -225,14 +225,14 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui break; } case SNF_UID: { - + if ( !reader ) break; if ( len != 9 ) break; if ( !CheckCrc14443(CRC_14443_A, data, 9)) break; if ( data[1] != 0x70 ) break; - + Dbprintf("[!] UID | %x", data[0]); - + if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT)) { // UID_4 - select 4 Byte UID from reader memcpy(sniffUID, data+2, 4); @@ -248,7 +248,7 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui //new uid bytes memcpy(sniffUID+3, data+2, 4); sniffUIDType = SNF_UID_7; - sniffState = SNF_SAK; + sniffState = SNF_SAK; } else if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3)) { // UID_10 - Select 3nd part of 10 Byte UID // 3+3+4 = 10. @@ -279,7 +279,7 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui } } break; - } + } case SNF_CARD_IDLE:{ // trace the card select sequence sniffBuf[0] = 0xFF; sniffBuf[1] = 0xFF; @@ -291,11 +291,11 @@ bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, ui LogTrace(sniffBuf, sizeof(sniffBuf), 0, 0, NULL, true); sniffState = SNF_CARD_CMD; } // intentionally no break; - case SNF_CARD_CMD:{ - LogTrace(data, len, 0, 0, NULL, reader); + case SNF_CARD_CMD:{ + LogTrace(data, len, 0, 0, NULL, reader); timerData = GetTickCount(); break; - } + } default: sniffState = SNF_INIT; break; @@ -308,12 +308,12 @@ void RAMFUNC MfSniffSend() { uint16_t tracelen = BigBuf_get_traceLen(); uint16_t chunksize = 0; int packlen = tracelen; // total number of bytes to send - uint8_t *data = BigBuf_get_addr(); - + uint8_t *data = BigBuf_get_addr(); + while (packlen > 0) { LED_B_ON(); chunksize = MIN(USB_CMD_DATA_SIZE, packlen); // chunk size 512 - cmd_send(CMD_ACK, 1, tracelen, chunksize, data + tracelen - packlen, chunksize); + cmd_send(CMD_ACK, 1, tracelen, chunksize, data + tracelen - packlen, chunksize); packlen -= chunksize; LED_B_OFF(); } diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index df85f6cbd..86048ae88 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -16,7 +16,7 @@ int MF_DBGLEVEL = MF_DBG_ERROR; void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out){ uint8_t bt = 0; int i; - + if (len != 1) { for (i = 0; i < len; i++) data_out[i] = crypto1_byte(pcs, 0x00, 0) ^ data_in[i]; @@ -38,14 +38,14 @@ void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, u uint8_t bt = 0; int i; par[0] = 0; - + for (i = 0; i < len; i++) { bt = data[i]; data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i]; - if ( ( i & 0x0007 ) == 0) + if ( ( i & 0x0007 ) == 0) par[ i >> 3 ] = 0; par[ i >> 3 ] |= (((filter(pcs->odd) ^ oddparity8(bt)) & 0x01)<<(7-(i&0x0007))); - } + } } uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) { @@ -80,22 +80,22 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t par[1] = {0x00}; // 1 Byte parity is enough here AddCrc14A(dcmd, 2); memcpy(ecmd, dcmd, sizeof(dcmd)); - + if (crypted) { par[0] = 0; for (pos = 0; pos < 4; pos++) { ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos]; par[0] |= (((filter(pcs->odd) ^ oddparity8(dcmd[pos])) & 0x01) << (7-pos)); - } + } ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing); } else { ReaderTransmit(dcmd, sizeof(dcmd), timing); } int len = ReaderReceive(answer, par); - + if (answer_parity) *answer_parity = par[0]; - + if (crypted == CRYPT_ALL) { if (len == 1) { res = 0; @@ -103,7 +103,7 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 1)) << 1; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 2)) << 2; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 3)) << 3; - answer[0] = res; + answer[0] = res; } else { for (pos = 0; pos < len; pos++) answer[pos] = crypto1_byte(pcs, 0x00, 0) ^ answer[pos]; @@ -118,7 +118,7 @@ int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, } int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { - int len; + int len; uint32_t pos, nt, ntpp; // Supplied tag nonce uint8_t par[1] = {0x00}; uint8_t nr[4]; @@ -128,11 +128,11 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN // "random" reader nonce: num_to_bytes( prng_successor( GetTickCount(), 32), 4, nr); - + // Transmit MIFARE_CLASSIC_AUTH len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing); if (len != 4) return 1; - + // Save the tag nonce (nt) nt = bytes_to_num(receivedAnswer, 4); @@ -144,7 +144,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN crypto1_create(pcs, ui64Key); if (isNested == AUTH_NESTED) { - // decrypt nt with help of new key + // decrypt nt with help of new key nt = crypto1_word(pcs, nt ^ uid, 1) ^ nt; } else { // Load (plain) uid^nt into the cipher @@ -154,7 +154,7 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN // some statistic if (!ntptr && (MF_DBGLEVEL >= MF_DBG_EXTENDED)) Dbprintf("auth uid: %08x | nr: %08x | nt: %08x", uid, nr, nt); - + // save Nt if (ntptr) *ntptr = nt; @@ -164,8 +164,8 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN for (pos = 0; pos < 4; pos++) { mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos]; par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7-pos)); - } - + } + // Skip 32 bits in pseudo random generator nt = prng_successor(nt, 32); @@ -174,8 +174,8 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN nt = prng_successor(nt,8); mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff); par[0] |= (((filter(pcs->odd) ^ oddparity8(nt & 0xff)) & 0x01) << (7-pos)); - } - + } + // Transmit reader nonce and reader answer ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); @@ -197,28 +197,28 @@ int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockN int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) { - int len; - uint8_t bt[2] = {0x00, 0x00}; + int len; + uint8_t bt[2] = {0x00, 0x00}; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - + len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); if (len == 1) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); return 1; } if (len != 18) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: wrong response len: %x (expected 18)", len); + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: wrong response len: %x (expected 18)", len); return 2; } memcpy(bt, receivedAnswer + 16, 2); AddCrc14A(receivedAnswer, 16); if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { - if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Cmd CRC response error."); + if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Cmd CRC response error."); return 3; } - + memcpy(blockData, receivedAnswer, 16); return 0; } @@ -234,7 +234,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(MIFARE_ULEV1_AUTH, key, sizeof(key), resp, respPar, NULL); if (len != 4) { @@ -307,7 +307,7 @@ int mifare_ultra_auth(uint8_t *keybytes){ uint8_t resp_random_a[8] = { 0,0,0,0,0,0,0,0 }; memcpy(enc_resp, resp+1, 8); - // decrypt out, in, length, key, iv + // decrypt out, in, length, key, iv tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b); if ( memcmp(resp_random_a, random_a, 8) != 0 ) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("failed authentication"); @@ -315,7 +315,7 @@ int mifare_ultra_auth(uint8_t *keybytes){ } if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", + Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3], rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); @@ -339,7 +339,7 @@ int mifare_ultra_readblockEx(uint8_t blockNo, uint8_t *blockData) { uint8_t bt[2] = {0x00, 0x00}; uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; - + len = mifare_sendcmd_short(NULL, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); if (len == 1) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); @@ -349,14 +349,14 @@ int mifare_ultra_readblockEx(uint8_t blockNo, uint8_t *blockData) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: card timeout. len: %x", len); return 2; } - + memcpy(bt, receivedAnswer + 16, 2); AddCrc14A(receivedAnswer, 16); if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd CRC response error."); return 3; } - + memcpy(blockData, receivedAnswer, 14); return 0; } @@ -366,7 +366,7 @@ int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) { for (uint8_t retries = 0; retries < MFU_MAX_RETRIES; ++retries) { res = mifare_ultra_readblockEx(blockNo, blockData); - + // break if OK, or NACK. switch ( res ) { case 0: @@ -381,36 +381,36 @@ int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) { int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) { // variables - uint16_t len = 0; + uint16_t len = 0; uint32_t pos = 0; uint8_t par[3] = {0x00, 0x00, 0x00}; // enough for 18 Bytes to send byte_t res = 0; - + uint8_t d_block[18], d_block_enc[18]; uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - + // command MIFARE_CLASSIC_WRITEBLOCK len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); return 1; } - + memcpy(d_block, blockData, 16); AddCrc14A(d_block, 16); - + // crypto for (pos = 0; pos < 18; pos++) { d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos]; par[pos>>3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos&0x0007))); - } + } ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL); // Receive the response - len = ReaderReceive(receivedAnswer, receivedAnswerPar); + len = ReaderReceive(receivedAnswer, receivedAnswerPar); res = 0; res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0; @@ -419,7 +419,7 @@ int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t bl res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3; if ((len != 1) || (res != 0x0A)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd send data2 Error: %02x", res); + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd send data2 Error: %02x", res); return 2; } return 0; @@ -511,7 +511,7 @@ uint8_t FirstBlockOfSector(uint8_t sectorNo) { return sectorNo * 4; else return 32*4 + (sectorNo - 32) * 16; - + } // work with emulator memory @@ -544,7 +544,7 @@ int emlCheckValBl(int blockNum) { (data[3] != (data[7] ^ 0xff)) || (data[3] != data[11]) || (data[12] != (data[13] ^ 0xff)) || (data[12] != data[14]) || (data[12] != (data[15] ^ 0xff)) - ) + ) return 1; return 0; } @@ -552,10 +552,10 @@ int emlCheckValBl(int blockNum) { int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) { uint8_t* emCARD = BigBuf_get_EM_addr(); uint8_t* data = emCARD + blockNum * 16; - + if (emlCheckValBl(blockNum)) return 1; - + memcpy(blReg, data, 4); *blBlock = data[12]; return 0; @@ -564,17 +564,17 @@ int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) { int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) { uint8_t* emCARD = BigBuf_get_EM_addr(); uint8_t* data = emCARD + blockNum * 16; - + memcpy(data + 0, &blReg, 4); memcpy(data + 8, &blReg, 4); blReg = blReg ^ 0xffffffff; memcpy(data + 4, &blReg, 4); - + data[12] = blBlock; data[13] = blBlock ^ 0xff; data[14] = blBlock; data[15] = blBlock ^ 0xff; - + return 0; } @@ -590,7 +590,7 @@ void emlClearMem(void) { const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04}; uint8_t* emCARD = BigBuf_get_EM_addr(); memset(emCARD, 0, CARD_MEMORY_SIZE); - + // fill sectors trailer data for(uint16_t b = 3; b < 256; ((b < 127) ? (b += 4) : (b += 16))) emlSetMem((uint8_t *)trailer, b, 1); @@ -605,7 +605,7 @@ void emlClearMem(void) { int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing) { uint8_t dcmd[5] = {cmd, data[0], data[1], 0x00, 0x00}; AddCrc14A(dcmd, 3); - + ReaderTransmit(dcmd, sizeof(dcmd), NULL); int len = ReaderReceive(answer, answer_parity); if(!len) { @@ -637,14 +637,14 @@ int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){ uint8_t data[2]={MFDES_AUTHENTICATE, 0x00}; uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; - + len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer,receivedAnswerPar,NULL); if (len == 1) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); return 1; } - + if (len == 12) { if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", @@ -663,18 +663,18 @@ int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){ int len; uint8_t data[17] = {MFDES_AUTHENTICATION_FRAME}; memcpy(data+1,key,16); - + uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; - + len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar ,NULL); - + if ((receivedAnswer[0] == 0x03) && (receivedAnswer[1] == 0xae)) { if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Auth Error: %02x %02x", receivedAnswer[0], receivedAnswer[1]); return 1; } - + if (len == 12){ if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 2406f9068..594b7ca80 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -27,7 +27,7 @@ #define CRYPT_NONE 0 #define CRYPT_ALL 1 #define CRYPT_REQUEST 2 -#define AUTH_FIRST 0 +#define AUTH_FIRST 0 #define AUTH_NESTED 2 #define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) @@ -65,7 +65,7 @@ int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested); int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t * ntptr, uint32_t *timing); int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); -int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); +int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid); int mifare_classic_halt_ex(struct Crypto1State *pcs); int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData); diff --git a/armsrc/optimized_cipher.c b/armsrc/optimized_cipher.c index 223d73fea..98ab88041 100644 --- a/armsrc/optimized_cipher.c +++ b/armsrc/optimized_cipher.c @@ -1,13 +1,13 @@ /***************************************************************************** * WARNING * - * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. - * - * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL - * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, - * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. - * - * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. + * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. + * + * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL + * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, + * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. + * + * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. * ***************************************************************************** * @@ -22,7 +22,7 @@ * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, or, at your option, any later version. + * by the Free Software Foundation, or, at your option, any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,9 +31,9 @@ * * You should have received a copy of the GNU General Public License * along with loclass. If not, see . - * - * - * + * + * + * ****************************************************************************/ /** @@ -138,7 +138,7 @@ void opt_suc(const uint8_t* k,State* s, uint8_t *in, uint8_t length, bool add32Z head = 1 & in[i]; opt_successor(k, &x2, head, s); } - + //For tag MAC, an additional 32 zeroes if (add32Zeroes) { for (i = 0; i < 16; i++) { diff --git a/armsrc/pcf7931.c b/armsrc/pcf7931.c index c9a76bb3b..4c8259ea5 100644 --- a/armsrc/pcf7931.c +++ b/armsrc/pcf7931.c @@ -7,11 +7,11 @@ size_t DemodPCF7931(uint8_t **outBlocks) { uint8_t bits[256] = {0x00}; uint8_t blocks[8][16]; uint8_t *dest = BigBuf_get_addr(); - + int GraphTraceLen = BigBuf_max_traceLen(); if ( GraphTraceLen > 18000 ) GraphTraceLen = 18000; - + int i, j, lastval, bitidx, half_switch; int clock = 64; int tolerance = clock / 8; @@ -155,38 +155,38 @@ bool IsBlock1PCF7931(uint8_t *block) { void ReadPCF7931() { int found_blocks = 0; // successfully read blocks - int max_blocks = 8; // readable blocks + int max_blocks = 8; // readable blocks uint8_t memory_blocks[8][17]; // PCF content - + uint8_t single_blocks[8][17]; // PFC blocks with unknown position int single_blocks_cnt = 0; - size_t n = 0; // transmitted blocks + size_t n = 0; // transmitted blocks uint8_t tmp_blocks[4][16]; // temporary read buffer - + uint8_t found_0_1 = 0; // flag: blocks 0 and 1 were found int errors = 0; // error counter int tries = 0; // tries counter - + memset(memory_blocks, 0, 8*17*sizeof(uint8_t)); memset(single_blocks, 0, 8*17*sizeof(uint8_t)); - + int i = 0, j = 0; do { i = 0; - + memset(tmp_blocks, 0, 4*16*sizeof(uint8_t)); n = DemodPCF7931((uint8_t**)tmp_blocks); if(!n) ++errors; - - // exit if no block is received + + // exit if no block is received if (errors >= 10 && found_blocks == 0 && single_blocks_cnt == 0) { Dbprintf("Error, no tag or bad tag"); return; } - // exit if too many errors during reading + // exit if too many errors during reading if (tries > 50 && (2*errors > tries)) { Dbprintf("Error reading the tag"); Dbprintf("Here is the partial content"); @@ -214,11 +214,11 @@ void ReadPCF7931() { ++tries; continue; } - + Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (max_blocks == 0 ? found_blocks : max_blocks), tries, errors); i = 0; - if(!found_0_1) { + if(!found_0_1) { while (i < n - 1) { if (IsBlock0PCF7931(tmp_blocks[i]) && IsBlock1PCF7931(tmp_blocks[i+1])) { found_0_1 = 1; @@ -228,9 +228,9 @@ void ReadPCF7931() { // block 1 tells how many blocks are going to be sent max_blocks = MAX((memory_blocks[1][14] & 0x7f), memory_blocks[1][15]) + 1; found_blocks = 2; - + Dbprintf("Found blocks 0 and 1. PCF is transmitting %d blocks.", max_blocks); - + // handle the following blocks for (j = i + 2; j < n; ++j) { memcpy(memory_blocks[found_blocks], tmp_blocks[j], 16); @@ -298,7 +298,7 @@ void ReadPCF7931() { Dbprintf("-----------------------------------------"); for (i = 0; i < single_blocks_cnt; ++i) print_result("Block", single_blocks[i], 16); - + Dbprintf("-----------------------------------------"); } cmd_send(CMD_ACK,0,0,0,0,0); @@ -354,7 +354,7 @@ static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int3 if (data&(1<PWMC_ENA = PWM_CHANNEL(0); - + // 48 MHz / 1024 gives 46.875 kHz AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); // Channel Mode Register AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; // Channel Duty Cycle Register @@ -63,7 +63,7 @@ uint32_t RAMFUNC GetTickCount(void){ } // ------------------------------------------------------------------------- -// microseconds timer +// microseconds timer // ------------------------------------------------------------------------- void StartCountUS(void) { AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); @@ -72,19 +72,19 @@ void StartCountUS(void) { // fast clock // tick=1.5mks AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32 + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32 AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR | AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET; AT91C_BASE_TC0->TC_RA = 1; AT91C_BASE_TC0->TC_RC = 0xBFFF + 1; // 0xC000 - - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable + + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // from timer 0 - + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TCB->TCB_BCR = 1; - + while (AT91C_BASE_TC1->TC_CV > 0); } @@ -95,7 +95,7 @@ uint32_t RAMFUNC GetCountUS(void){ } // ------------------------------------------------------------------------- -// Timer for iso14443 commands. Uses ssp_clk from FPGA +// Timer for iso14443 commands. Uses ssp_clk from FPGA // ------------------------------------------------------------------------- void StartCountSspClk(void) { AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1) | (1 << AT91C_ID_TC2); // Enable Clock to all timers @@ -127,7 +127,7 @@ void StartCountSspClk(void) { AT91C_BASE_TC0->TC_RC = 0; // RC Compare value = 0; increment TC2 on overflow // use TC2 to count TIOA0 pulses (giving us a 32bit counter (TC0/TC2) clocked by ssp_clk) - AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS; // disable TC2 + AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS; // disable TC2 AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_XC2 // TC2 clock = XC2 clock = TIOA0 | AT91C_TC_WAVE // Waveform Mode | AT91C_TC_WAVESEL_UP; // just count @@ -136,8 +136,8 @@ void StartCountSspClk(void) { AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC1 AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC2 - // synchronize the counter with the ssp_frame signal. - // Note: FPGA must be in any iso14443 mode, otherwise the frame signal would not be present + // synchronize the counter with the ssp_frame signal. + // Note: FPGA must be in any iso14443 mode, otherwise the frame signal would not be present while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME)); // wait for ssp_frame to go high (start of frame) while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME); // wait for ssp_frame to be low while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high @@ -150,16 +150,16 @@ void StartCountSspClk(void) { // whenever the last three bits of our counter go 0, we can be sure to be in the middle of a frame transfer. // (just started with the transfer of the 4th Bit). - // The high word of the counter (TC2) will not reset until the low word (TC0) overflows. + // The high word of the counter (TC2) will not reset until the low word (TC0) overflows. // Therefore need to wait quite some time before we can use the counter. while (AT91C_BASE_TC2->TC_CV > 0); } -void ResetSspClk(void) { +void ResetSspClk(void) { //enable clock of timer and software trigger AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - while (AT91C_BASE_TC2->TC_CV > 0); + while (AT91C_BASE_TC2->TC_CV > 0); } uint32_t RAMFUNC GetCountSspClk(void) { uint32_t tmp_count = (AT91C_BASE_TC2->TC_CV << 16) | AT91C_BASE_TC0->TC_CV; @@ -186,7 +186,7 @@ void StartTicks(void){ AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // re-enable timer and wait for TC0 // second configure TC0 (lower, 0x0000FFFF) 16 bit counter - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32 + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32 AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR | // RA comperator clears TIOA (carry bit) AT91C_TC_ACPC_SET | // RC comperator sets TIOA (carry bit) @@ -224,7 +224,7 @@ void WaitTicks(uint32_t ticks){ while (GetTicks() < ticks); } -// Wait / Spindelay in us (microseconds) +// Wait / Spindelay in us (microseconds) // 1us = 1.5ticks. void WaitUS(uint16_t us){ WaitTicks( (uint32_t)us * 3/2 ); @@ -236,5 +236,5 @@ void WaitMS(uint16_t ms){ // stop clock void StopTicks(void){ AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; } diff --git a/armsrc/util.c b/armsrc/util.c index 77ef3a494..04cf1fc33 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -15,7 +15,7 @@ size_t nbytes(size_t nbits) { /* ref http://www.csm.ornl.gov/~dunigan/crc.html - Returns the value v with the bottom b [0,32] bits reflected. + Returns the value v with the bottom b [0,32] bits reflected. Example: reflect(0x3e23L,3) == 0x3e26 */ uint32_t reflect(uint32_t v, int b) { @@ -35,7 +35,7 @@ uint8_t reflect8(uint8_t b) { } uint16_t reflect16(uint16_t b) { uint16_t v = 0; - v |= (b & 0x8000) >> 15; + v |= (b & 0x8000) >> 15; v |= (b & 0x4000) >> 13; v |= (b & 0x2000) >> 11; v |= (b & 0x1000) >> 9; @@ -165,7 +165,7 @@ void SpinOff(uint32_t pause) { // 0=A, 1=B, 2=C, 3=D void SpinErr(uint8_t led, uint32_t speed, uint8_t times) { SpinOff(speed); - NTIME(times) + NTIME(times) { switch (led) { case 0: diff --git a/bootrom/bootrom.c b/bootrom/bootrom.c index d2a18628a..c037da122 100644 --- a/bootrom/bootrom.c +++ b/bootrom/bootrom.c @@ -19,7 +19,7 @@ void DbpString(char *str) { byte_t len = 0; while (str[len] != 0x00) len++; - + cmd_send(CMD_DEBUG_PRINT_STRING, len, 0, 0, (byte_t*)str, len); } @@ -90,9 +90,9 @@ void UsbPacketReceived(uint8_t *packet, int len) { volatile uint32_t *p; //if ( len != sizeof(UsbCommand)) Fatal(); - + uint32_t arg0 = (uint32_t)c->arg[0]; - + switch(c->cmd) { case CMD_DEVICE_INFO: { dont_ack = 1; @@ -100,10 +100,10 @@ void UsbPacketReceived(uint8_t *packet, int len) { DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH; if(common_area.flags.osimage_present) arg0 |= DEVICE_INFO_FLAG_OSIMAGE_PRESENT; - + cmd_send(CMD_DEVICE_INFO,arg0,1,2,0,0); } break; - + case CMD_SETUP_WRITE: { /* The temporary write buffer of the embedded flash controller is mapped to the * whole memory region, only the last 8 bits are decoded. @@ -112,16 +112,16 @@ void UsbPacketReceived(uint8_t *packet, int len) { for(i = 0; i < 12; i++) p[i+arg0] = c->d.asDwords[i]; } break; - + case CMD_FINISH_WRITE: { uint32_t* flash_mem = (uint32_t*)(&_flash_start); for ( int j=0; j<2; j++) { for(i = 0+(64*j); i < 64+(64*j); i++) { flash_mem[i] = c->d.asDwords[i]; } - + uint32_t flash_address = arg0 + (0x100*j); - + /* Check that the address that we are supposed to write to is within our allowed region */ if( ((flash_address + AT91C_IFLASH_PAGE_SIZE - 1) >= end_addr) || (flash_address < start_addr) ) { /* Disallow write */ @@ -134,7 +134,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { MC_FLASH_COMMAND_PAGEN(page_n) | AT91C_MC_FCMD_START_PROG; } - + // Wait until flashing of page finishes uint32_t sr; while(!((sr = AT91C_BASE_EFC0->EFC_FSR) & AT91C_MC_FRDY)); @@ -144,18 +144,18 @@ void UsbPacketReceived(uint8_t *packet, int len) { } } } break; - + case CMD_HARDWARE_RESET: { usb_disable(); AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; } break; - + case CMD_START_FLASH: { - if (c->arg[2] == START_FLASH_MAGIC) + if (c->arg[2] == START_FLASH_MAGIC) bootrom_unlocked = 1; - else + else bootrom_unlocked = 0; - + int prot_start = (int)&_bootrom_start; int prot_end = (int)&_bootrom_end; int allow_start = (int)&_flash_start; @@ -167,7 +167,7 @@ void UsbPacketReceived(uint8_t *packet, int len) { * bootrom area. In any case they must be within the flash area. */ if( (bootrom_unlocked || ((cmd_start >= prot_end) || (cmd_end < prot_start))) && - (cmd_start >= allow_start) && + (cmd_start >= allow_start) && (cmd_end <= allow_end) ) { start_addr = cmd_start; end_addr = cmd_end; @@ -177,12 +177,12 @@ void UsbPacketReceived(uint8_t *packet, int len) { cmd_send(CMD_NACK,0,0,0,0,0); } } break; - + default: { Fatal(); } break; } - + if (!dont_ack) cmd_send(CMD_ACK,arg0,0,0,0,0); } @@ -194,19 +194,19 @@ static void flash_mode(int externally_entered) { uint8_t rx[sizeof(UsbCommand)]; usb_enable(); - + // wait for reset to be complete? for (volatile size_t i=0; i<0x100000; i++) {}; for(;;) { WDT_HIT(); - + // Check if there is a usb packet available if (usb_poll_validate_length()) { if (usb_read(rx, sizeof(rx)) ) UsbPacketReceived(rx, sizeof(rx)); } - + if (!externally_entered && !BUTTON_PRESS()) { /* Perform a reset to leave flash mode */ usb_disable(); @@ -274,7 +274,7 @@ void BootROM(void) { AT91C_BASE_EFC0->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48); // 9 = 256, 10+ is 512kb - uint8_t id = ( *(AT91C_DBGU_CIDR) & 0xF00) >> 8; + uint8_t id = ( *(AT91C_DBGU_CIDR) & 0xF00) >> 8; if ( id > 9 ) AT91C_BASE_EFC1->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48); @@ -298,11 +298,11 @@ void BootROM(void) { if (!common_area_present){ /* Common area not ok, initialize it */ - int i; + int i; /* Makeshift memset, no need to drag util.c into this */ - for(i=0; idata, plain, &dataKeys); // Generate tag HMAC - mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey), + mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey), plain + 0x1D4, 0x34, cipher + HMAC_POS_TAG ); // Init mbedtls HMAC context @@ -157,11 +157,11 @@ void nfc3d_amiibo_copy_app_data(const uint8_t * src, uint8_t * dst) { //uint16_t *ami_nb_wr = (uint16_t*)(dst + 0x29); //uint16_t *cfg_nb_wr = (uint16_t*)(dst + 0xB4); - + /* increment write counters */ //*ami_nb_wr = htobe16(be16toh(*ami_nb_wr) + 1); //*cfg_nb_wr = htobe16(be16toh(*cfg_nb_wr) + 1); - + uint16_t ami_nb_wr = ((uint16_t)bytes_to_num(dst + 0x29, 2)) + 1; uint16_t cfg_nb_wr = ((uint16_t)bytes_to_num(dst + 0xB4, 2)) + 1; diff --git a/client/amiitool/amiitool.c b/client/amiitool/amiitool.c index 40e7b05eb..163e6529c 100644 --- a/client/amiitool/amiitool.c +++ b/client/amiitool/amiitool.c @@ -33,7 +33,7 @@ void amiitool_usage() { } static bool LoadAmiikey(nfc3d_amiibo_keys keys, char* keyfile) { - + if (!nfc3d_amiibo_load_keys(&keys, keyfile)) { PrintAndLogEx(ERR, "Could not load keys from '%s'", keyfile); return false; @@ -84,7 +84,7 @@ int main(int argc, char ** argv) { nfc3d_amiibo_keys amiiboKeys; - + uint8_t original[NTAG215_SIZE]; uint8_t modified[NFC3D_AMIIBO_SIZE]; diff --git a/client/cliparser/argtable3.c b/client/cliparser/argtable3.c index abffa9dc2..7e3461b37 100644 --- a/client/cliparser/argtable3.c +++ b/client/cliparser/argtable3.c @@ -114,7 +114,7 @@ enum #define ARG_LOG(x) \ do { if (ARG_ENABLE_LOG) dbg_printf x; } while (0) -#endif +#endif extern void dbg_printf(const char *fmt, ...); @@ -1465,7 +1465,7 @@ static int arg_dbl_scanfn(struct arg_dbl *parent, const char *argval) static int arg_dbl_checkfn(struct arg_dbl *parent) { int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; - + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); return errorcode; } @@ -1575,7 +1575,7 @@ struct arg_dbl * arg_dbln( result->count = 0; } - + ARG_TRACE(("arg_dbln() returns %p\n", result)); return result; } @@ -1655,7 +1655,7 @@ static void arg_end_errorfn( fprintf(fp, "invalid option \"-%c\"", error); break; } - + fputc('\n', fp); } @@ -1851,7 +1851,7 @@ static int arg_file_scanfn(struct arg_file *parent, const char *argval) static int arg_file_checkfn(struct arg_file *parent) { int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; - + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); return errorcode; } @@ -1962,7 +1962,7 @@ struct arg_file * arg_filen( result->extension[i] = ""; } } - + ARG_TRACE(("arg_filen() returns %p\n", result)); return result; } @@ -2325,7 +2325,7 @@ struct arg_int * arg_intn( result->ival = (int *)(result + 1); result->count = 0; } - + ARG_TRACE(("arg_intn() returns %p\n", result)); return result; } @@ -2473,7 +2473,7 @@ struct arg_lit * arg_litn( /* init local variables */ result->count = 0; } - + ARG_TRACE(("arg_litn() returns %p\n", result)); return result; } @@ -3609,7 +3609,7 @@ static int arg_str_scanfn(struct arg_str *parent, const char *argval) static int arg_str_checkfn(struct arg_str *parent) { int errorcode = (parent->count < parent->hdr.mincount) ? EMINCOUNT : 0; - + ARG_TRACE(("%s:checkfn(%p) returns %d\n", __FILE__, parent, errorcode)); return errorcode; } @@ -3711,7 +3711,7 @@ struct arg_str * arg_strn( for (i = 0; i < maxcount; i++) result->sval[i] = ""; } - + ARG_TRACE(("arg_strn() returns %p\n", result)); return result; } @@ -4252,7 +4252,7 @@ int arg_parse(int argc, char * *argv, void * *argtable) argvcopy[i] = argv[i]; argvcopy[argc] = NULL; - + /* parse the command line (local copy) for tagged options */ arg_parse_tagged(argc, argvcopy, table, endtable); diff --git a/client/cliparser/argtable3.h b/client/cliparser/argtable3.h index 1107de250..452d0283a 100644 --- a/client/cliparser/argtable3.h +++ b/client/cliparser/argtable3.h @@ -39,7 +39,7 @@ extern "C" { #endif #define ARG_REX_ICASE 1 - + /* bit masks for arg_hdr.flag */ enum { @@ -218,7 +218,7 @@ struct arg_str* arg_str0(const char* shortopts, const char* datatype, const char* glossary); struct arg_str* arg_str1(const char* shortopts, - const char* longopts, + const char* longopts, const char* datatype, const char *glossary); struct arg_str* arg_strn(const char* shortopts, diff --git a/client/cliparser/cliparser.c b/client/cliparser/cliparser.c index 954220398..f1f2e3b1e 100644 --- a/client/cliparser/cliparser.c +++ b/client/cliparser/cliparser.c @@ -26,16 +26,16 @@ int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp) { programHint = vprogramHint; programHelp = vprogramHelp; memset(buf, 0x00, 500); - + return 0; } -int CLIParserParseArg(int argc, char **argv, void* vargtable[], size_t vargtableLen, bool allowEmptyExec) { +int CLIParserParseArg(int argc, char **argv, void* vargtable[], size_t vargtableLen, bool allowEmptyExec) { int nerrors; - + argtable = vargtable; argtableLen = vargtableLen; - + /* verify the argtable[] entries were allocated sucessfully */ if (arg_nullcheck(argtable) != 0) { /* NULL entries were detected, some allocations must have failed */ @@ -44,9 +44,9 @@ int CLIParserParseArg(int argc, char **argv, void* vargtable[], size_t vargtable } /* Parse the command line as defined by argtable[] */ nerrors = arg_parse(argc, argv, argtable); - + /* special case: '--help' takes precedence over error reporting */ - if ((argc < 2 && !allowEmptyExec) ||((struct arg_lit *)argtable[0])->count > 0) { // help must be the first record + if ((argc < 2 && !allowEmptyExec) ||((struct arg_lit *)argtable[0])->count > 0) { // help must be the first record printf("Usage: %s", programName); arg_print_syntaxv(stdout, argtable, "\n"); if (programHint) @@ -55,7 +55,7 @@ int CLIParserParseArg(int argc, char **argv, void* vargtable[], size_t vargtable printf("\n"); if (programHelp) printf("%s \n", programHelp); - + return 1; } @@ -64,10 +64,10 @@ int CLIParserParseArg(int argc, char **argv, void* vargtable[], size_t vargtable /* Display the error details contained in the arg_end struct.*/ arg_print_errors(stdout, ((struct arg_end *)argtable[vargtableLen - 1]), programName); printf("Try '%s --help' for more information.\n", programName); - + return 3; - } - + } + return 0; } @@ -86,19 +86,19 @@ int CLIParserParseString(const char* str, void* vargtable[], size_t vargtableLen int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData) { int argc = 0; char *argv[200] = {NULL}; - + int len = strlen(str); char *bufptr = buf; char *spaceptr = NULL; enum ParserState state = PS_FIRST; - - argv[argc++] = bufptr; + + argv[argc++] = bufptr; // param0 = program name memcpy(buf, programName, strlen(programName) + 1); // with 0x00 bufptr += strlen(programName) + 1; if (len) - argv[argc++] = bufptr; - + argv[argc++] = bufptr; + // parse params for (int i = 0; i < len; i++) { switch(state){ @@ -110,7 +110,7 @@ int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableL bufptr = spaceptr; *bufptr = 0x00; bufptr++; - argv[argc++] = bufptr; + argv[argc++] = bufptr; } } spaceptr = NULL; @@ -130,10 +130,10 @@ int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableL *bufptr = 0x00; bufptr++; - argv[argc++] = bufptr; + argv[argc++] = bufptr; break; } - + *bufptr = str[i]; bufptr++; break; @@ -146,20 +146,20 @@ int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableL void CLIParserFree() { arg_freetable(argtable, argtableLen); argtable = NULL; - + return; } // convertors int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) { *datalen = 0; - + int ibuf = 0; uint8_t buf[256] = {0}; int res = CLIParamStrToBuf(argstr, buf, maxdatalen * 2, &ibuf); // *2 because here HEX if (res || !ibuf) return res; - + switch(param_gethex_to_eol((char *)buf, 0, data, maxdatalen, datalen)) { case 1: printf("Parameter error: Invalid HEX value.\n"); @@ -171,7 +171,7 @@ int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int printf("Parameter error: Hex string must have even number of digits.\n"); return 3; } - + return 0; } @@ -179,26 +179,26 @@ int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen = 0; if (!argstr->count) return 0; - + uint8_t buf[256] = {0}; int ibuf = 0; - + for (int i = 0; i < argstr->count; i++) { int len = strlen(argstr->sval[i]); memcpy(&buf[ibuf], argstr->sval[i], len); ibuf += len; } buf[ibuf] = 0; - + if (!ibuf) return 0; if (ibuf > maxdatalen) return 2; - + memcpy(data, buf, ibuf); *datalen = ibuf; - + return 0; } diff --git a/client/cliparser/getopt.h b/client/cliparser/getopt.h index 789b4d1d4..09ff126b4 100644 --- a/client/cliparser/getopt.h +++ b/client/cliparser/getopt.h @@ -76,5 +76,5 @@ extern int optind, opterr, optopt; extern int optreset; /* getopt(3) external variable */ #endif __END_DECLS - + #endif /* !_GETOPT_H_ */ diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c index fea907206..94411f8b5 100644 --- a/client/cmdanalyse.c +++ b/client/cmdanalyse.c @@ -92,7 +92,7 @@ static uint16_t matrixadd ( uint8_t* bytes, uint8_t len){ 0x72 | 0111 0010 0x5e | 0101 1110 ----------------- - C32F 9d74 + C32F 9d74 return 0; } @@ -110,7 +110,7 @@ static uint16_t calcSumCrumbAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { sum += CRUMB(bytes[i], 4); sum += CRUMB(bytes[i], 6); } - sum &= mask; + sum &= mask; return sum; } static uint16_t calcSumCrumbAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask) { @@ -122,7 +122,7 @@ static uint16_t calcSumNibbleAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { sum += NIBBLE_LOW(bytes[i]); sum += NIBBLE_HIGH(bytes[i]); } - sum &= mask; + sum &= mask; return sum; } static uint16_t calcSumNibbleAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask){ @@ -135,7 +135,7 @@ static uint16_t calcSumCrumbXor( uint8_t* bytes, uint8_t len, uint32_t mask) { sum ^= CRUMB(bytes[i], 2); sum ^= CRUMB(bytes[i], 4); sum ^= CRUMB(bytes[i], 6); - } + } sum &= mask; return sum; } @@ -153,7 +153,7 @@ static uint16_t calcSumByteXor( uint8_t* bytes, uint8_t len, uint32_t mask) { for (uint8_t i = 0; i < len; i++) { sum ^= bytes[i]; } - sum &= mask; + sum &= mask; return sum; } static uint16_t calcSumByteAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { @@ -161,7 +161,7 @@ static uint16_t calcSumByteAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { for (uint8_t i = 0; i < len; i++) { sum += bytes[i]; } - sum &= mask; + sum &= mask; return sum; } // Ones complement @@ -174,7 +174,7 @@ static uint16_t calcSumByteSub( uint8_t* bytes, uint8_t len, uint32_t mask) { for (uint8_t i = 0; i < len; i++) { sum -= bytes[i]; } - sum &= mask; + sum &= mask; return sum; } static uint16_t calcSumByteSubOnes( uint8_t* bytes, uint8_t len, uint32_t mask){ @@ -186,7 +186,7 @@ static uint16_t calcSumNibbleSub( uint8_t* bytes, uint8_t len, uint32_t mask) { sum -= NIBBLE_LOW(bytes[i]); sum -= NIBBLE_HIGH(bytes[i]); } - sum &= mask; + sum &= mask; return sum; } static uint16_t calcSumNibbleSubOnes( uint8_t* bytes, uint8_t len, uint32_t mask) { @@ -199,7 +199,7 @@ static uint16_t calcBSDchecksum8( uint8_t* bytes, uint8_t len, uint32_t mask){ for(uint8_t i = 0; i < len; i++){ sum = ((sum & 0xFF) >> 1) | ((sum & 0x1) << 7); // rotate accumulator sum += bytes[i]; // add next byte - sum &= 0xFF; // + sum &= 0xFF; // } sum &= mask; return sum; @@ -210,10 +210,10 @@ static uint16_t calcBSDchecksum4( uint8_t* bytes, uint8_t len, uint32_t mask){ for(uint8_t i = 0; i < len; i++){ sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator sum += NIBBLE_HIGH(bytes[i]); // add high nibble - sum &= 0xF; // + sum &= 0xF; // sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator sum += NIBBLE_LOW(bytes[i]); // add low nibble - sum &= 0xF; // + sum &= 0xF; // } sum &= mask; return sum; @@ -228,10 +228,10 @@ int CmdAnalyseLfsr(const char *Cmd){ uint8_t iv = param_get8ex(Cmd, 0, 0, 16); uint8_t find = param_get8ex(Cmd, 1, 0, 16); - + PrintAndLogEx(NORMAL, "LEGIC LFSR IV 0x%02X: \n", iv); PrintAndLogEx(NORMAL, " bit# | lfsr | ^0x40 | 0x%02X ^ lfsr \n",find); - + for (uint8_t i = 0x01; i < 0x30; i += 1) { //period = 0; legic_prng_init(iv); @@ -246,7 +246,7 @@ int CmdAnalyseLCR(const char *Cmd) { uint8_t data[50]; char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0|| cmdp == 'h') return usage_analyse_lcr(); - + int len = 0; switch (param_gethex_to_eol(Cmd, 0, data, sizeof(data), &len)) { case 1: @@ -267,10 +267,10 @@ int CmdAnalyseCRC(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_analyse_crc(); - + int len = strlen(Cmd); if ( len & 1 ) return usage_analyse_crc(); - + // add 1 for null terminator. uint8_t *data = calloc(len+1, sizeof(uint8_t)); if ( !data ) return 1; @@ -279,35 +279,35 @@ int CmdAnalyseCRC(const char *Cmd) { free(data); return usage_analyse_crc(); } - len >>= 1; + len >>= 1; PrintAndLogEx(NORMAL, "\nTests with (%d) | %s",len, sprint_hex(data, len)); - - // 51 f5 7a d6 + + // 51 f5 7a d6 uint8_t uid[] = {0x51, 0xf5, 0x7a, 0xd6}; //12 34 56 init_table(CRC_LEGIC); uint8_t legic8 = CRC8Legic(uid, sizeof(uid)); PrintAndLogEx(NORMAL, "Legic 16 | %X (EF6F expected) [legic8 = %02x]", crc16_legic(data, len, legic8), legic8); init_table(CRC_FELICA); PrintAndLogEx(NORMAL, "FeliCa | %X ", crc16_xmodem(data, len)); - - PrintAndLogEx(NORMAL, "\nTests of reflection. Current methods in source code"); + + PrintAndLogEx(NORMAL, "\nTests of reflection. Current methods in source code"); PrintAndLogEx(NORMAL, " reflect(0x3e23L,3) is %04X == 0x3e26", reflect(0x3e23L,3) ); PrintAndLogEx(NORMAL, " reflect8(0x80) is %02X == 0x01", reflect8(0x80)); PrintAndLogEx(NORMAL, " reflect16(0x8000) is %04X == 0x0001", reflect16(0xc6c6)); - + uint8_t b1, b2; // ISO14443 crc B - compute_crc(CRC_14443_B, data, len, &b1, &b2); + compute_crc(CRC_14443_B, data, len, &b1, &b2); uint16_t crcBB_1 = b1 << 8 | b2; uint16_t bbb = crc(CRC_14443_B, data, len); PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x == %04x \n", crcBB_1, bbb ); - - + + // Test of CRC16, '123456789' string. // - - PrintAndLogEx(NORMAL, "\n\nStandard test with 31 32 33 34 35 36 37 38 39 '123456789'\n\n"); + + PrintAndLogEx(NORMAL, "\n\nStandard test with 31 32 33 34 35 36 37 38 39 '123456789'\n\n"); uint8_t dataStr[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39 }; legic8 = CRC8Legic(dataStr, sizeof(dataStr)); @@ -321,21 +321,21 @@ int CmdAnalyseCRC(const char *Cmd) { PrintAndLogEx(NORMAL, "CRC16 based\n\n"); // input from commandline - PrintAndLogEx(NORMAL, "CCITT | %X (29B1 expected)", crc(CRC_CCITT, dataStr, sizeof(dataStr))); - + PrintAndLogEx(NORMAL, "CCITT | %X (29B1 expected)", crc(CRC_CCITT, dataStr, sizeof(dataStr))); + uint8_t poll[] = {0xb2,0x4d,0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; PrintAndLogEx(NORMAL, "FeliCa | %04X (B37F expected)", crc(CRC_FELICA, poll+2, sizeof(poll)-4)); PrintAndLogEx(NORMAL, "FeliCa | %04X (0000 expected)", crc(CRC_FELICA, poll+2, sizeof(poll)-2)); - + uint8_t sel_corr[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01}; PrintAndLogEx(NORMAL, "iCLASS | %04x (0143 expected)", crc(CRC_ICLASS, sel_corr, sizeof(sel_corr)-2)); PrintAndLogEx(NORMAL, "---------------------------------------------------------------\n\n\n"); - + // ISO14443 crc A compute_crc(CRC_14443_A, dataStr, sizeof(dataStr), &b1, &b2); uint16_t crcAA = b1 << 8 | b2; PrintAndLogEx(NORMAL, "ISO14443 crc A | %04x or %04x (BF05 expected)\n", crcAA, crc(CRC_14443_A, dataStr, sizeof(dataStr)) ); - + // ISO14443 crc B compute_crc(CRC_14443_B, dataStr, sizeof(dataStr), &b1, &b2); uint16_t crcBB = b1 << 8 | b2; @@ -346,7 +346,7 @@ int CmdAnalyseCRC(const char *Cmd) { uint16_t crcCC = b1 << 8 | b2; PrintAndLogEx(NORMAL, "ISO15693 crc X25| %04x or %04x (906E expected)\n", crcCC, crc(CRC_15693, dataStr, sizeof(dataStr)) ); - // ICLASS + // ICLASS compute_crc(CRC_ICLASS, dataStr, sizeof(dataStr), &b1, &b2); uint16_t crcDD = b1 << 8 | b2; PrintAndLogEx(NORMAL, "ICLASS crc | %04x or %04x\n", crcDD, crc(CRC_ICLASS, dataStr, sizeof(dataStr)) ); @@ -355,12 +355,12 @@ int CmdAnalyseCRC(const char *Cmd) { compute_crc(CRC_FELICA, dataStr, sizeof(dataStr), &b1, &b2); uint16_t crcEE = b1 << 8 | b2; PrintAndLogEx(NORMAL, "FeliCa | %04x or %04x (31C3 expected)\n", crcEE, crc(CRC_FELICA, dataStr, sizeof(dataStr))); - + free(data); return 0; } int CmdAnalyseCHKSUM(const char *Cmd){ - + uint8_t data[50]; uint8_t cmdp = 0; uint32_t mask = 0xFFFF; @@ -368,18 +368,18 @@ int CmdAnalyseCHKSUM(const char *Cmd){ bool useHeader = false; int len = 0; memset(data, 0x0, sizeof(data)); - + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch(param_getchar(Cmd, cmdp)) { case 'b': case 'B': param_gethex_ex(Cmd, cmdp+1, data, &len); if ( len%2 ) errors = true; - len >>= 1; + len >>= 1; cmdp += 2; break; case 'm': - case 'M': + case 'M': mask = param_get32ex(Cmd, cmdp+1, 0, 16); cmdp += 2; break; @@ -399,13 +399,13 @@ int CmdAnalyseCHKSUM(const char *Cmd){ } //Validations if (errors || cmdp == 0 ) return usage_analyse_checksum(); - + if (useHeader) { PrintAndLogEx(NORMAL, " add | sub | add 1's compl | sub 1's compl | xor"); PrintAndLogEx(NORMAL, "byte nibble crumb | byte nibble | byte nibble cumb | byte nibble | byte nibble cumb | BSD |"); PrintAndLogEx(NORMAL, "------------------+-------------+------------------+-----------------+--------------------"); } - PrintAndLogEx(NORMAL, "0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X |\n", + PrintAndLogEx(NORMAL, "0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X |\n", calcSumByteAdd(data, len, mask) , calcSumNibbleAdd(data, len, mask) , calcSumCrumbAdd(data, len, mask) @@ -421,7 +421,7 @@ int CmdAnalyseCHKSUM(const char *Cmd){ , calcSumCrumbXor(data, len, mask) , calcBSDchecksum8(data, len, mask) , calcBSDchecksum4(data, len, mask) - ); + ); return 0; } @@ -431,7 +431,7 @@ int CmdAnalyseDates(const char *Cmd){ return 0; } int CmdAnalyseTEASelfTest(const char *Cmd){ - + uint8_t v[8], v_le[8]; memset(v, 0x00, sizeof(v)); memset(v_le, 0x00, sizeof(v_le)); @@ -439,26 +439,26 @@ int CmdAnalyseTEASelfTest(const char *Cmd){ uint8_t cmdlen = strlen(Cmd); cmdlen = ( sizeof(v)<<2 < cmdlen ) ? sizeof(v)<<2 : cmdlen; - + if ( param_gethex(Cmd, 0, v, cmdlen) > 0 ){ PrintAndLogEx(WARNING, "Can't read hex chars, uneven? :: %u", cmdlen); return 1; } - + SwapEndian64ex(v , 8, 4, v_ptr); - - // ENCRYPTION KEY: + + // ENCRYPTION KEY: uint8_t key[16] = {0x55,0xFE,0xF6,0x30,0x62,0xBF,0x0B,0xC1,0xC9,0xB3,0x7C,0x34,0x97,0x3E,0x29,0xFB }; uint8_t keyle[16]; uint8_t* key_ptr = keyle; SwapEndian64ex(key , sizeof(key), 4, key_ptr); - + PrintAndLogEx(NORMAL, "TEST LE enc| %s", sprint_hex(v_ptr, 8)); - - tea_decrypt(v_ptr, key_ptr); + + tea_decrypt(v_ptr, key_ptr); PrintAndLogEx(NORMAL, "TEST LE dec | %s", sprint_hex_ascii(v_ptr, 8)); - - tea_encrypt(v_ptr, key_ptr); + + tea_encrypt(v_ptr, key_ptr); tea_encrypt(v_ptr, key_ptr); PrintAndLogEx(NORMAL, "TEST enc2 | %s", sprint_hex_ascii(v_ptr, 8)); @@ -469,14 +469,14 @@ char* pb(uint32_t b) { static char buf1[33] = {0}; static char buf2[33] = {0}; static char *s; - + if (s != buf1) s = buf1; - else + else s = buf2; - + memset(s, 0, sizeof(buf1)); - + uint32_t mask = 0x80000000; for (uint8_t i=0; i<32;i++) { s[i] = (mask & b)?'1':'0'; @@ -491,7 +491,7 @@ int CmdAnalyseA(const char *Cmd){ uint8_t cmdp = 0; bool errors = false; uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'd': @@ -500,7 +500,7 @@ int CmdAnalyseA(const char *Cmd){ if ( hexlen != sizeof(data) ) { PrintAndLogEx(WARNING, "Read %d bytes of %u", hexlen, sizeof(data) ); } - cmdp += 2; + cmdp += 2; break; case 'h': return usage_analyse_a(); @@ -513,7 +513,7 @@ int CmdAnalyseA(const char *Cmd){ //Validations if (errors || cmdp == 0 ) return usage_analyse_a(); - + UsbCommand c = {CMD_FPC_SEND, {0, 0, 0}}; memcpy(c.d.asBytes, data, USB_CMD_DATA_SIZE); clearCommandBuffer(); @@ -525,16 +525,16 @@ int CmdAnalyseA(const char *Cmd){ } PrintAndLogEx(NORMAL, "got ack. Status %d", resp.arg[0]); return 0; - + PrintAndLogEx(NORMAL, "-- " _BLUE_(its my message) "\n"); PrintAndLogEx(NORMAL, "-- " _RED_(its my message) "\n"); PrintAndLogEx(NORMAL, "-- " _YELLOW_(its my message) "\n"); PrintAndLogEx(NORMAL, "-- " _GREEN_(its my message) "\n"); - + //uint8_t syncBit = 99; // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111) - // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern + // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's) # define SYNC_16BIT 0xB24D uint32_t shiftReg = param_get32ex(Cmd, 0, 0xb24d, 16); @@ -554,7 +554,7 @@ int CmdAnalyseA(const char *Cmd){ n1 = (n1 << 4) | (rev & (uint8_t)(~(0xFF << 4))); PrintAndLogEx(NORMAL, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1) ); - + /* hex(0xb24d shr 0) 0xB24D 0b1011001001001101 hex(0xb24d shr 1) 0x5926 @@ -568,29 +568,29 @@ for ( int i =0; i< 16; i++) { if ((( shiftReg >> 7) & 0xFFFF ) == SYNC_16BIT) byte_offset = 7; else if ((( shiftReg >> 6) & 0xFFFF ) == SYNC_16BIT) byte_offset = 6; else if ((( shiftReg >> 5) & 0xFFFF ) == SYNC_16BIT) byte_offset = 5; - else if ((( shiftReg >> 4) & 0xFFFF ) == SYNC_16BIT) byte_offset = 4; + else if ((( shiftReg >> 4) & 0xFFFF ) == SYNC_16BIT) byte_offset = 4; else if ((( shiftReg >> 3) & 0xFFFF ) == SYNC_16BIT) byte_offset = 3; else if ((( shiftReg >> 2) & 0xFFFF ) == SYNC_16BIT) byte_offset = 2; else if ((( shiftReg >> 1) & 0xFFFF ) == SYNC_16BIT) byte_offset = 1; else if ((( shiftReg >> 0) & 0xFFFF ) == SYNC_16BIT) byte_offset = 0; PrintAndLogEx(NORMAL, "Offset %u \n", byte_offset); - if ( byte_offset != 99 ) + if ( byte_offset != 99 ) break; - - shiftReg >>=1; + + shiftReg >>=1; } uint8_t p1 = (rev & (uint8_t)(~(0xFF << byte_offset))); PrintAndLogEx(NORMAL, "Offset %u | leftovers %02x %s \n", byte_offset, p1, pb(p1) ); - - /* + + /* pm3 --> da hex2bin 4db2 0100110110110010 */ return 0; -/* +/* // split byte into two parts. uint8_t offset = 3, n0 = 0, n1 = 0; rev = 0xB2; @@ -605,47 +605,47 @@ pm3 --> da hex2bin 4db2 0100110110110010 //PrintAndLogEx(NORMAL, "~(0xFF >> (8-offset)) == %s |\n", pb( (uint8_t)(~(0xFF >> (8-offset))) ) ); //PrintAndLogEx(NORMAL, " rev & xxx == %s\n\n", pb( (rev & (uint8_t)(~(0xFF << offset))) )); } -return 0; +return 0; // from A -- x bits into B and the rest into C. - - for ( uint8_t i=0; i<8; i++){ + + for ( uint8_t i=0; i<8; i++){ PrintAndLogEx(NORMAL, "%u | %02X %s | %02X %s |\n", i, a, pb(a), b, pb(b) ); b = a & (a & (0xFF >> (8-i))); a >>=1; } - + */ return 0; - // 14443-A - uint8_t u14_c[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe8 }; // atqs w crc + // 14443-A + uint8_t u14_c[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe8 }; // atqs w crc uint8_t u14_w[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe7 }; // atqs w crc - PrintAndLogEx(FAILED, "14a check wrong crc | %s\n", (check_crc(CRC_14443_A, u14_w, sizeof(u14_w))) ? "YES": "NO" ); + PrintAndLogEx(FAILED, "14a check wrong crc | %s\n", (check_crc(CRC_14443_A, u14_w, sizeof(u14_w))) ? "YES": "NO" ); PrintAndLogEx(SUCCESS, "14a check correct crc | %s\n", (check_crc(CRC_14443_A, u14_c, sizeof(u14_c))) ? "YES": "NO" ); - + // 14443-B uint8_t u14b[] = {0x05,0x00,0x08,0x39,0x73}; - PrintAndLogEx(NORMAL, "14b check crc | %s\n", (check_crc(CRC_14443_B, u14b, sizeof(u14b))) ? "YES": "NO"); + PrintAndLogEx(NORMAL, "14b check crc | %s\n", (check_crc(CRC_14443_B, u14b, sizeof(u14b))) ? "YES": "NO"); // 15693 test uint8_t u15_c[] = {0x05,0x00,0x08,0x39,0x73}; // correct uint8_t u15_w[] = {0x05,0x00,0x08,0x39,0x72}; // wrong - PrintAndLogEx(FAILED, "15 check wrong crc | %s\n", (check_crc(CRC_15693, u15_w, sizeof(u15_w))) ? "YES": "NO"); - PrintAndLogEx(SUCCESS, "15 check correct crc | %s\n", (check_crc(CRC_15693, u15_c, sizeof(u15_c))) ? "YES": "NO"); + PrintAndLogEx(FAILED, "15 check wrong crc | %s\n", (check_crc(CRC_15693, u15_w, sizeof(u15_w))) ? "YES": "NO"); + PrintAndLogEx(SUCCESS, "15 check correct crc | %s\n", (check_crc(CRC_15693, u15_c, sizeof(u15_c))) ? "YES": "NO"); // iCLASS test - wrong crc , swapped bytes. uint8_t iclass_w[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x01, 0x43}; uint8_t iclass_c[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01}; - PrintAndLogEx(FAILED, "iCLASS check wrong crc | %s\n", (check_crc(CRC_ICLASS, iclass_w, sizeof(iclass_w))) ? "YES": "NO"); - PrintAndLogEx(SUCCESS, "iCLASS check correct crc | %s\n", (check_crc(CRC_ICLASS, iclass_c, sizeof(iclass_c))) ? "YES": "NO"); - + PrintAndLogEx(FAILED, "iCLASS check wrong crc | %s\n", (check_crc(CRC_ICLASS, iclass_w, sizeof(iclass_w))) ? "YES": "NO"); + PrintAndLogEx(SUCCESS, "iCLASS check correct crc | %s\n", (check_crc(CRC_ICLASS, iclass_c, sizeof(iclass_c))) ? "YES": "NO"); + // FeliCa test uint8_t felica_w[] = {0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7e}; uint8_t felica_c[] = {0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; - PrintAndLogEx(FAILED, "FeliCa check wrong crc | %s\n", (check_crc(CRC_FELICA, felica_w, sizeof(felica_w))) ? "YES": "NO"); - PrintAndLogEx(SUCCESS, "FeliCa check correct crc | %s\n", (check_crc(CRC_FELICA, felica_c, sizeof(felica_c))) ? "YES": "NO"); - - PrintAndLogEx(NORMAL, "\n\n"); + PrintAndLogEx(FAILED, "FeliCa check wrong crc | %s\n", (check_crc(CRC_FELICA, felica_w, sizeof(felica_w))) ? "YES": "NO"); + PrintAndLogEx(SUCCESS, "FeliCa check correct crc | %s\n", (check_crc(CRC_FELICA, felica_c, sizeof(felica_c))) ? "YES": "NO"); + + PrintAndLogEx(NORMAL, "\n\n"); return 0; /* @@ -656,7 +656,7 @@ return 0; star[1] = '\\'; star[2] = '|'; star[3] = '/'; - + for (uint8_t k=0; k<4; k = (k+1) % 4 ) { PrintAndLogEx(NORMAL, "\e[s%c\e[u", star[k]); fflush(stdout); @@ -667,19 +667,19 @@ return 0; } } */ - + //piwi // uid(2e086b1a) nt(230736f6) ks(0b0008000804000e) nr(000000000) // uid(2e086b1a) nt(230736f6) ks(0e0b0e0b090c0d02) nr(000000001) // uid(2e086b1a) nt(230736f6) ks(0e05060e01080b08) nr(000000002) //uint64_t d1[] = {0x2e086b1a, 0x230736f6, 0x0000001, 0x0e0b0e0b090c0d02}; //uint64_t d2[] = {0x2e086b1a, 0x230736f6, 0x0000002, 0x0e05060e01080b08}; - + // uid(17758822) nt(c0c69e59) ks(080105020705040e) nr(00000001) // uid(17758822) nt(c0c69e59) ks(01070a05050c0705) nr(00000002) //uint64_t d1[] = {0x17758822, 0xc0c69e59, 0x0000001, 0x080105020705040e}; //uint64_t d2[] = {0x17758822, 0xc0c69e59, 0x0000002, 0x01070a05050c0705}; - + // uid(6e442129) nt(8f699195) ks(090d0b0305020f02) nr(00000001) // uid(6e442129) nt(8f699195) ks(03030508030b0c0e) nr(00000002) // uid(6e442129) nt(8f699195) ks(02010f030c0d050d) nr(00000003) @@ -687,7 +687,7 @@ return 0; //uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0x090d0b0305020f02}; //uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0x00040f0f0305030e}; -/* +/* uid(3e172b29) nt(039b7bd2) ks(0c0e0f0505080800) nr(00000001) uid(3e172b29) nt(039b7bd2) ks(0e06090d03000b0f) nr(00000002) */ @@ -697,7 +697,7 @@ uid(3e172b29) nt(039b7bd2) ks(0e06090d03000b0f) nr(00000002) // uint64_t d2[] = {0x3e172b29, 0x039b7bd2, 0x0000002, 0, 0x0e06090d03000b0f}; uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0, 0x090d0b0305020f02}; uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e}; - + keycountA = nonce2key(d1[0], d1[1], d1[2], 0, d1[3], d1[4] ,&keylistA); keycountB = nonce2key(d2[0], d2[1], d2[2], 0, d2[3], d2[4], &keylistB); @@ -708,11 +708,11 @@ uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e}; switch (keycountB) { case 0: PrintAndLogEx(FAILED, "Key test B failed\n"); break; case 1: PrintAndLogEx(SUCCESS, "KEY B | %012" PRIX64 " ", keylistB[0]); break; - } - + } + free(keylistA); free(keylistB); - + // qsort(keylist, keycount, sizeof(*keylist), compare_uint64); // keycount = intersection(last_keylist, keylist); @@ -727,7 +727,7 @@ uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e}; 0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b, 0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe }; - + uint64_t keya[] = { 0x7b5b8144a32f, 0x76b46ccc461e, 0x03c3c36ea7a2, 0x171414d31961, 0xe2bfc7153eea, 0x48023d1d1985, 0xff7e1a410953, 0x49a3110249d3, @@ -740,9 +740,9 @@ uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e}; 0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b, 0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe }; - + */ - + /* uint64_t xor[] = { 0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B, @@ -754,7 +754,7 @@ uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e}; 0x6082DB527C11, 0x4D666ADA4C0E, 0x2D461D05F163, 0x3596CFF0FEC8, 0x8CBD9258FE22, 0x00D29A7B304B, 0xBC33DC6C9244 }; - + uint64_t xorA[] = { 0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B, @@ -769,7 +769,7 @@ uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e}; 0x8CBD9258FE22, 0x00D29A7B304B, 0xBC33DC6C9244 }; */ - /* + /* // xor key A | xor key B 1 | 0DEFED88E531 | 2F87A1BDC230 2 | 7577AFA2E1BC | E43F502B984C @@ -795,12 +795,12 @@ uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e}; PrintAndLogEx(NORMAL, "%u | %012" PRIX64 " | \n", i, a); } */ - + /* - uint32_t id = param_get32ex(Cmd, 0, 0x93290142, 16); + uint32_t id = param_get32ex(Cmd, 0, 0x93290142, 16); uint8_t uid[6] = {0}; num_to_bytes(id,4,uid); - + uint8_t key_s0a[] = { uid[1] ^ uid[2] ^ uid[3] ^ 0x11, uid[1] ^ 0x72, @@ -812,20 +812,20 @@ uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e}; PrintAndLogEx(NORMAL, "UID | %s\n", sprint_hex(uid,4 )); PrintAndLogEx(NORMAL, "KEY A | %s\n", sprint_hex(key_s0a, 6)); - + // arrays w all keys uint64_t foo[32] = {0}; - + //A foo[0] = bytes_to_num(key_s0a, 6); //B //foo[16] = 0xcafe71411fbf; foo[16] = 0xeafe51411fbf; - - for (uint8_t i=0; i<15; i++){ + + for (uint8_t i=0; i<15; i++){ foo[i+1] = foo[i] ^ xorA[i]; foo[i+16+1] = foo[i+16] ^ xorB[i]; - + } for (uint8_t i=0; i<15; i++){ uint64_t a = foo[i]; @@ -836,7 +836,7 @@ uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e}; a, ( a == keya[i])?"ok":"err", b, - ( b == keyb[i])?"ok":"err" + ( b == keyb[i])?"ok":"err" ); } */ @@ -846,7 +846,7 @@ uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e}; void generate4bNUID(uint8_t *uid, uint8_t *nuid){ uint16_t crc; uint8_t b1, b2; - + compute_crc(CRC_14443_A, uid, 3, &b1, &b2); nuid[0] = (b2 & 0xE0) | 0xF; nuid[1] = b1; @@ -858,7 +858,7 @@ void generate4bNUID(uint8_t *uid, uint8_t *nuid){ } int CmdAnalyseNuid(const char *Cmd){ - uint8_t nuid[4] = {0}; + uint8_t nuid[4] = {0}; uint8_t uid[7] = {0}; int len = 0; char cmdp = tolower(param_getchar(Cmd, 0)); @@ -870,13 +870,13 @@ int CmdAnalyseNuid(const char *Cmd){ if (cmdp == 't') { memcpy(uid, "\x04\x0d\x68\x1a\xb5\x22\x81", 7); generate4bNUID(uid, nuid); - + bool test1 = (0 == memcmp(nuid, "\x8f\x43\x0f\xef", 4)); PrintAndLogEx(SUCCESS, "Selftest1 %s\n", test1 ? _GREEN_(OK): _RED_(Fail)); - + memcpy(uid, "\x04\x18\x3f\x09\x32\x1b\x85", 7); generate4bNUID(uid, nuid); - bool test2 = (0 == memcmp(nuid, "\x4f\x50\x5d\x7d", 4)); + bool test2 = (0 == memcmp(nuid, "\x4f\x50\x5d\x7d", 4)); PrintAndLogEx(SUCCESS, "Selftest2 %s\n", test2 ? _GREEN_(OK) : _RED_(Fail)); return 0; } @@ -885,7 +885,7 @@ int CmdAnalyseNuid(const char *Cmd){ if ( len%2 || len != 14) return usage_analyse_nuid(); generate4bNUID(uid, nuid); - + PrintAndLogEx(NORMAL, "UID | %s \n", sprint_hex(uid, 7)); PrintAndLogEx(NORMAL, "NUID | %s \n", sprint_hex(nuid, 4)); return 0; diff --git a/client/cmdanalyse.h b/client/cmdanalyse.h index ab7606f5c..c362744c0 100644 --- a/client/cmdanalyse.h +++ b/client/cmdanalyse.h @@ -23,7 +23,7 @@ #include "tea.h" #include "legic_prng.h" #include "loclass/elite_crack.h" -#include "mifare/mfkey.h" //nonce2key +#include "mifare/mfkey.h" //nonce2key #include "util_posix.h" // msclock diff --git a/client/cmdcrc.c b/client/cmdcrc.c index a34c7d351..a54653d3e 100644 --- a/client/cmdcrc.c +++ b/client/cmdcrc.c @@ -55,7 +55,7 @@ int CmdCrc(const char *Cmd) { for(int i = 0; i < argc; ++i) { free(argv[i]); } - return 0; + return 0; } //returns array of model names and the count of models returning @@ -75,7 +75,7 @@ int GetModels(char *Models[], int *count, uint8_t *width){ #endif /* _WIN32 */ SETBMP(); - + int args = 0, psets, pass; int Cnt = 0; if (width[0] == 0) { //reveng -D @@ -100,7 +100,7 @@ int GetModels(char *Models[], int *count, uint8_t *width){ mfree(&model); } else { //reveng -s - if (~model.flags & P_MULXN){ + if (~model.flags & P_MULXN){ PrintAndLogEx(WARNING, "cannot search for non-Williams compliant models"); return 0; } @@ -131,7 +131,7 @@ int GetModels(char *Models[], int *count, uint8_t *width){ while (psets) { mbynum(&pset, --psets); - + /* skip if different width, or refin or refout don't match */ if( plen(pset.spoly) != width[0] || (model.flags ^ pset.flags) & (P_REFIN | P_REFOUT)) continue; @@ -142,14 +142,14 @@ int GetModels(char *Models[], int *count, uint8_t *width){ continue; if (rflags & R_HAVEX && psncmp(&model.xorout, &pset.xorout)) continue; - + //for additional args (not used yet, maybe future?) apoly = pclone(pset.xorout); - + if (pset.flags & P_REFOUT) prev(&apoly); - - + + for (qptr = apolys; qptr < pptr; ++qptr) { crc = pcrc(*qptr, pset.spoly, pset.init, apoly, 0); if (ptst(crc)) { @@ -159,12 +159,12 @@ int GetModels(char *Models[], int *count, uint8_t *width){ pfree(&crc); } pfree(&apoly); - + if (qptr == pptr) { /* the selected model solved all arguments */ mcanon(&pset); - + size_t size = (pset.name && *pset.name) ? strlen(pset.name) : 7; //PrintAndLogEx(NORMAL, "Size: %d, %s, count: %d",size,pset.name, Cnt); char *tmp = calloc(size+1, sizeof(char)); @@ -201,8 +201,8 @@ int GetModels(char *Models[], int *count, uint8_t *width){ PrintAndLogEx(WARNING, "no models found"); return 0; } - - if (!(model.flags & P_REFIN) != !(model.flags & P_REFOUT)){ + + if (!(model.flags & P_REFIN) != !(model.flags & P_REFOUT)){ PrintAndLogEx(WARNING, "cannot search for crossed-endian models"); return 0; } @@ -223,13 +223,13 @@ int GetModels(char *Models[], int *count, uint8_t *width){ } } } while (~rflags & R_HAVERI && ++pass < 2); - + for (qptr = apolys; qptr < pptr; ++qptr) { pfree(qptr); } free(apolys); mfree(&model); - + if (~uflags & C_RESULT){ PrintAndLogEx(WARNING, "no models found"); return 0; @@ -248,9 +248,9 @@ int GetModels(char *Models[], int *count, uint8_t *width){ int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *result){ /* default values */ static model_t model = MZERO; - + int ibperhx = 8, obperhx = 8; - int rflags = 0; // search flags + int rflags = 0; // search flags int c; poly_t apoly, crc; @@ -273,7 +273,7 @@ int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *res return 0; } rflags |= R_HAVEP | R_HAVEI | R_HAVERI | R_HAVERO | R_HAVEX; - + //set flags switch (endian) { case 'b': /* b big-endian (RefIn = false, RefOut = false ) */ @@ -376,12 +376,12 @@ int CmdrevengTestC(const char *Cmd){ dataLen = param_getstr(Cmd, cmdp++, inHexStr, sizeof(inHexStr)); if (dataLen < 4) return 0; bool reverse = (param_get8(Cmd, cmdp++)) ? true : false; - endian = param_getchar(Cmd, cmdp++); + endian = param_getchar(Cmd, cmdp++); //PrintAndLogEx(NORMAL, "mod: %s, hex: %s, rev %d", inModel, inHexStr, reverse); int ans = RunModel(inModel, inHexStr, reverse, endian, result); if (!ans) return 0; - + PrintAndLogEx(SUCCESS, "result: %s",result); return 1; } @@ -401,8 +401,8 @@ char *SwapEndianStr(const char *inStr, const size_t len, const uint8_t blockSize // takes hex string in and searches for a matching result (hex string must include checksum) int CmdrevengSearch(const char *Cmd){ -#define NMODELS 105 - +#define NMODELS 105 + char inHexStr[100] = {0x00}; int dataLen = param_getstr(Cmd, 0, inHexStr, sizeof(inHexStr)); if (dataLen < 4) return 0; @@ -418,7 +418,7 @@ int CmdrevengSearch(const char *Cmd){ int ans = GetModels(Models, &count, width); bool found = false; if (!ans) return 0; - + // try each model and get result for (int i = 0; i < count; i++){ /*if (found) { @@ -426,9 +426,9 @@ int CmdrevengSearch(const char *Cmd){ continue; }*/ // round up to # of characters in this model's crc - crcChars = ((width[i]+7)/8)*2; + crcChars = ((width[i]+7)/8)*2; // can't test a model that has more crc digits than our data - if (crcChars >= dataLen) + if (crcChars >= dataLen) continue; memset(result, 0, 30); char *inCRC = calloc(crcChars+1, sizeof(char)); @@ -480,7 +480,7 @@ int CmdrevengSearch(const char *Cmd){ free(outHex); free(Models[i]); } - + if (!found) PrintAndLogEx(FAILED, "\nno matches found\n"); return 1; } \ No newline at end of file diff --git a/client/cmddata.c b/client/cmddata.c index 0403c4f28..998ce3779 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -24,14 +24,14 @@ int usage_data_printdemodbuf(void){ PrintAndLogEx(NORMAL, " x output in hex (omit for binary output)"); PrintAndLogEx(NORMAL, " o enter offset in # of bits"); PrintAndLogEx(NORMAL, " l enter length to print in # of bits or hex characters respectively"); - return 0; + return 0; } int usage_data_manrawdecode(void){ PrintAndLogEx(NORMAL, "Usage: data manrawdecode [invert] [maxErr]"); PrintAndLogEx(NORMAL, " Takes 10 and 01 and converts to 0 and 1 respectively"); PrintAndLogEx(NORMAL, " --must have binary sequence in demodbuffer (run data askrawdemod first)"); - PrintAndLogEx(NORMAL, " [invert] invert output"); - PrintAndLogEx(NORMAL, " [maxErr] set number of errors allowed (default = 20)"); + PrintAndLogEx(NORMAL, " [invert] invert output"); + PrintAndLogEx(NORMAL, " [maxErr] set number of errors allowed (default = 20)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " Example: data manrawdecode = decode manchester bitstream from the demodbuffer"); return 0; @@ -52,10 +52,10 @@ int usage_data_biphaserawdecode(void){ } int usage_data_rawdemod(void){ PrintAndLogEx(NORMAL, "Usage: data rawdemod [modulation] |"); - PrintAndLogEx(NORMAL, " [modulation] as 2 char, 'ab' for ask/biphase, 'am' for ask/manchester, 'ar' for ask/raw, 'fs' for fsk, ..."); + PrintAndLogEx(NORMAL, " [modulation] as 2 char, 'ab' for ask/biphase, 'am' for ask/manchester, 'ar' for ask/raw, 'fs' for fsk, ..."); PrintAndLogEx(NORMAL, " 'nr' for nrz/direct, 'p1' for psk1, 'p2' for psk2"); - PrintAndLogEx(NORMAL, " as 'h', prints the help for the specific modulation"); - PrintAndLogEx(NORMAL, " see specific modulation help for optional parameters"); + PrintAndLogEx(NORMAL, " as 'h', prints the help for the specific modulation"); + PrintAndLogEx(NORMAL, " see specific modulation help for optional parameters"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " Example: data rawdemod fs h = print help specific to fsk demod"); PrintAndLogEx(NORMAL, " : data rawdemod fs = demod GraphBuffer using: fsk - autodetect"); @@ -132,7 +132,7 @@ int usage_data_rawdemod_fs(void){ PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " Example: data rawdemod fs = demod an fsk tag from GraphBuffer using autodetect"); PrintAndLogEx(NORMAL, " : data rawdemod fs 32 = demod an fsk tag from GraphBuffer using a clock of RF/32, autodetect fc"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 1 = demod an fsk tag from GraphBuffer using autodetect, invert output"); + PrintAndLogEx(NORMAL, " : data rawdemod fs 1 = demod an fsk tag from GraphBuffer using autodetect, invert output"); PrintAndLogEx(NORMAL, " : data rawdemod fs 32 1 = demod an fsk tag from GraphBuffer using a clock of RF/32, invert output, autodetect fc"); PrintAndLogEx(NORMAL, " : data rawdemod fs 64 0 8 5 = demod an fsk1 RF/64 tag from GraphBuffer"); PrintAndLogEx(NORMAL, " : data rawdemod fs 50 0 10 8 = demod an fsk2 RF/50 tag from GraphBuffer"); @@ -232,7 +232,7 @@ int usage_data_fsktonrz() { PrintAndLogEx(NORMAL, " c enter the a clock (omit to autodetect)"); PrintAndLogEx(NORMAL, " l enter a field clock (omit to autodetect)"); PrintAndLogEx(NORMAL, " f enter a field clock (omit to autodetect)"); - return 0; + return 0; } //set the demod buffer with given array of binary (one bit per byte) @@ -242,10 +242,10 @@ void setDemodBuf(uint8_t *buf, size_t size, size_t start_idx) { if ( size > MAX_DEMOD_BUF_LEN - start_idx) size = MAX_DEMOD_BUF_LEN - start_idx; - + for (size_t i = 0; i < size; i++) DemodBuffer[i] = buf[start_idx++]; - + DemodBufferLen = size; } @@ -271,13 +271,13 @@ double rms(double *v, size_t n) { int cmp_int( const void *a, const void *b) { if (*(const int *)a < *(const int *)b) return -1; - else + else return *(const int *)a > *(const int *)b; } int cmp_uint8( const void *a, const void *b) { if (*(const uint8_t *)a < *(const uint8_t *)b) return -1; - else + else return *(const uint8_t *)a > *(const uint8_t *)b; } // Median of a array of values @@ -306,7 +306,7 @@ static double compute_variance(const int *data, size_t n) { for (size_t i=0; i < n; i++) variance += pow(( data[i] - mean), 2.0); - variance /= n; + variance /= n; return variance; } @@ -319,10 +319,10 @@ static double compute_autoc(const int *data, size_t n, int lag) { double ac_value; // Computed autocorrelation value to be returned double variance; // Computed variance double mean; - + mean = compute_mean(data, n); variance = compute_variance(data, n); - + for (size_t i=0; i < (n - lag); i++) autocv += (data[i] - mean) * (data[i+lag] - mean); @@ -350,13 +350,13 @@ void save_restoreDB(uint8_t saveOpt) { savedDemodStartIdx = g_DemodStartIdx; savedDemodClock = g_DemodClock; } else if (DB_Saved) { //restore - + memcpy(DemodBuffer, SavedDB, sizeof(DemodBuffer)); DemodBufferLen = SavedDBlen; g_DemodClock = savedDemodClock; g_DemodStartIdx = savedDemodStartIdx; } -} +} int CmdSetDebugMode(const char *Cmd) { int demod = 0; @@ -373,7 +373,7 @@ void printDemodBuff(void) { PrintAndLogEx(NORMAL, "(printDemodBuff) no bits found in demod buffer"); return; } - if (len > 512) len = 512; + if (len > 512) len = 512; PrintAndLogEx(NORMAL, "%s", sprint_bin_break(DemodBuffer, len, 16) ); } @@ -411,12 +411,12 @@ int CmdPrintDemodBuff(const char *Cmd) { } //Validations if (errors) return usage_data_printdemodbuf(); - + if (DemodBufferLen == 0) { PrintAndLogEx(NORMAL, "Demodbuffer is empty"); return 0; } - length = (length > (DemodBufferLen-offset)) ? DemodBufferLen-offset : length; + length = (length > (DemodBufferLen-offset)) ? DemodBufferLen-offset : length; int numBits = (length) & 0x00FFC; //make sure we don't exceed our string if (hexMode){ @@ -426,7 +426,7 @@ int CmdPrintDemodBuff(const char *Cmd) { if (numBits == 0) { return 0; } - PrintAndLogEx(NORMAL, "DemodBuffer: %s", hex); + PrintAndLogEx(NORMAL, "DemodBuffer: %s", hex); } else { PrintAndLogEx(NORMAL, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer+offset, numBits, 16)); } @@ -439,7 +439,7 @@ int CmdGetBitStream(const char *Cmd) { CmdHpf(Cmd); for (uint32_t i = 0; i < GraphTraceLen; i++) GraphBuffer[i] = (GraphBuffer[i] >= 1) ? 1 : 0; - + RepaintGraphWindow(); return 0; } @@ -449,7 +449,7 @@ int CmdGetBitStream(const char *Cmd) { // (amp may not be needed anymore) //verbose will print results and demoding messages //emSearch will auto search for EM410x format in bitstream -//askType switches decode: ask/raw = 0, ask/manchester = 1 +//askType switches decode: ask/raw = 0, ask/manchester = 1 int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool *stCheck) { int invert = 0; int clk = 0; @@ -484,11 +484,11 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, int foundclk = 0; //amp before ST check if (amp == 'a') - askAmp(bits, BitLen); + askAmp(bits, BitLen); bool st = false; size_t ststart = 0, stend = 0; - if (*stCheck) + if (*stCheck) st = DetectST(bits, &BitLen, &foundclk, &ststart, &stend); if (st) { @@ -496,7 +496,7 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, clk = (clk == 0) ? foundclk : clk; CursorCPos = ststart; CursorDPos = stend; - if (verbose || g_debugMode) + if (verbose || g_debugMode) PrintAndLogEx(NORMAL, "Found Sequence Terminator - First one is shown by orange and blue graph markers"); } @@ -512,7 +512,7 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Too many errors found, errors:%d, bits:%d, clock:%d", errCnt, BitLen, clk); return 0; } - + if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Using clock:%d, invert:%d, bits found:%d", clk, invert, BitLen); //output @@ -520,14 +520,14 @@ int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, setClockGrid(clk, startIdx); if (verbose || g_debugMode){ - if (errCnt > 0) + if (errCnt > 0) PrintAndLogEx(NORMAL, "# Errors during Demoding (shown as 7 in bit stream): %d",errCnt); - if (askType) + if (askType) PrintAndLogEx(NORMAL, "ASK/Manchester - Clock: %d - Decoded bitstream:",clk); - else + else PrintAndLogEx(NORMAL, "ASK/Raw - Clock: %d - Decoded bitstream:",clk); // Now output the bitstream to the scrollback by line of 16 bits - printDemodBuff(); + printDemodBuff(); } uint64_t lo = 0; uint32_t hi = 0; @@ -570,17 +570,17 @@ int Cmdmandecoderaw(const char *Cmd) { if (strlen(Cmd) > 5 || cmdp == 'h') return usage_data_manrawdecode(); if (DemodBufferLen == 0) return 0; - + uint8_t bits[MAX_DEMOD_BUF_LEN] = {0}; - + for (; i < DemodBufferLen; ++i){ - if (DemodBuffer[i] > high) + if (DemodBuffer[i] > high) high = DemodBuffer[i]; - else if(DemodBuffer[i] < low) + else if(DemodBuffer[i] < low) low = DemodBuffer[i]; bits[i] = DemodBuffer[i]; } - + if (high > 7 || low < 0 ){ PrintAndLogEx(WARNING, "Error: please raw demod the wave first then manchester raw decode"); return 0; @@ -594,10 +594,10 @@ int Cmdmandecoderaw(const char *Cmd) { PrintAndLogEx(WARNING, "Too many errors: %d",errCnt); return 0; } - + PrintAndLogEx(NORMAL, "Manchester Decoded - # errors:%d - data:",errCnt); PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 16)); - + if (errCnt == 0){ uint64_t id = 0; uint32_t hi = 0; @@ -628,11 +628,11 @@ int CmdBiphaseDecodeRaw(const char *Cmd) { PrintAndLogEx(NORMAL, "DemodBuffer Empty - run 'data rawdemod ar' first"); return 0; } - + uint8_t bits[MAX_DEMOD_BUF_LEN] = {0}; size = sizeof(bits); if ( !getDemodBuf(bits, &size) ) return 0; - + errCnt = BiphaseRawDecode(bits, &size, &offset, invert); if (errCnt < 0){ PrintAndLogEx(WARNING, "Error during decode:%d", errCnt); @@ -648,11 +648,11 @@ int CmdBiphaseDecodeRaw(const char *Cmd) { PrintAndLogEx(NORMAL, "Biphase Decoded using offset: %d - # invert:%d - data:",offset,invert); PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 16)); - + //remove first bit from raw demod - if (offset) + if (offset) setDemodBuf(DemodBuffer,DemodBufferLen-offset, offset); - + setClockGrid(g_DemodClock, g_DemodStartIdx + g_DemodClock*offset/2); return 1; } @@ -664,27 +664,27 @@ int ASKbiphaseDemod(const char *Cmd, bool verbose) //ask raw demod GraphBuffer first int offset=0, clk=0, invert=0, maxErr=0; sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr); - + uint8_t BitStream[MAX_DEMOD_BUF_LEN]; - size_t size = getFromGraphBuf(BitStream); + size_t size = getFromGraphBuf(BitStream); if (size == 0 ) { - PrintAndLogEx(DEBUG, "DEBUG: no data in graphbuf"); - return 0; + PrintAndLogEx(DEBUG, "DEBUG: no data in graphbuf"); + return 0; } - int startIdx = 0; + int startIdx = 0; //invert here inverts the ask raw demoded bits which has no effect on the demod, but we need the pointer - int errCnt = askdemod_ext(BitStream, &size, &clk, &invert, maxErr, 0, 0, &startIdx); - if ( errCnt < 0 || errCnt > maxErr ) { - PrintAndLogEx(DEBUG, "DEBUG: no data or error found %d, clock: %d", errCnt, clk); - return 0; - } + int errCnt = askdemod_ext(BitStream, &size, &clk, &invert, maxErr, 0, 0, &startIdx); + if ( errCnt < 0 || errCnt > maxErr ) { + PrintAndLogEx(DEBUG, "DEBUG: no data or error found %d, clock: %d", errCnt, clk); + return 0; + } //attempt to Biphase decode BitStream errCnt = BiphaseRawDecode(BitStream, &size, &offset, invert); if (errCnt < 0){ if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode: %d", errCnt); return 0; - } + } if (errCnt > maxErr) { if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode too many errors: %d", errCnt); return 0; @@ -712,16 +712,16 @@ int Cmdaskrawdemod(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ar(); - + return ASKDemod(Cmd, true, false, 0); } int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph, bool verbose) { // sanity check if ( window > len ) window = len; - + if (verbose) PrintAndLogEx(INFO, "performing %d correlations", GraphTraceLen - window); - + //test double autocv = 0.0; // Autocovariance value double ac_value; // Computed autocorrelation value to be returned @@ -729,13 +729,13 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph double mean; size_t correlation = 0; int lastmax = 0; - + // in, len, 4000 mean = compute_mean(in, len); variance = compute_variance(in, len); - + static int CorrelBuffer[MAX_GRAPH_TRACE_LEN]; - + for (int i = 0; i < len - window; ++i) { for (size_t j=0; j < (len - i); j++) { @@ -744,7 +744,7 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph autocv = (1.0 / (len - i)) * autocv; CorrelBuffer[i] = autocv; - + // Autocorrelation is autocovariance divided by variance ac_value = autocv / variance; @@ -754,8 +754,8 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph lastmax = i; } } - - // + + // int hi = 0, idx = 0; int distance = 0, hi_1 = 0, idx_1 = 0; for (int i = 0; i <= len; ++i){ @@ -764,7 +764,7 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph idx = i; } } - + for (int i = idx+1; i <= window; ++i){ if ( CorrelBuffer[i] > hi_1 ) { hi_1 = CorrelBuffer[i]; @@ -773,7 +773,7 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph } int foo = ABS(hi-hi_1); - int bar = (int)((int)((hi+hi_1) / 2) * 0.03); + int bar = (int)((int)((hi+hi_1) / 2) * 0.03); if ( verbose && foo < bar ) { distance = idx_1 - idx; PrintAndLogEx(SUCCESS, "possible 3% visible correlation %4d samples", distance); @@ -782,7 +782,7 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph } else { PrintAndLogEx(FAILED, "no repeating pattern found, try increasing window size"); } - + int retval = correlation; if (SaveGrph) { //GraphTraceLen = GraphTraceLen - window; @@ -792,14 +792,14 @@ int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph retval = distance; } else - setClockGrid(correlation, idx); - + setClockGrid(correlation, idx); + CursorCPos = idx_1; CursorDPos = idx_1+retval; DemodBufferLen = 0; - RepaintGraphWindow(); + RepaintGraphWindow(); } - + return retval; } @@ -809,7 +809,7 @@ int CmdAutoCorr(const char *Cmd) { uint8_t cmdp = 0; bool updateGrph = false; bool errors = false; - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': @@ -818,7 +818,7 @@ int CmdAutoCorr(const char *Cmd) { updateGrph = true; cmdp++; break; - case 'w': + case 'w': window = param_get32ex(Cmd, cmdp+1, 4000, 10); if (window >= GraphTraceLen) { PrintAndLogEx(WARNING, "window must be smaller than trace (%d samples)", GraphTraceLen); @@ -834,7 +834,7 @@ int CmdAutoCorr(const char *Cmd) { } //Validations if (errors || cmdp == 0 ) return usage_data_autocorr(); - + return AutoCorrelate(GraphBuffer, GraphBuffer, GraphTraceLen, window, updateGrph, true); } @@ -847,7 +847,7 @@ int CmdBitsamples(const char *Cmd) PrintAndLogEx(WARNING, "command execution time out"); return false; } - + for (int j = 0; j < sizeof(got); j++) { for (int k = 0; k < 8; k++) { if(got[j] & (1 << (7 - k))) @@ -865,7 +865,7 @@ int CmdBuffClear(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); if (cmdp == 'h' || cmdp == 'H') return usage_data_buffclear(); - + UsbCommand c = {CMD_BUFF_CLEAR, {0,0,0}}; clearCommandBuffer(); SendCommand(&c); @@ -924,12 +924,12 @@ int CmdGraphShiftZero(const char *Cmd) { for(int i = 0; i < GraphTraceLen; i++){ if ( i+shift >= GraphTraceLen) shiftedVal = GraphBuffer[i]; - else + else shiftedVal = GraphBuffer[i] + shift; - - if (shiftedVal > 127) + + if (shiftedVal > 127) shiftedVal = 127; - else if (shiftedVal < -127) + else if (shiftedVal < -127) shiftedVal = -127; GraphBuffer[i] = shiftedVal; } @@ -951,12 +951,12 @@ int AskEdgeDetect(const int *in, int *out, int len, int threshold) { //by marshmellow //use large jumps in read samples to identify edges of waves and then amplify that wave to max -//similar to dirtheshold, threshold commands +//similar to dirtheshold, threshold commands //takes a threshold length which is the measured length between two samples then determines an edge int CmdAskEdgeDetect(const char *Cmd) { int thresLen = 25; int ans = 0; - sscanf(Cmd, "%i", &thresLen); + sscanf(Cmd, "%i", &thresLen); ans = AskEdgeDetect(GraphBuffer, GraphBuffer, GraphTraceLen, thresLen); RepaintGraphWindow(); @@ -996,23 +996,23 @@ int CmdDetectClockRate(const char *Cmd) { char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert) { static char fType[8]; - memset(fType, 0x00, 8); + memset(fType, 0x00, 8); char *fskType = fType; - + if (fchigh == 10 && fclow == 8){ - + if (invert) memcpy(fskType, "FSK2a", 5); else memcpy(fskType, "FSK2", 4); - + } else if (fchigh == 8 && fclow == 5) { - + if (invert) memcpy(fskType, "FSK1", 4); else memcpy(fskType, "FSK1a", 5); - + } else { memcpy(fskType, "FSK??", 5); } @@ -1033,7 +1033,7 @@ int FSKrawDemod(const char *Cmd, bool verbose) { invert = param_get8(Cmd, 1); fchigh = param_get8(Cmd, 2); fclow = param_get8(Cmd, 3); - + if (strlen(Cmd) > 0 && strlen(Cmd) <= 2) { if (rfLen == 1) { invert = 1; //if invert option only is used @@ -1044,7 +1044,7 @@ int FSKrawDemod(const char *Cmd, bool verbose) { uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; size_t BitLen = getFromGraphBuf(bits); if (BitLen == 0) return 0; - + //get field clock lengths uint16_t fcs = 0; if (!fchigh || !fclow) { @@ -1115,7 +1115,7 @@ int PSKDemod(const char *Cmd, bool verbose) { if (errCnt > maxErr){ if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); return 0; - } + } if (errCnt < 0|| BitLen < 16){ //throw away static - allow 1 and -1 (in case of threshold command first) if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); return 0; @@ -1154,7 +1154,7 @@ int CmdPSKIdteck(const char *Cmd) { PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: size not correct: %d", size); else PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: idx: %d",idx); - + // if didn't find preamble try again inverting if (!PSKDemod("1", false)) { PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed"); @@ -1162,11 +1162,11 @@ int CmdPSKIdteck(const char *Cmd) { } idx = detectIdteck(DemodBuffer, &size); if (idx < 0){ - + if (idx == -1) PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: not enough samples"); else if (idx == -2) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: just noise"); + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: just noise"); else if (idx == -3) PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: preamble not found"); else if (idx == -4) @@ -1175,15 +1175,15 @@ int CmdPSKIdteck(const char *Cmd) { PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: idx: %d",idx); return 0; - } + } } setDemodBuf(DemodBuffer, 64, idx); - + //got a good demod uint32_t id = 0; uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); - + //parity check (TBD) //checksum check (TBD) @@ -1205,22 +1205,22 @@ int NRZrawDemod(const char *Cmd, bool verbose) { invert = 1; clk = 0; } - + if (invert != 0 && invert != 1) { PrintAndLogEx(WARNING, "(NRZrawDemod) Invalid argument: %s", Cmd); return 0; } - + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; size_t BitLen = getFromGraphBuf(bits); - + if (BitLen == 0) return 0; - + errCnt = nrzRawDemod(bits, &BitLen, &clk, &invert, &clkStartIdx); if (errCnt > maxErr){ PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt); return 0; - } + } if (errCnt < 0 || BitLen < 16){ //throw away static - allow 1 and -1 (in case of threshold command first) PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); return 0; @@ -1237,7 +1237,7 @@ int NRZrawDemod(const char *Cmd, bool verbose) { // Now output the bitstream to the scrollback by line of 16 bits printDemodBuff(); } - return 1; + return 1; } int CmdNRZrawDemod(const char *Cmd) { @@ -1258,7 +1258,7 @@ int CmdPSK1rawDemod(const char *Cmd) { int ans = PSKDemod(Cmd, true); //output if (!ans){ - if (g_debugMode) PrintAndLogEx(WARNING, "Error demoding: %d",ans); + if (g_debugMode) PrintAndLogEx(WARNING, "Error demoding: %d",ans); return 0; } PrintAndLogEx(NORMAL, "PSK1 demoded bitstream:"); @@ -1275,13 +1275,13 @@ int CmdPSK2rawDemod(const char *Cmd) { int ans = PSKDemod(Cmd, true); if (!ans){ - if (g_debugMode) PrintAndLogEx(WARNING, "Error demoding: %d",ans); + if (g_debugMode) PrintAndLogEx(WARNING, "Error demoding: %d",ans); return 0; - } + } psk1TOpsk2(DemodBuffer, DemodBufferLen); PrintAndLogEx(NORMAL, "PSK2 demoded bitstream:"); // Now output the bitstream to the scrollback by line of 16 bits - printDemodBuff(); + printDemodBuff(); return 1; } @@ -1291,7 +1291,7 @@ int CmdRawDemod(const char *Cmd) { if (strlen(Cmd) > 35 || strlen(Cmd) < 2) return usage_data_rawdemod(); - + str_lower( (char *)Cmd); if (str_startswith(Cmd, "fs")) ans = CmdFSKrawdemod(Cmd+2); @@ -1355,7 +1355,7 @@ int CmdHexsamples(const char *Cmd) { /* if no args send something */ if (requested == 0) requested = 8; - + if (offset + requested > sizeof(got)) { PrintAndLogEx(NORMAL, "Tried to read past end of buffer, + > %d", BIGBUF_SIZE); return 0; @@ -1365,7 +1365,7 @@ int CmdHexsamples(const char *Cmd) { PrintAndLogEx(WARNING, "command execution time out"); return false; } - + i = 0; for (j = 0; j < requested; j++) { i++; @@ -1438,7 +1438,7 @@ int getSamples(int n, bool silent) { } if (!silent) PrintAndLogEx(NORMAL, "Data fetched"); - + uint8_t bits_per_sample = 8; //Old devices without this feature would send 0 at arg[0] @@ -1447,11 +1447,11 @@ int getSamples(int n, bool silent) { if (!silent) PrintAndLogEx(NORMAL, "Samples @ %d bits/smpl, decimation 1:%d ", sc->bits_per_sample, sc->decimation); bits_per_sample = sc->bits_per_sample; } - + if (bits_per_sample < 8) { - + if (!silent) PrintAndLogEx(NORMAL, "Unpacking..."); - + BitstreamOut bout = { got, bits_per_sample * n, 0}; int j =0; for (j = 0; j * bits_per_sample < n * 8 && j < n; j++) { @@ -1459,9 +1459,9 @@ int getSamples(int n, bool silent) { GraphBuffer[j] = ((int) sample )- 128; } GraphTraceLen = j; - + if (!silent) PrintAndLogEx(NORMAL, "Unpacked %d samples" , j ); - + } else { for (int j = 0; j < n; j++) { GraphBuffer[j] = ((int)got[j]) - 128; @@ -1497,8 +1497,8 @@ int CmdTuneSamples(const char *Cmd) { DemodBufferLen = 0; setClockGrid(0, 0); RepaintGraphWindow(); - - + + int timeout = 0; PrintAndLogEx(INFO, "\nmeasuring antenna characteristics, please wait..."); @@ -1515,14 +1515,14 @@ int CmdTuneSamples(const char *Cmd) { } } PrintAndLogEx(NORMAL, "\n"); - + uint32_t v_lf125 = resp.arg[0]; uint32_t v_lf134 = resp.arg[0] >> 32; - + uint32_t v_hf = resp.arg[1]; uint32_t peakf = resp.arg[2]; uint32_t peakv = resp.arg[2] >> 32; - + if ( v_lf125 > NON_VOLTAGE ) PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - 125.00 kHz", (v_lf125 * ANTENNA_ERROR)/1000.0); if ( v_lf134 > NON_VOLTAGE ) @@ -1531,7 +1531,7 @@ int CmdTuneSamples(const char *Cmd) { PrintAndLogEx(SUCCESS, "LF optimal: %5.2f V - %6.2f kHz", (peakv * ANTENNA_ERROR)/1000.0, 12000.0/(peakf+1)); char judgement[20]; - memset(judgement, 0, sizeof(judgement)); + memset(judgement, 0, sizeof(judgement)); // LF evaluation if (peakv < LF_UNUSABLE_V) sprintf(judgement, _RED_(UNUSABLE) ); @@ -1539,25 +1539,25 @@ int CmdTuneSamples(const char *Cmd) { sprintf(judgement, _YELLOW_(MARGINAL) ); else sprintf(judgement, _GREEN_(OK) ); - + PrintAndLogEx(NORMAL, "%sLF antenna is %s \n" , (peakv < LF_UNUSABLE_V) ? _CYAN_([!]) : _GREEN_([+]) , judgement ); - + // HF evaluation if ( v_hf > NON_VOLTAGE ) PrintAndLogEx(SUCCESS, "HF antenna: %5.2f V - 13.56 MHz", (v_hf * ANTENNA_ERROR)/1000.0); memset(judgement, 0, sizeof(judgement)); - - if (v_hf < HF_UNUSABLE_V) + + if (v_hf < HF_UNUSABLE_V) sprintf(judgement, _RED_(UNUSABLE) ); else if (v_hf < HF_MARGINAL_V) sprintf(judgement, _YELLOW_(MARGINAL) ); else sprintf(judgement, _GREEN_(OK) ); - + PrintAndLogEx(NORMAL, "%sHF antenna is %s" , (v_hf < HF_UNUSABLE_V) ? _CYAN_([!]) : _GREEN_([+]) , judgement @@ -1590,7 +1590,7 @@ int CmdLoad(const char *Cmd) { len = strlen(Cmd); if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; memcpy(filename, Cmd, len); - + FILE *f = fopen(filename, "r"); if (!f) { PrintAndLogEx(WARNING, "couldn't open '%s'", filename); @@ -1607,7 +1607,7 @@ int CmdLoad(const char *Cmd) { fclose(f); PrintAndLogEx(SUCCESS, "loaded %d samples", GraphTraceLen); - + uint8_t bits[GraphTraceLen]; size_t size = getFromGraphBuf(bits); // set signal properties low/high/mean/amplitude and is_noise detection @@ -1639,7 +1639,7 @@ int CmdLtrim(const char *Cmd) { // trim graph from the beginning int CmdRtrim(const char *Cmd) { - + int ds = atoi(Cmd); // sanitycheck @@ -1656,7 +1656,7 @@ int CmdMtrim(const char *Cmd) { sscanf(Cmd, "%i %i", &start, &stop); if (start > GraphTraceLen || stop > GraphTraceLen || start > stop) return 1; - + // leave start position sample start++; @@ -1706,7 +1706,7 @@ int CmdSave(const char *Cmd) { len = strlen(Cmd); if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; memcpy(filename, Cmd, len); - + FILE *f = fopen(filename, "w"); if(!f) { PrintAndLogEx(WARNING, "couldn't open '%s'", filename); @@ -1736,10 +1736,10 @@ int CmdScale(const char *Cmd) { int directionalThreshold(const int* in, int *out, size_t len, int8_t up, int8_t down) { int lastValue = in[0]; - + // Will be changed at the end, but init 0 as we adjust to last samples // value if no threshold kicks in. - out[0] = 0; + out[0] = 0; for (size_t i = 1; i < len; ++i) { // Apply first threshold to samples heading up @@ -1760,9 +1760,9 @@ int directionalThreshold(const int* in, int *out, size_t len, int8_t up, int8_t out[i] = out[i-1]; } } - + // Align with first edited sample. - out[0] = out[1]; + out[0] = out[1]; return 0; } @@ -1773,7 +1773,7 @@ int CmdDirectionalThreshold(const char *Cmd) { PrintAndLogEx(INFO, "Applying Up Threshold: %d, Down Threshold: %d\n", up, down); directionalThreshold(GraphBuffer, GraphBuffer, GraphTraceLen, up, down); - + // set signal properties low/high/mean/amplitude and isnoice detection uint8_t bits[GraphTraceLen]; size_t size = getFromGraphBuf(bits); @@ -1836,9 +1836,9 @@ int Cmdbin2hex(const char *Cmd) { char c = Cmd[bg]; if( c == '1') pushBit(&bout, 1); - else if( c == '0') + else if( c == '0') pushBit(&bout, 0); - else + else PrintAndLogEx(NORMAL, "Ignoring '%c'", c); } @@ -1901,7 +1901,7 @@ void GetHiLoTone(int *LowTone, int *HighTone, int clk, int LowToneFC, int HighTo //int HighToneMod = clk mod HighToneFC; int LeftHalfFCCnt = (LowToneFC % 2) + (LowToneFC/2); //truncate int FCs_per_clk = clk / LowToneFC; - + // need to correctly split up the clock to field clocks. // First attempt uses modifiers on each end to make up for when FCs don't evenly divide into Clk @@ -1955,7 +1955,7 @@ void GetHiLoTone(int *LowTone, int *HighTone, int clk, int LowToneFC, int HighTo } } -//old CmdFSKdemod adapted by marshmellow +//old CmdFSKdemod adapted by marshmellow //converts FSK to clear NRZ style wave. (or demodulates) int FSKToNRZ(int *data, int *dataLen, int clk, int LowToneFC, int HighToneFC) { uint8_t ans = 0; @@ -1973,7 +1973,7 @@ int FSKToNRZ(int *data, int *dataLen, int clk, int LowToneFC, int HighToneFC) { } return 0; } - + int i, j; int LowTone[clk]; int HighTone[clk]; @@ -1996,7 +1996,7 @@ int FSKToNRZ(int *data, int *dataLen, int clk, int LowToneFC, int HighToneFC) { } // now we have the abs( [average sample value per clk] * 100 ) for each tone - // loop through again [all samples] - clk - 16 + // loop through again [all samples] - clk - 16 // note why 16??? is 16 the largest FC? changed to LowToneFC as that should be the > fc for(i = 0; i < *dataLen - clk - LowToneFC; ++i) { int lowTot = 0, highTot = 0; @@ -2009,8 +2009,8 @@ int FSKToNRZ(int *data, int *dataLen, int clk, int LowToneFC, int HighToneFC) { highTot += (data[i + j] >> 16); } - // subtract the sum of lowTone averages by the sum of highTone averages as it - // and write back the new graph value + // subtract the sum of lowTone averages by the sum of highTone averages as it + // and write back the new graph value data[i] = lowTot - highTot; } // update dataLen to what we put back to the data sample buffer @@ -2019,7 +2019,7 @@ int FSKToNRZ(int *data, int *dataLen, int clk, int LowToneFC, int HighToneFC) { } int CmdFSKToNRZ(const char *Cmd) { - // take clk, fc_low, fc_high + // take clk, fc_low, fc_high // blank = auto; bool errors = false; char cmdp = 0; @@ -2097,7 +2097,7 @@ static command_t CommandTable[] = { {"norm", CmdNorm, 1, "Normalize max/min to +/-128"}, {"plot", CmdPlot, 1, "Show graph window (hit 'h' in window for keystroke help)"}, {"printdemodbuffer",CmdPrintDemodBuff, 1, "[x] [o] [l] -- print the data in the DemodBuffer - 'x' for hex output"}, - {"rawdemod", CmdRawDemod, 1, "[modulation] ... -see help (h option) -- Demodulate the data in the GraphBuffer and output binary"}, + {"rawdemod", CmdRawDemod, 1, "[modulation] ... -see help (h option) -- Demodulate the data in the GraphBuffer and output binary"}, {"samples", CmdSamples, 0, "[512 - 40000] -- Get raw samples for graph window (GraphBuffer)"}, {"save", CmdSave, 1, " -- Save trace (from graph window)"}, {"setgraphmarkers", CmdSetGraphMarkers, 1, "[orange_marker] [blue_marker] (in graph window)"}, diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index cedb9516d..b576f43f7 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -29,7 +29,7 @@ static int CmdHelp(const char *Cmd); int usage_flashmem_spibaud(void){ PrintAndLogEx(NORMAL, "Usage: mem spibaud [h] "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " SPI baudrate in MHz [24|48]"); PrintAndLogEx(NORMAL, " "); PrintAndLogEx(NORMAL, " If >= 24Mhz, FASTREADS instead of READS instruction will be used."); @@ -48,7 +48,7 @@ int usage_flashmem_read(void){ PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " mem read o 0 l 32"); // read 32 bytes starting at offset 0 - PrintAndLogEx(NORMAL, " mem read o 1024 l 10"); // read 10 bytes starting at offset 1024 + PrintAndLogEx(NORMAL, " mem read o 1024 l 10"); // read 10 bytes starting at offset 1024 return 0; } int usage_flashmem_load(void){ @@ -82,7 +82,7 @@ int usage_flashmem_save(void){ return 0; } int usage_flashmem_wipe(void){ - + PrintAndLogEx(WARNING, "[OBS] use with caution."); PrintAndLogEx(NORMAL, "Wipe flash memory on device, which fills memory with 0xFF\n"); @@ -104,7 +104,7 @@ int usage_flashmem_info(void){ PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " mem info"); PrintAndLogEx(NORMAL, " mem info s"); - return 0; + return 0; } int CmdFlashMemRead(const char *Cmd) { @@ -112,7 +112,7 @@ int CmdFlashMemRead(const char *Cmd) { uint8_t cmdp = 0; bool errors = false; uint32_t start_index = 0, len = 0; - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'o': @@ -121,7 +121,7 @@ int CmdFlashMemRead(const char *Cmd) { break; case 'l': len = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; + cmdp += 2; break; case 'h': return usage_flashmem_read(); @@ -131,16 +131,16 @@ int CmdFlashMemRead(const char *Cmd) { break; } } - + //Validations - if (errors || cmdp == 0 ) return usage_flashmem_read(); - + if (errors || cmdp == 0 ) return usage_flashmem_read(); + if (start_index + len > FLASH_MEM_MAX_SIZE) { PrintAndLogDevice(WARNING, "error, start_index + length is larger than available memory"); return 1; } - UsbCommand c = {CMD_FLASHMEM_READ, {start_index, len, 0}}; + UsbCommand c = {CMD_FLASHMEM_READ, {start_index, len, 0}}; clearCommandBuffer(); SendCommand(&c); return 0; @@ -161,11 +161,11 @@ int CmdFlashmemSpiBaudrate(const char *Cmd) { int CmdFlashMemLoad(const char *Cmd){ uint32_t start_index = 0; - char filename[FILE_PATH_SIZE] = {0}; + char filename[FILE_PATH_SIZE] = {0}; bool errors = false; - uint8_t cmdp = 0; + uint8_t cmdp = 0; Dictionary_t d = DICTIONARY_NONE; - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': @@ -175,8 +175,8 @@ int CmdFlashMemLoad(const char *Cmd){ PrintAndLogEx(FAILED, "Filename too long"); errors = true; break; - } - cmdp += 2; + } + cmdp += 2; break; case 'o': start_index = param_get32ex(Cmd, cmdp+1, 0, 10); @@ -200,15 +200,15 @@ int CmdFlashMemLoad(const char *Cmd){ break; } } - + //Validations - if (errors || cmdp == 0 ) return usage_flashmem_load(); + if (errors || cmdp == 0 ) return usage_flashmem_load(); size_t datalen = 0; uint16_t keycount = 0; int res = 0; uint8_t *data = calloc(FLASH_MEM_MAX_SIZE, sizeof(uint8_t)); - + switch (d) { case DICTIONARY_MIFARE: start_index = DEFAULT_MF_KEYS_OFFSET; @@ -218,8 +218,8 @@ int CmdFlashMemLoad(const char *Cmd){ return 1; } data[0] = (keycount >> 0) & 0xFF; - data[1] = (keycount >> 8) & 0xFF; - datalen += 2; + data[1] = (keycount >> 8) & 0xFF; + datalen += 2; break; case DICTIONARY_T55XX: start_index = DEFAULT_T55XX_KEYS_OFFSET; @@ -229,7 +229,7 @@ int CmdFlashMemLoad(const char *Cmd){ return 1; } data[0] = (keycount >> 0) & 0xFF; - data[1] = (keycount >> 8) & 0xFF; + data[1] = (keycount >> 8) & 0xFF; datalen += 2; break; case DICTIONARY_ICLASS: @@ -240,26 +240,26 @@ int CmdFlashMemLoad(const char *Cmd){ return 1; } data[0] = (keycount >> 0) & 0xFF; - data[1] = (keycount >> 8) & 0xFF; - datalen += 2; + data[1] = (keycount >> 8) & 0xFF; + datalen += 2; break; default: - + res = loadFile(filename, "bin", data, &datalen); //int res = loadFileEML( filename, "eml", data, &datalen); if ( res ) { free(data); return 1; } - + if (datalen > FLASH_MEM_MAX_SIZE) { PrintAndLogDevice(WARNING, "error, filesize is larger than available memory"); free(data); return 1; } - break; + break; } - + data = realloc(data, datalen); //Send to device @@ -268,40 +268,40 @@ int CmdFlashMemLoad(const char *Cmd){ while (bytes_remaining > 0){ uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); - + UsbCommand c = {CMD_FLASHMEM_WRITE, {start_index + bytes_sent, bytes_in_packet, 0}}; - + memcpy(c.d.asBytes, data + bytes_sent, bytes_in_packet); clearCommandBuffer(); SendCommand(&c); bytes_remaining -= bytes_in_packet; bytes_sent += bytes_in_packet; - + UsbCommand resp; if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); free(data); return 1; } - + uint8_t isok = resp.arg[0] & 0xFF; if (!isok) PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent); - + } free(data); - + PrintAndLogEx(SUCCESS, "Wrote %u bytes to offset %u", datalen, start_index); return 0; } int CmdFlashMemSave(const char *Cmd){ - char filename[FILE_PATH_SIZE] = {0}; + char filename[FILE_PATH_SIZE] = {0}; uint8_t cmdp = 0; bool errors = false; uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE; - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_flashmem_save(); @@ -319,8 +319,8 @@ int CmdFlashMemSave(const char *Cmd){ PrintAndLogEx(FAILED, "Filename too long"); errors = true; break; - } - cmdp += 2; + } + cmdp += 2; break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); @@ -328,7 +328,7 @@ int CmdFlashMemSave(const char *Cmd){ break; } } - + //Validations if (errors || cmdp == 0 ) return usage_flashmem_save(); @@ -337,7 +337,7 @@ int CmdFlashMemSave(const char *Cmd){ PrintAndLogDevice(WARNING, "error, cannot allocate memory "); return 1; } - + PrintAndLogEx(NORMAL, "downloading %u bytes from flashmem", len); if ( !GetFromDevice(FLASH_MEM, dump, len, start_index, NULL, -1, true) ) { PrintAndLogEx(FAILED, "ERROR; downloading flashmem"); @@ -355,10 +355,10 @@ int CmdFlashMemWipe(const char *Cmd){ uint8_t cmdp = 0; bool errors = false; bool initalwipe = false; - uint8_t page = 0; + uint8_t page = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': return usage_flashmem_wipe(); + case 'h': return usage_flashmem_wipe(); case 'p': page = param_get8ex(Cmd, cmdp+1, 0, 10); if ( page > 2 ) { @@ -378,10 +378,10 @@ int CmdFlashMemWipe(const char *Cmd){ break; } } - + //Validations - if (errors || cmdp == 0 ) return usage_flashmem_wipe(); - + if (errors || cmdp == 0 ) return usage_flashmem_wipe(); + UsbCommand c = {CMD_FLASHMEM_WIPE, {page, initalwipe, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -393,7 +393,7 @@ int CmdFlashMemWipe(const char *Cmd){ uint8_t isok = resp.arg[0] & 0xFF; if (isok) PrintAndLogEx(SUCCESS, "Flash WIPE ok"); - else + else PrintAndLogEx(FAILED, "Flash WIPE failed"); return 0; @@ -402,18 +402,18 @@ int CmdFlashMemInfo(const char *Cmd){ uint8_t sha_hash[20] = {0}; mbedtls_rsa_context rsa; - + uint8_t cmdp = 0; bool errors = false, shall_write = false, shall_sign = false; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': return usage_flashmem_info(); + case 'h': return usage_flashmem_info(); case 's': { shall_sign = true; cmdp++; break; } - case 'w': + case 'w': shall_write = true; cmdp++; break; @@ -423,10 +423,10 @@ int CmdFlashMemInfo(const char *Cmd){ break; } } - + //Validations if (errors ) return usage_flashmem_info(); - + UsbCommand c = {CMD_FLASHMEM_INFO, {0, 0, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -435,12 +435,12 @@ int CmdFlashMemInfo(const char *Cmd){ PrintAndLogEx(WARNING, "timeout while waiting for reply."); return 1; } - + uint8_t isok = resp.arg[0] & 0xFF; if (!isok) { PrintAndLogEx(FAILED, "failed"); return 1; - } + } // validate signature here rdv40_validation_t mem; @@ -448,18 +448,18 @@ int CmdFlashMemInfo(const char *Cmd){ // Flash ID hash (sha1) mbedtls_sha1( mem.flashid, sizeof(mem.flashid), sha_hash ); - + // print header PrintAndLogEx(INFO, "\n--- Flash memory Information ---------"); - PrintAndLogEx(INFO, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); PrintAndLogEx(INFO, "ID | %s", sprint_hex(mem.flashid, sizeof(mem.flashid) )); PrintAndLogEx(INFO, "SHA1 | %s", sprint_hex(sha_hash, sizeof(sha_hash))); PrintAndLogEx(INFO, "RSA SIGNATURE |"); print_hex_break( mem.signature, sizeof(mem.signature), 32); -//------------------------------------------------------------------------------- +//------------------------------------------------------------------------------- // Example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c) -// +// // public key modulus N #define RSA_N "9292758453063D803DD603D5E777D788" \ @@ -484,7 +484,7 @@ int CmdFlashMemInfo(const char *Cmd){ "AF1FEDFDDE2BEB674CA15F3E81A1521E" \ "071513A1E85B5DFA031F21ECAE91A34D" -// prime P +// prime P #define RSA_P "C36D0EB7FCD285223CFB5AABA5BDA3D8" \ "2C01CAD19EA484A87EA4377637E75500" \ "FCB2005C5C7DD6EC4AC023CDA285D796" \ @@ -511,7 +511,7 @@ int CmdFlashMemInfo(const char *Cmd){ "F5A3B2A5D33605AEBBCCBA7FEB9F2D2F" \ "A74206CEC169D74BF5A8C50D6F48EA08" - + #define KEY_LEN 128 mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0); @@ -528,53 +528,53 @@ int CmdFlashMemInfo(const char *Cmd){ mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ); PrintAndLogEx(INFO, "KEY length | %d", KEY_LEN); - + bool is_keyok = ( mbedtls_rsa_check_pubkey( &rsa ) == 0 || mbedtls_rsa_check_privkey( &rsa ) == 0 ); if (is_keyok) PrintAndLogEx(SUCCESS, "RSA key validation ok"); else PrintAndLogEx(FAILED, "RSA key validation failed"); - - // + + // uint8_t from_device[KEY_LEN]; uint8_t sign[KEY_LEN]; // to be verified memcpy(from_device, mem.signature, KEY_LEN); - + // to be signed (all zeros memset(sign, 0, KEY_LEN); - + // Signing (private key) if (shall_sign) { - + int is_signed = mbedtls_rsa_pkcs1_sign( &rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign ); - if (is_signed == 0) + if (is_signed == 0) PrintAndLogEx(SUCCESS, "RSA Signing ok"); else PrintAndLogEx(FAILED, "RSA Signing failed"); if (shall_write) { // save to mem - c = (UsbCommand){CMD_FLASHMEM_WRITE, {FLASH_MEM_SIGNATURE_OFFSET, FLASH_MEM_SIGNATURE_LEN, 0}}; - memcpy(c.d.asBytes, sign, sizeof(sign)); + c = (UsbCommand){CMD_FLASHMEM_WRITE, {FLASH_MEM_SIGNATURE_OFFSET, FLASH_MEM_SIGNATURE_LEN, 0}}; + memcpy(c.d.asBytes, sign, sizeof(sign)); clearCommandBuffer(); SendCommand(&c); if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); } else { - + if (!resp.arg[0]) PrintAndLogEx(FAILED, "Writing signature failed"); else PrintAndLogEx(SUCCESS, "Writing signature ok [offset: %u]", FLASH_MEM_SIGNATURE_OFFSET); - + } } PrintAndLogEx(INFO, "Signed | "); print_hex_break( sign, sizeof(sign), 32); } - + // Verify (public key) int is_verified = mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device ); if (is_verified == 0) diff --git a/client/cmdhf.c b/client/cmdhf.c index cb4e424da..af5aa4c2b 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -38,14 +38,14 @@ int usage_hf_snoop(){ int CmdHFSearch(const char *Cmd){ - char cmdp = param_getchar(Cmd, 0); + char cmdp = param_getchar(Cmd, 0); if (cmdp == 'h' || cmdp == 'H') return usage_hf_search(); - + int ans = CmdHF14AInfo("s"); if (ans > 0) { PrintAndLogEx(SUCCESS, "\nValid ISO14443-A Tag Found\n"); return ans; - } + } ans = HF15Reader("", false); if (ans) { PrintAndLogEx(SUCCESS, "\nValid ISO15693 Tag Found\n"); @@ -80,7 +80,7 @@ int CmdHFSearch(const char *Cmd){ return ans; } */ - + PrintAndLogEx(FAILED, "\nno known/supported 13.56 MHz tags found\n"); return 0; } @@ -94,12 +94,12 @@ int CmdHFTune(const char *Cmd) { } int CmdHFSnoop(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); + char cmdp = param_getchar(Cmd, 0); if (cmdp == 'h' || cmdp == 'H') return usage_hf_snoop(); - + int skippairs = param_get32ex(Cmd, 0, 0, 10); int skiptriggers = param_get32ex(Cmd, 1, 0, 10); - + UsbCommand c = {CMD_HF_SNIFFER, {skippairs, skiptriggers, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -121,7 +121,7 @@ static command_t CommandTable[] = { {"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"}, {"topaz", CmdHFTopaz, 1, "{ TOPAZ (NFC Type 1) RFIDs... }"}, {"fido", CmdHFFido, 1, "{ FIDO and FIDO2 authenticators... }"}, - {"list", CmdTraceList, 0, "List protocol data in trace buffer"}, + {"list", CmdTraceList, 0, "List protocol data in trace buffer"}, {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, {"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"}, {"snoop", CmdHFSnoop, 0, " Generic HF Snoop"}, @@ -131,7 +131,7 @@ static command_t CommandTable[] = { int CmdHF(const char *Cmd) { clearCommandBuffer(); CmdsParse(CommandTable, Cmd); - return 0; + return 0; } int CmdHelp(const char *Cmd) { diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 27f670fac..90753fef8 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -21,14 +21,14 @@ static const manufactureName manufactureMapping[] = { // ID, "Vendor Country" { 0x01, "Motorola UK" }, { 0x02, "ST Microelectronics SA France" }, - { 0x03, "Hitachi, Ltd Japan" }, - { 0x04, "NXP Semiconductors Germany" }, - { 0x05, "Infineon Technologies AG Germany" }, - { 0x06, "Cylink USA" }, + { 0x03, "Hitachi, Ltd Japan" }, + { 0x04, "NXP Semiconductors Germany" }, + { 0x05, "Infineon Technologies AG Germany" }, + { 0x06, "Cylink USA" }, { 0x07, "Texas Instrument France" }, - { 0x08, "Fujitsu Limited Japan" }, - { 0x09, "Matsushita Electronics Corporation, Semiconductor Company Japan" }, - { 0x0A, "NEC Japan" }, + { 0x08, "Fujitsu Limited Japan" }, + { 0x09, "Matsushita Electronics Corporation, Semiconductor Company Japan" }, + { 0x0A, "NEC Japan" }, { 0x0B, "Oki Electric Industry Co. Ltd Japan" }, { 0x0C, "Toshiba Corp. Japan" }, { 0x0D, "Mitsubishi Electric Corp. Japan" }, @@ -69,7 +69,7 @@ static const manufactureName manufactureMapping[] = { { 0x30, "BeeDar Technology Inc. USA" }, { 0x31, "RFIDsec Denmark" }, { 0x32, "Schweizer Electronic AG Germany" }, - { 0x33, "AMIC Technology Corp Taiwan" }, + { 0x33, "AMIC Technology Corp Taiwan" }, { 0x34, "Mikron JSC Russia" }, { 0x35, "Fraunhofer Institute for Photonic Microsystems Germany" }, { 0x36, "IDS Microchip AG Switzerland" }, @@ -81,7 +81,7 @@ static const manufactureName manufactureMapping[] = { { 0x3C, "Verayo Inc. USA" }, { 0x3D, "HID Global USA" }, { 0x3E, "Productivity Engineering Gmbh Germany" }, - { 0x3F, "Austriamicrosystems AG (reserved) Austria" }, + { 0x3F, "Austriamicrosystems AG (reserved) Austria" }, { 0x40, "Gemalto SA France" }, { 0x41, "Renesas Electronics Corporation Japan" }, { 0x42, "3Alogics Inc Korea" }, @@ -129,24 +129,24 @@ static const manufactureName manufactureMapping[] = { { 0x6C, "Wisesec Ltd Israel" }, { 0x7C, "DB HiTek Co Ltd Korea" }, { 0x7D, "SATO Vicinity Australia" }, - { 0x7E, "Holtek Taiwan" }, + { 0x7E, "Holtek Taiwan" }, { 0x00, "no tag-info available" } // must be the last entry }; // get a product description based on the UID // uid[8] tag uid -// returns description of the best match +// returns description of the best match char* getTagInfo(uint8_t uid) { int i; int len = sizeof(manufactureMapping) / sizeof(manufactureName); - - for ( i = 0; i < len; ++i ) - if ( uid == manufactureMapping[i].uid) + + for ( i = 0; i < len; ++i ) + if ( uid == manufactureMapping[i].uid) return manufactureMapping[i].desc; //No match, return default - return manufactureMapping[len-1].desc; + return manufactureMapping[len-1].desc; } // iso14a apdu input frame length @@ -171,7 +171,7 @@ int usage_hf_14a_sim(void) { // PrintAndLogEx(NORMAL, " u : 4, 7 or 10 byte UID"); PrintAndLogEx(NORMAL, " u : 4, 7 byte UID"); PrintAndLogEx(NORMAL, " x : (Optional) Performs the 'reader attack', nr/ar attack against a reader"); - PrintAndLogEx(NORMAL, " e : (Optional) Fill simulator keys from found keys"); + PrintAndLogEx(NORMAL, " e : (Optional) Fill simulator keys from found keys"); PrintAndLogEx(NORMAL, " v : (Optional) Verbose"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223344 x"); @@ -232,11 +232,11 @@ int Hf14443_4aGetCardData(iso14a_card_select_t * card) { UsbCommand resp; WaitForResponse(CMD_ACK,&resp); - + memcpy(card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - + if(select_status == 0) { PrintAndLog("E->iso14443a card select failed"); return 1; @@ -261,22 +261,22 @@ int Hf14443_4aGetCardData(iso14a_card_select_t * card) { return 1; } PrintAndLog(" ATS: %s", sprint_hex(card->ats, card->ats_len)); - + return 0; } int CmdHF14AReader(const char *Cmd) { uint32_t cm = ISO14A_CONNECT; - bool disconnectAfter = true, silent = false; + bool disconnectAfter = true, silent = false; int cmdp = 0; - + while (param_getchar(Cmd, cmdp) != 0x00) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_hf_14a_reader(); case '3': - cm |= ISO14A_NO_RATS; + cm |= ISO14A_NO_RATS; break; case 'k': disconnectAfter = false; @@ -290,13 +290,13 @@ int CmdHF14AReader(const char *Cmd) { default: PrintAndLogEx(WARNING, "Unknown command."); return 1; - } + } cmdp++; } if (!disconnectAfter) - cm |= ISO14A_NO_DISCONNECT; - + cm |= ISO14A_NO_DISCONNECT; + UsbCommand c = {CMD_READER_ISO_14443a, {cm, 0, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -308,18 +308,18 @@ int CmdHF14AReader(const char *Cmd) { DropField(); return 1; } - + iso14a_card_select_t card; memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - /* + /* 0: couldn't read 1: OK, with ATS 2: OK, no ATS - 3: proprietary Anticollision + 3: proprietary Anticollision */ uint64_t select_status = resp.arg[0]; - + if (select_status == 0) { if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); DropField(); @@ -340,7 +340,7 @@ int CmdHF14AReader(const char *Cmd) { if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes PrintAndLogEx(NORMAL, " ATS : %s", sprint_hex(card.ats, card.ats_len)); } - + if (!disconnectAfter) { if (!silent) PrintAndLogEx(SUCCESS, "Card is selected. You can now start sending commands"); } @@ -354,12 +354,12 @@ int CmdHF14AReader(const char *Cmd) { } int CmdHF14AInfo(const char *Cmd) { - + if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_hf_14a_info(); - + bool silent = (Cmd[0] == 's' || Cmd[0] == 'S'); bool do_nack_test = (Cmd[0] == 'n' || Cmd[0] == 'N'); - + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -369,18 +369,18 @@ int CmdHF14AInfo(const char *Cmd) { DropField(); return 0; } - + iso14a_card_select_t card; memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - /* + /* 0: couldn't read 1: OK, with ATS 2: OK, no ATS - 3: proprietary Anticollision + 3: proprietary Anticollision */ uint64_t select_status = resp.arg[0]; - + if (select_status == 0) { if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); DropField(); @@ -400,16 +400,16 @@ int CmdHF14AInfo(const char *Cmd) { bool isMifareClassic = true; switch (card.sak) { - case 0x00: + case 0x00: isMifareClassic = false; - + // ******** is card of the MFU type (UL/ULC/NTAG/ etc etc) DropField(); - + uint32_t tagT = GetHF14AMfU_Type(); if (tagT != UL_ERROR) ul_print_type(tagT, 0); - else + else PrintAndLogEx(NORMAL, "TYPE: Possible AZTEK (iso14443a compliant)"); // reconnect for further tests @@ -420,11 +420,11 @@ int CmdHF14AInfo(const char *Cmd) { SendCommand(&c); UsbCommand resp; WaitForResponse(CMD_ACK, &resp); - + memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS - + if(select_status == 0) { DropField(); return 0; @@ -451,7 +451,7 @@ int CmdHF14AInfo(const char *Cmd) { if ( card.uidlen > 4 ) { PrintAndLogEx(NORMAL, "MANUFACTURER : %s", getTagInfo(card.uid[0])); } - + // try to request ATS even if tag claims not to support it if (select_status == 2) { uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 @@ -462,10 +462,10 @@ int CmdHF14AInfo(const char *Cmd) { clearCommandBuffer(); SendCommand(&c); WaitForResponse(CMD_ACK,&resp); - + memcpy(card.ats, resp.d.asBytes, resp.arg[0]); card.ats_len = resp.arg[0]; // note: ats_len includes CRC Bytes - } + } if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes bool ta1 = 0, tb1 = 0, tc1 = 0; @@ -479,13 +479,13 @@ int CmdHF14AInfo(const char *Cmd) { if (card.ats[0] != card.ats_len - 2) { PrintAndLogEx(NORMAL, "ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len); } - + if (card.ats[0] > 1) { // there is a format byte (T0) ta1 = (card.ats[1] & 0x10) == 0x10; tb1 = (card.ats[1] & 0x20) == 0x20; tc1 = (card.ats[1] & 0x40) == 0x40; int16_t fsci = card.ats[1] & 0x0f; - + PrintAndLogEx(NORMAL, " - T0 : TA1 is%s present, TB1 is%s present, " "TC1 is%s present, FSCI is %d (FSC = %ld)", (ta1 ? "" : " NOT"), @@ -538,7 +538,7 @@ int CmdHF14AInfo(const char *Cmd) { } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { tip = "-> MIFARE Plus S 2K or 4K"; } - } + } PrintAndLogEx(NORMAL, " - HB : %s%s", sprint_hex(card.ats + pos, card.ats[0] - pos), tip); if (card.ats[pos] == 0xC1) { PrintAndLogEx(NORMAL, " c1 -> Mifare or (multiple) virtual cards of various type"); @@ -573,9 +573,9 @@ int CmdHF14AInfo(const char *Cmd) { } else { PrintAndLogEx(INFO, "proprietary non iso14443-4 card found, RATS not supported"); } - + detect_classic_magic(); - + if (isMifareClassic) { int res = detect_classic_prng(); if ( res == 1 ) @@ -584,11 +584,11 @@ int CmdHF14AInfo(const char *Cmd) { PrintAndLogEx(SUCCESS, "Prng detection: " _YELLOW_(HARD)); else PrintAndLogEx(FAILED, "prng detection: " _RED_(failed)); - + if ( do_nack_test ) detect_classic_nackbug(silent); } - + return select_status; } @@ -610,11 +610,11 @@ int CmdHF14ACUIDs(const char *Cmd) { PrintAndLogEx(NORMAL, "\n[!] aborted via keyboard!\n"); break; } - + // execute anticollision procedure UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0}}; SendCommand(&c); - + UsbCommand resp; WaitForResponse(CMD_ACK,&resp); @@ -639,7 +639,7 @@ int CmdHF14ACUIDs(const char *Cmd) { int CmdHF14ASim(const char *Cmd) { bool errors = false; uint8_t flags = 0; - uint8_t tagtype = 1; + uint8_t tagtype = 1; uint8_t cmdp = 0; uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; int uidlen = 0; @@ -647,7 +647,7 @@ int CmdHF14ASim(const char *Cmd) { bool setEmulatorMem = false; bool verbose = false; nonces_t data[1]; - + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch(param_getchar(Cmd, cmdp)) { case 'h': @@ -658,19 +658,19 @@ int CmdHF14ASim(const char *Cmd) { // Retrieve the tag type tagtype = param_get8ex(Cmd, cmdp+1, 0, 10); if (tagtype == 0) - errors = true; + errors = true; cmdp += 2; break; case 'u': case 'U': - // Retrieve the full 4,7,10 byte long uid + // Retrieve the full 4,7,10 byte long uid param_gethex_ex(Cmd, cmdp+1, uid, &uidlen); switch(uidlen) { //case 20: flags |= FLAG_10B_UID_IN_DATA; break; case 14: flags |= FLAG_7B_UID_IN_DATA; break; case 8: flags |= FLAG_4B_UID_IN_DATA; break; default: errors = true; break; - } + } if (!errors) { PrintAndLogEx(SUCCESS, "Emulating ISO/IEC 14443 type A tag with %d byte UID (%s)", uidlen>>1, sprint_hex(uid, uidlen>>1)); useUIDfromEML = false; @@ -691,7 +691,7 @@ int CmdHF14ASim(const char *Cmd) { case 'E': setEmulatorMem = true; cmdp++; - break; + break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -702,22 +702,22 @@ int CmdHF14ASim(const char *Cmd) { //Validations if (errors || cmdp == 0) return usage_hf_14a_sim(); - if ( useUIDfromEML ) + if ( useUIDfromEML ) flags |= FLAG_UID_IN_EMUL; - - UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,{ tagtype, flags, 0 }}; + + UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,{ tagtype, flags, 0 }}; memcpy(c.d.asBytes, uid, uidlen>>1); clearCommandBuffer(); - SendCommand(&c); + SendCommand(&c); UsbCommand resp; - + PrintAndLogEx(SUCCESS, "press pm3-button to abort simulation"); - + while( !ukbhit() ){ if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; if ( !(flags & FLAG_NR_AR_ATTACK) ) break; if ( (resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD ) break; - + memcpy(data, resp.d.asBytes, sizeof(data) ); readerAttack(data[0], setEmulatorMem, verbose); } @@ -726,7 +726,7 @@ int CmdHF14ASim(const char *Cmd) { } int CmdHF14ASniff(const char *Cmd) { - int param = 0; + int param = 0; uint8_t ctmp; for (int i = 0; i < 2; i++) { ctmp = tolower(param_getchar(Cmd, i)); @@ -744,7 +744,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav static bool responseNum = false; uint16_t cmdc = 0; *dataoutlen = 0; - + if (activateField) { responseNum = false; UsbCommand resp; @@ -769,8 +769,8 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav } if (resp.arg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - // get ATS - UsbCommand cr = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0}}; + // get ATS + UsbCommand cr = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0}}; uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 memcpy(cr.d.asBytes, rats, 2); SendCommand(&cr); @@ -778,52 +778,52 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav PrintAndLogEx(ERR, "Proxmark connection timeout."); return 1; } - + if (resp.arg[0] <= 0) { // ats_len PrintAndLogEx(ERR, "Can't get ATS."); return 1; } } } - + if (leaveSignalON) cmdc |= ISO14A_NO_DISCONNECT; - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF) + 2, 0}}; + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF) + 2, 0}}; uint8_t header[] = {0x0a | responseNum, 0x00}; responseNum ^= 1; memcpy(c.d.asBytes, header, 2); memcpy(&c.d.asBytes[2], datain, datainlen); SendCommand(&c); - + uint8_t *recv; UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { recv = resp.d.asBytes; int iLen = resp.arg[0]; - + if(!iLen) { PrintAndLogEx(ERR, "No card response."); return 1; } - + *dataoutlen = iLen - 2; if (*dataoutlen < 0) *dataoutlen = 0; - + if (maxdataoutlen && *dataoutlen > maxdataoutlen) { PrintAndLogEx(ERR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); return 2; } - + if (recv[0] != header[0]) { PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", dataout[0], header[0]); return 2; } - + memcpy(dataout, &recv[2], *dataoutlen); - + // CRC Check if (iLen == -1) { PrintAndLogEx(ERR, "ISO 14443A CRC error."); @@ -835,7 +835,7 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav PrintAndLogEx(ERR, "Reply timeout."); return 4; } - + return 0; } @@ -846,8 +846,8 @@ int SelectCard14443_4(bool disconnect, iso14a_card_select_t *card) { if (card) memset(card, 0, sizeof(iso14a_card_select_t)); - - DropField(); + + DropField(); // Anticollision + SELECT card UsbCommand ca = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; @@ -869,8 +869,8 @@ int SelectCard14443_4(bool disconnect, iso14a_card_select_t *card) { } if (resp.arg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - // get ATS - UsbCommand cr = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0}}; + // get ATS + UsbCommand cr = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0}}; uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 memcpy(cr.d.asBytes, rats, 2); SendCommand(&cr); @@ -878,7 +878,7 @@ int SelectCard14443_4(bool disconnect, iso14a_card_select_t *card) { PrintAndLogEx(ERR, "Proxmark connection timeout."); return 1; } - + if (resp.arg[0] <= 0) { // ats_len PrintAndLogEx(ERR, "Can't get ATS."); return 1; @@ -898,39 +898,39 @@ int SelectCard14443_4(bool disconnect, iso14a_card_select_t *card) { if (fsci < sizeof(atsFSC)) frameLength = atsFSC[fsci]; } - + if (card) memcpy(card, vcard, sizeof(iso14a_card_select_t)); } - + if (disconnect) - DropField(); + DropField(); return 0; } int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chainingout) { *chainingout = false; - + if (activateField) { // select with no disconnect and set frameLength int selres = SelectCard14443_4(false, NULL); if (selres) return selres; } - + uint16_t cmdc = 0; if (chainingin) cmdc = ISO14A_SEND_CHAINING; - + // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes // https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size // here length USB_CMD_DATA_SIZE=512 // timeout must be authomatically set by "get ATS" - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, (datainlen & 0xFFFF), 0}}; + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, (datainlen & 0xFFFF), 0}}; memcpy(c.d.asBytes, datain, datainlen); SendCommand(&c); - + uint8_t *recv; UsbCommand resp; @@ -938,24 +938,24 @@ int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activa recv = resp.d.asBytes; int iLen = resp.arg[0]; uint8_t res = resp.arg[1]; - + int dlen = iLen - 2; if (dlen < 0) dlen = 0; *dataoutlen += dlen; - + if (maxdataoutlen && *dataoutlen > maxdataoutlen) { PrintAndLogEx(ERR, "APDU: Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); return 2; } - + // I-block ACK if ((res & 0xf2) == 0xa2) { *dataoutlen = 0; *chainingout = true; return 0; } - + if(!iLen) { PrintAndLogEx(ERR, "APDU: No APDU response."); return 1; @@ -966,7 +966,7 @@ int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activa PrintAndLogEx(ERR, "APDU: Small APDU response. Len=%d", iLen); return 2; } - + // check block TODO if (iLen == -2) { PrintAndLogEx(ERR, "APDU: Block type mismatch."); @@ -974,12 +974,12 @@ int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activa } memcpy(dataout, recv, dlen); - + // chaining if ((res & 0x10) != 0) { *chainingout = true; } - + // CRC Check if (iLen == -1) { PrintAndLogEx(ERR, "APDU: ISO 14443A CRC error."); @@ -999,12 +999,12 @@ int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool lea int res; // 3 byte here - 1b framing header, 2b crc16 - if (APDUInFramingEnable && + if (APDUInFramingEnable && ( (frameLength && (datainlen > frameLength - 3)) || (datainlen > USB_CMD_DATA_SIZE - 3)) ) { int clen = 0; - + bool vActivateField = activateField; - + do { int vlen = MIN(frameLength - 3, datainlen - clen); bool chainBlockNotLast = ((clen + vlen) < datainlen); @@ -1022,10 +1022,10 @@ int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool lea if ((*dataoutlen == 0) && (*dataoutlen != 0 || chaining != chainBlockNotLast)) { if (!leaveSignalON) DropField(); - + return 201; } - + clen += vlen; vActivateField = false; if (*dataoutlen) { @@ -1033,32 +1033,32 @@ int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool lea PrintAndLogEx(WARNING, "APDU: I-block/R-block sequence error. Data len=%d, Sent=%d, Last packet len=%d", datainlen, clen, *dataoutlen); break; } - } while (clen < datainlen); + } while (clen < datainlen); } else { res = CmdExchangeAPDU(false, datain, datainlen, activateField, dataout, maxdataoutlen, dataoutlen, &chaining); if (res) { if (!leaveSignalON) DropField(); - + return res; } } - + while (chaining) { // I-block with chaining res = CmdExchangeAPDU(false, NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining); - + if (res) { if (!leaveSignalON) DropField(); - + return 100; } - } - + } + if (!leaveSignalON) DropField(); - + return 0; } @@ -1070,8 +1070,8 @@ int CmdHF14AAPDU(const char *cmd) { bool leaveSignalON = false; bool decodeTLV = false; - CLIParserInit("hf 14a apdu", - "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL)", + CLIParserInit("hf 14a apdu", + "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL)", "Sample:\n\thf 14a apdu -st 00A404000E325041592E5359532E444446303100\n"); void* argtable[] = { @@ -1083,7 +1083,7 @@ int CmdHF14AAPDU(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, false); - + activateField = arg_get_lit(1); leaveSignalON = arg_get_lit(2); decodeTLV = arg_get_lit(3); @@ -1092,21 +1092,21 @@ int CmdHF14AAPDU(const char *cmd) { CLIParserFree(); PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s", activateField ? "sel ": "", leaveSignalON ? "keep ": "", decodeTLV ? "TLV": "", sprint_hex(data, datalen)); - + int res = ExchangeAPDU14a(data, datalen, activateField, leaveSignalON, data, USB_CMD_DATA_SIZE, &datalen); if (res) return res; PrintAndLogEx(NORMAL, "<<<< %s", sprint_hex(data, datalen)); - - PrintAndLogEx(SUCCESS, "APDU response: %02x %02x - %s", data[datalen - 2], data[datalen - 1], GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1])); + + PrintAndLogEx(SUCCESS, "APDU response: %02x %02x - %s", data[datalen - 2], data[datalen - 1], GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1])); // TLV decoder if (decodeTLV && datalen > 4) { TLVPrintFromBuffer(data, datalen - 2); } - + return 0; } @@ -1140,7 +1140,7 @@ int CmdHF14ACmdRaw(const char *cmd) { case 'H': case 'h': return usage_hf_14a_raw(); - case 'r': + case 'r': reply = false; break; case 'c': @@ -1155,7 +1155,7 @@ int CmdHF14ACmdRaw(const char *cmd) { case 's': active_select = true; break; - case 'b': + case 'b': sscanf(cmd+i+2, "%d", &temp); numbits = temp & 0xFFFF; i+=3; @@ -1235,21 +1235,21 @@ int CmdHF14ACmdRaw(const char *cmd) { if (power) { c.arg[0] |= ISO14A_NO_DISCONNECT; } - + if (datalen > 0) { c.arg[0] |= ISO14A_RAW; } - + if (topazmode) { c.arg[0] |= ISO14A_TOPAZMODE; } if (no_rats) { c.arg[0] |= ISO14A_NO_RATS; } - + // Max buffer is USB_CMD_DATA_SIZE datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; - + c.arg[1] = (datalen & 0xFFFF) | ((uint32_t)(numbits << 16)); memcpy(c.d.asBytes, data, datalen); @@ -1270,7 +1270,7 @@ static int waitCmd(uint8_t iSelect) { UsbCommand resp; uint16_t len = 0; - if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { len = (resp.arg[0] & 0xFFFF); if (iSelect){ len = (resp.arg[1] & 0xFFFF); @@ -1282,10 +1282,10 @@ static int waitCmd(uint8_t iSelect) { } else { PrintAndLogEx(NORMAL, "received %i bytes", len); } - + if (!len) return 1; - + PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) ); } else { PrintAndLogEx(WARNING, "timeout while waiting for reply."); @@ -1295,9 +1295,9 @@ static int waitCmd(uint8_t iSelect) { } int CmdHF14AAntiFuzz(const char *cmd) { - - CLIParserInit("hf 14a antifuzz", - "Tries to fuzz the ISO14443a anticollision phase", + + CLIParserInit("hf 14a antifuzz", + "Tries to fuzz the ISO14443a anticollision phase", "Usage:\n" "\thf 14a antifuzz -4\n"); @@ -1312,21 +1312,21 @@ int CmdHF14AAntiFuzz(const char *cmd) { uint8_t arg0 = FLAG_4B_UID_IN_DATA; if (arg_get_lit(2)) - arg0 = FLAG_7B_UID_IN_DATA; + arg0 = FLAG_7B_UID_IN_DATA; if (arg_get_lit(3)) arg0 = FLAG_10B_UID_IN_DATA; CLIParserFree(); - UsbCommand c = {CMD_ANTIFUZZ_ISO_14443a, {arg0, 0, 0}}; + UsbCommand c = {CMD_ANTIFUZZ_ISO_14443a, {arg0, 0, 0}}; clearCommandBuffer(); - SendCommand(&c); + SendCommand(&c); return 0; } int CmdHF14AChaining(const char *cmd) { - - CLIParserInit("hf 14a chaining", - "Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.", + + CLIParserInit("hf 14a chaining", + "Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.", "Usage:\n" "\thf 14a chaining disable -> disable chaining\n" "\thf 14a chaining -> show chaining enable/disable state\n"); @@ -1340,17 +1340,17 @@ int CmdHF14AChaining(const char *cmd) { struct arg_str *str = arg_get_str(1); int len = arg_get_str_len(1); - + if (len && (!strcmp(str->sval[0], "enable") || !strcmp(str->sval[0], "1"))) APDUInFramingEnable = true; - + if (len && (!strcmp(str->sval[0], "disable") || !strcmp(str->sval[0], "0"))) APDUInFramingEnable = false; CLIParserFree(); PrintAndLogEx(INFO, "\nISO 14443-4 input chaining %s.\n", APDUInFramingEnable ? "enabled" : "disabled"); - + return 0; } diff --git a/client/cmdhf14a.h b/client/cmdhf14a.h index 3fe04d26c..4396c4b79 100644 --- a/client/cmdhf14a.h +++ b/client/cmdhf14a.h @@ -31,13 +31,13 @@ #include "cmdhf.h" // list cmd #include "mifare/mifarehost.h" #include "emv/apduinfo.h" -#include "emv/emvcore.h" +#include "emv/emvcore.h" -// structure and database for uid -> tagtype lookups -typedef struct { +// structure and database for uid -> tagtype lookups +typedef struct { uint8_t uid; char* desc; -} manufactureName; +} manufactureName; extern int CmdHF14A(const char *Cmd); extern int CmdHF14AList(const char *Cmd); @@ -51,7 +51,7 @@ extern int CmdHF14AAntiFuzz(const char *cmd); extern char* getTagInfo(uint8_t uid); extern int Hf14443_4aGetCardData(iso14a_card_select_t * card); -extern int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); +extern int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); extern int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen); extern int usage_hf_14a_sim(void); diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index 4109a999a..f74ca9a34 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -43,7 +43,7 @@ int usage_hf_14b_raw(void){ PrintAndLogEx(NORMAL, " -ss active signal field ON with select for SRx ST Microelectronics tags"); PrintAndLogEx(NORMAL, "Example:"); PrintAndLogEx(NORMAL, " hf 14b raw -s -c -p 0200a40400"); - return 0; + return 0; } int usage_hf_14b_sniff(void){ PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer."); @@ -53,7 +53,7 @@ int usage_hf_14b_sniff(void){ PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, "Example:"); PrintAndLogEx(NORMAL, " hf 14b sniff"); - return 0; + return 0; } int usage_hf_14b_sim(void){ PrintAndLogEx(NORMAL, "Emulating ISO/IEC 14443 type B tag with 4 UID / PUPI"); @@ -64,7 +64,7 @@ int usage_hf_14b_sim(void){ PrintAndLogEx(NORMAL, "Example:"); PrintAndLogEx(NORMAL, " hf 14b sim"); PrintAndLogEx(NORMAL, " hf 14b sim u 11223344"); - return 0; + return 0; } int usage_hf_14b_read_srx(void){ PrintAndLogEx(NORMAL, "Usage: hf 14b sriread [h] <1|2>"); @@ -94,7 +94,7 @@ int usage_hf_14b_dump(void){ PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-14443-B tag and save it to file\n" "\n" "Usage: hf 14b dump [h] [card memory] \n" - "Options:\n" + "Options:\n" "\th this help\n" "\t[card memory] 1 = SRIX4K (default), 2 = SRI512" "\tf filename, if no UID will be used as filename\n" @@ -128,12 +128,12 @@ int CmdHF14BList(const char *Cmd) { int CmdHF14BSim(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_hf_14b_sim(); - + uint32_t pupi = 0; if (cmdp == 'u') { pupi = param_get32ex(Cmd, 1, 0, 16); } - + UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443B, {pupi, 0, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -141,10 +141,10 @@ int CmdHF14BSim(const char *Cmd) { } int CmdHF14BSniff(const char *Cmd) { - + char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_hf_14b_sniff(); - + UsbCommand c = {CMD_SNOOP_ISO_14443B, {0, 0, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -159,25 +159,25 @@ int CmdHF14BCmdRaw (const char *Cmd) { uint16_t datalen = 0; uint32_t flags = ISO14B_CONNECT; uint32_t temp = 0; - + if ( strlen(Cmd) < 3 ) return usage_hf_14b_raw(); // strip while (*Cmd==' ' || *Cmd=='\t') ++Cmd; - + while (Cmd[i]!='\0') { if (Cmd[i]==' ' || Cmd[i]=='\t') { ++i; continue; } if (Cmd[i]=='-') { switch (tolower(Cmd[i+1])) { case 'h': return usage_hf_14b_raw(); - case 'r': + case 'r': reply = false; break; case 'c': flags |= ISO14B_APPEND_CRC; break; - case 'p': + case 'p': power = true; break; case 's': @@ -201,7 +201,7 @@ int CmdHF14BCmdRaw (const char *Cmd) { buf[strlen(buf)+1]=0; buf[strlen(buf)]=Cmd[i]; i++; - + if (strlen(buf)>=2) { sscanf(buf,"%x",&temp); data[datalen++] = (uint8_t)(temp & 0xff); @@ -213,7 +213,7 @@ int CmdHF14BCmdRaw (const char *Cmd) { PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, i)); return 0; } - + if (!power) flags |= ISO14B_DISCONNECT; @@ -223,16 +223,16 @@ int CmdHF14BCmdRaw (const char *Cmd) { // Max buffer is USB_CMD_DATA_SIZE datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; - UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, 0}}; + UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, 0}}; memcpy(c.d.asBytes, data, datalen); clearCommandBuffer(); SendCommand(&c); - if (!reply) return 1; + if (!reply) return 1; bool success = true; // get back iso14b_card_select_t, don't print it. - if (select) + if (select) success = waitCmd14b(false); // get back response from the raw bytes you sent. @@ -245,47 +245,47 @@ static bool get_14b_UID(iso14b_card_select_t *card) { if (!card) return false; - + int8_t retry = 3; UsbCommand resp; UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}}; - - // test for 14b SR + + // test for 14b SR while (retry--) { clearCommandBuffer(); - SendCommand(&c); + SendCommand(&c); if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - + uint8_t status = resp.arg[0]; if ( status == 0) { memcpy(card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); return true; } - } + } } // retry // test 14b standard - c.arg[0] = ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT; + c.arg[0] = ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT; retry = 3; while (retry--) { clearCommandBuffer(); - SendCommand(&c); + SendCommand(&c); if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - + uint8_t status = resp.arg[0]; if ( status == 0) { memcpy(card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); return true; } - } - } // retry - + } + } // retry + if ( retry <= 0 ) PrintAndLogEx(WARNING, "timeout while waiting for reply."); - + return false; } @@ -302,11 +302,11 @@ static void print_atqb_resp(uint8_t *data, uint8_t cid){ uint8_t BitRate = data[4]; if (!BitRate) PrintAndLogEx(NORMAL, " Bit Rate: 106 kbit/s only PICC <-> PCD"); if (BitRate & 0x10) PrintAndLogEx(NORMAL, " Bit Rate: 212 kbit/s PICC -> PCD supported"); - if (BitRate & 0x20) PrintAndLogEx(NORMAL, " Bit Rate: 424 kbit/s PICC -> PCD supported"); - if (BitRate & 0x40) PrintAndLogEx(NORMAL, " Bit Rate: 847 kbit/s PICC -> PCD supported"); + if (BitRate & 0x20) PrintAndLogEx(NORMAL, " Bit Rate: 424 kbit/s PICC -> PCD supported"); + if (BitRate & 0x40) PrintAndLogEx(NORMAL, " Bit Rate: 847 kbit/s PICC -> PCD supported"); if (BitRate & 0x01) PrintAndLogEx(NORMAL, " Bit Rate: 212 kbit/s PICC <- PCD supported"); - if (BitRate & 0x02) PrintAndLogEx(NORMAL, " Bit Rate: 424 kbit/s PICC <- PCD supported"); - if (BitRate & 0x04) PrintAndLogEx(NORMAL, " Bit Rate: 847 kbit/s PICC <- PCD supported"); + if (BitRate & 0x02) PrintAndLogEx(NORMAL, " Bit Rate: 424 kbit/s PICC <- PCD supported"); + if (BitRate & 0x04) PrintAndLogEx(NORMAL, " Bit Rate: 847 kbit/s PICC <- PCD supported"); if (BitRate & 0x80) PrintAndLogEx(NORMAL, " Same bit rate <-> required"); uint16_t maxFrame = data[5] >> 4; @@ -316,12 +316,12 @@ static void print_atqb_resp(uint8_t *data, uint8_t cid){ else if (maxFrame == 7) maxFrame = 128; else if (maxFrame == 8) maxFrame = 256; else maxFrame = 257; - + PrintAndLogEx(NORMAL, "Max Frame Size: %u%s bytes", maxFrame, (maxFrame == 257) ? "+ RFU" : ""); uint8_t protocolT = data[5] & 0xF; PrintAndLogEx(NORMAL, " Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4",(protocolT) ? "" : "not " ); - + uint8_t fwt = data[6]>>4; if ( fwt < 16 ){ uint32_t etus = (32 << fwt); @@ -330,7 +330,7 @@ static void print_atqb_resp(uint8_t *data, uint8_t cid){ } else { PrintAndLogEx(NORMAL, "Frame Wait Integer: %u - RFU", fwt); } - + PrintAndLogEx(NORMAL, " App Data Code: Application is %s",(data[6]&4) ? "Standard" : "Proprietary"); PrintAndLogEx(NORMAL, " Frame Options: NAD is %ssupported",(data[6]&2) ? "" : "not "); PrintAndLogEx(NORMAL, " Frame Options: CID is %ssupported",(data[6]&1) ? "" : "not "); @@ -429,33 +429,33 @@ static void print_st_general_info(uint8_t *data, uint8_t len){ // 0200a4040010a000000018300301000000000000000000 (resp 02 6a 82 [4b 4c]) //03 = ? (resp 03 [e3 c2]) //c2 = ? (resp c2 [66 15]) -//b2 = ? (resp a3 [e9 67]) +//b2 = ? (resp a3 [e9 67]) //a2 = ? (resp 02 [6a d3]) // 14b get and print Full Info (as much as we know) bool HF14B_Std_Info(bool verbose){ bool isSuccess = false; - - // 14b get and print UID only (general info) + + // 14b get and print UID only (general info) UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0}}; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; - + if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); - switch_off_field_14b(); + switch_off_field_14b(); return false; } - + iso14b_card_select_t card; memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); - - uint64_t status = resp.arg[0]; - + + uint64_t status = resp.arg[0]; + switch( status ){ - case 0: + case 0: PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); PrintAndLogEx(NORMAL, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); PrintAndLogEx(NORMAL, " CHIPID : %02X", card.chipid); @@ -465,20 +465,20 @@ bool HF14B_Std_Info(bool verbose){ case 2: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); break; - case 3: + case 3: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); break; default: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed"); break; } - + return isSuccess; } // SRx get and print full info (needs more info...) bool HF14B_ST_Info(bool verbose){ - + UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -491,9 +491,9 @@ bool HF14B_ST_Info(bool verbose){ iso14b_card_select_t card; memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); - - uint64_t status = resp.arg[0]; - if ( status > 0 ) + + uint64_t status = resp.arg[0]; + if ( status > 0 ) return false; print_st_general_info(card.uid, card.uidlen); @@ -507,16 +507,16 @@ bool HF14B_ST_Info(bool verbose){ // // if (model == 0x2) { //SR176 has special command: // data[1] = 0xf; - // resplen = 4; + // resplen = 4; // } else { // data[1] = 0xff; // resplen = 6; // } // //std read cmd - // if (HF14BCmdRaw(true, true, data, &datalen, false)==0) + // if (HF14BCmdRaw(true, true, data, &datalen, false)==0) // return rawClose(); - + // if (datalen != resplen || !crc) return rawClose(); //print_ST_Lock_info(data[5]>>2); return true; @@ -541,7 +541,7 @@ bool HF14BInfo(bool verbose){ int CmdHF14Binfo(const char *Cmd){ char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_hf_14b_info(); - + bool verbose = !(cmdp == 's'); return HF14BInfo(verbose); } @@ -559,14 +559,14 @@ bool HF14B_ST_Reader(bool verbose){ if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); return false; } - + iso14b_card_select_t card; memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); uint64_t status = resp.arg[0]; switch( status ){ - case 0: + case 0: print_st_general_info(card.uid, card.uidlen); isSuccess = true; break; @@ -576,38 +576,38 @@ bool HF14B_ST_Reader(bool verbose){ case 2: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); break; - case 3: + case 3: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); break; default: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select SRx failed"); break; } - return isSuccess; + return isSuccess; } bool HF14B_Std_Reader(bool verbose){ bool isSuccess = false; - // 14b get and print UID only (general info) + // 14b get and print UID only (general info) UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0}}; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; - + if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); return false; } - + iso14b_card_select_t card; memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); - - uint64_t status = resp.arg[0]; - + + uint64_t status = resp.arg[0]; + switch( status ){ - case 0: + case 0: PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); PrintAndLogEx(NORMAL, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); PrintAndLogEx(NORMAL, " CHIPID : %02X", card.chipid); @@ -617,14 +617,14 @@ bool HF14B_Std_Reader(bool verbose){ case 2: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); break; - case 3: + case 3: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); break; default: if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed"); break; } - return isSuccess; + return isSuccess; } // test for other 14b type tags (mimic another reader - don't have tags to identify) @@ -633,17 +633,17 @@ bool HF14B_Other_Reader(){ // uint8_t data[] = {0x00, 0x0b, 0x3f, 0x80}; // uint8_t datalen = 4; - // // 14b get and print UID only (general info) + // // 14b get and print UID only (general info) // uint32_t flags = ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_RAW | ISO14B_APPEND_CRC; - - // UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, 0}}; + + // UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, 0}}; // memcpy(c.d.asBytes, data, datalen); // clearCommandBuffer(); // SendCommand(&c); // UsbCommand resp; // WaitForResponse(CMD_ACK,&resp); - + // if (datalen > 2 ) { // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); // PrintAndLogEx(NORMAL, "unknown tag type answered to a 0x000b3f80 command ans:"); @@ -658,7 +658,7 @@ bool HF14B_Other_Reader(){ // SendCommand(&c); // UsbCommand resp; // WaitForResponse(CMD_ACK, &resp); - + // if (datalen > 0) { // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); // PrintAndLogEx(NORMAL, "Unknown tag type answered to a 0x0A command ans:"); @@ -681,14 +681,14 @@ bool HF14B_Other_Reader(){ // rawClose(); // return true; // } - + // rawClose(); return false; } // get and print general info about all known 14b chips bool HF14BReader(bool verbose){ - + // try std 14b (atqb) if (HF14B_Std_Reader(verbose)) return true; @@ -707,7 +707,7 @@ bool HF14BReader(bool verbose){ int CmdHF14BReader(const char *Cmd){ char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_hf_14b_reader(); - + bool verbose = !(cmdp == 's'); return HF14BReader(verbose); } @@ -722,7 +722,7 @@ int CmdHF14BReadSri(const char *Cmd){ uint8_t tagtype = param_get8(Cmd, 0); uint8_t blocks = (tagtype == 1) ? 0x7F : 0x0F; - + UsbCommand c = {CMD_READ_SRI_TAG, {blocks, 0, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -736,7 +736,7 @@ int CmdHF14BWriteSri(const char *Cmd){ * * For SR512 blocks 00 - 0F * hf 14b raw -c -p 09 $sr512wblock $sr512wdata - * + * * Special block FF = otp_lock_reg block. * Data len 4 bytes- */ @@ -744,38 +744,38 @@ int CmdHF14BWriteSri(const char *Cmd){ uint8_t blockno = -1; uint8_t data[4] = {0x00}; bool isSrix4k = true; - char str[30]; + char str[30]; memset(str, 0x00, sizeof(str)); if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_14b_write_srx(); if ( cmdp == '2' ) isSrix4k = false; - + //blockno = param_get8(Cmd, 1); - + if ( param_gethex(Cmd, 1, &blockno, 2) ) { PrintAndLogEx(WARNING, "block number must include 2 HEX symbols"); return 0; } - + if ( isSrix4k ){ if ( blockno > 0x7f && blockno != 0xff ){ PrintAndLogEx(FAILED, "block number out of range"); return 0; - } + } } else { if ( blockno > 0x0f && blockno != 0xff ){ PrintAndLogEx(FAILED, "block number out of range"); return 0; - } + } } - + if (param_gethex(Cmd, 2, data, 8)) { PrintAndLogEx(WARNING, "data must include 8 HEX symbols"); return 0; } - + if ( blockno == 0xff) { PrintAndLogEx(SUCCESS, "[%s] Write special block %02X [ %s ]", (isSrix4k) ? "SRIX4K":"SRI512", @@ -785,11 +785,11 @@ int CmdHF14BWriteSri(const char *Cmd){ } else { PrintAndLogEx(SUCCESS, "[%s] Write block %02X [ %s ]", (isSrix4k) ? "SRIX4K":"SRI512", - blockno, + blockno, sprint_hex(data,4) ); } - + sprintf(str, "-ss -c %02x %02x %02x %02x %02x %02x", ISO14443B_WRITE_BLK, blockno, data[0], data[1], data[2], data[3]); CmdHF14BCmdRaw(str); return 0; @@ -797,7 +797,7 @@ int CmdHF14BWriteSri(const char *Cmd){ // need to write to file int CmdHF14BDump(const char*Cmd) { - + uint8_t fileNameLen = 0; char filename[FILE_PATH_SIZE] = {0}; char * fptr = filename; @@ -806,13 +806,13 @@ int CmdHF14BDump(const char*Cmd) { uint16_t cardsize = 0; uint8_t blocks = 0; iso14b_card_select_t card; - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_hf_14b_dump(); case 'f': - fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); + fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); cmdp += 2; break; default: @@ -839,26 +839,26 @@ int CmdHF14BDump(const char*Cmd) { default: cardsize = (4096/8) + 4; blocks = 0x7F; - break; + break; } - + if (!get_14b_UID(&card)) { PrintAndLogEx(WARNING, "No tag found."); return 1; } - + if (fileNameLen < 1) { PrintAndLogEx(INFO, "Using UID as filename"); - fptr += sprintf(fptr, "hf-14b-"); + fptr += sprintf(fptr, "hf-14b-"); FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen); - } + } - // detect blocksize from card :) + // detect blocksize from card :) PrintAndLogEx(NORMAL, "Reading memory from tag UID %s", sprint_hex(card.uid, card.uidlen)); - + uint8_t data[cardsize]; memset(data, 0, sizeof(data)); - + int blocknum = 0; uint8_t *recv = NULL; @@ -874,30 +874,30 @@ int CmdHF14BDump(const char*Cmd) { goto out; } } - + c.arg[0] = ISO14B_APPEND_CRC | ISO14B_RAW; c.arg[1] = 2; - + uint8_t *req = c.d.asBytes; - req[0] = ISO14443B_READ_BLK; - + req[0] = ISO14443B_READ_BLK; + for (int retry = 0; retry < 5; retry++) { - + req[1] = blocknum; - + clearCommandBuffer(); SendCommand(&c); - + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { uint8_t status = resp.arg[0] & 0xFF; if ( status > 0 ) { - continue; + continue; } - + uint16_t len = (resp.arg[1] & 0xFFFF); recv = resp.d.asBytes; - + if ( !check_crc(CRC_14443_B, recv, len) ) { PrintAndLogEx(FAILED, "crc fail, retrying one more time"); continue; @@ -909,43 +909,43 @@ int CmdHF14BDump(const char*Cmd) { //last read. break; } - - + + retry = 0; blocknum++; if ( blocknum > blocks ) { // read config block blocknum = 0xFF; } - + printf("."); fflush(stdout); - } + } } - + if ( blocknum != 0xFF) { PrintAndLogEx(NORMAL, "\n Dump failed"); goto out; } - + PrintAndLogEx(NORMAL, "\n"); PrintAndLogEx(NORMAL, "block# | data | ascii"); - PrintAndLogEx(NORMAL, "---------+--------------+----------"); + PrintAndLogEx(NORMAL, "---------+--------------+----------"); for (int i = 0; i <= blocks; i++) { PrintAndLogEx(NORMAL, - "%3d/0x%02X | %s | %s", + "%3d/0x%02X | %s | %s", i, i, sprint_hex(data + (i*4), 4 ), sprint_ascii(data + (i*4), 4) ); } - + PrintAndLogEx(NORMAL, "\n"); - + size_t datalen = (blocks+1) * 4; - saveFileEML(filename, "eml", data, datalen, 4); + saveFileEML(filename, "eml", data, datalen, 4); saveFile(filename, "bin", data, datalen); out: return switch_off_field_14b(); @@ -955,16 +955,16 @@ uint32_t srix4kEncode(uint32_t value) { /* // vv = value // pp = position -// vv vv vv pp +// vv vv vv pp 4 bytes : 00 1A 20 01 */ // only the lower crumbs. uint8_t block = (value & 0xFF); uint8_t i = 0; uint8_t valuebytes[] = {0,0,0}; - + num_to_bytes(value, 3, valuebytes); - + // Scrambled part // Crumb swapping of value. uint8_t temp[] = {0,0}; @@ -975,7 +975,7 @@ uint32_t srix4kEncode(uint32_t value) { // chksum part uint32_t chksum = 0xFF - block; - + // chksum is reduced by each nibbles of value. for (i = 0; i < 3; ++i){ chksum -= NIBBLE_HIGH(valuebytes[i]); @@ -984,23 +984,23 @@ uint32_t srix4kEncode(uint32_t value) { // base4 conversion and left shift twice i = 3; - uint8_t base4[] = {0,0,0,0}; + uint8_t base4[] = {0,0,0,0}; while( chksum !=0 ){ base4[i--] = (chksum % 4 << 2); chksum /= 4; } - + // merge scambled and chksum parts - uint32_t encvalue = + uint32_t encvalue = ( NIBBLE_LOW ( base4[0]) << 28 ) | ( NIBBLE_HIGH( temp[0]) << 24 ) | - + ( NIBBLE_LOW ( base4[1]) << 20 ) | ( NIBBLE_LOW ( temp[0]) << 16 ) | - + ( NIBBLE_LOW ( base4[2]) << 12 ) | ( NIBBLE_HIGH( temp[1]) << 8 ) | - + ( NIBBLE_LOW ( base4[3]) << 4 ) | NIBBLE_LOW ( temp[1] ); @@ -1040,12 +1040,12 @@ int srix4kValid(const char *Cmd){ uint32_t block18 = 0xC04F42C5; uint32_t block19 = 0xC1484807; uint32_t block21 = 0xD1BCABA4; - + uint32_t test_b18 = 0x00313918; uint32_t test_b18_enc = srix4kEncode(test_b18); //uint32_t test_b18_dec = srix4kDecode(test_b18_enc); PrintAndLogEx(SUCCESS, "ENCODE & CHECKSUM | %08X -> %08X (%s)", test_b18, test_b18_enc , ""); - + uint32_t magic = srix4kGetMagicbytes(uid, block6, block18, block19); PrintAndLogEx(SUCCESS, "BLOCK 21 | %08X -> %08X (no XOR)", block21, magic ^ block21); return 0; @@ -1056,22 +1056,22 @@ bool waitCmd14b(bool verbose) { bool crc = false; uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; uint8_t status = 0; - uint16_t len = 0; + uint16_t len = 0; UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { status = (resp.arg[0] & 0xFF); if ( status > 0 ) return false; - + len = (resp.arg[1] & 0xFFFF); - + memcpy(data, resp.d.asBytes, len); - + if (verbose) { if ( len >= 3 ) { crc = check_crc(CRC_14443_B, data, len); - + PrintAndLogEx(NORMAL, "[LEN %u] %s[%02X %02X] %s", len, sprint_hex(data, len-2), @@ -1082,7 +1082,7 @@ bool waitCmd14b(bool verbose) { } else { PrintAndLogEx(NORMAL, "[LEN %u] %s", len, sprint_hex(data, len) ); } - } + } return true; } else { PrintAndLogEx(WARNING, "command execution timeout"); @@ -1092,7 +1092,7 @@ bool waitCmd14b(bool verbose) { static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"dump", CmdHF14BDump, 0, "Read all memory pages of an ISO14443-B tag, save to file"}, + {"dump", CmdHF14BDump, 0, "Read all memory pages of an ISO14443-B tag, save to file"}, {"info", CmdHF14Binfo, 0, "Tag information"}, {"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443B history"}, {"raw", CmdHF14BCmdRaw, 0, "Send raw hex data to tag"}, diff --git a/client/cmdhf14b.h b/client/cmdhf14b.h index 793949c86..74b279620 100644 --- a/client/cmdhf14b.h +++ b/client/cmdhf14b.h @@ -51,7 +51,7 @@ extern bool HF14BInfo(bool verbose); extern bool HF14BReader(bool verbose); extern int CmdHF14BCmdRaw (const char *Cmd); -// SRi ST Microelectronics read/write +// SRi ST Microelectronics read/write extern int CmdHF14BReadSri(const char *Cmd); extern int CmdHF14BWriteSri(const char *Cmd); diff --git a/client/cmdhf15.c b/client/cmdhf15.c index 097a52704..dc1a47f40 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -15,13 +15,13 @@ // Mode 1: // All steps are done on the proxmark, the output of the commands is returned via // USB-debug-print commands. -// Mode 2: +// Mode 2: // The protocol is done on the PC, passing only Iso15693 data frames via USB. This // allows direct communication with a tag on command level // Mode 3: // The proxmark just samples the antenna and passes this "analog" data via USB to // the client. Signal Processing & decoding is done on the pc. This is the slowest -// variant, but offers the possibility to analyze the waveforms directly. +// variant, but offers the possibility to analyze the waveforms directly. #include "cmdhf15.h" #define FrameSOF Iso15693FrameSOF @@ -35,18 +35,18 @@ #define sprintUID(target, uid) Iso15693sprintUID((target), (uid)) -// structure and database for uid -> tagtype lookups -typedef struct { +// structure and database for uid -> tagtype lookups +typedef struct { uint64_t uid; int mask; // how many MSB bits used char* desc; -} productName; +} productName; const productName uidmapping[] = { // UID, #significant Bits, "Vendor(+Product)" { 0xE001000000000000LL, 16, "Motorola UK" }, - + // E0 02 xx // 02 = ST Microelectronics // XX = IC id (Chip ID Family) @@ -56,8 +56,8 @@ const productName uidmapping[] = { { 0xE0020A0000000000LL, 24, "ST Microelectronics; LRIS2K [IC id = 10]"}, { 0xE002440000000000LL, 24, "ST Microelectronics; LRIS64K [IC id = 68]"}, - { 0xE003000000000000LL, 16, "Hitachi, Ltd Japan" }, - + { 0xE003000000000000LL, 16, "Hitachi, Ltd Japan" }, + // E0 04 xx // 04 = Manufacturer code (Philips/NXP) // XX = IC id (Chip ID Family) @@ -67,7 +67,7 @@ const productName uidmapping[] = { //I-Code SLIX [IC id = 01 + bit36 set to 1 (starting from bit0 - different from normal SLI)] //I-Code SLIX-S [IC id = 02 + bit36 set to 1] //I-Code SLIX-L [IC id = 03 + bit36 set to 1] - { 0xE004000000000000LL, 16, "NXP Semiconductors Germany (Philips)" }, + { 0xE004000000000000LL, 16, "NXP Semiconductors Germany (Philips)" }, { 0xE004010000000000LL, 24, "NXP(Philips); IC SL2 ICS20/ICS21(SLI) ICS2002/ICS2102(SLIX)" }, { 0xE004020000000000LL, 24, "NXP(Philips); IC SL2 ICS53/ICS54(SLI-S) ICS5302/ICS5402(SLIX-S)" }, { 0xE004030000000000LL, 24, "NXP(Philips); IC SL2 ICS50/ICS51(SLI-L) ICS5002/ICS5102(SLIX-L)" }, @@ -75,7 +75,7 @@ const productName uidmapping[] = { // E0 05 XX .. .. .. // 05 = Manufacturer code (Infineon) // XX = IC id (Chip ID Family) - { 0xE005000000000000LL, 16, "Infineon Technologies AG Germany" }, + { 0xE005000000000000LL, 16, "Infineon Technologies AG Germany" }, { 0xE005A10000000000LL, 24, "Infineon; SRF55V01P [IC id = 161] plain mode 1kBit"}, { 0xE005A80000000000LL, 24, "Infineon; SRF55V01P [IC id = 168] pilot series 1kBit"}, { 0xE005400000000000LL, 24, "Infineon; SRF55V02P [IC id = 64] plain mode 2kBit"}, @@ -84,10 +84,10 @@ const productName uidmapping[] = { { 0xE005100000000000LL, 24, "Infineon; SRF55V10S [IC id = 16] secure mode 10KBit"}, { 0xE0051E0000000000LL, 23, "Infineon; SLE66r01P [IC id = 3x = My-d Move or My-d move NFC]"}, { 0xE005200000000000LL, 21, "Infineon; SLE66r01P [IC id = 3x = My-d Move or My-d move NFC]"}, - - { 0xE006000000000000LL, 16, "Cylink USA" }, - - + + { 0xE006000000000000LL, 16, "Cylink USA" }, + + // E0 07 xx // 07 = Texas Instruments // XX = from bit 41 to bit 43 = product configuration - from bit 44 to bit 47 IC id (Chip ID Family) @@ -101,11 +101,11 @@ const productName uidmapping[] = { { 0xE007100000000000LL, 20, "Texas Instrument; Tag-it HF-I Plus Chip; 64x32bit" }, { 0xE007800000000000LL, 23, "Texas Instrument; Tag-it HF-I Plus (RF-HDT-DVBB tag or Third Party Products)" }, { 0xE007C00000000000LL, 23, "Texas Instrument; Tag-it HF-I Standard; 8x32bit" }, - { 0xE007C40000000000LL, 23, "Texas Instrument; Tag-it HF-I Pro; 8x23bit; password" }, + { 0xE007C40000000000LL, 23, "Texas Instrument; Tag-it HF-I Pro; 8x23bit; password" }, - { 0xE008000000000000LL, 16, "Fujitsu Limited Japan" }, - { 0xE009000000000000LL, 16, "Matsushita Electronics Corporation, Semiconductor Company Japan" }, - { 0xE00A000000000000LL, 16, "NEC Japan" }, + { 0xE008000000000000LL, 16, "Fujitsu Limited Japan" }, + { 0xE009000000000000LL, 16, "Matsushita Electronics Corporation, Semiconductor Company Japan" }, + { 0xE00A000000000000LL, 16, "NEC Japan" }, { 0xE00B000000000000LL, 16, "Oki Electric Industry Co. Ltd Japan" }, { 0xE00C000000000000LL, 16, "Toshiba Corp. Japan" }, { 0xE00D000000000000LL, 16, "Mitsubishi Electric Corp. Japan" }, @@ -119,13 +119,13 @@ const productName uidmapping[] = { { 0xE013000000000000LL, 16, "ORGA Kartensysteme GmbH Germany" }, { 0xE014000000000000LL, 16, "SHARP Corporation Japan" }, { 0xE015000000000000LL, 16, "ATMEL France" }, - + { 0xE016000000000000LL, 16, "EM Microelectronic-Marin SA Switzerland (Skidata)"}, { 0xE016040000000000LL, 24, "EM-Marin SA (Skidata Keycard-eco); EM4034 [IC id = 01] (Read/Write - no AFI)"}, { 0xE0160C0000000000LL, 24, "EM-Marin SA (Skidata); EM4035 [IC id = 03] (Read/Write - replaced by 4233)"}, { 0xE016100000000000LL, 24, "EM-Marin SA (Skidata); EM4135 [IC id = 04] (Read/Write - replaced by 4233) 36x64bit start page 13"}, { 0xE016140000000000LL, 24, "EM-Marin SA (Skidata); EM4036 [IC id = 05] 28pF"}, - { 0xE016180000000000LL, 24, "EM-Marin SA (Skidata); EM4006 [IC id = 06] (Read Only)"}, + { 0xE016180000000000LL, 24, "EM-Marin SA (Skidata); EM4006 [IC id = 06] (Read Only)"}, { 0xE0161C0000000000LL, 24, "EM-Marin SA (Skidata); EM4133 [IC id = 07] 23,5pF (Read/Write)"}, { 0xE016200000000000LL, 24, "EM-Marin SA (Skidata); EM4033 [IC id = 08] 23,5pF (Read Only - no AFI / no DSFID / no security blocks)"}, { 0xE016240000000000LL, 24, "EM-Marin SA (Skidata); EM4233 [IC id = 09] 23,5pF CustomerID-102"}, @@ -165,7 +165,7 @@ const productName uidmapping[] = { { 0xE030000000000000LL, 16, "BeeDar Technology Inc. USA" }, { 0xE031000000000000LL, 16, "RFIDsec Denmark" }, { 0xE032000000000000LL, 16, "Schweizer Electronic AG Germany" }, - { 0xE033000000000000LL, 16, "AMIC Technology Corp Taiwan" }, + { 0xE033000000000000LL, 16, "AMIC Technology Corp Taiwan" }, { 0xE034000000000000LL, 16, "Mikron JSC Russia" }, { 0xE035000000000000LL, 16, "Fraunhofer Institute for Photonic Microsystems Germany" }, { 0xE036000000000000LL, 16, "IDS Microchip AG Switzerland" }, @@ -177,7 +177,7 @@ const productName uidmapping[] = { { 0xE03C000000000000LL, 16, "Verayo Inc. USA" }, { 0xE03D000000000000LL, 16, "HID Global USA" }, { 0xE03E000000000000LL, 16, "Productivity Engineering Gmbh Germany" }, - { 0xE03F000000000000LL, 16, "Austriamicrosystems AG (reserved) Austria" }, + { 0xE03F000000000000LL, 16, "Austriamicrosystems AG (reserved) Austria" }, { 0xE040000000000000LL, 16, "Gemalto SA France" }, { 0xE041000000000000LL, 16, "Renesas Electronics Corporation Japan" }, { 0xE042000000000000LL, 16, "3Alogics Inc Korea" }, @@ -202,53 +202,53 @@ int getUID(uint8_t *buf) { c.arg[0] = 5; // len uint8_t retry; - - // don't give up the at the first try + + // don't give up the at the first try for (retry = 0; retry < 3; retry++) { clearCommandBuffer(); SendCommand(&c); - + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - + uint8_t resplen = resp.arg[0]; if (resplen >= 12 && CheckCrc(resp.d.asBytes, 12)) { memcpy(buf, resp.d.asBytes + 2, 8); return 1; - } - } + } + } } // retry - + if ( retry >= 3 ) PrintAndLogEx(WARNING, "timeout while waiting for reply."); - + return 0; } // get a product description based on the UID // uid[8] tag uid -// returns description of the best match +// returns description of the best match static char* getTagInfo_15(uint8_t *uid) { uint64_t myuid, mask; - int i = 0, best = -1; + int i = 0, best = -1; memcpy(&myuid, uid, sizeof(uint64_t)); while (uidmapping[i].mask > 0) { mask = (~0LL) << (64-uidmapping[i].mask); if ((myuid & mask) == uidmapping[i].uid) { - if (best == -1) { + if (best == -1) { best = i; } else { if (uidmapping[i].mask > uidmapping[best].mask) { best=i; } - } - } + } + } i++; - } + } if (best >= 0) return uidmapping[best].desc; - return uidmapping[i].desc; + return uidmapping[i].desc; } // return a clear-text message to an errorcode @@ -333,7 +333,7 @@ int usage_15_dump(void){ return 0; } int usage_15_restore(void){ - char *options[][2]={ + char *options[][2]={ {"h", "this help"}, {"-2", "use slower '1 out of 256' mode"}, {"-o", "set OPTION Flag (needed for TI)"}, @@ -398,7 +398,7 @@ int usage_15_readmulti(void){ int CmdHF15Demod(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_15_demod(); - + // The sampling rate is 106.353 ksps/s, for T = 18.8 us int i, j; int max = 0, maxPos = 0; @@ -419,7 +419,7 @@ int CmdHF15Demod(const char *Cmd) { } PrintAndLogEx(NORMAL, "SOF at %d, correlation %d", maxPos, max / (ARRAYLEN(FrameSOF) / skip)); - + i = maxPos + ARRAYLEN(FrameSOF) / skip; int k = 0; uint8_t outBuf[20]; @@ -439,7 +439,7 @@ int CmdHF15Demod(const char *Cmd) { // Even things out by the length of the target waveform. corr0 *= 4; corr1 *= 4; - + if (corrEOF > corr1 && corrEOF > corr0) { PrintAndLogEx(NORMAL, "EOF at %d", i); break; @@ -459,13 +459,13 @@ int CmdHF15Demod(const char *Cmd) { break; } } - + if (mask != 0x01) { PrintAndLogEx(WARNING, "Error, uneven octet! (discard extra bits!)"); PrintAndLogEx(NORMAL, " mask = %02x", mask); } PrintAndLogEx(NORMAL, "%d octets", k); - + for (i = 0; i < k; i++) PrintAndLogEx(NORMAL, "# %2d: %02x ", i, outBuf[i]); @@ -480,10 +480,10 @@ int CmdHF15Samples(const char *Cmd) { if (cmdp == 'h' || cmdp == 'H') return usage_15_samples(); UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693, {0,0,0}}; - clearCommandBuffer(); + clearCommandBuffer(); SendCommand(&c); - - //download samples + + //download samples getSamples(0, false); return 0; } @@ -504,17 +504,17 @@ int CmdHF15Info(const char *Cmd) { char cmdbuf[100]; char *cmd = cmdbuf; memset(cmdbuf, 0, sizeof(cmdbuf)); - + strncpy(cmd, Cmd, 99); - + if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_SYSINFO) ) return 0; AddCrc(req, c.arg[0]); c.arg[0] += 2; - //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(c.d.asBytes, reqlen) ); - + //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(c.d.asBytes, reqlen) ); + clearCommandBuffer(); SendCommand(&c); @@ -522,44 +522,44 @@ int CmdHF15Info(const char *Cmd) { PrintAndLogEx(WARNING, "iso15693 card select failed"); return 1; } - + uint32_t status = resp.arg[0]; - + if ( status < 2 ) { PrintAndLogEx(WARNING, "iso15693 card doesn't answer to systeminfo command"); - return 1; + return 1; } - - recv = resp.d.asBytes; - + + recv = resp.d.asBytes; + if ( recv[0] & ISO15_RES_ERROR ) { - PrintAndLogEx(WARNING, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + PrintAndLogEx(WARNING, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); return 3; } - + PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, recv+2)); PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(recv+2)); PrintAndLogEx(NORMAL, " SYSINFO : %s", sprint_hex(recv, status-2)); // DSFID - if (recv[1] & 0x01) + if (recv[1] & 0x01) PrintAndLogEx(NORMAL, " - DSFID supported [0x%02X]", recv[10]); - else + else PrintAndLogEx(NORMAL, " - DSFID not supported"); - + // AFI - if (recv[1] & 0x02) + if (recv[1] & 0x02) PrintAndLogEx(NORMAL, " - AFI supported [0x%02X]", recv[11]); - else + else PrintAndLogEx(NORMAL, " - AFI not supported"); // IC reference - if (recv[1] & 0x08) + if (recv[1] & 0x08) PrintAndLogEx(NORMAL, " - IC reference supported [0x%02X]", recv[14]); - else + else PrintAndLogEx(NORMAL, " - IC reference not supported"); - // memory + // memory if (recv[1] & 0x04) { PrintAndLogEx(NORMAL, " - Tag provides info on memory layout (vendor dependent)"); uint8_t blocks = recv[12]+1; @@ -577,7 +577,7 @@ int CmdHF15Info(const char *Cmd) { int CmdHF15Record(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_15_record(); - + UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693, {0,0,0}}; clearCommandBuffer(); SendCommand(&c); @@ -586,7 +586,7 @@ int CmdHF15Record(const char *Cmd) { // used with 'hf search' int HF15Reader(const char *Cmd, bool verbose) { - uint8_t uid[8] = {0,0,0,0,0,0,0,0}; + uint8_t uid[8] = {0,0,0,0,0,0,0,0}; if (!getUID(uid)) { if (verbose) PrintAndLogEx(WARNING, "No tag found."); return 0; @@ -600,7 +600,7 @@ int HF15Reader(const char *Cmd, bool verbose) { int CmdHF15Reader(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_15_reader(); - + HF15Reader(Cmd, true); return 0; } @@ -611,12 +611,12 @@ int CmdHF15Sim(const char *Cmd) { char cmdp =tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_sim(); - uint8_t uid[8] = {0,0,0,0,0,0,0,0}; + uint8_t uid[8] = {0,0,0,0,0,0,0,0}; if (param_gethex(Cmd, 0, uid, 16)) { PrintAndLogEx(WARNING, "UID must include 16 HEX symbols"); return 0; } - + PrintAndLogEx(SUCCESS, "Starting simulating UID %s", sprint_hex(uid, sizeof(uid)) ); UsbCommand c = {CMD_SIMTAG_ISO_15693, {0, 0, 0}}; @@ -634,7 +634,7 @@ int CmdHF15Afi(const char *Cmd) { if (cmdp == 'h') return usage_15_findafi(); PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); - + UsbCommand c = {CMD_ISO_15693_FIND_AFI, {strtol(Cmd, NULL, 0), 0, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -649,20 +649,20 @@ typedef struct { // Reads all memory pages // need to write to file int CmdHF15Dump(const char*Cmd) { - + uint8_t fileNameLen = 0; char filename[FILE_PATH_SIZE] = {0}; char * fptr = filename; bool errors = false; uint8_t cmdp = 0; - uint8_t uid[8] = {0,0,0,0,0,0,0,0}; - + uint8_t uid[8] = {0,0,0,0,0,0,0,0}; + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_15_dump(); case 'f': - fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); + fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); cmdp += 2; break; default: @@ -674,7 +674,7 @@ int CmdHF15Dump(const char*Cmd) { //Validations if (errors) return usage_15_dump(); - + if (fileNameLen < 1) { PrintAndLogEx(INFO, "Using UID as filename"); @@ -683,12 +683,12 @@ int CmdHF15Dump(const char*Cmd) { PrintAndLogEx(WARNING, "No tag found."); return 1; } - - fptr += sprintf(fptr, "hf-15-"); + + fptr += sprintf(fptr, "hf-15-"); FillFileNameByUID(fptr,uid,"-dump",sizeof(uid)); - } + } // detect blocksize from card :) - + PrintAndLogEx(NORMAL, "Reading memory from tag UID " _YELLOW_(%s), sprintUID(NULL, uid)); int blocknum = 0; @@ -696,7 +696,7 @@ int CmdHF15Dump(const char*Cmd) { // memory. t15memory mem[256]; - + uint8_t data[256*4] = {0}; memset(data, 0, sizeof(data)); @@ -708,64 +708,64 @@ int CmdHF15Dump(const char*Cmd) { // copy uid to read command memcpy(req+2, uid, sizeof(uid)); - + for (int retry = 0; retry < 5; retry++) { - + req[10] = blocknum; AddCrc(req, 11); c.arg[0] = 13; - + clearCommandBuffer(); SendCommand(&c); - + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { uint8_t len = resp.arg[0]; if ( len < 2 ) { PrintAndLogEx(FAILED, "iso15693 card select failed"); - continue; + continue; } - + recv = resp.d.asBytes; - + if ( !CheckCrc(recv, len) ) { PrintAndLogEx(FAILED, "crc fail"); continue; } if (recv[0] & ISO15_RES_ERROR) { - PrintAndLogEx(FAILED, "Tag returned Error %i: %s", recv[1], TagErrorStr(recv[1]) ); + PrintAndLogEx(FAILED, "Tag returned Error %i: %s", recv[1], TagErrorStr(recv[1]) ); break; } - + mem[blocknum].lock = resp.d.asBytes[0]; - memcpy(mem[blocknum].block, resp.d.asBytes + 1, 4); + memcpy(mem[blocknum].block, resp.d.asBytes + 1, 4); memcpy(data + (blocknum * 4), resp.d.asBytes + 1, 4); - + retry = 0; blocknum++; - + printf("."); fflush(stdout); - } + } } PrintAndLogEx(NORMAL, "\n"); PrintAndLogEx(NORMAL, "block# | data |lck| ascii"); - PrintAndLogEx(NORMAL, "---------+--------------+---+----------"); + PrintAndLogEx(NORMAL, "---------+--------------+---+----------"); for (int i = 0; i < blocknum; i++) { PrintAndLogEx(NORMAL, "%3d/0x%02X | %s | %d | %s", i, i, sprint_hex(mem[i].block, 4 ), mem[i].lock, sprint_ascii(mem[i].block, 4) ); } PrintAndLogEx(NORMAL, "\n"); size_t datalen = blocknum * 4; - saveFileEML(filename, "eml", data, datalen, 4); + saveFileEML(filename, "eml", data, datalen, 4); saveFile(filename, "bin", data, datalen); return 0; } int CmdHF15Restore(const char*Cmd) { FILE *f; - + uint8_t uid[8]={0x00}; char filename[FILE_PATH_SIZE] = {0x00}; char buff[255] = {0x00}; @@ -796,20 +796,20 @@ int CmdHF15Restore(const char*Cmd) { break; case 'f': param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); - cmdp++; + cmdp++; break; case 'r': retries=param_get8ex(Cmd, cmdp+1, 3, 10); - cmdp++; + cmdp++; break; case 'b': blocksize=param_get8ex(Cmd, cmdp+1, 4, 10); - cmdp++; + cmdp++; break; case 'u': param_getstr(Cmd, cmdp+1, buff, FILE_PATH_SIZE); - cmdp++; - snprintf(filename,sizeof(filename),"hf-15-dump-%s-bin",buff); + cmdp++; + snprintf(filename,sizeof(filename),"hf-15-dump-%s-bin",buff); break; case 'h': return usage_15_restore(); @@ -821,7 +821,7 @@ int CmdHF15Restore(const char*Cmd) { } PrintAndLogEx(INFO,"Blocksize: %u",blocksize); - + if ( !strlen(filename)) { PrintAndLogEx(WARNING,"Please provide a filename"); return usage_15_restore(); @@ -831,18 +831,18 @@ int CmdHF15Restore(const char*Cmd) { PrintAndLogEx(WARNING, "Could not find file %s", filename); return 2; } - + if (!getUID(uid)) { PrintAndLogEx(WARNING, "No tag found"); fclose(f); return 3; } - + while (1) { tried = 0; hex[0] = 0x00; tmpCmd[0] = 0x00; - + bytes_read = fread( buff, 1, blocksize, f ); if ( bytes_read == 0) { PrintAndLogEx(SUCCESS, "File reading done `%s`", filename); @@ -853,13 +853,13 @@ int CmdHF15Restore(const char*Cmd) { fclose(f); return 2; } - + for(int j=0; j < blocksize; j++) snprintf(hex+j*2, 3, "%02X", buff[j]); - + for(int j=0; j < sizeof(uid)/sizeof(uid[0]); j++) snprintf(buff+j*2,3,"%02X", uid[j]); - + //TODO: Addressed mode currently not work //snprintf(tmpCmd, sizeof(tmpCmd), "%s %s %d %s", newCmdPrefix, buff, i, hex); snprintf(tmpCmd, sizeof(tmpCmd), "%s u %u %s", newCmdPrefix, i, hex); @@ -894,23 +894,23 @@ int CmdHF15Raw(const char *Cmd) { char buf[5] = ""; uint8_t data[100]; uint32_t datalen = 0, temp; - + // strip while (*Cmd==' ' || *Cmd=='\t') Cmd++; - + while (Cmd[i]!='\0') { if (Cmd[i]==' ' || Cmd[i]=='\t') { i++; continue; } if (Cmd[i]=='-') { switch (Cmd[i+1]) { - case 'r': - case 'R': + case 'r': + case 'R': reply = 0; break; case '2': fast = 0; break; case 'c': - case 'C': + case 'C': crc = true; break; default: @@ -926,7 +926,7 @@ int CmdHF15Raw(const char *Cmd) { buf[strlen(buf)+1] = 0; buf[strlen(buf)] = Cmd[i]; i++; - + if (strlen(buf) >= 2) { sscanf(buf, "%x", &temp); data[datalen] = (uint8_t)(temp & 0xff); @@ -938,20 +938,20 @@ int CmdHF15Raw(const char *Cmd) { PrintAndLogEx(WARNING, "Invalid char on input"); return 0; } - + if (crc) { AddCrc(data, datalen); datalen += 2; } - + c.arg[0] = datalen; c.arg[1] = fast; c.arg[2] = reply; memcpy(c.d.asBytes, data, datalen); - clearCommandBuffer(); + clearCommandBuffer(); SendCommand(&c); - + if (reply) { if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { uint8_t len = resp.arg[0]; @@ -959,7 +959,7 @@ int CmdHF15Raw(const char *Cmd) { PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) ); } else { PrintAndLogEx(WARNING, "timeout while waiting for reply."); - } + } } return 0; } @@ -977,7 +977,7 @@ int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd) { // strip while (**cmd==' ' || **cmd=='\t') (*cmd)++; - + if (strstr(*cmd, "-2") == *cmd) { c->arg[1] = 0; // use 1of256 (*cmd) += 2; @@ -985,15 +985,15 @@ int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd) { // strip while (**cmd==' ' || **cmd=='\t') (*cmd)++; - + if (strstr(*cmd, "-o") == *cmd) { req[reqlen] = ISO15_REQ_OPTION; (*cmd) += 2; } - + // strip while (**cmd == ' ' || **cmd == '\t') (*cmd)++; - + switch (**cmd) { case 0: PrintAndLogEx(WARNING, "missing addr"); @@ -1017,28 +1017,28 @@ int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd) { memcpy(&req[reqlen], uid, sizeof(uid)); PrintAndLogEx(NORMAL, "Detected UID %s", sprintUID(NULL, uid)); reqlen += sizeof(uid); - break; + break; default: req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; req[reqlen++] = iso15cmd; - + // parse UID for (int i=0; i<8 && (*cmd)[i*2] && (*cmd)[i*2+1]; i++) { sscanf((char[]){(*cmd)[i*2], (*cmd)[i*2+1],0}, "%X", &temp); uid[7-i] = temp & 0xff; - } - + } + PrintAndLogEx(NORMAL, "Using UID %s", sprintUID(NULL, uid)); memcpy(&req[reqlen], uid, sizeof(uid)); reqlen += sizeof(uid); break; } - // skip to next space + // skip to next space while (**cmd!=' ' && **cmd!='\t') (*cmd)++; // skip over the space while (**cmd==' ' || **cmd=='\t') (*cmd)++; - - c->arg[0] = reqlen; + + c->arg[0] = reqlen; return 1; } @@ -1066,7 +1066,7 @@ int CmdHF15Readmulti(const char *Cmd) { // add OPTION flag, in order to get lock-info req[0] |= ISO15_REQ_OPTION; - + reqlen = c.arg[0]; // decimal @@ -1074,11 +1074,11 @@ int CmdHF15Readmulti(const char *Cmd) { pagecount = param_get8ex(cmd, 1, 0, 10); //PrintAndLogEx(NORMAL, "ice %d %d\n", pagenum, pagecount); - + // 0 means 1 page, - // 1 means 2 pages, ... - if (pagecount > 0) pagecount--; - + // 1 means 2 pages, ... + if (pagecount > 0) pagecount--; + req[reqlen++] = pagenum; req[reqlen++] = pagecount; AddCrc(req, reqlen); @@ -1086,27 +1086,27 @@ int CmdHF15Readmulti(const char *Cmd) { clearCommandBuffer(); SendCommand(&c); - + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { PrintAndLogEx(FAILED, "iso15693 card select failed"); return 1; } - - uint32_t status = resp.arg[0]; + + uint32_t status = resp.arg[0]; if ( status < 2 ) { PrintAndLogEx(FAILED, "iso15693 card select failed"); - return 1; + return 1; } - recv = resp.d.asBytes; - + recv = resp.d.asBytes; + if (!CheckCrc(recv, status)) { PrintAndLogEx(FAILED, "CRC failed"); return 2; - } - + } + if ( recv[0] & ISO15_RES_ERROR ) { - PrintAndLogEx(FAILED, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + PrintAndLogEx(FAILED, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); return 3; } @@ -1116,7 +1116,7 @@ int CmdHF15Readmulti(const char *Cmd) { // print response PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "block# | data |lck| ascii"); - PrintAndLogEx(NORMAL, "---------+--------------+---+----------"); + PrintAndLogEx(NORMAL, "---------+--------------+---+----------"); for (int i = start; i < stop; i += 5) { PrintAndLogEx(NORMAL, "%3d/0x%02X | %s | %d | %s", currblock, currblock, sprint_hex(recv+i+1, 4 ), recv[i], sprint_ascii(recv+i+1, 4) ); currblock++; @@ -1133,7 +1133,7 @@ int CmdHF15Read(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_read(); - + UsbCommand resp; uint8_t *recv; @@ -1141,27 +1141,27 @@ int CmdHF15Read(const char *Cmd) { // arg0 (datalen, cmd len? .arg0 == crc?) // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 ) // arg2 (recv == 1 == expect a response) - UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; + UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; uint8_t *req = c.d.asBytes; int reqlen = 0, blocknum; char cmdbuf[100]; char *cmd = cmdbuf; strncpy(cmd, Cmd, 99); - + if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_READ) ) return 0; // add OPTION flag, in order to get lock-info req[0] |= ISO15_REQ_OPTION; - + reqlen = c.arg[0]; blocknum = strtol(cmd, NULL, 0); - + req[reqlen++] = (uint8_t)blocknum; - + AddCrc(req, reqlen); - + c.arg[0] = reqlen+2; clearCommandBuffer(); @@ -1171,31 +1171,31 @@ int CmdHF15Read(const char *Cmd) { PrintAndLogEx(NORMAL, "iso15693 card select failed"); return 1; } - - uint32_t status = resp.arg[0]; + + uint32_t status = resp.arg[0]; if ( status < 2 ) { PrintAndLogEx(NORMAL, "iso15693 card select failed"); - return 1; + return 1; } - recv = resp.d.asBytes; - + recv = resp.d.asBytes; + if ( !CheckCrc(recv, status) ) { PrintAndLogEx(NORMAL, "CRC failed"); return 2; - } - + } + if ( recv[0] & ISO15_RES_ERROR ) { - PrintAndLogEx(WARNING, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + PrintAndLogEx(WARNING, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); return 3; } - + // print response PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "block #%3d |lck| ascii", blocknum ); PrintAndLogEx(NORMAL, "------------+---+------" ); PrintAndLogEx(NORMAL, "%s| %d | %s", sprint_hex(recv+2, status-4), recv[1], sprint_ascii(recv+2, status-4) ); - PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, ""); return 0; } @@ -1207,7 +1207,7 @@ int CmdHF15Write(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_write(); - + UsbCommand resp; uint8_t *recv; UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? @@ -1216,38 +1216,38 @@ int CmdHF15Write(const char *Cmd) { char cmdbuf[100]; char *cmd = cmdbuf; char *cmd2; - + strncpy(cmd, Cmd, 99); if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_WRITE) ) return 0; reqlen = c.arg[0]; - - // *cmd -> page num ; *cmd2 -> data + + // *cmd -> page num ; *cmd2 -> data cmd2=cmd; while (*cmd2!=' ' && *cmd2!='\t' && *cmd2) cmd2++; *cmd2 = 0; - cmd2++; - + cmd2++; + pagenum = strtol(cmd, NULL, 0); - req[reqlen++] = (uint8_t)pagenum; - - while (cmd2[0] && cmd2[1]) { // hexdata, read by 2 hexchars + req[reqlen++] = (uint8_t)pagenum; + + while (cmd2[0] && cmd2[1]) { // hexdata, read by 2 hexchars if (*cmd2==' ') { - cmd2++; - continue; + cmd2++; + continue; } sscanf((char[]){cmd2[0],cmd2[1],0},"%X",&temp); req[reqlen++]=temp & 0xff; cmd2+=2; - } + } AddCrc(req, reqlen); c.arg[0] = reqlen+2; - + PrintAndLogEx(NORMAL, "iso15693 writing to page %02d (0x%02X) | data ", pagenum, pagenum); - + clearCommandBuffer(); SendCommand(&c); @@ -1255,25 +1255,25 @@ int CmdHF15Write(const char *Cmd) { PrintAndLogEx(FAILED, "iso15693 card timeout, data may be written anyway"); return 1; } - - uint32_t status = resp.arg[0]; + + uint32_t status = resp.arg[0]; if ( status < 2 ) { PrintAndLogEx(FAILED, "iso15693 card select failed"); - return 1; + return 1; } - recv = resp.d.asBytes; - + recv = resp.d.asBytes; + if ( !CheckCrc(recv, status) ) { PrintAndLogEx(FAILED, "CRC failed"); return 2; - } - + } + if ( recv[0] & ISO15_RES_ERROR ) { - PrintAndLogEx(NORMAL, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + PrintAndLogEx(NORMAL, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); return 3; } - + PrintAndLogEx(NORMAL, "OK"); return 0; } @@ -1283,22 +1283,22 @@ static command_t CommandTable15[] = { {"demod", CmdHF15Demod, 1, "Demodulate ISO15693 from tag"}, {"dump", CmdHF15Dump, 0, "Read all memory pages of an ISO15693 tag, save to file"}, {"findafi", CmdHF15Afi, 0, "Brute force AFI of an ISO15693 tag"}, - {"info", CmdHF15Info, 0, "Tag information"}, + {"info", CmdHF15Info, 0, "Tag information"}, {"list", CmdHF15List, 0, "[Deprecated] List ISO15693 history"}, - {"raw", CmdHF15Raw, 0, "Send raw hex data to tag"}, + {"raw", CmdHF15Raw, 0, "Send raw hex data to tag"}, {"reader", CmdHF15Reader, 0, "Act like an ISO15693 reader"}, {"record", CmdHF15Record, 0, "Record Samples (ISO15693)"}, {"restore", CmdHF15Restore, 0, "Restore from file to all memory pages of an ISO15693 tag"}, {"sim", CmdHF15Sim, 0, "Fake an ISO15693 tag"}, {"samples", CmdHF15Samples, 0, "Acquire Samples as Reader (enables carrier, sends inquiry)"}, - {"read", CmdHF15Read, 0, "Read a block"}, - {"write", CmdHF15Write, 0, "Write a block"}, + {"read", CmdHF15Read, 0, "Read a block"}, + {"write", CmdHF15Write, 0, "Write a block"}, {"readmulti", CmdHF15Readmulti, 0, "Reads multiple Blocks"}, {NULL, NULL, 0, NULL} }; int CmdHF15(const char *Cmd) { - clearCommandBuffer(); + clearCommandBuffer(); CmdsParse(CommandTable15, Cmd); return 0; } diff --git a/client/cmdhfepa.c b/client/cmdhfepa.c index dd110c9c0..4e7510fe0 100644 --- a/client/cmdhfepa.c +++ b/client/cmdhfepa.c @@ -127,8 +127,8 @@ int CmdHFEPAPACEReplay(const char *Cmd) memcpy(usb_cmd.d.asBytes, // + (j * sizeof(usb_cmd.d.asBytes)), apdus[i] + (j * sizeof(usb_cmd.d.asBytes)), packet_length); - - clearCommandBuffer(); + + clearCommandBuffer(); SendCommand(&usb_cmd); WaitForResponse(CMD_ACK, &resp); if (resp.arg[0] != 0) { diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index efb6b68d7..2a0380fc5 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -82,20 +82,20 @@ int CmdHFFelicaReader(const char *Cmd) { //SendCommand(&cDisconnect); return 0; } - + felica_card_select_t card; memcpy(&card, (felica_card_select_t *)resp.d.asBytes, sizeof(felica_card_select_t)); uint64_t status = resp.arg[0]; - + switch(status) { case 1: { - if (!silent) - PrintAndLogEx(WARNING, "card timeout"); + if (!silent) + PrintAndLogEx(WARNING, "card timeout"); break; } case 2: { if (!silent) - PrintAndLogEx(WARNING, "card answered wrong"); + PrintAndLogEx(WARNING, "card answered wrong"); break; } case 3: { @@ -105,15 +105,15 @@ int CmdHFFelicaReader(const char *Cmd) { } case 0: { PrintAndLogEx(SUCCESS, "FeliCa tag info"); - + PrintAndLogEx(NORMAL, "IDm %s", sprint_hex(card.IDm, sizeof(card.IDm))); PrintAndLogEx(NORMAL, " - CODE %s", sprint_hex(card.code, sizeof(card.code))); PrintAndLogEx(NORMAL, " - NFCID2 %s", sprint_hex(card.uid, sizeof(card.uid))); - + PrintAndLogEx(NORMAL, "Parameter (PAD) | %s", sprint_hex(card.PMm, sizeof(card.PMm))); PrintAndLogEx(NORMAL, " - IC CODE %s", sprint_hex(card.iccode, sizeof(card.iccode))); PrintAndLogEx(NORMAL, " - MRT %s", sprint_hex(card.mrt, sizeof(card.mrt))); - + PrintAndLogEx(NORMAL, "SERVICE CODE %s", sprint_hex(card.servicecode, sizeof(card.servicecode))); break; } @@ -125,12 +125,12 @@ int CmdHFFelicaReader(const char *Cmd) { int CmdHFFelicaSim(const char *Cmd) { bool errors = false; uint8_t flags = 0; - uint8_t tagtype = 1; + uint8_t tagtype = 1; uint8_t cmdp = 0; uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; int uidlen = 0; bool verbose = false; - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (param_getchar(Cmd, cmdp)) { case 'h': @@ -141,12 +141,12 @@ int CmdHFFelicaSim(const char *Cmd) { // Retrieve the tag type tagtype = param_get8ex(Cmd, cmdp+1, 0, 10); if (tagtype == 0) - errors = true; + errors = true; cmdp += 2; break; case 'u': case 'U': - // Retrieve the full 4,7,10 byte long uid + // Retrieve the full 4,7,10 byte long uid param_gethex_ex(Cmd, cmdp+1, uid, &uidlen); if (!errors) { PrintAndLogEx(NORMAL, "Emulating ISO18092/FeliCa tag with %d byte UID (%s)", uidlen>>1, sprint_hex(uid, uidlen>>1)); @@ -161,7 +161,7 @@ int CmdHFFelicaSim(const char *Cmd) { case 'e': case 'E': cmdp++; - break; + break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -171,29 +171,29 @@ int CmdHFFelicaSim(const char *Cmd) { //Validations if (errors || cmdp == 0) return usage_hf_felica_sim(); - - UsbCommand c = {CMD_FELICA_SIMULATE_TAG,{ tagtype, flags, 0 }}; + + UsbCommand c = {CMD_FELICA_SIMULATE_TAG,{ tagtype, flags, 0 }}; memcpy(c.d.asBytes, uid, uidlen>>1); clearCommandBuffer(); - SendCommand(&c); + SendCommand(&c); UsbCommand resp; - + if ( verbose ) PrintAndLogEx(NORMAL, "Press pm3-button to abort simulation"); - + while( !ukbhit() ){ - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; } return 0; } -int CmdHFFelicaSniff(const char *Cmd) { +int CmdHFFelicaSniff(const char *Cmd) { uint8_t cmdp = 0; uint64_t samples2skip = 0; uint64_t triggers2skip = 0; bool errors = false; - + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch(param_getchar(Cmd, cmdp)) { case 'h': @@ -204,7 +204,7 @@ int CmdHFFelicaSniff(const char *Cmd) { samples2skip = param_get32ex(Cmd, cmdp+1, 0, 10); cmdp += 2; break; - case 't': + case 't': case 'T': triggers2skip = param_get32ex(Cmd, cmdp+1, 0, 10); cmdp += 2; @@ -217,7 +217,7 @@ int CmdHFFelicaSniff(const char *Cmd) { } //Validations if (errors || cmdp == 0) return usage_hf_felica_sniff(); - + UsbCommand c = {CMD_FELICA_SNOOP, {samples2skip, triggers2skip, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -231,21 +231,21 @@ int CmdHFFelicaSimLite(const char *Cmd) { if (!uid) return usage_hf_felica_simlite(); - + UsbCommand c = {CMD_FELICA_LITE_SIM, {uid, 0, 0} }; clearCommandBuffer(); SendCommand(&c); return 0; } - + static void printSep() { PrintAndLogEx(NORMAL, "------------------------------------------------------------------------------------"); } uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) { - if (tracepos+19 >= tracelen) + if (tracepos+19 >= tracelen) return tracelen; - + trace += tracepos; uint8_t blocknum = trace[0]; uint8_t status1 = trace[1]; @@ -276,23 +276,23 @@ uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) { uint32_t regA = trace[3] | trace[4] << 8 | trace[5] << 16 | trace[ 6] << 24; uint32_t regB = trace[7] | trace[8] << 8 | trace[9] << 16 | trace[10] << 24; line[0] = 0; - for (int j = 0; j < 8; j++) + for (int j = 0; j < 8; j++) snprintf(line + (j*2), sizeof(line)-1-(j*2), "%02x", trace[j+11]); - + PrintAndLogEx(NORMAL, "REG: regA: %d regB: %d regC: %s ", regA, regB, line); } break; - case 0x80: PrintAndLogEx(NORMAL, "Random Challenge, WO: %s ", line); break; - case 0x81: PrintAndLogEx(NORMAL, "MAC, only set on dual read: %s ", line); break; + case 0x80: PrintAndLogEx(NORMAL, "Random Challenge, WO: %s ", line); break; + case 0x81: PrintAndLogEx(NORMAL, "MAC, only set on dual read: %s ", line); break; case 0x82: { char idd[20]; char idm[20]; - for (int j = 0; j < 8; j++) + for (int j = 0; j < 8; j++) snprintf(idd + (j*2), sizeof(idd)-1-(j*2), "%02x", trace[j+3]); - - for (int j = 0; j < 6; j++) + + for (int j = 0; j < 6; j++) snprintf(idm + (j*2), sizeof(idm)-1-(j*2), "%02x", trace[j+13]); - + PrintAndLogEx(NORMAL, "ID Block, IDd: 0x%s DFC: 0x%02x%02x Arb: %s ", idd, trace[11], trace [12], idm); } break; @@ -301,16 +301,16 @@ uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) { char pmm[20]; for (int j = 0; j < 8; j++) snprintf(idm + (j*2), sizeof(idm)-1-(j*2), "%02x", trace[j+3]); - + for (int j = 0; j < 8; j++) snprintf(pmm + (j*2), sizeof(pmm)-1-(j*2), "%02x", trace[j+11]); - + PrintAndLogEx(NORMAL, "DeviceId: IDm: 0x%s PMm: 0x%s ", idm, pmm); } - break; + break; case 0x84: PrintAndLogEx(NORMAL, "SER_C: 0x%02x%02x ", trace[3], trace[4]); break; - case 0x85: PrintAndLogEx(NORMAL, "SYS_Cl 0x%02x%02x ", trace[3], trace[4]); break; - case 0x86: PrintAndLogEx(NORMAL, "CKV (key version): 0x%02x%02x ", trace[3], trace[4]); break; + case 0x85: PrintAndLogEx(NORMAL, "SYS_Cl 0x%02x%02x ", trace[3], trace[4]); break; + case 0x86: PrintAndLogEx(NORMAL, "CKV (key version): 0x%02x%02x ", trace[3], trace[4]); break; case 0x87: PrintAndLogEx(NORMAL, "CK (card key), WO: %s ", line); break; case 0x88: { PrintAndLogEx(NORMAL, "Memory Configuration (MC):"); @@ -325,15 +325,15 @@ uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) { PrintAndLogEx(NORMAL, "Memory config writable : %s", (trace[3+2] == 0xff) ? "yes" : "no"); PrintAndLogEx(NORMAL, "RW access for S_PAD : %s ", sprint_bin(trace+3, 2) ); } - break; + break; case 0x90: { PrintAndLogEx(NORMAL, "Write count, RO: %02x %02x %02x ", trace[3], trace[4], trace[5]); } - break; + break; case 0x91: { PrintAndLogEx(NORMAL, "MAC_A, RW (auth): %s ", line); } - break; + break; case 0x92: PrintAndLogEx(NORMAL, "State:"); PrintAndLogEx(NORMAL, "Polling disabled: %s", trace[3+8] ? "yes" : "no"); @@ -342,7 +342,7 @@ uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) { case 0xa0: PrintAndLogEx(NORMAL, "CRC of all bloacks match : %s", (trace[3+2]==0xff) ? "no" : "yes"); break; - default: + default: PrintAndLogEx(WARNING, "INVALID %d: %s", blocknum, line); break; } @@ -360,7 +360,7 @@ int CmdHFFelicaDumpLite(const char *Cmd) { clearCommandBuffer(); SendCommand(&c); UsbCommand resp; - + uint8_t timeout = 0; while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { timeout++; @@ -381,32 +381,32 @@ int CmdHFFelicaDumpLite(const char *Cmd) { PrintAndLogEx(WARNING, "\nButton pressed. Aborted."); return 1; } - - uint64_t tracelen = resp.arg[1]; + + uint64_t tracelen = resp.arg[1]; uint8_t *trace = calloc(tracelen, sizeof(uint8_t)); if ( trace == NULL ) { - PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); + PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); return 1; } // only download data if there is any. - if ( tracelen > 0 ) { - + if ( tracelen > 0 ) { + if ( !GetFromDevice(BIG_BUF, trace, tracelen, 0, NULL, 2500, false) ){ PrintAndLogEx(WARNING, "command execution time out"); free(trace); return 0; } - + PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %d bytes)", tracelen); - + print_hex_break(trace, tracelen, 32); - + printSep(); uint16_t tracepos = 0; while (tracepos < tracelen) tracepos = PrintFliteBlock(tracepos, trace, tracelen); - + printSep(); } @@ -440,7 +440,7 @@ int CmdHFFelicaCmdRaw(const char *cmd) { case 'H': case 'h': return usage_hf_felica_raw(); - case 'r': + case 'r': reply = false; break; case 'c': @@ -455,7 +455,7 @@ int CmdHFFelicaCmdRaw(const char *cmd) { case 's': active_select = true; break; - case 'b': + case 'b': sscanf(cmd+i+2, "%d", &temp); numbits = temp & 0xFFFF; i+=3; @@ -507,14 +507,14 @@ int CmdHFFelicaCmdRaw(const char *cmd) { if (power) { c.arg[0] |= FELICA_NO_DISCONNECT; } - + if (datalen > 0) { c.arg[0] |= FELICA_RAW; } - + // Max buffer is USB_CMD_DATA_SIZE datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; - + c.arg[1] = (datalen & 0xFFFF) | (uint32_t)(numbits << 16); memcpy(c.d.asBytes, data, datalen); @@ -534,7 +534,7 @@ void waitCmdFelica(uint8_t iSelect) { UsbCommand resp; uint16_t len = 0; - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { len = iSelect ? (resp.arg[1] & 0xffff) : (resp.arg[0] & 0xffff); PrintAndLogEx(NORMAL, "received %i octets", len); if(!len) diff --git a/client/cmdhffido.c b/client/cmdhffido.c index 6d7741153..ea5d55c66 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -50,17 +50,17 @@ static int CmdHelp(const char *Cmd); int CmdHFFidoInfo(const char *cmd) { - + if (cmd && strlen(cmd) > 0) PrintAndLog("WARNING: command don't have any parameters.\n"); - + // info about 14a part CmdHF14AInfo(""); // FIDO info - PrintAndLog("--------------------------------------------"); + PrintAndLog("--------------------------------------------"); SetAPDULogging(false); - + uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; @@ -70,27 +70,27 @@ int CmdHFFidoInfo(const char *cmd) { DropField(); return res; } - + if (sw != 0x9000) { if (sw) - PrintAndLog("Not a FIDO card! APDU response: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLog("Not a FIDO card! APDU response: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); else - PrintAndLog("APDU exchange error. Card returns 0x0000."); - + PrintAndLog("APDU exchange error. Card returns 0x0000."); + DropField(); return 0; } - + if (!strncmp((char *)buf, "U2F_V2", 7)) { if (!strncmp((char *)buf, "FIDO_2_0", 8)) { - PrintAndLog("FIDO2 authenricator detected. Version: %.*s", len, buf); + PrintAndLog("FIDO2 authenricator detected. Version: %.*s", len, buf); } else { - PrintAndLog("FIDO authenricator detected (not standard U2F)."); - PrintAndLog("Non U2F authenticator version:"); + PrintAndLog("FIDO authenricator detected (not standard U2F)."); + PrintAndLog("Non U2F authenticator version:"); dump_buffer((const unsigned char *)buf, len, NULL, 0); } } else { - PrintAndLog("FIDO U2F authenricator detected. Version: %.*s", len, buf); + PrintAndLog("FIDO U2F authenricator detected. Version: %.*s", len, buf); } res = FIDO2GetInfo(buf, sizeof(buf), &len, &sw); @@ -99,32 +99,32 @@ int CmdHFFidoInfo(const char *cmd) { return res; } if (sw != 0x9000) { - PrintAndLog("FIDO2 version not exists (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - + PrintAndLog("FIDO2 version not exists (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + return 0; } - + if(buf[0]) { - PrintAndLog("FIDO2 ger version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); + PrintAndLog("FIDO2 ger version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); return 0; } if (len > 1) { // if (false) { -// PrintAndLog("FIDO2 version: (len=%d)", len); +// PrintAndLog("FIDO2 version: (len=%d)", len); // dump_buffer((const unsigned char *)buf, len, NULL, 0); // } - PrintAndLog("FIDO2 version CBOR decoded:"); + PrintAndLog("FIDO2 version CBOR decoded:"); TinyCborPrintFIDOPackage(fido2CmdGetInfo, true, &buf[1], len - 1); } else { - PrintAndLog("FIDO2 version length error"); + PrintAndLog("FIDO2 version length error"); } - + return 0; } -json_t *OpenJson(int paramnum, char *fname, void* argtable[], bool *err) { +json_t *OpenJson(int paramnum, char *fname, void* argtable[], bool *err) { json_t *root = NULL; json_error_t error; *err = false; @@ -132,17 +132,17 @@ json_t *OpenJson(int paramnum, char *fname, void* argtable[], bool *err) { uint8_t jsonname[250] ={0}; char *cjsonname = (char *)jsonname; int jsonnamelen = 0; - + // CLIGetStrWithReturn(paramnum, jsonname, &jsonnamelen); if (CLIParamStrToBuf(arg_get_str(paramnum), jsonname, sizeof(jsonname), &jsonnamelen)) { CLIParserFree(); return NULL; } - + // current path + file name if (!strstr(cjsonname, ".json")) strcat(cjsonname, ".json"); - + if (jsonnamelen) { strcpy(fname, get_my_executable_directory()); strcat(fname, cjsonname); @@ -151,16 +151,16 @@ json_t *OpenJson(int paramnum, char *fname, void* argtable[], bool *err) { if (!root) { PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); *err = true; - return NULL; + return NULL; } - + if (!json_is_object(root)) { PrintAndLog("ERROR: Invalid json format. root must be an object."); json_decref(root); *err = true; - return NULL; + return NULL; } - + } else { root = json_object(); } @@ -175,9 +175,9 @@ int CmdHFFidoRegister(const char *cmd) { int applen = 0; uint8_t adata[250] = {0}; json_t *root = NULL; - - CLIParserInit("hf fido reg", - "Initiate a U2F token registration. Needs two 32-byte hash number. \nchallenge parameter (32b) and application parameter (32b).", + + CLIParserInit("hf fido reg", + "Initiate a U2F token registration. Needs two 32-byte hash number. \nchallenge parameter (32b) and application parameter (32b).", "Usage:\n\thf fido reg -> execute command with 2 parameters, filled 0x00\n" "\thf fido reg 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters" "\thf fido reg -p s0 s1 -> execute command with plain parameters"); @@ -194,7 +194,7 @@ int CmdHFFidoRegister(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool APDULogging = arg_get_lit(1); bool verbose = arg_get_lit(2); bool verbose2 = arg_get_lit(2) > 1; @@ -206,12 +206,12 @@ int CmdHFFidoRegister(const char *cmd) { root = OpenJson(5, fname, argtable, &err); if(err) return 1; - if (root) { + if (root) { size_t jlen; JsonLoadBufAsHex(root, "$.ChallengeParam", data, 32, &jlen); JsonLoadBufAsHex(root, "$.ApplicationParam", &data[32], 32, &jlen); } - + if (paramsPlain) { memset(cdata, 0x00, 32); CLIGetStrWithReturn(6, cdata, &chlen); @@ -228,8 +228,8 @@ int CmdHFFidoRegister(const char *cmd) { } if (chlen) memmove(data, cdata, 32); - - + + if (paramsPlain) { memset(adata, 0x00, 32); CLIGetStrWithReturn(7, adata, &applen); @@ -246,14 +246,14 @@ int CmdHFFidoRegister(const char *cmd) { } if (applen) memmove(&data[32], adata, 32); - - CLIParserFree(); - + + CLIParserFree(); + SetAPDULogging(APDULogging); // challenge parameter [32 bytes] - The challenge parameter is the SHA-256 hash of the Client Data, a stringified JSON data structure that the FIDO Client prepares // application parameter [32 bytes] - The application parameter is the SHA-256 hash of the UTF-8 encoding of the application identity - + uint8_t buf[2048] = {0}; size_t len = 0; uint16_t sw = 0; @@ -266,9 +266,9 @@ int CmdHFFidoRegister(const char *cmd) { DropField(); return res; } - + if (sw != 0x9000) { - PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); DropField(); return 2; } @@ -279,12 +279,12 @@ int CmdHFFidoRegister(const char *cmd) { PrintAndLog("Can't execute register command. res=%x. Exit...", res); return res; } - + if (sw != 0x9000) { - PrintAndLog("ERROR execute register command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLog("ERROR execute register command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); return 3; } - + PrintAndLog(""); if (APDULogging) PrintAndLog("---------------------------------------------------------------"); @@ -300,10 +300,10 @@ int CmdHFFidoRegister(const char *cmd) { return 5; } PrintAndLog("User public key: %s", sprint_hex(&buf[1], 65)); - + uint8_t keyHandleLen = buf[66]; PrintAndLog("Key handle[%d]: %s", keyHandleLen, sprint_hex(&buf[67], keyHandleLen)); - + int derp = 67 + keyHandleLen; int derLen = (buf[derp + 2] << 8) + buf[derp + 3] + 4; if (verbose2) { @@ -315,26 +315,26 @@ int CmdHFFidoRegister(const char *cmd) { PrintAndLog("------------------DER-------------------"); PrintAndLog("DER certificate[%d]: %s...", derLen, sprint_hex(&buf[derp], 20)); } - + // check and print DER certificate uint8_t public_key[65] = {0}; - + // print DER certificate in TLV view if (showDERTLV) { PrintAndLog("----------------DER TLV-----------------"); asn1_print(&buf[derp], derLen, " "); PrintAndLog("----------------DER TLV-----------------"); } - + FIDOCheckDERAndGetKey(&buf[derp], derLen, verbose, public_key, sizeof(public_key)); - + // get hash int hashp = 1 + 65 + 1 + keyHandleLen + derLen; PrintAndLog("Hash[%d]: %s", len - hashp, sprint_hex(&buf[hashp], len - hashp)); // check ANSI X9.62 format ECDSA signature (on P-256) - uint8_t rval[300] = {0}; - uint8_t sval[300] = {0}; + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; res = ecdsa_asn1_get_signature(&buf[hashp], len - hashp, rval, sval); if (!res) { if (verbose) { @@ -346,7 +346,7 @@ int CmdHFFidoRegister(const char *cmd) { size_t xbuflen = 0; res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, "\x00", 1, - &data[32], 32, // application parameter + &data[32], 32, // application parameter &data[0], 32, // challenge parameter &buf[67], keyHandleLen, // keyHandle &buf[1], 65, // user public key @@ -362,11 +362,11 @@ int CmdHFFidoRegister(const char *cmd) { } else { PrintAndLog("Signature is OK."); } - + } else { PrintAndLog("Invalid signature. res=%d.", res); } - + PrintAndLog("\nauth command: "); printf("hf fido auth %s%s", paramsPlain?"-p ":"", sprint_hex_inrow(&buf[67], keyHandleLen)); if(chlen || applen) @@ -374,7 +374,7 @@ int CmdHFFidoRegister(const char *cmd) { if(applen) printf(" %s", paramsPlain?(char *)adata:sprint_hex_inrow(adata, 32)); printf("\n"); - + if (root) { JsonSaveBufAsHex(root, "ChallengeParam", data, 32); JsonSaveBufAsHex(root, "ApplicationParam", &data[32], 32); @@ -382,18 +382,18 @@ int CmdHFFidoRegister(const char *cmd) { JsonSaveInt(root, "KeyHandleLen", keyHandleLen); JsonSaveBufAsHexCompact(root, "KeyHandle", &buf[67], keyHandleLen); JsonSaveBufAsHexCompact(root, "DER", &buf[67 + keyHandleLen], derLen); - + res = json_dump_file(root, fname, JSON_INDENT(2)); if (res) { PrintAndLog("ERROR: can't save the file: %s", fname); return 200; } PrintAndLog("File `%s` saved.", fname); - + // free json object json_decref(root); } - + return 0; }; @@ -401,13 +401,13 @@ int CmdHFFidoAuthenticate(const char *cmd) { uint8_t data[512] = {0}; uint8_t hdata[250] = {0}; bool public_key_loaded = false; - uint8_t public_key[65] = {0}; + uint8_t public_key[65] = {0}; int hdatalen = 0; uint8_t keyHandleLen = 0; json_t *root = NULL; - - CLIParserInit("hf fido auth", - "Initiate a U2F token authentication. Needs key handle and two 32-byte hash number. \nkey handle(var 0..255), challenge parameter (32b) and application parameter (32b).", + + CLIParserInit("hf fido auth", + "Initiate a U2F token authentication. Needs key handle and two 32-byte hash number. \nkey handle(var 0..255), challenge parameter (32b) and application parameter (32b).", "Usage:\n\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n" "\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f " "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters"); @@ -428,7 +428,7 @@ int CmdHFFidoAuthenticate(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool APDULogging = arg_get_lit(1); bool verbose = arg_get_lit(2); bool paramsPlain = arg_get_lit(3); @@ -443,7 +443,7 @@ int CmdHFFidoAuthenticate(const char *cmd) { root = OpenJson(7, fname, argtable, &err); if(err) return 1; - if (root) { + if (root) { size_t jlen; JsonLoadBufAsHex(root, "$.ChallengeParam", data, 32, &jlen); JsonLoadBufAsHex(root, "$.ApplicationParam", &data[32], 32, &jlen); @@ -452,7 +452,7 @@ int CmdHFFidoAuthenticate(const char *cmd) { data[64] = keyHandleLen; JsonLoadBufAsHex(root, "$.PublicKey", public_key, 65, &jlen); public_key_loaded = (jlen > 0); - } + } // public key CLIGetHexWithReturn(8, hdata, &hdatalen); @@ -463,8 +463,8 @@ int CmdHFFidoAuthenticate(const char *cmd) { if (hdatalen) { memmove(public_key, hdata, hdatalen); public_key_loaded = true; - } - + } + CLIGetHexWithReturn(9, hdata, &hdatalen); if (hdatalen > 255) { PrintAndLog("ERROR: application parameter length must be less than 255."); @@ -510,8 +510,8 @@ int CmdHFFidoAuthenticate(const char *cmd) { if (hdatalen) memmove(&data[32], hdata, 32); - CLIParserFree(); - + CLIParserFree(); + SetAPDULogging(APDULogging); // (in parameter) conrtol byte 0x07 - check only, 0x03 - user presense + cign. 0x08 - sign only @@ -521,7 +521,7 @@ int CmdHFFidoAuthenticate(const char *cmd) { // key handle [N] uint8_t datalen = 32 + 32 + 1 + keyHandleLen; - + uint8_t buf[2048] = {0}; size_t len = 0; uint16_t sw = 0; @@ -534,9 +534,9 @@ int CmdHFFidoAuthenticate(const char *cmd) { DropField(); return res; } - + if (sw != 0x9000) { - PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); DropField(); return 2; } @@ -547,12 +547,12 @@ int CmdHFFidoAuthenticate(const char *cmd) { PrintAndLog("Can't execute authentication command. res=%x. Exit...", res); return res; } - + if (sw != 0x9000) { - PrintAndLog("ERROR execute authentication command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLog("ERROR execute authentication command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); return 3; } - + PrintAndLog("---------------------------------------------------------------"); PrintAndLog("User presence: %s", (buf[0]?"verified":"not verified")); uint32_t cntr = (uint32_t)bytes_to_num(&buf[1], 4); @@ -560,8 +560,8 @@ int CmdHFFidoAuthenticate(const char *cmd) { PrintAndLog("Hash[%d]: %s", len - 5, sprint_hex(&buf[5], len - 5)); // check ANSI X9.62 format ECDSA signature (on P-256) - uint8_t rval[300] = {0}; - uint8_t sval[300] = {0}; + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; res = ecdsa_asn1_get_signature(&buf[5], len - 5, rval, sval); if (!res) { if (verbose) { @@ -588,27 +588,27 @@ int CmdHFFidoAuthenticate(const char *cmd) { } else { PrintAndLog("Signature is OK."); } - } else { + } else { PrintAndLog("No public key provided. can't check signature."); } } else { PrintAndLog("Invalid signature. res=%d.", res); } - + if (root) { JsonSaveBufAsHex(root, "ChallengeParam", data, 32); JsonSaveBufAsHex(root, "ApplicationParam", &data[32], 32); JsonSaveInt(root, "KeyHandleLen", keyHandleLen); JsonSaveBufAsHexCompact(root, "KeyHandle", &data[65], keyHandleLen); JsonSaveInt(root, "Counter", cntr); - + res = json_dump_file(root, fname, JSON_INDENT(2)); if (res) { PrintAndLog("ERROR: can't save the file: %s", fname); return 200; } PrintAndLog("File `%s` saved.", fname); - + // free json object json_decref(root); } @@ -616,7 +616,7 @@ int CmdHFFidoAuthenticate(const char *cmd) { }; void CheckSlash(char *fileName) { - if ((fileName[strlen(fileName) - 1] != '/') && + if ((fileName[strlen(fileName) - 1] != '/') && (fileName[strlen(fileName) - 1] != '\\')) strcat(fileName, "/"); } @@ -625,22 +625,22 @@ int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileNam fileName[0] = 0x00; strcpy(fileName, get_my_executable_directory()); CheckSlash(fileName); - + strcat(fileName, prefixDir); CheckSlash(fileName); - + strcat(fileName, reqestedFileName); if (!strstr(fileName, ".json")) strcat(fileName, ".json"); - + if (access(fileName, F_OK) < 0) { strcpy(fileName, get_my_executable_directory()); CheckSlash(fileName); - + strcat(fileName, reqestedFileName); if (!strstr(fileName, ".json")) strcat(fileName, ".json"); - + if (access(fileName, F_OK) < 0) { return 1; // file not found } @@ -652,9 +652,9 @@ int CmdHFFido2MakeCredential(const char *cmd) { json_error_t error; json_t *root = NULL; char fname[300] = {0}; - - CLIParserInit("hf fido make", - "Execute a FIDO2 Make Credentional command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", + + CLIParserInit("hf fido make", + "Execute a FIDO2 Make Credentional command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", "Usage:\n\thf fido make -> execute command default parameters file `fido2.json`\n" "\thf fido make test.json -> execute command with parameters file `text.json`"); @@ -668,7 +668,7 @@ int CmdHFFido2MakeCredential(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool APDULogging = arg_get_lit(1); bool verbose = arg_get_lit(2); bool verbose2 = arg_get_lit(2) > 1; @@ -685,8 +685,8 @@ int CmdHFFido2MakeCredential(const char *cmd) { jsonnamelen = strlen(cjsonname); } - CLIParserFree(); - + CLIParserFree(); + SetAPDULogging(APDULogging); int res = GetExistsFileNameJson("fido", cjsonname, fname); @@ -695,12 +695,12 @@ int CmdHFFido2MakeCredential(const char *cmd) { return res; } PrintAndLog("fname: %s\n", fname); - root = json_load_file(fname, 0, &error); + root = json_load_file(fname, 0, &error); if (!root) { PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); return 1; } - + uint8_t data[2048] = {0}; size_t datalen = 0; uint8_t buf[2048] = {0}; @@ -715,9 +715,9 @@ int CmdHFFido2MakeCredential(const char *cmd) { DropField(); return res; } - + if (sw != 0x9000) { - PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); DropField(); return 2; } @@ -725,28 +725,28 @@ int CmdHFFido2MakeCredential(const char *cmd) { res = FIDO2CreateMakeCredentionalReq(root, data, sizeof(data), &datalen); if (res) return res; - + if (showCBOR) { PrintAndLog("CBOR make credentional request:"); PrintAndLog("---------------- CBOR ------------------"); TinyCborPrintFIDOPackage(fido2CmdMakeCredential, false, data, datalen); PrintAndLog("---------------- CBOR ------------------"); } - + res = FIDO2MakeCredential(data, datalen, buf, sizeof(buf), &len, &sw); DropField(); if (res) { PrintAndLog("Can't execute make credential command. res=%x. Exit...", res); return res; } - + if (sw != 0x9000) { - PrintAndLog("ERROR execute make credential command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLog("ERROR execute make credential command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); return 3; } - + if(buf[0]) { - PrintAndLog("FIDO2 make credential error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); + PrintAndLog("FIDO2 make credential error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); return 0; } @@ -760,7 +760,7 @@ int CmdHFFido2MakeCredential(const char *cmd) { // parse returned cbor FIDO2MakeCredentionalParseRes(root, &buf[1], len - 1, verbose, verbose2, showCBOR, showDERTLV); - + if (root) { res = json_dump_file(root, fname, JSON_INDENT(2)); if (res) { @@ -769,7 +769,7 @@ int CmdHFFido2MakeCredential(const char *cmd) { } PrintAndLog("File `%s` saved.", fname); } - + json_decref(root); return 0; @@ -779,9 +779,9 @@ int CmdHFFido2GetAssertion(const char *cmd) { json_error_t error; json_t *root = NULL; char fname[300] = {0}; - - CLIParserInit("hf fido assert", - "Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", + + CLIParserInit("hf fido assert", + "Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", "Usage:\n\thf fido assert -> execute command default parameters file `fido2.json`\n" "\thf fido assert test.json -l -> execute command with parameters file `text.json` and add to request CredentialId"); @@ -795,7 +795,7 @@ int CmdHFFido2GetAssertion(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool APDULogging = arg_get_lit(1); bool verbose = arg_get_lit(2); bool verbose2 = arg_get_lit(2) > 1; @@ -812,8 +812,8 @@ int CmdHFFido2GetAssertion(const char *cmd) { jsonnamelen = strlen(cjsonname); } - CLIParserFree(); - + CLIParserFree(); + SetAPDULogging(APDULogging); int res = GetExistsFileNameJson("fido", "fido2", fname); @@ -822,12 +822,12 @@ int CmdHFFido2GetAssertion(const char *cmd) { return res; } PrintAndLog("fname: %s\n", fname); - root = json_load_file(fname, 0, &error); + root = json_load_file(fname, 0, &error); if (!root) { PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); return 1; } - + uint8_t data[2048] = {0}; size_t datalen = 0; uint8_t buf[2048] = {0}; @@ -842,9 +842,9 @@ int CmdHFFido2GetAssertion(const char *cmd) { DropField(); return res; } - + if (sw != 0x9000) { - PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); DropField(); return 2; } @@ -852,28 +852,28 @@ int CmdHFFido2GetAssertion(const char *cmd) { res = FIDO2CreateGetAssertionReq(root, data, sizeof(data), &datalen, createAllowList); if (res) return res; - + if (showCBOR) { PrintAndLog("CBOR get assertion request:"); PrintAndLog("---------------- CBOR ------------------"); TinyCborPrintFIDOPackage(fido2CmdGetAssertion, false, data, datalen); PrintAndLog("---------------- CBOR ------------------"); } - + res = FIDO2GetAssertion(data, datalen, buf, sizeof(buf), &len, &sw); DropField(); if (res) { PrintAndLog("Can't execute get assertion command. res=%x. Exit...", res); return res; } - + if (sw != 0x9000) { - PrintAndLog("ERROR execute get assertion command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLog("ERROR execute get assertion command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); return 3; } - + if(buf[0]) { - PrintAndLog("FIDO2 get assertion error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); + PrintAndLog("FIDO2 get assertion error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); return 0; } @@ -887,7 +887,7 @@ int CmdHFFido2GetAssertion(const char *cmd) { // parse returned cbor FIDO2GetAssertionParseRes(root, &buf[1], len - 1, verbose, verbose2, showCBOR); - + if (root) { res = json_dump_file(root, fname, JSON_INDENT(2)); if (res) { @@ -898,7 +898,7 @@ int CmdHFFido2GetAssertion(const char *cmd) { } json_decref(root); - + return 0; }; diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 82e14d5ea..25be7df47 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -58,7 +58,7 @@ int usage_hf_iclass_decrypt(void) { PrintAndLogEx(NORMAL, "which is defined by the configuration block."); PrintAndLogEx(NORMAL, "OBS! In order to use this function, the file 'iclass_decryptionkey.bin' must reside"); PrintAndLogEx(NORMAL, "in the working directory. The file should be 16 bytes binary data"); - PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: hf iclass decrypt f "); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); @@ -192,14 +192,14 @@ int usage_hf_iclass_replay(void) { PrintAndLogEx(NORMAL, " h This help text"); PrintAndLogEx(NORMAL, " Mac bytes to replay (8 hexsymbols)"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf iclass replay 00112233"); + PrintAndLogEx(NORMAL, " hf iclass replay 00112233"); return 0; } int usage_hf_iclass_sniff(void) { PrintAndLogEx(NORMAL, "Sniff the communication between reader and tag"); PrintAndLogEx(NORMAL, "Usage: hf iclass sniff [h]"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf iclass sniff"); + PrintAndLogEx(NORMAL, " hf iclass sniff"); return 0; } int usage_hf_iclass_loclass(void) { @@ -218,7 +218,7 @@ int usage_hf_iclass_loclass(void) { return 0; } int usage_hf_iclass_chk(void) { - PrintAndLogEx(NORMAL, "Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag"); + PrintAndLogEx(NORMAL, "Checkkeys loads a dictionary text file with 8byte hex keys to test authenticating against a iClass tag"); PrintAndLogEx(NORMAL, "Usage: hf iclass chk [h|e|r] [f (*.dic)]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h Show this help"); @@ -227,12 +227,12 @@ int usage_hf_iclass_chk(void) { PrintAndLogEx(NORMAL, " e elite"); PrintAndLogEx(NORMAL, " c credit key (if not use, default is debit)"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf iclass chk f default_iclass_keys.dic"); + PrintAndLogEx(NORMAL, " hf iclass chk f default_iclass_keys.dic"); PrintAndLogEx(NORMAL, " hf iclass chk f default_iclass_keys.dic e"); return 0; } int usage_hf_iclass_lookup(void) { - PrintAndLogEx(NORMAL, "Lookup keys takes some sniffed trace data and tries to verify what key was used against a dictionary file"); + PrintAndLogEx(NORMAL, "Lookup keys takes some sniffed trace data and tries to verify what key was used against a dictionary file"); PrintAndLogEx(NORMAL, "Usage: hf iclass lookup [h|e|r] [f (*.dic)] [u ] [p ] [m ]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h Show this help"); @@ -308,33 +308,33 @@ int CmdHFiClassSim(const char *Cmd) { } uint8_t numberOfCSNs = 0; - + /* // pre-defined 8 CSN by Holiman - uint8_t csns[8*NUM_CSNS] = { - 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x13, 0x94, 0x7E, 0x76, 0xFF, 0x12, 0xE0, - 0x2A, 0x99, 0xAC, 0x79, 0xEC, 0xFF, 0x12, 0xE0, - 0x17, 0x12, 0x01, 0xFD, 0xF7, 0xFF, 0x12, 0xE0, - 0xCD, 0x56, 0x01, 0x7C, 0x6F, 0xFF, 0x12, 0xE0, - 0x4B, 0x5E, 0x0B, 0x72, 0xEF, 0xFF, 0x12, 0xE0, - 0x00, 0x73, 0xD8, 0x75, 0x58, 0xFF, 0x12, 0xE0, - 0x0C, 0x90, 0x32, 0xF3, 0x5D, 0xFF, 0x12, 0xE0 + uint8_t csns[8*NUM_CSNS] = { + 0x00, 0x0B, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, + 0x00, 0x13, 0x94, 0x7E, 0x76, 0xFF, 0x12, 0xE0, + 0x2A, 0x99, 0xAC, 0x79, 0xEC, 0xFF, 0x12, 0xE0, + 0x17, 0x12, 0x01, 0xFD, 0xF7, 0xFF, 0x12, 0xE0, + 0xCD, 0x56, 0x01, 0x7C, 0x6F, 0xFF, 0x12, 0xE0, + 0x4B, 0x5E, 0x0B, 0x72, 0xEF, 0xFF, 0x12, 0xE0, + 0x00, 0x73, 0xD8, 0x75, 0x58, 0xFF, 0x12, 0xE0, + 0x0C, 0x90, 0x32, 0xF3, 0x5D, 0xFF, 0x12, 0xE0 }; */ /* - pre-defined 9 CSN by iceman - only one csn depend on several others. + pre-defined 9 CSN by iceman + only one csn depend on several others. six depends only on the first csn, (0,1, 0x45) */ uint8_t csns[8*NUM_CSNS] = { - 0x01, 0x0A, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, - 0x0C, 0x06, 0x0C, 0xFE, 0xF7, 0xFF, 0x12, 0xE0, - 0x10, 0x97, 0x83, 0x7B, 0xF7, 0xFF, 0x12, 0xE0, - 0x13, 0x97, 0x82, 0x7A, 0xF7, 0xFF, 0x12, 0xE0, - 0x07, 0x0E, 0x0D, 0xF9, 0xF7, 0xFF, 0x12, 0xE0, - 0x14, 0x96, 0x84, 0x76, 0xF7, 0xFF, 0x12, 0xE0, - 0x17, 0x96, 0x85, 0x71, 0xF7, 0xFF, 0x12, 0xE0, + 0x01, 0x0A, 0x0F, 0xFF, 0xF7, 0xFF, 0x12, 0xE0, + 0x0C, 0x06, 0x0C, 0xFE, 0xF7, 0xFF, 0x12, 0xE0, + 0x10, 0x97, 0x83, 0x7B, 0xF7, 0xFF, 0x12, 0xE0, + 0x13, 0x97, 0x82, 0x7A, 0xF7, 0xFF, 0x12, 0xE0, + 0x07, 0x0E, 0x0D, 0xF9, 0xF7, 0xFF, 0x12, 0xE0, + 0x14, 0x96, 0x84, 0x76, 0xF7, 0xFF, 0x12, 0xE0, + 0x17, 0x96, 0x85, 0x71, 0xF7, 0xFF, 0x12, 0xE0, 0xCE, 0xC5, 0x0F, 0x77, 0xF7, 0xFF, 0x12, 0xE0, 0xD2, 0x5A, 0x82, 0xF8, 0xF7, 0xFF, 0x12, 0xE0 //0x04, 0x08, 0x9F, 0x78, 0x6E, 0xFF, 0x12, 0xE0 @@ -357,10 +357,10 @@ int CmdHFiClassSim(const char *Cmd) { 0x00, 0x02, 0x04, 0x1E, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x07, 0x03, 0x1B, 0xF7, 0xFF, 0x12, 0xE0, 0x00, 0x00, 0x02, 0x24, 0xF7, 0xFF, 0x12, 0xE0, - 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 - }; + 0x00, 0x05, 0x01, 0x21, 0xF7, 0xFF, 0x12, 0xE0 + }; */ - + /* DUMPFILE FORMAT: * * <8-byte CSN><8-byte CC><4 byte NR><4 byte MAC>.... @@ -372,9 +372,9 @@ int CmdHFiClassSim(const char *Cmd) { * CC are all zeroes, CSN is the same as was sent in **/ uint8_t tries = 0; - + switch(simType) { - + case 2: { PrintAndLogEx(INFO, "Starting iCLASS sim 2 attack (elite mode)"); PrintAndLogEx(INFO, "press keyboard to cancel"); @@ -383,7 +383,7 @@ int CmdHFiClassSim(const char *Cmd) { memcpy(c.d.asBytes, csns, 8 * NUM_CSNS); clearCommandBuffer(); SendCommand(&c); - + while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { tries++; if (ukbhit()) { @@ -402,19 +402,19 @@ int CmdHFiClassSim(const char *Cmd) { if ( num_mac == 0 ) break; - + size_t datalen = NUM_CSNS * 24; void* dump = calloc(datalen, sizeof(uint8_t)); if ( !dump ) { PrintAndLogEx(WARNING, "Failed to allocate memory"); return 2; } - + memset(dump, 0, datalen);//<-- Need zeroes for the EPURSE - field (offical) - + uint8_t i = 0; for (i = 0 ; i < NUM_CSNS ; i++) { - //copy CSN + //copy CSN memcpy(dump + i*24, csns + i*8, 8); //copy epurse memcpy(dump + i*24 + 8, resp.d.asBytes + i*16, 8); @@ -423,7 +423,7 @@ int CmdHFiClassSim(const char *Cmd) { } /** Now, save to dumpfile **/ saveFile("iclass_mac_attack", "bin", dump, datalen); - free(dump); + free(dump); break; } case 4: { @@ -454,16 +454,16 @@ int CmdHFiClassSim(const char *Cmd) { if ( num_mac == 0 ) break; - + size_t datalen = NUM_CSNS * 24; void* dump = calloc(datalen, sizeof(uint8_t)); if ( !dump ) { PrintAndLogEx(WARNING, "Failed to allocate memory"); return 2; } - + #define MAC_ITEM_SIZE 24 - + //KEYROLL 1 //Need zeroes for the CC-field memset(dump, 0, datalen); @@ -483,17 +483,17 @@ int CmdHFiClassSim(const char *Cmd) { for (uint8_t i = 0; i < NUM_CSNS; i++) { resp_index = (i + NUM_CSNS) * 16; // Copy CSN - memcpy(dump + i*MAC_ITEM_SIZE, csns + i*8, 8); + memcpy(dump + i*MAC_ITEM_SIZE, csns + i*8, 8); // copy EPURSE memcpy(dump + i*MAC_ITEM_SIZE + 8, resp.d.asBytes + resp_index, 8); // copy NR_MAC (eight bytes from the response) ( 8b csn + 8 epurse == 16) memcpy(dump + i*MAC_ITEM_SIZE + 16, resp.d.asBytes + resp_index + 8, 8); resp_index++; - } - saveFile("iclass_mac_attack_keyroll_B", "bin", dump, datalen); - free(dump); + } + saveFile("iclass_mac_attack_keyroll_B", "bin", dump, datalen); + free(dump); break; - } + } case 1: case 3: default: { @@ -502,7 +502,7 @@ int CmdHFiClassSim(const char *Cmd) { clearCommandBuffer(); SendCommand(&c); break; - } + } } return 0; } @@ -513,12 +513,12 @@ int HFiClassReader(const char *Cmd, bool loop, bool verbose) { uint32_t flags = FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CC | FLAG_ICLASS_READER_AIA | FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY; - + UsbCommand c = {CMD_READER_ICLASS, {flags, 0, 0}}; // loop in client not device - else on windows have a communication error UsbCommand resp; while (!ukbhit()){ - + clearCommandBuffer(); SendCommand(&c); if (WaitForResponseTimeout(CMD_ACK,&resp, 4500)) { @@ -530,7 +530,7 @@ int HFiClassReader(const char *Cmd, bool loop, bool verbose) { if ( (readStatus == 0 && !loop) || readStatus == 0xFF) { // abort if (verbose) { - PrintAndLogEx(FAILED, "Quitting..."); + PrintAndLogEx(FAILED, "Quitting..."); DropField(); return 0; } @@ -539,7 +539,7 @@ int HFiClassReader(const char *Cmd, bool loop, bool verbose) { PrintAndLogEx(NORMAL, " CSN: %s", sprint_hex(data, 8)); tagFound = true; } - if (readStatus & FLAG_ICLASS_READER_CC) { + if (readStatus & FLAG_ICLASS_READER_CC) { PrintAndLogEx(NORMAL, " CC: %s", sprint_hex(data+16, 8)); } if (readStatus & FLAG_ICLASS_READER_CONF) { @@ -547,9 +547,9 @@ int HFiClassReader(const char *Cmd, bool loop, bool verbose) { } if (readStatus & FLAG_ICLASS_READER_AIA) { bool legacy = ( memcmp( (uint8_t *)(data + 8*5), "\xff\xff\xff\xff\xff\xff\xff\xff", 8) == 0 ); - + bool se_enabled = ( memcmp( (uint8_t *)(data + 8*5), "\xff\xff\xff\x00\x06\xff\xff\xff", 8) == 0 ); - + PrintAndLogEx(NORMAL, " App IA: %s", sprint_hex(data+8*5, 8)); if ( legacy ) PrintAndLogEx(SUCCESS, " : Possible iClass (legacy credential tag)"); @@ -564,7 +564,7 @@ int HFiClassReader(const char *Cmd, bool loop, bool verbose) { return 1; } } else { - if (verbose) + if (verbose) PrintAndLogEx(WARNING, "command execute timeout"); } if (!loop) break; @@ -573,7 +573,7 @@ int HFiClassReader(const char *Cmd, bool loop, bool verbose) { return 0; } -int CmdHFiClassReader(const char *Cmd) { +int CmdHFiClassReader(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); if (cmdp == 'h' || cmdp == 'H') return usage_hf_iclass_reader(); bool findone = (cmdp == '1') ? false : true; @@ -581,13 +581,13 @@ int CmdHFiClassReader(const char *Cmd) { } int CmdHFiClassReader_Replay(const char *Cmd) { - + char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd)<1 || cmdp == 'H' || cmdp == 'h') return usage_hf_iclass_replay(); - + uint8_t readerType = 0; uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00}; - + if (param_gethex(Cmd, 0, MAC, 8)) { PrintAndLogEx(FAILED, "MAC must include 8 HEX symbols"); return 1; @@ -612,24 +612,24 @@ int CmdHFiClassELoad(const char *Cmd) { char ctmp = param_getchar(Cmd, 0); if (strlen(Cmd)< 1 || ctmp == 'h' || ctmp == 'H') return usage_hf_iclass_eload(); - + if ( ctmp != 'f' && ctmp != 'F') return usage_hf_iclass_eload(); - + //File handling and reading FILE *f; char filename[FILE_PATH_SIZE]; - + if ( param_getstr(Cmd, 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) { PrintAndLogEx(FAILED, "Filename too long"); return 1; } - + f = fopen(filename, "rb"); if ( !f ){ PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); return 1; } - + // get filesize in order to malloc memory fseek(f, 0, SEEK_END); long fsize = ftell(f); @@ -647,7 +647,7 @@ int CmdHFiClassELoad(const char *Cmd) { fclose(f); return 1; } - + size_t bytes_read = fread(dump, 1, fsize, f); fclose(f); @@ -688,12 +688,12 @@ static int readKeyfile(const char *filename, size_t len, uint8_t* buffer) { fseek(f, 0, SEEK_SET); size_t bytes_read = fread(buffer, 1, len, f); fclose(f); - + if (fsize != len) { PrintAndLogEx(WARNING, "Warning, file size is %d, expected %d", fsize, len); return 1; } - + if (bytes_read != len) { PrintAndLogEx(WARNING, "Warning, could only read %d bytes, expected %d" ,bytes_read, len); return 1; @@ -705,10 +705,10 @@ int CmdHFiClassDecrypt(const char *Cmd) { char opt = param_getchar(Cmd, 0); if (strlen(Cmd)<1 || opt == 'h' || opt == 'H') return usage_hf_iclass_decrypt(); - + uint8_t key[16] = { 0 }; if (readKeyfile("iclass_decryptionkey.bin", 16, key)) return usage_hf_iclass_decrypt(); - + PrintAndLogEx(SUCCESS, "decryption key loaded from file"); //Open the tagdump-file @@ -719,28 +719,28 @@ int CmdHFiClassDecrypt(const char *Cmd) { if (!f) { PrintAndLogEx(WARNING, "could not find file %s", filename); return 1; - } + } } else { return usage_hf_iclass_decrypt(); - } + } fseek(f, 0, SEEK_END); long fsize = ftell(f); fseek(f, 0, SEEK_SET); - + if ( fsize < 0 ) { PrintAndLogEx(WARNING, "error, when getting filesize"); fclose(f); return 2; } - + uint8_t *decrypted = calloc(fsize, sizeof(uint8_t)); if ( !decrypted ) { PrintAndLogEx(WARNING, "Failed to allocate memory"); fclose(f); return 1; } - + size_t bytes_read = fread(decrypted, 1, fsize, f); fclose(f); if ( bytes_read == 0) { @@ -750,15 +750,15 @@ int CmdHFiClassDecrypt(const char *Cmd) { } picopass_hdr *hdr = (picopass_hdr *)decrypted; - + uint8_t mem = hdr->conf.mem_config; uint8_t chip = hdr->conf.chip_config; uint8_t applimit = hdr->conf.app_limit; uint8_t kb = 2; uint8_t app_areas = 2; uint8_t max_blk = 31; - getMemConfig(mem, chip, &max_blk, &app_areas, &kb); - + getMemConfig(mem, chip, &max_blk, &app_areas, &kb); + //Use the first block (CSN) for filename char outfilename[FILE_PATH_SIZE] = {0}; snprintf(outfilename, FILE_PATH_SIZE, "iclass_tagdump-%02x%02x%02x%02x%02x%02x%02x%02x-decrypted", @@ -772,18 +772,18 @@ int CmdHFiClassDecrypt(const char *Cmd) { uint8_t enc_dump[8] = {0}; uint8_t empty[8] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}; for(uint16_t blocknum=0; blocknum < applimit; ++blocknum) { - + uint8_t idx = blocknum*8; memcpy(enc_dump, decrypted + idx, 8); - + // block 7 or higher, and not empty 0xFF if(blocknum > 6 && memcmp(enc_dump, empty, 8) != 0 ) { mbedtls_des3_crypt_ecb(&ctx, enc_dump, decrypted + idx ); } } - + saveFile(outfilename, "bin", decrypted, fsize); - free(decrypted); + free(decrypted); printIclassDumpContents(decrypted, 1, (fsize/8), fsize); return 0; } @@ -799,7 +799,7 @@ static int iClassEncryptBlkData(uint8_t *blkData) { uint8_t *encrypted = encryptedData; mbedtls_des3_context ctx; mbedtls_des3_set2key_enc( &ctx, key); - + mbedtls_des3_crypt_ecb(&ctx, blkData,encrypted); memcpy(blkData,encrypted,8); return 1; @@ -832,7 +832,7 @@ static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool v UsbCommand resp; UsbCommand c = {CMD_READER_ICLASS, {0}}; c.arg[0] = FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_CC | FLAG_ICLASS_READER_ONE_TRY; - + if (use_credit_key) c.arg[0] |= FLAG_ICLASS_READER_CEDITKEY; @@ -847,20 +847,20 @@ static bool select_only(uint8_t *CSN, uint8_t *CCNR, bool use_credit_key, bool v uint8_t *data = resp.d.asBytes; memcpy(CSN, data, 8); - - if (CCNR != NULL) + + if (CCNR != NULL) memcpy(CCNR, data+16, 8); - + if (isOK > 0 && verbose) { PrintAndLogEx(SUCCESS, "CSN | %s", sprint_hex(CSN, 8)); PrintAndLogEx(SUCCESS, "CCNR | %s", sprint_hex(CCNR, 8)); } - + if (isOK <= 1){ PrintAndLogEx(FAILED, "failed to obtain CC! Tag-select is aborting... (%d)", isOK); return false; } - return true; + return true; } static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool use_credit_key, bool elite, bool rawkey, bool verbose) { @@ -876,7 +876,7 @@ static bool select_and_auth(uint8_t *KEY, uint8_t *MAC, uint8_t *div_key, bool u memcpy(div_key, KEY, 8); else HFiClassCalcDivKey(CSN, KEY, div_key, elite); - + if (verbose) PrintAndLogEx(SUCCESS, "authing with %s: %s", rawkey ? "raw key" : "diversified key", sprint_hex(div_key, 8) ); doMAC(CCNR, div_key, MAC); @@ -955,7 +955,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { break; case 'f': case 'F': - fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); + fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); if (fileNameLen < 1) { PrintAndLogEx(WARNING, "no filename found after f"); errors = true; @@ -966,7 +966,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { case 'K': have_debit_key = true; dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); - if (dataLen == 16) { + if (dataLen == 16) { errors = param_gethex(tempStr, 0, KEY, dataLen); } else if (dataLen == 1) { keyNbr = param_get8(Cmd, cmdp+1); @@ -991,7 +991,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { case 'V': verbose = true; cmdp++; - break; + break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); errors = true; @@ -999,16 +999,16 @@ int CmdHFiClassReader_Dump(const char *Cmd) { } } if (errors || cmdp < 2) return usage_hf_iclass_dump(); - + // if no debit key given try credit key on AA1 (not for iclass but for some picopass this will work) if (!have_debit_key && have_credit_key) use_credit_key = true; uint32_t flags = FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CC | FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_ONLY_ONCE | FLAG_ICLASS_READER_ONE_TRY; - + //get config and first 3 blocks - UsbCommand c = {CMD_READER_ICLASS, {flags, 0, 0}}; + UsbCommand c = {CMD_READER_ICLASS, {flags, 0, 0}}; UsbCommand resp; uint8_t tag_data[255*8]; @@ -1020,7 +1020,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { return 0; } DropField(); - + uint8_t readStatus = resp.arg[0] & 0xff; uint8_t *data = resp.d.asBytes; @@ -1028,7 +1028,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { PrintAndLogEx(FAILED, "no tag found"); return 0; } - + if( readStatus & (FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CONF | FLAG_ICLASS_READER_CC)){ memcpy(tag_data, data, 8*3); blockno += 2; // 2 to force re-read of block 2 later. (seems to respond differently..) @@ -1037,7 +1037,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { // large memory - not able to dump pages currently if (numblks > maxBlk) numblks = maxBlk; } - + // authenticate debit key and get div_key - later store in dump block 3 if (!select_and_auth(KEY, MAC, div_key, use_credit_key, elite, rawkey, verbose)){ //try twice - for some reason it sometimes fails the first time... @@ -1048,7 +1048,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { return 0; } } - + // begin dump UsbCommand w = {CMD_ICLASS_DUMP, {blockno, numblks-blockno+1}}; clearCommandBuffer(); @@ -1061,31 +1061,31 @@ int CmdHFiClassReader_Dump(const char *Cmd) { DropField(); return 0; } - + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) break; } // dump cmd switch off at device when finised. - + uint32_t blocksRead = resp.arg[1]; uint8_t isOK = resp.arg[0] & 0xff; if (!isOK && !blocksRead) { PrintAndLogEx(WARNING, "read block failed"); return 0; } - + uint32_t startindex = resp.arg[2]; if (blocksRead*8 > sizeof(tag_data) - (blockno*8)) { PrintAndLogEx(FAILED, "data exceeded buffer size!"); blocksRead = (sizeof(tag_data)/8) - blockno; } - + // response ok - now get bigbuf content of the dump if ( !GetFromDevice(BIG_BUF, tag_data+(blockno*8), blocksRead*8, startindex, NULL, 2500, false) ) { PrintAndLogEx(WARNING, "command execution time out"); return 0; } - + size_t gotBytes = blocksRead*8 + blockno*8; // try AA2 @@ -1118,7 +1118,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { if (!isOK && !blocksRead) { PrintAndLogEx(WARNING, "read block failed 2"); return 0; - } + } startindex = resp.arg[2]; if (blocksRead * 8 > sizeof(tag_data) - gotBytes) { @@ -1131,19 +1131,19 @@ int CmdHFiClassReader_Dump(const char *Cmd) { return 0; } - gotBytes += blocksRead * 8; + gotBytes += blocksRead * 8; } } DropField(); - + // add diversified keys to dump if (have_debit_key) memcpy(tag_data+(3*8),div_key,8); if (have_credit_key) memcpy(tag_data+(4*8),c_div_key,8); // print the dump PrintAndLogEx(NORMAL, "------+--+-------------------------+\n"); - PrintAndLogEx(NORMAL, "CSN |00| %s|\n", sprint_hex(tag_data, 8)); + PrintAndLogEx(NORMAL, "CSN |00| %s|\n", sprint_hex(tag_data, 8)); printIclassDumpContents(tag_data, 1, (gotBytes/8), gotBytes); if (filename[0] == 0){ @@ -1170,7 +1170,7 @@ static int WriteBlock(uint8_t blockno, uint8_t *bldata, uint8_t *KEY, bool use_c UsbCommand w = {CMD_ICLASS_WRITEBLOCK, {blockno}}; memcpy(w.d.asBytes, bldata, 8); memcpy(w.d.asBytes + 8, MAC, 4); - + clearCommandBuffer(); SendCommand(&w); if (!WaitForResponseTimeout(CMD_ACK, &resp, 4500)) { @@ -1232,7 +1232,7 @@ int CmdHFiClass_WriteBlock(const char *Cmd) { case 'k': case 'K': dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); - if (dataLen == 16) { + if (dataLen == 16) { errors = param_gethex(tempStr, 0, KEY, dataLen); } else if (dataLen == 1) { keyNbr = param_get8(Cmd, cmdp+1); @@ -1257,7 +1257,7 @@ int CmdHFiClass_WriteBlock(const char *Cmd) { case 'V': verbose = true; cmdp++; - break; + break; default: PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); errors = true; @@ -1311,7 +1311,7 @@ int CmdHFiClassCloneTag(const char *Cmd) { break; case 'f': case 'F': - fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); + fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); if (fileNameLen < 1) { PrintAndLogEx(WARNING, "No filename found after f"); errors = true; @@ -1321,7 +1321,7 @@ int CmdHFiClassCloneTag(const char *Cmd) { case 'k': case 'K': dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); - if (dataLen == 16) { + if (dataLen == 16) { errors = param_gethex(tempStr, 0, KEY, dataLen); } else if (dataLen == 1) { keyNbr = param_get8(Cmd, cmdp+1); @@ -1354,7 +1354,7 @@ int CmdHFiClassCloneTag(const char *Cmd) { case 'V': verbose = true; cmdp++; - break; + break; default: PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); errors = true; @@ -1380,7 +1380,7 @@ int CmdHFiClassCloneTag(const char *Cmd) { if (startblock<5) { PrintAndLogEx(WARNING, "you cannot write key blocks this way. yet... make your start block > 4"); - fclose(f); + fclose(f); return 0; } // now read data from the file from block 6 --- 19 @@ -1455,7 +1455,7 @@ static int ReadBlock(uint8_t *KEY, uint8_t blockno, uint8_t keyType, bool elite, PrintAndLogEx(WARNING, "Command execute timeout"); return 0; } - + uint8_t isOK = resp.arg[0] & 0xff; if (!isOK) { PrintAndLogEx(WARNING, "read block failed"); @@ -1506,7 +1506,7 @@ int CmdHFiClass_ReadBlock(const char *Cmd) { case 'K': auth = true; dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); - if (dataLen == 16) { + if (dataLen == 16) { errors = param_gethex(tempStr, 0, KEY, dataLen); } else if (dataLen == 1) { keyNbr = param_get8(Cmd, cmdp+1); @@ -1531,7 +1531,7 @@ int CmdHFiClass_ReadBlock(const char *Cmd) { case 'V': verbose = true; cmdp++; - break; + break; default: PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); errors = true; @@ -1550,7 +1550,7 @@ int CmdHFiClass_loclass(const char *Cmd) { if (strlen(Cmd)<1 || opt == 'h') usage_hf_iclass_loclass(); - + char fileName[FILE_PATH_SIZE] = {0}; if (opt == 'f') { if (param_getstr(Cmd, 1, fileName, sizeof(fileName)) > 0) { @@ -1575,7 +1575,7 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e uint8_t mem_config; memcpy(&mem_config, iclass_dump + 13,1); uint8_t maxmemcount; - + uint8_t filemaxblock = filesize / 8; if (mem_config & 0x80) @@ -1585,21 +1585,21 @@ void printIclassDumpContents(uint8_t *iclass_dump, uint8_t startblock, uint8_t e if (startblock == 0) startblock = 6; - + if ((endblock > maxmemcount) || (endblock == 0)) endblock = maxmemcount; - + // remember endblock needs to relate to zero-index arrays. if (endblock > filemaxblock-1) endblock = filemaxblock-1; //PrintAndLog ("startblock: %d, endblock: %d, filesize: %d, maxmemcount: %d, filemaxblock: %d",startblock, endblock,filesize, maxmemcount, filemaxblock); - + int i = startblock; PrintAndLogEx(NORMAL, "------+--+-------------------------+\n"); while (i <= endblock){ uint8_t *blk = iclass_dump + (i * 8); - PrintAndLogEx(NORMAL, " |%02X| %s\n", i, sprint_hex_ascii(blk, 8) ); + PrintAndLogEx(NORMAL, " |%02X| %s\n", i, sprint_hex_ascii(blk, 8) ); i++; } PrintAndLogEx(NORMAL, "------+--+-------------------------+\n"); @@ -1613,7 +1613,7 @@ int CmdHFiClassReadTagFile(const char *Cmd) { char filename[FILE_PATH_SIZE]; if (param_getstr(Cmd, 0, filename, sizeof(filename)) < 1) return usage_hf_iclass_readtagfile(); - + if (param_getstr(Cmd, 1, tempnum, sizeof(tempnum)) < 1) startblock = 0; else @@ -1623,7 +1623,7 @@ int CmdHFiClassReadTagFile(const char *Cmd) { endblock = 0; else sscanf(tempnum,"%d",&endblock); - + // file handling and reading f = fopen(filename,"rb"); if(!f) { @@ -1648,7 +1648,7 @@ int CmdHFiClassReadTagFile(const char *Cmd) { } size_t bytes_read = fread(dump, 1, fsize, f); fclose(f); - + uint8_t *csn = dump; PrintAndLogEx(NORMAL, "------+--+-------------------------+\n"); PrintAndLogEx(NORMAL, "CSN |00| %s|\n", sprint_hex(csn, 8) ); @@ -1670,10 +1670,10 @@ void HFiClassCalcDivKey(uint8_t *CSN, uint8_t *KEY, uint8_t *div_key, bool elite //Permute from iclass format to standard format permutekey_rev(key_sel, key_sel_p); - diversifyKey(CSN, key_sel_p, div_key); + diversifyKey(CSN, key_sel_p, div_key); } else { diversifyKey(CSN, KEY, div_key); - } + } } //when told CSN, oldkey, newkey, if new key is elite (elite), and if old key was elite (oldElite) @@ -1686,14 +1686,14 @@ static void HFiClassCalcNewKey(uint8_t *CSN, uint8_t *OLDKEY, uint8_t *NEWKEY, u HFiClassCalcDivKey(CSN, OLDKEY, old_div_key, oldElite); //get new div key HFiClassCalcDivKey(CSN, NEWKEY, new_div_key, elite); - + for (uint8_t i = 0; i < sizeof(old_div_key); i++){ xor_div_key[i] = old_div_key[i] ^ new_div_key[i]; } if (verbose) { PrintAndLogEx(SUCCESS, "Old div key : %s\n",sprint_hex(old_div_key,8)); PrintAndLogEx(SUCCESS, "New div key : %s\n",sprint_hex(new_div_key,8)); - PrintAndLogEx(SUCCESS, "Xor div key : %s\n",sprint_hex(xor_div_key,8)); + PrintAndLogEx(SUCCESS, "Xor div key : %s\n",sprint_hex(xor_div_key,8)); } } @@ -1727,7 +1727,7 @@ int CmdHFiClassCalcNewKey(const char *Cmd) { case 'n': case 'N': dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); - if (dataLen == 16) { + if (dataLen == 16) { errors = param_gethex(tempStr, 0, NEWKEY, dataLen); } else if (dataLen == 1) { keyNbr = param_get8(Cmd, cmdp+1); @@ -1746,7 +1746,7 @@ int CmdHFiClassCalcNewKey(const char *Cmd) { case 'o': case 'O': dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); - if (dataLen == 16) { + if (dataLen == 16) { errors = param_gethex(tempStr, 0, OLDKEY, dataLen); } else if (dataLen == 1) { keyNbr = param_get8(Cmd, cmdp+1); @@ -1776,11 +1776,11 @@ int CmdHFiClassCalcNewKey(const char *Cmd) { } } if (errors || cmdp < 4) return usage_hf_iclass_calc_newkey(); - + if (!givenCSN) if (!select_only(CSN, CCNR, false, true)) return 0; - + HFiClassCalcNewKey(CSN, OLDKEY, NEWKEY, xor_div_key, elite, oldElite, true); return 0; } @@ -1818,7 +1818,7 @@ static int loadKeys(char *filename) { uint8_t i = 0; for (; i < bytes_read/8; i++) memcpy(iClass_Key_Table[i],dump+(i*8),8); - + free(dump); PrintAndLogEx(SUCCESS, "%u keys loaded", i); return 1; @@ -1845,7 +1845,7 @@ static int printKeys(void) { PrintAndLogEx(NORMAL, ""); for (uint8_t i = 0; i < ICLASS_KEYS_MAX; i++) PrintAndLogEx(NORMAL, "%u: %s", i, sprint_hex(iClass_Key_Table[i],8)); - PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, ""); return 0; } @@ -1867,7 +1867,7 @@ int CmdHFiClassManageKeys(const char *Cmd) { return usage_hf_iclass_managekeys(); case 'f': case 'F': - fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); + fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); if (fileNameLen < 1) { PrintAndLogEx(WARNING, "No filename found after f"); errors = true; @@ -1885,7 +1885,7 @@ int CmdHFiClassManageKeys(const char *Cmd) { break; case 'k': case 'K': - operation += 3; //set key + operation += 3; //set key dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { //ul-c or ev1/ntag key length errors = param_gethex(tempStr, 0, KEY, dataLen); @@ -1917,7 +1917,7 @@ int CmdHFiClassManageKeys(const char *Cmd) { } } if (errors) return usage_hf_iclass_managekeys(); - + if (operation == 0){ PrintAndLogEx(WARNING, "no operation specified (load, save, or print)\n"); return usage_hf_iclass_managekeys(); @@ -1945,10 +1945,10 @@ int CmdHFiClassCheckKeys(const char *Cmd) { // empty string if (strlen(Cmd) == 0) return usage_hf_iclass_chk(); - + uint8_t CSN[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t CCNR[12] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - + // elite key, raw key, standard key bool use_elite = false; bool use_raw = false; @@ -1962,19 +1962,19 @@ int CmdHFiClassCheckKeys(const char *Cmd) { char filename[FILE_PATH_SIZE] = {0}; uint8_t fileNameLen = 0; - uint8_t *keyBlock = NULL; + uint8_t *keyBlock = NULL; iclass_premac_t *pre = NULL; int keycnt = 0; - + // time uint64_t t1 = msclock(); - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch ( tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_hf_iclass_chk(); case 'f': - fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); + fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); if (fileNameLen < 1) { PrintAndLogEx(WARNING, "no filename found after f"); errors = true; @@ -1987,7 +1987,7 @@ int CmdHFiClassCheckKeys(const char *Cmd) { break; case 'c': use_credit_key = true; - cmdp++; + cmdp++; break; case 'r': use_raw = true; @@ -1999,9 +1999,9 @@ int CmdHFiClassCheckKeys(const char *Cmd) { break; } } - if (errors) return usage_hf_iclass_chk(); + if (errors) return usage_hf_iclass_chk(); + - // Get CSN / UID and CCNR PrintAndLogEx(SUCCESS, "Reading tag CSN"); for (uint8_t i=0; i<10 && !got_csn; i++) { @@ -2011,7 +2011,7 @@ int CmdHFiClassCheckKeys(const char *Cmd) { PrintAndLogEx(WARNING, "one more try\n"); } } - + if ( !got_csn ) { PrintAndLogEx(WARNING, "can't select card, aborting..."); return 1; @@ -2023,13 +2023,13 @@ int CmdHFiClassCheckKeys(const char *Cmd) { free(keyBlock); return 1; } - + pre = calloc(keycnt, sizeof(iclass_premac_t)); if ( !pre ) { free(keyBlock); return 1; } - + PrintAndLogEx(SUCCESS, "Generating diversified keys, MAC"); if (use_elite) PrintAndLogEx(SUCCESS, "Using elite algo"); @@ -2046,43 +2046,43 @@ int CmdHFiClassCheckKeys(const char *Cmd) { free(pre); return 1; } - + //PrintPreCalcMac(keyBlock, keycnt, pre); // max 42 keys inside USB_COMMAND. 512/4 = 103 mac uint32_t chunksize = keycnt > (USB_CMD_DATA_SIZE/4) ? (USB_CMD_DATA_SIZE/4) : keycnt; bool lastChunk = false; - // main keychunk loop + // main keychunk loop for (uint32_t i = 0; i < keycnt; i += chunksize) { - + uint64_t t2 = msclock(); uint8_t timeout = 0; - + if (ukbhit()) { int gc = getchar(); (void)gc; PrintAndLogEx(NORMAL, "\n[!] Aborted via keyboard!\n"); goto out; } - + uint32_t keys = ((keycnt - i) > chunksize) ? chunksize : keycnt - i; - + // last chunk? if ( keys == keycnt - i) lastChunk = true; - + UsbCommand c = {CMD_ICLASS_CHECK_KEYS, { (lastChunk << 8), keys, 0}}; - + // bit 16 // - 1 indicates credit key // - 0 indicates debit key (default) c.arg[0] |= (use_credit_key << 16); - + memcpy(c.d.asBytes, pre + i, 4 * keys); clearCommandBuffer(); SendCommand(&c); UsbCommand resp; - + while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { timeout++; printf("."); fflush(stdout); @@ -2092,17 +2092,17 @@ int CmdHFiClassCheckKeys(const char *Cmd) { } } - uint8_t found = resp.arg[1] & 0xFF; + uint8_t found = resp.arg[1] & 0xFF; uint8_t isOK = resp.arg[0] & 0xFF; - + t2 = msclock() - t2; switch ( isOK ) { case 1: { found_debit = true; - + PrintAndLogEx(NORMAL, "\n[-] Chunk [%d/%d]: %.1fs [%s] found key %s (index %u)" , i - , keycnt + , keycnt , (float)(t2/1000.0) , (use_credit_key) ? "credit" : "debit" , sprint_hex(keyBlock + (i+found)*8, 8) @@ -2130,13 +2130,13 @@ int CmdHFiClassCheckKeys(const char *Cmd) { break; } - } // end chunks of keys - -out: + } // end chunks of keys + +out: t1 = msclock() - t1; PrintAndLogEx(SUCCESS, "\nTime in iclass checkkeys: %.0f seconds\n", (float)t1/1000.0); - + DropField(); free(pre); free(keyBlock); @@ -2144,29 +2144,29 @@ out: } static int cmp_uint32( const void *a, const void *b) { - + const iclass_prekey_t* x = (const iclass_prekey_t *)a; const iclass_prekey_t* y = (const iclass_prekey_t *)b; - + uint32_t mx = bytes_to_num( (uint8_t*)x->mac, 4); uint32_t my = bytes_to_num( (uint8_t*)y->mac, 4); - + if (mx < my) return -1; - else + else return mx > my; } // this method tries to identify in which configuration mode a iClass / iClass SE reader is in. // Standard or Elite / HighSecurity mode. It uses a default key dictionary list in order to work. int CmdHFiClassLookUp(const char *Cmd) { - + uint8_t CSN[8]; uint8_t EPURSE[8] = { 0,0,0,0,0,0,0,0 }; uint8_t MACS[8]= { 0,0,0,0,0,0,0,0 }; uint8_t CCNR[12]; uint8_t MAC_TAG[4] = { 0,0,0,0 }; - + // elite key, raw key, standard key bool use_elite = false; bool use_raw = false; @@ -2176,7 +2176,7 @@ int CmdHFiClassLookUp(const char *Cmd) { char filename[FILE_PATH_SIZE] = {0}; uint8_t fileNameLen = 0; - uint8_t *keyBlock = NULL; + uint8_t *keyBlock = NULL; iclass_prekey_t *prekey = NULL; int keycnt = 0, len = 0; @@ -2184,13 +2184,13 @@ int CmdHFiClassLookUp(const char *Cmd) { if (strlen(Cmd) == 0) errors = true; // time uint64_t t1 = msclock(); - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_hf_iclass_lookup(); case 'f': - fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); + fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); if (fileNameLen < 1) { PrintAndLogEx(WARNING, "No filename found after f"); errors = true; @@ -2203,7 +2203,7 @@ int CmdHFiClassLookUp(const char *Cmd) { PrintAndLogEx(WARNING, "Wrong CSN length, expected %d got [%d]", sizeof(CSN), len>>1); errors = true; } - cmdp += 2; + cmdp += 2; break; case 'm': param_gethex_ex(Cmd, cmdp+1, MACS, &len); @@ -2213,7 +2213,7 @@ int CmdHFiClassLookUp(const char *Cmd) { } else { memcpy(MAC_TAG, MACS+4, 4); } - cmdp += 2; + cmdp += 2; break; case 'p': param_gethex_ex(Cmd, cmdp+1, EPURSE, &len); @@ -2221,7 +2221,7 @@ int CmdHFiClassLookUp(const char *Cmd) { PrintAndLogEx(WARNING, "Wrong EPURSE length, expected %d got [%d] ", sizeof(EPURSE), len>>1); errors = true; } - cmdp += 2; + cmdp += 2; break; break; case 'e': @@ -2239,24 +2239,24 @@ int CmdHFiClassLookUp(const char *Cmd) { } } - if (errors) return usage_hf_iclass_lookup(); + if (errors) return usage_hf_iclass_lookup(); // stupid copy.. CCNR is a combo of epurse and reader nonce memcpy(CCNR, EPURSE, 8); memcpy(CCNR+8, MACS, 4); - + PrintAndLogEx(SUCCESS, "CSN | %s", sprint_hex( CSN, sizeof(CSN) )); PrintAndLogEx(SUCCESS, "Epurse | %s", sprint_hex( EPURSE, sizeof(EPURSE) )); PrintAndLogEx(SUCCESS, "MACS | %s", sprint_hex( MACS, sizeof(MACS) )); PrintAndLogEx(SUCCESS, "CCNR | %s", sprint_hex( CCNR, sizeof(CCNR) )); PrintAndLogEx(SUCCESS, "MAC_TAG | %s", sprint_hex( MAC_TAG, sizeof(MAC_TAG) )); - + int res = LoadDictionaryKeyFile( filename, &keyBlock, &keycnt); if ( res > 0) { free(keyBlock); return 1; } - //iclass_prekey_t + //iclass_prekey_t prekey = calloc(keycnt, sizeof(iclass_prekey_t)); if ( !prekey ) { free(keyBlock); @@ -2269,22 +2269,22 @@ int CmdHFiClassLookUp(const char *Cmd) { free(keyBlock); free(prekey); return 1; - } + } PrintAndLogEx(FAILED, "Sorting"); - + // sort mac list. qsort( prekey, keycnt, sizeof(iclass_prekey_t), cmp_uint32); //PrintPreCalc(prekey, keycnt); - - PrintAndLogEx(FAILED, "Searching"); + + PrintAndLogEx(FAILED, "Searching"); iclass_prekey_t *item; iclass_prekey_t lookup; memcpy(lookup.mac, MAC_TAG, 4); - + // binsearch - item = (iclass_prekey_t*) bsearch(&lookup, prekey, keycnt, sizeof(iclass_prekey_t), cmp_uint32); + item = (iclass_prekey_t*) bsearch(&lookup, prekey, keycnt, sizeof(iclass_prekey_t), cmp_uint32); if( item != NULL ) PrintAndLogEx(SUCCESS, "\n[debit] found key %s", sprint_hex(item->key, 8)); @@ -2292,9 +2292,9 @@ int CmdHFiClassLookUp(const char *Cmd) { PrintAndLogEx(NORMAL, "\nTime in iclass : %.0f seconds\n", (float)t1/1000.0); free(prekey); free(keyBlock); - PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, ""); return 0; -} +} int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) { @@ -2302,7 +2302,7 @@ int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) { FILE * f; uint8_t *p; int keyitems = 0; - + if ( !(f = fopen( filename , "r")) ) { PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); return 1; @@ -2311,12 +2311,12 @@ int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) { while( fgets(buf, sizeof(buf), f) ){ if (strlen(buf) < 16 || buf[15] == '\n') continue; - + //goto next line - while (fgetc(f) != '\n' && !feof(f)) {}; - - //The line start with # is comment, skip - if( buf[0]=='#' ) + while (fgetc(f) != '\n' && !feof(f)) {}; + + //The line start with # is comment, skip + if( buf[0]=='#' ) continue; // doesn't this only test first char only? @@ -2324,7 +2324,7 @@ int LoadDictionaryKeyFile( char* filename, uint8_t **keys, int *keycnt) { PrintAndLogEx(ERR, "file content error. '%s' must include 16 HEX symbols", buf); continue; } - + // null terminator (skip the rest of the line) buf[16] = 0; @@ -2353,15 +2353,15 @@ int GenerateMacFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_ for ( int i=0; i < keycnt; i++) { - memcpy(key, keys + 8 * i , 8); - + memcpy(key, keys + 8 * i , 8); + if (use_raw) memcpy(div_key, key, 8); else HFiClassCalcDivKey(CSN, key, div_key, use_elite); doMAC(CCNR, div_key, list[i].mac); - } + } return 0; } @@ -2370,9 +2370,9 @@ int GenerateFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_eli uint8_t div_key[8] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; for ( int i=0; i < keycnt; i++) { - - memcpy(list[i].key, keys + 8 * i , 8); - + + memcpy(list[i].key, keys + 8 * i , 8); + // generate diversifed key if (use_raw) memcpy(div_key, list[i].key, 8); @@ -2381,7 +2381,7 @@ int GenerateFromKeyFile( uint8_t* CSN, uint8_t* CCNR, bool use_raw, bool use_eli // generate MAC doMAC(CCNR, div_key, list[i].mac); - } + } return 0; } @@ -2391,9 +2391,9 @@ void PrintPreCalcMac(uint8_t* keys, int keycnt, iclass_premac_t* pre_list) { iclass_prekey_t* b = calloc(keycnt, sizeof(iclass_prekey_t)); if ( !b ) return; - - for ( int i=0; i < keycnt; i++) { - memcpy(b[i].key, keys + 8 * i , 8); + + for ( int i=0; i < keycnt; i++) { + memcpy(b[i].key, keys + 8 * i , 8); memcpy(b[i].mac, pre_list[i].mac, 4); } PrintPreCalc(b, keycnt); @@ -2406,7 +2406,7 @@ void PrintPreCalc(iclass_prekey_t* list, int itemcnt) { PrintAndLogEx(NORMAL, "-----+------------------+---------"); for ( int i=0; i < itemcnt; i++) { - if (i < 10 ) { + if (i < 10 ) { PrintAndLogEx(NORMAL, "[%2d] | %016" PRIx64 " | %08" PRIx32, i, bytes_to_num(list[i].key, 8), bytes_to_num( list[i].mac, 4) ); } else if ( i == 10 ) { PrintAndLogEx(SUCCESS, "... skip printing the rest"); @@ -2414,7 +2414,7 @@ void PrintPreCalc(iclass_prekey_t* list, int itemcnt) { } } -static void permute(uint8_t *data, uint8_t len, uint8_t *output){ +static void permute(uint8_t *data, uint8_t len, uint8_t *output){ #define KEY_SIZE 8 if ( len > KEY_SIZE ) { @@ -2433,7 +2433,7 @@ static void permute(uint8_t *data, uint8_t len, uint8_t *output){ mask = 0x80 >> i; for( j=0; j < KEY_SIZE; ++j){ p >>= 1; - if (data[j] & mask) + if (data[j] & mask) p |= 0x80; } output[i] = p; @@ -2463,17 +2463,17 @@ static void shave(uint8_t *data, uint8_t len){ data[i] &= 0xFE; } static void generate_rev(uint8_t *data, uint8_t len) { - uint8_t *key = calloc(len, sizeof(uint8_t)); + uint8_t *key = calloc(len, sizeof(uint8_t)); PrintAndLogEx(SUCCESS, "input permuted key | %s \n", sprint_hex(data, len)); permute_rev(data, len, key); PrintAndLogEx(SUCCESS, " unpermuted key | %s \n", sprint_hex(key, len)); shave(key, len); PrintAndLogEx(SUCCESS, " key | %s \n", sprint_hex(key, len)); - free(key); + free(key); } static void generate(uint8_t *data, uint8_t len) { uint8_t *key = calloc(len, sizeof(uint8_t)); - uint8_t *pkey = calloc(len, sizeof(uint8_t)); + uint8_t *pkey = calloc(len, sizeof(uint8_t)); PrintAndLogEx(SUCCESS, " input key | %s \n", sprint_hex(data, len)); permute(data, len, pkey); PrintAndLogEx(SUCCESS, "permuted key | %s \n", sprint_hex(pkey, len)); @@ -2483,9 +2483,9 @@ static void generate(uint8_t *data, uint8_t len) { free(pkey); } -int CmdHFiClassPermuteKey(const char *Cmd) { +int CmdHFiClassPermuteKey(const char *Cmd) { - uint8_t key[8] = {0}; + uint8_t key[8] = {0}; uint8_t key_std_format[8] = {0}; uint8_t key_iclass_format[8] = {0}; uint8_t data[16] = {0}; @@ -2493,13 +2493,13 @@ int CmdHFiClassPermuteKey(const char *Cmd) { int len = 0; char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd) == 0|| cmdp == 'h' || cmdp == 'H') return usage_hf_iclass_permutekey(); - + isReverse = ( cmdp == 'r' || cmdp == 'R' ); - + param_gethex_ex(Cmd, 1, data, &len); if ( len%2 ) return usage_hf_iclass_permutekey(); - len >>= 1; + len >>= 1; memcpy(key, data, 8); @@ -2510,7 +2510,7 @@ int CmdHFiClassPermuteKey(const char *Cmd) { } else { generate(data, len); - permutekey(key, key_iclass_format); + permutekey(key, key_iclass_format); PrintAndLogEx(SUCCESS, "holiman std key | %s \n", sprint_hex(key_iclass_format, 8)); } return 0; diff --git a/client/cmdhflegic.c b/client/cmdhflegic.c index 41df287a9..bf61b570a 100644 --- a/client/cmdhflegic.c +++ b/client/cmdhflegic.c @@ -11,7 +11,7 @@ static int CmdHelp(const char *Cmd); -#define MAX_LENGTH 1024 +#define MAX_LENGTH 1024 int usage_legic_calccrc(void){ PrintAndLogEx(NORMAL, "Calculates the legic crc8/crc16 on the given data."); @@ -28,7 +28,7 @@ int usage_legic_calccrc(void){ PrintAndLogEx(NORMAL, " hf legic crc d deadbeef1122 u 9A c 16"); return 0; } -int usage_legic_rdmem(void){ +int usage_legic_rdmem(void){ PrintAndLogEx(NORMAL, "Read data from a legic tag."); PrintAndLogEx(NORMAL, "Usage: hf legic rdmem [h] "); PrintAndLogEx(NORMAL, "Options:"); @@ -94,7 +94,7 @@ int usage_legic_info(void){ int usage_legic_dump(void){ PrintAndLogEx(NORMAL, "Reads all pages from LEGIC Prime MIM22, MIM256, MIM1024"); PrintAndLogEx(NORMAL, "and saves binary dump into the file `filename.bin` or `cardUID.bin`"); - PrintAndLogEx(NORMAL, "It autodetects card type.\n"); + PrintAndLogEx(NORMAL, "It autodetects card type.\n"); PrintAndLogEx(NORMAL, "Usage: hf legic dump [h] o "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : this help"); @@ -121,11 +121,11 @@ int usage_legic_eload(void){ PrintAndLogEx(NORMAL, "It loads binary dump from the file `filename.bin`"); PrintAndLogEx(NORMAL, "Usage: hf legic eload [h] [card memory] "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); + PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, " [card memory] : 0 = MIM22"); PrintAndLogEx(NORMAL, " : 1 = MIM256 (default)"); PrintAndLogEx(NORMAL, " : 2 = MIM1024"); - PrintAndLogEx(NORMAL, " : filename w/o .bin to load"); + PrintAndLogEx(NORMAL, " : filename w/o .bin to load"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf legic eload 2 myfile"); @@ -139,9 +139,9 @@ int usage_legic_esave(void){ PrintAndLogEx(NORMAL, " [card memory] : 0 = MIM22"); PrintAndLogEx(NORMAL, " : 1 = MIM256 (default)"); PrintAndLogEx(NORMAL, " : 2 = MIM1024"); - PrintAndLogEx(NORMAL, " : filename w/o .bin to load"); + PrintAndLogEx(NORMAL, " : filename w/o .bin to load"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf legic esave 2 myfile"); return 0; } @@ -151,7 +151,7 @@ int usage_legic_wipe(void){ PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf legic wipe"); return 0; } @@ -181,7 +181,7 @@ int CmdLegicInfo(const char *Cmd) { } PrintAndLogEx(SUCCESS, "Reading tag memory %d b...", card.cardsize); - + // allocate receiver buffer uint8_t *data = calloc(card.cardsize, sizeof(uint8_t)); if (!data) { @@ -195,11 +195,11 @@ int CmdLegicInfo(const char *Cmd) { free(data); return 3; } - + // Output CDF System area (9 bytes) plus remaining header area (12 bytes) crc = data[4]; - uint32_t calc_crc = CRC8Legic(data, 4); - + uint32_t calc_crc = CRC8Legic(data, 4); + PrintAndLogEx(NORMAL, "\nCDF: System Area"); PrintAndLogEx(NORMAL, "------------------------------------------------------"); PrintAndLogEx(NORMAL, "MCD: %02x, MSN: %02x %02x %02x, MCC: %02x %s", @@ -210,7 +210,7 @@ int CmdLegicInfo(const char *Cmd) { data[4], (calc_crc == crc) ? "OK":"Fail" ); - + // MCD = Manufacturer ID (should be list meaning something?) token_type[0] = 0; @@ -224,7 +224,7 @@ int CmdLegicInfo(const char *Cmd) { data[5], data[6] ); - + } else if (dcf > 60000) { // Master token? int fl = 0; @@ -303,7 +303,7 @@ int CmdLegicInfo(const char *Cmd) { } } } - + uint8_t segCrcBytes[8] = {0,0,0,0,0,0,0,0}; uint32_t segCalcCRC = 0; uint32_t segCRC = 0; @@ -311,14 +311,14 @@ int CmdLegicInfo(const char *Cmd) { // Not Data card? if (dcf > 60000) goto out; - + PrintAndLogEx(NORMAL, "\nADF: User Area"); PrintAndLogEx(NORMAL, "------------------------------------------------------"); if(bIsSegmented) { // Data start point on segmented cards - i = 22; + i = 22; // decode segments for (segmentNum=1; segmentNum < 128; segmentNum++ ) @@ -332,7 +332,7 @@ int CmdLegicInfo(const char *Cmd) { bool hasWRP = (wrp > wrc); int wrp_len = (wrp - wrc); int remain_seg_payload_len = (segment_len - wrp - 5); - + // validate segment-crc segCrcBytes[0]=data[0]; //uid0 segCrcBytes[1]=data[1]; //uid1 @@ -352,7 +352,7 @@ int CmdLegicInfo(const char *Cmd) { data[i+1] ^ crc, data[i+2] ^ crc, data[i+3] ^ crc, - segment_len, + segment_len, segment_flag, (segment_flag & 0x4) >> 2, (segment_flag & 0x8) >> 3, @@ -374,7 +374,7 @@ int CmdLegicInfo(const char *Cmd) { data[k] ^= crc; print_hex_break( data+i, wrc, 16); - + i += wrc; } @@ -385,14 +385,14 @@ int CmdLegicInfo(const char *Cmd) { for (k=i; k < (i+wrp_len); ++k) data[k] ^= crc; - + print_hex_break( data+i, wrp_len, 16); - + i += wrp_len; - + // does this one work? (Answer: Only if KGH/BGH is used with BCD encoded card number! So maybe this will show just garbage...) if( wrp_len == 8 ) - PrintAndLogEx(NORMAL, "Card ID: %2X%02X%02X", data[i-4]^crc, data[i-3]^crc, data[i-2]^crc); + PrintAndLogEx(NORMAL, "Card ID: %2X%02X%02X", data[i-4]^crc, data[i-3]^crc, data[i-2]^crc); } PrintAndLogEx(NORMAL, "Remaining segment payload: (I %d | K %d | Remain LEN %d)", i, k, remain_seg_payload_len); @@ -401,19 +401,19 @@ int CmdLegicInfo(const char *Cmd) { for ( k=i; k < (i+remain_seg_payload_len); ++k) data[k] ^= crc; - + print_hex_break( data+i, remain_seg_payload_len, 16); i += remain_seg_payload_len; - + PrintAndLogEx(NORMAL, "-----+------------------------------------------------\n"); // end with last segment - if (segment_flag & 0x8) + if (segment_flag & 0x8) goto out; } // end for loop - + } else { // Data start point on unsegmented cards @@ -447,7 +447,7 @@ int CmdLegicInfo(const char *Cmd) { PrintAndLogEx(NORMAL, "-----+------------------------------------------------"); print_hex_break( data + i, wrp_len, 16); i += wrp_len; - + // does this one work? (Answer: Only if KGH/BGH is used with BCD encoded card number! So maybe this will show just garbage...) if( wrp_len == 8 ) PrintAndLogEx(NORMAL, "Card ID: %2X%02X%02X", data[i-4], data[i-3], data[i-2]); @@ -458,7 +458,7 @@ int CmdLegicInfo(const char *Cmd) { PrintAndLogEx(NORMAL, "-----+------------------------------------------------"); print_hex_break( data + i, remain_seg_payload_len, 16); i += remain_seg_payload_len; - + PrintAndLogEx(NORMAL, "-----+------------------------------------------------\n"); } @@ -474,11 +474,11 @@ int CmdLegicRdmem(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if ( cmdp == 'h' ) return usage_legic_rdmem(); - + uint32_t offset = 0, len = 0, iv = 1; uint16_t datalen = 0; sscanf(Cmd, "%x %x %x", &offset, &len, &iv); - + // sanity checks if ( len + offset >= MAX_LENGTH ) { PrintAndLogEx(WARNING, "Out-of-bounds, Cardsize = %d, [offset+len = %d ]", MAX_LENGTH, len + offset); @@ -486,14 +486,14 @@ int CmdLegicRdmem(const char *Cmd) { } PrintAndLogEx(SUCCESS, "Reading %d bytes, from offset %d", len, offset); - + // allocate receiver buffer uint8_t *data = calloc(len, sizeof(uint8_t)); if ( !data ){ PrintAndLogEx(WARNING, "Cannot allocate memory"); return -2; } - + int status = legic_read_mem(offset, len, iv, data, &datalen); if ( status == 0 ) { PrintAndLogEx(NORMAL, "\n ## | 0 1 2 3 4 5 6 7 8 9 A B C D E F 10 11 12 13 14 15 16 17 18 19 1A 1B 1C 1D 1E 1F"); @@ -523,7 +523,7 @@ int CmdLegicRfWrite(const char *Cmd) { bool errors = false; int len = 0, bg, en; uint32_t offset = 0, IV = 0x55; - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'd': @@ -542,7 +542,7 @@ int CmdLegicRfWrite(const char *Cmd) { errors = true; break; } - + // limit number of bytes to write. This is not a 'restore' command. if ( (len >> 1) > 100 ){ PrintAndLogEx(WARNING, "Max bound on 100bytes to write a one time."); @@ -554,20 +554,20 @@ int CmdLegicRfWrite(const char *Cmd) { // more than once - we have to clean previous malloc if (data) free(data); - + data = calloc(len >> 1, sizeof(uint8_t)); if ( data == NULL ) { PrintAndLogEx(WARNING, "Can't allocate memory. exiting"); errors = true; break; } - + if (param_gethex(Cmd, cmdp+1, data, len)) { errors = true; break; } - len >>= 1; + len >>= 1; cmdp += 2; break; case 'o': @@ -585,7 +585,7 @@ int CmdLegicRfWrite(const char *Cmd) { } //Validations if (errors || cmdp == 0){ - if (data) + if (data) free(data); return usage_legic_write(); } @@ -598,14 +598,14 @@ int CmdLegicRfWrite(const char *Cmd) { } legic_print_type(card.cardsize, 0); - + // OUT-OF-BOUNDS checks // UID 4+1 bytes can't be written to. if ( offset < 5 ) { PrintAndLogEx(WARNING, "Out-of-bounds, bytes 0-1-2-3-4 can't be written to. Offset = %d", offset); return -2; } - + if ( len + offset >= card.cardsize ) { PrintAndLogEx(WARNING, "Out-of-bounds, Cardsize = %d, [offset+len = %d ]", card.cardsize, len + offset); return -2; @@ -623,17 +623,17 @@ int CmdLegicRfWrite(const char *Cmd) { return 0; } } - + legic_chk_iv(&IV); - + PrintAndLogEx(SUCCESS, "Writing to tag"); UsbCommand c = {CMD_WRITER_LEGIC_RF, {offset, len, IV}}; - memcpy(c.d.asBytes, data, len); + memcpy(c.d.asBytes, data, len); UsbCommand resp; clearCommandBuffer(); SendCommand(&c); - + uint8_t timeout = 0; while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { @@ -643,9 +643,9 @@ int CmdLegicRfWrite(const char *Cmd) { PrintAndLogEx(WARNING, "\ncommand execution time out"); return 1; } - } + } PrintAndLogEx(NORMAL, "\n"); - + uint8_t isOK = resp.arg[0] & 0xFF; if ( !isOK ) { PrintAndLogEx(WARNING, "Failed writing tag"); @@ -662,7 +662,7 @@ int CmdLegicCalcCrc(const char *Cmd){ bool errors = false; int len = 0; int bg, en; - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'd': @@ -691,13 +691,13 @@ int CmdLegicCalcCrc(const char *Cmd){ errors = true; break; } - + if (param_gethex(Cmd, cmdp+1, data, len)) { errors = true; break; } - len >>= 1; + len >>= 1; cmdp += 2; break; case 'u': @@ -722,7 +722,7 @@ int CmdLegicCalcCrc(const char *Cmd){ if (data) free(data); return usage_legic_calccrc(); } - + switch (type){ case 16: init_table(CRC_LEGIC); @@ -732,20 +732,20 @@ int CmdLegicCalcCrc(const char *Cmd){ PrintAndLogEx(SUCCESS, "Legic crc8: %X", CRC8Legic(data, len) ); break; } - + if (data) free(data); return 0; -} +} int legic_read_mem(uint32_t offset, uint32_t len, uint32_t iv, uint8_t *out, uint16_t *outlen) { - + legic_chk_iv(&iv); - + UsbCommand c = {CMD_READER_LEGIC_RF, {offset, len, iv}}; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; - + uint8_t timeout = 0; while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { ++timeout; @@ -754,19 +754,19 @@ int legic_read_mem(uint32_t offset, uint32_t len, uint32_t iv, uint8_t *out, uin PrintAndLogEx(WARNING, "\ncommand execution time out"); return 1; } - } + } PrintAndLogEx(NORMAL, "\n"); - + uint8_t isOK = resp.arg[0] & 0xFF; *outlen = resp.arg[1]; if ( !isOK ) { PrintAndLogEx(WARNING, "Failed reading tag"); return 2; } - + if ( *outlen != len ) PrintAndLogEx(WARNING, "Fail, only managed to read %u bytes", *outlen); - + // copy data from device if ( !GetFromDevice( BIG_BUF_EML, out, *outlen, 0, NULL, 2500, false) ) { PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); @@ -780,7 +780,7 @@ int legic_print_type(uint32_t tagtype, uint8_t spaces){ spc[10]=0x00; char *spacer = spc + (10-spaces); - if ( tagtype == 22 ) + if ( tagtype == 22 ) PrintAndLogEx(SUCCESS, "%sTYPE : MIM%d card (outdated)", spacer, tagtype); else if ( tagtype == 256 ) PrintAndLogEx(SUCCESS, "%sTYPE : MIM%d card (234 bytes)", spacer, tagtype); @@ -800,11 +800,11 @@ int legic_get_type(legic_card_select_t *card){ UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) return 2; - + uint8_t isOK = resp.arg[0] & 0xFF; - if ( !isOK ) + if ( !isOK ) return 3; - + memcpy(card, (legic_card_select_t *)resp.d.asBytes, sizeof(legic_card_select_t)); return 0; } @@ -815,20 +815,20 @@ void legic_chk_iv(uint32_t *iv){ } // IV must be odd if ( (*iv & 1) == 0 ){ - *iv |= 0x01; - PrintAndLogEx(INFO, "LSB of IV must be SET %u", *iv); + *iv |= 0x01; + PrintAndLogEx(INFO, "LSB of IV must be SET %u", *iv); } } void legic_seteml(uint8_t *src, uint32_t offset, uint32_t numofbytes) { size_t len = 0; - UsbCommand c = {CMD_LEGIC_ESET, {0, 0, 0}}; + UsbCommand c = {CMD_LEGIC_ESET, {0, 0, 0}}; for(size_t i = offset; i < numofbytes; i += USB_CMD_DATA_SIZE) { - - len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); + + len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); c.arg[0] = i; // offset c.arg[1] = len; // number of bytes - memcpy(c.d.asBytes, src+i, len); + memcpy(c.d.asBytes, src+i, len); clearCommandBuffer(); SendCommand(&c); } @@ -838,15 +838,15 @@ int HFLegicReader(const char *Cmd, bool verbose) { char cmdp = tolower(param_getchar(Cmd, 0)); if ( cmdp == 'h' ) return usage_legic_reader(); - + legic_card_select_t card; switch (legic_get_type(&card)){ - case 1: + case 1: return 2; - case 2: - if ( verbose ) PrintAndLogEx(WARNING, "command execution time out"); + case 2: + if ( verbose ) PrintAndLogEx(WARNING, "command execution time out"); return 1; - case 3: + case 3: if ( verbose ) PrintAndLogEx(WARNING, "legic card select failed"); return 2; default: break; @@ -866,20 +866,20 @@ int CmdLegicDump(const char *Cmd){ char *fnameptr = filename; size_t fileNlen = 0; bool errors = false; - uint16_t dumplen; + uint16_t dumplen; uint8_t cmdp = 0; - + memset(filename, 0, sizeof(filename)); - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_legic_dump(); case 'o': fileNlen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); - if (!fileNlen) - errors = true; - if (fileNlen > FILE_PATH_SIZE-5) + if (!fileNlen) + errors = true; + if (fileNlen > FILE_PATH_SIZE-5) fileNlen = FILE_PATH_SIZE-5; cmdp += 2; break; @@ -891,7 +891,7 @@ int CmdLegicDump(const char *Cmd){ } //Validations if (errors) return usage_legic_dump(); - + // tagtype legic_card_select_t card; if (legic_get_type(&card)) { @@ -899,8 +899,8 @@ int CmdLegicDump(const char *Cmd){ return -1; } dumplen = card.cardsize; - - legic_print_type(dumplen, 0); + + legic_print_type(dumplen, 0); PrintAndLogEx(SUCCESS, "Reading tag memory %d b...", dumplen); UsbCommand c = {CMD_READER_LEGIC_RF, {0x00, dumplen, 0x55}}; @@ -916,9 +916,9 @@ int CmdLegicDump(const char *Cmd){ PrintAndLogEx(WARNING, "\ncommand execution time out"); return 1; } - } + } PrintAndLogEx(NORMAL, "\n"); - + uint8_t isOK = resp.arg[0] & 0xFF; if ( !isOK ) { PrintAndLogEx(WARNING, "Failed dumping tag data"); @@ -931,7 +931,7 @@ int CmdLegicDump(const char *Cmd){ PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); return 3; } - + if ( readlen != dumplen ) PrintAndLogEx(WARNING, "Fail, only managed to read 0x%02X bytes of 0x%02X", readlen, dumplen); @@ -949,7 +949,7 @@ int CmdLegicDump(const char *Cmd){ sprintf(fnameptr + fileNlen,".bin"); f = fopen(filename, "wb"); - if (!f) { + if (!f) { PrintAndLogEx(WARNING, "Could not create file name %s", filename); if (data) free(data); @@ -961,7 +961,7 @@ int CmdLegicDump(const char *Cmd){ free(data); PrintAndLogEx(SUCCESS, "Wrote %d bytes to %s", readlen, filename); return 0; -} +} int CmdLegicRestore(const char *Cmd){ @@ -970,11 +970,11 @@ int CmdLegicRestore(const char *Cmd){ char *fnameptr = filename; size_t fileNlen = 0; bool errors = false; - uint16_t numofbytes; + uint16_t numofbytes; uint8_t cmdp = 0; - + memset(filename, 0, sizeof(filename)); - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': @@ -982,12 +982,12 @@ int CmdLegicRestore(const char *Cmd){ break; case 'i': fileNlen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); - if (!fileNlen) + if (!fileNlen) errors = true; - - if (fileNlen > FILE_PATH_SIZE-5) + + if (fileNlen > FILE_PATH_SIZE-5) fileNlen = FILE_PATH_SIZE-5; - cmdp += 2; + cmdp += 2; break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); @@ -997,23 +997,23 @@ int CmdLegicRestore(const char *Cmd){ } //Validations if (errors || cmdp == 0) return usage_legic_restore(); - + // tagtype legic_card_select_t card; if (legic_get_type(&card)) { PrintAndLogEx(WARNING, "Failed to identify tagtype"); return 1; } - numofbytes = card.cardsize; - + numofbytes = card.cardsize; + // set up buffer uint8_t *data = calloc(numofbytes, sizeof(uint8_t) ); if (!data) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); - return 2; + return 2; } - - legic_print_type(numofbytes, 0); + + legic_print_type(numofbytes, 0); // set up file fnameptr += fileNlen; @@ -1024,13 +1024,13 @@ int CmdLegicRestore(const char *Cmd){ PrintAndLogEx(WARNING, "File %s not found or locked", filename); free(data); return 3; - } - - // verify size of dumpfile is the same as card. + } + + // verify size of dumpfile is the same as card. fseek(f, 0, SEEK_END); // seek to end of file size_t filesize = ftell(f); // get current file pointer fseek(f, 0, SEEK_SET); // seek back to beginning of file - + if ( filesize != numofbytes) { PrintAndLogEx(WARNING, "Fail, filesize and cardsize is not equal. [%u != %u]", filesize, numofbytes); free(data); @@ -1041,13 +1041,13 @@ int CmdLegicRestore(const char *Cmd){ // load file size_t bytes_read = fread(data, 1, numofbytes, f); fclose(f); - + if ( bytes_read == 0){ PrintAndLogEx(WARNING, "File reading error"); free(data); return 2; } - + PrintAndLogEx(SUCCESS, "Restoring to card"); // transfer to device @@ -1055,36 +1055,36 @@ int CmdLegicRestore(const char *Cmd){ UsbCommand c = {CMD_WRITER_LEGIC_RF, {0, 0, 0x55}}; UsbCommand resp; for(size_t i = 7; i < numofbytes; i += USB_CMD_DATA_SIZE) { - - len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); + + len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); c.arg[0] = i; // offset c.arg[1] = len; // number of bytes - memcpy(c.d.asBytes, data+i, len); + memcpy(c.d.asBytes, data+i, len); clearCommandBuffer(); SendCommand(&c); - + uint8_t timeout = 0; while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { ++timeout; printf("."); fflush(stdout); if (timeout > 7) { PrintAndLogEx(WARNING, "\ncommand execution time out"); - free(data); + free(data); return 1; } - } + } PrintAndLogEx(NORMAL, "\n"); - + uint8_t isOK = resp.arg[0] & 0xFF; if ( !isOK ) { PrintAndLogEx(WARNING, "Failed writing tag [msg = %u]", resp.arg[1] & 0xFF); - free(data); + free(data); return 1; } PrintAndLogEx(SUCCESS, "Wrote chunk [offset %d | len %d | total %d", i, len, i+len); - } - - free(data); + } + + free(data); PrintAndLogEx(SUCCESS, "\nWrote %d bytes to card from file %s", numofbytes, filename); return 0; } @@ -1095,14 +1095,14 @@ int CmdLegicELoad(const char *Cmd) { char *fnameptr = filename; int len, numofbytes; int nameParamNo = 1; - + char cmdp = tolower(param_getchar(Cmd, 0)); if ( cmdp == 'h' || cmdp == 0x00) return usage_legic_eload(); switch (cmdp) { case '0' : numofbytes = 22; break; - case '1' : + case '1' : case '\0': numofbytes = 256; break; case '2' : numofbytes = 1024; break; default : numofbytes = 256; nameParamNo = 0;break; @@ -1112,19 +1112,19 @@ int CmdLegicELoad(const char *Cmd) { uint8_t *data = calloc(numofbytes, sizeof(uint8_t)); if (!data) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); - return 3; + return 3; } - + // set up file len = param_getstr(Cmd, nameParamNo, filename, FILE_PATH_SIZE); - if (len > FILE_PATH_SIZE - 5) + if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; fnameptr += len; sprintf(fnameptr, ".bin"); - + // open file f = fopen(filename,"rb"); - if (!f) { + if (!f) { PrintAndLogEx(WARNING, "File %s not found or locked", filename); free(data); return 1; @@ -1136,16 +1136,16 @@ int CmdLegicELoad(const char *Cmd) { PrintAndLogEx(WARNING, "File reading error"); free(data); fclose(f); - f = NULL; + f = NULL; return 2; } fclose(f); f = NULL; - + // transfer to device legic_seteml(data, 0, numofbytes); - - free(data); + + free(data); PrintAndLogEx(SUCCESS, "\nLoaded %d bytes from file: %s to emulator memory", numofbytes, filename); return 0; } @@ -1155,48 +1155,48 @@ int CmdLegicESave(const char *Cmd) { char filename[FILE_PATH_SIZE]; char *fnameptr = filename; int fileNlen, numofbytes, nameParamNo = 1; - + memset(filename, 0, sizeof(filename)); char cmdp = tolower(param_getchar(Cmd, 0)); - + if ( cmdp == 'h' || cmdp == 0x00) return usage_legic_esave(); switch (cmdp) { case '0' : numofbytes = 22; break; - case '1' : + case '1' : case '\0': numofbytes = 256; break; case '2' : numofbytes = 1024; break; default : numofbytes = 256; nameParamNo = 0; break; } fileNlen = param_getstr(Cmd, nameParamNo, filename, FILE_PATH_SIZE); - - if (fileNlen > FILE_PATH_SIZE - 5) + + if (fileNlen > FILE_PATH_SIZE - 5) fileNlen = FILE_PATH_SIZE - 5; // set up buffer uint8_t *data = calloc(numofbytes, sizeof(uint8_t)); if (!data) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); - return 3; + return 3; } - + // download emulator memory - PrintAndLogEx(SUCCESS, "Reading emulator memory..."); + PrintAndLogEx(SUCCESS, "Reading emulator memory..."); if (!GetFromDevice( BIG_BUF_EML, data, numofbytes, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); free(data); return 4; } // user supplied filename? - if (fileNlen < 1) + if (fileNlen < 1) sprintf(fnameptr,"%02X%02X%02X%02X.bin", data[0], data[1], data[2], data[3]); else sprintf(fnameptr + fileNlen,".bin"); - - saveFileEML(filename, "eml", data, numofbytes, 8); + + saveFileEML(filename, "eml", data, numofbytes, 8); saveFile(filename, "bin", data, numofbytes); return 0; } @@ -1204,57 +1204,57 @@ int CmdLegicESave(const char *Cmd) { int CmdLegicWipe(const char *Cmd){ char cmdp = tolower(param_getchar(Cmd, 0)); - + if ( cmdp == 'h') return usage_legic_wipe(); - + // tagtype legic_card_select_t card; if (legic_get_type(&card)) { PrintAndLogEx(WARNING, "Failed to identify tagtype"); return 1; } - + // set up buffer uint8_t *data = calloc(card.cardsize, sizeof(uint8_t)); if (!data) { PrintAndLogEx(WARNING, "Fail, cannot allocate memory"); - return 2; + return 2; } - + legic_print_type(card.cardsize, 0); PrintAndLogEx(SUCCESS, "Erasing"); - + // transfer to device size_t len = 0; UsbCommand c = {CMD_WRITER_LEGIC_RF, {0, 0, 0x55}}; UsbCommand resp; for(size_t i = 7; i < card.cardsize; i += USB_CMD_DATA_SIZE) { - + printf("."); fflush(stdout); - len = MIN((card.cardsize - i), USB_CMD_DATA_SIZE); + len = MIN((card.cardsize - i), USB_CMD_DATA_SIZE); c.arg[0] = i; // offset c.arg[1] = len; // number of bytes - memcpy(c.d.asBytes, data+i, len); + memcpy(c.d.asBytes, data+i, len); clearCommandBuffer(); SendCommand(&c); - + uint8_t timeout = 0; while (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { ++timeout; printf("."); fflush(stdout); if (timeout > 7) { PrintAndLogEx(WARNING, "\ncommand execution time out"); - free(data); + free(data); return 3; } - } - PrintAndLogEx(NORMAL, "\n"); + } + PrintAndLogEx(NORMAL, "\n"); uint8_t isOK = resp.arg[0] & 0xFF; if ( !isOK ) { PrintAndLogEx(WARNING, "Failed writing tag [msg = %u]", resp.arg[1] & 0xFF); - free(data); + free(data); return 4; } } @@ -1276,7 +1276,7 @@ static command_t CommandTable[] = { {"rdmem", CmdLegicRdmem, 0, "Read bytes from a LEGIC Prime tag"}, {"sim", CmdLegicRfSim, 0, "Start tag simulator"}, {"write", CmdLegicRfWrite, 0, "Write data to a LEGIC Prime tag"}, - {"crc", CmdLegicCalcCrc, 1, "Calculate Legic CRC over given bytes"}, + {"crc", CmdLegicCalcCrc, 1, "Calculate Legic CRC over given bytes"}, {"eload", CmdLegicELoad, 1, "Load binary dump to emulator memory"}, {"esave", CmdLegicESave, 1, "Save emulator memory to binary file"}, {"list", CmdLegicList, 1, "[Deprecated] List LEGIC history"}, diff --git a/client/cmdhflist.c b/client/cmdhflist.c index faed275cd..f605008c5 100644 --- a/client/cmdhflist.c +++ b/client/cmdhflist.c @@ -103,7 +103,7 @@ uint8_t iclass_CRC_check(bool isResponse, uint8_t* d, uint8_t n) { return check_crc( CRC_ICLASS, d+1, n-1); } return 2; - } + } /** These tag responses should have CRC. Total length leftmost @@ -154,12 +154,12 @@ int applyIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { case ISO14443A_CMD_REQA: snprintf(exp,size,"REQA"); break; case ISO14443A_CMD_READBLOCK: snprintf(exp,size,"READBLOCK(%d)",cmd[1]); break; case ISO14443A_CMD_WRITEBLOCK: snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); break; - case ISO14443A_CMD_HALT: - snprintf(exp,size,"HALT"); + case ISO14443A_CMD_HALT: + snprintf(exp,size,"HALT"); MifareAuthState = masNone; break; case ISO14443A_CMD_RATS: snprintf(exp,size,"RATS"); break; - case ISO14443A_CMD_OPTS: snprintf(exp,size,"OPTIONAL TIMESLOT"); break; + case ISO14443A_CMD_OPTS: snprintf(exp,size,"OPTIONAL TIMESLOT"); break; case MIFARE_CMD_INC: snprintf(exp,size,"INC(%d)",cmd[1]); break; case MIFARE_CMD_DEC: snprintf(exp,size,"DEC(%d)",cmd[1]); break; case MIFARE_CMD_RESTORE: snprintf(exp,size,"RESTORE(%d)",cmd[1]); break; @@ -176,7 +176,7 @@ int applyIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { } case MIFARE_AUTH_KEYB: { MifareAuthState = masNt; - snprintf(exp,size,"AUTH-B(%d)",cmd[1]); + snprintf(exp,size,"AUTH-B(%d)",cmd[1]); break; } case MIFARE_MAGICWUPC1: snprintf(exp,size,"MAGIC WUPC1"); break; @@ -184,7 +184,7 @@ int applyIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { case MIFARE_MAGICWIPEC: snprintf(exp,size,"MAGIC WIPEC"); break; case MIFARE_ULC_AUTH_1 : snprintf(exp,size,"AUTH "); break; case MIFARE_ULC_AUTH_2 : snprintf(exp,size,"AUTH_ANSW"); break; - case MIFARE_ULEV1_AUTH : + case MIFARE_ULEV1_AUTH : if ( cmdsize == 7 ) snprintf(exp,size,"PWD-AUTH KEY: 0x%02x%02x%02x%02x", cmd[1], cmd[2], cmd[3], cmd[4] ); else @@ -192,18 +192,18 @@ int applyIso14443a(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { break; case MIFARE_ULEV1_FASTREAD : { if ( cmdsize >=3 && cmd[2] <= 0xE6) - snprintf(exp,size,"READ RANGE (%d-%d)",cmd[1],cmd[2]); + snprintf(exp,size,"READ RANGE (%d-%d)",cmd[1],cmd[2]); else // outside limits, useful for some tags... - snprintf(exp,size,"READ RANGE (%d-%d) (?)",cmd[1], cmd[2]); + snprintf(exp,size,"READ RANGE (%d-%d) (?)",cmd[1], cmd[2]); break; } case MIFARE_ULC_WRITE : { if ( cmd[1] < 0x21 ) - snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); + snprintf(exp,size,"WRITEBLOCK(%d)",cmd[1]); else - // outside limits, useful for some tags... - snprintf(exp, size, "WRITEBLOCK(%d) (?)", cmd[1]); + // outside limits, useful for some tags... + snprintf(exp, size, "WRITEBLOCK(%d) (?)", cmd[1]); break; } case MIFARE_ULEV1_READ_CNT :{ @@ -278,9 +278,9 @@ void annotateIso15693(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { default: break; } - if ( cmd[1] >= 0x2D && cmd[1] <= 0x9F ) snprintf(exp, size, "Optional RFU"); - else if ( cmd[1] >= 0xA0 && cmd[1] <= 0xDF ) snprintf(exp, size, "Cust IC MFG dependent"); - else if ( cmd[1] >= 0xE0 && cmd[1] <= 0xFF ) snprintf(exp, size, "Proprietary IC MFG dependent"); + if ( cmd[1] >= 0x2D && cmd[1] <= 0x9F ) snprintf(exp, size, "Optional RFU"); + else if ( cmd[1] >= 0xA0 && cmd[1] <= 0xDF ) snprintf(exp, size, "Cust IC MFG dependent"); + else if ( cmd[1] >= 0xE0 && cmd[1] <= 0xFF ) snprintf(exp, size, "Proprietary IC MFG dependent"); else snprintf(exp, size, "?"); } @@ -302,10 +302,10 @@ void annotateTopaz(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ } } -// iso 7816-3 +// iso 7816-3 void annotateIso7816(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ // S-block - if ( (cmd[0] & 0xC0) && (cmdsize == 3) ) { + if ( (cmd[0] & 0xC0) && (cmdsize == 3) ) { switch ( (cmd[0] & 0x3f) ) { case 0x00 : snprintf(exp, size, "S-block RESYNCH req"); break; case 0x20 : snprintf(exp, size, "S-block RESYNCH resp"); break; @@ -316,11 +316,11 @@ void annotateIso7816(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ case 0x03 : snprintf(exp, size, "S-block WTX reqt"); break; case 0x23 : snprintf(exp, size, "S-block WTX resp"); break; default : snprintf(exp, size, "S-block"); break; - } + } } // R-block (ack) else if ( ((cmd[0] & 0xD0) == 0x80) && ( cmdsize > 2) ) { - if ( (cmd[0] & 0x10) == 0 ) + if ( (cmd[0] & 0x10) == 0 ) snprintf(exp, size, "R-block ACK"); else snprintf(exp, size, "R-block NACK"); @@ -365,20 +365,20 @@ void annotateIso7816(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ // MIFARE DESFire void annotateMfDesfire(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ - + // it's basically a ISO14443a tag, so try annotation from there if (!applyIso14443a(exp, size, cmd, cmdsize)){ // S-block 11xxx010 - if ( (cmd[0] & 0xC0) && (cmdsize == 3) ) { + if ( (cmd[0] & 0xC0) && (cmdsize == 3) ) { switch ( (cmd[0] & 0x30) ) { case 0x30 : snprintf(exp, size, "S-block DESELECT"); break; case 0x00 : snprintf(exp, size, "S-block WTX"); break; default : snprintf(exp, size, "S-block"); break; - } + } } // R-block (ack) 101xx01x else if ( ((cmd[0] & 0xB0) == 0xA0) && ( cmdsize > 2) ) { - if ( (cmd[0] & 0x10) == 0 ) + if ( (cmd[0] & 0x10) == 0 ) snprintf(exp, size, "R-block ACK(%d)", (cmd[0] & 0x01)); else snprintf(exp, size, "R-block NACK(%d)", (cmd[0] & 0x01)); @@ -450,14 +450,14 @@ void annotateMfDesfire(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ void annotateIso14443b(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { switch(cmd[0]){ case ISO14443B_REQB : { - + switch ( cmd[2] & 0x07 ) { case 0: snprintf(exp, size,"1 slot ");break; - case 1: snprintf(exp, size,"2 slots ");break; + case 1: snprintf(exp, size,"2 slots ");break; case 2: snprintf(exp, size,"4 slots ");break; case 3: snprintf(exp, size,"8 slots ");break; default: snprintf(exp, size,"16 slots ");break; - } + } if ( (cmd[2] & 0x8) ) snprintf(exp, size,"WUPB"); else @@ -480,12 +480,12 @@ void annotateIso14443b(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize) { } } -// LEGIC +// LEGIC // 1 = read // 0 = write // Quite simpel tag -void annotateLegic(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ - uint8_t bitsend = cmd[0]; +void annotateLegic(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ + uint8_t bitsend = cmd[0]; uint8_t cmdBit = (cmd[1] & 1); switch (bitsend){ case 7: @@ -505,11 +505,11 @@ void annotateLegic(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ case 11: { uint16_t address = (cmd[2] << 7) | cmd[1] >> 1; - - if (cmdBit == LEGIC_READ) + + if (cmdBit == LEGIC_READ) snprintf(exp, size, "READ Byte(%d)", address); - - if (cmdBit == LEGIC_WRITE ) + + if (cmdBit == LEGIC_WRITE ) snprintf(exp, size, "WRITE Byte(%d)", address); break; } @@ -535,7 +535,7 @@ void annotateLegic(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ } } -void annotateFelica(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ +void annotateFelica(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ switch(cmd[0]){ case FELICA_POLL_REQ: snprintf(exp,size ,"POLLING");break; @@ -547,7 +547,7 @@ void annotateFelica(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ case FELICA_RDBLK_REQ: snprintf(exp,size ,"READ BLK");break; case FELICA_RDBLK_ACK: snprintf(exp,size ,"READ BLK ACK");break; case FELICA_WRTBLK_REQ: snprintf(exp,size ,"WRITE BLK");break; - case FELICA_WRTBLK_ACK: snprintf(exp,size ,"WRITE BLK ACK");break; + case FELICA_WRTBLK_ACK: snprintf(exp,size ,"WRITE BLK ACK");break; case FELICA_SRCHSYSCODE_REQ: snprintf(exp,size ,"SEARCH SERVICE CODE");break; case FELICA_SRCHSYSCODE_ACK: snprintf(exp,size ,"SSC ACK");break; case FELICA_REQSYSCODE_REQ: snprintf(exp,size ,"REQUEST SYSTEM CODE");break; @@ -555,11 +555,11 @@ void annotateFelica(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ case FELICA_AUTH1_REQ: snprintf(exp,size ,"AUTH 1");break; case FELICA_AUTH1_ACK: snprintf(exp,size ,"AUTH 1 ACK");break; case FELICA_AUTH2_REQ: snprintf(exp,size ,"AUTH 2");break; - case FELICA_AUTH2_ACK: snprintf(exp,size ,"AUTH 2 ACK");break; + case FELICA_AUTH2_ACK: snprintf(exp,size ,"AUTH 2 ACK");break; case FELICA_RDSEC_REQ: snprintf(exp,size ,"READ");break; case FELICA_RDSEC_ACK: snprintf(exp,size ,"READ ACK");break; case FELICA_WRTSEC_REQ: snprintf(exp,size ,"WRITE");break; - case FELICA_WRTSEC_ACK: snprintf(exp,size ,"WRITE ACK");break; + case FELICA_WRTSEC_ACK: snprintf(exp,size ,"WRITE ACK");break; case FELICA_REQSRV2_REQ: snprintf(exp,size ,"REQUEST SERVICE v2");break; case FELICA_REQSRV2_ACK: snprintf(exp,size ,"REQ SERV v2 ACK");break; case FELICA_GETSTATUS_REQ: snprintf(exp,size ,"GET STATUS");break; @@ -567,17 +567,17 @@ void annotateFelica(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ case FELICA_OSVER_REQ: snprintf(exp,size ,"REQUEST SPECIFIC VERSION");break; case FELICA_OSVER_ACK: snprintf(exp,size ,"RSV ACK");break; case FELICA_RESET_MODE_REQ: snprintf(exp,size ,"RESET MODE");break; - case FELICA_RESET_MODE_ACK: snprintf(exp,size ,"RESET MODE ACK");break; + case FELICA_RESET_MODE_ACK: snprintf(exp,size ,"RESET MODE ACK");break; case FELICA_AUTH1V2_REQ: snprintf(exp,size ,"AUTH 1 v2");break; case FELICA_AUTH1V2_ACK: snprintf(exp,size ,"AUTH 1 v2 ACK");break; case FELICA_AUTH2V2_REQ: snprintf(exp,size ,"AUTH 2 v2");break; - case FELICA_AUTH2V2_ACK: snprintf(exp,size ,"AUTH 2 v2 ACK");break; + case FELICA_AUTH2V2_ACK: snprintf(exp,size ,"AUTH 2 v2 ACK");break; case FELICA_RDSECV2_REQ: snprintf(exp,size ,"READ v2");break; case FELICA_RDSECV2_ACK: snprintf(exp,size ,"READ v2 ACK");break; case FELICA_WRTSECV2_REQ: snprintf(exp,size ,"WRITE v2");break; - case FELICA_WRTSECV2_ACK: snprintf(exp,size ,"WRITE v2 ACK");break; + case FELICA_WRTSECV2_ACK: snprintf(exp,size ,"WRITE v2 ACK");break; case FELICA_UPDATE_RNDID_REQ: snprintf(exp,size ,"UPDATE RANDOM ID");break; - case FELICA_UPDATE_RNDID_ACK: snprintf(exp,size ,"URI ACK");break; + case FELICA_UPDATE_RNDID_ACK: snprintf(exp,size ,"URI ACK");break; default : snprintf(exp,size ,"?");break; } } @@ -585,15 +585,15 @@ void annotateFelica(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize){ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8_t* parity, uint8_t paritysize, bool isResponse) { if (!isResponse && cmdsize == 1) { switch(cmd[0]) { - case ISO14443A_CMD_WUPA: - case ISO14443A_CMD_REQA: + case ISO14443A_CMD_WUPA: + case ISO14443A_CMD_REQA: MifareAuthState = masNone; break; default: break; } } - + // get UID if (MifareAuthState == masNone) { if (cmdsize == 9 && cmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && cmd[1] == 0x70) { @@ -609,7 +609,7 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8 AuthData.uid = bytes_to_num(&cmd[2], 4); } } - + switch(MifareAuthState) { case masNt: if (cmdsize == 4 && isResponse) { @@ -652,18 +652,18 @@ void annotateMifare(char *exp, size_t size, uint8_t* cmd, uint8_t cmdsize, uint8 default: break; } - + if (!isResponse && ((MifareAuthState == masNone) || (MifareAuthState == masError))) annotateIso14443a(exp, size, cmd, cmdsize); - + } bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isResponse, uint8_t *mfData, size_t *mfDataLen) { - static struct Crypto1State *traceCrypto1; + static struct Crypto1State *traceCrypto1; static uint64_t mfLastKey; - + *mfDataLen = 0; - + if (MifareAuthState == masAuthComplete) { if (traceCrypto1) { crypto1_destroy(traceCrypto1); @@ -673,21 +673,21 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes MifareAuthState = masFirstData; return false; } - + if (cmdsize > 32) return false; - + if (MifareAuthState == masFirstData) { if (AuthData.first_auth) { AuthData.ks2 = AuthData.ar_enc ^ prng_successor(AuthData.nt, 64); AuthData.ks3 = AuthData.at_enc ^ prng_successor(AuthData.nt, 96); mfLastKey = GetCrypto1ProbableKey(&AuthData); - PrintAndLogEx(NORMAL, " | | * |%49s %012"PRIx64" prng %s | |", - "key", + PrintAndLogEx(NORMAL, " | | * |%49s %012"PRIx64" prng %s | |", + "key", mfLastKey, validate_prng_nonce(AuthData.nt) ? _GREEN_(WEAK): _YELLOW_(HARD)); - + AuthData.first_auth = false; traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3); @@ -704,7 +704,7 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3); }; } - + // check default keys if (!traceCrypto1) { for (int i = 0; i < MIFARE_DEFAULTKEYS_SIZE; i++){ @@ -717,10 +717,10 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes }; } } - + // nested if (!traceCrypto1 && validate_prng_nonce(AuthData.nt)) { - uint32_t ntx = prng_successor(AuthData.nt, 90); + uint32_t ntx = prng_successor(AuthData.nt, 90); for (int i = 0; i < 16383; i++) { ntx = prng_successor(ntx, 1); if (NTParityChk(&AuthData, ntx)){ @@ -729,15 +729,15 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes uint32_t ks3 = AuthData.at_enc ^ prng_successor(ntx, 96); struct Crypto1State *pcs = lfsr_recovery64(ks2, ks3); memcpy(mfData, cmd, cmdsize); - mf_crypto1_decrypt(pcs, mfData, cmdsize, 0); + mf_crypto1_decrypt(pcs, mfData, cmdsize, 0); crypto1_destroy(pcs); - + if (CheckCrypto1Parity(cmd, cmdsize, mfData, parity) && check_crc(CRC_14443_A, mfData, cmdsize)) { AuthData.ks2 = ks2; AuthData.ks3 = ks3; AuthData.nt = ntx; mfLastKey = GetCrypto1ProbableKey(&AuthData); - PrintAndLogEx(NORMAL, " | | * | nested probable key:%012"PRIx64" ks2:%08x ks3:%08x | |", + PrintAndLogEx(NORMAL, " | | * | nested probable key:%012"PRIx64" ks2:%08x ks3:%08x | |", mfLastKey, AuthData.ks2, AuthData.ks3); @@ -745,10 +745,10 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes traceCrypto1 = lfsr_recovery64(AuthData.ks2, AuthData.ks3); break; } - } + } } } - + //hardnested if (!traceCrypto1) { PrintAndLogEx(NORMAL, "hardnested not implemented. uid:%x nt:%x ar_enc:%x at_enc:%x\n", AuthData.uid, AuthData.nt, AuthData.ar_enc, AuthData.at_enc); @@ -780,13 +780,13 @@ bool DecodeMifareData(uint8_t *cmd, uint8_t cmdsize, uint8_t *parity, bool isRes } MifareAuthState = masData; } - + if (MifareAuthState == masData && traceCrypto1) { memcpy(mfData, cmd, cmdsize); mf_crypto1_decrypt(traceCrypto1, mfData, cmdsize, 0); *mfDataLen = cmdsize; } - + return *mfDataLen > 0; } @@ -797,7 +797,7 @@ bool NTParityChk(TAuthData *ad, uint32_t ntx) { (oddparity8(ntx >> 24 & 0xff) ^ (ntx >> 16 & 0x01) ^ ((ad->nt_enc_par >> 7) & 0x01) ^ (ad->nt_enc >> 16 & 0x01)) ) return false; - + uint32_t ar = prng_successor(ntx, 64); if ( (oddparity8(ar >> 8 & 0xff) ^ (ar & 0x01) ^ ((ad->ar_enc_par >> 5) & 0x01) ^ (ad->ar_enc & 0x01)) || @@ -814,14 +814,14 @@ bool NTParityChk(TAuthData *ad, uint32_t ntx) { (oddparity8(at >> 24 & 0xff) ^ (at >> 16 & 0x01) ^ ((ad->at_enc_par >> 7) & 0x01) ^ (ad->at_enc >> 16 & 0x01)) ) return false; - + return true; } bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize, uint8_t *parity) { uint8_t buf[32] = {0}; struct Crypto1State *pcs; - + AuthData.ks2 = 0; AuthData.ks3 = 0; @@ -843,13 +843,13 @@ bool NestedCheckKey(uint64_t key, TAuthData *ad, uint8_t *cmd, uint8_t cmdsize, memcpy(buf, cmd, cmdsize); mf_crypto1_decrypt(pcs, buf, cmdsize, 0); crypto1_destroy(pcs); - + if (!CheckCrypto1Parity(cmd, cmdsize, buf, parity)) return false; - if (!check_crc(CRC_14443_A, buf, cmdsize)) + if (!check_crc(CRC_14443_A, buf, cmdsize)) return false; - + AuthData.nt = nt1; AuthData.ks2 = AuthData.ar_enc ^ ar; AuthData.ks3 = AuthData.at_enc ^ at; @@ -865,7 +865,7 @@ bool CheckCrypto1Parity(uint8_t *cmd_enc, uint8_t cmdsize, uint8_t *cmd, uint8_t } // Another implementation of mfkey64 attack, more "valid" than "probable" -// +// uint64_t GetCrypto1ProbableKey(TAuthData *ad) { struct Crypto1State *revstate = lfsr_recovery64(ad->ks2, ad->ks3); lfsr_rollback_word(revstate, 0, 0); diff --git a/client/cmdhfmf.c b/client/cmdhfmf.c index da027aad6..fa1f13102 100644 --- a/client/cmdhfmf.c +++ b/client/cmdhfmf.c @@ -17,7 +17,7 @@ #define MFBLOCK_SIZE 16 #define MIFARE_4K_MAXBLOCK 256 -#define MIFARE_2K_MAXBLOCK 128 +#define MIFARE_2K_MAXBLOCK 128 #define MIFARE_1K_MAXBLOCK 64 #define MIFARE_MINI_MAXBLOCK 20 @@ -77,14 +77,14 @@ int usage_hf14_mf1ksim(void){ PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf sim u 0a0a0a0a"); PrintAndLogEx(NORMAL, " hf mf sim u 11223344556677"); - PrintAndLogEx(NORMAL, " hf mf sim u 112233445566778899AA"); - PrintAndLogEx(NORMAL, " hf mf sim u 11223344 i x"); + PrintAndLogEx(NORMAL, " hf mf sim u 112233445566778899AA"); + PrintAndLogEx(NORMAL, " hf mf sim u 11223344 i x"); return 0; } int usage_hf14_dbg(void){ PrintAndLogEx(NORMAL, "Usage: hf mf dbg [h] "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " (Optional) see list for valid levels"); PrintAndLogEx(NORMAL, " 0 - no debug messages"); PrintAndLogEx(NORMAL, " 1 - error messages"); @@ -134,7 +134,7 @@ int usage_hf14_hardnested(void){ PrintAndLogEx(NORMAL, " or hf mf hardnested r [known target key]"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " w acquire nonces and UID, and write them to binary file with default name hf-mf--nonces.bin"); PrintAndLogEx(NORMAL, " s slower acquisition (required by some non standard cards)"); PrintAndLogEx(NORMAL, " r read hf-mf--nonces.bin if tag present, otherwise read nonces.bin, then start attack"); @@ -147,7 +147,7 @@ int usage_hf14_hardnested(void){ PrintAndLogEx(NORMAL, " i a = AVX"); PrintAndLogEx(NORMAL, " i s = SSE2"); PrintAndLogEx(NORMAL, " i m = MMX"); - PrintAndLogEx(NORMAL, " i n = none (use CPU regular instruction set)"); + PrintAndLogEx(NORMAL, " i n = none (use CPU regular instruction set)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf hardnested 0 A FFFFFFFFFFFF 4 A"); @@ -163,7 +163,7 @@ int usage_hf14_hardnested(void){ int usage_hf14_chk(void){ PrintAndLogEx(NORMAL, "Usage: hf mf chk [h] |<*card memory> [t|d] [] []"); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " * all sectors based on card memory, other values then below defaults to 1k"); PrintAndLogEx(NORMAL, " 0 - MINI(320 bytes)"); PrintAndLogEx(NORMAL, " 1 - 1K"); @@ -182,7 +182,7 @@ int usage_hf14_chk_fast(void){ PrintAndLogEx(NORMAL, "This is a improved checkkeys method speedwise. It checks Mifare Classic tags sector keys against a dictionary file with keys"); PrintAndLogEx(NORMAL, "Usage: hf mf fchk [h] [t|d|f] [] []"); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " all sectors based on card memory, other values than below defaults to 1k"); PrintAndLogEx(NORMAL, " 0 - MINI(320 bytes)"); PrintAndLogEx(NORMAL, " 1 - 1K "); @@ -204,7 +204,7 @@ int usage_hf14_chk_fast(void){ int usage_hf14_keybrute(void){ PrintAndLogEx(NORMAL, "J_Run's 2nd phase of multiple sector nested authentication key recovery"); PrintAndLogEx(NORMAL, "You have a known 4 last bytes of a key recovered with mf_nonce_brute tool."); - PrintAndLogEx(NORMAL, "First 2 bytes of key will be bruteforced"); + PrintAndLogEx(NORMAL, "First 2 bytes of key will be bruteforced"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " ---[ This attack is obsolete, try hardnested instead ]---"); PrintAndLogEx(NORMAL, ""); @@ -262,7 +262,7 @@ int usage_hf14_eclr(void){ int usage_hf14_eset(void){ PrintAndLogEx(NORMAL, "Usage: hf mf eset "); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf eset 1 000102030405060708090a0b0c0d0e0f "); + PrintAndLogEx(NORMAL, " hf mf eset 1 000102030405060708090a0b0c0d0e0f "); return 0; } int usage_hf14_eload(void){ @@ -272,7 +272,7 @@ int usage_hf14_eload(void){ PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf eload filename"); - PrintAndLogEx(NORMAL, " hf mf eload 4 filename"); + PrintAndLogEx(NORMAL, " hf mf eload 4 filename"); return 0; } int usage_hf14_esave(void){ @@ -283,7 +283,7 @@ int usage_hf14_esave(void){ PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf esave "); PrintAndLogEx(NORMAL, " hf mf esave 4"); - PrintAndLogEx(NORMAL, " hf mf esave 4 filename"); + PrintAndLogEx(NORMAL, " hf mf esave 4 filename"); return 0; } int usage_hf14_ecfill(void){ @@ -303,7 +303,7 @@ int usage_hf14_ekeyprn(void){ PrintAndLogEx(NORMAL, " [card memory]: 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf ekeyprn 1"); + PrintAndLogEx(NORMAL, " hf mf ekeyprn 1"); return 0; } @@ -324,7 +324,7 @@ int usage_hf14_csetuid(void){ } int usage_hf14_csetblk(void){ PrintAndLogEx(NORMAL, "Set block data for magic Chinese card. Only works with magic cards"); - PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: hf mf csetblk [h] [w]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h this help"); @@ -349,7 +349,7 @@ int usage_hf14_cload(void){ PrintAndLogEx(NORMAL, " load card with data from eml file"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf cload mydump"); - PrintAndLogEx(NORMAL, " hf mf cload e"); + PrintAndLogEx(NORMAL, " hf mf cload e"); return 0; } int usage_hf14_cgetblk(void){ @@ -358,9 +358,9 @@ int usage_hf14_cgetblk(void){ PrintAndLogEx(NORMAL, "Usage: hf mf cgetblk [h] "); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " block number"); + PrintAndLogEx(NORMAL, " block number"); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf mf cgetblk 1"); + PrintAndLogEx(NORMAL, " hf mf cgetblk 1"); return 0; } int usage_hf14_cgetsc(void){ @@ -382,7 +382,7 @@ int usage_hf14_csave(void){ PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h this help"); PrintAndLogEx(NORMAL, " e save data to emulator memory"); - PrintAndLogEx(NORMAL, " u save data to file, use carduid as filename"); + PrintAndLogEx(NORMAL, " u save data to file, use carduid as filename"); PrintAndLogEx(NORMAL, " card memory 0 = 320 bytes (Mifare Mini), 1 = 1K (default), 2 = 2K, 4 = 4K"); PrintAndLogEx(NORMAL, " o save data to file"); PrintAndLogEx(NORMAL, ""); @@ -394,7 +394,7 @@ int usage_hf14_csave(void){ } int usage_hf14_nack(void) { PrintAndLogEx(NORMAL, "Test a mifare classic based card for the NACK bug."); - PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: hf mf nack [h] [v]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h this help"); @@ -414,7 +414,7 @@ int GetHFMF14AUID(uint8_t *uid, int *uidlen) { DropField(); return 0; } - + iso14a_card_select_t card; memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); memcpy(uid, card.uid, card.uidlen * sizeof(uint8_t)); @@ -426,15 +426,15 @@ char * GenerateFilename(const char *prefix, const char *suffix){ uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; int uidlen=0; char * fptr = calloc (sizeof (char) * (strlen(prefix) + strlen(suffix)) + sizeof(uid)*2 + 1, sizeof(uint8_t)); - + GetHFMF14AUID(uid, &uidlen); if (!uidlen) { PrintAndLogEx(WARNING, "No tag found."); free(fptr); return NULL; } - - strcpy(fptr, prefix); + + strcpy(fptr, prefix); FillFileNameByUID(fptr, uid, suffix, uidlen); return fptr; } @@ -442,12 +442,12 @@ char * GenerateFilename(const char *prefix, const char *suffix){ int CmdHF14AMfDarkside(const char *Cmd) { uint8_t blockno = 0, key_type = MIFARE_AUTH_KEYA; uint64_t key = 0; - - char cmdp = tolower(param_getchar(Cmd, 0)); + + char cmdp = tolower(param_getchar(Cmd, 0)); if ( cmdp == 'h' ) return usage_hf14_mifare(); - - blockno = param_get8(Cmd, 0); - + + blockno = param_get8(Cmd, 0); + cmdp = tolower(param_getchar(Cmd, 1)); if (cmdp == 'b') key_type = MIFARE_AUTH_KEYB; @@ -479,7 +479,7 @@ int CmdHF14AMfWrBl(const char *Cmd) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F"); return 0; - } + } blockNo = param_get8(Cmd, 0); cmdp = tolower(param_getchar(Cmd, 1)); @@ -487,23 +487,23 @@ int CmdHF14AMfWrBl(const char *Cmd) { PrintAndLogEx(NORMAL, "Key type must be A or B"); return 1; } - - if (cmdp != 'a') + + if (cmdp != 'a') keyType = 1; - + if (param_gethex(Cmd, 2, key, 12)) { PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); return 1; } - + if (param_gethex(Cmd, 3, bldata, 32)) { PrintAndLogEx(NORMAL, "Block data must include 32 HEX symbols"); return 1; } - + PrintAndLogEx(NORMAL, "--block no:%d, key type:%c, key:%s", blockNo, keyType?'B':'A', sprint_hex(key, 6)); PrintAndLogEx(NORMAL, "--data: %s", sprint_hex(bldata, 16)); - + UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}}; memcpy(c.d.asBytes, key, 6); memcpy(c.d.asBytes + 10, bldata, 16); @@ -532,24 +532,24 @@ int CmdHF14AMfRdBl(const char *Cmd) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf rdbl 0 A FFFFFFFFFFFF "); return 0; - } - + } + blockNo = param_get8(Cmd, 0); cmdp = tolower(param_getchar(Cmd, 1)); if (cmdp == 0x00) { PrintAndLogEx(NORMAL, "Key type must be A or B"); return 1; } - - if (cmdp != 'a') + + if (cmdp != 'a') keyType = 1; - + if (param_gethex(Cmd, 2, key, 12)) { PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); return 1; } PrintAndLogEx(NORMAL, "--block no:%d, key type:%c, key:%s ", blockNo, keyType?'B':'A', sprint_hex(key, 6)); - + UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}}; memcpy(c.d.asBytes, key, 6); clearCommandBuffer(); @@ -581,7 +581,7 @@ int CmdHF14AMfRdBl(const char *Cmd) { PrintAndLogEx(WARNING, "Command execute timeout"); return 2; } - + return 0; } @@ -599,29 +599,29 @@ int CmdHF14AMfRdSc(const char *Cmd) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mf rdsc 0 A FFFFFFFFFFFF "); return 0; - } - + } + sectorNo = param_get8(Cmd, 0); if (sectorNo > MIFARE_4K_MAXSECTOR ) { PrintAndLogEx(NORMAL, "Sector number must be less than 40"); return 1; } - + cmdp = tolower(param_getchar(Cmd, 1)); if (cmdp != 'a' && cmdp != 'b') { PrintAndLogEx(NORMAL, "Key type must be A or B"); return 1; } - - if (cmdp != 'a') + + if (cmdp != 'a') keyType = 1; - + if (param_gethex(Cmd, 2, key, 12)) { PrintAndLogEx(NORMAL, "Key must include 12 HEX symbols"); return 1; } PrintAndLogEx(NORMAL, "--sector no:%d key type:%c key:%s ", sectorNo, keyType?'B':'A', sprint_hex(key, 6)); - + UsbCommand c = {CMD_MIFARE_READSC, {sectorNo, keyType, 0}}; memcpy(c.d.asBytes, key, 6); clearCommandBuffer(); @@ -639,7 +639,7 @@ int CmdHF14AMfRdSc(const char *Cmd) { PrintAndLogEx(NORMAL, "data : %s", sprint_hex(data + i * 16, 16)); } PrintAndLogEx(NORMAL, "trailer: %s", sprint_hex(data + (sectorNo<32?3:15) * 16, 16)); - + PrintAndLogEx(NORMAL, "Trailer decoded:"); int bln = mfFirstBlockOfSector(sectorNo); int blinc = (mfNumBlocksPerSector(sectorNo) > 4) ? 5 : 1; @@ -667,10 +667,10 @@ uint16_t NumOfBlocks(char card){ } uint8_t NumOfSectors(char card){ switch(card){ - case '0' : return MIFARE_MINI_MAXSECTOR; - case '1' : return MIFARE_1K_MAXSECTOR; - case '2' : return MIFARE_2K_MAXSECTOR; - case '4' : return MIFARE_4K_MAXSECTOR; + case '0' : return MIFARE_MINI_MAXSECTOR; + case '1' : return MIFARE_1K_MAXSECTOR; + case '2' : return MIFARE_2K_MAXSECTOR; + case '4' : return MIFARE_4K_MAXSECTOR; default : return MIFARE_1K_MAXSECTOR; } } @@ -700,27 +700,27 @@ int CmdHF14AMfDump(const char *Cmd) { uint8_t carddata[256][16]; uint8_t numSectors = 16; uint8_t cmdp = 0; - + char keyFilename[FILE_PATH_SIZE] = {0}; char dataFilename[FILE_PATH_SIZE]; char * fptr; - + memset(keyFilename, 0, sizeof(keyFilename)); memset(dataFilename, 0, sizeof(dataFilename)); - - FILE *f; + + FILE *f; UsbCommand resp; - + while(param_getchar(Cmd, cmdp) != 0x00) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_hf14_dump(); case 'k': - param_getstr(Cmd, cmdp+1, keyFilename, FILE_PATH_SIZE); + param_getstr(Cmd, cmdp+1, keyFilename, FILE_PATH_SIZE); cmdp += 2; break; case 'f': - param_getstr(Cmd, cmdp+1, dataFilename, FILE_PATH_SIZE); + param_getstr(Cmd, cmdp+1, dataFilename, FILE_PATH_SIZE); cmdp += 2; break; default: @@ -736,9 +736,9 @@ int CmdHF14AMfDump(const char *Cmd) { if ( keyFilename[0] == 0x00 ) { fptr = GenerateFilename("hf-mf-", "-key.bin"); - if (fptr == NULL) + if (fptr == NULL) return 1; - + strcpy(keyFilename, fptr); } @@ -746,7 +746,7 @@ int CmdHF14AMfDump(const char *Cmd) { PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), keyFilename); return 1; } - + // Read keys A from file size_t bytes_read; for (sectorNo=0; sectorNo= FILE_PATH_SIZE ) { PrintAndLogEx(FAILED, "Filename too long"); continue; } - + f = fopen( filename, "r"); if ( !f ){ PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); continue; } - + // read file while( fgets(buf, sizeof(buf), f) ){ if (strlen(buf) < 12 || buf[11] == '\n') continue; - + while (fgetc(f) != '\n' && !feof(f)) ; //goto next line - + if( buf[0]=='#' ) continue; //The line start with # is comment, skip if (!isxdigit(buf[0])){ PrintAndLogEx(FAILED, "File content error. '" _YELLOW_(%s)"' must include 12 HEX symbols", buf); continue; } - + buf[12] = 0; if ( keyitems - keycnt < 2) { p = realloc(keyBlock, 6 * (keyitems += 64)); @@ -1600,7 +1600,7 @@ int CmdHF14AMfChk_fast(const char *Cmd) { PrintAndLogEx(SUCCESS, "Loaded %2d keys from " _YELLOW_(%s), keycnt, filename); } } - + if (keycnt == 0 && !use_flashmemory) { PrintAndLogEx(SUCCESS, "No key specified, trying default keys"); for (;keycnt < MIFARE_DEFAULTKEYS_SIZE; keycnt++) @@ -1608,17 +1608,17 @@ int CmdHF14AMfChk_fast(const char *Cmd) { (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], (keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5]); } - + // // initialize storage for found keys e_sector = calloc(sectorsCnt, sizeof(sector_t)); if (e_sector == NULL) { free(keyBlock); return 1; } - + uint32_t chunksize = keycnt > (USB_CMD_DATA_SIZE/6) ? (USB_CMD_DATA_SIZE/6) : keycnt; bool firstChunk = true, lastChunk = false; - + // time uint64_t t1 = msclock(); @@ -1626,31 +1626,31 @@ int CmdHF14AMfChk_fast(const char *Cmd) { PrintAndLogEx(SUCCESS, "Using dictionary in flash memory"); mfCheckKeys_fast( sectorsCnt, true, true, 1, 0, keyBlock, e_sector, use_flashmemory); } else { - + // strategys. 1= deep first on sector 0 AB, 2= width first on all sectors for (uint8_t strategy = 1; strategy < 3; strategy++) { PrintAndLogEx(SUCCESS, "Running strategy %u", strategy); - // main keychunk loop + // main keychunk loop for (uint32_t i = 0; i < keycnt; i += chunksize) { - + if (ukbhit()) { int gc = getchar(); (void)gc; PrintAndLogEx(WARNING, "\naborted via keyboard!\n"); goto out; } - + uint32_t size = ((keycnt - i) > chunksize) ? chunksize : keycnt - i; - + // last chunk? if ( size == keycnt - i) lastChunk = true; - + int res = mfCheckKeys_fast( sectorsCnt, firstChunk, lastChunk, strategy, size, keyBlock + (i * 6), e_sector, false); if ( firstChunk ) firstChunk = false; - + // all keys, aborted if ( res == 0 || res == 2 ) goto out; @@ -1659,25 +1659,25 @@ int CmdHF14AMfChk_fast(const char *Cmd) { lastChunk = false; } // end strategy } -out: +out: t1 = msclock() - t1; PrintAndLogEx(SUCCESS, "Time in checkkeys (fast): %.1fs\n", (float)(t1/1000.0)); // check.. uint8_t found_keys = 0; for (uint8_t i = 0; i < sectorsCnt; ++i) { - - if ( e_sector[i].foundKey[0] ) + + if ( e_sector[i].foundKey[0] ) found_keys++; - + if ( e_sector[i].foundKey[1] ) found_keys++; } - + if ( found_keys == 0 ) { PrintAndLogEx(WARNING, "No keys found"); } else { - + printKeyTable( sectorsCnt, e_sector ); if (transferToEml) { @@ -1692,21 +1692,21 @@ out: } PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory"); } - + if (createDumpFile) { fptr = GenerateFilename("hf-mf-", "-key.bin"); - if (fptr == NULL) + if (fptr == NULL) return 1; FILE *fkeys = fopen(fptr, "wb"); - if (fkeys == NULL) { + if (fkeys == NULL) { PrintAndLogEx(WARNING, "Could not create file " _YELLOW_(%s), fptr); free(keyBlock); free(e_sector); return 1; } PrintAndLogEx(SUCCESS, "Printing keys to binary file " _YELLOW_(%s)"...", fptr); - + for (i=0; i 0xffffffffffff has been inserted for unknown keys.", fptr); - } + PrintAndLogEx(SUCCESS, "Found keys have been dumped to " _YELLOW_(%s)" --> 0xffffffffffff has been inserted for unknown keys.", fptr); + } } - + free(keyBlock); free(e_sector); PrintAndLogEx(NORMAL, ""); @@ -1743,12 +1743,12 @@ int CmdHF14AMfChk(const char *Cmd) { uint8_t SectorsCnt = 1; uint8_t keyType = 0; uint32_t keyitems = MIFARE_DEFAULTKEYS_SIZE; - uint64_t key64 = 0; + uint64_t key64 = 0; uint8_t tempkey[6] = {0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}; char *fptr; int clen = 0; int transferToEml = 0; - int createDumpFile = 0; + int createDumpFile = 0; int i, res, keycnt = 0; keyBlock = calloc(MIFARE_DEFAULTKEYS_SIZE, 6); @@ -1756,18 +1756,18 @@ int CmdHF14AMfChk(const char *Cmd) { for (int cnt = 0; cnt < MIFARE_DEFAULTKEYS_SIZE; cnt++) num_to_bytes(g_mifare_default_keys[cnt], 6, (uint8_t*)(keyBlock + cnt * 6)); - + if (param_getchar(Cmd, 0)=='*') { blockNo = 3; SectorsCnt = NumOfSectors( param_getchar(Cmd+1, 0) ); } else { blockNo = param_get8(Cmd, 0); } - + ctmp = tolower(param_getchar(Cmd, 1)); clen = param_getlength(Cmd, 1); if (clen == 1) { - switch (ctmp) { + switch (ctmp) { case 'a': keyType = 0; break; @@ -1788,9 +1788,9 @@ int CmdHF14AMfChk(const char *Cmd) { ctmp = tolower(param_getchar(Cmd, i)); clen = param_getlength(Cmd, i); - + if (clen == 12) { - + if ( param_gethex(Cmd, i, keyBlock + 6 * keycnt, 12) ){ PrintAndLogEx(FAILED, "not hex, skipping"); continue; @@ -1816,20 +1816,20 @@ int CmdHF14AMfChk(const char *Cmd) { PrintAndLogEx(FAILED, "File name too long"); continue; } - + f = fopen( filename , "r"); if ( !f ) { PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); continue; } - + // load keys from dictionary file while( fgets(buf, sizeof(buf), f) ){ if (strlen(buf) < 12 || buf[11] == '\n') continue; - + while (fgetc(f) != '\n' && !feof(f)) ; //goto next line - + if( buf[0]=='#' ) continue; //The line start with # is comment, skip // codesmell, only checks first char? @@ -1837,7 +1837,7 @@ int CmdHF14AMfChk(const char *Cmd) { PrintAndLogEx(FAILED, "File content error. '" _YELLOW_(%s)"' must include 12 HEX symbols",buf); continue; } - + buf[12] = 0; if ( keyitems - keycnt < 2) { @@ -1860,7 +1860,7 @@ int CmdHF14AMfChk(const char *Cmd) { PrintAndLogEx(SUCCESS, "Loaded %2d keys from " _YELLOW_(%s), keycnt, filename); } } - + if (keycnt == 0) { PrintAndLogEx(INFO, "No key specified, trying default keys"); for (;keycnt < MIFARE_DEFAULTKEYS_SIZE; keycnt++) @@ -1868,7 +1868,7 @@ int CmdHF14AMfChk(const char *Cmd) { (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], (keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6); } - + // initialize storage for found keys e_sector = calloc(SectorsCnt, sizeof(sector_t)); if (e_sector == NULL) { @@ -1883,62 +1883,62 @@ int CmdHF14AMfChk(const char *Cmd) { e_sector[i].foundKey[0] = false; e_sector[i].foundKey[1] = false; } - - + + uint8_t trgKeyType = 0; uint32_t max_keys = keycnt > (USB_CMD_DATA_SIZE/6) ? (USB_CMD_DATA_SIZE/6) : keycnt; - + // time uint64_t t1 = msclock(); - + // check keys. for (trgKeyType = (keyType==2)?0:keyType; trgKeyType < 2; (keyType==2) ? (++trgKeyType) : (trgKeyType=2) ) { int b = blockNo; for (int i = 0; i < SectorsCnt; ++i) { - + // skip already found keys. if (e_sector[i].foundKey[trgKeyType]) continue; - + for (uint32_t c = 0; c < keycnt; c += max_keys) { - + printf("."); fflush(stdout); if (ukbhit()) { int gc = getchar(); (void)gc; PrintAndLogEx(INFO, "\naborted via keyboard!\n"); goto out; } - + uint32_t size = keycnt-c > max_keys ? max_keys : keycnt-c; - + res = mfCheckKeys(b, trgKeyType, true, size, &keyBlock[6*c], &key64); if (!res) { e_sector[i].Key[trgKeyType] = key64; e_sector[i].foundKey[trgKeyType] = true; break; } - + } - b < 127 ? ( b +=4 ) : ( b += 16 ); + b < 127 ? ( b +=4 ) : ( b += 16 ); } } t1 = msclock() - t1; PrintAndLogEx(SUCCESS, "\nTime in checkkeys: %.0f seconds\n", (float)t1/1000.0); - + // 20160116 If Sector A is found, but not Sector B, try just reading it of the tag? if ( keyType != 1 ) { PrintAndLogEx(INFO, "testing to read key B..."); for (i = 0; i < SectorsCnt; i++) { // KEY A but not KEY B if ( e_sector[i].foundKey[0] && !e_sector[i].foundKey[1] ) { - + uint8_t sectrail = (FirstBlockOfSector(i) + NumBlocksPerSector(i) - 1); - + PrintAndLogEx(NORMAL, "Reading block %d", sectrail); - + UsbCommand c = {CMD_MIFARE_READBL, {sectrail, 0, 0}}; num_to_bytes(e_sector[i].Key[0], 6, c.d.asBytes); // KEY A clearCommandBuffer(); @@ -1946,7 +1946,7 @@ int CmdHF14AMfChk(const char *Cmd) { UsbCommand resp; if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) continue; - + uint8_t isOK = resp.arg[0] & 0xff; if (!isOK) continue; @@ -1962,10 +1962,10 @@ int CmdHF14AMfChk(const char *Cmd) { } out: - + //print keys printKeyTable( SectorsCnt, e_sector ); - + if (transferToEml) { uint8_t block[16] = {0x00}; for (uint8_t i = 0; i < SectorsCnt; ++i ) { @@ -1978,24 +1978,24 @@ out: } PrintAndLogEx(SUCCESS, "Found keys have been transferred to the emulator memory"); } - + if (createDumpFile) { fptr = GenerateFilename("hf-mf-", "-key.bin"); if (fptr == NULL) { free(keyBlock); - free(e_sector); + free(e_sector); return 1; } FILE *fkeys = fopen(fptr, "wb"); - if (fkeys == NULL) { + if (fkeys == NULL) { PrintAndLogEx(WARNING, "Could not create file " _YELLOW_(%s), fptr); free(keyBlock); free(e_sector); return 1; } PrintAndLogEx(INFO, "Printing keys to binary file " _YELLOW_(%s)"...", fptr); - + for( i=0; i>1) , exitAfterNReads @@ -2141,12 +2141,12 @@ int CmdHF14AMf1kSim(const char *Cmd) { memcpy(c.d.asBytes, uid, sizeof(uid)); clearCommandBuffer(); SendCommand(&c); - UsbCommand resp; + UsbCommand resp; if(flags & FLAG_INTERACTIVE) { PrintAndLogEx(INFO, "Press pm3-button or send another cmd to abort simulation"); - while( !ukbhit() ){ + while( !ukbhit() ){ if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; if ( !(flags & FLAG_NR_AR_ATTACK) ) break; if ( (resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD ) break; @@ -2165,7 +2165,7 @@ int CmdHF14AMfSniff(const char *Cmd){ //bool wantSaveToEml = false; TODO bool wantSaveToEmlFile = false; - //var + //var int res = 0, len = 0, blockLen = 0; int pckNum = 0, num = 0; uint8_t sak = 0; @@ -2177,12 +2177,12 @@ int CmdHF14AMfSniff(const char *Cmd){ uint16_t bufsize = 0; uint8_t *bufPtr = NULL; uint16_t traceLen = 0; - + memset(uid, 0x00, sizeof(uid)); - + char ctmp = tolower(param_getchar(Cmd, 0)); if ( ctmp == 'h') return usage_hf14_sniff(); - + for (int i = 0; i < 4; i++) { ctmp = tolower(param_getchar(Cmd, i)); if (ctmp == 'l') wantLogToFile = true; @@ -2190,7 +2190,7 @@ int CmdHF14AMfSniff(const char *Cmd){ //if (ctmp == 'e') wantSaveToEml = true; TODO if (ctmp == 'f') wantSaveToEmlFile = true; } - + PrintAndLogEx(NORMAL, "-------------------------------------------------------------------------\n"); PrintAndLogEx(NORMAL, "Executing mifare sniffing command. \n"); PrintAndLogEx(NORMAL, "Press the key on the proxmark3 device to abort both proxmark3 and client.\n"); @@ -2202,7 +2202,7 @@ int CmdHF14AMfSniff(const char *Cmd){ SendCommand(&c); UsbCommand resp; - + // wait cycle while (true) { printf("."); fflush(stdout); @@ -2211,11 +2211,11 @@ int CmdHF14AMfSniff(const char *Cmd){ PrintAndLogEx(INFO, "\naborted via keyboard!\n"); break; } - + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { continue; } - + res = resp.arg[0] & 0xff; traceLen = resp.arg[1]; len = resp.arg[2]; @@ -2234,7 +2234,7 @@ int CmdHF14AMfSniff(const char *Cmd){ p = calloc(traceLen, sizeof(uint8_t)); else // need more memory p = realloc(buf, traceLen); - + if (p == NULL) { PrintAndLogEx(FAILED, "Cannot allocate memory for trace"); free(buf); @@ -2268,8 +2268,8 @@ int CmdHF14AMfSniff(const char *Cmd){ isTag = false; } bufPtr += 2; - - // the uid identification package + + // the uid identification package // 0xFF 0xFF xx xx xx xx xx xx xx xx xx xx aa aa cc 0xFF 0xFF // x = uid, a = atqa, c = sak if ((len == 17) && (bufPtr[0] == 0xff) && (bufPtr[1] == 0xff) && (bufPtr[15] == 0xff) && (bufPtr[16] == 0xff)) { @@ -2281,25 +2281,25 @@ int CmdHF14AMfSniff(const char *Cmd){ default: uid_len = 4; break; } sak = bufPtr[14]; - PrintAndLogEx(SUCCESS, "UID %s | ATQA %02x %02x | SAK 0x%02x", + PrintAndLogEx(SUCCESS, "UID %s | ATQA %02x %02x | SAK 0x%02x", sprint_hex(uid, uid_len), - atqa[1], - atqa[0], + atqa[1], + atqa[0], sak); if (wantLogToFile || wantDecrypt) { FillFileNameByUID(logHexFileName, uid, ".log", uid_len); AddLogCurrentDT(logHexFileName); PrintAndLogEx(SUCCESS, "Trace saved to %s", logHexFileName); - } + } if (wantDecrypt) mfTraceInit(uid, uid_len, atqa, sak, wantSaveToEmlFile); } else { PrintAndLogEx(NORMAL, "%03d| %s |%s", num, isTag ? "TAG" : "RDR", sprint_hex(bufPtr, len)); - if (wantLogToFile) + if (wantLogToFile) AddLogHex(logHexFileName, isTag ? "TAG| ":"RDR| ", bufPtr, len); - if (wantDecrypt) + if (wantDecrypt) mfTraceDecode(bufPtr, len, wantSaveToEmlFile); - num++; + num++; } bufPtr += len; bufPtr += ((len-1)/8+1); // ignore parity @@ -2316,7 +2316,7 @@ int CmdHF14AMfDbg(const char *Cmd) { char ctmp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) < 1 || ctmp == 'h' ) return usage_hf14_dbg(); - + uint8_t dbgMode = param_get8ex(Cmd, 0, 0, 10); if (dbgMode > 4) return usage_hf14_dbg(); @@ -2330,50 +2330,50 @@ int CmdHF14AMfKeyBrute(const char *Cmd) { uint8_t blockNo = 0, keytype = 0; uint8_t key[6] = {0, 0, 0, 0, 0, 0}; uint64_t foundkey = 0; - - char cmdp = tolower(param_getchar(Cmd, 0)); + + char cmdp = tolower(param_getchar(Cmd, 0)); if ( cmdp == 'h' ) return usage_hf14_keybrute(); - + // block number - blockNo = param_get8(Cmd, 0); - + blockNo = param_get8(Cmd, 0); + // keytype cmdp = tolower(param_getchar(Cmd, 1)); if ( cmdp == 'b' ) keytype = 1; - + // key if (param_gethex(Cmd, 2, key, 12)) return usage_hf14_keybrute(); - + uint64_t t1 = msclock(); - + if (mfKeyBrute( blockNo, keytype, key, &foundkey)) PrintAndLogEx(SUCCESS, "found valid key: %012" PRIx64 " \n", foundkey); else PrintAndLogEx(FAILED, "key not found"); - + t1 = msclock() - t1; PrintAndLogEx(SUCCESS, "\ntime in keybrute: %.0f seconds\n", (float)t1/1000.0); - return 0; + return 0; } void printKeyTable( uint8_t sectorscnt, sector_t *e_sector ){ char strA[12+1] = {0}; - char strB[12+1] = {0}; + char strB[12+1] = {0}; PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); PrintAndLogEx(NORMAL, "|sec|key A |res|key B |res|"); PrintAndLogEx(NORMAL, "|---|----------------|---|----------------|---|"); for (uint8_t i = 0; i < sectorscnt; ++i) { - + snprintf(strA, sizeof(strA), "------------"); snprintf(strB, sizeof(strB), "------------"); - + if ( e_sector[i].foundKey[0] ) snprintf(strA, sizeof(strA), "%012" PRIx64, e_sector[i].Key[0]); - + if ( e_sector[i].foundKey[1] ) snprintf(strB, sizeof(strB), "%012" PRIx64, e_sector[i].Key[1]); - + PrintAndLogEx(NORMAL, "|%03d| %s | %d | %s | %d |" , i , strA, e_sector[i].foundKey[0] @@ -2388,9 +2388,9 @@ int CmdHF14AMfEGet(const char *Cmd) { uint8_t blockNo = 0; uint8_t data[16] = {0x00}; char c = tolower(param_getchar(Cmd, 0)); - + if (strlen(Cmd) < 1 || c == 'h') return usage_hf14_eget(); - + blockNo = param_get8(Cmd, 0); PrintAndLogEx(NORMAL, ""); @@ -2405,7 +2405,7 @@ int CmdHF14AMfEGet(const char *Cmd) { int CmdHF14AMfEClear(const char *Cmd) { char c = tolower(param_getchar(Cmd, 0)); if (c == 'h') return usage_hf14_eclr(); - + UsbCommand cmd = {CMD_MIFARE_EML_MEMCLR, {0, 0, 0}}; clearCommandBuffer(); SendCommand(&cmd); @@ -2420,14 +2420,14 @@ int CmdHF14AMfESet(const char *Cmd) { if (strlen(Cmd) < 3 || c == 'h') return usage_hf14_eset(); - + blockNo = param_get8(Cmd, 0); - + if (param_gethex(Cmd, 1, memBlock, 32)) { PrintAndLogEx(WARNING, "block data must include 32 HEX symbols"); return 1; } - + // 1 - blocks count return mfEmlSetMem(memBlock, blockNo, 1); } @@ -2440,12 +2440,12 @@ int CmdHF14AMfELoad(const char *Cmd) { uint8_t blockWidth = 16; char c = tolower(param_getchar(Cmd, 0)); - if ( strlen(Cmd) < 2 && c == 'h' ) + if ( strlen(Cmd) < 2 && c == 'h' ) return usage_hf14_eload(); - + switch (c) { case '0' : numBlocks = MIFARE_MINI_MAXBLOCK; break; - case '1' : + case '1' : case '\0': numBlocks = MIFARE_1K_MAXBLOCK; break; case '2' : numBlocks = MIFARE_2K_MAXBLOCK; break; case '4' : numBlocks = MIFARE_4K_MAXBLOCK; break; @@ -2456,11 +2456,11 @@ int CmdHF14AMfELoad(const char *Cmd) { } } uint32_t numblk2 = param_get32ex(Cmd, 2, 0, 10); - if (numblk2 > 0) + if (numblk2 > 0) numBlocks = numblk2; param_getstr(Cmd, nameParamNo, filename, sizeof(filename)); - + uint8_t *data = calloc(4096, sizeof(uint8_t)); size_t datalen = 0; //int res = loadFile(filename, "bin", data, &datalen); @@ -2469,26 +2469,26 @@ int CmdHF14AMfELoad(const char *Cmd) { free(data); return 1; } - + // 64 or 256 blocks. if ( (datalen % blockWidth) != 0 ) { PrintAndLogEx(FAILED, "File content error. Size doesn't match blockwidth "); - free(data); + free(data); return 2; } - + PrintAndLogEx(INFO, "Copying to emulator memory"); - + blockNum = 0; while ( datalen ) { - + if (mfEmlSetMem_xt(data + counter, blockNum, 1, blockWidth)) { PrintAndLogEx(FAILED, "Cant set emul block: %3d", blockNum); free(data); return 3; } printf("."); fflush(stdout); - + blockNum++; counter += blockWidth; datalen -= blockWidth; @@ -2497,7 +2497,7 @@ int CmdHF14AMfELoad(const char *Cmd) { // Ultralight /Ntag if ( blockWidth == 4 ) { - if ((blockNum != numBlocks)) { + if ((blockNum != numBlocks)) { PrintAndLogEx(FAILED, "Warning, Ultralight/Ntag file content, Loaded %d blocks into emulator memory", blockNum); free(data); return 0; @@ -2524,11 +2524,11 @@ int CmdHF14AMfESave(const char *Cmd) { memset(filename, 0, sizeof(filename)); - char c = tolower(param_getchar(Cmd, 0)); + char c = tolower(param_getchar(Cmd, 0)); if (c == 'h') return usage_hf14_esave(); blocks = NumOfBlocks(c); - bytes = blocks * MFBLOCK_SIZE; + bytes = blocks * MFBLOCK_SIZE; dump = calloc(bytes, sizeof(uint8_t)); if (!dump) { @@ -2536,23 +2536,23 @@ int CmdHF14AMfESave(const char *Cmd) { return 1; } memset(dump, 0, bytes); - + PrintAndLogEx(INFO, "downloading from emulator memory"); if (!GetFromDevice( BIG_BUF_EML, dump, bytes, 0, NULL, 2500, false)) { PrintAndLogEx(WARNING, "Fail, transfer from device time-out"); free(dump); return 2; - } + } len = param_getstr(Cmd, nameParamNo, filename, sizeof(filename)); if (len > FILE_PATH_SIZE - 5) len = FILE_PATH_SIZE - 5; - + // user supplied filename? if (len < 1) { fnameptr += sprintf(fnameptr, "hf-mf-"); FillFileNameByUID(fnameptr, dump, "-dump", 4); } - + saveFile(filename, "bin", dump, bytes); saveFileEML(filename, "eml", dump, bytes, MFBLOCK_SIZE); saveFileJSON(filename, "json", jsfCardMemory, dump, bytes); @@ -2564,7 +2564,7 @@ int CmdHF14AMfECFill(const char *Cmd) { uint8_t keyType = 0; uint8_t numSectors = 16; char c = tolower(param_getchar(Cmd, 0)); - + if (strlen(Cmd) < 1 || c == 'h') return usage_hf14_ecfill(); @@ -2596,7 +2596,7 @@ int CmdHF14AMfEKeyPrn(const char *Cmd) { return usage_hf14_ekeyprn(); numSectors = NumOfSectors(c); - + PrintAndLogEx(NORMAL, "|---|----------------|----------------|"); PrintAndLogEx(NORMAL, "|sec|key A |key B |"); PrintAndLogEx(NORMAL, "|---|----------------|----------------|"); @@ -2613,7 +2613,7 @@ int CmdHF14AMfEKeyPrn(const char *Cmd) { return 0; } -// CHINESE MAGIC COMMANDS +// CHINESE MAGIC COMMANDS int CmdHF14AMfCSetUID(const char *Cmd) { uint8_t wipeCard = 0; uint8_t uid[8] = {0x00}; @@ -2624,7 +2624,7 @@ int CmdHF14AMfCSetUID(const char *Cmd) { int res, argi = 0; char ctmp; - if (strlen(Cmd) < 1 || param_getchar(Cmd, argi) == 'h') + if (strlen(Cmd) < 1 || param_getchar(Cmd, argi) == 'h') return usage_hf14_csetuid(); if (param_getchar(Cmd, argi) && param_gethex(Cmd, argi, uid, 8)) @@ -2668,7 +2668,7 @@ int CmdHF14AMfCSetUID(const char *Cmd) { PrintAndLogEx(WARNING, "Can't set UID. error=%d", res); return 1; } - + PrintAndLogEx(SUCCESS, "old UID:%s", sprint_hex(oldUid, 4)); PrintAndLogEx(SUCCESS, "new UID:%s", sprint_hex(uid, 4)); return 0; @@ -2686,11 +2686,11 @@ int CmdHF14AMfCSetBlk(const char *Cmd) { blockNo = param_get8(Cmd, 0); if (param_gethex(Cmd, 1, block, 32)) return usage_hf14_csetblk(); - + ctmp = tolower(param_getchar(Cmd, 2)); if (ctmp == 'w') params |= MAGIC_WIPE; - + PrintAndLogEx(NORMAL, "--block number:%2d data:%s", blockNo, sprint_hex(block, 16)); res = mfCSetBlock(blockNo, block, NULL, params); @@ -2709,7 +2709,7 @@ int CmdHF14AMfCLoad(const char *Cmd) { bool fillFromJson = false; bool fillFromBin = false; char fileName[50] = {0}; - + char ctmp = tolower(param_getchar(Cmd, 0)); if ( param_getlength(Cmd, 0) == 1 ) { if (ctmp == 'h' || ctmp == 0x00) return usage_hf14_cload(); @@ -2721,7 +2721,7 @@ int CmdHF14AMfCLoad(const char *Cmd) { if (fillFromJson || fillFromBin) param_getstr(Cmd, 1, fileName, sizeof(fileName)); - + if (fillFromEmulator) { for (blockNum = 0; blockNum < 16 * 4; blockNum += 1) { if (mfEmlGetMem(buf8, blockNum, 1)) { @@ -2755,15 +2755,15 @@ int CmdHF14AMfCLoad(const char *Cmd) { res = loadFileEML( Cmd, "eml", data, &datalen); } } - + if ( res ) { if ( data ) free(data); return 1; } - + // PrintAndLogEx(INFO, "DATA | %s", sprint_hex(data+1000, 24) ); - + // 64 or 256blocks. if (datalen != 1024 && datalen != 4096) { @@ -2771,18 +2771,18 @@ int CmdHF14AMfCLoad(const char *Cmd) { free(data); return 2; } - + PrintAndLogEx(INFO, "Copying to magic card"); - + blockNum = 0; while ( datalen ) { - // switch on field and send magic sequence + // switch on field and send magic sequence if (blockNum == 0) flags = MAGIC_INIT + MAGIC_WUPC; - // write + // write if (blockNum == 1) flags = 0; - + // Switch off field. if (blockNum == 16 * 4 - 1) flags = MAGIC_HALT + MAGIC_OFF; @@ -2791,14 +2791,14 @@ int CmdHF14AMfCLoad(const char *Cmd) { free(data); return 3; } - + datalen -= 16; - + printf("."); fflush(stdout); blockNum++; - + // magic card type - mifare 1K - if (blockNum >= MIFARE_1K_MAXBLOCK ) break; + if (blockNum >= MIFARE_1K_MAXBLOCK ) break; } PrintAndLogEx(NORMAL, "\n"); @@ -2808,8 +2808,8 @@ int CmdHF14AMfCLoad(const char *Cmd) { free(data); return 4; } - - PrintAndLogEx(SUCCESS, "Card loaded %d blocks from file", blockNum); + + PrintAndLogEx(SUCCESS, "Card loaded %d blocks from file", blockNum); free(data); return 0; } @@ -2832,9 +2832,9 @@ int CmdHF14AMfCGetBlk(const char *Cmd) { PrintAndLogEx(WARNING, "Can't read block. error=%d", res); return 1; } - + PrintAndLogEx(NORMAL, "data: %s", sprint_hex(data, sizeof(data))); - + if (mfIsSectorTrailer(blockNo)) { PrintAndLogEx(NORMAL, "Trailer decoded:"); PrintAndLogEx(NORMAL, "Key A: %s", sprint_hex_inrow(data, 6)); @@ -2847,7 +2847,7 @@ int CmdHF14AMfCGetBlk(const char *Cmd) { } PrintAndLogEx(NORMAL, "UserData: %s", sprint_hex_inrow(&data[9], 1)); } - + return 0; } @@ -2873,9 +2873,9 @@ int CmdHF14AMfCGetSc(const char *Cmd) { blocks = 16; start = 128 + ( sector - 32 ) * 16; } - + flags = MAGIC_INIT + MAGIC_WUPC; - + for (i = 0; i < blocks; i++) { if (i == 1) flags = 0; if (i == blocks-1) flags = MAGIC_HALT + MAGIC_OFF; @@ -2894,7 +2894,7 @@ int CmdHF14AMfCSave(const char *Cmd) { char filename[FILE_PATH_SIZE]; char * fnameptr = filename; - uint8_t *dump; + uint8_t *dump; bool fillEmulator = false; bool errors = false, hasname = false, useuid = false; int i, len, flags; @@ -2904,7 +2904,7 @@ int CmdHF14AMfCSave(const char *Cmd) { while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { ctmp = tolower(param_getchar(Cmd, cmdp)); - switch (ctmp) { + switch (ctmp) { case 'e': useuid = true; fillEmulator = true; @@ -2924,7 +2924,7 @@ int CmdHF14AMfCSave(const char *Cmd) { case 'u': useuid = true; hasname = true; - cmdp++; + cmdp++; break; case 'o': len = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); @@ -2934,9 +2934,9 @@ int CmdHF14AMfCSave(const char *Cmd) { } useuid = false; - hasname = true; + hasname = true; cmdp += 2; - break; + break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -2945,7 +2945,7 @@ int CmdHF14AMfCSave(const char *Cmd) { } if (!hasname && !fillEmulator) errors = true; - + if (errors || cmdp == 0) return usage_hf14_csave(); dump = calloc(bytes, sizeof(uint8_t)); @@ -2954,27 +2954,27 @@ int CmdHF14AMfCSave(const char *Cmd) { return 1; } memset(dump, 0, bytes); - + flags = MAGIC_INIT + MAGIC_WUPC; for (i = 0; i < numblocks; i++) { if (i == 1) flags = 0; if (i == numblocks - 1) flags = MAGIC_HALT + MAGIC_OFF; - + if (mfCGetBlock(i, dump + (i*MFBLOCK_SIZE), flags)) { PrintAndLogEx(WARNING, "Cant get block: %d", i); free(dump); return 2; } } - + if ( useuid ){ - fnameptr += sprintf(fnameptr, "hf-mf-"); + fnameptr += sprintf(fnameptr, "hf-mf-"); FillFileNameByUID(fnameptr, dump, "-dump", 4); } - + if (fillEmulator) { PrintAndLogEx(INFO, "uploading to emulator memory"); - for (i = 0; i < numblocks; i += 5) { + for (i = 0; i < numblocks; i += 5) { if (mfEmlSetMem(dump + (i*MFBLOCK_SIZE), i, 5)) { PrintAndLogEx(WARNING, "Cant set emul block: %d", i); } @@ -2993,10 +2993,10 @@ int CmdHF14AMfCSave(const char *Cmd) { //needs nt, ar, at, Data to decrypt int CmdHf14AMfDecryptBytes(const char *Cmd){ - + char ctmp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) < 1 || ctmp == 'h') return usage_hf14_decryptbytes(); - + uint32_t nt = param_get32ex(Cmd,0,0,16); uint32_t ar_enc = param_get32ex(Cmd,1,0,16); uint32_t at_enc = param_get32ex(Cmd,2,0,16); @@ -3010,7 +3010,7 @@ int CmdHf14AMfDecryptBytes(const char *Cmd){ PrintAndLogEx(NORMAL, "nt\t%08X", nt); PrintAndLogEx(NORMAL, "ar enc\t%08X", ar_enc); PrintAndLogEx(NORMAL, "at enc\t%08X", at_enc); - + uint8_t *data = calloc(len, sizeof(uint8_t)); param_gethex_ex(Cmd, 3, data, &len); len >>= 1; @@ -3065,7 +3065,7 @@ int CmdHf14AMfNack(const char *Cmd) { if ( verbose ) PrintAndLogEx(INFO, "Started testing card for NACK bug. Press key to abort"); - + detect_classic_nackbug(verbose); return 0; } @@ -3114,14 +3114,14 @@ int CmdHF14AMfice(const char *Cmd) { if(filename[0]=='\0') { fptr = GenerateFilename("hf-mf-","-nonces.bin"); - if (fptr == NULL) + if (fptr == NULL) return 1; strcpy(filename, fptr); } PrintAndLogEx(NORMAL, "Collecting %u nonces \n", limit); - - if ((fnonces = fopen(filename,"wb")) == NULL) { + + if ((fnonces = fopen(filename,"wb")) == NULL) { PrintAndLogEx(WARNING, "Could not create file " _YELLOW_(%s),filename); return 3; } @@ -3129,21 +3129,21 @@ int CmdHF14AMfice(const char *Cmd) { clearCommandBuffer(); uint64_t t1 = msclock(); - + do { if (ukbhit()) { int gc = getchar(); (void)gc; PrintAndLogEx(INFO, "\naborted via keyboard!\n"); break; } - + flags = 0; flags |= initialize ? 0x0001 : 0; flags |= slow ? 0x0002 : 0; UsbCommand c = {CMD_MIFARE_ACQUIRE_NONCES, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, flags}}; clearCommandBuffer(); - SendCommand(&c); - + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) goto out; if (resp.arg[0]) goto out; @@ -3152,22 +3152,22 @@ int CmdHF14AMfice(const char *Cmd) { fwrite(resp.d.asBytes, 1, items*4, fnonces); fflush(fnonces); } - + total_num_nonces += items; if ( total_num_nonces > part_limit ) { PrintAndLogEx(INFO, "Total nonces %u\n", total_num_nonces); part_limit += 3000; } - - acquisition_completed = ( total_num_nonces > limit); + + acquisition_completed = ( total_num_nonces > limit); initialize = false; - + } while (!acquisition_completed); out: PrintAndLogEx(SUCCESS, "time: %" PRIu64 " seconds\n", (msclock()-t1)/1000); - + if ( fnonces ) { fflush(fnonces); fclose(fnonces); @@ -3185,8 +3185,8 @@ int CmdHF14AMfAuth4(const char *Cmd) { uint8_t key[16] = {0}; int keylen = 0; - CLIParserInit("hf mf auth4", - "Executes AES authentication command in ISO14443-4", + CLIParserInit("hf mf auth4", + "Executes AES authentication command in ISO14443-4", "Usage:\n\thf mf auth4 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n" "\thf mf auth4 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -> executes authentication\n"); @@ -3197,16 +3197,16 @@ int CmdHF14AMfAuth4(const char *Cmd) { arg_param_end }; CLIExecWithReturn(Cmd, argtable, true); - + CLIGetHexWithReturn(1, keyn, &keynlen); CLIGetHexWithReturn(2, key, &keylen); CLIParserFree(); - + if (keynlen != 2) { PrintAndLogEx(ERR, " must be 2 bytes long instead of: %d", keynlen); return 1; } - + if (keylen != 16) { PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); return 1; @@ -3218,8 +3218,8 @@ int CmdHF14AMfAuth4(const char *Cmd) { // https://www.nxp.com/docs/en/application-note/AN10787.pdf int CmdHF14AMfMAD(const char *cmd) { - CLIParserInit("hf mf mad", - "Checks and prints Mifare Application Directory (MAD)", + CLIParserInit("hf mf mad", + "Checks and prints Mifare Application Directory (MAD)", "Usage:\n\thf mf mad -> shows MAD if exists\n" "\thf mf mad -a 03e1 -k ffffffffffff -b -> shows NDEF data if exists. read card with custom key and key B\n"); @@ -3240,7 +3240,7 @@ int CmdHF14AMfMAD(const char *cmd) { int keylen; CLIGetHexWithReturn(3, key, &keylen); bool keyB = arg_get_lit(4); - + CLIParserFree(); if (aidlen != 2 && keylen > 0) { @@ -3253,15 +3253,15 @@ int CmdHF14AMfMAD(const char *cmd) { PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); return 2; } - + if (verbose) { for(int i = 0; i < 4; i ++) - PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(§or0[i * 16], 16)); + PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(§or0[i * 16], 16)); } bool haveMAD2 = false; MAD1DecodeAndPrint(sector0, verbose, &haveMAD2); - + if (haveMAD2) { if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10)) { PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); @@ -3274,7 +3274,7 @@ int CmdHF14AMfMAD(const char *cmd) { if (aidlen == 2) { uint16_t aaid = (aid[0] << 8) + aid[1]; PrintAndLogEx(NORMAL, "\n-------------- AID 0x%04x ---------------", aaid); - + uint16_t mad[7 + 8 + 8 + 8 + 8] = {0}; size_t madlen = 0; if (MADDecode(sector0, sector10, mad, &madlen)) { @@ -3287,7 +3287,7 @@ int CmdHF14AMfMAD(const char *cmd) { if (keylen == 6) { memcpy(akey, key, 6); } - + for (int i = 0; i < madlen; i++) { if (aaid == mad[i]) { uint8_t vsector[16 * 4] = {0}; @@ -3296,20 +3296,20 @@ int CmdHF14AMfMAD(const char *cmd) { PrintAndLogEx(ERR, "read sector %d error.", i + 1); return 2; } - + for(int j = 0; j < (verbose ? 4 : 3); j ++) - PrintAndLogEx(NORMAL, " [%03d] %s", (i + 1) * 4 + j, sprint_hex(&vsector[j * 16], 16)); + PrintAndLogEx(NORMAL, " [%03d] %s", (i + 1) * 4 + j, sprint_hex(&vsector[j * 16], 16)); } - } + } } - + return 0; } int CmdHFMFNDEF(const char *cmd) { - CLIParserInit("hf mf ndef", - "Prints NFC Data Exchange Format (NDEF)", + CLIParserInit("hf mf ndef", + "Prints NFC Data Exchange Format (NDEF)", "Usage:\n\thf mf ndef -> shows NDEF data\n" "\thf mf ndef -a 03e1 -k ffffffffffff -b -> shows NDEF data with custom AID, key and with key B\n"); @@ -3322,7 +3322,7 @@ int CmdHFMFNDEF(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool verbose = arg_get_lit(1); bool verbose2 = arg_get_lit(1) > 1; uint8_t aid[2] = {0}; @@ -3332,38 +3332,38 @@ int CmdHFMFNDEF(const char *cmd) { int keylen; CLIGetHexWithReturn(3, key, &keylen); bool keyB = arg_get_lit(4); - + CLIParserFree(); uint16_t ndefAID = 0x03e1; if (aidlen == 2) ndefAID = (aid[0] << 8) + aid[1]; - + uint8_t ndefkey[6] = {0}; memcpy(ndefkey, g_mifare_ndef_key, 6); if (keylen == 6) { memcpy(ndefkey, key, 6); } - + uint8_t sector0[16 * 4] = {0}; uint8_t sector10[16 * 4] = {0}; uint8_t data[4096] = {0}; int datalen = 0; PrintAndLogEx(NORMAL, ""); - + if (mfReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector0)) { PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); return 2; } - + bool haveMAD2 = false; int res = MADCheck(sector0, NULL, verbose, &haveMAD2); if (res) { PrintAndLogEx(ERR, "MAD error %d.", res); return res; } - + if (haveMAD2) { if (mfReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifare_mad_key, sector10)) { PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); @@ -3386,25 +3386,25 @@ int CmdHFMFNDEF(const char *cmd) { PrintAndLogEx(ERR, "read sector %d error.", i + 1); return 2; } - + memcpy(&data[datalen], vsector, 16 * 3); datalen += 16 * 3; - + printf("."); } } printf(" OK\n"); - + if (!datalen) { PrintAndLogEx(ERR, "no NDEF data."); return 11; } - + if (verbose2) { PrintAndLogEx(NORMAL, "NDEF data:"); dump_buffer(data, datalen, stdout, 1); } - + NDEFDecodeAndPrint(data, datalen, verbose); return 0; @@ -3417,11 +3417,11 @@ int CmdHF14AMfList(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"list", CmdHF14AMfList, 0, "[Deprecated] List ISO 14443-a / Mifare history"}, + {"list", CmdHF14AMfList, 0, "[Deprecated] List ISO 14443-a / Mifare history"}, {"darkside", CmdHF14AMfDarkside, 0, "Darkside attack. read parity error messages."}, {"nested", CmdHF14AMfNested, 0, "Nested attack. Test nested authentication"}, {"hardnested", CmdHF14AMfNestedHard, 0, "Nested attack for hardened Mifare cards"}, - {"keybrute", CmdHF14AMfKeyBrute, 0, "J_Run's 2nd phase of multiple sector nested authentication key recovery"}, + {"keybrute", CmdHF14AMfKeyBrute, 0, "J_Run's 2nd phase of multiple sector nested authentication key recovery"}, {"nack", CmdHf14AMfNack, 0, "Test for Mifare NACK bug"}, {"chk", CmdHF14AMfChk, 0, "Check keys"}, {"fchk", CmdHF14AMfChk_fast, 0, "Check keys fast, targets all keys on card"}, @@ -3433,7 +3433,7 @@ static command_t CommandTable[] = { {"dump", CmdHF14AMfDump, 0, "Dump MIFARE classic tag to binary file"}, {"restore", CmdHF14AMfRestore, 0, "Restore MIFARE classic binary file to BLANK tag"}, {"wrbl", CmdHF14AMfWrBl, 0, "Write MIFARE classic block"}, - {"setmod", CmdHf14AMfSetMod, 0, "Set MIFARE Classic EV1 load modulation strength"}, + {"setmod", CmdHf14AMfSetMod, 0, "Set MIFARE Classic EV1 load modulation strength"}, {"auth4", CmdHF14AMfAuth4, 0, "ISO14443-4 AES authentication"}, // {"sniff", CmdHF14AMfSniff, 0, "Sniff card-reader communication"}, {"-----------", CmdHelp, 1, ""}, diff --git a/client/cmdhfmfdes.c b/client/cmdhfmfdes.c index 0bf5b2443..9ddd23b5f 100644 --- a/client/cmdhfmfdes.c +++ b/client/cmdhfmfdes.c @@ -41,14 +41,14 @@ int CmdHF14ADesWb(const char *Cmd) uint8_t keyType = 0; uint8_t key[6] = {0, 0, 0, 0, 0, 0}; uint8_t bldata[16] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; - + char cmdp = 0x00; if (strlen(Cmd)<3) { PrintAndLogEx(NORMAL, "Usage: hf mf wrbl "); PrintAndLogEx(NORMAL, " sample: hf mf wrbl 0 A FFFFFFFFFFFF 000102030405060708090A0B0C0D0E0F"); return 0; - } + } blockNo = param_get8(Cmd, 0); cmdp = param_getchar(Cmd, 1); @@ -67,7 +67,7 @@ int CmdHF14ADesWb(const char *Cmd) } PrintAndLogEx(NORMAL, "--block no:%02x key type:%02x key:%s", blockNo, keyType, sprint_hex(key, 6)); PrintAndLogEx(NORMAL, "--data: %s", sprint_hex(bldata, 16)); - + UsbCommand c = {CMD_MIFARE_WRITEBL, {blockNo, keyType, 0}}; memcpy(c.d.asBytes, key, 6); memcpy(c.d.asBytes + 10, bldata, 16); @@ -89,7 +89,7 @@ int CmdHF14ADesRb(const char *Cmd) // uint8_t blockNo = 0; // uint8_t keyType = 0; // uint8_t key[6] = {0, 0, 0, 0, 0, 0}; - + // char cmdp = 0x00; @@ -97,8 +97,8 @@ int CmdHF14ADesRb(const char *Cmd) // PrintAndLogEx(NORMAL, "Usage: hf mf rdbl "); // PrintAndLogEx(NORMAL, " sample: hf mf rdbl 0 A FFFFFFFFFFFF "); // return 0; - // } - + // } + // blockNo = param_get8(Cmd, 0); // cmdp = param_getchar(Cmd, 1); // if (cmdp == 0x00) { @@ -111,7 +111,7 @@ int CmdHF14ADesRb(const char *Cmd) // return 1; // } // PrintAndLogEx(NORMAL, "--block no:%02x key type:%02x key:%s ", blockNo, keyType, sprint_hex(key, 6)); - + // UsbCommand c = {CMD_MIFARE_READBL, {blockNo, keyType, 0}}; // memcpy(c.d.asBytes, key, 6); // SendCommand(&c); @@ -137,7 +137,7 @@ int CmdHF14ADesInfo(const char *Cmd){ UsbCommand c = {CMD_MIFARE_DESFIRE_INFO}; SendCommand(&c); UsbCommand resp; - + if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { PrintAndLogEx(WARNING, "Command execute timeout"); return 0; @@ -145,16 +145,16 @@ int CmdHF14ADesInfo(const char *Cmd){ uint8_t isOK = resp.arg[0] & 0xff; if ( !isOK ){ switch ( resp.arg[1] ) { - case 1: + case 1: PrintAndLogEx(WARNING, "Can't select card"); break; case 2: PrintAndLogEx(WARNING, "Card is most likely not Desfire. Its UID has wrong size"); break; - case 3: + case 3: default: PrintAndLogEx(WARNING, "Command unsuccessful"); break; } return 0; - } + } PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "-- Desfire Information --------------------------------------"); PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); @@ -178,21 +178,21 @@ int CmdHF14ADesInfo(const char *Cmd){ PrintAndLogEx(NORMAL, " storage size : %s", GetCardSizeStr(resp.d.asBytes[19])); PrintAndLogEx(NORMAL, " Protocol : %s", GetProtocolStr(resp.d.asBytes[20])); PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - + // Master Key settings GetKeySettings(NULL); - + // Free memory on card c.cmd = CMD_MIFARE_DESFIRE; c.arg[0] = (INIT | DISCONNECT); c.arg[1] = 0x01; c.d.asBytes[0] = GET_FREE_MEMORY; SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) + if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500)) return 0; - + uint8_t tmp[3]; - memcpy(tmp, resp.d.asBytes+3,3); + memcpy(tmp, resp.d.asBytes+3,3); PrintAndLogEx(NORMAL, " Available free memory on card : %d bytes", le24toh( tmp )); PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); @@ -203,37 +203,37 @@ int CmdHF14ADesInfo(const char *Cmd){ Application keys (APK) 0x01-0x0D Application free 0x0E Application never 0x0F - + ACCESS RIGHTS: keys 0,1,2,3 C keys 4,5,6,7 RW keys 8,9,10,11 W keys 12,13,14,15 R - + */ - + return 1; } /* - The 7 MSBits (= n) code the storage size itself based on 2^n, + The 7 MSBits (= n) code the storage size itself based on 2^n, the LSBit is set to '0' if the size is exactly 2^n - and set to '1' if the storage size is between 2^n and 2^(n+1). + and set to '1' if the storage size is between 2^n and 2^(n+1). For this version of DESFire the 7 MSBits are set to 0x0C (2^12 = 4096) and the LSBit is '0'. */ char * GetCardSizeStr( uint8_t fsize ){ - + static char buf[30] = {0x00}; char *retStr = buf; uint16_t usize = 1 << ((fsize >>1) + 1); uint16_t lsize = 1 << (fsize >>1); - + // is LSB set? if ( fsize & 1 ) sprintf(retStr, "0x%02X (%d - %d bytes)",fsize, usize, lsize); - else - sprintf(retStr, "0x%02X (%d bytes)", fsize, lsize); + else + sprintf(retStr, "0x%02X (%d bytes)", fsize, lsize); return buf; } @@ -245,7 +245,7 @@ char * GetProtocolStr(uint8_t id){ if ( id == 0x05) sprintf(retStr,"0x%02X (ISO 14443-3, 14443-4)", id); else - sprintf(retStr,"0x%02X (Unknown)", id); + sprintf(retStr,"0x%02X (Unknown)", id); return buf; } @@ -255,7 +255,7 @@ char * GetVersionStr(uint8_t major, uint8_t minor){ char *retStr = buf; if ( major == 0x00) - sprintf(retStr,"%d.%d (Desfire MF3ICD40)", major, minor); + sprintf(retStr,"%d.%d (Desfire MF3ICD40)", major, minor); else if ( major == 0x01 && minor == 0x00) sprintf(retStr,"%d.%d (Desfire EV1)", major, minor); else if ( major == 0x12 && minor == 0x00) @@ -266,7 +266,7 @@ char * GetVersionStr(uint8_t major, uint8_t minor){ } void GetKeySettings( uint8_t *aid){ - + char messStr[512] = {0x00}; char *str = messStr; uint8_t isOK = 0; @@ -275,7 +275,7 @@ void GetKeySettings( uint8_t *aid){ UsbCommand resp; //memset(messStr, 0x00, 512); - + if ( aid == NULL ){ PrintAndLogEx(NORMAL, " CMK - PICC, Card Master Key settings "); PrintAndLogEx(NORMAL, ""); @@ -283,14 +283,14 @@ void GetKeySettings( uint8_t *aid){ c.arg[LENPOS] = 0x01; c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45 SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;} + if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;} isOK = resp.arg[0] & 0xff; if ( !isOK ){ - PrintAndLogEx(WARNING, " Can't select master application"); + PrintAndLogEx(WARNING, " Can't select master application"); return; - } + } - str = (resp.d.asBytes[3] & (1 << 3 )) ? "YES":"NO"; + str = (resp.d.asBytes[3] & (1 << 3 )) ? "YES":"NO"; PrintAndLogEx(NORMAL, " [0x08] Configuration changeable : %s", str); str = (resp.d.asBytes[3] & (1 << 2 )) ? "NO":"YES"; PrintAndLogEx(NORMAL, " [0x04] CMK required for create/delete : %s",str); @@ -298,7 +298,7 @@ void GetKeySettings( uint8_t *aid){ PrintAndLogEx(NORMAL, " [0x02] Directory list access with CMK : %s",str); str = (resp.d.asBytes[3] & (1 << 0 )) ? "YES" : "NO"; PrintAndLogEx(NORMAL, " [0x01] CMK is changeable : %s", str); - + c.arg[LENPOS] = 0x02; //LEN c.d.asBytes[0] = GET_KEY_VERSION; //0x64 c.d.asBytes[1] = 0x00; @@ -313,7 +313,7 @@ void GetKeySettings( uint8_t *aid){ PrintAndLogEx(NORMAL, " Max number of keys : %d", resp.d.asBytes[4]); PrintAndLogEx(NORMAL, " Master key Version : %d (0x%02x)", resp.d.asBytes[3], resp.d.asBytes[3]); PrintAndLogEx(NORMAL, " ----------------------------------------------------------"); - + c.arg[LENPOS] = 0x02; //LEN c.d.asBytes[0] = AUTHENTICATE; //0x0A c.d.asBytes[1] = 0x00; // KEY 0 @@ -327,7 +327,7 @@ void GetKeySettings( uint8_t *aid){ if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;} isOK = resp.d.asBytes[2] & 0xff; PrintAndLogEx(NORMAL, " [0x1A] Authenticate ISO : %s", ( isOK==0xAE ) ? "NO":"YES"); - + c.d.asBytes[0] = AUTHENTICATE_AES; //0xAA SendCommand(&c); if ( !WaitForResponseTimeout(CMD_ACK,&resp,1000) ) {return;} @@ -335,32 +335,32 @@ void GetKeySettings( uint8_t *aid){ PrintAndLogEx(NORMAL, " [0xAA] Authenticate AES : %s", ( isOK==0xAE ) ? "NO":"YES"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " ----------------------------------------------------------"); - + } else { PrintAndLogEx(NORMAL, " AMK - Application Master Key settings"); - + // SELECT AID c.arg[0] = (INIT | CLEARTRACE); c.arg[LENPOS] = 0x04; c.d.asBytes[0] = SELECT_APPLICATION; // 0x5a memcpy(c.d.asBytes+1, aid, 3); SendCommand(&c); - + if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { PrintAndLogEx(WARNING, " Timed-out"); return; - } + } isOK = resp.arg[0] & 0xff; if ( !isOK ){ - PrintAndLogEx(WARNING, " Can't select AID: %s",sprint_hex(aid,3)); + PrintAndLogEx(WARNING, " Can't select AID: %s",sprint_hex(aid,3)); return; - } - + } + // KEY SETTINGS options = NONE; c.arg[0] = options; c.arg[LENPOS] = 0x01; - c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45 + c.d.asBytes[0] = GET_KEY_SETTINGS; // 0x45 SendCommand(&c); if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { return; @@ -387,9 +387,9 @@ void GetKeySettings( uint8_t *aid){ } PrintAndLogEx(NORMAL, "Changekey Access rights"); PrintAndLogEx(NORMAL, "-- %s",str); - PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, ""); // same as CMK - str = (resp.d.asBytes[3] & (1 << 3 )) ? "YES":"NO"; + str = (resp.d.asBytes[3] & (1 << 3 )) ? "YES":"NO"; PrintAndLogEx(NORMAL, " 0x08 Configuration changeable : %s", str); str = (resp.d.asBytes[3] & (1 << 2 )) ? "NO":"YES"; PrintAndLogEx(NORMAL, " 0x04 AMK required for create/delete : %s",str); @@ -398,8 +398,8 @@ void GetKeySettings( uint8_t *aid){ str = (resp.d.asBytes[3] & (1 << 0 )) ? "YES" : "NO"; PrintAndLogEx(NORMAL, " 0x01 AMK is changeable : %s", str); } - - // KEY VERSION - AMK + + // KEY VERSION - AMK c.arg[0] = NONE; c.arg[LENPOS] = 0x02; c.d.asBytes[0] = GET_KEY_VERSION; //0x64 @@ -409,9 +409,9 @@ void GetKeySettings( uint8_t *aid){ PrintAndLogEx(WARNING, " Timed-out"); return; } - + int numOfKeys; - + isOK = resp.arg[0] & 0xff; if ( !isOK ){ PrintAndLogEx(WARNING, " Can't read Application Master key version. Trying all keys"); @@ -422,83 +422,83 @@ void GetKeySettings( uint8_t *aid){ PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " Max number of keys : %d", numOfKeys ); PrintAndLogEx(NORMAL, " Application Master key Version : %d (0x%02x)", resp.d.asBytes[3], resp.d.asBytes[3]); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); } - - // LOOP over numOfKeys that we got before. + + // LOOP over numOfKeys that we got before. // From 0x01 to numOfKeys. We already got 0x00. (AMK) for(int i=0x01; i<=0x0f; ++i){ - + } - - + + } } int CmdHF14ADesEnumApplications(const char *Cmd){ - + uint8_t isOK = 0x00; uint8_t aid[3]; uint32_t options = (INIT | DISCONNECT); - + UsbCommand c = {CMD_MIFARE_DESFIRE, {options , 0x01 }}; c.d.asBytes[0] = GET_APPLICATION_IDS; //0x6a - + SendCommand(&c); UsbCommand resp; - + if ( !WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { return 0; - } + } isOK = resp.arg[0] & 0xff; if ( !isOK ){ PrintAndLogEx(NORMAL, "Command unsuccessful"); return 0; - } - PrintAndLogEx(NORMAL, ""); + } + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "-- Desfire Enumerate Applications ---------------------------"); PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); UsbCommand respAid; UsbCommand respFiles; - + uint8_t num = 0; int max = resp.arg[1] -3 -2; - + for(int i=3; i<=max; i+=3){ PrintAndLogEx(NORMAL, " Aid %d : %02X %02X %02X ",num ,resp.d.asBytes[i],resp.d.asBytes[i+1],resp.d.asBytes[i+2]); num++; - + aid[0] = resp.d.asBytes[i]; aid[1] = resp.d.asBytes[i+1]; aid[2] = resp.d.asBytes[i+2]; GetKeySettings(aid); - + // Select Application c.arg[CMDPOS] = INIT; - c.arg[LENPOS] = 0x04; + c.arg[LENPOS] = 0x04; c.d.asBytes[0] = SELECT_APPLICATION; // 0x5a c.d.asBytes[1] = resp.d.asBytes[i]; - c.d.asBytes[2] = resp.d.asBytes[i+1]; + c.d.asBytes[2] = resp.d.asBytes[i+1]; c.d.asBytes[3] = resp.d.asBytes[i+2]; SendCommand(&c); - + if (!WaitForResponseTimeout(CMD_ACK,&respAid,1500) ) { PrintAndLogEx(WARNING, " Timed-out"); continue; - } + } isOK = respAid.d.asBytes[2] & 0xff; if ( isOK != 0x00 ){ - PrintAndLogEx(WARNING, " Can't select AID: %s",sprint_hex(resp.d.asBytes+i,3)); + PrintAndLogEx(WARNING, " Can't select AID: %s",sprint_hex(resp.d.asBytes+i,3)); continue; } - + // Get File IDs c.arg[CMDPOS] = NONE; c.arg[LENPOS] = 0x01; c.d.asBytes[0] = GET_FILE_IDS; // 0x6f SendCommand(&c); - + if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) { PrintAndLogEx(WARNING, " Timed-out"); continue; @@ -506,20 +506,20 @@ int CmdHF14ADesEnumApplications(const char *Cmd){ isOK = respFiles.d.asBytes[2] & 0xff; if ( !isOK ){ PrintAndLogEx(WARNING, " Can't get file ids "); - } else { - int respfileLen = resp.arg[1]-3-2; + } else { + int respfileLen = resp.arg[1]-3-2; for (int j=0; j< respfileLen; ++j){ PrintAndLogEx(NORMAL, " Fileid %d :", resp.d.asBytes[j+3]); } } } - + // Get ISO File IDs c.arg[CMDPOS] = DISCONNECT; c.arg[LENPOS] = 0x01; c.d.asBytes[0] = GET_ISOFILE_IDS; // 0x61 SendCommand(&c); - + if ( !WaitForResponseTimeout(CMD_ACK,&respFiles,1500) ) { PrintAndLogEx(WARNING, " Timed-out"); continue; @@ -527,27 +527,27 @@ int CmdHF14ADesEnumApplications(const char *Cmd){ isOK = respFiles.d.asBytes[2] & 0xff; if ( !isOK ){ PrintAndLogEx(WARNING, " Can't get ISO file ids "); - } else { - int respfileLen = resp.arg[1]-3-2; + } else { + int respfileLen = resp.arg[1]-3-2; for (int j=0; j< respfileLen; ++j){ PrintAndLogEx(NORMAL, " ISO Fileid %d :", resp.d.asBytes[j+3]); } } } - - + + } PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - - + + return 1; } // MIAFRE DesFire Authentication // -#define BUFSIZE 256 +#define BUFSIZE 256 int CmdHF14ADesAuth(const char *Cmd){ - + // NR DESC KEYLENGHT // ------------------------ // 1 = DES 8 @@ -556,8 +556,8 @@ int CmdHF14ADesAuth(const char *Cmd){ // 4 = AES 16 uint8_t keylength = 8; - unsigned char key[24]; - + unsigned char key[24]; + if (strlen(Cmd)<3) { PrintAndLogEx(NORMAL, "Usage: hf mfdes auth <1|2|3> <1|2|3|4> "); PrintAndLogEx(NORMAL, " Auth modes"); @@ -569,14 +569,14 @@ int CmdHF14ADesAuth(const char *Cmd){ PrintAndLogEx(NORMAL, " hf mfdes auth 1 1 0 11223344"); PrintAndLogEx(NORMAL, " hf mfdes auth 3 4 0 404142434445464748494a4b4c4d4e4f"); return 0; - } + } uint8_t cmdAuthMode = param_get8(Cmd,0); uint8_t cmdAuthAlgo = param_get8(Cmd,1); uint8_t cmdKeyNo = param_get8(Cmd,2); - + switch (cmdAuthMode) { - case 1: + case 1: if ( cmdAuthAlgo != 1 && cmdAuthAlgo != 2) { PrintAndLogEx(NORMAL, "Crypto algo not valid for the auth mode"); return 1; @@ -599,13 +599,13 @@ int CmdHF14ADesAuth(const char *Cmd){ return 1; break; } - + switch (cmdAuthAlgo){ - case 2: + case 2: keylength = 16; PrintAndLogEx(NORMAL, "3DES selected"); break; - case 3: + case 3: keylength = 24; PrintAndLogEx(NORMAL, "3 key 3DES selected"); break; @@ -625,24 +625,24 @@ int CmdHF14ADesAuth(const char *Cmd){ PrintAndLogEx(WARNING, "Key must include %d HEX symbols", keylength); return 1; } - // algo, nyckell�ngd, + // algo, nyckell�ngd, UsbCommand c = {CMD_MIFARE_DESFIRE_AUTH1, { cmdAuthMode, cmdAuthAlgo, cmdKeyNo }}; - + c.d.asBytes[0] = keylength; memcpy(c.d.asBytes+1, key, keylength); clearCommandBuffer(); SendCommand(&c); UsbCommand resp; - + if (!WaitForResponseTimeout(CMD_ACK,&resp,3000)) { PrintAndLogEx(WARNING, "Client command execute timeout"); return 0; - } + } uint8_t isOK = resp.arg[0] & 0xff; if ( isOK) { uint8_t * data= resp.d.asBytes; - + PrintAndLogEx(NORMAL, " Key :%s",sprint_hex(key, keylength)); PrintAndLogEx(NORMAL, " SESSION :%s",sprint_hex(data, keylength)); PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); @@ -650,7 +650,7 @@ int CmdHF14ADesAuth(const char *Cmd){ } else{ PrintAndLogEx(NORMAL, "Client command failed."); } - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); return 1; } diff --git a/client/cmdhfmfdes.h b/client/cmdhfmfdes.h index 18594075c..01ca471c9 100644 --- a/client/cmdhfmfdes.h +++ b/client/cmdhfmfdes.h @@ -82,7 +82,7 @@ enum { #define NO_CHANGES 0x0C // No changes done to backup files // ,CommitTransaction/ // AbortTransaction not necessary -#define OUT_OF_EEPROM_ERROR 0x0E // Insufficient NV-Memory to +#define OUT_OF_EEPROM_ERROR 0x0E // Insufficient NV-Memory to // complete command #define ILLEGAL_COMMAND_CODE 0x1C // Command code not supported #define INTEGRITY_ERROR 0x1E // CRC or MAC does not match data @@ -119,7 +119,7 @@ enum { // with same number already exists #define EEPROM_ERROR 0xEE // [1] // Could not complete NV-write // operation due to loss of power, - // internal backup/rollback + // internal backup/rollback // mechanism activated #define FILE_NOT_FOUND_ERROR 0xF0 // Specified file number does not // exist diff --git a/client/cmdhfmfdesfire.c b/client/cmdhfmfdesfire.c index a7452eb27..91b9bc645 100644 --- a/client/cmdhfmfdesfire.c +++ b/client/cmdhfmfdesfire.c @@ -30,7 +30,7 @@ static int CmdHelp(const char *Cmd); //verify n'r=nr int CmdHF14AMfDESAuth(const char *Cmd){ - + uint8_t blockNo = 0; //keyNo=0; uint32_t cuid = 0; @@ -39,8 +39,8 @@ int CmdHF14AMfDESAuth(const char *Cmd){ uint8_t b1[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t b2[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; DES_cblock nr, b0, r1, r0; - - + + uint8_t key[8]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; //DES_cblock iv={0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; DES_key_schedule ks1; @@ -51,15 +51,15 @@ int CmdHF14AMfDESAuth(const char *Cmd){ PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf desfire des-auth k 0"); return 0; - } - + } + //Change key to user defined one - + memcpy(key1,key,8); //memcpy(key2,key+8,8); DES_set_key((DES_cblock *)key1,&ks1); //DES_set_key((DES_cblock *)key2,&ks2); - + //Auth1 UsbCommand c = {CMD_MIFARE_DES_AUTH1, {blockNo}}; SendCommand(&c); @@ -76,7 +76,7 @@ int CmdHF14AMfDESAuth(const char *Cmd){ } else { PrintAndLogEx(WARNING, "Command execute timeout"); } - + //Do crypto magic DES_random_key(&nr); //b1=dec(nr) @@ -89,7 +89,7 @@ int CmdHF14AMfDESAuth(const char *Cmd){ memcpy(r1,r0,8); rol(r1,8); PrintAndLogEx(NORMAL, "r1:%s",sprint_hex(r1, 8)); - for(int i=0;i<8;i++){ + for(int i=0;i<8;i++){ b2[i]=(r1[i] ^ b1[i]); } DES_ecb_encrypt(&b2,&b2,&ks1,0); @@ -110,10 +110,10 @@ int CmdHF14AMfDESAuth(const char *Cmd){ if (isOK) PrintAndLogEx(NORMAL, "b3:%s", sprint_hex(data2+2, 8)); - + } else { PrintAndLogEx(WARNING, "Command execute timeout"); - } + } return 1; } @@ -123,14 +123,14 @@ int CmdHF14AMfDESAuth(const char *Cmd){ // Reader 2 Card : 03AF, 16 Bytes(b1),16Bytes(b2) CRC1 CRC2 // Card 2 Reader : 0300, 16 bytes(b3), CRC1 CRC2 ; success int CmdHF14AMfAESAuth(const char *Cmd){ - + uint8_t blockNo = 0; //keyNo=0; uint32_t cuid = 0; uint8_t reply[32] = {0x00}; //DES_cblock r1_b1; //unsigned char * b1, b2, nr, b0, r0, r1; - + uint8_t b1[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t b2[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; uint8_t nr[16]={ 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; @@ -148,8 +148,8 @@ int CmdHF14AMfAESAuth(const char *Cmd){ PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf desfire aes-auth k 0"); return 0; - } - + } + //Change key to user defined one // // int private_AES_set_encrypt_key(const unsigned char *userKey, const int bits,AES_KEY *key); @@ -159,7 +159,7 @@ int CmdHF14AMfAESAuth(const char *Cmd){ //memcpy(key2,key+8,8); AES_set_encrypt_key(key,128,&key_e); AES_set_decrypt_key(key,128,&key_d); - + //Auth1 UsbCommand c = {CMD_MIFARE_DES_AUTH1, {blockNo}}; SendCommand(&c); @@ -180,7 +180,7 @@ int CmdHF14AMfAESAuth(const char *Cmd){ // void AES_cbc_encrypt(const unsigned char *in, unsigned char *out, //size_t length, const AES_KEY *key, //unsigned char *ivec, const int enc); - + //Do crypto magic //DES_random_key(&nr); //b1=dec(nr) @@ -217,10 +217,10 @@ int CmdHF14AMfAESAuth(const char *Cmd){ if (isOK) PrintAndLogEx(NORMAL, "b3:%s", sprint_hex(data2+2, 16)); - + } else { PrintAndLogEx(WARNING, "Command execute timeout"); - } + } return 1; } diff --git a/client/cmdhfmfhard.c b/client/cmdhfmfhard.c index 1ebf2131d..d5c8c9403 100644 --- a/client/cmdhfmfhard.c +++ b/client/cmdhfmfhard.c @@ -11,7 +11,7 @@ // attacks this doesn't rely on implementation errors but only on the // inherent weaknesses of the crypto1 cypher. Described in // Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened -// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on +// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on // Computer and Communications Security, 2015 //----------------------------------------------------------------------------- @@ -92,8 +92,8 @@ static void get_SIMD_instruction_set(char* instruction_set) { default: strcpy(instruction_set, "no"); break; - } -} + } +} static void print_progress_header(void) { @@ -222,7 +222,7 @@ static void inflate_free(voidpf opaque, voidpf address) #define INPUT_BUFFER_LEN 80 //---------------------------------------------------------------------------- -// Initialize decompression of the respective (HF or LF) FPGA stream +// Initialize decompression of the respective (HF or LF) FPGA stream //---------------------------------------------------------------------------- static void init_inflate(z_streamp compressed_stream, uint8_t *input_buffer, uint32_t insize, uint8_t *output_buffer, uint32_t outsize) { @@ -236,7 +236,7 @@ static void init_inflate(z_streamp compressed_stream, uint8_t *input_buffer, uin compressed_stream->zfree = &inflate_free; inflateInit2(compressed_stream, 0); - + } @@ -244,14 +244,14 @@ static void init_bitflip_bitarrays(void) { #if defined (DEBUG_REDUCTION) uint8_t line = 0; -#endif +#endif z_stream compressed_stream; - + char state_files_path[strlen(get_my_executable_directory()) + strlen(STATE_FILES_DIRECTORY) + strlen(STATE_FILE_TEMPLATE) + 1]; char state_file_name[strlen(STATE_FILE_TEMPLATE)+1]; - + for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { num_effective_bitflips[odd_even] = 0; for (uint16_t bitflip = 0x001; bitflip < 0x400; bitflip++) { @@ -339,14 +339,14 @@ static void init_bitflip_bitarrays(void) for(uint16_t i = 0; i < num_1st_byte_effective_bitflips; i++) { PrintAndLogEx(NORMAL, "%03x ", all_effective_bitflip[i]); } -#endif +#endif qsort(all_effective_bitflip+num_1st_byte_effective_bitflips, num_all_effective_bitflips - num_1st_byte_effective_bitflips, sizeof(uint16_t), compare_count_bitflip_bitarrays); #if defined (DEBUG_REDUCTION) PrintAndLogEx(NORMAL, "\n2nd byte effective bitflips (%d): \n", num_all_effective_bitflips - num_1st_byte_effective_bitflips); for(uint16_t i = num_1st_byte_effective_bitflips; i < num_all_effective_bitflips; i++) { PrintAndLogEx(NORMAL, "%03x ", all_effective_bitflip[i]); } -#endif +#endif char progress_text[80]; sprintf(progress_text, "Using %d precalculated bitflip state tables", num_all_effective_bitflips); hardnested_print_progress(0, progress_text, (float)(1LL<<47), 0); @@ -369,10 +369,10 @@ static void free_bitflip_bitarrays(void) static uint32_t *part_sum_a0_bitarrays[2][NUM_PART_SUMS]; static uint32_t *part_sum_a8_bitarrays[2][NUM_PART_SUMS]; -static uint32_t *sum_a0_bitarrays[2][NUM_SUMS]; +static uint32_t *sum_a0_bitarrays[2][NUM_SUMS]; static uint16_t PartialSumProperty(uint32_t state, odd_even_t odd_even) -{ +{ uint16_t sum = 0; for (uint16_t j = 0; j < 16; j++) { uint32_t st = state; @@ -408,7 +408,7 @@ static void init_part_sum_bitarrays(void) } } for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { - //PrintAndLogEx(NORMAL, "(%d, %" PRIu16 ")...", odd_even, part_sum_a0); + //PrintAndLogEx(NORMAL, "(%d, %" PRIu16 ")...", odd_even, part_sum_a0); for (uint32_t state = 0; state < (1<<20); state++) { uint16_t part_sum_a0 = PartialSumProperty(state, odd_even) / 2; for (uint16_t low_bits = 0; low_bits < 1<<4; low_bits++) { @@ -428,7 +428,7 @@ static void init_part_sum_bitarrays(void) } } for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { - //PrintAndLogEx(NORMAL, "(%d, %" PRIu16 ")...", odd_even, part_sum_a8); + //PrintAndLogEx(NORMAL, "(%d, %" PRIu16 ")...", odd_even, part_sum_a8); for (uint32_t state = 0; state < (1<<20); state++) { uint16_t part_sum_a8 = PartialSumProperty(state, odd_even) / 2; for (uint16_t high_bits = 0; high_bits < 1<<4; high_bits++) { @@ -439,7 +439,7 @@ static void init_part_sum_bitarrays(void) } -static void free_part_sum_bitarrays(void) +static void free_part_sum_bitarrays(void) { for (int16_t part_sum_a8 = (NUM_PART_SUMS-1); part_sum_a8 >= 0; part_sum_a8--) { free_bitarray(part_sum_a8_bitarrays[ODD_STATE][part_sum_a8]); @@ -494,14 +494,14 @@ static void free_sum_bitarrays(void) char failstr[250] = ""; #endif -static const float p_K0[NUM_SUMS] = { // the probability that a random nonce has a Sum Property K - 0.0290, 0.0083, 0.0006, 0.0339, 0.0048, 0.0934, 0.0119, 0.0489, 0.0602, 0.4180, 0.0602, 0.0489, 0.0119, 0.0934, 0.0048, 0.0339, 0.0006, 0.0083, 0.0290 +static const float p_K0[NUM_SUMS] = { // the probability that a random nonce has a Sum Property K + 0.0290, 0.0083, 0.0006, 0.0339, 0.0048, 0.0934, 0.0119, 0.0489, 0.0602, 0.4180, 0.0602, 0.0489, 0.0119, 0.0934, 0.0048, 0.0339, 0.0006, 0.0083, 0.0290 }; -static float my_p_K[NUM_SUMS]; +static float my_p_K[NUM_SUMS]; static const float *p_K; - + static uint32_t cuid; static noncelist_t nonces[256]; static uint8_t best_first_bytes[256]; @@ -520,7 +520,7 @@ static uint64_t num_keys_tested = 0; static statelist_t *candidates = NULL; -static int add_nonce(uint32_t nonce_enc, uint8_t par_enc) +static int add_nonce(uint32_t nonce_enc, uint8_t par_enc) { uint8_t first_byte = nonce_enc >> 24; noncelistentry_t *p1 = nonces[first_byte].first; @@ -535,7 +535,7 @@ static int add_nonce(uint32_t nonce_enc, uint8_t par_enc) p2 = p1; p1 = p1->next; } - + if (p1 == NULL) { // need to add at the end of the list if (p2 == NULL) { // list is empty yet. Add first entry. p2 = nonces[first_byte].first = malloc(sizeof(noncelistentry_t)); @@ -548,7 +548,7 @@ static int add_nonce(uint32_t nonce_enc, uint8_t par_enc) } else { p2 = p2->next = malloc(sizeof(noncelistentry_t)); } - } else { // we have seen this 2nd byte before. Nothing to add or insert. + } else { // we have seen this 2nd byte before. Nothing to add or insert. return (0); } @@ -626,7 +626,7 @@ static void free_nonces_memory(void) -static double p_hypergeometric(uint16_t i_K, uint16_t n, uint16_t k) +static double p_hypergeometric(uint16_t i_K, uint16_t n, uint16_t k) { // for efficient computation we are using the recursive definition // (K-k+1) * (n-k+1) @@ -637,19 +637,19 @@ static double p_hypergeometric(uint16_t i_K, uint16_t n, uint16_t k) // P(X=0) = ----------------------------- // N*(N-1)*...*(N-n+1) - + uint16_t const N = 256; uint16_t K = sums[i_K]; - + if (n-k > N-K || k > K) return 0.0; // avoids log(x<=0) in calculation below if (k == 0) { // use logarithms to avoid overflow with huge factorials (double type can only hold 170!) double log_result = 0.0; for (int16_t i = N-K; i >= N-K-n+1; i--) { log_result += log(i); - } + } for (int16_t i = N; i >= N-n+1; i--) { log_result -= log(i); } @@ -669,8 +669,8 @@ static double p_hypergeometric(uint16_t i_K, uint16_t n, uint16_t k) } } } - - + + static float sum_probability(uint16_t i_K, uint16_t n, uint16_t k) { if (k > sums[i_K]) return 0.0; @@ -703,7 +703,7 @@ static void init_allbitflips_array(void) static void update_allbitflips_array(void) -{ +{ if (hardnested_stage & CHECK_2ND_BYTES) { for (uint16_t i = 0; i < 256; i++) { for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { @@ -720,22 +720,22 @@ static void update_allbitflips_array(void) } } - -static uint32_t estimated_num_states_part_sum_coarse(uint16_t part_sum_a0_idx, uint16_t part_sum_a8_idx, odd_even_t odd_even) + +static uint32_t estimated_num_states_part_sum_coarse(uint16_t part_sum_a0_idx, uint16_t part_sum_a8_idx, odd_even_t odd_even) { return part_sum_count[odd_even][part_sum_a0_idx][part_sum_a8_idx]; } -static uint32_t estimated_num_states_part_sum(uint8_t first_byte, uint16_t part_sum_a0_idx, uint16_t part_sum_a8_idx, odd_even_t odd_even) +static uint32_t estimated_num_states_part_sum(uint8_t first_byte, uint16_t part_sum_a0_idx, uint16_t part_sum_a8_idx, odd_even_t odd_even) { if (odd_even == ODD_STATE) { - return count_bitarray_AND3(part_sum_a0_bitarrays[odd_even][part_sum_a0_idx], - part_sum_a8_bitarrays[odd_even][part_sum_a8_idx], + return count_bitarray_AND3(part_sum_a0_bitarrays[odd_even][part_sum_a0_idx], + part_sum_a8_bitarrays[odd_even][part_sum_a8_idx], nonces[first_byte].states_bitarray[odd_even]); } else { - return count_bitarray_AND4(part_sum_a0_bitarrays[odd_even][part_sum_a0_idx], - part_sum_a8_bitarrays[odd_even][part_sum_a8_idx], + return count_bitarray_AND4(part_sum_a0_bitarrays[odd_even][part_sum_a0_idx], + part_sum_a8_bitarrays[odd_even][part_sum_a8_idx], nonces[first_byte].states_bitarray[odd_even], nonces[first_byte^0x80].states_bitarray[odd_even]); } @@ -759,7 +759,7 @@ static uint64_t estimated_num_states(uint8_t first_byte, uint16_t sum_a0, uint16 for (uint8_t r = 0; r < NUM_PART_SUMS; r++) { for (uint8_t s = 0; s < NUM_PART_SUMS; s++) { if (2*r*(16-2*s) + (16-2*r)*2*s == sum_a8) { - num_states += (uint64_t)estimated_num_states_part_sum(first_byte, p, r, ODD_STATE) + num_states += (uint64_t)estimated_num_states_part_sum(first_byte, p, r, ODD_STATE) * estimated_num_states_part_sum(first_byte, q, s, EVEN_STATE); } } @@ -780,7 +780,7 @@ static uint64_t estimated_num_states_coarse(uint16_t sum_a0, uint16_t sum_a8) for (uint8_t r = 0; r < NUM_PART_SUMS; r++) { for (uint8_t s = 0; s < NUM_PART_SUMS; s++) { if (2*r*(16-2*s) + (16-2*r)*2*s == sum_a8) { - num_states += (uint64_t)estimated_num_states_part_sum_coarse(p, r, ODD_STATE) + num_states += (uint64_t)estimated_num_states_part_sum_coarse(p, r, ODD_STATE) * estimated_num_states_part_sum_coarse(q, s, EVEN_STATE); } } @@ -826,7 +826,7 @@ static void update_sum_bitarrays(odd_even_t odd_even) } for (uint8_t part_sum_a0 = 0; part_sum_a0 < NUM_PART_SUMS; part_sum_a0++) { for (uint8_t part_sum_a8 = 0; part_sum_a8 < NUM_PART_SUMS; part_sum_a8++) { - part_sum_count[odd_even][part_sum_a0][part_sum_a8] + part_sum_count[odd_even][part_sum_a0][part_sum_a8] += count_bitarray_AND2(part_sum_a0_bitarrays[odd_even][part_sum_a0], part_sum_a8_bitarrays[odd_even][part_sum_a8]); } } @@ -854,7 +854,7 @@ static int compare_sum_a8_guess(const void *b1, const void *b2) } -static float check_smallest_bitflip_bitarrays(void) +static float check_smallest_bitflip_bitarrays(void) { uint32_t num_odd, num_even; uint64_t smallest = 1LL << 48; @@ -900,7 +900,7 @@ static void update_expected_brute_force(uint8_t best_byte) { static float sort_best_first_bytes(void) { - + // initialize best_first_bytes, do a rough estimation on remaining states for each Sum_a8 property // and the expected number of states to brute force for (uint16_t i = 0; i < 256; i++) { @@ -914,7 +914,7 @@ static float sort_best_first_bytes(void) nonces[i].expected_num_brute_force += prob_all_failed * (float)nonces[i].sum_a8_guess[j].num_states / 2.0; } } - + // sort based on expected number of states to brute force qsort(best_first_bytes, 256, 1, compare_expected_num_brute_force); @@ -988,11 +988,11 @@ static float sort_best_first_bytes(void) } -static float update_reduction_rate(float last, bool init) +static float update_reduction_rate(float last, bool init) { #define QUEUE_LEN 4 static float queue[QUEUE_LEN]; - + for (uint16_t i = 0; i < QUEUE_LEN-1; i++) { if (init) { queue[i] = (float)(1LL << 48); @@ -1005,7 +1005,7 @@ static float update_reduction_rate(float last, bool init) } else { queue[QUEUE_LEN-1] = last; } - + // linear regression float avg_y = 0.0; float avg_x = 0.0; @@ -1015,7 +1015,7 @@ static float update_reduction_rate(float last, bool init) } avg_x /= QUEUE_LEN; avg_y /= QUEUE_LEN; - + float dev_xy = 0.0; float dev_x2 = 0.0; for (uint16_t i = 0; i < QUEUE_LEN; i++) { @@ -1025,9 +1025,9 @@ static float update_reduction_rate(float last, bool init) float reduction_rate = -1.0 * dev_xy / dev_x2; // the negative slope of the linear regression -#if defined (DEBUG_REDUCTION) +#if defined (DEBUG_REDUCTION) PrintAndLogEx(NORMAL, "update_reduction_rate(%1.0f) = %1.0f per sample, brute_force_per_sample = %1.0f\n", last, reduction_rate, brute_force_per_second * (float)sample_period / 1000.0); -#endif +#endif return reduction_rate; } @@ -1047,12 +1047,12 @@ static bool shrink_key_space(float *brute_forces) //iceman 2018 return ((hardnested_stage & CHECK_2ND_BYTES) && - reduction_rate >= 0.0 && + reduction_rate >= 0.0 && ( reduction_rate < brute_force_per_second * (float)sample_period / 1000.0 || *brute_forces < 0x1F00000000)); } - -static void estimate_sum_a8(void) + +static void estimate_sum_a8(void) { if (first_byte_num == 256) { for (uint16_t i = 0; i < 256; i++) { @@ -1066,7 +1066,7 @@ static void estimate_sum_a8(void) } } } -} +} static int read_nonce_file(char *filename) @@ -1079,9 +1079,9 @@ static int read_nonce_file(char *filename) uint8_t read_buf[9]; uint32_t nt_enc1, nt_enc2; uint8_t par_enc; - + num_acquired_nonces = 0; - if ((fnonces = fopen(filename,"rb")) == NULL) { + if ((fnonces = fopen(filename,"rb")) == NULL) { PrintAndLogEx(WARNING, "Could not open file %s",filename); return 1; } @@ -1108,9 +1108,9 @@ static int read_nonce_file(char *filename) bytes_read = fread(read_buf, 1, 9, fnonces); } fclose(fnonces); - + char progress_string[80]; - sprintf(progress_string, "Read %d nonces from file. cuid=%08x", num_acquired_nonces, cuid); + sprintf(progress_string, "Read %d nonces from file. cuid=%08x", num_acquired_nonces, cuid); hardnested_print_progress(num_acquired_nonces, progress_string, (float)(1LL<<47), 0); sprintf(progress_string, "Target Block=%d, Keytype=%c", trgBlockNo, trgKeyType==0?'A':'B'); hardnested_print_progress(num_acquired_nonces, progress_string, (float)(1LL<<47), 0); @@ -1121,7 +1121,7 @@ static int read_nonce_file(char *filename) break; } } - + return 0; } @@ -1145,10 +1145,10 @@ static bool timeout(void) } -static void +static void #ifdef __has_attribute #if __has_attribute(force_align_arg_pointer) -__attribute__((force_align_arg_pointer)) +__attribute__((force_align_arg_pointer)) #endif #endif *check_for_BitFlipProperties_thread(void *args) @@ -1156,15 +1156,15 @@ __attribute__((force_align_arg_pointer)) uint8_t first_byte = ((uint8_t *)args)[0]; uint8_t last_byte = ((uint8_t *)args)[1]; uint8_t time_budget = ((uint8_t *)args)[2]; - + if (hardnested_stage & CHECK_1ST_BYTES) { // for (uint16_t bitflip = 0x001; bitflip < 0x200; bitflip++) { for (uint16_t bitflip_idx = 0; bitflip_idx < num_1st_byte_effective_bitflips; bitflip_idx++) { uint16_t bitflip = all_effective_bitflip[bitflip_idx]; if (time_budget & timeout()) { -#if defined (DEBUG_REDUCTION) +#if defined (DEBUG_REDUCTION) PrintAndLogEx(NORMAL, "break at bitflip_idx %d...", bitflip_idx); -#endif +#endif return NULL; } for (uint16_t i = first_byte; i <= last_byte; i++) { @@ -1243,26 +1243,26 @@ static void check_for_BitFlipProperties(bool time_budget) { // create and run worker threads pthread_t thread_id[NUM_CHECK_BITFLIPS_THREADS]; - + uint8_t args[NUM_CHECK_BITFLIPS_THREADS][3]; - uint16_t bytes_per_thread = (256 + (NUM_CHECK_BITFLIPS_THREADS/2)) / NUM_CHECK_BITFLIPS_THREADS; + uint16_t bytes_per_thread = (256 + (NUM_CHECK_BITFLIPS_THREADS/2)) / NUM_CHECK_BITFLIPS_THREADS; for (uint8_t i = 0; i < NUM_CHECK_BITFLIPS_THREADS; i++) { args[i][0] = i * bytes_per_thread; args[i][1] = MIN(args[i][0]+bytes_per_thread-1, 255); args[i][2] = time_budget; } args[NUM_CHECK_BITFLIPS_THREADS-1][1] = MAX(args[NUM_CHECK_BITFLIPS_THREADS-1][1], 255); - + // start threads for (uint8_t i = 0; i < NUM_CHECK_BITFLIPS_THREADS; i++) { pthread_create(&thread_id[i], NULL, check_for_BitFlipProperties_thread, args[i]); } - + // wait for threads to terminate: for (uint8_t i = 0; i < NUM_CHECK_BITFLIPS_THREADS; i++) { pthread_join(thread_id[i], NULL); } - + if (hardnested_stage & CHECK_2ND_BYTES) { hardnested_stage &= ~CHECK_1ST_BYTES; // we are done with 1st stage, except... for (uint16_t i = 0; i < NUM_CHECK_BITFLIPS_THREADS; i++) { @@ -1272,7 +1272,7 @@ static void check_for_BitFlipProperties(bool time_budget) } } } -#if defined (DEBUG_REDUCTION) +#if defined (DEBUG_REDUCTION) if (hardnested_stage & CHECK_1ST_BYTES) PrintAndLogEx(NORMAL, "stage 1 not completed yet\n"); #endif } @@ -1319,12 +1319,12 @@ static void simulate_MFplus_RNG(uint32_t test_cuid, uint64_t test_key, uint32_t for (int8_t byte_pos = 3; byte_pos >= 0; byte_pos--) { uint8_t nt_byte_dec = (nt >> (8*byte_pos)) & 0xff; uint8_t nt_byte_enc = crypto1_byte(&sim_cs, nt_byte_dec ^ (test_cuid >> (8*byte_pos)), false) ^ nt_byte_dec; // encode the nonce byte - *nt_enc = (*nt_enc << 8) | nt_byte_enc; + *nt_enc = (*nt_enc << 8) | nt_byte_enc; uint8_t ks_par = filter(sim_cs.odd); // the keystream bit to encode/decode the parity bit uint8_t nt_byte_par_enc = ks_par ^ oddparity8(nt_byte_dec); // determine the nt byte's parity and encode it *par_enc = (*par_enc << 1) | nt_byte_par_enc; } - + } @@ -1338,7 +1338,7 @@ static void simulate_acquire_nonces() uint32_t total_num_nonces = 0; float brute_force; bool reported_suma8 = false; - + cuid = (rand() & 0xff) << 24 | (rand() & 0xff) << 16 | (rand() & 0xff) << 8 | (rand() & 0xff); if (known_target_key == -1) { known_target_key = ((uint64_t)rand() & 0xfff) << 36 | ((uint64_t)rand() & 0xfff) << 24 | ((uint64_t)rand() & 0xfff) << 12 | ((uint64_t)rand() & 0xfff); @@ -1350,7 +1350,7 @@ static void simulate_acquire_nonces() fprintf(fstats, "%012" PRIx64 ";%" PRIx32 ";", known_target_key, cuid); num_acquired_nonces = 0; - + do { uint32_t nt_enc = 0; uint8_t par_enc = 0; @@ -1362,7 +1362,7 @@ static void simulate_acquire_nonces() } last_sample_clock = msclock(); - + if (first_byte_num == 256 ) { if (hardnested_stage == CHECK_1ST_BYTES) { for (uint16_t i = 0; i < NUM_SUMS; i++) { @@ -1373,7 +1373,7 @@ static void simulate_acquire_nonces() } hardnested_stage |= CHECK_2ND_BYTES; apply_sum_a0(); - } + } update_nonce_data(true); acquisition_completed = shrink_key_space(&brute_force); if (!reported_suma8) { @@ -1392,14 +1392,14 @@ static void simulate_acquire_nonces() } while (!acquisition_completed); time_t end_time = time(NULL); - // PrintAndLogEx(NORMAL, "Acquired a total of %" PRId32" nonces in %1.0f seconds (%1.0f nonces/minute)", - // num_acquired_nonces, - // difftime(end_time, time1), + // PrintAndLogEx(NORMAL, "Acquired a total of %" PRId32" nonces in %1.0f seconds (%1.0f nonces/minute)", + // num_acquired_nonces, + // difftime(end_time, time1), // difftime(end_time, time1)!=0.0?(float)total_num_nonces*60.0/difftime(end_time, time1):INFINITY // ); fprintf(fstats, "%" PRId32 ";%" PRId32 ";%1.0f;", total_num_nonces, num_acquired_nonces, difftime(end_time,time1)); - + } @@ -1421,7 +1421,7 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ UsbCommand resp; num_acquired_nonces = 0; - + clearCommandBuffer(); do { @@ -1434,9 +1434,9 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ clearCommandBuffer(); SendCommand(&c); - + if (field_off) break; - + if (initialize) { if (!WaitForResponseTimeout(CMD_ACK, &resp, 3000)) { //strange second call (iceman) @@ -1449,7 +1449,7 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ cuid = resp.arg[1]; if (nonce_file_write && fnonces == NULL) { - if ((fnonces = fopen(filename,"wb")) == NULL) { + if ((fnonces = fopen(filename,"wb")) == NULL) { PrintAndLogEx(WARNING, "Could not create file %s", filename); return 3; } @@ -1472,7 +1472,7 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ nt_enc1 = bytes_to_num(bufp, 4); nt_enc2 = bytes_to_num(bufp+4, 4); par_enc = bytes_to_num(bufp+8, 1); - + //PrintAndLogEx(NORMAL, "Encrypted nonce: %08x, encrypted_parity: %02x\n", nt_enc1, par_enc >> 4); num_acquired_nonces += add_nonce(nt_enc1, par_enc >> 4); //PrintAndLogEx(NORMAL, "Encrypted nonce: %08x, encrypted_parity: %02x\n", nt_enc2, par_enc & 0x0f); @@ -1485,7 +1485,7 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ bufp += 9; } total_num_nonces += num_sampled_nonces; - + if (first_byte_num == 256 ) { if (hardnested_stage == CHECK_1ST_BYTES) { for (uint16_t i = 0; i < NUM_SUMS; i++) { @@ -1513,7 +1513,7 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ hardnested_print_progress(num_acquired_nonces, "Apply bit flip properties", brute_force, 0); } } - + if (acquisition_completed) { field_off = true; // switch off field with next SendCommand and then finish } @@ -1545,12 +1545,12 @@ static int acquire_nonces(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_ if (nonce_file_write) { fclose(fnonces); } - - // PrintAndLogEx(NORMAL, "Sampled a total of %d nonces in %d seconds (%0.0f nonces/minute)", - // total_num_nonces, - // time(NULL)-time1, + + // PrintAndLogEx(NORMAL, "Sampled a total of %d nonces in %d seconds (%0.0f nonces/minute)", + // total_num_nonces, + // time(NULL)-time1, // (float)total_num_nonces*60.0/(time(NULL)-time1)); - + return 0; } @@ -1594,7 +1594,7 @@ static inline bool remaining_bits_match(uint_fast8_t num_common_bits, uint_fast8 } } else { // even bits - switch (num_common_bits) { + switch (num_common_bits) { case 0: if (invalid_state(byte_diff, state1, state2, 0, 0)) return false; case 1: if (!invariant_holds(byte_diff, state1, state2, 2, 1)) return true; case 2: if (invalid_state(byte_diff, state1, state2, 2, 1)) return false; @@ -1604,7 +1604,7 @@ static inline bool remaining_bits_match(uint_fast8_t num_common_bits, uint_fast8 case 6: if (invalid_state(byte_diff, state1, state2, 6, 3)) return false; } } - + return true; // valid state } @@ -1637,7 +1637,7 @@ static void init_statelist_cache(void) sl_cache[i][j][k].cache_status = TO_BE_DONE; } } - } + } pthread_mutex_unlock(&statelist_cache_mutex); } @@ -1651,7 +1651,7 @@ static void free_statelist_cache(void) free(sl_cache[i][j][k].sl); } } - } + } pthread_mutex_unlock(&statelist_cache_mutex); } @@ -1660,7 +1660,7 @@ static void free_statelist_cache(void) static inline bool bitflips_match(uint8_t byte, uint32_t state, odd_even_t odd_even, bool quiet) #else static inline bool bitflips_match(uint8_t byte, uint32_t state, odd_even_t odd_even) -#endif +#endif { uint32_t *bitset = nonces[byte].states_bitarray[odd_even]; bool possible = test_bit24(bitset, state); @@ -1673,11 +1673,11 @@ static inline bool bitflips_match(uint8_t byte, uint32_t state, odd_even_t odd_e #endif return false; } - + return true; } - - + + static uint_fast8_t reverse(uint_fast8_t b) { b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; @@ -1687,11 +1687,11 @@ static uint_fast8_t reverse(uint_fast8_t b) } -static bool all_bitflips_match(uint8_t byte, uint32_t state, odd_even_t odd_even) +static bool all_bitflips_match(uint8_t byte, uint32_t state, odd_even_t odd_even) { uint32_t masks[2][8] = {{0x00fffff0, 0x00fffff8, 0x00fffff8, 0x00fffffc, 0x00fffffc, 0x00fffffe, 0x00fffffe, 0x00ffffff}, {0x00fffff0, 0x00fffff0, 0x00fffff8, 0x00fffff8, 0x00fffffc, 0x00fffffc, 0x00fffffe, 0x00fffffe} }; - + for (uint16_t i = 1; i < 256; i++) { uint_fast8_t bytes_diff = reverse(i); // start with most common bits uint_fast8_t byte2 = byte ^ bytes_diff; @@ -1704,16 +1704,16 @@ static bool all_bitflips_match(uint8_t byte, uint32_t state, odd_even_t odd_even if (bitflips_match(byte2, (state & mask) | remaining_bits, odd_even, true)) { #else if (bitflips_match(byte2, (state & mask) | remaining_bits, odd_even)) { -#endif +#endif found_match = true; break; } } } if (!found_match) { -#ifdef DEBUG_KEY_ELIMINATION +#ifdef DEBUG_KEY_ELIMINATION if (known_target_key != -1 && state == test_state[odd_even]) { - PrintAndLogEx(NORMAL, "all_bitflips_match() 1st Byte: %s test state (0x%06x): Eliminated. Bytes = %02x, %02x, Common Bits = %d\n", + PrintAndLogEx(NORMAL, "all_bitflips_match() 1st Byte: %s test state (0x%06x): Eliminated. Bytes = %02x, %02x, Common Bits = %d\n", odd_even == ODD_STATE ? "odd" : "even", test_state[odd_even], byte, @@ -1767,15 +1767,15 @@ static void add_matching_states(statelist_t *candidates, uint8_t part_sum_a0, ui free(candidates->states[odd_even]); exit(4); } - + uint32_t *bitarray_a0 = part_sum_a0_bitarrays[odd_even][part_sum_a0/2]; uint32_t *bitarray_a8 = part_sum_a8_bitarrays[odd_even][part_sum_a8/2]; uint32_t *bitarray_bitflips = nonces[best_first_bytes[0]].states_bitarray[odd_even]; bitarray_AND4(candidates_bitarray, bitarray_a0, bitarray_a8, bitarray_bitflips); - + bitarray_to_list(best_first_bytes[0], candidates_bitarray, candidates->states[odd_even], &(candidates->len[odd_even]), odd_even); - + if (candidates->len[odd_even] == 0) { free(candidates->states[odd_even]); candidates->states[odd_even] = NULL; @@ -1825,7 +1825,7 @@ static void add_bitflip_candidates(uint8_t byte) PrintAndLogEx(WARNING, "Out of memory error in add_bitflip_candidates().\n"); exit(4); } - + bitarray_to_list(byte, nonces[byte].states_bitarray[odd_even], candidates->states[odd_even], &(candidates->len[odd_even]), odd_even); if (candidates->len[odd_even] + 1 < worstcase_size) { @@ -1844,7 +1844,7 @@ static bool TestIfKeyExists(uint64_t key) uint32_t state_odd = pcs->odd & 0x00ffffff; uint32_t state_even = pcs->even & 0x00ffffff; - + uint64_t count = 0; for (statelist_t *p = candidates; p != NULL; p = p->next) { bool found_odd = false; @@ -1898,10 +1898,10 @@ static void init_book_of_work(void) } } -static void +static void #ifdef __has_attribute #if __has_attribute(force_align_arg_pointer) -__attribute__((force_align_arg_pointer)) +__attribute__((force_align_arg_pointer)) #endif #endif *generate_candidates_worker_thread(void *args) @@ -1910,14 +1910,14 @@ __attribute__((force_align_arg_pointer)) uint16_t sum_a0 = sums[sum_args[0]]; uint16_t sum_a8 = sums[sum_args[1]]; // uint16_t my_thread_number = sums[2]; - + bool there_might_be_more_work = true; do { there_might_be_more_work = false; for (uint8_t p = 0; p < NUM_PART_SUMS; p++) { for (uint8_t q = 0; q < NUM_PART_SUMS; q++) { if (2*p*(16-2*q) + (16-2*p)*2*q == sum_a0) { - // PrintAndLogEx(NORMAL, "Reducing Partial Statelists (p,q) = (%d,%d) with lengths %d, %d\n", + // PrintAndLogEx(NORMAL, "Reducing Partial Statelists (p,q) = (%d,%d) with lengths %d, %d\n", // p, q, partial_statelist[p].len[ODD_STATE], partial_statelist[q].len[EVEN_STATE]); for (uint8_t r = 0; r < NUM_PART_SUMS; r++) { for (uint8_t s = 0; s < NUM_PART_SUMS; s++) { @@ -1952,13 +1952,13 @@ __attribute__((force_align_arg_pointer)) add_cached_states(current_candidates, 2*q, 2*s, EVEN_STATE); even_completed = true; } - + bool work_required = true; // if there had been two cached results, there is no more work to do if (even_completed && odd_completed) { work_required = false; - } + } // if there had been one cached empty result, there is no need to calculate the other part: if (work_required) { @@ -1966,7 +1966,7 @@ __attribute__((force_align_arg_pointer)) current_candidates->len[ODD_STATE] = 0; current_candidates->states[ODD_STATE] = NULL; work_required = false; - } + } if (odd_completed && !current_candidates->len[ODD_STATE]) { current_candidates->len[EVEN_STATE] = 0; current_candidates->states[EVEN_STATE] = NULL; @@ -1995,7 +1995,7 @@ __attribute__((force_align_arg_pointer)) work_required = false; } } - + if (work_required) { // we had no cached result. Need to calculate both odd and even sl_cache[p][r][ODD_STATE].cache_status = WORK_IN_PROGRESS; sl_cache[q][s][EVEN_STATE].cache_status = WORK_IN_PROGRESS; @@ -2027,10 +2027,10 @@ __attribute__((force_align_arg_pointer)) // log((uint64_t)current_candidates->len[ODD_STATE] * current_candidates->len[EVEN_STATE])/log(2)); // uint32_t estimated_odd = estimated_num_states_part_sum(best_first_bytes[0], p, r, ODD_STATE); // uint32_t estimated_even= estimated_num_states_part_sum(best_first_bytes[0], q, s, EVEN_STATE); - // uint64_t estimated_total = (uint64_t)estimated_odd * estimated_even; + // uint64_t estimated_total = (uint64_t)estimated_odd * estimated_even; // PrintAndLogEx(NORMAL, "Estimated: %" PRIu32 " * %" PRIu32 " = %" PRIu64 " (2^%0.1f)\n", estimated_odd, estimated_even, estimated_total, log(estimated_total) / log(2)); // if (estimated_odd < current_candidates->len[ODD_STATE] || estimated_even < current_candidates->len[EVEN_STATE]) { - // PrintAndLogEx(NORMAL, "############################################################################ERROR! ESTIMATED < REAL !!!\n"); + // PrintAndLogEx(NORMAL, "############################################################################ERROR! ESTIMATED < REAL !!!\n"); // //exit(2); // } // } @@ -2041,14 +2041,14 @@ __attribute__((force_align_arg_pointer)) } } } while (there_might_be_more_work); - + return NULL; } static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) { - + init_statelist_cache(); init_book_of_work(); @@ -2058,7 +2058,7 @@ static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) // create and run worker threads pthread_t thread_id[NUM_REDUCTION_WORKING_THREADS]; - + uint16_t sums[NUM_REDUCTION_WORKING_THREADS][3]; for (uint16_t i = 0; i < NUM_REDUCTION_WORKING_THREADS; i++) { sums[i][0] = sum_a0_idx; @@ -2066,7 +2066,7 @@ static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) sums[i][2] = i+1; pthread_create(thread_id + i, NULL, generate_candidates_worker_thread, sums[i]); } - + // wait for threads to terminate: for (uint16_t i = 0; i < NUM_REDUCTION_WORKING_THREADS; i++) { pthread_join(thread_id[i], NULL); @@ -2074,7 +2074,7 @@ static void generate_candidates(uint8_t sum_a0_idx, uint8_t sum_a8_idx) // clean up mutex pthread_mutex_destroy(&statelist_cache_mutex); - + maximum_states = 0; for (statelist_t *sl = candidates; sl != NULL; sl = sl->next) { maximum_states += (uint64_t)sl->len[ODD_STATE] * sl->len[EVEN_STATE]; @@ -2104,8 +2104,8 @@ static void free_candidates_memory(statelist_t *sl) static void pre_XOR_nonces(void) { - // prepare acquired nonces for faster brute forcing. - + // prepare acquired nonces for faster brute forcing. + // XOR the cryptoUID and its parity for (uint16_t i = 0; i < 256; i++) { noncelistentry_t *test_nonce = nonces[i].first; @@ -2142,8 +2142,8 @@ static void Tests() for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { uint32_t *bitset = nonces[best_first_bytes[0]].states_bitarray[odd_even]; if (!test_bit24(bitset, test_state[odd_even])) { - PrintAndLogEx(NORMAL, "\nBUG: known target key's %s state is not member of first nonce byte's (0x%02x) states_bitarray!\n", - odd_even==EVEN_STATE?"even":"odd ", + PrintAndLogEx(NORMAL, "\nBUG: known target key's %s state is not member of first nonce byte's (0x%02x) states_bitarray!\n", + odd_even==EVEN_STATE?"even":"odd ", best_first_bytes[0]); } } @@ -2153,43 +2153,43 @@ static void Tests() for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { uint32_t *bitset = all_bitflips_bitarray[odd_even]; if (!test_bit24(bitset, test_state[odd_even])) { - PrintAndLogEx(NORMAL, "\nBUG: known target key's %s state is not member of all_bitflips_bitarray!\n", + PrintAndLogEx(NORMAL, "\nBUG: known target key's %s state is not member of all_bitflips_bitarray!\n", odd_even==EVEN_STATE?"even":"odd "); } } - } + } } -static void Tests2(void) +static void Tests2(void) { if (known_target_key != -1) { for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { uint32_t *bitset = nonces[best_first_byte_smallest_bitarray].states_bitarray[odd_even]; if (!test_bit24(bitset, test_state[odd_even])) { PrintAndLogEx(NORMAL, "\nBUG: known target key's %s state is not member of first nonce byte's (0x%02x) states_bitarray!\n", - odd_even==EVEN_STATE?"even":"odd ", + odd_even==EVEN_STATE?"even":"odd ", best_first_byte_smallest_bitarray); } } - } + } if (known_target_key != -1) { for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { uint32_t *bitset = all_bitflips_bitarray[odd_even]; if (!test_bit24(bitset, test_state[odd_even])) { - PrintAndLogEx(NORMAL, "\nBUG: known target key's %s state is not member of all_bitflips_bitarray!\n", + PrintAndLogEx(NORMAL, "\nBUG: known target key's %s state is not member of all_bitflips_bitarray!\n", odd_even==EVEN_STATE?"even":"odd "); } } - } - + } + } static uint16_t real_sum_a8 = 0; -static void set_test_state(uint8_t byte) +static void set_test_state(uint8_t byte) { struct Crypto1State *pcs; pcs = crypto1_create(known_target_key); @@ -2201,11 +2201,11 @@ static void set_test_state(uint8_t byte) } -int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests, uint64_t *foundkey, char *filename) +int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBlockNo, uint8_t trgKeyType, uint8_t *trgkey, bool nonce_file_read, bool nonce_file_write, bool slow, int tests, uint64_t *foundkey, char *filename) { - char progress_text[80]; + char progress_text[80]; char instr_set[12] = {0}; - + get_SIMD_instruction_set(instr_set); PrintAndLogEx(SUCCESS,"Using %s SIMD core.", instr_set); @@ -2217,11 +2217,11 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc // set the correct locale for the stats printing write_stats = true; setlocale(LC_NUMERIC, ""); - if ((fstats = fopen("hardnested_stats.txt","a")) == NULL) { + if ((fstats = fopen("hardnested_stats.txt","a")) == NULL) { PrintAndLogEx(WARNING, "Could not create/open file hardnested_stats.txt"); return 3; } - + for (uint32_t i = 0; i < tests; i++) { start_time = msclock(); print_progress_header(); @@ -2241,7 +2241,7 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc init_allbitflips_array(); init_nonce_memory(); update_reduction_rate(0.0, true); - + simulate_acquire_nonces(); set_test_state(best_first_bytes[0]); @@ -2252,7 +2252,7 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc fprintf(fstats, "%" PRIu16 ";%1.1f;", sums[first_byte_Sum], log(p_K0[first_byte_Sum])/log(2.0)); fprintf(fstats, "%" PRIu16 ";%1.1f;", sums[nonces[best_first_bytes[0]].sum_a8_guess[0].sum_a8_idx], log(p_K[nonces[best_first_bytes[0]].sum_a8_guess[0].sum_a8_idx])/log(2.0)); fprintf(fstats, "%" PRIu16 ";", real_sum_a8); - + #ifdef DEBUG_KEY_ELIMINATION failstr[0] = '\0'; #endif @@ -2263,7 +2263,7 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc float expected_brute_force1 = (float)num_odd * num_even / 2.0; float expected_brute_force2 = nonces[best_first_bytes[0]].expected_num_brute_force; fprintf(fstats, "%1.1f;%1.1f;", log(expected_brute_force1)/log(2.0), log(expected_brute_force2)/log(2.0)); - + if (expected_brute_force1 < expected_brute_force2) { hardnested_print_progress(num_acquired_nonces, "(Ignoring Sum(a8) properties)", expected_brute_force1, 0); set_test_state(best_first_byte_smallest_bitarray); @@ -2289,7 +2289,7 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc for (uint8_t j = 0; j < NUM_SUMS && !key_found; j++) { float expected_brute_force = nonces[best_first_bytes[0]].expected_num_brute_force; sprintf(progress_text, "(%d. guess: Sum(a8) = %" PRIu16 ")", j+1, sums[nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx]); - hardnested_print_progress(num_acquired_nonces, progress_text, expected_brute_force, 0); + hardnested_print_progress(num_acquired_nonces, progress_text, expected_brute_force, 0); if (sums[nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx] != real_sum_a8) { sprintf(progress_text, "(Estimated Sum(a8) is WRONG! Correct Sum(a8) = %" PRIu16 ")", real_sum_a8); hardnested_print_progress(num_acquired_nonces, progress_text, expected_brute_force, 0); @@ -2314,7 +2314,7 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc #else fprintf(fstats, "%1.0f;%d\n", log(num_keys_tested)/log(2.0), (float)num_keys_tested/brute_force_per_second, key_found); #endif - + free_nonces_memory(); free_bitarray(all_bitflips_bitarray[ODD_STATE]); free_bitarray(all_bitflips_bitarray[EVEN_STATE]); @@ -2357,7 +2357,7 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc free_bitarray(all_bitflips_bitarray[EVEN_STATE]); free_sum_bitarrays(); free_part_sum_bitarrays(); - + return is_OK; } } @@ -2368,7 +2368,7 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc } else { known_target_key = -1; } - + Tests(); free_bitflip_bitarrays(); @@ -2378,14 +2378,14 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc uint32_t num_even = nonces[best_first_byte_smallest_bitarray].num_states_bitarray[EVEN_STATE]; float expected_brute_force1 = (float)num_odd * num_even / 2.0; float expected_brute_force2 = nonces[best_first_bytes[0]].expected_num_brute_force; - + if (expected_brute_force1 < expected_brute_force2) { hardnested_print_progress(num_acquired_nonces, "(Ignoring Sum(a8) properties)", expected_brute_force1, 0); set_test_state(best_first_byte_smallest_bitarray); add_bitflip_candidates(best_first_byte_smallest_bitarray); Tests2(); maximum_states = 0; - + for (statelist_t *sl = candidates; sl != NULL; sl = sl->next) { maximum_states += (uint64_t)sl->len[ODD_STATE] * sl->len[EVEN_STATE]; } @@ -2400,20 +2400,20 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc free_candidates_memory(candidates); candidates = NULL; } else { - + pre_XOR_nonces(); prepare_bf_test_nonces(nonces, best_first_bytes[0]); - + for (uint8_t j = 0; j < NUM_SUMS && !key_found; j++) { float expected_brute_force = nonces[best_first_bytes[0]].expected_num_brute_force; sprintf(progress_text, "(%d. guess: Sum(a8) = %" PRIu16 ")", j+1, sums[nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx]); - hardnested_print_progress(num_acquired_nonces, progress_text, expected_brute_force, 0); - + hardnested_print_progress(num_acquired_nonces, progress_text, expected_brute_force, 0); + if (trgkey != NULL && sums[nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx] != real_sum_a8) { sprintf(progress_text, "(Estimated Sum(a8) is WRONG! Correct Sum(a8) = %" PRIu16 ")", real_sum_a8); hardnested_print_progress(num_acquired_nonces, progress_text, expected_brute_force, 0); } - + generate_candidates(first_byte_Sum, nonces[best_first_bytes[0]].sum_a8_guess[j].sum_a8_idx); key_found = brute_force(foundkey); free_statelist_cache(); @@ -2429,7 +2429,7 @@ int mfnestedhard(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint8_t trgBloc } } - + free_nonces_memory(); free_bitarray(all_bitflips_bitarray[ODD_STATE]); free_bitarray(all_bitflips_bitarray[EVEN_STATE]); diff --git a/client/cmdhfmfp.c b/client/cmdhfmfp.c index 348a4a9c9..ade39b9bc 100644 --- a/client/cmdhfmfp.c +++ b/client/cmdhfmfp.c @@ -34,10 +34,10 @@ static const uint8_t DefaultKey[16] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, static int CmdHelp(const char *Cmd); int CmdHFMFPInfo(const char *cmd) { - + if (cmd && strlen(cmd) > 0) PrintAndLogEx(WARNING, "command don't have any parameters.\n"); - + // info about 14a part CmdHF14AInfo(""); @@ -47,16 +47,16 @@ int CmdHFMFPInfo(const char *cmd) { UsbCommand resp; WaitForResponse(CMD_ACK,&resp); - + iso14a_card_select_t card; memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - + if (select_status == 1 || select_status == 2) { PrintAndLogEx(NORMAL, "----------------------------------------------"); PrintAndLogEx(NORMAL, "Mifare Plus info:"); - + // MIFARE Type Identification Procedure // https://www.nxp.com/docs/en/application-note/AN10833.pdf uint16_t ATQA = card.atqa[0] + (card.atqa[1] << 8); @@ -64,7 +64,7 @@ int CmdHFMFPInfo(const char *cmd) { if (ATQA == 0x0002) PrintAndLogEx(INFO, "ATQA: Mifare Plus 4k 4bUID"); if (ATQA == 0x0044) PrintAndLogEx(INFO, "ATQA: Mifare Plus 2k 7bUID"); if (ATQA == 0x0042) PrintAndLogEx(INFO, "ATQA: Mifare Plus 4k 7bUID"); - + uint8_t SLmode = 0xff; if (card.sak == 0x08) { PrintAndLogEx(INFO, "SAK: Mifare Plus 2k 7bUID"); @@ -98,7 +98,7 @@ int CmdHFMFPInfo(const char *cmd) { } } } - + if (SLmode != 0xff) PrintAndLogEx(INFO, "Mifare Plus SL mode: SL%d", SLmode); else @@ -106,9 +106,9 @@ int CmdHFMFPInfo(const char *cmd) { } else { PrintAndLogEx(INFO, "Mifare Plus info not available."); } - + DropField(); - + return 0; } @@ -118,8 +118,8 @@ int CmdHFMFPWritePerso(const char *cmd) { uint8_t key[64] = {0}; int keyLen = 0; - CLIParserInit("hf mfp wrp", - "Executes Write Perso command. Can be used in SL0 mode only.", + CLIParserInit("hf mfp wrp", + "Executes Write Perso command. Can be used in SL0 mode only.", "Usage:\n\thf mfp wrp 4000 000102030405060708090a0b0c0d0e0f -> write key (00..0f) to key number 4000 \n" "\thf mfp wrp 4000 -> write default key(0xff..0xff) to key number 4000"); @@ -131,19 +131,19 @@ int CmdHFMFPWritePerso(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool verbose = arg_get_lit(1); CLIGetHexWithReturn(2, keyNum, &keyNumLen); CLIGetHexWithReturn(3, key, &keyLen); CLIParserFree(); - + mfpSetVerboseMode(verbose); - + if (!keyLen) { memmove(key, DefaultKey, 16); keyLen = 16; } - + if (keyNumLen != 2) { PrintAndLogEx(ERR, "Key number length must be 2 bytes instead of: %d", keyNumLen); return 1; @@ -161,7 +161,7 @@ int CmdHFMFPWritePerso(const char *cmd) { PrintAndLogEx(ERR, "Exchange error: %d", res); return res; } - + if (datalen != 3) { PrintAndLogEx(ERR, "Command must return 3 bytes instead of: %d", datalen); return 1; @@ -172,7 +172,7 @@ int CmdHFMFPWritePerso(const char *cmd) { return 1; } PrintAndLogEx(INFO, "Write OK."); - + return 0; } @@ -186,8 +186,8 @@ int CmdHFMFPInitPerso(const char *cmd) { uint8_t data[250] = {0}; int datalen = 0; - CLIParserInit("hf mfp initp", - "Executes Write Perso command for all card's keys. Can be used in SL0 mode only.", + CLIParserInit("hf mfp initp", + "Executes Write Perso command for all card's keys. Can be used in SL0 mode only.", "Usage:\n\thf mfp initp 000102030405060708090a0b0c0d0e0f -> fill all the keys with key (00..0f)\n" "\thf mfp initp -vv -> fill all the keys with default key(0xff..0xff) and show all the data exchange"); @@ -198,7 +198,7 @@ int CmdHFMFPInitPerso(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool verbose = arg_get_lit(1); bool verbose2 = arg_get_lit(1) > 1; CLIGetHexWithReturn(2, key, &keyLen); @@ -208,7 +208,7 @@ int CmdHFMFPInitPerso(const char *cmd) { PrintAndLogEx(ERR, "Key length must be 16 bytes instead of: %d", keyLen); return 1; } - + if (!keyLen) memmove(key, DefaultKey, 16); @@ -226,7 +226,7 @@ int CmdHFMFPInitPerso(const char *cmd) { break; } } - + mfpSetVerboseMode(verbose); for (int i = 0; i < sizeof(CardAddresses) / 2; i++) { keyNum[0] = CardAddresses[i] >> 8; @@ -241,20 +241,20 @@ int CmdHFMFPInitPerso(const char *cmd) { } } } - + DropField(); - + if (res) return res; - + PrintAndLogEx(INFO, "Done."); - + return 0; } int CmdHFMFPCommitPerso(const char *cmd) { - CLIParserInit("hf mfp commitp", - "Executes Commit Perso command. Can be used in SL0 mode only.", + CLIParserInit("hf mfp commitp", + "Executes Commit Perso command. Can be used in SL0 mode only.", "Usage:\n\thf mfp commitp -> \n"); void* argtable[] = { @@ -264,12 +264,12 @@ int CmdHFMFPCommitPerso(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool verbose = arg_get_lit(1); CLIParserFree(); - + mfpSetVerboseMode(verbose); - + uint8_t data[250] = {0}; int datalen = 0; @@ -278,7 +278,7 @@ int CmdHFMFPCommitPerso(const char *cmd) { PrintAndLogEx(ERR, "Exchange error: %d", res); return res; } - + if (datalen != 3) { PrintAndLogEx(ERR, "Command must return 3 bytes instead of: %d", datalen); return 1; @@ -298,9 +298,9 @@ int CmdHFMFPAuth(const char *cmd) { int keynlen = 0; uint8_t key[250] = {0}; int keylen = 0; - - CLIParserInit("hf mfp auth", - "Executes AES authentication command for Mifare Plus card", + + CLIParserInit("hf mfp auth", + "Executes AES authentication command for Mifare Plus card", "Usage:\n\thf mfp auth 4000 000102030405060708090a0b0c0d0e0f -> executes authentication\n" "\thf mfp auth 9003 FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF -v -> executes authentication and shows all the system data\n"); @@ -312,17 +312,17 @@ int CmdHFMFPAuth(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool verbose = arg_get_lit(1); CLIGetHexWithReturn(2, keyn, &keynlen); CLIGetHexWithReturn(3, key, &keylen); CLIParserFree(); - + if (keynlen != 2) { PrintAndLogEx(ERR, "ERROR: must be 2 bytes long instead of: %d", keynlen); return 1; } - + if (keylen != 16) { PrintAndLogEx(ERR, "ERROR: must be 16 bytes long instead of: %d", keylen); return 1; @@ -335,9 +335,9 @@ int CmdHFMFPRdbl(const char *cmd) { uint8_t keyn[2] = {0}; uint8_t key[250] = {0}; int keylen = 0; - - CLIParserInit("hf mfp rdbl", - "Reads several blocks from Mifare Plus card.", + + CLIParserInit("hf mfp rdbl", + "Reads several blocks from Mifare Plus card.", "Usage:\n\thf mfp rdbl 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read block 0 data\n" "\thf mfp rdbl 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data\n"); @@ -352,7 +352,7 @@ int CmdHFMFPRdbl(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, false); - + bool verbose = arg_get_lit(1); int blocksCount = arg_get_int_def(2, 1); bool keyB = arg_get_lit(3); @@ -360,19 +360,19 @@ int CmdHFMFPRdbl(const char *cmd) { uint32_t blockn = arg_get_int(5); CLIGetHexWithReturn(6, key, &keylen); CLIParserFree(); - + mfpSetVerboseMode(verbose); if (!keylen) { memmove(key, DefaultKey, 16); keylen = 16; } - + if (blockn > 255) { PrintAndLogEx(ERR, " must be in range [0..255] instead of: %d", blockn); return 1; } - + if (keylen != 16) { PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); return 1; @@ -383,25 +383,25 @@ int CmdHFMFPRdbl(const char *cmd) { PrintAndLogEx(ERR, "blocks count must be less than 3 instead of: %d", blocksCount); return 1; } - + if (blocksCount > 1 && mfIsSectorTrailer(blockn)) { PrintAndLog("WARNING: trailer!"); } - + uint8_t sectorNum = mfSectorNum(blockn & 0xff); uint16_t uKeyNum = 0x4000 + sectorNum * 2 + (keyB ? 1 : 0); keyn[0] = uKeyNum >> 8; keyn[1] = uKeyNum & 0xff; if (verbose) PrintAndLogEx(INFO, "--block:%d sector[%d]:%02x key:%04x", blockn, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); - + mf4Session session; int res = MifareAuth4(&session, keyn, key, true, true, verbose); if (res) { PrintAndLogEx(ERR, "Authentication error: %d", res); return res; } - + uint8_t data[250] = {0}; int datalen = 0; uint8_t mac[8] = {0}; @@ -410,12 +410,12 @@ int CmdHFMFPRdbl(const char *cmd) { PrintAndLogEx(ERR, "Read error: %d", res); return res; } - + if (datalen && data[0] != 0x90) { PrintAndLogEx(ERR, "Card read error: %02x %s", data[0], mfpGetErrorDescription(data[0])); return 6; } - + if (datalen != 1 + blocksCount * 16 + 8 + 2) { PrintAndLogEx(ERR, "Error return length:%d", datalen); return 5; @@ -435,11 +435,11 @@ int CmdHFMFPRdbl(const char *cmd) { PrintAndLogEx(WARNING, "WARNING: mac not equal..."); PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[blocksCount * 16 + 1], 8)); PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8)); - } else { + } else { if(verbose) PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[blocksCount * 16 + 1], 8)); } - + return 0; } @@ -447,9 +447,9 @@ int CmdHFMFPRdsc(const char *cmd) { uint8_t keyn[2] = {0}; uint8_t key[250] = {0}; int keylen = 0; - - CLIParserInit("hf mfp rdsc", - "Reads one sector from Mifare Plus card.", + + CLIParserInit("hf mfp rdsc", + "Reads one sector from Mifare Plus card.", "Usage:\n\thf mfp rdsc 0 000102030405060708090a0b0c0d0e0f -> executes authentication and read sector 0 data\n" "\thf mfp rdsc 1 -v -> executes authentication and shows sector 1 data with default key 0xFF..0xFF and some additional data\n"); @@ -463,44 +463,44 @@ int CmdHFMFPRdsc(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, false); - + bool verbose = arg_get_lit(1); bool keyB = arg_get_lit(2); bool plain = arg_get_lit(3); uint32_t sectorNum = arg_get_int(4); CLIGetHexWithReturn(5, key, &keylen); CLIParserFree(); - + mfpSetVerboseMode(verbose); if (!keylen) { memmove(key, DefaultKey, 16); keylen = 16; } - + if (sectorNum > 39) { PrintAndLogEx(ERR, " must be in range [0..39] instead of: %d", sectorNum); return 1; } - + if (keylen != 16) { PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); return 1; } - + uint16_t uKeyNum = 0x4000 + sectorNum * 2 + (keyB ? 1 : 0); keyn[0] = uKeyNum >> 8; keyn[1] = uKeyNum & 0xff; if (verbose) PrintAndLogEx(INFO, "--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); - + mf4Session session; int res = MifareAuth4(&session, keyn, key, true, true, verbose); if (res) { PrintAndLogEx(ERR, "Authentication error: %d", res); return res; } - + uint8_t data[250] = {0}; int datalen = 0; uint8_t mac[8] = {0}; @@ -511,7 +511,7 @@ int CmdHFMFPRdsc(const char *cmd) { DropField(); return res; } - + if (datalen && data[0] != 0x90) { PrintAndLogEx(ERR, "Card read error: %02x %s", data[0], mfpGetErrorDescription(data[0])); DropField(); @@ -524,18 +524,18 @@ int CmdHFMFPRdsc(const char *cmd) { } PrintAndLogEx(INFO, "data[%03d]: %s", n, sprint_hex(&data[1], 16)); - + if (memcmp(&data[1 + 16], mac, 8)) { PrintAndLogEx(WARNING, "WARNING: mac on block %d not equal...", n); PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[1 + 16], 8)); PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8)); - } else { + } else { if(verbose) PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1 + 16], 8)); } } DropField(); - + return 0; } @@ -545,9 +545,9 @@ int CmdHFMFPWrbl(const char *cmd) { int keylen = 0; uint8_t datain[250] = {0}; int datainlen = 0; - - CLIParserInit("hf mfp wrbl", - "Writes one block to Mifare Plus card.", + + CLIParserInit("hf mfp wrbl", + "Writes one block to Mifare Plus card.", "Usage:\n\thf mfp wrbl 1 ff0000000000000000000000000000ff 000102030405060708090a0b0c0d0e0f -> writes block 1 data\n" "\thf mfp wrbl 2 ff0000000000000000000000000000ff -v -> writes block 2 data with default key 0xFF..0xFF and some additional data\n"); @@ -561,26 +561,26 @@ int CmdHFMFPWrbl(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, false); - + bool verbose = arg_get_lit(1); bool keyB = arg_get_lit(2); uint32_t blockNum = arg_get_int(3); CLIGetHexWithReturn(4, datain, &datainlen); CLIGetHexWithReturn(5, key, &keylen); CLIParserFree(); - + mfpSetVerboseMode(verbose); if (!keylen) { memmove(key, DefaultKey, 16); keylen = 16; } - + if (blockNum > 39) { PrintAndLogEx(ERR, " must be in range [0..255] instead of: %d", blockNum); return 1; } - + if (keylen != 16) { PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", keylen); return 1; @@ -590,14 +590,14 @@ int CmdHFMFPWrbl(const char *cmd) { PrintAndLogEx(ERR, " must be 16 bytes long instead of: %d", datainlen); return 1; } - + uint8_t sectorNum = mfSectorNum(blockNum & 0xff); uint16_t uKeyNum = 0x4000 + sectorNum * 2 + (keyB ? 1 : 0); keyn[0] = uKeyNum >> 8; keyn[1] = uKeyNum & 0xff; if (verbose) PrintAndLogEx(INFO, "--block:%d sector[%d]:%02x key:%04x", blockNum & 0xff, mfNumBlocksPerSector(sectorNum), sectorNum, uKeyNum); - + mf4Session session; int res = MifareAuth4(&session, keyn, key, true, true, verbose); if (res) { @@ -614,37 +614,37 @@ int CmdHFMFPWrbl(const char *cmd) { DropField(); return res; } - + if (datalen != 3 && (datalen != 3 + 8)) { PrintAndLogEx(ERR, "Error return length:%d", datalen); DropField(); return 5; } - + if (datalen && data[0] != 0x90) { PrintAndLogEx(ERR, "Card write error: %02x %s", data[0], mfpGetErrorDescription(data[0])); DropField(); return 6; } - + if (memcmp(&data[1], mac, 8)) { PrintAndLogEx(WARNING, "WARNING: mac not equal..."); PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[1], 8)); PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8)); - } else { + } else { if(verbose) PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1], 8)); } - + DropField(); - PrintAndLogEx(INFO, "Write OK."); + PrintAndLogEx(INFO, "Write OK."); return 0; } int CmdHFMFPMAD(const char *cmd) { - CLIParserInit("hf mfp mad", - "Checks and prints Mifare Application Directory (MAD)", + CLIParserInit("hf mfp mad", + "Checks and prints Mifare Application Directory (MAD)", "Usage:\n\thf mfp mad -> shows MAD if exists\n" "\thf mfp mad -a 03e1 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> shows NDEF data if exists\n"); @@ -657,7 +657,7 @@ int CmdHFMFPMAD(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool verbose = arg_get_lit(1); uint8_t aid[2] = {0}; int aidlen; @@ -666,30 +666,30 @@ int CmdHFMFPMAD(const char *cmd) { int keylen; CLIGetHexWithReturn(3, key, &keylen); bool keyB = arg_get_lit(4); - + CLIParserFree(); - + if (aidlen != 2 && keylen > 0) { PrintAndLogEx(WARNING, "do not need a key without aid."); } uint8_t sector0[16 * 4] = {0}; uint8_t sector10[16 * 4] = {0}; - + if (mfpReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector0, verbose)) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); return 2; } - + if (verbose) { for(int i = 0; i < 4; i ++) - PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(§or0[i * 16], 16)); + PrintAndLogEx(NORMAL, "[%d] %s", i, sprint_hex(§or0[i * 16], 16)); } bool haveMAD2 = false; MAD1DecodeAndPrint(sector0, verbose, &haveMAD2); - + if (haveMAD2) { if (mfpReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector10, verbose)) { PrintAndLogEx(NORMAL, ""); @@ -703,7 +703,7 @@ int CmdHFMFPMAD(const char *cmd) { if (aidlen == 2) { uint16_t aaid = (aid[0] << 8) + aid[1]; PrintAndLogEx(NORMAL, "\n-------------- AID 0x%04x ---------------", aaid); - + uint16_t mad[7 + 8 + 8 + 8 + 8] = {0}; size_t madlen = 0; if (MADDecode(sector0, sector10, mad, &madlen)) { @@ -716,7 +716,7 @@ int CmdHFMFPMAD(const char *cmd) { if (keylen == 16) { memcpy(akey, key, 16); } - + for (int i = 0; i < madlen; i++) { if (aaid == mad[i]) { uint8_t vsector[16 * 4] = {0}; @@ -725,20 +725,20 @@ int CmdHFMFPMAD(const char *cmd) { PrintAndLogEx(ERR, "read sector %d error.", i + 1); return 2; } - + for(int j = 0; j < (verbose ? 4 : 3); j ++) - PrintAndLogEx(NORMAL, " [%03d] %s", (i + 1) * 4 + j, sprint_hex(&vsector[j * 16], 16)); + PrintAndLogEx(NORMAL, " [%03d] %s", (i + 1) * 4 + j, sprint_hex(&vsector[j * 16], 16)); } - } + } } - + return 0; } int CmdHFMFPNDEF(const char *cmd) { - CLIParserInit("hf mfp ndef", - "Prints NFC Data Exchange Format (NDEF)", + CLIParserInit("hf mfp ndef", + "Prints NFC Data Exchange Format (NDEF)", "Usage:\n\thf mfp ndef -> shows NDEF data\n" "\thf mfp ndef -a 03e1 -k d3f7d3f7d3f7d3f7d3f7d3f7d3f7d3f7 -> shows NDEF data with custom AID and key\n"); @@ -751,7 +751,7 @@ int CmdHFMFPNDEF(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool verbose = arg_get_lit(1); bool verbose2 = arg_get_lit(1) > 1; uint8_t aid[2] = {0}; @@ -761,38 +761,38 @@ int CmdHFMFPNDEF(const char *cmd) { int keylen; CLIGetHexWithReturn(3, key, &keylen); bool keyB = arg_get_lit(4); - + CLIParserFree(); uint16_t ndefAID = 0x03e1; if (aidlen == 2) ndefAID = (aid[0] << 8) + aid[1]; - + uint8_t ndefkey[16] = {0}; memcpy(ndefkey, g_mifarep_ndef_key, 16); if (keylen == 16) { memcpy(ndefkey, key, 16); } - + uint8_t sector0[16 * 4] = {0}; uint8_t sector10[16 * 4] = {0}; uint8_t data[4096] = {0}; int datalen = 0; PrintAndLogEx(NORMAL, ""); - + if (mfpReadSector(MF_MAD1_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector0, verbose)) { PrintAndLogEx(ERR, "read sector 0 error. card don't have MAD or don't have MAD on default keys."); return 2; } - + bool haveMAD2 = false; int res = MADCheck(sector0, NULL, verbose, &haveMAD2); if (res) { PrintAndLogEx(ERR, "MAD error %d.", res); return res; } - + if (haveMAD2) { if (mfpReadSector(MF_MAD2_SECTOR, MF_KEY_A, (uint8_t *)g_mifarep_mad_key, sector10, verbose)) { PrintAndLogEx(ERR, "read sector 0x10 error. card don't have MAD or don't have MAD on default keys."); @@ -815,25 +815,25 @@ int CmdHFMFPNDEF(const char *cmd) { PrintAndLogEx(ERR, "read sector %d error.", i + 1); return 2; } - + memcpy(&data[datalen], vsector, 16 * 3); datalen += 16 * 3; - + printf("."); } } printf(" OK\n"); - + if (!datalen) { PrintAndLogEx(ERR, "no NDEF data."); return 11; } - + if (verbose2) { PrintAndLogEx(NORMAL, "NDEF data:"); dump_buffer(data, datalen, stdout, 1); } - + NDEFDecodeAndPrint(data, datalen, verbose); return 0; diff --git a/client/cmdhfmfu.c b/client/cmdhfmfu.c index 8b27d9b22..c24ba6407 100644 --- a/client/cmdhfmfu.c +++ b/client/cmdhfmfu.c @@ -61,7 +61,7 @@ uint32_t UL_TYPES_ARRAY[MAX_UL_TYPES] = { 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_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, MAX_ULEV1a_BLOCKS, MAX_NTAG_213, MAX_NTAG_216, MAX_UL_NANO_40 }; @@ -69,13 +69,13 @@ uint8_t UL_MEMORY_ARRAY[MAX_UL_TYPES] = { //------------------------------------ // Pwd & Pack generation Stuff //------------------------------------ -const uint32_t c_D[] = { - 0x6D835AFC, 0x7D15CD97, 0x0942B409, 0x32F9C923, 0xA811FB02, 0x64F121E8, - 0xD1CC8B4E, 0xE8873E6F, 0x61399BBB, 0xF1B91926, 0xAC661520, 0xA21A31C9, - 0xD424808D, 0xFE118E07, 0xD18E728D, 0xABAC9E17, 0x18066433, 0x00E18E79, - 0x65A77305, 0x5AE9E297, 0x11FC628C, 0x7BB3431F, 0x942A8308, 0xB2F8FD20, +const uint32_t c_D[] = { + 0x6D835AFC, 0x7D15CD97, 0x0942B409, 0x32F9C923, 0xA811FB02, 0x64F121E8, + 0xD1CC8B4E, 0xE8873E6F, 0x61399BBB, 0xF1B91926, 0xAC661520, 0xA21A31C9, + 0xD424808D, 0xFE118E07, 0xD18E728D, 0xABAC9E17, 0x18066433, 0x00E18E79, + 0x65A77305, 0x5AE9E297, 0x11FC628C, 0x7BB3431F, 0x942A8308, 0xB2F8FD20, 0x5728B869, 0x30726D5A -}; +}; void transform_D(uint8_t* ru) { //Transform @@ -101,12 +101,12 @@ void transform_D(uint8_t* ru) { ru[6] = (v2 >> 16) & 0xFF; ru[7] = (v2 >> 24) & 0xFF; } - + // Certain pwd generation algo nickname A. -uint32_t ul_ev1_pwdgenA(uint8_t* uid) { +uint32_t ul_ev1_pwdgenA(uint8_t* uid) { uint8_t pos = (uid[3] ^ uid[4] ^ uid[5] ^ uid[6]) % 32; - + uint32_t xortable[] = { 0x4f2711c1, 0x07D7BB83, 0x9636EF07, 0xB5F4460E, 0xF271141C, 0x7D7BB038, 0x636EF871, 0x5F4468E3, 0x271149C7, 0xD7BB0B8F, 0x36EF8F1E, 0xF446863D, 0x7114947A, 0x7BB0B0F5, 0x6EF8F9EB, 0x44686BD7, @@ -116,7 +116,7 @@ uint32_t ul_ev1_pwdgenA(uint8_t* uid) { uint8_t entry[] = {0x00,0x00,0x00,0x00}; uint8_t pwd[] = {0x00,0x00,0x00,0x00}; - + num_to_bytes( xortable[pos], 4, entry); pwd[0] = entry[0] ^ uid[1] ^ uid[2] ^ uid[3]; @@ -131,7 +131,7 @@ uint32_t ul_ev1_pwdgenA(uint8_t* uid) { uint32_t ul_ev1_pwdgenB(uint8_t* uid) { uint8_t pwd[] = {0x00,0x00,0x00,0x00}; - + pwd[0] = uid[1] ^ uid[3] ^ 0xAA; pwd[1] = uid[2] ^ uid[4] ^ 0x55; pwd[2] = uid[3] ^ uid[5] ^ 0xAA; @@ -157,8 +157,8 @@ uint32_t ul_ev1_pwdgenC(uint8_t* uid){ } return BSWAP_32(pwd); } -// Certain pwd generation algo nickname D. -// a.k.a xzy +// Certain pwd generation algo nickname D. +// a.k.a xzy uint32_t ul_ev1_pwdgenD(uint8_t* uid){ uint8_t i; //Rotate @@ -166,9 +166,9 @@ uint32_t ul_ev1_pwdgenD(uint8_t* uid){ uint8_t ru[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //Rotated UID for (i = 0; i < 7; i++) ru[(i + r) & 7] = uid[i]; - + transform_D(ru); - + //Calc key uint32_t pwd = 0; //Key as int r = (ru[0] + ru[2] + ru[4] + ru[6]) & 3; //Offset @@ -195,11 +195,11 @@ uint16_t ul_ev1_packgenD(uint8_t* uid){ uint8_t ru[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; //Rotated UID for (i = 0; i < 7; i++) ru[(i + r) & 7] = uid[i]; - + transform_D(ru); - + //Calc pack - uint32_t p = 0; + uint32_t p = 0; for (i = 0; i < 8; i++) p += ru[i] * 13; @@ -208,12 +208,12 @@ uint16_t ul_ev1_packgenD(uint8_t* uid){ } int ul_ev1_pwdgen_selftest(){ - + uint8_t uid1[] = {0x04, 0x11, 0x12, 0x11, 0x12, 0x11, 0x10}; uint32_t pwd1 = ul_ev1_pwdgenA(uid1); PrintAndLogEx(NORMAL, "UID | %s | %08X | %s", sprint_hex(uid1,7), pwd1, (pwd1 == 0x8432EB17)?"OK":"->8432EB17<-"); - uint8_t uid2[] = {0x04, 0x1f, 0x98, 0xea, 0x1e, 0x3e, 0x81}; + uint8_t uid2[] = {0x04, 0x1f, 0x98, 0xea, 0x1e, 0x3e, 0x81}; uint32_t pwd2 = ul_ev1_pwdgenB(uid2); PrintAndLogEx(NORMAL, "UID | %s | %08X | %s", sprint_hex(uid2,7), pwd2, (pwd2 == 0x5fd37eca)?"OK":"->5fd37eca<--"); @@ -228,7 +228,7 @@ int ul_ev1_pwdgen_selftest(){ } //------------------------------------ -// get version nxp product type +// get version nxp product type char *getProductTypeStr( uint8_t id){ static char buf[20]; @@ -243,9 +243,9 @@ char *getProductTypeStr( uint8_t id){ } /* - The 7 MSBits (=n) code the storage size itself based on 2^n, + The 7 MSBits (=n) code the storage size itself based on 2^n, the LSBit is set to '0' if the size is exactly 2^n - and set to '1' if the storage size is between 2^n and 2^(n+1). + and set to '1' if the storage size is between 2^n and 2^(n+1). */ char *getUlev1CardSizeStr( uint8_t fsize ){ @@ -259,8 +259,8 @@ char *getUlev1CardSizeStr( uint8_t fsize ){ // is LSB set? if ( fsize & 1 ) sprintf(retStr, "%02X, (%u <-> %u bytes)",fsize, usize, lsize); - else - sprintf(retStr, "%02X, (%u bytes)", fsize, lsize); + else + sprintf(retStr, "%02X, (%u bytes)", fsize, lsize); return buf; } @@ -291,7 +291,7 @@ static int ul_select( iso14a_card_select_t *card ){ UsbCommand resp; bool ans = false; ans = WaitForResponseTimeout(CMD_ACK, &resp, 1500); - + if (!ans || resp.arg[0] < 1) { PrintAndLogEx(WARNING, "iso14443a card select failed"); DropField(); @@ -354,7 +354,7 @@ static int ulev1_requestAuthentication( uint8_t *pwd, uint8_t *pack, uint16_t pa int len = ul_send_cmd_raw(cmd, sizeof(cmd), pack, packLength); // NACK tables different tags, but between 0-9 is a NEGATIVE response. // ACK == 0xA - if ( len == 1 && pack[0] <= 0x09 ) + if ( len == 1 && pack[0] <= 0x09 ) return -1; return len; } @@ -381,7 +381,7 @@ static int ul_auth_select( iso14a_card_select_t *card, TagTypeUL_t tagtype, bool } static int ulev1_getVersion( uint8_t *response, uint16_t responseLength ){ - uint8_t cmd[] = {MIFARE_ULEV1_VERSION}; + uint8_t cmd[] = {MIFARE_ULEV1_VERSION}; int len = ul_send_cmd_raw(cmd, sizeof(cmd), response, responseLength); return len; } @@ -410,7 +410,7 @@ static int ulev1_readSignature( uint8_t *response, uint16_t responseLength ){ // Fudan check checks for which error is given for a command with incorrect crc // NXP UL chip responds with 01, fudan 00. // other possible checks: -// send a0 + crc +// send a0 + crc // UL responds with 00, fudan doesn't respond // or // send a200 + crc @@ -422,7 +422,7 @@ static int ulev1_readSignature( uint8_t *response, uint16_t responseLength ){ // make sure field is off before calling this function static int ul_fudan_check( void ){ iso14a_card_select_t card; - if ( !ul_select(&card) ) + if ( !ul_select(&card) ) return UL_ERROR; UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_NO_DISCONNECT | ISO14A_NO_RATS, 4, 0}}; @@ -459,7 +459,7 @@ static int ul_print_default( uint8_t *data){ case 0xc6: PrintAndLogEx(NORMAL, " IC type : SLE 66R32P 5120 Bytes"); break; //512 pages /2 sectors } } - // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 + // CT (cascade tag byte) 0x88 xor SN0 xor SN1 xor SN2 int crc0 = 0x88 ^ data[0] ^ data[1] ^data[2]; if ( data[3] == crc0 ) PrintAndLogEx(NORMAL, " BCC0 : %02X, Ok", data[3]); @@ -494,7 +494,7 @@ static int ndef_print_CC(uint8_t *data) { PrintAndLogEx(NORMAL, "--- NDEF Message"); PrintAndLogEx(NORMAL, "Capability Container: %s", sprint_hex(data,4) ); - PrintAndLogEx(NORMAL, " %02X : NDEF Magic Number", data[0]); + PrintAndLogEx(NORMAL, " %02X : NDEF Magic Number", data[0]); PrintAndLogEx(NORMAL, " %02X : version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0F); PrintAndLogEx(NORMAL, " %02X : Physical Memory Size: %d bytes", data[2], (data[2] + 1) * 8); if ( data[2] == 0x96 ) @@ -506,8 +506,8 @@ static int ndef_print_CC(uint8_t *data) { else if ( data[2] == 0x6D ) PrintAndLogEx(NORMAL, " %02X : NDEF Memory Size: %d bytes", data[2], 872); - PrintAndLogEx(NORMAL, " %02X : %s / %s", data[3], - (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", + PrintAndLogEx(NORMAL, " %02X : %s / %s", data[3], + (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", (data[3] & 0x0F)==0 ? "Write access granted without any security" : (data[3] & 0x0F)==0x0F ? "No write access granted at all" : "(RFU)"); return 0; } @@ -517,15 +517,15 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces){ spc[10]=0x00; char *spacer = spc + (10-spaces); - if ( tagtype & UL ) + if ( tagtype & UL ) PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight (MF0ICU1) %s", spacer, (tagtype & MAGIC) ? "" : "" ); else if ( tagtype & UL_C) PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight C (MF0ULC) %s", spacer, (tagtype & MAGIC) ? "" : "" ); else if ( tagtype & UL_NANO_40) - PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight Nano 40bytes (MF0UNH00)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight Nano 40bytes (MF0UNH00)", spacer); else if ( tagtype & UL_EV1_48) - PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)", spacer); - else if ( tagtype & UL_EV1_128) + PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight EV1 48bytes (MF0UL1101)", spacer); + else if ( tagtype & UL_EV1_128) PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight EV1 128bytes (MF0UL2101)", spacer); else if ( tagtype & UL_EV1 ) PrintAndLogEx(NORMAL, "%sTYPE : MIFARE Ultralight EV1 UNKNOWN", spacer); @@ -546,14 +546,14 @@ int ul_print_type(uint32_t tagtype, uint8_t spaces){ else if ( tagtype & NTAG_216 ) PrintAndLogEx(NORMAL, "%sTYPE : NTAG 216 888bytes (NT2H1611G0DU)", spacer); else if ( tagtype & NTAG_216_F ) - PrintAndLogEx(NORMAL, "%sTYPE : NTAG 216F 888bytes (NT2H1611F0DTL)", spacer); + PrintAndLogEx(NORMAL, "%sTYPE : NTAG 216F 888bytes (NT2H1611F0DTL)", spacer); else if ( tagtype & NTAG_I2C_1K ) PrintAndLogEx(NORMAL, "%sTYPE : NTAG I%sC 888bytes (NT3H1101FHK)", spacer, "\xFD"); - else if ( tagtype & NTAG_I2C_2K ) + else if ( tagtype & NTAG_I2C_2K ) PrintAndLogEx(NORMAL, "%sTYPE : NTAG I%sC 1904bytes (NT3H1201FHK)", spacer, "\xFD"); else if ( tagtype & NTAG_I2C_1K_PLUS ) PrintAndLogEx(NORMAL, "%sTYPE : NTAG I%sC plus 888bytes (NT3H2111FHK)", spacer, "\xFD"); - else if ( tagtype & NTAG_I2C_2K_PLUS ) + else if ( tagtype & NTAG_I2C_2K_PLUS ) PrintAndLogEx(NORMAL, "%sTYPE : NTAG I%sC plus 1912bytes (NT3H2211FHK)", spacer, "\xFD"); else if ( tagtype & MY_D ) PrintAndLogEx(NORMAL, "%sTYPE : INFINEON my-d\x99 (SLE 66RxxS)", spacer); @@ -617,29 +617,29 @@ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t st uint8_t vctid = data[5]; PrintAndLogEx(NORMAL, " cfg0 [%u/0x%02X] : %s", startPage, startPage, sprint_hex(data, 4)); - + if ( (tagtype & (NTAG_213_F | NTAG_216_F)) ) { uint8_t mirror_conf = (data[0] & 0xC0); uint8_t mirror_byte = (data[0] & 0x30); bool sleep_en = (data[0] & 0x08); strg_mod_en = (data[0] & 0x04); uint8_t fdp_conf = (data[0] & 0x03); - + switch (mirror_conf) { case 0: PrintAndLogEx(NORMAL, " - no ASCII mirror"); break; case 1: PrintAndLogEx(NORMAL, " - UID ASCII mirror"); break; case 2: PrintAndLogEx(NORMAL, " - NFC counter ASCII mirror"); break; - case 3: PrintAndLogEx(NORMAL, " - UID and NFC counter ASCII mirror"); break; + case 3: PrintAndLogEx(NORMAL, " - UID and NFC counter ASCII mirror"); break; default: break; } - - PrintAndLogEx(NORMAL, " - SLEEP mode %s", (sleep_en) ? "enabled":"disabled"); - + + PrintAndLogEx(NORMAL, " - SLEEP mode %s", (sleep_en) ? "enabled":"disabled"); + switch (fdp_conf) { case 0: PrintAndLogEx(NORMAL, " - no field detect"); break; case 1: PrintAndLogEx(NORMAL, " - enabled by first State-of-Frame (start of communication)"); break; case 2: PrintAndLogEx(NORMAL, " - enabled by selection of the tag"); break; - case 3: PrintAndLogEx(NORMAL, " - enabled by field presence"); break; + case 3: PrintAndLogEx(NORMAL, " - enabled by field presence"); break; default: break; } // valid mirror start page and byte position within start page. @@ -656,14 +656,14 @@ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t st case 2: { PrintAndLogEx(NORMAL, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, ( data[2]>= 0x4 && data[2] <= 0xE0) ? "OK":"Invalid value"); break;} case 3: { PrintAndLogEx(NORMAL, " mirror start block %02X | byte pos %02X - %s", data[2], mirror_byte, ( data[2]>= 0x4 && data[2] <= 0xDC) ? "OK":"Invalid value"); break;} default: break; - } + } } } PrintAndLogEx(NORMAL, " - strong modulation mode %s", (strg_mod_en) ? "enabled":"disabled"); - + if ( data[3] < 0xff ) PrintAndLogEx(NORMAL, " - page %d and above need authentication",data[3]); - else + else PrintAndLogEx(NORMAL, " - pages don't need authentication"); PrintAndLogEx(NORMAL, " cfg1 [%u/0x%02X] : %s", startPage + 1, startPage + 1, sprint_hex(data+4, 4) ); @@ -671,10 +671,10 @@ static int ulev1_print_configuration(uint32_t tagtype, uint8_t *data, uint8_t st PrintAndLogEx(NORMAL, " - Unlimited password attempts"); else PrintAndLogEx(NORMAL, " - Max number of password attempts is %d", authlim); - + PrintAndLogEx(NORMAL, " - NFC counter %s", (nfc_cnf_en) ? "enabled":"disabled"); PrintAndLogEx(NORMAL, " - NFC counter %s", (nfc_cnf_prot_pwd) ? "not protected":"password protection enabled"); - + PrintAndLogEx(NORMAL, " - user configuration %s", cfglck ? "permanently locked":"writeable"); PrintAndLogEx(NORMAL, " - %s access is protected with password", prot ? "read and write":"write"); PrintAndLogEx(NORMAL, " - %02X, Virtual Card Type Identifier is %s default", vctid, (vctid==0x05)? "":"not"); @@ -701,8 +701,8 @@ static int ulev1_print_counters(){ } static int ulev1_print_signature( uint8_t *data, uint8_t len){ - PrintAndLogEx(NORMAL, "\n--- Tag Signature"); - PrintAndLogEx(NORMAL, "IC signature public key name : NXP NTAG21x (2013)"); + PrintAndLogEx(NORMAL, "\n--- Tag Signature"); + PrintAndLogEx(NORMAL, "IC signature public key name : NXP NTAG21x (2013)"); PrintAndLogEx(NORMAL, "IC signature public key value : %s", sprint_hex(public_ecda_key, PUBLIC_ECDA_KEYLEN) ); PrintAndLogEx(NORMAL, " Elliptic curve parameters : secp128r1"); PrintAndLogEx(NORMAL, " Tag ECC Signature : %s", sprint_hex(data, len)); @@ -747,22 +747,22 @@ static int ulc_magic_test(){ returnValue = ( !memcmp(nonce1, nonce2, 11) ) ? UL_C_MAGIC : UL_C; } else { returnValue = UL; - } + } DropField(); return returnValue; } */ static int ul_magic_test(){ // Magic Ultralight tests - // 1) take present UID, and try to write it back. OBSOLETE + // 1) take present UID, and try to write it back. OBSOLETE // 2) make a wrong length write to page0, and see if tag answers with ACK/NACK: iso14a_card_select_t card; - if ( !ul_select(&card) ) + if ( !ul_select(&card) ) return UL_ERROR; int status = ul_comp_write(0, NULL, 0); DropField(); - if ( status == 0 ) + if ( status == 0 ) return MAGIC; return 0; } @@ -777,7 +777,7 @@ uint32_t GetHF14AMfU_Type(void){ if (!ul_select(&card)) return UL_ERROR; - // Ultralight - ATQA / SAK + // Ultralight - ATQA / SAK if ( card.atqa[1] != 0x00 || card.atqa[0] != 0x44 || card.sak != 0x00 ) { //PrintAndLogEx(NORMAL, "Tag is not Ultralight | NTAG | MY-D [ATQA: %02X %02X SAK: %02X]\n", card.atqa[1], card.atqa[0], card.sak); DropField(); @@ -828,7 +828,7 @@ uint32_t GetHF14AMfU_Type(void){ DropField(); if (status > 1) { tagtype = UL_C; - } else { + } else { // need to re-select after authentication error if ( !ul_select(&card) ) return UL_ERROR; @@ -850,12 +850,12 @@ uint32_t GetHF14AMfU_Type(void){ } } if (tagtype & UL) { - tagtype = ul_fudan_check(); + tagtype = ul_fudan_check(); DropField(); } } else { DropField(); - // Infinition MY-D tests Exam high nibble + // Infinition MY-D tests Exam high nibble uint8_t nib = (card.uid[1] & 0xf0) >> 4; switch ( nib ){ // case 0: tagtype = SLE66R35E7; break; //or SLE 66R35E7 - mifare compat... should have different sak/atqa for mf 1k @@ -929,7 +929,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); ul_print_type(tagtype, 6); - // Swap endianness + // Swap endianness if (swapEndian && hasAuthKey) authkeyptr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4 ); if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; @@ -957,10 +957,10 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLogEx(WARNING, "Error: tag didn't answer to READ UL-C"); DropField(); return status; - } - if (status == 16) + } + if (status == 16) ulc_print_configuration(ulc_conf); - else + else locked = true; if ((tagtype & MAGIC)) { @@ -976,7 +976,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } else { DropField(); - // if we called info with key, just return + // if we called info with key, just return if ( hasAuthKey ) return 1; // also try to diversify default keys.. look into CmdHF14AMfuGenDiverseKeys @@ -989,13 +989,13 @@ int CmdHF14AMfUInfo(const char *Cmd){ memcpy(keySwap, SwapEndian64(key,16,8), 16); ulc_print_3deskey(keySwap); return 1; - } + } } return 1; } } - // do counters and signature first (don't neet auth) + // do counters and signature first (don't neet auth) // ul counters are different than ntag counters if ((tagtype & (UL_EV1_48 | UL_EV1_128 | UL_EV1))) { @@ -1006,7 +1006,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } // NTAG counters? - + // Read signature if ((tagtype & (UL_EV1_48 | UL_EV1_128 | UL_EV1 | UL_NANO_40 | NTAG_213 | NTAG_213_F | NTAG_215 | NTAG_216 | NTAG_216_F | NTAG_I2C_1K | NTAG_I2C_2K | NTAG_I2C_1K_PLUS | NTAG_I2C_2K_PLUS))) { uint8_t ulev1_signature[32] = {0x00}; @@ -1040,7 +1040,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ uint8_t startconfigblock = 0; uint8_t ulev1_conf[16] = {0x00}; - + // config blocks always are last 4 pages for (uint8_t i = 0; i < MAX_UL_TYPES; i++) { if (tagtype & UL_TYPES_ARRAY[i]) { @@ -1048,7 +1048,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ break; } } - + if (startconfigblock){ // if we know where the config block is... status = ul_read(startconfigblock, ulev1_conf, sizeof(ulev1_conf)); if ( status == -1 ) { @@ -1074,7 +1074,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ if ( !authlim && !hasAuthKey ) { PrintAndLogEx(NORMAL, "\n--- Known EV1/NTAG passwords."); len = 0; - + // test pwd gen A num_to_bytes( ul_ev1_pwdgenA(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); @@ -1084,7 +1084,7 @@ int CmdHF14AMfUInfo(const char *Cmd){ } if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; - + // test pwd gen B num_to_bytes( ul_ev1_pwdgenB(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); @@ -1102,9 +1102,9 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLogEx(SUCCESS, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); goto out; } - + if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; - + // test pwd gen D num_to_bytes( ul_ev1_pwdgenD(card.uid), 4, key); len = ulev1_requestAuthentication(key, pack, sizeof(pack)); @@ -1112,9 +1112,9 @@ int CmdHF14AMfUInfo(const char *Cmd){ PrintAndLogEx(SUCCESS, "Found a default password: %s || Pack: %02X %02X",sprint_hex(key, 4), pack[0], pack[1]); goto out; } - - if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; - + + if (!ul_auth_select( &card, tagtype, hasAuthKey, authkeyptr, pack, sizeof(pack))) return -1; + for (uint8_t i = 0; i < KEYS_PWD_COUNT; ++i ) { key = default_pwd_pack[i]; len = ulev1_requestAuthentication(key, pack, sizeof(pack)); @@ -1140,7 +1140,7 @@ out: // int CmdHF14AMfUWrBl(const char *Cmd){ - int blockNo = -1; + int blockNo = -1; bool errors = false; bool hasAuthKey = false; bool hasPwdKey = false; @@ -1166,7 +1166,7 @@ int CmdHF14AMfUWrBl(const char *Cmd){ hasPwdKey = true; break; } - // UL-C size key + // UL-C size key keylen = param_gethex(Cmd, cmdp+1, data, 32); if (!keylen){ memcpy(authenticationkey, data, 16); @@ -1175,19 +1175,19 @@ int CmdHF14AMfUWrBl(const char *Cmd){ break; } PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); - errors = true; + errors = true; break; case 'b': blockNo = param_get8(Cmd, cmdp+1); if (blockNo < 0) { PrintAndLogEx(WARNING, "Wrong block number"); - errors = true; + errors = true; } cmdp += 2; break; case 'l': swapEndian = true; - cmdp++; + cmdp++; break; case 'd': if ( param_gethex(Cmd, cmdp+1, blockdata, 8) ) { @@ -1205,7 +1205,7 @@ int CmdHF14AMfUWrBl(const char *Cmd){ } //Validations if (errors || cmdp == 0) return usage_hf_mfu_wrbl(); - + if ( blockNo == -1 ) return usage_hf_mfu_wrbl(); // starting with getting tagtype TagTypeUL_t tagtype = GetHF14AMfU_Type(); @@ -1223,15 +1223,15 @@ int CmdHF14AMfUWrBl(const char *Cmd){ return usage_hf_mfu_wrbl(); } - // Swap endianness + // Swap endianness if (swapEndian && hasAuthKey) authKeyPtr = SwapEndian64(authenticationkey, 16, 8); if (swapEndian && hasPwdKey) authKeyPtr = SwapEndian64(authenticationkey, 4, 4); - if ( blockNo <= 3) + if ( blockNo <= 3) PrintAndLogEx(NORMAL, "Special Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4)); else PrintAndLogEx(NORMAL, "Block: %0d (0x%02X) [ %s]", blockNo, blockNo, sprint_hex(blockdata, 4)); - + //Send write Block UsbCommand c = {CMD_MIFAREU_WRITEBL, {blockNo}}; memcpy(c.d.asBytes, blockdata, 4); @@ -1244,7 +1244,7 @@ int CmdHF14AMfUWrBl(const char *Cmd){ c.arg[1] = 2; memcpy(c.d.asBytes+4, authKeyPtr, 4); } - + clearCommandBuffer(); SendCommand(&c); UsbCommand resp; @@ -1254,7 +1254,7 @@ int CmdHF14AMfUWrBl(const char *Cmd){ } else { PrintAndLogEx(WARNING, "Command execute timeout"); } - + return 0; } // @@ -1262,7 +1262,7 @@ int CmdHF14AMfUWrBl(const char *Cmd){ // int CmdHF14AMfURdBl(const char *Cmd){ - int blockNo = -1; + int blockNo = -1; bool errors = false; bool hasAuthKey = false; bool hasPwdKey = false; @@ -1286,7 +1286,7 @@ int CmdHF14AMfURdBl(const char *Cmd){ hasPwdKey = true; break; } - // UL-C size key + // UL-C size key keylen = param_gethex(Cmd, cmdp+1, data, 32); if (!keylen){ memcpy(authenticationkey, data, 16); @@ -1295,20 +1295,20 @@ int CmdHF14AMfURdBl(const char *Cmd){ break; } PrintAndLogEx(WARNING, "ERROR: Key is incorrect length\n"); - errors = true; + errors = true; break; case 'b': blockNo = param_get8(Cmd, cmdp+1); if (blockNo < 0) { PrintAndLogEx(WARNING, "Wrong block number"); - errors = true; + errors = true; } cmdp += 2; break; case 'l': swapEndian = true; - cmdp++; - break; + cmdp++; + break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -1317,7 +1317,7 @@ int CmdHF14AMfURdBl(const char *Cmd){ } //Validations if (errors || cmdp == 0) return usage_hf_mfu_rdbl(); - + if ( blockNo == -1 ) return usage_hf_mfu_rdbl(); // start with getting tagtype TagTypeUL_t tagtype = GetHF14AMfU_Type(); @@ -1335,10 +1335,10 @@ int CmdHF14AMfURdBl(const char *Cmd){ return usage_hf_mfu_rdbl(); } - // Swap endianness + // Swap endianness if (swapEndian && hasAuthKey) authKeyPtr = SwapEndian64(authenticationkey, 16, 8); if (swapEndian && hasPwdKey) authKeyPtr = SwapEndian64(authenticationkey, 4, 4); - + //Read Block UsbCommand c = {CMD_MIFAREU_READBL, {blockNo}}; if ( hasAuthKey ){ @@ -1349,7 +1349,7 @@ int CmdHF14AMfURdBl(const char *Cmd){ c.arg[1] = 2; memcpy(c.d.asBytes,authKeyPtr,4); } - + clearCommandBuffer(); SendCommand(&c); UsbCommand resp; @@ -1393,14 +1393,14 @@ int usage_hf_mfu_dump(void) { PrintAndLogEx(NORMAL, "Reads all pages from Ultralight, Ultralight-C, Ultralight EV1"); PrintAndLogEx(NORMAL, "NTAG 203, NTAG 210, NTAG 212, NTAG 213, NTAG 215, NTAG 216"); PrintAndLogEx(NORMAL, "and saves binary dump into the file `filename.bin` or `cardUID.bin`"); - PrintAndLogEx(NORMAL, "It autodetects card type.\n"); + PrintAndLogEx(NORMAL, "It autodetects card type.\n"); PrintAndLogEx(NORMAL, "Usage: hf mfu dump k l f p q <#pages>"); PrintAndLogEx(NORMAL, " Options :"); PrintAndLogEx(NORMAL, " k : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); - PrintAndLogEx(NORMAL, " f : filename w/o .bin to save the dump as"); - PrintAndLogEx(NORMAL, " p : starting Page number to manually set a page to start the dump at"); - PrintAndLogEx(NORMAL, " q : number of Pages to manually set how many pages to dump"); + PrintAndLogEx(NORMAL, " f : filename w/o .bin to save the dump as"); + PrintAndLogEx(NORMAL, " p : starting Page number to manually set a page to start the dump at"); + PrintAndLogEx(NORMAL, " q : number of Pages to manually set how many pages to dump"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mfu dump"); @@ -1419,7 +1419,7 @@ int usage_hf_mfu_restore(void){ PrintAndLogEx(NORMAL, " s : (optional) enable special write UID -MAGIC TAG ONLY-"); PrintAndLogEx(NORMAL, " e : (optional) enable special write version/signature -MAGIC NTAG 21* ONLY-"); PrintAndLogEx(NORMAL, " r : (optional) use the password found in dumpfile to configure tag. requires 'e' parameter to work"); - PrintAndLogEx(NORMAL, " f : filename w/o .bin to restore"); + PrintAndLogEx(NORMAL, " f : filename w/o .bin to restore"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mfu restore s f myfile"); @@ -1429,12 +1429,12 @@ int usage_hf_mfu_restore(void){ } int usage_hf_mfu_rdbl(void) { - PrintAndLogEx(NORMAL, "Read a block and print. It autodetects card type.\n"); + PrintAndLogEx(NORMAL, "Read a block and print. It autodetects card type.\n"); PrintAndLogEx(NORMAL, "Usage: hf mfu rdbl b k l\n"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " b : block to read"); PrintAndLogEx(NORMAL, " k : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); - PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); + PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mfu rdbl b 0"); @@ -1444,13 +1444,13 @@ int usage_hf_mfu_rdbl(void) { } int usage_hf_mfu_wrbl(void) { - PrintAndLogEx(NORMAL, "Write a block. It autodetects card type.\n"); + PrintAndLogEx(NORMAL, "Write a block. It autodetects card type.\n"); PrintAndLogEx(NORMAL, "Usage: hf mfu wrbl b d k l\n"); - PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " b : block to write"); PrintAndLogEx(NORMAL, " d : block data - (8 hex symbols)"); PrintAndLogEx(NORMAL, " k : (optional) key for authentication [UL-C 16bytes, EV1/NTAG 4bytes]"); - PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); + PrintAndLogEx(NORMAL, " l : (optional) swap entered key's endianness"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mfu wrbl b 0 d 01234567"); @@ -1463,9 +1463,9 @@ int usage_hf_mfu_eload(void) { PrintAndLogEx(NORMAL, "Hint: See script dumptoemul-mfu.lua to convert the .bin to the eml"); PrintAndLogEx(NORMAL, "Usage: hf mfu eload u [numblocks]"); PrintAndLogEx(NORMAL, " Options:"); - PrintAndLogEx(NORMAL, " h : this help"); + PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, " u : UL (required)"); - PrintAndLogEx(NORMAL, " [filename] : without `.eml` (required)"); + PrintAndLogEx(NORMAL, " [filename] : without `.eml` (required)"); PrintAndLogEx(NORMAL, " numblocks : number of blocks to load from eml file (optional)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " sample: hf mfu eload u filename"); @@ -1485,7 +1485,7 @@ int usage_hf_mfu_sim(void) { PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mfu sim t 7"); PrintAndLogEx(NORMAL, " hf mfu sim t 7 u 1122344556677\n"); - + return 0; } @@ -1497,7 +1497,7 @@ int usage_hf_mfu_ucauth(void) { PrintAndLogEx(NORMAL, " 3 : nfc key"); PrintAndLogEx(NORMAL, " 4 : all 0x01 key"); PrintAndLogEx(NORMAL, " 5 : all 0xff key"); - PrintAndLogEx(NORMAL, " 6 : 0x00-0xFF key"); + PrintAndLogEx(NORMAL, " 6 : 0x00-0xFF key"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " hf mfu cauth k"); PrintAndLogEx(NORMAL, " hf mfu cauth k 3"); @@ -1575,18 +1575,18 @@ void printMFUdumpEx(mfu_dump_t* card, uint16_t pages, uint8_t startpage) { uint8_t j = 0; bool lckbit = false; uint8_t *data = card->data; - + uint8_t lockbytes_sta[] = {0,0}; uint8_t lockbytes_dyn[] = {0,0,0}; bool bit_stat[16] = {0}; bool bit_dyn[16] = {0}; - - // Load static lock bytes. + + // Load static lock bytes. memcpy(lockbytes_sta, data+10, sizeof(lockbytes_sta)); for(j = 0; j < 16; j++){ bit_stat[j] = lockbytes_sta[j/8] & ( 1 <<(7-j%8)); } - + // Load dynamic lockbytes if available // TODO -- FIGURE OUT LOCK BYTES FOR TO EV1 and/or NTAG if ( pages == 44 ) { @@ -1598,7 +1598,7 @@ void printMFUdumpEx(mfu_dump_t* card, uint16_t pages, uint8_t startpage) { } PrintAndLogEx(NORMAL, "DYNAMIC LOCK: %s\n", sprint_hex(lockbytes_dyn,3)); } - + for (uint8_t i = 0; i < pages; ++i) { if ( i < 3 ) { PrintAndLogEx(NORMAL, "%3d/0x%02X | %s| | %s", i+startpage, i+startpage, sprint_hex(data + i * 4, 4), sprint_ascii(data + i * 4,4) ); @@ -1625,7 +1625,7 @@ void printMFUdumpEx(mfu_dump_t* card, uint16_t pages, uint8_t startpage) { case 20: case 21: case 22: - case 23: lckbit = bit_dyn[5]; break; + case 23: lckbit = bit_dyn[5]; break; case 24: case 25: case 26: @@ -1637,11 +1637,11 @@ void printMFUdumpEx(mfu_dump_t* card, uint16_t pages, uint8_t startpage) { case 32: case 33: case 34: - case 35: lckbit = bit_dyn[1]; break; + case 35: lckbit = bit_dyn[1]; break; case 36: case 37: case 38: - case 39: lckbit = bit_dyn[0]; break; + case 39: lckbit = bit_dyn[0]; break; case 40: lckbit = bit_dyn[12]; break; case 41: lckbit = bit_dyn[11]; break; case 42: lckbit = bit_dyn[10]; break; //auth0 @@ -1664,7 +1664,7 @@ int CmdHF14AMfUDump(const char *Cmd){ uint8_t data[1024] = {0x00}; memset(data, 0x00, sizeof(data)); - + bool hasAuthKey = false; int i = 0; int pages = 16; @@ -1726,12 +1726,12 @@ int CmdHF14AMfUDump(const char *Cmd){ if (errors) return usage_hf_mfu_dump(); //if we entered a key in little endian and set the swapEndian switch - switch it... - if (swapEndian && hasAuthKey) + if (swapEndian && hasAuthKey) authKeyPtr = SwapEndian64(authenticationkey, dataLen, (dataLen == 16) ? 8 : 4); TagTypeUL_t tagtype = GetHF14AMfU_Type(); if (tagtype == UL_ERROR) return -1; - + //get number of pages to read if (!manualPages) { for (uint8_t idx = 0; idx < MAX_UL_TYPES; idx++) { @@ -1772,16 +1772,16 @@ int CmdHF14AMfUDump(const char *Cmd){ PrintAndLogEx(FAILED, "Data exceeded Buffer size!"); bufferSize = sizeof(data); } - + if ( !GetFromDevice(BIG_BUF, data, bufferSize, startindex, NULL, 2500, false) ) { PrintAndLogEx(WARNING, "command execution time out"); return 1; } bool is_partial = (pages != bufferSize/4); - + pages = bufferSize/4; - + iso14a_card_select_t card; mfu_dump_t dump_file_data; uint8_t get_pack[] = {0,0}; @@ -1793,7 +1793,7 @@ int CmdHF14AMfUDump(const char *Cmd){ memset( get_signature, 0, sizeof(get_signature) ); // not ul_c and not std ul then attempt to collect info like - // VERSION, SIGNATURE, COUNTERS, TEARING, PACK, + // VERSION, SIGNATURE, COUNTERS, TEARING, PACK, if (!(tagtype & UL_C || tagtype & UL)) { //attempt to read pack if (!ul_auth_select( &card, tagtype, true, authKeyPtr, get_pack, sizeof(get_pack))) { @@ -1802,14 +1802,14 @@ int CmdHF14AMfUDump(const char *Cmd){ get_pack[1] = 0; } DropField(); - + // only add pack if not partial read, and complete pages read. if ( !is_partial && pages == card_mem_size) { - - // add pack to block read + + // add pack to block read memcpy(data + (pages*4) - 4, get_pack, sizeof(get_pack)); } - + if ( hasAuthKey ) ul_auth_select( &card, tagtype, hasAuthKey, authKeyPtr, dummy_pack, sizeof(dummy_pack)); else @@ -1820,13 +1820,13 @@ int CmdHF14AMfUDump(const char *Cmd){ ulev1_readTearing(i, get_tearing+i, 1); ulev1_readCounter(i, get_counter, sizeof(get_counter) ); } - + DropField(); if ( hasAuthKey ) ul_auth_select( &card, tagtype, hasAuthKey, authKeyPtr, dummy_pack, sizeof(dummy_pack)); else ul_select(&card); - + ulev1_readSignature( get_signature, sizeof(get_signature)); DropField(); } @@ -1844,7 +1844,7 @@ int CmdHF14AMfUDump(const char *Cmd){ if (tagtype & UL_C){ //add 4 pages memcpy(data + pages*4, authKeyPtr, dataLen); - pages += dataLen/4; + pages += dataLen/4; } else { // 2nd page from end memcpy(data + (pages*4) - 8, authenticationkey, dataLen); } @@ -1859,22 +1859,22 @@ int CmdHF14AMfUDump(const char *Cmd){ memcpy(dump_file_data.data, data, pages*4); printMFUdumpEx(&dump_file_data, pages, startPage); - + // user supplied filename? if (fileNameLen < 1) { PrintAndLogEx(INFO, "Using UID as filename"); - - fptr += sprintf(fptr, "hf-mfu-"); + + fptr += sprintf(fptr, "hf-mfu-"); FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen); - } + } uint16_t datalen = pages*4 + DUMP_PREFIX_LENGTH; saveFile(filename, "bin", (uint8_t*)&dump_file_data, datalen); saveFileJSON(filename, "json", jsfMfuMemory, (uint8_t*)&dump_file_data, datalen); - - if ( is_partial ) + + if ( is_partial ) PrintAndLogEx(WARNING, "Partial dump created. (%d of %d blocks)", pages, card_mem_size); - + return 0; } @@ -1896,7 +1896,7 @@ int CmdHF14AMfURestore(const char *Cmd){ char tempStr[50] = {0}; char filename[FILE_PATH_SIZE] = {0}; - uint8_t authkey[16] = {0}; + uint8_t authkey[16] = {0}; uint8_t *p_authkey = authkey; uint8_t cmdp = 0, keylen = 0; bool hasKey = false; @@ -1910,7 +1910,7 @@ int CmdHF14AMfURestore(const char *Cmd){ UsbCommand c = {CMD_MIFAREU_WRITEBL, {0,0,0}}; memset(authkey, 0x00, sizeof(authkey)); - + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': @@ -1936,7 +1936,7 @@ int CmdHF14AMfURestore(const char *Cmd){ if (filelen > FILE_PATH_SIZE-5) filelen = FILE_PATH_SIZE-5; - + if (filelen < 1) sprintf(filename, "dumpdata.bin"); @@ -1963,11 +1963,11 @@ int CmdHF14AMfURestore(const char *Cmd){ //Validations if (errors || cmdp == 0) return usage_hf_mfu_restore(); - + if ((f = fopen(filename,"rb")) == NULL) { PrintAndLogEx(WARNING, "Could not find file " _YELLOW_(%s), filename); return 1; - } + } // get filesize to know how memory to allocate fseek(f, 0, SEEK_END); @@ -1994,16 +1994,16 @@ int CmdHF14AMfURestore(const char *Cmd){ free(dump); return 1; } - + PrintAndLogEx(INFO, "Restoring " _YELLOW_(%s)" to card", filename); - + mfu_dump_t *mem = (mfu_dump_t*)dump; uint8_t pages = (bytes_read-48)/4; - + // print dump printMFUdumpEx(mem, pages, 0); - - // Swap endianness + + // Swap endianness if (swapEndian && hasKey) { if ( keylen == 16 ) p_authkey = SwapEndian64(authkey, keylen, 8); @@ -2016,11 +2016,11 @@ int CmdHF14AMfURestore(const char *Cmd){ c.arg[1] = (keylen == 16) ? 1 : 2; memcpy(c.d.asBytes+4, p_authkey, keylen); } - + // write version, signature, pack // only magic NTAG cards if ( write_extra ) { - + #define MFU_NTAG_SPECIAL_PWD 0xF0 #define MFU_NTAG_SPECIAL_PACK 0xF1 #define MFU_NTAG_SPECIAL_VERSION 0xFA @@ -2040,13 +2040,13 @@ int CmdHF14AMfURestore(const char *Cmd){ clearCommandBuffer(); SendCommand(&c); wait4response(MFU_NTAG_SPECIAL_PWD); - + // copy the new key c.arg[1] = 2; memcpy(authkey, c.d.asBytes, 4); memcpy(c.d.asBytes+4, authkey, 4); } - + // pack c.arg[0] = MFU_NTAG_SPECIAL_PACK; c.d.asBytes[0] = mem->pack[0]; @@ -2057,7 +2057,7 @@ int CmdHF14AMfURestore(const char *Cmd){ clearCommandBuffer(); SendCommand(&c); wait4response(MFU_NTAG_SPECIAL_PACK); - + // Signature for (uint8_t s = MFU_NTAG_SPECIAL_SIGNATURE, i=0; s < MFU_NTAG_SPECIAL_SIGNATURE+8; s++, i += 4){ c.arg[0] = s; @@ -2065,26 +2065,26 @@ int CmdHF14AMfURestore(const char *Cmd){ PrintAndLogEx(NORMAL, "special SIG block written 0x%X - %s\n", s, sprint_hex(c.d.asBytes, 4) ); clearCommandBuffer(); SendCommand(&c); - wait4response(s); + wait4response(s); } - + // Version - for (uint8_t s = MFU_NTAG_SPECIAL_VERSION, i=0; s < MFU_NTAG_SPECIAL_VERSION+2; s++, i += 4){ + for (uint8_t s = MFU_NTAG_SPECIAL_VERSION, i=0; s < MFU_NTAG_SPECIAL_VERSION+2; s++, i += 4){ c.arg[0] = s; - memcpy(c.d.asBytes, mem->version+i, 4 ); + memcpy(c.d.asBytes, mem->version+i, 4 ); PrintAndLogEx(NORMAL, "special VERSION block written 0x%X - %s\n", s, sprint_hex(c.d.asBytes, 4) ); clearCommandBuffer(); SendCommand(&c); wait4response(s); } } - + PrintAndLogEx(INFO, "Restoring data blocks."); - // write all other data + // write all other data // Skip block 0,1,2,3 (only magic tags can write to them) // Skip last 5 blocks usually is configuration for (uint8_t b = 4; b < pages-5; b++) { - + //Send write Block c.arg[0] = b; memcpy(c.d.asBytes, mem->data + (b*4), 4); @@ -2094,14 +2094,14 @@ int CmdHF14AMfURestore(const char *Cmd){ printf("."); fflush(stdout); } PrintAndLogEx(NORMAL, "\n"); - + // write special data last if (write_special) { - + PrintAndLogEx(INFO, "Restoring configuration blocks.\n"); - + PrintAndLogEx(NORMAL, "authentication with keytype[%x] %s\n", (uint8_t)(c.arg[1] & 0xff), sprint_hex(p_authkey,4)); - + // otp, uid, lock, cfg1, cfg0, dynlockbits uint8_t blocks[] = {3, 0, 1, 2, pages-5, pages-4, pages-3}; for ( uint8_t i = 0; i < sizeof(blocks); i++){ @@ -2114,10 +2114,10 @@ int CmdHF14AMfURestore(const char *Cmd){ PrintAndLogEx(NORMAL, "special block written %u - %s\n", b, sprint_hex(c.d.asBytes, 4) ); } } - + DropField(); free(dump); - return 0; + return 0; } // // Load emulator with dump file @@ -2153,33 +2153,33 @@ int CmdHF14AMfucAuth(const char *Cmd){ //Change key to user defined one if (cmdp == 'k'){ keyNo = param_get8(Cmd, 1); - if(keyNo >= KEYS_3DES_COUNT) + if(keyNo >= KEYS_3DES_COUNT) errors = true; } if (cmdp == 'h') errors = true; - - if (errors) return usage_hf_mfu_ucauth(); + + if (errors) return usage_hf_mfu_ucauth(); uint8_t *key = default_3des_keys[keyNo]; if (ulc_authentication(key, true)) PrintAndLogEx(SUCCESS, "Authentication successful. 3des key: %s",sprint_hex(key, 16)); else PrintAndLogEx(WARNING, "Authentication failed"); - + return 0; } /** -A test function to validate that the polarssl-function works the same -was as the openssl-implementation. -Commented out, since it requires openssl +A test function to validate that the polarssl-function works the same +was as the openssl-implementation. +Commented out, since it requires openssl int CmdTestDES(const char * cmd) { - uint8_t key[16] = {0x00}; - - memcpy(key,key3_3des_data,16); + uint8_t key[16] = {0x00}; + + memcpy(key,key3_3des_data,16); DES_cblock RndA, RndB; PrintAndLogEx(NORMAL, "----------OpenSSL DES implementation----------"); @@ -2191,7 +2191,7 @@ int CmdTestDES(const char * cmd) DES_key_schedule ks1,ks2; DES_cblock key1,key2; - memcpy(key,key3_3des_data,16); + memcpy(key,key3_3des_data,16); memcpy(key1,key,8); memcpy(key2,key+8,8); @@ -2248,7 +2248,7 @@ int CmdTestDES(const char * cmd) rol(random_b,8); memcpy(random_a_and_b ,random_a,8); memcpy(random_a_and_b+8,random_b,8); - + PrintAndLogEx(NORMAL, " RA+B:%s",sprint_hex(random_a_and_b, 16)); des3_set2key_enc(&ctx, key); @@ -2263,26 +2263,26 @@ int CmdTestDES(const char * cmd) PrintAndLogEx(NORMAL, "enc(RA+B):%s",sprint_hex(random_a_and_b, 16)); } - return 0; + return 0; } **/ -// +// // Mifare Ultralight C - Set password // int CmdHF14AMfucSetPwd(const char *Cmd){ - uint8_t pwd[16] = {0x00}; + uint8_t pwd[16] = {0x00}; char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_ucsetpwd(); - + if (param_gethex(Cmd, 0, pwd, 32)) { PrintAndLogEx(WARNING, "Password must include 32 HEX symbols"); return 1; } - - UsbCommand c = {CMD_MIFAREUC_SETPWD}; + + UsbCommand c = {CMD_MIFAREUC_SETPWD}; memcpy( c.d.asBytes, pwd, 16); clearCommandBuffer(); SendCommand(&c); @@ -2298,7 +2298,7 @@ int CmdHF14AMfucSetPwd(const char *Cmd){ } else { PrintAndLogEx(WARNING, "command execution time out"); return 1; - } + } return 0; } @@ -2311,7 +2311,7 @@ int CmdHF14AMfucSetUid(const char *Cmd){ UsbCommand resp; uint8_t uid[7] = {0x00}; char cmdp = tolower(param_getchar(Cmd, 0)); - + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_ucsetuid(); if (param_gethex(Cmd, 0, uid, 14)) { @@ -2319,7 +2319,7 @@ int CmdHF14AMfucSetUid(const char *Cmd){ return 1; } - // read block2. + // read block2. c.arg[0] = 2; clearCommandBuffer(); SendCommand(&c); @@ -2331,7 +2331,7 @@ int CmdHF14AMfucSetUid(const char *Cmd){ // save old block2. uint8_t oldblock2[4] = {0x00}; memcpy(resp.d.asBytes, oldblock2, 4); - + // block 0. c.cmd = CMD_MIFAREU_WRITEBL; c.arg[0] = 0; @@ -2370,13 +2370,13 @@ int CmdHF14AMfucSetUid(const char *Cmd){ if (!WaitForResponseTimeout(CMD_ACK,&resp,1500) ) { PrintAndLogEx(WARNING, "Command execute timeout"); return 5; - } + } return 0; } int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ - uint8_t uid[4]; + uint8_t uid[4]; char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_gendiverse(); @@ -2389,13 +2389,13 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ WaitForResponse(CMD_ACK, &resp); iso14a_card_select_t card; memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - - uint64_t select_status = resp.arg[0]; + + uint64_t select_status = resp.arg[0]; // 0: couldn't read, // 1: OK, with ATS // 2: OK, no ATS // 3: proprietary Anticollision - + if ( select_status == 0 ) { PrintAndLogEx(WARNING, "iso14443a card select failed"); return 1; @@ -2404,33 +2404,33 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ PrintAndLogEx(WARNING, "Wrong sized UID, expected 4bytes got %d", card.uidlen); return 1; } - memcpy(uid, card.uid, sizeof(uid)); + memcpy(uid, card.uid, sizeof(uid)); } else { if (param_gethex(Cmd, 0, uid, 8)) return usage_hf_mfu_gendiverse(); } - - + + uint8_t iv[8] = { 0x00 }; uint8_t block = 0x01; - + uint8_t mifarekeyA[] = { 0xA0,0xA1,0xA2,0xA3,0xA4,0xA5 }; uint8_t mifarekeyB[] = { 0xB0,0xB1,0xB2,0xB3,0xB4,0xB5 }; uint8_t dkeyA[8] = { 0x00 }; uint8_t dkeyB[8] = { 0x00 }; - + uint8_t masterkey[] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xaa,0xbb,0xcc,0xdd,0xee,0xff }; - + uint8_t mix[8] = { 0x00 }; uint8_t divkey[8] = { 0x00 }; - + memcpy(mix, mifarekeyA, 4); - + mix[4] = mifarekeyA[4] ^ uid[0]; mix[5] = mifarekeyA[5] ^ uid[1]; mix[6] = block ^ uid[2]; mix[7] = uid[3]; - + mbedtls_des3_context ctx; mbedtls_des3_set2key_enc(&ctx, masterkey); @@ -2449,17 +2449,17 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ PrintAndLogEx(NORMAL, "Mifare key :\t %s", sprint_hex(mifarekeyA, sizeof(mifarekeyA))); PrintAndLogEx(NORMAL, "Message :\t %s", sprint_hex(mix, sizeof(mix))); PrintAndLogEx(NORMAL, "Diversified key: %s", sprint_hex(divkey+1, 6)); - + for (int i=0; i < sizeof(mifarekeyA); ++i){ dkeyA[i] = (mifarekeyA[i] << 1) & 0xff; dkeyA[6] |= ((mifarekeyA[i] >> 7) & 1) << (i+1); } - + for (int i=0; i < sizeof(mifarekeyB); ++i){ dkeyB[1] |= ((mifarekeyB[i] >> 7) & 1) << (i+1); dkeyB[2+i] = (mifarekeyB[i] << 1) & 0xff; } - + uint8_t zeros[8] = {0x00}; uint8_t newpwd[8] = {0x00}; uint8_t dmkey[24] = {0x00}; @@ -2467,7 +2467,7 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ memcpy(dmkey+8, dkeyB, 8); memcpy(dmkey+16, dkeyA, 8); memset(iv, 0x00, 8); - + mbedtls_des3_set3key_enc(&ctx, dmkey); mbedtls_des3_crypt_cbc(&ctx // des3_context @@ -2477,25 +2477,25 @@ int CmdHF14AMfuGenDiverseKeys(const char *Cmd){ , zeros // input , newpwd // output ); - + PrintAndLogEx(NORMAL, "\n-- DES version"); PrintAndLogEx(NORMAL, "Mifare dkeyA :\t %s", sprint_hex(dkeyA, sizeof(dkeyA))); PrintAndLogEx(NORMAL, "Mifare dkeyB :\t %s", sprint_hex(dkeyB, sizeof(dkeyB))); PrintAndLogEx(NORMAL, "Mifare ABA :\t %s", sprint_hex(dmkey, sizeof(dmkey))); PrintAndLogEx(NORMAL, "Mifare Pwd :\t %s", sprint_hex(newpwd, sizeof(newpwd))); - - // next. from the diversify_key method. + + // next. from the diversify_key method. return 0; } int CmdHF14AMfuPwdGen(const char *Cmd){ - - uint8_t uid[7] = {0x00}; + + uint8_t uid[7] = {0x00}; char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_hf_mfu_pwdgen(); - + if (cmdp == 't') return ul_ev1_pwdgen_selftest(); - + if ( cmdp == 'r') { // read uid from tag UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0}}; @@ -2505,7 +2505,7 @@ int CmdHF14AMfuPwdGen(const char *Cmd){ WaitForResponse(CMD_ACK, &resp); iso14a_card_select_t card; memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - + uint64_t select_status = resp.arg[0]; // 0: couldn't read // 1: OK with ATS @@ -2519,12 +2519,12 @@ int CmdHF14AMfuPwdGen(const char *Cmd){ PrintAndLogEx(WARNING, "Wrong sized UID, expected 7bytes got %d", card.uidlen); return 1; } - memcpy(uid, card.uid, sizeof(uid)); + memcpy(uid, card.uid, sizeof(uid)); } else { if (param_gethex(Cmd, 0, uid, 14)) return usage_hf_mfu_pwdgen(); } - + PrintAndLogEx(NORMAL, "---------------------------------"); PrintAndLogEx(NORMAL, " Using UID : %s", sprint_hex(uid, 7)); PrintAndLogEx(NORMAL, "---------------------------------"); @@ -2548,13 +2548,13 @@ static command_t CommandTable[] = { {"info", CmdHF14AMfUInfo, 0, "Tag information"}, {"dump", CmdHF14AMfUDump, 0, "Dump Ultralight / Ultralight-C / NTAG tag to binary file"}, {"restore", CmdHF14AMfURestore, 0, "Restore a dump onto a MFU MAGIC tag"}, - {"eload", CmdHF14AMfUeLoad, 0, "load Ultralight .eml dump file into emulator memory"}, + {"eload", CmdHF14AMfUeLoad, 0, "load Ultralight .eml dump file into emulator memory"}, {"rdbl", CmdHF14AMfURdBl, 0, "Read block"}, {"wrbl", CmdHF14AMfUWrBl, 0, "Write block"}, {"cauth", CmdHF14AMfucAuth, 0, "Authentication - Ultralight C"}, {"setpwd", CmdHF14AMfucSetPwd, 0, "Set 3des password - Ultralight-C"}, {"setuid", CmdHF14AMfucSetUid, 0, "Set UID - MAGIC tags only"}, - {"sim", CmdHF14AMfUSim, 0, "Simulate Ultralight from emulator memory"}, + {"sim", CmdHF14AMfUSim, 0, "Simulate Ultralight from emulator memory"}, {"gen", CmdHF14AMfuGenDiverseKeys , 1, "Generate 3des mifare diversified keys"}, {"pwdgen", CmdHF14AMfuPwdGen, 1, "Generate pwd from known algos"}, {NULL, NULL, 0, NULL} diff --git a/client/cmdhfmfu.h b/client/cmdhfmfu.h index b03444839..4a5528b83 100644 --- a/client/cmdhfmfu.h +++ b/client/cmdhfmfu.h @@ -12,7 +12,7 @@ #include "comms.h" #include "loclass/fileutils.h" -#define DUMP_PREFIX_LENGTH 48 +#define DUMP_PREFIX_LENGTH 48 typedef struct { uint8_t version[8]; @@ -20,7 +20,7 @@ typedef struct { uint8_t tearing[3]; uint8_t pack[2]; uint8_t tbo1[1]; - uint8_t signature[32]; + uint8_t signature[32]; //uint8_t counter[3]; uint8_t data[1024]; } mfu_dump_t; diff --git a/client/cmdhftopaz.c b/client/cmdhftopaz.c index 2f80b054c..64d4a6f5b 100644 --- a/client/cmdhftopaz.c +++ b/client/cmdhftopaz.c @@ -52,12 +52,12 @@ static int topaz_send_cmd_raw(uint8_t *cmd, uint8_t len, uint8_t *response) { if (resp.arg[0] > 0) { memcpy(response, resp.d.asBytes, resp.arg[0]); } - + return resp.arg[0]; } -// calculate CRC bytes and send topaz command, returns the length of the response (0 in case of error) +// calculate CRC bytes and send topaz command, returns the length of the response (0 in case of error) static int topaz_send_cmd(uint8_t *cmd, uint8_t len, uint8_t *response) { if (len > 1) { uint8_t b1, b2; @@ -88,7 +88,7 @@ static int topaz_select(uint8_t *atqa, uint8_t *rid_response) { topaz_switch_off_field(); return -2; // RID failed } - + return 0; // OK } @@ -102,7 +102,7 @@ static int topaz_rall(uint8_t *uid, uint8_t *response) { topaz_switch_off_field(); return -1; // RALL failed } - + return 0; } @@ -112,7 +112,7 @@ static int topaz_read_block(uint8_t *uid, uint8_t blockno, uint8_t *block_data) { uint8_t read8_cmd[] = {TOPAZ_READ8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t read8_response[11]; - + read8_cmd[1] = blockno; memcpy(&read8_cmd[10], uid, 4); if (!topaz_send_cmd(read8_cmd, sizeof(read8_cmd), read8_response)) { @@ -127,7 +127,7 @@ static int topaz_read_block(uint8_t *uid, uint8_t blockno, uint8_t *block_data) static int topaz_read_segment(uint8_t *uid, uint8_t segno, uint8_t *segment_data) { uint8_t rseg_cmd[] = {TOPAZ_RSEG, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}; uint8_t rseg_response[131]; - + rseg_cmd[1] = segno << 4; memcpy(&rseg_cmd[10], uid, 4); if (!topaz_send_cmd(rseg_cmd, sizeof(rseg_cmd), rseg_response)) { @@ -138,11 +138,11 @@ static int topaz_read_segment(uint8_t *uid, uint8_t segno, uint8_t *segment_data return 0; } -// search for the lock area descriptor for the lockable area including byteno +// search for the lock area descriptor for the lockable area including byteno static dynamic_lock_area_t *get_dynamic_lock_area(uint16_t byteno) { - dynamic_lock_area_t *lock_area; + dynamic_lock_area_t *lock_area; lock_area = topaz_tag.dynamic_lock_areas; - + while (lock_area != NULL) { if (byteno < lock_area->first_locked_byte) { lock_area = lock_area->next; @@ -158,7 +158,7 @@ static bool topaz_byte_is_locked(uint16_t byteno) { uint8_t *lockbits; uint16_t locked_bytes_per_bit; dynamic_lock_area_t *lock_area; - + if (byteno < TOPAZ_STATIC_MEMORY) { lockbits = &topaz_tag.data_blocks[0x0e][0]; locked_bytes_per_bit = 8; @@ -190,20 +190,20 @@ static int topaz_print_CC(uint8_t *data) { } PrintAndLogEx(NORMAL, "Capability Container: %02x %02x %02x %02x", data[0], data[1], data[2], data[3]); - PrintAndLogEx(NORMAL, " %02x: NDEF Magic Number", data[0]); + PrintAndLogEx(NORMAL, " %02x: NDEF Magic Number", data[0]); PrintAndLogEx(NORMAL, " %02x: version %d.%d supported by tag", data[1], (data[1] & 0xF0) >> 4, data[1] & 0x0f); uint16_t memsize = (data[2] + 1) * 8; topaz_tag.size = memsize; topaz_tag.dynamic_memory = calloc(memsize - TOPAZ_STATIC_MEMORY, sizeof(uint8_t)); PrintAndLogEx(NORMAL, " %02x: Physical Memory Size of this tag: %d bytes", data[2], memsize); - PrintAndLogEx(NORMAL, " %02x: %s / %s", data[3], - (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", + PrintAndLogEx(NORMAL, " %02x: %s / %s", data[3], + (data[3] & 0xF0) ? "(RFU)" : "Read access granted without any security", (data[3] & 0x0F)==0 ? "Write access granted without any security" : (data[3] & 0x0F)==0x0F ? "No write access granted at all" : "(RFU)"); - return 0; + return 0; } -// return type, length and value of a TLV, starting at memory position *TLV_ptr +// return type, length and value of a TLV, starting at memory position *TLV_ptr static void get_TLV(uint8_t **TLV_ptr, uint8_t *TLV_type, uint16_t *TLV_length, uint8_t **TLV_value) { *TLV_length = 0; *TLV_value = NULL; @@ -236,7 +236,7 @@ static void get_TLV(uint8_t **TLV_ptr, uint8_t *TLV_type, uint16_t *TLV_length, // lock area TLVs contain no information on the start of the respective lockable area. Lockable areas -// do not include the lock bits and reserved memory. We therefore need to adjust the start of the +// do not include the lock bits and reserved memory. We therefore need to adjust the start of the // respective lockable areas accordingly static void adjust_lock_areas(uint16_t block_start, uint16_t block_size) { dynamic_lock_area_t *lock_area = topaz_tag.dynamic_lock_areas; @@ -258,8 +258,8 @@ static void topaz_print_control_TLVs(uint8_t *memory) { bool lock_TLV_present = false; bool reserved_memory_control_TLV_present = false; uint16_t next_lockable_byte = 0x0f * 8; // first byte after static memory area - - while (*TLV_ptr != 0x03 && *TLV_ptr != 0xFD && *TLV_ptr != 0xFE) { + + while (*TLV_ptr != 0x03 && *TLV_ptr != 0xFD && *TLV_ptr != 0xFE) { // all Lock Control TLVs shall be present before the NDEF message TLV, the proprietary TLV (and the Terminator TLV) get_TLV(&TLV_ptr, &TLV_type, &TLV_length, &TLV_value); if (TLV_type == 0x01) { // a Lock Control TLV @@ -270,7 +270,7 @@ static void topaz_print_control_TLVs(uint8_t *memory) { uint16_t bytes_per_page = 1 << (TLV_value[2] & 0x0f); uint16_t bytes_locked_per_bit = 1 << (TLV_value[2] >> 4); uint16_t area_start = pages_addr * bytes_per_page + byte_offset; - PrintAndLogEx(NORMAL, "Lock Area of %d bits at byte offset 0x%04x. Each Lock Bit locks %d bytes.", + PrintAndLogEx(NORMAL, "Lock Area of %d bits at byte offset 0x%04x. Each Lock Bit locks %d bytes.", size_in_bits, area_start, bytes_locked_per_bit); @@ -294,7 +294,7 @@ static void topaz_print_control_TLVs(uint8_t *memory) { new->byte_offset = area_start; new->size_in_bits = size_in_bits; new->bytes_locked_per_bit = bytes_locked_per_bit; - next_lockable_byte += size_in_bits * bytes_locked_per_bit; + next_lockable_byte += size_in_bits * bytes_locked_per_bit; } if (TLV_type == 0x02) { // a Reserved Memory Control TLV uint8_t pages_addr = TLV_value[0] >> 4; @@ -302,7 +302,7 @@ static void topaz_print_control_TLVs(uint8_t *memory) { uint16_t size_in_bytes = TLV_value[1] ? TLV_value[1] : 256; uint8_t bytes_per_page = 1 << (TLV_value[2] & 0x0f); uint16_t area_start = pages_addr * bytes_per_page + byte_offset; - PrintAndLogEx(NORMAL, "Reserved Memory of %d bytes at byte offset 0x%02x.", + PrintAndLogEx(NORMAL, "Reserved Memory of %d bytes at byte offset 0x%02x.", size_in_bytes, area_start); reserved_memory_control_TLV_present = true; @@ -312,14 +312,14 @@ static void topaz_print_control_TLVs(uint8_t *memory) { } } } - + if (!lock_TLV_present) { PrintAndLogEx(NORMAL, "(No Lock Control TLV present)"); } - + if (!reserved_memory_control_TLV_present) { PrintAndLogEx(NORMAL, "(No Reserved Memory Control TLV present)"); - } + } } // read all of the dynamic memory @@ -329,7 +329,7 @@ static int topaz_read_dynamic_data(void){ PrintAndLogEx(WARNING, "Error while reading dynamic memory block %02x. Aborting...", 0x0f); return -1; } - + // read the remaining segments uint8_t max_segment = topaz_tag.size / 128 - 1; for (uint8_t segment = 1; segment <= max_segment; segment++) { @@ -337,10 +337,10 @@ static int topaz_read_dynamic_data(void){ PrintAndLogEx(WARNING, "Error while reading dynamic memory block %02x. Aborting...", 0x0f); return -1; } - } + } return 0; } - + // read and print the dynamic memory static void topaz_print_dynamic_data(void) { @@ -368,10 +368,10 @@ static void topaz_print_lifecycle_state(uint8_t *data) { } static void topaz_print_NDEF(uint8_t *data) { - // to be done. + // to be done. } - -// read a Topaz tag and print some useful information + +// read a Topaz tag and print some useful information int CmdHFTopazReader(const char *Cmd) { int status; uint8_t atqa[2]; @@ -382,7 +382,7 @@ int CmdHFTopazReader(const char *Cmd) { char ctmp = param_getchar(Cmd, 0); if ( ctmp == 'S' || ctmp == 's') verbose = false; - + status = topaz_select(atqa, rid_response); if (status == -1) { @@ -396,7 +396,7 @@ int CmdHFTopazReader(const char *Cmd) { topaz_switch_off_field(); return -1; } - + if (status == -2) { PrintAndLogEx(WARNING, "Error: tag didn't answer to RID"); topaz_switch_off_field(); @@ -405,14 +405,14 @@ int CmdHFTopazReader(const char *Cmd) { topaz_tag.HR01[0] = rid_response[0]; topaz_tag.HR01[1] = rid_response[1]; - + // ToDo: CRC check - PrintAndLogEx(NORMAL, "HR0 : %02x (%sa Topaz tag (%scapable of carrying a NDEF message), %s memory map)", rid_response[0], + PrintAndLogEx(NORMAL, "HR0 : %02x (%sa Topaz tag (%scapable of carrying a NDEF message), %s memory map)", rid_response[0], (rid_response[0] & 0xF0) == 0x10 ? "" : "not ", (rid_response[0] & 0xF0) == 0x10 ? "" : "not ", (rid_response[0] & 0x0F) == 0x01 ? "static" : "dynamic"); PrintAndLogEx(NORMAL, "HR1 : %02x", rid_response[1]); - + status = topaz_rall(uid_echo, rall_response); if (status == -1) { @@ -422,19 +422,19 @@ int CmdHFTopazReader(const char *Cmd) { } memcpy(topaz_tag.uid, rall_response+2, 7); - PrintAndLogEx(NORMAL, "UID : %02x %02x %02x %02x %02x %02x %02x", - topaz_tag.uid[6], - topaz_tag.uid[5], - topaz_tag.uid[4], - topaz_tag.uid[3], - topaz_tag.uid[2], - topaz_tag.uid[1], + PrintAndLogEx(NORMAL, "UID : %02x %02x %02x %02x %02x %02x %02x", + topaz_tag.uid[6], + topaz_tag.uid[5], + topaz_tag.uid[4], + topaz_tag.uid[3], + topaz_tag.uid[2], + topaz_tag.uid[1], topaz_tag.uid[0]); - - PrintAndLogEx(NORMAL, " UID[6] (Manufacturer Byte) = %02x, Manufacturer: %s", - topaz_tag.uid[6], + + PrintAndLogEx(NORMAL, " UID[6] (Manufacturer Byte) = %02x, Manufacturer: %s", + topaz_tag.uid[6], getTagInfo(topaz_tag.uid[6])); - + memcpy(topaz_tag.data_blocks, rall_response+2, 0x0f*8); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Static Data blocks 00 to 0c:"); @@ -449,14 +449,14 @@ int CmdHFTopazReader(const char *Cmd) { lockbits[8] = '\0'; PrintAndLogEx(NORMAL, " 0x%02x | 0x%02x | %s| %-3s", i, i*8, line, lockbits); } - + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Static Reserved block 0d:"); for (uint16_t j = 0; j < 8; j++) { sprintf(&line[3*j], "%02x ", topaz_tag.data_blocks[0x0d][j]); } PrintAndLogEx(NORMAL, " 0x%02x | 0x%02x | %s| %-3s", 0x0d, 0x0d*8, line, "n/a"); - + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Static Lockbits and OTP Bytes:"); for (uint16_t j = 0; j < 8; j++) { @@ -467,7 +467,7 @@ int CmdHFTopazReader(const char *Cmd) { PrintAndLogEx(NORMAL, ""); status = topaz_print_CC(&topaz_tag.data_blocks[1][0]); - + if (status == -1) { PrintAndLogEx(NORMAL, "No NDEF message data present"); topaz_switch_off_field(); @@ -476,14 +476,14 @@ int CmdHFTopazReader(const char *Cmd) { PrintAndLogEx(NORMAL, ""); topaz_print_control_TLVs(&topaz_tag.data_blocks[1][4]); - + PrintAndLogEx(NORMAL, ""); topaz_print_dynamic_data(); - + topaz_print_lifecycle_state(&topaz_tag.data_blocks[1][0]); topaz_print_NDEF(&topaz_tag.data_blocks[1][0]); - + topaz_switch_off_field(); return 0; } diff --git a/client/cmdhw.c b/client/cmdhw.c index ec7b42a1a..640729306 100644 --- a/client/cmdhw.c +++ b/client/cmdhw.c @@ -26,9 +26,9 @@ static int CmdHelp(const char *Cmd); static void lookupChipID(uint32_t iChipID, uint32_t mem_used) { char asBuff[120]; memset(asBuff, 0, sizeof(asBuff)); - uint32_t mem_avail = 0; + uint32_t mem_avail = 0; PrintAndLogEx(NORMAL, "\n [ Hardware ] "); - + switch(iChipID) { case 0x270B0A40: sprintf(asBuff,"AT91SAM7S512 Rev A"); break; case 0x270B0A4F: sprintf(asBuff,"AT91SAM7S512 Rev B"); break; @@ -69,19 +69,19 @@ static void lookupChipID(uint32_t iChipID, uint32_t mem_used) { case 12: mem_avail = 1024; break; case 14: mem_avail = 2048; break; } - + uint32_t mem_left = 0; - if ( mem_avail > 0 ) + if ( mem_avail > 0 ) mem_left = (mem_avail * 1024) - mem_used; - - PrintAndLogEx(NORMAL, " --= Nonvolatile Program Memory Size: %uK bytes, Used: %u bytes (%2.0f%%) Free: %u bytes (%2.0f%%)", - mem_avail, - mem_used, + + PrintAndLogEx(NORMAL, " --= Nonvolatile Program Memory Size: %uK bytes, Used: %u bytes (%2.0f%%) Free: %u bytes (%2.0f%%)", + mem_avail, + mem_used, mem_avail == 0 ? 0.0f : (float)mem_used/(mem_avail*1024)*100, mem_left, mem_avail == 0 ? 0.0f : (float)mem_left/(mem_avail*1024)*100 ); - + switch( (iChipID & 0xF000) >> 12 ) { case 0: sprintf(asBuff,"None"); break; case 1: sprintf(asBuff,"8K bytes"); break; @@ -140,7 +140,7 @@ static void lookupChipID(uint32_t iChipID, uint32_t mem_used) { case 1: sprintf(asBuff,"ROMless or on-chip Flash"); break; case 2: sprintf(asBuff,"Embedded Flash Memory"); break; case 3: sprintf(asBuff,"ROM and Embedded Flash Memory\nNVPSIZ is ROM size\nNVPSIZ2 is Flash size"); break; - case 4: sprintf(asBuff,"SRAM emulating ROM"); break; + case 4: sprintf(asBuff,"SRAM emulating ROM"); break; } PrintAndLogEx(NORMAL, " --= Nonvolatile Program Memory Type: %s",asBuff); } @@ -156,7 +156,7 @@ int CmdDetectReader(const char *Cmd) { PrintAndLogEx(NORMAL, "use 'detectreader' or 'detectreader l' or 'detectreader h'"); return 0; } - clearCommandBuffer(); + clearCommandBuffer(); SendCommand(&c); return 0; } @@ -211,11 +211,11 @@ int CmdReset(const char *Cmd) { */ int CmdSetDivisor(const char *Cmd) { UsbCommand c = {CMD_SET_LF_DIVISOR, {strtol(Cmd, NULL, 0), 0, 0}}; - + if (c.arg[0] < 19 || c.arg[0] > 255) { PrintAndLogEx(NORMAL, "divisor must be between 19 and 255"); return 1; - } + } // 12 000 000 (12Mhz) clearCommandBuffer(); SendCommand(&c); @@ -224,12 +224,12 @@ int CmdSetDivisor(const char *Cmd) { } int CmdSetMux(const char *Cmd) { - + if (strlen(Cmd) < 5) { PrintAndLogEx(NORMAL, "expected: lopkd | loraw | hipkd | hiraw"); return 1; } - + UsbCommand c = {CMD_SET_ADC_MUX}; if (strcmp(Cmd, "lopkd") == 0) c.arg[0] = 0; @@ -246,9 +246,9 @@ int CmdTune(const char *Cmd) { } int CmdVersion(const char *Cmd) { - + bool silent = (Cmd[0] == 's' || Cmd[0] == 'S'); - if ( silent ) + if ( silent ) return 0; UsbCommand c = {CMD_VERSION, {0, 0, 0}}; @@ -259,15 +259,15 @@ int CmdVersion(const char *Cmd) { #ifdef __WIN32 PrintAndLogEx(NORMAL, "\n [ Proxmark3 RFID instrument ]\n"); #else - PrintAndLogEx(NORMAL, "\n\e[34m [ Proxmark3 RFID instrument ]\e[0m\n"); -#endif + PrintAndLogEx(NORMAL, "\n\e[34m [ Proxmark3 RFID instrument ]\e[0m\n"); +#endif char s[50] = {0}; #if defined(WITH_FLASH) || defined(WITH_SMARTCARD) || defined(WITH_FPC) strncat(s, "build for RDV40 with ", sizeof(s) - strlen(s) - 1); #endif #ifdef WITH_FLASH strncat(s, "flashmem; ", sizeof(s) - strlen(s) - 1); -#endif +#endif #ifdef WITH_SMARTCARD strncat(s, "smartcard; ", sizeof(s) - strlen(s) - 1); #endif @@ -276,10 +276,10 @@ int CmdVersion(const char *Cmd) { #endif PrintAndLogEx(NORMAL, "\n [ CLIENT ]"); PrintAndLogEx(NORMAL, " client: iceman %s \n", s); - + PrintAndLogEx(NORMAL, (char*)resp.d.asBytes); - lookupChipID(resp.arg[0], resp.arg[1]); - } + lookupChipID(resp.arg[0], resp.arg[1]); + } PrintAndLogEx(NORMAL, "\n"); return 0; } @@ -301,7 +301,7 @@ int CmdPing(const char *Cmd) { if (WaitForResponseTimeout(CMD_ACK, &resp, 1000)) PrintAndLogEx(NORMAL, "Ping successful"); else - PrintAndLogEx(NORMAL, "Ping failed"); + PrintAndLogEx(NORMAL, "Ping failed"); return 0; } @@ -312,7 +312,7 @@ static command_t CommandTable[] = { #ifdef WITH_LCD {"lcd", CmdLCD, 0, " -- Send command/data to LCD"}, {"lcdreset", CmdLCDReset, 0, "Hardware reset LCD"}, -#endif +#endif {"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)"}, diff --git a/client/cmdlf.c b/client/cmdlf.c index 240a1d402..59dc12654 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -23,7 +23,7 @@ int usage_lf_cmdread(void) { PrintAndLogEx(NORMAL, " c Command bytes (in ones and zeros)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " ************* All periods in microseconds (ms)"); - PrintAndLogEx(NORMAL, " ************* Use lf config to configure options."); + PrintAndLogEx(NORMAL, " ************* Use lf config to configure options."); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf cmdread d 80 z 100 o 200 c 11000"); return 0; @@ -33,7 +33,7 @@ int usage_lf_read(void){ PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h This help"); PrintAndLogEx(NORMAL, " s silent run no printout"); - PrintAndLogEx(NORMAL, " d #samples # samples to collect (optional)"); + PrintAndLogEx(NORMAL, " d #samples # samples to collect (optional)"); PrintAndLogEx(NORMAL, "Use 'lf config' to set parameters."); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); @@ -79,7 +79,7 @@ int usage_lf_simfsk(void) { PrintAndLogEx(NORMAL, "FSK1 - where fc/8 = high and fc/5 = low"); PrintAndLogEx(NORMAL, "FSK1a - is inverted FSK1, ie: fc/5 = high and fc/8 = low"); PrintAndLogEx(NORMAL, "FSK2 - where fc/10 = high and fc/8 = low"); - PrintAndLogEx(NORMAL, "FSK2a - is inverted FSK2, ie: fc/10 = high and fc/8 = low"); + PrintAndLogEx(NORMAL, "FSK2a - is inverted FSK2, ie: fc/10 = high and fc/8 = low"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h This help"); @@ -176,10 +176,10 @@ int CmdLFCommandRead(const char *Cmd) { //Validations if (errors || cmdp == 0) return usage_lf_cmdread(); - + clearCommandBuffer(); SendCommand(&c); - + WaitForResponse(CMD_ACK, NULL); getSamples(0, true); return 0; @@ -197,9 +197,9 @@ int CmdFlexdemod(const char *Cmd) { int data[GraphTraceLen]; memcpy(data, GraphBuffer, GraphTraceLen); - + size_t size = GraphTraceLen; - + for (i = 0; i < GraphTraceLen; ++i) data[i] = (data[i] < 0) ? -1 : 1; @@ -213,7 +213,7 @@ int CmdFlexdemod(const char *Cmd) { if (i == (start + LONG_WAIT)) break; } - + if (start == size - LONG_WAIT) { PrintAndLogEx(NORMAL, "nothing to wait for"); return 0; @@ -221,7 +221,7 @@ int CmdFlexdemod(const char *Cmd) { data[start] = 4; data[start+1] = 0; - + uint8_t bits[64] = {0x00}; i = start; @@ -250,9 +250,9 @@ int CmdFlexdemod(const char *Cmd) { GraphTraceLen = 32 * 64; i = 0; for (bit = 0; bit < 64; bit++) { - + phase = (bits[bit] == 0) ? 0 : 1; - + for (j = 0; j < 32; j++) { GraphBuffer[i++] = phase; phase = !phase; @@ -317,7 +317,7 @@ int CmdLFSetConfig(const char *Cmd) { //Validations if (errors || cmdp == 0) return usage_lf_config(); - + //Bps is limited to 8 if (bps >> 4) bps = 8; @@ -352,9 +352,9 @@ bool lf_read(bool silent, uint32_t samples) { } int CmdLFRead(const char *Cmd) { - + if ( IsOffline() ) return 0; - + bool errors = false; bool silent = false; uint32_t samples = 0; @@ -387,9 +387,9 @@ int CmdLFRead(const char *Cmd) { int CmdLFSnoop(const char *Cmd) { uint8_t cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_lf_snoop(); - + UsbCommand c = {CMD_LF_SNOOP_RAW_ADC_SAMPLES,{0,0,0}}; - clearCommandBuffer(); + clearCommandBuffer(); SendCommand(&c); WaitForResponse(CMD_ACK, NULL); getSamples(0, false); @@ -414,11 +414,11 @@ int CmdLFSim(const char *Cmd) { int gap = 0; sscanf(Cmd, "%i", &gap); - // convert to bitstream if necessary + // convert to bitstream if necessary ChkBitstream(Cmd); PrintAndLogEx(DEBUG, "DEBUG: Sending [%d bytes]\n", GraphTraceLen); - + //can send only 512 bits at a time (1 byte sent per bit...) for (uint16_t i = 0; i < GraphTraceLen; i += USB_CMD_DATA_SIZE) { UsbCommand c = {CMD_UPLOAD_SIM_SAMPLES_125K, {i, FPGA_LF, 0}}; @@ -440,7 +440,7 @@ int CmdLFSim(const char *Cmd) { return 0; } -// by marshmellow - sim fsk data given clock, fcHigh, fcLow, invert +// by marshmellow - sim fsk data given clock, fcHigh, fcLow, invert // - allow pull data from DemodBuffer int CmdLFfskSim(const char *Cmd) { //might be able to autodetect FCs and clock from Graphbuffer if using demod buffer @@ -448,10 +448,10 @@ int CmdLFfskSim(const char *Cmd) { uint8_t fcHigh = 0, fcLow = 0, clk = 0; bool errors = false, separator = false; char hexData[64] = {0x00}; // store entered hex data - uint8_t data[255] = {0x00}; + uint8_t data[255] = {0x00}; int dataLen = 0; - uint8_t cmdp = 0; - + uint8_t cmdp = 0; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (param_getchar(Cmd, cmdp)){ case 'h': @@ -475,11 +475,11 @@ int CmdLFfskSim(const char *Cmd) { case 'd': dataLen = param_getstr(Cmd, cmdp+1, hexData, sizeof(hexData)); if (dataLen == 0) - errors = true; + errors = true; else dataLen = hextobinarray((char *)data, hexData); - - if (dataLen == 0) errors = true; + + if (dataLen == 0) errors = true; if (errors) PrintAndLogEx(WARNING, "Error getting hex data"); cmdp += 2; break; @@ -489,7 +489,7 @@ int CmdLFfskSim(const char *Cmd) { break; } } - + // No args if (cmdp == 0 && DemodBufferLen == 0) return usage_lf_simfsk(); @@ -497,7 +497,7 @@ int CmdLFfskSim(const char *Cmd) { if (errors) return usage_lf_simfsk(); int firstClockEdge = 0; - if (dataLen == 0){ //using DemodBuffer + if (dataLen == 0){ //using DemodBuffer if (clk == 0 || fcHigh == 0 || fcLow == 0){ //manual settings must set them all uint8_t ans = fskClocks(&fcHigh, &fcLow, &clk, &firstClockEdge); if (ans==0){ @@ -522,29 +522,29 @@ int CmdLFfskSim(const char *Cmd) { if (size > USB_CMD_DATA_SIZE) { PrintAndLogEx(NORMAL, "DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE); size = USB_CMD_DATA_SIZE; - } + } UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}}; memcpy(c.d.asBytes, DemodBuffer, size); clearCommandBuffer(); SendCommand(&c); - + setClockGrid(clk, 0); return 0; } -// by marshmellow - sim ask data given clock, invert, manchester or raw, separator +// by marshmellow - sim ask data given clock, invert, manchester or raw, separator // - allow pull data from DemodBuffer int CmdLFaskSim(const char *Cmd) { // autodetect clock from Graphbuffer if using demod buffer // needs clock, invert, manchester/raw as m or r, separator as s, and bitstream uint8_t encoding = 1, separator = 0, clk = 0, invert = 0; bool errors = false; - char hexData[64] = {0x00}; + char hexData[64] = {0x00}; uint8_t data[255] = {0x00}; // store entered hex data int dataLen = 0; uint8_t cmdp = 0; - + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_lf_simask(); @@ -575,11 +575,11 @@ int CmdLFaskSim(const char *Cmd) { case 'd': dataLen = param_getstr(Cmd, cmdp+1, hexData, sizeof(hexData)); if (dataLen == 0) - errors = true; + errors = true; else dataLen = hextobinarray((char *)data, hexData); - - if (dataLen == 0) errors = true; + + if (dataLen == 0) errors = true; if (errors) PrintAndLogEx(WARNING, "Error getting hex data, datalen: %d", dataLen); cmdp += 2; break; @@ -595,26 +595,26 @@ int CmdLFaskSim(const char *Cmd) { //Validations if (errors) return usage_lf_simask(); - + if (dataLen == 0){ //using DemodBuffer - if (clk == 0) + if (clk == 0) clk = GetAskClock("0", false); } else { setDemodBuf(data, dataLen, 0); } if (clk == 0) clk = 64; if (encoding == 0) clk /= 2; //askraw needs to double the clock speed - + size_t size = DemodBufferLen; if (size > USB_CMD_DATA_SIZE) { PrintAndLogEx(NORMAL, "DemodBuffer too long for current implementation - length: %d - max: %d", size, USB_CMD_DATA_SIZE); size = USB_CMD_DATA_SIZE; } - - PrintAndLogEx(NORMAL, "preparing to sim ask data: %d bits", size); - uint16_t arg1, arg2; + PrintAndLogEx(NORMAL, "preparing to sim ask data: %d bits", size); + + uint16_t arg1, arg2; arg1 = clk << 8 | encoding; arg2 = invert << 8 | separator; @@ -625,7 +625,7 @@ int CmdLFaskSim(const char *Cmd) { return 0; } -// by marshmellow - sim psk data given carrier, clock, invert +// by marshmellow - sim psk data given carrier, clock, invert // - allow pull data from DemodBuffer or parameters int CmdLFpskSim(const char *Cmd) { //might be able to autodetect FC and clock from Graphbuffer if using demod buffer @@ -634,11 +634,11 @@ int CmdLFpskSim(const char *Cmd) { uint8_t invert=0; bool errors = false; char hexData[64] = {0x00}; // store entered hex data - uint8_t data[255] = {0x00}; + uint8_t data[255] = {0x00}; int dataLen = 0; uint8_t cmdp = 0; uint8_t pskType = 1; - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': @@ -670,11 +670,11 @@ int CmdLFpskSim(const char *Cmd) { case 'd': dataLen = param_getstr(Cmd, cmdp+1, hexData, sizeof(hexData)); if (dataLen == 0) - errors = true; + errors = true; else dataLen = hextobinarray((char *)data, hexData); - - if (dataLen == 0) errors = true; + + if (dataLen == 0) errors = true; if (errors) PrintAndLogEx(WARNING, "Error getting hex data"); cmdp+=2; break; @@ -693,13 +693,13 @@ int CmdLFpskSim(const char *Cmd) { if (dataLen == 0){ //using DemodBuffer PrintAndLogEx(NORMAL, "Getting Clocks"); - + if (clk==0) clk = GetPskClock("", false); PrintAndLogEx(NORMAL, "clk: %d",clk); - - if (!carrier) carrier = GetPskCarrier("", false); + + if (!carrier) carrier = GetPskCarrier("", false); PrintAndLogEx(NORMAL, "carrier: %d", carrier); - + } else { setDemodBuf(data, dataLen, 0); } @@ -708,7 +708,7 @@ int CmdLFpskSim(const char *Cmd) { if (carrier != 2 && carrier != 4 && carrier != 8 ) carrier = 2; - + if (pskType != 1){ if (pskType == 2){ //need to convert psk2 to psk1 data before sim @@ -784,14 +784,14 @@ int CmdVchDemod(const char *Cmd) { for (i = 0; i < 2048; i += 8) { sum = 0; - for (j = 0; j < 8; j++) + for (j = 0; j < 8; j++) sum += GraphBuffer[bestPos+i+j]; - + if (sum < 0) bits[i/8] = '.'; else bits[i/8] = '1'; - + if(abs(sum) < worst) { worst = abs(sum); worstPos = i; @@ -819,7 +819,7 @@ int CmdVchDemod(const char *Cmd) { int CheckChipType(bool getDeviceData) { if (!getDeviceData) return 0; - + save_restoreDB(GRAPH_SAVE); //check for em4x05/em4x69 chips first @@ -836,7 +836,7 @@ int CheckChipType(bool getDeviceData) { PrintAndLogEx(SUCCESS, "\nValid T55xx Chip Found"); PrintAndLogEx(SUCCESS, "Try " _YELLOW_(`lf t55xx`)" commands"); save_restoreGB(GRAPH_RESTORE); - return 1; + return 1; } save_restoreDB(GRAPH_RESTORE); @@ -849,16 +849,16 @@ int CmdLFfind(const char *Cmd) { size_t minLength = 2000; char cmdp = tolower(param_getchar(Cmd, 0)); char testRaw = param_getchar(Cmd, 1); - + if (strlen(Cmd) > 3 || cmdp == 'h') return usage_lf_find(); - + if (cmdp == 'u') testRaw = 'u'; - + bool isOnline = (!IsOffline() && (cmdp != '1') ); - + if (isOnline) lf_read(true, 30000); - + if (GraphTraceLen < minLength) { PrintAndLogEx(FAILED, "Data in Graphbuffer was too small."); return 0; @@ -866,9 +866,9 @@ int CmdLFfind(const char *Cmd) { PrintAndLogEx(INFO, "NOTE: some demods output possible binary"); PrintAndLogEx(INFO, "if it finds something that looks like a tag"); - PrintAndLogEx(INFO, "False Positives " _YELLOW_(ARE) "possible\n"); + PrintAndLogEx(INFO, "False Positives " _YELLOW_(ARE) "possible\n"); PrintAndLogEx(INFO, "\nChecking for known tags:\n"); - + // only run these tests if device is online if (isOnline) { // only run if graphbuffer is just noise as it should be for hitag @@ -876,21 +876,21 @@ int CmdLFfind(const char *Cmd) { signal_t *sp = getSignalProperties(); if (sp->isnoise) { - PrintAndLogEx(INFO, "Signal looks just like noise. Looking for Hitag signal now."); + PrintAndLogEx(INFO, "Signal looks just like noise. Looking for Hitag signal now."); // 26 === RHT2F_UID_ONLY if (CmdLFHitagReader("26") == 0) { PrintAndLogEx(SUCCESS, "\nValid Hitag Found!"); return 1;} if (CmdCOTAGRead("") > 0) { PrintAndLogEx(SUCCESS, "\nValid COTAG ID Found!"); return 1;} - + PrintAndLogEx(FAILED, "\nNo Data Found! - maybe not an LF tag?"); return 0; } } - + if (EM4x50Read("", false)) { PrintAndLogEx(SUCCESS, "\nValid EM4x50 ID Found!"); return 1;} if (CmdAWIDDemod("")) { PrintAndLogEx(SUCCESS, "\nValid AWID ID Found!"); goto out;} if (CmdEM410xDemod("")) { PrintAndLogEx(SUCCESS, "\nValid EM410x ID Found!"); goto out;} - if (CmdFdxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid FDX-B ID Found!"); goto out;} + if (CmdFdxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid FDX-B ID Found!"); goto out;} if (CmdGuardDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Guardall G-Prox II ID Found!"); goto out; } if (CmdHIDDemod("")) { PrintAndLogEx(SUCCESS, "\nValid HID Prox ID Found!"); goto out;} if (CmdPSKIdteck("")) { PrintAndLogEx(SUCCESS, "\nValid Idteck ID Found!"); goto out;} @@ -901,19 +901,19 @@ int CmdLFfind(const char *Cmd) { if (CmdNexWatchDemod("")) { PrintAndLogEx(SUCCESS, "\nValid NexWatch ID Found!"); goto out;} if (CmdNoralsyDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Noralsy ID Found!"); goto out;} if (CmdKeriDemod("")) { PrintAndLogEx(SUCCESS, "\nValid KERI ID Found!"); goto out;} - if (CmdPacDemod("")) { PrintAndLogEx(SUCCESS, "\nValid PAC/Stanley ID Found!"); goto out;} + if (CmdPacDemod("")) { PrintAndLogEx(SUCCESS, "\nValid PAC/Stanley ID Found!"); goto out;} if (CmdParadoxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Paradox ID Found!"); goto out;} - if (CmdPrescoDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Presco ID Found!"); goto out;} + if (CmdPrescoDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Presco ID Found!"); goto out;} if (CmdPyramidDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Pyramid ID Found!"); goto out;} if (CmdSecurakeyDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Securakey ID Found!"); goto out;} - if (CmdVikingDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Viking ID Found!"); goto out;} + if (CmdVikingDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Viking ID Found!"); goto out;} if (CmdVisa2kDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Visa2000 ID Found!"); goto out;} //if (CmdFermaxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Fermax ID Found!"); goto out;} // TIdemod? flexdemod? - + PrintAndLogEx(FAILED, "\nNo known 125/134 KHz tags Found!\n"); - + if (testRaw == 'u'){ //test unknown tag formats (raw mode) PrintAndLogEx(INFO, "\nChecking for Unknown tags:\n"); @@ -922,31 +922,31 @@ int CmdLFfind(const char *Cmd) { PrintAndLogEx(INFO, "Possible Auto Correlation of %d repeating samples",ans); - if ( ans % 8 == 0) + if ( ans % 8 == 0) PrintAndLogEx(INFO, "Possible %d bytes", (ans / 8)); } //fsk if ( GetFskClock("", false) ) { - if ( FSKrawDemod("", true) ) { + if ( FSKrawDemod("", true) ) { PrintAndLogEx(NORMAL, "\nUnknown FSK Modulated Tag Found!"); goto out; } } - + bool st = true; if ( ASKDemod_ext("0 0 0", true, false, 1, &st) ) { PrintAndLogEx(NORMAL, "\nUnknown ASK Modulated and Manchester encoded Tag Found!"); PrintAndLogEx(NORMAL, "\nif it does not look right it could instead be ASK/Biphase - try 'data rawdemod ab'"); goto out; } - + if ( CmdPSK1rawDemod("") ) { PrintAndLogEx(NORMAL, "Possible unknown PSK1 Modulated Tag Found above!\n\nCould also be PSK2 - try 'data rawdemod p2'"); PrintAndLogEx(NORMAL, "\nCould also be PSK3 - [currently not supported]"); PrintAndLogEx(NORMAL, "\nCould also be NRZ - try 'data nrzrawdemod"); goto out; } - + PrintAndLogEx(FAILED, "\nNo Data Found!\n"); } out: @@ -970,12 +970,12 @@ static command_t CommandTable[] = { {"keri", CmdLFKeri, 1, "{ KERI RFIDs... }"}, {"nedap", CmdLFNedap, 1, "{ Nedap RFIDs... }"}, {"nexwatch", CmdLFNEXWATCH, 1, "{ NexWatch RFIDs... }"}, - {"noralsy", CmdLFNoralsy, 1, "{ Noralsy RFIDs... }"}, + {"noralsy", CmdLFNoralsy, 1, "{ Noralsy RFIDs... }"}, {"pac", CmdLFPac, 1, "{ PAC/Stanley RFIDs... }"}, {"paradox", CmdLFParadox, 1, "{ Paradox RFIDs... }"}, {"pcf7931", CmdLFPCF7931, 1, "{ PCF7931 CHIPs... }"}, {"presco", CmdLFPresco, 1, "{ Presco RFIDs... }"}, - {"pyramid", CmdLFPyramid, 1, "{ Farpointe/Pyramid RFIDs... }"}, + {"pyramid", CmdLFPyramid, 1, "{ Farpointe/Pyramid RFIDs... }"}, {"securakey", CmdLFSecurakey, 1, "{ Securakey RFIDs... }"}, {"ti", CmdLFTI, 1, "{ TI CHIPs... }"}, {"t55xx", CmdLFT55XX, 1, "{ T55xx CHIPs... }"}, @@ -999,7 +999,7 @@ static command_t CommandTable[] = { int CmdLF(const char *Cmd) { clearCommandBuffer(); CmdsParse(CommandTable, Cmd); - return 0; + return 0; } int CmdHelp(const char *Cmd) { diff --git a/client/cmdlf.h b/client/cmdlf.h index 04c7317a1..be0313528 100644 --- a/client/cmdlf.h +++ b/client/cmdlf.h @@ -17,7 +17,7 @@ #include #include #include "proxmark3.h" -#include "lfdemod.h" // device/client demods of LF signals +#include "lfdemod.h" // device/client demods of LF signals #include "util.h" // for parsing cli command utils #include "ui.h" // for show graph controls #include "graph.h" // for graph data diff --git a/client/cmdlfawid.c b/client/cmdlfawid.c index 3cc56f56c..6e181aa34 100644 --- a/client/cmdlfawid.c +++ b/client/cmdlfawid.c @@ -11,7 +11,7 @@ // FSK2a, RF/50, 96 bits (complete) //----------------------------------------------------------------------------- #include "cmdlfawid.h" // AWID function declarations - + static int CmdHelp(const char *Cmd); int usage_lf_awid_read(void) { @@ -21,7 +21,7 @@ int usage_lf_awid_read(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: lf awid read [h] [1]"); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " 1 : (optional) stop after reading a single card"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); @@ -36,7 +36,7 @@ int usage_lf_awid_sim(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: lf awid sim [h] "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " : format length 26|34|37|50"); PrintAndLogEx(NORMAL, " : 8|16bit value facility code"); PrintAndLogEx(NORMAL, " : 16|32-bit value card number"); @@ -53,7 +53,7 @@ int usage_lf_awid_clone(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: lf awid clone [h] [Q5]"); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " : format length 26|34|37|50"); PrintAndLogEx(NORMAL, " : 8|16bit value facility code"); PrintAndLogEx(NORMAL, " : 16|32-bit value card number"); @@ -77,7 +77,7 @@ int usage_lf_awid_brute(void){ PrintAndLogEx(NORMAL, " f : 8|16bit value facility code"); PrintAndLogEx(NORMAL, " c : (optional) cardnumber to start with, max 65535"); PrintAndLogEx(NORMAL, " d : delay betweens attempts in ms. Default 1000ms"); - PrintAndLogEx(NORMAL, " v : verbose logging, show all tries"); + PrintAndLogEx(NORMAL, " v : verbose logging, show all tries"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf awid brute a 26 f 224"); @@ -89,8 +89,8 @@ int usage_lf_awid_brute(void){ static bool sendPing(void){ UsbCommand ping = {CMD_PING, {1, 2, 3}}; SendCommand(&ping); - SendCommand(&ping); - SendCommand(&ping); + SendCommand(&ping); + SendCommand(&ping); clearCommandBuffer(); UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) @@ -99,10 +99,10 @@ static bool sendPing(void){ } static bool sendTry(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint32_t delay, uint8_t *bits, size_t bs_len, bool verbose){ - + if ( verbose ) - PrintAndLogEx(INFO, "Trying FC: %u; CN: %u", fc, cn); - + PrintAndLogEx(INFO, "Trying FC: %u; CN: %u", fc, cn); + if ( !getAWIDBits(fmtlen, fc, cn, bits)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); return false; @@ -116,7 +116,7 @@ static bool sendTry(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint32_t delay, ui memcpy(c.d.asBytes, bits, bs_len); clearCommandBuffer(); SendCommand(&c); - + msleep(delay); sendPing(); return true; @@ -125,15 +125,15 @@ static bool sendTry(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint32_t delay, ui //refactored by marshmellow int getAWIDBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *bits) { - // the return bits, preamble 0000 0001 - bits[7] = 1; - + // the return bits, preamble 0000 0001 + bits[7] = 1; + uint8_t pre[66]; memset(pre, 0, sizeof(pre)); // add formatlength num_to_bytebits(fmtlen, 8, pre); - + // add facilitycode, cardnumber and wiegand parity bits switch (fmtlen) { case 26:{ @@ -165,14 +165,14 @@ int getAWIDBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *bits) { break; } } - - // add AWID 4bit parity + + // add AWID 4bit parity size_t bitLen = addParity(pre, bits+8, 66, 4, 1); if (bitLen != 88) return 0; - + PrintAndLogEx(SUCCESS, "awid raw bits:\n %s \n", sprint_bin(bits, bitLen)); - + return 1; } @@ -192,7 +192,7 @@ static void verify_values(uint8_t *fmtlen, uint32_t *fc, uint32_t *cn){ if ((*cn & 0x3FFFF) != *cn) { *cn &= 0x3FFFF; PrintAndLogEx(INFO, "Card Number Truncated to 18-bits (AWID37): %u", *cn); - } + } break; case 34: if ((*fc & 0xFF) != *fc) { @@ -233,7 +233,7 @@ int CmdAWIDRead_device(const char *Cmd) { UsbCommand c = {CMD_AWID_DEMOD_FSK, {findone, 0, 0}}; clearCommandBuffer(); SendCommand(&c); - return 0; + return 0; } //by marshmellow @@ -283,7 +283,7 @@ int CmdAWIDDemod(const char *Cmd) { // f = facility code, c = card number // w = wiegand parity // (26 bit format shown) - + //get raw ID before removing parities uint32_t rawLo = bytebits_to_byte(bits + idx + 64, 32); uint32_t rawHi = bytebits_to_byte(bits + idx + 32, 32); @@ -305,9 +305,9 @@ int CmdAWIDDemod(const char *Cmd) { // bbbbbbbb w ffffffff cccccccccccccccc w xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx // |26 bit| |-117--| |-----142------| // - // 00110010 0 0000111110100000 00000000000100010010100010000111 1 000000000 + // 00110010 0 0000111110100000 00000000000100010010100010000111 1 000000000 // bbbbbbbb w ffffffffffffffff cccccccccccccccccccccccccccccccc w xxxxxxxxx - // |50 bit| |----4000------| |-----------2248975------------| + // |50 bit| |----4000------| |-----------2248975------------| // b = format bit len, o = odd parity of last 3 bits // f = facility code, c = card number // w = wiegand parity @@ -319,7 +319,7 @@ int CmdAWIDDemod(const char *Cmd) { uint8_t fmtLen = bytebits_to_byte(bits, 8); switch(fmtLen) { - case 26: + case 26: fc = bytebits_to_byte(bits + 9, 8); cardnum = bytebits_to_byte(bits + 17, 16); code1 = bytebits_to_byte(bits + 8,fmtLen); @@ -329,18 +329,18 @@ int CmdAWIDDemod(const char *Cmd) { fc = bytebits_to_byte(bits + 9, 8); cardnum = bytebits_to_byte(bits + 17, 24); code1 = bytebits_to_byte(bits + 8, (fmtLen-32) ); - code2 = bytebits_to_byte(bits + 8 + (fmtLen-32), 32); - PrintAndLogEx(SUCCESS, "AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); + code2 = bytebits_to_byte(bits + 8 + (fmtLen-32), 32); + PrintAndLogEx(SUCCESS, "AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); break; case 37: fc = bytebits_to_byte(bits + 9, 13); cardnum = bytebits_to_byte(bits + 22, 18); code1 = bytebits_to_byte(bits + 8, (fmtLen-32) ); - code2 = bytebits_to_byte(bits + 8 + (fmtLen-32), 32); + code2 = bytebits_to_byte(bits + 8 + (fmtLen-32), 32); PrintAndLogEx(SUCCESS, "AWID Found - BitLength: %d, FC: %d, Card: %u - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, code2, rawHi2, rawHi, rawLo); break; // case 40: - // break; + // break; case 50: fc = bytebits_to_byte(bits + 9, 16); cardnum = bytebits_to_byte(bits + 25, 32); @@ -359,7 +359,7 @@ int CmdAWIDDemod(const char *Cmd) { code1 = bytebits_to_byte(bits + 8, fmtLen); PrintAndLogEx(SUCCESS, "AWID Found - BitLength: %d -unknown BitLength- (%u) - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo); } - break; + break; } PrintAndLogEx(DEBUG, "DEBUG: AWID idx: %d, Len: %d Printing Demod Buffer:", idx, size); @@ -378,22 +378,22 @@ int CmdAWIDSim(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_awid_sim(); - + fmtlen = param_get8(Cmd, 0); - fc = param_get32ex(Cmd, 1, 0, 10); + fc = param_get32ex(Cmd, 1, 0, 10); cn = param_get32ex(Cmd, 2, 0, 10); if ( !fc || !cn) return usage_lf_awid_sim(); - + verify_values(&fmtlen, &fc, &cn); - + PrintAndLogEx(SUCCESS, "Simulating AWID %u -- FC: %u; CN: %u\n", fmtlen, fc, cn); PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation or run another command"); - + if (!getAWIDBits(fmtlen, fc, cn, bits)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); return 1; } - + uint8_t clk = 50, high = 10, low = 8, invert = 1; uint64_t arg1 = (high << 8) + low; uint64_t arg2 = (invert << 8) + clk; @@ -402,7 +402,7 @@ int CmdAWIDSim(const char *Cmd) { // arg1 --- fcHigh<<8 + fcLow // arg2 --- Inversion and clk setting // 96 --- Bitstream length: 96-bits == 12 bytes - UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}}; + UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}}; memcpy(c.d.asBytes, bits, size); clearCommandBuffer(); SendCommand(&c); @@ -416,7 +416,7 @@ int CmdAWIDClone(const char *Cmd) { uint8_t bits[96]; uint8_t *bs=bits; memset(bs,0,sizeof(bits)); - + char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_awid_clone(); @@ -425,17 +425,17 @@ int CmdAWIDClone(const char *Cmd) { cn = param_get32ex(Cmd, 2, 0, 10); if ( !fc || !cn) return usage_lf_awid_clone(); - + if (tolower(param_getchar(Cmd, 3)) == 'q') //t5555 (Q5) BITRATE = (RF-2)/2 (iceman) blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(50) | 3< 1 ) if ( down > 1 ) diff --git a/client/cmdlfcotag.c b/client/cmdlfcotag.c index ff0167938..208355ad8 100644 --- a/client/cmdlfcotag.c +++ b/client/cmdlfcotag.c @@ -32,7 +32,7 @@ int CmdCOTAGDemod(const char *Cmd) { uint8_t bits[COTAG_BITS] = {0}; size_t bitlen = COTAG_BITS; memcpy(bits, DemodBuffer, COTAG_BITS); - + uint8_t alignPos = 0; int err = manrawdecode(bits, &bitlen, 1, &alignPos); if (err){ @@ -45,18 +45,18 @@ int CmdCOTAGDemod(const char *Cmd) { //got a good demod uint16_t cn = bytebits_to_byteLSBF(bits+1, 16); uint32_t fc = bytebits_to_byteLSBF(bits+1+16, 8); - + uint32_t raw1 = bytebits_to_byteLSBF(bits, 32); uint32_t raw2 = bytebits_to_byteLSBF(bits+32, 32); uint32_t raw3 = bytebits_to_byteLSBF(bits+64, 32); uint32_t raw4 = bytebits_to_byteLSBF(bits+96, 32); - + /* fc 161: 1010 0001 -> LSB 1000 0101 cn 33593 1000 0011 0011 1001 -> LSB 1001 1100 1100 0001 cccc cccc cccc cccc ffffffff 0 1001 1100 1100 0001 1000 0101 0000 0000 100001010000000001111011100000011010000010000000000000000000000000000000000000000000000000000000100111001100000110000101000 - 1001 1100 1100 0001 10000101 + 1001 1100 1100 0001 10000101 */ PrintAndLogEx(SUCCESS, "COTAG Found: FC %u, CN: %u Raw: %08X%08X%08X%08X", fc, cn, raw1 ,raw2, raw3, raw4); return 1; @@ -65,32 +65,32 @@ int CmdCOTAGDemod(const char *Cmd) { // When reading a COTAG. // 0 = HIGH/LOW signal - maxlength bigbuff // 1 = translation for HI/LO into bytes with manchester 0,1 - length 300 -// 2 = raw signal - maxlength bigbuff +// 2 = raw signal - maxlength bigbuff int CmdCOTAGRead(const char *Cmd) { - + if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_cotag_read(); - + uint32_t rawsignal = 1; sscanf(Cmd, "%u", &rawsignal); - + UsbCommand c = {CMD_COTAG, {rawsignal, 0, 0}}; clearCommandBuffer(); SendCommand(&c); if ( !WaitForResponseTimeout(CMD_ACK, NULL, 7000) ) { PrintAndLogEx(WARNING, "command execution time out"); - return -1; + return -1; } - + switch ( rawsignal ){ - case 0: + case 0: case 2: { CmdPlot(""); CmdGrid("384"); - getSamples(0, true); + getSamples(0, true); break; } case 1: { - + if ( !GetFromDevice(BIG_BUF, DemodBuffer, COTAG_BITS, 0, NULL, 1000, false)) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); return -1; @@ -98,7 +98,7 @@ int CmdCOTAGRead(const char *Cmd) { DemodBufferLen = COTAG_BITS; return CmdCOTAGDemod(""); } - } + } return 0; } diff --git a/client/cmdlfcotag.h b/client/cmdlfcotag.h index e03f7d5f5..9270ccbb7 100644 --- a/client/cmdlfcotag.h +++ b/client/cmdlfcotag.h @@ -17,7 +17,7 @@ #include "cmdparser.h" // CmdsParse, CmdsHelp #include "comms.h" #include "ui.h" // PrintAndLog -#include "cmdlf.h" // Setconfig +#include "cmdlf.h" // Setconfig #ifndef COTAG_BITS #define COTAG_BITS 264 diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 8b9530957..3024470de 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -130,7 +130,7 @@ int usage_lf_em4x50_write(void) { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); PrintAndLogEx(NORMAL, " address - memory address to write to. (0-15)"); - PrintAndLogEx(NORMAL, " data - data to write (hex)"); + PrintAndLogEx(NORMAL, " data - data to write (hex)"); PrintAndLogEx(NORMAL, " pwd - password (hex) (optional)"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf em 4x50_write 1 deadc0de"); @@ -171,7 +171,7 @@ int usage_lf_em4x05_write(void) { PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); PrintAndLogEx(NORMAL, " address - memory address to write to. (0-15)"); - PrintAndLogEx(NORMAL, " data - data to write (hex)"); + PrintAndLogEx(NORMAL, " data - data to write (hex)"); PrintAndLogEx(NORMAL, " pwd - password (hex) (optional)"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf em 4x05_write 1 deadc0de"); @@ -251,7 +251,7 @@ void ConstructEM410xEmulGraph(const char *uid,const uint8_t clock) { void printEM410x(uint32_t hi, uint64_t id) { if (!id && !hi) return; - + PrintAndLogEx(NORMAL, "EM410x %s pattern found", (hi) ? "XL" : "" ); uint64_t iii=1; @@ -263,7 +263,7 @@ void printEM410x(uint32_t hi, uint64_t id) { id2lo=(id2lo<<1LL) | ((id & (iii << (i+((ii-1)*8)))) >> (i+((ii-1)*8))); } } - + if (hi){ //output 88 bit em id PrintAndLogEx(NORMAL, "\nEM TAG ID : %06X%016" PRIX64, hi, id); @@ -294,12 +294,12 @@ void printEM410x(uint32_t hi, uint64_t id) { (id2lo & 0x000000000f) ); uint64_t paxton = (((id>>32) << 24) | (id & 0xffffff)) + 0x143e00; - PrintAndLogEx(NORMAL, "}\nOther : %05" PRIu64 "_%03" PRIu64 "_%08" PRIu64, (id&0xFFFF), ((id>>16LL) & 0xFF), (id & 0xFFFFFF)); + PrintAndLogEx(NORMAL, "}\nOther : %05" PRIu64 "_%03" PRIu64 "_%08" PRIu64, (id&0xFFFF), ((id>>16LL) & 0xFF), (id & 0xFFFFFF)); PrintAndLogEx(NORMAL, "Pattern Paxton : %" PRIu64 " [0x%" PRIX64 "]", paxton, paxton); uint32_t p1id = (id & 0xFFFFFF); uint8_t arr[32] = {0x00}; - int i =0; + int i =0; int j = 23; for (; i < 24; ++i, --j ){ arr[i] = (p1id >> i) & 1; @@ -311,12 +311,12 @@ void printEM410x(uint32_t hi, uint64_t id) { p1 |= arr[22] << 23; p1 |= arr[21] << 20; p1 |= arr[20] << 22; - + p1 |= arr[19] << 18; p1 |= arr[18] << 16; p1 |= arr[17] << 19; p1 |= arr[16] << 17; - + p1 |= arr[15] << 13; p1 |= arr[14] << 15; p1 |= arr[13] << 12; @@ -355,12 +355,12 @@ void printEM410x(uint32_t hi, uint64_t id) { int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo ) { size_t idx = 0; uint8_t bits[512] = {0}; - size_t size = sizeof(bits); + size_t size = sizeof(bits); if ( !getDemodBuf(bits, &size) ) { PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x problem during copy from ASK demod"); return 0; } - + int ans = Em410xDecode(bits, &size, &idx, hi, lo); if ( ans < 0){ @@ -379,13 +379,13 @@ int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo ) { PrintAndLogEx(DEBUG, "DEBUG: Error - Em410x decoded to all zeros"); return 0; } - + //set GraphBuffer for clone or sim command setDemodBuf(DemodBuffer, (size==40) ? 64 : 128, idx+1); setClockGrid(g_DemodClock, g_DemodStartIdx + ((idx+1)*g_DemodClock)); - + PrintAndLogEx(DEBUG, "DEBUG: Em410x idx: %d, Len: %d, Printing Demod Buffer:", idx, size); - if (g_debugMode) + if (g_debugMode) printDemodBuff(); if (verbose) @@ -422,12 +422,12 @@ int CmdEM410xRead_device(const char *Cmd) { int CmdEM410xDemod(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) > 10 || cmdp == 'h') return usage_lf_em410x_demod(); - + uint32_t hi = 0; uint64_t lo = 0; if (AskEm410xDemod(Cmd, &hi, &lo, true) != 1) return 0; - + g_em410xid = lo; return 1; } @@ -446,14 +446,14 @@ int CmdEM410xSim(const char *Cmd) { PrintAndLogEx(FAILED, "UID must include 10 HEX symbols"); return 0; } - + param_getdec(Cmd, 1, &clock); - + PrintAndLogEx(SUCCESS, "Starting simulating UID %02X%02X%02X%02X%02X clock: %d", uid[0],uid[1],uid[2],uid[3],uid[4],clock); PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation"); ConstructEM410xEmulGraph(Cmd, clock); - + CmdLFSim("0"); //240 start_gap. return 0; } @@ -470,10 +470,10 @@ int CmdEM410xBrute(const char *Cmd) { uint8_t clock = 64; /* default pause time: 1 second */ uint32_t delay = 1000; - + char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_lf_em410x_brute(); - + cmdp = tolower(param_getchar(Cmd, 1)); if (cmdp == 'd') { delay = param_get32ex(Cmd, 2, 1000, 10); @@ -483,12 +483,12 @@ int CmdEM410xBrute(const char *Cmd) { delay = param_get32ex(Cmd, 4, 1000, 10); } - int filelen = param_getstr(Cmd, 0, filename, FILE_PATH_SIZE); + int filelen = param_getstr(Cmd, 0, filename, FILE_PATH_SIZE); if (filelen == 0) { PrintAndLogEx(WARNING, "Error: Please specify a filename"); - return 1; + return 1; } - + if ((f = fopen(filename, "r")) == NULL) { PrintAndLogEx(WARNING, "Error: Could not open UIDs file [%s]", filename); return 1; @@ -499,23 +499,23 @@ int CmdEM410xBrute(const char *Cmd) { fclose(f); return 1; } - + while( fgets(buf, sizeof(buf), f) ) { if (strlen(buf) < 10 || buf[9] == '\n') continue; while (fgetc(f) != '\n' && !feof(f)); //goto next line //The line start with # is comment, skip if( buf[0]=='#' ) continue; - + if (param_gethex(buf, 0, uid, 10)) { PrintAndLogEx(FAILED, "UIDs must include 10 HEX symbols"); free(uidBlock); fclose(f); return 1; } - + buf[10] = 0; - + if ( stUidBlock - uidcnt < 2) { p = realloc(uidBlock, 5 * (stUidBlock += 10) ); if (!p) { @@ -531,50 +531,50 @@ int CmdEM410xBrute(const char *Cmd) { uidcnt++; memset(buf, 0, sizeof(buf)); } - + fclose(f); - + if (uidcnt == 0) { PrintAndLogEx(FAILED, "No UIDs found in file"); free(uidBlock); return 1; } - + PrintAndLogEx(SUCCESS, "Loaded %d UIDs from %s, pause delay: %d ms", uidcnt, filename, delay); - + // loop for(uint32_t c = 0; c < uidcnt; ++c ) { char testuid[11]; testuid[10] = 0; - + if (ukbhit()) { int gc = getchar(); (void)gc; PrintAndLogEx(NORMAL, "\nAborted via keyboard!\n"); free(uidBlock); return 0; } - + sprintf(testuid, "%010" PRIX64, bytes_to_num(uidBlock + 5*c, 5)); PrintAndLogEx(NORMAL, "Bruteforce %d / %d: simulating UID %s, clock %d", c + 1, uidcnt, testuid, clock); - + ConstructEM410xEmulGraph(testuid, clock); - + CmdLFSim("0"); //240 start_gap. msleep(delay); } - + free(uidBlock); return 0; } /* Function is equivalent of lf read + data samples + em410xread - * looped until an EM410x tag is detected - * + * looped until an EM410x tag is detected + * * Why is CmdSamples("16000")? * TBD: Auto-grow sample size based on detected sample rate. IE: If the * rate gets lower, then grow the number of samples - * Changed by martin, 4000 x 4 = 16000, + * Changed by martin, 4000 x 4 = 16000, * see http://www.proxmark.org/forum/viewtopic.php?pid=7235#p7235 * * EDIT -- capture enough to get 2 complete preambles at the slowest data rate known to be used (rf/64) (64*64*2+9 = 8201) marshmellow @@ -585,19 +585,19 @@ int CmdEM410xWatch(const char *Cmd) { int gc = getchar(); (void)gc; PrintAndLogEx(NORMAL, "\naborted via keyboard!\n"); break; - } + } lf_read(true, 8201); - + } while (!CmdEM410xRead("")); return 0; } //currently only supports manchester modulations int CmdEM410xWatchnSpoof(const char *Cmd) { - + char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_lf_em410x_ws(); - + // loops if the captured ID was in XL-format. CmdEM410xWatch(Cmd); PrintAndLogEx(SUCCESS, "# Replaying captured ID: %010" PRIx64 , g_em410xid); @@ -608,7 +608,7 @@ int CmdEM410xWatchnSpoof(const char *Cmd) { int CmdEM410xWrite(const char *Cmd) { char cmdp = param_getchar(Cmd, 0); if (cmdp == 'h' || cmdp == 'H') return usage_lf_em410x_write(); - + uint64_t id = 0xFFFFFFFFFFFFFFFF; // invalid id value int card = 0xFF; // invalid card value uint32_t clock = 0; // invalid clock value @@ -699,14 +699,14 @@ bool EM_ByteParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t co // 012345678|r3 // 012345678|r4 // ------------ -//c012345678| 0 +//c012345678| 0 // |- must be zero bool EMwordparitytest(uint8_t *bits){ // last row/col parity must be 0 if (bits[44] != 0 ) return false; - + // col parity check uint8_t c1 = bytebits_to_byte(bits, 8) ^ bytebits_to_byte(bits+9, 8) ^ bytebits_to_byte(bits+18, 8) ^ bytebits_to_byte(bits+27, 8); uint8_t c2 = bytebits_to_byte(bits+36, 8); @@ -718,8 +718,8 @@ bool EMwordparitytest(uint8_t *bits){ rowP ^= bits[i]; if ( i>0 && (i % 9) == 0) { - - if ( rowP != EVEN ) + + if ( rowP != EVEN ) return false; rowP = 0; @@ -733,12 +733,12 @@ bool EMwordparitytest(uint8_t *bits){ uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool pTest) { if (size<45) return 0; - + uint32_t code = bytebits_to_byte(BitStream,8); code = code<<8 | bytebits_to_byte(BitStream+9,8); code = code<<8 | bytebits_to_byte(BitStream+18,8); code = code<<8 | bytebits_to_byte(BitStream+27,8); - + if (verbose || g_debugMode){ for (uint8_t i = 0; i<5; i++){ if (i == 4) PrintAndLogEx(NORMAL, ""); //parity byte spacer @@ -797,11 +797,11 @@ int EM4x50Read(const char *Cmd, bool verbose) { // get user entry if any sscanf(Cmd, "%i %i", &clk, &invert); - + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; size_t size = getFromGraphBuf(bits); computeSignalProperties(bits, size); - + signal_t *sp = getSignalProperties(); high = sp->high; low = sp->low; @@ -835,7 +835,7 @@ int EM4x50Read(const char *Cmd, bool verbose) { if (!clk) { for (uint8_t clkCnt = 0; clkCnt < 7; clkCnt++) { tol = fndClk[clkCnt] / 8; - if (minClk >= fndClk[clkCnt] - tol && minClk <= fndClk[clkCnt] + 1) { + if (minClk >= fndClk[clkCnt] - tol && minClk <= fndClk[clkCnt] + 1) { clk = fndClk[clkCnt]; break; } @@ -863,12 +863,12 @@ int EM4x50Read(const char *Cmd, bool verbose) { // skip over the remainder of LW skip += (tmpbuff[i+1] + tmpbuff[i+2] + clk); - - if (tmpbuff[i+3] > clk) + + if (tmpbuff[i+3] > clk) phaseoff = tmpbuff[i+3] - clk; else phaseoff = 0; - + // now do it again to find the end end = skip; for (i += 3; i < j - 4 ; ++i) { @@ -894,12 +894,12 @@ int EM4x50Read(const char *Cmd, bool verbose) { return 0; } } else if (start < 0) return 0; - + start = skip; snprintf(tmp2, sizeof(tmp2),"%d %d 1000 %d", clk, invert, clk * 47); - // save GraphBuffer - to restore it later + // save GraphBuffer - to restore it later save_restoreGB(GRAPH_SAVE); - // get rid of leading crap + // get rid of leading crap snprintf(tmp, sizeof(tmp), "%i", skip); CmdLtrim(tmp); bool pTest; @@ -910,7 +910,7 @@ int EM4x50Read(const char *Cmd, bool verbose) { while (block < 6) { if (verbose || g_debugMode) PrintAndLogEx(NORMAL, "\nBlock %i:", block); skip = phaseoff; - + // look for LW before start of next block for ( ; i < j - 4 ; ++i) { skip += tmpbuff[i]; @@ -924,9 +924,9 @@ int EM4x50Read(const char *Cmd, bool verbose) { phaseoff = tmpbuff[i+1] - clk; else phaseoff = 0; - + i += 2; - + if (ASKDemod(tmp2, false, false, 1) < 1) { save_restoreGB(GRAPH_RESTORE); return 0; @@ -934,7 +934,7 @@ int EM4x50Read(const char *Cmd, bool verbose) { //set DemodBufferLen to just one block DemodBufferLen = skip/clk; //test parities - pTest = EM_ByteParityTest(DemodBuffer,DemodBufferLen, 5, 9, 0); + pTest = EM_ByteParityTest(DemodBuffer,DemodBufferLen, 5, 9, 0); pTest &= EM_EndParityTest(DemodBuffer,DemodBufferLen, 5, 9, 0); AllPTest &= pTest; //get output @@ -953,7 +953,7 @@ int EM4x50Read(const char *Cmd, bool verbose) { PrintAndLogEx(NORMAL, "Partial data - no end found!"); PrintAndLogEx(NORMAL, "Try again with more samples."); } - PrintAndLogEx(NORMAL, "Found data at sample: %i - using clock: %i", start, clk); + PrintAndLogEx(NORMAL, "Found data at sample: %i - using clock: %i", start, clk); end = block; for (block=0; block < end; block++){ PrintAndLogEx(NORMAL, "Block %d: %08x", block, Code[block]); @@ -973,7 +973,7 @@ int EM4x50Read(const char *Cmd, bool verbose) { int CmdEM4x50Read(const char *Cmd) { uint8_t ctmp = tolower(param_getchar(Cmd, 0)); - if ( ctmp == 'h' ) return usage_lf_em4x50_read(); + if ( ctmp == 'h' ) return usage_lf_em4x50_read(); return EM4x50Read(Cmd, true); } int CmdEM4x50Write(const char *Cmd){ @@ -992,7 +992,7 @@ int CmdEM4x50Dump(const char *Cmd){ #define EM_PREAMBLE_LEN 6 // download samples from device and copy to Graphbuffer bool downloadSamplesEM(){ - + // 8 bit preamble + 32 bit word response (max clock (128) * 40bits = 5120 samples) uint8_t got[6000]; if ( !GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 2500, false)) { @@ -1011,9 +1011,9 @@ bool downloadSamplesEM(){ return true; } -// em_demod +// em_demod bool doPreambleSearch(size_t *startIdx){ - + // sanity check if ( DemodBufferLen < EM_PREAMBLE_LEN) { PrintAndLogEx(DEBUG, "DEBUG: Error - EM4305 demodbuffer too small"); @@ -1022,14 +1022,14 @@ bool doPreambleSearch(size_t *startIdx){ // set size to 20 to only test first 14 positions for the preamble size_t size = (20 > DemodBufferLen) ? DemodBufferLen : 20; - *startIdx = 0; + *startIdx = 0; // skip first two 0 bits as they might have been missed in the demod uint8_t preamble[EM_PREAMBLE_LEN] = {0,0,1,0,1,0}; - + if ( !preambleSearchEx(DemodBuffer, preamble, EM_PREAMBLE_LEN, &size, startIdx, true)) { PrintAndLogEx(DEBUG, "DEBUG: Error - EM4305 preamble not found :: %d", *startIdx); return false; - } + } return true; } @@ -1048,7 +1048,7 @@ bool detectFSK(){ return true; } // PSK clocks should be easy to detect ( but difficult to demod a non-repeating pattern... ) -bool detectPSK(){ +bool detectPSK(){ int ans = GetPskClock("", false); if (ans <= 0) { PrintAndLogEx(DEBUG, "DEBUG: Error - EM: PSK clock failed"); @@ -1077,14 +1077,14 @@ bool detectASK_MAN(){ if ( !ASKDemod_ext("0 0 0", false, false, 1, &stcheck) ) { PrintAndLogEx(DEBUG, "DEBUG: Error - EM: ASK/Manchester Demod failed"); return false; - } + } return true; } bool detectASK_BI(){ int ans = ASKbiphaseDemod("0 0 1", false); - if (!ans) { + if (!ans) { PrintAndLogEx(DEBUG, "DEBUG: Error - EM: ASK/biphase normal demod failed"); - + ans = ASKbiphaseDemod("0 1 1", false); if (!ans) { PrintAndLogEx(DEBUG, "DEBUG: Error - EM: ASK/biphase inverted demod failed"); @@ -1104,8 +1104,8 @@ bool setDemodBufferEM(uint32_t *word, size_t idx){ PrintAndLogEx(DEBUG, "DEBUG: Error - EM Parity tests failed"); return false; } - - // test for even parity bits and remove them. (leave out the end row of parities so 36 bits) + + // test for even parity bits and remove them. (leave out the end row of parities so 36 bits) if (!removeParity(DemodBuffer, idx + EM_PREAMBLE_LEN, 9, 0, 36)) { PrintAndLogEx(DEBUG, "DEBUG: Error - EM, failed removing parity"); return false; @@ -1115,25 +1115,25 @@ bool setDemodBufferEM(uint32_t *word, size_t idx){ return true; } -// FSK, PSK, ASK/MANCHESTER, ASK/BIPHASE, ASK/DIPHASE +// FSK, PSK, ASK/MANCHESTER, ASK/BIPHASE, ASK/DIPHASE // should cover 90% of known used configs // the rest will need to be manually demoded for now... bool demodEM4x05resp(uint32_t *word) { - size_t idx = 0; + size_t idx = 0; *word = 0; if (detectASK_MAN() && doPreambleSearch( &idx )) return setDemodBufferEM(word, idx); - + if (detectASK_BI() && doPreambleSearch( &idx )) return setDemodBufferEM(word, idx); - + if (detectFSK() && doPreambleSearch( &idx )) return setDemodBufferEM(word, idx); - + if (detectPSK()) { if (doPreambleSearch( &idx )) return setDemodBufferEM(word, idx); - + psk1TOpsk2(DemodBuffer, DemodBufferLen); if (doPreambleSearch( &idx )) return setDemodBufferEM(word, idx); @@ -1146,7 +1146,7 @@ int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word) UsbCommand c = {CMD_EM4X_READ_WORD, {addr, pwd, usePwd}}; clearCommandBuffer(); SendCommand(&c); - UsbCommand resp; + UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)){ PrintAndLogEx(DEBUG, "Command timed out"); return -1; @@ -1154,7 +1154,7 @@ int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word) if ( !downloadSamplesEM() ) { return -1; } - + return demodEM4x05resp(word); } @@ -1167,7 +1167,7 @@ int CmdEM4x05Dump(const char *Cmd) { // for now use default input of 1 as invalid (unlikely 1 will be a valid password...) pwd = param_get32ex(Cmd, 0, 1, 16); - + if ( pwd != 1 ) usePwd = true; @@ -1176,7 +1176,7 @@ int CmdEM4x05Dump(const char *Cmd) { PrintAndLogEx(NORMAL, "Addr | data | ascii"); PrintAndLogEx(NORMAL, "-----+--------+------"); for (; addr < 16; addr++) { - + if (addr == 2) { if (usePwd) { PrintAndLogEx(NORMAL, " %02u | %08X", addr, pwd, word ); @@ -1200,7 +1200,7 @@ int CmdEM4x05Read(const char *Cmd) { addr = param_get8ex(Cmd, 0, 50, 10); pwd = param_get32ex(Cmd, 1, 1, 16); - + if (addr > 15) { PrintAndLogEx(NORMAL, "Address must be between 0 and 15"); return 1; @@ -1211,7 +1211,7 @@ int CmdEM4x05Read(const char *Cmd) { usePwd = true; PrintAndLogEx(NORMAL, "Reading address %02u | password %08X", addr, pwd); } - + uint32_t word = 0; int isOk = EM4x05ReadWord_ext(addr, pwd, usePwd, &word); if (isOk) @@ -1224,38 +1224,38 @@ int CmdEM4x05Read(const char *Cmd) { int CmdEM4x05Write(const char *Cmd) { uint8_t ctmp = param_getchar(Cmd, 0); if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em4x05_write(); - - bool usePwd = false; + + bool usePwd = false; uint8_t addr = 50; // default to invalid address uint32_t data = 0; // default to blank data uint32_t pwd = 1; // default to blank password - + addr = param_get8ex(Cmd, 0, 50, 10); data = param_get32ex(Cmd, 1, 0, 16); pwd = param_get32ex(Cmd, 2, 1, 16); - + if ( addr > 15 ) { PrintAndLogEx(NORMAL, "Address must be between 0 and 15"); return 1; } if ( pwd == 1 ) - PrintAndLogEx(NORMAL, "Writing address %d data %08X", addr, data); + PrintAndLogEx(NORMAL, "Writing address %d data %08X", addr, data); else { usePwd = true; - PrintAndLogEx(NORMAL, "Writing address %d data %08X using password %08X", addr, data, pwd); + PrintAndLogEx(NORMAL, "Writing address %d data %08X using password %08X", addr, data, pwd); } - + uint16_t flag = (addr << 8 ) | usePwd; - + UsbCommand c = {CMD_EM4X_WRITE_WORD, {flag, data, pwd}}; clearCommandBuffer(); SendCommand(&c); - UsbCommand resp; + UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)){ PrintAndLogEx(WARNING, "Error occurred, device did not respond during write operation."); return -1; } - + if (!downloadSamplesEM()) return -1; @@ -1265,7 +1265,7 @@ int CmdEM4x05Write(const char *Cmd) { if (isOk) PrintAndLogEx(NORMAL, "Write Verified"); else - PrintAndLogEx(NORMAL, "Write could not be verified"); + PrintAndLogEx(NORMAL, "Write could not be verified"); return isOk; } @@ -1325,10 +1325,10 @@ void printEM4x05config(uint32_t wordData) { PrintAndLogEx(NORMAL, " PSK CF: %u | %s", PSKcf, cf); PrintAndLogEx(NORMAL, " Delay: %u | %s", delay, cdelay); PrintAndLogEx(NORMAL, " LastWordR: %02u | Address of last word for default read - meaning %u blocks are output", LWR, numblks); - PrintAndLogEx(NORMAL, " ReadLogin: %u | Read Login is %s", readLogin, readLogin ? "Required" : "Not Required"); - PrintAndLogEx(NORMAL, " ReadHKL: %u | Read Housekeeping Words Login is %s", readHKL, readHKL ? "Required" : "Not Required"); - PrintAndLogEx(NORMAL, "WriteLogin: %u | Write Login is %s", writeLogin, writeLogin ? "Required" : "Not Required"); - PrintAndLogEx(NORMAL, " WriteHKL: %u | Write Housekeeping Words Login is %s", writeHKL, writeHKL ? "Required" : "Not Required"); + PrintAndLogEx(NORMAL, " ReadLogin: %u | Read Login is %s", readLogin, readLogin ? "Required" : "Not Required"); + PrintAndLogEx(NORMAL, " ReadHKL: %u | Read Housekeeping Words Login is %s", readHKL, readHKL ? "Required" : "Not Required"); + PrintAndLogEx(NORMAL, "WriteLogin: %u | Write Login is %s", writeLogin, writeLogin ? "Required" : "Not Required"); + PrintAndLogEx(NORMAL, " WriteHKL: %u | Write Housekeeping Words Login is %s", writeHKL, writeHKL ? "Required" : "Not Required"); PrintAndLogEx(NORMAL, " R.A.W.: %u | Read After Write is %s", raw, raw ? "On" : "Off"); PrintAndLogEx(NORMAL, " Disable: %u | Disable Command is %s", disable, disable ? "Accepted" : "Not Accepted"); PrintAndLogEx(NORMAL, " R.T.F.: %u | Reader Talk First is %s", rtf, rtf ? "Enabled" : "Disabled"); @@ -1336,11 +1336,11 @@ void printEM4x05config(uint32_t wordData) { } void printEM4x05info(uint32_t block0, uint32_t serial) { - + uint8_t chipType = (block0 >> 1) & 0xF; uint8_t cap = (block0 >> 5) & 3; uint16_t custCode = (block0 >> 9) & 0x3FF; - + switch (chipType) { case 9: PrintAndLogEx(NORMAL, "\n Chip Type: %u | EM4305", chipType); break; case 8: PrintAndLogEx(NORMAL, "\n Chip Type: %u | EM4205", chipType); break; @@ -1366,7 +1366,7 @@ void printEM4x05info(uint32_t block0, uint32_t serial) { void printEM4x05ProtectionBits(uint32_t word) { for (uint8_t i = 0; i < 15; i++) { PrintAndLogEx(NORMAL, " Word: %02u | %s", i, (((1 << i) & word ) || i < 2) ? "Is Write Locked" : "Is Not Write Locked"); - if (i==14) + if (i==14) PrintAndLogEx(NORMAL, " Word: %02u | %s", i+1, (((1 << i) & word ) || i < 2) ? "Is Write Locked" : "Is Not Write Locked"); } } @@ -1390,25 +1390,25 @@ int CmdEM4x05Info(const char *Cmd) { // for now use default input of 1 as invalid (unlikely 1 will be a valid password...) pwd = param_get32ex(Cmd, 0, 1, 16); - + if ( pwd != 1 ) usePwd = true; // read word 0 (chip info) // block 0 can be read even without a password. - if ( !EM4x05IsBlock0(&block0) ) + if ( !EM4x05IsBlock0(&block0) ) return -1; - + // read word 1 (serial #) doesn't need pwd // continue if failed, .. non blocking fail. EM4x05ReadWord_ext(EM_SERIAL_BLOCK, 0, false, &serial); printEM4x05info(block0, serial); - // read word 4 (config block) + // read word 4 (config block) // needs password if one is set if ( EM4x05ReadWord_ext(EM_CONFIG_BLOCK, pwd, usePwd, &word) != 1 ) return 0; - + printEM4x05config(word); // read word 14 and 15 to see which is being used for the protection bits @@ -1428,8 +1428,8 @@ int CmdEM4x05Info(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - //{"410x_demod", CmdEMdemodASK, 0, "Extract ID from EM410x tag on antenna)"}, - {"410x_demod", CmdEM410xDemod, 0, "demodulate a EM410x tag from the GraphBuffer"}, + //{"410x_demod", CmdEMdemodASK, 0, "Extract ID from EM410x tag on antenna)"}, + {"410x_demod", CmdEM410xDemod, 0, "demodulate a EM410x tag from the GraphBuffer"}, {"410x_read", CmdEM410xRead, 1, "attempt to read and extract tag data"}, {"410x_sim", CmdEM410xSim, 0, "simulate EM410x tag"}, {"410x_brute", CmdEM410xBrute, 0, "reader bruteforce attack by simulating EM410x tags"}, diff --git a/client/cmdlfem4x.h b/client/cmdlfem4x.h index 676c6fd6b..7a8186e6a 100644 --- a/client/cmdlfem4x.h +++ b/client/cmdlfem4x.h @@ -50,7 +50,7 @@ extern void printEM410x(uint32_t hi, uint64_t id); extern int AskEm410xDecode(bool verbose, uint32_t *hi, uint64_t *lo ); extern int AskEm410xDemod(const char *Cmd, uint32_t *hi, uint64_t *lo, bool verbose); -extern int usage_lf_em410x_sim(void); +extern int usage_lf_em410x_sim(void); extern int usage_lf_em410x_ws(void); extern int usage_lf_em410x_clone(void); extern int usage_lf_em410x_sim(void); diff --git a/client/cmdlffdx.c b/client/cmdlffdx.c index 4f867b038..c87f40ba4 100644 --- a/client/cmdlffdx.c +++ b/client/cmdlffdx.c @@ -18,8 +18,8 @@ COUNTRY CODE (ISO3166) or http://cms.abvma.ca/uploads/ManufacturersISOsandCountryCodes.pdf FLAG (animal/non-animal) - 38 IDbits - 10 country code + 38 IDbits + 10 country code 1 extra app bit 14 reserved bits 1 animal bit @@ -78,12 +78,12 @@ int detectFDXB(uint8_t *dest, size_t *size) { return (int)startIdx; } -// clearing the topbit needed for the preambl detection. +// clearing the topbit needed for the preambl detection. static void verify_values(uint32_t countryid, uint64_t animalid){ if ((animalid & 0x3FFFFFFFFF) != animalid) { animalid &= 0x3FFFFFFFFF; PrintAndLogEx(INFO, "Animal ID Truncated to 38bits: %"PRIx64, animalid); - } + } if ( (countryid & 0x3ff) != countryid ) { countryid &= 0x3ff; PrintAndLogEx(INFO, "Country ID Truncated to 10bits: %03d", countryid); @@ -95,31 +95,31 @@ int getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t // add preamble ten 0x00 and one 0x01 memset(bits, 0x00, 10); bits[10] = 1; - + // 128bits // every 9th bit is 0x01, but we can just fill the rest with 0x01 and overwrite memset(bits, 0x01, 128); - + // add preamble ten 0x00 and one 0x01 memset(bits, 0x00, 10); - // add reserved + // add reserved num_to_bytebitsLSBF(0x00, 7, bits + 66); num_to_bytebitsLSBF(0x00 >> 7, 7, bits + 74); // add animal flag - OK bits[65] = isanimal; - + // add extended flag - OK bits[81] = isextended; - + // add national code 40bits - OK num_to_bytebitsLSBF(national_id >> 0, 8, bits+11); num_to_bytebitsLSBF(national_id >> 8, 8, bits+20); num_to_bytebitsLSBF(national_id >> 16, 8, bits+29); num_to_bytebitsLSBF(national_id >> 24, 8, bits+38); num_to_bytebitsLSBF(national_id >> 32, 6, bits+47); - + // add country code - OK num_to_bytebitsLSBF(country >> 0, 2, bits+53); num_to_bytebitsLSBF(country >> 2, 8, bits+56); @@ -128,11 +128,11 @@ int getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t uint8_t raw[8]; for (uint8_t i=0; i<8; ++i) raw[i] = bytebits_to_byte(bits + 11 + i * 9, 8); - + uint16_t crc = crc16_kermit(raw, 8); num_to_bytebitsLSBF(crc >> 0, 8, bits+83); num_to_bytebitsLSBF(crc >> 8, 8, bits+92); - + // extended data - OK num_to_bytebitsLSBF( extended >> 0 , 8, bits+101); num_to_bytebitsLSBF( extended >> 8 , 8, bits+110); @@ -147,8 +147,8 @@ int getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t // COUNTRY CODE (ISO3166) or http://cms.abvma.ca/uploads/ManufacturersISOsandCountryCodes.pdf // FLAG (animal/non-animal) /* -38 IDbits -10 country code +38 IDbits +10 country code 1 extra app bit 14 reserved bits 1 animal bit @@ -161,11 +161,11 @@ int CmdFDXBdemodBI(const char *Cmd){ int clk = 32; int invert = 1, errCnt = 0, offset = 0, maxErr = 0; - uint8_t bs[MAX_DEMOD_BUF_LEN]; - size_t size = getFromGraphBuf(bs); - + uint8_t bs[MAX_DEMOD_BUF_LEN]; + size_t size = getFromGraphBuf(bs); + errCnt = askdemod(bs, &size, &clk, &invert, maxErr, 0, 0); - if ( errCnt < 0 || errCnt > maxErr ) { + if ( errCnt < 0 || errCnt > maxErr ) { PrintAndLogEx(DEBUG, "DEBUG: Error - FDXB no data or error found %d, clock: %d", errCnt, clk); return 0; } @@ -174,8 +174,8 @@ int CmdFDXBdemodBI(const char *Cmd){ if (errCnt < 0 || errCnt > maxErr ) { PrintAndLogEx(DEBUG, "DEBUG: Error - FDXB BiphaseRawDecode: %d", errCnt); return 0; - } - + } + int preambleIndex = detectFDXB(bs, &size); if (preambleIndex < 0){ PrintAndLogEx(DEBUG, "DEBUG: Error - FDXB preamble not found :: %d",preambleIndex); @@ -185,7 +185,7 @@ int CmdFDXBdemodBI(const char *Cmd){ PrintAndLogEx(DEBUG, "DEBUG: Error - FDXB incorrect data length found"); return 0; } - + setDemodBuf(bs, 128, preambleIndex); // remove marker bits (1's every 9th digit after preamble) (pType = 2) @@ -231,7 +231,7 @@ int CmdFDXBdemodBI(const char *Cmd){ //see ASKDemod for what args are accepted -//almost the same demod as cmddata.c/CmdFDXBdemodBI +//almost the same demod as cmddata.c/CmdFDXBdemodBI int CmdFdxDemod(const char *Cmd) { //Differential Biphase / di-phase (inverted biphase) @@ -279,25 +279,25 @@ int CmdFdxDemod(const char *Cmd) { uint16_t calcCrc = crc16_kermit(raw, 8); - + PrintAndLogEx(SUCCESS, "\nFDX-B / ISO 11784/5 Animal Tag ID Found: Raw : %s", sprint_hex(raw, 8)); PrintAndLogEx(SUCCESS, "Animal ID %04u-%012" PRIu64, countryCode, NationalCode); PrintAndLogEx(SUCCESS, "National Code %012" PRIu64 " (0x%" PRIx64 ")", NationalCode, NationalCode); PrintAndLogEx(SUCCESS, "Country Code %04u", countryCode); PrintAndLogEx(SUCCESS, "Reserved/RFU %u (0x04%X)", reservedCode, reservedCode); - PrintAndLogEx(SUCCESS, "Animal Tag %s", animalBit ? _YELLOW_(True) : "False"); - PrintAndLogEx(SUCCESS, "Has extended data %s [0x%X]", dataBlockBit ? _YELLOW_(True) : "False", extended); + PrintAndLogEx(SUCCESS, "Animal Tag %s", animalBit ? _YELLOW_(True) : "False"); + PrintAndLogEx(SUCCESS, "Has extended data %s [0x%X]", dataBlockBit ? _YELLOW_(True) : "False", extended); PrintAndLogEx(SUCCESS, "CRC-16 0x%04X - 0x%04X [%s]", crc16, calcCrc, (calcCrc == crc16) ? _GREEN_(Ok) : "Failed"); if (g_debugMode) { - PrintAndLogEx(DEBUG, "Start marker %d; Size %d", preambleIndex, size); + PrintAndLogEx(DEBUG, "Start marker %d; Size %d", preambleIndex, size); char *bin = sprint_bin_break(DemodBuffer, size, 16); PrintAndLogEx(DEBUG, "DEBUG bin stream:\n%s", bin); } // set block 0 for later //g_DemodConfig = T55x7_MODULATION_DIPHASE | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT; - + return 1; } @@ -314,20 +314,20 @@ int CmdFdxClone(const char *Cmd) { uint8_t bits[128]; uint8_t *bs = bits; memset(bs, 0, sizeof(bits)); - + char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_fdx_clone(); countryid = param_get32ex(Cmd, 0, 0, 10); animalid = param_get64ex(Cmd, 1, 0, 10); - + verify_values(countryid, animalid); - - // getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t isextended, uint32_t extended, uint8_t *bits) + + // getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t isextended, uint32_t extended, uint8_t *bits) if ( !getFDXBits(animalid, countryid, 1, 0, 0, bs)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); return 1; - } + } //Q5 if (param_getchar(Cmd, 2) == 'Q' || param_getchar(Cmd, 2) == 'q') @@ -341,7 +341,7 @@ int CmdFdxClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone FDX-B to T55x7 with animal ID: %04u-%"PRIu64, countryid, animalid); print_blocks(blocks, 5); - + UsbCommand resp; UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}}; @@ -367,9 +367,9 @@ int CmdFdxSim(const char *Cmd) { countryid = param_get32ex(Cmd, 0, 0, 10); animalid = param_get64ex(Cmd, 1, 0, 10); - + verify_values(countryid, animalid); - + // 32, no STT, BIPHASE INVERTED == diphase uint8_t clk = 32, encoding = 2, separator = 0, invert = 1; uint16_t arg1, arg2; @@ -381,7 +381,7 @@ int CmdFdxSim(const char *Cmd) { UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; - //getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t isextended, uint32_t extended, uint8_t *bits) + //getFDXBits(uint64_t national_id, uint16_t country, uint8_t isanimal, uint8_t isextended, uint32_t extended, uint8_t *bits) getFDXBits(animalid, countryid, 1, 0, 0, c.d.asBytes); clearCommandBuffer(); SendCommand(&c); diff --git a/client/cmdlffdx.h b/client/cmdlffdx.h index b7b019909..107bb83ec 100644 --- a/client/cmdlffdx.h +++ b/client/cmdlffdx.h @@ -17,7 +17,7 @@ #include "cmdlf.h" // lf read #include "crc16.h" // for checksum crc-16_ccitt #include "protocols.h" // for T55xx config register definitions -#include "lfdemod.h" // parityTest +#include "lfdemod.h" // parityTest extern int CmdLFFdx(const char *Cmd); extern int CmdFdxClone(const char *Cmd); diff --git a/client/cmdlfguard.c b/client/cmdlfguard.c index 5707c78fb..3e3642766 100644 --- a/client/cmdlfguard.c +++ b/client/cmdlfguard.c @@ -18,7 +18,7 @@ int usage_lf_guard_clone(void){ PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: lf gprox clone [h] "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " : format length 26|32|36|40"); + PrintAndLogEx(NORMAL, " : format length 26|32|36|40"); PrintAndLogEx(NORMAL, " : 8-bit value facility code"); PrintAndLogEx(NORMAL, " : 16-bit value card number"); PrintAndLogEx(NORMAL, ""); @@ -35,7 +35,7 @@ int usage_lf_guard_sim(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: lf gprox sim [h] "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " : format length 26|32|36|40"); + PrintAndLogEx(NORMAL, " : format length 26|32|36|40"); PrintAndLogEx(NORMAL, " : 8-bit value facility code"); PrintAndLogEx(NORMAL, " : 16-bit value card number"); PrintAndLogEx(NORMAL, ""); @@ -46,33 +46,33 @@ int usage_lf_guard_sim(void) { // Works for 26bits. int GetGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) { - + uint8_t xorKey = 0x66; uint8_t i; uint8_t pre[96]; uint8_t rawbytes[12]; memset(pre, 0x00, sizeof(pre)); - memset(rawbytes, 0x00, sizeof(rawbytes)); + memset(rawbytes, 0x00, sizeof(rawbytes)); // add format length (decimal) switch (fmtlen) { case 32: { rawbytes[1] = (32 << 2); - + break; } case 36: { // FC = ((ByteStream[3] & 0x7F)<<7) | (ByteStream[4]>>1); // Card = ((ByteStream[4]&1)<<19) | (ByteStream[5]<<11) | (ByteStream[6]<<3) | (ByteStream[7]>>5); rawbytes[1] = (36 << 2); - // Get 26 wiegand from FacilityCode, CardNumber + // Get 26 wiegand from FacilityCode, CardNumber uint8_t wiegand[34]; memset(wiegand, 0x00, sizeof(wiegand)); num_to_bytebits(fc, 8, wiegand); num_to_bytebits(cn, 26, wiegand+8); // add wiegand parity bits (dest, source, len) - wiegand_add_parity(pre, wiegand, 34); + wiegand_add_parity(pre, wiegand, 34); break; } case 40: { @@ -82,7 +82,7 @@ int GetGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) { case 26: default: { rawbytes[1] = (26 << 2); - // Get 26 wiegand from FacilityCode, CardNumber + // Get 26 wiegand from FacilityCode, CardNumber uint8_t wiegand[24]; memset(wiegand, 0x00, sizeof(wiegand)); num_to_bytebits(fc, 8, wiegand); @@ -93,27 +93,27 @@ int GetGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) { break; } } - // 2bit checksum, unknown today, + // 2bit checksum, unknown today, // these two bits are the last ones of rawbyte[1], hence the LSHIFT above. - + // xor key rawbytes[0] = xorKey; - + rawbytes[2] = 1; rawbytes[3] = 0; - + // add wiegand to rawbytes for (i = 0; i < 4; ++i) rawbytes[i+4] = bytebits_to_byte( pre + (i*8), 8); - - PrintAndLogEx(DEBUG, " WIE | %s\n", sprint_hex(rawbytes, sizeof(rawbytes))); - - + + PrintAndLogEx(DEBUG, " WIE | %s\n", sprint_hex(rawbytes, sizeof(rawbytes))); + + // XOR (only works on wiegand stuff) for (i = 1; i < 12; ++i) rawbytes[i] ^= xorKey ; - + PrintAndLogEx(DEBUG, " XOR | %s \n", sprint_hex(rawbytes, sizeof(rawbytes))); // convert rawbytes to bits in pre @@ -122,7 +122,7 @@ int GetGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) { PrintAndLogEx(DEBUG, "\n Raw | %s \n", sprint_hex(rawbytes, sizeof(rawbytes))); PrintAndLogEx(DEBUG, " Raw | %s\n", sprint_bin(pre, 64) ); - + // add spacer bit 0 every 4 bits, starting with index 0, // 12 bytes, 24 nibbles. 24+1 extra bites. 3bytes. ie 9bytes | 1byte xorkey, 8bytes rawdata (64bits, should be enough for a 40bit wiegand) addParity(pre, guardBits+6, 64, 5, 3); @@ -134,30 +134,30 @@ int GetGuardBits(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint8_t *guardBits) { guardBits[3] = 1; guardBits[4] = 1; guardBits[5] = 0; - + PrintAndLogEx(DEBUG, " FIN | %s\n", sprint_bin(guardBits, 96) ); return 1; } // by marshmellow -// demod gProxIIDemod -// error returns as -x +// demod gProxIIDemod +// error returns as -x // success returns start position in bitstream // Bitstream must contain previously askrawdemod and biphasedemoded data int detectGProxII(uint8_t *bits, size_t *size) { - + size_t startIdx = 0; uint8_t preamble[] = {1,1,1,1,1,0}; // sanity check if ( *size < sizeof(preamble) ) return -1; - - if (!preambleSearch(bits, preamble, sizeof(preamble), size, &startIdx)) + + if (!preambleSearch(bits, preamble, sizeof(preamble), size, &startIdx)) return -2; //preamble not found //gProxII should be 96 bits - if (*size != 96) return -3; - + if (*size != 96) return -3; + //check first 6 spacer bits to verify format if (!bits[startIdx+5] && !bits[startIdx+10] && !bits[startIdx+15] && !bits[startIdx+20] && !bits[startIdx+25] && !bits[startIdx+30]){ //confirmed proper separator bits found @@ -180,7 +180,7 @@ int CmdGuardDemod(const char *Cmd) { PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII ASKbiphaseDemod failed"); return 0; } - + size_t size = DemodBufferLen; int preambleIndex = detectGProxII(DemodBuffer, &size); @@ -194,11 +194,11 @@ int CmdGuardDemod(const char *Cmd) { PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII size not correct: %d", size); else if (preambleIndex == -5) PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII wrong spacerbits"); - else + else PrintAndLogEx(DEBUG, "DEBUG: Error - gProxII ans: %d", preambleIndex); return 0; } - + //got a good demod of 96 bits uint8_t ByteStream[8] = {0x00}; uint8_t xorKey = 0; @@ -221,8 +221,8 @@ int CmdGuardDemod(const char *Cmd) { } setDemodBuf(DemodBuffer, 96, preambleIndex); - setClockGrid(g_DemodClock, g_DemodStartIdx + (preambleIndex*g_DemodClock)); - + setClockGrid(g_DemodClock, g_DemodStartIdx + (preambleIndex*g_DemodClock)); + //ByteStream contains 8 Bytes (64 bits) of decrypted raw tag data uint8_t fmtLen = ByteStream[0] >> 2; uint32_t FC = 0; @@ -237,7 +237,7 @@ int CmdGuardDemod(const char *Cmd) { FC = ((ByteStream[3] & 0x7F)<<7) | (ByteStream[4]>>1); Card = ((ByteStream[4]&1)<<19) | (ByteStream[5]<<11) | (ByteStream[6]<<3) | (ByteStream[7]>>5); break; - case 26: + case 26: FC = ((ByteStream[3] & 0x7F)<<1) | (ByteStream[4]>>7); Card = ((ByteStream[4]&0x7F)<<9) | (ByteStream[5]<<1) | (ByteStream[6]>>7); break; @@ -267,20 +267,20 @@ int CmdGuardClone(const char *Cmd) { uint8_t i; uint8_t bs[96]; memset(bs, 0x00, sizeof(bs)); - + //GuardProxII - compat mode, ASK/Biphase, data rate 64, 3 data blocks uint32_t blocks[4] = {T55x7_MODULATION_BIPHASE | T55x7_BITRATE_RF_64 | 3 << T55x7_MAXBLOCK_SHIFT, 0, 0, 0}; - + if (sscanf(Cmd, "%u %u %u", &fmtlen, &fc, &cn ) != 3) return usage_lf_guard_clone(); fmtlen &= 0x7f; facilitycode = (fc & 0x000000FF); cardnumber = (cn & 0x0000FFFF); - + if ( !GetGuardBits(fmtlen, facilitycode, cardnumber, bs)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); return 1; - } + } // Q5 if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q') @@ -321,17 +321,17 @@ int CmdGuardSim(const char *Cmd) { if (sscanf(Cmd, "%u %u %u", &fmtlen, &fc, &cn ) != 3) return usage_lf_guard_sim(); uint8_t bs[96]; - size_t size = sizeof(bs); + size_t size = sizeof(bs); memset(bs, 0x00, size); fmtlen &= 0x7F; facilitycode = (fc & 0x000000FF); cardnumber = (cn & 0x0000FFFF); - + if ( !GetGuardBits(fmtlen, facilitycode, cardnumber, bs)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); return 1; - } + } PrintAndLogEx(SUCCESS, "Simulating Guardall - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber ); diff --git a/client/cmdlfhid.c b/client/cmdlfhid.c index 7d1bda95c..87cb8d160 100644 --- a/client/cmdlfhid.c +++ b/client/cmdlfhid.c @@ -23,12 +23,12 @@ int usage_lf_hid_read(void){ PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: lf hid read [h] [1]"); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " 1 : (optional) stop after reading a single card"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf hid read"); - PrintAndLogEx(NORMAL, " lf hid read 1"); + PrintAndLogEx(NORMAL, " lf hid read 1"); return 0; } int usage_lf_hid_wiegand(void){ @@ -76,7 +76,7 @@ int usage_lf_hid_brute(void){ PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: lf hid brute [h] [v] a f c d "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " a : 26|33|34|35|37|40|44|84"); PrintAndLogEx(NORMAL, " f : 8-bit value HID facility code"); PrintAndLogEx(NORMAL, " c : (optional) cardnumber to start with, max 65535"); @@ -94,8 +94,8 @@ int usage_lf_hid_brute(void){ static bool sendPing(void){ UsbCommand ping = {CMD_PING, {1, 2, 3}}; SendCommand(&ping); - SendCommand(&ping); - SendCommand(&ping); + SendCommand(&ping); + SendCommand(&ping); clearCommandBuffer(); UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 1000)) @@ -107,12 +107,12 @@ static bool sendTry(uint8_t fmtlen, uint32_t fc, uint32_t cn, uint32_t delay, ui // this should be optional. if ( verbose ) PrintAndLogEx(INFO, "Trying FC: %u; CN: %u", fc, cn); - + calcWiegand( fmtlen, fc, cn, bits); uint64_t arg1 = bytebits_to_byte(bits, 32); uint64_t arg2 = bytebits_to_byte(bits + 32, 32); - UsbCommand c = {CMD_HID_SIM_TAG, {arg1, arg2, 0}}; + UsbCommand c = {CMD_HID_SIM_TAG, {arg1, arg2, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -157,12 +157,12 @@ int CmdHIDDemod(const char *Cmd) { setDemodBuf(bits, size, idx); setClockGrid(50, waveIdx + (idx*50)); - + if (hi2==0 && hi==0 && lo==0) { PrintAndLogEx(DEBUG, "DEBUG: Error - HID no values found"); return 0; } - + if (hi2 != 0){ //extra large HID tags PrintAndLogEx(SUCCESS, "HID Prox TAG ID: %x%08x%08x (%u)", hi2, hi, lo, (lo>>1) & 0xFFFF); } else { //standard HID tags <38 bits @@ -216,9 +216,9 @@ int CmdHIDDemod(const char *Cmd) { } PrintAndLogEx(DEBUG, "DEBUG: HID idx: %d, Len: %d, Printing Demod Buffer:", idx, size); - if (g_debugMode) + if (g_debugMode) printDemodBuff(); - + return 1; } @@ -231,7 +231,7 @@ int CmdHIDRead(const char *Cmd) { // this read loops on device side. // uses the demod in lfops.c int CmdHIDRead_device(const char *Cmd) { - + if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_lf_hid_read(); uint8_t findone = ( Cmd[0] == '1' ) ? 1 : 0; UsbCommand c = {CMD_HID_DEMOD_FSK, {findone, 0 , 0}}; @@ -246,7 +246,7 @@ int CmdHIDSim(const char *Cmd) { uint8_t ctmp = tolower(param_getchar(Cmd, 0)); if ( strlen(Cmd) == 0 || ctmp == 'h' ) return usage_lf_hid_sim(); - + while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { hi = (hi << 4) | (lo >> 28); lo = (lo << 4) | (n & 0xf); @@ -262,7 +262,7 @@ int CmdHIDSim(const char *Cmd) { } int CmdHIDClone(const char *Cmd) { - + uint32_t hi2 = 0, hi = 0, lo = 0; uint32_t n = 0, i = 0; UsbCommand c = {CMD_HID_CLONE_TAG}; @@ -308,7 +308,7 @@ typedef struct { size_t Wiegand_n; } wiegand_t; -static void addHIDMarker(uint8_t fmtlen, uint8_t *out) { +static void addHIDMarker(uint8_t fmtlen, uint8_t *out) { // temp array uint8_t arr[BITS]; memset(arr, 0, BITS); @@ -316,7 +316,7 @@ static void addHIDMarker(uint8_t fmtlen, uint8_t *out) { // copy inpu uint8_t pos = sizeof(arr)-fmtlen; memcpy(arr+pos, out, fmtlen); - + switch(fmtlen) { case 26:{ // start sentinel, BITS-bit 27 = 1 @@ -329,7 +329,7 @@ static void addHIDMarker(uint8_t fmtlen, uint8_t *out) { case 34: // start sentinel, BITS-bit 27 = 1 arr[BITS-35] = 1; - + // fmt smaller than 37 used, bit37 = 1 arr[BITS-38] = 1; memcpy(out, arr, BITS); @@ -342,13 +342,13 @@ static void addHIDMarker(uint8_t fmtlen, uint8_t *out) { // uint32_t result = 0; // int i; - // // even parity + // // even parity // for (i = 7;i >= 0;i--) // result ^= (*hi >> i) & i; // for (i = 31;i >= 24;i--) // result ^= (*lo >> i) & 1; - // *hi |= result << 2; + // *hi |= result << 2; // // odd parity bit // result = 0; @@ -388,14 +388,14 @@ static void calc34(uint16_t fc, uint32_t cardno, uint8_t *out){ uint8_t wiegand[32]; num_to_bytebits(fc, 16, wiegand); num_to_bytebits(cardno, 16, wiegand + 16); - wiegand_add_parity(out, wiegand, sizeof(wiegand) ); + wiegand_add_parity(out, wiegand, sizeof(wiegand) ); } // static void calc35(uint16_t fc, uint32_t cardno, uint8_t *out){ - // *lo = ((cardno & 0xFFFFF) << 1) | fc << 21; - // *hi = (1 << 5) | ((fc >> 11) & 1); + // *lo = ((cardno & 0xFFFFF) << 1) | fc << 21; + // *hi = (1 << 5) | ((fc >> 11) & 1); // } static void calc37S(uint16_t fc, uint32_t cardno, uint8_t *out){ - // FC 2 - 17 - 16 bit + // FC 2 - 17 - 16 bit // cardno 18 - 36 - 19 bit // Even P1 1 - 19 // Odd P37 19 - 36 @@ -406,20 +406,20 @@ static void calc37S(uint16_t fc, uint32_t cardno, uint8_t *out){ } static void calc37H(uint64_t cardno, uint8_t *out){ // SC NONE - // cardno 1-35 34 bits + // cardno 1-35 34 bits // Even Parity 0th bit 1-18 // Odd Parity 36th bit 19-35 uint8_t wiegand[37]; num_to_bytebits( (uint32_t)(cardno >> 32), 2, wiegand); num_to_bytebits( (uint32_t)(cardno >> 0), 32, wiegand + 2); wiegand_add_parity(out, wiegand, sizeof(wiegand) ); - + PrintAndLogEx(NORMAL, "%x %x\n", (uint32_t)(cardno >> 32), (uint32_t)cardno ); } // static void calc40(uint64_t cardno, uint8_t *out){ // cardno = (cardno & 0xFFFFFFFFFF); - // *lo = ((cardno & 0xFFFFFFFF) << 1 ); - // *hi = (cardno >> 31); + // *lo = ((cardno & 0xFFFFFFFF) << 1 ); + // *hi = (cardno >> 31); // } void calcWiegand(uint8_t fmtlen, uint16_t fc, uint64_t cardno, uint8_t *bits){ @@ -436,17 +436,17 @@ void calcWiegand(uint8_t fmtlen, uint16_t fc, uint64_t cardno, uint8_t *bits){ // case 84 : { break; } default: break; } -} +} int CmdHIDWiegand(const char *Cmd) { uint32_t oem = 0, fc = 0; uint64_t cardnum = 0; - uint64_t blocks = 0, wiegand = 0; + uint64_t blocks = 0, wiegand = 0; uint8_t bits[BITS]; uint8_t *bs = bits; memset(bs, 0, sizeof(bits)); - + uint8_t ctmp = param_getchar(Cmd, 0); if ( strlen(Cmd) == 0 || strlen(Cmd) < 3 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_hid_wiegand(); @@ -455,7 +455,7 @@ int CmdHIDWiegand(const char *Cmd) { cardnum = param_get64ex(Cmd, 2, 0, 10); uint8_t fmtlen[] = {26,33,34,35,37,38,40}; - + PrintAndLogEx(NORMAL, "HID | OEM | FC | CN | Wiegand | HID Formatted"); PrintAndLogEx(NORMAL, "----+-----+------+---------+-----------+--------------------"); for (uint8_t i = 0; i < sizeof(fmtlen); i++){ @@ -463,13 +463,13 @@ int CmdHIDWiegand(const char *Cmd) { calcWiegand( fmtlen[i], fc, cardnum, bs); PrintAndLogEx(NORMAL, "ice:: %s \n", sprint_bin(bs, fmtlen[i])); wiegand = (uint64_t)bytebits_to_byte(bs, 32) << 32 | bytebits_to_byte(bs+32, 32); - - addHIDMarker(fmtlen[i], bs); + + addHIDMarker(fmtlen[i], bs); PrintAndLogEx(NORMAL, "ice:: %s\n", sprint_bin(bs, BITS)); blocks = (uint64_t)bytebits_to_byte(bs+32, 32) << 32 | bytebits_to_byte(bs+64, 32); - uint8_t shifts = 64-fmtlen[i]; + uint8_t shifts = 64-fmtlen[i]; wiegand >>= shifts; - + PrintAndLogEx(NORMAL, " %u | %03u | %03u | %" PRIu64 " | %" PRIX64 " | %" PRIX64 , fmtlen[i], oem, @@ -484,14 +484,14 @@ int CmdHIDWiegand(const char *Cmd) { } int CmdHIDBrute(const char *Cmd){ - + bool errors = false, verbose = false; uint32_t fc = 0, cn = 0, delay = 1000; uint8_t fmtlen = 0; uint8_t bits[96]; memset(bits, 0, sizeof(bits)); uint8_t cmdp = 0; - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': @@ -503,7 +503,7 @@ int CmdHIDBrute(const char *Cmd){ cmdp += 2; break; case 'd': - // delay between attemps, defaults to 1000ms. + // delay between attemps, defaults to 1000ms. delay = param_get32ex(Cmd, cmdp+1, 1000, 10); cmdp += 2; break; @@ -526,7 +526,7 @@ int CmdHIDBrute(const char *Cmd){ // negated errors = !is_ftm_ok; break; - case 'v': + case 'v': verbose = true; cmdp++; break; @@ -538,31 +538,31 @@ int CmdHIDBrute(const char *Cmd){ } if ( fc == 0 ) errors = true; if ( errors ) return usage_lf_hid_brute(); - + PrintAndLogEx(INFO, "Brute-forcing HID reader"); PrintAndLogEx(INFO, "Press pm3-button to abort simulation or run another command"); - + uint16_t up = cn; uint16_t down = cn; - + // main loop for (;;){ - + if ( IsOffline() ) { PrintAndLogEx(WARNING, "Device offline\n"); return 2; } - + if (ukbhit()) { int gc = getchar(); (void)gc; PrintAndLogEx(INFO, "aborted via keyboard!"); return sendPing(); } - + // Do one up if ( up < 0xFFFF ) if ( !sendTry(fmtlen, fc, up++, delay, bits, verbose)) return 1; - + // Do one down (if cardnumber is given) if ( cn > 1 ) if ( down > 1 ) diff --git a/client/cmdlfhid.h b/client/cmdlfhid.h index c34a48406..895117960 100644 --- a/client/cmdlfhid.h +++ b/client/cmdlfhid.h @@ -20,7 +20,7 @@ #include "util.h" // wiegand_add_parity etc #include "cmddata.h" //for g_debugMode, demodbuff cmds #include "cmdlf.h" // lf_read -#include "cmdmain.h" +#include "cmdmain.h" #include "util_posix.h" #include "lfdemod.h" diff --git a/client/cmdlfhitag.c b/client/cmdlfhitag.c index 69bae1b38..45aeea317 100644 --- a/client/cmdlfhitag.c +++ b/client/cmdlfhitag.c @@ -43,7 +43,7 @@ int CmdLFHitagList(const char *Cmd) { free(got); return 2; } - + uint16_t traceLen = response.arg[2]; if (traceLen > USB_CMD_DATA_SIZE) { uint8_t *p = realloc(got, traceLen); @@ -59,7 +59,7 @@ int CmdLFHitagList(const char *Cmd) { return 2; } } - + PrintAndLogEx(NORMAL, "recorded activity (TraceLen = %d bytes):"); PrintAndLogEx(NORMAL, " ETU :nbits: who bytes"); PrintAndLogEx(NORMAL, "---------+-----+----+-----------"); @@ -70,11 +70,11 @@ int CmdLFHitagList(const char *Cmd) { char filename[FILE_PATH_SIZE] = { 0x00 }; FILE* f = NULL; - + if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; - + memcpy(filename, Cmd, len); - + if (strlen(filename) > 0) { f = fopen(filename,"wb"); if (!f) { @@ -84,7 +84,7 @@ int CmdLFHitagList(const char *Cmd) { } for (;;) { - + if(i >= traceLen) { break; } bool isResponse; @@ -143,11 +143,11 @@ int CmdLFHitagList(const char *Cmd) { (isResponse ? "TAG" : " "), line); } - + prev = timestamp; i += (len + 9); } - + if (f) { fclose(f); PrintAndLogEx(NORMAL, "Recorded activity succesfully written to file: %s", filename); @@ -165,12 +165,12 @@ int CmdLFHitagSnoop(const char *Cmd) { } int CmdLFHitagSim(const char *Cmd) { - + UsbCommand c = {CMD_SIMULATE_HITAG}; char filename[FILE_PATH_SIZE] = { 0x00 }; FILE* f; bool tag_mem_supplied; - + int len = strlen(Cmd); if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; memcpy(filename, Cmd, len); @@ -201,11 +201,11 @@ int CmdLFHitagSim(const char *Cmd) { } int CmdLFHitagReader(const char *Cmd) { - + UsbCommand c = {CMD_READER_HITAG, {0,0,0} };//, {param_get32ex(Cmd,0,0,10),param_get32ex(Cmd,1,0,16),param_get32ex(Cmd,2,0,16),param_get32ex(Cmd,3,0,16)}}; hitag_data* htd = (hitag_data*)c.d.asBytes; hitag_function htf = param_get32ex(Cmd, 0, 0, 10); - + switch (htf) { case 01: { //RHTSF_CHALLENGE c.cmd = CMD_READ_HITAG_S; @@ -255,7 +255,7 @@ int CmdLFHitagReader(const char *Cmd) { c.arg[0] = htf; clearCommandBuffer(); SendCommand(&c); - UsbCommand resp; + UsbCommand resp; if ( !WaitForResponseTimeout(CMD_ACK, &resp, 4000) ) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); return 1; @@ -333,7 +333,7 @@ int CmdLFHitagCheckChallenges(const char *Cmd) { if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; memcpy(filename, Cmd, len); - + if (strlen(filename) > 0) { f = fopen(filename,"rb+"); if ( !f ) { @@ -351,7 +351,7 @@ int CmdLFHitagCheckChallenges(const char *Cmd) { } else { file_given = false; } - + //file with all the challenges to try c.arg[0] = (uint32_t)file_given; clearCommandBuffer(); @@ -406,7 +406,7 @@ static command_t CommandTable[] = { {"list", CmdLFHitagList, 1, " List Hitag trace history"}, {"reader", CmdLFHitagReader, 1, "Act like a Hitag Reader"}, {"sim", CmdLFHitagSim, 1, " Simulate Hitag transponder"}, - {"simS", CmdLFHitagSimS, 1, " Simulate HitagS transponder" }, + {"simS", CmdLFHitagSimS, 1, " Simulate HitagS transponder" }, {"snoop", CmdLFHitagSnoop, 1, "Eavesdrop Hitag communication"}, {"writer", CmdLFHitagWP, 1, "Act like a Hitag Writer" }, {"check_challenges", CmdLFHitagCheckChallenges, 1, " test all challenges" }, diff --git a/client/cmdlfindala.c b/client/cmdlfindala.c index 1707895b0..17e3455d9 100644 --- a/client/cmdlfindala.c +++ b/client/cmdlfindala.c @@ -31,7 +31,7 @@ int usage_lf_indala_sim(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: lf indala sim [h] "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " : 64/224 UID"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); @@ -45,7 +45,7 @@ int usage_lf_indala_clone(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: lf indala clone [h] [Q5]"); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " : 64/224 UID"); PrintAndLogEx(NORMAL, " Q5 : optional - clone to Q5 (T5555) instead of T55x7 chip"); PrintAndLogEx(NORMAL, ""); @@ -70,10 +70,10 @@ int indala64decode(uint8_t *dest, size_t *size, uint8_t *invert) { if (found_size != 64) return -2; if (*invert == 1) - for (size_t i = idx; i < found_size + idx; i++) + for (size_t i = idx; i < found_size + idx; i++) dest[i] ^= 1; - // note: don't change *size until we are sure we got it... + // note: don't change *size until we are sure we got it... *size = found_size; return (int) idx; } @@ -90,9 +90,9 @@ int indala224decode(uint8_t *dest, size_t *size, uint8_t *invert) { *invert ^= 1; } if (found_size != 224) return -2; - + if (*invert==1 && idx > 0) - for (size_t i = idx-1; i < found_size + idx + 2; i++) + for (size_t i = idx-1; i < found_size + idx + 2; i++) dest[i] ^= 1; // 224 formats are typically PSK2 (afaik 2017 Marshmellow) @@ -139,14 +139,14 @@ int CmdIndalaDemod(const char *Cmd) { return 0; } } - + setDemodBuf(DemodBuffer, size, (size_t)idx); setClockGrid(g_DemodClock, g_DemodStartIdx + (idx * g_DemodClock)); if (invert) { - PrintAndLogEx(DEBUG, "DEBUG: Error - Indala had to invert bits"); - for (size_t i = 0; i < size; i++) + PrintAndLogEx(DEBUG, "DEBUG: Error - Indala had to invert bits"); + for (size_t i = 0; i < size; i++) DemodBuffer[i] ^= 1; - } + } //convert UID to HEX uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7; @@ -162,7 +162,7 @@ int CmdIndalaDemod(const char *Cmd) { uid5 = bytebits_to_byte(DemodBuffer+128,32); uid6 = bytebits_to_byte(DemodBuffer+160,32); uid7 = bytebits_to_byte(DemodBuffer+192,32); - PrintAndLogEx(SUCCESS, "Indala Found - bitlength %d, UID = (0x%x%08x%08x%08x%08x%08x%08x)\n%s", + PrintAndLogEx(SUCCESS, "Indala Found - bitlength %d, UID = (0x%x%08x%08x%08x%08x%08x%08x)\n%s", DemodBufferLen, uid1, uid2, uid3, uid4, uid5, uid6, uid7, sprint_bin_break(DemodBuffer, DemodBufferLen, 32) ); @@ -188,7 +188,7 @@ int CmdIndalaDemodAlt(const char *Cmd) { // under normal conditions it's < 2048 uint8_t data[MAX_GRAPH_TRACE_LEN] = {0}; size_t datasize = getFromGraphBuf(data); - + uint8_t rawbits[4096]; int rawbit = 0; int worst = 0, worstPos = 0; @@ -196,7 +196,7 @@ int CmdIndalaDemodAlt(const char *Cmd) { //clear clock grid and demod plot setClockGrid(0, 0); DemodBufferLen = 0; - + // PrintAndLogEx(NORMAL, "Expecting a bit less than %d raw bits", GraphTraceLen / 32); // loop through raw signal - since we know it is psk1 rf/32 fc/2 skip every other value (+=2) for (i = 0; i < datasize-1; i += 2) { @@ -229,7 +229,7 @@ int CmdIndalaDemodAlt(const char *Cmd) { count = 0; } } - + if (rawbit > 0){ PrintAndLogEx(INFO, "Recovered %d raw bits, expected: %d", rawbit, GraphTraceLen/32); PrintAndLogEx(INFO, "worst metric (0=best..7=worst): %d at pos %d", worst, worstPos); @@ -260,7 +260,7 @@ int CmdIndalaDemodAlt(const char *Cmd) { break; } } - + if (start == rawbit - uidlen + 1) { PrintAndLogEx(FAILED, "nothing to wait for"); return 0; @@ -279,7 +279,7 @@ int CmdIndalaDemodAlt(const char *Cmd) { int bit; i = start; int times = 0; - + if (uidlen > rawbit) { PrintAndLogEx(WARNING, "Warning: not enough raw bits to get a full UID"); for (bit = 0; bit < rawbit; bit++) { @@ -297,12 +297,12 @@ int CmdIndalaDemodAlt(const char *Cmd) { } times = 1; } - + //convert UID to HEX uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7; int idx; uid1 = uid2 = 0; - + if (uidlen == 64){ for( idx=0; idx < 64; idx++) { if (showbits[idx] == '0') { @@ -311,7 +311,7 @@ int CmdIndalaDemodAlt(const char *Cmd) { } else { uid1 = (uid1<<1) | (uid2>>31); uid2 = (uid2<<1) | 1; - } + } } PrintAndLogEx(SUCCESS, "UID | %s (%x%08x)", showbits, uid1, uid2); } @@ -325,10 +325,10 @@ int CmdIndalaDemodAlt(const char *Cmd) { uid4 = (uid4<<1) | (uid5>>31); uid5 = (uid5<<1) | (uid6>>31); uid6 = (uid6<<1) | (uid7>>31); - - if (showbits[idx] == '0') + + if (showbits[idx] == '0') uid7 = (uid7<<1) | 0; - else + else uid7 = (uid7<<1) | 1; } PrintAndLogEx(SUCCESS, "UID | %s (%x%08x%08x%08x%08x%08x%08x)", showbits, uid1, uid2, uid3, uid4, uid5, uid6, uid7); @@ -353,7 +353,7 @@ int CmdIndalaDemodAlt(const char *Cmd) { PrintAndLogEx(DEBUG, "Occurrences: %d (expected %d)", times, (rawbit - start) / uidlen); // Remodulating for tag cloning - // HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod) + // HACK: 2015-01-04 this will have an impact on our new way of seening lf commands (demod) // since this changes graphbuffer data. GraphTraceLen = 32 * uidlen; i = 0; @@ -388,9 +388,9 @@ int CmdIndalaSim(const char *Cmd) { uint8_t hexuid[100]; int len = 0; param_gethex_ex(Cmd, 0, hexuid, &len); - if ( len > 28 ) + if ( len > 28 ) return usage_lf_indala_sim(); - + // convert to binarray uint8_t counter = 223; for (uint8_t i = 0; i < len; i++) { @@ -399,27 +399,27 @@ int CmdIndalaSim(const char *Cmd) { hexuid[i] >>= 1; } } - - // indala PSK + + // indala PSK uint8_t clk = 32, carrier = 2, invert = 0; uint16_t arg1, arg2; arg1 = clk << 8 | carrier; arg2 = invert; - + // It has to send either 64bits (8bytes) or 224bits (28bytes). Zero padding needed if not. // lf simpsk 1 c 32 r 2 d 0102030405060708 - + PrintAndLogEx(SUCCESS, "Simulating Indala UID: %s", sprint_hex(hexuid, len)); PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation or run another command"); - - UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}}; + + UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}}; memcpy(c.d.asBytes, bits, size); clearCommandBuffer(); SendCommand(&c); return 0; } -// iceman - needs refactoring +// iceman - needs refactoring int CmdIndalaClone(const char *Cmd) { UsbCommand c = {0}; uint32_t uid1, uid2, uid3, uid4, uid5, uid6, uid7; @@ -427,7 +427,7 @@ int CmdIndalaClone(const char *Cmd) { uint32_t n = 0, i = 0; if (strchr(Cmd,'l') != 0) { - + while (sscanf(&Cmd[i++], "%1x", &n ) == 1) { uid1 = (uid1 << 4) | (uid2 >> 28); uid2 = (uid2 << 4) | (uid3 >> 28); @@ -437,7 +437,7 @@ int CmdIndalaClone(const char *Cmd) { uid6 = (uid6 << 4) | (uid7 >> 28); uid7 = (uid7 << 4) | (n & 0xf); } - + PrintAndLogEx(INFO, "Preparing to clone Indala 224bit tag with UID %x%08x%08x%08x%08x%08x%08x", uid1, uid2, uid3, uid4, uid5, uid6, uid7); c.cmd = CMD_INDALA_CLONE_TAG_L; c.d.asDwords[0] = uid1; @@ -476,7 +476,7 @@ static command_t CommandTable[] = { int CmdLFINDALA(const char *Cmd){ clearCommandBuffer(); CmdsParse(CommandTable, Cmd); - return 0; + return 0; } int CmdHelp(const char *Cmd) { diff --git a/client/cmdlfio.c b/client/cmdlfio.c index 61fe9d00d..53ad90ec7 100644 --- a/client/cmdlfio.c +++ b/client/cmdlfio.c @@ -34,7 +34,7 @@ int usage_lf_io_sim(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: lf io sim [h] "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " : 8bit version"); PrintAndLogEx(NORMAL, " : 8bit value facility code"); PrintAndLogEx(NORMAL, " : 16bit value card number"); @@ -50,7 +50,7 @@ int usage_lf_io_clone(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: lf io clone [h] [Q5]"); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " h : This help"); PrintAndLogEx(NORMAL, " : 8bit version"); PrintAndLogEx(NORMAL, " : 8bit value facility code"); PrintAndLogEx(NORMAL, " : 16bit value card number"); @@ -88,18 +88,18 @@ int CmdIOProxDemod(const char *Cmd) { if (size < 65) { PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox not enough samples in GraphBuffer"); return 0; - } - //get binary from fsk wave + } + //get binary from fsk wave int waveIdx = 0; idx = detectIOProx(bits, &size, &waveIdx); if (idx < 0) { if (g_debugMode) { if (idx == -1) { - PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox not enough samples"); + PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox not enough samples"); } else if (idx == -2) { PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox just noise detected"); } else if (idx == -3) { - PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox error during fskdemod"); + PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox error during fskdemod"); } else if (idx == -4) { PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox preamble not found"); } else if (idx == -5) { @@ -114,15 +114,15 @@ int CmdIOProxDemod(const char *Cmd) { } setDemodBuf(bits, size, idx); setClockGrid(64, waveIdx + (idx*64)); - + if (idx == 0) { if (g_debugMode) { PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox data not found - FSK Bits: %d", size); if (size > 92) PrintAndLogEx(DEBUG, "%s", sprint_bin_break(bits, 92, 16)); - } + } return retval; } - + //Index map //0 10 20 30 40 50 60 //| | | | | | | @@ -131,7 +131,7 @@ int CmdIOProxDemod(const char *Cmd) { //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11 // //XSF(version)facility:codeone+codetwo (raw) - + PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d", bits[idx], bits[idx+1], bits[idx+2], bits[idx+3], bits[idx+4], bits[idx+5], bits[idx+6], bits[idx+7], bits[idx+8]); PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d", bits[idx+9], bits[idx+10], bits[idx+11],bits[idx+12],bits[idx+13],bits[idx+14],bits[idx+15],bits[idx+16],bits[idx+17]); PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d facility", bits[idx+18], bits[idx+19], bits[idx+20],bits[idx+21],bits[idx+22],bits[idx+23],bits[idx+24],bits[idx+25],bits[idx+26]); @@ -139,7 +139,7 @@ int CmdIOProxDemod(const char *Cmd) { PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d code1", bits[idx+36], bits[idx+37], bits[idx+38],bits[idx+39],bits[idx+40],bits[idx+41],bits[idx+42],bits[idx+43],bits[idx+44]); PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d code2", bits[idx+45], bits[idx+46], bits[idx+47],bits[idx+48],bits[idx+49],bits[idx+50],bits[idx+51],bits[idx+52],bits[idx+53]); PrintAndLogEx(DEBUG, "%d%d%d%d%d%d%d%d %d%d checksum", bits[idx+54],bits[idx+55],bits[idx+56],bits[idx+57],bits[idx+58],bits[idx+59],bits[idx+60],bits[idx+61],bits[idx+62],bits[idx+63]); - + uint32_t code = bytebits_to_byte(bits+idx,32); uint32_t code2 = bytebits_to_byte(bits+idx+32,32); uint8_t version = bytebits_to_byte(bits+idx+27,8); //14,4 @@ -156,13 +156,13 @@ int CmdIOProxDemod(const char *Cmd) { char crcStr[30]; memset(crcStr, 0x00, sizeof(crcStr) ); - + if (crc == calccrc) { snprintf(crcStr, 3, "ok"); retval = 1; } else { PrintAndLogEx(DEBUG, "DEBUG: Error - IO prox crc failed"); - + snprintf(crcStr, sizeof(crcStr), "failed 0x%02X != 0x%02X", crc, calccrc); retval = 0; } @@ -172,7 +172,7 @@ int CmdIOProxDemod(const char *Cmd) { if (g_debugMode){ PrintAndLogEx(DEBUG, "DEBUG: IO prox idx: %d, Len: %d, Printing demod buffer:", idx, size); printDemodBuff(); - } + } return retval; } @@ -184,7 +184,7 @@ int CmdIOProxDemod(const char *Cmd) { //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11 //XSF(version)facility:codeone+codetwo (raw) int getIOProxBits(uint8_t version, uint8_t fc, uint16_t cn, uint8_t *bits) { - #define SEPARATOR 1 + #define SEPARATOR 1 uint8_t pos=0; // the return bits, preamble 0000 0000 0 uint8_t pre[64]; @@ -192,31 +192,31 @@ int getIOProxBits(uint8_t version, uint8_t fc, uint16_t cn, uint8_t *bits) { // skip 9 zeros as preamble pos = 9; - + // another fixed byte 11110000 = 0xF0 num_to_bytebits(0xF0, 8, pre+pos); pos += 8; pre[pos] = SEPARATOR; - pos++; - + pos++; + // add facilitycode num_to_bytebits(fc, 8, pre+pos); pos += 8; pre[pos] = SEPARATOR; pos++; - + // add version num_to_bytebits(version, 8, pre+pos); pos += 8; pre[pos] = SEPARATOR; pos++; - + // cardnumber high byte num_to_bytebits( ((cn & 0xFF00)>>8), 8, pre+pos); pos += 8; pre[pos] = SEPARATOR; pos++; - + // cardnumber low byte num_to_bytebits( (cn & 0xFF), 8, pre+pos); pos += 8; @@ -227,18 +227,18 @@ int getIOProxBits(uint8_t version, uint8_t fc, uint16_t cn, uint8_t *bits) { uint16_t crc = 0; for (uint8_t i=1; i<6; ++i) crc += bytebits_to_byte(pre+9*i, 8); - + crc &= 0xFF; crc = 0xff - crc; num_to_bytebits(crc, 8, pre+pos); pos += 8; - + // Final two ONES pre[pos] = SEPARATOR; pre[++pos] = SEPARATOR; memcpy(bits, pre, sizeof(pre)); - + PrintAndLogEx(SUCCESS, "IO raw bits:\n %s \n", sprint_bin(bits, 64)); return 1; } @@ -249,30 +249,30 @@ int CmdIOProxSim(const char *Cmd) { uint8_t bits[64]; size_t size = sizeof(bits); memset(bits, 0x00, size); - + char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_io_sim(); - + version = param_get8(Cmd, 0); fc = param_get8(Cmd, 1); cn = param_get32ex(Cmd, 2, 0, 10); if ( !version | !fc || !cn) return usage_lf_io_sim(); - + if ((cn & 0xFFFF) != cn) { cn &= 0xFFFF; PrintAndLogEx(INFO, "Card Number Truncated to 16-bits (IOProx): %u", cn); } - + // clock 64, FSK2a fcHIGH 10 | fcLOW 8 uint8_t clk = 64, invert = 1, high = 10, low = 8; - uint16_t arg1, arg2; + uint16_t arg1, arg2; arg1 = high << 8 | low; arg2 = invert << 8 | clk; PrintAndLogEx(SUCCESS, "Simulating IOProx version: %u FC: %u; CN: %u\n", version, fc, cn); PrintAndLogEx(SUCCESS, "Press pm3-button to abort simulation or run another command"); - + if ( !getIOProxBits(version, fc, cn, bits)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); return 1; @@ -281,7 +281,7 @@ int CmdIOProxSim(const char *Cmd) { // arg1 --- fcHigh<<8 + fcLow // arg2 --- Invert and clk setting // size --- 64 bits == 8 bytes - UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}}; + UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}}; memcpy(c.d.asBytes, bits, size); clearCommandBuffer(); SendCommand(&c); @@ -289,13 +289,13 @@ int CmdIOProxSim(const char *Cmd) { } int CmdIOProxClone(const char *Cmd) { - + uint32_t blocks[3] = {T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_64 | 2 << T55x7_MAXBLOCK_SHIFT, 0, 0}; uint16_t cn = 0; uint8_t version = 0, fc = 0; uint8_t bits[64]; memset(bits,0,sizeof(bits)); - + char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_io_clone(); @@ -304,17 +304,17 @@ int CmdIOProxClone(const char *Cmd) { cn = param_get32ex(Cmd, 2, 0, 10); if ( !version | !fc || !cn) return usage_lf_io_clone(); - + if ((cn & 0xFFFF) != cn) { cn &= 0xFFFF; PrintAndLogEx(INFO, "Card Number Truncated to 16-bits (IOProx): %u", cn); } - + if ( !getIOProxBits(version, fc, cn, bits)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); return 1; } - + if (param_getchar(Cmd, 3) == 'Q' || param_getchar(Cmd, 3) == 'q') blocks[0] = T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT; @@ -323,7 +323,7 @@ int CmdIOProxClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone IOProx to T55x7 with Version: %u FC: %u, CN: %u", version, fc, cn); print_blocks(blocks, 3); - + //UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}}; UsbCommand c = {CMD_IO_CLONE_TAG, {blocks[1],blocks[2],0}}; clearCommandBuffer(); @@ -343,7 +343,7 @@ static command_t CommandTable[] = { int CmdLFIO(const char *Cmd){ clearCommandBuffer(); CmdsParse(CommandTable, Cmd); - return 0; + return 0; } int CmdHelp(const char *Cmd) { diff --git a/client/cmdlfjablotron.c b/client/cmdlfjablotron.c index 541e7b31b..339752202 100644 --- a/client/cmdlfjablotron.c +++ b/client/cmdlfjablotron.c @@ -44,11 +44,11 @@ static uint8_t jablontron_chksum(uint8_t *bits){ for (int i=16; i < 56; i += 8) { chksum += bytebits_to_byte(bits+i,8); } - chksum ^= 0x3A; + chksum ^= 0x3A; return chksum; } -int getJablotronBits(uint64_t fullcode, uint8_t *bits) { +int getJablotronBits(uint64_t fullcode, uint8_t *bits) { //preamp num_to_bytebits(0xFFFF, 16, bits); @@ -72,7 +72,7 @@ int detectJablotron(uint8_t *bits, size_t *size) { if (preambleSearch(bits, preamble, sizeof(preamble), size, &startIdx) == 0) return -2; //preamble not found if (*size != 64) return -3; // wrong demoded size - + uint8_t checkchksum = jablontron_chksum(bits+startIdx); uint8_t crc = bytebits_to_byte(bits+startIdx+56, 8); if ( checkchksum != crc ) return -5; @@ -119,7 +119,7 @@ int CmdJablotronDemod(const char *Cmd) { setDemodBuf(DemodBuffer, 64, ans); setClockGrid(g_DemodClock, g_DemodStartIdx + (ans*g_DemodClock)); - + //got a good demod uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); @@ -136,7 +136,7 @@ int CmdJablotronDemod(const char *Cmd) { ); id = DEC2BCD(id); - // Printed format: 1410-nn-nnnn-nnnn + // Printed format: 1410-nn-nnnn-nnnn PrintAndLogEx(SUCCESS, "Printed: 1410-%02X-%04X-%04X", (uint8_t)(id >> 32) & 0xFF, (uint16_t)(id >> 16) & 0xFFFF, @@ -157,33 +157,33 @@ int CmdJablotronClone(const char *Cmd) { uint8_t bits[64]; memset(bits, 0, sizeof(bits)); - + char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_jablotron_clone(); fullcode = param_get64ex(Cmd, 0, 0, 16); - + //Q5 if (param_getchar(Cmd, 1) == 'Q' || param_getchar(Cmd, 1) == 'q') blocks[0] = T5555_MODULATION_BIPHASE | T5555_INVERT_OUTPUT | T5555_SET_BITRATE(64) | 2 << T5555_MAXBLOCK_SHIFT; - - // clearing the topbit needed for the preambl detection. + + // clearing the topbit needed for the preambl detection. if ((fullcode & 0x7FFFFFFFFF) != fullcode) { fullcode &= 0x7FFFFFFFFF; PrintAndLogEx(INFO, "Card Number Truncated to 39bits: %"PRIx64, fullcode); } - + if ( !getJablotronBits(fullcode, bits)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); return 1; - } - + } + blocks[1] = bytebits_to_byte(bits, 32); blocks[2] = bytebits_to_byte(bits + 32, 32); PrintAndLogEx(INFO, "Preparing to clone Jablotron to T55x7 with FullCode: %"PRIx64, fullcode); print_blocks(blocks, 3); - + UsbCommand resp; UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}}; @@ -208,12 +208,12 @@ int CmdJablotronSim(const char *Cmd) { fullcode = param_get64ex(Cmd, 0, 0, 16); - // clearing the topbit needed for the preambl detection. + // clearing the topbit needed for the preambl detection. if ((fullcode & 0x7FFFFFFFFF) != fullcode) { fullcode &= 0x7FFFFFFFFF; PrintAndLogEx(INFO, "Card Number Truncated to 39bits: %"PRIx64, fullcode); } - + uint8_t clk = 64, encoding = 2, separator = 0, invert = 1; uint16_t arg1, arg2; size_t size = 64; diff --git a/client/cmdlfkeri.c b/client/cmdlfkeri.c index 560cd5c96..79fc9e6f1 100644 --- a/client/cmdlfkeri.c +++ b/client/cmdlfkeri.c @@ -5,7 +5,7 @@ // the license. //----------------------------------------------------------------------------- // Low frequency KERI tag commands -// PSK1, RF/128, RF/2, 64 bits long +// PSK1, RF/128, RF/2, 64 bits long //----------------------------------------------------------------------------- #include "cmdlfkeri.h" @@ -40,24 +40,24 @@ int usage_lf_keri_sim(void) { // find KERI preamble in already demoded data int detectKeri(uint8_t *dest, size_t *size, bool *invert) { - + uint8_t preamble[] = {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,1}; uint8_t preamble_i[] = {1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0}; - // sanity check. + // sanity check. if ( *size < sizeof(preamble) + 100) return -1; size_t startIdx = 0; - + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) { - + // if didn't find preamble try again inverting - if (!preambleSearch(DemodBuffer, preamble_i, sizeof(preamble_i), size, &startIdx)) + if (!preambleSearch(DemodBuffer, preamble_i, sizeof(preamble_i), size, &startIdx)) return -2; - + *invert ^= 1; } - + if (*size != 64) return -3; //wrong demoded size return (int)startIdx; @@ -69,7 +69,7 @@ int CmdKeriDemod(const char *Cmd) { PrintAndLogEx(DEBUG, "DEBUG: Error - KERI: PSK1 Demod failed"); return 0; } - bool invert = false; + bool invert = false; size_t size = DemodBufferLen; int idx = detectKeri(DemodBuffer, &size, &invert); if (idx < 0) { @@ -90,35 +90,35 @@ int CmdKeriDemod(const char *Cmd) { //got a good demod uint32_t raw1 = bytebits_to_byte(DemodBuffer , 32); uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); - + //get internal id - uint32_t ID = bytebits_to_byte(DemodBuffer+29, 32); + uint32_t ID = bytebits_to_byte(DemodBuffer+29, 32); ID &= 0x7FFFFFFF; - + /* 000000000000000000000000000001XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX111 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^1###############################^^^ Preamble block 29 bits of ZEROS - 32 bit Internal ID (First bit always 1) + 32 bit Internal ID (First bit always 1) 3 bit of 1s in the end - + How this is decoded to Facility ID, Card number is unknown Facility ID = 0-31 (indicates 5 bits) Card number = up to 10 digits - + Might be a hash of FC & CN to generate Internal ID */ - + PrintAndLogEx(SUCCESS, "KERI Tag Found -- Internal ID: %u", ID); PrintAndLogEx(SUCCESS, "Raw: %08X%08X", raw1 ,raw2); - + if (invert){ PrintAndLogEx(INFO, "Had to Invert - probably KERI"); for (size_t i = 0; i < size; i++) DemodBuffer[i] ^= 1; - + CmdPrintDemodBuff("x"); - } + } return 1; } @@ -132,38 +132,38 @@ int CmdKeriClone(const char *Cmd) { uint32_t internalid = 0; uint32_t blocks[3] = { T55x7_TESTMODE_DISABLED | - T55x7_X_MODE | - T55x7_MODULATION_PSK1 | - T55x7_PSKCF_RF_2 | + T55x7_X_MODE | + T55x7_MODULATION_PSK1 | + T55x7_PSKCF_RF_2 | 2 << T55x7_MAXBLOCK_SHIFT, 0, 0}; - + // dynamic bitrate used blocks[0] |= 0xF << 18; - + char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_keri_clone(); internalid = param_get32ex(Cmd, 0, 0, 10); - + //Q5 if (tolower(param_getchar(Cmd, 1)) == 'q') { - blocks[0] = - T5555_MODULATION_PSK1 | - T5555_SET_BITRATE(128) | - T5555_PSK_RF_2 | + blocks[0] = + T5555_MODULATION_PSK1 | + T5555_SET_BITRATE(128) | + T5555_PSK_RF_2 | 2 << T5555_MAXBLOCK_SHIFT; } - - + + // MSB is ONE internalid |= 0x80000000; // 3 LSB is ONE uint64_t data = ((uint64_t)internalid << 3 ) + 7; - - // + + // blocks[1] = data >> 32; blocks[2] = data & 0xFFFFFFFF; @@ -199,21 +199,21 @@ int CmdKeriSim(const char *Cmd) { internalid <<= 3; internalid += 7; - uint8_t bits[64] = {0x00}; + uint8_t bits[64] = {0x00}; // loop to bits uint8_t j = 0; for ( int8_t i = 63; i >= 0; --i) { bits[j++] = ((internalid >> i) & 1 ); } - + uint8_t clk = 32, carrier = 2, invert = 0; uint16_t arg1, arg2; size_t size = 64; arg1 = clk << 8 | carrier; arg2 = invert; - + PrintAndLogEx(SUCCESS, "Simulating KERI - Internal Id: %u", internalid); - + UsbCommand c = {CMD_PSK_SIM_TAG, {arg1, arg2, size}}; memcpy(c.d.asBytes, bits, size); clearCommandBuffer(); @@ -227,7 +227,7 @@ static command_t CommandTable[] = { {"demod", CmdKeriDemod, 1, "Demodulate an KERI tag from the GraphBuffer"}, {"read", CmdKeriRead, 0, "Attempt to read and extract tag data from the antenna"}, {"clone", CmdKeriClone, 0, "clone KERI to T55x7"}, - {"sim", CmdKeriSim, 0, "simulate KERI tag"}, + {"sim", CmdKeriSim, 0, "simulate KERI tag"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfnedap.c b/client/cmdlfnedap.c index 25f9b624b..353ff535d 100644 --- a/client/cmdlfnedap.c +++ b/client/cmdlfnedap.c @@ -61,10 +61,10 @@ int GetNedapBits(uint32_t cn, uint8_t *nedapBits) { // fixed tagtype code? 0010 1101 = 0x2D num_to_bytebits(0x2D, 8, pre+10); - + // 46 encrypted bits - UNKNOWN ALGO // -- 16 bits checksum. Should be 4x4 checksum, based on UID and 2 constant values. - // -- 30 bits undocumented? + // -- 30 bits undocumented? //num_to_bytebits(cn, 46, pre+18); //----from this part, the UID in clear text, with a 1bit ZERO as separator between bytes. @@ -75,7 +75,7 @@ int GetNedapBits(uint32_t cn, uint8_t *nedapBits) { pre[100] = 0; pre[109] = 0; pre[118] = 0; - + // cardnumber (uid) num_to_bytebits( (cn >> 0) & 0xFF, 8, pre+65); num_to_bytebits( (cn >> 8) & 0xFF, 8, pre+74); @@ -84,19 +84,19 @@ int GetNedapBits(uint32_t cn, uint8_t *nedapBits) { // two ? num_to_bytebits( 0, 8, pre+92); num_to_bytebits( 0, 8, pre+101); - - // chksum - num_to_bytebits( (0 >> 0) & 0xFF, 8, pre+110); - num_to_bytebits( (0 >> 8) & 0xFF, 8, pre+119); - + // chksum + num_to_bytebits( (0 >> 0) & 0xFF, 8, pre+110); + num_to_bytebits( (0 >> 8) & 0xFF, 8, pre+119); + + // add paritybits (bitsource, dest, sourcelen, paritylen, parityType (odd, even,) addParity(pre, pre+64, 64, 8, 1); addParity(pre+64, pre+64, 64, 8, 1); pre[63] = GetParity( DemodBuffer, EVEN, 63); pre[127] = GetParity( DemodBuffer+64, EVEN, 63); - + memcpy(nedapBits, pre, 128); // 1111111110001011010000010110100011001001000010110101001101011001000110011010010000000000100001110001001000000001000101011100111 @@ -110,7 +110,7 @@ int GetNedapBits(uint32_t cn, uint8_t *nedapBits) { //GetParity( uint8_t *bits, uint8_t type, int length) //NEDAP demod - ASK/Biphase (or Diphase), RF/64 with preamble of 1111111110 (always a 128 bit data stream) -//print NEDAP Prox ID, encoding, encrypted ID, +//print NEDAP Prox ID, encoding, encrypted ID, int CmdLFNedapDemod(const char *Cmd) { //raw ask demod no start bit finding just get binary from wave @@ -141,19 +141,19 @@ int CmdLFNedapDemod(const char *Cmd) { /* Index map E E preamble enc tag type encrypted uid P d 33 d 90 d 04 d 71 d 40 d 45 d E7 P 1111111110 00101101000001011010001100100100001011010100110101100 1 0 00110011 0 10010000 0 00000100 0 01110001 0 01000000 0 01000101 0 11100111 1 - uid2 uid1 uid0 I I R R - 1111111110 00101101000001011010001100100100001011010100110101100 1 - - 0 00110011 - 0 10010000 + uid2 uid1 uid0 I I R R + 1111111110 00101101000001011010001100100100001011010100110101100 1 + + 0 00110011 + 0 10010000 0 00000100 0 01110001 0 01000000 0 01000101 0 11100111 1 - - Tag ID is 049033 + + Tag ID is 049033 I = Identical on all tags R = Random ? UID2, UID1, UID0 == card number @@ -167,7 +167,7 @@ int CmdLFNedapDemod(const char *Cmd) { raw[3] = bytebits_to_byte(DemodBuffer+idx,32); setDemodBuf(DemodBuffer, 128, idx); setClockGrid(g_DemodClock, g_DemodStartIdx + (idx*g_DemodClock)); - + uint8_t firstParity = GetParity( DemodBuffer, EVEN, 63); if ( firstParity != DemodBuffer[63] ) { PrintAndLogEx(DEBUG, "DEBUG: Error - Nedap 1st 64bit parity check failed: %d|%d ", DemodBuffer[63], firstParity); @@ -187,9 +187,9 @@ int CmdLFNedapDemod(const char *Cmd) { uid |= bytebits_to_byte(DemodBuffer+83, 8) << 16; uint16_t two = 0; - two = bytebits_to_byte(DemodBuffer+92, 8); + two = bytebits_to_byte(DemodBuffer+92, 8); two |= bytebits_to_byte(DemodBuffer+101, 8) << 8; - + uint16_t chksum2 = 0; chksum2 = bytebits_to_byte(DemodBuffer+110, 8); chksum2 |= bytebits_to_byte(DemodBuffer+119, 8) << 8; @@ -249,11 +249,11 @@ int CmdLFNedapClone(const char *Cmd) { if (sscanf(Cmd, "%u", &cn ) != 1) return usage_lf_nedap_clone(); cardnumber = (cn & 0x00FFFFFF); - + if ( !GetNedapBits(cardnumber, bits)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); return 1; - } + } ((ASK/DIphase data rawdemod ab 0 64 1 0 //NEDAP - compat mode, ASK/DIphase, data rate 64, 4 data blocks @@ -291,32 +291,32 @@ int CmdLFNedapClone(const char *Cmd) { int CmdLFNedapSim(const char *Cmd) { uint32_t cardnumber = 0, cn = 0; - + char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_nedap_sim(); if (sscanf(Cmd, "%u", &cn ) != 1) return usage_lf_nedap_sim(); - + cardnumber = (cn & 0x00FFFFFF); - + uint8_t bs[128]; size_t size = sizeof(bs); memset(bs, 0x00, size); - + // NEDAP, Biphase = 2, clock 64, inverted, (DIPhase == inverted BIphase uint8_t clk = 64, encoding = 2, separator = 0, invert = 1; uint16_t arg1, arg2; arg1 = clk << 8 | encoding; arg2 = invert << 8 | separator; - + if ( !GetNedapBits(cardnumber, bs)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); return 1; - } + } PrintAndLogEx(SUCCESS, "bin %s", sprint_bin_break(bs, 128, 32)); PrintAndLogEx(SUCCESS, "Simulating Nedap - CardNumber: %u", cardnumber ); - + UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; memcpy(c.d.asBytes, bs, size); clearCommandBuffer(); @@ -329,51 +329,51 @@ int CmdLFNedapChk(const char *Cmd){ uint8_t data[256] = { 0x30, 0x16, 0x00, 0x71, 0x40, 0x21, 0xBE}; int len = 0; param_gethex_ex(Cmd, 0, data, &len); - + len = ( len == 0 ) ? 5 : len>>1; - + PrintAndLogEx(SUCCESS, "Input: [%d] %s", len, sprint_hex(data, len)); - + //uint8_t last = GetParity(data, EVEN, 62); //PrintAndLogEx(NORMAL, "TEST PARITY:: %d | %d ", DemodBuffer[62], last); uint8_t cl = 0x1D, ch = 0x1D, carry = 0; uint8_t al, bl, temp; - + for (int i =len; i >= 0; --i){ al = data[i]; for (int j = 8; j > 0; --j) { - + bl = al ^ ch; //PrintAndLogEx(NORMAL, "BL %02x | CH %02x \n", al, ch); - + carry = (cl & 0x80) ? 1 : 0; cl <<= 1; - + temp = (ch & 0x80) ? 1 : 0; ch = (ch << 1) | carry; carry = temp; - + carry = (al & 0x80) ? 1 : 0; al <<= 1; - + carry = (bl & 0x80) ? 1 : 0; bl <<= 1; - + if (carry) { cl ^= 0x21; ch ^= 0x10; } } } - + PrintAndLogEx(SUCCESS, "Nedap checksum: 0x%X", ((ch << 8) | cl) ); return 0; } static command_t CommandTable[] = { {"help", CmdHelp, 1, "this help"}, - {"demod", CmdLFNedapDemod,0, "demodulate an Nedap tag from the GraphBuffer"}, + {"demod", CmdLFNedapDemod,0, "demodulate an Nedap tag from the GraphBuffer"}, {"read", CmdLFNedapRead, 0, "attempt to read and extract tag data"}, // {"clone", CmdLFNedapClone,0, " clone nedap tag"}, {"sim", CmdLFNedapSim, 0, "simulate nedap tag"}, diff --git a/client/cmdlfnexwatch.c b/client/cmdlfnexwatch.c index 4057fe452..dd6bf3ff9 100644 --- a/client/cmdlfnexwatch.c +++ b/client/cmdlfnexwatch.c @@ -16,7 +16,7 @@ int detectNexWatch(uint8_t *dest, size_t *size, bool *invert) { uint8_t preamble[28] = {0,0,0,0,0,1,0,1,0,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t preamble_i[28] = {1,1,1,1,1,0,1,0,1,0,0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1}; - // sanity check. + // sanity check. if ( *size < sizeof(preamble) + 100) return -1; size_t startIdx = 0; @@ -26,7 +26,7 @@ int detectNexWatch(uint8_t *dest, size_t *size, bool *invert) { if (!preambleSearch(DemodBuffer, preamble_i, sizeof(preamble_i), size, &startIdx)) return -4; *invert ^= 1; } - + // size tests? return (int) startIdx; } @@ -56,18 +56,18 @@ int CmdNexWatchDemod(const char *Cmd) { return 0; } - + setDemodBuf(DemodBuffer, size, idx+4); setClockGrid(g_DemodClock, g_DemodStartIdx + ((idx+4)*g_DemodClock)); - + idx = 8+32; // 8 = preamble, 32 = reserved bits (always 0) - + //get ID uint32_t ID = 0; for (uint8_t k = 0; k < 4; k++){ for (uint8_t m = 0; m < 8; m++){ ID = (ID << 1) | DemodBuffer[m + k + (m*4)]; - } + } } //parity check (TBD) @@ -79,7 +79,7 @@ int CmdNexWatchDemod(const char *Cmd) { PrintAndLogEx(NORMAL, "Had to Invert - probably NexKey"); for (size_t i = 0; i < size; i++) DemodBuffer[i] ^= 1; - } + } CmdPrintDemodBuff("x"); return 1; @@ -100,7 +100,7 @@ static command_t CommandTable[] = { }; int CmdLFNEXWATCH(const char *Cmd) { - clearCommandBuffer(); + clearCommandBuffer(); CmdsParse(CommandTable, Cmd); return 0; } diff --git a/client/cmdlfnexwatch.h b/client/cmdlfnexwatch.h index 73a44f919..82782926a 100644 --- a/client/cmdlfnexwatch.h +++ b/client/cmdlfnexwatch.h @@ -20,7 +20,7 @@ #include "cmdparser.h" #include "cmddata.h" // preamblesearch #include "cmdlf.h" -#include "lfdemod.h" +#include "lfdemod.h" extern int CmdLFNEXWATCH(const char *Cmd); extern int CmdNexWatchDemod(const char *Cmd); diff --git a/client/cmdlfnoralsy.c b/client/cmdlfnoralsy.c index 0f61e26ea..a858feb2e 100644 --- a/client/cmdlfnoralsy.c +++ b/client/cmdlfnoralsy.c @@ -46,7 +46,7 @@ static uint8_t noralsy_chksum( uint8_t* bits, uint8_t len) { sum ^= bytebits_to_byte(bits+i, 4); return sum & 0x0F ; } -int getnoralsyBits(uint32_t id, uint16_t year, uint8_t *bits) { +int getnoralsyBits(uint32_t id, uint16_t year, uint8_t *bits) { //preamp num_to_bytebits(0xBB0214FF, 32, bits); // --> Have seen 0xBB0214FF / 0xBB0314FF UNKNOWN @@ -54,15 +54,15 @@ int getnoralsyBits(uint32_t id, uint16_t year, uint8_t *bits) { id = DEC2BCD(id); year = DEC2BCD(year); year &= 0xFF; - + uint16_t sub1 = (id & 0xFFF0000) >> 16; uint8_t sub2 = (id & 0x000FF00) >> 8; uint8_t sub3 = (id & 0x00000FF); - + num_to_bytebits(sub1, 12, bits+32); num_to_bytebits(year, 8, bits+44); num_to_bytebits(0, 4, bits+52); // --> UNKNOWN. Flag? - + num_to_bytebits(sub2, 8, bits+56); num_to_bytebits(sub3, 8, bits+64); @@ -91,12 +91,12 @@ int detectNoralsy(uint8_t *dest, size_t *size) { * 2520116 | BB0214FF2529900116360000 | 10111011 00000011 00010100 11111111 00100101 00101001 10010000 00000001 00010110 00110110 00000000 00000000 * aaa*aaaaiiiYY*iiiicc---- **** iiiiiiii iiiiYYYY YYYY**** iiiiiiii iiiiiiii cccccccc * -* a = fixed value BB0*14FF +* a = fixed value BB0*14FF * i = printed id, BCD-format * Y = year * c = checksum * * = unknown -* +* **/ //see ASKDemod for what args are accepted @@ -130,7 +130,7 @@ int CmdNoralsyDemod(const char *Cmd) { } setDemodBuf(DemodBuffer, 96, ans); setClockGrid(g_DemodClock, g_DemodStartIdx + (ans*g_DemodClock)); - + //got a good demod uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); @@ -144,7 +144,7 @@ int CmdNoralsyDemod(const char *Cmd) { uint16_t year = (raw2 & 0x000ff000) >> 12; year = BCD2DEC(year); year += ( year > 60 ) ? 1900: 2000; - + // calc checksums uint8_t calc1 = noralsy_chksum(DemodBuffer+32, 40); uint8_t calc2 = noralsy_chksum(DemodBuffer, 76); @@ -152,7 +152,7 @@ int CmdNoralsyDemod(const char *Cmd) { chk1 = bytebits_to_byte(DemodBuffer+72, 4); chk2 = bytebits_to_byte(DemodBuffer+76, 4); // test checksums - if ( chk1 != calc1 ) { + if ( chk1 != calc1 ) { if (g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: Error - Noralsy: checksum 1 failed %x - %x\n", chk1, calc1); return 0; } @@ -160,7 +160,7 @@ int CmdNoralsyDemod(const char *Cmd) { if (g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: Error - Noralsy: checksum 2 failed %x - %x\n", chk2, calc2); return 0; } - + PrintAndLogEx(SUCCESS, "Noralsy Tag Found: Card ID %u, Year: %u Raw: %08X%08X%08X", cardid, year, raw1 ,raw2, raw3); if (raw1 != 0xBB0214FF) { PrintAndLogEx(WARNING, "Unknown bits set in first block! Expected 0xBB0214FF, Found: 0x%08X", raw1); @@ -175,36 +175,36 @@ int CmdNoralsyRead(const char *Cmd) { } int CmdNoralsyClone(const char *Cmd) { - + uint16_t year = 0; uint32_t id = 0; uint32_t blocks[4] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | T55x7_ST_TERMINATOR | 3 << T55x7_MAXBLOCK_SHIFT, 0, 0}; uint8_t bits[96]; memset(bits, 0, sizeof(bits)); - + char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_noralsy_clone(); id = param_get32ex(Cmd, 0, 0, 10); year = param_get32ex(Cmd, 1, 2000, 10); - + //Q5 if (param_getchar(Cmd, 2) == 'Q' || param_getchar(Cmd, 2) == 'q') blocks[0] = T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(32) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT; - + if ( !getnoralsyBits(id, year, bits)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); return 1; - } - - // + } + + // blocks[1] = bytebits_to_byte(bits, 32); blocks[2] = bytebits_to_byte(bits + 32, 32); blocks[3] = bytebits_to_byte(bits + 64, 32); PrintAndLogEx(INFO, "Preparing to clone Noralsy to T55x7 with CardId: %u", id); print_blocks(blocks, 4); - + UsbCommand resp; UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}}; @@ -241,12 +241,12 @@ int CmdNoralsySim(const char *Cmd) { size_t size = 96; arg1 = clk << 8 | encoding; arg2 = invert << 8 | separator; - + if ( !getnoralsyBits(id, year, bs)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); return 1; - } - + } + PrintAndLogEx(SUCCESS, "Simulating Noralsy - CardId: %u", id); UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; diff --git a/client/cmdlfpac.c b/client/cmdlfpac.c index 73086ce59..a6a79e64a 100644 --- a/client/cmdlfpac.c +++ b/client/cmdlfpac.c @@ -55,10 +55,10 @@ int CmdPacDemod(const char *Cmd) { uint32_t raw3 = bytebits_to_byte(DemodBuffer+64, 32); uint32_t raw4 = bytebits_to_byte(DemodBuffer+96, 32); - // preamble then appears to have marker bits of "10" CS? + // preamble then appears to have marker bits of "10" CS? // 11111111001000000 10 01001100 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 00001101 10 10001100 10 100000001 // unknown checksum 9 bits at the end - + PrintAndLogEx(NORMAL, "PAC/Stanley Tag Found -- Raw: %08X%08X%08X%08X", raw1 ,raw2, raw3, raw4); PrintAndLogEx(NORMAL, "\nHow the Raw ID is translated by the reader is unknown"); return 1; diff --git a/client/cmdlfparadox.c b/client/cmdlfparadox.c index 139797a66..113036d6f 100644 --- a/client/cmdlfparadox.c +++ b/client/cmdlfparadox.c @@ -41,28 +41,28 @@ int usage_lf_paradox_sim(void) { int detectParadox(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx) { //make sure buffer has data if (*size < 96*50) return -1; - + signal_t *sp = getSignalProperties(); if (sp->isnoise) return -2; - + // FSK demodulator *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); // paradox fsk2a - //did we get a good demod? + //did we get a good demod? if (*size < 96) return -3; // 00001111 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1 - size_t startIdx = 0; + size_t startIdx = 0; uint8_t preamble[] = {0,0,0,0,1,1,1,1}; - if (preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) + if (preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) return -4; //preamble not found size_t numStart = startIdx + sizeof(preamble); // final loop, go over previously decoded FSK data and manchester decode into usable tag ID for (size_t idx = numStart; (idx-numStart) < *size - sizeof(preamble); idx+=2){ - if (dest[idx] == dest[idx+1]) + if (dest[idx] == dest[idx+1]) return -5; //not manchester data - + *hi2 = (*hi2 << 1) | (*hi >> 31); *hi = (*hi << 1) | (*lo >> 31); //Then, shift in a 0 or one into low @@ -86,8 +86,8 @@ int CmdParadoxDemod(const char *Cmd) { PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox not enough samples"); return 0; } - - uint32_t hi2=0, hi=0, lo=0; + + uint32_t hi2=0, hi=0, lo=0; int waveIdx=0; //get binary from fsk wave int idx = detectParadox(bits, &size, &hi2, &hi, &lo, &waveIdx); @@ -96,7 +96,7 @@ int CmdParadoxDemod(const char *Cmd) { if (idx == -1) PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox not enough samples"); else if (idx == -2) - PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox just noise detected"); + PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox just noise detected"); else if (idx == -3) PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox problem during FSK demod"); else if (idx == -4) @@ -105,18 +105,18 @@ int CmdParadoxDemod(const char *Cmd) { PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox error in Manchester data, size %d", size); else PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox error demoding fsk %d", idx); - + return 0; } setDemodBuf(bits, size, idx); - setClockGrid(50, waveIdx + (idx*50)); - + setClockGrid(50, waveIdx + (idx*50)); + if (hi2==0 && hi==0 && lo==0){ if (g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox no value found"); return 0; } - + uint32_t fc = ((hi & 0x3)<<6) | (lo>>26); uint32_t cardnum = (lo>>10) & 0xFFFF; uint32_t rawLo = bytebits_to_byte(bits + idx + 64, 32); @@ -125,14 +125,14 @@ int CmdParadoxDemod(const char *Cmd) { PrintAndLogEx(NORMAL, "Paradox TAG ID: %x%08x - FC: %d - Card: %d - Checksum: %02x - RAW: %08x%08x%08x", hi >> 10, - (hi & 0x3)<<26 | (lo>>10), + (hi & 0x3)<<26 | (lo>>10), fc, cardnum, (lo>>2) & 0xFF, rawHi2, rawHi, rawLo ); - + PrintAndLogEx(DEBUG, "DEBUG: Paradox idx: %d, len: %d, Printing Demod Buffer:", idx, size); if (g_debugMode) printDemodBuff(); @@ -142,7 +142,7 @@ int CmdParadoxDemod(const char *Cmd) { //by marshmellow //see ASKDemod for what args are accepted int CmdParadoxRead(const char *Cmd) { - lf_read(true, 10000); + lf_read(true, 10000); return CmdParadoxDemod(Cmd); } @@ -152,29 +152,29 @@ int CmdParadoxSim(const char *Cmd) { if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_paradox_sim(); uint32_t facilitycode = 0, cardnumber = 0, fc = 0, cn = 0; - + uint8_t bs[96]; size_t size = sizeof(bs); memset(bs, 0x00, size); - + // Paradox uses: fcHigh: 10, fcLow: 8, clk: 50, invert: 1 FSK2a uint8_t clk = 50, invert = 1, high = 10, low = 8; - uint16_t arg1, arg2; + uint16_t arg1, arg2; arg1 = high << 8 | low; arg2 = invert << 8 | clk; - + if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_paradox_sim(); facilitycode = (fc & 0x000000FF); cardnumber = (cn & 0x0000FFFF); - + // if ( !GetParadoxBits(facilitycode, cardnumber, bs)) { // PrintAndLogEx(WARNING, "Error with tag bitstream generation."); // return 1; - // } + // } PrintAndLogEx(NORMAL, "Simulating Paradox - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber ); - + UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}}; memcpy(c.d.asBytes, bs, size); clearCommandBuffer(); @@ -189,7 +189,7 @@ static command_t CommandTable[] = { {"demod", CmdParadoxDemod, 1, "Demodulate a Paradox FSK tag from the GraphBuffer"}, {"read", CmdParadoxRead, 0, "Attempt to read and Extract tag data from the antenna"}, // {"clone", CmdParadoxClone,0, "clone paradox tag"}, - {"sim", CmdParadoxSim, 0, "simulate paradox tag"}, + {"sim", CmdParadoxSim, 0, "simulate paradox tag"}, {NULL, NULL, 0, NULL} }; diff --git a/client/cmdlfpcf7931.c b/client/cmdlfpcf7931.c index 59ef1c818..c47a44e7b 100644 --- a/client/cmdlfpcf7931.c +++ b/client/cmdlfpcf7931.c @@ -30,7 +30,7 @@ static int CmdHelp(const char *Cmd); struct pcf7931_config configPcf = { {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF}, PCF7931_DEFAULT_INITDELAY, - PCF7931_DEFAULT_OFFSET_WIDTH, + PCF7931_DEFAULT_OFFSET_WIDTH, PCF7931_DEFAULT_OFFSET_POSITION }; @@ -38,8 +38,8 @@ struct pcf7931_config configPcf = { int pcf7931_resetConfig(){ memset(configPcf.Pwd, 0xFF, sizeof(configPcf.Pwd) ); configPcf.InitDelay = PCF7931_DEFAULT_INITDELAY; - configPcf.OffsetWidth = PCF7931_DEFAULT_OFFSET_WIDTH; - configPcf.OffsetPosition = PCF7931_DEFAULT_OFFSET_POSITION; + configPcf.OffsetWidth = PCF7931_DEFAULT_OFFSET_WIDTH; + configPcf.OffsetPosition = PCF7931_DEFAULT_OFFSET_POSITION; return 0; } @@ -85,7 +85,7 @@ int usage_pcf7931_config(){ PrintAndLogEx(NORMAL, " pwd Password, hex, 7bytes, LSB-order"); PrintAndLogEx(NORMAL, " delay Tag initialization delay (in us) decimal"); PrintAndLogEx(NORMAL, " offset Low pulses width (in us) decimal"); - PrintAndLogEx(NORMAL, " offset Low pulses position (in us) decimal"); + PrintAndLogEx(NORMAL, " offset Low pulses position (in us) decimal"); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf pcf7931 config"); PrintAndLogEx(NORMAL, " lf pcf7931 config r"); @@ -94,7 +94,7 @@ int usage_pcf7931_config(){ return 0; } -int CmdLFPCF7931Read(const char *Cmd){ +int CmdLFPCF7931Read(const char *Cmd){ uint8_t ctmp = param_getchar(Cmd, 0); if ( ctmp == 'H' || ctmp == 'h' ) return usage_pcf7931_read(); @@ -110,37 +110,37 @@ int CmdLFPCF7931Read(const char *Cmd){ return 0; } -int CmdLFPCF7931Config(const char *Cmd){ +int CmdLFPCF7931Config(const char *Cmd){ uint8_t ctmp = param_getchar(Cmd, 0); if ( ctmp == 0) return pcf7931_printConfig(); if ( ctmp == 'H' || ctmp == 'h' ) return usage_pcf7931_config(); - if ( ctmp == 'R' || ctmp == 'r' ) return pcf7931_resetConfig(); - + if ( ctmp == 'R' || ctmp == 'r' ) return pcf7931_resetConfig(); + if ( param_gethex(Cmd, 0, configPcf.Pwd, 14) ) return usage_pcf7931_config(); - + configPcf.InitDelay = (param_get32ex(Cmd,1,0,10) & 0xFFFF); configPcf.OffsetWidth = (int)(param_get32ex(Cmd,2,0,10) & 0xFFFF); configPcf.OffsetPosition = (int)(param_get32ex(Cmd,3,0,10) & 0xFFFF); - + pcf7931_printConfig(); return 0; } int CmdLFPCF7931Write(const char *Cmd){ - + uint8_t ctmp = param_getchar(Cmd, 0); - if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_pcf7931_write(); + if (strlen(Cmd) < 1 || ctmp == 'h' || ctmp == 'H') return usage_pcf7931_write(); uint8_t block = 0, bytepos = 0, data = 0; - + if ( param_getdec(Cmd, 0, &block) ) return usage_pcf7931_write(); if ( param_getdec(Cmd, 1, &bytepos) ) return usage_pcf7931_write(); - + if ( (block > 7) || (bytepos > 15) ) return usage_pcf7931_write(); data = param_get8ex(Cmd, 2, 0, 16); - + PrintAndLogEx(NORMAL, "Writing block: %d", block); PrintAndLogEx(NORMAL, " pos: %d", bytepos); PrintAndLogEx(NORMAL, " data: 0x%02X", data); diff --git a/client/cmdlfpresco.c b/client/cmdlfpresco.c index 98df02fe5..1b54899bd 100644 --- a/client/cmdlfpresco.c +++ b/client/cmdlfpresco.c @@ -14,7 +14,7 @@ int usage_lf_presco_clone(void){ PrintAndLogEx(NORMAL, "clone a Presco tag to a T55x7 tag."); PrintAndLogEx(NORMAL, "Usage: lf presco clone [h] d c "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); + PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, " d : 9 digit presco card ID"); PrintAndLogEx(NORMAL, " c : 8 digit hex card number"); PrintAndLogEx(NORMAL, " : specify write to Q5 (t5555 instead of t55x7)"); @@ -31,7 +31,7 @@ int usage_lf_presco_sim(void) { PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Usage: lf presco sim [h] d or c "); PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : this help"); + PrintAndLogEx(NORMAL, " h : this help"); PrintAndLogEx(NORMAL, " d : 9 digit presco card number"); PrintAndLogEx(NORMAL, " c : 8 digit hex card number"); PrintAndLogEx(NORMAL, ""); @@ -54,14 +54,14 @@ int detectPresco(uint8_t *dest, size_t *size) { // convert base 12 ID to sitecode & usercode & 8 bit other unknown code int GetWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode, uint32_t *fullcode, bool *Q5) { - + uint8_t val = 0; bool hex = false, errors = false; uint8_t cmdp = 0; char id[11]; int stringlen = 0; memset(id, 0x00, sizeof(id)); - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': @@ -93,7 +93,7 @@ int GetWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode if (!hex) { for (int index =0; index < strlen(id); ++index) { - + // Get value from number string. if ( id[index] == '*' ) val = 10; @@ -101,11 +101,11 @@ int GetWiegandFromPresco(const char *Cmd, uint32_t *sitecode, uint32_t *usercode val = 11; if ( id[index] >= 0x30 && id[index] <= 0x39 ) val = id[index] - 0x30; - + *fullcode += val; - + // last digit is only added, not multipled. - if ( index < strlen(id)-1 ) + if ( index < strlen(id)-1 ) *fullcode *= 12; } } @@ -146,7 +146,7 @@ int CmdPrescoDemod(const char *Cmd) { } setDemodBuf(DemodBuffer, 128, ans); setClockGrid(g_DemodClock, g_DemodStartIdx + (ans*g_DemodClock)); - + //got a good demod uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); @@ -178,7 +178,7 @@ int CmdPrescoClone(const char *Cmd) { bool Q5 = false; uint32_t sitecode=0, usercode=0, fullcode=0; uint32_t blocks[5] = {T55x7_MODULATION_MANCHESTER | T55x7_BITRATE_RF_32 | 4 << T55x7_MAXBLOCK_SHIFT | T55x7_ST_TERMINATOR, 0, 0, 0, 0}; - + // get wiegand from printed number. if (GetWiegandFromPresco(Cmd, &sitecode, &usercode, &fullcode, &Q5) == -1) return usage_lf_presco_clone(); @@ -194,7 +194,7 @@ int CmdPrescoClone(const char *Cmd) { usercode &= 0xFFFF; PrintAndLogEx(INFO, "Card Number Truncated to 16-bits (Presco): %u", usercode); } - + blocks[1] = 0x10D00000; //preamble blocks[2] = 0x00000000; blocks[3] = 0x00000000; @@ -202,7 +202,7 @@ int CmdPrescoClone(const char *Cmd) { PrintAndLogEx(INFO, "Preparing to clone Presco to T55x7 with SiteCode: %u, UserCode: %u, FullCode: %08x", sitecode, usercode, fullcode); print_blocks(blocks, 5); - + UsbCommand resp; UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}}; diff --git a/client/cmdlfpyramid.c b/client/cmdlfpyramid.c index 1153fccc3..796301761 100644 --- a/client/cmdlfpyramid.c +++ b/client/cmdlfpyramid.c @@ -80,8 +80,8 @@ int GetPyramidBits(uint32_t fc, uint32_t cn, uint8_t *pyramidBits) { // format start bit pre[79] = 1; - - // Get 26 wiegand from FacilityCode, CardNumber + + // Get 26 wiegand from FacilityCode, CardNumber uint8_t wiegand[24]; memset(wiegand, 0x00, sizeof(wiegand)); num_to_bytebits(fc, 8, wiegand); @@ -89,11 +89,11 @@ int GetPyramidBits(uint32_t fc, uint32_t cn, uint8_t *pyramidBits) { // add wiegand parity bits (dest, source, len) wiegand_add_parity(pre+80, wiegand, 24); - + // add paritybits (bitsource, dest, sourcelen, paritylen, parityType (odd, even,) addParity(pre+8, pyramidBits+8, 102, 8, 1); - // add checksum + // add checksum uint8_t csBuff[13]; for (uint8_t i = 0; i < 13; i++) csBuff[i] = bytebits_to_byte(pyramidBits + 16 + (i*8), 8); @@ -125,7 +125,7 @@ int CmdPyramidDemod(const char *Cmd) { else if (idx == -3) PrintAndLogEx(DEBUG, "DEBUG: Error - Pyramid: problem during FSK demod"); else if (idx == -4) - PrintAndLogEx(DEBUG, "DEBUG: Error - Pyramid: preamble not found"); + PrintAndLogEx(DEBUG, "DEBUG: Error - Pyramid: preamble not found"); else if (idx == -5) PrintAndLogEx(DEBUG, "DEBUG: Error - Pyramid: size not correct: %d", size); else @@ -134,7 +134,7 @@ int CmdPyramidDemod(const char *Cmd) { } setDemodBuf(bits, size, idx); setClockGrid(50, waveIdx + (idx*50)); - + // Index map // 0 10 20 30 40 50 60 // | | | | | | | @@ -209,12 +209,12 @@ int CmdPyramidDemod(const char *Cmd) { for (j=0; j < size; ++j){ if(bits[j]) break; } - + uint8_t fmtLen = size-j-8; uint32_t fc = 0; uint32_t cardnum = 0; uint32_t code1 = 0; - + if ( fmtLen == 26 ){ fc = bytebits_to_byte(bits+73, 8); cardnum = bytebits_to_byte(bits+81, 16); @@ -267,11 +267,11 @@ int CmdPyramidClone(const char *Cmd) { facilitycode = (fc & 0x000000FF); cardnumber = (cn & 0x0000FFFF); - + if ( !GetPyramidBits(facilitycode, cardnumber, bs)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); return 1; - } + } //Pyramid - compat mode, FSK2a, data rate 50, 4 data blocks blocks[0] = T55x7_MODULATION_FSK2a | T55x7_BITRATE_RF_50 | 4 << T55x7_MAXBLOCK_SHIFT; @@ -310,29 +310,29 @@ int CmdPyramidSim(const char *Cmd) { if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_pyramid_sim(); uint32_t facilitycode = 0, cardnumber = 0, fc = 0, cn = 0; - + uint8_t bs[128]; size_t size = sizeof(bs); memset(bs, 0x00, size); - + // Pyramid uses: fcHigh: 10, fcLow: 8, clk: 50, invert: 0 uint8_t clk = 50, invert = 0, high = 10, low = 8; - uint16_t arg1, arg2; + uint16_t arg1, arg2; arg1 = high << 8 | low; arg2 = invert << 8 | clk; - + if (sscanf(Cmd, "%u %u", &fc, &cn ) != 2) return usage_lf_pyramid_sim(); facilitycode = (fc & 0x000000FF); cardnumber = (cn & 0x0000FFFF); - + if ( !GetPyramidBits(facilitycode, cardnumber, bs)) { PrintAndLogEx(WARNING, "Error with tag bitstream generation."); return 1; - } + } PrintAndLogEx(SUCCESS, "Simulating Farpointe/Pyramid - Facility Code: %u, CardNumber: %u", facilitycode, cardnumber ); - + UsbCommand c = {CMD_FSK_SIM_TAG, {arg1, arg2, size}}; memcpy(c.d.asBytes, bs, size); clearCommandBuffer(); diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index e94ec84fe..4eb087874 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -61,7 +61,7 @@ int usage_t55xx_write(){ PrintAndLogEx(NORMAL, " d - 4 bytes of data to write (8 hex characters)"); PrintAndLogEx(NORMAL, " p - OPTIONAL password 4bytes (8 hex characters)"); PrintAndLogEx(NORMAL, " 1 - OPTIONAL write Page 1 instead of Page 0"); - PrintAndLogEx(NORMAL, " t - OPTIONAL test mode write - ****DANGER****"); + PrintAndLogEx(NORMAL, " t - OPTIONAL test mode write - ****DANGER****"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); PrintAndLogEx(NORMAL, " lf t55xx write b 3 d 11223344 - write 11223344 to block 3"); @@ -147,7 +147,7 @@ int usage_t55xx_chk(){ PrintAndLogEx(NORMAL, "Usage: lf t55xx bruteforce [h] [i <*.dic>]"); PrintAndLogEx(NORMAL, "Options:"); PrintAndLogEx(NORMAL, " h - this help"); - PrintAndLogEx(NORMAL, " m - use dictionary from flashmemory\n"); + PrintAndLogEx(NORMAL, " m - use dictionary from flashmemory\n"); PrintAndLogEx(NORMAL, " i <*.dic> - loads a default keys dictionary file <*.dic>"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); @@ -221,9 +221,9 @@ int usage_lf_deviceconfig(){ int CmdHelp(const char *Cmd); void printT5xxHeader(uint8_t page){ - PrintAndLogEx(NORMAL, "Reading Page %d:", page); + PrintAndLogEx(NORMAL, "Reading Page %d:", page); PrintAndLogEx(NORMAL, "blk | hex data | binary | ascii"); - PrintAndLogEx(NORMAL, "----+----------+----------------------------------+-------"); + PrintAndLogEx(NORMAL, "----+----------+----------------------------------+-------"); } int CmdT55xxSetConfig(const char *Cmd) { @@ -303,11 +303,11 @@ int CmdT55xxSetConfig(const char *Cmd) { config.offset = offset; cmdp+=2; break; - case 'q': + case 'q': config.Q5 = true; cmdp++; break; - case 's': + case 's': config.ST = true; cmdp++; break; @@ -333,14 +333,14 @@ int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32 if ( usepwd ) { // try reading the config block and verify that PWD bit is set before doing this! if ( !override ) { - + if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, false, 0 ) ) return 0; - + if ( !tryDetectModulation() ) { PrintAndLogEx(NORMAL, "Safety Check: Could not detect if PWD bit is set in config block. Exits."); return 0; } else { - PrintAndLogEx(NORMAL, "Safety Check: PWD bit is NOT set in config block. Reading without password..."); + PrintAndLogEx(NORMAL, "Safety Check: PWD bit is NOT set in config block. Reading without password..."); usepwd = false; page1 = false; } @@ -354,7 +354,7 @@ int T55xxReadBlock(uint8_t block, bool page1, bool usepwd, bool override, uint32 char blk[10] = {0}; sprintf(blk, "%02d", block); - printT55xxBlock(blk); + printT55xxBlock(blk); return 1; } @@ -405,7 +405,7 @@ int CmdT55xxReadBlock(const char *Cmd) { } bool DecodeT55xxBlock(){ - + char buf[30] = {0x00}; char *cmdStr = buf; int ans = 0; @@ -469,7 +469,7 @@ bool DecodeT55xxBlock(){ bool DecodeT5555TraceBlock() { DemodBufferLen = 0x00; - + // According to datasheet. Always: RF/64, not inverted, Manchester return (bool) ASKDemod("64 0 1", false, false, 1); } @@ -510,15 +510,15 @@ int CmdT55xxDetect(const char *Cmd){ } } if (errors) return usage_t55xx_detect(); - + // sanity check. if (!SanityOfflineCheck(useGB)) return 1; - + if ( !useGB) { if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, usepwd, password) ) return 1; } - + if ( !tryDetectModulation() ) PrintAndLogEx(WARNING, "Could not detect modulation automatically. Try setting it manually with \'lf t55xx config\'"); @@ -531,7 +531,7 @@ bool tryDetectModulation(){ t55xx_conf_block_t tests[15]; int bitRate = 0, clk = 0, firstClockEdge = 0; uint8_t hits = 0, fc1 = 0, fc2 = 0, ans = 0; - + ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, &firstClockEdge); if (ans && ((fc1==10 && fc2==8) || (fc1==8 && fc2==5))) { @@ -625,7 +625,7 @@ bool tryDetectModulation(){ ++hits; } } - + clk = GetPskClock("", false); if (clk > 0) { // allow undo @@ -676,7 +676,7 @@ bool tryDetectModulation(){ //undo trim samples save_restoreGB(GRAPH_RESTORE); } - } + } if ( hits == 1) { config.modulation = tests[0].modulation; config.bitrate = tests[0].bitrate; @@ -688,13 +688,13 @@ bool tryDetectModulation(){ printConfiguration( config ); return true; } - + bool retval = false; if ( hits > 1) { PrintAndLogEx(SUCCESS, "Found [%d] possible matches for modulation.", hits); for(int i=0; i 128 || bitRate < 8) continue; - //uint8_t AOR = PackBits(si, 1, DemodBuffer); si += 1; - //uint8_t PWD = PackBits(si, 1, DemodBuffer); si += 1; + //uint8_t AOR = PackBits(si, 1, DemodBuffer); si += 1; + //uint8_t PWD = PackBits(si, 1, DemodBuffer); si += 1; //uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2; //could check psk cr //uint8_t inverse = PackBits(si, 1, DemodBuffer); si += 1; si += 1+1+2+1; @@ -866,11 +866,11 @@ bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5) int bitRate = PackBits(si, 6, DemodBuffer); si += 6; //bit rate (includes extended mode part of rate) uint8_t extend = PackBits(si, 1, DemodBuffer); si += 1; //bit 15 extended mode - uint8_t modread = PackBits(si, 5, DemodBuffer); si += 5+2+1; + uint8_t modread = PackBits(si, 5, DemodBuffer); si += 5+2+1; //uint8_t pskcr = PackBits(si, 2, DemodBuffer); si += 2+1; //could check psk cr //uint8_t nml01 = PackBits(si, 1, DemodBuffer); si += 1+5; //bit 24, 30, 31 could be tested for 0 if not extended mode //uint8_t nml02 = PackBits(si, 2, DemodBuffer); si += 2; - + //if extended mode bool extMode =( (safer == 0x6 || safer == 0x9) && extend) ? true : false; @@ -896,7 +896,7 @@ bool test(uint8_t mode, uint8_t *offset, int *fndBitRate, uint8_t clk, bool *Q5) } void printT55xxBlock(const char *blockNum){ - + uint8_t i = config.offset; uint8_t endpos = 32 + i; uint32_t blockData = 0; @@ -927,13 +927,13 @@ int special(const char *Cmd) { PrintAndLogEx(NORMAL, "-------+-------+-------------------------------------+------"); int i,j = 0; for (; j < 64; ++j){ - + for (i = 0; i < 32; ++i) bits[i]=DemodBuffer[j+i]; - + blockData = PackBits(0, 32, bits); - - PrintAndLogEx(NORMAL, "%02d | 0x%08X | %s",j , blockData, sprint_bin(bits,32)); + + PrintAndLogEx(NORMAL, "%02d | 0x%08X | %s",j , blockData, sprint_bin(bits,32)); } return 0; } @@ -980,10 +980,10 @@ int CmdT55xxWakeUp(const char *Cmd) { int CmdT55xxWriteBlock(const char *Cmd) { uint8_t block = 0xFF; //default to invalid block - uint32_t data = 0; //default to blank Block + uint32_t data = 0; //default to blank Block uint32_t password = 0; //default to blank Block 7 bool usepwd = false; - bool page1 = false; + bool page1 = false; bool gotdata = false; bool testMode = false; bool errors = false; @@ -1026,21 +1026,21 @@ int CmdT55xxWriteBlock(const char *Cmd) { PrintAndLogEx(WARNING, "Block number must be between 0 and 7"); return 0; } - + UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {data, block, 0}}; UsbCommand resp; - c.d.asBytes[0] = (page1) ? 0x2 : 0; - c.d.asBytes[0] |= (testMode) ? 0x4 : 0; + c.d.asBytes[0] = (page1) ? 0x2 : 0; + c.d.asBytes[0] |= (testMode) ? 0x4 : 0; char pwdStr[16] = {0}; snprintf(pwdStr, sizeof(pwdStr), "pwd: 0x%08X", password); - + PrintAndLogEx(INFO, "Writing page %d block: %02d data: 0x%08X %s", page1, block, data, (usepwd) ? pwdStr : "" ); //Password mode if (usepwd) { c.arg[2] = password; - c.d.asBytes[0] |= 0x1; + c.d.asBytes[0] |= 0x1; } clearCommandBuffer(); SendCommand(&c); @@ -1057,7 +1057,7 @@ int CmdT55xxReadTrace(const char *Cmd) { bool pwdmode = false; uint32_t password = 0; - + if (strlen(Cmd) == 0) { // sanity check. if (!SanityOfflineCheck(false)) return 1; @@ -1071,29 +1071,29 @@ int CmdT55xxReadTrace(const char *Cmd) { } else { if (!DecodeT55xxBlock()) return 1; } - + if ( !DemodBufferLen ) return 1; - + RepaintGraphWindow(); uint8_t repeat = (config.offset > 5) ? 32 : 0; - + uint8_t si = config.offset + repeat; uint32_t bl1 = PackBits(si, 32, DemodBuffer); - uint32_t bl2 = PackBits(si+32, 32, DemodBuffer); - + uint32_t bl2 = PackBits(si+32, 32, DemodBuffer); + if (config.Q5) { uint32_t hdr = PackBits(si, 9, DemodBuffer); si += 9; - + if (hdr != 0x1FF) { PrintAndLogEx(FAILED, "Invalid Q5 Trace data header (expected 0x1FF, found %X)", hdr); return 1; } - + t5555_tracedata_t data = {.bl1 = bl1, .bl2 = bl2, .icr = 0, .lotidc = '?', .lotid = 0, .wafer = 0, .dw =0}; - + data.icr = PackBits(si, 2, DemodBuffer); si += 2; data.lotidc = 'Z' - PackBits(si, 2, DemodBuffer); si += 3; - + data.lotid = PackBits(si, 4, DemodBuffer); si += 5; data.lotid <<= 4; data.lotid |= PackBits(si, 4, DemodBuffer); si += 5; @@ -1103,11 +1103,11 @@ int CmdT55xxReadTrace(const char *Cmd) { data.lotid |= PackBits(si, 4, DemodBuffer); si += 5; data.lotid <<= 1; data.lotid |= PackBits(si, 1, DemodBuffer); si += 1; - + data.wafer = PackBits(si, 3, DemodBuffer); si += 4; data.wafer <<= 2; data.wafer |= PackBits(si, 2, DemodBuffer); si += 2; - + data.dw = PackBits(si, 2, DemodBuffer); si += 3; data.dw <<= 4; data.dw |= PackBits(si, 4, DemodBuffer); si += 5; @@ -1115,13 +1115,13 @@ int CmdT55xxReadTrace(const char *Cmd) { data.dw |= PackBits(si, 4, DemodBuffer); si += 5; data.dw <<= 4; data.dw |= PackBits(si, 4, DemodBuffer); si += 5; - + printT5555Trace(data, repeat); - + } else { - + t55x7_tracedata_t data = {.bl1 = bl1, .bl2 = bl2, .acl = 0, .mfc = 0, .cid = 0, .year = 0, .quarter = 0, .icr = 0, .lotid = 0, .wafer = 0, .dw = 0}; - + data.acl = PackBits(si, 8, DemodBuffer); si += 8; if ( data.acl != 0xE0 ) { PrintAndLogEx(FAILED, "The modulation is most likely wrong since the ACL is not 0xE0. "); @@ -1135,7 +1135,7 @@ int CmdT55xxReadTrace(const char *Cmd) { data.quarter = PackBits(si, 2, DemodBuffer); si += 2; data.lotid = PackBits(si, 14, DemodBuffer); si += 14; data.wafer = PackBits(si, 5, DemodBuffer); si += 5; - data.dw = PackBits(si, 15, DemodBuffer); + data.dw = PackBits(si, 15, DemodBuffer); time_t t = time(NULL); struct tm tm = *localtime(&t); @@ -1165,21 +1165,21 @@ void printT55x7Trace( t55x7_tracedata_t data, uint8_t repeat ){ PrintAndLogEx(NORMAL, " Raw Data - Page 1"); PrintAndLogEx(NORMAL, " Block 1 : 0x%08X %s", data.bl1, sprint_bin(DemodBuffer+config.offset+repeat,32) ); PrintAndLogEx(NORMAL, " Block 2 : 0x%08X %s", data.bl2, sprint_bin(DemodBuffer+config.offset+repeat+32,32) ); - PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); + PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); /* TRACE - BLOCK O Bits Definition HEX - 1-8 ACL Allocation class (ISO/IEC 15963-1) 0xE0 + 1-8 ACL Allocation class (ISO/IEC 15963-1) 0xE0 9-16 MFC Manufacturer ID (ISO/IEC 7816-6) 0x15 Atmel Corporation - 17-21 CID 0x1 = Atmel ATA5577M1 0x2 = Atmel ATA5577M2 + 17-21 CID 0x1 = Atmel ATA5577M1 0x2 = Atmel ATA5577M2 22-24 ICR IC revision 25-28 YEAR (BCD encoded) 9 (= 2009) - 29-30 QUARTER 1,2,3,4 + 29-30 QUARTER 1,2,3,4 31-32 LOT ID - + TRACE - BLOCK 1 - 1-12 LOT ID + 1-12 LOT ID 13-17 Wafer number 18-32 DW, die number sequential */ @@ -1188,7 +1188,7 @@ void printT55x7Trace( t55x7_tracedata_t data, uint8_t repeat ){ void printT5555Trace( t5555_tracedata_t data, uint8_t repeat ){ PrintAndLogEx(NORMAL, "-- T5555 (Q5) Trace Information -----------------------------"); PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); - PrintAndLogEx(NORMAL, " ICR IC Revision : %d", data.icr ); + PrintAndLogEx(NORMAL, " ICR IC Revision : %d", data.icr ); PrintAndLogEx(NORMAL, " Lot : %c%d", data.lotidc, data.lotid); PrintAndLogEx(NORMAL, " Wafer number : %d", data.wafer); PrintAndLogEx(NORMAL, " Die Number : %d", data.dw); @@ -1196,7 +1196,7 @@ void printT5555Trace( t5555_tracedata_t data, uint8_t repeat ){ PrintAndLogEx(NORMAL, " Raw Data - Page 1"); PrintAndLogEx(NORMAL, " Block 1 : 0x%08X %s", data.bl1, sprint_bin(DemodBuffer+config.offset+repeat,32) ); PrintAndLogEx(NORMAL, " Block 2 : 0x%08X %s", data.bl2, sprint_bin(DemodBuffer+config.offset+repeat+32,32) ); - + /* ** Q5 ** TRACE - BLOCK O and BLOCK1 @@ -1224,11 +1224,11 @@ int CmdT55xxInfo(const char *Cmd){ char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) > 1 || cmdp == 'h') return usage_t55xx_info(); - + if (strlen(Cmd) == 0) { // sanity check. if (!SanityOfflineCheck(false)) return 1; - + if ( !AquireData( T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, pwdmode, password ) ) return 1; } @@ -1238,29 +1238,29 @@ int CmdT55xxInfo(const char *Cmd){ // too little space to start with if ( DemodBufferLen < 32) return 1; - // + // //PrintAndLogEx(NORMAL, "Offset+32 ==%d\n DemodLen == %d", config.offset + 32, DemodBufferLen); uint8_t si = config.offset; - uint32_t block0 = PackBits(si, 32, DemodBuffer); - uint32_t safer = PackBits(si, 4, DemodBuffer); si += 4; + uint32_t block0 = PackBits(si, 32, DemodBuffer); + uint32_t safer = PackBits(si, 4, DemodBuffer); si += 4; uint32_t resv = PackBits(si, 7, DemodBuffer); si += 7; uint32_t dbr = PackBits(si, 3, DemodBuffer); si += 3; uint32_t extend = PackBits(si, 1, DemodBuffer); si += 1; uint32_t datamod = PackBits(si, 5, DemodBuffer); si += 5; uint32_t pskcf = PackBits(si, 2, DemodBuffer); si += 2; - uint32_t aor = PackBits(si, 1, DemodBuffer); si += 1; - uint32_t otp = PackBits(si, 1, DemodBuffer); si += 1; + uint32_t aor = PackBits(si, 1, DemodBuffer); si += 1; + uint32_t otp = PackBits(si, 1, DemodBuffer); si += 1; uint32_t maxblk = PackBits(si, 3, DemodBuffer); si += 3; - uint32_t pwd = PackBits(si, 1, DemodBuffer); si += 1; - uint32_t sst = PackBits(si, 1, DemodBuffer); si += 1; + uint32_t pwd = PackBits(si, 1, DemodBuffer); si += 1; + uint32_t sst = PackBits(si, 1, DemodBuffer); si += 1; uint32_t fw = PackBits(si, 1, DemodBuffer); si += 1; - uint32_t inv = PackBits(si, 1, DemodBuffer); si += 1; + uint32_t inv = PackBits(si, 1, DemodBuffer); si += 1; uint32_t por = PackBits(si, 1, DemodBuffer); si += 1; - - if (config.Q5) + + if (config.Q5) PrintAndLogEx(NORMAL, _RED_(*** Warning ***) " Config Info read off a Q5 will not display as expected"); - + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "-- T55x7 Configuration & Tag Information --------------------"); PrintAndLogEx(NORMAL, "-------------------------------------------------------------"); @@ -1292,20 +1292,20 @@ int CmdT55xxDump(const char *Cmd){ char cmdp = tolower(param_getchar(Cmd, 0)); if ( cmdp == 'h') return usage_t55xx_dump(); - bool usepwd = ( strlen(Cmd) > 0); + bool usepwd = ( strlen(Cmd) > 0); if ( usepwd ){ password = param_get32ex(Cmd, 0, 0, 16); if (param_getchar(Cmd, 1) =='o' ) override = true; } - + printT5xxHeader(0); for ( uint8_t i = 0; i < 8; ++i) T55xxReadBlock(i, 0, usepwd, override, password); printT5xxHeader(1); for ( uint8_t i = 0; i < 4; i++) - T55xxReadBlock(i, 1, usepwd, override, password); + T55xxReadBlock(i, 1, usepwd, override, password); return 1; } @@ -1362,7 +1362,7 @@ char * GetBitRateStr(uint32_t id, bool xmode) { char * GetSaferStr(uint32_t id){ static char buf[40]; char *retStr = buf; - + snprintf(retStr,sizeof(buf),"%d",id); if (id == 6) { snprintf(retStr,sizeof(buf),"%d - passwd",id); @@ -1370,14 +1370,14 @@ char * GetSaferStr(uint32_t id){ if (id == 9 ){ snprintf(retStr,sizeof(buf),"%d - testmode",id); } - + return buf; } char * GetModulationStr( uint32_t id){ static char buf[60]; char *retStr = buf; - + switch (id){ case 0: snprintf(retStr,sizeof(buf),"%d - DIRECT (ASK/NRZ)",id); break; case 1: snprintf(retStr,sizeof(buf),"%d - PSK 1 phase change when input changes",id); break; @@ -1397,12 +1397,12 @@ char * GetModulationStr( uint32_t id){ } char * GetModelStrFromCID(uint32_t cid){ - + static char buf[10]; char *retStr = buf; - + if (cid == 1) snprintf(retStr, sizeof(buf),"ATA5577M1"); - if (cid == 2) snprintf(retStr, sizeof(buf),"ATA5577M2"); + if (cid == 2) snprintf(retStr, sizeof(buf),"ATA5577M2"); return buf; } @@ -1434,12 +1434,12 @@ void t55x7_create_config_block( int tagtype ){ /* T55X7_DEFAULT_CONFIG_BLOCK, T55X7_RAW_CONFIG_BLOCK T55X7_EM_UNIQUE_CONFIG_BLOCK, T55X7_FDXB_CONFIG_BLOCK, - T55X7_FDXB_CONFIG_BLOCK, T55X7_HID_26_CONFIG_BLOCK, T55X7_INDALA_64_CONFIG_BLOCK, T55X7_INDALA_224_CONFIG_BLOCK - T55X7_GUARDPROXII_CONFIG_BLOCK, T55X7_VIKING_CONFIG_BLOCK, T55X7_NORALYS_CONFIG_BLOCK, T55X7_IOPROX_CONFIG_BLOCK + T55X7_FDXB_CONFIG_BLOCK, T55X7_HID_26_CONFIG_BLOCK, T55X7_INDALA_64_CONFIG_BLOCK, T55X7_INDALA_224_CONFIG_BLOCK + T55X7_GUARDPROXII_CONFIG_BLOCK, T55X7_VIKING_CONFIG_BLOCK, T55X7_NORALYS_CONFIG_BLOCK, T55X7_IOPROX_CONFIG_BLOCK */ static char buf[60]; char *retStr = buf; - + switch (tagtype){ case 0: snprintf(retStr, sizeof(buf),"%08X - T55X7 Default", T55X7_DEFAULT_CONFIG_BLOCK); break; case 1: snprintf(retStr, sizeof(buf),"%08X - T55X7 Raw", T55X7_RAW_CONFIG_BLOCK); break; @@ -1471,7 +1471,7 @@ int CmdResetRead(const char *Cmd) { int CmdT55xxWipe(const char *Cmd) { char writeData[20] = {0}; char *ptrData = writeData; - char cmdp = param_getchar(Cmd, 0); + char cmdp = param_getchar(Cmd, 0); if ( cmdp == 'h' || cmdp == 'H') return usage_t55xx_wipe(); bool Q5 = (cmdp == 'q' || cmdp == 'Q'); @@ -1479,20 +1479,20 @@ int CmdT55xxWipe(const char *Cmd) { // Try with the default password to reset block 0 // With a pwd should work even if pwd bit not set PrintAndLogEx(INFO, "\nBeginning Wipe of a T55xx tag (assuming the tag is not password protected)\n"); - + if ( Q5 ) snprintf(ptrData,sizeof(writeData),"b 0 d 6001F004 p 0"); else snprintf(ptrData,sizeof(writeData),"b 0 d 000880E0 p 0"); - + if (!CmdT55xxWriteBlock(ptrData)) PrintAndLogEx(WARNING, "Error writing blk 0"); - + for (uint8_t blk = 1; blk<8; blk++) { - + snprintf(ptrData,sizeof(writeData),"b %d d 0", blk); - + if (!CmdT55xxWriteBlock(ptrData)) PrintAndLogEx(WARNING, "Error writing blk %d", blk); - + memset(writeData, 0x00, sizeof(writeData)); } return 0; @@ -1518,22 +1518,22 @@ int CmdT55xxChkPwds(const char *Cmd) { uint8_t timeout = 0; memset(line, 0, sizeof(line)); - + char cmdp = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd) == 0 || cmdp == 'h') return usage_t55xx_chk(); - + /* if ( T55xxReadBlock(7, 0, 0, 0, 0) ) { - + // now try to validate it.. PrintAndLogEx(WARNING, "\n Block 7 was readable"); return 1; } */ - + uint64_t t1 = msclock(); - if ( cmdp == 'm' ) { + if ( cmdp == 'm' ) { UsbCommand c = {CMD_T55XX_CHKPWDS, {0,0,0} }; clearCommandBuffer(); SendCommand(&c); @@ -1547,15 +1547,15 @@ int CmdT55xxChkPwds(const char *Cmd) { return 2; } } - + if ( resp.arg[0] ) { PrintAndLogEx(SUCCESS, "\nFound a candidate [ %08X ]. Trying to validate", resp.arg[1]); - + if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, resp.arg[1])) { PrintAndLogEx(INFO, "Aquireing data from device failed. Quitting"); return 2; } - + found = tryDetectModulation(); if (found) { PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", resp.arg[1]); @@ -1565,32 +1565,32 @@ int CmdT55xxChkPwds(const char *Cmd) { } else { PrintAndLogEx(WARNING, "Password NOT found."); } - + goto out; } - + keyBlock = calloc(stKeyBlock, 4); if (keyBlock == NULL) return 1; if (cmdp == 'i') { - + int len = strlen(Cmd+2); if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; memcpy(filename, Cmd+2, len); - - FILE * f = fopen( filename , "r"); + + FILE * f = fopen( filename , "r"); if ( !f ) { PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); free(keyBlock); return 1; - } - + } + while( fgets(line, sizeof(line), f) ){ if (strlen(line) < 8 || line[7] == '\n') continue; - + //goto next line while (fgetc(f) != '\n' && !feof(f)) ; - + //The line start with # is comment, skip if( line[0]=='#' ) continue; @@ -1598,9 +1598,9 @@ int CmdT55xxChkPwds(const char *Cmd) { PrintAndLogEx(WARNING, "File content error. '%s' must include 8 HEX symbols", line); continue; } - - line[8] = 0; - + + line[8] = 0; + // realloc keyblock array size. if ( stKeyBlock - keycnt < 2) { p = realloc(keyBlock, 4 * (stKeyBlock += 10)); @@ -1615,24 +1615,24 @@ int CmdT55xxChkPwds(const char *Cmd) { } // clear mem memset(keyBlock + 4 * keycnt, 0, 4); - + num_to_bytes( strtoll(line, NULL, 16), 4, keyBlock + 4*keycnt); - + // PrintAndLogEx(NORMAL, "chk custom pwd[%2d] %08X", keycnt, bytes_to_num(keyBlock + 4 * keycnt, 4) ); - keycnt++; + keycnt++; memset(line, 0, sizeof(line)); } - + if (f) fclose(f); - + if (keycnt == 0) { PrintAndLogEx(WARNING, "No keys found in file"); free(keyBlock); return 1; } PrintAndLogEx(SUCCESS, "Loaded %d keys", keycnt); - + // loop uint64_t testpwd = 0x00; for (uint16_t c = 0; c < keycnt; ++c ) { @@ -1642,43 +1642,43 @@ int CmdT55xxChkPwds(const char *Cmd) { free(keyBlock); return 2; } - + if (IsCancelled()) { free(keyBlock); return 0; } - + testpwd = bytes_to_num(keyBlock + 4*c, 4); PrintAndLogEx(INFO, "Testing %08X", testpwd); - + if ( !AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, testpwd)) { PrintAndLogEx(INFO, "Aquireing data from device failed. Quitting"); free(keyBlock); return 0; } - + found = tryDetectModulation(); if ( found ) break; - + } - if ( found ) + if ( found ) PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", testpwd); else - PrintAndLogEx(WARNING, "Password NOT found."); + PrintAndLogEx(WARNING, "Password NOT found."); } - + free(keyBlock); - + out: t1 = msclock() - t1; - PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1/1000.0); + PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1/1000.0); return 0; } int CmdT55xxBruteForce(const char *Cmd) { - + uint32_t start_password = 0x00000000; //start password uint32_t end_password = 0xFFFFFFFF; //end password uint32_t curr = 0; @@ -1687,52 +1687,52 @@ int CmdT55xxBruteForce(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); if (cmdp == 'h') return usage_t55xx_bruteforce(); - + uint64_t t1 = msclock(); // Try to read Block 7, first :) - + // incremental pwd range search start_password = param_get32ex(Cmd, 0, 0, 16); end_password = param_get32ex(Cmd, 1, 0, 16); - + curr = start_password; - + if ( start_password >= end_password ) { return usage_t55xx_bruteforce(); } - + PrintAndLogEx(INFO, "Search password range [%08X -> %08X]", start_password, end_password); while ( !found ){ printf("."); fflush(stdout); - + if (IsCancelled()) { return 0; } - + if (!AquireData(T55x7_PAGE0, T55x7_CONFIGURATION_BLOCK, true, curr)) { PrintAndLogEx(WARNING, "Aquiring data from device failed. Quitting"); return 0; } - + found = tryDetectModulation(); if (curr == end_password) break; curr++; } - + PrintAndLogEx(NORMAL, ""); - + if (found) PrintAndLogEx(SUCCESS, "Found valid password: [ %08X ]", curr); else PrintAndLogEx(WARNING, "Password NOT found. Last tried: [ %08X ]", --curr); t1 = msclock() - t1; - PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1/1000.0); + PrintAndLogEx(SUCCESS, "\nTime in bruteforce: %.0f seconds\n", (float)t1/1000.0); return 0; } @@ -1745,7 +1745,7 @@ int tryOnePassword(uint32_t password) { if (tryDetectModulation()) return 1; - else + else return 0; } @@ -1767,14 +1767,14 @@ int CmdT55xxRecoverPW(const char *Cmd) { found = tryOnePassword(curr_password); if (found == -1) return 0; bit++; - + if (IsCancelled()) return 0; } // now try to use partial original password, since block 7 should have been completely // erased during the write sequence and it is possible that only partial password has been // written - // not sure from which end the bit bits are written, so try from both ends + // not sure from which end the bit bits are written, so try from both ends // from low bit to high bit bit = 0; while (bit < 32) { @@ -1789,7 +1789,7 @@ int CmdT55xxRecoverPW(const char *Cmd) { if (found == -1) return 0; bit++; prev_password = curr_password; - + if (IsCancelled()) return 0; } @@ -1809,7 +1809,7 @@ int CmdT55xxRecoverPW(const char *Cmd) { return 0; bit++; prev_password = curr_password; - + if (IsCancelled()) return 0; } @@ -1823,8 +1823,8 @@ int CmdT55xxRecoverPW(const char *Cmd) { return 0; } -// note length of data returned is different for different chips. -// some return all page 1 (64 bits) and others return just that block (32 bits) +// note length of data returned is different for different chips. +// some return all page 1 (64 bits) and others return just that block (32 bits) // unfortunately the 64 bits makes this more likely to get a false positive... bool tryDetectP1(bool getData) { uint8_t preamble[] = {1,1,1,0,0,0,0,0,0,0,0,1,0,1,0,1}; @@ -1841,13 +1841,13 @@ bool tryDetectP1(bool getData) { // try fsk clock detect. if successful it cannot be any other type of modulation... (in theory...) ans = fskClocks(&fc1, &fc2, (uint8_t *)&clk, &firstClockEdge); if (ans && ((fc1==10 && fc2==8) || (fc1==8 && fc2==5))) { - if ( FSKrawDemod("0 0", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + if ( FSKrawDemod("0 0", false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64) ) { return true; } - if ( FSKrawDemod("0 1", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + if ( FSKrawDemod("0 1", false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64) ) { return true; } @@ -1858,23 +1858,23 @@ bool tryDetectP1(bool getData) { clk = GetAskClock("", false); if (clk > 0) { if ( ASKDemod_ext("0 0 1", false, false, 1, &st) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64) ) { return true; } st = true; if ( ASKDemod_ext("0 1 1", false, false, 1, &st) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64) ) { return true; } if ( ASKbiphaseDemod("0 0 0 2", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64) ) { return true; } if ( ASKbiphaseDemod("0 0 1 2", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64) ) { return true; } @@ -1884,17 +1884,17 @@ bool tryDetectP1(bool getData) { clk = GetNrzClock("", false); //has the most false positives :( if (clk > 0) { if ( NRZrawDemod("0 0 1", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64) ) { return true; } if ( NRZrawDemod("0 1 1", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64) ) { return true; } } - + // Fewer card uses PSK // try psk clock detect. if successful it cannot be any other type of modulation... (in theory...) clk = GetPskClock("", false); @@ -1904,13 +1904,13 @@ bool tryDetectP1(bool getData) { // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) //CmdLtrim("160"); if ( PSKDemod("0 0 6", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64) ) { //save_restoreGB(0); return true; } if ( PSKDemod("0 1 6", false) && - preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64) ) { //save_restoreGB(0); return true; @@ -1918,14 +1918,14 @@ bool tryDetectP1(bool getData) { // PSK2 - needs a call to psk1TOpsk2. if ( PSKDemod("0 0 6", false)) { psk1TOpsk2(DemodBuffer, DemodBufferLen); - if (preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && + if (preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64) ) { //save_restoreGB(0); return true; } } // inverse waves does not affect PSK2 demod //undo trim samples - //save_restoreGB(0); + //save_restoreGB(0); // no other modulation clocks = 2 or 4 so quit searching if (fc1 != 8) return false; } @@ -2013,7 +2013,7 @@ int CmdT55xxSetDeviceConfig(const char *Cmd){ //Validations if (errors || cmdp == 0) return usage_lf_deviceconfig(); - + t55xx_config config = { startgap*8, writegap*8, write0*8, write1*8, readgap*8 }; UsbCommand c = {CMD_SET_LF_T55XX_CONFIG, {shall_persist,0,0} }; @@ -2036,7 +2036,7 @@ static command_t CommandTable[] = { {"read", CmdT55xxReadBlock, 0, "b p [password] [o] [1] -- Read T55xx block data. Optional [p password], [override], [page1]"}, {"resetread", CmdResetRead, 0, "Send Reset Cmd then lf read the stream to attempt to identify the start of it (needs a demod and/or plot after)"}, {"recoverpw", CmdT55xxRecoverPW, 0, "[password] Try to recover from bad password write from a cloner. Only use on PW protected chips!"}, - {"special", special, 0, "Show block changes with 64 different offsets"}, + {"special", special, 0, "Show block changes with 64 different offsets"}, {"trace", CmdT55xxReadTrace, 1, "[1] Show T55x7 traceability data (page 1/ blk 0-1)"}, {"wakeup", CmdT55xxWakeUp, 0, "Send AOR wakeup command"}, {"wipe", CmdT55xxWipe, 0, "[q] Wipe a T55xx tag and set defaults (will destroy any data on tag)"}, diff --git a/client/cmdlft55xx.h b/client/cmdlft55xx.h index 775f7ccca..c4e0fc98b 100644 --- a/client/cmdlft55xx.h +++ b/client/cmdlft55xx.h @@ -75,15 +75,15 @@ enum { typedef struct { uint32_t bl1; - uint32_t bl2; - uint32_t acl; - uint32_t mfc; - uint32_t cid; - uint32_t year; - uint32_t quarter; + uint32_t bl2; + uint32_t acl; + uint32_t mfc; + uint32_t cid; + uint32_t year; + uint32_t quarter; uint32_t icr; - uint32_t lotid; - uint32_t wafer; + uint32_t lotid; + uint32_t wafer; uint32_t dw; } t55x7_tracedata_t; @@ -99,18 +99,18 @@ typedef struct { typedef struct { enum { - DEMOD_NRZ = 0x00, + DEMOD_NRZ = 0x00, DEMOD_PSK1 = 0x01, DEMOD_PSK2 = 0x02, DEMOD_PSK3 = 0x03, - DEMOD_FSK1 = 0x04, - DEMOD_FSK1a = 0x05, - DEMOD_FSK2 = 0x06, - DEMOD_FSK2a = 0x07, - DEMOD_FSK = 0xF0, //generic FSK (auto detect FCs) + DEMOD_FSK1 = 0x04, + DEMOD_FSK1a = 0x05, + DEMOD_FSK2 = 0x06, + DEMOD_FSK2a = 0x07, + DEMOD_FSK = 0xF0, //generic FSK (auto detect FCs) DEMOD_ASK = 0x08, DEMOD_BI = 0x10, - DEMOD_BIa = 0x18, + DEMOD_BIa = 0x18, } modulation; bool inverted; uint8_t offset; diff --git a/client/cmdlfti.c b/client/cmdlfti.c index e5f3530f0..9928faf27 100644 --- a/client/cmdlfti.c +++ b/client/cmdlfti.c @@ -207,7 +207,7 @@ int CmdTIDemod(const char *Cmd) } RepaintGraphWindow(); - + PrintAndLogEx(INFO, "INFO: raw tag bits = %s", bits); TagType = (shift3>>8)&0xff; @@ -249,16 +249,16 @@ int CmdTIDemod(const char *Cmd) crc = update_crc16(crc, (shift1>>8)&0xff); crc = update_crc16(crc, (shift1>>16)&0xff); crc = update_crc16(crc, (shift1>>24)&0xff); - + //crc = crc16_ccitt(message, sizeof(message); char *crcStr = (crc == (shift2&0xffff) ) ? "Passed" : "Failed"; - + PrintAndLogEx(NORMAL, "Tag data = %08X%08X [Crc %04X %s]", shift1, shift0, crc, crcStr ); if (crc != (shift2&0xffff)) PrintAndLogEx(WARNING, "Error: CRC mismatch, calculated %04X, got %04X", crc, shift2&0xffff); - + } else { PrintAndLogEx(WARNING, "Unknown tag type."); diff --git a/client/cmdlfviking.c b/client/cmdlfviking.c index 33a5588d3..7f32ab5e5 100644 --- a/client/cmdlfviking.c +++ b/client/cmdlfviking.c @@ -52,18 +52,18 @@ int detectViking(uint8_t *dest, size_t *size) { if (*size < 64*2) return -2; size_t startIdx = 0; uint8_t preamble[] = {1,1,1,1,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) return -4; //preamble not found - - uint32_t checkCalc = bytebits_to_byte(dest+startIdx,8) ^ - bytebits_to_byte(dest+startIdx+8,8) ^ - bytebits_to_byte(dest+startIdx+16,8) ^ - bytebits_to_byte(dest+startIdx+24,8) ^ - bytebits_to_byte(dest+startIdx+32,8) ^ - bytebits_to_byte(dest+startIdx+40,8) ^ - bytebits_to_byte(dest+startIdx+48,8) ^ + + uint32_t checkCalc = bytebits_to_byte(dest+startIdx,8) ^ + bytebits_to_byte(dest+startIdx+8,8) ^ + bytebits_to_byte(dest+startIdx+16,8) ^ + bytebits_to_byte(dest+startIdx+24,8) ^ + bytebits_to_byte(dest+startIdx+32,8) ^ + bytebits_to_byte(dest+startIdx+40,8) ^ + bytebits_to_byte(dest+startIdx+48,8) ^ bytebits_to_byte(dest+startIdx+56,8); - if ( checkCalc != 0xA8 ) return -5; + if ( checkCalc != 0xA8 ) return -5; if (*size != 64) return -6; //return start position return (int)startIdx; @@ -108,18 +108,18 @@ int CmdVikingClone(const char *Cmd) { bool Q5 = false; char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd) == 0 || cmdp == 'h' || cmdp == 'H') return usage_lf_viking_clone(); - + id = param_get32ex(Cmd, 0, 0, 16); if (id == 0) return usage_lf_viking_clone(); - + cmdp = param_getchar(Cmd, 1); if ( cmdp == 'Q' || cmdp == 'q') Q5 = true; rawID = getVikingBits(id); - + PrintAndLogEx(INFO, "Preparing to clone Viking tag - ID: %08X, Raw: %08X%08X",id,(uint32_t)(rawID >> 32),(uint32_t) (rawID & 0xFFFFFFFF)); - + UsbCommand c = {CMD_VIKING_CLONE_TAG, {rawID >> 32, rawID & 0xFFFFFFFF, Q5}}; clearCommandBuffer(); SendCommand(&c); @@ -150,7 +150,7 @@ int CmdVikingSim(const char *Cmd) { arg2 = invert << 8 | separator; PrintAndLogEx(SUCCESS, "Simulating Viking - ID: %08X, Raw: %08X%08X",id,(uint32_t)(rawID >> 32),(uint32_t) (rawID & 0xFFFFFFFF)); - + UsbCommand c = {CMD_ASK_SIM_TAG, {arg1, arg2, size}}; num_to_bytebits(rawID, size, c.d.asBytes); clearCommandBuffer(); diff --git a/client/cmdlfvisa2000.c b/client/cmdlfvisa2000.c index 031894728..430aea8f4 100644 --- a/client/cmdlfvisa2000.c +++ b/client/cmdlfvisa2000.c @@ -56,7 +56,7 @@ static uint8_t visa_parity( uint32_t id) { ,1,0,0,1 ,1,0,0,1 ,0,1,1,0 - }; + }; uint8_t par = 0; par |= par_lut[ (id >> 28) & 0xF ] << 7; par |= par_lut[ (id >> 24) & 0xF ] << 6; @@ -66,7 +66,7 @@ static uint8_t visa_parity( uint32_t id) { par |= par_lut[ (id >> 8) & 0xF ] << 2; par |= par_lut[ (id >> 4) & 0xF ] << 1; par |= par_lut[ (id & 0xF) ]; - return par; + return par; } // by iceman @@ -91,15 +91,15 @@ int detectVisa2k(uint8_t *dest, size_t *size) { * i = card id * p = even parity bit for each nibble in card id. * c = checksum (xor of card id) -* +* **/ //see ASKDemod for what args are accepted int CmdVisa2kDemod(const char *Cmd) { - + save_restoreGB(GRAPH_SAVE); - + //sCmdAskEdgeDetect(""); - + //ASK / Manchester bool st = true; if (!ASKDemod_ext("64 0 0", false, false, 1, &st)) { @@ -124,18 +124,18 @@ int CmdVisa2kDemod(const char *Cmd) { } setDemodBuf(DemodBuffer, 96, ans); setClockGrid(g_DemodClock, g_DemodStartIdx + (ans*g_DemodClock)); - + //got a good demod uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); uint32_t raw3 = bytebits_to_byte(DemodBuffer+64, 32); - + // chksum uint8_t calc = visa_chksum(raw2); - uint8_t chk = raw3 & 0xF; - + uint8_t chk = raw3 & 0xF; + // test checksums - if ( chk != calc ) { + if ( chk != calc ) { PrintAndLogEx(DEBUG, "DEBUG: error: Visa2000 checksum failed %x - %x\n", chk, calc); save_restoreGB(GRAPH_RESTORE); return 0; @@ -146,7 +146,7 @@ int CmdVisa2kDemod(const char *Cmd) { if ( calc_par != chk_par) { PrintAndLogEx(DEBUG, "DEBUG: error: Visa2000 parity failed %x - %x\n", chk_par, calc_par); save_restoreGB(GRAPH_RESTORE); - return 0; + return 0; } PrintAndLogEx(SUCCESS, "Visa2000 Tag Found: Card ID %u, Raw: %08X%08X%08X", raw2, raw1 ,raw2, raw3); return 1; @@ -167,17 +167,17 @@ int CmdVisa2kClone(const char *Cmd) { if (strlen(Cmd) == 0 || cmdp == 'h') return usage_lf_visa2k_clone(); id = param_get32ex(Cmd, 0, 0, 10); - + //Q5 if (param_getchar(Cmd, 1) == 'Q' || param_getchar(Cmd, 1) == 'q') blocks[0] = T5555_MODULATION_MANCHESTER | T5555_SET_BITRATE(64) | T5555_ST_TERMINATOR | 3 << T5555_MAXBLOCK_SHIFT; - + blocks[2] = id; - blocks[3] = (visa_parity(id) << 4) | visa_chksum(id); + blocks[3] = (visa_parity(id) << 4) | visa_chksum(id); PrintAndLogEx(INFO, "Preparing to clone Visa2000 to T55x7 with CardId: %u", id); print_blocks(blocks, 4); - + UsbCommand resp; UsbCommand c = {CMD_T55XX_WRITE_BLOCK, {0,0,0}}; @@ -224,7 +224,7 @@ int CmdVisa2kSim(const char *Cmd) { static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"demod", CmdVisa2kDemod, 1, "demodulate an VISA2000 tag from the GraphBuffer"}, + {"demod", CmdVisa2kDemod, 1, "demodulate an VISA2000 tag from the GraphBuffer"}, {"read", CmdVisa2kRead, 0, "attempt to read and extract tag data from the antenna"}, {"clone", CmdVisa2kClone, 0, "clone Visa2000 to t55x7"}, {"sim", CmdVisa2kSim, 0, "simulate Visa2000 tag"}, diff --git a/client/cmdmain.c b/client/cmdmain.c index 9b71df21d..20e388b43 100644 --- a/client/cmdmain.c +++ b/client/cmdmain.c @@ -23,7 +23,7 @@ static command_t CommandTable[] = { {"hw", CmdHW, 1, "{ Hardware commands... }"}, {"lf", CmdLF, 1, "{ Low Frequency commands... }"}, {"emv", CmdEMV, 1, "{ EMV iso14443 and iso7816... }"}, - {"rem", CmdRem, 1, "{ Add text to row in log file }"}, + {"rem", CmdRem, 1, "{ Add text to row in log file }"}, {"reveng", CmdRev, 1, "{ Crc calculations from the RevEng software... }"}, {"script", CmdScript, 1, "{ Scripting commands }"}, {"trace", CmdTrace, 1, "{ Trace manipulation... }"}, diff --git a/client/cmdmain.h b/client/cmdmain.h index 629cd98af..a1ef64e1a 100644 --- a/client/cmdmain.h +++ b/client/cmdmain.h @@ -31,7 +31,7 @@ #include "cmdscript.h" #include "cmdcrc.h" #include "cmdanalyse.h" -#include "emv/cmdemv.h" // EMV +#include "emv/cmdemv.h" // EMV #ifdef WITH_FLASH #include "cmdflashmem.h" // rdv40 flashmem commands diff --git a/client/cmdparser.c b/client/cmdparser.c index 974439298..bbe7b2d8d 100644 --- a/client/cmdparser.c +++ b/client/cmdparser.c @@ -82,7 +82,7 @@ void dumpCommandsRecursive(const command_t cmds[], int markdown) { int i = 0; int w_cmd = 25; int w_off = 8; - // First, dump all single commands, which are not a container for + // First, dump all single commands, which are not a container for // other commands if (markdown) { PrintAndLogEx(NORMAL, "|%-*s|%-*s|%s\n",w_cmd,"command",w_off,"offline","description"); @@ -96,7 +96,7 @@ void dumpCommandsRecursive(const command_t cmds[], int markdown) { char* cmd_offline = "N"; if (cmds[i].Help[0] == '{' && ++i) continue; - if ( cmds[i].Offline) + if ( cmds[i].Offline) cmd_offline = "Y"; if (markdown) PrintAndLogEx(NORMAL, "|`%s%-*s`|%-*s|`%s`\n", parent, w_cmd-(int)strlen(parent)-2, cmds[i].Name, w_off, cmd_offline, cmds[i].Help); @@ -106,7 +106,7 @@ void dumpCommandsRecursive(const command_t cmds[], int markdown) { } PrintAndLogEx(NORMAL, "\n\n"); i = 0; - + // Then, print the categories. These will go into subsections with their own tables while (cmds[i].Name) { if(cmds[i].Help[0] != '{' && ++i) continue; @@ -118,7 +118,7 @@ void dumpCommandsRecursive(const command_t cmds[], int markdown) { char *old_parent = parent; parent = currentparent; // This is what causes the recursion, since commands Parse-implementation - // in turn calls the CmdsParse above. + // in turn calls the CmdsParse above. if (markdown) cmds[i].Parse("XX_internal_command_dump_markdown_XX"); else diff --git a/client/cmdparser.h b/client/cmdparser.h index 97b8f2813..eeb9a1460 100644 --- a/client/cmdparser.h +++ b/client/cmdparser.h @@ -9,7 +9,7 @@ //----------------------------------------------------------------------------- #ifndef CMDPARSER_H__ -#define CMDPARSER_H__ +#define CMDPARSER_H__ typedef struct command_s { diff --git a/client/cmdscript.c b/client/cmdscript.c index 7159fa70b..6ded9c1a9 100644 --- a/client/cmdscript.c +++ b/client/cmdscript.c @@ -63,7 +63,7 @@ bool endsWith(char* base, char* str) { } /** -* Generate a sorted list of available commands, what it does is +* Generate a sorted list of available commands, what it does is * generate a file listing of the script-directory for files * ending with .lua */ @@ -129,7 +129,7 @@ int CmdScriptRun(const char *Cmd) { if (!endsWith(script_name, ".lua")) { suffix = ".lua"; } - + char script_path[strlen(get_my_executable_directory()) + strlen(LUA_SCRIPTS_DIRECTORY) + strlen(script_name) + strlen(suffix) + 1]; strcpy(script_path, get_my_executable_directory()); strcat(script_path, LUA_SCRIPTS_DIRECTORY); diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index f371c87ce..42d777ee4 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -36,7 +36,7 @@ int usage_sm_reader(void) { PrintAndLogEx(NORMAL, " s : silent (no messages)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " sc reader"); + PrintAndLogEx(NORMAL, " sc reader"); return 0; } int usage_sm_info(void) { @@ -45,7 +45,7 @@ int usage_sm_info(void) { PrintAndLogEx(NORMAL, " s : silent (no messages)"); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " sc info"); + PrintAndLogEx(NORMAL, " sc info"); return 0; } int usage_sm_upgrade(void) { @@ -64,7 +64,7 @@ int usage_sm_setclock(void) { PrintAndLogEx(NORMAL, " c <> : clockspeed (0 = 16mhz, 1=8mhz, 2=4mhz) "); PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " sc setclock c 2"); + PrintAndLogEx(NORMAL, " sc setclock c 2"); return 0; } int usage_sm_brute(void) { @@ -93,29 +93,29 @@ static int smart_loadjson(const char *preferredName, const char *suffix, json_t *root = json_load_file(fileName, 0, &error); if (!*root) { PrintAndLogEx(ERR, "json (%s) error on line %d: %s", fileName, error.line, error.text); - retval = 2; + retval = 2; goto out; } - + if (!json_is_array(*root)) { PrintAndLogEx(ERR, "Invalid json (%s) format. root must be an array.", fileName); - retval = 3; + retval = 3; goto out; } PrintAndLogEx(SUCCESS, "Loaded file (%s) OK.", fileName); -out: +out: free(fileName); - return retval; + return retval; } uint8_t GetATRTA1(uint8_t *atr, size_t atrlen) { - if (atrlen > 2) { + if (atrlen > 2) { uint8_t T0 = atr[1]; if (T0 & 0x10) return atr[2]; } - + return 0x11; // default value is ‘0x11’, corresponding to fmax=5 MHz, Fi=372, Di=1. } @@ -178,7 +178,7 @@ float FArray[] = { int GetATRDi(uint8_t *atr, size_t atrlen) { uint8_t TA1 = GetATRTA1(atr, atrlen); - return DiArray[TA1 & 0x0F]; // The 4 low-order bits of TA1 (4th MSbit to 1st LSbit) encode Di + return DiArray[TA1 & 0x0F]; // The 4 low-order bits of TA1 (4th MSbit to 1st LSbit) encode Di } int GetATRFi(uint8_t *atr, size_t atrlen) { @@ -192,31 +192,31 @@ float GetATRF(uint8_t *atr, size_t atrlen) { } static int PrintATR(uint8_t *atr, size_t atrlen) { - + uint8_t T0 = atr[1]; uint8_t K = T0 & 0x0F; uint8_t TD1 = 0, T1len = 0, TD1len = 0, TDilen = 0; - + if (T0 & 0x10) { PrintAndLog("\t- TA1 (Maximum clock frequency, proposed bit duration) [ 0x%02x ]", atr[2 + T1len]); T1len++; } - + if (T0 & 0x20) { PrintAndLog("\t- TB1 (Deprecated: VPP requirements) [ 0x%02x ]", atr[2 + T1len]); T1len++; } - + if (T0 & 0x40) { PrintAndLog("\t- TC1 (Extra delay between bytes required by card) [ 0x%02x ]", atr[2 + T1len]); T1len++; } - + if (T0 & 0x80) { TD1 = atr[2 + T1len]; PrintAndLog("\t- TD1 (First offered transmission protocol, presence of TA2..TD2) [ 0x%02x ] Protocol T%d", TD1, TD1 & 0x0f); T1len++; - + if (TD1 & 0x10) { PrintAndLog("\t- TA2 (Specific protocol and parameters to be used after the ATR) [ 0x%02x ]", atr[2 + T1len + TD1len]); TD1len++; @@ -254,7 +254,7 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { TDi = atr[2 + T1len + TD1len + TDilen]; PrintAndLog("\t- TD%d [ 0x%02x ] Protocol T%d", vi, TDi, TDi & 0x0f); TDilen++; - + nextCycle = true; vi++; } @@ -265,7 +265,7 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { uint8_t vxor = 0; for (int i = 1; i < atrlen; i++) vxor ^= atr[i]; - + if (vxor) PrintAndLogEx(WARNING, "Check summ error. Must be 0 got 0x%02X", vxor); else @@ -274,26 +274,26 @@ static int PrintATR(uint8_t *atr, size_t atrlen) { if (atr[0] != 0x3b) PrintAndLogEx(WARNING, "Not a direct convention [ 0x%02x ]", atr[0]); - + uint8_t calen = 2 + T1len + TD1len + TDilen + K; - + if (atrlen != calen && atrlen != calen + 1) // may be CRC PrintAndLogEx(ERR, "ATR length error. len: %d, T1len: %d, TD1len: %d, TDilen: %d, K: %d", atrlen, T1len, TD1len, TDilen, K); - + if (K > 0) PrintAndLogEx(INFO, "\nHistorical bytes | len 0x%02d | format %02x", K, atr[2 + T1len + TD1len + TDilen]); - + if (K > 1) { PrintAndLogEx(INFO, "\tHistorical bytes"); dump_buffer(&atr[2 + T1len + TD1len + TDilen], K, NULL, 1); } - + return 0; } bool smart_select(bool silent, smart_card_atr_t *atr) { if (atr) - memset(atr, 0, sizeof(smart_card_atr_t)); + memset(atr, 0, sizeof(smart_card_atr_t)); UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}}; clearCommandBuffer(); @@ -303,21 +303,21 @@ bool smart_select(bool silent, smart_card_atr_t *atr) { if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); return false; } - + uint8_t isok = resp.arg[0] & 0xFF; if (!isok) { if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); return false; - } + } smart_card_atr_t card; memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t)); if (atr) - memcpy(atr, &card, sizeof(smart_card_atr_t)); + memcpy(atr, &card, sizeof(smart_card_atr_t)); if (!silent) - PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len)); + PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len)); return true; } @@ -328,27 +328,27 @@ static int smart_wait(uint8_t *data, bool silent) { if (!silent) PrintAndLogEx(WARNING, "smart card response timeout"); return -1; } - - uint32_t len = resp.arg[0]; + + uint32_t len = resp.arg[0]; if ( !len ) { if (!silent) PrintAndLogEx(WARNING, "smart card response failed"); - return -2; + return -2; } - memcpy(data, resp.d.asBytes, len); - if (len >= 2) { - if (!silent) PrintAndLogEx(SUCCESS, "%02X%02X | %s", data[len - 2], data[len - 1], GetAPDUCodeDescription(data[len - 2], data[len - 1])); + memcpy(data, resp.d.asBytes, len); + if (len >= 2) { + if (!silent) PrintAndLogEx(SUCCESS, "%02X%02X | %s", data[len - 2], data[len - 1], GetAPDUCodeDescription(data[len - 2], data[len - 1])); } else { if (!silent) PrintAndLogEx(SUCCESS, " %d | %s", len, sprint_hex_inrow_ex(data, len, 8)); } - + return len; } static int smart_responseEx(uint8_t *data, bool silent) { - - int datalen = smart_wait(data, silent); + + int datalen = smart_wait(data, silent); bool needGetData = false; - + if (datalen < 2 ) { goto out; } @@ -359,9 +359,9 @@ static int smart_responseEx(uint8_t *data, bool silent) { if (needGetData) { int len = data[datalen - 1]; - if (!silent) PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len); + if (!silent) PrintAndLogEx(INFO, "Requesting 0x%02X bytes response", len); uint8_t getstatus[] = {0x00, ISO7816_GET_RESPONSE, 0x00, 0x00, len}; - UsbCommand cStatus = {CMD_SMART_RAW, {SC_RAW, sizeof(getstatus), 0}}; + UsbCommand cStatus = {CMD_SMART_RAW, {SC_RAW, sizeof(getstatus), 0}}; memcpy(cStatus.d.asBytes, getstatus, sizeof(getstatus) ); clearCommandBuffer(); SendCommand(&cStatus); @@ -371,14 +371,14 @@ static int smart_responseEx(uint8_t *data, bool silent) { if (datalen < 2 ) { goto out; } - + // data wo ACK - if (datalen != len + 2) { + if (datalen != len + 2) { // data with ACK if (datalen == len + 2 + 1) { // 2 - response, 1 - ACK if (data[0] != ISO7816_GET_RESPONSE) { if (!silent) { - PrintAndLogEx(ERR, "GetResponse ACK error. len 0x%x | data[0] %02X", len, data[0]); + PrintAndLogEx(ERR, "GetResponse ACK error. len 0x%x | data[0] %02X", len, data[0]); } datalen = 0; goto out; @@ -389,12 +389,12 @@ static int smart_responseEx(uint8_t *data, bool silent) { } else { // wrong length if (!silent) { - PrintAndLogEx(WARNING, "GetResponse wrong length. Must be 0x%02X got 0x%02X", len, datalen - 3); + PrintAndLogEx(WARNING, "GetResponse wrong length. Must be 0x%02X got 0x%02X", len, datalen - 3); } } } } - + out: return datalen; } @@ -407,15 +407,15 @@ int CmdSmartRaw(const char *Cmd) { int hexlen = 0; bool active = false; - bool active_select = false; - bool useT0 = false; + bool active_select = false; + bool useT0 = false; uint8_t cmdp = 0; bool errors = false, reply = true, decodeTLV = false, breakloop = false; uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': return usage_sm_raw(); + case 'h': return usage_sm_raw(); case 'r': reply = false; cmdp++; @@ -431,11 +431,11 @@ int CmdSmartRaw(const char *Cmd) { case 't': decodeTLV = true; cmdp++; - break; + break; case '0': useT0 = true; cmdp++; - break; + break; case 'd': { switch (param_gethex_to_eol(Cmd, cmdp+1, data, sizeof(data), &hexlen)) { case 1: @@ -461,14 +461,14 @@ int CmdSmartRaw(const char *Cmd) { if ( breakloop ) break; } - + //Validations - if (errors || cmdp == 0 ) return usage_sm_raw(); + if (errors || cmdp == 0 ) return usage_sm_raw(); // arg0 = RFU flags // arg1 = length - UsbCommand c = {CMD_SMART_RAW, {0, hexlen, 0}}; - + UsbCommand c = {CMD_SMART_RAW, {0, hexlen, 0}}; + if (active || active_select) { c.arg[0] |= SC_CONNECT; if (active_select) @@ -480,28 +480,28 @@ int CmdSmartRaw(const char *Cmd) { c.arg[0] |= SC_RAW_T0; else c.arg[0] |= SC_RAW; - } - + } + memcpy(c.d.asBytes, data, hexlen ); clearCommandBuffer(); - SendCommand(&c); - + SendCommand(&c); + // reading response from smart card if ( reply ) { uint8_t* buf = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t)); if ( !buf ) - return 1; - + return 1; + int len = smart_response(buf); if ( len < 0 ) { free(buf); return 2; } - + if ( buf[0] == 0x6C ) { data[4] = buf[1]; - + memcpy(c.d.asBytes, data, sizeof(data) ); clearCommandBuffer(); SendCommand(&c); @@ -520,54 +520,54 @@ int CmdSmartRaw(const char *Cmd) { int ExchangeAPDUSC(uint8_t *datain, int datainlen, bool activateCard, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { *dataoutlen = 0; - + if (activateCard) smart_select(false, NULL); PrintAndLogEx(DEBUG, "APDU SC"); - UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, datainlen, 0}}; + UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, datainlen, 0}}; if (activateCard) { c.arg[0] |= SC_SELECT | SC_CONNECT; } memcpy(c.d.asBytes, datain, datainlen); clearCommandBuffer(); - SendCommand(&c); - + SendCommand(&c); + int len = smart_responseEx(dataout, true); - + if ( len < 0 ) { return 1; } - + // retry if (len > 1 && dataout[len - 2] == 0x6c && datainlen > 4) { - UsbCommand c2 = {CMD_SMART_RAW, {SC_RAW_T0, datainlen, 0}}; + UsbCommand c2 = {CMD_SMART_RAW, {SC_RAW_T0, datainlen, 0}}; memcpy(c2.d.asBytes, datain, 5); - + // transfer length via T=0 c2.d.asBytes[4] = dataout[len - 1]; - + clearCommandBuffer(); - SendCommand(&c2); - + SendCommand(&c2); + len = smart_responseEx(dataout, true); - } - + } + *dataoutlen = len; return 0; -} +} int CmdSmartUpgrade(const char *Cmd) { PrintAndLogEx(WARNING, "WARNING - Smartcard socket firmware upgrade."); PrintAndLogEx(WARNING, "A dangerous command, do wrong and you will brick the smart card socket"); - + FILE *f; char filename[FILE_PATH_SIZE] = {0}; uint8_t cmdp = 0; bool errors = false; - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'f': @@ -576,8 +576,8 @@ int CmdSmartUpgrade(const char *Cmd) { PrintAndLogEx(FAILED, "Filename too long"); errors = true; break; - } - cmdp += 2; + } + cmdp += 2; break; case 'h': return usage_sm_upgrade(); @@ -587,17 +587,17 @@ int CmdSmartUpgrade(const char *Cmd) { break; } } - + //Validations - if (errors || cmdp == 0 ) return usage_sm_upgrade(); - + if (errors || cmdp == 0 ) return usage_sm_upgrade(); + // load file f = fopen(filename, "rb"); if ( !f ){ PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); return 1; - } - + } + // get filesize in order to malloc memory fseek(f, 0, SEEK_END); long fsize = ftell(f); @@ -608,18 +608,18 @@ int CmdSmartUpgrade(const char *Cmd) { fclose(f); return 1; } - + uint8_t *dump = calloc(fsize, sizeof(uint8_t)); if (!dump) { PrintAndLogDevice(WARNING, "error, cannot allocate memory "); fclose(f); return 1; } - + size_t bytes_read = fread(dump, 1, fsize, f); if (f) fclose(f); - + PrintAndLogEx(SUCCESS, "Smartcard socket firmware uploading to PM3"); //Send to device uint32_t index = 0; @@ -627,20 +627,20 @@ int CmdSmartUpgrade(const char *Cmd) { uint32_t bytes_remaining = bytes_read; while (bytes_remaining > 0){ - uint32_t bytes_in_packet = MIN(USB_CMD_DATA_SIZE, bytes_remaining); + uint32_t bytes_in_packet = MIN(USB_CMD_DATA_SIZE, bytes_remaining); UsbCommand c = {CMD_SMART_UPLOAD, {index + bytes_sent, bytes_in_packet, 0}}; // Fill usb bytes with 0xFF memset(c.d.asBytes, 0xFF, USB_CMD_DATA_SIZE); memcpy(c.d.asBytes, dump + bytes_sent, bytes_in_packet); clearCommandBuffer(); - SendCommand(&c); + SendCommand(&c); if ( !WaitForResponseTimeout(CMD_ACK, NULL, 2000) ) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); free(dump); return 1; } - + bytes_remaining -= bytes_in_packet; bytes_sent += bytes_in_packet; printf("."); fflush(stdout); @@ -648,9 +648,9 @@ int CmdSmartUpgrade(const char *Cmd) { free(dump); printf("\n"); PrintAndLogEx(SUCCESS, "Smartcard socket firmware updating, don\'t turn off your PM3!"); - + // trigger the firmware upgrade - UsbCommand c = {CMD_SMART_UPGRADE, {bytes_read, 0, 0}}; + UsbCommand c = {CMD_SMART_UPGRADE, {bytes_read, 0, 0}}; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; @@ -668,13 +668,13 @@ int CmdSmartUpgrade(const char *Cmd) { int CmdSmartInfo(const char *Cmd){ uint8_t cmdp = 0; bool errors = false, silent = false; - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_sm_info(); - case 's': + case 's': silent = true; - break; + break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; @@ -682,10 +682,10 @@ int CmdSmartInfo(const char *Cmd){ } cmdp++; } - + //Validations if (errors ) return usage_sm_info(); - + UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -694,16 +694,16 @@ int CmdSmartInfo(const char *Cmd){ if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); return 1; } - + uint8_t isok = resp.arg[0] & 0xFF; if (!isok) { if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); return 1; - } - + } + smart_card_atr_t card; memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t)); - + // print header PrintAndLogEx(INFO, "--- Smartcard Information ---------"); PrintAndLogEx(INFO, "-------------------------------------------------------------"); @@ -714,7 +714,7 @@ int CmdSmartInfo(const char *Cmd){ PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "ATR"); PrintATR(card.atr, card.atr_len); - + // print D/F (brom byte TA1 or defaults) PrintAndLogEx(NORMAL, ""); PrintAndLogEx(INFO, "D/F (TA1)"); @@ -723,11 +723,11 @@ int CmdSmartInfo(const char *Cmd){ float F = GetATRF(card.atr, card.atr_len); if (GetATRTA1(card.atr, card.atr_len) == 0x11) PrintAndLogEx(INFO, "Using default values..."); - + PrintAndLogEx(NORMAL, "\t- Di %d", Di); PrintAndLogEx(NORMAL, "\t- Fi %d", Fi); PrintAndLogEx(NORMAL, "\t- F %.1f MHz", F); - + if (Di && Fi) { PrintAndLogEx(NORMAL, "\t- Cycles/ETU %d", Fi/Di); PrintAndLogEx(NORMAL, "\t- %.1f bits/sec at 4MHz", (float)4000000 / (Fi/Di)); @@ -742,24 +742,24 @@ int CmdSmartInfo(const char *Cmd){ int CmdSmartReader(const char *Cmd){ uint8_t cmdp = 0; bool errors = false, silent = false; - + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_sm_reader(); - case 's': + case 's': silent = true; - break; + break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; break; } - cmdp++; + cmdp++; } - + //Validations if (errors ) return usage_sm_reader(); - + UsbCommand c = {CMD_SMART_ATR, {0, 0, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -768,16 +768,16 @@ int CmdSmartReader(const char *Cmd){ if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); return 1; } - + uint8_t isok = resp.arg[0] & 0xFF; if (!isok) { if (!silent) PrintAndLogEx(WARNING, "smart card select failed"); return 1; - } + } smart_card_atr_t card; memcpy(&card, (smart_card_atr_t *)resp.d.asBytes, sizeof(smart_card_atr_t)); - - PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len)); + + PrintAndLogEx(INFO, "ISO7816-3 ATR : %s", sprint_hex(card.atr, card.atr_len)); return 0; } @@ -788,23 +788,23 @@ int CmdSmartSetClock(const char *Cmd){ while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_sm_setclock(); - case 'c': + case 'c': clock = param_get8ex(Cmd, cmdp+1, 2, 10); if ( clock > 2) errors = true; - + cmdp += 2; - break; + break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; break; } } - + //Validations if (errors || cmdp == 0) return usage_sm_setclock(); - + UsbCommand c = {CMD_SMART_SETCLOCK, {clock, 0, 0}}; clearCommandBuffer(); SendCommand(&c); @@ -813,15 +813,15 @@ int CmdSmartSetClock(const char *Cmd){ PrintAndLogEx(WARNING, "smart card select failed"); return 1; } - + uint8_t isok = resp.arg[0] & 0xFF; if (!isok) { PrintAndLogEx(WARNING, "smart card set clock failed"); return 1; } - + switch (clock) { - case 0: + case 0: PrintAndLogEx(SUCCESS, "Clock changed to 16mhz giving 10800 baudrate"); break; case 1: @@ -844,36 +844,36 @@ int CmdSmartList(const char *Cmd) { static void smart_brute_prim(){ uint8_t* buf = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t)); - if ( !buf ) + if ( !buf ) return; - + int len = 0; - uint8_t get_card_data[] = { + uint8_t get_card_data[] = { 0x80, 0xCA, 0x9F, 0x13, 0x00, 0x80, 0xCA, 0x9F, 0x17, 0x00, 0x80, 0xCA, 0x9F, 0x36, 0x00, 0x80, 0xCA, 0x9F, 0x4f, 0x00 }; - - UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, 5, 0}}; - + + UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, 5, 0}}; + PrintAndLogEx(INFO, "Reading primitives"); for (int i = 0; i < sizeof(get_card_data); i += 5) { - + memcpy(c.d.asBytes, get_card_data+i, 5 ); clearCommandBuffer(); SendCommand(&c); - + len = smart_responseEx(buf, true); if ( len > 2 ) { - + //if ( decodeTLV ) { //if (!TLVPrintFromBuffer(buf, len-2)) { PrintAndLogEx(SUCCESS, "\tHEX %d |: %s", len, sprint_hex(buf, len)); //} - //} + //} } len = 0; } @@ -883,20 +883,20 @@ static void smart_brute_prim(){ static int smart_brute_sfi(bool decodeTLV){ uint8_t* buf = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t)); - if ( !buf ) + if ( !buf ) return 1; - + int len = 0; // READ RECORD uint8_t READ_RECORD[] = {0x00, 0xB2, 0x00, 0x00, 0x00}; - UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, sizeof(READ_RECORD), 0}}; + UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, sizeof(READ_RECORD), 0}}; PrintAndLogEx(INFO, "Start SFI brute forcing"); - + for (uint8_t sfi=1; sfi <= 31; sfi++) { printf("."); fflush(stdout); - + for (uint16_t rec=1; rec <= 255; rec++) { if (ukbhit()) { @@ -904,40 +904,40 @@ static int smart_brute_sfi(bool decodeTLV){ PrintAndLogEx(NORMAL, "\naborted via keyboard!\n"); free(buf); return 1; - } - + } + READ_RECORD[2] = rec; READ_RECORD[3] = (sfi << 3) | 4; memcpy(c.d.asBytes, READ_RECORD, sizeof(READ_RECORD) ); clearCommandBuffer(); SendCommand(&c); - + len = smart_responseEx(buf, true); - + if ( buf[0] == 0x6C ) { READ_RECORD[4] = buf[1]; - + memcpy(c.d.asBytes, READ_RECORD, sizeof(READ_RECORD) ); clearCommandBuffer(); SendCommand(&c); len = smart_responseEx(buf, true); - - READ_RECORD[4] = 0; + + READ_RECORD[4] = 0; } - + if ( len > 4 ) { - + PrintAndLogEx(SUCCESS, "\n\t file %02d, record %02d found", sfi, rec); - + uint8_t modifier = (buf[0] == 0xC0) ? 1 : 0; - + if ( decodeTLV ) { if (!TLVPrintFromBuffer(buf + modifier, len-2-modifier)) { PrintAndLogEx(SUCCESS, "\tHEX: %s", sprint_hex(buf, len)); } - } - } + } + } memset(buf, 0x00, USB_CMD_DATA_SIZE); } } @@ -948,77 +948,77 @@ static int smart_brute_sfi(bool decodeTLV){ static void smart_brute_options(bool decodeTLV) { uint8_t* buf = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t)); - if ( !buf ) + if ( !buf ) return; - + uint8_t GET_PROCESSING_OPTIONS[] = {0x80, 0xA8, 0x00, 0x00, 0x02, 0x83, 0x00, 0x00}; - + // Get processing options command - UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, sizeof(GET_PROCESSING_OPTIONS), 0}}; - memcpy(c.d.asBytes, GET_PROCESSING_OPTIONS, sizeof(GET_PROCESSING_OPTIONS) ); + UsbCommand c = {CMD_SMART_RAW, {SC_RAW_T0, sizeof(GET_PROCESSING_OPTIONS), 0}}; + memcpy(c.d.asBytes, GET_PROCESSING_OPTIONS, sizeof(GET_PROCESSING_OPTIONS) ); clearCommandBuffer(); SendCommand(&c); - + int len = smart_responseEx(buf, true); if ( len > 4 ) { - PrintAndLogEx(SUCCESS, "Got processing options"); + PrintAndLogEx(SUCCESS, "Got processing options"); if ( decodeTLV ) { TLVPrintFromBuffer(buf, len-2); } } else { PrintAndLogEx(FAILED, "Getting processing options failed"); } - + free(buf); } int CmdSmartBruteforceSFI(const char *Cmd) { uint8_t cmdp = 0; - bool errors = false, decodeTLV = false; //, useT0 = false; - + bool errors = false, decodeTLV = false; //, useT0 = false; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': return usage_sm_brute(); + case 'h': return usage_sm_brute(); case 't': decodeTLV = true; cmdp++; break; -/* +/* case '0': useT0 = true; cmdp++; break; -*/ +*/ default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; break; } } - - //Validations - if (errors) return usage_sm_brute(); - const char *SELECT = "00a40400%02x%s"; - + //Validations + if (errors) return usage_sm_brute(); + + const char *SELECT = "00a40400%02x%s"; + // uint8_t GENERATE_AC[] = {0x80, 0xAE}; // uint8_t GET_CHALLENGE[] = {0x00, 0x84, 0x00}; // uint8_t GET_DATA[] = {0x80, 0xCA, 0x00, 0x00, 0x00}; // uint8_t SELECT[] = {0x00, 0xA4, 0x04, 0x00}; // uint8_t UNBLOCK_PIN[] = {0x84, 0x24, 0x00, 0x00, 0x00}; // uint8_t VERIFY[] = {0x00, 0x20, 0x00, 0x80}; - + // Select AID command - UsbCommand cAid = {CMD_SMART_RAW, {SC_RAW_T0, 0, 0}}; - + UsbCommand cAid = {CMD_SMART_RAW, {SC_RAW_T0, 0, 0}}; + PrintAndLogEx(INFO, "Importing AID list"); json_t *root = NULL; smart_loadjson("aidlist", "json", &root); uint8_t* buf = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t)); if ( !buf ) - return 1; + return 1; PrintAndLogEx(INFO, "Selecting card"); if ( !smart_select(false, NULL) ) { @@ -1027,14 +1027,14 @@ int CmdSmartBruteforceSFI(const char *Cmd) { } char* caid = NULL; - + for (int i = 0; i < json_array_size(root); i++) { - + printf("+"); fflush(stdout); if (caid) free(caid); - + json_t *data, *jaid; data = json_array_get(root, i); @@ -1043,47 +1043,47 @@ int CmdSmartBruteforceSFI(const char *Cmd) { json_decref(root); return 1; } - + jaid = json_object_get(data, "AID"); if (!json_is_string(jaid)) { PrintAndLogEx(ERR, "AID data [%d] is not a string", i + 1); json_decref(root); return 1; } - + const char* aid = json_string_value(jaid); - if ( !aid ) + if ( !aid ) continue; size_t aidlen = strlen(aid); caid = calloc( 8+2+aidlen+1, sizeof(uint8_t)); - snprintf(caid, 8+2+aidlen+1, SELECT, aidlen >> 1, aid); - + snprintf(caid, 8+2+aidlen+1, SELECT, aidlen >> 1, aid); + int hexlen = 0; int res = param_gethex_to_eol(caid, 0, cAid.d.asBytes, sizeof(cAid.d.asBytes), &hexlen); - if ( res ) + if ( res ) continue; - + cAid.arg[1] = hexlen; clearCommandBuffer(); - SendCommand(&cAid); - - int len = smart_responseEx(buf, true); + SendCommand(&cAid); + + int len = smart_responseEx(buf, true); if ( len < 3 ) continue; - + json_t *jvendor, *jname; jvendor = json_object_get(data, "Vendor"); if (!json_is_string(jvendor)) { PrintAndLogEx(ERR, "Vendor data [%d] is not a string", i + 1); continue; } - + const char* vendor = json_string_value(jvendor); if ( !vendor ) continue; - + jname = json_object_get(data, "Name"); if (!json_is_string(jname)) { PrintAndLogEx(ERR, "Name data [%d] is not a string", i + 1); @@ -1104,19 +1104,19 @@ int CmdSmartBruteforceSFI(const char *Cmd) { PrintAndLogEx(SUCCESS, "\nSFI brute force done\n"); } - if (caid) + if (caid) free(caid); - + free(buf); json_decref(root); - + PrintAndLogEx(SUCCESS, "\nSearch completed."); return 0; } static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"list", CmdSmartList, 0, "List ISO 7816 history"}, + {"list", CmdSmartList, 0, "List ISO 7816 history"}, {"info", CmdSmartInfo, 1, "Tag information"}, {"reader", CmdSmartReader, 1, "Act like an IS07816 reader"}, {"raw", CmdSmartRaw, 1, "Send raw hex data to tag"}, diff --git a/client/cmdtrace.c b/client/cmdtrace.c index cf55970b0..a93195635 100644 --- a/client/cmdtrace.c +++ b/client/cmdtrace.c @@ -14,7 +14,7 @@ static int CmdHelp(const char *Cmd); // trace pointer static uint8_t *trace; long traceLen = 0; - + int usage_trace_list(){ PrintAndLogEx(NORMAL, "List protocol data in trace buffer."); PrintAndLogEx(NORMAL, "Usage: trace list [f][c| <0|1>"); @@ -30,7 +30,7 @@ int usage_trace_list(){ PrintAndLogEx(NORMAL, " des - interpret data as DESFire communications"); #ifdef WITH_EMV PrintAndLogEx(NORMAL, " emv - interpret data as EMV / communications"); -#endif +#endif PrintAndLogEx(NORMAL, " iclass - interpret data as iclass communications"); PrintAndLogEx(NORMAL, " topaz - interpret data as topaz communications"); PrintAndLogEx(NORMAL, " 7816 - interpret data as iso7816-4 communications"); @@ -62,7 +62,7 @@ bool is_last_record(uint16_t tracepos, uint8_t *trace, uint16_t traceLen) { } bool next_record_is_response(uint16_t tracepos, uint8_t *trace) { - uint16_t next_records_datalen = *((uint16_t *)(trace + tracepos + sizeof(uint32_t) + sizeof(uint16_t))); + uint16_t next_records_datalen = *((uint16_t *)(trace + tracepos + sizeof(uint32_t) + sizeof(uint16_t))); return(next_records_datalen & 0x8000); } @@ -100,7 +100,7 @@ bool merge_topaz_reader_frames(uint32_t timestamp, uint32_t *duration, uint16_t } *duration = last_timestamp - timestamp; - + return true; } @@ -116,7 +116,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui uint8_t mfData[32] = {0}; size_t mfDataLen = 0; - + first_timestamp = *((uint32_t *)(trace)); timestamp = *((uint32_t *)(trace + tracepos)); tracepos += 4; @@ -150,7 +150,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui frame = topaz_reader_command; } } - + //Check the CRC status uint8_t crcStatus = 2; @@ -165,8 +165,8 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui crcStatus = iso14443B_CRC_check(frame, data_len); break; case PROTO_MIFARE: - crcStatus = mifare_CRC_check(isResponse, frame, data_len); - break; + crcStatus = mifare_CRC_check(isResponse, frame, data_len); + break; case ISO_14443A: case MFDES: crcStatus = iso14443A_CRC_check(isResponse, frame, data_len); @@ -175,7 +175,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui crcStatus = iso15693_CRC_check(frame, data_len); break; case ISO_7816_4: - default: + default: break; } } @@ -190,11 +190,11 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui uint8_t parityBits = parityBytes[j >> 3]; if (protocol != LEGIC && - protocol != ISO_14443B && + protocol != ISO_14443B && protocol != ISO_7816_4 && (isResponse || protocol == ISO_14443A) && (oddparity8(frame[j]) != ((parityBits >> (7-(j&0x0007))) & 0x01))) { - + snprintf(line[j/18]+(( j % 18) * 4),110, "%02x! ", frame[j]); } else { snprintf(line[j/18]+(( j % 18) * 4),110, "%02x ", frame[j]); @@ -228,7 +228,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui if ( protocol == PROTO_MIFARE ) annotateMifare(explanation, sizeof(explanation), frame, data_len, parityBytes, parity_len, isResponse); - + if (!isResponse) { switch(protocol) { case ICLASS: annotateIclass(explanation,sizeof(explanation),frame,data_len); break; @@ -274,7 +274,7 @@ uint16_t printTraceLine(uint16_t tracepos, uint16_t traceLen, uint8_t *trace, ui }; if (is_last_record(tracepos, trace, traceLen)) return traceLen; - + if (showWaitCycles && !isResponse && next_record_is_response(tracepos, trace)) { uint32_t next_timestamp = *((uint32_t *)(trace + tracepos)); PrintAndLogEx(NORMAL, " %10u | %10u | %s |fdt (Frame Delay Time): %d", @@ -298,7 +298,7 @@ void printFelica(uint16_t traceLen, uint8_t *trace) { if (tracepos + 3 >= traceLen) break; - + uint16_t gap = *((uint16_t *)(trace + tracepos)); uint8_t crc_ok = trace[tracepos+2]; tracepos += 3; @@ -377,7 +377,7 @@ void printFelica(uint16_t traceLen, uint8_t *trace) { case FELICA_UPDATE_RNDID_ACK: snprintf(expbuf,49,"Update IDr Resp");break; default: snprintf(expbuf,49,"Unknown");break; } - + int num_lines = MIN((len )/16 + 1, 16); for (int j = 0; j < num_lines ; j++) { if (j == 0) { @@ -412,7 +412,7 @@ static int SanityOfflineCheck( bool useTraceBuffer ){ int CmdTraceList(const char *Cmd) { clearCommandBuffer(); - + bool showWaitCycles = false; bool markCRCBytes = false; bool isOnline = true; @@ -426,10 +426,10 @@ int CmdTraceList(const char *Cmd) { char cmdp = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - + int slen = param_getstr(Cmd, cmdp, type, sizeof(type) ); if ( slen == 1) { - + switch ( tolower(param_getchar(Cmd, cmdp))) { case 'h': return usage_trace_list(); @@ -447,24 +447,24 @@ int CmdTraceList(const char *Cmd) { break; case '1': isOnline = false; - cmdp++; + cmdp++; break; default: PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); errors = true; break; } - - } else { - + + } else { + str_lower(type); - + // validate type of output if (strcmp(type, "iclass") == 0) protocol = ICLASS; else if(strcmp(type, "14a") == 0) protocol = ISO_14443A; else if(strcmp(type, "14b") == 0) protocol = ISO_14443B; else if(strcmp(type, "topaz") == 0) protocol = TOPAZ; - else if(strcmp(type, "7816") == 0) protocol = ISO_7816_4; + else if(strcmp(type, "7816") == 0) protocol = ISO_7816_4; else if(strcmp(type, "des") == 0) protocol = MFDES; else if(strcmp(type, "legic") == 0) protocol = LEGIC; else if(strcmp(type, "15") == 0) protocol = ISO_15693; @@ -472,22 +472,22 @@ int CmdTraceList(const char *Cmd) { else if(strcmp(type, "mf") == 0) protocol = PROTO_MIFARE; else if(strcmp(type, "raw") == 0) protocol = -1;//No crc, no annotations else errors = true; - + cmdp++; - } + } } - + //if (!SanityOfflineCheck(isOnline)) return 1; - + //Validations if (errors) return usage_trace_list(); - + uint16_t tracepos = 0; // reserv some space. if (!trace) trace = calloc(USB_CMD_DATA_SIZE, sizeof(uint8_t)); - + if ( isOnline ) { // Query for the size of the trace, downloading USB_CMD_DATA_SIZE UsbCommand response; @@ -495,7 +495,7 @@ int CmdTraceList(const char *Cmd) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); return 1; } - + traceLen = response.arg[2]; if (traceLen > USB_CMD_DATA_SIZE) { uint8_t *p = realloc(trace, traceLen); @@ -510,14 +510,14 @@ int CmdTraceList(const char *Cmd) { free(trace); return 3; } - } + } } PrintAndLogEx(SUCCESS, "Recorded Activity (TraceLen = %d bytes)", traceLen); PrintAndLogEx(INFO, ""); if (protocol == FELICA) { printFelica(traceLen, trace); - } else { + } else { PrintAndLogEx(NORMAL, "Start = Start of Start Bit, End = End of last modulation. Src = Source of Transfer"); if ( protocol == ISO_14443A || protocol == PROTO_MIFARE) PrintAndLogEx(NORMAL, "iso14443a - All times are in carrier periods (1/13.56Mhz)"); @@ -530,7 +530,7 @@ int CmdTraceList(const char *Cmd) { PrintAndLogEx(NORMAL, "ISO15693 - Timings are not as accurate"); if ( protocol == ISO_7816_4 ) PrintAndLogEx(NORMAL, "ISO7816-4 / Smartcard - Timings N/A yet"); - + PrintAndLogEx(NORMAL, ""); PrintAndLogEx(NORMAL, " Start | End | Src | Data (! denotes parity error) | CRC | Annotation"); PrintAndLogEx(NORMAL, "------------+------------+-----+-------------------------------------------------------------------------+-----+--------------------"); @@ -544,24 +544,24 @@ int CmdTraceList(const char *Cmd) { } int CmdTraceLoad(const char *Cmd) { - + FILE *f = NULL; char filename[FILE_PATH_SIZE]; char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_trace_load(); - - param_getstr(Cmd, 0, filename, sizeof(filename)); - - if ((f = fopen(filename, "rb")) == NULL) { + if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_trace_load(); + + param_getstr(Cmd, 0, filename, sizeof(filename)); + + if ((f = fopen(filename, "rb")) == NULL) { PrintAndLogEx(FAILED, "Could not open file %s", filename); return 0; } - + // get filesize in order to malloc memory fseek(f, 0, SEEK_END); long fsize = ftell(f); - fseek(f, 0, SEEK_SET); - + fseek(f, 0, SEEK_SET); + if (fsize < 0) { PrintAndLogEx(FAILED, "error, when getting filesize"); fclose(f); @@ -571,7 +571,7 @@ int CmdTraceLoad(const char *Cmd) { PrintAndLogEx(FAILED, "error, file is too small"); fclose(f); return 4; - } + } if ( trace ) free(trace); @@ -579,36 +579,36 @@ int CmdTraceLoad(const char *Cmd) { trace = calloc(fsize, sizeof(uint8_t)); if (!trace) { PrintAndLogEx(FAILED, "Cannot allocate memory for trace"); - fclose(f); + fclose(f); return 2; } - + size_t bytes_read = fread(trace, 1, fsize, f); traceLen = bytes_read; fclose(f); - PrintAndLogEx(SUCCESS, "Recorded Activity (TraceLen = %d bytes) loaded from file %s", traceLen, filename); + PrintAndLogEx(SUCCESS, "Recorded Activity (TraceLen = %d bytes) loaded from file %s", traceLen, filename); return 0; } int CmdTraceSave(const char *Cmd) { - + if (traceLen == 0 ) { PrintAndLogEx(WARNING, "trace is empty, exiting..."); return 0; } - + char filename[FILE_PATH_SIZE]; char cmdp = param_getchar(Cmd, 0); if (strlen(Cmd) < 1 || cmdp == 'h' || cmdp == 'H') return usage_trace_save(); - - param_getstr(Cmd, 0, filename, sizeof(filename)); + + param_getstr(Cmd, 0, filename, sizeof(filename)); saveFile(filename, "bin", trace, traceLen); return 0; } static command_t CommandTable[] = { {"help", CmdHelp, 1, "This help"}, - {"list", CmdTraceList, 1, "List protocol data in trace buffer"}, + {"list", CmdTraceList, 1, "List protocol data in trace buffer"}, {"load", CmdTraceLoad, 1, "Load trace from file"}, {"save", CmdTraceSave, 1, "Save trace buffer to file"}, {NULL, NULL, 0, NULL} @@ -617,7 +617,7 @@ static command_t CommandTable[] = { int CmdTrace(const char *Cmd) { clearCommandBuffer(); CmdsParse(CommandTable, Cmd); - return 0; + return 0; } int CmdHelp(const char *Cmd) { diff --git a/client/cmdtrace.h b/client/cmdtrace.h index c6ba0cc38..ca56fd3cc 100644 --- a/client/cmdtrace.h +++ b/client/cmdtrace.h @@ -17,7 +17,7 @@ #include #include #include "proxmark3.h" -#include "protocols.h" +#include "protocols.h" #include "parity.h" // oddparity #include "cmdhflist.h" // annotations #include "iso15693tools.h" // ISO15693 crc @@ -34,7 +34,7 @@ extern int CmdTraceLoad(const char *Cmd); extern int CmdTraceSave(const char *Cmd); // usages helptext -extern int usage_trace_list(void); +extern int usage_trace_list(void); extern int usage_trace_load(void); extern int usage_trace_save(void); #endif diff --git a/client/comms.c b/client/comms.c index f08c5f413..7e9441a95 100644 --- a/client/comms.c +++ b/client/comms.c @@ -57,7 +57,7 @@ void SendCommand(UsbCommand *c) { #ifdef COMMS_DEBUG PrintAndLogEx(NORMAL, "Sending %d bytes | cmd %04x\n", sizeof(UsbCommand), c->cmd); #endif - + if (offline) { PrintAndLogEx(NORMAL, "Sending bytes to proxmark failed - offline"); return; @@ -65,22 +65,22 @@ void SendCommand(UsbCommand *c) { pthread_mutex_lock(&txBufferMutex); /** - This causes hangups at times, when the pm3 unit is unresponsive or disconnected. The main console thread is alive, + This causes hangups at times, when the pm3 unit is unresponsive or disconnected. The main console thread is alive, but comm thread just spins here. Not good.../holiman **/ while (txBuffer_pending) { - // wait for communication thread to complete sending a previous commmand - pthread_cond_wait(&txBufferSig, &txBufferMutex); + // wait for communication thread to complete sending a previous commmand + pthread_cond_wait(&txBufferSig, &txBufferMutex); } txBuffer = *c; txBuffer_pending = true; - - // tell communication thread that a new command can be send + + // tell communication thread that a new command can be send pthread_cond_signal(&txBufferSig); pthread_mutex_unlock(&txBufferMutex); - + //__atomic_test_and_set(&txcmd_pending, __ATOMIC_SEQ_CST); } @@ -101,7 +101,7 @@ void clearCommandBuffer() { * @param UC */ static void storeCommand(UsbCommand *command) { - + pthread_mutex_lock(&rxBufferMutex); if ( ( cmd_head+1) % CMD_BUFFER_SIZE == cmd_tail) { //If these two are equal, we're about to overwrite in the @@ -114,7 +114,7 @@ static void storeCommand(UsbCommand *command) { memcpy(destination, command, sizeof(UsbCommand)); //increment head and wrap - cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; + cmd_head = (cmd_head +1) % CMD_BUFFER_SIZE; pthread_mutex_unlock(&rxBufferMutex); } /** @@ -129,7 +129,7 @@ static int getCommand(UsbCommand* response) { pthread_mutex_unlock(&rxBufferMutex); return 0; } - + //Pick out the next unread command UsbCommand* last_unread = &rxBuffer[cmd_tail]; memcpy(response, last_unread, sizeof(UsbCommand)); @@ -146,17 +146,17 @@ static int getCommand(UsbCommand* response) { // that we weren't necessarily expecting, for example a debug print. //----------------------------------------------------------------------------- static void UsbCommandReceived(UsbCommand* c) { - + switch(c->cmd) { // First check if we are handling a debug message case CMD_DEBUG_PRINT_STRING: { char s[USB_CMD_DATA_SIZE+1]; - memset(s, 0x00, sizeof(s)); + memset(s, 0x00, sizeof(s)); size_t len = MIN(c->arg[0], USB_CMD_DATA_SIZE); - memcpy(s, c->d.asBytes, len); + memcpy(s, c->d.asBytes, len); uint64_t flag = c->arg[1]; - + switch (flag) { case FLAG_RAWPRINT: printf("%s", s); @@ -183,7 +183,7 @@ static void UsbCommandReceived(UsbCommand* c) { } // iceman: hw status - down the path on device, runs printusbspeed which starts sending a lot of // CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K packages which is not dealt with. I wonder if simply ignoring them will - // work. lets try it. + // work. lets try it. default: { storeCommand(c); break; @@ -192,14 +192,14 @@ static void UsbCommandReceived(UsbCommand* c) { } /* -bool hookUpPM3() { +bool hookUpPM3() { bool ret = false; sp = uart_open( comport ); if (sp == INVALID_SERIAL_PORT) { PrintAndLogEx(WARNING, "Reconnect failed, retrying... (reason: invalid serial port)\n"); sp = NULL; - serial_port_name = NULL; + serial_port_name = NULL; ret = false; offline = 1; } else if (sp == CLAIMED_SERIAL_PORT) { @@ -208,7 +208,7 @@ bool hookUpPM3() { serial_port_name = NULL; ret = false; offline = 1; - } else { + } else { PrintAndLogEx(SUCCESS, "Proxmark reconnected\n"); serial_port_name = ; ret = true; @@ -221,44 +221,44 @@ bool hookUpPM3() { void #ifdef __has_attribute #if __has_attribute(force_align_arg_pointer) -__attribute__((force_align_arg_pointer)) +__attribute__((force_align_arg_pointer)) #endif #endif *uart_communication(void *targ) { communication_arg_t *conn = (communication_arg_t*)targ; - size_t rxlen, totallen = 0; + size_t rxlen, totallen = 0; UsbCommand rx; UsbCommand *prx = ℞ - + //int counter_to_offline = 0; #if defined(__MACH__) && defined(__APPLE__) disableAppNap("Proxmark3 polling UART"); #endif - + while (conn->run) { rxlen = 0; bool ACK_received = false; - + if (uart_receive(sp, (uint8_t *)prx, sizeof(UsbCommand) - (prx - &rx), &rxlen) && rxlen) { prx += rxlen; totallen += rxlen; - + if ( totallen < sizeof(UsbCommand)) { - + // iceman: this looping is no working as expected at all. The reassemble of package is nonfunctional. // solved so far with increasing the timeouts of the serial port configuration. PrintAndLogEx(NORMAL, "Foo %d | %d (loop)", prx - &rx, rxlen); continue; } - + totallen = 0; UsbCommandReceived(&rx); if (rx.cmd == CMD_ACK) { ACK_received = true; } } - + prx = ℞ pthread_mutex_lock(&txBufferMutex); @@ -274,11 +274,11 @@ __attribute__((force_align_arg_pointer)) if (txBuffer_pending) { if (!uart_send(sp, (uint8_t*) &txBuffer, sizeof(UsbCommand))) { - //counter_to_offline++; + //counter_to_offline++; PrintAndLogEx(WARNING, "sending bytes to proxmark failed"); } txBuffer_pending = false; - + // tell main thread that txBuffer is empty pthread_cond_signal(&txBufferSig); } @@ -293,13 +293,13 @@ __attribute__((force_align_arg_pointer)) #if defined(__MACH__) && defined(__APPLE__) enableAppNap(); #endif - + pthread_exit(NULL); return NULL; } bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode) { - + char *portname = (char *)port; if (!wait_for_port) { sp = uart_open(portname); @@ -331,7 +331,7 @@ bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode) serial_port_name = portname; conn.run = true; conn.block_after_ACK = flash_mode; - pthread_create(&USB_communication_thread, NULL, &uart_communication, &conn); + pthread_create(&USB_communication_thread, NULL, &uart_communication, &conn); //pthread_create(&FPC_communication_thread, NULL, &uart_communication, &conn); fflush(stdout); @@ -350,10 +350,10 @@ void CloseProxmark(void) { pthread_join(USB_communication_thread, NULL); } #else - pthread_join(USB_communication_thread, NULL); + pthread_join(USB_communication_thread, NULL); //pthread_join(FPC_communication_thread, NULL); #endif - + if (sp) { uart_close(sp); } @@ -376,7 +376,7 @@ void CloseProxmark(void) { /** * @brief Waits for a certain response type. This method waits for a maximum of * ms_timeout milliseconds for a specified response command. - + * @param cmd command to wait for, or CMD_UNKNOWN to take any command. * @param response struct to copy received command into. * @param ms_timeout display message after 3 seconds @@ -384,25 +384,25 @@ void CloseProxmark(void) { * @return true if command was returned, otherwise false */ bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning) { - + UsbCommand resp; if (response == NULL) response = &resp; uint64_t start_time = msclock(); - + // Wait until the command is received while (true) { while ( getCommand(response) ) { if (cmd == CMD_UNKNOWN || response->cmd == cmd) - return true; + return true; } if (msclock() - start_time > ms_timeout) break; - + if (msclock() - start_time > 3000 && show_warning) { // 3 seconds elapsed (but this doesn't mean the timeout was exceeded) PrintAndLogEx(NORMAL, "Waiting for a response from the proxmark..."); @@ -435,7 +435,7 @@ bool WaitForResponse(uint32_t cmd, UsbCommand* response) { * @return true if command was returned, otherwise false */ bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint32_t start_index, UsbCommand *response, size_t ms_timeout, bool show_warning) { - + if (dest == NULL) return false; if (bytes == 0) return true; @@ -443,9 +443,9 @@ bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint3 if (response == NULL) response = &resp; - // clear + // clear clearCommandBuffer(); - + switch (memtype) { case BIG_BUF: { UsbCommand c = {CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K, {start_index, bytes, 0}}; @@ -454,10 +454,10 @@ bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint3 } case BIG_BUF_EML: { UsbCommand c = {CMD_DOWNLOAD_EML_BIGBUF, {start_index, bytes, 0}}; - SendCommand(&c); + SendCommand(&c); return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_DOWNLOADED_EML_BIGBUF); } - case FLASH_MEM: { + case FLASH_MEM: { UsbCommand c = {CMD_FLASHMEM_DOWNLOAD, {start_index, bytes, 0}}; SendCommand(&c); return dl_it(dest, bytes, start_index, response, ms_timeout, show_warning, CMD_FLASHMEM_DOWNLOADED); @@ -473,46 +473,46 @@ bool GetFromDevice(DeviceMemType_t memtype, uint8_t *dest, uint32_t bytes, uint3 } bool dl_it(uint8_t *dest, uint32_t bytes, uint32_t start_index, UsbCommand *response, size_t ms_timeout, bool show_warning, uint32_t rec_cmd) { - + uint32_t bytes_completed = 0; uint64_t start_time = msclock(); - + while (true) { - + if (getCommand(response)) { // sample_buf is a array pointer, located in data.c // arg0 = offset in transfer. Startindex of this chunk // arg1 = length bytes to transfer - // arg2 = bigbuff tracelength (?) + // arg2 = bigbuff tracelength (?) if (response->cmd == rec_cmd) { - + uint32_t offset = response->arg[0]; uint32_t copy_bytes = MIN(bytes - bytes_completed, response->arg[1]); //uint32_t tracelen = c->arg[2]; - + // extended bounds check1. upper limit is USB_CMD_DATA_SIZE // shouldn't happen copy_bytes = MIN(copy_bytes, USB_CMD_DATA_SIZE); - - // extended bounds check2. + + // extended bounds check2. if ( offset + copy_bytes > bytes ) { PrintAndLogEx(FAILED, "ERROR: Out of bounds when downloading from device, offset %u | len %u | total len %u > buf_size %u", offset, copy_bytes, offset+copy_bytes, bytes); break; - } - + } + memcpy(dest + offset, response->d.asBytes, copy_bytes); bytes_completed += copy_bytes; } else if (response->cmd == CMD_ACK) { return true; } } - + if (msclock() - start_time > ms_timeout) { PrintAndLogEx(FAILED, "Timed out while trying to download data from device"); break; } - + if (msclock() - start_time > 3000 && show_warning) { // 3 seconds elapsed (but this doesn't mean the timeout was exceeded) PrintAndLogEx(NORMAL, "Waiting for a response from the proxmark..."); diff --git a/client/comms.h b/client/comms.h index e311f5e0c..d3303be3f 100644 --- a/client/comms.h +++ b/client/comms.h @@ -20,7 +20,7 @@ #include "ui.h" #include "common.h" #include "util_posix.h" -#include "util.h" +#include "util.h" #include "util_darwin.h" #if defined(__linux__) && !defined(NO_UNLINK) @@ -43,7 +43,7 @@ typedef struct { bool run; // If TRUE, continue running the uart_communication thread bool block_after_ACK; // if true, block after receiving an ACK package } communication_arg_t; - + bool dl_it(uint8_t *dest, uint32_t bytes, uint32_t start_index, UsbCommand *response, size_t ms_timeout, bool show_warning, uint32_t rec_cmd); @@ -56,7 +56,7 @@ void clearCommandBuffer(); bool OpenProxmark(void *port, bool wait_for_port, int timeout, bool flash_mode); void CloseProxmark(void); - + bool WaitForResponseTimeoutW(uint32_t cmd, UsbCommand* response, size_t ms_timeout, bool show_warning); bool WaitForResponseTimeout(uint32_t cmd, UsbCommand* response, size_t ms_timeout); bool WaitForResponse(uint32_t cmd, UsbCommand* response); diff --git a/client/crypto/asn1dump.c b/client/crypto/asn1dump.c index a0abdf3cf..38d03d353 100644 --- a/client/crypto/asn1dump.c +++ b/client/crypto/asn1dump.c @@ -12,7 +12,7 @@ #include "asn1dump.h" #include #include -#include +#include #include #include #include @@ -110,7 +110,7 @@ static void asn1_tag_dump_str_time(const struct tlv *tlv, const struct asn1_tag *needdump = false; int startindx = longyear ? 4 : 2; - + if (len > 4) { fprintf(f, "\tvalue: '"); while (true) { @@ -119,42 +119,42 @@ static void asn1_tag_dump_str_time(const struct tlv *tlv, const struct asn1_tag fprintf(f, "20"); fwrite(tlv->value, 1, longyear ? 4 : 2, f); fprintf(f, "-"); - if (len < startindx + 2) + if (len < startindx + 2) break; // month fwrite(&tlv->value[startindx], 1, 2, f); fprintf(f, "-"); - if (len < startindx + 4) + if (len < startindx + 4) break; // day fwrite(&tlv->value[startindx + 2], 1, 2, f); fprintf(f, " "); - if (len < startindx + 6) + if (len < startindx + 6) break; // hour fwrite(&tlv->value[startindx + 4], 1, 2, f); fprintf(f, ":"); - if (len < startindx + 8) + if (len < startindx + 8) break; // min fwrite(&tlv->value[startindx + 6], 1, 2, f); fprintf(f, ":"); - if (len < startindx + 10) + if (len < startindx + 10) break; // sec fwrite(&tlv->value[startindx + 8], 1, 2, f); - if (len < startindx + 11) + if (len < startindx + 11) break; // time zone fprintf(f, " zone: %.*s", len - 10 - (longyear ? 4 : 2), &tlv->value[startindx + 10]); - + break; } fprintf(f, "'\n"); } else { fprintf(f, "\n"); *needdump = true; - } + } } static void asn1_tag_dump_string(const struct tlv *tlv, const struct asn1_tag *tag, FILE *f, int level){ @@ -170,7 +170,7 @@ static void asn1_tag_dump_octet_string(const struct tlv *tlv, const struct asn1_ *needdump = true; break; } - + if (*needdump) { fprintf(f, "'\n"); } else { @@ -239,7 +239,7 @@ static char *asn1_oid_description(const char *oid, bool with_group_desc) { size_t len = strlen(get_my_executable_directory()); if ( len > 300 ) len = 299; - + strncpy(fname, get_my_executable_directory(), len); strcat(fname, "crypto/oids.json"); if (access(fname, F_OK) < 0) { @@ -249,19 +249,19 @@ static char *asn1_oid_description(const char *oid, bool with_group_desc) { goto error; // file not found } } - + // load `oids.json` root = json_load_file(fname, 0, &error); - + if (!root || !json_is_object(root)) { goto error; } - + json_t *elm = json_object_get(root, oid); if (!elm) { goto error; } - + if (JsonLoadStr(elm, "$.d", res)) goto error; @@ -271,10 +271,10 @@ static char *asn1_oid_description(const char *oid, bool with_group_desc) { strcat(res, strext); strcat(res, ")"); } - + json_decref(root); return res; - + error: if (root) json_decref(root); @@ -287,15 +287,15 @@ static void asn1_tag_dump_object_id(const struct tlv *tlv, const struct asn1_tag asn1_buf.len = tlv->len; asn1_buf.p = (uint8_t *)tlv->value; char pstr[300]; - mbedtls_oid_get_numeric_string(pstr, sizeof(pstr), &asn1_buf); + mbedtls_oid_get_numeric_string(pstr, sizeof(pstr), &asn1_buf); fprintf(f, " %s", pstr); - + char *jsondesc = asn1_oid_description(pstr, true); if (jsondesc) { fprintf(f, " - %s", jsondesc); - } else { + } else { const char *ppstr; - mbedtls_oid_get_attr_short_name(&asn1_buf, &ppstr); + mbedtls_oid_get_attr_short_name(&asn1_buf, &ppstr); if (ppstr && strnlen(ppstr, 1)) { fprintf(f, " (%s)\n", ppstr); return; @@ -355,6 +355,6 @@ bool asn1_tag_dump(const struct tlv *tlv, FILE *f, int level, bool *candump) { *candump = false; break; }; - + return true; } diff --git a/client/crypto/asn1utils.c b/client/crypto/asn1utils.c index 5be323b45..f8b296e60 100644 --- a/client/crypto/asn1utils.c +++ b/client/crypto/asn1utils.c @@ -34,10 +34,10 @@ int ecdsa_asn1_get_signature(uint8_t *signature, size_t signaturelen, uint8_t *r mbedtls_mpi_free(&xmpi); goto exit; } - + res = mbedtls_mpi_write_binary(&xmpi, rval, 32); mbedtls_mpi_free(&xmpi); - if (res) + if (res) goto exit; mbedtls_mpi_init(&xmpi); @@ -46,10 +46,10 @@ int ecdsa_asn1_get_signature(uint8_t *signature, size_t signaturelen, uint8_t *r mbedtls_mpi_free(&xmpi); goto exit; } - + res = mbedtls_mpi_write_binary(&xmpi, sval, 32); mbedtls_mpi_free(&xmpi); - if (res) + if (res) goto exit; // check size @@ -72,7 +72,7 @@ static bool print_cb(void *data, const struct tlv *tlv, int level, bool is_leaf) } int asn1_print(uint8_t *asn1buf, size_t asn1buflen, char *indent) { - + struct tlvdb *t = NULL; t = tlvdb_parse_multi(asn1buf, asn1buflen); if (t) { @@ -82,7 +82,7 @@ int asn1_print(uint8_t *asn1buf, size_t asn1buflen, char *indent) { PrintAndLogEx(ERR, "Can't parse data as TLV tree."); return 1; } - + return 0; } diff --git a/client/crypto/libpcrypto.c b/client/crypto/libpcrypto.c index 896048bf0..37668b4e4 100644 --- a/client/crypto/libpcrypto.c +++ b/client/crypto/libpcrypto.c @@ -30,7 +30,7 @@ int aes_encode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int l uint8_t iiv[16] = {0}; if (iv) memcpy(iiv, iv, 16); - + mbedtls_aes_context aes; mbedtls_aes_init(&aes); if (mbedtls_aes_setkey_enc(&aes, key, 128)) @@ -46,7 +46,7 @@ int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int l uint8_t iiv[16] = {0}; if (iv) memcpy(iiv, iv, 16); - + mbedtls_aes_context aes; mbedtls_aes_init(&aes); if (mbedtls_aes_setkey_dec(&aes, key, 128)) @@ -62,20 +62,20 @@ int aes_decode(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *output, int l // https://csrc.nist.gov/CSRC/media/Projects/Cryptographic-Standards-and-Guidelines/documents/examples/AES_CMAC.pdf int aes_cmac(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length) { memset(mac, 0x00, 16); - - // NIST 800-38B + + // NIST 800-38B return mbedtls_aes_cmac_prf_128(key, MBEDTLS_AES_BLOCK_SIZE, input, length, mac); } int aes_cmac8(uint8_t *iv, uint8_t *key, uint8_t *input, uint8_t *mac, int length) { uint8_t cmac[16] = {0}; memset(mac, 0x00, 8); - + int res = aes_cmac(iv, key, input, cmac, length); if (res) return res; - - for(int i = 0; i < 8; i++) + + for(int i = 0; i < 8; i++) mac[i] = cmac[i * 2 + 1]; return 0; @@ -88,73 +88,73 @@ static int fixed_rand(void *rng_state, unsigned char *output, size_t len) { } else { memset(output, 0x00, len); } - + return 0; } int sha256hash(uint8_t *input, int length, uint8_t *hash) { if (!hash || !input) return 1; - + mbedtls_sha256_context sctx; mbedtls_sha256_init(&sctx); - mbedtls_sha256_starts(&sctx, 0); // SHA-256, not 224 + mbedtls_sha256_starts(&sctx, 0); // SHA-256, not 224 mbedtls_sha256_update(&sctx, input, length); - mbedtls_sha256_finish(&sctx, hash); + mbedtls_sha256_finish(&sctx, hash); mbedtls_sha256_free(&sctx); - + return 0; } int ecdsa_init_str(mbedtls_ecdsa_context *ctx, char * key_d, char *key_x, char *key_y) { if (!ctx) return 1; - + int res; mbedtls_ecdsa_init(ctx); res = mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1); // secp256r1 - if (res) + if (res) return res; - + if (key_d) { res = mbedtls_mpi_read_string(&ctx->d, 16, key_d); - if (res) + if (res) return res; } - + if (key_x && key_y) { res = mbedtls_ecp_point_read_string(&ctx->Q, 16, key_x, key_y); - if (res) + if (res) return res; } - + return 0; } int ecdsa_init(mbedtls_ecdsa_context *ctx, uint8_t * key_d, uint8_t *key_xy) { if (!ctx) return 1; - + int res; mbedtls_ecdsa_init(ctx); res = mbedtls_ecp_group_load(&ctx->grp, MBEDTLS_ECP_DP_SECP256R1); // secp256r1 - if (res) + if (res) return res; - + if (key_d) { res = mbedtls_mpi_read_binary(&ctx->d, key_d, 32); - if (res) + if (res) return res; } - + if (key_xy) { res = mbedtls_ecp_point_read_binary(&ctx->grp, &ctx->Q, key_xy, 32 * 2 + 1); - if (res) + if (res) return res; } - + return 0; } @@ -188,7 +188,7 @@ int ecdsa_key_create(uint8_t * key_d, uint8_t *key_xy) { res = mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &keylen, public_key, sizeof(public_key)); if (res) goto exit; - + if (keylen != 65) { // 0x04 res = 1; goto exit; @@ -212,20 +212,20 @@ char *ecdsa_get_error(int ret) { int ecdsa_public_key_from_pk(mbedtls_pk_context *pk, uint8_t *key, size_t keylen) { int res = 0; size_t realkeylen = 0; - if (keylen < 65) + if (keylen < 65) return 1; - + mbedtls_ecdsa_context ctx; mbedtls_ecdsa_init(&ctx); - + res = mbedtls_ecp_group_load(&ctx.grp, MBEDTLS_ECP_DP_SECP256R1); // secp256r1 if (res) goto exit; - + res = mbedtls_ecdsa_from_keypair(&ctx, mbedtls_pk_ec(*pk) ); if (res) goto exit; - + res = mbedtls_ecp_point_write_binary(&ctx.grp, &ctx.Q, MBEDTLS_ECP_PF_UNCOMPRESSED, &realkeylen, key, keylen); if (realkeylen != 65) res = 2; @@ -237,8 +237,8 @@ exit: int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen) { int res; *signaturelen = 0; - - uint8_t shahash[32] = {0}; + + uint8_t shahash[32] = {0}; res = sha256hash(input, length, shahash); if (res) return res; @@ -254,10 +254,10 @@ int ecdsa_signature_create(uint8_t *key_d, uint8_t *key_xy, uint8_t *input, int if (res) goto exit; - mbedtls_ecdsa_context ctx; + mbedtls_ecdsa_context ctx; ecdsa_init(&ctx, key_d, key_xy); res = mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256, shahash, sizeof(shahash), signature, signaturelen, mbedtls_ctr_drbg_random, &ctr_drbg); - + exit: mbedtls_ctr_drbg_free(&ctr_drbg); mbedtls_ecdsa_free(&ctx); @@ -267,49 +267,49 @@ exit: int ecdsa_signature_create_test(char * key_d, char *key_x, char *key_y, char *random, uint8_t *input, int length, uint8_t *signature, size_t *signaturelen) { int res; *signaturelen = 0; - - uint8_t shahash[32] = {0}; + + uint8_t shahash[32] = {0}; res = sha256hash(input, length, shahash); if (res) return res; int rndlen = 0; param_gethex_to_eol(random, 0, fixed_rand_value, sizeof(fixed_rand_value), &rndlen); - - mbedtls_ecdsa_context ctx; + + mbedtls_ecdsa_context ctx; ecdsa_init_str(&ctx, key_d, key_x, key_y); res = mbedtls_ecdsa_write_signature(&ctx, MBEDTLS_MD_SHA256, shahash, sizeof(shahash), signature, signaturelen, fixed_rand, NULL); - + mbedtls_ecdsa_free(&ctx); return res; } int ecdsa_signature_verify_keystr(char *key_x, char *key_y, uint8_t *input, int length, uint8_t *signature, size_t signaturelen) { int res; - uint8_t shahash[32] = {0}; + uint8_t shahash[32] = {0}; res = sha256hash(input, length, shahash); if (res) return res; - mbedtls_ecdsa_context ctx; + mbedtls_ecdsa_context ctx; ecdsa_init_str(&ctx, NULL, key_x, key_y); res = mbedtls_ecdsa_read_signature(&ctx, shahash, sizeof(shahash), signature, signaturelen); - + mbedtls_ecdsa_free(&ctx); return res; } int ecdsa_signature_verify(uint8_t *key_xy, uint8_t *input, int length, uint8_t *signature, size_t signaturelen) { int res; - uint8_t shahash[32] = {0}; + uint8_t shahash[32] = {0}; res = sha256hash(input, length, shahash); if (res) return res; - mbedtls_ecdsa_context ctx; + mbedtls_ecdsa_context ctx; ecdsa_init(&ctx, NULL, key_xy); res = mbedtls_ecdsa_read_signature(&ctx, shahash, sizeof(shahash), signature, signaturelen); - + mbedtls_ecdsa_free(&ctx); return res; } @@ -325,8 +325,8 @@ int ecdsa_nist_test(bool verbose) { int res; uint8_t input[] = "Example of ECDSA with P-256"; int length = strlen((char *)input); - uint8_t signature[300] = {0}; - size_t siglen = 0; + uint8_t signature[300] = {0}; + size_t siglen = 0; // NIST ecdsa test if (verbose) @@ -334,32 +334,32 @@ int ecdsa_nist_test(bool verbose) { // make signature res = ecdsa_signature_create_test(T_PRIVATE_KEY, T_Q_X, T_Q_Y, T_K, input, length, signature, &siglen); // printf("res: %x signature[%x]: %s\n", (res<0)?-res:res, siglen, sprint_hex(signature, siglen)); - if (res) + if (res) goto exit; // check vectors - uint8_t rval[300] = {0}; - uint8_t sval[300] = {0}; + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; res = ecdsa_asn1_get_signature(signature, siglen, rval, sval); if (res) goto exit; - + int slen = 0; uint8_t rval_s[33] = {0}; param_gethex_to_eol(T_R, 0, rval_s, sizeof(rval_s), &slen); - uint8_t sval_s[33] = {0}; + uint8_t sval_s[33] = {0}; param_gethex_to_eol(T_S, 0, sval_s, sizeof(sval_s), &slen); if (strncmp((char *)rval, (char *)rval_s, 32) || strncmp((char *)sval, (char *)sval_s, 32)) { printf("R or S check error\n"); res = 100; goto exit; } - + // verify signature res = ecdsa_signature_verify_keystr(T_Q_X, T_Q_Y, input, length, signature, siglen); - if (res) + if (res) goto exit; - + // verify wrong signature input[0] ^= 0xFF; res = ecdsa_signature_verify_keystr(T_Q_X, T_Q_Y, input, length, signature, siglen); @@ -378,27 +378,27 @@ int ecdsa_nist_test(bool verbose) { uint8_t key_xy[32 * 2 + 2] = {0}; memset(signature, 0x00, sizeof(signature)); siglen = 0; - + res = ecdsa_key_create(key_d, key_xy); - if (res) + if (res) goto exit; res = ecdsa_signature_create(key_d, key_xy, input, length, signature, &siglen); - if (res) + if (res) goto exit; res = ecdsa_signature_verify(key_xy, input, length, signature, siglen); - if (res) + if (res) goto exit; input[0] ^= 0xFF; res = ecdsa_signature_verify(key_xy, input, length, signature, siglen); - if (!res) + if (!res) goto exit; - + if (verbose) printf("passed\n\n"); - + return 0; exit: if (verbose) diff --git a/client/emv/apduinfo.c b/client/emv/apduinfo.c index b1bb84dae..17e87c45f 100644 --- a/client/emv/apduinfo.c +++ b/client/emv/apduinfo.c @@ -270,10 +270,10 @@ int CodeCmp(const char *code1, const char *code2) { } if (cmp == 4) return 0; - + if (cmp + xsymb == 4) return xsymb; - + return -1; } @@ -282,17 +282,17 @@ const APDUCode* const GetAPDUCode(uint8_t sw1, uint8_t sw2) { int res; int mineq = APDUCodeTableLen; int mineqindx = 0; - + sprintf(buf, "%02X%02X", sw1, sw2); - + for (int i = 0; i < APDUCodeTableLen; i++) { res = CodeCmp(APDUCodeTable[i].ID, buf); - + // equal - if (res == 0) { + if (res == 0) { return &APDUCodeTable[i]; } - + // with some 'X' if (res > 0 && mineq > res) { mineq = res; @@ -304,7 +304,7 @@ const APDUCode* const GetAPDUCode(uint8_t sw1, uint8_t sw2) { if (mineqindx < APDUCodeTableLen) { return &APDUCodeTable[mineqindx]; } - + return NULL; } diff --git a/client/emv/apduinfo.h b/client/emv/apduinfo.h index a3fa2049b..c64230502 100644 --- a/client/emv/apduinfo.h +++ b/client/emv/apduinfo.h @@ -27,7 +27,7 @@ typedef struct { const uint8_t Type; const char *Description; } APDUCode; - + extern const APDUCode* const GetAPDUCode(uint8_t sw1, uint8_t sw2); extern const char* GetAPDUCodeDescription(uint8_t sw1, uint8_t sw2); diff --git a/client/emv/cmdemv.c b/client/emv/cmdemv.c index f14d23f2d..5d73e88c9 100644 --- a/client/emv/cmdemv.c +++ b/client/emv/cmdemv.c @@ -58,8 +58,8 @@ int CmdEMVSelect(const char *cmd) { uint8_t data[APDU_AID_LEN] = {0}; int datalen = 0; - CLIParserInit("emv select", - "Executes select applet command", + CLIParserInit("emv select", + "Executes select applet command", "Usage:\n\temv select -s a00000000101 -> select card, select applet\n\temv select -st a00000000101 -> select card, select applet, show result in TLV\n"); void* argtable[] = { @@ -73,7 +73,7 @@ int CmdEMVSelect(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool activateField = arg_get_lit(1); bool leaveSignalON = arg_get_lit(2); bool APDULogging = arg_get_lit(3); @@ -84,9 +84,9 @@ int CmdEMVSelect(const char *cmd) { PrintChannel(channel); CLIGetHexWithReturn(6, data, &datalen); CLIParserFree(); - + SetAPDULogging(APDULogging); - + // exec uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; @@ -94,11 +94,11 @@ int CmdEMVSelect(const char *cmd) { int res = EMVSelect(channel, activateField, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL); if (sw) - PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - + PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + if (res) return res; - + if (decodeTLV) TLVPrintFromBuffer(buf, len); @@ -107,8 +107,8 @@ int CmdEMVSelect(const char *cmd) { int CmdEMVSearch(const char *cmd) { - CLIParserInit("emv search", - "Tries to select all applets from applet list:\n", + CLIParserInit("emv search", + "Tries to select all applets from applet list:\n", "Usage:\n\temv search -s -> select card and search\n\temv search -st -> select card, search and show result in TLV\n"); void* argtable[] = { @@ -121,7 +121,7 @@ int CmdEMVSearch(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool activateField = arg_get_lit(1); bool leaveSignalON = arg_get_lit(2); bool APDULogging = arg_get_lit(3); @@ -131,9 +131,9 @@ int CmdEMVSearch(const char *cmd) { channel = ECC_CONTACT; PrintChannel(channel); CLIParserFree(); - + SetAPDULogging(APDULogging); - + struct tlvdb *t = NULL; const char *al = "Applets list"; t = tlvdb_fixed(1, strlen(al), (const unsigned char *)al); @@ -142,23 +142,23 @@ int CmdEMVSearch(const char *cmd) { tlvdb_free(t); return 2; } - + PrintAndLogEx(SUCCESS, "Search completed."); // print list here - if (!decodeTLV) { + if (!decodeTLV) { TLVPrintAIDlistFromSelectTLV(t); } - + tlvdb_free(t); - + return 0; } int CmdEMVPPSE(const char *cmd) { - - CLIParserInit("emv pse", - "Executes PSE/PPSE select command. It returns list of applet on the card:\n", + + CLIParserInit("emv pse", + "Executes PSE/PPSE select command. It returns list of applet on the card:\n", "Usage:\n\temv pse -s1 -> select, get pse\n\temv pse -st2 -> select, get ppse, show result in TLV\n"); void* argtable[] = { @@ -173,7 +173,7 @@ int CmdEMVPPSE(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool activateField = arg_get_lit(1); bool leaveSignalON = arg_get_lit(2); uint8_t PSENum = 2; @@ -187,23 +187,23 @@ int CmdEMVPPSE(const char *cmd) { if (arg_get_lit(7)) channel = ECC_CONTACT; PrintChannel(channel); - CLIParserFree(); - + CLIParserFree(); + SetAPDULogging(APDULogging); - + // exec uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; int res = EMVSelectPSE(channel, activateField, leaveSignalON, PSENum, buf, sizeof(buf), &len, &sw); - + if (sw) - PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); if (res) return res; - - + + if (decodeTLV) TLVPrintFromBuffer(buf, len); @@ -214,11 +214,11 @@ int CmdEMVGPO(const char *cmd) { uint8_t data[APDU_RES_LEN] = {0}; int datalen = 0; - CLIParserInit("emv gpo", - "Executes Get Processing Options command. It returns data in TLV format (0x77 - format2) or plain format (0x80 - format1).\nNeeds a EMV applet to be selected.", + CLIParserInit("emv gpo", + "Executes Get Processing Options command. It returns data in TLV format (0x77 - format2) or plain format (0x80 - format1).\nNeeds a EMV applet to be selected.", "Usage:\n\temv gpo -k -> execute GPO\n" "\temv gpo -t 01020304 -> execute GPO with 4-byte PDOL data, show result in TLV\n" - "\temv gpo -pmt 9F 37 04 -> load params from file, make PDOL data from PDOL, execute GPO with PDOL, show result in TLV\n"); + "\temv gpo -pmt 9F 37 04 -> load params from file, make PDOL data from PDOL, execute GPO with PDOL, show result in TLV\n"); void* argtable[] = { arg_param_begin, @@ -232,7 +232,7 @@ int CmdEMVGPO(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool leaveSignalON = arg_get_lit(1); bool paramsLoadFromFile = arg_get_lit(2); bool dataMakeFromPDOL = arg_get_lit(3); @@ -243,14 +243,14 @@ int CmdEMVGPO(const char *cmd) { channel = ECC_CONTACT; PrintChannel(channel); CLIGetHexWithReturn(7, data, &datalen); - CLIParserFree(); - + CLIParserFree(); + SetAPDULogging(APDULogging); - + // Init TLV tree const char *alr = "Root terminal TLV tree"; struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr); - + // calc PDOL struct tlv *pdol_data_tlv = NULL; struct tlvdb *tmp_ext = NULL; @@ -266,7 +266,7 @@ int CmdEMVGPO(const char *cmd) { PrintAndLogEx(INFO, "Params loading from file..."); ParamLoadFromJson(tlvRoot); }; - + tmp_ext = tlvdb_external(0x9f38, datalen, data); pdol_data_tlv = dol_process((const struct tlv *)tmp_ext, tlvRoot, 0x83); if (!pdol_data_tlv){ @@ -291,25 +291,25 @@ int CmdEMVGPO(const char *cmd) { return 4; } PrintAndLogEx(INFO, "PDOL data[%d]: %s", pdol_data_tlv_data_len, sprint_hex(pdol_data_tlv_data, pdol_data_tlv_data_len)); - + // exec uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; int res = EMVGPO(channel, leaveSignalON, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot); - + if (pdol_data_tlv != &data_tlv) free(pdol_data_tlv); - tlvdb_free(tmp_ext); + tlvdb_free(tmp_ext); tlvdb_free(tlvRoot); - + if (sw) - PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); if (res) return res; - + if (decodeTLV) TLVPrintFromBuffer(buf, len); @@ -320,8 +320,8 @@ int CmdEMVReadRecord(const char *cmd) { uint8_t data[APDU_RES_LEN] = {0}; int datalen = 0; - CLIParserInit("emv readrec", - "Executes Read Record command. It returns data in TLV format.\nNeeds a bank applet to be selected and sometimes needs GPO to be executed.", + CLIParserInit("emv readrec", + "Executes Read Record command. It returns data in TLV format.\nNeeds a bank applet to be selected and sometimes needs GPO to be executed.", "Usage:\n\temv readrec -k 0101 -> read file SFI=01, SFIrec=01\n\temv readrec -kt 0201-> read file 0201 and show result in TLV\n"); void* argtable[] = { @@ -334,7 +334,7 @@ int CmdEMVReadRecord(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool leaveSignalON = arg_get_lit(1); bool APDULogging = arg_get_lit(2); bool decodeTLV = arg_get_lit(3); @@ -344,27 +344,27 @@ int CmdEMVReadRecord(const char *cmd) { PrintChannel(channel); CLIGetHexWithReturn(5, data, &datalen); CLIParserFree(); - + if (datalen != 2) { PrintAndLogEx(ERR, "Command needs to have 2 bytes of data"); return 1; } - + SetAPDULogging(APDULogging); - + // exec uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; int res = EMVReadRecord(channel, leaveSignalON, data[0], data[1], buf, sizeof(buf), &len, &sw, NULL); - + if (sw) - PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); if (res) return res; - - + + if (decodeTLV) TLVPrintFromBuffer(buf, len); @@ -375,12 +375,12 @@ int CmdEMVAC(const char *cmd) { uint8_t data[APDU_RES_LEN] = {0}; int datalen = 0; - CLIParserInit("emv genac", - "Generate Application Cryptogram command. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.", + CLIParserInit("emv genac", + "Generate Application Cryptogram command. It returns data in TLV format .\nNeeds a EMV applet to be selected and GPO to be executed.", "Usage:\n\temv genac -k 0102 -> generate AC with 2-byte CDOLdata and keep field ON after command\n" "\temv genac -t 01020304 -> generate AC with 4-byte CDOL data, show result in TLV\n" "\temv genac -Daac 01020304 -> generate AC with 4-byte CDOL data and terminal decision 'declined'\n" - "\temv genac -pmt 9F 37 04 -> load params from file, make CDOL data from CDOL, generate AC with CDOL, show result in TLV"); + "\temv genac -pmt 9F 37 04 -> load params from file, make CDOL data from CDOL, generate AC with CDOL, show result in TLV"); void* argtable[] = { arg_param_begin, @@ -396,7 +396,7 @@ int CmdEMVAC(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, false); - + bool leaveSignalON = arg_get_lit(1); bool trTypeCDA = arg_get_lit(2); uint8_t termDecision = 0xff; @@ -426,14 +426,14 @@ int CmdEMVAC(const char *cmd) { channel = ECC_CONTACT; PrintChannel(channel); CLIGetHexWithReturn(9, data, &datalen); - CLIParserFree(); - + CLIParserFree(); + SetAPDULogging(APDULogging); - + // Init TLV tree const char *alr = "Root terminal TLV tree"; struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr); - + // calc CDOL struct tlv *cdol_data_tlv = NULL; struct tlvdb *tmp_ext = NULL; @@ -442,7 +442,7 @@ int CmdEMVAC(const char *cmd) { .len = datalen, .value = (uint8_t *)data, }; - + if (dataMakeFromCDOL) { ParamLoadDefaults(tlvRoot); @@ -450,7 +450,7 @@ int CmdEMVAC(const char *cmd) { PrintAndLogEx(INFO, "Params loading from file..."); ParamLoadFromJson(tlvRoot); }; - + tmp_ext = tlvdb_external(0x8c, datalen, data); cdol_data_tlv = dol_process((const struct tlv *)tmp_ext, tlvRoot, 0x01); // 0x01 - dummy tag if (!cdol_data_tlv){ @@ -465,7 +465,7 @@ int CmdEMVAC(const char *cmd) { } cdol_data_tlv = &data_tlv; } - + PrintAndLogEx(INFO, "CDOL data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len)); // exec @@ -473,29 +473,29 @@ int CmdEMVAC(const char *cmd) { size_t len = 0; uint16_t sw = 0; int res = EMVAC(channel, leaveSignalON, termDecision, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot); - + if (cdol_data_tlv != &data_tlv) free(cdol_data_tlv); tlvdb_free(tmp_ext); tlvdb_free(tlvRoot); - + if (sw) - PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); if (res) return res; - + if (decodeTLV) TLVPrintFromBuffer(buf, len); - return 0; + return 0; } int CmdEMVGenerateChallenge(const char *cmd) { - CLIParserInit("emv challenge", - "Executes Generate Challenge command. It returns 4 or 8-byte random number from card.\nNeeds a EMV applet to be selected and GPO to be executed.", + CLIParserInit("emv challenge", + "Executes Generate Challenge command. It returns 4 or 8-byte random number from card.\nNeeds a EMV applet to be selected and GPO to be executed.", "Usage:\n\temv challenge -> get challenge\n\temv challenge -k -> get challenge, keep fileld ON\n"); void* argtable[] = { @@ -506,34 +506,34 @@ int CmdEMVGenerateChallenge(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool leaveSignalON = arg_get_lit(1); bool APDULogging = arg_get_lit(2); EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(3)) channel = ECC_CONTACT; PrintChannel(channel); - CLIParserFree(); - + CLIParserFree(); + SetAPDULogging(APDULogging); - + // exec uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; int res = EMVGenerateChallenge(channel, leaveSignalON, buf, sizeof(buf), &len, &sw, NULL); - + if (sw) - PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); if (res) return res; PrintAndLogEx(SUCCESS, "Challenge: %s", sprint_hex(buf, len)); - + if (len != 4 && len != 8) PrintAndLogEx(WARNING, "Length of challenge must be 4 or 8, but it %d", len); - + return 0; } @@ -541,14 +541,14 @@ int CmdEMVInternalAuthenticate(const char *cmd) { uint8_t data[APDU_RES_LEN] = {0}; int datalen = 0; - CLIParserInit("emv intauth", + CLIParserInit("emv intauth", "Generate Internal Authenticate command. Usually needs 4-byte random number. It returns data in TLV format .\n" - "Needs a EMV applet to be selected and GPO to be executed.", - + "Needs a EMV applet to be selected and GPO to be executed.", + "Usage:\n" "\temv intauth -k 01020304 -> execute Internal Authenticate with 4-byte DDOLdata and keep field ON after command\n" "\temv intauth -t 01020304 -> execute Internal Authenticate with 4-byte DDOL data, show result in TLV\n" - "\temv intauth -pmt 9F 37 04 -> load params from file, make DDOL data from DDOL, Internal Authenticate with DDOL, show result in TLV"); + "\temv intauth -pmt 9F 37 04 -> load params from file, make DDOL data from DDOL, Internal Authenticate with DDOL, show result in TLV"); void* argtable[] = { arg_param_begin, @@ -562,7 +562,7 @@ int CmdEMVInternalAuthenticate(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, false); - + bool leaveSignalON = arg_get_lit(1); bool paramsLoadFromFile = arg_get_lit(2); bool dataMakeFromDDOL = arg_get_lit(3); @@ -573,14 +573,14 @@ int CmdEMVInternalAuthenticate(const char *cmd) { channel = ECC_CONTACT; PrintChannel(channel); CLIGetHexWithReturn(7, data, &datalen); - CLIParserFree(); - + CLIParserFree(); + SetAPDULogging(APDULogging); // Init TLV tree const char *alr = "Root terminal TLV tree"; struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr); - + // calc DDOL struct tlv *ddol_data_tlv = NULL; struct tlvdb *tmp_ext = NULL; @@ -589,7 +589,7 @@ int CmdEMVInternalAuthenticate(const char *cmd) { .len = datalen, .value = (uint8_t *)data, }; - + if (dataMakeFromDDOL) { ParamLoadDefaults(tlvRoot); @@ -597,7 +597,7 @@ int CmdEMVInternalAuthenticate(const char *cmd) { PrintAndLogEx(INFO, "Params loading from file..."); ParamLoadFromJson(tlvRoot); }; - + tmp_ext = tlvdb_external(0x9f49, datalen, data); ddol_data_tlv = dol_process((const struct tlv *)tmp_ext, tlvRoot, 0x01); // 0x01 - dummy tag if (!ddol_data_tlv){ @@ -612,44 +612,44 @@ int CmdEMVInternalAuthenticate(const char *cmd) { } ddol_data_tlv = &data_tlv; } - + PrintAndLogEx(INFO, "DDOL data[%d]: %s", ddol_data_tlv->len, sprint_hex(ddol_data_tlv->value, ddol_data_tlv->len)); - + // exec uint8_t buf[APDU_RES_LEN] = {0}; size_t len = 0; uint16_t sw = 0; int res = EMVInternalAuthenticate(channel, leaveSignalON, data, datalen, buf, sizeof(buf), &len, &sw, NULL); - + if (ddol_data_tlv != &data_tlv) free(ddol_data_tlv); - tlvdb_free(tmp_ext); - tlvdb_free(tlvRoot); - + tlvdb_free(tmp_ext); + tlvdb_free(tlvRoot); + if (sw) - PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + PrintAndLogEx(INFO, "APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); if (res) return res; - + if (decodeTLV) TLVPrintFromBuffer(buf, len); - return 0; + return 0; } #define dreturn(n) {free(pdol_data_tlv); tlvdb_free(tlvSelect); tlvdb_free(tlvRoot); DropFieldEx( channel ); return n;} void InitTransactionParameters(struct tlvdb *tlvRoot, bool paramLoadJSON, enum TransactionType TrType, bool GenACGPO) { - + ParamLoadDefaults(tlvRoot); if (paramLoadJSON) { PrintAndLog("* * Transaction parameters loading from JSON..."); ParamLoadFromJson(tlvRoot); } - + //9F66:(Terminal Transaction Qualifiers (TTQ)) len:4 char *qVSDC = "\x26\x00\x00\x00"; if (GenACGPO) { @@ -660,7 +660,7 @@ void InitTransactionParameters(struct tlvdb *tlvRoot, bool paramLoadJSON, enum T TLV_ADD(0x9F66, "\x86\x00\x00\x00"); // MSD break; // not standard for contactless. just for test. - case TT_VSDC: + case TT_VSDC: TLV_ADD(0x9F66, "\x46\x00\x00\x00"); // VSDC break; case TT_QVSDCMCHIP: @@ -680,7 +680,7 @@ void ProcessGPOResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, PrintAndLog("GPO response format1:"); TLVPrintFromBuffer(buf, len); } - + if (len < 4 || (len - 4) % 4) { PrintAndLogEx(ERR, "GPO response format1 parsing error. length=%d", len); } else { @@ -697,7 +697,7 @@ void ProcessGPOResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, tlvdb_add(tlvRoot, f1AFL); if (decodeTLV) TLVPrintFromTLV(f1AFL); - } + } } else { if (decodeTLV) TLVPrintFromBuffer(buf, len); @@ -710,38 +710,38 @@ void ProcessACResponseFormat1(struct tlvdb *tlvRoot, uint8_t *buf, size_t len, b PrintAndLog("GPO response format1:"); TLVPrintFromBuffer(buf, len); } - + uint8_t elmlen = len - 2; // wo 0x80XX - + if (len < 4 + 2 || (elmlen - 2) % 4 || elmlen != buf[1]) { PrintAndLogEx(ERR, "GPO response format1 parsing error. length=%d", len); } else { struct tlvdb *tlvElm = NULL; if (decodeTLV) PrintAndLog("\n------------ Format1 decoded ------------"); - + // CID (Cryptogram Information Data) tlvdb_change_or_add_node_ex(tlvRoot, 0x9f27, 1, &buf[2], &tlvElm); if (decodeTLV) TLVPrintFromTLV(tlvElm); // ATC (Application Transaction Counter) - tlvdb_change_or_add_node_ex(tlvRoot, 0x9f36, 2, &buf[3], &tlvElm); + tlvdb_change_or_add_node_ex(tlvRoot, 0x9f36, 2, &buf[3], &tlvElm); if (decodeTLV) TLVPrintFromTLV(tlvElm); // AC (Application Cryptogram) - tlvdb_change_or_add_node_ex(tlvRoot, 0x9f26, MIN(8, elmlen - 3), &buf[5], &tlvElm); + tlvdb_change_or_add_node_ex(tlvRoot, 0x9f26, MIN(8, elmlen - 3), &buf[5], &tlvElm); if (decodeTLV) TLVPrintFromTLV(tlvElm); // IAD (Issuer Application Data) - optional if (len > 11 + 2) { - tlvdb_change_or_add_node_ex(tlvRoot, 0x9f10, elmlen - 11, &buf[13], &tlvElm); + tlvdb_change_or_add_node_ex(tlvRoot, 0x9f10, elmlen - 11, &buf[13], &tlvElm); if (decodeTLV) TLVPrintFromTLV(tlvElm); - } - } + } + } } else { if (decodeTLV) TLVPrintFromBuffer(buf, len); @@ -756,15 +756,15 @@ int CmdEMVExec(const char *cmd) { size_t AIDlen = 0; uint8_t ODAiList[4096]; size_t ODAiListLen = 0; - + int res; - + struct tlvdb *tlvSelect = NULL; struct tlvdb *tlvRoot = NULL; struct tlv *pdol_data_tlv = NULL; - CLIParserInit("emv exec", - "Executes EMV contactless transaction", + CLIParserInit("emv exec", + "Executes EMV contactless transaction", "Usage:\n" "\temv exec -sat -> select card, execute MSD transaction, show APDU and TLV\n" "\temv exec -satc -> select card, execute CDA transaction, show APDU and TLV\n"); @@ -785,7 +785,7 @@ int CmdEMVExec(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool activateField = arg_get_lit(1); bool showAPDU = arg_get_lit(2); bool decodeTLV = arg_get_lit(3); @@ -807,17 +807,17 @@ int CmdEMVExec(const char *cmd) { PrintChannel(channel); uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; CLIParserFree(); - + #ifndef WITH_SMARTCARD // not compiled with smartcard functionality, we need to exit if ( channel == ECC_CONTACT ) { PrintAndLogEx(WARNING, "PM3 Client is not compiled with support for SMARTCARD. Exiting."); return 0; } -#endif +#endif SetAPDULogging(showAPDU); - + // init applets list tree const char *al = "Applets list"; tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al); @@ -831,12 +831,12 @@ int CmdEMVExec(const char *cmd) { res = EMVSearchPSE(channel, activateField, true, psenum, decodeTLV, tlvSelect); // check PPSE and select application id - if (!res) { + if (!res) { TLVPrintAIDlistFromSelectTLV(tlvSelect); EMVSelectApplication(tlvSelect, AID, &AIDlen); } } - + // Search if (!AIDlen) { PrintAndLogEx(NORMAL, "\n* Search AID in list."); @@ -849,42 +849,42 @@ int CmdEMVExec(const char *cmd) { TLVPrintAIDlistFromSelectTLV(tlvSelect); EMVSelectApplication(tlvSelect, AID, &AIDlen); } - + // Init TLV tree const char *alr = "Root terminal TLV tree"; tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr); - + // check if we found EMV application on card if (!AIDlen) { PrintAndLogEx(WARNING, "Can't select AID. EMV AID not found"); dreturn(2); } - + // Select PrintAndLogEx(NORMAL, "\n* Selecting AID:%s", sprint_hex_inrow(AID, AIDlen)); SetAPDULogging(showAPDU); res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot); - - if (res) { + + if (res) { PrintAndLogEx(WARNING, "Can't select AID (%d). Exit...", res); dreturn(3); } - + if (decodeTLV) TLVPrintFromBuffer(buf, len); PrintAndLog("* Selected."); - + PrintAndLog("\n* Init transaction parameters."); InitTransactionParameters(tlvRoot, paramLoadJSON, TrType, GenACGPO); TLVPrintFromTLV(tlvRoot); // TODO delete!!! - + PrintAndLogEx(NORMAL, "\n* Calc PDOL."); pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83); if (!pdol_data_tlv){ PrintAndLogEx(WARNING, "Error: can't create PDOL TLV."); dreturn(4); } - + size_t pdol_data_tlv_data_len; unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len); if (!pdol_data_tlv_data) { @@ -895,40 +895,40 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "\n* GPO."); res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot); - + free(pdol_data_tlv_data); //free(pdol_data_tlv); --- free on exit. - - if (res) { + + if (res) { PrintAndLogEx(NORMAL, "GPO error(%d): %4x. Exit...", res, sw); dreturn(5); } // process response template format 1 [id:80 2b AIP + x4b AFL] and format 2 [id:77 TLV] ProcessGPOResponseFormat1(tlvRoot, buf, len, decodeTLV); - + // extract PAN from track2 { const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL); if (!tlvdb_get(tlvRoot, 0x5a, NULL) && track2 && track2->len >= 8) { struct tlvdb *pan = GetPANFromTrack2(track2); if (pan) { - tlvdb_add(tlvRoot, pan); - - const struct tlv *pantlv = tlvdb_get(tlvRoot, 0x5a, NULL); + tlvdb_add(tlvRoot, pan); + + const struct tlv *pantlv = tlvdb_get(tlvRoot, 0x5a, NULL); PrintAndLogEx(NORMAL, "\n* * Extracted PAN from track2: %s", sprint_hex(pantlv->value, pantlv->len)); } else { PrintAndLogEx(NORMAL, "\n* * WARNING: Can't extract PAN from track2."); } } } - + PrintAndLogEx(NORMAL, "\n* Read records from AFL."); const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL); if (!AFL || !AFL->len) PrintAndLogEx(NORMAL, "WARNING: AFL not found."); - + while (AFL && AFL->len) { if (AFL->len % 4) { PrintAndLogEx(WARNING, "Error: Wrong AFL length: %d", AFL->len); @@ -940,27 +940,27 @@ int CmdEMVExec(const char *cmd) { uint8_t SFIstart = AFL->value[i * 4 + 1]; uint8_t SFIend = AFL->value[i * 4 + 2]; uint8_t SFIoffline = AFL->value[i * 4 + 3]; - + PrintAndLogEx(NORMAL, "* * SFI[%02x] start:%02x end:%02x offline count:%02x", SFI, SFIstart, SFIend, SFIoffline); if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) { PrintAndLogEx(NORMAL, "SFI ERROR! Skipped..."); continue; } - + for (int n = SFIstart; n <= SFIend; n++) { PrintAndLogEx(NORMAL, "* * * SFI[%02x] %d", SFI, n); - + res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot); if (res) { PrintAndLogEx(WARNING, "Error SFI[%02x]. APDU error %4x", SFI, sw); continue; } - + if (decodeTLV) { TLVPrintFromBuffer(buf, len); PrintAndLogEx(NORMAL, ""); } - + // Build Input list for Offline Data Authentication // EMV 4.3 book3 10.3, page 96 if (SFIoffline > 0) { @@ -978,25 +978,25 @@ int CmdEMVExec(const char *cmd) { memcpy(&ODAiList[ODAiListLen], buf, len); ODAiListLen += len; } - + SFIoffline--; } } } - + break; - } - + } + // copy Input list for Offline Data Authentication if (ODAiListLen) { struct tlvdb *oda = tlvdb_fixed(0x21, ODAiListLen, ODAiList); // not a standard tag - tlvdb_add(tlvRoot, oda); + tlvdb_add(tlvRoot, oda); PrintAndLogEx(NORMAL, "* Input list for Offline Data Authentication added to TLV. len=%d \n", ODAiListLen); } // get AIP uint16_t AIP = 0; - const struct tlv *AIPtlv = tlvdb_get(tlvRoot, 0x82, NULL); + const struct tlv *AIPtlv = tlvdb_get(tlvRoot, 0x82, NULL); if (AIPtlv) { AIP = AIPtlv->value[0] + AIPtlv->value[1] * 0x100; PrintAndLogEx(NORMAL, "* * AIP=%04x", AIP); @@ -1012,10 +1012,10 @@ int CmdEMVExec(const char *cmd) { // DDA if (AIP & 0x0020) { - PrintAndLogEx(NORMAL, "\n* DDA"); + PrintAndLogEx(NORMAL, "\n* DDA"); trDDA(channel, decodeTLV, tlvRoot); - } - + } + // transaction check // qVSDC @@ -1025,11 +1025,11 @@ int CmdEMVExec(const char *cmd) { if (AC) { PrintAndLogEx(NORMAL, "\n--> qVSDC transaction."); PrintAndLogEx(NORMAL, "* AC path"); - + // 9F36: Application Transaction Counter (ATC) const struct tlv *ATC = tlvdb_get(tlvRoot, 0x9F36, NULL); if (ATC) { - + // 9F10: Issuer Application Data - optional const struct tlv *IAD = tlvdb_get(tlvRoot, 0x9F10, NULL); @@ -1038,7 +1038,7 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "AC: %s", sprint_hex(AC->value, AC->len)); if (IAD) { PrintAndLogEx(NORMAL, "IAD: %s", sprint_hex(IAD->value, IAD->len)); - + if (IAD->len >= IAD->value[0] + 1) { PrintAndLogEx(NORMAL, "\tKey index: 0x%02x", IAD->value[1]); PrintAndLogEx(NORMAL, "\tCrypto ver: 0x%02x(%03d)", IAD->value[2], IAD->value[2]); @@ -1049,13 +1049,13 @@ int CmdEMVExec(const char *cmd) { } else { PrintAndLogEx(NORMAL, "WARNING: IAD not found."); } - + } else { PrintAndLogEx(WARNING, "Error AC: Application Transaction Counter (ATC) not found."); } } } - + // Mastercard M/CHIP if (GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD && (TrType == TT_QVSDCMCHIP || TrType == TT_CDA)){ const struct tlv *CDOL1 = tlvdb_get(tlvRoot, 0x8c, NULL); @@ -1072,7 +1072,7 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(WARNING, "Error GetChallenge. Wrong challenge length %d", len); dreturn(6); } - + // ICC Dynamic Number struct tlvdb * ICCDynN = tlvdb_fixed(0x9f4c, len, buf); tlvdb_add(tlvRoot, ICCDynN); @@ -1080,39 +1080,39 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(NORMAL, "\n* * ICC Dynamic Number:"); TLVPrintFromTLV(ICCDynN); } - + PrintAndLogEx(NORMAL, "* * Calc CDOL1"); struct tlv *cdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag if (!cdol_data_tlv) { PrintAndLogEx(WARNING, "Error: can't create CDOL1 TLV."); dreturn(6); } - + PrintAndLogEx(NORMAL, "CDOL1 data[%d]: %s", cdol_data_tlv->len, sprint_hex(cdol_data_tlv->value, cdol_data_tlv->len)); - + PrintAndLogEx(NORMAL, "* * AC1"); // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD res = EMVAC(channel, true, (TrType == TT_CDA) ? EMVAC_TC + EMVAC_CDAREQ : EMVAC_TC, (uint8_t *)cdol_data_tlv->value, cdol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot); - - if (res) { + + if (res) { PrintAndLogEx(NORMAL, "AC1 error(%d): %4x. Exit...", res, sw); dreturn(7); } - + if (decodeTLV) TLVPrintFromBuffer(buf, len); - + // CDA PrintAndLogEx(NORMAL, "\n* CDA:"); struct tlvdb *ac_tlv = tlvdb_parse_multi(buf, len); res = trCDA(tlvRoot, ac_tlv, pdol_data_tlv, cdol_data_tlv); - if (res) { + if (res) { PrintAndLogEx(NORMAL, "CDA error (%d)", res); } - + free(ac_tlv); free(cdol_data_tlv); - + PrintAndLogEx(NORMAL, "\n* M/Chip transaction result:"); // 9F27: Cryptogram Information Data (CID) const struct tlv *CID = tlvdb_get(tlvRoot, 0x9F27, NULL); @@ -1140,14 +1140,14 @@ int CmdEMVExec(const char *cmd) { } else { PrintAndLogEx(WARNING, "Error: CID(9F27) not found."); } - + } } - + // MSD - if (AIP & 0x8000 && TrType == TT_MSD) { + if (AIP & 0x8000 && TrType == TT_MSD) { PrintAndLogEx(NORMAL, "\n--> MSD transaction."); - + PrintAndLogEx(NORMAL, "* MSD dCVV path. Check dCVV"); const struct tlv *track2 = tlvdb_get(tlvRoot, 0x57, NULL); @@ -1157,7 +1157,7 @@ int CmdEMVExec(const char *cmd) { struct tlvdb *dCVV = GetdCVVRawFromTrack2(track2); PrintAndLogEx(NORMAL, "dCVV raw data:"); TLVPrintFromTLV(dCVV); - + if (GetCardPSVendor(AID, AIDlen) == CV_MASTERCARD) { PrintAndLogEx(NORMAL, "\n* Mastercard calculate UDOL"); @@ -1179,16 +1179,16 @@ int CmdEMVExec(const char *cmd) { } PrintAndLogEx(NORMAL, "UDOL data[%d]: %s", udol_data_tlv->len, sprint_hex(udol_data_tlv->value, udol_data_tlv->len)); - + PrintAndLogEx(NORMAL, "\n* Mastercard compute cryptographic checksum(UDOL)"); - + res = MSCComputeCryptoChecksum(channel, true, (uint8_t *)udol_data_tlv->value, udol_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot); if (res) { PrintAndLogEx(WARNING, "Error Compute Crypto Checksum. APDU error %4x", sw); free(udol_data_tlv); dreturn(9); } - + // Mastercard compute cryptographic checksum result TLVPrintFromBuffer(buf, len); PrintAndLogEx(NORMAL, ""); @@ -1204,21 +1204,21 @@ int CmdEMVExec(const char *cmd) { // VSDC if (GetCardPSVendor(AID, AIDlen) == CV_VISA && (TrType == TT_VSDC || TrType == TT_CDA)){ PrintAndLogEx(NORMAL, "\n--> VSDC transaction."); - + PrintAndLogEx(NORMAL, "* * Calc CDOL1"); struct tlv *cdol1_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x8c, NULL), tlvRoot, 0x01); // 0x01 - dummy tag if (!cdol1_data_tlv) { PrintAndLogEx(WARNING, "Error: can't create CDOL1 TLV."); dreturn(6); } - + PrintAndLogEx(NORMAL, "CDOL1 data[%d]: %s", cdol1_data_tlv->len, sprint_hex(cdol1_data_tlv->value, cdol1_data_tlv->len)); - + PrintAndLogEx(NORMAL, "* * AC1"); // EMVAC_TC + EMVAC_CDAREQ --- to get SDAD res = EMVAC(channel, true, (TrType == TT_CDA) ? EMVAC_TC + EMVAC_CDAREQ : EMVAC_TC, (uint8_t *)cdol1_data_tlv->value, cdol1_data_tlv->len, buf, sizeof(buf), &len, &sw, tlvRoot); - - if (res) { + + if (res) { PrintAndLogEx(NORMAL, "AC1 error(%d): %4x. Exit...", res, sw); free(cdol1_data_tlv); dreturn(7); @@ -1246,10 +1246,10 @@ int CmdEMVExec(const char *cmd) { uint8_t IDDlen = 0; // Issuer discretionary data length PrintAndLogEx(NORMAL, "IAD length: %d", IAD->len); PrintAndLogEx(NORMAL, "VDDlen: %d", VDDlen); - if (VDDlen < IAD->len - 1) + if (VDDlen < IAD->len - 1) IDDlen = IAD->value[VDDlen + 1]; PrintAndLogEx(NORMAL, "IDDlen: %d", IDDlen); - + uint8_t DerivKeyIndex = IAD->value[1]; CryptoVersion = IAD->value[2]; @@ -1267,22 +1267,22 @@ int CmdEMVExec(const char *cmd) { } } if (IDDlen) - PrintAndLogEx(NORMAL, "IDD: %s", sprint_hex(&IAD->value[VDDlen + 1], IDDlen)); + PrintAndLogEx(NORMAL, "IDD: %s", sprint_hex(&IAD->value[VDDlen + 1], IDDlen)); } else { PrintAndLogEx(NORMAL, "Issuer Application Data (IAD) not found."); } - + PrintAndLogEx(NORMAL, "\n* * Processing online request"); // authorization response code from acquirer const char HostResponse[] = "00"; // 0x3030 size_t HostResponseLen = sizeof(HostResponse) - 1; PrintAndLogEx(NORMAL, "Host Response: `%s`", HostResponse); - tlvdb_change_or_add_node(tlvRoot, 0x8a, HostResponseLen, (const unsigned char *)HostResponse); - + tlvdb_change_or_add_node(tlvRoot, 0x8a, HostResponseLen, (const unsigned char *)HostResponse); + if (CryptoVersion == 10) { PrintAndLogEx(NORMAL, "\n* * Generate ARPC"); - + // Application Cryptogram (AC) const struct tlv *AC = tlvdb_get(tlvRoot, 0x9f26, NULL); if (AC && (AC->len > 0)) { @@ -1294,18 +1294,18 @@ int CmdEMVExec(const char *cmd) { for (int i = 0; (i < HostResponseLen) && (i < rawARPClen); i++) rawARPC[i] ^= HostResponse[i]; PrintAndLogEx(NORMAL, "raw ARPC: %s", sprint_hex(rawARPC, rawARPClen)); - + // here must be calculation of ARPC, but we dont know a bank keys. PrintAndLogEx(NORMAL, "ARPC: n/a"); - + } else { PrintAndLogEx(NORMAL, "Application Cryptogram (AC) not found."); } // here must be external authenticate, but we dont know ARPC - + } - + // needs to send AC2 command (res == ARQC) if ((CID & EMVAC_AC_MASK) == EMVAC_ARQC) { @@ -1315,14 +1315,14 @@ int CmdEMVExec(const char *cmd) { PrintAndLogEx(WARNING, "Error: can't create CDOL2 TLV."); dreturn(6); } - + PrintAndLogEx(NORMAL, "CDOL2 data[%d]: %s", cdol2_data_tlv->len, sprint_hex(cdol2_data_tlv->value, cdol2_data_tlv->len)); - + //PrintAndLogEx(NORMAL, "* * AC2"); - - + + // here must be AC2, but we dont make external authenticate ( - + /* // AC2 PRINT_INDENT(level); if ((CID & EMVAC_AC2_MASK) == EMVAC_AAC2) fprintf(f, "\tAC2: AAC (Transaction declined)\n"); @@ -1331,11 +1331,11 @@ int CmdEMVExec(const char *cmd) { if ((CID & EMVAC_AC2_MASK) == EMVAC_AC2_MASK) fprintf(f, "\tAC2: RFU\n"); */ } - + } - + DropFieldEx( channel ); - + // Destroy TLV's free(pdol_data_tlv); tlvdb_free(tlvSelect); @@ -1355,8 +1355,8 @@ int CmdEMVScan(const char *cmd) { json_t *root; json_error_t error; - CLIParserInit("emv scan", - "Scan EMV card and save it contents to a file.", + CLIParserInit("emv scan", + "Scan EMV card and save it contents to a file.", "It executes EMV contactless transaction and saves result to a file which can be used for emulation\n" "Usage:\n\temv scan -at -> scan MSD transaction mode and show APDU and TLV\n" "\temv scan -c -> scan CDA transaction mode\n"); @@ -1378,7 +1378,7 @@ int CmdEMVScan(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + bool showAPDU = arg_get_lit(1); bool decodeTLV = arg_get_lit(2); bool extractTLVElements = arg_get_lit(3); @@ -1404,17 +1404,17 @@ int CmdEMVScan(const char *cmd) { int relfnamelen = 0; CLIGetStrWithReturn(12, relfname, &relfnamelen); CLIParserFree(); - + #ifndef WITH_SMARTCARD // not compiled with smartcard functionality, we need to exit if ( channel == ECC_CONTACT ) { PrintAndLogEx(WARNING, "PM3 Client is not compiled with support for SMARTCARD. Exiting."); return 0; } -#endif +#endif SetAPDULogging(showAPDU); - + // current path + file name if (!strstr(crelfname, ".json")) strcat(crelfname, ".json"); @@ -1426,12 +1426,12 @@ int CmdEMVScan(const char *cmd) { root = json_load_file(fname, 0, &error); if (!root) { PrintAndLogEx(ERR, "Json error on line %d: %s", error.line, error.text); - return 1; + return 1; } - + if (!json_is_object(root)) { PrintAndLogEx(ERR, "Invalid json format. root must be an object."); - return 1; + return 1; } } else { root = json_object(); @@ -1441,16 +1441,16 @@ int CmdEMVScan(const char *cmd) { DropFieldEx( channel ); JsonSaveStr(root, "$.File.Created", "proxmark3 `emv scan`"); - + if (channel == ECC_CONTACTLESS) { // iso 14443 select PrintAndLogEx(NORMAL, "--> GET UID, ATS."); - + iso14a_card_select_t card; if (Hf14443_4aGetCardData(&card)) { return 2; } - + JsonSaveStr(root, "$.Card.Contactless.Communication", "iso14443-4a"); JsonSaveBufAsHex(root, "$.Card.Contactless.UID", (uint8_t *)&card.uid, card.uidlen); JsonSaveHex(root, "$.Card.Contactless.ATQA", card.atqa[0] + (card.atqa[1] << 2), 2); @@ -1458,22 +1458,22 @@ int CmdEMVScan(const char *cmd) { JsonSaveBufAsHex(root, "$.Card.Contactless.ATS", (uint8_t *)card.ats, card.ats_len); } else { PrintAndLogEx(NORMAL, "--> GET ATR."); - + smart_card_atr_t card; smart_select(true, &card); if (!card.atr_len) { PrintAndLogEx(ERR, "Can't get ATR from a smart card."); return 1; } - + JsonSaveStr(root, "$.Card.Contact.Communication", "iso7816"); JsonSaveBufAsHex(root, "$.Card.Contact.ATR", (uint8_t *)card.atr, card.atr_len); } - + // init applets list tree const char *al = "Applets list"; struct tlvdb *tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al); - + // EMV PPSE PrintAndLogEx(NORMAL, "--> PPSE."); res = EMVSelectPSE(channel, true, true, 2, buf, sizeof(buf), &len, &sw); @@ -1481,9 +1481,9 @@ int CmdEMVScan(const char *cmd) { if (!res && sw == 0x9000){ if (decodeTLV) TLVPrintFromBuffer(buf, len); - + JsonSaveBufAsHex(root, "$.PPSE.AID", (uint8_t *)"2PAY.SYS.DDF01", 14); - + struct tlvdb *fci = tlvdb_parse_multi(buf, len); if (extractTLVElements) JsonSaveTLVTree(root, root, "$.PPSE.FCITemplate", fci); @@ -1496,8 +1496,8 @@ int CmdEMVScan(const char *cmd) { res = EMVSearchPSE(channel, false, true, psenum, decodeTLV, tlvSelect); // check PPSE and select application id - if (!res) { - TLVPrintAIDlistFromSelectTLV(tlvSelect); + if (!res) { + TLVPrintAIDlistFromSelectTLV(tlvSelect); } else { // EMV SEARCH with AID list SetAPDULogging(false); @@ -1526,7 +1526,7 @@ int CmdEMVScan(const char *cmd) { } JsonSaveBufAsHex(root, "$.Application.AID", AID, AIDlen); - + // Init TLV tree const char *alr = "Root terminal TLV tree"; struct tlvdb *tlvRoot = tlvdb_fixed(1, strlen(alr), (const unsigned char *)alr); @@ -1536,14 +1536,14 @@ int CmdEMVScan(const char *cmd) { PrintAndLogEx(NORMAL, "\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen)); SetAPDULogging(showAPDU); res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot); - - if (res) { + + if (res) { PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res); tlvdb_free(tlvRoot); DropFieldEx( channel ); return 5; } - + if (decodeTLV) TLVPrintFromBuffer(buf, len); @@ -1562,7 +1562,7 @@ int CmdEMVScan(const char *cmd) { // create transaction parameters PrintAndLogEx(NORMAL, "-->Init transaction parameters."); InitTransactionParameters(tlvRoot, paramLoadJSON, TrType, GenACGPO); - + PrintAndLogEx(NORMAL, "-->Calc PDOL."); struct tlv *pdol_data_tlv = dol_process(tlvdb_get(tlvRoot, 0x9f38, NULL), tlvRoot, 0x83); if (!pdol_data_tlv){ @@ -1571,7 +1571,7 @@ int CmdEMVScan(const char *cmd) { DropFieldEx( channel ); return 6; } - + size_t pdol_data_tlv_data_len; unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len); if (!pdol_data_tlv_data) { @@ -1584,18 +1584,18 @@ int CmdEMVScan(const char *cmd) { PrintAndLogEx(INFO, "-->GPO."); res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot); - + free(pdol_data_tlv_data); free(pdol_data_tlv); - - if (res) { + + if (res) { PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw); tlvdb_free(tlvRoot); DropFieldEx( channel ); return 7; } ProcessGPOResponseFormat1(tlvRoot, buf, len, decodeTLV); - + struct tlvdb *gpofci = tlvdb_parse_multi(buf, len); if (extractTLVElements) JsonSaveTLVTree(root, root, "$.Application.GPO", gpofci); @@ -1609,7 +1609,7 @@ int CmdEMVScan(const char *cmd) { PrintAndLogEx(INFO, "-->Read records from AFL."); const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL); - + while(AFL && AFL->len) { if (AFL->len % 4) { PrintAndLogEx(ERR, "Wrong AFL length: %d", AFL->len); @@ -1620,7 +1620,7 @@ int CmdEMVScan(const char *cmd) { if (!sfijson) { json_t *app = json_path_get(root, "$.Application"); json_object_set_new(app, "Records", json_array()); - + sfijson = json_path_get(root, "$.Application.Records"); } if (!json_is_array(sfijson)) { @@ -1632,34 +1632,34 @@ int CmdEMVScan(const char *cmd) { uint8_t SFIstart = AFL->value[i * 4 + 1]; uint8_t SFIend = AFL->value[i * 4 + 2]; uint8_t SFIoffline = AFL->value[i * 4 + 3]; - + PrintAndLogEx(INFO, "--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline); if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) { PrintAndLogEx(ERR, "SFI ERROR! Skipped..."); continue; } - + for(int n = SFIstart; n <= SFIend; n++) { PrintAndLogEx(INFO, "---->SFI[%02x] %d", SFI, n); - + res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot); if (res) { PrintAndLogEx(ERR, "SFI[%02x]. APDU error %4x", SFI, sw); continue; } - + if (decodeTLV) { TLVPrintFromBuffer(buf, len); PrintAndLog(""); } - + json_t *jsonelm = json_object(); json_array_append_new(sfijson, jsonelm); JsonSaveHex(jsonelm, "SFI", SFI, 1); JsonSaveHex(jsonelm, "RecordNum", n, 1); JsonSaveHex(jsonelm, "Offline", SFIoffline, 1); - + struct tlvdb *rsfi = tlvdb_parse_multi(buf, len); if (extractTLVElements) JsonSaveTLVTree(root, jsonelm, "$.Data", rsfi); @@ -1668,10 +1668,10 @@ int CmdEMVScan(const char *cmd) { tlvdb_free(rsfi); } } - + break; } - + // getting certificates if (tlvdb_get(tlvRoot, 0x90, NULL)) { PrintAndLogEx(INFO, "-->Recovering certificates."); @@ -1679,22 +1679,22 @@ int CmdEMVScan(const char *cmd) { RecoveryCertificates(tlvRoot, root); PKISetStrictExecution(true); } - + // free tlv object tlvdb_free(tlvRoot); DropFieldEx( channel ); - + res = json_dump_file(root, fname, JSON_INDENT(2)); if (res) { PrintAndLogEx(ERR, "Can't save the file: %s", fname); return 200; } PrintAndLogEx(SUCCESS, "File `%s` saved.", fname); - + // free json object json_decref(root); - + return 0; } @@ -1713,9 +1713,9 @@ int CmdEMVRoca(const char *cmd) { size_t len = 0; uint16_t sw = 0; int res; - - CLIParserInit("emv roca", - "Tries to extract public keys and run the ROCA test against them.\n", + + CLIParserInit("emv roca", + "Tries to extract public keys and run the ROCA test against them.\n", "Usage:\n" "\temv roca -w -> select --CONTACT-- card and run test\n" "\temv roca -> select --CONTACTLESS-- card and run test\n" @@ -1728,7 +1728,7 @@ int CmdEMVRoca(const char *cmd) { arg_param_end }; CLIExecWithReturn(cmd, argtable, true); - + EMVCommandChannel channel = ECC_CONTACTLESS; if (arg_get_lit(1)) return roca_self_test(); @@ -1737,20 +1737,20 @@ int CmdEMVRoca(const char *cmd) { channel = ECC_CONTACT; PrintChannel(channel); CLIParserFree(); - + #ifndef WITH_SMARTCARD // not compiled with smartcard functionality, we need to exit if ( channel == ECC_CONTACT ) { PrintAndLogEx(WARNING, "PM3 Client is not compiled with support for SMARTCARD. Exiting."); return 0; } -#endif +#endif // select card uint8_t psenum = (channel == ECC_CONTACT) ? 1 : 2; - + SetAPDULogging(false); - + // init applets list tree const char *al = "Applets list"; struct tlvdb *tlvSelect = tlvdb_fixed(1, strlen(al), (const unsigned char *)al); @@ -1760,8 +1760,8 @@ int CmdEMVRoca(const char *cmd) { res = EMVSearchPSE(channel, false, true, psenum, false, tlvSelect); // check PPSE and select application id - if (!res) { - TLVPrintAIDlistFromSelectTLV(tlvSelect); + if (!res) { + TLVPrintAIDlistFromSelectTLV(tlvSelect); } else { // EMV SEARCH with AID list PrintAndLogEx(NORMAL, "--> AID search."); @@ -1795,8 +1795,8 @@ int CmdEMVRoca(const char *cmd) { // EMV SELECT applet PrintAndLogEx(NORMAL, "\n-->Selecting AID:%s.", sprint_hex_inrow(AID, AIDlen)); res = EMVSelect(channel, false, true, AID, AIDlen, buf, sizeof(buf), &len, &sw, tlvRoot); - - if (res) { + + if (res) { PrintAndLogEx(ERR, "Can't select AID (%d). Exit...", res); tlvdb_free(tlvRoot); DropFieldEx( channel ); @@ -1814,7 +1814,7 @@ int CmdEMVRoca(const char *cmd) { DropFieldEx( channel ); return 6; } - + size_t pdol_data_tlv_data_len; unsigned char *pdol_data_tlv_data = tlv_encode(pdol_data_tlv, &pdol_data_tlv_data_len); if (!pdol_data_tlv_data) { @@ -1828,21 +1828,21 @@ int CmdEMVRoca(const char *cmd) { PrintAndLogEx(INFO, "-->GPO."); res = EMVGPO(channel, true, pdol_data_tlv_data, pdol_data_tlv_data_len, buf, sizeof(buf), &len, &sw, tlvRoot); - + free(pdol_data_tlv_data); free(pdol_data_tlv); - - if (res) { + + if (res) { PrintAndLogEx(ERR, "GPO error(%d): %4x. Exit...", res, sw); tlvdb_free(tlvRoot); DropFieldEx( channel ); return 7; } ProcessGPOResponseFormat1(tlvRoot, buf, len, false); - + PrintAndLogEx(INFO, "-->Read records from AFL."); const struct tlv *AFL = tlvdb_get(tlvRoot, 0x94, NULL); - + while(AFL && AFL->len) { if (AFL->len % 4) { PrintAndLogEx(ERR, "Wrong AFL length: %d", AFL->len); @@ -1854,16 +1854,16 @@ int CmdEMVRoca(const char *cmd) { uint8_t SFIstart = AFL->value[i * 4 + 1]; uint8_t SFIend = AFL->value[i * 4 + 2]; uint8_t SFIoffline = AFL->value[i * 4 + 3]; - + PrintAndLogEx(INFO, "--->SFI[%02x] start:%02x end:%02x offline:%02x", SFI, SFIstart, SFIend, SFIoffline); if (SFI == 0 || SFI == 31 || SFIstart == 0 || SFIstart > SFIend) { PrintAndLogEx(ERR, "SFI ERROR! Skipped..."); continue; } - + for(int n = SFIstart; n <= SFIend; n++) { PrintAndLogEx(INFO, "---->SFI[%02x] %d", SFI, n); - + res = EMVReadRecord(channel, true, SFI, n, buf, sizeof(buf), &len, &sw, tlvRoot); if (res) { PrintAndLogEx(ERR, "SFI[%02x]. APDU error %4x", SFI, sw); @@ -1871,7 +1871,7 @@ int CmdEMVRoca(const char *cmd) { } } } - + break; } @@ -1892,7 +1892,7 @@ int CmdEMVRoca(const char *cmd) { PrintAndLogEx(WARNING, "WARNING: Issuer certificate not found. Exit."); goto out; } - + PrintAndLogEx(SUCCESS, "Issuer PK recovered. RID %s IDX %02hhx CSN %s", sprint_hex(issuer_pk->rid, 5), issuer_pk->index, @@ -1912,9 +1912,9 @@ int CmdEMVRoca(const char *cmd) { icc_pk->index, sprint_hex(icc_pk->serial, 3) ); - + PrintAndLogEx(INFO, "ICC pk modulus: %s", sprint_hex_inrow(icc_pk->modulus, icc_pk->mlen)); - + // icc_pk->exp, icc_pk->elen // icc_pk->modulus, icc_pk->mlen if (icc_pk->elen > 0 && icc_pk->mlen > 0) { @@ -1923,13 +1923,13 @@ int CmdEMVRoca(const char *cmd) { } else { PrintAndLogEx(INFO, "ICC pk is OK("); } - } - + } + PKISetStrictExecution(true); } out: - + // free tlv object tlvdb_free(tlvRoot); @@ -1951,14 +1951,14 @@ static command_t CommandTable[] = { {"scan", CmdEMVScan, 0, "Scan EMV card and save it contents to json file for emulator."}, {"test", CmdEMVTest, 0, "Crypto logic test."}, /* - {"getrng", CmdEMVGetrng, 0, "get random number from terminal"}, + {"getrng", CmdEMVGetrng, 0, "get random number from terminal"}, {"eload", CmdEmvELoad, 0, "load EMV tag into device"}, {"dump", CmdEmvDump, 0, "dump EMV tag values"}, {"sim", CmdEmvSim, 0, "simulate EMV tag"}, - {"clone", CmdEmvClone, 0, "clone an EMV tag"}, + {"clone", CmdEmvClone, 0, "clone an EMV tag"}, */ - {"list", CmdEMVList, 0, "[Deprecated] List ISO7816 history"}, - {"roca", CmdEMVRoca, 0, "Extract public keys and run ROCA test"}, + {"list", CmdEMVList, 0, "[Deprecated] List ISO7816 history"}, + {"roca", CmdEMVRoca, 0, "Extract public keys and run ROCA test"}, {NULL, NULL, 0, NULL} }; diff --git a/client/emv/crypto.c b/client/emv/crypto.c index c8ced6d43..d8ec5fc08 100644 --- a/client/emv/crypto.c +++ b/client/emv/crypto.c @@ -29,7 +29,7 @@ static bool crypto_init(void) if (crypto_backend) return true; - crypto_backend = crypto_polarssl_init(); + crypto_backend = crypto_polarssl_init(); if (!crypto_backend) return false; diff --git a/client/emv/crypto_polarssl.c b/client/emv/crypto_polarssl.c index 938535059..f04b6c9e5 100644 --- a/client/emv/crypto_polarssl.c +++ b/client/emv/crypto_polarssl.c @@ -98,11 +98,11 @@ static struct crypto_pk *crypto_pk_polarssl_open_rsa(va_list vl) int explen = va_arg(vl, size_t); mbedtls_rsa_init(&cp->ctx, MBEDTLS_RSA_PKCS_V15, 0); - + cp->ctx.len = modlen; // size(N) in bytes mbedtls_mpi_read_binary(&cp->ctx.N, (const unsigned char *)mod, modlen); mbedtls_mpi_read_binary(&cp->ctx.E, (const unsigned char *)exp, explen); - + int res = mbedtls_rsa_check_pubkey(&cp->ctx); if(res != 0) { fprintf(stderr, "PolarSSL public key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen); @@ -133,10 +133,10 @@ static struct crypto_pk *crypto_pk_polarssl_open_priv_rsa(va_list vl) int dqlen = va_arg(vl, size_t); // calc QP via Q and P // char *inv = va_arg(vl, char *); -// int invlen = va_arg(vl, size_t); - +// int invlen = va_arg(vl, size_t); + mbedtls_rsa_init(&cp->ctx, MBEDTLS_RSA_PKCS_V15, 0); - + cp->ctx.len = modlen; // size(N) in bytes mbedtls_mpi_read_binary(&cp->ctx.N, (const unsigned char *)mod, modlen); mbedtls_mpi_read_binary(&cp->ctx.E, (const unsigned char *)exp, explen); @@ -147,7 +147,7 @@ static struct crypto_pk *crypto_pk_polarssl_open_priv_rsa(va_list vl) mbedtls_mpi_read_binary(&cp->ctx.DP, (const unsigned char *)dp, dplen); mbedtls_mpi_read_binary(&cp->ctx.DQ, (const unsigned char *)dq, dqlen); mbedtls_mpi_inv_mod(&cp->ctx.QP, &cp->ctx.Q, &cp->ctx.P); - + int res = mbedtls_rsa_check_privkey(&cp->ctx); if(res != 0) { fprintf(stderr, "PolarSSL private key error res=%x exp=%d mod=%d.\n", res * -1, explen, modlen); @@ -166,7 +166,7 @@ static int myrand(void *rng_state, unsigned char *output, size_t len) { for( i = 0; i < len; ++i ) output[i] = rand(); - + return 0; } @@ -175,21 +175,21 @@ static struct crypto_pk *crypto_pk_polarssl_genkey_rsa(va_list vl) { struct crypto_pk_polarssl *cp = malloc(sizeof(*cp)); memset(cp, 0x00, sizeof(*cp)); - + int transient = va_arg(vl, int); unsigned int nbits = va_arg(vl, unsigned int); unsigned int exp = va_arg(vl, unsigned int); if (transient) { } - + int res = mbedtls_rsa_gen_key(&cp->ctx, &myrand, NULL, nbits, exp); if (res) { fprintf(stderr, "PolarSSL private key generation error res=%x exp=%d nbits=%d.\n", res * -1, exp, nbits); free(cp); return NULL; } - + return &cp->cp; } @@ -206,7 +206,7 @@ static unsigned char *crypto_pk_polarssl_encrypt(const struct crypto_pk *_cp, co struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp; int res; unsigned char *result; - + *clen = 0; size_t keylen = mbedtls_mpi_size(&cp->ctx.N); @@ -222,9 +222,9 @@ static unsigned char *crypto_pk_polarssl_encrypt(const struct crypto_pk *_cp, co free(result); return NULL; } - + *clen = keylen; - + return result; } @@ -233,7 +233,7 @@ static unsigned char *crypto_pk_polarssl_decrypt(const struct crypto_pk *_cp, co struct crypto_pk_polarssl *cp = (struct crypto_pk_polarssl *)_cp; int res; unsigned char *result; - + *clen = 0; size_t keylen = mbedtls_mpi_size(&cp->ctx.N); @@ -249,9 +249,9 @@ static unsigned char *crypto_pk_polarssl_decrypt(const struct crypto_pk *_cp, co free(result); return NULL; } - + *clen = keylen; - + return result; } @@ -286,7 +286,7 @@ static unsigned char *crypto_pk_polarssl_get_parameter(const struct crypto_pk *_ printf("Error get parameter. Param=%d", param); break; } - + return result; } diff --git a/client/emv/emv_pk.c b/client/emv/emv_pk.c index 091ab8062..211e4edc2 100644 --- a/client/emv/emv_pk.c +++ b/client/emv/emv_pk.c @@ -486,7 +486,7 @@ struct emv_pk *emv_pk_get_ca_pk(const unsigned char *rid, unsigned char idx) } */ if (!pk) { - const char *relfname = "emv/capk.txt"; + const char *relfname = "emv/capk.txt"; char fname[strlen(get_my_executable_directory()) + strlen(relfname) + 1]; strcpy(fname, get_my_executable_directory()); diff --git a/client/emv/emv_pki.c b/client/emv/emv_pki.c index 84224a957..2c661f11a 100644 --- a/client/emv/emv_pki.c +++ b/client/emv/emv_pki.c @@ -75,7 +75,7 @@ static unsigned char *emv_pki_decode_message(const struct emv_pk *enc_pk, printf("Recovered data:\n"); dump_buffer(data, data_len, stdout, 0); }*/ - + if (data[data_len-1] != 0xbc || data[0] != 0x6a || data[1] != msgtype) { printf("ERROR: Certificate format\n"); free(data); @@ -117,7 +117,7 @@ static unsigned char *emv_pki_decode_message(const struct emv_pk *enc_pk, printf("ERROR: Calculated wrong hash\n"); printf("decoded: %s\n",sprint_hex(data + data_len - 1 - hash_len, hash_len)); printf("calculated: %s\n",sprint_hex(hash, hash_len)); - + if (strictExecution) { crypto_hash_close(ch); free(data); @@ -206,7 +206,7 @@ static struct emv_pk *emv_pki_decode_key_ex(const struct emv_pk *enc_pk, return NULL; } - if (showData){ + if (showData){ printf("Recovered data:\n"); dump_buffer(data, data_len, stdout, 0); } @@ -308,7 +308,7 @@ struct emv_pk *emv_pki_recover_icc_cert(const struct emv_pk *pk, struct tlvdb *d .len = sdatl_len, .value = sdatl }; - + struct emv_pk *res = emv_pki_decode_key(pk, 4, tlvdb_get(db, 0x5a, NULL), tlvdb_get(db, 0x9f46, NULL), @@ -316,7 +316,7 @@ struct emv_pk *emv_pki_recover_icc_cert(const struct emv_pk *pk, struct tlvdb *d tlvdb_get(db, 0x9f48, NULL), sda_tlv, &sda_tdata); - + free(sdatl); // malloc here: emv_pki_sdatl_fill return res; } @@ -335,9 +335,9 @@ struct emv_pk *emv_pki_recover_icc_pe_cert(const struct emv_pk *pk, struct tlvdb unsigned char *emv_pki_sdatl_fill(const struct tlvdb *db, size_t *sdatl_len) { uint8_t buf[2048] = {0}; size_t len = 0; - + *sdatl_len = 0; - + const struct tlv *sda_tl = tlvdb_get(db, 0x9f4a, NULL); if (!sda_tl || sda_tl->len <= 0) return NULL; @@ -348,16 +348,16 @@ unsigned char *emv_pki_sdatl_fill(const struct tlvdb *db, size_t *sdatl_len) { if (elm) { memcpy(&buf[len], elm->value, elm->len); len += elm->len; - } + } } - + if (len) { *sdatl_len = len; unsigned char *value = malloc(len); memcpy(value, buf, len); return value; } - + return NULL; } @@ -365,7 +365,7 @@ unsigned char *emv_pki_sdatl_fill(const struct tlvdb *db, size_t *sdatl_len) { struct tlvdb *emv_pki_recover_dac_ex(const struct emv_pk *enc_pk, const struct tlvdb *db, const struct tlv *sda_tlv, bool showData) { size_t data_len; - + // Static Data Authentication Tag List size_t sdatl_len; unsigned char *sdatl = emv_pki_sdatl_fill(db, &sdatl_len); @@ -383,7 +383,7 @@ struct tlvdb *emv_pki_recover_dac_ex(const struct emv_pk *enc_pk, const struct t NULL); free(sdatl); // malloc here: emv_pki_sdatl_fill - + if (!data || data_len < 5) return NULL; @@ -436,7 +436,7 @@ struct tlvdb *emv_pki_recover_idn_ex(const struct emv_pk *enc_pk, const struct t // 9f4c ICC Dynamic Number struct tlvdb *idn_db = tlvdb_fixed(0x9f4c, idn_len, data + 5); - + free(data); return idn_db; @@ -475,7 +475,7 @@ struct tlvdb *emv_pki_recover_atc_ex(const struct emv_pk *enc_pk, const struct t // 9f36 Application Transaction Counter (ATC) struct tlvdb *atc_db = tlvdb_fixed(0x9f36, idn_len, data + 5); - + free(data); return atc_db; diff --git a/client/emv/emv_roca.c b/client/emv/emv_roca.c index 6f90f11b5..f98117450 100644 --- a/client/emv/emv_roca.c +++ b/client/emv/emv_roca.c @@ -3,7 +3,7 @@ * Copyright (C) 2017-2018 Sectigo Limited * modified 2018 iceman (dropped openssl bignum, now use mbedtls lib) * modified 2018 merlok - * + * * 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 @@ -30,10 +30,10 @@ static uint8_t g_primes[ROCA_PRINTS_LENGTH] = { mbedtls_mpi g_prints[ROCA_PRINTS_LENGTH]; void rocacheck_init(void) { - + for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) mbedtls_mpi_init(&g_prints[i]); - + mbedtls_mpi_read_string(&g_prints[0], 10, "1026"); mbedtls_mpi_read_string(&g_prints[1], 10, "5658"); mbedtls_mpi_read_string(&g_prints[2], 10, "107286"); @@ -61,7 +61,7 @@ void rocacheck_cleanup(void) { int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ) { for (int i = 0; i < mbedtls_mpi_bitlen(a); i++) { - + if (mbedtls_mpi_get_bit(a, i) && mbedtls_mpi_get_bit(b, i)) return 0; } @@ -70,7 +70,7 @@ int bitand_is_zero( mbedtls_mpi* a, mbedtls_mpi* b ) { mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) { - + if (X->n == 1 && X->s > 0) { return X->p[0]; } @@ -79,12 +79,12 @@ mbedtls_mpi_uint mpi_get_uint(const mbedtls_mpi *X) { } void print_mpi(const char *msg, int radix, const mbedtls_mpi *X) { - + char Xchar[400] = {0}; size_t len = 0; - - mbedtls_mpi_write_string(X, radix, Xchar, sizeof(Xchar), &len); - printf("%s[%d] %s\n", msg, len, Xchar); + + mbedtls_mpi_write_string(X, radix, Xchar, sizeof(Xchar), &len); + printf("%s[%d] %s\n", msg, len, Xchar); } bool emv_rocacheck(const unsigned char *buf, size_t buflen, bool verbose) { @@ -97,13 +97,13 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen, bool verbose) { rocacheck_init(); MBEDTLS_MPI_CHK( mbedtls_mpi_read_binary(&t_modulus, buf, buflen) ); - + for (int i = 0; i < ROCA_PRINTS_LENGTH; i++) { mbedtls_mpi t_temp; mbedtls_mpi t_prime; mbedtls_mpi g_one; - + mbedtls_mpi_init(&t_temp); mbedtls_mpi_init(&t_prime); mbedtls_mpi_init(&g_one); @@ -111,18 +111,18 @@ bool emv_rocacheck(const unsigned char *buf, size_t buflen, bool verbose) { MBEDTLS_MPI_CHK( mbedtls_mpi_read_string(&g_one, 10, "1") ); MBEDTLS_MPI_CHK( mbedtls_mpi_add_int(&t_prime, &t_prime, g_primes[i]) ); - - MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi(&t_temp, &t_modulus, &t_prime) ); - + + MBEDTLS_MPI_CHK( mbedtls_mpi_mod_mpi(&t_temp, &t_modulus, &t_prime) ); + MBEDTLS_MPI_CHK( mbedtls_mpi_shift_l(&g_one, mpi_get_uint(&t_temp)) ); - + if (bitand_is_zero(&g_one, &g_prints[i])) { if (verbose) PrintAndLogEx(FAILED, "No fingerprint found.\n"); goto cleanup; } - - mbedtls_mpi_free(&g_one); + + mbedtls_mpi_free(&g_one); mbedtls_mpi_free(&t_temp); mbedtls_mpi_free(&t_prime); } @@ -149,9 +149,9 @@ int roca_self_test(void) { "\x27\x83\x30\xd3\xf4\x71\xa2\x53\x8f\xa6\x67\x80\x2e\xd2\xa3\xc4"\ "\x4a\x8b\x7d\xea\x82\x6e\x88\x8d\x0a\xa3\x41\xfd\x66\x4f\x7f\xa7"; - + if (emv_rocacheck(keyp, 64, false)) { - PrintAndLogEx(SUCCESS, "Weak modulus [ %s]", _GREEN_(PASS) ); + PrintAndLogEx(SUCCESS, "Weak modulus [ %s]", _GREEN_(PASS) ); } else { ret++; @@ -168,8 +168,8 @@ int roca_self_test(void) { ret++; PrintAndLogEx(FAILED, "Strong modulus [ %s]", _RED_(FAIL) ); } else { - PrintAndLogEx(SUCCESS, "Strong modulus [ %s]", _GREEN_(PASS) ); + PrintAndLogEx(SUCCESS, "Strong modulus [ %s]", _GREEN_(PASS) ); } - + return ret; } diff --git a/client/emv/emv_roca.h b/client/emv/emv_roca.h index 9e12e4256..b37d4de14 100644 --- a/client/emv/emv_roca.h +++ b/client/emv/emv_roca.h @@ -3,7 +3,7 @@ * Copyright (C) 2017-2018 Sectigo Limited * modified 2018 iceman (dropped openssl bignum, now use mbedtls lib) * modified 2018 merlok - * + * * 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 diff --git a/client/emv/emv_tags.c b/client/emv/emv_tags.c index 521598b67..2cad81397 100644 --- a/client/emv/emv_tags.c +++ b/client/emv/emv_tags.c @@ -199,13 +199,13 @@ static const struct emv_tag emv_tags[] = { { 0x5f2d, "Language Preference", EMV_TAG_STRING }, { 0x5f30, "Service Code", EMV_TAG_NUMERIC }, { 0x5f34, "Application Primary Account Number (PAN) Sequence Number", EMV_TAG_NUMERIC }, - { 0x5f36, "Transaction Currency Exponent", EMV_TAG_NUMERIC }, + { 0x5f36, "Transaction Currency Exponent", EMV_TAG_NUMERIC }, { 0x5f50, "Issuer URL", EMV_TAG_STRING }, { 0x5f53, "International Bank Account Number (IBAN)" }, { 0x5f54, "Bank Identifier Code (BIC)" }, { 0x5f55, "Issuer Country Code (alpha2 format)", EMV_TAG_STRING }, { 0x5f56, "Issuer Country Code (alpha3 format)", EMV_TAG_STRING }, - + { 0x61 , "Application Template" }, { 0x6f , "File Control Information (FCI) Template" }, { 0x70 , "READ RECORD Response Message Template" }, @@ -240,7 +240,7 @@ static const struct emv_tag emv_tags[] = { { 0x9b , "Transaction Status Information" }, { 0x9c , "Transaction Type", EMV_TAG_NUMERIC }, { 0x9d , "Directory Definition File (DDF) Name" }, - + { 0x9f01, "Acquirer Identifier", EMV_TAG_NUMERIC }, { 0x9f02, "Amount, Authorised (Numeric)", EMV_TAG_NUMERIC }, { 0x9f03, "Amount, Other (Numeric)", EMV_TAG_NUMERIC }, @@ -268,10 +268,10 @@ static const struct emv_tag emv_tags[] = { { 0x9f1b, "Terminal Floor Limit" }, { 0x9f1c, "Terminal Identification", EMV_TAG_STRING }, { 0x9f1d, "Terminal Risk Management Data" }, - { 0x9f1e, "Interface Device (IFD) Serial Number", EMV_TAG_STRING }, + { 0x9f1e, "Interface Device (IFD) Serial Number", EMV_TAG_STRING }, { 0x9f1f, "Track 1 Discretionary Data", EMV_TAG_STRING }, { 0x9f20, "Track 2 Discretionary Data", EMV_TAG_STRING }, - { 0x9f21, "Transaction Time" }, + { 0x9f21, "Transaction Time" }, { 0x9f22, "Certification Authority Public Key Index - Terminal" }, { 0x9f23, "Upper Consecutive Offline Limit" }, { 0x9f26, "Application Cryptogram" }, @@ -308,20 +308,20 @@ static const struct emv_tag emv_tags[] = { { 0x9f4d, "Log Entry" }, { 0x9f4e, "Merchant Name and Location", EMV_TAG_STRING }, { 0x9f4f, "Log Format", EMV_TAG_DOL }, - + { 0x9f50, "Offline Accumulator Balance" }, { 0x9f51, "Application Currency Code" }, { 0x9f51, "DRDOL" }, { 0x9f52, "Application Default Action (ADA)" }, { 0x9f52, "Terminal Compatibility Indicator" }, - + { 0x9f53, "Transaction Category Code" }, { 0x9f54, "DS ODS Card" }, - - { 0x9f55, "Mobile Support Indicator" }, + + { 0x9f55, "Mobile Support Indicator" }, { 0x9f55, "Issuer Authentication Flags" }, - + { 0x9f56, "Issuer Authentication Indicator" }, { 0x9f57, "Issuer Country Code" }, { 0x9f58, "Consecutive Transaction Counter Limit (CTCL)" }, @@ -332,7 +332,7 @@ static const struct emv_tag emv_tags[] = { { 0x9f5d, "Application Capabilities Information" }, { 0x9f5e, "Data Storage Identifier" }, { 0x9f5f, "DS Slot Availability" }, - + { 0x9f60, "CVC3 (Track1)" }, { 0x9f61, "CVC3 (Track2)" }, { 0x9f62, "PCVC3 (Track1)" }, @@ -421,7 +421,7 @@ static const struct emv_tag emv_tags[] = { { 0xff8103, "Tags To Write After Gen AC" }, { 0xff8104, "Data To Send" }, { 0xff8105, "Data Record" }, - { 0xff8106, "Discretionary Data" }, + { 0xff8106, "Discretionary Data" }, }; static int emv_sort_tag(tlv_tag_t tag) { @@ -554,13 +554,13 @@ static void emv_tag_dump_cvr(const struct tlv *tlv, const struct emv_tag *tag, F fprintf(f, "\tINVALID!\n"); return; } - + if (tlv->len != tlv->value[0] + 1) { PRINT_INDENT(level); fprintf(f, "\tINVALID length!\n"); return; } - + if (tlv->len >= 2) { // AC1 PRINT_INDENT(level); @@ -587,7 +587,7 @@ static void emv_tag_dump_cvr(const struct tlv *tlv, const struct emv_tag *tag, F PRINT_INDENT(level); fprintf(f, "\tSuccessfully processed issuer script commands: %x\n", tlv->value[4] >> 4); } - + // mask 0F 0F F0 0F uint8_t data[20] = {0}; memcpy(data, &tlv->value[1], tlv->len - 1); @@ -606,7 +606,7 @@ static void emv_tag_dump_cvr(const struct tlv *tlv, const struct emv_tag *tag, F .type = EMV_TAG_BITMASK, .data = EMV_CVR, }; - + if (data[0] || data[1] || data[2] || data[3]) emv_tag_dump_bitmask(&bit_tlv, &bit_tag, f, level); } @@ -618,7 +618,7 @@ static void emv_tag_dump_cid(const struct tlv *tlv, const struct emv_tag *tag, F fprintf(f, "\tINVALID!\n"); return; } - + PRINT_INDENT(level); if ((tlv->value[0] & EMVAC_AC_MASK) == EMVAC_AAC) fprintf(f, "\tAC1: AAC (Transaction declined)\n"); if ((tlv->value[0] & EMVAC_AC_MASK) == EMVAC_TC) fprintf(f, "\tAC1: TC (Transaction approved)\n"); @@ -757,7 +757,7 @@ static void emv_tag_dump_afl(const struct tlv *tlv, const struct emv_tag *tag, F fprintf(f, "\tINVALID!\n"); return; } - + for (int i = 0; i < tlv->len / 4; i++) { PRINT_INDENT(level); fprintf(f, "SFI[%02x] start:%02x end:%02x offline:%02x\n", tlv->value[i * 4 + 0] >> 3, tlv->value[i * 4 + 1], tlv->value[i * 4 + 2], tlv->value[i * 4 + 3]); @@ -819,13 +819,13 @@ bool emv_tag_dump(const struct tlv *tlv, FILE *f, int level) { char *emv_get_tag_name(const struct tlv *tlv) { static char *defstr = ""; - - if (!tlv) + + if (!tlv) return defstr; const struct emv_tag *tag = emv_get_tag(tlv); if (tag) return tag->name; - + return defstr; } diff --git a/client/emv/emvcore.c b/client/emv/emvcore.c index 7af08690c..796fc22ea 100644 --- a/client/emv/emvcore.c +++ b/client/emv/emvcore.c @@ -14,7 +14,7 @@ // Got from here. Thanks) // https://eftlab.co.uk/index.php/site-map/knowledge-base/211-emv-aid-rid-pix -static const char *PSElist [] = { +static const char *PSElist [] = { "325041592E5359532E4444463031", // 2PAY.SYS.DDF01 - Visa Proximity Payment System Environment - PPSE "315041592E5359532E4444463031" // 1PAY.SYS.DDF01 - Visa Payment System Environment - PSE }; @@ -32,28 +32,28 @@ typedef struct { const char* aid; } TAIDList; -static const TAIDList AIDlist [] = { +static const TAIDList AIDlist [] = { // Visa International - { CV_VISA, "A00000000305076010"}, // VISA ELO Credit - { CV_VISA, "A0000000031010" }, // VISA Debit/Credit (Classic) - { CV_VISA, "A000000003101001" }, // VISA Credit - { CV_VISA, "A000000003101002" }, // VISA Debit + { CV_VISA, "A00000000305076010"}, // VISA ELO Credit + { CV_VISA, "A0000000031010" }, // VISA Debit/Credit (Classic) + { CV_VISA, "A000000003101001" }, // VISA Credit + { CV_VISA, "A000000003101002" }, // VISA Debit { CV_VISA, "A0000000032010" }, // VISA Electron - { CV_VISA, "A0000000032020" }, // VISA - { CV_VISA, "A0000000033010" }, // VISA Interlink - { CV_VISA, "A0000000034010" }, // VISA Specific - { CV_VISA, "A0000000035010" }, // VISA Specific - { CV_VISA, "A0000000036010" }, // Domestic Visa Cash Stored Value - { CV_VISA, "A0000000036020" }, // International Visa Cash Stored Value - { CV_VISA, "A0000000038002" }, // VISA Auth, VisaRemAuthen EMV-CAP (DPA) - { CV_VISA, "A0000000038010" }, // VISA Plus - { CV_VISA, "A0000000039010" }, // VISA Loyalty - { CV_VISA, "A000000003999910" }, // VISA Proprietary ATM + { CV_VISA, "A0000000032020" }, // VISA + { CV_VISA, "A0000000033010" }, // VISA Interlink + { CV_VISA, "A0000000034010" }, // VISA Specific + { CV_VISA, "A0000000035010" }, // VISA Specific + { CV_VISA, "A0000000036010" }, // Domestic Visa Cash Stored Value + { CV_VISA, "A0000000036020" }, // International Visa Cash Stored Value + { CV_VISA, "A0000000038002" }, // VISA Auth, VisaRemAuthen EMV-CAP (DPA) + { CV_VISA, "A0000000038010" }, // VISA Plus + { CV_VISA, "A0000000039010" }, // VISA Loyalty + { CV_VISA, "A000000003999910" }, // VISA Proprietary ATM // Visa USA { CV_VISA, "A000000098" }, // Debit Card { CV_VISA, "A0000000980848" }, // Debit Card // Mastercard International - { CV_MASTERCARD, "A00000000401" }, // MasterCard PayPass + { CV_MASTERCARD, "A00000000401" }, // MasterCard PayPass { CV_MASTERCARD, "A0000000041010" }, // MasterCard Credit { CV_MASTERCARD, "A00000000410101213" }, // MasterCard Credit { CV_MASTERCARD, "A00000000410101215" }, // MasterCard Credit @@ -65,7 +65,7 @@ static const TAIDList AIDlist [] = { { CV_MASTERCARD, "A0000000045010" }, // MasterCard Specific { CV_MASTERCARD, "A0000000046000" }, // Cirrus { CV_MASTERCARD, "A0000000048002" }, // SecureCode Auth EMV-CAP - { CV_MASTERCARD, "A0000000049999" }, // MasterCard PayPass + { CV_MASTERCARD, "A0000000049999" }, // MasterCard PayPass // American Express { CV_AMERICANEXPRESS, "A000000025" }, { CV_AMERICANEXPRESS, "A0000000250000" }, @@ -74,14 +74,14 @@ static const TAIDList AIDlist [] = { { CV_AMERICANEXPRESS, "A000000025010701" }, { CV_AMERICANEXPRESS, "A000000025010801" }, // Groupement des Cartes Bancaires "CB" - { CV_CB, "A0000000421010" }, // Cartes Bancaire EMV Card - { CV_CB, "A0000000422010" }, - { CV_CB, "A0000000423010" }, - { CV_CB, "A0000000424010" }, - { CV_CB, "A0000000425010" }, + { CV_CB, "A0000000421010" }, // Cartes Bancaire EMV Card + { CV_CB, "A0000000422010" }, + { CV_CB, "A0000000423010" }, + { CV_CB, "A0000000424010" }, + { CV_CB, "A0000000425010" }, // JCB CO., LTD. - { CV_JCB, "A00000006510" }, // JCB - { CV_JCB, "A0000000651010" }, // JCB J Smart Credit + { CV_JCB, "A00000006510" }, // JCB + { CV_JCB, "A0000000651010" }, // JCB J Smart Credit // Other { CV_OTHER, "A0000001544442" }, // Banricompras Debito - Banrisul - Banco do Estado do Rio Grande do SUL - S.A. { CV_OTHER, "F0000000030001" }, // BRADESCO @@ -106,8 +106,8 @@ enum CardPSVendor GetCardPSVendor(uint8_t * AID, size_t AIDlen) { if (strncmp(AIDlist[i].aid, buf, strlen(AIDlist[i].aid)) == 0){ return AIDlist[i].vendor; } - } - + } + return CV_NA; } @@ -125,7 +125,7 @@ bool TLVPrintFromBuffer(uint8_t *data, int datalen) { t = tlvdb_parse_multi(data, datalen); if (t) { PrintAndLogEx(NORMAL, "-------------------- TLV decoded --------------------"); - + tlvdb_visit(t, print_cb, NULL, 0); tlvdb_free(t); return true; @@ -136,9 +136,9 @@ bool TLVPrintFromBuffer(uint8_t *data, int datalen) { } void TLVPrintFromTLVLev(struct tlvdb *tlv, int level) { - if (!tlv) + if (!tlv) return; - + tlvdb_visit(tlv, print_cb, NULL, level); } @@ -154,18 +154,18 @@ void TLVPrintAIDlistFromSelectTLV(struct tlvdb *tlv) { struct tlvdb *ttmp = tlvdb_find(tlv, 0x6f); if (!ttmp) PrintAndLogEx(NORMAL, "| none |"); - + while (ttmp) { const struct tlv *tgAID = tlvdb_get_inchild(ttmp, 0x84, NULL); const struct tlv *tgName = tlvdb_get_inchild(ttmp, 0x50, NULL); const struct tlv *tgPrio = tlvdb_get_inchild(ttmp, 0x87, NULL); if (!tgAID) break; - PrintAndLogEx(NORMAL, "|%s| %s |%s|", - sprint_hex_inrow_ex(tgAID->value, tgAID->len, 18), - (tgPrio) ? sprint_hex(tgPrio->value, 1) : " ", + PrintAndLogEx(NORMAL, "|%s| %s |%s|", + sprint_hex_inrow_ex(tgAID->value, tgAID->len, 18), + (tgPrio) ? sprint_hex(tgPrio->value, 1) : " ", (tgName) ? sprint_ascii_ex(tgName->value, tgName->len, 25) : " "); - + ttmp = tlvdb_find_next(ttmp, 0x6f); } @@ -183,19 +183,19 @@ struct tlvdb *GetPANFromTrack2(const struct tlv *track2) { for (int i = 0; i < track2->len; ++i, tmp += 2) sprintf(tmp, "%02x", (unsigned int)track2->value[i]); - + int posD = strchr(track2Hex, 'd') - track2Hex; if (posD < 1) return NULL; - + track2Hex[posD] = 0; if (strlen(track2Hex) % 2) { track2Hex[posD] = 'F'; track2Hex[posD + 1] = '\0'; } - + param_gethex_to_eol(track2Hex, 0, PAN, sizeof(PAN), &PANlen); - + return tlvdb_fixed(0x5a, PANlen, PAN); } @@ -206,13 +206,13 @@ struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2) { int dCVVlen = 0; const int PINlen = 5; // must calculated from 9F67 MSD Offset but i have not seen this tag) char *tmp = track2Hex; - + if (!track2) return NULL; - + for (int i = 0; i < track2->len; ++i, tmp += 2) sprintf(tmp, "%02x", (unsigned int)track2->value[i]); - + int posD = strchr(track2Hex, 'd') - track2Hex; if (posD < 1) return NULL; @@ -226,9 +226,9 @@ struct tlvdb *GetdCVVRawFromTrack2(const struct tlv *track2) { memcpy(dCVVHex + 9, track2Hex + posD + 1, 4); // service code memcpy(dCVVHex + 13, track2Hex + posD + 5, 3); - + param_gethex_to_eol(dCVVHex, 0, dCVV, sizeof(dCVV), &dCVVlen); - + return tlvdb_fixed(0x02, dCVVlen, dCVV); } @@ -239,17 +239,17 @@ int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveField if (sw) *sw = 0; uint16_t isw = 0; int res = 0; - + if (ActivateField) { DropFieldEx( channel ); msleep(50); } - + // COMPUTE APDU memcpy(data, &apdu, 5); if (apdu.data) memcpy(&data[5], apdu.data, apdu.Lc); - + if (APDULogging) PrintAndLogEx(SUCCESS, ">>>> %s", sprint_hex(data, (IncludeLe?6:5) + apdu.Lc)); @@ -262,24 +262,24 @@ int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveField } break; case ECC_CONTACT: -#ifdef WITH_SMARTCARD +#ifdef WITH_SMARTCARD res = ExchangeAPDUSC(data, (IncludeLe?6:5) + apdu.Lc, ActivateField, LeaveFieldON, Result, (int)MaxResultLen, (int *)ResultLen); #else res = 1; -#endif +#endif if (res) { return res; } break; } - + if (APDULogging) PrintAndLogEx(SUCCESS, "<<<< %s", sprint_hex(Result, *ResultLen)); if (*ResultLen < 2) { return 200; } - + *ResultLen -= 2; isw = Result[*ResultLen] * 0x0100 + Result[*ResultLen + 1]; if (sw) @@ -301,7 +301,7 @@ int EMVExchangeEx(EMVCommandChannel channel, bool ActivateField, bool LeaveField struct tlvdb *t = tlvdb_parse_multi(Result, *ResultLen); tlvdb_add(tlv, t); } - + return 0; } @@ -328,7 +328,7 @@ int EMVSelectPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO default: return -1; } - + // select res = EMVSelect(channel, ActivateField, LeaveFieldON, buf, len, Result, MaxResultLen, ResultLen, sw, NULL); @@ -351,11 +351,11 @@ int EMVSelectWithRetry(EMVCommandChannel channel, bool ActivateField, bool Leave PrintAndLogEx(WARNING, "Exit..."); return 1; } - + retrycnt = 0; PrintAndLogEx(NORMAL, "Retry failed [%s]. Skiped...", sprint_hex_inrow(AID, AIDLen)); return res; - } + } } } while (res && res != 5); @@ -379,7 +379,7 @@ int EMVCheckAID(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlvdbel tlvdbelm = tlvdb_find_next(tlvdbelm, 0x61); continue; } - + if (res) break; @@ -411,7 +411,7 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO PrintAndLogEx(FAILED, "Select PSE error. APDU error: %04x.", sw); return 1; } - + struct tlvdb *t = NULL; t = tlvdb_parse_multi(data, datalen); if (t) { @@ -421,18 +421,18 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO uint8_t sfin = 0; tlv_get_uint8(tlvdb_get_tlv(tsfi), &sfin); PrintAndLogEx(INFO, "* PPSE get SFI: 0x%02x.", sfin); - + for (uint8_t ui = 0x01; ui <= 0x10; ui++) { PrintAndLogEx(INFO, "* * Get SFI: 0x%02x. num: 0x%02x", sfin, ui); res = EMVReadRecord(channel, true, sfin, ui, sfidata[ui], APDU_RES_LEN, &sfidatalen[ui], &sw, NULL); - + // end of records if (sw == 0x6a83) { sfidatalen[ui] = 0; PrintAndLogEx(INFO, "* * PPSE get SFI. End of records."); break; } - + // error catch! if (sw != 0x9000) { sfidatalen[ui] = 0; @@ -455,7 +455,7 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO PrintAndLogEx(FAILED, "SFI 0x%02d don't have records.", sfidatalen[ui]); continue; } - res = EMVCheckAID(channel, decodeTLV, tsfitmp, tlv); + res = EMVCheckAID(channel, decodeTLV, tsfitmp, tlv); fileFound = true; } tlvdb_free(tsfi); @@ -470,21 +470,21 @@ int EMVSearchPSE(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldO res = EMVCheckAID(channel, decodeTLV, ttmp, tlv); fileFound = true; } - + if (!fileFound) PrintAndLogEx(FAILED, "PPSE don't have records."); tlvdb_free(t); } else { PrintAndLogEx(WARNING, "PPSE ERROR: Can't get TLV from response."); - } + } } else { PrintAndLogEx(WARNING, "PPSE ERROR: Can't select PPSE AID. Error: %d", res); } - + if(!LeaveFieldON) DropFieldEx( channel ); - + return res; } @@ -494,7 +494,7 @@ int EMVSearch(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, uint8_t data[APDU_RES_LEN] = {0}; size_t datalen = 0; uint16_t sw = 0; - + int res = 0; int retrycnt = 0; for(int i = 0; i < AIDlistLen; i ++) { @@ -510,20 +510,20 @@ int EMVSearch(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, PrintAndLogEx(WARNING, "Exit..."); return 1; } - + retrycnt = 0; PrintAndLogEx(FAILED, "Retry failed [%s]. Skipped...", AIDlist[i].aid); } continue; } retrycnt = 0; - + if (res) continue; - + if (!datalen) continue; - + if (decodeTLV) { PrintAndLogEx(SUCCESS, "%s", AIDlist[i].aid); TLVPrintFromBuffer(data, datalen); @@ -536,25 +536,25 @@ int EMVSearch(EMVCommandChannel channel, bool ActivateField, bool LeaveFieldON, int EMVSelectApplication(struct tlvdb *tlv, uint8_t *AID, size_t *AIDlen) { // check priority. 0x00 - highest int prio = 0xffff; - + *AIDlen = 0; struct tlvdb *ttmp = tlvdb_find(tlv, 0x6f); if (!ttmp) return 1; - + while (ttmp) { const struct tlv *tgAID = tlvdb_get_inchild(ttmp, 0x84, NULL); const struct tlv *tgPrio = tlvdb_get_inchild(ttmp, 0x87, NULL); - + if (!tgAID) break; if (tgPrio) { - int pt = bytes_to_num((uint8_t*)tgPrio->value, (tgPrio->len < 2) ? tgPrio->len : 2); + int pt = bytes_to_num((uint8_t*)tgPrio->value, (tgPrio->len < 2) ? tgPrio->len : 2); if (pt < prio) { prio = pt; - + memcpy(AID, tgAID->value, tgAID->len); *AIDlen = tgAID->len; } @@ -562,13 +562,13 @@ int EMVSelectApplication(struct tlvdb *tlv, uint8_t *AID, size_t *AIDlen) { // takes the first application from list wo priority if (!*AIDlen) { memcpy(AID, tgAID->value, tgAID->len); - *AIDlen = tgAID->len; + *AIDlen = tgAID->len; } } - + ttmp = tlvdb_find_next(ttmp, 0x6f); } - + return 0; } @@ -606,7 +606,7 @@ int MSCComputeCryptoChecksum(EMVCommandChannel channel, bool LeaveFieldON, uint8 return EMVExchange(channel, LeaveFieldON, (sAPDU){0x80, 0x2a, 0x8e, 0x80, UDOLlen, UDOL}, Result, MaxResultLen, ResultLen, sw, tlv); } -// Authentication +// Authentication struct emv_pk *get_ca_pk(struct tlvdb *db) { const struct tlv *df_tlv = tlvdb_get(db, 0x84, NULL); const struct tlv *caidx_tlv = tlvdb_get(db, 0x8f, NULL); @@ -625,7 +625,7 @@ int trSDA(struct tlvdb *tlv) { PrintAndLogEx(WARNING, "Error: Key not found. Exit."); return 2; } - + struct emv_pk *issuer_pk = emv_pki_recover_issuer_cert(pk, tlv); if (!issuer_pk) { emv_pk_free(pk); @@ -652,7 +652,7 @@ int trSDA(struct tlvdb *tlv) { PrintAndLogEx(WARNING, "Can't find input list for Offline Data Authentication. Exit."); return 3; } - + struct tlvdb *dac_db = emv_pki_recover_dac(issuer_pk, tlv, sda_tlv); if (dac_db) { const struct tlv *dac_tlv = tlvdb_get(dac_db, 0x9f45, NULL); @@ -664,7 +664,7 @@ int trSDA(struct tlvdb *tlv) { PrintAndLogEx(WARNING, "SSAD verify error"); return 4; } - + emv_pk_free(issuer_pk); emv_pk_free(pk); return 0; @@ -708,7 +708,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { issuer_pk->serial[1], issuer_pk->serial[2] ); - + struct emv_pk *icc_pk = emv_pki_recover_icc_cert(issuer_pk, tlv, sda_tlv); if (!icc_pk) { emv_pk_free(pk); @@ -769,7 +769,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { const struct tlv *atc_tlv = tlvdb_get(atc_db, 0x9f36, NULL); if(atc_tlv) { PrintAndLogEx(NORMAL, "\nATC (Application Transaction Counter) [%zu] %s", atc_tlv->len, sprint_hex_inrow(atc_tlv->value, atc_tlv->len)); - + const struct tlv *core_atc_tlv = tlvdb_get(tlv, 0x9f36, NULL); if(tlv_equal(core_atc_tlv, atc_tlv)) { PrintAndLogEx(SUCCESS, "ATC check OK."); @@ -797,7 +797,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { emv_pk_free(icc_pk); return 4; } - + PrintAndLogEx(NORMAL, "\n* * Calc DDOL"); const struct tlv *ddol_tlv = tlvdb_get(tlv, 0x9f49, NULL); if (!ddol_tlv) { @@ -818,7 +818,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { PrintAndLogEx(NORMAL, "\n* * Internal Authenticate"); int res = EMVInternalAuthenticate(channel, true, (uint8_t *)ddol_data_tlv->value, ddol_data_tlv->len, buf, sizeof(buf), &len, &sw, NULL); - if (res) { + if (res) { PrintAndLogEx(WARNING, "Internal Authenticate error(%d): %4x. Exit...", res, sw); free(ddol_data_tlv); emv_pk_free(pk); @@ -835,13 +835,13 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { // parse response 0x80 struct tlvdb *t80 = tlvdb_parse_multi(buf, len); const struct tlv * t80tlv = tlvdb_get_tlv(t80); - + // 9f4b Signed Dynamic Application Data dda_db = tlvdb_fixed(0x9f4b, t80tlv->len, t80tlv->value); tlvdb_add(tlv, dda_db); - + tlvdb_free(t80); - + if (decodeTLV){ PrintAndLogEx(NORMAL, "* * * Decode response format 1:"); TLVPrintFromTLV(dda_db); @@ -858,7 +858,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { return 7; } tlvdb_add(tlv, dda_db); - + if (decodeTLV) TLVPrintFromTLV(dda_db); } @@ -892,7 +892,7 @@ int trDDA(EMVCommandChannel channel, bool decodeTLV, struct tlvdb *tlv) { return 9; } } - + emv_pk_free(pk); emv_pk_free(issuer_pk); emv_pk_free(icc_pk); @@ -931,7 +931,7 @@ int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_tlv, st issuer_pk->serial[1], issuer_pk->serial[2] ); - + struct emv_pk *icc_pk = emv_pki_recover_icc_cert(issuer_pk, tlv, sda_tlv); if (!icc_pk) { PrintAndLogEx(WARNING, "Error: ICC setrificate not found. Exit."); @@ -963,12 +963,12 @@ int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_tlv, st emv_pk_free(icc_pk); return 4; } - + PrintAndLogEx(NORMAL, "\n* * Check Signed Dynamic Application Data (SDAD)"); struct tlvdb *idn_db = emv_pki_perform_cda_ex(icc_pk, tlv, ac_tlv, pdol_data_tlv, // pdol ac_data_tlv, // cdol1 - NULL, // cdol2 + NULL, // cdol2 true); if (idn_db) { const struct tlv *idn_tlv = tlvdb_get(idn_db, 0x9f4c, NULL); @@ -986,7 +986,7 @@ int trCDA(struct tlvdb *tlv, struct tlvdb *ac_tlv, struct tlv *pdol_data_tlv, st } int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root) { - + struct emv_pk *pk = get_ca_pk(tlvRoot); if (!pk) { PrintAndLog("ERROR: Key not found. Exit."); @@ -1036,11 +1036,11 @@ int RecoveryCertificates(struct tlvdb *tlvRoot, json_t *root) { icc_pk->serial[1], icc_pk->serial[2] ); - + char *icc_pk_c = emv_pk_dump_pk(icc_pk); JsonSaveStr(root, "$.ApplicationData.ICCPublicKeyDec", icc_pk_c); JsonSaveBufAsHex(root, "$.ApplicationData.ICCPublicKeyModulus", icc_pk->modulus, icc_pk->mlen); free(issuer_pk_c); - + return 0; } diff --git a/client/emv/emvjson.c b/client/emv/emvjson.c index dc409a2a5..4468d49b3 100644 --- a/client/emv/emvjson.c +++ b/client/emv/emvjson.c @@ -64,7 +64,7 @@ char* GetApplicationDataName(tlv_tag_t tag) { for (int i = 0; i < ApplicationDataLen; i++) if (ApplicationData[i].Tag == tag) return ApplicationData[i].Name; - + return NULL; } @@ -73,7 +73,7 @@ int JsonSaveJsonObject(json_t *root, char *path, json_t *value) { if (strlen(path) < 1) return 1; - + if (path[0] == '$') { if (json_path_set(root, path, value, 0, &error)) { PrintAndLog("ERROR: can't set json path: ", error.text); @@ -124,9 +124,9 @@ int JsonSaveHex(json_t *elm, char *path, uint64_t data, int datalen) { len = 1; } else { len = datalen; - } + } num_to_bytes(data, len, bdata); - + return JsonSaveBufAsHex(elm, path, bdata, len); } @@ -135,7 +135,7 @@ int JsonSaveTLVValue(json_t *root, char *path, struct tlvdb *tlvdbelm) { if (tlvelm) return JsonSaveBufAsHex(root, path, (uint8_t *)tlvelm->value, tlvelm->len); else - return 1; + return 1; } int JsonSaveTLVElm(json_t *elm, char *path, struct tlv *tlvelm, bool saveName, bool saveValue, bool saveAppDataLink) { @@ -143,13 +143,13 @@ int JsonSaveTLVElm(json_t *elm, char *path, struct tlv *tlvelm, bool saveName, b if (strlen(path) < 1 || !tlvelm) return 1; - + if (path[0] == '$') { json_t *obj = json_path_get(elm, path); if (!obj) { obj = json_object(); - + if (json_is_array(elm)) { if (json_array_append_new(elm, obj)) { PrintAndLog("ERROR: can't append array: %s", path); @@ -162,12 +162,12 @@ int JsonSaveTLVElm(json_t *elm, char *path, struct tlv *tlvelm, bool saveName, b } } } - + if (saveAppDataLink) { char * AppDataName = GetApplicationDataName(tlvelm->tag); if (AppDataName) JsonSaveStr(obj, "appdata", AppDataName); - } else { + } else { char * name = emv_get_tag_name(tlvelm); if (saveName && name && strlen(name) > 0 && strncmp(name, "Unknown", 7)) JsonSaveStr(obj, "name", emv_get_tag_name(tlvelm)); @@ -193,13 +193,13 @@ int JsonSaveTLVTree(json_t *root, json_t *elm, char *path, struct tlvdb *tlvdbel char * AppDataName = NULL; if (tlvpelm) AppDataName = GetApplicationDataName(tlvpelm->tag); - + if (AppDataName) { char appdatalink[200] = {0}; sprintf(appdatalink, "$.ApplicationData.%s", AppDataName); JsonSaveBufAsHex(root, appdatalink, (uint8_t *)tlvpelm->value, tlvpelm->len); } - + json_t *pelm = json_path_get(elm, path); if (pelm && json_is_array(pelm)) { json_t *appendelm = json_object(); @@ -210,20 +210,20 @@ int JsonSaveTLVTree(json_t *root, json_t *elm, char *path, struct tlvdb *tlvdbel JsonSaveTLVTreeElm(elm, path, tlvp, !AppDataName, !tlvdb_elm_get_children(tlvp), AppDataName); pelm = json_path_get(elm, path); } - + if (tlvdb_elm_get_children(tlvp)) { // get path element if(!pelm) return 1; - + // check childs element and add it if not found json_t *chjson = json_path_get(pelm, "$.Childs"); if (!chjson) { json_object_set_new(pelm, "Childs", json_array()); - + chjson = json_path_get(pelm, "$.Childs"); } - + // check if (!json_is_array(chjson)) { PrintAndLog("E->Internal logic error. `$.Childs` is not an array."); @@ -240,8 +240,8 @@ int JsonSaveTLVTree(json_t *root, json_t *elm, char *path, struct tlvdb *tlvdbel } bool HexToBuffer(const char *errormsg, const char *hexvalue, uint8_t * buffer, size_t maxbufferlen, size_t *bufferlen) { - int buflen = 0; - + int buflen = 0; + switch (param_gethex_to_eol(hexvalue, 0, buffer, maxbufferlen, &buflen)) { case 1: PrintAndLog("%s Invalid HEX value.", errormsg); @@ -253,15 +253,15 @@ bool HexToBuffer(const char *errormsg, const char *hexvalue, uint8_t * buffer, s PrintAndLog("%s Hex value must have even number of digits.", errormsg); return false; } - + if (buflen > maxbufferlen) { PrintAndLog("%s HEX length (%d) more than %d", errormsg, (bufferlen) ? *bufferlen : -1, maxbufferlen); return false; } - + if ( bufferlen ) *bufferlen = buflen; - + return true; } @@ -272,27 +272,27 @@ int JsonLoadStr(json_t *root, char *path, char *value) { json_t *jelm = json_path_get((const json_t *)root, path); if (!jelm || !json_is_string(jelm)) return 2; - + const char * strval = json_string_value(jelm); if (!strval) return 1; - + memcpy(value, strval, strlen(strval)); - + return 0; } int JsonLoadBufAsHex(json_t *elm, char *path, uint8_t *data, size_t maxbufferlen, size_t *datalen) { if (datalen) *datalen = 0; - + json_t *jelm = json_path_get((const json_t *)elm, path); if (!jelm || !json_is_string(jelm)) return 1; - + if (!HexToBuffer("ERROR load", json_string_value(jelm), data, maxbufferlen, datalen)) return 2; - + return 0; }; @@ -302,11 +302,11 @@ bool ParamLoadFromJson(struct tlvdb *tlv) { if (!tlv) { PrintAndLog("ERROR load params: tlv tree is NULL."); - return false; + return false; } // current path + file name - const char *relfname = "emv/defparams.json"; + const char *relfname = "emv/defparams.json"; char fname[strlen(get_my_executable_directory()) + strlen(relfname) + 1]; strcpy(fname, get_my_executable_directory()); strcat(fname, relfname); @@ -314,16 +314,16 @@ bool ParamLoadFromJson(struct tlvdb *tlv) { root = json_load_file(fname, 0, &error); if (!root) { PrintAndLog("Load params: json error on line %d: %s", error.line, error.text); - return false; + return false; } - + if (!json_is_array(root)) { PrintAndLog("Load params: Invalid json format. root must be array."); - return false; + return false; } - + PrintAndLog("Load params: json(%d) OK", json_array_size(root)); - + for(int i = 0; i < json_array_size(root); i++) { json_t *data, *jtag, *jlength, *jvalue; @@ -334,7 +334,7 @@ bool ParamLoadFromJson(struct tlvdb *tlv) { json_decref(root); return false; } - + jtag = json_object_get(data, "tag"); if(!json_is_string(jtag)) { @@ -360,39 +360,39 @@ bool ParamLoadFromJson(struct tlvdb *tlv) { json_decref(root); return false; } - + int tlvLength = json_integer_value(jlength); if (tlvLength > 250) { PrintAndLog("Load params: data [%d] length more than 250", i + 1); json_decref(root); return false; } - + PrintAndLog("TLV param: %s[%d]=%s", tlvTag, tlvLength, tlvValue); uint8_t buf[251] = {0}; size_t buflen = 0; - - if (!HexToBuffer("TLV Error type:", tlvTag, buf, 4, &buflen)) { + + if (!HexToBuffer("TLV Error type:", tlvTag, buf, 4, &buflen)) { json_decref(root); return false; } tlv_tag_t tag = 0; for (int i = 0; i < buflen; i++) { tag = (tag << 8) | buf[i]; - } - + } + if (!HexToBuffer("TLV Error value:", tlvValue, buf, sizeof(buf) - 1, &buflen)) { json_decref(root); return false; } - + if (buflen != tlvLength) { PrintAndLog("Load params: data [%d] length of HEX must(%d) be identical to length in TLV param(%d)", i + 1, buflen, tlvLength); json_decref(root); return false; } - - tlvdb_change_or_add_node(tlv, tag, tlvLength, (const unsigned char *)buf); + + tlvdb_change_or_add_node(tlv, tag, tlvLength, (const unsigned char *)buf); } json_decref(root); diff --git a/client/emv/test/cda_test.c b/client/emv/test/cda_test.c index 536a5862b..a029558d6 100644 --- a/client/emv/test/cda_test.c +++ b/client/emv/test/cda_test.c @@ -423,7 +423,7 @@ int exec_cda_test(bool verbose) { int ret; fprintf(stdout, "\n"); - + ret = cda_test_raw(verbose); if (ret) { fprintf(stderr, "CDA raw test: failed\n"); diff --git a/client/emv/test/cda_test.h b/client/emv/test/cda_test.h index 1d321a26e..8d80043cd 100644 --- a/client/emv/test/cda_test.h +++ b/client/emv/test/cda_test.h @@ -13,6 +13,6 @@ * Lesser General Public License for more details. */ -#include - +#include + extern int exec_cda_test(bool verbose); diff --git a/client/emv/test/cryptotest.c b/client/emv/test/cryptotest.c index 4e8df1a25..5d7017f9c 100644 --- a/client/emv/test/cryptotest.c +++ b/client/emv/test/cryptotest.c @@ -36,25 +36,25 @@ int ExecuteCryptoTests(bool verbose) { int res; bool TestFail = false; - + res = mbedtls_mpi_self_test(verbose); if (res) TestFail = true; - + res = mbedtls_aes_self_test(verbose); if (res) TestFail = true; res = mbedtls_des_self_test(verbose); if (res) TestFail = true; - + res = mbedtls_sha1_self_test(verbose); if (res) TestFail = true; res = mbedtls_md5_self_test(verbose); if (res) TestFail = true; - + res = mbedtls_rsa_self_test(verbose); if (res) TestFail = true; - + res = mbedtls_entropy_self_test(verbose); if (res) TestFail = true; @@ -63,7 +63,7 @@ int ExecuteCryptoTests(bool verbose) { res = mbedtls_ctr_drbg_self_test(verbose); if (res) TestFail = true; - + res = mbedtls_base64_self_test(verbose); if (res) TestFail = true; @@ -78,13 +78,13 @@ int ExecuteCryptoTests(bool verbose) { res = mbedtls_x509_self_test(verbose); if (res) TestFail = true; - + res = exec_sda_test(verbose); if (res) TestFail = true; res = exec_dda_test(verbose); if (res) TestFail = true; - + res = exec_cda_test(verbose); if (res) TestFail = true; @@ -95,12 +95,12 @@ int ExecuteCryptoTests(bool verbose) { if (res) TestFail = true; PrintAndLog("\n--------------------------"); - + if (TestFail) PrintAndLogEx(FAILED, "\tTest(s) [ %s ]", _RED_(FAIL) ); else PrintAndLogEx(SUCCESS, "\tTest(s) [ %s ]", _GREEN_(OK) ); - + return TestFail; } diff --git a/client/emv/test/dda_test.h b/client/emv/test/dda_test.h index 354cd7e13..1ae1a0660 100644 --- a/client/emv/test/dda_test.h +++ b/client/emv/test/dda_test.h @@ -13,6 +13,6 @@ * Lesser General Public License for more details. */ -#include - +#include + extern int exec_dda_test(bool verbose); diff --git a/client/emv/test/sda_test.h b/client/emv/test/sda_test.h index 43a4c9482..8d47aa9b3 100644 --- a/client/emv/test/sda_test.h +++ b/client/emv/test/sda_test.h @@ -12,5 +12,5 @@ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. */ - + extern int exec_sda_test(bool verbose); diff --git a/client/emv/tlv.c b/client/emv/tlv.c index a309d0659..31277c325 100644 --- a/client/emv/tlv.c +++ b/client/emv/tlv.c @@ -11,7 +11,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * https://github.com/lumag/emv-tools/blob/master/lib/tlv.c */ @@ -37,8 +37,8 @@ #define TLV_LEN_INVALID (~0) // http://radek.io/2012/11/10/magical-container_of-macro/ -//#define container_of(ptr, type, member) ({ -// const typeof( ((type *)0)->member ) *__mptr = (ptr); +//#define container_of(ptr, type, member) ({ +// const typeof( ((type *)0)->member ) *__mptr = (ptr); // (type *)( (char *)__mptr - offsetof(type,member) );}) struct tlvdb { @@ -301,14 +301,14 @@ void tlvdb_free(struct tlvdb *tlvdb) struct tlvdb *tlvdb_find_next(struct tlvdb *tlvdb, tlv_tag_t tag) { if (!tlvdb) return NULL; - + return tlvdb_find(tlvdb->next, tag); } struct tlvdb *tlvdb_find(struct tlvdb *tlvdb, tlv_tag_t tag) { if (!tlvdb) return NULL; - + for (; tlvdb; tlvdb = tlvdb->next) { if (tlvdb->tag.tag == tag) return tlvdb; @@ -320,16 +320,16 @@ struct tlvdb *tlvdb_find(struct tlvdb *tlvdb, tlv_tag_t tag) { struct tlvdb *tlvdb_find_full(struct tlvdb *tlvdb, tlv_tag_t tag) { if (!tlvdb) return NULL; - + for (; tlvdb; tlvdb = tlvdb->next) { if (tlvdb->tag.tag == tag) return tlvdb; - + if (tlvdb->children) { struct tlvdb * ch = tlvdb_find_full(tlvdb->children, tag); if (ch) return ch; - } + } } return NULL; @@ -338,7 +338,7 @@ struct tlvdb *tlvdb_find_full(struct tlvdb *tlvdb, tlv_tag_t tag) { struct tlvdb *tlvdb_find_path(struct tlvdb *tlvdb, tlv_tag_t tag[]) { int i = 0; struct tlvdb *tnext = tlvdb; - + while (tnext && tag[i]) { tnext = tlvdb_find(tnext, tag[i]); i++; @@ -346,7 +346,7 @@ struct tlvdb *tlvdb_find_path(struct tlvdb *tlvdb, tlv_tag_t tag[]) { tnext = tnext->children; } } - + return tnext; } @@ -354,11 +354,11 @@ void tlvdb_add(struct tlvdb *tlvdb, struct tlvdb *other) { if (tlvdb == other) return; - + while (tlvdb->next) { if (tlvdb->next == other) return; - + tlvdb = tlvdb->next; } @@ -383,20 +383,20 @@ void tlvdb_change_or_add_node_ex(struct tlvdb *tlvdb, tlv_tag_t tag, size_t len, struct tlvdb *tnewelm = tlvdb_fixed(tag, len, value); tnewelm->next = telm->next; tnewelm->parent = telm->parent; - + // if telm stayed first in children chain if (telm->parent && telm->parent->children == telm) { telm->parent->children = tnewelm; } - + // if telm have previous element if (telm != tlvdb) { // elm in root struct tlvdb *celm = tlvdb; // elm in child list of node if (telm->parent && telm->parent->children) - celm = telm->parent->children; - + celm = telm->parent->children; + // find previous element for (; celm; celm = celm->next) { if (celm->next == telm) { @@ -405,15 +405,15 @@ void tlvdb_change_or_add_node_ex(struct tlvdb *tlvdb, tlv_tag_t tag, size_t len, } } } - + // free old element with childrens telm->next = NULL; tlvdb_free(telm); - + if (tlvdb_elm) *tlvdb_elm = tnewelm; } - + return; } @@ -557,18 +557,18 @@ struct tlvdb *tlvdb_elm_get_parent(struct tlvdb *tlvdb) bool tlvdb_get_uint8(struct tlvdb *tlvRoot, tlv_tag_t tag, uint8_t *value) { - const struct tlv *tlvelm = tlvdb_get(tlvRoot, tag, NULL); + const struct tlv *tlvelm = tlvdb_get(tlvRoot, tag, NULL); return tlv_get_uint8(tlvelm, value); } -bool tlv_get_uint8(const struct tlv *etlv, uint8_t *value) +bool tlv_get_uint8(const struct tlv *etlv, uint8_t *value) { *value = 0; if (etlv) { if (etlv->len == 0) return true; - + if (etlv->len == 1) { *value = etlv->value[0]; @@ -585,7 +585,7 @@ bool tlv_get_int(const struct tlv *etlv, int *value) { if (etlv->len == 0) return true; - + if (etlv->len <= 4) { for (int i = 0; i < etlv->len; i++) diff --git a/client/emv/tlv.h b/client/emv/tlv.h index e75bbf986..7e171c102 100644 --- a/client/emv/tlv.h +++ b/client/emv/tlv.h @@ -11,7 +11,7 @@ * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. - * + * * https://github.com/lumag/emv-tools/blob/master/lib/include/openemv/tlv.h */ diff --git a/client/fido/additional_ca.c b/client/fido/additional_ca.c index 564eda2ae..ccda7f251 100644 --- a/client/fido/additional_ca.c +++ b/client/fido/additional_ca.c @@ -5,7 +5,7 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// CA PEM certificates +// CA PEM certificates //----------------------------------------------------------------------------- // diff --git a/client/fido/additional_ca.h b/client/fido/additional_ca.h index 856583039..d0f642e46 100644 --- a/client/fido/additional_ca.h +++ b/client/fido/additional_ca.h @@ -5,7 +5,7 @@ // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// CA PEM certificates +// CA PEM certificates //----------------------------------------------------------------------------- // @@ -14,7 +14,7 @@ #include -// Concatenation of all CA certificates in PEM format if available +// Concatenation of all CA certificates in PEM format if available extern const char additional_ca_pem[]; extern const size_t additional_ca_pem_len; diff --git a/client/fido/cbortools.c b/client/fido/cbortools.c index 01691dad1..8883ac475 100644 --- a/client/fido/cbortools.c +++ b/client/fido/cbortools.c @@ -28,7 +28,7 @@ static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) { CborType type = cbor_value_get_type(it); indent(nestingLevel); switch (type) { - case CborMapType: + case CborMapType: case CborArrayType: { printf(type == CborArrayType ? "Array[" : "Map["); break; @@ -67,14 +67,14 @@ static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) { case CborTagType: { CborTag tag; - cbor_value_get_tag(it, &tag); + cbor_value_get_tag(it, &tag); printf("Tag(%lld)", (long long)tag); break; } case CborSimpleType: { uint8_t type; - cbor_value_get_simple_type(it, &type); + cbor_value_get_simple_type(it, &type); printf("simple(%u)", type); break; } @@ -118,7 +118,7 @@ static CborError dumpelm(CborValue *it, bool *got_next, int nestingLevel) { printf("CborInvalidType!!!"); break; } - + return CborNoError; } @@ -131,7 +131,7 @@ static CborError dumprecursive(uint8_t cmdCode, bool isResponse, CborValue *it, bool got_next; switch (type) { - case CborMapType: + case CborMapType: case CborArrayType: { // recursive type CborValue recursed; @@ -189,7 +189,7 @@ int TinyCborInit(uint8_t *data, size_t length, CborValue *cb) { CborError err = cbor_parser_init(data, length, 0, &parser, cb); if (err) return err; - + return 0; } @@ -199,20 +199,20 @@ int TinyCborPrintFIDOPackage(uint8_t cmdCode, bool isResponse, uint8_t *data, si res = TinyCborInit(data, length, &cb); if (res) return res; - + CborError err = dumprecursive(cmdCode, isResponse, &cb, false, 0); if (err) { fprintf(stderr, -#if __WORDSIZE == 64 +#if __WORDSIZE == 64 "CBOR parsing failure at offset %" PRId64 " : %s\n", #else - "CBOR parsing failure at offset %" PRId32 " : %s\n", + "CBOR parsing failure at offset %" PRId32 " : %s\n", #endif cb.ptr - data, cbor_error_string(err)); return 1; - } - + } + return 0; } @@ -220,15 +220,15 @@ int JsonObjElmCount(json_t *elm) { int res = 0; const char *key; json_t *value; - + if (!json_is_object(elm)) return 0; - + json_object_foreach(elm, key, value) { if (strlen(key) > 0 && key[0] != '.') - res++; + res++; } - + return res; } @@ -237,7 +237,7 @@ int JsonToCbor(json_t *elm, CborEncoder *encoder) { return 1; int res; - + // CBOR map == JSON object if (json_is_object(elm)) { CborEncoder map; @@ -246,17 +246,17 @@ int JsonToCbor(json_t *elm, CborEncoder *encoder) { res = cbor_encoder_create_map(encoder, &map, JsonObjElmCount(elm)); cbor_check(res); - + json_object_foreach(elm, key, value) { if (strlen(key) > 0 && key[0] != '.') { - res = cbor_encode_text_stringz(&map, key); + res = cbor_encode_text_stringz(&map, key); cbor_check(res); - + // RECURSION! JsonToCbor(value, &map); } } - + res = cbor_encoder_close_container(encoder, &map); cbor_check(res); } @@ -266,15 +266,15 @@ int JsonToCbor(json_t *elm, CborEncoder *encoder) { size_t index; json_t *value; CborEncoder array; - + res = cbor_encoder_create_array(encoder, &array, json_array_size(elm)); cbor_check(res); - + json_array_foreach(elm, index, value) { // RECURSION! JsonToCbor(value, &array); } - + res = cbor_encoder_close_container(encoder, &array); cbor_check(res); } @@ -304,15 +304,15 @@ int JsonToCbor(json_t *elm, CborEncoder *encoder) { return 100; res = cbor_encode_byte_string(encoder, data, datalen); - cbor_check(res); + cbor_check(res); } else { res = cbor_encode_text_stringz(encoder, val); cbor_check(res); } } - - - + + + return 0; } @@ -324,7 +324,7 @@ int CborMapGetKeyById(CborParser *parser, CborValue *map, uint8_t *data, size_t if (cbor_value_get_type(&cb) != CborMapType) return 1; - + err = cbor_value_enter_container(&cb, map); cbor_check(err); @@ -335,10 +335,10 @@ int CborMapGetKeyById(CborParser *parser, CborValue *map, uint8_t *data, size_t return 1; cbor_value_get_int64(map, &indx); - + err = cbor_value_advance(map); cbor_check(err); - + if (indx == key) return 0; @@ -361,17 +361,17 @@ CborError CborGetArrayBinStringValueEx(CborValue *elm, uint8_t *data, size_t max CborValue array; if (datalen) *datalen = 0; - + size_t slen = maxdatalen; size_t totallen = 0; CborError res = cbor_value_enter_container(elm, &array); cbor_check(res); - + while (!cbor_value_at_end(&array)) { res = cbor_value_copy_byte_string(&array, &data[totallen], &slen, &array); cbor_check(res); - + totallen += slen; if (delimeter) { memcpy(&data[totallen], delimeter, delimeterlen); @@ -386,13 +386,13 @@ CborError CborGetArrayBinStringValueEx(CborValue *elm, uint8_t *data, size_t max if (datalen) *datalen = totallen; - return CborNoError; + return CborNoError; }; CborError CborGetBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen, size_t *datalen) { if (datalen) *datalen = 0; - + size_t slen = maxdatalen; CborError res = cbor_value_copy_byte_string(elm, data, &slen, elm); @@ -401,24 +401,24 @@ CborError CborGetBinStringValue(CborValue *elm, uint8_t *data, size_t maxdatalen if (datalen) *datalen = slen; - return CborNoError; + return CborNoError; }; CborError CborGetArrayStringValue(CborValue *elm, char *data, size_t maxdatalen, size_t *datalen, char *delimeter) { CborValue array; if (datalen) *datalen = 0; - + size_t slen = maxdatalen; size_t totallen = 0; CborError res = cbor_value_enter_container(elm, &array); cbor_check(res); - + while (!cbor_value_at_end(&array)) { res = cbor_value_copy_text_string(&array, &data[totallen], &slen, &array); cbor_check(res); - + totallen += slen; if (delimeter) { strcat(data, delimeter); @@ -434,13 +434,13 @@ CborError CborGetArrayStringValue(CborValue *elm, char *data, size_t maxdatalen, if (datalen) *datalen = totallen; - return CborNoError; + return CborNoError; }; CborError CborGetStringValue(CborValue *elm, char *data, size_t maxdatalen, size_t *datalen) { if (datalen) *datalen = 0; - + size_t slen = maxdatalen; CborError res = cbor_value_copy_text_string(elm, data, &slen, elm); @@ -449,13 +449,13 @@ CborError CborGetStringValue(CborValue *elm, char *data, size_t maxdatalen, size if (datalen) *datalen = slen; - return CborNoError; + return CborNoError; }; CborError CborGetStringValueBuf(CborValue *elm) { static char stringBuf[2048]; memset(stringBuf, 0x00, sizeof(stringBuf)); - + return CborGetStringValue(elm, stringBuf, sizeof(stringBuf), NULL); }; @@ -465,10 +465,10 @@ int CBOREncodeElm(json_t *root, char *rootElmId, CborEncoder *encoder) { elm = json_path_get(root, rootElmId); else elm = json_object_get(root, rootElmId); - + if (!elm) return 1; - + int res = JsonToCbor(elm, encoder); return res; @@ -479,11 +479,11 @@ CborError CBOREncodeClientDataHash(json_t *root, CborEncoder *encoder) { size_t jlen; JsonLoadBufAsHex(root, "$.ClientDataHash", buf, sizeof(buf), &jlen); - + // fill with 0x00 if not found if (!jlen) jlen = 32; - + int res = cbor_encode_byte_string(encoder, buf, jlen); cbor_check(res); diff --git a/client/fido/cose.c b/client/fido/cose.c index e45f46290..86c016314 100644 --- a/client/fido/cose.c +++ b/client/fido/cose.c @@ -22,13 +22,13 @@ typedef struct { char *Name; char *Description; } COSEValueNameDesc_t; - + typedef struct { int Value; char *Type; char *Name; char *Description; -} COSEValueTypeNameDesc_t; +} COSEValueTypeNameDesc_t; // kty - Key Type Values COSEValueNameDesc_t COSEKeyTypeValueDesc[] = { @@ -141,7 +141,7 @@ COSEValueNameDesc_t *GetCOSEAlgElm(int id) { return &COSEAlg[i]; return NULL; } - + const char *GetCOSEAlgName(int id) { COSEValueNameDesc_t *elm = GetCOSEAlgElm(id); if (elm) @@ -164,11 +164,11 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public if(verbose) PrintAndLog("----------- CBOR decode ----------------"); - + // kty int res = CborMapGetKeyById(&parser, &map, data, datalen, 1); if(!res) { - cbor_value_get_int64(&map, &i64); + cbor_value_get_int64(&map, &i64); if(verbose) PrintAndLog("kty [%lld] %s", (long long)i64, GetCOSEktyDescription(i64)); if (i64 != 2) @@ -178,26 +178,26 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public // algorithm res = CborMapGetKeyById(&parser, &map, data, datalen, 3); if(!res) { - cbor_value_get_int64(&map, &i64); + cbor_value_get_int64(&map, &i64); if(verbose) PrintAndLog("algorithm [%lld] %s", (long long)i64, GetCOSEAlgDescription(i64)); if (i64 != -7) PrintAndLog("ERROR: algorithm must be -7."); } - + // curve res = CborMapGetKeyById(&parser, &map, data, datalen, -1); if(!res) { - cbor_value_get_int64(&map, &i64); + cbor_value_get_int64(&map, &i64); if(verbose) PrintAndLog("curve [%lld] %s", (long long)i64, GetCOSECurveDescription(i64)); if (i64 != 1) PrintAndLog("ERROR: curve must be 1."); } - + // plain key public_key[0] = 0x04; - + // x - coordinate res = CborMapGetKeyById(&parser, &map, data, datalen, -2); if(!res) { @@ -229,10 +229,10 @@ int COSEGetECDSAKey(uint8_t *data, size_t datalen, bool verbose, uint8_t *public if(verbose) PrintAndLog("d - private key [%d]: %s", len, sprint_hex(private_key, len)); } - + if(verbose) PrintAndLog("----------- CBOR decode ----------------"); - + return 0; } diff --git a/client/fido/fidocore.c b/client/fido/fidocore.c index 49088ec28..a91a57d8f 100644 --- a/client/fido/fidocore.c +++ b/client/fido/fidocore.c @@ -101,7 +101,7 @@ fido2Desc_t fido2CmdGetInfoRespDesc[] = { {fido2CmdMakeCredential, ptQuery, 0x07, "options"}, {fido2CmdMakeCredential, ptQuery, 0x08, "pinAuth"}, {fido2CmdMakeCredential, ptQuery, 0x09, "pinProtocol"}, - + {fido2CmdGetAssertion, ptResponse, 0x01, "credential"}, {fido2CmdGetAssertion, ptResponse, 0x02, "authData"}, {fido2CmdGetAssertion, ptResponse, 0x03, "signature"}, @@ -115,12 +115,12 @@ fido2Desc_t fido2CmdGetInfoRespDesc[] = { {fido2CmdGetAssertion, ptQuery, 0x05, "options"}, {fido2CmdGetAssertion, ptQuery, 0x06, "pinAuth"}, {fido2CmdGetAssertion, ptQuery, 0x07, "pinProtocol"}, - + {fido2CmdGetNextAssertion, ptResponse, 0x01, "credential"}, {fido2CmdGetNextAssertion, ptResponse, 0x02, "authData"}, {fido2CmdGetNextAssertion, ptResponse, 0x03, "signature"}, {fido2CmdGetNextAssertion, ptResponse, 0x04, "publicKeyCredentialUserEntity"}, - + {fido2CmdGetInfo, ptResponse, 0x01, "versions"}, {fido2CmdGetInfo, ptResponse, 0x02, "extensions"}, {fido2CmdGetInfo, ptResponse, 0x03, "aaguid"}, @@ -140,7 +140,7 @@ fido2Desc_t fido2CmdGetInfoRespDesc[] = { {fido2CmdClientPIN, ptQuery, 0x06, "pinHashEnc"}, {fido2CmdClientPIN, ptQuery, 0x07, "getKeyAgreement"}, {fido2CmdClientPIN, ptQuery, 0x08, "getRetries"}, - + {fido2COSEKey, ptResponse, 0x01, "kty"}, {fido2COSEKey, ptResponse, 0x03, "alg"}, {fido2COSEKey, ptResponse, -1, "crv"}, @@ -153,7 +153,7 @@ char *fido2GetCmdErrorDescription(uint8_t errorCode) { for (int i = 0; i < sizeof(fido2Errors) / sizeof(fido2Error_t); i++) if (fido2Errors[i].ErrorCode == errorCode) return fido2Errors[i].Description; - + return fido2Errors[0].Description; } @@ -169,7 +169,7 @@ char *fido2GetCmdMemberDescription(uint8_t cmdCode, bool isResponse, int memberN int FIDOSelect(bool ActivateField, bool LeaveFieldON, uint8_t *Result, size_t MaxResultLen, size_t *ResultLen, uint16_t *sw) { uint8_t data[] = {0xA0, 0x00, 0x00, 0x06, 0x47, 0x2F, 0x00, 0x01}; - + return EMVSelect(ECC_CONTACTLESS, ActivateField, LeaveFieldON, data, sizeof(data), Result, MaxResultLen, ResultLen, sw, NULL); } @@ -183,9 +183,9 @@ int FIDOExchange(sAPDU apdu, uint8_t *Result, size_t MaxResultLen, size_t *Resul res = EMVExchange(ECC_CONTACTLESS, true, (sAPDU){0x00, 0xC0, 0x00, 0x00, 0x00, NULL}, &Result[oldlen], MaxResultLen - oldlen, ResultLen, sw, NULL); if (res == 5) // apdu result (sw) not a 0x9000 res = 0; - + *ResultLen += oldlen; - if (*ResultLen > MaxResultLen) + if (*ResultLen > MaxResultLen) return 100; } return res; @@ -220,7 +220,7 @@ int FIDO2GetAssertion(uint8_t *params, uint8_t paramslen, uint8_t *Result, size_ int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint8_t *publicKey, size_t publicKeyMaxLen) { int res; - + // load CA's mbedtls_x509_crt cacert; mbedtls_x509_crt_init(&cacert); @@ -228,9 +228,9 @@ int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint8_t *pu if (res < 0) { PrintAndLog("ERROR: CA parse certificate returned -0x%x - %s", -res, ecdsa_get_error(res)); } - if (verbose) + if (verbose) PrintAndLog("CA load OK. %d skipped", res); - + // load DER certificate from authenticator's data mbedtls_x509_crt cert; mbedtls_x509_crt_init(&cert); @@ -238,14 +238,14 @@ int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint8_t *pu if (res) { PrintAndLog("ERROR: DER parse returned 0x%x - %s", (res<0)?-res:res, ecdsa_get_error(res)); } - + // get certificate info char linfo[300] = {0}; if (verbose) { mbedtls_x509_crt_info(linfo, sizeof(linfo), " ", &cert); PrintAndLog("DER certificate info:\n%s", linfo); } - + // verify certificate uint32_t verifyflags = 0; res = mbedtls_x509_crt_verify(&cert, &cacert, NULL, NULL, &verifyflags, NULL, NULL); @@ -254,13 +254,13 @@ int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint8_t *pu } else { PrintAndLog("Certificate OK.\n"); } - + if (verbose) { memset(linfo, 0x00, sizeof(linfo)); mbedtls_x509_crt_verify_info(linfo, sizeof(linfo), " ", verifyflags); PrintAndLog("Verification info:\n%s", linfo); } - + // get public key res = ecdsa_public_key_from_pk(&cert.pk, publicKey, publicKeyMaxLen); if (res) { @@ -275,7 +275,7 @@ int FIDOCheckDERAndGetKey(uint8_t *der, size_t derLen, bool verbose, uint8_t *pu mbedtls_x509_crt_free(&cert); mbedtls_x509_crt_free(&cacert); - + return 0; } @@ -291,7 +291,7 @@ int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatale int res; CborEncoder encoder; CborEncoder map; - + cbor_encoder_init(&encoder, data, maxdatalen, 0); // create main map @@ -334,31 +334,31 @@ int FIDO2CreateMakeCredentionalReq(json_t *root, uint8_t *data, size_t maxdatale } res = cbor_encoder_close_container(&encoder, &map); fido_check(res); - + size_t len = cbor_encoder_get_buffer_size(&encoder, data); if (datalen) *datalen = len; - + return 0; } bool CheckrpIdHash(json_t *json, uint8_t *hash) { char hashval[300] = {0}; uint8_t hash2[32] = {0}; - + JsonLoadStr(json, "$.RelyingPartyEntity.id", hashval); int res = sha256hash((uint8_t *)hashval, strlen(hashval), hash2); if (res) return false; - + return !memcmp(hash, hash2, 32); } // check ANSI X9.62 format ECDSA signature (on P-256) int FIDO2CheckSignature(json_t *root, uint8_t *publickey, uint8_t *sign, size_t signLen, uint8_t *authData, size_t authDataLen, bool verbose) { int res; - uint8_t rval[300] = {0}; - uint8_t sval[300] = {0}; + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; res = ecdsa_asn1_get_signature(sign, signLen, rval, sval); if (!res) { if (verbose) { @@ -372,12 +372,12 @@ int FIDO2CheckSignature(json_t *root, uint8_t *publickey, uint8_t *sign, size_t if (res || clientDataHashLen != 32) { PrintAndLog("ERROR: Can't get clientDataHash from json!"); return 2; - } - + } + uint8_t xbuf[4096] = {0}; size_t xbuflen = 0; res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, - authData, authDataLen, // rpIdHash[32] + flags[1] + signCount[4] + authData, authDataLen, // rpIdHash[32] + flags[1] + signCount[4] clientDataHash, 32, // Hash of the serialized client data. "$.ClientDataHash" from json NULL, 0); //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); @@ -391,12 +391,12 @@ int FIDO2CheckSignature(json_t *root, uint8_t *publickey, uint8_t *sign, size_t return res; } else { PrintAndLog("Signature is OK."); - } + } } else { PrintAndLog("Invalid signature. res=%d.", res); return res; } - + return 0; } @@ -407,37 +407,37 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b char *buf; uint8_t *ubuf; size_t n; - + // fmt res = CborMapGetKeyById(&parser, &map, data, dataLen, 1); if (res) return res; - + res = cbor_value_dup_text_string(&map, &buf, &n, &map); cbor_check(res); PrintAndLog("format: %s", buf); free(buf); // authData - uint8_t authData[400] = {0}; + uint8_t authData[400] = {0}; size_t authDataLen = 0; res = CborMapGetKeyById(&parser, &map, data, dataLen, 2); if (res) return res; res = cbor_value_dup_byte_string(&map, &ubuf, &n, &map); cbor_check(res); - + authDataLen = n; - memcpy(authData, ubuf, authDataLen); - + memcpy(authData, ubuf, authDataLen); + if (verbose2) { PrintAndLog("authData[%d]: %s", n, sprint_hex_inrow(authData, authDataLen)); } else { PrintAndLog("authData[%d]: %s...", n, sprint_hex(authData, MIN(authDataLen, 16))); } - + PrintAndLog("RP ID Hash: %s", sprint_hex(ubuf, 32)); - + // check RP ID Hash if (CheckrpIdHash(root, ubuf)) { PrintAndLog("rpIdHash OK."); @@ -460,17 +460,17 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b uint32_t cntr = (uint32_t)bytes_to_num(&ubuf[33], 4); PrintAndLog("Counter: %d", cntr); JsonSaveInt(root, "$.AppData.Counter", cntr); - + // attestation data PrintAndLog("AAGUID: %s", sprint_hex(&ubuf[37], 16)); JsonSaveBufAsHexCompact(root, "$.AppData.AAGUID", &ubuf[37], 16); - + // Credential ID uint8_t cridlen = (uint16_t)bytes_to_num(&ubuf[53], 2); PrintAndLog("Credential id[%d]: %s", cridlen, sprint_hex_inrow(&ubuf[55], cridlen)); JsonSaveInt(root, "$.AppData.CredentialIdLen", cridlen); JsonSaveBufAsHexCompact(root, "$.AppData.CredentialId", &ubuf[55], cridlen); - + //Credentional public key (COSE_KEY) uint8_t coseKey[65] = {0}; uint16_t cplen = n - 55 - cridlen; @@ -480,14 +480,14 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b PrintAndLog("Credentional public key (COSE_KEY)[%d]: %s...", cplen, sprint_hex(&ubuf[55 + cridlen], MIN(cplen, 16))); } JsonSaveBufAsHexCompact(root, "$.AppData.COSE_KEY", &ubuf[55 + cridlen], cplen); - + if (showCBOR) { PrintAndLog("COSE structure:"); PrintAndLog("---------------- CBOR ------------------"); - TinyCborPrintFIDOPackage(fido2COSEKey, true, &ubuf[55 + cridlen], cplen); + TinyCborPrintFIDOPackage(fido2COSEKey, true, &ubuf[55 + cridlen], cplen); PrintAndLog("---------------- CBOR ------------------"); } - + res = COSEGetECDSAKey(&ubuf[55 + cridlen], cplen, verbose, coseKey); if (res) { PrintAndLog("ERROR: Can't get COSE_KEY."); @@ -497,27 +497,27 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b } free(ubuf); - + // attStmt - we are check only as DER certificate int64_t alg = 0; uint8_t sign[128] = {0}; size_t signLen = 0; uint8_t der[4097] = {0}; size_t derLen = 0; - + res = CborMapGetKeyById(&parser, &map, data, dataLen, 3); if (res) return res; res = cbor_value_enter_container(&map, &mapsmt); cbor_check(res); - + while (!cbor_value_at_end(&mapsmt)) { char key[100] = {0}; res = CborGetStringValue(&mapsmt, key, sizeof(key), &n); cbor_check(res); if (!strcmp(key, "alg")) { - cbor_value_get_int64(&mapsmt, &alg); + cbor_value_get_int64(&mapsmt, &alg); PrintAndLog("Alg [%lld] %s", (long long)alg, GetCOSEAlgDescription(alg)); res = cbor_value_advance_fixed(&mapsmt); cbor_check(res); @@ -544,11 +544,11 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b PrintAndLog("DER [%d]: %s...", derLen, sprint_hex(der, MIN(derLen, 16))); } JsonSaveBufAsHexCompact(root, "$.AppData.DER", der, derLen); - } + } } res = cbor_value_leave_container(&map, &mapsmt); cbor_check(res); - + uint8_t public_key[65] = {0}; // print DER certificate in TLV view @@ -562,7 +562,7 @@ int FIDO2MakeCredentionalParseRes(json_t *root, uint8_t *data, size_t dataLen, b // check ANSI X9.62 format ECDSA signature (on P-256) FIDO2CheckSignature(root, public_key, sign, signLen, authData, authDataLen, verbose); - + return 0; } @@ -575,7 +575,7 @@ int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, s int res; CborEncoder encoder; CborEncoder map, array, mapint; - + cbor_encoder_init(&encoder, data, maxdatalen, 0); // create main map @@ -605,15 +605,15 @@ int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, s fido_check_if(res) { res = cbor_encode_text_stringz(&mapint, "type"); fido_check(res); - + res = cbor_encode_text_stringz(&mapint, "public-key"); - fido_check(res); - + fido_check(res); + res = cbor_encode_text_stringz(&mapint, "id"); - fido_check(res); - + fido_check(res); + res = CBOREncodeElm(root, "$.AppData.CredentialId", &mapint); - fido_check(res); + fido_check(res); } res = cbor_encoder_close_container(&array, &mapint); fido_check(res); @@ -632,11 +632,11 @@ int FIDO2CreateGetAssertionReq(json_t *root, uint8_t *data, size_t maxdatalen, s } res = cbor_encoder_close_container(&encoder, &map); fido_check(res); - + size_t len = cbor_encoder_get_buffer_size(&encoder, data); if (datalen) *datalen = len; - + return 0; } @@ -646,7 +646,7 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool int res; uint8_t *ubuf; size_t n; - + // credential res = CborMapGetKeyById(&parser, &map, data, dataLen, 1); if (res) @@ -654,7 +654,7 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool res = cbor_value_enter_container(&map, &mapint); cbor_check(res); - + while (!cbor_value_at_end(&mapint)) { char key[100] = {0}; res = CborGetStringValue(&mapint, key, sizeof(key), &n); @@ -676,27 +676,27 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool } res = cbor_value_leave_container(&map, &mapint); cbor_check(res); - + // authData - uint8_t authData[400] = {0}; + uint8_t authData[400] = {0}; size_t authDataLen = 0; res = CborMapGetKeyById(&parser, &map, data, dataLen, 2); if (res) return res; res = cbor_value_dup_byte_string(&map, &ubuf, &n, &map); cbor_check(res); - + authDataLen = n; - memcpy(authData, ubuf, authDataLen); - + memcpy(authData, ubuf, authDataLen); + if (verbose2) { PrintAndLog("authData[%d]: %s", n, sprint_hex_inrow(authData, authDataLen)); } else { PrintAndLog("authData[%d]: %s...", n, sprint_hex(authData, MIN(authDataLen, 16))); } - + PrintAndLog("RP ID Hash: %s", sprint_hex(ubuf, 32)); - + // check RP ID Hash if (CheckrpIdHash(root, ubuf)) { PrintAndLog("rpIdHash OK."); @@ -719,17 +719,17 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool uint32_t cntr = (uint32_t)bytes_to_num(&ubuf[33], 4); PrintAndLog("Counter: %d", cntr); JsonSaveInt(root, "$.AppData.Counter", cntr); - + free(ubuf); // publicKeyCredentialUserEntity res = CborMapGetKeyById(&parser, &map, data, dataLen, 4); - if (res) { + if (res) { PrintAndLog("UserEntity n/a"); } else { res = cbor_value_enter_container(&map, &mapint); cbor_check(res); - + while (!cbor_value_at_end(&mapint)) { char key[100] = {0}; res = CborGetStringValue(&mapint, key, sizeof(key), &n); @@ -747,7 +747,7 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool res = CborGetBinStringValue(&mapint, cid, sizeof(cid), &n); cbor_check(res); PrintAndLog("UserEntity id [%d]: %s", n, sprint_hex(cid, n)); - + // check uint8_t idbuf[100] = {0}; size_t idbuflen; @@ -764,15 +764,15 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool res = cbor_value_leave_container(&map, &mapint); cbor_check(res); } - - + + // signature res = CborMapGetKeyById(&parser, &map, data, dataLen, 3); if (res) return res; res = cbor_value_dup_byte_string(&map, &ubuf, &n, &map); cbor_check(res); - + uint8_t *sign = ubuf; size_t signLen = n; @@ -787,7 +787,7 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool uint8_t PublicKey[65] = {0}; size_t PublicKeyLen = 0; JsonLoadBufAsHex(root, "$.AppData.COSEPublicKey", PublicKey, 65, &PublicKeyLen); - + // check ANSI X9.62 format ECDSA signature (on P-256) FIDO2CheckSignature(root, PublicKey, sign, signLen, authData, authDataLen, verbose); @@ -799,9 +799,9 @@ int FIDO2GetAssertionParseRes(json_t *root, uint8_t *data, size_t dataLen, bool PrintAndLog("numberOfCredentials: 1 by default"); } else { int64_t numberOfCredentials = 0; - cbor_value_get_int64(&map, &numberOfCredentials); + cbor_value_get_int64(&map, &numberOfCredentials); PrintAndLog("numberOfCredentials: %lld", (long long)numberOfCredentials); } - + return 0; } diff --git a/client/fido/fidocore.h b/client/fido/fidocore.h index b0b50e2ac..931cf146b 100644 --- a/client/fido/fidocore.h +++ b/client/fido/fidocore.h @@ -25,7 +25,7 @@ typedef enum { fido2CmdClientPIN = 0x06, fido2CmdReset = 0x07, fido2CmdGetNextAssertion = 0x08, - + // another data fido2COSEKey = 0xF0 } fido2Commands; diff --git a/client/flasher.c b/client/flasher.c index a20b264b9..c1ec7b4f1 100644 --- a/client/flasher.c +++ b/client/flasher.c @@ -39,13 +39,13 @@ static void usage(char *argv0) { fprintf(stdout, "Usage: %s [-b] image.elf [image.elf...]\n\n", argv0); fprintf(stdout, "\t-b\tEnable flashing of bootloader area (DANGEROUS)\n\n"); fprintf(stdout, "\nExample:\n\n\t %s "SERIAL_PORT_H" armsrc/obj/fullimage.elf\n", argv0); -#ifdef __linux__ +#ifdef __linux__ fprintf(stdout, "\nNote (Linux): if the flasher gets stuck in 'Waiting for Proxmark to reappear on ',\n"); fprintf(stdout, " you need to blacklist proxmark for modem-manager - see wiki for more details:\n\n"); fprintf(stdout, " https://github.com/Proxmark/proxmark3/wiki/Gentoo Linux\n\n"); fprintf(stdout, " https://github.com/Proxmark/proxmark3/wiki/Ubuntu Linux\n\n"); fprintf(stdout, " https://github.com/Proxmark/proxmark3/wiki/OSX\n\n"); -#endif +#endif } int main(int argc, char **argv) { @@ -78,7 +78,7 @@ int main(int argc, char **argv) { num_files++; } } - + char* serial_port_name = argv[1]; if (!OpenProxmark(serial_port_name, true, 60, true)) { diff --git a/client/fpga_compress.c b/client/fpga_compress.c index 6e6e67be4..1f959fa9f 100644 --- a/client/fpga_compress.c +++ b/client/fpga_compress.c @@ -27,18 +27,18 @@ #define COMPRESS_LEVEL 9 // use best possible compression #define COMPRESS_WINDOW_BITS 15 // default = max = 15 for a window of 2^15 = 32KBytes #define COMPRESS_MEM_LEVEL 9 // determines the amount of memory allocated during compression. Default = 8. -/* COMPRESS_STRATEGY can be - Z_DEFAULT_STRATEGY (the default), +/* COMPRESS_STRATEGY can be + Z_DEFAULT_STRATEGY (the default), Z_FILTERED (more huffmann, less string matching), Z_HUFFMAN_ONLY (huffman only, no string matching) Z_RLE (distances limited to one) Z_FIXED (prevents the use of dynamic Huffman codes) -*/ +*/ #define COMPRESS_STRATEGY Z_DEFAULT_STRATEGY // zlib tuning parameters: #define COMPRESS_GOOD_LENGTH 258 -#define COMPRESS_MAX_LAZY 258 +#define COMPRESS_MAX_LAZY 258 #define COMPRESS_MAX_NICE_LENGTH 258 #define COMPRESS_MAX_CHAIN 8192 @@ -75,7 +75,7 @@ static bool all_feof(FILE *infile[], uint8_t num_infiles) if (!feof(infile[i])) { return false; } - } + } return true; } @@ -92,21 +92,21 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardn fpga_config = calloc(num_infiles * HARDNESTED_TABLE_SIZE, sizeof(uint8_t)); } else { fpga_config = calloc(num_infiles * FPGA_CONFIG_SIZE, sizeof(uint8_t)); - } + } // read the input files. Interleave them into fpga_config[] i = 0; do { if (i >= num_infiles * (hardnested_mode ? HARDNESTED_TABLE_SIZE : FPGA_CONFIG_SIZE)) { if (hardnested_mode) { - fprintf(stderr, -#if __WORDSIZE == 64 + fprintf(stderr, +#if __WORDSIZE == 64 "Input file too big (> %" PRIu64 " bytes). This is probably not a hardnested bitflip state table.\n" #else - "Input file too big (> %lu bytes). This is probably not a hardnested bitflip state table.\n" -#endif + "Input file too big (> %lu bytes). This is probably not a hardnested bitflip state table.\n" +#endif , HARDNESTED_TABLE_SIZE); - + } else { fprintf(stderr, "Input files too big (total > %lu bytes). These are probably not PM3 FPGA config files.\n", num_infiles * FPGA_CONFIG_SIZE); } @@ -136,8 +136,8 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardn compressed_fpga_stream.zalloc = fpga_deflate_malloc; compressed_fpga_stream.zfree = fpga_deflate_free; compressed_fpga_stream.opaque = Z_NULL; - - ret = deflateInit2(&compressed_fpga_stream, + + ret = deflateInit2(&compressed_fpga_stream, COMPRESS_LEVEL, Z_DEFLATED, COMPRESS_WINDOW_BITS, @@ -149,7 +149,7 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardn uint8_t *outbuf = calloc(outsize_max, sizeof(uint8_t)); compressed_fpga_stream.next_out = outbuf; compressed_fpga_stream.avail_out = outsize_max; - + if (ret == Z_OK) { ret = deflateTune(&compressed_fpga_stream, COMPRESS_GOOD_LENGTH, @@ -157,11 +157,11 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardn COMPRESS_MAX_NICE_LENGTH, COMPRESS_MAX_CHAIN); } - + if (ret == Z_OK) { ret = deflate(&compressed_fpga_stream, Z_FINISH); } - + fprintf(stdout, "compressed %u input bytes to %lu output bytes\n", i, compressed_fpga_stream.total_out); if (ret != Z_STREAM_END) { @@ -176,10 +176,10 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardn free(fpga_config); return(EXIT_FAILURE); } - + for (i = 0; i < compressed_fpga_stream.total_out; i++) { fputc(outbuf[i], outfile); - } + } free(outbuf); deflateEnd(&compressed_fpga_stream); @@ -189,9 +189,9 @@ int zlib_compress(FILE *infile[], uint8_t num_infiles, FILE *outfile, bool hardn fclose(outfile); free(infile); free(fpga_config); - + return(EXIT_SUCCESS); - + } @@ -201,7 +201,7 @@ int zlib_decompress(FILE *infile, FILE *outfile) uint8_t outbuf[DECOMPRESS_BUF_SIZE]; uint8_t inbuf[DECOMPRESS_BUF_SIZE]; int32_t ret; - + z_stream compressed_fpga_stream; // initialize zlib structures @@ -212,9 +212,9 @@ int zlib_decompress(FILE *infile, FILE *outfile) compressed_fpga_stream.zalloc = fpga_deflate_malloc; compressed_fpga_stream.zfree = fpga_deflate_free; compressed_fpga_stream.opaque = Z_NULL; - + ret = inflateInit2(&compressed_fpga_stream, 0); - + do { if (compressed_fpga_stream.avail_in == 0) { compressed_fpga_stream.next_in = inbuf; @@ -260,7 +260,7 @@ int zlib_decompress(FILE *infile, FILE *outfile) fclose(infile); return(EXIT_FAILURE); } - + } @@ -319,7 +319,7 @@ static int FpgaGatherVersion(FILE *infile, char* infile_name, char *dst, int len { unsigned int fpga_info_len; char tempstr[40] = {0x00}; - + dst[0] = '\0'; for (uint16_t i = 0; i < FPGA_BITSTREAM_FIXED_HEADER_SIZE; i++) { @@ -345,7 +345,7 @@ static int FpgaGatherVersion(FILE *infile, char* infile_name, char *dst, int len } strncat(dst, tempstr, len-1); } - + if (bitparse_find_section(infile, 'c', &fpga_info_len)) { strncat(dst, " on ", len-1); for (uint16_t i = 0; i < fpga_info_len; i++) { @@ -356,7 +356,7 @@ static int FpgaGatherVersion(FILE *infile, char* infile_name, char *dst, int len } strncat(dst, tempstr, len-1); } - + if (bitparse_find_section(infile, 'd', &fpga_info_len)) { strncat(dst, " at ", len-1); for (uint16_t i = 0; i < fpga_info_len; i++) { @@ -389,11 +389,11 @@ static void print_version_info_preamble(FILE *outfile, int num_infiles) { } static int generate_fpga_version_info(FILE *infile[], char *infile_names[], int num_infiles, FILE *outfile) { - + char version_string[80] = ""; - + print_version_info_preamble(outfile, num_infiles); - + for (int i = 0; i < num_infiles; i++) { FpgaGatherVersion(infile[i], infile_names[i], version_string, sizeof(version_string)); fprintf(outfile, "\t\" %s\"", version_string); @@ -401,7 +401,7 @@ static int generate_fpga_version_info(FILE *infile[], char *infile_names[], int fprintf(outfile, ","); } fprintf(outfile,"\n"); - } + } fprintf(outfile, "};\n"); return 0; } @@ -411,19 +411,19 @@ int main(int argc, char **argv) FILE **infiles; char **infile_names; FILE *outfile; - + if (argc == 1 || argc == 2) { usage(); return(EXIT_FAILURE); } - + if (!strcmp(argv[1], "-d")) { // Decompress infiles = calloc(1, sizeof(FILE*)); if (argc != 4) { usage(); return(EXIT_FAILURE); - } + } infiles[0] = fopen(argv[2], "rb"); if (infiles[0] == NULL) { fprintf(stderr, "Error. Cannot open input file %s\n\n", argv[2]); @@ -454,10 +454,10 @@ int main(int argc, char **argv) } else { // compress 1..n fpga files num_input_files = argc-2; } - + infiles = calloc(num_input_files, sizeof(FILE*)); infile_names = calloc(num_input_files, sizeof(char*)); - for (uint16_t i = 0; i < num_input_files; i++) { + for (uint16_t i = 0; i < num_input_files; i++) { infile_names[i] = argv[i+((hardnested_mode || generate_version_file)?2:1)]; infiles[i] = fopen(infile_names[i], "rb"); if (infiles[i] == NULL) { diff --git a/client/graph.c b/client/graph.c index 42bb79c84..db29919bc 100644 --- a/client/graph.c +++ b/client/graph.c @@ -16,7 +16,7 @@ int s_Buff[MAX_GRAPH_TRACE_LEN]; /* write a manchester bit to the graph */ void AppendGraph(int redraw, int clock, int bit) { int i; - //set first half the clock bit (all 1's or 0's for a 0 or 1 bit) + //set first half the clock bit (all 1's or 0's for a 0 or 1 bit) for (i = 0; i < (int)(clock / 2); ++i) GraphBuffer[GraphTraceLen++] = bit ; //set second half of the clock bit (all 0's or 1's for a 0 or 1 bit) @@ -59,12 +59,12 @@ void save_restoreGB(uint8_t saveOpt) { void setGraphBuf(uint8_t *buf, size_t size) { if ( buf == NULL ) return; - + ClearGraph(0); - + if ( size > MAX_GRAPH_TRACE_LEN ) size = MAX_GRAPH_TRACE_LEN; - + for (uint16_t i = 0; i < size; ++i) GraphBuffer[i] = buf[i] - 128; @@ -85,22 +85,22 @@ size_t getFromGraphBuf(uint8_t *buf) { return i; } -// A simple test to see if there is any data inside Graphbuffer. +// A simple test to see if there is any data inside Graphbuffer. bool HasGraphData(){ if ( GraphTraceLen <= 0) { PrintAndLogEx(NORMAL, "No data available, try reading something first"); return false; } - return true; + return true; } // Get or auto-detect ask clock rate int GetAskClock(const char *str, bool printAns) { int clock = param_get32ex(str, 0, 0, 10); - if (clock > 0) + if (clock > 0) return clock; - + // Auto-detect clock uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; size_t size = getFromGraphBuf(bits); @@ -115,7 +115,7 @@ int GetAskClock(const char *str, bool printAns) { if (st == false) { idx = DetectASKClock(bits, size, &clock, 20); } - + if ( clock > 0 ) { setClockGrid(clock, idx); } @@ -146,9 +146,9 @@ uint8_t GetPskCarrier(const char *str, bool printAns) { int GetPskClock(const char* str, bool printAns) { int clock = param_get32ex(str, 0, 0, 10); - if (clock != 0) + if (clock != 0) return clock; - + // Auto-detect clock uint8_t grph[MAX_GRAPH_TRACE_LEN] = {0}; size_t size = getFromGraphBuf(grph); @@ -169,9 +169,9 @@ int GetPskClock(const char* str, bool printAns) { int GetNrzClock(const char* str, bool printAns) { int clock = param_get32ex(str, 0, 0, 10); - if (clock != 0) + if (clock != 0) return clock; - + // Auto-detect clock uint8_t grph[MAX_GRAPH_TRACE_LEN] = {0}; size_t size = getFromGraphBuf(grph); @@ -192,17 +192,17 @@ int GetNrzClock(const char* str, bool printAns) { int GetFskClock(const char* str, bool printAns) { int clock = param_get32ex(str, 0, 0, 10); - if (clock != 0) + if (clock != 0) return clock; uint8_t fc1 = 0, fc2 = 0, rf1 = 0; int firstClockEdge = 0; - + if ( !fskClocks(&fc1, &fc2, &rf1, &firstClockEdge)) return 0; - + if ((fc1==10 && fc2==8) || (fc1==8 && fc2==5)){ - if (printAns) + if (printAns) PrintAndLogEx(SUCCESS, "Detected Field Clocks: FC/%d, FC/%d - Bit Clock: RF/%d", fc1, fc2, rf1); setClockGrid(rf1, firstClockEdge); return rf1; @@ -215,15 +215,15 @@ int GetFskClock(const char* str, bool printAns) { bool fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, int *firstClockEdge) { uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; size_t size = getFromGraphBuf(bits); - if (size == 0) + if (size == 0) return false; - + uint16_t ans = countFC(bits, size, true); if (ans == 0) { PrintAndLogEx(DEBUG, "DEBUG: No data found"); return false; } - + *fc1 = (ans >> 8) & 0xFF; *fc2 = ans & 0xFF; *rf1 = detectFSKClk(bits, size, *fc1, *fc2, firstClockEdge); diff --git a/client/hardnested/hardnested_bf_core.c b/client/hardnested/hardnested_bf_core.c index 6bf29b795..e80a9cd19 100644 --- a/client/hardnested/hardnested_bf_core.c +++ b/client/hardnested/hardnested_bf_core.c @@ -10,7 +10,7 @@ // attacks this doesn't rely on implementation errors but only on the // inherent weaknesses of the crypto1 cypher. Described in // Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened -// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on +// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on // Computer and Communications Security, 2015 //----------------------------------------------------------------------------- // @@ -19,7 +19,7 @@ // - don't rollback. Start with 2nd byte of nonce instead // - reuse results of filter subfunctions // - reuse results of previous nonces if some first bits are identical -// +// //----------------------------------------------------------------------------- // aczid's Copyright notice: // @@ -100,7 +100,7 @@ typedef union { // size of nonce to be decrypted #define KEYSTREAM_SIZE 24 -// this needs to be compiled several times for each instruction set. +// this needs to be compiled several times for each instruction set. // For each instruction set, define a dedicated function name: #if defined (__AVX512F__) #define BITSLICE_TEST_NONCES bitslice_test_nonces_AVX512 @@ -114,7 +114,7 @@ typedef union { #elif defined (__SSE2__) #define BITSLICE_TEST_NONCES bitslice_test_nonces_SSE2 #define CRACK_STATES_BITSLICED crack_states_bitsliced_SSE2 -#elif defined (__MMX__) +#elif defined (__MMX__) #define BITSLICE_TEST_NONCES bitslice_test_nonces_MMX #define CRACK_STATES_BITSLICED crack_states_bitsliced_MMX #else @@ -208,7 +208,7 @@ void BITSLICE_TEST_NONCES(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonce const uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonce_2nd_byte, noncelist_t *nonces){ // Unlike aczid's implementation this doesn't roll back at all when performing bitsliced bruteforce. - // We know that the best first byte is already shifted in. Testing with the remaining three bytes of + // We know that the best first byte is already shifted in. Testing with the remaining three bytes of // the nonces is sufficient to eliminate most of them. The small rest is tested with a simple unsliced // brute forcing (including roll back). @@ -223,7 +223,7 @@ const uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, uint32_t elimination_step = 0; #define MAX_ELIMINATION_STEP 32 uint64_t keys_eliminated[MAX_ELIMINATION_STEP] = {0}; -#endif +#endif #ifdef DEBUG_KEY_ELIMINATION bool bucket_contains_test_key[(p->len[EVEN_STATE] - 1)/MAX_BITSLICES + 1]; #endif @@ -233,7 +233,7 @@ const uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, memset(bs_ones.bytes, 0xff, VECTOR_SIZE); bitslice_t bs_zeroes; memset(bs_zeroes.bytes, 0x00, VECTOR_SIZE); - + // bitslice all the even states bitslice_t **restrict bitsliced_even_states = (bitslice_t **)malloc(((p->len[EVEN_STATE] - 1)/MAX_BITSLICES + 1) * sizeof(bitslice_t *)); if (bitsliced_even_states == NULL) { @@ -284,10 +284,10 @@ const uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, lstate_p[bit_idx].bytes64[slice_idx>>6] |= 1ull << (slice_idx & 0x3f); } } - } + } bitsliced_even_states[bitsliced_blocks] = lstate_p; // bitsliced_even_feedback[bitsliced_blocks] = bs_ones; - bitsliced_even_feedback[bitsliced_blocks] = lstate_p[(47- 0)/2].value ^ + bitsliced_even_feedback[bitsliced_blocks] = lstate_p[(47- 0)/2].value ^ lstate_p[(47-10)/2].value ^ lstate_p[(47-12)/2].value ^ lstate_p[(47-14)/2].value ^ lstate_p[(47-24)/2].value ^ lstate_p[(47-42)/2].value; bitsliced_blocks++; @@ -298,9 +298,9 @@ const uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, if(*keys_found){ goto out; } - + // set odd state bits and pre-compute first keystream bit vector. This is the same for all blocks of even states - + state_p = &states[KEYSTREAM_SIZE]; uint32_t o = *p_odd; @@ -316,13 +316,13 @@ const uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, state_p[state_idx] = bs_zeroes; } } - + bitslice_value_t crypto1_bs_f20b_2[16]; bitslice_value_t crypto1_bs_f20b_3[8]; crypto1_bs_f20b_2[0] = f20b(state_p[47-25].value, state_p[47-27].value, state_p[47-29].value, state_p[47-31].value); crypto1_bs_f20b_3[0] = f20b(state_p[47-41].value, state_p[47-43].value, state_p[47-45].value, state_p[47-47].value); - + bitslice_value_t ksb[8]; ksb[0] = f20c(f20a(state_p[47- 9].value, state_p[47-11].value, state_p[47-13].value, state_p[47-15].value), f20b(state_p[47-17].value, state_p[47-19].value, state_p[47-21].value, state_p[47-23].value), @@ -347,11 +347,11 @@ const uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, // pre-compute first feedback bit vector. This is the same for all nonces bitslice_value_t fbb[8]; - fbb[0] = odd_feedback ^ bitsliced_even_feedback[block_idx]; + fbb[0] = odd_feedback ^ bitsliced_even_feedback[block_idx]; // vector to contain test results (1 = passed, 0 = failed) bitslice_t results = bs_ones; - + // parity_bits bitslice_value_t par[8]; par[0] = bs_zeroes.value; @@ -398,7 +398,7 @@ const uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, f20a_1 = f20a(state_p[47- 9].value, state_p[47-11].value, state_p[47-13].value, state_p[47-15].value); f20b_1 = crypto1_bs_f20b_2[KEYSTREAM_SIZE - ks_idx - 8]; f20b_2 = f20b(state_p[47-25].value, state_p[47-27].value, state_p[47-29].value, state_p[47-31].value); - crypto1_bs_f20b_2[KEYSTREAM_SIZE - ks_idx] = f20b_2; + crypto1_bs_f20b_2[KEYSTREAM_SIZE - ks_idx] = f20b_2; } else if (ks_idx > KEYSTREAM_SIZE - 24){ f20a_1 = f20a(state_p[47- 9].value, state_p[47-11].value, state_p[47-13].value, state_p[47-15].value); f20b_1 = crypto1_bs_f20b_2[KEYSTREAM_SIZE - ks_idx - 8]; @@ -407,7 +407,7 @@ const uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, f20a_1 = f20a(state_p[47- 9].value, state_p[47-11].value, state_p[47-13].value, state_p[47-15].value); f20b_1 = f20b(state_p[47-17].value, state_p[47-19].value, state_p[47-21].value, state_p[47-23].value); f20b_2 = f20b(state_p[47-25].value, state_p[47-27].value, state_p[47-29].value, state_p[47-31].value); - } + } // update keystream bit ks_bits = f20c(f20a_1, f20b_1, f20b_2, f20a_2, f20b_3); @@ -436,7 +436,7 @@ const uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, && results.bytes64[3] == 0 #endif ) { -#if defined (DEBUG_BRUTE_FORCE) +#if defined (DEBUG_BRUTE_FORCE) if (elimination_step < MAX_ELIMINATION_STEP) { keys_eliminated[elimination_step] += MAX_BITSLICES; } @@ -450,14 +450,14 @@ const uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, goto stop_tests; } // prepare for next nonce byte -#if defined (DEBUG_BRUTE_FORCE) +#if defined (DEBUG_BRUTE_FORCE) elimination_step++; #endif parity_bit_vector = bs_zeroes.value; - } + } // update feedback bit vector if (ks_idx != 0) { - fb_bits = + fb_bits = (state_p[47- 0].value ^ state_p[47- 5].value ^ state_p[47- 9].value ^ state_p[47-10].value ^ state_p[47-12].value ^ state_p[47-14].value ^ state_p[47-15].value ^ state_p[47-17].value ^ state_p[47-19].value ^ @@ -513,9 +513,9 @@ const uint64_t CRACK_STATES_BITSLICED(uint32_t cuid, uint8_t *best_first_bytes, } } stop_tests: -#if defined (DEBUG_BRUTE_FORCE) +#if defined (DEBUG_BRUTE_FORCE) elimination_step = 0; -#endif +#endif bucket_states_tested += bucket_size[block_idx]; // prepare to set new states state_p = &states[KEYSTREAM_SIZE]; @@ -529,12 +529,12 @@ out: free(bitsliced_even_states); free_bitslice(bitsliced_even_feedback); __sync_fetch_and_add(num_keys_tested, bucket_states_tested); - -#if defined (DEBUG_BRUTE_FORCE) + +#if defined (DEBUG_BRUTE_FORCE) for (uint32_t i = 0; i < MAX_ELIMINATION_STEP; i++) { printf("Eliminated after %2u test_bytes: %5.2f%%\n", i+1, (float)keys_eliminated[i] / bucket_states_tested * 100); } -#endif +#endif return key; } @@ -550,17 +550,17 @@ static SIMDExecInstr intSIMDInstr = SIMD_AUTO; void SetSIMDInstr(SIMDExecInstr instr) { intSIMDInstr = instr; - + crack_states_bitsliced_function_p = &crack_states_bitsliced_dispatch; bitslice_test_nonces_function_p = &bitslice_test_nonces_dispatch; } SIMDExecInstr GetSIMDInstr() { SIMDExecInstr instr = SIMD_NONE; - + #if defined (__i386__) || defined (__x86_64__) #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) - #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) + #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) if (__builtin_cpu_supports("avx512f")) instr = SIMD_AVX512; else if (__builtin_cpu_supports("avx2")) instr = SIMD_AVX2; #else @@ -573,7 +573,7 @@ SIMDExecInstr GetSIMDInstr() { #endif #endif instr = SIMD_NONE; - + return instr; } @@ -581,7 +581,7 @@ SIMDExecInstr GetSIMDInstrAuto() { SIMDExecInstr instr = intSIMDInstr; if (instr == SIMD_AUTO) return GetSIMDInstr(); - + return instr; } @@ -589,8 +589,8 @@ SIMDExecInstr GetSIMDInstrAuto() { const uint64_t crack_states_bitsliced_dispatch(uint32_t cuid, uint8_t *best_first_bytes, statelist_t *p, uint32_t *keys_found, uint64_t *num_keys_tested, uint32_t nonces_to_bruteforce, uint8_t *bf_test_nonce_2nd_byte, noncelist_t *nonces) { switch(GetSIMDInstrAuto()) { #if defined (__i386__) || defined (__x86_64__) - #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) - #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) + #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) + #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) case SIMD_AVX512: crack_states_bitsliced_function_p = &crack_states_bitsliced_AVX512; break; @@ -612,7 +612,7 @@ const uint64_t crack_states_bitsliced_dispatch(uint32_t cuid, uint8_t *best_firs default: crack_states_bitsliced_function_p = &crack_states_bitsliced_NOSIMD; break; - } + } // call the most optimized function for this CPU return (*crack_states_bitsliced_function_p)(cuid, best_first_bytes, p, keys_found, num_keys_tested, nonces_to_bruteforce, bf_test_nonce_2nd_byte, nonces); @@ -620,7 +620,7 @@ const uint64_t crack_states_bitsliced_dispatch(uint32_t cuid, uint8_t *best_firs void bitslice_test_nonces_dispatch(uint32_t nonces_to_bruteforce, uint32_t *bf_test_nonce, uint8_t *bf_test_nonce_par) { switch(GetSIMDInstrAuto()) { -#if defined (__i386__) || defined (__x86_64__) +#if defined (__i386__) || defined (__x86_64__) #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) case SIMD_AVX512: @@ -644,7 +644,7 @@ void bitslice_test_nonces_dispatch(uint32_t nonces_to_bruteforce, uint32_t *bf_t default: bitslice_test_nonces_function_p = &bitslice_test_nonces_NOSIMD; break; - } + } // call the most optimized function for this CPU (*bitslice_test_nonces_function_p)(nonces_to_bruteforce, bf_test_nonce, bf_test_nonce_par); diff --git a/client/hardnested/hardnested_bf_core.h b/client/hardnested/hardnested_bf_core.h index b3df05474..c7d0b03dd 100644 --- a/client/hardnested/hardnested_bf_core.h +++ b/client/hardnested/hardnested_bf_core.h @@ -10,7 +10,7 @@ // attacks this doesn't rely on implementation errors but only on the // inherent weaknesses of the crypto1 cypher. Described in // Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened -// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on +// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on // Computer and Communications Security, 2015 //----------------------------------------------------------------------------- // @@ -19,7 +19,7 @@ // - don't rollback. Start with 2nd byte of nonce instead // - reuse results of filter subfunctions // - reuse results of previous nonces if some first bits are identical -// +// //----------------------------------------------------------------------------- // aczid's Copyright notice: // diff --git a/client/hardnested/hardnested_bitarray_core.c b/client/hardnested/hardnested_bitarray_core.c index aca4f149d..1abdd8c79 100644 --- a/client/hardnested/hardnested_bitarray_core.c +++ b/client/hardnested/hardnested_bitarray_core.c @@ -10,7 +10,7 @@ // attacks this doesn't rely on implementation errors but only on the // inherent weaknesses of the crypto1 cypher. Described in // Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened -// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on +// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on // Computer and Communications Security, 2015 //----------------------------------------------------------------------------- // some helper functions which can benefit from SIMD instructions or other special instructions @@ -25,7 +25,7 @@ #include #endif -// this needs to be compiled several times for each instruction set. +// this needs to be compiled several times for each instruction set. // For each instruction set, define a dedicated function name: #if defined (__AVX512F__) #define MALLOC_BITARRAY malloc_bitarray_AVX512 @@ -83,7 +83,7 @@ #define COUNT_BITARRAY_AND2 count_bitarray_AND2_SSE2 #define COUNT_BITARRAY_AND3 count_bitarray_AND3_SSE2 #define COUNT_BITARRAY_AND4 count_bitarray_AND4_SSE2 -#elif defined (__MMX__) +#elif defined (__MMX__) #define MALLOC_BITARRAY malloc_bitarray_MMX #define FREE_BITARRAY free_bitarray_MMX #define BITCOUNT bitcount_MMX @@ -169,7 +169,7 @@ inline void FREE_BITARRAY(uint32_t *x) #endif } - + inline uint32_t BITCOUNT(uint32_t a) { return __builtin_popcountl(a); @@ -200,12 +200,12 @@ inline void BITARRAY_LOW20_AND(uint32_t *restrict A, uint32_t *restrict B) { uint16_t *a = (uint16_t *)__builtin_assume_aligned(A, __BIGGEST_ALIGNMENT__); uint16_t *b = (uint16_t *)__builtin_assume_aligned(B, __BIGGEST_ALIGNMENT__); - + for (uint32_t i = 0; i < (1<<20); i++) { if (!b[i]) { a[i] = 0; } - } + } } @@ -227,14 +227,14 @@ inline uint32_t COUNT_BITARRAY_LOW20_AND(uint32_t *restrict A, uint32_t *restric uint16_t *a = (uint16_t *)__builtin_assume_aligned(A, __BIGGEST_ALIGNMENT__); uint16_t *b = (uint16_t *)__builtin_assume_aligned(B, __BIGGEST_ALIGNMENT__); uint32_t count = 0; - + for (uint32_t i = 0; i < (1<<20); i++) { if (!b[i]) { a[i] = 0; } count += BITCOUNT(a[i]); } - return count; + return count; } @@ -318,7 +318,7 @@ count_bitarray_AND4_t *count_bitarray_AND4_function_p = &count_bitarray_AND4_dis // determine the available instruction set at runtime and call the correct function uint32_t *malloc_bitarray_dispatch(uint32_t x) { -#if defined (__i386__) || defined (__x86_64__) +#if defined (__i386__) || defined (__x86_64__) #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) if (__builtin_cpu_supports("avx512f")) malloc_bitarray_function_p = &malloc_bitarray_AVX512; @@ -331,7 +331,7 @@ uint32_t *malloc_bitarray_dispatch(uint32_t x) { else if (__builtin_cpu_supports("mmx")) malloc_bitarray_function_p = &malloc_bitarray_MMX; else #endif -#endif +#endif malloc_bitarray_function_p = &malloc_bitarray_NOSIMD; // call the most optimized function for this CPU @@ -360,7 +360,7 @@ void free_bitarray_dispatch(uint32_t *x) { } uint32_t bitcount_dispatch(uint32_t a) { -#if defined (__i386__) || defined (__x86_64__) +#if defined (__i386__) || defined (__x86_64__) #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) if (__builtin_cpu_supports("avx512f")) bitcount_function_p = &bitcount_AVX512; @@ -381,7 +381,7 @@ uint32_t bitcount_dispatch(uint32_t a) { } uint32_t count_states_dispatch(uint32_t *bitarray) { -#if defined (__i386__) || defined (__x86_64__) +#if defined (__i386__) || defined (__x86_64__) #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) if (__builtin_cpu_supports("avx512f")) count_states_function_p = &count_states_AVX512; @@ -393,7 +393,7 @@ uint32_t count_states_dispatch(uint32_t *bitarray) { else if (__builtin_cpu_supports("sse2")) count_states_function_p = &count_states_SSE2; else if (__builtin_cpu_supports("mmx")) count_states_function_p = &count_states_MMX; else - #endif + #endif #endif count_states_function_p = &count_states_NOSIMD; @@ -402,7 +402,7 @@ uint32_t count_states_dispatch(uint32_t *bitarray) { } void bitarray_AND_dispatch(uint32_t *A, uint32_t *B) { -#if defined (__i386__) || defined (__x86_64__) +#if defined (__i386__) || defined (__x86_64__) #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) if (__builtin_cpu_supports("avx512f")) bitarray_AND_function_p = &bitarray_AND_AVX512; @@ -444,7 +444,7 @@ void bitarray_low20_AND_dispatch(uint32_t *A, uint32_t *B) { } uint32_t count_bitarray_AND_dispatch(uint32_t *A, uint32_t *B) { -#if defined (__i386__) || defined (__x86_64__) +#if defined (__i386__) || defined (__x86_64__) #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) if (__builtin_cpu_supports("avx512f")) count_bitarray_AND_function_p = &count_bitarray_AND_AVX512; @@ -465,7 +465,7 @@ uint32_t count_bitarray_AND_dispatch(uint32_t *A, uint32_t *B) { } uint32_t count_bitarray_low20_AND_dispatch(uint32_t *A, uint32_t *B) { -#if defined (__i386__) || defined (__x86_64__) +#if defined (__i386__) || defined (__x86_64__) #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) if (__builtin_cpu_supports("avx512f")) count_bitarray_low20_AND_function_p = &count_bitarray_low20_AND_AVX512; @@ -486,7 +486,7 @@ uint32_t count_bitarray_low20_AND_dispatch(uint32_t *A, uint32_t *B) { } void bitarray_AND4_dispatch(uint32_t *A, uint32_t *B, uint32_t *C, uint32_t *D) { -#if defined (__i386__) || defined (__x86_64__) +#if defined (__i386__) || defined (__x86_64__) #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) if (__builtin_cpu_supports("avx512f")) bitarray_AND4_function_p = &bitarray_AND4_AVX512; @@ -507,7 +507,7 @@ void bitarray_AND4_dispatch(uint32_t *A, uint32_t *B, uint32_t *C, uint32_t *D) } void bitarray_OR_dispatch(uint32_t *A, uint32_t *B) { -#if defined (__i386__) || defined (__x86_64__) +#if defined (__i386__) || defined (__x86_64__) #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) if (__builtin_cpu_supports("avx512f")) bitarray_OR_function_p = &bitarray_OR_AVX512; @@ -528,7 +528,7 @@ void bitarray_OR_dispatch(uint32_t *A, uint32_t *B) { } uint32_t count_bitarray_AND2_dispatch(uint32_t *A, uint32_t *B) { -#if defined (__i386__) || defined (__x86_64__) +#if defined (__i386__) || defined (__x86_64__) #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) if (__builtin_cpu_supports("avx512f")) count_bitarray_AND2_function_p = &count_bitarray_AND2_AVX512; @@ -549,7 +549,7 @@ uint32_t count_bitarray_AND2_dispatch(uint32_t *A, uint32_t *B) { } uint32_t count_bitarray_AND3_dispatch(uint32_t *A, uint32_t *B, uint32_t *C) { -#if defined (__i386__) || defined (__x86_64__) +#if defined (__i386__) || defined (__x86_64__) #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) if (__builtin_cpu_supports("avx512f")) count_bitarray_AND3_function_p = &count_bitarray_AND3_AVX512; @@ -570,7 +570,7 @@ uint32_t count_bitarray_AND3_dispatch(uint32_t *A, uint32_t *B, uint32_t *C) { } uint32_t count_bitarray_AND4_dispatch(uint32_t *A, uint32_t *B, uint32_t *C, uint32_t *D) { -#if defined (__i386__) || defined (__x86_64__) +#if defined (__i386__) || defined (__x86_64__) #if !defined(__APPLE__) || (defined(__APPLE__) && (__clang_major__ > 8 || __clang_major__ == 8 && __clang_minor__ >= 1)) #if (__GNUC__ >= 5) && (__GNUC__ > 5 || __GNUC_MINOR__ > 2) if (__builtin_cpu_supports("avx512f")) count_bitarray_AND4_function_p = &count_bitarray_AND4_AVX512; diff --git a/client/hardnested/hardnested_bitarray_core.h b/client/hardnested/hardnested_bitarray_core.h index 0d92d6b9a..b12fcf89d 100644 --- a/client/hardnested/hardnested_bitarray_core.h +++ b/client/hardnested/hardnested_bitarray_core.h @@ -10,7 +10,7 @@ // attacks this doesn't rely on implementation errors but only on the // inherent weaknesses of the crypto1 cypher. Described in // Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened -// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on +// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on // Computer and Communications Security, 2015 //----------------------------------------------------------------------------- // @@ -19,7 +19,7 @@ // - don't rollback. Start with 2nd byte of nonce instead // - reuse results of filter subfunctions // - reuse results of previous nonces if some first bits are identical -// +// //----------------------------------------------------------------------------- // aczid's Copyright notice: // diff --git a/client/hardnested/hardnested_bruteforce.c b/client/hardnested/hardnested_bruteforce.c index 1a09d7a49..49cd4908d 100644 --- a/client/hardnested/hardnested_bruteforce.c +++ b/client/hardnested/hardnested_bruteforce.c @@ -10,7 +10,7 @@ // attacks this doesn't rely on implementation errors but only on the // inherent weaknesses of the crypto1 cypher. Described in // Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened -// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on +// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on // Computer and Communications Security, 2015 //----------------------------------------------------------------------------- // @@ -19,7 +19,7 @@ // - don't rollback. Start with 2nd byte of nonce instead // - reuse results of filter subfunctions // - reuse results of previous nonces if some first bits are identical -// +// //----------------------------------------------------------------------------- // aczid's Copyright notice: // @@ -89,7 +89,7 @@ static uint32_t keys_found = 0; static uint64_t num_keys_tested; static uint64_t found_bs_key = 0; -inline uint8_t trailing_zeros(uint8_t byte) +inline uint8_t trailing_zeros(uint8_t byte) { static const uint8_t trailing_zeros_LUT[256] = { 8, 0, 1, 0, 2, 0, 1, 0, 3, 0, 1, 0, 2, 0, 1, 0, @@ -126,7 +126,7 @@ bool verify_key(uint32_t cuid, noncelist_t *nonces, uint8_t *best_first_bytes, u for (int8_t byte_pos = 3; byte_pos >= 0; byte_pos--) { uint8_t test_par_enc_bit = (test_nonce->par_enc >> byte_pos) & 0x01; // the encoded parity bit uint8_t test_byte_enc = (test_nonce->nonce_enc >> (8*byte_pos)) & 0xff; // the encoded nonce byte - uint8_t test_byte_dec = crypto1_byte(&pcs, test_byte_enc /* ^ (cuid >> (8*byte_pos)) */, true) ^ test_byte_enc; // decode the nonce byte + uint8_t test_byte_dec = crypto1_byte(&pcs, test_byte_enc /* ^ (cuid >> (8*byte_pos)) */, true) ^ test_byte_enc; // decode the nonce byte uint8_t ks_par = filter(pcs.odd); // the keystream bit to encode/decode the parity bit uint8_t test_par_enc2 = ks_par ^ evenparity8(test_byte_dec); // determine the decoded byte's parity and encode it if (test_par_enc_bit != test_par_enc2) { @@ -138,10 +138,10 @@ bool verify_key(uint32_t cuid, noncelist_t *nonces, uint8_t *best_first_bytes, u } return true; } -static void* +static void* #ifdef __has_attribute #if __has_attribute(force_align_arg_pointer) - __attribute__((force_align_arg_pointer)) + __attribute__((force_align_arg_pointer)) #endif #endif crack_states_thread(void* x){ @@ -161,9 +161,9 @@ crack_states_thread(void* x){ while(current_bucket < bucket_count){ statelist_t *bucket = buckets[current_bucket]; if(bucket){ -#if defined (DEBUG_BRUTE_FORCE) +#if defined (DEBUG_BRUTE_FORCE) printf("Thread %u starts working on bucket %u\n", thread_id, current_bucket); -#endif +#endif const uint64_t key = crack_states_bitsliced(thread_arg->cuid, thread_arg->best_first_bytes, bucket, &keys_found, &num_keys_tested, nonces_to_bruteforce, bf_test_nonce_2nd_byte, thread_arg->nonces); if(key != -1){ __atomic_fetch_add(&keys_found, 1, __ATOMIC_SEQ_CST); @@ -173,7 +173,7 @@ crack_states_thread(void* x){ char keystr[18]; sprintf(keystr, "%012" PRIx64 " ", key); sprintf(progress_text, "Brute force phase completed. Key found: " _YELLOW_(%s), keystr); - hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, 0.0, 0); + hardnested_print_progress(thread_arg->num_acquired_nonces, progress_text, 0.0, 0); break; } else if(keys_found){ break; @@ -212,20 +212,20 @@ void prepare_bf_test_nonces(noncelist_t *nonces, uint8_t best_first_byte) // trailing_zeros(bf_test_nonce_2nd_byte[1] ^ bf_test_nonce_2nd_byte[0]), // trailing_zeros(bf_test_nonce_2nd_byte[2] ^ bf_test_nonce_2nd_byte[1]), // trailing_zeros(bf_test_nonce_2nd_byte[3] ^ bf_test_nonce_2nd_byte[2])); - + uint8_t best_4[4] = {0}; int sum_best = -1; for (uint16_t n1 = 0; n1 < nonces_to_bruteforce; n1++) { for (uint16_t n2 = 0; n2 < nonces_to_bruteforce; n2++) { if (n2 != n1) { for (uint16_t n3 = 0; n3 < nonces_to_bruteforce; n3++) { - if ((n3 != n2 && n3 != n1) || nonces_to_bruteforce < 3 - // && trailing_zeros(bf_test_nonce_2nd_byte[n1] ^ bf_test_nonce_2nd_byte[n2]) + if ((n3 != n2 && n3 != n1) || nonces_to_bruteforce < 3 + // && trailing_zeros(bf_test_nonce_2nd_byte[n1] ^ bf_test_nonce_2nd_byte[n2]) // > trailing_zeros(bf_test_nonce_2nd_byte[n2] ^ bf_test_nonce_2nd_byte[n3]) ) { for (uint16_t n4 = 0; n4 < nonces_to_bruteforce; n4++) { if ((n4 != n3 && n4 != n2 && n4 != n1) || nonces_to_bruteforce < 4 - // && trailing_zeros(bf_test_nonce_2nd_byte[n2] ^ bf_test_nonce_2nd_byte[n3]) + // && trailing_zeros(bf_test_nonce_2nd_byte[n2] ^ bf_test_nonce_2nd_byte[n3]) // > trailing_zeros(bf_test_nonce_2nd_byte[n3] ^ bf_test_nonce_2nd_byte[n4]) ) { int sum = nonces_to_bruteforce > 1 ? trailing_zeros(bf_test_nonce_2nd_byte[n1] ^ bf_test_nonce_2nd_byte[n2]) : 0.0 @@ -245,13 +245,13 @@ void prepare_bf_test_nonces(noncelist_t *nonces, uint8_t best_first_byte) } } } - + uint32_t bf_test_nonce_temp[4]; uint8_t bf_test_nonce_par_temp[4]; uint8_t bf_test_nonce_2nd_byte_temp[4]; for (uint8_t i = 0; i < 4 && i < nonces_to_bruteforce; i++) { - bf_test_nonce_temp[i] = bf_test_nonce[best_4[i]]; - + bf_test_nonce_temp[i] = bf_test_nonce[best_4[i]]; + bf_test_nonce_par_temp[i] = bf_test_nonce_par[best_4[i]]; bf_test_nonce_2nd_byte_temp[i] = bf_test_nonce_2nd_byte[best_4[i]]; } @@ -295,13 +295,13 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint write_benchfile(candidates); #endif bool silent = (bf_rate != NULL); - + keys_found = 0; num_keys_tested = 0; found_bs_key = 0; - + bitslice_test_nonces(nonces_to_bruteforce, bf_test_nonce, bf_test_nonce_par); - + // count number of states to go bucket_count = 0; for (statelist_t *p = candidates; p != NULL; p = p->next) { @@ -313,7 +313,7 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint uint64_t start_time = msclock(); -#if defined(__linux__) || defined(__APPLE__) +#if defined(__linux__) || defined(__APPLE__) if ( NUM_BRUTE_FORCE_THREADS < 0 ) return false; #endif @@ -328,7 +328,7 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint noncelist_t *nonces; uint8_t *best_first_bytes; } thread_args[NUM_BRUTE_FORCE_THREADS]; - + for (uint32_t i = 0; i < NUM_BRUTE_FORCE_THREADS; i++){ thread_args[i].thread_ID = i; thread_args[i].silent = silent; @@ -347,10 +347,10 @@ bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint if (bf_rate != NULL) *bf_rate = (float)num_keys_tested / ((float)elapsed_time / 1000.0); - + if ( keys_found > 0) *foundkey = found_bs_key; - + return (keys_found != 0); } @@ -361,7 +361,7 @@ static bool read_bench_data(statelist_t *test_candidates) { uint32_t temp = 0; uint32_t num_states = 0; uint32_t states_read = 0; - + char bench_file_path[strlen(get_my_executable_directory()) + strlen(TEST_BENCH_FILENAME) + 1]; strcpy(bench_file_path, get_my_executable_directory()); strcat(bench_file_path, TEST_BENCH_FILENAME); @@ -371,7 +371,7 @@ static bool read_bench_data(statelist_t *test_candidates) { return false; } bytes_read = fread(&nonces_to_bruteforce, 1, sizeof(nonces_to_bruteforce), benchfile); - if (bytes_read != sizeof(nonces_to_bruteforce)) { + if (bytes_read != sizeof(nonces_to_bruteforce)) { fclose(benchfile); return false; } @@ -388,7 +388,7 @@ static bool read_bench_data(statelist_t *test_candidates) { return false; } } - bytes_read = fread(&num_states, 1, sizeof(uint32_t), benchfile); + bytes_read = fread(&num_states, 1, sizeof(uint32_t), benchfile); if (bytes_read != sizeof(uint32_t)) { fclose(benchfile); return false; @@ -420,9 +420,9 @@ static bool read_bench_data(statelist_t *test_candidates) { for (uint32_t i = states_read; i < TEST_BENCH_SIZE; i++) { test_candidates->states[ODD_STATE][i] = test_candidates->states[ODD_STATE][i-states_read]; } - + fclose(benchfile); - return true; + return true; } @@ -435,7 +435,7 @@ float brute_force_benchmark() { test_candidates[i].next = test_candidates + i + 1; test_candidates[i+1].states[ODD_STATE] = test_candidates[0].states[ODD_STATE]; test_candidates[i+1].states[EVEN_STATE] = test_candidates[0].states[EVEN_STATE]; - } + } test_candidates[NUM_BRUTE_FORCE_THREADS-1].next = NULL; if (!read_bench_data(test_candidates)) { @@ -449,13 +449,13 @@ float brute_force_benchmark() { test_candidates[i].states[ODD_STATE][TEST_BENCH_SIZE] = -1; test_candidates[i].states[EVEN_STATE][TEST_BENCH_SIZE] = -1; } - + uint64_t maximum_states = TEST_BENCH_SIZE*TEST_BENCH_SIZE*(uint64_t)NUM_BRUTE_FORCE_THREADS; float bf_rate; uint64_t found_key = 0; brute_force_bs(&bf_rate, test_candidates, 0, 0, maximum_states, NULL, 0, &found_key); - + free(test_candidates[0].states[ODD_STATE]); free(test_candidates[0].states[EVEN_STATE]); diff --git a/client/hardnested/hardnested_bruteforce.h b/client/hardnested/hardnested_bruteforce.h index c978a82c3..68dc7442d 100644 --- a/client/hardnested/hardnested_bruteforce.h +++ b/client/hardnested/hardnested_bruteforce.h @@ -10,7 +10,7 @@ // attacks this doesn't rely on implementation errors but only on the // inherent weaknesses of the crypto1 cypher. Described in // Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened -// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on +// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on // Computer and Communications Security, 2015 //----------------------------------------------------------------------------- @@ -30,7 +30,7 @@ typedef struct { extern void prepare_bf_test_nonces(noncelist_t *nonces, uint8_t best_first_byte); extern bool brute_force_bs(float *bf_rate, statelist_t *candidates, uint32_t cuid, uint32_t num_acquired_nonces, uint64_t maximum_states, noncelist_t *nonces, uint8_t *best_first_bytes, uint64_t *found_key); extern float brute_force_benchmark(); -extern uint8_t trailing_zeros(uint8_t byte); +extern uint8_t trailing_zeros(uint8_t byte); extern bool verify_key(uint32_t cuid, noncelist_t *nonces, uint8_t *best_first_bytes, uint32_t odd, uint32_t even); #endif diff --git a/client/hardnested/hardnested_tables.c b/client/hardnested/hardnested_tables.c index 278ed9596..9a520603b 100644 --- a/client/hardnested/hardnested_tables.c +++ b/client/hardnested/hardnested_tables.c @@ -10,7 +10,7 @@ // attacks this doesn't rely on implementation errors but only on the // inherent weaknesses of the crypto1 cypher. Described in // Carlo Meijer, Roel Verdult, "Ciphertext-only Cryptanalysis on Hardened -// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on +// Mifare Classic Cards" in Proceedings of the 22nd ACM SIGSAC Conference on // Computer and Communications Security, 2015 //----------------------------------------------------------------------------- // @@ -39,7 +39,7 @@ typedef enum { static uint16_t PartialSumProperty(uint32_t state, odd_even_t odd_even) -{ +{ uint16_t sum = 0; for (uint16_t j = 0; j < 16; j++) { uint32_t st = state; @@ -203,7 +203,7 @@ static void init_part_sum_bitarrays(void) } } for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { - //printf("(%d, %" PRIu16 ")...", odd_even, part_sum_a0); + //printf("(%d, %" PRIu16 ")...", odd_even, part_sum_a0); for (uint32_t state = 0; state < (1<<20); state++) { uint16_t part_sum_a0 = PartialSumProperty(state, odd_even) / 2; for (uint16_t low_bits = 0; low_bits < 1<<4; low_bits++) { @@ -215,7 +215,7 @@ static void init_part_sum_bitarrays(void) } -static void free_part_sum_bitarrays(void) +static void free_part_sum_bitarrays(void) { printf("free_part_sum_bitarrays()..."); for (int16_t part_sum_a0 = (NUM_PART_SUMS-1); part_sum_a0 >= 0; part_sum_a0--) { @@ -257,7 +257,7 @@ void init_sum_bitarray(uint16_t sum_a0) printf("done.\n"); } - + static void free_sum_bitarray(void) { printf("free_sum_bitarray()..."); @@ -275,10 +275,10 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t #else #define NUM_TEST_STATES (1<<23) #endif - + time_t start_time = time(NULL); time_t last_check_time = start_time; - + uint32_t *restrict test_bitarray[2]; uint32_t *restrict test_not_bitarray[2]; @@ -291,7 +291,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t clear_bitarray24(test_not_bitarray[EVEN_STATE]); test_not_bitarray[ODD_STATE] = malloc_bitarray(sizeof(uint32_t) * (1<<19)); clear_bitarray24(test_not_bitarray[ODD_STATE]); - + uint32_t count[2]; bool all_odd_states_are_possible_for_notbitflip = false; @@ -302,7 +302,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t if (difftime(time_now, last_check_time) > 5*60) { // print status every 5 minutes float runtime = difftime(time_now, start_time); float remaining_time = runtime * ((1<<23) - even_state) / even_state; - printf("\n%1.1f hours elapsed, expected completion in %1.1f hours (%1.1f days)", runtime/3600, remaining_time/3600, remaining_time/3600/24); + printf("\n%1.1f hours elapsed, expected completion in %1.1f hours (%1.1f days)", runtime/3600, remaining_time/3600, remaining_time/3600/24); last_check_time = time_now; } for (uint32_t odd_state = next_state(sum_a0_bitarray[ODD_STATE], -1); odd_state < (1<<24); odd_state = next_state(test_bitarray[ODD_STATE], odd_state)) { @@ -319,15 +319,15 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t } cs_delta; cs_delta.odd = 0; cs_delta.even = 0; - + uint_fast16_t keystream = 0; - + // decrypt 9 bits for (int i = 0; i < 9; i++) { - uint_fast8_t keystream_bit = filter(cs.odd & 0x000fffff) ^ filter((cs.odd & 0x000fffff) ^ cs_delta.odd); + uint_fast8_t keystream_bit = filter(cs.odd & 0x000fffff) ^ filter((cs.odd & 0x000fffff) ^ cs_delta.odd); keystream = keystream << 1 | keystream_bit; uint_fast8_t nt_bit = BIT(bitflip, i) ^ keystream_bit; - uint_fast8_t LSFR_feedback = BIT(cs_delta.odd, 2) ^ BIT(cs_delta.even, 2) ^ BIT(cs_delta.odd, 3); + uint_fast8_t LSFR_feedback = BIT(cs_delta.odd, 2) ^ BIT(cs_delta.even, 2) ^ BIT(cs_delta.odd, 3); cs_delta.even = cs_delta.even << 1 | (LSFR_feedback ^ nt_bit); uint_fast8_t tmp = cs_delta.odd; @@ -341,7 +341,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t cs.odd = even_state >> (7 - i) / 2; } } - + if (evenparity32(keystream) == evenparity32(bitflip)) { // found valid bitflip state even_state_is_possible = true; @@ -353,7 +353,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t set_bit24(test_not_bitarray[EVEN_STATE], even_state); set_bit24(test_not_bitarray[EVEN_STATE], 1 << 23 | even_state); set_bit24(test_not_bitarray[ODD_STATE], odd_state); - } + } } if (!even_state_is_possible) { all_odd_states_are_possible_for_notbitflip = true; @@ -364,9 +364,9 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { count[odd_even] = count_states(test_bitarray[odd_even]); if (count[odd_even] != 1<<24) { - printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", - count[odd_even], - odd_even==EVEN_STATE?"even":"odd", + printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", + count[odd_even], + odd_even==EVEN_STATE?"even":"odd", bitflip, (1<<24) - count[odd_even], (float)((1<<24) - count[odd_even]) / (1<<24) * 100.0); #ifndef TEST_RUN @@ -391,9 +391,9 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t } count[odd_even] = count_states(test_bitarray_2nd); if (count[odd_even] != 1<<24) { - printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", - count[odd_even], - odd_even==EVEN_STATE?"even":"odd", + printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", + count[odd_even], + odd_even==EVEN_STATE?"even":"odd", bitflip | BITFLIP_2ND_BYTE, (1<<24) - count[odd_even], (float)((1<<24) - count[odd_even]) / (1<<24) * 100.0); #ifndef TEST_RUN @@ -418,7 +418,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t if (difftime(time_now, last_check_time) > 5*60) { // print status every 5 minutes float runtime = difftime(time_now, start_time); float remaining_time = runtime * ((1<<23) - even_state) / even_state; - printf("\n%1.1f hours elapsed, expected completion in %1.1f hours (%1.1f days)", runtime/3600, remaining_time/3600, remaining_time/3600/24); + printf("\n%1.1f hours elapsed, expected completion in %1.1f hours (%1.1f days)", runtime/3600, remaining_time/3600, remaining_time/3600/24); last_check_time = time_now; } for (uint32_t odd_state = next_state(sum_a0_bitarray[ODD_STATE], -1); odd_state < (1<<24); odd_state = next_state(sum_a0_bitarray[ODD_STATE], odd_state)) { @@ -438,16 +438,16 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t } cs_delta; cs_delta.odd = 0; cs_delta.even = 0; - + uint_fast16_t keystream = 0; // uint_fast16_t nt = 0; - + // decrypt 9 bits for (int i = 0; i < 9; i++) { - uint_fast8_t keystream_bit = filter(cs.odd & 0x000fffff) ^ filter((cs.odd & 0x000fffff) ^ cs_delta.odd); + uint_fast8_t keystream_bit = filter(cs.odd & 0x000fffff) ^ filter((cs.odd & 0x000fffff) ^ cs_delta.odd); keystream = keystream << 1 | keystream_bit; uint_fast8_t nt_bit = BIT(bitflip|0x100, i) ^ keystream_bit; - uint_fast8_t LSFR_feedback = BIT(cs_delta.odd, 2) ^ BIT(cs_delta.even, 2) ^ BIT(cs_delta.odd, 3); + uint_fast8_t LSFR_feedback = BIT(cs_delta.odd, 2) ^ BIT(cs_delta.even, 2) ^ BIT(cs_delta.odd, 3); cs_delta.even = cs_delta.even << 1 | (LSFR_feedback ^ nt_bit); uint_fast8_t tmp = cs_delta.odd; @@ -461,7 +461,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t cs.odd = even_state >> (7 - i) / 2; } } - + if (evenparity32(keystream) != evenparity32(bitflip)) { // found valid !bitflip state even_state_is_possible = true; @@ -471,14 +471,14 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t } } } - + printf("\nAnalysis completed. Checking for effective !bitflip properties...\n"); for (odd_even_t odd_even = EVEN_STATE; odd_even <= ODD_STATE; odd_even++) { count[odd_even] = count_states(test_not_bitarray[odd_even]); if (count[odd_even] != 1<<24) { - printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", - count[odd_even], - odd_even==EVEN_STATE?"even":"odd", + printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", + count[odd_even], + odd_even==EVEN_STATE?"even":"odd", bitflip|0x100, (1<<24) - count[odd_even], (float)((1<<24) - count[odd_even]) / (1<<24) * 100.0); #ifndef TEST_RUN @@ -503,9 +503,9 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t } count[odd_even] = count_states(test_bitarray_2nd); if (count[odd_even] != 1<<24) { - printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", - count[odd_even], - odd_even==EVEN_STATE?"even":"odd", + printf("Writing %d possible %s states for bitflip property %03x (%d (%1.2f%%) states eliminated)\n", + count[odd_even], + odd_even==EVEN_STATE?"even":"odd", bitflip | 0x100| BITFLIP_2ND_BYTE, (1<<24) - count[odd_even], (float)((1<<24) - count[odd_even]) / (1<<24) * 100.0); #ifndef TEST_RUN @@ -524,7 +524,7 @@ static void precalculate_bit0_bitflip_bitarrays(uint8_t const bitflip, uint16_t free_bitarray(test_not_bitarray[EVEN_STATE]); free_bitarray(test_bitarray[ODD_STATE]); free_bitarray(test_bitarray[EVEN_STATE]); - + exit(0); } @@ -533,7 +533,7 @@ int main (int argc, char *argv[]) { unsigned int bitflip_in; int sum_a0; - + printf("Create tables required by hardnested attack.\n"); printf("Expect a runtime in the range of days or weeks.\n"); printf("Single thread only. If you want to use several threads, start it multiple times :-)\n\n"); @@ -550,7 +550,7 @@ int main (int argc, char *argv[]) { printf("Bitflip property must be less than or equal to 0xff\n\n"); return 1; } - + if(argc == 3) { sscanf(argv[2], "%d", &sum_a0); } @@ -577,16 +577,16 @@ int main (int argc, char *argv[]) { case 256: break; default: sum_a0 = -1; } - + printf("Calculating for bitflip = %02x, sum_a0 = %d\n", bitflip_in, sum_a0); - + init_part_sum_bitarrays(); init_sum_bitarray(sum_a0); - + precalculate_bit0_bitflip_bitarrays(bitflip_in, sum_a0); free_sum_bitarray(); free_part_sum_bitarrays(); - + return 0; } \ No newline at end of file diff --git a/client/hid-flasher/proxusb.c b/client/hid-flasher/proxusb.c index eb0860ec1..45100e9ed 100644 --- a/client/hid-flasher/proxusb.c +++ b/client/hid-flasher/proxusb.c @@ -155,7 +155,7 @@ usb_dev_handle* findProxmark(int verbose, unsigned int *iface) else { iSelection = 1; } - + iSelection --; for (int i = 0; i < iUnit; i++) { diff --git a/client/hid-flasher/usb_cmd.h b/client/hid-flasher/usb_cmd.h index 59027c9d3..002c41252 100644 --- a/client/hid-flasher/usb_cmd.h +++ b/client/hid-flasher/usb_cmd.h @@ -200,7 +200,7 @@ typedef struct { #define CMD_MIFARE_SNIFFER 0x0630 //ultralightC #define CMD_MIFAREUC_AUTH 0x0724 -//0x0725 and 0x0726 no longer used +//0x0725 and 0x0726 no longer used #define CMD_MIFAREUC_SETPWD 0x0727 @@ -214,7 +214,7 @@ typedef struct { #define CMD_MIFARE_DESFIRE 0x072e #define CMD_MIFARE_COLLECT_NONCES 0x072f - + #define CMD_HF_SNIFFER 0x0800 #define CMD_UNKNOWN 0xFFFF diff --git a/client/jansson/lookup3.h b/client/jansson/lookup3.h index 2fe4c258f..ec2d0ffd6 100644 --- a/client/jansson/lookup3.h +++ b/client/jansson/lookup3.h @@ -3,8 +3,8 @@ lookup3.c, by Bob Jenkins, May 2006, Public Domain. These are functions for producing 32-bit hashes for hash table lookup. -hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() -are externally useful functions. Routines to test the hash are included +hashword(), hashlittle(), hashlittle2(), hashbig(), mix(), and final() +are externally useful functions. Routines to test the hash are included if SELF_TEST is defined. You can use this free for any purpose. It's in the public domain. It has no warranty. @@ -12,7 +12,7 @@ You probably want to use hashlittle(). hashlittle() and hashbig() hash byte arrays. hashlittle() is is faster than hashbig() on little-endian machines. Intel and AMD are little-endian machines. On second thought, you probably want hashlittle2(), which is identical to -hashlittle() except it returns two 32-bit hashes for the price of one. +hashlittle() except it returns two 32-bit hashes for the price of one. You could implement hashbig2() if you wanted but I haven't bothered here. If you want to find a hash of, say, exactly 7 integers, do @@ -25,9 +25,9 @@ If you want to find a hash of, say, exactly 7 integers, do then use c as the hash value. If you have a variable length array of 4-byte integers to hash, use hashword(). If you have a byte array (like a character string), use hashlittle(). If you have several byte arrays, or -a mix of things, see the comments above hashlittle(). +a mix of things, see the comments above hashlittle(). -Why is this so big? I read 12 bytes at a time into 3 4-byte integers, +Why is this so big? I read 12 bytes at a time into 3 4-byte integers, then mix those integers. This is fast (you can do a lot more thorough mixing with 12*3 instructions on 3 integers than you can with 3 instructions on 1 byte), but shoehorning those bytes into integers efficiently is messy. @@ -94,7 +94,7 @@ This was tested for: the output delta to a Gray code (a^(a>>1)) so a string of 1's (as is commonly produced by subtraction) look like a single 1-bit difference. -* the base values were pseudorandom, all zero but one bit set, or +* the base values were pseudorandom, all zero but one bit set, or all zero plus a counter that starts at zero. Some k values for my "a-=c; a^=rot(c,k); c+=b;" arrangement that @@ -104,7 +104,7 @@ satisfy this are 14 9 3 7 17 3 Well, "9 15 3 18 27 15" didn't quite get 32 bits diffing for "differ" defined as + with a one-bit base and a two-bit delta. I -used http://burtleburtle.net/bob/hash/avalanche.html to choose +used http://burtleburtle.net/bob/hash/avalanche.html to choose the operations, constants, and arrangements of the variables. This does not achieve avalanche. There are input bits of (a,b,c) @@ -143,7 +143,7 @@ produce values of c that look totally different. This was tested for the output delta to a Gray code (a^(a>>1)) so a string of 1's (as is commonly produced by subtraction) look like a single 1-bit difference. -* the base values were pseudorandom, all zero but one bit set, or +* the base values were pseudorandom, all zero but one bit set, or all zero plus a counter that starts at zero. These constants passed: @@ -236,7 +236,7 @@ static uint32_t hashlittle(const void *key, size_t length, uint32_t initval) } /*----------------------------- handle the last (probably partial) block */ - /* + /* * "k[2]&0xffffff" actually reads beyond the end of the string, but * then masks off the part it's not allowed to read. Because the * string is aligned, the masked-off tail is in the same word as the diff --git a/client/jansson/path.c b/client/jansson/path.c index e3098f5f4..785a3e824 100644 --- a/client/jansson/path.c +++ b/client/jansson/path.c @@ -3,7 +3,7 @@ * * Jansson is free software; you can redistribute it and/or modify * it under the terms of the MIT license. See LICENSE for details. - * + * * source here https://github.com/rogerz/jansson/blob/json_path/src/path.c */ diff --git a/client/loclass/cipher.c b/client/loclass/cipher.c index e8553ba6c..bf921c452 100644 --- a/client/loclass/cipher.c +++ b/client/loclass/cipher.c @@ -1,13 +1,13 @@ /***************************************************************************** * WARNING * - * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. - * - * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL - * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, - * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. - * - * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. + * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. + * + * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL + * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, + * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. + * + * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. * ***************************************************************************** * @@ -22,7 +22,7 @@ * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, or, at your option, any later version. + * by the Free Software Foundation, or, at your option, any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,8 +31,8 @@ * * You should have received a copy of the GNU General Public License * along with loclass. If not, see . - * - * + * + * ****************************************************************************/ @@ -218,7 +218,7 @@ void MAC(uint8_t* k, BitstreamIn input, BitstreamOut out) BitstreamIn input_32_zeroes = {zeroes_32,sizeof(zeroes_32)*8,0}; State initState = suc(k,init(k),&input); output(k,initState,&input_32_zeroes,&out); -} +} void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) { @@ -228,7 +228,7 @@ void doMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) memcpy(cc_nr, cc_nr_p, 12); memcpy(div_key, div_key_p, 8); - + reverse_arraybytes(cc_nr, 12); BitstreamIn bitstream = {cc_nr, 12 * 8, 0}; uint8_t dest []= {0,0,0,0,0,0,0,0}; diff --git a/client/loclass/cipher.h b/client/loclass/cipher.h index 632910a98..c6d2f0320 100644 --- a/client/loclass/cipher.h +++ b/client/loclass/cipher.h @@ -1,13 +1,13 @@ /***************************************************************************** * WARNING * - * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. - * - * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL - * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, - * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. - * - * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. + * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. + * + * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL + * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, + * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. + * + * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. * ***************************************************************************** * @@ -22,7 +22,7 @@ * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, or, at your option, any later version. + * by the Free Software Foundation, or, at your option, any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,8 +31,8 @@ * * You should have received a copy of the GNU General Public License * along with loclass. If not, see . - * - * + * + * ****************************************************************************/ diff --git a/client/loclass/cipherutils.c b/client/loclass/cipherutils.c index e22c88894..43b892fd8 100644 --- a/client/loclass/cipherutils.c +++ b/client/loclass/cipherutils.c @@ -1,13 +1,13 @@ /***************************************************************************** * WARNING * - * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. - * - * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL - * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, - * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. - * - * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. + * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. + * + * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL + * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, + * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. + * + * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. * ***************************************************************************** * @@ -22,7 +22,7 @@ * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, or, at your option, any later version. + * by the Free Software Foundation, or, at your option, any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,8 +31,8 @@ * * You should have received a copy of the GNU General Public License * along with loclass. If not, see . - * - * + * + * ****************************************************************************/ #include @@ -212,7 +212,7 @@ int testBitStream() //printf("Bits left: %d\n", bitsLeft(&in)); //printf("Bits out: %d\n", numBits(&out)); } - + if(memcmp(input, output, sizeof(input)) == 0) { PrintAndLogDevice(SUCCESS, " Bitstream test 1 ok"); } else { @@ -240,11 +240,11 @@ int testReversedBitstream() while (bitsLeft(&in) > 0) { pushBit(&reversed_out, tailBit(&in)); } - + while (bitsLeft(&reversed_in) > 0) { pushBit(&out, tailBit(&reversed_in)); } - + if (memcmp(input, output, sizeof(input)) == 0) { PrintAndLogDevice(SUCCESS, " Bitstream test 2 ok"); } else { diff --git a/client/loclass/cipherutils.h b/client/loclass/cipherutils.h index 21d11aac0..bc40c560b 100644 --- a/client/loclass/cipherutils.h +++ b/client/loclass/cipherutils.h @@ -1,13 +1,13 @@ /***************************************************************************** * WARNING * - * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. - * - * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL - * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, - * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. - * - * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. + * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. + * + * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL + * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, + * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. + * + * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. * ***************************************************************************** * @@ -22,7 +22,7 @@ * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, or, at your option, any later version. + * by the Free Software Foundation, or, at your option, any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,8 +31,8 @@ * * You should have received a copy of the GNU General Public License * along with loclass. If not, see . - * - * + * + * ****************************************************************************/ diff --git a/client/loclass/elite_crack.c b/client/loclass/elite_crack.c index 630fa72a6..fa370a940 100644 --- a/client/loclass/elite_crack.c +++ b/client/loclass/elite_crack.c @@ -1,13 +1,13 @@ /***************************************************************************** * WARNING * - * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. - * - * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL - * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, - * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. - * - * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. + * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. + * + * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL + * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, + * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. + * + * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. * ***************************************************************************** * @@ -22,7 +22,7 @@ * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, or, at your option, any later version. + * by the Free Software Foundation, or, at your option, any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,9 +31,9 @@ * * You should have received a copy of the GNU General Public License * along with loclass. If not, see . - * - * - * + * + * + * ****************************************************************************/ #include #include @@ -147,7 +147,7 @@ void hash1(uint8_t csn[] , uint8_t k[]) { k[5] = ~rl( csn[5] + k[3] ) + 1; k[6] = rr( csn[6] + (k[4] ^ 0x3c) ); k[7] = rl( csn[7] + (k[5] ^ 0xc3) ); - + k[7] &= 0x7F; k[6] &= 0x7F; k[5] &= 0x7F; @@ -217,7 +217,7 @@ void hash2(uint8_t *key64, uint8_t *outp_keytable) { int i; for (i=0; i<8; i++) key64_negated[i]= ~key64[i]; - + // Once again, key is on iclass-format desencrypt_iclass(key64, key64_negated, z[0]); @@ -319,7 +319,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) { int i; for (i=0; i<8; i++) { if (keytable[key_index[i]] & (CRACKED | BEING_CRACKED)) continue; - + bytes_to_recover[numbytes_to_recover++] = key_index[i]; keytable[key_index[i]] |= BEING_CRACKED; @@ -355,7 +355,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) { PrintAndLogDevice(INFO, "Bruteforcing byte %d", bytes_to_recover[i]); while (!found && !(brute & endmask)) { - + //Update the keytable with the brute-values for (i=0; i < numbytes_to_recover; i++) { keytable[bytes_to_recover[i]] &= 0xFF00; @@ -383,7 +383,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) { if (memcmp(calculated_MAC, item.mac, 4) == 0) { printf("\r\n"); for (i =0 ; i < numbytes_to_recover; i++) { - PrintAndLogDevice(INFO, "%d: 0x%02x", bytes_to_recover[i], 0xFF & keytable[bytes_to_recover[i]]); + PrintAndLogDevice(INFO, "%d: 0x%02x", bytes_to_recover[i], 0xFF & keytable[bytes_to_recover[i]]); } found = true; break; @@ -397,7 +397,7 @@ int bruteforceItem(dumpdata item, uint16_t keytable[]) { fflush(stdout); } } - + if (!found) { PrintAndLogDevice(NORMAL, "\n"); PrintAndLogDevice(WARNING, "Failed to recover %d bytes using the following CSN", numbytes_to_recover); printvar("[!] CSN", item.csn, 8); @@ -501,7 +501,7 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) { } free(attack); - PrintAndLogDevice(SUCCESS, "time: %" PRIu64 " seconds", (msclock()-t1)/1000); + PrintAndLogDevice(SUCCESS, "time: %" PRIu64 " seconds", (msclock()-t1)/1000); // Pick out the first 16 bytes of the keytable. // The keytable is now in 16-bit ints, where the upper 8 bits @@ -511,7 +511,7 @@ int bruteforceDump(uint8_t dump[], size_t dumpsize, uint16_t keytable[]) { for (i = 0 ; i < 16 ; i++) { first16bytes[i] = keytable[i] & 0xFF; - + if (!(keytable[i] & CRACKED)) PrintAndLogDevice(WARNING, "error, we are missing byte %d, custom key calculation will fail...", i); } @@ -551,7 +551,7 @@ int bruteforceFile(const char *filename, uint16_t keytable[]) { size_t bytes_read = fread(dump, 1, fsize, f); fclose(f); - + if (bytes_read < fsize) { PrintAndLogDevice(WARNING, "Error, could only read %d bytes (should be %d)", bytes_read, fsize ); } diff --git a/client/loclass/elite_crack.h b/client/loclass/elite_crack.h index 5413d84d0..f2cce1064 100644 --- a/client/loclass/elite_crack.h +++ b/client/loclass/elite_crack.h @@ -1,13 +1,13 @@ /***************************************************************************** * WARNING * - * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. - * - * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL - * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, - * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. - * - * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. + * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. + * + * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL + * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, + * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. + * + * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. * ***************************************************************************** * @@ -22,7 +22,7 @@ * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, or, at your option, any later version. + * by the Free Software Foundation, or, at your option, any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,8 +31,8 @@ * * You should have received a copy of the GNU General Public License * along with loclass. If not, see . - * - * + * + * ****************************************************************************/ diff --git a/client/loclass/fileutils.c b/client/loclass/fileutils.c index f9d4db8d1..c26bb2a5d 100644 --- a/client/loclass/fileutils.c +++ b/client/loclass/fileutils.c @@ -1,13 +1,13 @@ /***************************************************************************** * WARNING * - * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. - * - * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL - * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, - * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. - * - * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. + * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. + * + * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL + * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, + * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. + * + * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. * ***************************************************************************** * @@ -22,7 +22,7 @@ * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, or, at your option, any later version. + * by the Free Software Foundation, or, at your option, any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,8 +31,8 @@ * * You should have received a copy of the GNU General Public License * along with loclass. If not, see . - * - * + * + * ****************************************************************************/ #include "fileutils.h" @@ -101,12 +101,12 @@ int saveFileEML(const char *preferredName, const char *suffix, uint8_t* data, si sprintf(fileName,"%s-%d.%s", preferredName, num, suffix); num++; } - + /* We should have a valid filename now, e.g. dumpdata-3.bin */ /*Opening file for writing in text mode*/ FILE *f = fopen(fileName, "w+"); - if (!f) { + if (!f) { PrintAndLogDevice(WARNING, "file not found or locked. '" _YELLOW_(%s)"'", fileName); retval = 1; goto out; @@ -114,7 +114,7 @@ int saveFileEML(const char *preferredName, const char *suffix, uint8_t* data, si for (i = 0; i < datalen; i++) { fprintf(f, "%02X", data[i] ); - + // no extra line in the end if ( (i+1) % blocksize == 0 && currblock != blocks ) { fprintf(f, "\n"); @@ -131,8 +131,8 @@ int saveFileEML(const char *preferredName, const char *suffix, uint8_t* data, si fflush(f); fclose(f); PrintAndLogDevice(SUCCESS, "saved %d blocks to text file " _YELLOW_(%s), blocks, fileName); - -out: + +out: free(fileName); return retval; } @@ -165,13 +165,13 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty char path[PATH_MAX_LENGTH] = {0}; sprintf(path, "$.blocks.%d", i); JsonSaveBufAsHexCompact(root, path, &data[i * 16], 16); - + if (i == 0) { JsonSaveBufAsHexCompact(root, "$.Card.UID", &data[0], 4); JsonSaveBufAsHexCompact(root, "$.Card.SAK", &data[5], 1); JsonSaveBufAsHexCompact(root, "$.Card.ATQA", &data[6], 2); } - + if (mfIsSectorTrailer(i)) { memset(path, 0x00, sizeof(path)); sprintf(path, "$.SectorKeys.%d.KeyA", mfSectorNum(i)); @@ -216,7 +216,7 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty uint8_t uid[7] = {0}; memcpy(uid, tmp->data, 3); memcpy(uid+3, tmp->data+4, 4); - + JsonSaveBufAsHexCompact(root, "$.Card.UID", uid, sizeof(uid)); JsonSaveBufAsHexCompact(root, "$.Card.Version", tmp->version, sizeof(tmp->version)); JsonSaveBufAsHexCompact(root, "$.Card.TBO_0", tmp->tbo, sizeof(tmp->tbo)); @@ -233,7 +233,7 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty char path[PATH_MAX_LENGTH] = {0}; sprintf(path, "$.blocks.%d", i); - JsonSaveBufAsHexCompact(root, path, tmp->data + (i * 4), 4); + JsonSaveBufAsHexCompact(root, path, tmp->data + (i * 4), 4); } break; } @@ -248,7 +248,7 @@ int saveFileJSON(const char *preferredName, const char *suffix, JSONFileType fty PrintAndLogDevice(SUCCESS, "saved to json file " _YELLOW_(%s), fileName); json_decref(root); -out: +out: free(fileName); return retval; } @@ -270,7 +270,7 @@ int loadFile(const char *preferredName, const char *suffix, void* data, size_t* free(fileName); return 1; } - + // get filesize in order to malloc memory fseek(f, 0, SEEK_END); long fsize = ftell(f); @@ -281,14 +281,14 @@ int loadFile(const char *preferredName, const char *suffix, void* data, size_t* retval = 1; goto out; } - + uint8_t *dump = calloc(fsize, sizeof(uint8_t)); if ( !dump ) { PrintAndLogDevice(FAILED, "error, cannot allocate memory"); retval = 2; goto out; } - + size_t bytes_read = fread(dump, 1, fsize, f); if ( bytes_read != fsize ) { @@ -297,18 +297,18 @@ int loadFile(const char *preferredName, const char *suffix, void* data, size_t* retval = 3; goto out; } - + memcpy( (data), dump, bytes_read); free(dump); - + PrintAndLogDevice(SUCCESS, "loaded %d bytes from binary file " _YELLOW_(%s), bytes_read, fileName); - + *datalen = bytes_read; -out: +out: fclose(f); free(fileName); - + return retval; } @@ -330,12 +330,12 @@ int loadFileEML(const char *preferredName, const char *suffix, void* data, size_ retval = 1; goto out; } - - // 128 + 2 newline chars + 1 null terminator + + // 128 + 2 newline chars + 1 null terminator char line[131]; memset(line, 0, sizeof(line)); uint8_t buf[64] = {0x00}; - + while ( !feof(f) ) { memset(line, 0, sizeof(line)); @@ -346,10 +346,10 @@ int loadFileEML(const char *preferredName, const char *suffix, void* data, size_ retval = 2; goto out; } - + if ( line[0] == '#' ) continue; - + int res = param_gethex_to_eol(line, 0, buf, sizeof(buf), &hexlen); if (res == 0 || res == 1) { memcpy(data + counter, buf, hexlen); @@ -358,11 +358,11 @@ int loadFileEML(const char *preferredName, const char *suffix, void* data, size_ } fclose(f); PrintAndLogDevice(SUCCESS, "loaded %d bytes from text file " _YELLOW_(%s), counter, fileName); - + if ( datalen ) *datalen = counter; - -out: + +out: free(fileName); return retval; } @@ -372,7 +372,7 @@ int loadFileJSON(const char *preferredName, const char *suffix, void* data, size if ( preferredName == NULL ) return 1; if ( suffix == NULL ) return 1; if ( data == NULL ) return 1; - + *datalen = 0; json_t *root; json_error_t error; @@ -385,20 +385,20 @@ int loadFileJSON(const char *preferredName, const char *suffix, void* data, size root = json_load_file(fileName, 0, &error); if (!root) { PrintAndLog("ERROR: json " _YELLOW_(%s) " error on line %d: %s", fileName, error.line, error.text); - retval = 2; + retval = 2; goto out; } - + if (!json_is_object(root)) { PrintAndLog("ERROR: Invalid json " _YELLOW_(%s) " format. root must be an object.", fileName); - retval = 3; + retval = 3; goto out; } - + uint8_t *udata = (uint8_t *)data; char ctype[100] = {0}; JsonLoadStr(root, "$.FileType", ctype); - + if (!strcmp(ctype, "raw")) { JsonLoadBufAsHex(root, "$.raw", udata, maxdatalen, datalen); } @@ -413,15 +413,15 @@ int loadFileJSON(const char *preferredName, const char *suffix, void* data, size char path[30] = {0}; sprintf(path, "$.blocks.%d", i); - + size_t len = 0; JsonLoadBufAsHex(root, path, &udata[sptr], 16, &len); if (!len) break; - + sptr += len; } - + *datalen = sptr; } @@ -435,21 +435,21 @@ int loadFileJSON(const char *preferredName, const char *suffix, void* data, size char path[30] = {0}; sprintf(path, "$.blocks.%d", i); - + size_t len = 0; JsonLoadBufAsHex(root, path, &udata[sptr], 4, &len); if (!len) break; - + sptr += len; } - + *datalen = sptr; } - + PrintAndLog("loaded from JSON file " _YELLOW_(%s), fileName); -out: +out: json_decref(root); free(fileName); return retval; @@ -468,12 +468,12 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data if (keylen != 4 && keylen != 6 && keylen != 8) { keylen = 6; } - + // double up since its chars - keylen <<= 1; - + keylen <<= 1; + char line[255]; - + size_t counter = 0; int retval = 0; int size = sizeof(char) * (strlen(preferredName) + strlen(suffix) + 10); @@ -486,10 +486,10 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data retval = 1; goto out; } - + // read file while ( fgets(line, sizeof(line), f) ) { - + // add null terminator line[keylen] = 0; @@ -497,18 +497,18 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data if (strlen(line) < keylen) continue; - + // The line start with # is comment, skip if( line[0] == '#' ) continue; - + if (!isxdigit(line[0])){ PrintAndLogEx(FAILED, "file content error. '%s' must include " _BLUE_(%2d) "HEX symbols", line, keylen); continue; - } + } uint64_t key = strtoull(line, NULL, 16); - + num_to_bytes(key, keylen >> 1, data + counter); (*keycnt)++; memset(line, 0, sizeof(line)); @@ -516,12 +516,12 @@ int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data } fclose(f); PrintAndLogDevice(SUCCESS, "loaded " _GREEN_(%2d) "keys from dictionary file " _YELLOW_(%s), *keycnt, fileName); - - if ( datalen ) - *datalen = counter; -out: + + if ( datalen ) + *datalen = counter; +out: free(fileName); - return retval; + return retval; } #else //if we're on ARM diff --git a/client/loclass/fileutils.h b/client/loclass/fileutils.h index 9485707f1..94bc18e94 100644 --- a/client/loclass/fileutils.h +++ b/client/loclass/fileutils.h @@ -1,13 +1,13 @@ /***************************************************************************** * WARNING * - * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. - * - * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL - * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, - * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. - * - * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. + * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. + * + * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL + * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, + * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. + * + * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. * ***************************************************************************** * @@ -22,7 +22,7 @@ * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, or, at your option, any later version. + * by the Free Software Foundation, or, at your option, any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,8 +31,8 @@ * * You should have received a copy of the GNU General Public License * along with loclass. If not, see . - * - * + * + * ****************************************************************************/ #ifndef FILEUTILS_H @@ -153,7 +153,7 @@ extern int loadFileJSON(const char *preferredName, const char *suffix, void* dat extern int loadFileDICTIONARY(const char *preferredName, const char *suffix, void* data, size_t* datalen, uint8_t keylen, uint16_t* keycnt ); #define PrintAndLogDevice(level, format, args...) PrintAndLogEx(level, format , ## args) -#else +#else /** * Utility function to print to console. This is used consistently within the library instead @@ -164,7 +164,7 @@ extern int loadFileDICTIONARY(const char *preferredName, const char *suffix, voi */ #define PrintAndLogDevice(level, format, args...) { } - + #endif //ON_DEVICE #endif // FILEUTILS_H diff --git a/client/loclass/hash1_brute.c b/client/loclass/hash1_brute.c index 003a10423..d2ae822a5 100644 --- a/client/loclass/hash1_brute.c +++ b/client/loclass/hash1_brute.c @@ -38,13 +38,13 @@ void calc_score(uint8_t* csn, uint8_t* k) { score +=1; } } - + if (score >=2 && badscore < 2) { printf("CSN\t%02x%02x%02x%02x%02x%02x%02x%02x\t%02x %02x %02x %02x %02x %02x %02x %02x\t" ,csn[0],csn[1],csn[2],csn[3],csn[4],csn[5],csn[6],csn[7] ,k[0],k[1],k[2],k[3],k[4],k[5],k[6],k[7] ); - + for (i=0 ; i < score; i++) { printf("%d,", uniq_vals[i]); } @@ -62,7 +62,7 @@ void brute_hash1(void){ calc_score(testcsn,testkey); printf("Brute forcing hashones\n"); //exit(1); - + for (a=0; a < 256; a++) { //if(a > 0)printf("%d/256 done...\n", a); for (b=0; b < 256; b++) diff --git a/client/loclass/ikeys.c b/client/loclass/ikeys.c index c1265dc4d..847f90729 100644 --- a/client/loclass/ikeys.c +++ b/client/loclass/ikeys.c @@ -1,13 +1,13 @@ /***************************************************************************** * WARNING * - * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. - * - * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL - * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, - * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. - * - * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. + * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. + * + * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL + * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, + * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. + * + * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. * ***************************************************************************** * @@ -22,7 +22,7 @@ * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, or, at your option, any later version. + * by the Free Software Foundation, or, at your option, any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,8 +31,8 @@ * * You should have received a copy of the GNU General Public License * along with loclass. If not, see . - * - * + * + * ****************************************************************************/ /** @@ -207,7 +207,7 @@ void permute(BitstreamIn *p_in, uint64_t z,int l,int r, BitstreamOut* out) { if(bitsLeft(p_in) == 0) return; - + bool pn = tailBit(p_in); if( pn ) // pn = 1 { @@ -674,10 +674,10 @@ int doTestsWithKnownInputs() { static bool readKeyFile(uint8_t key[8]) { bool retval = false; - + //Test a few variants char filename[30] = {0}; - + if (fileExists("iclass_key.bin")){ sprintf(filename, "%s.bin", "iclass_key"); } else if (fileExists("loclass/iclass_key.bin")){ @@ -685,17 +685,17 @@ static bool readKeyFile(uint8_t key[8]) { } else if (fileExists("client/loclass/iclass_key.bin")){ sprintf(filename, "%s.bin", "client/loclass/iclass_key"); } - + if ( strlen(filename) == 0 ) return retval; - + FILE *f = fopen(filename, "rb"); if (!f) return retval; - + size_t bytes_read = fread(key, sizeof(uint8_t), 8, f); if ( bytes_read == 8) - retval = true; + retval = true; if (f) fclose(f); @@ -716,7 +716,7 @@ int doKeyTests(uint8_t debuglevel) { uint8_t j = 0; for (i = 0; i < sizeof(key); i++) j += key[i]; - + if (j != 185) { PrintAndLogDevice(INFO, "A key was loaded, but it does not seem to be the correct one. Aborting these tests"); } else { diff --git a/client/loclass/ikeys.h b/client/loclass/ikeys.h index 5b44d1796..7de3c582e 100644 --- a/client/loclass/ikeys.h +++ b/client/loclass/ikeys.h @@ -1,13 +1,13 @@ /***************************************************************************** * WARNING * - * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. - * - * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL - * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, - * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. - * - * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. + * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. + * + * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL + * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, + * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. + * + * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. * ***************************************************************************** * @@ -22,7 +22,7 @@ * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, or, at your option, any later version. + * by the Free Software Foundation, or, at your option, any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,8 +31,8 @@ * * You should have received a copy of the GNU General Public License * along with loclass. If not, see . - * - * + * + * ****************************************************************************/ #ifndef IKEYS_H diff --git a/client/loclass/main.c b/client/loclass/main.c index e0dcd48e2..e77cc8103 100644 --- a/client/loclass/main.c +++ b/client/loclass/main.c @@ -1,13 +1,13 @@ /***************************************************************************** * WARNING * - * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. - * - * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL - * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, - * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. - * - * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. + * THIS CODE IS CREATED FOR EXPERIMENTATION AND EDUCATIONAL USE ONLY. + * + * USAGE OF THIS CODE IN OTHER WAYS MAY INFRINGE UPON THE INTELLECTUAL + * PROPERTY OF OTHER PARTIES, SUCH AS INSIDE SECURE AND HID GLOBAL, + * AND MAY EXPOSE YOU TO AN INFRINGEMENT ACTION FROM THOSE PARTIES. + * + * THIS CODE SHOULD NEVER BE USED TO INFRINGE PATENTS OR INTELLECTUAL PROPERTY RIGHTS. * ***************************************************************************** * @@ -22,7 +22,7 @@ * * This is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 as published - * by the Free Software Foundation, or, at your option, any later version. + * by the Free Software Foundation, or, at your option, any later version. * * This file is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of @@ -31,8 +31,8 @@ * * You should have received a copy of the GNU General Public License * along with loclass. If not, see . - * - * + * + * ****************************************************************************/ diff --git a/client/mifare/mad.c b/client/mifare/mad.c index 96a4bf152..d2df7780c 100644 --- a/client/mifare/mad.c +++ b/client/mifare/mad.c @@ -15,7 +15,7 @@ // https://www.nxp.com/docs/en/application-note/AN10787.pdf static madAIDDescr madKnownAIDs[] = { - {0x0000, "free"}, + {0x0000, "free"}, {0x0001, "defect, e.g. access keys are destroyed or unknown"}, {0x0002, "reserved"}, {0x0003, "contains additional directory info"}, @@ -103,7 +103,7 @@ static const char *GetAIDDescription(uint16_t AID) { for(int i = 0; i < ARRAYLEN(madKnownClusterCodes); i++) if (madKnownClusterCodes[i].AID == (AID >> 8)) // high byte - cluster code return madKnownClusterCodes[i].Description; - + return unknownAID; } @@ -121,33 +121,33 @@ int madCRCCheck(uint8_t *sector, bool verbose, int MADver) { return 3; }; } - + return 0; } uint16_t madGetAID(uint8_t *sector, int MADver, int sectorNo) { if (MADver == 1) - return (sector[16 + 2 + (sectorNo - 1) * 2] << 8) + (sector[16 + 2 + (sectorNo - 1) * 2 + 1]); + return (sector[16 + 2 + (sectorNo - 1) * 2] << 8) + (sector[16 + 2 + (sectorNo - 1) * 2 + 1]); else - return (sector[2 + (sectorNo - 1) * 2] << 8) + (sector[2 + (sectorNo - 1) * 2 + 1]); + return (sector[2 + (sectorNo - 1) * 2] << 8) + (sector[2 + (sectorNo - 1) * 2 + 1]); } int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2) { int res = 0; - + if (!sector0) return 1; - + uint8_t GPB = sector0[3 * 16 + 9]; if (verbose) PrintAndLogEx(NORMAL, "GPB: 0x%02x", GPB); - + // DA (MAD available) if (!(GPB & 0x80)) { PrintAndLogEx(ERR, "DA=0! MAD not available."); return 1; } - + // MA (multi-application card) if (verbose) { if (GPB & 0x40) @@ -155,34 +155,34 @@ int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2) else PrintAndLogEx(NORMAL, "Single application card."); } - + uint8_t MADVer = GPB & 0x03; if (verbose) PrintAndLogEx(NORMAL, "MAD version: %d", MADVer); - + // MAD version if ((MADVer != 0x01) && (MADVer != 0x02)) { PrintAndLogEx(ERR, "Wrong MAD version: 0x%02x", MADVer); return 2; }; - + if (haveMAD2) *haveMAD2 = (MADVer == 2); res = madCRCCheck(sector0, true, 1); - + if (verbose && !res) PrintAndLogEx(NORMAL, "CRC8-MAD1 OK."); - + if (MADVer == 2 && sector10) { int res2 = madCRCCheck(sector10, true, 2); if (!res) - res = res2; + res = res2; if (verbose & !res2) PrintAndLogEx(NORMAL, "CRC8-MAD2 OK."); } - + return res; } @@ -190,12 +190,12 @@ int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen *madlen = 0; bool haveMAD2 = false; MADCheck(sector0, sector10, false, &haveMAD2); - + for (int i = 1; i < 16; i++) { mad[*madlen] = madGetAID(sector0, 1, i); (*madlen)++; } - + if (haveMAD2) { // mad2 sector (0x10 == 16dec) here mad[*madlen] = 0x0005; @@ -206,7 +206,7 @@ int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen (*madlen)++; } } - + return 0; } @@ -215,7 +215,7 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { // check MAD1 only MADCheck(sector, NULL, verbose, haveMAD2); - + // info byte uint8_t InfoByte = sector[16 + 1] & 0x3f; if (InfoByte) { @@ -226,13 +226,13 @@ int MAD1DecodeAndPrint(uint8_t *sector, bool verbose, bool *haveMAD2) { } if (InfoByte == 0x10 || InfoByte >= 0x28) PrintAndLogEx(WARNING, "Info byte error"); - + PrintAndLogEx(NORMAL, "00 MAD1"); for(int i = 1; i < 16; i++) { uint16_t AID = madGetAID(sector, 1, i); PrintAndLogEx(NORMAL, "%02d [%04X] %s", i, AID, GetAIDDescription(AID)); }; - + return 0; }; @@ -250,7 +250,7 @@ int MAD2DecodeAndPrint(uint8_t *sector, bool verbose) { for(int i = 1; i < 8 + 8 + 7 + 1; i++) { uint16_t AID = madGetAID(sector, 2, i); PrintAndLogEx(NORMAL, "%02d [%04X] %s", i + 16, AID, GetAIDDescription(AID)); - }; - + }; + return 0; }; diff --git a/client/mifare/mad.h b/client/mifare/mad.h index 6289982d9..d9dd3ff53 100644 --- a/client/mifare/mad.h +++ b/client/mifare/mad.h @@ -18,7 +18,7 @@ typedef struct { uint16_t AID; const char *Description; -} madAIDDescr; +} madAIDDescr; extern int MADCheck(uint8_t *sector0, uint8_t *sector10, bool verbose, bool *haveMAD2); extern int MADDecode(uint8_t *sector0, uint8_t *sector10, uint16_t *mad, size_t *madlen); diff --git a/client/mifare/mfkey.c b/client/mifare/mfkey.c index b35a3104c..e463c4505 100644 --- a/client/mifare/mfkey.c +++ b/client/mifare/mfkey.c @@ -22,7 +22,7 @@ int compare_uint64(const void *a, const void *b) { uint32_t intersection(uint64_t *listA, uint64_t *listB) { if (listA == NULL || listB == NULL) return 0; - + uint64_t *p1, *p2, *p3; p1 = p3 = listA; p2 = listB; @@ -56,7 +56,7 @@ uint32_t nonce2key(uint32_t uid, uint32_t nt, uint32_t nr, uint32_t ar, uint64_t for ( pos = 0; pos < 8; pos++ ) { ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0F; bt = (par_info >> (pos*8)) & 0xFF; - + par[7-pos][0] = (bt >> 0) & 1; par[7-pos][1] = (bt >> 1) & 1; par[7-pos][2] = (bt >> 2) & 1; @@ -128,15 +128,15 @@ bool mfkey32_moebius(nonces_t data, uint64_t *outputkey) { int counter = 0; uint32_t p640 = prng_successor(data.nonce, 64); uint32_t p641 = prng_successor(data.nonce2, 64); - + s = lfsr_recovery32(data.ar ^ p640, 0); - + for(t = s; t->odd | t->even; ++t) { lfsr_rollback_word(t, 0, 0); lfsr_rollback_word(t, data.nr, 1); lfsr_rollback_word(t, data.cuid ^ data.nonce, 0); crypto1_get_lfsr(t, &key); - + crypto1_word(t, data.cuid ^ data.nonce2, 0); crypto1_word(t, data.nr2, 1); if (data.ar2 == (crypto1_word(t, 0, 0) ^ p641)) { @@ -157,7 +157,7 @@ int mfkey64(nonces_t data, uint64_t *outputkey){ uint32_t ks2; // keystream used to encrypt reader response uint32_t ks3; // keystream used to encrypt tag response struct Crypto1State *revstate; - + // Extract the keystream from the messages ks2 = data.ar ^ prng_successor(data.nonce, 64); ks3 = data.at ^ prng_successor(data.nonce, 96); @@ -168,6 +168,6 @@ int mfkey64(nonces_t data, uint64_t *outputkey){ lfsr_rollback_word(revstate, data.cuid ^ data.nonce, 0); crypto1_get_lfsr(revstate, &key); crypto1_destroy(revstate); - *outputkey = key; + *outputkey = key; return 0; } diff --git a/client/mifare/mifare4.c b/client/mifare/mifare4.c index c95529a84..b829c564a 100644 --- a/client/mifare/mifare4.c +++ b/client/mifare/mifare4.c @@ -46,7 +46,7 @@ const char * mfpGetErrorDescription(uint8_t errorCode) { for(int i = 0; i < PlusErrorsLen; i++) if (errorCode == PlusErrors[i].Code) return PlusErrors[i].Description; - + return PlusErrors[0].Description; } @@ -74,11 +74,11 @@ AccessConditions_t MFAccessConditionsTrailer[] = { char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data) { static char StaticNone[] = "none"; - + uint8_t data1 = ((data[1] >> 4) & 0x0f) >> blockn; uint8_t data2 = ((data[2]) & 0x0f) >> blockn; uint8_t data3 = ((data[2] >> 4) & 0x0f) >> blockn; - + uint8_t cond = (data1 & 0x01) << 2 | (data2 & 0x01) << 1 | (data3 & 0x01); if (blockn == 3) { @@ -92,7 +92,7 @@ char *mfGetAccessConditionsDesc(uint8_t blockn, uint8_t *data) { return MFAccessConditions[i].description; } }; - + return StaticNone; }; @@ -124,9 +124,9 @@ int CalculateEncIVResponse(mf4Session *session, uint8_t *iv, bool verbose) { int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose) { if (!session || !session->Authenticated || !mac || !data || !datalen || datalen < 1) return 1; - + memset(mac, 0x00, 8); - + uint16_t ctr = session->R_Ctr; switch(mtype) { case mtypWriteCmd: @@ -162,23 +162,23 @@ int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t macdatalen = 1 + 6; break; } - + if (verbose) PrintAndLog("MAC data[%d]: %s", macdatalen, sprint_hex(macdata, macdatalen)); - + return aes_cmac8(NULL, session->Kmac, macdata, mac, macdatalen); } int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose) { uint8_t data[257] = {0}; int datalen = 0; - + uint8_t RndA[17] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x00}; uint8_t RndB[17] = {0}; - + if (session) - session->Authenticated = false; - + session->Authenticated = false; + uint8_t cmd1[] = {0x70, keyn[1], keyn[0], 0x00}; int res = ExchangeRAW14a(cmd1, sizeof(cmd1), activateField, true, data, sizeof(data), &datalen); if (res) { @@ -186,16 +186,16 @@ int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateF DropField(); return 2; } - + if (verbose) PrintAndLogEx(INFO, "phase2: %s", sprint_hex(cmd2, 33)); - + res = ExchangeRAW14a(cmd2, sizeof(cmd2), false, true, data, sizeof(data), &datalen); if (res) { PrintAndLogEx(ERR, "Exchande raw error: %d", res); DropField(); return 4; } - + if (verbose) PrintAndLogEx(INFO, "Kenc, kenc, 16); memmove(session->Kmac, kmac, 16); } - + if (verbose) PrintAndLogEx(INFO, "Authentication OK"); - + return 0; } int intExchangeRAW14aPlus(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { if(VerboseMode) PrintAndLogEx(INFO, ">>> %s", sprint_hex(datain, datainlen)); - + int res = ExchangeRAW14a(datain, datainlen, activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); if(VerboseMode) PrintAndLogEx(INFO, "<<< %s", sprint_hex(dataout, *dataoutlen)); - + return res; } int MFPWritePerso(uint8_t *keyNum, uint8_t *key, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { uint8_t rcmd[3 + 16] = {0xa8, keyNum[1], keyNum[0], 0x00}; memmove(&rcmd[3], key, 16); - + return intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); } int MFPCommitPerso(bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { uint8_t rcmd[1] = {0xaa}; - + return intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); } int MFPReadBlock(mf4Session *session, bool plain, uint8_t blockNum, uint8_t blockCount, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, uint8_t *mac) { - uint8_t rcmd[4 + 8] = {(plain?(0x37):(0x33)), blockNum, 0x00, blockCount}; + uint8_t rcmd[4 + 8] = {(plain?(0x37):(0x33)), blockNum, 0x00, blockCount}; if (!plain && session) CalculateMAC(session, mtypReadCmd, blockNum, blockCount, rcmd, 4, &rcmd[4], VerboseMode); - + int res = intExchangeRAW14aPlus(rcmd, plain?4:sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); if(res) return res; - if (session) + if (session) session->R_Ctr++; - + if(session && mac && *dataoutlen > 11) CalculateMAC(session, mtypReadResp, blockNum, blockCount, dataout, *dataoutlen - 8 - 2, mac, VerboseMode); - + return 0; } @@ -356,37 +356,37 @@ int MFPWriteBlock(mf4Session *session, uint8_t blockNum, uint8_t *data, bool act memmove(&rcmd[3], data, 16); if (session) CalculateMAC(session, mtypWriteCmd, blockNum, 1, rcmd, 19, &rcmd[19], VerboseMode); - + int res = intExchangeRAW14aPlus(rcmd, sizeof(rcmd), activateField, leaveSignalON, dataout, maxdataoutlen, dataoutlen); if(res) return res; - if (session) + if (session) session->W_Ctr++; - + if(session && mac && *dataoutlen > 3) CalculateMAC(session, mtypWriteResp, blockNum, 1, dataout, *dataoutlen, mac, VerboseMode); - + return 0; } int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *dataout, bool verbose){ uint8_t keyn[2] = {0}; bool plain = false; - + uint16_t uKeyNum = 0x4000 + sectorNo * 2 + (keyType ? 1 : 0); keyn[0] = uKeyNum >> 8; keyn[1] = uKeyNum & 0xff; if (verbose) PrintAndLogEx(INFO, "--sector[%d]:%02x key:%04x", mfNumBlocksPerSector(sectorNo), sectorNo, uKeyNum); - + mf4Session session; int res = MifareAuth4(&session, keyn, key, true, true, verbose); if (res) { PrintAndLogEx(ERR, "Sector %d authentication error: %d", sectorNo, res); return res; } - + uint8_t data[250] = {0}; int datalen = 0; uint8_t mac[8] = {0}; @@ -398,7 +398,7 @@ int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data DropField(); return res; } - + if (datalen && data[0] != 0x90) { PrintAndLogEx(ERR, "Sector %d card read error: %02x %s", sectorNo, data[0], mfpGetErrorDescription(data[0])); DropField(); @@ -411,31 +411,31 @@ int mfpReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data } memcpy(&dataout[(n - firstBlockNo) * 16], &data[1], 16); - + if (verbose) PrintAndLogEx(INFO, "data[%03d]: %s", n, sprint_hex(&data[1], 16)); - + if (memcmp(&data[1 + 16], mac, 8)) { PrintAndLogEx(WARNING, "WARNING: mac on block %d not equal...", n); PrintAndLogEx(WARNING, "MAC card: %s", sprint_hex(&data[1 + 16], 8)); PrintAndLogEx(WARNING, "MAC reader: %s", sprint_hex(mac, 8)); - + if (!verbose) - return 7; - } else { + return 7; + } else { if(verbose) PrintAndLogEx(INFO, "MAC: %s", sprint_hex(&data[1 + 16], 8)); } } DropField(); - return 0; + return 0; } // Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards), // plus evtl. 8 sectors with 16 blocks each (4k cards) uint8_t mfNumBlocksPerSector(uint8_t sectorNo) { - if (sectorNo < 32) + if (sectorNo < 32) return 4; else return 16; @@ -465,5 +465,5 @@ uint8_t mfSectorNum(uint8_t blockNo) { return blockNo / 4; else return 32 + (blockNo - 32 * 4) / 16; - + } diff --git a/client/mifare/mifare4.h b/client/mifare/mifare4.h index e4bf6e386..c41c05d2e 100644 --- a/client/mifare/mifare4.h +++ b/client/mifare/mifare4.h @@ -30,7 +30,7 @@ typedef struct { uint16_t R_Ctr; uint16_t W_Ctr; }mf4Session; - + typedef enum { mtypReadCmd, mtypReadResp, @@ -45,7 +45,7 @@ typedef struct { extern void mfpSetVerboseMode(bool verbose); extern const char * mfpGetErrorDescription(uint8_t errorCode); - + extern int CalculateMAC(mf4Session *session, MACType_t mtype, uint8_t blockNum, uint8_t blockCount, uint8_t *data, int datalen, uint8_t *mac, bool verbose); extern int MifareAuth4(mf4Session *session, uint8_t *keyn, uint8_t *key, bool activateField, bool leaveSignalON, bool verbose); diff --git a/client/mifare/mifarehost.c b/client/mifare/mifarehost.c index eb89e0389..1d1da1d1c 100644 --- a/client/mifare/mifarehost.c +++ b/client/mifare/mifarehost.c @@ -17,7 +17,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { uint64_t *keylist = NULL, *last_keylist = NULL; uint32_t keycount = 0; int16_t isOK = 0; - + UsbCommand c = {CMD_READER_MIFARE, {true, blockno, key_type}}; // message @@ -31,11 +31,11 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { SendCommand(&c); //flush queue - while (ukbhit()) { - int gc = getchar(); (void)gc; + while (ukbhit()) { + int gc = getchar(); (void)gc; return -5; } - + // wait cycle while (true) { printf("."); fflush(stdout); @@ -47,9 +47,9 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { isOK = resp.arg[0]; - if (isOK < 0) + if (isOK < 0) return isOK; - + uid = (uint32_t)bytes_to_num(resp.d.asBytes + 0, 4); nt = (uint32_t)bytes_to_num(resp.d.asBytes + 4, 4); par_list = bytes_to_num(resp.d.asBytes + 8, 8); @@ -60,7 +60,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { } } PrintAndLogEx(NORMAL, "\n"); - + if (par_list == 0 && c.arg[0] == true) { PrintAndLogEx(SUCCESS, "Parity is all zero. Most likely this card sends NACK on every authentication."); } @@ -92,7 +92,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { uint8_t keyBlock[USB_CMD_DATA_SIZE]; int max_keys = USB_CMD_DATA_SIZE / 6; for (int i = 0; i < keycount; i += max_keys) { - + int size = keycount - i > max_keys ? max_keys : keycount - i; for (int j = 0; j < size; j++) { if (par_list == 0) { @@ -101,12 +101,12 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { num_to_bytes(keylist[i*max_keys + j], 6, keyBlock+(j*6)); } } - + if (!mfCheckKeys(blockno, key_type - 0x60, false, size, keyBlock, key)) { break; } } - + if (*key != -1) { break; } else { @@ -121,7 +121,7 @@ int mfDarkside(uint8_t blockno, uint8_t key_type, uint64_t *key) { return 0; } int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keycnt, uint8_t * keyBlock, uint64_t * key){ - *key = -1; + *key = -1; UsbCommand c = {CMD_MIFARE_CHKKEYS, { (blockNo | (keyType << 8)), clear_trace, keycnt}}; memcpy(c.d.asBytes, keyBlock, 6 * keycnt); clearCommandBuffer(); @@ -133,9 +133,9 @@ int mfCheckKeys(uint8_t blockNo, uint8_t keyType, bool clear_trace, uint8_t keyc return 0; } -// Sends chunks of keys to device. +// Sends chunks of keys to device. // 0 == ok all keys found -// 1 == +// 1 == // 2 == Time-out, aborting int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, uint8_t strategy, uint32_t size, uint8_t *keyBlock, sector_t *e_sector, bool use_flashmemory) { @@ -143,8 +143,8 @@ int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, uint64_t t2 = msclock(); uint32_t timeout = 0; - // send keychunk - UsbCommand c = {CMD_MIFARE_CHKKEYS_FAST, { (sectorsCnt | (firstChunk << 8) | (lastChunk << 12) ), ((use_flashmemory << 8) | strategy), size}}; + // send keychunk + UsbCommand c = {CMD_MIFARE_CHKKEYS_FAST, { (sectorsCnt | (firstChunk << 8) | (lastChunk << 12) ), ((use_flashmemory << 8) | strategy), size}}; memcpy(c.d.asBytes, keyBlock, 6 * size); clearCommandBuffer(); SendCommand(&c); @@ -167,11 +167,11 @@ int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, uint8_t curr_keys = resp.arg[0]; PrintAndLogEx(SUCCESS, "\nChunk: %.1fs | found %u/%u keys (%u)", (float)(t2/1000.0), curr_keys, (sectorsCnt<<1), size); - - // all keys? + + // all keys? if ( curr_keys == sectorsCnt*2 || lastChunk ) { - - // success array. each byte is status of key + + // success array. each byte is status of key uint8_t arr[80]; uint64_t foo = 0; uint16_t bar = 0; @@ -180,10 +180,10 @@ int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, for (uint8_t i = 0; i < 64; i++) arr[i] = (foo >> i) & 0x1; - + for (uint8_t i = 0; i < 16; i++) arr[i+64] = (bar >> i) & 0x1; - + // initialize storage for found keys icesector_t *tmp = calloc(sectorsCnt, sizeof(icesector_t)); if (tmp == NULL) @@ -203,7 +203,7 @@ int mfCheckKeys_fast( uint8_t sectorsCnt, uint8_t firstChunk, uint8_t lastChunk, } } free(tmp); - + if ( curr_keys == sectorsCnt*2 ) return 0; if ( lastChunk ) @@ -226,11 +226,11 @@ int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultk memset(candidates, 0, sizeof(candidates)); memset(keyBlock, 0, sizeof(keyBlock)); - + // Generate all possible keys for the first two unknown bytes. - for (uint16_t i = 0; i < 0xFFFF; ++i) { - uint32_t j = i * 6; - candidates[0 + j] = i >> 8; + for (uint16_t i = 0; i < 0xFFFF; ++i) { + uint32_t j = i * 6; + candidates[0 + j] = i >> 8; candidates[1 + j] = i; candidates[2 + j] = key[2]; candidates[3 + j] = key[3]; @@ -241,7 +241,7 @@ int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultk for ( i = 0, counter = 1; i < CANDIDATE_SIZE; i += KEYBLOCK_SIZE, ++counter){ key64 = 0; - + // copy candidatekeys to test key block memcpy(keyBlock, candidates + i, KEYBLOCK_SIZE); @@ -251,8 +251,8 @@ int mfKeyBrute(uint8_t blockNo, uint8_t keyType, uint8_t *key, uint64_t *resultk found = true; break; } - - // progress + + // progress if ( counter % 20 == 0 ) PrintAndLogEx(SUCCESS, "tried : %s.. \t %u keys", sprint_hex(candidates + i, 6), counter * KEYS_IN_BLOCK ); } @@ -270,20 +270,20 @@ int Compare16Bits(const void * a, const void * b) { void #ifdef __has_attribute #if __has_attribute(force_align_arg_pointer) -__attribute__((force_align_arg_pointer)) +__attribute__((force_align_arg_pointer)) #endif #endif *nested_worker_thread(void *arg) { struct Crypto1State *p1; StateList_t *statelist = arg; - statelist->head.slhead = lfsr_recovery32(statelist->ks1, statelist->nt ^ statelist->uid); - + statelist->head.slhead = lfsr_recovery32(statelist->ks1, statelist->nt ^ statelist->uid); + for (p1 = statelist->head.slhead; *(uint64_t *)p1 != 0; p1++) {}; - + statelist->len = p1 - statelist->head.slhead; statelist->tail.sltail = --p1; qsort(statelist->head.slhead, statelist->len, sizeof(uint64_t), Compare16Bits); - + return statelist->head.slhead; } @@ -293,7 +293,7 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo UsbCommand resp; StateList_t statelists[2]; struct Crypto1State *p1, *p2, *p3, *p4; - + UsbCommand c = {CMD_MIFARE_NESTED, {blockNo + keyType * 0x100, trgBlockNo + trgKeyType * 0x100, calibrate}}; memcpy(c.d.asBytes, key, 6); clearCommandBuffer(); @@ -302,9 +302,9 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo // error during nested if (resp.arg[0]) return resp.arg[0]; - + memcpy(&uid, resp.d.asBytes, 4); - + for (i = 0; i < 2; i++) { statelists[i].blockNo = resp.arg[2] & 0xff; statelists[i].keyType = (resp.arg[2] >> 8) & 0xff; @@ -312,10 +312,10 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo 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 + + // calc keys pthread_t thread_id[2]; - + // create and run worker threads for (i = 0; i < 2; i++) pthread_create(thread_id + i, NULL, nested_worker_thread, &statelists[i]); @@ -327,12 +327,12 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo // the first 16 Bits of the cryptostate already contain part of our key. // Create the intersection of the two lists based on these 16 Bits and // roll back the cryptostate - p1 = p3 = statelists[0].head.slhead; + p1 = p3 = statelists[0].head.slhead; p2 = p4 = statelists[1].head.slhead; while (p1 <= statelists[0].tail.sltail && p2 <= statelists[1].tail.sltail) { if (Compare16Bits(p1, p2) == 0) { - + struct Crypto1State savestate, *savep = &savestate; savestate = *p1; while(Compare16Bits(p1, savep) == 0 && p1 <= statelists[0].tail.sltail) { @@ -381,15 +381,15 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo uint8_t keyBlock[USB_CMD_DATA_SIZE] = {0x00}; for (int i = 0; i < keycnt; i += max_keys) { - + int size = keycnt - i > max_keys ? max_keys : keycnt - i; - + for (int j = 0; j < size; j++) { crypto1_get_lfsr(statelists[0].head.slhead + i, &key64); num_to_bytes(key64, 6, keyBlock + i * 6); } - - if (!mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, size, keyBlock, &key64)) { + + if (!mfCheckKeys(statelists[0].blockNo, statelists[0].keyType, false, size, keyBlock, &key64)) { free(statelists[0].head.slhead); free(statelists[1].head.slhead); num_to_bytes(key64, 6, resultKey); @@ -400,14 +400,14 @@ int mfnested(uint8_t blockNo, uint8_t keyType, uint8_t * key, uint8_t trgBlockNo key64 ); return -5; - } + } } - + out: PrintAndLogEx(SUCCESS, "target block:%3u key type: %c", (uint16_t)resp.arg[2] & 0xff, (resp.arg[2] >> 8) ? 'B' : 'A' - ); + ); free(statelists[0].head.slhead); free(statelists[1].head.slhead); @@ -416,7 +416,7 @@ out: // MIFARE int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data) { - + UsbCommand c = {CMD_MIFARE_READSC, {sectorNo, keyType, 0}}; memcpy(c.d.asBytes, key, 6); clearCommandBuffer(); @@ -436,7 +436,7 @@ int mfReadSector(uint8_t sectorNo, uint8_t keyType, uint8_t *key, uint8_t *data) PrintAndLogEx(ERR, "Command execute timeout"); return 2; } - + return 0; } @@ -457,7 +457,7 @@ int mfEmlSetMem(uint8_t *data, int blockNum, int blocksCount) { 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); + memcpy(c.d.asBytes, data, blocksCount * blockBtWidth); clearCommandBuffer(); SendCommand(&c); return 0; @@ -473,27 +473,27 @@ int mfCSetUID(uint8_t *uid, uint8_t *atqa, uint8_t *sak, uint8_t *oldUID, uint8_ int old = mfCGetBlock(0, block0, params); if (old == 0) PrintAndLogEx(SUCCESS, "old block 0: %s", sprint_hex(block0, sizeof(block0))); - else - PrintAndLogEx(FAILED, "couldn't get old data. Will write over the last bytes of Block 0."); + else + PrintAndLogEx(FAILED, "couldn't get old data. Will write over the last bytes of Block 0."); // fill in the new values // UID - memcpy(block0, uid, 4); + memcpy(block0, uid, 4); // Mifare UID BCC block0[4] = block0[0] ^ block0[1] ^ block0[2] ^ block0[3]; // mifare classic SAK(byte 5) and ATQA(byte 6 and 7, reversed) if ( sak != NULL ) block0[5] = sak[0]; - + if ( atqa != NULL ) { block0[6] = atqa[1]; block0[7] = atqa[0]; } PrintAndLogEx(SUCCESS, "new block 0: %s", sprint_hex(block0,16)); - - if ( wipecard ) params |= MAGIC_WIPE; + + if ( wipecard ) params |= MAGIC_WIPE; if ( oldUID == NULL) params |= MAGIC_UID; - + return mfCSetBlock(0, block0, oldUID, params); } @@ -501,15 +501,15 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params) { uint8_t isOK = 0; UsbCommand c = {CMD_MIFARE_CSETBLOCK, {params, blockNo, 0}}; - memcpy(c.d.asBytes, data, 16); + memcpy(c.d.asBytes, data, 16); clearCommandBuffer(); SendCommand(&c); UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { isOK = resp.arg[0] & 0xff; - if (uid != NULL) + if (uid != NULL) memcpy(uid, resp.d.asBytes, 4); - if (!isOK) + if (!isOK) return 2; } else { PrintAndLogEx(WARNING, "command execute timeout"); @@ -520,14 +520,14 @@ int mfCSetBlock(uint8_t blockNo, uint8_t *data, uint8_t *uid, uint8_t params) { int mfCGetBlock(uint8_t blockNo, uint8_t *data, uint8_t params) { uint8_t isOK = 0; - UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, blockNo, 0}}; + UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, blockNo, 0}}; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { isOK = resp.arg[0] & 0xff; - if (!isOK) - return 2; + if (!isOK) + return 2; memcpy(data, resp.d.asBytes, 16); } else { PrintAndLogEx(WARNING, "command execute timeout"); @@ -567,7 +567,7 @@ int isTraceCardEmpty(void) { } int isBlockEmpty(int blockN) { - for (int i = 0; i < 16; i++) + for (int i = 0; i < 16; i++) if (traceCard[blockN * 16 + i] != 0) return 0; return 1; @@ -583,10 +583,10 @@ int loadTraceCard(uint8_t *tuid, uint8_t uidlen) { uint8_t buf8[64] = {0x00}; int i, blockNum; uint32_t tmp; - - if (!isTraceCardEmpty()) + + if (!isTraceCardEmpty()) saveTraceCard(); - + memset(traceCard, 0x00, 4096); memcpy(traceCard, tuid, uidlen); @@ -594,11 +594,11 @@ int loadTraceCard(uint8_t *tuid, uint8_t uidlen) { f = fopen(traceFileName, "r"); if (!f) return 1; - + blockNum = 0; - + while (!feof(f)){ - + memset(buf, 0, sizeof(buf)); if (fgets(buf, sizeof(buf), f) == NULL) { PrintAndLogEx(FAILED, "No trace file found or reading error."); @@ -632,19 +632,19 @@ int loadTraceCard(uint8_t *tuid, uint8_t uidlen) { } int saveTraceCard(void) { - + if ((!strlen(traceFileName)) || (isTraceCardEmpty())) return 0; - + FILE * f; f = fopen(traceFileName, "w+"); if ( !f ) return 1; // given 4096 tracecard size, these loop will only match a 1024, 1kb card memory - // 4086/16 == 256blocks. + // 4086/16 == 256blocks. for (uint16_t i = 0; i < 256; i++) { // blocks for (uint8_t j = 0; j < 16; j++) // bytes - fprintf(f, "%02X", *(traceCard + i * 16 + j)); - + fprintf(f, "%02X", *(traceCard + i * 16 + j)); + // no extra line in the end if ( i < 255 ) fprintf(f, "\n"); @@ -656,14 +656,14 @@ int saveTraceCard(void) { // int mfTraceInit(uint8_t *tuid, uint8_t uidlen, uint8_t *atqa, uint8_t sak, bool wantSaveToEmlFile) { - if (traceCrypto1) + if (traceCrypto1) crypto1_destroy(traceCrypto1); traceCrypto1 = NULL; - if (wantSaveToEmlFile) + if (wantSaveToEmlFile) loadTraceCard(tuid, uidlen); - + traceCard[4] = traceCard[0] ^ traceCard[1] ^ traceCard[2] ^ traceCard[3]; traceCard[5] = sak; memcpy(&traceCard[6], atqa, 2); @@ -676,16 +676,16 @@ int mfTraceInit(uint8_t *tuid, uint8_t uidlen, uint8_t *atqa, uint8_t sak, bool void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len, bool isEncrypted){ uint8_t bt = 0; int i; - + if (len != 1) { for (i = 0; i < len; i++) data[i] = crypto1_byte(pcs, 0x00, isEncrypted) ^ data[i]; } else { - bt = 0; + bt = 0; bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 0)) << 0; bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 1)) << 1; bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 2)) << 2; - bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 3)) << 3; + bt |= (crypto1_bit(pcs, 0, isEncrypted) ^ BIT(data[0], 3)) << 3; data[0] = bt; } } @@ -699,28 +699,28 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { traceState = TRACE_ERROR; return 1; } - + uint8_t data[255]; memset(data, 0x00, sizeof(data)); - + memcpy(data, data_src, len); - + if ((traceCrypto1) && ((traceState == TRACE_IDLE) || (traceState > TRACE_AUTH_OK))) { mf_crypto1_decrypt(traceCrypto1, data, len, 0); PrintAndLogEx(NORMAL, "DEC| %s", sprint_hex(data, len)); - AddLogHex(logHexFileName, "DEC| ", data, len); + AddLogHex(logHexFileName, "DEC| ", data, len); } - + switch (traceState) { - case TRACE_IDLE: + case TRACE_IDLE: // check packet crc16! if ((len >= 4) && (!check_crc(CRC_14443_A, data, len))) { PrintAndLogEx(NORMAL, "DEC| CRC ERROR!!!"); - AddLogLine(logHexFileName, "DEC| ", "CRC ERROR!!!"); + AddLogLine(logHexFileName, "DEC| ", "CRC ERROR!!!"); traceState = TRACE_ERROR; // do not decrypt the next commands return 1; } - + // AUTHENTICATION if ((len == 4) && ((data[0] == MIFARE_AUTH_KEYA) || (data[0] == MIFARE_AUTH_KEYB))) { traceState = TRACE_AUTH1; @@ -750,7 +750,7 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { } return 0; - case TRACE_READ_DATA: + case TRACE_READ_DATA: if (len == 18) { traceState = TRACE_IDLE; @@ -766,7 +766,7 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { return 1; } break; - case TRACE_WRITE_OK: + case TRACE_WRITE_OK: if ((len == 1) && (data[0] == 0x0a)) { traceState = TRACE_WRITE_DATA; return 0; @@ -775,7 +775,7 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { return 1; } break; - case TRACE_WRITE_DATA: + case TRACE_WRITE_DATA: if (len == 18) { traceState = TRACE_IDLE; memcpy(traceCard + traceCurBlock * 16, data, 16); @@ -786,7 +786,7 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { return 1; } break; - case TRACE_AUTH1: + case TRACE_AUTH1: if (len == 4) { traceState = TRACE_AUTH2; nt = bytes_to_num(data, 4); @@ -796,7 +796,7 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { return 1; } break; - case TRACE_AUTH2: + case TRACE_AUTH2: if (len == 8) { traceState = TRACE_AUTH_OK; nr_enc = bytes_to_num(data, 4); @@ -807,11 +807,11 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { return 1; } break; - case TRACE_AUTH_OK: + case TRACE_AUTH_OK: if (len == 4) { traceState = TRACE_IDLE; at_enc = bytes_to_num(data, 4); - + // mfkey64 recover key. ks2 = ar_enc ^ prng_successor(nt, 64); ks3 = at_enc ^ prng_successor(nt, 96); @@ -822,37 +822,37 @@ int mfTraceDecode(uint8_t *data_src, int len, bool wantSaveToEmlFile) { lfsr_rollback_word(revstate, cuid ^ nt, 0); crypto1_get_lfsr(revstate, &key); PrintAndLogEx(SUCCESS, "found Key: [%012" PRIx64 "]", key); - + //if ( tryMfk64(cuid, nt, nr_enc, ar_enc, at_enc, &key) ) - AddLogUint64(logHexFileName, "Found Key: ", key); - + AddLogUint64(logHexFileName, "Found Key: ", key); + int blockShift = ((traceCurBlock & 0xFC) + 3) * 16; - if (isBlockEmpty((traceCurBlock & 0xFC) + 3)) + if (isBlockEmpty((traceCurBlock & 0xFC) + 3)) memcpy(traceCard + blockShift + 6, trailerAccessBytes, 4); - + // keytype A/B if (traceCurKey) num_to_bytes(key, 6, traceCard + blockShift + 10); else num_to_bytes(key, 6, traceCard + blockShift); - + if (wantSaveToEmlFile) saveTraceCard(); if (traceCrypto1) crypto1_destroy(traceCrypto1); - + // set cryptosystem state - traceCrypto1 = lfsr_recovery64(ks2, ks3); + traceCrypto1 = lfsr_recovery64(ks2, ks3); } else { PrintAndLogEx(NORMAL, "[!] nested key recovery not implemented!\n"); at_enc = bytes_to_num(data, 4); - crypto1_destroy(traceCrypto1); + crypto1_destroy(traceCrypto1); traceState = TRACE_ERROR; } break; - default: + default: traceState = TRACE_ERROR; return 1; } @@ -871,30 +871,30 @@ int tryDecryptWord(uint32_t nt, uint32_t ar_enc, uint32_t at_enc, uint8_t *data, return 0; } -/* Detect Tag Prng, +/* Detect Tag Prng, * function performs a partial AUTH, where it tries to authenticate against block0, key A, but only collects tag nonce. * the tag nonce is check to see if it has a predictable PRNG. -* @returns +* @returns * TRUE if tag uses WEAK prng (ie Now the NACK bug also needs to be present for Darkside attack) * FALSE is tag uses HARDEND prng (ie hardnested attack possible, with known key) */ int detect_classic_prng(void){ - UsbCommand resp, respA; + UsbCommand resp, respA; uint8_t cmd[] = {MIFARE_AUTH_KEYA, 0x00}; uint32_t flags = ISO14A_CONNECT | ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_RATS; - + UsbCommand c = {CMD_READER_ISO_14443a, {flags, sizeof(cmd), 0}}; memcpy(c.d.asBytes, cmd, sizeof(cmd)); clearCommandBuffer(); - SendCommand(&c); - + SendCommand(&c); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { PrintAndLogEx(WARNING, "PRNG UID: Reply timeout."); return -1; } - + // if select tag failed. if ( resp.arg[0] == 0 ) { PrintAndLogEx(WARNING, "error: selecting tag failed, can't detect prng\n"); @@ -909,12 +909,12 @@ int detect_classic_prng(void){ if (respA.arg[0] != 4) { PrintAndLogEx(WARNING, "PRNG data error: Wrong length: %d", respA.arg[0]); return -4; - } + } uint32_t nonce = bytes_to_num(respA.d.asBytes, respA.arg[0]); return validate_prng_nonce(nonce); } -/* Detect Mifare Classic NACK bug +/* Detect Mifare Classic NACK bug returns: 0 = error during test / aborted @@ -923,25 +923,25 @@ returns: 3 = always leak nacks (clones) */ int detect_classic_nackbug(bool verbose){ - + UsbCommand c = {CMD_MIFARE_NACK_DETECT, {0, 0, 0}}; clearCommandBuffer(); SendCommand(&c); UsbCommand resp; - + if ( verbose ) PrintAndLogEx(SUCCESS, "press pm3-button on the proxmark3 device to abort both proxmark3 and client.\n"); - - // for nice animation + + // for nice animation bool term = !isatty(STDIN_FILENO); #if defined(__linux__) || (__APPLE__) char star[] = {'-', '\\', '|', '/'}; - uint8_t staridx = 0; -#endif + uint8_t staridx = 0; +#endif while (true) { - if (term) { + if (term) { printf("."); } else { printf( @@ -958,21 +958,21 @@ int detect_classic_nackbug(bool verbose){ return -1; break; } - + if (WaitForResponseTimeout(CMD_ACK, &resp, 500)) { int32_t ok = resp.arg[0]; uint32_t nacks = resp.arg[1]; uint32_t auths = resp.arg[2]; PrintAndLogEx(NORMAL, ""); - + if ( verbose ) { PrintAndLogEx(SUCCESS, "num of auth requests : %u", auths); PrintAndLogEx(SUCCESS, "num of received NACK : %u", nacks); } switch( ok ) { case 99 : PrintAndLogEx(WARNING, "button pressed. Aborted."); return 0; - case 96 : - case 98 : { + case 96 : + case 98 : { if (verbose) PrintAndLogEx(FAILED, "card random number generator is not predictable."); PrintAndLogEx(WARNING, "detection failed"); @@ -981,10 +981,10 @@ int detect_classic_nackbug(bool verbose){ case 97 : { if (verbose) { PrintAndLogEx(FAILED, "card random number generator seems to be based on the well-known generating polynomial"); - PrintAndLogEx(NORMAL, "[- ]with 16 effective bits only, but shows unexpected behavior, try again."); + PrintAndLogEx(NORMAL, "[- ]with 16 effective bits only, but shows unexpected behavior, try again."); } return 2; - } + } case 2 : PrintAndLogEx(SUCCESS, _GREEN_(always leak NACK detected)); return 3; case 1 : PrintAndLogEx(SUCCESS, _GREEN_(NACK bug detected)); return 1; case 0 : PrintAndLogEx(SUCCESS, "No NACK bug detected"); return 2; @@ -992,12 +992,12 @@ int detect_classic_nackbug(bool verbose){ } break; } - } + } return 0; } /* try to see if card responses to "chinese magic backdoor" commands. */ void detect_classic_magic(void) { - + uint8_t isGeneration = 0; UsbCommand resp; UsbCommand c = {CMD_MIFARE_CIDENT, {0, 0, 0}}; @@ -1005,11 +1005,11 @@ void detect_classic_magic(void) { SendCommand(&c); if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) isGeneration = resp.arg[0] & 0xff; - + switch( isGeneration ){ case 1: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 1a): " _GREEN_(YES)); break; case 2: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 1b): " _GREEN_(YES)); break; //case 4: PrintAndLogEx(SUCCESS, "Answers to magic commands (GEN 2): " _GREEN_(YES)); break; default: PrintAndLogEx(INFO, "Answers to magic commands: " _YELLOW_(NO)); break; - } + } } \ No newline at end of file diff --git a/client/mifare/mifarehost.h b/client/mifare/mifarehost.h index 917cf5557..e0f4eaadd 100644 --- a/client/mifare/mifarehost.h +++ b/client/mifare/mifarehost.h @@ -55,7 +55,7 @@ typedef struct { uint32_t nt; uint32_t ks1; } StateList_t; - + typedef struct { uint64_t Key[2]; uint8_t foundKey[2]; diff --git a/client/mifare/ndef.c b/client/mifare/ndef.c index 6c7e12229..e8edc19da 100644 --- a/client/mifare/ndef.c +++ b/client/mifare/ndef.c @@ -89,7 +89,7 @@ uint16_t ndefTLVGetLength(uint8_t *data, size_t *indx) { len = data[0]; *indx += 1; } - + return len; } @@ -107,12 +107,12 @@ int ndefDecodeHeader(uint8_t *data, size_t datalen, NDEFHeader_t *header) { header->len = 1 + 1 + (header->ShortRecordBit ? 1 : 4) + (header->IDLenPresent ? 1 : 0); // header + typelen + payloadlen + idlen if (header->len > datalen) return 1; - + header->TypeLen = data[1]; header->Type = data + header->len; - + header->PayloadLen = (header->ShortRecordBit ? (data[2]) : ((data[2] << 24) + (data[3] << 16) + (data[4] << 8) + data[5])); - + if (header->IDLenPresent) { header->IDLen = (header->ShortRecordBit ? (data[3]) : (data[6])); header->Payload = header->Type + header->TypeLen; @@ -121,9 +121,9 @@ int ndefDecodeHeader(uint8_t *data, size_t datalen, NDEFHeader_t *header) { } header->Payload = header->Type + header->TypeLen + header->IDLen; - + header->RecLen = header->len + header->TypeLen + header->PayloadLen + header->IDLen; - + if (header->RecLen > datalen) return 3; @@ -132,7 +132,7 @@ int ndefDecodeHeader(uint8_t *data, size_t datalen, NDEFHeader_t *header) { int ndefPrintHeader(NDEFHeader_t *header) { PrintAndLogEx(INFO, "Header:"); - + PrintAndLogEx(NORMAL, "\tMessage Begin: %s", STRBOOL(header->MessageBegin)); PrintAndLogEx(NORMAL, "\tMessage End: %s", STRBOOL(header->MessageEnd)); PrintAndLogEx(NORMAL, "\tChunk Flag: %s", STRBOOL(header->ChunkFlag)); @@ -157,21 +157,21 @@ int ndefDecodeSig(uint8_t *sig, size_t siglen) { return 1; } indx++; - + uint8_t sigType = sig[indx] & 0x7f; bool sigURI = sig[indx] & 0x80; PrintAndLogEx(NORMAL, "\tsignature type: %s", ((sigType < stNA) ? ndefSigType_s[sigType] : ndefSigType_s[stNA])); PrintAndLogEx(NORMAL, "\tsignature uri: %s", (sigURI ? "present" : "not present")); - + size_t intsiglen = (sig[indx + 1] << 8) + sig[indx + 2]; // ecdsa 0x04 if (sigType == stECDSA) { indx += 3; PrintAndLogEx(NORMAL, "\tsignature [%d]: %s", intsiglen, sprint_hex_inrow(&sig[indx], intsiglen)); - - uint8_t rval[300] = {0}; - uint8_t sval[300] = {0}; + + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; int res = ecdsa_asn1_get_signature(&sig[indx], intsiglen, rval, sval); if (!res) { PrintAndLogEx(NORMAL ,"\t\tr: %s", sprint_hex(rval, 32)); @@ -179,28 +179,28 @@ int ndefDecodeSig(uint8_t *sig, size_t siglen) { } } indx += intsiglen; - + if (sigURI) { size_t intsigurilen = (sig[indx] << 8) + sig[indx + 1]; indx += 2; - PrintAndLogEx(NORMAL, "\tsignature uri [%d]: %.*s", intsigurilen, intsigurilen, &sig[indx]); + PrintAndLogEx(NORMAL, "\tsignature uri [%d]: %.*s", intsigurilen, intsigurilen, &sig[indx]); indx += intsigurilen; } - + uint8_t certFormat = (sig[indx] >> 4) & 0x07; uint8_t certCount = sig[indx] & 0x0f; bool certURI = sig[indx] & 0x80; - + PrintAndLogEx(NORMAL, "\tcertificate format: %s", ((certFormat < sfNA) ? ndefCertificateFormat_s[certFormat] : ndefCertificateFormat_s[sfNA])); PrintAndLogEx(NORMAL, "\tcertificates count: %d", certCount); - + // print certificates indx++; for (int i = 0; i < certCount; i++) { size_t intcertlen = (sig[indx + 1] << 8) + sig[indx + 2]; indx += 2; - - PrintAndLogEx(NORMAL, "\tcertificate %d [%d]: %s", i + 1, intcertlen, sprint_hex_inrow(&sig[indx], intcertlen)); + + PrintAndLogEx(NORMAL, "\tcertificate %d [%d]: %s", i + 1, intcertlen, sprint_hex_inrow(&sig[indx], intcertlen)); indx += intcertlen; } @@ -208,32 +208,32 @@ int ndefDecodeSig(uint8_t *sig, size_t siglen) { if ((indx <= siglen) && certURI) { size_t inturilen = (sig[indx] << 8) + sig[indx + 1]; indx += 2; - PrintAndLogEx(NORMAL, "\tcertificate uri [%d]: %.*s", inturilen, inturilen, &sig[indx]); + PrintAndLogEx(NORMAL, "\tcertificate uri [%d]: %.*s", inturilen, inturilen, &sig[indx]); indx += inturilen; } - + return 0; }; int ndefDecodePayload(NDEFHeader_t *ndef) { - + switch(ndef->TypeNameFormat) { case tnfWellKnownRecord: PrintAndLogEx(INFO, "Well Known Record"); PrintAndLogEx(NORMAL, "\ttype: %.*s", ndef->TypeLen, ndef->Type); - + if (!strncmp((char *)ndef->Type, "T", ndef->TypeLen)) { PrintAndLogEx(NORMAL, "\ttext : %.*s", ndef->PayloadLen, ndef->Payload); } - + if (!strncmp((char *)ndef->Type, "U", ndef->TypeLen)) { PrintAndLogEx(NORMAL, "\turi : %s%.*s", (ndef->Payload[0] <= 0x23 ? URI_s[ndef->Payload[0]] : "[err]"), ndef->PayloadLen, &ndef->Payload[1]); } - + if (!strncmp((char *)ndef->Type, "Sig", ndef->TypeLen)) { ndefDecodeSig(ndef->Payload, ndef->PayloadLen); } - + break; case tnfAbsoluteURIRecord: PrintAndLogEx(INFO, "Absolute URI Record"); @@ -242,7 +242,7 @@ int ndefDecodePayload(NDEFHeader_t *ndef) { break; default: break; - } + } return 0; } @@ -251,9 +251,9 @@ int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { int res = ndefDecodeHeader(ndefRecord, ndefRecordLen, &NDEFHeader); if (res) return res; - + ndefPrintHeader(&NDEFHeader); - + if (NDEFHeader.TypeLen) { PrintAndLogEx(INFO, "Type data:"); dump_buffer(NDEFHeader.Type, NDEFHeader.TypeLen, stdout, 1); @@ -275,13 +275,13 @@ int ndefRecordDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { int ndefRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { bool firstRec = true; size_t len = 0; - + while (len < ndefRecordLen) { NDEFHeader_t NDEFHeader = {0}; int res = ndefDecodeHeader(&ndefRecord[len], ndefRecordLen - len, &NDEFHeader); if (res) return res; - + if (firstRec) { if (!NDEFHeader.MessageBegin) { PrintAndLogEx(ERR, "NDEF first record have MessageBegin=false!"); @@ -289,27 +289,27 @@ int ndefRecordsDecodeAndPrint(uint8_t *ndefRecord, size_t ndefRecordLen) { } firstRec = false; } - + if (NDEFHeader.MessageEnd && len + NDEFHeader.RecLen != ndefRecordLen) { PrintAndLogEx(ERR, "NDEF records have wrong length. Must be %d, calculated %d", ndefRecordLen, len + NDEFHeader.RecLen); return 1; } - - ndefRecordDecodeAndPrint(&ndefRecord[len], NDEFHeader.RecLen); - + + ndefRecordDecodeAndPrint(&ndefRecord[len], NDEFHeader.RecLen); + len += NDEFHeader.RecLen; - + if (NDEFHeader.MessageEnd) break; - } - + } + return 0; } int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { - + size_t indx = 0; - + PrintAndLogEx(INFO, "NDEF decoding:"); while (indx < ndefLen) { switch (ndef[indx]) { @@ -326,11 +326,11 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { indx++; uint16_t len = ndefTLVGetLength(&ndef[indx], &indx); PrintAndLogEx(INFO, "-- NDEF message. len: %d", len); - + int res = ndefRecordsDecodeAndPrint(&ndef[indx], len); if (res) return res; - + indx += len; break; } @@ -350,8 +350,8 @@ int NDEFDecodeAndPrint(uint8_t *ndef, size_t ndefLen, bool verbose) { PrintAndLogEx(ERR, "unknown tag 0x%02x", ndef[indx]); return 1; } - } + } } - + return 0; } diff --git a/client/proxguiqt.h b/client/proxguiqt.h index f01526178..dbd2a9983 100644 --- a/client/proxguiqt.h +++ b/client/proxguiqt.h @@ -115,7 +115,7 @@ class ProxGuiQT : public QObject char **argv; //void (*main_func)(void); WorkerThread *proxmarkThread; - + public: ProxGuiQT(int argc, char **argv, WorkerThread *wthread); ~ProxGuiQT(void); @@ -124,7 +124,7 @@ class ProxGuiQT : public QObject void HideGraphWindow(void); void MainLoop(void); void Exit(void); - + private slots: void _ShowGraphWindow(void); void _RepaintGraphWindow(void); diff --git a/client/proxmark3.c b/client/proxmark3.c index 072fec427..45ed2b47a 100644 --- a/client/proxmark3.c +++ b/client/proxmark3.c @@ -47,7 +47,7 @@ static void showBanner(void){ void #ifdef __has_attribute #if __has_attribute(force_align_arg_pointer) -__attribute__((force_align_arg_pointer)) +__attribute__((force_align_arg_pointer)) #endif #endif main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { @@ -57,39 +57,39 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { bool stdinOnPipe = !isatty(STDIN_FILENO); FILE *sf = NULL; char script_cmd_buf[256] = {0x00}; // iceman, needs lua script the same file_path_buffer as the rest - + PrintAndLogEx(DEBUG, "ISATTY/STDIN_FILENO == %s\n", (stdinOnPipe) ? "true" : "false"); - + if (usb_present) { SetOffline(false); // cache Version information now: if ( execCommand || script_cmds_file || stdinOnPipe) CmdVersion("s"); - else + else CmdVersion(""); } else { SetOffline(true); } if (script_cmds_file) { - - sf = fopen(script_cmds_file, "r"); + + sf = fopen(script_cmds_file, "r"); if (sf) PrintAndLogEx(SUCCESS, "executing commands from file: %s\n", script_cmds_file); } read_history(".history"); - + // loops every time enter is pressed... while (1) { - + // this should hook up the PM3 again. /* if ( IsOffline() ) { - + // sets the global variable, SP and offline) usb_present = hookUpPM3(); - + // usb and the reader_thread is NULL, create a new reader thread. if (usb_present && !IsOffline() ) { rarg.run = 1; @@ -97,7 +97,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { // cache Version information now: if ( execCommand || script_cmds_file || stdinOnPipe) CmdVersion("s"); - else + else CmdVersion(""); } } @@ -105,16 +105,16 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { // If there is a script file if (sf) { - + // clear array memset(script_cmd_buf, 0, sizeof(script_cmd_buf)); - + // read script file if (!fgets(script_cmd_buf, sizeof(script_cmd_buf), sf)) { fclose(sf); sf = NULL; } else { - + // remove linebreaks strcleanrn(script_cmd_buf, sizeof(script_cmd_buf)); @@ -124,7 +124,7 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { } else { // If there is a script command if (execCommand){ - + if ((cmd = strmcopy(script_cmd)) != NULL) PrintAndLogEx(NORMAL, PROXPROMPT"%s", cmd); @@ -136,10 +136,10 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { // if there is a pipe from stdin if (stdinOnPipe) { - + // clear array memset(script_cmd_buf, 0, sizeof(script_cmd_buf)); - // get + // get if (!fgets(script_cmd_buf, sizeof(script_cmd_buf), stdin)) { PrintAndLogEx(ERR, "STDIN unexpected end, exit..."); break; @@ -149,17 +149,17 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { if ((cmd = strmcopy(script_cmd_buf)) != NULL) PrintAndLogEx(NORMAL, PROXPROMPT"%s", cmd); - - } else { + + } else { cmd = readline(PROXPROMPT); fflush(NULL); } } } - + // execute command if (cmd) { - + // rtrim size_t l = strlen(cmd); if ( l > 0 && isspace(cmd[l - 1])) @@ -170,9 +170,9 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { HIST_ENTRY * entry = history_get(history_length); if ((!entry) || (strcmp(entry->line, cmd) != 0)) add_history(cmd); - + // exit or quit - if (ret == 99) + if (ret == 99) break; } free(cmd); @@ -181,17 +181,17 @@ main_loop(char *script_cmds_file, char *script_cmd, bool usb_present) { PrintAndLogEx(NORMAL, "\n"); break; } - } // end while - + } // end while + if (sf) fclose(sf); - + write_history(".history"); if (cmd) { free(cmd); cmd = NULL; - } + } } static void dumpAllHelp(int markdown) { @@ -231,7 +231,7 @@ static void set_my_executable_path(void) { static void show_help(bool showFullHelp, char *command_line){ PrintAndLogEx(NORMAL, "syntax: %s [-h | -help | -m | -f | -flush | -w | -wait | -c | -command | -l | -lua] [cmd_script_file_name] [command][lua_script_name]\n", command_line); PrintAndLogEx(NORMAL, "\texample:'%s "SERIAL_PORT_H"'\n\n", command_line); - + if (showFullHelp){ PrintAndLogEx(NORMAL, "help: <-h|-help> Dump all interactive command's help at once.\n"); PrintAndLogEx(NORMAL, "\t%s -h\n\n", command_line); @@ -252,7 +252,7 @@ static void show_help(bool showFullHelp, char *command_line){ int main(int argc, char* argv[]) { srand(time(0)); - + bool usb_present = false; bool waitCOMPort = false; bool executeCommand = false; @@ -264,35 +264,35 @@ int main(int argc, char* argv[]) { using_history(); #ifdef RL_STATE_READCMD - rl_extend_line_buffer(1024); + rl_extend_line_buffer(1024); #endif - + if (argc < 2) { show_help(true, argv[0]); return 1; } for (int i = 1; i < argc; i++) { - + // helptext if (strcmp(argv[i], "-h") == 0 || strcmp(argv[i], "-help") == 0) { show_help(false, argv[0]); dumpAllHelp(0); return 0; } - + // dump markup if (strcmp(argv[i], "-m") == 0) { dumpAllHelp(1); return 0; - } + } // flush output if (strcmp(argv[i], "-f") == 0 || strcmp(argv[i], "-flush") == 0){ SetFlushAfterWrite(true); PrintAndLogEx(INFO, "Output will be flushed after every print.\n"); } - + // wait for comport if (strcmp(argv[i], "-w") == 0 || strcmp(argv[i], "-wait") == 0){ waitCOMPort = true; @@ -314,10 +314,10 @@ int main(int argc, char* argv[]) { if (argc > 2 && argv[argc - 1] && argv[argc - 1][0] != '-') { if (executeCommand){ script_cmd = argv[argc - 1]; - + while (script_cmd[strlen(script_cmd) - 1] == ' ') script_cmd[strlen(script_cmd) - 1] = 0x00; - + if (strlen(script_cmd) == 0) { script_cmd = NULL; } else { @@ -332,7 +332,7 @@ int main(int argc, char* argv[]) { script_cmd = ctmp; } } - + PrintAndLogEx(SUCCESS, "execute command from commandline: %s\n", script_cmd); } } else { @@ -347,16 +347,16 @@ int main(int argc, char* argv[]) { } #if defined(__linux__) || (__APPLE__) -// ascii art doesn't work well on mingw :( +// ascii art doesn't work well on mingw :( bool stdinOnPipe = !isatty(STDIN_FILENO); if ( !executeCommand && !script_cmds_file && !stdinOnPipe ) - showBanner(); + showBanner(); #endif - + // set global variables set_my_executable_path(); - + // try to open USB connection to Proxmark usb_present = OpenProxmark(argv[1], waitCOMPort, 20, false); @@ -375,15 +375,15 @@ int main(int argc, char* argv[]) { main_loop(script_cmds_file, script_cmd, usb_present); } # endif - + #else main_loop(script_cmds_file, script_cmd, usb_present); -#endif - +#endif + // Clean up the port if (usb_present) { CloseProxmark(); } - + exit(0); } diff --git a/client/proxmark3.h b/client/proxmark3.h index 0a69e71ba..52fe27385 100644 --- a/client/proxmark3.h +++ b/client/proxmark3.h @@ -13,7 +13,7 @@ #define PROXMARK3_H__ #include "usb_cmd.h" -#include "cmdscript.h" // CmdScriptRun +#include "cmdscript.h" // CmdScriptRun #define PROXPROMPT "pm3 --> " diff --git a/client/reveng/cli.c b/client/reveng/cli.c index 6e147ba20..562b2d084 100644 --- a/client/reveng/cli.c +++ b/client/reveng/cli.c @@ -377,7 +377,7 @@ ipqx: /* allocate argument array */ args = argc - optind; - + apolys = calloc(args * sizeof(poly_t), sizeof(char)); if ( !apolys ){ uerror("cannot allocate memory for argument list"); diff --git a/client/reveng/getopt.c b/client/reveng/getopt.c index ebea43f06..7987d8e6b 100644 --- a/client/reveng/getopt.c +++ b/client/reveng/getopt.c @@ -35,7 +35,7 @@ int getopt(int argc, char *argv[], const char *optstring) { //static int pos = 0; char *str; - + if (pos == 0) { if ((optind >= argc) || (*argv[optind] != '-')) return EOF; @@ -43,7 +43,7 @@ int getopt(int argc, char *argv[], const char *optstring) if (argv[optind][pos] == '\0') return EOF; } - + str = strchr(optstring, argv[optind][pos]); if (str == NULL) { optopt = argv[optind][pos]; @@ -52,7 +52,7 @@ int getopt(int argc, char *argv[], const char *optstring) optopt); return '?'; } - + if (str[1] == ':') { if (argv[optind][pos+1] != '\0') { optarg = &argv[optind][pos+1]; diff --git a/client/reveng/preset.c b/client/reveng/preset.c index 82a18b977..dd093a6f3 100644 --- a/client/reveng/preset.c +++ b/client/reveng/preset.c @@ -811,7 +811,7 @@ int mbynam(model_t *dest, const char *key) { if (!aliases->name) return(-1); - + ukey = calloc((size_t) 1 + strlen(key) + 1, sizeof(char)); if (!ukey) { uerror("[!] cannot allocate memory for comparison string"); @@ -863,7 +863,7 @@ char * mnames(void) { ++aptr; } if (!size) return(NULL); - + string = calloc(size, sizeof(char)); if (string) { aptr = aliases; diff --git a/client/reveng/reveng.c b/client/reveng/reveng.c index 550dc2da5..1525bb265 100644 --- a/client/reveng/reveng.c +++ b/client/reveng/reveng.c @@ -173,7 +173,7 @@ modpol(const poly_t init, int rflags, int args, const poly_t *argpolys) { unsigned long alen, blen; if(args < 2) return(NULL); - + result = calloc(((((args - 1) * args) >> 1) + 1) * sizeof(poly_t), sizeof(char)); if(!result) uerror("cannot allocate memory for codeword table"); @@ -482,7 +482,7 @@ chkres(int *resc, model_t **result, const poly_t divisor, const poly_t init, int uerror("cannot reallocate result array"); return; } - + rptr = *result + *resc - 1; rptr->spoly = pclone(divisor); rptr->init = pclone(init); diff --git a/client/scandir.c b/client/scandir.c index 619bd72c6..d7cb0e9d6 100644 --- a/client/scandir.c +++ b/client/scandir.c @@ -28,7 +28,7 @@ int scandir (const char *dir, int count = 0; int allocated = 0; int err_no = 0; - + if (!(dirp = opendir (dir))) return -1; diff --git a/client/scripting.c b/client/scripting.c index 6f6a30f53..5f01f6afe 100644 --- a/client/scripting.c +++ b/client/scripting.c @@ -1,6 +1,6 @@ //----------------------------------------------------------------------------- // Copyright (C) 2013 m h swende -// Modified 2015,2016, iceman +// Modified 2015,2016, iceman // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of @@ -54,9 +54,9 @@ static int l_SendCommand(lua_State *L){ * @return */ static int l_GetFromBigBuf(lua_State *L){ - + int len = 0, startindex = 0; - + //Check number of arguments int n = lua_gettop(L); if (n == 0) { @@ -81,10 +81,10 @@ static int l_GetFromBigBuf(lua_State *L){ if ( !GetFromDevice(BIG_BUF, data, len, startindex, NULL, 2500, false)) { free(data); lua_pushnil(L); - lua_pushstring(L, "command execution time out"); + lua_pushstring(L, "command execution time out"); return 2; } - + //Push it as a string lua_pushlstring(L,(const char *)data, len); free(data); @@ -103,11 +103,11 @@ static int l_GetFromFlashMem(lua_State *L){ #ifndef WITH_FLASH lua_pushnil(L); - lua_pushstring(L, "Not compiled with FLASH MEM support"); + lua_pushstring(L, "Not compiled with FLASH MEM support"); return 2; #else int len = 0, startindex = 0; - + int n = lua_gettop(L); if (n == 0) { lua_pushnil(L); @@ -123,13 +123,13 @@ static int l_GetFromFlashMem(lua_State *L){ if ( !data ) { lua_pushnil(L); lua_pushstring(L, "Allocating memory failed"); - return 2; + return 2; } - + if ( !GetFromDevice(FLASH_MEM, data, len, startindex, NULL, -1, false)) { free(data); lua_pushnil(L); - lua_pushstring(L, "command execution time out"); + lua_pushstring(L, "command execution time out"); return 2; } @@ -160,7 +160,7 @@ static int l_WaitForResponseTimeout(lua_State *L){ lua_pushstring(L, "You need to supply at least command to wait for"); return 2; } - + // extract first param. cmd byte to look for if (n >= 1) { cmd = luaL_checkunsigned(L, 1); @@ -208,7 +208,7 @@ static int l_mfDarkside(lua_State *L){ case 2:{ const char *p_keytype = luaL_checklstring(L, 2, &size); if (size != 2) return returnToLuaWithError(L,"Wrong size of keytype, got %d bytes, expected 1", (int) size); - sscanf(p_keytype, "%x", &keytype); + sscanf(p_keytype, "%x", &keytype); } case 1: { const char *p_blockno = luaL_checklstring(L, 1, &size); @@ -223,7 +223,7 @@ static int l_mfDarkside(lua_State *L){ uint8_t dest_key[8]; num_to_bytes(key, sizeof(dest_key), dest_key); - + //Push the retval on the stack lua_pushinteger(L, retval); lua_pushlstring(L, (const char *) dest_key, sizeof(dest_key)); @@ -282,16 +282,16 @@ static int l_CmdConsole(lua_State *L) { static int l_iso15693_crc(lua_State *L) { uint32_t tmp; unsigned char buf[USB_CMD_DATA_SIZE] = {0x00}; - size_t size = 0; + size_t size = 0; const char *data = luaL_checklstring(L, 1, &size); - + for (int i = 0; i < size; i += 2) { sscanf(&data[i], "%02x", &tmp); buf[i / 2] = tmp & 0xFF; } - - size /= 2; - compute_crc(CRC_15693, buf, size, &buf[size], &buf[size+1]); + + size /= 2; + compute_crc(CRC_15693, buf, size, &buf[size], &buf[size+1]); lua_pushlstring(L, (const char *)&buf, size+2); return 1; } @@ -299,16 +299,16 @@ static int l_iso15693_crc(lua_State *L) { static int l_iso14443b_crc(lua_State *L) { uint32_t tmp; unsigned char buf[USB_CMD_DATA_SIZE] = {0x00}; - size_t size = 0; + size_t size = 0; const char *data = luaL_checklstring(L, 1, &size); - + for (int i = 0; i < size; i += 2) { sscanf(&data[i], "%02x", &tmp); buf[i / 2] = tmp & 0xFF; } - - size /= 2; - compute_crc(CRC_14443_B, buf, size, &buf[size], &buf[size+1]); + + size /= 2; + compute_crc(CRC_14443_B, buf, size, &buf[size], &buf[size+1]); lua_pushlstring(L, (const char *)&buf, size+2); return 1; } @@ -388,12 +388,12 @@ static int l_aes128encrypt_cbc(lua_State *L) { if (size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size); const char *p_txt = luaL_checklstring(L, 2, &size); - + unsigned char indata[16] = {0x00}; unsigned char outdata[16] = {0x00}; unsigned char aes_key[16] = {0x00}; unsigned char iv[16] = {0x00}; - + for (i = 0; i < 32; i += 2) { sscanf(&p_txt[i], "%02x", &tmp); indata[i / 2] = tmp & 0xFF; @@ -419,17 +419,17 @@ static int l_aes128encrypt_ecb(lua_State *L) { if (size != 32) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 32", (int) size); const char *p_txt = luaL_checklstring(L, 2, &size); - + unsigned char indata[16] = {0x00}; unsigned char outdata[16] = {0x00}; unsigned char aes_key[16] = {0x00}; - + for (i = 0; i < 32; i += 2) { sscanf(&p_txt[i], "%02x", &tmp); indata[i / 2] = tmp & 0xFF; sscanf(&p_key[i], "%02x", &tmp); aes_key[i / 2] = tmp & 0xFF; - } + } mbedtls_aes_context ctx; mbedtls_aes_init(&ctx); mbedtls_aes_setkey_enc(&ctx, aes_key, 128); @@ -459,7 +459,7 @@ static int l_crc16(lua_State *L) { static int l_crc64(lua_State *L) { size_t size; - uint64_t crc = 0; + uint64_t crc = 0; unsigned char outdata[8] = {0x00}; const char *p_str = luaL_checklstring(L, 1, &size); @@ -480,7 +480,7 @@ static int l_crc64(lua_State *L) { static int l_crc64_ecma182(lua_State *L) { //size_t size; - uint64_t crc = 0; + uint64_t crc = 0; unsigned char outdata[8] = {0x00}; //const char *p_str = luaL_checklstring(L, 1, &size); @@ -490,7 +490,7 @@ static int l_crc64_ecma182(lua_State *L) { // calc hash //crc64_ecma182((uint8_t*) p_str, size, &crc); - + outdata[0] = (uint8_t)(crc >> 56) & 0xff; outdata[1] = (uint8_t)(crc >> 48) & 0xff; outdata[2] = (uint8_t)(crc >> 40) & 0xff; @@ -505,11 +505,11 @@ static int l_crc64_ecma182(lua_State *L) { static int l_sha1(lua_State *L) { size_t size; - const char *p_str = luaL_checklstring(L, 1, &size); - unsigned char outdata[20] = {0x00}; - mbedtls_sha1( (uint8_t*) p_str, size, outdata); + const char *p_str = luaL_checklstring(L, 1, &size); + unsigned char outdata[20] = {0x00}; + mbedtls_sha1( (uint8_t*) p_str, size, outdata); lua_pushlstring(L, (const char *)&outdata, sizeof(outdata)); - return 1; + return 1; } static int l_reveng_models(lua_State *L){ @@ -526,11 +526,11 @@ static int l_reveng_models(lua_State *L){ char *models[NMODELS]; width[0] = in_width; - + if (!GetModels(models, &count, width)) return returnToLuaWithError(L, "didn't find any models"); - - lua_newtable(L); + + lua_newtable(L); for (int i = 0; i < count; i++){ lua_pushstring(L, (const char*)models[i]); lua_rawseti(L,-2,i+1); @@ -553,19 +553,19 @@ static int l_reveng_RunModel(lua_State *L){ //reverse = reverse calc option if true //endian = {0 = calc default endian input and output, b = big endian input and output, B = big endian output, r = right justified // l = little endian input and output, L = little endian output only, t = left justified} - //result = calculated crc hex string + //result = calculated crc hex string char result[50]; - + const char *inModel = luaL_checkstring(L, 1); const char *inHexStr = luaL_checkstring(L, 2); bool reverse = lua_toboolean(L, 3); const char endian = luaL_checkstring(L, 4)[0]; int ans = RunModel( (char *)inModel, (char *)inHexStr, reverse, endian, result); - if (!ans) + if (!ans) return returnToLuaWithError(L,"Reveng failed"); - lua_pushstring(L, (const char*)result); + lua_pushstring(L, (const char*)result); return 1; } @@ -582,7 +582,7 @@ static int l_hardnested(lua_State *L){ const char *p_key = luaL_checklstring(L, 3, &size); if(size != 12) return returnToLuaWithError(L,"Wrong size of key, got %d bytes, expected 12", (int) size); - + const char *p_trg_blockno = luaL_checklstring(L, 4, &size); if(size != 2) return returnToLuaWithError(L,"Wrong size of trgBlockNo, got %d bytes, expected 2", (int) size); @@ -604,7 +604,7 @@ static int l_hardnested(lua_State *L){ const char *p_tests = luaL_checklstring(L, 10, &size); if(size != 1) return returnToLuaWithError(L,"Wrong size of tests, got %d bytes, expected 1", (int) size); - + char filename[FILE_PATH_SIZE]="nonces.bin"; const char *p_filename = luaL_checklstring(L, 11, &size); if(size != 0) @@ -634,7 +634,7 @@ static int l_hardnested(lua_State *L){ trgkey[i / 2] = tmp & 0xFF; } } - + uint64_t foundkey = 0; int retval = mfnestedhard(blockNo, keyType, key, trgBlockNo, trgKeyType, haveTarget ? trgkey : NULL, nonce_file_read, nonce_file_write, slow, tests, &foundkey, filename); DropField(); @@ -642,7 +642,7 @@ static int l_hardnested(lua_State *L){ //Push the key onto the stack uint8_t dest_key[6]; num_to_bytes(foundkey, sizeof(dest_key), dest_key); - + //Push the retval on the stack lua_pushinteger(L,retval); lua_pushlstring(L, (const char *) dest_key, sizeof(dest_key)); @@ -680,10 +680,10 @@ static int l_keygen_algoD(lua_State *L) { uint32_t pwd = ul_ev1_pwdgenD(uid); uint16_t pack = ul_ev1_packgenD(uid); - + lua_pushunsigned(L, pwd); lua_pushunsigned(L, pack); - return 2; + return 2; } /** @@ -724,7 +724,7 @@ int set_pm3_libraries(lua_State *L) { {"iso14443b_crc", l_iso14443b_crc}, {"aes128_decrypt", l_aes128decrypt_cbc}, {"aes128_decrypt_ecb", l_aes128decrypt_ecb}, - {"aes128_encrypt", l_aes128encrypt_cbc}, + {"aes128_encrypt", l_aes128encrypt_cbc}, {"aes128_encrypt_ecb", l_aes128encrypt_ecb}, {"crc8legic", l_crc8legic}, {"crc16", l_crc16}, @@ -758,7 +758,7 @@ int set_pm3_libraries(lua_State *L) { //-- remove the global environment table from the stack lua_pop(L, 1); - + //--add to the LUA_PATH (package.path in lua) // so we can load scripts from the ./scripts/ - directory char scripts_path[strlen(get_my_executable_directory()) + strlen(LUA_SCRIPTS_DIRECTORY) + strlen(LUA_LIBRARIES_WILDCARD) + 1]; @@ -766,7 +766,7 @@ int set_pm3_libraries(lua_State *L) { strcat(scripts_path, LUA_SCRIPTS_DIRECTORY); strcat(scripts_path, LUA_LIBRARIES_WILDCARD); setLuaPath(L, scripts_path); - + //-- Last but not least, add to the LUA_PATH (package.path in lua) // so we can load libraries from the ./lualib/ - directory char libraries_path[strlen(get_my_executable_directory()) + strlen(LUA_LIBRARIES_DIRECTORY) + strlen(LUA_LIBRARIES_WILDCARD) + 1]; diff --git a/client/ui.c b/client/ui.c index 71603fed6..96049f6cf 100644 --- a/client/ui.c +++ b/client/ui.c @@ -45,18 +45,18 @@ void PrintAndLogOptions(char *str[][2], size_t size, size_t space) { } void PrintAndLogEx(logLevel_t level, char *fmt, ...) { - // skip debug messages if client debugging is turned off i.e. 'DATA SETDEBUG 0' + // skip debug messages if client debugging is turned off i.e. 'DATA SETDEBUG 0' if (g_debugMode == 0 && level == DEBUG) return; - char prefix[20] = {0}; + char prefix[20] = {0}; char buffer[MAX_PRINT_BUFFER] = {0}; char buffer2[MAX_PRINT_BUFFER+20] = {0}; char *token = NULL; int size = 0; // {NORMAL, SUCCESS, INFO, FAILED, WARNING, ERR, DEBUG} static char *prefixes[7] = { "", "[+] ", "[=] ", "[-] ", "[!] ", "[!!] ", "[#] "}; - + switch( level ) { case ERR: strncpy(prefix,_RED_([!!] ), sizeof(prefix)-1); @@ -65,19 +65,19 @@ void PrintAndLogEx(logLevel_t level, char *fmt, ...) { strncpy(prefix,_RED_([-] ), sizeof(prefix)-1); break; case DEBUG: - strncpy(prefix,_BLUE_([#] ), sizeof(prefix)-1); + strncpy(prefix,_BLUE_([#] ), sizeof(prefix)-1); break; - case SUCCESS: + case SUCCESS: strncpy(prefix,_GREEN_([+] ), sizeof(prefix)-1); break; case WARNING: strncpy(prefix,_CYAN_([!] ), sizeof(prefix)-1); - break; + break; default: strncpy(prefix, prefixes[level], sizeof(prefix)-1); break; } - + va_list args; va_start(args, fmt); vsnprintf(buffer, sizeof(buffer), fmt, args); @@ -88,26 +88,26 @@ void PrintAndLogEx(logLevel_t level, char *fmt, ...) { PrintAndLog("%s", buffer); return; } - + if (strchr(buffer, '\n')) { const char delim[2] = "\n"; - + // line starts with newline - if (buffer[0] == '\n') + if (buffer[0] == '\n') PrintAndLog(""); - + token = strtok(buffer, delim); - + while (token != NULL) { - + size = strlen(buffer2); - + if (strlen(token)) snprintf(buffer2+size, sizeof(buffer2)-size, "%s%s\n", prefix, token); else snprintf(buffer2+size, sizeof(buffer2)-size, "\n"); - + token = strtok(NULL, delim); } PrintAndLog("%s", buffer2); @@ -123,10 +123,10 @@ void PrintAndLog(char *fmt, ...) { va_list argptr, argptr2; static FILE *logfile = NULL; static int logging = 1; - + // lock this section to avoid interlacing prints from different threads pthread_mutex_lock(&print_lock); - + if (logging && !logfile) { logfile = fopen(logfilename, "a"); if (!logfile) { @@ -135,10 +135,10 @@ void PrintAndLog(char *fmt, ...) { } } - + // If there is an incoming message from the hardware (eg: lf hid read) in // the background (while the prompt is displayed and accepting user input), -// stash the prompt and bring it back later. +// stash the prompt and bring it back later. #ifdef RL_STATE_READCMD // We are using GNU readline. libedit (OSX) doesn't support this flag. int need_hack = (rl_readline_state & RL_STATE_READCMD) > 0; @@ -151,7 +151,7 @@ void PrintAndLog(char *fmt, ...) { rl_redisplay(); } #endif - + va_start(argptr, fmt); va_copy(argptr2, argptr); vprintf(fmt, argptr); @@ -169,7 +169,7 @@ void PrintAndLog(char *fmt, ...) { free(saved_line); } #endif - + if (logging && logfile) { vfprintf(logfile, fmt, argptr2); fprintf(logfile, "\n"); @@ -181,13 +181,13 @@ void PrintAndLog(char *fmt, ...) { fflush(stdout); //release lock - pthread_mutex_unlock(&print_lock); + pthread_mutex_unlock(&print_lock); } void SetLogFilename(char *fn) { logfilename = fn; } - + void SetFlushAfterWrite(bool value) { flushAfterWrite = value; } @@ -195,29 +195,29 @@ void SetFlushAfterWrite(bool value) { void iceIIR_Butterworth(int *data, const size_t len){ int i,j; - - int * output = (int* ) calloc(sizeof(int) * len, sizeof(uint8_t)); + + int * output = (int* ) calloc(sizeof(int) * len, sizeof(uint8_t)); if ( !output ) return; - + // clear mem memset(output, 0x00, len); - + size_t adjustedLen = len; float fc = 0.1125f; // center frequency - + // create very simple low-pass filter to remove images (2nd-order Butterworth) float complex iir_buf[3] = {0,0,0}; float b[3] = {0.003621681514929, 0.007243363029857, 0.003621681514929}; float a[3] = {1.000000000000000, -1.822694925196308, 0.837181651256023}; - + float sample = 0; // input sample read from array float complex x_prime = 1.0f; // save sample for estimating frequency float complex x; - + for (i = 0; i < adjustedLen; ++i) { sample = data[i]; - + // remove DC offset and mix to complex baseband x = (sample - 127.5f) * cexpf( _Complex_I * 2 * M_PI * fc * i ); @@ -228,27 +228,27 @@ void SetFlushAfterWrite(bool value) { x = b[0]*iir_buf[0] + b[1]*iir_buf[1] + b[2]*iir_buf[2]; - + // compute instantaneous frequency by looking at phase difference // between adjacent samples float freq = cargf(x * conjf(x_prime)); x_prime = x; // retain this sample for next iteration output[i] =(freq > 0) ? 127 : -127; - } + } // show data //memcpy(data, output, adjustedLen); for (j=0; j #include #include -#include +#include #include #include "util.h" diff --git a/client/util.c b/client/util.c index cea42f338..99c44ff13 100644 --- a/client/util.c +++ b/client/util.c @@ -21,7 +21,7 @@ uint8_t g_debugMode = 0; #ifndef _WIN32 #include -#include +#include #include #include @@ -64,10 +64,10 @@ void AddLogLine(char *fn, char *data, char *c) { int len = 0; len = strlen(fn); - if (len > FILE_PATH_SIZE) + if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; memcpy(filename, fn, len); - + f = fopen(filename, "a"); if (!f) { printf("Could not append log file %s", filename); @@ -111,14 +111,14 @@ void FillFileNameByUID(char *filenamePrefix, uint8_t *uid, const char *ext, int printf("[!] error parameter is NULL\n"); return; } - + int len = 0; len = strlen(filenamePrefix); //memset(fn, 0x00, FILE_PATH_SIZE); - + for (int j = 0; j < uidlen; j++) - sprintf(filenamePrefix + len + j * 2, "%02X", uid[j]); - strcat(filenamePrefix, ext); + sprintf(filenamePrefix + len + j * 2, "%02X", uid[j]); + strcat(filenamePrefix, ext); } // fill buffer from structure [{uint8_t data, size_t length},...] @@ -126,25 +126,25 @@ int FillBuffer(uint8_t *data, size_t maxDataLength, size_t *dataLength, ...) { *dataLength = 0; va_list valist; va_start(valist, dataLength); - + uint8_t *vdata = NULL; size_t vlength = 0; do{ vdata = va_arg(valist, uint8_t *); if (!vdata) break; - + vlength = va_arg(valist, size_t); if (*dataLength + vlength > maxDataLength) { va_end(valist); return 1; } - + memcpy(&data[*dataLength], vdata, vlength); *dataLength += vlength; - + } while (vdata); - + va_end(valist); return 0; @@ -157,13 +157,13 @@ bool CheckStringIsHEXValue(const char *value) { if (strlen(value) % 2) return false; - + return true; } -void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, const size_t hex_max_len, +void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, const size_t hex_max_len, const size_t min_str_len, const size_t spaces_between, bool uppercase) { - + char *tmp = (char *)buf; size_t i; memset(tmp, 0x00, hex_max_len); @@ -171,17 +171,17 @@ void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex int maxLen = ( hex_len > hex_max_len) ? hex_max_len : hex_len; for (i = 0; i < maxLen; ++i, tmp += 2 + spaces_between) { - sprintf(tmp, (uppercase) ? "%02X" : "%02x", (unsigned int) hex_data[i]); - + sprintf(tmp, (uppercase) ? "%02X" : "%02x", (unsigned int) hex_data[i]); + for (int j = 0; j < spaces_between; j++) sprintf(tmp + 2 + j, " "); } - + i *= (2 + spaces_between); int minStrLen = min_str_len > i ? min_str_len : 0; if (minStrLen > hex_max_len) minStrLen = hex_max_len; - for(; i < minStrLen; i++, tmp += 1) + for(; i < minStrLen; i++, tmp += 1) sprintf(tmp, " "); return; @@ -201,7 +201,7 @@ void print_hex_break(const uint8_t *data, const size_t len, uint8_t breaks) { for (int i = 0; i < len; ++i) { printf("%02X ", data[i]); - + // check if a line break is needed if ( breaks > 0 && !((i+1) % breaks) && (i+1 < len) ) { ++rownum; @@ -233,17 +233,17 @@ char *sprint_hex_inrow_spaces(const uint8_t *data, const size_t len, size_t spac } char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t breaks) { - + // make sure we don't go beyond our char array memory size_t in_index = 0, out_index = 0; - + int rowlen = (len > MAX_BIN_BREAK_LENGTH ) ? MAX_BIN_BREAK_LENGTH : len; - - if ( breaks > 0 && len % breaks != 0) + + if ( breaks > 0 && len % breaks != 0) rowlen = ( len+(len/breaks) > MAX_BIN_BREAK_LENGTH ) ? MAX_BIN_BREAK_LENGTH : len+(len/breaks); - + //printf("(sprint_bin_break) rowlen %d\n", rowlen); - + static char buf[MAX_BIN_BREAK_LENGTH]; // 3072 + end of line characters if broken at 8 bits //clear memory memset(buf, 0x00, sizeof(buf)); @@ -268,21 +268,21 @@ char *sprint_bin_break(const uint8_t *data, const size_t len, const uint8_t brea void sprint_bin_break_ex(uint8_t *src, size_t srclen, char *dest , uint8_t breaks) { if ( src == NULL ) return; if ( srclen < 1 ) return; - + // make sure we don't go beyond our char array memory size_t in_index = 0, out_index = 0; - int rowlen; + int rowlen; if (breaks==0) rowlen = ( len > MAX_BIN_BREAK_LENGTH ) ? MAX_BIN_BREAK_LENGTH : len; else rowlen = ( len+(len/breaks) > MAX_BIN_BREAK_LENGTH ) ? MAX_BIN_BREAK_LENGTH : len+(len/breaks); printf("(sprint_bin_break) rowlen %d\n", rowlen); - + // 3072 + end of line characters if broken at 8 bits - dest = (char *)calloc(MAX_BIN_BREAK_LENGTH, sizeof(uint8_t)); + dest = (char *)calloc(MAX_BIN_BREAK_LENGTH, sizeof(uint8_t)); if (dest == NULL) return; - + //clear memory memset(dest, 0x00, sizeof(dest)); @@ -314,7 +314,7 @@ char *sprint_hex_ascii(const uint8_t *data, const size_t len) { size_t max_len = (len > 1010) ? 1010 : len; snprintf(tmp, UTIL_BUFFER_SIZE_SPRINT, "%s| ", sprint_hex(data, max_len) ); - + size_t i = 0; size_t pos = (max_len * 3) + 2; while (i < max_len){ @@ -338,11 +338,11 @@ char *sprint_ascii_ex(const uint8_t *data, const size_t len, const size_t min_st tmp[i] = ((c < 32) || (c == 127)) ? '.' : c; ++i; } - + int m = min_str_len > i ? min_str_len : 0; - for(; i < m; ++i) + for(; i < m; ++i) tmp[i] = ' '; - + return buf; } char *sprint_ascii(const uint8_t *data, const size_t len) { @@ -409,7 +409,7 @@ uint8_t *SwapEndian64(const uint8_t *src, const size_t len, const uint8_t blockS return buf; } -// takes a uint8_t src array, for len items and reverses the byte order in blocksizes (8,16,32,64), +// takes a uint8_t src array, for len items and reverses the byte order in blocksizes (8,16,32,64), // returns: the dest array contains the reordered src array. void SwapEndian64ex(const uint8_t *src, const size_t len, const uint8_t blockSize, uint8_t *dest){ for (uint8_t block=0; block < (uint8_t)(len/blockSize); block++){ @@ -432,10 +432,10 @@ int param_getptr(const char *line, int *bg, int *en, int paramnum) { int i; int len = strlen(line); - + *bg = 0; *en = 0; - + // skip spaces while (line[*bg] ==' ' || line[*bg]=='\t') (*bg)++; if (*bg >= len) { @@ -445,13 +445,13 @@ int param_getptr(const char *line, int *bg, int *en, int paramnum) for (i = 0; i < paramnum; i++) { while (line[*bg]!=' ' && line[*bg]!='\t' && line[*bg] != '\0') (*bg)++; while (line[*bg]==' ' || line[*bg]=='\t') (*bg)++; - + if (line[*bg] == '\0') return 1; } - + *en = *bg; while (line[*en] != ' ' && line[*en] != '\t' && line[*en] != '\0') (*en)++; - + (*en)--; return 0; @@ -460,7 +460,7 @@ int param_getptr(const char *line, int *bg, int *en, int paramnum) int param_getlength(const char *line, int paramnum) { int bg, en; - + if (param_getptr(line, &bg, &en, paramnum)) return 0; return en - bg + 1; @@ -472,12 +472,12 @@ char param_getchar(const char *line, int paramnum) { char param_getchar_indx(const char *line, int indx, int paramnum) { int bg, en; - + if (param_getptr(line, &bg, &en, paramnum)) return 0x00; if (bg + indx > en) return '\0'; - + return line[bg + indx]; } @@ -518,7 +518,7 @@ uint8_t param_isdec(const char *line, int paramnum) uint8_t param_get8ex(const char *line, int paramnum, int deflt, int base) { int bg, en; - if (!param_getptr(line, &bg, &en, paramnum)) + if (!param_getptr(line, &bg, &en, paramnum)) return strtoul(&line[bg], NULL, base) & 0xff; else return deflt; @@ -527,7 +527,7 @@ 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) { int bg, en; - if (!param_getptr(line, &bg, &en, paramnum)) + if (!param_getptr(line, &bg, &en, paramnum)) return strtoul(&line[bg], NULL, base); else return deflt; @@ -536,7 +536,7 @@ uint32_t param_get32ex(const char *line, int paramnum, int deflt, int base) uint64_t param_get64ex(const char *line, int paramnum, int deflt, int base) { int bg, en; - if (!param_getptr(line, &bg, &en, paramnum)) + if (!param_getptr(line, &bg, &en, paramnum)) return strtoull(&line[bg], NULL, base); else return deflt; @@ -547,17 +547,17 @@ int param_gethex(const char *line, int paramnum, uint8_t * data, int hexcnt) { uint32_t temp; if (hexcnt & 1) return 1; - + if (param_getptr(line, &bg, &en, paramnum)) return 1; if (en - bg + 1 != hexcnt) return 1; for(i = 0; i < hexcnt; i += 2) { if (!(isxdigit(line[bg + i]) && isxdigit(line[bg + i + 1])) ) return 1; - + sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp); data[i / 2] = temp & 0xff; - } + } return 0; } @@ -573,10 +573,10 @@ int param_gethex_ex(const char *line, int paramnum, uint8_t * data, int *hexcnt) for(i = 0; i < *hexcnt; i += 2) { if (!(isxdigit(line[bg + i]) && isxdigit(line[bg + i + 1])) ) return 1; - + sscanf((char[]){line[bg + i], line[bg + i + 1], 0}, "%X", &temp); data[i / 2] = temp & 0xff; - } + } return 0; } @@ -589,21 +589,21 @@ int param_gethex_to_eol(const char *line, int paramnum, uint8_t * data, int maxd if (param_getptr(line, &bg, &en, paramnum)) return 1; *datalen = 0; - + int indx = bg; while (line[indx]) { if (line[indx] == '\t' || line[indx] == ' ') { indx++; continue; } - + if (isxdigit(line[indx])) { buf[strlen(buf) + 1] = 0x00; buf[strlen(buf)] = line[indx]; } else { // if we have symbols other than spaces and hex return 1; - } + } if (*datalen >= maxdatalen) { // if we dont have space in buffer and have symbols to translate @@ -616,14 +616,14 @@ int param_gethex_to_eol(const char *line, int paramnum, uint8_t * data, int maxd *buf = 0; (*datalen)++; } - + indx++; } - if (strlen(buf) > 0) + if (strlen(buf) > 0) //error when not completed hex bytes return 3; - + return 0; } @@ -631,7 +631,7 @@ int param_getstr(const char *line, int paramnum, char * str, size_t buffersize) { int bg, en; - if (param_getptr(line, &bg, &en, paramnum)) { + if (param_getptr(line, &bg, &en, paramnum)) { return 0; } @@ -640,10 +640,10 @@ int param_getstr(const char *line, int paramnum, char * str, size_t buffersize) printf("out of bounds error: want %d bytes have %zu bytes\n", en - bg + 1 + 1, buffersize); return 0; } - + memcpy(str, line + bg, en - bg + 1); str[en - bg + 1] = 0; - + return en - bg + 1; } @@ -680,7 +680,7 @@ int hextobinarray(char *target, char *source) for(i= 0 ; i < 4 ; ++i, ++count) *(target++)= (x >> (3 - i)) & 1; } - + return count; } @@ -755,11 +755,11 @@ void xor(unsigned char * dst, unsigned char * src, size_t len) { int32_t le24toh (uint8_t data[3]) { return (data[2] << 16) | (data[1] << 8) | data[0]; } -// Pack a bitarray into a uint32_t. +// Pack a bitarray into a uint32_t. uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bits) { if (len > 32) return 0; - + int i = start; int j = len-1; uint32_t tmp = 0; @@ -772,7 +772,7 @@ uint32_t PackBits(uint8_t start, uint8_t len, uint8_t* bits) { // RotateLeft - Ultralight, Desfire, works on byte level // 00-01-02 >> 01-02-00 -void rol(uint8_t *data, const size_t len){ +void rol(uint8_t *data, const size_t len){ uint8_t first = data[0]; for (size_t i = 0; i < len-1; i++) { data[i] = data[i+1]; @@ -793,7 +793,7 @@ uint8_t reflect8(uint8_t b) { } uint16_t reflect16(uint16_t b) { uint16_t v = 0; - v |= (b & 0x8000) >> 15; + v |= (b & 0x8000) >> 15; v |= (b & 0x4000) >> 13; v |= (b & 0x2000) >> 11; v |= (b & 0x1000) >> 9; @@ -814,7 +814,7 @@ uint16_t reflect16(uint16_t b) { } /* ref http://www.csm.ornl.gov/~dunigan/crc.html - Returns the value v with the bottom b [0,32] bits reflected. + Returns the value v with the bottom b [0,32] bits reflected. Example: reflect(0x3e23L,3) == 0x3e26 */ uint32_t reflect(uint32_t v, int b) { @@ -857,7 +857,7 @@ extern void str_lower(char *s ){ for(int i=0; i < strlen(s); i++) s[i] = tolower( s[i] ); } -extern bool str_startswith(const char *s, const char *pre) { +extern bool str_startswith(const char *s, const char *pre) { return strncmp(pre, s, strlen(pre)) == 0; } @@ -888,6 +888,6 @@ extern char *strmcopy(char *buf) { if (str != NULL) { memset(str, 0, strlen(buf) + 1); strcpy(str, buf); - } + } return str; } \ No newline at end of file diff --git a/client/util.h b/client/util.h index e10f06497..ec99a4903 100644 --- a/client/util.h +++ b/client/util.h @@ -199,7 +199,7 @@ extern void FillFileNameByUID(char *filenamePrefix, uint8_t * uid, const char *e extern int FillBuffer(uint8_t *data, size_t maxDataLength, size_t *dataLength, ...); extern bool CheckStringIsHEXValue(const char *value); -extern void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, +extern void hex_to_buffer(const uint8_t *buf, const uint8_t *hex_data, const size_t hex_len, const size_t hex_max_len, const size_t min_str_len, const size_t spaces_between, bool uppercase); @@ -263,4 +263,4 @@ extern bool str_startswith(const char *s, const char *pre); // check for prefi extern void strcleanrn(char *buf, size_t len); extern void strcreplace(char *buf, size_t len, char from, char to); extern char *strmcopy(char *buf); -#endif \ No newline at end of file +#endif \ No newline at end of file diff --git a/client/util_posix.c b/client/util_posix.c index a45dc48e9..5ecc50d13 100644 --- a/client/util_posix.c +++ b/client/util_posix.c @@ -40,7 +40,7 @@ void msleep(uint32_t n) { #ifndef CLOCK_MONOTONIC #define CLOCK_MONOTONIC (1) #endif -#ifndef CLOCK_REALTIME +#ifndef CLOCK_REALTIME #define CLOCK_REALTIME (2) #endif @@ -72,7 +72,7 @@ void msleep(uint32_t n) { uint64_t now = mach_absolute_time(); if (clock_start_time == 0) { - + mach_timebase_info(&timebase_info); clock_start_time = now; } diff --git a/client/whereami.c b/client/whereami.c index acf3ff2e8..127e49504 100644 --- a/client/whereami.c +++ b/client/whereami.c @@ -140,7 +140,7 @@ int WAI_PREFIX(getExecutablePath)(char* out, int capacity, int* dirname_length) return WAI_PREFIX(getModulePath_)(NULL, out, capacity, dirname_length); } -// GetModuleHandleEx() is not available on old mingw environments. We don't need getModulePath() yet. +// GetModuleHandleEx() is not available on old mingw environments. We don't need getModulePath() yet. // Sacrifice it for the time being to improve backwards compatibility /* WAI_NOINLINE WAI_FUNCSPEC diff --git a/common/cmd.c b/common/cmd.c index bed968c2c..ebeaf4f7c 100644 --- a/common/cmd.c +++ b/common/cmd.c @@ -40,7 +40,7 @@ uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void // Compose the outgoing command frame txcmd.cmd = cmd; txcmd.arg[0] = arg0; - txcmd.arg[1] = arg1; + txcmd.arg[1] = arg1; txcmd.arg[2] = arg2; // Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE @@ -50,7 +50,7 @@ uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void txcmd.d.asBytes[i] = ((uint8_t*)data)[i]; } } - + uint32_t sendlen = 0; // Send frame and make sure all bytes are transmitted sendlen = usb_write( (uint8_t*)&txcmd, sizeof(UsbCommand) ); @@ -59,6 +59,6 @@ uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void // usart_init(); // usart_writebuffer( (uint8_t*)&txcmd, sizeof(UsbCommand) ); #endif - + return sendlen; } \ No newline at end of file diff --git a/common/crapto1/crapto1.h b/common/crapto1/crapto1.h index c941879ce..5abdaeb09 100644 --- a/common/crapto1/crapto1.h +++ b/common/crapto1/crapto1.h @@ -61,7 +61,7 @@ extern bool validate_prng_nonce(uint32_t nonce); break;\ else if(__i)\ __M = prng_successor(__M, (__i == 7) ? 48 : 8);\ - else + else #define LF_POLY_ODD (0x29CE5C) #define LF_POLY_EVEN (0x870804) diff --git a/common/crc.c b/common/crc.c index 77bea0b47..4097fdd48 100644 --- a/common/crc.c +++ b/common/crc.c @@ -5,7 +5,7 @@ //----------------------------------------------------------------------------- // Generic CRC calculation code. //----------------------------------------------------------------------------- -// the Check value below in the comments is CRC of the string '123456789' +// the Check value below in the comments is CRC of the string '123456789' // #include "crc.h" @@ -29,21 +29,21 @@ void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, u } void crc_clear(crc_t *crc) { - + crc->state = crc->initial_value & crc->mask; - if (crc->refin) + if (crc->refin) crc->state = reflect(crc->state, crc->order); } void crc_update2(crc_t *crc, uint32_t data, int data_width){ - - if (crc->refin) + + if (crc->refin) data = reflect(data, data_width); - + // Bring the next byte into the remainder. crc->state ^= data << (crc->order - data_width); - - for( uint8_t bit = data_width; bit > 0; --bit) { + + for( uint8_t bit = data_width; bit > 0; --bit) { if (crc->state & crc->topbit) crc->state = (crc->state << 1) ^ crc->polynom; @@ -54,9 +54,9 @@ void crc_update2(crc_t *crc, uint32_t data, int data_width){ void crc_update(crc_t *crc, uint32_t data, int data_width) { - if (crc->refin) + if (crc->refin) data = reflect(data, data_width); - + int i; for(i=0; istate; @@ -70,7 +70,7 @@ void crc_update(crc_t *crc, uint32_t data, int data_width) uint32_t crc_finish(crc_t *crc) { uint32_t val = crc->state; - if (crc->refout) + if (crc->refout) val = reflect(val, crc->order); return ( val ^ crc->final_xor ) & crc->mask; } @@ -94,7 +94,7 @@ static void print_crc(crc_t *crc) { // width=8 poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xA1 name="CRC-8/MAXIM" uint32_t CRC8Maxim(uint8_t *buff, size_t size) { crc_t crc; - crc_init_ref(&crc, 8, 0x31, 0, 0, true, true); + crc_init_ref(&crc, 8, 0x31, 0, 0, true, true); for ( int i=0; i < size; ++i) crc_update2(&crc, buff[i], 8); return crc_finish(&crc); @@ -114,7 +114,7 @@ uint32_t CRC4Legic(uint8_t *cmd, size_t size) { crc_update2(&crc, 1, 1); /* CMD_READ */ crc_update2(&crc, cmd[0], 8); crc_update2(&crc, cmd[1], 8); - return reflect(crc_finish(&crc), 4); + return reflect(crc_finish(&crc), 4); } // width=8 poly=0x63, reversed poly=0x8D init=0x55 refin=true refout=true xorout=0x0000 check=0xC6 name="CRC-8/LEGIC" // the CRC needs to be reversed before returned. diff --git a/common/crc.h b/common/crc.h index 40bdc7daf..015fbf60c 100644 --- a/common/crc.h +++ b/common/crc.h @@ -26,12 +26,12 @@ typedef struct crc { /* Initialize a crc structure. order is the order of the polynom, e.g. 32 for a CRC-32 * polynom is the CRC polynom. initial_value is the initial value of a clean state. - * final_xor is XORed onto the state before returning it from crc_result(). + * final_xor is XORed onto the state before returning it from crc_result(). * refin is the setting for reversing (bitwise) the bytes during crc * refot is the setting for reversing (bitwise) the crc byte before returning it. */ extern void crc_init_ref(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor, bool refin, bool refout); - + /* Initialize a crc structure. order is the order of the polynom, e.g. 32 for a CRC-32 * polynom is the CRC polynom. initial_value is the initial value of a clean state. * final_xor is XORed onto the state before returning it from crc_result(). */ diff --git a/common/crc16.c b/common/crc16.c index 8110d8045..b6145013b 100644 --- a/common/crc16.c +++ b/common/crc16.c @@ -12,17 +12,17 @@ static bool crc_table_init = false; static CrcType_t crc_type = CRC_NONE; void init_table(CrcType_t ct) { - + // same crc algo, and initialised already - if ( ct == crc_type && crc_table_init) + if ( ct == crc_type && crc_table_init) return; - + // not the same crc algo. reset table. if ( ct != crc_type) reset_table(); - + crc_type = ct; - + switch (ct) { case CRC_14443_A: case CRC_14443_B: @@ -59,9 +59,9 @@ void generate_table( uint16_t polynomial, bool refin) { c = c << 1; } - if (refin) + if (refin) crc = reflect16(crc); - + crc_table[i] = crc; } crc_table_init = true; @@ -80,20 +80,20 @@ uint16_t crc16_fast(uint8_t const *d, size_t n, uint16_t initval, bool refin, bo // only usable with polynom orders of 8, 16, 24 or 32. if (n == 0) return (~initval); - + uint16_t crc = initval; - if (refin) + if (refin) crc = reflect16(crc); - if (!refin) + if (!refin) while (n--) crc = (crc << 8) ^ crc_table[ ((crc >> 8) ^ *d++) & 0xFF ]; - else + else while (n--) crc = (crc >> 8) ^ crc_table[ (crc & 0xFF) ^ *d++]; - if (refout^refin) + if (refout^refin) crc = reflect16(crc); - + return crc; } @@ -102,14 +102,14 @@ uint16_t update_crc16_ex( uint16_t crc, uint8_t c, uint16_t polynomial ) { uint16_t i, v, tmp = 0; v = (crc ^ c) & 0xff; - + for (i = 0; i < 8; i++) { - + if ( (tmp ^ v) & 1 ) tmp = ( tmp >> 1 ) ^ polynomial; else tmp >>= 1; - + v >>= 1; } return ((crc >> 8) ^ tmp) & 0xffff; @@ -130,19 +130,19 @@ uint16_t crc16(uint8_t const *d, size_t length, uint16_t remainder, uint16_t pol // xor in at msb remainder ^= (c << 8); - - // 8 iteration loop + + // 8 iteration loop for (uint8_t j = 8; j; --j) { if (remainder & 0x8000) { remainder = (remainder << 1) ^ polynomial; } else { remainder <<= 1; } - } + } } - if (refout) + if (refout) remainder = reflect16(remainder); - + return remainder; } @@ -150,9 +150,9 @@ void compute_crc(CrcType_t ct, const uint8_t *d, size_t n, uint8_t *first, uint8 // can't calc a crc on less than 1 byte if ( n == 0 ) return; - + init_table(ct); - + uint16_t crc = 0; switch (ct) { case CRC_14443_A: crc = crc16_a(d, n); break; @@ -172,7 +172,7 @@ uint16_t crc(CrcType_t ct, const uint8_t *d, size_t n) { // can't calc a crc on less than 3 byte. (1byte + 2 crc bytes) if ( n < 3 ) return 0; - + init_table(ct); switch (ct) { case CRC_14443_A: return crc16_a(d, n); @@ -192,7 +192,7 @@ uint16_t crc(CrcType_t ct, const uint8_t *d, size_t n) { // ct crc type // d buffer with data // n length (including crc) -// +// // This function uses the message + crc bytes in order to compare the "residue" afterwards. // crc16 algos like CRC-A become 0x000 // while CRC-15693 become 0x0F47 @@ -201,14 +201,14 @@ bool check_crc(CrcType_t ct, const uint8_t *d, size_t n) { // can't calc a crc on less than 3 byte. (1byte + 2 crc bytes) if ( n < 3 ) return false; - + init_table(ct); - + switch (ct) { case CRC_14443_A: return (crc16_a(d, n) == 0); case CRC_14443_B: return (crc16_x25(d, n) == X25_CRC_CHECK); case CRC_15693: return (crc16_x25(d, n) == X25_CRC_CHECK); - case CRC_ICLASS: return (crc16_iclass(d, n) == 0); + case CRC_ICLASS: return (crc16_iclass(d, n) == 0); case CRC_FELICA: return (crc16_xmodem(d, n) == 0); //case CRC_LEGIC: case CRC_CCITT: return (crc16_ccitt(d, n) == 0); @@ -222,7 +222,7 @@ uint16_t crc16_ccitt(uint8_t const *d, size_t n) { return crc16_fast(d, n, 0xffff, false, false); } -// FDX-B ISO11784/85) uses KERMIT +// FDX-B ISO11784/85) uses KERMIT // poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 name="KERMIT" uint16_t crc16_kermit(uint8_t const *d, size_t n) { return crc16_fast(d, n, 0x0000, true, true); @@ -231,7 +231,7 @@ uint16_t crc16_kermit(uint8_t const *d, size_t n) { // FeliCa uses XMODEM // poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 name="XMODEM" uint16_t crc16_xmodem(uint8_t const *d, size_t n) { - return crc16_fast(d, n, 0x0000, false, false); + return crc16_fast(d, n, 0x0000, false, false); } // Following standards uses X-25 @@ -239,14 +239,14 @@ uint16_t crc16_xmodem(uint8_t const *d, size_t n) { // ISO 14443 CRC-B // ISO/IEC 13239 (formerly ISO/IEC 3309) // poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff name="X-25" -uint16_t crc16_x25(uint8_t const *d, size_t n) { +uint16_t crc16_x25(uint8_t const *d, size_t n) { uint16_t crc = crc16_fast(d, n, 0xffff, true, true); crc = ~crc; return crc; } // CRC-A (14443-3) // poly=0x1021 init=0xc6c6 refin=true refout=true xorout=0x0000 name="CRC-A" -uint16_t crc16_a(uint8_t const *d, size_t n) { +uint16_t crc16_a(uint8_t const *d, size_t n) { return crc16_fast(d, n, 0xC6C6, true, true); } @@ -258,7 +258,7 @@ uint16_t crc16_iclass(uint8_t const *d, size_t n) { return crc16_fast(d, n, 0x4807, true, true); } -// This CRC-16 is used in Legic Advant systems. +// This CRC-16 is used in Legic Advant systems. // poly=0xB400, init=depends refin=true refout=true xorout=0x0000 check= name="CRC-16/LEGIC" uint16_t crc16_legic(uint8_t const *d, size_t n, uint8_t uidcrc) { uint16_t initial = uidcrc << 8 | uidcrc; diff --git a/common/crc16.h b/common/crc16.h index e4c3abac2..c11cf6351 100644 --- a/common/crc16.h +++ b/common/crc16.h @@ -47,7 +47,7 @@ uint16_t crc16_kermit(uint8_t const *d, size_t n); // Calculate CRC-16/XMODEM (FeliCa) uint16_t crc16_xmodem(uint8_t const *d, size_t n); -// Calculate CRC-16/X25 (ISO15693, ISO14443 CRC-B,ISO/IEC 13239) +// Calculate CRC-16/X25 (ISO15693, ISO14443 CRC-B,ISO/IEC 13239) uint16_t crc16_x25(uint8_t const *d, size_t n); // Calculate CRC-16/CRC-A (ISO14443 CRC-A) diff --git a/common/default_version.c b/common/default_version.c index b564681c7..b143afd4c 100644 --- a/common/default_version.c +++ b/common/default_version.c @@ -1,9 +1,9 @@ #include "proxmark3.h" /* This is the default version.c file that Makefile.common falls back to if perl is not available */ -const struct version_information __attribute__((section(".version_information"))) version_information = { - VERSION_INFORMATION_MAGIC, +const struct version_information __attribute__((section(".version_information"))) version_information = { + VERSION_INFORMATION_MAGIC, 1, /* version 1 */ 0, /* version information not present */ 2, /* cleanliness couldn't be determined */ /* Remaining fields: zero */ -}; +}; diff --git a/common/desfire.h b/common/desfire.h index a2b0599e9..81ca57b92 100644 --- a/common/desfire.h +++ b/common/desfire.h @@ -91,7 +91,7 @@ struct desfire_tag { desfirekey_t session_key; enum DESFIRE_AUTH_SCHEME authentication_scheme; uint8_t authenticated_key_no; - + uint8_t ivect[MAX_CRYPTO_BLOCK_SIZE]; uint8_t cmac[16]; uint8_t *crypto_buffer; diff --git a/common/emvtags.h b/common/emvtags.h index beecd5716..72cd34ccb 100644 --- a/common/emvtags.h +++ b/common/emvtags.h @@ -1,13 +1,13 @@ //----------------------------------------------------------------------------- // Peter Fillmore 2014 // code derived off merloks mifare code -// +// // // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. //----------------------------------------------------------------------------- -// structure to hold EMV card and terminal parameters +// structure to hold EMV card and terminal parameters //----------------------------------------------------------------------------- #ifndef __EMVCARD_H #define __EMVCARD_H @@ -16,133 +16,133 @@ #include //structure to hold received/set tag values -//variable data inputs have length specifiers +//variable data inputs have length specifiers typedef struct { //ISO14443-A card stuff - uint8_t ATQA[2]; //Answer to Request - uint8_t UID_len; - uint8_t UID[10]; + uint8_t ATQA[2]; //Answer to Request + uint8_t UID_len; + uint8_t UID[10]; uint8_t SAK1; //SAK for UID 1 uint8_t SAK2; //SAK for UID 2 - uint8_t ATS_len; //Answer to select - uint8_t ATS[256]; - //ATS + uint8_t ATS_len; //Answer to select + uint8_t ATS[256]; + //ATS uint8_t TL; uint8_t T0; uint8_t TA1; uint8_t TB1; uint8_t TC1; uint8_t* historicalbytes; - //PPS response + //PPS response uint8_t PPSS; - //SFI 2 record 1 - uint8_t tag_4F_len; //length of AID - uint8_t tag_4F[16]; //Application Identifier (AID) - uint8_t tag_50_len; //length of application label + //SFI 2 record 1 + uint8_t tag_4F_len; //length of AID + uint8_t tag_4F[16]; //Application Identifier (AID) + uint8_t tag_50_len; //length of application label uint8_t tag_50[16]; //Application Label - uint8_t tag_56_len; //track1 length + uint8_t tag_56_len; //track1 length uint8_t tag_56[76]; //Track 1 Data - uint8_t tag_57_len; //track2 equiv len + uint8_t tag_57_len; //track2 equiv len uint8_t tag_57[19]; //Track 2 Equivalent Data - uint8_t tag_5A_len; //PAN length + uint8_t tag_5A_len; //PAN length uint8_t tag_5A[10]; //Application Primary Account Number (PAN) //uint8_t tag_6F[]; //File Control Information (FCI) Template //uint8_t tag_70[255]; //Record Template //uint8_t tag_77[]; //Response Message Template Format 2 - //uint8_t tag_80[]; //Response Message Template Format 1 + //uint8_t tag_80[]; //Response Message Template Format 1 uint8_t tag_82[2]; //Application Interchange Profile AIP //uint8_t tag_83[]; //Command Template - uint8_t tag_84_len; + uint8_t tag_84_len; uint8_t tag_84[16]; //DF Name - uint8_t tag_86_len; + uint8_t tag_86_len; uint8_t tag_86[261]; //Issuer Script Command uint8_t tag_87[1]; //Application Priority Indicator uint8_t tag_88[1]; //Short File Identifier uint8_t tag_8A[2]; //Authorisation Response Code - uint8_t tag_8C_len; + uint8_t tag_8C_len; uint8_t tag_8C[252]; //CDOL1 - uint8_t tag_8D_len; + uint8_t tag_8D_len; uint8_t tag_8D[252]; //CDOL2 - uint8_t tag_8E_len; + uint8_t tag_8E_len; uint8_t tag_8E[252]; //Cardholder Verification Method (CVM) List uint8_t tag_8F[1]; //Certification Authority Public Key Index - uint8_t tag_90_len; + uint8_t tag_90_len; uint8_t tag_90[255]; //ssuer Public Key Certificate - uint8_t tag_92_len; + uint8_t tag_92_len; uint8_t tag_92[255]; //Issuer Public Key Remainder - uint8_t tag_93_len; + uint8_t tag_93_len; uint8_t tag_93[255]; //Signed Static Application Data - uint8_t tag_94_len; + uint8_t tag_94_len; uint8_t tag_94[252]; //Application File Locator AFL uint8_t tag_95[5]; //Terminal Verification Results - uint8_t tag_97_len; + uint8_t tag_97_len; uint8_t tag_97[252]; //Transaction Certificate Data Object List (TDOL) - uint8_t tag_98[20]; //Transaction Certificate (TC) Hash Value + uint8_t tag_98[20]; //Transaction Certificate (TC) Hash Value //assume 20 bytes, change after testing - uint8_t tag_99_len; - uint8_t tag_99[20]; //Transaction Personal Identification Number (PIN) Data - uint8_t tag_9A[3]; //Transaction Date - uint8_t tag_9B[2]; //Transaction Status Information + uint8_t tag_99_len; + uint8_t tag_99[20]; //Transaction Personal Identification Number (PIN) Data + uint8_t tag_9A[3]; //Transaction Date + uint8_t tag_9B[2]; //Transaction Status Information uint8_t tag_9C[1]; //Transaction Type uint8_t tag_9D_len; uint8_t tag_9D[16]; //Directory Definition File - + uint8_t tag_CD[3]; //Card Issuer Action Codes Paypass uint8_t tag_CE[3]; uint8_t tag_CF[3]; - + uint8_t tag_D7[3]; //Application Control (PayPass) - uint8_t tag_D8[2]; //Application Interchange Profile (PayPass) - uint8_t tag_D9_len; //Application File Locator (PayPass) - uint8_t tag_D9[16]; - uint8_t tag_DA[2]; //Static CVC3track1 - uint8_t tag_DB[2]; //Static CVC3track2 - uint8_t tag_DC[2]; //IVCVC3 CVC3track1 - uint8_t tag_DD[2]; //IVCVC3 CVC3track2 - - uint8_t tag_AF_len; - uint8_t tag_AF[255]; //Proprietary Information - - uint8_t tag_5F20_len; + uint8_t tag_D8[2]; //Application Interchange Profile (PayPass) + uint8_t tag_D9_len; //Application File Locator (PayPass) + uint8_t tag_D9[16]; + uint8_t tag_DA[2]; //Static CVC3track1 + uint8_t tag_DB[2]; //Static CVC3track2 + uint8_t tag_DC[2]; //IVCVC3 CVC3track1 + uint8_t tag_DD[2]; //IVCVC3 CVC3track2 + + uint8_t tag_AF_len; + uint8_t tag_AF[255]; //Proprietary Information + + uint8_t tag_5F20_len; uint8_t tag_5F20[26]; //Cardholder Name - uint8_t tag_5F24[3]; //Application Expiry Date + uint8_t tag_5F24[3]; //Application Expiry Date uint8_t tag_5F25[3]; //Application Effective Date YYMMDD - uint8_t tag_5F28[2]; //Issuer Country Code + uint8_t tag_5F28[2]; //Issuer Country Code uint8_t tag_5F2A[2]; //Transaction Currency Code - uint8_t tag_5F2D_len; + uint8_t tag_5F2D_len; uint8_t tag_5F2D[8]; //Language Preference uint8_t tag_5F30[2]; //Service Code uint8_t tag_5F34[1]; //Application Primary Account Number (PAN) Sequence Number uint8_t tag_5F36[2]; //ATC - uint8_t tag_5F50_len; - uint8_t tag_5F50[255]; //Issuer URL - uint8_t tag_5F54_len; - uint8_t tag_5F54[11]; //Bank Identifier Code (BIC) - uint8_t tag_9F01[6]; //Acquirer Identifier + uint8_t tag_5F50_len; + uint8_t tag_5F50[255]; //Issuer URL + uint8_t tag_5F54_len; + uint8_t tag_5F54[11]; //Bank Identifier Code (BIC) + uint8_t tag_9F01[6]; //Acquirer Identifier uint8_t tag_9F02[6]; // Amount, Authorised (Numeric) - uint8_t tag_9F03[6]; //Amount, Other (Numeric) + uint8_t tag_9F03[6]; //Amount, Other (Numeric) uint8_t tag_9F04[4]; //Amount, Other (Binary) - uint8_t tag_9F05_len; - uint8_t tag_9F05[32]; //Application Discretionary Data - uint8_t tag_9F06_len; - uint8_t tag_9F06[16]; //AID terminal - uint8_t tag_9F07[2]; //Application Usage Control - uint8_t tag_9F08[2]; //Application Version Number + uint8_t tag_9F05_len; + uint8_t tag_9F05[32]; //Application Discretionary Data + uint8_t tag_9F06_len; + uint8_t tag_9F06[16]; //AID terminal + uint8_t tag_9F07[2]; //Application Usage Control + uint8_t tag_9F08[2]; //Application Version Number uint8_t tag_9F09[2]; //Application Version Number - //uint8_t tag_9F0A[2] - uint8_t tag_9F0B_len; + //uint8_t tag_9F0A[2] + uint8_t tag_9F0B_len; uint8_t tag_9F0B[45]; //Cardholder Name Extended - uint8_t tag_9F0D[5]; //Issuer Action Code - Default - uint8_t tag_9F0E[5]; //Issuer Action Code - Denial - uint8_t tag_9F0F[5]; //Issuer Action Code - Online + uint8_t tag_9F0D[5]; //Issuer Action Code - Default + uint8_t tag_9F0E[5]; //Issuer Action Code - Denial + uint8_t tag_9F0F[5]; //Issuer Action Code - Online uint8_t tag_9F10_len; //Issuer Application Data - uint8_t tag_9F10[32]; + uint8_t tag_9F10[32]; uint8_t tag_9F11[1]; //Issuer Code Table Index - uint8_t tag_9F12_len; - uint8_t tag_9F12[255]; //Application Preferred Name - uint8_t tag_9F13[2]; //Last Online Application Transaction Counter (ATC) Registerjk + uint8_t tag_9F12_len; + uint8_t tag_9F12[255]; //Application Preferred Name + uint8_t tag_9F13[2]; //Last Online Application Transaction Counter (ATC) Registerjk uint8_t tag_9F14[1]; //Lower Consecutive Offline Limit - uint8_t tag_9F15[2]; //Merchant Category Code + uint8_t tag_9F15[2]; //Merchant Category Code uint8_t tag_9F16[15]; //Merchant Identifier uint8_t tag_9F17[1]; //Personal Identification Number (PIN) Try Counter uint8_t tag_9F18[4]; //Issuer Script Identifier @@ -150,41 +150,41 @@ typedef struct { uint8_t tag_9F1A[2]; //Terminal Country Code uint8_t tag_9F1B[4]; //Terminal Floor Limit uint8_t tag_9F1C[8]; //Terminal Identification - uint8_t tag_9F1D_len; - uint8_t tag_9F1D[8]; //Terminal Risk Management Data - uint8_t tag_9F1E[8]; //Interface Device (IFD) Serial Number + uint8_t tag_9F1D_len; + uint8_t tag_9F1D[8]; //Terminal Risk Management Data + uint8_t tag_9F1E[8]; //Interface Device (IFD) Serial Number uint8_t tag_9F1F_len; - uint8_t tag_9F1F[255]; //Track 1 Discretionary Data + uint8_t tag_9F1F[255]; //Track 1 Discretionary Data uint8_t tag_9F20_len; - uint8_t tag_9F20[255]; //Track 2 DD + uint8_t tag_9F20[255]; //Track 2 DD uint8_t tag_9F21[3]; //Transaction Time uint8_t tag_9F22[1]; //Certification Authority Public Key Index uint8_t tag_9F23[1]; //Upper Consecutive Offline Limit - //uint8_t tag_9F24 - //uint8_t tag_9F25 + //uint8_t tag_9F24 + //uint8_t tag_9F25 uint8_t tag_9F26[8]; //Application Cryptogram uint8_t tag_9F27[1]; //Cryptogram Information Data - //uint8_t tag_9F28 - //uint8_t tag_9F29 + //uint8_t tag_9F28 + //uint8_t tag_9F29 //uint8_t tag_9F2A //uint8_t tag_9F2B //uint8_t tag_9F2C - uint8_t tag_9F2D_len; + uint8_t tag_9F2D_len; uint8_t tag_9F2D[255]; //Integrated Circuit Card (ICC) PIN Encipherment Public Key Certificate uint8_t tag_9F2E[3]; //Integrated Circuit Card (ICC) PIN Encipherment Public Key Exponent - uint8_t tag_9F2F_len; - uint8_t tag_9F2F[255]; //Integrated Circuit Card (ICC) PIN Encipherment Public Key Remainder - //uint8_t tag_9F30 - //uint8_t tag_9F31 - uint8_t tag_9F32_len; + uint8_t tag_9F2F_len; + uint8_t tag_9F2F[255]; //Integrated Circuit Card (ICC) PIN Encipherment Public Key Remainder + //uint8_t tag_9F30 + //uint8_t tag_9F31 + uint8_t tag_9F32_len; uint8_t tag_9F32[3]; //Issuer Public Key Exponent uint8_t tag_9F33[3]; //Terminal Capabilities - uint8_t tag_9F34[3]; //Cardholder Verification Method (CVM) Results + uint8_t tag_9F34[3]; //Cardholder Verification Method (CVM) Results uint8_t tag_9F35[1]; //Terminal Type uint8_t tag_9F36[2]; //Application Transaction Counter (ATC) uint8_t tag_9F37[8]; //Unpredictable Number - uint8_t tag_9F38_len; - uint8_t tag_9F38[255]; //PDOL + uint8_t tag_9F38_len; + uint8_t tag_9F38[255]; //PDOL uint8_t tag_9F39[1]; //Point-of-Service (POS) Entry Mode uint8_t tag_9F40[5]; //Additional Terminal Capabilities uint8_t tag_9F41[4]; //Transaction Sequence Counter @@ -192,21 +192,21 @@ typedef struct { uint8_t tag_9F43[4]; //Application Reference Currency Exponent uint8_t tag_9F44[1]; //Application Currency Exponent uint8_t tag_9F45[2]; //Data Authentication Code - uint8_t tag_9F46_len; + uint8_t tag_9F46_len; uint8_t tag_9F46[255]; //ICC Public Key Certificate - uint8_t tag_9F47_len; + uint8_t tag_9F47_len; uint8_t tag_9F47[3]; //ICC Public Key Exponent - uint8_t tag_9F48_len; + uint8_t tag_9F48_len; uint8_t tag_9F48[255]; //ICC Public Key Remainder - uint8_t tag_9F49_len; - uint8_t tag_9F49[252]; + uint8_t tag_9F49_len; + uint8_t tag_9F49[252]; uint8_t tag_9F4A[1]; //SDA Tag list - uint8_t tag_9F4B_len; - uint8_t tag_9F4B[255]; //Signed Dynamic Application Data + uint8_t tag_9F4B_len; + uint8_t tag_9F4B[255]; //Signed Dynamic Application Data uint8_t tag_9F4C[8]; //ICC Dynamic Number uint8_t tag_9F4D[2]; //Log Entry uint8_t tag_9F4E[255]; //Merchant Name and Location - //9F50-9F7F are payment system specific + //9F50-9F7F are payment system specific uint8_t tag_9F60[2]; //CVC3 track1 uint8_t tag_9F61[2]; //CVC3 track2 uint8_t tag_9F62[6]; //Track 1 Bit Map for CVC3 (PCVC3TRACK1) @@ -215,33 +215,33 @@ typedef struct { uint8_t tag_9F65[2]; //rack 2 Bit Map for CVC3 (PCVC3TRACK2) uint8_t tag_9F66[4]; //Track 2 Bit Map for UN and ATC (PUNATCTRACK2), or VISA card type uint8_t tag_9F67[1]; //Track 2 Number of ATC Digits (NATCTRACK2) - uint8_t tag_9F68_len; + uint8_t tag_9F68_len; uint8_t tag_9F68[252]; //Mag Stripe CVM List - uint8_t tag_9F69_len; + uint8_t tag_9F69_len; uint8_t tag_9F69[255]; //Unpredictable Number Data Object List (UDOL) uint8_t tag_9F6A[8]; //Unpredictable Number (Numeric) - uint8_t tag_9F6B_len; + uint8_t tag_9F6B_len; uint8_t tag_9F6B[19]; //track 2 data uint8_t tag_9F6C[2]; //Mag Stripe Application Version Number(Card) //template holders - uint8_t tag_61_len; + uint8_t tag_61_len; uint8_t tag_61[255]; //Application template - uint8_t tag_6F_len; + uint8_t tag_6F_len; uint8_t tag_6F[255]; //6F template - uint8_t tag_A5_len; - uint8_t tag_A5[255]; //A5 template - uint8_t tag_DFNAME_len; - uint8_t tag_DFNAME[255]; //A5 template - uint8_t tag_70_len; + uint8_t tag_A5_len; + uint8_t tag_A5[255]; //A5 template + uint8_t tag_DFNAME_len; + uint8_t tag_DFNAME[255]; //A5 template + uint8_t tag_70_len; uint8_t tag_70[255]; //70 template - uint8_t tag_77_len; + uint8_t tag_77_len; uint8_t tag_77[255]; //77 template - uint8_t tag_80_len; - uint8_t tag_80[255]; //80 template - uint8_t tag_91_len; //Issuer Authentication Data - uint8_t tag_91[16]; - uint8_t tag_BF0C_len; - uint8_t tag_BF0C[222]; //File Control Information (FCI) Issuer Discretionary Data + uint8_t tag_80_len; + uint8_t tag_80[255]; //80 template + uint8_t tag_91_len; //Issuer Authentication Data + uint8_t tag_91[16]; + uint8_t tag_BF0C_len; + uint8_t tag_BF0C[222]; //File Control Information (FCI) Issuer Discretionary Data uint8_t tag_DFName[16]; uint8_t tag_DFName_len; }emvtags; diff --git a/common/i2c.c b/common/i2c.c index 53627966e..dff77a05a 100644 --- a/common/i2c.c +++ b/common/i2c.c @@ -22,7 +22,7 @@ #define SCL_read (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SCL) #define SDA_read (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SDA) -#define I2C_ERROR "I2C_WaitAck Error" +#define I2C_ERROR "I2C_WaitAck Error" volatile unsigned long c; @@ -42,24 +42,24 @@ void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) { // try i2c bus recovery at 100kHz = 5uS high, 5uS low void I2C_recovery(void) { - - DbpString("Performing i2c bus recovery"); - + + DbpString("Performing i2c bus recovery"); + // reset I2C SDA_H; SCL_H; - + //9nth cycle acts as NACK for (int i = 0; i < 10; i++) { SCL_H; WaitUS(5); SCL_L; WaitUS(5); } - - //a STOP signal (SDA from low to high while CLK is high) + + //a STOP signal (SDA from low to high while CLK is high) SDA_L; WaitUS(5); SCL_H; WaitUS(2); SDA_H; WaitUS(2); - - bool isok = (SCL_read && SDA_read); + + bool isok = (SCL_read && SDA_read); if (!SDA_read) DbpString("I2C bus recovery error: SDA still LOW"); if (!SCL_read) @@ -72,7 +72,7 @@ void I2C_init(void) { // Configure reset pin, close up pull up, push-pull output, default high AT91C_BASE_PIOA->PIO_PPUDR = GPIO_RST; AT91C_BASE_PIOA->PIO_MDDR = GPIO_RST; - + // Configure I2C pin, open up, open leakage AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_SCL | GPIO_SDA); AT91C_BASE_PIOA->PIO_MDER |= (GPIO_SCL | GPIO_SDA); @@ -82,12 +82,12 @@ void I2C_init(void) { AT91C_BASE_PIOA->PIO_OER |= (GPIO_SCL | GPIO_SDA | GPIO_RST); AT91C_BASE_PIOA->PIO_PER |= (GPIO_SCL | GPIO_SDA | GPIO_RST); - - - bool isok = (SCL_read && SDA_read); + + + bool isok = (SCL_read && SDA_read); if ( !isok ) I2C_recovery(); - + } // set the reset state @@ -132,7 +132,7 @@ void I2C_Reset_EnterBootloader(void) { WaitMS(10); } -// Wait for the clock to go High. +// Wait for the clock to go High. bool WaitSCL_H_delay(uint32_t delay) { while (delay--) { if (SCL_read) { @@ -154,9 +154,9 @@ bool WaitSCL_L_delay(uint32_t delay) { if (!SCL_read) { return true; } - I2C_DELAY_1CLK; + I2C_DELAY_1CLK; } - return false; + return false; } // 5000 * 3.07us = 15350us. 15.35ms bool WaitSCL_L(void) { @@ -168,25 +168,25 @@ bool WaitSCL_L(void) { // Which ever comes first bool WaitSCL_L_timeout(void){ volatile uint16_t delay = 1800; - while ( delay-- ) { + while ( delay-- ) { // exit on SCL LOW if (!SCL_read) return true; - + WaitMS(1); } return (delay == 0); } bool I2C_Start(void) { - + I2C_DELAY_XCLK(4); SDA_H; I2C_DELAY_1CLK; - SCL_H; + SCL_H; if (!WaitSCL_H()) return false; I2C_DELAY_2CLK; - + if (!SCL_read) return false; if (!SDA_read) return false; @@ -224,7 +224,7 @@ void I2C_Ack(void) { SCL_L; I2C_DELAY_2CLK; SDA_L; I2C_DELAY_2CLK; SCL_H; I2C_DELAY_2CLK; - if (!WaitSCL_H()) return; + if (!WaitSCL_H()) return; SCL_L; I2C_DELAY_2CLK; } @@ -233,7 +233,7 @@ void I2C_NoAck(void) { SCL_L; I2C_DELAY_2CLK; SDA_H; I2C_DELAY_2CLK; SCL_H; I2C_DELAY_2CLK; - if (!WaitSCL_H()) return; + if (!WaitSCL_H()) return; SCL_L; I2C_DELAY_2CLK; } @@ -259,16 +259,16 @@ void I2C_SendByte(uint8_t data) { while (bits--) { SCL_L; - + I2C_DELAY_1CLK; - + if (data & 0x80) SDA_H; else SDA_L; - + data <<= 1; - + I2C_DELAY_1CLK; SCL_H; @@ -286,11 +286,11 @@ int16_t I2C_ReadByte(void) { SDA_H; while (bits--) { b <<= 1; - SCL_L; + SCL_L; if (!WaitSCL_L()) return -2; - + I2C_DELAY_1CLK; - + SCL_H; if (!WaitSCL_H()) return -1; @@ -375,13 +375,13 @@ bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t dev break; while (len) { - + I2C_SendByte(*data); if (!I2C_WaitAck()) break; len--; - data++; + data++; } if (len == 0) @@ -393,7 +393,7 @@ bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t dev if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); return false; } - return true; + return true; } // read one array of data (Data array, Readout length, command to be written , SlaveDevice address ). @@ -408,7 +408,7 @@ int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d WaitUS(600); bool bBreak = true; uint16_t readcount = 0; - + do { if (!I2C_Start()) return 0; @@ -421,7 +421,7 @@ int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d I2C_SendByte(device_cmd); if (!I2C_WaitAck()) break; - + // 0xB1 / 0xC1 == i2c read I2C_Start(); I2C_SendByte(device_address | 1); @@ -442,35 +442,35 @@ int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t d int16_t tmp = I2C_ReadByte(); if ( tmp < 0 ) return tmp; - + *data = (uint8_t)tmp & 0xFF; len--; - // ȡĵһֽΪ + // ȡĵһֽΪ // The first byte in response is the message length if (!readcount && (len > *data)) { len = *data; } else { - data++; + data++; } readcount++; - + // acknowledgements. After last byte send NACK. if (len == 0) I2C_NoAck(); else I2C_Ack(); } - + I2C_Stop(); - + // return bytecount - first byte (which is length byte) return --readcount; } int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) { - //START, 0xB0, 0x00, 0x00, START, 0xB1, xx, yy, zz, ......, STOP + //START, 0xB0, 0x00, 0x00, START, 0xB1, xx, yy, zz, ......, STOP bool bBreak = true; uint8_t readcount = 0; @@ -491,7 +491,7 @@ int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t I2C_SendByte(lsb); if (!I2C_WaitAck()) break; - + // 0xB1 / 0xC1 i2c read I2C_Start(); I2C_SendByte(device_address | 1); @@ -509,30 +509,30 @@ int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t // reading while (len) { - + int16_t tmp = I2C_ReadByte(); if ( tmp < 0 ) return tmp; - + *data = (uint8_t)tmp & 0xFF; data++; readcount++; len--; - // acknowledgements. After last byte send NACK. + // acknowledgements. After last byte send NACK. if (len == 0) I2C_NoAck(); else I2C_Ack(); } - + I2C_Stop(); return readcount; } bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) { - //START, 0xB0, 0x00, 0x00, xx, yy, zz, ......, STOP + //START, 0xB0, 0x00, 0x00, xx, yy, zz, ......, STOP bool bBreak = true; do { @@ -543,7 +543,7 @@ bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t d I2C_SendByte(device_address & 0xFE); if (!I2C_WaitAck()) break; - + I2C_SendByte(msb); if (!I2C_WaitAck()) break; @@ -558,7 +558,7 @@ bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t d break; len--; - data++; + data++; } if (len == 0) @@ -570,7 +570,7 @@ bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t d if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); return false; } - return true; + return true; } void I2C_print_status(void) { @@ -581,7 +581,7 @@ void I2C_print_status(void) { if ( len > 0 ) Dbprintf(" version.................v%x.%02d", resp[0], resp[1]); else - DbpString(" version.................FAILED"); + DbpString(" version.................FAILED"); } // Will read response from smart card module, retries 3 times to get the data. @@ -590,46 +590,46 @@ bool sc_rx_bytes(uint8_t* dest, uint8_t *destlen) { uint8_t i = 3; int16_t len = 0; while (i--) { - + I2C_WaitForSim(); - + len = I2C_BufferRead(dest, *destlen, I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN); - + if ( len > 1 ){ break; } else if ( len == 1 ) { continue; } else if ( len <= 0 ) { - return false; - } + return false; + } } // after three if ( len <= 1 ) return false; - + *destlen = (uint8_t)len & 0xFF; return true; } bool GetATR(smart_card_atr_t *card_ptr) { - + if ( !card_ptr ) return false; - + card_ptr->atr_len = 0; memset(card_ptr->atr, 0, sizeof(card_ptr->atr)); - + // Send ATR // start [C0 01] stop start C1 len aa bb cc stop] I2C_WriteCmd(I2C_DEVICE_CMD_GENERATE_ATR, I2C_DEVICE_ADDRESS_MAIN); //wait for sim card to answer. // 1byte = 1ms , max frame 256bytes. SHould wait 256ms atleast just in case. - if (!I2C_WaitForSim()) + if (!I2C_WaitForSim()) return false; - + // read bytes from module uint8_t len = sizeof(card_ptr->atr); if ( !sc_rx_bytes(card_ptr->atr, &len) ) @@ -639,12 +639,12 @@ bool GetATR(smart_card_atr_t *card_ptr) { if ( (card_ptr->atr[1] & 0x10) == 0x10) pos_td++; if ( (card_ptr->atr[1] & 0x20) == 0x20) pos_td++; if ( (card_ptr->atr[1] & 0x40) == 0x40) pos_td++; - + // T0 indicate presence T=0 vs T=1. T=1 has checksum TCK if ( (card_ptr->atr[1] & 0x80) == 0x80) { - + pos_td++; - + // 1 == T1 , presence of checksum TCK if ( (card_ptr->atr[pos_td] & 0x01) == 0x01) { @@ -683,16 +683,16 @@ void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) { uint8_t len = 0; uint8_t *resp = BigBuf_malloc(ISO7618_MAX_FRAME); smartcard_command_t flags = arg0; - + if ((flags & SC_CONNECT)) clear_trace(); set_tracing(true); - - if ((flags & SC_CONNECT)) { + + if ((flags & SC_CONNECT)) { I2C_Reset_EnterMainProgram(); - + if ((flags & SC_SELECT)) { smart_card_atr_t card; bool gotATR = GetATR( &card ); @@ -703,15 +703,15 @@ void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) { } if ((flags & SC_RAW) || (flags & SC_RAW_T0)) { - + LogTrace(data, arg1, 0, 0, NULL, true); - + // Send raw bytes // asBytes = A0 A4 00 00 02 // arg1 = len 5 bool res = I2C_BufferWrite(data, arg1, ((flags & SC_RAW_T0) ? I2C_DEVICE_CMD_SEND_T0 : I2C_DEVICE_CMD_SEND), I2C_DEVICE_ADDRESS_MAIN); - if ( !res && MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); - + if ( !res && MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); + // read bytes from module len = ISO7618_MAX_FRAME; res = sc_rx_bytes(resp, &len); @@ -721,11 +721,11 @@ void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) { len = 0; } } -OUT: +OUT: cmd_send(CMD_ACK, len, 0, 0, resp, len); BigBuf_free(); set_tracing(false); - LEDsoff(); + LEDsoff(); } void SmartCardUpgrade(uint64_t arg0) { @@ -735,8 +735,8 @@ void SmartCardUpgrade(uint64_t arg0) { #define I2C_BLOCK_SIZE 128 // write. Sector0, with 11,22,33,44 // erase is 128bytes, and takes 50ms to execute - - I2C_Reset_EnterBootloader(); + + I2C_Reset_EnterBootloader(); bool isOK = true; int16_t res = 0; @@ -744,16 +744,16 @@ void SmartCardUpgrade(uint64_t arg0) { uint16_t pos = 0; uint8_t *fwdata = BigBuf_get_addr(); uint8_t *verfiydata = BigBuf_malloc(I2C_BLOCK_SIZE); - + while (length) { - + uint8_t msb = (pos >> 8) & 0xFF; uint8_t lsb = pos & 0xFF; - + Dbprintf("FW %02X%02X", msb, lsb); size_t size = MIN(I2C_BLOCK_SIZE, length); - + // write res = I2C_WriteFW(fwdata+pos, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT); if ( !res ) { @@ -761,7 +761,7 @@ void SmartCardUpgrade(uint64_t arg0) { isOK = false; break; } - + // writing takes time. WaitMS(50); @@ -769,23 +769,23 @@ void SmartCardUpgrade(uint64_t arg0) { res = I2C_ReadFW(verfiydata, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT); if ( res <= 0) { DbpString("Reading back failed"); - isOK = false; + isOK = false; break; } - + // cmp if ( 0 != memcmp(fwdata+pos, verfiydata, size)) { DbpString("not equal data"); - isOK = false; + isOK = false; break; } - + length -= size; pos += size; - } + } cmd_send(CMD_ACK, isOK, pos, 0, 0, 0); LED_C_OFF(); - BigBuf_free(); + BigBuf_free(); } void SmartCardSetBaud(uint64_t arg0) { @@ -793,13 +793,13 @@ void SmartCardSetBaud(uint64_t arg0) { void SmartCardSetClock(uint64_t arg0) { LED_D_ON(); - set_tracing(true); - I2C_Reset_EnterMainProgram(); + set_tracing(true); + I2C_Reset_EnterMainProgram(); // Send SIM CLC // start [C0 05 xx] stop I2C_WriteByte(arg0, I2C_DEVICE_CMD_SIM_CLC, I2C_DEVICE_ADDRESS_MAIN); - + cmd_send(CMD_ACK, 1, 0, 0, 0, 0); set_tracing(false); LEDsoff(); diff --git a/common/iso14443crc.c b/common/iso14443crc.c index 01e77c855..ceac3c4df 100644 --- a/common/iso14443crc.c +++ b/common/iso14443crc.c @@ -39,7 +39,7 @@ bool CheckCrc14443(uint16_t CrcType, const uint8_t *data, int length) { if (length < 3) return false; uint8_t b1, b2; ComputeCrc14443(CrcType, data, length - 2, &b1, &b2); - if ((b1 == data[length - 2]) && (b2 == data[length - 1])) + if ((b1 == data[length - 2]) && (b2 == data[length - 1])) return true; return false; } diff --git a/common/iso15693tools.c b/common/iso15693tools.c index 8d06c026c..fbd79da52 100644 --- a/common/iso15693tools.c +++ b/common/iso15693tools.c @@ -15,7 +15,7 @@ char* Iso15693sprintUID(char *target, uint8_t *uid) { static char tempbuf[2*8+1] = {0}; - if (target == NULL) + if (target == NULL) target = tempbuf; sprintf(target, "%02X %02X %02X %02X %02X %02X %02X %02X", uid[7], uid[6], uid[5], uid[4], diff --git a/common/iso15693tools.h b/common/iso15693tools.h index 70382ce04..0dd4d4444 100644 --- a/common/iso15693tools.h +++ b/common/iso15693tools.h @@ -39,7 +39,7 @@ //RESPONSE FLAGS #define ISO15_RES_ERROR 0x01 -#define ISO15_RES_EXT 0x08 // Protocol Extention +#define ISO15_RES_EXT 0x08 // Protocol Extention // RESPONSE ERROR CODES #define ISO15_NOERROR 0x00 @@ -47,7 +47,7 @@ #define ISO15_ERROR_CMD_NOT_REC 0x02 // Command not recognized (eg. parameter error) #define ISO15_ERROR_CMD_OPTION 0x03 // Command option not supported #define ISO15_ERROR_GENERIC 0x0F // No additional Info about this error -#define ISO15_ERROR_BLOCK_UNAVAILABLE 0x10 +#define ISO15_ERROR_BLOCK_UNAVAILABLE 0x10 #define ISO15_ERROR_BLOCK_LOCKED_ALREADY 0x11 // cannot lock again #define ISO15_ERROR_BLOCK_LOCKED 0x12 // cannot be changed #define ISO15_ERROR_BLOCK_WRITE 0x13 // Writing was unsuccessful diff --git a/common/legic_prng.c b/common/legic_prng.c index df711aa10..c4927b33b 100644 --- a/common/legic_prng.c +++ b/common/legic_prng.c @@ -11,7 +11,7 @@ // a is 7bit lsfr // b is 8bit lsfr // c keeps track on which step the prng is. -// legic_prng_get_bit() = gets a bit muxed from a and b. +// legic_prng_get_bit() = gets a bit muxed from a and b. struct lfsr { uint8_t a; uint8_t b; @@ -26,10 +26,10 @@ struct lfsr { // Now we have a special case with iv == 0 // it sets b to 0 aswell to make sure we get a all zero keystream out // which is used in the initialisation phase sending the IV -// +// void legic_prng_init(uint8_t iv) { lfsr.a = iv; - lfsr.b = 0; // hack to get a always 0 keystream + lfsr.b = 0; // hack to get a always 0 keystream lfsr.c = 0; if(iv) lfsr.b = (iv << 1) | 1; @@ -37,7 +37,7 @@ void legic_prng_init(uint8_t iv) { void legic_prng_forward(int count) { if (count == 0) return; - + lfsr.c += count; while(count--) { // According: http://www.proxmark.org/forum/viewtopic.php?pid=5437#p5437 diff --git a/common/lfdemod.c b/common/lfdemod.c index b9807ff8f..65999ae77 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -8,20 +8,20 @@ // Low frequency demod/decode commands - by marshmellow, holiman, iceman and // many others who came before // -// NOTES: +// NOTES: // LF Demod functions are placed here to allow the flexability to use client or -// device side. Most BUT NOT ALL of these functions are currenlty safe for +// device side. Most BUT NOT ALL of these functions are currenlty safe for // device side use currently. (DetectST for example...) // // There are likely many improvements to the code that could be made, please // make suggestions... // -// we tried to include author comments so any questions could be directed to +// we tried to include author comments so any questions could be directed to // the source. // // There are 4 main sections of code below: // -// Utilities Section: +// Utilities Section: // for general utilities used by multiple other functions // // Clock / Bitrate Detection Section: @@ -58,7 +58,7 @@ extern void Dbprintf(const char *fmt, ...); # include "cmdparser.h" # include "cmddata.h" # define prnt PrintAndLog -#else +#else uint8_t g_debugMode = 0; # define prnt Dbprintf #endif @@ -99,11 +99,11 @@ void computeSignalProperties(uint8_t *samples, uint32_t size) { // measure amplitude of signal signalprop.mean = sum / size; signalprop.amplitude = signalprop.high - signalprop.mean; - // By measuring mean and look at amplitude of signal from HIGH / LOW, + // By measuring mean and look at amplitude of signal from HIGH / LOW, // we can detect noise signalprop.isnoise = signalprop.amplitude < NOISE_AMPLITUDE_THRESHOLD; - if (g_debugMode) + if (g_debugMode) printSignal(); } @@ -136,17 +136,17 @@ void getHiLo(int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo) { *low = (signalprop.low * fuzzLo) / 100; } else { uint8_t range = signalprop.high - signalprop.low; - + *low = signalprop.low + ((range * (100-fuzzLo))/100); } - + // if fuzzing to great and overlap if ( *high < *low ) { *high = signalprop.high; *low = signalprop.low; } - - if (g_debugMode) + + if (g_debugMode) prnt("getHiLo fuzzed: High %d | Low %d", *high, *low); } @@ -159,7 +159,7 @@ bool parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType) { //by marshmellow // takes a array of binary values, start position, length of bits per parity (includes parity bit - MAX 32), -// Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run) +// Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run) size_t removeParity(uint8_t *bits, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen) { uint32_t parityWd = 0; size_t bitCnt = 0; @@ -201,7 +201,7 @@ size_t addParity(uint8_t *src, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, u switch (pType) { case 3: dest[j++]=0; break; // marker bit which should be a 0 case 2: dest[j++]=1; break; // marker bit which should be a 1 - default: + default: dest[j++] = parityTest(parityWd, pLen-1, pType) ^ 1; break; } @@ -216,7 +216,7 @@ size_t addParity(uint8_t *src, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, u // array must be size dividable with 8 uint8_t bits_to_array(const uint8_t *bits, size_t size, uint8_t *dest) { if ( (size == 0) || (size % 8) != 0) return 0; - + for(uint32_t i = 0; i < (size / 8); i++) dest[i] = bytebits_to_byte((uint8_t *) bits + (i * 8), 8); @@ -247,14 +247,14 @@ bool preambleSearch(uint8_t *bits, uint8_t *preamble, size_t pLen, size_t *size, return preambleSearchEx(bits, preamble, pLen, size, startIdx, false); } //by marshmellow -// search for given preamble in given BitStream and return success=1 or fail=0 and startIndex (where it was found) and length if not fineone +// search for given preamble in given BitStream and return success=1 or fail=0 and startIndex (where it was found) and length if not fineone // fineone does not look for a repeating preamble for em4x05/4x69 sends preamble once, so look for it once in the first pLen bits //(iceman) FINDONE, only finds start index. NOT SIZE!. I see Em410xDecode (lfdemod.c) uses SIZE to determine success bool preambleSearchEx(uint8_t *bits, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx, bool findone) { // Sanity check. If preamble length is bigger than bits length. if ( *size <= pLen ) return false; - + uint8_t foundCnt = 0; for (size_t idx = 0; idx < *size - pLen; idx++) { if (memcmp(bits+idx, preamble, pLen) == 0){ @@ -284,12 +284,12 @@ size_t findModStart(uint8_t *src, size_t size, uint8_t expWaveSize) { for (; i < size-20; i++ ) { if (src[i] < signalprop.mean && isAboveThreshold) { thresholdCnt++; - if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break; + if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break; isAboveThreshold = false; waveSizeCnt = 0; } else if (src[i] >= signalprop.mean && !isAboveThreshold) { thresholdCnt++; - if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break; + if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break; isAboveThreshold = true; waveSizeCnt = 0; } else { @@ -326,13 +326,13 @@ void getNextHigh(uint8_t *samples, size_t size, int high, size_t *i) { bool loadWaveCounters(uint8_t *samples, size_t size, int lowToLowWaveLen[], int highToLowWaveLen[], int *waveCnt, int *skip, int *minClk, int *high, int *low) { size_t i = 0, firstLow, firstHigh; //size_t testsize = (size < 512) ? size : 512; - + // just noise - no super good detection. good enough if (signalprop.isnoise) { if (g_debugMode == 2) prnt("DEBUG STT: just noise detected - quitting"); return false; } - + getHiLo(high, low, 80, 80); // get to first full low to prime loop and skip incomplete first pulse @@ -354,7 +354,7 @@ bool loadWaveCounters(uint8_t *samples, size_t size, int lowToLowWaveLen[], int break; highToLowWaveLen[*waveCnt] = i - firstHigh; //first high to first low - lowToLowWaveLen[*waveCnt] = i - firstLow; + lowToLowWaveLen[*waveCnt] = i - firstLow; *waveCnt += 1; if (i-firstLow < *minClk && i < size) { *minClk = i - firstLow; @@ -399,7 +399,7 @@ void askAmp(uint8_t *bits, size_t size) { last = 255; else if ( bits[i-1] - bits[i] >= 20) //large jump down last = 0; - + bits[i] = last; } } @@ -416,7 +416,7 @@ uint32_t manchesterEncode2Bytes(uint16_t datain) { } //by marshmellow -//encode binary data into binary manchester +//encode binary data into binary manchester //NOTE: bitstream must have triple the size of "size" available in memory to do the swap int ManchesterEncode(uint8_t *bits, size_t size) { //allow up to 4096b out (means bits must be at least 2048+4096 to handle the swap) @@ -440,18 +440,18 @@ bool DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low) { bool allArePeaks = true; uint16_t cntPeaks = 0; size_t loopEnd = 512 + 160; - + // sanity check if (loopEnd > size) loopEnd = size; - + for (size_t i = 160; i < loopEnd; i++){ - - if (dest[i] > low && dest[i] < high) + + if (dest[i] > low && dest[i] < high) allArePeaks = false; else cntPeaks++; } - + if (!allArePeaks){ if (cntPeaks > 250) return true; } @@ -472,11 +472,11 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo size_t i = 100; size_t minClk = 512; int shortestWaveIdx = 0; - + // get to first full low to prime loop and skip incomplete first pulse getNextHigh(dest, size, high, &i); getNextLow(dest, size, low, &i); - + // loop through all samples (well, we don't want to go out-of-bounds) while (i < size-512) { // measure from low to low @@ -491,14 +491,14 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo shortestWaveIdx = startwave; } } - + // set clock if (g_debugMode == 2) prnt("DEBUG ASK: DetectStrongAskClock smallest wave: %d", minClk); *clock = getClosestClock(minClk); - if (*clock == 0) + if (*clock == 0) return -1; - + return shortestWaveIdx; } @@ -509,27 +509,27 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { //don't need to loop through entire array. (cotag has clock of 384) - uint16_t loopCnt = 1500; + uint16_t loopCnt = 1500; // not enough samples if (size <= loopCnt + 60){ if (g_debugMode == 2) prnt("DEBUG DetectASKClock: not enough samples - aborting"); - return -1; + return -1; } - + // just noise - no super good detection. good enough if (signalprop.isnoise) { if (g_debugMode == 2) prnt("DEBUG DetectASKClock: just noise detected - aborting"); return -2; } - + size_t i = 1; uint16_t num_clks = 9; // first 255 value pos0 is placeholder for user inputed clock. uint16_t clk[] = {255, 8, 16, 32, 40, 50, 64, 100, 128, 255}; - + // sometimes there is a strange end wave - filter out this - size -= 60; + size -= 60; // What is purpose? // already have a valid clock? @@ -543,28 +543,28 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { // threshold 75% of high, low peak int peak_hi, peak_low; getHiLo(&peak_hi, &peak_low, 75, 75); - + // test for large clean, STRONG, CLIPPED peaks - + if (!found_clk) { - + if (DetectCleanAskWave(dest, size, peak_hi, peak_low)){ - + int idx = DetectStrongAskClock(dest, size, peak_hi, peak_low, clock); - if (g_debugMode == 2) + if (g_debugMode == 2) prnt("DEBUG ASK: DetectASKClock Clean ASK Wave detected: clk %i, Best Starting Position: %i", *clock, idx); - + // return shortest wave start position if (idx > -1) return idx; } } // test for weak peaks - + // test clock if given as cmd parameter if ( *clock > 0 ) clk[0] = *clock; - + uint8_t clkCnt, tol = 0; size_t j = 0; uint16_t bestErr[] = {1000,1000,1000,1000,1000,1000,1000,1000,1000}; @@ -586,7 +586,7 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { tol = 0; } //if no errors allowed - keep start within the first clock - if (!maxErr && size > clk[clkCnt]*2 + tol && clk[clkCnt] < 128) + if (!maxErr && size > clk[clkCnt]*2 + tol && clk[clkCnt] < 128) loopCnt = clk[clkCnt] * 2; bestErr[clkCnt] = 1000; @@ -596,7 +596,7 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { // get to first full low to prime loop and skip incomplete first pulse getNextHigh(dest, size, peak_hi, &j); getNextLow(dest, size, peak_low, &j); - + for (; j < loopCnt; j++){ errCnt = 0; // now that we have the first one lined up test rest of wave array @@ -613,11 +613,11 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { // if we found no errors then we can stop here and a low clock (common clocks) // this is correct one - return this clock // if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d", clk[clkCnt], errCnt, j, i); - if (errCnt == 0 && clkCnt < 7) { - if (!found_clk) + if (errCnt == 0 && clkCnt < 7) { + if (!found_clk) *clock = clk[clkCnt]; return j; - } + } // if we found errors see if it is lowest so far and save it as best run if (errCnt < bestErr[clkCnt]) { bestErr[clkCnt] = errCnt; @@ -625,9 +625,9 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { } } } - + uint8_t k, best = 0; - + for (k=1; k < num_clks; ++k){ if (bestErr[k] < bestErr[best]){ if (bestErr[k] == 0) bestErr[k] = 1; @@ -638,10 +638,10 @@ int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { } //if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, # Errors %d, Current Best Clk %d, bestStart %d", clk[k], bestErr[k], clk[best], bestStart[best]); } - - if (!found_clk) + + if (!found_clk) *clock = clk[best]; - + return bestStart[best]; } @@ -669,16 +669,16 @@ int DetectStrongNRZClk(uint8_t *dest, size_t size, int peak, int low, bool *stro for (;i < size; i++) { if ((dest[i] >= peak && !lastWasHigh) || (dest[i] <= low && lastWasHigh)) { lastWasHigh = (dest[i] >= peak); - if (i-transition1 < lowestTransition) + if (i-transition1 < lowestTransition) lowestTransition = i-transition1; transition1 = i; } else if (dest[i] < peak && dest[i] > low) { transitionSampleCount++; } } - if (lowestTransition == 255) + if (lowestTransition == 255) lowestTransition = 0; - + if (g_debugMode == 2) prnt("DEBUG NRZ: detectstrongNRZclk smallest wave: %d", lowestTransition); // if less than 10% of the samples were not peaks (or 90% were peaks) then we have a strong wave if (transitionSampleCount / size < 10) { @@ -698,23 +698,23 @@ int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx) //if we already have a valid clock quit for (; i < 8; ++i) if (clk[i] == clock) return clock; - + if (size < 20) return 0; // size must be larger than 20 here if (size < loopCnt) loopCnt = size-20; - + // just noise - no super good detection. good enough if (signalprop.isnoise) { if (g_debugMode == 2) prnt("DEBUG DetectNZRClock: just noise detected - quitting"); return 0; } - + //get high and low peak int peak, low; //getHiLo(dest, loopCnt, &peak, &low, 90, 90); getHiLo(&peak, &low, 90, 90); - + bool strong = false; int lowestTransition = DetectStrongNRZClk(dest, size-20, peak, low, &strong); if (strong) return lowestTransition; @@ -742,10 +742,10 @@ int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx) } } if (minPeak < 8) return 0; - + bool errBitHigh = 0, bitHigh = 0, lastPeakHigh = 0; uint8_t ignoreCnt = 0, ignoreWindow = 4; - int lastBit = 0; + int lastBit = 0; size_t bestStart[] = {0,0,0,0,0,0,0,0,0}; peakcnt = 0; //test each valid clock from smallest to greatest to see which lines up @@ -758,7 +758,7 @@ int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx) peakcnt=0; bitHigh = false; ignoreCnt = 0; - lastBit = ii-clk[clkCnt]; + lastBit = ii-clk[clkCnt]; //loop through to see if this start location works for (i = ii; i < size-20; ++i) { //if we are at a clock bit @@ -781,7 +781,7 @@ int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx) } else if (dest[i] < peak && dest[i] > low){ if (ignoreCnt == 0){ bitHigh = false; - if (errBitHigh == true) + if (errBitHigh == true) peakcnt--; errBitHigh = false; } else { @@ -841,7 +841,7 @@ uint16_t countFC(uint8_t *bits, size_t size, bool fskAdj) { if (fskAdj){ //if we had 5 and now have 9 then go back to 8 (for when we get a fc 9 instead of an 8) if (lastFCcnt == 5 && fcCounter == 9) fcCounter--; - + //if fc=9 or 4 add one (for when we get a fc 9 instead of 10 or a 4 instead of a 5) if ((fcCounter == 9) || fcCounter == 4) fcCounter++; // save last field clock count (fc/xx) @@ -856,7 +856,7 @@ uint16_t countFC(uint8_t *bits, size_t size, bool fskAdj) { } } if (fcCounter>0 && fcLensFnd<15){ - //add new fc length + //add new fc length fcCnts[fcLensFnd]++; fcLens[fcLensFnd++] = fcCounter; } @@ -866,10 +866,10 @@ uint16_t countFC(uint8_t *bits, size_t size, bool fskAdj) { fcCounter++; } } - + uint8_t best1 = 14, best2 = 14, best3 = 14; uint16_t maxCnt1 = 0; - // go through fclens and find which ones are bigest 2 + // go through fclens and find which ones are bigest 2 for (i=0; i<15; i++){ // get the 3 best FC values if (fcCnts[i] > maxCnt1) { @@ -886,7 +886,7 @@ uint16_t countFC(uint8_t *bits, size_t size, bool fskAdj) { if (g_debugMode == 2) prnt("DEBUG countfc: FC %u, Cnt %u, best fc: %u, best2 fc: %u", fcLens[i], fcCnts[i], fcLens[best1], fcLens[best2]); if (fcLens[i] == 0) break; } - + if (fcLens[best1] == 0) return 0; uint8_t fcH = 0, fcL = 0; if (fcLens[best1] > fcLens[best2]){ @@ -903,7 +903,7 @@ uint16_t countFC(uint8_t *bits, size_t size, bool fskAdj) { // TODO: take top 3 answers and compare to known Field clocks to get top 2 uint16_t fcs = (((uint16_t)fcH)<<8) | fcL; - if (fskAdj) return fcs; + if (fskAdj) return fcs; return (uint16_t)fcLens[best2] << 8 | fcLens[best1]; } @@ -921,16 +921,16 @@ int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShif if (size < 160+20) return 0; // size must be larger than 20 here, and 160 later on. - if (size < loopCnt) loopCnt = size-20; + if (size < loopCnt) loopCnt = size-20; uint16_t fcs = countFC(dest, size, 0); - + *fc = fcs & 0xFF; - + if (g_debugMode == 2) prnt("DEBUG PSK: FC: %d, FC2: %d",*fc, fcs>>8); - + if ((fcs >> 8) == 10 && *fc == 8) return 0; - + if (*fc != 2 && *fc != 4 && *fc != 8) return 0; @@ -941,7 +941,7 @@ int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShif uint16_t bestErr[] = {1000,1000,1000,1000,1000,1000,1000,1000,1000}; uint16_t peaksdet[] = {0,0,0,0,0,0,0,0,0}; - //find start of modulating data in trace + //find start of modulating data in trace i = findModStart(dest, size, *fc); firstFullWave = pskFindFirstPhaseShift(dest, size, curPhase, i, *fc, &fullWaveLen); @@ -954,7 +954,7 @@ int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShif *firstPhaseShift = firstFullWave; if (g_debugMode == 2) prnt("DEBUG PSK: firstFullWave: %d, waveLen: %d",firstFullWave,fullWaveLen); - + //test each valid clock from greatest to smallest to see which lines up for (clkCnt=7; clkCnt >= 1 ; clkCnt--){ tol = *fc/2; @@ -965,7 +965,7 @@ int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShif if (g_debugMode == 2) prnt("DEBUG PSK: clk: %d, lastClkBit: %d", clk[clkCnt], lastClkBit); for (i = firstFullWave+fullWaveLen-1; i < loopCnt-2; i++){ - //top edge of wave = start of new wave + //top edge of wave = start of new wave if (dest[i] < dest[i+1] && dest[i+1] >= dest[i+2]){ if (waveStart == 0) { waveStart = i+1; @@ -973,7 +973,7 @@ int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShif } else { //waveEnd waveEnd = i+1; waveLenCnt = waveEnd-waveStart; - if (waveLenCnt > *fc){ + if (waveLenCnt > *fc){ //if this wave is a phase shift if (g_debugMode == 2) prnt("DEBUG PSK: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d", waveStart, waveLenCnt, lastClkBit + clk[clkCnt] - tol, i+1, *fc); if (i+1 >= lastClkBit + clk[clkCnt] - tol){ //should be a clock bit @@ -994,8 +994,8 @@ int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShif if (errCnt == 0) return clk[clkCnt]; if (errCnt <= bestErr[clkCnt]) bestErr[clkCnt] = errCnt; if (peakcnt > peaksdet[clkCnt]) peaksdet[clkCnt] = peakcnt; - } - //all tested with errors + } + //all tested with errors //return the highest clk with the most peaks found uint8_t best = 7; for (i=7; i >= 1; i--){ @@ -1011,9 +1011,9 @@ int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShif //detects the bit clock for FSK given the high and low Field Clocks uint8_t detectFSKClk(uint8_t *bits, size_t size, uint8_t fcHigh, uint8_t fcLow, int *firstClockEdge) { - if (size == 0) + if (size == 0) return 0; - + uint8_t clk[] = {8,16,32,40,50,64,100,128,0}; uint16_t rfLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; uint8_t rfCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; @@ -1034,14 +1034,14 @@ uint8_t detectFSKClk(uint8_t *bits, size_t size, uint8_t fcHigh, uint8_t fcLow, fcCounter++; rfCounter++; - if (bits[i] <= bits[i-1] || bits[i] < bits[i+1]) - continue; - // else new peak + if (bits[i] <= bits[i-1] || bits[i] < bits[i+1]) + continue; + // else new peak // if we got less than the small fc + tolerance then set it to the small fc // if it is inbetween set it to the last counter if (fcCounter < fcHigh && fcCounter > fcLow) fcCounter = lastFCcnt; - else if (fcCounter < fcLow+fcTol) + else if (fcCounter < fcLow+fcTol) fcCounter = fcLow; else //set it to the large fc fcCounter = fcHigh; @@ -1085,14 +1085,14 @@ uint8_t detectFSKClk(uint8_t *bits, size_t size, uint8_t fcHigh, uint8_t fcLow, } else if(rfCnts[i] > rfCnts[rfHighest3]){ rfHighest3 = i; } - if (g_debugMode == 2) + if (g_debugMode == 2) prnt("DEBUG FSK: RF %d, cnts %d", rfLens[i], rfCnts[i]); - } - // set allowed clock remainder tolerance to be 1 large field clock length+1 - // we could have mistakenly made a 9 a 10 instead of an 8 or visa versa so rfLens could be 1 FC off - uint8_t tol1 = fcHigh+1; - - if (g_debugMode == 2) + } + // set allowed clock remainder tolerance to be 1 large field clock length+1 + // we could have mistakenly made a 9 a 10 instead of an 8 or visa versa so rfLens could be 1 FC off + uint8_t tol1 = fcHigh+1; + + if (g_debugMode == 2) prnt("DEBUG FSK: most counted rf values: 1 %d, 2 %d, 3 %d", rfLens[rfHighest], rfLens[rfHighest2], rfLens[rfHighest3]); // loop to find the highest clock that has a remainder less than the tolerance @@ -1103,7 +1103,7 @@ uint8_t detectFSKClk(uint8_t *bits, size_t size, uint8_t fcHigh, uint8_t fcLow, if (rfLens[rfHighest] % clk[m] < tol1 || rfLens[rfHighest] % clk[m] > clk[m]-tol1){ if (rfLens[rfHighest2] % clk[m] < tol1 || rfLens[rfHighest2] % clk[m] > clk[m]-tol1){ if (rfLens[rfHighest3] % clk[m] < tol1 || rfLens[rfHighest3] % clk[m] > clk[m]-tol1){ - if (g_debugMode == 2) + if (g_debugMode == 2) prnt("DEBUG FSK: clk %d divides into the 3 most rf values within tolerance", clk[m]); break; } @@ -1146,7 +1146,7 @@ bool findST(int *stStopLoc, int *stStartIdx, int lowToLowWaveLen[], int highToLo bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, size_t *stend) { size_t bufsize = *size; //need to loop through all samples and identify our clock, look for the ST pattern - int clk = 0; + int clk = 0; int tol = 0; int j=0, high, low, skip=0, start=0, end=0, minClk=255; size_t i = 0; @@ -1181,7 +1181,7 @@ bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, s phaseoff = 0; else phaseoff = clk/2; - + // skip over the remainder of ST skip += clk*7/2; //3.5 clocks from tmpbuff[i] = end of st - also aligns for ending point @@ -1212,12 +1212,12 @@ bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, s } // if datalen is less than one t55xx block - ERROR if (datalen/clk < 8*4) { - if (g_debugMode == 2) prnt("DEBUG STT: datalen is less than 1 full t55xx block - quitting"); + if (g_debugMode == 2) prnt("DEBUG STT: datalen is less than 1 full t55xx block - quitting"); return false; } size_t dataloc = start; if (buffer[dataloc-(clk*4)-(clk/4)] <= low && buffer[dataloc] <= low && buffer[dataloc-(clk*4)] >= high) { - //we have low drift (and a low just before the ST and a low just after the ST) - compensate by backing up the start + //we have low drift (and a low just before the ST and a low just after the ST) - compensate by backing up the start for ( i=0; i <= (clk/4); ++i ) { if ( buffer[dataloc - (clk*4) - i] <= low ) { dataloc -= i; @@ -1225,10 +1225,10 @@ bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, s } } } - + size_t newloc = 0; i=0; - if (g_debugMode == 2) prnt("DEBUG STT: Starting STT trim - start: %d, datalen: %d ",dataloc, datalen); + if (g_debugMode == 2) prnt("DEBUG STT: Starting STT trim - start: %d, datalen: %d ",dataloc, datalen); bool firstrun = true; // warning - overwriting buffer given with raw wave data with ST removed... while ( dataloc < bufsize-(clk/2) ) { @@ -1253,7 +1253,7 @@ bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, s if (i+newloc < dataloc) buffer[i+newloc] = buffer[dataloc]; - dataloc++; + dataloc++; } } newloc += i; @@ -1266,17 +1266,17 @@ bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, s } //by marshmellow -//take 11 10 01 11 00 and make 01100 ... miller decoding +//take 11 10 01 11 00 and make 01100 ... miller decoding //check for phase errors - should never have half a 1 or 0 by itself and should never exceed 1111 or 0000 in a row //decodes miller encoded binary //NOTE askrawdemod will NOT demod miller encoded ask unless the clock is manually set to 1/2 what it is detected as! int millerRawDecode(uint8_t *bits, size_t *size, int invert) { if (*size < 16) return -1; - + uint16_t MaxBits = 512, errCnt = 0; size_t i, bitCnt = 0; uint8_t alignCnt = 0, curBit = bits[0], alignedIdx = 0, halfClkErr = 0; - + //find alignment, needs 4 1s or 0s to properly align for (i=1; i < *size-1; i++) { alignCnt = (bits[i] == curBit) ? alignCnt+1 : 0; @@ -1311,7 +1311,7 @@ int millerRawDecode(uint8_t *bits, size_t *size, int invert) { int BiphaseRawDecode(uint8_t *bits, size_t *size, int *offset, int invert) { //sanity check if (*size < 51) return -1; - + uint16_t bitnum = 0; uint16_t errCnt = 0; size_t i = *offset; @@ -1324,7 +1324,7 @@ int BiphaseRawDecode(uint8_t *bits, size_t *size, int *offset, int invert) { if (bits[i+2] == bits[i+3]) offsetB = false; } if (!offsetA && offsetB) ++*offset; - + for (i = *offset; i < *size-3; i += 2){ //check for phase error if (bits[i+1] == bits[i+2]) { @@ -1352,7 +1352,7 @@ int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos) // sanity check if (*size < 16) return -1; - + int errCnt = 0, bestErr = 1000; uint16_t bitnum = 0, maxBits = 512, bestRun = 0; size_t i, k; @@ -1394,7 +1394,7 @@ int cleanAskRawDemod(uint8_t *bits, size_t *size, int clk, int invert, int high, uint8_t cl_4 = clk / 4; uint8_t cl_2 = clk / 2; bool waveHigh = true; - + getNextHigh(bits, *size, high, &pos); // sample counts, like clock = 32.. it tries to find 32/4 = 8, 32/2 = 16 @@ -1409,7 +1409,7 @@ int cleanAskRawDemod(uint8_t *bits, size_t *size, int clk, int invert, int high, // 32-8-1 = 23 // 32+8+1 = 41 if (smplCnt > clk - cl_4 - 1) { //full clock - + if (smplCnt > clk + cl_4 + 1) { //too many samples errCnt++; if (g_debugMode == 2) prnt("DEBUG ASK: cleanAskRawDemod ASK Modulation Error FULL at: %u [%u]", i, smplCnt); @@ -1423,18 +1423,18 @@ int cleanAskRawDemod(uint8_t *bits, size_t *size, int clk, int invert, int high, } if (*startIdx == 0) *startIdx = i - clk; - waveHigh = !waveHigh; + waveHigh = !waveHigh; smplCnt = 0; - + // 16-8-1 = 7 } else if (smplCnt > cl_2 - cl_4 - 1) { //half clock - + if (smplCnt > cl_2 + cl_4 + 1) { //too many samples errCnt++; if (g_debugMode == 2) prnt("DEBUG ASK: cleanAskRawDemod ASK Modulation Error HALF at: %u [%u]", i, smplCnt); bits[bitCnt++] = 7; } - + if (waveHigh) { bits[bitCnt++] = invert; } else if (!waveHigh) { @@ -1442,7 +1442,7 @@ int cleanAskRawDemod(uint8_t *bits, size_t *size, int clk, int invert, int high, } if (*startIdx == 0) *startIdx = i - cl_2; - waveHigh = !waveHigh; + waveHigh = !waveHigh; smplCnt = 0; } else { smplCnt++; @@ -1460,59 +1460,59 @@ int cleanAskRawDemod(uint8_t *bits, size_t *size, int clk, int invert, int high, //by marshmellow //attempts to demodulate ask modulations, askType == 0 for ask/raw, askType==1 for ask/manchester int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType, int *startIdx) { - + if (*size == 0) return -1; - + int start = DetectASKClock(bits, *size, clk, maxErr); if (*clk == 0 || start < 0) return -3; - + if (*invert != 1) *invert = 0; - + // amplify signal data. - // ICEMAN todo, + // ICEMAN todo, if (amp == 1) askAmp(bits, *size); - + if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, beststart %d, amp %d", *clk, start, amp); - + //start pos from detect ask clock is 1/2 clock offset // NOTE: can be negative (demod assumes rest of wave was there) - *startIdx = start - (*clk/2); + *startIdx = start - (*clk/2); uint16_t initLoopMax = 1024; if (initLoopMax > *size) initLoopMax = *size; - + // just noise - no super good detection. good enough if (signalprop.isnoise) { if (g_debugMode == 2) prnt("DEBUG askdemod_ext: just noise detected - aborting"); return -2; } - + // Detect high and lows //25% clip in case highs and lows aren't clipped [marshmellow] int high, low; //getHiLo(bits, initLoopMax, &high, &low, 75, 75); getHiLo(&high, &low, 75, 75); - + size_t errCnt = 0; // if clean clipped waves detected run alternate demod if (DetectCleanAskWave(bits, *size, high, low)) { if (g_debugMode == 2) prnt("DEBUG ASK: Clean Wave Detected - using clean wave demod"); - + errCnt = cleanAskRawDemod(bits, size, *clk, *invert, high, low, startIdx); if (askType) { //ask/manchester uint8_t alignPos = 0; errCnt = manrawdecode(bits, size, 0, &alignPos); *startIdx += *clk/2 * alignPos; - - if (g_debugMode) + + if (g_debugMode) prnt("DEBUG: (askdemod_ext) CLEAN: startIdx %i, alignPos %u", *startIdx, alignPos); - } + } return errCnt; } - + if (g_debugMode) prnt("DEBUG: (askdemod_ext) Weak wave detected: startIdx %i", *startIdx); - + int lastBit; //set first clock check - can go negative size_t i, bitnum = 0; //output counter uint8_t midBit = 0; @@ -1532,7 +1532,7 @@ int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, if (g_debugMode == 2) prnt("DEBUG: (askdemod_ext) Modulation Error at: %u", i); bits[bitnum++] = 7; errCnt++; - } + } } else { //in tolerance - looking for peak continue; } @@ -1566,22 +1566,22 @@ int askdemod(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, uin // peaks invert bit (high=1 low=0) each clock cycle = 1 bit determined by last peak int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startIdx) { if (signalprop.isnoise) return -1; - + size_t clkStartIdx = 0; *clk = DetectNRZClock(dest, *size, *clk, &clkStartIdx); if (*clk == 0) return -2; - + size_t i, gLen = 4096; - if (gLen > *size) + if (gLen > *size) gLen = *size-20; - - + + // just noise - no super good detection. good enough if (signalprop.isnoise) { if (g_debugMode == 2) prnt("DEBUG nrzRawDemod: just noise detected - quitting"); return -3; } - + int high, low; //getHiLo(dest, gLen, &high, &low, 75, 75); getHiLo(&high, &low, 75, 75); @@ -1594,7 +1594,7 @@ int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startId if (dest[i] <= low) bit = 0; dest[i] = bit; } - //now demod based on clock (rf/32 = 32 1's for one 1 bit, 32 0's for one 0 bit) + //now demod based on clock (rf/32 = 32 1's for one 1 bit, 32 0's for one 0 bit) size_t lastBit = 0; size_t numBits = 0; for(i=21; i < *size-20; i++) { @@ -1615,9 +1615,9 @@ int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startId //translate wave to 11111100000 (1 for each short wave [higher freq] 0 for each long wave [lower freq]) size_t fsk_wave_demod(uint8_t *dest, size_t size, uint8_t fchigh, uint8_t fclow, int *startIdx) { - + if ( size < 1024 ) return 0; // not enough samples - + if (fchigh == 0) fchigh = 10; if (fclow == 0) fclow = 8; @@ -1629,24 +1629,24 @@ size_t fsk_wave_demod(uint8_t *dest, size_t size, uint8_t fchigh, uint8_t fclow, size_t idx = 1; size_t numBits = 0; - //find start of modulating data in trace + //find start of modulating data in trace idx = findModStart(dest, size, fchigh); // Need to threshold first sample dest[idx] = (dest[idx] < signalprop.mean) ? 0 : 1; - + last_transition = idx; idx++; - + // Definition: cycles between consecutive lo-hi transitions // Lets define some expected lengths. FSK1 is easier since it has bigger differences between. - // FSK1 8/5 + // FSK1 8/5 // 50/8 = 6 | 40/8 = 5 | 64/8 = 8 // 50/5 = 10 | 40/5 = 8 | 64/5 = 12 // FSK2 10/8 // 50/10 = 5 | 40/10 = 4 | 64/10 = 6 // 50/8 = 6 | 40/8 = 5 | 64/8 = 8 - + // count cycles between consecutive lo-hi transitions, // in practice due to noise etc we may end up with anywhere // To allow fuzz would mean +-1 on expected cycle width. @@ -1661,14 +1661,14 @@ size_t fsk_wave_demod(uint8_t *dest, size_t size, uint8_t fchigh, uint8_t fclow, // It easy to see to the overgaping, but luckily we the group value also, like 1111000001111 // to separate between which bit to demodulate to. - // process: - // count width from 0-1 transition to 1-0. + // process: + // count width from 0-1 transition to 1-0. // determine the width is withing FUZZ_min and FUZZ_max tolerances - // width should be divided with exp_one. i:e 6+7+6+2=21, 21/5 = 4, - // the 1-0 to 0-1 width should be divided with exp_zero. Ie: 3+5+6+7 = 21/6 = 3 - + // width should be divided with exp_one. i:e 6+7+6+2=21, 21/5 = 4, + // the 1-0 to 0-1 width should be divided with exp_zero. Ie: 3+5+6+7 = 21/6 = 3 + for(; idx < size-20; idx++) { - + // threshold current value dest[idx] = (dest[idx] < signalprop.mean) ? 0 : 1; @@ -1685,14 +1685,14 @@ size_t fsk_wave_demod(uint8_t *dest, size_t size, uint8_t fchigh, uint8_t fclow, dest[numBits-1]=1; } dest[numBits++]=1; - - + + if (numBits > 0 && *startIdx == 0) *startIdx = idx - fclow; - + } else if (currSample > (fchigh+1) && numBits < 3) { //12 + and first two bit = unusable garbage //do nothing with beginning garbage and reset.. should be rare.. - numBits = 0; + numBits = 0; } else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's (or 4 then a 6 should be two 5's) dest[numBits++]=1; if (numBits > 0 && *startIdx == 0) { @@ -1719,21 +1719,21 @@ size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t clk, uint8_t invert, u size_t numBits = 0; uint32_t n = 1; uint8_t hclk = clk/2; - + for( i = 1; i < size; i++) { n++; if (dest[i] == lastval) continue; //skip until we hit a transition - + //find out how many bits (n) we collected (use 1/2 clk tolerance) - + if (dest[i-1] == 1) //if lastval was 1, we have a 1->0 crossing n = (n * fclow + hclk) / clk; - else - // 0->1 crossing - n = (n * fchigh + hclk) / clk; + else + // 0->1 crossing + n = (n * fchigh + hclk) / clk; - if (n == 0) + if (n == 0) n = 1; //first transition - save startidx @@ -1747,7 +1747,7 @@ size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t clk, uint8_t invert, u } } - //add to our destination the bits we collected + //add to our destination the bits we collected memset(dest+numBits, dest[i-1] ^ invert , n); numBits += n; @@ -1755,7 +1755,7 @@ size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t clk, uint8_t invert, u lastval = dest[i]; }//end for - + // if valid extra bits at the end were all the same frequency - add them in if (n > clk/fchigh) { if (dest[i-2] == 1) { @@ -1786,9 +1786,9 @@ size_t fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8 void psk1TOpsk2(uint8_t *bits, size_t size) { uint8_t lastbit = bits[0]; for (size_t i = 1; i < size; i++){ - //ignore errors + //ignore errors if (bits[i] == 7) continue; - + if (lastbit != bits[i]){ lastbit = bits[i]; bits[i] = 1; @@ -1811,11 +1811,11 @@ void psk2TOpsk1(uint8_t *bits, size_t size) { } } -//by marshmellow - demodulate PSK1 wave -//uses wave lengths (# Samples) +//by marshmellow - demodulate PSK1 wave +//uses wave lengths (# Samples) //TODO: Iceman - hard coded value 7, should be #define int pskRawDemod_ext(uint8_t *dest, size_t *size, int *clock, int *invert, int *startIdx) { - + // sanity check if (*size < 170) return -1; @@ -1830,7 +1830,7 @@ int pskRawDemod_ext(uint8_t *dest, size_t *size, int *clock, int *invert, int *s //if clock detect found firstfullwave... uint16_t tol = fc/2; if (firstFullWave == 0) { - //find start of modulating data in trace + //find start of modulating data in trace i = findModStart(dest, *size, fc); //find first phase shift firstFullWave = pskFindFirstPhaseShift(dest, *size, &curPhase, i, fc, &fullWaveLen); @@ -1855,7 +1855,7 @@ int pskRawDemod_ext(uint8_t *dest, size_t *size, int *clock, int *invert, int *s waveStart = 0; dest[numBits++] = curPhase; //set first read bit for (i = firstFullWave + fullWaveLen - 1; i < *size-3; i++){ - //top edge of wave = start of new wave + //top edge of wave = start of new wave if (dest[i]+fc < dest[i+1] && dest[i+1] >= dest[i+2]){ if (waveStart == 0) { waveStart = i+1; @@ -1864,7 +1864,7 @@ int pskRawDemod_ext(uint8_t *dest, size_t *size, int *clock, int *invert, int *s } else { //waveEnd waveEnd = i+1; waveLenCnt = waveEnd-waveStart; - if (waveLenCnt > fc){ + if (waveLenCnt > fc){ //this wave is a phase shift //prnt("DEBUG: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d",waveStart,waveLenCnt,lastClkBit+*clock-tol,i+1,fc); if (i+1 >= lastClkBit + *clock - tol){ //should be a clock bit @@ -1925,10 +1925,10 @@ int detectAWID(uint8_t *dest, size_t *size, int *waveStartIdx) { uint8_t preamble[] = {0,0,0,0,0,0,0,1}; if (!preambleSearch(dest, preamble, sizeof(preamble), size, &start_idx)) return -4; //preamble not found - + // wrong size? (between to preambles) if (*size != 96) return -5; - + return (int)start_idx; } @@ -1936,12 +1936,12 @@ int detectAWID(uint8_t *dest, size_t *size, int *waveStartIdx) { //takes 1s and 0s and searches for EM410x format - output EM ID int Em410xDecode(uint8_t *bits, size_t *size, size_t *start_idx, uint32_t *hi, uint64_t *lo) { // sanity check - if (bits[1] > 1) return -1; - if (*size < 64) return -2; + if (bits[1] > 1) return -1; + if (*size < 64) return -2; uint8_t fmtlen; *start_idx = 0; - + // preamble 0111111111 // include 0 in front to help get start pos uint8_t preamble[] = {0,1,1,1,1,1,1,1,1,1}; @@ -1952,22 +1952,22 @@ int Em410xDecode(uint8_t *bits, size_t *size, size_t *start_idx, uint32_t *hi, u fmtlen = (*size == 128) ? 22 : 10; //skip last 4bit parity row for simplicity - *size = removeParity(bits, *start_idx + sizeof(preamble), 5, 0, fmtlen * 5); - + *size = removeParity(bits, *start_idx + sizeof(preamble), 5, 0, fmtlen * 5); + switch (*size) { - case 40: { + case 40: { // std em410x format *hi = 0; *lo = ((uint64_t)(bytebits_to_byte(bits, 8)) << 32) | (bytebits_to_byte(bits + 8, 32)); break; - } - case 88: { + } + case 88: { // long em format - *hi = (bytebits_to_byte(bits, 24)); + *hi = (bytebits_to_byte(bits, 24)); *lo = ((uint64_t)(bytebits_to_byte(bits + 24, 32)) << 32) | (bytebits_to_byte(bits + 24 + 32, 32)); break; - } - default: return -6; + } + default: return -6; } return 1; } @@ -1977,7 +1977,7 @@ int Em410xDecode(uint8_t *bits, size_t *size, size_t *start_idx, uint32_t *hi, u int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx) { //make sure buffer has data if (*size < 96*50) return -1; - + if (signalprop.isnoise) return -2; // FSK demodulator fsk2a so invert and fc/10/8 @@ -1987,14 +1987,14 @@ int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32 if (*size < 96*2) return -3; // 00011101 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1 - size_t start_idx = 0; + size_t start_idx = 0; uint8_t preamble[] = {0,0,0,1,1,1,0,1}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &start_idx)) + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &start_idx)) return -4; //preamble not found // wrong size? (between to preambles) //if (*size != 96) return -5; - + size_t num_start = start_idx + sizeof(preamble); // final loop, go over previously decoded FSK data and manchester decode into usable tag ID for (size_t idx = num_start; (idx - num_start) < *size - sizeof(preamble); idx += 2) { @@ -2017,17 +2017,17 @@ int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32 // by iceman int detectIdteck(uint8_t *dest, size_t *size) { //make sure buffer has data - if (*size < 64*2) return -1; - + if (*size < 64*2) return -1; + if (signalprop.isnoise) return -2; - + size_t start_idx = 0; uint8_t preamble[] = {0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,1,0,1,1}; - + //preamble not found if (!preambleSearch(dest, preamble, sizeof(preamble), size, &start_idx)) - return -3; - + return -3; + // wrong demoded size if (*size != 64) return -4; return (int)start_idx; @@ -2036,15 +2036,15 @@ int detectIdteck(uint8_t *dest, size_t *size) { int detectIOProx(uint8_t *dest, size_t *size, int *waveStartIdx) { //make sure buffer has data if (*size < 66*64) return -1; - + if (signalprop.isnoise) return -2; - + // FSK demodulator RF/64, fsk2a so invert, and fc/10/8 *size = fskdemod(dest, *size, 64, 1, 10, 8, waveStartIdx); //io fsk2a - + //did we get enough demod data? if (*size < 64) return -3; - + //Index map //0 10 20 30 40 50 60 //| | | | | | | @@ -2061,12 +2061,12 @@ int detectIOProx(uint8_t *dest, size_t *size, int *waveStartIdx) { // wrong size? (between to preambles) if (*size != 64) return -5; - - if ( !dest[start_idx + 8] - && dest[start_idx + 17] == 1 - && dest[start_idx + 26] == 1 + + if ( !dest[start_idx + 8] + && dest[start_idx + 17] == 1 + && dest[start_idx + 26] == 1 && dest[start_idx + 35] == 1 - && dest[start_idx + 44] == 1 + && dest[start_idx + 44] == 1 && dest[start_idx + 53] == 1) { //confirmed proper separator bits found //return start position diff --git a/common/lfdemod.h b/common/lfdemod.h index a6542059e..222495a99 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -7,8 +7,8 @@ // Low frequency demod related commands // marshmellow // note that many of these demods are not the slickest code and they often rely -// on peaks and clock instead of converting to clean signal. -// +// on peaks and clock instead of converting to clean signal. +// //----------------------------------------------------------------------------- #ifndef LFDEMOD_H__ diff --git a/common/parity.h b/common/parity.h index fe1c2504f..9aaf936ed 100644 --- a/common/parity.h +++ b/common/parity.h @@ -6,7 +6,7 @@ // Parity functions //----------------------------------------------------------------------------- -// all functions defined in header file by purpose. Allows compiler optimizations. +// all functions defined in header file by purpose. Allows compiler optimizations. #ifndef __PARITY_H #define __PARITY_H @@ -31,7 +31,7 @@ static inline bool evenparity8(const uint8_t x) { } -static inline bool evenparity32(uint32_t x) +static inline bool evenparity32(uint32_t x) { #if !defined __GNUC__ x ^= x >> 16; @@ -43,7 +43,7 @@ static inline bool evenparity32(uint32_t x) } -static inline bool oddparity32(uint32_t x) +static inline bool oddparity32(uint32_t x) { #if !defined __GNUC__ x ^= x >> 16; diff --git a/common/prng.c b/common/prng.c index 170550edf..b1a608d7e 100644 --- a/common/prng.c +++ b/common/prng.c @@ -24,7 +24,7 @@ void burtle_init_mod(prng_ctx *x, uint32_t seed ) { } void burtle_init(prng_ctx *x, uint32_t seed ) { - uint32_t i; + uint32_t i; x->a = 0xf1ea5eed, x->b = x->c = x->d = seed; for (i=0; i < 20; ++i) { (void)burtle_get_mod(x); diff --git a/common/prng.h b/common/prng.h index 4aa890927..f7a875b6c 100644 --- a/common/prng.h +++ b/common/prng.h @@ -8,11 +8,11 @@ #define __PRNG_H #include #include -typedef struct prng_ctx { - uint32_t a; - uint32_t b; - uint32_t c; - uint32_t d; +typedef struct prng_ctx { + uint32_t a; + uint32_t b; + uint32_t c; + uint32_t d; } prng_ctx; //uint32_t burtle_get( prng_ctx *x ); diff --git a/common/protocols.c b/common/protocols.c index 96ecdab51..9649c51d9 100644 --- a/common/protocols.c +++ b/common/protocols.c @@ -30,17 +30,17 @@ uint8_t notset(uint8_t val, uint8_t mask){ void fuse_config(const picopass_hdr *hdr) { uint8_t fuses = hdr->conf.fuses; - if (isset(fuses,FUSE_FPERS)) + if (isset(fuses,FUSE_FPERS)) PrintAndLogDevice(SUCCESS, "\tMode: Personalization [Programmable]"); - else + else PrintAndLogDevice(NORMAL, "\tMode: Application [Locked]"); if (isset(fuses, FUSE_CODING1)) { PrintAndLogDevice(NORMAL, "\tCoding: RFU"); } else { - if( isset( fuses , FUSE_CODING0)) + if( isset( fuses , FUSE_CODING0)) PrintAndLogDevice(NORMAL, "\tCoding: ISO 14443-2 B/ISO 15693"); - else + else PrintAndLogDevice(NORMAL, "\tCoding: ISO 14443B only"); } // 1 1 @@ -54,7 +54,7 @@ void fuse_config(const picopass_hdr *hdr) { if( isset( fuses, FUSE_RA)) PrintAndLogDevice(NORMAL, "\tRA: Read access enabled"); - else + else PrintAndLogDevice(WARNING, "\tRA: Read access not enabled"); } @@ -63,7 +63,7 @@ void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t * uint8_t k16 = isset(mem_cfg, 0x80); //uint8_t k2 = isset(mem_cfg, 0x08); uint8_t book = isset(mem_cfg, 0x20); - + if(isset(chip_cfg, 0x10) && !k16 && !book) { *kb = 2; *app_areas = 2; @@ -100,10 +100,10 @@ void mem_app_config(const picopass_hdr *hdr) { uint8_t max_blk = 31; getMemConfig(mem, chip, &max_blk, &app_areas, &kb); - + if (applimit < 6) applimit = 26; if (kb == 2 && (applimit > 0x1f) ) applimit = 26; - + PrintAndLogDevice(NORMAL, " Mem: %u KBits/%u App Areas (%u * 8 bytes) [%02X]", kb, app_areas, max_blk, mem); PrintAndLogDevice(NORMAL, "\tAA1: blocks 06-%02X", applimit); PrintAndLogDevice(NORMAL, "\tAA2: blocks %02X-%02X", applimit+1, max_blk); diff --git a/common/protocols.h b/common/protocols.h index 73355c85d..ce56b3175 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -36,7 +36,7 @@ ISO14443B 05 = REQB 1D = ATTRIB 50 = HALT - + BA = PING (reader -> tag) AB = PONG (tag -> reader) SRIX4K (tag does not respond to 05) @@ -132,7 +132,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define ICLASS_CMD_READ4 0x06 #define ICLASS_CMD_READ_OR_IDENTIFY 0x0C -#define ICLASS_CMD_SELECT 0x81 +#define ICLASS_CMD_SELECT 0x81 #define ICLASS_CMD_PAGESEL 0x84 #define ICLASS_CMD_UPDATE 0x87 #define ICLASS_CMD_READCHECK_KC 0x18 @@ -309,7 +309,7 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. // ISO7816-4 For response APDU's #define ISO7816_OK 0x9000 // 6x xx = ERROR - + // MIFARE DESFire command set: #define MFDES_CREATE_APPLICATION 0xca #define MFDES_DELETE_APPLICATION 0xda @@ -417,7 +417,7 @@ void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t * #define T55XX_WRITE_TIMEOUT 1500 uint32_t GetT55xxClockBit(uint32_t clock); - + // em4x05 & em4x69 chip configuration register definitions #define EM4x05_GET_BITRATE(x) (((x & 0x3F)*2)+2) @@ -515,7 +515,7 @@ uint32_t GetT55xxClockBit(uint32_t clock); #define SYSTEMCODE_CYBERNE 0x0003 // Cyberne #define SYSTEMCODE_SUICA 0x0003 // Suica #define SYSTEMCODE_PASMO 0x0003 // Pasmo - + //FeliCa Service list Suica/pasmo (little endian) #define SERVICE_SUICA_INOUT 0x108f // SUICA/PASMO #define SERVICE_SUICA_HISTORY 0x090f // SUICA/PASMO @@ -569,5 +569,5 @@ typedef struct { } picopass_hdr; -#endif +#endif // PROTOCOLS_H diff --git a/common/radixsort.c b/common/radixsort.c index 981c19191..fa0643216 100644 --- a/common/radixsort.c +++ b/common/radixsort.c @@ -44,13 +44,13 @@ uint64_t * radixSort(uint64_t * array, uint32_t size) { counts.c3[x] = o3; counts.c2[x] = o2; counts.c1[x] = o1; - o8 = t8; - o7 = t7; - o6 = t6; - o5 = t5; - o4 = t4; - o3 = t3; - o2 = t2; + o8 = t8; + o7 = t7; + o6 = t6; + o5 = t5; + o4 = t4; + o3 = t3; + o2 = t2; o1 = t1; } // radix diff --git a/common/random.c b/common/random.c index 5658683de..96cdbb628 100644 --- a/common/random.c +++ b/common/random.c @@ -6,20 +6,20 @@ static uint32_t g_nextrandom; * * We don't have an implementation of the "rand" function. Instead we use a * method of seeding with the time it took to call "autoseed" from first run. - * + * * https://github.com/Proxmark/proxmark3/pull/209/commits/f9c1dcd9f6e68a8c07cffed697a9c4c8caed6015 * * Iceman, rand needs to be fast. * https://software.intel.com/en-us/articles/fast-random-number-generator-on-the-intel-pentiumr-4-processor/ */ - + inline void fast_prand(){ fast_prandEx(GetTickCount()); } inline void fast_prandEx(uint32_t seed) { g_nextrandom = seed; } - + uint32_t prand() { // g_nextrandom *= 6364136223846793005; // g_nextrandom += 1; diff --git a/common/random.h b/common/random.h index 800ad8103..315794f8d 100644 --- a/common/random.h +++ b/common/random.h @@ -6,7 +6,7 @@ // the license. //----------------------------------------------------------------------------- // pseudo rng generator. To be used when PM3 simulates Mifare tag. -// i.e. 'hf mf sim' +// i.e. 'hf mf sim' // 'hf 14a sim' //----------------------------------------------------------------------------- diff --git a/common/tea.c b/common/tea.c index 616b4043b..b3e1a39c1 100644 --- a/common/tea.c +++ b/common/tea.c @@ -16,17 +16,17 @@ void tea_encrypt(uint8_t *v, uint8_t *key) { uint32_t a=0,b=0,c=0,d=0,y=0,z=0; uint32_t sum = 0; uint8_t n = ROUNDS; - + //key a = bytes_to_num(key, 4); b = bytes_to_num(key+4, 4); c = bytes_to_num(key+8, 4); d = bytes_to_num(key+12, 4); - + //input y = bytes_to_num(v, 4); z = bytes_to_num(v+4, 4); - + while ( n-- > 0 ) { sum += DELTA; y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); @@ -48,7 +48,7 @@ void tea_decrypt(uint8_t *v, uint8_t *key) { b = bytes_to_num(key+4, 4); c = bytes_to_num(key+8, 4); d = bytes_to_num(key+12, 4); - + //input y = bytes_to_num(v, 4); z = bytes_to_num(v+4, 4); diff --git a/common/usart.c b/common/usart.c index 32ccb5ca1..c62e3c8f6 100644 --- a/common/usart.c +++ b/common/usart.c @@ -1,7 +1,7 @@ //----------------------------------------------------------------------------- // Iceman, July 2018 // edits by - Anticat, August 2018 -// +// // This code is licensed to you under the terms of the GNU GPL, version 2 or, // at your option, any later version. See the LICENSE.txt file for the text of // the license. @@ -24,7 +24,7 @@ void usart_close(void) { // Reset the baud rate divisor register pUS1->US_BRGR = 0; - + // Reset the Timeguard Register pUS1->US_TTGR = 0; @@ -96,20 +96,20 @@ void usart_init(void) { // disable & reset receiver / transmitter for configuration pUS1->US_CR = (AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS); - + //enable the USART1 Peripheral clock AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US1); // disable PIO control of receive / transmit pins - pPIO->PIO_PDR |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); - + pPIO->PIO_PDR |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); + // enable peripheral mode A on receive / transmit pins pPIO->PIO_ASR |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); pPIO->PIO_BSR = 0; // enable pull-up on receive / transmit pins (see 31.5.1 I/O Lines) pPIO->PIO_PPUER |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); - + // set mode pUS1->US_MR = AT91C_US_USMODE_NORMAL | // normal mode AT91C_US_CLKS_CLOCK | // MCK (48MHz) @@ -126,18 +126,18 @@ void usart_init(void) { // For a nice detailed sample, interrupt driven but still relevant. // See https://www.sparkfun.com/datasheets/DevTools/SAM7/at91sam7%20serial%20communications.pdf - // set baudrate to 115200 + // set baudrate to 115200 // 115200 * 16 == 1843200 // //pUS1->US_BRGR = (48UL*1000*1000) / (9600*16); pUS1->US_BRGR = 48054841 / (9600 << 4); - + // Write the Timeguard Register pUS1->US_TTGR = 0; pUS1->US_RTOR = 0; pUS1->US_FIDI = 0; pUS1->US_IF = 0; - + // re-enable receiver / transmitter pUS1->US_CR = (AT91C_US_RXEN | AT91C_US_TXEN); } \ No newline at end of file diff --git a/common/usb_cdc.c b/common/usb_cdc.c index a0005017e..b1acff692 100644 --- a/common/usb_cdc.c +++ b/common/usb_cdc.c @@ -36,14 +36,14 @@ /* AT91SAM7S256 USB Device Port • Embedded 328-byte dual-port RAM for endpoints -• Four endpoints +• Four endpoints – Endpoint 0: 8 bytes – Endpoint 1 and 2: 64 bytes ping-pong – Endpoint 3: 64 bytes – Ping-pong Mode (two memory banks) for bulk endpoints */ -// +// #define AT91C_EP_CONTROL 0 #define AT91C_EP_OUT 1 // cfg bulk out #define AT91C_EP_IN 2 // cfg bulk in @@ -79,7 +79,7 @@ AT91SAM7S256 USB Device Port #define _ISO 0x01 //Isochronous Transfer #define _BULK 0x02 //Bulk Transfer #define _INTERRUPT 0x03 //Interrupt Transfer - + // (bit7 | 0 = OUT, 1 = IN) #define _EP_IN 0x80 #define _EP_OUT 0x00 @@ -92,7 +92,7 @@ AT91SAM7S256 USB Device Port /* WCID specific Request Code */ -#define MS_OS_DESCRIPTOR_INDEX 0xEE +#define MS_OS_DESCRIPTOR_INDEX 0xEE #define MS_VENDOR_CODE 0x1C #define MS_EXTENDED_COMPAT_ID 0x04 #define MS_EXTENDED_PROPERTIES 0x05 @@ -143,10 +143,10 @@ static const char devDescriptor[] = { 0xc4,0x9a, // Vendor ID [0x9ac4 = J. Westhues] 0x8f,0x4b, // Product ID [0x4b8f = Proxmark-3 RFID Instrument] 0x00,0x01, // BCD Device release number (1.00) - 1, // index Manufacturer + 1, // index Manufacturer 2, // index Product 3, // index SerialNumber - 1 // Number of Configs + 1 // Number of Configs }; static const char cfgDescriptor[] = { @@ -154,8 +154,8 @@ static const char cfgDescriptor[] = { /* Configuration 1 descriptor */ // ----------------------------- 9, // Length - USB_DESCRIPTOR_CONFIGURATION, // Descriptor Type - (9+9+5+5+4+5+7+9+7+7), 0, // Total Length 2 EP + Control + USB_DESCRIPTOR_CONFIGURATION, // Descriptor Type + (9+9+5+5+4+5+7+9+7+7), 0, // Total Length 2 EP + Control 2, // Number of Interfaces 1, // Index value of this Configuration (used in SetConfiguration from Host) 0, // Configuration string index @@ -174,7 +174,7 @@ static const char cfgDescriptor[] = { 1, // Function Protocol: v.25term 0, // iInterface */ - + /* Interface 0 Descriptor */ /* CDC Communication Class Interface Descriptor Requirement for Notification*/ // ----------------------------------------------------------- @@ -192,7 +192,7 @@ static const char cfgDescriptor[] = { 5, // Function Length 0x24, // Descriptor type: CS_INTERFACE 0, // Descriptor subtype: Header Functional Descriptor - 0x10,0x01, // bcd CDC:1.1 + 0x10,0x01, // bcd CDC:1.1 /* ACM Functional Descriptor */ 4, // Function Length @@ -206,23 +206,23 @@ static const char cfgDescriptor[] = { 6, // Descriptor Subtype: Union Functional Descriptor 0, // MasterInterface: Communication Class Interface 1, // SlaveInterface0: Data Class Interface - + /* Call Management Functional Descriptor */ 5, // Function Length 0x24, // Descriptor Type: CS_INTERFACE - 1, // Descriptor Subtype: Call Management Functional Descriptor + 1, // Descriptor Subtype: Call Management Functional Descriptor 0, // Capabilities: Device sends/receives call management information only over the Communication Class interface. Device does not handle call management itself 1, // Data Interface: Data Class Interface - + /* Protocol Functional Descriptor */ /* 6, 0x24, // Descriptor Type: CS_INTERFACE 0x0B, // Descriptor Subtype: Protocol Unit functional Descriptor 0xDD, // constant uniq ID of unit - 0xFE, // protocol + 0xFE, // protocol */ - + /* CDC Notification Endpoint descriptor */ // --------------------------------------- 7, // Length @@ -232,7 +232,7 @@ static const char cfgDescriptor[] = { AT91C_EP_CONTROL_SIZE, 0x00, // MaxPacket Size: EP0 - 8 0xFF, // Interval polling - + /* Interface 1 Descriptor */ /* CDC Data Class Interface 1 Descriptor Requirement */ 9, // Length @@ -283,10 +283,10 @@ static const char bosDescriptor[] = { static const char CompatIDFeatureDescriptor[] = { 0x28, 0x00, 0x00, 0x00, // Descriptor Length 40bytes (0x28) 0x00, 0x01, // Version ('1.0') - MS_EXTENDED_COMPAT_ID, 0x00, // Compatibility ID Descriptor Index 0x0004 + MS_EXTENDED_COMPAT_ID, 0x00, // Compatibility ID Descriptor Index 0x0004 0x01, // Number of sections. 0x1 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved (7bytes) - //-----function section 1------ + //-----function section 1------ 0x00, // Interface Number #0 0x01, // reserved (0x1) 0x57, 0x49, 0x4E, 0x55, 0x53, 0x42, 0x00, 0x00, // Compatible ID ('WINUSB\0\0') (8bytes) @@ -306,7 +306,7 @@ static const char OSprop[] = { MS_EXTENDED_PROPERTIES, 0, // u16 wCount -- three section 3, 0, - + //-----property section 1------ // u32 size ( 14+40+78 == 132) 132, 0, 0, 0, @@ -321,7 +321,7 @@ static const char OSprop[] = { // data {4D36E978-E325-11CE-BFC1-08002BE10318} '{',0,'4',0,'d',0,'3',0,'6',0,'e',0,'9',0,'7',0,'8',0,'-',0,'e',0,'3',0,'2',0,'5',0, '-',0,'1',0,'1',0,'c',0,'e',0,'-',0,'b',0,'f',0,'c',0,'1',0,'-',0,'0',0,'8',0,'0',0, - '0',0,'2',0,'b',0,'e',0,'1',0,'0',0,'3',0,'1',0,'8',0,'}',0,0,0, + '0',0,'2',0,'b',0,'e',0,'1',0,'0',0,'3',0,'1',0,'8',0,'}',0,0,0, //-----property section 2------ // u32 size ( 14+12+38 == 64) @@ -343,7 +343,7 @@ static const char OSprop[] = { // u32 type 2, 0, 0, 0, //Unicode string with environment variables // u16 namelen (12) - 12, 0, + 12, 0, // name Icons 'I',0,'c',0,'o',0,'n',0,'s',0,0,0, // u32 datalen ( 38*2 == 76) @@ -393,12 +393,12 @@ static const char StrMS_OSDescriptor[] = { const char* getStringDescriptor(uint8_t idx) { switch(idx) { - case 0: return StrLanguageCodes; + case 0: return StrLanguageCodes; case 1: return StrManufacturer; case 2: return StrProduct; case 3: return StrSerialNumber; case MS_OS_DESCRIPTOR_INDEX: return StrMS_OSDescriptor; - default: + default: return(NULL); } } @@ -446,7 +446,7 @@ static void SpinDelay(int ms) { // Borrow a PWM unit for my real-time clock AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0); - + // 48 MHz / 1024 gives 46.875 kHz AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; @@ -489,7 +489,7 @@ void usb_enable() { // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_UDP; AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP); - + AT91C_BASE_UDP->UDP_FADDR = 0; AT91C_BASE_UDP->UDP_GLBSTATE = 0; @@ -507,7 +507,7 @@ void usb_enable() { SpinDelay(100); // Wait for a short while //for (volatile size_t i=0; i<0x100000; i++) {}; - + // Reconnect USB reconnect AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU; AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; @@ -533,23 +533,23 @@ int GetUSBconfigured(void){ } bool usb_check() { - + /* - // reconnected ONCE and + // reconnected ONCE and if ( !USB_ATTACHED() ){ usb_reconnect = 1; return false; } - - // only one time after USB been disengaged and re-engaged + + // only one time after USB been disengaged and re-engaged if ( USB_ATTACHED() && usb_reconnect == 1 ) { - - if ( usb_configured == 0) { + + if ( usb_configured == 0) { usb_disable(); - usb_enable(); + usb_enable(); AT91F_CDC_Enumerate(); - + usb_configured = 1; return false; } @@ -573,7 +573,7 @@ bool usb_check() { else if (isr & AT91C_UDP_EPINT0) { pUdp->UDP_ICR = AT91C_UDP_EPINT0; AT91F_CDC_Enumerate(); - } + } /* else if (isr & AT91C_UDP_EPINT3 ) { pUdp->UDP_ICR = AT91C_UDP_EPINT3; @@ -608,20 +608,20 @@ bool usb_poll_validate_length() { //* \brief Read available data from Endpoint 1 OUT (host to device) //*---------------------------------------------------------------------------- uint32_t usb_read(byte_t* data, size_t len) { - + if ( len == 0 ) return 0; - + uint8_t bank = btReceiveBank; uint32_t packetSize, nbBytesRcv = 0; uint32_t time_out = 0; - + while (len) { if (!usb_check()) break; if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) { - + packetSize = (pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16; - packetSize = MIN( packetSize, len); + packetSize = MIN( packetSize, len); len -= packetSize; while (packetSize--) data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT]; @@ -632,7 +632,7 @@ uint32_t usb_read(byte_t* data, size_t len) { if (bank == AT91C_UDP_RX_DATA_BK0) bank = AT91C_UDP_RX_DATA_BK1; else - bank = AT91C_UDP_RX_DATA_BK0; + bank = AT91C_UDP_RX_DATA_BK0; } if (time_out++ == 0x1fff) break; } @@ -652,20 +652,20 @@ uint32_t usb_write(const byte_t* data, const size_t len) { // can we write? if ( (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) != 0 ) return 0; - + size_t length = len; uint32_t cpt = 0; - - + + // send first chunk cpt = MIN(length, AT91C_EP_IN_SIZE); length -= cpt; while (cpt--) { pUdp->UDP_FDR[AT91C_EP_IN] = *data++; } - + UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); - + while (length) { // Send next chunk cpt = MIN(length, AT91C_EP_IN_SIZE); @@ -673,19 +673,19 @@ uint32_t usb_write(const byte_t* data, const size_t len) { while (cpt--) { pUdp->UDP_FDR[AT91C_EP_IN] = *data++; } - + // Wait for previous chunk to be sent // (iceman) when is the bankswapping done? while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { if (!usb_check()) return length; } - + UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP); UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); - + } - + // Wait for the end of transfer while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { if (!usb_check()) return length; @@ -704,7 +704,7 @@ uint32_t usb_write(const byte_t* data, const size_t len) { void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) { uint32_t cpt = 0; AT91_REG csr; - + do { cpt = MIN(length, AT91C_EP_CONTROL_SIZE); length -= cpt; @@ -723,7 +723,7 @@ void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) { csr = pUdp->UDP_CSR[AT91C_EP_CONTROL]; // Data IN stage has been stopped by a status OUT if ( csr & AT91C_UDP_RX_DATA_BK0) { - + UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0) return; } @@ -736,14 +736,14 @@ void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) { while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP); } } - + //*---------------------------------------------------------------------------- //* \fn AT91F_USB_SendZlp //* \brief Send zero length packet through the control endpoint //*---------------------------------------------------------------------------- void AT91F_USB_SendZlp(AT91PS_UDP pUdp) { - UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY); + UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY); while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) ); UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP); while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP); @@ -763,7 +763,7 @@ void AT91F_USB_SendStall(AT91PS_UDP pUdp) { //*---------------------------------------------------------------------------- //* \fn AT91F_CDC_Enumerate //* \brief This function is a callback invoked when a SETUP packet is received -//* problem: +//* problem: //* 1. this is for USB endpoint0. the control endpoint. //* 2. mixed with CDC ACM endpoint3 , interrupt, control endpoint //*---------------------------------------------------------------------------- @@ -796,22 +796,22 @@ void AT91F_CDC_Enumerate() { if ( wIndex == MS_EXTENDED_COMPAT_ID ) { // 4 //AT91F_USB_SendData(pUdp, CompatIDFeatureDescriptor, MIN(sizeof(CompatIDFeatureDescriptor), wLength)); //return; - } + } } if ( bmRequestType == MS_WCID_GET_FEATURE_DESCRIPTOR ) { //C1 // if ( wIndex == MS_EXTENDED_PROPERTIES ) { // 5 - winusb bug with wIndex == interface index, so I just send it always) //AT91F_USB_SendData(pUdp, OSprop, MIN(sizeof(OSprop), wLength)); //return; - // } + // } } } */ - + // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1 switch ((bRequest << 8) | bmRequestType) { case STD_GET_DESCRIPTOR: { - + if ( wValue == 0x100 ) // Return Device Descriptor AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength)); else if ( wValue == 0x200 ) // Return Configuration Descriptor @@ -837,25 +837,25 @@ void AT91F_CDC_Enumerate() { pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0; break; case STD_SET_CONFIGURATION: - - /* - * Set or clear the device "configured" state. - * The LSB of wValue is the "Configuration Number". If this value is non-zero, - * it should be the same number as defined in the Configuration Descriptor; - * otherwise an error must have occurred. - * This device has only one configuration and its Config Number is CONF_NB (= 1). - */ + + /* + * Set or clear the device "configured" state. + * The LSB of wValue is the "Configuration Number". If this value is non-zero, + * it should be the same number as defined in the Configuration Descriptor; + * otherwise an error must have occurred. + * This device has only one configuration and its Config Number is CONF_NB (= 1). + */ AT91F_USB_SendZlp(pUdp); btConfiguration = wValue; pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN; - + // make sure we are not stalled /* UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT , AT91C_UDP_FORCESTALL); UDP_CLEAR_EP_FLAGS(AT91C_EP_IN , AT91C_UDP_FORCESTALL); UDP_CLEAR_EP_FLAGS(AT91C_EP_NOTIFY, AT91C_UDP_FORCESTALL); */ - + // enable endpoints pUdp->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0; pUdp->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0; @@ -924,8 +924,8 @@ void AT91F_CDC_Enumerate() { // handle CDC class requests case SET_LINE_CODING: { /* - uint8_t i; - for ( i = 0 ; i < 7 ; i++ ) { + uint8_t i; + for ( i = 0 ; i < 7 ; i++ ) { ((uint8_t*)&line)[i] = pUdp->UDP_FDR[AT91C_EP_CONTROL]; } */ // ignore SET_LINE_CODING... diff --git a/common/usb_cdc.h b/common/usb_cdc.h index fcac556fd..aad046cc1 100644 --- a/common/usb_cdc.h +++ b/common/usb_cdc.h @@ -37,7 +37,7 @@ #include #include "at91sam7s512.h" -#include "config_gpio.h" +#include "config_gpio.h" #include "proxmark3.h" // USB_CONNECT() #include "common.h" diff --git a/common/wiegand.c b/common/wiegand.c index c9d5fbed1..730cb0206 100644 --- a/common/wiegand.c +++ b/common/wiegand.c @@ -17,7 +17,7 @@ */ uint8_t getParity( uint8_t *bits, uint8_t len, uint8_t type ) { uint8_t x = 0; - for(; len > 0; --len) + for(; len > 0; --len) x += bits[len - 1]; return (x & 1 ) ^ type; @@ -35,7 +35,7 @@ uint8_t checkParity(uint32_t bits, uint8_t len, uint8_t type); // by marshmellow // takes a array of binary values, start position, length of bits per parity (includes parity bit), -// Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run) +// Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run) size_t removeParity(uint8_t *bitstream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen) { uint32_t parityWd = 0; size_t j = 0, bitcount = 0; @@ -69,10 +69,10 @@ size_t removeParity(uint8_t *bitstream, size_t startIdx, uint8_t pLen, uint8_t p * @brief addParity * @param bits pointer to the source bitstream of binary values * @param dest pointer to the destination where parities together with bits are added. -* @param sourceLen number of +* @param sourceLen number of * @param pLen length bits to be checked * @param pType EVEN|ODD|2 (always 1's)|3 (always 0's) -* @return +* @return */ size_t addParity(uint8_t *bits, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType) { @@ -83,12 +83,12 @@ size_t addParity(uint8_t *bits, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, parityWd = (parityWd << 1) | bits[word+bit]; dest[j++] = (bits[word+bit]); } - + // if parity fails then return 0 switch (pType) { case 3: dest[j++] = 0; break; // marker bit which should be a 0 case 2: dest[j++] = 1; break; // marker bit which should be a 1 - default: + default: dest[j++] = parityTest(parityWd, pLen-1, pType) ^ 1; break; } @@ -115,34 +115,34 @@ void wiegand_add_parity(uint8_t *source, uint8_t *dest, uint8_t len) { // half length, Even and Odd is calculated to the middle. uint8_t len_h2 = length >> 1; - + // add EVEN parity at the beginning *(dest) = GetParity(source, EVEN, len_h2); - + dest += length + 1; - + // add ODD parity at the very end *(dest) = GetParity(source + len_h2, ODD, len_h2); } //uint32_t bytebits_to_byte(uint8_t* src, size_t numbits); #define MAX_BITS_TXX55 6*4*8 -#define MAX_BYTES_TXX55 6*4 +#define MAX_BYTES_TXX55 6*4 /* * @brief num_to_wiegand_bytes * @param oem Sometimes call FF Fixfield, SiteCode. Used in a few formats -* @param fc Facility code +* @param fc Facility code * @param cn Card number * @param dest pointer to the destination where wiegand bytes will be stored -* @param formatlen +* @param formatlen */ void num_to_wiegand_bytes(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, uint8_t formatlen){ uint8_t data[MAX_BITS_TXX55] = {0}; memset(data, 0, sizeof(data)); - + num_to_wiegand_bits(oem, fc, cn, data, formatlen); - + // loop // (formatlen / 32 ) + 1 // (formatlen >> 5) + 1 @@ -150,15 +150,15 @@ void num_to_wiegand_bytes(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, uint32_t value = bytebits_to_byte( data + (i * 32), 32); num_to_bytes(value, 32, dest + (i*4) ); } - + } /* * @brief num_to_wiegand_bits * @param oem Sometimes call FF Fixfield, SiteCode. Used in a few formats -* @param fc Facility code +* @param fc Facility code * @param cn Card number * @param dest pointer to the destination where wiegand bits will be stored -* @param formatlen +* @param formatlen */ void num_to_wiegand_bits(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, uint8_t formatlen){ @@ -166,8 +166,8 @@ void num_to_wiegand_bits(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, memset(bits, 0, sizeof(bits)); uint8_t *temp = bits; uint64_t value = 0; - - switch ( formatlen ){ + + switch ( formatlen ){ case 26 : // 26bit HID H10301 fc &= 0xFF; // 8bits cn &= 0xFFFF; // 16bits @@ -175,26 +175,26 @@ void num_to_wiegand_bits(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, num_to_bytebits(value, 24, temp); wiegand_add_parity(temp, dest, 24); break; - case 261: // 26bit Indala + case 261: // 26bit Indala fc &= 0xFFF; // 12bits cn &= 0xFFF; // 12bits value = fc << 12 | cn; num_to_bytebits(value, 24, temp); - wiegand_add_parity(temp, dest, 24); + wiegand_add_parity(temp, dest, 24); break; case 34 : // 34bits HID fc &= 0xFFFF; // 16bits cn &= 0xFFFF; // 16bits value = fc << 16 | cn; num_to_bytebits(value, 32, temp); - wiegand_add_parity(temp, dest, 32); + wiegand_add_parity(temp, dest, 32); break; case 35 : // 35bits HID fc &= 0xFFF; // 12bits cn &= 0xFFFFFF; // 20bits value = fc << 20 | cn; num_to_bytebits(value, 32, temp); - wiegand_add_parity(temp, dest, 32); + wiegand_add_parity(temp, dest, 32); break; case 37 : // H10304 fc &= 0xFFFF; // 16bits diff --git a/include/common.h b/include/common.h index d3da792aa..8c73100ff 100644 --- a/include/common.h +++ b/include/common.h @@ -24,7 +24,7 @@ typedef unsigned char byte_t; // debug // 0 - no debug messages 1 - error messages 2 - all messages 4 - extended debug mode -#define MF_DBG_NONE 0 +#define MF_DBG_NONE 0 #define MF_DBG_ERROR 1 #define MF_DBG_ALL 2 #define MF_DBG_EXTENDED 4 @@ -51,7 +51,7 @@ extern uint32_t FLASHMEM_SPIBAUDRATE; // RDV40 Section // 256kb divided into 4k sectors. -// +// // last 4k sector = signature // second last 4k sector = settings // third last 4k sector = default MF keys dictionary @@ -94,11 +94,11 @@ extern uint32_t FLASHMEM_SPIBAUDRATE; #ifndef DEFAULT_T55XX_KEYS_OFFSET # define DEFAULT_T55XX_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x3000) #endif - + #ifndef DEFAULT_MF_KEYS_OFFSET # define DEFAULT_MF_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x4000) #endif - + #ifndef DEFAULT_ICLASS_KEYS_OFFSET # define DEFAULT_ICLASS_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x5000) #endif @@ -114,5 +114,5 @@ typedef struct { #ifdef __cplusplus } -#endif +#endif #endif \ No newline at end of file diff --git a/include/hitag2.h b/include/hitag2.h index a2d592410..2eeb48f6f 100644 --- a/include/hitag2.h +++ b/include/hitag2.h @@ -7,7 +7,7 @@ //----------------------------------------------------------------------------- // Hitag2 type prototyping //----------------------------------------------------------------------------- -// HitagS added +// HitagS added //----------------------------------------------------------------------------- #ifndef _HITAG2_H_ diff --git a/include/hitagS.h b/include/hitagS.h index 11b4fccb3..d74463f20 100644 --- a/include/hitagS.h +++ b/include/hitagS.h @@ -34,7 +34,7 @@ typedef enum TAG_STATE { HT_WRITING_PAGE_DATA, HT_WRITING_BLOCK_DATA} TSATE; -//number of start-of-frame bits +//number of start-of-frame bits typedef enum SOF_TYPE { HT_STANDARD=0, HT_ADVANCED, diff --git a/include/legic.h b/include/legic.h index 246af0e8b..d5ba8f166 100644 --- a/include/legic.h +++ b/include/legic.h @@ -21,7 +21,7 @@ typedef struct { uint32_t tagtype; uint8_t cmdsize; uint8_t addrsize; - uint16_t cardsize; + uint16_t cardsize; } legic_card_select_t; #endif // _LEGIC_H_ diff --git a/include/mifare.h b/include/mifare.h index 90077f60d..eec72c26f 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -91,7 +91,7 @@ typedef struct { uint32_t nonce; uint32_t ar; uint32_t nr; - uint32_t at; + uint32_t at; uint32_t nonce2; uint32_t ar2; uint32_t nr2; @@ -105,7 +105,7 @@ typedef struct { } nonces_t; //----------------------------------------------------------------------------- -// ISO 7618 Smart Card +// ISO 7618 Smart Card //----------------------------------------------------------------------------- typedef struct { uint8_t atr_len; @@ -127,7 +127,7 @@ typedef enum SMARTCARD_COMMAND { // mc = manufactureCode // mc1 mc2 u1 u2 u3 u4 u5 u6 // PMm = Product manufacturer -// icCode = +// icCode = // ic1 = ROM // ic2 = IC // maximum response time = @@ -136,7 +136,7 @@ typedef enum SMARTCARD_COMMAND { // B5(authenticate) // B6(read) // B7(write) -// B8() +// B8() // ServiceCode 2bytes (access-rights) // FileSystem = 1 Block = 16 bytes @@ -147,7 +147,7 @@ typedef struct { uint8_t PMm[8]; uint8_t iccode[2]; uint8_t mrt[6]; - uint8_t servicecode[2]; + uint8_t servicecode[2]; } __attribute__((__packed__)) felica_card_select_t; typedef enum FELICA_COMMAND { diff --git a/include/proxmark3.h b/include/proxmark3.h index 4532baf09..4b16f4eed 100644 --- a/include/proxmark3.h +++ b/include/proxmark3.h @@ -86,9 +86,9 @@ #define LED_D_OFF() LOW(GPIO_LED_D) #define LED_D_INV() INVBIT(GPIO_LED_D) -// SPI -#define SCK_LOW LOW(GPIO_SPCK) -#define SCK_HIGH HIGH(GPIO_SPCK) +// SPI +#define SCK_LOW LOW(GPIO_SPCK) +#define SCK_HIGH HIGH(GPIO_SPCK) #define MOSI_HIGH HIGH(GPIO_MOSI) #define MOSI_LOW LOW(GPIO_MOSI) #define MISO_VALUE (AT91C_BASE_PIOA->PIO_PDSR & GPIO_MISO) @@ -106,7 +106,7 @@ #define BUTTON_PRESS() !((AT91C_BASE_PIOA->PIO_PDSR & GPIO_BUTTON) == GPIO_BUTTON) //NVDD goes LOW when USB is attached. -#define USB_ATTACHED() !((AT91C_BASE_PIOA->PIO_PDSR & GPIO_NVDD_ON) == GPIO_NVDD_ON) +#define USB_ATTACHED() !((AT91C_BASE_PIOA->PIO_PDSR & GPIO_NVDD_ON) == GPIO_NVDD_ON) #define VERSION_INFORMATION_MAGIC 0x56334d50 struct version_information { diff --git a/include/usb_cmd.h b/include/usb_cmd.h index a54b27e0f..0680b443a 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -48,7 +48,7 @@ typedef struct{ uint16_t write_gap; uint16_t write_0; uint16_t write_1; - uint16_t read_gap; + uint16_t read_gap; } t55xx_config; // For the bootloader @@ -161,7 +161,7 @@ typedef struct{ #define CMD_SIMULATE_HITAG 0x0371 #define CMD_READER_HITAG 0x0372 -// For HitagS +// For HitagS #define CMD_TEST_HITAGS_TRACES 0x0367 #define CMD_SIMULATE_HITAG_S 0x0368 #define CMD_READ_HITAG_S 0x0373 @@ -202,7 +202,7 @@ typedef struct{ #define CMD_ICLASS_AUTHENTICATION 0x0399 #define CMD_ICLASS_CHECK_KEYS 0x039A -// For ISO1092 / FeliCa +// For ISO1092 / FeliCa #define CMD_FELICA_SIMULATE_TAG 0x03A0 #define CMD_FELICA_SNOOP 0x03A1 #define CMD_FELICA_COMMAND 0x03A2 @@ -253,7 +253,7 @@ typedef struct{ #define CMD_MIFARE_SNIFFER 0x0630 //ultralightC #define CMD_MIFAREUC_AUTH 0x0724 -//0x0725 and 0x0726 no longer used +//0x0725 and 0x0726 no longer used #define CMD_MIFAREUC_SETPWD 0x0727 // mifare desfire diff --git a/liblua/lgc.c b/liblua/lgc.c index 535e988ae..af001682c 100644 --- a/liblua/lgc.c +++ b/liblua/lgc.c @@ -1053,7 +1053,7 @@ static lu_mem singlestep (lua_State *L) { g->gcstate = GCSatomic; /* finish mark phase */ g->GCestimate = g->GCmemtrav; /* save what was counted */; work = atomic(L); /* add what was traversed by 'atomic' */ - g->GCestimate += work; /* estimate of total memory traversed */ + g->GCestimate += work; /* estimate of total memory traversed */ sw = entersweep(L); return work + sw * GCSWEEPCOST; } diff --git a/tools/mfkey/crapto1.c b/tools/mfkey/crapto1.c index 203efeb4f..9b2b58085 100755 --- a/tools/mfkey/crapto1.c +++ b/tools/mfkey/crapto1.c @@ -222,7 +222,7 @@ struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in) // allocate memory for out of place bucket_sort bucket_array_t bucket; - + for (uint32_t i = 0; i < 2; i++) { for (uint32_t j = 0; j <= 0xff; j++) { bucket[i][j].head = malloc(sizeof(uint32_t)<<14); @@ -424,7 +424,7 @@ uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) ret |= lfsr_rollback_bit(s, BEBIT(in, 18), fb) << (18 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 17), fb) << (17 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 16), fb) << (16 ^ 24); - + ret |= lfsr_rollback_bit(s, BEBIT(in, 15), fb) << (15 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 14), fb) << (14 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 13), fb) << (13 ^ 24); @@ -433,7 +433,7 @@ uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) ret |= lfsr_rollback_bit(s, BEBIT(in, 10), fb) << (10 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 9), fb) << (9 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 8), fb) << (8 ^ 24); - + ret |= lfsr_rollback_bit(s, BEBIT(in, 7), fb) << (7 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 6), fb) << (6 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 5), fb) << (5 ^ 24); @@ -483,7 +483,7 @@ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) { uint32_t *candidates = malloc(4 << 10); if(!candidates) return 0; - + uint32_t c, entry; int size = 0, i, good; @@ -531,7 +531,7 @@ static struct Crypto1State* check_pfx_parity(uint32_t prefix, uint32_t rresp, ui } return sl + good; -} +} /** lfsr_common_prefix * Implentation of the common prefix attack. diff --git a/tools/mfkey/crapto1.h b/tools/mfkey/crapto1.h index 65c570216..875ffdaab 100755 --- a/tools/mfkey/crapto1.h +++ b/tools/mfkey/crapto1.h @@ -44,7 +44,7 @@ uint32_t lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb); int nonce_distance(uint32_t from, uint32_t to); #define SWAPENDIAN(x)\ (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) - + #define FOREACH_VALID_NONCE(N, FILTER, FSIZE)\ uint32_t __n = 0,__M = 0, N = 0;\ int __i;\ @@ -54,7 +54,7 @@ int nonce_distance(uint32_t from, uint32_t to); break;\ else if(__i)\ __M = prng_successor(__M, (__i == 7) ? 48 : 8);\ - else + else #define LF_POLY_ODD (0x29CE5C) #define LF_POLY_EVEN (0x870804) diff --git a/tools/mfkey/crypto1.c b/tools/mfkey/crypto1.c index f49a07225..14e2cc829 100755 --- a/tools/mfkey/crypto1.c +++ b/tools/mfkey/crypto1.c @@ -25,8 +25,8 @@ struct Crypto1State * crypto1_create(uint64_t key) struct Crypto1State *s = malloc(sizeof(*s)); if ( !s ) return NULL; - s->odd = s->even = 0; - + s->odd = s->even = 0; + int i; //for(i = 47;s && i > 0; i -= 2) { for(i = 47; i > 0; i -= 2) { @@ -103,7 +103,7 @@ uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) ret |= crypto1_bit(s, BEBIT(in, 5), is_encrypted) << (5 ^ 24); ret |= crypto1_bit(s, BEBIT(in, 6), is_encrypted) << (6 ^ 24); ret |= crypto1_bit(s, BEBIT(in, 7), is_encrypted) << (7 ^ 24); - + ret |= crypto1_bit(s, BEBIT(in, 8), is_encrypted) << (8 ^ 24); ret |= crypto1_bit(s, BEBIT(in, 9), is_encrypted) << (9 ^ 24); ret |= crypto1_bit(s, BEBIT(in, 10), is_encrypted) << (10 ^ 24); diff --git a/tools/mfkey/mfkey32.c b/tools/mfkey/mfkey32.c index 1196868d4..2761a063b 100755 --- a/tools/mfkey/mfkey32.c +++ b/tools/mfkey/mfkey32.c @@ -43,14 +43,14 @@ int main (int argc, char *argv[]) { uint32_t p64 = prng_successor(nt, 64); printf(" nt': %08x\n", p64); printf(" nt'': %08x\n", prng_successor(p64, 32)); - + // Extract the keystream from the messages printf("\nKeystream used to generate {ar} and {at}:\n"); ks2 = ar0_enc ^ p64; printf(" ks2: %08x\n", ks2); s = lfsr_recovery32(ar0_enc ^ p64, 0); - + for(t = s; t->odd | t->even; ++t) { lfsr_rollback_word(t, 0, 0); lfsr_rollback_word(t, nr0_enc, 1); diff --git a/tools/mfkey/mfkey32v2.c b/tools/mfkey/mfkey32v2.c index 9c04e9c18..03189aa73 100644 --- a/tools/mfkey/mfkey32v2.c +++ b/tools/mfkey/mfkey32v2.c @@ -3,7 +3,7 @@ #include "crapto1.h" #include #include - + int main (int argc, char *argv[]) { struct Crypto1State *s,*t; uint64_t key; // recovered key @@ -46,7 +46,7 @@ int main (int argc, char *argv[]) { printf("\nLFSR succesors of the tag challenge:\n"); uint32_t p64 = prng_successor(nt0, 64); uint32_t p64b = prng_successor(nt1, 64); - + printf(" nt': %08x\n", p64); printf(" nt'': %08x\n", prng_successor(p64, 32)); @@ -56,13 +56,13 @@ int main (int argc, char *argv[]) { printf(" ks2: %08x\n",ks2); s = lfsr_recovery32(ar0_enc ^ p64, 0); - + for(t = s; t->odd | t->even; ++t) { lfsr_rollback_word(t, 0, 0); lfsr_rollback_word(t, nr0_enc, 1); lfsr_rollback_word(t, uid ^ nt0, 0); crypto1_get_lfsr(t, &key); - + crypto1_word(t, uid ^ nt1, 0); crypto1_word(t, nr1_enc, 1); if (ar1_enc == (crypto1_word(t, 0, 0) ^ p64b)) { diff --git a/tools/mfkey/mfkey64.c b/tools/mfkey/mfkey64.c index bf1226ba8..a05cd223e 100755 --- a/tools/mfkey/mfkey64.c +++ b/tools/mfkey/mfkey64.c @@ -26,7 +26,7 @@ int main (int argc, char *argv[]) { int encc = argc - 6; int enclen[encc]; - uint8_t enc[encc][120]; + uint8_t enc[encc][120]; sscanf(argv[1],"%x",&uid); sscanf(argv[2],"%x",&nt); @@ -39,7 +39,7 @@ int main (int argc, char *argv[]) { sscanf(argv[i+6] + i2*2, "%2x", (unsigned int *)&enc[i][i2]); } } - + printf("Recovering key for:\n"); printf(" uid: %08x\n",uid); @@ -60,7 +60,7 @@ int main (int argc, char *argv[]) { printf("\nLFSR succesors of the tag challenge:\n"); printf(" nt': %08x\n",prng_successor(nt, 64)); printf(" nt'': %08x\n",prng_successor(nt, 96)); - + // Extract the keystream from the messages printf("\nKeystream used to generate {ar} and {at}:\n"); ks2 = ar_enc ^ prng_successor(nt, 64); @@ -73,11 +73,11 @@ int main (int argc, char *argv[]) { // Decrypting communication using keystream if presented if (argc > 6 ) { printf("\nDecrypted communication:\n"); - uint8_t ks4; + uint8_t ks4; int rollb = 0; for (int i = 0; i < encc; i++) { printf("{dec%d}: ", i); - for (int i2 = 0; i2 < enclen[i]; i2++) { + for (int i2 = 0; i2 < enclen[i]; i2++) { ks4 = crypto1_byte(revstate, 0, 0); printf("%02x", ks4 ^ enc[i][i2]); rollb += 1; @@ -87,7 +87,7 @@ int main (int argc, char *argv[]) { for (int i = 0; i < rollb; i++) lfsr_rollback_byte(revstate, 0, 0); } - + lfsr_rollback_word(revstate, 0, 0); lfsr_rollback_word(revstate, 0, 0); lfsr_rollback_word(revstate, nr_enc, 1); diff --git a/tools/nonce2key/crapto1.c b/tools/nonce2key/crapto1.c index fcfa931c4..5412ca8f6 100644 --- a/tools/nonce2key/crapto1.c +++ b/tools/nonce2key/crapto1.c @@ -221,7 +221,7 @@ struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in) // allocate memory for out of place bucket_sort bucket_array_t bucket; - + for (uint32_t i = 0; i < 2; i++) { for (uint32_t j = 0; j <= 0xff; j++) { bucket[i][j].head = malloc(sizeof(uint32_t)<<14); @@ -423,7 +423,7 @@ uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) ret |= lfsr_rollback_bit(s, BEBIT(in, 18), fb) << (18 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 17), fb) << (17 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 16), fb) << (16 ^ 24); - + ret |= lfsr_rollback_bit(s, BEBIT(in, 15), fb) << (15 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 14), fb) << (14 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 13), fb) << (13 ^ 24); @@ -432,7 +432,7 @@ uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) ret |= lfsr_rollback_bit(s, BEBIT(in, 10), fb) << (10 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 9), fb) << (9 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 8), fb) << (8 ^ 24); - + ret |= lfsr_rollback_bit(s, BEBIT(in, 7), fb) << (7 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 6), fb) << (6 ^ 24); ret |= lfsr_rollback_bit(s, BEBIT(in, 5), fb) << (5 ^ 24); @@ -482,7 +482,7 @@ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) { uint32_t *candidates = malloc(4 << 10); if(!candidates) return 0; - + uint32_t c, entry; int size = 0, i, good; @@ -530,7 +530,7 @@ static struct Crypto1State* check_pfx_parity(uint32_t prefix, uint32_t rresp, ui } return sl + good; -} +} /** lfsr_common_prefix * Implentation of the common prefix attack. diff --git a/tools/nonce2key/crapto1.h b/tools/nonce2key/crapto1.h index 3eaf88b72..2fd6600ec 100644 --- a/tools/nonce2key/crapto1.h +++ b/tools/nonce2key/crapto1.h @@ -44,7 +44,7 @@ uint32_t lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb); int nonce_distance(uint32_t from, uint32_t to); #define SWAPENDIAN(x)\ (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) - + #define FOREACH_VALID_NONCE(N, FILTER, FSIZE)\ uint32_t __n = 0,__M = 0, N = 0;\ int __i;\ @@ -54,7 +54,7 @@ int nonce_distance(uint32_t from, uint32_t to); break;\ else if(__i)\ __M = prng_successor(__M, (__i == 7) ? 48 : 8);\ - else + else #define LF_POLY_ODD (0x29CE5C) #define LF_POLY_EVEN (0x870804) diff --git a/tools/nonce2key/crypto1.c b/tools/nonce2key/crypto1.c index f49a07225..14e2cc829 100644 --- a/tools/nonce2key/crypto1.c +++ b/tools/nonce2key/crypto1.c @@ -25,8 +25,8 @@ struct Crypto1State * crypto1_create(uint64_t key) struct Crypto1State *s = malloc(sizeof(*s)); if ( !s ) return NULL; - s->odd = s->even = 0; - + s->odd = s->even = 0; + int i; //for(i = 47;s && i > 0; i -= 2) { for(i = 47; i > 0; i -= 2) { @@ -103,7 +103,7 @@ uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) ret |= crypto1_bit(s, BEBIT(in, 5), is_encrypted) << (5 ^ 24); ret |= crypto1_bit(s, BEBIT(in, 6), is_encrypted) << (6 ^ 24); ret |= crypto1_bit(s, BEBIT(in, 7), is_encrypted) << (7 ^ 24); - + ret |= crypto1_bit(s, BEBIT(in, 8), is_encrypted) << (8 ^ 24); ret |= crypto1_bit(s, BEBIT(in, 9), is_encrypted) << (9 ^ 24); ret |= crypto1_bit(s, BEBIT(in, 10), is_encrypted) << (10 ^ 24); diff --git a/tools/nonce2key/nonce2key.c b/tools/nonce2key/nonce2key.c index fffa5a2ac..f7bbc43b7 100644 --- a/tools/nonce2key/nonce2key.c +++ b/tools/nonce2key/nonce2key.c @@ -20,7 +20,7 @@ int main(const int argc, const char* argv[]) { sscanf(argv[2],"%08x", &nt); sscanf(argv[3],"%016" SCNx64 ,&par_info); sscanf(argv[4],"%016" SCNx64 ,&ks_info); - + // Reset the last three significant bits of the reader nonce nr &= 0xffffff1f; @@ -47,7 +47,7 @@ int main(const int argc, const char* argv[]) { printf("%01x|\n", par[i][7]); } printf("+----+--------+---+-----+---------------+\n"); - + state = lfsr_common_prefix(nr,rr,ks3x,par); lfsr_rollback_word(state,uid^nt,0); crypto1_get_lfsr(state,&key_recovered); diff --git a/uart/uart.h b/uart/uart.h index a1521a58d..d724831be 100644 --- a/uart/uart.h +++ b/uart/uart.h @@ -86,7 +86,7 @@ void uart_close(const serial_port sp); * * Returns FALSE if there was an error reading from the device. Note that a * partial read may have completed into the buffer by the corresponding - * implementation, so pszRxLen should be checked to see if any data was written. + * implementation, so pszRxLen should be checked to see if any data was written. */ bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen); diff --git a/uart/uart_posix.c b/uart/uart_posix.c index c3ff7dcca..58f24298d 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -34,7 +34,7 @@ */ // Test if we are dealing with posix operating systems -#ifndef _WIN32 +#ifndef _WIN32 #define _DEFAULT_SOURCE #include "uart.h" @@ -88,7 +88,7 @@ serial_port uart_open(const char* pcPortName) { } timeout.tv_usec = 300000; // 300 000 micro seconds - + char *colon = strrchr(addrstr, ':'); char *portstr; if (colon) { @@ -142,7 +142,7 @@ serial_port uart_open(const char* pcPortName) { return sp; } - + sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); if (sp->fd == -1) { uart_close(sp); @@ -196,12 +196,12 @@ serial_port uart_open(const char* pcPortName) { #ifdef WITH_FPC if ( uart_set_speed(sp, 115200) ) { - printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n"); + printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n"); } else { uart_set_speed(sp, 9600); - printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n"); + printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n"); } -#else +#else // set speed, works for UBUNTU 14.04 bool success = uart_set_speed(sp, 460800); if (success) { @@ -210,7 +210,7 @@ serial_port uart_open(const char* pcPortName) { uart_set_speed(sp, 115200); printf("[=] UART Setting serial baudrate 115200\n"); } -#endif +#endif return sp; } @@ -229,7 +229,7 @@ void uart_close(const serial_port sp) { int err = fcntl(spu->fd, F_SETLK, &fl); if ( err == -1) { //perror("fcntl"); - } + } close(spu->fd); free(sp); } @@ -242,7 +242,7 @@ bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size // Reset the output count *pszRxLen = 0; - + do { // Reset file descriptor FD_ZERO(&rfds); @@ -365,11 +365,11 @@ bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) { # endif default: return false; }; - + struct termios ti; - if (tcgetattr(spu->fd,&ti) == -1) + if (tcgetattr(spu->fd,&ti) == -1) return false; - + // Set port speed (Input and Output) cfsetispeed(&ti, stPortSpeed); cfsetospeed(&ti, stPortSpeed); @@ -380,10 +380,10 @@ uint32_t uart_get_speed(const serial_port sp) { struct termios ti; uint32_t uiPortSpeed; const serial_port_unix* spu = (serial_port_unix*)sp; - - if (tcgetattr(spu->fd, &ti) == -1) + + if (tcgetattr(spu->fd, &ti) == -1) return 0; - + // Set port speed (Input) speed_t stPortSpeed = cfgetispeed(&ti); switch (stPortSpeed) { diff --git a/uart/uart_win32.c b/uart/uart_win32.c index 438f586c8..5f269c677 100644 --- a/uart/uart_win32.c +++ b/uart/uart_win32.c @@ -67,8 +67,8 @@ serial_port uart_open(const char* pcPortName) { uart_close(sp); return INVALID_SERIAL_PORT; } - - // Prepare the device control + + // Prepare the device control // doesn't matter since PM3 device ignors this CDC command: set_line_coding in usb_cdc.c memset(&sp->dcb, 0, sizeof(DCB)); sp->dcb.DCBlength = sizeof(DCB); @@ -77,7 +77,7 @@ serial_port uart_open(const char* pcPortName) { printf("[!] UART error cdc setup\n"); return INVALID_SERIAL_PORT; } - + // Update the active serial port if (!SetCommState(sp->hPort, &sp->dcb)) { uart_close(sp); @@ -92,20 +92,20 @@ serial_port uart_open(const char* pcPortName) { sp->ct.ReadTotalTimeoutConstant = 1500; sp->ct.WriteTotalTimeoutMultiplier = 1000; sp->ct.WriteTotalTimeoutConstant = 0; -#else +#else sp->ct.ReadIntervalTimeout = 30; sp->ct.ReadTotalTimeoutMultiplier = 0; sp->ct.ReadTotalTimeoutConstant = 30; sp->ct.WriteTotalTimeoutMultiplier = 30; sp->ct.WriteTotalTimeoutConstant = 0; -#endif - +#endif + if (!SetCommTimeouts(sp->hPort, &sp->ct)) { uart_close(sp); printf("[!] UART error while setting comm time outs\n"); return INVALID_SERIAL_PORT; } - + PurgeComm(sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR); #ifdef WITH_FPC @@ -113,7 +113,7 @@ serial_port uart_open(const char* pcPortName) { printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n"); } else { uart_set_speed(sp, 9600); - printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n"); + printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n"); } #else bool success = uart_set_speed(sp, 460800); @@ -123,7 +123,7 @@ serial_port uart_open(const char* pcPortName) { uart_set_speed(sp, 115200); printf("[=] UART Setting serial baudrate 115200\n"); } -#endif +#endif return sp; } @@ -149,7 +149,7 @@ bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) { default: return false; }; - + spw = (serial_port_windows*)sp; spw->dcb.BaudRate = uiPortSpeed; bool result = SetCommState(spw->hPort, &spw->dcb); @@ -170,7 +170,7 @@ bool uart_receive(const serial_port sp, uint8_t* p_rx, size_t pszMaxRxLen, size_ } bool uart_send(const serial_port sp, const uint8_t* p_tx, const size_t len) { - DWORD txlen = 0; + DWORD txlen = 0; return WriteFile(((serial_port_windows*)sp)->hPort, p_tx, len, &txlen, NULL); } diff --git a/zlib/deflate.c b/zlib/deflate.c index 8e9a3e653..593f5ebd3 100644 --- a/zlib/deflate.c +++ b/zlib/deflate.c @@ -61,14 +61,14 @@ const char deflate_copyright[] = */ //----------------------------------------------------------------------------- -// This version of zlib is modified for use within the Proxmark3 project. +// This version of zlib is modified for use within the Proxmark3 project. // Files from the original distribution which are not required for this // purpose are not included. All modifications can easily be found // by searching for #ifdef ZLIB_PM3_TUNED and #ifndef ZLIB_PM3_TUNED. //----------------------------------------------------------------------------- - + /* =========================================================================== * Function prototypes. */ @@ -1776,7 +1776,7 @@ local uInt try_harder(s, strstart, lookahead, hash_head) } else { combined_gain = s->strstart - strstart + 1 - MIN_MATCH; // (possibly truncated) previous_length - 3 literals } - if (match_length < MIN_MATCH) { + if (match_length < MIN_MATCH) { combined_gain += 0; // no gain } else { combined_gain += match_length - MIN_MATCH; // match_length bytes are coded as three literals @@ -1791,7 +1791,7 @@ local uInt try_harder(s, strstart, lookahead, hash_head) hash_head = s->head[s->ins_h]; } while (s->strstart <= strstart-1 + prev_length // try to truncate the previous match to 1, 3, ... prev_length && s->strstart <= s->window_size - MIN_LOOKAHEAD); // watch out for the end of the input - + s->strstart = strstart_save; s->lookahead = lookahead_save; s->ins_h = ins_h_save; diff --git a/zlib/inflate.c b/zlib/inflate.c index 656cd6464..1b3003370 100644 --- a/zlib/inflate.c +++ b/zlib/inflate.c @@ -81,14 +81,14 @@ */ //----------------------------------------------------------------------------- -// This version of zlib is modified for use within the Proxmark3 project. +// This version of zlib is modified for use within the Proxmark3 project. // Files from the original distribution which are not required for this // purpose are not included. All modifications can easily be found // by searching for #ifdef ZLIB_PM3_TUNED and #ifndef ZLIB_PM3_TUNED. //----------------------------------------------------------------------------- - + #include "zutil.h" #include "inftrees.h" #include "inflate.h" @@ -858,7 +858,7 @@ int flush; #ifdef ZLIB_PM3_TUNED strm->msg = (char *)"fixed block coding not supported"; state->mode = BAD; -#else +#else fixedtables(state); Tracev((stderr, "inflate: fixed codes block%s\n", state->last ? " (last)" : "")); diff --git a/zlib/trees.c b/zlib/trees.c index df83f56a3..9d032bf9c 100644 --- a/zlib/trees.c +++ b/zlib/trees.c @@ -33,7 +33,7 @@ /* @(#) $Id$ */ //----------------------------------------------------------------------------- -// This version of zlib is modified for use within the Proxmark3 project. +// This version of zlib is modified for use within the Proxmark3 project. // Files from the original distribution which are not required for this // purpose are not included. All modifications can easily be found // by searching for #ifdef ZLIB_PM3_TUNED and #ifndef ZLIB_PM3_TUNED. @@ -997,9 +997,9 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) #ifdef DEBUG s->compressed_len += 3 + s->opt_len; #endif -#ifndef ZLIB_PM3_TUNED +#ifndef ZLIB_PM3_TUNED } -#endif +#endif Assert (s->compressed_len == s->bits_sent, "bad compressed size"); /* The above check is made mod 2^32, for files larger than 512 MB * and uLong implemented on 32 bits. diff --git a/zlib/zlib.h b/zlib/zlib.h index b2aa55728..d62758aaf 100644 --- a/zlib/zlib.h +++ b/zlib/zlib.h @@ -29,7 +29,7 @@ */ //----------------------------------------------------------------------------- -// This version of zlib is modified for use within the Proxmark3 project. +// This version of zlib is modified for use within the Proxmark3 project. // Files from the original distribution which are not required for this // purpose are not included. All modifications can easily be found // by searching for #ifdef ZLIB_PM3_TUNED and #ifndef ZLIB_PM3_TUNED. From bdd04942901fb86e9585fd8cafd1a1fc87fa8649 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 09:11:08 +0100 Subject: [PATCH 0681/1938] remove spurious spaces & tabs at end of lines: cpp files --- client/proxgui.cpp | 2 +- client/proxguiqt.cpp | 28 ++++++++++++++-------------- 2 files changed, 15 insertions(+), 15 deletions(-) diff --git a/client/proxgui.cpp b/client/proxgui.cpp index 3815579f4..b71ca59e3 100644 --- a/client/proxgui.cpp +++ b/client/proxgui.cpp @@ -19,7 +19,7 @@ WorkerThread::WorkerThread(char *script_cmds_file, char *script_cmd, bool usb_pr { } -WorkerThread::~WorkerThread() +WorkerThread::~WorkerThread() { } diff --git a/client/proxguiqt.cpp b/client/proxguiqt.cpp index c8ccba197..f5bdc0243 100644 --- a/client/proxguiqt.cpp +++ b/client/proxguiqt.cpp @@ -58,11 +58,11 @@ void ProxGuiQT::_ShowGraphWindow(void) { return; if (!plotwidget) { - + #if defined(__MACH__) && defined(__APPLE__) makeFocusable(); -#endif - +#endif + plotwidget = new ProxWidget(); } plotwidget->show(); @@ -114,7 +114,7 @@ void ProxGuiQT::MainLoop() makeUnfocusable(); #endif - + plotapp->exec(); } @@ -248,7 +248,7 @@ int Plot::xCoordOf(int i, QRect r ) { } int Plot::yCoordOf(int v, QRect r, int maxVal) { - int z = (r.bottom() - r.top()) / 2; + int z = (r.bottom() - r.top()) / 2; if ( maxVal == 0 ) ++maxVal; return -(z * v) / maxVal + z; } @@ -427,10 +427,10 @@ void Plot::PlotGraph(int *buffer, int len, QRect plotRect, QRect annotationRect, } void Plot::plotGridLines(QPainter* painter, QRect r) { - + // set GridOffset if (PlotGridX <= 0) return; - + int offset = GridOffset; if (GridLocked && PlotGridX) { offset = GridOffset + PlotGridX - (GraphStart % PlotGridX); @@ -447,9 +447,9 @@ void Plot::plotGridLines(QPainter* painter, QRect r) { if ((PlotGridX > 0) && ((PlotGridX * GraphPixelsPerPoint) > 1)) { for (i = (offset * GraphPixelsPerPoint); i < r.right(); i += grid_delta_x) { painter->drawLine(r.left()+i, r.top(), r.left()+i, r.bottom()); - } + } } - + if (PlotGridY > 0) { for (i = 0; yCoordOf(i, r, g_absVMax) > r.top(); i += grid_delta_y) { // line above mid @@ -565,7 +565,7 @@ Plot::Plot(QWidget *parent) : QWidget(parent), GraphStart(0), GraphPixelsPerPoin CursorBPos = 0; setWindowTitle(tr("Sliders")); - + master = parent; } @@ -605,7 +605,7 @@ void Plot::keyPressEvent(QKeyEvent *event) else offset = (int)(20 / GraphPixelsPerPoint); } - + switch(event->key()) { case Qt::Key_Down: if (GraphPixelsPerPoint <= 50) { @@ -635,7 +635,7 @@ void Plot::keyPressEvent(QKeyEvent *event) } break; - case Qt::Key_G: + case Qt::Key_G: if (PlotGridX || PlotGridY) { PlotGridX = 0; PlotGridY = 0; @@ -644,7 +644,7 @@ void Plot::keyPressEvent(QKeyEvent *event) PlotGridXdefault = 64; if ( PlotGridYdefault < 0 ) PlotGridYdefault = 0; - + PlotGridX = PlotGridXdefault; PlotGridY = PlotGridYdefault; } @@ -663,7 +663,7 @@ void Plot::keyPressEvent(QKeyEvent *event) puts("\tL Toggle lock grid relative to samples"); puts("\tQ Hide window"); puts("\tLEFT Move left"); - puts("\t LEFT Move left 1 sample"); + puts("\t LEFT Move left 1 sample"); puts("\t LEFT Page left"); puts("\tLEFT MOUSE CLICK Set yellow cursor"); puts("\tRIGHT Move right"); From 716c17bac87fa1d6164c2fa7c4b9517444116d30 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 09:11:26 +0100 Subject: [PATCH 0682/1938] Introduce make style, more to come --- Makefile | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Makefile b/Makefile index a1c593a76..93ee2d19c 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ recovery/%: FORCE $(MAKE) -C recovery $(patsubst recovery/%,%,$@) FORCE: # Dummy target to force remake in the subdirectories, even if files exist (this Makefile doesn't know about the prerequisites) -.PHONY: all clean help _test flash-bootrom flash-os flash-all FORCE +.PHONY: all clean help _test flash-bootrom flash-os flash-all style FORCE help: @echo Multi-OS Makefile, you are running on $(DETECTED_OS) @@ -88,5 +88,8 @@ endif # easy printing of MAKE VARIABLES print-%: ; @echo $* = $($*) +style: + find . \( -name "*.[ch]" -or -name "*.cpp" \) -exec perl -pi -e 's/[ \t\r]+$$//' {} \; + # Dummy target to test for GNU make availability _test: From 05ff45e5504ae6cf88bae013f5d395584f6086d1 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 10:34:43 +0100 Subject: [PATCH 0683/1938] lua: fix mix of spaces & tabs --- client/scripts/14araw.lua | 230 ++++---- client/scripts/Legic_clone.lua | 786 +++++++++++++-------------- client/scripts/amiibo.lua | 6 +- client/scripts/brutesim.lua | 414 +++++++------- client/scripts/calc_di.lua | 224 ++++---- client/scripts/calc_ev1_it.lua | 232 ++++---- client/scripts/calc_mizip.lua | 256 ++++----- client/scripts/calypso.lua | 306 +++++------ client/scripts/cmdline.lua | 16 +- client/scripts/didump.lua | 442 +++++++-------- client/scripts/dumptoemul-mfu.lua | 164 +++--- client/scripts/dumptoemul.lua | 152 +++--- client/scripts/e.lua | 100 ++-- client/scripts/emul2dump.lua | 118 ++-- client/scripts/emul2html.lua | 58 +- client/scripts/formatMifare.lua | 430 +++++++-------- client/scripts/hf_read.lua | 24 +- client/scripts/htmldump.lua | 58 +- client/scripts/iso15_magic.lua | 140 ++--- client/scripts/legic.lua | 706 ++++++++++++------------ client/scripts/legic_buffer2card.lua | 58 +- client/scripts/lf_bulk.lua | 220 ++++---- client/scripts/mfkeys.lua | 364 ++++++------- client/scripts/mifare_access.lua | 140 ++--- client/scripts/mifare_autopwn.lua | 320 +++++------ client/scripts/mifareplus.lua | 502 ++++++++--------- client/scripts/ndef_dump.lua | 320 +++++------ client/scripts/ntag_3d.lua | 552 +++++++++---------- client/scripts/parameters.lua | 44 +- client/scripts/read_pwd_mem.lua | 282 +++++----- client/scripts/remagic.lua | 132 ++--- client/scripts/test_t55x7_ask.lua | 150 ++--- client/scripts/test_t55x7_bi.lua | 142 ++--- client/scripts/test_t55x7_fsk.lua | 154 +++--- client/scripts/test_t55x7_psk.lua | 166 +++--- client/scripts/tnp3clone.lua | 252 ++++----- client/scripts/tnp3dump.lua | 446 +++++++-------- client/scripts/tnp3sim.lua | 694 +++++++++++------------ client/scripts/tracetest.lua | 162 +++--- client/scripts/ufodump.lua | 222 ++++---- client/scripts/ul_uid.lua | 186 +++---- 41 files changed, 5185 insertions(+), 5185 deletions(-) diff --git a/client/scripts/14araw.lua b/client/scripts/14araw.lua index 01af5422e..e0448d9db 100644 --- a/client/scripts/14araw.lua +++ b/client/scripts/14araw.lua @@ -6,22 +6,22 @@ example = "script run 14araw -x 6000F57b" author = "Martin Holst Swende" desc = [[ -This is a script to allow raw 1444a commands to be sent and received. +This is a script to allow raw 1444a commands to be sent and received. Arguments: - -o do not connect - use this only if you previously used -p to stay connected - -r do not read response - -c calculate and append CRC - -p stay connected - dont inactivate the field - -x Data to send (NO SPACES!) - -d Debug flag - -t Topaz mode - -3 ISO14443-4 (use RATS) + -o do not connect - use this only if you previously used -p to stay connected + -r do not read response + -c calculate and append CRC + -p stay connected - dont inactivate the field + -x Data to send (NO SPACES!) + -d Debug flag + -t Topaz mode + -3 ISO14443-4 (use RATS) -Examples : +Examples : # 1. Connect and don't disconnect -script run 14araw -p +script run 14araw -p # 2. Send mf auth, read response (nonce) script run 14araw -o -x 6000F57b -p # 3. disconnect @@ -33,11 +33,11 @@ script run 14araw -x 6000F57b --[[ -This script communicates with -/armsrc/iso14443a.c, specifically ReaderIso14443a() at around line 1779 and onwards. +This script communicates with +/armsrc/iso14443a.c, specifically ReaderIso14443a() at around line 1779 and onwards. -Check there for details about data format and how commands are interpreted on the -device-side. +Check there for details about data format and how commands are interpreted on the +device-side. ]] -- Some globals @@ -45,143 +45,143 @@ local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds local DEBUG = false -- the debug flag ------------------------------- --- Some utilities +-- Some utilities ------------------------------- ---- +--- -- A debug printout-function local function dbg(args) - if DEBUG then - print("###", args) - end -end ---- + if DEBUG then + print("###", args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) + print("ERROR: ",err) end ---- +--- -- Usage help local function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end ---- +--- -- The main entry point function main(args) - if args == nil or #args == 0 then return help() end + if args == nil or #args == 0 then return help() end - local ignore_response = false - local append_crc = false - local stayconnected = false - local payload = nil - local doconnect = true - local topaz_mode = false - local no_rats = false - - -- Read the parameters - for o, a in getopt.getopt(args, 'orcpx:dt3') do - if o == "o" then doconnect = false end - if o == "r" then ignore_response = true end - if o == "c" then append_crc = true end - if o == "p" then stayconnected = true end - if o == "x" then payload = a end - if o == "d" then DEBUG = true end - if o == "t" then topaz_mode = true end - if o == "3" then no_rats = true end - end + local ignore_response = false + local append_crc = false + local stayconnected = false + local payload = nil + local doconnect = true + local topaz_mode = false + local no_rats = false - -- First of all, connect - if doconnect then - dbg("doconnect") - -- We reuse the connect functionality from a - -- common library - info, err = lib14a.read(true, no_rats) + -- Read the parameters + for o, a in getopt.getopt(args, 'orcpx:dt3') do + if o == "o" then doconnect = false end + if o == "r" then ignore_response = true end + if o == "c" then append_crc = true end + if o == "p" then stayconnected = true end + if o == "x" then payload = a end + if o == "d" then DEBUG = true end + if o == "t" then topaz_mode = true end + if o == "3" then no_rats = true end + end - if err then return oops(err) end - print(("Connected to card, uid = %s"):format(info.uid)) - end + -- First of all, connect + if doconnect then + dbg("doconnect") + -- We reuse the connect functionality from a + -- common library + info, err = lib14a.read(true, no_rats) - -- The actual raw payload, if any - if payload then - res,err = sendRaw(payload,{ignore_response = ignore_response, topaz_mode = topaz_mode, append_crc = append_crc}) - if err then return oops(err) end - - if not ignoreresponse then - -- Display the returned data - showdata(res) - end - end - -- And, perhaps disconnect? - if not stayconnected then - disconnect() - end + if err then return oops(err) end + print(("Connected to card, uid = %s"):format(info.uid)) + end + + -- The actual raw payload, if any + if payload then + res,err = sendRaw(payload,{ignore_response = ignore_response, topaz_mode = topaz_mode, append_crc = append_crc}) + if err then return oops(err) end + + if not ignoreresponse then + -- Display the returned data + showdata(res) + end + end + -- And, perhaps disconnect? + if not stayconnected then + disconnect() + end end --- Picks out and displays the data read from a tag -- Specifically, takes a usb packet, converts to a Command --- (as in commands.lua), takes the data-array and +-- (as in commands.lua), takes the data-array and -- reads the number of bytes specified in arg1 (arg0 in c-struct) -- and displays the data -- @param usbpacket the data received from the device function showdata(usbpacket) - local cmd_response = Command.parse(usbpacket) - local len = tonumber(cmd_response.arg1) *2 - --print("data length:",len) - local data = string.sub(tostring(cmd_response.data), 0, len); - print("<< ",data) - --print("----------------") + local cmd_response = Command.parse(usbpacket) + local len = tonumber(cmd_response.arg1) *2 + --print("data length:",len) + local data = string.sub(tostring(cmd_response.data), 0, len); + print("<< ",data) + --print("----------------") end function sendRaw(rawdata, options) - print(">> ", rawdata) - - local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW + print(">> ", rawdata) - if options.topaz_mode then - flags = flags + lib14a.ISO14A_COMMAND.ISO14A_TOPAZMODE - end - if options.append_crc then - flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC - end - - local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, - arg1 = flags, -- Send raw - -- arg2 contains the length, which is half the length - -- of the ASCII-string rawdata - arg2 = string.len(rawdata)/2, - data = rawdata} - return lib14a.sendToDevice(command, options.ignore_response) + local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW + + if options.topaz_mode then + flags = flags + lib14a.ISO14A_COMMAND.ISO14A_TOPAZMODE + end + if options.append_crc then + flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC + end + + local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, + arg1 = flags, -- Send raw + -- arg2 contains the length, which is half the length + -- of the ASCII-string rawdata + arg2 = string.len(rawdata)/2, + data = rawdata} + return lib14a.sendToDevice(command, options.ignore_response) end -- Sends an instruction to do nothing, only disconnect function disconnect() - local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0, } - -- We can ignore the response here, no ACK is returned for this command - -- Check /armsrc/iso14443a.c, ReaderIso14443a() for details - return lib14a.sendToDevice(command,true) -end + local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0,} + -- We can ignore the response here, no ACK is returned for this command + -- Check /armsrc/iso14443a.c, ReaderIso14443a() for details + return lib14a.sendToDevice(command,true) +end ------------------------- --- Testing +-- Testing ------------------------- function selftest() - DEBUG = true - dbg("Performing test") - main() - main("-p") - main(" -o -x 6000F57b -p") - main("-o") - main("-x 6000F57b") - dbg("Tests done") + DEBUG = true + dbg("Performing test") + main() + main("-p") + main(" -o -x 6000F57b -p") + main("-o") + main("-x 6000F57b") + dbg("Tests done") end --- Flip the switch here to perform a sanity check. +-- Flip the switch here to perform a sanity check. -- It read a nonce in two different ways, as specified in the usage-section -if "--test"==args then - selftest() -else - -- Call the main - main(args) +if "--test"==args then + selftest() +else + -- Call the main + main(args) end diff --git a/client/scripts/Legic_clone.lua b/client/scripts/Legic_clone.lua index 4c638f82f..dcac7f323 100644 --- a/client/scripts/Legic_clone.lua +++ b/client/scripts/Legic_clone.lua @@ -1,87 +1,87 @@ --[[ - script to create a clone-dump with new crc + script to create a clone-dump with new crc Author: mosci my Fork: https://github.com/icsom/proxmark3.git - Upstream: https://github.com/Proxmark/proxmark3.git + Upstream: https://github.com/Proxmark/proxmark3.git - 1. read tag-dump, xor byte 22..end with byte 0x05 of the inputfile - 2. write to outfile - 3. set byte 0x05 to newcrc - 4. until byte 0x21 plain like in inputfile - 5. from 0x22..end xored with newcrc - 6. calculate new crc on each segment (needs to know the new MCD & MSN0..2) - - simplest usage: - read a valid legic tag with 'hf legic reader' - save the dump with 'hf legic save orig.hex' + 1. read tag-dump, xor byte 22..end with byte 0x05 of the inputfile + 2. write to outfile + 3. set byte 0x05 to newcrc + 4. until byte 0x21 plain like in inputfile + 5. from 0x22..end xored with newcrc + 6. calculate new crc on each segment (needs to know the new MCD & MSN0..2) + + simplest usage: + read a valid legic tag with 'hf legic reader' + save the dump with 'hf legic save orig.hex' place your 'empty' tag on the reader and run 'script run Legic_clone -i orig.hex -w' you will see some output like: - read 1024 bytes from legic_dumps/j_0000.hex - - place your empty tag onto the PM3 to read and display the MCD & MSN0..2 - the values will be shown below - confirm whnen ready [y/n] ?y - #db# setting up legic card - #db# MIM 256 card found, reading card ... - #db# Card read, use 'hf legic decode' or - #db# 'data hexsamples 8' to view results - 0b ad c0 de <- !! here you'll see the MCD & MSN of your empty tag, which has to be typed in manually as seen below !! - type in MCD as 2-digit value - e.g.: 00 (default: 79 ) - > 0b - type in MSN0 as 2-digit value - e.g.: 01 (default: 28 ) - > ad - type in MSN1 as 2-digit value - e.g.: 02 (default: d1 ) - > c0 - type in MSN2 as 2-digit value - e.g.: 03 (default: 43 ) - > de - MCD:0b, MSN:ad c0 de, MCC:79 <- this crc is calculated from the MCD & MSN and must match the one on yout empty tag - - wrote 1024 bytes to myLegicClone.hex - enter number of bytes to write? (default: 86 ) - - loaded 1024 samples - #db# setting up legic card - #db# MIM 256 card found, writing 0x00 - 0x01 ... - #db# write successful - ... - #db# setting up legic card - #db# MIM 256 card found, writing 0x56 - 0x01 ... - #db# write successful - proxmark3> - - the default value (number of bytes to write) is calculated over all valid segments and should be ok - just hit enter, wait until write has finished - and your clone should be ready (except there has to be a additional KGH-CRC to be calculated - which credentials are unknown until yet) - - the '-w' switch will only work with my fork - it needs the binary legic_crc8 which is not part of the proxmark3-master-branch - also the ability to write DCF is not possible with the proxmark3-master-branch - but creating dumpfile-clone files will be possible (without valid segment-crc - this has to done manually with) + read 1024 bytes from legic_dumps/j_0000.hex - - (example) Legic-Prime Layout with 'Kaba Group Header' - +----+----+----+----+----+----+----+----+ - 0x00|MCD |MSN0|MSN1|MSN2|MCC | 60 | ea | 9f | - +----+----+----+----+----+----+----+----+ - 0x08| ff | 00 | 00 | 00 | 11 |Bck0|Bck1|Bck2| - +----+----+----+----+----+----+----+----+ - 0x10|Bck3|Bck4|Bck5|BCC | 00 | 00 |Seg0|Seg1| - +----+----+----+----+----+----+----+----+ - 0x18|Seg2|Seg3|SegC|Stp0|Stp1|Stp2|Stp3|UID0| - +----+----+----+----+----+----+----+----+ - 0x20|UID1|UID2|kghC| - +----+----+----+ - - MCD= ManufacturerID (1 Byte) - MSN0..2= ManufactureSerialNumber (3 Byte) - MCC= CRC (1 Byte) calculated over MCD,MSN0..2 - DCF= DecrementalField (2 Byte) 'credential' (enduser-Tag) seems to have always DCF-low=0x60 DCF-high=0xea - Bck0..5= Backup (6 Byte) Bck0 'dirty-flag', Bck1..5 SegmentHeader-Backup - BCC= BackupCRC (1 Byte) CRC calculated over Bck1..5 - Seg0..3= SegmentHeader (on MIM 4 Byte ) - SegC= SegmentCRC (1 Byte) calculated over MCD,MSN0..2,Seg0..3 - Stp0..n= Stamp0... (variable length) length = Segment-Len - UserData - 1 - UID0..n= UserDater (variable length - with KGH hex 0x00-0x63 / dec 0-99) length = Segment-Len - WRP - WRC - 1 - kghC= KabaGroupHeader (1 Byte + addr 0x0c must be 0x11) - as seen on ths example: addr 0x05..0x08 & 0x0c must have been set to this values - otherwise kghCRC will not be created by a official reader (not accepted) + place your empty tag onto the PM3 to read and display the MCD & MSN0..2 + the values will be shown below + confirm whnen ready [y/n] ?y + #db# setting up legic card + #db# MIM 256 card found, reading card ... + #db# Card read, use 'hf legic decode' or + #db# 'data hexsamples 8' to view results + 0b ad c0 de <- !! here you'll see the MCD & MSN of your empty tag, which has to be typed in manually as seen below !! + type in MCD as 2-digit value - e.g.: 00 (default: 79 ) + > 0b + type in MSN0 as 2-digit value - e.g.: 01 (default: 28 ) + > ad + type in MSN1 as 2-digit value - e.g.: 02 (default: d1 ) + > c0 + type in MSN2 as 2-digit value - e.g.: 03 (default: 43 ) + > de + MCD:0b, MSN:ad c0 de, MCC:79 <- this crc is calculated from the MCD & MSN and must match the one on yout empty tag + + wrote 1024 bytes to myLegicClone.hex + enter number of bytes to write? (default: 86 ) + + loaded 1024 samples + #db# setting up legic card + #db# MIM 256 card found, writing 0x00 - 0x01 ... + #db# write successful + ... + #db# setting up legic card + #db# MIM 256 card found, writing 0x56 - 0x01 ... + #db# write successful + proxmark3> + + the default value (number of bytes to write) is calculated over all valid segments and should be ok - just hit enter, wait until write has finished + and your clone should be ready (except there has to be a additional KGH-CRC to be calculated - which credentials are unknown until yet) + + the '-w' switch will only work with my fork - it needs the binary legic_crc8 which is not part of the proxmark3-master-branch + also the ability to write DCF is not possible with the proxmark3-master-branch + but creating dumpfile-clone files will be possible (without valid segment-crc - this has to done manually with) + + + (example) Legic-Prime Layout with 'Kaba Group Header' + +----+----+----+----+----+----+----+----+ + 0x00|MCD |MSN0|MSN1|MSN2|MCC | 60 | ea | 9f | + +----+----+----+----+----+----+----+----+ + 0x08| ff | 00 | 00 | 00 | 11 |Bck0|Bck1|Bck2| + +----+----+----+----+----+----+----+----+ + 0x10|Bck3|Bck4|Bck5|BCC | 00 | 00 |Seg0|Seg1| + +----+----+----+----+----+----+----+----+ + 0x18|Seg2|Seg3|SegC|Stp0|Stp1|Stp2|Stp3|UID0| + +----+----+----+----+----+----+----+----+ + 0x20|UID1|UID2|kghC| + +----+----+----+ + + MCD= ManufacturerID (1 Byte) + MSN0..2= ManufactureSerialNumber (3 Byte) + MCC= CRC (1 Byte) calculated over MCD,MSN0..2 + DCF= DecrementalField (2 Byte) 'credential' (enduser-Tag) seems to have always DCF-low=0x60 DCF-high=0xea + Bck0..5= Backup (6 Byte) Bck0 'dirty-flag', Bck1..5 SegmentHeader-Backup + BCC= BackupCRC (1 Byte) CRC calculated over Bck1..5 + Seg0..3= SegmentHeader (on MIM 4 Byte ) + SegC= SegmentCRC (1 Byte) calculated over MCD,MSN0..2,Seg0..3 + Stp0..n= Stamp0... (variable length) length = Segment-Len - UserData - 1 + UID0..n= UserDater (variable length - with KGH hex 0x00-0x63 / dec 0-99) length = Segment-Len - WRP - WRC - 1 + kghC= KabaGroupHeader (1 Byte + addr 0x0c must be 0x11) + as seen on this example: addr 0x05..0x08 & 0x0c must have been set to this values - otherwise kghCRC will not be created by a official reader (not accepted) --]] example = "Script create a clone-dump of a dump from a Legic Prime Tag" @@ -89,24 +89,24 @@ author = "Mosci" desc = [[ This is a script which create a clone-dump of a dump from a Legic Prime Tag (MIM256 or MIM1024) -(created with 'hf legic save my_dump.hex') +(created with 'hf legic save my_dump.hex') requiered arguments: - -i (file to read data from) - -optional arguments : - -h - Help text - -o - requieres option -c to be given - -c - requieres option -o to be given - -d - Display content of found Segments - -s - Display summary at the end - -w - write directly to Tag - a file myLegicClone.hex wille be generated also - - e.g.: - hint: using the CRC '00' will result in a plain dump ( -c 00 ) + -i (file to read data from) -Examples : - script run legic_clone -i my_dump.hex -o my_clone.hex -c f8 - script run legic_clone -i my_dump.hex -d -s +optional arguments : + -h - Help text + -o - requieres option -c to be given + -c - requieres option -o to be given + -d - Display content of found Segments + -s - Display summary at the end + -w - write directly to Tag - a file myLegicClone.hex wille be generated also + + e.g.: + hint: using the CRC '00' will result in a plain dump ( -c 00 ) + +Examples : + script run legic_clone -i my_dump.hex -o my_clone.hex -c f8 + script run legic_clone -i my_dump.hex -d -s ]] local utils = require('utils') @@ -114,33 +114,33 @@ local getopt = require('getopt') local bxor = bit32.bxor -- we need always 2 digits -function prepend_zero(s) - if (string.len(s)==1) then return "0" .. s - else - if (string.len(s)==0) then return "00" - else return s - end - end +function prepend_zero(s) + if (string.len(s)==1) then return "0" .. s + else + if (string.len(s)==0) then return "00" + else return s + end + end end ---- +--- -- This is only meant to be used when errors occur function oops(err) - print("ERROR: ",err) - return nil, err + print("ERROR: ",err) + return nil, err end ---- +--- -- Usage help function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end -- Check availability of file function file_check(file_name) - local file_found=io.open(file_name, "r") + local file_found=io.open(file_name, "r") if file_found==nil then file_found=false else @@ -152,113 +152,113 @@ end --- xor-wrapper -- xor all from addr 0x22 (start counting from 1 => 23) function xorme(hex, xor, index) - if ( index >= 23 ) then - return ('%02x'):format(bxor( tonumber(hex,16) , tonumber(xor,16) )) - else - return hex - end + if ( index >= 23 ) then + return ('%02x'):format(bxor( tonumber(hex,16) , tonumber(xor,16) )) + else + return hex + end end -- read input-file into array function getInputBytes(infile) - local line - local bytes = {} + local line + local bytes = {} - local fhi,err = io.open(infile) - if err then print("OOps ... faild to read from file ".. infile); return false; end + local fhi,err = io.open(infile) + if err then print("OOps ... faild to read from file ".. infile); return false; end - while true do - line = fhi:read() - if line == nil then break end + while true do + line = fhi:read() + if line == nil then break end - for byte in line:gmatch("%w+") do - table.insert(bytes, byte) - end - end - - fhi:close() + for byte in line:gmatch("%w+") do + table.insert(bytes, byte) + end + end - print("\nread ".. #bytes .." bytes from ".. infile) - return bytes + fhi:close() + + print("\nread ".. #bytes .." bytes from ".. infile) + return bytes end -- write to file function writeOutputBytes(bytes, outfile) - local line - local bcnt=0 - local fho,err = io.open(outfile,"w") - if err then print("OOps ... faild to open output-file ".. outfile); return false; end + local line + local bcnt=0 + local fho,err = io.open(outfile,"w") + if err then print("OOps ... faild to open output-file ".. outfile); return false; end - for i = 1, #bytes do - if (bcnt == 0) then - line=bytes[i] - elseif (bcnt <= 7) then - line=line.." "..bytes[i] - end - if (bcnt == 7) then - -- write line to new file - fho:write(line.."\n") - -- reset counter & line - bcnt=-1 - line="" - end - bcnt=bcnt+1 - end - fho:close() - print("\nwrote ".. #bytes .." bytes to " .. outfile) - return true + for i = 1, #bytes do + if (bcnt == 0) then + line=bytes[i] + elseif (bcnt <= 7) then + line=line.." "..bytes[i] + end + if (bcnt == 7) then + -- write line to new file + fho:write(line.."\n") + -- reset counter & line + bcnt=-1 + line="" + end + bcnt=bcnt+1 + end + fho:close() + print("\nwrote ".. #bytes .." bytes to " .. outfile) + return true end -- xore certain bytes function xorBytes(inBytes, crc) - local bytes = {} - for index = 1, #inBytes do - bytes[index] = xorme(inBytes[index], crc, index) - end - if (#inBytes == #bytes) then - -- replace crc - bytes[5] = string.sub(crc,-2) - return bytes - else - print("error: byte-count missmatch") - return false - end + local bytes = {} + for index = 1, #inBytes do + bytes[index] = xorme(inBytes[index], crc, index) + end + if (#inBytes == #bytes) then + -- replace crc + bytes[5] = string.sub(crc,-2) + return bytes + else + print("error: byte-count missmatch") + return false + end end -- get raw segment-data function getSegmentData(bytes, start, index) - local raw, len, valid, last, wrp, wrc, rd, crc - local segment = {} - segment[0] = bytes[start].." "..bytes[start+1].." "..bytes[start+2].." "..bytes[start+3] - -- flag = high nibble of byte 1 - segment[1] = string.sub(bytes[start+1],0,1) + local raw, len, valid, last, wrp, wrc, rd, crc + local segment = {} + segment[0] = bytes[start].." "..bytes[start+1].." "..bytes[start+2].." "..bytes[start+3] + -- flag = high nibble of byte 1 + segment[1] = string.sub(bytes[start+1],0,1) - -- valid = bit 6 of byte 1 - segment[2] = tonumber(bit32.extract("0x"..bytes[start+1],6,1),16) + -- valid = bit 6 of byte 1 + segment[2] = tonumber(bit32.extract("0x"..bytes[start+1],6,1),16) - -- last = bit 7 of byte 1 - segment[3] = tonumber(bit32.extract("0x"..bytes[start+1],7,1),16) + -- last = bit 7 of byte 1 + segment[3] = tonumber(bit32.extract("0x"..bytes[start+1],7,1),16) - -- len = (byte 0)+(bit0-3 of byte 1) + -- len = (byte 0)+(bit0-3 of byte 1) segment[4] = tonumber(("%03x"):format(tonumber(bit32.extract("0x"..bytes[start+1],0,3),16)..tonumber(bytes[start],16)),16) - - -- wrp (write proteted) = byte 2 - segment[5] = tonumber(bytes[start+2]) - -- wrc (write control) - bit 4-6 of byte 3 - segment[6] = tonumber(bit32.extract("0x"..bytes[start+3],4,3),16) + -- wrp (write proteted) = byte 2 + segment[5] = tonumber(bytes[start+2]) - -- rd (read disabled) - bit 7 of byte 3 - segment[7] = tonumber(bit32.extract("0x"..bytes[start+3],7,1),16) + -- wrc (write control) - bit 4-6 of byte 3 + segment[6] = tonumber(bit32.extract("0x"..bytes[start+3],4,3),16) - -- crc byte 4 - segment[8] = bytes[start+4] + -- rd (read disabled) - bit 7 of byte 3 + segment[7] = tonumber(bit32.extract("0x"..bytes[start+3],7,1),16) - -- segment index - segment[9] = index + -- crc byte 4 + segment[8] = bytes[start+4] - -- # crc-byte - segment[10] = start+4 + -- segment index + segment[9] = index + + -- # crc-byte + segment[10] = start+4 return segment end @@ -276,7 +276,7 @@ function CheckKgh(bytes, segStart, segEnd) local WRP = bytes[(segStart+2)] local WRC = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3],4,3),16)) local RD = ("%02x"):format(tonumber(bit32.extract("0x"..bytes[segStart+3],7,1),16)) - local XX = "00" + local XX = "00" cmd = bytes[1]..bytes[2]..bytes[3]..bytes[4]..WRP..WRC..RD..XX for i=(segStart+5), (segStart+5+dataLen-2) do cmd = cmd..bytes[i] @@ -294,247 +294,247 @@ end -- get only the addresses of segemnt-crc's and the length of bytes function getSegmentCrcBytes(bytes) - local start=23 - local index=0 - local crcbytes = {} - repeat - seg = getSegmentData(bytes,start,index) - crcbytes[index]= seg[10] - start = start + seg[4] - index = index + 1 - until (seg[3] == 1 or tonumber(seg[9]) == 126 ) - crcbytes[index] = start - return crcbytes + local start=23 + local index=0 + local crcbytes = {} + repeat + seg = getSegmentData(bytes,start,index) + crcbytes[index]= seg[10] + start = start + seg[4] + index = index + 1 + until (seg[3] == 1 or tonumber(seg[9]) == 126 ) + crcbytes[index] = start + return crcbytes end -- print segment-data (hf legic decode like) function displaySegments(bytes) - --display segment header(s) - start=23 - index="00" - - --repeat until last-flag ist set to 1 or segment-index has reached 126 - repeat - wrc="" - wrp="" - pld="" - Seg = getSegmentData(bytes,start,index) - KGH = CheckKgh(bytes,start,(start+tonumber(Seg[4],10))) - printSegment(Seg) + --display segment header(s) + start=23 + index="00" - -- wrc - if(Seg[6]>0) then - print("WRC protected area:") - -- length of wrc = wrc - for i=1, Seg[6] do - -- starts at (segment-start + segment-header + segment-crc)-1 - wrc = wrc..bytes[(start+4+1+i)-1].." " - end - print(wrc) - elseif(Seg[5]>0) then - print("Remaining write protected area:") - -- length of wrp = (wrp-wrc) - for i=1, (Seg[5]-Seg[6]) do - -- starts at (segment-start + segment-header + segment-crc + wrc)-1 - wrp = wrp..bytes[(start+4+1+Seg[6]+i)-1].." " - end - print(wrp) - end - - -- payload - print("Remaining segment payload:") - --length of payload = segment-len - segment-header - segment-crc - wrp -wrc - for i=1, (Seg[4]-4-1-Seg[5]-Seg[6]) do - -- starts at (segment-start + segment-header + segment-crc + segment-wrp + segemnt-wrc)-1 - pld = pld..bytes[(start+4+1+Seg[5]+Seg[6]+i)-1].." " - end - print(pld) + --repeat until last-flag ist set to 1 or segment-index has reached 126 + repeat + wrc="" + wrp="" + pld="" + Seg = getSegmentData(bytes,start,index) + KGH = CheckKgh(bytes,start,(start+tonumber(Seg[4],10))) + printSegment(Seg) + + -- wrc + if(Seg[6]>0) then + print("WRC protected area:") + -- length of wrc = wrc + for i=1, Seg[6] do + -- starts at (segment-start + segment-header + segment-crc)-1 + wrc = wrc..bytes[(start+4+1+i)-1].." " + end + print(wrc) + elseif(Seg[5]>0) then + print("Remaining write protected area:") + -- length of wrp = (wrp-wrc) + for i=1, (Seg[5]-Seg[6]) do + -- starts at (segment-start + segment-header + segment-crc + wrc)-1 + wrp = wrp..bytes[(start+4+1+Seg[6]+i)-1].." " + end + print(wrp) + end + + -- payload + print("Remaining segment payload:") + --length of payload = segment-len - segment-header - segment-crc - wrp -wrc + for i=1, (Seg[4]-4-1-Seg[5]-Seg[6]) do + -- starts at (segment-start + segment-header + segment-crc + segment-wrp + segemnt-wrc)-1 + pld = pld..bytes[(start+4+1+Seg[5]+Seg[6]+i)-1].." " + end + print(pld) if (KGH) then print("'Kaba Group Header' detected"); end - start = start+Seg[4] - index = prepend_zero(tonumber(Seg[9])+1) - - until (Seg[3] == 1 or tonumber(Seg[9]) == 126 ) + start = start+Seg[4] + index = prepend_zero(tonumber(Seg[9])+1) + + until (Seg[3] == 1 or tonumber(Seg[9]) == 126 ) end -- print Segment values function printSegment(SegmentData) - res = "\nSegment "..SegmentData[9]..": " - res = res.. "raw header="..SegmentData[0]..", " - res = res.. "flag="..SegmentData[1].." (valid="..SegmentData[2].." last="..SegmentData[3].."), " - res = res.. "len="..("%04d"):format(SegmentData[4])..", " - res = res.. "WRP="..prepend_zero(SegmentData[5])..", " - res = res.. "WRC="..prepend_zero(SegmentData[6])..", " - res = res.. "RD="..SegmentData[7]..", " - res = res.. "crc="..SegmentData[8] - print(res) + res = "\nSegment "..SegmentData[9]..": " + res = res.. "raw header="..SegmentData[0]..", " + res = res.. "flag="..SegmentData[1].." (valid="..SegmentData[2].." last="..SegmentData[3].."), " + res = res.. "len="..("%04d"):format(SegmentData[4])..", " + res = res.. "WRP="..prepend_zero(SegmentData[5])..", " + res = res.. "WRC="..prepend_zero(SegmentData[6])..", " + res = res.. "RD="..SegmentData[7]..", " + res = res.. "crc="..SegmentData[8] + print(res) end -- write clone-data to tag function writeToTag(plainBytes) - local SegCrcs = {} - if(utils.confirm("\nplace your empty tag onto the PM3 to read and display the MCD & MSN0..2\nthe values will be shown below\n confirm when ready") == false) then + local SegCrcs = {} + if(utils.confirm("\nplace your empty tag onto the PM3 to read and display the MCD & MSN0..2\nthe values will be shown below\n confirm when ready") == false) then return end - -- gather MCD & MSN from new Tag - this must be enterd manually - cmd = 'hf legic read 0x00 0x04' - core.console(cmd) - print("\nthese are the MCD MSN0 MSN1 MSN2 from the Tag that has being read:") - cmd = 'data hexsamples 4' - core.console(cmd) + -- gather MCD & MSN from new Tag - this must be enterd manually + cmd = 'hf legic read 0x00 0x04' + core.console(cmd) + print("\nthese are the MCD MSN0 MSN1 MSN2 from the Tag that has being read:") + cmd = 'data hexsamples 4' + core.console(cmd) print("^^ use this values as input for the following answers (one 2-digit-value per question/answer):") - -- enter MCD & MSN (in hex) - MCD = utils.input("type in MCD as 2-digit value - e.g.: 00", plainBytes[1]) - MSN0 = utils.input("type in MSN0 as 2-digit value - e.g.: 01", plainBytes[2]) - MSN1 = utils.input("type in MSN1 as 2-digit value - e.g.: 02", plainBytes[3]) - MSN2 = utils.input("type in MSN2 as 2-digit value - e.g.: 03", plainBytes[4]) + -- enter MCD & MSN (in hex) + MCD = utils.input("type in MCD as 2-digit value - e.g.: 00", plainBytes[1]) + MSN0 = utils.input("type in MSN0 as 2-digit value - e.g.: 01", plainBytes[2]) + MSN1 = utils.input("type in MSN1 as 2-digit value - e.g.: 02", plainBytes[3]) + MSN2 = utils.input("type in MSN2 as 2-digit value - e.g.: 03", plainBytes[4]) - -- calculate crc8 over MCD & MSN - cmd = MCD..MSN0..MSN1..MSN2 - MCC = ("%02x"):format(utils.Crc8Legic(cmd)) - print("MCD:"..MCD..", MSN:"..MSN0.." "..MSN1.." "..MSN2..", MCC:"..MCC) + -- calculate crc8 over MCD & MSN + cmd = MCD..MSN0..MSN1..MSN2 + MCC = ("%02x"):format(utils.Crc8Legic(cmd)) + print("MCD:"..MCD..", MSN:"..MSN0.." "..MSN1.." "..MSN2..", MCC:"..MCC) - -- calculate new Segment-CRC for each valid segment - SegCrcs = getSegmentCrcBytes(plainBytes) - for i=0, (#SegCrcs-1) do + -- calculate new Segment-CRC for each valid segment + SegCrcs = getSegmentCrcBytes(plainBytes) + for i=0, (#SegCrcs-1) do -- SegCrcs[i]-4 = address of first byte of segmentHeader (low byte segment-length) segLen=tonumber(("%1x"):format(tonumber(bit32.extract("0x"..plainBytes[(SegCrcs[i]-3)],0,3),16))..("%02x"):format(tonumber(plainBytes[SegCrcs[i]-4],16)),16) segStart=(SegCrcs[i]-4) segEnd=(SegCrcs[i]-4+segLen) KGH=CheckKgh(plainBytes,segStart,segEnd) - if (KGH) then + if (KGH) then print("'Kaba Group Header' detected - re-calculate...") end - cmd = MCD..MSN0..MSN1..MSN2..plainBytes[SegCrcs[i]-4]..plainBytes[SegCrcs[i]-3]..plainBytes[SegCrcs[i]-2]..plainBytes[SegCrcs[i]-1] - plainBytes[SegCrcs[i]] = ("%02x"):format(utils.Crc8Legic(cmd)) - end + cmd = MCD..MSN0..MSN1..MSN2..plainBytes[SegCrcs[i]-4]..plainBytes[SegCrcs[i]-3]..plainBytes[SegCrcs[i]-2]..plainBytes[SegCrcs[i]-1] + plainBytes[SegCrcs[i]] = ("%02x"):format(utils.Crc8Legic(cmd)) + end - -- apply MCD & MSN to plain data - plainBytes[1] = MCD - plainBytes[2] = MSN0 - plainBytes[3] = MSN1 - plainBytes[4] = MSN2 - plainBytes[5] = MCC - - -- prepare plainBytes for writing (xor plain data with new MCC) - bytes = xorBytes(plainBytes, MCC) - - -- write data to file - if (writeOutputBytes(bytes, "myLegicClone.hex")) then - WriteBytes = utils.input("enter number of bytes to write?", SegCrcs[#SegCrcs]) + -- apply MCD & MSN to plain data + plainBytes[1] = MCD + plainBytes[2] = MSN0 + plainBytes[3] = MSN1 + plainBytes[4] = MSN2 + plainBytes[5] = MCC - -- load file into pm3-buffer - cmd = 'hf legic load myLegicClone.hex' - core.console(cmd) - - -- write pm3-buffer to Tag - for i=0, WriteBytes do - if ( i<5 or i>6) then - cmd = ('hf legic write 0x%02x 0x01'):format(i) - core.console(cmd) - elseif (i == 6) then - -- write DCF in reverse order (requires 'mosci-patch') - cmd = 'hf legic write 0x05 0x02' - core.console(cmd) - else - print("skipping byte 0x05 - will be written next step") - end - utils.Sleep(0.2) - end - end + -- prepare plainBytes for writing (xor plain data with new MCC) + bytes = xorBytes(plainBytes, MCC) + + -- write data to file + if (writeOutputBytes(bytes, "myLegicClone.hex")) then + WriteBytes = utils.input("enter number of bytes to write?", SegCrcs[#SegCrcs]) + + -- load file into pm3-buffer + cmd = 'hf legic load myLegicClone.hex' + core.console(cmd) + + -- write pm3-buffer to Tag + for i=0, WriteBytes do + if ( i<5 or i>6) then + cmd = ('hf legic write 0x%02x 0x01'):format(i) + core.console(cmd) + elseif (i == 6) then + -- write DCF in reverse order (requires 'mosci-patch') + cmd = 'hf legic write 0x05 0x02' + core.console(cmd) + else + print("skipping byte 0x05 - will be written next step") + end + utils.Sleep(0.2) + end + end end -- main function function main(args) - -- some variables - local i=0 - local oldcrc, newcrc, infile, outfile - local bytes = {} - local segments = {} - - -- parse arguments for the script - for o, a in getopt.getopt(args, 'hwsdc:i:o:') do - -- output file - if o == "o" then - outfile = a - ofs = true - if (file_check(a)) then - local answer = utils.confirm("\nthe output-file "..a.." alredy exists!\nthis will delete the previous content!\ncontinue?") - if (answer==false) then return oops("quiting") end - end - end - -- input file - if o == "i" then - infile = a - if (file_check(infile)==false) then - return oops("input file: "..infile.." not found") - else - bytes = getInputBytes(infile) - oldcrc = bytes[5] - ifs = true - if (bytes == false) then return oops('couldnt get input bytes') end - end - i = i+1 - end - -- new crc - if o == "c" then - newcrc = a - ncs = true - end - -- display segments switch - if o == "d" then ds = true; end - -- display summary switch - if o == "s" then ss = true; end - -- write to tag switch - if o == "w" then ws = true; end - -- help - if o == "h" then return help() end - end - - if (not ifs) then return oops("option -i is required but missing") end - - -- bytes to plain - bytes = xorBytes(bytes, oldcrc) - - -- show segments (works only on plain bytes) - if (ds) then - print("+------------------------------------------- Segments -------------------------------------------+") - displaySegments(bytes); - end + -- some variables + local i=0 + local oldcrc, newcrc, infile, outfile + local bytes = {} + local segments = {} - if (ofs and ncs) then - -- xor bytes with new crc - newBytes = xorBytes(bytes, newcrc) - -- write output - if (writeOutputBytes(newBytes, outfile)) then - -- show summary if requested - if (ss) then - -- information - res = "\n+-------------------------------------------- Summary -------------------------------------------+" - res = res .."\ncreated clone_dump from\n\t"..infile.." crc: "..oldcrc.."\ndump_file:" - res = res .."\n\t"..outfile.." crc: "..string.sub(newcrc,-2) - res = res .."\nyou may load the new file with: hf legic load "..outfile - res = res .."\n\nif you don't write to tag immediately ('-w' switch) you will need to recalculate each segmentCRC" - res = res .."\nafter writing this dump to a tag!" - res = res .."\n\na segmentCRC gets calculated over MCD,MSN0..3,Segment-Header0..3" - res = res .."\ne.g. (based on Segment00 of the data from "..infile.."):" - res = res .."\nhf legic crc8 "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26] - -- this can not be calculated without knowing the new MCD, MSN0..2 - print(res) - end - end - else - if (ss) then - -- show why the output-file was not written - print("\nnew file not written - some arguments are missing ..") - print("output file: ".. (ofs and outfile or "not given")) - print("new crc: ".. (ncs and newcrc or "not given")) - end - end - -- write to tag - if (ws and #bytes == 1024) then - writeToTag(bytes) - end + -- parse arguments for the script + for o, a in getopt.getopt(args, 'hwsdc:i:o:') do + -- output file + if o == "o" then + outfile = a + ofs = true + if (file_check(a)) then + local answer = utils.confirm("\nthe output-file "..a.." alredy exists!\nthis will delete the previous content!\ncontinue?") + if (answer==false) then return oops("quiting") end + end + end + -- input file + if o == "i" then + infile = a + if (file_check(infile)==false) then + return oops("input file: "..infile.." not found") + else + bytes = getInputBytes(infile) + oldcrc = bytes[5] + ifs = true + if (bytes == false) then return oops('couldnt get input bytes') end + end + i = i+1 + end + -- new crc + if o == "c" then + newcrc = a + ncs = true + end + -- display segments switch + if o == "d" then ds = true; end + -- display summary switch + if o == "s" then ss = true; end + -- write to tag switch + if o == "w" then ws = true; end + -- help + if o == "h" then return help() end + end + + if (not ifs) then return oops("option -i is required but missing") end + + -- bytes to plain + bytes = xorBytes(bytes, oldcrc) + + -- show segments (works only on plain bytes) + if (ds) then + print("+------------------------------------------- Segments -------------------------------------------+") + displaySegments(bytes); + end + + if (ofs and ncs) then + -- xor bytes with new crc + newBytes = xorBytes(bytes, newcrc) + -- write output + if (writeOutputBytes(newBytes, outfile)) then + -- show summary if requested + if (ss) then + -- information + res = "\n+-------------------------------------------- Summary -------------------------------------------+" + res = res .."\ncreated clone_dump from\n\t"..infile.." crc: "..oldcrc.."\ndump_file:" + res = res .."\n\t"..outfile.." crc: "..string.sub(newcrc,-2) + res = res .."\nyou may load the new file with: hf legic load "..outfile + res = res .."\n\nif you don't write to tag immediately ('-w' switch) you will need to recalculate each segmentCRC" + res = res .."\nafter writing this dump to a tag!" + res = res .."\n\na segmentCRC gets calculated over MCD,MSN0..3,Segment-Header0..3" + res = res .."\ne.g. (based on Segment00 of the data from "..infile.."):" + res = res .."\nhf legic crc8 "..bytes[1]..bytes[2]..bytes[3]..bytes[4]..bytes[23]..bytes[24]..bytes[25]..bytes[26] + -- this can not be calculated without knowing the new MCD, MSN0..2 + print(res) + end + end + else + if (ss) then + -- show why the output-file was not written + print("\nnew file not written - some arguments are missing ..") + print("output file: ".. (ofs and outfile or "not given")) + print("new crc: ".. (ncs and newcrc or "not given")) + end + end + -- write to tag + if (ws and #bytes == 1024) then + writeToTag(bytes) + end end -- call main with arguments diff --git a/client/scripts/amiibo.lua b/client/scripts/amiibo.lua index cc2459f30..2bcd2a07e 100644 --- a/client/scripts/amiibo.lua +++ b/client/scripts/amiibo.lua @@ -88,10 +88,10 @@ local function emulate_amiibo (amiibo_data) local simCmd = Command:new{cmd = cmds.CMD_SIMULATE_TAG_ISO_14443a, arg1 = 7, arg2 = uid_first, arg3 = uid_second} local _, err = reader.sendToDevice(simCmd) if err then - print('Failed to start simulator', err) - return + print('Failed to start simulator', err) + return else - print('Starting simulator') + print('Starting simulator') end end diff --git a/client/scripts/brutesim.lua b/client/scripts/brutesim.lua index 50e3b5888..9527d8970 100644 --- a/client/scripts/brutesim.lua +++ b/client/scripts/brutesim.lua @@ -21,7 +21,7 @@ desc = [[ This script uses the proxmark3 implementations of simulation to bruteforce given ranges of id. It uses both LF and HF simulations. - + -- Author note -- I wrote this as i was doing a PACS audit. This is far from complete, but is easily expandable. -- The idea was based on proxbrute, but i needed more options, and support for different readers. @@ -38,8 +38,8 @@ usage = [[ script run brutesim -r rfid_tag -f facility_code -b base_card_number -c count -t timeout -d direction Arguments: - -h this help - -r *see below RFID Tag: the RFID tag to emulate + -h this help + -r *see below RFID Tag: the RFID tag to emulate pyramid awid fdx @@ -50,251 +50,251 @@ Arguments: 14a hid - -f 0-999 facility code (dfx: country id, 14a: type) - -b 0-65535 base card number to start from - -c 1-65536 number of cards to try - -t .0-99999, pause timeout between cards (use the word 'pause' to wait for user input) - -d up, down direction to move through card numbers + -f 0-999 facility code (dfx: country id, 14a: type) + -b 0-65535 base card number to start from + -c 1-65536 number of cards to try + -t .0-99999, pause timeout between cards (use the word 'pause' to wait for user input) + -d up, down direction to move through card numbers ]] local DEBUG = true -local bor = bit32.bor -local bxor = bit32.bxor +local bor = bit32.bor +local bxor = bit32.bxor local lshift = bit32.lshift ---- +--- -- A debug printout-function local function dbg(args) if type(args) == "table" then - local i = 1 - while args[i] do - dbg(args[i]) - i = i+1 - end - else - print("###", args) - end + local i = 1 + while args[i] do + dbg(args[i]) + i = i+1 + end + else + print("###", args) + end end ---- +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) - return nil,err + print("ERROR: ",err) + return nil,err end ---- +--- -- Usage help local function help() - print(copyright) - print(author) - print(version) - print(desc) - print("Example usage") - print(example) + print(copyright) + print(author) + print(version) + print(desc) + print("Example usage") + print(example) end -- -- Exit message function exitMsg(msg) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print(msg) - print() + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() end -- -- Check if a string is empty local function isempty(s) - return s == nil or s == '' + return s == nil or s == '' end --- The code below was blatantly stolen from Brian Redbeard's lf_bulk_program.lua script +-- The code below was blatantly stolen from Brian Redbeard's lf_bulk_program.lua script local function toBits(num, bits) - bits = bits or math.max(1, select(2, math.frexp(num))) - local t = {} - for b = bits, 1, -1 do - t[b] = math.fmod(num, 2) - num = math.floor((num - t[b]) / 2) - end - return table.concat(t) + bits = bits or math.max(1, select(2, math.frexp(num))) + local t = {} + for b = bits, 1, -1 do + t[b] = math.fmod(num, 2) + num = math.floor((num - t[b]) / 2) + end + return table.concat(t) end -- --- check for parity in bit-string. +-- check for parity in bit-string. local function evenparity(s) - local _, count = string.gsub(s, "1", "") - local p = count % 2 - if (p == 0) then - return false - end - return true + local _, count = string.gsub(s, "1", "") + local p = count % 2 + if (p == 0) then + return false + end + return true end -- --- calcs hex for HID +-- calcs hex for HID local function cardHex(i, f) - fac = lshift(f, 16) - id = bor(i, fac) - stream = toBits(id, 26) - high = evenparity(string.sub(stream, 0, 12)) and 1 or 0 - low = not evenparity(string.sub(stream, 13)) and 1 or 0 - bits = bor(lshift(id, 1), low) - bits = bor(bits, lshift(high, 25)) - preamble = bor(0, lshift(1, 5)) - bits = bor(bits, lshift(1, 26)) - return ("%04x%08x"):format(preamble, bits) + fac = lshift(f, 16) + id = bor(i, fac) + stream = toBits(id, 26) + high = evenparity(string.sub(stream, 0, 12)) and 1 or 0 + low = not evenparity(string.sub(stream, 13)) and 1 or 0 + bits = bor(lshift(id, 1), low) + bits = bor(bits, lshift(high, 25)) + preamble = bor(0, lshift(1, 5)) + bits = bor(bits, lshift(1, 26)) + return ("%04x%08x"):format(preamble, bits) end -- -- local function main(args) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print() - - if #args == 0 then return help() end + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print() - for o, a in getopt.getopt(args, 'r:f:b:c:t:d:h') do -- Populate command like arguments - if o == 'r' then rfidtag = a end - if o == 'f' then facility = a end - if o == 'b' then baseid = a end - if o == 'c' then count = a end - if o == 't' then timeout = a end - if o == 'd' then direction = a end - if o == 'h' then return print(usage) end - end + if #args == 0 then return help() end - -- Check to see if -r argument was passed - if isempty(rfidtag) then - print("You must supply the flag -r (rfid tag)") - print(usage) - return - end + for o, a in getopt.getopt(args, 'r:f:b:c:t:d:h') do -- Populate command like arguments + if o == 'r' then rfidtag = a end + if o == 'f' then facility = a end + if o == 'b' then baseid = a end + if o == 'c' then count = a end + if o == 't' then timeout = a end + if o == 'd' then direction = a end + if o == 'h' then return print(usage) end + end - -- Check what RFID Tag we are using - if rfidtag == 'pyramid' then - consolecommand = 'lf pyramid sim' -- set the console command - rfidtagname = 'Farpointe/Pyramid' -- set the display name - facilityrequired = 1 -- set if FC is required - elseif rfidtag == 'awid' then - consolecommand = 'lf awid sim' - rfidtagname = 'AWID' - facilityrequired = 1 - elseif rfidtag == 'fdx' then -- I'm not sure why you would need to bruteforce this ¯\_(ツ)_/¯ - consolecommand = 'lf fdx sim' - rfidtagname = 'FDX-B' - facilityrequired = 1 - elseif rfidtag == 'jablotron' then - consolecommand = 'lf jablotron sim' - rfidtagname = 'Jablotron' - facilityrequired = 0 - elseif rfidtag == 'noralsy' then - consolecommand = 'lf noralsy sim' - rfidtagname = 'Noralsy' - facilityrequired = 0 - elseif rfidtag == 'presco' then - consolecommand = 'lf presco sim d' - rfidtagname = 'Presco' - facilityrequired = 0 - elseif rfidtag == 'visa2000' then - consolecommand = 'lf visa2000 sim' - rfidtagname = 'Visa2000' - facilityrequired = 0 - elseif rfidtag == '14a' then - consolecommand = 'hf 14a sim' - if facility == "1" then rfidtagname = 'MIFARE Classic' -- Here we use the -f option to read the 14a type instead of the facility code - elseif facility == "2" then rfidtagname = 'MIFARE Ultralight' - elseif facility == "3" then rfidtagname = 'MIFARE Desfire' - elseif facility == "4" then rfidtagname = 'ISO/IEC 14443-4' - elseif facility == "5" then rfidtagname = 'MIFARE Tnp3xxx' - else - print("Invalid 14a type (-f) supplied. Must be 1-5") - print(usage) - return - end - facilityrequired = 0 -- Disable the FC required check, as we used it for type instead of FC - elseif rfidtag == 'hid' then - consolecommand = 'lf hid sim' - rfidtagname = 'HID' - facilityrequired = 1 - else -- Display error and exit out if bad RFID tag was supplied - print("Invalid rfid tag (-r) supplied") - print(usage) - return - end - - if isempty(baseid) then -- Display error and exit out if no starting id is set - print("You must supply the flag -b (base id)") - print(usage) - return - end + -- Check to see if -r argument was passed + if isempty(rfidtag) then + print("You must supply the flag -r (rfid tag)") + print(usage) + return + end - if isempty(count) then -- Display error and exit out of no count is set - print("You must supply the flag -c (count)") - print(usage) - return - end - - if facilityrequired == 1 then -- If FC is required - facilitymessage = " - Facility Code: " -- Add FC to status message - if isempty(facility) then -- If FC was left blank, display warning and set FC to 0 - print("Using 0 for the facility code as -f was not supplied") - facility = 0 - end - else -- If FC is not required - facility = "" -- Clear FC - facilitymessage = "" -- Remove FC from status message - end - - if isempty(timeout) then -- If timeout was not supplied, show warning and set timeout to 0 - print("Using 0 for the timeout as -t was not supplied") - timeout = 0 - end - - if isempty(direction) then -- If direction was not supplied, show warning and set direction to down - print("Using down for direction as -d was not supplied") - direction = 'down' - end - - if tonumber(count) < 1 then - print("Count -c must be set to 1 or higher") - return - else - count = count -1 -- Make our count accurate by removing 1, because math - end - - if direction == 'down' then -- If counting down, set up our for loop to count down - endid = baseid - count - fordirection = -1 - elseif direction == 'up' then -- If counting up, set our for loop to count up - endid = baseid + count - fordirection = 1 - else -- If invalid direction was set, show warning and set up our for loop to count down - print("Invalid direction (-d) supplied, using down") - endid = baseid - count - fordirection = -1 - end - + -- Check what RFID Tag we are using + if rfidtag == 'pyramid' then + consolecommand = 'lf pyramid sim' -- set the console command + rfidtagname = 'Farpointe/Pyramid' -- set the display name + facilityrequired = 1 -- set if FC is required + elseif rfidtag == 'awid' then + consolecommand = 'lf awid sim' + rfidtagname = 'AWID' + facilityrequired = 1 + elseif rfidtag == 'fdx' then -- I'm not sure why you would need to bruteforce this ¯\_(ツ)_/¯ + consolecommand = 'lf fdx sim' + rfidtagname = 'FDX-B' + facilityrequired = 1 + elseif rfidtag == 'jablotron' then + consolecommand = 'lf jablotron sim' + rfidtagname = 'Jablotron' + facilityrequired = 0 + elseif rfidtag == 'noralsy' then + consolecommand = 'lf noralsy sim' + rfidtagname = 'Noralsy' + facilityrequired = 0 + elseif rfidtag == 'presco' then + consolecommand = 'lf presco sim d' + rfidtagname = 'Presco' + facilityrequired = 0 + elseif rfidtag == 'visa2000' then + consolecommand = 'lf visa2000 sim' + rfidtagname = 'Visa2000' + facilityrequired = 0 + elseif rfidtag == '14a' then + consolecommand = 'hf 14a sim' + if facility == "1" then rfidtagname = 'MIFARE Classic' -- Here we use the -f option to read the 14a type instead of the facility code + elseif facility == "2" then rfidtagname = 'MIFARE Ultralight' + elseif facility == "3" then rfidtagname = 'MIFARE Desfire' + elseif facility == "4" then rfidtagname = 'ISO/IEC 14443-4' + elseif facility == "5" then rfidtagname = 'MIFARE Tnp3xxx' + else + print("Invalid 14a type (-f) supplied. Must be 1-5") + print(usage) + return + end + facilityrequired = 0 -- Disable the FC required check, as we used it for type instead of FC + elseif rfidtag == 'hid' then + consolecommand = 'lf hid sim' + rfidtagname = 'HID' + facilityrequired = 1 + else -- Display error and exit out if bad RFID tag was supplied + print("Invalid rfid tag (-r) supplied") + print(usage) + return + end - - -- display status message - print("") - print("BruteForcing "..rfidtagname..""..facilitymessage..""..facility.." - CardNumber Start: "..baseid.." - CardNumber End: "..endid.." - TimeOut: "..timeout) - print("") - - -- loop through for each count (-c) - for cardnum = baseid, endid, fordirection do - - -- If rfid tag is set to HID, convert card to HEX using the stolen code above - if rfidtag == 'hid' then cardnum = cardHex(cardnum, facility) end - - -- send command to proxmark - core.console(consolecommand..' '..facility..' '..cardnum) + if isempty(baseid) then -- Display error and exit out if no starting id is set + print("You must supply the flag -b (base id)") + print(usage) + return + end - if timeout == 'pause' then - print("Press enter to continue ...") - io.read() - else - os.execute("sleep "..timeout.."") - end - end - - -- ping the proxmark to stop emulation and see if its still responding - core.console('hw ping') + if isempty(count) then -- Display error and exit out of no count is set + print("You must supply the flag -c (count)") + print(usage) + return + end + + if facilityrequired == 1 then -- If FC is required + facilitymessage = " - Facility Code: " -- Add FC to status message + if isempty(facility) then -- If FC was left blank, display warning and set FC to 0 + print("Using 0 for the facility code as -f was not supplied") + facility = 0 + end + else -- If FC is not required + facility = "" -- Clear FC + facilitymessage = "" -- Remove FC from status message + end + + if isempty(timeout) then -- If timeout was not supplied, show warning and set timeout to 0 + print("Using 0 for the timeout as -t was not supplied") + timeout = 0 + end + + if isempty(direction) then -- If direction was not supplied, show warning and set direction to down + print("Using down for direction as -d was not supplied") + direction = 'down' + end + + if tonumber(count) < 1 then + print("Count -c must be set to 1 or higher") + return + else + count = count -1 -- Make our count accurate by removing 1, because math + end + + if direction == 'down' then -- If counting down, set up our for loop to count down + endid = baseid - count + fordirection = -1 + elseif direction == 'up' then -- If counting up, set our for loop to count up + endid = baseid + count + fordirection = 1 + else -- If invalid direction was set, show warning and set up our for loop to count down + print("Invalid direction (-d) supplied, using down") + endid = baseid - count + fordirection = -1 + end + + + + -- display status message + print("") + print("BruteForcing "..rfidtagname..""..facilitymessage..""..facility.." - CardNumber Start: "..baseid.." - CardNumber End: "..endid.." - TimeOut: "..timeout) + print("") + + -- loop through for each count (-c) + for cardnum = baseid, endid, fordirection do + + -- If rfid tag is set to HID, convert card to HEX using the stolen code above + if rfidtag == 'hid' then cardnum = cardHex(cardnum, facility) end + + -- send command to proxmark + core.console(consolecommand..' '..facility..' '..cardnum) + + if timeout == 'pause' then + print("Press enter to continue ...") + io.read() + else + os.execute("sleep "..timeout.."") + end + end + + -- ping the proxmark to stop emulation and see if its still responding + core.console('hw ping') end main(args) \ No newline at end of file diff --git a/client/scripts/calc_di.lua b/client/scripts/calc_di.lua index b46d45b51..e0b587332 100644 --- a/client/scripts/calc_di.lua +++ b/client/scripts/calc_di.lua @@ -7,170 +7,170 @@ copyright = '' author = "Iceman" version = 'v1.0.0' desc = [[ -This script calculates mifare keys based on uid diversification for DI. +This script calculates mifare keys based on uid diversification for DI. Algo not found by me. ]] example = [[ - -- if called without, it reads tag uid - script run calc_di - - -- - script run calc_di -u 11223344556677 + -- if called without, it reads tag uid + script run calc_di + + -- + script run calc_di -u 11223344556677 ]] usage = [[ script run calc_di -h -u Arguments: - -h : this help - -u : UID + -h : this help + -u : UID ]] local DEBUG = true local BAR = '286329204469736E65792032303133' local MIS = '0A14FD0507FF4BCD026BA83F0A3B89A9' local bxor = bit32.bxor ---- +--- -- A debug printout-function local function dbg(args) if not DEBUG then return end if type(args) == "table" then - local i = 1 - while args[i] do - dbg(args[i]) - i = i+1 - end - else - print("###", args) - end -end ---- + local i = 1 + while args[i] do + dbg(args[i]) + i = i+1 + end + else + print("###", args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) - return nil,err + print("ERROR: ",err) + return nil,err end ---- +--- -- Usage help local function help() - print(copyright) - print(author) - print(version) - print(desc) - print('Example usage') - print(example) + print(copyright) + print(author) + print(version) + print(desc) + print('Example usage') + print(example) end --- -- Exit message local function exitMsg(msg) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print(msg) - print() + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() end --- -- dumps all keys to file local function dumptofile(keys) - dbg('dumping keys to file') + dbg('dumping keys to file') - if utils.confirm('Do you wish to save the keys to dumpfile?') then - local destination = utils.input('Select a filename to store to', 'dumpkeys.bin') - local file = io.open(destination, 'wb') - if file == nil then - print('Could not write to file ', destination) - return - end + if utils.confirm('Do you wish to save the keys to dumpfile?') then + local destination = utils.input('Select a filename to store to', 'dumpkeys.bin') + local file = io.open(destination, 'wb') + if file == nil then + print('Could not write to file ', destination) + return + end - -- Mifare Mini has 5 sectors, - local key_a = '' - local key_b = '' - - for sector = 0, #keys do - local keyA, keyB = unpack(keys[sector]) - key_a = key_a .. bin.pack('H', keyA); - key_b = key_b .. bin.pack('H', keyB); - end - file:write(key_a) - file:write(key_b) - file:close() - end + -- Mifare Mini has 5 sectors, + local key_a = '' + local key_b = '' + + for sector = 0, #keys do + local keyA, keyB = unpack(keys[sector]) + key_a = key_a .. bin.pack('H', keyA); + key_b = key_b .. bin.pack('H', keyB); + end + file:write(key_a) + file:write(key_b) + file:close() + end end --- -- create key local function keygen(uid) - local data = MIS..uid..BAR - local hash = utils.ConvertAsciiToBytes(utils.Sha1Hex(data)) - return string.format("%02X%02X%02X%02X%02X%02X", - hash[3+1], - hash[2+1], - hash[1+1], - hash[0+1], - hash[7+1], - hash[6+1] - ) + local data = MIS..uid..BAR + local hash = utils.ConvertAsciiToBytes(utils.Sha1Hex(data)) + return string.format("%02X%02X%02X%02X%02X%02X", + hash[3+1], + hash[2+1], + hash[1+1], + hash[0+1], + hash[7+1], + hash[6+1] + ) end --- -- print keys local function printKeys(keys) - print('|---|----------------|---|----------------|---|') - print('|sec|key A |res|key B |res|') - print('|---|----------------|---|----------------|---|') - for sector = 0, #keys do - local keyA, keyB = unpack(keys[sector]) - print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, 1, keyB, 1)) - end - print('|---|----------------|---|----------------|---|') + print('|---|----------------|---|----------------|---|') + print('|sec|key A |res|key B |res|') + print('|---|----------------|---|----------------|---|') + for sector = 0, #keys do + local keyA, keyB = unpack(keys[sector]) + print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, 1, keyB, 1)) + end + print('|---|----------------|---|----------------|---|') end --- -- createfull set of keys local function createKeys(uid) - local key = keygen(uid) - local k = {} - for i = 0,4 do - k[i] = { key, key } - end - return k + local key = keygen(uid) + local k = {} + for i = 0,4 do + k[i] = { key, key } + end + return k end --- -- main local function main(args) - print( string.rep('==', 30) ) - print() - - local uid - local useUID = false - - -- Arguments for the script - for o, a in getopt.getopt(args, 'hu:') do - if o == "h" then return help() end - if o == "u" then uid = a; useUID = true end - end + print( string.rep('==', 30) ) + print() - if useUID then - -- uid string checks if supplied - if uid == nil then return oops('empty uid string') end - if #uid == 0 then return oops('empty uid string') end - if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end - else - -- GET TAG UID - local tag, err = lib14a.read(false, true) - if not tag then return oops(err) end - core.clearCommandBuffer() + local uid + local useUID = false - -- simple tag check - if 0x09 ~= tag.sak then - if 0x4400 ~= tag.atqa then - return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name)) - end - end - uid = tag.uid - end - - print('|UID|', uid) - - local keys, err = createKeys( uid ) - printKeys( keys ) - dumptofile( keys ) + -- Arguments for the script + for o, a in getopt.getopt(args, 'hu:') do + if o == "h" then return help() end + if o == "u" then uid = a; useUID = true end + end + + if useUID then + -- uid string checks if supplied + if uid == nil then return oops('empty uid string') end + if #uid == 0 then return oops('empty uid string') end + if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end + else + -- GET TAG UID + local tag, err = lib14a.read(false, true) + if not tag then return oops(err) end + core.clearCommandBuffer() + + -- simple tag check + if 0x09 ~= tag.sak then + if 0x4400 ~= tag.atqa then + return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name)) + end + end + uid = tag.uid + end + + print('|UID|', uid) + + local keys, err = createKeys( uid ) + printKeys( keys ) + dumptofile( keys ) end main(args) \ No newline at end of file diff --git a/client/scripts/calc_ev1_it.lua b/client/scripts/calc_ev1_it.lua index f7a59dc1e..c6070d20d 100644 --- a/client/scripts/calc_ev1_it.lua +++ b/client/scripts/calc_ev1_it.lua @@ -12,167 +12,167 @@ Algo not found by me. ]] example =[[ -- if called without, it reads tag uid - script run calc_ev1_it - - -- - script run calc_ev1_it -u 11223344556677 + script run calc_ev1_it + + -- + script run calc_ev1_it -u 11223344556677 ]] usage = [[ script run calc_ev1_it -h -u " Arguments: - -h : this help - -u : UID + -h : this help + -u : UID ]] local DEBUG = true local bxor = bit32.bxor ---- +--- -- A debug printout-function local function dbg(args) - if not DEBUG then return end - + if not DEBUG then return end + if type(args) == "table" then - local i = 1 - while args[i] do - dbg(args[i]) - i = i+1 - end - else - print("###", args) - end -end ---- + local i = 1 + while args[i] do + dbg(args[i]) + i = i+1 + end + else + print("###", args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) - return nil,err + print("ERROR: ",err) + return nil,err end ---- +--- -- Usage help local function help() - print(copyright) - print(author) - print(version) - print(desc) - print("Example usage") - print(example) + print(copyright) + print(author) + print(version) + print(desc) + print("Example usage") + print(example) end -- -- Exit message function exitMsg(msg) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print(msg) - print() + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() end local _xortable = { --[[ position, 4byte xor --]] - {"00","4f2711c1"}, - {"01","07D7BB83"}, - {"02","9636EF07"}, - {"03","B5F4460E"}, - {"04","F271141C"}, - {"05","7D7BB038"}, - {"06","636EF871"}, - {"07","5F4468E3"}, - {"08","271149C7"}, - {"09","D7BB0B8F"}, - {"0A","36EF8F1E"}, - {"0B","F446863D"}, - {"0C","7114947A"}, - {"0D","7BB0B0F5"}, - {"0E","6EF8F9EB"}, - {"0F","44686BD7"}, - {"10","11494fAF"}, - {"11","BB0B075F"}, - {"12","EF8F96BE"}, - {"13","4686B57C"}, - {"14","1494F2F9"}, - {"15","B0B07DF3"}, - {"16","F8F963E6"}, - {"17","686B5FCC"}, - {"18","494F2799"}, - {"19","0B07D733"}, - {"1A","8F963667"}, - {"1B","86B5F4CE"}, - {"1C","94F2719C"}, - {"1D","B07D7B38"}, - {"1E","F9636E70"}, - {"1F","6B5F44E0"}, + {"00","4f2711c1"}, + {"01","07D7BB83"}, + {"02","9636EF07"}, + {"03","B5F4460E"}, + {"04","F271141C"}, + {"05","7D7BB038"}, + {"06","636EF871"}, + {"07","5F4468E3"}, + {"08","271149C7"}, + {"09","D7BB0B8F"}, + {"0A","36EF8F1E"}, + {"0B","F446863D"}, + {"0C","7114947A"}, + {"0D","7BB0B0F5"}, + {"0E","6EF8F9EB"}, + {"0F","44686BD7"}, + {"10","11494fAF"}, + {"11","BB0B075F"}, + {"12","EF8F96BE"}, + {"13","4686B57C"}, + {"14","1494F2F9"}, + {"15","B0B07DF3"}, + {"16","F8F963E6"}, + {"17","686B5FCC"}, + {"18","494F2799"}, + {"19","0B07D733"}, + {"1A","8F963667"}, + {"1B","86B5F4CE"}, + {"1C","94F2719C"}, + {"1D","B07D7B38"}, + {"1E","F9636E70"}, + {"1F","6B5F44E0"}, } local function findEntryByUid( uid ) - -- xor UID4,UID5,UID6,UID7 - -- mod 0x20 (dec 32) - local pos = (bxor(uid[4], uid[5], uid[6], uid[7])) % 32 + -- xor UID4,UID5,UID6,UID7 + -- mod 0x20 (dec 32) + local pos = (bxor(uid[4], uid[5], uid[6], uid[7])) % 32 + + -- convert to hexstring + pos = string.format('%02X', pos) - -- convert to hexstring - pos = string.format('%02X', pos) - for k, v in pairs(_xortable) do - if ( v[1] == pos ) then - return utils.ConvertHexToBytes(v[2]) - end - end - return nil + if ( v[1] == pos ) then + return utils.ConvertHexToBytes(v[2]) + end + end + return nil end --- -- create pwd local function pwdgen(uid) - -- PWD CALC - -- PWD0 = T0 xor B xor C xor D - -- PWD1 = T1 xor A xor C xor E - -- PWD2 = T2 xor A xor B xor F - -- PWD3 = T3 xor G - local uidbytes = utils.ConvertHexToBytes(uid) + -- PWD CALC + -- PWD0 = T0 xor B xor C xor D + -- PWD1 = T1 xor A xor C xor E + -- PWD2 = T2 xor A xor B xor F + -- PWD3 = T3 xor G + local uidbytes = utils.ConvertHexToBytes(uid) local entry = findEntryByUid(uidbytes) - if entry == nil then return nil, "Can't find a xor entry" end + if entry == nil then return nil, "Can't find a xor entry" end local pwd0 = bxor( entry[1], uidbytes[2], uidbytes[3], uidbytes[4]) - local pwd1 = bxor( entry[2], uidbytes[1], uidbytes[3], uidbytes[5]) - local pwd2 = bxor( entry[3], uidbytes[1], uidbytes[2], uidbytes[6]) - local pwd3 = bxor( entry[4], uidbytes[7]) - return string.format('%02X%02X%02X%02X', pwd0, pwd1, pwd2, pwd3) + local pwd1 = bxor( entry[2], uidbytes[1], uidbytes[3], uidbytes[5]) + local pwd2 = bxor( entry[3], uidbytes[1], uidbytes[2], uidbytes[6]) + local pwd3 = bxor( entry[4], uidbytes[7]) + return string.format('%02X%02X%02X%02X', pwd0, pwd1, pwd2, pwd3) end -- -- main local function main(args) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print() - - local uid = '04111211121110' - local useUID = false - - -- Arguments for the script - for o, a in getopt.getopt(args, 'hu:') do - if o == "h" then return help() end - if o == "u" then uid = a; useUID = true end - end + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print() - if useUID then - -- uid string checks - if uid == nil then return oops('empty uid string') end - if #uid == 0 then return oops('empty uid string') end - if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end - else - -- GET TAG UID - local tag, err = lib14a.read(false, true) - if not tag then return oops(err) end - core.clearCommandBuffer() - uid = tag.uid - end - - print('UID | '..uid) - local pwd, err = pwdgen(uid) - if not pwd then return ooops(err) end - - print(string.format('PWD | %s', pwd)) + local uid = '04111211121110' + local useUID = false + + -- Arguments for the script + for o, a in getopt.getopt(args, 'hu:') do + if o == "h" then return help() end + if o == "u" then uid = a; useUID = true end + end + + if useUID then + -- uid string checks + if uid == nil then return oops('empty uid string') end + if #uid == 0 then return oops('empty uid string') end + if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end + else + -- GET TAG UID + local tag, err = lib14a.read(false, true) + if not tag then return oops(err) end + core.clearCommandBuffer() + uid = tag.uid + end + + print('UID | '..uid) + local pwd, err = pwdgen(uid) + if not pwd then return ooops(err) end + + print(string.format('PWD | %s', pwd)) end main(args) \ No newline at end of file diff --git a/client/scripts/calc_mizip.lua b/client/scripts/calc_mizip.lua index 4500c9c0f..42f13c578 100644 --- a/client/scripts/calc_mizip.lua +++ b/client/scripts/calc_mizip.lua @@ -6,192 +6,192 @@ local utils = require('utils') author = 'Iceman' version = 'v1.0.0' desc = [[ -This script calculates mifare keys based on uid diversification for mizip. +This script calculates mifare keys based on uid diversification for mizip. Algo not found by me. ]] example = [[ - -- if called without, it reads tag uid - script run calc_mizip - - -- - script run calc_mizip -u 11223344 + -- if called without, it reads tag uid + script run calc_mizip + + -- + script run calc_mizip -u 11223344 ]] usage = [[ script run calc_mizip -h -u Arguments: - -h : this help - -u : UID + -h : this help + -u : UID ]] local DEBUG = true local bxor = bit32.bxor local _xortable = { --[[ sector key A/B, 6byte xor --]] - {1, "09125a2589e5", "F12C8453D821"}, - {2, "AB75C937922F", "73E799FE3241"}, - {3, "E27241AF2C09", "AA4D137656AE"}, - {4, "317AB72F4490", "B01327272DFD"}, + {1, "09125a2589e5", "F12C8453D821"}, + {2, "AB75C937922F", "73E799FE3241"}, + {3, "E27241AF2C09", "AA4D137656AE"}, + {4, "317AB72F4490", "B01327272DFD"}, } ---- +--- -- A debug printout-function local function dbg(args) if not DEBUG then return end if type(args) == "table" then - local i = 1 - while args[i] do - dbg(args[i]) - i = i+1 - end - else - print("###", args) - end -end ---- + local i = 1 + while args[i] do + dbg(args[i]) + i = i+1 + end + else + print("###", args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) - return nil,err + print("ERROR: ",err) + return nil,err end ---- +--- -- Usage help local function help() - print(copyright) - print(author) - print(version) - print(desc) - print("Example usage") - print(example) + print(copyright) + print(author) + print(version) + print(desc) + print("Example usage") + print(example) end -- -- Exit message local function exitMsg(msg) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print(msg) - print() + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() end -- -- dumps all keys to file local function dumptofile(keys) - dbg('dumping keys to file') + dbg('dumping keys to file') - if utils.confirm('Do you wish to save the keys to dumpfile?') then - local destination = utils.input('Select a filename to store to', 'dumpkeys.bin') - local file = io.open(destination, 'wb') - if file == nil then - print('Could not write to file ', destination) - return - end + if utils.confirm('Do you wish to save the keys to dumpfile?') then + local destination = utils.input('Select a filename to store to', 'dumpkeys.bin') + local file = io.open(destination, 'wb') + if file == nil then + print('Could not write to file ', destination) + return + end - -- Mifare Mini has 5 sectors, - local key_a = '' - local key_b = '' - - for sector = 0, #keys do - local keyA, keyB = unpack(keys[sector]) - key_a = key_a .. bin.pack('H', keyA); - key_b = key_b .. bin.pack('H', keyB); - end - file:write(key_a) - file:write(key_b) - file:close() - end + -- Mifare Mini has 5 sectors, + local key_a = '' + local key_b = '' + + for sector = 0, #keys do + local keyA, keyB = unpack(keys[sector]) + key_a = key_a .. bin.pack('H', keyA); + key_b = key_b .. bin.pack('H', keyB); + end + file:write(key_a) + file:write(key_b) + file:close() + end end --- -- key bytes to string local function keyStr(p1, p2, p3, p4, p5, p6) - return string.format('%02X%02X%02X%02X%02X%02X',p1, p2, p3, p4, p5, p6) + return string.format('%02X%02X%02X%02X%02X%02X',p1, p2, p3, p4, p5, p6) end --- -- create key local function calckey(uid, xorkey, keytype) - local p1,p2,p3,p4,p5,p6 - if keytype == 'A' then - p1 = bxor( uid[1], xorkey[1]) - p2 = bxor( uid[2], xorkey[2]) - p3 = bxor( uid[3], xorkey[3]) - p4 = bxor( uid[4], xorkey[4]) - p5 = bxor( uid[1], xorkey[5]) - p6 = bxor( uid[2], xorkey[6]) - else - p1 = bxor( uid[3], xorkey[1]) - p2 = bxor( uid[4], xorkey[2]) - p3 = bxor( uid[1], xorkey[3]) - p4 = bxor( uid[2], xorkey[4]) - p5 = bxor( uid[3], xorkey[5]) - p6 = bxor( uid[4], xorkey[6]) - end - return keyStr(p1,p2,p3,p4,p5,p6) -end + local p1,p2,p3,p4,p5,p6 + if keytype == 'A' then + p1 = bxor( uid[1], xorkey[1]) + p2 = bxor( uid[2], xorkey[2]) + p3 = bxor( uid[3], xorkey[3]) + p4 = bxor( uid[4], xorkey[4]) + p5 = bxor( uid[1], xorkey[5]) + p6 = bxor( uid[2], xorkey[6]) + else + p1 = bxor( uid[3], xorkey[1]) + p2 = bxor( uid[4], xorkey[2]) + p3 = bxor( uid[1], xorkey[3]) + p4 = bxor( uid[2], xorkey[4]) + p5 = bxor( uid[3], xorkey[5]) + p6 = bxor( uid[4], xorkey[6]) + end + return keyStr(p1,p2,p3,p4,p5,p6) +end --- -- print keys local function printKeys(keys) - print('|---|----------------|---|----------------|---|') - print('|sec|key A |res|key B |res|') - print('|---|----------------|---|----------------|---|') - for sector = 0, #keys do - local keyA, keyB = unpack(keys[sector]) - print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, 1, keyB, 1)) - end - print('|---|----------------|---|----------------|---|') + print('|---|----------------|---|----------------|---|') + print('|sec|key A |res|key B |res|') + print('|---|----------------|---|----------------|---|') + for sector = 0, #keys do + local keyA, keyB = unpack(keys[sector]) + print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, 1, keyB, 1)) + end + print('|---|----------------|---|----------------|---|') end --- -- create a full set of keys local function createKeys(uid) - local uidbytes = utils.ConvertHexToBytes(uid) - - local k = {} - k[0] = { keyStr(0xA0,0xA1,0xA2,0xA3,0xA4,0xA5), keyStr(0xB4,0xC1,0x32,0x43,0x9e,0xef) } + local uidbytes = utils.ConvertHexToBytes(uid) + + local k = {} + k[0] = { keyStr(0xA0,0xA1,0xA2,0xA3,0xA4,0xA5), keyStr(0xB4,0xC1,0x32,0x43,0x9e,0xef) } for _, v in pairs(_xortable) do - local keyA = calckey(uidbytes, utils.ConvertHexToBytes(v[2]), 'A') - local keyB = calckey(uidbytes, utils.ConvertHexToBytes(v[3]), 'B') - k[v[1]] = { keyA, keyB } - end - return k + local keyA = calckey(uidbytes, utils.ConvertHexToBytes(v[2]), 'A') + local keyB = calckey(uidbytes, utils.ConvertHexToBytes(v[3]), 'B') + k[v[1]] = { keyA, keyB } + end + return k end --- -- main local function main(args) - print( string.rep('==', 30) ) - print() - - local uid = '11223344' - local useUID = false - - -- Arguments for the script - for o, a in getopt.getopt(args, 'hu:') do - if o == "h" then return help() end - if o == "u" then uid = a ; useUID = true end - end + print( string.rep('==', 30) ) + print() - if useUID then - -- uid string checks - if uid == nil then return oops('empty uid string') end - if #uid == 0 then return oops('empty uid string') end - if #uid ~= 8 then return oops('uid wrong length. Should be 4 hex bytes') end - else - -- GET TAG UID - local tag, err = lib14a.read(false, true) - if not tag then return oops(err) end - core.clearCommandBuffer() + local uid = '11223344' + local useUID = false - -- simple tag check - if 0x09 ~= tag.sak then - if 0x4400 ~= tag.atqa then - return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name)) - end - end - uid = tag.uid - end - - print('|UID|', uid) - - local keys, err = createKeys( uid ) - printKeys( keys ) - dumptofile( keys ) + -- Arguments for the script + for o, a in getopt.getopt(args, 'hu:') do + if o == "h" then return help() end + if o == "u" then uid = a ; useUID = true end + end + + if useUID then + -- uid string checks + if uid == nil then return oops('empty uid string') end + if #uid == 0 then return oops('empty uid string') end + if #uid ~= 8 then return oops('uid wrong length. Should be 4 hex bytes') end + else + -- GET TAG UID + local tag, err = lib14a.read(false, true) + if not tag then return oops(err) end + core.clearCommandBuffer() + + -- simple tag check + if 0x09 ~= tag.sak then + if 0x4400 ~= tag.atqa then + return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name)) + end + end + uid = tag.uid + end + + print('|UID|', uid) + + local keys, err = createKeys( uid ) + printKeys( keys ) + dumptofile( keys ) end main(args) \ No newline at end of file diff --git a/client/scripts/calypso.lua b/client/scripts/calypso.lua index ce90a25fd..2b7252261 100644 --- a/client/scripts/calypso.lua +++ b/client/scripts/calypso.lua @@ -11,15 +11,15 @@ desc = This is a script to communicate with a CALYSPO / 14443b tag using the '14b raw' commands Arguments: - -b 123 -Examples : - script run f -b 11223344 - script run f + -b 123 +Examples : + script run f -b 11223344 + script run f -Examples : +Examples : # 1. Connect and don't disconnect -script run f +script run f # 2. Send mf auth, read response script run f # 3. disconnect @@ -28,56 +28,56 @@ script run f ]] --[[ -This script communicates with /armsrc/iso14443b.c, -Check there for details about data format and how commands are interpreted on the -device-side. +This script communicates with /armsrc/iso14443b.c, +Check there for details about data format and how commands are interpreted on the +device-side. ]] --- -- local function calypso_switch_on_field() - local flags = lib14b.ISO14B_COMMAND.ISO14B_CONNECT - local c = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags} - return lib14b.sendToDevice(c, true) + local flags = lib14b.ISO14B_COMMAND.ISO14B_CONNECT + local c = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags} + return lib14b.sendToDevice(c, true) end --- -- Disconnect (poweroff) the antenna forcing a disconnect of a 14b tag. local function calypso_switch_off_field() - local flags = lib14b.ISO14B_COMMAND.ISO14B_DISCONNECT - local c = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags} - return lib14b.sendToDevice(c, true) + local flags = lib14b.ISO14B_COMMAND.ISO14B_DISCONNECT + local c = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags} + return lib14b.sendToDevice(c, true) end local function calypso_parse(result) - local r = Command.parse(result) - local len = r.arg2 * 2 - r.data = string.sub(r.data, 0, len); - print('GOT:', r.data) - if r.arg1 == 0 then - return r, nil - end - return nil,nil + local r = Command.parse(result) + local len = r.arg2 * 2 + r.data = string.sub(r.data, 0, len); + print('GOT:', r.data) + if r.arg1 == 0 then + return r, nil + end + return nil,nil end ---- +--- -- A debug printout-function local function dbg(args) - if DEBUG then - print("###", args) - end -end ---- + if DEBUG then + print("###", args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ", err) - calypso_switch_off_field() - return nil, err + print("ERROR: ", err) + calypso_switch_off_field() + return nil, err end ---- +--- -- Usage help local function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end -- -- helper function, give current count of items in lua-table. @@ -87,7 +87,7 @@ local function tablelen(T) return count end --- --- helper function, gives a sorted table from table t, +-- helper function, gives a sorted table from table t, -- order can be a seperate sorting-order function. local function spairs(t, order) -- collect the keys @@ -95,7 +95,7 @@ local function spairs(t, order) for k in pairs(t) do keys[#keys+1] = k end -- if order function given, sort by it by passing the table and keys a, b, - -- otherwise just sort the keys + -- otherwise just sort the keys if order then table.sort(keys, function(a,b) return order(t, a, b) end) else @@ -112,54 +112,54 @@ local function spairs(t, order) end end --- --- Sends a usbpackage , "hf 14b raw" +-- Sends a usbpackage , "hf 14b raw" -- if it reads the response, it converts it to a lua object "Command" first and the Data is cut to correct length. local function calypso_send_cmd_raw(data, ignoreresponse ) - local command, flags, result, err - flags = lib14b.ISO14B_COMMAND.ISO14B_RAW + - lib14b.ISO14B_COMMAND.ISO14B_APPEND_CRC + local command, flags, result, err + flags = lib14b.ISO14B_COMMAND.ISO14B_RAW + + lib14b.ISO14B_COMMAND.ISO14B_APPEND_CRC - data = data or "00" + data = data or "00" - command = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, - arg1 = flags, - arg2 = #data/2, -- LEN of data, half the length of the ASCII-string hex string - arg3 = 0, - data = data} -- data bytes (commands etc) - result, err = lib14b.sendToDevice(command, false) - - if ignoreresponse then return response, err end - - if result then - local r = calypso_parse(result) - return r, nil - end - return respone, err + command = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, + arg1 = flags, + arg2 = #data/2, -- LEN of data, half the length of the ASCII-string hex string + arg3 = 0, + data = data} -- data bytes (commands etc) + result, err = lib14b.sendToDevice(command, false) + + if ignoreresponse then return response, err end + + if result then + local r = calypso_parse(result) + return r, nil + end + return respone, err end --- -- calypso_card_num : Reads card number from ATR and -- writes it in the tree in decimal format. local function calypso_card_num(card) - if not card then return end - local card_num = tonumber( card.uid:sub(1,8),16 ) - print('Card UID', card.uid) - print('Card Number', card_num) + if not card then return end + local card_num = tonumber( card.uid:sub(1,8),16 ) + print('Card UID', card.uid) + print('Card Number', card_num) end --- -- analyse CALYPSO apdu status bytes. local function calypso_apdu_status(apdu) - -- last two is CRC - -- next two is APDU status bytes. - local status = false - local mess = 'FAIL' - local sw = apdu:sub( #apdu-7, #apdu-4) - desc, err = iso7816.tostring(sw) - print ('SW', sw, desc, err ) + -- last two is CRC + -- next two is APDU status bytes. + local status = false + local mess = 'FAIL' + local sw = apdu:sub( #apdu-7, #apdu-4) + desc, err = iso7816.tostring(sw) + print ('SW', sw, desc, err ) - status = ( sw == '9000' ) - - return status + status = ( sw == '9000' ) + + return status end local _calypso_cmds = { @@ -167,16 +167,16 @@ local _calypso_cmds = { -- Break down of command bytes: -- A4 = select -- Master File 3F00 --- 0x3F = master file +-- 0x3F = master file -- 0x00 = master file id, is constant to 0x00. -- DF Dedicated File 38nn -- can be seen as directories --- 0x38 +-- 0x38 -- 0xNN id --- ["01.Select ICC file"] = '0294 a4 080004 3f00 0002', +-- ["01.Select ICC file"] = '0294 a4 080004 3f00 0002', --- EF Elementary File +-- EF Elementary File -- EF1 Pin file -- EF2 Key file -- Grey Lock file @@ -184,93 +184,93 @@ local _calypso_cmds = { -- Electronic Purse file -- Electronic Transaction log file - - --["01.Select ICC file"] = '0294 a4 00 0002 3f00', - ["01.Select ICC file"] = '0294 a4 080004 3f00 0002', - ["02.ICC"] = '0394 b2 01 041d', - ["03.Select EnvHol file"] = '0294 a4 080004 2000 2001', - ["04.EnvHol1"] = '0394 b2 01 041d', - ["05.Select EvLog file"] = '0294 a4 080004 2000 2010', - ["06.EvLog1"] = '0394 b2 01 041d', - ["07.EvLog2"] = '0294 b2 02 041d', - ["08.EvLog3"] = '0394 b2 03 041d', - ["09.Select ConList file"] ='0294 a4 080004 2000 2050', - ["10.ConList"] = '0394 b2 01 041d', - ["11.Select Contra file"] = '0294 a4 080004 2000 2020', - ["12.Contra1"] = '0394 b2 01 041d', - ["13.Contra2"] = '0294 b2 02 041d', - ["14.Contra3"] = '0394 b2 03 041d', - ["15.Contra4"] = '0294 b2 04 041d', - ["16.Select Counter file"]= '0394 a4 080004 2000 2069', - ["17.Counter"] = '0294 b2 01 041d', - ["18.Select SpecEv file"]= '0394 a4 080004 2000 2040', - ["19.SpecEv1"] = '0294 b2 01 041d', + + --["01.Select ICC file"] = '0294 a4 00 0002 3f00', + ["01.Select ICC file"] = '0294 a4 080004 3f00 0002', + ["02.ICC"] = '0394 b2 01 041d', + ["03.Select EnvHol file"] = '0294 a4 080004 2000 2001', + ["04.EnvHol1"] = '0394 b2 01 041d', + ["05.Select EvLog file"] = '0294 a4 080004 2000 2010', + ["06.EvLog1"] = '0394 b2 01 041d', + ["07.EvLog2"] = '0294 b2 02 041d', + ["08.EvLog3"] = '0394 b2 03 041d', + ["09.Select ConList file"]= '0294 a4 080004 2000 2050', + ["10.ConList"] = '0394 b2 01 041d', + ["11.Select Contra file"] = '0294 a4 080004 2000 2020', + ["12.Contra1"] = '0394 b2 01 041d', + ["13.Contra2"] = '0294 b2 02 041d', + ["14.Contra3"] = '0394 b2 03 041d', + ["15.Contra4"] = '0294 b2 04 041d', + ["16.Select Counter file"]= '0394 a4 080004 2000 2069', + ["17.Counter"] = '0294 b2 01 041d', + ["18.Select SpecEv file"] = '0394 a4 080004 2000 2040', + ["19.SpecEv1"] = '0294 b2 01 041d', } ---- +--- -- The main entry point function main(args) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print() - - local data, apdu, flags, uid, cid, result, err, card - -- Read the parameters - for o, a in getopt.getopt(args, 'h') do - if o == "h" then return help() end - end - - calypso_switch_on_field() - - -- Select 14b tag. - card, err = lib14b.waitFor14443b() - if not card then return oops(err) end - - calypso_card_num(card) - cid = card.cid + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print() - --[[ - NAME VALUE APDU_POS - PCB 0x0A 0 - CID 0x00 1 - CLA 0x94 2 - SELECT FILE 0xA4 3 - READ FILE 0xB2 3 - P1 4 - P2 5 - LEN_ - 0 1 2 3 4 5 6 7 - apdu = '02 94 a4 08 00 04 3f 00 00 02' --select ICC file - DF_NAME = "1TIC.ICA" - --]] - --for i = 1,10 do - --result, err = calypso_send_cmd_raw('0294a40800043f000002',false) --select ICC file - for i, apdu in spairs(_calypso_cmds) do - print('>>', i ) - apdu = apdu:gsub("%s+","") - result, err = calypso_send_cmd_raw(apdu , false) - if result then - calypso_apdu_status(result.data) - print('<<', result.data ) - else - print('<< no answer') - end - end - calypso_switch_off_field() + local data, apdu, flags, uid, cid, result, err, card + -- Read the parameters + for o, a in getopt.getopt(args, 'h') do + if o == "h" then return help() end + end + + calypso_switch_on_field() + + -- Select 14b tag. + card, err = lib14b.waitFor14443b() + if not card then return oops(err) end + + calypso_card_num(card) + cid = card.cid + + --[[ + NAME VALUE APDU_POS + PCB 0x0A 0 + CID 0x00 1 + CLA 0x94 2 + SELECT FILE 0xA4 3 + READ FILE 0xB2 3 + P1 4 + P2 5 + LEN_ + 0 1 2 3 4 5 6 7 + apdu = '02 94 a4 08 00 04 3f 00 00 02' --select ICC file + DF_NAME = "1TIC.ICA" + --]] + --for i = 1,10 do + --result, err = calypso_send_cmd_raw('0294a40800043f000002',false) --select ICC file + for i, apdu in spairs(_calypso_cmds) do + print('>>', i ) + apdu = apdu:gsub("%s+","") + result, err = calypso_send_cmd_raw(apdu , false) + if result then + calypso_apdu_status(result.data) + print('<<', result.data ) + else + print('<< no answer') + end + end + calypso_switch_off_field() end --- --- a simple selftest function, tries to convert +-- a simple selftest function, tries to convert function selftest() - DEBUG = true - dbg("Performing test") - dbg("Tests done") + DEBUG = true + dbg("Performing test") + dbg("Tests done") end --- Flip the switch here to perform a sanity check. +-- Flip the switch here to perform a sanity check. -- It read a nonce in two different ways, as specified in the usage-section -if "--test"==args then - selftest() -else - -- Call the main - main(args) +if "--test"==args then + selftest() +else + -- Call the main + main(args) end \ No newline at end of file diff --git a/client/scripts/cmdline.lua b/client/scripts/cmdline.lua index 9c4df1446..29627afc7 100644 --- a/client/scripts/cmdline.lua +++ b/client/scripts/cmdline.lua @@ -1,12 +1,12 @@ print("This is how a cmd-line interface could be implemented\nPrint 'exit' to exit.\n") local answer repeat - io.write("$>") - io.flush() - answer=io.read() - if answer ~= 'exit' then - local func = assert(loadstring("return " .. answer)) - io.write("\n"..tostring(func() or "").."\n"); - end--]] -until answer=="exit" + io.write("$>") + io.flush() + answer=io.read() + if answer ~= 'exit' then + local func = assert(loadstring("return " .. answer)) + io.write("\n"..tostring(func() or "").."\n"); + end--]] +until answer=="exit" print("Bye\n"); diff --git a/client/scripts/didump.lua b/client/scripts/didump.lua index b63d2ed07..b6bc03a11 100644 --- a/client/scripts/didump.lua +++ b/client/scripts/didump.lua @@ -1,4 +1,4 @@ ---- +--- -- requirements local cmds = require('commands') local getopt = require('getopt') @@ -8,9 +8,9 @@ local json = require('dkjson') local toys = require('default_toys_di') example =[[ - script run didump - script run didump -t - script run didump -r + script run didump + script run didump -t + script run didump -r ]] author = "Iceman" usage = "script run didump -h -t" @@ -18,9 +18,9 @@ desc = [[ This is a script to dump and decrypt the data of a specific type of Mifare Mini token. The dump is decrypted. If a raw dump is wanted, use the -r parameter Arguments: - -h : this help - -r : raw - -t : selftest + -h : this help + -r : raw + -t : selftest ]] local band=bit32.band @@ -40,50 +40,50 @@ local numBlocks = 20 local numSectors = 5 local CHECKSUM_OFFSET = 12; -- +1??? ---- +--- -- A debug printout-function local function dbg(args) if not DEBUG then return end - if type(args) == "table" then - local i = 1 - while args[i] do - print("###", args[i]) - i = i+1 - end - else - print("###", args) - end -end ---- + if type(args) == "table" then + local i = 1 + while args[i] do + print("###", args[i]) + i = i+1 + end + else + print("###", args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) - core.clearCommandBuffer() - return false + print("ERROR: ",err) + core.clearCommandBuffer() + return false end ---- +--- -- Usage help local function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end --- -- local function print_info(tagdata) - --got table with data. - local h = tagdata[2]:sub(1,8) - local t = tostring( tonumber( h, 16 ) ) - local item = toys.Find(t) - print( ("Modelid : %s , %s, v.%s.0"):format(t, item[3], item[2])) + --got table with data. + local h = tagdata[2]:sub(1,8) + local t = tostring( tonumber( h, 16 ) ) + local item = toys.Find(t) + print( ("Modelid : %s , %s, v.%s.0"):format(t, item[3], item[2])) end --- -- Get checksum, -- called: data is string (32 hex digits) -- returns: number local function getChecksum(data) - local chksum = data:sub(25,32) - return tonumber(chksum,16) + local chksum = data:sub(25,32) + return tonumber(chksum,16) end --- -- calculate checksum @@ -91,8 +91,8 @@ end -- returns: number local function calculateChecksum(data) - -- Generate table - local _tbl = {} + -- Generate table + local _tbl = {} _tbl[0] = { 0x0 } _tbl[1] = { 0x77073096 } _tbl[2] = { 0xEE0E612C } @@ -351,248 +351,248 @@ _tbl[254] = { 0x5A05DF1B } _tbl[255] = { 0x2D02EF8D } - -- Calculate it - local ret = 0 - for i,item in pairs(data) do - local tmp = band(ret, 0xFF) - local index = band( bxor(tmp, item), 0xFF) - ret = bxor(rsh(ret,8), _tbl[index][1]) - end - return ret + -- Calculate it + local ret = 0 + for i,item in pairs(data) do + local tmp = band(ret, 0xFF) + local index = band( bxor(tmp, item), 0xFF) + ret = bxor(rsh(ret,8), _tbl[index][1]) + end + return ret end --- -- update checksum -- called: data is string, ( >= 24 hex digits ) -- returns: string, (data concat new checksum) local function updateChecksum(data) - local part = data:sub(1,24) - local chksum = calculateChecksum( utils.ConvertHexToBytes(part)) - return string.format("%s%X", part, chksum) + local part = data:sub(1,24) + local chksum = calculateChecksum( utils.ConvertHexToBytes(part)) + return string.format("%s%X", part, chksum) end --- -- receives the answer from deviceside, used with a readblock command local function waitCmd() - local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) - if response then - local count,cmd,arg0 = bin.unpack('LL',response) - if(arg0==1) then - local count,arg1,arg2,data = bin.unpack('LLH511',response,count) - return data:sub(1,32) - else - return nil, "Couldn't read block.." - end - end - return nil, "No response from device" + local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) + if response then + local count,cmd,arg0 = bin.unpack('LL',response) + if(arg0==1) then + local count,arg1,arg2,data = bin.unpack('LLH511',response,count) + return data:sub(1,32) + else + return nil, "Couldn't read block.." + end + end + return nil, "No response from device" end local function keygen(uid) - local data = MIS..uid..BAR - local hash = utils.ConvertAsciiToBytes(utils.Sha1Hex(data)) - return string.format("%02X%02X%02X%02X%02X%02X", - hash[3+1], - hash[2+1], - hash[1+1], - hash[0+1], - hash[7+1], - hash[6+1] - ) + local data = MIS..uid..BAR + local hash = utils.ConvertAsciiToBytes(utils.Sha1Hex(data)) + return string.format("%02X%02X%02X%02X%02X%02X", + hash[3+1], + hash[2+1], + hash[1+1], + hash[0+1], + hash[7+1], + hash[6+1] + ) end --- encode 'table' into a json formatted string --- +-- local function convert_to_json( obj ) - if type(obj) == "table" then - return json.encode (obj, { indent = true }) - end - return oops('[fail] input object must be a lua-TABLE') + if type(obj) == "table" then + return json.encode (obj, { indent = true }) + end + return oops('[fail] input object must be a lua-TABLE') end -- --- Save +-- Save local function save_json(filename, data) - jsondata = convert_to_json(data) - filename = filename or 'dumpdata.json' - local f = io.open(filename, "w") - if not f then return oops(string.format("Could not write to file %s", tostring(filename))) end - f:write(jsondata) - io.close(f) - return filename + jsondata = convert_to_json(data) + filename = filename or 'dumpdata.json' + local f = io.open(filename, "w") + if not f then return oops(string.format("Could not write to file %s", tostring(filename))) end + f:write(jsondata) + io.close(f) + return filename end ---- loads a json formatted text file with +--- loads a json formatted text file with -- -- @param filename the file containing the json-dump (defaults to dumpdata.json) local function load_json(filename) - filename = filename or 'dumpdata.json' - local f = io.open(filename, "rb") - if not f then return oops(string.format("Could not read file %s", tostring(filename))) end - - -- Read file - local t = f:read("*all") - io.close(f) + filename = filename or 'dumpdata.json' + local f = io.open(filename, "rb") + if not f then return oops(string.format("Could not read file %s", tostring(filename))) end - local obj, pos, err = json.decode(t, 1, nil) - if err then return oops(string.format("importing json file failed. %s", err)) end + -- Read file + local t = f:read("*all") + io.close(f) - dbg(string.format('loaded file %s', input)) - return obj + local obj, pos, err = json.decode(t, 1, nil) + if err then return oops(string.format("importing json file failed. %s", err)) end --- local len, hex = bin.unpack( ("H%d"):format(#t), t) + dbg(string.format('loaded file %s', input)) + return obj + +-- local len, hex = bin.unpack( ("H%d"):format(#t), t) end --- -- Generate encryption key local function create_key(uid) - local key = '' - local sha = utils.Sha1Hex( FOO..BAR..uid ) - sha = utils.ConvertBytesToHex( utils.ConvertAsciiToBytes(sha:sub(1,16)) ) - key = utils.SwapEndiannessStr( sha:sub(1,8) , 32 ) - key = key..utils.SwapEndiannessStr( sha:sub(9,16), 32 ) - key = key..utils.SwapEndiannessStr( sha:sub(17,24), 32 ) - key = key..utils.SwapEndiannessStr( sha:sub(25,32), 32 ) - return key + local key = '' + local sha = utils.Sha1Hex( FOO..BAR..uid ) + sha = utils.ConvertBytesToHex( utils.ConvertAsciiToBytes(sha:sub(1,16)) ) + key = utils.SwapEndiannessStr( sha:sub(1,8) , 32 ) + key = key..utils.SwapEndiannessStr( sha:sub(9,16), 32 ) + key = key..utils.SwapEndiannessStr( sha:sub(17,24), 32 ) + key = key..utils.SwapEndiannessStr( sha:sub(25,32), 32 ) + return key end --- reads all blocks from tag -- local function readtag(mfkey, aeskey ) - - local tagdata = {} - - for blockNo = 0, numBlocks-1 do - if core.ukbhit() then - print("[fail] aborted by user") - return nil - end + local tagdata = {} - -- read block from tag. - cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = mfkey} - local err = core.SendCommand(cmd:getBytes()) - if err then return oops(err) end - local blockdata, err = waitCmd() - if err then return oops(err) end + for blockNo = 0, numBlocks-1 do - -- rules: - -- the following blocks is NOT encrypted - -- block 0 (manufacturing) and 18 - -- block with all zeros - -- sector trailor - if blockNo == 0 or blockNo == 18 then - - elseif blockNo%4 ~= 3 then - - if not string.find(blockdata, '^0+$') then - if aeskey then - local decrypted, err = core.aes128_decrypt_ecb(aeskey, blockdata) - if err then dbg(err) end - blockdata = utils.ConvertAsciiToHex(decrypted) - end - end - else - -- Sectorblocks, not encrypted, but we add our known key to it since it is normally zeros. - blockdata = mfkey..blockdata:sub(13,20)..mfkey - --dbg(blockdata:sub(13,20)) - end - table.insert(tagdata, blockdata) - end - return tagdata + if core.ukbhit() then + print("[fail] aborted by user") + return nil + end + + -- read block from tag. + cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = mfkey} + local err = core.SendCommand(cmd:getBytes()) + if err then return oops(err) end + local blockdata, err = waitCmd() + if err then return oops(err) end + + -- rules: + -- the following blocks is NOT encrypted + -- block 0 (manufacturing) and 18 + -- block with all zeros + -- sector trailor + if blockNo == 0 or blockNo == 18 then + + elseif blockNo%4 ~= 3 then + + if not string.find(blockdata, '^0+$') then + if aeskey then + local decrypted, err = core.aes128_decrypt_ecb(aeskey, blockdata) + if err then dbg(err) end + blockdata = utils.ConvertAsciiToHex(decrypted) + end + end + else + -- Sectorblocks, not encrypted, but we add our known key to it since it is normally zeros. + blockdata = mfkey..blockdata:sub(13,20)..mfkey + --dbg(blockdata:sub(13,20)) + end + table.insert(tagdata, blockdata) + end + return tagdata end --- -- simple selftest of functionality local function selftest() - local testdata = '000F42430D0A14000001D11F'..'5D738517' - local chksum = getChecksum(testdata) - local calc = calculateChecksum( utils.ConvertHexToBytes(testdata:sub(1,24))) - print ( testdata:sub(1,24) ) - print ( ('%x - %x'):format(chksum, calc)) - - local isValid = false - local validStr = "FAIL" - if calc == chksum then - isValid = true - validStr = "OK" - end - local newtestdata = updateChecksum(testdata) - local revalidated = "FAIL" - if newtestdata == testdata then - revalidated = "OK" - end - print ('TESTDATA :: '..testdata) - print ('DATA :: '..testdata:sub(1,24)) - print (('VALID CHKSUM :: %s'):format(validStr )) - print (('UPDATE CHKSUM :: %s'):format(revalidated)) - - local testkey = keygen('0456263a873a80') - print ('TEST KEY :: '..testkey) - print ('VALID KEY :: 29564af75805') + local testdata = '000F42430D0A14000001D11F'..'5D738517' + local chksum = getChecksum(testdata) + local calc = calculateChecksum( utils.ConvertHexToBytes(testdata:sub(1,24))) + print ( testdata:sub(1,24) ) + print ( ('%x - %x'):format(chksum, calc)) + + local isValid = false + local validStr = "FAIL" + if calc == chksum then + isValid = true + validStr = "OK" + end + local newtestdata = updateChecksum(testdata) + local revalidated = "FAIL" + if newtestdata == testdata then + revalidated = "OK" + end + print ('TESTDATA :: '..testdata) + print ('DATA :: '..testdata:sub(1,24)) + print (('VALID CHKSUM :: %s'):format(validStr )) + print (('UPDATE CHKSUM :: %s'):format(revalidated)) + + local testkey = keygen('0456263a873a80') + print ('TEST KEY :: '..testkey) + print ('VALID KEY :: 29564af75805') end local function setdevicedebug( status ) - local c = 'hf mf dbg ' - if status then - c = c..'1' - else - c = c..'0' - end - core.console(c) + local c = 'hf mf dbg ' + if status then + c = c..'1' + else + c = c..'0' + end + core.console(c) end ---- +--- -- The main entry point -- -d decrypt -- -e encrypt -- -v validate function main(args) - local cmd, tag, err, blockNo, mfkey - local shall_validate = false - local shall_dec = false - local shall_enc = false - local blocks = {} - local aeskey = '' - local input = '' - - -- Read the parameters - for o, a in getopt.getopt(args, 'htdevi:') do - if o == "h" then help() return end - if o == "t" then return selftest() end - if o == "d" then shall_dec = true end - if o == "e" then shall_enc = true end - if o == "v" then shall_validate = true end - if o == "i" then input = load_json(a) end - end + local cmd, tag, err, blockNo, mfkey + local shall_validate = false + local shall_dec = false + local shall_enc = false + local blocks = {} + local aeskey = '' + local input = '' - -- Turn off Debug - setdevicedebug(false) + -- Read the parameters + for o, a in getopt.getopt(args, 'htdevi:') do + if o == "h" then help() return end + if o == "t" then return selftest() end + if o == "d" then shall_dec = true end + if o == "e" then shall_enc = true end + if o == "v" then shall_validate = true end + if o == "i" then input = load_json(a) end + end - -- GET TAG UID - tag, err = lib14a.read(false, true) - if not tag then return oops(err) end - core.clearCommandBuffer() - - -- simple tag check - if 0x09 ~= tag.sak then - if 0x4400 ~= tag.atqa then - return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name)) - end - end - dbg ('[ok] found '..tag.name) - - -- tag key - mfkey = keygen(tag.uid) - dbg('[ok] using mf keyA : '.. mfkey) - - -- AES key - aeskey = create_key(tag.uid) - dbg('[ok] using AES key : '.. aeskey) + -- Turn off Debug + setdevicedebug(false) - -- read tag data, complete, enc/dec - tagdata = readtag(mfkey, aeskey) - dbg('[ok] read card data') + -- GET TAG UID + tag, err = lib14a.read(false, true) + if not tag then return oops(err) end + core.clearCommandBuffer() - -- show information? - print_info(tagdata) + -- simple tag check + if 0x09 ~= tag.sak then + if 0x4400 ~= tag.atqa then + return oops(('[fail] found tag %s :: looking for Mifare Mini 0.3k'):format(tag.name)) + end + end + dbg ('[ok] found '..tag.name) - -- save - res = save_json(nil, tagdata) - if not res then return oops('[fail] saving json file') end - - dbg('[ok] read card data') + -- tag key + mfkey = keygen(tag.uid) + dbg('[ok] using mf keyA : '.. mfkey) + + -- AES key + aeskey = create_key(tag.uid) + dbg('[ok] using AES key : '.. aeskey) + + -- read tag data, complete, enc/dec + tagdata = readtag(mfkey, aeskey) + dbg('[ok] read card data') + + -- show information? + print_info(tagdata) + + -- save + res = save_json(nil, tagdata) + if not res then return oops('[fail] saving json file') end + + dbg('[ok] read card data') end main(args) diff --git a/client/scripts/dumptoemul-mfu.lua b/client/scripts/dumptoemul-mfu.lua index bb04008e9..34fbdc1d0 100644 --- a/client/scripts/dumptoemul-mfu.lua +++ b/client/scripts/dumptoemul-mfu.lua @@ -13,120 +13,120 @@ This script takes a dumpfile from 'hf mfu dump' and converts it to a format that 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. + -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. ]] local DEBUG = false ---- +--- -- A debug printout-function local function dbg(args) - if not DEBUG then return end - - if type(args) == 'table' then - local i = 1 - while result[i] do - dbg(result[i]) - i = i+1 - end - else - print('###', args) - end -end ---- + if not DEBUG then return end + + if type(args) == 'table' then + local i = 1 + while result[i] do + dbg(result[i]) + i = i+1 + end + else + print('###', args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print('ERROR: ',err) - return nil,err + print('ERROR: ',err) + return nil,err end ---- +--- -- Usage help function help() - print(desc) - print(author) - print("Example usage") - print(example) + print(desc) + print(author) + 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 + 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 + 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") - len = string.len(t) - local len,hex = bin.unpack(("H%d"):format(len),t) - return hex + t = infile:read("*all") + len = string.len(t) + local len,hex = bin.unpack(("H%d"):format(len),t) + 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, -2) + 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, -2) end local function main(args) - local input = "dumpdata.bin" - local output + 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, + 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 - -- But first, check the uid - -- lua uses start index and endindex, not count. - -- UID is 3three skip bcc0 then 4bytes. - -- 1 lua is one-index. - -- 1 + 96 (48*2) new dump format has version/signature/counter data here - -- 97,98,99,100,101,102 UID first three bytes - -- 103,104 bcc0 - -- 105--- UID last four bytes - local uid = string.sub(dumpdata, 97, 97+5)..string.sub(dumpdata, 97+8, 97+8+7) - output = output or (uid .. ".eml") + 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, - -- Format some linebreaks - dumpdata = convert_to_emulform(dumpdata) + -- But first, check the uid + -- lua uses start index and endindex, not count. + -- UID is 3three skip bcc0 then 4bytes. + -- 1 lua is one-index. + -- 1 + 96 (48*2) new dump format has version/signature/counter data here + -- 97,98,99,100,101,102 UID first three bytes + -- 103,104 bcc0 + -- 105--- UID last four bytes + local uid = string.sub(dumpdata, 97, 97+5)..string.sub(dumpdata, 97+8, 97+8+7) + output = output or (uid .. ".eml") - 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)) + -- 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 +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. +compatibility, I have done so, but I invoke my main from here. --]] main(args) diff --git a/client/scripts/dumptoemul.lua b/client/scripts/dumptoemul.lua index 1e4d6323a..08e5e03dd 100644 --- a/client/scripts/dumptoemul.lua +++ b/client/scripts/dumptoemul.lua @@ -11,117 +11,117 @@ This script takes a dumpfile from 'hf mf dump' and converts it to a format that 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. + -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. ]] local DEBUG = false ------------------------------- --- Some utilities +-- Some utilities ------------------------------- ---- +--- -- A debug printout-function local function dbg(args) - if not DEBUG then return end - - if type(args) == 'table' then - local i = 1 - while result[i] do - dbg(result[i]) - i = i+1 - end - else - print('###', args) - end -end ---- + if not DEBUG then return end + + if type(args) == 'table' then + local i = 1 + while result[i] do + dbg(result[i]) + i = i+1 + end + else + print('###', args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print('ERROR: ',err) - return nil,err + print('ERROR: ',err) + return nil,err end ---- +--- -- Usage help function help() - print(desc) - print(author) - print("Example usage") - print(example) + print(desc) + print(author) + print("Example usage") + print(example) end local function convert_to_ascii(hexdata) - if string.len(hexdata) % 32 ~= 0 then - return oops(("Bad data, length should be a multiple of 32 (was %d)"):format(string.len(hexdata))) - end + if string.len(hexdata) % 32 ~= 0 then + return oops(("Bad data, length should be a multiple of 32 (was %d)"):format(string.len(hexdata))) + end - local js,i = "["; - for i = 1, string.len(hexdata),32 do - js = js .."'" ..string.sub(hexdata,i,i+31).."',\n" - end - js = js .. "]" - return js + local js,i = "["; + for i = 1, string.len(hexdata),32 do + js = js .."'" ..string.sub(hexdata,i,i+31).."',\n" + end + js = js .. "]" + return js end local function readdump(infile) - t = infile:read("*all") - len = string.len(t) - local len,hex = bin.unpack(("H%d"):format(len),t) - return hex + t = infile:read("*all") + len = string.len(t) + local len,hex = bin.unpack(("H%d"):format(len),t) + return hex end local function convert_to_emulform(hexdata) - if string.len(hexdata) % 32 ~= 0 then - return oops(("Bad data, length should be a multiple of 32 (was %d)"):format(string.len(hexdata))) - end - local ascii,i = ""; - for i = 1, string.len(hexdata),32 do - ascii = ascii..string.sub(hexdata,i,i+31).."\n" - end - return string.sub(ascii, 1, -2) + if string.len(hexdata) % 32 ~= 0 then + return oops(("Bad data, length should be a multiple of 32 (was %d)"):format(string.len(hexdata))) + end + local ascii,i = ""; + for i = 1, string.len(hexdata),32 do + ascii = ascii..string.sub(hexdata,i,i+31).."\n" + end + return string.sub(ascii, 1, -2) end local function main(args) - local input = "dumpdata.bin" - local output + 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, + 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 - -- But first, check the uid - local uid = string.sub(dumpdata,1,8) - output = output or (uid .. ".eml") + 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, - -- Format some linebreaks - dumpdata = convert_to_emulform(dumpdata) + -- But first, check the uid + local uid = string.sub(dumpdata,1,8) + output = output or (uid .. ".eml") - 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)) + -- 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 +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. +compatibility, I have done so, but I invoke my main from here. --]] main(args) diff --git a/client/scripts/e.lua b/client/scripts/e.lua index 4e032337e..6b9d80364 100644 --- a/client/scripts/e.lua +++ b/client/scripts/e.lua @@ -5,73 +5,73 @@ example = "script calculates many different checksums (CRC) over the provided he author = "Iceman" desc = [[ -This script calculates many checksums (CRC) over the provided hex input. +This script calculates many checksums (CRC) over the provided hex input. Arguments: - -b data in hex - -w bitwidth of the CRC family of algorithm. defaults to all known CRC presets. -Examples : - script run e -b 010203040506070809 - script run e -b 010203040506070809 -w 16 + -b data in hex + -w bitwidth of the CRC family of algorithm. defaults to all known CRC presets. +Examples : + script run e -b 010203040506070809 + script run e -b 010203040506070809 -w 16 ]] ---- +--- -- A debug printout-function function dbg(args) - if DEBUG then - print("###", args) - end -end ---- + if DEBUG then + print("###", args) + end +end +--- -- This is only meant to be used when errors occur function oops(err) - print("[!] ERROR: ",err) - return nil,err + print("[!] ERROR: ",err) + return nil,err end ---- +--- -- Usage help function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end ---- +--- -- The main entry point function main(args) - local data - local width = 0 + local data + local width = 0 - -- Read the parameters - for o, a in getopt.getopt(args, 'hb:w:') do - if o == "h" then return help() end - if o == "b" then data = a end - if o == "w" then width = a end - end + -- Read the parameters + for o, a in getopt.getopt(args, 'hb:w:') do + if o == "h" then return help() end + if o == "b" then data = a end + if o == "w" then width = a end + end - data = data or '01020304' - width = width or 0 - - print( string.rep('-',60) ) - print('Bit width of CRC | '..width) - print('Bytes | '..data) - print('') - print( ('%-20s| %-16s| %s'):format('Model','CRC', 'CRC reverse','bigEnd', 'bigEnd','little','little')) - print( string.rep('-',60) ) - local lists, err = core.reveng_models(width) - if lists == nil then return oops(err) end - - for _,i in pairs(lists) do - if string.len(i) > 1 then - local a1 = core.reveng_runmodel(i, data, false, '0') - local a2 = core.reveng_runmodel(i, data, true, '0') - local a3 = core.reveng_runmodel(i, data, false, 'b') - local a4 = core.reveng_runmodel(i, data, false, 'B') - local a5 = core.reveng_runmodel(i, data, false, 'l') - local a6 = core.reveng_runmodel(i, data, false, 'L') - print( ('%-20s| %-16s| %-16s| %-16s| %-16s| %-16s| %-16s'):format(i, a1:upper(), a2:upper(),a3:upper(),a4:upper(),a5:upper(),a6:upper() ) ) - end - end + data = data or '01020304' + width = width or 0 + + print( string.rep('-',60) ) + print('Bit width of CRC | '..width) + print('Bytes | '..data) + print('') + print( ('%-20s| %-16s| %s'):format('Model','CRC', 'CRC reverse','bigEnd', 'bigEnd','little','little')) + print( string.rep('-',60) ) + local lists, err = core.reveng_models(width) + if lists == nil then return oops(err) end + + for _,i in pairs(lists) do + if string.len(i) > 1 then + local a1 = core.reveng_runmodel(i, data, false, '0') + local a2 = core.reveng_runmodel(i, data, true, '0') + local a3 = core.reveng_runmodel(i, data, false, 'b') + local a4 = core.reveng_runmodel(i, data, false, 'B') + local a5 = core.reveng_runmodel(i, data, false, 'l') + local a6 = core.reveng_runmodel(i, data, false, 'L') + print( ('%-20s| %-16s| %-16s| %-16s| %-16s| %-16s| %-16s'):format(i, a1:upper(), a2:upper(),a3:upper(),a4:upper(),a5:upper(),a6:upper() ) ) + end + end end main(args) \ No newline at end of file diff --git a/client/scripts/emul2dump.lua b/client/scripts/emul2dump.lua index 315ad99ab..04b9da12b 100644 --- a/client/scripts/emul2dump.lua +++ b/client/scripts/emul2dump.lua @@ -1,60 +1,60 @@ -local getopt = require('getopt') -local bin = require('bin') -local dumplib = require('html_dumplib') - -example =[[ - 1. script run emul2dump - 2. script run emul2dump -i myfile.eml - 3. script run emul2dump -i myfile.eml -o myfile.bin -]] -author = "Iceman" -usage = "script run emul2dump [-i ] [-o ]" -desc =[[ -This script takes an dumpfile on EML (ASCII) format and converts it to the PM3 dumpbin file to be used with "hf mf restore" - -Arguments: - -h This help - -i Specifies the dump-file (input). If omitted, 'dumpdata.eml' is used - -o Specifies the output file. If omitted, .bin is used. -]] - ---- --- 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 --- --- Exit message -function ExitMsg(msg) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print(msg) - print() -end - -local function main(args) - - local input = "dumpdata.eml" - local output = os.date("%Y-%m-%d_%H%M%S.bin"); - - -- Arguments for the script - for o, a in getopt.getopt(args, 'hi:o:') do - if o == "h" then return help() end - if o == "i" then input = a end - if o == "o" then output = a end - end - - local filename, err = dumplib.convert_eml_to_bin(input,output) - if err then return oops(err) end - - ExitMsg(("Wrote a BIN dump to the file %s"):format(filename)) -end - +local getopt = require('getopt') +local bin = require('bin') +local dumplib = require('html_dumplib') + +example =[[ + 1. script run emul2dump + 2. script run emul2dump -i myfile.eml + 3. script run emul2dump -i myfile.eml -o myfile.bin +]] +author = "Iceman" +usage = "script run emul2dump [-i ] [-o ]" +desc =[[ +This script takes an dumpfile on EML (ASCII) format and converts it to the PM3 dumpbin file to be used with "hf mf restore" + +Arguments: + -h This help + -i Specifies the dump-file (input). If omitted, 'dumpdata.eml' is used + -o Specifies the output file. If omitted, .bin is used. +]] + +--- +-- 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 +-- +-- Exit message +function ExitMsg(msg) + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() +end + +local function main(args) + + local input = "dumpdata.eml" + local output = os.date("%Y-%m-%d_%H%M%S.bin"); + + -- Arguments for the script + for o, a in getopt.getopt(args, 'hi:o:') do + if o == "h" then return help() end + if o == "i" then input = a end + if o == "o" then output = a end + end + + local filename, err = dumplib.convert_eml_to_bin(input,output) + if err then return oops(err) end + + ExitMsg(("Wrote a BIN dump to the file %s"):format(filename)) +end + main(args) \ No newline at end of file diff --git a/client/scripts/emul2html.lua b/client/scripts/emul2html.lua index 52d4dacb0..db76ec9c0 100644 --- a/client/scripts/emul2html.lua +++ b/client/scripts/emul2html.lua @@ -8,60 +8,60 @@ example = "script run emul2html -o dumpdata.eml " author = "Martin Holst Swende" usage = "script run htmldump [-i ] [-o ]" desc =[[ -This script takes a dumpfile on EML (ASCII) format and produces a html based dump, which is a -bit more easily analyzed. +This script takes a dumpfile on EML (ASCII) format and produces a html based dump, which is a +bit more easily analyzed. Arguments: - -h This help - -i Specifies the dump-file (input). If omitted, 'dumpdata.eml' is used - -o Speciies the output file. If omitted, .html is used. + -h This help + -i Specifies the dump-file (input). If omitted, 'dumpdata.eml' is used + -o Speciies the output file. If omitted, .html is used. ]] ------------------------------- --- Some utilities +-- Some utilities ------------------------------- ---- +--- -- A debug printout-function function dbg(args) - if DEBUG then - print("###", args) - end -end ---- + if DEBUG then + print("###", args) + end +end +--- -- This is only meant to be used when errors occur function oops(err) - print("ERROR: ",err) + print("ERROR: ",err) end ---- +--- -- Usage help function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end local function main(args) - local input = "dumpdata.eml" - local output = os.date("%Y-%m-%d_%H%M%S.html"); - 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 - local filename, err = dumplib.convert_eml_to_html(input,output) - if err then return oops(err) end + local input = "dumpdata.eml" + local output = os.date("%Y-%m-%d_%H%M%S.html"); + 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 + local filename, err = dumplib.convert_eml_to_html(input,output) + if err then return oops(err) end - print(("Wrote a HTML dump to the file %s"):format(filename)) + print(("Wrote a HTML dump to the file %s"):format(filename)) end --[[ -In the future, we may implement so that scripts are invoked directly +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. +compatibility, I have done so, but I invoke my main from here. --]] main(args) \ No newline at end of file diff --git a/client/scripts/formatMifare.lua b/client/scripts/formatMifare.lua index 35475db84..90801b2a2 100644 --- a/client/scripts/formatMifare.lua +++ b/client/scripts/formatMifare.lua @@ -1,216 +1,216 @@ -local cmds = require('commands') -local getopt = require('getopt') -local bin = require('bin') -local lib14a = require('read14a') -local utils = require('utils') - -example = [[ - -- generate commands - 1. script run formatMifare - - -- generate command, replacing key with new key. - 2. script run formatMifare -k aabbccddeeff -n 112233445566 -a FF0780 - - -- generate commands and excute them against card. - 3. script run formatMifare -x -]] -copyright = '' -version = '' -author = 'Iceman' -usage = [[ - script run formatMifare -k -n -a -x -]] -desc = [[ -This script will generate 'hf mf wrbl' commands for each block to format a Mifare card. - -Alla datablocks gets 0x00 -As default the script sets the keys A/B to 0xFFFFFFFFFFFF -and the access bytes will become 0x78,0x77,0x88 -The GDB will become 0x00 - -The script will skip the manufactoring block 0. - - -Arguments: - -h - this help - -k - the current six byte key with write access - -n - the new key that will be written to the card - -a - the new access bytes that will be written to the card - -x - execute the commands aswell. -]] -local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds -local DEBUG = true -- the debug flag -local CmdString = 'hf mf wrbl %d B %s %s' -local numBlocks = 64 -local numSectors = 16 ---- --- A debug printout-function -function dbg(args) - if not DEBUG then - return - end - - if type(args) == "table" then - local i = 1 - while result[i] do - dbg(result[i]) - i = i+1 - end - else - 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(copyright) - print(author) - print(version) - print(desc) - print("Example usage") - print(example) -end --- --- Exit message -function ExitMsg(msg) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print(msg) - print() -end --- --- Read information from a card -function GetCardInfo() - result, err = lib14a.read(false, true) - if not result then - print(err) - return - end - print(("Found: %s"):format(result.name)) - - core.clearCommandBuffer() - - if 0x18 == result.sak then -- NXP MIFARE Classic 4k | Plus 4k - -- IFARE Classic 4K offers 4096 bytes split into forty sectors, - -- of which 32 are same size as in the 1K with eight more that are quadruple size sectors. - numSectors = 40 - elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k - -- 1K offers 1024 bytes of data storage, split into 16 sector - numSectors = 16 - elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k - -- MIFARE Classic mini offers 320 bytes split into five sectors. - numSectors = 5 - elseif 0x10 == result.sak then -- NXP MIFARE Plus 2k - numSectors = 32 - elseif 0x01 == result.sak then -- NXP MIFARE TNP3xxx 1K - numSectors = 16 - else - print("I don't know how many sectors there are on this type of card, defaulting to 16") - end - --[[ - The mifare Classic 1k card has 16 sectors of 4 data blocks each. - The first 32 sectors of a mifare Classic 4k card consists of 4 data blocks and the remaining - 8 sectors consist of 16 data blocks. - --]] - - -- Defaults to 16 * 4 = 64 - 1 = 63 - numBlocks = numSectors * 4 - 1 - - if numSectors > 32 then - numBlocks = 32*4+ (numSectors-32)*16 -1 - end - -end - -local function main(args) - - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print() - - local OldKey, NewKey, Accessbytes - local x = false - - -- Arguments for the script - for o, a in getopt.getopt(args, 'hk:n:a:x') do - if o == "h" then return help() end - if o == "k" then OldKey = a end - if o == "n" then NewKey = a end - if o == "a" then Accessbytes = a end - if o == "x" then x = true end - end - - -- validate input args. - OldKey = OldKey or 'FFFFFFFFFFFF' - if #(OldKey) ~= 12 then - return oops( string.format('Wrong length of write key (was %d) expected 12', #OldKey)) - end - - NewKey = NewKey or 'FFFFFFFFFFFF' - if #(NewKey) ~= 12 then - return oops( string.format('Wrong length of new key (was %d) expected 12', #NewKey)) - end - - --Accessbytes = Accessbytes or '787788' - Accessbytes = Accessbytes or 'FF0780' - if #(Accessbytes) ~= 6 then - return oops( string.format('Wrong length of accessbytes (was %d) expected 12', #Accessbytes)) - end - - GetCardInfo() - - -- Show info - print( string.format('Estimating number of blocks: %d', numBlocks)) - print( string.format('Old key: %s', OldKey)) - print( string.format('New key: %s', NewKey)) - print( string.format('New Access: %s', Accessbytes)) - print( string.rep('--',20) ) - - -- Set new block data - local EMPTY_BL = string.rep('00',16) - local EMPTY_SECTORTRAIL = string.format('%s%s%s%s',NewKey,Accessbytes,'00',NewKey) - - dbg( string.format('New sector-trailer : %s',EMPTY_SECTORTRAIL)) - dbg( string.format('New emptyblock: %s',EMPTY_BL)) - dbg('') - - if x then - print('[Warning] you have used the EXECUTE parameter, which means this will run these commands against card.') - end - -- Ask - local dialogResult = utils.confirm("Do you want to erase this card") - if dialogResult == false then - return ExitMsg('Quiting it is then. Your wish is my command...') - end - - print( string.rep('--',20) ) - - -- main loop - for block=0,numBlocks,1 do - - local reminder = (block+1) % 4 - local cmd - if reminder == 0 then - cmd = CmdString:format(block, OldKey , EMPTY_SECTORTRAIL) - else - cmd = CmdString:format(block, OldKey , EMPTY_BL) - end - - if block ~= 0 then - print(cmd) - if x then core.console(cmd) end - end - - if core.ukbhit() then - print("aborted by user") - break - end - end -end - +local cmds = require('commands') +local getopt = require('getopt') +local bin = require('bin') +local lib14a = require('read14a') +local utils = require('utils') + +example = [[ + -- generate commands + 1. script run formatMifare + + -- generate command, replacing key with new key. + 2. script run formatMifare -k aabbccddeeff -n 112233445566 -a FF0780 + + -- generate commands and excute them against card. + 3. script run formatMifare -x +]] +copyright = '' +version = '' +author = 'Iceman' +usage = [[ + script run formatMifare -k -n -a -x +]] +desc = [[ +This script will generate 'hf mf wrbl' commands for each block to format a Mifare card. + +Alla datablocks gets 0x00 +As default the script sets the keys A/B to 0xFFFFFFFFFFFF +and the access bytes will become 0x78,0x77,0x88 +The GDB will become 0x00 + +The script will skip the manufactoring block 0. + + +Arguments: + -h - this help + -k - the current six byte key with write access + -n - the new key that will be written to the card + -a - the new access bytes that will be written to the card + -x - execute the commands aswell. +]] +local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds +local DEBUG = true -- the debug flag +local CmdString = 'hf mf wrbl %d B %s %s' +local numBlocks = 64 +local numSectors = 16 +--- +-- A debug printout-function +function dbg(args) + if not DEBUG then + return + end + + if type(args) == "table" then + local i = 1 + while result[i] do + dbg(result[i]) + i = i+1 + end + else + 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(copyright) + print(author) + print(version) + print(desc) + print("Example usage") + print(example) +end +-- +-- Exit message +function ExitMsg(msg) + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() +end +-- +-- Read information from a card +function GetCardInfo() + result, err = lib14a.read(false, true) + if not result then + print(err) + return + end + print(("Found: %s"):format(result.name)) + + core.clearCommandBuffer() + + if 0x18 == result.sak then -- NXP MIFARE Classic 4k | Plus 4k + -- IFARE Classic 4K offers 4096 bytes split into forty sectors, + -- of which 32 are same size as in the 1K with eight more that are quadruple size sectors. + numSectors = 40 + elseif 0x08 == result.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k + -- 1K offers 1024 bytes of data storage, split into 16 sector + numSectors = 16 + elseif 0x09 == result.sak then -- NXP MIFARE Mini 0.3k + -- MIFARE Classic mini offers 320 bytes split into five sectors. + numSectors = 5 + elseif 0x10 == result.sak then -- NXP MIFARE Plus 2k + numSectors = 32 + elseif 0x01 == result.sak then -- NXP MIFARE TNP3xxx 1K + numSectors = 16 + else + print("I don't know how many sectors there are on this type of card, defaulting to 16") + end + --[[ + The mifare Classic 1k card has 16 sectors of 4 data blocks each. + The first 32 sectors of a mifare Classic 4k card consists of 4 data blocks and the remaining + 8 sectors consist of 16 data blocks. + --]] + + -- Defaults to 16 * 4 = 64 - 1 = 63 + numBlocks = numSectors * 4 - 1 + + if numSectors > 32 then + numBlocks = 32*4+ (numSectors-32)*16 -1 + end + +end + +local function main(args) + + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print() + + local OldKey, NewKey, Accessbytes + local x = false + + -- Arguments for the script + for o, a in getopt.getopt(args, 'hk:n:a:x') do + if o == "h" then return help() end + if o == "k" then OldKey = a end + if o == "n" then NewKey = a end + if o == "a" then Accessbytes = a end + if o == "x" then x = true end + end + + -- validate input args. + OldKey = OldKey or 'FFFFFFFFFFFF' + if #(OldKey) ~= 12 then + return oops( string.format('Wrong length of write key (was %d) expected 12', #OldKey)) + end + + NewKey = NewKey or 'FFFFFFFFFFFF' + if #(NewKey) ~= 12 then + return oops( string.format('Wrong length of new key (was %d) expected 12', #NewKey)) + end + + --Accessbytes = Accessbytes or '787788' + Accessbytes = Accessbytes or 'FF0780' + if #(Accessbytes) ~= 6 then + return oops( string.format('Wrong length of accessbytes (was %d) expected 12', #Accessbytes)) + end + + GetCardInfo() + + -- Show info + print( string.format('Estimating number of blocks: %d', numBlocks)) + print( string.format('Old key: %s', OldKey)) + print( string.format('New key: %s', NewKey)) + print( string.format('New Access: %s', Accessbytes)) + print( string.rep('--',20) ) + + -- Set new block data + local EMPTY_BL = string.rep('00',16) + local EMPTY_SECTORTRAIL = string.format('%s%s%s%s',NewKey,Accessbytes,'00',NewKey) + + dbg( string.format('New sector-trailer : %s',EMPTY_SECTORTRAIL)) + dbg( string.format('New emptyblock: %s',EMPTY_BL)) + dbg('') + + if x then + print('[Warning] you have used the EXECUTE parameter, which means this will run these commands against card.') + end + -- Ask + local dialogResult = utils.confirm("Do you want to erase this card") + if dialogResult == false then + return ExitMsg('Quiting it is then. Your wish is my command...') + end + + print( string.rep('--',20) ) + + -- main loop + for block=0,numBlocks,1 do + + local reminder = (block+1) % 4 + local cmd + if reminder == 0 then + cmd = CmdString:format(block, OldKey , EMPTY_SECTORTRAIL) + else + cmd = CmdString:format(block, OldKey , EMPTY_BL) + end + + if block ~= 0 then + print(cmd) + if x then core.console(cmd) end + end + + if core.ukbhit() then + print("aborted by user") + break + end + end +end + main(args) \ No newline at end of file diff --git a/client/scripts/hf_read.lua b/client/scripts/hf_read.lua index 82655a364..7653e6e75 100644 --- a/client/scripts/hf_read.lua +++ b/client/scripts/hf_read.lua @@ -1,18 +1,18 @@ local reader = require('hf_reader') local function main(args) - print("WORK IN PROGRESS - not expected to be functional yet") - info, err = reader.waitForTag() + print("WORK IN PROGRESS - not expected to be functional yet") + info, err = reader.waitForTag() - if err then - print(err) - return - end - local k,v - print("Tag info") - for k,v in pairs(info) do - print(string.format(" %s : %s", tostring(k), tostring(v))) - end - return + if err then + print(err) + return + end + local k,v + print("Tag info") + for k,v in pairs(info) do + print(string.format(" %s : %s", tostring(k), tostring(v))) + end + return end main(args) \ No newline at end of file diff --git a/client/scripts/htmldump.lua b/client/scripts/htmldump.lua index 0299e13c5..40f3028b4 100644 --- a/client/scripts/htmldump.lua +++ b/client/scripts/htmldump.lua @@ -8,58 +8,58 @@ example = "script run htmldump -o mifarecard_foo.html" author = "Martin Holst Swende" usage = "script run htmldump [-i ] [-o ]" desc =[[ -This script takes a dumpfile and produces a html based dump, which is a -bit more easily analyzed. +This script takes a dumpfile and produces a html based dump, which is a +bit more easily analyzed. Arguments: - -h This help - -i Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used - -o Speciies the output file. If omitted, .html is used. + -h This help + -i Specifies the dump-file (input). If omitted, 'dumpdata.bin' is used + -o Speciies the output file. If omitted, .html is used. ]] ------------------------------- --- Some utilities +-- Some utilities ------------------------------- ---- +--- -- A debug printout-function function dbg(args) - if DEBUG then - print("###", args) - end -end ---- + if DEBUG then + print("###", args) + end +end +--- -- This is only meant to be used when errors occur function oops(err) - print("ERROR: ",err) + print("ERROR: ",err) end ---- +--- -- Usage help function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end local function main(args) - local input = "dumpdata.bin" - local output = os.date("%Y-%m-%d_%H%M%S.html"); - 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 - local filename, err = dumplib.convert_bin_to_html(input,output,16) - if err then return oops(err) end + local input = "dumpdata.bin" + local output = os.date("%Y-%m-%d_%H%M%S.html"); + 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 + local filename, err = dumplib.convert_bin_to_html(input,output,16) + if err then return oops(err) end - print(("Wrote a HTML dump to the file %s"):format(filename)) + print(("Wrote a HTML dump to the file %s"):format(filename)) end --[[ -In the future, we may implement so that scripts are invoked directly +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. +compatibility, I have done so, but I invoke my main from here. --]] main(args) \ No newline at end of file diff --git a/client/scripts/iso15_magic.lua b/client/scripts/iso15_magic.lua index 3923f2b1e..939c7a943 100644 --- a/client/scripts/iso15_magic.lua +++ b/client/scripts/iso15_magic.lua @@ -7,112 +7,112 @@ copyright = 'Copyright (c) 2018 IceSQL AB. All rights reserved.' author = 'Christian Herrmann' version = 'v1.0.4' desc = [[ -This script tries to set UID on a IS15693 SLIX magic card +This script tries to set UID on a IS15693 SLIX magic card Remember the UID ->MUST<- start with 0xE0 ]] example = [[ - -- ISO15693 slix magic tag + -- ISO15693 slix magic tag - script run iso15_magic -u E004013344556677 - - script run iso15_magic -u E004013344556677 -a + script run iso15_magic -u E004013344556677 + + script run iso15_magic -u E004013344556677 -a ]] usage = [[ script run iso15_magic -h -u Arguments: - -h : this help - -u : UID (16 hexsymbols) - -a : use offical pm3 repo ISO15 commands instead of iceman fork. + -h : this help + -u : UID (16 hexsymbols) + -a : use offical pm3 repo ISO15 commands instead of iceman fork. ]] local DEBUG = true ---- +--- -- A debug printout-function local function dbg(args) if not DEBUG then return end if type(args) == "table" then - local i = 1 - while args[i] do - dbg(args[i]) - i = i+1 - end - else - print("###", args) - end -end ---- + local i = 1 + while args[i] do + dbg(args[i]) + i = i+1 + end + else + print("###", args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) - return nil, err + print("ERROR: ",err) + return nil, err end ---- +--- -- Usage help local function help() - print(copyright) - print(author) - print(version) - print(desc) - print('Example usage') - print(example) + print(copyright) + print(author) + print(version) + print(desc) + print('Example usage') + print(example) end -- --- Set UID on magic command enabled on a ICEMAN based REPO local function magicUID_iceman(b0, b1) - print('Using backdoor Magic tag function') - core.console("hf 15 raw -2 -c 02213E00000000") - core.console("hf 15 raw -2 -c 02213F69960000") - core.console("hf 15 raw -2 -c 022138"..b1) - core.console("hf 15 raw -2 -c 022139"..b0) + print('Using backdoor Magic tag function') + core.console("hf 15 raw -2 -c 02213E00000000") + core.console("hf 15 raw -2 -c 02213F69960000") + core.console("hf 15 raw -2 -c 022138"..b1) + core.console("hf 15 raw -2 -c 022139"..b0) end -- --- Set UID on magic command enabled, OFFICAL REPO local function magicUID_offical(b0, b1) - print('Using backdoor Magic tag function OFFICAL REPO') - core.console("hf 15 cmd raw -c 02213E00000000") - core.console("hf 15 cmd raw -c 02213F69960000") - core.console("hf 15 cmd raw -c 022138"..b1) - core.console("hf 15 cmd raw -c 022139"..b0) + print('Using backdoor Magic tag function OFFICAL REPO') + core.console("hf 15 cmd raw -c 02213E00000000") + core.console("hf 15 cmd raw -c 02213F69960000") + core.console("hf 15 cmd raw -c 022138"..b1) + core.console("hf 15 cmd raw -c 022139"..b0) end ---- +--- -- The main entry point function main(args) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print() + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print() - local uid = 'E004013344556677' - local use_iceman = true - - -- Read the parameters - for o, a in getopt.getopt(args, 'hu:a') do - if o == "h" then return help() end - if o == "u" then uid = a end - if o == "a" then use_iceman = false end - end - - -- uid string checks - if uid == nil then return oops('empty uid string') end - if #uid == 0 then return oops('empty uid string') end - if #uid ~= 16 then return oops('uid wrong length. Should be 8 hex bytes') end + local uid = 'E004013344556677' + local use_iceman = true - local bytes = utils.ConvertHexToBytes(uid) - - local block0 = string.format('%02X%02X%02X%02X', bytes[4], bytes[3], bytes[2], bytes[1]) - local block1 = string.format('%02X%02X%02X%02X', bytes[8], bytes[7], bytes[6], bytes[5]) - - print('new UID | '..uid) - - core.clearCommandBuffer() - - if use_iceman then - magicUID_iceman(block0, block1) - else - magicUID_offical(block0, block1) - end + -- Read the parameters + for o, a in getopt.getopt(args, 'hu:a') do + if o == "h" then return help() end + if o == "u" then uid = a end + if o == "a" then use_iceman = false end + end + + -- uid string checks + if uid == nil then return oops('empty uid string') end + if #uid == 0 then return oops('empty uid string') end + if #uid ~= 16 then return oops('uid wrong length. Should be 8 hex bytes') end + + local bytes = utils.ConvertHexToBytes(uid) + + local block0 = string.format('%02X%02X%02X%02X', bytes[4], bytes[3], bytes[2], bytes[1]) + local block1 = string.format('%02X%02X%02X%02X', bytes[8], bytes[7], bytes[6], bytes[5]) + + print('new UID | '..uid) + + core.clearCommandBuffer() + + if use_iceman then + magicUID_iceman(block0, block1) + else + magicUID_offical(block0, block1) + end end main(args) diff --git a/client/scripts/legic.lua b/client/scripts/legic.lua index 264d4dfef..97fd64f11 100644 --- a/client/scripts/legic.lua +++ b/client/scripts/legic.lua @@ -3,7 +3,7 @@ if it don't works with you tag-layout - be so kind and let me know ;-) Tested on Tags with those Layouts: -(example) Legic-Prime Layout with 'Kaba Group Header' +(example) Legic-Prime Layout with 'Kaba Group Header' +----+----+----+----+----+----+----+----+ 0x00|MCD |MSN0|MSN1|MSN2|MCC | 60 | ea | 9f | +----+----+----+----+----+----+----+----+ @@ -31,7 +31,7 @@ UID = dec User-ID for online-Mapping kghC = crc8 over MCD + MSN0..MSN2 + UID -(example) Legic-Cash on MIM256/1024 tag' (37 bytes) +(example) Legic-Cash on MIM256/1024 tag' (37 bytes) +----+----+----+----+----+----+----+----+ 0x00|Seg0|Seg1|Seg2|Seg3|SegC|STP0|STP1|STP2| +----+----+----+----+----+----+----+----+ @@ -56,7 +56,7 @@ LRS = ID of the reader that changed the shadow balance (?? should be always the CV = Counter value for transactions CHK = crc16 over SHD + LRS + CV -(example) Legic-Prime Layout 'gantner unsegmented user-credential' +(example) Legic-Prime Layout 'gantner unsegmented user-credential' +----+----+----+----+----+----+----+----+ 0x00|MCD |MSN0|MSN1|MSN2|MCC | 60 | ea | 08 | +----+----+----+----+----+----+----+----+ @@ -73,7 +73,7 @@ Dat = Online-Mapping Data uCRC = crc8 over addr 0x00..0x03+0x07..0x0E -(example) Legic-Prime Layout 'gantner unsegmented Master-Token (IAM) with a stamp_len of 4' +(example) Legic-Prime Layout 'gantner unsegmented Master-Token (IAM) with a stamp_len of 4' +----+----+----+----+----+----+----+----+ 0x00|MCD |MSN0|MSN1|MSN2|MCC | 20 | f8 | 08 | +----+----+----+----+----+----+----+----+ @@ -224,16 +224,16 @@ local currency = { --- -- This is only meant to be used when errors occur function oops(err) - print(acred.."ERROR: "..acoff ,err) - return nil, err + print(acred.."ERROR: "..acoff ,err) + return nil, err end --- -- Usage help function help() - print(desc) - print("Version: "..version) - print("Example usage: "..example) + print(desc) + print("Version: "..version) + print("Example usage: "..example) end --- @@ -265,28 +265,28 @@ end --- -- xor single byte function xorme(hex, xor, index) - if ( index >= 23 ) then - return ('%02x'):format(bxor( tonumber(hex,16) , tonumber(xor,16) )) - else - return hex - end + if ( index >= 23 ) then + return ('%02x'):format(bxor( tonumber(hex,16) , tonumber(xor,16) )) + else + return hex + end end --- -- (de)obfuscate bytes function xorBytes(inBytes, crc) - local bytes = {} - for index = 1, #inBytes do - bytes[index] = xorme(inBytes[index], crc, index) - end - if (#inBytes == #bytes) then - -- replace crc - bytes[5] = string.sub(crc,-2) - return bytes - else - print("error: byte-count missmatch") - return false - end + local bytes = {} + for index = 1, #inBytes do + bytes[index] = xorme(inBytes[index], crc, index) + end + if (#inBytes == #bytes) then + -- replace crc + bytes[5] = string.sub(crc,-2) + return bytes + else + print("error: byte-count missmatch") + return false + end end --- @@ -317,9 +317,9 @@ end --- -- put a string into a bytes-table function str2bytes(s) - if (string.len(s)%2 ~= 0) then - return print("stamp should be a even hexstring e.g.: deadbeef or 0badc0de") - end + if (string.len(s)%2 ~= 0) then + return print("stamp should be a even hexstring e.g.: deadbeef or 0badc0de") + end local res={} for i=1, string.len(s), 2 do table.insert(res, string.sub(s,i,(i+1))) @@ -330,29 +330,29 @@ end --- -- put certain bytes into a new table function bytesToTable(bytes, bstart, bend) - local t={} - for i=0, (bend-bstart) do - t[i]=bytes[bstart+i] - end - return t + local t={} + for i=0, (bend-bstart) do + t[i]=bytes[bstart+i] + end + return t end --- -- read file into table function getInputBytes(infile) - local line - local bytes = {} - local fhi,err = io.open(infile,"rb") - if err then oops("faild to read from file ".. infile); return false; end + local line + local bytes = {} + local fhi,err = io.open(infile,"rb") + if err then oops("faild to read from file ".. infile); return false; end - file_data = fhi:read("*a"); - for i = 1, #file_data do - bytes[i] = string.format("%x",file_data:byte(i)) - end - fhi:close() - if (bytes[7]=='00') then return false end - print(#bytes .. " bytes from "..infile.." loaded") - return bytes + file_data = fhi:read("*a"); + for i = 1, #file_data do + bytes[i] = string.format("%x",file_data:byte(i)) + end + fhi:close() + if (bytes[7]=='00') then return false end + print(#bytes .. " bytes from "..infile.." loaded") + return bytes end --- @@ -385,7 +385,7 @@ end --- -- put bytes into tag-table function bytesToTag(bytes, tag) - if istable(tag) == false then return oops("tag is no table in: bytesToTag ("..type(tag)..")") end + if istable(tag) == false then return oops("tag is no table in: bytesToTag ("..type(tag)..")") end tag.MCD =bytes[1]; tag.MSN0=bytes[2]; @@ -453,7 +453,7 @@ end --- -- read Tag-Table in bytes-table function tagToBytes(tag) - if istable(tag) == false then return oops("tag is no table in tagToBytes ("..type(tag)..")") end + if istable(tag) == false then return oops("tag is no table in tagToBytes ("..type(tag)..")") end local bytes = {} local i, i2 @@ -524,249 +524,249 @@ end --- -- write virtual Tag to real Tag function writeToTag(tag) - local bytes - local filename = 'MylegicClone.hex' - local taglen = 22 - if(utils.confirm(acred.."\nplace the (empty) Tag onto the PM3\nand confirm writing to this Tag: "..acoff) == false) then - return - end - - -- get used bytes / tag-len - if (istable(tag.SEG)) then - if (istable(tag.Bck)) then - for i=0, #tag.SEG do - taglen = taglen + tag.SEG[i] . len + 5 - end - end - local uid_old = tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2 - - -- read new tag into memory so we can xor the new data with the new MCC - outTAG = readFromPM3() - outbytes = tagToBytes(outTAG) - -- copy 'inputbuffer' to 'outputbuffer' - tag.MCD = outbytes[1] - tag.MSN0 = outbytes[2] - tag.MSN1 = outbytes[3] - tag.MSN2 = outbytes[4] - tag.MCC = outbytes[5] - -- recheck all segments-crc/kghcrc (only on a credential) - if (istable(tag.Bck)) then - checkAllSegCrc(tag) - checkAllKghCrc(tag) - local uid_new = tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2 - for i=0, #tag.SEG do - if (check43rdPartyCash1(uid_old, tag.SEG[i].data)) then - io.write(accyan.."\nfixing known checksums"..acoff.." ... ") - if (fix3rdPartyCash1(uid_new, tag.SEG[i].data)) then - io.write(acgreen.." done\n"..acoff) - else - oops("\nsomething went wrong at the repair of the 3rd-party-cash-segment") - end - end - end - end - bytes = tagToBytes(tag) - -- master-token-crc - if (tag.Type ~= "SAM") then - bytes[22] = calcMtCrc(bytes) - end - if (bytes) then - print("write temp-file '"..filename.."'") - print(accyan) - writeFile(bytes, filename..".bin") - print(acoff) - end - end + local bytes + local filename = 'MylegicClone.hex' + local taglen = 22 + if(utils.confirm(acred.."\nplace the (empty) Tag onto the PM3\nand confirm writing to this Tag: "..acoff) == false) then + return + end - -- write data to file - if (taglen > 0) then - WriteBytes = utils.input(acyellow.."enter number of bytes to write?"..acoff, taglen) - -- load file into pm3-buffer - if (type(filename) ~= "string") then - filename = input(acyellow.."filename to load to pm3-buffer?"..acoff, "legic.temp") - end - - cmd = 'hf legic eload 2 '..filename - core.console(cmd) - -- write pm3-buffer to Tag - for i=0, WriteBytes do - if (i > 6) then - cmd = ("hf legic write o %x d %s "):format(i, padString(bytes[i])) - print(acgreen..cmd..acoff) - core.console(cmd) - core.clearCommandBuffer() - elseif (i == 6) then - -- write DCF in reverse order (requires 'mosci-patch') - cmd = ('hf legic write o 05 d %s%s'):format(padString(bytes[i-1]), padString(bytes[i])) - print(acgreen..cmd..acoff) - core.console(cmd) - core.clearCommandBuffer() - elseif (i == 5) then - print(acgreen.."skip byte 0x05 - will be written next step"..acoff) - else - print(acgreen.."skip byte 0x00-0x04 - unwritable area"..acoff) - end - utils.Sleep(0.2) - end - end + -- get used bytes / tag-len + if (istable(tag.SEG)) then + if (istable(tag.Bck)) then + for i=0, #tag.SEG do + taglen = taglen + tag.SEG[i] . len + 5 + end + end + local uid_old = tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2 + + -- read new tag into memory so we can xor the new data with the new MCC + outTAG = readFromPM3() + outbytes = tagToBytes(outTAG) + -- copy 'inputbuffer' to 'outputbuffer' + tag.MCD = outbytes[1] + tag.MSN0 = outbytes[2] + tag.MSN1 = outbytes[3] + tag.MSN2 = outbytes[4] + tag.MCC = outbytes[5] + -- recheck all segments-crc/kghcrc (only on a credential) + if (istable(tag.Bck)) then + checkAllSegCrc(tag) + checkAllKghCrc(tag) + local uid_new = tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2 + for i=0, #tag.SEG do + if (check43rdPartyCash1(uid_old, tag.SEG[i].data)) then + io.write(accyan.."\nfixing known checksums"..acoff.." ... ") + if (fix3rdPartyCash1(uid_new, tag.SEG[i].data)) then + io.write(acgreen.." done\n"..acoff) + else + oops("\nsomething went wrong at the repair of the 3rd-party-cash-segment") + end + end + end + end + bytes = tagToBytes(tag) + -- master-token-crc + if (tag.Type ~= "SAM") then + bytes[22] = calcMtCrc(bytes) + end + if (bytes) then + print("write temp-file '"..filename.."'") + print(accyan) + writeFile(bytes, filename..".bin") + print(acoff) + end + end + + -- write data to file + if (taglen > 0) then + WriteBytes = utils.input(acyellow.."enter number of bytes to write?"..acoff, taglen) + -- load file into pm3-buffer + if (type(filename) ~= "string") then + filename = input(acyellow.."filename to load to pm3-buffer?"..acoff, "legic.temp") + end + + cmd = 'hf legic eload 2 '..filename + core.console(cmd) + -- write pm3-buffer to Tag + for i=0, WriteBytes do + if (i > 6) then + cmd = ("hf legic write o %x d %s "):format(i, padString(bytes[i])) + print(acgreen..cmd..acoff) + core.console(cmd) + core.clearCommandBuffer() + elseif (i == 6) then + -- write DCF in reverse order (requires 'mosci-patch') + cmd = ('hf legic write o 05 d %s%s'):format(padString(bytes[i-1]), padString(bytes[i])) + print(acgreen..cmd..acoff) + core.console(cmd) + core.clearCommandBuffer() + elseif (i == 5) then + print(acgreen.."skip byte 0x05 - will be written next step"..acoff) + else + print(acgreen.."skip byte 0x00-0x04 - unwritable area"..acoff) + end + utils.Sleep(0.2) + end + end end --- File I/O --- --- -- read file into virtual-tag local function readFile(filename) - print(accyan) - local bytes = {} - local tag = {} - if file_check(filename) == false then - return oops("input file: "..filename.." not found") - end + print(accyan) + local bytes = {} + local tag = {} + if file_check(filename) == false then + return oops("input file: "..filename.." not found") + end - bytes = getInputBytes(filename) + bytes = getInputBytes(filename) - if bytes == false then return oops('couldnt get input bytes') end + if bytes == false then return oops('couldnt get input bytes') end - -- make plain bytes - bytes = xorBytes(bytes,bytes[5]) - print("create virtual tag from ".. #bytes .. " bytes") - -- create Tag for plain bytes - tag = createTagTable() - -- load plain bytes to tag-table - print(acoff) - tag = bytesToTag(bytes, tag) + -- make plain bytes + bytes = xorBytes(bytes,bytes[5]) + print("create virtual tag from ".. #bytes .. " bytes") + -- create Tag for plain bytes + tag = createTagTable() + -- load plain bytes to tag-table + print(acoff) + tag = bytesToTag(bytes, tag) - return tag + return tag end --- -- write bytes to file function writeFile(bytes, filename) - if (filename ~= 'MylegicClone.hex') then - if (file_check(filename)) then - local answer = confirm("\nthe output-file "..filename.." already exists!\nthis will delete the previous content!\ncontinue?") - if not answer then return print("user abort") end - end - end - local line - local bcnt = 0 - local fho, err = io.open(filename, "w") - if err then - return oops("OOps ... failed to open output-file ".. filename) - end - bytes = xorBytes(bytes, bytes[5]) - for i = 1, #bytes do - if (bcnt == 0) then - line = bytes[i] - elseif (bcnt <= 7) then - line = line.." "..bytes[i] - end - if (bcnt == 7) then - -- write line to new file - fho:write(line.."\n") - -- reset counter & line - bcnt = -1 - line = "" - end - bcnt = bcnt + 1 - end - fho:close() - print("\nwrote ".. #bytes .." bytes to " .. filename) - return true + if (filename ~= 'MylegicClone.hex') then + if (file_check(filename)) then + local answer = confirm("\nthe output-file "..filename.." already exists!\nthis will delete the previous content!\ncontinue?") + if not answer then return print("user abort") end + end + end + local line + local bcnt = 0 + local fho, err = io.open(filename, "w") + if err then + return oops("OOps ... failed to open output-file ".. filename) + end + bytes = xorBytes(bytes, bytes[5]) + for i = 1, #bytes do + if (bcnt == 0) then + line = bytes[i] + elseif (bcnt <= 7) then + line = line.." "..bytes[i] + end + if (bcnt == 7) then + -- write line to new file + fho:write(line.."\n") + -- reset counter & line + bcnt = -1 + line = "" + end + bcnt = bcnt + 1 + end + fho:close() + print("\nwrote ".. #bytes .." bytes to " .. filename) + return true end --- Map related --- --- -- make tagMap local function makeTagMap() - local tagMap = {} - if (#tagMap == 0) then - tagMap['name'] = input(accyan.."enter Name for this Map: "..acoff , "newTagMap") - tagMap['mappings'] = {} - tagMap['crc8'] = {} - -- insert fixed Tag-CRC - table.insert(tagMap.crc8, {name = 'TAG-CRC', pos = 5, seq = {1, 4}}) - tagMap['crc16'] = {} - end - print(accyan.."new tagMap created"..acoff) - return tagMap + local tagMap = {} + if (#tagMap == 0) then + tagMap['name'] = input(accyan.."enter Name for this Map: "..acoff , "newTagMap") + tagMap['mappings'] = {} + tagMap['crc8'] = {} + -- insert fixed Tag-CRC + table.insert(tagMap.crc8, {name = 'TAG-CRC', pos = 5, seq = {1, 4}}) + tagMap['crc16'] = {} + end + print(accyan.."new tagMap created"..acoff) + return tagMap end --- -- save mapping to file local function saveTagMap(map, filename) - if (string.len(filename)>0) then - if (file_check(filename)) then - local answer = confirm("\nthe output-file "..filename.." alredy exists!\nthis will delete the previous content!\ncontinue?") - if not answer then return print("user abort") end - end - end + if (string.len(filename)>0) then + if (file_check(filename)) then + local answer = confirm("\nthe output-file "..filename.." alredy exists!\nthis will delete the previous content!\ncontinue?") + if not answer then return print("user abort") end + end + end - local line - local fho,err = io.open(filename, "w") - if err then oops("OOps ... faild to open output-file ".. filename) end + local line + local fho,err = io.open(filename, "w") + if err then oops("OOps ... faild to open output-file ".. filename) end - -- write line to new file - for k, v in pairs(map) do - if (istable(v)) then - for k2, v2 in pairs(v) do - if (k == 'mappings') then - fho:write(k..","..k2..","..v2['name']..","..v2['start']..","..v2['end']..","..((v2['highlight']) and "1" or "0").."\n") - elseif (k == "crc8") then - local tmp = "" - tmp = k..","..k2..","..v2['name']..","..v2['pos'].."," - tmp=tmp..tbl2seqstr(v2['seq']) - fho:write(tmp.."\n") - end - end - else - fho:write(k..","..v.."\n") - end - end - fho:close() - return true + -- write line to new file + for k, v in pairs(map) do + if (istable(v)) then + for k2, v2 in pairs(v) do + if (k == 'mappings') then + fho:write(k..","..k2..","..v2['name']..","..v2['start']..","..v2['end']..","..((v2['highlight']) and "1" or "0").."\n") + elseif (k == "crc8") then + local tmp = "" + tmp = k..","..k2..","..v2['name']..","..v2['pos'].."," + tmp=tmp..tbl2seqstr(v2['seq']) + fho:write(tmp.."\n") + end + end + else + fho:write(k..","..v.."\n") + end + end + fho:close() + return true end --- -- toggle higligh local function toggleHighlight(tbl) - if (tbl['highlight']) then - tbl['highlight'] = false - else - tbl['highlight'] = true - end - return tbl + if (tbl['highlight']) then + tbl['highlight'] = false + else + tbl['highlight'] = true + end + return tbl end --- -- return table od seqence-string local function seqstr2tbl(seqstr) - local s = split(seqstr) - local res = {} - if (#s >= 1) then - for sk, sv in pairs(s) do - s2 = split(sv, '-') - if(#s2 == 2) then - table.insert(res, s2[1]) - table.insert(res, s2[2]) - end - end - end - return res + local s = split(seqstr) + local res = {} + if (#s >= 1) then + for sk, sv in pairs(s) do + s2 = split(sv, '-') + if(#s2 == 2) then + table.insert(res, s2[1]) + table.insert(res, s2[2]) + end + end + end + return res end --- -- return sequence-string from table local function tbl2seqstr(seqtbl) - local res = "" - if (istable(seqtbl)) then - for sk, sv in pairs(seqtbl) do - res = res..sv..((sk%2==0) and "," or "-") - end - if (string.sub(res, string.len(res))== ",") then - res = string.sub(res, 1, string.len(res)-1) - end - end - return res + local res = "" + if (istable(seqtbl)) then + for sk, sv in pairs(seqtbl) do + res = res..sv..((sk%2==0) and "," or "-") + end + if (string.sub(res, string.len(res))== ",") then + res = string.sub(res, 1, string.len(res)-1) + end + end + return res end --- @@ -778,18 +778,18 @@ function loadTagMap(filename) local line, fields local temp={} local offset=0 - if (file_check(filename)==false) then - return oops("input file: "..filename.." not found") - else - local fhi,err = io.open(filename) - while true do - line = fhi:read() - if line == nil then + if (file_check(filename)==false) then + return oops("input file: "..filename.." not found") + else + local fhi,err = io.open(filename) + while true do + line = fhi:read() + if line == nil then break else fields=split(line) end - if (#fields==2) then + if (#fields==2) then if (fields[1]=='offset') then offset=tonumber(fields[2],10) end @@ -823,9 +823,9 @@ function loadTagMap(filename) end table.insert(map.crc8, temp) end - end - fhi:close() - end + end + fhi:close() + end return map end @@ -1127,10 +1127,10 @@ function mapAllSegments(tag, tagMap) segs=getSegmentStats(bytes) if (istable(segs)) then for k, v in pairs(segs) do - -- wrp (write proteted) = byte 2 - WRP = tonumber(bytes[v['start']+2],16) - -- wrc (write control) - bit 4-6 of byte 3 - WRC = tonumber(bbit("0x"..bytes[v['start']+3],4,3),16) + -- wrp (write proteted) = byte 2 + WRP = tonumber(bytes[v['start']+2],16) + -- wrc (write control) - bit 4-6 of byte 3 + WRC = tonumber(bbit("0x"..bytes[v['start']+3],4,3),16) --tagMap=mapTokenData(tagMap, 'Segment '..("%02d"):format(v['index']).." HDR", v['start'], v['start']+3) tagMap=mapTokenData(tagMap, 'Segment '..("%02d"):format(v['index']).." CRC", v['start']+4, v['start']+4, true) table.insert(tagMap.crc8, {name = 'Segment '..("%02d"):format(v['index']).." CRC", pos=v['start']+4, seq={1,4,v['start'],v['start']+3}} ) @@ -1327,11 +1327,11 @@ function dumpTable(tab, header, tstart, tend) for i=tstart, tend do res=res..tab[i].." " end - if (#header == 0) then - return res - else - return (header.." #"..(tend-tstart+1).."\n"..res) - end + if (#header == 0) then + return res + else + return (header.." #"..(tend-tstart+1).."\n"..res) + end end --- @@ -1377,7 +1377,7 @@ end -- dump Legic-Cash data function dumpLegicCash(tag, x) - if istable(tag.SEG[x]) == false then return end + if istable(tag.SEG[x]) == false then return end io.write("in Segment "..tag.SEG[x].index.." :\n") print("--------------------------------\n\tLegic-Cash Values\n--------------------------------") @@ -1403,7 +1403,7 @@ function dumpLegicCash(tag, x) -- raw 3rd-party function print3rdPartyCash1(tag, x) - if istable(tag.SEG[x]) == false then return end + if istable(tag.SEG[x]) == false then return end local uid=tag.MCD..tag.MSN0..tag.MSN1..tag.MSN2 print("\n\t\tStamp : "..dumpTable(tag.SEG[x].data, "", 0 , 2)) @@ -1608,25 +1608,25 @@ function getSegmentData(bytes, start, index) if (bytes[start]) then local i -- #index - segment.index = index - -- flag = high nibble of byte 1 - segment.flag = string.sub(bytes[start+1],0,1) - -- valid = bit 6 of byte 1 - segment.valid = bbit("0x"..bytes[start+1],6,1) - -- last = bit 7 of byte 1 - segment.last = bbit("0x"..bytes[start+1],7,1) - -- len = (byte 0)+(bit0-3 of byte 1) + segment.index = index + -- flag = high nibble of byte 1 + segment.flag = string.sub(bytes[start+1],0,1) + -- valid = bit 6 of byte 1 + segment.valid = bbit("0x"..bytes[start+1],6,1) + -- last = bit 7 of byte 1 + segment.last = bbit("0x"..bytes[start+1],7,1) + -- len = (byte 0)+(bit0-3 of byte 1) segment.len = tonumber(bbit("0x"..bytes[start+1],0,4)..bytes[start],16) -- raw segment header segment.raw = {bytes[start], bytes[start+1], bytes[start+2], bytes[start+3]} - -- wrp (write proteted) = byte 2 - segment.WRP = tonumber(bytes[start+2],16) - -- wrc (write control) - bit 4-6 of byte 3 - segment.WRC = tonumber(bbit("0x"..bytes[start+3],4,3),16) - -- rd (read disabled) - bit 7 of byte 3 - segment.RD = tonumber(bbit("0x"..bytes[start+3],7,1),16) - -- crc byte 4 - segment.crc = bytes[start+4] + -- wrp (write proteted) = byte 2 + segment.WRP = tonumber(bytes[start+2],16) + -- wrc (write control) - bit 4-6 of byte 3 + segment.WRC = tonumber(bbit("0x"..bytes[start+3],4,3),16) + -- rd (read disabled) - bit 7 of byte 3 + segment.RD = tonumber(bbit("0x"..bytes[start+3],7,1),16) + -- crc byte 4 + segment.crc = bytes[start+4] -- segment-data starts at segment.len - segment.header - segment.crc for i=0, (segment.len-5) do segment.data[i]=bytes[start+5+i] @@ -1645,11 +1645,11 @@ function getSegmentStats(bytes) x=0 repeat local s={} - -- valid = bit 6 of byte 1 - sValid = bbit("0x"..bytes[sStart+1],6,1) - -- last = bit 7 of byte 1 - sLast = bbit("0x"..bytes[sStart+1],7,1) - -- len = (byte 0)+(bit0-3 of byte 1) + -- valid = bit 6 of byte 1 + sValid = bbit("0x"..bytes[sStart+1],6,1) + -- last = bit 7 of byte 1 + sLast = bbit("0x"..bytes[sStart+1],7,1) + -- len = (byte 0)+(bit0-3 of byte 1) sLen = tonumber(bbit("0x"..bytes[sStart+1],0,4)..bytes[sStart],16) --print("index: "..("%02d"):format(x).." Len: "..sLen.." start:"..sStart.." end: "..(sStart+sLen-1)) s['index']=x @@ -1721,18 +1721,18 @@ end --- -- edit Segment Data function editSegmentData(data) - io.write("\n") - if istable(data) == false then print("no Segment-Data found") end + io.write("\n") + if istable(data) == false then print("no Segment-Data found") end - local lc = check4LegicCash(data) + local lc = check4LegicCash(data) for i=0, #data-1 do - data[i]=input(accyan.."Data"..i..acoff..": ", data[i]) + data[i]=input(accyan.."Data"..i..acoff..": ", data[i]) end - if (lc) then - data = fixLegicCash(data) - end - return data + if (lc) then + data = fixLegicCash(data) + end + return data end --- @@ -2302,10 +2302,10 @@ function modifyMode() ["lf"] = function(x) if (type(x)=='string' and file_check(x)) then - filename = x + filename = x else - filename = input("enter filename: ", "legic.temp") - end + filename = input("enter filename: ", "legic.temp") + end inTAG=readFile(filename) -- check for existing tagMap if (file_check(filename..".map")) then @@ -2408,10 +2408,10 @@ function modifyMode() -- dump single segment ["ds"] = function(x) if (type(x)=="string" and string.len(x)>0) then - sel = tonumber(x,10) + sel = tonumber(x,10) else - sel = selectSegment(inTAG) - end + sel = selectSegment(inTAG) + end if (sel) then print("\n"..(dumpSegment(inTAG, sel) or acred.."no Segments available") ..acoff.."\n") end end, --- @@ -2423,9 +2423,9 @@ function modifyMode() if(istable(inTAG.SEG[0])) then inTAG=editSegment(inTAG, sel) inTAG.SEG[sel]=regenSegmentHeader(inTAG.SEG[sel]) - else - print(acyellow.."no Segments in Tag"..acoff) - end + else + print(acyellow.."no Segments in Tag"..acoff) + end end end, --- @@ -2481,15 +2481,15 @@ function modifyMode() ["tk"] = function(x) if (istable(inTAG) and istable(inTAG.SEG[0])) then if (type(x)=="string" and string.len(x)>0) then - sel = tonumber(x,10) - else - sel = selectSegment(inTAG) - end - if(inTAG.SEG[sel].kgh) then - inTAG.SEG[sel].kgh = false + sel = tonumber(x,10) else - inTAG.SEG[sel].kgh = true - end + sel = selectSegment(inTAG) + end + if(inTAG.SEG[sel].kgh) then + inTAG.SEG[sel].kgh = false + else + inTAG.SEG[sel].kgh = true + end end end, --- @@ -2508,10 +2508,10 @@ function modifyMode() ["xc"] = function(x) if (istable(inTAG) and istable(inTAG.SEG[0])) then if (type(x)=="string" and string.len(x)>0) then - sel = tonumber(x,10) + sel = tonumber(x,10) else - sel = selectSegment(inTAG) - end + sel = selectSegment(inTAG) + end print("k "..kghCrcCredentials(inTAG, sel)) end end, @@ -2519,10 +2519,10 @@ function modifyMode() -- fix legic-cash checksums ["flc"] = function(x) if (type(x)=="string" and string.len(x)>0) then - x = tonumber(x,10) + x = tonumber(x,10) else - x = selectSegment(inTAG) - end + x = selectSegment(inTAG) + end inTAG.SEG[x].data=fixLegicCash(inTAG.SEG[x].data) end, --- @@ -2540,8 +2540,8 @@ function modifyMode() print(string.format("User-Selected Index %02d", x)) else -- or try to find match - x = autoSelectSegment(inTAG, "legiccash") - end + x = autoSelectSegment(inTAG, "legiccash") + end -- dump it dumpLegicCash(inTAG, x) end, @@ -2555,8 +2555,8 @@ function modifyMode() print(string.format("User-Selected Index %02d", x)) else -- or try to find match - x = autoSelectSegment(inTAG, "3rdparty") - end + x = autoSelectSegment(inTAG, "3rdparty") + end if (istable(inTAG) and istable(inTAG.SEG[x]) and inTAG.SEG[x].len == 100) then uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2 if (check43rdPartyCash1(uid, inTAG.SEG[x].data)) then @@ -2574,8 +2574,8 @@ function modifyMode() print(string.format("User-Selected Index %02d", x)) else -- or try to find match - x = autoSelectSegment(inTAG, "3rdparty") - end + x = autoSelectSegment(inTAG, "3rdparty") + end print3rdPartyCash1(inTAG, x) end, --- @@ -2589,8 +2589,8 @@ function modifyMode() else -- or try to find match - x = autoSelectSegment(inTAG, "3rdparty") - end + x = autoSelectSegment(inTAG, "3rdparty") + end if (istable(inTAG) and istable(inTAG.SEG[x]) and inTAG.SEG[x].len == 100) then inTAG=edit3rdPartyCash1(inTAG, x) dump3rdPartyCash1(inTAG, x) @@ -2600,10 +2600,10 @@ function modifyMode() -- force fixing 3rd-party-checksums ["f3p"] = function(x) if(type(x)=="string" and string.len(x)>=2) then - x = tonumber(x, 10) - else - x = selectSegment(inTAG) - end + x = tonumber(x, 10) + else + x = selectSegment(inTAG) + end if (istable(inTAG.SEG[x])) then local uid=inTAG.MCD..inTAG.MSN0..inTAG.MSN1..inTAG.MSN2 inTAG.SEG[x].data=fix3rdPartyCash1(uid, inTAG.SEG[x].data) @@ -2613,10 +2613,10 @@ function modifyMode() -- get stamp from single segment ["gs"] = function(x) if(type(x)=="string" and string.len(x)>=2) then - x = tonumber(x, 10) + x = tonumber(x, 10) else - x = selectSegment(inTAG) - end + x = selectSegment(inTAG) + end local stamp=getSegmentStamp(inTAG.SEG[x]) print("Stamp : "..stamp) stamp=str2bytes(stamp) @@ -2663,8 +2663,8 @@ function modifyMode() elseif (type(actions[string.lower(string.sub(ic,0,1))])=='function') then actions[string.lower(string.sub(ic,0,1))](string.sub(ic,3)) else - actions.h('') - end + actions.h('') + end until (string.sub(ic,0,1)=="q") end @@ -2673,40 +2673,40 @@ end function main(args) -- set init colors/switch (can be toggled with 'tac' => 'toggle ansicolors') load_colors(colored_output) - if (#args == 0 ) then modifyMode() end + if (#args == 0 ) then modifyMode() end --- variables local inTAG, backupTAG, outTAG, outfile, interactive, crc, ofs, cfs, dfs - -- just a spacer for better readability + -- just a spacer for better readability print() --- parse arguments - for o, a in getopt.getopt(args, 'hrmi:do:c:') do + for o, a in getopt.getopt(args, 'hrmi:do:c:') do -- display help if o == "h" then return help(); end -- read tag from PM3 if o == "r" then inTAG=readFromPM3() end -- input file - if o == "i" then inTAG=readFile(a) end + if o == "i" then inTAG=readFile(a) end -- dump virtual-Tag if o == "d" then dfs=true end -- interacive modifying if o == "m" then - interactive = true - modifyMode() - end + interactive = true + modifyMode() + end -- xor (e.g. for clone or plain file) if o == "c" then - cfs = true - crc = a - end + cfs = true + crc = a + end -- output file - if o == "o" then - outfile = a - ofs = true - end + if o == "o" then + outfile = a + ofs = true + end end -- file conversion (output to file) - if ofs == false then return end + if ofs == false then return end -- dump infile / tag-read if (dfs) then diff --git a/client/scripts/legic_buffer2card.lua b/client/scripts/legic_buffer2card.lua index 845e8e8e5..68440b8ac 100644 --- a/client/scripts/legic_buffer2card.lua +++ b/client/scripts/legic_buffer2card.lua @@ -4,51 +4,51 @@ author = "Mosci" desc = [[ This is a script which writes value 0x01 to bytes from position 0x07 until 0xFF on a Legic Prime Tag (MIM256 or MIM1024) -(created with 'hf legic save my_dump.hex') - -optional arguments : - -h - Help text +(created with 'hf legic save my_dump.hex') -Examples : - script run legic_buffer2card +optional arguments : + -h - Help text + +Examples : + script run legic_buffer2card ]] local utils = require('utils') local getopt = require('getopt') ---- +--- -- This is only meant to be used when errors occur function oops(err) - print("ERROR: ",err) - return nil, err + print("ERROR: ",err) + return nil, err end ---- +--- -- Usage help function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end -- -- simple loop-write from 0x07 to 0xff function main() - -- parse arguments for the script - for o, a in getopt.getopt(args, 'h') do - if o == "h" then return help() end - end + -- parse arguments for the script + for o, a in getopt.getopt(args, 'h') do + if o == "h" then return help() end + end - local cmd = '' - local i - for i = 7, 255 do - cmd = ('hf legic write 0x%02x 0x01'):format(i) - print(cmd) - core.clearCommandBuffer() - core.console(cmd) - - -- got a 'cmd-buffer overflow' on my mac - so just wait a little - -- works without that pause on my linux-box - utils.Sleep(0.1) - end + local cmd = '' + local i + for i = 7, 255 do + cmd = ('hf legic write 0x%02x 0x01'):format(i) + print(cmd) + core.clearCommandBuffer() + core.console(cmd) + + -- got a 'cmd-buffer overflow' on my mac - so just wait a little + -- works without that pause on my linux-box + utils.Sleep(0.1) + end end main() diff --git a/client/scripts/lf_bulk.lua b/client/scripts/lf_bulk.lua index 7f02094b8..b4604bebb 100644 --- a/client/scripts/lf_bulk.lua +++ b/client/scripts/lf_bulk.lua @@ -12,59 +12,59 @@ Perform bulk enrollment of 26 bit H10301 style RFID Tags For more info, check the comments in the code ]] example = [[ - -- - script run lf_bulk.lua -f 1 -b 1000 -c 10 + -- + script run lf_bulk.lua -f 1 -b 1000 -c 10 ]] usage = [[ script run lf_bulk.lua -f facility -b base_id_num -c count Arguments: - -h : this help - -f : facility id - -b : starting card id - -c : count, number of cards to make + -h : this help + -f : facility id + -b : starting card id + -c : count, number of cards to make ]] local DEBUG = true --local bxor = bit32.bxor local bor = bit32.bor local lshift = bit32.lshift ---- +--- -- A debug printout-function local function dbg(args) if not DEBUG then return end if type(args) == "table" then - local i = 1 - while args[i] do - dbg(args[i]) - i = i+1 - end - else - print("###", args) - end -end ---- + local i = 1 + while args[i] do + dbg(args[i]) + i = i+1 + end + else + print("###", args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) - return nil,err + print("ERROR: ",err) + return nil,err end ---- +--- -- Usage help local function help() - print(copyright) - print(author) - print(version) - print(desc) - print('Example usage') - print(example) + print(copyright) + print(author) + print(version) + print(desc) + print('Example usage') + print(example) end --- -- Exit message local function exitMsg(msg) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print(msg) - print() + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() end --[[Implement a function to simply visualize the bitstream in a text format --This is especially helpful for troubleshooting bitwise math issues]]-- @@ -81,22 +81,22 @@ end --[[ Likely, I'm an idiot, but I couldn't find any parity functions in Lua - This can also be done with a combination of bitwise operations (in fact, + This can also be done with a combination of bitwise operations (in fact, is the canonically "correct" way to do it, but my brain doesn't just default to this and so counting some ones is good enough for me ]]-- local function evenparity(s) - local _, count = string.gsub(s, "1", "") - local p = count % 2 - if (p == 0) then - return false - else - return true - end + local _, count = string.gsub(s, "1", "") + local p = count % 2 + if (p == 0) then + return false + else + return true + end end - + local function isempty(s) - return s == nil or s == '' + return s == nil or s == '' end --[[ @@ -105,89 +105,89 @@ end hex. This should be easy enough to extend to non 26bit formats ]]-- local function cardHex(i, f) - fac = lshift(f, 16) - id = bor(i, fac) - stream = toBits(id, 24) + fac = lshift(f, 16) + id = bor(i, fac) + stream = toBits(id, 24) - --As the function defaults to even parity and returns a boolean, - --perform a 'not' function to get odd parity - high = evenparity(string.sub(stream,1,12)) and 1 or 0 - low = not evenparity(string.sub(stream,13)) and 1 or 0 - bits = bor( lshift(id, 1), low) - bits = bor( bits, lshift(high, 25)) + --As the function defaults to even parity and returns a boolean, + --perform a 'not' function to get odd parity + high = evenparity(string.sub(stream,1,12)) and 1 or 0 + low = not evenparity(string.sub(stream,13)) and 1 or 0 + bits = bor( lshift(id, 1), low) + bits = bor( bits, lshift(high, 25)) - --Since the lua library bit32 is (obviously) 32 bits and we need to - --encode 36 bits to properly do a 26 bit tag with the preamble we need - --to create a higher order and lower order component which we will - --then assemble in the return. The math above defines the proper - --encoding as per HID/Weigand/etc. These bit flips are due to the - --format length check on bit 38 (cmdlfhid.c:64) and - --bit 31 (cmdlfhid.c:66). - preamble = bor(0, lshift(1, 5)) - bits = bor(bits, lshift(1, 26)) + --Since the lua library bit32 is (obviously) 32 bits and we need to + --encode 36 bits to properly do a 26 bit tag with the preamble we need + --to create a higher order and lower order component which we will + --then assemble in the return. The math above defines the proper + --encoding as per HID/Weigand/etc. These bit flips are due to the + --format length check on bit 38 (cmdlfhid.c:64) and + --bit 31 (cmdlfhid.c:66). + preamble = bor(0, lshift(1, 5)) + bits = bor(bits, lshift(1, 26)) - return ("%04x%08x"):format(preamble, bits) + return ("%04x%08x"):format(preamble, bits) end --- -- main local function main(args) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print() - - if #args == 0 then return help() end - - --I really wish a better getopt function would be brought in supporting - --long arguments, but it seems this library was chosen for BSD style - --compatibility - for o, a in getopt.getopt(args, 'f:b:c:h') do - if o == 'h' then return help() end - if o == 'f' then - if isempty(a) then - print("You did not supply a facility code, using 0") - facility = 0 - else - facility = a - end - end - if o == 'b' then - if isempty(a) then return oops("You must supply the flag -b (base id)") end - baseid = a - end - if o == 'c' then - if isempty(a) then return oops("You must supply the flag -c (count)") end - count = a - end - end + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print() - --Due to my earlier complaints about how this specific getopt library - --works, specifying ":" does not enforce supplying a value, thus we - --need to do these checks all over again. - if isempty(baseid) then return oops("You must supply the flag -b (base id)") end - if isempty(count) then return oops("You must supply the flag -c (count)") end + if #args == 0 then return help() end - --If the facility ID is non specified, ensure we code it as zero - if isempty(facility) then - print("Using 0 for the facility code as -f was not supplied") - facility = 0 - end + --I really wish a better getopt function would be brought in supporting + --long arguments, but it seems this library was chosen for BSD style + --compatibility + for o, a in getopt.getopt(args, 'f:b:c:h') do + if o == 'h' then return help() end + if o == 'f' then + if isempty(a) then + print("You did not supply a facility code, using 0") + facility = 0 + else + facility = a + end + end + if o == 'b' then + if isempty(a) then return oops("You must supply the flag -b (base id)") end + baseid = a + end + if o == 'c' then + if isempty(a) then return oops("You must supply the flag -c (count)") end + count = a + end + end - --The next baseid + count function presents a logic/UX conflict - --where users specifying -c 1 (count = 1) would try to program two - --tags. This makes it so that -c 0 & -c 1 both code one tag, and all - --other values encode the expected amount. - if tonumber(count) > 0 then count = count - 1 end + --Due to my earlier complaints about how this specific getopt library + --works, specifying ":" does not enforce supplying a value, thus we + --need to do these checks all over again. + if isempty(baseid) then return oops("You must supply the flag -b (base id)") end + if isempty(count) then return oops("You must supply the flag -c (count)") end - endid = baseid + count + --If the facility ID is non specified, ensure we code it as zero + if isempty(facility) then + print("Using 0 for the facility code as -f was not supplied") + facility = 0 + end - for cardnum = baseid, endid do - local card = cardHex(cardnum, facility) - print("Press enter to program card "..cardnum..":"..facility.." (hex: "..card..")") - --This would be better with "press any key", but we'll take what we can get. - io.read() - core.console( ('lf hid clone %s'):format(card) ) - end + --The next baseid + count function presents a logic/UX conflict + --where users specifying -c 1 (count = 1) would try to program two + --tags. This makes it so that -c 0 & -c 1 both code one tag, and all + --other values encode the expected amount. + if tonumber(count) > 0 then count = count - 1 end + + endid = baseid + count + + for cardnum = baseid, endid do + local card = cardHex(cardnum, facility) + print("Press enter to program card "..cardnum..":"..facility.." (hex: "..card..")") + --This would be better with "press any key", but we'll take what we can get. + io.read() + core.console( ('lf hid clone %s'):format(card) ) + end end main(args) \ No newline at end of file diff --git a/client/scripts/mfkeys.lua b/client/scripts/mfkeys.lua index 085390526..18078b822 100644 --- a/client/scripts/mfkeys.lua +++ b/client/scripts/mfkeys.lua @@ -1,12 +1,12 @@ --[[ - This is an example of Lua-scripting within proxmark3. This is a lua-side - implementation of hf mf chk + This is an example of Lua-scripting within proxmark3. This is a lua-side + implementation of hf mf chk - This code is licensed to you under the terms of the GNU GPL, version 2 or, - at your option, any later version. See the LICENSE.txt file for the text of - the license. + This code is licensed to you under the terms of the GNU GPL, version 2 or, + at your option, any later version. See the LICENSE.txt file for the text of + the license. - Copyright (C) 2013 m h swende + Copyright (C) 2013 m h swende --]] -- Loads the commands-library local cmds = require('commands') @@ -19,7 +19,7 @@ local getopt = require('getopt') local utils = require('utils') example =[[ - script run mfkeys + script run mfkeys ]] author = "Holiman" usage = "script run mfkeys" @@ -29,247 +29,247 @@ If you want to add more, just put them inside /lualibs/mf_default_keys.lua\n"):f [[ Arguments: - -h : this help - -p : print keys + -h : this help + -p : print keys ]] local TIMEOUT = 10000 -- 10 seconds ---- +--- -- This is only meant to be used when errors occur local function oops(err) - print('ERROR: ',err) - return nil,err + print('ERROR: ',err) + return nil,err end ---- +--- -- Usage help local function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end -- -- waits for answer from pm3 device local function checkCommand(command) - core.clearCommandBuffer() - local usb = command:getBytes() - core.SendCommand(usb) - local result = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) - if result then - local count, cmd, arg0 = bin.unpack('LL',result) - if(arg0==1) then - local count, arg1, arg2, data = bin.unpack('LLH511',result,count) - key = data:sub(1,12) - return key - else - return nil - end - else - print("Timeout while waiting for response. Increase TIMEOUT in mfkeys.lua to wait longer") - return nil, "Timeout while waiting for device to respond" - end + core.clearCommandBuffer() + local usb = command:getBytes() + core.SendCommand(usb) + local result = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) + if result then + local count, cmd, arg0 = bin.unpack('LL',result) + if(arg0==1) then + local count, arg1, arg2, data = bin.unpack('LLH511',result,count) + key = data:sub(1,12) + return key + else + return nil + end + else + print("Timeout while waiting for response. Increase TIMEOUT in mfkeys.lua to wait longer") + return nil, "Timeout while waiting for device to respond" + end end local function checkBlock(blockno, testkeys, keytype) - -- The command data is only 512 bytes, each key is 6 bytes, meaning that we can send max 85 keys in one go. - -- If there's more, we need to split it up - local arg1 = bit32.bor(bit32.lshift(keytype, 8), blockno) + -- The command data is only 512 bytes, each key is 6 bytes, meaning that we can send max 85 keys in one go. + -- If there's more, we need to split it up + local arg1 = bit32.bor(bit32.lshift(keytype, 8), blockno) - local start, remaining = 1, #testkeys - local chunksize = remaining - if remaining > 85 then chunksize = 85 end - local n = chunksize - - while remaining > 0 do - --print('start', start, 'chunksize', chunksize, 'testkeys kvar', remaining, 'N-index=', n) + local start, remaining = 1, #testkeys + local chunksize = remaining + if remaining > 85 then chunksize = 85 end + local n = chunksize - local d1 = table.concat(testkeys, "", start, n) - - print(("Testing block %d, keytype %d, with %d keys"):format(blockno, keytype, chunksize)) - local command = Command:new{cmd = cmds.CMD_MIFARE_CHKKEYS, - arg1 = arg1, - arg2 = 0, - arg3 = chunksize, - data = d1} - local status = checkCommand(command) - if status then return status, blockno end - start = start + chunksize - remaining = remaining - chunksize - - if remaining < 85 then chunksize = remaining end - n = n + chunksize - end - return nil + while remaining > 0 do + --print('start', start, 'chunksize', chunksize, 'testkeys kvar', remaining, 'N-index=', n) + + local d1 = table.concat(testkeys, "", start, n) + + print(("Testing block %d, keytype %d, with %d keys"):format(blockno, keytype, chunksize)) + local command = Command:new{cmd = cmds.CMD_MIFARE_CHKKEYS, + arg1 = arg1, + arg2 = 0, + arg3 = chunksize, + data = d1} + local status = checkCommand(command) + if status then return status, blockno end + start = start + chunksize + remaining = remaining - chunksize + + if remaining < 85 then chunksize = remaining end + n = n + chunksize + end + return nil end -- A function to display the results local function display_results(keys) - local sector, keyA, keyB, succA, succB - print('') - print('|---|----------------|---|----------------|---|') - print('|sec|key A |res|key B |res|') - print('|---|----------------|---|----------------|---|') + local sector, keyA, keyB, succA, succB + print('') + print('|---|----------------|---|----------------|---|') + print('|sec|key A |res|key B |res|') + print('|---|----------------|---|----------------|---|') - for sector = 0, #keys do - succA, succB, keyA, keyB = unpack(keys[sector]) - print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, succA, keyB, succB)) - end - print('|---|----------------|---|----------------|---|') + for sector = 0, #keys do + succA, succB, keyA, keyB = unpack(keys[sector]) + print(('|%03d| %s | %s | %s | %s |'):format(sector, keyA, succA, keyB, succB)) + end + print('|---|----------------|---|----------------|---|') end -- A little helper to place an item first in the list local function placeFirst(akey, list) - akey = akey:lower() - if list[1] == akey then - -- Already at pole position - return list - end - local result = {akey} - --print(("Putting '%s' first"):format(akey)) - for i,v in ipairs(list) do - if v ~= akey then - result[#result+1] = v - end - end - return result + akey = akey:lower() + if list[1] == akey then + -- Already at pole position + return list + end + local result = {akey} + --print(("Putting '%s' first"):format(akey)) + for i,v in ipairs(list) do + if v ~= akey then + result[#result+1] = v + end + end + return result end --[[ -The mifare Classic 1k card has 16 sectors of 4 data blocks each. +The mifare Classic 1k card has 16 sectors of 4 data blocks each. The first 32 sectors of a mifare Classic 4k card consists of 4 data blocks and the remaining -8 sectors consist of 16 data blocks. +8 sectors consist of 16 data blocks. --]] local function get_blockno(s) - local b, sector + local b, sector - if type(s) == 'string' then - sector = tonumber(s) - else - sector = s - end + if type(s) == 'string' then + sector = tonumber(s) + else + sector = s + end - if sector < 32 then - b = sector * 4 - else - b = 32 * 4 + (sector - 32) * 16 + if sector < 32 then + b = sector * 4 + else + b = 32 * 4 + (sector - 32) * 16 end - return ('%02x'):format(b) + return ('%02x'):format(b) end -- -- dumps all keys to file local function dumptofile(keys) - if utils.confirm('Do you wish to save the keys to dumpfile?') then - local destination = utils.input('Select a filename to store to', 'dumpkeys.bin') - local file = io.open(destination, 'wb') - if file == nil then - print('Could not write to file ', destination) - return - end + if utils.confirm('Do you wish to save the keys to dumpfile?') then + local destination = utils.input('Select a filename to store to', 'dumpkeys.bin') + local file = io.open(destination, 'wb') + if file == nil then + print('Could not write to file ', destination) + return + end - local key_a = '' - local key_b = '' + local key_a = '' + local key_b = '' - --for sector,_ in pairs(keys) do - for sector = 0, #keys do - local succA, succB, keyA, keyB = unpack(keys[sector]) - key_a = key_a .. bin.pack('H', keyA); - key_b = key_b .. bin.pack('H', keyB); - end - file:write(key_a) - file:write(key_b) - file:close() - end + --for sector,_ in pairs(keys) do + for sector = 0, #keys do + local succA, succB, keyA, keyB = unpack(keys[sector]) + key_a = key_a .. bin.pack('H', keyA); + key_b = key_b .. bin.pack('H', keyB); + end + file:write(key_a) + file:write(key_b) + file:close() + end end -local function printkeys() - for i=1, #keylist do - print(i, keylist[i]) - end - print ('Number of keys: '..#keylist) +local function printkeys() + for i=1, #keylist do + print(i, keylist[i]) + end + print ('Number of keys: '..#keylist) end local function perform_check(numsectors) - local keyType = 0 -- A=0, B=1 + local keyType = 0 -- A=0, B=1 - -- empty list of found keys - local keys = {} - for i = 0, numsectors-1 do - keys[i] = {0,0,'',''} - end + -- empty list of found keys + local keys = {} + for i = 0, numsectors-1 do + keys[i] = {0,0,'',''} + end - for sector = 0, #keys do - -- Check if user aborted - if core.ukbhit() then - print('Aborted by user') - break - end + for sector = 0, #keys do + -- Check if user aborted + if core.ukbhit() then + print('Aborted by user') + break + end - local targetblock = tonumber(get_blockno(sector), 16) - - local succA, succB, keyA, keyB = unpack(keys[sector]) - - local keyA = checkBlock(targetblock, keylist, 0) - if keyA then succA = 1; keylist = placeFirst(keyA, keylist) end - keyA = keyA or '------------' + local targetblock = tonumber(get_blockno(sector), 16) - local keyB = checkBlock(targetblock, keylist, 1) - if keyB then succB = 1; keylist = placeFirst(keyB, keylist) end - keyB = keyB or '------------' + local succA, succB, keyA, keyB = unpack(keys[sector]) - keys[sector] = {succA, succB, keyA, keyB} - end - - display_results(keys) + local keyA = checkBlock(targetblock, keylist, 0) + if keyA then succA = 1; keylist = placeFirst(keyA, keylist) end + keyA = keyA or '------------' - -- save to dumpkeys.bin - dumptofile(keys) + local keyB = checkBlock(targetblock, keylist, 1) + if keyB then succB = 1; keylist = placeFirst(keyB, keylist) end + keyB = keyB or '------------' + + keys[sector] = {succA, succB, keyA, keyB} + end + + display_results(keys) + + -- save to dumpkeys.bin + dumptofile(keys) end -- -- shows tag information local function taginfo(tag) - local sectors = 16 - -- Show tag info - print((' Found tag %s'):format(tag.name)) + local sectors = 16 + -- Show tag info + print((' Found tag %s'):format(tag.name)) - if 0x18 == tag.sak then --NXP MIFARE Classic 4k | Plus 4k - -- MIFARE Classic 4K offers 4096 bytes split into forty sectors, - -- of which 32 are same size as in the 1K with eight more that are quadruple size sectors. - sectors = 40 - elseif 0x08 == tag.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k - -- 1K offers 1024 bytes of data storage, split into 16 sector - sectors = 16 - elseif 0x09 == tag.sak then -- NXP MIFARE Mini 0.3k - -- MIFARE Classic mini offers 320 bytes split into five sectors. - sectors = 5 - elseif 0x10 == tag.sak then-- "NXP MIFARE Plus 2k" - sectors = 32 - else - print("I don't know how many sectors there are on this type of card, defaulting to 16") - end - return sectors + if 0x18 == tag.sak then --NXP MIFARE Classic 4k | Plus 4k + -- MIFARE Classic 4K offers 4096 bytes split into forty sectors, + -- of which 32 are same size as in the 1K with eight more that are quadruple size sectors. + sectors = 40 + elseif 0x08 == tag.sak then -- NXP MIFARE CLASSIC 1k | Plus 2k + -- 1K offers 1024 bytes of data storage, split into 16 sector + sectors = 16 + elseif 0x09 == tag.sak then -- NXP MIFARE Mini 0.3k + -- MIFARE Classic mini offers 320 bytes split into five sectors. + sectors = 5 + elseif 0x10 == tag.sak then-- "NXP MIFARE Plus 2k" + sectors = 32 + else + print("I don't know how many sectors there are on this type of card, defaulting to 16") + end + return sectors end --- -- The main entry point local function main(args) - local start_time = os.time() - local numSectors = 16 + local start_time = os.time() + local numSectors = 16 - -- Arguments for the script - for o, a in getopt.getopt(args, 'hp') do - if o == "h" then return help() end - if o == "p" then return printkeys() end - end - -- identify tag - tag, err = lib14a.read(false, true) - if not tag then return oops(err) end + -- Arguments for the script + for o, a in getopt.getopt(args, 'hp') do + if o == "h" then return help() end + if o == "p" then return printkeys() end + end + -- identify tag + tag, err = lib14a.read(false, true) + if not tag then return oops(err) end - -- detect sectors and print taginfo - numsectors = taginfo(tag) + -- detect sectors and print taginfo + numsectors = taginfo(tag) - perform_check(numsectors) + perform_check(numsectors) - local end_time = os.time() - print('mfkeys - Total execution time: '..os.difftime(end_time, start_time)..' sec') + local end_time = os.time() + print('mfkeys - Total execution time: '..os.difftime(end_time, start_time)..' sec') end main( args) \ No newline at end of file diff --git a/client/scripts/mifare_access.lua b/client/scripts/mifare_access.lua index 273d524c8..20120aced 100644 --- a/client/scripts/mifare_access.lua +++ b/client/scripts/mifare_access.lua @@ -11,8 +11,8 @@ usage = [[ script run mifare_access -h -a Arguments: - -h : this help - -a : 4 bytes ACCESS CONDITIONS + -h : this help + -a : 4 bytes ACCESS CONDITIONS ]] local DEBUG = true @@ -20,35 +20,35 @@ local bxor = bit32.bxor local band = bit32.band local rshift = bit32.rshift ---- +--- -- A debug printout-function local function dbg(args) if not DEBUG then return end if type(args) == "table" then - local i = 1 - while args[i] do - dbg(args[i]) - i = i+1 - end - else - print("###", args) - end -end ---- + local i = 1 + while args[i] do + dbg(args[i]) + i = i+1 + end + else + print("###", args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) - return nil, err + print("ERROR: ",err) + return nil, err end ---- +--- -- Usage help local function help() - print(copyright) - print(author) - print(version) - print(desc) - print('Example usage') - print(example) + print(copyright) + print(author) + print(version) + print(desc) + print('Example usage') + print(example) end local access_condition_sector_trailer = {} @@ -73,58 +73,58 @@ access_condition_data_block[0x7] = {'never','never','never','never'} local function main(args) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print() + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print() - local access = '' - - -- Read the parameters - for o, a in getopt.getopt(args, 'ha:') do - if o == "h" then return help() end - if o == "a" then access = a end - end - - if access == nil then return oops('empty ACCESS CONDITIONS') end - if #access == 0 then return oops('empty ACCESS CONDITIONS') end - if #access ~= 8 then return oops("Wrong length. Should be 4 hex bytes ACCESS CONDITIONS (e.g. 7F0F0869)") end - - local c2_b = tonumber(string.sub(access, 1, 1), 16) - local c1_b = tonumber(string.sub(access, 2, 2), 16) - local c1 = tonumber(string.sub(access, 3, 3), 16) - local c3_b = tonumber(string.sub(access, 4, 4), 16) - local c3 = tonumber(string.sub(access, 5, 5), 16) - local c2 = tonumber(string.sub(access, 6, 6), 16) - local gpb = string.sub(access, 7, 8) + local access = '' - if bxor(c1, c1_b) ~= 0xF then print("!!! bitflip in c1") end - if bxor(c2, c2_b) ~= 0xF then print("!!! bitflip in c2") end - if bxor(c3, c3_b) ~= 0xF then print("!!! bitflip in c3") end + -- Read the parameters + for o, a in getopt.getopt(args, 'ha:') do + if o == "h" then return help() end + if o == "a" then access = a end + end - local ab = c1 * 256 + c2 * 16 + c3 + if access == nil then return oops('empty ACCESS CONDITIONS') end + if #access == 0 then return oops('empty ACCESS CONDITIONS') end + if #access ~= 8 then return oops("Wrong length. Should be 4 hex bytes ACCESS CONDITIONS (e.g. 7F0F0869)") end - for block = 0,3 do - print("--> block "..block) - -- mask bits for block - local abi = band(rshift(ab, block), 0x111) - -- compress bits - abi = band(abi + rshift(abi, 3) + rshift(abi, 6),7) --- print(abi) - if block == 3 then - print(" KEYSECXA read: "..access_condition_sector_trailer[abi][1]) - print(" KEYSECXA write: "..access_condition_sector_trailer[abi][2]) - print(" ACCESS COND. read: "..access_condition_sector_trailer[abi][3]) - print("ACCESS COND. write: "..access_condition_sector_trailer[abi][4]) - print(" KEYSECXB read: "..access_condition_sector_trailer[abi][5]) - print(" KEYSECXB write: "..access_condition_sector_trailer[abi][6]) - else - print(" read: "..access_condition_data_block[abi][1]) - print(" write: "..access_condition_data_block[abi][2]) - print(" inc: "..access_condition_data_block[abi][3]) - print("decr, transfer, restore: "..access_condition_data_block[abi][4]) - end - end + local c2_b = tonumber(string.sub(access, 1, 1), 16) + local c1_b = tonumber(string.sub(access, 2, 2), 16) + local c1 = tonumber(string.sub(access, 3, 3), 16) + local c3_b = tonumber(string.sub(access, 4, 4), 16) + local c3 = tonumber(string.sub(access, 5, 5), 16) + local c2 = tonumber(string.sub(access, 6, 6), 16) + local gpb = string.sub(access, 7, 8) - print("GPB: "..gpb) + if bxor(c1, c1_b) ~= 0xF then print("!!! bitflip in c1") end + if bxor(c2, c2_b) ~= 0xF then print("!!! bitflip in c2") end + if bxor(c3, c3_b) ~= 0xF then print("!!! bitflip in c3") end + + local ab = c1 * 256 + c2 * 16 + c3 + + for block = 0,3 do + print("--> block "..block) + -- mask bits for block + local abi = band(rshift(ab, block), 0x111) + -- compress bits + abi = band(abi + rshift(abi, 3) + rshift(abi, 6),7) + -- print(abi) + if block == 3 then + print(" KEYSECXA read: "..access_condition_sector_trailer[abi][1]) + print(" KEYSECXA write: "..access_condition_sector_trailer[abi][2]) + print(" ACCESS COND. read: "..access_condition_sector_trailer[abi][3]) + print("ACCESS COND. write: "..access_condition_sector_trailer[abi][4]) + print(" KEYSECXB read: "..access_condition_sector_trailer[abi][5]) + print(" KEYSECXB write: "..access_condition_sector_trailer[abi][6]) + else + print(" read: "..access_condition_data_block[abi][1]) + print(" write: "..access_condition_data_block[abi][2]) + print(" inc: "..access_condition_data_block[abi][3]) + print("decr, transfer, restore: "..access_condition_data_block[abi][4]) + end + end + + print("GPB: "..gpb) end main(args) diff --git a/client/scripts/mifare_autopwn.lua b/client/scripts/mifare_autopwn.lua index 738ca6950..b99488d96 100644 --- a/client/scripts/mifare_autopwn.lua +++ b/client/scripts/mifare_autopwn.lua @@ -7,208 +7,208 @@ example = "script run mifare_autopwn" author = "Martin Holst Swende" desc = [[ -This is a script which automates cracking and dumping mifare classic cards. It sets itself into -'listening'-mode, after which it cracks and dumps any mifare classic card that you -place by the device. +This is a script which automates cracking and dumping mifare classic cards. It sets itself into +'listening'-mode, after which it cracks and dumps any mifare classic card that you +place by the device. Arguments: - -h this help - -d debug logging on - -k known key for Sector 0 , keytype A + -h this help + -d debug logging on + -k known key for Sector 0 , keytype A Output files from this operation: - .eml - emulator file - .html - html file containing card data - dumpkeys.bin - keys are dumped here. OBS! This file is volatile, as other commands overwrite it sometimes. - dumpdata.bin - card data in binary form. OBS! This file is volatile, as other commands (hf mf dump) overwrite it. + .eml - emulator file + .html - html file containing card data + dumpkeys.bin - keys are dumped here. OBS! This file is volatile, as other commands overwrite it sometimes. + dumpdata.bin - card data in binary form. OBS! This file is volatile, as other commands (hf mf dump) overwrite it. ]] ------------------------------- --- Some utilities +-- Some utilities ------------------------------- local DEBUG = false ---- +--- -- A debug printout-function local function dbg(args) - if not DEBUG then return end - - if type(args) == 'table' then - local i = 1 - while result[i] do - dbg(result[i]) - i = i+1 - end - else - print('###', args) - end -end ---- --- This is only meant to be used when errors occur -local function oops(err) - print("ERROR: ",err) - return nil,err -end ---- --- Usage help -local function help() - print(desc) - print("Example usage") - print(example) + if not DEBUG then return end + + if type(args) == 'table' then + local i = 1 + while result[i] do + dbg(result[i]) + i = i+1 + end + else + print('###', args) + end end --- --- Waits for a mifare card to be placed within the vicinity of the reader. +-- This is only meant to be used when errors occur +local function oops(err) + print("ERROR: ",err) + return nil,err +end +--- +-- Usage help +local function help() + print(desc) + print("Example usage") + print(example) +end +--- +-- Waits for a mifare card to be placed within the vicinity of the reader. -- @return if successfull: an table containing card info -- @return if unsuccessfull : nil, error local function wait_for_mifare() - while not core.ukbhit() do - res, err = lib14a.read() - if res then return res end - -- err means that there was no response from card - end - return nil, "Aborted by user" + while not core.ukbhit() do + res, err = lib14a.read() + if res then return res end + -- err means that there was no response from card + end + return nil, "Aborted by user" end local function nested(key,sak) - local typ = 1 - if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k - typ = 4 - elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K - typ = 1 - elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k - typ = 0 - elseif 0x10 == sak then-- "NXP MIFARE Plus 2k" - typ = 2 - elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K" - typ = 1 - else - print("I don't know how many sectors there are on this type of card, defaulting to 16") - end - local cmd = string.format("hf mf nested %d 0 A %s d", typ, key) - core.console(cmd) + local typ = 1 + if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k + typ = 4 + elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K + typ = 1 + elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k + typ = 0 + elseif 0x10 == sak then-- "NXP MIFARE Plus 2k" + typ = 2 + elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K" + typ = 1 + else + print("I don't know how many sectors there are on this type of card, defaulting to 16") + end + local cmd = string.format("hf mf nested %d 0 A %s d", typ, key) + core.console(cmd) end local function dump(uid, numsectors) - dbg('dumping tag memory') + dbg('dumping tag memory') - local typ = 1 - if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k - typ = 4 - elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K - typ = 1 - elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k - typ = 0 - elseif 0x10 == sak then-- "NXP MIFARE Plus 2k" - typ = 2 - elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K" - typ = 1 - end + local typ = 1 + if 0x18 == sak then --NXP MIFARE Classic 4k | Plus 4k | Ev1 4k + typ = 4 + elseif 0x08 == sak then -- NXP MIFARE CLASSIC 1k | Plus 2k | Ev1 1K + typ = 1 + elseif 0x09 == sak then -- NXP MIFARE Mini 0.3k + typ = 0 + elseif 0x10 == sak then-- "NXP MIFARE Plus 2k" + typ = 2 + elseif 0x01 == sak then-- "NXP MIFARE TNP3xxx 1K" + typ = 1 + end - if utils.confirm('Do you wish to create a memory dump of tag?') then + if utils.confirm('Do you wish to create a memory dump of tag?') then - local dumpfile = 'hf-mf-'..uid..'-data.bin' + local dumpfile = 'hf-mf-'..uid..'-data.bin' - local dmp = ('hf mf dump %s f %s'):format(typ, dumpfile) - core.console(dmp) + local dmp = ('hf mf dump %s f %s'):format(typ, dumpfile) + core.console(dmp) - -- Save the global args, those are *our* arguments - local myargs = args - -- Set the arguments for htmldump script - args =('-i %s -o %s.html'):format(dumpfile, uid) - -- call it - require('htmldump') + -- Save the global args, those are *our* arguments + local myargs = args + -- Set the arguments for htmldump script + args =('-i %s -o %s.html'):format(dumpfile, uid) + -- call it + require('htmldump') - -- dump to emulator - args =('-i %s -o %s.eml'):format(dumpfile, uid) - require('dumptoemul') + -- dump to emulator + args =('-i %s -o %s.eml'):format(dumpfile, uid) + require('dumptoemul') - -- Set back args. Not that it's used, just for the karma... - args = myargs - end + -- Set back args. Not that it's used, just for the karma... + args = myargs + end end -- -- performs a test if tag nonce uses weak or hardend prng local function perform_prng_test() - local isweak = core.detect_prng() - if isweak == 1 then - dbg('PRNG detection : WEAK nonce detected') - elseif isweak == 0 then - dbg('PRNG detection : HARDEND nonce detected') - else - dbg('PRNG detection : failed') - end - return isweak + local isweak = core.detect_prng() + if isweak == 1 then + dbg('PRNG detection : WEAK nonce detected') + elseif isweak == 0 then + dbg('PRNG detection : HARDEND nonce detected') + else + dbg('PRNG detection : failed') + end + return isweak end ---- +--- -- The main entry point local function main(args) - local verbose, exit, res, uid, err, _, sak - local seen_uids = {} - local key = '' - local print_message = true - -- Read the parameters - for o, a in getopt.getopt(args, 'hdk:') do - if o == "h" then help() return end - if o == "d" then DEBUG = true end - if o == 'k' then key = a end - end + local verbose, exit, res, uid, err, _, sak + local seen_uids = {} + local key = '' + local print_message = true + -- Read the parameters + for o, a in getopt.getopt(args, 'hdk:') do + if o == "h" then help() return end + if o == "d" then DEBUG = true end + if o == 'k' then key = a end + end - while not exit do - if print_message then - print("Waiting for card or press any key to stop") - print_message = false - end - res, err = wait_for_mifare() - if err then return oops(err) end - -- Seen already? - uid = res.uid - sak = res.sak - - if not seen_uids[uid] then - -- Store it - seen_uids[uid] = uid - - -- check if PRNG is WEAK - if perform_prng_test() == 1 then - print("Card found, commencing crack on UID", uid) + while not exit do + if print_message then + print("Waiting for card or press any key to stop") + print_message = false + end + res, err = wait_for_mifare() + if err then return oops(err) end + -- Seen already? + uid = res.uid + sak = res.sak - if #key == 12 then - print("Using key: "..key); - else - -- Crack it - local cnt - err, res = core.mfDarkside() - if err == -1 then return oops("Button pressed. Aborted.") - elseif err == -2 then return oops("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).") - elseif err == -3 then return oops("Card is not vulnerable to Darkside attack (its random number generator is not predictable).") - elseif err == -4 then return oops([[ - Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown - generating polynomial with 16 effective bits only, but shows unexpected behaviour.]]) - elseif err == -5 then return oops("Aborted via keyboard.") - end - -- The key is actually 8 bytes, so a - -- 6-byte key is sent as 00XXXXXX - -- This means we unpack it as first - -- two bytes, then six bytes actual key data - -- We can discard first and second return values - _,_,key = bin.unpack("H2H6",res) - print("Found valid key: "..key); - end - -- Use nested attack - nested(key, sak) - -- Dump info - dump(uid, sak) + if not seen_uids[uid] then + -- Store it + seen_uids[uid] = uid - if #key == 12 then exit = true end - else - print("Card found, darkside attack useless PRNG hardend on UID", uid) - end - print_message = true - end - end + -- check if PRNG is WEAK + if perform_prng_test() == 1 then + print("Card found, commencing crack on UID", uid) + + if #key == 12 then + print("Using key: "..key); + else + -- Crack it + local cnt + err, res = core.mfDarkside() + if err == -1 then return oops("Button pressed. Aborted.") + elseif err == -2 then return oops("Card is not vulnerable to Darkside attack (doesn't send NACK on authentication requests).") + elseif err == -3 then return oops("Card is not vulnerable to Darkside attack (its random number generator is not predictable).") + elseif err == -4 then return oops([[ + Card is not vulnerable to Darkside attack (its random number generator seems to be based on the wellknown + generating polynomial with 16 effective bits only, but shows unexpected behaviour.]]) + elseif err == -5 then return oops("Aborted via keyboard.") + end + -- The key is actually 8 bytes, so a + -- 6-byte key is sent as 00XXXXXX + -- This means we unpack it as first + -- two bytes, then six bytes actual key data + -- We can discard first and second return values + _,_,key = bin.unpack("H2H6",res) + print("Found valid key: "..key); + end + -- Use nested attack + nested(key, sak) + -- Dump info + dump(uid, sak) + + if #key == 12 then exit = true end + else + print("Card found, darkside attack useless PRNG hardend on UID", uid) + end + print_message = true + end + end end --- Call the main +-- Call the main main(args) diff --git a/client/scripts/mifareplus.lua b/client/scripts/mifareplus.lua index 39462360a..b559b6beb 100644 --- a/client/scripts/mifareplus.lua +++ b/client/scripts/mifareplus.lua @@ -9,19 +9,19 @@ desc = [[ Purpose: Lua script to communicate with the Mifare Plus EV1, including personalization (setting the keys) and proximity check. Manually edit the file to add to the commands you can send the card. Please read the NXP manual before running this script to prevent making irreversible changes. Also note: - - The Mifare Plus must start in SL0 for personalization. Card can then be moved to SL1 or SL3. - - The keys are hardcoded in the script to "00...". Unless you change this, only use this script for testing purposes. - - Make sure you choose your card size correctly (2kB or 4kB). + - The Mifare Plus must start in SL0 for personalization. Card can then be moved to SL1 or SL3. + - The keys are hardcoded in the script to "00...". Unless you change this, only use this script for testing purposes. + - Make sure you choose your card size correctly (2kB or 4kB). Small changes can be to made this script to communicate with the Mifare Plus S, X, or SE. ]] usage = [[ script run mifareplus -h Arguments: - -h : this help + -h : this help ]] --- Default +-- Default SIXTEEN_BYTES_ZEROS = '00000000000000000000000000000000' -- ISO7816 commands used @@ -38,264 +38,264 @@ PROXIMITYCHECK = '03F2' VERIFYPC = '03FD' READPLAINNOMACUNMACED = '0336' ---- +--- -- This is only meant to be used when errors occur local function oops(err) - print('ERROR: ',err) - return nil, err + print('ERROR: ',err) + return nil, err end --- -- Usage help local function help() - print(copyright) - print(author) - print(version) - print(desc) - print('Example usage') - print(example) + print(copyright) + print(author) + print(version) + print(desc) + print('Example usage') + print(example) end --- -- Used to send raw data to the firmware to subsequently forward the data to the card. local function sendRaw(rawdata, crc, power) - print((": %s"):format(rawdata)) + print((": %s"):format(rawdata)) - local flags = lib14a.ISO14A_COMMAND.ISO14A_RAW - if crc then - flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC - end - if power then - flags = flags + lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT - end + local flags = lib14a.ISO14A_COMMAND.ISO14A_RAW + if crc then + flags = flags + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC + end + if power then + flags = flags + lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + end - local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, - arg1 = flags, -- Send raw - arg2 = string.len(rawdata) / 2, -- arg2 contains the length, which is half the length of the ASCII-string rawdata - data = rawdata} - local ignore_response = false - local result, err = lib14a.sendToDevice(command, ignore_response) - if result then - --unpack the first 4 parts of the result as longs, and the last as an extremely long string to later be cut down based on arg1, the number of bytes returned - local count,cmd,arg1,arg2,arg3,data = bin.unpack('LLLLH512',result) + local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, + arg1 = flags, -- Send raw + arg2 = string.len(rawdata) / 2, -- arg2 contains the length, which is half the length of the ASCII-string rawdata + data = rawdata} + local ignore_response = false + local result, err = lib14a.sendToDevice(command, ignore_response) + if result then + --unpack the first 4 parts of the result as longs, and the last as an extremely long string to later be cut down based on arg1, the number of bytes returned + local count,cmd,arg1,arg2,arg3,data = bin.unpack('LLLLH512',result) - returned_bytes = string.sub(data, 1, arg1 * 2) - if #returned_bytes > 0 then - print((": %s"):format(returned_bytes)) -- need to multiply by 2 because the hex digits are actually two bytes when they are strings - return returned_bytes - else - return nil - end - else - oops("Error sending the card raw data.") - return nil - end + returned_bytes = string.sub(data, 1, arg1 * 2) + if #returned_bytes > 0 then + print((": %s"):format(returned_bytes)) -- need to multiply by 2 because the hex digits are actually two bytes when they are strings + return returned_bytes + else + return nil + end + else + oops("Error sending the card raw data.") + return nil + end end -- Sends an instruction to do nothing, only disconnect local function disconnect() - local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0, } - -- We can ignore the response here, no ACK is returned for this command - -- Check /armsrc/iso14443a.c, ReaderIso14443a() for details - return lib14a.sendToDevice(command,true) -end + local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0,} + -- We can ignore the response here, no ACK is returned for this command + -- Check /armsrc/iso14443a.c, ReaderIso14443a() for details + return lib14a.sendToDevice(command,true) +end local function writePerso() - -- Used to write any data, including the keys (Key A and Key B), for all the sectors. - -- writePerso() command parameters: - -- 1 byte - 0xA8 - Command Code - -- 2 bytes - Address of the first block or key to be written to (40 blocks are numbered from 0x0000 to 0x00FF) - -- X bytes - The data bytes to be written, starting from the first block. Amount of data sent can be from 16 to 240 bytes in 16 byte increments. This allows - -- up to 15 blocks to be written at once. - -- response from PICC: - -- 0x90 - OK - -- 0x09 - targeted block is invalid for writes, i.e. block 0, which contains manufacturer data - -- 0x0B - command invalid - -- 0x0C - unexpected command length - + -- Used to write any data, including the keys (Key A and Key B), for all the sectors. + -- writePerso() command parameters: + -- 1 byte - 0xA8 - Command Code + -- 2 bytes - Address of the first block or key to be written to (40 blocks are numbered from 0x0000 to 0x00FF) + -- X bytes - The data bytes to be written, starting from the first block. Amount of data sent can be from 16 to 240 bytes in 16 byte increments. This allows + -- up to 15 blocks to be written at once. + -- response from PICC: + -- 0x90 - OK + -- 0x09 - targeted block is invalid for writes, i.e. block 0, which contains manufacturer data + -- 0x0B - command invalid + -- 0x0C - unexpected command length - cardsize = 4 --need to set to 4 for 4k or 2 for 2k - if(cardsize == 4) then - numsectors = 39 - elseif(cardsize == 2) then - numsectors = 31 - else - oops("Invalid card size") - end - -- Write to the AES sector keys - print("Setting AES Sector keys") - for i=0,numsectors do --for each sector number - local keyA_block = "40" .. string.format("%02x", i * 2) - local keyB_block = "40" .. string.format("%02x", (i * 2) + 1) - --Can also calculate the keys fancily to make them unique, if desired - keyA = SIXTEEN_BYTES_ZEROS - keyB = SIXTEEN_BYTES_ZEROS - writeBlock(keyA_block, keyA) - writeBlock(keyB_block, keyB) - end - print("Finished setting AES Sector keys") + cardsize = 4 --need to set to 4 for 4k or 2 for 2k + if(cardsize == 4) then + numsectors = 39 + elseif(cardsize == 2) then + numsectors = 31 + else + oops("Invalid card size") + end - print("Setting misc keys which haven't been set yet.") - --CardMasterKey - blocknum = "9000" - writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) - --CardConfigurationKey - blocknum = "9001" - writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) - --L3SwitchKey - blocknum = "9003" - writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) - --SL1CardAuthKey - blocknum = "9004" - writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) - --L3SectorSwitchKey - blocknum = "9006" - writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) - --L1L3MixSectorSwitchKey - blocknum = "9007" - writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) - --VC Keys - --VCProximityKey - blocknum = "A001" - writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) - --VCSelectENCKey - blocknum = "A080" - writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) - --VCSelectMACKey - blocknum = "A081" - writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) - --TransactionMACKey1 - blocknum = "C000" - writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) - --TransactionMACConfKey1 - blocknum = "C001" - writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) - print("Finished setting misc keys.") + -- Write to the AES sector keys + print("Setting AES Sector keys") + for i=0,numsectors do --for each sector number + local keyA_block = "40" .. string.format("%02x", i * 2) + local keyB_block = "40" .. string.format("%02x", (i * 2) + 1) + --Can also calculate the keys fancily to make them unique, if desired + keyA = SIXTEEN_BYTES_ZEROS + keyB = SIXTEEN_BYTES_ZEROS + writeBlock(keyA_block, keyA) + writeBlock(keyB_block, keyB) + end + print("Finished setting AES Sector keys") - print("WritePerso finished! Card is ready to move into new security level.") + print("Setting misc keys which haven't been set yet.") + --CardMasterKey + blocknum = "9000" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --CardConfigurationKey + blocknum = "9001" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --L3SwitchKey + blocknum = "9003" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --SL1CardAuthKey + blocknum = "9004" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --L3SectorSwitchKey + blocknum = "9006" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --L1L3MixSectorSwitchKey + blocknum = "9007" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --VC Keys + --VCProximityKey + blocknum = "A001" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --VCSelectENCKey + blocknum = "A080" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --VCSelectMACKey + blocknum = "A081" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --TransactionMACKey1 + blocknum = "C000" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + --TransactionMACConfKey1 + blocknum = "C001" + writeBlock(blocknum, SIXTEEN_BYTES_ZEROS) + print("Finished setting misc keys.") + + print("WritePerso finished! Card is ready to move into new security level.") end local function writeBlock(blocknum, data) - -- Method writes 16 bytes of the string sent (data) to the specified block number - -- The block numbers sent to the card need to be in little endian format (i.e. block 0x0001 is sent as 0x1000) - blocknum_little_endian = string.sub(blocknum, 3, 4) .. string.sub(blocknum, 1, 2) - commandString = WRITEPERSO .. blocknum_little_endian .. data --Write 16 bytes (32 hex chars). - response = sendRaw(commandString, true, true) --0x90 is returned upon success - if string.sub(response, 3, 4) ~= "90" then - oops(("error occurred while trying to write to block %s"):format(blocknum)) - end + -- Method writes 16 bytes of the string sent (data) to the specified block number + -- The block numbers sent to the card need to be in little endian format (i.e. block 0x0001 is sent as 0x1000) + blocknum_little_endian = string.sub(blocknum, 3, 4) .. string.sub(blocknum, 1, 2) + commandString = WRITEPERSO .. blocknum_little_endian .. data --Write 16 bytes (32 hex chars). + response = sendRaw(commandString, true, true) --0x90 is returned upon success + if string.sub(response, 3, 4) ~= "90" then + oops(("error occurred while trying to write to block %s"):format(blocknum)) + end end local function authenticateAES() - -- Used to try to authenticate with the AES keys we programmed into the card, to ensure the authentication works correctly. - commandString = AUTH_FIRST - commandString = commandString .. '' + -- Used to try to authenticate with the AES keys we programmed into the card, to ensure the authentication works correctly. + commandString = AUTH_FIRST + commandString = commandString .. '' end local function getVersion() - sendRaw(GETVERS_INIT, true, true) - sendRaw(GETVERS_CONT, true, true) - sendRaw(GETVERS_CONT, true, true) + sendRaw(GETVERS_INIT, true, true) + sendRaw(GETVERS_CONT, true, true) + sendRaw(GETVERS_CONT, true, true) end local function commitPerso(SL) - --pass SL as "01" to move to SL1 or "03" to move to SL3. - commandString = COMMITPERSO .. SL - response = sendRaw(commandString, true, true) --0x90 is returned upon success - if string.sub(response, 3, 4) ~= "90" then - oops("error occurred while trying to switch security level") - end + --pass SL as "01" to move to SL1 or "03" to move to SL3. + commandString = COMMITPERSO .. SL + response = sendRaw(commandString, true, true) --0x90 is returned upon success + if string.sub(response, 3, 4) ~= "90" then + oops("error occurred while trying to switch security level") + end end local function calculateMAC(MAC_input) - -- Pad the input if it is not a multiple of 16 bytes (32 nibbles). - if(string.len(MAC_input) % 32 ~= 0) then - MAC_input = MAC_input .. "80" - end - while(string.len(MAC_input) % 32 ~= 0) do - MAC_input = MAC_input .. "0" - end - print("Padded MAC Input = " .. MAC_input .. ", length (bytes) = " .. string.len(MAC_input) / 2) + -- Pad the input if it is not a multiple of 16 bytes (32 nibbles). + if(string.len(MAC_input) % 32 ~= 0) then + MAC_input = MAC_input .. "80" + end + while(string.len(MAC_input) % 32 ~= 0) do + MAC_input = MAC_input .. "0" + end + print("Padded MAC Input = " .. MAC_input .. ", length (bytes) = " .. string.len(MAC_input) / 2) - --The MAC would actually be calculated here, and the output stored in raw_output - raw_output = "00010203040506070001020304050607" -- Dummy filler for now of 16-byte output. To be filled with actual MAC for testing purposes. + --The MAC would actually be calculated here, and the output stored in raw_output + raw_output = "00010203040506070001020304050607" -- Dummy filler for now of 16-byte output. To be filled with actual MAC for testing purposes. - -- The final 8-byte MAC output is a concatenation of every 2nd byte starting from the second MSB. - final_output = "" - j = 3 - for i = 1,8 do - final_output = final_output .. string.sub(RndR, j, j + 1) .. string.sub(RndC, j, j + 1) - j = j + 4 - end - return final_output + -- The final 8-byte MAC output is a concatenation of every 2nd byte starting from the second MSB. + final_output = "" + j = 3 + for i = 1,8 do + final_output = final_output .. string.sub(RndR, j, j + 1) .. string.sub(RndC, j, j + 1) + j = j + 4 + end + return final_output end local function proximityCheck() - --PreparePC-- - commandString = PREPAREPC - response = sendRaw(commandString, true, true) - if not response then return oops("This card is not support the proximity check command.") end - - OPT = string.sub(response, 5, 6) - if tonumber(OPT) == 1 then - pps_present = true - else - pps_present = false - end - pubRespTime = string.sub(response, 7, 10) - if(pps_present == true) then - pps = string.sub(response, 11, 12) - else - pps = '' - end - print("OPT = " .. OPT .. " pubRespTime = " .. pubRespTime .. " pps = " .. pps) + --PreparePC-- + commandString = PREPAREPC + response = sendRaw(commandString, true, true) + if not response then return oops("This card is not support the proximity check command.") end - --PC-- - RndC = "0001020304050607" --Random Challenge - num_rounds = 8 --Needs to be 1, 2, 4, or 8 - part_len = 8 / num_rounds - j = 1 - RndR = "" - for i = 1,num_rounds do - pRndC = "" - for q = 1,(part_len*2) do - pRndC = pRndC .. string.sub(RndC,j,j) - j = j + 1 - end - commandString = PROXIMITYCHECK .. "0" .. tostring(part_len) .. pRndC - pRndR = string.sub(sendRaw(commandString, true, true), 3, 3+part_len) - RndR = RndR .. pRndR - end - print("RndC = " .. RndC .. " RndR = " .. RndR) + OPT = string.sub(response, 5, 6) + if tonumber(OPT) == 1 then + pps_present = true + else + pps_present = false + end + pubRespTime = string.sub(response, 7, 10) + if(pps_present == true) then + pps = string.sub(response, 11, 12) + else + pps = '' + end + print("OPT = " .. OPT .. " pubRespTime = " .. pubRespTime .. " pps = " .. pps) - --VerifyPC-- - MAC_input = "FD" .. OPT .. pubRespTime - if pps_present then - MAC_input = MAC_input .. pps - end - rnum_concat = "" - rnum_concat = RndR .. RndC --temporary (only works for when a single random challenge (8 bytes) is sent) - -- j = 1 - -- for i = 1,8 do - -- rnum_concat = rnum_concat .. string.sub(RndR, j, j + 1) .. string.sub(RndC, j, j + 1) - -- j = j + 2 - -- end - MAC_input = MAC_input .. rnum_concat - print("Concatenation of random numbers = " .. rnum_concat) - print("Final PCD concatenation before input into MAC function = " .. MAC_input) - MAC_tag = calculateMAC(MAC_input) - print("8-byte PCD MAC_tag (placeholder - currently incorrect) = " .. MAC_tag) - commandString = VERIFYPC .. MAC_tag - response = sendRaw(commandString, true, true) - print(#response, response) - if #response < 20 then return oops("Wrong response length (expected 20, got "..#response..") exiting") end - - PICC_MAC = string.sub(response, 5, 20) - print("8-byte MAC returned by PICC = " .. PICC_MAC) - MAC_input = "90" .. string.sub(MAC_input, 3) - print("Final PICC concatenation before input into MAC function = " .. MAC_input) - MAC_tag = calculateMAC(MAC_input) - print("8-byte PICC MAC_tag (placeholder - currently incorrect) = " .. MAC_tag) + --PC-- + RndC = "0001020304050607" --Random Challenge + num_rounds = 8 --Needs to be 1, 2, 4, or 8 + part_len = 8 / num_rounds + j = 1 + RndR = "" + for i = 1,num_rounds do + pRndC = "" + for q = 1,(part_len*2) do + pRndC = pRndC .. string.sub(RndC,j,j) + j = j + 1 + end + commandString = PROXIMITYCHECK .. "0" .. tostring(part_len) .. pRndC + pRndR = string.sub(sendRaw(commandString, true, true), 3, 3+part_len) + RndR = RndR .. pRndR + end + print("RndC = " .. RndC .. " RndR = " .. RndR) + + --VerifyPC-- + MAC_input = "FD" .. OPT .. pubRespTime + if pps_present then + MAC_input = MAC_input .. pps + end + rnum_concat = "" + rnum_concat = RndR .. RndC --temporary (only works for when a single random challenge (8 bytes) is sent) + -- j = 1 + -- for i = 1,8 do + -- rnum_concat = rnum_concat .. string.sub(RndR, j, j + 1) .. string.sub(RndC, j, j + 1) + -- j = j + 2 + -- end + MAC_input = MAC_input .. rnum_concat + print("Concatenation of random numbers = " .. rnum_concat) + print("Final PCD concatenation before input into MAC function = " .. MAC_input) + MAC_tag = calculateMAC(MAC_input) + print("8-byte PCD MAC_tag (placeholder - currently incorrect) = " .. MAC_tag) + commandString = VERIFYPC .. MAC_tag + response = sendRaw(commandString, true, true) + print(#response, response) + if #response < 20 then return oops("Wrong response length (expected 20, got "..#response..") exiting") end + + PICC_MAC = string.sub(response, 5, 20) + print("8-byte MAC returned by PICC = " .. PICC_MAC) + MAC_input = "90" .. string.sub(MAC_input, 3) + print("Final PICC concatenation before input into MAC function = " .. MAC_input) + MAC_tag = calculateMAC(MAC_input) + print("8-byte PICC MAC_tag (placeholder - currently incorrect) = " .. MAC_tag) end @@ -303,47 +303,47 @@ end -- The main entry point function main(args) - local o, a - for o, a in getopt.getopt(args, 'h') do -- Populate command line arguments - if o == "h" then return help() end - end + local o, a + for o, a in getopt.getopt(args, 'h') do -- Populate command line arguments + if o == "h" then return help() end + end - -- Initialize the card using the already-present read14a library - -- Perform RATS and PPS (Protocol and Parameter Selection) check to finish the ISO 14443-4 protocol. - info,err = lib14a.read(true, false) - if not info then oops(err); disconnect(); return; end - - -- - response = sendRaw("D01100", true, true) - if not response then oops("No response from PPS check"); disconnect(); return; end + -- Initialize the card using the already-present read14a library + -- Perform RATS and PPS (Protocol and Parameter Selection) check to finish the ISO 14443-4 protocol. + info,err = lib14a.read(true, false) + if not info then oops(err); disconnect(); return; end - print("Connected to") - print(" Type : "..info.name) - print(" UID : "..info.uid) - - -- Now, the card is initialized and we can do more interesting things. + -- + response = sendRaw("D01100", true, true) + if not response then oops("No response from PPS check"); disconnect(); return; end - --writePerso() - --commitPerso("03") --move to SL3 - --getVersion() - proximityCheck() + print("Connected to") + print(" Type : "..info.name) + print(" UID : "..info.uid) - --commandString = VERIFYPC .. "186EFDE8DDC7D30B" - -- MAC = f5180d6e 40fdeae8 e9dd6ac7 bcd3350b - -- response = sendRaw(commandString, true, true) + -- Now, the card is initialized and we can do more interesting things. - -- attempt to read VCProximityKey at block A001 - -- commandString = READPLAINNOMACUNMACED .. "01A0" .. "01" - -- response = sendRaw(commandString, true, true) + --writePerso() + --commitPerso("03") --move to SL3 + --getVersion() + proximityCheck() - -- authenticate with CardConfigurationKey - -- commandString = AUTH_FIRST .. "0190" .. "00" - -- response = sendRaw(commandString, true, true) + --commandString = VERIFYPC .. "186EFDE8DDC7D30B" + -- MAC = f5180d6e 40fdeae8 e9dd6ac7 bcd3350b + -- response = sendRaw(commandString, true, true) - -- Power off the Proxmark - sendRaw(POWEROFF, false, false) - - disconnect() + -- attempt to read VCProximityKey at block A001 + -- commandString = READPLAINNOMACUNMACED .. "01A0" .. "01" + -- response = sendRaw(commandString, true, true) + + -- authenticate with CardConfigurationKey + -- commandString = AUTH_FIRST .. "0190" .. "00" + -- response = sendRaw(commandString, true, true) + + -- Power off the Proxmark + sendRaw(POWEROFF, false, false) + + disconnect() end main(args) diff --git a/client/scripts/ndef_dump.lua b/client/scripts/ndef_dump.lua index f1bf70ddd..4a740d7e6 100644 --- a/client/scripts/ndef_dump.lua +++ b/client/scripts/ndef_dump.lua @@ -4,20 +4,20 @@ local getopt = require('getopt') local cmds = require('commands') local taglib = require('taglib') -local desc = +local desc = [[This script will automatically recognize and dump full content of a NFC NDEF Initialized tag; non-initialized tags will be ignored. It also write the dump to an eml-file .eml. (The difference between an .eml-file and a .bin-file is that the eml file contains -ASCII representation of the hex-data, with linebreaks between 'rows'. A .bin-file contains the -raw data, but when saving into that for, we lose the infromation about how the memory is structured. -For example: 24 bytes could be 6 blocks of 4 bytes, or vice versa. +ASCII representation of the hex-data, with linebreaks between 'rows'. A .bin-file contains the +raw data, but when saving into that for, we lose the infromation about how the memory is structured. +For example: 24 bytes could be 6 blocks of 4 bytes, or vice versa. Therefore, the .eml is better to use file when saving dumps.) Arguments: - -d debug logging on - -h this help + -h this help + -d debug logging on ]] local example = "script run xxx" @@ -25,116 +25,116 @@ local author = "Martin Holst Swende & Asper" --- -- PrintAndLog local function prlog(...) - -- TODO; replace this with a call to the proper PrintAndLog - print(...) + -- TODO; replace this with a call to the proper PrintAndLog + print(...) end ---- +--- -- This is only meant to be used when errors occur local function oops(err) - prlog("ERROR: ",err) - return nil,err + prlog("ERROR: ",err) + return nil,err end -- Perhaps this will be moved to a separate library at one point local utils = { - --- Writes an eml-file. - -- @param uid - the uid of the tag. Used in filename - -- @param blockData. Assumed to be on the format {'\0\1\2\3,'\b\e\e\f' ..., - -- that is, blockData[row] contains a string with the actual data, not ascii hex representation - -- return filename if all went well, - -- @reurn nil, error message if unsuccessfull - writeDumpFile = function(uid, blockData) - local destination = string.format("%s.eml", uid) - local file = io.open(destination, "w") - if file == nil then - return nil, string.format("Could not write to file %s", destination) - end - local rowlen = string.len(blockData[1]) + --- Writes an eml-file. + -- @param uid - the uid of the tag. Used in filename + -- @param blockData. Assumed to be on the format {'\0\1\2\3,'\b\e\e\f' ..., + -- that is, blockData[row] contains a string with the actual data, not ascii hex representation + -- return filename if all went well, + -- @reurn nil, error message if unsuccessfull + writeDumpFile = function(uid, blockData) + local destination = string.format("%s.eml", uid) + local file = io.open(destination, "w") + if file == nil then + return nil, string.format("Could not write to file %s", destination) + end + local rowlen = string.len(blockData[1]) - for i,block in ipairs(blockData) do - if rowlen ~= string.len(block) then - prlog(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i)) - end + for i,block in ipairs(blockData) do + if rowlen ~= string.len(block) then + prlog(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i)) + end - local formatString = string.format("H%d", string.len(block)) - local _,hex = bin.unpack(formatString,block) - file:write(hex.."\n") - end - file:close() - return destination - end, + local formatString = string.format("H%d", string.len(block)) + local _,hex = bin.unpack(formatString,block) + file:write(hex.."\n") + end + file:close() + return destination + end, } ---- +--- -- Usage help local function help() - prlog(desc) - prlog("Example usage") - prlog(example) + prlog(desc) + prlog("Example usage") + prlog(example) end local function debug(...) - if DEBUG then - prlog("debug:", ...) - end + if DEBUG then + prlog("debug:", ...) + end end --- This function is a lua-implementation of -- cmdhf14a.c:waitCmd(uint8_t iSelect) local function waitCmd(iSelect) - local response = core.WaitForResponseTimeout(cmds.CMD_ACK,1000) - if response then - local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response) - - local iLen = arg0 - if iSelect then iLen = arg1 end - debug(("Received %i octets (arg0:%d, arg1:%d)"):format(iLen, arg0, arg1)) - if iLen == 0 then return nil, "No response from tag" end - local recv = string.sub(response,count, iLen+count-1) - return recv - end - return nil, "No response from device" + local response = core.WaitForResponseTimeout(cmds.CMD_ACK,1000) + if response then + local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',response) + + local iLen = arg0 + if iSelect then iLen = arg1 end + debug(("Received %i octets (arg0:%d, arg1:%d)"):format(iLen, arg0, arg1)) + if iLen == 0 then return nil, "No response from tag" end + local recv = string.sub(response,count, iLen+count-1) + return recv + end + return nil, "No response from device" end local function show(data) - if DEBUG then - local formatString = ("H%d"):format(string.len(data)) - local _,hexdata = bin.unpack(formatString, data) - debug("Hexdata" , hexdata) - end + if DEBUG then + local formatString = ("H%d"):format(string.len(data)) + local _,hexdata = bin.unpack(formatString, data) + debug("Hexdata" , hexdata) + end end --- Fire up a connection with a tag, return uid -- @return UID if successfull -- @return nil, errormessage if unsuccessfull local function open() - debug("Opening connection") - core.clearCommandBuffer() - local x = string.format("hf 14a raw -r -p -s") - debug(x) - core.console(x) - debug("done") - data, err = waitCmd(true) - if err then return oops(err) end - show(data) - local formatString = ("H%d"):format(string.len(data)) - local _,uid = bin.unpack(formatString, data) - return uid + debug("Opening connection") + core.clearCommandBuffer() + local x = string.format("hf 14a raw -r -p -s") + debug(x) + core.console(x) + debug("done") + data, err = waitCmd(true) + if err then return oops(err) end + show(data) + local formatString = ("H%d"):format(string.len(data)) + local _,uid = bin.unpack(formatString, data) + return uid end --- Shut down tag communication -- return no return values local function close() - debug("Closing connection") - core.clearCommandBuffer() - local x = string.format("hf 14a raw -r") - debug(x) - core.console(x) - debug("done") - --data, err = waitCmd(true) - --data, err = waitCmd(false) + debug("Closing connection") + core.clearCommandBuffer() + local x = string.format("hf 14a raw -r") + debug(x) + core.console(x) + debug("done") + --data, err = waitCmd(true) + --data, err = waitCmd(false) end @@ -143,105 +143,105 @@ end -- @return {block, block+1, block+2, block+3} if successfull -- @return nil, errormessage if unsuccessfull local function getBlock(block) - local data, err + local data, err - core.clearCommandBuffer() - - local x = string.format("hf 14a raw -r -c -p 30 %02x", block) - debug(x) - core.console(x) - debug("done") - -- By now, there should be an ACK waiting from the device, since - -- we used the -r flag (don't read response). + core.clearCommandBuffer() - data, err = waitCmd(false) - if err then return oops(err) end - show(data) - - if string.len(data) < 18 then - return nil, ("Expected at least 18 bytes, got %d - this tag is not NDEF-compliant"):format(string.len(data)) - end - -- Now, parse out the block data - -- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155 - -- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC - b0 = string.sub(data,1,4) - b1 = string.sub(data,5,8) - b2 = string.sub(data,9,12) - b3 = string.sub(data,13,16) - return {b0,b1,b2,b3} + local x = string.format("hf 14a raw -r -c -p 30 %02x", block) + debug(x) + core.console(x) + debug("done") + -- By now, there should be an ACK waiting from the device, since + -- we used the -r flag (don't read response). + + data, err = waitCmd(false) + if err then return oops(err) end + show(data) + + if string.len(data) < 18 then + return nil, ("Expected at least 18 bytes, got %d - this tag is not NDEF-compliant"):format(string.len(data)) + end + -- Now, parse out the block data + -- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155 + -- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC + b0 = string.sub(data,1,4) + b1 = string.sub(data,5,8) + b2 = string.sub(data,9,12) + b3 = string.sub(data,13,16) + return {b0,b1,b2,b3} end local function main( args) - debug("script started") - local err, data, data2,k,v,i - -- Read the parameters - for o, a in getopt.getopt(args, 'hd') do - if o == "h" then help() return end - if o == "d" then DEBUG = true end - end + debug("script started") + local err, data, data2,k,v,i + -- Read the parameters + for o, a in getopt.getopt(args, 'hd') do + if o == "h" then help() return end + if o == "d" then DEBUG = true end + end - -- Info contained within the tag (block 0 example) - -- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155 - -- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC - -- MM?? ???? ???? ???? ???? ???? NNVV SS?? ---- - -- M = Manufacturer info - -- N = NDEF-Structure-Compliant (if value is E1) - -- V = NFC Forum Specification version (if 10 = v1.0) + -- Info contained within the tag (block 0 example) + -- 0534 00B9 049C AD7F 4A00 0000 E110 1000 2155 + -- b0b0 b0b0 b1b1 b1b1 b2b2 b2b2 b3b3 b3b3 CRCC + -- MM?? ???? ???? ???? ???? ???? NNVV SS?? ---- + -- M = Manufacturer info + -- N = NDEF-Structure-Compliant (if value is E1) + -- V = NFC Forum Specification version (if 10 = v1.0) - -- First, 'connect' (fire up the field) and get the uid - local uidHexstr = open() + -- First, 'connect' (fire up the field) and get the uid + local uidHexstr = open() - -- First, get blockt 3 byte 2 - local blocks, err = getBlock(0) - if err then return oops(err) end - -- Block 3 contains number of blocks - local b3chars = {string.byte(blocks[4], 1,4)} - local numBlocks = b3chars[3] * 2 + 6 - prlog("Number of blocks:", numBlocks) + -- First, get blockt 3 byte 2 + local blocks, err = getBlock(0) + if err then return oops(err) end + -- Block 3 contains number of blocks + local b3chars = {string.byte(blocks[4], 1,4)} + local numBlocks = b3chars[3] * 2 + 6 + prlog("Number of blocks:", numBlocks) - -- NDEF compliant? - if b3chars[1] ~= 0xE1 then - return oops("This tag is not NDEF-Compliant") - end + -- NDEF compliant? + if b3chars[1] ~= 0xE1 then + return oops("This tag is not NDEF-Compliant") + end - local ndefVersion = b3chars[2] + local ndefVersion = b3chars[2] - -- Block 1, byte 1 contains manufacturer info - local bl1_b1 = string.byte(blocks[1], 1) - local manufacturer = taglib.lookupManufacturer(bl1_b1) + -- Block 1, byte 1 contains manufacturer info + local bl1_b1 = string.byte(blocks[1], 1) + local manufacturer = taglib.lookupManufacturer(bl1_b1) - -- Reuse existing info - local blockData = {blocks[1],blocks[2],blocks[3],blocks[4]} + -- Reuse existing info + local blockData = {blocks[1],blocks[2],blocks[3],blocks[4]} - --[[ Due to the infineon my-d move bug - (if I send 30 0F i receive block0f+block00+block01+block02 insted of block0f+block10+block11+block12) - the only way to avoid this is to send the read command as many times as block numbers - removing bytes from 5 to 18 from each answer. - --]] - prlog("Dumping data...please wait") - for i=4,numBlocks-1,1 do - blocks, err = getBlock(i) - if err then return oops(err) end - table.insert(blockData,blocks[1]) - end - -- Deactivate field - close() - -- Print results - prlog(string.format("Tag manufacturer: %s", manufacturer)) - prlog(string.format("Tag UID: %s", uidHexstr)) - prlog(string.format("Tag NDEF version: 0x%02x", ndefVersion)) - - for k,v in ipairs(blockData) do - prlog(string.format("Block %02x: %02x %02x %02x %02x",k-1, string.byte(v, 1,4))) - end - local filename, err = utils.writeDumpFile(uidHexstr, blockData) - if err then return oops(err) end + --[[ Due to the infineon my-d move bug + (if I send 30 0F i receive block0f+block00+block01+block02 insted of block0f+block10+block11+block12) + the only way to avoid this is to send the read command as many times as block numbers + removing bytes from 5 to 18 from each answer. + --]] + prlog("Dumping data...please wait") + for i=4,numBlocks-1,1 do + blocks, err = getBlock(i) + if err then return oops(err) end + table.insert(blockData,blocks[1]) + end + -- Deactivate field + close() + -- Print results + prlog(string.format("Tag manufacturer: %s", manufacturer)) + prlog(string.format("Tag UID: %s", uidHexstr)) + prlog(string.format("Tag NDEF version: 0x%02x", ndefVersion)) - prlog(string.format("Dumped data into %s", filename)) + for k,v in ipairs(blockData) do + prlog(string.format("Block %02x: %02x %02x %02x %02x",k-1, string.byte(v, 1,4))) + end + local filename, err = utils.writeDumpFile(uidHexstr, blockData) + if err then return oops(err) end + + prlog(string.format("Dumped data into %s", filename)) end main(args) \ No newline at end of file diff --git a/client/scripts/ntag_3d.lua b/client/scripts/ntag_3d.lua index 278f800be..890f29d94 100644 --- a/client/scripts/ntag_3d.lua +++ b/client/scripts/ntag_3d.lua @@ -12,25 +12,25 @@ Thanks to @jack for his invaluable input on some of the configuration. example =[[ -- This will generate GOLD, PLA, TH, EU, 200m, tagbased uid. script run ntag_3d -c 46 -m 50 -p 5448 -s 4555 -l 200 - + -- This will generate GOLD, PLA, TH, EU, 200m, userbased uid. script run ntag_3d -u 11223344556677 -c 46 -m 50 -p 5448 -s 4555 -l 200 - - -- This will generate GOLD, PLA, TH, EU, 200m, userbased uid. and configure a MAGIC NTAG. - script run ntag_3d -u 11223344556677 -c 46 -m 50 -p 5448 -s 4555 -l 200 -1 + + -- This will generate GOLD, PLA, TH, EU, 200m, userbased uid. and configure a MAGIC NTAG. + script run ntag_3d -u 11223344556677 -c 46 -m 50 -p 5448 -s 4555 -l 200 -1 ]] usage = [[ script run calc_ntag_3d -h -t -u -c -m -p -s -l Arguments: - -h : this help - -t : selftest - -u : UID - -c : color of filament - -m : material of filament - -p : Manufacturer region - -s : Sales region - -l : Spool length. Use only 100,200,300. 300 has problems on OSX + -h : this help + -t : selftest + -u : UID + -c : color of filament + -m : material of filament + -p : Manufacturer region + -s : Sales region + -l : Spool length. Use only 100,200,300. 300 has problems on OSX ]] local DEBUG = true @@ -40,344 +40,344 @@ local band = bit32.band local rshift = bit32.rshift local _regions = { - {'4742', 'GB'}, - {'5457', 'TW'}, - {'4555', 'EU'}, - {'5553', 'US'}, - {'454E', 'EN'}, - {'4A50', 'JP'}, - {'434E', 'CN'}, - {'5448', 'TH'}, - {'4153', 'AS'}, - {'5246', 'RF'}, - {'4746', 'GF'}, - {'4341', 'CA'}, - {'504D', 'PM'}, - {'5044', 'PD'}, + {'4742', 'GB'}, + {'5457', 'TW'}, + {'4555', 'EU'}, + {'5553', 'US'}, + {'454E', 'EN'}, + {'4A50', 'JP'}, + {'434E', 'CN'}, + {'5448', 'TH'}, + {'4153', 'AS'}, + {'5246', 'RF'}, + {'4746', 'GF'}, + {'4341', 'CA'}, + {'504D', 'PM'}, + {'5044', 'PD'}, } local _manufacturers = { - {'5457', 'TW'}, - {'434E', 'CN'}, - {'5448', 'TH'}, + {'5457', 'TW'}, + {'434E', 'CN'}, + {'5448', 'TH'}, } local _sales = { - {'4742', 'GB'}, - {'4555', 'EU'}, - {'5553', 'US'}, - {'454E', 'EN'}, - {'504D', 'PM'}, + {'4742', 'GB'}, + {'4555', 'EU'}, + {'5553', 'US'}, + {'454E', 'EN'}, + {'504D', 'PM'}, } local _materials = { - {'20', 'Other material'}, - {'41', 'ABS'}, - {'46', 'Flexible TPE Tree'}, - {'46', 'TPE'}, - {'46', 'PVA'}, - {'47', 'PETG'}, - {'50', 'PLA'}, - {'51', 'PLA'}, - {'54', 'Tough PLA'}, - {'55', 'UVCR'}, - {'56', 'Water Soluble PVA'}, + {'20', 'Other material'}, + {'41', 'ABS'}, + {'46', 'Flexible TPE Tree'}, + {'46', 'TPE'}, + {'46', 'PVA'}, + {'47', 'PETG'}, + {'50', 'PLA'}, + {'51', 'PLA'}, + {'54', 'Tough PLA'}, + {'55', 'UVCR'}, + {'56', 'Water Soluble PVA'}, } local _colors = { - {'30', 'Bronze'}, - {'31', 'Silver'}, - {'32', 'Clear Red'}, - {'33', 'Clear'}, - {'34', 'Bottle Green'}, - {'35', 'Neon Magenta'}, - {'36', 'SteelBlue'}, - {'37', 'Sun Orange'}, - {'38', 'Pearl White'}, - {'39', 'Copper'}, - {'41', 'Purple'}, - {'42', 'Blue'}, - {'43', 'Neon Tangerine'}, - {'44', 'Viridity'}, - {'45', 'Olivine'}, - {'46', 'Gold'}, - {'47', 'Green'}, - {'48', 'Neon Green'}, - {'49', 'Snow White'}, - {'4A', 'Neon Yellow'}, - {'4B', 'Black'}, - {'4C', 'Violet'}, - {'4D', 'Grape Purple'}, - {'4E', 'Purpurine'}, - {'4F', 'Clear Yellow'}, - {'50', 'Clear Green'}, - {'51', 'Clear Tangerine'}, - {'52', 'Red'}, - {'53', 'Cyber Yellow'}, - {'54', 'Tangerine'}, - {'55', 'Clear Blue'}, - {'56', 'Clear Purple'}, - {'57', 'White'}, - {'58', 'Clear Magenta'}, - {'59', 'Yellow'}, - {'5A', 'Nature'}, + {'30', 'Bronze'}, + {'31', 'Silver'}, + {'32', 'Clear Red'}, + {'33', 'Clear'}, + {'34', 'Bottle Green'}, + {'35', 'Neon Magenta'}, + {'36', 'SteelBlue'}, + {'37', 'Sun Orange'}, + {'38', 'Pearl White'}, + {'39', 'Copper'}, + {'41', 'Purple'}, + {'42', 'Blue'}, + {'43', 'Neon Tangerine'}, + {'44', 'Viridity'}, + {'45', 'Olivine'}, + {'46', 'Gold'}, + {'47', 'Green'}, + {'48', 'Neon Green'}, + {'49', 'Snow White'}, + {'4A', 'Neon Yellow'}, + {'4B', 'Black'}, + {'4C', 'Violet'}, + {'4D', 'Grape Purple'}, + {'4E', 'Purpurine'}, + {'4F', 'Clear Yellow'}, + {'50', 'Clear Green'}, + {'51', 'Clear Tangerine'}, + {'52', 'Red'}, + {'53', 'Cyber Yellow'}, + {'54', 'Tangerine'}, + {'55', 'Clear Blue'}, + {'56', 'Clear Purple'}, + {'57', 'White'}, + {'58', 'Clear Magenta'}, + {'59', 'Yellow'}, + {'5A', 'Nature'}, } --- -- local function find( arr, name ) - if not name then return nil end + if not name then return nil end name = name:lower() for k, v in pairs(arr) do - if ( v[2]:lower() == name or v[1]:lower() == name ) then - return v - end - end - return nil + if ( v[2]:lower() == name or v[1]:lower() == name ) then + return v + end + end + return nil end --- -- local function list( arr, desc ) - print ('Value\t'..desc) - print (string.rep('=', 20)) + print ('Value\t'..desc) + print (string.rep('=', 20)) for k, v in pairs(arr) do - print(("%s\t%s"):format(v[1],v[2])) - end + print(("%s\t%s"):format(v[1],v[2])) + end end ---- +--- -- A debug printout-function local function dbg(args) - if not DEBUG then return end - - if type(args) == 'table' then - local i = 1 - while result[i] do - dbg(result[i]) - i = i+1 - end - else - print('###', args) - end -end ---- + if not DEBUG then return end + + if type(args) == 'table' then + local i = 1 + while result[i] do + dbg(result[i]) + i = i+1 + end + else + print('###', args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print('ERROR: ',err) - return nil,err + print('ERROR: ',err) + return nil,err end ---- +--- -- Usage help local function help() - print(copyright) - print(version) - print(desc) - print('Example usage') - print(example) + print(copyright) + print(version) + print(desc) + print('Example usage') + print(example) end -- -- Exit message local function ExitMsg(msg) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print(msg) - print() + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() end --- -- local function write_tag(uid, t) - print('Writing to tag') - core.console('hf mf dbg 0') - - local cmd = '' - local pwd, pack = core.keygen_algo_d(uid) - - for i= 8, 23 do - cmd = ('hf mfu wrbl b %02d d %s k %08X'):format(i, t[i], pwd) - core.console(cmd) - end - - --cfg1 - core.console(('hf mfu wrbl b 42 d %s k %08X'):format(t[42], pwd)) - --cfg0 - core.console(('hf mfu wrbl b 41 d %s k %08X'):format(t[41], pwd)) - --dynamic - core.console(('hf mfu wrbl b 40 d %s k %08X'):format(t[40], pwd)) - - core.console('hf mf dbg 1') - print('Done') + print('Writing to tag') + core.console('hf mf dbg 0') + + local cmd = '' + local pwd, pack = core.keygen_algo_d(uid) + + for i= 8, 23 do + cmd = ('hf mfu wrbl b %02d d %s k %08X'):format(i, t[i], pwd) + core.console(cmd) + end + + --cfg1 + core.console(('hf mfu wrbl b 42 d %s k %08X'):format(t[42], pwd)) + --cfg0 + core.console(('hf mfu wrbl b 41 d %s k %08X'):format(t[41], pwd)) + --dynamic + core.console(('hf mfu wrbl b 40 d %s k %08X'):format(t[40], pwd)) + + core.console('hf mf dbg 1') + print('Done') end --- -- configures a magic NTAG for NTAG213, with UID and PWD,PACK. local function configure_magic_ntag(uid) - print('Configuring MAGIC NTAG') - -- Save the global args, those are *our* arguments - local myargs = args - - local pwd, pack = core.keygen_algo_d(uid) - - -- Set the arguments for mfu_magic script v1.0.8 - -- -t 12 == configure NTAG213F - -- -u == set UID - -- -p == set pwd - -- -a == set pack - args =('-t 12 -u %s -p %08X -a %04X'):format(uid, pwd, pack) - require('../scripts/mfu_magic') - - -- Set back args. Not that it's used, just for the karma... - args = myargs - - print('Done') + print('Configuring MAGIC NTAG') + -- Save the global args, those are *our* arguments + local myargs = args + + local pwd, pack = core.keygen_algo_d(uid) + + -- Set the arguments for mfu_magic script v1.0.8 + -- -t 12 == configure NTAG213F + -- -u == set UID + -- -p == set pwd + -- -a == set pack + args =('-t 12 -u %s -p %08X -a %04X'):format(uid, pwd, pack) + require('../scripts/mfu_magic') + + -- Set back args. Not that it's used, just for the karma... + args = myargs + + print('Done') end --- -- generates random hex numbers between 31-39 local function random_num_hex(length) - local str = "" - local i - for i = 1, length, 1 do - str = str..math.random(31, 39) - end - return str + local str = "" + local i + for i = 1, length, 1 do + str = str..math.random(31, 39) + end + return str end --- -- local function nwo( val ) - local b1 = band(val, 0xFF) - local b2 = band( rshift(val, 8), 0xFF) - local b3 = band( rshift(val, 16), 0xFF) - local b4 = band( rshift(val, 24), 0xFF) - return ('%02X%02X%02X%02X'):format(b1, b2, b3, b4) + local b1 = band(val, 0xFF) + local b2 = band( rshift(val, 8), 0xFF) + local b3 = band( rshift(val, 16), 0xFF) + local b4 = band( rshift(val, 24), 0xFF) + return ('%02X%02X%02X%02X'):format(b1, b2, b3, b4) end --- -- NTAG213 template local function template_NTAG213(uid, material, color, length, manufacture, sales) - local pwd, pack = core.keygen_algo_d(uid) + local pwd, pack = core.keygen_algo_d(uid) - local m = tonumber(length, 10) * 1000 - local m_str = nwo(m) - - local t = {} - -- default empty file - for i = 0,42 do - t[i] = '00000000' - end --- t[4] = '0103A00C' -- --- t[5] = '340300FE' -- + local m = tonumber(length, 10) * 1000 + local m_str = nwo(m) + + local t = {} + -- default empty file + for i = 0,42 do + t[i] = '00000000' + end +-- t[4] = '0103A00C' -- +-- t[5] = '340300FE' -- -- 6,7 - t[8] = '5A'..material..color..'00' -- 5A, material, color, 00 - t[9] = '00'..random_num_hex(3) -- 00, three bytes serial number - t[10] = m_str -- total capacity - t[11] = m_str -- total capacity - t[12] = 'D2002D00' -- fixed - t[13] = manufacture..sales -- regioner, - t[14] = random_num_hex(4) -- serial number + t[8] = '5A'..material..color..'00' -- 5A, material, color, 00 + t[9] = '00'..random_num_hex(3) -- 00, three bytes serial number + t[10] = m_str -- total capacity + t[11] = m_str -- total capacity + t[12] = 'D2002D00' -- fixed + t[13] = manufacture..sales -- regioner, + t[14] = random_num_hex(4) -- serial number -- 15,16 - t[17] = '34000000' -- fixed + t[17] = '34000000' -- fixed -- 18,19 - -- remaining capacity of spool - t[20] = m_str - t[21] = nwo( bxor( m, 0x54321248)) - t[22] = nwo( bxor( (m - 3876923 ), 0x31275455)) - t[23] = nwo( bxor( (m + 6923923 ), 0x76235481)) --- 24-39 - t[40] = '000000BD' --dynamic - t[41] = '07000008' --cfg0 - t[42] = '80050000' --cfg1 - t[43] = ('%08X'):format(pwd) - t[44] = ('%04X0000'):format(pack) - return t + -- remaining capacity of spool + t[20] = m_str + t[21] = nwo( bxor( m, 0x54321248)) + t[22] = nwo( bxor( (m - 3876923 ), 0x31275455)) + t[23] = nwo( bxor( (m + 6923923 ), 0x76235481)) +-- 24-39 + t[40] = '000000BD' --dynamic + t[41] = '07000008' --cfg0 + t[42] = '80050000' --cfg1 + t[43] = ('%08X'):format(pwd) + t[44] = ('%04X0000'):format(pack) + return t end --- -- outputs the called arguments local function print_conf(uid, material, color, length, producer, sales ) - print('Create tag as following') - print( string.rep('--',16) ) - print('UID ', uid) - print('Material ', material[2]) - print('Color ', color[2]) - print('Spool length ', length) - print('Region') - print(' manufacturer', producer[2]) - print(' sales ', sales[2]) - print( string.rep('--',16) ) + print('Create tag as following') + print( string.rep('--',16) ) + print('UID ', uid) + print('Material ', material[2]) + print('Color ', color[2]) + print('Spool length ', length) + print('Region') + print(' manufacturer', producer[2]) + print(' sales ', sales[2]) + print( string.rep('--',16) ) end --- -- self test -local function selftest() - list(_regions, 'Regions') - list(_materials, 'Materials') - list(_colors, 'Colors') - return nil +local function selftest() + list(_regions, 'Regions') + list(_materials, 'Materials') + list(_colors, 'Colors') + return nil end ---- +--- -- The main entry point local function main(args) - math.randomseed(os.time()); - math.random(); + math.randomseed(os.time()); + math.random(); - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print() - - local uid = '04C5DF4A6D5180' - local useUID = false - local useMAGIC = false - local material, color, length, producer, sales - - if #args == 0 then return help() end + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print() - -- Read the parameters - for o, a in getopt.getopt(args, 'ht1u:l:m:c:p:s:') do - if o == "h" then return help() end - if o == "t" then return selftest() end - if o == "u" then uid = a; useUID = true end - if o == "m" then material = a end - if o == "c" then color = a end - if o == "l" then length = tonumber(a) end - if o == "p" then producer = a end - if o == "s" then sales = a end - if o == "1" then useMAGIC = true end - end + local uid = '04C5DF4A6D5180' + local useUID = false + local useMAGIC = false + local material, color, length, producer, sales - color = find(_colors, color) - if not color then list(_colors, 'Colors'); return oops('\n\nNot valid color') end - - material = find(_materials, material) - if not material then list(_materials, 'Materials'); return oops('\n\nNot valid material') end - - producer = find(_manufacturers, producer) - if not producer then list(_manufacturers, 'Regions Manufacturers'); return oops('\n\nNo valid manufacturer region') end + if #args == 0 then return help() end - sales = find(_sales, sales) - if not sales then list(_sales, 'Regions Sales'); return oops('\n\nNo valid sales region') end - - if length > 300 then - return oops('\n\nNot valid spool length. Must be lesser than 300') - end - - if useUID then - -- uid string checks - if uid == nil then return oops('empty uid string') end - if #uid == 0 then return oops('empty uid string') end - if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end - else - -- GET TAG UID - local tag, err = lib14a.read(false, true) - if not tag then return oops(err) end - core.clearCommandBuffer() - uid = tag.uid - end + -- Read the parameters + for o, a in getopt.getopt(args, 'ht1u:l:m:c:p:s:') do + if o == "h" then return help() end + if o == "t" then return selftest() end + if o == "u" then uid = a; useUID = true end + if o == "m" then material = a end + if o == "c" then color = a end + if o == "l" then length = tonumber(a) end + if o == "p" then producer = a end + if o == "s" then sales = a end + if o == "1" then useMAGIC = true end + end - --print - print_conf(uid, material, color, length, producer, sales ) - - -- create template - local t = template_NTAG213(uid, material[1], color[1], length, producer[1], sales[1]) + color = find(_colors, color) + if not color then list(_colors, 'Colors'); return oops('\n\nNot valid color') end - -- using MAGIC NTAG - if useMAGIC then - configure_magic_ntag(uid) - end - - -- write template data to tag - write_tag(uid, t) + material = find(_materials, material) + if not material then list(_materials, 'Materials'); return oops('\n\nNot valid material') end + + producer = find(_manufacturers, producer) + if not producer then list(_manufacturers, 'Regions Manufacturers'); return oops('\n\nNo valid manufacturer region') end + + sales = find(_sales, sales) + if not sales then list(_sales, 'Regions Sales'); return oops('\n\nNo valid sales region') end + + if length > 300 then + return oops('\n\nNot valid spool length. Must be lesser than 300') + end + + if useUID then + -- uid string checks + if uid == nil then return oops('empty uid string') end + if #uid == 0 then return oops('empty uid string') end + if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end + else + -- GET TAG UID + local tag, err = lib14a.read(false, true) + if not tag then return oops(err) end + core.clearCommandBuffer() + uid = tag.uid + end + + --print + print_conf(uid, material, color, length, producer, sales ) + + -- create template + local t = template_NTAG213(uid, material[1], color[1], length, producer[1], sales[1]) + + -- using MAGIC NTAG + if useMAGIC then + configure_magic_ntag(uid) + end + + -- write template data to tag + write_tag(uid, t) end main(args) \ No newline at end of file diff --git a/client/scripts/parameters.lua b/client/scripts/parameters.lua index fa260204f..f51266f7f 100644 --- a/client/scripts/parameters.lua +++ b/client/scripts/parameters.lua @@ -6,40 +6,40 @@ getopt = require('getopt') usage = "script run parameters.lua -a 1 -blala -c -de" author = "Martin Holst Swende" desc =[[ -This is an example script to demonstrate handle parameters in scripts. +This is an example script to demonstrate handle parameters in scripts. For more info, check the comments in the code ]] local function main(args) - print(desc) - print("These parameters were passed") - --[[ - When passing parameters, - x: means that a value should follow x - y means that 'y' is a flag, either on or off - So, the string a:b:def means that we support up to - 5 parameters; two with values and three flags. The following - should be valid: + print(desc) + print("These parameters were passed") + --[[ + When passing parameters, + x: means that a value should follow x + y means that 'y' is a flag, either on or off + So, the string a:b:def means that we support up to + 5 parameters; two with values and three flags. The following + should be valid: - script run parameters.lua -a 1 -blala -c -de + script run parameters.lua -a 1 -blala -c -de - Notice two things: - 1. 'blala' works just like 'b lala', both set 'b' to 'lala' - 2. Flags can be put together, '-de' is the same as '-d -e' - 3. The format -b=lala is *not* supported - 4. The format b lala (without -) is *not* supported - --]] + Notice two things: + 1. 'blala' works just like 'b lala', both set 'b' to 'lala' + 2. Flags can be put together, '-de' is the same as '-d -e' + 3. The format -b=lala is *not* supported + 4. The format b lala (without -) is *not* supported + --]] - for o, a in getopt.getopt(args, 'a:b:ced') do - print(o, a) - end + for o, a in getopt.getopt(args, 'a:b:ced') do + print(o, a) + end end --[[ -In the future, we may implement so that scripts are invoked directly +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. +compatibility, I have done so, but I invoke my main from here. --]] main(args) \ No newline at end of file diff --git a/client/scripts/read_pwd_mem.lua b/client/scripts/read_pwd_mem.lua index a0688a639..4611c32cc 100644 --- a/client/scripts/read_pwd_mem.lua +++ b/client/scripts/read_pwd_mem.lua @@ -1,141 +1,141 @@ -local getopt = require('getopt') -local bin = require('bin') - -copyright = 'Copyright (c) 2018 Bogito. All rights reserved.' -author = "Bogito" -version = 'v1.0.1' -desc = -[[ -This script will read the flash memory of RDV4 and print the stored passwords. -It was meant to be used as a help tool after using the BogRun standalone mode. - -(Iceman) script adapted to read and print keys in the default dictionary flashmemory sections. -]] -usage = -[[ -Usage: - script run read_pwd_mem -h -o -l -k - -Arguments: - -h : this help - -o : memory offset, default is 0 - -l : length in bytes, default is 256 - -k : key length in bytes <4|6|8> , default is 4 - -m : print Mifare dictionary keys - -t : print t55xx dictionary passwords - -i : print iClass dictionary keys -]] -example = -[[ - -- This will scan the first 256 bytes of flash memory for stored passwords - script run read_pwd_mem - - -- This will scan 256 bytes of flash memory at offset 64 for stored passwords - script run read_pwd_mem -o 64 - - -- This will scan 32 bytes of flash memory at offset 64 for stored passwords - script run read_pwd_mem -o 64 -l 32 - - -- This will print found - script run read_pwd_mem -o 241664 -k 6 -]] ---- --- This is only meant to be used when errors occur -local function oops(err) - print("ERROR: ", err) - return nil, err -end ---- --- Usage help -local function help() - print(copyright) - print(version) - print(desc) - print(usage) - print('Example usage:') - print(example) -end ---- --- The main entry point -local function main(args) - - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print() - - local data, err, quadlet - local cnt = 0 - local offset = 0 - local length = 256 - local keylength = 4 - local usedkey = false - - for o, a in getopt.getopt(args, 'ho:l:k:mti') do - - -- help - if o == "h" then return help() end - - -- offset - if o == "o" then offset = tonumber(a) end - - -- num of bytes to read - if o == "l" then length = tonumber(a) end - - -- keylength - if o == "k" then keylength = tonumber(a); usedkey = true end - - if o == "m" then keylength =6; usedkey = true; offset = 0x3F000-0x4000; end - if o == "t" then keylength =4; usedkey = true; offset = 0x3F000-0x3000; end - if o == "i" then keylength =8; usedkey = true; offset = 0x3F000-0x5000; end - end - - if length < 0 or length > 256 then - return oops('Error: Length is not valid. Must be less than 256') - end - - if (offset < 0) or (offset % 4 ~= 0) then - return oops('Error: Offset is not valid. Mod-4 values are only allowed.') - end - - print('Memory offset', offset) - print('Length ', length) - print('Key length ', keylength) - print( string.rep('--',20) ) - - if usedkey then length = 4096 end - - data, err = core.GetFromFlashMem(offset, length) - if err then return oops(err) end - - if usedkey then - - _, keys, s = bin.unpack('SH'..length-2, data) - if keys == 0xFFFF then return "No keys found in section" end - - local kl = keylength * 2 - for i = 1, keys do - - key = string.sub(s, (i - 1) * kl + 1, i * kl ) - print(string.format("[%02d] %s",i, key)) - end - print( string.rep('--',20) ) - print( ('[+] found %d passwords'):format(keys)) - else - - _, s = bin.unpack('H'..length, data) - - local cnt = 0, i - for i = 1, (length/keylength) do - - key = string.sub(s, (i-1)*8+1, i*8) - if key == "FFFFFFFF" then break end - print(string.format("[%02d] %s",i, key)) - cnt = cnt + 1 - end - print( string.rep('--',20) ) - print( ('[+] found %d passwords'):format(cnt)) - end - print( string.rep('--',20) ) -end - -main(args) +local getopt = require('getopt') +local bin = require('bin') + +copyright = 'Copyright (c) 2018 Bogito. All rights reserved.' +author = "Bogito" +version = 'v1.0.1' +desc = +[[ +This script will read the flash memory of RDV4 and print the stored passwords. +It was meant to be used as a help tool after using the BogRun standalone mode. + +(Iceman) script adapted to read and print keys in the default dictionary flashmemory sections. +]] +usage = +[[ +Usage: + script run read_pwd_mem -h -o -l -k + +Arguments: + -h : this help + -o : memory offset, default is 0 + -l : length in bytes, default is 256 + -k : key length in bytes <4|6|8> , default is 4 + -m : print Mifare dictionary keys + -t : print t55xx dictionary passwords + -i : print iClass dictionary keys +]] +example = +[[ + -- This will scan the first 256 bytes of flash memory for stored passwords + script run read_pwd_mem + + -- This will scan 256 bytes of flash memory at offset 64 for stored passwords + script run read_pwd_mem -o 64 + + -- This will scan 32 bytes of flash memory at offset 64 for stored passwords + script run read_pwd_mem -o 64 -l 32 + + -- This will print found + script run read_pwd_mem -o 241664 -k 6 +]] +--- +-- This is only meant to be used when errors occur +local function oops(err) + print("ERROR: ", err) + return nil, err +end +--- +-- Usage help +local function help() + print(copyright) + print(version) + print(desc) + print(usage) + print('Example usage:') + print(example) +end +--- +-- The main entry point +local function main(args) + + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print() + + local data, err, quadlet + local cnt = 0 + local offset = 0 + local length = 256 + local keylength = 4 + local usedkey = false + + for o, a in getopt.getopt(args, 'ho:l:k:mti') do + + -- help + if o == "h" then return help() end + + -- offset + if o == "o" then offset = tonumber(a) end + + -- num of bytes to read + if o == "l" then length = tonumber(a) end + + -- keylength + if o == "k" then keylength = tonumber(a); usedkey = true end + + if o == "m" then keylength =6; usedkey = true; offset = 0x3F000-0x4000; end + if o == "t" then keylength =4; usedkey = true; offset = 0x3F000-0x3000; end + if o == "i" then keylength =8; usedkey = true; offset = 0x3F000-0x5000; end + end + + if length < 0 or length > 256 then + return oops('Error: Length is not valid. Must be less than 256') + end + + if (offset < 0) or (offset % 4 ~= 0) then + return oops('Error: Offset is not valid. Mod-4 values are only allowed.') + end + + print('Memory offset', offset) + print('Length ', length) + print('Key length ', keylength) + print( string.rep('--',20) ) + + if usedkey then length = 4096 end + + data, err = core.GetFromFlashMem(offset, length) + if err then return oops(err) end + + if usedkey then + + _, keys, s = bin.unpack('SH'..length-2, data) + if keys == 0xFFFF then return "No keys found in section" end + + local kl = keylength * 2 + for i = 1, keys do + + key = string.sub(s, (i - 1) * kl + 1, i * kl ) + print(string.format("[%02d] %s",i, key)) + end + print( string.rep('--',20) ) + print( ('[+] found %d passwords'):format(keys)) + else + + _, s = bin.unpack('H'..length, data) + + local cnt = 0, i + for i = 1, (length/keylength) do + + key = string.sub(s, (i-1)*8+1, i*8) + if key == "FFFFFFFF" then break end + print(string.format("[%02d] %s",i, key)) + cnt = cnt + 1 + end + print( string.rep('--',20) ) + print( ('[+] found %d passwords'):format(cnt)) + end + print( string.rep('--',20) ) +end + +main(args) diff --git a/client/scripts/remagic.lua b/client/scripts/remagic.lua index 10e25583a..29e9a2c56 100644 --- a/client/scripts/remagic.lua +++ b/client/scripts/remagic.lua @@ -4,100 +4,100 @@ example = "script run remagic" author = "Iceman" desc = [[ -This is a script that tries to bring back a chinese magic card (1k generation1) +This is a script that tries to bring back a chinese magic card (1k generation1) from the dead when it's block 0 has been written with bad values. or mifare Ultralight magic card which answers to chinese backdoor commands Arguments: - -h this help - -u remagic a Ultralight tag w 7 bytes UID. + -h this help + -u remagic a Ultralight tag w 7 bytes UID. ]] ---- +--- -- A debug printout-function local function dbg(args) - if DEBUG then - print('###', args) - end -end ---- + if DEBUG then + print('###', args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print('ERROR: ',err) + print('ERROR: ',err) end ---- +--- -- Usage help local function help() - print(desc) - print('Example usage') - print(example) + print(desc) + print('Example usage') + print(example) end local function cmdUltralight() - return { + return { --[[ --]] - [0] = "hf 14a raw -p -a -b 7 40", - [1] = "hf 14a raw -p -a 43", - [2] = "hf 14a raw -c -a A2005380712A", - [3] = "hf 14a raw -p -a -b 7 40", - [4] = "hf 14a raw -p -a 43", - [5] = "hf 14a raw -c -a A2010200D980", - [6] = "hf 14a raw -p -a -b 7 40", - [7] = "hf 14a raw -p -a 43", - [8] = "hf 14a raw -c -a A2025B480000", - [9] = "hf 14a raw -c -a 5000", - } + [0] = "hf 14a raw -p -a -b 7 40", + [1] = "hf 14a raw -p -a 43", + [2] = "hf 14a raw -c -a A2005380712A", + [3] = "hf 14a raw -p -a -b 7 40", + [4] = "hf 14a raw -p -a 43", + [5] = "hf 14a raw -c -a A2010200D980", + [6] = "hf 14a raw -p -a -b 7 40", + [7] = "hf 14a raw -p -a 43", + [8] = "hf 14a raw -c -a A2025B480000", + [9] = "hf 14a raw -c -a 5000", + } end local function cmdClassic() - return { + return { --[[ --]] - [0] = "hf 14a raw -p -a -b 7 40", - [1] = "hf 14a raw -p -a 43", - [2] = "hf 14a raw -c -p -a A000", - [3] = "hf 14a raw -c -p -a 01020304049802000000000000001001", - [4] = "hf 14a raw -c -a 5000", - } + [0] = "hf 14a raw -p -a -b 7 40", + [1] = "hf 14a raw -p -a 43", + [2] = "hf 14a raw -c -p -a A000", + [3] = "hf 14a raw -c -p -a 01020304049802000000000000001001", + [4] = "hf 14a raw -c -a 5000", + } end local function cmdRestoreST() - local arr = {} - for i = 0, 15 do - local blk = 3 + (4*i) - arr[i] = "hf mf csetbl "..blk.." FFFFFFFFFFFFFF078000FFFFFFFFFFFF" - end - return arr -end -local function sendCmds( cmds ) - for i = 0, #cmds do - if cmds[i] then - print ( cmds[i] ) - core.console( cmds[i] ) - core.clearCommandBuffer() - end - end + local arr = {} + for i = 0, 15 do + local blk = 3 + (4*i) + arr[i] = "hf mf csetbl "..blk.." FFFFFFFFFFFFFF078000FFFFFFFFFFFF" + end + return arr end ---- +local function sendCmds( cmds ) + for i = 0, #cmds do + if cmds[i] then + print ( cmds[i] ) + core.console( cmds[i] ) + core.clearCommandBuffer() + end + end +end +--- -- The main entry point function main(args) - local i - local cmds = {} - local isUltralight = false - - -- Read the parameters - for o, a in getopt.getopt(args, 'hu') do - if o == "h" then return help() end - if o == "u" then isUltralight = true end - end + local i + local cmds = {} + local isUltralight = false - core.clearCommandBuffer() - - if isUltralight then - sendCmds ( cmdUltralight() ) - else - sendCmds( cmdClassic() ) - sendCmds( cmdRestoreST() ) - end + -- Read the parameters + for o, a in getopt.getopt(args, 'hu') do + if o == "h" then return help() end + if o == "u" then isUltralight = true end + end + + core.clearCommandBuffer() + + if isUltralight then + sendCmds ( cmdUltralight() ) + else + sendCmds( cmdClassic() ) + sendCmds( cmdRestoreST() ) + end end main(args) diff --git a/client/scripts/test_t55x7_ask.lua b/client/scripts/test_t55x7_ask.lua index 189cc4734..3f224b28a 100644 --- a/client/scripts/test_t55x7_ask.lua +++ b/client/scripts/test_t55x7_ask.lua @@ -7,7 +7,7 @@ local format=string.format local floor=math.floor example =[[ - 1. script run test_t55x7_ask + 1. script run test_t55x7_ask ]] author = "Iceman" usage = "script run test_t55x7_ask" @@ -15,32 +15,32 @@ desc =[[ This script will program a T55x7 TAG with the configuration: block 0x00 data 0x000100 The outlined procedure is as following: ---ASK - 00 00 80 40 +--ASK + 00 00 80 40 -- max 2 -- manchester -- bit rate - + "lf t55xx write b 0 d 00008040" "lf t55xx detect" "lf t55xx info" Loop: - change the configuretion block 0 with: - -xx 00 xxxx = RF/8 - -xx 04 xxxx = RF/16 - -xx 08 xxxx = RF/32 - -xx 0C xxxx = RF/40 - -xx 10 xxxx = RF/50 - -xx 14 xxxx = RF/64 - -xx 18 xxxx = RF/100 - -xx 1C xxxx = RF/128 + change the configuretion block 0 with: + -xx 00 xxxx = RF/8 + -xx 04 xxxx = RF/16 + -xx 08 xxxx = RF/32 + -xx 0C xxxx = RF/40 + -xx 10 xxxx = RF/50 + -xx 14 xxxx = RF/64 + -xx 18 xxxx = RF/100 + -xx 1C xxxx = RF/128 testsuit for the ASK/MANCHESTER demod Arguments: - -h : this help + -h : this help ]] local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds @@ -51,90 +51,90 @@ local config1 = '00' local config2 = '8040' local procedurecmds = { - [1] = '%s%02X%s', - [2] = 'lf t55xx detect', - [3] = 'lf t55xx info', + [1] = '%s%02X%s', + [2] = 'lf t55xx detect', + [3] = 'lf t55xx info', } ---- +--- -- A debug printout-function local function dbg(args) - if not DEBUG then - return - end - + if not DEBUG then + return + end + if type(args) == "table" then - local i = 1 - while args[i] do - dbg(args[i]) - i = i+1 - end - else - print("###", args) - end -end ---- + local i = 1 + while args[i] do + dbg(args[i]) + i = i+1 + end + else + print("###", args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) + print("ERROR: ",err) end ---- +--- -- Usage help local function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end -- -- Exit message local function ExitMsg(msg) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print(msg) - print() + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() end local function test() - local y - local block = "00" - for y = 0x0, 0x1d, 0x4 do - for _ = 1, #procedurecmds do - local pcmd = procedurecmds[_] - - if #pcmd == 0 then - - elseif _ == 1 then + local y + local block = "00" + for y = 0x0, 0x1d, 0x4 do + for _ = 1, #procedurecmds do + local pcmd = procedurecmds[_] - local config = pcmd:format(config1, y, config2) - dbg(('lf t55xx write b 0 d %s'):format(config)) - config = tonumber(config,16) - - local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"} - local err = core.SendCommand(writecmd:getBytes()) - if err then return oops(err) end - local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) + if #pcmd == 0 then - else - dbg(pcmd) - core.console( pcmd ) - end - end - core.clearCommandBuffer() - end - print( string.rep('--',20) ) + elseif _ == 1 then + + local config = pcmd:format(config1, y, config2) + dbg(('lf t55xx write b 0 d %s'):format(config)) + config = tonumber(config,16) + + local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"} + local err = core.SendCommand(writecmd:getBytes()) + if err then return oops(err) end + local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) + + else + dbg(pcmd) + core.console( pcmd ) + end + end + core.clearCommandBuffer() + end + print( string.rep('--',20) ) end local function main(args) - print( string.rep('--',20) ) - print( string.rep('--',20) ) + print( string.rep('--',20) ) + print( string.rep('--',20) ) - -- Arguments for the script - for o, arg in getopt.getopt(args, 'h') do - if o == "h" then return help() end - end + -- Arguments for the script + for o, arg in getopt.getopt(args, 'h') do + if o == "h" then return help() end + end - core.clearCommandBuffer() - test() - print( string.rep('--',20) ) + core.clearCommandBuffer() + test() + print( string.rep('--',20) ) end main(args) \ No newline at end of file diff --git a/client/scripts/test_t55x7_bi.lua b/client/scripts/test_t55x7_bi.lua index f9a0688fe..dce5350dc 100644 --- a/client/scripts/test_t55x7_bi.lua +++ b/client/scripts/test_t55x7_bi.lua @@ -4,7 +4,7 @@ local bin = require('bin') local utils = require('utils') example =[[ - 1. script run test_t55x7_bi + 1. script run test_t55x7_bi ]] author = "Iceman" usage = "script run test_t55x7_bi" @@ -20,21 +20,21 @@ The outlined procedure is as following: "lf t55xx info" Loop: - change the configuretion block 0 with: - -xx01xxxx = RF/8 + change the configuretion block 0 with: + -xx01xxxx = RF/8 -xx05xxxx = RF/16 - -xx09xxxx = RF/32 - -xx0Dxxxx = RF/40 - -xx11xxxx = RF/50 - -xx15xxxx = RF/64 - -xx19xxxx = RF/100 - -xx1Dxxxx = RF/128 + -xx09xxxx = RF/32 + -xx0Dxxxx = RF/40 + -xx11xxxx = RF/50 + -xx15xxxx = RF/64 + -xx19xxxx = RF/100 + -xx1Dxxxx = RF/128 testsuit for the BIPHASE demod Arguments: - -h : this help + -h : this help ]] local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds @@ -45,90 +45,90 @@ local config1 = '00' local config2 = '0040' local procedurecmds = { - [1] = '%s%02X%s', - [2] = 'lf t55xx detect', - [3] = 'lf t55xx info', + [1] = '%s%02X%s', + [2] = 'lf t55xx detect', + [3] = 'lf t55xx info', } ---- +--- -- A debug printout-function local function dbg(args) - if not DEBUG then - return - end - + if not DEBUG then + return + end + if type(args) == "table" then - local i = 1 - while args[i] do - dbg(args[i]) - i = i+1 - end - else - print("###", args) - end -end ---- + local i = 1 + while args[i] do + dbg(args[i]) + i = i+1 + end + else + print("###", args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) + print("ERROR: ",err) end ---- +--- -- Usage help local function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end -- -- Exit message local function ExitMsg(msg) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print(msg) - print() + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() end local function test() - local y - local block = "00" - for y = 1, 0x1D, 4 do - for _ = 1, #procedurecmds do - local pcmd = procedurecmds[_] - - if #pcmd == 0 then - - elseif _ == 1 then + local y + local block = "00" + for y = 1, 0x1D, 4 do + for _ = 1, #procedurecmds do + local pcmd = procedurecmds[_] - local config = pcmd:format(config1, y, config2) - dbg(('lf t55xx write b 0 d %s'):format(config)) - - config = tonumber(config,16) - local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"} - local err = core.SendCommand(writecmd:getBytes()) - if err then return oops(err) end - local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) - else - dbg(pcmd) - core.console( pcmd ) - end - end - core.clearCommandBuffer() - end - print( string.rep('--',20) ) + if #pcmd == 0 then + + elseif _ == 1 then + + local config = pcmd:format(config1, y, config2) + dbg(('lf t55xx write b 0 d %s'):format(config)) + + config = tonumber(config,16) + local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"} + local err = core.SendCommand(writecmd:getBytes()) + if err then return oops(err) end + local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) + else + dbg(pcmd) + core.console( pcmd ) + end + end + core.clearCommandBuffer() + end + print( string.rep('--',20) ) end local function main(args) - print( string.rep('--',20) ) - print( string.rep('--',20) ) + print( string.rep('--',20) ) + print( string.rep('--',20) ) - -- Arguments for the script - for o, arg in getopt.getopt(args, 'h') do - if o == "h" then return help() end - end + -- Arguments for the script + for o, arg in getopt.getopt(args, 'h') do + if o == "h" then return help() end + end - core.clearCommandBuffer() - test() - print( string.rep('--',20) ) + core.clearCommandBuffer() + test() + print( string.rep('--',20) ) end main(args) diff --git a/client/scripts/test_t55x7_fsk.lua b/client/scripts/test_t55x7_fsk.lua index 0d067b96a..9dbb1b6bb 100644 --- a/client/scripts/test_t55x7_fsk.lua +++ b/client/scripts/test_t55x7_fsk.lua @@ -4,7 +4,7 @@ local bin = require('bin') local utils = require('utils') example =[[ - 1. script run test_t55x7_fsk + 1. script run test_t55x7_fsk ]] author = "Iceman" usage = "script run test_t55x7_fsk" @@ -12,32 +12,32 @@ desc =[[ This script will program a T55x7 TAG with the configuration: block 0x00 data 0x000100 The outlined procedure is as following: ---ASK - 00 00 80 40 +--ASK + 00 00 80 40 -- max 2 blocks -- FSK1 -- bit rate - + "lf t55xx write b 0 d 00007040" "lf t55xx detect" "lf t55xx info" Loop: - change the configuretion block 0 with: - -xx 00 xxxx = RF/8 + change the configuretion block 0 with: + -xx 00 xxxx = RF/8 -xx 04 xxxx = RF/16 - -xx 08 xxxx = RF/32 - -xx 0C xxxx = RF/40 - -xx 10 xxxx = RF/50 - -xx 14 xxxx = RF/64 - -xx 18 xxxx = RF/100 - -xx 1C xxxx = RF/128 + -xx 08 xxxx = RF/32 + -xx 0C xxxx = RF/40 + -xx 10 xxxx = RF/50 + -xx 14 xxxx = RF/64 + -xx 18 xxxx = RF/100 + -xx 1C xxxx = RF/128 testsuit for the ASK/MANCHESTER demod Arguments: - -h : this help + -h : this help ]] local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds @@ -48,93 +48,93 @@ local config1 = '00' local config2 = '040' local procedurecmds = { - [1] = '%s%02X%X%s', - [2] = 'lf t55xx detect', - [3] = 'lf t55xx info', + [1] = '%s%02X%X%s', + [2] = 'lf t55xx detect', + [3] = 'lf t55xx info', } ---- +--- -- A debug printout-function local function dbg(args) - if not DEBUG then - return - end - + if not DEBUG then + return + end + if type(args) == "table" then - local i = 1 - while args[i] do - dbg(args[i]) - i = i+1 - end - else - print("###", args) - end -end ---- + local i = 1 + while args[i] do + dbg(args[i]) + i = i+1 + end + else + print("###", args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) + print("ERROR: ",err) end ---- +--- -- Usage help local function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end -- -- Exit message local function ExitMsg(msg) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print(msg) - print() + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() end local function test(modulation) - local y - local block = "00" - for y = 0x0, 0x1d, 0x4 do - for _ = 1, #procedurecmds do - local pcmd = procedurecmds[_] - - if #pcmd == 0 then - - elseif _ == 1 then + local y + local block = "00" + for y = 0x0, 0x1d, 0x4 do + for _ = 1, #procedurecmds do + local pcmd = procedurecmds[_] - local config = pcmd:format(config1, y, modulation, config2) - dbg(('lf t55xx write b 0 d %s'):format(config)) - - config = tonumber(config,16) - local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"} - local err = core.SendCommand(writecmd:getBytes()) - if err then return oops(err) end - local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) + if #pcmd == 0 then - else - dbg(pcmd) - core.console( pcmd ) - end - end - core.clearCommandBuffer() - end - print( string.rep('--',20) ) + elseif _ == 1 then + + local config = pcmd:format(config1, y, modulation, config2) + dbg(('lf t55xx write b 0 d %s'):format(config)) + + config = tonumber(config,16) + local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"} + local err = core.SendCommand(writecmd:getBytes()) + if err then return oops(err) end + local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) + + else + dbg(pcmd) + core.console( pcmd ) + end + end + core.clearCommandBuffer() + end + print( string.rep('--',20) ) end local function main(args) - print( string.rep('--',20) ) - print( string.rep('--',20) ) + print( string.rep('--',20) ) + print( string.rep('--',20) ) - -- Arguments for the script - for o, arg in getopt.getopt(args, 'h') do - if o == "h" then return help() end - end + -- Arguments for the script + for o, arg in getopt.getopt(args, 'h') do + if o == "h" then return help() end + end - core.clearCommandBuffer() - test(4) - test(5) - test(6) - test(7) - print( string.rep('--',20) ) + core.clearCommandBuffer() + test(4) + test(5) + test(6) + test(7) + print( string.rep('--',20) ) end main(args) \ No newline at end of file diff --git a/client/scripts/test_t55x7_psk.lua b/client/scripts/test_t55x7_psk.lua index 15bdb71d3..bd3aa2f79 100644 --- a/client/scripts/test_t55x7_psk.lua +++ b/client/scripts/test_t55x7_psk.lua @@ -4,8 +4,8 @@ local bin = require('bin') local utils = require('utils') example =[[ - 1. script run test_t55x7_psk - 2. script run test_t55x7_psk -o + 1. script run test_t55x7_psk + 2. script run test_t55x7_psk -o ]] author = "Iceman" usage = "script run test_t55x7_psk" @@ -18,21 +18,21 @@ The outlined procedure is as following: "lf t55xx info" Loop OUTER: - change the configuretion block 0 with: + change the configuretion block 0 with: -xxxx8xxx = PSK RF/2 with Manchester modulation -xxxx1xxx = PSK RF/2 with PSK1 modulation (phase change when input changes) -xxxx2xxx = PSK RF/2 with PSk2 modulation (phase change on bitclk if input high) -xxxx3xxx = PSK RF/2 with PSk3 modulation (phase change on rising edge of input) - Loop INNER - for each outer configuration, also do - XXXXX0XX = PSK RF/2 - XXXXX4XX = PSK RF/4 - XXXXX8XX = PSK RF/8 + Loop INNER + for each outer configuration, also do + XXXXX0XX = PSK RF/2 + XXXXX4XX = PSK RF/4 + XXXXX8XX = PSK RF/8 In all 12 individual test for the PSK demod Arguments: - -h : this help + -h : this help ]] local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds @@ -40,111 +40,111 @@ local DEBUG = true -- the debug flag -- --BLOCK 0 = 00 08 80 40 PSK -- ----------- - -- 08------- bitrate - -- 8----- modulation PSK1 - -- 0---- PSK ClockRate - -- 40 max 2 blocks + -- 08------- bitrate + -- 8----- modulation PSK1 + -- 0---- PSK ClockRate + -- 40 max 2 blocks local procedurecmds = { - [1] = '00%02X%X%X40', - [2] = 'lf t55xx detect', - [3] = 'lf t55xx info', + [1] = '00%02X%X%X40', + [2] = 'lf t55xx detect', + [3] = 'lf t55xx info', } ---- +--- -- A debug printout-function local function dbg(args) - if not DEBUG then - return - end - + if not DEBUG then + return + end + if type(args) == "table" then - local i = 1 - while args[i] do - dbg(args[i]) - i = i+1 - end - else - print("###", args) - end -end ---- + local i = 1 + while args[i] do + dbg(args[i]) + i = i+1 + end + else + print("###", args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) + print("ERROR: ",err) end ---- +--- -- Usage help local function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end -- -- Exit message local function ExitMsg(msg) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print(msg) - print() + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() end local function test(modulation) - local bitrate - local clockrate - local block = "00" - for bitrate = 0x0, 0x1d, 0x4 do - - for clockrate = 0,8,4 do + local bitrate + local clockrate + local block = "00" + for bitrate = 0x0, 0x1d, 0x4 do - for _ = 1, #procedurecmds do - local cmd = procedurecmds[_] - - if #cmd == 0 then - - elseif _ == 1 then + for clockrate = 0,8,4 do - dbg("Writing to T55x7 TAG") + for _ = 1, #procedurecmds do + local cmd = procedurecmds[_] - local config = cmd:format(bitrate, modulation, clockrate) - dbg(('lf t55xx write b 0 d %s'):format(config)) - - config = tonumber(config,16) - local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"} - local err = core.SendCommand(writecmd:getBytes()) - if err then return oops(err) end - local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) - else - dbg(cmd) - core.console( cmd ) - end - end - core.clearCommandBuffer() - end - end - print( string.rep('--',20) ) + if #cmd == 0 then + + elseif _ == 1 then + + dbg("Writing to T55x7 TAG") + + local config = cmd:format(bitrate, modulation, clockrate) + dbg(('lf t55xx write b 0 d %s'):format(config)) + + config = tonumber(config,16) + local writecmd = Command:new{cmd = cmds.CMD_T55XX_WRITE_BLOCK,arg1 = config, arg2 = block, arg3 = "00", data = "00"} + local err = core.SendCommand(writecmd:getBytes()) + if err then return oops(err) end + local response = core.WaitForResponseTimeout(cmds.CMD_ACK,TIMEOUT) + else + dbg(cmd) + core.console( cmd ) + end + end + core.clearCommandBuffer() + end + end + print( string.rep('--',20) ) end local function main(args) - print( string.rep('--',20) ) - print( string.rep('--',20) ) + print( string.rep('--',20) ) + print( string.rep('--',20) ) - -- Arguments for the script - for o, arg in getopt.getopt(args, 'h') do - if o == "h" then return help() end - end + -- Arguments for the script + for o, arg in getopt.getopt(args, 'h') do + if o == "h" then return help() end + end - core.clearCommandBuffer() + core.clearCommandBuffer() - test(1) -- PSK1 - --test(2) -- PSK2 - --test(3) -- PSK3 - - print( string.rep('--',20) ) + test(1) -- PSK1 + --test(2) -- PSK2 + --test(3) -- PSK3 + + print( string.rep('--',20) ) end main(args) --- Where it iterates over +-- Where it iterates over -- xxxx8xxx = PSK RF/2 with Manchester modulation -- xxxx1xxx = PSK RF/2 with PSK1 modulation (phase change when input changes) -- xxxx2xxx = PSK RF/2 with PSk2 modulation (phase change on bitclk if input high) diff --git a/client/scripts/tnp3clone.lua b/client/scripts/tnp3clone.lua index b17cf2661..386a7e25c 100644 --- a/client/scripts/tnp3clone.lua +++ b/client/scripts/tnp3clone.lua @@ -11,10 +11,10 @@ local bor = bit32.bor local band = bit32.band example =[[ - script run tnp3clone - script run tnp3clone -h - script run tnp3clone -l - script run tnp3clone -t aa00 -s 0030 + script run tnp3clone + script run tnp3clone -h + script run tnp3clone -l + script run tnp3clone -t aa00 -s 0030 ]] author = "Iceman" @@ -23,152 +23,152 @@ desc =[[ This script will try making a barebone clone of a tnp3 tag on to a magic generation1 card. Arguments: - -h : this help - -l : list all known toy tokens - -t : toytype id, 4hex symbols - -s : subtype id, 4hex symbols - - For fun, try the following subtype id: - 0612 - Lightcore - 0118 - Series 1 - 0138 - Series 2 - 0234 - Special - 023c - Special - 0020 - Swapforce + -h : this help + -l : list all known toy tokens + -t : toytype id, 4hex symbols + -s : subtype id, 4hex symbols + + For fun, try the following subtype id: + 0612 - Lightcore + 0118 - Series 1 + 0138 - Series 2 + 0234 - Special + 023c - Special + 0020 - Swapforce ]] -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) + print("ERROR: ",err) end -- Usage help local function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end local function waitCmd() - local response = core.WaitForResponseTimeout(cmds.CMD_ACK,2000) - if response then - local count,cmd,arg0 = bin.unpack('LL',response) - if(arg0==1) then - local count,arg1,arg2,data = bin.unpack('LLH511',response,count) - return data:sub(1,32) - else - return nil, "Couldn't read block." - end - end - return nil, "No response from device" + local response = core.WaitForResponseTimeout(cmds.CMD_ACK,2000) + if response then + local count,cmd,arg0 = bin.unpack('LL',response) + if(arg0==1) then + local count,arg1,arg2,data = bin.unpack('LLH511',response,count) + return data:sub(1,32) + else + return nil, "Couldn't read block." + end + end + return nil, "No response from device" end local function readblock( blocknum, keyA ) - -- Read block N - cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blocknum, arg2 = 0, arg3 = 0, data = keyA} - err = core.SendCommand(cmd:getBytes()) - if err then return nil, err end - local block0, err = waitCmd() - if err then return nil, err end - return block0 + -- Read block N + cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blocknum, arg2 = 0, arg3 = 0, data = keyA} + err = core.SendCommand(cmd:getBytes()) + if err then return nil, err end + local block0, err = waitCmd() + if err then return nil, err end + return block0 end local function readmagicblock( blocknum ) - -- Read block N - local CSETBLOCK_SINGLE_OPERATION = 0x1F - cmd = Command:new{cmd = cmds.CMD_MIFARE_CGETBLOCK, arg1 = CSETBLOCK_SINGLE_OPERATION, arg2 = 0, arg3 = blocknum} - err = core.SendCommand(cmd:getBytes()) - if err then return nil, err end - local block0, err = waitCmd() - if err then return nil, err end - return block0 + -- Read block N + local CSETBLOCK_SINGLE_OPERATION = 0x1F + cmd = Command:new{cmd = cmds.CMD_MIFARE_CGETBLOCK, arg1 = CSETBLOCK_SINGLE_OPERATION, arg2 = 0, arg3 = blocknum} + err = core.SendCommand(cmd:getBytes()) + if err then return nil, err end + local block0, err = waitCmd() + if err then return nil, err end + return block0 end local function main(args) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - - local numBlocks = 64 - local cset = 'hf mf csetbl ' - local csetuid = 'hf mf csetuid ' - local cget = 'hf mf cgetbl ' - local empty = '00000000000000000000000000000000' - local AccAndKeyB = '7F0F0869000000000000' - local atqa = '0F01' - local sak = '81' - -- Defaults to Gusto - local toytype = 'C201' - local subtype = '0030' - local DEBUG = true - - -- Arguments for the script - for o, a in getopt.getopt(args, 'ht:s:l') do - if o == "h" then return help() end - if o == "t" then toytype = a end - if o == "s" then subtype = a end - if o == "l" then return toys.List() end - end + print( string.rep('--',20) ) + print( string.rep('--',20) ) - if #toytype ~= 4 then return oops('[!] Wrong size - toytype. (4hex symbols)') end - if #subtype ~= 4 then return oops('[!] Wrong size - subtype. (4hex symbols)') end + local numBlocks = 64 + local cset = 'hf mf csetbl ' + local csetuid = 'hf mf csetuid ' + local cget = 'hf mf cgetbl ' + local empty = '00000000000000000000000000000000' + local AccAndKeyB = '7F0F0869000000000000' + local atqa = '0F01' + local sak = '81' + -- Defaults to Gusto + local toytype = 'C201' + local subtype = '0030' + local DEBUG = true - -- look up type, find & validate types - local item = toys.Find( toytype, subtype) - if item then - print( ('[+] Looking up input: Found %s - %s (%s)'):format(item[6],item[5], item[4]) ) - else - print('[-] Didn\'t find item type. If you are sure about it, post on forum') - end - --15,16 - --13-14 - - -- find tag - result, err = lib14a.read(false, true) - if not result then return oops(err) end + -- Arguments for the script + for o, a in getopt.getopt(args, 'ht:s:l') do + if o == "h" then return help() end + if o == "t" then toytype = a end + if o == "s" then subtype = a end + if o == "l" then return toys.List() end + end - -- load keys - local akeys = pre.GetAll(result.uid) - local keyA = akeys:sub(1, 12 ) + if #toytype ~= 4 then return oops('[!] Wrong size - toytype. (4hex symbols)') end + if #subtype ~= 4 then return oops('[!] Wrong size - subtype. (4hex symbols)') end - local b0 = readblock(0, keyA) - if not b0 then - print('[-] failed reading block with factorydefault key. Trying chinese magic read.') - b0, err = readmagicblock(0) - if not b0 then - oops('[!] '..err) - return oops('[!] failed reading block with chinese magic command. Quitting...') - end - end - core.clearCommandBuffer() + -- look up type, find & validate types + local item = toys.Find( toytype, subtype) + if item then + print( ('[+] Looking up input: Found %s - %s (%s)'):format(item[6],item[5], item[4]) ) + else + print('[-] Didn\'t find item type. If you are sure about it, post on forum') + end + --15,16 + --13-14 - -- wipe card. - local cmd = (csetuid..'%s %s %s w'):format(result.uid, atqa, sak) - core.console(cmd) - core.clearCommandBuffer() - - local b1 = toytype..string.rep('00',10)..subtype - - local calc = utils.Crc16(b0..b1) - local calcEndian = bor(rsh(calc,8), lsh(band(calc, 0xff), 8)) - - local cmd = (cset..'1 %s%04x'):format( b1, calcEndian) - core.console(cmd) - core.clearCommandBuffer() - - local pos, key - for blockNo = 2, numBlocks-1, 1 do - pos = (math.floor( blockNo / 4 ) * 12)+1 - key = akeys:sub(pos, pos + 11 ) - if blockNo%4 == 3 then - cmd = ('%s %d %s%s'):format(cset,blockNo,key,AccAndKeyB) - core.console(cmd) - end - end - core.clearCommandBuffer() - - -- Set sector trailer S0, since it has different access rights - cmd = ('%s 3 %s0f0f0f69000000000000'):format(cset, keyA) - core.console(cmd) - core.clearCommandBuffer() + -- find tag + result, err = lib14a.read(false, true) + if not result then return oops(err) end + + -- load keys + local akeys = pre.GetAll(result.uid) + local keyA = akeys:sub(1, 12 ) + + local b0 = readblock(0, keyA) + if not b0 then + print('[-] failed reading block with factorydefault key. Trying chinese magic read.') + b0, err = readmagicblock(0) + if not b0 then + oops('[!] '..err) + return oops('[!] failed reading block with chinese magic command. Quitting...') + end + end + core.clearCommandBuffer() + + -- wipe card. + local cmd = (csetuid..'%s %s %s w'):format(result.uid, atqa, sak) + core.console(cmd) + core.clearCommandBuffer() + + local b1 = toytype..string.rep('00',10)..subtype + + local calc = utils.Crc16(b0..b1) + local calcEndian = bor(rsh(calc,8), lsh(band(calc, 0xff), 8)) + + local cmd = (cset..'1 %s%04x'):format( b1, calcEndian) + core.console(cmd) + core.clearCommandBuffer() + + local pos, key + for blockNo = 2, numBlocks-1, 1 do + pos = (math.floor( blockNo / 4 ) * 12)+1 + key = akeys:sub(pos, pos + 11 ) + if blockNo%4 == 3 then + cmd = ('%s %d %s%s'):format(cset,blockNo,key,AccAndKeyB) + core.console(cmd) + end + end + core.clearCommandBuffer() + + -- Set sector trailer S0, since it has different access rights + cmd = ('%s 3 %s0f0f0f69000000000000'):format(cset, keyA) + core.console(cmd) + core.clearCommandBuffer() end main(args) diff --git a/client/scripts/tnp3dump.lua b/client/scripts/tnp3dump.lua index 8c354ef89..2a5545497 100644 --- a/client/scripts/tnp3dump.lua +++ b/client/scripts/tnp3dump.lua @@ -8,15 +8,15 @@ local dumplib = require('html_dumplib') local toys = require('default_toys') example =[[ - script run tnp3dump - script run tnp3dump -n - script run tnp3dump -p - script run tnp3dump -k aabbccddeeff - script run tnp3dump -k aabbccddeeff -n - script run tnp3dump -o myfile - script run tnp3dump -n -o myfile - script run tnp3dump -p -o myfile - script run tnp3dump -k aabbccddeeff -n -o myfile + script run tnp3dump + script run tnp3dump -n + script run tnp3dump -p + script run tnp3dump -k aabbccddeeff + script run tnp3dump -k aabbccddeeff -n + script run tnp3dump -o myfile + script run tnp3dump -n -o myfile + script run tnp3dump -p -o myfile + script run tnp3dump -k aabbccddeeff -n -o myfile ]] author = "Iceman" usage = "script run tnp3dump -k -n -p -o " @@ -24,262 +24,262 @@ desc =[[ This script will try to dump the contents of a Mifare TNP3xxx card. It will need a valid KeyA in order to find the other keys and decode the card. Arguments: - -h : this help - -k : Sector 0 Key A. - -n : Use the nested cmd to find all keys - -p : Use the precalc to find all keys - -o : filename for the saved dumps + -h : this help + -k : Sector 0 Key A. + -n : Use the nested cmd to find all keys + -p : Use the precalc to find all keys + -o : filename for the saved dumps ]] local RANDOM = '20436F707972696768742028432920323031302041637469766973696F6E2E20416C6C205269676874732052657365727665642E20' local TIMEOUT = 2500 -- Shouldn't take longer than 2 seconds local DEBUG = false -- the debug flag local numBlocks = 64 local numSectors = 16 ---- +--- -- A debug printout-function function dbg(args) - if not DEBUG then return end - + if not DEBUG then return end + if type(args) == "table" then - local i = 1 - while result[i] do - dbg(result[i]) - i = i+1 - end - else - print("###", args) - end -end ---- + local i = 1 + while result[i] do + dbg(result[i]) + i = i+1 + end + else + print("###", args) + end +end +--- -- This is only meant to be used when errors occur function oops(err) - print("ERROR: ",err) - return nil,err + print("ERROR: ",err) + return nil,err end ---- +--- -- Usage help function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end -- -- Exit message function ExitMsg(msg) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print(msg) - print() + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() end local function readdumpkeys(infile) - t = infile:read("*all") - len = string.len(t) - local len,hex = bin.unpack(("H%d"):format(len),t) - return hex + t = infile:read("*all") + len = string.len(t) + local len,hex = bin.unpack(("H%d"):format(len),t) + return hex end local function waitCmd() - local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) - if response then - local count, cmd, arg0 = bin.unpack('LL',response) - if(arg0==1) then - local count,arg1,arg2,data = bin.unpack('LLH511',response,count) - return data:sub(1,32) - else - return nil, "Couldn't read block.. ["..arg0.."]" - end - end - return nil, 'No response from device' + local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) + if response then + local count, cmd, arg0 = bin.unpack('LL',response) + if(arg0==1) then + local count,arg1,arg2,data = bin.unpack('LLH511',response,count) + return data:sub(1,32) + else + return nil, "Couldn't read block.. ["..arg0.."]" + end + end + return nil, 'No response from device' end local function main(args) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - - local keyA - local cmd - local err - local useNested = false - local usePreCalc = false - local cmdReadBlockString = 'hf mf rdbl %d A %s' - local input = "dumpkeys.bin" - local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S"); + print( string.rep('--',20) ) + print( string.rep('--',20) ) - -- Arguments for the script - for o, a in getopt.getopt(args, 'hk:npo:') do - if o == "h" then return help() end - if o == "k" then keyA = a end - if o == "n" then useNested = true end - if o == "p" then usePreCalc = true end - if o == "o" then outputTemplate = a end - end - - -- validate input args. - keyA = keyA or '4b0b20107ccb' - if #(keyA) ~= 12 then - return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA)) - end + local keyA + local cmd + local err + local useNested = false + local usePreCalc = false + local cmdReadBlockString = 'hf mf rdbl %d A %s' + local input = "dumpkeys.bin" + local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M%S"); - -- Turn off Debug - local cmdSetDbgOff = "hf mf dbg 0" - core.console( cmdSetDbgOff) - - result, err = lib14a.read(false, true) - if not result then - return oops(err) - end + -- Arguments for the script + for o, a in getopt.getopt(args, 'hk:npo:') do + if o == "h" then return help() end + if o == "k" then keyA = a end + if o == "n" then useNested = true end + if o == "p" then usePreCalc = true end + if o == "o" then outputTemplate = a end + end - core.clearCommandBuffer() - - -- Show tag info - print((' Found tag %s'):format(result.name)) + -- validate input args. + keyA = keyA or '4b0b20107ccb' + if #(keyA) ~= 12 then + return oops( string.format('Wrong length of write key (was %d) expected 12', #keyA)) + end - dbg(('Using keyA : %s'):format(keyA)) + -- Turn off Debug + local cmdSetDbgOff = "hf mf dbg 0" + core.console( cmdSetDbgOff) - --Trying to find the other keys - if useNested then - core.console( ('hf mf nested 1 0 A %s d'):format(keyA) ) - end + result, err = lib14a.read(false, true) + if not result then + return oops(err) + end - core.clearCommandBuffer() - - local akeys = '' - if usePreCalc then - local pre = require('precalc') - akeys = pre.GetAll(result.uid) - dbg(akeys) - else - print('Loading dumpkeys.bin') - local hex, err = utils.ReadDumpFile(input) - if not hex then - return oops(err) - end - akeys = hex:sub(0,12*16) - end - - -- Read block 0 - dbg('Reading block 0') - cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0, arg2 = 0, arg3 = 0, data = keyA} - err = core.SendCommand(cmd:getBytes()) - if err then return oops(err) end - local block0, err = waitCmd() - if err then return oops(err) end - - core.clearCommandBuffer() - - -- Read block 1 - dbg('Reading block 1') - cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 1, arg2 = 0, arg3 = 0, data = keyA} - err = core.SendCommand(cmd:getBytes()) - if err then return oops(err) end - local block1, err = waitCmd() - if err then return oops(err) end + core.clearCommandBuffer() - core.clearCommandBuffer() - - local tmpHash = block0..block1..'%02x'..RANDOM + -- Show tag info + print((' Found tag %s'):format(result.name)) - local key - local pos = 0 - local blockNo - local blocks = {} - - -- main loop - io.write('Reading blocks > ') - for blockNo = 0, numBlocks-1, 1 do + dbg(('Using keyA : %s'):format(keyA)) - io.flush() - - if core.ukbhit() then - print("aborted by user") - break - end - - core.clearCommandBuffer() - - pos = (math.floor( blockNo / 4 ) * 12)+1 - key = akeys:sub(pos, pos + 11 ) - cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = key} - local err = core.SendCommand(cmd:getBytes()) - if err then return oops(err) end - local blockdata, err = waitCmd() - if err then return oops(err) end + --Trying to find the other keys + if useNested then + core.console( ('hf mf nested 1 0 A %s d'):format(keyA) ) + end + + core.clearCommandBuffer() + + local akeys = '' + if usePreCalc then + local pre = require('precalc') + akeys = pre.GetAll(result.uid) + dbg(akeys) + else + print('Loading dumpkeys.bin') + local hex, err = utils.ReadDumpFile(input) + if not hex then + return oops(err) + end + akeys = hex:sub(0,12*16) + end + + -- Read block 0 + dbg('Reading block 0') + cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 0, arg2 = 0, arg3 = 0, data = keyA} + err = core.SendCommand(cmd:getBytes()) + if err then return oops(err) end + local block0, err = waitCmd() + if err then return oops(err) end + + core.clearCommandBuffer() + + -- Read block 1 + dbg('Reading block 1') + cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = 1, arg2 = 0, arg3 = 0, data = keyA} + err = core.SendCommand(cmd:getBytes()) + if err then return oops(err) end + local block1, err = waitCmd() + if err then return oops(err) end + + core.clearCommandBuffer() + + local tmpHash = block0..block1..'%02x'..RANDOM + + local key + local pos = 0 + local blockNo + local blocks = {} + + -- main loop + io.write('Reading blocks > ') + for blockNo = 0, numBlocks-1, 1 do + + io.flush() + + if core.ukbhit() then + print("aborted by user") + break + end + + core.clearCommandBuffer() + + pos = (math.floor( blockNo / 4 ) * 12)+1 + key = akeys:sub(pos, pos + 11 ) + cmd = Command:new{cmd = cmds.CMD_MIFARE_READBL, arg1 = blockNo ,arg2 = 0,arg3 = 0, data = key} + local err = core.SendCommand(cmd:getBytes()) + if err then return oops(err) end + local blockdata, err = waitCmd() + if err then return oops(err) end - if blockNo%4 ~= 3 then - - if blockNo < 8 then - -- Block 0-7 not encrypted - blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) - else - -- blocks with zero not encrypted. - if string.find(blockdata, '^0+$') then - blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) - else - local baseStr = utils.ConvertHexToAscii(tmpHash:format(blockNo)) - local key = md5.sumhexa(baseStr) - local aestest = core.aes128_decrypt(key, blockdata) - local hex = utils.ConvertAsciiToHex(aestest) - - blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex) - io.write(blockNo..',') - end - end - else - -- Sectorblocks, not encrypted - blocks[blockNo+1] = ('%02d :: %s%s'):format(blockNo,key,blockdata:sub(13,32)) - end - end - io.write('\n') - - core.clearCommandBuffer() - - -- Print results - local bindata = {} - local emldata = '' + if blockNo%4 ~= 3 then - for _,s in pairs(blocks) do - local slice = s:sub(8,#s) - local str = utils.ConvertHexToAscii(slice) - emldata = emldata..slice..'\n' - for c in (str):gmatch('.') do - bindata[#bindata+1] = c - end - end + if blockNo < 8 then + -- Block 0-7 not encrypted + blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) + else + -- blocks with zero not encrypted. + if string.find(blockdata, '^0+$') then + blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,blockdata) + else + local baseStr = utils.ConvertHexToAscii(tmpHash:format(blockNo)) + local key = md5.sumhexa(baseStr) + local aestest = core.aes128_decrypt(key, blockdata) + local hex = utils.ConvertAsciiToHex(aestest) - print( string.rep('--',20) ) - - local uid = block0:sub(1,8) - local toytype = block1:sub(1,4) - local cardidLsw = block1:sub(9,16) - local cardidMsw = block1:sub(16,24) - local cardid = block1:sub(9,24) - local subtype = block1:sub(25,28) - - -- Write dump to files - if not DEBUG then - local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'-'..uid..'.bin') - print(("Wrote a BIN dump to: %s"):format(foo)) - local bar = dumplib.SaveAsText(emldata, outputTemplate..'-'..uid..'.eml') - print(("Wrote a EML dump to: %s"):format(bar)) - end - - print( string.rep('--',20) ) - -- Show info + blocks[blockNo+1] = ('%02d :: %s'):format(blockNo,hex) + io.write(blockNo..',') + end + end + else + -- Sectorblocks, not encrypted + blocks[blockNo+1] = ('%02d :: %s%s'):format(blockNo,key,blockdata:sub(13,32)) + end + end + io.write('\n') - local item = toys.Find(toytype, subtype) - if item then - print((' ITEM TYPE : %s - %s (%s)'):format(item[6],item[5], item[4]) ) - else - print((' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype)) - end + core.clearCommandBuffer() - print( (' UID : 0x%s'):format(uid) ) - print( (' CARDID : 0x%s'):format(cardid ) ) - print( string.rep('--',20) ) - - core.clearCommandBuffer() + -- Print results + local bindata = {} + local emldata = '' + + for _,s in pairs(blocks) do + local slice = s:sub(8,#s) + local str = utils.ConvertHexToAscii(slice) + emldata = emldata..slice..'\n' + for c in (str):gmatch('.') do + bindata[#bindata+1] = c + end + end + + print( string.rep('--',20) ) + + local uid = block0:sub(1,8) + local toytype = block1:sub(1,4) + local cardidLsw = block1:sub(9,16) + local cardidMsw = block1:sub(16,24) + local cardid = block1:sub(9,24) + local subtype = block1:sub(25,28) + + -- Write dump to files + if not DEBUG then + local foo = dumplib.SaveAsBinary(bindata, outputTemplate..'-'..uid..'.bin') + print(("Wrote a BIN dump to: %s"):format(foo)) + local bar = dumplib.SaveAsText(emldata, outputTemplate..'-'..uid..'.eml') + print(("Wrote a EML dump to: %s"):format(bar)) + end + + print( string.rep('--',20) ) + -- Show info + + local item = toys.Find(toytype, subtype) + if item then + print((' ITEM TYPE : %s - %s (%s)'):format(item[6],item[5], item[4]) ) + else + print((' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype)) + end + + print( (' UID : 0x%s'):format(uid) ) + print( (' CARDID : 0x%s'):format(cardid ) ) + print( string.rep('--',20) ) + + core.clearCommandBuffer() end main(args) \ No newline at end of file diff --git a/client/scripts/tnp3sim.lua b/client/scripts/tnp3sim.lua index ca729f38d..f64bebfce 100644 --- a/client/scripts/tnp3sim.lua +++ b/client/scripts/tnp3sim.lua @@ -6,11 +6,11 @@ local utils = require('utils') local md5 = require('md5') local toys = require('default_toys') local pre = require('precalc') - + example =[[ - 1. script run tnp3sim - 2. script run tnp3sim -m - 3. script run tnp3sim -m -i myfile + 1. script run tnp3sim + 2. script run tnp3sim -m + 3. script run tnp3sim -m -i myfile ]] author = "Iceman" usage = "script run tnp3sim -h -m -i " @@ -21,11 +21,11 @@ For an experimental mode, it tries to manipulate some data. At last it sends all data to the PM3 device memory where it can be used in the command "hf mf sim" Arguments: - -h : this help - -m : Maxed out items (experimental) - -i : filename for the datadump to read (bin) + -h : this help + -m : Maxed out items (experimental) + -i : filename for the datadump to read (bin) - ]] + ]] local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds local DEBUG = true -- the debug flag @@ -40,239 +40,239 @@ local char = string.char local sub = string.sub local format = string.format ---- +--- -- A debug printout-function function dbg(args) - if not DEBUG then return end - + if not DEBUG then return end + if type(args) == "table" then - local i = 1 - while result[i] do - dbg(result[i]) - i = i+1 - end - else - print("###", args) - end -end ---- + local i = 1 + while result[i] do + dbg(result[i]) + i = i+1 + end + else + print("###", args) + end +end +--- -- This is only meant to be used when errors occur function oops(err) - print("ERROR: ",err) - return nil,err + print("ERROR: ",err) + return nil,err end ---- +--- -- Usage help function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end -- -- Exit message function ExitMsg(msg) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print(msg) - print() + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() end local function writedumpfile(infile) - t = infile:read("*all") - len = string.len(t) - local len,hex = bin.unpack(("H%d"):format(len),t) - return hex + t = infile:read("*all") + len = string.len(t) + local len,hex = bin.unpack(("H%d"):format(len),t) + return hex end -- blocks with data -- there are two dataareas, in block 8 or block 36, ( 1==8 , -- checksum type = 0, 1, 2, 3 local function GetCheckSum(blocks, dataarea, chksumtype) - local crc - local area = 36 - if dataarea == 1 then - area = 8 - end - - if chksumtype == 0 then - crc = blocks[1]:sub(29,32) - elseif chksumtype == 1 then - crc = blocks[area]:sub(29,32) - elseif chksumtype == 2 then - crc = blocks[area]:sub(25,28) - elseif chksumtype == 3 then - crc = blocks[area]:sub(21,24) - end - return utils.SwapEndianness(crc,16) + local crc + local area = 36 + if dataarea == 1 then + area = 8 + end + + if chksumtype == 0 then + crc = blocks[1]:sub(29,32) + elseif chksumtype == 1 then + crc = blocks[area]:sub(29,32) + elseif chksumtype == 2 then + crc = blocks[area]:sub(25,28) + elseif chksumtype == 3 then + crc = blocks[area]:sub(21,24) + end + return utils.SwapEndianness(crc,16) end local function SetAllCheckSum(blocks) - print('Updating all checksums') - SetCheckSum(blocks, 3) - SetCheckSum(blocks, 2) - SetCheckSum(blocks, 1) - SetCheckSum(blocks, 0) + print('Updating all checksums') + SetCheckSum(blocks, 3) + SetCheckSum(blocks, 2) + SetCheckSum(blocks, 1) + SetCheckSum(blocks, 0) end local function SetCheckSum(blocks, chksumtype) - if blocks == nil then return nil, 'Argument \"blocks\" nil' end - local newcrc - local area1 = 8 - local area2 = 36 - - if chksumtype == 0 then - newcrc = ('%04X'):format(CalcCheckSum(blocks,1,0)) - blocks[1] = blocks[1]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2) - elseif chksumtype == 1 then - newcrc = ('%04X'):format(CalcCheckSum(blocks,1,1)) - blocks[area1] = blocks[area1]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2) - newcrc = ('%04X'):format(CalcCheckSum(blocks,2,1)) - blocks[area2] = blocks[area2]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2) - elseif chksumtype == 2 then - newcrc = ('%04X'):format(CalcCheckSum(blocks,1,2)) - blocks[area1] = blocks[area1]:sub(1,24)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area1]:sub(29,32) - newcrc = ('%04X'):format(CalcCheckSum(blocks,2,2)) - blocks[area2] = blocks[area2]:sub(1,24)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area2]:sub(29,32) - elseif chksumtype == 3 then - newcrc = ('%04X'):format(CalcCheckSum(blocks,1,3)) - blocks[area1] = blocks[area1]:sub(1,20)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area1]:sub(25,32) - newcrc = ('%04X'):format(CalcCheckSum(blocks,2,3)) - blocks[area2] = blocks[area2]:sub(1,20)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area2]:sub(25,32) - end + if blocks == nil then return nil, 'Argument \"blocks\" nil' end + local newcrc + local area1 = 8 + local area2 = 36 + + if chksumtype == 0 then + newcrc = ('%04X'):format(CalcCheckSum(blocks,1,0)) + blocks[1] = blocks[1]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2) + elseif chksumtype == 1 then + newcrc = ('%04X'):format(CalcCheckSum(blocks,1,1)) + blocks[area1] = blocks[area1]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2) + newcrc = ('%04X'):format(CalcCheckSum(blocks,2,1)) + blocks[area2] = blocks[area2]:sub(1,28)..newcrc:sub(3,4)..newcrc:sub(1,2) + elseif chksumtype == 2 then + newcrc = ('%04X'):format(CalcCheckSum(blocks,1,2)) + blocks[area1] = blocks[area1]:sub(1,24)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area1]:sub(29,32) + newcrc = ('%04X'):format(CalcCheckSum(blocks,2,2)) + blocks[area2] = blocks[area2]:sub(1,24)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area2]:sub(29,32) + elseif chksumtype == 3 then + newcrc = ('%04X'):format(CalcCheckSum(blocks,1,3)) + blocks[area1] = blocks[area1]:sub(1,20)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area1]:sub(25,32) + newcrc = ('%04X'):format(CalcCheckSum(blocks,2,3)) + blocks[area2] = blocks[area2]:sub(1,20)..newcrc:sub(3,4)..newcrc:sub(1,2)..blocks[area2]:sub(25,32) + end end function CalcCheckSum(blocks, dataarea, chksumtype) - local area = 36 - if dataarea == 1 then - area = 8 - end - - if chksumtype == 0 then - data = blocks[0]..blocks[1]:sub(1,28) - elseif chksumtype == 1 then - data = blocks[area]:sub(1,28)..'0500' - elseif chksumtype == 2 then - data = blocks[area+1]..blocks[area+2]..blocks[area+4] - elseif chksumtype == 3 then - data = blocks[area+5]..blocks[area+6]..blocks[area+8]..string.rep('00',0xe0) - end - return utils.Crc16(data) + local area = 36 + if dataarea == 1 then + area = 8 + end + + if chksumtype == 0 then + data = blocks[0]..blocks[1]:sub(1,28) + elseif chksumtype == 1 then + data = blocks[area]:sub(1,28)..'0500' + elseif chksumtype == 2 then + data = blocks[area+1]..blocks[area+2]..blocks[area+4] + elseif chksumtype == 3 then + data = blocks[area+5]..blocks[area+6]..blocks[area+8]..string.rep('00',0xe0) + end + return utils.Crc16(data) end local function ValidateCheckSums(blocks) - print(' Validating checksums') - - local isOk, crc, calc - -- Checksum Type 0 - crc = GetCheckSum(blocks,1,0) - calc = CalcCheckSum(blocks, 1, 0) - if crc == calc then isOk='Ok' else isOk = 'Error' end - io.write( ('TYPE 0 : %04x = %04x -- %s\n'):format(crc,calc,isOk)) + print(' Validating checksums') - -- Checksum Type 1 (DATAAREAHEADER 1) - crc = GetCheckSum(blocks,1,1) - calc = CalcCheckSum(blocks,1,1) - if crc == calc then isOk='Ok' else isOk = 'Error' end - io.write( ('TYPE 1 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk)) - - -- Checksum Type 1 (DATAAREAHEADER 2) - crc = GetCheckSum(blocks,2,1) - calc = CalcCheckSum(blocks,2,1) - if crc == calc then isOk='Ok' else isOk = 'Error' end - io.write( ('TYPE 1 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk)) - - -- Checksum Type 2 (DATAAREA 1) - crc = GetCheckSum(blocks,1,2) - calc = CalcCheckSum(blocks,1,2) - if crc == calc then isOk='Ok' else isOk = 'Error' end - io.write( ('TYPE 2 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk)) + local isOk, crc, calc + -- Checksum Type 0 + crc = GetCheckSum(blocks,1,0) + calc = CalcCheckSum(blocks, 1, 0) + if crc == calc then isOk='Ok' else isOk = 'Error' end + io.write( ('TYPE 0 : %04x = %04x -- %s\n'):format(crc,calc,isOk)) - -- Checksum Type 2 (DATAAREA 2) - crc = GetCheckSum(blocks,2,2) - calc = CalcCheckSum(blocks,2,2) - if crc == calc then isOk='Ok' else isOk = 'Error' end - io.write( ('TYPE 2 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk)) + -- Checksum Type 1 (DATAAREAHEADER 1) + crc = GetCheckSum(blocks,1,1) + calc = CalcCheckSum(blocks,1,1) + if crc == calc then isOk='Ok' else isOk = 'Error' end + io.write( ('TYPE 1 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk)) - -- Checksum Type 3 (DATAAREA 1) - crc = GetCheckSum(blocks,1,3) - calc = CalcCheckSum(blocks,1,3) - if crc == calc then isOk='Ok' else isOk = 'Error' end - io.write( ('TYPE 3 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk)) + -- Checksum Type 1 (DATAAREAHEADER 2) + crc = GetCheckSum(blocks,2,1) + calc = CalcCheckSum(blocks,2,1) + if crc == calc then isOk='Ok' else isOk = 'Error' end + io.write( ('TYPE 1 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk)) - -- Checksum Type 3 (DATAAREA 2) - crc = GetCheckSum(blocks,2,3) - calc = CalcCheckSum(blocks,2,3) - if crc == calc then isOk='Ok' else isOk = 'Error' end - io.write( ('TYPE 3 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk)) + -- Checksum Type 2 (DATAAREA 1) + crc = GetCheckSum(blocks,1,2) + calc = CalcCheckSum(blocks,1,2) + if crc == calc then isOk='Ok' else isOk = 'Error' end + io.write( ('TYPE 2 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk)) + + -- Checksum Type 2 (DATAAREA 2) + crc = GetCheckSum(blocks,2,2) + calc = CalcCheckSum(blocks,2,2) + if crc == calc then isOk='Ok' else isOk = 'Error' end + io.write( ('TYPE 2 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk)) + + -- Checksum Type 3 (DATAAREA 1) + crc = GetCheckSum(blocks,1,3) + calc = CalcCheckSum(blocks,1,3) + if crc == calc then isOk='Ok' else isOk = 'Error' end + io.write( ('TYPE 3 area 1: %04x = %04x -- %s\n'):format(crc,calc,isOk)) + + -- Checksum Type 3 (DATAAREA 2) + crc = GetCheckSum(blocks,2,3) + calc = CalcCheckSum(blocks,2,3) + if crc == calc then isOk='Ok' else isOk = 'Error' end + io.write( ('TYPE 3 area 2: %04x = %04x -- %s\n'):format(crc,calc,isOk)) end local function AddKey(keys, blockNo, data) - local pos = (math.floor( blockNo / 4 ) * 12)+1 - local key = keys:sub(pos, pos + 11 ) - return key..data:sub(13) + local pos = (math.floor( blockNo / 4 ) * 12)+1 + local key = keys:sub(pos, pos + 11 ) + return key..data:sub(13) end local function LoadEmulator(uid, blocks) - print('Sending dumpdata to emulator memory') - local keys = pre.GetAll(uid) - local cmd, blockdata - for _,b in pairs(blocks) do - - blockdata = b - - if _%4 ~= 3 then - if (_ >= 8 and _<=21) or (_ >= 36 and _<=49) then - local base = ('%s%s%02x%s'):format(blocks[0], blocks[1], _ , RANDOM) - local baseStr = utils.ConvertHexToAscii(base) - local key = md5.sumhexa(baseStr) - local enc = core.aes128_encrypt(key, blockdata) - blockdata = utils.ConvertAsciiToHex(enc) - io.write( _..',') - end - else - -- add keys if not existing.. - if ( blockdata:sub(1,12) == '000000000000' ) then - blockdata = AddKey(keys, _, blockdata) - end - end - core.clearCommandBuffer() - cmd = Command:new{cmd = cmds.CMD_MIFARE_EML_MEMSET, arg1 = _ ,arg2 = 1,arg3 = 16, data = blockdata} - local err = core.SendCommand(cmd:getBytes()) - if err then return err end - end - io.write('\n') + print('Sending dumpdata to emulator memory') + local keys = pre.GetAll(uid) + local cmd, blockdata + for _,b in pairs(blocks) do + + blockdata = b + + if _%4 ~= 3 then + if (_ >= 8 and _<=21) or (_ >= 36 and _<=49) then + local base = ('%s%s%02x%s'):format(blocks[0], blocks[1], _ , RANDOM) + local baseStr = utils.ConvertHexToAscii(base) + local key = md5.sumhexa(baseStr) + local enc = core.aes128_encrypt(key, blockdata) + blockdata = utils.ConvertAsciiToHex(enc) + io.write( _..',') + end + else + -- add keys if not existing.. + if ( blockdata:sub(1,12) == '000000000000' ) then + blockdata = AddKey(keys, _, blockdata) + end + end + core.clearCommandBuffer() + cmd = Command:new{cmd = cmds.CMD_MIFARE_EML_MEMSET, arg1 = _ ,arg2 = 1,arg3 = 16, data = blockdata} + local err = core.SendCommand(cmd:getBytes()) + if err then return err end + end + io.write('\n') end local function Num2Card(m, l) - local k = { - 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, - 0x4C, 0x4D, 0x4E, 0x50, 0x51, 0x52, 0x53, 0x54,0x56, 0x57, 0x58, 0x59, 0x5A, 0x00 - } - local msw = tonumber(utils.SwapEndiannessStr(m,32),16) - local lsw = tonumber(utils.SwapEndiannessStr(l,32),16) + local k = { + 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39,0x42, 0x43, 0x44, 0x46, 0x47, 0x48, 0x4A, 0x4B, + 0x4C, 0x4D, 0x4E, 0x50, 0x51, 0x52, 0x53, 0x54,0x56, 0x57, 0x58, 0x59, 0x5A, 0x00 + } + local msw = tonumber(utils.SwapEndiannessStr(m,32),16) + local lsw = tonumber(utils.SwapEndiannessStr(l,32),16) - if msw > 0x17ea1 then - return "too big" - end + if msw > 0x17ea1 then + return "too big" + end - if msw == 0x17ea1 and lsw > 0x8931fee8 then - return "out of range" - end + if msw == 0x17ea1 and lsw > 0x8931fee8 then + return "out of range" + end - local s = "" - local index - for i = 1,10 do - index, msw, lsw = DivideByK( msw, lsw) - if ( index <= 1 ) then - s = char(k[index]) .. s - else - s = char(k[index-1]) .. s - end - print (index-1, msw, lsw) - end + local s = "" + local index + for i = 1,10 do + index, msw, lsw = DivideByK( msw, lsw) + if ( index <= 1 ) then + s = char(k[index]) .. s + else + s = char(k[index-1]) .. s + end + print (index-1, msw, lsw) + end return s end --33LRT-LM9Q9 @@ -289,43 +289,43 @@ end function DivideByK(msw, lsw) - local lowLSW - local highLSW - local remainder = 0 - local RADIX = 29 + local lowLSW + local highLSW + local remainder = 0 + local RADIX = 29 - --local num = 0 | band( rshift(msw,16), 0xffff) - local num = band( rshift(msw, 16), 0xffff) - - --highLSW = 0 | lshift( (num / RADIX) , 16) - highLSW = lshift( (num / RADIX) , 16) - remainder = num % RADIX + --local num = 0 | band( rshift(msw,16), 0xffff) + local num = band( rshift(msw, 16), 0xffff) - num = bor( lshift(remainder,16), band(msw, 0xffff)) + --highLSW = 0 | lshift( (num / RADIX) , 16) + highLSW = lshift( (num / RADIX) , 16) + remainder = num % RADIX - --highLSW |= num / RADIX - highLSW = highLSW or (num / RADIX) - remainder = num % RADIX + num = bor( lshift(remainder,16), band(msw, 0xffff)) - num = bor( lshift(remainder,16), ( band(rshift(lsw,16), 0xffff))) + --highLSW |= num / RADIX + highLSW = highLSW or (num / RADIX) + remainder = num % RADIX - --lowLSW = 0 | (num / RADIX) << 16 - lowLSW = 0 or (lshift( (num / RADIX), 16)) - remainder = num % RADIX + num = bor( lshift(remainder,16), ( band(rshift(lsw,16), 0xffff))) - num = bor( lshift(remainder,16) , band(lsw, 0xffff) ) + --lowLSW = 0 | (num / RADIX) << 16 + lowLSW = 0 or (lshift( (num / RADIX), 16)) + remainder = num % RADIX + + num = bor( lshift(remainder,16) , band(lsw, 0xffff) ) + + lowLSW = bor(lowLSW, (num / RADIX)) + remainder = num % RADIX + return remainder, highLSW, lowLSW + + -- uint num = 0 | (msw >> 16) & 0xffff; - lowLSW = bor(lowLSW, (num / RADIX)) - remainder = num % RADIX - return remainder, highLSW, lowLSW - - -- uint num = 0 | (msw >> 16) & 0xffff; - -- highLSW = 0 | (num / RADIX) << 16; -- remainder = num % RADIX; -- num = (remainder << 16) | (msw & 0xffff); - + -- highLSW |= num / RADIX; -- remainder = num % RADIX; @@ -343,147 +343,147 @@ end local function main(args) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - - local result, err, hex - local maxed = false - local inputTemplate = "dumpdata.bin" - local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M"); - - -- Arguments for the script - for o, a in getopt.getopt(args, 'hmi:o:') do - if o == "h" then return help() end - if o == "m" then maxed = true end - if o == "o" then outputTemplate = a end - if o == "i" then inputTemplate = a end - end - - -- Turn off Debug - local cmdSetDbgOff = "hf mf dbg 0" - core.console( cmdSetDbgOff) - - -- Load dump.bin file - print( (' Load data from %s'):format(inputTemplate)) - hex, err = utils.ReadDumpFile(inputTemplate) - if not hex then return oops(err) end - - local blocks = {} - local blockindex = 0 - for i = 1, #hex, 32 do - blocks[blockindex] = hex:sub(i,i+31) - blockindex = blockindex + 1 - end + print( string.rep('--',20) ) + print( string.rep('--',20) ) - if DEBUG then ValidateCheckSums(blocks) end - - -- - print( string.rep('--',20) ) - print(' Gathering info') - local uid = blocks[0]:sub(1,8) - local toytype = blocks[1]:sub(1,4) - local cardidLsw = blocks[1]:sub(9,16) - local cardidMsw = blocks[1]:sub(17,24) - local subtype = blocks[1]:sub(25,28) + local result, err, hex + local maxed = false + local inputTemplate = "dumpdata.bin" + local outputTemplate = os.date("toydump_%Y-%m-%d_%H%M"); - -- Show info - print( string.rep('--',20) ) - - local item = toys.Find( toytype, subtype) - if item then - local itemStr = ('%s - %s (%s)'):format(item[6],item[5], item[4]) - print(' ITEM TYPE : '..itemStr ) - else - print( (' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype) ) - end - - print( (' UID : 0x%s'):format(uid) ) - print( (' CARDID : 0x%s %s [%s]'):format( - cardidMsw,cardidLsw, - --Num2Card(cardidMsw, cardidLsw)) - '') - ) - print( string.rep('--',20) ) + -- Arguments for the script + for o, a in getopt.getopt(args, 'hmi:o:') do + if o == "h" then return help() end + if o == "m" then maxed = true end + if o == "o" then outputTemplate = a end + if o == "i" then inputTemplate = a end + end + + -- Turn off Debug + local cmdSetDbgOff = "hf mf dbg 0" + core.console( cmdSetDbgOff) + + -- Load dump.bin file + print( (' Load data from %s'):format(inputTemplate)) + hex, err = utils.ReadDumpFile(inputTemplate) + if not hex then return oops(err) end + + local blocks = {} + local blockindex = 0 + for i = 1, #hex, 32 do + blocks[blockindex] = hex:sub(i,i+31) + blockindex = blockindex + 1 + end + + if DEBUG then ValidateCheckSums(blocks) end + + -- + print( string.rep('--',20) ) + print(' Gathering info') + local uid = blocks[0]:sub(1,8) + local toytype = blocks[1]:sub(1,4) + local cardidLsw = blocks[1]:sub(9,16) + local cardidMsw = blocks[1]:sub(17,24) + local subtype = blocks[1]:sub(25,28) + + -- Show info + print( string.rep('--',20) ) + + local item = toys.Find( toytype, subtype) + if item then + local itemStr = ('%s - %s (%s)'):format(item[6],item[5], item[4]) + print(' ITEM TYPE : '..itemStr ) + else + print( (' ITEM TYPE : 0x%s 0x%s'):format(toytype, subtype) ) + end + + print( (' UID : 0x%s'):format(uid) ) + print( (' CARDID : 0x%s %s [%s]'):format( + cardidMsw,cardidLsw, + --Num2Card(cardidMsw, cardidLsw)) + '') + ) + print( string.rep('--',20) ) - -- Experience should be: - local experience = blocks[8]:sub(1,6) - print(('Experience : %d'):format(utils.SwapEndianness(experience,16))) - - local money = blocks[8]:sub(7,10) - print(('Money : %d'):format(utils.SwapEndianness(money,16))) + -- Experience should be: + local experience = blocks[8]:sub(1,6) + print(('Experience : %d'):format(utils.SwapEndianness(experience,16))) - -- - - -- Sequence number - local seqnum = blocks[8]:sub(18,19) - print(('Sequence number : %d'):format( tonumber(seqnum,16))) - - local fairy = blocks[9]:sub(1,8) - --FD0F = Left, FF0F = Right - local path = 'not choosen' - if fairy:sub(2,2) == 'D' then - path = 'Left' - elseif fairy:sub(2,2) == 'F' then - path = 'Right' - end - print(('Fairy : %d [Path: %s] '):format(utils.SwapEndianness(fairy,24),path)) - - local hat = blocks[9]:sub(8,11) - print(('Hat : %d'):format(utils.SwapEndianness(hat,16))) + local money = blocks[8]:sub(7,10) + print(('Money : %d'):format(utils.SwapEndianness(money,16))) - local level = blocks[13]:sub(27,28) - print(('LEVEL : %d'):format( tonumber(level,16))) + -- - --local health = blocks[]:sub(); - --print(('Health : %d'):format( tonumber(health,16)) - - --0x0D 0x29 0x0A 0x02 16-bit hero points value. Maximum 100. - local heropoints = blocks[13]:sub(20,23) - print(('Hero points : %d'):format(utils.SwapEndianness(heropoints,16))) + -- Sequence number + local seqnum = blocks[8]:sub(18,19) + print(('Sequence number : %d'):format( tonumber(seqnum,16))) - --0x10 0x2C 0x0C 0x04 32 bit flag value indicating heroic challenges completed. - local challenges = blocks[16]:sub(25,32) - print(('Finished hero challenges : %d'):format(utils.SwapEndianness(challenges,32))) - - -- Character Name - local name1 = blocks[10]:sub(1,32) - local name2 = blocks[12]:sub(1,32) - print('Custom name : '..utils.ConvertHexToAscii(name1..name2)) - - if maxed then - print('Lets try to max out some values') - -- max out money, experience - --print (blocks[8]) - blocks[8] = 'FFFFFF'..'FFFF'..blocks[8]:sub(11,32) - blocks[36] = 'FFFFFF'..'FFFF'..blocks[36]:sub(11,32) - --print (blocks[8]) - - -- max out hero challenges - --print (blocks[16]) - blocks[16] = blocks[16]:sub(1,24)..'FFFFFFFF' - blocks[44] = blocks[44]:sub(1,24)..'FFFFFFFF' - --print (blocks[16]) - - -- max out heropoints - --print (blocks[13]) - blocks[13] = blocks[13]:sub(1,19)..'0064'..blocks[13]:sub(24,32) - blocks[41] = blocks[41]:sub(1,19)..'0064'..blocks[41]:sub(24,32) - --print (blocks[13]) - - -- Update Checksums - SetAllCheckSum(blocks) + local fairy = blocks[9]:sub(1,8) + --FD0F = Left, FF0F = Right + local path = 'not choosen' + if fairy:sub(2,2) == 'D' then + path = 'Left' + elseif fairy:sub(2,2) == 'F' then + path = 'Right' + end + print(('Fairy : %d [Path: %s] '):format(utils.SwapEndianness(fairy,24),path)) - -- Validate Checksums - ValidateCheckSums(blocks) - end + local hat = blocks[9]:sub(8,11) + print(('Hat : %d'):format(utils.SwapEndianness(hat,16))) - --Load dumpdata to emulator memory - if DEBUG then - err = LoadEmulator(uid, blocks) - if err then return oops(err) end - core.clearCommandBuffer() - print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..'\" <--') - end + local level = blocks[13]:sub(27,28) + print(('LEVEL : %d'):format( tonumber(level,16))) + + --local health = blocks[]:sub(); + --print(('Health : %d'):format( tonumber(health,16)) + + --0x0D 0x29 0x0A 0x02 16-bit hero points value. Maximum 100. + local heropoints = blocks[13]:sub(20,23) + print(('Hero points : %d'):format(utils.SwapEndianness(heropoints,16))) + + --0x10 0x2C 0x0C 0x04 32 bit flag value indicating heroic challenges completed. + local challenges = blocks[16]:sub(25,32) + print(('Finished hero challenges : %d'):format(utils.SwapEndianness(challenges,32))) + + -- Character Name + local name1 = blocks[10]:sub(1,32) + local name2 = blocks[12]:sub(1,32) + print('Custom name : '..utils.ConvertHexToAscii(name1..name2)) + + if maxed then + print('Lets try to max out some values') + -- max out money, experience + --print (blocks[8]) + blocks[8] = 'FFFFFF'..'FFFF'..blocks[8]:sub(11,32) + blocks[36] = 'FFFFFF'..'FFFF'..blocks[36]:sub(11,32) + --print (blocks[8]) + + -- max out hero challenges + --print (blocks[16]) + blocks[16] = blocks[16]:sub(1,24)..'FFFFFFFF' + blocks[44] = blocks[44]:sub(1,24)..'FFFFFFFF' + --print (blocks[16]) + + -- max out heropoints + --print (blocks[13]) + blocks[13] = blocks[13]:sub(1,19)..'0064'..blocks[13]:sub(24,32) + blocks[41] = blocks[41]:sub(1,19)..'0064'..blocks[41]:sub(24,32) + --print (blocks[13]) + + -- Update Checksums + SetAllCheckSum(blocks) + + -- Validate Checksums + ValidateCheckSums(blocks) + end + + --Load dumpdata to emulator memory + if DEBUG then + err = LoadEmulator(uid, blocks) + if err then return oops(err) end + core.clearCommandBuffer() + print('The simulation is now prepared.\n --> run \"hf mf sim u '..uid..'\" <--') + end end main(args) \ No newline at end of file diff --git a/client/scripts/tracetest.lua b/client/scripts/tracetest.lua index ae4055aed..96d1f79c6 100644 --- a/client/scripts/tracetest.lua +++ b/client/scripts/tracetest.lua @@ -5,122 +5,122 @@ local utils = require('utils') local dumplib = require('html_dumplib') example =[[ - 1. script run tracetest + 1. script run tracetest ]] author = "Iceman" usage = "script run tracetest" desc =[[ -This script will load several traces files in ../traces/ folder and do +This script will load several traces files in ../traces/ folder and do "data load" -"lf search 1 u" +"lf search 1 u" -The following tracefiles will be loaded: +The following tracefiles will be loaded: em*.pm3 m*.pm3 Arguments: - -h : this help + -h : this help ]] local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds local DEBUG = true -- the debug flag ---- +--- -- A debug printout-function function dbg(args) - if not DEBUG then - return - end - + if not DEBUG then + return + end + if type(args) == "table" then - local i = 1 - while result[i] do - dbg(result[i]) - i = i+1 - end - else - print("###", args) - end -end ---- + local i = 1 + while result[i] do + dbg(result[i]) + i = i+1 + end + else + print("###", args) + end +end +--- -- This is only meant to be used when errors occur function oops(err) - print("ERROR: ",err) + print("ERROR: ",err) end ---- +--- -- Usage help function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end -- -- Exit message function ExitMsg(msg) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print(msg) - print() + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print(msg) + print() end local function main(args) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - - local cmdDataLoad = 'data load %s'; - local tracesEM = "find '../traces/' -iname 'em*.pm3' -type f" - local tracesMOD = "find '../traces/' -iname 'm*.pm3' -type f" + print( string.rep('--',20) ) + print( string.rep('--',20) ) - local write2File = false - local outputTemplate = os.date("testtest_%Y-%m-%d_%H%M%S") + local cmdDataLoad = 'data load %s'; + local tracesEM = "find '../traces/' -iname 'em*.pm3' -type f" + local tracesMOD = "find '../traces/' -iname 'm*.pm3' -type f" - -- Arguments for the script - for o, arg in getopt.getopt(args, 'h') do - if o == "h" then return help() end - end - - core.clearCommandBuffer() - - local files = {} - - -- Find a set of traces staring with EM - local p = assert( io.popen(tracesEM)) - for file in p:lines() do - table.insert(files, file) - end - p.close(); - - -- Find a set of traces staring with MOD - p = assert( io.popen(tracesMOD) ) - for file in p:lines() do - table.insert(files, file) - end - p.close(); - - local cmdLFSEARCH = "lf search 1 u" - - -- main loop - io.write('Starting to test traces > ') - for _,file in pairs(files) do + local write2File = false + local outputTemplate = os.date("testtest_%Y-%m-%d_%H%M%S") - local x = "data load "..file - dbg(x) - core.console(x) - - dbg(cmdLFSEARCH) - core.console(cmdLFSEARCH) - - core.clearCommandBuffer() - - if core.ukbhit() then - print("aborted by user") - break - end - end - io.write('\n') + -- Arguments for the script + for o, arg in getopt.getopt(args, 'h') do + if o == "h" then return help() end + end - print( string.rep('--',20) ) + core.clearCommandBuffer() + + local files = {} + + -- Find a set of traces staring with EM + local p = assert( io.popen(tracesEM)) + for file in p:lines() do + table.insert(files, file) + end + p.close(); + + -- Find a set of traces staring with MOD + p = assert( io.popen(tracesMOD) ) + for file in p:lines() do + table.insert(files, file) + end + p.close(); + + local cmdLFSEARCH = "lf search 1 u" + + -- main loop + io.write('Starting to test traces > ') + for _,file in pairs(files) do + + local x = "data load "..file + dbg(x) + core.console(x) + + dbg(cmdLFSEARCH) + core.console(cmdLFSEARCH) + + core.clearCommandBuffer() + + if core.ukbhit() then + print("aborted by user") + break + end + end + io.write('\n') + + print( string.rep('--',20) ) end main(args) \ No newline at end of file diff --git a/client/scripts/ufodump.lua b/client/scripts/ufodump.lua index a77bb6c92..67949fd94 100644 --- a/client/scripts/ufodump.lua +++ b/client/scripts/ufodump.lua @@ -3,8 +3,8 @@ local getopt = require('getopt') local lib14a = require('read14a') local utils = require('utils') example = [[ - script run ufodump - script run ufodump -b 10 + script run ufodump + script run ufodump -b 10 ]] author = "Iceman" desc = @@ -22,155 +22,155 @@ Arguments: -- Some globals local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds local DEBUG = false -- the debug flag ---- +--- -- A debug printout-function local function dbg(args) - if DEBUG then - print("###", args) - end -end ---- + if DEBUG then + print("###", args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) - core.clearCommandBuffer() + print("ERROR: ",err) + core.clearCommandBuffer() end ---- +--- -- Usage help local function help() - print(desc) - print("Example usage") - print(example) + print(desc) + print("Example usage") + print(example) end -- -- writes data to ascii textfile. function writeDumpFile(uid, blockData) - local destination = string.format("%s.eml", uid) - local file = io.open(destination, "w") - if file == nil then - return nil, string.format("Could not write to file %s", destination) - end - local rowlen = string.len(blockData[1]) + local destination = string.format("%s.eml", uid) + local file = io.open(destination, "w") + if file == nil then + return nil, string.format("Could not write to file %s", destination) + end + local rowlen = string.len(blockData[1]) - for i,block in ipairs(blockData) do - if rowlen ~= string.len(block) then - print(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i)) - end - file:write(block.."\n") - end - file:close() - return destination + for i,block in ipairs(blockData) do + if rowlen ~= string.len(block) then + print(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i)) + end + file:write(block.."\n") + end + file:close() + return destination end -- --- Picks out and displays the data read from a tag -- Specifically, takes a usb packet, converts to a Command --- (as in commands.lua), takes the data-array and +-- (as in commands.lua), takes the data-array and -- reads the number of bytes specified in arg1 (arg0 in c-struct) -- and displays the data -- @blockno just to print which block the data belong to -- @param usbpacket the data received from the device function showdata(blockno, data) - local xorkey = '55AA55AA55AA55AA6262' - local s = data.." | " - local dex = '' - local rs - for i = 1, 20-4, 4 do - local item = string.sub(data, i, i+3) - local xor = string.sub(xorkey, i, i+3) + local xorkey = '55AA55AA55AA55AA6262' + local s = data.." | " + local dex = '' + local rs + for i = 1, 20-4, 4 do + local item = string.sub(data, i, i+3) + local xor = string.sub(xorkey, i, i+3) - if blockno > 2 then - rs = bit32.bxor(tonumber(item,16) , tonumber(xor,16)) - else - rs = tonumber(item, 16) - end - dex = (dex..'%04X'):format(rs) - end - s = s..dex.." | " - print( (" %02d | %s"):format(blockno,s)) + if blockno > 2 then + rs = bit32.bxor(tonumber(item,16) , tonumber(xor,16)) + else + rs = tonumber(item, 16) + end + dex = (dex..'%04X'):format(rs) + end + s = s..dex.." | " + print( (" %02d | %s"):format(blockno,s)) end -- -- Send a "raw" iso14443a package, ie "hf 14a raw" command function sendRaw(rawdata, options) - --print(">> ", rawdata) - local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC + lib14a.ISO14A_COMMAND.ISO14A_NO_RATS - local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, - arg1 = flags, -- Send raw - -- arg2 contains the length, which is half the length - -- of the ASCII-string rawdata - arg2 = string.len(rawdata)/2, - data = rawdata} - return lib14a.sendToDevice(command, options.ignore_response) + --print(">> ", rawdata) + local flags = lib14a.ISO14A_COMMAND.ISO14A_NO_DISCONNECT + lib14a.ISO14A_COMMAND.ISO14A_RAW + lib14a.ISO14A_COMMAND.ISO14A_APPEND_CRC + lib14a.ISO14A_COMMAND.ISO14A_NO_RATS + local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, + arg1 = flags, -- Send raw + -- arg2 contains the length, which is half the length + -- of the ASCII-string rawdata + arg2 = string.len(rawdata)/2, + data = rawdata} + return lib14a.sendToDevice(command, options.ignore_response) end -- -- Sends an instruction to do nothing, only disconnect function disconnect() - local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0, } - -- We can ignore the response here, no ACK is returned for this command - -- Check /armsrc/iso14443a.c, ReaderIso14443a() for details - return lib14a.sendToDevice(command, true) - --core.console("hf 14a raw -r") -end ---- + local command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = 0,} + -- We can ignore the response here, no ACK is returned for this command + -- Check /armsrc/iso14443a.c, ReaderIso14443a() for details + return lib14a.sendToDevice(command, true) + --core.console("hf 14a raw -r") +end +--- -- The main entry point function main(args) - local ignore_response = false - local endblock = 20 - - -- Read the parameters - for o, a in getopt.getopt(args, 'hb:') do - if o == "h" then return help() end - if o == "b" then endblock = a end - end - endblock = endblock or 20 - - -- First of all, connect - info, err = lib14a.read(true, true) - if err then disconnect() return oops(err) end - core.clearCommandBuffer() - - local blockData = {} - - -- Show tag info - print(("\nFound Card UID [%s]\n"):format(info.uid)) + local ignore_response = false + local endblock = 20 - print("blk | data | xored") - print("----+------------------+-------------------") - for block = 00, endblock do - local cmd = string.format("10%02x00", block) - res, err = sendRaw(cmd , {ignore_response = ignore_response}) - if err then disconnect() return oops(err) end - - local cmd_response = Command.parse(res) - local len = tonumber(cmd_response.arg1) * 2 - local data = string.sub(tostring(cmd_response.data), 0, len-4) + -- Read the parameters + for o, a in getopt.getopt(args, 'hb:') do + if o == "h" then return help() end + if o == "b" then endblock = a end + end + endblock = endblock or 20 - showdata(block, data) - table.insert(blockData, data) - end - print("----+------------------+-------------------") - disconnect() - - local filename, err = writeDumpFile(info.uid, blockData) - if err then return oops(err) end + -- First of all, connect + info, err = lib14a.read(true, true) + if err then disconnect() return oops(err) end + core.clearCommandBuffer() - print(string.format("\nDumped data into %s", filename)) + local blockData = {} + + -- Show tag info + print(("\nFound Card UID [%s]\n"):format(info.uid)) + + print("blk | data | xored") + print("----+------------------+-------------------") + for block = 00, endblock do + local cmd = string.format("10%02x00", block) + res, err = sendRaw(cmd , {ignore_response = ignore_response}) + if err then disconnect() return oops(err) end + + local cmd_response = Command.parse(res) + local len = tonumber(cmd_response.arg1) * 2 + local data = string.sub(tostring(cmd_response.data), 0, len-4) + + showdata(block, data) + table.insert(blockData, data) + end + print("----+------------------+-------------------") + disconnect() + + local filename, err = writeDumpFile(info.uid, blockData) + if err then return oops(err) end + + print(string.format("\nDumped data into %s", filename)) end - + ------------------------- --- Testing +-- Testing ------------------------- function selftest() - DEBUG = true - dbg("Performing test") - main() - dbg("Tests done") + DEBUG = true + dbg("Performing test") + main() + dbg("Tests done") end --- Flip the switch here to perform a sanity check. +-- Flip the switch here to perform a sanity check. -- It read a nonce in two different ways, as specified in the usage-section -if "--test"==args then - selftest() -else - -- Call the main - main(args) +if "--test"==args then + selftest() +else + -- Call the main + main(args) end \ No newline at end of file diff --git a/client/scripts/ul_uid.lua b/client/scripts/ul_uid.lua index d87939c4a..7dbb51b49 100644 --- a/client/scripts/ul_uid.lua +++ b/client/scripts/ul_uid.lua @@ -6,139 +6,139 @@ author = "Iceman" version = 'v1.0.0' desc = [[ This script tries to set UID on a mifare Ultralight magic card which either - - answers to chinese backdoor commands + - answers to chinese backdoor commands - brickable magic tag (must write in one session) ]] example = [[ - -- backdoor magic tag - script run ul_uid -u 11223344556677 - - -- brickable magic tag - script run ul_uid -b -u 11223344556677 + -- backdoor magic tag + script run ul_uid -u 11223344556677 + + -- brickable magic tag + script run ul_uid -b -u 11223344556677 ]] usage = [[ script run ul_uid -h -b -u Arguments: - -h : this help - -u : UID (14 hexsymbols) - -b : write to brickable magic tag + -h : this help + -u : UID (14 hexsymbols) + -b : write to brickable magic tag ]] local DEBUG = true local bxor = bit32.bxor ---- +--- -- A debug printout-function local function dbg(args) if not DEBUG then return end if type(args) == "table" then - local i = 1 - while args[i] do - dbg(args[i]) - i = i+1 - end - else - print("###", args) - end -end ---- + local i = 1 + while args[i] do + dbg(args[i]) + i = i+1 + end + else + print("###", args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) - return nil, err + print("ERROR: ",err) + return nil, err end ---- +--- -- Usage help local function help() - print(copyright) - print(author) - print(version) - print(desc) - print('Example usage') - print(example) + print(copyright) + print(author) + print(version) + print(desc) + print('Example usage') + print(example) end -- --- Set UID on magic command enabled function magicUID(b0, b1, b2) - print('Using backdoor Magic tag function') + print('Using backdoor Magic tag function') - -- write block 0 - core.console("hf 14a raw -p -a -b 7 40") - core.console("hf 14a raw -p -a 43") - core.console("hf 14a raw -c -a A200"..b0) + -- write block 0 + core.console("hf 14a raw -p -a -b 7 40") + core.console("hf 14a raw -p -a 43") + core.console("hf 14a raw -c -a A200"..b0) - -- write block 1 - core.console("hf 14a raw -p -a -b 7 40") - core.console("hf 14a raw -p -a 43") - core.console("hf 14a raw -c -a A201"..b1) + -- write block 1 + core.console("hf 14a raw -p -a -b 7 40") + core.console("hf 14a raw -p -a 43") + core.console("hf 14a raw -c -a A201"..b1) - -- write block 2 - core.console("hf 14a raw -p -a -b 7 40") - core.console("hf 14a raw -p -a 43") - core.console("hf 14a raw -c -a A202"..b2) + -- write block 2 + core.console("hf 14a raw -p -a -b 7 40") + core.console("hf 14a raw -p -a 43") + core.console("hf 14a raw -c -a A202"..b2) end -- ---- Set UID on magic but brickable +--- Set UID on magic but brickable function brickableUID(b0, b1, b2) - - print('Using BRICKABLE Magic tag function') - - core.console("hf 14a raw -p -s -3") - - -- write block 0 - core.console("hf 14a raw -p -c A200"..b0) - -- write block 1 - core.console("hf 14a raw -p -c A201"..b1) + print('Using BRICKABLE Magic tag function') - -- write block 2 - core.console("hf 14a raw -p -c A202"..b2) + core.console("hf 14a raw -p -s -3") + + -- write block 0 + core.console("hf 14a raw -p -c A200"..b0) + + -- write block 1 + core.console("hf 14a raw -p -c A201"..b1) + + -- write block 2 + core.console("hf 14a raw -p -c A202"..b2) end ---- +--- -- The main entry point function main(args) - print( string.rep('--',20) ) - print( string.rep('--',20) ) - print() + print( string.rep('--',20) ) + print( string.rep('--',20) ) + print() - local uid = '04112233445566' - local tagtype = 1 - - -- Read the parameters - for o, a in getopt.getopt(args, 'hu:b') do - if o == "h" then return help() end - if o == "u" then uid = a end - if o == "b" then tagtype = 2 end - end - - -- uid string checks - if uid == nil then return oops('empty uid string') end - if #uid == 0 then return oops('empty uid string') end - if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end + local uid = '04112233445566' + local tagtype = 1 - local uidbytes = utils.ConvertHexToBytes(uid) - - local bcc1 = bxor(0x88, uidbytes[1], uidbytes[2], uidbytes[3]) - local bcc2 = bxor(uidbytes[4], uidbytes[5], uidbytes[6], uidbytes[7]) - - local block0 = string.format('%02X%02X%02X%02X', uidbytes[1], uidbytes[2], uidbytes[3], bcc1) - local block1 = string.format('%02X%02X%02X%02X', uidbytes[4], uidbytes[5], uidbytes[6], uidbytes[7]) - local block2 = string.format('%02X%02X%02X%02X', bcc2, 0x48, 0x00, 0x00) - - print('new UID | '..uid) - - core.clearCommandBuffer() - - if tagtype == 2 then - brickableUID(block0, block1, block2) - else - magicUID(block0, block1, block2) - end - - --halt - core.console("hf 14a raw -c -a 5000") + -- Read the parameters + for o, a in getopt.getopt(args, 'hu:b') do + if o == "h" then return help() end + if o == "u" then uid = a end + if o == "b" then tagtype = 2 end + end + + -- uid string checks + if uid == nil then return oops('empty uid string') end + if #uid == 0 then return oops('empty uid string') end + if #uid ~= 14 then return oops('uid wrong length. Should be 7 hex bytes') end + + local uidbytes = utils.ConvertHexToBytes(uid) + + local bcc1 = bxor(0x88, uidbytes[1], uidbytes[2], uidbytes[3]) + local bcc2 = bxor(uidbytes[4], uidbytes[5], uidbytes[6], uidbytes[7]) + + local block0 = string.format('%02X%02X%02X%02X', uidbytes[1], uidbytes[2], uidbytes[3], bcc1) + local block1 = string.format('%02X%02X%02X%02X', uidbytes[4], uidbytes[5], uidbytes[6], uidbytes[7]) + local block2 = string.format('%02X%02X%02X%02X', bcc2, 0x48, 0x00, 0x00) + + print('new UID | '..uid) + + core.clearCommandBuffer() + + if tagtype == 2 then + brickableUID(block0, block1, block2) + else + magicUID(block0, block1, block2) + end + + --halt + core.console("hf 14a raw -c -a 5000") end main(args) From 2d1a077ae4a52c66ae6565cb2a4c40a3ceaffa7d Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 10:40:45 +0100 Subject: [PATCH 0684/1938] lua: more fix mix of spaces & tabs --- client/lualibs/7816_error.lua | 116 ++-- client/lualibs/commands.lua | 106 ++-- client/lualibs/default_toys.lua | 56 +- client/lualibs/default_toys_di.lua | 30 +- client/lualibs/getopt.lua | 22 +- client/lualibs/hf_reader.lua | 36 +- client/lualibs/html_dumplib.lua | 262 ++++----- client/lualibs/htmlskel.lua | 642 ++++++++++----------- client/lualibs/precalc.lua | 94 ++-- client/lualibs/read14a.lua | 172 +++--- client/lualibs/read14b.lua | 204 +++---- client/lualibs/read15.lua | 230 ++++---- client/lualibs/taglib.lua | 18 +- client/lualibs/utils.lua | 858 ++++++++++++++--------------- 14 files changed, 1423 insertions(+), 1423 deletions(-) diff --git a/client/lualibs/7816_error.lua b/client/lualibs/7816_error.lua index 47779388d..038f668fb 100644 --- a/client/lualibs/7816_error.lua +++ b/client/lualibs/7816_error.lua @@ -1,78 +1,78 @@ --[[ local _errorcodes = { - SW_NO_ERROR = 0x9000, - SW_BYTES_REMAINING_00 = 0x6100, -- Response bytes remaining - SW_WARNING_STATE_UNCHANGED = 0x6200, -- Warning, card state unchanged = - SW_WRONG_LENGTH = 0x6700, -- : Wrong length - SW_WRONG_P1P2 = 0x6B00, -- : Incorrect parameters (P1,P2) - SW_CORRECT_LENGTH_00 = 0x6C00, -- : Correct Expected Length (Le) - SW_INS_NOT_SUPPORTED = 0x6D00, -- : INS value not supported - SW_CLA_NOT_SUPPORTED = 0x6E00, -- : CLA value not supported - SW_UNKNOWN = 0x6F00, -- : No precise diagnosis + SW_NO_ERROR = 0x9000, + SW_BYTES_REMAINING_00 = 0x6100, -- Response bytes remaining + SW_WARNING_STATE_UNCHANGED = 0x6200, -- Warning, card state unchanged = + SW_WRONG_LENGTH = 0x6700, -- : Wrong length + SW_WRONG_P1P2 = 0x6B00, -- : Incorrect parameters (P1,P2) + SW_CORRECT_LENGTH_00 = 0x6C00, -- : Correct Expected Length (Le) + SW_INS_NOT_SUPPORTED = 0x6D00, -- : INS value not supported + SW_CLA_NOT_SUPPORTED = 0x6E00, -- : CLA value not supported + SW_UNKNOWN = 0x6F00, -- : No precise diagnosis - SW_LOGICAL_CHANNEL_NOT_SUPPORTED = 0x6881, -- : Card does not support the operation on the specified logical channel - SW_SECURE_MESSAGING_NOT_SUPPORTED = 0x6882, -- : Card does not support secure messaging - SW_LAST_COMMAND_EXPECTED = 0x6883, -- : Last command in chain expected - SW_COMMAND_CHAINING_NOT_SUPPORTED = 0x6884, -- : Command chaining not supported + SW_LOGICAL_CHANNEL_NOT_SUPPORTED = 0x6881, -- : Card does not support the operation on the specified logical channel + SW_SECURE_MESSAGING_NOT_SUPPORTED = 0x6882, -- : Card does not support secure messaging + SW_LAST_COMMAND_EXPECTED = 0x6883, -- : Last command in chain expected + SW_COMMAND_CHAINING_NOT_SUPPORTED = 0x6884, -- : Command chaining not supported - SW_SECURITY_STATUS_NOT_SATISFIED = 0x6982, -- : Security condition not satisfied - SW_FILE_INVALID = 0x6983, -- : File invalid - SW_DATA_INVALID = 0x6984, -- : Data invalid - SW_CONDITIONS_NOT_SATISFIED = 0x6985, -- : Conditions of use not satisfied - SW_COMMAND_NOT_ALLOWED = 0x6986, -- : Command not allowed (no current EF) - SW_APPLET_SELECT_FAILED = 0x6999, -- : Applet selection failed + SW_SECURITY_STATUS_NOT_SATISFIED = 0x6982, -- : Security condition not satisfied + SW_FILE_INVALID = 0x6983, -- : File invalid + SW_DATA_INVALID = 0x6984, -- : Data invalid + SW_CONDITIONS_NOT_SATISFIED = 0x6985, -- : Conditions of use not satisfied + SW_COMMAND_NOT_ALLOWED = 0x6986, -- : Command not allowed (no current EF) + SW_APPLET_SELECT_FAILED = 0x6999, -- : Applet selection failed - SW_WRONG_DATA = 0x6A80, -- : Wrong data - SW_FUNC_NOT_SUPPORTED = 0x6A81, -- : Function not supported - SW_FILE_NOT_FOUND = 0x6A82, -- : File not found - SW_RECORD_NOT_FOUND = 0x6A83, -- : Record not found - SW_FILE_FULL = 0x6A84, -- : Not enough memory space in the file - SW_INCORRECT_P1P2 = 0x6A86, -- : Incorrect parameters (P1,P2) + SW_WRONG_DATA = 0x6A80, -- : Wrong data + SW_FUNC_NOT_SUPPORTED = 0x6A81, -- : Function not supported + SW_FILE_NOT_FOUND = 0x6A82, -- : File not found + SW_RECORD_NOT_FOUND = 0x6A83, -- : Record not found + SW_FILE_FULL = 0x6A84, -- : Not enough memory space in the file + SW_INCORRECT_P1P2 = 0x6A86, -- : Incorrect parameters (P1,P2) } --]] local _errorcodes = { - SW_NO_ERROR = '9000', - SW_BYTES_REMAINING_00 = '6100', -- Response bytes remaining - SW_WARNING_STATE_UNCHANGED = '6200', -- Warning', card state unchanged = - SW_WRONG_LENGTH = '6700', -- : Wrong length - SW_WRONG_P1P2 = '6B00', -- : Incorrect parameters (P1,P2) - SW_CORRECT_LENGTH_00 = '6C00', -- : Correct Expected Length (Le) - SW_INS_NOT_SUPPORTED = '6D00', -- : INS value not supported - SW_CLA_NOT_SUPPORTED = '6E00', -- : CLA value not supported - SW_UNKNOWN = '6F00', -- : No precise diagnosis + SW_NO_ERROR = '9000', + SW_BYTES_REMAINING_00 = '6100', -- Response bytes remaining + SW_WARNING_STATE_UNCHANGED = '6200', -- Warning', card state unchanged = + SW_WRONG_LENGTH = '6700', -- : Wrong length + SW_WRONG_P1P2 = '6B00', -- : Incorrect parameters (P1,P2) + SW_CORRECT_LENGTH_00 = '6C00', -- : Correct Expected Length (Le) + SW_INS_NOT_SUPPORTED = '6D00', -- : INS value not supported + SW_CLA_NOT_SUPPORTED = '6E00', -- : CLA value not supported + SW_UNKNOWN = '6F00', -- : No precise diagnosis - SW_LOGICAL_CHANNEL_NOT_SUPPORTED = '6881', -- : Card does not support the operation on the specified logical channel - SW_SECURE_MESSAGING_NOT_SUPPORTED = '6882', -- : Card does not support secure messaging - SW_LAST_COMMAND_EXPECTED = '6883', -- : Last command in chain expected - SW_COMMAND_CHAINING_NOT_SUPPORTED = '6884', -- : Command chaining not supported + SW_LOGICAL_CHANNEL_NOT_SUPPORTED = '6881', -- : Card does not support the operation on the specified logical channel + SW_SECURE_MESSAGING_NOT_SUPPORTED = '6882', -- : Card does not support secure messaging + SW_LAST_COMMAND_EXPECTED = '6883', -- : Last command in chain expected + SW_COMMAND_CHAINING_NOT_SUPPORTED = '6884', -- : Command chaining not supported - SW_SECURITY_STATUS_NOT_SATISFIED = '6982', -- : Security condition not satisfied - SW_FILE_INVALID = '6983', -- : File invalid - SW_DATA_INVALID = '6984', -- : Data invalid - SW_CONDITIONS_NOT_SATISFIED = '6985', -- : Conditions of use not satisfied - SW_COMMAND_NOT_ALLOWED = '6986', -- : Command not allowed (no current EF) - SW_APPLET_SELECT_FAILED = '6999', -- : Applet selection failed + SW_SECURITY_STATUS_NOT_SATISFIED = '6982', -- : Security condition not satisfied + SW_FILE_INVALID = '6983', -- : File invalid + SW_DATA_INVALID = '6984', -- : Data invalid + SW_CONDITIONS_NOT_SATISFIED = '6985', -- : Conditions of use not satisfied + SW_COMMAND_NOT_ALLOWED = '6986', -- : Command not allowed (no current EF) + SW_APPLET_SELECT_FAILED = '6999', -- : Applet selection failed - SW_WRONG_DATA = '6A80', -- : Wrong data - SW_FUNC_NOT_SUPPORTED = '6A81', -- : Function not supported - SW_FILE_NOT_FOUND = '6A82', -- : File not found - SW_RECORD_NOT_FOUND = '6A83', -- : Record not found - SW_FILE_FULL = '6A84', -- : Not enough memory space in the file - SW_INCORRECT_P1P2 = '6A86', -- : Incorrect parameters (P1,P2) + SW_WRONG_DATA = '6A80', -- : Wrong data + SW_FUNC_NOT_SUPPORTED = '6A81', -- : Function not supported + SW_FILE_NOT_FOUND = '6A82', -- : File not found + SW_RECORD_NOT_FOUND = '6A83', -- : Record not found + SW_FILE_FULL = '6A84', -- : Not enough memory space in the file + SW_INCORRECT_P1P2 = '6A86', -- : Incorrect parameters (P1,P2) } local _reverse_lookup,k,v = {} for k, v in pairs(_errorcodes) do - _reverse_lookup[v] = k + _reverse_lookup[v] = k end _errorcodes.tostring = function(command) - if(type(command) == 'string') then - return ("%s (%d)"):format(_reverse_lookup[command] or "ERROR UNDEFINED!", command) - end - if(type(command) == 'number') then - return ("%s (%d)"):format(_reverse_lookup[ tostring(command)] or "ERROR UNDEFINED!", command) - end - return ("Error, numeric or string argument expected, got : %s"):format(tostring(command)) + if(type(command) == 'string') then + return ("%s (%d)"):format(_reverse_lookup[command] or "ERROR UNDEFINED!", command) + end + if(type(command) == 'number') then + return ("%s (%d)"):format(_reverse_lookup[ tostring(command)] or "ERROR UNDEFINED!", command) + end + return ("Error, numeric or string argument expected, got : %s"):format(tostring(command)) end return _errorcodes \ No newline at end of file diff --git a/client/lualibs/commands.lua b/client/lualibs/commands.lua index e65d0f706..c493699c5 100644 --- a/client/lualibs/commands.lua +++ b/client/lualibs/commands.lua @@ -1,73 +1,73 @@ --[[ -Handle Proxmark USB Commands +Handle Proxmark USB Commands --]] local _commands = require('usb_cmd') local _reverse_lookup,k,v = {} - for k, v in pairs(_commands) do - _reverse_lookup[v] = k - end - _commands.tostring = function(command) - if(type(command) == 'number') then - return ("%s (%d)"):format(_reverse_lookup[command]or "ERROR UNDEFINED!", command) - end - return ("Error, numeric argument expected, got : %s"):format(tostring(command)) + for k, v in pairs(_commands) do + _reverse_lookup[v] = k + end + _commands.tostring = function(command) + if(type(command) == 'number') then + return ("%s (%d)"):format(_reverse_lookup[command]or "ERROR UNDEFINED!", command) + end + return ("Error, numeric argument expected, got : %s"):format(tostring(command)) end Command = { - new = function(self, o) + new = function(self, o) - local o = o or {} -- create object if user does not provide one - setmetatable(o, self) -- DIY inheritance a'la javascript - self.__index = self + local o = o or {} -- create object if user does not provide one + setmetatable(o, self) -- DIY inheritance a'la javascript + self.__index = self - o.cmd = o.cmd or _commands.CMD_UNKNOWN - o.arg1 = o.arg1 or 0 - o.arg2 = o.arg2 or 0 - o.arg3 = o.arg3 or 0 - local data = o.data or "0" + o.cmd = o.cmd or _commands.CMD_UNKNOWN + o.arg1 = o.arg1 or 0 + o.arg2 = o.arg2 or 0 + o.arg3 = o.arg3 or 0 + local data = o.data or "0" - if(type(data) == 'string') then - -- We need to check if it is correct length, otherwise pad it - local len = string.len(data) - if(len < 1024) then - --Should be 1024 hex characters to represent 512 bytes of data - data = data .. string.rep("0",1024 - len ) - end - if(len > 1024) then - -- OOps, a bit too much data here - print( ( "WARNING: data size too large, was %s chars, will be truncated "):format(len) ) - -- - data = data:sub(1,1024) - end - else - print(("WARNING; data was NOT a (hex-) string, but was %s"):format(type(data))) - end - o.data = data - return o - end, - parse = function (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 + if(type(data) == 'string') then + -- We need to check if it is correct length, otherwise pad it + local len = string.len(data) + if(len < 1024) then + --Should be 1024 hex characters to represent 512 bytes of data + data = data .. string.rep("0",1024 - len ) + end + if(len > 1024) then + -- OOps, a bit too much data here + print( ( "WARNING: data size too large, was %s chars, will be truncated "):format(len) ) + -- + data = data:sub(1,1024) + end + else + print(("WARNING; data was NOT a (hex-) string, but was %s"):format(type(data))) + end + o.data = data + return o + end, + parse = function (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 } function Command:__tostring() - local output = ("%s\r\nargs : (%s, %s, %s)\r\ndata:\r\n%s\r\n"):format( - _commands.tostring(self.cmd), - tostring(self.arg1), - tostring(self.arg2), - tostring(self.arg3), - tostring(self.data)) - return output + local output = ("%s\r\nargs : (%s, %s, %s)\r\ndata:\r\n%s\r\n"):format( + _commands.tostring(self.cmd), + tostring(self.arg1), + tostring(self.arg2), + tostring(self.arg3), + tostring(self.data)) + return output end function Command:getBytes() - --If a hex-string has been used - local data = self.data - local cmd = self.cmd - local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3 - return bin.pack("LLLLH",cmd, arg1, arg2, arg3, data); + --If a hex-string has been used + local data = self.data + local cmd = self.cmd + local arg1, arg2, arg3 = self.arg1, self.arg2, self.arg3 + return bin.pack("LLLLH",cmd, arg1, arg2, arg3, data); end return _commands diff --git a/client/lualibs/default_toys.lua b/client/lualibs/default_toys.lua index 62fe88f31..a0591c1fc 100644 --- a/client/lualibs/default_toys.lua +++ b/client/lualibs/default_toys.lua @@ -185,25 +185,25 @@ local _names = { {"404", "9401", "0030", "earth", "legendary","Bash"}, {"416", "a001", "0030", "magic", "legendary", "Spyro"}, - --{"", "", "0030", "magic", "legendary", "Deja Vu"}, + --{"", "", "0030", "magic", "legendary", "Deja Vu"}, {"419", "a301", "0030", "tech", "legendary", "Trigger Happy"}, - --{"", "", "0030", "tech", "legendary", "bouncer"}, - --{"", "", "0030", "tech", "legendary", "jawbreaker"}, + --{"", "", "0030", "tech", "legendary", "bouncer"}, + --{"", "", "0030", "tech", "legendary", "jawbreaker"}, {"430", "ae01", "0030", "undead", "legendary", "Chop Chop"}, - --{"", "", "0030", "undead", "legendary", "grim creeper"}, - --{"", "", "0030", "undead", "legendary", "night shift"}, - - --{"", "", "0030", "air", "legendary", "blades"}, - --{"", "", "0030", "air", "legendary", "jet vac"}, - --{"", "", "0030", "air", "legendary", "Free Ranger"}, - --{"", "", "0030", "life", "legendary", "stealth elf"}, - --{"", "", "0030", "life", "legendary", "Bushwhack"}, - --{"", "", "0030", "fire", "legendary", "ignitor"}, - --{"", "", "0030", "water", "legendary", "slam bam"}, - --{"", "", "0030", "water", "legendary", "chill"}, + --{"", "", "0030", "undead", "legendary", "grim creeper"}, + --{"", "", "0030", "undead", "legendary", "night shift"}, + + --{"", "", "0030", "air", "legendary", "blades"}, + --{"", "", "0030", "air", "legendary", "jet vac"}, + --{"", "", "0030", "air", "legendary", "Free Ranger"}, + --{"", "", "0030", "life", "legendary", "stealth elf"}, + --{"", "", "0030", "life", "legendary", "Bushwhack"}, + --{"", "", "0030", "fire", "legendary", "ignitor"}, + --{"", "", "0030", "water", "legendary", "slam bam"}, + --{"", "", "0030", "water", "legendary", "chill"}, + + --{"", "", "0030", "", "legendary", "zoo lou"}, - --{"", "", "0030", "", "legendary", "zoo lou"}, - {"450", "c201", "0030", "air", "trapmaster", "Gusto"}, --{"450", "c201", "0234", "air", "trapmaster", "Special Gusto"}, {"451", "c301", "0030", "air", "trapmaster", "Thunderbolt"}, @@ -453,23 +453,23 @@ local _names = { local function find( main, sub) main = main:lower() - sub = sub:lower() + sub = sub:lower() for k, v in pairs(_names) do - if ( v[2]:lower() == main and v[3]:lower() == sub) then - return v - end - end - return nil + if ( v[2]:lower() == main and v[3]:lower() == sub) then + return v + end + end + return nil end local function list() - print ("Type\tSub\tElement\tGame Name") - print (string.rep('=', 54)) + print ("Type\tSub\tElement\tGame Name") + print (string.rep('=', 54)) for k, v in pairs(_names) do - print(("%s\t%s\t%s\t%-9s\t%s"):format(v[2],v[3],v[4], v[5], v[6] )) - end + print(("%s\t%s\t%s\t%-9s\t%s"):format(v[2],v[3],v[4], v[5], v[6] )) + end end return { - Find = find, - List = list, + Find = find, + List = list, } diff --git a/client/lualibs/default_toys_di.lua b/client/lualibs/default_toys_di.lua index 4d5d75020..8060dbcd4 100644 --- a/client/lualibs/default_toys_di.lua +++ b/client/lualibs/default_toys_di.lua @@ -1,5 +1,5 @@ - --[[ - decimal, di edition, model name + --[[ + decimal, di edition, model name --]] local _names = { {"1000001","1","Mr. Incredible"}, @@ -319,8 +319,8 @@ local _names = { {"4000226","3","?? unknown ??"}, {"4000227","3","?? unknown ??"}, {"4000229","3","Quad Jumper"}, ---[[ - these below are Portals. Not to be used for tags. +--[[ + these below are Portals. Not to be used for tags. --]] {"8032384","0","Infinity Base - 3DS"}, {"8032385","0","Infinity Base - Xbox"}, @@ -332,21 +332,21 @@ local _names = { local function find( main ) main = main:lower() for k, v in pairs(_names) do - if ( v[1]:lower() == main ) then - return v - end - end - return nil + if ( v[1]:lower() == main ) then + return v + end + end + return nil end local function list() - print ("Type\tEdition\t Model name") - print (string.rep('=', 54)) + print ("Type\tEdition\t Model name") + print (string.rep('=', 54)) for k, v in pairs(_names) do - print(("%s\t%s\t%s"):format(v[1],v[2],v[3] )) - end + print(("%s\t%s\t%s"):format(v[1],v[2],v[3] )) + end end return { - Find = find, - List = list, + Find = find, + List = list, } diff --git a/client/lualibs/getopt.lua b/client/lualibs/getopt.lua index add11842a..2265c106b 100644 --- a/client/lualibs/getopt.lua +++ b/client/lualibs/getopt.lua @@ -7,19 +7,19 @@ https://github.com/attractivechaos/klib/blob/master/lua/klib.lua --[[ The MIT License - + Copyright (c) 2011, Attractive Chaos - + Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - + The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE @@ -56,8 +56,8 @@ local function getopt(args, ostr) return function () if place == 0 then -- update scanning pointer place = 1 - if #args == 0 - or args[1]:sub(1, 1) ~= '-' then + if #args == 0 + or args[1]:sub(1, 1) ~= '-' then place = 0; return nil end if #args[1] >= 2 then place = place + 1 @@ -96,12 +96,12 @@ local function getopt(args, ostr) if ostr:sub(1, 1) == ':' then return ':' end return '?'; else arg = args[1] end - end - table.remove(args, 1); - place = 0; - end + end + table.remove(args, 1); + place = 0; + end return optopt, arg; end end -return { getopt = getopt } +return { getopt = getopt } diff --git a/client/lualibs/hf_reader.lua b/client/lualibs/hf_reader.lua index c9970f772..d0550a335 100644 --- a/client/lualibs/hf_reader.lua +++ b/client/lualibs/hf_reader.lua @@ -1,7 +1,7 @@ --[[ -THIS IS WORK IN PROGREESS, very much not finished. +THIS IS WORK IN PROGREESS, very much not finished. -This library utilises other libraries under the hood, but can be used as a generic reader for 13.56MHz tags. +This library utilises other libraries under the hood, but can be used as a generic reader for 13.56MHz tags. ]] local reader14443A = require('read14a') @@ -10,26 +10,26 @@ local reader15693 = require('read15') --- -- This method library can be set waits or a 13.56 MHz tag, and when one is found, returns info about --- what tag it is. --- +-- what tag it is. +-- -- @return if successfull: an table containing card info -- @return if unsuccessfull : nil, error local function waitForTag() - print("Waiting for card... press any key to quit") - local readers = {reader14443A, reader14443B, reader15693} - local i = 0; - while not core.ukbhit() do - i = (i % 3) +1 - r = readers[i] - print("Reading with ",i) - res, err = r.read() - if res then return res end - print(err) - -- err means that there was no response from card - end - return nil, "Aborted by user" + print("Waiting for card... press any key to quit") + local readers = {reader14443A, reader14443B, reader15693} + local i = 0; + while not core.ukbhit() do + i = (i % 3) +1 + r = readers[i] + print("Reading with ",i) + res, err = r.read() + if res then return res end + print(err) + -- err means that there was no response from card + end + return nil, "Aborted by user" end return { - waitForTag = waitForTag, + waitForTag = waitForTag, } \ No newline at end of file diff --git a/client/lualibs/html_dumplib.lua b/client/lualibs/html_dumplib.lua index 59cebf593..de462f19b 100644 --- a/client/lualibs/html_dumplib.lua +++ b/client/lualibs/html_dumplib.lua @@ -2,154 +2,154 @@ bin = require('bin') ------------------------------- --- Some utilities +-- Some utilities ------------------------------- ---- +--- -- A debug printout-function local function dbg(args) - + if type(args) == "table" then - local i = 1 - while args[i] do - print("###", args[i]) - i = i+1 - end - else - print("###", args) - end -end ---- + local i = 1 + while args[i] do + print("###", args[i]) + i = i+1 + end + else + print("###", args) + end +end +--- -- This is only meant to be used when errors occur local function oops(err) - print("ERROR: ",err) - return nil, err + print("ERROR: ",err) + return nil, err end local function save_HTML(javascript, filename) - -- Read the HTML-skel file - local skel = require("htmlskel") - html = skel.getHTML(javascript); + -- Read the HTML-skel file + local skel = require("htmlskel") + html = skel.getHTML(javascript); - -- Open the output file - - local outfile = io.open(filename, "w") - if outfile == nil then - return oops(string.format("Could not write to file %s",tostring(filename))) - end - -- Write the data into it - outfile:write(html) - io.close(outfile) + -- Open the output file - -- Done - return filename + local outfile = io.open(filename, "w") + if outfile == nil then + return oops(string.format("Could not write to file %s",tostring(filename))) + end + -- Write the data into it + outfile:write(html) + io.close(outfile) + + -- Done + return filename end local function save_TEXT(data,filename) - -- Open the output file - local outfile = io.open(filename, "w") - if outfile == nil then - return oops(string.format("Could not write to file %s",tostring(filename))) - end - - outfile:write(data) - io.close(outfile) - return filename + -- Open the output file + local outfile = io.open(filename, "w") + if outfile == nil then + return oops(string.format("Could not write to file %s",tostring(filename))) + end + + outfile:write(data) + io.close(outfile) + return filename end local function save_BIN(data, filename) - -- Open the output file - - local outfile = io.open(filename, "wb") - if outfile == nil then - return oops(string.format("Could not write to file %s",tostring(filename))) - end - - -- Write the data into it - local i = 1 - while data[i] do - outfile:write(data[i]) - i = i+1 - end - - io.close(outfile) - return filename + -- Open the output file + + local outfile = io.open(filename, "wb") + if outfile == nil then + return oops(string.format("Could not write to file %s",tostring(filename))) + end + + -- Write the data into it + local i = 1 + while data[i] do + outfile:write(data[i]) + i = i+1 + end + + io.close(outfile) + return filename end local function convert_ascii_dump_to_JS(infile) - local t = infile:read("*all") - local cleaned - local output = "["; - for line in string.gmatch(t, "[^\n]+") do - if string.byte(line,1) ~= string.byte("+",1) then - cleaned = (line or ''):gsub('%s+','') - output = output .. "'"..cleaned.."',\n" + local t = infile:read("*all") + local cleaned + local output = "["; + for line in string.gmatch(t, "[^\n]+") do + if string.byte(line,1) ~= string.byte("+",1) then + cleaned = (line or ''):gsub('%s+','') + output = output .. "'"..cleaned.."',\n" end - end - output = output .. "]" - return output + end + output = output .. "]" + return output end local function convert_binary_dump_to_JS(infile, blockLen) - local bindata = infile:read("*all") - len = string.len(bindata) + local bindata = infile:read("*all") + len = string.len(bindata) - if len % blockLen ~= 0 then - return oops(("Bad data, length (%d) should be a multiple of blocklen (%d)"):format(len, blockLen)) - end + if len % blockLen ~= 0 then + return oops(("Bad data, length (%d) should be a multiple of blocklen (%d)"):format(len, blockLen)) + end - local _,hex = bin.unpack(("H%d"):format(len),bindata) + local _,hex = bin.unpack(("H%d"):format(len),bindata) - -- Now that we've converted binary data into hex, we doubled the size. - -- One byte, like 0xDE is now - -- the characters 'D' and 'E' : one byte each. - -- Thus: - blockLen = blockLen * 2 + -- Now that we've converted binary data into hex, we doubled the size. + -- One byte, like 0xDE is now + -- the characters 'D' and 'E' : one byte each. + -- Thus: + blockLen = blockLen * 2 - local js,i = "["; - for i = 1, string.len(hex),blockLen do - js = js .."'" ..string.sub(hex,i,i+blockLen -1).."',\n" - end - js = js .. "]" - return js + local js,i = "["; + for i = 1, string.len(hex),blockLen do + js = js .."'" ..string.sub(hex,i,i+blockLen -1).."',\n" + end + js = js .. "]" + return js end local function convert_ascii_dump_to_BIN(infile) - local t = infile:read("*all") - local cleaned - local output = {}; - for line in string.gmatch(t, "[^\n]+") do - if string.byte(line) ~= string.byte("+") then - cleaned = (line or ''):gsub('%s+','') - for c in cleaned:gmatch('..') do - output[#output+1] = string.char( tonumber(c,16) ) - end - end - end - return output + local t = infile:read("*all") + local cleaned + local output = {}; + for line in string.gmatch(t, "[^\n]+") do + if string.byte(line) ~= string.byte("+") then + cleaned = (line or ''):gsub('%s+','') + for c in cleaned:gmatch('..') do + output[#output+1] = string.char( tonumber(c,16) ) + end + end + end + return output end --- --- Converts a .eml-file into a HTML/Javascript file. +-- Converts a .eml-file into a HTML/Javascript file. -- @param input the file to convert -- @param output the file to write to --- @return the name of the new file. +-- @return the name of the new file. local function convert_eml_to_html(input, output) - input = input or 'dumpdata.eml' - output = output or input .. 'html' + input = input or 'dumpdata.eml' + output = output or input .. 'html' - local infile = io.open(input, "r") - if infile == nil then - return oops(string.format("Could not read file %s",tostring(input))) - end + local infile = io.open(input, "r") + if infile == nil then + return oops(string.format("Could not read file %s",tostring(input))) + end - -- Read file, get JS - local javascript = convert_ascii_dump_to_JS(infile) - io.close(infile) - return save_HTML(javascript, output ) + -- Read file, get JS + local javascript = convert_ascii_dump_to_JS(infile) + io.close(infile) + return save_HTML(javascript, output ) end --- Converts a binary dump into HTML/Javascript file @@ -157,46 +157,46 @@ end -- @param output the file to write to -- @param blockLen, the length of each block. Defaults to 16 bytes local function convert_bin_to_html(input, output, blockLen) - input = input or 'dumpdata.bin' - blockLen = blockLen or 16 - output = output or input .. 'html' + input = input or 'dumpdata.bin' + blockLen = blockLen or 16 + output = output or input .. 'html' - local infile = io.open(input, "rb") - if infile == nil then - return oops(string.format("Could not read file %s",tostring(input))) - end - -- Read file, get JS - local javascript = convert_binary_dump_to_JS(infile, blockLen) - io.close(infile) + local infile = io.open(input, "rb") + if infile == nil then + return oops(string.format("Could not read file %s",tostring(input))) + end + -- Read file, get JS + local javascript = convert_binary_dump_to_JS(infile, blockLen) + io.close(infile) - return save_HTML(javascript, output ) + return save_HTML(javascript, output ) end --- Converts a eml dump into a binary file -- @param input the file containing the eml-dump (defaults to dumpdata.eml) -- @param output the file to write to ( defaults to dumpdata.bin) local function convert_eml_to_bin(input, output) - input = input or 'dumpdata.eml' - output = output or 'dumpdata.bin' + input = input or 'dumpdata.eml' + output = output or 'dumpdata.bin' - local infile = io.open(input, "rb") - if infile == nil then - return oops(string.format("Could not read file %s",tostring(input))) - end - -- Read file, get BIN - local data = convert_ascii_dump_to_BIN(infile) - io.close(infile) + local infile = io.open(input, "rb") + if infile == nil then + return oops(string.format("Could not read file %s",tostring(input))) + end + -- Read file, get BIN + local data = convert_ascii_dump_to_BIN(infile) + io.close(infile) - return save_BIN(data, output ) + return save_BIN(data, output ) end return { - convert_bin_to_html = convert_bin_to_html, - convert_eml_to_html = convert_eml_to_html, - convert_eml_to_bin = convert_eml_to_bin, + convert_bin_to_html = convert_bin_to_html, + convert_eml_to_html = convert_eml_to_html, + convert_eml_to_bin = convert_eml_to_bin, SaveAsBinary = save_BIN, - SaveAsText = save_TEXT, + SaveAsText = save_TEXT, SaveAsBinary = save_BIN, - SaveAsText = save_TEXT, + SaveAsText = save_TEXT, } diff --git a/client/lualibs/htmlskel.lua b/client/lualibs/htmlskel.lua index f216df1e1..ee5f6583e 100644 --- a/client/lualibs/htmlskel.lua +++ b/client/lualibs/htmlskel.lua @@ -2,360 +2,360 @@ local skel_1 = [[ - + add("04,,,Mifare TNP3xxx Activision 1K,0f01,01"); + add("04,,,Mifare Mini,0004,09"); + add("04,,,Mifare Classic 1k/Mifare Plus(4 byte UID) 2K SL1,0004,08"); + add("04,,,Mifare Plus (4 byte UID) 2K SL2,0004,10"); + add("04,,,Mifare Plus (4 byte UID) 4K SL2,0004,11"); + add("04,,,Mifare Plus (4 byte UID) 4K SL1,0004,18"); + add("04,,,Mifare Plus (4 byte UID) 2K/4K SL3,0004,20"); + add("04,,,Mifare Classic 4K,0002,18"); + add("xx,,,NDEF Tags,0044,00 "); + add("04,,,Mifare Ultralight/UltralightC,0044,04"); + add("04,,,Mifare Plus (7 byte UID) 2K SL1,0042,08"); + add("04,,,Mifare Plus (7 byte UID) 2K SL1,0044,08"); + add("04,,,Mifare Plus (7 byte UID) 4K SL1,0042,18"); + add("04,,,Mifare Plus (7 byte UID) 4K SL1,0044,18"); + add("04,,,Mifare Plus (7 byte UID),0042,10"); + add("04,,,Mifare Plus (7 byte UID),0044,10"); + add("04,,,Mifare Plus (7 byte UID),0042,11"); + add("04,,,Mifare Plus (7 byte UID),0044,11"); + add("04,,,Mifare Plus (7 byte UID),0042,20"); + add("04,,,Mifare Plus (7 byte UID),0044,20"); + add("04,,,Mifare DesFire / DesFire EV1,0344,20067577810280"); + add("04,,,JCOP31,0304,283877B14A434F503331"); + add("04,,,JCOP31 v2.4.1,0048,207877B1024A434F5076323431"); + add("04,,,JCOP41 v2.2,0048,203833B14A434F503431563232"); + add("04,,,JCOP41 v2.3.1,0004,283833B14A434F50343156323331"); + add("05,,,Mifare Classic 1K,0004,88"); + add("40,,,MPCOS,0002,98"); + add("25,,,Topaz/Topaz512/Jewel,0C00,"); + add("1D,,,FM1208SH01,0004,53"); + add("1D,,,FM1208,0008,20"); + add("Nokia,,,Mifare Classic 4K emulated by Nokia 6212,0002,38"); + add("Nokia,,,Mifare Classic 4K emulated by Nokia 6131,0008,38"); + add("04,,,Smart MX with Mifare 4K emulation,0002"); + add("04,,,Smart MX with Mifare 4K emulation,0102"); + add("04,,,Smart MX with Mifare 4K emulation,0202"); + add("04,,,Smart MX with Mifare 4K emulation,0302"); + add("04,,,Smart MX with Mifare 4K emulation,0402"); + add("04,,,Smart MX with Mifare 4K emulation,0502"); + add("04,,,Smart MX with Mifare 4K emulation,0602"); + add("04,,,Smart MX with Mifare 4K emulation,0702"); + add("04,,,Smart MX with Mifare 4K emulation,0802"); + add("04,,,Smart MX with Mifare 4K emulation,0902"); + add("04,,,Smart MX with Mifare 4K emulation,0A02"); + add("04,,,Smart MX with Mifare 4K emulation,0B02"); + add("04,,,Smart MX with Mifare 4K emulation,0C02"); + add("04,,,Smart MX with Mifare 4K emulation,0D02"); + add("04,,,Smart MX with Mifare 4K emulation,0E02"); + add("04,,,Smart MX with Mifare 4K emulation,0F02"); + add("04,,,Smart MX with Mifare 1K emulation,0004"); + add("04,,,Smart MX with Mifare 1K emulation,0104"); + add("04,,,Smart MX with Mifare 1K emulation,0204"); + add("04,,,Smart MX with Mifare 1K emulation,0304"); + add("04,,,Smart MX with Mifare 1K emulation,0404"); + add("04,,,Smart MX with Mifare 1K emulation,0504"); + add("04,,,Smart MX with Mifare 1K emulation,0604"); + add("04,,,Smart MX with Mifare 1K emulation,0704"); + add("04,,,Smart MX with Mifare 1K emulation,0804"); + add("04,,,Smart MX with Mifare 1K emulation,0904"); + add("04,,,Smart MX with Mifare 1K emulation,0A04"); + add("04,,,Smart MX with Mifare 1K emulation,0B04"); + add("04,,,Smart MX with Mifare 1K emulation,0C04"); + add("04,,,Smart MX with Mifare 1K emulation,0D04"); + add("04,,,Smart MX with Mifare 1K emulation,0E04"); + add("04,,,Smart MX with Mifare 1K emulation,0F04"); + add("04,,,Smart MX with 7 byte UID,0048"); + add("04,,,Smart MX with 7 byte UID,0148"); + add("04,,,Smart MX with 7 byte UID,0248"); + add("04,,,Smart MX with 7 byte UID,0348"); + add("04,,,Smart MX with 7 byte UID,0448"); + add("04,,,Smart MX with 7 byte UID,0548"); + add("04,,,Smart MX with 7 byte UID,0648"); + add("04,,,Smart MX with 7 byte UID,0748"); + add("04,,,Smart MX with 7 byte UID,0848"); + add("04,,,Smart MX with 7 byte UID,0948"); + add("04,,,Smart MX with 7 byte UID,0A48"); + add("04,,,Smart MX with 7 byte UID,0B48"); + add("04,,,Smart MX with 7 byte UID,0C48"); + add("04,,,Smart MX with 7 byte UID,0D48"); + add("04,,,Smart MX with 7 byte UID,0E48"); + add("04,,,Smart MX with 7 byte UID,0F48"); + - - - - + + }; + handle(x); + ]] local function getHTML(data) - return skel_1 .. data .. skel_2 + return skel_1 .. data .. skel_2 end return {getHTML = getHTML} diff --git a/client/lualibs/precalc.lua b/client/lualibs/precalc.lua index cedad4cf2..71d91c05a 100644 --- a/client/lualibs/precalc.lua +++ b/client/lualibs/precalc.lua @@ -1,5 +1,5 @@ --[[ - This is an experimental lib. + This is an experimental lib. --]] local utils = require('utils') @@ -35,60 +35,60 @@ shifts[9]= { 0xD, 0xB, 0x0, 0x6, 0x6, 0x0, 0xB, 0xD, 0xA, 0xC, 0x7, 0x1, 0x1, 0x shifts[10]= { 0xe, 0x1, 0x1, 0xe, 0x1, 0xe, 0xe, 0x1, 0x1, 0xe, 0xe, 0x1, 0xe, 0x1, 0x1, 0xe } local function ApplyPermutationAndShifts( pos, value, nibble) - local shiftbytes = shifts[pos] - local shiftElem = shiftbytes[nibble+1] --one indexed - local shiftOne = shiftbytes[1] - local rs = bit32.bxor(value, shiftOne, shiftElem) - return rs + local shiftbytes = shifts[pos] + local shiftElem = shiftbytes[nibble+1] --one indexed + local shiftOne = shiftbytes[1] + local rs = bit32.bxor(value, shiftOne, shiftElem) + return rs end local function GetOne( uid, block ) - if uid == nil then return nil, 'empty uid string' end - if #uid == 0 then return nil, 'empty uid string' end - if #uid ~= 8 then return nil, 'uid wrong length. Should be 4 hex bytes' end - if type(block) ~= 'number' then return nil, 'block is not number' end - if block > 16 or block < 0 then return nil, 'block is out-of-range' end - - local s = ('%s%02X'):format(uid,block) - local nibble1 = tonumber(s:sub(1,1),16) + 1 + if uid == nil then return nil, 'empty uid string' end + if #uid == 0 then return nil, 'empty uid string' end + if #uid ~= 8 then return nil, 'uid wrong length. Should be 4 hex bytes' end + if type(block) ~= 'number' then return nil, 'block is not number' end + if block > 16 or block < 0 then return nil, 'block is out-of-range' end - local permuted = '' - for i = 1, #s do - local el_row = shifts[i] - local el_value = el_row[nibble1] - j = 1 - while j <= i do - if i-j > 0 then - local nibble = tonumber(s:sub(j+1,j+1),16) - el_value = ApplyPermutationAndShifts(i-j, el_value, nibble) - end - j = j+1 - end - permuted =('%s%X'):format(permuted,el_value) - end + local s = ('%s%02X'):format(uid,block) + local nibble1 = tonumber(s:sub(1,1),16) + 1 - permuted = 'C2'..permuted - local crc64numStr = utils.Crc64(permuted) - local keybytes = utils.ConvertAsciiToBytes(crc64numStr, true) - local key = utils.ConvertBytesToHex(keybytes) - return key:sub(1,12) + local permuted = '' + for i = 1, #s do + local el_row = shifts[i] + local el_value = el_row[nibble1] + j = 1 + while j <= i do + if i-j > 0 then + local nibble = tonumber(s:sub(j+1,j+1),16) + el_value = ApplyPermutationAndShifts(i-j, el_value, nibble) + end + j = j+1 + end + permuted =('%s%X'):format(permuted,el_value) + end + + permuted = 'C2'..permuted + local crc64numStr = utils.Crc64(permuted) + local keybytes = utils.ConvertAsciiToBytes(crc64numStr, true) + local key = utils.ConvertBytesToHex(keybytes) + return key:sub(1,12) end -local PreCalc = +local PreCalc = { - GetAll = function(id) - if id == nil then return nil, 'empty string' end - if #id == 0 then return nil, 'empty string' end - if #id ~= 8 then return nil, 'wrong length. Should be 4 hex bytes' end - - local list = '4b0b20107ccb' - for i = 1,15 do - local key, err = GetOne(id,i) - if not key then return oops(err) end - list = list..key - end - return list - end, + GetAll = function(id) + if id == nil then return nil, 'empty string' end + if #id == 0 then return nil, 'empty string' end + if #id ~= 8 then return nil, 'wrong length. Should be 4 hex bytes' end + + local list = '4b0b20107ccb' + for i = 1,15 do + local key, err = GetOne(id,i) + if not key then return oops(err) end + list = list..key + end + return list + end, } return PreCalc \ No newline at end of file diff --git a/client/lualibs/read14a.lua b/client/lualibs/read14a.lua index 9e53cacca..8ed87f5eb 100644 --- a/client/lualibs/read14a.lua +++ b/client/lualibs/read14a.lua @@ -1,32 +1,32 @@ --[[ - This is a library to read 14443a tags. It can be used something like this + This is a library to read 14443a tags. It can be used something like this - local reader = require('read14a') - result, err = reader.read14443a() - if not result then - print(err) - return - end - print(result.name) + local reader = require('read14a') + result, err = reader.read14443a() + if not result then + print(err) + return + end + print(result.name) --]] -- Loads the commands-library local cmds = require('commands') local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds local ISO14A_COMMAND = { - ISO14A_CONNECT = 1, - ISO14A_NO_DISCONNECT = 2, - ISO14A_APDU = 4, - ISO14A_RAW = 8, - ISO14A_REQUEST_TRIGGER = 0x10, - ISO14A_APPEND_CRC = 0x20, - ISO14A_SET_TIMEOUT = 0x40, - ISO14A_NO_SELECT = 0x80, - ISO14A_TOPAZMODE = 0x100, - ISO14A_NO_RATS = 0x200 + ISO14A_CONNECT = 1, + ISO14A_NO_DISCONNECT = 2, + ISO14A_APDU = 4, + ISO14A_RAW = 8, + ISO14A_REQUEST_TRIGGER = 0x10, + ISO14A_APPEND_CRC = 0x20, + ISO14A_SET_TIMEOUT = 0x40, + ISO14A_NO_SELECT = 0x80, + ISO14A_TOPAZMODE = 0x100, + ISO14A_NO_RATS = 0x200 } -local ISO14443a_TYPES = {} +local ISO14443a_TYPES = {} ISO14443a_TYPES[0x00] = "NXP MIFARE Ultralight | Ultralight C | NTAG" ISO14443a_TYPES[0x01] = "NXP MIFARE TNP3xxx Activision Game Appliance" ISO14443a_TYPES[0x04] = "NXP MIFARE (various !DESFire !DESFire EV1)" @@ -45,50 +45,50 @@ ISO14443a_TYPES[0x98] = "Gemplus MPCOS" local function tostring_14443a(sak) - return ISO14443a_TYPES[sak] or ("Unknown (SAK=%x)"):format(sak) + return ISO14443a_TYPES[sak] or ("Unknown (SAK=%x)"):format(sak) end local function parse14443a(data) - --[[ + --[[ - Based on this struct : + Based on this struct : - typedef struct { - byte_t uid[10]; - byte_t uidlen; - byte_t atqa[2]; - byte_t sak; - byte_t ats_len; - byte_t ats[256]; - } __attribute__((__packed__)) iso14a_card_select_t; + typedef struct { + byte_t uid[10]; + byte_t uidlen; + byte_t atqa[2]; + byte_t sak; + byte_t ats_len; + byte_t ats[256]; + } __attribute__((__packed__)) iso14a_card_select_t; - --]] + --]] - local count, uid, uidlen, atqa, sak, ats_len, ats = bin.unpack('H10CH2CC',data) - uid = uid:sub(1, 2*uidlen) - --print("uid, atqa, sak: ",uid, atqa, sak) - --print("TYPE: ", tostring_1443a(sak)) - return { uid = uid, atqa = atqa, sak = sak, name = tostring_14443a(sak), data = data} + local count, uid, uidlen, atqa, sak, ats_len, ats = bin.unpack('H10CH2CC',data) + uid = uid:sub(1, 2*uidlen) + --print("uid, atqa, sak: ",uid, atqa, sak) + --print("TYPE: ", tostring_1443a(sak)) + return { uid = uid, atqa = atqa, sak = sak, name = tostring_14443a(sak), data = data} end --- Sends a USBpacket to the device -- @param command - the usb packet to send -- @param ignoreresponse - if set to true, we don't read the device answer packet --- which is usually recipe for fail. If not sent, the host will wait 2s for a --- response of type CMD_ACK --- @return packet,nil if successfull --- nil, errormessage if unsuccessfull +-- which is usually recipe for fail. If not sent, the host will wait 2s for a +-- response of type CMD_ACK +-- @return packet,nil if successfull +-- nil, errormessage if unsuccessfull local function sendToDevice(command, ignoreresponse) - --core.clearCommandBuffer() - local err = core.SendCommand(command:getBytes()) - if err then - print(err) - return nil, err - end - if ignoreresponse then return nil,nil end + --core.clearCommandBuffer() + local err = core.SendCommand(command:getBytes()) + if err then + print(err) + return nil, err + end + if ignoreresponse then return nil,nil end - local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) - return response,nil + local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) + return response,nil end -- This function does a connect and retrieves som einfo @@ -96,34 +96,34 @@ end -- @return if successfull: an table containing card info -- @return if unsuccessfull : nil, error local function read14443a(dont_disconnect, no_rats) - local command, result, info, err, data + local command, result, info, err, data - command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = ISO14A_COMMAND.ISO14A_CONNECT } + command = Command:new{cmd = cmds.CMD_READER_ISO_14443a, arg1 = ISO14A_COMMAND.ISO14A_CONNECT } - if dont_disconnect then - command.arg1 = command.arg1 + ISO14A_COMMAND.ISO14A_NO_DISCONNECT - end - if no_rats then - command.arg1 = command.arg1 + ISO14A_COMMAND.ISO14A_NO_RATS - end - - local result,err = sendToDevice(command) - if result then - local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result) - if arg0 == 0 then - return nil, "iso14443a card select failed" - end - data = string.sub(result,count) - info, err = parse14443a(data) - else - err ="No response from card" - end + if dont_disconnect then + command.arg1 = command.arg1 + ISO14A_COMMAND.ISO14A_NO_DISCONNECT + end + if no_rats then + command.arg1 = command.arg1 + ISO14A_COMMAND.ISO14A_NO_RATS + end - if err then - print(err) - return nil, err - end - return info + local result,err = sendToDevice(command) + if result then + local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result) + if arg0 == 0 then + return nil, "iso14443a card select failed" + end + data = string.sub(result,count) + info, err = parse14443a(data) + else + err ="No response from card" + end + + if err then + print(err) + return nil, err + end + return info end --- @@ -131,20 +131,20 @@ end -- @return if successfull: an table containing card info -- @return if unsuccessfull : nil, error local function waitFor14443a() - print("Waiting for card... press any key to quit") - while not core.ukbhit() do - res, err = read14443a() - if res then return res end - -- err means that there was no response from card - end - return nil, "Aborted by user" + print("Waiting for card... press any key to quit") + while not core.ukbhit() do + res, err = read14443a() + if res then return res end + -- err means that there was no response from card + end + return nil, "Aborted by user" end local library = { - read = read14443a, - waitFor14443a = waitFor14443a, - parse14443a = parse14443a, - sendToDevice = sendToDevice, - ISO14A_COMMAND = ISO14A_COMMAND, + read = read14443a, + waitFor14443a = waitFor14443a, + parse14443a = parse14443a, + sendToDevice = sendToDevice, + ISO14A_COMMAND = ISO14A_COMMAND, } return library diff --git a/client/lualibs/read14b.lua b/client/lualibs/read14b.lua index b92fb0b3b..3711c02a3 100644 --- a/client/lualibs/read14b.lua +++ b/client/lualibs/read14b.lua @@ -1,13 +1,13 @@ --[[ - This is a library to read 14443b tags. It can be used something like this + This is a library to read 14443b tags. It can be used something like this - local reader = require('read14b') - result, err = reader.select1443b() - if not result then - print(err) - return - end - print(result.name) + local reader = require('read14b') + result, err = reader.select1443b() + if not result then + print(err) + return + end + print(result.name) --]] -- Loads the commands-library @@ -15,68 +15,68 @@ local cmds = require('commands') local utils = require('utils') local TIMEOUT = 2500 local ISO14B_COMMAND = { - ISO14B_CONNECT = 1, - ISO14B_DISCONNECT = 2, - ISO14B_APDU = 4, - ISO14B_RAW = 8, - ISO14B_REQUEST_TRIGGER = 0x10, - ISO14B_APPEND_CRC = 0x20, - ISO14B_SELECT_STD = 0x40, - ISO14B_SELECT_SR = 0x80, + ISO14B_CONNECT = 1, + ISO14B_DISCONNECT = 2, + ISO14B_APDU = 4, + ISO14B_RAW = 8, + ISO14B_REQUEST_TRIGGER = 0x10, + ISO14B_APPEND_CRC = 0x20, + ISO14B_SELECT_STD = 0x40, + ISO14B_SELECT_SR = 0x80, } local function parse1443b(data) - --[[ - - Based on this struct : - - typedef struct { - byte_t uid[10]; - byte_t uidlen; - byte_t atqb[7]; - byte_t chipid; - byte_t cid; - } __attribute__((__packed__)) iso14b_card_select_t; + --[[ - --]] - - local count, uid, uidlen, atqb, chipid, cid = bin.unpack('H10CH7CC',data) - uid = uid:sub(1, 2*uidlen) - return { uid = uid, uidlen = uidlen, atqb = atqb, chipid = chipid, cid = cid } + Based on this struct : + + typedef struct { + byte_t uid[10]; + byte_t uidlen; + byte_t atqb[7]; + byte_t chipid; + byte_t cid; + } __attribute__((__packed__)) iso14b_card_select_t; + + --]] + + local count, uid, uidlen, atqb, chipid, cid = bin.unpack('H10CH7CC',data) + uid = uid:sub(1, 2*uidlen) + return { uid = uid, uidlen = uidlen, atqb = atqb, chipid = chipid, cid = cid } end --- Sends a USBpacket to the device -- @param command - the usb packet to send --- @param ignoreresponse - if set to true, we don't read the device answer packet --- which is usually recipe for fail. If not sent, the host will wait 2s for a --- response of type CMD_ACK --- @return packet,nil if successfull --- nil, errormessage if unsuccessfull +-- @param ignoreresponse - if set to true, we don't read the device answer packet +-- which is usually recipe for fail. If not sent, the host will wait 2s for a +-- response of type CMD_ACK +-- @return packet,nil if successfull +-- nil, errormessage if unsuccessfull local function sendToDevice(cmd, ignoreresponse) - --core.clearCommandBuffer() - local bytes = cmd:getBytes() - local count,c,arg0,arg1,arg2 = bin.unpack('LLLL',bytes) - local err = core.SendCommand(cmd:getBytes()) - if err then - print('ERROR',err) - return nil, err - end - if ignoreresponse then return nil,nil end - - local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) - return response,nil + --core.clearCommandBuffer() + local bytes = cmd:getBytes() + local count,c,arg0,arg1,arg2 = bin.unpack('LLLL',bytes) + local err = core.SendCommand(cmd:getBytes()) + if err then + print('ERROR',err) + return nil, err + end + if ignoreresponse then return nil,nil end + + local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) + return response,nil end --- Picks out and displays the data read from a tag -- Specifically, takes a usb packet, converts to a Command --- (as in commands.lua), takes the data-array and +-- (as in commands.lua), takes the data-array and -- reads the number of bytes specified in arg1 (arg0 in c-struct) -- and displays the data -- @param usbpacket the data received from the device local function showData(usbpacket) - local response = Command.parse(usbpacket) - local len = response.arg2 * 2 - local data = string.sub(response.data, 0, len); - print("<< ",data) + local response = Command.parse(usbpacket) + local len = response.arg2 * 2 + local data = string.sub(response.data, 0, len); + print("<< ",data) end @@ -85,74 +85,74 @@ end -- @return if unsuccessfull : nil, error local function read14443b(disconnect) - local command, result, info, err, data + local command, result, info, err, data - local flags = ISO14B_COMMAND.ISO14B_CONNECT + - ISO14B_COMMAND.ISO14B_SELECT_STD - - if disconnect then - print('DISCONNECT') - flags = flags + ISO14B_COMMAND.ISO14B_DISCONNECT - end + local flags = ISO14B_COMMAND.ISO14B_CONNECT + + ISO14B_COMMAND.ISO14B_SELECT_STD - command = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags} - local result, err = sendToDevice(command, false) - if result then - local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result) - if arg0 == 0 then - data = string.sub(result, count) - info, err = parse1443b(data) - else - err = "iso14443b card select failed" - end - else - err = "No response from card" - end + if disconnect then + print('DISCONNECT') + flags = flags + ISO14B_COMMAND.ISO14B_DISCONNECT + end - if err then - print(err) - return nil, err - end - return info + command = Command:new{cmd = cmds.CMD_ISO_14443B_COMMAND, arg1 = flags} + local result, err = sendToDevice(command, false) + if result then + local count,cmd,arg0,arg1,arg2 = bin.unpack('LLLL',result) + if arg0 == 0 then + data = string.sub(result, count) + info, err = parse1443b(data) + else + err = "iso14443b card select failed" + end + else + err = "No response from card" + end + + if err then + print(err) + return nil, err + end + return info end --PING / PONG - Custom Anticollison for Navigo. -- AA / BB ?!? -- local ping = ('BA00') -- result, err = sendRaw(ping, 1, 1) -- if result then - -- resp = Command.parse( result ) - -- if arg1 == 0 then - -- return nil, "iso14443b card - PING/PONG failed" - -- end - -- showData(result) + -- resp = Command.parse( result ) + -- if arg1 == 0 then + -- return nil, "iso14443b card - PING/PONG failed" + -- end + -- showData(result) -- else - -- err = "No response from card" - -- print(err) - -- return nil, err + -- err = "No response from card" + -- print(err) + -- return nil, err -- end --- --- Waits for a mifare card to be placed within the vicinity of the reader. +-- Waits for a mifare card to be placed within the vicinity of the reader. -- @return if successfull: an table containing card info -- @return if unsuccessfull : nil, error local function waitFor14443b() - print("Waiting for card... press any key to quit") - while not core.ukbhit() do - res, err = read14443b(false) - if res then return res end - -- err means that there was no response from card - end - return nil, "Aborted by user" + print("Waiting for card... press any key to quit") + while not core.ukbhit() do + res, err = read14443b(false) + if res then return res end + -- err means that there was no response from card + end + return nil, "Aborted by user" end local library = { - read = read14443b, - waitFor14443b = waitFor14443b, - parse1443b = parse1443b, - sendToDevice = sendToDevice, - showData = showData, - ISO14B_COMMAND = ISO14B_COMMAND, + read = read14443b, + waitFor14443b = waitFor14443b, + parse1443b = parse1443b, + sendToDevice = sendToDevice, + showData = showData, + ISO14B_COMMAND = ISO14B_COMMAND, } return library \ No newline at end of file diff --git a/client/lualibs/read15.lua b/client/lualibs/read15.lua index b0089b769..5d231ad52 100644 --- a/client/lualibs/read15.lua +++ b/client/lualibs/read15.lua @@ -1,13 +1,13 @@ --[[ - This is a library to read 15693 tags. It can be used something like this + This is a library to read 15693 tags. It can be used something like this - local reader = require('read15') - local info, err = reader.read() - if not info then - print(err) - return - end - print(info.UID) + local reader = require('read15') + local info, err = reader.read() + if not info then + print(err) + return + end + print(info.UID) --]] -- Loads the commands-library @@ -19,60 +19,60 @@ local TIMEOUT = 2000 -- Shouldn't take longer than 2 seconds --- Sends a USBpacket to the device -- @param command - the usb packet to send -- @param ignoreresponse - if set to true, we don't read the device answer packet --- which is usually recipe for fail. If not sent, the host will wait 2s for a --- response of type CMD_ACK --- @return packet,nil if successfull --- nil, errormessage if unsuccessfull +-- which is usually recipe for fail. If not sent, the host will wait 2s for a +-- response of type CMD_ACK +-- @return packet,nil if successfull +-- nil, errormessage if unsuccessfull local function sendToDevice(command, ignoreresponse) - local err = core.SendCommand(command:getBytes()) - if err then - print(err) - return nil, err - end - if ignoreresponse then return nil, nil end + local err = core.SendCommand(command:getBytes()) + if err then + print(err) + return nil, err + end + if ignoreresponse then return nil, nil end - local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) - return response, nil + local response = core.WaitForResponseTimeout(cmds.CMD_ACK, TIMEOUT) + return response, nil end local function errorString15693(number) - local errors = {} - errors[0x01] = "The command is not supported" - errors[0x02] = "The command is not recognised" - errors[0x03] = "The option is not supported." - errors[0x0f] = "Unknown error." - errors[0x10] = "The specified block is not available (doesn’t exist)." - errors[0x11] = "The specified block is already -locked and thus cannot be locked again" - errors[0x12] = "The specified block is locked and its content cannot be changed." - errors[0x13] = "The specified block was not successfully programmed." - errors[0x14] = "The specified block was not successfully locked." - - return errors[number] or "Reserved for Future Use or Custom command error." + local errors = {} + errors[0x01] = "The command is not supported" + errors[0x02] = "The command is not recognised" + errors[0x03] = "The option is not supported." + errors[0x0f] = "Unknown error." + errors[0x10] = "The specified block is not available (doesn’t exist)." + errors[0x11] = "The specified block is already -locked and thus cannot be locked again" + errors[0x12] = "The specified block is locked and its content cannot be changed." + errors[0x13] = "The specified block was not successfully programmed." + errors[0x14] = "The specified block was not successfully locked." + + return errors[number] or "Reserved for Future Use or Custom command error." end local function parse15693(data) - local bytes = utils.ConvertAsciiToBytes(data) - local tmp = utils.ConvertAsciiToHex(data) - - -- define ISO15_CRC_CHECK 0F47 - local crcStr = utils.Crc15(tmp, #tmp) + local bytes = utils.ConvertAsciiToBytes(data) + local tmp = utils.ConvertAsciiToHex(data) - if string.sub(crcStr, #crcStr - 3) ~= '470F' then - print("CRC", crc ) - return nil, "CRC failed" - end + -- define ISO15_CRC_CHECK 0F47 + local crcStr = utils.Crc15(tmp, #tmp) - if bytes[1] % 2 == 1 then - -- Above is a poor-mans bit check: - -- recv[0] & ISO15_RES_ERROR //(0x01) - local err = "Tag returned error %i: %s" - err = string.format(err, bytes[1], errorString15693(bytes[1])) - return nil, err - end - local uid = utils.ConvertBytesToHex( bytes, true ) - uid = uid:sub(5, #uid-4) - return { uid = uid, } + if string.sub(crcStr, #crcStr - 3) ~= '470F' then + print("CRC", crc ) + return nil, "CRC failed" + end + + if bytes[1] % 2 == 1 then + -- Above is a poor-mans bit check: + -- recv[0] & ISO15_RES_ERROR //(0x01) + local err = "Tag returned error %i: %s" + err = string.format(err, bytes[1], errorString15693(bytes[1])) + return nil, err + end + local uid = utils.ConvertBytesToHex( bytes, true ) + uid = uid:sub(5, #uid-4) + return { uid = uid, } end -- This function does a connect and retrieves som info @@ -83,62 +83,62 @@ local function read15693(slow, dont_readresponse) --[[ - We start by trying this command: - MANDATORY (present in ALL iso15693 tags) command (the example below is sent to a tag different from the above one): - - pm3> hf 15 info u - UID=E007C1A257394244 - Tag Info: Texas Instrument; Tag-it HF-I Standard; 8x32bit - pm3> - - From which we obtain less information than the above one. - - "260100" means - 0x26 - -- #define ISO15_REQ_SUBCARRIER_SINGLE 0x00 // Tag should respond using one subcarrier (ASK) - -- #define ISO15_REQ_DATARATE_HIGH 0x02 // Tag should respond using high data rate - -- #define ISO15_REQ_NONINVENTORY 0x00 - 0x01 - inventory - 0x00 - - --]] + We start by trying this command: + MANDATORY (present in ALL iso15693 tags) command (the example below is sent to a tag different from the above one): - local command, result, info, err, data + pm3> hf 15 info u + UID=E007C1A257394244 + Tag Info: Texas Instrument; Tag-it HF-I Standard; 8x32bit + pm3> - data = utils.Crc15("260100") + From which we obtain less information than the above one. - command = Command:new{cmd = cmds.CMD_ISO_15693_COMMAND, - arg1 = #data / 2, - arg2 = 1, - arg3 = 1, - data = data} - - if slow then - command.arg2 = 0 - end - if dont_readresponse then - command.arg3 = 0 - end - - local result, err = sendToDevice(command, dont_readresponse) - if not result then - print(err) - return nil, "15693 identify: no answer" - end - - local count, cmd, len, arg2, arg3 = bin.unpack('LLLL', result) - if len > 0 then - data = string.sub(result, count, count+len-1) - info, err = parse15693(data) - if err then - print(err) - return nil, err - end - return info - else - return nil, "Failed to get response" - end + "260100" means + 0x26 + -- #define ISO15_REQ_SUBCARRIER_SINGLE 0x00 // Tag should respond using one subcarrier (ASK) + -- #define ISO15_REQ_DATARATE_HIGH 0x02 // Tag should respond using high data rate + -- #define ISO15_REQ_NONINVENTORY 0x00 + 0x01 + inventory + 0x00 + + --]] + + local command, result, info, err, data + + data = utils.Crc15("260100") + + command = Command:new{cmd = cmds.CMD_ISO_15693_COMMAND, + arg1 = #data / 2, + arg2 = 1, + arg3 = 1, + data = data} + + if slow then + command.arg2 = 0 + end + if dont_readresponse then + command.arg3 = 0 + end + + local result, err = sendToDevice(command, dont_readresponse) + if not result then + print(err) + return nil, "15693 identify: no answer" + end + + local count, cmd, len, arg2, arg3 = bin.unpack('LLLL', result) + if len > 0 then + data = string.sub(result, count, count+len-1) + info, err = parse15693(data) + if err then + print(err) + return nil, err + end + return info + else + return nil, "Failed to get response" + end end --- @@ -146,19 +146,19 @@ end -- @return if successfull: an table containing card info -- @return if unsuccessfull : nil, error local function waitFor15693() - print("Waiting for card... press any key to quit") - while not core.ukbhit() do - res, err = read15693() - if res then return res end - -- err means that there was no response from card - end - return nil, "Aborted by user" + print("Waiting for card... press any key to quit") + while not core.ukbhit() do + res, err = read15693() + if res then return res end + -- err means that there was no response from card + end + return nil, "Aborted by user" end local library = { - read = read15693, - waitFor15693 = waitFor15693, - parse15693 = parse15693, - sendToDevice = sendToDevice, + read = read15693, + waitFor15693 = waitFor15693, + parse15693 = parse15693, + sendToDevice = sendToDevice, } return library diff --git a/client/lualibs/taglib.lua b/client/lualibs/taglib.lua index 97194714c..715a29487 100644 --- a/client/lualibs/taglib.lua +++ b/client/lualibs/taglib.lua @@ -109,16 +109,16 @@ m[0x6B]='ISSM France' m[0x6C]='Wisesec Ltd Israel' m[0x7C]='DB HiTek Co Ltd Korea' m[0x7D]='SATO Vicinity Australia' -m[0x7E]='Holtek Taiwan' +m[0x7E]='Holtek Taiwan' return { - lookupManufacturer = function (value) - if type(value) == 'string' then - local v = tonumber(value, 16) - print(string.format("WARNING: lookupManufacturer expects numeric value, converted %s into %x", value,v)) - value = v - end + lookupManufacturer = function (value) + if type(value) == 'string' then + local v = tonumber(value, 16) + print(string.format("WARNING: lookupManufacturer expects numeric value, converted %s into %x", value,v)) + value = v + end - return m[value] or "no tag-info available" - end, + return m[value] or "no tag-info available" + end, } \ No newline at end of file diff --git a/client/lualibs/utils.lua b/client/lualibs/utils.lua index ca49c21e9..697e48b72 100644 --- a/client/lualibs/utils.lua +++ b/client/lualibs/utils.lua @@ -1,430 +1,430 @@ ---[[ - This may be moved to a separate library at some point (Holiman) ---]] -local Utils = -{ - -- Asks the user for Yes or No - confirm = function(message, ...) - local answer - message = message .. " [y/n] ?" - repeat - io.write(message) - io.flush() - answer = io.read() - if answer == 'Y' or answer == "y" then - return true - elseif answer == 'N' or answer == 'n' then - return false - end - until false - end, - --- - -- Asks the user for input - input = function (message , default) - local answer - if default ~= nil then - message = message .. " (default: ".. default.. " )" - end - message = message .." \n > " - io.write(message) - io.flush() - answer = io.read() - if answer == '' then answer = default end - - return answer - end, - - ------------ FILE READING - ReadDumpFile = function (filename) - - filename = filename or 'dumpdata.bin' - if #filename == 0 then - return nil, 'Filename length is zero' - end - - infile = io.open(filename, "rb") - if infile == nil then - return nil, string.format("Could not read file %s",filename) - end - local t = infile:read("*all") - io.close(infile) - len = string.len(t) - local _,hex = bin.unpack(("H%d"):format(len),t) - return hex - end, - - ------------ FILE WRITING (EML) - --- Writes an eml-file. - -- @param uid - the uid of the tag. Used in filename - -- @param blockData. Assumed to be on the format {'\0\1\2\3,'\b\e\e\f' ..., - -- that is, blockData[row] contains a string with the actual data, not ascii hex representation - -- return filename if all went well, - -- @reurn nil, error message if unsuccessfulls - WriteDumpFile = function(uid, blockData) - local destination = string.format("%s.eml", uid) - local file = io.open(destination, "w") - if file == nil then - return nil, string.format("Could not write to file %s", destination) - end - local rowlen = string.len(blockData[1]) - - for i,block in ipairs(blockData) do - if rowlen ~= string.len(block) then - prlog(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i)) - end - - local formatString = string.format("H%d", string.len(block)) - local _,hex = bin.unpack(formatString,block) - file:write(hex.."\n") - end - file:close() - return destination - end, - - ------------ string split function - Split = function( inSplitPattern, outResults ) - if not outResults then - outResults = {} - end - local start = 1 - local splitStart, splitEnd = string.find( self, inSplitPattern, start ) - while splitStart do - table.insert( outResults, string.sub( self, start, splitStart-1 ) ) - start = splitEnd + 1 - splitStart, splitEnd = string.find( self, inSplitPattern, start ) - end - table.insert( outResults, string.sub( self, start ) ) - return outResults - end, - - ----ISO14443-B CRC - Crc14b = function(s) - if s == nil then return nil end - if #s == 0 then return nil end - if type(s) == 'string' then - local utils = require('utils') - return utils.ConvertAsciiToHex( - core.iso14443b_crc(s) - ) - end - return nil - end, - ----ISO15693 CRC - Crc15 = function(s) - if s == nil then return nil end - if #s == 0 then return nil end - if type(s) == 'string' then - local utils = require('utils') - return utils.ConvertAsciiToHex( - core.iso15693_crc(s) - ) - end - return nil - end, - - ------------ CRC-8 Legic checksums - -- Takes a hex string and calculates a crc8 - Crc8Legic = function(s) - if s == nil then return nil end - if #s == 0 then return nil end - if type(s) == 'string' then - local utils = require('utils') - local asc = utils.ConvertHexToAscii(s) - local hash = core.crc8legic(asc) - return hash - end - return nil - end, - - ------------ CRC-16 ccitt checksums - -- Takes a hex string and calculates a crc16 - Crc16 = function(s) - if s == nil then return nil end - if #s == 0 then return nil end - if type(s) == 'string' then - local utils = require('utils') - local asc = utils.ConvertHexToAscii(s) - local hash = core.crc16(asc) - return hash - end - return nil - end, - - - ------------ CRC-64 ecma checksums - -- Takes a hex string and calculates a crc64 ecma hash - Crc64 = function(s) - if s == nil then return nil end - if #s == 0 then return nil end - if type(s) == 'string' then - local utils = require('utils') - local asc = utils.ConvertHexToAscii(s) - local hash = core.crc64(asc) - return hash - end - return nil - end, - ------------ CRC-64 ecma 182 checksums - -- Takes a hex string and calculates a crc64 ecma182 hash - Crc64_ecma182 = function(s) - if s == nil then return nil end - if #s == 0 then return nil end - if type(s) == 'string' then - local utils = require('utils') - local asc = utils.ConvertHexToAscii(s) - local hash = core.crc64_ecma182(asc) - return hash - end - return nil - end, - - ------------ SHA1 hash - -- Takes a string and calculates a SHA1 hash - Sha1 = function(s) - if s == nil then return nil end - if #s == 0 then return nil end - if type(s) == 'string' then - return core.sha1(s) - end - return nil - end, - -- Takes a hex string and calculates a SHA1 hash - Sha1Hex = function(s) - if s == nil then return nil end - if #s == 0 then return nil end - if type(s) == 'string' then - local utils = require('utils') - local asc = utils.ConvertHexToAscii(s) - local hash = core.sha1(asc) - return hash - end - return nil - end, - - - -- input parameter is a string - -- Swaps the endianess and returns a number, - -- IE: 'cd7a' -> '7acd' -> 0x7acd - SwapEndianness = function(s, len) - if s == nil then return nil end - if #s == 0 then return '' end - if type(s) ~= 'string' then return nil end - - local retval = 0 - if len == 16 then - local t = s:sub(3,4)..s:sub(1,2) - retval = tonumber(t,16) - elseif len == 24 then - local t = s:sub(5,6)..s:sub(3,4)..s:sub(1,2) - retval = tonumber(t,16) - elseif len == 32 then - local t = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2) - retval = tonumber(t,16) - end - return retval - end, - - -- input parameter is a string - -- Swaps the endianess and returns a string, - -- IE: 'cd7a' -> '7acd' -> 0x7acd - SwapEndiannessStr = function(s, len) - if s == nil then return nil end - if #s == 0 then return '' end - if type(s) ~= 'string' then return nil end - - local retval - if len == 16 then - retval = s:sub(3,4)..s:sub(1,2) - elseif len == 24 then - retval = s:sub(5,6)..s:sub(3,4)..s:sub(1,2) - elseif len == 32 then - retval = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2) - end - return retval - end, - ------------ CONVERSIONS - - -- - -- Converts DECIMAL to HEX - ConvertDecToHex = function(IN) - local B,K,OUT,I,D = 16, "0123456789ABCDEF", "", 0 - while IN > 0 do - I = I+1 - IN, D = math.floor(IN/B), math.modf(IN, B) + 1 - OUT = string.sub(K, D, D)..OUT - end - return OUT - end, - --- - -- Convert Byte array to string of hex - ConvertBytesToHex = function(bytes, reverse) - if bytes == nil then return '' end - if #bytes == 0 then return '' end - local s={} - if reverse then - local j=1 - for i = #bytes, 1, -1 do - s[i] = string.format("%02X", bytes[j]) - j = j + 1 - end - else - for i = 1, #bytes do - s[i] = string.format("%02X", bytes[i]) - end - end - return table.concat(s) - end, - -- Convert byte array to string with ascii - ConvertBytesToAscii = function(bytes) - if bytes == nil then return '' end - if #bytes == 0 then return '' end - local s={} - for i = 1, #(bytes) do - s[i] = string.char(bytes[i]) - end - return table.concat(s) - end, - ConvertHexToBytes = function(s) - local t={} - if s == nil then return t end - if #s == 0 then return t end - for k in s:gmatch"(%x%x)" do - table.insert(t,tonumber(k,16)) - end - return t - end, - ConvertAsciiToBytes = function(s, reverse) - local t = {} - if s == nil then return t end - if #s == 0 then return t end - - for k in s:gmatch"(.)" do - table.insert(t, string.byte(k)) - end - - if not reverse then - return t - end - - local rev = {} - if reverse then - for i = #t, 1,-1 do - table.insert(rev, t[i] ) - end - end - return rev - end, - - ConvertHexToAscii = function(s, useSafechars) - if s == nil then return '' end - if #s == 0 then return '' end - local t={} - for k in s:gmatch"(%x%x)" do - - local n = tonumber(k,16) - local c - if useSafechars and ( (n < 32) or (n == 127) ) then - c = '.'; - else - c = string.char(n) - end - table.insert(t,c) - end - return table.concat(t) - end, - - ConvertAsciiToHex = function(s) - if s == nil then return '' end - if #s == 0 then return '' end - local t={} - for k in s:gmatch"(.)" do - table.insert(t, string.format("%02X", string.byte(k))) - end - return table.concat(t) - end, - - hexlify = function(s) - local u = require('utils') - return u.ConvertAsciiToHex(s) - end, - - Chars2num = function(s) - return (s:byte(1)*16777216)+(s:byte(2)*65536)+(s:byte(3)*256)+(s:byte(4)) - end, - - -- use length of string to determine 8,16,32,64 bits - bytes_to_int = function(str,endian,signed) - local t = {str:byte(1, -1)} - if endian == "big" then --reverse bytes - local tt = {} - for k = 1, #t do - tt[#t-k+1] = t[k] - end - t = tt - end - local n = 0 - for k = 1, #t do - n = n + t[k] * 2^((k-1) * 8) - end - if signed then - n = (n > 2^(#t*8-1) -1) and (n - 2^(#t*8)) or n -- if last bit set, negative. - end - return n - end, - - -- a simple implementation of a sleep command. Thanks to Mosci - -- takes number of seconds to sleep - Sleep = function(n) - local clock = os.clock - local t0 = clock() - while clock() - t0 <= n do end - return nil - end, - - -- function convertStringToBytes(str) - -- local bytes = {} - -- local strLength = string.len(str) - -- for i=1,strLength do - -- table.insert(bytes, string.byte(str, i)) - -- end - - -- return bytes --- end - --- function convertBytesToString(bytes) - -- local bytesLength = table.getn(bytes) - -- local str = "" - -- for i=1,bytesLength do - -- str = str .. string.char(bytes[i]) - -- end - - -- return str --- end - --- function convertHexStringToBytes(str) - -- local bytes = {} - -- local strLength = string.len(str) - -- for k=2,strLength,2 do - -- local hexString = "0x" .. string.sub(str, (k - 1), k) - -- table.insert(bytes, hex.to_dec(hexString)) - -- end - - -- return bytes --- end - --- function convertBytesToHexString(bytes) - -- local str = "" - -- local bytesLength = table.getn(bytes) - -- for i=1,bytesLength do - -- local hexString = string.sub(hex.to_hex(bytes[i]), 3) - -- if string.len(hexString) == 1 then - -- hexString = "0" .. hexString - -- end - -- str = str .. hexString - -- end - - -- return str --- end - -} +--[[ + This may be moved to a separate library at some point (Holiman) +--]] +local Utils = +{ + -- Asks the user for Yes or No + confirm = function(message, ...) + local answer + message = message .. " [y/n] ?" + repeat + io.write(message) + io.flush() + answer = io.read() + if answer == 'Y' or answer == "y" then + return true + elseif answer == 'N' or answer == 'n' then + return false + end + until false + end, + --- + -- Asks the user for input + input = function (message , default) + local answer + if default ~= nil then + message = message .. " (default: ".. default.. " )" + end + message = message .." \n > " + io.write(message) + io.flush() + answer = io.read() + if answer == '' then answer = default end + + return answer + end, + + ------------ FILE READING + ReadDumpFile = function (filename) + + filename = filename or 'dumpdata.bin' + if #filename == 0 then + return nil, 'Filename length is zero' + end + + infile = io.open(filename, "rb") + if infile == nil then + return nil, string.format("Could not read file %s",filename) + end + local t = infile:read("*all") + io.close(infile) + len = string.len(t) + local _,hex = bin.unpack(("H%d"):format(len),t) + return hex + end, + + ------------ FILE WRITING (EML) + --- Writes an eml-file. + -- @param uid - the uid of the tag. Used in filename + -- @param blockData. Assumed to be on the format {'\0\1\2\3,'\b\e\e\f' ..., + -- that is, blockData[row] contains a string with the actual data, not ascii hex representation + -- return filename if all went well, + -- @reurn nil, error message if unsuccessfulls + WriteDumpFile = function(uid, blockData) + local destination = string.format("%s.eml", uid) + local file = io.open(destination, "w") + if file == nil then + return nil, string.format("Could not write to file %s", destination) + end + local rowlen = string.len(blockData[1]) + + for i,block in ipairs(blockData) do + if rowlen ~= string.len(block) then + prlog(string.format("WARNING: Dumpdata seems corrupted, line %d was not the same length as line 1",i)) + end + + local formatString = string.format("H%d", string.len(block)) + local _,hex = bin.unpack(formatString,block) + file:write(hex.."\n") + end + file:close() + return destination + end, + + ------------ string split function + Split = function( inSplitPattern, outResults ) + if not outResults then + outResults = {} + end + local start = 1 + local splitStart, splitEnd = string.find( self, inSplitPattern, start ) + while splitStart do + table.insert( outResults, string.sub( self, start, splitStart-1 ) ) + start = splitEnd + 1 + splitStart, splitEnd = string.find( self, inSplitPattern, start ) + end + table.insert( outResults, string.sub( self, start ) ) + return outResults + end, + + ----ISO14443-B CRC + Crc14b = function(s) + if s == nil then return nil end + if #s == 0 then return nil end + if type(s) == 'string' then + local utils = require('utils') + return utils.ConvertAsciiToHex( + core.iso14443b_crc(s) + ) + end + return nil + end, + ----ISO15693 CRC + Crc15 = function(s) + if s == nil then return nil end + if #s == 0 then return nil end + if type(s) == 'string' then + local utils = require('utils') + return utils.ConvertAsciiToHex( + core.iso15693_crc(s) + ) + end + return nil + end, + + ------------ CRC-8 Legic checksums + -- Takes a hex string and calculates a crc8 + Crc8Legic = function(s) + if s == nil then return nil end + if #s == 0 then return nil end + if type(s) == 'string' then + local utils = require('utils') + local asc = utils.ConvertHexToAscii(s) + local hash = core.crc8legic(asc) + return hash + end + return nil + end, + + ------------ CRC-16 ccitt checksums + -- Takes a hex string and calculates a crc16 + Crc16 = function(s) + if s == nil then return nil end + if #s == 0 then return nil end + if type(s) == 'string' then + local utils = require('utils') + local asc = utils.ConvertHexToAscii(s) + local hash = core.crc16(asc) + return hash + end + return nil + end, + + + ------------ CRC-64 ecma checksums + -- Takes a hex string and calculates a crc64 ecma hash + Crc64 = function(s) + if s == nil then return nil end + if #s == 0 then return nil end + if type(s) == 'string' then + local utils = require('utils') + local asc = utils.ConvertHexToAscii(s) + local hash = core.crc64(asc) + return hash + end + return nil + end, + ------------ CRC-64 ecma 182 checksums + -- Takes a hex string and calculates a crc64 ecma182 hash + Crc64_ecma182 = function(s) + if s == nil then return nil end + if #s == 0 then return nil end + if type(s) == 'string' then + local utils = require('utils') + local asc = utils.ConvertHexToAscii(s) + local hash = core.crc64_ecma182(asc) + return hash + end + return nil + end, + + ------------ SHA1 hash + -- Takes a string and calculates a SHA1 hash + Sha1 = function(s) + if s == nil then return nil end + if #s == 0 then return nil end + if type(s) == 'string' then + return core.sha1(s) + end + return nil + end, + -- Takes a hex string and calculates a SHA1 hash + Sha1Hex = function(s) + if s == nil then return nil end + if #s == 0 then return nil end + if type(s) == 'string' then + local utils = require('utils') + local asc = utils.ConvertHexToAscii(s) + local hash = core.sha1(asc) + return hash + end + return nil + end, + + + -- input parameter is a string + -- Swaps the endianess and returns a number, + -- IE: 'cd7a' -> '7acd' -> 0x7acd + SwapEndianness = function(s, len) + if s == nil then return nil end + if #s == 0 then return '' end + if type(s) ~= 'string' then return nil end + + local retval = 0 + if len == 16 then + local t = s:sub(3,4)..s:sub(1,2) + retval = tonumber(t,16) + elseif len == 24 then + local t = s:sub(5,6)..s:sub(3,4)..s:sub(1,2) + retval = tonumber(t,16) + elseif len == 32 then + local t = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2) + retval = tonumber(t,16) + end + return retval + end, + + -- input parameter is a string + -- Swaps the endianess and returns a string, + -- IE: 'cd7a' -> '7acd' -> 0x7acd + SwapEndiannessStr = function(s, len) + if s == nil then return nil end + if #s == 0 then return '' end + if type(s) ~= 'string' then return nil end + + local retval + if len == 16 then + retval = s:sub(3,4)..s:sub(1,2) + elseif len == 24 then + retval = s:sub(5,6)..s:sub(3,4)..s:sub(1,2) + elseif len == 32 then + retval = s:sub(7,8)..s:sub(5,6)..s:sub(3,4)..s:sub(1,2) + end + return retval + end, + ------------ CONVERSIONS + + -- + -- Converts DECIMAL to HEX + ConvertDecToHex = function(IN) + local B,K,OUT,I,D = 16, "0123456789ABCDEF", "", 0 + while IN > 0 do + I = I+1 + IN, D = math.floor(IN/B), math.modf(IN, B) + 1 + OUT = string.sub(K, D, D)..OUT + end + return OUT + end, + --- + -- Convert Byte array to string of hex + ConvertBytesToHex = function(bytes, reverse) + if bytes == nil then return '' end + if #bytes == 0 then return '' end + local s={} + if reverse then + local j=1 + for i = #bytes, 1, -1 do + s[i] = string.format("%02X", bytes[j]) + j = j + 1 + end + else + for i = 1, #bytes do + s[i] = string.format("%02X", bytes[i]) + end + end + return table.concat(s) + end, + -- Convert byte array to string with ascii + ConvertBytesToAscii = function(bytes) + if bytes == nil then return '' end + if #bytes == 0 then return '' end + local s={} + for i = 1, #(bytes) do + s[i] = string.char(bytes[i]) + end + return table.concat(s) + end, + ConvertHexToBytes = function(s) + local t={} + if s == nil then return t end + if #s == 0 then return t end + for k in s:gmatch"(%x%x)" do + table.insert(t,tonumber(k,16)) + end + return t + end, + ConvertAsciiToBytes = function(s, reverse) + local t = {} + if s == nil then return t end + if #s == 0 then return t end + + for k in s:gmatch"(.)" do + table.insert(t, string.byte(k)) + end + + if not reverse then + return t + end + + local rev = {} + if reverse then + for i = #t, 1,-1 do + table.insert(rev, t[i] ) + end + end + return rev + end, + + ConvertHexToAscii = function(s, useSafechars) + if s == nil then return '' end + if #s == 0 then return '' end + local t={} + for k in s:gmatch"(%x%x)" do + + local n = tonumber(k,16) + local c + if useSafechars and ( (n < 32) or (n == 127) ) then + c = '.'; + else + c = string.char(n) + end + table.insert(t,c) + end + return table.concat(t) + end, + + ConvertAsciiToHex = function(s) + if s == nil then return '' end + if #s == 0 then return '' end + local t={} + for k in s:gmatch"(.)" do + table.insert(t, string.format("%02X", string.byte(k))) + end + return table.concat(t) + end, + + hexlify = function(s) + local u = require('utils') + return u.ConvertAsciiToHex(s) + end, + + Chars2num = function(s) + return (s:byte(1)*16777216)+(s:byte(2)*65536)+(s:byte(3)*256)+(s:byte(4)) + end, + + -- use length of string to determine 8,16,32,64 bits + bytes_to_int = function(str,endian,signed) + local t = {str:byte(1, -1)} + if endian == "big" then --reverse bytes + local tt = {} + for k = 1, #t do + tt[#t-k+1] = t[k] + end + t = tt + end + local n = 0 + for k = 1, #t do + n = n + t[k] * 2^((k-1) * 8) + end + if signed then + n = (n > 2^(#t*8-1) -1) and (n - 2^(#t*8)) or n -- if last bit set, negative. + end + return n + end, + + -- a simple implementation of a sleep command. Thanks to Mosci + -- takes number of seconds to sleep + Sleep = function(n) + local clock = os.clock + local t0 = clock() + while clock() - t0 <= n do end + return nil + end, + + -- function convertStringToBytes(str) + -- local bytes = {} + -- local strLength = string.len(str) + -- for i=1,strLength do + -- table.insert(bytes, string.byte(str, i)) + -- end + + -- return bytes +-- end + +-- function convertBytesToString(bytes) + -- local bytesLength = table.getn(bytes) + -- local str = "" + -- for i=1,bytesLength do + -- str = str .. string.char(bytes[i]) + -- end + + -- return str +-- end + +-- function convertHexStringToBytes(str) + -- local bytes = {} + -- local strLength = string.len(str) + -- for k=2,strLength,2 do + -- local hexString = "0x" .. string.sub(str, (k - 1), k) + -- table.insert(bytes, hex.to_dec(hexString)) + -- end + + -- return bytes +-- end + +-- function convertBytesToHexString(bytes) + -- local str = "" + -- local bytesLength = table.getn(bytes) + -- for i=1,bytesLength do + -- local hexString = string.sub(hex.to_hex(bytes[i]), 3) + -- if string.len(hexString) == 1 then + -- hexString = "0" .. hexString + -- end + -- str = str .. hexString + -- end + + -- return str +-- end + +} return Utils \ No newline at end of file From 248a861613b8d2206dac358a2878b4fee87ba97c Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 10:42:03 +0100 Subject: [PATCH 0685/1938] bootrom: fix mix of spaces & tabs --- bootrom/bootrom.c | 412 ++++++++++++++++++++--------------------- bootrom/flash-reset.s | 50 ++--- bootrom/ldscript-flash | 74 ++++---- bootrom/ram-reset.s | 6 +- 4 files changed, 271 insertions(+), 271 deletions(-) diff --git a/bootrom/bootrom.c b/bootrom/bootrom.c index c037da122..fda79f905 100644 --- a/bootrom/bootrom.c +++ b/bootrom/bootrom.c @@ -16,11 +16,11 @@ extern char _bootrom_start, _bootrom_end, _flash_start, _flash_end; extern uint32_t _osimage_entry; void DbpString(char *str) { - byte_t len = 0; - while (str[len] != 0x00) - len++; + byte_t len = 0; + while (str[len] != 0x00) + len++; - cmd_send(CMD_DEBUG_PRINT_STRING, len, 0, 0, (byte_t*)str, len); + cmd_send(CMD_DEBUG_PRINT_STRING, len, 0, 0, (byte_t*)str, len); } static void ConfigClocks(void) { @@ -30,54 +30,54 @@ static void ConfigClocks(void) { // enable system clock and USB clock AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_PCK | AT91C_PMC_UDP; - // enable the clock to the following peripherals + // enable the clock to the following peripherals AT91C_BASE_PMC->PMC_PCER = - (1<PMC_MOR = AT91C_CKGR_MOSCEN | PMC_MAIN_OSC_STARTUP_DELAY(8); - // wait for main oscillator to stabilize - while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS) ) {}; + // wait for main oscillator to stabilize + while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MOSCS) ) {}; // PLL output clock frequency in range 80 - 160 MHz needs CKGR_PLL = 00 // PLL output clock frequency in range 150 - 180 MHz needs CKGR_PLL = 10 // PLL output is MAINCK * multiplier / divisor = 16Mhz * 12 / 2 = 96Mhz AT91C_BASE_PMC->PMC_PLLR = - PMC_PLL_DIVISOR(2) | - //PMC_PLL_COUNT_BEFORE_LOCK(0x10) | - PMC_PLL_COUNT_BEFORE_LOCK(0x3F) | - PMC_PLL_FREQUENCY_RANGE(0) | - PMC_PLL_MULTIPLIER(12) | - PMC_PLL_USB_DIVISOR(1); + PMC_PLL_DIVISOR(2) | + //PMC_PLL_COUNT_BEFORE_LOCK(0x10) | + PMC_PLL_COUNT_BEFORE_LOCK(0x3F) | + PMC_PLL_FREQUENCY_RANGE(0) | + PMC_PLL_MULTIPLIER(12) | + PMC_PLL_USB_DIVISOR(1); - // wait for PLL to lock - while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK) ) {}; + // wait for PLL to lock + while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_LOCK) ) {}; - // we want a master clock (MCK) to be PLL clock / 2 = 96Mhz / 2 = 48Mhz - // datasheet recommends that this register is programmed in two operations - // when changing to PLL, program the prescaler first then the source + // we want a master clock (MCK) to be PLL clock / 2 = 96Mhz / 2 = 48Mhz + // datasheet recommends that this register is programmed in two operations + // when changing to PLL, program the prescaler first then the source AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2; - // wait for main clock ready signal - while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) ) {}; + // wait for main clock ready signal + while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) ) {}; - // set the source to PLL + // set the source to PLL AT91C_BASE_PMC->PMC_MCKR = AT91C_PMC_PRES_CLK_2 | AT91C_PMC_CSS_PLL_CLK; - // wait for main clock ready signal - while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) ) {}; + // wait for main clock ready signal + while ( !(AT91C_BASE_PMC->PMC_SR & AT91C_PMC_MCKRDY) ) {}; } static void Fatal(void) { @@ -85,140 +85,140 @@ static void Fatal(void) { } void UsbPacketReceived(uint8_t *packet, int len) { - int i, dont_ack = 0; - UsbCommand* c = (UsbCommand *)packet; - volatile uint32_t *p; + int i, dont_ack = 0; + UsbCommand* c = (UsbCommand *)packet; + volatile uint32_t *p; - //if ( len != sizeof(UsbCommand)) Fatal(); + //if ( len != sizeof(UsbCommand)) Fatal(); - uint32_t arg0 = (uint32_t)c->arg[0]; + uint32_t arg0 = (uint32_t)c->arg[0]; - switch(c->cmd) { - case CMD_DEVICE_INFO: { - dont_ack = 1; - arg0 = DEVICE_INFO_FLAG_BOOTROM_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM | - DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH; - if(common_area.flags.osimage_present) - arg0 |= DEVICE_INFO_FLAG_OSIMAGE_PRESENT; + switch(c->cmd) { + case CMD_DEVICE_INFO: { + dont_ack = 1; + arg0 = DEVICE_INFO_FLAG_BOOTROM_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM | + DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH; + if(common_area.flags.osimage_present) + arg0 |= DEVICE_INFO_FLAG_OSIMAGE_PRESENT; - cmd_send(CMD_DEVICE_INFO,arg0,1,2,0,0); - } break; + cmd_send(CMD_DEVICE_INFO,arg0,1,2,0,0); + } break; - case CMD_SETUP_WRITE: { - /* The temporary write buffer of the embedded flash controller is mapped to the - * whole memory region, only the last 8 bits are decoded. - */ - p = (volatile uint32_t *)&_flash_start; - for(i = 0; i < 12; i++) - p[i+arg0] = c->d.asDwords[i]; - } break; + case CMD_SETUP_WRITE: { + /* The temporary write buffer of the embedded flash controller is mapped to the + * whole memory region, only the last 8 bits are decoded. + */ + p = (volatile uint32_t *)&_flash_start; + for(i = 0; i < 12; i++) + p[i+arg0] = c->d.asDwords[i]; + } break; - case CMD_FINISH_WRITE: { - uint32_t* flash_mem = (uint32_t*)(&_flash_start); - for ( int j=0; j<2; j++) { - for(i = 0+(64*j); i < 64+(64*j); i++) { - flash_mem[i] = c->d.asDwords[i]; - } + case CMD_FINISH_WRITE: { + uint32_t* flash_mem = (uint32_t*)(&_flash_start); + for ( int j=0; j<2; j++) { + for(i = 0+(64*j); i < 64+(64*j); i++) { + flash_mem[i] = c->d.asDwords[i]; + } - uint32_t flash_address = arg0 + (0x100*j); + uint32_t flash_address = arg0 + (0x100*j); - /* Check that the address that we are supposed to write to is within our allowed region */ - if( ((flash_address + AT91C_IFLASH_PAGE_SIZE - 1) >= end_addr) || (flash_address < start_addr) ) { - /* Disallow write */ - dont_ack = 1; - cmd_send(CMD_NACK,0,0,0,0,0); - } else { - uint32_t page_n = (flash_address - ((uint32_t)flash_mem)) / AT91C_IFLASH_PAGE_SIZE; - /* Translate address to flash page and do flash, update here for the 512k part */ - AT91C_BASE_EFC0->EFC_FCR = MC_FLASH_COMMAND_KEY | - MC_FLASH_COMMAND_PAGEN(page_n) | - AT91C_MC_FCMD_START_PROG; - } + /* Check that the address that we are supposed to write to is within our allowed region */ + if( ((flash_address + AT91C_IFLASH_PAGE_SIZE - 1) >= end_addr) || (flash_address < start_addr) ) { + /* Disallow write */ + dont_ack = 1; + cmd_send(CMD_NACK,0,0,0,0,0); + } else { + uint32_t page_n = (flash_address - ((uint32_t)flash_mem)) / AT91C_IFLASH_PAGE_SIZE; + /* Translate address to flash page and do flash, update here for the 512k part */ + AT91C_BASE_EFC0->EFC_FCR = MC_FLASH_COMMAND_KEY | + MC_FLASH_COMMAND_PAGEN(page_n) | + AT91C_MC_FCMD_START_PROG; + } - // Wait until flashing of page finishes - uint32_t sr; - while(!((sr = AT91C_BASE_EFC0->EFC_FSR) & AT91C_MC_FRDY)); - if(sr & (AT91C_MC_LOCKE | AT91C_MC_PROGE)) { - dont_ack = 1; - cmd_send(CMD_NACK,sr,0,0,0,0); - } - } - } break; + // Wait until flashing of page finishes + uint32_t sr; + while(!((sr = AT91C_BASE_EFC0->EFC_FSR) & AT91C_MC_FRDY)); + if(sr & (AT91C_MC_LOCKE | AT91C_MC_PROGE)) { + dont_ack = 1; + cmd_send(CMD_NACK,sr,0,0,0,0); + } + } + } break; - case CMD_HARDWARE_RESET: { - usb_disable(); - AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; - } break; + case CMD_HARDWARE_RESET: { + usb_disable(); + AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; + } break; - case CMD_START_FLASH: { - if (c->arg[2] == START_FLASH_MAGIC) - bootrom_unlocked = 1; - else - bootrom_unlocked = 0; + case CMD_START_FLASH: { + if (c->arg[2] == START_FLASH_MAGIC) + bootrom_unlocked = 1; + else + bootrom_unlocked = 0; - int prot_start = (int)&_bootrom_start; - int prot_end = (int)&_bootrom_end; - int allow_start = (int)&_flash_start; - int allow_end = (int)&_flash_end; - int cmd_start = c->arg[0]; - int cmd_end = c->arg[1]; + int prot_start = (int)&_bootrom_start; + int prot_end = (int)&_bootrom_end; + int allow_start = (int)&_flash_start; + int allow_end = (int)&_flash_end; + int cmd_start = c->arg[0]; + int cmd_end = c->arg[1]; - /* Only allow command if the bootrom is unlocked, or the parameters are outside of the protected - * bootrom area. In any case they must be within the flash area. - */ - if( (bootrom_unlocked || ((cmd_start >= prot_end) || (cmd_end < prot_start))) && - (cmd_start >= allow_start) && - (cmd_end <= allow_end) ) { - start_addr = cmd_start; - end_addr = cmd_end; - } else { - start_addr = end_addr = 0; - dont_ack = 1; - cmd_send(CMD_NACK,0,0,0,0,0); - } - } break; + /* Only allow command if the bootrom is unlocked, or the parameters are outside of the protected + * bootrom area. In any case they must be within the flash area. + */ + if( (bootrom_unlocked || ((cmd_start >= prot_end) || (cmd_end < prot_start))) && + (cmd_start >= allow_start) && + (cmd_end <= allow_end) ) { + start_addr = cmd_start; + end_addr = cmd_end; + } else { + start_addr = end_addr = 0; + dont_ack = 1; + cmd_send(CMD_NACK,0,0,0,0,0); + } + } break; - default: { - Fatal(); - } break; - } + default: { + Fatal(); + } break; + } - if (!dont_ack) - cmd_send(CMD_ACK,arg0,0,0,0,0); + if (!dont_ack) + cmd_send(CMD_ACK,arg0,0,0,0,0); } static void flash_mode(int externally_entered) { - start_addr = 0; - end_addr = 0; - bootrom_unlocked = 0; - uint8_t rx[sizeof(UsbCommand)]; + start_addr = 0; + end_addr = 0; + bootrom_unlocked = 0; + uint8_t rx[sizeof(UsbCommand)]; - usb_enable(); + usb_enable(); - // wait for reset to be complete? - for (volatile size_t i=0; i<0x100000; i++) {}; + // wait for reset to be complete? + for (volatile size_t i=0; i<0x100000; i++) {}; - for(;;) { - WDT_HIT(); + for(;;) { + WDT_HIT(); - // Check if there is a usb packet available - if (usb_poll_validate_length()) { - if (usb_read(rx, sizeof(rx)) ) - UsbPacketReceived(rx, sizeof(rx)); - } + // Check if there is a usb packet available + if (usb_poll_validate_length()) { + if (usb_read(rx, sizeof(rx)) ) + UsbPacketReceived(rx, sizeof(rx)); + } - if (!externally_entered && !BUTTON_PRESS()) { - /* Perform a reset to leave flash mode */ - usb_disable(); - LED_B_ON(); - AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; - for(;;) {}; - } - if (externally_entered && BUTTON_PRESS()) { - /* Let the user's button press override the automatic leave */ - externally_entered = 0; - } - } + if (!externally_entered && !BUTTON_PRESS()) { + /* Perform a reset to leave flash mode */ + usb_disable(); + LED_B_ON(); + AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; + for(;;) {}; + } + if (externally_entered && BUTTON_PRESS()) { + /* Let the user's button press override the automatic leave */ + externally_entered = 0; + } + } } void BootROM(void) { @@ -229,54 +229,54 @@ void BootROM(void) { // Kill all the pullups, especially the one on USB D+; leave them for // the unused pins, though. AT91C_BASE_PIOA->PIO_PPUDR = - GPIO_USB_PU | - GPIO_LED_A | - GPIO_LED_B | - GPIO_LED_C | - GPIO_LED_D | - GPIO_FPGA_DIN | - GPIO_FPGA_DOUT | - GPIO_FPGA_CCLK | - GPIO_FPGA_NINIT | - GPIO_FPGA_NPROGRAM | - GPIO_FPGA_DONE | - GPIO_MUXSEL_HIPKD | - GPIO_MUXSEL_HIRAW | - GPIO_MUXSEL_LOPKD | - GPIO_MUXSEL_LORAW | - GPIO_RELAY | - GPIO_NVDD_ON; - // (and add GPIO_FPGA_ON) - // These pins are outputs + GPIO_USB_PU | + GPIO_LED_A | + GPIO_LED_B | + GPIO_LED_C | + GPIO_LED_D | + GPIO_FPGA_DIN | + GPIO_FPGA_DOUT | + GPIO_FPGA_CCLK | + GPIO_FPGA_NINIT | + GPIO_FPGA_NPROGRAM | + GPIO_FPGA_DONE | + GPIO_MUXSEL_HIPKD | + GPIO_MUXSEL_HIRAW | + GPIO_MUXSEL_LOPKD | + GPIO_MUXSEL_LORAW | + GPIO_RELAY | + GPIO_NVDD_ON; + // (and add GPIO_FPGA_ON) + // These pins are outputs AT91C_BASE_PIOA->PIO_OER = - GPIO_LED_A | - GPIO_LED_B | - GPIO_LED_C | - GPIO_LED_D | - GPIO_RELAY | - GPIO_NVDD_ON; - // PIO controls the following pins + GPIO_LED_A | + GPIO_LED_B | + GPIO_LED_C | + GPIO_LED_D | + GPIO_RELAY | + GPIO_NVDD_ON; + // PIO controls the following pins AT91C_BASE_PIOA->PIO_PER = - GPIO_USB_PU | - GPIO_LED_A | - GPIO_LED_B | - GPIO_LED_C | - GPIO_LED_D; + GPIO_USB_PU | + GPIO_LED_A | + GPIO_LED_B | + GPIO_LED_C | + GPIO_LED_D; - // USB_D_PLUS_PULLUP_OFF(); - usb_disable(); - LED_D_OFF(); - LED_C_ON(); - LED_B_OFF(); - LED_A_OFF(); + // USB_D_PLUS_PULLUP_OFF(); + usb_disable(); + LED_D_OFF(); + LED_C_ON(); + LED_B_OFF(); + LED_A_OFF(); - // Set the first 256kb memory flashspeed - AT91C_BASE_EFC0->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48); + // Set the first 256kb memory flashspeed + AT91C_BASE_EFC0->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48); - // 9 = 256, 10+ is 512kb - uint8_t id = ( *(AT91C_DBGU_CIDR) & 0xF00) >> 8; - if ( id > 9 ) - AT91C_BASE_EFC1->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48); + // 9 = 256, 10+ is 512kb + uint8_t id = ( *(AT91C_DBGU_CIDR) & 0xF00) >> 8; + if ( id > 9 ) + AT91C_BASE_EFC1->EFC_FMR = AT91C_MC_FWS_1FWS | MC_FLASH_MODE_MASTER_CLK_IN_MHZ(48); // Initialize all system clocks ConfigClocks(); @@ -288,36 +288,36 @@ void BootROM(void) { case AT91C_RSTC_RSTTYP_WATCHDOG: case AT91C_RSTC_RSTTYP_SOFTWARE: case AT91C_RSTC_RSTTYP_USER: - /* In these cases the common_area in RAM should be ok, retain it if it's there */ - if(common_area.magic == COMMON_AREA_MAGIC && common_area.version == 1) - common_area_present = 1; - break; + /* In these cases the common_area in RAM should be ok, retain it if it's there */ + if(common_area.magic == COMMON_AREA_MAGIC && common_area.version == 1) + common_area_present = 1; + break; default: /* Otherwise, initialize it from scratch */ - break; + break; } if (!common_area_present){ - /* Common area not ok, initialize it */ - int i; - /* Makeshift memset, no need to drag util.c into this */ - for(i=0; ibootphase1 :phase1 + . = LENGTH(bootphase1) - 0x4; + LONG(_version_information_start); + } >bootphase1 :phase1 - .bootphase2 : { - *(.startphase2) - *(.text) - *(.text.*) - *(.eh_frame) - *(.glue_7) - *(.glue_7t) - *(.rodata) - *(.rodata.*) - *(.data) - *(.data.*) - . = ALIGN(4); - } >ram AT>bootphase2 :phase2 + .bootphase2 : { + *(.startphase2) + *(.text) + *(.text.*) + *(.eh_frame) + *(.glue_7) + *(.glue_7t) + *(.rodata) + *(.rodata.*) + *(.data) + *(.data.*) + . = ALIGN(4); + } >ram AT>bootphase2 :phase2 - __bootphase2_src_start__ = LOADADDR(.bootphase2); - __bootphase2_start__ = ADDR(.bootphase2); - __bootphase2_end__ = __bootphase2_start__ + SIZEOF(.bootphase2); + __bootphase2_src_start__ = LOADADDR(.bootphase2); + __bootphase2_start__ = ADDR(.bootphase2); + __bootphase2_end__ = __bootphase2_start__ + SIZEOF(.bootphase2); - .bss : { - __bss_start__ = .; - *(.bss) - *(.bss.*) - . = ALIGN(4); - __bss_end__ = .; - } >ram AT>ram :bss + .bss : { + __bss_start__ = .; + *(.bss) + *(.bss.*) + . = ALIGN(4); + __bss_end__ = .; + } >ram AT>ram :bss - .commonarea (NOLOAD) : { - *(.commonarea) - } >commonarea + .commonarea (NOLOAD) : { + *(.commonarea) + } >commonarea } diff --git a/bootrom/ram-reset.s b/bootrom/ram-reset.s index ade70d8cc..ab57ee29a 100644 --- a/bootrom/ram-reset.s +++ b/bootrom/ram-reset.s @@ -14,7 +14,7 @@ .global ram_start ram_start: - ldr sp, =_stack_end - bl BootROM + ldr sp, =_stack_end + bl BootROM - .ltorg + .ltorg From e559a4a5afdaa105aeb5f3eca9dd7487417cff38 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 10:46:59 +0100 Subject: [PATCH 0686/1938] tools: fix mix of spaces & tabs --- tools/mfkey/crapto1.c | 712 ++++++++++++++++++------------------ tools/mfkey/crapto1.h | 58 +-- tools/mfkey/crypto1.c | 170 ++++----- tools/mfkey/mfkey32.c | 102 +++--- tools/mfkey/mfkey32v2.c | 112 +++--- tools/mfkey/mfkey64.c | 156 ++++---- tools/nonce2key/crapto1.c | 712 ++++++++++++++++++------------------ tools/nonce2key/crapto1.h | 50 +-- tools/nonce2key/crypto1.c | 170 ++++----- tools/nonce2key/nonce2key.c | 82 ++--- 10 files changed, 1162 insertions(+), 1162 deletions(-) diff --git a/tools/mfkey/crapto1.c b/tools/mfkey/crapto1.c index 9b2b58085..cfb07cea4 100755 --- a/tools/mfkey/crapto1.c +++ b/tools/mfkey/crapto1.c @@ -34,65 +34,65 @@ static void __attribute__((constructor)) fill_lut() typedef struct bucket { - uint32_t *head; - uint32_t *bp; + uint32_t *head; + uint32_t *bp; } bucket_t; typedef bucket_t bucket_array_t[2][0x100]; typedef struct bucket_info { - struct { - uint32_t *head, *tail; - } bucket_info[2][0x100]; - uint32_t numbuckets; - } bucket_info_t; + struct { + uint32_t *head, *tail; + } bucket_info[2][0x100]; + uint32_t numbuckets; + } bucket_info_t; static void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop, - uint32_t* const ostart, uint32_t* const ostop, - bucket_info_t *bucket_info, bucket_array_t bucket) + uint32_t* const ostart, uint32_t* const ostop, + bucket_info_t *bucket_info, bucket_array_t bucket) { - uint32_t *p1, *p2; - uint32_t *start[2]; - uint32_t *stop[2]; + uint32_t *p1, *p2; + uint32_t *start[2]; + uint32_t *stop[2]; - start[0] = estart; - stop[0] = estop; - start[1] = ostart; - stop[1] = ostop; + start[0] = estart; + stop[0] = estop; + start[1] = ostart; + stop[1] = ostop; - // init buckets to be empty - for (uint32_t i = 0; i < 2; i++) { - for (uint32_t j = 0x00; j <= 0xff; j++) { - bucket[i][j].bp = bucket[i][j].head; - } - } + // init buckets to be empty + for (uint32_t i = 0; i < 2; i++) { + for (uint32_t j = 0x00; j <= 0xff; j++) { + bucket[i][j].bp = bucket[i][j].head; + } + } - // sort the lists into the buckets based on the MSB (contribution bits) - for (uint32_t i = 0; i < 2; i++) { - for (p1 = start[i]; p1 <= stop[i]; p1++) { - uint32_t bucket_index = (*p1 & 0xff000000) >> 24; - *(bucket[i][bucket_index].bp++) = *p1; - } - } + // sort the lists into the buckets based on the MSB (contribution bits) + for (uint32_t i = 0; i < 2; i++) { + for (p1 = start[i]; p1 <= stop[i]; p1++) { + uint32_t bucket_index = (*p1 & 0xff000000) >> 24; + *(bucket[i][bucket_index].bp++) = *p1; + } + } - // write back intersecting buckets as sorted list. - // fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets. - uint32_t nonempty_bucket; - for (uint32_t i = 0; i < 2; i++) { - p1 = start[i]; - nonempty_bucket = 0; - for (uint32_t j = 0x00; j <= 0xff; j++) { - if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only - bucket_info->bucket_info[i][nonempty_bucket].head = p1; - for (p2 = bucket[i][j].head; p2 < bucket[i][j].bp; *p1++ = *p2++); - bucket_info->bucket_info[i][nonempty_bucket].tail = p1 - 1; - nonempty_bucket++; - } - } - bucket_info->numbuckets = nonempty_bucket; - } + // write back intersecting buckets as sorted list. + // fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets. + uint32_t nonempty_bucket; + for (uint32_t i = 0; i < 2; i++) { + p1 = start[i]; + nonempty_bucket = 0; + for (uint32_t j = 0x00; j <= 0xff; j++) { + if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only + bucket_info->bucket_info[i][nonempty_bucket].head = p1; + for (p2 = bucket[i][j].head; p2 < bucket[i][j].bp; *p1++ = *p2++); + bucket_info->bucket_info[i][nonempty_bucket].tail = p1 - 1; + nonempty_bucket++; + } + } + bucket_info->numbuckets = nonempty_bucket; + } } @@ -101,11 +101,11 @@ static void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop, */ static inline void update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2) { - uint32_t p = *item >> 25; + uint32_t p = *item >> 25; - p = p << 1 | parity(*item & mask1); - p = p << 1 | parity(*item & mask2); - *item = p << 24 | (*item & 0xffffff); + p = p << 1 | parity(*item & mask1); + p = p << 1 | parity(*item & mask2); + *item = p << 24 | (*item & 0xffffff); } /** extend_table @@ -113,83 +113,83 @@ static inline void update_contribution(uint32_t *item, const uint32_t mask1, con */ static inline void extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in) { - in <<= 24; - for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) - if(filter(*tbl) ^ filter(*tbl | 1)) { - *tbl |= filter(*tbl) ^ bit; - update_contribution(tbl, m1, m2); - *tbl ^= in; - } else if(filter(*tbl) == bit) { - *++*end = tbl[1]; - tbl[1] = tbl[0] | 1; - update_contribution(tbl, m1, m2); - *tbl++ ^= in; - update_contribution(tbl, m1, m2); - *tbl ^= in; - } else - *tbl-- = *(*end)--; + in <<= 24; + for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) + if(filter(*tbl) ^ filter(*tbl | 1)) { + *tbl |= filter(*tbl) ^ bit; + update_contribution(tbl, m1, m2); + *tbl ^= in; + } else if(filter(*tbl) == bit) { + *++*end = tbl[1]; + tbl[1] = tbl[0] | 1; + update_contribution(tbl, m1, m2); + *tbl++ ^= in; + update_contribution(tbl, m1, m2); + *tbl ^= in; + } else + *tbl-- = *(*end)--; } /** extend_table_simple * using a bit of the keystream extend the table of possible lfsr states */ static inline void extend_table_simple(uint32_t *tbl, uint32_t **end, int bit) { - for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) { - if(filter(*tbl) ^ filter(*tbl | 1)) { // replace - *tbl |= filter(*tbl) ^ bit; - } else if(filter(*tbl) == bit) { // insert - *++*end = *++tbl; - *tbl = tbl[-1] | 1; - } else { // drop - *tbl-- = *(*end)--; - } - } + for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) { + if(filter(*tbl) ^ filter(*tbl | 1)) { // replace + *tbl |= filter(*tbl) ^ bit; + } else if(filter(*tbl) == bit) { // insert + *++*end = *++tbl; + *tbl = tbl[-1] | 1; + } else { // drop + *tbl-- = *(*end)--; + } + } } /** recover * recursively narrow down the search space, 4 bits of keystream at a time */ static struct Crypto1State* recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks, - uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem, - struct Crypto1State *sl, uint32_t in, bucket_array_t bucket) + uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem, + struct Crypto1State *sl, uint32_t in, bucket_array_t bucket) { - uint32_t *o, *e; - bucket_info_t bucket_info; + uint32_t *o, *e; + bucket_info_t bucket_info; - if(rem == -1) { - for(e = e_head; e <= e_tail; ++e) { - *e = *e << 1 ^ parity(*e & LF_POLY_EVEN) ^ !!(in & 4); - for(o = o_head; o <= o_tail; ++o, ++sl) { - sl->even = *o; - sl->odd = *e ^ parity(*o & LF_POLY_ODD); - sl[1].odd = sl[1].even = 0; - } - } - return sl; - } + if(rem == -1) { + for(e = e_head; e <= e_tail; ++e) { + *e = *e << 1 ^ parity(*e & LF_POLY_EVEN) ^ !!(in & 4); + for(o = o_head; o <= o_tail; ++o, ++sl) { + sl->even = *o; + sl->odd = *e ^ parity(*o & LF_POLY_ODD); + sl[1].odd = sl[1].even = 0; + } + } + return sl; + } - for(uint32_t i = 0; i < 4 && rem--; i++) { - oks >>= 1; - eks >>= 1; - in >>= 2; - extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0); - if(o_head > o_tail) - return sl; + for(uint32_t i = 0; i < 4 && rem--; i++) { + oks >>= 1; + eks >>= 1; + in >>= 2; + extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0); + if(o_head > o_tail) + return sl; - extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, in & 3); - if(e_head > e_tail) - return sl; - } + extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, in & 3); + if(e_head > e_tail) + return sl; + } - bucket_sort_intersect(e_head, e_tail, o_head, o_tail, &bucket_info, bucket); + bucket_sort_intersect(e_head, e_tail, o_head, o_tail, &bucket_info, bucket); - for (int i = bucket_info.numbuckets - 1; i >= 0; i--) { - sl = recover(bucket_info.bucket_info[1][i].head, bucket_info.bucket_info[1][i].tail, oks, - bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks, - rem, sl, in, bucket); - } + for (int i = bucket_info.numbuckets - 1; i >= 0; i--) { + sl = recover(bucket_info.bucket_info[1][i].head, bucket_info.bucket_info[1][i].tail, oks, + bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks, + rem, sl, in, bucket); + } - return sl; + return sl; } /** lfsr_recovery * recover the state of the lfsr given 32 bits of the keystream @@ -198,87 +198,87 @@ recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks, */ struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in) { - struct Crypto1State *statelist; - uint32_t *odd_head = 0, *odd_tail = 0, oks = 0; - uint32_t *even_head = 0, *even_tail = 0, eks = 0; - int i; + struct Crypto1State *statelist; + uint32_t *odd_head = 0, *odd_tail = 0, oks = 0; + uint32_t *even_head = 0, *even_tail = 0, eks = 0; + int i; - // split the keystream into an odd and even part - for(i = 31; i >= 0; i -= 2) - oks = oks << 1 | BEBIT(ks2, i); - for(i = 30; i >= 0; i -= 2) - eks = eks << 1 | BEBIT(ks2, i); + // split the keystream into an odd and even part + for(i = 31; i >= 0; i -= 2) + oks = oks << 1 | BEBIT(ks2, i); + for(i = 30; i >= 0; i -= 2) + eks = eks << 1 | BEBIT(ks2, i); - odd_head = odd_tail = malloc(sizeof(uint32_t) << 21); - even_head = even_tail = malloc(sizeof(uint32_t) << 21); - statelist = malloc(sizeof(struct Crypto1State) << 18); - if(!odd_tail-- || !even_tail-- || !statelist) { - free(statelist); - statelist = 0; - goto out; - } + odd_head = odd_tail = malloc(sizeof(uint32_t) << 21); + even_head = even_tail = malloc(sizeof(uint32_t) << 21); + statelist = malloc(sizeof(struct Crypto1State) << 18); + if(!odd_tail-- || !even_tail-- || !statelist) { + free(statelist); + statelist = 0; + goto out; + } - statelist->odd = statelist->even = 0; + statelist->odd = statelist->even = 0; - // allocate memory for out of place bucket_sort - bucket_array_t bucket; + // allocate memory for out of place bucket_sort + bucket_array_t bucket; - for (uint32_t i = 0; i < 2; i++) { - for (uint32_t j = 0; j <= 0xff; j++) { - bucket[i][j].head = malloc(sizeof(uint32_t)<<14); - if (!bucket[i][j].head) { - goto out; - } - } - } + for (uint32_t i = 0; i < 2; i++) { + for (uint32_t j = 0; j <= 0xff; j++) { + bucket[i][j].head = malloc(sizeof(uint32_t)<<14); + if (!bucket[i][j].head) { + goto out; + } + } + } - // initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream - for(i = 1 << 20; i >= 0; --i) { - if(filter(i) == (oks & 1)) - *++odd_tail = i; - if(filter(i) == (eks & 1)) - *++even_tail = i; - } + // initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream + for(i = 1 << 20; i >= 0; --i) { + if(filter(i) == (oks & 1)) + *++odd_tail = i; + if(filter(i) == (eks & 1)) + *++even_tail = i; + } - // extend the statelists. Look at the next 8 Bits of the keystream (4 Bit each odd and even): - for(i = 0; i < 4; i++) { - extend_table_simple(odd_head, &odd_tail, (oks >>= 1) & 1); - extend_table_simple(even_head, &even_tail, (eks >>= 1) & 1); - } + // extend the statelists. Look at the next 8 Bits of the keystream (4 Bit each odd and even): + for(i = 0; i < 4; i++) { + extend_table_simple(odd_head, &odd_tail, (oks >>= 1) & 1); + extend_table_simple(even_head, &even_tail, (eks >>= 1) & 1); + } - // the statelists now contain all states which could have generated the last 10 Bits of the keystream. - // 22 bits to go to recover 32 bits in total. From now on, we need to take the "in" - // parameter into account. - in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping - recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket); + // the statelists now contain all states which could have generated the last 10 Bits of the keystream. + // 22 bits to go to recover 32 bits in total. From now on, we need to take the "in" + // parameter into account. + in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping + recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket); out: - for (uint32_t i = 0; i < 2; i++) - for (uint32_t j = 0; j <= 0xff; j++) - free(bucket[i][j].head); - free(odd_head); - free(even_head); - return statelist; + for (uint32_t i = 0; i < 2; i++) + for (uint32_t j = 0; j <= 0xff; j++) + free(bucket[i][j].head); + free(odd_head); + free(even_head); + return statelist; } static const uint32_t S1[] = { 0x62141, 0x310A0, 0x18850, 0x0C428, 0x06214, - 0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83, - 0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA}; + 0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83, + 0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA}; static const uint32_t S2[] = { 0x3A557B00, 0x5D2ABD80, 0x2E955EC0, 0x174AAF60, - 0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8, - 0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20, - 0x7EC7EE90, 0x7F63F748, 0x79117020}; + 0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8, + 0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20, + 0x7EC7EE90, 0x7F63F748, 0x79117020}; static const uint32_t T1[] = { - 0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66, - 0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B, - 0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615, - 0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C}; + 0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66, + 0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B, + 0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615, + 0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C}; static const uint32_t T2[] = { 0x3C88B810, 0x5E445C08, 0x2982A580, 0x14C152C0, - 0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268, - 0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0, - 0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0, - 0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950, - 0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0}; + 0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268, + 0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0, + 0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0, + 0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950, + 0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0}; static const uint32_t C1[] = { 0x846B5, 0x4235A, 0x211AD}; static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0}; /** Reverse 64 bits of keystream into possible cipher states @@ -286,69 +286,69 @@ static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0}; */ struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3) { - struct Crypto1State *statelist, *sl; - uint8_t oks[32], eks[32], hi[32]; - uint32_t low = 0, win = 0; - uint32_t *tail, table[1 << 16]; - int i, j; + struct Crypto1State *statelist, *sl; + uint8_t oks[32], eks[32], hi[32]; + uint32_t low = 0, win = 0; + uint32_t *tail, table[1 << 16]; + int i, j; - sl = statelist = malloc(sizeof(struct Crypto1State) << 4); - if(!sl) - return 0; - sl->odd = sl->even = 0; + sl = statelist = malloc(sizeof(struct Crypto1State) << 4); + if(!sl) + return 0; + sl->odd = sl->even = 0; - for(i = 30; i >= 0; i -= 2) { - oks[i >> 1] = BEBIT(ks2, i); - oks[16 + (i >> 1)] = BEBIT(ks3, i); - } - for(i = 31; i >= 0; i -= 2) { - eks[i >> 1] = BEBIT(ks2, i); - eks[16 + (i >> 1)] = BEBIT(ks3, i); - } + for(i = 30; i >= 0; i -= 2) { + oks[i >> 1] = BEBIT(ks2, i); + oks[16 + (i >> 1)] = BEBIT(ks3, i); + } + for(i = 31; i >= 0; i -= 2) { + eks[i >> 1] = BEBIT(ks2, i); + eks[16 + (i >> 1)] = BEBIT(ks3, i); + } - for(i = 0xfffff; i >= 0; --i) { - if (filter(i) != oks[0]) - continue; + for(i = 0xfffff; i >= 0; --i) { + if (filter(i) != oks[0]) + continue; - *(tail = table) = i; - for(j = 1; tail >= table && j < 29; ++j) - extend_table_simple(table, &tail, oks[j]); + *(tail = table) = i; + for(j = 1; tail >= table && j < 29; ++j) + extend_table_simple(table, &tail, oks[j]); - if(tail < table) - continue; + if(tail < table) + continue; - for(j = 0; j < 19; ++j) - low = low << 1 | parity(i & S1[j]); - for(j = 0; j < 32; ++j) - hi[j] = parity(i & T1[j]); + for(j = 0; j < 19; ++j) + low = low << 1 | parity(i & S1[j]); + for(j = 0; j < 32; ++j) + hi[j] = parity(i & T1[j]); - for(; tail >= table; --tail) { - for(j = 0; j < 3; ++j) { - *tail = *tail << 1; - *tail |= parity((i & C1[j]) ^ (*tail & C2[j])); - if(filter(*tail) != oks[29 + j]) - goto continue2; - } + for(; tail >= table; --tail) { + for(j = 0; j < 3; ++j) { + *tail = *tail << 1; + *tail |= parity((i & C1[j]) ^ (*tail & C2[j])); + if(filter(*tail) != oks[29 + j]) + goto continue2; + } - for(j = 0; j < 19; ++j) - win = win << 1 | parity(*tail & S2[j]); + for(j = 0; j < 19; ++j) + win = win << 1 | parity(*tail & S2[j]); - win ^= low; - for(j = 0; j < 32; ++j) { - win = win << 1 ^ hi[j] ^ parity(*tail & T2[j]); - if(filter(win) != eks[j]) - goto continue2; - } + win ^= low; + for(j = 0; j < 32; ++j) { + win = win << 1 ^ hi[j] ^ parity(*tail & T2[j]); + if(filter(win) != eks[j]) + goto continue2; + } - *tail = *tail << 1 | parity(LF_POLY_EVEN & *tail); - sl->odd = *tail ^ parity(LF_POLY_ODD & win); - sl->even = win; - ++sl; - sl->odd = sl->even = 0; - continue2:; - } - } - return statelist; + *tail = *tail << 1 | parity(LF_POLY_EVEN & *tail); + sl->odd = *tail ^ parity(LF_POLY_ODD & win); + sl->even = win; + ++sl; + sl->odd = sl->even = 0; + continue2:; + } + } + return statelist; } /** lfsr_rollback_bit @@ -356,93 +356,93 @@ struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3) */ uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb) { - int out; - uint8_t ret; - uint32_t t; + int out; + uint8_t ret; + uint32_t t; - s->odd &= 0xffffff; - t = s->odd, s->odd = s->even, s->even = t; + s->odd &= 0xffffff; + t = s->odd, s->odd = s->even, s->even = t; - out = s->even & 1; - out ^= LF_POLY_EVEN & (s->even >>= 1); - out ^= LF_POLY_ODD & s->odd; - out ^= !!in; - out ^= (ret = filter(s->odd)) & !!fb; + out = s->even & 1; + out ^= LF_POLY_EVEN & (s->even >>= 1); + out ^= LF_POLY_ODD & s->odd; + out ^= !!in; + out ^= (ret = filter(s->odd)) & !!fb; - s->even |= parity(out) << 23; - return ret; + s->even |= parity(out) << 23; + return ret; } /** lfsr_rollback_byte * Rollback the shift register in order to get previous states */ uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb) { - /* - int i, ret = 0; - for (i = 7; i >= 0; --i) - ret |= lfsr_rollback_bit(s, BIT(in, i), fb) << i; + /* + int i, ret = 0; + for (i = 7; i >= 0; --i) + ret |= lfsr_rollback_bit(s, BIT(in, i), fb) << i; */ // unfold loop 20160112 - uint8_t ret = 0; - ret |= lfsr_rollback_bit(s, BIT(in, 7), fb) << 7; - ret |= lfsr_rollback_bit(s, BIT(in, 6), fb) << 6; - ret |= lfsr_rollback_bit(s, BIT(in, 5), fb) << 5; - ret |= lfsr_rollback_bit(s, BIT(in, 4), fb) << 4; - ret |= lfsr_rollback_bit(s, BIT(in, 3), fb) << 3; - ret |= lfsr_rollback_bit(s, BIT(in, 2), fb) << 2; - ret |= lfsr_rollback_bit(s, BIT(in, 1), fb) << 1; - ret |= lfsr_rollback_bit(s, BIT(in, 0), fb) << 0; - return ret; + uint8_t ret = 0; + ret |= lfsr_rollback_bit(s, BIT(in, 7), fb) << 7; + ret |= lfsr_rollback_bit(s, BIT(in, 6), fb) << 6; + ret |= lfsr_rollback_bit(s, BIT(in, 5), fb) << 5; + ret |= lfsr_rollback_bit(s, BIT(in, 4), fb) << 4; + ret |= lfsr_rollback_bit(s, BIT(in, 3), fb) << 3; + ret |= lfsr_rollback_bit(s, BIT(in, 2), fb) << 2; + ret |= lfsr_rollback_bit(s, BIT(in, 1), fb) << 1; + ret |= lfsr_rollback_bit(s, BIT(in, 0), fb) << 0; + return ret; } /** lfsr_rollback_word * Rollback the shift register in order to get previous states */ uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) { - /* - int i; - uint32_t ret = 0; - for (i = 31; i >= 0; --i) - ret |= lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24); + /* + int i; + uint32_t ret = 0; + for (i = 31; i >= 0; --i) + ret |= lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24); */ // unfold loop 20160112 - uint32_t ret = 0; - ret |= lfsr_rollback_bit(s, BEBIT(in, 31), fb) << (31 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 30), fb) << (30 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 29), fb) << (29 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 28), fb) << (28 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 27), fb) << (27 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 26), fb) << (26 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 25), fb) << (25 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 24), fb) << (24 ^ 24); + uint32_t ret = 0; + ret |= lfsr_rollback_bit(s, BEBIT(in, 31), fb) << (31 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 30), fb) << (30 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 29), fb) << (29 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 28), fb) << (28 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 27), fb) << (27 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 26), fb) << (26 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 25), fb) << (25 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 24), fb) << (24 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 23), fb) << (23 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 22), fb) << (22 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 21), fb) << (21 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 20), fb) << (20 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 19), fb) << (19 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 18), fb) << (18 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 17), fb) << (17 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 16), fb) << (16 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 23), fb) << (23 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 22), fb) << (22 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 21), fb) << (21 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 20), fb) << (20 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 19), fb) << (19 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 18), fb) << (18 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 17), fb) << (17 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 16), fb) << (16 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 15), fb) << (15 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 14), fb) << (14 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 13), fb) << (13 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 12), fb) << (12 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 11), fb) << (11 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 10), fb) << (10 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 9), fb) << (9 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 8), fb) << (8 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 15), fb) << (15 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 14), fb) << (14 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 13), fb) << (13 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 12), fb) << (12 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 11), fb) << (11 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 10), fb) << (10 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 9), fb) << (9 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 8), fb) << (8 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 7), fb) << (7 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 6), fb) << (6 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 5), fb) << (5 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 4), fb) << (4 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 3), fb) << (3 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 2), fb) << (2 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 1), fb) << (1 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 0), fb) << (0 ^ 24); - return ret; + ret |= lfsr_rollback_bit(s, BEBIT(in, 7), fb) << (7 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 6), fb) << (6 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 5), fb) << (5 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 4), fb) << (4 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 3), fb) << (3 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 2), fb) << (2 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 1), fb) << (1 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 0), fb) << (0 ^ 24); + return ret; } /** nonce_distance @@ -451,23 +451,23 @@ uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) static uint16_t *dist = 0; int nonce_distance(uint32_t from, uint32_t to) { - uint16_t x, i; - if(!dist) { - dist = malloc(2 << 16); - if(!dist) - return -1; - for (x = i = 1; i; ++i) { - dist[(x & 0xff) << 8 | x >> 8] = i; - x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; - } - } - return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535; + uint16_t x, i; + if(!dist) { + dist = malloc(2 << 16); + if(!dist) + return -1; + for (x = i = 1; i; ++i) { + dist[(x & 0xff) << 8 | x >> 8] = i; + x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; + } + } + return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535; } static uint32_t fastfwd[2][8] = { - { 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB}, - { 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}}; + { 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB}, + { 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}}; /** lfsr_prefix_ks @@ -481,25 +481,25 @@ static uint32_t fastfwd[2][8] = { */ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) { - uint32_t *candidates = malloc(4 << 10); - if(!candidates) return 0; + uint32_t *candidates = malloc(4 << 10); + if(!candidates) return 0; - uint32_t c, entry; - int size = 0, i, good; + uint32_t c, entry; + int size = 0, i, good; - for(i = 0; i < 1 << 21; ++i) { - for(c = 0, good = 1; good && c < 8; ++c) { - entry = i ^ fastfwd[isodd][c]; - good &= (BIT(ks[c], isodd) == filter(entry >> 1)); - good &= (BIT(ks[c], isodd + 2) == filter(entry)); - } - if(good) - candidates[size++] = i; - } + for(i = 0; i < 1 << 21; ++i) { + for(c = 0, good = 1; good && c < 8; ++c) { + entry = i ^ fastfwd[isodd][c]; + good &= (BIT(ks[c], isodd) == filter(entry >> 1)); + good &= (BIT(ks[c], isodd + 2) == filter(entry)); + } + if(good) + candidates[size++] = i; + } - candidates[size] = -1; + candidates[size] = -1; - return candidates; + return candidates; } /** check_pfx_parity @@ -507,30 +507,30 @@ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) */ static struct Crypto1State* check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8], uint32_t odd, uint32_t even, struct Crypto1State* sl) { - uint32_t ks1, nr, ks2, rr, ks3, c, good = 1; + uint32_t ks1, nr, ks2, rr, ks3, c, good = 1; - for(c = 0; good && c < 8; ++c) { - sl->odd = odd ^ fastfwd[1][c]; - sl->even = even ^ fastfwd[0][c]; + for(c = 0; good && c < 8; ++c) { + sl->odd = odd ^ fastfwd[1][c]; + sl->even = even ^ fastfwd[0][c]; - lfsr_rollback_bit(sl, 0, 0); - lfsr_rollback_bit(sl, 0, 0); + lfsr_rollback_bit(sl, 0, 0); + lfsr_rollback_bit(sl, 0, 0); - ks3 = lfsr_rollback_bit(sl, 0, 0); - ks2 = lfsr_rollback_word(sl, 0, 0); - ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1); + ks3 = lfsr_rollback_bit(sl, 0, 0); + ks2 = lfsr_rollback_word(sl, 0, 0); + ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1); - nr = ks1 ^ (prefix | c << 5); - rr = ks2 ^ rresp; + nr = ks1 ^ (prefix | c << 5); + rr = ks2 ^ rresp; - good &= parity(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); - good &= parity(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); - good &= parity(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8); - good &= parity(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0); - good &= parity(rr & 0x000000ff) ^ parities[c][7] ^ ks3; - } + good &= parity(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); + good &= parity(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); + good &= parity(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8); + good &= parity(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0); + good &= parity(rr & 0x000000ff) ^ parities[c][7] ^ ks3; + } - return sl + good; + return sl + good; } /** lfsr_common_prefix @@ -545,30 +545,30 @@ static struct Crypto1State* check_pfx_parity(uint32_t prefix, uint32_t rresp, ui struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]) { - struct Crypto1State *statelist, *s; - uint32_t *odd, *even, *o, *e, top; + struct Crypto1State *statelist, *s; + uint32_t *odd, *even, *o, *e, top; - odd = lfsr_prefix_ks(ks, 1); - even = lfsr_prefix_ks(ks, 0); + odd = lfsr_prefix_ks(ks, 1); + even = lfsr_prefix_ks(ks, 0); - s = statelist = malloc((sizeof *statelist) << 24); - if(!s || !odd || !even) { - free(statelist); - statelist = 0; + s = statelist = malloc((sizeof *statelist) << 24); + if(!s || !odd || !even) { + free(statelist); + statelist = 0; goto out; - } + } - for(o = odd; *o + 1; ++o) - for(e = even; *e + 1; ++e) - for(top = 0; top < 64; ++top) { - *o += 1 << 21; - *e += (!(top & 7) + 1) << 21; - s = check_pfx_parity(pfx, rr, par, *o, *e, s); - } + for(o = odd; *o + 1; ++o) + for(e = even; *e + 1; ++e) + for(top = 0; top < 64; ++top) { + *o += 1 << 21; + *e += (!(top & 7) + 1) << 21; + s = check_pfx_parity(pfx, rr, par, *o, *e, s); + } - s->odd = s->even = 0; + s->odd = s->even = 0; out: - free(odd); - free(even); - return statelist; + free(odd); + free(even); + return statelist; } diff --git a/tools/mfkey/crapto1.h b/tools/mfkey/crapto1.h index 875ffdaab..75391c4f2 100755 --- a/tools/mfkey/crapto1.h +++ b/tools/mfkey/crapto1.h @@ -43,18 +43,18 @@ uint8_t lfsr_rollback_byte(struct Crypto1State* s, uint32_t in, int fb); uint32_t lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb); int nonce_distance(uint32_t from, uint32_t to); #define SWAPENDIAN(x)\ - (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) + (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) #define FOREACH_VALID_NONCE(N, FILTER, FSIZE)\ - uint32_t __n = 0,__M = 0, N = 0;\ - int __i;\ - for(; __n < 1 << 16; N = prng_successor(__M = ++__n, 16))\ - for(__i = FSIZE - 1; __i >= 0; __i--)\ - if(BIT(FILTER, __i) ^ parity(__M & 0xFF01))\ - break;\ - else if(__i)\ - __M = prng_successor(__M, (__i == 7) ? 48 : 8);\ - else + uint32_t __n = 0,__M = 0, N = 0;\ + int __i;\ + for(; __n < 1 << 16; N = prng_successor(__M = ++__n, 16))\ + for(__i = FSIZE - 1; __i >= 0; __i--)\ + if(BIT(FILTER, __i) ^ parity(__M & 0xFF01))\ + break;\ + else if(__i)\ + __M = prng_successor(__M, (__i == 7) ? 48 : 8);\ + else #define LF_POLY_ODD (0x29CE5C) #define LF_POLY_EVEN (0x870804) @@ -63,31 +63,31 @@ int nonce_distance(uint32_t from, uint32_t to); static inline int parity(uint32_t x) { #if !defined __i386__ || !defined __GNUC__ - x ^= x >> 16; - x ^= x >> 8; - x ^= x >> 4; - return BIT(0x6996, x & 0xf); + x ^= x >> 16; + x ^= x >> 8; + x ^= x >> 4; + return BIT(0x6996, x & 0xf); #else - __asm__( "movl %1, %%eax\n" - "mov %%ax, %%cx\n" - "shrl $0x10, %%eax\n" - "xor %%ax, %%cx\n" - "xor %%ch, %%cl\n" - "setpo %%al\n" - "movzx %%al, %0\n": "=r"(x) : "r"(x): "eax","ecx"); - return x; + __asm__( "movl %1, %%eax\n" + "mov %%ax, %%cx\n" + "shrl $0x10, %%eax\n" + "xor %%ax, %%cx\n" + "xor %%ch, %%cl\n" + "setpo %%al\n" + "movzx %%al, %0\n": "=r"(x) : "r"(x): "eax","ecx"); + return x; #endif } static inline int filter(uint32_t const x) { - uint32_t f; + uint32_t f; - f = 0xf22c0 >> (x & 0xf) & 16; - f |= 0x6c9c0 >> (x >> 4 & 0xf) & 8; - f |= 0x3c8b0 >> (x >> 8 & 0xf) & 4; - f |= 0x1e458 >> (x >> 12 & 0xf) & 2; - f |= 0x0d938 >> (x >> 16 & 0xf) & 1; - return BIT(0xEC57E80A, f); + f = 0xf22c0 >> (x & 0xf) & 16; + f |= 0x6c9c0 >> (x >> 4 & 0xf) & 8; + f |= 0x3c8b0 >> (x >> 8 & 0xf) & 4; + f |= 0x1e458 >> (x >> 12 & 0xf) & 2; + f |= 0x0d938 >> (x >> 16 & 0xf) & 1; + return BIT(0xEC57E80A, f); } #ifdef __cplusplus } diff --git a/tools/mfkey/crypto1.c b/tools/mfkey/crypto1.c index 14e2cc829..e8384c16a 100755 --- a/tools/mfkey/crypto1.c +++ b/tools/mfkey/crypto1.c @@ -22,115 +22,115 @@ struct Crypto1State * crypto1_create(uint64_t key) { - struct Crypto1State *s = malloc(sizeof(*s)); - if ( !s ) return NULL; + struct Crypto1State *s = malloc(sizeof(*s)); + if ( !s ) return NULL; - s->odd = s->even = 0; + s->odd = s->even = 0; - int i; - //for(i = 47;s && i > 0; i -= 2) { - for(i = 47; i > 0; i -= 2) { - s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7); - s->even = s->even << 1 | BIT(key, i ^ 7); - } - return s; + int i; + //for(i = 47;s && i > 0; i -= 2) { + for(i = 47; i > 0; i -= 2) { + s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7); + s->even = s->even << 1 | BIT(key, i ^ 7); + } + return s; } void crypto1_destroy(struct Crypto1State *state) { - free(state); + free(state); } void crypto1_get_lfsr(struct Crypto1State *state, uint64_t *lfsr) { - int i; - for(*lfsr = 0, i = 23; i >= 0; --i) { - *lfsr = *lfsr << 1 | BIT(state->odd, i ^ 3); - *lfsr = *lfsr << 1 | BIT(state->even, i ^ 3); - } + int i; + for(*lfsr = 0, i = 23; i >= 0; --i) { + *lfsr = *lfsr << 1 | BIT(state->odd, i ^ 3); + *lfsr = *lfsr << 1 | BIT(state->even, i ^ 3); + } } uint8_t crypto1_bit(struct Crypto1State *s, uint8_t in, int is_encrypted) { - uint32_t feedin; - uint32_t tmp; - uint8_t ret = filter(s->odd); + uint32_t feedin; + uint32_t tmp; + uint8_t ret = filter(s->odd); - feedin = ret & !!is_encrypted; - feedin ^= !!in; - feedin ^= LF_POLY_ODD & s->odd; - feedin ^= LF_POLY_EVEN & s->even; - s->even = s->even << 1 | parity(feedin); + feedin = ret & !!is_encrypted; + feedin ^= !!in; + feedin ^= LF_POLY_ODD & s->odd; + feedin ^= LF_POLY_EVEN & s->even; + s->even = s->even << 1 | parity(feedin); - tmp = s->odd; - s->odd = s->even; - s->even = tmp; + tmp = s->odd; + s->odd = s->even; + s->even = tmp; - return ret; + return ret; } uint8_t crypto1_byte(struct Crypto1State *s, uint8_t in, int is_encrypted) { - /* - uint8_t i, ret = 0; + /* + uint8_t i, ret = 0; - for (i = 0; i < 8; ++i) - ret |= crypto1_bit(s, BIT(in, i), is_encrypted) << i; - */ + for (i = 0; i < 8; ++i) + ret |= crypto1_bit(s, BIT(in, i), is_encrypted) << i; + */ // unfold loop 20161012 - uint8_t ret = 0; - ret |= crypto1_bit(s, BIT(in, 0), is_encrypted) << 0; - ret |= crypto1_bit(s, BIT(in, 1), is_encrypted) << 1; - ret |= crypto1_bit(s, BIT(in, 2), is_encrypted) << 2; - ret |= crypto1_bit(s, BIT(in, 3), is_encrypted) << 3; - ret |= crypto1_bit(s, BIT(in, 4), is_encrypted) << 4; - ret |= crypto1_bit(s, BIT(in, 5), is_encrypted) << 5; - ret |= crypto1_bit(s, BIT(in, 6), is_encrypted) << 6; - ret |= crypto1_bit(s, BIT(in, 7), is_encrypted) << 7; - return ret; + uint8_t ret = 0; + ret |= crypto1_bit(s, BIT(in, 0), is_encrypted) << 0; + ret |= crypto1_bit(s, BIT(in, 1), is_encrypted) << 1; + ret |= crypto1_bit(s, BIT(in, 2), is_encrypted) << 2; + ret |= crypto1_bit(s, BIT(in, 3), is_encrypted) << 3; + ret |= crypto1_bit(s, BIT(in, 4), is_encrypted) << 4; + ret |= crypto1_bit(s, BIT(in, 5), is_encrypted) << 5; + ret |= crypto1_bit(s, BIT(in, 6), is_encrypted) << 6; + ret |= crypto1_bit(s, BIT(in, 7), is_encrypted) << 7; + return ret; } uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) { - /* - uint32_t i, ret = 0; + /* + uint32_t i, ret = 0; - for (i = 0; i < 32; ++i) - ret |= crypto1_bit(s, BEBIT(in, i), is_encrypted) << (i ^ 24); + for (i = 0; i < 32; ++i) + ret |= crypto1_bit(s, BEBIT(in, i), is_encrypted) << (i ^ 24); */ //unfold loop 2016012 - uint32_t ret = 0; - ret |= crypto1_bit(s, BEBIT(in, 0), is_encrypted) << (0 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 1), is_encrypted) << (1 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 2), is_encrypted) << (2 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 3), is_encrypted) << (3 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 4), is_encrypted) << (4 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 5), is_encrypted) << (5 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 6), is_encrypted) << (6 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 7), is_encrypted) << (7 ^ 24); + uint32_t ret = 0; + ret |= crypto1_bit(s, BEBIT(in, 0), is_encrypted) << (0 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 1), is_encrypted) << (1 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 2), is_encrypted) << (2 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 3), is_encrypted) << (3 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 4), is_encrypted) << (4 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 5), is_encrypted) << (5 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 6), is_encrypted) << (6 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 7), is_encrypted) << (7 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 8), is_encrypted) << (8 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 9), is_encrypted) << (9 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 10), is_encrypted) << (10 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 11), is_encrypted) << (11 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 12), is_encrypted) << (12 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 13), is_encrypted) << (13 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 14), is_encrypted) << (14 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 15), is_encrypted) << (15 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 8), is_encrypted) << (8 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 9), is_encrypted) << (9 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 10), is_encrypted) << (10 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 11), is_encrypted) << (11 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 12), is_encrypted) << (12 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 13), is_encrypted) << (13 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 14), is_encrypted) << (14 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 15), is_encrypted) << (15 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 16), is_encrypted) << (16 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 17), is_encrypted) << (17 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 18), is_encrypted) << (18 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 19), is_encrypted) << (19 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 20), is_encrypted) << (20 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 21), is_encrypted) << (21 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 22), is_encrypted) << (22 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 23), is_encrypted) << (23 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 16), is_encrypted) << (16 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 17), is_encrypted) << (17 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 18), is_encrypted) << (18 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 19), is_encrypted) << (19 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 20), is_encrypted) << (20 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 21), is_encrypted) << (21 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 22), is_encrypted) << (22 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 23), is_encrypted) << (23 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 24), is_encrypted) << (24 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 25), is_encrypted) << (25 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 26), is_encrypted) << (26 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 27), is_encrypted) << (27 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 28), is_encrypted) << (28 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 29), is_encrypted) << (29 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 30), is_encrypted) << (30 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 31), is_encrypted) << (31 ^ 24); - return ret; + ret |= crypto1_bit(s, BEBIT(in, 24), is_encrypted) << (24 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 25), is_encrypted) << (25 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 26), is_encrypted) << (26 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 27), is_encrypted) << (27 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 28), is_encrypted) << (28 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 29), is_encrypted) << (29 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 30), is_encrypted) << (30 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 31), is_encrypted) << (31 ^ 24); + return ret; } /* prng_successor @@ -138,9 +138,9 @@ uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) */ uint32_t prng_successor(uint32_t x, uint32_t n) { - SWAPENDIAN(x); - while(n--) - x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; + SWAPENDIAN(x); + while(n--) + x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; - return SWAPENDIAN(x); + return SWAPENDIAN(x); } diff --git a/tools/mfkey/mfkey32.c b/tools/mfkey/mfkey32.c index 2761a063b..df4dc65cd 100755 --- a/tools/mfkey/mfkey32.c +++ b/tools/mfkey/mfkey32.c @@ -5,63 +5,63 @@ #include int main (int argc, char *argv[]) { - struct Crypto1State *s,*t; - uint64_t key; // recovered key - uint32_t uid; // serial number - uint32_t nt; // tag challenge - uint32_t nr0_enc; // first encrypted reader challenge - uint32_t ar0_enc; // first encrypted reader response - uint32_t nr1_enc; // second encrypted reader challenge - uint32_t ar1_enc; // second encrypted reader response - uint32_t ks2; // keystream used to encrypt reader response + struct Crypto1State *s,*t; + uint64_t key; // recovered key + uint32_t uid; // serial number + uint32_t nt; // tag challenge + uint32_t nr0_enc; // first encrypted reader challenge + uint32_t ar0_enc; // first encrypted reader response + uint32_t nr1_enc; // second encrypted reader challenge + uint32_t ar1_enc; // second encrypted reader response + uint32_t ks2; // keystream used to encrypt reader response - printf("MIFARE Classic key recovery - based 32 bits of keystream\n"); - printf("Recover key from two 32-bit reader authentication answers only!\n\n"); + printf("MIFARE Classic key recovery - based 32 bits of keystream\n"); + printf("Recover key from two 32-bit reader authentication answers only!\n\n"); - if (argc < 7) { - printf(" syntax: %s \n\n",argv[0]); - return 1; - } + if (argc < 7) { + printf(" syntax: %s \n\n",argv[0]); + return 1; + } - sscanf(argv[1],"%x",&uid); - sscanf(argv[2],"%x",&nt); - sscanf(argv[3],"%x",&nr0_enc); - sscanf(argv[4],"%x",&ar0_enc); - sscanf(argv[5],"%x",&nr1_enc); - sscanf(argv[6],"%x",&ar1_enc); + sscanf(argv[1],"%x",&uid); + sscanf(argv[2],"%x",&nt); + sscanf(argv[3],"%x",&nr0_enc); + sscanf(argv[4],"%x",&ar0_enc); + sscanf(argv[5],"%x",&nr1_enc); + sscanf(argv[6],"%x",&ar1_enc); - printf("Recovering key for:\n"); - printf(" uid: %08x\n",uid); - printf(" nt: %08x\n",nt); - printf(" {nr_0}: %08x\n",nr0_enc); - printf(" {ar_0}: %08x\n",ar0_enc); - printf(" {nr_1}: %08x\n",nr1_enc); - printf(" {ar_1}: %08x\n",ar1_enc); + printf("Recovering key for:\n"); + printf(" uid: %08x\n",uid); + printf(" nt: %08x\n",nt); + printf(" {nr_0}: %08x\n",nr0_enc); + printf(" {ar_0}: %08x\n",ar0_enc); + printf(" {nr_1}: %08x\n",nr1_enc); + printf(" {ar_1}: %08x\n",ar1_enc); - // Generate lfsr succesors of the tag challenge - printf("\nLFSR succesors of the tag challenge:\n"); - uint32_t p64 = prng_successor(nt, 64); - printf(" nt': %08x\n", p64); - printf(" nt'': %08x\n", prng_successor(p64, 32)); + // Generate lfsr succesors of the tag challenge + printf("\nLFSR succesors of the tag challenge:\n"); + uint32_t p64 = prng_successor(nt, 64); + printf(" nt': %08x\n", p64); + printf(" nt'': %08x\n", prng_successor(p64, 32)); - // Extract the keystream from the messages - printf("\nKeystream used to generate {ar} and {at}:\n"); - ks2 = ar0_enc ^ p64; - printf(" ks2: %08x\n", ks2); + // Extract the keystream from the messages + printf("\nKeystream used to generate {ar} and {at}:\n"); + ks2 = ar0_enc ^ p64; + printf(" ks2: %08x\n", ks2); - s = lfsr_recovery32(ar0_enc ^ p64, 0); + s = lfsr_recovery32(ar0_enc ^ p64, 0); - for(t = s; t->odd | t->even; ++t) { - lfsr_rollback_word(t, 0, 0); - lfsr_rollback_word(t, nr0_enc, 1); - lfsr_rollback_word(t, uid ^ nt, 0); - crypto1_get_lfsr(t, &key); - crypto1_word(t, uid ^ nt, 0); - crypto1_word(t, nr1_enc, 1); - if (ar1_enc == (crypto1_word(t, 0, 0) ^ p64)) { - printf("\nFound Key: [%012" PRIx64 "]\n\n",key); - break;} - } - free(s); - return 0; + for(t = s; t->odd | t->even; ++t) { + lfsr_rollback_word(t, 0, 0); + lfsr_rollback_word(t, nr0_enc, 1); + lfsr_rollback_word(t, uid ^ nt, 0); + crypto1_get_lfsr(t, &key); + crypto1_word(t, uid ^ nt, 0); + crypto1_word(t, nr1_enc, 1); + if (ar1_enc == (crypto1_word(t, 0, 0) ^ p64)) { + printf("\nFound Key: [%012" PRIx64 "]\n\n",key); + break;} + } + free(s); + return 0; } diff --git a/tools/mfkey/mfkey32v2.c b/tools/mfkey/mfkey32v2.c index 03189aa73..d799dc8e6 100644 --- a/tools/mfkey/mfkey32v2.c +++ b/tools/mfkey/mfkey32v2.c @@ -5,70 +5,70 @@ #include int main (int argc, char *argv[]) { - struct Crypto1State *s,*t; - uint64_t key; // recovered key - uint32_t uid; // serial number - uint32_t nt0; // tag challenge first - uint32_t nt1; // tag challenge second - uint32_t nr0_enc; // first encrypted reader challenge - uint32_t ar0_enc; // first encrypted reader response - uint32_t nr1_enc; // second encrypted reader challenge - uint32_t ar1_enc; // second encrypted reader response - uint32_t ks2; // keystream used to encrypt reader response + struct Crypto1State *s,*t; + uint64_t key; // recovered key + uint32_t uid; // serial number + uint32_t nt0; // tag challenge first + uint32_t nt1; // tag challenge second + uint32_t nr0_enc; // first encrypted reader challenge + uint32_t ar0_enc; // first encrypted reader response + uint32_t nr1_enc; // second encrypted reader challenge + uint32_t ar1_enc; // second encrypted reader response + uint32_t ks2; // keystream used to encrypt reader response - printf("MIFARE Classic key recovery - based 32 bits of keystream VERSION2\n"); - printf("Recover key from two 32-bit reader authentication answers only\n"); - printf("This version implements Moebius two different nonce solution (like the supercard)\n\n"); + printf("MIFARE Classic key recovery - based 32 bits of keystream VERSION2\n"); + printf("Recover key from two 32-bit reader authentication answers only\n"); + printf("This version implements Moebius two different nonce solution (like the supercard)\n\n"); - if (argc < 8) { - printf("syntax: %s \n\n", argv[0]); - return 1; - } + if (argc < 8) { + printf("syntax: %s \n\n", argv[0]); + return 1; + } - sscanf(argv[1],"%x",&uid); - sscanf(argv[2],"%x",&nt0); - sscanf(argv[3],"%x",&nr0_enc); - sscanf(argv[4],"%x",&ar0_enc); - sscanf(argv[5],"%x",&nt1); - sscanf(argv[6],"%x",&nr1_enc); - sscanf(argv[7],"%x",&ar1_enc); + sscanf(argv[1],"%x",&uid); + sscanf(argv[2],"%x",&nt0); + sscanf(argv[3],"%x",&nr0_enc); + sscanf(argv[4],"%x",&ar0_enc); + sscanf(argv[5],"%x",&nt1); + sscanf(argv[6],"%x",&nr1_enc); + sscanf(argv[7],"%x",&ar1_enc); - printf("Recovering key for:\n"); - printf(" uid: %08x\n",uid); - printf(" nt_0: %08x\n",nt0); - printf(" {nr_0}: %08x\n",nr0_enc); - printf(" {ar_0}: %08x\n",ar0_enc); - printf(" nt_1: %08x\n",nt1); - printf(" {nr_1}: %08x\n",nr1_enc); - printf(" {ar_1}: %08x\n",ar1_enc); + printf("Recovering key for:\n"); + printf(" uid: %08x\n",uid); + printf(" nt_0: %08x\n",nt0); + printf(" {nr_0}: %08x\n",nr0_enc); + printf(" {ar_0}: %08x\n",ar0_enc); + printf(" nt_1: %08x\n",nt1); + printf(" {nr_1}: %08x\n",nr1_enc); + printf(" {ar_1}: %08x\n",ar1_enc); - // Generate lfsr succesors of the tag challenge - printf("\nLFSR succesors of the tag challenge:\n"); - uint32_t p64 = prng_successor(nt0, 64); - uint32_t p64b = prng_successor(nt1, 64); + // Generate lfsr succesors of the tag challenge + printf("\nLFSR succesors of the tag challenge:\n"); + uint32_t p64 = prng_successor(nt0, 64); + uint32_t p64b = prng_successor(nt1, 64); - printf(" nt': %08x\n", p64); - printf(" nt'': %08x\n", prng_successor(p64, 32)); + printf(" nt': %08x\n", p64); + printf(" nt'': %08x\n", prng_successor(p64, 32)); - // Extract the keystream from the messages - printf("\nKeystream used to generate {ar} and {at}:\n"); - ks2 = ar0_enc ^ p64; - printf(" ks2: %08x\n",ks2); + // Extract the keystream from the messages + printf("\nKeystream used to generate {ar} and {at}:\n"); + ks2 = ar0_enc ^ p64; + printf(" ks2: %08x\n",ks2); - s = lfsr_recovery32(ar0_enc ^ p64, 0); + s = lfsr_recovery32(ar0_enc ^ p64, 0); - for(t = s; t->odd | t->even; ++t) { - lfsr_rollback_word(t, 0, 0); - lfsr_rollback_word(t, nr0_enc, 1); - lfsr_rollback_word(t, uid ^ nt0, 0); - crypto1_get_lfsr(t, &key); + for(t = s; t->odd | t->even; ++t) { + lfsr_rollback_word(t, 0, 0); + lfsr_rollback_word(t, nr0_enc, 1); + lfsr_rollback_word(t, uid ^ nt0, 0); + crypto1_get_lfsr(t, &key); - crypto1_word(t, uid ^ nt1, 0); - crypto1_word(t, nr1_enc, 1); - if (ar1_enc == (crypto1_word(t, 0, 0) ^ p64b)) { - printf("\nFound Key: [%012" PRIx64 "]\n\n",key); - break;} - } - free(s); - return 0; + crypto1_word(t, uid ^ nt1, 0); + crypto1_word(t, nr1_enc, 1); + if (ar1_enc == (crypto1_word(t, 0, 0) ^ p64b)) { + printf("\nFound Key: [%012" PRIx64 "]\n\n",key); + break;} + } + free(s); + return 0; } diff --git a/tools/mfkey/mfkey64.c b/tools/mfkey/mfkey64.c index a05cd223e..f7cf790eb 100755 --- a/tools/mfkey/mfkey64.c +++ b/tools/mfkey/mfkey64.c @@ -6,94 +6,94 @@ #include "crapto1.h" int main (int argc, char *argv[]) { - struct Crypto1State *revstate; - uint64_t key; // recovered key - uint32_t uid; // serial number - uint32_t nt; // tag challenge - uint32_t nr_enc; // encrypted reader challenge - uint32_t ar_enc; // encrypted reader response - uint32_t at_enc; // encrypted tag response - uint32_t ks2; // keystream used to encrypt reader response - uint32_t ks3; // keystream used to encrypt tag response + struct Crypto1State *revstate; + uint64_t key; // recovered key + uint32_t uid; // serial number + uint32_t nt; // tag challenge + uint32_t nr_enc; // encrypted reader challenge + uint32_t ar_enc; // encrypted reader response + uint32_t at_enc; // encrypted tag response + uint32_t ks2; // keystream used to encrypt reader response + uint32_t ks3; // keystream used to encrypt tag response - printf("MIFARE Classic key recovery - based 64 bits of keystream\n"); - printf("Recover key from only one complete authentication!\n\n"); + printf("MIFARE Classic key recovery - based 64 bits of keystream\n"); + printf("Recover key from only one complete authentication!\n\n"); - if (argc < 6) { - printf(" syntax: %s <{nr}> <{ar}> <{at}> [enc...]\n\n", argv[0]); - return 1; - } + if (argc < 6) { + printf(" syntax: %s <{nr}> <{ar}> <{at}> [enc...]\n\n", argv[0]); + return 1; + } - int encc = argc - 6; - int enclen[encc]; - uint8_t enc[encc][120]; + int encc = argc - 6; + int enclen[encc]; + uint8_t enc[encc][120]; - sscanf(argv[1],"%x",&uid); - sscanf(argv[2],"%x",&nt); - sscanf(argv[3],"%x",&nr_enc); - sscanf(argv[4],"%x",&ar_enc); - sscanf(argv[5],"%x",&at_enc); - for (int i = 0; i < encc; i++) { - enclen[i] = strlen(argv[i + 6]) / 2; - for (int i2 = 0; i2 < enclen[i]; i2++) { - sscanf(argv[i+6] + i2*2, "%2x", (unsigned int *)&enc[i][i2]); - } - } + sscanf(argv[1],"%x",&uid); + sscanf(argv[2],"%x",&nt); + sscanf(argv[3],"%x",&nr_enc); + sscanf(argv[4],"%x",&ar_enc); + sscanf(argv[5],"%x",&at_enc); + for (int i = 0; i < encc; i++) { + enclen[i] = strlen(argv[i + 6]) / 2; + for (int i2 = 0; i2 < enclen[i]; i2++) { + sscanf(argv[i+6] + i2*2, "%2x", (unsigned int *)&enc[i][i2]); + } + } - printf("Recovering key for:\n"); + printf("Recovering key for:\n"); - printf(" uid: %08x\n",uid); - printf(" nt: %08x\n",nt); - printf(" {nr}: %08x\n",nr_enc); - printf(" {ar}: %08x\n",ar_enc); - printf(" {at}: %08x\n",at_enc); + printf(" uid: %08x\n",uid); + printf(" nt: %08x\n",nt); + printf(" {nr}: %08x\n",nr_enc); + printf(" {ar}: %08x\n",ar_enc); + printf(" {at}: %08x\n",at_enc); - for (int i = 0; i < encc; i++) { - printf("{enc%d}: ", i); - for (int i2 = 0; i2 < enclen[i]; i2++) { - printf("%02x", enc[i][i2]); - } - printf("\n"); - } + for (int i = 0; i < encc; i++) { + printf("{enc%d}: ", i); + for (int i2 = 0; i2 < enclen[i]; i2++) { + printf("%02x", enc[i][i2]); + } + printf("\n"); + } - // Generate lfsr succesors of the tag challenge - printf("\nLFSR succesors of the tag challenge:\n"); - printf(" nt': %08x\n",prng_successor(nt, 64)); - printf(" nt'': %08x\n",prng_successor(nt, 96)); + // Generate lfsr succesors of the tag challenge + printf("\nLFSR succesors of the tag challenge:\n"); + printf(" nt': %08x\n",prng_successor(nt, 64)); + printf(" nt'': %08x\n",prng_successor(nt, 96)); - // Extract the keystream from the messages - printf("\nKeystream used to generate {ar} and {at}:\n"); - ks2 = ar_enc ^ prng_successor(nt, 64); - ks3 = at_enc ^ prng_successor(nt, 96); - printf(" ks2: %08x\n",ks2); - printf(" ks3: %08x\n",ks3); + // Extract the keystream from the messages + printf("\nKeystream used to generate {ar} and {at}:\n"); + ks2 = ar_enc ^ prng_successor(nt, 64); + ks3 = at_enc ^ prng_successor(nt, 96); + printf(" ks2: %08x\n",ks2); + printf(" ks3: %08x\n",ks3); - revstate = lfsr_recovery64(ks2, ks3); + revstate = lfsr_recovery64(ks2, ks3); - // Decrypting communication using keystream if presented - if (argc > 6 ) { - printf("\nDecrypted communication:\n"); - uint8_t ks4; - int rollb = 0; - for (int i = 0; i < encc; i++) { - printf("{dec%d}: ", i); - for (int i2 = 0; i2 < enclen[i]; i2++) { - ks4 = crypto1_byte(revstate, 0, 0); - printf("%02x", ks4 ^ enc[i][i2]); - rollb += 1; - } - printf("\n"); - } - for (int i = 0; i < rollb; i++) - lfsr_rollback_byte(revstate, 0, 0); - } + // Decrypting communication using keystream if presented + if (argc > 6 ) { + printf("\nDecrypted communication:\n"); + uint8_t ks4; + int rollb = 0; + for (int i = 0; i < encc; i++) { + printf("{dec%d}: ", i); + for (int i2 = 0; i2 < enclen[i]; i2++) { + ks4 = crypto1_byte(revstate, 0, 0); + printf("%02x", ks4 ^ enc[i][i2]); + rollb += 1; + } + printf("\n"); + } + for (int i = 0; i < rollb; i++) + lfsr_rollback_byte(revstate, 0, 0); + } - lfsr_rollback_word(revstate, 0, 0); - lfsr_rollback_word(revstate, 0, 0); - lfsr_rollback_word(revstate, nr_enc, 1); - lfsr_rollback_word(revstate, uid ^ nt, 0); - crypto1_get_lfsr(revstate, &key); - printf("\nFound Key: [%012" PRIx64 "]\n\n", key); - crypto1_destroy(revstate); - return 0; + lfsr_rollback_word(revstate, 0, 0); + lfsr_rollback_word(revstate, 0, 0); + lfsr_rollback_word(revstate, nr_enc, 1); + lfsr_rollback_word(revstate, uid ^ nt, 0); + crypto1_get_lfsr(revstate, &key); + printf("\nFound Key: [%012" PRIx64 "]\n\n", key); + crypto1_destroy(revstate); + return 0; } diff --git a/tools/nonce2key/crapto1.c b/tools/nonce2key/crapto1.c index 5412ca8f6..c4701b7e9 100644 --- a/tools/nonce2key/crapto1.c +++ b/tools/nonce2key/crapto1.c @@ -34,65 +34,65 @@ static void __attribute__((constructor)) fill_lut() typedef struct bucket { - uint32_t *head; - uint32_t *bp; + uint32_t *head; + uint32_t *bp; } bucket_t; typedef bucket_t bucket_array_t[2][0x100]; typedef struct bucket_info { - struct { - uint32_t *head, *tail; - } bucket_info[2][0x100]; - uint32_t numbuckets; - } bucket_info_t; + struct { + uint32_t *head, *tail; + } bucket_info[2][0x100]; + uint32_t numbuckets; + } bucket_info_t; static void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop, - uint32_t* const ostart, uint32_t* const ostop, - bucket_info_t *bucket_info, bucket_array_t bucket) + uint32_t* const ostart, uint32_t* const ostop, + bucket_info_t *bucket_info, bucket_array_t bucket) { - uint32_t *p1, *p2; - uint32_t *start[2]; - uint32_t *stop[2]; + uint32_t *p1, *p2; + uint32_t *start[2]; + uint32_t *stop[2]; - start[0] = estart; - stop[0] = estop; - start[1] = ostart; - stop[1] = ostop; + start[0] = estart; + stop[0] = estop; + start[1] = ostart; + stop[1] = ostop; - // init buckets to be empty - for (uint32_t i = 0; i < 2; i++) { - for (uint32_t j = 0x00; j <= 0xff; j++) { - bucket[i][j].bp = bucket[i][j].head; - } - } + // init buckets to be empty + for (uint32_t i = 0; i < 2; i++) { + for (uint32_t j = 0x00; j <= 0xff; j++) { + bucket[i][j].bp = bucket[i][j].head; + } + } - // sort the lists into the buckets based on the MSB (contribution bits) - for (uint32_t i = 0; i < 2; i++) { - for (p1 = start[i]; p1 <= stop[i]; p1++) { - uint32_t bucket_index = (*p1 & 0xff000000) >> 24; - *(bucket[i][bucket_index].bp++) = *p1; - } - } + // sort the lists into the buckets based on the MSB (contribution bits) + for (uint32_t i = 0; i < 2; i++) { + for (p1 = start[i]; p1 <= stop[i]; p1++) { + uint32_t bucket_index = (*p1 & 0xff000000) >> 24; + *(bucket[i][bucket_index].bp++) = *p1; + } + } - // write back intersecting buckets as sorted list. - // fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets. - uint32_t nonempty_bucket; - for (uint32_t i = 0; i < 2; i++) { - p1 = start[i]; - nonempty_bucket = 0; - for (uint32_t j = 0x00; j <= 0xff; j++) { - if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only - bucket_info->bucket_info[i][nonempty_bucket].head = p1; - for (p2 = bucket[i][j].head; p2 < bucket[i][j].bp; *p1++ = *p2++); - bucket_info->bucket_info[i][nonempty_bucket].tail = p1 - 1; - nonempty_bucket++; - } - } - bucket_info->numbuckets = nonempty_bucket; - } + // write back intersecting buckets as sorted list. + // fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets. + uint32_t nonempty_bucket; + for (uint32_t i = 0; i < 2; i++) { + p1 = start[i]; + nonempty_bucket = 0; + for (uint32_t j = 0x00; j <= 0xff; j++) { + if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only + bucket_info->bucket_info[i][nonempty_bucket].head = p1; + for (p2 = bucket[i][j].head; p2 < bucket[i][j].bp; *p1++ = *p2++); + bucket_info->bucket_info[i][nonempty_bucket].tail = p1 - 1; + nonempty_bucket++; + } + } + bucket_info->numbuckets = nonempty_bucket; + } } /** update_contribution @@ -100,11 +100,11 @@ static void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop, */ static inline void update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2) { - uint32_t p = *item >> 25; + uint32_t p = *item >> 25; - p = p << 1 | parity(*item & mask1); - p = p << 1 | parity(*item & mask2); - *item = p << 24 | (*item & 0xffffff); + p = p << 1 | parity(*item & mask1); + p = p << 1 | parity(*item & mask2); + *item = p << 24 | (*item & 0xffffff); } /** extend_table @@ -112,83 +112,83 @@ static inline void update_contribution(uint32_t *item, const uint32_t mask1, con */ static inline void extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in) { - in <<= 24; - for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) - if(filter(*tbl) ^ filter(*tbl | 1)) { - *tbl |= filter(*tbl) ^ bit; - update_contribution(tbl, m1, m2); - *tbl ^= in; - } else if(filter(*tbl) == bit) { - *++*end = tbl[1]; - tbl[1] = tbl[0] | 1; - update_contribution(tbl, m1, m2); - *tbl++ ^= in; - update_contribution(tbl, m1, m2); - *tbl ^= in; - } else - *tbl-- = *(*end)--; + in <<= 24; + for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) + if(filter(*tbl) ^ filter(*tbl | 1)) { + *tbl |= filter(*tbl) ^ bit; + update_contribution(tbl, m1, m2); + *tbl ^= in; + } else if(filter(*tbl) == bit) { + *++*end = tbl[1]; + tbl[1] = tbl[0] | 1; + update_contribution(tbl, m1, m2); + *tbl++ ^= in; + update_contribution(tbl, m1, m2); + *tbl ^= in; + } else + *tbl-- = *(*end)--; } /** extend_table_simple * using a bit of the keystream extend the table of possible lfsr states */ static inline void extend_table_simple(uint32_t *tbl, uint32_t **end, int bit) { - for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) { - if(filter(*tbl) ^ filter(*tbl | 1)) { // replace - *tbl |= filter(*tbl) ^ bit; - } else if(filter(*tbl) == bit) { // insert - *++*end = *++tbl; - *tbl = tbl[-1] | 1; - } else { // drop - *tbl-- = *(*end)--; - } - } + for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) { + if(filter(*tbl) ^ filter(*tbl | 1)) { // replace + *tbl |= filter(*tbl) ^ bit; + } else if(filter(*tbl) == bit) { // insert + *++*end = *++tbl; + *tbl = tbl[-1] | 1; + } else { // drop + *tbl-- = *(*end)--; + } + } } /** recover * recursively narrow down the search space, 4 bits of keystream at a time */ static struct Crypto1State* recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks, - uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem, - struct Crypto1State *sl, uint32_t in, bucket_array_t bucket) + uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem, + struct Crypto1State *sl, uint32_t in, bucket_array_t bucket) { - uint32_t *o, *e; - bucket_info_t bucket_info; + uint32_t *o, *e; + bucket_info_t bucket_info; - if(rem == -1) { - for(e = e_head; e <= e_tail; ++e) { - *e = *e << 1 ^ parity(*e & LF_POLY_EVEN) ^ !!(in & 4); - for(o = o_head; o <= o_tail; ++o, ++sl) { - sl->even = *o; - sl->odd = *e ^ parity(*o & LF_POLY_ODD); - sl[1].odd = sl[1].even = 0; - } - } - return sl; - } + if(rem == -1) { + for(e = e_head; e <= e_tail; ++e) { + *e = *e << 1 ^ parity(*e & LF_POLY_EVEN) ^ !!(in & 4); + for(o = o_head; o <= o_tail; ++o, ++sl) { + sl->even = *o; + sl->odd = *e ^ parity(*o & LF_POLY_ODD); + sl[1].odd = sl[1].even = 0; + } + } + return sl; + } - for(uint32_t i = 0; i < 4 && rem--; i++) { - oks >>= 1; - eks >>= 1; - in >>= 2; - extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0); - if(o_head > o_tail) - return sl; + for(uint32_t i = 0; i < 4 && rem--; i++) { + oks >>= 1; + eks >>= 1; + in >>= 2; + extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0); + if(o_head > o_tail) + return sl; - extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, in & 3); - if(e_head > e_tail) - return sl; - } + extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, in & 3); + if(e_head > e_tail) + return sl; + } - bucket_sort_intersect(e_head, e_tail, o_head, o_tail, &bucket_info, bucket); + bucket_sort_intersect(e_head, e_tail, o_head, o_tail, &bucket_info, bucket); - for (int i = bucket_info.numbuckets - 1; i >= 0; i--) { - sl = recover(bucket_info.bucket_info[1][i].head, bucket_info.bucket_info[1][i].tail, oks, - bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks, - rem, sl, in, bucket); - } + for (int i = bucket_info.numbuckets - 1; i >= 0; i--) { + sl = recover(bucket_info.bucket_info[1][i].head, bucket_info.bucket_info[1][i].tail, oks, + bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks, + rem, sl, in, bucket); + } - return sl; + return sl; } /** lfsr_recovery * recover the state of the lfsr given 32 bits of the keystream @@ -197,87 +197,87 @@ recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks, */ struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in) { - struct Crypto1State *statelist; - uint32_t *odd_head = 0, *odd_tail = 0, oks = 0; - uint32_t *even_head = 0, *even_tail = 0, eks = 0; - int i; + struct Crypto1State *statelist; + uint32_t *odd_head = 0, *odd_tail = 0, oks = 0; + uint32_t *even_head = 0, *even_tail = 0, eks = 0; + int i; - // split the keystream into an odd and even part - for(i = 31; i >= 0; i -= 2) - oks = oks << 1 | BEBIT(ks2, i); - for(i = 30; i >= 0; i -= 2) - eks = eks << 1 | BEBIT(ks2, i); + // split the keystream into an odd and even part + for(i = 31; i >= 0; i -= 2) + oks = oks << 1 | BEBIT(ks2, i); + for(i = 30; i >= 0; i -= 2) + eks = eks << 1 | BEBIT(ks2, i); - odd_head = odd_tail = malloc(sizeof(uint32_t) << 21); - even_head = even_tail = malloc(sizeof(uint32_t) << 21); - statelist = malloc(sizeof(struct Crypto1State) << 18); - if(!odd_tail-- || !even_tail-- || !statelist) { - free(statelist); - statelist = 0; - goto out; - } + odd_head = odd_tail = malloc(sizeof(uint32_t) << 21); + even_head = even_tail = malloc(sizeof(uint32_t) << 21); + statelist = malloc(sizeof(struct Crypto1State) << 18); + if(!odd_tail-- || !even_tail-- || !statelist) { + free(statelist); + statelist = 0; + goto out; + } - statelist->odd = statelist->even = 0; + statelist->odd = statelist->even = 0; - // allocate memory for out of place bucket_sort - bucket_array_t bucket; + // allocate memory for out of place bucket_sort + bucket_array_t bucket; - for (uint32_t i = 0; i < 2; i++) { - for (uint32_t j = 0; j <= 0xff; j++) { - bucket[i][j].head = malloc(sizeof(uint32_t)<<14); - if (!bucket[i][j].head) { - goto out; - } - } - } + for (uint32_t i = 0; i < 2; i++) { + for (uint32_t j = 0; j <= 0xff; j++) { + bucket[i][j].head = malloc(sizeof(uint32_t)<<14); + if (!bucket[i][j].head) { + goto out; + } + } + } - // initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream - for(i = 1 << 20; i >= 0; --i) { - if(filter(i) == (oks & 1)) - *++odd_tail = i; - if(filter(i) == (eks & 1)) - *++even_tail = i; - } + // initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream + for(i = 1 << 20; i >= 0; --i) { + if(filter(i) == (oks & 1)) + *++odd_tail = i; + if(filter(i) == (eks & 1)) + *++even_tail = i; + } - // extend the statelists. Look at the next 8 Bits of the keystream (4 Bit each odd and even): - for(i = 0; i < 4; i++) { - extend_table_simple(odd_head, &odd_tail, (oks >>= 1) & 1); - extend_table_simple(even_head, &even_tail, (eks >>= 1) & 1); - } + // extend the statelists. Look at the next 8 Bits of the keystream (4 Bit each odd and even): + for(i = 0; i < 4; i++) { + extend_table_simple(odd_head, &odd_tail, (oks >>= 1) & 1); + extend_table_simple(even_head, &even_tail, (eks >>= 1) & 1); + } - // the statelists now contain all states which could have generated the last 10 Bits of the keystream. - // 22 bits to go to recover 32 bits in total. From now on, we need to take the "in" - // parameter into account. - in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping - recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket); + // the statelists now contain all states which could have generated the last 10 Bits of the keystream. + // 22 bits to go to recover 32 bits in total. From now on, we need to take the "in" + // parameter into account. + in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping + recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket); out: - for (uint32_t i = 0; i < 2; i++) - for (uint32_t j = 0; j <= 0xff; j++) - free(bucket[i][j].head); - free(odd_head); - free(even_head); - return statelist; + for (uint32_t i = 0; i < 2; i++) + for (uint32_t j = 0; j <= 0xff; j++) + free(bucket[i][j].head); + free(odd_head); + free(even_head); + return statelist; } static const uint32_t S1[] = { 0x62141, 0x310A0, 0x18850, 0x0C428, 0x06214, - 0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83, - 0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA}; + 0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83, + 0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA}; static const uint32_t S2[] = { 0x3A557B00, 0x5D2ABD80, 0x2E955EC0, 0x174AAF60, - 0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8, - 0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20, - 0x7EC7EE90, 0x7F63F748, 0x79117020}; + 0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8, + 0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20, + 0x7EC7EE90, 0x7F63F748, 0x79117020}; static const uint32_t T1[] = { - 0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66, - 0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B, - 0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615, - 0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C}; + 0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66, + 0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B, + 0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615, + 0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C}; static const uint32_t T2[] = { 0x3C88B810, 0x5E445C08, 0x2982A580, 0x14C152C0, - 0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268, - 0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0, - 0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0, - 0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950, - 0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0}; + 0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268, + 0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0, + 0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0, + 0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950, + 0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0}; static const uint32_t C1[] = { 0x846B5, 0x4235A, 0x211AD}; static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0}; /** Reverse 64 bits of keystream into possible cipher states @@ -285,69 +285,69 @@ static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0}; */ struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3) { - struct Crypto1State *statelist, *sl; - uint8_t oks[32], eks[32], hi[32]; - uint32_t low = 0, win = 0; - uint32_t *tail, table[1 << 16]; - int i, j; + struct Crypto1State *statelist, *sl; + uint8_t oks[32], eks[32], hi[32]; + uint32_t low = 0, win = 0; + uint32_t *tail, table[1 << 16]; + int i, j; - sl = statelist = malloc(sizeof(struct Crypto1State) << 4); - if(!sl) - return 0; - sl->odd = sl->even = 0; + sl = statelist = malloc(sizeof(struct Crypto1State) << 4); + if(!sl) + return 0; + sl->odd = sl->even = 0; - for(i = 30; i >= 0; i -= 2) { - oks[i >> 1] = BEBIT(ks2, i); - oks[16 + (i >> 1)] = BEBIT(ks3, i); - } - for(i = 31; i >= 0; i -= 2) { - eks[i >> 1] = BEBIT(ks2, i); - eks[16 + (i >> 1)] = BEBIT(ks3, i); - } + for(i = 30; i >= 0; i -= 2) { + oks[i >> 1] = BEBIT(ks2, i); + oks[16 + (i >> 1)] = BEBIT(ks3, i); + } + for(i = 31; i >= 0; i -= 2) { + eks[i >> 1] = BEBIT(ks2, i); + eks[16 + (i >> 1)] = BEBIT(ks3, i); + } - for(i = 0xfffff; i >= 0; --i) { - if (filter(i) != oks[0]) - continue; + for(i = 0xfffff; i >= 0; --i) { + if (filter(i) != oks[0]) + continue; - *(tail = table) = i; - for(j = 1; tail >= table && j < 29; ++j) - extend_table_simple(table, &tail, oks[j]); + *(tail = table) = i; + for(j = 1; tail >= table && j < 29; ++j) + extend_table_simple(table, &tail, oks[j]); - if(tail < table) - continue; + if(tail < table) + continue; - for(j = 0; j < 19; ++j) - low = low << 1 | parity(i & S1[j]); - for(j = 0; j < 32; ++j) - hi[j] = parity(i & T1[j]); + for(j = 0; j < 19; ++j) + low = low << 1 | parity(i & S1[j]); + for(j = 0; j < 32; ++j) + hi[j] = parity(i & T1[j]); - for(; tail >= table; --tail) { - for(j = 0; j < 3; ++j) { - *tail = *tail << 1; - *tail |= parity((i & C1[j]) ^ (*tail & C2[j])); - if(filter(*tail) != oks[29 + j]) - goto continue2; - } + for(; tail >= table; --tail) { + for(j = 0; j < 3; ++j) { + *tail = *tail << 1; + *tail |= parity((i & C1[j]) ^ (*tail & C2[j])); + if(filter(*tail) != oks[29 + j]) + goto continue2; + } - for(j = 0; j < 19; ++j) - win = win << 1 | parity(*tail & S2[j]); + for(j = 0; j < 19; ++j) + win = win << 1 | parity(*tail & S2[j]); - win ^= low; - for(j = 0; j < 32; ++j) { - win = win << 1 ^ hi[j] ^ parity(*tail & T2[j]); - if(filter(win) != eks[j]) - goto continue2; - } + win ^= low; + for(j = 0; j < 32; ++j) { + win = win << 1 ^ hi[j] ^ parity(*tail & T2[j]); + if(filter(win) != eks[j]) + goto continue2; + } - *tail = *tail << 1 | parity(LF_POLY_EVEN & *tail); - sl->odd = *tail ^ parity(LF_POLY_ODD & win); - sl->even = win; - ++sl; - sl->odd = sl->even = 0; - continue2:; - } - } - return statelist; + *tail = *tail << 1 | parity(LF_POLY_EVEN & *tail); + sl->odd = *tail ^ parity(LF_POLY_ODD & win); + sl->even = win; + ++sl; + sl->odd = sl->even = 0; + continue2:; + } + } + return statelist; } /** lfsr_rollback_bit @@ -355,93 +355,93 @@ struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3) */ uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb) { - int out; - uint8_t ret; - uint32_t t; + int out; + uint8_t ret; + uint32_t t; - s->odd &= 0xffffff; - t = s->odd, s->odd = s->even, s->even = t; + s->odd &= 0xffffff; + t = s->odd, s->odd = s->even, s->even = t; - out = s->even & 1; - out ^= LF_POLY_EVEN & (s->even >>= 1); - out ^= LF_POLY_ODD & s->odd; - out ^= !!in; - out ^= (ret = filter(s->odd)) & !!fb; + out = s->even & 1; + out ^= LF_POLY_EVEN & (s->even >>= 1); + out ^= LF_POLY_ODD & s->odd; + out ^= !!in; + out ^= (ret = filter(s->odd)) & !!fb; - s->even |= parity(out) << 23; - return ret; + s->even |= parity(out) << 23; + return ret; } /** lfsr_rollback_byte * Rollback the shift register in order to get previous states */ uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb) { - /* - int i, ret = 0; - for (i = 7; i >= 0; --i) - ret |= lfsr_rollback_bit(s, BIT(in, i), fb) << i; + /* + int i, ret = 0; + for (i = 7; i >= 0; --i) + ret |= lfsr_rollback_bit(s, BIT(in, i), fb) << i; */ // unfold loop 20160112 - uint8_t ret = 0; - ret |= lfsr_rollback_bit(s, BIT(in, 7), fb) << 7; - ret |= lfsr_rollback_bit(s, BIT(in, 6), fb) << 6; - ret |= lfsr_rollback_bit(s, BIT(in, 5), fb) << 5; - ret |= lfsr_rollback_bit(s, BIT(in, 4), fb) << 4; - ret |= lfsr_rollback_bit(s, BIT(in, 3), fb) << 3; - ret |= lfsr_rollback_bit(s, BIT(in, 2), fb) << 2; - ret |= lfsr_rollback_bit(s, BIT(in, 1), fb) << 1; - ret |= lfsr_rollback_bit(s, BIT(in, 0), fb) << 0; - return ret; + uint8_t ret = 0; + ret |= lfsr_rollback_bit(s, BIT(in, 7), fb) << 7; + ret |= lfsr_rollback_bit(s, BIT(in, 6), fb) << 6; + ret |= lfsr_rollback_bit(s, BIT(in, 5), fb) << 5; + ret |= lfsr_rollback_bit(s, BIT(in, 4), fb) << 4; + ret |= lfsr_rollback_bit(s, BIT(in, 3), fb) << 3; + ret |= lfsr_rollback_bit(s, BIT(in, 2), fb) << 2; + ret |= lfsr_rollback_bit(s, BIT(in, 1), fb) << 1; + ret |= lfsr_rollback_bit(s, BIT(in, 0), fb) << 0; + return ret; } /** lfsr_rollback_word * Rollback the shift register in order to get previous states */ uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) { - /* - int i; - uint32_t ret = 0; - for (i = 31; i >= 0; --i) - ret |= lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24); + /* + int i; + uint32_t ret = 0; + for (i = 31; i >= 0; --i) + ret |= lfsr_rollback_bit(s, BEBIT(in, i), fb) << (i ^ 24); */ // unfold loop 20160112 - uint32_t ret = 0; - ret |= lfsr_rollback_bit(s, BEBIT(in, 31), fb) << (31 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 30), fb) << (30 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 29), fb) << (29 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 28), fb) << (28 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 27), fb) << (27 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 26), fb) << (26 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 25), fb) << (25 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 24), fb) << (24 ^ 24); + uint32_t ret = 0; + ret |= lfsr_rollback_bit(s, BEBIT(in, 31), fb) << (31 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 30), fb) << (30 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 29), fb) << (29 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 28), fb) << (28 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 27), fb) << (27 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 26), fb) << (26 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 25), fb) << (25 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 24), fb) << (24 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 23), fb) << (23 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 22), fb) << (22 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 21), fb) << (21 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 20), fb) << (20 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 19), fb) << (19 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 18), fb) << (18 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 17), fb) << (17 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 16), fb) << (16 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 23), fb) << (23 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 22), fb) << (22 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 21), fb) << (21 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 20), fb) << (20 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 19), fb) << (19 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 18), fb) << (18 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 17), fb) << (17 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 16), fb) << (16 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 15), fb) << (15 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 14), fb) << (14 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 13), fb) << (13 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 12), fb) << (12 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 11), fb) << (11 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 10), fb) << (10 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 9), fb) << (9 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 8), fb) << (8 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 15), fb) << (15 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 14), fb) << (14 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 13), fb) << (13 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 12), fb) << (12 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 11), fb) << (11 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 10), fb) << (10 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 9), fb) << (9 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 8), fb) << (8 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 7), fb) << (7 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 6), fb) << (6 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 5), fb) << (5 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 4), fb) << (4 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 3), fb) << (3 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 2), fb) << (2 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 1), fb) << (1 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 0), fb) << (0 ^ 24); - return ret; + ret |= lfsr_rollback_bit(s, BEBIT(in, 7), fb) << (7 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 6), fb) << (6 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 5), fb) << (5 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 4), fb) << (4 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 3), fb) << (3 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 2), fb) << (2 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 1), fb) << (1 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 0), fb) << (0 ^ 24); + return ret; } /** nonce_distance @@ -450,23 +450,23 @@ uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) static uint16_t *dist = 0; int nonce_distance(uint32_t from, uint32_t to) { - uint16_t x, i; - if(!dist) { - dist = malloc(2 << 16); - if(!dist) - return -1; - for (x = i = 1; i; ++i) { - dist[(x & 0xff) << 8 | x >> 8] = i; - x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; - } - } - return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535; + uint16_t x, i; + if(!dist) { + dist = malloc(2 << 16); + if(!dist) + return -1; + for (x = i = 1; i; ++i) { + dist[(x & 0xff) << 8 | x >> 8] = i; + x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; + } + } + return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535; } static uint32_t fastfwd[2][8] = { - { 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB}, - { 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}}; + { 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB}, + { 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}}; /** lfsr_prefix_ks @@ -480,25 +480,25 @@ static uint32_t fastfwd[2][8] = { */ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) { - uint32_t *candidates = malloc(4 << 10); - if(!candidates) return 0; + uint32_t *candidates = malloc(4 << 10); + if(!candidates) return 0; - uint32_t c, entry; - int size = 0, i, good; + uint32_t c, entry; + int size = 0, i, good; - for(i = 0; i < 1 << 21; ++i) { - for(c = 0, good = 1; good && c < 8; ++c) { - entry = i ^ fastfwd[isodd][c]; - good &= (BIT(ks[c], isodd) == filter(entry >> 1)); - good &= (BIT(ks[c], isodd + 2) == filter(entry)); - } - if(good) - candidates[size++] = i; - } + for(i = 0; i < 1 << 21; ++i) { + for(c = 0, good = 1; good && c < 8; ++c) { + entry = i ^ fastfwd[isodd][c]; + good &= (BIT(ks[c], isodd) == filter(entry >> 1)); + good &= (BIT(ks[c], isodd + 2) == filter(entry)); + } + if(good) + candidates[size++] = i; + } - candidates[size] = -1; + candidates[size] = -1; - return candidates; + return candidates; } /** check_pfx_parity @@ -506,30 +506,30 @@ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) */ static struct Crypto1State* check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8], uint32_t odd, uint32_t even, struct Crypto1State* sl) { - uint32_t ks1, nr, ks2, rr, ks3, c, good = 1; + uint32_t ks1, nr, ks2, rr, ks3, c, good = 1; - for(c = 0; good && c < 8; ++c) { - sl->odd = odd ^ fastfwd[1][c]; - sl->even = even ^ fastfwd[0][c]; + for(c = 0; good && c < 8; ++c) { + sl->odd = odd ^ fastfwd[1][c]; + sl->even = even ^ fastfwd[0][c]; - lfsr_rollback_bit(sl, 0, 0); - lfsr_rollback_bit(sl, 0, 0); + lfsr_rollback_bit(sl, 0, 0); + lfsr_rollback_bit(sl, 0, 0); - ks3 = lfsr_rollback_bit(sl, 0, 0); - ks2 = lfsr_rollback_word(sl, 0, 0); - ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1); + ks3 = lfsr_rollback_bit(sl, 0, 0); + ks2 = lfsr_rollback_word(sl, 0, 0); + ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1); - nr = ks1 ^ (prefix | c << 5); - rr = ks2 ^ rresp; + nr = ks1 ^ (prefix | c << 5); + rr = ks2 ^ rresp; - good &= parity(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); - good &= parity(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); - good &= parity(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8); - good &= parity(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0); - good &= parity(rr & 0x000000ff) ^ parities[c][7] ^ ks3; - } + good &= parity(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); + good &= parity(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); + good &= parity(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8); + good &= parity(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0); + good &= parity(rr & 0x000000ff) ^ parities[c][7] ^ ks3; + } - return sl + good; + return sl + good; } /** lfsr_common_prefix @@ -544,30 +544,30 @@ static struct Crypto1State* check_pfx_parity(uint32_t prefix, uint32_t rresp, ui struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8]) { - struct Crypto1State *statelist, *s; - uint32_t *odd, *even, *o, *e, top; + struct Crypto1State *statelist, *s; + uint32_t *odd, *even, *o, *e, top; - odd = lfsr_prefix_ks(ks, 1); - even = lfsr_prefix_ks(ks, 0); + odd = lfsr_prefix_ks(ks, 1); + even = lfsr_prefix_ks(ks, 0); - s = statelist = malloc((sizeof *statelist) << 20); - if(!s || !odd || !even) { - free(statelist); - statelist = 0; + s = statelist = malloc((sizeof *statelist) << 20); + if(!s || !odd || !even) { + free(statelist); + statelist = 0; goto out; - } + } - for(o = odd; *o + 1; ++o) - for(e = even; *e + 1; ++e) - for(top = 0; top < 64; ++top) { - *o += 1 << 21; - *e += (!(top & 7) + 1) << 21; - s = check_pfx_parity(pfx, rr, par, *o, *e, s); - } + for(o = odd; *o + 1; ++o) + for(e = even; *e + 1; ++e) + for(top = 0; top < 64; ++top) { + *o += 1 << 21; + *e += (!(top & 7) + 1) << 21; + s = check_pfx_parity(pfx, rr, par, *o, *e, s); + } - s->odd = s->even = 0; + s->odd = s->even = 0; out: - free(odd); - free(even); - return statelist; + free(odd); + free(even); + return statelist; } diff --git a/tools/nonce2key/crapto1.h b/tools/nonce2key/crapto1.h index 2fd6600ec..4117dd6a1 100644 --- a/tools/nonce2key/crapto1.h +++ b/tools/nonce2key/crapto1.h @@ -43,18 +43,18 @@ uint8_t lfsr_rollback_byte(struct Crypto1State* s, uint32_t in, int fb); uint32_t lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb); int nonce_distance(uint32_t from, uint32_t to); #define SWAPENDIAN(x)\ - (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) + (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) #define FOREACH_VALID_NONCE(N, FILTER, FSIZE)\ - uint32_t __n = 0,__M = 0, N = 0;\ - int __i;\ - for(; __n < 1 << 16; N = prng_successor(__M = ++__n, 16))\ - for(__i = FSIZE - 1; __i >= 0; __i--)\ - if(BIT(FILTER, __i) ^ parity(__M & 0xFF01))\ - break;\ - else if(__i)\ - __M = prng_successor(__M, (__i == 7) ? 48 : 8);\ - else + uint32_t __n = 0,__M = 0, N = 0;\ + int __i;\ + for(; __n < 1 << 16; N = prng_successor(__M = ++__n, 16))\ + for(__i = FSIZE - 1; __i >= 0; __i--)\ + if(BIT(FILTER, __i) ^ parity(__M & 0xFF01))\ + break;\ + else if(__i)\ + __M = prng_successor(__M, (__i == 7) ? 48 : 8);\ + else #define LF_POLY_ODD (0x29CE5C) #define LF_POLY_EVEN (0x870804) @@ -63,31 +63,31 @@ int nonce_distance(uint32_t from, uint32_t to); static inline int parity(uint32_t x) { #if !defined __i386__ || !defined __GNUC__ - x ^= x >> 16; - x ^= x >> 8; - x ^= x >> 4; - return BIT(0x6996, x & 0xf); + x ^= x >> 16; + x ^= x >> 8; + x ^= x >> 4; + return BIT(0x6996, x & 0xf); #else __asm__( "movl %1, %%eax\n" - "mov %%ax, %%cx\n" - "shrl $0x10, %%eax\n" - "xor %%ax, %%cx\n" + "mov %%ax, %%cx\n" + "shrl $0x10, %%eax\n" + "xor %%ax, %%cx\n" "xor %%ch, %%cl\n" "setpo %%al\n" "movzx %%al, %0\n": "=r"(x) : "r"(x): "eax","ecx"); - return x; + return x; #endif } static inline int filter(uint32_t const x) { - uint32_t f; + uint32_t f; - f = 0xf22c0 >> (x & 0xf) & 16; - f |= 0x6c9c0 >> (x >> 4 & 0xf) & 8; - f |= 0x3c8b0 >> (x >> 8 & 0xf) & 4; - f |= 0x1e458 >> (x >> 12 & 0xf) & 2; - f |= 0x0d938 >> (x >> 16 & 0xf) & 1; - return BIT(0xEC57E80A, f); + f = 0xf22c0 >> (x & 0xf) & 16; + f |= 0x6c9c0 >> (x >> 4 & 0xf) & 8; + f |= 0x3c8b0 >> (x >> 8 & 0xf) & 4; + f |= 0x1e458 >> (x >> 12 & 0xf) & 2; + f |= 0x0d938 >> (x >> 16 & 0xf) & 1; + return BIT(0xEC57E80A, f); } #ifdef __cplusplus } diff --git a/tools/nonce2key/crypto1.c b/tools/nonce2key/crypto1.c index 14e2cc829..e8384c16a 100644 --- a/tools/nonce2key/crypto1.c +++ b/tools/nonce2key/crypto1.c @@ -22,115 +22,115 @@ struct Crypto1State * crypto1_create(uint64_t key) { - struct Crypto1State *s = malloc(sizeof(*s)); - if ( !s ) return NULL; + struct Crypto1State *s = malloc(sizeof(*s)); + if ( !s ) return NULL; - s->odd = s->even = 0; + s->odd = s->even = 0; - int i; - //for(i = 47;s && i > 0; i -= 2) { - for(i = 47; i > 0; i -= 2) { - s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7); - s->even = s->even << 1 | BIT(key, i ^ 7); - } - return s; + int i; + //for(i = 47;s && i > 0; i -= 2) { + for(i = 47; i > 0; i -= 2) { + s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7); + s->even = s->even << 1 | BIT(key, i ^ 7); + } + return s; } void crypto1_destroy(struct Crypto1State *state) { - free(state); + free(state); } void crypto1_get_lfsr(struct Crypto1State *state, uint64_t *lfsr) { - int i; - for(*lfsr = 0, i = 23; i >= 0; --i) { - *lfsr = *lfsr << 1 | BIT(state->odd, i ^ 3); - *lfsr = *lfsr << 1 | BIT(state->even, i ^ 3); - } + int i; + for(*lfsr = 0, i = 23; i >= 0; --i) { + *lfsr = *lfsr << 1 | BIT(state->odd, i ^ 3); + *lfsr = *lfsr << 1 | BIT(state->even, i ^ 3); + } } uint8_t crypto1_bit(struct Crypto1State *s, uint8_t in, int is_encrypted) { - uint32_t feedin; - uint32_t tmp; - uint8_t ret = filter(s->odd); + uint32_t feedin; + uint32_t tmp; + uint8_t ret = filter(s->odd); - feedin = ret & !!is_encrypted; - feedin ^= !!in; - feedin ^= LF_POLY_ODD & s->odd; - feedin ^= LF_POLY_EVEN & s->even; - s->even = s->even << 1 | parity(feedin); + feedin = ret & !!is_encrypted; + feedin ^= !!in; + feedin ^= LF_POLY_ODD & s->odd; + feedin ^= LF_POLY_EVEN & s->even; + s->even = s->even << 1 | parity(feedin); - tmp = s->odd; - s->odd = s->even; - s->even = tmp; + tmp = s->odd; + s->odd = s->even; + s->even = tmp; - return ret; + return ret; } uint8_t crypto1_byte(struct Crypto1State *s, uint8_t in, int is_encrypted) { - /* - uint8_t i, ret = 0; + /* + uint8_t i, ret = 0; - for (i = 0; i < 8; ++i) - ret |= crypto1_bit(s, BIT(in, i), is_encrypted) << i; - */ + for (i = 0; i < 8; ++i) + ret |= crypto1_bit(s, BIT(in, i), is_encrypted) << i; + */ // unfold loop 20161012 - uint8_t ret = 0; - ret |= crypto1_bit(s, BIT(in, 0), is_encrypted) << 0; - ret |= crypto1_bit(s, BIT(in, 1), is_encrypted) << 1; - ret |= crypto1_bit(s, BIT(in, 2), is_encrypted) << 2; - ret |= crypto1_bit(s, BIT(in, 3), is_encrypted) << 3; - ret |= crypto1_bit(s, BIT(in, 4), is_encrypted) << 4; - ret |= crypto1_bit(s, BIT(in, 5), is_encrypted) << 5; - ret |= crypto1_bit(s, BIT(in, 6), is_encrypted) << 6; - ret |= crypto1_bit(s, BIT(in, 7), is_encrypted) << 7; - return ret; + uint8_t ret = 0; + ret |= crypto1_bit(s, BIT(in, 0), is_encrypted) << 0; + ret |= crypto1_bit(s, BIT(in, 1), is_encrypted) << 1; + ret |= crypto1_bit(s, BIT(in, 2), is_encrypted) << 2; + ret |= crypto1_bit(s, BIT(in, 3), is_encrypted) << 3; + ret |= crypto1_bit(s, BIT(in, 4), is_encrypted) << 4; + ret |= crypto1_bit(s, BIT(in, 5), is_encrypted) << 5; + ret |= crypto1_bit(s, BIT(in, 6), is_encrypted) << 6; + ret |= crypto1_bit(s, BIT(in, 7), is_encrypted) << 7; + return ret; } uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) { - /* - uint32_t i, ret = 0; + /* + uint32_t i, ret = 0; - for (i = 0; i < 32; ++i) - ret |= crypto1_bit(s, BEBIT(in, i), is_encrypted) << (i ^ 24); + for (i = 0; i < 32; ++i) + ret |= crypto1_bit(s, BEBIT(in, i), is_encrypted) << (i ^ 24); */ //unfold loop 2016012 - uint32_t ret = 0; - ret |= crypto1_bit(s, BEBIT(in, 0), is_encrypted) << (0 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 1), is_encrypted) << (1 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 2), is_encrypted) << (2 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 3), is_encrypted) << (3 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 4), is_encrypted) << (4 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 5), is_encrypted) << (5 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 6), is_encrypted) << (6 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 7), is_encrypted) << (7 ^ 24); + uint32_t ret = 0; + ret |= crypto1_bit(s, BEBIT(in, 0), is_encrypted) << (0 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 1), is_encrypted) << (1 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 2), is_encrypted) << (2 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 3), is_encrypted) << (3 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 4), is_encrypted) << (4 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 5), is_encrypted) << (5 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 6), is_encrypted) << (6 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 7), is_encrypted) << (7 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 8), is_encrypted) << (8 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 9), is_encrypted) << (9 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 10), is_encrypted) << (10 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 11), is_encrypted) << (11 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 12), is_encrypted) << (12 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 13), is_encrypted) << (13 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 14), is_encrypted) << (14 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 15), is_encrypted) << (15 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 8), is_encrypted) << (8 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 9), is_encrypted) << (9 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 10), is_encrypted) << (10 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 11), is_encrypted) << (11 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 12), is_encrypted) << (12 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 13), is_encrypted) << (13 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 14), is_encrypted) << (14 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 15), is_encrypted) << (15 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 16), is_encrypted) << (16 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 17), is_encrypted) << (17 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 18), is_encrypted) << (18 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 19), is_encrypted) << (19 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 20), is_encrypted) << (20 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 21), is_encrypted) << (21 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 22), is_encrypted) << (22 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 23), is_encrypted) << (23 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 16), is_encrypted) << (16 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 17), is_encrypted) << (17 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 18), is_encrypted) << (18 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 19), is_encrypted) << (19 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 20), is_encrypted) << (20 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 21), is_encrypted) << (21 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 22), is_encrypted) << (22 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 23), is_encrypted) << (23 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 24), is_encrypted) << (24 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 25), is_encrypted) << (25 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 26), is_encrypted) << (26 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 27), is_encrypted) << (27 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 28), is_encrypted) << (28 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 29), is_encrypted) << (29 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 30), is_encrypted) << (30 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 31), is_encrypted) << (31 ^ 24); - return ret; + ret |= crypto1_bit(s, BEBIT(in, 24), is_encrypted) << (24 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 25), is_encrypted) << (25 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 26), is_encrypted) << (26 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 27), is_encrypted) << (27 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 28), is_encrypted) << (28 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 29), is_encrypted) << (29 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 30), is_encrypted) << (30 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 31), is_encrypted) << (31 ^ 24); + return ret; } /* prng_successor @@ -138,9 +138,9 @@ uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) */ uint32_t prng_successor(uint32_t x, uint32_t n) { - SWAPENDIAN(x); - while(n--) - x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; + SWAPENDIAN(x); + while(n--) + x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; - return SWAPENDIAN(x); + return SWAPENDIAN(x); } diff --git a/tools/nonce2key/nonce2key.c b/tools/nonce2key/nonce2key.c index f7bbc43b7..52b7998ae 100644 --- a/tools/nonce2key/nonce2key.c +++ b/tools/nonce2key/nonce2key.c @@ -4,54 +4,54 @@ #include int main(const int argc, const char* argv[]) { - struct Crypto1State *state; - uint32_t pos, uid, nt, nr, rr, nr_diff; - uint8_t bt, i, ks3x[8], par[8][8]; - uint64_t key_recovered; - uint64_t par_info; - uint64_t ks_info; - nr = rr = 0; + struct Crypto1State *state; + uint32_t pos, uid, nt, nr, rr, nr_diff; + uint8_t bt, i, ks3x[8], par[8][8]; + uint64_t key_recovered; + uint64_t par_info; + uint64_t ks_info; + nr = rr = 0; - if (argc < 5) { - printf("\nsyntax: %s \n\n",argv[0]); - return 1; - } - sscanf(argv[1],"%08x", &uid); - sscanf(argv[2],"%08x", &nt); - sscanf(argv[3],"%016" SCNx64 ,&par_info); - sscanf(argv[4],"%016" SCNx64 ,&ks_info); + if (argc < 5) { + printf("\nsyntax: %s \n\n",argv[0]); + return 1; + } + sscanf(argv[1],"%08x", &uid); + sscanf(argv[2],"%08x", &nt); + sscanf(argv[3],"%016" SCNx64 ,&par_info); + sscanf(argv[4],"%016" SCNx64 ,&ks_info); - // Reset the last three significant bits of the reader nonce - nr &= 0xffffff1f; + // Reset the last three significant bits of the reader nonce + nr &= 0xffffff1f; - printf("\nuid(%08x) nt(%08x) par(%016" PRIx64 ") ks(%016" PRIx64 ")\n\n", uid, nt, par_info, ks_info); + printf("\nuid(%08x) nt(%08x) par(%016" PRIx64 ") ks(%016" PRIx64 ")\n\n", uid, nt, par_info, ks_info); - for ( pos = 0; pos < 8; pos++ ) { - ks3x[7-pos] = (ks_info >> (pos*8)) & 0x0f; - bt = (par_info >> (pos*8)) & 0xff; + 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 ( i = 0; i < 8; i++) { + par[7-pos][i] = (bt >> i) & 0x01; + } + } - printf("|diff|{nr} |ks3|ks3^5|parity |\n"); - 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| %01x | %01x |", i << 5, nr_diff, ks3x[i], ks3x[i]^5); + for ( i = 0; i < 8; i++) { + nr_diff = nr | i << 5; + printf("| %02x |%08x| %01x | %01x |", i << 5, nr_diff, ks3x[i], ks3x[i]^5); - for ( pos = 0; pos < 7; pos++) - printf("%01x,", par[i][pos]); - printf("%01x|\n", par[i][7]); - } - printf("+----+--------+---+-----+---------------+\n"); + for ( pos = 0; pos < 7; pos++) + printf("%01x,", par[i][pos]); + printf("%01x|\n", par[i][7]); + } + printf("+----+--------+---+-----+---------------+\n"); - state = lfsr_common_prefix(nr,rr,ks3x,par); - lfsr_rollback_word(state,uid^nt,0); - crypto1_get_lfsr(state,&key_recovered); - printf("\nkey recovered: %012" PRIx64 "\n\n", key_recovered); - crypto1_destroy(state); - return 0; + state = lfsr_common_prefix(nr,rr,ks3x,par); + lfsr_rollback_word(state,uid^nt,0); + crypto1_get_lfsr(state,&key_recovered); + printf("\nkey recovered: %012" PRIx64 "\n\n", key_recovered); + crypto1_destroy(state); + return 0; } From bcb33ca5ef5336013998d6530c0f739780fdaaa4 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 10:52:45 +0100 Subject: [PATCH 0687/1938] tools scripts: fix mix of spaces & tabs --- tools/findbits.py | 110 +++++++++++++++++++-------------------- tools/findbits_test.py | 94 ++++++++++++++++----------------- tools/install-gnuarm4.sh | 6 +-- tools/mkversion.pl | 50 +++++++++--------- tools/rfidtest.pl | 94 ++++++++++++++++----------------- tools/srecswap.pl | 38 +++++++------- tools/xorcheck.py | 36 ++++++------- 7 files changed, 214 insertions(+), 214 deletions(-) diff --git a/tools/findbits.py b/tools/findbits.py index 501d23019..fb088d739 100755 --- a/tools/findbits.py +++ b/tools/findbits.py @@ -25,77 +25,77 @@ import os # invert binary string def invert(data): - return ''.join('0' if c == '1' else '1' for c in data) + return ''.join('0' if c == '1' else '1' for c in data) # do the actual search def search(target,data): - location = data.find(target) - if location >= 0: - print '*** Match at bit %d:' % location, - print '%s<%s>%s' % (data[:location],target,data[location+len(target):]) - else: - print 'Not found' + location = data.find(target) + if location >= 0: + print '*** Match at bit %d:' % location, + print '%s<%s>%s' % (data[:location],target,data[location+len(target):]) + else: + print 'Not found' # convert integer to binary string def binstring(number): - return bin(number)[2:] if number > 0 else '' + return bin(number)[2:] if number > 0 else '' # reverse string order def stringreverse(data): - return data[::-1] + return data[::-1] # match forward, backward and inverted def domatch(binary,number): - reversed= stringreverse(number) - inverted= invert(binary) + reversed= stringreverse(number) + inverted= invert(binary) - print ' Forward: (%s)' % number, - search(binary,number) - print ' Reverse: (%s)' % reversed, - search(binary,reversed) - print ' Inverse: (%s)' % inverted - print ' Forward: (%s)' % number, - search(inverted,number) - print ' Reverse: (%s)' % reversed, - search(inverted,reversed) + print ' Forward: (%s)' % number, + search(binary,number) + print ' Reverse: (%s)' % reversed, + search(binary,reversed) + print ' Inverse: (%s)' % inverted + print ' Forward: (%s)' % number, + search(inverted,number) + print ' Reverse: (%s)' % reversed, + search(inverted,reversed) def main(): - if(len(sys.argv) < 3): - print - print '\t'+sys.argv[0] + ' - Search bitstream for a known number' - print - print 'Usage: ' + sys.argv[0] + ' ' - print - print '\tNUMBER will be converted to it\'s BINARY equivalent for all valid' - print '\tinstances of BINARY, OCTAL, DECIMAL and HEX, and the bitstream' - print '\tand it\'s inverse will be searched for a pattern match. Note that' - print '\tNUMBER must be specified in BINARY to match leading zeros.' - print - print 'Example:' - print - print '\tfindbits.py 73 0110010101110011' - print - os._exit(True) + if(len(sys.argv) < 3): + print + print '\t'+sys.argv[0] + ' - Search bitstream for a known number' + print + print 'Usage: ' + sys.argv[0] + ' ' + print + print '\tNUMBER will be converted to it\'s BINARY equivalent for all valid' + print '\tinstances of BINARY, OCTAL, DECIMAL and HEX, and the bitstream' + print '\tand it\'s inverse will be searched for a pattern match. Note that' + print '\tNUMBER must be specified in BINARY to match leading zeros.' + print + print 'Example:' + print + print '\tfindbits.py 73 0110010101110011' + print + os._exit(True) - bases= { - 2:'BINARY', - 8:'OCTAL', - 10:'DECIMAL', - 16:'HEX', - } + bases= { + 2:'BINARY', + 8:'OCTAL', + 10:'DECIMAL', + 16:'HEX', + } - for base, base_name in sorted(bases.iteritems()): - try: - number= int(sys.argv[1],base) - print - print 'Trying', base_name - # do BINARY as specified to preserve leading zeros - if base == 2: - domatch(sys.argv[1],sys.argv[2]) - else: - domatch(binstring(number),sys.argv[2]) - except: - continue + for base, base_name in sorted(bases.iteritems()): + try: + number= int(sys.argv[1],base) + print + print 'Trying', base_name + # do BINARY as specified to preserve leading zeros + if base == 2: + domatch(sys.argv[1],sys.argv[2]) + else: + domatch(binstring(number),sys.argv[2]) + except: + continue if __name__ == '__main__': - main() + main() diff --git a/tools/findbits_test.py b/tools/findbits_test.py index 3288cb35b..4415ce726 100644 --- a/tools/findbits_test.py +++ b/tools/findbits_test.py @@ -4,65 +4,65 @@ from itertools import imap import unittest, sys, findbits class TestFindBits(unittest.TestCase): - def setUp(self): - self.old_stdout = sys.stdout - sys.stdout = OutputBuffer() + def setUp(self): + self.old_stdout = sys.stdout + sys.stdout = OutputBuffer() - def tearDown(self): - sys.stdout = self.old_stdout + def tearDown(self): + sys.stdout = self.old_stdout - INVERT_CASES = [ - ('10', '01'), - ('', ''), - ] - def test_invert(self): - self.commutative_test(findbits.invert, self.INVERT_CASES) + INVERT_CASES = [ + ('10', '01'), + ('', ''), + ] + def test_invert(self): + self.commutative_test(findbits.invert, self.INVERT_CASES) - SEARCH_CASES = [ - ('1111', '10111101', ['Match at bit 2', '0<1111>0']), - ('00', '10111101', ['Not found']), - ] - def test_search(self): - for target, data, expected_fragments in self.SEARCH_CASES: - sys.stdout.clear_buffer() - findbits.search(target, data) - for fragment in expected_fragments: - self.assertIn(fragment, sys.stdout.content) + SEARCH_CASES = [ + ('1111', '10111101', ['Match at bit 2', '0<1111>0']), + ('00', '10111101', ['Not found']), + ] + def test_search(self): + for target, data, expected_fragments in self.SEARCH_CASES: + sys.stdout.clear_buffer() + findbits.search(target, data) + for fragment in expected_fragments: + self.assertIn(fragment, sys.stdout.content) - BINSTRING_CASES = [ - (42, '101010'), - (1, '1'), - (0, ''), - ] - def test_binstring(self): - self.unary_operation_test(findbits.binstring, self.BINSTRING_CASES) + BINSTRING_CASES = [ + (42, '101010'), + (1, '1'), + (0, ''), + ] + def test_binstring(self): + self.unary_operation_test(findbits.binstring, self.BINSTRING_CASES) - REVERSE_CASES = [ - ('abc', 'cba'), - ('', ''), - ] - def test_stringreverse(self): - self.commutative_test(findbits.stringreverse, self.REVERSE_CASES) + REVERSE_CASES = [ + ('abc', 'cba'), + ('', ''), + ] + def test_stringreverse(self): + self.commutative_test(findbits.stringreverse, self.REVERSE_CASES) - def commutative_test(self, operation, cases): - self.unary_operation_test(operation, cases) - self.unary_operation_test(operation, imap(reversed, cases)) + def commutative_test(self, operation, cases): + self.unary_operation_test(operation, cases) + self.unary_operation_test(operation, imap(reversed, cases)) - def unary_operation_test(self, operation, cases): - for case_in, case_out in cases: - self.assertEqual(operation(case_in), case_out) + def unary_operation_test(self, operation, cases): + for case_in, case_out in cases: + self.assertEqual(operation(case_in), case_out) class OutputBuffer(object): - def __init__(self): - self.clear_buffer() + def __init__(self): + self.clear_buffer() - def clear_buffer(self): - self.content = '' + def clear_buffer(self): + self.content = '' - def write(self, data): - self.content += data + def write(self, data): + self.content += data if __name__ == '__main__': - unittest.main() \ No newline at end of file + unittest.main() \ No newline at end of file diff --git a/tools/install-gnuarm4.sh b/tools/install-gnuarm4.sh index 793bdbf5d..a5d92c5d5 100755 --- a/tools/install-gnuarm4.sh +++ b/tools/install-gnuarm4.sh @@ -14,16 +14,16 @@ if [ "${1}" = "" ]; then echo "Syntax: ${0} [download & build directory (default ${PWD})]" exit 1 else - DESTDIR="${1}" + DESTDIR="${1}" fi # Where do you want to build the tools. This is where the log files # will be written (which you can monitor with 'tail' during compilation). # You can delete this directory after everything is done. if [ ! "${2}" = "" ]; then - SRCDIR="${2}" + SRCDIR="${2}" else - SRCDIR="${PWD}" + SRCDIR="${PWD}" fi BUILDDIR=${SRCDIR}/build-gnuarm4 diff --git a/tools/mkversion.pl b/tools/mkversion.pl index 674c44177..023c84c8b 100644 --- a/tools/mkversion.pl +++ b/tools/mkversion.pl @@ -32,28 +32,28 @@ my $commandGIT = "env which git"; if ( defined($commandGIT) ) { - my $githistory = `git fetch --all`; - # now avoiding the "fatal: No names found, cannot describe anything." error by fallbacking to abbrev hash in such case - my $gitversion = `git describe --dirty --always`; - my $gitbranch = `git rev-parse --abbrev-ref HEAD`; - $clean = $gitversion =~ '-dirty' ? 0 : 1; + my $githistory = `git fetch --all`; + # now avoiding the "fatal: No names found, cannot describe anything." error by fallbacking to abbrev hash in such case + my $gitversion = `git describe --dirty --always`; + my $gitbranch = `git rev-parse --abbrev-ref HEAD`; + $clean = $gitversion =~ '-dirty' ? 0 : 1; - if ( defined($gitbranch) and defined($gitversion) ) { - $fullgitinfo = $fullgitinfo.'/'. $gitbranch . '/' . $gitversion; + if ( defined($gitbranch) and defined($gitversion) ) { + $fullgitinfo = $fullgitinfo.'/'. $gitbranch . '/' . $gitversion; - my @compiletime = localtime(); - $compiletime[4] += 1; - $compiletime[5] += 1900; - $ctime = sprintf("%6\$04i-%5\$02i-%4\$02i %3\$02i:%2\$02i:%1\$02i", @compiletime); - } else { - $fullgitinfo = $fullgitinfo.'/master/release (git)'; - } + my @compiletime = localtime(); + $compiletime[4] += 1; + $compiletime[5] += 1900; + $ctime = sprintf("%6\$04i-%5\$02i-%4\$02i %3\$02i:%2\$02i:%1\$02i", @compiletime); + } else { + $fullgitinfo = $fullgitinfo.'/master/release (git)'; + } } else { - $fullgitinfo = $fullgitinfo.'/master/release (no_git)'; - my @dl_time = localtime( (stat('../README.md'))[10] ); - $dl_time[4] += 1; - $dl_time[5] += 1900; - $ctime = sprintf("%6\$04i-%5\$02i-%4\$02i %3\$02i:%2\$02i:%1\$02i", @dl_time); + $fullgitinfo = $fullgitinfo.'/master/release (no_git)'; + my @dl_time = localtime( (stat('../README.md'))[10] ); + $dl_time[4] += 1; + $dl_time[5] += 1900; + $ctime = sprintf("%6\$04i-%5\$02i-%4\$02i %3\$02i:%2\$02i:%1\$02i", @dl_time); } $fullgitinfo =~ s/(\s)//g; @@ -66,11 +66,11 @@ print < out.s19\n"; + die "usage: $0 file-to-endian-swap.s19 > out.s19\n"; } while(<>) { - chomp; + chomp; - if(/^S0/) { - next; - } - if(/^S7/) { - print "$_\n"; - next; - } + if(/^S0/) { + next; + } + if(/^S7/) { + print "$_\n"; + next; + } - if(not /^S3(..)(........)(.*)(..)$/) { - die "bad S record at line $.\n"; - } + if(not /^S3(..)(........)(.*)(..)$/) { + die "bad S record at line $.\n"; + } - $data = $3; - $checksum = $4; + $data = $3; + $checksum = $4; - print "S3$1$2"; - while($data =~ m#(..)(..)(..)(..)#g) { - print "$4$3$2$1"; - } - print "$checksum\n"; + print "S3$1$2"; + while($data =~ m#(..)(..)(..)(..)#g) { + print "$4$3$2$1"; + } + print "$checksum\n"; } diff --git a/tools/xorcheck.py b/tools/xorcheck.py index 73eeb4a7f..091998a31 100755 --- a/tools/xorcheck.py +++ b/tools/xorcheck.py @@ -24,29 +24,29 @@ import sys import os if(len(sys.argv) < 3): - print - print '\t'+sys.argv[0] + ' - Generate final byte for XOR LRC' - print - print 'Usage: ' + sys.argv[0] + ' ... ' - print - print '\tSpecifying the bytes of a UID with a known LRC will find the last byte value' - print '\tneeded to generate that LRC with a rolling XOR. All bytes should be specified in HEX.' - print - print 'Example:' - print - print '\txorcheck.py 04 00 80 64 ba' - print - print 'Should produce the output:' - print - print '\tTarget (BA) requires final LRC XOR byte value: 5A' - print - os._exit(True) + print + print '\t'+sys.argv[0] + ' - Generate final byte for XOR LRC' + print + print 'Usage: ' + sys.argv[0] + ' ... ' + print + print '\tSpecifying the bytes of a UID with a known LRC will find the last byte value' + print '\tneeded to generate that LRC with a rolling XOR. All bytes should be specified in HEX.' + print + print 'Example:' + print + print '\txorcheck.py 04 00 80 64 ba' + print + print 'Should produce the output:' + print + print '\tTarget (BA) requires final LRC XOR byte value: 5A' + print + os._exit(True) target= int(sys.argv[len(sys.argv) - 1],16) lrc= 0x00 for i in range(len(sys.argv) - 1): - lrc ^= int(sys.argv[i + 1],16) + lrc ^= int(sys.argv[i + 1],16) print print 'Target (%02X) requires final LRC XOR byte value: %02X' % (target,lrc) print From 46af10d54d5f4dc82227b2ccd19afbc56accaa65 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 11:10:22 +0100 Subject: [PATCH 0688/1938] scripts: fix mix of spaces & tabs --- fpga/tests/plot_edgedetect.py | 4 ++-- proxmark3.sh | 34 +++++++++++++++++----------------- update.sh | 34 +++++++++++++++++----------------- 3 files changed, 36 insertions(+), 36 deletions(-) diff --git a/fpga/tests/plot_edgedetect.py b/fpga/tests/plot_edgedetect.py index 4e244ebc3..3249de6c2 100755 --- a/fpga/tests/plot_edgedetect.py +++ b/fpga/tests/plot_edgedetect.py @@ -11,8 +11,8 @@ import matplotlib.pyplot as plt import sys if len(sys.argv) != 2: - print "Usage: %s " % sys.argv[0] - sys.exit(1) + print "Usage: %s " % sys.argv[0] + sys.exit(1) BASENAME = sys.argv[1] diff --git a/proxmark3.sh b/proxmark3.sh index e58749b2e..34691b95a 100755 --- a/proxmark3.sh +++ b/proxmark3.sh @@ -1,26 +1,26 @@ #!/bin/bash function wait4proxmark_Linux { - echo >&2 "Waiting for Proxmark to appear..." - while [ ! -c /dev/ttyACM? -a ! -L /dev/pm3-? ]; do - sleep .1 - done - local PM3=`ls -1 /dev/pm3-? /dev/ttyACM? 2>/dev/null | head -1` - echo >&2 -e "Found proxmark on ${PM3}\n" - echo $PM3 + echo >&2 "Waiting for Proxmark to appear..." + while [ ! -c /dev/ttyACM? -a ! -L /dev/pm3-? ]; do + sleep .1 + done + local PM3=`ls -1 /dev/pm3-? /dev/ttyACM? 2>/dev/null | head -1` + echo >&2 -e "Found proxmark on ${PM3}\n" + echo $PM3 } function wait4proxmark_macOS { - echo >&2 "Waiting for Proxmark to appear..." - while true; do - PM3=$(ls /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1) - if [[ $PM3 != "" ]]; then - #echo >&2 -e "Found proxmark on $(ls /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1)\n" - break - fi - sleep .1 - done - echo $PM3 + echo >&2 "Waiting for Proxmark to appear..." + while true; do + PM3=$(ls /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1) + if [[ $PM3 != "" ]]; then + #echo >&2 -e "Found proxmark on $(ls /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1)\n" + break + fi + sleep .1 + done + echo $PM3 } # start proxmark with first detected interface diff --git a/update.sh b/update.sh index 3546cc3d1..fe5f0dd95 100755 --- a/update.sh +++ b/update.sh @@ -1,26 +1,26 @@ #!/bin/bash function wait4proxmark_Linux { - echo >&2 "Waiting for Proxmark to appear..." - while [ ! -c /dev/ttyACM? -a ! -L /dev/pm3-? ]; do - sleep .1 - done - local PM3=`ls -1 /dev/pm3-? /dev/ttyACM? 2>/dev/null | head -1` - echo >&2 -e "Found proxmark on ${PM3}\n" - echo $PM3 + echo >&2 "Waiting for Proxmark to appear..." + while [ ! -c /dev/ttyACM? -a ! -L /dev/pm3-? ]; do + sleep .1 + done + local PM3=`ls -1 /dev/pm3-? /dev/ttyACM? 2>/dev/null | head -1` + echo >&2 -e "Found proxmark on ${PM3}\n" + echo $PM3 } function wait4proxmark_macOS { - echo >&2 "Waiting for Proxmark to appear..." - while true; do - PM3=$(ls /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1) - if [[ $PM3 != "" ]]; then - #echo >&2 -e "Found proxmark on $(ls /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1)\n" - break - fi - sleep .1 - done - echo $PM3 + echo >&2 "Waiting for Proxmark to appear..." + while true; do + PM3=$(ls /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1) + if [[ $PM3 != "" ]]; then + #echo >&2 -e "Found proxmark on $(ls /dev/pm3-* /dev/cu.usbmodem* 2>/dev/null | head -1)\n" + break + fi + sleep .1 + done + echo $PM3 } # Detect OS and flash bootroom & system image From 59eb83bf90acee21351181178ad976ac7b5dcf61 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 11:10:54 +0100 Subject: [PATCH 0689/1938] fix: use defines instead. --- client/cmdlft55xx.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 4eb087874..4acf07c3e 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1900,19 +1900,19 @@ bool tryDetectP1(bool getData) { clk = GetPskClock("", false); if (clk > 0) { // allow undo - // save_restoreGB(1); + // save_restoreGB(GRAPH_SAVE); // skip first 160 samples to allow antenna to settle in (psk gets inverted occasionally otherwise) //CmdLtrim("160"); if ( PSKDemod("0 0 6", false) && preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - //save_restoreGB(0); + //save_restoreGB(GRAPH_RESTORE); return true; } if ( PSKDemod("0 1 6", false) && preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - //save_restoreGB(0); + //save_restoreGB(GRAPH_RESTORE); return true; } // PSK2 - needs a call to psk1TOpsk2. @@ -1920,12 +1920,12 @@ bool tryDetectP1(bool getData) { psk1TOpsk2(DemodBuffer, DemodBufferLen); if (preambleSearchEx(DemodBuffer, preamble, sizeof(preamble), &DemodBufferLen, &startIdx, false) && (DemodBufferLen == 32 || DemodBufferLen == 64) ) { - //save_restoreGB(0); + //save_restoreGB(GRAPH_RESTORE); return true; } } // inverse waves does not affect PSK2 demod //undo trim samples - //save_restoreGB(0); + //save_restoreGB(GRAPH_RESTORE); // no other modulation clocks = 2 or 4 so quit searching if (fc1 != 8) return false; } From dc36bd5e5a59e10870f02ef42fdec5a1663287cf Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 11:13:46 +0100 Subject: [PATCH 0690/1938] fix: 'lf CheckChipType' - restores demodbuff/graphbuf properly --- client/cmdlf.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index 59dc12654..7358d9da1 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -816,10 +816,13 @@ int CmdVchDemod(const char *Cmd) { } //by marshmellow -int CheckChipType(bool getDeviceData) { +bool CheckChipType(bool getDeviceData) { - if (!getDeviceData) return 0; + bool retval = false; + if (!getDeviceData) return retval; + + save_restoreGB(GRAPH_SAVE); save_restoreDB(GRAPH_SAVE); //check for em4x05/em4x69 chips first @@ -827,20 +830,22 @@ int CheckChipType(bool getDeviceData) { if (EM4x05IsBlock0(&word)) { PrintAndLogEx(SUCCESS, "\nValid EM4x05/EM4x69 Chip Found"); PrintAndLogEx(SUCCESS, "Try " _YELLOW_(`lf em 4x05`) " commands"); - save_restoreGB(GRAPH_RESTORE); - return 1; + retval = true; + goto out; } //check for t55xx chip... if (tryDetectP1(true)) { PrintAndLogEx(SUCCESS, "\nValid T55xx Chip Found"); PrintAndLogEx(SUCCESS, "Try " _YELLOW_(`lf t55xx`)" commands"); - save_restoreGB(GRAPH_RESTORE); - return 1; + retval = true; + goto out; } +out: + save_restoreGB(GRAPH_RESTORE); save_restoreDB(GRAPH_RESTORE); - return 0; + return retval; } //by marshmellow From 1fe75f248150b553eaa6d17db243aacbb5d99847 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 11:15:18 +0100 Subject: [PATCH 0691/1938] zlib, uart: fix mix of spaces & tabs --- uart/uart.h | 4 +- uart/uart_posix.c | 528 +++++++++++++++++++++++----------------------- uart/uart_win32.c | 184 ++++++++-------- zlib/deflate.c | 132 ++++++------ zlib/inflate.c | 2 +- zlib/trees.c | 2 +- 6 files changed, 426 insertions(+), 426 deletions(-) diff --git a/uart/uart.h b/uart/uart.h index d724831be..f7bd2117f 100644 --- a/uart/uart.h +++ b/uart/uart.h @@ -44,11 +44,11 @@ #if defined (_WIN32) -#define SERIAL_PORT_H "com3" +#define SERIAL_PORT_H "com3" #elif defined(__APPLE__) #define SERIAL_PORT_H "/dev/cu.usbmodem" #else -#define SERIAL_PORT_H "/dev/ttyACM0" +#define SERIAL_PORT_H "/dev/ttyACM0" #endif /* serial_port is declared as a void*, which you should cast to whatever type diff --git a/uart/uart_posix.c b/uart/uart_posix.c index 58f24298d..b2639f2f0 100644 --- a/uart/uart_posix.c +++ b/uart/uart_posix.c @@ -62,363 +62,363 @@ typedef struct termios term_info; typedef struct { - int fd; // Serial port file descriptor - term_info tiOld; // Terminal info before using the port - term_info tiNew; // Terminal info during the transaction + int fd; // Serial port file descriptor + term_info tiOld; // Terminal info before using the port + term_info tiNew; // Terminal info during the transaction } serial_port_unix; // Set time-out on 30 miliseconds struct timeval timeout = { - .tv_sec = 0, // 0 second - .tv_usec = 30000 // 30 000 micro seconds + .tv_sec = 0, // 0 second + .tv_usec = 30000 // 30 000 micro seconds }; serial_port uart_open(const char* pcPortName) { - serial_port_unix* sp = calloc(sizeof(serial_port_unix), sizeof(uint8_t)); - if (sp == 0) return INVALID_SERIAL_PORT; + serial_port_unix* sp = calloc(sizeof(serial_port_unix), sizeof(uint8_t)); + if (sp == 0) return INVALID_SERIAL_PORT; - if (memcmp(pcPortName, "tcp:", 4) == 0) { - struct addrinfo *addr, *rp; - char *addrstr = strdup(pcPortName + 4); + if (memcmp(pcPortName, "tcp:", 4) == 0) { + struct addrinfo *addr, *rp; + char *addrstr = strdup(pcPortName + 4); - if (addrstr == NULL) { - printf("Error: strdup\n"); - free(sp); - return INVALID_SERIAL_PORT; - } + if (addrstr == NULL) { + printf("Error: strdup\n"); + free(sp); + return INVALID_SERIAL_PORT; + } - timeout.tv_usec = 300000; // 300 000 micro seconds + timeout.tv_usec = 300000; // 300 000 micro seconds - char *colon = strrchr(addrstr, ':'); - char *portstr; - if (colon) { - portstr = colon + 1; - *colon = '\0'; - } else { - portstr = "7901"; - } + char *colon = strrchr(addrstr, ':'); + char *portstr; + if (colon) { + portstr = colon + 1; + *colon = '\0'; + } else { + portstr = "7901"; + } - int s = getaddrinfo(addrstr, portstr, NULL, &addr); - if (s != 0) { - printf("Error: getaddrinfo: %s\n", gai_strerror(s)); - freeaddrinfo(addr); - free(addrstr); - free(sp); - return INVALID_SERIAL_PORT; - } + int s = getaddrinfo(addrstr, portstr, NULL, &addr); + if (s != 0) { + printf("Error: getaddrinfo: %s\n", gai_strerror(s)); + freeaddrinfo(addr); + free(addrstr); + free(sp); + return INVALID_SERIAL_PORT; + } - int sfd; - for (rp = addr; rp != NULL; rp = rp->ai_next) { - sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); + int sfd; + for (rp = addr; rp != NULL; rp = rp->ai_next) { + sfd = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); - if (sfd == -1) - continue; + if (sfd == -1) + continue; - if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) - break; + if (connect(sfd, rp->ai_addr, rp->ai_addrlen) != -1) + break; - close(sfd); - } + close(sfd); + } - if (rp == NULL) { /* No address succeeded */ - printf("Error: Could not connect\n"); - freeaddrinfo(addr); - free(addrstr); - free(sp); - return INVALID_SERIAL_PORT; - } + if (rp == NULL) { /* No address succeeded */ + printf("Error: Could not connect\n"); + freeaddrinfo(addr); + free(addrstr); + free(sp); + return INVALID_SERIAL_PORT; + } - freeaddrinfo(addr); - free(addrstr); + freeaddrinfo(addr); + free(addrstr); - sp->fd = sfd; + sp->fd = sfd; - int one = 1; - int res = setsockopt(sp->fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)); - if ( res != 0) { - free(sp); - return INVALID_SERIAL_PORT; - } - return sp; - } + int one = 1; + int res = setsockopt(sp->fd, SOL_TCP, TCP_NODELAY, &one, sizeof(one)); + if ( res != 0) { + free(sp); + return INVALID_SERIAL_PORT; + } + return sp; + } - sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); - if (sp->fd == -1) { - uart_close(sp); - return INVALID_SERIAL_PORT; - } + sp->fd = open(pcPortName, O_RDWR | O_NOCTTY | O_NDELAY | O_NONBLOCK); + if (sp->fd == -1) { + uart_close(sp); + return INVALID_SERIAL_PORT; + } - // Finally figured out a way to claim a serial port interface under unix - // We just try to set a (advisory) lock on the file descriptor - struct flock fl; - fl.l_type = F_WRLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_pid = getpid(); + // Finally figured out a way to claim a serial port interface under unix + // We just try to set a (advisory) lock on the file descriptor + struct flock fl; + fl.l_type = F_WRLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_pid = getpid(); - // Does the system allows us to place a lock on this file descriptor - if (fcntl(sp->fd, F_SETLK, &fl) == -1) { - // A conflicting lock is held by another process - free(sp); - return CLAIMED_SERIAL_PORT; - } + // Does the system allows us to place a lock on this file descriptor + if (fcntl(sp->fd, F_SETLK, &fl) == -1) { + // A conflicting lock is held by another process + free(sp); + return CLAIMED_SERIAL_PORT; + } - // Try to retrieve the old (current) terminal info struct - if (tcgetattr(sp->fd,&sp->tiOld) == -1) { - uart_close(sp); - return INVALID_SERIAL_PORT; - } + // Try to retrieve the old (current) terminal info struct + if (tcgetattr(sp->fd,&sp->tiOld) == -1) { + uart_close(sp); + return INVALID_SERIAL_PORT; + } - // Duplicate the (old) terminal info struct - sp->tiNew = sp->tiOld; + // Duplicate the (old) terminal info struct + sp->tiNew = sp->tiOld; - // Configure the serial port - sp->tiNew.c_cflag = CS8 | CLOCAL | CREAD; - sp->tiNew.c_iflag = IGNPAR; - sp->tiNew.c_oflag = 0; - sp->tiNew.c_lflag = 0; + // Configure the serial port + sp->tiNew.c_cflag = CS8 | CLOCAL | CREAD; + sp->tiNew.c_iflag = IGNPAR; + sp->tiNew.c_oflag = 0; + sp->tiNew.c_lflag = 0; - // Block until n bytes are received - sp->tiNew.c_cc[VMIN] = 0; - // Block until a timer expires (n * 100 mSec.) - sp->tiNew.c_cc[VTIME] = 0; + // Block until n bytes are received + sp->tiNew.c_cc[VMIN] = 0; + // Block until a timer expires (n * 100 mSec.) + sp->tiNew.c_cc[VTIME] = 0; - // Try to set the new terminal info struct - if (tcsetattr(sp->fd, TCSANOW, &sp->tiNew) == -1) { - uart_close(sp); - return INVALID_SERIAL_PORT; - } + // Try to set the new terminal info struct + if (tcsetattr(sp->fd, TCSANOW, &sp->tiNew) == -1) { + uart_close(sp); + return INVALID_SERIAL_PORT; + } // Flush all lingering data that may exist tcflush(sp->fd, TCIOFLUSH); #ifdef WITH_FPC - if ( uart_set_speed(sp, 115200) ) { - printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n"); - } else { - uart_set_speed(sp, 9600); - printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n"); - } + if ( uart_set_speed(sp, 115200) ) { + printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n"); + } else { + uart_set_speed(sp, 9600); + printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n"); + } #else - // set speed, works for UBUNTU 14.04 - bool success = uart_set_speed(sp, 460800); - if (success) { - printf("[=] UART Setting serial baudrate 460800\n"); - } else { - uart_set_speed(sp, 115200); - printf("[=] UART Setting serial baudrate 115200\n"); - } + // set speed, works for UBUNTU 14.04 + bool success = uart_set_speed(sp, 460800); + if (success) { + printf("[=] UART Setting serial baudrate 460800\n"); + } else { + uart_set_speed(sp, 115200); + printf("[=] UART Setting serial baudrate 115200\n"); + } #endif - return sp; + return sp; } void uart_close(const serial_port sp) { - serial_port_unix* spu = (serial_port_unix*)sp; - tcflush(spu->fd, TCIOFLUSH); - tcsetattr(spu->fd, TCSANOW, &(spu->tiOld)); - struct flock fl; - fl.l_type = F_UNLCK; - fl.l_whence = SEEK_SET; - fl.l_start = 0; - fl.l_len = 0; - fl.l_pid = getpid(); + serial_port_unix* spu = (serial_port_unix*)sp; + tcflush(spu->fd, TCIOFLUSH); + tcsetattr(spu->fd, TCSANOW, &(spu->tiOld)); + struct flock fl; + fl.l_type = F_UNLCK; + fl.l_whence = SEEK_SET; + fl.l_start = 0; + fl.l_len = 0; + fl.l_pid = getpid(); - // Does the system allows us to place a lock on this file descriptor - int err = fcntl(spu->fd, F_SETLK, &fl); - if ( err == -1) { - //perror("fcntl"); - } - close(spu->fd); - free(sp); + // Does the system allows us to place a lock on this file descriptor + int err = fcntl(spu->fd, F_SETLK, &fl); + if ( err == -1) { + //perror("fcntl"); + } + close(spu->fd); + free(sp); } bool uart_receive(const serial_port sp, uint8_t* pbtRx, size_t pszMaxRxLen, size_t* pszRxLen) { - int res; - int byteCount; - fd_set rfds; - struct timeval tv; + int res; + int byteCount; + fd_set rfds; + struct timeval tv; - // Reset the output count - *pszRxLen = 0; + // Reset the output count + *pszRxLen = 0; - do { - // Reset file descriptor - FD_ZERO(&rfds); - FD_SET(((serial_port_unix*)sp)->fd, &rfds); - tv = timeout; - res = select(((serial_port_unix*)sp)->fd + 1, &rfds, NULL, NULL, &tv); + do { + // Reset file descriptor + FD_ZERO(&rfds); + FD_SET(((serial_port_unix*)sp)->fd, &rfds); + tv = timeout; + res = select(((serial_port_unix*)sp)->fd + 1, &rfds, NULL, NULL, &tv); - // Read error - if (res < 0) { - return false; - } + // Read error + if (res < 0) { + return false; + } - // Read time-out - if (res == 0) { - if (*pszRxLen == 0) { - // Error, we received no data - return false; - } else { - // We received some data, but nothing more is available - return true; - } - } + // Read time-out + if (res == 0) { + if (*pszRxLen == 0) { + // Error, we received no data + return false; + } else { + // We received some data, but nothing more is available + return true; + } + } - // Retrieve the count of the incoming bytes - res = ioctl(((serial_port_unix*)sp)->fd, FIONREAD, &byteCount); - if (res < 0) return false; + // Retrieve the count of the incoming bytes + res = ioctl(((serial_port_unix*)sp)->fd, FIONREAD, &byteCount); + if (res < 0) return false; - // Cap the number of bytes, so we don't overrun the buffer - if (pszMaxRxLen - (*pszRxLen) < byteCount) { - byteCount = pszMaxRxLen - (*pszRxLen); - } + // Cap the number of bytes, so we don't overrun the buffer + if (pszMaxRxLen - (*pszRxLen) < byteCount) { + byteCount = pszMaxRxLen - (*pszRxLen); + } - // There is something available, read the data - res = read(((serial_port_unix*)sp)->fd, pbtRx + (*pszRxLen), byteCount); + // There is something available, read the data + res = read(((serial_port_unix*)sp)->fd, pbtRx + (*pszRxLen), byteCount); - // Stop if the OS has some troubles reading the data - if (res <= 0) return false; + // Stop if the OS has some troubles reading the data + if (res <= 0) return false; - *pszRxLen += res; + *pszRxLen += res; - if (*pszRxLen == pszMaxRxLen) { - // We have all the data we wanted. - return true; - } + if (*pszRxLen == pszMaxRxLen) { + // We have all the data we wanted. + return true; + } - } while (byteCount); + } while (byteCount); - return true; + return true; } bool uart_send(const serial_port sp, const uint8_t* pbtTx, const size_t len) { - int32_t res; - size_t pos = 0; - fd_set rfds; - struct timeval tv; + int32_t res; + size_t pos = 0; + fd_set rfds; + struct timeval tv; - while (pos < len) { - // Reset file descriptor - FD_ZERO(&rfds); - FD_SET(((serial_port_unix*)sp)->fd, &rfds); - tv = timeout; - res = select(((serial_port_unix*)sp)->fd+1, NULL, &rfds, NULL, &tv); + while (pos < len) { + // Reset file descriptor + FD_ZERO(&rfds); + FD_SET(((serial_port_unix*)sp)->fd, &rfds); + tv = timeout; + res = select(((serial_port_unix*)sp)->fd+1, NULL, &rfds, NULL, &tv); - // Write error - if (res < 0) { - printf("UART:: write error (%d)\n", res); - return false; - } + // Write error + if (res < 0) { + printf("UART:: write error (%d)\n", res); + return false; + } - // Write time-out - if (res == 0) { - printf("UART:: write time-out\n"); - return false; - } + // Write time-out + if (res == 0) { + printf("UART:: write time-out\n"); + return false; + } - // Send away the bytes - res = write(((serial_port_unix*)sp)->fd, pbtTx + pos, len - pos); + // Send away the bytes + res = write(((serial_port_unix*)sp)->fd, pbtTx + pos, len - pos); - // Stop if the OS has some troubles sending the data - if (res <= 0) return false; + // Stop if the OS has some troubles sending the data + if (res <= 0) return false; - pos += res; - } - return true; + pos += res; + } + return true; } bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) { - const serial_port_unix* spu = (serial_port_unix*)sp; - speed_t stPortSpeed; - switch (uiPortSpeed) { - case 0: stPortSpeed = B0; break; - case 50: stPortSpeed = B50; break; - case 75: stPortSpeed = B75; break; - case 110: stPortSpeed = B110; break; - case 134: stPortSpeed = B134; break; - case 150: stPortSpeed = B150; break; - case 300: stPortSpeed = B300; break; - case 600: stPortSpeed = B600; break; - case 1200: stPortSpeed = B1200; break; - case 1800: stPortSpeed = B1800; break; - case 2400: stPortSpeed = B2400; break; - case 4800: stPortSpeed = B4800; break; - case 9600: stPortSpeed = B9600; break; - case 19200: stPortSpeed = B19200; break; - case 38400: stPortSpeed = B38400; break; + const serial_port_unix* spu = (serial_port_unix*)sp; + speed_t stPortSpeed; + switch (uiPortSpeed) { + case 0: stPortSpeed = B0; break; + case 50: stPortSpeed = B50; break; + case 75: stPortSpeed = B75; break; + case 110: stPortSpeed = B110; break; + case 134: stPortSpeed = B134; break; + case 150: stPortSpeed = B150; break; + case 300: stPortSpeed = B300; break; + case 600: stPortSpeed = B600; break; + case 1200: stPortSpeed = B1200; break; + case 1800: stPortSpeed = B1800; break; + case 2400: stPortSpeed = B2400; break; + case 4800: stPortSpeed = B4800; break; + case 9600: stPortSpeed = B9600; break; + case 19200: stPortSpeed = B19200; break; + case 38400: stPortSpeed = B38400; break; # ifdef B57600 - case 57600: stPortSpeed = B57600; break; + case 57600: stPortSpeed = B57600; break; # endif # ifdef B115200 - case 115200: stPortSpeed = B115200; break; + case 115200: stPortSpeed = B115200; break; # endif # ifdef B230400 - case 230400: stPortSpeed = B230400; break; + case 230400: stPortSpeed = B230400; break; # endif # ifdef B460800 - case 460800: stPortSpeed = B460800; break; + case 460800: stPortSpeed = B460800; break; # endif # ifdef B921600 - case 921600: stPortSpeed = B921600; break; + case 921600: stPortSpeed = B921600; break; # endif - default: return false; - }; + default: return false; + }; - struct termios ti; - if (tcgetattr(spu->fd,&ti) == -1) - return false; + struct termios ti; + if (tcgetattr(spu->fd,&ti) == -1) + return false; - // Set port speed (Input and Output) - cfsetispeed(&ti, stPortSpeed); - cfsetospeed(&ti, stPortSpeed); - return (tcsetattr(spu->fd, TCSANOW, &ti) != -1); + // Set port speed (Input and Output) + cfsetispeed(&ti, stPortSpeed); + cfsetospeed(&ti, stPortSpeed); + return (tcsetattr(spu->fd, TCSANOW, &ti) != -1); } uint32_t uart_get_speed(const serial_port sp) { - struct termios ti; - uint32_t uiPortSpeed; - const serial_port_unix* spu = (serial_port_unix*)sp; + struct termios ti; + uint32_t uiPortSpeed; + const serial_port_unix* spu = (serial_port_unix*)sp; - if (tcgetattr(spu->fd, &ti) == -1) - return 0; + if (tcgetattr(spu->fd, &ti) == -1) + return 0; - // Set port speed (Input) - speed_t stPortSpeed = cfgetispeed(&ti); - switch (stPortSpeed) { - case B0: uiPortSpeed = 0; break; - case B50: uiPortSpeed = 50; break; - case B75: uiPortSpeed = 75; break; - case B110: uiPortSpeed = 110; break; - case B134: uiPortSpeed = 134; break; - case B150: uiPortSpeed = 150; break; - case B300: uiPortSpeed = 300; break; - case B600: uiPortSpeed = 600; break; - case B1200: uiPortSpeed = 1200; break; - case B1800: uiPortSpeed = 1800; break; - case B2400: uiPortSpeed = 2400; break; - case B4800: uiPortSpeed = 4800; break; - case B9600: uiPortSpeed = 9600; break; - case B19200: uiPortSpeed = 19200; break; - case B38400: uiPortSpeed = 38400; break; + // Set port speed (Input) + speed_t stPortSpeed = cfgetispeed(&ti); + switch (stPortSpeed) { + case B0: uiPortSpeed = 0; break; + case B50: uiPortSpeed = 50; break; + case B75: uiPortSpeed = 75; break; + case B110: uiPortSpeed = 110; break; + case B134: uiPortSpeed = 134; break; + case B150: uiPortSpeed = 150; break; + case B300: uiPortSpeed = 300; break; + case B600: uiPortSpeed = 600; break; + case B1200: uiPortSpeed = 1200; break; + case B1800: uiPortSpeed = 1800; break; + case B2400: uiPortSpeed = 2400; break; + case B4800: uiPortSpeed = 4800; break; + case B9600: uiPortSpeed = 9600; break; + case B19200: uiPortSpeed = 19200; break; + case B38400: uiPortSpeed = 38400; break; # ifdef B57600 - case B57600: uiPortSpeed = 57600; break; + case B57600: uiPortSpeed = 57600; break; # endif # ifdef B115200 - case B115200: uiPortSpeed = 115200; break; + case B115200: uiPortSpeed = 115200; break; # endif # ifdef B230400 - case B230400: uiPortSpeed = 230400; break; + case B230400: uiPortSpeed = 230400; break; # endif # ifdef B460800 - case B460800: uiPortSpeed = 460800; break; + case B460800: uiPortSpeed = 460800; break; # endif # ifdef B921600 - case B921600: uiPortSpeed = 921600; break; + case B921600: uiPortSpeed = 921600; break; # endif - default: return 0; - }; - return uiPortSpeed; + default: return 0; + }; + return uiPortSpeed; } #endif diff --git a/uart/uart_win32.c b/uart/uart_win32.c index 5f269c677..f3f129d85 100644 --- a/uart/uart_win32.c +++ b/uart/uart_win32.c @@ -49,129 +49,129 @@ typedef struct { } serial_port_windows; serial_port uart_open(const char* pcPortName) { - char acPortName[255]; - serial_port_windows* sp = calloc(sizeof(serial_port_windows), sizeof(uint8_t)); + char acPortName[255]; + serial_port_windows* sp = calloc(sizeof(serial_port_windows), sizeof(uint8_t)); - if (sp == 0) { - printf("[!] UART failed to allocate memory\n"); - return INVALID_SERIAL_PORT; - } - // Copy the input "com?" to "\\.\COM?" format - sprintf(acPortName,"\\\\.\\%s", pcPortName); - _strupr(acPortName); + if (sp == 0) { + printf("[!] UART failed to allocate memory\n"); + return INVALID_SERIAL_PORT; + } + // Copy the input "com?" to "\\.\COM?" format + sprintf(acPortName,"\\\\.\\%s", pcPortName); + _strupr(acPortName); - // Try to open the serial port - // r/w, none-share comport, no security, existing, no overlapping, no templates - sp->hPort = CreateFileA(acPortName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); - if (sp->hPort == INVALID_HANDLE_VALUE) { - uart_close(sp); - return INVALID_SERIAL_PORT; - } + // Try to open the serial port + // r/w, none-share comport, no security, existing, no overlapping, no templates + sp->hPort = CreateFileA(acPortName, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL); + if (sp->hPort == INVALID_HANDLE_VALUE) { + uart_close(sp); + return INVALID_SERIAL_PORT; + } - // Prepare the device control - // doesn't matter since PM3 device ignors this CDC command: set_line_coding in usb_cdc.c - memset(&sp->dcb, 0, sizeof(DCB)); - sp->dcb.DCBlength = sizeof(DCB); - if (!BuildCommDCBA("baud=115200 parity=N data=8 stop=1", &sp->dcb)) { - uart_close(sp); - printf("[!] UART error cdc setup\n"); - return INVALID_SERIAL_PORT; - } + // Prepare the device control + // doesn't matter since PM3 device ignors this CDC command: set_line_coding in usb_cdc.c + memset(&sp->dcb, 0, sizeof(DCB)); + sp->dcb.DCBlength = sizeof(DCB); + if (!BuildCommDCBA("baud=115200 parity=N data=8 stop=1", &sp->dcb)) { + uart_close(sp); + printf("[!] UART error cdc setup\n"); + return INVALID_SERIAL_PORT; + } - // Update the active serial port - if (!SetCommState(sp->hPort, &sp->dcb)) { - uart_close(sp); - printf("[!] UART error while setting com state\n"); - return INVALID_SERIAL_PORT; - } - // all zero's configure: no timeout for read/write used. - // took settings from libnfc/buses/uart.c + // Update the active serial port + if (!SetCommState(sp->hPort, &sp->dcb)) { + uart_close(sp); + printf("[!] UART error while setting com state\n"); + return INVALID_SERIAL_PORT; + } + // all zero's configure: no timeout for read/write used. + // took settings from libnfc/buses/uart.c #ifdef WITH_FPC - sp->ct.ReadIntervalTimeout = 1000; - sp->ct.ReadTotalTimeoutMultiplier = 0; - sp->ct.ReadTotalTimeoutConstant = 1500; - sp->ct.WriteTotalTimeoutMultiplier = 1000; - sp->ct.WriteTotalTimeoutConstant = 0; + sp->ct.ReadIntervalTimeout = 1000; + sp->ct.ReadTotalTimeoutMultiplier = 0; + sp->ct.ReadTotalTimeoutConstant = 1500; + sp->ct.WriteTotalTimeoutMultiplier = 1000; + sp->ct.WriteTotalTimeoutConstant = 0; #else - sp->ct.ReadIntervalTimeout = 30; - sp->ct.ReadTotalTimeoutMultiplier = 0; - sp->ct.ReadTotalTimeoutConstant = 30; - sp->ct.WriteTotalTimeoutMultiplier = 30; - sp->ct.WriteTotalTimeoutConstant = 0; + sp->ct.ReadIntervalTimeout = 30; + sp->ct.ReadTotalTimeoutMultiplier = 0; + sp->ct.ReadTotalTimeoutConstant = 30; + sp->ct.WriteTotalTimeoutMultiplier = 30; + sp->ct.WriteTotalTimeoutConstant = 0; #endif - if (!SetCommTimeouts(sp->hPort, &sp->ct)) { - uart_close(sp); - printf("[!] UART error while setting comm time outs\n"); - return INVALID_SERIAL_PORT; - } + if (!SetCommTimeouts(sp->hPort, &sp->ct)) { + uart_close(sp); + printf("[!] UART error while setting comm time outs\n"); + return INVALID_SERIAL_PORT; + } - PurgeComm(sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR); + PurgeComm(sp->hPort, PURGE_RXABORT | PURGE_RXCLEAR); #ifdef WITH_FPC - if ( uart_set_speed(sp, 115200) ) { - printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n"); - } else { - uart_set_speed(sp, 9600); - printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n"); - } + if ( uart_set_speed(sp, 115200) ) { + printf("[=] UART Setting serial baudrate 115200 [FPC enabled]\n"); + } else { + uart_set_speed(sp, 9600); + printf("[=] UART Setting serial baudrate 9600 [FPC enabled]\n"); + } #else - bool success = uart_set_speed(sp, 460800); - if (success) { - printf("[=] UART Setting serial baudrate 460800\n"); - } else { - uart_set_speed(sp, 115200); - printf("[=] UART Setting serial baudrate 115200\n"); - } + bool success = uart_set_speed(sp, 460800); + if (success) { + printf("[=] UART Setting serial baudrate 460800\n"); + } else { + uart_set_speed(sp, 115200); + printf("[=] UART Setting serial baudrate 115200\n"); + } #endif - return sp; + return sp; } void uart_close(const serial_port sp) { - if (((serial_port_windows*)sp)->hPort != INVALID_HANDLE_VALUE ) - CloseHandle(((serial_port_windows*)sp)->hPort); - free(sp); + if (((serial_port_windows*)sp)->hPort != INVALID_HANDLE_VALUE ) + CloseHandle(((serial_port_windows*)sp)->hPort); + free(sp); } bool uart_set_speed(serial_port sp, const uint32_t uiPortSpeed) { - serial_port_windows* spw; + serial_port_windows* spw; - // Set port speed (Input and Output) - switch (uiPortSpeed) { - case 9600: - case 19200: - case 38400: - case 57600: - case 115200: - case 230400: - case 460800: - break; - default: - return false; - }; + // Set port speed (Input and Output) + switch (uiPortSpeed) { + case 9600: + case 19200: + case 38400: + case 57600: + case 115200: + case 230400: + case 460800: + break; + default: + return false; + }; - spw = (serial_port_windows*)sp; - spw->dcb.BaudRate = uiPortSpeed; - bool result = SetCommState(spw->hPort, &spw->dcb); - PurgeComm(spw->hPort, PURGE_RXABORT | PURGE_RXCLEAR); - return result; + spw = (serial_port_windows*)sp; + spw->dcb.BaudRate = uiPortSpeed; + bool result = SetCommState(spw->hPort, &spw->dcb); + PurgeComm(spw->hPort, PURGE_RXABORT | PURGE_RXCLEAR); + return result; } uint32_t uart_get_speed(const serial_port sp) { - const serial_port_windows* spw = (serial_port_windows*)sp; - if (!GetCommState(spw->hPort, (serial_port) & spw->dcb)) - return spw->dcb.BaudRate; + const serial_port_windows* spw = (serial_port_windows*)sp; + if (!GetCommState(spw->hPort, (serial_port) & spw->dcb)) + return spw->dcb.BaudRate; - return 0; + return 0; } bool uart_receive(const serial_port sp, uint8_t* p_rx, size_t pszMaxRxLen, size_t* len) { - return ReadFile(((serial_port_windows*)sp)->hPort, p_rx, pszMaxRxLen, (LPDWORD)len, NULL); + return ReadFile(((serial_port_windows*)sp)->hPort, p_rx, pszMaxRxLen, (LPDWORD)len, NULL); } bool uart_send(const serial_port sp, const uint8_t* p_tx, const size_t len) { - DWORD txlen = 0; - return WriteFile(((serial_port_windows*)sp)->hPort, p_tx, len, &txlen, NULL); + DWORD txlen = 0; + return WriteFile(((serial_port_windows*)sp)->hPort, p_tx, len, &txlen, NULL); } #endif \ No newline at end of file diff --git a/zlib/deflate.c b/zlib/deflate.c index 593f5ebd3..91f1f1dc7 100644 --- a/zlib/deflate.c +++ b/zlib/deflate.c @@ -1160,10 +1160,10 @@ local uInt longest_match(s, cur_match) { unsigned chain_length = s->max_chain_length;/* max hash chain length */ register Bytef *scan = s->window + s->strstart; /* current string */ - register Bytef *match; /* matched string */ + register Bytef *match; /* matched string */ register int len; /* length of current match */ #ifdef ZLIB_PM3_TUNED - int best_len = MIN_MATCH-1; // lift the restriction on prev-length + int best_len = MIN_MATCH-1; /* lift the restriction on prev-length */ #else int best_len = s->prev_length; /* best match length so far */ #endif @@ -1737,73 +1737,73 @@ local block_state deflate_fast(s, flush) #ifdef ZLIB_PM3_TUNED local uInt try_harder(s, strstart, lookahead, hash_head) - deflate_state *s; - uInt strstart; - uInt lookahead; - IPos hash_head; + deflate_state *s; + uInt strstart; + uInt lookahead; + IPos hash_head; { - uInt strstart_save = s->strstart; - s->strstart = strstart; - uInt lookahead_save = s->lookahead; - s->lookahead = lookahead; - uInt ins_h_save = s->ins_h; - uInt combined_gain; - uInt best_combined_gain = 0; - uInt match_length; - uInt prev_length = s->prev_length < MIN_MATCH ? 1 : s->prev_length; - uInt best_prev_length = prev_length; - uInt current_match_start = s->match_start; - uInt current_match_length = s->match_length; + uInt strstart_save = s->strstart; + s->strstart = strstart; + uInt lookahead_save = s->lookahead; + s->lookahead = lookahead; + uInt ins_h_save = s->ins_h; + uInt combined_gain; + uInt best_combined_gain = 0; + uInt match_length; + uInt prev_length = s->prev_length < MIN_MATCH ? 1 : s->prev_length; + uInt best_prev_length = prev_length; + uInt current_match_start = s->match_start; + uInt current_match_length = s->match_length; - do { + do { if (hash_head != NIL && s->strstart - hash_head <= MAX_DIST(s)) { - match_length = longest_match (s, hash_head); - /* longest_match() sets match_start */ - } else { - match_length = MIN_MATCH - 1; - } + match_length = longest_match (s, hash_head); + /* longest_match() sets match_start */ + } else { + match_length = MIN_MATCH - 1; + } #if TOO_FAR <= 32767 - if (match_length == MIN_MATCH && s->strstart - s->match_start > TOO_FAR) { - match_length = MIN_MATCH-1; - } + if (match_length == MIN_MATCH && s->strstart - s->match_start > TOO_FAR) { + match_length = MIN_MATCH-1; + } #endif - if (s->strstart == strstart) { // store match at current position - current_match_length = match_length; - current_match_start = s->match_start; - } - if (s->strstart - strstart + 1 < MIN_MATCH) { // previous match reduced to one or two literals - combined_gain = 0; // need one literal per byte: no gain (assuming 8 bits per literal) - } else { - combined_gain = s->strstart - strstart + 1 - MIN_MATCH; // (possibly truncated) previous_length - 3 literals - } - if (match_length < MIN_MATCH) { - combined_gain += 0; // no gain - } else { - combined_gain += match_length - MIN_MATCH; // match_length bytes are coded as three literals - } - if (combined_gain >= best_combined_gain) { // in case of a tie we prefer the longer prev_length - best_combined_gain = combined_gain; - best_prev_length = s->strstart - strstart + 1; - } - s->strstart++; - s->lookahead--; - UPDATE_HASH(s, s->ins_h, s->window[(s->strstart) + (MIN_MATCH-1)]); - hash_head = s->head[s->ins_h]; - } while (s->strstart <= strstart-1 + prev_length // try to truncate the previous match to 1, 3, ... prev_length - && s->strstart <= s->window_size - MIN_LOOKAHEAD); // watch out for the end of the input + if (s->strstart == strstart) { // store match at current position + current_match_length = match_length; + current_match_start = s->match_start; + } + if (s->strstart - strstart + 1 < MIN_MATCH) { // previous match reduced to one or two literals + combined_gain = 0; // need one literal per byte: no gain (assuming 8 bits per literal) + } else { + combined_gain = s->strstart - strstart + 1 - MIN_MATCH; // (possibly truncated) previous_length - 3 literals + } + if (match_length < MIN_MATCH) { + combined_gain += 0; // no gain + } else { + combined_gain += match_length - MIN_MATCH; // match_length bytes are coded as three literals + } + if (combined_gain >= best_combined_gain) { // in case of a tie we prefer the longer prev_length + best_combined_gain = combined_gain; + best_prev_length = s->strstart - strstart + 1; + } + s->strstart++; + s->lookahead--; + UPDATE_HASH(s, s->ins_h, s->window[(s->strstart) + (MIN_MATCH-1)]); + hash_head = s->head[s->ins_h]; + } while (s->strstart <= strstart-1 + prev_length // try to truncate the previous match to 1, 3, ... prev_length + && s->strstart <= s->window_size - MIN_LOOKAHEAD); // watch out for the end of the input - s->strstart = strstart_save; - s->lookahead = lookahead_save; - s->ins_h = ins_h_save; - s->match_length = current_match_length; - s->match_start = current_match_start; - if (best_prev_length >= MIN_MATCH) { - s->prev_length = best_prev_length; - s->match_length = MIN_MATCH - 1; - } else { - s->prev_length = MIN_MATCH - 1; - } - return best_combined_gain; + s->strstart = strstart_save; + s->lookahead = lookahead_save; + s->ins_h = ins_h_save; + s->match_length = current_match_length; + s->match_start = current_match_start; + if (best_prev_length >= MIN_MATCH) { + s->prev_length = best_prev_length; + s->match_length = MIN_MATCH - 1; + } else { + s->prev_length = MIN_MATCH - 1; + } + return best_combined_gain; } #endif @@ -1850,9 +1850,9 @@ local block_state deflate_slow(s, flush) s->match_length = MIN_MATCH-1; #ifdef ZLIB_PM3_TUNED - if (s->prev_length < s->max_lazy_match) { - try_harder(s, s->strstart, s->lookahead, hash_head); - } + if (s->prev_length < s->max_lazy_match) { + try_harder(s, s->strstart, s->lookahead, hash_head); + } #else if (hash_head != NIL && s->prev_length < s->max_lazy_match && diff --git a/zlib/inflate.c b/zlib/inflate.c index 1b3003370..40d9f568f 100644 --- a/zlib/inflate.c +++ b/zlib/inflate.c @@ -857,7 +857,7 @@ int flush; case 1: /* fixed block */ #ifdef ZLIB_PM3_TUNED strm->msg = (char *)"fixed block coding not supported"; - state->mode = BAD; + state->mode = BAD; #else fixedtables(state); Tracev((stderr, "inflate: fixed codes block%s\n", diff --git a/zlib/trees.c b/zlib/trees.c index 9d032bf9c..eff4d8545 100644 --- a/zlib/trees.c +++ b/zlib/trees.c @@ -989,7 +989,7 @@ void ZLIB_INTERNAL _tr_flush_block(s, buf, stored_len, last) #endif } else { #endif /* !ZLIB_PM3_TUNED */ - send_bits(s, (DYN_TREES<<1)+last, 3); + send_bits(s, (DYN_TREES<<1)+last, 3); send_all_trees(s, s->l_desc.max_code+1, s->d_desc.max_code+1, max_blindex+1); compress_block(s, (const ct_data *)s->dyn_ltree, From 957464ca88da52fbfee44b217a8a31716563b4a0 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 11:19:45 +0100 Subject: [PATCH 0692/1938] armsrc Standalone: fix mix of spaces & tabs --- armsrc/Standalone/hf_bog.c | 390 +++++++++++++-------------- armsrc/Standalone/hf_colin.c | 18 +- armsrc/Standalone/hf_mattyrun.c | 410 ++++++++++++++-------------- armsrc/Standalone/hf_mattyrun.h | 4 +- armsrc/Standalone/hf_young.c | 414 ++++++++++++++-------------- armsrc/Standalone/lf_hidbrute.c | 444 +++++++++++++++---------------- armsrc/Standalone/lf_proxbrute.c | 244 ++++++++--------- armsrc/Standalone/lf_samyrun.c | 196 +++++++------- armsrc/Standalone/readme.md | 80 +++--- 9 files changed, 1100 insertions(+), 1100 deletions(-) diff --git a/armsrc/Standalone/hf_bog.c b/armsrc/Standalone/hf_bog.c index 1f62e4c0c..826fab0ee 100644 --- a/armsrc/Standalone/hf_bog.c +++ b/armsrc/Standalone/hf_bog.c @@ -28,20 +28,20 @@ from the client to view the stored quadlets. #define MAX_PWDS_PER_SESSION 64 uint8_t FindOffsetInFlash() { - uint8_t mem[4] = { 0x00, 0x00, 0x00, 0x00 }; - uint8_t eom[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; - uint8_t memcnt = 0; + uint8_t mem[4] = { 0x00, 0x00, 0x00, 0x00 }; + uint8_t eom[4] = { 0xFF, 0xFF, 0xFF, 0xFF }; + uint8_t memcnt = 0; - while (memcnt < 0xFF) - { - Flash_ReadData(memcnt, mem, 4); - if (memcmp(mem, eom, 4) == 0) { - return memcnt; - } - memcnt += 4; - } + while (memcnt < 0xFF) + { + Flash_ReadData(memcnt, mem, 4); + if (memcmp(mem, eom, 4) == 0) { + return memcnt; + } + memcnt += 4; + } - return 0; // wrap-around + return 0; // wrap-around } void EraseMemory() { @@ -55,247 +55,247 @@ void EraseMemory() { if (MF_DBGLEVEL > 1) Dbprintf("[!] Erased flash!"); FlashStop(); - SpinDelay(100); + SpinDelay(100); } // This is actually copied from SniffIso14443a void RAMFUNC SniffAndStore(uint8_t param) { - iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); + iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); - // Allocate memory from BigBuf for some buffers - // free all previous allocations first - BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); - set_tracing(true); + // Allocate memory from BigBuf for some buffers + // free all previous allocations first + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); - // Array to store the authpwds - uint8_t *capturedPwds = BigBuf_malloc(4 * MAX_PWDS_PER_SESSION); + // Array to store the authpwds + uint8_t *capturedPwds = BigBuf_malloc(4 * MAX_PWDS_PER_SESSION); - // The command (reader -> tag) that we're receiving. - uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); - uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE); + // The command (reader -> tag) that we're receiving. + uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); + uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE); - // The response (tag -> reader) that we're receiving. - uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE); - uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE); + // The response (tag -> reader) that we're receiving. + uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE); + uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE); - // The DMA buffer, used to stream samples from the FPGA - uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); - uint8_t *data = dmaBuf; + // The DMA buffer, used to stream samples from the FPGA + uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); + uint8_t *data = dmaBuf; - uint8_t previous_data = 0; - int dataLen = 0; - bool TagIsActive = false; - bool ReaderIsActive = false; + uint8_t previous_data = 0; + int dataLen = 0; + bool TagIsActive = false; + bool ReaderIsActive = false; - // Set up the demodulator for tag -> reader responses. - DemodInit(receivedResp, receivedRespPar); + // Set up the demodulator for tag -> reader responses. + DemodInit(receivedResp, receivedRespPar); - // Set up the demodulator for the reader -> tag commands - UartInit(receivedCmd, receivedCmdPar); + // Set up the demodulator for the reader -> tag commands + UartInit(receivedCmd, receivedCmdPar); - // Setup and start DMA. - if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE) ){ - if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); - return; - } + // Setup and start DMA. + if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE) ){ + if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); + return; + } - tUart* uart = GetUart(); - tDemod* demod = GetDemod(); + tUart* uart = GetUart(); + tDemod* demod = GetDemod(); - // We won't start recording the frames that we acquire until we trigger; - // a good trigger condition to get started is probably when we see a - // response from the tag. - // triggered == false -- to wait first for card - bool triggered = !(param & 0x03); + // We won't start recording the frames that we acquire until we trigger; + // a good trigger condition to get started is probably when we see a + // response from the tag. + // triggered == false -- to wait first for card + bool triggered = !(param & 0x03); - uint32_t rsamples = 0; + uint32_t rsamples = 0; - // Current captured passwords counter - uint8_t auth_attempts = 0; + // Current captured passwords counter + uint8_t auth_attempts = 0; - SpinDelay(50); + SpinDelay(50); - // loop and listen - while (!BUTTON_PRESS()) { + // loop and listen + while (!BUTTON_PRESS()) { WDT_HIT(); LED_A_ON(); - int register readBufDataP = data - dmaBuf; - int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; - if (readBufDataP <= dmaBufDataP) - dataLen = dmaBufDataP - readBufDataP; - else - dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; + int register readBufDataP = data - dmaBuf; + int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; + if (readBufDataP <= dmaBufDataP) + dataLen = dmaBufDataP - readBufDataP; + else + dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; - // test for length of buffer - if (dataLen > DMA_BUFFER_SIZE) { // TODO: Check if this works properly - Dbprintf("[!] blew circular buffer! | datalen %u", dataLen); - break; - } - if (dataLen < 1) continue; + // test for length of buffer + if (dataLen > DMA_BUFFER_SIZE) { // TODO: Check if this works properly + Dbprintf("[!] blew circular buffer! | datalen %u", dataLen); + break; + } + if (dataLen < 1) continue; - // primary buffer was stopped( <-- we lost data! - if (!AT91C_BASE_PDC_SSC->PDC_RCR) { - AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE; - //Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary - } - // secondary buffer sets as primary, secondary buffer was stopped - if (!AT91C_BASE_PDC_SSC->PDC_RNCR) { - AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; - } + // primary buffer was stopped( <-- we lost data! + if (!AT91C_BASE_PDC_SSC->PDC_RCR) { + AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf; + AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE; + //Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary + } + // secondary buffer sets as primary, secondary buffer was stopped + if (!AT91C_BASE_PDC_SSC->PDC_RNCR) { + AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; + AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; + } - LED_A_OFF(); + LED_A_OFF(); - // Need two samples to feed Miller and Manchester-Decoder - if (rsamples & 0x01) { + // Need two samples to feed Miller and Manchester-Decoder + if (rsamples & 0x01) { - if (!TagIsActive) { // no need to try decoding reader data if the tag is sending - uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4); - if (MillerDecoding(readerdata, (rsamples-1)*4)) { - LED_C_ON(); + if (!TagIsActive) { // no need to try decoding reader data if the tag is sending + uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4); + if (MillerDecoding(readerdata, (rsamples-1)*4)) { + LED_C_ON(); - // check - if there is a short 7bit request from reader - if ((!triggered) && (param & 0x02) && (uart->len == 1) && (uart->bitCount == 7)) triggered = true; + // check - if there is a short 7bit request from reader + if ((!triggered) && (param & 0x02) && (uart->len == 1) && (uart->bitCount == 7)) triggered = true; - if (triggered) { - if ((receivedCmd) && ((receivedCmd[0] == MIFARE_ULEV1_AUTH) || (receivedCmd[0] == MIFARE_ULC_AUTH_1))) { - if (MF_DBGLEVEL > 1) Dbprintf("PWD-AUTH KEY: 0x%02x%02x%02x%02x", receivedCmd[1], receivedCmd[2], receivedCmd[3], receivedCmd[4]); + if (triggered) { + if ((receivedCmd) && ((receivedCmd[0] == MIFARE_ULEV1_AUTH) || (receivedCmd[0] == MIFARE_ULC_AUTH_1))) { + if (MF_DBGLEVEL > 1) Dbprintf("PWD-AUTH KEY: 0x%02x%02x%02x%02x", receivedCmd[1], receivedCmd[2], receivedCmd[3], receivedCmd[4]); - // temporarily save the captured pwd in our array - memcpy(&capturedPwds[4 * auth_attempts], receivedCmd+1, 4); - auth_attempts++; - } + // temporarily save the captured pwd in our array + memcpy(&capturedPwds[4 * auth_attempts], receivedCmd+1, 4); + auth_attempts++; + } - if (!LogTrace(receivedCmd, - uart->len, - uart->startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, - uart->endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, - uart->parity, - true)) break; - } - /* ready to receive another command. */ - UartReset(); - /* reset the demod code, which might have been */ - /* false-triggered by the commands from the reader. */ - DemodReset(); - LED_B_OFF(); - } - ReaderIsActive = (uart->state != STATE_UNSYNCD); - } + if (!LogTrace(receivedCmd, + uart->len, + uart->startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, + uart->endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, + uart->parity, + true)) break; + } + /* ready to receive another command. */ + UartReset(); + /* reset the demod code, which might have been */ + /* false-triggered by the commands from the reader. */ + DemodReset(); + LED_B_OFF(); + } + ReaderIsActive = (uart->state != STATE_UNSYNCD); + } - // no need to try decoding tag data if the reader is sending - and we cannot afford the time - if (!ReaderIsActive) { - uint8_t tagdata = (previous_data << 4) | (*data & 0x0F); - if (ManchesterDecoding(tagdata, 0, (rsamples-1)*4)) { - LED_B_ON(); + // no need to try decoding tag data if the reader is sending - and we cannot afford the time + if (!ReaderIsActive) { + uint8_t tagdata = (previous_data << 4) | (*data & 0x0F); + if (ManchesterDecoding(tagdata, 0, (rsamples-1)*4)) { + LED_B_ON(); - if (!LogTrace(receivedResp, - demod->len, - demod->startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, - demod->endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, - demod->parity, - false)) break; + if (!LogTrace(receivedResp, + demod->len, + demod->startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, + demod->endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, + demod->parity, + false)) break; - if ((!triggered) && (param & 0x01)) triggered = true; + if ((!triggered) && (param & 0x01)) triggered = true; - // ready to receive another response. - DemodReset(); - // reset the Miller decoder including its (now outdated) input buffer - UartReset(); - //UartInit(receivedCmd, receivedCmdPar); - LED_C_OFF(); - } - TagIsActive = (demod->state != DEMOD_UNSYNCD); - } - } + // ready to receive another response. + DemodReset(); + // reset the Miller decoder including its (now outdated) input buffer + UartReset(); + //UartInit(receivedCmd, receivedCmdPar); + LED_C_OFF(); + } + TagIsActive = (demod->state != DEMOD_UNSYNCD); + } + } - previous_data = *data; - rsamples++; - data++; - if (data == dmaBuf + DMA_BUFFER_SIZE) { - data = dmaBuf; - } - } // end main loop + previous_data = *data; + rsamples++; + data++; + if (data == dmaBuf + DMA_BUFFER_SIZE) { + data = dmaBuf; + } + } // end main loop - FpgaDisableSscDma(); - set_tracing(false); + FpgaDisableSscDma(); + set_tracing(false); - Dbprintf("Stopped sniffing"); + Dbprintf("Stopped sniffing"); - SpinDelay(200); + SpinDelay(200); - // Write stuff to flash - if (auth_attempts > 0) { - if (MF_DBGLEVEL > 1) Dbprintf("[!] Authentication attempts = %u", auth_attempts); + // Write stuff to flash + if (auth_attempts > 0) { + if (MF_DBGLEVEL > 1) Dbprintf("[!] Authentication attempts = %u", auth_attempts); - // Setting the SPI Baudrate to 48MHz to avoid the bit-flip issue (https://github.com/RfidResearchGroup/proxmark3/issues/34) - FlashmemSetSpiBaudrate(48000000); + // Setting the SPI Baudrate to 48MHz to avoid the bit-flip issue (https://github.com/RfidResearchGroup/proxmark3/issues/34) + FlashmemSetSpiBaudrate(48000000); - // Find the offset in flash mem to continue writing the auth attempts - uint8_t memoffset = FindOffsetInFlash(); - if (MF_DBGLEVEL > 1) Dbprintf("[!] Memory offset = %u", memoffset); + // Find the offset in flash mem to continue writing the auth attempts + uint8_t memoffset = FindOffsetInFlash(); + if (MF_DBGLEVEL > 1) Dbprintf("[!] Memory offset = %u", memoffset); - if ((memoffset + 4 * auth_attempts) > 0xFF) - { - // We opt to keep the new data only - memoffset = 0; - if (MF_DBGLEVEL > 1) Dbprintf("[!] Size of total data > 256 bytes. Discarding the old data."); - } + if ((memoffset + 4 * auth_attempts) > 0xFF) + { + // We opt to keep the new data only + memoffset = 0; + if (MF_DBGLEVEL > 1) Dbprintf("[!] Size of total data > 256 bytes. Discarding the old data."); + } - // Get previous data from flash mem - uint8_t *previousdata = BigBuf_malloc(memoffset); - if (memoffset > 0) - { - uint16_t readlen = Flash_ReadData(0, previousdata, memoffset); - if (MF_DBGLEVEL > 1) Dbprintf("[!] Read %u bytes from flash mem", readlen); - } + // Get previous data from flash mem + uint8_t *previousdata = BigBuf_malloc(memoffset); + if (memoffset > 0) + { + uint16_t readlen = Flash_ReadData(0, previousdata, memoffset); + if (MF_DBGLEVEL > 1) Dbprintf("[!] Read %u bytes from flash mem", readlen); + } - // create new bigbuf to hold all data - size_t total_size = memoffset + 4 * auth_attempts; - uint8_t *total_data = BigBuf_malloc(total_size); + // create new bigbuf to hold all data + size_t total_size = memoffset + 4 * auth_attempts; + uint8_t *total_data = BigBuf_malloc(total_size); - // Add the previousdata array into total_data array - memcpy(total_data, previousdata, memoffset); + // Add the previousdata array into total_data array + memcpy(total_data, previousdata, memoffset); - // Copy bytes of capturedPwds immediately following bytes of previousdata - memcpy(total_data + memoffset, capturedPwds, 4 * auth_attempts); + // Copy bytes of capturedPwds immediately following bytes of previousdata + memcpy(total_data + memoffset, capturedPwds, 4 * auth_attempts); - // Erase first page of flash mem - EraseMemory(); + // Erase first page of flash mem + EraseMemory(); - // Write total data to flash mem - uint16_t writelen = Flash_WriteData(0, total_data, memoffset + 4 * auth_attempts); - if (MF_DBGLEVEL > 1) Dbprintf("[!] Wrote %u bytes into flash mem", writelen); + // Write total data to flash mem + uint16_t writelen = Flash_WriteData(0, total_data, memoffset + 4 * auth_attempts); + if (MF_DBGLEVEL > 1) Dbprintf("[!] Wrote %u bytes into flash mem", writelen); // If pwd saved successfully, blink led A three times - if (writelen > 0) { - SpinErr(0, 200, 5); // blink led A - } + if (writelen > 0) { + SpinErr(0, 200, 5); // blink led A + } - SpinDelay(100); + SpinDelay(100); - // Reset the SPI Baudrate to the default value (24MHz) - FlashmemSetSpiBaudrate(24000000); - } + // Reset the SPI Baudrate to the default value (24MHz) + FlashmemSetSpiBaudrate(24000000); + } } void RunMod() { - StandAloneMode(); + StandAloneMode(); - Dbprintf(">> Bogiton 14a Sniff UL/UL-EV1/NTAG a.k.a BogitoRun Started <<"); - Dbprintf("Starting to sniff"); + Dbprintf(">> Bogiton 14a Sniff UL/UL-EV1/NTAG a.k.a BogitoRun Started <<"); + Dbprintf("Starting to sniff"); - // param: - // bit 0 - trigger from first card answer - // bit 1 - trigger from first reader 7-bit request - SniffAndStore(0); - LEDsoff(); - SpinDelay(300); - Dbprintf("- [ End ] -> You can take shell back ..."); - Dbprintf("- [ ! ] -> use 'script run read_pwd_mem' to print passwords"); + // param: + // bit 0 - trigger from first card answer + // bit 1 - trigger from first reader 7-bit request + SniffAndStore(0); + LEDsoff(); + SpinDelay(300); + Dbprintf("- [ End ] -> You can take shell back ..."); + Dbprintf("- [ ! ] -> use 'script run read_pwd_mem' to print passwords"); } diff --git a/armsrc/Standalone/hf_colin.c b/armsrc/Standalone/hf_colin.c index c1b8d65ab..229236376 100644 --- a/armsrc/Standalone/hf_colin.c +++ b/armsrc/Standalone/hf_colin.c @@ -171,8 +171,8 @@ void WriteTagToFlash(uint8_t index, size_t size) while (bytes_remaining > 0) { - Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); @@ -210,7 +210,7 @@ void WriteTagToFlash(uint8_t index, size_t size) void RunMod() { - StandAloneMode(); + StandAloneMode(); FpgaDownloadAndGo(FPGA_BITSTREAM_HF); currline = 20; @@ -323,12 +323,12 @@ ACCBITS : 796788[00]+VALUE { for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { - foundKey[t][sectorNo][0] = 0xFF; - foundKey[t][sectorNo][1] = 0xFF; - foundKey[t][sectorNo][2] = 0xFF; - foundKey[t][sectorNo][3] = 0xFF; - foundKey[t][sectorNo][4] = 0xFF; - foundKey[t][sectorNo][5] = 0xFF; + foundKey[t][sectorNo][0] = 0xFF; + foundKey[t][sectorNo][1] = 0xFF; + foundKey[t][sectorNo][2] = 0xFF; + foundKey[t][sectorNo][3] = 0xFF; + foundKey[t][sectorNo][4] = 0xFF; + foundKey[t][sectorNo][5] = 0xFF; } } diff --git a/armsrc/Standalone/hf_mattyrun.c b/armsrc/Standalone/hf_mattyrun.c index 1f3d4b70c..1061d9bfe 100644 --- a/armsrc/Standalone/hf_mattyrun.c +++ b/armsrc/Standalone/hf_mattyrun.c @@ -215,244 +215,244 @@ static int saMifareChkKeys(uint8_t blockNo, uint8_t keyType, bool clearTrace, ui void RunMod() { - StandAloneMode(); - Dbprintf(">> Matty mifare chk/dump/sim a.k.a MattyRun Started <<"); + StandAloneMode(); + Dbprintf(">> Matty mifare chk/dump/sim a.k.a MattyRun Started <<"); FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - /* - It will check if the keys from the attacked tag are a subset from - the hardcoded set of keys inside of the ARM. If this is the case - then it will load the keys into the emulator memory and also the - content of the victim tag, to finally simulate it. + /* + It will check if the keys from the attacked tag are a subset from + the hardcoded set of keys inside of the ARM. If this is the case + then it will load the keys into the emulator memory and also the + content of the victim tag, to finally simulate it. - Alternatively, it can be dumped into a blank card. + Alternatively, it can be dumped into a blank card. - This source code has been tested only in Mifare 1k. + This source code has been tested only in Mifare 1k. - If you're using the proxmark connected to a device that has an OS, and you're not using the proxmark3 client to see the debug - messages, you MUST uncomment usb_disable(). - */ + If you're using the proxmark connected to a device that has an OS, and you're not using the proxmark3 client to see the debug + messages, you MUST uncomment usb_disable(). + */ - // Comment this line below if you want to see debug messages. + // Comment this line below if you want to see debug messages. // usb_disable(); /* - Pseudo-configuration block. + Pseudo-configuration block. */ - bool printKeys = false; // Prints keys - bool transferToEml = true; // Transfer keys to emulator memory - bool ecfill = true; // Fill emulator memory with cards content. - bool simulation = true; // Simulates an exact copy of the target tag - bool fillFromEmulator = false; // Dump emulator memory. + bool printKeys = false; // Prints keys + bool transferToEml = true; // Transfer keys to emulator memory + bool ecfill = true; // Fill emulator memory with cards content. + bool simulation = true; // Simulates an exact copy of the target tag + bool fillFromEmulator = false; // Dump emulator memory. - uint16_t mifare_size = 1024; // Mifare 1k (only 1k supported for now) - uint8_t sectorSize = 64; // 1k's sector size is 64 bytes. - uint8_t blockNo = 3; // Security block is number 3 for each sector. - uint8_t sectorsCnt = (mifare_size/sectorSize); - uint8_t keyType = 2; // Keytype buffer - uint64_t key64; // Defines current key - uint8_t *keyBlock = NULL; // Where the keys will be held in memory. - uint8_t stKeyBlock = 20; // Set the quantity of keys in the block. - uint8_t filled = 0; // Used to check if the memory was filled with success. - bool keyFound = false; + uint16_t mifare_size = 1024; // Mifare 1k (only 1k supported for now) + uint8_t sectorSize = 64; // 1k's sector size is 64 bytes. + uint8_t blockNo = 3; // Security block is number 3 for each sector. + uint8_t sectorsCnt = (mifare_size/sectorSize); + uint8_t keyType = 2; // Keytype buffer + uint64_t key64; // Defines current key + uint8_t *keyBlock = NULL; // Where the keys will be held in memory. + uint8_t stKeyBlock = 20; // Set the quantity of keys in the block. + uint8_t filled = 0; // Used to check if the memory was filled with success. + bool keyFound = false; - /* - Set of keys to be used. - */ - uint64_t mfKeys[] = { - 0xffffffffffff, // Default key - 0x000000000000, // Blank key - 0xa0a1a2a3a4a5, // NFCForum MAD key - 0xb0b1b2b3b4b5, - 0xaabbccddeeff, - 0x4d3a99c351dd, - 0x1a982c7e459a, - 0xd3f7d3f7d3f7, - 0x714c5c886e97, - 0x587ee5f9350f, - 0xa0478cc39091, - 0x533cb6c723f6, - 0x8fd0a4f256e9, - }; + /* + Set of keys to be used. + */ + uint64_t mfKeys[] = { + 0xffffffffffff, // Default key + 0x000000000000, // Blank key + 0xa0a1a2a3a4a5, // NFCForum MAD key + 0xb0b1b2b3b4b5, + 0xaabbccddeeff, + 0x4d3a99c351dd, + 0x1a982c7e459a, + 0xd3f7d3f7d3f7, + 0x714c5c886e97, + 0x587ee5f9350f, + 0xa0478cc39091, + 0x533cb6c723f6, + 0x8fd0a4f256e9, + }; - /* - This part allocates the byte representation of the - keys in keyBlock's memory space . - */ - keyBlock = BigBuf_malloc(stKeyBlock * 6); - int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t); + /* + This part allocates the byte representation of the + keys in keyBlock's memory space . + */ + keyBlock = BigBuf_malloc(stKeyBlock * 6); + int mfKeysCnt = sizeof(mfKeys) / sizeof(uint64_t); - for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) { - num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t*)(keyBlock + mfKeyCounter * 6)); - } + for (int mfKeyCounter = 0; mfKeyCounter < mfKeysCnt; mfKeyCounter++) { + num_to_bytes(mfKeys[mfKeyCounter], 6, (uint8_t*)(keyBlock + mfKeyCounter * 6)); + } - /* - Pretty print of the keys to be checked. - */ - if (printKeys) { - Dbprintf("[+] Printing mf keys"); - for (uint8_t keycnt = 0; keycnt < mfKeysCnt; keycnt++) - Dbprintf("[-] chk mf key[%2d] %02x%02x%02x%02x%02x%02x", keycnt, - (keyBlock + 6*keycnt)[0],(keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], - (keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6); - DbpString("--------------------------------------------------------"); - } + /* + Pretty print of the keys to be checked. + */ + if (printKeys) { + Dbprintf("[+] Printing mf keys"); + for (uint8_t keycnt = 0; keycnt < mfKeysCnt; keycnt++) + Dbprintf("[-] chk mf key[%2d] %02x%02x%02x%02x%02x%02x", keycnt, + (keyBlock + 6*keycnt)[0], (keyBlock + 6*keycnt)[1], (keyBlock + 6*keycnt)[2], + (keyBlock + 6*keycnt)[3], (keyBlock + 6*keycnt)[4], (keyBlock + 6*keycnt)[5], 6); + DbpString("--------------------------------------------------------"); + } - /* - Initialization of validKeys and foundKeys storages. - - validKey will store whether the sector has a valid A/B key. - - foundKey will store the found A/B key for each sector. - */ - bool validKey[2][40]; - uint8_t foundKey[2][40][6]; - for (uint16_t t = 0; t < 2; t++) { - for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { - validKey[t][sectorNo] = false; - for (uint16_t i = 0; i < 6; i++) { - foundKey[t][sectorNo][i] = 0xff; - } - } - } + /* + Initialization of validKeys and foundKeys storages. + - validKey will store whether the sector has a valid A/B key. + - foundKey will store the found A/B key for each sector. + */ + bool validKey[2][40]; + uint8_t foundKey[2][40][6]; + for (uint16_t t = 0; t < 2; t++) { + for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { + validKey[t][sectorNo] = false; + for (uint16_t i = 0; i < 6; i++) { + foundKey[t][sectorNo][i] = 0xff; + } + } + } - /* - Iterates through each sector checking if there is a correct key. - */ - int key = -1; - int block = 0; - bool err = 0; - bool allKeysFound = true; - uint32_t size = mfKeysCnt; + /* + Iterates through each sector checking if there is a correct key. + */ + int key = -1; + int block = 0; + bool err = 0; + bool allKeysFound = true; + uint32_t size = mfKeysCnt; - for (int type = !keyType; type < 2 && !err; keyType == 2 ? (type++) : (type = 2)) { - block = blockNo; - for (int sec = 0; sec < sectorsCnt && !err; ++sec) { - Dbprintf("\tCurrent sector:%3d, block:%3d, key type: %c, key count: %i ", sec, block, type ? 'B':'A', mfKeysCnt); - key = saMifareChkKeys(block, type, true, size, &keyBlock[0], &key64); - if (key == -1) { - LED(LED_RED, 50); //red - Dbprintf("\t✕ Key not found for this sector!"); - allKeysFound = false; - // break; - } else if (key == -2) { - err = 1; // Can't select card. - break; - } else { - num_to_bytes(key64, 6, foundKey[type][sec]); - validKey[type][sec] = true; - keyFound = true; - Dbprintf("\t✓ Found valid key: [%02x%02x%02x%02x%02x%02x]\n", - (keyBlock + 6*key)[0], (keyBlock + 6*key)[1], (keyBlock + 6*key)[2], - (keyBlock + 6*key)[3], (keyBlock + 6*key)[4], (keyBlock + 6*key)[5] - ); - } + for (int type = !keyType; type < 2 && !err; keyType == 2 ? (type++) : (type = 2)) { + block = blockNo; + for (int sec = 0; sec < sectorsCnt && !err; ++sec) { + Dbprintf("\tCurrent sector:%3d, block:%3d, key type: %c, key count: %i ", sec, block, type ? 'B':'A', mfKeysCnt); + key = saMifareChkKeys(block, type, true, size, &keyBlock[0], &key64); + if (key == -1) { + LED(LED_RED, 50); //red + Dbprintf("\t✕ Key not found for this sector!"); + allKeysFound = false; + // break; + } else if (key == -2) { + err = 1; // Can't select card. + break; + } else { + num_to_bytes(key64, 6, foundKey[type][sec]); + validKey[type][sec] = true; + keyFound = true; + Dbprintf("\t✓ Found valid key: [%02x%02x%02x%02x%02x%02x]\n", + (keyBlock + 6*key)[0], (keyBlock + 6*key)[1], (keyBlock + 6*key)[2], + (keyBlock + 6*key)[3], (keyBlock + 6*key)[4], (keyBlock + 6*key)[5] + ); + } - block < 127 ? (block += 4) : (block += 16); - } - } + block < 127 ? (block += 4) : (block += 16); + } + } - /* - TODO: - - Get UID from tag and set accordingly in emulator memory and call mifare1ksim with right flags (iceman) - */ - if (!allKeysFound && keyFound) { - Dbprintf("\t✕ There's currently no nested attack in MattyRun, sorry!"); - LED_C_ON(); //red - LED_A_ON(); //yellow - // no room to run nested attack on device (iceman) - // Do nested attack, set allKeysFound = true; - // allKeysFound = true; - } else { - Dbprintf("\t✕ There's nothing I can do without at least a one valid key, sorry!"); - LED_C_ON(); //red - } + /* + TODO: + - Get UID from tag and set accordingly in emulator memory and call mifare1ksim with right flags (iceman) + */ + if (!allKeysFound && keyFound) { + Dbprintf("\t✕ There's currently no nested attack in MattyRun, sorry!"); + LED_C_ON(); //red + LED_A_ON(); //yellow + // no room to run nested attack on device (iceman) + // Do nested attack, set allKeysFound = true; + // allKeysFound = true; + } else { + Dbprintf("\t✕ There's nothing I can do without at least a one valid key, sorry!"); + LED_C_ON(); //red + } - /* - If enabled, transfers found keys to memory and loads target content in emulator memory. Then it simulates to be the tag it has basically cloned. - */ - if ((transferToEml) && (allKeysFound)) { + /* + If enabled, transfers found keys to memory and loads target content in emulator memory. Then it simulates to be the tag it has basically cloned. + */ + if ((transferToEml) && (allKeysFound)) { - emlClearMem(); + emlClearMem(); - uint8_t mblock[16]; - for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { - if (validKey[0][sectorNo] || validKey[1][sectorNo]) { - emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); // data, block num, blocks count (max 4) - for (uint16_t t = 0; t < 2; t++) { - if (validKey[t][sectorNo]) { - memcpy(mblock + t*10, foundKey[t][sectorNo], 6); - } - } - emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); - } - } - Dbprintf("\t✓ Found keys have been transferred to the emulator memory."); - if (ecfill) { + uint8_t mblock[16]; + for (uint16_t sectorNo = 0; sectorNo < sectorsCnt; sectorNo++) { + if (validKey[0][sectorNo] || validKey[1][sectorNo]) { + emlGetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); // data, block num, blocks count (max 4) + for (uint16_t t = 0; t < 2; t++) { + if (validKey[t][sectorNo]) { + memcpy(mblock + t*10, foundKey[t][sectorNo], 6); + } + } + emlSetMem(mblock, FirstBlockOfSector(sectorNo) + NumBlocksPerSector(sectorNo) - 1, 1); + } + } + Dbprintf("\t✓ Found keys have been transferred to the emulator memory."); + if (ecfill) { - Dbprintf("\tFilling in with key A."); - MifareECardLoad(sectorsCnt, 0, 0, &filled); - if (filled != 1) { - Dbprintf("\t✕ Failed filling with A."); - } + Dbprintf("\tFilling in with key A."); + MifareECardLoad(sectorsCnt, 0, 0, &filled); + if (filled != 1) { + Dbprintf("\t✕ Failed filling with A."); + } - Dbprintf("\tFilling in with key B."); - MifareECardLoad(sectorsCnt, 1, 0, &filled); - if (filled != 1) { - Dbprintf("\t✕ Failed filling with B."); - } + Dbprintf("\tFilling in with key B."); + MifareECardLoad(sectorsCnt, 1, 0, &filled); + if (filled != 1) { + Dbprintf("\t✕ Failed filling with B."); + } - if ((filled == 1) && simulation) { - Dbprintf("\t✓ Filled, simulation started."); + if ((filled == 1) && simulation) { + Dbprintf("\t✓ Filled, simulation started."); - // This will tell the fpga to emulate using previous keys and current target tag content. - Dbprintf("\t Press button to abort simulation at anytime."); + // This will tell the fpga to emulate using previous keys and current target tag content. + Dbprintf("\t Press button to abort simulation at anytime."); - LED_B_ON(); // green - // assuming arg0==0, use hardcoded uid 0xdeadbeaf - Mifare1ksim( FLAG_4B_UID_IN_DATA | FLAG_UID_IN_EMUL, 0, 0, uid); - LED_B_OFF(); + LED_B_ON(); // green + // assuming arg0==0, use hardcoded uid 0xdeadbeaf + Mifare1ksim( FLAG_4B_UID_IN_DATA | FLAG_UID_IN_EMUL, 0, 0, uid); + LED_B_OFF(); - /* - Needs further testing. - */ - if (fillFromEmulator) { - uint8_t retry = 5, cnt; - Dbprintf("\t Trying to dump into blank card."); - int flags = 0; - LED_A_ON(); //yellow - for (int blockNum = 0; blockNum < 16 * 4; blockNum += 1) { - cnt = 0; - emlGetMem(mblock, blockNum, 1); - // switch on field and send magic sequence - if (blockNum == 0) flags = 0x08 + 0x02; + /* + Needs further testing. + */ + if (fillFromEmulator) { + uint8_t retry = 5, cnt; + Dbprintf("\t Trying to dump into blank card."); + int flags = 0; + LED_A_ON(); //yellow + for (int blockNum = 0; blockNum < 16 * 4; blockNum += 1) { + cnt = 0; + emlGetMem(mblock, blockNum, 1); + // switch on field and send magic sequence + if (blockNum == 0) flags = 0x08 + 0x02; - // just write - if (blockNum == 1) flags = 0; + // just write + if (blockNum == 1) flags = 0; - // Done. Magic Halt and switch off field. - if (blockNum == 16 * 4 - 1) flags = 0x04 + 0x10; + // Done. Magic Halt and switch off field. + if (blockNum == 16 * 4 - 1) flags = 0x04 + 0x10; - while (!saMifareCSetBlock(0, flags & 0xFE, blockNum, mblock) && cnt <= retry) { - cnt++; - Dbprintf("\t! Could not write block. Retrying."); - } - if (cnt == retry) { - Dbprintf("\t✕ Retries failed. Aborting."); - break; - } - } + while (!saMifareCSetBlock(0, flags & 0xFE, blockNum, mblock) && cnt <= retry) { + cnt++; + Dbprintf("\t! Could not write block. Retrying."); + } + if (cnt == retry) { + Dbprintf("\t✕ Retries failed. Aborting."); + break; + } + } - if (!err) { - LED_B_ON(); - } else { - LED_C_ON(); - } + if (!err) { + LED_B_ON(); + } else { + LED_C_ON(); + } - } - } else if (filled != 1) { - Dbprintf("\t✕ Memory could not be filled due to errors."); - LED_C_ON(); - } - } - } + } + } else if (filled != 1) { + Dbprintf("\t✕ Memory could not be filled due to errors."); + LED_C_ON(); + } + } + } } \ No newline at end of file diff --git a/armsrc/Standalone/hf_mattyrun.h b/armsrc/Standalone/hf_mattyrun.h index 9bf2166ab..8b33e67c5 100644 --- a/armsrc/Standalone/hf_mattyrun.h +++ b/armsrc/Standalone/hf_mattyrun.h @@ -14,8 +14,8 @@ //#include // for bool #include "standalone.h" // standalone definitions -#include "apps.h" // debugstatements, lfops? -#include "usb_cmd.h" // mifare1ksim flags +#include "apps.h" // debugstatements, lfops? +#include "usb_cmd.h" // mifare1ksim flags #include "mifareutil.h" #define OPTS 2 diff --git a/armsrc/Standalone/hf_young.c b/armsrc/Standalone/hf_young.c index 3feb77a94..76c7b8c30 100644 --- a/armsrc/Standalone/hf_young.c +++ b/armsrc/Standalone/hf_young.c @@ -11,252 +11,252 @@ #include "hf_young.h" typedef struct { - uint8_t uid[10]; - uint8_t uidlen; - uint8_t atqa[2]; - uint8_t sak; + uint8_t uid[10]; + uint8_t uidlen; + uint8_t atqa[2]; + uint8_t sak; } __attribute__((__packed__)) card_clone_t; void RunMod() { - StandAloneMode(); - Dbprintf(">> Craig Young Mifare sniff UID/clone uid 2 magic/sim a.k.a YoungRun Started <<"); - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + StandAloneMode(); + Dbprintf(">> Craig Young Mifare sniff UID/clone uid 2 magic/sim a.k.a YoungRun Started <<"); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - int selected = 0, playing = 0, iGotoRecord = 0, iGotoClone = 0; - int cardRead[OPTS] = {0}; + int selected = 0, playing = 0, iGotoRecord = 0, iGotoClone = 0; + int cardRead[OPTS] = {0}; - card_clone_t uids[OPTS]; - iso14a_card_select_t card[OPTS]; - uint8_t params = (MAGIC_SINGLE | MAGIC_DATAIN); + card_clone_t uids[OPTS]; + iso14a_card_select_t card[OPTS]; + uint8_t params = (MAGIC_SINGLE | MAGIC_DATAIN); - LED(selected + 1, 0); + LED(selected + 1, 0); - for (;;) { - WDT_HIT(); - // exit from Standalone Mode, send a usbcommand. - if (usb_poll_validate_length()) return; + for (;;) { + WDT_HIT(); + // exit from Standalone Mode, send a usbcommand. + if (usb_poll_validate_length()) return; - SpinDelay(300); + SpinDelay(300); - if (iGotoRecord == 1 || cardRead[selected] == 0) { - iGotoRecord = 0; - LEDsoff(); - LED(selected + 1, 0); - LED(LED_RED2, 0); + if (iGotoRecord == 1 || cardRead[selected] == 0) { + iGotoRecord = 0; + LEDsoff(); + LED(selected + 1, 0); + LED(LED_RED2, 0); - // record - Dbprintf("Enabling iso14443a reader mode for [Bank: %d]...", selected); - /* need this delay to prevent catching some weird data */ - SpinDelay(500); - iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); + // record + Dbprintf("Enabling iso14443a reader mode for [Bank: %d]...", selected); + /* need this delay to prevent catching some weird data */ + SpinDelay(500); + iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); - for (;;) { - // exit from Standalone Mode, send a usbcommand. - if (usb_poll_validate_length()) return; + for (;;) { + // exit from Standalone Mode, send a usbcommand. + if (usb_poll_validate_length()) return; - if (BUTTON_PRESS()) { - if (cardRead[selected]) { - Dbprintf("Button press detected -- replaying card in bank[%d]", selected); - break; - } else if (cardRead[(selected+1) % OPTS]) { - Dbprintf("Button press detected but no card in bank[%d] so playing from bank[%d]", selected, (selected+1)%OPTS); - selected = (selected+1) % OPTS; - break; // playing = 1; - } else { - Dbprintf("Button press detected but no stored tag to play. (Ignoring button)"); - SpinDelay(300); - } - } + if (BUTTON_PRESS()) { + if (cardRead[selected]) { + Dbprintf("Button press detected -- replaying card in bank[%d]", selected); + break; + } else if (cardRead[(selected+1) % OPTS]) { + Dbprintf("Button press detected but no card in bank[%d] so playing from bank[%d]", selected, (selected+1)%OPTS); + selected = (selected+1) % OPTS; + break; // playing = 1; + } else { + Dbprintf("Button press detected but no stored tag to play. (Ignoring button)"); + SpinDelay(300); + } + } - if (!iso14443a_select_card(NULL, &card[selected], NULL, true, 0, true)) { - continue; - } else { - Dbprintf("Read UID:"); - Dbhexdump(card[selected].uidlen, card[selected].uid, 0); + if (!iso14443a_select_card(NULL, &card[selected], NULL, true, 0, true)) { + continue; + } else { + Dbprintf("Read UID:"); + Dbhexdump(card[selected].uidlen, card[selected].uid, 0); - if (memcmp(uids[(selected+1)%OPTS].uid, card[selected].uid, card[selected].uidlen ) == 0 ) { - Dbprintf("Card selected has same UID as what is stored in the other bank. Skipping."); - } else { - uids[selected].sak = card[selected].sak; - uids[selected].uidlen = card[selected].uidlen; - memcpy(uids[selected].uid , card[selected].uid, uids[selected].uidlen); - memcpy(uids[selected].atqa, card[selected].atqa, 2); + if (memcmp(uids[(selected+1)%OPTS].uid, card[selected].uid, card[selected].uidlen ) == 0 ) { + Dbprintf("Card selected has same UID as what is stored in the other bank. Skipping."); + } else { + uids[selected].sak = card[selected].sak; + uids[selected].uidlen = card[selected].uidlen; + memcpy(uids[selected].uid , card[selected].uid, uids[selected].uidlen); + memcpy(uids[selected].atqa, card[selected].atqa, 2); - if (uids[selected].uidlen > 4) - Dbprintf("Bank[%d] received a 7-byte UID", selected); - else - Dbprintf("Bank[%d] received a 4-byte UID", selected); - break; - } - } - } + if (uids[selected].uidlen > 4) + Dbprintf("Bank[%d] received a 7-byte UID", selected); + else + Dbprintf("Bank[%d] received a 4-byte UID", selected); + break; + } + } + } - Dbprintf("ATQA = %02X%02X", uids[selected].atqa[0], uids[selected].atqa[1]); - Dbprintf("SAK = %02X", uids[selected].sak); - LEDsoff(); - LED(LED_GREEN, 200); - LED(LED_ORANGE, 200); - LED(LED_GREEN, 200); - LED(LED_ORANGE, 200); + Dbprintf("ATQA = %02X%02X", uids[selected].atqa[0], uids[selected].atqa[1]); + Dbprintf("SAK = %02X", uids[selected].sak); + LEDsoff(); + LED(LED_GREEN, 200); + LED(LED_ORANGE, 200); + LED(LED_GREEN, 200); + LED(LED_ORANGE, 200); - LEDsoff(); - LED(selected + 1, 0); + LEDsoff(); + LED(selected + 1, 0); - // Next state is replay: - playing = 1; + // Next state is replay: + playing = 1; - cardRead[selected] = 1; - } + cardRead[selected] = 1; + } - /* MF Classic UID clone */ - else if (iGotoClone==1) { - iGotoClone=0; - LEDsoff(); - LED(selected + 1, 0); - LED(LED_ORANGE, 250); + /* MF Classic UID clone */ + else if (iGotoClone==1) { + iGotoClone=0; + LEDsoff(); + LED(selected + 1, 0); + LED(LED_ORANGE, 250); - // magiccards holds 4bytes uid. *usually* - uint32_t tmpuid = bytes_to_num(uids[selected].uid, 4); + // magiccards holds 4bytes uid. *usually* + uint32_t tmpuid = bytes_to_num(uids[selected].uid, 4); - // record - Dbprintf("Preparing to Clone card [Bank: %d]; uid: %08x", selected, tmpuid); + // record + Dbprintf("Preparing to Clone card [Bank: %d]; uid: %08x", selected, tmpuid); - // wait for button to be released - // Delay cloning until card is in place - while (BUTTON_PRESS()) - WDT_HIT(); + // wait for button to be released + // Delay cloning until card is in place + while (BUTTON_PRESS()) + WDT_HIT(); - Dbprintf("Starting clone. [Bank: %d]", selected); - // need this delay to prevent catching some weird data - SpinDelay(500); - // Begin clone function here: - /* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards: - UsbCommand c = {CMD_MIFARE_CSETBLOCK, {params & (0xFE | (uid == NULL ? 0:1)), blockNo, 0}}; - memcpy(c.d.asBytes, data, 16); - SendCommand(&c); + Dbprintf("Starting clone. [Bank: %d]", selected); + // need this delay to prevent catching some weird data + SpinDelay(500); + // Begin clone function here: + /* Example from client/mifarehost.c for commanding a block write for "magic Chinese" cards: + UsbCommand c = {CMD_MIFARE_CSETBLOCK, {params & (0xFE | (uid == NULL ? 0:1)), blockNo, 0}}; + memcpy(c.d.asBytes, data, 16); + SendCommand(&c); - Block read is similar: - UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, blockNo, 0}}; - We need to imitate that call with blockNo 0 to set a uid. + Block read is similar: + UsbCommand c = {CMD_MIFARE_CGETBLOCK, {params, blockNo, 0}}; + We need to imitate that call with blockNo 0 to set a uid. - The get and set commands are handled in this file: - // Work with "magic Chinese" card - case CMD_MIFARE_CSETBLOCK: - MifareCSetBlock(c->arg[0], c->arg[1], c->d.asBytes); - break; - case CMD_MIFARE_CGETBLOCK: - MifareCGetBlock(c->arg[0], c->arg[1], c->d.asBytes); - break; + The get and set commands are handled in this file: + // Work with "magic Chinese" card + case CMD_MIFARE_CSETBLOCK: + MifareCSetBlock(c->arg[0], c->arg[1], c->d.asBytes); + break; + case CMD_MIFARE_CGETBLOCK: + MifareCGetBlock(c->arg[0], c->arg[1], c->d.asBytes); + break; - mfCSetUID provides example logic for UID set workflow: - -Read block0 from card in field with MifareCGetBlock() - -Configure new values without replacing reserved bytes - memcpy(block0, uid, 4); // Copy UID bytes from byte array - // Mifare UID BCC - block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // BCC on byte 5 - Bytes 5-7 are reserved SAK and ATQA for mifare classic - -Use mfCSetBlock(0, block0, oldUID, wantWipe, MAGIC_SINGLE) to write it - */ - uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0}, testBlock0[16] = {0}; - // arg0 = Flags, arg1=blockNo - MifareCGetBlock(params, 0, oldBlock0); - if (oldBlock0[0] == 0 && oldBlock0[0] == oldBlock0[1] && oldBlock0[1] == oldBlock0[2] && oldBlock0[2] == oldBlock0[3]) { - Dbprintf("No changeable tag detected. Returning to replay mode for bank[%d]", selected); - playing = 1; - } else { - Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0], oldBlock0[1], oldBlock0[2], oldBlock0[3]); - memcpy(newBlock0, oldBlock0, 16); + mfCSetUID provides example logic for UID set workflow: + -Read block0 from card in field with MifareCGetBlock() + -Configure new values without replacing reserved bytes + memcpy(block0, uid, 4); // Copy UID bytes from byte array + // Mifare UID BCC + block0[4] = block0[0]^block0[1]^block0[2]^block0[3]; // BCC on byte 5 + Bytes 5-7 are reserved SAK and ATQA for mifare classic + -Use mfCSetBlock(0, block0, oldUID, wantWipe, MAGIC_SINGLE) to write it + */ + uint8_t oldBlock0[16] = {0}, newBlock0[16] = {0}, testBlock0[16] = {0}; + // arg0 = Flags, arg1=blockNo + MifareCGetBlock(params, 0, oldBlock0); + if (oldBlock0[0] == 0 && oldBlock0[0] == oldBlock0[1] && oldBlock0[1] == oldBlock0[2] && oldBlock0[2] == oldBlock0[3]) { + Dbprintf("No changeable tag detected. Returning to replay mode for bank[%d]", selected); + playing = 1; + } else { + Dbprintf("UID from target tag: %02X%02X%02X%02X", oldBlock0[0], oldBlock0[1], oldBlock0[2], oldBlock0[3]); + memcpy(newBlock0, oldBlock0, 16); - // Copy uid for bank (2nd is for longer UIDs not supported if classic) - memcpy(newBlock0, uids[selected].uid, 4); - newBlock0[4] = newBlock0[0] ^ newBlock0[1] ^ newBlock0[2] ^ newBlock0[3]; + // Copy uid for bank (2nd is for longer UIDs not supported if classic) + memcpy(newBlock0, uids[selected].uid, 4); + newBlock0[4] = newBlock0[0] ^ newBlock0[1] ^ newBlock0[2] ^ newBlock0[3]; - // arg0 = workFlags, arg1 = blockNo, datain - MifareCSetBlock(params, 0, newBlock0); - MifareCGetBlock(params, 0, testBlock0); + // arg0 = workFlags, arg1 = blockNo, datain + MifareCSetBlock(params, 0, newBlock0); + MifareCGetBlock(params, 0, testBlock0); - if (memcmp(testBlock0, newBlock0, 16)==0) { - DbpString("Cloned successfull!"); - cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it - playing = 0; - iGotoRecord = 1; - selected = (selected + 1) % OPTS; - } else { - Dbprintf("Clone failed. Back to replay mode on bank[%d]", selected); - playing = 1; - } - } - LEDsoff(); - LED(selected + 1, 0); - } + if (memcmp(testBlock0, newBlock0, 16)==0) { + DbpString("Cloned successfull!"); + cardRead[selected] = 0; // Only if the card was cloned successfully should we clear it + playing = 0; + iGotoRecord = 1; + selected = (selected + 1) % OPTS; + } else { + Dbprintf("Clone failed. Back to replay mode on bank[%d]", selected); + playing = 1; + } + } + LEDsoff(); + LED(selected + 1, 0); + } - // Change where to record (or begin playing) - // button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected]) - else if (playing==1) { - LEDsoff(); - LED(selected + 1, 0); + // Change where to record (or begin playing) + // button_pressed == BUTTON_SINGLE_CLICK && cardRead[selected]) + else if (playing==1) { + LEDsoff(); + LED(selected + 1, 0); - // Begin transmitting - LED(LED_GREEN, 0); - DbpString("Playing"); - for ( ; ; ) { - // exit from Standalone Mode, send a usbcommand. - if (usb_poll_validate_length()) return; + // Begin transmitting + LED(LED_GREEN, 0); + DbpString("Playing"); + for ( ; ; ) { + // exit from Standalone Mode, send a usbcommand. + if (usb_poll_validate_length()) return; - int button_action = BUTTON_HELD(1000); - if ( button_action == 0) { // No button action, proceed with sim + int button_action = BUTTON_HELD(1000); + if ( button_action == 0) { // No button action, proceed with sim - uint8_t flags = FLAG_4B_UID_IN_DATA; - uint8_t data[USB_CMD_DATA_SIZE] = {0}; // in case there is a read command received we shouldn't break + uint8_t flags = FLAG_4B_UID_IN_DATA; + uint8_t data[USB_CMD_DATA_SIZE] = {0}; // in case there is a read command received we shouldn't break - memcpy(data, uids[selected].uid, uids[selected].uidlen); + memcpy(data, uids[selected].uid, uids[selected].uidlen); - uint64_t tmpuid = bytes_to_num(uids[selected].uid, uids[selected].uidlen); + uint64_t tmpuid = bytes_to_num(uids[selected].uid, uids[selected].uidlen); - if ( uids[selected].uidlen == 7 ) { - flags = FLAG_7B_UID_IN_DATA; - Dbprintf("Simulating ISO14443a tag with uid: %014" PRIx64 " [Bank: %d]", tmpuid, selected); - } else { - Dbprintf("Simulating ISO14443a tag with uid: %08" PRIx64 " [Bank: %d]", tmpuid, selected); - } + if ( uids[selected].uidlen == 7 ) { + flags = FLAG_7B_UID_IN_DATA; + Dbprintf("Simulating ISO14443a tag with uid: %014" PRIx64 " [Bank: %d]", tmpuid, selected); + } else { + Dbprintf("Simulating ISO14443a tag with uid: %08" PRIx64 " [Bank: %d]", tmpuid, selected); + } - if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0) { - DbpString("Mifare Classic 1k"); - SimulateIso14443aTag(1, flags, data); - } else if (uids[selected].sak == 0x18 && uids[selected].atqa[0] == 0x02 && uids[selected].atqa[1] == 0) { - DbpString("Mifare Classic 4k (4b uid)"); - SimulateIso14443aTag(8, flags, data); - } else if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) { - DbpString("Mifare Classic 4k (7b uid)"); - SimulateIso14443aTag(8, flags, data); - } else if (uids[selected].sak == 0x00 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) { - DbpString("Mifare Ultralight"); - SimulateIso14443aTag(2, flags, data); - } else if (uids[selected].sak == 0x20 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0x03) { - DbpString("Mifare DESFire"); - SimulateIso14443aTag(3, flags, data); - } else { - Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation"); - SimulateIso14443aTag(1, flags, data); - } + if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0) { + DbpString("Mifare Classic 1k"); + SimulateIso14443aTag(1, flags, data); + } else if (uids[selected].sak == 0x18 && uids[selected].atqa[0] == 0x02 && uids[selected].atqa[1] == 0) { + DbpString("Mifare Classic 4k (4b uid)"); + SimulateIso14443aTag(8, flags, data); + } else if (uids[selected].sak == 0x08 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) { + DbpString("Mifare Classic 4k (7b uid)"); + SimulateIso14443aTag(8, flags, data); + } else if (uids[selected].sak == 0x00 && uids[selected].atqa[0] == 0x44 && uids[selected].atqa[1] == 0) { + DbpString("Mifare Ultralight"); + SimulateIso14443aTag(2, flags, data); + } else if (uids[selected].sak == 0x20 && uids[selected].atqa[0] == 0x04 && uids[selected].atqa[1] == 0x03) { + DbpString("Mifare DESFire"); + SimulateIso14443aTag(3, flags, data); + } else { + Dbprintf("Unrecognized tag type -- defaulting to Mifare Classic emulation"); + SimulateIso14443aTag(1, flags, data); + } - } else if (button_action == BUTTON_SINGLE_CLICK) { - selected = (selected + 1) % OPTS; - Dbprintf("Done playing. Switching to record mode on bank %d", selected); - iGotoRecord = 1; - break; - } else if (button_action == BUTTON_HOLD) { - Dbprintf("Playtime over. Begin cloning..."); - iGotoClone = 1; - break; - } - } + } else if (button_action == BUTTON_SINGLE_CLICK) { + selected = (selected + 1) % OPTS; + Dbprintf("Done playing. Switching to record mode on bank %d", selected); + iGotoRecord = 1; + break; + } else if (button_action == BUTTON_HOLD) { + Dbprintf("Playtime over. Begin cloning..."); + iGotoClone = 1; + break; + } + } - /* We pressed a button so ignore it here with a delay */ - SpinDelay(300); - LEDsoff(); - LED(selected + 1, 0); - } - } + /* We pressed a button so ignore it here with a delay */ + SpinDelay(300); + LEDsoff(); + LED(selected + 1, 0); + } + } } \ No newline at end of file diff --git a/armsrc/Standalone/lf_hidbrute.c b/armsrc/Standalone/lf_hidbrute.c index f8b41771c..b730246fa 100644 --- a/armsrc/Standalone/lf_hidbrute.c +++ b/armsrc/Standalone/lf_hidbrute.c @@ -28,296 +28,296 @@ // samy's sniff and repeat routine for LF void RunMod() { - StandAloneMode(); - Dbprintf(">> LF HID corporate bruteforce a.k.a CorporateBrute Started <<"); - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + StandAloneMode(); + Dbprintf(">> LF HID corporate bruteforce a.k.a CorporateBrute Started <<"); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - uint32_t high[OPTS], low[OPTS]; - int selected = 0; - int playing = 0; - int cardRead = 0; + uint32_t high[OPTS], low[OPTS]; + int selected = 0; + int playing = 0; + int cardRead = 0; - // Turn on selected LED - LED(selected + 1, 0); + // Turn on selected LED + LED(selected + 1, 0); - for (;;) { - WDT_HIT(); + for (;;) { + WDT_HIT(); - // exit from SamyRun, send a usbcommand. - if (usb_poll_validate_length()) break; + // exit from SamyRun, send a usbcommand. + if (usb_poll_validate_length()) break; - // Was our button held down or pressed? - int button_pressed = BUTTON_HELD(1000); - SpinDelay(300); + // Was our button held down or pressed? + int button_pressed = BUTTON_HELD(1000); + SpinDelay(300); - // Button was held for a second, begin recording - if (button_pressed > 0 && cardRead == 0) { - LEDsoff(); - LED(selected + 1, 0); - LED(LED_RED2, 0); + // Button was held for a second, begin recording + if (button_pressed > 0 && cardRead == 0) { + LEDsoff(); + LED(selected + 1, 0); + LED(LED_RED2, 0); - // record - DbpString("[=] starting recording"); + // record + DbpString("[=] starting recording"); - // wait for button to be released - while(BUTTON_PRESS()) - WDT_HIT(); + // wait for button to be released + while(BUTTON_PRESS()) + WDT_HIT(); - /* need this delay to prevent catching some weird data */ - SpinDelay(500); + /* need this delay to prevent catching some weird data */ + SpinDelay(500); - CmdHIDdemodFSK(1, &high[selected], &low[selected], 0); - Dbprintf("[=] recorded %x %x %08x", selected, high[selected], low[selected]); + CmdHIDdemodFSK(1, &high[selected], &low[selected], 0); + Dbprintf("[=] recorded %x %x %08x", selected, high[selected], low[selected]); - LEDsoff(); - LED(selected + 1, 0); - // Finished recording - // If we were previously playing, set playing off - // so next button push begins playing what we recorded - playing = 0; - cardRead = 1; - } - else if (button_pressed > 0 && cardRead == 1) { - LEDsoff(); - LED(selected + 1, 0); - LED(LED_ORANGE, 0); + LEDsoff(); + LED(selected + 1, 0); + // Finished recording + // If we were previously playing, set playing off + // so next button push begins playing what we recorded + playing = 0; + cardRead = 1; + } + else if (button_pressed > 0 && cardRead == 1) { + LEDsoff(); + LED(selected + 1, 0); + LED(LED_ORANGE, 0); - // record - Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]); + // record + Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]); - // wait for button to be released - while(BUTTON_PRESS()) - WDT_HIT(); + // wait for button to be released + while(BUTTON_PRESS()) + WDT_HIT(); - /* need this delay to prevent catching some weird data */ - SpinDelay(500); + /* need this delay to prevent catching some weird data */ + SpinDelay(500); - CopyHIDtoT55x7(0, high[selected], low[selected], 0); - Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]); + CopyHIDtoT55x7(0, high[selected], low[selected], 0); + Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]); - LEDsoff(); - LED(selected + 1, 0); - // Finished recording + LEDsoff(); + LED(selected + 1, 0); + // Finished recording - // If we were previously playing, set playing off - // so next button push begins playing what we recorded - playing = 0; - cardRead = 0; - } + // If we were previously playing, set playing off + // so next button push begins playing what we recorded + playing = 0; + cardRead = 0; + } - // Change where to record (or begin playing) - else if (button_pressed) { - // Next option if we were previously playing - if (playing) - selected = (selected + 1) % OPTS; + // Change where to record (or begin playing) + else if (button_pressed) { + // Next option if we were previously playing + if (playing) + selected = (selected + 1) % OPTS; - playing = !playing; + playing = !playing; - LEDsoff(); - LED(selected + 1, 0); + LEDsoff(); + LED(selected + 1, 0); - // Begin transmitting - if (playing && selected != 2) { + // Begin transmitting + if (playing && selected != 2) { - LED(LED_GREEN, 0); - DbpString("[=] playing"); + LED(LED_GREEN, 0); + DbpString("[=] playing"); - // wait for button to be released - while (BUTTON_PRESS()) - WDT_HIT(); + // wait for button to be released + while (BUTTON_PRESS()) + WDT_HIT(); - Dbprintf("[=] %x %x %08x", selected, high[selected], low[selected]); - CmdHIDsimTAG(high[selected], low[selected], 0); - DbpString("[=] done playing"); + Dbprintf("[=] %x %x %08x", selected, high[selected], low[selected]); + CmdHIDsimTAG(high[selected], low[selected], 0); + DbpString("[=] done playing"); - if (BUTTON_HELD(1000) > 0) - goto out; + if (BUTTON_HELD(1000) > 0) + goto out; - /* We pressed a button so ignore it here with a delay */ - SpinDelay(300); + /* We pressed a button so ignore it here with a delay */ + SpinDelay(300); - // when done, we're done playing, move to next option - selected = (selected + 1) % OPTS; - playing = !playing; - LEDsoff(); - LED(selected + 1, 0); - } - else if (playing && selected == 2) - { - // Now it work only with HID Corporate 1000 (35bit), but is easily extensible to others RFID. - // It is necessary only to calculate the correct parity. + // when done, we're done playing, move to next option + selected = (selected + 1) % OPTS; + playing = !playing; + LEDsoff(); + LED(selected + 1, 0); + } + else if (playing && selected == 2) + { + // Now it work only with HID Corporate 1000 (35bit), but is easily extensible to others RFID. + // It is necessary only to calculate the correct parity. - // Brute force code - // Check if the badge is an HID Corporate 1000 - if( (high[selected] & 0xFFFFFFF8) != 0x28 ) { - DbpString("[-] Card is not a HID Corporate 1000. Skipping bruteforce."); - continue; - } + // Brute force code + // Check if the badge is an HID Corporate 1000 + if( (high[selected] & 0xFFFFFFF8) != 0x28 ) { + DbpString("[-] Card is not a HID Corporate 1000. Skipping bruteforce."); + continue; + } - LED(LED_GREEN, 0); - DbpString("[=] entering bruteforce mode"); - // wait for button to be released - while (BUTTON_PRESS()) - WDT_HIT(); + LED(LED_GREEN, 0); + DbpString("[=] entering bruteforce mode"); + // wait for button to be released + while (BUTTON_PRESS()) + WDT_HIT(); - // Calculate Facility Code and Card Number from high and low - uint32_t cardnum = (low[selected] >> 1) & 0xFFFFF; - uint32_t fc = ((high[selected] & 1 ) << 11 ) | (low[selected] >> 21); - uint32_t original_cardnum = cardnum; + // Calculate Facility Code and Card Number from high and low + uint32_t cardnum = (low[selected] >> 1) & 0xFFFFF; + uint32_t fc = ((high[selected] & 1 ) << 11 ) | (low[selected] >> 21); + uint32_t original_cardnum = cardnum; - Dbprintf("[=] Proxbrute - starting decrementing card number"); + Dbprintf("[=] Proxbrute - starting decrementing card number"); - while (cardnum >= 0) { + while (cardnum >= 0) { - // Needed for exiting from proxbrute when button is pressed - if (BUTTON_PRESS()) { - if (BUTTON_HELD(1000) > 0) { - goto out; - } else { - while (BUTTON_PRESS()) { - WDT_HIT(); - } - break; - } - } + // Needed for exiting from proxbrute when button is pressed + if (BUTTON_PRESS()) { + if (BUTTON_HELD(1000) > 0) { + goto out; + } else { + while (BUTTON_PRESS()) { + WDT_HIT(); + } + break; + } + } - // Decrement Card Number - cardnum--; + // Decrement Card Number + cardnum--; - // Calculate checksum of HID Corporate 1000 and set card number and facility code in high and low variables - hid_corporate_1000_calculate_checksum_and_set(&high[selected], &low[selected], cardnum, fc); + // Calculate checksum of HID Corporate 1000 and set card number and facility code in high and low variables + hid_corporate_1000_calculate_checksum_and_set(&high[selected], &low[selected], cardnum, fc); - // Print actual code to brute - Dbprintf("[=] TAG ID: %x%08x (%d) - FC: %u - Card: %u", high[selected], low[selected], (low[selected] >> 1) & 0xFFFF, fc, cardnum); + // Print actual code to brute + Dbprintf("[=] TAG ID: %x%08x (%d) - FC: %u - Card: %u", high[selected], low[selected], (low[selected] >> 1) & 0xFFFF, fc, cardnum); - CmdHIDsimTAGEx(high[selected], low[selected], 1, 50000); - } + CmdHIDsimTAGEx(high[selected], low[selected], 1, 50000); + } - cardnum = original_cardnum; + cardnum = original_cardnum; - Dbprintf("[=] Proxbrute - starting incrementing card number"); + Dbprintf("[=] Proxbrute - starting incrementing card number"); - while (cardnum <= 0xFFFFF) { + while (cardnum <= 0xFFFFF) { - // Needed for exiting from proxbrute when button is pressed - if (BUTTON_PRESS()) { - if (BUTTON_HELD(1000) > 0) { - goto out; - } else { - while (BUTTON_PRESS()) { WDT_HIT(); } - break; - } - } + // Needed for exiting from proxbrute when button is pressed + if (BUTTON_PRESS()) { + if (BUTTON_HELD(1000) > 0) { + goto out; + } else { + while (BUTTON_PRESS()) { WDT_HIT(); } + break; + } + } - // Decrement Card Number - cardnum++; + // Decrement Card Number + cardnum++; - // Calculate checksum of HID Corporate 1000 and set card number and facility code in high and low variables - hid_corporate_1000_calculate_checksum_and_set(&high[selected], &low[selected], cardnum, fc); + // Calculate checksum of HID Corporate 1000 and set card number and facility code in high and low variables + hid_corporate_1000_calculate_checksum_and_set(&high[selected], &low[selected], cardnum, fc); - // Print actual code to brute - Dbprintf("[=] TAG ID: %x%08x (%d) - FC: %u - Card: %u", high[selected], low[selected], (low[selected] >> 1) & 0xFFFF, fc, cardnum); + // Print actual code to brute + Dbprintf("[=] TAG ID: %x%08x (%d) - FC: %u - Card: %u", high[selected], low[selected], (low[selected] >> 1) & 0xFFFF, fc, cardnum); - CmdHIDsimTAGEx(high[selected], low[selected], 1, 50000); - } + CmdHIDsimTAGEx(high[selected], low[selected], 1, 50000); + } - DbpString("[=] done bruteforcing"); - if (BUTTON_HELD(1000) > 0) - goto out; + DbpString("[=] done bruteforcing"); + if (BUTTON_HELD(1000) > 0) + goto out; - /* We pressed a button so ignore it here with a delay */ - SpinDelay(300); + /* We pressed a button so ignore it here with a delay */ + SpinDelay(300); - // when done, we're done playing, move to next option - selected = (selected + 1) % OPTS; - playing = !playing; - LEDsoff(); - LED(selected + 1, 0); + // when done, we're done playing, move to next option + selected = (selected + 1) % OPTS; + playing = !playing; + LEDsoff(); + LED(selected + 1, 0); - } else { - while(BUTTON_PRESS()) - WDT_HIT(); - } - } - } + } else { + while(BUTTON_PRESS()) + WDT_HIT(); + } + } + } out: - DbpString("[=] exiting"); - LEDsoff(); + DbpString("[=] exiting"); + LEDsoff(); } // Function that calculate next value for the brutforce of HID corporate 1000 void hid_corporate_1000_calculate_checksum_and_set( uint32_t *high, uint32_t *low, uint32_t cardnum, uint32_t fc) { - uint32_t new_high = 0; - uint32_t new_low = 0; + uint32_t new_high = 0; + uint32_t new_low = 0; - // Calculate new high and low base value from card number and facility code, without parity - new_low = (fc << 21) | (cardnum << 1); - new_high = 0x28 | ((fc >> 11) & 1); // 0x28 is 101000 + // Calculate new high and low base value from card number and facility code, without parity + new_low = (fc << 21) | (cardnum << 1); + new_high = 0x28 | ((fc >> 11) & 1); // 0x28 is 101000 - int n_ones; - uint32_t i; + int n_ones; + uint32_t i; - // Calculating and setting parity bit 34 - // Select only bit used for parity bit 34 in low number (10110110110110110110110110110110) - uint32_t parity_bit_34_low = new_low & 0xB6DB6DB6; - n_ones = 0; - // Calculate number of ones in low number - for ( i = 1; i != 0; i <<= 1) { - if( parity_bit_34_low & i ) - n_ones++; - } - // Calculate number of ones in high number - if (new_high & 1) - n_ones++; + // Calculating and setting parity bit 34 + // Select only bit used for parity bit 34 in low number (10110110110110110110110110110110) + uint32_t parity_bit_34_low = new_low & 0xB6DB6DB6; + n_ones = 0; + // Calculate number of ones in low number + for ( i = 1; i != 0; i <<= 1) { + if( parity_bit_34_low & i ) + n_ones++; + } + // Calculate number of ones in high number + if (new_high & 1) + n_ones++; - // Set parity bit (Even parity) - if (n_ones % 2) - new_high = new_high | 0x2; + // Set parity bit (Even parity) + if (n_ones % 2) + new_high = new_high | 0x2; - // Calculating and setting parity bit 1 - // Select only bit used for parity bit 1 in low number (01101101101101101101101101101100) - uint32_t parity_bit_1_low = new_low & 0x6DB6DB6C; - n_ones = 0; + // Calculating and setting parity bit 1 + // Select only bit used for parity bit 1 in low number (01101101101101101101101101101100) + uint32_t parity_bit_1_low = new_low & 0x6DB6DB6C; + n_ones = 0; - // Calculate number of ones in low number - for ( i=1; i != 0; i <<= 1) { - if( parity_bit_1_low & i ) - n_ones++; - } - // Calculate number of ones in high number - if ( new_high & 0x1) - n_ones++; + // Calculate number of ones in low number + for ( i=1; i != 0; i <<= 1) { + if( parity_bit_1_low & i ) + n_ones++; + } + // Calculate number of ones in high number + if ( new_high & 0x1) + n_ones++; - if ( new_high & 0x2) - n_ones++; + if ( new_high & 0x2) + n_ones++; - // Set parity bit (Odd parity) - if (!(n_ones % 2)) - new_low = new_low | 0x1; + // Set parity bit (Odd parity) + if (!(n_ones % 2)) + new_low = new_low | 0x1; - // Calculating and setting parity bit 35 - n_ones = 0; - // Calculate number of ones in low number (all bit of low, bitmask unnecessary) - for (i = 1; i != 0; i <<= 1) { - if ( new_low & i ) - n_ones++; - } - // Calculate number of ones in high number - if ( new_high & 0x1) - n_ones++; + // Calculating and setting parity bit 35 + n_ones = 0; + // Calculate number of ones in low number (all bit of low, bitmask unnecessary) + for (i = 1; i != 0; i <<= 1) { + if ( new_low & i ) + n_ones++; + } + // Calculate number of ones in high number + if ( new_high & 0x1) + n_ones++; - if ( new_high & 0x2) - n_ones++; + if ( new_high & 0x2) + n_ones++; - // Set parity bit (Odd parity) - if (!(n_ones % 2)) - new_high = new_high | 0x4; + // Set parity bit (Odd parity) + if (!(n_ones % 2)) + new_high = new_high | 0x4; - // Setting new calculated values - *low = new_low; - *high = new_high; + // Setting new calculated values + *low = new_low; + *high = new_high; } // prepare a waveform pattern in the buffer based on the ID given then diff --git a/armsrc/Standalone/lf_proxbrute.c b/armsrc/Standalone/lf_proxbrute.c index 268a96eec..7d1bdd35d 100644 --- a/armsrc/Standalone/lf_proxbrute.c +++ b/armsrc/Standalone/lf_proxbrute.c @@ -13,157 +13,157 @@ // samy's sniff and repeat routine for LF void RunMod() { - StandAloneMode(); - Dbprintf(">> LF HID proxII bruteforce a.k.a ProxBrute Started (Brad Antoniewicz) <<"); - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + StandAloneMode(); + Dbprintf(">> LF HID proxII bruteforce a.k.a ProxBrute Started (Brad Antoniewicz) <<"); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - uint32_t high[OPTS], low[OPTS]; - int selected = 0; - int playing = 0; - int cardRead = 0; + uint32_t high[OPTS], low[OPTS]; + int selected = 0; + int playing = 0; + int cardRead = 0; - // Turn on selected LED - LED(selected + 1, 0); + // Turn on selected LED + LED(selected + 1, 0); - for (;;) { - WDT_HIT(); + for (;;) { + WDT_HIT(); - // exit from SamyRun, send a usbcommand. - if (usb_poll_validate_length()) break; + // exit from SamyRun, send a usbcommand. + if (usb_poll_validate_length()) break; - // Was our button held down or pressed? - int button_pressed = BUTTON_HELD(1000); - SpinDelay(300); + // Was our button held down or pressed? + int button_pressed = BUTTON_HELD(1000); + SpinDelay(300); - // Button was held for a second, begin recording - if (button_pressed > 0 && cardRead == 0) { - LEDsoff(); - LED(selected + 1, 0); - LED(LED_RED2, 0); + // Button was held for a second, begin recording + if (button_pressed > 0 && cardRead == 0) { + LEDsoff(); + LED(selected + 1, 0); + LED(LED_RED2, 0); - // record - DbpString("[=] starting recording"); + // record + DbpString("[=] starting recording"); - // wait for button to be released - while (BUTTON_PRESS()) - WDT_HIT(); + // wait for button to be released + while (BUTTON_PRESS()) + WDT_HIT(); - /* need this delay to prevent catching some weird data */ - SpinDelay(500); + /* need this delay to prevent catching some weird data */ + SpinDelay(500); - CmdHIDdemodFSK(1, &high[selected], &low[selected], 0); - Dbprintf("[=] recorded %x %x %08x", selected, high[selected], low[selected]); + CmdHIDdemodFSK(1, &high[selected], &low[selected], 0); + Dbprintf("[=] recorded %x %x %08x", selected, high[selected], low[selected]); - LEDsoff(); - LED(selected + 1, 0); - // Finished recording - // If we were previously playing, set playing off - // so next button push begins playing what we recorded - playing = 0; - cardRead = 1; - } - else if (button_pressed > 0 && cardRead == 1) { - LEDsoff(); - LED(selected + 1, 0); - LED(LED_ORANGE, 0); + LEDsoff(); + LED(selected + 1, 0); + // Finished recording + // If we were previously playing, set playing off + // so next button push begins playing what we recorded + playing = 0; + cardRead = 1; + } + else if (button_pressed > 0 && cardRead == 1) { + LEDsoff(); + LED(selected + 1, 0); + LED(LED_ORANGE, 0); - // record - Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]); + // record + Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]); - // wait for button to be released - while (BUTTON_PRESS()) - WDT_HIT(); + // wait for button to be released + while (BUTTON_PRESS()) + WDT_HIT(); - /* need this delay to prevent catching some weird data */ - SpinDelay(500); + /* need this delay to prevent catching some weird data */ + SpinDelay(500); - CopyHIDtoT55x7(0, high[selected], low[selected], 0); - Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]); + CopyHIDtoT55x7(0, high[selected], low[selected], 0); + Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]); - LEDsoff(); - LED(selected + 1, 0); - // Finished recording + LEDsoff(); + LED(selected + 1, 0); + // Finished recording - // If we were previously playing, set playing off - // so next button push begins playing what we recorded - playing = 0; - cardRead = 0; - } + // If we were previously playing, set playing off + // so next button push begins playing what we recorded + playing = 0; + cardRead = 0; + } - // Change where to record (or begin playing) - else if (button_pressed) { - // Next option if we were previously playing - if (playing) - selected = (selected + 1) % OPTS; - playing = !playing; + // Change where to record (or begin playing) + else if (button_pressed) { + // Next option if we were previously playing + if (playing) + selected = (selected + 1) % OPTS; + playing = !playing; - LEDsoff(); - LED(selected + 1, 0); + LEDsoff(); + LED(selected + 1, 0); - // Begin transmitting - if (playing) { - LED(LED_GREEN, 0); - DbpString("[=] playing"); - // wait for button to be released - while (BUTTON_PRESS()) - WDT_HIT(); + // Begin transmitting + if (playing) { + LED(LED_GREEN, 0); + DbpString("[=] playing"); + // wait for button to be released + while (BUTTON_PRESS()) + WDT_HIT(); - /* START PROXBRUTE */ + /* START PROXBRUTE */ - /* - ProxBrute - brad a. - foundstone + /* + ProxBrute - brad a. - foundstone - Following code is a trivial brute forcer once you read a valid tag - the idea is you get a valid tag, then just try and brute force to - another priv level. The problem is that it has no idea if the code - worked or not, so its a crap shoot. One option is to time how long - it takes to get a valid ID then start from scratch every time. - */ - if ( selected == 1 ) { - DbpString("[=] entering ProxBrute Mode"); - Dbprintf("[=] current Tag: Selected = %x Facility = %08x ID = %08x", selected, high[selected], low[selected]); - LED(LED_ORANGE, 0); - LED(LED_RED, 0); - for (uint16_t i = low[selected]-1; i > 0; i--) { - if (BUTTON_PRESS()) { - DbpString("[-] told to stop"); - break; - } + Following code is a trivial brute forcer once you read a valid tag + the idea is you get a valid tag, then just try and brute force to + another priv level. The problem is that it has no idea if the code + worked or not, so its a crap shoot. One option is to time how long + it takes to get a valid ID then start from scratch every time. + */ + if ( selected == 1 ) { + DbpString("[=] entering ProxBrute Mode"); + Dbprintf("[=] current Tag: Selected = %x Facility = %08x ID = %08x", selected, high[selected], low[selected]); + LED(LED_ORANGE, 0); + LED(LED_RED, 0); + for (uint16_t i = low[selected]-1; i > 0; i--) { + if (BUTTON_PRESS()) { + DbpString("[-] told to stop"); + break; + } - Dbprintf("[=] trying Facility = %08x ID %08x", high[selected], i); - CmdHIDsimTAGEx(high[selected], i, 0, 20000); - SpinDelay(500); - } + Dbprintf("[=] trying Facility = %08x ID %08x", high[selected], i); + CmdHIDsimTAGEx(high[selected], i, 0, 20000); + SpinDelay(500); + } - } else { - DbpString("[=] RED is lit, not entering ProxBrute Mode"); - Dbprintf("[=] %x %x %x", selected, high[selected], low[selected]); - CmdHIDsimTAGEx(high[selected], low[selected], 0, 20000); - DbpString("[=] done playing"); - } + } else { + DbpString("[=] RED is lit, not entering ProxBrute Mode"); + Dbprintf("[=] %x %x %x", selected, high[selected], low[selected]); + CmdHIDsimTAGEx(high[selected], low[selected], 0, 20000); + DbpString("[=] done playing"); + } - /* END PROXBRUTE */ + /* END PROXBRUTE */ - if (BUTTON_HELD(1000) > 0) - goto out; + if (BUTTON_HELD(1000) > 0) + goto out; - /* We pressed a button so ignore it here with a delay */ - SpinDelay(300); + /* We pressed a button so ignore it here with a delay */ + SpinDelay(300); - // when done, we're done playing, move to next option - selected = (selected + 1) % OPTS; - playing = !playing; - LEDsoff(); - LED(selected + 1, 0); - } - else { - while (BUTTON_PRESS()) - WDT_HIT(); - } - } - } + // when done, we're done playing, move to next option + selected = (selected + 1) % OPTS; + playing = !playing; + LEDsoff(); + LED(selected + 1, 0); + } + else { + while (BUTTON_PRESS()) + WDT_HIT(); + } + } + } out: - DbpString("[=] exiting"); - LEDsoff(); + DbpString("[=] exiting"); + LEDsoff(); } \ No newline at end of file diff --git a/armsrc/Standalone/lf_samyrun.c b/armsrc/Standalone/lf_samyrun.c index c96a2ced6..8536260ff 100644 --- a/armsrc/Standalone/lf_samyrun.c +++ b/armsrc/Standalone/lf_samyrun.c @@ -12,132 +12,132 @@ // samy's sniff and repeat routine for LF void RunMod() { - StandAloneMode(); - Dbprintf(">> LF HID Read/Clone/Sim a.k.a SamyRun Started <<"); - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + StandAloneMode(); + Dbprintf(">> LF HID Read/Clone/Sim a.k.a SamyRun Started <<"); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - uint32_t high[OPTS], low[OPTS]; - int selected = 0; - int playing = 0; - int cardRead = 0; - bool gotCard; - // Turn on selected LED - LED(selected + 1, 0); + uint32_t high[OPTS], low[OPTS]; + int selected = 0; + int playing = 0; + int cardRead = 0; + bool gotCard; + // Turn on selected LED + LED(selected + 1, 0); - for (;;) { - WDT_HIT(); + for (;;) { + WDT_HIT(); - // exit from SamyRun, send a usbcommand. - if (usb_poll_validate_length()) break; + // exit from SamyRun, send a usbcommand. + if (usb_poll_validate_length()) break; - // Was our button held down or pressed? - int button_pressed = BUTTON_HELD(1000); + // Was our button held down or pressed? + int button_pressed = BUTTON_HELD(1000); - Dbprintf("button %d", button_pressed); - SpinDelay(300); + Dbprintf("button %d", button_pressed); + SpinDelay(300); - // Button was held for a second, begin recording - if (button_pressed > 0 && cardRead == 0) { - LEDsoff(); - LED(selected + 1, 0); - LED(LED_RED2, 0); + // Button was held for a second, begin recording + if (button_pressed > 0 && cardRead == 0) { + LEDsoff(); + LED(selected + 1, 0); + LED(LED_RED2, 0); - // record - DbpString("[=] starting recording"); + // record + DbpString("[=] starting recording"); - // wait for button to be released - while (BUTTON_PRESS()) - WDT_HIT(); + // wait for button to be released + while (BUTTON_PRESS()) + WDT_HIT(); - /* need this delay to prevent catching some weird data */ - SpinDelay(500); + /* need this delay to prevent catching some weird data */ + SpinDelay(500); - CmdHIDdemodFSK(1, &high[selected], &low[selected], 0); - Dbprintf("[=] recorded bank %x | %x %08x", selected, high[selected], low[selected]); + CmdHIDdemodFSK(1, &high[selected], &low[selected], 0); + Dbprintf("[=] recorded bank %x | %x %08x", selected, high[selected], low[selected]); - LEDsoff(); - LED(selected + 1, 0); - // Finished recording - // If we were previously playing, set playing off - // so next button push begins playing what we recorded - playing = 0; - cardRead = 1; + LEDsoff(); + LED(selected + 1, 0); + // Finished recording + // If we were previously playing, set playing off + // so next button push begins playing what we recorded + playing = 0; + cardRead = 1; - gotCard = true; - } - else if (button_pressed > 0 && cardRead == 1) { - LEDsoff(); - LED(selected + 1, 0); - LED(LED_ORANGE, 0); + gotCard = true; + } + else if (button_pressed > 0 && cardRead == 1) { + LEDsoff(); + LED(selected + 1, 0); + LED(LED_ORANGE, 0); - // record - Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]); + // record + Dbprintf("[=] cloning %x %x %08x", selected, high[selected], low[selected]); - // wait for button to be released - while (BUTTON_PRESS()) - WDT_HIT(); + // wait for button to be released + while (BUTTON_PRESS()) + WDT_HIT(); - /* need this delay to prevent catching some weird data */ - SpinDelay(500); + /* need this delay to prevent catching some weird data */ + SpinDelay(500); - CopyHIDtoT55x7(0, high[selected], low[selected], 0); - Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]); + CopyHIDtoT55x7(0, high[selected], low[selected], 0); + Dbprintf("[=] cloned %x %x %08x", selected, high[selected], low[selected]); - LEDsoff(); - LED(selected + 1, 0); - // Finished recording + LEDsoff(); + LED(selected + 1, 0); + // Finished recording - // If we were previously playing, set playing off - // so next button push begins playing what we recorded - playing = 0; - cardRead = 0; - } + // If we were previously playing, set playing off + // so next button push begins playing what we recorded + playing = 0; + cardRead = 0; + } - // Change where to record (or begin playing) - else if (button_pressed && gotCard) { - // Next option if we were previously playing - if (playing) - selected = (selected + 1) % OPTS; + // Change where to record (or begin playing) + else if (button_pressed && gotCard) { + // Next option if we were previously playing + if (playing) + selected = (selected + 1) % OPTS; - playing = !playing; + playing = !playing; - LEDsoff(); - LED(selected + 1, 0); + LEDsoff(); + LED(selected + 1, 0); - // Begin transmitting - if (playing) { + // Begin transmitting + if (playing) { - LED(LED_GREEN, 0); - DbpString("[=] playing"); + LED(LED_GREEN, 0); + DbpString("[=] playing"); - // wait for button to be released - while (BUTTON_PRESS()) - WDT_HIT(); + // wait for button to be released + while (BUTTON_PRESS()) + WDT_HIT(); - Dbprintf("[=] %x %x %08x", selected, high[selected], low[selected]); - CmdHIDsimTAG(high[selected], low[selected], false); - DbpString("[=] done playing"); + Dbprintf("[=] %x %x %08x", selected, high[selected], low[selected]); + CmdHIDsimTAG(high[selected], low[selected], false); + DbpString("[=] done playing"); - if (BUTTON_HELD(1000) > 0) - goto out; + if (BUTTON_HELD(1000) > 0) + goto out; - /* We pressed a button so ignore it here with a delay */ - SpinDelay(300); + /* We pressed a button so ignore it here with a delay */ + SpinDelay(300); - // when done, we're done playing, move to next option - selected = (selected + 1) % OPTS; - playing = !playing; - LEDsoff(); - LED(selected + 1, 0); - } - else { - while (BUTTON_PRESS()) - WDT_HIT(); - } - } - } + // when done, we're done playing, move to next option + selected = (selected + 1) % OPTS; + playing = !playing; + LEDsoff(); + LED(selected + 1, 0); + } + else { + while (BUTTON_PRESS()) + WDT_HIT(); + } + } + } out: - DbpString("[=] exiting"); - LEDsoff(); + DbpString("[=] exiting"); + LEDsoff(); } \ No newline at end of file diff --git a/armsrc/Standalone/readme.md b/armsrc/Standalone/readme.md index 618fcdc13..b694971a5 100644 --- a/armsrc/Standalone/readme.md +++ b/armsrc/Standalone/readme.md @@ -11,19 +11,19 @@ Each standalone mod needs to have its own compiler flag to be added in `armsrc\m The RunMod function is your "main" function when running. You need to check for Usb commands, in order to let the pm3 client break the standalone mode. See this basic skeleton of main function RunMod(). ```` void RunMod() { - // led show - StandAloneMode(); - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + // led show + StandAloneMode(); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - // main loop - for (;;) { - WDT_HIT(); - - // exit from standalone mode, just send a usbcommand - if (usb_poll_validate_length()) break; - - // do your standalone stuff.. - } + // main loop + for (;;) { + WDT_HIT(); + + // exit from standalone mode, just send a usbcommand + if (usb_poll_validate_length()) break; + + // do your standalone stuff.. + } ```` As it is now, you can only have one standalone mode installed at the time. @@ -47,9 +47,9 @@ Add your source code file like the following sample in the `armsrc\makefile` ``` # WITH_HF_COLIN ifneq (,$(findstring WITH_HF_COLIN,$(APP_CFLAGS))) - SRC_STANDALONE = hf_colin.c vtsend.c + SRC_STANDALONE = hf_colin.c vtsend.c else - SRC_STANDALONE = + SRC_STANDALONE = endif ``` @@ -67,36 +67,36 @@ Once all this is done, you and others can now easily compile different standalon ```` #remove one of the following defines and comment out the relevant line #in the next section to remove that particular feature from compilation. -# NO space,TABs after the "\" sign. +# NO space,TABs after the "\" sign. APP_CFLAGS = -DWITH_CRC \ - -DON_DEVICE \ - -DWITH_LF \ - -DWITH_HITAG \ - -DWITH_ISO15693 \ - -DWITH_LEGICRF \ - -DWITH_ISO14443b \ - -DWITH_ISO14443a \ - -DWITH_ICLASS \ - -DWITH_FELICA \ - -DWITH_FLASH \ - -DWITH_SMARTCARD \ - -DWITH_HFSNOOP \ - -DWITH_HF_COLIN\ - -DWITH_FPC \ - -fno-strict-aliasing -ffunction-sections -fdata-sections + -DON_DEVICE \ + -DWITH_LF \ + -DWITH_HITAG \ + -DWITH_ISO15693 \ + -DWITH_LEGICRF \ + -DWITH_ISO14443b \ + -DWITH_ISO14443a \ + -DWITH_ICLASS \ + -DWITH_FELICA \ + -DWITH_FLASH \ + -DWITH_SMARTCARD \ + -DWITH_HFSNOOP \ + -DWITH_HF_COLIN\ + -DWITH_FPC \ + -fno-strict-aliasing -ffunction-sections -fdata-sections ### IMPORTANT - move the commented variable below this line -# -DWITH_LCD \ -# -DWITH_EMV \ -# -DWITH_FPC \ +# -DWITH_LCD \ +# -DWITH_EMV \ +# -DWITH_FPC \ # # Standalone Mods #------------------------------------------------------- -# -DWITH_LF_ICERUN -# -DWITH_LF_SAMYRUN -# -DWITH_LF_PROXBRUTE -# -DWITH_LF_HIDBRUTE -# -DWITH_HF_YOUNG -# -DWITH_HF_MATTYRUN -# -DWITH_HF_COLIN +# -DWITH_LF_ICERUN +# -DWITH_LF_SAMYRUN +# -DWITH_LF_PROXBRUTE +# -DWITH_LF_HIDBRUTE +# -DWITH_HF_YOUNG +# -DWITH_HF_MATTYRUN +# -DWITH_HF_COLIN ```` From e093d1ab2927fe83d6ed073b2ad7db7676ca9d9b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 11:29:34 +0100 Subject: [PATCH 0693/1938] Adds colors, etc --- client/cmdlfem4x.c | 73 +++++++++++++++++++++++----------------------- 1 file changed, 36 insertions(+), 37 deletions(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 3024470de..843c63809 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -252,7 +252,7 @@ void printEM410x(uint32_t hi, uint64_t id) { if (!id && !hi) return; - PrintAndLogEx(NORMAL, "EM410x %s pattern found", (hi) ? "XL" : "" ); + PrintAndLogEx(SUCCESS, "EM410x %s pattern found", (hi) ? "XL" : "" ); uint64_t iii=1; uint64_t id2lo=0; @@ -549,7 +549,7 @@ int CmdEM410xBrute(const char *Cmd) { if (ukbhit()) { int gc = getchar(); (void)gc; - PrintAndLogEx(NORMAL, "\nAborted via keyboard!\n"); + PrintAndLogEx(WARNING, "\nAborted via keyboard!\n"); free(uidBlock); return 0; } @@ -583,7 +583,7 @@ int CmdEM410xWatch(const char *Cmd) { do { if (ukbhit()) { int gc = getchar(); (void)gc; - PrintAndLogEx(NORMAL, "\naborted via keyboard!\n"); + PrintAndLogEx(WARNING, "\naborted via keyboard!\n"); break; } lf_read(true, 8201); @@ -606,8 +606,8 @@ int CmdEM410xWatchnSpoof(const char *Cmd) { } int CmdEM410xWrite(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_lf_em410x_write(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_lf_em410x_write(); uint64_t id = 0xFFFFFFFFFFFFFFFF; // invalid id value int card = 0xFF; // invalid card value @@ -666,26 +666,27 @@ int CmdEM410xWrite(const char *Cmd) { } //**************** Start of EM4x50 Code ************************ -bool EM_EndParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType) { - if (rows*cols>size) return false; - uint8_t colP=0; +bool EM_EndParityTest(uint8_t *bs, size_t size, uint8_t rows, uint8_t cols, uint8_t pType) { + if (rows * cols > size) return false; + uint8_t colP = 0; //assume last col is a parity and do not test for (uint8_t colNum = 0; colNum < cols-1; colNum++) { for (uint8_t rowNum = 0; rowNum < rows; rowNum++) { - colP ^= BitStream[(rowNum*cols)+colNum]; + colP ^= bs[(rowNum * cols) + colNum]; } if (colP != pType) return false; } return true; } -bool EM_ByteParityTest(uint8_t *BitStream, size_t size, uint8_t rows, uint8_t cols, uint8_t pType) { - if (rows*cols>size) return false; - uint8_t rowP=0; +bool EM_ByteParityTest(uint8_t *bs, size_t size, uint8_t rows, uint8_t cols, uint8_t pType) { + if (rows * cols > size) return false; + + uint8_t rowP = 0; //assume last row is a parity row and do not test for (uint8_t rowNum = 0; rowNum < rows-1; rowNum++) { for (uint8_t colNum = 0; colNum < cols; colNum++) { - rowP ^= BitStream[(rowNum*cols)+colNum]; + rowP ^= bs[(rowNum * cols) + colNum]; } if (rowP != pType) return false; } @@ -755,10 +756,8 @@ uint32_t OutputEM4x50_Block(uint8_t *BitStream, size_t size, bool verbose, bool bytebits_to_byte(BitStream+i*9,8) ); } - if (pTest) - PrintAndLogEx(NORMAL, "Parity Passed"); - else - PrintAndLogEx(NORMAL, "Parity Failed"); + + PrintAndLogEx(SUCCESS, "Parity checks | %s", (pTest)? _GREEN_(Passed) : _RED_(Failed)); } return code; } @@ -949,7 +948,7 @@ int EM4x50Read(const char *Cmd, bool verbose) { //print full code: if (verbose || g_debugMode || AllPTest){ if (!complete) { - PrintAndLogEx(NORMAL, "*** Warning!"); + PrintAndLogEx(NORMAL, _RED_(*** Warning!) ); PrintAndLogEx(NORMAL, "Partial data - no end found!"); PrintAndLogEx(NORMAL, "Try again with more samples."); } @@ -958,11 +957,11 @@ int EM4x50Read(const char *Cmd, bool verbose) { for (block=0; block < end; block++){ PrintAndLogEx(NORMAL, "Block %d: %08x", block, Code[block]); } - if (AllPTest) { - PrintAndLogEx(NORMAL, "Parities Passed"); - } else { - PrintAndLogEx(NORMAL, "Parities Failed"); - PrintAndLogEx(NORMAL, "Try cleaning the read samples with 'data askedge'"); + + PrintAndLogEx(NORMAL, "Parities checks | %s", (AllPTest) ? _GREEN_(Passed) : _RED_(Failed) ); + + if (AllPTest == 0) { + PrintAndLogEx(NORMAL, "Try cleaning the read samples with " _YELLOW_('data askedge') ); } } @@ -1005,7 +1004,7 @@ bool downloadSamplesEM(){ computeSignalProperties(got, sizeof(got)); RepaintGraphWindow(); if (getSignalProperties()->isnoise) { - PrintAndLogEx(DEBUG, "No tag found"); + PrintAndLogEx(DEBUG, "No tag found - signal looks like noise"); return false; } return true; @@ -1148,7 +1147,7 @@ int EM4x05ReadWord_ext(uint8_t addr, uint32_t pwd, bool usePwd, uint32_t *word) SendCommand(&c); UsbCommand resp; if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)){ - PrintAndLogEx(DEBUG, "Command timed out"); + PrintAndLogEx(DEBUG, "timeout while waiting for reply."); return -1; } if ( !downloadSamplesEM() ) { @@ -1162,8 +1161,8 @@ int CmdEM4x05Dump(const char *Cmd) { uint8_t addr = 0; uint32_t pwd = 0; bool usePwd = false; - uint8_t ctmp = param_getchar(Cmd, 0); - if ( ctmp == 'H' || ctmp == 'h' ) return usage_lf_em4x05_dump(); + uint8_t ctmp = tolower(param_getchar(Cmd, 0)); + if ( ctmp == 'h' ) return usage_lf_em4x05_dump(); // for now use default input of 1 as invalid (unlikely 1 will be a valid password...) pwd = param_get32ex(Cmd, 0, 1, 16); @@ -1181,7 +1180,7 @@ int CmdEM4x05Dump(const char *Cmd) { if (usePwd) { PrintAndLogEx(NORMAL, " %02u | %08X", addr, pwd, word ); } else { - PrintAndLogEx(NORMAL, " 02 | cannot read"); + PrintAndLogEx(NORMAL, " 02 | " _RED_(cannot read) ); } } else { success &= EM4x05ReadWord_ext(addr, pwd, usePwd, &word); @@ -1195,8 +1194,8 @@ int CmdEM4x05Read(const char *Cmd) { uint8_t addr; uint32_t pwd; bool usePwd = false; - uint8_t ctmp = param_getchar(Cmd, 0); - if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em4x05_read(); + uint8_t ctmp = tolower(param_getchar(Cmd, 0)); + if ( strlen(Cmd) == 0 || ctmp == 'h' ) return usage_lf_em4x05_read(); addr = param_get8ex(Cmd, 0, 50, 10); pwd = param_get32ex(Cmd, 1, 1, 16); @@ -1217,13 +1216,13 @@ int CmdEM4x05Read(const char *Cmd) { if (isOk) PrintAndLogEx(NORMAL, "Address %02d | %08X - %s", addr, word, (addr > 13) ? "Lock" : ""); else - PrintAndLogEx(NORMAL, "Read Address %02d | failed",addr); + PrintAndLogEx(NORMAL, "Read Address %02d | " _RED_(failed), addr); return isOk; } int CmdEM4x05Write(const char *Cmd) { - uint8_t ctmp = param_getchar(Cmd, 0); - if ( strlen(Cmd) == 0 || ctmp == 'H' || ctmp == 'h' ) return usage_lf_em4x05_write(); + uint8_t ctmp = tolower(param_getchar(Cmd, 0)); + if ( strlen(Cmd) == 0 || ctmp == 'h' ) return usage_lf_em4x05_write(); bool usePwd = false; uint8_t addr = 50; // default to invalid address @@ -1263,9 +1262,9 @@ int CmdEM4x05Write(const char *Cmd) { uint32_t dummy = 0; int isOk = demodEM4x05resp(&dummy); if (isOk) - PrintAndLogEx(NORMAL, "Write Verified"); + PrintAndLogEx(NORMAL, "Write " _GREEN_(Verified) ); else - PrintAndLogEx(NORMAL, "Write could not be verified"); + PrintAndLogEx(NORMAL, "Write could " _RED_(not) "be verified"); return isOk; } @@ -1385,8 +1384,8 @@ int CmdEM4x05Info(const char *Cmd) { uint32_t pwd; uint32_t word = 0, block0 = 0, serial = 0; bool usePwd = false; - uint8_t ctmp = param_getchar(Cmd, 0); - if ( ctmp == 'H' || ctmp == 'h' ) return usage_lf_em4x05_info(); + uint8_t ctmp = tolower(param_getchar(Cmd, 0)); + if ( ctmp == 'h' ) return usage_lf_em4x05_info(); // for now use default input of 1 as invalid (unlikely 1 will be a valid password...) pwd = param_get32ex(Cmd, 0, 1, 16); From cc9ec2d79ce594f65a67f11dd40402ea78d60cc8 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 11:30:26 +0100 Subject: [PATCH 0694/1938] textual --- client/cmdhf14a.c | 2 +- client/cmdhffelica.c | 2 +- client/cmdhficlass.c | 4 ++-- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 90753fef8..98a6168b2 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -607,7 +607,7 @@ int CmdHF14ACUIDs(const char *Cmd) { if (ukbhit()) { int gc = getchar(); (void)gc; - PrintAndLogEx(NORMAL, "\n[!] aborted via keyboard!\n"); + PrintAndLogEx(WARNING, "\n[!] aborted via keyboard!\n"); break; } diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 2a0380fc5..7a00c2490 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -367,7 +367,7 @@ int CmdHFFelicaDumpLite(const char *Cmd) { printf("."); fflush(stdout); if (ukbhit()) { int gc = getchar(); (void)gc; - PrintAndLogEx(NORMAL, "\n[!] aborted via keyboard!\n"); + PrintAndLogEx(WARNING, "\n[!] aborted via keyboard!\n"); DropField(); return 1; } diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 25be7df47..21384d935 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -1057,7 +1057,7 @@ int CmdHFiClassReader_Dump(const char *Cmd) { printf("."); fflush(stdout); if (ukbhit()) { int gc = getchar(); (void)gc; - PrintAndLogEx(NORMAL, "\n[!] aborted via keyboard!\n"); + PrintAndLogEx(WARNING, "\n[!] aborted via keyboard!\n"); DropField(); return 0; } @@ -2061,7 +2061,7 @@ int CmdHFiClassCheckKeys(const char *Cmd) { if (ukbhit()) { int gc = getchar(); (void)gc; - PrintAndLogEx(NORMAL, "\n[!] Aborted via keyboard!\n"); + PrintAndLogEx(WARNING, "\n[!] Aborted via keyboard!\n"); goto out; } From d998602690f0872d6be9e0998783f51456e7862a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 11:31:53 +0100 Subject: [PATCH 0695/1938] textual --- client/cmdlft55xx.c | 2 +- client/cmdsmartcard.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 4acf07c3e..068fd2612 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1501,7 +1501,7 @@ int CmdT55xxWipe(const char *Cmd) { bool IsCancelled(void) { if (ukbhit()) { int gc = getchar(); (void)gc; - PrintAndLogEx(NORMAL, "\naborted via keyboard!\n"); + PrintAndLogEx(WARNING, "\naborted via keyboard!\n"); return true; } return false; diff --git a/client/cmdsmartcard.c b/client/cmdsmartcard.c index 42d777ee4..0faacd23a 100644 --- a/client/cmdsmartcard.c +++ b/client/cmdsmartcard.c @@ -901,7 +901,7 @@ static int smart_brute_sfi(bool decodeTLV){ if (ukbhit()) { int gc = getchar(); (void)gc; - PrintAndLogEx(NORMAL, "\naborted via keyboard!\n"); + PrintAndLogEx(WARNING, "\naborted via keyboard!\n"); free(buf); return 1; } From 6b9e5e04009867883dd6ab1fa07b5702433ada24 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 11:36:05 +0100 Subject: [PATCH 0696/1938] chg: unified code --- client/cmdlf.c | 3 +-- client/cmdlfparadox.c | 5 ++--- client/cmdlfpyramid.c | 3 +-- 3 files changed, 4 insertions(+), 7 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index 7358d9da1..71c429f00 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -878,8 +878,7 @@ int CmdLFfind(const char *Cmd) { if (isOnline) { // only run if graphbuffer is just noise as it should be for hitag // The improved noise detection will find Cotag. - signal_t *sp = getSignalProperties(); - if (sp->isnoise) { + if (getSignalProperties()->isnoise) { PrintAndLogEx(INFO, "Signal looks just like noise. Looking for Hitag signal now."); diff --git a/client/cmdlfparadox.c b/client/cmdlfparadox.c index 113036d6f..4ffd7ef61 100644 --- a/client/cmdlfparadox.c +++ b/client/cmdlfparadox.c @@ -41,9 +41,8 @@ int usage_lf_paradox_sim(void) { int detectParadox(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx) { //make sure buffer has data if (*size < 96*50) return -1; - - signal_t *sp = getSignalProperties(); - if (sp->isnoise) return -2; + + if (getSignalProperties()->isnoise) return -2; // FSK demodulator *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); // paradox fsk2a diff --git a/client/cmdlfpyramid.c b/client/cmdlfpyramid.c index 796301761..af8c570c5 100644 --- a/client/cmdlfpyramid.c +++ b/client/cmdlfpyramid.c @@ -52,8 +52,7 @@ int detectPyramid(uint8_t *dest, size_t *size, int *waveStartIdx) { if (*size < 128*50) return -1; //test samples are not just noise - signal_t *sp = getSignalProperties(); - if (sp->isnoise) return -2; + if (getSignalProperties()->isnoise) return -2; // FSK demodulator RF/50 FSK 10,8 *size = fskdemod(dest, *size, 50, 0, 10, 8, waveStartIdx); // pyramid fsk2 From 29adb88f32b5340f5d056648a5bfe1ba5f9a343a Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 11:49:56 +0100 Subject: [PATCH 0697/1938] fix: use correct define --- include/common.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/common.h b/include/common.h index 8c73100ff..4b4cf99f3 100644 --- a/include/common.h +++ b/include/common.h @@ -82,7 +82,7 @@ extern uint32_t FLASHMEM_SPIBAUDRATE; # define FLASH_MEM_SIGNATURE_OFFSET (FLASH_MEM_MAX_SIZE - FLASH_MEM_SIGNATURE_LEN) #endif -#if WITH_FLASH +#ifdef WITH_FLASH #ifndef T55XX_CONFIG_LEN # define T55XX_CONFIG_LEN sizeof( t55xx_config ) #endif From f4409ab3750a35f12bbdc848998f3a61ae7e22bc Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 11:51:18 +0100 Subject: [PATCH 0698/1938] chg: revert it --- armsrc/fpgaloader.c | 11 +++-------- armsrc/fpgaloader.h | 1 - 2 files changed, 3 insertions(+), 9 deletions(-) diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index 6f8489026..18430b78b 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -118,7 +118,7 @@ void SetupSpi(int mode) { // Set up the synchronous serial port, with the one set of options that we // always use when we are talking to the FPGA. Both RX and TX are enabled. //----------------------------------------------------------------------------- -void FpgaSetupSscExt(uint8_t clearPCER) { +void FpgaSetupSsc(void) { // First configure the GPIOs, and get ourselves a clock. AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_FRAME | @@ -127,10 +127,7 @@ void FpgaSetupSscExt(uint8_t clearPCER) { GPIO_SSC_CLK; AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT; - if ( clearPCER ) AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SSC); - else - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_SSC); // Now set up the SSC proper, starting from a known state. AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; @@ -152,9 +149,7 @@ void FpgaSetupSscExt(uint8_t clearPCER) { AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN; } -void FpgaSetupSsc(void) { - FpgaSetupSscExt(true); -} + //----------------------------------------------------------------------------- // Set up DMA to receive samples from the FPGA. We will use the PDC, with // a single buffer as a circular buffer (so that we just chain back to @@ -247,7 +242,7 @@ static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_s return false; } -static void DownloadFPGA_byte(unsigned char w) { +static void DownloadFPGA_byte( uint8_t w) { #define SEND_BIT(x) { if(w & (1< Date: Sat, 9 Mar 2019 11:51:46 +0100 Subject: [PATCH 0699/1938] textual --- armsrc/hfsnoop.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/armsrc/hfsnoop.c b/armsrc/hfsnoop.c index cc72c7176..d66f88276 100644 --- a/armsrc/hfsnoop.c +++ b/armsrc/hfsnoop.c @@ -20,7 +20,7 @@ static void RAMFUNC optimizedSnoop(void) dest++; } } - //setting tracelen - importsnt! it was set by buffer overflow before + //setting tracelen - important! it was set by buffer overflow before set_tracelen( BigBuf_max_traceLen()); } From cc81b5bed9023a4ac93e6d45eab4584b13051150 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 12:31:29 +0100 Subject: [PATCH 0700/1938] fix: tolower --- client/cmddata.c | 8 ++++---- client/cmdhf.c | 8 ++++---- client/cmdhf15.c | 5 ++--- client/cmdhficlass.c | 8 ++++---- client/cmdlfem4x.c | 2 +- client/cmdlft55xx.c | 6 +++--- 6 files changed, 18 insertions(+), 19 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 998ce3779..cdd26c27b 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -863,8 +863,8 @@ int CmdBitsamples(const char *Cmd) int CmdBuffClear(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_data_buffclear(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_data_buffclear(); UsbCommand c = {CMD_BUFF_CLEAR, {0,0,0}}; clearCommandBuffer(); @@ -891,8 +891,8 @@ int CmdDec(const char *Cmd) */ int CmdUndec(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_data_undecimate(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_data_undecimate(); uint8_t factor = param_get8ex(Cmd, 0, 2, 10); diff --git a/client/cmdhf.c b/client/cmdhf.c index af5aa4c2b..6931f5c14 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -38,8 +38,8 @@ int usage_hf_snoop(){ int CmdHFSearch(const char *Cmd){ - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_hf_search(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_search(); int ans = CmdHF14AInfo("s"); if (ans > 0) { @@ -94,8 +94,8 @@ int CmdHFTune(const char *Cmd) { } int CmdHFSnoop(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_hf_snoop(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_snoop(); int skippairs = param_get32ex(Cmd, 0, 0, 10); int skiptriggers = param_get32ex(Cmd, 1, 0, 10); diff --git a/client/cmdhf15.c b/client/cmdhf15.c index dc1a47f40..bdec7c339 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -476,14 +476,13 @@ int CmdHF15Demod(const char *Cmd) { // * Acquire Samples as Reader (enables carrier, sends inquiry) //helptext int CmdHF15Samples(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_15_samples(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_15_samples(); UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693, {0,0,0}}; clearCommandBuffer(); SendCommand(&c); - //download samples getSamples(0, false); return 0; } diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index 21384d935..e21de76ab 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -277,8 +277,8 @@ int CmdHFiClassList(const char *Cmd) { } int CmdHFiClassSniff(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_hf_iclass_sniff(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h' ) return usage_hf_iclass_sniff(); UsbCommand c = {CMD_SNOOP_ICLASS}; SendCommand(&c); return 0; @@ -286,8 +286,8 @@ int CmdHFiClassSniff(const char *Cmd) { int CmdHFiClassSim(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd)<1 || cmdp == 'H' || cmdp == 'h') return usage_hf_iclass_sim(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_iclass_sim(); uint8_t simType = 0; uint8_t CSN[8] = {0, 0, 0, 0, 0, 0, 0, 0}; diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 843c63809..47a05b260 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -607,7 +607,7 @@ int CmdEM410xWatchnSpoof(const char *Cmd) { int CmdEM410xWrite(const char *Cmd) { char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_lf_em410x_write(); + if (cmdp == 0x00 || cmdp == 'h') return usage_lf_em410x_write(); uint64_t id = 0xFFFFFFFFFFFFFFFF; // invalid id value int card = 0xFF; // invalid card value diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 068fd2612..285eb75bb 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1471,10 +1471,10 @@ int CmdResetRead(const char *Cmd) { int CmdT55xxWipe(const char *Cmd) { char writeData[20] = {0}; char *ptrData = writeData; - char cmdp = param_getchar(Cmd, 0); - if ( cmdp == 'h' || cmdp == 'H') return usage_t55xx_wipe(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if ( cmdp == 'h') return usage_t55xx_wipe(); - bool Q5 = (cmdp == 'q' || cmdp == 'Q'); + bool Q5 = (cmdp == 'q'); // Try with the default password to reset block 0 // With a pwd should work even if pwd bit not set From 45e8403d4d4f50c3b193c0f2eec06352c8200f25 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 12:54:39 +0100 Subject: [PATCH 0701/1938] fix: 'lf t55' - aquiredata uses getsamples --- client/cmdlft55xx.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/client/cmdlft55xx.c b/client/cmdlft55xx.c index 285eb75bb..3e4e8dc2a 100644 --- a/client/cmdlft55xx.c +++ b/client/cmdlft55xx.c @@ -1325,15 +1325,8 @@ bool AquireData( uint8_t page, uint8_t block, bool pwdmode, uint32_t password ) return false; } - uint8_t got[8000]; - if ( !GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 4000, true)) { - PrintAndLogEx(WARNING, "command execution time out"); - return false; - } - setGraphBuf(got, sizeof(got)); - // set signal properties low/high/mean/amplitude and is_noise detection - computeSignalProperties(got, sizeof(got)); - RepaintGraphWindow(); + getSamples(12000, true); + return !getSignalProperties()->isnoise; } From aebfe193dcbdd34a5fe5e7666f2a934151a2d6b7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 13:54:03 +0100 Subject: [PATCH 0702/1938] chg: 'data raw' - skip if signal is noise --- client/cmddata.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/client/cmddata.c b/client/cmddata.c index cdd26c27b..6d83a4e0b 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1041,6 +1041,9 @@ int FSKrawDemod(const char *Cmd, bool verbose) { } } + if (getSignalProperties()->isnoise) + return 0; + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; size_t BitLen = getFromGraphBuf(bits); if (BitLen == 0) return 0; @@ -1106,6 +1109,10 @@ int PSKDemod(const char *Cmd, bool verbose) { if (g_debugMode || verbose) PrintAndLogEx(WARNING, "Invalid argument: %s", Cmd); return 0; } + + if (getSignalProperties()->isnoise) + return 0; + uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; size_t BitLen = getFromGraphBuf(BitStream); if (BitLen == 0) return 0; @@ -1210,6 +1217,9 @@ int NRZrawDemod(const char *Cmd, bool verbose) { PrintAndLogEx(WARNING, "(NRZrawDemod) Invalid argument: %s", Cmd); return 0; } + + if (getSignalProperties()->isnoise) + return 0; uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; size_t BitLen = getFromGraphBuf(bits); From 6d364ec70d897235117579bf57e62972a431a807 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 14:00:46 +0100 Subject: [PATCH 0703/1938] chg: 'data detectclocks' - skip if isnoise --- client/graph.c | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/client/graph.c b/client/graph.c index db29919bc..0f7789093 100644 --- a/client/graph.c +++ b/client/graph.c @@ -96,7 +96,9 @@ bool HasGraphData(){ // Get or auto-detect ask clock rate int GetAskClock(const char *str, bool printAns) { - + if (getSignalProperties()->isnoise) + return false; + int clock = param_get32ex(str, 0, 0, 10); if (clock > 0) return clock; @@ -127,6 +129,9 @@ int GetAskClock(const char *str, bool printAns) { } uint8_t GetPskCarrier(const char *str, bool printAns) { + if (getSignalProperties()->isnoise) + return false; + uint8_t carrier = 0; uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; size_t size = getFromGraphBuf(bits); @@ -145,6 +150,10 @@ uint8_t GetPskCarrier(const char *str, bool printAns) { } int GetPskClock(const char* str, bool printAns) { + + if (getSignalProperties()->isnoise) + return -1; + int clock = param_get32ex(str, 0, 0, 10); if (clock != 0) return clock; @@ -168,10 +177,13 @@ int GetPskClock(const char* str, bool printAns) { int GetNrzClock(const char* str, bool printAns) { + if (getSignalProperties()->isnoise) + return -1; + int clock = param_get32ex(str, 0, 0, 10); if (clock != 0) return clock; - + // Auto-detect clock uint8_t grph[MAX_GRAPH_TRACE_LEN] = {0}; size_t size = getFromGraphBuf(grph); @@ -213,6 +225,10 @@ int GetFskClock(const char* str, bool printAns) { return 0; } bool fskClocks(uint8_t *fc1, uint8_t *fc2, uint8_t *rf1, int *firstClockEdge) { + + if (getSignalProperties()->isnoise) + return false; + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; size_t size = getFromGraphBuf(bits); if (size == 0) From 89db6064d063f91d3c7bfa29f7d11504ca3cf542 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 17:25:53 +0100 Subject: [PATCH 0704/1938] fix: 'lf paradox demod' - wrong check --- client/cmdlfparadox.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/cmdlfparadox.c b/client/cmdlfparadox.c index 4ffd7ef61..238d7bc00 100644 --- a/client/cmdlfparadox.c +++ b/client/cmdlfparadox.c @@ -53,7 +53,7 @@ int detectParadox(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint // 00001111 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1 size_t startIdx = 0; uint8_t preamble[] = {0,0,0,0,1,1,1,1}; - if (preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &startIdx)) return -4; //preamble not found size_t numStart = startIdx + sizeof(preamble); From 2b1b76c2a9f5bb210b8db32fd5477b39ed11b3cd Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 18:16:50 +0100 Subject: [PATCH 0705/1938] liblua: fix mix of spaces & tabs --- liblua/lapi.c | 12 +-- liblua/lapi.h | 6 +- liblua/lauxlib.c | 12 +-- liblua/lauxlib.h | 42 ++++----- liblua/lbaselib.c | 4 +- liblua/lbitlib.c | 8 +- liblua/lcode.c | 2 +- liblua/lcode.h | 8 +- liblua/lctype.c | 36 +++---- liblua/lctype.h | 52 +++++------ liblua/ldblib.c | 4 +- liblua/ldebug.c | 2 +- liblua/ldebug.h | 8 +- liblua/ldo.c | 20 ++-- liblua/ldo.h | 8 +- liblua/ldump.c | 22 ++--- liblua/lfunc.h | 4 +- liblua/lgc.c | 32 +++---- liblua/lgc.h | 84 ++++++++--------- liblua/liolib.c | 68 +++++++------- liblua/llex.c | 6 +- liblua/llex.h | 4 +- liblua/llimits.h | 112 +++++++++++----------- liblua/lmathlib.c | 4 +- liblua/lmem.c | 2 +- liblua/lmem.h | 12 +-- liblua/loadlib.c | 44 ++++----- liblua/lobject.c | 10 +- liblua/lobject.h | 232 +++++++++++++++++++++++----------------------- liblua/lopcodes.c | 82 ++++++++-------- liblua/lopcodes.h | 214 +++++++++++++++++++++--------------------- liblua/loslib.c | 22 ++--- liblua/lparser.c | 12 +-- liblua/lparser.h | 24 ++--- liblua/lstate.c | 12 +-- liblua/lstate.h | 56 +++++------ liblua/lstring.c | 2 +- liblua/lstring.h | 12 +-- liblua/lstrlib.c | 38 ++++---- liblua/ltable.c | 20 ++-- liblua/ltable.h | 10 +- liblua/ltablib.c | 2 +- liblua/ltm.h | 8 +- liblua/lua.c | 42 ++++----- liblua/lua.h | 195 +++++++++++++++++++------------------- liblua/luac.c | 88 +++++++++--------- liblua/luaconf.h | 230 ++++++++++++++++++++++----------------------- liblua/lualib.h | 20 ++-- liblua/lundump.c | 48 +++++----- liblua/lundump.h | 4 +- liblua/lvm.c | 28 +++--- liblua/lvm.h | 4 +- liblua/lzio.h | 26 +++--- 53 files changed, 1030 insertions(+), 1029 deletions(-) diff --git a/liblua/lapi.c b/liblua/lapi.c index 791d85454..3d7fa5701 100644 --- a/liblua/lapi.c +++ b/liblua/lapi.c @@ -35,21 +35,21 @@ const char lua_ident[] = /* value at a non-valid index */ -#define NONVALIDVALUE cast(TValue *, luaO_nilobject) +#define NONVALIDVALUE cast(TValue *, luaO_nilobject) /* corresponding test */ -#define isvalid(o) ((o) != luaO_nilobject) +#define isvalid(o) ((o) != luaO_nilobject) /* test for pseudo index */ -#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) +#define ispseudo(i) ((i) <= LUA_REGISTRYINDEX) /* test for valid but not pseudo index */ -#define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) +#define isstackindex(i, o) (isvalid(o) && !ispseudo(i)) #define api_checkvalidindex(L, o) api_check(L, isvalid(o), "invalid index") #define api_checkstackindex(L, i, o) \ - api_check(L, isstackindex(i, o), "index not in the stack") + api_check(L, isstackindex(i, o), "index not in the stack") static TValue *index2addr (lua_State *L, int idx) { @@ -874,7 +874,7 @@ LUA_API void lua_setuservalue (lua_State *L, int idx) { #define checkresults(L,na,nr) \ api_check(L, (nr) == LUA_MULTRET || (L->ci->top - L->top >= (nr) - (na)), \ - "results from function overflow current stack size") + "results from function overflow current stack size") LUA_API int lua_getctx (lua_State *L, int *ctx) { diff --git a/liblua/lapi.h b/liblua/lapi.h index 0909a3911..3d45c0b66 100644 --- a/liblua/lapi.h +++ b/liblua/lapi.h @@ -12,13 +12,13 @@ #include "lstate.h" #define api_incr_top(L) {L->top++; api_check(L, L->top <= L->ci->top, \ - "stack overflow");} + "stack overflow");} #define adjustresults(L,nres) \ { if ((nres) == LUA_MULTRET && L->ci->top < L->top) L->ci->top = L->top; } -#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ - "not enough elements in the stack") +#define api_checknelems(L,n) api_check(L, (n) < (L->top - L->ci->func), \ + "not enough elements in the stack") #endif diff --git a/liblua/lauxlib.c b/liblua/lauxlib.c index 2e989d661..9a91a2a4b 100644 --- a/liblua/lauxlib.c +++ b/liblua/lauxlib.c @@ -31,8 +31,8 @@ */ -#define LEVELS1 12 /* size of the first part of the stack */ -#define LEVELS2 10 /* size of the second part of the stack */ +#define LEVELS1 12 /* size of the first part of the stack */ +#define LEVELS2 10 /* size of the second part of the stack */ @@ -222,7 +222,7 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { } -#if !defined(inspectstat) /* { */ +#if !defined(inspectstat) /* { */ #if defined(LUA_USE_POSIX) @@ -241,7 +241,7 @@ LUALIB_API int luaL_fileresult (lua_State *L, int stat, const char *fname) { #endif -#endif /* } */ +#endif /* } */ LUALIB_API int luaL_execresult (lua_State *L, int stat) { @@ -428,7 +428,7 @@ LUALIB_API lua_Unsigned luaL_optunsigned (lua_State *L, int narg, ** check whether buffer is using a userdata on the stack as a temporary ** buffer */ -#define buffonstack(B) ((B)->b != (B)->initb) +#define buffonstack(B) ((B)->b != (B)->initb) /* @@ -516,7 +516,7 @@ LUALIB_API char *luaL_buffinitsize (lua_State *L, luaL_Buffer *B, size_t sz) { */ /* index of free-list header */ -#define freelist 0 +#define freelist 0 LUALIB_API int luaL_ref (lua_State *L, int t) { diff --git a/liblua/lauxlib.h b/liblua/lauxlib.h index ac4d15fbb..e9f4130a6 100644 --- a/liblua/lauxlib.h +++ b/liblua/lauxlib.h @@ -27,7 +27,7 @@ typedef struct luaL_Reg { LUALIB_API void (luaL_checkversion_) (lua_State *L, lua_Number ver); -#define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) +#define luaL_checkversion(L) luaL_checkversion_(L, LUA_VERSION_NUM) LUALIB_API int (luaL_getmetafield) (lua_State *L, int obj, const char *e); LUALIB_API int (luaL_callmeta) (lua_State *L, int obj, const char *e); @@ -75,7 +75,7 @@ LUALIB_API void (luaL_unref) (lua_State *L, int t, int ref); LUALIB_API int (luaL_loadfilex) (lua_State *L, const char *filename, const char *mode); -#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) +#define luaL_loadfile(L,f) luaL_loadfilex(L,f,NULL) LUALIB_API int (luaL_loadbufferx) (lua_State *L, const char *buff, size_t sz, const char *name, const char *mode); @@ -105,33 +105,33 @@ LUALIB_API void (luaL_requiref) (lua_State *L, const char *modname, */ -#define luaL_newlibtable(L,l) \ +#define luaL_newlibtable(L,l) \ lua_createtable(L, 0, sizeof(l)/sizeof((l)[0]) - 1) -#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) +#define luaL_newlib(L,l) (luaL_newlibtable(L,l), luaL_setfuncs(L,l,0)) -#define luaL_argcheck(L, cond,numarg,extramsg) \ - ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) -#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) -#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) -#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) -#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) -#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) -#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) +#define luaL_argcheck(L, cond,numarg,extramsg) \ + ((void)((cond) || luaL_argerror(L, (numarg), (extramsg)))) +#define luaL_checkstring(L,n) (luaL_checklstring(L, (n), NULL)) +#define luaL_optstring(L,n,d) (luaL_optlstring(L, (n), (d), NULL)) +#define luaL_checkint(L,n) ((int)luaL_checkinteger(L, (n))) +#define luaL_optint(L,n,d) ((int)luaL_optinteger(L, (n), (d))) +#define luaL_checklong(L,n) ((long)luaL_checkinteger(L, (n))) +#define luaL_optlong(L,n,d) ((long)luaL_optinteger(L, (n), (d))) -#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) +#define luaL_typename(L,i) lua_typename(L, lua_type(L,(i))) #define luaL_dofile(L, fn) \ - (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) + (luaL_loadfile(L, fn) || lua_pcall(L, 0, LUA_MULTRET, 0)) #define luaL_dostring(L, s) \ - (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) + (luaL_loadstring(L, s) || lua_pcall(L, 0, LUA_MULTRET, 0)) -#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) +#define luaL_getmetatable(L,n) (lua_getfield(L, LUA_REGISTRYINDEX, (n))) -#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) +#define luaL_opt(L,f,n,d) (lua_isnoneornil(L,(n)) ? (d) : f(L,(n))) -#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) +#define luaL_loadbuffer(L,s,sz,n) luaL_loadbufferx(L,s,sz,n,NULL) /* @@ -153,7 +153,7 @@ typedef struct luaL_Buffer { ((void)((B)->n < (B)->size || luaL_prepbuffsize((B), 1)), \ ((B)->b[(B)->n++] = (c))) -#define luaL_addsize(B,s) ((B)->n += (s)) +#define luaL_addsize(B,s) ((B)->n += (s)) LUALIB_API void (luaL_buffinit) (lua_State *L, luaL_Buffer *B); LUALIB_API char *(luaL_prepbuffsize) (luaL_Buffer *B, size_t sz); @@ -164,7 +164,7 @@ LUALIB_API void (luaL_pushresult) (luaL_Buffer *B); LUALIB_API void (luaL_pushresultsize) (luaL_Buffer *B, size_t sz); LUALIB_API char *(luaL_buffinitsize) (lua_State *L, luaL_Buffer *B, size_t sz); -#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) +#define luaL_prepbuffer(B) luaL_prepbuffsize(B, LUAL_BUFFERSIZE) /* }====================================================== */ @@ -202,7 +202,7 @@ LUALIB_API void (luaL_pushmodule) (lua_State *L, const char *modname, LUALIB_API void (luaL_openlib) (lua_State *L, const char *libname, const luaL_Reg *l, int nup); -#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) +#define luaL_register(L,n,l) (luaL_openlib(L,(n),(l),0)) #endif diff --git a/liblua/lbaselib.c b/liblua/lbaselib.c index 540e9a5cc..f5db0b9fe 100644 --- a/liblua/lbaselib.c +++ b/liblua/lbaselib.c @@ -43,7 +43,7 @@ static int luaB_print (lua_State *L) { } -#define SPACECHARS " \f\n\r\t\v" +#define SPACECHARS " \f\n\r\t\v" static int luaB_tonumber (lua_State *L) { if (lua_isnoneornil(L, 2)) { /* standard conversion */ @@ -280,7 +280,7 @@ static int luaB_loadfile (lua_State *L) { ** string to avoid it being collected while parsed. 'load' has four ** optional arguments (chunk, source name, mode, and environment). */ -#define RESERVEDSLOT 5 +#define RESERVEDSLOT 5 /* diff --git a/liblua/lbitlib.c b/liblua/lbitlib.c index 9637532e3..b1c0e2839 100644 --- a/liblua/lbitlib.c +++ b/liblua/lbitlib.c @@ -15,18 +15,18 @@ /* number of bits to consider in a number */ #if !defined(LUA_NBITS) -#define LUA_NBITS 32 +#define LUA_NBITS 32 #endif -#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) +#define ALLONES (~(((~(lua_Unsigned)0) << (LUA_NBITS - 1)) << 1)) /* macro to trim extra bits */ -#define trim(x) ((x) & ALLONES) +#define trim(x) ((x) & ALLONES) /* builds a number with 'n' ones (1 <= n <= LUA_NBITS) */ -#define mask(n) (~((ALLONES << 1) << ((n) - 1))) +#define mask(n) (~((ALLONES << 1) << ((n) - 1))) typedef lua_Unsigned b_uint; diff --git a/liblua/lcode.c b/liblua/lcode.c index 56c26ac8a..df9ee6d86 100644 --- a/liblua/lcode.c +++ b/liblua/lcode.c @@ -26,7 +26,7 @@ #include "lvm.h" -#define hasjumps(e) ((e)->t != (e)->f) +#define hasjumps(e) ((e)->t != (e)->f) static int isnumeral(expdesc *e) { diff --git a/liblua/lcode.h b/liblua/lcode.h index 5a1fa9fea..17337f1cb 100644 --- a/liblua/lcode.h +++ b/liblua/lcode.h @@ -36,13 +36,13 @@ typedef enum BinOpr { typedef enum UnOpr { OPR_MINUS, OPR_NOT, OPR_LEN, OPR_NOUNOPR } UnOpr; -#define getcode(fs,e) ((fs)->f->code[(e)->u.info]) +#define getcode(fs,e) ((fs)->f->code[(e)->u.info]) -#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) +#define luaK_codeAsBx(fs,o,A,sBx) luaK_codeABx(fs,o,A,(sBx)+MAXARG_sBx) -#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) +#define luaK_setmultret(fs,e) luaK_setreturns(fs, e, LUA_MULTRET) -#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) +#define luaK_jumpto(fs,t) luaK_patchlist(fs, luaK_jump(fs), t) LUAI_FUNC int luaK_codeABx (FuncState *fs, OpCode o, int A, unsigned int Bx); LUAI_FUNC int luaK_codeABC (FuncState *fs, OpCode o, int A, int B, int C); diff --git a/liblua/lctype.c b/liblua/lctype.c index 55e433a5d..2afccf0bb 100644 --- a/liblua/lctype.c +++ b/liblua/lctype.c @@ -9,44 +9,44 @@ #include "lctype.h" -#if !LUA_USE_CTYPE /* { */ +#if !LUA_USE_CTYPE /* { */ #include LUAI_DDEF const lu_byte luai_ctype_[UCHAR_MAX + 2] = { 0x00, /* EOZ */ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 0. */ 0x00, 0x08, 0x08, 0x08, 0x08, 0x08, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 1. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ + 0x0c, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, /* 2. */ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ + 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, 0x16, /* 3. */ 0x16, 0x16, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, - 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 4. */ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 5. */ 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x05, - 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ + 0x04, 0x15, 0x15, 0x15, 0x15, 0x15, 0x15, 0x05, /* 6. */ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, - 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ + 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, /* 7. */ 0x05, 0x05, 0x05, 0x04, 0x04, 0x04, 0x04, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 8. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* 9. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* a. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* b. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* c. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* d. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* e. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* f. */ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, }; -#endif /* } */ +#endif /* } */ diff --git a/liblua/lctype.h b/liblua/lctype.h index 99c7d1223..eda021a90 100644 --- a/liblua/lctype.h +++ b/liblua/lctype.h @@ -20,58 +20,58 @@ #if 'A' == 65 && '0' == 48 /* ASCII case: can use its own tables; faster and fixed */ -#define LUA_USE_CTYPE 0 +#define LUA_USE_CTYPE 0 #else /* must use standard C ctype */ -#define LUA_USE_CTYPE 1 +#define LUA_USE_CTYPE 1 #endif #endif -#if !LUA_USE_CTYPE /* { */ +#if !LUA_USE_CTYPE /* { */ #include #include "llimits.h" -#define ALPHABIT 0 -#define DIGITBIT 1 -#define PRINTBIT 2 -#define SPACEBIT 3 -#define XDIGITBIT 4 +#define ALPHABIT 0 +#define DIGITBIT 1 +#define PRINTBIT 2 +#define SPACEBIT 3 +#define XDIGITBIT 4 -#define MASK(B) (1 << (B)) +#define MASK(B) (1 << (B)) /* ** add 1 to char to allow index -1 (EOZ) */ -#define testprop(c,p) (luai_ctype_[(c)+1] & (p)) +#define testprop(c,p) (luai_ctype_[(c)+1] & (p)) /* ** 'lalpha' (Lua alphabetic) and 'lalnum' (Lua alphanumeric) both include '_' */ -#define lislalpha(c) testprop(c, MASK(ALPHABIT)) -#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) -#define lisdigit(c) testprop(c, MASK(DIGITBIT)) -#define lisspace(c) testprop(c, MASK(SPACEBIT)) -#define lisprint(c) testprop(c, MASK(PRINTBIT)) -#define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) +#define lislalpha(c) testprop(c, MASK(ALPHABIT)) +#define lislalnum(c) testprop(c, (MASK(ALPHABIT) | MASK(DIGITBIT))) +#define lisdigit(c) testprop(c, MASK(DIGITBIT)) +#define lisspace(c) testprop(c, MASK(SPACEBIT)) +#define lisprint(c) testprop(c, MASK(PRINTBIT)) +#define lisxdigit(c) testprop(c, MASK(XDIGITBIT)) /* ** this 'ltolower' only works for alphabetic characters */ -#define ltolower(c) ((c) | ('A' ^ 'a')) +#define ltolower(c) ((c) | ('A' ^ 'a')) /* two more entries for 0 and -1 (EOZ) */ LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2]; -#else /* }{ */ +#else /* }{ */ /* ** use standard C ctypes @@ -80,16 +80,16 @@ LUAI_DDEC const lu_byte luai_ctype_[UCHAR_MAX + 2]; #include -#define lislalpha(c) (isalpha(c) || (c) == '_') -#define lislalnum(c) (isalnum(c) || (c) == '_') -#define lisdigit(c) (isdigit(c)) -#define lisspace(c) (isspace(c)) -#define lisprint(c) (isprint(c)) -#define lisxdigit(c) (isxdigit(c)) +#define lislalpha(c) (isalpha(c) || (c) == '_') +#define lislalnum(c) (isalnum(c) || (c) == '_') +#define lisdigit(c) (isdigit(c)) +#define lisspace(c) (isspace(c)) +#define lisprint(c) (isprint(c)) +#define lisxdigit(c) (isxdigit(c)) -#define ltolower(c) (tolower(c)) +#define ltolower(c) (tolower(c)) -#endif /* } */ +#endif /* } */ #endif diff --git a/liblua/ldblib.c b/liblua/ldblib.c index c02269457..65d2c971e 100644 --- a/liblua/ldblib.c +++ b/liblua/ldblib.c @@ -18,7 +18,7 @@ #include "lualib.h" -#define HOOKKEY "_HKEY" +#define HOOKKEY "_HKEY" @@ -253,7 +253,7 @@ static int db_upvaluejoin (lua_State *L) { } -#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY) +#define gethooktable(L) luaL_getsubtable(L, LUA_REGISTRYINDEX, HOOKKEY) static void hookf (lua_State *L, lua_Debug *ar) { diff --git a/liblua/ldebug.c b/liblua/ldebug.c index 7e04f9d09..3c3f32e90 100644 --- a/liblua/ldebug.c +++ b/liblua/ldebug.c @@ -30,7 +30,7 @@ -#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL) +#define noLuaClosure(f) ((f) == NULL || (f)->c.tt == LUA_TCCL) static const char *getfuncname (lua_State *L, CallInfo *ci, const char **name); diff --git a/liblua/ldebug.h b/liblua/ldebug.h index fe39556b0..f95965029 100644 --- a/liblua/ldebug.h +++ b/liblua/ldebug.h @@ -11,14 +11,14 @@ #include "lstate.h" -#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) +#define pcRel(pc, p) (cast(int, (pc) - (p)->code) - 1) -#define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) +#define getfuncline(f,pc) (((f)->lineinfo) ? (f)->lineinfo[pc] : 0) -#define resethookcount(L) (L->hookcount = L->basehookcount) +#define resethookcount(L) (L->hookcount = L->basehookcount) /* Active Lua function (given call info) */ -#define ci_func(ci) (clLvalue((ci)->func)) +#define ci_func(ci) (clLvalue((ci)->func)) LUAI_FUNC l_noret luaG_typeerror (lua_State *L, const TValue *o, diff --git a/liblua/ldo.c b/liblua/ldo.c index aafa3dca2..6c97ba5bf 100644 --- a/liblua/ldo.c +++ b/liblua/ldo.c @@ -50,22 +50,22 @@ #if defined(__cplusplus) && !defined(LUA_USE_LONGJMP) /* C++ exceptions */ -#define LUAI_THROW(L,c) throw(c) +#define LUAI_THROW(L,c) throw(c) #define LUAI_TRY(L,c,a) \ - try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } -#define luai_jmpbuf int /* dummy variable */ + try { a } catch(...) { if ((c)->status == 0) (c)->status = -1; } +#define luai_jmpbuf int /* dummy variable */ #elif defined(LUA_USE_ULONGJMP) /* in Unix, try _longjmp/_setjmp (more efficient) */ -#define LUAI_THROW(L,c) _longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf +#define LUAI_THROW(L,c) _longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (_setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf #else /* default handling with long jumps */ -#define LUAI_THROW(L,c) longjmp((c)->b, 1) -#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } -#define luai_jmpbuf jmp_buf +#define LUAI_THROW(L,c) longjmp((c)->b, 1) +#define LUAI_TRY(L,c,a) if (setjmp((c)->b) == 0) { a } +#define luai_jmpbuf jmp_buf #endif @@ -155,7 +155,7 @@ static void correctstack (lua_State *L, TValue *oldstack) { /* some space for error handling */ -#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) +#define ERRORSTACKSIZE (LUAI_MAXSTACK + 200) void luaD_reallocstack (lua_State *L, int newsize) { diff --git a/liblua/ldo.h b/liblua/ldo.h index 27b837d99..f1c1b48d8 100644 --- a/liblua/ldo.h +++ b/liblua/ldo.h @@ -13,14 +13,14 @@ #include "lzio.h" -#define luaD_checkstack(L,n) if (L->stack_last - L->top <= (n)) \ - luaD_growstack(L, n); else condmovestack(L); +#define luaD_checkstack(L,n) if (L->stack_last - L->top <= (n)) \ + luaD_growstack(L, n); else condmovestack(L); #define incr_top(L) {L->top++; luaD_checkstack(L,0);} -#define savestack(L,p) ((char *)(p) - (char *)L->stack) -#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) +#define savestack(L,p) ((char *)(p) - (char *)L->stack) +#define restorestack(L,n) ((TValue *)((char *)L->stack + (n))) /* type of protected functions, to be ran by `runprotected' */ diff --git a/liblua/ldump.c b/liblua/ldump.c index d5e6a47cb..aca840679 100644 --- a/liblua/ldump.c +++ b/liblua/ldump.c @@ -23,8 +23,8 @@ typedef struct { int status; } DumpState; -#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) -#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) +#define DumpMem(b,n,size,D) DumpBlock(b,(n)*(size),D) +#define DumpVar(x,D) DumpMem(&x,1,sizeof(x),D) static void DumpBlock(const void* b, size_t size, DumpState* D) { @@ -67,13 +67,13 @@ static void DumpString(const TString* s, DumpState* D) } else { - size_t size=s->tsv.len+1; /* include trailing '\0' */ + size_t size=s->tsv.len+1; /* include trailing '\0' */ DumpVar(size,D); DumpBlock(getstr(s),size*sizeof(char),D); } } -#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) +#define DumpCode(f,D) DumpVector(f->code,f->sizecode,sizeof(Instruction),D) static void DumpFunction(const Proto* f, DumpState* D); @@ -88,16 +88,16 @@ static void DumpConstants(const Proto* f, DumpState* D) switch (ttypenv(o)) { case LUA_TNIL: - break; + break; case LUA_TBOOLEAN: - DumpChar(bvalue(o),D); - break; + DumpChar(bvalue(o),D); + break; case LUA_TNUMBER: - DumpNumber(nvalue(o),D); - break; + DumpNumber(nvalue(o),D); + break; case LUA_TSTRING: - DumpString(rawtsvalue(o),D); - break; + DumpString(rawtsvalue(o),D); + break; default: lua_assert(0); } } diff --git a/liblua/lfunc.h b/liblua/lfunc.h index e236a717c..fee3205ad 100644 --- a/liblua/lfunc.h +++ b/liblua/lfunc.h @@ -11,10 +11,10 @@ #include "lobject.h" -#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ +#define sizeCclosure(n) (cast(int, sizeof(CClosure)) + \ cast(int, sizeof(TValue)*((n)-1))) -#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ +#define sizeLclosure(n) (cast(int, sizeof(LClosure)) + \ cast(int, sizeof(TValue *)*((n)-1))) diff --git a/liblua/lgc.c b/liblua/lgc.c index af001682c..7388d1b28 100644 --- a/liblua/lgc.c +++ b/liblua/lgc.c @@ -28,44 +28,44 @@ ** cost of sweeping one element (the size of a small object divided ** by some adjust for the sweep speed) */ -#define GCSWEEPCOST ((sizeof(TString) + 4) / 4) +#define GCSWEEPCOST ((sizeof(TString) + 4) / 4) /* maximum number of elements to sweep in each single step */ -#define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4)) +#define GCSWEEPMAX (cast_int((GCSTEPSIZE / GCSWEEPCOST) / 4)) /* maximum number of finalizers to call in each GC step */ -#define GCFINALIZENUM 4 +#define GCFINALIZENUM 4 /* ** macro to adjust 'stepmul': 'stepmul' is actually used like ** 'stepmul / STEPMULADJ' (value chosen by tests) */ -#define STEPMULADJ 200 +#define STEPMULADJ 200 /* ** macro to adjust 'pause': 'pause' is actually used like ** 'pause / PAUSEADJ' (value chosen by tests) */ -#define PAUSEADJ 100 +#define PAUSEADJ 100 /* ** 'makewhite' erases all color bits plus the old bit and then ** sets only the current white bit */ -#define maskcolors (~(bit2mask(BLACKBIT, OLDBIT) | WHITEBITS)) -#define makewhite(g,x) \ +#define maskcolors (~(bit2mask(BLACKBIT, OLDBIT) | WHITEBITS)) +#define makewhite(g,x) \ (gch(x)->marked = cast_byte((gch(x)->marked & maskcolors) | luaC_white(g))) -#define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) -#define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) +#define white2gray(x) resetbits(gch(x)->marked, WHITEBITS) +#define black2gray(x) resetbit(gch(x)->marked, BLACKBIT) -#define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT) +#define isfinalized(x) testbit(gch(x)->marked, FINALIZEDBIT) -#define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) +#define checkdeadkey(n) lua_assert(!ttisdeadkey(gkey(n)) || ttisnil(gval(n))) #define checkconsistency(obj) \ @@ -76,7 +76,7 @@ if (valiswhite(o)) reallymarkobject(g,gcvalue(o)); } #define markobject(g,t) { if ((t) && iswhite(obj2gco(t))) \ - reallymarkobject(g, obj2gco(t)); } + reallymarkobject(g, obj2gco(t)); } static void reallymarkobject (global_State *g, GCObject *o); @@ -91,13 +91,13 @@ static void reallymarkobject (global_State *g, GCObject *o); /* ** one after last element in a hash array */ -#define gnodelast(h) gnode(h, cast(size_t, sizenode(h))) +#define gnodelast(h) gnode(h, cast(size_t, sizenode(h))) /* ** link table 'h' into list pointed by 'p' */ -#define linktable(h,p) ((h)->gclist = *(p), *(p) = obj2gco(h)) +#define linktable(h,p) ((h)->gclist = *(p), *(p) = obj2gco(h)) /* @@ -680,7 +680,7 @@ static void freeobj (lua_State *L, GCObject *o) { } -#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) +#define sweepwholelist(L,p) sweeplist(L,p,MAX_LUMEM) static GCObject **sweeplist (lua_State *L, GCObject **p, lu_mem count); @@ -915,7 +915,7 @@ static void setpause (global_State *g, l_mem estimate) { #define sweepphases \ - (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep)) + (bitmask(GCSsweepstring) | bitmask(GCSsweepudata) | bitmask(GCSsweep)) /* diff --git a/liblua/lgc.h b/liblua/lgc.h index dee270b4d..1c92199a5 100644 --- a/liblua/lgc.h +++ b/liblua/lgc.h @@ -29,25 +29,25 @@ /* how much to allocate before next GC step */ #if !defined(GCSTEPSIZE) /* ~100 small strings */ -#define GCSTEPSIZE (cast_int(100 * sizeof(TString))) +#define GCSTEPSIZE (cast_int(100 * sizeof(TString))) #endif /* ** Possible states of the Garbage Collector */ -#define GCSpropagate 0 -#define GCSatomic 1 -#define GCSsweepstring 2 -#define GCSsweepudata 3 -#define GCSsweep 4 -#define GCSpause 5 +#define GCSpropagate 0 +#define GCSatomic 1 +#define GCSsweepstring 2 +#define GCSsweepudata 3 +#define GCSsweep 4 +#define GCSpause 5 #define issweepphase(g) \ - (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) + (GCSsweepstring <= (g)->gcstate && (g)->gcstate <= GCSsweep) -#define isgenerational(g) ((g)->gckind == KGC_GEN) +#define isgenerational(g) ((g)->gckind == KGC_GEN) /* ** macros to tell when main invariant (white objects cannot point to black @@ -58,7 +58,7 @@ ** invariant must be kept all times. */ -#define keepinvariant(g) (isgenerational(g) || g->gcstate <= GCSatomic) +#define keepinvariant(g) (isgenerational(g) || g->gcstate <= GCSatomic) /* @@ -73,66 +73,66 @@ /* ** some useful bit tricks */ -#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) -#define setbits(x,m) ((x) |= (m)) -#define testbits(x,m) ((x) & (m)) -#define bitmask(b) (1<<(b)) -#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) -#define l_setbit(x,b) setbits(x, bitmask(b)) -#define resetbit(x,b) resetbits(x, bitmask(b)) -#define testbit(x,b) testbits(x, bitmask(b)) +#define resetbits(x,m) ((x) &= cast(lu_byte, ~(m))) +#define setbits(x,m) ((x) |= (m)) +#define testbits(x,m) ((x) & (m)) +#define bitmask(b) (1<<(b)) +#define bit2mask(b1,b2) (bitmask(b1) | bitmask(b2)) +#define l_setbit(x,b) setbits(x, bitmask(b)) +#define resetbit(x,b) resetbits(x, bitmask(b)) +#define testbit(x,b) testbits(x, bitmask(b)) /* Layout for bit use in `marked' field: */ -#define WHITE0BIT 0 /* object is white (type 0) */ -#define WHITE1BIT 1 /* object is white (type 1) */ -#define BLACKBIT 2 /* object is black */ -#define FINALIZEDBIT 3 /* object has been separated for finalization */ -#define SEPARATED 4 /* object is in 'finobj' list or in 'tobefnz' */ -#define FIXEDBIT 5 /* object is fixed (should not be collected) */ -#define OLDBIT 6 /* object is old (only in generational mode) */ +#define WHITE0BIT 0 /* object is white (type 0) */ +#define WHITE1BIT 1 /* object is white (type 1) */ +#define BLACKBIT 2 /* object is black */ +#define FINALIZEDBIT 3 /* object has been separated for finalization */ +#define SEPARATED 4 /* object is in 'finobj' list or in 'tobefnz' */ +#define FIXEDBIT 5 /* object is fixed (should not be collected) */ +#define OLDBIT 6 /* object is old (only in generational mode) */ /* bit 7 is currently used by tests (luaL_checkmemory) */ -#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) +#define WHITEBITS bit2mask(WHITE0BIT, WHITE1BIT) #define iswhite(x) testbits((x)->gch.marked, WHITEBITS) #define isblack(x) testbit((x)->gch.marked, BLACKBIT) #define isgray(x) /* neither white nor black */ \ - (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) + (!testbits((x)->gch.marked, WHITEBITS | bitmask(BLACKBIT))) -#define isold(x) testbit((x)->gch.marked, OLDBIT) +#define isold(x) testbit((x)->gch.marked, OLDBIT) /* MOVE OLD rule: whenever an object is moved to the beginning of a GC list, its old bit must be cleared */ -#define resetoldbit(o) resetbit((o)->gch.marked, OLDBIT) +#define resetoldbit(o) resetbit((o)->gch.marked, OLDBIT) -#define otherwhite(g) (g->currentwhite ^ WHITEBITS) -#define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) -#define isdead(g,v) isdeadm(otherwhite(g), (v)->gch.marked) +#define otherwhite(g) (g->currentwhite ^ WHITEBITS) +#define isdeadm(ow,m) (!(((m) ^ WHITEBITS) & (ow))) +#define isdead(g,v) isdeadm(otherwhite(g), (v)->gch.marked) -#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) -#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) +#define changewhite(x) ((x)->gch.marked ^= WHITEBITS) +#define gray2black(x) l_setbit((x)->gch.marked, BLACKBIT) -#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) +#define valiswhite(x) (iscollectable(x) && iswhite(gcvalue(x))) -#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) +#define luaC_white(g) cast(lu_byte, (g)->currentwhite & WHITEBITS) #define luaC_condGC(L,c) \ - {if (G(L)->GCdebt > 0) {c;}; condchangemem(L);} -#define luaC_checkGC(L) luaC_condGC(L, luaC_step(L);) + {if (G(L)->GCdebt > 0) {c;}; condchangemem(L);} +#define luaC_checkGC(L) luaC_condGC(L, luaC_step(L);) #define luaC_barrier(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ - luaC_barrier_(L,obj2gco(p),gcvalue(v)); } + luaC_barrier_(L,obj2gco(p),gcvalue(v)); } #define luaC_barrierback(L,p,v) { if (valiswhite(v) && isblack(obj2gco(p))) \ - luaC_barrierback_(L,p); } + luaC_barrierback_(L,p); } #define luaC_objbarrier(L,p,o) \ - { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ - luaC_barrier_(L,obj2gco(p),obj2gco(o)); } + { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) \ + luaC_barrier_(L,obj2gco(p),obj2gco(o)); } #define luaC_objbarrierback(L,p,o) \ { if (iswhite(obj2gco(o)) && isblack(obj2gco(p))) luaC_barrierback_(L,p); } diff --git a/liblua/liolib.c b/liblua/liolib.c index 3f80db192..9db6f6f87 100644 --- a/liblua/liolib.c +++ b/liblua/liolib.c @@ -37,10 +37,10 @@ ** the standard ones. */ #define lua_checkmode(mode) \ - (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && \ - (*mode != '+' || ++mode) && /* skip if char is '+' */ \ - (*mode != 'b' || ++mode) && /* skip if char is 'b' */ \ - (*mode == '\0')) + (*mode != '\0' && strchr("rwa", *(mode++)) != NULL && \ + (*mode != '+' || ++mode) && /* skip if char is '+' */ \ + (*mode != 'b' || ++mode) && /* skip if char is 'b' */ \ + (*mode == '\0')) #endif @@ -51,29 +51,29 @@ ** ======================================================= */ -#if !defined(lua_popen) /* { */ +#if !defined(lua_popen) /* { */ -#if defined(LUA_USE_POPEN) /* { */ +#if defined(LUA_USE_POPEN) /* { */ -#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) -#define lua_pclose(L,file) ((void)L, pclose(file)) +#define lua_popen(L,c,m) ((void)L, fflush(NULL), popen(c,m)) +#define lua_pclose(L,file) ((void)L, pclose(file)) -#elif defined(LUA_WIN) /* }{ */ +#elif defined(LUA_WIN) /* }{ */ -#define lua_popen(L,c,m) ((void)L, _popen(c,m)) -#define lua_pclose(L,file) ((void)L, _pclose(file)) +#define lua_popen(L,c,m) ((void)L, _popen(c,m)) +#define lua_pclose(L,file) ((void)L, _pclose(file)) -#else /* }{ */ +#else /* }{ */ -#define lua_popen(L,c,m) ((void)((void)c, m), \ - luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) -#define lua_pclose(L,file) ((void)((void)L, file), -1) +#define lua_popen(L,c,m) ((void)((void)c, m), \ + luaL_error(L, LUA_QL("popen") " not supported"), (FILE*)0) +#define lua_pclose(L,file) ((void)((void)L, file), -1) -#endif /* } */ +#endif /* } */ -#endif /* } */ +#endif /* } */ /* }====================================================== */ @@ -84,46 +84,46 @@ ** ======================================================= */ -#if !defined(lua_fseek) /* { */ +#if !defined(lua_fseek) /* { */ #if defined(LUA_USE_POSIX) -#define l_fseek(f,o,w) fseeko(f,o,w) -#define l_ftell(f) ftello(f) -#define l_seeknum off_t +#define l_fseek(f,o,w) fseeko(f,o,w) +#define l_ftell(f) ftello(f) +#define l_seeknum off_t #elif defined(LUA_WIN) && !defined(_CRTIMP_TYPEINFO) \ && defined(_MSC_VER) && (_MSC_VER >= 1400) /* Windows (but not DDK) and Visual C++ 2005 or higher */ -#define l_fseek(f,o,w) _fseeki64(f,o,w) -#define l_ftell(f) _ftelli64(f) -#define l_seeknum __int64 +#define l_fseek(f,o,w) _fseeki64(f,o,w) +#define l_ftell(f) _ftelli64(f) +#define l_seeknum __int64 #else -#define l_fseek(f,o,w) fseek(f,o,w) -#define l_ftell(f) ftell(f) -#define l_seeknum long +#define l_fseek(f,o,w) fseek(f,o,w) +#define l_ftell(f) ftell(f) +#define l_seeknum long #endif -#endif /* } */ +#endif /* } */ /* }====================================================== */ -#define IO_PREFIX "_IO_" -#define IO_INPUT (IO_PREFIX "input") -#define IO_OUTPUT (IO_PREFIX "output") +#define IO_PREFIX "_IO_" +#define IO_INPUT (IO_PREFIX "input") +#define IO_OUTPUT (IO_PREFIX "output") typedef luaL_Stream LStream; -#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) +#define tolstream(L) ((LStream *)luaL_checkudata(L, 1, LUA_FILEHANDLE)) -#define isclosed(p) ((p)->closef == NULL) +#define isclosed(p) ((p)->closef == NULL) static int io_type (lua_State *L) { @@ -389,7 +389,7 @@ static int read_line (lua_State *L, FILE *f, int chop) { } -#define MAX_SIZE_T (~(size_t)0) +#define MAX_SIZE_T (~(size_t)0) static void read_all (lua_State *L, FILE *f) { size_t rlen = LUAL_BUFFERSIZE; /* how much to read in each cycle */ diff --git a/liblua/llex.c b/liblua/llex.c index 81b8de9e3..bd83444ce 100644 --- a/liblua/llex.c +++ b/liblua/llex.c @@ -29,7 +29,7 @@ -#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') +#define currIsNewline(ls) (ls->current == '\n' || ls->current == '\r') /* ORDER RESERVED */ @@ -201,11 +201,11 @@ static void buffreplace (LexState *ls, char from, char to) { #if ANDROID #define getlocaldecpoint() '.' #elif !defined(getlocaledecpoint) -#define getlocaledecpoint() (localeconv()->decimal_point[0]) +#define getlocaledecpoint() (localeconv()->decimal_point[0]) #endif -#define buff2d(b,e) luaO_str2d(luaZ_buffer(b), luaZ_bufflen(b) - 1, e) +#define buff2d(b,e) luaO_str2d(luaZ_buffer(b), luaZ_bufflen(b) - 1, e) /* ** in case of format error, try to change decimal point separator to diff --git a/liblua/llex.h b/liblua/llex.h index 9ca8a2994..f78926d66 100644 --- a/liblua/llex.h +++ b/liblua/llex.h @@ -11,7 +11,7 @@ #include "lzio.h" -#define FIRST_RESERVED 257 +#define FIRST_RESERVED 257 @@ -31,7 +31,7 @@ enum RESERVED { }; /* number of reserved words */ -#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) +#define NUM_RESERVED (cast(int, TK_WHILE-FIRST_RESERVED+1)) typedef union { diff --git a/liblua/llimits.h b/liblua/llimits.h index 1b8c79bda..f5f8ed9e1 100644 --- a/liblua/llimits.h +++ b/liblua/llimits.h @@ -27,11 +27,11 @@ typedef LUAI_MEM l_mem; typedef unsigned char lu_byte; -#define MAX_SIZET ((size_t)(~(size_t)0)-2) +#define MAX_SIZET ((size_t)(~(size_t)0)-2) -#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) +#define MAX_LUMEM ((lu_mem)(~(lu_mem)0)-2) -#define MAX_LMEM ((l_mem) ((MAX_LUMEM >> 1) - 2)) +#define MAX_LMEM ((l_mem) ((MAX_LUMEM >> 1) - 2)) #define MAX_INT (INT_MAX-2) /* maximum value of an int (-2 for safety) */ @@ -47,7 +47,7 @@ typedef unsigned char lu_byte; /* type to ensure maximum alignment */ #if !defined(LUAI_USER_ALIGNMENT_T) -#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } +#define LUAI_USER_ALIGNMENT_T union { double u; void *s; long l; } #endif typedef LUAI_USER_ALIGNMENT_T L_Umaxalign; @@ -59,13 +59,13 @@ typedef LUAI_UACNUMBER l_uacNumber; /* internal assertions for in-house debugging */ #if defined(lua_assert) -#define check_exp(c,e) (lua_assert(c), (e)) +#define check_exp(c,e) (lua_assert(c), (e)) /* to avoid problems with conditions too long */ -#define lua_longassert(c) { if (!(c)) lua_assert(0); } +#define lua_longassert(c) { if (!(c)) lua_assert(0); } #else -#define lua_assert(c) ((void)0) -#define check_exp(c,e) (e) -#define lua_longassert(c) ((void)0) +#define lua_assert(c) ((void)0) +#define check_exp(c,e) (e) +#define lua_longassert(c) ((void)0) #endif /* @@ -75,38 +75,38 @@ typedef LUAI_UACNUMBER l_uacNumber; #if defined(LUA_USE_APICHECK) #include -#define luai_apicheck(L,e) assert(e) +#define luai_apicheck(L,e) assert(e) #else -#define luai_apicheck(L,e) lua_assert(e) +#define luai_apicheck(L,e) lua_assert(e) #endif #endif -#define api_check(l,e,msg) luai_apicheck(l,(e) && msg) +#define api_check(l,e,msg) luai_apicheck(l,(e) && msg) #if !defined(UNUSED) -#define UNUSED(x) ((void)(x)) /* to avoid warnings */ +#define UNUSED(x) ((void)(x)) /* to avoid warnings */ #endif -#define cast(t, exp) ((t)(exp)) +#define cast(t, exp) ((t)(exp)) -#define cast_byte(i) cast(lu_byte, (i)) -#define cast_num(i) cast(lua_Number, (i)) -#define cast_int(i) cast(int, (i)) -#define cast_uchar(i) cast(unsigned char, (i)) +#define cast_byte(i) cast(lu_byte, (i)) +#define cast_num(i) cast(lua_Number, (i)) +#define cast_int(i) cast(int, (i)) +#define cast_uchar(i) cast(unsigned char, (i)) /* ** non-return type */ #if defined(__GNUC__) -#define l_noret void __attribute__((noreturn)) +#define l_noret void __attribute__((noreturn)) #elif defined(_MSC_VER) -#define l_noret void __declspec(noreturn) +#define l_noret void __declspec(noreturn) #else -#define l_noret void +#define l_noret void #endif @@ -116,14 +116,14 @@ typedef LUAI_UACNUMBER l_uacNumber; ** in a program. (Value must fit in an unsigned short int.) */ #if !defined(LUAI_MAXCCALLS) -#define LUAI_MAXCCALLS 200 +#define LUAI_MAXCCALLS 200 #endif /* ** maximum number of upvalues in a closure (both C and Lua). (Value ** must fit in an unsigned char.) */ -#define MAXUPVAL UCHAR_MAX +#define MAXUPVAL UCHAR_MAX /* @@ -135,19 +135,19 @@ typedef lu_int32 Instruction; /* maximum stack for a Lua function */ -#define MAXSTACK 250 +#define MAXSTACK 250 /* minimum size for the string table (must be power of 2) */ #if !defined(MINSTRTABSIZE) -#define MINSTRTABSIZE 32 +#define MINSTRTABSIZE 32 #endif /* minimum size for string buffer */ #if !defined(LUA_MINBUFFER) -#define LUA_MINBUFFER 32 +#define LUA_MINBUFFER 32 #endif @@ -167,27 +167,27 @@ typedef lu_int32 Instruction; ** created/deleted/resumed/yielded. */ #if !defined(luai_userstateopen) -#define luai_userstateopen(L) ((void)L) +#define luai_userstateopen(L) ((void)L) #endif #if !defined(luai_userstateclose) -#define luai_userstateclose(L) ((void)L) +#define luai_userstateclose(L) ((void)L) #endif #if !defined(luai_userstatethread) -#define luai_userstatethread(L,L1) ((void)L) +#define luai_userstatethread(L,L1) ((void)L) #endif #if !defined(luai_userstatefree) -#define luai_userstatefree(L,L1) ((void)L) +#define luai_userstatefree(L,L1) ((void)L) #endif #if !defined(luai_userstateresume) -#define luai_userstateresume(L,n) ((void)L) +#define luai_userstateresume(L,n) ((void)L) #endif #if !defined(luai_userstateyield) -#define luai_userstateyield(L,n) ((void)L) +#define luai_userstateyield(L,n) ((void)L) #endif /* @@ -200,29 +200,29 @@ typedef lu_int32 Instruction; ** both small and large values (outside the range of integers). */ -#if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */ +#if defined(MS_ASMTRICK) || defined(LUA_MSASMTRICK) /* { */ /* trick with Microsoft assembler for X86 */ #define lua_number2int(i,n) __asm {__asm fld n __asm fistp i} -#define lua_number2integer(i,n) lua_number2int(i, n) +#define lua_number2integer(i,n) lua_number2int(i, n) #define lua_number2unsigned(i,n) \ {__int64 l; __asm {__asm fld n __asm fistp l} i = (unsigned int)l;} -#elif defined(LUA_IEEE754TRICK) /* }{ */ +#elif defined(LUA_IEEE754TRICK) /* }{ */ /* the next trick should work on any machine using IEEE754 with a 32-bit int type */ union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; -#if !defined(LUA_IEEEENDIAN) /* { */ -#define LUAI_EXTRAIEEE \ +#if !defined(LUA_IEEEENDIAN) /* { */ +#define LUAI_EXTRAIEEE \ static const union luai_Cast ieeeendian = {-(33.0 + 6755399441055744.0)}; -#define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33) +#define LUA_IEEEENDIANLOC (ieeeendian.l_p[1] == 33) #else -#define LUA_IEEEENDIANLOC LUA_IEEEENDIAN -#define LUAI_EXTRAIEEE /* empty */ -#endif /* } */ +#define LUA_IEEEENDIANLOC LUA_IEEEENDIAN +#define LUAI_EXTRAIEEE /* empty */ +#endif /* } */ #define lua_number2int32(i,n,t) \ { LUAI_EXTRAIEEE \ @@ -233,38 +233,38 @@ union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; { volatile union luai_Cast u; u.l_d = (n) + 1.0; /* avoid -0 */ \ (i) = u.l_p[0]; (i) += u.l_p[1]; } /* add double bits for his hash */ -#define lua_number2int(i,n) lua_number2int32(i, n, int) -#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned) +#define lua_number2int(i,n) lua_number2int32(i, n, int) +#define lua_number2unsigned(i,n) lua_number2int32(i, n, lua_Unsigned) /* the trick can be expanded to lua_Integer when it is a 32-bit value */ #if defined(LUA_IEEELL) -#define lua_number2integer(i,n) lua_number2int32(i, n, lua_Integer) +#define lua_number2integer(i,n) lua_number2int32(i, n, lua_Integer) #endif -#endif /* } */ +#endif /* } */ /* the following definitions always work, but may be slow */ #if !defined(lua_number2int) -#define lua_number2int(i,n) ((i)=(int)(n)) +#define lua_number2int(i,n) ((i)=(int)(n)) #endif #if !defined(lua_number2integer) -#define lua_number2integer(i,n) ((i)=(lua_Integer)(n)) +#define lua_number2integer(i,n) ((i)=(lua_Integer)(n)) #endif -#if !defined(lua_number2unsigned) /* { */ +#if !defined(lua_number2unsigned) /* { */ /* the following definition assures proper modulo behavior */ #if defined(LUA_NUMBER_DOUBLE) || defined(LUA_NUMBER_FLOAT) #include -#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1) +#define SUPUNSIGNED ((lua_Number)(~(lua_Unsigned)0) + 1) #define lua_number2unsigned(i,n) \ - ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED)) + ((i)=(lua_Unsigned)((n) - floor((n)/SUPUNSIGNED)*SUPUNSIGNED)) #else -#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n)) +#define lua_number2unsigned(i,n) ((i)=(lua_Unsigned)(n)) #endif -#endif /* } */ +#endif /* } */ #if !defined(lua_unsigned2number) @@ -293,17 +293,17 @@ union luai_Cast { double l_d; LUA_INT32 l_p[2]; }; ** macro to control inclusion of some hard tests on stack reallocation */ #if !defined(HARDSTACKTESTS) -#define condmovestack(L) ((void)0) +#define condmovestack(L) ((void)0) #else /* realloc stack keeping its size */ -#define condmovestack(L) luaD_reallocstack((L), (L)->stacksize) +#define condmovestack(L) luaD_reallocstack((L), (L)->stacksize) #endif #if !defined(HARDMEMTESTS) -#define condchangemem(L) condmovestack(L) +#define condchangemem(L) condmovestack(L) #else #define condchangemem(L) \ - ((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1))) + ((void)(!(G(L)->gcrunning) || (luaC_fullgc(L, 0), 1))) #endif #endif diff --git a/liblua/lmathlib.c b/liblua/lmathlib.c index a49f1fd25..835a5494b 100644 --- a/liblua/lmathlib.c +++ b/liblua/lmathlib.c @@ -18,8 +18,8 @@ #undef PI -#define PI ((lua_Number)(3.1415926535897932384626433832795)) -#define RADIANS_PER_DEGREE ((lua_Number)(PI/180.0)) +#define PI ((lua_Number)(3.1415926535897932384626433832795)) +#define RADIANS_PER_DEGREE ((lua_Number)(PI/180.0)) diff --git a/liblua/lmem.c b/liblua/lmem.c index 3f88496e0..6db0b791c 100644 --- a/liblua/lmem.c +++ b/liblua/lmem.c @@ -40,7 +40,7 @@ -#define MINSIZEARRAY 4 +#define MINSIZEARRAY 4 void *luaM_growaux_ (lua_State *L, void *block, int *size, size_t size_elems, diff --git a/liblua/lmem.h b/liblua/lmem.h index 5f850999a..4a9a3c27f 100644 --- a/liblua/lmem.h +++ b/liblua/lmem.h @@ -26,16 +26,16 @@ (cast(size_t, (n)+1) > MAX_SIZET/(e)) ? (luaM_toobig(L), 0) : 0), \ luaM_realloc_(L, (b), (on)*(e), (n)*(e))) -#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) -#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) +#define luaM_freemem(L, b, s) luaM_realloc_(L, (b), (s), 0) +#define luaM_free(L, b) luaM_realloc_(L, (b), sizeof(*(b)), 0) #define luaM_freearray(L, b, n) luaM_reallocv(L, (b), n, 0, sizeof((b)[0])) -#define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s)) -#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) +#define luaM_malloc(L,s) luaM_realloc_(L, NULL, 0, (s)) +#define luaM_new(L,t) cast(t *, luaM_malloc(L, sizeof(t))) #define luaM_newvector(L,n,t) \ - cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) + cast(t *, luaM_reallocv(L, NULL, 0, n, sizeof(t))) -#define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s)) +#define luaM_newobject(L,tag,s) luaM_realloc_(L, NULL, tag, (s)) #define luaM_growvector(L,v,nelems,size,t,limit,e) \ if ((nelems)+1 > (size)) \ diff --git a/liblua/loadlib.c b/liblua/loadlib.c index a9959277b..52b48855d 100644 --- a/liblua/loadlib.c +++ b/liblua/loadlib.c @@ -35,17 +35,17 @@ ** variables that Lua check to set its paths. */ #if !defined(LUA_PATH) -#define LUA_PATH "LUA_PATH" +#define LUA_PATH "LUA_PATH" #endif #if !defined(LUA_CPATH) -#define LUA_CPATH "LUA_CPATH" +#define LUA_CPATH "LUA_CPATH" #endif -#define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR +#define LUA_PATHSUFFIX "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR -#define LUA_PATHVERSION LUA_PATH LUA_PATHSUFFIX -#define LUA_CPATHVERSION LUA_CPATH LUA_PATHSUFFIX +#define LUA_PATHVERSION LUA_PATH LUA_PATHSUFFIX +#define LUA_CPATHVERSION LUA_CPATH LUA_PATHSUFFIX /* ** LUA_PATH_SEP is the character that separates templates in a path. @@ -57,16 +57,16 @@ ** luaopen_ function name. */ #if !defined (LUA_PATH_SEP) -#define LUA_PATH_SEP ";" +#define LUA_PATH_SEP ";" #endif #if !defined (LUA_PATH_MARK) -#define LUA_PATH_MARK "?" +#define LUA_PATH_MARK "?" #endif #if !defined (LUA_EXEC_DIR) -#define LUA_EXEC_DIR "!" +#define LUA_EXEC_DIR "!" #endif #if !defined (LUA_IGMARK) -#define LUA_IGMARK "-" +#define LUA_IGMARK "-" #endif @@ -77,32 +77,32 @@ ** when searching for a Lua loader. */ #if !defined(LUA_CSUBSEP) -#define LUA_CSUBSEP LUA_DIRSEP +#define LUA_CSUBSEP LUA_DIRSEP #endif #if !defined(LUA_LSUBSEP) -#define LUA_LSUBSEP LUA_DIRSEP +#define LUA_LSUBSEP LUA_DIRSEP #endif /* prefix for open functions in C libraries */ -#define LUA_POF "luaopen_" +#define LUA_POF "luaopen_" /* separator for open functions in C libraries */ -#define LUA_OFSEP "_" +#define LUA_OFSEP "_" /* table (in the registry) that keeps handles for all loaded C libraries */ -#define CLIBS "_CLIBS" +#define CLIBS "_CLIBS" -#define LIB_FAIL "open" +#define LIB_FAIL "open" /* error codes for ll_loadfunc */ -#define ERRLIB 1 -#define ERRFUNC 2 +#define ERRLIB 1 +#define ERRFUNC 2 -#define setprogdir(L) ((void)0) +#define setprogdir(L) ((void)0) /* @@ -161,7 +161,7 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { ** optional flags for LoadLibraryEx */ #if !defined(LUA_LLE_FLAGS) -#define LUA_LLE_FLAGS 0 +#define LUA_LLE_FLAGS 0 #endif @@ -220,10 +220,10 @@ static lua_CFunction ll_sym (lua_State *L, void *lib, const char *sym) { */ #undef LIB_FAIL -#define LIB_FAIL "absent" +#define LIB_FAIL "absent" -#define DLMSG "dynamic libraries not enabled; check your Lua installation" +#define DLMSG "dynamic libraries not enabled; check your Lua installation" static void ll_unloadlib (void *lib) { @@ -619,7 +619,7 @@ static int ll_seeall (lua_State *L) { /* auxiliary mark (for internal use) */ -#define AUXMARK "\1" +#define AUXMARK "\1" /* diff --git a/liblua/lobject.c b/liblua/lobject.c index c152785a5..2e6f2b95a 100644 --- a/liblua/lobject.c +++ b/liblua/lobject.c @@ -241,13 +241,13 @@ const char *luaO_pushfstring (lua_State *L, const char *fmt, ...) { /* number of chars of a literal string without the ending \0 */ -#define LL(x) (sizeof(x)/sizeof(char) - 1) +#define LL(x) (sizeof(x)/sizeof(char) - 1) -#define RETS "..." -#define PRE "[string \"" -#define POS "\"]" +#define RETS "..." +#define PRE "[string \"" +#define POS "\"]" -#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) +#define addstr(a,b,l) ( memcpy(a,b,(l) * sizeof(char)), a += (l) ) void luaO_chunkid (char *out, const char *source, size_t bufflen) { size_t l = strlen(source); diff --git a/liblua/lobject.h b/liblua/lobject.h index dd23b9143..acf95689d 100644 --- a/liblua/lobject.h +++ b/liblua/lobject.h @@ -19,14 +19,14 @@ /* ** Extra tags for non-values */ -#define LUA_TPROTO LUA_NUMTAGS -#define LUA_TUPVAL (LUA_NUMTAGS+1) -#define LUA_TDEADKEY (LUA_NUMTAGS+2) +#define LUA_TPROTO LUA_NUMTAGS +#define LUA_TUPVAL (LUA_NUMTAGS+1) +#define LUA_TDEADKEY (LUA_NUMTAGS+2) /* ** number of all possible tags (including LUA_TNONE but excluding DEADKEY) */ -#define LUA_TOTALTAGS (LUA_TUPVAL+2) +#define LUA_TOTALTAGS (LUA_TUPVAL+2) /* @@ -36,7 +36,7 @@ ** bit 6: whether value is collectable */ -#define VARBITS (3 << 4) +#define VARBITS (3 << 4) /* @@ -47,21 +47,21 @@ */ /* Variant tags for functions */ -#define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */ -#define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */ -#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */ +#define LUA_TLCL (LUA_TFUNCTION | (0 << 4)) /* Lua closure */ +#define LUA_TLCF (LUA_TFUNCTION | (1 << 4)) /* light C function */ +#define LUA_TCCL (LUA_TFUNCTION | (2 << 4)) /* C closure */ /* Variant tags for strings */ -#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */ -#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */ +#define LUA_TSHRSTR (LUA_TSTRING | (0 << 4)) /* short strings */ +#define LUA_TLNGSTR (LUA_TSTRING | (1 << 4)) /* long strings */ /* Bit mark for collectable types */ -#define BIT_ISCOLLECTABLE (1 << 6) +#define BIT_ISCOLLECTABLE (1 << 6) /* mark a tag as collectable */ -#define ctb(t) ((t) | BIT_ISCOLLECTABLE) +#define ctb(t) ((t) | BIT_ISCOLLECTABLE) /* @@ -74,7 +74,7 @@ typedef union GCObject GCObject; ** Common Header for all collectable objects (in macro form, to be ** included in other objects) */ -#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked +#define CommonHeader GCObject *next; lu_byte tt; lu_byte marked /* @@ -92,7 +92,7 @@ typedef struct GCheader { typedef union Value Value; -#define numfield lua_Number n; /* numbers */ +#define numfield lua_Number n; /* numbers */ @@ -101,88 +101,88 @@ typedef union Value Value; ** an actual value plus a tag with its type. */ -#define TValuefields Value value_; int tt_ +#define TValuefields Value value_; int tt_ typedef struct lua_TValue TValue; /* macro defining a nil value */ -#define NILCONSTANT {NULL}, LUA_TNIL +#define NILCONSTANT {NULL}, LUA_TNIL -#define val_(o) ((o)->value_) -#define num_(o) (val_(o).n) +#define val_(o) ((o)->value_) +#define num_(o) (val_(o).n) /* raw type tag of a TValue */ -#define rttype(o) ((o)->tt_) +#define rttype(o) ((o)->tt_) /* tag with no variants (bits 0-3) */ -#define novariant(x) ((x) & 0x0F) +#define novariant(x) ((x) & 0x0F) /* type tag of a TValue (bits 0-3 for tags + variant bits 4-5) */ -#define ttype(o) (rttype(o) & 0x3F) +#define ttype(o) (rttype(o) & 0x3F) /* type tag of a TValue with no variants (bits 0-3) */ -#define ttypenv(o) (novariant(rttype(o))) +#define ttypenv(o) (novariant(rttype(o))) /* Macros to test type */ -#define checktag(o,t) (rttype(o) == (t)) -#define checktype(o,t) (ttypenv(o) == (t)) -#define ttisnumber(o) checktag((o), LUA_TNUMBER) -#define ttisnil(o) checktag((o), LUA_TNIL) -#define ttisboolean(o) checktag((o), LUA_TBOOLEAN) -#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) -#define ttisstring(o) checktype((o), LUA_TSTRING) -#define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR)) -#define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR)) -#define ttistable(o) checktag((o), ctb(LUA_TTABLE)) -#define ttisfunction(o) checktype(o, LUA_TFUNCTION) -#define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION) -#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL)) -#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL)) -#define ttislcf(o) checktag((o), LUA_TLCF) -#define ttisuserdata(o) checktag((o), ctb(LUA_TUSERDATA)) -#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) -#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) +#define checktag(o,t) (rttype(o) == (t)) +#define checktype(o,t) (ttypenv(o) == (t)) +#define ttisnumber(o) checktag((o), LUA_TNUMBER) +#define ttisnil(o) checktag((o), LUA_TNIL) +#define ttisboolean(o) checktag((o), LUA_TBOOLEAN) +#define ttislightuserdata(o) checktag((o), LUA_TLIGHTUSERDATA) +#define ttisstring(o) checktype((o), LUA_TSTRING) +#define ttisshrstring(o) checktag((o), ctb(LUA_TSHRSTR)) +#define ttislngstring(o) checktag((o), ctb(LUA_TLNGSTR)) +#define ttistable(o) checktag((o), ctb(LUA_TTABLE)) +#define ttisfunction(o) checktype(o, LUA_TFUNCTION) +#define ttisclosure(o) ((rttype(o) & 0x1F) == LUA_TFUNCTION) +#define ttisCclosure(o) checktag((o), ctb(LUA_TCCL)) +#define ttisLclosure(o) checktag((o), ctb(LUA_TLCL)) +#define ttislcf(o) checktag((o), LUA_TLCF) +#define ttisuserdata(o) checktag((o), ctb(LUA_TUSERDATA)) +#define ttisthread(o) checktag((o), ctb(LUA_TTHREAD)) +#define ttisdeadkey(o) checktag((o), LUA_TDEADKEY) -#define ttisequal(o1,o2) (rttype(o1) == rttype(o2)) +#define ttisequal(o1,o2) (rttype(o1) == rttype(o2)) /* Macros to access values */ -#define nvalue(o) check_exp(ttisnumber(o), num_(o)) -#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) -#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) -#define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts) -#define tsvalue(o) (&rawtsvalue(o)->tsv) -#define rawuvalue(o) check_exp(ttisuserdata(o), &val_(o).gc->u) -#define uvalue(o) (&rawuvalue(o)->uv) -#define clvalue(o) check_exp(ttisclosure(o), &val_(o).gc->cl) -#define clLvalue(o) check_exp(ttisLclosure(o), &val_(o).gc->cl.l) -#define clCvalue(o) check_exp(ttisCclosure(o), &val_(o).gc->cl.c) -#define fvalue(o) check_exp(ttislcf(o), val_(o).f) -#define hvalue(o) check_exp(ttistable(o), &val_(o).gc->h) -#define bvalue(o) check_exp(ttisboolean(o), val_(o).b) -#define thvalue(o) check_exp(ttisthread(o), &val_(o).gc->th) +#define nvalue(o) check_exp(ttisnumber(o), num_(o)) +#define gcvalue(o) check_exp(iscollectable(o), val_(o).gc) +#define pvalue(o) check_exp(ttislightuserdata(o), val_(o).p) +#define rawtsvalue(o) check_exp(ttisstring(o), &val_(o).gc->ts) +#define tsvalue(o) (&rawtsvalue(o)->tsv) +#define rawuvalue(o) check_exp(ttisuserdata(o), &val_(o).gc->u) +#define uvalue(o) (&rawuvalue(o)->uv) +#define clvalue(o) check_exp(ttisclosure(o), &val_(o).gc->cl) +#define clLvalue(o) check_exp(ttisLclosure(o), &val_(o).gc->cl.l) +#define clCvalue(o) check_exp(ttisCclosure(o), &val_(o).gc->cl.c) +#define fvalue(o) check_exp(ttislcf(o), val_(o).f) +#define hvalue(o) check_exp(ttistable(o), &val_(o).gc->h) +#define bvalue(o) check_exp(ttisboolean(o), val_(o).b) +#define thvalue(o) check_exp(ttisthread(o), &val_(o).gc->th) /* a dead value may get the 'gc' field, but cannot access its contents */ -#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc)) +#define deadvalue(o) check_exp(ttisdeadkey(o), cast(void *, val_(o).gc)) -#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) +#define l_isfalse(o) (ttisnil(o) || (ttisboolean(o) && bvalue(o) == 0)) -#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE) +#define iscollectable(o) (rttype(o) & BIT_ISCOLLECTABLE) /* Macros for internal tests */ -#define righttt(obj) (ttype(obj) == gcvalue(obj)->gch.tt) +#define righttt(obj) (ttype(obj) == gcvalue(obj)->gch.tt) #define checkliveness(g,obj) \ - lua_longassert(!iscollectable(obj) || \ - (righttt(obj) && !isdead(g,gcvalue(obj)))) + lua_longassert(!iscollectable(obj) || \ + (righttt(obj) && !isdead(g,gcvalue(obj)))) /* Macros to set values */ -#define settt_(o,t) ((o)->tt_=(t)) +#define settt_(o,t) ((o)->tt_=(t)) #define setnvalue(obj,x) \ { TValue *io=(obj); num_(io)=(x); settt_(io, LUA_TNUMBER); } @@ -233,14 +233,14 @@ typedef struct lua_TValue TValue; val_(io).gc=cast(GCObject *, (x)); settt_(io, ctb(LUA_TTABLE)); \ checkliveness(G(L),io); } -#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY) +#define setdeadvalue(obj) settt_(obj, LUA_TDEADKEY) #define setobj(L,obj1,obj2) \ - { const TValue *io2=(obj2); TValue *io1=(obj1); \ - io1->value_ = io2->value_; io1->tt_ = io2->tt_; \ - checkliveness(G(L),io1); } + { const TValue *io2=(obj2); TValue *io1=(obj1); \ + io1->value_ = io2->value_; io1->tt_ = io2->tt_; \ + checkliveness(G(L),io1); } /* @@ -248,23 +248,23 @@ typedef struct lua_TValue TValue; */ /* from stack to (same) stack */ -#define setobjs2s setobj +#define setobjs2s setobj /* to stack (not from same stack) */ -#define setobj2s setobj -#define setsvalue2s setsvalue -#define sethvalue2s sethvalue -#define setptvalue2s setptvalue +#define setobj2s setobj +#define setsvalue2s setsvalue +#define sethvalue2s sethvalue +#define setptvalue2s setptvalue /* from table to same table */ -#define setobjt2t setobj +#define setobjt2t setobj /* to table */ -#define setobj2t setobj +#define setobj2t setobj /* to new object */ -#define setobj2n setobj -#define setsvalue2n setsvalue +#define setobj2n setobj +#define setsvalue2n setsvalue /* check whether a number is valid (useful only for NaN trick) */ -#define luai_checknum(L,o,c) { /* empty */ } +#define luai_checknum(L,o,c) { /* empty */ } /* @@ -282,7 +282,7 @@ typedef struct lua_TValue TValue; */ /* allows for external implementation for part of the trick */ -#if !defined(NNMARK) /* { */ +#if !defined(NNMARK) /* { */ #if !defined(LUA_IEEEENDIAN) @@ -290,70 +290,70 @@ typedef struct lua_TValue TValue; #endif -#define NNMARK 0x7FF7A500 -#define NNMASK 0x7FFFFF00 +#define NNMARK 0x7FF7A500 +#define NNMASK 0x7FFFFF00 #undef TValuefields #undef NILCONSTANT -#if (LUA_IEEEENDIAN == 0) /* { */ +#if (LUA_IEEEENDIAN == 0) /* { */ /* little endian */ #define TValuefields \ - union { struct { Value v__; int tt__; } i; double d__; } u -#define NILCONSTANT {{{NULL}, tag2tt(LUA_TNIL)}} + union { struct { Value v__; int tt__; } i; double d__; } u +#define NILCONSTANT {{{NULL}, tag2tt(LUA_TNIL)}} /* field-access macros */ -#define v_(o) ((o)->u.i.v__) -#define d_(o) ((o)->u.d__) -#define tt_(o) ((o)->u.i.tt__) +#define v_(o) ((o)->u.i.v__) +#define d_(o) ((o)->u.d__) +#define tt_(o) ((o)->u.i.tt__) -#else /* }{ */ +#else /* }{ */ /* big endian */ #define TValuefields \ - union { struct { int tt__; Value v__; } i; double d__; } u -#define NILCONSTANT {{tag2tt(LUA_TNIL), {NULL}}} + union { struct { int tt__; Value v__; } i; double d__; } u +#define NILCONSTANT {{tag2tt(LUA_TNIL), {NULL}}} /* field-access macros */ -#define v_(o) ((o)->u.i.v__) -#define d_(o) ((o)->u.d__) -#define tt_(o) ((o)->u.i.tt__) +#define v_(o) ((o)->u.i.v__) +#define d_(o) ((o)->u.d__) +#define tt_(o) ((o)->u.i.tt__) -#endif /* } */ +#endif /* } */ -#endif /* } */ +#endif /* } */ /* correspondence with standard representation */ #undef val_ -#define val_(o) v_(o) +#define val_(o) v_(o) #undef num_ -#define num_(o) d_(o) +#define num_(o) d_(o) #undef numfield -#define numfield /* no such field; numbers are the entire struct */ +#define numfield /* no such field; numbers are the entire struct */ /* basic check to distinguish numbers from non-numbers */ #undef ttisnumber -#define ttisnumber(o) ((tt_(o) & NNMASK) != NNMARK) +#define ttisnumber(o) ((tt_(o) & NNMASK) != NNMARK) -#define tag2tt(t) (NNMARK | (t)) +#define tag2tt(t) (NNMARK | (t)) #undef rttype -#define rttype(o) (ttisnumber(o) ? LUA_TNUMBER : tt_(o) & 0xff) +#define rttype(o) (ttisnumber(o) ? LUA_TNUMBER : tt_(o) & 0xff) #undef settt_ -#define settt_(o,t) (tt_(o) = tag2tt(t)) +#define settt_(o,t) (tt_(o) = tag2tt(t)) #undef setnvalue #define setnvalue(obj,x) \ - { TValue *io_=(obj); num_(io_)=(x); lua_assert(ttisnumber(io_)); } + { TValue *io_=(obj); num_(io_)=(x); lua_assert(ttisnumber(io_)); } #undef setobj #define setobj(L,obj1,obj2) \ - { const TValue *o2_=(obj2); TValue *o1_=(obj1); \ - o1_->u = o2_->u; \ - checkliveness(G(L),o1_); } + { const TValue *o2_=(obj2); TValue *o1_=(obj1); \ + o1_->u = o2_->u; \ + checkliveness(G(L),o1_); } /* @@ -362,16 +362,16 @@ typedef struct lua_TValue TValue; #undef checktag #undef checktype -#define checktag(o,t) (tt_(o) == tag2tt(t)) -#define checktype(o,t) (ctb(tt_(o) | VARBITS) == ctb(tag2tt(t) | VARBITS)) +#define checktag(o,t) (tt_(o) == tag2tt(t)) +#define checktype(o,t) (ctb(tt_(o) | VARBITS) == ctb(tag2tt(t) | VARBITS)) #undef ttisequal #define ttisequal(o1,o2) \ - (ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2))) + (ttisnumber(o1) ? ttisnumber(o2) : (tt_(o1) == tt_(o2))) #undef luai_checknum -#define luai_checknum(L,o,c) { if (!ttisnumber(o)) c; } +#define luai_checknum(L,o,c) { if (!ttisnumber(o)) c; } #endif /* }====================================================== */ @@ -419,7 +419,7 @@ typedef union TString { /* get the actual string (array of bytes) from a TString */ -#define getstr(ts) cast(const char *, (ts) + 1) +#define getstr(ts) cast(const char *, (ts) + 1) /* get the actual string (array of bytes) from a Lua value */ #define svalue(o) getstr(rawtsvalue(o)) @@ -511,7 +511,7 @@ typedef struct UpVal { */ #define ClosureHeader \ - CommonHeader; lu_byte nupvalues; GCObject *gclist + CommonHeader; lu_byte nupvalues; GCObject *gclist typedef struct CClosure { ClosureHeader; @@ -533,9 +533,9 @@ typedef union Closure { } Closure; -#define isLfunction(o) ttisLclosure(o) +#define isLfunction(o) ttisLclosure(o) -#define getproto(o) (clLvalue(o)->p) +#define getproto(o) (clLvalue(o)->p) /* @@ -575,17 +575,17 @@ typedef struct Table { ** `module' operation for hashing (size is always a power of 2) */ #define lmod(s,size) \ - (check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1))))) + (check_exp((size&(size-1))==0, (cast(int, (s) & ((size)-1))))) -#define twoto(x) (1<<(x)) -#define sizenode(t) (twoto((t)->lsizenode)) +#define twoto(x) (1<<(x)) +#define sizenode(t) (twoto((t)->lsizenode)) /* ** (address of) a fixed nil value */ -#define luaO_nilobject (&luaO_nilobject_) +#define luaO_nilobject (&luaO_nilobject_) LUAI_DDEC const TValue luaO_nilobject_; diff --git a/liblua/lopcodes.c b/liblua/lopcodes.c index ef7369275..5dcb89eaa 100644 --- a/liblua/lopcodes.c +++ b/liblua/lopcodes.c @@ -62,46 +62,46 @@ LUAI_DDEF const char *const luaP_opnames[NUM_OPCODES+1] = { #define opmode(t,a,b,c,m) (((t)<<7) | ((a)<<6) | ((b)<<4) | ((c)<<2) | (m)) LUAI_DDEF const lu_byte luaP_opmodes[NUM_OPCODES] = { -/* T A B C mode opcode */ - opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ - ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ - ,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ - ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ - ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ - ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ - ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ - ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ - ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ - ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ - ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ - ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ - ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ - ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TEST */ - ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ - ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ - ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ - ,opmode(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */ - ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */ - ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ - ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ - ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ - ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */ +/* T A B C mode opcode */ + opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_MOVE */ + ,opmode(0, 1, OpArgK, OpArgN, iABx) /* OP_LOADK */ + ,opmode(0, 1, OpArgN, OpArgN, iABx) /* OP_LOADKX */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_LOADBOOL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_LOADNIL */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_GETUPVAL */ + ,opmode(0, 1, OpArgU, OpArgK, iABC) /* OP_GETTABUP */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_GETTABLE */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABUP */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_SETUPVAL */ + ,opmode(0, 0, OpArgK, OpArgK, iABC) /* OP_SETTABLE */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_NEWTABLE */ + ,opmode(0, 1, OpArgR, OpArgK, iABC) /* OP_SELF */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_ADD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_SUB */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MUL */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_DIV */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_MOD */ + ,opmode(0, 1, OpArgK, OpArgK, iABC) /* OP_POW */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_UNM */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_NOT */ + ,opmode(0, 1, OpArgR, OpArgN, iABC) /* OP_LEN */ + ,opmode(0, 1, OpArgR, OpArgR, iABC) /* OP_CONCAT */ + ,opmode(0, 0, OpArgR, OpArgN, iAsBx) /* OP_JMP */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_EQ */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LT */ + ,opmode(1, 0, OpArgK, OpArgK, iABC) /* OP_LE */ + ,opmode(1, 0, OpArgN, OpArgU, iABC) /* OP_TEST */ + ,opmode(1, 1, OpArgR, OpArgU, iABC) /* OP_TESTSET */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_CALL */ + ,opmode(0, 1, OpArgU, OpArgU, iABC) /* OP_TAILCALL */ + ,opmode(0, 0, OpArgU, OpArgN, iABC) /* OP_RETURN */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORLOOP */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_FORPREP */ + ,opmode(0, 0, OpArgN, OpArgU, iABC) /* OP_TFORCALL */ + ,opmode(0, 1, OpArgR, OpArgN, iAsBx) /* OP_TFORLOOP */ + ,opmode(0, 0, OpArgU, OpArgU, iABC) /* OP_SETLIST */ + ,opmode(0, 1, OpArgU, OpArgN, iABx) /* OP_CLOSURE */ + ,opmode(0, 1, OpArgU, OpArgN, iABC) /* OP_VARARG */ + ,opmode(0, 0, OpArgU, OpArgU, iAx) /* OP_EXTRAARG */ }; diff --git a/liblua/lopcodes.h b/liblua/lopcodes.h index 07d2b3f39..3c8948440 100644 --- a/liblua/lopcodes.h +++ b/liblua/lopcodes.h @@ -14,12 +14,12 @@ We assume that instructions are unsigned numbers. All instructions have an opcode in the first 6 bits. Instructions can have the following fields: - `A' : 8 bits - `B' : 9 bits - `C' : 9 bits - 'Ax' : 26 bits ('A', 'B', and 'C' together) - `Bx' : 18 bits (`B' and `C' together) - `sBx' : signed Bx + `A' : 8 bits + `B' : 9 bits + `C' : 9 bits + 'Ax' : 26 bits ('A', 'B', and 'C' together) + `Bx' : 18 bits (`B' and `C' together) + `sBx' : signed Bx A signed argument is represented in excess K; that is, the number value is the unsigned value minus K. K is exactly the maximum value @@ -35,20 +35,20 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ /* ** size and position of opcode arguments. */ -#define SIZE_C 9 -#define SIZE_B 9 -#define SIZE_Bx (SIZE_C + SIZE_B) -#define SIZE_A 8 -#define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A) +#define SIZE_C 9 +#define SIZE_B 9 +#define SIZE_Bx (SIZE_C + SIZE_B) +#define SIZE_A 8 +#define SIZE_Ax (SIZE_C + SIZE_B + SIZE_A) -#define SIZE_OP 6 +#define SIZE_OP 6 -#define POS_OP 0 -#define POS_A (POS_OP + SIZE_OP) -#define POS_C (POS_A + SIZE_A) -#define POS_B (POS_C + SIZE_C) -#define POS_Bx POS_C -#define POS_Ax POS_A +#define POS_OP 0 +#define POS_A (POS_OP + SIZE_OP) +#define POS_C (POS_A + SIZE_A) +#define POS_B (POS_C + SIZE_C) +#define POS_Bx POS_C +#define POS_Ax POS_A /* @@ -57,17 +57,17 @@ enum OpMode {iABC, iABx, iAsBx, iAx}; /* basic instruction format */ ** so they must fit in LUAI_BITSINT-1 bits (-1 for sign) */ #if SIZE_Bx < LUAI_BITSINT-1 -#define MAXARG_Bx ((1<>1) /* `sBx' is signed */ +#define MAXARG_Bx ((1<>1) /* `sBx' is signed */ #else -#define MAXARG_Bx MAX_INT -#define MAXARG_sBx MAX_INT +#define MAXARG_Bx MAX_INT +#define MAXARG_sBx MAX_INT #endif #if SIZE_Ax < LUAI_BITSINT-1 -#define MAXARG_Ax ((1<>POS_OP) & MASK1(SIZE_OP,0))) -#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ - ((cast(Instruction, o)<>POS_OP) & MASK1(SIZE_OP,0))) +#define SET_OPCODE(i,o) ((i) = (((i)&MASK0(SIZE_OP,POS_OP)) | \ + ((cast(Instruction, o)<>pos) & MASK1(size,0))) -#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ +#define getarg(i,pos,size) (cast(int, ((i)>>pos) & MASK1(size,0))) +#define setarg(i,v,pos,size) ((i) = (((i)&MASK0(size,pos)) | \ ((cast(Instruction, v)<= R(A) + 1 */ -OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ -OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ -OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ +OP_JMP,/* A sBx pc+=sBx; if (A) close all upvalues >= R(A) + 1 */ +OP_EQ,/* A B C if ((RK(B) == RK(C)) ~= A) then pc++ */ +OP_LT,/* A B C if ((RK(B) < RK(C)) ~= A) then pc++ */ +OP_LE,/* A B C if ((RK(B) <= RK(C)) ~= A) then pc++ */ -OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ -OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ +OP_TEST,/* A C if not (R(A) <=> C) then pc++ */ +OP_TESTSET,/* A B C if (R(B) <=> C) then R(A) := R(B) else pc++ */ -OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ -OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ -OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ +OP_CALL,/* A B C R(A), ... ,R(A+C-2) := R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_TAILCALL,/* A B C return R(A)(R(A+1), ... ,R(A+B-1)) */ +OP_RETURN,/* A B return R(A), ... ,R(A+B-2) (see note) */ -OP_FORLOOP,/* A sBx R(A)+=R(A+2); - if R(A) > 4) & 3)) -#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) -#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) -#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) +#define getOpMode(m) (cast(enum OpMode, luaP_opmodes[m] & 3)) +#define getBMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 4) & 3)) +#define getCMode(m) (cast(enum OpArgMask, (luaP_opmodes[m] >> 2) & 3)) +#define testAMode(m) (luaP_opmodes[m] & (1 << 6)) +#define testTMode(m) (luaP_opmodes[m] & (1 << 7)) LUAI_DDEC const char *const luaP_opnames[NUM_OPCODES+1]; /* opcode names */ /* number of list items to accumulate before a SETLIST instruction */ -#define LFIELDS_PER_FLUSH 50 +#define LFIELDS_PER_FLUSH 50 #endif diff --git a/liblua/loslib.c b/liblua/loslib.c index 5170fd0d0..2b7a8b5f6 100644 --- a/liblua/loslib.c +++ b/liblua/loslib.c @@ -26,12 +26,12 @@ #if !defined(LUA_STRFTIMEOPTIONS) #if !defined(LUA_USE_POSIX) -#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" } +#define LUA_STRFTIMEOPTIONS { "aAbBcdHIjmMpSUwWxXyYz%", "" } #else #define LUA_STRFTIMEOPTIONS \ - { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \ - "", "E", "cCxXyY", \ - "O", "deHImMSuUVwWy" } + { "aAbBcCdDeFgGhHIjmMnprRStTuUVwWxXyYzZ%", "" \ + "", "E", "cCxXyY", \ + "O", "deHImMSuUVwWy" } #endif #endif @@ -44,7 +44,7 @@ */ #if defined(LUA_USE_MKSTEMP) #include -#define LUA_TMPNAMBUFSIZE 32 +#define LUA_TMPNAMBUFSIZE 32 #define lua_tmpnam(b,e) { \ strcpy(b, "/tmp/lua_XXXXXX"); \ e = mkstemp(b); \ @@ -53,8 +53,8 @@ #elif !defined(lua_tmpnam) -#define LUA_TMPNAMBUFSIZE L_tmpnam -#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } +#define LUA_TMPNAMBUFSIZE L_tmpnam +#define lua_tmpnam(b,e) { e = (tmpnam(b) == NULL); } #endif @@ -65,13 +65,13 @@ */ #if defined(LUA_USE_GMTIME_R) -#define l_gmtime(t,r) gmtime_r(t,r) -#define l_localtime(t,r) localtime_r(t,r) +#define l_gmtime(t,r) gmtime_r(t,r) +#define l_localtime(t,r) localtime_r(t,r) #elif !defined(l_gmtime) -#define l_gmtime(t,r) ((void)r, gmtime(t)) -#define l_localtime(t,r) ((void)r, localtime(t)) +#define l_gmtime(t,r) ((void)r, gmtime(t)) +#define l_localtime(t,r) ((void)r, localtime(t)) #endif diff --git a/liblua/lparser.c b/liblua/lparser.c index d8f5b4ffc..453452298 100644 --- a/liblua/lparser.c +++ b/liblua/lparser.c @@ -29,10 +29,10 @@ /* maximum number of local variables per function (must be smaller than 250, due to the bytecode format) */ -#define MAXVARS 200 +#define MAXVARS 200 -#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) +#define hasmultret(k) ((k) == VCALL || (k) == VVARARG) @@ -119,7 +119,7 @@ static void checknext (LexState *ls, int c) { } -#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } +#define check_condition(ls,c,msg) { if (!(c)) luaX_syntaxerror(ls, msg); } @@ -192,7 +192,7 @@ static void new_localvarliteral_ (LexState *ls, const char *name, size_t sz) { } #define new_localvarliteral(ls,v) \ - new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) + new_localvarliteral_(ls, "" v, (sizeof(v)/sizeof(char))-1) static LocVar *getlocvar (FuncState *fs, int i) { @@ -334,7 +334,7 @@ static void enterlevel (LexState *ls) { } -#define leavelevel(ls) ((ls)->L->nCcalls--) +#define leavelevel(ls) ((ls)->L->nCcalls--) static void closegoto (LexState *ls, int g, Labeldesc *label) { @@ -1027,7 +1027,7 @@ static const struct { {2, 2}, {1, 1} /* and, or */ }; -#define UNARY_PRIORITY 8 /* priority for unary operators */ +#define UNARY_PRIORITY 8 /* priority for unary operators */ /* diff --git a/liblua/lparser.h b/liblua/lparser.h index 301167d4f..4dbb6e21f 100644 --- a/liblua/lparser.h +++ b/liblua/lparser.h @@ -17,25 +17,25 @@ */ typedef enum { - VVOID, /* no value */ + VVOID, /* no value */ VNIL, VTRUE, VFALSE, - VK, /* info = index of constant in `k' */ - VKNUM, /* nval = numerical value */ - VNONRELOC, /* info = result register */ - VLOCAL, /* info = local register */ + VK, /* info = index of constant in `k' */ + VKNUM, /* nval = numerical value */ + VNONRELOC, /* info = result register */ + VLOCAL, /* info = local register */ VUPVAL, /* info = index of upvalue in 'upvalues' */ - VINDEXED, /* t = table register/upvalue; idx = index R/K */ - VJMP, /* info = instruction pc */ - VRELOCABLE, /* info = instruction pc */ - VCALL, /* info = instruction pc */ - VVARARG /* info = instruction pc */ + VINDEXED, /* t = table register/upvalue; idx = index R/K */ + VJMP, /* info = instruction pc */ + VRELOCABLE, /* info = instruction pc */ + VCALL, /* info = instruction pc */ + VVARARG /* info = instruction pc */ } expkind; -#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) -#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) +#define vkisvar(k) (VLOCAL <= (k) && (k) <= VINDEXED) +#define vkisinreg(k) ((k) == VNONRELOC || (k) == VLOCAL) typedef struct expdesc { expkind k; diff --git a/liblua/lstate.c b/liblua/lstate.c index 207a106d5..486442ac7 100644 --- a/liblua/lstate.c +++ b/liblua/lstate.c @@ -27,19 +27,19 @@ #if !defined(LUAI_GCPAUSE) -#define LUAI_GCPAUSE 200 /* 200% */ +#define LUAI_GCPAUSE 200 /* 200% */ #endif #if !defined(LUAI_GCMAJOR) -#define LUAI_GCMAJOR 200 /* 200% */ +#define LUAI_GCMAJOR 200 /* 200% */ #endif #if !defined(LUAI_GCMUL) -#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ +#define LUAI_GCMUL 200 /* GC runs 'twice the speed' of memory allocation */ #endif -#define MEMERRMSG "not enough memory" +#define MEMERRMSG "not enough memory" /* @@ -48,7 +48,7 @@ */ #if !defined(luai_makeseed) #include -#define luai_makeseed() cast(unsigned int, time(NULL)) +#define luai_makeseed() cast(unsigned int, time(NULL)) #endif @@ -74,7 +74,7 @@ typedef struct LG { -#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) +#define fromstate(L) (cast(LX *, cast(lu_byte *, (L)) - offsetof(LX, l))) /* diff --git a/liblua/lstate.h b/liblua/lstate.h index c8a31f5c0..f862da81f 100644 --- a/liblua/lstate.h +++ b/liblua/lstate.h @@ -51,9 +51,9 @@ struct lua_longjmp; /* defined in ldo.c */ /* kinds of Garbage Collection */ -#define KGC_NORMAL 0 -#define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ -#define KGC_GEN 2 /* generational collection */ +#define KGC_NORMAL 0 +#define KGC_EMERGENCY 1 /* gc was forced by an allocation failure */ +#define KGC_GEN 2 /* generational collection */ typedef struct stringtable { @@ -68,7 +68,7 @@ typedef struct stringtable { */ typedef struct CallInfo { StkId func; /* function index in the stack */ - StkId top; /* top for this function */ + StkId top; /* top for this function */ struct CallInfo *previous, *next; /* dynamic call link */ short nresults; /* expected number of results from this function */ lu_byte callstatus; @@ -92,18 +92,18 @@ typedef struct CallInfo { /* ** Bits in CallInfo status */ -#define CIST_LUA (1<<0) /* call is running a Lua function */ -#define CIST_HOOKED (1<<1) /* call is running a debug hook */ -#define CIST_REENTRY (1<<2) /* call is running on same invocation of +#define CIST_LUA (1<<0) /* call is running a Lua function */ +#define CIST_HOOKED (1<<1) /* call is running a debug hook */ +#define CIST_REENTRY (1<<2) /* call is running on same invocation of luaV_execute of previous call */ -#define CIST_YIELDED (1<<3) /* call reentered after suspension */ -#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ -#define CIST_STAT (1<<5) /* call has an error status (pcall) */ -#define CIST_TAIL (1<<6) /* call was tail called */ -#define CIST_HOOKYIELD (1<<7) /* last hook called yielded */ +#define CIST_YIELDED (1<<3) /* call reentered after suspension */ +#define CIST_YPCALL (1<<4) /* call is a yieldable protected call */ +#define CIST_STAT (1<<5) /* call has an error status (pcall) */ +#define CIST_TAIL (1<<6) /* call was tail called */ +#define CIST_HOOKYIELD (1<<7) /* last hook called yielded */ -#define isLua(ci) ((ci)->callstatus & CIST_LUA) +#define isLua(ci) ((ci)->callstatus & CIST_LUA) /* @@ -176,7 +176,7 @@ struct lua_State { }; -#define G(L) (L->l_G) +#define G(L) (L->l_G) /* @@ -194,29 +194,29 @@ union GCObject { }; -#define gch(o) (&(o)->gch) +#define gch(o) (&(o)->gch) /* macros to convert a GCObject into a specific value */ #define rawgco2ts(o) \ - check_exp(novariant((o)->gch.tt) == LUA_TSTRING, &((o)->ts)) -#define gco2ts(o) (&rawgco2ts(o)->tsv) -#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) -#define gco2u(o) (&rawgco2u(o)->uv) -#define gco2lcl(o) check_exp((o)->gch.tt == LUA_TLCL, &((o)->cl.l)) -#define gco2ccl(o) check_exp((o)->gch.tt == LUA_TCCL, &((o)->cl.c)) + check_exp(novariant((o)->gch.tt) == LUA_TSTRING, &((o)->ts)) +#define gco2ts(o) (&rawgco2ts(o)->tsv) +#define rawgco2u(o) check_exp((o)->gch.tt == LUA_TUSERDATA, &((o)->u)) +#define gco2u(o) (&rawgco2u(o)->uv) +#define gco2lcl(o) check_exp((o)->gch.tt == LUA_TLCL, &((o)->cl.l)) +#define gco2ccl(o) check_exp((o)->gch.tt == LUA_TCCL, &((o)->cl.c)) #define gco2cl(o) \ - check_exp(novariant((o)->gch.tt) == LUA_TFUNCTION, &((o)->cl)) -#define gco2t(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) -#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) -#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) -#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) + check_exp(novariant((o)->gch.tt) == LUA_TFUNCTION, &((o)->cl)) +#define gco2t(o) check_exp((o)->gch.tt == LUA_TTABLE, &((o)->h)) +#define gco2p(o) check_exp((o)->gch.tt == LUA_TPROTO, &((o)->p)) +#define gco2uv(o) check_exp((o)->gch.tt == LUA_TUPVAL, &((o)->uv)) +#define gco2th(o) check_exp((o)->gch.tt == LUA_TTHREAD, &((o)->th)) /* macro to convert any Lua object into a GCObject */ -#define obj2gco(v) (cast(GCObject *, (v))) +#define obj2gco(v) (cast(GCObject *, (v))) /* actual number of total bytes allocated */ -#define gettotalbytes(g) ((g)->totalbytes + (g)->GCdebt) +#define gettotalbytes(g) ((g)->totalbytes + (g)->GCdebt) LUAI_FUNC void luaE_setdebt (global_State *g, l_mem debt); LUAI_FUNC void luaE_freethread (lua_State *L, lua_State *L1); diff --git a/liblua/lstring.c b/liblua/lstring.c index 8b5af0b2e..049d09b67 100644 --- a/liblua/lstring.c +++ b/liblua/lstring.c @@ -23,7 +23,7 @@ ** compute its hash */ #if !defined(LUAI_HASHLIMIT) -#define LUAI_HASHLIMIT 5 +#define LUAI_HASHLIMIT 5 #endif diff --git a/liblua/lstring.h b/liblua/lstring.h index d312ff3d2..b7891d6b1 100644 --- a/liblua/lstring.h +++ b/liblua/lstring.h @@ -12,26 +12,26 @@ #include "lstate.h" -#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) +#define sizestring(s) (sizeof(union TString)+((s)->len+1)*sizeof(char)) -#define sizeudata(u) (sizeof(union Udata)+(u)->len) +#define sizeudata(u) (sizeof(union Udata)+(u)->len) -#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ +#define luaS_newliteral(L, s) (luaS_newlstr(L, "" s, \ (sizeof(s)/sizeof(char))-1)) -#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) +#define luaS_fix(s) l_setbit((s)->tsv.marked, FIXEDBIT) /* ** test whether a string is a reserved word */ -#define isreserved(s) ((s)->tsv.tt == LUA_TSHRSTR && (s)->tsv.extra > 0) +#define isreserved(s) ((s)->tsv.tt == LUA_TSHRSTR && (s)->tsv.extra > 0) /* ** equality for short strings, which are always internalized */ -#define eqshrstr(a,b) check_exp((a)->tsv.tt == LUA_TSHRSTR, (a) == (b)) +#define eqshrstr(a,b) check_exp((a)->tsv.tt == LUA_TSHRSTR, (a) == (b)) LUAI_FUNC unsigned int luaS_hash (const char *str, size_t l, unsigned int seed); diff --git a/liblua/lstrlib.c b/liblua/lstrlib.c index fcc61c9a6..685beb77f 100644 --- a/liblua/lstrlib.c +++ b/liblua/lstrlib.c @@ -25,12 +25,12 @@ ** pattern-matching. This limit is arbitrary. */ #if !defined(LUA_MAXCAPTURES) -#define LUA_MAXCAPTURES 32 +#define LUA_MAXCAPTURES 32 #endif /* macro to `unsign' a character */ -#define uchar(c) ((unsigned char)(c)) +#define uchar(c) ((unsigned char)(c)) @@ -103,7 +103,7 @@ static int str_upper (lua_State *L) { /* reasonable limit to avoid arithmetic overflow */ -#define MAXSIZE ((~(size_t)0) >> 1) +#define MAXSIZE ((~(size_t)0) >> 1) static int str_rep (lua_State *L) { size_t l, lsep; @@ -191,8 +191,8 @@ static int str_dump (lua_State *L) { */ -#define CAP_UNFINISHED (-1) -#define CAP_POSITION (-2) +#define CAP_UNFINISHED (-1) +#define CAP_POSITION (-2) typedef struct MatchState { @@ -215,12 +215,12 @@ static const char *match (MatchState *ms, const char *s, const char *p); /* maximum recursion depth for 'match' */ #if !defined(MAXCCALLS) -#define MAXCCALLS 200 +#define MAXCCALLS 200 #endif -#define L_ESC '%' -#define SPECIALS "^$*+?.([%-" +#define L_ESC '%' +#define SPECIALS "^$*+?.([%-" static int check_capture (MatchState *ms, int l) { @@ -791,19 +791,19 @@ static int str_gsub (lua_State *L) { ** 'string.format'; LUA_INTFRM_T is the integer type corresponding to ** the previous length */ -#if !defined(LUA_INTFRMLEN) /* { */ +#if !defined(LUA_INTFRMLEN) /* { */ #if defined(LUA_USE_LONGLONG) -#define LUA_INTFRMLEN "ll" -#define LUA_INTFRM_T long long +#define LUA_INTFRMLEN "ll" +#define LUA_INTFRM_T long long #else -#define LUA_INTFRMLEN "l" -#define LUA_INTFRM_T long +#define LUA_INTFRMLEN "l" +#define LUA_INTFRM_T long #endif -#endif /* } */ +#endif /* } */ /* @@ -813,21 +813,21 @@ static int str_gsub (lua_State *L) { */ #if !defined(LUA_FLTFRMLEN) -#define LUA_FLTFRMLEN "" -#define LUA_FLTFRM_T double +#define LUA_FLTFRMLEN "" +#define LUA_FLTFRM_T double #endif /* maximum size of each formatted item (> len(format('%99.99f', -1e308))) */ -#define MAX_ITEM 512 +#define MAX_ITEM 512 /* valid flags in a format specification */ -#define FLAGS "-+ #0" +#define FLAGS "-+ #0" /* ** maximum size of each format specification (such as '%-099.99d') ** (+10 accounts for %99.99x plus margin of error) */ -#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) +#define MAX_FORMAT (sizeof(FLAGS) + sizeof(LUA_INTFRMLEN) + 10) static void addquoted (lua_State *L, luaL_Buffer *b, int arg) { diff --git a/liblua/ltable.c b/liblua/ltable.c index 420391fc7..713ff34c7 100644 --- a/liblua/ltable.c +++ b/liblua/ltable.c @@ -40,33 +40,33 @@ ** max size of array part is 2^MAXBITS */ #if LUAI_BITSINT >= 32 -#define MAXBITS 30 +#define MAXBITS 30 #else -#define MAXBITS (LUAI_BITSINT-2) +#define MAXBITS (LUAI_BITSINT-2) #endif -#define MAXASIZE (1 << MAXBITS) +#define MAXASIZE (1 << MAXBITS) -#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) +#define hashpow2(t,n) (gnode(t, lmod((n), sizenode(t)))) -#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) -#define hashboolean(t,p) hashpow2(t, p) +#define hashstr(t,str) hashpow2(t, (str)->tsv.hash) +#define hashboolean(t,p) hashpow2(t, p) /* ** for some types, it is better to avoid modulus by power of 2, as ** they tend to have many 2 factors. */ -#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) +#define hashmod(t,n) (gnode(t, ((n) % ((sizenode(t)-1)|1)))) -#define hashpointer(t,p) hashmod(t, IntPoint(p)) +#define hashpointer(t,p) hashmod(t, IntPoint(p)) -#define dummynode (&dummynode_) +#define dummynode (&dummynode_) -#define isdummy(n) ((n) == dummynode) +#define isdummy(n) ((n) == dummynode) static const Node dummynode_ = { {NILCONSTANT}, /* value */ diff --git a/liblua/ltable.h b/liblua/ltable.h index 2f6f5c2dc..b7d4f7db9 100644 --- a/liblua/ltable.h +++ b/liblua/ltable.h @@ -10,12 +10,12 @@ #include "lobject.h" -#define gnode(t,i) (&(t)->node[i]) -#define gkey(n) (&(n)->i_key.tvk) -#define gval(n) (&(n)->i_val) -#define gnext(n) ((n)->i_key.nk.next) +#define gnode(t,i) (&(t)->node[i]) +#define gkey(n) (&(n)->i_key.tvk) +#define gval(n) (&(n)->i_val) +#define gnext(n) ((n)->i_key.nk.next) -#define invalidateTMcache(t) ((t)->flags = 0) +#define invalidateTMcache(t) ((t)->flags = 0) LUAI_FUNC const TValue *luaH_getint (Table *t, int key); diff --git a/liblua/ltablib.c b/liblua/ltablib.c index ad798b4e2..ba8de3f29 100644 --- a/liblua/ltablib.c +++ b/liblua/ltablib.c @@ -16,7 +16,7 @@ #include "lualib.h" -#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_len(L, n)) +#define aux_getn(L,n) (luaL_checktype(L, n, LUA_TTABLE), luaL_len(L, n)) diff --git a/liblua/ltm.h b/liblua/ltm.h index 89bdc19a1..a12037628 100644 --- a/liblua/ltm.h +++ b/liblua/ltm.h @@ -33,7 +33,7 @@ typedef enum { TM_LE, TM_CONCAT, TM_CALL, - TM_N /* number of elements in the enum */ + TM_N /* number of elements in the enum */ } TMS; @@ -41,10 +41,10 @@ typedef enum { #define gfasttm(g,et,e) ((et) == NULL ? NULL : \ ((et)->flags & (1u<<(e))) ? NULL : luaT_gettm(et, e, (g)->tmname[e])) -#define fasttm(l,et,e) gfasttm(G(l), et, e) +#define fasttm(l,et,e) gfasttm(G(l), et, e) -#define ttypename(x) luaT_typenames_[(x) + 1] -#define objtypename(x) ttypename(ttypenv(x)) +#define ttypename(x) luaT_typenames_[(x) + 1] +#define objtypename(x) ttypename(ttypenv(x)) LUAI_DDEC const char *const luaT_typenames_[LUA_TOTALTAGS]; diff --git a/liblua/lua.c b/liblua/lua.c index 6a0071292..cd6984494 100644 --- a/liblua/lua.c +++ b/liblua/lua.c @@ -19,24 +19,24 @@ #if !defined(LUA_PROMPT) -#define LUA_PROMPT "> " -#define LUA_PROMPT2 ">> " +#define LUA_PROMPT "> " +#define LUA_PROMPT2 ">> " #endif #if !defined(LUA_PROGNAME) -#define LUA_PROGNAME "lua" +#define LUA_PROGNAME "lua" #endif #if !defined(LUA_MAXINPUT) -#define LUA_MAXINPUT 512 +#define LUA_MAXINPUT 512 #endif #if !defined(LUA_INIT) -#define LUA_INIT "LUA_INIT" +#define LUA_INIT "LUA_INIT" #endif #define LUA_INITVERSION \ - LUA_INIT "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR + LUA_INIT "_" LUA_VERSION_MAJOR "_" LUA_VERSION_MINOR /* @@ -45,13 +45,13 @@ */ #if defined(LUA_USE_ISATTY) #include -#define lua_stdin_is_tty() isatty(0) +#define lua_stdin_is_tty() isatty(0) #elif defined(LUA_WIN) #include #include -#define lua_stdin_is_tty() _isatty(_fileno(stdin)) +#define lua_stdin_is_tty() _isatty(_fileno(stdin)) #else -#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ +#define lua_stdin_is_tty() 1 /* assume stdin is a tty */ #endif @@ -66,19 +66,19 @@ #include #include #include -#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) +#define lua_readline(L,b,p) ((void)L, ((b)=readline(p)) != NULL) #define lua_saveline(L,idx) \ if (lua_rawlen(L,idx) > 0) /* non-empty line? */ \ add_history(lua_tostring(L, idx)); /* add it to history */ -#define lua_freeline(L,b) ((void)L, free(b)) +#define lua_freeline(L,b) ((void)L, free(b)) #elif !defined(lua_readline) #define lua_readline(L,b,p) \ ((void)L, fputs(p, stdout), fflush(stdout), /* show prompt */ \ fgets(b, LUA_MAXINPUT, stdin) != NULL) /* get line */ -#define lua_saveline(L,idx) { (void)L; (void)idx; } -#define lua_freeline(L,b) { (void)L; (void)b; } +#define lua_saveline(L,idx) { (void)L; (void)idx; } +#define lua_freeline(L,b) { (void)L; (void)b; } #endif @@ -241,8 +241,8 @@ static const char *get_prompt (lua_State *L, int firstline) { } /* mark in error messages for incomplete statements */ -#define EOFMARK "" -#define marklen (sizeof(EOFMARK)/sizeof(char) - 1) +#define EOFMARK "" +#define marklen (sizeof(EOFMARK)/sizeof(char) - 1) static int incomplete (lua_State *L, int status) { if (status == LUA_ERRSYNTAX) { @@ -342,16 +342,16 @@ static int handle_script (lua_State *L, char **argv, int n) { /* check that argument has no extra characters at the end */ -#define noextrachars(x) {if ((x)[2] != '\0') return -1;} +#define noextrachars(x) {if ((x)[2] != '\0') return -1;} /* indices of various argument indicators in array args */ -#define has_i 0 /* -i */ -#define has_v 1 /* -v */ -#define has_e 2 /* -e */ -#define has_E 3 /* -E */ +#define has_i 0 /* -i */ +#define has_v 1 /* -v */ +#define has_e 2 /* -e */ +#define has_E 3 /* -E */ -#define num_has 4 /* number of 'has_*' */ +#define num_has 4 /* number of 'has_*' */ static int collectargs (char **argv, int *args) { diff --git a/liblua/lua.h b/liblua/lua.h index eb0482b8f..8346e227a 100644 --- a/liblua/lua.h +++ b/liblua/lua.h @@ -16,39 +16,39 @@ #include "luaconf.h" -#define LUA_VERSION_MAJOR "5" -#define LUA_VERSION_MINOR "2" -#define LUA_VERSION_NUM 502 -#define LUA_VERSION_RELEASE "2" +#define LUA_VERSION_MAJOR "5" +#define LUA_VERSION_MINOR "2" +#define LUA_VERSION_NUM 502 +#define LUA_VERSION_RELEASE "2" -#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR -#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE -#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2013 Lua.org, PUC-Rio" -#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" +#define LUA_VERSION "Lua " LUA_VERSION_MAJOR "." LUA_VERSION_MINOR +#define LUA_RELEASE LUA_VERSION "." LUA_VERSION_RELEASE +#define LUA_COPYRIGHT LUA_RELEASE " Copyright (C) 1994-2013 Lua.org, PUC-Rio" +#define LUA_AUTHORS "R. Ierusalimschy, L. H. de Figueiredo, W. Celes" /* mark for precompiled code ('Lua') */ -#define LUA_SIGNATURE "\033Lua" +#define LUA_SIGNATURE "\033Lua" /* option for multiple returns in 'lua_pcall' and 'lua_call' */ -#define LUA_MULTRET (-1) +#define LUA_MULTRET (-1) /* ** pseudo-indices */ -#define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX -#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) +#define LUA_REGISTRYINDEX LUAI_FIRSTPSEUDOIDX +#define lua_upvalueindex(i) (LUA_REGISTRYINDEX - (i)) /* thread status */ -#define LUA_OK 0 -#define LUA_YIELD 1 -#define LUA_ERRRUN 2 -#define LUA_ERRSYNTAX 3 -#define LUA_ERRMEM 4 -#define LUA_ERRGCMM 5 -#define LUA_ERRERR 6 +#define LUA_OK 0 +#define LUA_YIELD 1 +#define LUA_ERRRUN 2 +#define LUA_ERRSYNTAX 3 +#define LUA_ERRMEM 4 +#define LUA_ERRGCMM 5 +#define LUA_ERRERR 6 typedef struct lua_State lua_State; @@ -73,30 +73,30 @@ typedef void * (*lua_Alloc) (void *ud, void *ptr, size_t osize, size_t nsize); /* ** basic types */ -#define LUA_TNONE (-1) +#define LUA_TNONE (-1) -#define LUA_TNIL 0 -#define LUA_TBOOLEAN 1 -#define LUA_TLIGHTUSERDATA 2 -#define LUA_TNUMBER 3 -#define LUA_TSTRING 4 -#define LUA_TTABLE 5 -#define LUA_TFUNCTION 6 -#define LUA_TUSERDATA 7 -#define LUA_TTHREAD 8 +#define LUA_TNIL 0 +#define LUA_TBOOLEAN 1 +#define LUA_TLIGHTUSERDATA 2 +#define LUA_TNUMBER 3 +#define LUA_TSTRING 4 +#define LUA_TTABLE 5 +#define LUA_TFUNCTION 6 +#define LUA_TUSERDATA 7 +#define LUA_TTHREAD 8 -#define LUA_NUMTAGS 9 +#define LUA_NUMTAGS 9 /* minimum Lua stack available to a C function */ -#define LUA_MINSTACK 20 +#define LUA_MINSTACK 20 /* predefined values in the registry */ -#define LUA_RIDX_MAINTHREAD 1 -#define LUA_RIDX_GLOBALS 2 -#define LUA_RIDX_LAST LUA_RIDX_GLOBALS +#define LUA_RIDX_MAINTHREAD 1 +#define LUA_RIDX_GLOBALS 2 +#define LUA_RIDX_LAST LUA_RIDX_GLOBALS /* type of numbers in Lua */ @@ -172,7 +172,7 @@ LUA_API int (lua_toboolean) (lua_State *L, int idx); LUA_API const char *(lua_tolstring) (lua_State *L, int idx, size_t *len); LUA_API size_t (lua_rawlen) (lua_State *L, int idx); LUA_API lua_CFunction (lua_tocfunction) (lua_State *L, int idx); -LUA_API void *(lua_touserdata) (lua_State *L, int idx); +LUA_API void *(lua_touserdata) (lua_State *L, int idx); LUA_API lua_State *(lua_tothread) (lua_State *L, int idx); LUA_API const void *(lua_topointer) (lua_State *L, int idx); @@ -181,19 +181,19 @@ LUA_API const void *(lua_topointer) (lua_State *L, int idx); ** Comparison and arithmetic functions */ -#define LUA_OPADD 0 /* ORDER TM */ -#define LUA_OPSUB 1 -#define LUA_OPMUL 2 -#define LUA_OPDIV 3 -#define LUA_OPMOD 4 -#define LUA_OPPOW 5 -#define LUA_OPUNM 6 +#define LUA_OPADD 0 /* ORDER TM */ +#define LUA_OPSUB 1 +#define LUA_OPMUL 2 +#define LUA_OPDIV 3 +#define LUA_OPMOD 4 +#define LUA_OPPOW 5 +#define LUA_OPUNM 6 LUA_API void (lua_arith) (lua_State *L, int op); -#define LUA_OPEQ 0 -#define LUA_OPLT 1 -#define LUA_OPLE 2 +#define LUA_OPEQ 0 +#define LUA_OPLT 1 +#define LUA_OPLE 2 LUA_API int (lua_rawequal) (lua_State *L, int idx1, int idx2); LUA_API int (lua_compare) (lua_State *L, int idx1, int idx2, int op); @@ -250,13 +250,13 @@ LUA_API void (lua_setuservalue) (lua_State *L, int idx); */ LUA_API void (lua_callk) (lua_State *L, int nargs, int nresults, int ctx, lua_CFunction k); -#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) +#define lua_call(L,n,r) lua_callk(L, (n), (r), 0, NULL) LUA_API int (lua_getctx) (lua_State *L, int *ctx); LUA_API int (lua_pcallk) (lua_State *L, int nargs, int nresults, int errfunc, int ctx, lua_CFunction k); -#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) +#define lua_pcall(L,n,r,f) lua_pcallk(L, (n), (r), (f), 0, NULL) LUA_API int (lua_load) (lua_State *L, lua_Reader reader, void *dt, const char *chunkname, @@ -270,7 +270,7 @@ LUA_API int (lua_dump) (lua_State *L, lua_Writer writer, void *data); */ LUA_API int (lua_yieldk) (lua_State *L, int nresults, int ctx, lua_CFunction k); -#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) +#define lua_yield(L,n) lua_yieldk(L, (n), 0, NULL) LUA_API int (lua_resume) (lua_State *L, lua_State *from, int narg); LUA_API int (lua_status) (lua_State *L); @@ -278,18 +278,18 @@ LUA_API int (lua_status) (lua_State *L); ** garbage-collection function and options */ -#define LUA_GCSTOP 0 -#define LUA_GCRESTART 1 -#define LUA_GCCOLLECT 2 -#define LUA_GCCOUNT 3 -#define LUA_GCCOUNTB 4 -#define LUA_GCSTEP 5 -#define LUA_GCSETPAUSE 6 -#define LUA_GCSETSTEPMUL 7 -#define LUA_GCSETMAJORINC 8 -#define LUA_GCISRUNNING 9 -#define LUA_GCGEN 10 -#define LUA_GCINC 11 +#define LUA_GCSTOP 0 +#define LUA_GCRESTART 1 +#define LUA_GCCOLLECT 2 +#define LUA_GCCOUNT 3 +#define LUA_GCCOUNTB 4 +#define LUA_GCSTEP 5 +#define LUA_GCSETPAUSE 6 +#define LUA_GCSETSTEPMUL 7 +#define LUA_GCSETMAJORINC 8 +#define LUA_GCISRUNNING 9 +#define LUA_GCGEN 10 +#define LUA_GCINC 11 LUA_API int (lua_gc) (lua_State *L, int what, int data); @@ -316,34 +316,35 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); ** =============================================================== */ -#define lua_tonumber(L,i) lua_tonumberx(L,i,NULL) -#define lua_tointeger(L,i) lua_tointegerx(L,i,NULL) -#define lua_tounsigned(L,i) lua_tounsignedx(L,i,NULL) +#define lua_tonumber(L,i) lua_tonumberx(L,i,NULL) +#define lua_tointeger(L,i) lua_tointegerx(L,i,NULL) +#define lua_tounsigned(L,i) lua_tounsignedx(L,i,NULL) -#define lua_pop(L,n) lua_settop(L, -(n)-1) +#define lua_pop(L,n) lua_settop(L, -(n)-1) -#define lua_newtable(L) lua_createtable(L, 0, 0) +#define lua_newtable(L) lua_createtable(L, 0, 0) -#define lua_register(L,n,f) (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) +#define lua_register(L,n,f) \ + (lua_pushcfunction(L, (f)), lua_setglobal(L, (n))) -#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) +#define lua_pushcfunction(L,f) lua_pushcclosure(L, (f), 0) -#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) -#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) -#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) -#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) -#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) -#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) -#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) -#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) +#define lua_isfunction(L,n) (lua_type(L, (n)) == LUA_TFUNCTION) +#define lua_istable(L,n) (lua_type(L, (n)) == LUA_TTABLE) +#define lua_islightuserdata(L,n) (lua_type(L, (n)) == LUA_TLIGHTUSERDATA) +#define lua_isnil(L,n) (lua_type(L, (n)) == LUA_TNIL) +#define lua_isboolean(L,n) (lua_type(L, (n)) == LUA_TBOOLEAN) +#define lua_isthread(L,n) (lua_type(L, (n)) == LUA_TTHREAD) +#define lua_isnone(L,n) (lua_type(L, (n)) == LUA_TNONE) +#define lua_isnoneornil(L, n) (lua_type(L, (n)) <= 0) -#define lua_pushliteral(L, s) \ - lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) +#define lua_pushliteral(L, s) \ + lua_pushlstring(L, "" s, (sizeof(s)/sizeof(char))-1) -#define lua_pushglobaltable(L) \ - lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) +#define lua_pushglobaltable(L) \ + lua_rawgeti(L, LUA_REGISTRYINDEX, LUA_RIDX_GLOBALS) -#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) +#define lua_tostring(L,i) lua_tolstring(L, (i), NULL) @@ -357,20 +358,20 @@ LUA_API void (lua_setallocf) (lua_State *L, lua_Alloc f, void *ud); /* ** Event codes */ -#define LUA_HOOKCALL 0 -#define LUA_HOOKRET 1 -#define LUA_HOOKLINE 2 -#define LUA_HOOKCOUNT 3 +#define LUA_HOOKCALL 0 +#define LUA_HOOKRET 1 +#define LUA_HOOKLINE 2 +#define LUA_HOOKCOUNT 3 #define LUA_HOOKTAILCALL 4 /* ** Event masks */ -#define LUA_MASKCALL (1 << LUA_HOOKCALL) -#define LUA_MASKRET (1 << LUA_HOOKRET) -#define LUA_MASKLINE (1 << LUA_HOOKLINE) -#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) +#define LUA_MASKCALL (1 << LUA_HOOKCALL) +#define LUA_MASKRET (1 << LUA_HOOKRET) +#define LUA_MASKLINE (1 << LUA_HOOKLINE) +#define LUA_MASKCOUNT (1 << LUA_HOOKCOUNT) typedef struct lua_Debug lua_Debug; /* activation record */ @@ -398,17 +399,17 @@ LUA_API int (lua_gethookcount) (lua_State *L); struct lua_Debug { int event; - const char *name; /* (n) */ - const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ - const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ - const char *source; /* (S) */ - int currentline; /* (l) */ - int linedefined; /* (S) */ - int lastlinedefined; /* (S) */ - unsigned char nups; /* (u) number of upvalues */ + const char *name; /* (n) */ + const char *namewhat; /* (n) 'global', 'local', 'field', 'method' */ + const char *what; /* (S) 'Lua', 'C', 'main', 'tail' */ + const char *source; /* (S) */ + int currentline; /* (l) */ + int linedefined; /* (S) */ + int lastlinedefined; /* (S) */ + unsigned char nups; /* (u) number of upvalues */ unsigned char nparams;/* (u) number of parameters */ char isvararg; /* (u) */ - char istailcall; /* (t) */ + char istailcall; /* (t) */ char short_src[LUA_IDSIZE]; /* (S) */ /* private part */ struct CallInfo *i_ci; /* active function */ diff --git a/liblua/luac.c b/liblua/luac.c index 5081836d4..d1533d4e7 100644 --- a/liblua/luac.c +++ b/liblua/luac.c @@ -20,17 +20,17 @@ #include "lundump.h" static void PrintFunction(const Proto* f, int full); -#define luaU_print PrintFunction +#define luaU_print PrintFunction -#define PROGNAME "luac" /* default program name */ -#define OUTPUT PROGNAME ".out" /* default output file */ +#define PROGNAME "luac" /* default program name */ +#define OUTPUT PROGNAME ".out" /* default output file */ -static int listing=0; /* list bytecodes? */ -static int dumping=1; /* dump bytecodes? */ -static int stripping=0; /* strip debug information? */ -static char Output[]={ OUTPUT }; /* default output file name */ -static const char* output=Output; /* actual output file name */ -static const char* progname=PROGNAME; /* actual program name */ +static int listing=0; /* list bytecodes? */ +static int dumping=1; /* dump bytecodes? */ +static int stripping=0; /* strip debug information? */ +static char Output[]={ OUTPUT }; /* default output file name */ +static const char* output=Output; /* actual output file name */ +static const char* progname=PROGNAME; /* actual program name */ static void fatal(const char* message) { @@ -64,7 +64,7 @@ static void usage(const char* message) exit(EXIT_FAILURE); } -#define IS(s) (strcmp(argv[i],s)==0) +#define IS(s) (strcmp(argv[i],s)==0) static int doargs(int argc, char* argv[]) { @@ -73,32 +73,32 @@ static int doargs(int argc, char* argv[]) if (argv[0]!=NULL && *argv[0]!=0) progname=argv[0]; for (i=1; iupvalues[x].name) ? getstr(f->upvalues[x].name) : "-") -#define MYK(x) (-1-(x)) +#define MYK(x) (-1-(x)) static void PrintCode(const Proto* f) { @@ -372,8 +372,8 @@ static void PrintCode(const Proto* f) } } -#define SS(x) ((x==1)?"":"s") -#define S(x) (int)(x),SS(x) +#define SS(x) ((x==1)?"":"s") +#define S(x) (int)(x),SS(x) static void PrintHeader(const Proto* f) { @@ -385,14 +385,14 @@ static void PrintHeader(const Proto* f) else s="(string)"; printf("\n%s <%s:%d,%d> (%d instruction%s at %p)\n", - (f->linedefined==0)?"main":"function",s, - f->linedefined,f->lastlinedefined, - S(f->sizecode),VOID(f)); + (f->linedefined==0)?"main":"function",s, + f->linedefined,f->lastlinedefined, + S(f->sizecode),VOID(f)); printf("%d%s param%s, %d slot%s, %d upvalue%s, ", - (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), - S(f->maxstacksize),S(f->sizeupvalues)); + (int)(f->numparams),f->is_vararg?"+":"",SS(f->numparams), + S(f->maxstacksize),S(f->sizeupvalues)); printf("%d local%s, %d constant%s, %d function%s\n", - S(f->sizelocvars),S(f->sizek),S(f->sizep)); + S(f->sizelocvars),S(f->sizek),S(f->sizep)); } static void PrintDebug(const Proto* f) diff --git a/liblua/luaconf.h b/liblua/luaconf.h index df802c952..f004c5a8a 100644 --- a/liblua/luaconf.h +++ b/liblua/luaconf.h @@ -30,32 +30,32 @@ #if !defined(LUA_ANSI) && defined(_WIN32) && !defined(_WIN32_WCE) -#define LUA_WIN /* enable goodies for regular Windows platforms */ +#define LUA_WIN /* enable goodies for regular Windows platforms */ #endif #if defined(LUA_WIN) #define LUA_DL_DLL -#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ #endif #if defined(LUA_USE_LINUX) #define LUA_USE_POSIX -#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ -#define LUA_USE_READLINE /* needs some extra libraries */ -#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ -#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ -#define LUA_USE_LONGLONG /* assume support for long long */ +#define LUA_USE_DLOPEN /* needs an extra library: -ldl */ +#define LUA_USE_READLINE /* needs some extra libraries */ +#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#define LUA_USE_LONGLONG /* assume support for long long */ #endif #if defined(LUA_USE_MACOSX) #define LUA_USE_POSIX -#define LUA_USE_DLOPEN /* does not need -ldl */ -#define LUA_USE_READLINE /* needs an extra library: -lreadline */ -#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ -#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ -#define LUA_USE_LONGLONG /* assume support for long long */ +#define LUA_USE_DLOPEN /* does not need -ldl */ +#define LUA_USE_READLINE /* needs an extra library: -lreadline */ +#define LUA_USE_STRTODHEX /* assume 'strtod' handles hex formats */ +#define LUA_USE_AFORMAT /* assume 'printf' handles 'aA' specifiers */ +#define LUA_USE_LONGLONG /* assume support for long long */ #endif @@ -84,31 +84,31 @@ ** hierarchy or if you want to install your libraries in ** non-conventional directories. */ -#if defined(_WIN32) /* { */ +#if defined(_WIN32) /* { */ /* ** In Windows, any exclamation mark ('!') in the path is replaced by the ** path of the directory of the executable file of the current process. */ -#define LUA_LDIR "!\\lua\\" -#define LUA_CDIR "!\\" +#define LUA_LDIR "!\\lua\\" +#define LUA_CDIR "!\\" #define LUA_PATH_DEFAULT \ - LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua" + LUA_LDIR"?.lua;" LUA_LDIR"?\\init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?\\init.lua;" ".\\?.lua" #define LUA_CPATH_DEFAULT \ - LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" + LUA_CDIR"?.dll;" LUA_CDIR"loadall.dll;" ".\\?.dll" -#else /* }{ */ +#else /* }{ */ -#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/" -#define LUA_ROOT "/usr/local/" -#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR -#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR +#define LUA_VDIR LUA_VERSION_MAJOR "." LUA_VERSION_MINOR "/" +#define LUA_ROOT "/usr/local/" +#define LUA_LDIR LUA_ROOT "share/lua/" LUA_VDIR +#define LUA_CDIR LUA_ROOT "lib/lua/" LUA_VDIR #define LUA_PATH_DEFAULT \ - LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ - LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua" + LUA_LDIR"?.lua;" LUA_LDIR"?/init.lua;" \ + LUA_CDIR"?.lua;" LUA_CDIR"?/init.lua;" "./?.lua" #define LUA_CPATH_DEFAULT \ - LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" -#endif /* } */ + LUA_CDIR"?.so;" LUA_CDIR"loadall.so;" "./?.so" +#endif /* } */ /* @@ -117,9 +117,9 @@ ** and is not Windows. (On Windows Lua automatically uses "\".) */ #if defined(_WIN32) -#define LUA_DIRSEP "\\" +#define LUA_DIRSEP "\\" #else -#define LUA_DIRSEP "/" +#define LUA_DIRSEP "/" #endif @@ -128,7 +128,7 @@ @@ environment, used to access global names. ** CHANGE it if you do not like this name. */ -#define LUA_ENV "_ENV" +#define LUA_ENV "_ENV" /* @@ -140,24 +140,24 @@ ** the libraries, you may want to use the following definition (define ** LUA_BUILD_AS_DLL to get it). */ -#if defined(LUA_BUILD_AS_DLL) /* { */ +#if defined(LUA_BUILD_AS_DLL) /* { */ -#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ +#if defined(LUA_CORE) || defined(LUA_LIB) /* { */ #define LUA_API __declspec(dllexport) -#else /* }{ */ +#else /* }{ */ #define LUA_API __declspec(dllimport) -#endif /* } */ +#endif /* } */ -#else /* }{ */ +#else /* }{ */ -#define LUA_API extern +#define LUA_API extern -#endif /* } */ +#endif /* } */ /* more often than not the libs go together with the core */ -#define LUALIB_API LUA_API -#define LUAMOD_API LUALIB_API +#define LUALIB_API LUA_API +#define LUAMOD_API LUALIB_API /* @@ -175,16 +175,16 @@ ** default definition. */ #if defined(__GNUC__) && ((__GNUC__*100 + __GNUC_MINOR__) >= 302) && \ - defined(__ELF__) /* { */ -#define LUAI_FUNC __attribute__((visibility("hidden"))) extern -#define LUAI_DDEC LUAI_FUNC -#define LUAI_DDEF /* empty */ + defined(__ELF__) /* { */ +#define LUAI_FUNC __attribute__((visibility("hidden"))) extern +#define LUAI_DDEC LUAI_FUNC +#define LUAI_DDEF /* empty */ -#else /* }{ */ -#define LUAI_FUNC extern -#define LUAI_DDEC extern -#define LUAI_DDEF /* empty */ -#endif /* } */ +#else /* }{ */ +#define LUAI_FUNC extern +#define LUAI_DDEC extern +#define LUAI_DDEF /* empty */ +#endif /* } */ @@ -192,8 +192,8 @@ @@ LUA_QL describes how error messages quote program elements. ** CHANGE it if you want a different appearance. */ -#define LUA_QL(x) "'" x "'" -#define LUA_QS LUA_QL("%s") +#define LUA_QL(x) "'" x "'" +#define LUA_QS LUA_QL("%s") /* @@ -201,7 +201,7 @@ @* of a function in debug information. ** CHANGE it if you want a different size. */ -#define LUA_IDSIZE 60 +#define LUA_IDSIZE 60 /* @@ -211,8 +211,8 @@ */ #if defined(LUA_LIB) || defined(lua_c) #include -#define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) -#define luai_writeline() (luai_writestring("\n", 1), fflush(stdout)) +#define luai_writestring(s,l) fwrite((s), sizeof(char), (l), stdout) +#define luai_writeline() (luai_writestring("\n", 1), fflush(stdout)) #endif /* @@ -220,7 +220,7 @@ ** (A format string with one argument is enough for Lua...) */ #define luai_writestringerror(s,p) \ - (fprintf(stderr, (s), (p)), fflush(stderr)) + (fprintf(stderr, (s), (p)), fflush(stderr)) /* @@ -244,7 +244,7 @@ ** You can define it to get all options, or change specific options ** to fit your specific needs. */ -#if defined(LUA_COMPAT_ALL) /* { */ +#if defined(LUA_COMPAT_ALL) /* { */ /* @@ LUA_COMPAT_UNPACK controls the presence of global 'unpack'. @@ -263,9 +263,9 @@ ** You can call your C function directly (with light C functions). */ #define lua_cpcall(L,f,u) \ - (lua_pushcfunction(L, (f)), \ - lua_pushlightuserdata(L,(u)), \ - lua_pcall(L,1,0,0)) + (lua_pushcfunction(L, (f)), \ + lua_pushlightuserdata(L,(u)), \ + lua_pcall(L,1,0,0)) /* @@ -290,12 +290,12 @@ ** changes in the API. The macros themselves document how to ** change your code to avoid using them. */ -#define lua_strlen(L,i) lua_rawlen(L, (i)) +#define lua_strlen(L,i) lua_rawlen(L, (i)) -#define lua_objlen(L,i) lua_rawlen(L, (i)) +#define lua_objlen(L,i) lua_rawlen(L, (i)) -#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) -#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) +#define lua_equal(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPEQ) +#define lua_lessthan(L,idx1,idx2) lua_compare(L,(idx1),(idx2),LUA_OPLT) /* @@ LUA_COMPAT_MODULE controls compatibility with previous @@ -303,7 +303,7 @@ */ #define LUA_COMPAT_MODULE -#endif /* } */ +#endif /* } */ /* }================================================================== */ @@ -315,14 +315,14 @@ ** your machine. Probably you do not need to change this. */ /* avoid overflows in comparison */ -#if INT_MAX-20 < 32760 /* { */ -#define LUAI_BITSINT 16 -#elif INT_MAX > 2147483640L /* }{ */ +#if INT_MAX-20 < 32760 /* { */ +#define LUAI_BITSINT 16 +#elif INT_MAX > 2147483640L /* }{ */ /* int has at least 32 bits */ -#define LUAI_BITSINT 32 -#else /* }{ */ +#define LUAI_BITSINT 32 +#else /* }{ */ #error "you must define LUA_BITSINT with number of bits in an integer" -#endif /* } */ +#endif /* } */ /* @@ -335,16 +335,16 @@ ** good enough for your machine. Probably you do not need to change ** this. */ -#if LUAI_BITSINT >= 32 /* { */ -#define LUA_INT32 int -#define LUAI_UMEM size_t -#define LUAI_MEM ptrdiff_t -#else /* }{ */ +#if LUAI_BITSINT >= 32 /* { */ +#define LUA_INT32 int +#define LUAI_UMEM size_t +#define LUAI_MEM ptrdiff_t +#else /* }{ */ /* 16-bit ints */ -#define LUA_INT32 long -#define LUAI_UMEM unsigned long -#define LUAI_MEM long -#endif /* } */ +#define LUA_INT32 long +#define LUAI_UMEM unsigned long +#define LUAI_MEM long +#endif /* } */ /* @@ -354,13 +354,13 @@ ** space (and to reserve some numbers for pseudo-indices). */ #if LUAI_BITSINT >= 32 -#define LUAI_MAXSTACK 1000000 +#define LUAI_MAXSTACK 1000000 #else -#define LUAI_MAXSTACK 15000 +#define LUAI_MAXSTACK 15000 #endif /* reserve some space for error handling */ -#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000) +#define LUAI_FIRSTPSEUDOIDX (-LUAI_MAXSTACK - 1000) @@ -369,7 +369,7 @@ @@ LUAL_BUFFERSIZE is the buffer size used by the lauxlib buffer system. ** CHANGE it if it uses too much C-stack space. */ -#define LUAL_BUFFERSIZE BUFSIZ +#define LUAL_BUFFERSIZE BUFSIZ @@ -384,13 +384,13 @@ */ #define LUA_NUMBER_DOUBLE -#define LUA_NUMBER double +#define LUA_NUMBER double /* @@ LUAI_UACNUMBER is the result of an 'usual argument conversion' @* over a number. */ -#define LUAI_UACNUMBER double +#define LUAI_UACNUMBER double /* @@ -399,16 +399,16 @@ @@ lua_number2str converts a number to a string. @@ LUAI_MAXNUMBER2STR is maximum size of previous conversion. */ -#define LUA_NUMBER_SCAN "%lf" -#define LUA_NUMBER_FMT "%.14g" -#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) -#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ +#define LUA_NUMBER_SCAN "%lf" +#define LUA_NUMBER_FMT "%.14g" +#define lua_number2str(s,n) sprintf((s), LUA_NUMBER_FMT, (n)) +#define LUAI_MAXNUMBER2STR 32 /* 16 digits, sign, point, and \0 */ /* @@ l_mathop allows the addition of an 'l' or 'f' to all math operations */ -#define l_mathop(x) (x) +#define l_mathop(x) (x) /* @@ -419,10 +419,10 @@ ** systems, you can leave 'lua_strx2number' undefined and Lua will ** provide its own implementation. */ -#define lua_str2number(s,p) strtod((s), (p)) +#define lua_str2number(s,p) strtod((s), (p)) #if defined(LUA_USE_STRTODHEX) -#define lua_strx2number(s,p) strtod((s), (p)) +#define lua_strx2number(s,p) strtod((s), (p)) #endif @@ -433,21 +433,21 @@ /* the following operations need the math library */ #if defined(lobject_c) || defined(lvm_c) #include -#define luai_nummod(L,a,b) ((a) - l_mathop(floor)((a)/(b))*(b)) -#define luai_numpow(L,a,b) (l_mathop(pow)(a,b)) +#define luai_nummod(L,a,b) ((a) - l_mathop(floor)((a)/(b))*(b)) +#define luai_numpow(L,a,b) (l_mathop(pow)(a,b)) #endif /* these are quite standard operations */ #if defined(LUA_CORE) -#define luai_numadd(L,a,b) ((a)+(b)) -#define luai_numsub(L,a,b) ((a)-(b)) -#define luai_nummul(L,a,b) ((a)*(b)) -#define luai_numdiv(L,a,b) ((a)/(b)) -#define luai_numunm(L,a) (-(a)) -#define luai_numeq(a,b) ((a)==(b)) -#define luai_numlt(L,a,b) ((a)<(b)) -#define luai_numle(L,a,b) ((a)<=(b)) -#define luai_numisnan(L,a) (!luai_numeq((a), (a))) +#define luai_numadd(L,a,b) ((a)+(b)) +#define luai_numsub(L,a,b) ((a)-(b)) +#define luai_nummul(L,a,b) ((a)*(b)) +#define luai_numdiv(L,a,b) ((a)/(b)) +#define luai_numunm(L,a) (-(a)) +#define luai_numeq(a,b) ((a)==(b)) +#define luai_numlt(L,a,b) ((a)<(b)) +#define luai_numle(L,a,b) ((a)<=(b)) +#define luai_numisnan(L,a) (!luai_numeq((a), (a))) #endif @@ -457,13 +457,13 @@ ** CHANGE that if ptrdiff_t is not adequate on your machine. (On most ** machines, ptrdiff_t gives a good choice between int or long.) */ -#define LUA_INTEGER ptrdiff_t +#define LUA_INTEGER ptrdiff_t /* @@ LUA_UNSIGNED is the integral type used by lua_pushunsigned/lua_tounsigned. ** It must have at least 32 bits. */ -#define LUA_UNSIGNED unsigned LUA_INT32 +#define LUA_UNSIGNED unsigned LUA_INT32 @@ -471,7 +471,7 @@ ** Some tricks with doubles */ -#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ +#if defined(LUA_NUMBER_DOUBLE) && !defined(LUA_ANSI) /* { */ /* ** The next definitions activate some tricks to speed up the ** conversion from doubles to integer types, mainly to LUA_UNSIGNED. @@ -498,10 +498,10 @@ */ /* Microsoft compiler on a Pentium (32 bit) ? */ -#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ +#if defined(LUA_WIN) && defined(_MSC_VER) && defined(_M_IX86) /* { */ #define LUA_MSASMTRICK -#define LUA_IEEEENDIAN 0 +#define LUA_IEEEENDIAN 0 #define LUA_NANTRICK @@ -510,28 +510,28 @@ #define LUA_IEEE754TRICK #define LUA_IEEELL -#define LUA_IEEEENDIAN 0 +#define LUA_IEEEENDIAN 0 #define LUA_NANTRICK /* pentium 64 bits? */ -#elif defined(__x86_64) /* }{ */ +#elif defined(__x86_64) /* }{ */ #define LUA_IEEE754TRICK -#define LUA_IEEEENDIAN 0 +#define LUA_IEEEENDIAN 0 -#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */ +#elif defined(__POWERPC__) || defined(__ppc__) /* }{ */ #define LUA_IEEE754TRICK -#define LUA_IEEEENDIAN 1 +#define LUA_IEEEENDIAN 1 -#else /* }{ */ +#else /* }{ */ /* assume IEEE754 and a 32-bit integer type */ #define LUA_IEEE754TRICK -#endif /* } */ +#endif /* } */ -#endif /* } */ +#endif /* } */ /* }================================================================== */ diff --git a/liblua/lualib.h b/liblua/lualib.h index 9fd126bf7..0a123aa2c 100644 --- a/liblua/lualib.h +++ b/liblua/lualib.h @@ -14,31 +14,31 @@ LUAMOD_API int (luaopen_base) (lua_State *L); -#define LUA_COLIBNAME "coroutine" +#define LUA_COLIBNAME "coroutine" LUAMOD_API int (luaopen_coroutine) (lua_State *L); -#define LUA_TABLIBNAME "table" +#define LUA_TABLIBNAME "table" LUAMOD_API int (luaopen_table) (lua_State *L); -#define LUA_IOLIBNAME "io" +#define LUA_IOLIBNAME "io" LUAMOD_API int (luaopen_io) (lua_State *L); -#define LUA_OSLIBNAME "os" +#define LUA_OSLIBNAME "os" LUAMOD_API int (luaopen_os) (lua_State *L); -#define LUA_STRLIBNAME "string" +#define LUA_STRLIBNAME "string" LUAMOD_API int (luaopen_string) (lua_State *L); -#define LUA_BITLIBNAME "bit32" +#define LUA_BITLIBNAME "bit32" LUAMOD_API int (luaopen_bit32) (lua_State *L); -#define LUA_MATHLIBNAME "math" +#define LUA_MATHLIBNAME "math" LUAMOD_API int (luaopen_math) (lua_State *L); -#define LUA_DBLIBNAME "debug" +#define LUA_DBLIBNAME "debug" LUAMOD_API int (luaopen_debug) (lua_State *L); -#define LUA_LOADLIBNAME "package" +#define LUA_LOADLIBNAME "package" LUAMOD_API int (luaopen_package) (lua_State *L); @@ -48,7 +48,7 @@ LUALIB_API void (luaL_openlibs) (lua_State *L); #if !defined(lua_assert) -#define lua_assert(x) ((void)0) +#define lua_assert(x) ((void)0) #endif diff --git a/liblua/lundump.c b/liblua/lundump.c index 54de011a4..0ee0f3527 100644 --- a/liblua/lundump.c +++ b/liblua/lundump.c @@ -33,13 +33,13 @@ static l_noret error(LoadState* S, const char* why) luaD_throw(S->L,LUA_ERRSYNTAX); } -#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) -#define LoadByte(S) (lu_byte)LoadChar(S) -#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) -#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) +#define LoadMem(S,b,n,size) LoadBlock(S,b,(n)*(size)) +#define LoadByte(S) (lu_byte)LoadChar(S) +#define LoadVar(S,x) LoadMem(S,&x,1,sizeof(x)) +#define LoadVector(S,b,n,size) LoadMem(S,b,n,size) #if !defined(luai_verifycode) -#define luai_verifycode(L,b,f) /* empty */ +#define luai_verifycode(L,b,f) /* empty */ #endif static void LoadBlock(LoadState* S, void* b, size_t size) @@ -79,7 +79,7 @@ static TString* LoadString(LoadState* S) { char* s=luaZ_openspace(S->L,S->b,size); LoadBlock(S,s,size*sizeof(char)); - return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ + return luaS_newlstr(S->L,s,size-1); /* remove trailing '\0' */ } } @@ -107,17 +107,17 @@ static void LoadConstants(LoadState* S, Proto* f) switch (t) { case LUA_TNIL: - setnilvalue(o); - break; + setnilvalue(o); + break; case LUA_TBOOLEAN: - setbvalue(o,LoadChar(S)); - break; + setbvalue(o,LoadChar(S)); + break; case LUA_TNUMBER: - setnvalue(o,LoadNumber(S)); - break; + setnvalue(o,LoadNumber(S)); + break; case LUA_TSTRING: - setsvalue2n(S->L,o,LoadString(S)); - break; + setsvalue2n(S->L,o,LoadString(S)); + break; default: lua_assert(0); } } @@ -182,17 +182,17 @@ static void LoadFunction(LoadState* S, Proto* f) } /* the code below must be consistent with the code in luaU_header */ -#define N0 LUAC_HEADERSIZE -#define N1 (sizeof(LUA_SIGNATURE)-sizeof(char)) -#define N2 N1+2 -#define N3 N2+6 +#define N0 LUAC_HEADERSIZE +#define N1 (sizeof(LUA_SIGNATURE)-sizeof(char)) +#define N2 N1+2 +#define N3 N2+6 static void LoadHeader(LoadState* S) { lu_byte h[LUAC_HEADERSIZE]; lu_byte s[LUAC_HEADERSIZE]; luaU_header(h); - memcpy(s,h,sizeof(char)); /* first char already read */ + memcpy(s,h,sizeof(char)); /* first char already read */ LoadBlock(S,s+sizeof(char),LUAC_HEADERSIZE-sizeof(char)); if (memcmp(h,s,N0)==0) return; if (memcmp(h,s,N1)!=0) error(S,"not a"); @@ -232,9 +232,9 @@ Closure* luaU_undump (lua_State* L, ZIO* Z, Mbuffer* buff, const char* name) return cl; } -#define MYINT(s) (s[0]-'0') -#define VERSION MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR) -#define FORMAT 0 /* this is the official format */ +#define MYINT(s) (s[0]-'0') +#define VERSION MYINT(LUA_VERSION_MAJOR)*16+MYINT(LUA_VERSION_MINOR) +#define FORMAT 0 /* this is the official format */ /* * make header for precompiled chunks @@ -248,11 +248,11 @@ void luaU_header (lu_byte* h) h+=sizeof(LUA_SIGNATURE)-sizeof(char); *h++=cast_byte(VERSION); *h++=cast_byte(FORMAT); - *h++=cast_byte(*(char*)&x); /* endianness */ + *h++=cast_byte(*(char*)&x); /* endianness */ *h++=cast_byte(sizeof(int)); *h++=cast_byte(sizeof(size_t)); *h++=cast_byte(sizeof(Instruction)); *h++=cast_byte(sizeof(lua_Number)); - *h++=cast_byte(((lua_Number)0.5)==0); /* is lua_Number integral? */ + *h++=cast_byte(((lua_Number)0.5)==0); /* is lua_Number integral? */ memcpy(h,LUAC_TAIL,sizeof(LUAC_TAIL)-sizeof(char)); } diff --git a/liblua/lundump.h b/liblua/lundump.h index 2b8accecb..9a0643d57 100644 --- a/liblua/lundump.h +++ b/liblua/lundump.h @@ -20,9 +20,9 @@ LUAI_FUNC void luaU_header (lu_byte* h); LUAI_FUNC int luaU_dump (lua_State* L, const Proto* f, lua_Writer w, void* data, int strip); /* data to catch conversion errors */ -#define LUAC_TAIL "\x19\x93\r\n\x1a\n" +#define LUAC_TAIL "\x19\x93\r\n\x1a\n" /* size in bytes of header of binary files */ -#define LUAC_HEADERSIZE (sizeof(LUA_SIGNATURE)-sizeof(char)+2+6+sizeof(LUAC_TAIL)-sizeof(char)) +#define LUAC_HEADERSIZE (sizeof(LUA_SIGNATURE)-sizeof(char)+2+6+sizeof(LUAC_TAIL)-sizeof(char)) #endif diff --git a/liblua/lvm.c b/liblua/lvm.c index 657d5c456..8e8f26636 100644 --- a/liblua/lvm.c +++ b/liblua/lvm.c @@ -29,7 +29,7 @@ /* limit for table tag-method chains (to avoid loops) */ -#define MAXTAGLOOP 100 +#define MAXTAGLOOP 100 const TValue *luaV_tonumber (const TValue *obj, TValue *n) { @@ -482,18 +482,18 @@ void luaV_finishOp (lua_State *L) { */ #if !defined luai_runtimecheck -#define luai_runtimecheck(L, c) /* void */ +#define luai_runtimecheck(L, c) /* void */ #endif -#define RA(i) (base+GETARG_A(i)) +#define RA(i) (base+GETARG_A(i)) /* to be used after possible stack reallocation */ -#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) -#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) -#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ - ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) -#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ - ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) +#define RB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgR, base+GETARG_B(i)) +#define RC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgR, base+GETARG_C(i)) +#define RKB(i) check_exp(getBMode(GET_OPCODE(i)) == OpArgK, \ + ISK(GETARG_B(i)) ? k+INDEXK(GETARG_B(i)) : base+GETARG_B(i)) +#define RKC(i) check_exp(getCMode(GET_OPCODE(i)) == OpArgK, \ + ISK(GETARG_C(i)) ? k+INDEXK(GETARG_C(i)) : base+GETARG_C(i)) #define KBx(i) \ (k + (GETARG_Bx(i) != 0 ? GETARG_Bx(i) - 1 : GETARG_Ax(*ci->u.l.savedpc++))) @@ -505,10 +505,10 @@ void luaV_finishOp (lua_State *L) { ci->u.l.savedpc += GETARG_sBx(i) + e; } /* for test instructions, execute the jump instruction that follows it */ -#define donextjump(ci) { i = *ci->u.l.savedpc; dojump(ci, i, 1); } +#define donextjump(ci) { i = *ci->u.l.savedpc; dojump(ci, i, 1); } -#define Protect(x) { {x;}; base = ci->u.l.base; } +#define Protect(x) { {x;}; base = ci->u.l.base; } #define checkGC(L,c) \ Protect( luaC_condGC(L,{L->top = (c); /* limit of live values */ \ @@ -527,9 +527,9 @@ void luaV_finishOp (lua_State *L) { else { Protect(luaV_arith(L, ra, rb, rc, tm)); } } -#define vmdispatch(o) switch(o) -#define vmcase(l,b) case l: {b} break; -#define vmcasenb(l,b) case l: {b} /* nb = no break */ +#define vmdispatch(o) switch(o) +#define vmcase(l,b) case l: {b} break; +#define vmcasenb(l,b) case l: {b} /* nb = no break */ void luaV_execute (lua_State *L) { CallInfo *ci = L->ci; diff --git a/liblua/lvm.h b/liblua/lvm.h index 07e25f9c6..caff32d21 100644 --- a/liblua/lvm.h +++ b/liblua/lvm.h @@ -15,11 +15,11 @@ #define tostring(L,o) (ttisstring(o) || (luaV_tostring(L, o))) -#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL)) +#define tonumber(o,n) (ttisnumber(o) || (((o) = luaV_tonumber(o,n)) != NULL)) #define equalobj(L,o1,o2) (ttisequal(o1, o2) && luaV_equalobj_(L, o1, o2)) -#define luaV_rawequalobj(o1,o2) equalobj(NULL,o1,o2) +#define luaV_rawequalobj(o1,o2) equalobj(NULL,o1,o2) /* not to called directly */ diff --git a/liblua/lzio.h b/liblua/lzio.h index 08682301e..f0cbe7e96 100644 --- a/liblua/lzio.h +++ b/liblua/lzio.h @@ -13,7 +13,7 @@ #include "lmem.h" -#define EOZ (-1) /* end of stream */ +#define EOZ (-1) /* end of stream */ typedef struct Zio ZIO; @@ -28,35 +28,35 @@ typedef struct Mbuffer { #define luaZ_initbuffer(L, buff) ((buff)->buffer = NULL, (buff)->buffsize = 0) -#define luaZ_buffer(buff) ((buff)->buffer) -#define luaZ_sizebuffer(buff) ((buff)->buffsize) -#define luaZ_bufflen(buff) ((buff)->n) +#define luaZ_buffer(buff) ((buff)->buffer) +#define luaZ_sizebuffer(buff) ((buff)->buffsize) +#define luaZ_bufflen(buff) ((buff)->n) #define luaZ_resetbuffer(buff) ((buff)->n = 0) #define luaZ_resizebuffer(L, buff, size) \ - (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ - (buff)->buffsize = size) + (luaM_reallocvector(L, (buff)->buffer, (buff)->buffsize, size, char), \ + (buff)->buffsize = size) -#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) +#define luaZ_freebuffer(L, buff) luaZ_resizebuffer(L, buff, 0) LUAI_FUNC char *luaZ_openspace (lua_State *L, Mbuffer *buff, size_t n); LUAI_FUNC void luaZ_init (lua_State *L, ZIO *z, lua_Reader reader, void *data); -LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ +LUAI_FUNC size_t luaZ_read (ZIO* z, void* b, size_t n); /* read next n bytes */ /* --------- Private Part ------------------ */ struct Zio { - size_t n; /* bytes still unread */ - const char *p; /* current position in buffer */ - lua_Reader reader; /* reader function */ - void* data; /* additional data */ - lua_State *L; /* Lua state (for reader) */ + size_t n; /* bytes still unread */ + const char *p; /* current position in buffer */ + lua_Reader reader; /* reader function */ + void* data; /* additional data */ + lua_State *L; /* Lua state (for reader) */ }; From 9502b54aa07aaa037100aaabfddf65dd0f056fe2 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 18:41:30 +0100 Subject: [PATCH 0706/1938] include: fix mix of spaces & tabs --- include/at91sam7s512.h | 888 ++++++++++++++++++++--------------------- include/common.h | 42 +- include/config_gpio.h | 66 +-- include/hitag2.h | 36 +- include/hitagS.h | 86 ++-- include/legic.h | 10 +- include/mifare.h | 174 ++++---- include/proxmark3.h | 140 +++---- include/usb_cmd.h | 140 +++---- 9 files changed, 791 insertions(+), 791 deletions(-) diff --git a/include/at91sam7s512.h b/include/at91sam7s512.h index 7dd557636..f8fa2e8d4 100644 --- a/include/at91sam7s512.h +++ b/include/at91sam7s512.h @@ -71,126 +71,126 @@ typedef volatile unsigned int AT91_REG;// Hardware register definition // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_SYS { - AT91_REG AIC_SMR[32]; // Source Mode Register - AT91_REG AIC_SVR[32]; // Source Vector Register - AT91_REG AIC_IVR; // IRQ Vector Register - AT91_REG AIC_FVR; // FIQ Vector Register - AT91_REG AIC_ISR; // Interrupt Status Register - AT91_REG AIC_IPR; // Interrupt Pending Register - AT91_REG AIC_IMR; // Interrupt Mask Register - AT91_REG AIC_CISR; // Core Interrupt Status Register - AT91_REG Reserved0[2]; // - AT91_REG AIC_IECR; // Interrupt Enable Command Register - AT91_REG AIC_IDCR; // Interrupt Disable Command Register - AT91_REG AIC_ICCR; // Interrupt Clear Command Register - AT91_REG AIC_ISCR; // Interrupt Set Command Register - AT91_REG AIC_EOICR; // End of Interrupt Command Register - AT91_REG AIC_SPU; // Spurious Vector Register - AT91_REG AIC_DCR; // Debug Control Register (Protect) - AT91_REG Reserved1[1]; // - AT91_REG AIC_FFER; // Fast Forcing Enable Register - AT91_REG AIC_FFDR; // Fast Forcing Disable Register - AT91_REG AIC_FFSR; // Fast Forcing Status Register - AT91_REG Reserved2[45]; // - AT91_REG DBGU_CR; // Control Register - AT91_REG DBGU_MR; // Mode Register - AT91_REG DBGU_IER; // Interrupt Enable Register - AT91_REG DBGU_IDR; // Interrupt Disable Register - AT91_REG DBGU_IMR; // Interrupt Mask Register - AT91_REG DBGU_CSR; // Channel Status Register - AT91_REG DBGU_RHR; // Receiver Holding Register - AT91_REG DBGU_THR; // Transmitter Holding Register - AT91_REG DBGU_BRGR; // Baud Rate Generator Register - AT91_REG Reserved3[7]; // - AT91_REG DBGU_CIDR; // Chip ID Register - AT91_REG DBGU_EXID; // Chip ID Extension Register - AT91_REG DBGU_FNTR; // Force NTRST Register - AT91_REG Reserved4[45]; // - AT91_REG DBGU_RPR; // Receive Pointer Register - AT91_REG DBGU_RCR; // Receive Counter Register - AT91_REG DBGU_TPR; // Transmit Pointer Register - AT91_REG DBGU_TCR; // Transmit Counter Register - AT91_REG DBGU_RNPR; // Receive Next Pointer Register - AT91_REG DBGU_RNCR; // Receive Next Counter Register - AT91_REG DBGU_TNPR; // Transmit Next Pointer Register - AT91_REG DBGU_TNCR; // Transmit Next Counter Register - AT91_REG DBGU_PTCR; // PDC Transfer Control Register - AT91_REG DBGU_PTSR; // PDC Transfer Status Register - AT91_REG Reserved5[54]; // - AT91_REG PIOA_PER; // PIO Enable Register - AT91_REG PIOA_PDR; // PIO Disable Register - AT91_REG PIOA_PSR; // PIO Status Register - AT91_REG Reserved6[1]; // - AT91_REG PIOA_OER; // Output Enable Register - AT91_REG PIOA_ODR; // Output Disable Registerr - AT91_REG PIOA_OSR; // Output Status Register - AT91_REG Reserved7[1]; // - AT91_REG PIOA_IFER; // Input Filter Enable Register - AT91_REG PIOA_IFDR; // Input Filter Disable Register - AT91_REG PIOA_IFSR; // Input Filter Status Register - AT91_REG Reserved8[1]; // - AT91_REG PIOA_SODR; // Set Output Data Register - AT91_REG PIOA_CODR; // Clear Output Data Register - AT91_REG PIOA_ODSR; // Output Data Status Register - AT91_REG PIOA_PDSR; // Pin Data Status Register - AT91_REG PIOA_IER; // Interrupt Enable Register - AT91_REG PIOA_IDR; // Interrupt Disable Register - AT91_REG PIOA_IMR; // Interrupt Mask Register - AT91_REG PIOA_ISR; // Interrupt Status Register - AT91_REG PIOA_MDER; // Multi-driver Enable Register - AT91_REG PIOA_MDDR; // Multi-driver Disable Register - AT91_REG PIOA_MDSR; // Multi-driver Status Register - AT91_REG Reserved9[1]; // - AT91_REG PIOA_PPUDR; // Pull-up Disable Register - AT91_REG PIOA_PPUER; // Pull-up Enable Register - AT91_REG PIOA_PPUSR; // Pull-up Status Register - AT91_REG Reserved10[1]; // - AT91_REG PIOA_ASR; // Select A Register - AT91_REG PIOA_BSR; // Select B Register - AT91_REG PIOA_ABSR; // AB Select Status Register - AT91_REG Reserved11[9]; // - AT91_REG PIOA_OWER; // Output Write Enable Register - AT91_REG PIOA_OWDR; // Output Write Disable Register - AT91_REG PIOA_OWSR; // Output Write Status Register - AT91_REG Reserved12[469]; // - AT91_REG PMC_SCER; // System Clock Enable Register - AT91_REG PMC_SCDR; // System Clock Disable Register - AT91_REG PMC_SCSR; // System Clock Status Register - AT91_REG Reserved13[1]; // - AT91_REG PMC_PCER; // Peripheral Clock Enable Register - AT91_REG PMC_PCDR; // Peripheral Clock Disable Register - AT91_REG PMC_PCSR; // Peripheral Clock Status Register - AT91_REG Reserved14[1]; // - AT91_REG PMC_MOR; // Main Oscillator Register - AT91_REG PMC_MCFR; // Main Clock Frequency Register - AT91_REG Reserved15[1]; // - AT91_REG PMC_PLLR; // PLL Register - AT91_REG PMC_MCKR; // Master Clock Register - AT91_REG Reserved16[3]; // - AT91_REG PMC_PCKR[3]; // Programmable Clock Register - AT91_REG Reserved17[5]; // - AT91_REG PMC_IER; // Interrupt Enable Register - AT91_REG PMC_IDR; // Interrupt Disable Register - AT91_REG PMC_SR; // Status Register - AT91_REG PMC_IMR; // Interrupt Mask Register - AT91_REG Reserved18[36]; // - AT91_REG RSTC_RCR; // Reset Control Register - AT91_REG RSTC_RSR; // Reset Status Register - AT91_REG RSTC_RMR; // Reset Mode Register - AT91_REG Reserved19[5]; // - AT91_REG RTTC_RTMR; // Real-time Mode Register - AT91_REG RTTC_RTAR; // Real-time Alarm Register - AT91_REG RTTC_RTVR; // Real-time Value Register - AT91_REG RTTC_RTSR; // Real-time Status Register - AT91_REG PITC_PIMR; // Period Interval Mode Register - AT91_REG PITC_PISR; // Period Interval Status Register - AT91_REG PITC_PIVR; // Period Interval Value Register - AT91_REG PITC_PIIR; // Period Interval Image Register - AT91_REG WDTC_WDCR; // Watchdog Control Register - AT91_REG WDTC_WDMR; // Watchdog Mode Register - AT91_REG WDTC_WDSR; // Watchdog Status Register - AT91_REG Reserved20[5]; // - AT91_REG VREG_MR; // Voltage Regulator Mode Register + AT91_REG AIC_SMR[32]; // Source Mode Register + AT91_REG AIC_SVR[32]; // Source Vector Register + AT91_REG AIC_IVR; // IRQ Vector Register + AT91_REG AIC_FVR; // FIQ Vector Register + AT91_REG AIC_ISR; // Interrupt Status Register + AT91_REG AIC_IPR; // Interrupt Pending Register + AT91_REG AIC_IMR; // Interrupt Mask Register + AT91_REG AIC_CISR; // Core Interrupt Status Register + AT91_REG Reserved0[2]; // + AT91_REG AIC_IECR; // Interrupt Enable Command Register + AT91_REG AIC_IDCR; // Interrupt Disable Command Register + AT91_REG AIC_ICCR; // Interrupt Clear Command Register + AT91_REG AIC_ISCR; // Interrupt Set Command Register + AT91_REG AIC_EOICR; // End of Interrupt Command Register + AT91_REG AIC_SPU; // Spurious Vector Register + AT91_REG AIC_DCR; // Debug Control Register (Protect) + AT91_REG Reserved1[1]; // + AT91_REG AIC_FFER; // Fast Forcing Enable Register + AT91_REG AIC_FFDR; // Fast Forcing Disable Register + AT91_REG AIC_FFSR; // Fast Forcing Status Register + AT91_REG Reserved2[45]; // + AT91_REG DBGU_CR; // Control Register + AT91_REG DBGU_MR; // Mode Register + AT91_REG DBGU_IER; // Interrupt Enable Register + AT91_REG DBGU_IDR; // Interrupt Disable Register + AT91_REG DBGU_IMR; // Interrupt Mask Register + AT91_REG DBGU_CSR; // Channel Status Register + AT91_REG DBGU_RHR; // Receiver Holding Register + AT91_REG DBGU_THR; // Transmitter Holding Register + AT91_REG DBGU_BRGR; // Baud Rate Generator Register + AT91_REG Reserved3[7]; // + AT91_REG DBGU_CIDR; // Chip ID Register + AT91_REG DBGU_EXID; // Chip ID Extension Register + AT91_REG DBGU_FNTR; // Force NTRST Register + AT91_REG Reserved4[45]; // + AT91_REG DBGU_RPR; // Receive Pointer Register + AT91_REG DBGU_RCR; // Receive Counter Register + AT91_REG DBGU_TPR; // Transmit Pointer Register + AT91_REG DBGU_TCR; // Transmit Counter Register + AT91_REG DBGU_RNPR; // Receive Next Pointer Register + AT91_REG DBGU_RNCR; // Receive Next Counter Register + AT91_REG DBGU_TNPR; // Transmit Next Pointer Register + AT91_REG DBGU_TNCR; // Transmit Next Counter Register + AT91_REG DBGU_PTCR; // PDC Transfer Control Register + AT91_REG DBGU_PTSR; // PDC Transfer Status Register + AT91_REG Reserved5[54]; // + AT91_REG PIOA_PER; // PIO Enable Register + AT91_REG PIOA_PDR; // PIO Disable Register + AT91_REG PIOA_PSR; // PIO Status Register + AT91_REG Reserved6[1]; // + AT91_REG PIOA_OER; // Output Enable Register + AT91_REG PIOA_ODR; // Output Disable Registerr + AT91_REG PIOA_OSR; // Output Status Register + AT91_REG Reserved7[1]; // + AT91_REG PIOA_IFER; // Input Filter Enable Register + AT91_REG PIOA_IFDR; // Input Filter Disable Register + AT91_REG PIOA_IFSR; // Input Filter Status Register + AT91_REG Reserved8[1]; // + AT91_REG PIOA_SODR; // Set Output Data Register + AT91_REG PIOA_CODR; // Clear Output Data Register + AT91_REG PIOA_ODSR; // Output Data Status Register + AT91_REG PIOA_PDSR; // Pin Data Status Register + AT91_REG PIOA_IER; // Interrupt Enable Register + AT91_REG PIOA_IDR; // Interrupt Disable Register + AT91_REG PIOA_IMR; // Interrupt Mask Register + AT91_REG PIOA_ISR; // Interrupt Status Register + AT91_REG PIOA_MDER; // Multi-driver Enable Register + AT91_REG PIOA_MDDR; // Multi-driver Disable Register + AT91_REG PIOA_MDSR; // Multi-driver Status Register + AT91_REG Reserved9[1]; // + AT91_REG PIOA_PPUDR; // Pull-up Disable Register + AT91_REG PIOA_PPUER; // Pull-up Enable Register + AT91_REG PIOA_PPUSR; // Pull-up Status Register + AT91_REG Reserved10[1]; // + AT91_REG PIOA_ASR; // Select A Register + AT91_REG PIOA_BSR; // Select B Register + AT91_REG PIOA_ABSR; // AB Select Status Register + AT91_REG Reserved11[9]; // + AT91_REG PIOA_OWER; // Output Write Enable Register + AT91_REG PIOA_OWDR; // Output Write Disable Register + AT91_REG PIOA_OWSR; // Output Write Status Register + AT91_REG Reserved12[469]; // + AT91_REG PMC_SCER; // System Clock Enable Register + AT91_REG PMC_SCDR; // System Clock Disable Register + AT91_REG PMC_SCSR; // System Clock Status Register + AT91_REG Reserved13[1]; // + AT91_REG PMC_PCER; // Peripheral Clock Enable Register + AT91_REG PMC_PCDR; // Peripheral Clock Disable Register + AT91_REG PMC_PCSR; // Peripheral Clock Status Register + AT91_REG Reserved14[1]; // + AT91_REG PMC_MOR; // Main Oscillator Register + AT91_REG PMC_MCFR; // Main Clock Frequency Register + AT91_REG Reserved15[1]; // + AT91_REG PMC_PLLR; // PLL Register + AT91_REG PMC_MCKR; // Master Clock Register + AT91_REG Reserved16[3]; // + AT91_REG PMC_PCKR[3]; // Programmable Clock Register + AT91_REG Reserved17[5]; // + AT91_REG PMC_IER; // Interrupt Enable Register + AT91_REG PMC_IDR; // Interrupt Disable Register + AT91_REG PMC_SR; // Status Register + AT91_REG PMC_IMR; // Interrupt Mask Register + AT91_REG Reserved18[36]; // + AT91_REG RSTC_RCR; // Reset Control Register + AT91_REG RSTC_RSR; // Reset Status Register + AT91_REG RSTC_RMR; // Reset Mode Register + AT91_REG Reserved19[5]; // + AT91_REG RTTC_RTMR; // Real-time Mode Register + AT91_REG RTTC_RTAR; // Real-time Alarm Register + AT91_REG RTTC_RTVR; // Real-time Value Register + AT91_REG RTTC_RTSR; // Real-time Status Register + AT91_REG PITC_PIMR; // Period Interval Mode Register + AT91_REG PITC_PISR; // Period Interval Status Register + AT91_REG PITC_PIVR; // Period Interval Value Register + AT91_REG PITC_PIIR; // Period Interval Image Register + AT91_REG WDTC_WDCR; // Watchdog Control Register + AT91_REG WDTC_WDMR; // Watchdog Mode Register + AT91_REG WDTC_WDSR; // Watchdog Status Register + AT91_REG Reserved20[5]; // + AT91_REG VREG_MR; // Voltage Regulator Mode Register } AT91S_SYS, *AT91PS_SYS; #else @@ -201,26 +201,26 @@ typedef struct _AT91S_SYS { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_AIC { - AT91_REG AIC_SMR[32]; // Source Mode Register - AT91_REG AIC_SVR[32]; // Source Vector Register - AT91_REG AIC_IVR; // IRQ Vector Register - AT91_REG AIC_FVR; // FIQ Vector Register - AT91_REG AIC_ISR; // Interrupt Status Register - AT91_REG AIC_IPR; // Interrupt Pending Register - AT91_REG AIC_IMR; // Interrupt Mask Register - AT91_REG AIC_CISR; // Core Interrupt Status Register - AT91_REG Reserved0[2]; // - AT91_REG AIC_IECR; // Interrupt Enable Command Register - AT91_REG AIC_IDCR; // Interrupt Disable Command Register - AT91_REG AIC_ICCR; // Interrupt Clear Command Register - AT91_REG AIC_ISCR; // Interrupt Set Command Register - AT91_REG AIC_EOICR; // End of Interrupt Command Register - AT91_REG AIC_SPU; // Spurious Vector Register - AT91_REG AIC_DCR; // Debug Control Register (Protect) - AT91_REG Reserved1[1]; // - AT91_REG AIC_FFER; // Fast Forcing Enable Register - AT91_REG AIC_FFDR; // Fast Forcing Disable Register - AT91_REG AIC_FFSR; // Fast Forcing Status Register + AT91_REG AIC_SMR[32]; // Source Mode Register + AT91_REG AIC_SVR[32]; // Source Vector Register + AT91_REG AIC_IVR; // IRQ Vector Register + AT91_REG AIC_FVR; // FIQ Vector Register + AT91_REG AIC_ISR; // Interrupt Status Register + AT91_REG AIC_IPR; // Interrupt Pending Register + AT91_REG AIC_IMR; // Interrupt Mask Register + AT91_REG AIC_CISR; // Core Interrupt Status Register + AT91_REG Reserved0[2]; // + AT91_REG AIC_IECR; // Interrupt Enable Command Register + AT91_REG AIC_IDCR; // Interrupt Disable Command Register + AT91_REG AIC_ICCR; // Interrupt Clear Command Register + AT91_REG AIC_ISCR; // Interrupt Set Command Register + AT91_REG AIC_EOICR; // End of Interrupt Command Register + AT91_REG AIC_SPU; // Spurious Vector Register + AT91_REG AIC_DCR; // Debug Control Register (Protect) + AT91_REG Reserved1[1]; // + AT91_REG AIC_FFER; // Fast Forcing Enable Register + AT91_REG AIC_FFDR; // Fast Forcing Disable Register + AT91_REG AIC_FFSR; // Fast Forcing Status Register } AT91S_AIC, *AT91PS_AIC; #else #define AIC_SMR (AT91_CAST(AT91_REG *) 0x00000000) // (AIC_SMR) Source Mode Register @@ -266,16 +266,16 @@ typedef struct _AT91S_AIC { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_PDC { - AT91_REG PDC_RPR; // Receive Pointer Register - AT91_REG PDC_RCR; // Receive Counter Register - AT91_REG PDC_TPR; // Transmit Pointer Register - AT91_REG PDC_TCR; // Transmit Counter Register - AT91_REG PDC_RNPR; // Receive Next Pointer Register - AT91_REG PDC_RNCR; // Receive Next Counter Register - AT91_REG PDC_TNPR; // Transmit Next Pointer Register - AT91_REG PDC_TNCR; // Transmit Next Counter Register - AT91_REG PDC_PTCR; // PDC Transfer Control Register - AT91_REG PDC_PTSR; // PDC Transfer Status Register + AT91_REG PDC_RPR; // Receive Pointer Register + AT91_REG PDC_RCR; // Receive Counter Register + AT91_REG PDC_TPR; // Transmit Pointer Register + AT91_REG PDC_TCR; // Transmit Counter Register + AT91_REG PDC_RNPR; // Receive Next Pointer Register + AT91_REG PDC_RNCR; // Receive Next Counter Register + AT91_REG PDC_TNPR; // Transmit Next Pointer Register + AT91_REG PDC_TNCR; // Transmit Next Counter Register + AT91_REG PDC_PTCR; // PDC Transfer Control Register + AT91_REG PDC_PTSR; // PDC Transfer Status Register } AT91S_PDC, *AT91PS_PDC; #else #define PDC_RPR (AT91_CAST(AT91_REG *) 0x00000000) // (PDC_RPR) Receive Pointer Register @@ -302,30 +302,30 @@ typedef struct _AT91S_PDC { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_DBGU { - AT91_REG DBGU_CR; // Control Register - AT91_REG DBGU_MR; // Mode Register - AT91_REG DBGU_IER; // Interrupt Enable Register - AT91_REG DBGU_IDR; // Interrupt Disable Register - AT91_REG DBGU_IMR; // Interrupt Mask Register - AT91_REG DBGU_CSR; // Channel Status Register - AT91_REG DBGU_RHR; // Receiver Holding Register - AT91_REG DBGU_THR; // Transmitter Holding Register - AT91_REG DBGU_BRGR; // Baud Rate Generator Register - AT91_REG Reserved0[7]; // - AT91_REG DBGU_CIDR; // Chip ID Register - AT91_REG DBGU_EXID; // Chip ID Extension Register - AT91_REG DBGU_FNTR; // Force NTRST Register - AT91_REG Reserved1[45]; // - AT91_REG DBGU_RPR; // Receive Pointer Register - AT91_REG DBGU_RCR; // Receive Counter Register - AT91_REG DBGU_TPR; // Transmit Pointer Register - AT91_REG DBGU_TCR; // Transmit Counter Register - AT91_REG DBGU_RNPR; // Receive Next Pointer Register - AT91_REG DBGU_RNCR; // Receive Next Counter Register - AT91_REG DBGU_TNPR; // Transmit Next Pointer Register - AT91_REG DBGU_TNCR; // Transmit Next Counter Register - AT91_REG DBGU_PTCR; // PDC Transfer Control Register - AT91_REG DBGU_PTSR; // PDC Transfer Status Register + AT91_REG DBGU_CR; // Control Register + AT91_REG DBGU_MR; // Mode Register + AT91_REG DBGU_IER; // Interrupt Enable Register + AT91_REG DBGU_IDR; // Interrupt Disable Register + AT91_REG DBGU_IMR; // Interrupt Mask Register + AT91_REG DBGU_CSR; // Channel Status Register + AT91_REG DBGU_RHR; // Receiver Holding Register + AT91_REG DBGU_THR; // Transmitter Holding Register + AT91_REG DBGU_BRGR; // Baud Rate Generator Register + AT91_REG Reserved0[7]; // + AT91_REG DBGU_CIDR; // Chip ID Register + AT91_REG DBGU_EXID; // Chip ID Extension Register + AT91_REG DBGU_FNTR; // Force NTRST Register + AT91_REG Reserved1[45]; // + AT91_REG DBGU_RPR; // Receive Pointer Register + AT91_REG DBGU_RCR; // Receive Counter Register + AT91_REG DBGU_TPR; // Transmit Pointer Register + AT91_REG DBGU_TCR; // Transmit Counter Register + AT91_REG DBGU_RNPR; // Receive Next Pointer Register + AT91_REG DBGU_RNCR; // Receive Next Counter Register + AT91_REG DBGU_TNPR; // Transmit Next Pointer Register + AT91_REG DBGU_TNCR; // Transmit Next Counter Register + AT91_REG DBGU_PTCR; // PDC Transfer Control Register + AT91_REG DBGU_PTSR; // PDC Transfer Status Register } AT91S_DBGU, *AT91PS_DBGU; #else #define DBGU_CR (AT91_CAST(AT91_REG *) 0x00000000) // (DBGU_CR) Control Register @@ -387,41 +387,41 @@ typedef struct _AT91S_DBGU { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_PIO { - AT91_REG PIO_PER; // PIO Enable Register - AT91_REG PIO_PDR; // PIO Disable Register - AT91_REG PIO_PSR; // PIO Status Register - AT91_REG Reserved0[1]; // - AT91_REG PIO_OER; // Output Enable Register - AT91_REG PIO_ODR; // Output Disable Registerr - AT91_REG PIO_OSR; // Output Status Register - AT91_REG Reserved1[1]; // - AT91_REG PIO_IFER; // Input Filter Enable Register - AT91_REG PIO_IFDR; // Input Filter Disable Register - AT91_REG PIO_IFSR; // Input Filter Status Register - AT91_REG Reserved2[1]; // - AT91_REG PIO_SODR; // Set Output Data Register - AT91_REG PIO_CODR; // Clear Output Data Register - AT91_REG PIO_ODSR; // Output Data Status Register - AT91_REG PIO_PDSR; // Pin Data Status Register - AT91_REG PIO_IER; // Interrupt Enable Register - AT91_REG PIO_IDR; // Interrupt Disable Register - AT91_REG PIO_IMR; // Interrupt Mask Register - AT91_REG PIO_ISR; // Interrupt Status Register - AT91_REG PIO_MDER; // Multi-driver Enable Register - AT91_REG PIO_MDDR; // Multi-driver Disable Register - AT91_REG PIO_MDSR; // Multi-driver Status Register - AT91_REG Reserved3[1]; // - AT91_REG PIO_PPUDR; // Pull-up Disable Register - AT91_REG PIO_PPUER; // Pull-up Enable Register - AT91_REG PIO_PPUSR; // Pull-up Status Register - AT91_REG Reserved4[1]; // - AT91_REG PIO_ASR; // Select A Register - AT91_REG PIO_BSR; // Select B Register - AT91_REG PIO_ABSR; // AB Select Status Register - AT91_REG Reserved5[9]; // - AT91_REG PIO_OWER; // Output Write Enable Register - AT91_REG PIO_OWDR; // Output Write Disable Register - AT91_REG PIO_OWSR; // Output Write Status Register + AT91_REG PIO_PER; // PIO Enable Register + AT91_REG PIO_PDR; // PIO Disable Register + AT91_REG PIO_PSR; // PIO Status Register + AT91_REG Reserved0[1]; // + AT91_REG PIO_OER; // Output Enable Register + AT91_REG PIO_ODR; // Output Disable Registerr + AT91_REG PIO_OSR; // Output Status Register + AT91_REG Reserved1[1]; // + AT91_REG PIO_IFER; // Input Filter Enable Register + AT91_REG PIO_IFDR; // Input Filter Disable Register + AT91_REG PIO_IFSR; // Input Filter Status Register + AT91_REG Reserved2[1]; // + AT91_REG PIO_SODR; // Set Output Data Register + AT91_REG PIO_CODR; // Clear Output Data Register + AT91_REG PIO_ODSR; // Output Data Status Register + AT91_REG PIO_PDSR; // Pin Data Status Register + AT91_REG PIO_IER; // Interrupt Enable Register + AT91_REG PIO_IDR; // Interrupt Disable Register + AT91_REG PIO_IMR; // Interrupt Mask Register + AT91_REG PIO_ISR; // Interrupt Status Register + AT91_REG PIO_MDER; // Multi-driver Enable Register + AT91_REG PIO_MDDR; // Multi-driver Disable Register + AT91_REG PIO_MDSR; // Multi-driver Status Register + AT91_REG Reserved3[1]; // + AT91_REG PIO_PPUDR; // Pull-up Disable Register + AT91_REG PIO_PPUER; // Pull-up Enable Register + AT91_REG PIO_PPUSR; // Pull-up Status Register + AT91_REG Reserved4[1]; // + AT91_REG PIO_ASR; // Select A Register + AT91_REG PIO_BSR; // Select B Register + AT91_REG PIO_ABSR; // AB Select Status Register + AT91_REG Reserved5[9]; // + AT91_REG PIO_OWER; // Output Write Enable Register + AT91_REG PIO_OWDR; // Output Write Disable Register + AT91_REG PIO_OWSR; // Output Write Status Register } AT91S_PIO, *AT91PS_PIO; #else #define PIO_PER (AT91_CAST(AT91_REG *) 0x00000000) // (PIO_PER) PIO Enable Register @@ -461,10 +461,10 @@ typedef struct _AT91S_PIO { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_CKGR { - AT91_REG CKGR_MOR; // Main Oscillator Register - AT91_REG CKGR_MCFR; // Main Clock Frequency Register - AT91_REG Reserved0[1]; // - AT91_REG CKGR_PLLR; // PLL Register + AT91_REG CKGR_MOR; // Main Oscillator Register + AT91_REG CKGR_MCFR; // Main Clock Frequency Register + AT91_REG Reserved0[1]; // + AT91_REG CKGR_PLLR; // PLL Register } AT91S_CKGR, *AT91PS_CKGR; #else #define CKGR_MOR (AT91_CAST(AT91_REG *) 0x00000000) // (CKGR_MOR) Main Oscillator Register @@ -500,26 +500,26 @@ typedef struct _AT91S_CKGR { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_PMC { - AT91_REG PMC_SCER; // System Clock Enable Register - AT91_REG PMC_SCDR; // System Clock Disable Register - AT91_REG PMC_SCSR; // System Clock Status Register - AT91_REG Reserved0[1]; // - AT91_REG PMC_PCER; // Peripheral Clock Enable Register - AT91_REG PMC_PCDR; // Peripheral Clock Disable Register - AT91_REG PMC_PCSR; // Peripheral Clock Status Register - AT91_REG Reserved1[1]; // - AT91_REG PMC_MOR; // Main Oscillator Register - AT91_REG PMC_MCFR; // Main Clock Frequency Register - AT91_REG Reserved2[1]; // - AT91_REG PMC_PLLR; // PLL Register - AT91_REG PMC_MCKR; // Master Clock Register - AT91_REG Reserved3[3]; // - AT91_REG PMC_PCKR[3]; // Programmable Clock Register - AT91_REG Reserved4[5]; // - AT91_REG PMC_IER; // Interrupt Enable Register - AT91_REG PMC_IDR; // Interrupt Disable Register - AT91_REG PMC_SR; // Status Register - AT91_REG PMC_IMR; // Interrupt Mask Register + AT91_REG PMC_SCER; // System Clock Enable Register + AT91_REG PMC_SCDR; // System Clock Disable Register + AT91_REG PMC_SCSR; // System Clock Status Register + AT91_REG Reserved0[1]; // + AT91_REG PMC_PCER; // Peripheral Clock Enable Register + AT91_REG PMC_PCDR; // Peripheral Clock Disable Register + AT91_REG PMC_PCSR; // Peripheral Clock Status Register + AT91_REG Reserved1[1]; // + AT91_REG PMC_MOR; // Main Oscillator Register + AT91_REG PMC_MCFR; // Main Clock Frequency Register + AT91_REG Reserved2[1]; // + AT91_REG PMC_PLLR; // PLL Register + AT91_REG PMC_MCKR; // Master Clock Register + AT91_REG Reserved3[3]; // + AT91_REG PMC_PCKR[3]; // Programmable Clock Register + AT91_REG Reserved4[5]; // + AT91_REG PMC_IER; // Interrupt Enable Register + AT91_REG PMC_IDR; // Interrupt Disable Register + AT91_REG PMC_SR; // Status Register + AT91_REG PMC_IMR; // Interrupt Mask Register } AT91S_PMC, *AT91PS_PMC; #else #define PMC_SCER (AT91_CAST(AT91_REG *) 0x00000000) // (PMC_SCER) System Clock Enable Register @@ -577,9 +577,9 @@ typedef struct _AT91S_PMC { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_RSTC { - AT91_REG RSTC_RCR; // Reset Control Register - AT91_REG RSTC_RSR; // Reset Status Register - AT91_REG RSTC_RMR; // Reset Mode Register + AT91_REG RSTC_RCR; // Reset Control Register + AT91_REG RSTC_RSR; // Reset Status Register + AT91_REG RSTC_RMR; // Reset Mode Register } AT91S_RSTC, *AT91PS_RSTC; #else #define RSTC_RCR (AT91_CAST(AT91_REG *) 0x00000000) // (RSTC_RCR) Reset Control Register @@ -615,10 +615,10 @@ typedef struct _AT91S_RSTC { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_RTTC { - AT91_REG RTTC_RTMR; // Real-time Mode Register - AT91_REG RTTC_RTAR; // Real-time Alarm Register - AT91_REG RTTC_RTVR; // Real-time Value Register - AT91_REG RTTC_RTSR; // Real-time Status Register + AT91_REG RTTC_RTMR; // Real-time Mode Register + AT91_REG RTTC_RTAR; // Real-time Alarm Register + AT91_REG RTTC_RTVR; // Real-time Value Register + AT91_REG RTTC_RTSR; // Real-time Status Register } AT91S_RTTC, *AT91PS_RTTC; #else #define RTTC_RTMR (AT91_CAST(AT91_REG *) 0x00000000) // (RTTC_RTMR) Real-time Mode Register @@ -645,10 +645,10 @@ typedef struct _AT91S_RTTC { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_PITC { - AT91_REG PITC_PIMR; // Period Interval Mode Register - AT91_REG PITC_PISR; // Period Interval Status Register - AT91_REG PITC_PIVR; // Period Interval Value Register - AT91_REG PITC_PIIR; // Period Interval Image Register + AT91_REG PITC_PIMR; // Period Interval Mode Register + AT91_REG PITC_PISR; // Period Interval Status Register + AT91_REG PITC_PIVR; // Period Interval Value Register + AT91_REG PITC_PIIR; // Period Interval Image Register } AT91S_PITC, *AT91PS_PITC; #else #define PITC_PIMR (AT91_CAST(AT91_REG *) 0x00000000) // (PITC_PIMR) Period Interval Mode Register @@ -673,9 +673,9 @@ typedef struct _AT91S_PITC { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_WDTC { - AT91_REG WDTC_WDCR; // Watchdog Control Register - AT91_REG WDTC_WDMR; // Watchdog Mode Register - AT91_REG WDTC_WDSR; // Watchdog Status Register + AT91_REG WDTC_WDCR; // Watchdog Control Register + AT91_REG WDTC_WDMR; // Watchdog Mode Register + AT91_REG WDTC_WDSR; // Watchdog Status Register } AT91S_WDTC, *AT91PS_WDTC; #else #define WDTC_WDCR (AT91_CAST(AT91_REG *) 0x00000000) // (WDTC_WDCR) Watchdog Control Register @@ -704,7 +704,7 @@ typedef struct _AT91S_WDTC { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_VREG { - AT91_REG VREG_MR; // Voltage Regulator Mode Register + AT91_REG VREG_MR; // Voltage Regulator Mode Register } AT91S_VREG, *AT91PS_VREG; #else #define VREG_MR (AT91_CAST(AT91_REG *) 0x00000000) // (VREG_MR) Voltage Regulator Mode Register @@ -718,10 +718,10 @@ typedef struct _AT91S_VREG { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_EFC { - AT91_REG EFC_FMR; // MC Flash Mode Register - AT91_REG EFC_FCR; // MC Flash Command Register - AT91_REG EFC_FSR; // MC Flash Status Register - AT91_REG EFC_VR; // MC Flash Version Register + AT91_REG EFC_FMR; // MC Flash Mode Register + AT91_REG EFC_FCR; // MC Flash Command Register + AT91_REG EFC_FSR; // MC Flash Status Register + AT91_REG EFC_VR; // MC Flash Version Register } AT91S_EFC, *AT91PS_EFC; #else #define MC_FMR (AT91_CAST(AT91_REG *) 0x00000000) // (MC_FMR) MC Flash Mode Register @@ -788,22 +788,22 @@ typedef struct _AT91S_EFC { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_MC { - AT91_REG MC_RCR; // MC Remap Control Register - AT91_REG MC_ASR; // MC Abort Status Register - AT91_REG MC_AASR; // MC Abort Address Status Register - AT91_REG Reserved0[1]; // - AT91_REG MC_PUIA[16]; // MC Protection Unit Area - AT91_REG MC_PUP; // MC Protection Unit Peripherals - AT91_REG MC_PUER; // MC Protection Unit Enable Register - AT91_REG Reserved1[2]; // - AT91_REG MC0_FMR; // MC Flash Mode Register - AT91_REG MC0_FCR; // MC Flash Command Register - AT91_REG MC0_FSR; // MC Flash Status Register - AT91_REG MC0_VR; // MC Flash Version Register - AT91_REG MC1_FMR; // MC Flash Mode Register - AT91_REG MC1_FCR; // MC Flash Command Register - AT91_REG MC1_FSR; // MC Flash Status Register - AT91_REG MC1_VR; // MC Flash Version Register + AT91_REG MC_RCR; // MC Remap Control Register + AT91_REG MC_ASR; // MC Abort Status Register + AT91_REG MC_AASR; // MC Abort Address Status Register + AT91_REG Reserved0[1]; // + AT91_REG MC_PUIA[16]; // MC Protection Unit Area + AT91_REG MC_PUP; // MC Protection Unit Peripherals + AT91_REG MC_PUER; // MC Protection Unit Enable Register + AT91_REG Reserved1[2]; // + AT91_REG MC0_FMR; // MC Flash Mode Register + AT91_REG MC0_FCR; // MC Flash Command Register + AT91_REG MC0_FSR; // MC Flash Status Register + AT91_REG MC0_VR; // MC Flash Version Register + AT91_REG MC1_FMR; // MC Flash Mode Register + AT91_REG MC1_FCR; // MC Flash Command Register + AT91_REG MC1_FSR; // MC Flash Status Register + AT91_REG MC1_VR; // MC Flash Version Register } AT91S_MC, *AT91PS_MC; #else #define MC_RCR (AT91_CAST(AT91_REG *) 0x00000000) // (MC_RCR) MC Remap Control Register @@ -865,27 +865,27 @@ typedef struct _AT91S_MC { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_SPI { - AT91_REG SPI_CR; // Control Register - AT91_REG SPI_MR; // Mode Register - AT91_REG SPI_RDR; // Receive Data Register - AT91_REG SPI_TDR; // Transmit Data Register - AT91_REG SPI_SR; // Status Register - AT91_REG SPI_IER; // Interrupt Enable Register - AT91_REG SPI_IDR; // Interrupt Disable Register - AT91_REG SPI_IMR; // Interrupt Mask Register - AT91_REG Reserved0[4]; // - AT91_REG SPI_CSR[4]; // Chip Select Register - AT91_REG Reserved1[48]; // - AT91_REG SPI_RPR; // Receive Pointer Register - AT91_REG SPI_RCR; // Receive Counter Register - AT91_REG SPI_TPR; // Transmit Pointer Register - AT91_REG SPI_TCR; // Transmit Counter Register - AT91_REG SPI_RNPR; // Receive Next Pointer Register - AT91_REG SPI_RNCR; // Receive Next Counter Register - AT91_REG SPI_TNPR; // Transmit Next Pointer Register - AT91_REG SPI_TNCR; // Transmit Next Counter Register - AT91_REG SPI_PTCR; // PDC Transfer Control Register - AT91_REG SPI_PTSR; // PDC Transfer Status Register + AT91_REG SPI_CR; // Control Register + AT91_REG SPI_MR; // Mode Register + AT91_REG SPI_RDR; // Receive Data Register + AT91_REG SPI_TDR; // Transmit Data Register + AT91_REG SPI_SR; // Status Register + AT91_REG SPI_IER; // Interrupt Enable Register + AT91_REG SPI_IDR; // Interrupt Disable Register + AT91_REG SPI_IMR; // Interrupt Mask Register + AT91_REG Reserved0[4]; // + AT91_REG SPI_CSR[4]; // Chip Select Register + AT91_REG Reserved1[48]; // + AT91_REG SPI_RPR; // Receive Pointer Register + AT91_REG SPI_RCR; // Receive Counter Register + AT91_REG SPI_TPR; // Transmit Pointer Register + AT91_REG SPI_TCR; // Transmit Counter Register + AT91_REG SPI_RNPR; // Receive Next Pointer Register + AT91_REG SPI_RNCR; // Receive Next Counter Register + AT91_REG SPI_TNPR; // Transmit Next Pointer Register + AT91_REG SPI_TNCR; // Transmit Next Counter Register + AT91_REG SPI_PTCR; // PDC Transfer Control Register + AT91_REG SPI_PTSR; // PDC Transfer Status Register } AT91S_SPI, *AT91PS_SPI; #else #define SPI_CR (AT91_CAST(AT91_REG *) 0x00000000) // (SPI_CR) Control Register @@ -959,29 +959,29 @@ typedef struct _AT91S_SPI { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_ADC { - AT91_REG ADC_CR; // ADC Control Register - AT91_REG ADC_MR; // ADC Mode Register - AT91_REG Reserved0[2]; // - AT91_REG ADC_CHER; // ADC Channel Enable Register - AT91_REG ADC_CHDR; // ADC Channel Disable Register - AT91_REG ADC_CHSR; // ADC Channel Status Register - AT91_REG ADC_SR; // ADC Status Register - AT91_REG ADC_LCDR; // ADC Last Converted Data Register - AT91_REG ADC_IER; // ADC Interrupt Enable Register - AT91_REG ADC_IDR; // ADC Interrupt Disable Register - AT91_REG ADC_IMR; // ADC Interrupt Mask Register - AT91_REG ADC_CDR[8]; // ADC Channel Data Register - AT91_REG Reserved1[44]; // - AT91_REG ADC_RPR; // Receive Pointer Register - AT91_REG ADC_RCR; // Receive Counter Register - AT91_REG ADC_TPR; // Transmit Pointer Register - AT91_REG ADC_TCR; // Transmit Counter Register - AT91_REG ADC_RNPR; // Receive Next Pointer Register - AT91_REG ADC_RNCR; // Receive Next Counter Register - AT91_REG ADC_TNPR; // Transmit Next Pointer Register - AT91_REG ADC_TNCR; // Transmit Next Counter Register - AT91_REG ADC_PTCR; // PDC Transfer Control Register - AT91_REG ADC_PTSR; // PDC Transfer Status Register + AT91_REG ADC_CR; // ADC Control Register + AT91_REG ADC_MR; // ADC Mode Register + AT91_REG Reserved0[2]; // + AT91_REG ADC_CHER; // ADC Channel Enable Register + AT91_REG ADC_CHDR; // ADC Channel Disable Register + AT91_REG ADC_CHSR; // ADC Channel Status Register + AT91_REG ADC_SR; // ADC Status Register + AT91_REG ADC_LCDR; // ADC Last Converted Data Register + AT91_REG ADC_IER; // ADC Interrupt Enable Register + AT91_REG ADC_IDR; // ADC Interrupt Disable Register + AT91_REG ADC_IMR; // ADC Interrupt Mask Register + AT91_REG ADC_CDR[8]; // ADC Channel Data Register + AT91_REG Reserved1[44]; // + AT91_REG ADC_RPR; // Receive Pointer Register + AT91_REG ADC_RCR; // Receive Counter Register + AT91_REG ADC_TPR; // Transmit Pointer Register + AT91_REG ADC_TCR; // Transmit Counter Register + AT91_REG ADC_RNPR; // Receive Next Pointer Register + AT91_REG ADC_RNCR; // Receive Next Counter Register + AT91_REG ADC_TNPR; // Transmit Next Pointer Register + AT91_REG ADC_TNCR; // Transmit Next Counter Register + AT91_REG ADC_PTCR; // PDC Transfer Control Register + AT91_REG ADC_PTSR; // PDC Transfer Status Register } AT91S_ADC, *AT91PS_ADC; #else #define ADC_CR (AT91_CAST(AT91_REG *) 0x00000000) // (ADC_CR) ADC Control Register @@ -1080,34 +1080,34 @@ typedef struct _AT91S_ADC { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_SSC { - AT91_REG SSC_CR; // Control Register - AT91_REG SSC_CMR; // Clock Mode Register - AT91_REG Reserved0[2]; // - AT91_REG SSC_RCMR; // Receive Clock ModeRegister - AT91_REG SSC_RFMR; // Receive Frame Mode Register - AT91_REG SSC_TCMR; // Transmit Clock Mode Register - AT91_REG SSC_TFMR; // Transmit Frame Mode Register - AT91_REG SSC_RHR; // Receive Holding Register - AT91_REG SSC_THR; // Transmit Holding Register - AT91_REG Reserved1[2]; // - AT91_REG SSC_RSHR; // Receive Sync Holding Register - AT91_REG SSC_TSHR; // Transmit Sync Holding Register - AT91_REG Reserved2[2]; // - AT91_REG SSC_SR; // Status Register - AT91_REG SSC_IER; // Interrupt Enable Register - AT91_REG SSC_IDR; // Interrupt Disable Register - AT91_REG SSC_IMR; // Interrupt Mask Register - AT91_REG Reserved3[44]; // - AT91_REG SSC_RPR; // Receive Pointer Register - AT91_REG SSC_RCR; // Receive Counter Register - AT91_REG SSC_TPR; // Transmit Pointer Register - AT91_REG SSC_TCR; // Transmit Counter Register - AT91_REG SSC_RNPR; // Receive Next Pointer Register - AT91_REG SSC_RNCR; // Receive Next Counter Register - AT91_REG SSC_TNPR; // Transmit Next Pointer Register - AT91_REG SSC_TNCR; // Transmit Next Counter Register - AT91_REG SSC_PTCR; // PDC Transfer Control Register - AT91_REG SSC_PTSR; // PDC Transfer Status Register + AT91_REG SSC_CR; // Control Register + AT91_REG SSC_CMR; // Clock Mode Register + AT91_REG Reserved0[2]; // + AT91_REG SSC_RCMR; // Receive Clock ModeRegister + AT91_REG SSC_RFMR; // Receive Frame Mode Register + AT91_REG SSC_TCMR; // Transmit Clock Mode Register + AT91_REG SSC_TFMR; // Transmit Frame Mode Register + AT91_REG SSC_RHR; // Receive Holding Register + AT91_REG SSC_THR; // Transmit Holding Register + AT91_REG Reserved1[2]; // + AT91_REG SSC_RSHR; // Receive Sync Holding Register + AT91_REG SSC_TSHR; // Transmit Sync Holding Register + AT91_REG Reserved2[2]; // + AT91_REG SSC_SR; // Status Register + AT91_REG SSC_IER; // Interrupt Enable Register + AT91_REG SSC_IDR; // Interrupt Disable Register + AT91_REG SSC_IMR; // Interrupt Mask Register + AT91_REG Reserved3[44]; // + AT91_REG SSC_RPR; // Receive Pointer Register + AT91_REG SSC_RCR; // Receive Counter Register + AT91_REG SSC_TPR; // Transmit Pointer Register + AT91_REG SSC_TCR; // Transmit Counter Register + AT91_REG SSC_RNPR; // Receive Next Pointer Register + AT91_REG SSC_RNCR; // Receive Next Counter Register + AT91_REG SSC_TNPR; // Transmit Next Pointer Register + AT91_REG SSC_TNCR; // Transmit Next Counter Register + AT91_REG SSC_PTCR; // PDC Transfer Control Register + AT91_REG SSC_PTSR; // PDC Transfer Status Register } AT91S_SSC, *AT91PS_SSC; #else #define SSC_CR (AT91_CAST(AT91_REG *) 0x00000000) // (SSC_CR) Control Register @@ -1194,33 +1194,33 @@ typedef struct _AT91S_SSC { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_USART { - AT91_REG US_CR; // Control Register - AT91_REG US_MR; // Mode Register - AT91_REG US_IER; // Interrupt Enable Register - AT91_REG US_IDR; // Interrupt Disable Register - AT91_REG US_IMR; // Interrupt Mask Register - AT91_REG US_CSR; // Channel Status Register - AT91_REG US_RHR; // Receiver Holding Register - AT91_REG US_THR; // Transmitter Holding Register - AT91_REG US_BRGR; // Baud Rate Generator Register - AT91_REG US_RTOR; // Receiver Time-out Register - AT91_REG US_TTGR; // Transmitter Time-guard Register - AT91_REG Reserved0[5]; // - AT91_REG US_FIDI; // FI_DI_Ratio Register - AT91_REG US_NER; // Nb Errors Register - AT91_REG Reserved1[1]; // - AT91_REG US_IF; // IRDA_FILTER Register - AT91_REG Reserved2[44]; // - AT91_REG US_RPR; // Receive Pointer Register - AT91_REG US_RCR; // Receive Counter Register - AT91_REG US_TPR; // Transmit Pointer Register - AT91_REG US_TCR; // Transmit Counter Register - AT91_REG US_RNPR; // Receive Next Pointer Register - AT91_REG US_RNCR; // Receive Next Counter Register - AT91_REG US_TNPR; // Transmit Next Pointer Register - AT91_REG US_TNCR; // Transmit Next Counter Register - AT91_REG US_PTCR; // PDC Transfer Control Register - AT91_REG US_PTSR; // PDC Transfer Status Register + AT91_REG US_CR; // Control Register + AT91_REG US_MR; // Mode Register + AT91_REG US_IER; // Interrupt Enable Register + AT91_REG US_IDR; // Interrupt Disable Register + AT91_REG US_IMR; // Interrupt Mask Register + AT91_REG US_CSR; // Channel Status Register + AT91_REG US_RHR; // Receiver Holding Register + AT91_REG US_THR; // Transmitter Holding Register + AT91_REG US_BRGR; // Baud Rate Generator Register + AT91_REG US_RTOR; // Receiver Time-out Register + AT91_REG US_TTGR; // Transmitter Time-guard Register + AT91_REG Reserved0[5]; // + AT91_REG US_FIDI; // FI_DI_Ratio Register + AT91_REG US_NER; // Nb Errors Register + AT91_REG Reserved1[1]; // + AT91_REG US_IF; // IRDA_FILTER Register + AT91_REG Reserved2[44]; // + AT91_REG US_RPR; // Receive Pointer Register + AT91_REG US_RCR; // Receive Counter Register + AT91_REG US_TPR; // Transmit Pointer Register + AT91_REG US_TCR; // Transmit Counter Register + AT91_REG US_RNPR; // Receive Next Pointer Register + AT91_REG US_RNCR; // Receive Next Counter Register + AT91_REG US_TNPR; // Transmit Next Pointer Register + AT91_REG US_TNCR; // Transmit Next Counter Register + AT91_REG US_PTCR; // PDC Transfer Control Register + AT91_REG US_PTSR; // PDC Transfer Status Register } AT91S_USART, *AT91PS_USART; #else #define US_CR (AT91_CAST(AT91_REG *) 0x00000000) // (US_CR) Control Register @@ -1306,29 +1306,29 @@ typedef struct _AT91S_USART { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_TWI { - AT91_REG TWI_CR; // Control Register - AT91_REG TWI_MMR; // Master Mode Register - AT91_REG Reserved0[1]; // - AT91_REG TWI_IADR; // Internal Address Register - AT91_REG TWI_CWGR; // Clock Waveform Generator Register - AT91_REG Reserved1[3]; // - AT91_REG TWI_SR; // Status Register - AT91_REG TWI_IER; // Interrupt Enable Register - AT91_REG TWI_IDR; // Interrupt Disable Register - AT91_REG TWI_IMR; // Interrupt Mask Register - AT91_REG TWI_RHR; // Receive Holding Register - AT91_REG TWI_THR; // Transmit Holding Register - AT91_REG Reserved2[50]; // - AT91_REG TWI_RPR; // Receive Pointer Register - AT91_REG TWI_RCR; // Receive Counter Register - AT91_REG TWI_TPR; // Transmit Pointer Register - AT91_REG TWI_TCR; // Transmit Counter Register - AT91_REG TWI_RNPR; // Receive Next Pointer Register - AT91_REG TWI_RNCR; // Receive Next Counter Register - AT91_REG TWI_TNPR; // Transmit Next Pointer Register - AT91_REG TWI_TNCR; // Transmit Next Counter Register - AT91_REG TWI_PTCR; // PDC Transfer Control Register - AT91_REG TWI_PTSR; // PDC Transfer Status Register + AT91_REG TWI_CR; // Control Register + AT91_REG TWI_MMR; // Master Mode Register + AT91_REG Reserved0[1]; // + AT91_REG TWI_IADR; // Internal Address Register + AT91_REG TWI_CWGR; // Clock Waveform Generator Register + AT91_REG Reserved1[3]; // + AT91_REG TWI_SR; // Status Register + AT91_REG TWI_IER; // Interrupt Enable Register + AT91_REG TWI_IDR; // Interrupt Disable Register + AT91_REG TWI_IMR; // Interrupt Mask Register + AT91_REG TWI_RHR; // Receive Holding Register + AT91_REG TWI_THR; // Transmit Holding Register + AT91_REG Reserved2[50]; // + AT91_REG TWI_RPR; // Receive Pointer Register + AT91_REG TWI_RCR; // Receive Counter Register + AT91_REG TWI_TPR; // Transmit Pointer Register + AT91_REG TWI_TCR; // Transmit Counter Register + AT91_REG TWI_RNPR; // Receive Next Pointer Register + AT91_REG TWI_RNCR; // Receive Next Counter Register + AT91_REG TWI_TNPR; // Transmit Next Pointer Register + AT91_REG TWI_TNCR; // Transmit Next Counter Register + AT91_REG TWI_PTCR; // PDC Transfer Control Register + AT91_REG TWI_PTSR; // PDC Transfer Status Register } AT91S_TWI, *AT91PS_TWI; #else #define TWI_CR (AT91_CAST(AT91_REG *) 0x00000000) // (TWI_CR) Control Register @@ -1381,17 +1381,17 @@ typedef struct _AT91S_TWI { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_TC { - AT91_REG TC_CCR; // Channel Control Register - AT91_REG TC_CMR; // Channel Mode Register (Capture Mode / Waveform Mode) - AT91_REG Reserved0[2]; // - AT91_REG TC_CV; // Counter Value - AT91_REG TC_RA; // Register A - AT91_REG TC_RB; // Register B - AT91_REG TC_RC; // Register C - AT91_REG TC_SR; // Status Register - AT91_REG TC_IER; // Interrupt Enable Register - AT91_REG TC_IDR; // Interrupt Disable Register - AT91_REG TC_IMR; // Interrupt Mask Register + AT91_REG TC_CCR; // Channel Control Register + AT91_REG TC_CMR; // Channel Mode Register (Capture Mode / Waveform Mode) + AT91_REG Reserved0[2]; // + AT91_REG TC_CV; // Counter Value + AT91_REG TC_RA; // Register A + AT91_REG TC_RB; // Register B + AT91_REG TC_RC; // Register C + AT91_REG TC_SR; // Status Register + AT91_REG TC_IER; // Interrupt Enable Register + AT91_REG TC_IDR; // Interrupt Disable Register + AT91_REG TC_IMR; // Interrupt Mask Register } AT91S_TC, *AT91PS_TC; #else #define TC_CCR (AT91_CAST(AT91_REG *) 0x00000000) // (TC_CCR) Channel Control Register @@ -1525,14 +1525,14 @@ typedef struct _AT91S_TC { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_TCB { - AT91S_TC TCB_TC0; // TC Channel 0 - AT91_REG Reserved0[4]; // - AT91S_TC TCB_TC1; // TC Channel 1 - AT91_REG Reserved1[4]; // - AT91S_TC TCB_TC2; // TC Channel 2 - AT91_REG Reserved2[4]; // - AT91_REG TCB_BCR; // TC Block Control Register - AT91_REG TCB_BMR; // TC Block Mode Register + AT91S_TC TCB_TC0; // TC Channel 0 + AT91_REG Reserved0[4]; // + AT91S_TC TCB_TC1; // TC Channel 1 + AT91_REG Reserved1[4]; // + AT91S_TC TCB_TC2; // TC Channel 2 + AT91_REG Reserved2[4]; // + AT91_REG TCB_BCR; // TC Block Control Register + AT91_REG TCB_BMR; // TC Block Mode Register } AT91S_TCB, *AT91PS_TCB; #else #define TCB_BCR (AT91_CAST(AT91_REG *) 0x000000C0) // (TCB_BCR) TC Block Control Register @@ -1563,12 +1563,12 @@ typedef struct _AT91S_TCB { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_PWMC_CH { - AT91_REG PWMC_CMR; // Channel Mode Register - AT91_REG PWMC_CDTYR; // Channel Duty Cycle Register - AT91_REG PWMC_CPRDR; // Channel Period Register - AT91_REG PWMC_CCNTR; // Channel Counter Register - AT91_REG PWMC_CUPDR; // Channel Update Register - AT91_REG PWMC_Reserved[3]; // Reserved + AT91_REG PWMC_CMR; // Channel Mode Register + AT91_REG PWMC_CDTYR; // Channel Duty Cycle Register + AT91_REG PWMC_CPRDR; // Channel Period Register + AT91_REG PWMC_CCNTR; // Channel Counter Register + AT91_REG PWMC_CUPDR; // Channel Update Register + AT91_REG PWMC_Reserved[3]; // Reserved } AT91S_PWMC_CH, *AT91PS_PWMC_CH; #else #define PWMC_CMR (AT91_CAST(AT91_REG *) 0x00000000) // (PWMC_CMR) Channel Mode Register @@ -1601,18 +1601,18 @@ typedef struct _AT91S_PWMC_CH { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_PWMC { - AT91_REG PWMC_MR; // PWMC Mode Register - AT91_REG PWMC_ENA; // PWMC Enable Register - AT91_REG PWMC_DIS; // PWMC Disable Register - AT91_REG PWMC_SR; // PWMC Status Register - AT91_REG PWMC_IER; // PWMC Interrupt Enable Register - AT91_REG PWMC_IDR; // PWMC Interrupt Disable Register - AT91_REG PWMC_IMR; // PWMC Interrupt Mask Register - AT91_REG PWMC_ISR; // PWMC Interrupt Status Register - AT91_REG Reserved0[55]; // - AT91_REG PWMC_VR; // PWMC Version Register - AT91_REG Reserved1[64]; // - AT91S_PWMC_CH PWMC_CH[4]; // PWMC Channel + AT91_REG PWMC_MR; // PWMC Mode Register + AT91_REG PWMC_ENA; // PWMC Enable Register + AT91_REG PWMC_DIS; // PWMC Disable Register + AT91_REG PWMC_SR; // PWMC Status Register + AT91_REG PWMC_IER; // PWMC Interrupt Enable Register + AT91_REG PWMC_IDR; // PWMC Interrupt Disable Register + AT91_REG PWMC_IMR; // PWMC Interrupt Mask Register + AT91_REG PWMC_ISR; // PWMC Interrupt Status Register + AT91_REG Reserved0[55]; // + AT91_REG PWMC_VR; // PWMC Version Register + AT91_REG Reserved1[64]; // + AT91S_PWMC_CH PWMC_CH[4]; // PWMC Channel } AT91S_PWMC, *AT91PS_PWMC; #else #define PWMC_MR (AT91_CAST(AT91_REG *) 0x00000000) // (PWMC_MR) PWMC Mode Register @@ -1650,23 +1650,23 @@ typedef struct _AT91S_PWMC { // ***************************************************************************** #ifndef __ASSEMBLY__ typedef struct _AT91S_UDP { - AT91_REG UDP_NUM; // Frame Number Register - AT91_REG UDP_GLBSTATE; // Global State Register - AT91_REG UDP_FADDR; // Function Address Register - AT91_REG Reserved0[1]; // - AT91_REG UDP_IER; // Interrupt Enable Register - AT91_REG UDP_IDR; // Interrupt Disable Register - AT91_REG UDP_IMR; // Interrupt Mask Register - AT91_REG UDP_ISR; // Interrupt Status Register - AT91_REG UDP_ICR; // Interrupt Clear Register - AT91_REG Reserved1[1]; // - AT91_REG UDP_RSTEP; // Reset Endpoint Register - AT91_REG Reserved2[1]; // - AT91_REG UDP_CSR[4]; // Endpoint Control and Status Register - AT91_REG Reserved3[4]; // - AT91_REG UDP_FDR[4]; // Endpoint FIFO Data Register - AT91_REG Reserved4[5]; // - AT91_REG UDP_TXVC; // Transceiver Control Register + AT91_REG UDP_NUM; // Frame Number Register + AT91_REG UDP_GLBSTATE; // Global State Register + AT91_REG UDP_FADDR; // Function Address Register + AT91_REG Reserved0[1]; // + AT91_REG UDP_IER; // Interrupt Enable Register + AT91_REG UDP_IDR; // Interrupt Disable Register + AT91_REG UDP_IMR; // Interrupt Mask Register + AT91_REG UDP_ISR; // Interrupt Status Register + AT91_REG UDP_ICR; // Interrupt Clear Register + AT91_REG Reserved1[1]; // + AT91_REG UDP_RSTEP; // Reset Endpoint Register + AT91_REG Reserved2[1]; // + AT91_REG UDP_CSR[4]; // Endpoint Control and Status Register + AT91_REG Reserved3[4]; // + AT91_REG UDP_FDR[4]; // Endpoint FIFO Data Register + AT91_REG Reserved4[5]; // + AT91_REG UDP_TXVC; // Transceiver Control Register } AT91S_UDP, *AT91PS_UDP; #else #define UDP_FRM_NUM (AT91_CAST(AT91_REG *) 0x00000000) // (UDP_FRM_NUM) Frame Number Register diff --git a/include/common.h b/include/common.h index 4b4cf99f3..4f856ac8e 100644 --- a/include/common.h +++ b/include/common.h @@ -71,44 +71,44 @@ extern uint32_t FLASHMEM_SPIBAUDRATE; #ifndef FLASH_MEM_ID_LEN -# define FLASH_MEM_ID_LEN 8 +# define FLASH_MEM_ID_LEN 8 #endif #ifndef FLASH_MEM_SIGNATURE_LEN -# define FLASH_MEM_SIGNATURE_LEN 128 +# define FLASH_MEM_SIGNATURE_LEN 128 #endif #ifndef FLASH_MEM_SIGNATURE_OFFSET -# define FLASH_MEM_SIGNATURE_OFFSET (FLASH_MEM_MAX_SIZE - FLASH_MEM_SIGNATURE_LEN) +# define FLASH_MEM_SIGNATURE_OFFSET (FLASH_MEM_MAX_SIZE - FLASH_MEM_SIGNATURE_LEN) #endif #ifdef WITH_FLASH - #ifndef T55XX_CONFIG_LEN - # define T55XX_CONFIG_LEN sizeof( t55xx_config ) - #endif + #ifndef T55XX_CONFIG_LEN + # define T55XX_CONFIG_LEN sizeof( t55xx_config ) + #endif - #ifndef T55XX_CONFIG_OFFSET - # define T55XX_CONFIG_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x2000) - #endif + #ifndef T55XX_CONFIG_OFFSET + # define T55XX_CONFIG_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x2000) + #endif - #ifndef DEFAULT_T55XX_KEYS_OFFSET - # define DEFAULT_T55XX_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x3000) - #endif + #ifndef DEFAULT_T55XX_KEYS_OFFSET + # define DEFAULT_T55XX_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x3000) + #endif - #ifndef DEFAULT_MF_KEYS_OFFSET - # define DEFAULT_MF_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x4000) - #endif + #ifndef DEFAULT_MF_KEYS_OFFSET + # define DEFAULT_MF_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x4000) + #endif - #ifndef DEFAULT_ICLASS_KEYS_OFFSET - # define DEFAULT_ICLASS_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x5000) - #endif + #ifndef DEFAULT_ICLASS_KEYS_OFFSET + # define DEFAULT_ICLASS_KEYS_OFFSET (FLASH_MEM_MAX_4K_SECTOR - 0x5000) + #endif #endif // RDV40, validation structure to help identifying that client/firmware is talking with RDV40 typedef struct { - uint8_t magic[4]; - uint8_t flashid[FLASH_MEM_ID_LEN]; - uint8_t signature[FLASH_MEM_SIGNATURE_LEN]; + uint8_t magic[4]; + uint8_t flashid[FLASH_MEM_ID_LEN]; + uint8_t signature[FLASH_MEM_SIGNATURE_LEN]; } __attribute__((__packed__)) rdv40_validation_t; diff --git a/include/config_gpio.h b/include/config_gpio.h index bcc06eaa7..89e63de5d 100644 --- a/include/config_gpio.h +++ b/include/config_gpio.h @@ -9,45 +9,45 @@ #ifndef __CONFIG_GPIO_H #define __CONFIG_GPIO_H -#define GPIO_LED_A AT91C_PIO_PA0 -#define GPIO_PA1 AT91C_PIO_PA1 -#define GPIO_LED_D AT91C_PIO_PA2 -#define GPIO_NVDD_ON AT91C_PIO_PA3 -#define GPIO_FPGA_NINIT AT91C_PIO_PA4 -#define GPIO_PA5 AT91C_PIO_PA5 -#define GPIO_PCK0 AT91C_PA6_PCK0 -#define GPIO_LRST AT91C_PIO_PA7 -#define GPIO_LED_B AT91C_PIO_PA8 -#define GPIO_LED_C AT91C_PIO_PA9 +#define GPIO_LED_A AT91C_PIO_PA0 +#define GPIO_PA1 AT91C_PIO_PA1 +#define GPIO_LED_D AT91C_PIO_PA2 +#define GPIO_NVDD_ON AT91C_PIO_PA3 +#define GPIO_FPGA_NINIT AT91C_PIO_PA4 +#define GPIO_PA5 AT91C_PIO_PA5 +#define GPIO_PCK0 AT91C_PA6_PCK0 +#define GPIO_LRST AT91C_PIO_PA7 +#define GPIO_LED_B AT91C_PIO_PA8 +#define GPIO_LED_C AT91C_PIO_PA9 // defines for flash mem, or rdv40 ? // flashmem hooked on PA10 -//#define GPIO_NCS2 AT91C_PIO_PA1 -#define GPIO_NCS2 AT91C_PA10_NPCS2 -#define GPIO_NCS0 AT91C_PA11_NPCS0 +//#define GPIO_NCS2 AT91C_PIO_PA1 +#define GPIO_NCS2 AT91C_PA10_NPCS2 +#define GPIO_NCS0 AT91C_PA11_NPCS0 -#define GPIO_MISO AT91C_PA12_MISO -#define GPIO_MOSI AT91C_PA13_MOSI -#define GPIO_SPCK AT91C_PA14_SPCK -#define GPIO_SSC_FRAME AT91C_PA15_TF -#define GPIO_SSC_CLK AT91C_PA16_TK -#define GPIO_SSC_DOUT AT91C_PA17_TD -#define GPIO_SSC_DIN AT91C_PA18_RD -#define GPIO_MUXSEL_HIPKD AT91C_PIO_PA19 -#define GPIO_MUXSEL_LOPKD AT91C_PIO_PA20 +#define GPIO_MISO AT91C_PA12_MISO +#define GPIO_MOSI AT91C_PA13_MOSI +#define GPIO_SPCK AT91C_PA14_SPCK +#define GPIO_SSC_FRAME AT91C_PA15_TF +#define GPIO_SSC_CLK AT91C_PA16_TK +#define GPIO_SSC_DOUT AT91C_PA17_TD +#define GPIO_SSC_DIN AT91C_PA18_RD +#define GPIO_MUXSEL_HIPKD AT91C_PIO_PA19 +#define GPIO_MUXSEL_LOPKD AT91C_PIO_PA20 // RDV40 has no HIRAW/LORAW, its used for FPC -#define GPIO_MUXSEL_HIRAW AT91C_PIO_PA21 -#define GPIO_MUXSEL_LORAW AT91C_PIO_PA22 +#define GPIO_MUXSEL_HIRAW AT91C_PIO_PA21 +#define GPIO_MUXSEL_LORAW AT91C_PIO_PA22 -#define GPIO_BUTTON AT91C_PIO_PA23 -#define GPIO_USB_PU AT91C_PIO_PA24 -#define GPIO_RELAY AT91C_PIO_PA25 -#define GPIO_FPGA_ON AT91C_PIO_PA26 -#define GPIO_FPGA_DONE AT91C_PIO_PA27 -#define GPIO_FPGA_NPROGRAM AT91C_PIO_PA28 -#define GPIO_FPGA_CCLK AT91C_PIO_PA29 -#define GPIO_FPGA_DIN AT91C_PIO_PA30 -#define GPIO_FPGA_DOUT AT91C_PIO_PA31 +#define GPIO_BUTTON AT91C_PIO_PA23 +#define GPIO_USB_PU AT91C_PIO_PA24 +#define GPIO_RELAY AT91C_PIO_PA25 +#define GPIO_FPGA_ON AT91C_PIO_PA26 +#define GPIO_FPGA_DONE AT91C_PIO_PA27 +#define GPIO_FPGA_NPROGRAM AT91C_PIO_PA28 +#define GPIO_FPGA_CCLK AT91C_PIO_PA29 +#define GPIO_FPGA_DIN AT91C_PIO_PA30 +#define GPIO_FPGA_DOUT AT91C_PIO_PA31 #endif diff --git a/include/hitag2.h b/include/hitag2.h index 2eeb48f6f..96cfb7abb 100644 --- a/include/hitag2.h +++ b/include/hitag2.h @@ -20,36 +20,36 @@ #endif typedef enum { - RHTSF_CHALLENGE = 01, - RHTSF_KEY = 02, - WHTSF_CHALLENGE = 03, - WHTSF_KEY = 04, - RHT2F_PASSWORD = 21, - RHT2F_AUTHENTICATE = 22, - RHT2F_CRYPTO = 23, - WHT2F_CRYPTO = 24, - RHT2F_TEST_AUTH_ATTEMPTS = 25, - RHT2F_UID_ONLY = 26, + RHTSF_CHALLENGE = 01, + RHTSF_KEY = 02, + WHTSF_CHALLENGE = 03, + WHTSF_KEY = 04, + RHT2F_PASSWORD = 21, + RHT2F_AUTHENTICATE = 22, + RHT2F_CRYPTO = 23, + WHT2F_CRYPTO = 24, + RHT2F_TEST_AUTH_ATTEMPTS = 25, + RHT2F_UID_ONLY = 26, } hitag_function; typedef struct { - byte_t password[4]; + byte_t password[4]; } PACKED rht2d_password; typedef struct { - byte_t NrAr[8]; - byte_t data[4]; + byte_t NrAr[8]; + byte_t data[4]; } PACKED rht2d_authenticate; typedef struct { - byte_t key[6]; - byte_t data[4]; + byte_t key[6]; + byte_t data[4]; } PACKED rht2d_crypto; typedef union { - rht2d_password pwd; - rht2d_authenticate auth; - rht2d_crypto crypto; + rht2d_password pwd; + rht2d_authenticate auth; + rht2d_crypto crypto; } hitag_data; #endif diff --git a/include/hitagS.h b/include/hitagS.h index d74463f20..307e456b3 100644 --- a/include/hitagS.h +++ b/include/hitagS.h @@ -18,57 +18,57 @@ //protocol-state typedef enum PROTO_STATE { - HT_READY=0, - HT_INIT, - HT_AUTHENTICATE, - HT_SELECTED, - HT_QUIET, - HT_TTF, - HT_FAIL} PSTATE; + HT_READY=0, + HT_INIT, + HT_AUTHENTICATE, + HT_SELECTED, + HT_QUIET, + HT_TTF, + HT_FAIL} PSTATE; //tag-state typedef enum TAG_STATE { - HT_NO_OP=0, - HT_READING_PAGE, - HT_WRITING_PAGE_ACK, - HT_WRITING_PAGE_DATA, - HT_WRITING_BLOCK_DATA} TSATE; + HT_NO_OP=0, + HT_READING_PAGE, + HT_WRITING_PAGE_ACK, + HT_WRITING_PAGE_DATA, + HT_WRITING_BLOCK_DATA} TSATE; //number of start-of-frame bits typedef enum SOF_TYPE { - HT_STANDARD=0, - HT_ADVANCED, - HT_FAST_ADVANCED, - HT_ONE, - HT_NO_BITS} stype; + HT_STANDARD=0, + HT_ADVANCED, + HT_FAST_ADVANCED, + HT_ONE, + HT_NO_BITS} stype; struct hitagS_tag { - PSTATE pstate; //protocol-state - TSATE tstate; //tag-state - uint32_t uid; - uint32_t pages[16][4]; - uint64_t key; - byte_t pwdl0, pwdl1, pwdh0; - //con0 - int max_page; - stype mode; - //con1 - bool auth; //0=Plain 1=Auth - bool TTFC; //Transponder Talks first coding. 0=Manchester 1=Biphase - int TTFDR; //data rate in TTF Mode - int TTFM; //the number of pages that are sent to the RWD - bool LCON; //0=con1/2 read write 1=con1 read only and con2 OTP - bool LKP; //0=page2/3 read write 1=page2/3 read only in Plain mode and no access in authenticate mode - //con2 - //0=read write 1=read only - bool LCK7; //page4/5 - bool LCK6; //page6/7 - bool LCK5; //page8-11 - bool LCK4; //page12-15 - bool LCK3; //page16-23 - bool LCK2; //page24-31 - bool LCK1; //page32-47 - bool LCK0; //page48-63 + PSTATE pstate; //protocol-state + TSATE tstate; //tag-state + uint32_t uid; + uint32_t pages[16][4]; + uint64_t key; + byte_t pwdl0, pwdl1, pwdh0; + //con0 + int max_page; + stype mode; + //con1 + bool auth; //0=Plain 1=Auth + bool TTFC; //Transponder Talks first coding. 0=Manchester 1=Biphase + int TTFDR; //data rate in TTF Mode + int TTFM; //the number of pages that are sent to the RWD + bool LCON; //0=con1/2 read write 1=con1 read only and con2 OTP + bool LKP; //0=page2/3 read write 1=page2/3 read only in Plain mode and no access in authenticate mode + //con2 + //0=read write 1=read only + bool LCK7; //page4/5 + bool LCK6; //page6/7 + bool LCK5; //page8-11 + bool LCK4; //page12-15 + bool LCK3; //page16-23 + bool LCK2; //page24-31 + bool LCK1; //page32-47 + bool LCK0; //page48-63 } ; #endif diff --git a/include/legic.h b/include/legic.h index d5ba8f166..574cb7fdf 100644 --- a/include/legic.h +++ b/include/legic.h @@ -17,11 +17,11 @@ // LEGIC //----------------------------------------------------------------------------- typedef struct { - uint8_t uid[4]; - uint32_t tagtype; - uint8_t cmdsize; - uint8_t addrsize; - uint16_t cardsize; + uint8_t uid[4]; + uint32_t tagtype; + uint8_t cmdsize; + uint8_t addrsize; + uint16_t cardsize; } legic_card_select_t; #endif // _LEGIC_H_ diff --git a/include/mifare.h b/include/mifare.h index eec72c26f..222719188 100644 --- a/include/mifare.h +++ b/include/mifare.h @@ -13,111 +13,111 @@ #include "common.h" -#define MF_KEY_A 0 -#define MF_KEY_B 1 +#define MF_KEY_A 0 +#define MF_KEY_B 1 -#define MF_MAD1_SECTOR 0x00 -#define MF_MAD2_SECTOR 0x10 +#define MF_MAD1_SECTOR 0x00 +#define MF_MAD2_SECTOR 0x10 //----------------------------------------------------------------------------- // ISO 14443A //----------------------------------------------------------------------------- typedef struct { - byte_t uid[10]; - byte_t uidlen; - byte_t atqa[2]; - byte_t sak; - byte_t ats_len; - byte_t ats[256]; + byte_t uid[10]; + byte_t uidlen; + byte_t atqa[2]; + byte_t sak; + byte_t ats_len; + byte_t ats[256]; } __attribute__((__packed__)) iso14a_card_select_t; typedef enum ISO14A_COMMAND { - ISO14A_CONNECT = (1 << 0), - ISO14A_NO_DISCONNECT = (1 << 1), - ISO14A_APDU = (1 << 2), - ISO14A_RAW = (1 << 3), - ISO14A_REQUEST_TRIGGER = (1 << 4), - ISO14A_APPEND_CRC = (1 << 5), - ISO14A_SET_TIMEOUT = (1 << 6), - ISO14A_NO_SELECT = (1 << 7), - ISO14A_TOPAZMODE = (1 << 8), - ISO14A_NO_RATS = (1 << 9), - ISO14A_SEND_CHAINING = (1 << 10) + ISO14A_CONNECT = (1 << 0), + ISO14A_NO_DISCONNECT = (1 << 1), + ISO14A_APDU = (1 << 2), + ISO14A_RAW = (1 << 3), + ISO14A_REQUEST_TRIGGER = (1 << 4), + ISO14A_APPEND_CRC = (1 << 5), + ISO14A_SET_TIMEOUT = (1 << 6), + ISO14A_NO_SELECT = (1 << 7), + ISO14A_TOPAZMODE = (1 << 8), + ISO14A_NO_RATS = (1 << 9), + ISO14A_SEND_CHAINING = (1 << 10) } iso14a_command_t; typedef struct { - uint8_t* response; - size_t response_n; - uint8_t* modulation; - size_t modulation_n; - uint32_t ProxToAirDuration; + uint8_t* response; + size_t response_n; + uint8_t* modulation; + size_t modulation_n; + uint32_t ProxToAirDuration; } tag_response_info_t; //----------------------------------------------------------------------------- // ISO 14443B //----------------------------------------------------------------------------- typedef struct { - byte_t uid[10]; - byte_t uidlen; - byte_t atqb[7]; - byte_t chipid; - byte_t cid; + byte_t uid[10]; + byte_t uidlen; + byte_t atqb[7]; + byte_t chipid; + byte_t cid; } __attribute__((__packed__)) iso14b_card_select_t; typedef enum ISO14B_COMMAND { - ISO14B_CONNECT = (1 << 0), - ISO14B_DISCONNECT = (1 << 1), - ISO14B_APDU = (1 << 2), - ISO14B_RAW = (1 << 3), - ISO14B_REQUEST_TRIGGER = (1 << 4), - ISO14B_APPEND_CRC = (1 << 5), - ISO14B_SELECT_STD = (1 << 6), - ISO14B_SELECT_SR = (1 << 7) + ISO14B_CONNECT = (1 << 0), + ISO14B_DISCONNECT = (1 << 1), + ISO14B_APDU = (1 << 2), + ISO14B_RAW = (1 << 3), + ISO14B_REQUEST_TRIGGER = (1 << 4), + ISO14B_APPEND_CRC = (1 << 5), + ISO14B_SELECT_STD = (1 << 6), + ISO14B_SELECT_SR = (1 << 7) } iso14b_command_t; typedef enum ISO15_COMMAND { - ISO15_CONNECT = (1 << 0), - ISO15_NO_DISCONNECT = (1 << 1), - ISO15_RAW = (1 << 2), - ISO15_APPEND_CRC = (1 << 3), - ISO15_HIGH_SPEED = (1 << 4), - ISO15_READ_RESPONSE = (1 << 5) + ISO15_CONNECT = (1 << 0), + ISO15_NO_DISCONNECT = (1 << 1), + ISO15_RAW = (1 << 2), + ISO15_APPEND_CRC = (1 << 3), + ISO15_HIGH_SPEED = (1 << 4), + ISO15_READ_RESPONSE = (1 << 5) } iso15_command_t; //----------------------------------------------------------------------------- // "hf 14a sim x", "hf mf sim x" attacks //----------------------------------------------------------------------------- typedef struct { - uint32_t cuid; - uint32_t nonce; - uint32_t ar; - uint32_t nr; - uint32_t at; - uint32_t nonce2; - uint32_t ar2; - uint32_t nr2; - uint8_t sector; - uint8_t keytype; - enum { - EMPTY, - FIRST, - SECOND, - } state; + uint32_t cuid; + uint32_t nonce; + uint32_t ar; + uint32_t nr; + uint32_t at; + uint32_t nonce2; + uint32_t ar2; + uint32_t nr2; + uint8_t sector; + uint8_t keytype; + enum { + EMPTY, + FIRST, + SECOND, + } state; } nonces_t; //----------------------------------------------------------------------------- // ISO 7618 Smart Card //----------------------------------------------------------------------------- typedef struct { - uint8_t atr_len; - uint8_t atr[30]; + uint8_t atr_len; + uint8_t atr[30]; } __attribute__((__packed__)) smart_card_atr_t; typedef enum SMARTCARD_COMMAND { - SC_CONNECT = (1 << 0), - SC_NO_DISCONNECT = (1 << 1), - SC_RAW = (1 << 2), - SC_SELECT = (1 << 3), - SC_RAW_T0 = (1 << 4), + SC_CONNECT = (1 << 0), + SC_NO_DISCONNECT = (1 << 1), + SC_RAW = (1 << 2), + SC_SELECT = (1 << 3), + SC_RAW_T0 = (1 << 4), } smartcard_command_t; //----------------------------------------------------------------------------- @@ -128,34 +128,34 @@ typedef enum SMARTCARD_COMMAND { // mc1 mc2 u1 u2 u3 u4 u5 u6 // PMm = Product manufacturer // icCode = -// ic1 = ROM -// ic2 = IC +// ic1 = ROM +// ic2 = IC // maximum response time = -// B3(request service) -// B4(request response) -// B5(authenticate) -// B6(read) -// B7(write) -// B8() +// B3(request service) +// B4(request response) +// B5(authenticate) +// B6(read) +// B7(write) +// B8() // ServiceCode 2bytes (access-rights) // FileSystem = 1 Block = 16 bytes typedef struct { - uint8_t IDm[8]; - uint8_t code[2]; - uint8_t uid[6]; - uint8_t PMm[8]; - uint8_t iccode[2]; - uint8_t mrt[6]; - uint8_t servicecode[2]; + uint8_t IDm[8]; + uint8_t code[2]; + uint8_t uid[6]; + uint8_t PMm[8]; + uint8_t iccode[2]; + uint8_t mrt[6]; + uint8_t servicecode[2]; } __attribute__((__packed__)) felica_card_select_t; typedef enum FELICA_COMMAND { - FELICA_CONNECT = (1 << 0), - FELICA_NO_DISCONNECT = (1 << 1), - FELICA_RAW = (1 << 3), - FELICA_APPEND_CRC = (1 << 5), - FELICA_NO_SELECT = (1 << 6), + FELICA_CONNECT = (1 << 0), + FELICA_NO_DISCONNECT = (1 << 1), + FELICA_RAW = (1 << 3), + FELICA_APPEND_CRC = (1 << 5), + FELICA_NO_SELECT = (1 << 6), } felica_command_t; #endif // _MIFARE_H_ diff --git a/include/proxmark3.h b/include/proxmark3.h index 4b16f4eed..ff3a8dfde 100644 --- a/include/proxmark3.h +++ b/include/proxmark3.h @@ -16,56 +16,56 @@ #include "config_gpio.h" #include "usb_cmd.h" -#define WDT_HIT() AT91C_BASE_WDTC->WDTC_WDCR = 0xa5000001 +#define WDT_HIT() AT91C_BASE_WDTC->WDTC_WDCR = 0xa5000001 -#define PWM_CH_MODE_PRESCALER(x) ((x) << 0) -#define PWM_CHANNEL(x) (1 << (x)) +#define PWM_CH_MODE_PRESCALER(x) ((x) << 0) +#define PWM_CHANNEL(x) (1 << (x)) -#define ADC_CHAN_LF 4 -#define ADC_CHAN_HF 5 -#define ADC_CHAN_HF_RDV40 7 -#define ADC_MODE_PRESCALE(x) ((x) << 8) -#define ADC_MODE_STARTUP_TIME(x) ((x) << 16) -#define ADC_MODE_SAMPLE_HOLD_TIME(x) ((x) << 24) -#define ADC_CHANNEL(x) (1 << (x)) -#define ADC_END_OF_CONVERSION(x) (1 << (x)) +#define ADC_CHAN_LF 4 +#define ADC_CHAN_HF 5 +#define ADC_CHAN_HF_RDV40 7 +#define ADC_MODE_PRESCALE(x) ((x) << 8) +#define ADC_MODE_STARTUP_TIME(x) ((x) << 16) +#define ADC_MODE_SAMPLE_HOLD_TIME(x) ((x) << 24) +#define ADC_CHANNEL(x) (1 << (x)) +#define ADC_END_OF_CONVERSION(x) (1 << (x)) -#define SSC_CLOCK_MODE_START(x) ((x) << 8) -#define SSC_FRAME_MODE_WORDS_PER_TRANSFER(x) ((x) << 8) -#define SSC_CLOCK_MODE_SELECT(x) ((x) << 0) -#define SSC_FRAME_MODE_BITS_IN_WORD(x) (((x)-1) << 0) +#define SSC_CLOCK_MODE_START(x) ((x) << 8) +#define SSC_FRAME_MODE_WORDS_PER_TRANSFER(x) ((x) << 8) +#define SSC_CLOCK_MODE_SELECT(x) ((x) << 0) +#define SSC_FRAME_MODE_BITS_IN_WORD(x) (((x)-1) << 0) -#define MC_FLASH_COMMAND_KEY ((0x5a) << 24) -#define MC_FLASH_MODE_FLASH_WAIT_STATES(x) ((x) << 8) -#define MC_FLASH_MODE_MASTER_CLK_IN_MHZ(x) (((x)+((x)/2)) << 16) -#define MC_FLASH_COMMAND_PAGEN(x) ((x) << 8) +#define MC_FLASH_COMMAND_KEY ((0x5a) << 24) +#define MC_FLASH_MODE_FLASH_WAIT_STATES(x) ((x) << 8) +#define MC_FLASH_MODE_MASTER_CLK_IN_MHZ(x) (((x)+((x)/2)) << 16) +#define MC_FLASH_COMMAND_PAGEN(x) ((x) << 8) -#define RST_CONTROL_KEY (0xa5 << 24) +#define RST_CONTROL_KEY (0xa5 << 24) -#define PMC_MAIN_OSC_STARTUP_DELAY(x) ((x) << 8) -#define PMC_PLL_DIVISOR(x) (x) -#define PMC_PLL_MULTIPLIER(x) (((x)-1) << 16) -#define PMC_PLL_COUNT_BEFORE_LOCK(x) (((x) & 0x3F) << 8) // 6bit register 0011 1111 -#define PMC_PLL_FREQUENCY_RANGE(x) (((x) & 0x3) << 14) // 2bit register -#define PMC_PLL_USB_DIVISOR(x) ((x) << 28) +#define PMC_MAIN_OSC_STARTUP_DELAY(x) ((x) << 8) +#define PMC_PLL_DIVISOR(x) (x) +#define PMC_PLL_MULTIPLIER(x) (((x)-1) << 16) +#define PMC_PLL_COUNT_BEFORE_LOCK(x) (((x) & 0x3F) << 8) // 6bit register 0011 1111 +#define PMC_PLL_FREQUENCY_RANGE(x) (((x) & 0x3) << 14) // 2bit register +#define PMC_PLL_USB_DIVISOR(x) ((x) << 28) -#define UDP_INTERRUPT_ENDPOINT(x) (1 << (x)) -#define UDP_CSR_BYTES_RECEIVED(x) (((x) >> 16) & 0x7ff) +#define UDP_INTERRUPT_ENDPOINT(x) (1 << (x)) +#define UDP_CSR_BYTES_RECEIVED(x) (((x) >> 16) & 0x7ff) //************************************************************** -#define LOW(x) AT91C_BASE_PIOA->PIO_CODR |= (x) -#define HIGH(x) AT91C_BASE_PIOA->PIO_SODR |= (x) +#define LOW(x) AT91C_BASE_PIOA->PIO_CODR |= (x) +#define HIGH(x) AT91C_BASE_PIOA->PIO_SODR |= (x) -#define GETBIT(x) (AT91C_BASE_PIOA->PIO_ODSR & (x)) ? 1:0 +#define GETBIT(x) (AT91C_BASE_PIOA->PIO_ODSR & (x)) ? 1:0 #define SETBIT(x, y) (y) ? (HIGH(x)):(LOW(x)) -#define INVBIT(x) SETBIT((x), !(GETBIT(x))) +#define INVBIT(x) SETBIT((x), !(GETBIT(x))) // Setup for SPI current modes -#define SPI_FPGA_MODE 0 -#define SPI_LCD_MODE 1 -#define SPI_MEM_MODE 2 +#define SPI_FPGA_MODE 0 +#define SPI_LCD_MODE 1 +#define SPI_MEM_MODE 2 #ifndef COTAG_BITS #define COTAG_BITS 264 @@ -73,25 +73,25 @@ //#define PACKED __attribute__((__packed__)) -#define LED_A_ON() HIGH(GPIO_LED_A) -#define LED_A_OFF() LOW(GPIO_LED_A) -#define LED_A_INV() INVBIT(GPIO_LED_A) -#define LED_B_ON() HIGH(GPIO_LED_B) -#define LED_B_OFF() LOW(GPIO_LED_B) -#define LED_B_INV() INVBIT(GPIO_LED_B) -#define LED_C_ON() HIGH(GPIO_LED_C) -#define LED_C_OFF() LOW(GPIO_LED_C) -#define LED_C_INV() INVBIT(GPIO_LED_C) -#define LED_D_ON() HIGH(GPIO_LED_D) -#define LED_D_OFF() LOW(GPIO_LED_D) -#define LED_D_INV() INVBIT(GPIO_LED_D) +#define LED_A_ON() HIGH(GPIO_LED_A) +#define LED_A_OFF() LOW(GPIO_LED_A) +#define LED_A_INV() INVBIT(GPIO_LED_A) +#define LED_B_ON() HIGH(GPIO_LED_B) +#define LED_B_OFF() LOW(GPIO_LED_B) +#define LED_B_INV() INVBIT(GPIO_LED_B) +#define LED_C_ON() HIGH(GPIO_LED_C) +#define LED_C_OFF() LOW(GPIO_LED_C) +#define LED_C_INV() INVBIT(GPIO_LED_C) +#define LED_D_ON() HIGH(GPIO_LED_D) +#define LED_D_OFF() LOW(GPIO_LED_D) +#define LED_D_INV() INVBIT(GPIO_LED_D) // SPI -#define SCK_LOW LOW(GPIO_SPCK) -#define SCK_HIGH HIGH(GPIO_SPCK) -#define MOSI_HIGH HIGH(GPIO_MOSI) -#define MOSI_LOW LOW(GPIO_MOSI) -#define MISO_VALUE (AT91C_BASE_PIOA->PIO_PDSR & GPIO_MISO) +#define SCK_LOW LOW(GPIO_SPCK) +#define SCK_HIGH HIGH(GPIO_SPCK) +#define MOSI_HIGH HIGH(GPIO_MOSI) +#define MOSI_LOW LOW(GPIO_MOSI) +#define MISO_VALUE (AT91C_BASE_PIOA->PIO_PDSR & GPIO_MISO) // fpga #define NCS_0_LOW LOW(GPIO_NCS0) @@ -101,35 +101,35 @@ #define NCS_1_LOW LOW(GPIO_NCS2) #define NCS_1_HIGH HIGH(GPIO_NCS2) -#define RELAY_ON() HIGH(GPIO_RELAY) -#define RELAY_OFF() LOW(GPIO_RELAY) -#define BUTTON_PRESS() !((AT91C_BASE_PIOA->PIO_PDSR & GPIO_BUTTON) == GPIO_BUTTON) +#define RELAY_ON() HIGH(GPIO_RELAY) +#define RELAY_OFF() LOW(GPIO_RELAY) +#define BUTTON_PRESS() !((AT91C_BASE_PIOA->PIO_PDSR & GPIO_BUTTON) == GPIO_BUTTON) //NVDD goes LOW when USB is attached. -#define USB_ATTACHED() !((AT91C_BASE_PIOA->PIO_PDSR & GPIO_NVDD_ON) == GPIO_NVDD_ON) +#define USB_ATTACHED() !((AT91C_BASE_PIOA->PIO_PDSR & GPIO_NVDD_ON) == GPIO_NVDD_ON) #define VERSION_INFORMATION_MAGIC 0x56334d50 struct version_information { - int magic; /* Magic sequence to identify this as a correct version information structure. Must be VERSION_INFORMATION_MAGIC */ - char versionversion; /* Must be 1 */ - char present; /* 1 if the version information could be created at compile time, otherwise 0 and the remaining fields (except for magic) are empty */ - char clean; /* 1: Tree was clean, no local changes. 0: Tree was unclean. 2: Couldn't be determined */ - char gitversion[50]; /* String with the git revision */ - char buildtime[30]; /* string with the build time */ + int magic; /* Magic sequence to identify this as a correct version information structure. Must be VERSION_INFORMATION_MAGIC */ + char versionversion; /* Must be 1 */ + char present; /* 1 if the version information could be created at compile time, otherwise 0 and the remaining fields (except for magic) are empty */ + char clean; /* 1: Tree was clean, no local changes. 0: Tree was unclean. 2: Couldn't be determined */ + char gitversion[50]; /* String with the git revision */ + char buildtime[30]; /* string with the build time */ } __attribute__((packed)); #define COMMON_AREA_MAGIC 0x43334d50 #define COMMON_AREA_COMMAND_NONE 0 #define COMMON_AREA_COMMAND_ENTER_FLASH_MODE 1 struct common_area { - int magic; /* Magic sequence, to distinguish against random uninitialized memory */ - char version; /* Must be 1 */ - char command; - struct { - unsigned int bootrom_present:1; /* Set when a bootrom that is capable of parsing the common area is present */ - unsigned int osimage_present:1; /* Set when a osimage that is capable of parsing the common area is present */ - } __attribute__((packed)) flags; - int arg1, arg2; + int magic; /* Magic sequence, to distinguish against random uninitialized memory */ + char version; /* Must be 1 */ + char command; + struct { + unsigned int bootrom_present:1; /* Set when a bootrom that is capable of parsing the common area is present */ + unsigned int osimage_present:1; /* Set when a osimage that is capable of parsing the common area is present */ + } __attribute__((packed)) flags; + int arg1, arg2; } __attribute__((packed)); #endif diff --git a/include/usb_cmd.h b/include/usb_cmd.h index 0680b443a..2e2526bf3 100644 --- a/include/usb_cmd.h +++ b/include/usb_cmd.h @@ -36,19 +36,19 @@ typedef struct { } PACKED UsbCommand; // A struct used to send sample-configs over USB typedef struct{ - uint8_t decimation; - uint8_t bits_per_sample; - bool averaging; - int divisor; - int trigger_threshold; + uint8_t decimation; + uint8_t bits_per_sample; + bool averaging; + int divisor; + int trigger_threshold; } sample_config; typedef struct{ - uint16_t start_gap; - uint16_t write_gap; - uint16_t write_0; - uint16_t write_1; - uint16_t read_gap; + uint16_t start_gap; + uint16_t write_gap; + uint16_t write_0; + uint16_t write_1; + uint16_t read_gap; } t55xx_config; // For the bootloader @@ -69,35 +69,35 @@ typedef struct{ #define CMD_BUFF_CLEAR 0x0105 #define CMD_READ_MEM 0x0106 #define CMD_VERSION 0x0107 -#define CMD_STATUS 0x0108 -#define CMD_PING 0x0109 +#define CMD_STATUS 0x0108 +#define CMD_PING 0x0109 -#define CMD_DOWNLOAD_EML_BIGBUF 0x0110 -#define CMD_DOWNLOADED_EML_BIGBUF 0x0111 +#define CMD_DOWNLOAD_EML_BIGBUF 0x0110 +#define CMD_DOWNLOADED_EML_BIGBUF 0x0111 // RDV40, Flash memory operations -#define CMD_FLASHMEM_READ 0x0120 -#define CMD_FLASHMEM_WRITE 0x0121 -#define CMD_FLASHMEM_WIPE 0x0122 -#define CMD_FLASHMEM_DOWNLOAD 0x0123 -#define CMD_FLASHMEM_DOWNLOADED 0x0124 -#define CMD_FLASHMEM_INFO 0x0125 +#define CMD_FLASHMEM_READ 0x0120 +#define CMD_FLASHMEM_WRITE 0x0121 +#define CMD_FLASHMEM_WIPE 0x0122 +#define CMD_FLASHMEM_DOWNLOAD 0x0123 +#define CMD_FLASHMEM_DOWNLOADED 0x0124 +#define CMD_FLASHMEM_INFO 0x0125 #define CMD_FLASHMEM_SET_SPIBAUDRATE 0x0126 // RDV40, Smart card operations -#define CMD_SMART_RAW 0x0140 -#define CMD_SMART_UPGRADE 0x0141 -#define CMD_SMART_UPLOAD 0x0142 -#define CMD_SMART_ATR 0x0143 -#define CMD_SMART_SETBAUD 0x0144 -#define CMD_SMART_SETCLOCK 0x0145 +#define CMD_SMART_RAW 0x0140 +#define CMD_SMART_UPGRADE 0x0141 +#define CMD_SMART_UPLOAD 0x0142 +#define CMD_SMART_ATR 0x0143 +#define CMD_SMART_SETBAUD 0x0144 +#define CMD_SMART_SETCLOCK 0x0145 // RDV40, FPC serial -#define CMD_FPC_SEND 0x0160 -#define CMD_FPC_READ 0x0161 +#define CMD_FPC_SEND 0x0160 +#define CMD_FPC_READ 0x0161 // For low-frequency tags #define CMD_READ_TI_TYPE 0x0202 @@ -136,9 +136,9 @@ typedef struct{ #define CMD_PSK_SIM_TAG 0x0220 #define CMD_AWID_DEMOD_FSK 0x0221 #define CMD_VIKING_CLONE_TAG 0x0222 -#define CMD_T55XX_WAKEUP 0x0224 -#define CMD_COTAG 0x0225 -#define CMD_SET_LF_T55XX_CONFIG 0x0226 +#define CMD_T55XX_WAKEUP 0x0224 +#define CMD_COTAG 0x0225 +#define CMD_SET_LF_T55XX_CONFIG 0x0226 #define CMD_T55XX_CHKPWDS 0x0230 @@ -162,13 +162,13 @@ typedef struct{ #define CMD_READER_HITAG 0x0372 // For HitagS -#define CMD_TEST_HITAGS_TRACES 0x0367 -#define CMD_SIMULATE_HITAG_S 0x0368 -#define CMD_READ_HITAG_S 0x0373 -#define CMD_WR_HITAG_S 0x0375 -#define CMD_EMU_HITAG_S 0x0376 +#define CMD_TEST_HITAGS_TRACES 0x0367 +#define CMD_SIMULATE_HITAG_S 0x0368 +#define CMD_READ_HITAG_S 0x0373 +#define CMD_WR_HITAG_S 0x0375 +#define CMD_EMU_HITAG_S 0x0376 -#define CMD_ANTIFUZZ_ISO_14443a 0x0380 +#define CMD_ANTIFUZZ_ISO_14443a 0x0380 #define CMD_SIMULATE_TAG_ISO_14443B 0x0381 #define CMD_SNOOP_ISO_14443B 0x0382 @@ -185,9 +185,9 @@ typedef struct{ #define CMD_EPA_PACE_COLLECT_NONCE 0x038A #define CMD_EPA_PACE_REPLAY 0x038B -#define CMD_LEGIC_INFO 0x03BC -#define CMD_LEGIC_ESET 0x03BD -#define CMD_LEGIC_EGET 0x03BE +#define CMD_LEGIC_INFO 0x03BC +#define CMD_LEGIC_ESET 0x03BD +#define CMD_LEGIC_EGET 0x03BE #define CMD_ICLASS_READCHECK 0x038F #define CMD_ICLASS_CLONE 0x0390 @@ -236,19 +236,19 @@ typedef struct{ #define CMD_READER_MIFARE 0x0611 #define CMD_MIFARE_NESTED 0x0612 #define CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES 0x0613 -#define CMD_MIFARE_ACQUIRE_NONCES 0x0614 +#define CMD_MIFARE_ACQUIRE_NONCES 0x0614 #define CMD_MIFARE_READBL 0x0620 #define CMD_MIFAREU_READBL 0x0720 #define CMD_MIFARE_READSC 0x0621 #define CMD_MIFAREU_READCARD 0x0721 #define CMD_MIFARE_WRITEBL 0x0622 -#define CMD_MIFAREU_WRITEBL 0x0722 -#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723 +#define CMD_MIFAREU_WRITEBL 0x0722 +#define CMD_MIFAREU_WRITEBL_COMPAT 0x0723 #define CMD_MIFARE_CHKKEYS 0x0623 #define CMD_MIFARE_SETMOD 0x0624 -#define CMD_MIFARE_CHKKEYS_FAST 0x0625 +#define CMD_MIFARE_CHKKEYS_FAST 0x0625 #define CMD_MIFARE_SNIFFER 0x0630 //ultralightC @@ -265,8 +265,8 @@ typedef struct{ #define CMD_MIFARE_DESFIRE_INFO 0x072d #define CMD_MIFARE_DESFIRE 0x072e -#define CMD_MIFARE_COLLECT_NONCES 0x072f -#define CMD_MIFARE_NACK_DETECT 0x0730 +#define CMD_MIFARE_COLLECT_NONCES 0x072f +#define CMD_MIFARE_NACK_DETECT 0x0730 #define CMD_HF_SNIFFER 0x0800 @@ -284,46 +284,46 @@ typedef struct{ #define CMD_UNKNOWN 0xFFFF //Mifare simulation flags -#define FLAG_INTERACTIVE 0x01 -#define FLAG_4B_UID_IN_DATA 0x02 -#define FLAG_7B_UID_IN_DATA 0x04 -#define FLAG_10B_UID_IN_DATA 0x08 -#define FLAG_UID_IN_EMUL 0x10 -#define FLAG_NR_AR_ATTACK 0x20 -//#define FLAG_RANDOM_NONCE 0x40 +#define FLAG_INTERACTIVE 0x01 +#define FLAG_4B_UID_IN_DATA 0x02 +#define FLAG_7B_UID_IN_DATA 0x04 +#define FLAG_10B_UID_IN_DATA 0x08 +#define FLAG_UID_IN_EMUL 0x10 +#define FLAG_NR_AR_ATTACK 0x20 +//#define FLAG_RANDOM_NONCE 0x40 //Iclass reader flags -#define FLAG_ICLASS_READER_ONLY_ONCE 0x01 -#define FLAG_ICLASS_READER_CC 0x02 -#define FLAG_ICLASS_READER_CSN 0x04 -#define FLAG_ICLASS_READER_CONF 0x08 -#define FLAG_ICLASS_READER_AIA 0x10 -#define FLAG_ICLASS_READER_ONE_TRY 0x20 -#define FLAG_ICLASS_READER_CEDITKEY 0x40 +#define FLAG_ICLASS_READER_ONLY_ONCE 0x01 +#define FLAG_ICLASS_READER_CC 0x02 +#define FLAG_ICLASS_READER_CSN 0x04 +#define FLAG_ICLASS_READER_CONF 0x08 +#define FLAG_ICLASS_READER_AIA 0x10 +#define FLAG_ICLASS_READER_ONE_TRY 0x20 +#define FLAG_ICLASS_READER_CEDITKEY 0x40 // Dbprintf flags -#define FLAG_RAWPRINT 0x0111 -#define FLAG_NOOPT 0x0000 -#define FLAG_NOLOG 0x0001 -#define FLAG_NONEWLINE 0x0010 -#define FLAG_NOPROMPT 0x0100 +#define FLAG_RAWPRINT 0x0111 +#define FLAG_NOOPT 0x0000 +#define FLAG_NOLOG 0x0001 +#define FLAG_NONEWLINE 0x0010 +#define FLAG_NOPROMPT 0x0100 // CMD_DEVICE_INFO response packet has flags in arg[0], flag definitions: /* Whether a bootloader that understands the common_area is present */ -#define DEVICE_INFO_FLAG_BOOTROM_PRESENT (1<<0) +#define DEVICE_INFO_FLAG_BOOTROM_PRESENT (1<<0) /* Whether a osimage that understands the common_area is present */ -#define DEVICE_INFO_FLAG_OSIMAGE_PRESENT (1<<1) +#define DEVICE_INFO_FLAG_OSIMAGE_PRESENT (1<<1) /* Set if the bootloader is currently executing */ -#define DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM (1<<2) +#define DEVICE_INFO_FLAG_CURRENT_MODE_BOOTROM (1<<2) /* Set if the OS is currently executing */ -#define DEVICE_INFO_FLAG_CURRENT_MODE_OS (1<<3) +#define DEVICE_INFO_FLAG_CURRENT_MODE_OS (1<<3) /* Set if this device understands the extend start flash command */ -#define DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH (1<<4) +#define DEVICE_INFO_FLAG_UNDERSTANDS_START_FLASH (1<<4) /* CMD_START_FLASH may have three arguments: start of area to flash, end of area to flash, optional magic. From 23f1a253a71fbb79b239e4d1e34270b08ad5ce43 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 19:19:50 +0100 Subject: [PATCH 0707/1938] common: fix mix of spaces & tabs --- common/bucketsort.c | 76 +- common/bucketsort.h | 16 +- common/cmd.c | 42 +- common/crapto1/crapto1.c | 644 ++++---- common/crapto1/crapto1.h | 34 +- common/crapto1/crypto1.c | 194 +-- common/crc.c | 146 +- common/crc.h | 40 +- common/crc16.c | 252 ++-- common/crc16.h | 22 +- common/crc64.c | 12 +- common/default_version.c | 10 +- common/desfire.h | 132 +- common/i2c.c | 1056 ++++++------- common/i2c.h | 18 +- common/iso14443crc.c | 14 +- common/iso15693tools.c | 22 +- common/iso15693tools.h | 166 +- common/ldscript.common | 12 +- common/legic_prng.c | 48 +- common/lfdemod.c | 3072 +++++++++++++++++++------------------- common/lfdemod.h | 20 +- common/parity.h | 20 +- common/prng.c | 8 +- common/prng.h | 8 +- common/protocols.c | 202 +-- common/protocols.h | 766 +++++----- common/random.c | 12 +- common/tea.c | 74 +- common/usart.c | 92 +- common/usb_cdc.c | 1172 +++++++-------- common/wiegand.c | 244 +-- 32 files changed, 4323 insertions(+), 4323 deletions(-) diff --git a/common/bucketsort.c b/common/bucketsort.c index 162869e38..c42b8673f 100644 --- a/common/bucketsort.c +++ b/common/bucketsort.c @@ -1,47 +1,47 @@ #include "bucketsort.h" extern void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop, - uint32_t* const ostart, uint32_t* const ostop, - bucket_info_t *bucket_info, bucket_array_t bucket) + uint32_t* const ostart, uint32_t* const ostop, + bucket_info_t *bucket_info, bucket_array_t bucket) { - uint32_t *p1, *p2; - uint32_t *start[2]; - uint32_t *stop[2]; + uint32_t *p1, *p2; + uint32_t *start[2]; + uint32_t *stop[2]; - start[0] = estart; - stop[0] = estop; - start[1] = ostart; - stop[1] = ostop; + start[0] = estart; + stop[0] = estop; + start[1] = ostart; + stop[1] = ostop; - // init buckets to be empty - for (uint32_t i = 0; i < 2; i++) { - for (uint32_t j = 0x00; j <= 0xff; j++) { - bucket[i][j].bp = bucket[i][j].head; - } - } + // init buckets to be empty + for (uint32_t i = 0; i < 2; i++) { + for (uint32_t j = 0x00; j <= 0xff; j++) { + bucket[i][j].bp = bucket[i][j].head; + } + } - // sort the lists into the buckets based on the MSB (contribution bits) - for (uint32_t i = 0; i < 2; i++) { - for (p1 = start[i]; p1 <= stop[i]; p1++) { - uint32_t bucket_index = (*p1 & 0xff000000) >> 24; - *(bucket[i][bucket_index].bp++) = *p1; - } - } + // sort the lists into the buckets based on the MSB (contribution bits) + for (uint32_t i = 0; i < 2; i++) { + for (p1 = start[i]; p1 <= stop[i]; p1++) { + uint32_t bucket_index = (*p1 & 0xff000000) >> 24; + *(bucket[i][bucket_index].bp++) = *p1; + } + } - // write back intersecting buckets as sorted list. - // fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets. - uint32_t nonempty_bucket; - for (uint32_t i = 0; i < 2; i++) { - p1 = start[i]; - nonempty_bucket = 0; - for (uint32_t j = 0x00; j <= 0xff; j++) { - if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only - bucket_info->bucket_info[i][nonempty_bucket].head = p1; - for (p2 = bucket[i][j].head; p2 < bucket[i][j].bp; *p1++ = *p2++); - bucket_info->bucket_info[i][nonempty_bucket].tail = p1 - 1; - nonempty_bucket++; - } - } - bucket_info->numbuckets = nonempty_bucket; - } + // write back intersecting buckets as sorted list. + // fill in bucket_info with head and tail of the bucket contents in the list and number of non-empty buckets. + uint32_t nonempty_bucket; + for (uint32_t i = 0; i < 2; i++) { + p1 = start[i]; + nonempty_bucket = 0; + for (uint32_t j = 0x00; j <= 0xff; j++) { + if (bucket[0][j].bp != bucket[0][j].head && bucket[1][j].bp != bucket[1][j].head) { // non-empty intersecting buckets only + bucket_info->bucket_info[i][nonempty_bucket].head = p1; + for (p2 = bucket[i][j].head; p2 < bucket[i][j].bp; *p1++ = *p2++); + bucket_info->bucket_info[i][nonempty_bucket].tail = p1 - 1; + nonempty_bucket++; + } + } + bucket_info->numbuckets = nonempty_bucket; + } } diff --git a/common/bucketsort.h b/common/bucketsort.h index be504508a..30da87f2c 100644 --- a/common/bucketsort.h +++ b/common/bucketsort.h @@ -5,20 +5,20 @@ #include typedef struct bucket { - uint32_t *head; - uint32_t *bp; + uint32_t *head; + uint32_t *bp; } bucket_t; typedef bucket_t bucket_array_t[2][0x100]; typedef struct bucket_info { - struct { - uint32_t *head, *tail; - } bucket_info[2][0x100]; - uint32_t numbuckets; + struct { + uint32_t *head, *tail; + } bucket_info[2][0x100]; + uint32_t numbuckets; } bucket_info_t; void bucket_sort_intersect(uint32_t* const estart, uint32_t* const estop, - uint32_t* const ostart, uint32_t* const ostop, - bucket_info_t *bucket_info, bucket_array_t bucket); + uint32_t* const ostart, uint32_t* const ostop, + bucket_info_t *bucket_info, bucket_array_t bucket); #endif \ No newline at end of file diff --git a/common/cmd.c b/common/cmd.c index ebeaf4f7c..bc042b068 100644 --- a/common/cmd.c +++ b/common/cmd.c @@ -32,33 +32,33 @@ #include "cmd.h" uint8_t cmd_send(uint64_t cmd, uint64_t arg0, uint64_t arg1, uint64_t arg2, void* data, size_t len) { - UsbCommand txcmd; + UsbCommand txcmd; - for (size_t i=0; i < sizeof(UsbCommand); i++) - ((uint8_t*)&txcmd)[i] = 0x00; + for (size_t i=0; i < sizeof(UsbCommand); i++) + ((uint8_t*)&txcmd)[i] = 0x00; - // Compose the outgoing command frame - txcmd.cmd = cmd; - txcmd.arg[0] = arg0; - txcmd.arg[1] = arg1; - txcmd.arg[2] = arg2; + // Compose the outgoing command frame + txcmd.cmd = cmd; + txcmd.arg[0] = arg0; + txcmd.arg[1] = arg1; + txcmd.arg[2] = arg2; - // Add the (optional) content to the frame, with a maximum size of USB_CMD_DATA_SIZE - if (data && len) { - len = MIN(len, USB_CMD_DATA_SIZE); - for (size_t i=0; i */ @@ -26,9 +26,9 @@ static uint8_t filterlut[1 << 20]; static void __attribute__((constructor)) fill_lut() { - uint32_t i; - for(i = 0; i < 1 << 20; ++i) - filterlut[i] = filter(i); + uint32_t i; + for(i = 0; i < 1 << 20; ++i) + filterlut[i] = filter(i); } #define filter(x) (filterlut[(x) & 0xfffff]) #endif @@ -38,11 +38,11 @@ static void __attribute__((constructor)) fill_lut() */ static inline void update_contribution(uint32_t *item, const uint32_t mask1, const uint32_t mask2) { - uint32_t p = *item >> 25; + uint32_t p = *item >> 25; - p = p << 1 | evenparity32(*item & mask1); - p = p << 1 | evenparity32(*item & mask2); - *item = p << 24 | (*item & 0xffffff); + p = p << 1 | evenparity32(*item & mask1); + p = p << 1 | evenparity32(*item & mask2); + *item = p << 24 | (*item & 0xffffff); } /** extend_table @@ -50,83 +50,83 @@ static inline void update_contribution(uint32_t *item, const uint32_t mask1, con */ static inline void extend_table(uint32_t *tbl, uint32_t **end, int bit, int m1, int m2, uint32_t in) { - in <<= 24; - for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) - if(filter(*tbl) ^ filter(*tbl | 1)) { - *tbl |= filter(*tbl) ^ bit; - update_contribution(tbl, m1, m2); - *tbl ^= in; - } else if(filter(*tbl) == bit) { - *++*end = tbl[1]; - tbl[1] = tbl[0] | 1; - update_contribution(tbl, m1, m2); - *tbl++ ^= in; - update_contribution(tbl, m1, m2); - *tbl ^= in; - } else - *tbl-- = *(*end)--; + in <<= 24; + for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) + if(filter(*tbl) ^ filter(*tbl | 1)) { + *tbl |= filter(*tbl) ^ bit; + update_contribution(tbl, m1, m2); + *tbl ^= in; + } else if(filter(*tbl) == bit) { + *++*end = tbl[1]; + tbl[1] = tbl[0] | 1; + update_contribution(tbl, m1, m2); + *tbl++ ^= in; + update_contribution(tbl, m1, m2); + *tbl ^= in; + } else + *tbl-- = *(*end)--; } /** extend_table_simple * using a bit of the keystream extend the table of possible lfsr states */ static inline void extend_table_simple(uint32_t *tbl, uint32_t **end, int bit) { - for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) { - if(filter(*tbl) ^ filter(*tbl | 1)) { // replace - *tbl |= filter(*tbl) ^ bit; - } else if(filter(*tbl) == bit) { // insert - *++*end = *++tbl; - *tbl = tbl[-1] | 1; - } else { // drop - *tbl-- = *(*end)--; + for(*tbl <<= 1; tbl <= *end; *++tbl <<= 1) { + if(filter(*tbl) ^ filter(*tbl | 1)) { // replace + *tbl |= filter(*tbl) ^ bit; + } else if(filter(*tbl) == bit) { // insert + *++*end = *++tbl; + *tbl = tbl[-1] | 1; + } else { // drop + *tbl-- = *(*end)--; } - } + } } /** recover * recursively narrow down the search space, 4 bits of keystream at a time */ static struct Crypto1State* recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks, - uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem, - struct Crypto1State *sl, uint32_t in, bucket_array_t bucket) + uint32_t *e_head, uint32_t *e_tail, uint32_t eks, int rem, + struct Crypto1State *sl, uint32_t in, bucket_array_t bucket) { - uint32_t *o, *e; - bucket_info_t bucket_info; + uint32_t *o, *e; + bucket_info_t bucket_info; - if(rem == -1) { - for(e = e_head; e <= e_tail; ++e) { - *e = *e << 1 ^ evenparity32(*e & LF_POLY_EVEN) ^ !!(in & 4); - for(o = o_head; o <= o_tail; ++o, ++sl) { - sl->even = *o; - sl->odd = *e ^ evenparity32(*o & LF_POLY_ODD); - sl[1].odd = sl[1].even = 0; - } - } - return sl; - } + if(rem == -1) { + for(e = e_head; e <= e_tail; ++e) { + *e = *e << 1 ^ evenparity32(*e & LF_POLY_EVEN) ^ !!(in & 4); + for(o = o_head; o <= o_tail; ++o, ++sl) { + sl->even = *o; + sl->odd = *e ^ evenparity32(*o & LF_POLY_ODD); + sl[1].odd = sl[1].even = 0; + } + } + return sl; + } - for(uint32_t i = 0; i < 4 && rem--; i++) { - oks >>= 1; - eks >>= 1; - in >>= 2; - extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0); - if(o_head > o_tail) - return sl; + for(uint32_t i = 0; i < 4 && rem--; i++) { + oks >>= 1; + eks >>= 1; + in >>= 2; + extend_table(o_head, &o_tail, oks & 1, LF_POLY_EVEN << 1 | 1, LF_POLY_ODD << 1, 0); + if(o_head > o_tail) + return sl; - extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, in & 3); - if(e_head > e_tail) - return sl; - } + extend_table(e_head, &e_tail, eks & 1, LF_POLY_ODD, LF_POLY_EVEN << 1 | 1, in & 3); + if(e_head > e_tail) + return sl; + } - bucket_sort_intersect(e_head, e_tail, o_head, o_tail, &bucket_info, bucket); + bucket_sort_intersect(e_head, e_tail, o_head, o_tail, &bucket_info, bucket); - for (int i = bucket_info.numbuckets - 1; i >= 0; i--) { - sl = recover(bucket_info.bucket_info[1][i].head, bucket_info.bucket_info[1][i].tail, oks, - bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks, - rem, sl, in, bucket); - } + for (int i = bucket_info.numbuckets - 1; i >= 0; i--) { + sl = recover(bucket_info.bucket_info[1][i].head, bucket_info.bucket_info[1][i].tail, oks, + bucket_info.bucket_info[0][i].head, bucket_info.bucket_info[0][i].tail, eks, + rem, sl, in, bucket); + } - return sl; + return sl; } /** lfsr_recovery * recover the state of the lfsr given 32 bits of the keystream @@ -135,87 +135,87 @@ recover(uint32_t *o_head, uint32_t *o_tail, uint32_t oks, */ struct Crypto1State* lfsr_recovery32(uint32_t ks2, uint32_t in) { - struct Crypto1State *statelist; - uint32_t *odd_head = 0, *odd_tail = 0, oks = 0; - uint32_t *even_head = 0, *even_tail = 0, eks = 0; - int i; + struct Crypto1State *statelist; + uint32_t *odd_head = 0, *odd_tail = 0, oks = 0; + uint32_t *even_head = 0, *even_tail = 0, eks = 0; + int i; - // split the keystream into an odd and even part - for (i = 31; i >= 0; i -= 2) - oks = oks << 1 | BEBIT(ks2, i); - for (i = 30; i >= 0; i -= 2) - eks = eks << 1 | BEBIT(ks2, i); + // split the keystream into an odd and even part + for (i = 31; i >= 0; i -= 2) + oks = oks << 1 | BEBIT(ks2, i); + for (i = 30; i >= 0; i -= 2) + eks = eks << 1 | BEBIT(ks2, i); - odd_head = odd_tail = malloc(sizeof(uint32_t) << 21); - even_head = even_tail = malloc(sizeof(uint32_t) << 21); - statelist = malloc(sizeof(struct Crypto1State) << 18); - if (!odd_tail-- || !even_tail-- || !statelist) { - free(statelist); - statelist = 0; - goto out; - } + odd_head = odd_tail = malloc(sizeof(uint32_t) << 21); + even_head = even_tail = malloc(sizeof(uint32_t) << 21); + statelist = malloc(sizeof(struct Crypto1State) << 18); + if (!odd_tail-- || !even_tail-- || !statelist) { + free(statelist); + statelist = 0; + goto out; + } - statelist->odd = statelist->even = 0; + statelist->odd = statelist->even = 0; - // allocate memory for out of place bucket_sort - bucket_array_t bucket; + // allocate memory for out of place bucket_sort + bucket_array_t bucket; - for (uint32_t i = 0; i < 2; i++) { - for (uint32_t j = 0; j <= 0xff; j++) { - bucket[i][j].head = malloc(sizeof(uint32_t) << 14); - if (!bucket[i][j].head) { - goto out; - } - } - } + for (uint32_t i = 0; i < 2; i++) { + for (uint32_t j = 0; j <= 0xff; j++) { + bucket[i][j].head = malloc(sizeof(uint32_t) << 14); + if (!bucket[i][j].head) { + goto out; + } + } + } - // initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream - for(i = 1 << 20; i >= 0; --i) { - if(filter(i) == (oks & 1)) - *++odd_tail = i; - if(filter(i) == (eks & 1)) - *++even_tail = i; - } + // initialize statelists: add all possible states which would result into the rightmost 2 bits of the keystream + for(i = 1 << 20; i >= 0; --i) { + if(filter(i) == (oks & 1)) + *++odd_tail = i; + if(filter(i) == (eks & 1)) + *++even_tail = i; + } - // extend the statelists. Look at the next 8 Bits of the keystream (4 Bit each odd and even): - for(i = 0; i < 4; i++) { - extend_table_simple(odd_head, &odd_tail, (oks >>= 1) & 1); - extend_table_simple(even_head, &even_tail, (eks >>= 1) & 1); - } + // extend the statelists. Look at the next 8 Bits of the keystream (4 Bit each odd and even): + for(i = 0; i < 4; i++) { + extend_table_simple(odd_head, &odd_tail, (oks >>= 1) & 1); + extend_table_simple(even_head, &even_tail, (eks >>= 1) & 1); + } - // the statelists now contain all states which could have generated the last 10 Bits of the keystream. - // 22 bits to go to recover 32 bits in total. From now on, we need to take the "in" - // parameter into account. - in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping - recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket); + // the statelists now contain all states which could have generated the last 10 Bits of the keystream. + // 22 bits to go to recover 32 bits in total. From now on, we need to take the "in" + // parameter into account. + in = (in >> 16 & 0xff) | (in << 16) | (in & 0xff00); // Byte swapping + recover(odd_head, odd_tail, oks, even_head, even_tail, eks, 11, statelist, in << 1, bucket); out: - for (uint32_t i = 0; i < 2; i++) - for (uint32_t j = 0; j <= 0xff; j++) - free(bucket[i][j].head); - free(odd_head); - free(even_head); - return statelist; + for (uint32_t i = 0; i < 2; i++) + for (uint32_t j = 0; j <= 0xff; j++) + free(bucket[i][j].head); + free(odd_head); + free(even_head); + return statelist; } static const uint32_t S1[] = { 0x62141, 0x310A0, 0x18850, 0x0C428, 0x06214, - 0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83, - 0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA}; + 0x0310A, 0x85E30, 0xC69AD, 0x634D6, 0xB5CDE, 0xDE8DA, 0x6F46D, 0xB3C83, + 0x59E41, 0xA8995, 0xD027F, 0x6813F, 0x3409F, 0x9E6FA}; static const uint32_t S2[] = { 0x3A557B00, 0x5D2ABD80, 0x2E955EC0, 0x174AAF60, - 0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8, - 0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20, - 0x7EC7EE90, 0x7F63F748, 0x79117020}; + 0x0BA557B0, 0x05D2ABD8, 0x0449DE68, 0x048464B0, 0x42423258, 0x278192A8, + 0x156042D0, 0x0AB02168, 0x43F89B30, 0x61FC4D98, 0x765EAD48, 0x7D8FDD20, + 0x7EC7EE90, 0x7F63F748, 0x79117020}; static const uint32_t T1[] = { - 0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66, - 0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B, - 0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615, - 0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C}; + 0x4F37D, 0x279BE, 0x97A6A, 0x4BD35, 0x25E9A, 0x12F4D, 0x097A6, 0x80D66, + 0xC4006, 0x62003, 0xB56B4, 0x5AB5A, 0xA9318, 0xD0F39, 0x6879C, 0xB057B, + 0x582BD, 0x2C15E, 0x160AF, 0x8F6E2, 0xC3DC4, 0xE5857, 0x72C2B, 0x39615, + 0x98DBF, 0xC806A, 0xE0680, 0x70340, 0x381A0, 0x98665, 0x4C332, 0xA272C}; static const uint32_t T2[] = { 0x3C88B810, 0x5E445C08, 0x2982A580, 0x14C152C0, - 0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268, - 0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0, - 0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0, - 0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950, - 0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0}; + 0x4A60A960, 0x253054B0, 0x52982A58, 0x2FEC9EA8, 0x1156C4D0, 0x08AB6268, + 0x42F53AB0, 0x217A9D58, 0x161DC528, 0x0DAE6910, 0x46D73488, 0x25CB11C0, + 0x52E588E0, 0x6972C470, 0x34B96238, 0x5CFC3A98, 0x28DE96C8, 0x12CFC0E0, + 0x4967E070, 0x64B3F038, 0x74F97398, 0x7CDC3248, 0x38CE92A0, 0x1C674950, + 0x0E33A4A8, 0x01B959D0, 0x40DCACE8, 0x26CEDDF0}; static const uint32_t C1[] = { 0x846B5, 0x4235A, 0x211AD}; static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0}; /** Reverse 64 bits of keystream into possible cipher states @@ -223,69 +223,69 @@ static const uint32_t C2[] = { 0x1A822E0, 0x21A822E0, 0x21A822E0}; */ struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3) { - struct Crypto1State *statelist, *sl; - uint8_t oks[32], eks[32], hi[32]; - uint32_t low = 0, win = 0; - uint32_t *tail, table[1 << 16]; - int i, j; + struct Crypto1State *statelist, *sl; + uint8_t oks[32], eks[32], hi[32]; + uint32_t low = 0, win = 0; + uint32_t *tail, table[1 << 16]; + int i, j; - sl = statelist = malloc(sizeof(struct Crypto1State) << 4); - if(!sl) - return 0; - sl->odd = sl->even = 0; + sl = statelist = malloc(sizeof(struct Crypto1State) << 4); + if(!sl) + return 0; + sl->odd = sl->even = 0; - for(i = 30; i >= 0; i -= 2) { - oks[i >> 1] = BEBIT(ks2, i); - oks[16 + (i >> 1)] = BEBIT(ks3, i); - } - for(i = 31; i >= 0; i -= 2) { - eks[i >> 1] = BEBIT(ks2, i); - eks[16 + (i >> 1)] = BEBIT(ks3, i); - } + for(i = 30; i >= 0; i -= 2) { + oks[i >> 1] = BEBIT(ks2, i); + oks[16 + (i >> 1)] = BEBIT(ks3, i); + } + for(i = 31; i >= 0; i -= 2) { + eks[i >> 1] = BEBIT(ks2, i); + eks[16 + (i >> 1)] = BEBIT(ks3, i); + } - for(i = 0xfffff; i >= 0; --i) { - if (filter(i) != oks[0]) - continue; + for(i = 0xfffff; i >= 0; --i) { + if (filter(i) != oks[0]) + continue; - *(tail = table) = i; - for(j = 1; tail >= table && j < 29; ++j) - extend_table_simple(table, &tail, oks[j]); + *(tail = table) = i; + for(j = 1; tail >= table && j < 29; ++j) + extend_table_simple(table, &tail, oks[j]); - if(tail < table) - continue; + if(tail < table) + continue; - for(j = 0; j < 19; ++j) - low = low << 1 | evenparity32(i & S1[j]); - for(j = 0; j < 32; ++j) - hi[j] = evenparity32(i & T1[j]); + for(j = 0; j < 19; ++j) + low = low << 1 | evenparity32(i & S1[j]); + for(j = 0; j < 32; ++j) + hi[j] = evenparity32(i & T1[j]); - for(; tail >= table; --tail) { - for(j = 0; j < 3; ++j) { - *tail = *tail << 1; - *tail |= evenparity32((i & C1[j]) ^ (*tail & C2[j])); - if(filter(*tail) != oks[29 + j]) - goto continue2; - } + for(; tail >= table; --tail) { + for(j = 0; j < 3; ++j) { + *tail = *tail << 1; + *tail |= evenparity32((i & C1[j]) ^ (*tail & C2[j])); + if(filter(*tail) != oks[29 + j]) + goto continue2; + } - for(j = 0; j < 19; ++j) - win = win << 1 | evenparity32(*tail & S2[j]); + for(j = 0; j < 19; ++j) + win = win << 1 | evenparity32(*tail & S2[j]); - win ^= low; - for(j = 0; j < 32; ++j) { - win = win << 1 ^ hi[j] ^ evenparity32(*tail & T2[j]); - if(filter(win) != eks[j]) - goto continue2; - } + win ^= low; + for(j = 0; j < 32; ++j) { + win = win << 1 ^ hi[j] ^ evenparity32(*tail & T2[j]); + if(filter(win) != eks[j]) + goto continue2; + } - *tail = *tail << 1 | evenparity32(LF_POLY_EVEN & *tail); - sl->odd = *tail ^ evenparity32(LF_POLY_ODD & win); - sl->even = win; - ++sl; - sl->odd = sl->even = 0; - continue2:; - } - } - return statelist; + *tail = *tail << 1 | evenparity32(LF_POLY_EVEN & *tail); + sl->odd = *tail ^ evenparity32(LF_POLY_ODD & win); + sl->even = win; + ++sl; + sl->odd = sl->even = 0; + continue2:; + } + } + return statelist; } /** lfsr_rollback_bit @@ -293,37 +293,37 @@ struct Crypto1State* lfsr_recovery64(uint32_t ks2, uint32_t ks3) */ uint8_t lfsr_rollback_bit(struct Crypto1State *s, uint32_t in, int fb) { - int out; - uint8_t ret; - uint32_t t; + int out; + uint8_t ret; + uint32_t t; - s->odd &= 0xffffff; - t = s->odd, s->odd = s->even, s->even = t; + s->odd &= 0xffffff; + t = s->odd, s->odd = s->even, s->even = t; - out = s->even & 1; - out ^= LF_POLY_EVEN & (s->even >>= 1); - out ^= LF_POLY_ODD & s->odd; - out ^= !!in; - out ^= (ret = filter(s->odd)) & !!fb; + out = s->even & 1; + out ^= LF_POLY_EVEN & (s->even >>= 1); + out ^= LF_POLY_ODD & s->odd; + out ^= !!in; + out ^= (ret = filter(s->odd)) & !!fb; - s->even |= evenparity32(out) << 23; - return ret; + s->even |= evenparity32(out) << 23; + return ret; } /** lfsr_rollback_byte * Rollback the shift register in order to get previous states */ uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb) { - uint8_t ret = 0; - ret |= lfsr_rollback_bit(s, BIT(in, 7), fb) << 7; - ret |= lfsr_rollback_bit(s, BIT(in, 6), fb) << 6; - ret |= lfsr_rollback_bit(s, BIT(in, 5), fb) << 5; - ret |= lfsr_rollback_bit(s, BIT(in, 4), fb) << 4; - ret |= lfsr_rollback_bit(s, BIT(in, 3), fb) << 3; - ret |= lfsr_rollback_bit(s, BIT(in, 2), fb) << 2; - ret |= lfsr_rollback_bit(s, BIT(in, 1), fb) << 1; - ret |= lfsr_rollback_bit(s, BIT(in, 0), fb) << 0; - return ret; + uint8_t ret = 0; + ret |= lfsr_rollback_bit(s, BIT(in, 7), fb) << 7; + ret |= lfsr_rollback_bit(s, BIT(in, 6), fb) << 6; + ret |= lfsr_rollback_bit(s, BIT(in, 5), fb) << 5; + ret |= lfsr_rollback_bit(s, BIT(in, 4), fb) << 4; + ret |= lfsr_rollback_bit(s, BIT(in, 3), fb) << 3; + ret |= lfsr_rollback_bit(s, BIT(in, 2), fb) << 2; + ret |= lfsr_rollback_bit(s, BIT(in, 1), fb) << 1; + ret |= lfsr_rollback_bit(s, BIT(in, 0), fb) << 0; + return ret; } /** lfsr_rollback_word * Rollback the shift register in order to get previous states @@ -331,43 +331,43 @@ uint8_t lfsr_rollback_byte(struct Crypto1State *s, uint32_t in, int fb) uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) { - uint32_t ret = 0; - ret |= lfsr_rollback_bit(s, BEBIT(in, 31), fb) << (31 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 30), fb) << (30 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 29), fb) << (29 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 28), fb) << (28 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 27), fb) << (27 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 26), fb) << (26 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 25), fb) << (25 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 24), fb) << (24 ^ 24); + uint32_t ret = 0; + ret |= lfsr_rollback_bit(s, BEBIT(in, 31), fb) << (31 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 30), fb) << (30 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 29), fb) << (29 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 28), fb) << (28 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 27), fb) << (27 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 26), fb) << (26 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 25), fb) << (25 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 24), fb) << (24 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 23), fb) << (23 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 22), fb) << (22 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 21), fb) << (21 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 20), fb) << (20 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 19), fb) << (19 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 18), fb) << (18 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 17), fb) << (17 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 16), fb) << (16 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 23), fb) << (23 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 22), fb) << (22 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 21), fb) << (21 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 20), fb) << (20 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 19), fb) << (19 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 18), fb) << (18 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 17), fb) << (17 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 16), fb) << (16 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 15), fb) << (15 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 14), fb) << (14 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 13), fb) << (13 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 12), fb) << (12 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 11), fb) << (11 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 10), fb) << (10 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 9), fb) << (9 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 8), fb) << (8 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 15), fb) << (15 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 14), fb) << (14 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 13), fb) << (13 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 12), fb) << (12 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 11), fb) << (11 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 10), fb) << (10 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 9), fb) << (9 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 8), fb) << (8 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 7), fb) << (7 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 6), fb) << (6 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 5), fb) << (5 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 4), fb) << (4 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 3), fb) << (3 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 2), fb) << (2 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 1), fb) << (1 ^ 24); - ret |= lfsr_rollback_bit(s, BEBIT(in, 0), fb) << (0 ^ 24); - return ret; + ret |= lfsr_rollback_bit(s, BEBIT(in, 7), fb) << (7 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 6), fb) << (6 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 5), fb) << (5 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 4), fb) << (4 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 3), fb) << (3 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 2), fb) << (2 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 1), fb) << (1 ^ 24); + ret |= lfsr_rollback_bit(s, BEBIT(in, 0), fb) << (0 ^ 24); + return ret; } /** nonce_distance @@ -376,17 +376,17 @@ uint32_t lfsr_rollback_word(struct Crypto1State *s, uint32_t in, int fb) static uint16_t *dist = 0; int nonce_distance(uint32_t from, uint32_t to) { - uint16_t x, i; - if(!dist) { - dist = calloc(2 << 16, sizeof(uint8_t)); - if(!dist) - return -1; - for (x = i = 1; i; ++i) { - dist[(x & 0xff) << 8 | x >> 8] = i; - x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; - } - } - return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535; + uint16_t x, i; + if(!dist) { + dist = calloc(2 << 16, sizeof(uint8_t)); + if(!dist) + return -1; + for (x = i = 1; i; ++i) { + dist[(x & 0xff) << 8 | x >> 8] = i; + x = x >> 1 | (x ^ x >> 2 ^ x >> 3 ^ x >> 5) << 15; + } + } + return (65535 + dist[to >> 16] - dist[from >> 16]) % 65535; } /** validate_prng_nonce @@ -396,14 +396,14 @@ int nonce_distance(uint32_t from, uint32_t to) * false = hardend prng */ bool validate_prng_nonce(uint32_t nonce) { - // init prng table: - nonce_distance(nonce, nonce); - return ((65535 - dist[nonce >> 16] + dist[nonce & 0xffff]) % 65535) == 16; + // init prng table: + nonce_distance(nonce, nonce); + return ((65535 - dist[nonce >> 16] + dist[nonce & 0xffff]) % 65535) == 16; } static uint32_t fastfwd[2][8] = { - { 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB}, - { 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}}; + { 0, 0x4BC53, 0xECB1, 0x450E2, 0x25E29, 0x6E27A, 0x2B298, 0x60ECB}, + { 0, 0x1D962, 0x4BC53, 0x56531, 0xECB1, 0x135D3, 0x450E2, 0x58980}}; /** lfsr_prefix_ks * @@ -416,25 +416,25 @@ static uint32_t fastfwd[2][8] = { */ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) { - uint32_t *candidates = calloc(4 << 10, sizeof(uint8_t)); - if (!candidates) return 0; + uint32_t *candidates = calloc(4 << 10, sizeof(uint8_t)); + if (!candidates) return 0; - uint32_t c, entry; - int size = 0, i, good; + uint32_t c, entry; + int size = 0, i, good; - for (i = 0; i < 1 << 21; ++i) { - for (c = 0, good = 1; good && c < 8; ++c) { - entry = i ^ fastfwd[isodd][c]; - good &= (BIT(ks[c], isodd) == filter(entry >> 1)); - good &= (BIT(ks[c], isodd + 2) == filter(entry)); - } - if (good) - candidates[size++] = i; - } + for (i = 0; i < 1 << 21; ++i) { + for (c = 0, good = 1; good && c < 8; ++c) { + entry = i ^ fastfwd[isodd][c]; + good &= (BIT(ks[c], isodd) == filter(entry >> 1)); + good &= (BIT(ks[c], isodd + 2) == filter(entry)); + } + if (good) + candidates[size++] = i; + } - candidates[size] = -1; + candidates[size] = -1; - return candidates; + return candidates; } /** check_pfx_parity @@ -442,33 +442,33 @@ uint32_t *lfsr_prefix_ks(uint8_t ks[8], int isodd) */ static struct Crypto1State* check_pfx_parity(uint32_t prefix, uint32_t rresp, uint8_t parities[8][8], uint32_t odd, uint32_t even, struct Crypto1State* sl, uint32_t no_par) { - uint32_t ks1, nr, ks2, rr, ks3, c, good = 1; + uint32_t ks1, nr, ks2, rr, ks3, c, good = 1; - for(c = 0; good && c < 8; ++c) { - sl->odd = odd ^ fastfwd[1][c]; - sl->even = even ^ fastfwd[0][c]; + for(c = 0; good && c < 8; ++c) { + sl->odd = odd ^ fastfwd[1][c]; + sl->even = even ^ fastfwd[0][c]; - lfsr_rollback_bit(sl, 0, 0); - lfsr_rollback_bit(sl, 0, 0); + lfsr_rollback_bit(sl, 0, 0); + lfsr_rollback_bit(sl, 0, 0); - ks3 = lfsr_rollback_bit(sl, 0, 0); - ks2 = lfsr_rollback_word(sl, 0, 0); - ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1); + ks3 = lfsr_rollback_bit(sl, 0, 0); + ks2 = lfsr_rollback_word(sl, 0, 0); + ks1 = lfsr_rollback_word(sl, prefix | c << 5, 1); - if (no_par) - break; + if (no_par) + break; - nr = ks1 ^ (prefix | c << 5); - rr = ks2 ^ rresp; + nr = ks1 ^ (prefix | c << 5); + rr = ks2 ^ rresp; - good &= evenparity32(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); - good &= evenparity32(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); - good &= evenparity32(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8); - good &= evenparity32(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0); - good &= evenparity32(rr & 0x000000ff) ^ parities[c][7] ^ ks3; - } + good &= evenparity32(nr & 0x000000ff) ^ parities[c][3] ^ BIT(ks2, 24); + good &= evenparity32(rr & 0xff000000) ^ parities[c][4] ^ BIT(ks2, 16); + good &= evenparity32(rr & 0x00ff0000) ^ parities[c][5] ^ BIT(ks2, 8); + good &= evenparity32(rr & 0x0000ff00) ^ parities[c][6] ^ BIT(ks2, 0); + good &= evenparity32(rr & 0x000000ff) ^ parities[c][7] ^ ks3; + } - return sl + good; + return sl + good; } @@ -484,30 +484,30 @@ static struct Crypto1State* check_pfx_parity(uint32_t prefix, uint32_t rresp, ui struct Crypto1State* lfsr_common_prefix(uint32_t pfx, uint32_t rr, uint8_t ks[8], uint8_t par[8][8], uint32_t no_par) { - struct Crypto1State *statelist, *s; - uint32_t *odd, *even, *o, *e, top; + struct Crypto1State *statelist, *s; + uint32_t *odd, *even, *o, *e, top; - odd = lfsr_prefix_ks(ks, 1); - even = lfsr_prefix_ks(ks, 0); + odd = lfsr_prefix_ks(ks, 1); + even = lfsr_prefix_ks(ks, 0); - s = statelist = malloc((sizeof *statelist) << 24); // was << 20. Need more for no_par special attack. Enough??? - if (!s || !odd || !even) { - free(statelist); - statelist = 0; - goto out; - } + s = statelist = malloc((sizeof *statelist) << 24); // was << 20. Need more for no_par special attack. Enough??? + if (!s || !odd || !even) { + free(statelist); + statelist = 0; + goto out; + } - for (o = odd; *o + 1; ++o) - for (e = even; *e + 1; ++e) - for (top = 0; top < 64; ++top) { - *o += 1 << 21; - *e += (!(top & 7) + 1) << 21; - s = check_pfx_parity(pfx, rr, par, *o, *e, s, no_par); - } + for (o = odd; *o + 1; ++o) + for (e = even; *e + 1; ++e) + for (top = 0; top < 64; ++top) { + *o += 1 << 21; + *e += (!(top & 7) + 1) << 21; + s = check_pfx_parity(pfx, rr, par, *o, *e, s, no_par); + } - s->odd = s->even = 0; + s->odd = s->even = 0; out: - free(odd); - free(even); - return statelist; + free(odd); + free(even); + return statelist; } diff --git a/common/crapto1/crapto1.h b/common/crapto1/crapto1.h index 5abdaeb09..b51b2aa15 100644 --- a/common/crapto1/crapto1.h +++ b/common/crapto1/crapto1.h @@ -28,7 +28,7 @@ extern "C" { #endif struct Crypto1State {uint32_t odd, even;}; -#if defined(__arm__) && !defined(__linux__) && !defined(_WIN32) && !defined(__APPLE__) // bare metal ARM Proxmark lacks malloc()/free() +#if defined(__arm__) && !defined(__linux__) && !defined(_WIN32) && !defined(__APPLE__) // bare metal ARM Proxmark lacks malloc()/free() void crypto1_create(struct Crypto1State *s, uint64_t key); #else struct Crypto1State *crypto1_create(uint64_t key); @@ -53,15 +53,15 @@ uint32_t lfsr_rollback_word(struct Crypto1State* s, uint32_t in, int fb); int nonce_distance(uint32_t from, uint32_t to); extern bool validate_prng_nonce(uint32_t nonce); #define FOREACH_VALID_NONCE(N, FILTER, FSIZE)\ - uint32_t __n = 0,__M = 0, N = 0;\ - int __i;\ - for(; __n < 1 << 16; N = prng_successor(__M = ++__n, 16))\ - for(__i = FSIZE - 1; __i >= 0; __i--)\ - if(BIT(FILTER, __i) ^ evenparity32(__M & 0xFF01))\ - break;\ - else if(__i)\ - __M = prng_successor(__M, (__i == 7) ? 48 : 8);\ - else + uint32_t __n = 0,__M = 0, N = 0;\ + int __i;\ + for(; __n < 1 << 16; N = prng_successor(__M = ++__n, 16))\ + for(__i = FSIZE - 1; __i >= 0; __i--)\ + if(BIT(FILTER, __i) ^ evenparity32(__M & 0xFF01))\ + break;\ + else if(__i)\ + __M = prng_successor(__M, (__i == 7) ? 48 : 8);\ + else #define LF_POLY_ODD (0x29CE5C) #define LF_POLY_EVEN (0x870804) @@ -69,14 +69,14 @@ extern bool validate_prng_nonce(uint32_t nonce); #define BEBIT(x, n) BIT(x, (n) ^ 24) static inline int filter(uint32_t const x) { - uint32_t f; + uint32_t f; - f = 0xf22c0 >> (x & 0xf) & 16; - f |= 0x6c9c0 >> (x >> 4 & 0xf) & 8; - f |= 0x3c8b0 >> (x >> 8 & 0xf) & 4; - f |= 0x1e458 >> (x >> 12 & 0xf) & 2; - f |= 0x0d938 >> (x >> 16 & 0xf) & 1; - return BIT(0xEC57E80A, f); + f = 0xf22c0 >> (x & 0xf) & 16; + f |= 0x6c9c0 >> (x >> 4 & 0xf) & 8; + f |= 0x3c8b0 >> (x >> 8 & 0xf) & 4; + f |= 0x1e458 >> (x >> 12 & 0xf) & 2; + f |= 0x0d938 >> (x >> 16 & 0xf) & 1; + return BIT(0xEC57E80A, f); } #ifdef __cplusplus } diff --git a/common/crapto1/crypto1.c b/common/crapto1/crypto1.c index 034d92215..f4147bf4f 100644 --- a/common/crapto1/crypto1.c +++ b/common/crapto1/crypto1.c @@ -1,21 +1,21 @@ /* crypto1.c - 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 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. + 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, US + 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, US - Copyright (C) 2008-2008 bla + Copyright (C) 2008-2008 bla */ #include "crapto1.h" @@ -23,121 +23,121 @@ #include "parity.h" #define SWAPENDIAN(x)\ - (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) + (x = (x >> 8 & 0xff00ff) | (x & 0xff00ff) << 8, x = x >> 16 | x << 16) -#if defined(__arm__) && !defined(__linux__) && !defined(_WIN32) && !defined(__APPLE__) // bare metal ARM Proxmark lacks malloc()/free() +#if defined(__arm__) && !defined(__linux__) && !defined(_WIN32) && !defined(__APPLE__) // bare metal ARM Proxmark lacks malloc()/free() void crypto1_create(struct Crypto1State *s, uint64_t key) { - int i; + int i; - for(i = 47;s && i > 0; i -= 2) { - s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7); - s->even = s->even << 1 | BIT(key, i ^ 7); - } - return; + for(i = 47;s && i > 0; i -= 2) { + s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7); + s->even = s->even << 1 | BIT(key, i ^ 7); + } + return; } void crypto1_destroy(struct Crypto1State *state) { - state->odd = 0; - state->even = 0; + state->odd = 0; + state->even = 0; } #else struct Crypto1State * crypto1_create(uint64_t key) { - struct Crypto1State *s = malloc(sizeof(*s)); - if ( !s ) return NULL; + struct Crypto1State *s = malloc(sizeof(*s)); + if ( !s ) return NULL; - s->odd = s->even = 0; + s->odd = s->even = 0; - int i; - for(i = 47; i > 0; i -= 2) { - s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7); - s->even = s->even << 1 | BIT(key, i ^ 7); - } - return s; + int i; + for(i = 47; i > 0; i -= 2) { + s->odd = s->odd << 1 | BIT(key, (i - 1) ^ 7); + s->even = s->even << 1 | BIT(key, i ^ 7); + } + return s; } void crypto1_destroy(struct Crypto1State *state) { - free(state); + free(state); } #endif void crypto1_get_lfsr(struct Crypto1State *state, uint64_t *lfsr) { - int i; - for(*lfsr = 0, i = 23; i >= 0; --i) { - *lfsr = *lfsr << 1 | BIT(state->odd, i ^ 3); - *lfsr = *lfsr << 1 | BIT(state->even, i ^ 3); - } + int i; + for(*lfsr = 0, i = 23; i >= 0; --i) { + *lfsr = *lfsr << 1 | BIT(state->odd, i ^ 3); + *lfsr = *lfsr << 1 | BIT(state->even, i ^ 3); + } } uint8_t crypto1_bit(struct Crypto1State *s, uint8_t in, int is_encrypted) { - uint32_t feedin, t; - uint8_t ret = filter(s->odd); + uint32_t feedin, t; + uint8_t ret = filter(s->odd); - feedin = ret & !!is_encrypted; - feedin ^= !!in; - feedin ^= LF_POLY_ODD & s->odd; - feedin ^= LF_POLY_EVEN & s->even; - s->even = s->even << 1 | evenparity32(feedin); + feedin = ret & !!is_encrypted; + feedin ^= !!in; + feedin ^= LF_POLY_ODD & s->odd; + feedin ^= LF_POLY_EVEN & s->even; + s->even = s->even << 1 | evenparity32(feedin); - t = s->odd; - s->odd = s->even; - s->even = t; + t = s->odd; + s->odd = s->even; + s->even = t; - return ret; + return ret; } uint8_t crypto1_byte(struct Crypto1State *s, uint8_t in, int is_encrypted) { - uint8_t ret = 0; - ret |= crypto1_bit(s, BIT(in, 0), is_encrypted) << 0; - ret |= crypto1_bit(s, BIT(in, 1), is_encrypted) << 1; - ret |= crypto1_bit(s, BIT(in, 2), is_encrypted) << 2; - ret |= crypto1_bit(s, BIT(in, 3), is_encrypted) << 3; - ret |= crypto1_bit(s, BIT(in, 4), is_encrypted) << 4; - ret |= crypto1_bit(s, BIT(in, 5), is_encrypted) << 5; - ret |= crypto1_bit(s, BIT(in, 6), is_encrypted) << 6; - ret |= crypto1_bit(s, BIT(in, 7), is_encrypted) << 7; - return ret; + uint8_t ret = 0; + ret |= crypto1_bit(s, BIT(in, 0), is_encrypted) << 0; + ret |= crypto1_bit(s, BIT(in, 1), is_encrypted) << 1; + ret |= crypto1_bit(s, BIT(in, 2), is_encrypted) << 2; + ret |= crypto1_bit(s, BIT(in, 3), is_encrypted) << 3; + ret |= crypto1_bit(s, BIT(in, 4), is_encrypted) << 4; + ret |= crypto1_bit(s, BIT(in, 5), is_encrypted) << 5; + ret |= crypto1_bit(s, BIT(in, 6), is_encrypted) << 6; + ret |= crypto1_bit(s, BIT(in, 7), is_encrypted) << 7; + return ret; } uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) { - uint32_t ret = 0; - ret |= crypto1_bit(s, BEBIT(in, 0), is_encrypted) << (0 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 1), is_encrypted) << (1 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 2), is_encrypted) << (2 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 3), is_encrypted) << (3 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 4), is_encrypted) << (4 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 5), is_encrypted) << (5 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 6), is_encrypted) << (6 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 7), is_encrypted) << (7 ^ 24); + uint32_t ret = 0; + ret |= crypto1_bit(s, BEBIT(in, 0), is_encrypted) << (0 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 1), is_encrypted) << (1 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 2), is_encrypted) << (2 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 3), is_encrypted) << (3 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 4), is_encrypted) << (4 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 5), is_encrypted) << (5 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 6), is_encrypted) << (6 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 7), is_encrypted) << (7 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 8), is_encrypted) << (8 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 9), is_encrypted) << (9 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 10), is_encrypted) << (10 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 11), is_encrypted) << (11 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 12), is_encrypted) << (12 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 13), is_encrypted) << (13 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 14), is_encrypted) << (14 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 15), is_encrypted) << (15 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 8), is_encrypted) << (8 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 9), is_encrypted) << (9 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 10), is_encrypted) << (10 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 11), is_encrypted) << (11 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 12), is_encrypted) << (12 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 13), is_encrypted) << (13 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 14), is_encrypted) << (14 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 15), is_encrypted) << (15 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 16), is_encrypted) << (16 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 17), is_encrypted) << (17 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 18), is_encrypted) << (18 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 19), is_encrypted) << (19 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 20), is_encrypted) << (20 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 21), is_encrypted) << (21 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 22), is_encrypted) << (22 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 23), is_encrypted) << (23 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 16), is_encrypted) << (16 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 17), is_encrypted) << (17 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 18), is_encrypted) << (18 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 19), is_encrypted) << (19 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 20), is_encrypted) << (20 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 21), is_encrypted) << (21 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 22), is_encrypted) << (22 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 23), is_encrypted) << (23 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 24), is_encrypted) << (24 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 25), is_encrypted) << (25 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 26), is_encrypted) << (26 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 27), is_encrypted) << (27 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 28), is_encrypted) << (28 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 29), is_encrypted) << (29 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 30), is_encrypted) << (30 ^ 24); - ret |= crypto1_bit(s, BEBIT(in, 31), is_encrypted) << (31 ^ 24); - return ret; + ret |= crypto1_bit(s, BEBIT(in, 24), is_encrypted) << (24 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 25), is_encrypted) << (25 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 26), is_encrypted) << (26 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 27), is_encrypted) << (27 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 28), is_encrypted) << (28 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 29), is_encrypted) << (29 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 30), is_encrypted) << (30 ^ 24); + ret |= crypto1_bit(s, BEBIT(in, 31), is_encrypted) << (31 ^ 24); + return ret; } /* prng_successor @@ -145,9 +145,9 @@ uint32_t crypto1_word(struct Crypto1State *s, uint32_t in, int is_encrypted) */ uint32_t prng_successor(uint32_t x, uint32_t n) { - SWAPENDIAN(x); - while(n--) - x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; + SWAPENDIAN(x); + while(n--) + x = x >> 1 | (x >> 16 ^ x >> 18 ^ x >> 19 ^ x >> 21) << 31; - return SWAPENDIAN(x); + return SWAPENDIAN(x); } diff --git a/common/crc.c b/common/crc.c index 4097fdd48..b91eea505 100644 --- a/common/crc.c +++ b/common/crc.c @@ -10,118 +10,118 @@ #include "crc.h" void crc_init_ref(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor, bool refin, bool refout) { - crc_init(crc, order, polynom, initial_value, final_xor); - crc->refin = refin; - crc->refout = refout; - crc_clear(crc); + crc_init(crc, order, polynom, initial_value, final_xor); + crc->refin = refin; + crc->refout = refout; + crc_clear(crc); } void crc_init(crc_t *crc, int order, uint32_t polynom, uint32_t initial_value, uint32_t final_xor) { - crc->order = order; - crc->topbit = BITMASK( order-1 ); - crc->polynom = polynom; - crc->initial_value = initial_value; - crc->final_xor = final_xor; - crc->mask = (1L<refin = false; - crc->refout = false; - crc_clear(crc); + crc->order = order; + crc->topbit = BITMASK( order-1 ); + crc->polynom = polynom; + crc->initial_value = initial_value; + crc->final_xor = final_xor; + crc->mask = (1L<refin = false; + crc->refout = false; + crc_clear(crc); } void crc_clear(crc_t *crc) { - crc->state = crc->initial_value & crc->mask; - if (crc->refin) - crc->state = reflect(crc->state, crc->order); + crc->state = crc->initial_value & crc->mask; + if (crc->refin) + crc->state = reflect(crc->state, crc->order); } void crc_update2(crc_t *crc, uint32_t data, int data_width){ - if (crc->refin) - data = reflect(data, data_width); + if (crc->refin) + data = reflect(data, data_width); - // Bring the next byte into the remainder. - crc->state ^= data << (crc->order - data_width); + // Bring the next byte into the remainder. + crc->state ^= data << (crc->order - data_width); - for( uint8_t bit = data_width; bit > 0; --bit) { + for( uint8_t bit = data_width; bit > 0; --bit) { - if (crc->state & crc->topbit) - crc->state = (crc->state << 1) ^ crc->polynom; - else - crc->state = (crc->state << 1); - } + if (crc->state & crc->topbit) + crc->state = (crc->state << 1) ^ crc->polynom; + else + crc->state = (crc->state << 1); + } } void crc_update(crc_t *crc, uint32_t data, int data_width) { - if (crc->refin) - data = reflect(data, data_width); + if (crc->refin) + data = reflect(data, data_width); - int i; - for(i=0; istate; - crc->state = crc->state >> 1; - if( (oldstate^data) & 1 ) { - crc->state ^= crc->polynom; - } - data >>= 1; - } + int i; + for(i=0; istate; + crc->state = crc->state >> 1; + if( (oldstate^data) & 1 ) { + crc->state ^= crc->polynom; + } + data >>= 1; + } } uint32_t crc_finish(crc_t *crc) { - uint32_t val = crc->state; - if (crc->refout) - val = reflect(val, crc->order); - return ( val ^ crc->final_xor ) & crc->mask; + uint32_t val = crc->state; + if (crc->refout) + val = reflect(val, crc->order); + return ( val ^ crc->final_xor ) & crc->mask; } /* static void print_crc(crc_t *crc) { - printf(" Order %d\n Poly %x\n Init %x\n Final %x\n Mask %x\n topbit %x\n RefIn %s\n RefOut %s\n State %x\n", - crc->order, - crc->polynom, - crc->initial_value, - crc->final_xor, - crc->mask, - crc->topbit, - (crc->refin) ? "TRUE":"FALSE", - (crc->refout) ? "TRUE":"FALSE", - crc->state - ); + printf(" Order %d\n Poly %x\n Init %x\n Final %x\n Mask %x\n topbit %x\n RefIn %s\n RefOut %s\n State %x\n", + crc->order, + crc->polynom, + crc->initial_value, + crc->final_xor, + crc->mask, + crc->topbit, + (crc->refin) ? "TRUE":"FALSE", + (crc->refout) ? "TRUE":"FALSE", + crc->state + ); } */ // width=8 poly=0x31 init=0x00 refin=true refout=true xorout=0x00 check=0xA1 name="CRC-8/MAXIM" uint32_t CRC8Maxim(uint8_t *buff, size_t size) { - crc_t crc; - crc_init_ref(&crc, 8, 0x31, 0, 0, true, true); - for ( int i=0; i < size; ++i) - crc_update2(&crc, buff[i], 8); - return crc_finish(&crc); + crc_t crc; + crc_init_ref(&crc, 8, 0x31, 0, 0, true, true); + for ( int i=0; i < size; ++i) + crc_update2(&crc, buff[i], 8); + return crc_finish(&crc); } // width=8 poly=0x1d, init=0xc7 (0xe3 - WRONG! but it mentioned in MAD datasheet) refin=false refout=false xorout=0x00 name="CRC-8/MIFARE-MAD" uint32_t CRC8Mad(uint8_t *buff, size_t size) { - crc_t crc; - crc_init_ref(&crc, 8, 0x1d, 0xc7, 0, false, false); - for ( int i = 0; i < size; ++i) - crc_update2(&crc, buff[i], 8); - return crc_finish(&crc); + crc_t crc; + crc_init_ref(&crc, 8, 0x1d, 0xc7, 0, false, false); + for ( int i = 0; i < size; ++i) + crc_update2(&crc, buff[i], 8); + return crc_finish(&crc); } // width=4 poly=0xC, reversed poly=0x7 init=0x5 refin=true refout=true xorout=0x0000 check= name="CRC-4/LEGIC" uint32_t CRC4Legic(uint8_t *cmd, size_t size) { - crc_t crc; - crc_init_ref(&crc, 4, 0x19 >> 1, 0x5, 0, true, true); - crc_update2(&crc, 1, 1); /* CMD_READ */ - crc_update2(&crc, cmd[0], 8); - crc_update2(&crc, cmd[1], 8); - return reflect(crc_finish(&crc), 4); + crc_t crc; + crc_init_ref(&crc, 4, 0x19 >> 1, 0x5, 0, true, true); + crc_update2(&crc, 1, 1); /* CMD_READ */ + crc_update2(&crc, cmd[0], 8); + crc_update2(&crc, cmd[1], 8); + return reflect(crc_finish(&crc), 4); } // width=8 poly=0x63, reversed poly=0x8D init=0x55 refin=true refout=true xorout=0x0000 check=0xC6 name="CRC-8/LEGIC" // the CRC needs to be reversed before returned. uint32_t CRC8Legic(uint8_t *buff, size_t size) { - crc_t crc; - crc_init_ref(&crc, 8, 0x63, 0x55, 0, true, true); - for ( int i = 0; i < size; ++i) - crc_update2(&crc, buff[i], 8); - return reflect8(crc_finish(&crc)); + crc_t crc; + crc_init_ref(&crc, 8, 0x63, 0x55, 0, true, true); + for ( int i = 0; i < size; ++i) + crc_update2(&crc, buff[i], 8); + return reflect8(crc_finish(&crc)); } \ No newline at end of file diff --git a/common/crc.h b/common/crc.h index 015fbf60c..5a15563b7 100644 --- a/common/crc.h +++ b/common/crc.h @@ -9,19 +9,19 @@ #ifndef __CRC_H #define __CRC_H -#include "common.h" //stdint, stddef, stdbool -#include "util.h" // reflect, bswap_16 +#include "common.h" //stdint, stddef, stdbool +#include "util.h" // reflect, bswap_16 typedef struct crc { - uint32_t state; - int order; - uint32_t polynom; - uint32_t initial_value; - uint32_t final_xor; - uint32_t mask; - int topbit; - bool refin; /* Parameter: Reflect input bytes? */ - bool refout; /* Parameter: Reflect output CRC? */ + uint32_t state; + int order; + uint32_t polynom; + uint32_t initial_value; + uint32_t final_xor; + uint32_t mask; + int topbit; + bool refin; /* Parameter: Reflect input bytes? */ + bool refout; /* Parameter: Reflect output CRC? */ } crc_t; /* Initialize a crc structure. order is the order of the polynom, e.g. 32 for a CRC-32 @@ -64,14 +64,14 @@ uint32_t CRC8Legic(uint8_t *buff, size_t size); /* Static initialization of a crc structure */ #define CRC_INITIALIZER(_order, _polynom, _initial_value, _final_xor) { \ - .state = ((_initial_value) & ((1L<<(_order))-1)), \ - .order = (_order), \ - .polynom = (_polynom), \ - .initial_value = (_initial_value), \ - .final_xor = (_final_xor), \ - .mask = ((1L<<(_order))-1) \ - .refin = false, \ - .refout = false \ - } + .state = ((_initial_value) & ((1L<<(_order))-1)), \ + .order = (_order), \ + .polynom = (_polynom), \ + .initial_value = (_initial_value), \ + .final_xor = (_final_xor), \ + .mask = ((1L<<(_order))-1) \ + .refin = false, \ + .refout = false \ + } #endif /* __CRC_H */ diff --git a/common/crc16.c b/common/crc16.c index b6145013b..af3ca2676 100644 --- a/common/crc16.c +++ b/common/crc16.c @@ -13,125 +13,125 @@ static CrcType_t crc_type = CRC_NONE; void init_table(CrcType_t ct) { - // same crc algo, and initialised already - if ( ct == crc_type && crc_table_init) - return; + // same crc algo, and initialised already + if ( ct == crc_type && crc_table_init) + return; - // not the same crc algo. reset table. - if ( ct != crc_type) - reset_table(); + // not the same crc algo. reset table. + if ( ct != crc_type) + reset_table(); - crc_type = ct; + crc_type = ct; - switch (ct) { - case CRC_14443_A: - case CRC_14443_B: - case CRC_15693: - case CRC_ICLASS: generate_table(CRC16_POLY_CCITT, true); break; - case CRC_FELICA: generate_table(CRC16_POLY_CCITT, false); break; - case CRC_LEGIC: generate_table(CRC16_POLY_LEGIC, true); break; - case CRC_CCITT: generate_table(CRC16_POLY_CCITT, false); break; - case CRC_KERMIT: generate_table(CRC16_POLY_CCITT, true); break; - default: - crc_table_init = false; - crc_type = CRC_NONE; - break; - } + switch (ct) { + case CRC_14443_A: + case CRC_14443_B: + case CRC_15693: + case CRC_ICLASS: generate_table(CRC16_POLY_CCITT, true); break; + case CRC_FELICA: generate_table(CRC16_POLY_CCITT, false); break; + case CRC_LEGIC: generate_table(CRC16_POLY_LEGIC, true); break; + case CRC_CCITT: generate_table(CRC16_POLY_CCITT, false); break; + case CRC_KERMIT: generate_table(CRC16_POLY_CCITT, true); break; + default: + crc_table_init = false; + crc_type = CRC_NONE; + break; + } } void generate_table( uint16_t polynomial, bool refin) { - uint16_t i, j, crc, c; + uint16_t i, j, crc, c; - for (i = 0; i < 256; i++) { - crc = 0; - if (refin) - c = reflect8(i) << 8; - else - c = i << 8; + for (i = 0; i < 256; i++) { + crc = 0; + if (refin) + c = reflect8(i) << 8; + else + c = i << 8; for (j = 0; j < 8; j++) { if ( (crc ^ c) & 0x8000 ) - crc = ( crc << 1 ) ^ polynomial; + crc = ( crc << 1 ) ^ polynomial; else - crc = crc << 1; + crc = crc << 1; c = c << 1; } - if (refin) - crc = reflect16(crc); + if (refin) + crc = reflect16(crc); - crc_table[i] = crc; - } + crc_table[i] = crc; + } crc_table_init = true; } void reset_table(void) { - memset(crc_table, 0, sizeof(crc_table)); - crc_table_init = false; - crc_type = CRC_NONE; + memset(crc_table, 0, sizeof(crc_table)); + crc_table_init = false; + crc_type = CRC_NONE; } // table lookup LUT solution uint16_t crc16_fast(uint8_t const *d, size_t n, uint16_t initval, bool refin, bool refout) { - // fast lookup table algorithm without augmented zero bytes, e.g. used in pkzip. - // only usable with polynom orders of 8, 16, 24 or 32. - if (n == 0) + // fast lookup table algorithm without augmented zero bytes, e.g. used in pkzip. + // only usable with polynom orders of 8, 16, 24 or 32. + if (n == 0) return (~initval); - uint16_t crc = initval; + uint16_t crc = initval; - if (refin) - crc = reflect16(crc); + if (refin) + crc = reflect16(crc); - if (!refin) - while (n--) crc = (crc << 8) ^ crc_table[ ((crc >> 8) ^ *d++) & 0xFF ]; - else - while (n--) crc = (crc >> 8) ^ crc_table[ (crc & 0xFF) ^ *d++]; + if (!refin) + while (n--) crc = (crc << 8) ^ crc_table[ ((crc >> 8) ^ *d++) & 0xFF ]; + else + while (n--) crc = (crc >> 8) ^ crc_table[ (crc & 0xFF) ^ *d++]; - if (refout^refin) - crc = reflect16(crc); + if (refout^refin) + crc = reflect16(crc); - return crc; + return crc; } // bit looped solution TODO REMOVED uint16_t update_crc16_ex( uint16_t crc, uint8_t c, uint16_t polynomial ) { - uint16_t i, v, tmp = 0; + uint16_t i, v, tmp = 0; - v = (crc ^ c) & 0xff; + v = (crc ^ c) & 0xff; - for (i = 0; i < 8; i++) { + for (i = 0; i < 8; i++) { - if ( (tmp ^ v) & 1 ) - tmp = ( tmp >> 1 ) ^ polynomial; - else - tmp >>= 1; + if ( (tmp ^ v) & 1 ) + tmp = ( tmp >> 1 ) ^ polynomial; + else + tmp >>= 1; - v >>= 1; - } - return ((crc >> 8) ^ tmp) & 0xffff; + v >>= 1; + } + return ((crc >> 8) ^ tmp) & 0xffff; } uint16_t update_crc16( uint16_t crc, uint8_t c ) { - return update_crc16_ex( crc, c, CRC16_POLY_CCITT); + return update_crc16_ex( crc, c, CRC16_POLY_CCITT); } // two ways. msb or lsb loop. uint16_t crc16(uint8_t const *d, size_t length, uint16_t remainder, uint16_t polynomial, bool refin, bool refout) { - if (length == 0) + if (length == 0) return (~remainder); - uint8_t c; + uint8_t c; for (uint32_t i = 0; i < length; ++i) { - c = d[i]; - if (refin) c = reflect8(c); + c = d[i]; + if (refin) c = reflect8(c); - // xor in at msb + // xor in at msb remainder ^= (c << 8); - // 8 iteration loop + // 8 iteration loop for (uint8_t j = 8; j; --j) { if (remainder & 0x8000) { remainder = (remainder << 1) ^ polynomial; @@ -140,58 +140,58 @@ uint16_t crc16(uint8_t const *d, size_t length, uint16_t remainder, uint16_t pol } } } - if (refout) - remainder = reflect16(remainder); + if (refout) + remainder = reflect16(remainder); return remainder; } void compute_crc(CrcType_t ct, const uint8_t *d, size_t n, uint8_t *first, uint8_t *second) { - // can't calc a crc on less than 1 byte - if ( n == 0 ) return; + // can't calc a crc on less than 1 byte + if ( n == 0 ) return; - init_table(ct); + init_table(ct); - uint16_t crc = 0; - switch (ct) { - case CRC_14443_A: crc = crc16_a(d, n); break; - case CRC_14443_B: - case CRC_15693: crc = crc16_x25(d, n); break; - case CRC_ICLASS: crc = crc16_iclass(d, n); break; - case CRC_FELICA:crc = crc16_xmodem(d, n); break; - //case CRC_LEGIC: - case CRC_CCITT: crc = crc16_ccitt(d, n); break; - case CRC_KERMIT: crc = crc16_kermit(d, n); break; - default: break; - } - *first = (crc & 0xFF); + uint16_t crc = 0; + switch (ct) { + case CRC_14443_A: crc = crc16_a(d, n); break; + case CRC_14443_B: + case CRC_15693: crc = crc16_x25(d, n); break; + case CRC_ICLASS: crc = crc16_iclass(d, n); break; + case CRC_FELICA:crc = crc16_xmodem(d, n); break; + //case CRC_LEGIC: + case CRC_CCITT: crc = crc16_ccitt(d, n); break; + case CRC_KERMIT: crc = crc16_kermit(d, n); break; + default: break; + } + *first = (crc & 0xFF); *second = ((crc >> 8) & 0xFF); } uint16_t crc(CrcType_t ct, const uint8_t *d, size_t n) { - // can't calc a crc on less than 3 byte. (1byte + 2 crc bytes) - if ( n < 3 ) return 0; + // can't calc a crc on less than 3 byte. (1byte + 2 crc bytes) + if ( n < 3 ) return 0; - init_table(ct); - switch (ct) { - case CRC_14443_A: return crc16_a(d, n); - case CRC_14443_B: - case CRC_15693: return crc16_x25(d, n); - case CRC_ICLASS: return crc16_iclass(d, n); - case CRC_FELICA: return crc16_xmodem(d, n); - //case CRC_LEGIC: - case CRC_CCITT: return crc16_ccitt(d, n); - case CRC_KERMIT: return crc16_kermit(d, n); - default: break; - } - return 0; + init_table(ct); + switch (ct) { + case CRC_14443_A: return crc16_a(d, n); + case CRC_14443_B: + case CRC_15693: return crc16_x25(d, n); + case CRC_ICLASS: return crc16_iclass(d, n); + case CRC_FELICA: return crc16_xmodem(d, n); + //case CRC_LEGIC: + case CRC_CCITT: return crc16_ccitt(d, n); + case CRC_KERMIT: return crc16_kermit(d, n); + default: break; + } + return 0; } // check CRC // ct crc type -// d buffer with data -// n length (including crc) +// d buffer with data +// n length (including crc) // // This function uses the message + crc bytes in order to compare the "residue" afterwards. // crc16 algos like CRC-A become 0x000 @@ -199,39 +199,39 @@ uint16_t crc(CrcType_t ct, const uint8_t *d, size_t n) { // If calculated with crc bytes, the residue should be 0xF0B8 bool check_crc(CrcType_t ct, const uint8_t *d, size_t n) { - // can't calc a crc on less than 3 byte. (1byte + 2 crc bytes) - if ( n < 3 ) return false; + // can't calc a crc on less than 3 byte. (1byte + 2 crc bytes) + if ( n < 3 ) return false; - init_table(ct); + init_table(ct); - switch (ct) { - case CRC_14443_A: return (crc16_a(d, n) == 0); - case CRC_14443_B: return (crc16_x25(d, n) == X25_CRC_CHECK); - case CRC_15693: return (crc16_x25(d, n) == X25_CRC_CHECK); - case CRC_ICLASS: return (crc16_iclass(d, n) == 0); - case CRC_FELICA: return (crc16_xmodem(d, n) == 0); - //case CRC_LEGIC: - case CRC_CCITT: return (crc16_ccitt(d, n) == 0); - default: break; - } - return false; + switch (ct) { + case CRC_14443_A: return (crc16_a(d, n) == 0); + case CRC_14443_B: return (crc16_x25(d, n) == X25_CRC_CHECK); + case CRC_15693: return (crc16_x25(d, n) == X25_CRC_CHECK); + case CRC_ICLASS: return (crc16_iclass(d, n) == 0); + case CRC_FELICA: return (crc16_xmodem(d, n) == 0); + //case CRC_LEGIC: + case CRC_CCITT: return (crc16_ccitt(d, n) == 0); + default: break; + } + return false; } // poly=0x1021 init=0xffff refin=false refout=false xorout=0x0000 check=0x29b1 residue=0x0000 name="CRC-16/CCITT-FALSE" uint16_t crc16_ccitt(uint8_t const *d, size_t n) { - return crc16_fast(d, n, 0xffff, false, false); + return crc16_fast(d, n, 0xffff, false, false); } // FDX-B ISO11784/85) uses KERMIT // poly=0x1021 init=0x0000 refin=true refout=true xorout=0x0000 name="KERMIT" uint16_t crc16_kermit(uint8_t const *d, size_t n) { - return crc16_fast(d, n, 0x0000, true, true); + return crc16_fast(d, n, 0x0000, true, true); } // FeliCa uses XMODEM // poly=0x1021 init=0x0000 refin=false refout=false xorout=0x0000 name="XMODEM" uint16_t crc16_xmodem(uint8_t const *d, size_t n) { - return crc16_fast(d, n, 0x0000, false, false); + return crc16_fast(d, n, 0x0000, false, false); } // Following standards uses X-25 @@ -240,14 +240,14 @@ uint16_t crc16_xmodem(uint8_t const *d, size_t n) { // ISO/IEC 13239 (formerly ISO/IEC 3309) // poly=0x1021 init=0xffff refin=true refout=true xorout=0xffff name="X-25" uint16_t crc16_x25(uint8_t const *d, size_t n) { - uint16_t crc = crc16_fast(d, n, 0xffff, true, true); - crc = ~crc; - return crc; + uint16_t crc = crc16_fast(d, n, 0xffff, true, true); + crc = ~crc; + return crc; } // CRC-A (14443-3) // poly=0x1021 init=0xc6c6 refin=true refout=true xorout=0x0000 name="CRC-A" uint16_t crc16_a(uint8_t const *d, size_t n) { - return crc16_fast(d, n, 0xC6C6, true, true); + return crc16_fast(d, n, 0xC6C6, true, true); } // iClass crc @@ -255,12 +255,12 @@ uint16_t crc16_a(uint8_t const *d, size_t n) { // poly 0x1021 reflected 0x8408 // poly=0x1021 init=0x4807 refin=true refout=true xorout=0x0BC3 check=0xF0B8 name="CRC-16/ICLASS" uint16_t crc16_iclass(uint8_t const *d, size_t n) { - return crc16_fast(d, n, 0x4807, true, true); + return crc16_fast(d, n, 0x4807, true, true); } // This CRC-16 is used in Legic Advant systems. // poly=0xB400, init=depends refin=true refout=true xorout=0x0000 check= name="CRC-16/LEGIC" uint16_t crc16_legic(uint8_t const *d, size_t n, uint8_t uidcrc) { - uint16_t initial = uidcrc << 8 | uidcrc; - return crc16_fast(d, n, initial, true, true); + uint16_t initial = uidcrc << 8 | uidcrc; + return crc16_fast(d, n, initial, true, true); } diff --git a/common/crc16.h b/common/crc16.h index c11cf6351..6b3f1432b 100644 --- a/common/crc16.h +++ b/common/crc16.h @@ -14,20 +14,20 @@ #define CRC16_POLY_CCITT 0x1021 #define CRC16_POLY_LEGIC 0xc6c6 //0x6363 -#define CRC16_POLY_DNP 0x3d65 +#define CRC16_POLY_DNP 0x3d65 -#define X25_CRC_CHECK ((uint16_t)(~0xF0B8 & 0xFFFF)) // use this for checking of a correct crc +#define X25_CRC_CHECK ((uint16_t)(~0xF0B8 & 0xFFFF)) // use this for checking of a correct crc typedef enum { - CRC_NONE, - CRC_14443_A, - CRC_14443_B, - CRC_15693, - CRC_ICLASS, - CRC_FELICA, - CRC_LEGIC, - CRC_CCITT, - CRC_KERMIT, + CRC_NONE, + CRC_14443_A, + CRC_14443_B, + CRC_15693, + CRC_ICLASS, + CRC_FELICA, + CRC_LEGIC, + CRC_CCITT, + CRC_KERMIT, } CrcType_t; uint16_t update_crc16_ex( uint16_t crc, uint8_t c, uint16_t polynomial ); diff --git a/common/crc64.c b/common/crc64.c index adf62d97d..5dc779f8d 100644 --- a/common/crc64.c +++ b/common/crc64.c @@ -6,7 +6,7 @@ #define CRC64_ECMA_PRESET 0x0000000000000000 const uint64_t crc64_table[] = { - 0x0000000000000000, 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26, 0xC711223CFA3E5BB5, + 0x0000000000000000, 0x42F0E1EBA9EA3693, 0x85E1C3D753D46D26, 0xC711223CFA3E5BB5, 0x493366450E42ECDF, 0x0BC387AEA7A8DA4C, 0xCCD2A5925D9681F9, 0x8E224479F47CB76A, 0x9266CC8A1C85D9BE, 0xD0962D61B56FEF2D, 0x17870F5D4F51B498, 0x5577EEB6E6BB820B, 0xDB55AACF12C73561, 0x99A54B24BB2D03F2, 0x5EB4691841135847, 0x1C4488F3E8F96ED4, @@ -74,10 +74,10 @@ const uint64_t crc64_table[] = { void crc64 (const uint8_t *data, const size_t len, uint64_t *crc) { - for (size_t i = 0; i < len; i++) { - uint8_t tableIndex = (((uint8_t)(*crc >> 56)) ^ data[i]) & 0xff; - *crc = crc64_table[tableIndex] ^ (*crc << 8); - } + for (size_t i = 0; i < len; i++) { + uint8_t tableIndex = (((uint8_t)(*crc >> 56)) ^ data[i]) & 0xff; + *crc = crc64_table[tableIndex] ^ (*crc << 8); + } } -//suint8_t x = (c & 0xFF00000000000000 ) >> 56; \ No newline at end of file +//suint8_t x = (c & 0xFF00000000000000 ) >> 56; \ No newline at end of file diff --git a/common/default_version.c b/common/default_version.c index b143afd4c..af5bc59e2 100644 --- a/common/default_version.c +++ b/common/default_version.c @@ -1,9 +1,9 @@ #include "proxmark3.h" /* This is the default version.c file that Makefile.common falls back to if perl is not available */ const struct version_information __attribute__((section(".version_information"))) version_information = { - VERSION_INFORMATION_MAGIC, - 1, /* version 1 */ - 0, /* version information not present */ - 2, /* cleanliness couldn't be determined */ - /* Remaining fields: zero */ + VERSION_INFORMATION_MAGIC, + 1, /* version 1 */ + 0, /* version information not present */ + 2, /* cleanliness couldn't be determined */ + /* Remaining fields: zero */ }; diff --git a/common/desfire.h b/common/desfire.h index 81ca57b92..3cffd2967 100644 --- a/common/desfire.h +++ b/common/desfire.h @@ -55,15 +55,15 @@ typedef enum { enum DESFIRE_AUTH_SCHEME { - AS_LEGACY, - AS_NEW + AS_LEGACY, + AS_NEW }; enum DESFIRE_CRYPTOALGO { - T_DES = 0x00, - T_3DES = 0x01, - T_3K3DES = 0x02, - T_AES = 0x03 + T_DES = 0x00, + T_3DES = 0x01, + T_3K3DES = 0x02, + T_AES = 0x03 }; @@ -74,7 +74,7 @@ struct desfire_key { // DES_key_schedule ks1; // DES_key_schedule ks2; // DES_key_schedule ks3; - AesCtx aes_ks; + AesCtx aes_ks; uint8_t cmac_sk1[24]; uint8_t cmac_sk2[24]; uint8_t aes_version; @@ -89,10 +89,10 @@ struct desfire_tag { uint8_t last_internal_error; uint8_t last_pcd_error; desfirekey_t session_key; - enum DESFIRE_AUTH_SCHEME authentication_scheme; + enum DESFIRE_AUTH_SCHEME authentication_scheme; uint8_t authenticated_key_no; - uint8_t ivect[MAX_CRYPTO_BLOCK_SIZE]; + uint8_t ivect[MAX_CRYPTO_BLOCK_SIZE]; uint8_t cmac[16]; uint8_t *crypto_buffer; size_t crypto_buffer_size; @@ -111,66 +111,66 @@ enum DESFIRE_FILE_TYPES { }; enum DESFIRE_STATUS { - OPERATION_OK = 0x00, - NO_CHANGES = 0x0c, - OUT_OF_EEPROM_ERROR = 0x0e, - ILLEGAL_COMMAND_CODE = 0x1c, - INTEGRITY_ERROR = 0x1e, - NO_SUCH_KEY = 0x40, - LENGTH_ERROR = 0x7e, - PERMISSION_DENIED = 0x9d, - PARAMETER_ERROR = 0x9e, - APPLICATION_NOT_FOUND = 0xa0, - APPL_INTEGRITY_ERROR = 0xa1, - AUTHENTICATION_ERROR = 0xae, - ADDITIONAL_FRAME = 0xaf, - BOUNDARY_ERROR = 0xbe, - PICC_INTEGRITY_ERROR = 0xc1, - COMMAND_ABORTED = 0xca, - PICC_DISABLED_ERROR = 0xcd, - COUNT_ERROR = 0xce, - DUPLICATE_ERROR = 0xde, - EEPROM_ERROR = 0xee, - FILE_NOT_FOUND = 0xf0, - FILE_INTEGRITY_ERROR = 0xf1 + OPERATION_OK = 0x00, + NO_CHANGES = 0x0c, + OUT_OF_EEPROM_ERROR = 0x0e, + ILLEGAL_COMMAND_CODE = 0x1c, + INTEGRITY_ERROR = 0x1e, + NO_SUCH_KEY = 0x40, + LENGTH_ERROR = 0x7e, + PERMISSION_DENIED = 0x9d, + PARAMETER_ERROR = 0x9e, + APPLICATION_NOT_FOUND = 0xa0, + APPL_INTEGRITY_ERROR = 0xa1, + AUTHENTICATION_ERROR = 0xae, + ADDITIONAL_FRAME = 0xaf, + BOUNDARY_ERROR = 0xbe, + PICC_INTEGRITY_ERROR = 0xc1, + COMMAND_ABORTED = 0xca, + PICC_DISABLED_ERROR = 0xcd, + COUNT_ERROR = 0xce, + DUPLICATE_ERROR = 0xde, + EEPROM_ERROR = 0xee, + FILE_NOT_FOUND = 0xf0, + FILE_INTEGRITY_ERROR = 0xf1 }; enum DESFIRE_CMD { - CREATE_APPLICATION = 0xca, - DELETE_APPLICATION = 0xda, - GET_APPLICATION_IDS = 0x6a, - SELECT_APPLICATION = 0x5a, - FORMAT_PICC = 0xfc, - GET_VERSION = 0x60, - READ_DATA = 0xbd, - WRITE_DATA = 0x3d, - GET_VALUE = 0x6c, - CREDIT = 0x0c, - DEBIT = 0xdc, - LIMITED_CREDIT = 0x1c, - WRITE_RECORD = 0x3b, - READ_RECORDS = 0xbb, - CLEAR_RECORD_FILE = 0xeb, - COMMIT_TRANSACTION = 0xc7, - ABORT_TRANSACTION = 0xa7, - GET_FREE_MEMORY = 0x6e, - GET_FILE_IDS = 0x6f, - GET_FILE_SETTINGS = 0xf5, - CHANGE_FILE_SETTINGS = 0x5f, - CREATE_STD_DATA_FILE = 0xcd, - CREATE_BACKUP_DATA_FILE = 0xcb, - CREATE_VALUE_FILE = 0xcc, - CREATE_LINEAR_RECORD_FILE = 0xc1, - CREATE_CYCLIC_RECORD_FILE = 0xc0, - DELETE_FILE = 0xdf, - AUTHENTICATE = 0x0a, // AUTHENTICATE_NATIVE - AUTHENTICATE_ISO = 0x1a, // AUTHENTICATE_STANDARD - AUTHENTICATE_AES = 0xaa, - CHANGE_KEY_SETTINGS = 0x54, - GET_KEY_SETTINGS = 0x45, - CHANGE_KEY = 0xc4, - GET_KEY_VERSION = 0x64, - AUTHENTICATION_FRAME = 0xAF + CREATE_APPLICATION = 0xca, + DELETE_APPLICATION = 0xda, + GET_APPLICATION_IDS = 0x6a, + SELECT_APPLICATION = 0x5a, + FORMAT_PICC = 0xfc, + GET_VERSION = 0x60, + READ_DATA = 0xbd, + WRITE_DATA = 0x3d, + GET_VALUE = 0x6c, + CREDIT = 0x0c, + DEBIT = 0xdc, + LIMITED_CREDIT = 0x1c, + WRITE_RECORD = 0x3b, + READ_RECORDS = 0xbb, + CLEAR_RECORD_FILE = 0xeb, + COMMIT_TRANSACTION = 0xc7, + ABORT_TRANSACTION = 0xa7, + GET_FREE_MEMORY = 0x6e, + GET_FILE_IDS = 0x6f, + GET_FILE_SETTINGS = 0xf5, + CHANGE_FILE_SETTINGS = 0x5f, + CREATE_STD_DATA_FILE = 0xcd, + CREATE_BACKUP_DATA_FILE = 0xcb, + CREATE_VALUE_FILE = 0xcc, + CREATE_LINEAR_RECORD_FILE = 0xc1, + CREATE_CYCLIC_RECORD_FILE = 0xc0, + DELETE_FILE = 0xdf, + AUTHENTICATE = 0x0a, // AUTHENTICATE_NATIVE + AUTHENTICATE_ISO = 0x1a, // AUTHENTICATE_STANDARD + AUTHENTICATE_AES = 0xaa, + CHANGE_KEY_SETTINGS = 0x54, + GET_KEY_SETTINGS = 0x45, + CHANGE_KEY = 0xc4, + GET_KEY_VERSION = 0x64, + AUTHENTICATION_FRAME = 0xAF }; #endif diff --git a/common/i2c.c b/common/i2c.c index dff77a05a..041b3e7ec 100644 --- a/common/i2c.c +++ b/common/i2c.c @@ -10,797 +10,797 @@ //----------------------------------------------------------------------------- #include "i2c.h" -#define GPIO_RST AT91C_PIO_PA1 -#define GPIO_SCL AT91C_PIO_PA5 -#define GPIO_SDA AT91C_PIO_PA7 +#define GPIO_RST AT91C_PIO_PA1 +#define GPIO_SCL AT91C_PIO_PA5 +#define GPIO_SDA AT91C_PIO_PA7 -#define SCL_H HIGH(GPIO_SCL) -#define SCL_L LOW(GPIO_SCL) -#define SDA_H HIGH(GPIO_SDA) -#define SDA_L LOW(GPIO_SDA) +#define SCL_H HIGH(GPIO_SCL) +#define SCL_L LOW(GPIO_SCL) +#define SDA_H HIGH(GPIO_SDA) +#define SDA_L LOW(GPIO_SDA) -#define SCL_read (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SCL) -#define SDA_read (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SDA) +#define SCL_read (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SCL) +#define SDA_read (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SDA) #define I2C_ERROR "I2C_WaitAck Error" volatile unsigned long c; -// ֱʹѭʱһѭ 6 ָ48M Delay=1 Ϊ 200kbps +// ֱʹѭʱһѭ 6 ָ48M Delay=1 Ϊ 200kbps // timer. // I2CSpinDelayClk(4) = 12.31us // I2CSpinDelayClk(1) = 3.07us void __attribute__((optimize("O0"))) I2CSpinDelayClk(uint16_t delay) { - for (c = delay * 2; c; c--) {}; + for (c = delay * 2; c; c--) {}; } -#define I2C_DELAY_1CLK I2CSpinDelayClk(1) -#define I2C_DELAY_2CLK I2CSpinDelayClk(2) -#define I2C_DELAY_XCLK(x) I2CSpinDelayClk((x)) +#define I2C_DELAY_1CLK I2CSpinDelayClk(1) +#define I2C_DELAY_2CLK I2CSpinDelayClk(2) +#define I2C_DELAY_XCLK(x) I2CSpinDelayClk((x)) #define ISO7618_MAX_FRAME 255 // try i2c bus recovery at 100kHz = 5uS high, 5uS low void I2C_recovery(void) { - DbpString("Performing i2c bus recovery"); + DbpString("Performing i2c bus recovery"); - // reset I2C - SDA_H; SCL_H; + // reset I2C + SDA_H; SCL_H; - //9nth cycle acts as NACK - for (int i = 0; i < 10; i++) { - SCL_H; WaitUS(5); - SCL_L; WaitUS(5); - } + //9nth cycle acts as NACK + for (int i = 0; i < 10; i++) { + SCL_H; WaitUS(5); + SCL_L; WaitUS(5); + } //a STOP signal (SDA from low to high while CLK is high) - SDA_L; WaitUS(5); - SCL_H; WaitUS(2); - SDA_H; WaitUS(2); + SDA_L; WaitUS(5); + SCL_H; WaitUS(2); + SDA_H; WaitUS(2); - bool isok = (SCL_read && SDA_read); + bool isok = (SCL_read && SDA_read); if (!SDA_read) - DbpString("I2C bus recovery error: SDA still LOW"); - if (!SCL_read) - DbpString("I2C bus recovery error: SCL still LOW"); - if (isok) - DbpString("I2C bus recovery complete"); + DbpString("I2C bus recovery error: SDA still LOW"); + if (!SCL_read) + DbpString("I2C bus recovery error: SCL still LOW"); + if (isok) + DbpString("I2C bus recovery complete"); } void I2C_init(void) { - // Configure reset pin, close up pull up, push-pull output, default high - AT91C_BASE_PIOA->PIO_PPUDR = GPIO_RST; - AT91C_BASE_PIOA->PIO_MDDR = GPIO_RST; + // Configure reset pin, close up pull up, push-pull output, default high + AT91C_BASE_PIOA->PIO_PPUDR = GPIO_RST; + AT91C_BASE_PIOA->PIO_MDDR = GPIO_RST; - // Configure I2C pin, open up, open leakage - AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_SCL | GPIO_SDA); - AT91C_BASE_PIOA->PIO_MDER |= (GPIO_SCL | GPIO_SDA); + // Configure I2C pin, open up, open leakage + AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_SCL | GPIO_SDA); + AT91C_BASE_PIOA->PIO_MDER |= (GPIO_SCL | GPIO_SDA); - // default three lines all pull up - AT91C_BASE_PIOA->PIO_SODR |= (GPIO_SCL | GPIO_SDA | GPIO_RST); + // default three lines all pull up + AT91C_BASE_PIOA->PIO_SODR |= (GPIO_SCL | GPIO_SDA | GPIO_RST); - AT91C_BASE_PIOA->PIO_OER |= (GPIO_SCL | GPIO_SDA | GPIO_RST); - AT91C_BASE_PIOA->PIO_PER |= (GPIO_SCL | GPIO_SDA | GPIO_RST); + AT91C_BASE_PIOA->PIO_OER |= (GPIO_SCL | GPIO_SDA | GPIO_RST); + AT91C_BASE_PIOA->PIO_PER |= (GPIO_SCL | GPIO_SDA | GPIO_RST); - bool isok = (SCL_read && SDA_read); - if ( !isok ) - I2C_recovery(); + bool isok = (SCL_read && SDA_read); + if ( !isok ) + I2C_recovery(); } // set the reset state void I2C_SetResetStatus(uint8_t LineRST, uint8_t LineSCK, uint8_t LineSDA) { - if (LineRST) - HIGH(GPIO_RST); - else - LOW(GPIO_RST); + if (LineRST) + HIGH(GPIO_RST); + else + LOW(GPIO_RST); - if (LineSCK) - HIGH(GPIO_SCL); - else - LOW(GPIO_SCL); + if (LineSCK) + HIGH(GPIO_SCL); + else + LOW(GPIO_SCL); - if (LineSDA) - HIGH(GPIO_SDA); - else - LOW(GPIO_SDA); + if (LineSDA) + HIGH(GPIO_SDA); + else + LOW(GPIO_SDA); } // Reset the SIM_Adapter, then enter the main program // Note: the SIM_Adapter will not enter the main program after power up. Please run this function before use SIM_Adapter. void I2C_Reset_EnterMainProgram(void) { - StartTicks(); - I2C_init(); - I2C_SetResetStatus(0, 0, 0); - WaitMS(30); - I2C_SetResetStatus(1, 0, 0); - WaitMS(30); - I2C_SetResetStatus(1, 1, 1); - WaitMS(10); + StartTicks(); + I2C_init(); + I2C_SetResetStatus(0, 0, 0); + WaitMS(30); + I2C_SetResetStatus(1, 0, 0); + WaitMS(30); + I2C_SetResetStatus(1, 1, 1); + WaitMS(10); } // Reset the SIM_Adapter, then enter the bootloader program // Reserve for firmware update. void I2C_Reset_EnterBootloader(void) { - StartTicks(); - I2C_init(); - I2C_SetResetStatus(0, 1, 1); - WaitMS(100); - I2C_SetResetStatus(1, 1, 1); - WaitMS(10); + StartTicks(); + I2C_init(); + I2C_SetResetStatus(0, 1, 1); + WaitMS(100); + I2C_SetResetStatus(1, 1, 1); + WaitMS(10); } // Wait for the clock to go High. bool WaitSCL_H_delay(uint32_t delay) { - while (delay--) { - if (SCL_read) { - return true; - } - I2C_DELAY_1CLK; - } - return false; + while (delay--) { + if (SCL_read) { + return true; + } + I2C_DELAY_1CLK; + } + return false; } // 5000 * 3.07us = 15350us. 15.35ms // 15000 * 3.07us = 46050us. 46.05ms bool WaitSCL_H(void) { - return WaitSCL_H_delay(15000); + return WaitSCL_H_delay(15000); } bool WaitSCL_L_delay(uint32_t delay) { - while (delay--) { - if (!SCL_read) { - return true; - } - I2C_DELAY_1CLK; - } - return false; + while (delay--) { + if (!SCL_read) { + return true; + } + I2C_DELAY_1CLK; + } + return false; } // 5000 * 3.07us = 15350us. 15.35ms bool WaitSCL_L(void) { - return WaitSCL_L_delay(15000); + return WaitSCL_L_delay(15000); } // Wait max 1800ms or until SCL goes LOW. // It timeout reading response from card // Which ever comes first bool WaitSCL_L_timeout(void){ - volatile uint16_t delay = 1800; - while ( delay-- ) { - // exit on SCL LOW - if (!SCL_read) - return true; + volatile uint16_t delay = 1800; + while ( delay-- ) { + // exit on SCL LOW + if (!SCL_read) + return true; - WaitMS(1); - } - return (delay == 0); + WaitMS(1); + } + return (delay == 0); } bool I2C_Start(void) { - I2C_DELAY_XCLK(4); - SDA_H; I2C_DELAY_1CLK; - SCL_H; - if (!WaitSCL_H()) return false; + I2C_DELAY_XCLK(4); + SDA_H; I2C_DELAY_1CLK; + SCL_H; + if (!WaitSCL_H()) return false; - I2C_DELAY_2CLK; + I2C_DELAY_2CLK; - if (!SCL_read) return false; - if (!SDA_read) return false; + if (!SCL_read) return false; + if (!SDA_read) return false; - SDA_L; I2C_DELAY_2CLK; - return true; + SDA_L; I2C_DELAY_2CLK; + return true; } bool I2C_WaitForSim() { - // wait for data from card - if (!WaitSCL_L_timeout()) - return false; + // wait for data from card + if (!WaitSCL_L_timeout()) + return false; - // 8051 speaks with smart card. - // 1000*50*3.07 = 153.5ms - // 1byte transfer == 1ms with max frame being 256bytes - if (!WaitSCL_H_delay(10 * 1000 * 50) ) - return false; + // 8051 speaks with smart card. + // 1000*50*3.07 = 153.5ms + // 1byte transfer == 1ms with max frame being 256bytes + if (!WaitSCL_H_delay(10 * 1000 * 50) ) + return false; - return true; + return true; } // send i2c STOP void I2C_Stop(void) { - SCL_L; I2C_DELAY_2CLK; - SDA_L; I2C_DELAY_2CLK; - SCL_H; I2C_DELAY_2CLK; - if (!WaitSCL_H()) return; - SDA_H; - I2C_DELAY_XCLK(8); + SCL_L; I2C_DELAY_2CLK; + SDA_L; I2C_DELAY_2CLK; + SCL_H; I2C_DELAY_2CLK; + if (!WaitSCL_H()) return; + SDA_H; + I2C_DELAY_XCLK(8); } // Send i2c ACK void I2C_Ack(void) { - SCL_L; I2C_DELAY_2CLK; - SDA_L; I2C_DELAY_2CLK; - SCL_H; I2C_DELAY_2CLK; - if (!WaitSCL_H()) return; - SCL_L; I2C_DELAY_2CLK; + SCL_L; I2C_DELAY_2CLK; + SDA_L; I2C_DELAY_2CLK; + SCL_H; I2C_DELAY_2CLK; + if (!WaitSCL_H()) return; + SCL_L; I2C_DELAY_2CLK; } // Send i2c NACK void I2C_NoAck(void) { - SCL_L; I2C_DELAY_2CLK; - SDA_H; I2C_DELAY_2CLK; - SCL_H; I2C_DELAY_2CLK; - if (!WaitSCL_H()) return; - SCL_L; I2C_DELAY_2CLK; + SCL_L; I2C_DELAY_2CLK; + SDA_H; I2C_DELAY_2CLK; + SCL_H; I2C_DELAY_2CLK; + if (!WaitSCL_H()) return; + SCL_L; I2C_DELAY_2CLK; } bool I2C_WaitAck(void) { - SCL_L; I2C_DELAY_1CLK; - SDA_H; I2C_DELAY_1CLK; - SCL_H; - if (!WaitSCL_H()) - return false; + SCL_L; I2C_DELAY_1CLK; + SDA_H; I2C_DELAY_1CLK; + SCL_H; + if (!WaitSCL_H()) + return false; - I2C_DELAY_2CLK; - I2C_DELAY_2CLK; - if (SDA_read) { - SCL_L; - return false; - } - SCL_L; - return true; + I2C_DELAY_2CLK; + I2C_DELAY_2CLK; + if (SDA_read) { + SCL_L; + return false; + } + SCL_L; + return true; } -void I2C_SendByte(uint8_t data) { - uint8_t bits = 8; +void I2C_SendByte(uint8_t data) { + uint8_t bits = 8; - while (bits--) { - SCL_L; + while (bits--) { + SCL_L; - I2C_DELAY_1CLK; + I2C_DELAY_1CLK; - if (data & 0x80) - SDA_H; - else - SDA_L; + if (data & 0x80) + SDA_H; + else + SDA_L; - data <<= 1; + data <<= 1; - I2C_DELAY_1CLK; + I2C_DELAY_1CLK; - SCL_H; - if (!WaitSCL_H()) - return; + SCL_H; + if (!WaitSCL_H()) + return; - I2C_DELAY_2CLK; - } - SCL_L; + I2C_DELAY_2CLK; + } + SCL_L; } int16_t I2C_ReadByte(void) { - uint8_t bits = 8, b = 0; + uint8_t bits = 8, b = 0; - SDA_H; - while (bits--) { - b <<= 1; - SCL_L; - if (!WaitSCL_L()) return -2; + SDA_H; + while (bits--) { + b <<= 1; + SCL_L; + if (!WaitSCL_L()) return -2; - I2C_DELAY_1CLK; + I2C_DELAY_1CLK; - SCL_H; - if (!WaitSCL_H()) return -1; + SCL_H; + if (!WaitSCL_H()) return -1; - I2C_DELAY_1CLK; - if (SDA_read) - b |= 0x01; - } - SCL_L; - return b; + I2C_DELAY_1CLK; + if (SDA_read) + b |= 0x01; + } + SCL_L; + return b; } // Sends one byte ( command to be written, SlaveDevice address) bool I2C_WriteCmd(uint8_t device_cmd, uint8_t device_address) { - bool bBreak = true; - do { - if (!I2C_Start()) - return false; + bool bBreak = true; + do { + if (!I2C_Start()) + return false; - I2C_SendByte(device_address & 0xFE); - if (!I2C_WaitAck()) - break; + I2C_SendByte(device_address & 0xFE); + if (!I2C_WaitAck()) + break; - I2C_SendByte(device_cmd); - if (!I2C_WaitAck()) - break; + I2C_SendByte(device_cmd); + if (!I2C_WaitAck()) + break; - bBreak = false; - } while (false); + bBreak = false; + } while (false); - I2C_Stop(); - if (bBreak) { - if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); - return false; - } - return true; + I2C_Stop(); + if (bBreak) { + if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); + return false; + } + return true; } // Sends 1 byte data (Data to be written, command to be written , SlaveDevice address ). bool I2C_WriteByte(uint8_t data, uint8_t device_cmd, uint8_t device_address) { - bool bBreak = true; - do { - if (!I2C_Start()) - return false; + bool bBreak = true; + do { + if (!I2C_Start()) + return false; - I2C_SendByte(device_address & 0xFE); - if (!I2C_WaitAck()) - break; + I2C_SendByte(device_address & 0xFE); + if (!I2C_WaitAck()) + break; - I2C_SendByte(device_cmd); - if (!I2C_WaitAck()) - break; + I2C_SendByte(device_cmd); + if (!I2C_WaitAck()) + break; - I2C_SendByte(data); - if (!I2C_WaitAck()) - break; + I2C_SendByte(data); + if (!I2C_WaitAck()) + break; - bBreak = false; - } while (false); + bBreak = false; + } while (false); - I2C_Stop(); - if (bBreak) { - if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); - return false; - } - return true; + I2C_Stop(); + if (bBreak) { + if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); + return false; + } + return true; } //Sends array of data (Array, length, command to be written , SlaveDevice address ). // len = uint8 (max buffer to write 256bytes) bool I2C_BufferWrite(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) { - bool bBreak = true; - do { - if (!I2C_Start()) - return false; + bool bBreak = true; + do { + if (!I2C_Start()) + return false; - I2C_SendByte(device_address & 0xFE); - if (!I2C_WaitAck()) - break; + I2C_SendByte(device_address & 0xFE); + if (!I2C_WaitAck()) + break; - I2C_SendByte(device_cmd); - if (!I2C_WaitAck()) - break; + I2C_SendByte(device_cmd); + if (!I2C_WaitAck()) + break; - while (len) { + while (len) { - I2C_SendByte(*data); - if (!I2C_WaitAck()) - break; + I2C_SendByte(*data); + if (!I2C_WaitAck()) + break; - len--; - data++; - } + len--; + data++; + } - if (len == 0) - bBreak = false; - } while (false); + if (len == 0) + bBreak = false; + } while (false); - I2C_Stop(); - if (bBreak) { - if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); - return false; - } - return true; + I2C_Stop(); + if (bBreak) { + if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); + return false; + } + return true; } // read one array of data (Data array, Readout length, command to be written , SlaveDevice address ). // len = uint8 (max buffer to read 256bytes) int16_t I2C_BufferRead(uint8_t *data, uint8_t len, uint8_t device_cmd, uint8_t device_address) { - if ( !data || len == 0 ) - return 0; + if ( !data || len == 0 ) + return 0; - // extra wait 500us (514us measured) - // 200us (xx measured) - WaitUS(600); - bool bBreak = true; - uint16_t readcount = 0; + // extra wait 500us (514us measured) + // 200us (xx measured) + WaitUS(600); + bool bBreak = true; + uint16_t readcount = 0; - do { - if (!I2C_Start()) - return 0; + do { + if (!I2C_Start()) + return 0; - // 0xB0 / 0xC0 == i2c write - I2C_SendByte(device_address & 0xFE); - if (!I2C_WaitAck()) - break; + // 0xB0 / 0xC0 == i2c write + I2C_SendByte(device_address & 0xFE); + if (!I2C_WaitAck()) + break; - I2C_SendByte(device_cmd); - if (!I2C_WaitAck()) - break; + I2C_SendByte(device_cmd); + if (!I2C_WaitAck()) + break; - // 0xB1 / 0xC1 == i2c read - I2C_Start(); - I2C_SendByte(device_address | 1); - if (!I2C_WaitAck()) - break; + // 0xB1 / 0xC1 == i2c read + I2C_Start(); + I2C_SendByte(device_address | 1); + if (!I2C_WaitAck()) + break; - bBreak = false; - } while (false); + bBreak = false; + } while (false); - if (bBreak) { - I2C_Stop(); - if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); - return 0; - } + if (bBreak) { + I2C_Stop(); + if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); + return 0; + } - while (len) { + while (len) { - int16_t tmp = I2C_ReadByte(); - if ( tmp < 0 ) - return tmp; + int16_t tmp = I2C_ReadByte(); + if ( tmp < 0 ) + return tmp; - *data = (uint8_t)tmp & 0xFF; + *data = (uint8_t)tmp & 0xFF; - len--; + len--; - // ȡĵһֽΪ - // The first byte in response is the message length - if (!readcount && (len > *data)) { - len = *data; - } else { - data++; - } - readcount++; + // ȡĵһֽΪ + // The first byte in response is the message length + if (!readcount && (len > *data)) { + len = *data; + } else { + data++; + } + readcount++; - // acknowledgements. After last byte send NACK. - if (len == 0) - I2C_NoAck(); - else - I2C_Ack(); - } + // acknowledgements. After last byte send NACK. + if (len == 0) + I2C_NoAck(); + else + I2C_Ack(); + } - I2C_Stop(); + I2C_Stop(); - // return bytecount - first byte (which is length byte) - return --readcount; + // return bytecount - first byte (which is length byte) + return --readcount; } int16_t I2C_ReadFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) { - //START, 0xB0, 0x00, 0x00, START, 0xB1, xx, yy, zz, ......, STOP - bool bBreak = true; - uint8_t readcount = 0; + //START, 0xB0, 0x00, 0x00, START, 0xB1, xx, yy, zz, ......, STOP + bool bBreak = true; + uint8_t readcount = 0; - // sending - do { - if (!I2C_Start()) - return 0; + // sending + do { + if (!I2C_Start()) + return 0; - // 0xB0 / 0xC0 i2c write - I2C_SendByte(device_address & 0xFE); - if (!I2C_WaitAck()) - break; + // 0xB0 / 0xC0 i2c write + I2C_SendByte(device_address & 0xFE); + if (!I2C_WaitAck()) + break; - I2C_SendByte(msb); - if (!I2C_WaitAck()) - break; + I2C_SendByte(msb); + if (!I2C_WaitAck()) + break; - I2C_SendByte(lsb); - if (!I2C_WaitAck()) - break; + I2C_SendByte(lsb); + if (!I2C_WaitAck()) + break; - // 0xB1 / 0xC1 i2c read - I2C_Start(); - I2C_SendByte(device_address | 1); - if (!I2C_WaitAck()) - break; + // 0xB1 / 0xC1 i2c read + I2C_Start(); + I2C_SendByte(device_address | 1); + if (!I2C_WaitAck()) + break; - bBreak = false; - } while (false); + bBreak = false; + } while (false); - if (bBreak) { - I2C_Stop(); - if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); - return 0; - } + if (bBreak) { + I2C_Stop(); + if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); + return 0; + } - // reading - while (len) { + // reading + while (len) { - int16_t tmp = I2C_ReadByte(); - if ( tmp < 0 ) - return tmp; + int16_t tmp = I2C_ReadByte(); + if ( tmp < 0 ) + return tmp; - *data = (uint8_t)tmp & 0xFF; + *data = (uint8_t)tmp & 0xFF; - data++; - readcount++; - len--; + data++; + readcount++; + len--; - // acknowledgements. After last byte send NACK. - if (len == 0) - I2C_NoAck(); - else - I2C_Ack(); - } + // acknowledgements. After last byte send NACK. + if (len == 0) + I2C_NoAck(); + else + I2C_Ack(); + } - I2C_Stop(); - return readcount; + I2C_Stop(); + return readcount; } bool I2C_WriteFW(uint8_t *data, uint8_t len, uint8_t msb, uint8_t lsb, uint8_t device_address) { - //START, 0xB0, 0x00, 0x00, xx, yy, zz, ......, STOP - bool bBreak = true; + //START, 0xB0, 0x00, 0x00, xx, yy, zz, ......, STOP + bool bBreak = true; - do { - if (!I2C_Start()) - return false; + do { + if (!I2C_Start()) + return false; - // 0xB0 == i2c write - I2C_SendByte(device_address & 0xFE); - if (!I2C_WaitAck()) - break; + // 0xB0 == i2c write + I2C_SendByte(device_address & 0xFE); + if (!I2C_WaitAck()) + break; - I2C_SendByte(msb); - if (!I2C_WaitAck()) - break; + I2C_SendByte(msb); + if (!I2C_WaitAck()) + break; - I2C_SendByte(lsb); - if (!I2C_WaitAck()) - break; + I2C_SendByte(lsb); + if (!I2C_WaitAck()) + break; - while (len) { - I2C_SendByte(*data); - if (!I2C_WaitAck()) - break; + while (len) { + I2C_SendByte(*data); + if (!I2C_WaitAck()) + break; - len--; - data++; - } + len--; + data++; + } - if (len == 0) - bBreak = false; - } while (false); + if (len == 0) + bBreak = false; + } while (false); - I2C_Stop(); - if (bBreak) { - if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); - return false; - } - return true; + I2C_Stop(); + if (bBreak) { + if ( MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); + return false; + } + return true; } void I2C_print_status(void) { - DbpString("Smart card module (ISO 7816)"); - uint8_t resp[] = {0,0,0,0}; - I2C_Reset_EnterMainProgram(); - uint8_t len = I2C_BufferRead(resp, sizeof(resp), I2C_DEVICE_CMD_GETVERSION, I2C_DEVICE_ADDRESS_MAIN); - if ( len > 0 ) - Dbprintf(" version.................v%x.%02d", resp[0], resp[1]); - else - DbpString(" version.................FAILED"); + DbpString("Smart card module (ISO 7816)"); + uint8_t resp[] = {0,0,0,0}; + I2C_Reset_EnterMainProgram(); + uint8_t len = I2C_BufferRead(resp, sizeof(resp), I2C_DEVICE_CMD_GETVERSION, I2C_DEVICE_ADDRESS_MAIN); + if ( len > 0 ) + Dbprintf(" version.................v%x.%02d", resp[0], resp[1]); + else + DbpString(" version.................FAILED"); } // Will read response from smart card module, retries 3 times to get the data. bool sc_rx_bytes(uint8_t* dest, uint8_t *destlen) { - uint8_t i = 3; - int16_t len = 0; - while (i--) { + uint8_t i = 3; + int16_t len = 0; + while (i--) { - I2C_WaitForSim(); + I2C_WaitForSim(); - len = I2C_BufferRead(dest, *destlen, I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN); + len = I2C_BufferRead(dest, *destlen, I2C_DEVICE_CMD_READ, I2C_DEVICE_ADDRESS_MAIN); - if ( len > 1 ){ - break; - } else if ( len == 1 ) { - continue; - } else if ( len <= 0 ) { - return false; - } - } + if ( len > 1 ){ + break; + } else if ( len == 1 ) { + continue; + } else if ( len <= 0 ) { + return false; + } + } - // after three - if ( len <= 1 ) - return false; + // after three + if ( len <= 1 ) + return false; - *destlen = (uint8_t)len & 0xFF; - return true; + *destlen = (uint8_t)len & 0xFF; + return true; } bool GetATR(smart_card_atr_t *card_ptr) { - if ( !card_ptr ) - return false; + if ( !card_ptr ) + return false; - card_ptr->atr_len = 0; - memset(card_ptr->atr, 0, sizeof(card_ptr->atr)); + card_ptr->atr_len = 0; + memset(card_ptr->atr, 0, sizeof(card_ptr->atr)); - // Send ATR - // start [C0 01] stop start C1 len aa bb cc stop] - I2C_WriteCmd(I2C_DEVICE_CMD_GENERATE_ATR, I2C_DEVICE_ADDRESS_MAIN); + // Send ATR + // start [C0 01] stop start C1 len aa bb cc stop] + I2C_WriteCmd(I2C_DEVICE_CMD_GENERATE_ATR, I2C_DEVICE_ADDRESS_MAIN); - //wait for sim card to answer. - // 1byte = 1ms , max frame 256bytes. SHould wait 256ms atleast just in case. - if (!I2C_WaitForSim()) - return false; + //wait for sim card to answer. + // 1byte = 1ms , max frame 256bytes. SHould wait 256ms atleast just in case. + if (!I2C_WaitForSim()) + return false; - // read bytes from module - uint8_t len = sizeof(card_ptr->atr); - if ( !sc_rx_bytes(card_ptr->atr, &len) ) - return false; + // read bytes from module + uint8_t len = sizeof(card_ptr->atr); + if ( !sc_rx_bytes(card_ptr->atr, &len) ) + return false; - uint8_t pos_td = 1; - if ( (card_ptr->atr[1] & 0x10) == 0x10) pos_td++; - if ( (card_ptr->atr[1] & 0x20) == 0x20) pos_td++; - if ( (card_ptr->atr[1] & 0x40) == 0x40) pos_td++; + uint8_t pos_td = 1; + if ( (card_ptr->atr[1] & 0x10) == 0x10) pos_td++; + if ( (card_ptr->atr[1] & 0x20) == 0x20) pos_td++; + if ( (card_ptr->atr[1] & 0x40) == 0x40) pos_td++; - // T0 indicate presence T=0 vs T=1. T=1 has checksum TCK - if ( (card_ptr->atr[1] & 0x80) == 0x80) { + // T0 indicate presence T=0 vs T=1. T=1 has checksum TCK + if ( (card_ptr->atr[1] & 0x80) == 0x80) { - pos_td++; + pos_td++; - // 1 == T1 , presence of checksum TCK - if ( (card_ptr->atr[pos_td] & 0x01) == 0x01) { + // 1 == T1 , presence of checksum TCK + if ( (card_ptr->atr[pos_td] & 0x01) == 0x01) { - uint8_t chksum = 0; - // xor property. will be zero when xored with chksum. - for (uint8_t i = 1; i < len; ++i) - chksum ^= card_ptr->atr[i]; + uint8_t chksum = 0; + // xor property. will be zero when xored with chksum. + for (uint8_t i = 1; i < len; ++i) + chksum ^= card_ptr->atr[i]; - if ( chksum ) { - if ( MF_DBGLEVEL > 2) DbpString("Wrong ATR checksum"); - } - } - } + if ( chksum ) { + if ( MF_DBGLEVEL > 2) DbpString("Wrong ATR checksum"); + } + } + } - card_ptr->atr_len = len; - LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false); - return true; + card_ptr->atr_len = len; + LogTrace(card_ptr->atr, card_ptr->atr_len, 0, 0, NULL, false); + return true; } void SmartCardAtr(void) { - smart_card_atr_t card; - LED_D_ON(); - clear_trace(); - set_tracing(true); - I2C_Reset_EnterMainProgram(); - bool isOK = GetATR( &card ); - cmd_send(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t)); - set_tracing(false); - LEDsoff(); + smart_card_atr_t card; + LED_D_ON(); + clear_trace(); + set_tracing(true); + I2C_Reset_EnterMainProgram(); + bool isOK = GetATR( &card ); + cmd_send(CMD_ACK, isOK, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t)); + set_tracing(false); + LEDsoff(); } void SmartCardRaw( uint64_t arg0, uint64_t arg1, uint8_t *data ) { - LED_D_ON(); + LED_D_ON(); - uint8_t len = 0; - uint8_t *resp = BigBuf_malloc(ISO7618_MAX_FRAME); - smartcard_command_t flags = arg0; + uint8_t len = 0; + uint8_t *resp = BigBuf_malloc(ISO7618_MAX_FRAME); + smartcard_command_t flags = arg0; - if ((flags & SC_CONNECT)) - clear_trace(); + if ((flags & SC_CONNECT)) + clear_trace(); - set_tracing(true); + set_tracing(true); - if ((flags & SC_CONNECT)) { + if ((flags & SC_CONNECT)) { - I2C_Reset_EnterMainProgram(); + I2C_Reset_EnterMainProgram(); - if ((flags & SC_SELECT)) { - smart_card_atr_t card; - bool gotATR = GetATR( &card ); - //cmd_send(CMD_ACK, gotATR, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t)); - if ( !gotATR ) - goto OUT; - } - } + if ((flags & SC_SELECT)) { + smart_card_atr_t card; + bool gotATR = GetATR( &card ); + //cmd_send(CMD_ACK, gotATR, sizeof(smart_card_atr_t), 0, &card, sizeof(smart_card_atr_t)); + if ( !gotATR ) + goto OUT; + } + } - if ((flags & SC_RAW) || (flags & SC_RAW_T0)) { + if ((flags & SC_RAW) || (flags & SC_RAW_T0)) { - LogTrace(data, arg1, 0, 0, NULL, true); + LogTrace(data, arg1, 0, 0, NULL, true); - // Send raw bytes - // asBytes = A0 A4 00 00 02 - // arg1 = len 5 - bool res = I2C_BufferWrite(data, arg1, ((flags & SC_RAW_T0) ? I2C_DEVICE_CMD_SEND_T0 : I2C_DEVICE_CMD_SEND), I2C_DEVICE_ADDRESS_MAIN); - if ( !res && MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); + // Send raw bytes + // asBytes = A0 A4 00 00 02 + // arg1 = len 5 + bool res = I2C_BufferWrite(data, arg1, ((flags & SC_RAW_T0) ? I2C_DEVICE_CMD_SEND_T0 : I2C_DEVICE_CMD_SEND), I2C_DEVICE_ADDRESS_MAIN); + if ( !res && MF_DBGLEVEL > 3 ) DbpString(I2C_ERROR); - // read bytes from module - len = ISO7618_MAX_FRAME; - res = sc_rx_bytes(resp, &len); - if ( res ) { - LogTrace(resp, len, 0, 0, NULL, false); - } else { - len = 0; - } - } + // read bytes from module + len = ISO7618_MAX_FRAME; + res = sc_rx_bytes(resp, &len); + if ( res ) { + LogTrace(resp, len, 0, 0, NULL, false); + } else { + len = 0; + } + } OUT: - cmd_send(CMD_ACK, len, 0, 0, resp, len); - BigBuf_free(); - set_tracing(false); - LEDsoff(); + cmd_send(CMD_ACK, len, 0, 0, resp, len); + BigBuf_free(); + set_tracing(false); + LEDsoff(); } void SmartCardUpgrade(uint64_t arg0) { - LED_C_ON(); + LED_C_ON(); - #define I2C_BLOCK_SIZE 128 - // write. Sector0, with 11,22,33,44 - // erase is 128bytes, and takes 50ms to execute + #define I2C_BLOCK_SIZE 128 + // write. Sector0, with 11,22,33,44 + // erase is 128bytes, and takes 50ms to execute - I2C_Reset_EnterBootloader(); + I2C_Reset_EnterBootloader(); - bool isOK = true; - int16_t res = 0; - uint16_t length = arg0; - uint16_t pos = 0; - uint8_t *fwdata = BigBuf_get_addr(); - uint8_t *verfiydata = BigBuf_malloc(I2C_BLOCK_SIZE); + bool isOK = true; + int16_t res = 0; + uint16_t length = arg0; + uint16_t pos = 0; + uint8_t *fwdata = BigBuf_get_addr(); + uint8_t *verfiydata = BigBuf_malloc(I2C_BLOCK_SIZE); - while (length) { + while (length) { - uint8_t msb = (pos >> 8) & 0xFF; - uint8_t lsb = pos & 0xFF; + uint8_t msb = (pos >> 8) & 0xFF; + uint8_t lsb = pos & 0xFF; - Dbprintf("FW %02X%02X", msb, lsb); + Dbprintf("FW %02X%02X", msb, lsb); - size_t size = MIN(I2C_BLOCK_SIZE, length); + size_t size = MIN(I2C_BLOCK_SIZE, length); - // write - res = I2C_WriteFW(fwdata+pos, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT); - if ( !res ) { - DbpString("Writing failed"); - isOK = false; - break; - } + // write + res = I2C_WriteFW(fwdata+pos, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT); + if ( !res ) { + DbpString("Writing failed"); + isOK = false; + break; + } - // writing takes time. - WaitMS(50); + // writing takes time. + WaitMS(50); - // read - res = I2C_ReadFW(verfiydata, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT); - if ( res <= 0) { - DbpString("Reading back failed"); - isOK = false; - break; - } + // read + res = I2C_ReadFW(verfiydata, size, msb, lsb, I2C_DEVICE_ADDRESS_BOOT); + if ( res <= 0) { + DbpString("Reading back failed"); + isOK = false; + break; + } - // cmp - if ( 0 != memcmp(fwdata+pos, verfiydata, size)) { - DbpString("not equal data"); - isOK = false; - break; - } + // cmp + if ( 0 != memcmp(fwdata+pos, verfiydata, size)) { + DbpString("not equal data"); + isOK = false; + break; + } - length -= size; - pos += size; - } - cmd_send(CMD_ACK, isOK, pos, 0, 0, 0); - LED_C_OFF(); - BigBuf_free(); + length -= size; + pos += size; + } + cmd_send(CMD_ACK, isOK, pos, 0, 0, 0); + LED_C_OFF(); + BigBuf_free(); } void SmartCardSetBaud(uint64_t arg0) { } void SmartCardSetClock(uint64_t arg0) { - LED_D_ON(); - set_tracing(true); - I2C_Reset_EnterMainProgram(); + LED_D_ON(); + set_tracing(true); + I2C_Reset_EnterMainProgram(); - // Send SIM CLC - // start [C0 05 xx] stop - I2C_WriteByte(arg0, I2C_DEVICE_CMD_SIM_CLC, I2C_DEVICE_ADDRESS_MAIN); + // Send SIM CLC + // start [C0 05 xx] stop + I2C_WriteByte(arg0, I2C_DEVICE_CMD_SIM_CLC, I2C_DEVICE_ADDRESS_MAIN); - cmd_send(CMD_ACK, 1, 0, 0, 0, 0); - set_tracing(false); - LEDsoff(); + cmd_send(CMD_ACK, 1, 0, 0, 0, 0); + set_tracing(false); + LEDsoff(); } diff --git a/common/i2c.h b/common/i2c.h index e5ff26e4d..4254a73c3 100644 --- a/common/i2c.h +++ b/common/i2c.h @@ -8,16 +8,16 @@ #include "BigBuf.h" #include "mifare.h" -#define I2C_DEVICE_ADDRESS_BOOT 0xB0 -#define I2C_DEVICE_ADDRESS_MAIN 0xC0 +#define I2C_DEVICE_ADDRESS_BOOT 0xB0 +#define I2C_DEVICE_ADDRESS_MAIN 0xC0 -#define I2C_DEVICE_CMD_GENERATE_ATR 0x01 -#define I2C_DEVICE_CMD_SEND 0x02 -#define I2C_DEVICE_CMD_READ 0x03 -#define I2C_DEVICE_CMD_SETBAUD 0x04 -#define I2C_DEVICE_CMD_SIM_CLC 0x05 -#define I2C_DEVICE_CMD_GETVERSION 0x06 -#define I2C_DEVICE_CMD_SEND_T0 0x07 +#define I2C_DEVICE_CMD_GENERATE_ATR 0x01 +#define I2C_DEVICE_CMD_SEND 0x02 +#define I2C_DEVICE_CMD_READ 0x03 +#define I2C_DEVICE_CMD_SETBAUD 0x04 +#define I2C_DEVICE_CMD_SIM_CLC 0x05 +#define I2C_DEVICE_CMD_GETVERSION 0x06 +#define I2C_DEVICE_CMD_SEND_T0 0x07 void I2C_recovery(void); diff --git a/common/iso14443crc.c b/common/iso14443crc.c index ceac3c4df..891eb9b14 100644 --- a/common/iso14443crc.c +++ b/common/iso14443crc.c @@ -22,7 +22,7 @@ void ComputeCrc14443(uint16_t CrcType, const uint8_t *data, int length, uint8_t b; uint16_t crc = CrcType; - do { + do { b = *data++; UpdateCrc14443(b, &crc); } while (--length); @@ -36,10 +36,10 @@ void ComputeCrc14443(uint16_t CrcType, const uint8_t *data, int length, } bool CheckCrc14443(uint16_t CrcType, const uint8_t *data, int length) { - if (length < 3) return false; - uint8_t b1, b2; - ComputeCrc14443(CrcType, data, length - 2, &b1, &b2); - if ((b1 == data[length - 2]) && (b2 == data[length - 1])) - return true; - return false; + if (length < 3) return false; + uint8_t b1, b2; + ComputeCrc14443(CrcType, data, length - 2, &b1, &b2); + if ((b1 == data[length - 2]) && (b2 == data[length - 1])) + return true; + return false; } diff --git a/common/iso15693tools.c b/common/iso15693tools.c index fbd79da52..e821feb1f 100644 --- a/common/iso15693tools.c +++ b/common/iso15693tools.c @@ -9,17 +9,17 @@ // returns a string representation of the UID // UID is transmitted and stored LSB first, displayed MSB first -// target char* buffer, where to put the UID, if NULL a static buffer is returned -// uid[] the UID in transmission order -// return: ptr to string +// target char* buffer, where to put the UID, if NULL a static buffer is returned +// uid[] the UID in transmission order +// return: ptr to string char* Iso15693sprintUID(char *target, uint8_t *uid) { - static char tempbuf[2*8+1] = {0}; - if (target == NULL) - target = tempbuf; - sprintf(target, "%02X %02X %02X %02X %02X %02X %02X %02X", - uid[7], uid[6], uid[5], uid[4], - uid[3], uid[2], uid[1], uid[0] - ); - return target; + static char tempbuf[2*8+1] = {0}; + if (target == NULL) + target = tempbuf; + sprintf(target, "%02X %02X %02X %02X %02X %02X %02X %02X", + uid[7], uid[6], uid[5], uid[4], + uid[3], uid[2], uid[1], uid[0] + ); + return target; } \ No newline at end of file diff --git a/common/iso15693tools.h b/common/iso15693tools.h index 0dd4d4444..1937ec84e 100644 --- a/common/iso15693tools.h +++ b/common/iso15693tools.h @@ -17,58 +17,58 @@ #include "crc16.h" // REQUEST FLAGS -#define ISO15_REQ_SUBCARRIER_SINGLE 0x00 // Tag should respond using one subcarrier (ASK) -#define ISO15_REQ_SUBCARRIER_TWO 0x01 // Tag should respond using two subcarriers (FSK) -#define ISO15_REQ_DATARATE_LOW 0x00 // Tag should respond using low data rate -#define ISO15_REQ_DATARATE_HIGH 0x02 // Tag should respond using high data rate -#define ISO15_REQ_NONINVENTORY 0x00 -#define ISO15_REQ_INVENTORY 0x04 // This is an inventory request - see inventory flags -#define ISO15_REQ_PROTOCOL_NONEXT 0x00 -#define ISO15_REQ_PROTOCOL_EXT 0x08 // RFU +#define ISO15_REQ_SUBCARRIER_SINGLE 0x00 // Tag should respond using one subcarrier (ASK) +#define ISO15_REQ_SUBCARRIER_TWO 0x01 // Tag should respond using two subcarriers (FSK) +#define ISO15_REQ_DATARATE_LOW 0x00 // Tag should respond using low data rate +#define ISO15_REQ_DATARATE_HIGH 0x02 // Tag should respond using high data rate +#define ISO15_REQ_NONINVENTORY 0x00 +#define ISO15_REQ_INVENTORY 0x04 // This is an inventory request - see inventory flags +#define ISO15_REQ_PROTOCOL_NONEXT 0x00 +#define ISO15_REQ_PROTOCOL_EXT 0x08 // RFU // REQUEST FLAGS when INVENTORY is not set -#define ISO15_REQ_SELECT 0x10 // only selected cards response -#define ISO15_REQ_ADDRESS 0x20 // this req contains an address -#define ISO15_REQ_OPTION 0x40 // Command specific option selector +#define ISO15_REQ_SELECT 0x10 // only selected cards response +#define ISO15_REQ_ADDRESS 0x20 // this req contains an address +#define ISO15_REQ_OPTION 0x40 // Command specific option selector //REQUEST FLAGS when INVENTORY is set -#define ISO15_REQINV_AFI 0x10 // AFI Field is present -#define ISO15_REQINV_SLOT1 0x20 // 1 Slot -#define ISO15_REQINV_SLOT16 0x00 // 16 Slots -#define ISO15_REQINV_OPTION 0x40 // Command specific option selector +#define ISO15_REQINV_AFI 0x10 // AFI Field is present +#define ISO15_REQINV_SLOT1 0x20 // 1 Slot +#define ISO15_REQINV_SLOT16 0x00 // 16 Slots +#define ISO15_REQINV_OPTION 0x40 // Command specific option selector //RESPONSE FLAGS -#define ISO15_RES_ERROR 0x01 -#define ISO15_RES_EXT 0x08 // Protocol Extention +#define ISO15_RES_ERROR 0x01 +#define ISO15_RES_EXT 0x08 // Protocol Extention // RESPONSE ERROR CODES -#define ISO15_NOERROR 0x00 -#define ISO15_ERROR_CMD_NOT_SUP 0x01 // Command not supported -#define ISO15_ERROR_CMD_NOT_REC 0x02 // Command not recognized (eg. parameter error) -#define ISO15_ERROR_CMD_OPTION 0x03 // Command option not supported -#define ISO15_ERROR_GENERIC 0x0F // No additional Info about this error -#define ISO15_ERROR_BLOCK_UNAVAILABLE 0x10 -#define ISO15_ERROR_BLOCK_LOCKED_ALREADY 0x11 // cannot lock again -#define ISO15_ERROR_BLOCK_LOCKED 0x12 // cannot be changed -#define ISO15_ERROR_BLOCK_WRITE 0x13 // Writing was unsuccessful -#define ISO15_ERROR_BLOCL_WRITELOCK 0x14 // Locking was unsuccessful +#define ISO15_NOERROR 0x00 +#define ISO15_ERROR_CMD_NOT_SUP 0x01 // Command not supported +#define ISO15_ERROR_CMD_NOT_REC 0x02 // Command not recognized (eg. parameter error) +#define ISO15_ERROR_CMD_OPTION 0x03 // Command option not supported +#define ISO15_ERROR_GENERIC 0x0F // No additional Info about this error +#define ISO15_ERROR_BLOCK_UNAVAILABLE 0x10 +#define ISO15_ERROR_BLOCK_LOCKED_ALREADY 0x11 // cannot lock again +#define ISO15_ERROR_BLOCK_LOCKED 0x12 // cannot be changed +#define ISO15_ERROR_BLOCK_WRITE 0x13 // Writing was unsuccessful +#define ISO15_ERROR_BLOCL_WRITELOCK 0x14 // Locking was unsuccessful // COMMAND CODES -#define ISO15_CMD_INVENTORY 0x01 -#define ISO15_CMD_STAYQUIET 0x02 -#define ISO15_CMD_READ 0x20 -#define ISO15_CMD_WRITE 0x21 -#define ISO15_CMD_LOCK 0x22 -#define ISO15_CMD_READMULTI 0x23 -#define ISO15_CMD_WRITEMULTI 0x24 -#define ISO15_CMD_SELECT 0x25 -#define ISO15_CMD_RESET 0x26 -#define ISO15_CMD_WRITEAFI 0x27 -#define ISO15_CMD_LOCKAFI 0x28 -#define ISO15_CMD_WRITEDSFID 0x29 -#define ISO15_CMD_LOCKDSFID 0x2A -#define ISO15_CMD_SYSINFO 0x2B -#define ISO15_CMD_SECSTATUS 0x2C +#define ISO15_CMD_INVENTORY 0x01 +#define ISO15_CMD_STAYQUIET 0x02 +#define ISO15_CMD_READ 0x20 +#define ISO15_CMD_WRITE 0x21 +#define ISO15_CMD_LOCK 0x22 +#define ISO15_CMD_READMULTI 0x23 +#define ISO15_CMD_WRITEMULTI 0x24 +#define ISO15_CMD_SELECT 0x25 +#define ISO15_CMD_RESET 0x26 +#define ISO15_CMD_WRITEAFI 0x27 +#define ISO15_CMD_LOCKAFI 0x28 +#define ISO15_CMD_WRITEDSFID 0x29 +#define ISO15_CMD_LOCKDSFID 0x2A +#define ISO15_CMD_SYSINFO 0x2B +#define ISO15_CMD_SECSTATUS 0x2C char* Iso15693sprintUID(char *target, uint8_t *uid); @@ -78,49 +78,49 @@ char* Iso15693sprintUID(char *target, uint8_t *uid); // Mode: highspeed && one subcarrier (ASK) //----------------------------------------------------------------------------- - // The sampling rate is 106.353 ksps/s, for T = 18.8 us + // The sampling rate is 106.353 ksps/s, for T = 18.8 us - // SOF defined as - // 1) Unmodulated time of 56.64us - // 2) 24 pulses of 423.75khz - // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz) + // SOF defined as + // 1) Unmodulated time of 56.64us + // 2) 24 pulses of 423.75khz + // 3) logic '1' (unmodulated for 18.88us followed by 8 pulses of 423.75khz) - static const int Iso15693FrameSOF[] = { - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - -1, -1, -1, -1, - -1, -1, -1, -1, - 1, 1, 1, 1, - 1, 1, 1, 1 - }; - static const int Iso15693Logic0[] = { - 1, 1, 1, 1, - 1, 1, 1, 1, - -1, -1, -1, -1, - -1, -1, -1, -1 - }; - static const int Iso15693Logic1[] = { - -1, -1, -1, -1, - -1, -1, -1, -1, - 1, 1, 1, 1, - 1, 1, 1, 1 - }; + static const int Iso15693FrameSOF[] = { + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + -1, -1, -1, -1, + -1, -1, -1, -1, + 1, 1, 1, 1, + 1, 1, 1, 1 + }; + static const int Iso15693Logic0[] = { + 1, 1, 1, 1, + 1, 1, 1, 1, + -1, -1, -1, -1, + -1, -1, -1, -1 + }; + static const int Iso15693Logic1[] = { + -1, -1, -1, -1, + -1, -1, -1, -1, + 1, 1, 1, 1, + 1, 1, 1, 1 + }; - // EOF defined as - // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us) - // 2) 24 pulses of 423.75khz - // 3) Unmodulated time of 56.64us - static const int Iso15693FrameEOF[] = { - 1, 1, 1, 1, - 1, 1, 1, 1, - -1, -1, -1, -1, - -1, -1, -1, -1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, - -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 - }; + // EOF defined as + // 1) logic '0' (8 pulses of 423.75khz followed by unmodulated for 18.88us) + // 2) 24 pulses of 423.75khz + // 3) Unmodulated time of 56.64us + static const int Iso15693FrameEOF[] = { + 1, 1, 1, 1, + 1, 1, 1, 1, + -1, -1, -1, -1, + -1, -1, -1, -1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, + -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 + }; #endif \ No newline at end of file diff --git a/common/ldscript.common b/common/ldscript.common index c0134ffd0..5b2f1e3c4 100644 --- a/common/ldscript.common +++ b/common/ldscript.common @@ -11,13 +11,13 @@ ms of the GNU GPL, version 2 or, /* AT91SAM7S256 has 256k Flash and 64k RAM */ /* AT91SAM7S512 has 512k Flash and 64k RAM */ -MEMORY +MEMORY { - bootphase1 : ORIGIN = 0x00100000, LENGTH = 0x200 /* Phase 1 bootloader: Copies real bootloader to RAM */ - bootphase2 : ORIGIN = 0x00100200, LENGTH = 0x2000 - 0x200 /* Main bootloader code, stored in Flash, executed from RAM */ - osimage : ORIGIN = 0x00102000, LENGTH = 512K - 0x2000 /* Place where the main OS will end up */ - ram : ORIGIN = 0x00200000, LENGTH = 64K - 0x20 /* RAM, minus small common area */ - commonarea : ORIGIN = 0x00200000 + 64K - 0x20, LENGTH = 0x20 /* Communication between bootloader and main OS */ + bootphase1 : ORIGIN = 0x00100000, LENGTH = 0x200 /* Phase 1 bootloader: Copies real bootloader to RAM */ + bootphase2 : ORIGIN = 0x00100200, LENGTH = 0x2000 - 0x200 /* Main bootloader code, stored in Flash, executed from RAM */ + osimage : ORIGIN = 0x00102000, LENGTH = 512K - 0x2000 /* Place where the main OS will end up */ + ram : ORIGIN = 0x00200000, LENGTH = 64K - 0x20 /* RAM, minus small common area */ + commonarea : ORIGIN = 0x00200000 + 64K - 0x20, LENGTH = 0x20 /* Communication between bootloader and main OS */ } /* Export some information that can be used from within the firmware */ diff --git a/common/legic_prng.c b/common/legic_prng.c index c4927b33b..75e04d8b6 100644 --- a/common/legic_prng.c +++ b/common/legic_prng.c @@ -13,9 +13,9 @@ // c keeps track on which step the prng is. // legic_prng_get_bit() = gets a bit muxed from a and b. struct lfsr { - uint8_t a; - uint8_t b; - uint32_t c; + uint8_t a; + uint8_t b; + uint32_t c; } lfsr; // Normal init is set following variables with a random value IV @@ -28,38 +28,38 @@ struct lfsr { // which is used in the initialisation phase sending the IV // void legic_prng_init(uint8_t iv) { - lfsr.a = iv; - lfsr.b = 0; // hack to get a always 0 keystream - lfsr.c = 0; - if(iv) - lfsr.b = (iv << 1) | 1; + lfsr.a = iv; + lfsr.b = 0; // hack to get a always 0 keystream + lfsr.c = 0; + if(iv) + lfsr.b = (iv << 1) | 1; } void legic_prng_forward(int count) { - if (count == 0) return; + if (count == 0) return; - lfsr.c += count; - while(count--) { - // According: http://www.proxmark.org/forum/viewtopic.php?pid=5437#p5437 - lfsr.a = (lfsr.a >> 1 | (lfsr.a ^ lfsr.a >> 6) << 6) & 0x7F; - lfsr.b = lfsr.b >> 1 | (lfsr.b ^ lfsr.b >> 2 ^ lfsr.b >> 3 ^ lfsr.b >> 7) << 7; - } + lfsr.c += count; + while(count--) { + // According: http://www.proxmark.org/forum/viewtopic.php?pid=5437#p5437 + lfsr.a = (lfsr.a >> 1 | (lfsr.a ^ lfsr.a >> 6) << 6) & 0x7F; + lfsr.b = lfsr.b >> 1 | (lfsr.b ^ lfsr.b >> 2 ^ lfsr.b >> 3 ^ lfsr.b >> 7) << 7; + } } uint32_t legic_prng_count() { - return lfsr.c; + return lfsr.c; } uint8_t legic_prng_get_bit() { - uint8_t idx = 7 - ( (lfsr.a & 4) | (lfsr.a >> 2 & 2) | (lfsr.a >> 4 & 1) ); - return lfsr.b >> idx & 1; + uint8_t idx = 7 - ( (lfsr.a & 4) | (lfsr.a >> 2 & 2) | (lfsr.a >> 4 & 1) ); + return lfsr.b >> idx & 1; } uint32_t legic_prng_get_bits(uint8_t len){ - uint32_t a = 0; - for(uint8_t i = 0; i < len; ++i) { - a |= legic_prng_get_bit() << i; - legic_prng_forward(1); - } - return a; + uint32_t a = 0; + for(uint8_t i = 0; i < len; ++i) { + a |= legic_prng_get_bit() << i; + legic_prng_forward(1); + } + return a; } \ No newline at end of file diff --git a/common/lfdemod.c b/common/lfdemod.c index 65999ae77..13c2a3f9f 100644 --- a/common/lfdemod.c +++ b/common/lfdemod.c @@ -65,124 +65,124 @@ extern void Dbprintf(const char *fmt, ...); signal_t signalprop = { 255, -255, 0, 0, true }; signal_t* getSignalProperties(void) { - return &signalprop; + return &signalprop; } static void resetSignal(void) { - signalprop.low = 255; - signalprop.high = -255; - signalprop.mean = 0; - signalprop.amplitude = 0; - signalprop.isnoise = true; + signalprop.low = 255; + signalprop.high = -255; + signalprop.mean = 0; + signalprop.amplitude = 0; + signalprop.isnoise = true; } static void printSignal(void) { - prnt("LF signal properties:"); - prnt(" high..........%d", signalprop.high); - prnt(" low...........%d", signalprop.low); - prnt(" mean..........%d", signalprop.mean); - prnt(" amplitude.....%d", signalprop.amplitude); - prnt(" is Noise......%s", (signalprop.isnoise) ? "Yes" : "No"); - prnt(" THRESHOLD noise amplitude......%d" , NOISE_AMPLITUDE_THRESHOLD); + prnt("LF signal properties:"); + prnt(" high..........%d", signalprop.high); + prnt(" low...........%d", signalprop.low); + prnt(" mean..........%d", signalprop.mean); + prnt(" amplitude.....%d", signalprop.amplitude); + prnt(" is Noise......%s", (signalprop.isnoise) ? "Yes" : "No"); + prnt(" THRESHOLD noise amplitude......%d" , NOISE_AMPLITUDE_THRESHOLD); } void computeSignalProperties(uint8_t *samples, uint32_t size) { - resetSignal(); + resetSignal(); - uint32_t sum = 0; - for ( uint32_t i = 0; i < size; i++) { - if ( samples[i] < signalprop.low ) signalprop.low = samples[i]; - if ( samples[i] > signalprop.high ) signalprop.high = samples[i]; - sum += samples[i]; - } + uint32_t sum = 0; + for ( uint32_t i = 0; i < size; i++) { + if ( samples[i] < signalprop.low ) signalprop.low = samples[i]; + if ( samples[i] > signalprop.high ) signalprop.high = samples[i]; + sum += samples[i]; + } - // measure amplitude of signal - signalprop.mean = sum / size; - signalprop.amplitude = signalprop.high - signalprop.mean; - // By measuring mean and look at amplitude of signal from HIGH / LOW, - // we can detect noise - signalprop.isnoise = signalprop.amplitude < NOISE_AMPLITUDE_THRESHOLD; + // measure amplitude of signal + signalprop.mean = sum / size; + signalprop.amplitude = signalprop.high - signalprop.mean; + // By measuring mean and look at amplitude of signal from HIGH / LOW, + // we can detect noise + signalprop.isnoise = signalprop.amplitude < NOISE_AMPLITUDE_THRESHOLD; - if (g_debugMode) - printSignal(); + if (g_debugMode) + printSignal(); } void removeSignalOffset(uint8_t *samples, uint32_t size) { - if ( samples == NULL || size < SIGNAL_MIN_SAMPLES ) return; + if ( samples == NULL || size < SIGNAL_MIN_SAMPLES ) return; - int acc_off = 0; - for (uint32_t i = SIGNAL_IGNORE_FIRST_SAMPLES; i < size; i++) - acc_off += samples[i] - 128; - acc_off /= (int)(size - SIGNAL_IGNORE_FIRST_SAMPLES); + int acc_off = 0; + for (uint32_t i = SIGNAL_IGNORE_FIRST_SAMPLES; i < size; i++) + acc_off += samples[i] - 128; + acc_off /= (int)(size - SIGNAL_IGNORE_FIRST_SAMPLES); - // shift and saturate samples to center the mean - for ( uint32_t i = 0; i < size; i++) { - if (acc_off > 0) { - samples[i] = (samples[i] >= acc_off)? samples[i] - acc_off : 0; - } - if (acc_off < 0) { - samples[i] = (255 - samples[i] >= -acc_off)? samples[i] - acc_off : 255; - } - } + // shift and saturate samples to center the mean + for ( uint32_t i = 0; i < size; i++) { + if (acc_off > 0) { + samples[i] = (samples[i] >= acc_off)? samples[i] - acc_off : 0; + } + if (acc_off < 0) { + samples[i] = (255 - samples[i] >= -acc_off)? samples[i] - acc_off : 255; + } + } } //by marshmellow //get high and low values of a wave with passed in fuzz factor. also return noise test = 1 for passed or 0 for only noise //void getHiLo(uint8_t *bits, size_t size, int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo) { void getHiLo(int *high, int *low, uint8_t fuzzHi, uint8_t fuzzLo) { - // add fuzz. - *high = (signalprop.high * fuzzHi) / 100; - if ( signalprop.low < 0 ) { - *low = (signalprop.low * fuzzLo) / 100; - } else { - uint8_t range = signalprop.high - signalprop.low; + // add fuzz. + *high = (signalprop.high * fuzzHi) / 100; + if ( signalprop.low < 0 ) { + *low = (signalprop.low * fuzzLo) / 100; + } else { + uint8_t range = signalprop.high - signalprop.low; - *low = signalprop.low + ((range * (100-fuzzLo))/100); - } + *low = signalprop.low + ((range * (100-fuzzLo))/100); + } - // if fuzzing to great and overlap - if ( *high < *low ) { - *high = signalprop.high; - *low = signalprop.low; - } + // if fuzzing to great and overlap + if ( *high < *low ) { + *high = signalprop.high; + *low = signalprop.low; + } - if (g_debugMode) - prnt("getHiLo fuzzed: High %d | Low %d", *high, *low); + if (g_debugMode) + prnt("getHiLo fuzzed: High %d | Low %d", *high, *low); } // by marshmellow // pass bits to be tested in bits, length bits passed in bitLen, and parity type (even=0 | odd=1) in pType // returns 1 if passed bool parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType) { - return oddparity32(bits) ^ pType; + return oddparity32(bits) ^ pType; } //by marshmellow // takes a array of binary values, start position, length of bits per parity (includes parity bit - MAX 32), // Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run) size_t removeParity(uint8_t *bits, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen) { - uint32_t parityWd = 0; - size_t bitCnt = 0; - for (int word = 0; word < (bLen); word += pLen){ - for (int bit=0; bit < pLen; bit++){ - if (word+bit >= bLen) break; - parityWd = (parityWd << 1) | bits[startIdx+word+bit]; - bits[bitCnt++] = (bits[startIdx+word+bit]); - } - if (word+pLen > bLen) break; + uint32_t parityWd = 0; + size_t bitCnt = 0; + for (int word = 0; word < (bLen); word += pLen){ + for (int bit=0; bit < pLen; bit++){ + if (word+bit >= bLen) break; + parityWd = (parityWd << 1) | bits[startIdx+word+bit]; + bits[bitCnt++] = (bits[startIdx+word+bit]); + } + if (word+pLen > bLen) break; - bitCnt--; // overwrite parity with next data - // if parity fails then return 0 - switch (pType) { - case 3: if (bits[bitCnt]==1) {return 0;} break; //should be 0 spacer bit - case 2: if (bits[bitCnt]==0) {return 0;} break; //should be 1 spacer bit - default: if (parityTest(parityWd, pLen, pType) == 0) { return 0; } break; //test parity - } - parityWd = 0; - } - // if we got here then all the parities passed - //return size - return bitCnt; + bitCnt--; // overwrite parity with next data + // if parity fails then return 0 + switch (pType) { + case 3: if (bits[bitCnt]==1) {return 0;} break; //should be 0 spacer bit + case 2: if (bits[bitCnt]==0) {return 0;} break; //should be 1 spacer bit + default: if (parityTest(parityWd, pLen, pType) == 0) { return 0; } break; //test parity + } + parityWd = 0; + } + // if we got here then all the parities passed + //return size + return bitCnt; } // by marshmellow @@ -190,61 +190,61 @@ size_t removeParity(uint8_t *bits, size_t startIdx, uint8_t pLen, uint8_t pType, // Parity Type (1 for odd; 0 for even; 2 Always 1's; 3 Always 0's), and binary Length (length to run) // Make sure *dest is long enough to store original sourceLen + #_of_parities_to_be_added size_t addParity(uint8_t *src, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType) { - uint32_t parityWd = 0; - size_t j = 0, bitCnt = 0; - for (int word = 0; word < sourceLen; word += pLen-1) { - for (int bit=0; bit < pLen-1; bit++){ - parityWd = (parityWd << 1) | src[word+bit]; - dest[j++] = (src[word+bit]); - } - // if parity fails then return 0 - switch (pType) { - case 3: dest[j++]=0; break; // marker bit which should be a 0 - case 2: dest[j++]=1; break; // marker bit which should be a 1 - default: - dest[j++] = parityTest(parityWd, pLen-1, pType) ^ 1; - break; - } - bitCnt += pLen; - parityWd = 0; - } - // if we got here then all the parities passed - //return ID start index and size - return bitCnt; + uint32_t parityWd = 0; + size_t j = 0, bitCnt = 0; + for (int word = 0; word < sourceLen; word += pLen-1) { + for (int bit=0; bit < pLen-1; bit++){ + parityWd = (parityWd << 1) | src[word+bit]; + dest[j++] = (src[word+bit]); + } + // if parity fails then return 0 + switch (pType) { + case 3: dest[j++]=0; break; // marker bit which should be a 0 + case 2: dest[j++]=1; break; // marker bit which should be a 1 + default: + dest[j++] = parityTest(parityWd, pLen-1, pType) ^ 1; + break; + } + bitCnt += pLen; + parityWd = 0; + } + // if we got here then all the parities passed + //return ID start index and size + return bitCnt; } // array must be size dividable with 8 uint8_t bits_to_array(const uint8_t *bits, size_t size, uint8_t *dest) { - if ( (size == 0) || (size % 8) != 0) return 0; + if ( (size == 0) || (size % 8) != 0) return 0; - for(uint32_t i = 0; i < (size / 8); i++) - dest[i] = bytebits_to_byte((uint8_t *) bits + (i * 8), 8); + for(uint32_t i = 0; i < (size / 8); i++) + dest[i] = bytebits_to_byte((uint8_t *) bits + (i * 8), 8); - return 0; + return 0; } uint32_t bytebits_to_byte(uint8_t *src, size_t numbits) { - uint32_t num = 0; - for(int i = 0 ; i < numbits ; i++) { - num = (num << 1) | (*src); - src++; - } - return num; + uint32_t num = 0; + for(int i = 0 ; i < numbits ; i++) { + num = (num << 1) | (*src); + src++; + } + return num; } //least significant bit first uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits) { - uint32_t num = 0; - for(int i = 0 ; i < numbits ; i++) { - num = (num << 1) | *(src + (numbits-(i+1))); - } - return num; + uint32_t num = 0; + for(int i = 0 ; i < numbits ; i++) { + num = (num << 1) | *(src + (numbits-(i+1))); + } + return num; } //by marshmellow //search for given preamble in given BitStream and return success = TRUE or fail = FALSE and startIndex and length bool preambleSearch(uint8_t *bits, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx){ - return preambleSearchEx(bits, preamble, pLen, size, startIdx, false); + return preambleSearchEx(bits, preamble, pLen, size, startIdx, false); } //by marshmellow // search for given preamble in given BitStream and return success=1 or fail=0 and startIndex (where it was found) and length if not fineone @@ -252,210 +252,210 @@ bool preambleSearch(uint8_t *bits, uint8_t *preamble, size_t pLen, size_t *size, //(iceman) FINDONE, only finds start index. NOT SIZE!. I see Em410xDecode (lfdemod.c) uses SIZE to determine success bool preambleSearchEx(uint8_t *bits, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx, bool findone) { - // Sanity check. If preamble length is bigger than bits length. - if ( *size <= pLen ) return false; + // Sanity check. If preamble length is bigger than bits length. + if ( *size <= pLen ) return false; - uint8_t foundCnt = 0; - for (size_t idx = 0; idx < *size - pLen; idx++) { - if (memcmp(bits+idx, preamble, pLen) == 0){ - //first index found - foundCnt++; - if (foundCnt == 1){ - if (g_debugMode) prnt("DEBUG: (preambleSearchEx) preamble found at %i", idx); - *startIdx = idx; - if (findone) return true; - } - if (foundCnt == 2){ - if (g_debugMode) prnt("DEBUG: (preambleSearchEx) preamble 2 found at %i", idx); - *size = idx - *startIdx; - return true; - } - } - } - return (foundCnt > 0); + uint8_t foundCnt = 0; + for (size_t idx = 0; idx < *size - pLen; idx++) { + if (memcmp(bits+idx, preamble, pLen) == 0){ + //first index found + foundCnt++; + if (foundCnt == 1){ + if (g_debugMode) prnt("DEBUG: (preambleSearchEx) preamble found at %i", idx); + *startIdx = idx; + if (findone) return true; + } + if (foundCnt == 2){ + if (g_debugMode) prnt("DEBUG: (preambleSearchEx) preamble 2 found at %i", idx); + *size = idx - *startIdx; + return true; + } + } + } + return (foundCnt > 0); } // find start of modulating data (for fsk and psk) in case of beginning noise or slow chip startup. size_t findModStart(uint8_t *src, size_t size, uint8_t expWaveSize) { - size_t i = 0; - size_t waveSizeCnt = 0; - uint8_t thresholdCnt = 0; - bool isAboveThreshold = src[i++] >= signalprop.mean; //FSK_PSK_THRESHOLD; - for (; i < size-20; i++ ) { - if (src[i] < signalprop.mean && isAboveThreshold) { - thresholdCnt++; - if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break; - isAboveThreshold = false; - waveSizeCnt = 0; - } else if (src[i] >= signalprop.mean && !isAboveThreshold) { - thresholdCnt++; - if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break; - isAboveThreshold = true; - waveSizeCnt = 0; - } else { - waveSizeCnt++; - } - if (thresholdCnt > 10) break; - } - if (g_debugMode == 2) prnt("DEBUG: threshold Count reached at index %u, count: %u", i, thresholdCnt); - return i; + size_t i = 0; + size_t waveSizeCnt = 0; + uint8_t thresholdCnt = 0; + bool isAboveThreshold = src[i++] >= signalprop.mean; //FSK_PSK_THRESHOLD; + for (; i < size-20; i++ ) { + if (src[i] < signalprop.mean && isAboveThreshold) { + thresholdCnt++; + if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break; + isAboveThreshold = false; + waveSizeCnt = 0; + } else if (src[i] >= signalprop.mean && !isAboveThreshold) { + thresholdCnt++; + if (thresholdCnt > 2 && waveSizeCnt < expWaveSize+1) break; + isAboveThreshold = true; + waveSizeCnt = 0; + } else { + waveSizeCnt++; + } + if (thresholdCnt > 10) break; + } + if (g_debugMode == 2) prnt("DEBUG: threshold Count reached at index %u, count: %u", i, thresholdCnt); + return i; } int getClosestClock(int testclk) { - uint16_t clocks[] = {8, 16, 32, 40, 50, 64, 128, 256, 384}; - uint8_t limit[] = {1, 2, 4, 4, 5, 8, 8, 8, 8}; + uint16_t clocks[] = {8, 16, 32, 40, 50, 64, 128, 256, 384}; + uint8_t limit[] = {1, 2, 4, 4, 5, 8, 8, 8, 8}; - for (uint8_t i = 0; i < 9; i++) - if ( testclk >= clocks[i]-limit[i] && testclk <= clocks[i]+limit[i] ) - return clocks[i]; + for (uint8_t i = 0; i < 9; i++) + if ( testclk >= clocks[i]-limit[i] && testclk <= clocks[i]+limit[i] ) + return clocks[i]; - return 0; + return 0; } void getNextLow(uint8_t *samples, size_t size, int low, size_t *i) { - while ((samples[*i] > low) && (*i < size)) - *i += 1; + while ((samples[*i] > low) && (*i < size)) + *i += 1; } void getNextHigh(uint8_t *samples, size_t size, int high, size_t *i) { - while ((samples[*i] < high) && (*i < size)) - *i += 1; + while ((samples[*i] < high) && (*i < size)) + *i += 1; } // load wave counters bool loadWaveCounters(uint8_t *samples, size_t size, int lowToLowWaveLen[], int highToLowWaveLen[], int *waveCnt, int *skip, int *minClk, int *high, int *low) { - size_t i = 0, firstLow, firstHigh; - //size_t testsize = (size < 512) ? size : 512; + size_t i = 0, firstLow, firstHigh; + //size_t testsize = (size < 512) ? size : 512; - // just noise - no super good detection. good enough - if (signalprop.isnoise) { - if (g_debugMode == 2) prnt("DEBUG STT: just noise detected - quitting"); - return false; - } + // just noise - no super good detection. good enough + if (signalprop.isnoise) { + if (g_debugMode == 2) prnt("DEBUG STT: just noise detected - quitting"); + return false; + } - getHiLo(high, low, 80, 80); + getHiLo(high, low, 80, 80); - // get to first full low to prime loop and skip incomplete first pulse - getNextHigh(samples, size, *high, &i); - getNextLow(samples, size, *low, &i); - *skip = i; + // get to first full low to prime loop and skip incomplete first pulse + getNextHigh(samples, size, *high, &i); + getNextLow(samples, size, *low, &i); + *skip = i; - // populate tmpbuff buffer with pulse lengths - while (i < size) { - // measure from low to low - firstLow = i; - //find first high point for this wave - getNextHigh(samples, size, *high, &i); - firstHigh = i; + // populate tmpbuff buffer with pulse lengths + while (i < size) { + // measure from low to low + firstLow = i; + //find first high point for this wave + getNextHigh(samples, size, *high, &i); + firstHigh = i; - getNextLow(samples, size, *low, &i); + getNextLow(samples, size, *low, &i); - if (*waveCnt >= (size/LOWEST_DEFAULT_CLOCK)) - break; + if (*waveCnt >= (size/LOWEST_DEFAULT_CLOCK)) + break; - highToLowWaveLen[*waveCnt] = i - firstHigh; //first high to first low - lowToLowWaveLen[*waveCnt] = i - firstLow; - *waveCnt += 1; - if (i-firstLow < *minClk && i < size) { - *minClk = i - firstLow; - } - } - return true; + highToLowWaveLen[*waveCnt] = i - firstHigh; //first high to first low + lowToLowWaveLen[*waveCnt] = i - firstLow; + *waveCnt += 1; + if (i-firstLow < *minClk && i < size) { + *minClk = i - firstLow; + } + } + return true; } size_t pskFindFirstPhaseShift(uint8_t *samples, size_t size, uint8_t *curPhase, size_t waveStart, uint16_t fc, uint16_t *fullWaveLen) { - uint16_t loopCnt = (size+3 < 4096) ? size : 4096; //don't need to loop through entire array... + uint16_t loopCnt = (size+3 < 4096) ? size : 4096; //don't need to loop through entire array... - uint16_t avgWaveVal=0, lastAvgWaveVal=0; - size_t i = waveStart, waveEnd, waveLenCnt, firstFullWave; - for (; i= samples[i+2]){ - waveEnd = i+1; - if (g_debugMode == 2) prnt("DEBUG PSK: waveEnd: %u, waveStart: %u", waveEnd, waveStart); - waveLenCnt = waveEnd-waveStart; - if (waveLenCnt > fc && waveStart > fc && !(waveLenCnt > fc+8)){ //not first peak and is a large wave but not out of whack - lastAvgWaveVal = avgWaveVal/(waveLenCnt); - firstFullWave = waveStart; - *fullWaveLen = waveLenCnt; - //if average wave value is > graph 0 then it is an up wave or a 1 (could cause inverting) - if (lastAvgWaveVal > FSK_PSK_THRESHOLD) *curPhase ^= 1; - return firstFullWave; - } - waveStart = i+1; - avgWaveVal = 0; - } - avgWaveVal += samples[i+2]; - } - return 0; + uint16_t avgWaveVal=0, lastAvgWaveVal=0; + size_t i = waveStart, waveEnd, waveLenCnt, firstFullWave; + for (; i= samples[i+2]){ + waveEnd = i+1; + if (g_debugMode == 2) prnt("DEBUG PSK: waveEnd: %u, waveStart: %u", waveEnd, waveStart); + waveLenCnt = waveEnd-waveStart; + if (waveLenCnt > fc && waveStart > fc && !(waveLenCnt > fc+8)){ //not first peak and is a large wave but not out of whack + lastAvgWaveVal = avgWaveVal/(waveLenCnt); + firstFullWave = waveStart; + *fullWaveLen = waveLenCnt; + //if average wave value is > graph 0 then it is an up wave or a 1 (could cause inverting) + if (lastAvgWaveVal > FSK_PSK_THRESHOLD) *curPhase ^= 1; + return firstFullWave; + } + waveStart = i+1; + avgWaveVal = 0; + } + avgWaveVal += samples[i+2]; + } + return 0; } //by marshmellow //amplify based on ask edge detection - not accurate enough to use all the time void askAmp(uint8_t *bits, size_t size) { - uint8_t last = 128; - for(size_t i = 1; i < size; ++i){ - if ( bits[i] - bits[i-1] >= 30) //large jump up - last = 255; - else if ( bits[i-1] - bits[i] >= 20) //large jump down - last = 0; + uint8_t last = 128; + for(size_t i = 1; i < size; ++i){ + if ( bits[i] - bits[i-1] >= 30) //large jump up + last = 255; + else if ( bits[i-1] - bits[i] >= 20) //large jump down + last = 0; - bits[i] = last; - } + bits[i] = last; + } } // iceman, simplify this uint32_t manchesterEncode2Bytes(uint16_t datain) { - uint32_t output = 0; - uint8_t curBit = 0; - for (uint8_t i = 0; i < 16; i++) { - curBit = (datain >> (15-i) & 1); - output |= ( 1 << ( ( (15-i) * 2 ) + curBit)); - } - return output; + uint32_t output = 0; + uint8_t curBit = 0; + for (uint8_t i = 0; i < 16; i++) { + curBit = (datain >> (15-i) & 1); + output |= ( 1 << ( ( (15-i) * 2 ) + curBit)); + } + return output; } //by marshmellow //encode binary data into binary manchester //NOTE: bitstream must have triple the size of "size" available in memory to do the swap int ManchesterEncode(uint8_t *bits, size_t size) { - //allow up to 4096b out (means bits must be at least 2048+4096 to handle the swap) - size = (size > 2048) ? 2048 : size; - size_t modIdx = size; - size_t i; - for (size_t idx=0; idx < size; idx++){ - bits[idx+modIdx++] = bits[idx]; - bits[idx+modIdx++] = bits[idx]^1; - } - for (i=0; i < (size*2); i++){ - bits[i] = bits[i+size]; - } - return i; + //allow up to 4096b out (means bits must be at least 2048+4096 to handle the swap) + size = (size > 2048) ? 2048 : size; + size_t modIdx = size; + size_t i; + for (size_t idx=0; idx < size; idx++){ + bits[idx+modIdx++] = bits[idx]; + bits[idx+modIdx++] = bits[idx]^1; + } + for (i=0; i < (size*2); i++){ + bits[i] = bits[i+size]; + } + return i; } // by marshmellow // to detect a wave that has heavily clipped (clean) samples // loop 512 samples, if 250 of them is deemed maxed out, we assume the wave is clipped. bool DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low) { - bool allArePeaks = true; - uint16_t cntPeaks = 0; - size_t loopEnd = 512 + 160; + bool allArePeaks = true; + uint16_t cntPeaks = 0; + size_t loopEnd = 512 + 160; - // sanity check - if (loopEnd > size) loopEnd = size; + // sanity check + if (loopEnd > size) loopEnd = size; - for (size_t i = 160; i < loopEnd; i++){ + for (size_t i = 160; i < loopEnd; i++){ - if (dest[i] > low && dest[i] < high) - allArePeaks = false; - else - cntPeaks++; - } + if (dest[i] > low && dest[i] < high) + allArePeaks = false; + else + cntPeaks++; + } - if (!allArePeaks){ - if (cntPeaks > 250) return true; - } - return allArePeaks; + if (!allArePeaks){ + if (cntPeaks > 250) return true; + } + return allArePeaks; } @@ -468,38 +468,38 @@ bool DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low) { // to help detect clocks on heavily clipped samples // based on count of low to low int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clock) { - size_t startwave; - size_t i = 100; - size_t minClk = 512; - int shortestWaveIdx = 0; + size_t startwave; + size_t i = 100; + size_t minClk = 512; + int shortestWaveIdx = 0; - // get to first full low to prime loop and skip incomplete first pulse - getNextHigh(dest, size, high, &i); - getNextLow(dest, size, low, &i); + // get to first full low to prime loop and skip incomplete first pulse + getNextHigh(dest, size, high, &i); + getNextLow(dest, size, low, &i); - // loop through all samples (well, we don't want to go out-of-bounds) - while (i < size-512) { - // measure from low to low - startwave = i; + // loop through all samples (well, we don't want to go out-of-bounds) + while (i < size-512) { + // measure from low to low + startwave = i; - getNextHigh(dest, size, high, &i); - getNextLow(dest, size, low, &i); + getNextHigh(dest, size, high, &i); + getNextLow(dest, size, low, &i); - //get minimum measured distance - if (i-startwave < minClk && i < size) { - minClk = i - startwave; - shortestWaveIdx = startwave; - } - } + //get minimum measured distance + if (i-startwave < minClk && i < size) { + minClk = i - startwave; + shortestWaveIdx = startwave; + } + } - // set clock - if (g_debugMode == 2) prnt("DEBUG ASK: DetectStrongAskClock smallest wave: %d", minClk); - *clock = getClosestClock(minClk); + // set clock + if (g_debugMode == 2) prnt("DEBUG ASK: DetectStrongAskClock smallest wave: %d", minClk); + *clock = getClosestClock(minClk); - if (*clock == 0) - return -1; + if (*clock == 0) + return -1; - return shortestWaveIdx; + return shortestWaveIdx; } // by marshmellow @@ -508,312 +508,312 @@ int DetectStrongAskClock(uint8_t *dest, size_t size, int high, int low, int *clo // return start index of best starting position for that clock and return clock (by reference) int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr) { - //don't need to loop through entire array. (cotag has clock of 384) - uint16_t loopCnt = 1500; + //don't need to loop through entire array. (cotag has clock of 384) + uint16_t loopCnt = 1500; - // not enough samples - if (size <= loopCnt + 60){ - if (g_debugMode == 2) prnt("DEBUG DetectASKClock: not enough samples - aborting"); - return -1; - } + // not enough samples + if (size <= loopCnt + 60){ + if (g_debugMode == 2) prnt("DEBUG DetectASKClock: not enough samples - aborting"); + return -1; + } - // just noise - no super good detection. good enough - if (signalprop.isnoise) { - if (g_debugMode == 2) prnt("DEBUG DetectASKClock: just noise detected - aborting"); - return -2; - } + // just noise - no super good detection. good enough + if (signalprop.isnoise) { + if (g_debugMode == 2) prnt("DEBUG DetectASKClock: just noise detected - aborting"); + return -2; + } - size_t i = 1; - uint16_t num_clks = 9; - // first 255 value pos0 is placeholder for user inputed clock. - uint16_t clk[] = {255, 8, 16, 32, 40, 50, 64, 100, 128, 255}; + size_t i = 1; + uint16_t num_clks = 9; + // first 255 value pos0 is placeholder for user inputed clock. + uint16_t clk[] = {255, 8, 16, 32, 40, 50, 64, 100, 128, 255}; - // sometimes there is a strange end wave - filter out this - size -= 60; + // sometimes there is a strange end wave - filter out this + size -= 60; - // What is purpose? - // already have a valid clock? - uint8_t found_clk = 0; - for (; i < num_clks; ++i) { - if (clk[i] == *clock) { - found_clk = i; - } - } + // What is purpose? + // already have a valid clock? + uint8_t found_clk = 0; + for (; i < num_clks; ++i) { + if (clk[i] == *clock) { + found_clk = i; + } + } - // threshold 75% of high, low peak - int peak_hi, peak_low; - getHiLo(&peak_hi, &peak_low, 75, 75); + // threshold 75% of high, low peak + int peak_hi, peak_low; + getHiLo(&peak_hi, &peak_low, 75, 75); - // test for large clean, STRONG, CLIPPED peaks + // test for large clean, STRONG, CLIPPED peaks - if (!found_clk) { + if (!found_clk) { - if (DetectCleanAskWave(dest, size, peak_hi, peak_low)){ + if (DetectCleanAskWave(dest, size, peak_hi, peak_low)){ - int idx = DetectStrongAskClock(dest, size, peak_hi, peak_low, clock); - if (g_debugMode == 2) - prnt("DEBUG ASK: DetectASKClock Clean ASK Wave detected: clk %i, Best Starting Position: %i", *clock, idx); + int idx = DetectStrongAskClock(dest, size, peak_hi, peak_low, clock); + if (g_debugMode == 2) + prnt("DEBUG ASK: DetectASKClock Clean ASK Wave detected: clk %i, Best Starting Position: %i", *clock, idx); - // return shortest wave start position - if (idx > -1) - return idx; - } - } - // test for weak peaks + // return shortest wave start position + if (idx > -1) + return idx; + } + } + // test for weak peaks - // test clock if given as cmd parameter - if ( *clock > 0 ) - clk[0] = *clock; + // test clock if given as cmd parameter + if ( *clock > 0 ) + clk[0] = *clock; - uint8_t clkCnt, tol = 0; - size_t j = 0; - uint16_t bestErr[] = {1000,1000,1000,1000,1000,1000,1000,1000,1000}; - uint8_t bestStart[] = {0,0,0,0,0,0,0,0,0}; - size_t errCnt = 0, arrLoc, loopEnd; + uint8_t clkCnt, tol = 0; + size_t j = 0; + uint16_t bestErr[] = {1000,1000,1000,1000,1000,1000,1000,1000,1000}; + uint8_t bestStart[] = {0,0,0,0,0,0,0,0,0}; + size_t errCnt = 0, arrLoc, loopEnd; - if (found_clk) { - clkCnt = found_clk; - num_clks = found_clk + 1; - } else { - clkCnt = 1; - } + if (found_clk) { + clkCnt = found_clk; + num_clks = found_clk + 1; + } else { + clkCnt = 1; + } - //test each valid clock from smallest to greatest to see which lines up - for (; clkCnt < num_clks; clkCnt++) { - if (clk[clkCnt] <= 32) { - tol = 1; - } else { - tol = 0; - } - //if no errors allowed - keep start within the first clock - if (!maxErr && size > clk[clkCnt]*2 + tol && clk[clkCnt] < 128) - loopCnt = clk[clkCnt] * 2; + //test each valid clock from smallest to greatest to see which lines up + for (; clkCnt < num_clks; clkCnt++) { + if (clk[clkCnt] <= 32) { + tol = 1; + } else { + tol = 0; + } + //if no errors allowed - keep start within the first clock + if (!maxErr && size > clk[clkCnt]*2 + tol && clk[clkCnt] < 128) + loopCnt = clk[clkCnt] * 2; - bestErr[clkCnt] = 1000; + bestErr[clkCnt] = 1000; - //try lining up the peaks by moving starting point (try first few clocks) + //try lining up the peaks by moving starting point (try first few clocks) - // get to first full low to prime loop and skip incomplete first pulse - getNextHigh(dest, size, peak_hi, &j); - getNextLow(dest, size, peak_low, &j); + // get to first full low to prime loop and skip incomplete first pulse + getNextHigh(dest, size, peak_hi, &j); + getNextLow(dest, size, peak_low, &j); - for (; j < loopCnt; j++){ - errCnt = 0; - // now that we have the first one lined up test rest of wave array - loopEnd = ((size-j-tol) / clk[clkCnt]) - 1; - for (i=0; i < loopEnd; ++i){ - arrLoc = j + (i * clk[clkCnt]); - if (dest[arrLoc] >= peak_hi || dest[arrLoc] <= peak_low){ - } else if (dest[arrLoc-tol] >= peak_hi || dest[arrLoc-tol] <= peak_low){ - } else if (dest[arrLoc+tol] >= peak_hi || dest[arrLoc+tol] <= peak_low){ - } else { //error no peak detected - errCnt++; - } - } - // if we found no errors then we can stop here and a low clock (common clocks) - // this is correct one - return this clock - // if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d", clk[clkCnt], errCnt, j, i); - if (errCnt == 0 && clkCnt < 7) { - if (!found_clk) - *clock = clk[clkCnt]; - return j; - } - // if we found errors see if it is lowest so far and save it as best run - if (errCnt < bestErr[clkCnt]) { - bestErr[clkCnt] = errCnt; - bestStart[clkCnt] = j; - } - } - } + for (; j < loopCnt; j++){ + errCnt = 0; + // now that we have the first one lined up test rest of wave array + loopEnd = ((size-j-tol) / clk[clkCnt]) - 1; + for (i=0; i < loopEnd; ++i){ + arrLoc = j + (i * clk[clkCnt]); + if (dest[arrLoc] >= peak_hi || dest[arrLoc] <= peak_low){ + } else if (dest[arrLoc-tol] >= peak_hi || dest[arrLoc-tol] <= peak_low){ + } else if (dest[arrLoc+tol] >= peak_hi || dest[arrLoc+tol] <= peak_low){ + } else { //error no peak detected + errCnt++; + } + } + // if we found no errors then we can stop here and a low clock (common clocks) + // this is correct one - return this clock + // if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, err %d, startpos %d, endpos %d", clk[clkCnt], errCnt, j, i); + if (errCnt == 0 && clkCnt < 7) { + if (!found_clk) + *clock = clk[clkCnt]; + return j; + } + // if we found errors see if it is lowest so far and save it as best run + if (errCnt < bestErr[clkCnt]) { + bestErr[clkCnt] = errCnt; + bestStart[clkCnt] = j; + } + } + } - uint8_t k, best = 0; + uint8_t k, best = 0; - for (k=1; k < num_clks; ++k){ - if (bestErr[k] < bestErr[best]){ - if (bestErr[k] == 0) bestErr[k] = 1; - // current best bit to error ratio vs new bit to error ratio - if ( (size/clk[best])/bestErr[best] < (size/clk[k])/bestErr[k] ){ - best = k; - } - } - //if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, # Errors %d, Current Best Clk %d, bestStart %d", clk[k], bestErr[k], clk[best], bestStart[best]); - } + for (k=1; k < num_clks; ++k){ + if (bestErr[k] < bestErr[best]){ + if (bestErr[k] == 0) bestErr[k] = 1; + // current best bit to error ratio vs new bit to error ratio + if ( (size/clk[best])/bestErr[best] < (size/clk[k])/bestErr[k] ){ + best = k; + } + } + //if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, # Errors %d, Current Best Clk %d, bestStart %d", clk[k], bestErr[k], clk[best], bestStart[best]); + } - if (!found_clk) - *clock = clk[best]; + if (!found_clk) + *clock = clk[best]; - return bestStart[best]; + return bestStart[best]; } int DetectStrongNRZClk(uint8_t *dest, size_t size, int peak, int low, bool *strong) { - //find shortest transition from high to low - *strong = false; - size_t i = 0; - size_t transition1 = 0; - int lowestTransition = 255; - bool lastWasHigh = false; - size_t transitionSampleCount = 0; - //find first valid beginning of a high or low wave - while ((dest[i] >= peak || dest[i] <= low) && (i < size)) - ++i; - while ((dest[i] < peak && dest[i] > low) && (i < size)) - ++i; + //find shortest transition from high to low + *strong = false; + size_t i = 0; + size_t transition1 = 0; + int lowestTransition = 255; + bool lastWasHigh = false; + size_t transitionSampleCount = 0; + //find first valid beginning of a high or low wave + while ((dest[i] >= peak || dest[i] <= low) && (i < size)) + ++i; + while ((dest[i] < peak && dest[i] > low) && (i < size)) + ++i; - lastWasHigh = (dest[i] >= peak); + lastWasHigh = (dest[i] >= peak); - if (i == size) - return 0; + if (i == size) + return 0; - transition1 = i; + transition1 = i; - for (;i < size; i++) { - if ((dest[i] >= peak && !lastWasHigh) || (dest[i] <= low && lastWasHigh)) { - lastWasHigh = (dest[i] >= peak); - if (i-transition1 < lowestTransition) - lowestTransition = i-transition1; - transition1 = i; - } else if (dest[i] < peak && dest[i] > low) { - transitionSampleCount++; - } - } - if (lowestTransition == 255) - lowestTransition = 0; + for (;i < size; i++) { + if ((dest[i] >= peak && !lastWasHigh) || (dest[i] <= low && lastWasHigh)) { + lastWasHigh = (dest[i] >= peak); + if (i-transition1 < lowestTransition) + lowestTransition = i-transition1; + transition1 = i; + } else if (dest[i] < peak && dest[i] > low) { + transitionSampleCount++; + } + } + if (lowestTransition == 255) + lowestTransition = 0; - if (g_debugMode == 2) prnt("DEBUG NRZ: detectstrongNRZclk smallest wave: %d", lowestTransition); - // if less than 10% of the samples were not peaks (or 90% were peaks) then we have a strong wave - if (transitionSampleCount / size < 10) { - *strong = true; - lowestTransition = getClosestClock(lowestTransition); - } - return lowestTransition; + if (g_debugMode == 2) prnt("DEBUG NRZ: detectstrongNRZclk smallest wave: %d", lowestTransition); + // if less than 10% of the samples were not peaks (or 90% were peaks) then we have a strong wave + if (transitionSampleCount / size < 10) { + *strong = true; + lowestTransition = getClosestClock(lowestTransition); + } + return lowestTransition; } //by marshmellow //detect nrz clock by reading #peaks vs no peaks(or errors) int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx) { - size_t i = 0; - uint8_t clk[] = {8,16,32,40,50,64,100,128,255}; - size_t loopCnt = 4096; //don't need to loop through entire array... + size_t i = 0; + uint8_t clk[] = {8,16,32,40,50,64,100,128,255}; + size_t loopCnt = 4096; //don't need to loop through entire array... - //if we already have a valid clock quit - for (; i < 8; ++i) - if (clk[i] == clock) return clock; + //if we already have a valid clock quit + for (; i < 8; ++i) + if (clk[i] == clock) return clock; - if (size < 20) return 0; - // size must be larger than 20 here - if (size < loopCnt) loopCnt = size-20; + if (size < 20) return 0; + // size must be larger than 20 here + if (size < loopCnt) loopCnt = size-20; - // just noise - no super good detection. good enough - if (signalprop.isnoise) { - if (g_debugMode == 2) prnt("DEBUG DetectNZRClock: just noise detected - quitting"); - return 0; - } + // just noise - no super good detection. good enough + if (signalprop.isnoise) { + if (g_debugMode == 2) prnt("DEBUG DetectNZRClock: just noise detected - quitting"); + return 0; + } - //get high and low peak - int peak, low; - //getHiLo(dest, loopCnt, &peak, &low, 90, 90); - getHiLo(&peak, &low, 90, 90); + //get high and low peak + int peak, low; + //getHiLo(dest, loopCnt, &peak, &low, 90, 90); + getHiLo(&peak, &low, 90, 90); - bool strong = false; - int lowestTransition = DetectStrongNRZClk(dest, size-20, peak, low, &strong); - if (strong) return lowestTransition; - size_t ii; - uint8_t clkCnt; - uint8_t tol = 0; - uint16_t smplCnt = 0; - int16_t peakcnt = 0; - int16_t peaksdet[] = {0,0,0,0,0,0,0,0}; - uint16_t minPeak = 255; - bool firstpeak = true; - //test for large clipped waves - ignore first peak - for (i=0; i= peak || dest[i] <= low){ - if (firstpeak) continue; - smplCnt++; - } else { - firstpeak = false; - if (smplCnt > 0) { - if (minPeak > smplCnt && smplCnt > 7) minPeak = smplCnt; - peakcnt++; - if (g_debugMode == 2) prnt("DEBUG NRZ: minPeak: %d, smplCnt: %d, peakcnt: %d",minPeak,smplCnt,peakcnt); - smplCnt = 0; - } - } - } - if (minPeak < 8) return 0; + bool strong = false; + int lowestTransition = DetectStrongNRZClk(dest, size-20, peak, low, &strong); + if (strong) return lowestTransition; + size_t ii; + uint8_t clkCnt; + uint8_t tol = 0; + uint16_t smplCnt = 0; + int16_t peakcnt = 0; + int16_t peaksdet[] = {0,0,0,0,0,0,0,0}; + uint16_t minPeak = 255; + bool firstpeak = true; + //test for large clipped waves - ignore first peak + for (i=0; i= peak || dest[i] <= low){ + if (firstpeak) continue; + smplCnt++; + } else { + firstpeak = false; + if (smplCnt > 0) { + if (minPeak > smplCnt && smplCnt > 7) minPeak = smplCnt; + peakcnt++; + if (g_debugMode == 2) prnt("DEBUG NRZ: minPeak: %d, smplCnt: %d, peakcnt: %d",minPeak,smplCnt,peakcnt); + smplCnt = 0; + } + } + } + if (minPeak < 8) return 0; - bool errBitHigh = 0, bitHigh = 0, lastPeakHigh = 0; - uint8_t ignoreCnt = 0, ignoreWindow = 4; - int lastBit = 0; - size_t bestStart[] = {0,0,0,0,0,0,0,0,0}; - peakcnt = 0; - //test each valid clock from smallest to greatest to see which lines up - for (clkCnt=0; clkCnt < 8; ++clkCnt){ - //ignore clocks smaller than smallest peak - if (clk[clkCnt] < minPeak - (clk[clkCnt]/4)) continue; - //try lining up the peaks by moving starting point (try first 256) - for (ii=20; ii < loopCnt; ++ii){ - if ((dest[ii] >= peak) || (dest[ii] <= low)){ - peakcnt=0; - bitHigh = false; - ignoreCnt = 0; - lastBit = ii-clk[clkCnt]; - //loop through to see if this start location works - for (i = ii; i < size-20; ++i) { - //if we are at a clock bit - if ((i >= lastBit + clk[clkCnt] - tol) && (i <= lastBit + clk[clkCnt] + tol)) { - //test high/low - if (dest[i] >= peak || dest[i] <= low) { - //if same peak don't count it - if ((dest[i] >= peak && !lastPeakHigh) || (dest[i] <= low && lastPeakHigh)) { - peakcnt++; - } - lastPeakHigh = (dest[i] >= peak); - bitHigh = true; - errBitHigh = false; - ignoreCnt = ignoreWindow; - lastBit += clk[clkCnt]; - } else if (i == lastBit + clk[clkCnt] + tol) { - lastBit += clk[clkCnt]; - } - //else if not a clock bit and no peaks - } else if (dest[i] < peak && dest[i] > low){ - if (ignoreCnt == 0){ - bitHigh = false; - if (errBitHigh == true) - peakcnt--; - errBitHigh = false; - } else { - ignoreCnt--; - } - // else if not a clock bit but we have a peak - } else if ((dest[i] >= peak || dest[i] <= low) && (!bitHigh)) { - //error bar found no clock... - errBitHigh = true; - } - } - if (peakcnt > peaksdet[clkCnt]) { - bestStart[clkCnt] = ii; - peaksdet[clkCnt] = peakcnt; - } - } - } - } + bool errBitHigh = 0, bitHigh = 0, lastPeakHigh = 0; + uint8_t ignoreCnt = 0, ignoreWindow = 4; + int lastBit = 0; + size_t bestStart[] = {0,0,0,0,0,0,0,0,0}; + peakcnt = 0; + //test each valid clock from smallest to greatest to see which lines up + for (clkCnt=0; clkCnt < 8; ++clkCnt){ + //ignore clocks smaller than smallest peak + if (clk[clkCnt] < minPeak - (clk[clkCnt]/4)) continue; + //try lining up the peaks by moving starting point (try first 256) + for (ii=20; ii < loopCnt; ++ii){ + if ((dest[ii] >= peak) || (dest[ii] <= low)){ + peakcnt=0; + bitHigh = false; + ignoreCnt = 0; + lastBit = ii-clk[clkCnt]; + //loop through to see if this start location works + for (i = ii; i < size-20; ++i) { + //if we are at a clock bit + if ((i >= lastBit + clk[clkCnt] - tol) && (i <= lastBit + clk[clkCnt] + tol)) { + //test high/low + if (dest[i] >= peak || dest[i] <= low) { + //if same peak don't count it + if ((dest[i] >= peak && !lastPeakHigh) || (dest[i] <= low && lastPeakHigh)) { + peakcnt++; + } + lastPeakHigh = (dest[i] >= peak); + bitHigh = true; + errBitHigh = false; + ignoreCnt = ignoreWindow; + lastBit += clk[clkCnt]; + } else if (i == lastBit + clk[clkCnt] + tol) { + lastBit += clk[clkCnt]; + } + //else if not a clock bit and no peaks + } else if (dest[i] < peak && dest[i] > low){ + if (ignoreCnt == 0){ + bitHigh = false; + if (errBitHigh == true) + peakcnt--; + errBitHigh = false; + } else { + ignoreCnt--; + } + // else if not a clock bit but we have a peak + } else if ((dest[i] >= peak || dest[i] <= low) && (!bitHigh)) { + //error bar found no clock... + errBitHigh = true; + } + } + if (peakcnt > peaksdet[clkCnt]) { + bestStart[clkCnt] = ii; + peaksdet[clkCnt] = peakcnt; + } + } + } + } - uint8_t best = 0; - for (int m = 7; m > 0; m--){ - if ((peaksdet[m] >= (peaksdet[best]-1)) && (peaksdet[m] <= peaksdet[best]+1) && lowestTransition) { - if (clk[m] > (lowestTransition - (clk[m]/8)) && clk[m] < (lowestTransition + (clk[m]/8))) { - best = m; - } - } else if (peaksdet[m] > peaksdet[best]){ - best = m; - } - if (g_debugMode == 2) prnt("DEBUG NRZ: Clk: %d, peaks: %d, minPeak: %d, bestClk: %d, lowestTrs: %d", clk[m], peaksdet[m], minPeak, clk[best], lowestTransition); - } - *clockStartIdx = bestStart[best]; - return clk[best]; + uint8_t best = 0; + for (int m = 7; m > 0; m--){ + if ((peaksdet[m] >= (peaksdet[best]-1)) && (peaksdet[m] <= peaksdet[best]+1) && lowestTransition) { + if (clk[m] > (lowestTransition - (clk[m]/8)) && clk[m] < (lowestTransition + (clk[m]/8))) { + best = m; + } + } else if (peaksdet[m] > peaksdet[best]){ + best = m; + } + if (g_debugMode == 2) prnt("DEBUG NRZ: Clk: %d, peaks: %d, minPeak: %d, bestClk: %d, lowestTrs: %d", clk[m], peaksdet[m], minPeak, clk[best], lowestTransition); + } + *clockStartIdx = bestStart[best]; + return clk[best]; } //by marshmellow @@ -821,299 +821,299 @@ int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx) //counts and returns the 2 most common wave lengths //mainly used for FSK field clock detection uint16_t countFC(uint8_t *bits, size_t size, bool fskAdj) { - uint8_t fcLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint16_t fcCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t fcLensFnd = 0; - uint8_t lastFCcnt = 0; - uint8_t fcCounter = 0; - size_t i; - if (size < 180) return 0; + uint8_t fcLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + uint16_t fcCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + uint8_t fcLensFnd = 0; + uint8_t lastFCcnt = 0; + uint8_t fcCounter = 0; + size_t i; + if (size < 180) return 0; - // prime i to first up transition - for (i = 160; i < size-20; i++) - if (bits[i] > bits[i-1] && bits[i] >= bits[i+1]) - break; + // prime i to first up transition + for (i = 160; i < size-20; i++) + if (bits[i] > bits[i-1] && bits[i] >= bits[i+1]) + break; - for (; i < size-20; i++){ - if (bits[i] > bits[i-1] && bits[i] >= bits[i+1]){ - // new up transition - fcCounter++; - if (fskAdj){ - //if we had 5 and now have 9 then go back to 8 (for when we get a fc 9 instead of an 8) - if (lastFCcnt == 5 && fcCounter == 9) fcCounter--; + for (; i < size-20; i++){ + if (bits[i] > bits[i-1] && bits[i] >= bits[i+1]){ + // new up transition + fcCounter++; + if (fskAdj){ + //if we had 5 and now have 9 then go back to 8 (for when we get a fc 9 instead of an 8) + if (lastFCcnt == 5 && fcCounter == 9) fcCounter--; - //if fc=9 or 4 add one (for when we get a fc 9 instead of 10 or a 4 instead of a 5) - if ((fcCounter == 9) || fcCounter == 4) fcCounter++; - // save last field clock count (fc/xx) - lastFCcnt = fcCounter; - } - // find which fcLens to save it to: - for (int m=0; m<15; m++){ - if (fcLens[m] == fcCounter){ - fcCnts[m]++; - fcCounter = 0; - break; - } - } - if (fcCounter>0 && fcLensFnd<15){ - //add new fc length - fcCnts[fcLensFnd]++; - fcLens[fcLensFnd++] = fcCounter; - } - fcCounter=0; - } else { - // count sample - fcCounter++; - } - } + //if fc=9 or 4 add one (for when we get a fc 9 instead of 10 or a 4 instead of a 5) + if ((fcCounter == 9) || fcCounter == 4) fcCounter++; + // save last field clock count (fc/xx) + lastFCcnt = fcCounter; + } + // find which fcLens to save it to: + for (int m=0; m<15; m++){ + if (fcLens[m] == fcCounter){ + fcCnts[m]++; + fcCounter = 0; + break; + } + } + if (fcCounter>0 && fcLensFnd<15){ + //add new fc length + fcCnts[fcLensFnd]++; + fcLens[fcLensFnd++] = fcCounter; + } + fcCounter=0; + } else { + // count sample + fcCounter++; + } + } - uint8_t best1 = 14, best2 = 14, best3 = 14; - uint16_t maxCnt1 = 0; - // go through fclens and find which ones are bigest 2 - for (i=0; i<15; i++){ - // get the 3 best FC values - if (fcCnts[i] > maxCnt1) { - best3 = best2; - best2 = best1; - maxCnt1 = fcCnts[i]; - best1 = i; - } else if(fcCnts[i] > fcCnts[best2]){ - best3 = best2; - best2 = i; - } else if(fcCnts[i] > fcCnts[best3]){ - best3 = i; - } - if (g_debugMode == 2) prnt("DEBUG countfc: FC %u, Cnt %u, best fc: %u, best2 fc: %u", fcLens[i], fcCnts[i], fcLens[best1], fcLens[best2]); - if (fcLens[i] == 0) break; - } + uint8_t best1 = 14, best2 = 14, best3 = 14; + uint16_t maxCnt1 = 0; + // go through fclens and find which ones are bigest 2 + for (i=0; i<15; i++){ + // get the 3 best FC values + if (fcCnts[i] > maxCnt1) { + best3 = best2; + best2 = best1; + maxCnt1 = fcCnts[i]; + best1 = i; + } else if(fcCnts[i] > fcCnts[best2]){ + best3 = best2; + best2 = i; + } else if(fcCnts[i] > fcCnts[best3]){ + best3 = i; + } + if (g_debugMode == 2) prnt("DEBUG countfc: FC %u, Cnt %u, best fc: %u, best2 fc: %u", fcLens[i], fcCnts[i], fcLens[best1], fcLens[best2]); + if (fcLens[i] == 0) break; + } - if (fcLens[best1] == 0) return 0; - uint8_t fcH = 0, fcL = 0; - if (fcLens[best1] > fcLens[best2]){ - fcH = fcLens[best1]; - fcL = fcLens[best2]; - } else{ - fcH = fcLens[best2]; - fcL = fcLens[best1]; - } - if ((size-180)/fcH/3 > fcCnts[best1] + fcCnts[best2]) { - if (g_debugMode == 2) prnt("DEBUG countfc: fc is too large: %u > %u. Not psk or fsk", (size-180)/fcH/3, fcCnts[best1] + fcCnts[best2]); - return 0; //lots of waves not psk or fsk - } - // TODO: take top 3 answers and compare to known Field clocks to get top 2 + if (fcLens[best1] == 0) return 0; + uint8_t fcH = 0, fcL = 0; + if (fcLens[best1] > fcLens[best2]){ + fcH = fcLens[best1]; + fcL = fcLens[best2]; + } else{ + fcH = fcLens[best2]; + fcL = fcLens[best1]; + } + if ((size-180)/fcH/3 > fcCnts[best1] + fcCnts[best2]) { + if (g_debugMode == 2) prnt("DEBUG countfc: fc is too large: %u > %u. Not psk or fsk", (size-180)/fcH/3, fcCnts[best1] + fcCnts[best2]); + return 0; //lots of waves not psk or fsk + } + // TODO: take top 3 answers and compare to known Field clocks to get top 2 - uint16_t fcs = (((uint16_t)fcH)<<8) | fcL; - if (fskAdj) return fcs; - return (uint16_t)fcLens[best2] << 8 | fcLens[best1]; + uint16_t fcs = (((uint16_t)fcH)<<8) | fcL; + if (fskAdj) return fcs; + return (uint16_t)fcLens[best2] << 8 | fcLens[best1]; } //by marshmellow //detect psk clock by reading each phase shift // a phase shift is determined by measuring the sample length of each wave int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShift, uint8_t *curPhase, uint8_t *fc) { - uint8_t clk[] = {255,16,32,40,50,64,100,128,255}; //255 is not a valid clock - uint16_t loopCnt = 4096; //don't need to loop through entire array... + uint8_t clk[] = {255,16,32,40,50,64,100,128,255}; //255 is not a valid clock + uint16_t loopCnt = 4096; //don't need to loop through entire array... - //if we already have a valid clock quit - size_t i = 1; - for (; i < 8; ++i) - if (clk[i] == clock) return clock; + //if we already have a valid clock quit + size_t i = 1; + for (; i < 8; ++i) + if (clk[i] == clock) return clock; - if (size < 160+20) return 0; - // size must be larger than 20 here, and 160 later on. - if (size < loopCnt) loopCnt = size-20; + if (size < 160+20) return 0; + // size must be larger than 20 here, and 160 later on. + if (size < loopCnt) loopCnt = size-20; - uint16_t fcs = countFC(dest, size, 0); + uint16_t fcs = countFC(dest, size, 0); - *fc = fcs & 0xFF; + *fc = fcs & 0xFF; - if (g_debugMode == 2) prnt("DEBUG PSK: FC: %d, FC2: %d",*fc, fcs>>8); + if (g_debugMode == 2) prnt("DEBUG PSK: FC: %d, FC2: %d",*fc, fcs>>8); - if ((fcs >> 8) == 10 && *fc == 8) return 0; + if ((fcs >> 8) == 10 && *fc == 8) return 0; - if (*fc != 2 && *fc != 4 && *fc != 8) return 0; + if (*fc != 2 && *fc != 4 && *fc != 8) return 0; - size_t waveStart=0, waveEnd=0, firstFullWave=0, lastClkBit=0; + size_t waveStart=0, waveEnd=0, firstFullWave=0, lastClkBit=0; - uint8_t clkCnt, tol=1; - uint16_t peakcnt=0, errCnt=0, waveLenCnt=0, fullWaveLen=0; - uint16_t bestErr[] = {1000,1000,1000,1000,1000,1000,1000,1000,1000}; - uint16_t peaksdet[] = {0,0,0,0,0,0,0,0,0}; + uint8_t clkCnt, tol=1; + uint16_t peakcnt=0, errCnt=0, waveLenCnt=0, fullWaveLen=0; + uint16_t bestErr[] = {1000,1000,1000,1000,1000,1000,1000,1000,1000}; + uint16_t peaksdet[] = {0,0,0,0,0,0,0,0,0}; - //find start of modulating data in trace - i = findModStart(dest, size, *fc); + //find start of modulating data in trace + i = findModStart(dest, size, *fc); - firstFullWave = pskFindFirstPhaseShift(dest, size, curPhase, i, *fc, &fullWaveLen); - if (firstFullWave == 0) { - // no phase shift detected - could be all 1's or 0's - doesn't matter where we start - // so skip a little to ensure we are past any Start Signal - firstFullWave = 160; - fullWaveLen = 0; - } + firstFullWave = pskFindFirstPhaseShift(dest, size, curPhase, i, *fc, &fullWaveLen); + if (firstFullWave == 0) { + // no phase shift detected - could be all 1's or 0's - doesn't matter where we start + // so skip a little to ensure we are past any Start Signal + firstFullWave = 160; + fullWaveLen = 0; + } - *firstPhaseShift = firstFullWave; - if (g_debugMode == 2) prnt("DEBUG PSK: firstFullWave: %d, waveLen: %d",firstFullWave,fullWaveLen); + *firstPhaseShift = firstFullWave; + if (g_debugMode == 2) prnt("DEBUG PSK: firstFullWave: %d, waveLen: %d",firstFullWave,fullWaveLen); - //test each valid clock from greatest to smallest to see which lines up - for (clkCnt=7; clkCnt >= 1 ; clkCnt--){ - tol = *fc/2; - lastClkBit = firstFullWave; //set end of wave as clock align - waveStart = 0; - errCnt = 0; - peakcnt = 0; - if (g_debugMode == 2) prnt("DEBUG PSK: clk: %d, lastClkBit: %d", clk[clkCnt], lastClkBit); + //test each valid clock from greatest to smallest to see which lines up + for (clkCnt=7; clkCnt >= 1 ; clkCnt--){ + tol = *fc/2; + lastClkBit = firstFullWave; //set end of wave as clock align + waveStart = 0; + errCnt = 0; + peakcnt = 0; + if (g_debugMode == 2) prnt("DEBUG PSK: clk: %d, lastClkBit: %d", clk[clkCnt], lastClkBit); - for (i = firstFullWave+fullWaveLen-1; i < loopCnt-2; i++){ - //top edge of wave = start of new wave - if (dest[i] < dest[i+1] && dest[i+1] >= dest[i+2]){ - if (waveStart == 0) { - waveStart = i+1; - waveLenCnt = 0; - } else { //waveEnd - waveEnd = i+1; - waveLenCnt = waveEnd-waveStart; - if (waveLenCnt > *fc){ - //if this wave is a phase shift - if (g_debugMode == 2) prnt("DEBUG PSK: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d", waveStart, waveLenCnt, lastClkBit + clk[clkCnt] - tol, i+1, *fc); - if (i+1 >= lastClkBit + clk[clkCnt] - tol){ //should be a clock bit - peakcnt++; - lastClkBit += clk[clkCnt]; - } else if (i < lastClkBit+8){ - //noise after a phase shift - ignore - } else { //phase shift before supposed to based on clock - errCnt++; - } - } else if (i+1 > lastClkBit + clk[clkCnt] + tol + *fc){ - lastClkBit+=clk[clkCnt]; //no phase shift but clock bit - } - waveStart = i+1; - } - } - } - if (errCnt == 0) return clk[clkCnt]; - if (errCnt <= bestErr[clkCnt]) bestErr[clkCnt] = errCnt; - if (peakcnt > peaksdet[clkCnt]) peaksdet[clkCnt] = peakcnt; - } - //all tested with errors - //return the highest clk with the most peaks found - uint8_t best = 7; - for (i=7; i >= 1; i--){ - if (peaksdet[i] > peaksdet[best]) - best = i; + for (i = firstFullWave+fullWaveLen-1; i < loopCnt-2; i++){ + //top edge of wave = start of new wave + if (dest[i] < dest[i+1] && dest[i+1] >= dest[i+2]){ + if (waveStart == 0) { + waveStart = i+1; + waveLenCnt = 0; + } else { //waveEnd + waveEnd = i+1; + waveLenCnt = waveEnd-waveStart; + if (waveLenCnt > *fc){ + //if this wave is a phase shift + if (g_debugMode == 2) prnt("DEBUG PSK: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d", waveStart, waveLenCnt, lastClkBit + clk[clkCnt] - tol, i+1, *fc); + if (i+1 >= lastClkBit + clk[clkCnt] - tol){ //should be a clock bit + peakcnt++; + lastClkBit += clk[clkCnt]; + } else if (i < lastClkBit+8){ + //noise after a phase shift - ignore + } else { //phase shift before supposed to based on clock + errCnt++; + } + } else if (i+1 > lastClkBit + clk[clkCnt] + tol + *fc){ + lastClkBit+=clk[clkCnt]; //no phase shift but clock bit + } + waveStart = i+1; + } + } + } + if (errCnt == 0) return clk[clkCnt]; + if (errCnt <= bestErr[clkCnt]) bestErr[clkCnt] = errCnt; + if (peakcnt > peaksdet[clkCnt]) peaksdet[clkCnt] = peakcnt; + } + //all tested with errors + //return the highest clk with the most peaks found + uint8_t best = 7; + for (i=7; i >= 1; i--){ + if (peaksdet[i] > peaksdet[best]) + best = i; - if (g_debugMode == 2) prnt("DEBUG PSK: Clk: %d, peaks: %d, errs: %d, bestClk: %d",clk[i],peaksdet[i],bestErr[i],clk[best]); - } - return clk[best]; + if (g_debugMode == 2) prnt("DEBUG PSK: Clk: %d, peaks: %d, errs: %d, bestClk: %d",clk[i],peaksdet[i],bestErr[i],clk[best]); + } + return clk[best]; } //by marshmellow //detects the bit clock for FSK given the high and low Field Clocks uint8_t detectFSKClk(uint8_t *bits, size_t size, uint8_t fcHigh, uint8_t fcLow, int *firstClockEdge) { - if (size == 0) - return 0; + if (size == 0) + return 0; - uint8_t clk[] = {8,16,32,40,50,64,100,128,0}; - uint16_t rfLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t rfCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; - uint8_t rfLensFnd = 0; - uint8_t lastFCcnt = 0; - uint16_t fcCounter = 0; - uint16_t rfCounter = 0; - uint8_t firstBitFnd = 0; - size_t i; - uint8_t fcTol = ((fcHigh * 100 - fcLow * 100)/2 + 50)/100; //(uint8_t)(0.5+(float)(fcHigh-fcLow)/2); + uint8_t clk[] = {8,16,32,40,50,64,100,128,0}; + uint16_t rfLens[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + uint8_t rfCnts[] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; + uint8_t rfLensFnd = 0; + uint8_t lastFCcnt = 0; + uint16_t fcCounter = 0; + uint16_t rfCounter = 0; + uint8_t firstBitFnd = 0; + size_t i; + uint8_t fcTol = ((fcHigh * 100 - fcLow * 100)/2 + 50)/100; //(uint8_t)(0.5+(float)(fcHigh-fcLow)/2); - // prime i to first peak / up transition - for (i = 160; i < size-20; i++) - if (bits[i] > bits[i-1] && bits[i] >= bits[i+1]) - break; + // prime i to first peak / up transition + for (i = 160; i < size-20; i++) + if (bits[i] > bits[i-1] && bits[i] >= bits[i+1]) + break; - for (; i < size-20; i++){ - fcCounter++; - rfCounter++; + for (; i < size-20; i++){ + fcCounter++; + rfCounter++; - if (bits[i] <= bits[i-1] || bits[i] < bits[i+1]) - continue; - // else new peak - // if we got less than the small fc + tolerance then set it to the small fc - // if it is inbetween set it to the last counter - if (fcCounter < fcHigh && fcCounter > fcLow) - fcCounter = lastFCcnt; - else if (fcCounter < fcLow+fcTol) - fcCounter = fcLow; - else //set it to the large fc - fcCounter = fcHigh; + if (bits[i] <= bits[i-1] || bits[i] < bits[i+1]) + continue; + // else new peak + // if we got less than the small fc + tolerance then set it to the small fc + // if it is inbetween set it to the last counter + if (fcCounter < fcHigh && fcCounter > fcLow) + fcCounter = lastFCcnt; + else if (fcCounter < fcLow+fcTol) + fcCounter = fcLow; + else //set it to the large fc + fcCounter = fcHigh; - //look for bit clock (rf/xx) - if ((fcCounter < lastFCcnt || fcCounter > lastFCcnt)){ - //not the same size as the last wave - start of new bit sequence - if (firstBitFnd > 1){ //skip first wave change - probably not a complete bit - for (int ii=0; ii<15; ii++){ - if (rfLens[ii] >= (rfCounter-4) && rfLens[ii] <= (rfCounter+4)){ - rfCnts[ii]++; - rfCounter = 0; - break; - } - } - if (rfCounter > 0 && rfLensFnd < 15){ - //prnt("DEBUG: rfCntr %d, fcCntr %d",rfCounter,fcCounter); - rfCnts[rfLensFnd]++; - rfLens[rfLensFnd++] = rfCounter; - } - } else { - *firstClockEdge = i; - firstBitFnd++; - } - rfCounter = 0; - lastFCcnt = fcCounter; - } - fcCounter = 0; - } - uint8_t rfHighest = 15, rfHighest2 = 15, rfHighest3 = 15; + //look for bit clock (rf/xx) + if ((fcCounter < lastFCcnt || fcCounter > lastFCcnt)){ + //not the same size as the last wave - start of new bit sequence + if (firstBitFnd > 1){ //skip first wave change - probably not a complete bit + for (int ii=0; ii<15; ii++){ + if (rfLens[ii] >= (rfCounter-4) && rfLens[ii] <= (rfCounter+4)){ + rfCnts[ii]++; + rfCounter = 0; + break; + } + } + if (rfCounter > 0 && rfLensFnd < 15){ + //prnt("DEBUG: rfCntr %d, fcCntr %d",rfCounter,fcCounter); + rfCnts[rfLensFnd]++; + rfLens[rfLensFnd++] = rfCounter; + } + } else { + *firstClockEdge = i; + firstBitFnd++; + } + rfCounter = 0; + lastFCcnt = fcCounter; + } + fcCounter = 0; + } + uint8_t rfHighest = 15, rfHighest2 = 15, rfHighest3 = 15; - for (i=0; i<15; i++){ - //get highest 2 RF values (might need to get more values to compare or compare all?) - if (rfCnts[i] > rfCnts[rfHighest]){ - rfHighest3 = rfHighest2; - rfHighest2 = rfHighest; - rfHighest = i; - } else if(rfCnts[i] > rfCnts[rfHighest2]){ - rfHighest3 = rfHighest2; - rfHighest2 = i; - } else if(rfCnts[i] > rfCnts[rfHighest3]){ - rfHighest3 = i; - } - if (g_debugMode == 2) - prnt("DEBUG FSK: RF %d, cnts %d", rfLens[i], rfCnts[i]); - } - // set allowed clock remainder tolerance to be 1 large field clock length+1 - // we could have mistakenly made a 9 a 10 instead of an 8 or visa versa so rfLens could be 1 FC off - uint8_t tol1 = fcHigh+1; + for (i=0; i<15; i++){ + //get highest 2 RF values (might need to get more values to compare or compare all?) + if (rfCnts[i] > rfCnts[rfHighest]){ + rfHighest3 = rfHighest2; + rfHighest2 = rfHighest; + rfHighest = i; + } else if(rfCnts[i] > rfCnts[rfHighest2]){ + rfHighest3 = rfHighest2; + rfHighest2 = i; + } else if(rfCnts[i] > rfCnts[rfHighest3]){ + rfHighest3 = i; + } + if (g_debugMode == 2) + prnt("DEBUG FSK: RF %d, cnts %d", rfLens[i], rfCnts[i]); + } + // set allowed clock remainder tolerance to be 1 large field clock length+1 + // we could have mistakenly made a 9 a 10 instead of an 8 or visa versa so rfLens could be 1 FC off + uint8_t tol1 = fcHigh+1; - if (g_debugMode == 2) - prnt("DEBUG FSK: most counted rf values: 1 %d, 2 %d, 3 %d", rfLens[rfHighest], rfLens[rfHighest2], rfLens[rfHighest3]); + if (g_debugMode == 2) + prnt("DEBUG FSK: most counted rf values: 1 %d, 2 %d, 3 %d", rfLens[rfHighest], rfLens[rfHighest2], rfLens[rfHighest3]); - // loop to find the highest clock that has a remainder less than the tolerance - // compare samples counted divided by - // test 128 down to 32 (shouldn't be possible to have fc/10 & fc/8 and rf/16 or less) - int m = 7; - for (; m >= 2; m--){ - if (rfLens[rfHighest] % clk[m] < tol1 || rfLens[rfHighest] % clk[m] > clk[m]-tol1){ - if (rfLens[rfHighest2] % clk[m] < tol1 || rfLens[rfHighest2] % clk[m] > clk[m]-tol1){ - if (rfLens[rfHighest3] % clk[m] < tol1 || rfLens[rfHighest3] % clk[m] > clk[m]-tol1){ - if (g_debugMode == 2) - prnt("DEBUG FSK: clk %d divides into the 3 most rf values within tolerance", clk[m]); - break; - } - } - } - } + // loop to find the highest clock that has a remainder less than the tolerance + // compare samples counted divided by + // test 128 down to 32 (shouldn't be possible to have fc/10 & fc/8 and rf/16 or less) + int m = 7; + for (; m >= 2; m--){ + if (rfLens[rfHighest] % clk[m] < tol1 || rfLens[rfHighest] % clk[m] > clk[m]-tol1){ + if (rfLens[rfHighest2] % clk[m] < tol1 || rfLens[rfHighest2] % clk[m] > clk[m]-tol1){ + if (rfLens[rfHighest3] % clk[m] < tol1 || rfLens[rfHighest3] % clk[m] > clk[m]-tol1){ + if (g_debugMode == 2) + prnt("DEBUG FSK: clk %d divides into the 3 most rf values within tolerance", clk[m]); + break; + } + } + } + } - if (m < 2) return 0; // oops we went too far + if (m < 2) return 0; // oops we went too far - return clk[m]; + return clk[m]; } @@ -1124,145 +1124,145 @@ uint8_t detectFSKClk(uint8_t *bits, size_t size, uint8_t fcHigh, uint8_t fcLow, // look for Sequence Terminator - should be pulses of clk*(1 or 2), clk*2, clk*(1.5 or 2), by idx we mean graph position index... bool findST(int *stStopLoc, int *stStartIdx, int lowToLowWaveLen[], int highToLowWaveLen[], int clk, int tol, int buffSize, size_t *i) { - if (buffSize < *i+4) return false; + if (buffSize < *i+4) return false; - for (; *i < buffSize - 4; *i+=1) { - *stStartIdx += lowToLowWaveLen[*i]; //caution part of this wave may be data and part may be ST.... to be accounted for in main function for now... - if (lowToLowWaveLen[*i] >= clk*1-tol && lowToLowWaveLen[*i] <= (clk*2)+tol && highToLowWaveLen[*i] < clk+tol) { //1 to 2 clocks depending on 2 bits prior - if (lowToLowWaveLen[*i+1] >= clk*2-tol && lowToLowWaveLen[*i+1] <= clk*2+tol && highToLowWaveLen[*i+1] > clk*3/2-tol) { //2 clocks and wave size is 1 1/2 - if (lowToLowWaveLen[*i+2] >= (clk*3)/2-tol && lowToLowWaveLen[*i+2] <= clk*2+tol && highToLowWaveLen[*i+2] > clk-tol) { //1 1/2 to 2 clocks and at least one full clock wave - if (lowToLowWaveLen[*i+3] >= clk*1-tol && lowToLowWaveLen[*i+3] <= clk*2+tol) { //1 to 2 clocks for end of ST + first bit - *stStopLoc = *i + 3; - return true; - } - } - } - } - } - return false; + for (; *i < buffSize - 4; *i+=1) { + *stStartIdx += lowToLowWaveLen[*i]; //caution part of this wave may be data and part may be ST.... to be accounted for in main function for now... + if (lowToLowWaveLen[*i] >= clk*1-tol && lowToLowWaveLen[*i] <= (clk*2)+tol && highToLowWaveLen[*i] < clk+tol) { //1 to 2 clocks depending on 2 bits prior + if (lowToLowWaveLen[*i+1] >= clk*2-tol && lowToLowWaveLen[*i+1] <= clk*2+tol && highToLowWaveLen[*i+1] > clk*3/2-tol) { //2 clocks and wave size is 1 1/2 + if (lowToLowWaveLen[*i+2] >= (clk*3)/2-tol && lowToLowWaveLen[*i+2] <= clk*2+tol && highToLowWaveLen[*i+2] > clk-tol) { //1 1/2 to 2 clocks and at least one full clock wave + if (lowToLowWaveLen[*i+3] >= clk*1-tol && lowToLowWaveLen[*i+3] <= clk*2+tol) { //1 to 2 clocks for end of ST + first bit + *stStopLoc = *i + 3; + return true; + } + } + } + } + } + return false; } //by marshmellow //attempt to identify a Sequence Terminator in ASK modulated raw wave bool DetectST(uint8_t *buffer, size_t *size, int *foundclock, size_t *ststart, size_t *stend) { - size_t bufsize = *size; - //need to loop through all samples and identify our clock, look for the ST pattern - int clk = 0; - int tol = 0; - int j=0, high, low, skip=0, start=0, end=0, minClk=255; - size_t i = 0; - //probably should malloc... || test if memory is available ... handle device side? memory danger!!! [marshmellow] - int tmpbuff[bufsize / LOWEST_DEFAULT_CLOCK]; // low to low wave count //guess rf/32 clock, if click is smaller we will only have room for a fraction of the samples captured - int waveLen[bufsize / LOWEST_DEFAULT_CLOCK]; // high to low wave count //if clock is larger then we waste memory in array size that is not needed... - //size_t testsize = (bufsize < 512) ? bufsize : 512; - int phaseoff = 0; - high = low = 128; - memset(tmpbuff, 0, sizeof(tmpbuff)); - memset(waveLen, 0, sizeof(waveLen)); + size_t bufsize = *size; + //need to loop through all samples and identify our clock, look for the ST pattern + int clk = 0; + int tol = 0; + int j=0, high, low, skip=0, start=0, end=0, minClk=255; + size_t i = 0; + //probably should malloc... || test if memory is available ... handle device side? memory danger!!! [marshmellow] + int tmpbuff[bufsize / LOWEST_DEFAULT_CLOCK]; // low to low wave count //guess rf/32 clock, if click is smaller we will only have room for a fraction of the samples captured + int waveLen[bufsize / LOWEST_DEFAULT_CLOCK]; // high to low wave count //if clock is larger then we waste memory in array size that is not needed... + //size_t testsize = (bufsize < 512) ? bufsize : 512; + int phaseoff = 0; + high = low = 128; + memset(tmpbuff, 0, sizeof(tmpbuff)); + memset(waveLen, 0, sizeof(waveLen)); - if (!loadWaveCounters(buffer, bufsize, tmpbuff, waveLen, &j, &skip, &minClk, &high, &low)) return false; - // set clock - might be able to get this externally and remove this work... - clk = getClosestClock(minClk); - // clock not found - ERROR - if (!clk) { - if (g_debugMode == 2) prnt("DEBUG STT: clock not found - quitting"); - return false; - } - *foundclock = clk; + if (!loadWaveCounters(buffer, bufsize, tmpbuff, waveLen, &j, &skip, &minClk, &high, &low)) return false; + // set clock - might be able to get this externally and remove this work... + clk = getClosestClock(minClk); + // clock not found - ERROR + if (!clk) { + if (g_debugMode == 2) prnt("DEBUG STT: clock not found - quitting"); + return false; + } + *foundclock = clk; - tol = clk/8; - if (!findST(&start, &skip, tmpbuff, waveLen, clk, tol, j, &i)) { - // first ST not found - ERROR - if (g_debugMode == 2) prnt("DEBUG STT: first STT not found - quitting"); - return false; - } else { - if (g_debugMode == 2) prnt("DEBUG STT: first STT found at wave: %i, skip: %i, j=%i", start, skip, j); - } - if (waveLen[i+2] > clk*1+tol) - phaseoff = 0; - else - phaseoff = clk/2; + tol = clk/8; + if (!findST(&start, &skip, tmpbuff, waveLen, clk, tol, j, &i)) { + // first ST not found - ERROR + if (g_debugMode == 2) prnt("DEBUG STT: first STT not found - quitting"); + return false; + } else { + if (g_debugMode == 2) prnt("DEBUG STT: first STT found at wave: %i, skip: %i, j=%i", start, skip, j); + } + if (waveLen[i+2] > clk*1+tol) + phaseoff = 0; + else + phaseoff = clk/2; - // skip over the remainder of ST - skip += clk*7/2; //3.5 clocks from tmpbuff[i] = end of st - also aligns for ending point + // skip over the remainder of ST + skip += clk*7/2; //3.5 clocks from tmpbuff[i] = end of st - also aligns for ending point - // now do it again to find the end - int dummy1 = 0; - end = skip; - i += 3; - if (!findST(&dummy1, &end, tmpbuff, waveLen, clk, tol, j, &i)) { - //didn't find second ST - ERROR - if (g_debugMode == 2) prnt("DEBUG STT: second STT not found - quitting"); - return false; - } - end -= phaseoff; - if (g_debugMode == 2) prnt("DEBUG STT: start of data: %d end of data: %d, datalen: %d, clk: %d, bits: %d, phaseoff: %d", skip, end, end-skip, clk, (end-skip)/clk, phaseoff); - //now begin to trim out ST so we can use normal demod cmds - start = skip; - size_t datalen = end - start; - // check validity of datalen (should be even clock increments) - use a tolerance of up to 1/8th a clock - if ( clk - (datalen % clk) <= clk/8) { - // padd the amount off - could be problematic... but shouldn't happen often - datalen += clk - (datalen % clk); - } else if ( (datalen % clk) <= clk/8 ) { - // padd the amount off - could be problematic... but shouldn't happen often - datalen -= datalen % clk; - } else { - if (g_debugMode == 2) prnt("DEBUG STT: datalen not divisible by clk: %u %% %d = %d - quitting", datalen, clk, datalen % clk); - return false; - } - // if datalen is less than one t55xx block - ERROR - if (datalen/clk < 8*4) { - if (g_debugMode == 2) prnt("DEBUG STT: datalen is less than 1 full t55xx block - quitting"); - return false; - } - size_t dataloc = start; - if (buffer[dataloc-(clk*4)-(clk/4)] <= low && buffer[dataloc] <= low && buffer[dataloc-(clk*4)] >= high) { - //we have low drift (and a low just before the ST and a low just after the ST) - compensate by backing up the start - for ( i=0; i <= (clk/4); ++i ) { - if ( buffer[dataloc - (clk*4) - i] <= low ) { - dataloc -= i; - break; - } - } - } + // now do it again to find the end + int dummy1 = 0; + end = skip; + i += 3; + if (!findST(&dummy1, &end, tmpbuff, waveLen, clk, tol, j, &i)) { + //didn't find second ST - ERROR + if (g_debugMode == 2) prnt("DEBUG STT: second STT not found - quitting"); + return false; + } + end -= phaseoff; + if (g_debugMode == 2) prnt("DEBUG STT: start of data: %d end of data: %d, datalen: %d, clk: %d, bits: %d, phaseoff: %d", skip, end, end-skip, clk, (end-skip)/clk, phaseoff); + //now begin to trim out ST so we can use normal demod cmds + start = skip; + size_t datalen = end - start; + // check validity of datalen (should be even clock increments) - use a tolerance of up to 1/8th a clock + if ( clk - (datalen % clk) <= clk/8) { + // padd the amount off - could be problematic... but shouldn't happen often + datalen += clk - (datalen % clk); + } else if ( (datalen % clk) <= clk/8 ) { + // padd the amount off - could be problematic... but shouldn't happen often + datalen -= datalen % clk; + } else { + if (g_debugMode == 2) prnt("DEBUG STT: datalen not divisible by clk: %u %% %d = %d - quitting", datalen, clk, datalen % clk); + return false; + } + // if datalen is less than one t55xx block - ERROR + if (datalen/clk < 8*4) { + if (g_debugMode == 2) prnt("DEBUG STT: datalen is less than 1 full t55xx block - quitting"); + return false; + } + size_t dataloc = start; + if (buffer[dataloc-(clk*4)-(clk/4)] <= low && buffer[dataloc] <= low && buffer[dataloc-(clk*4)] >= high) { + //we have low drift (and a low just before the ST and a low just after the ST) - compensate by backing up the start + for ( i=0; i <= (clk/4); ++i ) { + if ( buffer[dataloc - (clk*4) - i] <= low ) { + dataloc -= i; + break; + } + } + } - size_t newloc = 0; - i=0; - if (g_debugMode == 2) prnt("DEBUG STT: Starting STT trim - start: %d, datalen: %d ",dataloc, datalen); - bool firstrun = true; - // warning - overwriting buffer given with raw wave data with ST removed... - while ( dataloc < bufsize-(clk/2) ) { - //compensate for long high at end of ST not being high due to signal loss... (and we cut out the start of wave high part) - if (buffer[dataloc]low && buffer[dataloc+clk/4]low) { - for(i=0; i < clk/2-tol; ++i) { - buffer[dataloc+i] = high+5; - } - } //test for small spike outlier (high between two lows) in the case of very strong waves - if (buffer[dataloc] > low && buffer[dataloc+clk/4] <= low) { - for(i=0; i < clk/4; ++i) { - buffer[dataloc+i] = buffer[dataloc+clk/4]; - } - } - if (firstrun) { - *stend = dataloc; - *ststart = dataloc-(clk*4); - firstrun=false; - } - for (i=0; ilow && buffer[dataloc+clk/4]low) { + for(i=0; i < clk/2-tol; ++i) { + buffer[dataloc+i] = high+5; + } + } //test for small spike outlier (high between two lows) in the case of very strong waves + if (buffer[dataloc] > low && buffer[dataloc+clk/4] <= low) { + for(i=0; i < clk/4; ++i) { + buffer[dataloc+i] = buffer[dataloc+clk/4]; + } + } + if (firstrun) { + *stend = dataloc; + *ststart = dataloc-(clk*4); + firstrun=false; + } + for (i=0; i 2 && (halfClkErr & 0x7) == 0) || (halfClkErr & 0x1F) == 0x1F) { - errCnt++; - bits[bitCnt++] = 7; - continue; - } - bits[bitCnt++] = bits[i] ^ bits[i+1] ^ invert; + //find alignment, needs 4 1s or 0s to properly align + for (i=1; i < *size-1; i++) { + alignCnt = (bits[i] == curBit) ? alignCnt+1 : 0; + curBit = bits[i]; + if (alignCnt == 4) break; + } + // for now error if alignment not found. later add option to run it with multiple offsets... + if (alignCnt != 4) { + if (g_debugMode) prnt("ERROR MillerDecode: alignment not found so either your bits is not miller or your data does not have a 101 in it"); + return -1; + } + alignedIdx = (i-1) % 2; + for (i = alignedIdx; i < *size-3; i += 2) { + halfClkErr = (uint8_t)((halfClkErr << 1 | bits[i]) & 0xFF); + if ( (halfClkErr & 0x7) == 5 || (halfClkErr & 0x7) == 2 || (i > 2 && (halfClkErr & 0x7) == 0) || (halfClkErr & 0x1F) == 0x1F) { + errCnt++; + bits[bitCnt++] = 7; + continue; + } + bits[bitCnt++] = bits[i] ^ bits[i+1] ^ invert; - if (bitCnt > MaxBits) break; - } - *size = bitCnt; - return errCnt; + if (bitCnt > MaxBits) break; + } + *size = bitCnt; + return errCnt; } //by marshmellow @@ -1309,40 +1309,40 @@ int millerRawDecode(uint8_t *bits, size_t *size, int invert) { //check for phase errors - should never have 111 or 000 should be 01001011 or 10110100 for 1010 //decodes biphase or if inverted it is AKA conditional dephase encoding AKA differential manchester encoding int BiphaseRawDecode(uint8_t *bits, size_t *size, int *offset, int invert) { - //sanity check - if (*size < 51) return -1; + //sanity check + if (*size < 51) return -1; - uint16_t bitnum = 0; - uint16_t errCnt = 0; - size_t i = *offset; - uint16_t maxbits = 512; + uint16_t bitnum = 0; + uint16_t errCnt = 0; + size_t i = *offset; + uint16_t maxbits = 512; - //check for phase change faults - skip one sample if faulty - bool offsetA = true, offsetB = true; - for (; i < *offset+48; i += 2){ - if (bits[i+1] == bits[i+2]) offsetA = false; - if (bits[i+2] == bits[i+3]) offsetB = false; - } - if (!offsetA && offsetB) ++*offset; + //check for phase change faults - skip one sample if faulty + bool offsetA = true, offsetB = true; + for (; i < *offset+48; i += 2){ + if (bits[i+1] == bits[i+2]) offsetA = false; + if (bits[i+2] == bits[i+3]) offsetB = false; + } + if (!offsetA && offsetB) ++*offset; - for (i = *offset; i < *size-3; i += 2){ - //check for phase error - if (bits[i+1] == bits[i+2]) { - bits[bitnum++] = 7; - errCnt++; - } - if((bits[i]==1 && bits[i+1]==0) || (bits[i]==0 && bits[i+1]==1)){ - bits[bitnum++] = 1 ^ invert; - } else if((bits[i]==0 && bits[i+1]==0) || (bits[i]==1 && bits[i+1]==1)){ - bits[bitnum++] = invert; - } else { - bits[bitnum++] = 7; - errCnt++; - } - if (bitnum > maxbits) break; - } - *size = bitnum; - return errCnt; + for (i = *offset; i < *size-3; i += 2){ + //check for phase error + if (bits[i+1] == bits[i+2]) { + bits[bitnum++] = 7; + errCnt++; + } + if((bits[i]==1 && bits[i+1]==0) || (bits[i]==0 && bits[i+1]==1)){ + bits[bitnum++] = 1 ^ invert; + } else if((bits[i]==0 && bits[i+1]==0) || (bits[i]==1 && bits[i+1]==1)){ + bits[bitnum++] = invert; + } else { + bits[bitnum++] = 7; + errCnt++; + } + if (bitnum > maxbits) break; + } + *size = bitnum; + return errCnt; } //by marshmellow @@ -1350,433 +1350,433 @@ int BiphaseRawDecode(uint8_t *bits, size_t *size, int *offset, int invert) { //run through 2 times and take least errCnt int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos){ - // sanity check - if (*size < 16) return -1; + // sanity check + if (*size < 16) return -1; - int errCnt = 0, bestErr = 1000; - uint16_t bitnum = 0, maxBits = 512, bestRun = 0; - size_t i, k; + int errCnt = 0, bestErr = 1000; + uint16_t bitnum = 0, maxBits = 512, bestRun = 0; + size_t i, k; - //find correct start position [alignment] - for (k = 0; k < 2; ++k){ - for (i = k; i < *size-3; i += 2) { - if (bits[i] == bits[i+1]) - errCnt++; - } - if (bestErr > errCnt){ - bestErr = errCnt; - bestRun = k; - } - errCnt = 0; - } - *alignPos = bestRun; - //decode - for (i = bestRun; i < *size-3; i += 2){ - if (bits[i] == 1 && (bits[i+1] == 0)){ - bits[bitnum++] = invert; - } else if ((bits[i] == 0) && bits[i+1] == 1){ - bits[bitnum++] = invert^1; - } else { - bits[bitnum++] = 7; - } - if (bitnum > maxBits) break; - } - *size = bitnum; - return bestErr; + //find correct start position [alignment] + for (k = 0; k < 2; ++k){ + for (i = k; i < *size-3; i += 2) { + if (bits[i] == bits[i+1]) + errCnt++; + } + if (bestErr > errCnt){ + bestErr = errCnt; + bestRun = k; + } + errCnt = 0; + } + *alignPos = bestRun; + //decode + for (i = bestRun; i < *size-3; i += 2){ + if (bits[i] == 1 && (bits[i+1] == 0)){ + bits[bitnum++] = invert; + } else if ((bits[i] == 0) && bits[i+1] == 1){ + bits[bitnum++] = invert^1; + } else { + bits[bitnum++] = 7; + } + if (bitnum > maxBits) break; + } + *size = bitnum; + return bestErr; } //by marshmellow //demodulates strong heavily clipped samples //RETURN: num of errors. if 0, is ok. int cleanAskRawDemod(uint8_t *bits, size_t *size, int clk, int invert, int high, int low, int *startIdx) { - *startIdx = 0; - size_t bitCnt = 0, smplCnt = 1, errCnt = 0, pos = 0; - uint8_t cl_4 = clk / 4; - uint8_t cl_2 = clk / 2; - bool waveHigh = true; + *startIdx = 0; + size_t bitCnt = 0, smplCnt = 1, errCnt = 0, pos = 0; + uint8_t cl_4 = clk / 4; + uint8_t cl_2 = clk / 2; + bool waveHigh = true; - getNextHigh(bits, *size, high, &pos); + getNextHigh(bits, *size, high, &pos); - // sample counts, like clock = 32.. it tries to find 32/4 = 8, 32/2 = 16 - for (size_t i = pos; i < *size; i++){ - if (bits[i] >= high && waveHigh){ - smplCnt++; - } else if (bits[i] <= low && !waveHigh){ - smplCnt++; - } else { //transition - if ((bits[i] >= high && !waveHigh) || (bits[i] <= low && waveHigh)){ + // sample counts, like clock = 32.. it tries to find 32/4 = 8, 32/2 = 16 + for (size_t i = pos; i < *size; i++){ + if (bits[i] >= high && waveHigh){ + smplCnt++; + } else if (bits[i] <= low && !waveHigh){ + smplCnt++; + } else { //transition + if ((bits[i] >= high && !waveHigh) || (bits[i] <= low && waveHigh)){ - // 32-8-1 = 23 - // 32+8+1 = 41 - if (smplCnt > clk - cl_4 - 1) { //full clock + // 32-8-1 = 23 + // 32+8+1 = 41 + if (smplCnt > clk - cl_4 - 1) { //full clock - if (smplCnt > clk + cl_4 + 1) { //too many samples - errCnt++; - if (g_debugMode == 2) prnt("DEBUG ASK: cleanAskRawDemod ASK Modulation Error FULL at: %u [%u]", i, smplCnt); - bits[bitCnt++] = 7; - } else if (waveHigh) { - bits[bitCnt++] = invert; - bits[bitCnt++] = invert; - } else if (!waveHigh) { - bits[bitCnt++] = invert ^ 1; - bits[bitCnt++] = invert ^ 1; - } - if (*startIdx == 0) - *startIdx = i - clk; - waveHigh = !waveHigh; - smplCnt = 0; + if (smplCnt > clk + cl_4 + 1) { //too many samples + errCnt++; + if (g_debugMode == 2) prnt("DEBUG ASK: cleanAskRawDemod ASK Modulation Error FULL at: %u [%u]", i, smplCnt); + bits[bitCnt++] = 7; + } else if (waveHigh) { + bits[bitCnt++] = invert; + bits[bitCnt++] = invert; + } else if (!waveHigh) { + bits[bitCnt++] = invert ^ 1; + bits[bitCnt++] = invert ^ 1; + } + if (*startIdx == 0) + *startIdx = i - clk; + waveHigh = !waveHigh; + smplCnt = 0; - // 16-8-1 = 7 - } else if (smplCnt > cl_2 - cl_4 - 1) { //half clock + // 16-8-1 = 7 + } else if (smplCnt > cl_2 - cl_4 - 1) { //half clock - if (smplCnt > cl_2 + cl_4 + 1) { //too many samples - errCnt++; - if (g_debugMode == 2) prnt("DEBUG ASK: cleanAskRawDemod ASK Modulation Error HALF at: %u [%u]", i, smplCnt); - bits[bitCnt++] = 7; - } + if (smplCnt > cl_2 + cl_4 + 1) { //too many samples + errCnt++; + if (g_debugMode == 2) prnt("DEBUG ASK: cleanAskRawDemod ASK Modulation Error HALF at: %u [%u]", i, smplCnt); + bits[bitCnt++] = 7; + } - if (waveHigh) { - bits[bitCnt++] = invert; - } else if (!waveHigh) { - bits[bitCnt++] = invert ^ 1; - } - if (*startIdx == 0) - *startIdx = i - cl_2; - waveHigh = !waveHigh; - smplCnt = 0; - } else { - smplCnt++; - //transition bit oops - } - } else { //haven't hit new high or new low yet - smplCnt++; - } - } - } - *size = bitCnt; - return errCnt; + if (waveHigh) { + bits[bitCnt++] = invert; + } else if (!waveHigh) { + bits[bitCnt++] = invert ^ 1; + } + if (*startIdx == 0) + *startIdx = i - cl_2; + waveHigh = !waveHigh; + smplCnt = 0; + } else { + smplCnt++; + //transition bit oops + } + } else { //haven't hit new high or new low yet + smplCnt++; + } + } + } + *size = bitCnt; + return errCnt; } //by marshmellow //attempts to demodulate ask modulations, askType == 0 for ask/raw, askType==1 for ask/manchester int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType, int *startIdx) { - if (*size == 0) return -1; + if (*size == 0) return -1; - int start = DetectASKClock(bits, *size, clk, maxErr); - if (*clk == 0 || start < 0) return -3; + int start = DetectASKClock(bits, *size, clk, maxErr); + if (*clk == 0 || start < 0) return -3; - if (*invert != 1) *invert = 0; + if (*invert != 1) *invert = 0; - // amplify signal data. - // ICEMAN todo, - if (amp == 1) askAmp(bits, *size); + // amplify signal data. + // ICEMAN todo, + if (amp == 1) askAmp(bits, *size); - if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, beststart %d, amp %d", *clk, start, amp); + if (g_debugMode == 2) prnt("DEBUG ASK: clk %d, beststart %d, amp %d", *clk, start, amp); - //start pos from detect ask clock is 1/2 clock offset - // NOTE: can be negative (demod assumes rest of wave was there) - *startIdx = start - (*clk/2); - uint16_t initLoopMax = 1024; - if (initLoopMax > *size) initLoopMax = *size; + //start pos from detect ask clock is 1/2 clock offset + // NOTE: can be negative (demod assumes rest of wave was there) + *startIdx = start - (*clk/2); + uint16_t initLoopMax = 1024; + if (initLoopMax > *size) initLoopMax = *size; - // just noise - no super good detection. good enough - if (signalprop.isnoise) { - if (g_debugMode == 2) prnt("DEBUG askdemod_ext: just noise detected - aborting"); - return -2; - } + // just noise - no super good detection. good enough + if (signalprop.isnoise) { + if (g_debugMode == 2) prnt("DEBUG askdemod_ext: just noise detected - aborting"); + return -2; + } - // Detect high and lows - //25% clip in case highs and lows aren't clipped [marshmellow] - int high, low; - //getHiLo(bits, initLoopMax, &high, &low, 75, 75); - getHiLo(&high, &low, 75, 75); + // Detect high and lows + //25% clip in case highs and lows aren't clipped [marshmellow] + int high, low; + //getHiLo(bits, initLoopMax, &high, &low, 75, 75); + getHiLo(&high, &low, 75, 75); - size_t errCnt = 0; - // if clean clipped waves detected run alternate demod - if (DetectCleanAskWave(bits, *size, high, low)) { + size_t errCnt = 0; + // if clean clipped waves detected run alternate demod + if (DetectCleanAskWave(bits, *size, high, low)) { - if (g_debugMode == 2) prnt("DEBUG ASK: Clean Wave Detected - using clean wave demod"); + if (g_debugMode == 2) prnt("DEBUG ASK: Clean Wave Detected - using clean wave demod"); - errCnt = cleanAskRawDemod(bits, size, *clk, *invert, high, low, startIdx); + errCnt = cleanAskRawDemod(bits, size, *clk, *invert, high, low, startIdx); - if (askType) { //ask/manchester - uint8_t alignPos = 0; - errCnt = manrawdecode(bits, size, 0, &alignPos); - *startIdx += *clk/2 * alignPos; + if (askType) { //ask/manchester + uint8_t alignPos = 0; + errCnt = manrawdecode(bits, size, 0, &alignPos); + *startIdx += *clk/2 * alignPos; - if (g_debugMode) - prnt("DEBUG: (askdemod_ext) CLEAN: startIdx %i, alignPos %u", *startIdx, alignPos); - } - return errCnt; - } + if (g_debugMode) + prnt("DEBUG: (askdemod_ext) CLEAN: startIdx %i, alignPos %u", *startIdx, alignPos); + } + return errCnt; + } - if (g_debugMode) prnt("DEBUG: (askdemod_ext) Weak wave detected: startIdx %i", *startIdx); + if (g_debugMode) prnt("DEBUG: (askdemod_ext) Weak wave detected: startIdx %i", *startIdx); - int lastBit; //set first clock check - can go negative - size_t i, bitnum = 0; //output counter - uint8_t midBit = 0; - uint8_t tol = 0; //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave - if (*clk <= 32) tol = 1; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely - size_t MaxBits = 3072; //max bits to collect - lastBit = start - *clk; + int lastBit; //set first clock check - can go negative + size_t i, bitnum = 0; //output counter + uint8_t midBit = 0; + uint8_t tol = 0; //clock tolerance adjust - waves will be accepted as within the clock if they fall + or - this value + clock from last valid wave + if (*clk <= 32) tol = 1; //clock tolerance may not be needed anymore currently set to + or - 1 but could be increased for poor waves or removed entirely + size_t MaxBits = 3072; //max bits to collect + lastBit = start - *clk; - for (i = start; i < *size; ++i) { - if (i - lastBit >= *clk - tol){ - if (bits[i] >= high) { - bits[bitnum++] = *invert; - } else if (bits[i] <= low) { - bits[bitnum++] = *invert ^ 1; - } else if (i-lastBit >= *clk + tol) { - if (bitnum > 0) { - if (g_debugMode == 2) prnt("DEBUG: (askdemod_ext) Modulation Error at: %u", i); - bits[bitnum++] = 7; - errCnt++; - } - } else { //in tolerance - looking for peak - continue; - } - midBit = 0; - lastBit += *clk; - } else if (i-lastBit >= (*clk/2 - tol) && !midBit && !askType){ - if (bits[i] >= high) { - bits[bitnum++] = *invert; - } else if (bits[i] <= low) { - bits[bitnum++] = *invert ^ 1; - } else if (i-lastBit >= *clk/2 + tol) { - bits[bitnum] = bits[bitnum-1]; - bitnum++; - } else { //in tolerance - looking for peak - continue; - } - midBit = 1; - } - if (bitnum >= MaxBits) break; - } - *size = bitnum; - return errCnt; + for (i = start; i < *size; ++i) { + if (i - lastBit >= *clk - tol){ + if (bits[i] >= high) { + bits[bitnum++] = *invert; + } else if (bits[i] <= low) { + bits[bitnum++] = *invert ^ 1; + } else if (i-lastBit >= *clk + tol) { + if (bitnum > 0) { + if (g_debugMode == 2) prnt("DEBUG: (askdemod_ext) Modulation Error at: %u", i); + bits[bitnum++] = 7; + errCnt++; + } + } else { //in tolerance - looking for peak + continue; + } + midBit = 0; + lastBit += *clk; + } else if (i-lastBit >= (*clk/2 - tol) && !midBit && !askType){ + if (bits[i] >= high) { + bits[bitnum++] = *invert; + } else if (bits[i] <= low) { + bits[bitnum++] = *invert ^ 1; + } else if (i-lastBit >= *clk/2 + tol) { + bits[bitnum] = bits[bitnum-1]; + bitnum++; + } else { //in tolerance - looking for peak + continue; + } + midBit = 1; + } + if (bitnum >= MaxBits) break; + } + *size = bitnum; + return errCnt; } int askdemod(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType) { - int start = 0; - return askdemod_ext(bits, size, clk, invert, maxErr, amp, askType, &start); + int start = 0; + return askdemod_ext(bits, size, clk, invert, maxErr, amp, askType, &start); } // by marshmellow - demodulate NRZ wave - requires a read with strong signal // peaks invert bit (high=1 low=0) each clock cycle = 1 bit determined by last peak int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startIdx) { - if (signalprop.isnoise) return -1; + if (signalprop.isnoise) return -1; - size_t clkStartIdx = 0; - *clk = DetectNRZClock(dest, *size, *clk, &clkStartIdx); - if (*clk == 0) return -2; + size_t clkStartIdx = 0; + *clk = DetectNRZClock(dest, *size, *clk, &clkStartIdx); + if (*clk == 0) return -2; - size_t i, gLen = 4096; - if (gLen > *size) - gLen = *size-20; + size_t i, gLen = 4096; + if (gLen > *size) + gLen = *size-20; - // just noise - no super good detection. good enough - if (signalprop.isnoise) { - if (g_debugMode == 2) prnt("DEBUG nrzRawDemod: just noise detected - quitting"); - return -3; - } + // just noise - no super good detection. good enough + if (signalprop.isnoise) { + if (g_debugMode == 2) prnt("DEBUG nrzRawDemod: just noise detected - quitting"); + return -3; + } - int high, low; - //getHiLo(dest, gLen, &high, &low, 75, 75); - getHiLo(&high, &low, 75, 75); - getHiLo(&high, &low, 75, 75); + int high, low; + //getHiLo(dest, gLen, &high, &low, 75, 75); + getHiLo(&high, &low, 75, 75); + getHiLo(&high, &low, 75, 75); - uint8_t bit=0; - //convert wave samples to 1's and 0's - for(i=20; i < *size-20; i++){ - if (dest[i] >= high) bit = 1; - if (dest[i] <= low) bit = 0; - dest[i] = bit; - } - //now demod based on clock (rf/32 = 32 1's for one 1 bit, 32 0's for one 0 bit) - size_t lastBit = 0; - size_t numBits = 0; - for(i=21; i < *size-20; i++) { - //if transition detected or large number of same bits - store the passed bits - if (dest[i] != dest[i-1] || (i-lastBit) == (10 * *clk)) { - memset(dest+numBits, dest[i-1] ^ *invert, (i - lastBit + (*clk/4)) / *clk); - numBits += (i - lastBit + (*clk/4)) / *clk; - if (lastBit == 0) { - *startIdx = i - (numBits * *clk); - if (g_debugMode == 2) prnt("DEBUG NRZ: startIdx %i", *startIdx); - } - lastBit = i-1; - } - } - *size = numBits; - return 0; + uint8_t bit=0; + //convert wave samples to 1's and 0's + for(i=20; i < *size-20; i++){ + if (dest[i] >= high) bit = 1; + if (dest[i] <= low) bit = 0; + dest[i] = bit; + } + //now demod based on clock (rf/32 = 32 1's for one 1 bit, 32 0's for one 0 bit) + size_t lastBit = 0; + size_t numBits = 0; + for(i=21; i < *size-20; i++) { + //if transition detected or large number of same bits - store the passed bits + if (dest[i] != dest[i-1] || (i-lastBit) == (10 * *clk)) { + memset(dest+numBits, dest[i-1] ^ *invert, (i - lastBit + (*clk/4)) / *clk); + numBits += (i - lastBit + (*clk/4)) / *clk; + if (lastBit == 0) { + *startIdx = i - (numBits * *clk); + if (g_debugMode == 2) prnt("DEBUG NRZ: startIdx %i", *startIdx); + } + lastBit = i-1; + } + } + *size = numBits; + return 0; } //translate wave to 11111100000 (1 for each short wave [higher freq] 0 for each long wave [lower freq]) size_t fsk_wave_demod(uint8_t *dest, size_t size, uint8_t fchigh, uint8_t fclow, int *startIdx) { - if ( size < 1024 ) return 0; // not enough samples + if ( size < 1024 ) return 0; // not enough samples - if (fchigh == 0) fchigh = 10; - if (fclow == 0) fclow = 8; + if (fchigh == 0) fchigh = 10; + if (fclow == 0) fclow = 8; - //set the threshold close to 0 (graph) or 128 std to avoid static - size_t preLastSample = 0; - size_t LastSample = 0; - size_t currSample = 0; - size_t last_transition = 0; - size_t idx = 1; - size_t numBits = 0; + //set the threshold close to 0 (graph) or 128 std to avoid static + size_t preLastSample = 0; + size_t LastSample = 0; + size_t currSample = 0; + size_t last_transition = 0; + size_t idx = 1; + size_t numBits = 0; - //find start of modulating data in trace - idx = findModStart(dest, size, fchigh); - // Need to threshold first sample - dest[idx] = (dest[idx] < signalprop.mean) ? 0 : 1; + //find start of modulating data in trace + idx = findModStart(dest, size, fchigh); + // Need to threshold first sample + dest[idx] = (dest[idx] < signalprop.mean) ? 0 : 1; - last_transition = idx; - idx++; + last_transition = idx; + idx++; - // Definition: cycles between consecutive lo-hi transitions - // Lets define some expected lengths. FSK1 is easier since it has bigger differences between. - // FSK1 8/5 - // 50/8 = 6 | 40/8 = 5 | 64/8 = 8 - // 50/5 = 10 | 40/5 = 8 | 64/5 = 12 + // Definition: cycles between consecutive lo-hi transitions + // Lets define some expected lengths. FSK1 is easier since it has bigger differences between. + // FSK1 8/5 + // 50/8 = 6 | 40/8 = 5 | 64/8 = 8 + // 50/5 = 10 | 40/5 = 8 | 64/5 = 12 - // FSK2 10/8 - // 50/10 = 5 | 40/10 = 4 | 64/10 = 6 - // 50/8 = 6 | 40/8 = 5 | 64/8 = 8 + // FSK2 10/8 + // 50/10 = 5 | 40/10 = 4 | 64/10 = 6 + // 50/8 = 6 | 40/8 = 5 | 64/8 = 8 - // count cycles between consecutive lo-hi transitions, - // in practice due to noise etc we may end up with anywhere - // To allow fuzz would mean +-1 on expected cycle width. - // FSK1 8/5 - // 50/8 = 6 (5-7) | 40/8 = 5 (4-6) | 64/8 = 8 (7-9) - // 50/5 = 10 (9-11) | 40/5 = 8 (7-9) | 64/5 = 12 (11-13) + // count cycles between consecutive lo-hi transitions, + // in practice due to noise etc we may end up with anywhere + // To allow fuzz would mean +-1 on expected cycle width. + // FSK1 8/5 + // 50/8 = 6 (5-7) | 40/8 = 5 (4-6) | 64/8 = 8 (7-9) + // 50/5 = 10 (9-11) | 40/5 = 8 (7-9) | 64/5 = 12 (11-13) - // FSK2 10/8 - // 50/10 = 5 (4-6) | 40/10 = 4 (3-5) | 64/10 = 6 (5-7) - // 50/8 = 6 (5-7) | 40/8 = 5 (4-6) | 64/8 = 8 (7-9) - // - // It easy to see to the overgaping, but luckily we the group value also, like 1111000001111 - // to separate between which bit to demodulate to. + // FSK2 10/8 + // 50/10 = 5 (4-6) | 40/10 = 4 (3-5) | 64/10 = 6 (5-7) + // 50/8 = 6 (5-7) | 40/8 = 5 (4-6) | 64/8 = 8 (7-9) + // + // It easy to see to the overgaping, but luckily we the group value also, like 1111000001111 + // to separate between which bit to demodulate to. - // process: - // count width from 0-1 transition to 1-0. - // determine the width is withing FUZZ_min and FUZZ_max tolerances - // width should be divided with exp_one. i:e 6+7+6+2=21, 21/5 = 4, - // the 1-0 to 0-1 width should be divided with exp_zero. Ie: 3+5+6+7 = 21/6 = 3 + // process: + // count width from 0-1 transition to 1-0. + // determine the width is withing FUZZ_min and FUZZ_max tolerances + // width should be divided with exp_one. i:e 6+7+6+2=21, 21/5 = 4, + // the 1-0 to 0-1 width should be divided with exp_zero. Ie: 3+5+6+7 = 21/6 = 3 - for(; idx < size-20; idx++) { + for(; idx < size-20; idx++) { - // threshold current value - dest[idx] = (dest[idx] < signalprop.mean) ? 0 : 1; + // threshold current value + dest[idx] = (dest[idx] < signalprop.mean) ? 0 : 1; - // Check for 0->1 transition - if (dest[idx-1] < dest[idx]) { - preLastSample = LastSample; - LastSample = currSample; - currSample = idx-last_transition; - if (currSample < (fclow-2)){ //0-5 = garbage noise (or 0-3) - //do nothing with extra garbage - } else if (currSample < (fchigh-1)) { //6-8 = 8 sample waves (or 3-6 = 5) - //correct previous 9 wave surrounded by 8 waves (or 6 surrounded by 5) - if (numBits > 1 && LastSample > (fchigh-2) && (preLastSample < (fchigh-1))){ - dest[numBits-1]=1; - } - dest[numBits++]=1; + // Check for 0->1 transition + if (dest[idx-1] < dest[idx]) { + preLastSample = LastSample; + LastSample = currSample; + currSample = idx-last_transition; + if (currSample < (fclow-2)){ //0-5 = garbage noise (or 0-3) + //do nothing with extra garbage + } else if (currSample < (fchigh-1)) { //6-8 = 8 sample waves (or 3-6 = 5) + //correct previous 9 wave surrounded by 8 waves (or 6 surrounded by 5) + if (numBits > 1 && LastSample > (fchigh-2) && (preLastSample < (fchigh-1))){ + dest[numBits-1]=1; + } + dest[numBits++]=1; - if (numBits > 0 && *startIdx == 0) - *startIdx = idx - fclow; + if (numBits > 0 && *startIdx == 0) + *startIdx = idx - fclow; - } else if (currSample > (fchigh+1) && numBits < 3) { //12 + and first two bit = unusable garbage - //do nothing with beginning garbage and reset.. should be rare.. - numBits = 0; - } else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's (or 4 then a 6 should be two 5's) - dest[numBits++]=1; - if (numBits > 0 && *startIdx == 0) { - *startIdx = idx - fclow; - } - } else { //9+ = 10 sample waves (or 6+ = 7) - dest[numBits++]=0; - if (numBits > 0 && *startIdx == 0) { - *startIdx = idx - fchigh; - } - } - last_transition = idx; - } - } - return numBits; //Actually, it returns the number of bytes, but each byte represents a bit: 1 or 0 + } else if (currSample > (fchigh+1) && numBits < 3) { //12 + and first two bit = unusable garbage + //do nothing with beginning garbage and reset.. should be rare.. + numBits = 0; + } else if (currSample == (fclow+1) && LastSample == (fclow-1)) { // had a 7 then a 9 should be two 8's (or 4 then a 6 should be two 5's) + dest[numBits++]=1; + if (numBits > 0 && *startIdx == 0) { + *startIdx = idx - fclow; + } + } else { //9+ = 10 sample waves (or 6+ = 7) + dest[numBits++]=0; + if (numBits > 0 && *startIdx == 0) { + *startIdx = idx - fchigh; + } + } + last_transition = idx; + } + } + return numBits; //Actually, it returns the number of bytes, but each byte represents a bit: 1 or 0 } //translate 11111100000 to 10 //rfLen = clock, fchigh = larger field clock, fclow = smaller field clock size_t aggregate_bits(uint8_t *dest, size_t size, uint8_t clk, uint8_t invert, uint8_t fchigh, uint8_t fclow, int *startIdx) { - uint8_t lastval = dest[0]; - size_t i = 0; - size_t numBits = 0; - uint32_t n = 1; - uint8_t hclk = clk/2; + uint8_t lastval = dest[0]; + size_t i = 0; + size_t numBits = 0; + uint32_t n = 1; + uint8_t hclk = clk/2; - for( i = 1; i < size; i++) { - n++; - if (dest[i] == lastval) continue; //skip until we hit a transition + for( i = 1; i < size; i++) { + n++; + if (dest[i] == lastval) continue; //skip until we hit a transition - //find out how many bits (n) we collected (use 1/2 clk tolerance) + //find out how many bits (n) we collected (use 1/2 clk tolerance) - if (dest[i-1] == 1) - //if lastval was 1, we have a 1->0 crossing - n = (n * fclow + hclk) / clk; - else - // 0->1 crossing - n = (n * fchigh + hclk) / clk; + if (dest[i-1] == 1) + //if lastval was 1, we have a 1->0 crossing + n = (n * fclow + hclk) / clk; + else + // 0->1 crossing + n = (n * fchigh + hclk) / clk; - if (n == 0) - n = 1; + if (n == 0) + n = 1; - //first transition - save startidx - if (numBits == 0) { - if (lastval == 1) { //high to low - *startIdx += (fclow * i) - (n*clk); - if (g_debugMode == 2) prnt("DEBUG (aggregate_bits) FSK startIdx %i, fclow*idx %i, n*clk %u", *startIdx, fclow*i, n*clk); - } else { - *startIdx += (fchigh * i) - (n*clk); - if (g_debugMode == 2) prnt("DEBUG (aggregate_bits) FSK startIdx %i, fchigh*idx %i, n*clk %u", *startIdx, fchigh*i, n*clk); - } - } + //first transition - save startidx + if (numBits == 0) { + if (lastval == 1) { //high to low + *startIdx += (fclow * i) - (n*clk); + if (g_debugMode == 2) prnt("DEBUG (aggregate_bits) FSK startIdx %i, fclow*idx %i, n*clk %u", *startIdx, fclow*i, n*clk); + } else { + *startIdx += (fchigh * i) - (n*clk); + if (g_debugMode == 2) prnt("DEBUG (aggregate_bits) FSK startIdx %i, fchigh*idx %i, n*clk %u", *startIdx, fchigh*i, n*clk); + } + } - //add to our destination the bits we collected - memset(dest+numBits, dest[i-1] ^ invert , n); + //add to our destination the bits we collected + memset(dest+numBits, dest[i-1] ^ invert , n); - numBits += n; - n = 0; - lastval = dest[i]; + numBits += n; + n = 0; + lastval = dest[i]; - }//end for + }//end for - // if valid extra bits at the end were all the same frequency - add them in - if (n > clk/fchigh) { - if (dest[i-2] == 1) { - n = (n * fclow + clk/2) / clk; - } else { - n = (n * fchigh + clk/2) / clk; - } - memset(dest+numBits, dest[i-1] ^ invert , n); - numBits += n; - } - return numBits; + // if valid extra bits at the end were all the same frequency - add them in + if (n > clk/fchigh) { + if (dest[i-2] == 1) { + n = (n * fclow + clk/2) / clk; + } else { + n = (n * fchigh + clk/2) / clk; + } + memset(dest+numBits, dest[i-1] ^ invert , n); + numBits += n; + } + return numBits; } //by marshmellow (from holiman's base) // full fsk demod from GraphBuffer wave to decoded 1s and 0s (no mandemod) size_t fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8_t fchigh, uint8_t fclow, int *start_idx) { - if (signalprop.isnoise) return 0; - // FSK demodulator - size = fsk_wave_demod(dest, size, fchigh, fclow, start_idx); - size = aggregate_bits(dest, size, rfLen, invert, fchigh, fclow, start_idx); - return size; + if (signalprop.isnoise) return 0; + // FSK demodulator + size = fsk_wave_demod(dest, size, fchigh, fclow, start_idx); + size = aggregate_bits(dest, size, rfLen, invert, fchigh, fclow, start_idx); + return size; } // by marshmellow @@ -1784,31 +1784,31 @@ size_t fskdemod(uint8_t *dest, size_t size, uint8_t rfLen, uint8_t invert, uint8 // only transition waves are 1s //TODO: Iceman - hard coded value 7, should be #define void psk1TOpsk2(uint8_t *bits, size_t size) { - uint8_t lastbit = bits[0]; - for (size_t i = 1; i < size; i++){ - //ignore errors - if (bits[i] == 7) continue; + uint8_t lastbit = bits[0]; + for (size_t i = 1; i < size; i++){ + //ignore errors + if (bits[i] == 7) continue; - if (lastbit != bits[i]){ - lastbit = bits[i]; - bits[i] = 1; - } else { - bits[i] = 0; - } - } + if (lastbit != bits[i]){ + lastbit = bits[i]; + bits[i] = 1; + } else { + bits[i] = 0; + } + } } // by marshmellow // convert psk2 demod to psk1 demod // from only transition waves are 1s to phase shifts change bit void psk2TOpsk1(uint8_t *bits, size_t size) { - uint8_t phase = 0; - for (size_t i = 0; i < size; i++){ - if (bits[i] == 1){ - phase ^= 1; - } - bits[i] = phase; - } + uint8_t phase = 0; + for (size_t i = 0; i < size; i++){ + if (bits[i] == 1){ + phase ^= 1; + } + bits[i] = phase; + } } //by marshmellow - demodulate PSK1 wave @@ -1816,89 +1816,89 @@ void psk2TOpsk1(uint8_t *bits, size_t size) { //TODO: Iceman - hard coded value 7, should be #define int pskRawDemod_ext(uint8_t *dest, size_t *size, int *clock, int *invert, int *startIdx) { - // sanity check - if (*size < 170) return -1; + // sanity check + if (*size < 170) return -1; - uint8_t curPhase = *invert; - uint8_t fc=0; - size_t i=0, numBits=0, waveStart=1, waveEnd=0, firstFullWave=0, lastClkBit=0; - uint16_t fullWaveLen=0, waveLenCnt=0, avgWaveVal=0; - uint16_t errCnt=0, errCnt2=0; + uint8_t curPhase = *invert; + uint8_t fc=0; + size_t i=0, numBits=0, waveStart=1, waveEnd=0, firstFullWave=0, lastClkBit=0; + uint16_t fullWaveLen=0, waveLenCnt=0, avgWaveVal=0; + uint16_t errCnt=0, errCnt2=0; - *clock = DetectPSKClock(dest, *size, *clock, &firstFullWave, &curPhase, &fc); - if (*clock <= 0) return -1; - //if clock detect found firstfullwave... - uint16_t tol = fc/2; - if (firstFullWave == 0) { - //find start of modulating data in trace - i = findModStart(dest, *size, fc); - //find first phase shift - firstFullWave = pskFindFirstPhaseShift(dest, *size, &curPhase, i, fc, &fullWaveLen); - if (firstFullWave == 0) { - // no phase shift detected - could be all 1's or 0's - doesn't matter where we start - // so skip a little to ensure we are past any Start Signal - firstFullWave = 160; - memset(dest, curPhase, firstFullWave / *clock); - } else { - memset(dest, curPhase^1, firstFullWave / *clock); - } - } else { - memset(dest, curPhase^1, firstFullWave / *clock); - } - //advance bits - numBits += (firstFullWave / *clock); - *startIdx = firstFullWave - (*clock * numBits)+2; - //set start of wave as clock align - lastClkBit = firstFullWave; - if (g_debugMode == 2) prnt("DEBUG PSK: firstFullWave: %u, waveLen: %u, startIdx %i",firstFullWave,fullWaveLen, *startIdx); - if (g_debugMode == 2) prnt("DEBUG PSK: clk: %d, lastClkBit: %u, fc: %u", *clock, lastClkBit, fc); - waveStart = 0; - dest[numBits++] = curPhase; //set first read bit - for (i = firstFullWave + fullWaveLen - 1; i < *size-3; i++){ - //top edge of wave = start of new wave - if (dest[i]+fc < dest[i+1] && dest[i+1] >= dest[i+2]){ - if (waveStart == 0) { - waveStart = i+1; - waveLenCnt = 0; - avgWaveVal = dest[i+1]; - } else { //waveEnd - waveEnd = i+1; - waveLenCnt = waveEnd-waveStart; - if (waveLenCnt > fc){ - //this wave is a phase shift - //prnt("DEBUG: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d",waveStart,waveLenCnt,lastClkBit+*clock-tol,i+1,fc); - if (i+1 >= lastClkBit + *clock - tol){ //should be a clock bit - curPhase ^= 1; - dest[numBits++] = curPhase; - lastClkBit += *clock; - } else if (i < lastClkBit+10+fc){ - //noise after a phase shift - ignore - } else { //phase shift before supposed to based on clock - errCnt++; - dest[numBits++] = 7; - } - } else if (i+1 > lastClkBit + *clock + tol + fc){ - lastClkBit += *clock; //no phase shift but clock bit - dest[numBits++] = curPhase; - } else if (waveLenCnt < fc - 1) { //wave is smaller than field clock (shouldn't happen often) - errCnt2++; - if (errCnt2 > 101) return errCnt2; - avgWaveVal += dest[i+1]; - continue; - } - avgWaveVal = 0; - waveStart = i+1; - } - } - avgWaveVal += dest[i+1]; - } - *size = numBits; - return errCnt; + *clock = DetectPSKClock(dest, *size, *clock, &firstFullWave, &curPhase, &fc); + if (*clock <= 0) return -1; + //if clock detect found firstfullwave... + uint16_t tol = fc/2; + if (firstFullWave == 0) { + //find start of modulating data in trace + i = findModStart(dest, *size, fc); + //find first phase shift + firstFullWave = pskFindFirstPhaseShift(dest, *size, &curPhase, i, fc, &fullWaveLen); + if (firstFullWave == 0) { + // no phase shift detected - could be all 1's or 0's - doesn't matter where we start + // so skip a little to ensure we are past any Start Signal + firstFullWave = 160; + memset(dest, curPhase, firstFullWave / *clock); + } else { + memset(dest, curPhase^1, firstFullWave / *clock); + } + } else { + memset(dest, curPhase^1, firstFullWave / *clock); + } + //advance bits + numBits += (firstFullWave / *clock); + *startIdx = firstFullWave - (*clock * numBits)+2; + //set start of wave as clock align + lastClkBit = firstFullWave; + if (g_debugMode == 2) prnt("DEBUG PSK: firstFullWave: %u, waveLen: %u, startIdx %i",firstFullWave,fullWaveLen, *startIdx); + if (g_debugMode == 2) prnt("DEBUG PSK: clk: %d, lastClkBit: %u, fc: %u", *clock, lastClkBit, fc); + waveStart = 0; + dest[numBits++] = curPhase; //set first read bit + for (i = firstFullWave + fullWaveLen - 1; i < *size-3; i++){ + //top edge of wave = start of new wave + if (dest[i]+fc < dest[i+1] && dest[i+1] >= dest[i+2]){ + if (waveStart == 0) { + waveStart = i+1; + waveLenCnt = 0; + avgWaveVal = dest[i+1]; + } else { //waveEnd + waveEnd = i+1; + waveLenCnt = waveEnd-waveStart; + if (waveLenCnt > fc){ + //this wave is a phase shift + //prnt("DEBUG: phase shift at: %d, len: %d, nextClk: %d, i: %d, fc: %d",waveStart,waveLenCnt,lastClkBit+*clock-tol,i+1,fc); + if (i+1 >= lastClkBit + *clock - tol){ //should be a clock bit + curPhase ^= 1; + dest[numBits++] = curPhase; + lastClkBit += *clock; + } else if (i < lastClkBit+10+fc){ + //noise after a phase shift - ignore + } else { //phase shift before supposed to based on clock + errCnt++; + dest[numBits++] = 7; + } + } else if (i+1 > lastClkBit + *clock + tol + fc){ + lastClkBit += *clock; //no phase shift but clock bit + dest[numBits++] = curPhase; + } else if (waveLenCnt < fc - 1) { //wave is smaller than field clock (shouldn't happen often) + errCnt2++; + if (errCnt2 > 101) return errCnt2; + avgWaveVal += dest[i+1]; + continue; + } + avgWaveVal = 0; + waveStart = i+1; + } + } + avgWaveVal += dest[i+1]; + } + *size = numBits; + return errCnt; } int pskRawDemod(uint8_t *dest, size_t *size, int *clock, int *invert) { - int start_idx = 0; - return pskRawDemod_ext(dest, size, clock, invert, &start_idx); + int start_idx = 0; + return pskRawDemod_ext(dest, size, clock, invert, &start_idx); } @@ -1910,167 +1910,167 @@ int pskRawDemod(uint8_t *dest, size_t *size, int *clock, int *invert) { // by marshmellow // FSK Demod then try to locate an AWID ID int detectAWID(uint8_t *dest, size_t *size, int *waveStartIdx) { - //make sure buffer has enough data (96bits * 50clock samples) - if (*size < 96*50) return -1; + //make sure buffer has enough data (96bits * 50clock samples) + if (*size < 96*50) return -1; - if (signalprop.isnoise) return -2; + if (signalprop.isnoise) return -2; - // FSK2a demodulator clock 50, invert 1, fcHigh 10, fcLow 8 - *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); //awid fsk2a + // FSK2a demodulator clock 50, invert 1, fcHigh 10, fcLow 8 + *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); //awid fsk2a - //did we get a good demod? - if (*size < 96) return -3; + //did we get a good demod? + if (*size < 96) return -3; - size_t start_idx = 0; - uint8_t preamble[] = {0,0,0,0,0,0,0,1}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &start_idx)) - return -4; //preamble not found + size_t start_idx = 0; + uint8_t preamble[] = {0,0,0,0,0,0,0,1}; + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &start_idx)) + return -4; //preamble not found - // wrong size? (between to preambles) - if (*size != 96) return -5; + // wrong size? (between to preambles) + if (*size != 96) return -5; - return (int)start_idx; + return (int)start_idx; } //by marshmellow //takes 1s and 0s and searches for EM410x format - output EM ID int Em410xDecode(uint8_t *bits, size_t *size, size_t *start_idx, uint32_t *hi, uint64_t *lo) { - // sanity check - if (bits[1] > 1) return -1; - if (*size < 64) return -2; + // sanity check + if (bits[1] > 1) return -1; + if (*size < 64) return -2; - uint8_t fmtlen; - *start_idx = 0; + uint8_t fmtlen; + *start_idx = 0; - // preamble 0111111111 - // include 0 in front to help get start pos - uint8_t preamble[] = {0,1,1,1,1,1,1,1,1,1}; - if (!preambleSearch(bits, preamble, sizeof(preamble), size, start_idx)) - return -4; + // preamble 0111111111 + // include 0 in front to help get start pos + uint8_t preamble[] = {0,1,1,1,1,1,1,1,1,1}; + if (!preambleSearch(bits, preamble, sizeof(preamble), size, start_idx)) + return -4; - // (iceman) if the preamble doesn't find two occuriences, this identification fails. - fmtlen = (*size == 128) ? 22 : 10; + // (iceman) if the preamble doesn't find two occuriences, this identification fails. + fmtlen = (*size == 128) ? 22 : 10; - //skip last 4bit parity row for simplicity - *size = removeParity(bits, *start_idx + sizeof(preamble), 5, 0, fmtlen * 5); + //skip last 4bit parity row for simplicity + *size = removeParity(bits, *start_idx + sizeof(preamble), 5, 0, fmtlen * 5); - switch (*size) { - case 40: { - // std em410x format - *hi = 0; - *lo = ((uint64_t)(bytebits_to_byte(bits, 8)) << 32) | (bytebits_to_byte(bits + 8, 32)); - break; - } - case 88: { - // long em format - *hi = (bytebits_to_byte(bits, 24)); - *lo = ((uint64_t)(bytebits_to_byte(bits + 24, 32)) << 32) | (bytebits_to_byte(bits + 24 + 32, 32)); - break; - } - default: return -6; - } - return 1; + switch (*size) { + case 40: { + // std em410x format + *hi = 0; + *lo = ((uint64_t)(bytebits_to_byte(bits, 8)) << 32) | (bytebits_to_byte(bits + 8, 32)); + break; + } + case 88: { + // long em format + *hi = (bytebits_to_byte(bits, 24)); + *lo = ((uint64_t)(bytebits_to_byte(bits + 24, 32)) << 32) | (bytebits_to_byte(bits + 24 + 32, 32)); + break; + } + default: return -6; + } + return 1; } // loop to get raw HID waveform then FSK demodulate the TAG ID from it int HIDdemodFSK(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint32_t *lo, int *waveStartIdx) { - //make sure buffer has data - if (*size < 96*50) return -1; + //make sure buffer has data + if (*size < 96*50) return -1; - if (signalprop.isnoise) return -2; + if (signalprop.isnoise) return -2; - // FSK demodulator fsk2a so invert and fc/10/8 - *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); //hid fsk2a + // FSK demodulator fsk2a so invert and fc/10/8 + *size = fskdemod(dest, *size, 50, 1, 10, 8, waveStartIdx); //hid fsk2a - //did we get a good demod? - if (*size < 96*2) return -3; + //did we get a good demod? + if (*size < 96*2) return -3; - // 00011101 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1 - size_t start_idx = 0; - uint8_t preamble[] = {0,0,0,1,1,1,0,1}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &start_idx)) - return -4; //preamble not found + // 00011101 bit pattern represent start of frame, 01 pattern represents a 0 and 10 represents a 1 + size_t start_idx = 0; + uint8_t preamble[] = {0,0,0,1,1,1,0,1}; + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &start_idx)) + return -4; //preamble not found - // wrong size? (between to preambles) - //if (*size != 96) return -5; + // wrong size? (between to preambles) + //if (*size != 96) return -5; - size_t num_start = start_idx + sizeof(preamble); - // final loop, go over previously decoded FSK data and manchester decode into usable tag ID - for (size_t idx = num_start; (idx - num_start) < *size - sizeof(preamble); idx += 2) { - if (dest[idx] == dest[idx+1]){ - return -5; //not manchester data - } - *hi2 = (*hi2 << 1) | (*hi >> 31); - *hi = (*hi << 1) | (*lo >> 31); - //Then, shift in a 0 or one into low - *lo <<= 1; - if (dest[idx] && !dest[idx+1]) // 1 0 - *lo |= 1; - else // 0 1 - *lo |= 0; - } - return (int)start_idx; + size_t num_start = start_idx + sizeof(preamble); + // final loop, go over previously decoded FSK data and manchester decode into usable tag ID + for (size_t idx = num_start; (idx - num_start) < *size - sizeof(preamble); idx += 2) { + if (dest[idx] == dest[idx+1]){ + return -5; //not manchester data + } + *hi2 = (*hi2 << 1) | (*hi >> 31); + *hi = (*hi << 1) | (*lo >> 31); + //Then, shift in a 0 or one into low + *lo <<= 1; + if (dest[idx] && !dest[idx+1]) // 1 0 + *lo |= 1; + else // 0 1 + *lo |= 0; + } + return (int)start_idx; } // Find IDTEC PSK1, RF Preamble == 0x4944544B, Demodsize 64bits // by iceman int detectIdteck(uint8_t *dest, size_t *size) { - //make sure buffer has data - if (*size < 64*2) return -1; + //make sure buffer has data + if (*size < 64*2) return -1; - if (signalprop.isnoise) return -2; + if (signalprop.isnoise) return -2; - size_t start_idx = 0; - uint8_t preamble[] = {0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,1,0,1,1}; + size_t start_idx = 0; + uint8_t preamble[] = {0,1,0,0,1,0,0,1,0,1,0,0,0,1,0,0,0,1,0,1,0,1,0,0,0,1,0,0,1,0,1,1}; - //preamble not found - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &start_idx)) - return -3; + //preamble not found + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &start_idx)) + return -3; - // wrong demoded size - if (*size != 64) return -4; - return (int)start_idx; + // wrong demoded size + if (*size != 64) return -4; + return (int)start_idx; } int detectIOProx(uint8_t *dest, size_t *size, int *waveStartIdx) { - //make sure buffer has data - if (*size < 66*64) return -1; + //make sure buffer has data + if (*size < 66*64) return -1; - if (signalprop.isnoise) return -2; + if (signalprop.isnoise) return -2; - // FSK demodulator RF/64, fsk2a so invert, and fc/10/8 - *size = fskdemod(dest, *size, 64, 1, 10, 8, waveStartIdx); //io fsk2a + // FSK demodulator RF/64, fsk2a so invert, and fc/10/8 + *size = fskdemod(dest, *size, 64, 1, 10, 8, waveStartIdx); //io fsk2a - //did we get enough demod data? - if (*size < 64) return -3; + //did we get enough demod data? + if (*size < 64) return -3; - //Index map - //0 10 20 30 40 50 60 - //| | | | | | | - //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23 - //----------------------------------------------------------------------------- - //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11 - // - //XSF(version)facility:codeone+codetwo + //Index map + //0 10 20 30 40 50 60 + //| | | | | | | + //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23 + //----------------------------------------------------------------------------- + //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 ???????? 11 + // + //XSF(version)facility:codeone+codetwo - size_t start_idx = 0; - uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,1}; - if (!preambleSearch(dest, preamble, sizeof(preamble), size, &start_idx)) - return -4; //preamble not found + size_t start_idx = 0; + uint8_t preamble[] = {0,0,0,0,0,0,0,0,0,1}; + if (!preambleSearch(dest, preamble, sizeof(preamble), size, &start_idx)) + return -4; //preamble not found - // wrong size? (between to preambles) - if (*size != 64) return -5; + // wrong size? (between to preambles) + if (*size != 64) return -5; - if ( !dest[start_idx + 8] - && dest[start_idx + 17] == 1 - && dest[start_idx + 26] == 1 - && dest[start_idx + 35] == 1 - && dest[start_idx + 44] == 1 - && dest[start_idx + 53] == 1) { - //confirmed proper separator bits found - //return start position - return (int) start_idx; - } - return -6; + if ( !dest[start_idx + 8] + && dest[start_idx + 17] == 1 + && dest[start_idx + 26] == 1 + && dest[start_idx + 35] == 1 + && dest[start_idx + 44] == 1 + && dest[start_idx + 53] == 1) { + //confirmed proper separator bits found + //return start position + return (int) start_idx; + } + return -6; } diff --git a/common/lfdemod.h b/common/lfdemod.h index 222495a99..80f0e06a7 100644 --- a/common/lfdemod.h +++ b/common/lfdemod.h @@ -19,7 +19,7 @@ #include // for #include // for bool #include "parity.h" // for parity test -#include "util.h" // for ARRAYLEN +#include "util.h" // for ARRAYLEN //might not be high enough for noisy environments #define NOISE_AMPLITUDE_THRESHOLD 10 @@ -30,11 +30,11 @@ //generic typedef struct { - int low; - int high; - int mean; - int amplitude; - bool isnoise; + int low; + int high; + int mean; + int amplitude; + bool isnoise; } signal_t; signal_t* getSignalProperties(void); @@ -50,12 +50,12 @@ extern int askdemod(uint8_t *bits, size_t *size, int *clk, int *invert, int extern int askdemod_ext(uint8_t *bits, size_t *size, int *clk, int *invert, int maxErr, uint8_t amp, uint8_t askType, int *startIdx); extern void askAmp(uint8_t *bits, size_t size); extern int BiphaseRawDecode(uint8_t *bits, size_t *size, int *offset, int invert); -extern uint8_t bits_to_array(const uint8_t *bits, size_t size, uint8_t *dest); +extern uint8_t bits_to_array(const uint8_t *bits, size_t size, uint8_t *dest); extern uint32_t bytebits_to_byte(uint8_t *src, size_t numbits); extern uint32_t bytebits_to_byteLSBF(uint8_t *src, size_t numbits); extern uint16_t countFC(uint8_t *bits, size_t size, bool fskAdj); extern int DetectASKClock(uint8_t *dest, size_t size, int *clock, int maxErr); -extern bool DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low); +extern bool DetectCleanAskWave(uint8_t *dest, size_t size, uint8_t high, uint8_t low); extern uint8_t detectFSKClk(uint8_t *bits, size_t size, uint8_t fcHigh, uint8_t fcLow, int *firstClockEdge); extern int DetectNRZClock(uint8_t *dest, size_t size, int clock, size_t *clockStartIdx); extern int DetectPSKClock(uint8_t *dest, size_t size, int clock, size_t *firstPhaseShift, uint8_t *curPhase, uint8_t *fc); @@ -69,8 +69,8 @@ extern int ManchesterEncode(uint8_t *bits, size_t size); extern int manrawdecode(uint8_t *bits, size_t *size, uint8_t invert, uint8_t *alignPos); extern int nrzRawDemod(uint8_t *dest, size_t *size, int *clk, int *invert, int *startIdx); extern bool parityTest(uint32_t bits, uint8_t bitLen, uint8_t pType); -extern bool preambleSearch(uint8_t *bits, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx); -extern bool preambleSearchEx(uint8_t *bits, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx, bool findone); +extern bool preambleSearch(uint8_t *bits, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx); +extern bool preambleSearchEx(uint8_t *bits, uint8_t *preamble, size_t pLen, size_t *size, size_t *startIdx, bool findone); extern int pskRawDemod(uint8_t *dest, size_t *size, int *clock, int *invert); extern int pskRawDemod_ext(uint8_t *dest, size_t *size, int *clock, int *invert, int *startIdx); extern void psk2TOpsk1(uint8_t *bits, size_t size); diff --git a/common/parity.h b/common/parity.h index 9aaf936ed..94d98d913 100644 --- a/common/parity.h +++ b/common/parity.h @@ -22,23 +22,23 @@ extern const uint8_t OddByteParity[256]; static inline bool oddparity8(const uint8_t x) { - return OddByteParity[x]; + return OddByteParity[x]; } static inline bool evenparity8(const uint8_t x) { - return !OddByteParity[x]; + return !OddByteParity[x]; } static inline bool evenparity32(uint32_t x) { #if !defined __GNUC__ - x ^= x >> 16; - x ^= x >> 8; - return evenparity8(x); + x ^= x >> 16; + x ^= x >> 8; + return evenparity8(x); #else - return __builtin_parity(x); + return __builtin_parity(x); #endif } @@ -46,11 +46,11 @@ static inline bool evenparity32(uint32_t x) static inline bool oddparity32(uint32_t x) { #if !defined __GNUC__ - x ^= x >> 16; - x ^= x >> 8; - return oddparity8(x); + x ^= x >> 16; + x ^= x >> 8; + return oddparity8(x); #else - return !__builtin_parity(x); + return !__builtin_parity(x); #endif } diff --git a/common/prng.c b/common/prng.c index b1a608d7e..fb39dd11c 100644 --- a/common/prng.c +++ b/common/prng.c @@ -17,7 +17,7 @@ uint32_t burtle_get_mod( prng_ctx *x ) { void burtle_init_mod(prng_ctx *x, uint32_t seed ) { x->a = 0xf1ea5eed; - x->b = x->c = x->d = seed; + x->b = x->c = x->d = seed; for (uint8_t i=0; i < 42; ++i) { (void)burtle_get_mod(x); } @@ -33,7 +33,7 @@ void burtle_init(prng_ctx *x, uint32_t seed ) { uint32_t GetSimplePrng( uint32_t seed ){ - seed *= 0x19660D; - seed += 0x3C6EF35F; - return seed; + seed *= 0x19660D; + seed += 0x3C6EF35F; + return seed; } diff --git a/common/prng.h b/common/prng.h index f7a875b6c..fc9abd346 100644 --- a/common/prng.h +++ b/common/prng.h @@ -9,10 +9,10 @@ #include #include typedef struct prng_ctx { - uint32_t a; - uint32_t b; - uint32_t c; - uint32_t d; + uint32_t a; + uint32_t b; + uint32_t c; + uint32_t d; } prng_ctx; //uint32_t burtle_get( prng_ctx *x ); diff --git a/common/protocols.c b/common/protocols.c index 9649c51d9..be1076846 100644 --- a/common/protocols.c +++ b/common/protocols.c @@ -2,17 +2,17 @@ // ATA55xx shared presets & routines uint32_t GetT55xxClockBit(uint32_t clock) { - switch (clock) { - case 128: return T55x7_BITRATE_RF_128; - case 100: return T55x7_BITRATE_RF_100; - case 64: return T55x7_BITRATE_RF_64; - case 50: return T55x7_BITRATE_RF_50; - case 40: return T55x7_BITRATE_RF_40; - case 32: return T55x7_BITRATE_RF_32; - case 16: return T55x7_BITRATE_RF_16; - case 8: return T55x7_BITRATE_RF_8; - default : return 0; - } + switch (clock) { + case 128: return T55x7_BITRATE_RF_128; + case 100: return T55x7_BITRATE_RF_100; + case 64: return T55x7_BITRATE_RF_64; + case 50: return T55x7_BITRATE_RF_50; + case 40: return T55x7_BITRATE_RF_40; + case 32: return T55x7_BITRATE_RF_32; + case 16: return T55x7_BITRATE_RF_16; + case 8: return T55x7_BITRATE_RF_8; + default : return 0; + } } #ifndef ON_DEVICE @@ -20,122 +20,122 @@ uint32_t GetT55xxClockBit(uint32_t clock) { #define PrintAndLogDevice(level, format, args...) PrintAndLogEx(level, format , ## args) uint8_t isset(uint8_t val, uint8_t mask) { - return (val & mask); + return (val & mask); } uint8_t notset(uint8_t val, uint8_t mask){ - return !(val & mask); + return !(val & mask); } void fuse_config(const picopass_hdr *hdr) { - uint8_t fuses = hdr->conf.fuses; + uint8_t fuses = hdr->conf.fuses; - if (isset(fuses,FUSE_FPERS)) - PrintAndLogDevice(SUCCESS, "\tMode: Personalization [Programmable]"); - else - PrintAndLogDevice(NORMAL, "\tMode: Application [Locked]"); + if (isset(fuses,FUSE_FPERS)) + PrintAndLogDevice(SUCCESS, "\tMode: Personalization [Programmable]"); + else + PrintAndLogDevice(NORMAL, "\tMode: Application [Locked]"); - if (isset(fuses, FUSE_CODING1)) { - PrintAndLogDevice(NORMAL, "\tCoding: RFU"); - } else { - if( isset( fuses , FUSE_CODING0)) - PrintAndLogDevice(NORMAL, "\tCoding: ISO 14443-2 B/ISO 15693"); - else - PrintAndLogDevice(NORMAL, "\tCoding: ISO 14443B only"); - } - // 1 1 - if( isset (fuses,FUSE_CRYPT1) && isset(fuses, FUSE_CRYPT0 )) PrintAndLogDevice(SUCCESS, "\tCrypt: Secured page, keys not locked"); - // 1 0 - if( isset (fuses,FUSE_CRYPT1) && notset( fuses, FUSE_CRYPT0 )) PrintAndLogDevice(NORMAL, "\tCrypt: Secured page, keys locked"); - // 0 1 - if( notset (fuses,FUSE_CRYPT1) && isset( fuses, FUSE_CRYPT0 )) PrintAndLogDevice(SUCCESS, "\tCrypt: Non secured page"); - // 0 0 - if( notset (fuses,FUSE_CRYPT1) && notset( fuses, FUSE_CRYPT0 )) PrintAndLogDevice(NORMAL, "\tCrypt: No auth possible. Read only if RA is enabled"); + if (isset(fuses, FUSE_CODING1)) { + PrintAndLogDevice(NORMAL, "\tCoding: RFU"); + } else { + if( isset( fuses , FUSE_CODING0)) + PrintAndLogDevice(NORMAL, "\tCoding: ISO 14443-2 B/ISO 15693"); + else + PrintAndLogDevice(NORMAL, "\tCoding: ISO 14443B only"); + } + // 1 1 + if( isset (fuses,FUSE_CRYPT1) && isset(fuses, FUSE_CRYPT0 )) PrintAndLogDevice(SUCCESS, "\tCrypt: Secured page, keys not locked"); + // 1 0 + if( isset (fuses,FUSE_CRYPT1) && notset( fuses, FUSE_CRYPT0 )) PrintAndLogDevice(NORMAL, "\tCrypt: Secured page, keys locked"); + // 0 1 + if( notset (fuses,FUSE_CRYPT1) && isset( fuses, FUSE_CRYPT0 )) PrintAndLogDevice(SUCCESS, "\tCrypt: Non secured page"); + // 0 0 + if( notset (fuses,FUSE_CRYPT1) && notset( fuses, FUSE_CRYPT0 )) PrintAndLogDevice(NORMAL, "\tCrypt: No auth possible. Read only if RA is enabled"); - if( isset( fuses, FUSE_RA)) - PrintAndLogDevice(NORMAL, "\tRA: Read access enabled"); - else - PrintAndLogDevice(WARNING, "\tRA: Read access not enabled"); + if( isset( fuses, FUSE_RA)) + PrintAndLogDevice(NORMAL, "\tRA: Read access enabled"); + else + PrintAndLogDevice(WARNING, "\tRA: Read access not enabled"); } void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb) { - // mem-bit 5, mem-bit 7, chip-bit 4: defines chip type - uint8_t k16 = isset(mem_cfg, 0x80); - //uint8_t k2 = isset(mem_cfg, 0x08); - uint8_t book = isset(mem_cfg, 0x20); + // mem-bit 5, mem-bit 7, chip-bit 4: defines chip type + uint8_t k16 = isset(mem_cfg, 0x80); + //uint8_t k2 = isset(mem_cfg, 0x08); + uint8_t book = isset(mem_cfg, 0x20); - if(isset(chip_cfg, 0x10) && !k16 && !book) { - *kb = 2; - *app_areas = 2; - *max_blk = 31; - } else if(isset(chip_cfg, 0x10) && k16 && !book) { - *kb = 16; - *app_areas = 2; - *max_blk = 255; //16kb - } else if(notset(chip_cfg, 0x10) && !k16 && !book) { - *kb = 16; - *app_areas = 16; - *max_blk = 255; //16kb - } else if(isset(chip_cfg, 0x10) && k16 && book) { - *kb = 32; - *app_areas = 3; - *max_blk = 255; //16kb - } else if(notset(chip_cfg, 0x10) && !k16 && book) { - *kb = 32; - *app_areas = 17; - *max_blk = 255; //16kb - } else { - *kb = 32; - *app_areas = 2; - *max_blk = 255; - } + if(isset(chip_cfg, 0x10) && !k16 && !book) { + *kb = 2; + *app_areas = 2; + *max_blk = 31; + } else if(isset(chip_cfg, 0x10) && k16 && !book) { + *kb = 16; + *app_areas = 2; + *max_blk = 255; //16kb + } else if(notset(chip_cfg, 0x10) && !k16 && !book) { + *kb = 16; + *app_areas = 16; + *max_blk = 255; //16kb + } else if(isset(chip_cfg, 0x10) && k16 && book) { + *kb = 32; + *app_areas = 3; + *max_blk = 255; //16kb + } else if(notset(chip_cfg, 0x10) && !k16 && book) { + *kb = 32; + *app_areas = 17; + *max_blk = 255; //16kb + } else { + *kb = 32; + *app_areas = 2; + *max_blk = 255; + } } void mem_app_config(const picopass_hdr *hdr) { - uint8_t mem = hdr->conf.mem_config; - uint8_t chip = hdr->conf.chip_config; - uint8_t applimit = hdr->conf.app_limit; - uint8_t kb = 2; - uint8_t app_areas = 2; - uint8_t max_blk = 31; + uint8_t mem = hdr->conf.mem_config; + uint8_t chip = hdr->conf.chip_config; + uint8_t applimit = hdr->conf.app_limit; + uint8_t kb = 2; + uint8_t app_areas = 2; + uint8_t max_blk = 31; - getMemConfig(mem, chip, &max_blk, &app_areas, &kb); + getMemConfig(mem, chip, &max_blk, &app_areas, &kb); - if (applimit < 6) applimit = 26; - if (kb == 2 && (applimit > 0x1f) ) applimit = 26; + if (applimit < 6) applimit = 26; + if (kb == 2 && (applimit > 0x1f) ) applimit = 26; - PrintAndLogDevice(NORMAL, " Mem: %u KBits/%u App Areas (%u * 8 bytes) [%02X]", kb, app_areas, max_blk, mem); - PrintAndLogDevice(NORMAL, "\tAA1: blocks 06-%02X", applimit); - PrintAndLogDevice(NORMAL, "\tAA2: blocks %02X-%02X", applimit+1, max_blk); - PrintAndLogDevice(NORMAL, "\tOTP: 0x%02X%02X", hdr->conf.otp[1], hdr->conf.otp[0]); - PrintAndLogDevice(NORMAL, "\nKeyAccess:"); + PrintAndLogDevice(NORMAL, " Mem: %u KBits/%u App Areas (%u * 8 bytes) [%02X]", kb, app_areas, max_blk, mem); + PrintAndLogDevice(NORMAL, "\tAA1: blocks 06-%02X", applimit); + PrintAndLogDevice(NORMAL, "\tAA2: blocks %02X-%02X", applimit+1, max_blk); + PrintAndLogDevice(NORMAL, "\tOTP: 0x%02X%02X", hdr->conf.otp[1], hdr->conf.otp[0]); + PrintAndLogDevice(NORMAL, "\nKeyAccess:"); - uint8_t book = isset(mem, 0x20); - if (book) { - PrintAndLogDevice(NORMAL, "\tRead A - Kd"); - PrintAndLogDevice(NORMAL, "\tRead B - Kc"); - PrintAndLogDevice(NORMAL, "\tWrite A - Kd"); - PrintAndLogDevice(NORMAL, "\tWrite B - Kc"); - PrintAndLogDevice(NORMAL, "\tDebit - Kd or Kc"); - PrintAndLogDevice(NORMAL,"\tCredit - Kc"); - } else{ - PrintAndLogDevice(NORMAL, "\tRead A - Kd or Kc"); - PrintAndLogDevice(NORMAL, "\tRead B - Kd or Kc"); - PrintAndLogDevice(NORMAL, "\tWrite A - Kc"); - PrintAndLogDevice(NORMAL, "\tWrite B - Kc"); - PrintAndLogDevice(NORMAL, "\tDebit - Kd or Kc"); - PrintAndLogDevice(NORMAL, "\tCredit - Kc"); - } + uint8_t book = isset(mem, 0x20); + if (book) { + PrintAndLogDevice(NORMAL, "\tRead A - Kd"); + PrintAndLogDevice(NORMAL, "\tRead B - Kc"); + PrintAndLogDevice(NORMAL, "\tWrite A - Kd"); + PrintAndLogDevice(NORMAL, "\tWrite B - Kc"); + PrintAndLogDevice(NORMAL, "\tDebit - Kd or Kc"); + PrintAndLogDevice(NORMAL,"\tCredit - Kc"); + } else{ + PrintAndLogDevice(NORMAL, "\tRead A - Kd or Kc"); + PrintAndLogDevice(NORMAL, "\tRead B - Kd or Kc"); + PrintAndLogDevice(NORMAL, "\tWrite A - Kc"); + PrintAndLogDevice(NORMAL, "\tWrite B - Kc"); + PrintAndLogDevice(NORMAL, "\tDebit - Kd or Kc"); + PrintAndLogDevice(NORMAL, "\tCredit - Kc"); + } } void print_picopass_info(const picopass_hdr *hdr) { - fuse_config(hdr); - mem_app_config(hdr); + fuse_config(hdr); + mem_app_config(hdr); } void printIclassDumpInfo(uint8_t* iclass_dump) { - print_picopass_info((picopass_hdr *) iclass_dump); + print_picopass_info((picopass_hdr *) iclass_dump); } #else - #define PrintAndLogDevice(level, format, ...) { } + #define PrintAndLogDevice(level, format, ...) { } #endif //ON_DEVICE diff --git a/common/protocols.h b/common/protocols.h index ce56b3175..50e6e0b46 100644 --- a/common/protocols.h +++ b/common/protocols.h @@ -9,115 +9,115 @@ //The following data is taken from http://www.proxmark.org/forum/viewtopic.php?pid=13501#p13501 /* ISO14443A (usually NFC tags) - 26 (7bits) = REQA - 30 = Read (usage: 30+1byte block number+2bytes ISO14443A-CRC - answer: 16bytes) - A2 = Write (usage: A2+1byte block number+4bytes data+2bytes ISO14443A-CRC - answer: 0A [ACK] or 00 [NAK]) - 52 (7bits) = WUPA (usage: 52(7bits) - answer: 2bytes ATQA) - 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor) - 93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK) - 95 20 = Anticollision of cascade level2 - 95 70 = Select of cascade level2 - 50 00 = Halt (usage: 5000+2bytes ISO14443A-CRC - no answer from card) + 26 (7bits) = REQA + 30 = Read (usage: 30+1byte block number+2bytes ISO14443A-CRC - answer: 16bytes) + A2 = Write (usage: A2+1byte block number+4bytes data+2bytes ISO14443A-CRC - answer: 0A [ACK] or 00 [NAK]) + 52 (7bits) = WUPA (usage: 52(7bits) - answer: 2bytes ATQA) + 93 20 = Anticollision (usage: 9320 - answer: 4bytes UID+1byte UID-bytes-xor) + 93 70 = Select (usage: 9370+5bytes 9320 answer - answer: 1byte SAK) + 95 20 = Anticollision of cascade level2 + 95 70 = Select of cascade level2 + 50 00 = Halt (usage: 5000+2bytes ISO14443A-CRC - no answer from card) Mifare - 60 = Authenticate with KeyA - 61 = Authenticate with KeyB - 40 (7bits) = Used to put Chinese Changeable UID cards in special mode (must be followed by 43 (8bits) - answer: 0A) - C0 = Decrement - C1 = Increment - C2 = Restore - B0 = Transfer + 60 = Authenticate with KeyA + 61 = Authenticate with KeyB + 40 (7bits) = Used to put Chinese Changeable UID cards in special mode (must be followed by 43 (8bits) - answer: 0A) + C0 = Decrement + C1 = Increment + C2 = Restore + B0 = Transfer Ultralight C - A0 = Compatibility Write (to accomodate MIFARE commands) - 1A = Step1 Authenticate - AF = Step2 Authenticate + A0 = Compatibility Write (to accomodate MIFARE commands) + 1A = Step1 Authenticate + AF = Step2 Authenticate ISO14443B - 05 = REQB - 1D = ATTRIB - 50 = HALT + 05 = REQB + 1D = ATTRIB + 50 = HALT - BA = PING (reader -> tag) - AB = PONG (tag -> reader) + BA = PING (reader -> tag) + AB = PONG (tag -> reader) SRIX4K (tag does not respond to 05) - 06 00 = INITIATE - 0E xx = SELECT ID (xx = Chip-ID) - 0B = Get UID - 08 yy = Read Block (yy = block number) - 09 yy dd dd dd dd = Write Block (yy = block number; dd dd dd dd = data to be written) - 0C = Reset to Inventory - 0F = Completion - 0A 11 22 33 44 55 66 = Authenticate (11 22 33 44 55 66 = data to authenticate) + 06 00 = INITIATE + 0E xx = SELECT ID (xx = Chip-ID) + 0B = Get UID + 08 yy = Read Block (yy = block number) + 09 yy dd dd dd dd = Write Block (yy = block number; dd dd dd dd = data to be written) + 0C = Reset to Inventory + 0F = Completion + 0A 11 22 33 44 55 66 = Authenticate (11 22 33 44 55 66 = data to authenticate) ISO15693 - MANDATORY COMMANDS (all ISO15693 tags must support those) - 01 = Inventory (usage: 260100+2bytes ISO15693-CRC - answer: 12bytes) - 02 = Stay Quiet - OPTIONAL COMMANDS (not all tags support them) - 20 = Read Block (usage: 0220+1byte block number+2bytes ISO15693-CRC - answer: 4bytes) - 21 = Write Block (usage: 0221+1byte block number+4bytes data+2bytes ISO15693-CRC - answer: 4bytes) - 22 = Lock Block - 23 = Read Multiple Blocks (usage: 0223+1byte 1st block to read+1byte last block to read+2bytes ISO15693-CRC) - 25 = Select - 26 = Reset to Ready - 27 = Write AFI - 28 = Lock AFI - 29 = Write DSFID - 2A = Lock DSFID - 2B = Get_System_Info (usage: 022B+2bytes ISO15693-CRC - answer: 14 or more bytes) - 2C = Read Multiple Block Security Status (usage: 022C+1byte 1st block security to read+1byte last block security to read+2bytes ISO15693-CRC) + MANDATORY COMMANDS (all ISO15693 tags must support those) + 01 = Inventory (usage: 260100+2bytes ISO15693-CRC - answer: 12bytes) + 02 = Stay Quiet + OPTIONAL COMMANDS (not all tags support them) + 20 = Read Block (usage: 0220+1byte block number+2bytes ISO15693-CRC - answer: 4bytes) + 21 = Write Block (usage: 0221+1byte block number+4bytes data+2bytes ISO15693-CRC - answer: 4bytes) + 22 = Lock Block + 23 = Read Multiple Blocks (usage: 0223+1byte 1st block to read+1byte last block to read+2bytes ISO15693-CRC) + 25 = Select + 26 = Reset to Ready + 27 = Write AFI + 28 = Lock AFI + 29 = Write DSFID + 2A = Lock DSFID + 2B = Get_System_Info (usage: 022B+2bytes ISO15693-CRC - answer: 14 or more bytes) + 2C = Read Multiple Block Security Status (usage: 022C+1byte 1st block security to read+1byte last block security to read+2bytes ISO15693-CRC) EM Microelectronic CUSTOM COMMANDS - A5 = Active EAS (followed by 1byte IC Manufacturer code+1byte EAS type) - A7 = Write EAS ID (followed by 1byte IC Manufacturer code+2bytes EAS value) - B8 = Get Protection Status for a specific block (followed by 1byte IC Manufacturer code+1byte block number+1byte of how many blocks after the previous is needed the info) - E4 = Login (followed by 1byte IC Manufacturer code+4bytes password) + A5 = Active EAS (followed by 1byte IC Manufacturer code+1byte EAS type) + A7 = Write EAS ID (followed by 1byte IC Manufacturer code+2bytes EAS value) + B8 = Get Protection Status for a specific block (followed by 1byte IC Manufacturer code+1byte block number+1byte of how many blocks after the previous is needed the info) + E4 = Login (followed by 1byte IC Manufacturer code+4bytes password) NXP/Philips CUSTOM COMMANDS - A0 = Inventory Read - A1 = Fast Inventory Read - A2 = Set EAS - A3 = Reset EAS - A4 = Lock EAS - A5 = EAS Alarm - A6 = Password Protect EAS - A7 = Write EAS ID - A8 = Read EPC - B0 = Inventory Page Read - B1 = Fast Inventory Page Read - B2 = Get Random Number - B3 = Set Password - B4 = Write Password - B5 = Lock Password - B6 = Bit Password Protection - B7 = Lock Page Protection Condition - B8 = Get Multiple Block Protection Status - B9 = Destroy SLI - BA = Enable Privacy - BB = 64bit Password Protection - 40 = Long Range CMD (Standard ISO/TR7003:1990) + A0 = Inventory Read + A1 = Fast Inventory Read + A2 = Set EAS + A3 = Reset EAS + A4 = Lock EAS + A5 = EAS Alarm + A6 = Password Protect EAS + A7 = Write EAS ID + A8 = Read EPC + B0 = Inventory Page Read + B1 = Fast Inventory Page Read + B2 = Get Random Number + B3 = Set Password + B4 = Write Password + B5 = Lock Password + B6 = Bit Password Protection + B7 = Lock Page Protection Condition + B8 = Get Multiple Block Protection Status + B9 = Destroy SLI + BA = Enable Privacy + BB = 64bit Password Protection + 40 = Long Range CMD (Standard ISO/TR7003:1990) ISO 7816-4 Basic interindustry commands. For command APDU's. - B0 = READ BINARY - D0 = WRITE BINARY - D6 = UPDATE BINARY - 0E = ERASE BINARY - B2 = READ RECORDS - D2 = WRITE RECORDS - E2 = APPEND RECORD - DC = UPDATE RECORD - CA = GET DATA - DA = PUT DATA - A4 = SELECT FILE - 20 = VERIFY - 88 = INTERNAL AUTHENTICATION - 82 = EXTERNAL AUTHENTICATION - B4 = GET CHALLENGE - 70 = MANAGE CHANNEL + B0 = READ BINARY + D0 = WRITE BINARY + D6 = UPDATE BINARY + 0E = ERASE BINARY + B2 = READ RECORDS + D2 = WRITE RECORDS + E2 = APPEND RECORD + DC = UPDATE RECORD + CA = GET DATA + DA = PUT DATA + A4 = SELECT FILE + 20 = VERIFY + 88 = INTERNAL AUTHENTICATION + 82 = EXTERNAL AUTHENTICATION + B4 = GET CHALLENGE + 70 = MANAGE CHANNEL - For response APDU's - 90 00 = OK - 6x xx = ERROR + For response APDU's + 90 00 = OK + 6x xx = ERROR */ // these cmds are adjusted to ISO15693 and Manchester encoding requests. // for instance ICLASS_CMD_SELECT 0x81 tells if ISO14443b/BPSK coding/106 kbits/s @@ -134,62 +134,62 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define ICLASS_CMD_SELECT 0x81 #define ICLASS_CMD_PAGESEL 0x84 -#define ICLASS_CMD_UPDATE 0x87 +#define ICLASS_CMD_UPDATE 0x87 #define ICLASS_CMD_READCHECK_KC 0x18 #define ICLASS_CMD_READCHECK_KD 0x88 #define ICLASS_CMD_ACT 0x8E -#define ISO14443A_CMD_REQA 0x26 -#define ISO14443A_CMD_READBLOCK 0x30 -#define ISO14443A_CMD_WUPA 0x52 -#define ISO14443A_CMD_OPTS 0x35 +#define ISO14443A_CMD_REQA 0x26 +#define ISO14443A_CMD_READBLOCK 0x30 +#define ISO14443A_CMD_WUPA 0x52 +#define ISO14443A_CMD_OPTS 0x35 #define ISO14443A_CMD_ANTICOLL_OR_SELECT 0x93 #define ISO14443A_CMD_ANTICOLL_OR_SELECT_2 0x95 #define ISO14443A_CMD_ANTICOLL_OR_SELECT_3 0x97 -#define ISO14443A_CMD_WRITEBLOCK 0xA0 -#define ISO14443A_CMD_HALT 0x50 -#define ISO14443A_CMD_RATS 0xE0 +#define ISO14443A_CMD_WRITEBLOCK 0xA0 +#define ISO14443A_CMD_HALT 0x50 +#define ISO14443A_CMD_RATS 0xE0 -#define MIFARE_AUTH_KEYA 0x60 -#define MIFARE_AUTH_KEYB 0x61 -#define MIFARE_MAGICWUPC1 0x40 -#define MIFARE_MAGICWUPC2 0x43 -#define MIFARE_MAGICWIPEC 0x41 -#define MIFARE_CMD_INC 0xC0 -#define MIFARE_CMD_DEC 0xC1 -#define MIFARE_CMD_RESTORE 0xC2 -#define MIFARE_CMD_TRANSFER 0xB0 +#define MIFARE_AUTH_KEYA 0x60 +#define MIFARE_AUTH_KEYB 0x61 +#define MIFARE_MAGICWUPC1 0x40 +#define MIFARE_MAGICWUPC2 0x43 +#define MIFARE_MAGICWIPEC 0x41 +#define MIFARE_CMD_INC 0xC0 +#define MIFARE_CMD_DEC 0xC1 +#define MIFARE_CMD_RESTORE 0xC2 +#define MIFARE_CMD_TRANSFER 0xB0 -#define MIFARE_EV1_PERSONAL_UID 0x40 -#define MIFARE_EV1_SETMODE 0x43 +#define MIFARE_EV1_PERSONAL_UID 0x40 +#define MIFARE_EV1_SETMODE 0x43 -#define MIFARE_ULC_WRITE 0xA2 -//#define MIFARE_ULC__COMP_WRITE 0xA0 -#define MIFARE_ULC_AUTH_1 0x1A -#define MIFARE_ULC_AUTH_2 0xAF +#define MIFARE_ULC_WRITE 0xA2 +//#define MIFARE_ULC__COMP_WRITE 0xA0 +#define MIFARE_ULC_AUTH_1 0x1A +#define MIFARE_ULC_AUTH_2 0xAF -#define MIFARE_ULEV1_AUTH 0x1B -#define MIFARE_ULEV1_VERSION 0x60 -#define MIFARE_ULEV1_FASTREAD 0x3A -#define MIFARE_ULEV1_READ_CNT 0x39 -#define MIFARE_ULEV1_INCR_CNT 0xA5 -#define MIFARE_ULEV1_READSIG 0x3C -#define MIFARE_ULEV1_CHECKTEAR 0x3E -#define MIFARE_ULEV1_VCSL 0x4B +#define MIFARE_ULEV1_AUTH 0x1B +#define MIFARE_ULEV1_VERSION 0x60 +#define MIFARE_ULEV1_FASTREAD 0x3A +#define MIFARE_ULEV1_READ_CNT 0x39 +#define MIFARE_ULEV1_INCR_CNT 0xA5 +#define MIFARE_ULEV1_READSIG 0x3C +#define MIFARE_ULEV1_CHECKTEAR 0x3E +#define MIFARE_ULEV1_VCSL 0x4B // New Mifare UL Nano commands. Ref:: (https://www.nxp.com/docs/en/data-sheet/MF0UN_H_00.pdf) -#define MIFARE_ULNANO_WRITESIG 0xA9 -#define MIFARE_ULNANO_LOCKSIF 0xAC +#define MIFARE_ULNANO_WRITESIG 0xA9 +#define MIFARE_ULNANO_LOCKSIF 0xAC // mifare 4bit card answers #define CARD_ACK 0x0A // 1010 - ACK -#define CARD_NACK_IV 0x00 // 0000 - NACK, invalid argument (invalid page address) -#define CARD_NACK_PA 0x01 // 0001 - NACK, parity / crc error +#define CARD_NACK_IV 0x00 // 0000 - NACK, invalid argument (invalid page address) +#define CARD_NACK_PA 0x01 // 0001 - NACK, parity / crc error #define CARD_NACK_NA 0x04 // 0100 - NACK, not allowed (command not allowed) #define CARD_NACK_TR 0x05 // 0101 - NACK, transmission error -#define CARD_NACK_EE 0x07 // 0111 - NACK, EEPROM write error +#define CARD_NACK_EE 0x07 // 0111 - NACK, EEPROM write error // Magic Generation 1, parameter "work flags" // bit 0 - need get UID @@ -198,14 +198,14 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. // bit 3 - turn on FPGA // bit 4 - turn off FPGA // bit 5 - set datain instead of issuing USB reply (called via ARM for StandAloneMode14a) -#define MAGIC_UID 0x01 -#define MAGIC_WUPC 0x02 -#define MAGIC_HALT 0x04 -#define MAGIC_INIT 0x08 -#define MAGIC_OFF 0x10 -#define MAGIC_DATAIN 0x20 -#define MAGIC_WIPE 0x40 -#define MAGIC_SINGLE (MAGIC_WUPC | MAGIC_HALT | MAGIC_INIT | MAGIC_OFF) //0x1E +#define MAGIC_UID 0x01 +#define MAGIC_WUPC 0x02 +#define MAGIC_HALT 0x04 +#define MAGIC_INIT 0x08 +#define MAGIC_OFF 0x10 +#define MAGIC_DATAIN 0x20 +#define MAGIC_WIPE 0x40 +#define MAGIC_SINGLE (MAGIC_WUPC | MAGIC_HALT | MAGIC_INIT | MAGIC_OFF) //0x1E /** 06 00 = INITIATE @@ -229,8 +229,8 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define ISO14443B_RESET 0x0C #define ISO14443B_COMPLETION 0x0F #define ISO14443B_AUTHENTICATE 0x0A -#define ISO14443B_PING 0xBA -#define ISO14443B_PONG 0xAB +#define ISO14443B_PING 0xBA +#define ISO14443B_PONG 0xAB //First byte is 26 #define ISO15693_INVENTORY 0x01 @@ -251,31 +251,31 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. // Topaz command set: -#define TOPAZ_REQA 0x26 // Request -#define TOPAZ_WUPA 0x52 // WakeUp -#define TOPAZ_RID 0x78 // Read ID -#define TOPAZ_RALL 0x00 // Read All (all bytes) -#define TOPAZ_READ 0x01 // Read (a single byte) -#define TOPAZ_WRITE_E 0x53 // Write-with-erase (a single byte) -#define TOPAZ_WRITE_NE 0x1a // Write-no-erase (a single byte) +#define TOPAZ_REQA 0x26 // Request +#define TOPAZ_WUPA 0x52 // WakeUp +#define TOPAZ_RID 0x78 // Read ID +#define TOPAZ_RALL 0x00 // Read All (all bytes) +#define TOPAZ_READ 0x01 // Read (a single byte) +#define TOPAZ_WRITE_E 0x53 // Write-with-erase (a single byte) +#define TOPAZ_WRITE_NE 0x1a // Write-no-erase (a single byte) // additional commands for Dynamic Memory Model -#define TOPAZ_RSEG 0x10 // Read segment -#define TOPAZ_READ8 0x02 // Read (eight bytes) -#define TOPAZ_WRITE_E8 0x54 // Write-with-erase (eight bytes) -#define TOPAZ_WRITE_NE8 0x1B // Write-no-erase (eight bytes) +#define TOPAZ_RSEG 0x10 // Read segment +#define TOPAZ_READ8 0x02 // Read (eight bytes) +#define TOPAZ_WRITE_E8 0x54 // Write-with-erase (eight bytes) +#define TOPAZ_WRITE_NE8 0x1B // Write-no-erase (eight bytes) // Definitions of which protocol annotations there are available -#define ISO_14443A 0 -#define ICLASS 1 -#define ISO_14443B 2 -#define TOPAZ 3 -#define ISO_7816_4 4 -#define MFDES 5 -#define LEGIC 6 -#define ISO_15693 7 -#define FELICA 8 -#define PROTO_MIFARE 9 +#define ISO_14443A 0 +#define ICLASS 1 +#define ISO_14443B 2 +#define TOPAZ 3 +#define ISO_7816_4 4 +#define MFDES 5 +#define LEGIC 6 +#define ISO_15693 7 +#define FELICA 8 +#define PROTO_MIFARE 9 //-- Picopass fuses #define FUSE_FPERS 0x80 @@ -288,131 +288,131 @@ ISO 7816-4 Basic interindustry commands. For command APDU's. #define FUSE_RA 0x01 // ISO 7816-4 Basic interindustry commands. For command APDU's. -#define ISO7816_READ_BINARY 0xB0 -#define ISO7816_WRITE_BINARY 0xD0 -#define ISO7816_UPDATE_BINARY 0xD6 -#define ISO7816_ERASE_BINARY 0x0E -#define ISO7816_READ_RECORDS 0xB2 -#define ISO7816_WRITE_RECORDS 0xD2 -#define ISO7816_APPEND_RECORD 0xE2 -#define ISO7816_UPDATE_RECORD 0xDC -#define ISO7816_GET_DATA 0xCA -#define ISO7816_PUT_DATA 0xDA -#define ISO7816_SELECT_FILE 0xA4 -#define ISO7816_VERIFY 0x20 +#define ISO7816_READ_BINARY 0xB0 +#define ISO7816_WRITE_BINARY 0xD0 +#define ISO7816_UPDATE_BINARY 0xD6 +#define ISO7816_ERASE_BINARY 0x0E +#define ISO7816_READ_RECORDS 0xB2 +#define ISO7816_WRITE_RECORDS 0xD2 +#define ISO7816_APPEND_RECORD 0xE2 +#define ISO7816_UPDATE_RECORD 0xDC +#define ISO7816_GET_DATA 0xCA +#define ISO7816_PUT_DATA 0xDA +#define ISO7816_SELECT_FILE 0xA4 +#define ISO7816_VERIFY 0x20 #define ISO7816_INTERNAL_AUTHENTICATION 0x88 #define ISO7816_EXTERNAL_AUTHENTICATION 0x82 -#define ISO7816_GET_CHALLENGE 0x84 -#define ISO7816_MANAGE_CHANNEL 0x70 +#define ISO7816_GET_CHALLENGE 0x84 +#define ISO7816_MANAGE_CHANNEL 0x70 -#define ISO7816_GET_RESPONSE 0xC0 -// ISO7816-4 For response APDU's -#define ISO7816_OK 0x9000 -// 6x xx = ERROR +#define ISO7816_GET_RESPONSE 0xC0 +// ISO7816-4 For response APDU's +#define ISO7816_OK 0x9000 +// 6x xx = ERROR // MIFARE DESFire command set: -#define MFDES_CREATE_APPLICATION 0xca -#define MFDES_DELETE_APPLICATION 0xda -#define MFDES_GET_APPLICATION_IDS 0x6a -#define MFDES_SELECT_APPLICATION 0x5a -#define MFDES_FORMAT_PICC 0xfc -#define MFDES_GET_VERSION 0x60 -#define MFDES_READ_DATA 0xbd -#define MFDES_WRITE_DATA 0x3d -#define MFDES_GET_VALUE 0x6c -#define MFDES_CREDIT 0x0c -#define MFDES_DEBIT 0xdc -#define MFDES_LIMITED_CREDIT 0x1c -#define MFDES_WRITE_RECORD 0x3b -#define MFDES_READ_RECORDS 0xbb -#define MFDES_CLEAR_RECORD_FILE 0xeb -#define MFDES_COMMIT_TRANSACTION 0xc7 -#define MFDES_ABORT_TRANSACTION 0xa7 -#define MFDES_GET_FREE_MEMORY 0x6e -#define MFDES_GET_FILE_IDS 0x6f -#define MFDES_GET_ISOFILE_IDS 0x61 -#define MFDES_GET_FILE_SETTINGS 0xf5 -#define MFDES_CHANGE_FILE_SETTINGS 0x5f -#define MFDES_CREATE_STD_DATA_FILE 0xcd -#define MFDES_CREATE_BACKUP_DATA_FILE 0xcb -#define MFDES_CREATE_VALUE_FILE 0xcc -#define MFDES_CREATE_LINEAR_RECORD_FILE 0xc1 -#define MFDES_CREATE_CYCLIC_RECORD_FILE 0xc0 -#define MFDES_DELETE_FILE 0xdf -#define MFDES_AUTHENTICATE 0x0a // AUTHENTICATE_NATIVE -#define MFDES_AUTHENTICATE_ISO 0x1a // AUTHENTICATE_STANDARD -#define MFDES_AUTHENTICATE_AES 0xaa -#define MFDES_CHANGE_KEY_SETTINGS 0x54 -#define MFDES_GET_KEY_SETTINGS 0x45 -#define MFDES_CHANGE_KEY 0xc4 -#define MFDES_GET_KEY_VERSION 0x64 -#define MFDES_AUTHENTICATION_FRAME 0xAF +#define MFDES_CREATE_APPLICATION 0xca +#define MFDES_DELETE_APPLICATION 0xda +#define MFDES_GET_APPLICATION_IDS 0x6a +#define MFDES_SELECT_APPLICATION 0x5a +#define MFDES_FORMAT_PICC 0xfc +#define MFDES_GET_VERSION 0x60 +#define MFDES_READ_DATA 0xbd +#define MFDES_WRITE_DATA 0x3d +#define MFDES_GET_VALUE 0x6c +#define MFDES_CREDIT 0x0c +#define MFDES_DEBIT 0xdc +#define MFDES_LIMITED_CREDIT 0x1c +#define MFDES_WRITE_RECORD 0x3b +#define MFDES_READ_RECORDS 0xbb +#define MFDES_CLEAR_RECORD_FILE 0xeb +#define MFDES_COMMIT_TRANSACTION 0xc7 +#define MFDES_ABORT_TRANSACTION 0xa7 +#define MFDES_GET_FREE_MEMORY 0x6e +#define MFDES_GET_FILE_IDS 0x6f +#define MFDES_GET_ISOFILE_IDS 0x61 +#define MFDES_GET_FILE_SETTINGS 0xf5 +#define MFDES_CHANGE_FILE_SETTINGS 0x5f +#define MFDES_CREATE_STD_DATA_FILE 0xcd +#define MFDES_CREATE_BACKUP_DATA_FILE 0xcb +#define MFDES_CREATE_VALUE_FILE 0xcc +#define MFDES_CREATE_LINEAR_RECORD_FILE 0xc1 +#define MFDES_CREATE_CYCLIC_RECORD_FILE 0xc0 +#define MFDES_DELETE_FILE 0xdf +#define MFDES_AUTHENTICATE 0x0a // AUTHENTICATE_NATIVE +#define MFDES_AUTHENTICATE_ISO 0x1a // AUTHENTICATE_STANDARD +#define MFDES_AUTHENTICATE_AES 0xaa +#define MFDES_CHANGE_KEY_SETTINGS 0x54 +#define MFDES_GET_KEY_SETTINGS 0x45 +#define MFDES_CHANGE_KEY 0xc4 +#define MFDES_GET_KEY_VERSION 0x64 +#define MFDES_AUTHENTICATION_FRAME 0xAF // LEGIC Commands -#define LEGIC_MIM_22 0x0D -#define LEGIC_MIM_256 0x1D -#define LEGIC_MIM_1024 0x3D -#define LEGIC_ACK_22 0x19 -#define LEGIC_ACK_256 0x39 -#define LEGIC_READ 0x01 -#define LEGIC_WRITE 0x00 +#define LEGIC_MIM_22 0x0D +#define LEGIC_MIM_256 0x1D +#define LEGIC_MIM_1024 0x3D +#define LEGIC_ACK_22 0x19 +#define LEGIC_ACK_256 0x39 +#define LEGIC_READ 0x01 +#define LEGIC_WRITE 0x00 void printIclassDumpInfo(uint8_t* iclass_dump); void getMemConfig(uint8_t mem_cfg, uint8_t chip_cfg, uint8_t *max_blk, uint8_t *app_areas, uint8_t *kb); /* T55x7 configuration register definitions */ -#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_MODULATION_DIRECT 0 -#define T55x7_MODULATION_PSK1 0x00001000 -#define T55x7_MODULATION_PSK2 0x00002000 -#define T55x7_MODULATION_PSK3 0x00003000 -#define T55x7_MODULATION_FSK1 0x00004000 -#define T55x7_MODULATION_FSK2 0x00005000 -#define T55x7_MODULATION_FSK1a 0x00006000 -#define T55x7_MODULATION_FSK2a 0x00007000 -#define T55x7_MODULATION_MANCHESTER 0x00008000 -#define T55x7_MODULATION_BIPHASE 0x00010000 -#define T55x7_MODULATION_DIPHASE 0x00018000 -#define T55x7_X_MODE 0x00020000 -#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 -#define T55x7_TESTMODE_DISABLED 0x60000000 +#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_MODULATION_DIRECT 0 +#define T55x7_MODULATION_PSK1 0x00001000 +#define T55x7_MODULATION_PSK2 0x00002000 +#define T55x7_MODULATION_PSK3 0x00003000 +#define T55x7_MODULATION_FSK1 0x00004000 +#define T55x7_MODULATION_FSK2 0x00005000 +#define T55x7_MODULATION_FSK1a 0x00006000 +#define T55x7_MODULATION_FSK2a 0x00007000 +#define T55x7_MODULATION_MANCHESTER 0x00008000 +#define T55x7_MODULATION_BIPHASE 0x00010000 +#define T55x7_MODULATION_DIPHASE 0x00018000 +#define T55x7_X_MODE 0x00020000 +#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 +#define T55x7_TESTMODE_DISABLED 0x60000000 /* T5555 (Q5) configuration register definitions */ -#define T5555_ST_TERMINATOR 0x00000001 -#define T5555_MAXBLOCK_SHIFT 0x00000001 -#define T5555_MODULATION_MANCHESTER 0 -#define T5555_MODULATION_PSK1 0x00000010 -#define T5555_MODULATION_PSK2 0x00000020 -#define T5555_MODULATION_PSK3 0x00000030 -#define T5555_MODULATION_FSK1 0x00000040 -#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_SET_BITRATE(x) (((x-2)/2)<<12) -#define T5555_GET_BITRATE(x) ((((x >> 12) & 0x3F)*2)+2) -#define T5555_BITRATE_SHIFT 12 //(RF=2n+2) ie 64=2*0x1F+2 or n = (RF-2)/2 -#define T5555_FAST_WRITE 0x00004000 -#define T5555_PAGE_SELECT 0x00008000 +#define T5555_ST_TERMINATOR 0x00000001 +#define T5555_MAXBLOCK_SHIFT 0x00000001 +#define T5555_MODULATION_MANCHESTER 0 +#define T5555_MODULATION_PSK1 0x00000010 +#define T5555_MODULATION_PSK2 0x00000020 +#define T5555_MODULATION_PSK3 0x00000030 +#define T5555_MODULATION_FSK1 0x00000040 +#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_SET_BITRATE(x) (((x-2)/2)<<12) +#define T5555_GET_BITRATE(x) ((((x >> 12) & 0x3F)*2)+2) +#define T5555_BITRATE_SHIFT 12 //(RF=2n+2) ie 64=2*0x1F+2 or n = (RF-2)/2 +#define T5555_FAST_WRITE 0x00004000 +#define T5555_PAGE_SELECT 0x00008000 #define T55XX_WRITE_TIMEOUT 1500 @@ -420,152 +420,152 @@ uint32_t GetT55xxClockBit(uint32_t clock); // em4x05 & em4x69 chip configuration register definitions -#define EM4x05_GET_BITRATE(x) (((x & 0x3F)*2)+2) -#define EM4x05_SET_BITRATE(x) ((x-2)/2) -#define EM4x05_MODULATION_NRZ 0x00000000 -#define EM4x05_MODULATION_MANCHESTER 0x00000040 -#define EM4x05_MODULATION_BIPHASE 0x00000080 -#define EM4x05_MODULATION_MILLER 0x000000C0 //not supported by all 4x05/4x69 chips -#define EM4x05_MODULATION_PSK1 0x00000100 //not supported by all 4x05/4x69 chips -#define EM4x05_MODULATION_PSK2 0x00000140 //not supported by all 4x05/4x69 chips -#define EM4x05_MODULATION_PSK3 0x00000180 //not supported by all 4x05/4x69 chips -#define EM4x05_MODULATION_FSK1 0x00000200 //not supported by all 4x05/4x69 chips -#define EM4x05_MODULATION_FSK2 0x00000240 //not supported by all 4x05/4x69 chips -#define EM4x05_PSK_RF_2 0 -#define EM4x05_PSK_RF_4 0x00000400 -#define EM4x05_PSK_RF_8 0x00000800 -#define EM4x05_MAXBLOCK_SHIFT 14 -#define EM4x05_FIRST_USER_BLOCK 5 -#define EM4x05_SET_NUM_BLOCKS(x) ((x+5-1)<<14) //# of blocks sent during default read mode -#define EM4x05_GET_NUM_BLOCKS(x) (((x>>14) & 0xF)-5+1) -#define EM4x05_READ_LOGIN_REQ 1<<18 -#define EM4x05_READ_HK_LOGIN_REQ 1<<19 -#define EM4x05_WRITE_LOGIN_REQ 1<<20 -#define EM4x05_WRITE_HK_LOGIN_REQ 1<<21 -#define EM4x05_READ_AFTER_WRITE 1<<22 -#define EM4x05_DISABLE_ALLOWED 1<<23 -#define EM4x05_READER_TALK_FIRST 1<<24 +#define EM4x05_GET_BITRATE(x) (((x & 0x3F)*2)+2) +#define EM4x05_SET_BITRATE(x) ((x-2)/2) +#define EM4x05_MODULATION_NRZ 0x00000000 +#define EM4x05_MODULATION_MANCHESTER 0x00000040 +#define EM4x05_MODULATION_BIPHASE 0x00000080 +#define EM4x05_MODULATION_MILLER 0x000000C0 //not supported by all 4x05/4x69 chips +#define EM4x05_MODULATION_PSK1 0x00000100 //not supported by all 4x05/4x69 chips +#define EM4x05_MODULATION_PSK2 0x00000140 //not supported by all 4x05/4x69 chips +#define EM4x05_MODULATION_PSK3 0x00000180 //not supported by all 4x05/4x69 chips +#define EM4x05_MODULATION_FSK1 0x00000200 //not supported by all 4x05/4x69 chips +#define EM4x05_MODULATION_FSK2 0x00000240 //not supported by all 4x05/4x69 chips +#define EM4x05_PSK_RF_2 0 +#define EM4x05_PSK_RF_4 0x00000400 +#define EM4x05_PSK_RF_8 0x00000800 +#define EM4x05_MAXBLOCK_SHIFT 14 +#define EM4x05_FIRST_USER_BLOCK 5 +#define EM4x05_SET_NUM_BLOCKS(x) ((x+5-1)<<14) //# of blocks sent during default read mode +#define EM4x05_GET_NUM_BLOCKS(x) (((x>>14) & 0xF)-5+1) +#define EM4x05_READ_LOGIN_REQ 1<<18 +#define EM4x05_READ_HK_LOGIN_REQ 1<<19 +#define EM4x05_WRITE_LOGIN_REQ 1<<20 +#define EM4x05_WRITE_HK_LOGIN_REQ 1<<21 +#define EM4x05_READ_AFTER_WRITE 1<<22 +#define EM4x05_DISABLE_ALLOWED 1<<23 +#define EM4x05_READER_TALK_FIRST 1<<24 // FeliCa protocol -#define FELICA_POLL_REQ 0x00 -#define FELICA_POLL_ACK 0x01 +#define FELICA_POLL_REQ 0x00 +#define FELICA_POLL_ACK 0x01 -#define FELICA_REQSRV_REQ 0x02 -#define FELICA_REQSRV_ACK 0x03 +#define FELICA_REQSRV_REQ 0x02 +#define FELICA_REQSRV_ACK 0x03 -#define FELICA_REQRESP_REQ 0x04 -#define FELICA_REQRESP_ACK 0x05 +#define FELICA_REQRESP_REQ 0x04 +#define FELICA_REQRESP_ACK 0x05 -#define FELICA_RDBLK_REQ 0x06 -#define FELICA_RDBLK_ACK 0x07 +#define FELICA_RDBLK_REQ 0x06 +#define FELICA_RDBLK_ACK 0x07 -#define FELICA_WRTBLK_REQ 0x08 -#define FELICA_WRTBLK_ACK 0x09 +#define FELICA_WRTBLK_REQ 0x08 +#define FELICA_WRTBLK_ACK 0x09 -#define FELICA_SRCHSYSCODE_REQ 0x0a -#define FELICA_SRCHSYSCODE_ACK 0x0b +#define FELICA_SRCHSYSCODE_REQ 0x0a +#define FELICA_SRCHSYSCODE_ACK 0x0b -#define FELICA_REQSYSCODE_REQ 0x0c -#define FELICA_REQSYSCODE_ACK 0x0d +#define FELICA_REQSYSCODE_REQ 0x0c +#define FELICA_REQSYSCODE_ACK 0x0d -#define FELICA_AUTH1_REQ 0x10 -#define FELICA_AUTH1_ACK 0x11 +#define FELICA_AUTH1_REQ 0x10 +#define FELICA_AUTH1_ACK 0x11 -#define FELICA_AUTH2_REQ 0x12 -#define FELICA_AUTH2_ACK 0x13 +#define FELICA_AUTH2_REQ 0x12 +#define FELICA_AUTH2_ACK 0x13 -#define FELICA_RDSEC_REQ 0x14 -#define FELICA_RDSEC_ACK 0x15 +#define FELICA_RDSEC_REQ 0x14 +#define FELICA_RDSEC_ACK 0x15 -#define FELICA_WRTSEC_REQ 0x16 -#define FELICA_WRTSEC_ACK 0x17 +#define FELICA_WRTSEC_REQ 0x16 +#define FELICA_WRTSEC_ACK 0x17 -#define FELICA_REQSRV2_REQ 0x32 -#define FELICA_REQSRV2_ACK 0x33 +#define FELICA_REQSRV2_REQ 0x32 +#define FELICA_REQSRV2_ACK 0x33 -#define FELICA_GETSTATUS_REQ 0x38 -#define FELICA_GETSTATUS_ACK 0x39 +#define FELICA_GETSTATUS_REQ 0x38 +#define FELICA_GETSTATUS_ACK 0x39 -#define FELICA_OSVER_REQ 0x3c -#define FELICA_OSVER_ACK 0x3d +#define FELICA_OSVER_REQ 0x3c +#define FELICA_OSVER_ACK 0x3d -#define FELICA_RESET_MODE_REQ 0x3e -#define FELICA_RESET_MODE_ACK 0x3f +#define FELICA_RESET_MODE_REQ 0x3e +#define FELICA_RESET_MODE_ACK 0x3f -#define FELICA_AUTH1V2_REQ 0x40 -#define FELICA_AUTH1V2_ACK 0x41 +#define FELICA_AUTH1V2_REQ 0x40 +#define FELICA_AUTH1V2_ACK 0x41 -#define FELICA_AUTH2V2_REQ 0x42 -#define FELICA_AUTH2V2_ACK 0x43 +#define FELICA_AUTH2V2_REQ 0x42 +#define FELICA_AUTH2V2_ACK 0x43 -#define FELICA_RDSECV2_REQ 0x44 -#define FELICA_RDSECV2_ACK 0x45 -#define FELICA_WRTSECV2_REQ 0x46 -#define FELICA_WRTSECV2_ACK 0x47 +#define FELICA_RDSECV2_REQ 0x44 +#define FELICA_RDSECV2_ACK 0x45 +#define FELICA_WRTSECV2_REQ 0x46 +#define FELICA_WRTSECV2_ACK 0x47 -#define FELICA_UPDATE_RNDID_REQ 0x4C -#define FELICA_UPDATE_RNDID_ACK 0x4D +#define FELICA_UPDATE_RNDID_REQ 0x4C +#define FELICA_UPDATE_RNDID_ACK 0x4D // FeliCa SYSTEM list -#define SYSTEMCODE_ANY 0xffff // ANY -#define SYSTEMCODE_FELICA_LITE 0x88b4 // FeliCa Lite -#define SYSTEMCODE_COMMON 0xfe00 // Common -#define SYSTEMCODE_EDY 0xfe00 // Edy -#define SYSTEMCODE_CYBERNE 0x0003 // Cyberne -#define SYSTEMCODE_SUICA 0x0003 // Suica -#define SYSTEMCODE_PASMO 0x0003 // Pasmo +#define SYSTEMCODE_ANY 0xffff // ANY +#define SYSTEMCODE_FELICA_LITE 0x88b4 // FeliCa Lite +#define SYSTEMCODE_COMMON 0xfe00 // Common +#define SYSTEMCODE_EDY 0xfe00 // Edy +#define SYSTEMCODE_CYBERNE 0x0003 // Cyberne +#define SYSTEMCODE_SUICA 0x0003 // Suica +#define SYSTEMCODE_PASMO 0x0003 // Pasmo //FeliCa Service list Suica/pasmo (little endian) -#define SERVICE_SUICA_INOUT 0x108f // SUICA/PASMO -#define SERVICE_SUICA_HISTORY 0x090f // SUICA/PASMO -#define SERVICE_FELICA_LITE_READONLY 0x0b00 // FeliCa Lite RO -#define SERVICE_FELICA_LITE_READWRITE 0x0900 // FeliCa Lite RW +#define SERVICE_SUICA_INOUT 0x108f // SUICA/PASMO +#define SERVICE_SUICA_HISTORY 0x090f // SUICA/PASMO +#define SERVICE_FELICA_LITE_READONLY 0x0b00 // FeliCa Lite RO +#define SERVICE_FELICA_LITE_READWRITE 0x0900 // FeliCa Lite RW // Calypso protocol -#define CALYPSO_GET_RESPONSE 0xC0 -#define CALYPSO_SELECT 0xA4 -#define CALYPSO_INVALIDATE 0x04 -#define CALYPSO_REHABILITATE 0x44 -#define CALYPSO_APPEND_RECORD 0xE2 -#define CALYPSO_DECREASE 0x30 -#define CALYPSO_INCREASE 0x32 -#define CALYPSO_READ_BINARY 0xB0 -#define CALYPSO_READ_RECORD 0xB2 -#define CALYPSO_UPDATE_BINARY 0xD6 -#define CALYPSO_UPDATE_RECORD 0xDC -#define CALYPSO_WRITE_RECORD 0xD2 -#define CALYPSO_OPEN_SESSION 0x8A -#define CALYPSO_CLOSE_SESSION 0x8E -#define CALYPSO_GET_CHALLENGE 0x84 -#define CALYPSO_CHANGE_PIN 0xD8 -#define CALYPSO_VERIFY_PIN 0x20 -#define CALYPSO_SV_GET 0x7C -#define CALYPSO_SV_DEBIT 0xBA -#define CALYPSO_SV_RELOAD 0xB8 -#define CALYPSO_SV_UN_DEBIT 0xBC -#define CALYPSO_SAM_SV_DEBIT 0x54 -#define CALYPSO_SAM_SV_RELOAD 0x56 +#define CALYPSO_GET_RESPONSE 0xC0 +#define CALYPSO_SELECT 0xA4 +#define CALYPSO_INVALIDATE 0x04 +#define CALYPSO_REHABILITATE 0x44 +#define CALYPSO_APPEND_RECORD 0xE2 +#define CALYPSO_DECREASE 0x30 +#define CALYPSO_INCREASE 0x32 +#define CALYPSO_READ_BINARY 0xB0 +#define CALYPSO_READ_RECORD 0xB2 +#define CALYPSO_UPDATE_BINARY 0xD6 +#define CALYPSO_UPDATE_RECORD 0xDC +#define CALYPSO_WRITE_RECORD 0xD2 +#define CALYPSO_OPEN_SESSION 0x8A +#define CALYPSO_CLOSE_SESSION 0x8E +#define CALYPSO_GET_CHALLENGE 0x84 +#define CALYPSO_CHANGE_PIN 0xD8 +#define CALYPSO_VERIFY_PIN 0x20 +#define CALYPSO_SV_GET 0x7C +#define CALYPSO_SV_DEBIT 0xBA +#define CALYPSO_SV_RELOAD 0xB8 +#define CALYPSO_SV_UN_DEBIT 0xBC +#define CALYPSO_SAM_SV_DEBIT 0x54 +#define CALYPSO_SAM_SV_RELOAD 0x56 // iclass / picopass chip config structures and shared routines typedef struct { - uint8_t app_limit; //[8] - uint8_t otp[2]; //[9-10] - uint8_t block_writelock;//[11] - uint8_t chip_config; //[12] - uint8_t mem_config; //[13] - uint8_t eas; //[14] - uint8_t fuses; //[15] + uint8_t app_limit; //[8] + uint8_t otp[2]; //[9-10] + uint8_t block_writelock;//[11] + uint8_t chip_config; //[12] + uint8_t mem_config; //[13] + uint8_t eas; //[14] + uint8_t fuses; //[15] } picopass_conf_block; typedef struct { - uint8_t csn[8]; - picopass_conf_block conf; - uint8_t epurse[8]; - uint8_t key_d[8]; - uint8_t key_c[8]; - uint8_t app_issuer_area[8]; + uint8_t csn[8]; + picopass_conf_block conf; + uint8_t epurse[8]; + uint8_t key_d[8]; + uint8_t key_c[8]; + uint8_t app_issuer_area[8]; } picopass_hdr; diff --git a/common/random.c b/common/random.c index 96cdbb628..060f0bd7a 100644 --- a/common/random.c +++ b/common/random.c @@ -14,17 +14,17 @@ static uint32_t g_nextrandom; */ inline void fast_prand(){ - fast_prandEx(GetTickCount()); + fast_prandEx(GetTickCount()); } inline void fast_prandEx(uint32_t seed) { - g_nextrandom = seed; + g_nextrandom = seed; } uint32_t prand() { -// g_nextrandom *= 6364136223846793005; -// g_nextrandom += 1; +// g_nextrandom *= 6364136223846793005; +// g_nextrandom += 1; //return (uint32_t)(g_nextrandom >> 32) % 0xffffffff; - g_nextrandom = (214013 * g_nextrandom + 2531011); - return (g_nextrandom>>16) & 0xFFFF; + g_nextrandom = (214013 * g_nextrandom + 2531011); + return (g_nextrandom>>16) & 0xFFFF; } diff --git a/common/tea.c b/common/tea.c index b3e1a39c1..287a12de9 100644 --- a/common/tea.c +++ b/common/tea.c @@ -13,52 +13,52 @@ void tea_encrypt(uint8_t *v, uint8_t *key) { - uint32_t a=0,b=0,c=0,d=0,y=0,z=0; - uint32_t sum = 0; - uint8_t n = ROUNDS; + uint32_t a=0,b=0,c=0,d=0,y=0,z=0; + uint32_t sum = 0; + uint8_t n = ROUNDS; - //key - a = bytes_to_num(key, 4); - b = bytes_to_num(key+4, 4); - c = bytes_to_num(key+8, 4); - d = bytes_to_num(key+12, 4); + //key + a = bytes_to_num(key, 4); + b = bytes_to_num(key+4, 4); + c = bytes_to_num(key+8, 4); + d = bytes_to_num(key+12, 4); - //input - y = bytes_to_num(v, 4); - z = bytes_to_num(v+4, 4); + //input + y = bytes_to_num(v, 4); + z = bytes_to_num(v+4, 4); - while ( n-- > 0 ) { - sum += DELTA; - y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); - z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d); - } + while ( n-- > 0 ) { + sum += DELTA; + y += ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); + z += ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d); + } - num_to_bytes(y, 4, v); - num_to_bytes(z, 4, v+4); + num_to_bytes(y, 4, v); + num_to_bytes(z, 4, v+4); } void tea_decrypt(uint8_t *v, uint8_t *key) { - uint32_t a=0,b=0,c=0,d=0,y=0,z=0; - uint32_t sum = SUM; - uint8_t n = ROUNDS; + uint32_t a=0,b=0,c=0,d=0,y=0,z=0; + uint32_t sum = SUM; + uint8_t n = ROUNDS; - //key - a = bytes_to_num(key, 4); - b = bytes_to_num(key+4, 4); - c = bytes_to_num(key+8, 4); - d = bytes_to_num(key+12, 4); + //key + a = bytes_to_num(key, 4); + b = bytes_to_num(key+4, 4); + c = bytes_to_num(key+8, 4); + d = bytes_to_num(key+12, 4); - //input - y = bytes_to_num(v, 4); - z = bytes_to_num(v+4, 4); + //input + y = bytes_to_num(v, 4); + z = bytes_to_num(v+4, 4); - /* sum = delta<<5, in general sum = delta * n */ - while ( n-- > 0 ) { - z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d); - y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); - sum -= DELTA; - } - num_to_bytes(y, 4, v); - num_to_bytes(z, 4, v+4); + /* sum = delta<<5, in general sum = delta * n */ + while ( n-- > 0 ) { + z -= ((y << 4) + c) ^ (y + sum) ^ ((y >> 5) + d); + y -= ((z << 4) + a) ^ (z + sum) ^ ((z >> 5) + b); + sum -= DELTA; + } + num_to_bytes(y, 4, v); + num_to_bytes(z, 4, v+4); } diff --git a/common/usart.c b/common/usart.c index c62e3c8f6..9371e6243 100644 --- a/common/usart.c +++ b/common/usart.c @@ -11,19 +11,19 @@ #include "usart.h" #include "string.h" -#define AT91_BAUD_RATE 115200 +#define AT91_BAUD_RATE 115200 -volatile AT91PS_USART pUS1 = AT91C_BASE_US1; -volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; -volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_US1; +volatile AT91PS_USART pUS1 = AT91C_BASE_US1; +volatile AT91PS_PIO pPIO = AT91C_BASE_PIOA; +volatile AT91PS_PDC pPDC = AT91C_BASE_PDC_US1; /* void usart_close(void) { // Reset the USART mode - pUS1->US_MR = 0; + pUS1->US_MR = 0; // Reset the baud rate divisor register - pUS1->US_BRGR = 0; + pUS1->US_BRGR = 0; // Reset the Timeguard Register pUS1->US_TTGR = 0; @@ -32,7 +32,7 @@ void usart_close(void) { pUS1->US_IDR = 0xFFFFFFFF; // Abort the Peripheral Data Transfers - pUS1->US_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS; + pUS1->US_PTCR = AT91C_PDC_RXTDIS | AT91C_PDC_TXTDIS; // Disable receiver and transmitter and stop any activity immediately pUS1->US_CR = AT91C_US_TXDIS | AT91C_US_RXDIS | AT91C_US_RSTTX | AT91C_US_RSTRX; @@ -46,12 +46,12 @@ static uint8_t us_outbuf[sizeof(UsbCommand)]; /// \param len Size of the data buffer (in bytes). inline int16_t usart_readbuffer(uint8_t *data, size_t len) { - // Check if the first PDC bank is free + // Check if the first PDC bank is free if (!(pUS1->US_RCR)) { pUS1->US_RPR = (uint32_t)data; pUS1->US_RCR = len; - pUS1->US_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTDIS; + pUS1->US_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTDIS; return 2; } // Check if the second PDC bank is free @@ -59,7 +59,7 @@ inline int16_t usart_readbuffer(uint8_t *data, size_t len) { pUS1->US_RNPR = (uint32_t)data; pUS1->US_RNCR = len; - pUS1->US_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTDIS; + pUS1->US_PTCR = AT91C_PDC_RXTEN | AT91C_PDC_TXTDIS; return 1; } else { return 0; @@ -72,21 +72,21 @@ inline int16_t usart_writebuffer(uint8_t *data, size_t len) { // Check if the first PDC bank is free if (!(pUS1->US_TCR)) { - memcpy(us_outbuf, data, len); - pUS1->US_TPR = (uint32_t)us_outbuf; + memcpy(us_outbuf, data, len); + pUS1->US_TPR = (uint32_t)us_outbuf; pUS1->US_TCR = sizeof(us_outbuf); - pUS1->US_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTDIS; - return 2; + pUS1->US_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTDIS; + return 2; } // Check if the second PDC bank is free else if (!(pUS1->US_TNCR)) { - memcpy(us_outbuf, data, len); + memcpy(us_outbuf, data, len); pUS1->US_TNPR = (uint32_t)us_outbuf; pUS1->US_TNCR = sizeof(us_outbuf); - pUS1->US_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTDIS; - return 1; + pUS1->US_PTCR = AT91C_PDC_TXTEN | AT91C_PDC_RXTDIS; + return 1; } else { return 0; } @@ -94,21 +94,21 @@ inline int16_t usart_writebuffer(uint8_t *data, size_t len) { void usart_init(void) { - // disable & reset receiver / transmitter for configuration - pUS1->US_CR = (AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS); + // disable & reset receiver / transmitter for configuration + pUS1->US_CR = (AT91C_US_RSTRX | AT91C_US_RSTTX | AT91C_US_RXDIS | AT91C_US_TXDIS); - //enable the USART1 Peripheral clock - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US1); + //enable the USART1 Peripheral clock + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_US1); - // disable PIO control of receive / transmit pins - pPIO->PIO_PDR |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); + // disable PIO control of receive / transmit pins + pPIO->PIO_PDR |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); - // enable peripheral mode A on receive / transmit pins - pPIO->PIO_ASR |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); - pPIO->PIO_BSR = 0; + // enable peripheral mode A on receive / transmit pins + pPIO->PIO_ASR |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); + pPIO->PIO_BSR = 0; - // enable pull-up on receive / transmit pins (see 31.5.1 I/O Lines) - pPIO->PIO_PPUER |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); + // enable pull-up on receive / transmit pins (see 31.5.1 I/O Lines) + pPIO->PIO_PPUER |= (AT91C_PA21_RXD1 | AT91C_PA22_TXD1); // set mode pUS1->US_MR = AT91C_US_USMODE_NORMAL | // normal mode @@ -118,26 +118,26 @@ void usart_init(void) { AT91C_US_NBSTOP_1_BIT | // 1 stop bit AT91C_US_CHMODE_NORMAL; // channel mode: normal - // all interrupts disabled - pUS1->US_IDR = 0xFFFF; + // all interrupts disabled + pUS1->US_IDR = 0xFFFF; - // iceman, setting 115200 doesn't work. Only speed I got to work is 9600. - // something fishy with the AT91SAM7S512 USART.. Or I missed something - // For a nice detailed sample, interrupt driven but still relevant. - // See https://www.sparkfun.com/datasheets/DevTools/SAM7/at91sam7%20serial%20communications.pdf + // iceman, setting 115200 doesn't work. Only speed I got to work is 9600. + // something fishy with the AT91SAM7S512 USART.. Or I missed something + // For a nice detailed sample, interrupt driven but still relevant. + // See https://www.sparkfun.com/datasheets/DevTools/SAM7/at91sam7%20serial%20communications.pdf - // set baudrate to 115200 - // 115200 * 16 == 1843200 - // - //pUS1->US_BRGR = (48UL*1000*1000) / (9600*16); - pUS1->US_BRGR = 48054841 / (9600 << 4); + // set baudrate to 115200 + // 115200 * 16 == 1843200 + // + //pUS1->US_BRGR = (48UL*1000*1000) / (9600*16); + pUS1->US_BRGR = 48054841 / (9600 << 4); - // Write the Timeguard Register - pUS1->US_TTGR = 0; - pUS1->US_RTOR = 0; - pUS1->US_FIDI = 0; - pUS1->US_IF = 0; + // Write the Timeguard Register + pUS1->US_TTGR = 0; + pUS1->US_RTOR = 0; + pUS1->US_FIDI = 0; + pUS1->US_IF = 0; - // re-enable receiver / transmitter - pUS1->US_CR = (AT91C_US_RXEN | AT91C_US_TXEN); + // re-enable receiver / transmitter + pUS1->US_CR = (AT91C_US_RXEN | AT91C_US_TXEN); } \ No newline at end of file diff --git a/common/usb_cdc.c b/common/usb_cdc.c index b1acff692..b60ec8176 100644 --- a/common/usb_cdc.c +++ b/common/usb_cdc.c @@ -64,21 +64,21 @@ AT91SAM7S256 USB Device Port #define USB_DESCRIPTOR_OTHER_SPEED 0x07 // DescriptorType for a Other Speed Configuration. #define USB_DESCRIPTOR_INTERFACE_POWER 0x08 // DescriptorType for Interface Power. #define USB_DESCRIPTOR_OTG 0x09 // DescriptorType for an OTG Descriptor. -#define USB_DESCRIPTOR_IAD 0x0B // DescriptorType for a Interface Association Descriptor +#define USB_DESCRIPTOR_IAD 0x0B // DescriptorType for a Interface Association Descriptor #define USB_DESCRIPTOR_TYPE_BO 0x0F // DescriptorType for a BOS Descriptor. /* Configuration Attributes */ #define _DEFAULT (0x01<<7) //Default Value (Bit 7 is set) #define _SELF (0x01<<6) //Self-powered (Supports if set) #define _RWU (0x01<<5) //Remote Wakeup (Supports if set) -#define _HNP (0x01 << 1) //HNP (Supports if set) -#define _SRP (0x01) //SRP (Supports if set) +#define _HNP (0x01 << 1) //HNP (Supports if set) +#define _SRP (0x01) //SRP (Supports if set) /* Endpoint Transfer Type */ #define _CTRL 0x00 //Control Transfer #define _ISO 0x01 //Isochronous Transfer -#define _BULK 0x02 //Bulk Transfer -#define _INTERRUPT 0x03 //Interrupt Transfer +#define _BULK 0x02 //Bulk Transfer +#define _INTERRUPT 0x03 //Interrupt Transfer // (bit7 | 0 = OUT, 1 = IN) #define _EP_IN 0x80 @@ -92,12 +92,12 @@ AT91SAM7S256 USB Device Port /* WCID specific Request Code */ -#define MS_OS_DESCRIPTOR_INDEX 0xEE -#define MS_VENDOR_CODE 0x1C +#define MS_OS_DESCRIPTOR_INDEX 0xEE +#define MS_VENDOR_CODE 0x1C #define MS_EXTENDED_COMPAT_ID 0x04 #define MS_EXTENDED_PROPERTIES 0x05 -#define MS_WCID_GET_DESCRIPTOR 0xC0 -#define MS_WCID_GET_FEATURE_DESCRIPTOR 0xC1 +#define MS_WCID_GET_DESCRIPTOR 0xC0 +#define MS_WCID_GET_FEATURE_DESCRIPTOR 0xC1 /* USB standard request code */ #define STD_GET_STATUS_ZERO 0x0080 @@ -132,275 +132,275 @@ uint8_t btConnection = 0; uint8_t btReceiveBank = AT91C_UDP_RX_DATA_BK0; static const char devDescriptor[] = { - /* Device descriptor */ - 0x12, // Length - USB_DESCRIPTOR_DEVICE, // Descriptor Type (DEVICE) - 0x00,0x02, // Complies with USB Spec. Release (0200h = release 2.00) 0210 == release 2.10 - 2, // Device Class: Communication Device Class - 0, // Device Subclass: CDC class sub code ACM [ice 0x02 = win10 virtual comport ] - 0, // Device Protocol: CDC Device protocol (unused) - AT91C_EP_CONTROL_SIZE, // MaxPacketSize0 + /* Device descriptor */ + 0x12, // Length + USB_DESCRIPTOR_DEVICE, // Descriptor Type (DEVICE) + 0x00,0x02, // Complies with USB Spec. Release (0200h = release 2.00) 0210 == release 2.10 + 2, // Device Class: Communication Device Class + 0, // Device Subclass: CDC class sub code ACM [ice 0x02 = win10 virtual comport ] + 0, // Device Protocol: CDC Device protocol (unused) + AT91C_EP_CONTROL_SIZE, // MaxPacketSize0 0xc4,0x9a, // Vendor ID [0x9ac4 = J. Westhues] 0x8f,0x4b, // Product ID [0x4b8f = Proxmark-3 RFID Instrument] - 0x00,0x01, // BCD Device release number (1.00) - 1, // index Manufacturer - 2, // index Product - 3, // index SerialNumber - 1 // Number of Configs + 0x00,0x01, // BCD Device release number (1.00) + 1, // index Manufacturer + 2, // index Product + 3, // index SerialNumber + 1 // Number of Configs }; static const char cfgDescriptor[] = { - /* Configuration 1 descriptor */ - // ----------------------------- - 9, // Length - USB_DESCRIPTOR_CONFIGURATION, // Descriptor Type - (9+9+5+5+4+5+7+9+7+7), 0, // Total Length 2 EP + Control - 2, // Number of Interfaces - 1, // Index value of this Configuration (used in SetConfiguration from Host) - 0, // Configuration string index - _DEFAULT, // Attributes 0xA0 - 0xFA, // Max Power consumption + /* Configuration 1 descriptor */ + // ----------------------------- + 9, // Length + USB_DESCRIPTOR_CONFIGURATION, // Descriptor Type + (9+9+5+5+4+5+7+9+7+7), 0, // Total Length 2 EP + Control + 2, // Number of Interfaces + 1, // Index value of this Configuration (used in SetConfiguration from Host) + 0, // Configuration string index + _DEFAULT, // Attributes 0xA0 + 0xFA, // Max Power consumption - // IAD to associate the one CDC interface + // IAD to associate the one CDC interface // -------------------------------------- /* - 8, // Length - USB_DESCRIPTOR_IAD, // IAD_DESCRIPTOR (0x0B) - 0, // CDC_INT_INTERFACE NUMBER ( - 2, // IAD INTERFACE COUNT (two interfaces) - 2, // Function Class: CDC_CLASS - 2, // Function SubClass: ACM - 1, // Function Protocol: v.25term - 0, // iInterface + 8, // Length + USB_DESCRIPTOR_IAD, // IAD_DESCRIPTOR (0x0B) + 0, // CDC_INT_INTERFACE NUMBER ( + 2, // IAD INTERFACE COUNT (two interfaces) + 2, // Function Class: CDC_CLASS + 2, // Function SubClass: ACM + 1, // Function Protocol: v.25term + 0, // iInterface */ - /* Interface 0 Descriptor */ - /* CDC Communication Class Interface Descriptor Requirement for Notification*/ - // ----------------------------------------------------------- - 9, // Length - USB_DESCRIPTOR_INTERFACE, // Descriptor Type - 0, // Interface Number - 0, // Alternate Setting - 1, // Number of Endpoints in this interface - 2, // Interface Class code (Communication Interface Class) - 2, // Interface Subclass code (Abstract Control Model) - 1, // InterfaceProtocol (Common AT Commands, V.25term) - 0, // iInterface + /* Interface 0 Descriptor */ + /* CDC Communication Class Interface Descriptor Requirement for Notification*/ + // ----------------------------------------------------------- + 9, // Length + USB_DESCRIPTOR_INTERFACE, // Descriptor Type + 0, // Interface Number + 0, // Alternate Setting + 1, // Number of Endpoints in this interface + 2, // Interface Class code (Communication Interface Class) + 2, // Interface Subclass code (Abstract Control Model) + 1, // InterfaceProtocol (Common AT Commands, V.25term) + 0, // iInterface - /* Header Functional Descriptor */ - 5, // Function Length - 0x24, // Descriptor type: CS_INTERFACE - 0, // Descriptor subtype: Header Functional Descriptor - 0x10,0x01, // bcd CDC:1.1 + /* Header Functional Descriptor */ + 5, // Function Length + 0x24, // Descriptor type: CS_INTERFACE + 0, // Descriptor subtype: Header Functional Descriptor + 0x10,0x01, // bcd CDC:1.1 - /* ACM Functional Descriptor */ - 4, // Function Length - 0x24, // Descriptor Type: CS_INTERFACE - 2, // Descriptor Subtype: Abstract Control Management Functional Descriptor - 2, // Capabilities D1, Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State + /* ACM Functional Descriptor */ + 4, // Function Length + 0x24, // Descriptor Type: CS_INTERFACE + 2, // Descriptor Subtype: Abstract Control Management Functional Descriptor + 2, // Capabilities D1, Device supports the request combination of Set_Line_Coding, Set_Control_Line_State, Get_Line_Coding, and the notification Serial_State - /* Union Functional Descriptor */ - 5, // Function Length - 0x24, // Descriptor Type: CS_INTERFACE - 6, // Descriptor Subtype: Union Functional Descriptor - 0, // MasterInterface: Communication Class Interface - 1, // SlaveInterface0: Data Class Interface + /* Union Functional Descriptor */ + 5, // Function Length + 0x24, // Descriptor Type: CS_INTERFACE + 6, // Descriptor Subtype: Union Functional Descriptor + 0, // MasterInterface: Communication Class Interface + 1, // SlaveInterface0: Data Class Interface - /* Call Management Functional Descriptor */ - 5, // Function Length - 0x24, // Descriptor Type: CS_INTERFACE - 1, // Descriptor Subtype: Call Management Functional Descriptor - 0, // Capabilities: Device sends/receives call management information only over the Communication Class interface. Device does not handle call management itself - 1, // Data Interface: Data Class Interface + /* Call Management Functional Descriptor */ + 5, // Function Length + 0x24, // Descriptor Type: CS_INTERFACE + 1, // Descriptor Subtype: Call Management Functional Descriptor + 0, // Capabilities: Device sends/receives call management information only over the Communication Class interface. Device does not handle call management itself + 1, // Data Interface: Data Class Interface - /* Protocol Functional Descriptor */ - /* - 6, - 0x24, // Descriptor Type: CS_INTERFACE - 0x0B, // Descriptor Subtype: Protocol Unit functional Descriptor - 0xDD, // constant uniq ID of unit - 0xFE, // protocol - */ + /* Protocol Functional Descriptor */ + /* + 6, + 0x24, // Descriptor Type: CS_INTERFACE + 0x0B, // Descriptor Subtype: Protocol Unit functional Descriptor + 0xDD, // constant uniq ID of unit + 0xFE, // protocol + */ - /* CDC Notification Endpoint descriptor */ - // --------------------------------------- - 7, // Length - USB_DESCRIPTOR_ENDPOINT, // Descriptor Type - _EP03_IN, // EndpointAddress: Endpoint 03 - IN - _INTERRUPT, // Attributes - AT91C_EP_CONTROL_SIZE, 0x00, // MaxPacket Size: EP0 - 8 - 0xFF, // Interval polling + /* CDC Notification Endpoint descriptor */ + // --------------------------------------- + 7, // Length + USB_DESCRIPTOR_ENDPOINT, // Descriptor Type + _EP03_IN, // EndpointAddress: Endpoint 03 - IN + _INTERRUPT, // Attributes + AT91C_EP_CONTROL_SIZE, 0x00, // MaxPacket Size: EP0 - 8 + 0xFF, // Interval polling - /* Interface 1 Descriptor */ - /* CDC Data Class Interface 1 Descriptor Requirement */ - 9, // Length - USB_DESCRIPTOR_INTERFACE, // Descriptor Type - 1, // Interface Number - 0, // Alternate Setting - 2, // Number of Endpoints - 0x0A, // Interface Class: CDC Data interface class - 0, // Interface Subclass: not used - 0, // Interface Protocol: No class specific protocol required (usb spec) - 0, // Interface + /* Interface 1 Descriptor */ + /* CDC Data Class Interface 1 Descriptor Requirement */ + 9, // Length + USB_DESCRIPTOR_INTERFACE, // Descriptor Type + 1, // Interface Number + 0, // Alternate Setting + 2, // Number of Endpoints + 0x0A, // Interface Class: CDC Data interface class + 0, // Interface Subclass: not used + 0, // Interface Protocol: No class specific protocol required (usb spec) + 0, // Interface - /* Endpoint descriptor */ - 7, // Length - USB_DESCRIPTOR_ENDPOINT, // Descriptor Type - _EP01_OUT, // Endpoint Address: Endpoint 01 - OUT - _BULK, // Attributes: BULK - AT91C_EP_OUT_SIZE, 0x00, // MaxPacket Size: 64 bytes - 0, // Interval: ignored for bulk + /* Endpoint descriptor */ + 7, // Length + USB_DESCRIPTOR_ENDPOINT, // Descriptor Type + _EP01_OUT, // Endpoint Address: Endpoint 01 - OUT + _BULK, // Attributes: BULK + AT91C_EP_OUT_SIZE, 0x00, // MaxPacket Size: 64 bytes + 0, // Interval: ignored for bulk - /* Endpoint descriptor */ - 7, // Length - USB_DESCRIPTOR_ENDPOINT, // Descriptor Type - _EP02_IN, // Endpoint Address: Endpoint 02 - IN - _BULK, // Attribute: BULK - AT91C_EP_IN_SIZE, 0x00, // MaxPacket Size: 64 bytes - 0 // Interval: ignored for bulk + /* Endpoint descriptor */ + 7, // Length + USB_DESCRIPTOR_ENDPOINT, // Descriptor Type + _EP02_IN, // Endpoint Address: Endpoint 02 - IN + _BULK, // Attribute: BULK + AT91C_EP_IN_SIZE, 0x00, // MaxPacket Size: 64 bytes + 0 // Interval: ignored for bulk }; // BOS descriptor static const char bosDescriptor[] = { - 0x5, - USB_DESCRIPTOR_TYPE_BO, - 0xC, - 0x0, - 0x1, // 1 device capability - 0x7, - 0x10, //USB_DEVICE_CAPABITY_TYPE, - 0x2, - 0x2, // LPM capability bit set - 0x0, - 0x0, - 0x0 + 0x5, + USB_DESCRIPTOR_TYPE_BO, + 0xC, + 0x0, + 0x1, // 1 device capability + 0x7, + 0x10, // USB_DEVICE_CAPABITY_TYPE, + 0x2, + 0x2, // LPM capability bit set + 0x0, + 0x0, + 0x0 }; // Microsoft OS Extended Configuration Compatible ID Descriptor /* static const char CompatIDFeatureDescriptor[] = { - 0x28, 0x00, 0x00, 0x00, // Descriptor Length 40bytes (0x28) - 0x00, 0x01, // Version ('1.0') - MS_EXTENDED_COMPAT_ID, 0x00, // Compatibility ID Descriptor Index 0x0004 - 0x01, // Number of sections. 0x1 - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved (7bytes) - //-----function section 1------ - 0x00, // Interface Number #0 - 0x01, // reserved (0x1) - 0x57, 0x49, 0x4E, 0x55, 0x53, 0x42, 0x00, 0x00, // Compatible ID ('WINUSB\0\0') (8bytes) - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sub-Compatible ID (8byte) - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Reserved (6bytes) + 0x28, 0x00, 0x00, 0x00, // Descriptor Length 40bytes (0x28) + 0x00, 0x01, // Version ('1.0') + MS_EXTENDED_COMPAT_ID, 0x00, // Compatibility ID Descriptor Index 0x0004 + 0x01, // Number of sections. 0x1 + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Reserved (7bytes) + //-----function section 1------ + 0x00, // Interface Number #0 + 0x01, // reserved (0x1) + 0x57, 0x49, 0x4E, 0x55, 0x53, 0x42, 0x00, 0x00, // Compatible ID ('WINUSB\0\0') (8bytes) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, // Sub-Compatible ID (8byte) + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 // Reserved (6bytes) }; */ // Microsoft Extended Properties Feature Descriptor /* static const char OSprop[] = { - // u32 Descriptor Length (10+132+64+102 == 308 - 0x34, 0x01, 0, 0, - // u16 Version ('1.0') - 0, 1, - // u16 wIndex - MS_EXTENDED_PROPERTIES, 0, - // u16 wCount -- three section - 3, 0, + // u32 Descriptor Length (10+132+64+102 == 308 + 0x34, 0x01, 0, 0, + // u16 Version ('1.0') + 0, 1, + // u16 wIndex + MS_EXTENDED_PROPERTIES, 0, + // u16 wCount -- three section + 3, 0, - //-----property section 1------ - // u32 size ( 14+40+78 == 132) - 132, 0, 0, 0, - // u32 type - 1, 0, 0, 0, // unicode string - // u16 namelen (20*2 = 40) - 40, 0, - // name DeviceInterfaceGUID - 'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,'I',0,'n',0,'t',0,'e',0,'r',0,'f',0,'a',0,'c',0,'e',0,'G',0,'U',0,'I',0,'D',0,0,0, - // u32 datalen (39*2 = 78) - 78, 0, 0, 0, - // data {4D36E978-E325-11CE-BFC1-08002BE10318} - '{',0,'4',0,'d',0,'3',0,'6',0,'e',0,'9',0,'7',0,'8',0,'-',0,'e',0,'3',0,'2',0,'5',0, - '-',0,'1',0,'1',0,'c',0,'e',0,'-',0,'b',0,'f',0,'c',0,'1',0,'-',0,'0',0,'8',0,'0',0, - '0',0,'2',0,'b',0,'e',0,'1',0,'0',0,'3',0,'1',0,'8',0,'}',0,0,0, + //-----property section 1------ + // u32 size ( 14+40+78 == 132) + 132, 0, 0, 0, + // u32 type + 1, 0, 0, 0, // unicode string + // u16 namelen (20*2 = 40) + 40, 0, + // name DeviceInterfaceGUID + 'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,'I',0,'n',0,'t',0,'e',0,'r',0,'f',0,'a',0,'c',0,'e',0,'G',0,'U',0,'I',0,'D',0,0,0, + // u32 datalen (39*2 = 78) + 78, 0, 0, 0, + // data {4D36E978-E325-11CE-BFC1-08002BE10318} + '{',0,'4',0,'d',0,'3',0,'6',0,'e',0,'9',0,'7',0,'8',0,'-',0,'e',0,'3',0,'2',0,'5',0, + '-',0,'1',0,'1',0,'c',0,'e',0,'-',0,'b',0,'f',0,'c',0,'1',0,'-',0,'0',0,'8',0,'0',0, + '0',0,'2',0,'b',0,'e',0,'1',0,'0',0,'3',0,'1',0,'8',0,'}',0,0,0, - //-----property section 2------ - // u32 size ( 14+12+38 == 64) - 64, 0, 0, 0, - // u32 type - 1, 0, 0, 0, // unicode string - // u16 namelen (12) - 12, 0, - // name Label - 'L',0,'a',0,'b',0,'e',0,'l',0,0,0, - // u32 datalen ( 19*2 = 38 ) - 38, 0, 0, 0, - // data 'Awesome PM3 Device' - 'A',0,'w',0,'e',0,'s',0,'o',0,'m',0,'e',0,' ',0,'P',0,'M',0,'3',0,' ',0,'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,0,0, + //-----property section 2------ + // u32 size ( 14+12+38 == 64) + 64, 0, 0, 0, + // u32 type + 1, 0, 0, 0, // unicode string + // u16 namelen (12) + 12, 0, + // name Label + 'L',0,'a',0,'b',0,'e',0,'l',0,0,0, + // u32 datalen ( 19*2 = 38 ) + 38, 0, 0, 0, + // data 'Awesome PM3 Device' + 'A',0,'w',0,'e',0,'s',0,'o',0,'m',0,'e',0,' ',0,'P',0,'M',0,'3',0,' ',0,'D',0,'e',0,'v',0,'i',0,'c',0,'e',0,0,0, - //-----property section 3------ - // u32 size ( 14+12+76 == 102) - 102, 0, 0, 0, - // u32 type - 2, 0, 0, 0, //Unicode string with environment variables - // u16 namelen (12) - 12, 0, - // name Icons - 'I',0,'c',0,'o',0,'n',0,'s',0,0,0, - // u32 datalen ( 38*2 == 76) - 76, 0, 0, 0, - // data '%SystemRoot%\\system32\\Shell32.dll,-13' - '%',0,'S',0,'y',0,'s',0,'t',0,'e',0,'m',0,'R',0,'o',0,'o',0,'t',0,'%',0, - '\\',0,'s',0,'y',0,'s',0,'t',0,'e',0,'m',0,'3',0,'2',0,'\\',0, - 'S',0,'h',0,'e',0,'l',0,'l',0,'3',0,'2',0,'.',0,'d',0,'l',0,'l',0,',',0, - '-',0,'1',0,'3',0,0,0 + //-----property section 3------ + // u32 size ( 14+12+76 == 102) + 102, 0, 0, 0, + // u32 type + 2, 0, 0, 0, //Unicode string with environment variables + // u16 namelen (12) + 12, 0, + // name Icons + 'I',0,'c',0,'o',0,'n',0,'s',0,0,0, + // u32 datalen ( 38*2 == 76) + 76, 0, 0, 0, + // data '%SystemRoot%\\system32\\Shell32.dll,-13' + '%',0,'S',0,'y',0,'s',0,'t',0,'e',0,'m',0,'R',0,'o',0,'o',0,'t',0,'%',0, + '\\',0,'s',0,'y',0,'s',0,'t',0,'e',0,'m',0,'3',0,'2',0,'\\',0, + 'S',0,'h',0,'e',0,'l',0,'l',0,'3',0,'2',0,'.',0,'d',0,'l',0,'l',0,',',0, + '-',0,'1',0,'3',0,0,0 }; */ static const char StrLanguageCodes[] = { - 4, // Length - 0x03, // Type is string - 0x09, 0x04 // supported language Code 0 = 0x0409 (English) + 4, // Length + 0x03, // Type is string + 0x09, 0x04 // supported language Code 0 = 0x0409 (English) }; // Note: ModemManager (Linux) ignores Proxmark3 devices by matching the // manufacturer string "proxmark.org". Don't change this. // or use the blacklisting file. static const char StrManufacturer[] = { - 26, // Length - 0x03, // Type is string - 'p',0,'r',0,'o',0,'x',0,'m',0,'a',0,'r',0,'k',0,'.',0,'o',0,'r',0,'g',0, + 26, // Length + 0x03, // Type is string + 'p',0,'r',0,'o',0,'x',0,'m',0,'a',0,'r',0,'k',0,'.',0,'o',0,'r',0,'g',0, }; static const char StrProduct[] = { - 20, // Length - 0x03, // Type is string - 'p',0,'r',0,'o',0,'x',0,'m',0,'a',0,'r',0,'k',0,'3',0 + 20, // Length + 0x03, // Type is string + 'p',0,'r',0,'o',0,'x',0,'m',0,'a',0,'r',0,'k',0,'3',0 }; static const char StrSerialNumber[] = { - 14, // Length - 0x03, // Type is string - 'i',0,'c',0,'e',0,'m',0,'a',0,'n',0 + 14, // Length + 0x03, // Type is string + 'i',0,'c',0,'e',0,'m',0,'a',0,'n',0 }; // size includes their own field. static const char StrMS_OSDescriptor[] = { - 18, // length 0x12 - 0x03, // Type is string + 18, // length 0x12 + 0x03, // Type is string 'M',0,'S',0,'F',0,'T',0,'1',0,'0',0,'0',0,MS_VENDOR_CODE,0 }; const char* getStringDescriptor(uint8_t idx) { - switch(idx) { - case 0: return StrLanguageCodes; - case 1: return StrManufacturer; - case 2: return StrProduct; - case 3: return StrSerialNumber; - case MS_OS_DESCRIPTOR_INDEX: return StrMS_OSDescriptor; - default: - return(NULL); - } + switch(idx) { + case 0: return StrLanguageCodes; + case 1: return StrManufacturer; + case 2: return StrProduct; + case 3: return StrSerialNumber; + case MS_OS_DESCRIPTOR_INDEX: return StrMS_OSDescriptor; + default: + return(NULL); + } } // Bitmap for all status bits in CSR which must be written as 1 to cause no effect @@ -410,57 +410,57 @@ const char* getStringDescriptor(uint8_t idx) { // Clear flags in the UDP_CSR register and waits for synchronization #define UDP_CLEAR_EP_FLAGS(endpoint, flags) { \ - volatile unsigned int reg; \ - reg = pUdp->UDP_CSR[(endpoint)]; \ - reg |= REG_NO_EFFECT_1_ALL; \ - reg &= ~(flags); \ - pUdp->UDP_CSR[(endpoint)] = reg; \ + volatile unsigned int reg; \ + reg = pUdp->UDP_CSR[(endpoint)]; \ + reg |= REG_NO_EFFECT_1_ALL; \ + reg &= ~(flags); \ + pUdp->UDP_CSR[(endpoint)] = reg; \ } \ // reset flags in the UDP_CSR register and waits for synchronization #define UDP_SET_EP_FLAGS(endpoint, flags) { \ - volatile unsigned int reg; \ - reg = pUdp->UDP_CSR[(endpoint)]; \ - reg |= REG_NO_EFFECT_1_ALL; \ - reg |= (flags); \ - pUdp->UDP_CSR[(endpoint)] = reg; \ + volatile unsigned int reg; \ + reg = pUdp->UDP_CSR[(endpoint)]; \ + reg |= REG_NO_EFFECT_1_ALL; \ + reg |= (flags); \ + pUdp->UDP_CSR[(endpoint)] = reg; \ } \ typedef struct { - uint32_t BitRate; - uint8_t Format; - uint8_t ParityType; - uint8_t DataBits; + uint32_t BitRate; + uint8_t Format; + uint8_t ParityType; + uint8_t DataBits; } AT91S_CDC_LINE_CODING, *AT91PS_CDC_LINE_CODING; AT91S_CDC_LINE_CODING line = { - 115200, // baudrate - 0, // 1 Stop Bit - 0, // None Parity - 8}; // 8 Data bits + 115200, // baudrate + 0, // 1 Stop Bit + 0, // None Parity + 8}; // 8 Data bits static void SpinDelay(int ms) { - int us = ms * 1000; - int ticks = (48 * us) >> 10; + int us = ms * 1000; + int ticks = (48 * us) >> 10; - // Borrow a PWM unit for my real-time clock - AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0); + // Borrow a PWM unit for my real-time clock + AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0); - // 48 MHz / 1024 gives 46.875 kHz - AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); - AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; - AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; + // 48 MHz / 1024 gives 46.875 kHz + AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); + AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; + AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; - uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; + uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; - for(;;) { - uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; - if (now == (uint16_t)(start + ticks)) - return; + for(;;) { + uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; + if (now == (uint16_t)(start + ticks)) + return; - WDT_HIT(); - } + WDT_HIT(); + } } //*---------------------------------------------------------------------------- @@ -468,13 +468,13 @@ static void SpinDelay(int ms) { //* \brief This function deactivates the USB device //*---------------------------------------------------------------------------- void usb_disable() { - // Disconnect the USB device - AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU; + // Disconnect the USB device + AT91C_BASE_PIOA->PIO_ODR = GPIO_USB_PU; - // Clear all lingering interrupts - if (pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES) { - pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES; - } + // Clear all lingering interrupts + if (pUdp->UDP_ISR & AT91C_UDP_ENDBUSRES) { + pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES; + } } //*---------------------------------------------------------------------------- @@ -482,35 +482,35 @@ void usb_disable() { //* \brief This function Activates the USB device //*---------------------------------------------------------------------------- void usb_enable() { - // Set the PLL USB Divider - AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ; + // Set the PLL USB Divider + AT91C_BASE_CKGR->CKGR_PLLR |= AT91C_CKGR_USBDIV_1 ; - // Specific Chip USB Initialisation - // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock - AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_UDP; - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP); + // Specific Chip USB Initialisation + // Enables the 48MHz USB clock UDPCK and System Peripheral USB Clock + AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_UDP; + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_UDP); - AT91C_BASE_UDP->UDP_FADDR = 0; - AT91C_BASE_UDP->UDP_GLBSTATE = 0; + AT91C_BASE_UDP->UDP_FADDR = 0; + AT91C_BASE_UDP->UDP_GLBSTATE = 0; - // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO - // Set in PIO mode and Configure in Output - AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode - AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output + // Enable UDP PullUp (USB_DP_PUP) : enable & Clear of the corresponding PIO + // Set in PIO mode and Configure in Output + AT91C_BASE_PIOA->PIO_PER = GPIO_USB_PU; // Set in PIO mode + AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; // Configure as Output - // Clear for set the Pullup resistor - AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU; + // Clear for set the Pullup resistor + AT91C_BASE_PIOA->PIO_CODR = GPIO_USB_PU; - // Disconnect and reconnect USB controller for 100ms - usb_disable(); + // Disconnect and reconnect USB controller for 100ms + usb_disable(); - SpinDelay(100); - // Wait for a short while - //for (volatile size_t i=0; i<0x100000; i++) {}; + SpinDelay(100); + // Wait for a short while + //for (volatile size_t i=0; i<0x100000; i++) {}; - // Reconnect USB reconnect - AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU; - AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; + // Reconnect USB reconnect + AT91C_BASE_PIOA->PIO_SODR = GPIO_USB_PU; + AT91C_BASE_PIOA->PIO_OER = GPIO_USB_PU; } //*---------------------------------------------------------------------------- @@ -520,87 +520,87 @@ void usb_enable() { static int usb_reconnect = 0; static int usb_configured = 0; void SetUSBreconnect(int value) { - usb_reconnect = value; + usb_reconnect = value; } int GetUSBreconnect(void) { - return usb_reconnect; + return usb_reconnect; } void SetUSBconfigured(int value) { - usb_configured = value; + usb_configured = value; } int GetUSBconfigured(void){ - return usb_configured; + return usb_configured; } bool usb_check() { - /* - // reconnected ONCE and - if ( !USB_ATTACHED() ){ - usb_reconnect = 1; - return false; - } + /* + // reconnected ONCE and + if ( !USB_ATTACHED() ){ + usb_reconnect = 1; + return false; + } - // only one time after USB been disengaged and re-engaged - if ( USB_ATTACHED() && usb_reconnect == 1 ) { + // only one time after USB been disengaged and re-engaged + if ( USB_ATTACHED() && usb_reconnect == 1 ) { - if ( usb_configured == 0) { - usb_disable(); - usb_enable(); + if ( usb_configured == 0) { + usb_disable(); + usb_enable(); - AT91F_CDC_Enumerate(); + AT91F_CDC_Enumerate(); - usb_configured = 1; - return false; - } - } - */ + usb_configured = 1; + return false; + } + } + */ - // interrupt status register - AT91_REG isr = pUdp->UDP_ISR; + // interrupt status register + AT91_REG isr = pUdp->UDP_ISR; - // end of bus reset - if (isr & AT91C_UDP_ENDBUSRES) { - pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES; - // reset all endpoints - pUdp->UDP_RSTEP = (unsigned int)-1; - pUdp->UDP_RSTEP = 0; - // Enable the function - pUdp->UDP_FADDR = AT91C_UDP_FEN; - // Configure endpoint 0 (enable control endpoint) - pUdp->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL); - } - else if (isr & AT91C_UDP_EPINT0) { - pUdp->UDP_ICR = AT91C_UDP_EPINT0; - AT91F_CDC_Enumerate(); - } - /* - else if (isr & AT91C_UDP_EPINT3 ) { - pUdp->UDP_ICR = AT91C_UDP_EPINT3; - AT91F_CDC_Enumerate(); - //pUdp->UDP_ICR |= AT91C_UDP_EPINT3; - } - */ - return (btConfiguration) ? true : false; + // end of bus reset + if (isr & AT91C_UDP_ENDBUSRES) { + pUdp->UDP_ICR = AT91C_UDP_ENDBUSRES; + // reset all endpoints + pUdp->UDP_RSTEP = (unsigned int)-1; + pUdp->UDP_RSTEP = 0; + // Enable the function + pUdp->UDP_FADDR = AT91C_UDP_FEN; + // Configure endpoint 0 (enable control endpoint) + pUdp->UDP_CSR[AT91C_EP_CONTROL] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_CTRL); + } + else if (isr & AT91C_UDP_EPINT0) { + pUdp->UDP_ICR = AT91C_UDP_EPINT0; + AT91F_CDC_Enumerate(); + } + /* + else if (isr & AT91C_UDP_EPINT3 ) { + pUdp->UDP_ICR = AT91C_UDP_EPINT3; + AT91F_CDC_Enumerate(); + //pUdp->UDP_ICR |= AT91C_UDP_EPINT3; + } + */ + return (btConfiguration) ? true : false; } bool usb_poll() { - if (!usb_check()) return false; - return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank); + if (!usb_check()) return false; + return (pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank); } /** - In github PR #129, some users appears to get a false positive from - usb_poll, which returns true, but the usb_read operation - still returns 0. - This check is basically the same as above, but also checks - that the length available to read is non-zero, thus hopefully fixes the - bug. + In github PR #129, some users appears to get a false positive from + usb_poll, which returns true, but the usb_read operation + still returns 0. + This check is basically the same as above, but also checks + that the length available to read is non-zero, thus hopefully fixes the + bug. **/ bool usb_poll_validate_length() { - if (!usb_check()) return false; - if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false; - return ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) > 0; + if (!usb_check()) return false; + if (!(pUdp->UDP_CSR[AT91C_EP_OUT] & btReceiveBank)) return false; + return ((pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16) > 0; } //*---------------------------------------------------------------------------- @@ -609,36 +609,36 @@ bool usb_poll_validate_length() { //*---------------------------------------------------------------------------- uint32_t usb_read(byte_t* data, size_t len) { - if ( len == 0 ) return 0; + if ( len == 0 ) return 0; - uint8_t bank = btReceiveBank; - uint32_t packetSize, nbBytesRcv = 0; - uint32_t time_out = 0; + uint8_t bank = btReceiveBank; + uint32_t packetSize, nbBytesRcv = 0; + uint32_t time_out = 0; - while (len) { - if (!usb_check()) break; + while (len) { + if (!usb_check()) break; - if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) { + if ( pUdp->UDP_CSR[AT91C_EP_OUT] & bank ) { - packetSize = (pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16; - packetSize = MIN( packetSize, len); - len -= packetSize; - while (packetSize--) - data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT]; + packetSize = (pUdp->UDP_CSR[AT91C_EP_OUT] & AT91C_UDP_RXBYTECNT) >> 16; + packetSize = MIN( packetSize, len); + len -= packetSize; + while (packetSize--) + data[nbBytesRcv++] = pUdp->UDP_FDR[AT91C_EP_OUT]; - // flip bank - UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank) + // flip bank + UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT, bank) - if (bank == AT91C_UDP_RX_DATA_BK0) - bank = AT91C_UDP_RX_DATA_BK1; - else - bank = AT91C_UDP_RX_DATA_BK0; - } - if (time_out++ == 0x1fff) break; - } + if (bank == AT91C_UDP_RX_DATA_BK0) + bank = AT91C_UDP_RX_DATA_BK1; + else + bank = AT91C_UDP_RX_DATA_BK0; + } + if (time_out++ == 0x1fff) break; + } - btReceiveBank = bank; - return nbBytesRcv; + btReceiveBank = bank; + return nbBytesRcv; } //*---------------------------------------------------------------------------- @@ -647,54 +647,54 @@ uint32_t usb_read(byte_t* data, size_t len) { //*---------------------------------------------------------------------------- uint32_t usb_write(const byte_t* data, const size_t len) { - if (!len) return 0; - if (!usb_check()) return 0; + if (!len) return 0; + if (!usb_check()) return 0; - // can we write? - if ( (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) != 0 ) return 0; + // can we write? + if ( (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXPKTRDY) != 0 ) return 0; - size_t length = len; - uint32_t cpt = 0; + size_t length = len; + uint32_t cpt = 0; - // send first chunk - cpt = MIN(length, AT91C_EP_IN_SIZE); - length -= cpt; - while (cpt--) { - pUdp->UDP_FDR[AT91C_EP_IN] = *data++; - } + // send first chunk + cpt = MIN(length, AT91C_EP_IN_SIZE); + length -= cpt; + while (cpt--) { + pUdp->UDP_FDR[AT91C_EP_IN] = *data++; + } - UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); + UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); - while (length) { - // Send next chunk - cpt = MIN(length, AT91C_EP_IN_SIZE); - length -= cpt; - while (cpt--) { - pUdp->UDP_FDR[AT91C_EP_IN] = *data++; - } + while (length) { + // Send next chunk + cpt = MIN(length, AT91C_EP_IN_SIZE); + length -= cpt; + while (cpt--) { + pUdp->UDP_FDR[AT91C_EP_IN] = *data++; + } - // Wait for previous chunk to be sent - // (iceman) when is the bankswapping done? - while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { - if (!usb_check()) return length; - } + // Wait for previous chunk to be sent + // (iceman) when is the bankswapping done? + while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { + if (!usb_check()) return length; + } - UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); - while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP); - UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); + UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); + while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP); + UDP_SET_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXPKTRDY); - } + } - // Wait for the end of transfer - while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { - if (!usb_check()) return length; - } + // Wait for the end of transfer + while (!(pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP)) { + if (!usb_check()) return length; + } - UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); - while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP); + UDP_CLEAR_EP_FLAGS(AT91C_EP_IN, AT91C_UDP_TXCOMP); + while (pUdp->UDP_CSR[AT91C_EP_IN] & AT91C_UDP_TXCOMP); - return length; + return length; } //*---------------------------------------------------------------------------- @@ -702,39 +702,39 @@ uint32_t usb_write(const byte_t* data, const size_t len) { //* \brief Send Data through the control endpoint //*---------------------------------------------------------------------------- void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) { - uint32_t cpt = 0; - AT91_REG csr; + uint32_t cpt = 0; + AT91_REG csr; - do { - cpt = MIN(length, AT91C_EP_CONTROL_SIZE); - length -= cpt; + do { + cpt = MIN(length, AT91C_EP_CONTROL_SIZE); + length -= cpt; - while (cpt--) - pUdp->UDP_FDR[AT91C_EP_CONTROL] = *pData++; + while (cpt--) + pUdp->UDP_FDR[AT91C_EP_CONTROL] = *pData++; - if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) { - UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP); - while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP); - } + if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) { + UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP); + while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP); + } - UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY); + UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY); - do { - csr = pUdp->UDP_CSR[AT91C_EP_CONTROL]; - // Data IN stage has been stopped by a status OUT - if ( csr & AT91C_UDP_RX_DATA_BK0) { + do { + csr = pUdp->UDP_CSR[AT91C_EP_CONTROL]; + // Data IN stage has been stopped by a status OUT + if ( csr & AT91C_UDP_RX_DATA_BK0) { - UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0) - return; - } - } while ( !(csr & AT91C_UDP_TXCOMP) ); + UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0) + return; + } + } while ( !(csr & AT91C_UDP_TXCOMP) ); - } while (length); + } while (length); - if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) { - UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP); - while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP); - } + if (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) { + UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP); + while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP); + } } @@ -743,10 +743,10 @@ void AT91F_USB_SendData(AT91PS_UDP pUdp, const char *pData, uint32_t length) { //* \brief Send zero length packet through the control endpoint //*---------------------------------------------------------------------------- void AT91F_USB_SendZlp(AT91PS_UDP pUdp) { - UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY); - while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) ); - UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP); - while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP); + UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXPKTRDY); + while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP) ); + UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_TXCOMP); + while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_TXCOMP); } //*---------------------------------------------------------------------------- @@ -754,10 +754,10 @@ void AT91F_USB_SendZlp(AT91PS_UDP pUdp) { //* \brief Stall the control endpoint //*---------------------------------------------------------------------------- void AT91F_USB_SendStall(AT91PS_UDP pUdp) { - UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL); - while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_ISOERROR) ); - UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR) ); - while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR)); + UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_FORCESTALL); + while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_ISOERROR) ); + UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR) ); + while (pUdp->UDP_CSR[AT91C_EP_CONTROL] & (AT91C_UDP_FORCESTALL | AT91C_UDP_ISOERROR)); } //*---------------------------------------------------------------------------- @@ -768,181 +768,181 @@ void AT91F_USB_SendStall(AT91PS_UDP pUdp) { //* 2. mixed with CDC ACM endpoint3 , interrupt, control endpoint //*---------------------------------------------------------------------------- void AT91F_CDC_Enumerate() { - byte_t bmRequestType, bRequest; - uint16_t wValue, wIndex, wLength, wStatus; + byte_t bmRequestType, bRequest; + uint16_t wValue, wIndex, wLength, wStatus; - if ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) ) - return; + if ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) ) + return; - bmRequestType = pUdp->UDP_FDR[AT91C_EP_CONTROL]; - bRequest = pUdp->UDP_FDR[AT91C_EP_CONTROL]; - wValue = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF); - wValue |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8); - wIndex = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF); - wIndex |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8); - wLength = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF); - wLength |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8); + bmRequestType = pUdp->UDP_FDR[AT91C_EP_CONTROL]; + bRequest = pUdp->UDP_FDR[AT91C_EP_CONTROL]; + wValue = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF); + wValue |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8); + wIndex = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF); + wIndex |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8); + wLength = (pUdp->UDP_FDR[AT91C_EP_CONTROL] & 0xFF); + wLength |= (pUdp->UDP_FDR[AT91C_EP_CONTROL] << 8); - if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host - UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR); - while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR) ); - } - UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RXSETUP); - while ( (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) ); + if (bmRequestType & 0x80) { // Data Phase Transfer Direction Device to Host + UDP_SET_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_DIR); + while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_DIR) ); + } + UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RXSETUP); + while ( (pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RXSETUP) ); - /* - if ( bRequest == MS_VENDOR_CODE) { - if ( bmRequestType == MS_WCID_GET_DESCRIPTOR ) { // C0 - if ( wIndex == MS_EXTENDED_COMPAT_ID ) { // 4 - //AT91F_USB_SendData(pUdp, CompatIDFeatureDescriptor, MIN(sizeof(CompatIDFeatureDescriptor), wLength)); - //return; - } - } + /* + if ( bRequest == MS_VENDOR_CODE) { + if ( bmRequestType == MS_WCID_GET_DESCRIPTOR ) { // C0 + if ( wIndex == MS_EXTENDED_COMPAT_ID ) { // 4 + //AT91F_USB_SendData(pUdp, CompatIDFeatureDescriptor, MIN(sizeof(CompatIDFeatureDescriptor), wLength)); + //return; + } + } - if ( bmRequestType == MS_WCID_GET_FEATURE_DESCRIPTOR ) { //C1 - // if ( wIndex == MS_EXTENDED_PROPERTIES ) { // 5 - winusb bug with wIndex == interface index, so I just send it always) - //AT91F_USB_SendData(pUdp, OSprop, MIN(sizeof(OSprop), wLength)); - //return; - // } - } - } - */ + if ( bmRequestType == MS_WCID_GET_FEATURE_DESCRIPTOR ) { //C1 + // if ( wIndex == MS_EXTENDED_PROPERTIES ) { // 5 - winusb bug with wIndex == interface index, so I just send it always) + //AT91F_USB_SendData(pUdp, OSprop, MIN(sizeof(OSprop), wLength)); + //return; + // } + } + } + */ - // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1 - switch ((bRequest << 8) | bmRequestType) { - case STD_GET_DESCRIPTOR: { + // Handle supported standard device request Cf Table 9-3 in USB specification Rev 1.1 + switch ((bRequest << 8) | bmRequestType) { + case STD_GET_DESCRIPTOR: { - if ( wValue == 0x100 ) // Return Device Descriptor - AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength)); - else if ( wValue == 0x200 ) // Return Configuration Descriptor - AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength)); - else if ( (wValue & 0xF00) == 0xF00) // Return BOS Descriptor - AT91F_USB_SendData(pUdp, bosDescriptor, MIN(sizeof(bosDescriptor), wLength)); - else if ( (wValue & 0x300) == 0x300) { // Return String Descriptor + if ( wValue == 0x100 ) // Return Device Descriptor + AT91F_USB_SendData(pUdp, devDescriptor, MIN(sizeof(devDescriptor), wLength)); + else if ( wValue == 0x200 ) // Return Configuration Descriptor + AT91F_USB_SendData(pUdp, cfgDescriptor, MIN(sizeof(cfgDescriptor), wLength)); + else if ( (wValue & 0xF00) == 0xF00) // Return BOS Descriptor + AT91F_USB_SendData(pUdp, bosDescriptor, MIN(sizeof(bosDescriptor), wLength)); + else if ( (wValue & 0x300) == 0x300) { // Return String Descriptor - const char *strDescriptor = getStringDescriptor(wValue & 0xff); - if (strDescriptor != NULL) { - AT91F_USB_SendData(pUdp, strDescriptor, MIN(strDescriptor[0], wLength)); - } else { - AT91F_USB_SendStall(pUdp); - } - } else { - AT91F_USB_SendStall(pUdp); - } - } - break; - case STD_SET_ADDRESS: - AT91F_USB_SendZlp(pUdp); - pUdp->UDP_FADDR = (AT91C_UDP_FEN | (wValue & 0x7F) ); - pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0; - break; - case STD_SET_CONFIGURATION: + const char *strDescriptor = getStringDescriptor(wValue & 0xff); + if (strDescriptor != NULL) { + AT91F_USB_SendData(pUdp, strDescriptor, MIN(strDescriptor[0], wLength)); + } else { + AT91F_USB_SendStall(pUdp); + } + } else { + AT91F_USB_SendStall(pUdp); + } + } + break; + case STD_SET_ADDRESS: + AT91F_USB_SendZlp(pUdp); + pUdp->UDP_FADDR = (AT91C_UDP_FEN | (wValue & 0x7F) ); + pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_FADDEN : 0; + break; + case STD_SET_CONFIGURATION: - /* - * Set or clear the device "configured" state. - * The LSB of wValue is the "Configuration Number". If this value is non-zero, - * it should be the same number as defined in the Configuration Descriptor; - * otherwise an error must have occurred. - * This device has only one configuration and its Config Number is CONF_NB (= 1). - */ - AT91F_USB_SendZlp(pUdp); - btConfiguration = wValue; - pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN; + /* + * Set or clear the device "configured" state. + * The LSB of wValue is the "Configuration Number". If this value is non-zero, + * it should be the same number as defined in the Configuration Descriptor; + * otherwise an error must have occurred. + * This device has only one configuration and its Config Number is CONF_NB (= 1). + */ + AT91F_USB_SendZlp(pUdp); + btConfiguration = wValue; + pUdp->UDP_GLBSTATE = (wValue) ? AT91C_UDP_CONFG : AT91C_UDP_FADDEN; - // make sure we are not stalled - /* - UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT , AT91C_UDP_FORCESTALL); + // make sure we are not stalled + /* + UDP_CLEAR_EP_FLAGS(AT91C_EP_OUT , AT91C_UDP_FORCESTALL); UDP_CLEAR_EP_FLAGS(AT91C_EP_IN , AT91C_UDP_FORCESTALL); - UDP_CLEAR_EP_FLAGS(AT91C_EP_NOTIFY, AT91C_UDP_FORCESTALL); - */ + UDP_CLEAR_EP_FLAGS(AT91C_EP_NOTIFY, AT91C_UDP_FORCESTALL); + */ - // enable endpoints - pUdp->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0; - pUdp->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0; - pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0; - break; - case STD_GET_CONFIGURATION: - AT91F_USB_SendData(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration)); - break; - case STD_GET_STATUS_ZERO: - wStatus = 0; // Device is Bus powered, remote wakeup disabled - AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); - break; - case STD_GET_STATUS_INTERFACE: - wStatus = 0; // reserved for future use - AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); - break; - case STD_GET_STATUS_ENDPOINT: - wStatus = 0; - wIndex &= 0x0F; - if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) { - wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1; - AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); - } - else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) { - wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1; - AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); - } else { - AT91F_USB_SendStall(pUdp); - } - break; - case STD_SET_FEATURE_ZERO: - AT91F_USB_SendStall(pUdp); - break; - case STD_SET_FEATURE_INTERFACE: - AT91F_USB_SendZlp(pUdp); - break; - case STD_SET_FEATURE_ENDPOINT: - wIndex &= 0x0F; - if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) { - pUdp->UDP_CSR[wIndex] = 0; - AT91F_USB_SendZlp(pUdp); - } else { - AT91F_USB_SendStall(pUdp); - } - break; - case STD_CLEAR_FEATURE_ZERO: - AT91F_USB_SendStall(pUdp); - break; - case STD_CLEAR_FEATURE_INTERFACE: - AT91F_USB_SendZlp(pUdp); - break; - case STD_CLEAR_FEATURE_ENDPOINT: - wIndex &= 0x0F; - if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) { + // enable endpoints + pUdp->UDP_CSR[AT91C_EP_OUT] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT) : 0; + pUdp->UDP_CSR[AT91C_EP_IN] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN) : 0; + pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (wValue) ? (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN) : 0; + break; + case STD_GET_CONFIGURATION: + AT91F_USB_SendData(pUdp, (char *) &(btConfiguration), sizeof(btConfiguration)); + break; + case STD_GET_STATUS_ZERO: + wStatus = 0; // Device is Bus powered, remote wakeup disabled + AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); + break; + case STD_GET_STATUS_INTERFACE: + wStatus = 0; // reserved for future use + AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); + break; + case STD_GET_STATUS_ENDPOINT: + wStatus = 0; + wIndex &= 0x0F; + if ((pUdp->UDP_GLBSTATE & AT91C_UDP_CONFG) && (wIndex <= AT91C_EP_NOTIFY)) { + wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1; + AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); + } + else if ((pUdp->UDP_GLBSTATE & AT91C_UDP_FADDEN) && (wIndex == AT91C_EP_CONTROL)) { + wStatus = (pUdp->UDP_CSR[wIndex] & AT91C_UDP_EPEDS) ? 0 : 1; + AT91F_USB_SendData(pUdp, (char *) &wStatus, sizeof(wStatus)); + } else { + AT91F_USB_SendStall(pUdp); + } + break; + case STD_SET_FEATURE_ZERO: + AT91F_USB_SendStall(pUdp); + break; + case STD_SET_FEATURE_INTERFACE: + AT91F_USB_SendZlp(pUdp); + break; + case STD_SET_FEATURE_ENDPOINT: + wIndex &= 0x0F; + if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) { + pUdp->UDP_CSR[wIndex] = 0; + AT91F_USB_SendZlp(pUdp); + } else { + AT91F_USB_SendStall(pUdp); + } + break; + case STD_CLEAR_FEATURE_ZERO: + AT91F_USB_SendStall(pUdp); + break; + case STD_CLEAR_FEATURE_INTERFACE: + AT91F_USB_SendZlp(pUdp); + break; + case STD_CLEAR_FEATURE_ENDPOINT: + wIndex &= 0x0F; + if ((wValue == 0) && (wIndex >= AT91C_EP_OUT) && (wIndex <= AT91C_EP_NOTIFY)) { - if (wIndex == AT91C_EP_OUT) pUdp->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT); - else if (wIndex == AT91C_EP_IN) pUdp->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN); - else if (wIndex == AT91C_EP_NOTIFY) pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN); + if (wIndex == AT91C_EP_OUT) pUdp->UDP_CSR[AT91C_EP_OUT] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_OUT); + else if (wIndex == AT91C_EP_IN) pUdp->UDP_CSR[AT91C_EP_IN] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_BULK_IN); + else if (wIndex == AT91C_EP_NOTIFY) pUdp->UDP_CSR[AT91C_EP_NOTIFY] = (AT91C_UDP_EPEDS | AT91C_UDP_EPTYPE_INT_IN); - AT91F_USB_SendZlp(pUdp); - } else { - AT91F_USB_SendStall(pUdp); - } - break; + AT91F_USB_SendZlp(pUdp); + } else { + AT91F_USB_SendStall(pUdp); + } + break; - // handle CDC class requests - case SET_LINE_CODING: { - /* - uint8_t i; - for ( i = 0 ; i < 7 ; i++ ) { - ((uint8_t*)&line)[i] = pUdp->UDP_FDR[AT91C_EP_CONTROL]; - } */ - // ignore SET_LINE_CODING... - while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RX_DATA_BK0) ); - UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0); - AT91F_USB_SendZlp(pUdp); - break; - } - case GET_LINE_CODING: - AT91F_USB_SendData(pUdp, (char *) &line, MIN(sizeof(line), wLength)); - break; - case SET_CONTROL_LINE_STATE: - btConnection = wValue; - AT91F_USB_SendZlp(pUdp); - break; - default: - AT91F_USB_SendStall(pUdp); - break; - } + // handle CDC class requests + case SET_LINE_CODING: { + /* + uint8_t i; + for ( i = 0 ; i < 7 ; i++ ) { + ((uint8_t*)&line)[i] = pUdp->UDP_FDR[AT91C_EP_CONTROL]; + } */ + // ignore SET_LINE_CODING... + while ( !(pUdp->UDP_CSR[AT91C_EP_CONTROL] & AT91C_UDP_RX_DATA_BK0) ); + UDP_CLEAR_EP_FLAGS(AT91C_EP_CONTROL, AT91C_UDP_RX_DATA_BK0); + AT91F_USB_SendZlp(pUdp); + break; + } + case GET_LINE_CODING: + AT91F_USB_SendData(pUdp, (char *) &line, MIN(sizeof(line), wLength)); + break; + case SET_CONTROL_LINE_STATE: + btConnection = wValue; + AT91F_USB_SendZlp(pUdp); + break; + default: + AT91F_USB_SendStall(pUdp); + break; + } } \ No newline at end of file diff --git a/common/wiegand.c b/common/wiegand.c index 730cb0206..18f1bca7d 100644 --- a/common/wiegand.c +++ b/common/wiegand.c @@ -37,27 +37,27 @@ uint8_t checkParity(uint32_t bits, uint8_t len, uint8_t type); // takes a array of binary values, start position, length of bits per parity (includes parity bit), // Parity Type (1 for odd; 0 for even; 2 for Always 1's; 3 for Always 0's), and binary Length (length to run) size_t removeParity(uint8_t *bitstream, size_t startIdx, uint8_t pLen, uint8_t pType, size_t bLen) { - uint32_t parityWd = 0; - size_t j = 0, bitcount = 0; - for (int word = 0; word < (bLen); word += pLen){ - for (int bit = 0; bit < pLen; ++bit){ - parityWd = (parityWd << 1) | bitstream[startIdx+word+bit]; - bitstream[j++] = (bitstream[startIdx + word + bit]); - } - j--; // overwrite parity with next data - // if parity fails then return 0 - switch (pType) { - case 3: if (bitstream[j] == 1) return 0; break; //should be 0 spacer bit - case 2: if (bitstream[j] == 0) return 0; break; //should be 1 spacer bit - default: //test parity - if (parityTest(parityWd, pLen, pType) == 0) return 0; break; - } - bitcount += ( pLen - 1 ); - parityWd = 0; - } - // if we got here then all the parities passed - //return ID start index and size - return bitcount; + uint32_t parityWd = 0; + size_t j = 0, bitcount = 0; + for (int word = 0; word < (bLen); word += pLen){ + for (int bit = 0; bit < pLen; ++bit){ + parityWd = (parityWd << 1) | bitstream[startIdx+word+bit]; + bitstream[j++] = (bitstream[startIdx + word + bit]); + } + j--; // overwrite parity with next data + // if parity fails then return 0 + switch (pType) { + case 3: if (bitstream[j] == 1) return 0; break; //should be 0 spacer bit + case 2: if (bitstream[j] == 0) return 0; break; //should be 1 spacer bit + default: //test parity + if (parityTest(parityWd, pLen, pType) == 0) return 0; break; + } + bitcount += ( pLen - 1 ); + parityWd = 0; + } + // if we got here then all the parities passed + //return ID start index and size + return bitcount; } @@ -76,28 +76,28 @@ size_t removeParity(uint8_t *bitstream, size_t startIdx, uint8_t pLen, uint8_t p */ size_t addParity(uint8_t *bits, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, uint8_t pType) { - uint32_t parityWd = 0; - size_t j = 0, bitCnt = 0; - for (int word = 0; word < sourceLen; word += pLen-1) { - for (int bit = 0; bit < pLen-1; ++bit){ - parityWd = (parityWd << 1) | bits[word+bit]; - dest[j++] = (bits[word+bit]); - } + uint32_t parityWd = 0; + size_t j = 0, bitCnt = 0; + for (int word = 0; word < sourceLen; word += pLen-1) { + for (int bit = 0; bit < pLen-1; ++bit){ + parityWd = (parityWd << 1) | bits[word+bit]; + dest[j++] = (bits[word+bit]); + } - // if parity fails then return 0 - switch (pType) { - case 3: dest[j++] = 0; break; // marker bit which should be a 0 - case 2: dest[j++] = 1; break; // marker bit which should be a 1 - default: - dest[j++] = parityTest(parityWd, pLen-1, pType) ^ 1; - break; - } - bitCnt += pLen; - parityWd = 0; - } - // if we got here then all the parities passed - //return ID start index and size - return bitCnt; + // if parity fails then return 0 + switch (pType) { + case 3: dest[j++] = 0; break; // marker bit which should be a 0 + case 2: dest[j++] = 1; break; // marker bit which should be a 1 + default: + dest[j++] = parityTest(parityWd, pLen-1, pType) ^ 1; + break; + } + bitCnt += pLen; + parityWd = 0; + } + // if we got here then all the parities passed + //return ID start index and size + return bitCnt; } // by marshmellow @@ -110,18 +110,18 @@ size_t addParity(uint8_t *bits, uint8_t *dest, uint8_t sourceLen, uint8_t pLen, */ void wiegand_add_parity(uint8_t *source, uint8_t *dest, uint8_t len) { - // Copy to destination, shifted one step to make room for EVEN parity + // Copy to destination, shifted one step to make room for EVEN parity memcpy(dest+1, source, length); - // half length, Even and Odd is calculated to the middle. - uint8_t len_h2 = length >> 1; + // half length, Even and Odd is calculated to the middle. + uint8_t len_h2 = length >> 1; - // add EVEN parity at the beginning + // add EVEN parity at the beginning *(dest) = GetParity(source, EVEN, len_h2); dest += length + 1; - // add ODD parity at the very end + // add ODD parity at the very end *(dest) = GetParity(source + len_h2, ODD, len_h2); } @@ -138,18 +138,18 @@ void wiegand_add_parity(uint8_t *source, uint8_t *dest, uint8_t len) { */ void num_to_wiegand_bytes(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, uint8_t formatlen){ - uint8_t data[MAX_BITS_TXX55] = {0}; - memset(data, 0, sizeof(data)); + uint8_t data[MAX_BITS_TXX55] = {0}; + memset(data, 0, sizeof(data)); - num_to_wiegand_bits(oem, fc, cn, data, formatlen); + num_to_wiegand_bits(oem, fc, cn, data, formatlen); - // loop - // (formatlen / 32 ) + 1 - // (formatlen >> 5) + 1 - for (int i = 0; i < formatlen ; ++i){ - uint32_t value = bytebits_to_byte( data + (i * 32), 32); - num_to_bytes(value, 32, dest + (i*4) ); - } + // loop + // (formatlen / 32 ) + 1 + // (formatlen >> 5) + 1 + for (int i = 0; i < formatlen ; ++i){ + uint32_t value = bytebits_to_byte( data + (i * 32), 32); + num_to_bytes(value, 32, dest + (i*4) ); + } } /* @@ -162,70 +162,70 @@ void num_to_wiegand_bytes(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, */ void num_to_wiegand_bits(uint64_t oem, uint64_t fc, uint64_t cn, uint8_t *dest, uint8_t formatlen){ - uint8_t bits[MAX_BITS_TXX55] = {0}; - memset(bits, 0, sizeof(bits)); - uint8_t *temp = bits; - uint64_t value = 0; + uint8_t bits[MAX_BITS_TXX55] = {0}; + memset(bits, 0, sizeof(bits)); + uint8_t *temp = bits; + uint64_t value = 0; - switch ( formatlen ){ - case 26 : // 26bit HID H10301 - fc &= 0xFF; // 8bits - cn &= 0xFFFF; // 16bits - value = fc << 16 | cn; - num_to_bytebits(value, 24, temp); - wiegand_add_parity(temp, dest, 24); - break; - case 261: // 26bit Indala - fc &= 0xFFF; // 12bits - cn &= 0xFFF; // 12bits - value = fc << 12 | cn; - num_to_bytebits(value, 24, temp); - wiegand_add_parity(temp, dest, 24); - break; - case 34 : // 34bits HID - fc &= 0xFFFF; // 16bits - cn &= 0xFFFF; // 16bits - value = fc << 16 | cn; - num_to_bytebits(value, 32, temp); - wiegand_add_parity(temp, dest, 32); - break; - case 35 : // 35bits HID - fc &= 0xFFF; // 12bits - cn &= 0xFFFFFF; // 20bits - value = fc << 20 | cn; - num_to_bytebits(value, 32, temp); - wiegand_add_parity(temp, dest, 32); - break; - case 37 : // H10304 - fc &= 0xFFFF; // 16bits - cn &= 0x7FFFF; // 19bits - value = fc << 19 | cn; - num_to_bytebits(value, 35, temp); - wiegand_add_parity(temp, dest, 35); - break; - case 39 : // 39bit KERI System Pyramid - fc &= 0x1FFFF; // 17bits - cn &= 0xFFFFFFFF; // 20bits - value = fc << 20 | cn; - num_to_bytebits(value, 37, temp); - wiegand_add_parity(temp, dest, 37); - break; - case 44 : // 44bit KERI system Pyramid - oem &= 0xFF; // 8bits - fc &= 0xFFF; // 12bits - cn &= 0xFFFFFFFF; // 21bits - value = oem << 20 | fc << 12 | cn; - num_to_bytebits(value, 42, temp); - wiegand_add_parity(temp, dest, 42); - break; - case 50 : // AWID 50 RBH - fc &= 0xFFFF; // 16bits - cn &= 0xFFFFFFFF // 32bits - value = fc << 32 | cn; - num_to_bytebits(value, 48, temp); - wiegand_add_parity(temp, dest, 48); // verify! - break; - default: - break; - } + switch ( formatlen ){ + case 26 : // 26bit HID H10301 + fc &= 0xFF; // 8bits + cn &= 0xFFFF; // 16bits + value = fc << 16 | cn; + num_to_bytebits(value, 24, temp); + wiegand_add_parity(temp, dest, 24); + break; + case 261: // 26bit Indala + fc &= 0xFFF; // 12bits + cn &= 0xFFF; // 12bits + value = fc << 12 | cn; + num_to_bytebits(value, 24, temp); + wiegand_add_parity(temp, dest, 24); + break; + case 34 : // 34bits HID + fc &= 0xFFFF; // 16bits + cn &= 0xFFFF; // 16bits + value = fc << 16 | cn; + num_to_bytebits(value, 32, temp); + wiegand_add_parity(temp, dest, 32); + break; + case 35 : // 35bits HID + fc &= 0xFFF; // 12bits + cn &= 0xFFFFFF; // 20bits + value = fc << 20 | cn; + num_to_bytebits(value, 32, temp); + wiegand_add_parity(temp, dest, 32); + break; + case 37 : // H10304 + fc &= 0xFFFF; // 16bits + cn &= 0x7FFFF; // 19bits + value = fc << 19 | cn; + num_to_bytebits(value, 35, temp); + wiegand_add_parity(temp, dest, 35); + break; + case 39 : // 39bit KERI System Pyramid + fc &= 0x1FFFF; // 17bits + cn &= 0xFFFFFFFF; // 20bits + value = fc << 20 | cn; + num_to_bytebits(value, 37, temp); + wiegand_add_parity(temp, dest, 37); + break; + case 44 : // 44bit KERI system Pyramid + oem &= 0xFF; // 8bits + fc &= 0xFFF; // 12bits + cn &= 0xFFFFFFFF; // 21bits + value = oem << 20 | fc << 12 | cn; + num_to_bytebits(value, 42, temp); + wiegand_add_parity(temp, dest, 42); + break; + case 50 : // AWID 50 RBH + fc &= 0xFFFF; // 16bits + cn &= 0xFFFFFFFF // 32bits + value = fc << 32 | cn; + num_to_bytebits(value, 48, temp); + wiegand_add_parity(temp, dest, 48); // verify! + break; + default: + break; + } } \ No newline at end of file From 9ebf3f4f6d3cbb0100920ddb8c706a16419b04ab Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 20:34:20 +0100 Subject: [PATCH 0708/1938] chg: use bool instead --- client/cmdlfem4x.c | 24 ++++++++++++------------ client/graph.c | 10 ++++++---- client/graph.h | 4 ++-- 3 files changed, 20 insertions(+), 18 deletions(-) diff --git a/client/cmdlfem4x.c b/client/cmdlfem4x.c index 47a05b260..f9ebf5f03 100644 --- a/client/cmdlfem4x.c +++ b/client/cmdlfem4x.c @@ -206,11 +206,11 @@ void ConstructEM410xEmulGraph(const char *uid,const uint8_t clock) { int i, j, binary[4], parity[4]; uint32_t n; /* clear our graph */ - ClearGraph(0); + ClearGraph(false); /* write 9 start bits */ for (i = 0; i < 9; i++) - AppendGraph(0, clock, 1); + AppendGraph(false, clock, 1); /* for each hex char */ parity[0] = parity[1] = parity[2] = parity[3] = 0; @@ -221,13 +221,13 @@ void ConstructEM410xEmulGraph(const char *uid,const uint8_t clock) { binary[j] = n % 2; /* append each bit */ - AppendGraph(0, clock, binary[0]); - AppendGraph(0, clock, binary[1]); - AppendGraph(0, clock, binary[2]); - AppendGraph(0, clock, binary[3]); + AppendGraph(false, clock, binary[0]); + AppendGraph(false, clock, binary[1]); + AppendGraph(false, clock, binary[2]); + AppendGraph(false, clock, binary[3]); /* append parity bit */ - AppendGraph(0, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); + AppendGraph(false, clock, binary[0] ^ binary[1] ^ binary[2] ^ binary[3]); /* keep track of column parity */ parity[0] ^= binary[0]; @@ -237,13 +237,13 @@ void ConstructEM410xEmulGraph(const char *uid,const uint8_t clock) { } /* parity columns */ - AppendGraph(0, clock, parity[0]); - AppendGraph(0, clock, parity[1]); - AppendGraph(0, clock, parity[2]); - AppendGraph(0, clock, parity[3]); + AppendGraph(false, clock, parity[0]); + AppendGraph(false, clock, parity[1]); + AppendGraph(false, clock, parity[2]); + AppendGraph(false, clock, parity[3]); /* stop bit */ - AppendGraph(1, clock, 0); + AppendGraph(true, clock, 0); } //by marshmellow diff --git a/client/graph.c b/client/graph.c index 0f7789093..c3f6a2b99 100644 --- a/client/graph.c +++ b/client/graph.c @@ -13,8 +13,10 @@ int GraphBuffer[MAX_GRAPH_TRACE_LEN]; int GraphTraceLen; int s_Buff[MAX_GRAPH_TRACE_LEN]; -/* write a manchester bit to the graph */ -void AppendGraph(int redraw, int clock, int bit) { +/* write a manchester bit to the graph +TODO, verfy that this doesn't overflow buffer (iceman) +*/ +void AppendGraph(bool redraw, int clock, int bit) { int i; //set first half the clock bit (all 1's or 0's for a 0 or 1 bit) for (i = 0; i < (int)(clock / 2); ++i) @@ -28,7 +30,7 @@ void AppendGraph(int redraw, int clock, int bit) { } // clear out our graph window -int ClearGraph(int redraw) { +int ClearGraph(bool redraw) { int gtl = GraphTraceLen; memset(GraphBuffer, 0x00, GraphTraceLen); GraphTraceLen = 0; @@ -60,7 +62,7 @@ void save_restoreGB(uint8_t saveOpt) { void setGraphBuf(uint8_t *buf, size_t size) { if ( buf == NULL ) return; - ClearGraph(0); + ClearGraph(false); if ( size > MAX_GRAPH_TRACE_LEN ) size = MAX_GRAPH_TRACE_LEN; diff --git a/client/graph.h b/client/graph.h index 3e56d09f2..05750ab16 100644 --- a/client/graph.h +++ b/client/graph.h @@ -18,8 +18,8 @@ #include "lfdemod.h" #include "cmddata.h" //for g_debugmode -void AppendGraph(int redraw, int clock, int bit); -int ClearGraph(int redraw); +void AppendGraph(bool redraw, int clock, int bit); +int ClearGraph(bool redraw); size_t getFromGraphBuf(uint8_t *buff); int GetAskClock(const char *str, bool printAns); int GetPskClock(const char *str, bool printAns); From 8a7c6825b53e400cb480d93dab88ddb8c96182d8 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 20:34:41 +0100 Subject: [PATCH 0709/1938] armsrc: fix mix of spaces & tabs --- armsrc/BigBuf.c | 236 +- armsrc/BigBuf.h | 14 +- armsrc/LCD.c | 172 +- armsrc/LCD.h | 190 +- armsrc/appmain.c | 2248 ++++++++-------- armsrc/apps.h | 4 +- armsrc/buzzer.c | 112 +- armsrc/des.c | 450 ++-- armsrc/des.h | 10 +- armsrc/desfire_crypto.c | 78 +- armsrc/desfire_key.c | 42 +- armsrc/desfire_key.h | 22 +- armsrc/epa.c | 728 ++--- armsrc/epa.h | 6 +- armsrc/felica.c | 806 +++--- armsrc/flashmem.c | 620 ++--- armsrc/flashmem.h | 104 +- armsrc/fonts.c | 582 ++-- armsrc/fpgaloader.c | 568 ++-- armsrc/fpgaloader.h | 80 +- armsrc/hfsnoop.c | 90 +- armsrc/hitag2.c | 2722 +++++++++---------- armsrc/hitagS.c | 3524 ++++++++++++------------ armsrc/iclass.c | 3196 +++++++++++----------- armsrc/iso14443a.c | 5317 +++++++++++++++++++------------------ armsrc/iso14443a.h | 96 +- armsrc/iso14443b.c | 2218 ++++++++-------- armsrc/iso14443b.h | 18 +- armsrc/iso15693.c | 1298 ++++----- armsrc/lfops.c | 2981 ++++++++++----------- armsrc/lfsampling.c | 554 ++-- armsrc/lfsampling.h | 6 +- armsrc/mifarecmd.c | 2936 ++++++++++---------- armsrc/mifaredesfire.c | 498 ++-- armsrc/mifaresniff.c | 494 ++-- armsrc/mifaresniff.h | 22 +- armsrc/mifareutil.c | 902 +++---- armsrc/mifareutil.h | 8 +- armsrc/optimized_cipher.c | 258 +- armsrc/optimized_cipher.h | 16 +- armsrc/pcf7931.c | 788 +++--- armsrc/printf.c | 630 ++--- armsrc/start.c | 70 +- armsrc/string.c | 84 +- armsrc/ticks.c | 280 +- armsrc/util.c | 288 +- armsrc/util.h | 4 +- 47 files changed, 18186 insertions(+), 18184 deletions(-) diff --git a/armsrc/BigBuf.c b/armsrc/BigBuf.c index b6c9e544d..26421732c 100644 --- a/armsrc/BigBuf.c +++ b/armsrc/BigBuf.c @@ -20,7 +20,7 @@ Pointer to highest available memory: BigBuf_hi high BIGBUF_SIZE reserved = BigBuf_malloc() subtracts amount from BigBuf_hi, - low 0x00 + low 0x00 */ // High memory mark @@ -35,92 +35,92 @@ static bool tracing = true; //todo static? // get the address of BigBuf uint8_t *BigBuf_get_addr(void) { - return (uint8_t *)BigBuf; + return (uint8_t *)BigBuf; } // get the address of the emulator memory. Allocate part of Bigbuf for it, if not yet done uint8_t *BigBuf_get_EM_addr(void) { - // not yet allocated - if (emulator_memory == NULL) - emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE); + // not yet allocated + if (emulator_memory == NULL) + emulator_memory = BigBuf_malloc(CARD_MEMORY_SIZE); - return emulator_memory; + return emulator_memory; } // clear ALL of BigBuf void BigBuf_Clear(void) { - BigBuf_Clear_ext(true); + BigBuf_Clear_ext(true); } // clear ALL of BigBuf void BigBuf_Clear_ext(bool verbose) { - memset(BigBuf, 0, BIGBUF_SIZE); - if (verbose) - Dbprintf("Buffer cleared (%i bytes)", BIGBUF_SIZE); + memset(BigBuf, 0, BIGBUF_SIZE); + if (verbose) + Dbprintf("Buffer cleared (%i bytes)", BIGBUF_SIZE); } void BigBuf_Clear_EM(void) { - memset(BigBuf_get_EM_addr(), 0, CARD_MEMORY_SIZE); + memset(BigBuf_get_EM_addr(), 0, CARD_MEMORY_SIZE); } void BigBuf_Clear_keep_EM(void) { - memset(BigBuf, 0, BigBuf_hi); + memset(BigBuf, 0, BigBuf_hi); } // allocate a chunk of memory from BigBuf. We allocate high memory first. The unallocated memory // at the beginning of BigBuf is always for traces/samples uint8_t *BigBuf_malloc(uint16_t chunksize) { - if (BigBuf_hi - chunksize < 0) - return NULL; // no memory left + if (BigBuf_hi - chunksize < 0) + return NULL; // no memory left - chunksize = (chunksize + 3) & 0xfffc; // round to next multiple of 4 - BigBuf_hi -= chunksize; // aligned to 4 Byte boundary - return (uint8_t *)BigBuf + BigBuf_hi; + chunksize = (chunksize + 3) & 0xfffc; // round to next multiple of 4 + BigBuf_hi -= chunksize; // aligned to 4 Byte boundary + return (uint8_t *)BigBuf + BigBuf_hi; } // free ALL allocated chunks. The whole BigBuf is available for traces or samples again. void BigBuf_free(void){ - BigBuf_hi = BIGBUF_SIZE; - emulator_memory = NULL; - // shouldn't this empty BigBuf also? + BigBuf_hi = BIGBUF_SIZE; + emulator_memory = NULL; + // shouldn't this empty BigBuf also? } // free allocated chunks EXCEPT the emulator memory void BigBuf_free_keep_EM(void) { - if (emulator_memory != NULL) - BigBuf_hi = emulator_memory - (uint8_t *)BigBuf; - else - BigBuf_hi = BIGBUF_SIZE; + if (emulator_memory != NULL) + BigBuf_hi = emulator_memory - (uint8_t *)BigBuf; + else + BigBuf_hi = BIGBUF_SIZE; - // shouldn't this empty BigBuf also? + // shouldn't this empty BigBuf also? } void BigBuf_print_status(void) { - Dbprintf("Memory"); - Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE); - Dbprintf(" Available memory........%d", BigBuf_hi); - Dbprintf("Tracing"); - Dbprintf(" tracing ................%d", tracing); - Dbprintf(" traceLen ...............%d", traceLen); + Dbprintf("Memory"); + Dbprintf(" BIGBUF_SIZE.............%d", BIGBUF_SIZE); + Dbprintf(" Available memory........%d", BigBuf_hi); + Dbprintf("Tracing"); + Dbprintf(" tracing ................%d", tracing); + Dbprintf(" traceLen ...............%d", traceLen); } // return the maximum trace length (i.e. the unallocated size of BigBuf) uint16_t BigBuf_max_traceLen(void) { - return BigBuf_hi; + return BigBuf_hi; } void clear_trace(void) { - traceLen = 0; + traceLen = 0; } void set_tracelen(uint32_t value) { traceLen = value; } void set_tracing(bool enable) { - tracing = enable; + tracing = enable; } bool get_tracing(void) { - return tracing; + return tracing; } /** @@ -128,7 +128,7 @@ bool get_tracing(void) { * @return */ uint32_t BigBuf_get_traceLen(void) { - return traceLen; + return traceLen; } /** @@ -138,111 +138,111 @@ uint32_t BigBuf_get_traceLen(void) { annotation of commands/responses. **/ bool RAMFUNC LogTrace(const uint8_t *btBytes, uint16_t iLen, uint32_t timestamp_start, uint32_t timestamp_end, uint8_t *parity, bool readerToTag) { - if (!tracing) return false; + if (!tracing) return false; - uint8_t *trace = BigBuf_get_addr(); + uint8_t *trace = BigBuf_get_addr(); - uint32_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity - uint32_t duration = timestamp_end - timestamp_start; + uint32_t num_paritybytes = (iLen-1)/8 + 1; // number of valid paritybytes in *parity + uint32_t duration = timestamp_end - timestamp_start; - // Return when trace is full - if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= BigBuf_max_traceLen()) { - tracing = false; // don't trace any more - return false; - } - // Traceformat: - // 32 bits timestamp (little endian) - // 16 bits duration (little endian) - // 16 bits data length (little endian, Highest Bit used as readerToTag flag) - // y Bytes data - // x Bytes parity (one byte per 8 bytes data) + // Return when trace is full + if (traceLen + sizeof(iLen) + sizeof(timestamp_start) + sizeof(duration) + num_paritybytes + iLen >= BigBuf_max_traceLen()) { + tracing = false; // don't trace any more + return false; + } + // Traceformat: + // 32 bits timestamp (little endian) + // 16 bits duration (little endian) + // 16 bits data length (little endian, Highest Bit used as readerToTag flag) + // y Bytes data + // x Bytes parity (one byte per 8 bytes data) - // timestamp (start) - trace[traceLen++] = ((timestamp_start >> 0) & 0xff); - trace[traceLen++] = ((timestamp_start >> 8) & 0xff); - trace[traceLen++] = ((timestamp_start >> 16) & 0xff); - trace[traceLen++] = ((timestamp_start >> 24) & 0xff); + // timestamp (start) + trace[traceLen++] = ((timestamp_start >> 0) & 0xff); + trace[traceLen++] = ((timestamp_start >> 8) & 0xff); + trace[traceLen++] = ((timestamp_start >> 16) & 0xff); + trace[traceLen++] = ((timestamp_start >> 24) & 0xff); - // duration - trace[traceLen++] = ((duration >> 0) & 0xff); - trace[traceLen++] = ((duration >> 8) & 0xff); + // duration + trace[traceLen++] = ((duration >> 0) & 0xff); + trace[traceLen++] = ((duration >> 8) & 0xff); - // data length - trace[traceLen++] = ((iLen >> 0) & 0xff); - trace[traceLen++] = ((iLen >> 8) & 0xff); + // data length + trace[traceLen++] = ((iLen >> 0) & 0xff); + trace[traceLen++] = ((iLen >> 8) & 0xff); - // readerToTag flag - if (!readerToTag) { - trace[traceLen - 1] |= 0x80; - } + // readerToTag flag + if (!readerToTag) { + trace[traceLen - 1] |= 0x80; + } - // data bytes - if (btBytes != NULL && iLen != 0) { - memcpy(trace + traceLen, btBytes, iLen); - } - traceLen += iLen; + // data bytes + if (btBytes != NULL && iLen != 0) { + memcpy(trace + traceLen, btBytes, iLen); + } + traceLen += iLen; - // parity bytes - if (num_paritybytes != 0) { - if (parity != NULL) { - memcpy(trace + traceLen, parity, num_paritybytes); - } else { - memset(trace + traceLen, 0x00, num_paritybytes); - } - } - traceLen += num_paritybytes; + // parity bytes + if (num_paritybytes != 0) { + if (parity != NULL) { + memcpy(trace + traceLen, parity, num_paritybytes); + } else { + memset(trace + traceLen, 0x00, num_paritybytes); + } + } + traceLen += num_paritybytes; - return true; + return true; } int LogTraceHitag(const uint8_t * btBytes, int iBits, int iSamples, uint32_t dwParity, int readerToTag) { - /** - Todo, rewrite the logger to use the generic functionality instead. It should be noted, however, - that this logger takes number of bits as argument, not number of bytes. - **/ + /** + Todo, rewrite the logger to use the generic functionality instead. It should be noted, however, + that this logger takes number of bits as argument, not number of bytes. + **/ - if (!tracing) return false; + if (!tracing) return false; - uint8_t *trace = BigBuf_get_addr(); - uint32_t iLen = nbytes(iBits); - // Return when trace is full - if (traceLen + sizeof(rsamples) + sizeof(dwParity) + sizeof(iBits) + iLen > BigBuf_max_traceLen()) return false; + uint8_t *trace = BigBuf_get_addr(); + uint32_t iLen = nbytes(iBits); + // Return when trace is full + if (traceLen + sizeof(rsamples) + sizeof(dwParity) + sizeof(iBits) + iLen > BigBuf_max_traceLen()) return false; - //Hitag traces appear to use this traceformat: - // 32 bits timestamp (little endian,Highest Bit used as readerToTag flag) - // 32 bits parity - // 8 bits size (number of bits in the trace entry, not number of bytes) - // y Bytes data + //Hitag traces appear to use this traceformat: + // 32 bits timestamp (little endian,Highest Bit used as readerToTag flag) + // 32 bits parity + // 8 bits size (number of bits in the trace entry, not number of bytes) + // y Bytes data - rsamples += iSamples; - trace[traceLen++] = ((rsamples >> 0) & 0xff); - trace[traceLen++] = ((rsamples >> 8) & 0xff); - trace[traceLen++] = ((rsamples >> 16) & 0xff); - trace[traceLen++] = ((rsamples >> 24) & 0xff); + rsamples += iSamples; + trace[traceLen++] = ((rsamples >> 0) & 0xff); + trace[traceLen++] = ((rsamples >> 8) & 0xff); + trace[traceLen++] = ((rsamples >> 16) & 0xff); + trace[traceLen++] = ((rsamples >> 24) & 0xff); - if (!readerToTag) { - trace[traceLen - 1] |= 0x80; - } + if (!readerToTag) { + trace[traceLen - 1] |= 0x80; + } - trace[traceLen++] = ((dwParity >> 0) & 0xff); - trace[traceLen++] = ((dwParity >> 8) & 0xff); - trace[traceLen++] = ((dwParity >> 16) & 0xff); - trace[traceLen++] = ((dwParity >> 24) & 0xff); - trace[traceLen++] = iBits; + trace[traceLen++] = ((dwParity >> 0) & 0xff); + trace[traceLen++] = ((dwParity >> 8) & 0xff); + trace[traceLen++] = ((dwParity >> 16) & 0xff); + trace[traceLen++] = ((dwParity >> 24) & 0xff); + trace[traceLen++] = iBits; - memcpy(trace + traceLen, btBytes, iLen); - traceLen += iLen; + memcpy(trace + traceLen, btBytes, iLen); + traceLen += iLen; - return true; + return true; } // Emulator memory uint8_t emlSet(uint8_t *data, uint32_t offset, uint32_t length){ - uint8_t* mem = BigBuf_get_EM_addr(); - if (offset + length < CARD_MEMORY_SIZE) { - memcpy(mem+offset, data, length); - return 0; - } - Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset + length), CARD_MEMORY_SIZE); - return 1; + uint8_t* mem = BigBuf_get_EM_addr(); + if (offset + length < CARD_MEMORY_SIZE) { + memcpy(mem+offset, data, length); + return 0; + } + Dbprintf("Error, trying to set memory outside of bounds! %d > %d", (offset + length), CARD_MEMORY_SIZE); + return 1; } diff --git a/armsrc/BigBuf.h b/armsrc/BigBuf.h index 9b7b33e47..e9a7b8098 100644 --- a/armsrc/BigBuf.h +++ b/armsrc/BigBuf.h @@ -17,13 +17,13 @@ #include "string.h" #include "ticks.h" -#define BIGBUF_SIZE 40000 -#define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame -#define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 7) / 8) -#define MAX_MIFARE_FRAME_SIZE 18 // biggest Mifare frame is answer to a read (one block = 16 Bytes) + 2 Bytes CRC -#define MAX_MIFARE_PARITY_SIZE 3 // need 18 parity bits for the 18 Byte above. 3 Bytes are enough to store these -#define CARD_MEMORY_SIZE 4096 -#define DMA_BUFFER_SIZE 256 //128 (how big is the dma?!? +#define BIGBUF_SIZE 40000 +#define MAX_FRAME_SIZE 256 // maximum allowed ISO14443 frame +#define MAX_PARITY_SIZE ((MAX_FRAME_SIZE + 7) / 8) +#define MAX_MIFARE_FRAME_SIZE 18 // biggest Mifare frame is answer to a read (one block = 16 Bytes) + 2 Bytes CRC +#define MAX_MIFARE_PARITY_SIZE 3 // need 18 parity bits for the 18 Byte above. 3 Bytes are enough to store these +#define CARD_MEMORY_SIZE 4096 +#define DMA_BUFFER_SIZE 256 //128 (how big is the dma?!? extern uint8_t *BigBuf_get_addr(void); extern uint8_t *BigBuf_get_EM_addr(void); diff --git a/armsrc/LCD.c b/armsrc/LCD.c index 3e74c77fa..7987da188 100644 --- a/armsrc/LCD.c +++ b/armsrc/LCD.c @@ -9,141 +9,141 @@ void LCDSend(unsigned int data) { - // 9th bit set for data, clear for command - while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete - // For clarity's sake we pass data with 9th bit clear and commands with 9th - // bit set since they're implemented as defines, se we need to invert bit - AT91C_BASE_SPI->SPI_TDR = data^0x100; // Send the data/command + // 9th bit set for data, clear for command + while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete + // For clarity's sake we pass data with 9th bit clear and commands with 9th + // bit set since they're implemented as defines, se we need to invert bit + AT91C_BASE_SPI->SPI_TDR = data^0x100; // Send the data/command } void LCDSetXY(unsigned char x, unsigned char y) { - LCDSend(PPASET); // page start/end ram - LCDSend(y); // Start Page to display to - LCDSend(131); // End Page to display to + LCDSend(PPASET); // page start/end ram + LCDSend(y); // Start Page to display to + LCDSend(131); // End Page to display to - LCDSend(PCASET); // column start/end ram - LCDSend(x); // Start Column to display to - LCDSend(131); // End Column to display to + LCDSend(PCASET); // column start/end ram + LCDSend(x); // Start Column to display to + LCDSend(131); // End Column to display to } void LCDSetPixel(unsigned char x, unsigned char y, unsigned char color) { - LCDSetXY(x,y); // Set position - LCDSend(PRAMWR); // Now write the pixel to the display - LCDSend(color); // Write the data in the specified Color + LCDSetXY(x,y); // Set position + LCDSend(PRAMWR); // Now write the pixel to the display + LCDSend(color); // Write the data in the specified Color } void LCDFill (unsigned char xs,unsigned char ys,unsigned char width,unsigned char height, unsigned char color) { unsigned char i,j; - for (i=0;i < height;i++) // Number of horizontal lines + for (i=0;i < height;i++) // Number of horizontal lines { - LCDSetXY(xs,ys+i); // Goto start of fill area (Top Left) - LCDSend(PRAMWR); // Write to display + LCDSetXY(xs,ys+i); // Goto start of fill area (Top Left) + LCDSend(PRAMWR); // Write to display - for (j=0;j < width;j++) // pixels per line - LCDSend(color); + for (j=0;j < width;j++) // pixels per line + LCDSend(color); } } void LCDString (char *lcd_string, const char *font_style,unsigned char x, unsigned char y, unsigned char fcolor, unsigned char bcolor) { - unsigned int i; - unsigned char mask=0, px, py, xme, yme, offset; - const char *data; + unsigned int i; + unsigned char mask=0, px, py, xme, yme, offset; + const char *data; - data = font_style; // point to the start of the font table + data = font_style; // point to the start of the font table - xme = *data; // get font x width - data++; - yme = *data; // get font y length - data++; - offset = *data; // get data bytes per font + xme = *data; // get font x width + data++; + yme = *data; // get font y length + data++; + offset = *data; // get data bytes per font - do - { - // point to data in table to be loaded - data = (font_style + offset) + (offset * (int)(*lcd_string - 32)); + do + { + // point to data in table to be loaded + data = (font_style + offset) + (offset * (int)(*lcd_string - 32)); - for (i=0;i < yme;i++) { - mask |=0x80; + for (i=0;i < yme;i++) { + mask |=0x80; - for (px=x; px < (x + xme); px++) { - py= y + i; + for (px=x; px < (x + xme); px++) { + py= y + i; - if (*data & mask) LCDSetPixel (px,py,fcolor); - else LCDSetPixel (px,py,bcolor); + if (*data & mask) LCDSetPixel (px,py,fcolor); + else LCDSetPixel (px,py,bcolor); - mask>>=1; - } - data++; - } - x+=xme; + mask>>=1; + } + data++; + } + x+=xme; - lcd_string++; // next character in string + lcd_string++; // next character in string - } while(*lcd_string !='\0'); // keep spitting chars out until end of string + } while(*lcd_string !='\0'); // keep spitting chars out until end of string } void LCDReset(void) { - LED_A_ON(); - SetupSpi(SPI_LCD_MODE); - LOW(GPIO_LRST); - SpinDelay(100); + LED_A_ON(); + SetupSpi(SPI_LCD_MODE); + LOW(GPIO_LRST); + SpinDelay(100); - HIGH(GPIO_LRST); - SpinDelay(100); - LED_A_OFF(); + HIGH(GPIO_LRST); + SpinDelay(100); + LED_A_OFF(); } void LCDInit(void) { - int i; + int i; - LCDReset(); + LCDReset(); - LCDSend(PSWRESET); // software reset - SpinDelay(100); - LCDSend(PSLEEPOUT); // exit sleep mode - LCDSend(PBSTRON); // booster on - LCDSend(PDISPON); // display on - LCDSend(PNORON); // normal on - LCDSend(PMADCTL); // rotate display 180 deg - LCDSend(0xC0); + LCDSend(PSWRESET); // software reset + SpinDelay(100); + LCDSend(PSLEEPOUT); // exit sleep mode + LCDSend(PBSTRON); // booster on + LCDSend(PDISPON); // display on + LCDSend(PNORON); // normal on + LCDSend(PMADCTL); // rotate display 180 deg + LCDSend(0xC0); - LCDSend(PCOLMOD); // color mode - LCDSend(0x02); // 8bpp color mode + LCDSend(PCOLMOD); // color mode + LCDSend(0x02); // 8bpp color mode - LCDSend(PSETCON); // set contrast + LCDSend(PSETCON); // set contrast LCDSend(0xDC); - // clear display + // clear display LCDSetXY(0,0); - LCDSend(PRAMWR); // Write to display - i=LCD_XRES*LCD_YRES; - while(i--) LCDSend(WHITE); + LCDSend(PRAMWR); // Write to display + i=LCD_XRES*LCD_YRES; + while(i--) LCDSend(WHITE); // test text on different colored backgrounds - LCDString(" The quick brown fox ", (char *)&FONT6x8,1,1+8*0,WHITE ,BLACK ); - LCDString(" jumped over the ", (char *)&FONT6x8,1,1+8*1,BLACK ,WHITE ); - LCDString(" lazy dog. ", (char *)&FONT6x8,1,1+8*2,YELLOW ,RED ); - LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8,1,1+8*3,RED ,GREEN ); - LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8,1,1+8*4,MAGENTA,BLUE ); - LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8,1,1+8*5,BLUE ,YELLOW); - LCDString("`-=[]_;',./~!@#$%^&*()", (char *)&FONT6x8,1,1+8*6,BLACK ,CYAN ); - LCDString(" _+{}|:\\\"<>? ",(char *)&FONT6x8,1,1+8*7,BLUE ,MAGENTA); + LCDString(" The quick brown fox ", (char *)&FONT6x8,1,1+8*0,WHITE ,BLACK ); + LCDString(" jumped over the ", (char *)&FONT6x8,1,1+8*1,BLACK ,WHITE ); + LCDString(" lazy dog. ", (char *)&FONT6x8,1,1+8*2,YELLOW ,RED ); + LCDString(" AaBbCcDdEeFfGgHhIiJj ", (char *)&FONT6x8,1,1+8*3,RED ,GREEN ); + LCDString(" KkLlMmNnOoPpQqRrSsTt ", (char *)&FONT6x8,1,1+8*4,MAGENTA,BLUE ); + LCDString("UuVvWwXxYyZz0123456789", (char *)&FONT6x8,1,1+8*5,BLUE ,YELLOW); + LCDString("`-=[]_;',./~!@#$%^&*()", (char *)&FONT6x8,1,1+8*6,BLACK ,CYAN ); + LCDString(" _+{}|:\\\"<>? ", (char *)&FONT6x8,1,1+8*7,BLUE ,MAGENTA); - // color bands - LCDFill(0, 1+8* 8, 132, 8, BLACK); - LCDFill(0, 1+8* 9, 132, 8, WHITE); - LCDFill(0, 1+8*10, 132, 8, RED); - LCDFill(0, 1+8*11, 132, 8, GREEN); - LCDFill(0, 1+8*12, 132, 8, BLUE); - LCDFill(0, 1+8*13, 132, 8, YELLOW); - LCDFill(0, 1+8*14, 132, 8, CYAN); - LCDFill(0, 1+8*15, 132, 8, MAGENTA); + // color bands + LCDFill(0, 1+8* 8, 132, 8, BLACK); + LCDFill(0, 1+8* 9, 132, 8, WHITE); + LCDFill(0, 1+8*10, 132, 8, RED); + LCDFill(0, 1+8*11, 132, 8, GREEN); + LCDFill(0, 1+8*12, 132, 8, BLUE); + LCDFill(0, 1+8*13, 132, 8, YELLOW); + LCDFill(0, 1+8*14, 132, 8, CYAN); + LCDFill(0, 1+8*15, 132, 8, MAGENTA); } diff --git a/armsrc/LCD.h b/armsrc/LCD.h index 2643f66ee..a21c3eeff 100644 --- a/armsrc/LCD.h +++ b/armsrc/LCD.h @@ -14,110 +14,110 @@ #include "fonts.h" // The resolution of the LCD -#define LCD_XRES 132 -#define LCD_YRES 132 +#define LCD_XRES 132 +#define LCD_YRES 132 // 8bpp Color Mode - Some basic colors defined for ease of use // remember 8bpp color = 3xRed, 3xGreen & 2xBlue bits // organised as RRRGGGBB -#define BLACK 0x00 -#define BLUE 0x03 -#define GREEN 0x1C -#define CYAN 0x1F -#define RED 0xE0 -#define MAGENTA 0xE3 -#define YELLOW 0xFC -#define WHITE 0xFF +#define BLACK 0x00 +#define BLUE 0x03 +#define GREEN 0x1C +#define CYAN 0x1F +#define RED 0xE0 +#define MAGENTA 0xE3 +#define YELLOW 0xFC +#define WHITE 0xFF // EPSON LCD command set -#define ECASET 0x115 -#define EPWRCTR 0x120 -#define ENOP 0x125 -#define ERAMWR 0x15C -#define ERAMRD 0x15D -#define EPASET 0x175 -#define EEPSRRD1 0x17C -#define EEPSRRD2 0x17D -#define EVOLCTR 0x181 -#define ETMPGRD 0x182 -#define ESLPOUT 0x194 -#define ESLPIN 0x195 -#define EDISNOR 0x1A6 -#define EDISINV 0x1A7 -#define EPTLIN 0x1A8 -#define EPTLOUT 0x1A9 -#define EASCSET 0x1AA -#define ESCSTART 0x1AB -#define EDISOFF 0x1AE -#define EDISON 0x1AF -#define ECOMSCN 0x1BB -#define EDATCTL 0x1BC -#define EDISCTL 0x1CA -#define EEPCOUT 0x1CC -#define EEPCTIN 0x1CD -#define ERGBSET8 0x1CE -#define EOSCON 0x1D1 -#define EOSCOFF 0x1D2 -#define EVOLUP 0x1D6 -#define EVOLDOWN 0x1D7 -#define ERMWIN 0x1E0 -#define ERMWOUT 0x1EE -#define EEPMWR 0x1FC -#define EEPMRD 0x1FD +#define ECASET 0x115 +#define EPWRCTR 0x120 +#define ENOP 0x125 +#define ERAMWR 0x15C +#define ERAMRD 0x15D +#define EPASET 0x175 +#define EEPSRRD1 0x17C +#define EEPSRRD2 0x17D +#define EVOLCTR 0x181 +#define ETMPGRD 0x182 +#define ESLPOUT 0x194 +#define ESLPIN 0x195 +#define EDISNOR 0x1A6 +#define EDISINV 0x1A7 +#define EPTLIN 0x1A8 +#define EPTLOUT 0x1A9 +#define EASCSET 0x1AA +#define ESCSTART 0x1AB +#define EDISOFF 0x1AE +#define EDISON 0x1AF +#define ECOMSCN 0x1BB +#define EDATCTL 0x1BC +#define EDISCTL 0x1CA +#define EEPCOUT 0x1CC +#define EEPCTIN 0x1CD +#define ERGBSET8 0x1CE +#define EOSCON 0x1D1 +#define EOSCOFF 0x1D2 +#define EVOLUP 0x1D6 +#define EVOLDOWN 0x1D7 +#define ERMWIN 0x1E0 +#define ERMWOUT 0x1EE +#define EEPMWR 0x1FC +#define EEPMRD 0x1FD // PHILIPS LCD command set -#define PNOP 0x100 -#define PSWRESET 0x101 -#define PBSTROFF 0x102 -#define PBSTRON 0x103 -#define PRDDIDIF 0x104 -#define PRDDST 0x109 -#define PSLEEPIN 0x110 -#define PSLEEPOUT 0x111 -#define PPTLON 0x112 -#define PNORON 0x113 -#define PINVOFF 0x120 -#define PINVON 0x121 -#define PDALO 0x122 -#define PDAL 0x123 -#define PSETCON 0x125 -#define PDISPOFF 0x128 -#define PDISPON 0x129 -#define PCASET 0x12A -#define PPASET 0x12B -#define PRAMWR 0x12C -#define PRGBSET 0x12D -#define PPTLAR 0x130 -#define PVSCRDEF 0x133 -#define PTEOFF 0x134 -#define PTEON 0x135 -#define PMADCTL 0x136 -#define PSEP 0x137 -#define PIDMOFF 0x138 -#define PIDMON 0x139 -#define PCOLMOD 0x13A -#define PSETVOP 0x1B0 -#define PBRS 0x1B4 -#define PTRS 0x1B6 -#define PFINV 0x1B9 -#define PDOR 0x1BA -#define PTCDFE 0x1BD -#define PTCVOPE 0x1BF -#define PEC 0x1C0 -#define PSETMUL 0x1C2 -#define PTCVOPAB 0x1C3 -#define PTCVOPCD 0x1C4 -#define PTCDF 0x1C5 -#define PDF8C 0x1C6 -#define PSETBS 0x1C7 -#define PRDTEMP 0x1C8 -#define PNLI 0x1C9 -#define PRDID1 0x1DA -#define PRDID2 0x1DB -#define PRDID3 0x1DC -#define PSFD 0x1EF -#define PECM 0x1F0 +#define PNOP 0x100 +#define PSWRESET 0x101 +#define PBSTROFF 0x102 +#define PBSTRON 0x103 +#define PRDDIDIF 0x104 +#define PRDDST 0x109 +#define PSLEEPIN 0x110 +#define PSLEEPOUT 0x111 +#define PPTLON 0x112 +#define PNORON 0x113 +#define PINVOFF 0x120 +#define PINVON 0x121 +#define PDALO 0x122 +#define PDAL 0x123 +#define PSETCON 0x125 +#define PDISPOFF 0x128 +#define PDISPON 0x129 +#define PCASET 0x12A +#define PPASET 0x12B +#define PRAMWR 0x12C +#define PRGBSET 0x12D +#define PPTLAR 0x130 +#define PVSCRDEF 0x133 +#define PTEOFF 0x134 +#define PTEON 0x135 +#define PMADCTL 0x136 +#define PSEP 0x137 +#define PIDMOFF 0x138 +#define PIDMON 0x139 +#define PCOLMOD 0x13A +#define PSETVOP 0x1B0 +#define PBRS 0x1B4 +#define PTRS 0x1B6 +#define PFINV 0x1B9 +#define PDOR 0x1BA +#define PTCDFE 0x1BD +#define PTCVOPE 0x1BF +#define PEC 0x1C0 +#define PSETMUL 0x1C2 +#define PTCVOPAB 0x1C3 +#define PTCVOPCD 0x1C4 +#define PTCDF 0x1C5 +#define PDF8C 0x1C6 +#define PSETBS 0x1C7 +#define PRDTEMP 0x1C8 +#define PNLI 0x1C9 +#define PRDID1 0x1DA +#define PRDID2 0x1DB +#define PRDID3 0x1DC +#define PSFD 0x1EF +#define PECM 0x1F0 void LCDSend(unsigned int data); void LCDInit(void); diff --git a/armsrc/appmain.c b/armsrc/appmain.c index 68b51913f..2d8730cd7 100644 --- a/armsrc/appmain.c +++ b/armsrc/appmain.c @@ -55,55 +55,55 @@ static int ToSendBit; struct common_area common_area __attribute__((section(".commonarea"))); void ToSendReset(void) { - ToSendMax = -1; - ToSendBit = 8; + ToSendMax = -1; + ToSendBit = 8; } void ToSendStuffBit(int b) { - if(ToSendBit >= 8) { - ToSendMax++; - ToSend[ToSendMax] = 0; - ToSendBit = 0; - } + if(ToSendBit >= 8) { + ToSendMax++; + ToSend[ToSendMax] = 0; + ToSendBit = 0; + } - if(b) - ToSend[ToSendMax] |= (1 << (7 - ToSendBit)); + if(b) + ToSend[ToSendMax] |= (1 << (7 - ToSendBit)); - ToSendBit++; + ToSendBit++; - if(ToSendMax >= sizeof(ToSend)) { - ToSendBit = 0; - DbpString("ToSendStuffBit overflowed!"); - } + if(ToSendMax >= sizeof(ToSend)) { + ToSendBit = 0; + DbpString("ToSendStuffBit overflowed!"); + } } void PrintToSendBuffer(void) { - DbpString("Printing ToSendBuffer:"); - Dbhexdump(ToSendMax, ToSend, 0); + DbpString("Printing ToSendBuffer:"); + Dbhexdump(ToSendMax, ToSend, 0); } void print_result(char *name, uint8_t *buf, size_t len) { - uint8_t *p = buf; - uint16_t tmp = len & 0xFFF0; + uint8_t *p = buf; + uint16_t tmp = len & 0xFFF0; - for(; p-buf < tmp; p += 16) { - Dbprintf("[%s: %02d/%02d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", - name, - p-buf, - len, - p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15] - ); - } - if (len % 16 != 0) { - char s[46] = {0}; - char *sp = s; - for (; p-buf < len; p++ ) { - sprintf(sp, "%02x ", p[0] ); - sp += 3; - } - Dbprintf("[%s: %02d/%02d] %s", name, p-buf, len, s); - } + for(; p-buf < tmp; p += 16) { + Dbprintf("[%s: %02d/%02d] %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + name, + p-buf, + len, + p[0], p[1], p[2], p[3], p[4], p[5], p[6], p[7],p[8], p[9], p[10], p[11], p[12], p[13], p[14], p[15] + ); + } + if (len % 16 != 0) { + char s[46] = {0}; + char *sp = s; + for (; p-buf < len; p++ ) { + sprintf(sp, "%02x ", p[0] ); + sp += 3; + } + Dbprintf("[%s: %02d/%02d] %s", name, p-buf, len, s); + } } //============================================================================= @@ -112,77 +112,77 @@ void print_result(char *name, uint8_t *buf, size_t len) { void DbpStringEx(char *str, uint32_t cmd) { #if DEBUG - uint8_t len = strlen(str); - cmd_send(CMD_DEBUG_PRINT_STRING, len, cmd, 0, (uint8_t*)str, len); + uint8_t len = strlen(str); + cmd_send(CMD_DEBUG_PRINT_STRING, len, cmd, 0, (uint8_t*)str, len); #endif } void DbpString(char *str) { #if DEBUG - DbpStringEx(str, 0); + DbpStringEx(str, 0); #endif } #if 0 void DbpIntegers(int x1, int x2, int x3) { - cmd_send(CMD_DEBUG_PRINT_INTEGERS,x1,x2,x3,0,0); + cmd_send(CMD_DEBUG_PRINT_INTEGERS,x1,x2,x3,0,0); } #endif void DbprintfEx(uint32_t cmd, const char *fmt, ...) { #if DEBUG - // should probably limit size here; oh well, let's just use a big buffer - char output_string[128] = {0x00}; - va_list ap; - va_start(ap, fmt); - kvsprintf(fmt, output_string, 10, ap); - va_end(ap); + // should probably limit size here; oh well, let's just use a big buffer + char output_string[128] = {0x00}; + va_list ap; + va_start(ap, fmt); + kvsprintf(fmt, output_string, 10, ap); + va_end(ap); - DbpStringEx(output_string, cmd); + DbpStringEx(output_string, cmd); #endif } void Dbprintf(const char *fmt, ...) { #if DEBUG - // should probably limit size here; oh well, let's just use a big buffer - char output_string[128] = {0x00}; - va_list ap; + // should probably limit size here; oh well, let's just use a big buffer + char output_string[128] = {0x00}; + va_list ap; - va_start(ap, fmt); - kvsprintf(fmt, output_string, 10, ap); - va_end(ap); + va_start(ap, fmt); + kvsprintf(fmt, output_string, 10, ap); + va_end(ap); - DbpString(output_string); + DbpString(output_string); #endif } // prints HEX & ASCII void Dbhexdump(int len, uint8_t *d, bool bAsci) { #if DEBUG - int l=0, i; - char ascii[9]; + int l=0, i; + char ascii[9]; - while (len > 0) { + while (len > 0) { - l = (len > 8) ? 8 : len; + l = (len > 8) ? 8 : len; - memcpy(ascii, d, l); - ascii[l] = 0; + memcpy(ascii, d, l); + ascii[l] = 0; - // filter safe ascii - for (i=0; i 126) { ascii[i] = '.'; - } + } } - if (bAsci) - Dbprintf("%-8s %*D", ascii, l, d, " "); - else - Dbprintf("%*D", l, d, " "); + if (bAsci) + Dbprintf("%-8s %*D", ascii, l, d, " "); + else + Dbprintf("%*D", l, d, " "); - len -= 8; - d += 8; - } + len -= 8; + d += 8; + } #endif } @@ -193,47 +193,47 @@ void Dbhexdump(int len, uint8_t *d, bool bAsci) { //----------------------------------------------------------------------------- static uint16_t ReadAdc(int ch) { - // Note: ADC_MODE_PRESCALE and ADC_MODE_SAMPLE_HOLD_TIME are set to the maximum allowed value. - // AMPL_HI is are high impedance (10MOhm || 1MOhm) output, the input capacitance of the ADC is 12pF (typical). This results in a time constant - // of RC = (0.91MOhm) * 12pF = 10.9us. Even after the maximum configurable sample&hold time of 40us the input capacitor will not be fully charged. - // - // The maths are: - // If there is a voltage v_in at the input, the voltage v_cap at the capacitor (this is what we are measuring) will be - // - // v_cap = v_in * (1 - exp(-SHTIM/RC)) = v_in * (1 - exp(-40us/10.9us)) = v_in * 0,97 (i.e. an error of 3%) + // Note: ADC_MODE_PRESCALE and ADC_MODE_SAMPLE_HOLD_TIME are set to the maximum allowed value. + // AMPL_HI is are high impedance (10MOhm || 1MOhm) output, the input capacitance of the ADC is 12pF (typical). This results in a time constant + // of RC = (0.91MOhm) * 12pF = 10.9us. Even after the maximum configurable sample&hold time of 40us the input capacitor will not be fully charged. + // + // The maths are: + // If there is a voltage v_in at the input, the voltage v_cap at the capacitor (this is what we are measuring) will be + // + // v_cap = v_in * (1 - exp(-SHTIM/RC)) = v_in * (1 - exp(-40us/10.9us)) = v_in * 0,97 (i.e. an error of 3%) - AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST; + AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST; AT91C_BASE_ADC->ADC_MR = - ADC_MODE_PRESCALE(63) // ADC_CLK = MCK / ((63+1) * 2) = 48MHz / 128 = 375kHz - | ADC_MODE_STARTUP_TIME(1) // Startup Time = (1+1) * 8 / ADC_CLK = 16 / 375kHz = 42,7us Note: must be > 20us - | ADC_MODE_SAMPLE_HOLD_TIME(15); // Sample & Hold Time SHTIM = 15 / ADC_CLK = 15 / 375kHz = 40us + ADC_MODE_PRESCALE(63) // ADC_CLK = MCK / ((63+1) * 2) = 48MHz / 128 = 375kHz + | ADC_MODE_STARTUP_TIME(1) // Startup Time = (1+1) * 8 / ADC_CLK = 16 / 375kHz = 42,7us Note: must be > 20us + | ADC_MODE_SAMPLE_HOLD_TIME(15); // Sample & Hold Time SHTIM = 15 / ADC_CLK = 15 / 375kHz = 40us - AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ch); - AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; + AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ch); + AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; - while (!(AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ch))) {}; + while (!(AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ch))) {}; - return (AT91C_BASE_ADC->ADC_CDR[ch] & 0x3FF); + return (AT91C_BASE_ADC->ADC_CDR[ch] & 0x3FF); } // was static - merlok uint16_t AvgAdc(int ch) { - uint16_t a = 0; - for(uint8_t i = 0; i < 32; i++) - a += ReadAdc(ch); + uint16_t a = 0; + for(uint8_t i = 0; i < 32; i++) + a += ReadAdc(ch); - //division by 32 - return (a + 15) >> 5; + //division by 32 + return (a + 15) >> 5; } void MeasureAntennaTuning(void) { - uint8_t LF_Results[256]; - uint32_t i, adcval = 0, peak = 0, peakv = 0, peakf = 0; - uint32_t v_lf125 = 0, v_lf134 = 0, v_hf = 0; // in mV + uint8_t LF_Results[256]; + uint32_t i, adcval = 0, peak = 0, peakv = 0, peakf = 0; + uint32_t v_lf125 = 0, v_lf134 = 0, v_hf = 0; // in mV - memset(LF_Results, 0, sizeof(LF_Results)); - LED_B_ON(); + memset(LF_Results, 0, sizeof(LF_Results)); + LED_B_ON(); /* * Sweeps the useful LF range of the proxmark from @@ -244,77 +244,77 @@ void MeasureAntennaTuning(void) { * ( hopefully around 95 if it is tuned to 125kHz!) */ - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); - SpinDelay(50); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + SpinDelay(50); - for (i = 255; i >= 19; i--) { - WDT_HIT(); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i); - SpinDelay(20); - adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10); + for (i = 255; i >= 19; i--) { + WDT_HIT(); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, i); + SpinDelay(20); + adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10); if (i == 95) v_lf125 = adcval; // voltage at 125Khz if (i == 89) v_lf134 = adcval; // voltage at 134Khz - LF_Results[i] = adcval >> 9; // scale int to fit in byte for graphing purposes - if(LF_Results[i] > peak) { - peakv = adcval; - peakf = i; - peak = LF_Results[i]; - } - } + LF_Results[i] = adcval >> 9; // scale int to fit in byte for graphing purposes + if(LF_Results[i] > peak) { + peakv = adcval; + peakf = i; + peak = LF_Results[i]; + } + } - LED_A_ON(); - // Let the FPGA drive the high-frequency antenna around 13.56 MHz. - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); - SpinDelay(50); - v_hf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; + LED_A_ON(); + // Let the FPGA drive the high-frequency antenna around 13.56 MHz. + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); + SpinDelay(50); + v_hf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; - // RDV40 will hit the roof, try other ADC channel used in that hardware revision. - if ( v_hf > MAX_ADC_HF_VOLTAGE-300 ) { - v_hf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10; - } + // RDV40 will hit the roof, try other ADC channel used in that hardware revision. + if ( v_hf > MAX_ADC_HF_VOLTAGE-300 ) { + v_hf = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10; + } - uint64_t arg0 = v_lf134; - arg0 <<= 32; - arg0 |= v_lf125; + uint64_t arg0 = v_lf134; + arg0 <<= 32; + arg0 |= v_lf125; - uint64_t arg2 = peakv; - arg2 <<= 32; - arg2 |= peakf; + uint64_t arg2 = peakv; + arg2 <<= 32; + arg2 |= peakf; - cmd_send(CMD_MEASURED_ANTENNA_TUNING, arg0, v_hf, arg2, LF_Results, 256); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + cmd_send(CMD_MEASURED_ANTENNA_TUNING, arg0, v_hf, arg2, LF_Results, 256); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); } void MeasureAntennaTuningHf(void) { - uint16_t volt = 0; // in mV - // Let the FPGA drive the high-frequency antenna around 13.56 MHz. - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); - SpinDelay(50); - volt = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; - bool use_high = ( volt > MAX_ADC_HF_VOLTAGE-300 ); + uint16_t volt = 0; // in mV + // Let the FPGA drive the high-frequency antenna around 13.56 MHz. + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); + SpinDelay(50); + volt = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; + bool use_high = ( volt > MAX_ADC_HF_VOLTAGE-300 ); - while( !BUTTON_PRESS() ){ - SpinDelay(20); - if ( !use_high ) { - volt = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; - } else { - volt = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10; - } - DbprintfEx(FLAG_NONEWLINE, "%u mV / %5u V", volt, (uint16_t)(volt/1000)); - } - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - DbprintfEx(FLAG_NOOPT, "\n[+] cancelled", 1); + while( !BUTTON_PRESS() ){ + SpinDelay(20); + if ( !use_high ) { + volt = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; + } else { + volt = (MAX_ADC_HF_VOLTAGE_RDV40 * AvgAdc(ADC_CHAN_HF_RDV40)) >> 10; + } + DbprintfEx(FLAG_NONEWLINE, "%u mV / %5u V", volt, (uint16_t)(volt/1000)); + } + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + DbprintfEx(FLAG_NOOPT, "\n[+] cancelled", 1); } void ReadMem(int addr) { - const uint8_t *data = ((uint8_t *)addr); + const uint8_t *data = ((uint8_t *)addr); Dbprintf("%x: %02x %02x %02x %02x %02x %02x %02x %02x", addr, data[0], data[1], data[2], data[3], data[4], data[5], data[6], data[7]); } @@ -324,64 +324,64 @@ extern struct version_information version_information; /* bootrom version information is pointed to from _bootphase1_version_pointer */ extern char *_bootphase1_version_pointer, _flash_start, _flash_end, _bootrom_start, _bootrom_end, __data_src_start__; void SendVersion(void) { - char temp[USB_CMD_DATA_SIZE]; /* Limited data payload in USB packets */ - char VersionString[USB_CMD_DATA_SIZE] = { '\0' }; + char temp[USB_CMD_DATA_SIZE]; /* Limited data payload in USB packets */ + char VersionString[USB_CMD_DATA_SIZE] = { '\0' }; - /* Try to find the bootrom version information. Expect to find a pointer at - * symbol _bootphase1_version_pointer, perform slight sanity checks on the - * pointer, then use it. - */ - char *bootrom_version = *(char**)&_bootphase1_version_pointer; + /* Try to find the bootrom version information. Expect to find a pointer at + * symbol _bootphase1_version_pointer, perform slight sanity checks on the + * pointer, then use it. + */ + char *bootrom_version = *(char**)&_bootphase1_version_pointer; - strncat(VersionString, " [ ARM ]\n", sizeof(VersionString) - strlen(VersionString) - 1); + strncat(VersionString, " [ ARM ]\n", sizeof(VersionString) - strlen(VersionString) - 1); - if( bootrom_version < &_flash_start || bootrom_version >= &_flash_end ) { - strcat(VersionString, "bootrom version information appears invalid\n"); - } else { - FormatVersionInformation(temp, sizeof(temp), " bootrom: ", bootrom_version); - strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1); - } + if( bootrom_version < &_flash_start || bootrom_version >= &_flash_end ) { + strcat(VersionString, "bootrom version information appears invalid\n"); + } else { + FormatVersionInformation(temp, sizeof(temp), " bootrom: ", bootrom_version); + strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1); + } - FormatVersionInformation(temp, sizeof(temp), " os: ", &version_information); - strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1); + FormatVersionInformation(temp, sizeof(temp), " os: ", &version_information); + strncat(VersionString, temp, sizeof(VersionString) - strlen(VersionString) - 1); - strncat(VersionString, "\n [ FPGA ]\n", sizeof(VersionString) - strlen(VersionString) - 1); + strncat(VersionString, "\n [ FPGA ]\n", sizeof(VersionString) - strlen(VersionString) - 1); - for (int i = 0; i < fpga_bitstream_num; i++) { - strncat(VersionString, fpga_version_information[i], sizeof(VersionString) - strlen(VersionString) - 1); - if (i < fpga_bitstream_num - 1) { - strncat(VersionString, "\n", sizeof(VersionString) - strlen(VersionString) - 1); - } - } - // Send Chip ID and used flash memory - uint32_t text_and_rodata_section_size = (uint32_t)&__data_src_start__ - (uint32_t)&_flash_start; - uint32_t compressed_data_section_size = common_area.arg1; - cmd_send(CMD_ACK, *(AT91C_DBGU_CIDR), text_and_rodata_section_size + compressed_data_section_size, 0, VersionString, strlen(VersionString)); + for (int i = 0; i < fpga_bitstream_num; i++) { + strncat(VersionString, fpga_version_information[i], sizeof(VersionString) - strlen(VersionString) - 1); + if (i < fpga_bitstream_num - 1) { + strncat(VersionString, "\n", sizeof(VersionString) - strlen(VersionString) - 1); + } + } + // Send Chip ID and used flash memory + uint32_t text_and_rodata_section_size = (uint32_t)&__data_src_start__ - (uint32_t)&_flash_start; + uint32_t compressed_data_section_size = common_area.arg1; + cmd_send(CMD_ACK, *(AT91C_DBGU_CIDR), text_and_rodata_section_size + compressed_data_section_size, 0, VersionString, strlen(VersionString)); } // 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(void) { - Dbprintf("USB Speed"); - Dbprintf(" Sending USB packets to client..."); + Dbprintf("USB Speed"); + 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; + #define USB_SPEED_TEST_MIN_TIME 1500 // in milliseconds + uint8_t *test_data = BigBuf_get_addr(); + uint32_t end_time; - uint32_t start_time = end_time = GetTickCount(); - uint32_t bytes_transferred = 0; + uint32_t start_time = end_time = GetTickCount(); + uint32_t bytes_transferred = 0; - LED_B_ON(); - 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(); + LED_B_ON(); + 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(); - Dbprintf(" Time elapsed............%dms", end_time - start_time); - Dbprintf(" Bytes transferred.......%d", bytes_transferred); + 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)); } @@ -389,81 +389,81 @@ void printUSBSpeed(void) { * Prints runtime information about the PM3. **/ void SendStatus(void) { - BigBuf_print_status(); - Fpga_print_status(); + BigBuf_print_status(); + Fpga_print_status(); #ifdef WITH_FLASH - Flashmem_print_status(); + Flashmem_print_status(); #endif #ifdef WITH_SMARTCARD - I2C_print_status(); + I2C_print_status(); #endif #ifdef WITH_LF - printConfig(); // LF Sampling config - printT55xxConfig(); // LF T55XX Config + printConfig(); // LF Sampling config + printT55xxConfig(); // LF T55XX Config #endif - printUSBSpeed(); - Dbprintf("Various"); - Dbprintf(" MF_DBGLEVEL.............%d", MF_DBGLEVEL); - Dbprintf(" ToSendMax...............%d", ToSendMax); - Dbprintf(" ToSendBit...............%d", ToSendBit); - Dbprintf(" ToSend BUFFERSIZE.......%d", TOSEND_BUFFER_SIZE); - printStandAloneModes(); - cmd_send(CMD_ACK, 1, 0, 0, 0, 0); + printUSBSpeed(); + Dbprintf("Various"); + Dbprintf(" MF_DBGLEVEL.............%d", MF_DBGLEVEL); + Dbprintf(" ToSendMax...............%d", ToSendMax); + Dbprintf(" ToSendBit...............%d", ToSendBit); + Dbprintf(" ToSend BUFFERSIZE.......%d", TOSEND_BUFFER_SIZE); + printStandAloneModes(); + cmd_send(CMD_ACK, 1, 0, 0, 0, 0); } // Show some leds in a pattern to identify StandAlone mod is running void StandAloneMode(void) { - DbpString("Stand-alone mode! No PC necessary."); + DbpString("Stand-alone mode! No PC necessary."); - SpinDown(50); + SpinDown(50); SpinOff(50); SpinUp(50); SpinOff(50); SpinDown(50); - SpinDelay(500); + SpinDelay(500); } // detection of which Standalone Modes is installed // (iceman) void printStandAloneModes(void) { - DbpString("Installed StandAlone Mode"); + DbpString("Installed StandAlone Mode"); #if defined(WITH_LF_ICERUN) - DbpString(" LF sniff/clone/simulation - aka IceRun (iceman)"); + DbpString(" LF sniff/clone/simulation - aka IceRun (iceman)"); #endif #if defined(WITH_HF_YOUNG) - DbpString(" HF Mifare sniff/simulation - (Craig Young)"); + DbpString(" HF Mifare sniff/simulation - (Craig Young)"); #endif #if defined(WITH_LF_SAMYRUN) - DbpString(" LF HID26 standalone - aka SamyRun (Samy Kamkar)"); + DbpString(" LF HID26 standalone - aka SamyRun (Samy Kamkar)"); #endif #if defined(WITH_LF_PROXBRUTE) - DbpString(" LF HID ProxII bruteforce - aka Proxbrute (Brad Antoniewicz)"); + DbpString(" LF HID ProxII bruteforce - aka Proxbrute (Brad Antoniewicz)"); #endif #if defined(WITH_LF_HIDBRUTE) - DbpString(" LF HID corporate 1000 bruteforce - aka Corporatebrute (Federico dotta & Maurizio Agazzini)"); + DbpString(" LF HID corporate 1000 bruteforce - aka Corporatebrute (Federico dotta & Maurizio Agazzini)"); #endif #if defined(WITH_HF_MATTYRUN) - DbpString(" HF Mifare sniff/clone - aka MattyRun (Matías A. Ré Medina)"); + DbpString(" HF Mifare sniff/clone - aka MattyRun (Matías A. Ré Medina)"); #endif #if defined(WITH_HF_COLIN) DbpString(" HF Mifare ultra fast sniff/sim/clone - aka VIGIKPWN (Colin Brigato)"); #endif #if defined(WITH_HF_BOG) - DbpString(" HF 14a sniff standalone with ULC/ULEV1/NTAG auth storing in flashmem - aka BogitoRun (Bogito)"); + DbpString(" HF 14a sniff standalone with ULC/ULEV1/NTAG auth storing in flashmem - aka BogitoRun (Bogito)"); #endif - //DbpString("Running "); - //Dbprintf(" Is Device attached to USB| %s", USB_ATTACHED() ? "Yes" : "No"); - //Dbprintf(" Is Device attached to FPC| %s", 0 ? "Yes" : "No"); - //Dbprintf(" Is USB_reconnect value | %d", GetUSBreconnect() ); - //Dbprintf(" Is USB_configured value | %d", GetUSBconfigured() ); + //DbpString("Running "); + //Dbprintf(" Is Device attached to USB| %s", USB_ATTACHED() ? "Yes" : "No"); + //Dbprintf(" Is Device attached to FPC| %s", 0 ? "Yes" : "No"); + //Dbprintf(" Is USB_reconnect value | %d", GetUSBreconnect() ); + //Dbprintf(" Is USB_configured value | %d", GetUSBconfigured() ); - //.. add your own standalone detection based on with compiler directive you are used. - // don't "reuse" the already taken ones, this will make things easier when trying to detect the different modes - // 2017-08-06 must adapt the makefile and have individual compilation flags for all mods - // + //.. add your own standalone detection based on with compiler directive you are used. + // don't "reuse" the already taken ones, this will make things easier when trying to detect the different modes + // 2017-08-06 must adapt the makefile and have individual compilation flags for all mods + // } /* @@ -492,369 +492,369 @@ at the same place! :-) LIGHT SCHEME USED: */ static const char LIGHT_SCHEME[] = { - 0x0, /* ---- | No field detected */ - 0x1, /* X--- | 14% of maximum current detected */ - 0x2, /* -X-- | 29% of maximum current detected */ - 0x4, /* --X- | 43% of maximum current detected */ - 0x8, /* ---X | 57% of maximum current detected */ - 0xC, /* --XX | 71% of maximum current detected */ - 0xE, /* -XXX | 86% of maximum current detected */ - 0xF, /* XXXX | 100% of maximum current detected */ + 0x0, /* ---- | No field detected */ + 0x1, /* X--- | 14% of maximum current detected */ + 0x2, /* -X-- | 29% of maximum current detected */ + 0x4, /* --X- | 43% of maximum current detected */ + 0x8, /* ---X | 57% of maximum current detected */ + 0xC, /* --XX | 71% of maximum current detected */ + 0xE, /* -XXX | 86% of maximum current detected */ + 0xF, /* XXXX | 100% of maximum current detected */ }; static const int LIGHT_LEN = sizeof(LIGHT_SCHEME)/sizeof(LIGHT_SCHEME[0]); void ListenReaderField(int limit) { -#define LF_ONLY 1 -#define HF_ONLY 2 -#define REPORT_CHANGE 10 // report new values only if they have changed at least by REPORT_CHANGE +#define LF_ONLY 1 +#define HF_ONLY 2 +#define REPORT_CHANGE 10 // report new values only if they have changed at least by REPORT_CHANGE - uint16_t lf_av, lf_av_new, lf_baseline = 0, lf_max; - uint16_t hf_av, hf_av_new, hf_baseline = 0, hf_max; - uint16_t mode = 1, display_val, display_max, i; + uint16_t lf_av, lf_av_new, lf_baseline = 0, lf_max; + uint16_t hf_av, hf_av_new, hf_baseline = 0, hf_max; + uint16_t mode = 1, display_val, display_max, i; - // switch off FPGA - we don't want to measure our own signal - // 20180315 - iceman, why load this before and then turn off? - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + // switch off FPGA - we don't want to measure our own signal + // 20180315 - iceman, why load this before and then turn off? + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + LEDsoff(); - lf_av = lf_max = AvgAdc(ADC_CHAN_LF); + lf_av = lf_max = AvgAdc(ADC_CHAN_LF); - if (limit != HF_ONLY) { - Dbprintf("LF 125/134kHz Baseline: %dmV", (MAX_ADC_LF_VOLTAGE * lf_av) >> 10); - lf_baseline = lf_av; - } + if (limit != HF_ONLY) { + Dbprintf("LF 125/134kHz Baseline: %dmV", (MAX_ADC_LF_VOLTAGE * lf_av) >> 10); + lf_baseline = lf_av; + } - hf_av = hf_max = AvgAdc(ADC_CHAN_HF); + hf_av = hf_max = AvgAdc(ADC_CHAN_HF); - // iceman, useless, since we are measuring readerfield, not our field. My tests shows a max of 20v from a reader. - // RDV40 will hit the roof, try other ADC channel used in that hardware revision. - bool use_high = ( ((MAX_ADC_HF_VOLTAGE * hf_max) >> 10) > MAX_ADC_HF_VOLTAGE-300 ); - if ( use_high ) { - hf_av = hf_max = AvgAdc(ADC_CHAN_HF_RDV40); - } + // iceman, useless, since we are measuring readerfield, not our field. My tests shows a max of 20v from a reader. + // RDV40 will hit the roof, try other ADC channel used in that hardware revision. + bool use_high = ( ((MAX_ADC_HF_VOLTAGE * hf_max) >> 10) > MAX_ADC_HF_VOLTAGE-300 ); + if ( use_high ) { + hf_av = hf_max = AvgAdc(ADC_CHAN_HF_RDV40); + } - if (limit != LF_ONLY) { - Dbprintf("HF 13.56MHz Baseline: %dmV", (MAX_ADC_HF_VOLTAGE * hf_av) >> 10); - hf_baseline = hf_av; - } + if (limit != LF_ONLY) { + Dbprintf("HF 13.56MHz Baseline: %dmV", (MAX_ADC_HF_VOLTAGE * hf_av) >> 10); + hf_baseline = hf_av; + } - for(;;) { - // Switch modes with button - if (BUTTON_PRESS()) { - SpinDelay(500); - switch (mode) { - case 1: - mode = 2; - DbpString("Signal Strength Mode"); - break; - case 2: - default: - DbpString("Stopped"); - LEDsoff(); - return; - break; - } - } - WDT_HIT(); + for(;;) { + // Switch modes with button + if (BUTTON_PRESS()) { + SpinDelay(500); + switch (mode) { + case 1: + mode = 2; + DbpString("Signal Strength Mode"); + break; + case 2: + default: + DbpString("Stopped"); + LEDsoff(); + return; + break; + } + } + WDT_HIT(); - if (limit != HF_ONLY) { - if(mode == 1) { - if (ABS(lf_av - lf_baseline) > REPORT_CHANGE) - LED_D_ON(); - else - LED_D_OFF(); - } + if (limit != HF_ONLY) { + if(mode == 1) { + if (ABS(lf_av - lf_baseline) > REPORT_CHANGE) + LED_D_ON(); + else + LED_D_OFF(); + } - lf_av_new = AvgAdc(ADC_CHAN_LF); - // see if there's a significant change - if (ABS(lf_av - lf_av_new) > REPORT_CHANGE) { - Dbprintf("LF 125/134kHz Field Change: %5dmV", (MAX_ADC_LF_VOLTAGE * lf_av_new) >> 10); - lf_av = lf_av_new; - if (lf_av > lf_max) - lf_max = lf_av; - } - } + lf_av_new = AvgAdc(ADC_CHAN_LF); + // see if there's a significant change + if (ABS(lf_av - lf_av_new) > REPORT_CHANGE) { + Dbprintf("LF 125/134kHz Field Change: %5dmV", (MAX_ADC_LF_VOLTAGE * lf_av_new) >> 10); + lf_av = lf_av_new; + if (lf_av > lf_max) + lf_max = lf_av; + } + } - if (limit != LF_ONLY) { - if (mode == 1){ - if (ABS(hf_av - hf_baseline) > REPORT_CHANGE) - LED_B_ON(); - else - LED_B_OFF(); - } + if (limit != LF_ONLY) { + if (mode == 1){ + if (ABS(hf_av - hf_baseline) > REPORT_CHANGE) + LED_B_ON(); + else + LED_B_OFF(); + } - hf_av_new = (use_high) ? AvgAdc(ADC_CHAN_HF_RDV40) : AvgAdc(ADC_CHAN_HF); + hf_av_new = (use_high) ? AvgAdc(ADC_CHAN_HF_RDV40) : AvgAdc(ADC_CHAN_HF); - // see if there's a significant change - if(ABS(hf_av - hf_av_new) > REPORT_CHANGE) { - Dbprintf("HF 13.56MHz Field Change: %5dmV", (MAX_ADC_HF_VOLTAGE * hf_av_new) >> 10); - hf_av = hf_av_new; - if (hf_av > hf_max) - hf_max = hf_av; - } - } + // see if there's a significant change + if(ABS(hf_av - hf_av_new) > REPORT_CHANGE) { + Dbprintf("HF 13.56MHz Field Change: %5dmV", (MAX_ADC_HF_VOLTAGE * hf_av_new) >> 10); + hf_av = hf_av_new; + if (hf_av > hf_max) + hf_max = hf_av; + } + } - if (mode == 2) { - if (limit == LF_ONLY) { - display_val = lf_av; - display_max = lf_max; - } else if (limit == HF_ONLY) { - display_val = hf_av; - display_max = hf_max; - } else { /* Pick one at random */ - if( (hf_max - hf_baseline) > (lf_max - lf_baseline) ) { - display_val = hf_av; - display_max = hf_max; - } else { - display_val = lf_av; - display_max = lf_max; - } - } - for (i=0; i= ((display_max/LIGHT_LEN)*i) && display_val <= ((display_max/LIGHT_LEN)*(i+1))) { - if (LIGHT_SCHEME[i] & 0x1) LED_C_ON(); else LED_C_OFF(); - if (LIGHT_SCHEME[i] & 0x2) LED_A_ON(); else LED_A_OFF(); - if (LIGHT_SCHEME[i] & 0x4) LED_B_ON(); else LED_B_OFF(); - if (LIGHT_SCHEME[i] & 0x8) LED_D_ON(); else LED_D_OFF(); - break; - } - } - } - } + if (mode == 2) { + if (limit == LF_ONLY) { + display_val = lf_av; + display_max = lf_max; + } else if (limit == HF_ONLY) { + display_val = hf_av; + display_max = hf_max; + } else { /* Pick one at random */ + if( (hf_max - hf_baseline) > (lf_max - lf_baseline) ) { + display_val = hf_av; + display_max = hf_max; + } else { + display_val = lf_av; + display_max = lf_max; + } + } + for (i=0; i= ((display_max/LIGHT_LEN)*i) && display_val <= ((display_max/LIGHT_LEN)*(i+1))) { + if (LIGHT_SCHEME[i] & 0x1) LED_C_ON(); else LED_C_OFF(); + if (LIGHT_SCHEME[i] & 0x2) LED_A_ON(); else LED_A_OFF(); + if (LIGHT_SCHEME[i] & 0x4) LED_B_ON(); else LED_B_OFF(); + if (LIGHT_SCHEME[i] & 0x8) LED_D_ON(); else LED_D_OFF(); + break; + } + } + } + } } void UsbPacketReceived(uint8_t *packet, int len) { - UsbCommand *c = (UsbCommand *)packet; + UsbCommand *c = (UsbCommand *)packet; - //Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d", len, c->cmd, c->arg[0], c->arg[1], c->arg[2]); + //Dbprintf("received %d bytes, with command: 0x%04x and args: %d %d %d", len, c->cmd, c->arg[0], c->arg[1], c->arg[2]); - switch(c->cmd) { + switch(c->cmd) { #ifdef WITH_LF - case CMD_SET_LF_T55XX_CONFIG: - setT55xxConfig( c->arg[0], (t55xx_config *) c->d.asBytes); - break; - case CMD_SET_LF_SAMPLING_CONFIG: - setSamplingConfig((sample_config *) c->d.asBytes); - break; - case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K: { - uint32_t bits = SampleLF(c->arg[0], c->arg[1]); - cmd_send(CMD_ACK, bits, 0, 0, 0, 0); - break; - } - case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K: - ModThenAcquireRawAdcSamples125k(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_LF_SNOOP_RAW_ADC_SAMPLES: { - uint32_t bits = SnoopLF(); - cmd_send(CMD_ACK, bits, 0, 0, 0, 0); - break; - } - case CMD_HID_DEMOD_FSK: { - uint32_t high, low; - CmdHIDdemodFSK(c->arg[0], &high, &low, 1); - break; - } - case CMD_HID_SIM_TAG: - CmdHIDsimTAG(c->arg[0], c->arg[1], 1); - break; - case CMD_FSK_SIM_TAG: - CmdFSKsimTAG(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_ASK_SIM_TAG: - CmdASKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_PSK_SIM_TAG: - CmdPSKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_HID_CLONE_TAG: - CopyHIDtoT55x7(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]); - break; - case CMD_IO_DEMOD_FSK: { - uint32_t high, low; - CmdIOdemodFSK(c->arg[0], &high, &low, 1); - break; - } - case CMD_IO_CLONE_TAG: - CopyIOtoT55x7(c->arg[0], c->arg[1]); - break; - case CMD_EM410X_DEMOD: { - uint32_t high; - uint64_t low; - CmdEM410xdemod(c->arg[0], &high, &low, 1); - break; - } - case CMD_EM410X_WRITE_TAG: - WriteEM410x(c->arg[0], c->arg[1], c->arg[2]); - break; - case CMD_READ_TI_TYPE: - ReadTItag(); - break; - case CMD_WRITE_TI_TYPE: - WriteTItag(c->arg[0],c->arg[1],c->arg[2]); - break; - case CMD_SIMULATE_TAG_125K: - LED_A_ON(); - SimulateTagLowFrequency(c->arg[0], c->arg[1], 1); - LED_A_OFF(); - break; - case CMD_LF_SIMULATE_BIDIR: - SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]); - break; - case CMD_INDALA_CLONE_TAG: - CopyIndala64toT55x7(c->arg[0], c->arg[1]); - break; - case CMD_INDALA_CLONE_TAG_L: - CopyIndala224toT55x7( - c->d.asDwords[0], c->d.asDwords[1], c->d.asDwords[2], c->d.asDwords[3], - c->d.asDwords[4], c->d.asDwords[5], c->d.asDwords[6] - ); - break; - case CMD_T55XX_READ_BLOCK: { - T55xxReadBlock(c->arg[0], c->arg[1], c->arg[2]); - break; - } - case CMD_T55XX_WRITE_BLOCK: - T55xxWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]); - break; - case CMD_T55XX_WAKEUP: - T55xxWakeUp(c->arg[0]); - break; - case CMD_T55XX_RESET_READ: - T55xxResetRead(); - break; - case CMD_T55XX_CHKPWDS: - T55xx_ChkPwds(); - break; - case CMD_PCF7931_READ: - ReadPCF7931(); - break; - case CMD_PCF7931_WRITE: - WritePCF7931( - c->d.asBytes[0], c->d.asBytes[1], c->d.asBytes[2], c->d.asBytes[3], - c->d.asBytes[4], c->d.asBytes[5], c->d.asBytes[6], c->d.asBytes[9], - c->d.asBytes[7] - 128, c->d.asBytes[8] - 128, - c->arg[0], - c->arg[1], - c->arg[2] - ); - break; - case CMD_EM4X_READ_WORD: - EM4xReadWord(c->arg[0], c->arg[1], c->arg[2]); - break; - case CMD_EM4X_WRITE_WORD: - EM4xWriteWord(c->arg[0], c->arg[1], c->arg[2]); - break; - case CMD_AWID_DEMOD_FSK: { - uint32_t high, low; - // Set realtime AWID demodulation - CmdAWIDdemodFSK(c->arg[0], &high, &low, 1); - break; - } - case CMD_VIKING_CLONE_TAG: - CopyVikingtoT55xx(c->arg[0], c->arg[1], c->arg[2]); + case CMD_SET_LF_T55XX_CONFIG: + setT55xxConfig( c->arg[0], (t55xx_config *) c->d.asBytes); + break; + case CMD_SET_LF_SAMPLING_CONFIG: + setSamplingConfig((sample_config *) c->d.asBytes); + break; + case CMD_ACQUIRE_RAW_ADC_SAMPLES_125K: { + uint32_t bits = SampleLF(c->arg[0], c->arg[1]); + cmd_send(CMD_ACK, bits, 0, 0, 0, 0); + break; + } + case CMD_MOD_THEN_ACQUIRE_RAW_ADC_SAMPLES_125K: + ModThenAcquireRawAdcSamples125k(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_LF_SNOOP_RAW_ADC_SAMPLES: { + uint32_t bits = SnoopLF(); + cmd_send(CMD_ACK, bits, 0, 0, 0, 0); + break; + } + case CMD_HID_DEMOD_FSK: { + uint32_t high, low; + CmdHIDdemodFSK(c->arg[0], &high, &low, 1); + break; + } + case CMD_HID_SIM_TAG: + CmdHIDsimTAG(c->arg[0], c->arg[1], 1); + break; + case CMD_FSK_SIM_TAG: + CmdFSKsimTAG(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_ASK_SIM_TAG: + CmdASKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_PSK_SIM_TAG: + CmdPSKsimTag(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_HID_CLONE_TAG: + CopyHIDtoT55x7(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]); + break; + case CMD_IO_DEMOD_FSK: { + uint32_t high, low; + CmdIOdemodFSK(c->arg[0], &high, &low, 1); + break; + } + case CMD_IO_CLONE_TAG: + CopyIOtoT55x7(c->arg[0], c->arg[1]); + break; + case CMD_EM410X_DEMOD: { + uint32_t high; + uint64_t low; + CmdEM410xdemod(c->arg[0], &high, &low, 1); + break; + } + case CMD_EM410X_WRITE_TAG: + WriteEM410x(c->arg[0], c->arg[1], c->arg[2]); + break; + case CMD_READ_TI_TYPE: + ReadTItag(); + break; + case CMD_WRITE_TI_TYPE: + WriteTItag(c->arg[0],c->arg[1],c->arg[2]); + break; + case CMD_SIMULATE_TAG_125K: + LED_A_ON(); + SimulateTagLowFrequency(c->arg[0], c->arg[1], 1); + LED_A_OFF(); + break; + case CMD_LF_SIMULATE_BIDIR: + SimulateTagLowFrequencyBidir(c->arg[0], c->arg[1]); + break; + case CMD_INDALA_CLONE_TAG: + CopyIndala64toT55x7(c->arg[0], c->arg[1]); + break; + case CMD_INDALA_CLONE_TAG_L: + CopyIndala224toT55x7( + c->d.asDwords[0], c->d.asDwords[1], c->d.asDwords[2], c->d.asDwords[3], + c->d.asDwords[4], c->d.asDwords[5], c->d.asDwords[6] + ); + break; + case CMD_T55XX_READ_BLOCK: { + T55xxReadBlock(c->arg[0], c->arg[1], c->arg[2]); + break; + } + case CMD_T55XX_WRITE_BLOCK: + T55xxWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes[0]); + break; + case CMD_T55XX_WAKEUP: + T55xxWakeUp(c->arg[0]); + break; + case CMD_T55XX_RESET_READ: + T55xxResetRead(); + break; + case CMD_T55XX_CHKPWDS: + T55xx_ChkPwds(); + break; + case CMD_PCF7931_READ: + ReadPCF7931(); + break; + case CMD_PCF7931_WRITE: + WritePCF7931( + c->d.asBytes[0], c->d.asBytes[1], c->d.asBytes[2], c->d.asBytes[3], + c->d.asBytes[4], c->d.asBytes[5], c->d.asBytes[6], c->d.asBytes[9], + c->d.asBytes[7] - 128, c->d.asBytes[8] - 128, + c->arg[0], + c->arg[1], + c->arg[2] + ); + break; + case CMD_EM4X_READ_WORD: + EM4xReadWord(c->arg[0], c->arg[1], c->arg[2]); + break; + case CMD_EM4X_WRITE_WORD: + EM4xWriteWord(c->arg[0], c->arg[1], c->arg[2]); + break; + case CMD_AWID_DEMOD_FSK: { + uint32_t high, low; + // Set realtime AWID demodulation + CmdAWIDdemodFSK(c->arg[0], &high, &low, 1); + break; + } + case CMD_VIKING_CLONE_TAG: + CopyVikingtoT55xx(c->arg[0], c->arg[1], c->arg[2]); + break; + case CMD_COTAG: + Cotag(c->arg[0]); break; - case CMD_COTAG: - Cotag(c->arg[0]); - break; #endif #ifdef WITH_HITAG - case CMD_SNOOP_HITAG: // Eavesdrop Hitag tag, args = type - SnoopHitag(c->arg[0]); - break; - case CMD_SIMULATE_HITAG: // Simulate Hitag tag, args = memory content - SimulateHitagTag((bool)c->arg[0],(byte_t*)c->d.asBytes); - break; - case CMD_READER_HITAG: // Reader for Hitag tags, args = type and function - ReaderHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes); - break; - case CMD_SIMULATE_HITAG_S:// Simulate Hitag s tag, args = memory content - SimulateHitagSTag((bool)c->arg[0],(byte_t*)c->d.asBytes); - break; - case CMD_TEST_HITAGS_TRACES:// Tests every challenge within the given file - check_challenges((bool)c->arg[0],(byte_t*)c->d.asBytes); - break; - case CMD_READ_HITAG_S: //Reader for only Hitag S tags, args = key or challenge - ReadHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes); - break; - case CMD_WR_HITAG_S: //writer for Hitag tags args=data to write,page and key or challenge - if ((hitag_function)c->arg[0] < 10) { - WritePageHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes,c->arg[2]); - } else if ((hitag_function)c->arg[0] >= 10) { - WriterHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes, c->arg[2]); - } - break; + case CMD_SNOOP_HITAG: // Eavesdrop Hitag tag, args = type + SnoopHitag(c->arg[0]); + break; + case CMD_SIMULATE_HITAG: // Simulate Hitag tag, args = memory content + SimulateHitagTag((bool)c->arg[0],(byte_t*)c->d.asBytes); + break; + case CMD_READER_HITAG: // Reader for Hitag tags, args = type and function + ReaderHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes); + break; + case CMD_SIMULATE_HITAG_S:// Simulate Hitag s tag, args = memory content + SimulateHitagSTag((bool)c->arg[0],(byte_t*)c->d.asBytes); + break; + case CMD_TEST_HITAGS_TRACES:// Tests every challenge within the given file + check_challenges((bool)c->arg[0],(byte_t*)c->d.asBytes); + break; + case CMD_READ_HITAG_S: //Reader for only Hitag S tags, args = key or challenge + ReadHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes); + break; + case CMD_WR_HITAG_S: //writer for Hitag tags args=data to write,page and key or challenge + if ((hitag_function)c->arg[0] < 10) { + WritePageHitagS((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes,c->arg[2]); + } else if ((hitag_function)c->arg[0] >= 10) { + WriterHitag((hitag_function)c->arg[0],(hitag_data*)c->d.asBytes, c->arg[2]); + } + break; #endif #ifdef WITH_ISO15693 - case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693: - AcquireRawAdcSamplesIso15693(); - break; - case CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693: - RecordRawAdcSamplesIso15693(); - break; - case CMD_ISO_15693_COMMAND: - DirectTag15693Command(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_ISO_15693_FIND_AFI: - BruteforceIso15693Afi(c->arg[0]); - break; - case CMD_READER_ISO_15693: - ReaderIso15693(c->arg[0]); - break; - case CMD_SIMTAG_ISO_15693: - SimTagIso15693(c->arg[0], c->d.asBytes); - break; + case CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693: + AcquireRawAdcSamplesIso15693(); + break; + case CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693: + RecordRawAdcSamplesIso15693(); + break; + case CMD_ISO_15693_COMMAND: + DirectTag15693Command(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_ISO_15693_FIND_AFI: + BruteforceIso15693Afi(c->arg[0]); + break; + case CMD_READER_ISO_15693: + ReaderIso15693(c->arg[0]); + break; + case CMD_SIMTAG_ISO_15693: + SimTagIso15693(c->arg[0], c->d.asBytes); + break; #endif #ifdef WITH_LEGICRF - case CMD_SIMULATE_TAG_LEGIC_RF: - LegicRfSimulate(c->arg[0]); - break; - case CMD_WRITER_LEGIC_RF: - LegicRfWriter(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_READER_LEGIC_RF: - LegicRfReader(c->arg[0], c->arg[1], c->arg[2]); - break; - case CMD_LEGIC_INFO: - LegicRfInfo(); - break; - case CMD_LEGIC_ESET: - //----------------------------------------------------------------------------- - // Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not - // involved in dealing with emulator memory. But if it is called later, it might - // destroy the Emulator Memory. - //----------------------------------------------------------------------------- - // arg0 = offset - // arg1 = num of bytes - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - emlSet(c->d.asBytes, c->arg[0], c->arg[1]); - break; + case CMD_SIMULATE_TAG_LEGIC_RF: + LegicRfSimulate(c->arg[0]); + break; + case CMD_WRITER_LEGIC_RF: + LegicRfWriter(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_READER_LEGIC_RF: + LegicRfReader(c->arg[0], c->arg[1], c->arg[2]); + break; + case CMD_LEGIC_INFO: + LegicRfInfo(); + break; + case CMD_LEGIC_ESET: + //----------------------------------------------------------------------------- + // Note: we call FpgaDownloadAndGo(FPGA_BITSTREAM_HF) here although FPGA is not + // involved in dealing with emulator memory. But if it is called later, it might + // destroy the Emulator Memory. + //----------------------------------------------------------------------------- + // arg0 = offset + // arg1 = num of bytes + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + emlSet(c->d.asBytes, c->arg[0], c->arg[1]); + break; #endif #ifdef WITH_ISO14443b - case CMD_READ_SRI_TAG: - ReadSTMemoryIso14443b(c->arg[0]); - break; - case CMD_SNOOP_ISO_14443B: - SniffIso14443b(); - break; - case CMD_SIMULATE_TAG_ISO_14443B: - SimulateIso14443bTag(c->arg[0]); - break; - case CMD_ISO_14443B_COMMAND: - //SendRawCommand14443B(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes); - SendRawCommand14443B_Ex(c); - break; + case CMD_READ_SRI_TAG: + ReadSTMemoryIso14443b(c->arg[0]); + break; + case CMD_SNOOP_ISO_14443B: + SniffIso14443b(); + break; + case CMD_SIMULATE_TAG_ISO_14443B: + SimulateIso14443bTag(c->arg[0]); + break; + case CMD_ISO_14443B_COMMAND: + //SendRawCommand14443B(c->arg[0],c->arg[1],c->arg[2],c->d.asBytes); + SendRawCommand14443B_Ex(c); + break; #endif #ifdef WITH_FELICA - case CMD_FELICA_COMMAND: - felica_sendraw(c); - break; + case CMD_FELICA_COMMAND: + felica_sendraw(c); + break; case CMD_FELICA_LITE_SIM: felica_sim_lite(c->arg[0]); break; @@ -862,701 +862,701 @@ void UsbPacketReceived(uint8_t *packet, int len) { felica_sniff(c->arg[0], c->arg[1]); break; case CMD_FELICA_LITE_DUMP: - felica_dump_lite_s(); + felica_dump_lite_s(); break; #endif #ifdef WITH_ISO14443a - case CMD_SNOOP_ISO_14443a: - SniffIso14443a(c->arg[0]); - break; - case CMD_READER_ISO_14443a: - ReaderIso14443a(c); - break; - case CMD_SIMULATE_TAG_ISO_14443a: - SimulateIso14443aTag(c->arg[0], c->arg[1], c->d.asBytes); // ## Simulate iso14443a tag - pass tag type & UID - break; - case CMD_ANTIFUZZ_ISO_14443a: - iso14443a_antifuzz(c->arg[0]); - break; - case CMD_EPA_PACE_COLLECT_NONCE: - EPA_PACE_Collect_Nonce(c); - break; - case CMD_EPA_PACE_REPLAY: - EPA_PACE_Replay(c); - break; - case CMD_READER_MIFARE: + case CMD_SNOOP_ISO_14443a: + SniffIso14443a(c->arg[0]); + break; + case CMD_READER_ISO_14443a: + ReaderIso14443a(c); + break; + case CMD_SIMULATE_TAG_ISO_14443a: + SimulateIso14443aTag(c->arg[0], c->arg[1], c->d.asBytes); // ## Simulate iso14443a tag - pass tag type & UID + break; + case CMD_ANTIFUZZ_ISO_14443a: + iso14443a_antifuzz(c->arg[0]); + break; + case CMD_EPA_PACE_COLLECT_NONCE: + EPA_PACE_Collect_Nonce(c); + break; + case CMD_EPA_PACE_REPLAY: + EPA_PACE_Replay(c); + break; + case CMD_READER_MIFARE: ReaderMifare(c->arg[0], c->arg[1], c->arg[2]); - break; - case CMD_MIFARE_READBL: - MifareReadBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_MIFAREU_READBL: - MifareUReadBlock(c->arg[0],c->arg[1], c->d.asBytes); - break; - case CMD_MIFAREUC_AUTH: - MifareUC_Auth(c->arg[0],c->d.asBytes); - break; - case CMD_MIFAREU_READCARD: - MifareUReadCard(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_MIFAREUC_SETPWD: - MifareUSetPwd(c->arg[0], c->d.asBytes); - break; - case CMD_MIFARE_READSC: - MifareReadSector(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_MIFARE_WRITEBL: - MifareWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - //case CMD_MIFAREU_WRITEBL_COMPAT: - //MifareUWriteBlockCompat(c->arg[0], c->d.asBytes); - //break; - case CMD_MIFAREU_WRITEBL: - MifareUWriteBlock(c->arg[0], c->arg[1], c->d.asBytes); - break; - case CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES: - MifareAcquireEncryptedNonces(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_MIFARE_ACQUIRE_NONCES: - MifareAcquireNonces(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_MIFARE_NESTED: - MifareNested(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_MIFARE_CHKKEYS: { - MifareChkKeys(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - } - case CMD_MIFARE_CHKKEYS_FAST: { - MifareChkKeys_fast(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - } - case CMD_SIMULATE_MIFARE_CARD: - Mifare1ksim(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; + break; + case CMD_MIFARE_READBL: + MifareReadBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_MIFAREU_READBL: + MifareUReadBlock(c->arg[0],c->arg[1], c->d.asBytes); + break; + case CMD_MIFAREUC_AUTH: + MifareUC_Auth(c->arg[0],c->d.asBytes); + break; + case CMD_MIFAREU_READCARD: + MifareUReadCard(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_MIFAREUC_SETPWD: + MifareUSetPwd(c->arg[0], c->d.asBytes); + break; + case CMD_MIFARE_READSC: + MifareReadSector(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_MIFARE_WRITEBL: + MifareWriteBlock(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + //case CMD_MIFAREU_WRITEBL_COMPAT: + //MifareUWriteBlockCompat(c->arg[0], c->d.asBytes); + //break; + case CMD_MIFAREU_WRITEBL: + MifareUWriteBlock(c->arg[0], c->arg[1], c->d.asBytes); + break; + case CMD_MIFARE_ACQUIRE_ENCRYPTED_NONCES: + MifareAcquireEncryptedNonces(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_MIFARE_ACQUIRE_NONCES: + MifareAcquireNonces(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_MIFARE_NESTED: + MifareNested(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_MIFARE_CHKKEYS: { + MifareChkKeys(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + } + case CMD_MIFARE_CHKKEYS_FAST: { + MifareChkKeys_fast(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + } + case CMD_SIMULATE_MIFARE_CARD: + Mifare1ksim(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; - // emulator - case CMD_MIFARE_SET_DBGMODE: - MifareSetDbgLvl(c->arg[0]); - break; - case CMD_MIFARE_EML_MEMCLR: - MifareEMemClr(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_MIFARE_EML_MEMSET: - MifareEMemSet(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_MIFARE_EML_MEMGET: - MifareEMemGet(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_MIFARE_EML_CARDLOAD: - MifareECardLoad(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; + // emulator + case CMD_MIFARE_SET_DBGMODE: + MifareSetDbgLvl(c->arg[0]); + break; + case CMD_MIFARE_EML_MEMCLR: + MifareEMemClr(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_MIFARE_EML_MEMSET: + MifareEMemSet(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_MIFARE_EML_MEMGET: + MifareEMemGet(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_MIFARE_EML_CARDLOAD: + MifareECardLoad(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; - // Work with "magic Chinese" card - case CMD_MIFARE_CSETBLOCK: - MifareCSetBlock(c->arg[0], c->arg[1], c->d.asBytes); - break; - case CMD_MIFARE_CGETBLOCK: - MifareCGetBlock(c->arg[0], c->arg[1], c->d.asBytes); - break; - case CMD_MIFARE_CIDENT: - MifareCIdent(); - break; - // mifare sniffer -// case CMD_MIFARE_SNIFFER: - //SniffMifare(c->arg[0]); -// break; - case CMD_MIFARE_SETMOD: - MifareSetMod(c->arg[0], c->d.asBytes); - break; - //mifare desfire - case CMD_MIFARE_DESFIRE_READBL: - break; - case CMD_MIFARE_DESFIRE_WRITEBL: - break; - case CMD_MIFARE_DESFIRE_AUTH1: - MifareDES_Auth1(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_MIFARE_DESFIRE_AUTH2: - //MifareDES_Auth2(c->arg[0],c->d.asBytes); - break; - case CMD_MIFARE_DES_READER: - //readermifaredes(c->arg[0], c->arg[1], c->d.asBytes); - break; - case CMD_MIFARE_DESFIRE_INFO: - MifareDesfireGetInformation(); - break; - case CMD_MIFARE_DESFIRE: - MifareSendCommand(c->arg[0], c->arg[1], c->d.asBytes); - break; - case CMD_MIFARE_COLLECT_NONCES: - break; - case CMD_MIFARE_NACK_DETECT: - DetectNACKbug(); - break; + // Work with "magic Chinese" card + case CMD_MIFARE_CSETBLOCK: + MifareCSetBlock(c->arg[0], c->arg[1], c->d.asBytes); + break; + case CMD_MIFARE_CGETBLOCK: + MifareCGetBlock(c->arg[0], c->arg[1], c->d.asBytes); + break; + case CMD_MIFARE_CIDENT: + MifareCIdent(); + break; + // mifare sniffer +// case CMD_MIFARE_SNIFFER: +// SniffMifare(c->arg[0]); +// break; + case CMD_MIFARE_SETMOD: + MifareSetMod(c->arg[0], c->d.asBytes); + break; + //mifare desfire + case CMD_MIFARE_DESFIRE_READBL: + break; + case CMD_MIFARE_DESFIRE_WRITEBL: + break; + case CMD_MIFARE_DESFIRE_AUTH1: + MifareDES_Auth1(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_MIFARE_DESFIRE_AUTH2: + //MifareDES_Auth2(c->arg[0],c->d.asBytes); + break; + case CMD_MIFARE_DES_READER: + //readermifaredes(c->arg[0], c->arg[1], c->d.asBytes); + break; + case CMD_MIFARE_DESFIRE_INFO: + MifareDesfireGetInformation(); + break; + case CMD_MIFARE_DESFIRE: + MifareSendCommand(c->arg[0], c->arg[1], c->d.asBytes); + break; + case CMD_MIFARE_COLLECT_NONCES: + break; + case CMD_MIFARE_NACK_DETECT: + DetectNACKbug(); + break; #endif #ifdef WITH_ICLASS - // Makes use of ISO14443a FPGA Firmware - case CMD_SNOOP_ICLASS: - SniffIClass(); - break; - case CMD_SIMULATE_TAG_ICLASS: - SimulateIClass(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); - break; - case CMD_READER_ICLASS: - ReaderIClass(c->arg[0]); - break; - case CMD_READER_ICLASS_REPLAY: - ReaderIClass_Replay(c->arg[0], c->d.asBytes); - break; - case CMD_ICLASS_EML_MEMSET: - //iceman, should call FPGADOWNLOAD before, since it corrupts BigBuf - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - emlSet(c->d.asBytes, c->arg[0], c->arg[1]); - break; - case CMD_ICLASS_WRITEBLOCK: - iClass_WriteBlock(c->arg[0], c->d.asBytes); - break; - case CMD_ICLASS_READCHECK: // auth step 1 - iClass_ReadCheck(c->arg[0], c->arg[1]); - break; - case CMD_ICLASS_READBLOCK: - iClass_ReadBlk(c->arg[0]); - break; - case CMD_ICLASS_AUTHENTICATION: //check - iClass_Authentication(c->d.asBytes); - break; - case CMD_ICLASS_CHECK_KEYS: - iClass_Authentication_fast(c->arg[0], c->arg[1], c->d.asBytes); - break; - case CMD_ICLASS_DUMP: - iClass_Dump(c->arg[0], c->arg[1]); - break; - case CMD_ICLASS_CLONE: - iClass_Clone(c->arg[0], c->arg[1], c->d.asBytes); - break; + // Makes use of ISO14443a FPGA Firmware + case CMD_SNOOP_ICLASS: + SniffIClass(); + break; + case CMD_SIMULATE_TAG_ICLASS: + SimulateIClass(c->arg[0], c->arg[1], c->arg[2], c->d.asBytes); + break; + case CMD_READER_ICLASS: + ReaderIClass(c->arg[0]); + break; + case CMD_READER_ICLASS_REPLAY: + ReaderIClass_Replay(c->arg[0], c->d.asBytes); + break; + case CMD_ICLASS_EML_MEMSET: + //iceman, should call FPGADOWNLOAD before, since it corrupts BigBuf + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + emlSet(c->d.asBytes, c->arg[0], c->arg[1]); + break; + case CMD_ICLASS_WRITEBLOCK: + iClass_WriteBlock(c->arg[0], c->d.asBytes); + break; + case CMD_ICLASS_READCHECK: // auth step 1 + iClass_ReadCheck(c->arg[0], c->arg[1]); + break; + case CMD_ICLASS_READBLOCK: + iClass_ReadBlk(c->arg[0]); + break; + case CMD_ICLASS_AUTHENTICATION: //check + iClass_Authentication(c->d.asBytes); + break; + case CMD_ICLASS_CHECK_KEYS: + iClass_Authentication_fast(c->arg[0], c->arg[1], c->d.asBytes); + break; + case CMD_ICLASS_DUMP: + iClass_Dump(c->arg[0], c->arg[1]); + break; + case CMD_ICLASS_CLONE: + iClass_Clone(c->arg[0], c->arg[1], c->d.asBytes); + break; #endif #ifdef WITH_HFSNOOP - case CMD_HF_SNIFFER: - HfSnoop(c->arg[0], c->arg[1]); - break; + case CMD_HF_SNIFFER: + HfSnoop(c->arg[0], c->arg[1]); + break; #endif #ifdef WITH_SMARTCARD - case CMD_SMART_ATR: { - SmartCardAtr(); - break; - } - case CMD_SMART_SETBAUD:{ - SmartCardSetBaud(c->arg[0]); - break; - } - case CMD_SMART_SETCLOCK:{ - SmartCardSetClock(c->arg[0]); - break; - } - case CMD_SMART_RAW: { - SmartCardRaw(c->arg[0], c->arg[1], c->d.asBytes); + case CMD_SMART_ATR: { + SmartCardAtr(); break; } - case CMD_SMART_UPLOAD: { - // upload file from client - uint8_t *mem = BigBuf_get_addr(); - memcpy( mem + c->arg[0], c->d.asBytes, USB_CMD_DATA_SIZE); - cmd_send(CMD_ACK,1,0,0,0,0); - break; - } - case CMD_SMART_UPGRADE: { - SmartCardUpgrade(c->arg[0]); + case CMD_SMART_SETBAUD:{ + SmartCardSetBaud(c->arg[0]); break; - } + } + case CMD_SMART_SETCLOCK:{ + SmartCardSetClock(c->arg[0]); + break; + } + case CMD_SMART_RAW: { + SmartCardRaw(c->arg[0], c->arg[1], c->d.asBytes); + break; + } + case CMD_SMART_UPLOAD: { + // upload file from client + uint8_t *mem = BigBuf_get_addr(); + memcpy( mem + c->arg[0], c->d.asBytes, USB_CMD_DATA_SIZE); + cmd_send(CMD_ACK,1,0,0,0,0); + break; + } + case CMD_SMART_UPGRADE: { + SmartCardUpgrade(c->arg[0]); + break; + } #endif #ifdef WITH_FPC - case CMD_FPC_SEND: { + case CMD_FPC_SEND: { - StartTicks(); - DbpString("Mutual USB/FPC sending from device to client"); + StartTicks(); + DbpString("Mutual USB/FPC sending from device to client"); - /* - char at[11] = {'\0'}; - static const char* s_at = "AT+BAUD8\0D\0A"; - strncat(at, s_at, sizeof(at) - strlen(at) - 1); - DbpString("Try AT baud rate setting"); - usart_init(); - int16_t res = usart_writebuffer((uint8_t*)&at, sizeof(at)); - WaitMS(1); - Dbprintf("SEND %d | %c%c%c%c%c%c%c%c%c%c%c", res, at[0], at[1], at[2], at[3], at[4], at[5], at[6], at[7], at[8], at[9], at[10]); + /* + char at[11] = {'\0'}; + static const char* s_at = "AT+BAUD8\0D\0A"; + strncat(at, s_at, sizeof(at) - strlen(at) - 1); + DbpString("Try AT baud rate setting"); + usart_init(); + int16_t res = usart_writebuffer((uint8_t*)&at, sizeof(at)); + WaitMS(1); + Dbprintf("SEND %d | %c%c%c%c%c%c%c%c%c%c%c", res, at[0], at[1], at[2], at[3], at[4], at[5], at[6], at[7], at[8], at[9], at[10]); - uint8_t my_rx[20]; - memset(my_rx, 0, sizeof(my_rx)); - res = usart_readbuffer(my_rx, sizeof(my_rx)); - WaitMS(1); - Dbprintf("GOT %d | %c%c%c%c%c%c%c%c", res, my_rx[0], my_rx[1], my_rx[2], my_rx[3], my_rx[4], my_rx[5], my_rx[6], my_rx[7]); - */ + uint8_t my_rx[20]; + memset(my_rx, 0, sizeof(my_rx)); + res = usart_readbuffer(my_rx, sizeof(my_rx)); + WaitMS(1); + Dbprintf("GOT %d | %c%c%c%c%c%c%c%c", res, my_rx[0], my_rx[1], my_rx[2], my_rx[3], my_rx[4], my_rx[5], my_rx[6], my_rx[7]); + */ - char dest[USB_CMD_DATA_SIZE] = { '\0' }; - static const char* welcome = "Proxmark3 Serial interface via FPC ready\n"; - strncat(dest, welcome, sizeof(dest) - strlen(dest) - 1); - sprintf(dest + strlen(dest) - 1, "| bytes 0x%02x 0x%02x 0x%02x 0x%02x \n" - , c->d.asBytes[0] - , c->d.asBytes[1] - , c->d.asBytes[2] - , c->d.asBytes[3] - ); + char dest[USB_CMD_DATA_SIZE] = { '\0' }; + static const char* welcome = "Proxmark3 Serial interface via FPC ready\n"; + strncat(dest, welcome, sizeof(dest) - strlen(dest) - 1); + sprintf(dest + strlen(dest) - 1, "| bytes 0x%02x 0x%02x 0x%02x 0x%02x \n" + , c->d.asBytes[0] + , c->d.asBytes[1] + , c->d.asBytes[2] + , c->d.asBytes[3] + ); - UsbCommand txcmd = { CMD_DEBUG_PRINT_STRING, { strlen(dest), 0, 0 } }; - memcpy(txcmd.d.asBytes, dest, sizeof(dest)); + UsbCommand txcmd = { CMD_DEBUG_PRINT_STRING, { strlen(dest), 0, 0 } }; + memcpy(txcmd.d.asBytes, dest, sizeof(dest)); - LED_A_ON(); + LED_A_ON(); - usart_init(); - usart_writebuffer((uint8_t*)&txcmd, sizeof(UsbCommand)); + usart_init(); + usart_writebuffer((uint8_t*)&txcmd, sizeof(UsbCommand)); - //usb - cmd_send(CMD_DEBUG_PRINT_STRING, strlen(dest), 0, 0, dest, strlen(dest)); - LED_A_OFF(); + //usb + cmd_send(CMD_DEBUG_PRINT_STRING, strlen(dest), 0, 0, dest, strlen(dest)); + LED_A_OFF(); - /* - uint8_t my_rx[sizeof(UsbCommand)]; - while (!BUTTON_PRESS() && !usb_poll_validate_length()) { - LED_B_INV(); - if (usart_readbuffer(my_rx, sizeof(UsbCommand)) ) { - //UsbPacketReceived(my_rx, sizeof(my_rx)); + /* + uint8_t my_rx[sizeof(UsbCommand)]; + while (!BUTTON_PRESS() && !usb_poll_validate_length()) { + LED_B_INV(); + if (usart_readbuffer(my_rx, sizeof(UsbCommand)) ) { + //UsbPacketReceived(my_rx, sizeof(my_rx)); - UsbCommand *my = (UsbCommand *)my_rx; - if (mc->cmd > 0 ) { - Dbprintf("received command: 0x%04x and args: %d %d %d", my->cmd, my->arg[0], my->arg[1], my->arg[2]); - } - } - } - */ + UsbCommand *my = (UsbCommand *)my_rx; + if (mc->cmd > 0 ) { + Dbprintf("received command: 0x%04x and args: %d %d %d", my->cmd, my->arg[0], my->arg[1], my->arg[2]); + } + } + } + */ - //cmd_send(CMD_DEBUG_PRINT_STRING, strlen(dest), 0, 0, dest, strlen(dest)); + //cmd_send(CMD_DEBUG_PRINT_STRING, strlen(dest), 0, 0, dest, strlen(dest)); - cmd_send(CMD_ACK,0,0,0,0,0); - StopTicks(); - break; - } + cmd_send(CMD_ACK,0,0,0,0,0); + StopTicks(); + break; + } #endif - case CMD_BUFF_CLEAR: - BigBuf_Clear(); - BigBuf_free(); - break; + case CMD_BUFF_CLEAR: + BigBuf_Clear(); + BigBuf_free(); + break; - case CMD_MEASURE_ANTENNA_TUNING: - MeasureAntennaTuning(); - break; + case CMD_MEASURE_ANTENNA_TUNING: + MeasureAntennaTuning(); + break; - case CMD_MEASURE_ANTENNA_TUNING_HF: - MeasureAntennaTuningHf(); - break; + case CMD_MEASURE_ANTENNA_TUNING_HF: + MeasureAntennaTuningHf(); + break; - case CMD_LISTEN_READER_FIELD: - ListenReaderField(c->arg[0]); - break; + case CMD_LISTEN_READER_FIELD: + ListenReaderField(c->arg[0]); + break; - case CMD_FPGA_MAJOR_MODE_OFF: // ## FPGA Control - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelay(200); - LED_D_OFF(); // LED D indicates field ON or OFF - break; + case CMD_FPGA_MAJOR_MODE_OFF: // ## FPGA Control + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(200); + LED_D_OFF(); // LED D indicates field ON or OFF + break; #ifdef WITH_LF - case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K: { - LED_B_ON(); - uint8_t *mem = BigBuf_get_addr(); - bool isok = false; - size_t len = 0; - uint32_t startidx = c->arg[0]; - uint32_t numofbytes = c->arg[1]; - // arg0 = startindex - // arg1 = length bytes to transfer - // arg2 = BigBuf tracelen - //Dbprintf("transfer to client parameters: %" PRIu32 " | %" PRIu32 " | %" PRIu32, startidx, numofbytes, c->arg[2]); + case CMD_DOWNLOAD_RAW_ADC_SAMPLES_125K: { + LED_B_ON(); + uint8_t *mem = BigBuf_get_addr(); + bool isok = false; + size_t len = 0; + uint32_t startidx = c->arg[0]; + uint32_t numofbytes = c->arg[1]; + // arg0 = startindex + // arg1 = length bytes to transfer + // arg2 = BigBuf tracelen + //Dbprintf("transfer to client parameters: %" PRIu32 " | %" PRIu32 " | %" PRIu32, startidx, numofbytes, c->arg[2]); - for(size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { - len = MIN( (numofbytes - i), USB_CMD_DATA_SIZE); - isok = cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, i, len, BigBuf_get_traceLen(), mem + startidx + i, len); - if (isok != 0) - Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len); - } - // Trigger a finish downloading signal with an ACK frame - // iceman, when did sending samplingconfig array got attached here?!? - // arg0 = status of download transfer - // arg1 = RFU - // arg2 = tracelen? - // asbytes = samplingconfig array - cmd_send(CMD_ACK, 1, 0, BigBuf_get_traceLen(), getSamplingConfig(), sizeof(sample_config)); - LED_B_OFF(); - break; - } + for(size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { + len = MIN( (numofbytes - i), USB_CMD_DATA_SIZE); + isok = cmd_send(CMD_DOWNLOADED_RAW_ADC_SAMPLES_125K, i, len, BigBuf_get_traceLen(), mem + startidx + i, len); + if (isok != 0) + Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len); + } + // Trigger a finish downloading signal with an ACK frame + // iceman, when did sending samplingconfig array got attached here?!? + // arg0 = status of download transfer + // arg1 = RFU + // arg2 = tracelen? + // asbytes = samplingconfig array + cmd_send(CMD_ACK, 1, 0, BigBuf_get_traceLen(), getSamplingConfig(), sizeof(sample_config)); + LED_B_OFF(); + break; + } #endif - case CMD_UPLOAD_SIM_SAMPLES_125K: { - // iceman; since changing fpga_bitstreams clears bigbuff, Its better to call it before. - // to be able to use this one for uploading data to device - // arg1 = 0 upload for LF usage - // 1 upload for HF usage - #define FPGA_LF 1 - if ( c->arg[1] == FPGA_LF ) - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - else - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + case CMD_UPLOAD_SIM_SAMPLES_125K: { + // iceman; since changing fpga_bitstreams clears bigbuff, Its better to call it before. + // to be able to use this one for uploading data to device + // arg1 = 0 upload for LF usage + // 1 upload for HF usage + #define FPGA_LF 1 + if ( c->arg[1] == FPGA_LF ) + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + else + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - uint8_t *mem = BigBuf_get_addr(); - memcpy( mem + c->arg[0], c->d.asBytes, USB_CMD_DATA_SIZE); - cmd_send(CMD_ACK,1,0,0,0,0); - break; - } - case CMD_DOWNLOAD_EML_BIGBUF: { - LED_B_ON(); - uint8_t *mem = BigBuf_get_EM_addr(); - bool isok = false; - size_t len = 0; - uint32_t startidx = c->arg[0]; - uint32_t numofbytes = c->arg[1]; + uint8_t *mem = BigBuf_get_addr(); + memcpy( mem + c->arg[0], c->d.asBytes, USB_CMD_DATA_SIZE); + cmd_send(CMD_ACK,1,0,0,0,0); + break; + } + case CMD_DOWNLOAD_EML_BIGBUF: { + LED_B_ON(); + uint8_t *mem = BigBuf_get_EM_addr(); + bool isok = false; + size_t len = 0; + uint32_t startidx = c->arg[0]; + uint32_t numofbytes = c->arg[1]; - // arg0 = startindex - // arg1 = length bytes to transfer - // arg2 = RFU + // arg0 = startindex + // arg1 = length bytes to transfer + // arg2 = RFU - for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { - len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); - isok = cmd_send(CMD_DOWNLOADED_EML_BIGBUF, i, len, 0, mem + startidx + i, len); - if (isok != 0) - Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len); - } - // Trigger a finish downloading signal with an ACK frame - cmd_send(CMD_ACK, 1, 0, 0, 0, 0); - LED_B_OFF(); - break; - } - case CMD_READ_MEM: - ReadMem(c->arg[0]); - break; + for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { + len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); + isok = cmd_send(CMD_DOWNLOADED_EML_BIGBUF, i, len, 0, mem + startidx + i, len); + if (isok != 0) + Dbprintf("transfer to client failed :: | bytes between %d - %d (%d)", i, i+len, len); + } + // Trigger a finish downloading signal with an ACK frame + cmd_send(CMD_ACK, 1, 0, 0, 0, 0); + LED_B_OFF(); + break; + } + case CMD_READ_MEM: + ReadMem(c->arg[0]); + break; #ifdef WITH_FLASH - case CMD_FLASHMEM_SET_SPIBAUDRATE: - FlashmemSetSpiBaudrate(c->arg[0]); - break; - case CMD_FLASHMEM_READ: { - LED_B_ON(); - uint16_t isok = 0; - uint32_t startidx = c->arg[0]; - uint16_t len = c->arg[1]; + case CMD_FLASHMEM_SET_SPIBAUDRATE: + FlashmemSetSpiBaudrate(c->arg[0]); + break; + case CMD_FLASHMEM_READ: { + LED_B_ON(); + uint16_t isok = 0; + uint32_t startidx = c->arg[0]; + uint16_t len = c->arg[1]; - Dbprintf("FlashMem read | %d - %d | ", startidx, len); + Dbprintf("FlashMem read | %d - %d | ", startidx, len); - size_t size = MIN(USB_CMD_DATA_SIZE, len); + size_t size = MIN(USB_CMD_DATA_SIZE, len); - if (!FlashInit()) { - break; - } + if (!FlashInit()) { + break; + } - uint8_t *mem = BigBuf_malloc(size); + uint8_t *mem = BigBuf_malloc(size); - for(size_t i = 0; i < len; i += size) { - len = MIN((len - i), size); + for(size_t i = 0; i < len; i += size) { + len = MIN((len - i), size); - Dbprintf("FlashMem reading | %d | %d | %d |", startidx + i, i, len); - isok = Flash_ReadDataCont(startidx + i, mem, len); - if ( isok == len ) { - print_result("Chunk: ", mem, len); - } else { - Dbprintf("FlashMem reading failed | %d | %d", len, isok); - break; - } - } - BigBuf_free(); - FlashStop(); - LED_B_OFF(); - break; - } - case CMD_FLASHMEM_WRITE: { - LED_B_ON(); - uint8_t isok = 0; - uint16_t res = 0; - uint32_t startidx = c->arg[0]; - uint16_t len = c->arg[1]; - uint8_t* data = c->d.asBytes; + Dbprintf("FlashMem reading | %d | %d | %d |", startidx + i, i, len); + isok = Flash_ReadDataCont(startidx + i, mem, len); + if ( isok == len ) { + print_result("Chunk: ", mem, len); + } else { + Dbprintf("FlashMem reading failed | %d | %d", len, isok); + break; + } + } + BigBuf_free(); + FlashStop(); + LED_B_OFF(); + break; + } + case CMD_FLASHMEM_WRITE: { + LED_B_ON(); + uint8_t isok = 0; + uint16_t res = 0; + uint32_t startidx = c->arg[0]; + uint16_t len = c->arg[1]; + uint8_t* data = c->d.asBytes; - uint32_t tmp = startidx + len; + uint32_t tmp = startidx + len; - if (!FlashInit()) { - break; - } + if (!FlashInit()) { + break; + } - Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); - if ( startidx == DEFAULT_T55XX_KEYS_OFFSET ) - Flash_Erase4k(3, 0xC); - else if (startidx == DEFAULT_MF_KEYS_OFFSET ) - Flash_Erase4k(3, 0xB); - else if (startidx == DEFAULT_ICLASS_KEYS_OFFSET) - Flash_Erase4k(3, 0xA); + if ( startidx == DEFAULT_T55XX_KEYS_OFFSET ) + Flash_Erase4k(3, 0xC); + else if (startidx == DEFAULT_MF_KEYS_OFFSET ) + Flash_Erase4k(3, 0xB); + else if (startidx == DEFAULT_ICLASS_KEYS_OFFSET) + Flash_Erase4k(3, 0xA); - Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); - // inside 256b page? - if ( (tmp & 0xFF) != 0) { + // inside 256b page? + if ( (tmp & 0xFF) != 0) { - // is offset+len larger than a page - tmp = (startidx & 0xFF ) + len; - if (tmp > 0xFF ) { + // is offset+len larger than a page + tmp = (startidx & 0xFF ) + len; + if (tmp > 0xFF ) { - // data spread over two pages. + // data spread over two pages. - // offset xxxx10, - uint8_t first_len = (~startidx & 0xFF)+1; + // offset xxxx10, + uint8_t first_len = (~startidx & 0xFF)+1; - // first mem page - res = Flash_WriteDataCont(startidx, data, first_len); + // first mem page + res = Flash_WriteDataCont(startidx, data, first_len); - // second mem page - res = Flash_WriteDataCont(startidx + first_len, data + first_len, len - first_len); + // second mem page + res = Flash_WriteDataCont(startidx + first_len, data + first_len, len - first_len); - isok = (res == (len - first_len)) ? 1 : 0; + isok = (res == (len - first_len)) ? 1 : 0; - } else { - res = Flash_WriteDataCont(startidx, data, len); - isok = (res == len) ? 1 : 0; - } - } else { - res = Flash_WriteDataCont(startidx, data, len); - isok = (res == len) ? 1 : 0; - } - FlashStop(); + } else { + res = Flash_WriteDataCont(startidx, data, len); + isok = (res == len) ? 1 : 0; + } + } else { + res = Flash_WriteDataCont(startidx, data, len); + isok = (res == len) ? 1 : 0; + } + FlashStop(); - cmd_send(CMD_ACK, isok, 0, 0, 0, 0); - LED_B_OFF(); - break; - } - case CMD_FLASHMEM_WIPE: { - LED_B_ON(); - uint8_t page = c->arg[0]; - uint8_t initalwipe = c->arg[1]; - bool isok = false; - if ( initalwipe ) { - isok = Flash_WipeMemory(); - cmd_send(CMD_ACK, isok, 0, 0, 0, 0); - LED_B_OFF(); - break; - } - if ( page < 3) - isok = Flash_WipeMemoryPage(page); + cmd_send(CMD_ACK, isok, 0, 0, 0, 0); + LED_B_OFF(); + break; + } + case CMD_FLASHMEM_WIPE: { + LED_B_ON(); + uint8_t page = c->arg[0]; + uint8_t initalwipe = c->arg[1]; + bool isok = false; + if ( initalwipe ) { + isok = Flash_WipeMemory(); + cmd_send(CMD_ACK, isok, 0, 0, 0, 0); + LED_B_OFF(); + break; + } + if ( page < 3) + isok = Flash_WipeMemoryPage(page); - cmd_send(CMD_ACK, isok, 0, 0, 0, 0); - LED_B_OFF(); - break; - } - case CMD_FLASHMEM_DOWNLOAD: { + cmd_send(CMD_ACK, isok, 0, 0, 0, 0); + LED_B_OFF(); + break; + } + case CMD_FLASHMEM_DOWNLOAD: { - LED_B_ON(); - uint8_t *mem = BigBuf_malloc(USB_CMD_DATA_SIZE); - bool isok = false; - size_t len = 0; - uint32_t startidx = c->arg[0]; - uint32_t numofbytes = c->arg[1]; - // arg0 = startindex - // arg1 = length bytes to transfer - // arg2 = RFU + LED_B_ON(); + uint8_t *mem = BigBuf_malloc(USB_CMD_DATA_SIZE); + bool isok = false; + size_t len = 0; + uint32_t startidx = c->arg[0]; + uint32_t numofbytes = c->arg[1]; + // arg0 = startindex + // arg1 = length bytes to transfer + // arg2 = RFU - if (!FlashInit()) { - break; - } + if (!FlashInit()) { + break; + } - for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { - len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); + for (size_t i = 0; i < numofbytes; i += USB_CMD_DATA_SIZE) { + len = MIN((numofbytes - i), USB_CMD_DATA_SIZE); - isok = Flash_ReadDataCont(startidx + i, mem, len); - if (!isok ) - Dbprintf("reading flash memory failed :: | bytes between %d - %d", i, len); + isok = Flash_ReadDataCont(startidx + i, mem, len); + if (!isok ) + Dbprintf("reading flash memory failed :: | bytes between %d - %d", i, len); - isok = cmd_send(CMD_FLASHMEM_DOWNLOADED, i, len, 0, mem, len); - if (isok != 0) - Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); - } - FlashStop(); + isok = cmd_send(CMD_FLASHMEM_DOWNLOADED, i, len, 0, mem, len); + if (isok != 0) + Dbprintf("transfer to client failed :: | bytes between %d - %d", i, len); + } + FlashStop(); - cmd_send(CMD_ACK, 1, 0, 0, 0, 0); - LED_B_OFF(); - break; - } - case CMD_FLASHMEM_INFO: { + cmd_send(CMD_ACK, 1, 0, 0, 0, 0); + LED_B_OFF(); + break; + } + case CMD_FLASHMEM_INFO: { - LED_B_ON(); - rdv40_validation_t *info = (rdv40_validation_t*)BigBuf_malloc( sizeof(rdv40_validation_t) ); + LED_B_ON(); + rdv40_validation_t *info = (rdv40_validation_t*)BigBuf_malloc( sizeof(rdv40_validation_t) ); - bool isok = Flash_ReadData(FLASH_MEM_SIGNATURE_OFFSET, info->signature, FLASH_MEM_SIGNATURE_LEN); + bool isok = Flash_ReadData(FLASH_MEM_SIGNATURE_OFFSET, info->signature, FLASH_MEM_SIGNATURE_LEN); - if (FlashInit()) { - Flash_UniqueID( info->flashid); - FlashStop(); - } - cmd_send(CMD_ACK, isok, 0, 0, info, sizeof(rdv40_validation_t)); - BigBuf_free(); + if (FlashInit()) { + Flash_UniqueID( info->flashid); + FlashStop(); + } + cmd_send(CMD_ACK, isok, 0, 0, info, sizeof(rdv40_validation_t)); + BigBuf_free(); - LED_B_OFF(); - break; - } + LED_B_OFF(); + break; + } #endif - case CMD_SET_LF_DIVISOR: - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->arg[0]); - break; + case CMD_SET_LF_DIVISOR: + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, c->arg[0]); + break; - case CMD_SET_ADC_MUX: - switch(c->arg[0]) { - case 0: SetAdcMuxFor(GPIO_MUXSEL_LOPKD); break; - case 2: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); break; + case CMD_SET_ADC_MUX: + switch(c->arg[0]) { + case 0: SetAdcMuxFor(GPIO_MUXSEL_LOPKD); break; + case 2: SetAdcMuxFor(GPIO_MUXSEL_HIPKD); break; #ifndef WITH_FPC - case 1: SetAdcMuxFor(GPIO_MUXSEL_LORAW); break; - case 3: SetAdcMuxFor(GPIO_MUXSEL_HIRAW); break; + case 1: SetAdcMuxFor(GPIO_MUXSEL_LORAW); break; + case 3: SetAdcMuxFor(GPIO_MUXSEL_HIRAW); break; #endif - } - break; + } + break; - case CMD_VERSION: - SendVersion(); - break; - case CMD_STATUS: - SendStatus(); - break; - case CMD_PING: - cmd_send(CMD_ACK,0,0,0,0,0); - break; + case CMD_VERSION: + SendVersion(); + break; + case CMD_STATUS: + SendStatus(); + break; + case CMD_PING: + cmd_send(CMD_ACK,0,0,0,0,0); + break; #ifdef WITH_LCD - case CMD_LCD_RESET: - LCDReset(); - break; - case CMD_LCD: - LCDSend(c->arg[0]); - break; + case CMD_LCD_RESET: + LCDReset(); + break; + case CMD_LCD: + LCDSend(c->arg[0]); + break; #endif - case CMD_SETUP_WRITE: - case CMD_FINISH_WRITE: - case CMD_HARDWARE_RESET: - usb_disable(); + case CMD_SETUP_WRITE: + case CMD_FINISH_WRITE: + case CMD_HARDWARE_RESET: + usb_disable(); - // (iceman) why this wait? - SpinDelay(1000); - AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; - // We're going to reset, and the bootrom will take control. - for(;;) {} - break; + // (iceman) why this wait? + SpinDelay(1000); + AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; + // We're going to reset, and the bootrom will take control. + for(;;) {} + break; - case CMD_START_FLASH: - if(common_area.flags.bootrom_present) { - common_area.command = COMMON_AREA_COMMAND_ENTER_FLASH_MODE; - } - usb_disable(); - AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; - // We're going to flash, and the bootrom will take control. - for(;;) {} - break; + case CMD_START_FLASH: + if(common_area.flags.bootrom_present) { + common_area.command = COMMON_AREA_COMMAND_ENTER_FLASH_MODE; + } + usb_disable(); + AT91C_BASE_RSTC->RSTC_RCR = RST_CONTROL_KEY | AT91C_RSTC_PROCRST; + // We're going to flash, and the bootrom will take control. + for(;;) {} + break; - case CMD_DEVICE_INFO: { - uint32_t dev_info = DEVICE_INFO_FLAG_OSIMAGE_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_OS; - if (common_area.flags.bootrom_present) { - dev_info |= DEVICE_INFO_FLAG_BOOTROM_PRESENT; - } - cmd_send(CMD_DEVICE_INFO,dev_info,0,0,0,0); - break; - } - default: - Dbprintf("%s: 0x%04x","unknown command:", c->cmd); - break; - } + case CMD_DEVICE_INFO: { + uint32_t dev_info = DEVICE_INFO_FLAG_OSIMAGE_PRESENT | DEVICE_INFO_FLAG_CURRENT_MODE_OS; + if (common_area.flags.bootrom_present) { + dev_info |= DEVICE_INFO_FLAG_BOOTROM_PRESENT; + } + cmd_send(CMD_DEVICE_INFO,dev_info,0,0,0,0); + break; + } + default: + Dbprintf("%s: 0x%04x","unknown command:", c->cmd); + break; + } } void __attribute__((noreturn)) AppMain(void) { - SpinDelay(100); - clear_trace(); + SpinDelay(100); + clear_trace(); - if(common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) { - /* Initialize common area */ - memset(&common_area, 0, sizeof(common_area)); - common_area.magic = COMMON_AREA_MAGIC; - common_area.version = 1; - } - common_area.flags.osimage_present = 1; + if(common_area.magic != COMMON_AREA_MAGIC || common_area.version != 1) { + /* Initialize common area */ + memset(&common_area, 0, sizeof(common_area)); + common_area.magic = COMMON_AREA_MAGIC; + common_area.version = 1; + } + common_area.flags.osimage_present = 1; - LEDsoff(); + LEDsoff(); - // The FPGA gets its clock from us from PCK0 output, so set that up. - AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0; - AT91C_BASE_PIOA->PIO_PDR = GPIO_PCK0; - AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_PCK0; - // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz - AT91C_BASE_PMC->PMC_PCKR[0] = AT91C_PMC_CSS_PLL_CLK | AT91C_PMC_PRES_CLK_4; // 4 for 24Mhz pck0, 2 for 48 MHZ pck0 - AT91C_BASE_PIOA->PIO_OER = GPIO_PCK0; + // The FPGA gets its clock from us from PCK0 output, so set that up. + AT91C_BASE_PIOA->PIO_BSR = GPIO_PCK0; + AT91C_BASE_PIOA->PIO_PDR = GPIO_PCK0; + AT91C_BASE_PMC->PMC_SCER |= AT91C_PMC_PCK0; + // PCK0 is PLL clock / 4 = 96Mhz / 4 = 24Mhz + AT91C_BASE_PMC->PMC_PCKR[0] = AT91C_PMC_CSS_PLL_CLK | AT91C_PMC_PRES_CLK_4; // 4 for 24Mhz pck0, 2 for 48 MHZ pck0 + AT91C_BASE_PIOA->PIO_OER = GPIO_PCK0; - // Reset SPI - AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; - AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; // errata says it needs twice to be correctly set. + // Reset SPI + AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; + AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; // errata says it needs twice to be correctly set. - // Reset SSC - AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; + // Reset SSC + AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; - // Configure MUX - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + // Configure MUX + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - // Load the FPGA image, which we have stored in our flash. - // (the HF version by default) - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + // Load the FPGA image, which we have stored in our flash. + // (the HF version by default) + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - StartTickCount(); + StartTickCount(); #ifdef WITH_LCD - LCDInit(); + LCDInit(); #endif #ifdef WITH_SMARTCARD - I2C_init(); + I2C_init(); #endif #ifdef WITH_FPC - usart_init(); + usart_init(); #endif #ifdef WITH_FLASH - loadT55xxConfig(); + loadT55xxConfig(); #endif - // This is made as late as possible to ensure enumeration without timeout - // against device such as http://www.hobbytronics.co.uk/usb-host-board-v2 - usb_disable(); - usb_enable(); + // This is made as late as possible to ensure enumeration without timeout + // against device such as http://www.hobbytronics.co.uk/usb-host-board-v2 + usb_disable(); + usb_enable(); - uint8_t rx[sizeof(UsbCommand)]; + uint8_t rx[sizeof(UsbCommand)]; - for(;;) { - WDT_HIT(); + for(;;) { + WDT_HIT(); - // Check if there is a usb packet available - if (usb_poll_validate_length()) { - if (usb_read(rx, sizeof(rx)) ) - UsbPacketReceived(rx, sizeof(rx)); - } + // Check if there is a usb packet available + if (usb_poll_validate_length()) { + if (usb_read(rx, sizeof(rx)) ) + UsbPacketReceived(rx, sizeof(rx)); + } #ifdef WITH_FPC - // Check is there is FPC package available - /* - usart_init(); - if (usart_readbuffer(rx, sizeof(rx)) ) - UsbPacketReceived(rx, sizeof(rx) ); - */ + // Check is there is FPC package available + /* + usart_init(); + if (usart_readbuffer(rx, sizeof(rx)) ) + UsbPacketReceived(rx, sizeof(rx) ); + */ #endif - // Press button for one second to enter a possible standalone mode - if (BUTTON_HELD(1000) > 0) { + // Press button for one second to enter a possible standalone mode + if (BUTTON_HELD(1000) > 0) { /* * So this is the trigger to execute a standalone mod. Generic entrypoint by following the standalone/standalone.h headerfile @@ -1564,13 +1564,13 @@ void __attribute__((noreturn)) AppMain(void) { * Since the standalone is either LF or HF, the somewhat bisarr defines below exists. */ #if defined (WITH_LF) && ( defined (WITH_LF_SAMYRUN) || defined (WITH_LF_HIDBRUTE) || defined (WITH_LF_PROXBRUTE) ) - RunMod(); + RunMod(); #endif #if defined (WITH_ISO14443a) && ( defined (WITH_HF_YOUNG) || defined(WITH_HF_COLIN) || defined(WITH_HF_MATTYRUN) || defined(WITH_HF_BOG) ) - RunMod(); + RunMod(); #endif - } - } + } + } } diff --git a/armsrc/apps.h b/armsrc/apps.h index 276331575..4a775702a 100644 --- a/armsrc/apps.h +++ b/armsrc/apps.h @@ -202,8 +202,8 @@ void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t // iso15693.h void RecordRawAdcSamplesIso15693(void); void AcquireRawAdcSamplesIso15693(void); -void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg -void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - greg +void ReaderIso15693(uint32_t parameter); // Simulate an ISO15693 reader - greg +void SimTagIso15693(uint32_t parameter, uint8_t *uid); // simulate an ISO15693 tag - greg void BruteforceIso15693Afi(uint32_t speed); // find an AFI of a tag - atrox void DirectTag15693Command(uint32_t datalen,uint32_t speed, uint32_t recv, uint8_t *data); // send arbitrary commands from CLI - atrox void Iso15693InitReader(void); diff --git a/armsrc/buzzer.c b/armsrc/buzzer.c index 5f29c6472..987d8fade 100644 --- a/armsrc/buzzer.c +++ b/armsrc/buzzer.c @@ -2,9 +2,9 @@ void Ring_BEE_ONCE(uint16_t music_note) { BEE_ON(); - SpinDelayUs(music_note); - BEE_OFF(); - SpinDelayUs(music_note); + SpinDelayUs(music_note); + BEE_OFF(); + SpinDelayUs(music_note); } void ring_2_7khz(uint16_t count) { @@ -12,9 +12,9 @@ void ring_2_7khz(uint16_t count) { } void Ring_BEE_TIME(uint16_t music_note,uint16_t count) { - for(uint16_t i=0 ; i < count; i++) - Ring_BEE_ONCE(music_note); - SpinDelay(9); + for(uint16_t i=0 ; i < count; i++) + Ring_BEE_ONCE(music_note); + SpinDelay(9); } void Ring_ALL(uint16_t count) { @@ -29,58 +29,58 @@ void Ring_ALL(uint16_t count) { } void Ring_Little_Star(uint16_t count) { - Ring_BEE_TIME(note_1,count); - Ring_BEE_TIME(note_1,count); - Ring_BEE_TIME(note_5,count); - Ring_BEE_TIME(note_5,count); - Ring_BEE_TIME(note_6,count); - Ring_BEE_TIME(note_6,count); - Ring_BEE_TIME(note_5,2*count); - LED_A_ON(); - /* - Ring_BEE_TIME(note_4,count); - Ring_BEE_TIME(note_4,count); - Ring_BEE_TIME(note_3,count); - Ring_BEE_TIME(note_3,count); - Ring_BEE_TIME(note_2,count); - Ring_BEE_TIME(note_2,count); - Ring_BEE_TIME(note_1,2*count); - LED_A_OFF(); + Ring_BEE_TIME(note_1,count); + Ring_BEE_TIME(note_1,count); + Ring_BEE_TIME(note_5,count); + Ring_BEE_TIME(note_5,count); + Ring_BEE_TIME(note_6,count); + Ring_BEE_TIME(note_6,count); + Ring_BEE_TIME(note_5,2*count); + LED_A_ON(); + /* + Ring_BEE_TIME(note_4,count); + Ring_BEE_TIME(note_4,count); + Ring_BEE_TIME(note_3,count); + Ring_BEE_TIME(note_3,count); + Ring_BEE_TIME(note_2,count); + Ring_BEE_TIME(note_2,count); + Ring_BEE_TIME(note_1,2*count); + LED_A_OFF(); - Ring_BEE_TIME(note_5,count); - Ring_BEE_TIME(note_5,count); - Ring_BEE_TIME(note_4,count); - Ring_BEE_TIME(note_4,count); - Ring_BEE_TIME(note_3,count); - Ring_BEE_TIME(note_3,count); - Ring_BEE_TIME(note_2,2*count); - LED_A_ON(); + Ring_BEE_TIME(note_5,count); + Ring_BEE_TIME(note_5,count); + Ring_BEE_TIME(note_4,count); + Ring_BEE_TIME(note_4,count); + Ring_BEE_TIME(note_3,count); + Ring_BEE_TIME(note_3,count); + Ring_BEE_TIME(note_2,2*count); + LED_A_ON(); - Ring_BEE_TIME(note_5,count); - Ring_BEE_TIME(note_5,count); - Ring_BEE_TIME(note_4,count); - Ring_BEE_TIME(note_4,count); - Ring_BEE_TIME(note_3,count); - Ring_BEE_TIME(note_3,count); - Ring_BEE_TIME(note_2,2*count); - LED_A_OFF(); + Ring_BEE_TIME(note_5,count); + Ring_BEE_TIME(note_5,count); + Ring_BEE_TIME(note_4,count); + Ring_BEE_TIME(note_4,count); + Ring_BEE_TIME(note_3,count); + Ring_BEE_TIME(note_3,count); + Ring_BEE_TIME(note_2,2*count); + LED_A_OFF(); - Ring_BEE_TIME(note_1,count); - Ring_BEE_TIME(note_1,count); - Ring_BEE_TIME(note_5,count); - Ring_BEE_TIME(note_5,count); - Ring_BEE_TIME(note_6,count); - Ring_BEE_TIME(note_6,count); - Ring_BEE_TIME(note_5,2*count); - LED_A_ON(); + Ring_BEE_TIME(note_1,count); + Ring_BEE_TIME(note_1,count); + Ring_BEE_TIME(note_5,count); + Ring_BEE_TIME(note_5,count); + Ring_BEE_TIME(note_6,count); + Ring_BEE_TIME(note_6,count); + Ring_BEE_TIME(note_5,2*count); + LED_A_ON(); - Ring_BEE_TIME(note_4,count); - Ring_BEE_TIME(note_4,count); - Ring_BEE_TIME(note_3,count); - Ring_BEE_TIME(note_3,count); - Ring_BEE_TIME(note_2,count); - Ring_BEE_TIME(note_2,count); - Ring_BEE_TIME(note_1,2*count); - LED_B_ON(); - */ + Ring_BEE_TIME(note_4,count); + Ring_BEE_TIME(note_4,count); + Ring_BEE_TIME(note_3,count); + Ring_BEE_TIME(note_3,count); + Ring_BEE_TIME(note_2,count); + Ring_BEE_TIME(note_2,count); + Ring_BEE_TIME(note_1,2*count); + LED_B_ON(); + */ } \ No newline at end of file diff --git a/armsrc/des.c b/armsrc/des.c index be5670e69..a8c416f06 100644 --- a/armsrc/des.c +++ b/armsrc/des.c @@ -22,7 +22,7 @@ * \email daniel.otte@rub.de * \date 2007-06-16 * \brief DES and EDE-DES implementation - * \license GPLv3 or later + * \license GPLv3 or later * */ @@ -72,111 +72,111 @@ const uint8_t sbox[256] = { }; const uint8_t e_permtab[] ={ - 4, 6, /* 4 bytes in 6 bytes out*/ - 32, 1, 2, 3, 4, 5, - 4, 5, 6, 7, 8, 9, - 8, 9, 10, 11, 12, 13, - 12, 13, 14, 15, 16, 17, - 16, 17, 18, 19, 20, 21, - 20, 21, 22, 23, 24, 25, - 24, 25, 26, 27, 28, 29, - 28, 29, 30, 31, 32, 1 + 4, 6, /* 4 bytes in 6 bytes out*/ + 32, 1, 2, 3, 4, 5, + 4, 5, 6, 7, 8, 9, + 8, 9, 10, 11, 12, 13, + 12, 13, 14, 15, 16, 17, + 16, 17, 18, 19, 20, 21, + 20, 21, 22, 23, 24, 25, + 24, 25, 26, 27, 28, 29, + 28, 29, 30, 31, 32, 1 }; const uint8_t p_permtab[] ={ - 4, 4, /* 32 bit -> 32 bit */ - 16, 7, 20, 21, - 29, 12, 28, 17, - 1, 15, 23, 26, - 5, 18, 31, 10, - 2, 8, 24, 14, - 32, 27, 3, 9, - 19, 13, 30, 6, - 22, 11, 4, 25 + 4, 4, /* 32 bit -> 32 bit */ + 16, 7, 20, 21, + 29, 12, 28, 17, + 1, 15, 23, 26, + 5, 18, 31, 10, + 2, 8, 24, 14, + 32, 27, 3, 9, + 19, 13, 30, 6, + 22, 11, 4, 25 }; const uint8_t ip_permtab[] ={ - 8, 8, /* 64 bit -> 64 bit */ - 58, 50, 42, 34, 26, 18, 10, 2, - 60, 52, 44, 36, 28, 20, 12, 4, - 62, 54, 46, 38, 30, 22, 14, 6, - 64, 56, 48, 40, 32, 24, 16, 8, - 57, 49, 41, 33, 25, 17, 9, 1, - 59, 51, 43, 35, 27, 19, 11, 3, - 61, 53, 45, 37, 29, 21, 13, 5, - 63, 55, 47, 39, 31, 23, 15, 7 + 8, 8, /* 64 bit -> 64 bit */ + 58, 50, 42, 34, 26, 18, 10, 2, + 60, 52, 44, 36, 28, 20, 12, 4, + 62, 54, 46, 38, 30, 22, 14, 6, + 64, 56, 48, 40, 32, 24, 16, 8, + 57, 49, 41, 33, 25, 17, 9, 1, + 59, 51, 43, 35, 27, 19, 11, 3, + 61, 53, 45, 37, 29, 21, 13, 5, + 63, 55, 47, 39, 31, 23, 15, 7 }; const uint8_t inv_ip_permtab[] ={ - 8, 8, /* 64 bit -> 64 bit */ - 40, 8, 48, 16, 56, 24, 64, 32, - 39, 7, 47, 15, 55, 23, 63, 31, - 38, 6, 46, 14, 54, 22, 62, 30, - 37, 5, 45, 13, 53, 21, 61, 29, - 36, 4, 44, 12, 52, 20, 60, 28, - 35, 3, 43, 11, 51, 19, 59, 27, - 34, 2, 42, 10, 50, 18, 58, 26, - 33, 1, 41, 9, 49, 17, 57, 25 + 8, 8, /* 64 bit -> 64 bit */ + 40, 8, 48, 16, 56, 24, 64, 32, + 39, 7, 47, 15, 55, 23, 63, 31, + 38, 6, 46, 14, 54, 22, 62, 30, + 37, 5, 45, 13, 53, 21, 61, 29, + 36, 4, 44, 12, 52, 20, 60, 28, + 35, 3, 43, 11, 51, 19, 59, 27, + 34, 2, 42, 10, 50, 18, 58, 26, + 33, 1, 41, 9, 49, 17, 57, 25 }; const uint8_t pc1_permtab[] ={ - 8, 7, /* 64 bit -> 56 bit*/ - 57, 49, 41, 33, 25, 17, 9, - 1, 58, 50, 42, 34, 26, 18, - 10, 2, 59, 51, 43, 35, 27, - 19, 11, 3, 60, 52, 44, 36, - 63, 55, 47, 39, 31, 23, 15, - 7, 62, 54, 46, 38, 30, 22, - 14, 6, 61, 53, 45, 37, 29, - 21, 13, 5, 28, 20, 12, 4 + 8, 7, /* 64 bit -> 56 bit*/ + 57, 49, 41, 33, 25, 17, 9, + 1, 58, 50, 42, 34, 26, 18, + 10, 2, 59, 51, 43, 35, 27, + 19, 11, 3, 60, 52, 44, 36, + 63, 55, 47, 39, 31, 23, 15, + 7, 62, 54, 46, 38, 30, 22, + 14, 6, 61, 53, 45, 37, 29, + 21, 13, 5, 28, 20, 12, 4 }; const uint8_t pc2_permtab[] ={ - 7, 6, /* 56 bit -> 48 bit */ - 14, 17, 11, 24, 1, 5, - 3, 28, 15, 6, 21, 10, - 23, 19, 12, 4, 26, 8, - 16, 7, 27, 20, 13, 2, - 41, 52, 31, 37, 47, 55, - 30, 40, 51, 45, 33, 48, - 44, 49, 39, 56, 34, 53, - 46, 42, 50, 36, 29, 32 + 7, 6, /* 56 bit -> 48 bit */ + 14, 17, 11, 24, 1, 5, + 3, 28, 15, 6, 21, 10, + 23, 19, 12, 4, 26, 8, + 16, 7, 27, 20, 13, 2, + 41, 52, 31, 37, 47, 55, + 30, 40, 51, 45, 33, 48, + 44, 49, 39, 56, 34, 53, + 46, 42, 50, 36, 29, 32 }; const uint8_t splitin6bitword_permtab[] = { - 8, 8, /* 64 bit -> 64 bit */ - 64, 64, 1, 6, 2, 3, 4, 5, - 64, 64, 7, 12, 8, 9, 10, 11, - 64, 64, 13, 18, 14, 15, 16, 17, - 64, 64, 19, 24, 20, 21, 22, 23, - 64, 64, 25, 30, 26, 27, 28, 29, - 64, 64, 31, 36, 32, 33, 34, 35, - 64, 64, 37, 42, 38, 39, 40, 41, - 64, 64, 43, 48, 44, 45, 46, 47 + 8, 8, /* 64 bit -> 64 bit */ + 64, 64, 1, 6, 2, 3, 4, 5, + 64, 64, 7, 12, 8, 9, 10, 11, + 64, 64, 13, 18, 14, 15, 16, 17, + 64, 64, 19, 24, 20, 21, 22, 23, + 64, 64, 25, 30, 26, 27, 28, 29, + 64, 64, 31, 36, 32, 33, 34, 35, + 64, 64, 37, 42, 38, 39, 40, 41, + 64, 64, 43, 48, 44, 45, 46, 47 }; const uint8_t shiftkey_permtab[] = { - 7, 7, /* 56 bit -> 56 bit */ - 2, 3, 4, 5, 6, 7, 8, 9, - 10, 11, 12, 13, 14, 15, 16, 17, - 18, 19, 20, 21, 22, 23, 24, 25, - 26, 27, 28, 1, - 30, 31, 32, 33, 34, 35, 36, 37, - 38, 39, 40, 41, 42, 43, 44, 45, - 46, 47, 48, 49, 50, 51, 52, 53, - 54, 55, 56, 29 + 7, 7, /* 56 bit -> 56 bit */ + 2, 3, 4, 5, 6, 7, 8, 9, + 10, 11, 12, 13, 14, 15, 16, 17, + 18, 19, 20, 21, 22, 23, 24, 25, + 26, 27, 28, 1, + 30, 31, 32, 33, 34, 35, 36, 37, + 38, 39, 40, 41, 42, 43, 44, 45, + 46, 47, 48, 49, 50, 51, 52, 53, + 54, 55, 56, 29 }; const uint8_t shiftkeyinv_permtab[] = { - 7, 7, - 28, 1, 2, 3, 4, 5, 6, 7, - 8, 9, 10, 11, 12, 13, 14, 15, - 16, 17, 18, 19, 20, 21, 22, 23, - 24, 25, 26, 27, - 56, 29, 30, 31, 32, 33, 34, 35, - 36, 37, 38, 39, 40, 41, 42, 43, - 44, 45, 46, 47, 48, 49, 50, 51, - 52, 53, 54, 55 + 7, 7, + 28, 1, 2, 3, 4, 5, 6, 7, + 8, 9, 10, 11, 12, 13, 14, 15, + 16, 17, 18, 19, 20, 21, 22, 23, + 24, 25, 26, 27, + 56, 29, 30, 31, 32, 33, 34, 35, + 36, 37, 38, 39, 40, 41, 42, 43, + 44, 45, 46, 47, 48, 49, 50, 51, + 52, 53, 54, 55 }; /* @@ -203,241 +203,241 @@ const uint8_t shiftkeyinv_permtab[] = { /******************************************************************************/ void permute(const uint8_t *ptable, const uint8_t *in, uint8_t *out){ - uint8_t ob; /* in-bytes and out-bytes */ - uint8_t byte, bit; /* counter for bit and byte */ - ob = ptable[1]; - ptable = &(ptable[2]); - for(byte=0; byte>(x%8)) ){ - t|=0x01; - } - } - out[byte]=t; - } + uint8_t ob; /* in-bytes and out-bytes */ + uint8_t byte, bit; /* counter for bit and byte */ + ob = ptable[1]; + ptable = &(ptable[2]); + for(byte=0; byte>(x%8)) ){ + t|=0x01; + } + } + out[byte]=t; + } } /******************************************************************************/ void changeendian32(uint32_t * a){ - *a = (*a & 0x000000FF) << 24 | - (*a & 0x0000FF00) << 8 | - (*a & 0x00FF0000) >> 8 | - (*a & 0xFF000000) >> 24; + *a = (*a & 0x000000FF) << 24 | + (*a & 0x0000FF00) << 8 | + (*a & 0x00FF0000) >> 8 | + (*a & 0xFF000000) >> 24; } /******************************************************************************/ static inline void shiftkey(uint8_t *key){ - uint8_t k[7]; - memcpy(k, key, 7); - permute((uint8_t*)shiftkey_permtab, k, key); + uint8_t k[7]; + memcpy(k, key, 7); + permute((uint8_t*)shiftkey_permtab, k, key); } /******************************************************************************/ static inline void shiftkey_inv(uint8_t *key){ - uint8_t k[7]; - memcpy(k, key, 7); - permute((uint8_t*)shiftkeyinv_permtab, k, key); + uint8_t k[7]; + memcpy(k, key, 7); + permute((uint8_t*)shiftkeyinv_permtab, k, key); } /******************************************************************************/ static inline uint64_t splitin6bitwords(uint64_t a){ - uint64_t ret=0; - a &= 0x0000ffffffffffffLL; - permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret); - return ret; + uint64_t ret=0; + a &= 0x0000ffffffffffffLL; + permute((uint8_t*)splitin6bitword_permtab, (uint8_t*)&a, (uint8_t*)&ret); + return ret; } /******************************************************************************/ static inline uint8_t substitute(uint8_t a, uint8_t * sbp){ - uint8_t x; - x = sbp[a>>1]; - x = (a&1)?x&0x0F:x>>4; - return x; + uint8_t x; + x = sbp[a>>1]; + x = (a&1)?x&0x0F:x>>4; + return x; } /******************************************************************************/ uint32_t des_f(uint32_t r, uint8_t* kr){ - uint8_t i; - uint32_t t=0,ret; - uint64_t data; - uint8_t *sbp; /* sboxpointer */ - permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data); - for(i=0; i<6; ++i) - ((uint8_t*)&data)[i] ^= kr[i]; + uint8_t i; + uint32_t t=0,ret; + uint64_t data; + uint8_t *sbp; /* sboxpointer */ + permute((uint8_t*)e_permtab, (uint8_t*)&r, (uint8_t*)&data); + for(i=0; i<6; ++i) + ((uint8_t*)&data)[i] ^= kr[i]; - /* Sbox substitution */ - data = splitin6bitwords(data); - sbp=(uint8_t*)sbox; - for(i=0; i<8; ++i){ - uint8_t x; - x = substitute(((uint8_t*)&data)[i], sbp); - t<<=4; - t |= x; - sbp += 32; - } - changeendian32(&t); + /* Sbox substitution */ + data = splitin6bitwords(data); + sbp=(uint8_t*)sbox; + for(i=0; i<8; ++i){ + uint8_t x; + x = substitute(((uint8_t*)&data)[i], sbp); + t<<=4; + t |= x; + sbp += 32; + } + changeendian32(&t); - permute((uint8_t*)p_permtab,(uint8_t*)&t, (uint8_t*)&ret); + permute((uint8_t*)p_permtab,(uint8_t*)&t, (uint8_t*)&ret); - return ret; + return ret; } /******************************************************************************/ typedef struct { - union { - uint8_t v8[8]; - uint32_t v32[2]; - } d; + union { + uint8_t v8[8]; + uint32_t v32[2]; + } d; } data_t; #define R (data.d.v32[1]) #define L (data.d.v32[0]) void des_enc(void* out, const void* in, const void* key){ - uint8_t kr[6], k[7]; - uint8_t i; - data_t data; + uint8_t kr[6], k[7]; + uint8_t i; + data_t data; - permute((uint8_t*)ip_permtab, (uint8_t*)in, data.d.v8); - permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); + permute((uint8_t*)ip_permtab, (uint8_t*)in, data.d.v8); + permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); - for(i=0; i<8; ++i){ - shiftkey(k); - if(ROTTABLE&((1<<((i<<1)+0))) ) - shiftkey(k); - permute((uint8_t*)pc2_permtab, k, kr); - L ^= des_f(R, kr); + for(i=0; i<8; ++i){ + shiftkey(k); + if(ROTTABLE&((1<<((i<<1)+0))) ) + shiftkey(k); + permute((uint8_t*)pc2_permtab, k, kr); + L ^= des_f(R, kr); - shiftkey(k); - if(ROTTABLE&((1<<((i<<1)+1))) ) - shiftkey(k); - permute((uint8_t*)pc2_permtab, k, kr); - R ^= des_f(L, kr); + shiftkey(k); + if(ROTTABLE&((1<<((i<<1)+1))) ) + shiftkey(k); + permute((uint8_t*)pc2_permtab, k, kr); + R ^= des_f(L, kr); - } - /* L <-> R*/ - R ^= L; - L ^= R; - R ^= L; + } + /* L <-> R*/ + R ^= L; + L ^= R; + R ^= L; - permute((uint8_t*)inv_ip_permtab, data.d.v8, (uint8_t*)out); + permute((uint8_t*)inv_ip_permtab, data.d.v8, (uint8_t*)out); } /******************************************************************************/ void des_dec(void* out, const void* in, const uint8_t* key){ - uint8_t kr[6],k[7]; - int8_t i; - data_t data; + uint8_t kr[6],k[7]; + int8_t i; + data_t data; - permute((uint8_t*)ip_permtab, (uint8_t*)in, data.d.v8); - permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); - for(i=7; i>=0; --i){ + permute((uint8_t*)ip_permtab, (uint8_t*)in, data.d.v8); + permute((uint8_t*)pc1_permtab, (const uint8_t*)key, k); + for(i=7; i>=0; --i){ - permute((uint8_t*)pc2_permtab, k, kr); - L ^= des_f(R, kr); - shiftkey_inv(k); - if(ROTTABLE&((1<<((i<<1)+1))) ){ - shiftkey_inv(k); - } + permute((uint8_t*)pc2_permtab, k, kr); + L ^= des_f(R, kr); + shiftkey_inv(k); + if(ROTTABLE&((1<<((i<<1)+1))) ){ + shiftkey_inv(k); + } - permute((uint8_t*)pc2_permtab, k, kr); - R ^= des_f(L, kr); - shiftkey_inv(k); - if(ROTTABLE&((1<<((i<<1)+0))) ){ - shiftkey_inv(k); - } + permute((uint8_t*)pc2_permtab, k, kr); + R ^= des_f(L, kr); + shiftkey_inv(k); + if(ROTTABLE&((1<<((i<<1)+0))) ){ + shiftkey_inv(k); + } - } - /* L <-> R*/ - R ^= L; - L ^= R; - R ^= L; + } + /* L <-> R*/ + R ^= L; + L ^= R; + R ^= L; - permute((uint8_t*)inv_ip_permtab, data.d.v8, (uint8_t*)out); + permute((uint8_t*)inv_ip_permtab, data.d.v8, (uint8_t*)out); } /******************************************************************************/ void tdes_enc(void* out, void* in, const void* key){ - des_enc(out, in, (uint8_t*)key + 0); - des_dec(out, out, (uint8_t*)key + 8); - des_enc(out, out, (uint8_t*)key +16); + des_enc(out, in, (uint8_t*)key + 0); + des_dec(out, out, (uint8_t*)key + 8); + des_enc(out, out, (uint8_t*)key +16); } /******************************************************************************/ void tdes_dec(void* out, void* in, const uint8_t* key){ - des_dec(out, in, (uint8_t*)key +16); - des_enc(out, out, (uint8_t*)key + 8); - des_dec(out, out, (uint8_t*)key + 0); + des_dec(out, in, (uint8_t*)key +16); + des_enc(out, out, (uint8_t*)key + 8); + des_dec(out, out, (uint8_t*)key + 0); } void tdes_2key_enc(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){ - if( length % 8 ) return; + if( length % 8 ) return; - uint8_t i; - uint8_t* tin = (uint8_t*) in; - uint8_t* tout = (uint8_t*) out; + uint8_t i; + uint8_t* tin = (uint8_t*) in; + uint8_t* tout = (uint8_t*) out; - while( length > 0 ) - { - for( i = 0; i < 8; i++ ) - tout[i] = (unsigned char)( tin[i] ^ iv[i] ); + while( length > 0 ) + { + for( i = 0; i < 8; i++ ) + tout[i] = (unsigned char)( tin[i] ^ iv[i] ); - des_enc(tout, tin, (uint8_t*)key + 0); - des_dec(tout, tout, (uint8_t*)key + 8); - des_enc(tout, tout, (uint8_t*)key + 0); + des_enc(tout, tin, (uint8_t*)key + 0); + des_dec(tout, tout, (uint8_t*)key + 8); + des_enc(tout, tout, (uint8_t*)key + 0); - memcpy( iv, tout, 8 ); + memcpy( iv, tout, 8 ); - tin += 8; - tout += 8; - length -= 8; - } + tin += 8; + tout += 8; + length -= 8; + } } void tdes_2key_dec(void* out, const void* in, size_t length, const void* key, unsigned char iv[8]){ - if( length % 8 ) return; + if( length % 8 ) return; - uint8_t i; - unsigned char temp[8]; - uint8_t* tin = (uint8_t*) in; - uint8_t* tout = (uint8_t*) out; + uint8_t i; + unsigned char temp[8]; + uint8_t* tin = (uint8_t*) in; + uint8_t* tout = (uint8_t*) out; - while( length > 0 ) - { - memcpy( temp, tin, 8 ); + while( length > 0 ) + { + memcpy( temp, tin, 8 ); - des_dec(tout, tin, (uint8_t*)key + 0); - des_enc(tout, tout, (uint8_t*)key + 8); - des_dec(tout, tout, (uint8_t*)key + 0); + des_dec(tout, tin, (uint8_t*)key + 0); + des_enc(tout, tout, (uint8_t*)key + 8); + des_dec(tout, tout, (uint8_t*)key + 0); - for( i = 0; i < 8; i++ ) - tout[i] = (unsigned char)( tout[i] ^ iv[i] ); + for( i = 0; i < 8; i++ ) + tout[i] = (unsigned char)( tout[i] ^ iv[i] ); - memcpy( iv, temp, 8 ); + memcpy( iv, temp, 8 ); - tin += 8; - tout += 8; - length -= 8; - } + tin += 8; + tout += 8; + length -= 8; + } } diff --git a/armsrc/des.h b/armsrc/des.h index 22735f2f3..2afe39b14 100644 --- a/armsrc/des.h +++ b/armsrc/des.h @@ -17,11 +17,11 @@ along with this program. If not, see . */ /** - * \file des.h - * \author Daniel Otte - * \date 2007-06-16 - * \brief des and tdes declarations - * \license GPLv3 or later + * \file des.h + * \author Daniel Otte + * \date 2007-06-16 + * \brief des and tdes declarations + * \license GPLv3 or later * */ #ifndef __DES_H_ diff --git a/armsrc/desfire_crypto.c b/armsrc/desfire_crypto.c index d79ecc8e3..dd958d3ea 100644 --- a/armsrc/desfire_crypto.c +++ b/armsrc/desfire_crypto.c @@ -85,20 +85,20 @@ void cmac (const desfirekey_t key, uint8_t *ivect, const uint8_t *data, size_t l mifare_cypher_blocks_chained (NULL, key, ivect, buffer, len, MCD_SEND, MCO_ENCYPHER); memcpy (cmac, ivect, kbs); - free(buffer); + free(buffer); } size_t key_block_size (const desfirekey_t key) { size_t block_size = 8; switch (key->type) { - case T_DES: - case T_3DES: - case T_3K3DES: - block_size = 8; - break; - case T_AES: - block_size = 16; - break; + case T_DES: + case T_3DES: + case T_3K3DES: + block_size = 8; + break; + case T_AES: + block_size = 16; + break; } return block_size; } @@ -211,7 +211,7 @@ void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes break; // Append MAC size_t bla = maced_data_length (DESFIRE(tag)->session_key, *nbytes - offset) + offset; - bla++; + bla++; memcpy (res + *nbytes, mac, 4); @@ -224,7 +224,7 @@ void* mifare_cryto_preprocess_data (desfiretag_t tag, void *data, size_t *nbytes if (append_mac) { size_t len = maced_data_length (key, *nbytes); - ++len; + ++len; memcpy (res, data, *nbytes); memcpy (res + *nbytes, DESFIRE (tag)->cmac, CMAC_LENGTH); *nbytes += CMAC_LENGTH; @@ -448,7 +448,7 @@ void* mifare_cryto_postprocess_data (desfiretag_t tag, void *data, size_t *nbyte case AS_LEGACY: AddCrc14A( (uint8_t*)res, end_crc_pos); end_crc_pos = crc_pos + 2; - // + // crc = crc16; @@ -529,11 +529,11 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect switch (operation) { case MCO_ENCYPHER: //DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); - des_enc(edata, data, key->data); + des_enc(edata, data, key->data); break; case MCO_DECYPHER: //DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); - des_dec(edata, data, key->data); + des_dec(edata, data, key->data); break; } break; @@ -543,27 +543,27 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); - tdes_enc(edata,data, key->data); + tdes_enc(edata,data, key->data); break; case MCO_DECYPHER: // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); - tdes_dec(data, edata, key->data); + tdes_dec(data, edata, key->data); break; } break; case T_3K3DES: switch (operation) { case MCO_ENCYPHER: - tdes_enc(edata,data, key->data); + tdes_enc(edata,data, key->data); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_ENCRYPT); // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_DECRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_ENCRYPT); break; case MCO_DECYPHER: - tdes_dec(data, edata, key->data); - // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_DECRYPT); + tdes_dec(data, edata, key->data); + // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks3), DES_DECRYPT); // DES_ecb_encrypt ((DES_cblock *) edata, (DES_cblock *) data, &(key->ks2), DES_ENCRYPT); // DES_ecb_encrypt ((DES_cblock *) data, (DES_cblock *) edata, &(key->ks1), DES_DECRYPT); break; @@ -571,21 +571,21 @@ void mifare_cypher_single_block (desfirekey_t key, uint8_t *data, uint8_t *ivect break; case T_AES: switch (operation) - { - case MCO_ENCYPHER: - { - AesCtx ctx; - AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); - AesEncrypt(&ctx, data, edata, sizeof(edata) ); - break; - } - case MCO_DECYPHER: - { - AesCtx ctx; - AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); - AesDecrypt(&ctx, edata, data, sizeof(edata)); - break; - } + { + case MCO_ENCYPHER: + { + AesCtx ctx; + AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); + AesEncrypt(&ctx, data, edata, sizeof(edata) ); + break; + } + case MCO_DECYPHER: + { + AesCtx ctx; + AesCtxIni(&ctx, ivect, key->data, KEY128,CBC); + AesDecrypt(&ctx, edata, data, sizeof(edata)); + break; + } } break; } @@ -620,11 +620,11 @@ void mifare_cypher_blocks_chained (desfiretag_t tag, desfirekey_t key, uint8_t * ivect = DESFIRE (tag)->ivect; switch (DESFIRE (tag)->authentication_scheme) { - case AS_LEGACY: - memset (ivect, 0, MAX_CRYPTO_BLOCK_SIZE); - break; - case AS_NEW: - break; + case AS_LEGACY: + memset (ivect, 0, MAX_CRYPTO_BLOCK_SIZE); + break; + case AS_NEW: + break; } } diff --git a/armsrc/desfire_key.c b/armsrc/desfire_key.c index a4ed05f68..f8ea8c794 100644 --- a/armsrc/desfire_key.c +++ b/armsrc/desfire_key.c @@ -38,12 +38,12 @@ void Desfire_des_key_new (const uint8_t value[8], desfirekey_t key) { } void Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key) { - if ( key != NULL) { - key->type = T_DES; - memcpy (key->data, value, 8); - memcpy (key->data+8, value, 8); - update_key_schedules (key); - } + if ( key != NULL) { + key->type = T_DES; + memcpy (key->data, value, 8); + memcpy (key->data+8, value, 8); + update_key_schedules (key); + } } void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key) { @@ -58,11 +58,11 @@ void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key) { void Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key) { if ( key != NULL ){ - key->type = T_3DES; - memcpy (key->data, value, 16); - memcpy (key->data + 16, value, 8); - update_key_schedules (key); - } + key->type = T_3DES; + memcpy (key->data, value, 16); + memcpy (key->data + 16, value, 8); + update_key_schedules (key); + } } void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key) { @@ -74,11 +74,11 @@ void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key) { } void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key) { - if ( key != NULL){ - key->type = T_3K3DES; - memcpy (key->data, value, 24); - update_key_schedules (key); - } + if ( key != NULL){ + key->type = T_3K3DES; + memcpy (key->data, value, 24); + update_key_schedules (key); + } } void Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key) { @@ -87,11 +87,11 @@ void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t void Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version, desfirekey_t key) { - if (key != NULL) { - memcpy (key->data, value, 16); - key->type = T_AES; - key->aes_version = version; - } + if (key != NULL) { + memcpy (key->data, value, 16); + key->type = T_AES; + key->aes_version = version; + } } uint8_t Desfire_key_get_version (desfirekey_t key) { diff --git a/armsrc/desfire_key.h b/armsrc/desfire_key.h index 4e6fdaea9..cb0e8b250 100644 --- a/armsrc/desfire_key.h +++ b/armsrc/desfire_key.h @@ -6,15 +6,15 @@ #include "iso14443a.h" #include "desfire.h" //#include "mifare.h" // iso14a_card_select_t struct -void Desfire_des_key_new (const uint8_t value[8], desfirekey_t key); -void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key); -void Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key); -void Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key); -void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key); -void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key); -void Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key); -void Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version,desfirekey_t key); -uint8_t Desfire_key_get_version (desfirekey_t key); -void Desfire_key_set_version (desfirekey_t key, uint8_t version); -void Desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key); +void Desfire_des_key_new (const uint8_t value[8], desfirekey_t key); +void Desfire_3des_key_new (const uint8_t value[16], desfirekey_t key); +void Desfire_des_key_new_with_version (const uint8_t value[8], desfirekey_t key); +void Desfire_3des_key_new_with_version (const uint8_t value[16], desfirekey_t key); +void Desfire_3k3des_key_new (const uint8_t value[24], desfirekey_t key); +void Desfire_3k3des_key_new_with_version (const uint8_t value[24], desfirekey_t key); +void Desfire_aes_key_new (const uint8_t value[16], desfirekey_t key); +void Desfire_aes_key_new_with_version (const uint8_t value[16], uint8_t version,desfirekey_t key); +uint8_t Desfire_key_get_version (desfirekey_t key); +void Desfire_key_set_version (desfirekey_t key, uint8_t version); +void Desfire_session_key_new (const uint8_t rnda[], const uint8_t rndb[], desfirekey_t authkey, desfirekey_t key); #endif \ No newline at end of file diff --git a/armsrc/epa.c b/armsrc/epa.c index 80d51e553..63a57d46b 100644 --- a/armsrc/epa.c +++ b/armsrc/epa.c @@ -21,41 +21,41 @@ static const uint8_t pps[] = {0xD0, 0x11, 0x00, 0x52, 0xA6}; // General Authenticate (request encrypted nonce) WITHOUT the Le at the end static const uint8_t apdu_general_authenticate_pace_get_nonce[] = { - 0x10, // CLA - 0x86, // INS - 0x00, // P1 - 0x00, // P2 - 0x02, // Lc - 0x7C, // Type: Dynamic Authentication Data - 0x00, // Length: 0 bytes + 0x10, // CLA + 0x86, // INS + 0x00, // P1 + 0x00, // P2 + 0x02, // Lc + 0x7C, // Type: Dynamic Authentication Data + 0x00, // Length: 0 bytes }; // MSE: Set AT (only CLA, INS, P1 and P2) static const uint8_t apdu_mse_set_at_start[] = { - 0x00, // CLA - 0x22, // INS - 0xC1, // P1 - 0xA4, // P2 + 0x00, // CLA + 0x22, // INS + 0xC1, // P1 + 0xA4, // P2 }; // SELECT BINARY with the ID for EF.CardAccess static const uint8_t apdu_select_binary_cardaccess[] = { - 0x00, // CLA - 0xA4, // INS - 0x02, // P1 - 0x0C, // P2 - 0x02, // Lc - 0x01, // ID - 0x1C // ID + 0x00, // CLA + 0xA4, // INS + 0x02, // P1 + 0x0C, // P2 + 0x02, // Lc + 0x01, // ID + 0x1C // ID }; // READ BINARY static const uint8_t apdu_read_binary[] = { - 0x00, // CLA - 0xB0, // INS - 0x00, // P1 - 0x00, // P2 - 0x38 // Le + 0x00, // CLA + 0xB0, // INS + 0x00, // P1 + 0x00, // P2 + 0x38 // Le }; @@ -84,14 +84,14 @@ static uint8_t apdu_replay_general_authenticate_pace_mutual_authenticate[75]; static uint8_t apdu_replay_general_authenticate_pace_perform_key_agreement[18]; // pointers to the APDUs (for iterations) static struct { - uint8_t len; - uint8_t *data; + uint8_t len; + uint8_t *data; } const apdus_replay[] = { - {sizeof(apdu_replay_mse_set_at_pace), apdu_replay_mse_set_at_pace}, - {sizeof(apdu_replay_general_authenticate_pace_get_nonce), apdu_replay_general_authenticate_pace_get_nonce}, - {sizeof(apdu_replay_general_authenticate_pace_map_nonce), apdu_replay_general_authenticate_pace_map_nonce}, - {sizeof(apdu_replay_general_authenticate_pace_mutual_authenticate), apdu_replay_general_authenticate_pace_mutual_authenticate}, - {sizeof(apdu_replay_general_authenticate_pace_perform_key_agreement), apdu_replay_general_authenticate_pace_perform_key_agreement} + {sizeof(apdu_replay_mse_set_at_pace), apdu_replay_mse_set_at_pace}, + {sizeof(apdu_replay_general_authenticate_pace_get_nonce), apdu_replay_general_authenticate_pace_get_nonce}, + {sizeof(apdu_replay_general_authenticate_pace_map_nonce), apdu_replay_general_authenticate_pace_map_nonce}, + {sizeof(apdu_replay_general_authenticate_pace_mutual_authenticate), apdu_replay_general_authenticate_pace_mutual_authenticate}, + {sizeof(apdu_replay_general_authenticate_pace_perform_key_agreement), apdu_replay_general_authenticate_pace_perform_key_agreement} }; // lengths of the replay APDUs @@ -105,18 +105,18 @@ static char iso_type = 0; //----------------------------------------------------------------------------- int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response) { - switch(iso_type) - { - case 'a': - return iso14_apdu(apdu, (uint16_t) length, false, response, NULL); - break; - case 'b': - return iso14443b_apdu(apdu, length, response); - break; - default: - return 0; - break; - } + switch(iso_type) + { + case 'a': + return iso14_apdu(apdu, (uint16_t) length, false, response, NULL); + break; + case 'b': + return iso14443b_apdu(apdu, length, response); + break; + default: + return 0; + break; + } } //----------------------------------------------------------------------------- @@ -124,9 +124,9 @@ int EPA_APDU(uint8_t *apdu, size_t length, uint8_t *response) //----------------------------------------------------------------------------- void EPA_Finish() { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - iso_type = 0; + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + iso_type = 0; } //----------------------------------------------------------------------------- @@ -146,68 +146,68 @@ size_t EPA_Parse_CardAccess(uint8_t *data, size_t length, pace_version_info_t *pace_info) { - size_t index = 0; + size_t index = 0; - while (index <= length - 2) { - // determine type of element - // SET or SEQUENCE - if (data[index] == 0x31 || data[index] == 0x30) { - // enter the set (skip tag + length) - index += 2; - // check for extended length - if ((data[index - 1] & 0x80) != 0) { - index += (data[index-1] & 0x7F); - } - } - // OID - else if (data[index] == 0x06) { - // is this a PACE OID? - if (data[index + 1] == 0x0A // length matches - && memcmp(data + index + 2, - oid_pace_start, - sizeof(oid_pace_start)) == 0 // content matches - && pace_info != NULL) - { - // first, clear the pace_info struct - memset(pace_info, 0, sizeof(pace_version_info_t)); - memcpy(pace_info->oid, data + index + 2, sizeof(pace_info->oid)); - // a PACE OID is followed by the version - index += data[index + 1] + 2; - if (data[index] == 02 && data[index + 1] == 01) { - pace_info->version = data[index + 2]; - index += 3; - } - else { - return index; - } - // after that there might(!) be the parameter ID - if (data[index] == 02 && data[index + 1] == 01) { - pace_info->parameter_id = data[index + 2]; - index += 3; - } - } - else { - // skip this OID - index += 2 + data[index + 1]; - } - } - // if the length is 0, something is wrong - // TODO: This needs to be extended to support long tags - else if (data[index + 1] == 0) { - return index; - } - else { - // skip this part - // TODO: This needs to be extended to support long tags - // TODO: This needs to be extended to support unknown elements with - // a size > 0x7F - index += 2 + data[index + 1]; - } - } + while (index <= length - 2) { + // determine type of element + // SET or SEQUENCE + if (data[index] == 0x31 || data[index] == 0x30) { + // enter the set (skip tag + length) + index += 2; + // check for extended length + if ((data[index - 1] & 0x80) != 0) { + index += (data[index-1] & 0x7F); + } + } + // OID + else if (data[index] == 0x06) { + // is this a PACE OID? + if (data[index + 1] == 0x0A // length matches + && memcmp(data + index + 2, + oid_pace_start, + sizeof(oid_pace_start)) == 0 // content matches + && pace_info != NULL) + { + // first, clear the pace_info struct + memset(pace_info, 0, sizeof(pace_version_info_t)); + memcpy(pace_info->oid, data + index + 2, sizeof(pace_info->oid)); + // a PACE OID is followed by the version + index += data[index + 1] + 2; + if (data[index] == 02 && data[index + 1] == 01) { + pace_info->version = data[index + 2]; + index += 3; + } + else { + return index; + } + // after that there might(!) be the parameter ID + if (data[index] == 02 && data[index + 1] == 01) { + pace_info->parameter_id = data[index + 2]; + index += 3; + } + } + else { + // skip this OID + index += 2 + data[index + 1]; + } + } + // if the length is 0, something is wrong + // TODO: This needs to be extended to support long tags + else if (data[index + 1] == 0) { + return index; + } + else { + // skip this part + // TODO: This needs to be extended to support long tags + // TODO: This needs to be extended to support unknown elements with + // a size > 0x7F + index += 2 + data[index + 1]; + } + } - // TODO: We should check whether we reached the end in error, but for that - // we need a better parser (e.g. with states like IN_SET or IN_PACE_INFO) - return 0; + // TODO: We should check whether we reached the end in error, but for that + // we need a better parser (e.g. with states like IN_SET or IN_PACE_INFO) + return 0; } //----------------------------------------------------------------------------- @@ -217,42 +217,42 @@ size_t EPA_Parse_CardAccess(uint8_t *data, //----------------------------------------------------------------------------- int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length) { - // the response APDU of the card - // since the card doesn't always care for the expected length we send it, - // we reserve 262 bytes here just to be safe (256-byte APDU + SW + ISO frame) - uint8_t response_apdu[262]; - int rapdu_length = 0; + // the response APDU of the card + // since the card doesn't always care for the expected length we send it, + // we reserve 262 bytes here just to be safe (256-byte APDU + SW + ISO frame) + uint8_t response_apdu[262]; + int rapdu_length = 0; - // select the file EF.CardAccess - rapdu_length = EPA_APDU((uint8_t *)apdu_select_binary_cardaccess, - sizeof(apdu_select_binary_cardaccess), - response_apdu); - if (rapdu_length < 6 - || response_apdu[rapdu_length - 4] != 0x90 - || response_apdu[rapdu_length - 3] != 0x00) - { - DbpString("Failed to select EF.CardAccess!"); - return -1; - } + // select the file EF.CardAccess + rapdu_length = EPA_APDU((uint8_t *)apdu_select_binary_cardaccess, + sizeof(apdu_select_binary_cardaccess), + response_apdu); + if (rapdu_length < 6 + || response_apdu[rapdu_length - 4] != 0x90 + || response_apdu[rapdu_length - 3] != 0x00) + { + DbpString("Failed to select EF.CardAccess!"); + return -1; + } - // read the file - rapdu_length = EPA_APDU((uint8_t *)apdu_read_binary, - sizeof(apdu_read_binary), - response_apdu); - if (rapdu_length <= 6 - || response_apdu[rapdu_length - 4] != 0x90 - || response_apdu[rapdu_length - 3] != 0x00) - { - Dbprintf("Failed to read EF.CardAccess!"); - return -1; - } + // read the file + rapdu_length = EPA_APDU((uint8_t *)apdu_read_binary, + sizeof(apdu_read_binary), + response_apdu); + if (rapdu_length <= 6 + || response_apdu[rapdu_length - 4] != 0x90 + || response_apdu[rapdu_length - 3] != 0x00) + { + Dbprintf("Failed to read EF.CardAccess!"); + return -1; + } - // copy the content into the buffer - // length of data available: apdu_length - 4 (ISO frame) - 2 (SW) - size_t to_copy = rapdu_length - 6; - to_copy = to_copy < max_length ? to_copy : max_length; - memcpy(buffer, response_apdu+2, to_copy); - return to_copy; + // copy the content into the buffer + // length of data available: apdu_length - 4 (ISO frame) - 2 (SW) + size_t to_copy = rapdu_length - 6; + to_copy = to_copy < max_length ? to_copy : max_length; + memcpy(buffer, response_apdu+2, to_copy); + return to_copy; } //----------------------------------------------------------------------------- @@ -261,11 +261,11 @@ int EPA_Read_CardAccess(uint8_t *buffer, size_t max_length) //----------------------------------------------------------------------------- static void EPA_PACE_Collect_Nonce_Abort(uint8_t step, int func_return) { - // power down the field - EPA_Finish(); + // power down the field + EPA_Finish(); - // send the USB packet - cmd_send(CMD_ACK,step,func_return,0,0,0); + // send the USB packet + cmd_send(CMD_ACK,step,func_return,0,0,0); } //----------------------------------------------------------------------------- @@ -273,68 +273,68 @@ static void EPA_PACE_Collect_Nonce_Abort(uint8_t step, int func_return) //----------------------------------------------------------------------------- void EPA_PACE_Collect_Nonce(UsbCommand *c) { - /* - * ack layout: - * arg: - * 1. element - * step where the error occured or 0 if no error occured + /* + * ack layout: + * arg: + * 1. element + * step where the error occured or 0 if no error occured * 2. element * return code of the last executed function - * d: - * Encrypted nonce - */ + * d: + * Encrypted nonce + */ - // return value of a function - int func_return = 0; + // return value of a function + int func_return = 0; - // set up communication - func_return = EPA_Setup(); - if (func_return != 0) { - EPA_PACE_Collect_Nonce_Abort(1, func_return); - return; - } + // set up communication + func_return = EPA_Setup(); + if (func_return != 0) { + EPA_PACE_Collect_Nonce_Abort(1, func_return); + return; + } - // read the CardAccess file - // this array will hold the CardAccess file - uint8_t card_access[256] = {0}; - int card_access_length = EPA_Read_CardAccess(card_access, 256); - // the response has to be at least this big to hold the OID - if (card_access_length < 18) { - EPA_PACE_Collect_Nonce_Abort(2, card_access_length); - return; - } + // read the CardAccess file + // this array will hold the CardAccess file + uint8_t card_access[256] = {0}; + int card_access_length = EPA_Read_CardAccess(card_access, 256); + // the response has to be at least this big to hold the OID + if (card_access_length < 18) { + EPA_PACE_Collect_Nonce_Abort(2, card_access_length); + return; + } - // this will hold the PACE info of the card - pace_version_info_t pace_version_info; - // search for the PACE OID - func_return = EPA_Parse_CardAccess(card_access, - card_access_length, - &pace_version_info); - if (func_return != 0 || pace_version_info.version == 0) { - EPA_PACE_Collect_Nonce_Abort(3, func_return); - return; - } + // this will hold the PACE info of the card + pace_version_info_t pace_version_info; + // search for the PACE OID + func_return = EPA_Parse_CardAccess(card_access, + card_access_length, + &pace_version_info); + if (func_return != 0 || pace_version_info.version == 0) { + EPA_PACE_Collect_Nonce_Abort(3, func_return); + return; + } - // initiate the PACE protocol - // use the CAN for the password since that doesn't change - func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2); + // initiate the PACE protocol + // use the CAN for the password since that doesn't change + func_return = EPA_PACE_MSE_Set_AT(pace_version_info, 2); - // now get the nonce - uint8_t nonce[256] = {0}; - uint8_t requested_size = (uint8_t)c->arg[0]; - func_return = EPA_PACE_Get_Nonce(requested_size, nonce); - // check if the command succeeded - if (func_return < 0) - { - EPA_PACE_Collect_Nonce_Abort(4, func_return); - return; - } + // now get the nonce + uint8_t nonce[256] = {0}; + uint8_t requested_size = (uint8_t)c->arg[0]; + func_return = EPA_PACE_Get_Nonce(requested_size, nonce); + // check if the command succeeded + if (func_return < 0) + { + EPA_PACE_Collect_Nonce_Abort(4, func_return); + return; + } - // all done, return - EPA_Finish(); + // all done, return + EPA_Finish(); - // save received information - cmd_send(CMD_ACK,0,func_return,0,nonce,func_return); + // save received information + cmd_send(CMD_ACK,0,func_return,0,nonce,func_return); } //----------------------------------------------------------------------------- @@ -347,44 +347,44 @@ void EPA_PACE_Collect_Nonce(UsbCommand *c) //----------------------------------------------------------------------------- int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce) { - // build the APDU - uint8_t apdu[sizeof(apdu_general_authenticate_pace_get_nonce) + 1]; - // copy the constant part - memcpy(apdu, - apdu_general_authenticate_pace_get_nonce, - sizeof(apdu_general_authenticate_pace_get_nonce)); - // append Le (requested length + 2 due to tag/length taking 2 bytes) in RAPDU - apdu[sizeof(apdu_general_authenticate_pace_get_nonce)] = requested_length + 4; + // build the APDU + uint8_t apdu[sizeof(apdu_general_authenticate_pace_get_nonce) + 1]; + // copy the constant part + memcpy(apdu, + apdu_general_authenticate_pace_get_nonce, + sizeof(apdu_general_authenticate_pace_get_nonce)); + // append Le (requested length + 2 due to tag/length taking 2 bytes) in RAPDU + apdu[sizeof(apdu_general_authenticate_pace_get_nonce)] = requested_length + 4; - // send it - uint8_t response_apdu[262]; - int send_return = EPA_APDU(apdu, - sizeof(apdu), - response_apdu); - // check if the command succeeded - if (send_return < 6 - || response_apdu[send_return - 4] != 0x90 - || response_apdu[send_return - 3] != 0x00) - { - return -1; - } + // send it + uint8_t response_apdu[262]; + int send_return = EPA_APDU(apdu, + sizeof(apdu), + response_apdu); + // check if the command succeeded + if (send_return < 6 + || response_apdu[send_return - 4] != 0x90 + || response_apdu[send_return - 3] != 0x00) + { + return -1; + } - // if there is no nonce in the RAPDU, return here - if (send_return < 10) - { - // no error - return 0; - } - // get the actual length of the nonce - uint8_t nonce_length = response_apdu[5]; - if (nonce_length > send_return - 10) - { - nonce_length = send_return - 10; - } - // copy the nonce - memcpy(nonce, response_apdu + 6, nonce_length); + // if there is no nonce in the RAPDU, return here + if (send_return < 10) + { + // no error + return 0; + } + // get the actual length of the nonce + uint8_t nonce_length = response_apdu[5]; + if (nonce_length > send_return - 10) + { + nonce_length = send_return - 10; + } + // copy the nonce + memcpy(nonce, response_apdu + 6, nonce_length); - return nonce_length; + return nonce_length; } //----------------------------------------------------------------------------- @@ -393,53 +393,53 @@ int EPA_PACE_Get_Nonce(uint8_t requested_length, uint8_t *nonce) //----------------------------------------------------------------------------- int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password) { - // create the MSE: Set AT APDU - uint8_t apdu[23]; - // the minimum length (will be increased as more data is added) - size_t apdu_length = 20; - // copy the constant part - memcpy(apdu, - apdu_mse_set_at_start, - sizeof(apdu_mse_set_at_start)); - // type: OID - apdu[5] = 0x80; - // length of the OID - apdu[6] = sizeof(pace_version_info.oid); - // copy the OID - memcpy(apdu + 7, - pace_version_info.oid, - sizeof(pace_version_info.oid)); - // type: password - apdu[17] = 0x83; - // length: 1 - apdu[18] = 1; - // password - apdu[19] = password; - // if standardized domain parameters are used, copy the ID - if (pace_version_info.parameter_id != 0) { - apdu_length += 3; - // type: domain parameter - apdu[20] = 0x84; - // length: 1 - apdu[21] = 1; - // copy the parameter ID - apdu[22] = pace_version_info.parameter_id; - } - // now set Lc to the actual length - apdu[4] = apdu_length - 5; - // send it - uint8_t response_apdu[6]; - int send_return = EPA_APDU(apdu, - apdu_length, - response_apdu); - // check if the command succeeded - if (send_return != 6 - || response_apdu[send_return - 4] != 0x90 - || response_apdu[send_return - 3] != 0x00) - { - return 1; - } - return 0; + // create the MSE: Set AT APDU + uint8_t apdu[23]; + // the minimum length (will be increased as more data is added) + size_t apdu_length = 20; + // copy the constant part + memcpy(apdu, + apdu_mse_set_at_start, + sizeof(apdu_mse_set_at_start)); + // type: OID + apdu[5] = 0x80; + // length of the OID + apdu[6] = sizeof(pace_version_info.oid); + // copy the OID + memcpy(apdu + 7, + pace_version_info.oid, + sizeof(pace_version_info.oid)); + // type: password + apdu[17] = 0x83; + // length: 1 + apdu[18] = 1; + // password + apdu[19] = password; + // if standardized domain parameters are used, copy the ID + if (pace_version_info.parameter_id != 0) { + apdu_length += 3; + // type: domain parameter + apdu[20] = 0x84; + // length: 1 + apdu[21] = 1; + // copy the parameter ID + apdu[22] = pace_version_info.parameter_id; + } + // now set Lc to the actual length + apdu[4] = apdu_length - 5; + // send it + uint8_t response_apdu[6]; + int send_return = EPA_APDU(apdu, + apdu_length, + response_apdu); + // check if the command succeeded + if (send_return != 6 + || response_apdu[send_return - 4] != 0x90 + || response_apdu[send_return - 3] != 0x00) + { + return 1; + } + return 0; } //----------------------------------------------------------------------------- @@ -447,66 +447,66 @@ int EPA_PACE_MSE_Set_AT(pace_version_info_t pace_version_info, uint8_t password) //----------------------------------------------------------------------------- void EPA_PACE_Replay(UsbCommand *c) { - uint32_t timings[sizeof(apdu_lengths_replay) / sizeof(apdu_lengths_replay[0])] = {0}; + uint32_t timings[sizeof(apdu_lengths_replay) / sizeof(apdu_lengths_replay[0])] = {0}; - // if an APDU has been passed, save it - if (c->arg[0] != 0) { - // make sure it's not too big - if(c->arg[2] > apdus_replay[c->arg[0] - 1].len) - { - cmd_send(CMD_ACK, 1, 0, 0, NULL, 0); - } - memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1], - c->d.asBytes, - c->arg[2]); - // save/update APDU length - if (c->arg[1] == 0) { - apdu_lengths_replay[c->arg[0] - 1] = c->arg[2]; - } else { - apdu_lengths_replay[c->arg[0] - 1] += c->arg[2]; - } - cmd_send(CMD_ACK, 0, 0, 0, NULL, 0); - return; - } + // if an APDU has been passed, save it + if (c->arg[0] != 0) { + // make sure it's not too big + if(c->arg[2] > apdus_replay[c->arg[0] - 1].len) + { + cmd_send(CMD_ACK, 1, 0, 0, NULL, 0); + } + memcpy(apdus_replay[c->arg[0] - 1].data + c->arg[1], + c->d.asBytes, + c->arg[2]); + // save/update APDU length + if (c->arg[1] == 0) { + apdu_lengths_replay[c->arg[0] - 1] = c->arg[2]; + } else { + apdu_lengths_replay[c->arg[0] - 1] += c->arg[2]; + } + cmd_send(CMD_ACK, 0, 0, 0, NULL, 0); + return; + } - // return value of a function - int func_return; + // return value of a function + int func_return; - // set up communication - func_return = EPA_Setup(); - if (func_return != 0) { - EPA_Finish(); - cmd_send(CMD_ACK, 2, func_return, 0, NULL, 0); - return; - } + // set up communication + func_return = EPA_Setup(); + if (func_return != 0) { + EPA_Finish(); + cmd_send(CMD_ACK, 2, func_return, 0, NULL, 0); + return; + } - // increase the timeout (at least some cards really do need this!)///////////// - // iso14a_set_timeout(0x0003FFFF); + // increase the timeout (at least some cards really do need this!)///////////// + // iso14a_set_timeout(0x0003FFFF); - // response APDU - uint8_t response_apdu[300] = {0}; + // response APDU + uint8_t response_apdu[300] = {0}; - // now replay the data and measure the timings - for (int i = 0; i < sizeof(apdu_lengths_replay); i++) { - StartCountUS(); - func_return = EPA_APDU(apdus_replay[i].data, - apdu_lengths_replay[i], - response_apdu); - timings[i] = GetCountUS(); - // every step but the last one should succeed - if (i < sizeof(apdu_lengths_replay) - 1 - && (func_return < 6 - || response_apdu[func_return - 4] != 0x90 - || response_apdu[func_return - 3] != 0x00)) - { - EPA_Finish(); - cmd_send(CMD_ACK, 3 + i, func_return, 0, timings, 20); - return; - } - } - EPA_Finish(); - cmd_send(CMD_ACK,0,0,0,timings,20); - return; + // now replay the data and measure the timings + for (int i = 0; i < sizeof(apdu_lengths_replay); i++) { + StartCountUS(); + func_return = EPA_APDU(apdus_replay[i].data, + apdu_lengths_replay[i], + response_apdu); + timings[i] = GetCountUS(); + // every step but the last one should succeed + if (i < sizeof(apdu_lengths_replay) - 1 + && (func_return < 6 + || response_apdu[func_return - 4] != 0x90 + || response_apdu[func_return - 3] != 0x00)) + { + EPA_Finish(); + cmd_send(CMD_ACK, 3 + i, func_return, 0, timings, 20); + return; + } + } + EPA_Finish(); + cmd_send(CMD_ACK,0,0,0,timings,20); + return; } //----------------------------------------------------------------------------- @@ -515,40 +515,40 @@ void EPA_PACE_Replay(UsbCommand *c) //----------------------------------------------------------------------------- int EPA_Setup() { - int return_code = 0; - uint8_t uid[10]; - uint8_t pps_response[3]; - uint8_t pps_response_par[1]; - iso14a_card_select_t card_a_info; - iso14b_card_select_t card_b_info; + int return_code = 0; + uint8_t uid[10]; + uint8_t pps_response[3]; + uint8_t pps_response_par[1]; + iso14a_card_select_t card_a_info; + iso14b_card_select_t card_b_info; - // first, look for type A cards - // power up the field - iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); - // select the card - return_code = iso14443a_select_card(uid, &card_a_info, NULL, true, 0, false); - if (return_code == 1) { - // send the PPS request - ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL); - return_code = ReaderReceive(pps_response, pps_response_par); - if (return_code != 3 || pps_response[0] != 0xD0) { - return return_code == 0 ? 2 : return_code; - } - Dbprintf("ISO 14443 Type A"); - iso_type = 'a'; - return 0; - } + // first, look for type A cards + // power up the field + iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); + // select the card + return_code = iso14443a_select_card(uid, &card_a_info, NULL, true, 0, false); + if (return_code == 1) { + // send the PPS request + ReaderTransmit((uint8_t *)pps, sizeof(pps), NULL); + return_code = ReaderReceive(pps_response, pps_response_par); + if (return_code != 3 || pps_response[0] != 0xD0) { + return return_code == 0 ? 2 : return_code; + } + Dbprintf("ISO 14443 Type A"); + iso_type = 'a'; + return 0; + } - // if we're here, there is no type A card, so we look for type B - // power up the field - iso14443b_setup(); - // select the card - return_code = iso14443b_select_card( &card_b_info ); - if (return_code == 0) { - Dbprintf("ISO 14443 Type B"); - iso_type = 'b'; - return 0; - } - Dbprintf("No card found."); - return 1; + // if we're here, there is no type A card, so we look for type B + // power up the field + iso14443b_setup(); + // select the card + return_code = iso14443b_select_card( &card_b_info ); + if (return_code == 0) { + Dbprintf("ISO 14443 Type B"); + iso_type = 'b'; + return 0; + } + Dbprintf("No card found."); + return 1; } diff --git a/armsrc/epa.h b/armsrc/epa.h index 550af8200..a0701ab57 100644 --- a/armsrc/epa.h +++ b/armsrc/epa.h @@ -18,9 +18,9 @@ // this struct is used by EPA_Parse_CardAccess and contains info about the // PACE protocol supported by the chip typedef struct { - uint8_t oid[10]; - uint8_t version; - uint8_t parameter_id; + uint8_t oid[10]; + uint8_t version; + uint8_t parameter_id; } pace_version_info_t; // note: EPA_PACE_Collect_Nonce and EPA_PACE_Replay are declared in apps.h diff --git a/armsrc/felica.c b/armsrc/felica.c index 6b2bb5bfb..07aa763c9 100644 --- a/armsrc/felica.c +++ b/armsrc/felica.c @@ -2,9 +2,9 @@ #include "apps.h" #include "BigBuf.h" #include "util.h" -#include "usb_cdc.h" // for usb_poll_validate_length +#include "usb_cdc.h" // for usb_poll_validate_length #include "protocols.h" -#include "crc16.h" // crc16 ccitt +#include "crc16.h" // crc16 ccitt // FeliCa timings // minimum time between the start bits of consecutive transfers from reader to tag: 6800 carrier (13.56Mhz) cycles @@ -23,7 +23,7 @@ #endif // CRC skips two first sync bits in data buffer -#define AddCrc(data, len) compute_crc(CRC_FELICA, (data)+2, (len),(data)+(len)+2, (data)+(len)+3) +#define AddCrc(data, len) compute_crc(CRC_FELICA, (data)+2, (len),(data)+(len)+2, (data)+(len)+3) static uint32_t felica_timeout; static uint32_t felica_nexttransfertime; @@ -35,11 +35,11 @@ static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t *timing bool WaitForFelicaReply(uint16_t maxbytes); void iso18092_set_timeout(uint32_t timeout) { - felica_timeout = timeout + (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/(16*8) + 2; + felica_timeout = timeout + (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/(16*8) + 2; } uint32_t iso18092_get_timeout(void) { - return felica_timeout - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/(16*8) - 2; + return felica_timeout - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/(16*8) - 2; } #ifndef FELICA_MAX_FRAME_SIZE @@ -62,11 +62,11 @@ static struct { uint16_t shiftReg; //for synchronization and offset calculation int posCnt; - bool crc_ok; + bool crc_ok; int rem_len; uint16_t len; uint8_t byte_offset; - uint8_t *framebytes; + uint8_t *framebytes; //should be enough. maxlen is 255, 254 for data, 2 for sync, 2 for crc // 0,1 -> SYNC, 2 - len, 3-(len+1)->data, then crc } FelicaFrame; @@ -84,13 +84,13 @@ static void FelicaFrameReset() { FelicaFrame.byte_offset = 0; } static void FelicaFrameinit(uint8_t *data) { - FelicaFrame.framebytes = data; - FelicaFrameReset(); + FelicaFrame.framebytes = data; + FelicaFrameReset(); } //shift byte into frame, reversing it at the same time static void shiftInByte(uint8_t bt) { - uint8_t j; + uint8_t j; for(j=0; j < FelicaFrame.byte_offset; j++) { FelicaFrame.framebytes[FelicaFrame.posCnt] = ( FelicaFrame.framebytes[FelicaFrame.posCnt]<<1 ) + (bt & 1); bt >>= 1; @@ -105,85 +105,85 @@ static void shiftInByte(uint8_t bt) { static void Process18092Byte(uint8_t bt) { switch (FelicaFrame.state) { - case STATE_UNSYNCD: { - //almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not alsways the case - if (bt > 0) { - FelicaFrame.shiftReg = reflect8(bt); - FelicaFrame.state = STATE_TRYING_SYNC; - } - break; - } - case STATE_TRYING_SYNC: { - if (bt == 0) { - //desync - FelicaFrame.shiftReg = bt; - FelicaFrame.state = STATE_UNSYNCD; - } else { - for (uint8_t i=0; i<8; i++) { + case STATE_UNSYNCD: { + //almost any nonzero byte can be start of SYNC. SYNC should be preceded by zeros, but that is not alsways the case + if (bt > 0) { + FelicaFrame.shiftReg = reflect8(bt); + FelicaFrame.state = STATE_TRYING_SYNC; + } + break; + } + case STATE_TRYING_SYNC: { + if (bt == 0) { + //desync + FelicaFrame.shiftReg = bt; + FelicaFrame.state = STATE_UNSYNCD; + } else { + for (uint8_t i=0; i<8; i++) { - if (FelicaFrame.shiftReg == SYNC_16BIT) { - //SYNC done! - FelicaFrame.state = STATE_GET_LENGTH; - FelicaFrame.framebytes[0] = 0xb2; - FelicaFrame.framebytes[1] = 0x4d; - FelicaFrame.byte_offset = i; - //shift in remaining byte, slowly... - for(uint8_t j=i; j<8; j++) { - FelicaFrame.framebytes[2] = (FelicaFrame.framebytes[2] << 1) + (bt & 1); - bt >>= 1; - } + if (FelicaFrame.shiftReg == SYNC_16BIT) { + //SYNC done! + FelicaFrame.state = STATE_GET_LENGTH; + FelicaFrame.framebytes[0] = 0xb2; + FelicaFrame.framebytes[1] = 0x4d; + FelicaFrame.byte_offset = i; + //shift in remaining byte, slowly... + for(uint8_t j=i; j<8; j++) { + FelicaFrame.framebytes[2] = (FelicaFrame.framebytes[2] << 1) + (bt & 1); + bt >>= 1; + } - FelicaFrame.posCnt = 2; - if (i==0) - break; - } - FelicaFrame.shiftReg = (FelicaFrame.shiftReg << 1) + (bt & 1); - bt >>= 1; - } + FelicaFrame.posCnt = 2; + if (i==0) + break; + } + FelicaFrame.shiftReg = (FelicaFrame.shiftReg << 1) + (bt & 1); + bt >>= 1; + } - //that byte was last byte of sync - if (FelicaFrame.shiftReg == SYNC_16BIT) { - //Force SYNC on next byte - FelicaFrame.state = STATE_GET_LENGTH; - FelicaFrame.framebytes[0] = 0xb2; - FelicaFrame.framebytes[1] = 0x4d; - FelicaFrame.byte_offset = 0; - FelicaFrame.posCnt = 1; - } - } - break; - } - case STATE_GET_LENGTH: { - shiftInByte(bt); - FelicaFrame.rem_len = FelicaFrame.framebytes[2] - 1; - FelicaFrame.len = FelicaFrame.framebytes[2] + 4; //with crc and sync - FelicaFrame.state = STATE_GET_DATA; - break; - } - case STATE_GET_DATA: { - shiftInByte(bt); - if (FelicaFrame.rem_len <= 0) { - FelicaFrame.state = STATE_GET_CRC; - FelicaFrame.rem_len = 2; - } - break; - } - case STATE_GET_CRC: { - shiftInByte(bt); + //that byte was last byte of sync + if (FelicaFrame.shiftReg == SYNC_16BIT) { + //Force SYNC on next byte + FelicaFrame.state = STATE_GET_LENGTH; + FelicaFrame.framebytes[0] = 0xb2; + FelicaFrame.framebytes[1] = 0x4d; + FelicaFrame.byte_offset = 0; + FelicaFrame.posCnt = 1; + } + } + break; + } + case STATE_GET_LENGTH: { + shiftInByte(bt); + FelicaFrame.rem_len = FelicaFrame.framebytes[2] - 1; + FelicaFrame.len = FelicaFrame.framebytes[2] + 4; //with crc and sync + FelicaFrame.state = STATE_GET_DATA; + break; + } + case STATE_GET_DATA: { + shiftInByte(bt); + if (FelicaFrame.rem_len <= 0) { + FelicaFrame.state = STATE_GET_CRC; + FelicaFrame.rem_len = 2; + } + break; + } + case STATE_GET_CRC: { + shiftInByte(bt); - if ( FelicaFrame.rem_len <= 0 ) { - // skip sync 2bytes. IF ok, residue should be 0x0000 - FelicaFrame.crc_ok = check_crc(CRC_FELICA, FelicaFrame.framebytes+2, FelicaFrame.len-2); - FelicaFrame.state = STATE_FULL; - FelicaFrame.rem_len = 0; - if (MF_DBGLEVEL > 3) Dbprintf("[+] got 2 crc bytes [%s]", (FelicaFrame.crc_ok) ? "OK" : "No" ); - } - break; - } - case STATE_FULL: //ignore byte. Don't forget to clear frame to receive next one... - default: - break; - } + if ( FelicaFrame.rem_len <= 0 ) { + // skip sync 2bytes. IF ok, residue should be 0x0000 + FelicaFrame.crc_ok = check_crc(CRC_FELICA, FelicaFrame.framebytes+2, FelicaFrame.len-2); + FelicaFrame.state = STATE_FULL; + FelicaFrame.rem_len = 0; + if (MF_DBGLEVEL > 3) Dbprintf("[+] got 2 crc bytes [%s]", (FelicaFrame.crc_ok) ? "OK" : "No" ); + } + break; + } + case STATE_FULL: //ignore byte. Don't forget to clear frame to receive next one... + default: + break; + } } /* Perform FeliCa polling card @@ -192,64 +192,64 @@ static void Process18092Byte(uint8_t bt) { */ static uint8_t felica_select_card(felica_card_select_t *card) { - // POLL command - // 0xB2 0x4B = sync code - // 0x06 = len - // 0x00 = rfu - // 0xff = system service - // 0xff = system service - // 0x00 = - // b7 = automatic switching of data rate - // b6-b2 = reserved - // b1 = fc/32 (414kbps) - // b0 = fc/64 (212kbps) - // 0x00 = timeslot - // 0x09 0x21 = crc - static uint8_t poll[10] = {0xb2,0x4d,0x06,FELICA_POLL_REQ,0xFF,0xFF,0x00,0x00,0x09,0x21}; + // POLL command + // 0xB2 0x4B = sync code + // 0x06 = len + // 0x00 = rfu + // 0xff = system service + // 0xff = system service + // 0x00 = + // b7 = automatic switching of data rate + // b6-b2 = reserved + // b1 = fc/32 (414kbps) + // b0 = fc/64 (212kbps) + // 0x00 = timeslot + // 0x09 0x21 = crc + static uint8_t poll[10] = {0xb2,0x4d,0x06,FELICA_POLL_REQ,0xFF,0xFF,0x00,0x00,0x09,0x21}; - int len = 20; + int len = 20; - // We try 20 times, or if answer was received. - do { - // end-of-reception response packet data, wait approx. 501μs - // end-of-transmission command packet data, wait approx. 197μs - // polling card - TransmitFor18092_AsReader(poll, sizeof(poll), NULL, 1, 0); + // We try 20 times, or if answer was received. + do { + // end-of-reception response packet data, wait approx. 501μs + // end-of-transmission command packet data, wait approx. 197μs + // polling card + TransmitFor18092_AsReader(poll, sizeof(poll), NULL, 1, 0); - // polling card, break if success - if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK) - break; + // polling card, break if success + if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK) + break; - WDT_HIT(); + WDT_HIT(); - } while (--len); + } while (--len); - // timed-out - if ( len == 0 ) - return 1; + // timed-out + if ( len == 0 ) + return 1; - // wrong answer - if (FelicaFrame.framebytes[3] != FELICA_POLL_ACK) - return 2; + // wrong answer + if (FelicaFrame.framebytes[3] != FELICA_POLL_ACK) + return 2; - // VALIDATE CRC residue is 0, hence if crc is a value it failed. - if (!check_crc(CRC_FELICA, FelicaFrame.framebytes+2, FelicaFrame.len-2)) - return 3; + // VALIDATE CRC residue is 0, hence if crc is a value it failed. + if (!check_crc(CRC_FELICA, FelicaFrame.framebytes+2, FelicaFrame.len-2)) + return 3; - // copy UID - // idm 8 - if (card) { - memcpy(card->IDm, FelicaFrame.framebytes + 4, 8); - memcpy(card->PMm, FelicaFrame.framebytes + 4 + 8, 8); - //memcpy(card->servicecode, FelicaFrame.framebytes + 4 + 8 + 8, 2); - memcpy(card->code, card->IDm, 2); - memcpy(card->uid, card->IDm + 2, 6); - memcpy(card->iccode, card->PMm, 2); - memcpy(card->mrt, card->PMm+2, 6); + // copy UID + // idm 8 + if (card) { + memcpy(card->IDm, FelicaFrame.framebytes + 4, 8); + memcpy(card->PMm, FelicaFrame.framebytes + 4 + 8, 8); + //memcpy(card->servicecode, FelicaFrame.framebytes + 4 + 8 + 8, 2); + memcpy(card->code, card->IDm, 2); + memcpy(card->uid, card->IDm + 2, 6); + memcpy(card->iccode, card->PMm, 2); + memcpy(card->mrt, card->PMm+2, 6); - } - // more status bytes? - return 0; + } + // more status bytes? + return 0; } // poll-0: 0xb2,0x4d,0x06,0x00,0xff,0xff,0x00,0x00,0x09,0x21, @@ -274,34 +274,34 @@ static void BuildFliteRdblk(uint8_t* idm, int blocknum, uint16_t *blocks ) { frameSpace[c++] = 0xb2; frameSpace[c++] = 0x4d; - c++; //set length later + c++; //set length later - frameSpace[c++] = FELICA_RDBLK_REQ; //command number + frameSpace[c++] = FELICA_RDBLK_REQ; //command number - //card IDm, from poll - frameSpace[c++] = idm[0]; - frameSpace[c++] = idm[1]; - frameSpace[c++] = idm[2]; - frameSpace[c++] = idm[3]; - frameSpace[c++] = idm[4]; - frameSpace[c++] = idm[5]; - frameSpace[c++] = idm[6]; - frameSpace[c++] = idm[7]; + //card IDm, from poll + frameSpace[c++] = idm[0]; + frameSpace[c++] = idm[1]; + frameSpace[c++] = idm[2]; + frameSpace[c++] = idm[3]; + frameSpace[c++] = idm[4]; + frameSpace[c++] = idm[5]; + frameSpace[c++] = idm[6]; + frameSpace[c++] = idm[7]; - //number of services + //number of services frameSpace[c++] = 0x01; - //service code - frameSpace[c++] = (SERVICE_FELICA_LITE_READONLY >> 8); + //service code + frameSpace[c++] = (SERVICE_FELICA_LITE_READONLY >> 8); frameSpace[c++] = SERVICE_FELICA_LITE_READONLY & 0xFF; - //number of blocks + //number of blocks frameSpace[c++] = blocknum; for (i=0; i < blocknum; i++) { - //3-byte block - if (blocks[i] >= 256) { + //3-byte block + if (blocks[i] >= 256) { frameSpace[c++] = 0x00; frameSpace[c++] = (blocks[i] >> 8); //block number, little endian.... frameSpace[c++] = (blocks[i] & 0xff); @@ -311,70 +311,70 @@ static void BuildFliteRdblk(uint8_t* idm, int blocknum, uint16_t *blocks ) { } } - //set length + //set length frameSpace[2] = c-2; AddCrc(frameSpace, c-2); } static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t *timing, uint8_t power, uint8_t highspeed) { - uint8_t flags = FPGA_MAJOR_MODE_ISO18092; + uint8_t flags = FPGA_MAJOR_MODE_ISO18092; - if ( power ) - flags |= FPGA_HF_ISO18092_FLAG_READER; - if (highspeed) - flags |= FPGA_HF_ISO18092_FLAG_424K; + if ( power ) + flags |= FPGA_HF_ISO18092_FLAG_READER; + if (highspeed) + flags |= FPGA_HF_ISO18092_FLAG_424K; - FpgaWriteConfWord(flags); + FpgaWriteConfWord(flags); - uint32_t curr_transfer_time = ((MAX(felica_nexttransfertime, GetCountSspClk()) & 0xfffffff8) + 8); + uint32_t curr_transfer_time = ((MAX(felica_nexttransfertime, GetCountSspClk()) & 0xfffffff8) + 8); - while (GetCountSspClk() < curr_transfer_time) {}; + while (GetCountSspClk() < curr_transfer_time) {}; - felica_lasttime_prox2air_start = curr_transfer_time; + felica_lasttime_prox2air_start = curr_transfer_time; // preamble - // sending 0x00 0x00 0x00 0x00 0x00 0x00 - uint16_t c = 0; - while (c < 6) { + // sending 0x00 0x00 0x00 0x00 0x00 0x00 + uint16_t c = 0; + while (c < 6) { - // keep tx buffer in a defined state anyway. - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x00; - c++; - } - } - // sending sync code + // keep tx buffer in a defined state anyway. + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0x00; + c++; + } + } + // sending sync code - // sending data - c = 0; - while (c < len) { + // sending data + c = 0; + while (c < len) { - // Put byte into tx holding register as soon as it is ready - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = frame[c++]; - } - } + // Put byte into tx holding register as soon as it is ready + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = frame[c++]; + } + } /**/ - while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {}; - AT91C_BASE_SSC->SSC_THR = 0x00; //minimum delay + while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {}; + AT91C_BASE_SSC->SSC_THR = 0x00; //minimum delay - while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {}; - AT91C_BASE_SSC->SSC_THR = 0x00; //spin + while (!(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY))) {}; + AT91C_BASE_SSC->SSC_THR = 0x00; //spin /**/ - // log - LogTrace( - frame, - len, - (felica_lasttime_prox2air_start<<4) + DELAY_ARM2AIR_AS_READER, - ((felica_lasttime_prox2air_start + felica_lasttime_prox2air_start)<<4) + DELAY_ARM2AIR_AS_READER, - NULL, - true - ); + // log + LogTrace( + frame, + len, + (felica_lasttime_prox2air_start<<4) + DELAY_ARM2AIR_AS_READER, + ((felica_lasttime_prox2air_start + felica_lasttime_prox2air_start)<<4) + DELAY_ARM2AIR_AS_READER, + NULL, + true + ); - felica_nexttransfertime = MAX(felica_nexttransfertime ,felica_lasttime_prox2air_start + FELICA_REQUEST_GUARD_TIME); + felica_nexttransfertime = MAX(felica_nexttransfertime ,felica_lasttime_prox2air_start + FELICA_REQUEST_GUARD_TIME); } // Wait for tag reply @@ -382,161 +382,161 @@ static void TransmitFor18092_AsReader(uint8_t * frame, int len, uint32_t *timing // or return TRUE when command is captured bool WaitForFelicaReply(uint16_t maxbytes) { - uint32_t c = 0; + uint32_t c = 0; - // power, no modulation - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); + // power, no modulation + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); - FelicaFrameReset(); + FelicaFrameReset(); - // clear RXRDY: - uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + // clear RXRDY: + uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - uint32_t timeout = iso18092_get_timeout(); - for(;;) { + uint32_t timeout = iso18092_get_timeout(); + for(;;) { WDT_HIT(); - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - b = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); - Process18092Byte(b); - if (FelicaFrame.state == STATE_FULL) { - felica_nexttransfertime = - MAX( - felica_nexttransfertime, - (GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/16 + FELICA_FRAME_DELAY_TIME - ) - ; + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + b = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); + Process18092Byte(b); + if (FelicaFrame.state == STATE_FULL) { + felica_nexttransfertime = + MAX( + felica_nexttransfertime, + (GetCountSspClk() & 0xfffffff8) - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/16 + FELICA_FRAME_DELAY_TIME + ) + ; - LogTrace( - FelicaFrame.framebytes, - FelicaFrame.len, - ((GetCountSspClk() & 0xfffffff8)<<4) - DELAY_AIR2ARM_AS_READER - timeout, - ((GetCountSspClk() & 0xfffffff8)<<4) - DELAY_AIR2ARM_AS_READER, - NULL, - false - ); - return true; - } else if (c++ > timeout && FelicaFrame.state == STATE_UNSYNCD) { - return false; - } else if (FelicaFrame.state == STATE_GET_CRC) { - Dbprintf(" Frame: "); - Dbhexdump(16, FelicaFrame.framebytes, 0); - //return false; - } - } - } - return false; + LogTrace( + FelicaFrame.framebytes, + FelicaFrame.len, + ((GetCountSspClk() & 0xfffffff8)<<4) - DELAY_AIR2ARM_AS_READER - timeout, + ((GetCountSspClk() & 0xfffffff8)<<4) - DELAY_AIR2ARM_AS_READER, + NULL, + false + ); + return true; + } else if (c++ > timeout && FelicaFrame.state == STATE_UNSYNCD) { + return false; + } else if (FelicaFrame.state == STATE_GET_CRC) { + Dbprintf(" Frame: "); + Dbhexdump(16, FelicaFrame.framebytes, 0); + //return false; + } + } + } + return false; } // Set up FeliCa communication (similar to iso14443a_setup) // field is setup for "Sending as Reader" static void iso18092_setup(uint8_t fpga_minor_mode) { - LEDsoff(); - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + LEDsoff(); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - // allocate command receive buffer - BigBuf_free(); BigBuf_Clear_ext(false); + // allocate command receive buffer + BigBuf_free(); BigBuf_Clear_ext(false); - // Initialize Demod and Uart structs - //DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); - FelicaFrameinit(BigBuf_malloc(FELICA_MAX_FRAME_SIZE)); + // Initialize Demod and Uart structs + //DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); + FelicaFrameinit(BigBuf_malloc(FELICA_MAX_FRAME_SIZE)); - felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER; - iso18092_set_timeout(2120); // 106 * 20ms maximum start-up time of card + felica_nexttransfertime = 2 * DELAY_ARM2AIR_AS_READER; + iso18092_set_timeout(2120); // 106 * 20ms maximum start-up time of card - init_table(CRC_FELICA); + init_table(CRC_FELICA); - // connect Demodulated Signal to ADC: - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + // connect Demodulated Signal to ADC: + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - // Set up the synchronous serial port - FpgaSetupSsc(); + // Set up the synchronous serial port + FpgaSetupSsc(); - // LSB transfer. Remember to set it back to MSB with - AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); + // LSB transfer. Remember to set it back to MSB with + AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - // Signal field is on with the appropriate LED - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | fpga_minor_mode); + // Signal field is on with the appropriate LED + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | fpga_minor_mode); - //20.4 ms generate field, start sending polling command afterwars. - SpinDelay(100); + //20.4 ms generate field, start sending polling command afterwars. + SpinDelay(100); - // Start the timer - StartCountSspClk(); + // Start the timer + StartCountSspClk(); - LED_D_ON(); + LED_D_ON(); } //----------------------------------------------------------------------------- // RAW FeliCa commands. Send out commands and store answers. //----------------------------------------------------------------------------- -// arg0 FeliCa flags -// arg1 len of commandbytes +// arg0 FeliCa flags +// arg1 len of commandbytes // d.asBytes command bytes to send void felica_sendraw(UsbCommand *c) { - if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Enter"); + if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Enter"); - felica_command_t param = c->arg[0]; - size_t len = c->arg[1] & 0xffff; - uint8_t *cmd = c->d.asBytes; - uint32_t arg0 = 0; + felica_command_t param = c->arg[0]; + size_t len = c->arg[1] & 0xffff; + uint8_t *cmd = c->d.asBytes; + uint32_t arg0 = 0; - felica_card_select_t card; + felica_card_select_t card; - if ((param & FELICA_CONNECT)) - clear_trace(); + if ((param & FELICA_CONNECT)) + clear_trace(); - set_tracing(true); + set_tracing(true); - if ((param & FELICA_CONNECT)) { - iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); + if ((param & FELICA_CONNECT)) { + iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); - // notify client selecting status. - // if failed selecting, turn off antenna and quite. - if( !(param & FELICA_NO_SELECT) ) { - arg0 = felica_select_card(&card); - cmd_send(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t)); - if ( arg0 > 0 ) - goto OUT; - } - } + // notify client selecting status. + // if failed selecting, turn off antenna and quite. + if( !(param & FELICA_NO_SELECT) ) { + arg0 = felica_select_card(&card); + cmd_send(CMD_ACK, arg0, sizeof(card.uid), 0, &card, sizeof(felica_card_select_t)); + if ( arg0 > 0 ) + goto OUT; + } + } - if ((param & FELICA_RAW)) { + if ((param & FELICA_RAW)) { - // 2 sync, 1 len, 2crc == 5 - uint8_t *buf = BigBuf_malloc(len+5); - // add sync bits - buf[0] = 0xb2; - buf[1] = 0x4d; - buf[2] = len; + // 2 sync, 1 len, 2crc == 5 + uint8_t *buf = BigBuf_malloc(len+5); + // add sync bits + buf[0] = 0xb2; + buf[1] = 0x4d; + buf[2] = len; - // copy command - memcpy(buf+2, cmd, len); + // copy command + memcpy(buf+2, cmd, len); - if ((param & FELICA_APPEND_CRC)) { - // Don't append crc on empty bytearray... - if ( len > 0 ) { - AddCrc(buf, len); - len += 2; - } - } + if ((param & FELICA_APPEND_CRC)) { + // Don't append crc on empty bytearray... + if ( len > 0 ) { + AddCrc(buf, len); + len += 2; + } + } - TransmitFor18092_AsReader(buf, buf[2]+4, NULL, 1, 0); - arg0 = !WaitForFelicaReply(1024); - cmd_send(CMD_ACK, arg0, 0, 0, FelicaFrame.framebytes+2, FelicaFrame.len-2); - } + TransmitFor18092_AsReader(buf, buf[2]+4, NULL, 1, 0); + arg0 = !WaitForFelicaReply(1024); + cmd_send(CMD_ACK, arg0, 0, 0, FelicaFrame.framebytes+2, FelicaFrame.len-2); + } - if ((param & FELICA_NO_DISCONNECT)) - return; + if ((param & FELICA_NO_DISCONNECT)) + return; OUT: - switch_off(); + switch_off(); - //Resetting Frame mode (First set in fpgaloader.c) + //Resetting Frame mode (First set in fpgaloader.c) AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Exit"); + if (MF_DBGLEVEL > 3) Dbprintf("FeliCa_sendraw Exit"); } void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { @@ -545,11 +545,11 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { Dbprintf("Snoop FelicaLiteS: Getting first %d frames, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); - iso18092_setup( FPGA_HF_ISO18092_FLAG_NOMOD); + iso18092_setup( FPGA_HF_ISO18092_FLAG_NOMOD); //the frame bits are slow enough. int n = BigBuf_max_traceLen() / sizeof(uint8_t); // take all memory - int numbts = 0; + int numbts = 0; uint8_t *dest = (uint8_t *)BigBuf_get_addr(); uint8_t *destend = dest + n-2; @@ -557,13 +557,13 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { while (dest <= destend) { WDT_HIT(); - if( BUTTON_PRESS()) break; + if( BUTTON_PRESS()) break; if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); Process18092Byte(dist); - //to be sure we are in frame + //to be sure we are in frame if (FelicaFrame.state == STATE_GET_LENGTH) { //length is after 48 (PRE)+16 (SYNC) - 64 ticks +maybe offset? not 100% uint16_t distance = GetCountSspClk() - endframe - 64 + (FelicaFrame.byte_offset > 0 ? (8-FelicaFrame.byte_offset) : 0); @@ -572,7 +572,7 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { *dest = (distance & 0xff); dest++; } - //crc NOT checked + //crc NOT checked if (FelicaFrame.state == STATE_FULL) { endframe = GetCountSspClk(); //*dest = FelicaFrame.crc_ok; //kind of wasteful @@ -590,19 +590,19 @@ void felica_sniff(uint32_t samplesToSkip, uint32_t triggersToSkip) { numbts += FelicaFrame.len; - FelicaFrameReset(); + FelicaFrameReset(); } } } - switch_off(); + switch_off(); //reset framing AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); set_tracelen(numbts); Dbprintf("Felica sniffing done, tracelen: %i, use hf list felica for annotations", BigBuf_get_traceLen()); - cmd_send(CMD_ACK,1, numbts,0,0,0); + cmd_send(CMD_ACK,1, numbts,0,0,0); } #define R_POLL0_LEN 0x16 @@ -615,19 +615,19 @@ void felica_sim_lite(uint64_t nfcid) { int i, curlen = 0; uint8_t *curresp = 0; - uint8_t ndef[8]; - num_to_bytes(nfcid, 8, ndef); + uint8_t ndef[8]; + num_to_bytes(nfcid, 8, ndef); - //prepare our 3 responses... + //prepare our 3 responses... uint8_t resp_poll0[R_POLL0_LEN] = { 0xb2,0x4d,0x12,FELICA_POLL_ACK,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; uint8_t resp_poll1[R_POLL1_LEN] = { 0xb2,0x4d,0x14,FELICA_POLL_ACK,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00, 0x88,0xb4,0xb3,0x7f}; uint8_t resp_readblk[R_READBLK_LEN] = { 0xb2,0x4d,0x1d,FELICA_RDBLK_ACK,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x10,0x04,0x01,0x00,0x0d,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x00,0x00,0x00,0x23,0xcb,0x6e}; - //NFC tag 3/ ISo technically. Many overlapping standards + //NFC tag 3/ ISo technically. Many overlapping standards DbpString("Felica Lite-S sim start"); Dbprintf("NDEF2 UID: %02x %02x %02x %02x %02x %02x %02x %02x", - ndef[0], ndef[1], ndef[2], ndef[3], ndef[4], ndef[5], ndef[6], ndef[7] - ); + ndef[0], ndef[1], ndef[2], ndef[3], ndef[4], ndef[5], ndef[6], ndef[7] + ); //fill in blanks for( i=0; i<8; i++) { @@ -641,21 +641,21 @@ void felica_sim_lite(uint64_t nfcid) { AddCrc(resp_poll1, resp_poll1[2]); AddCrc(resp_readblk, resp_readblk[2]); - iso18092_setup( FPGA_HF_ISO18092_FLAG_NOMOD); + iso18092_setup( FPGA_HF_ISO18092_FLAG_NOMOD); - bool listenmode = true; - //uint32_t frtm = GetCountSspClk(); + bool listenmode = true; + //uint32_t frtm = GetCountSspClk(); for(;;) { - if( BUTTON_PRESS()) break; + if( BUTTON_PRESS()) break; WDT_HIT(); if (listenmode) { //waiting for request... if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); - //frtm = GetCountSspClk(); - Process18092Byte(dist); + uint8_t dist = (uint8_t)(AT91C_BASE_SSC->SSC_RHR); + //frtm = GetCountSspClk(); + Process18092Byte(dist); if (FelicaFrame.state == STATE_FULL) { @@ -663,17 +663,17 @@ void felica_sim_lite(uint64_t nfcid) { if (FelicaFrame.framebytes[2] == 6 && FelicaFrame.framebytes[3] == 0) { - //polling... there are two types of polling we answer to - if (FelicaFrame.framebytes[6] == 0) { - curresp = resp_poll0; - curlen = R_POLL0_LEN; - listenmode = false; - } - if (FelicaFrame.framebytes[6] == 1) { - curresp = resp_poll1; - curlen = R_POLL1_LEN; - listenmode = true; - } + //polling... there are two types of polling we answer to + if (FelicaFrame.framebytes[6] == 0) { + curresp = resp_poll0; + curlen = R_POLL0_LEN; + listenmode = false; + } + if (FelicaFrame.framebytes[6] == 1) { + curresp = resp_poll1; + curlen = R_POLL1_LEN; + listenmode = true; + } } if (FelicaFrame.framebytes[2] > 5 && FelicaFrame.framebytes[3] == 0x06) { @@ -687,30 +687,30 @@ void felica_sim_lite(uint64_t nfcid) { FelicaFrameReset(); } else { //frame invalid, clear it out to allow for the next one - FelicaFrameReset(); - } - } - } - } - if (!listenmode) { - //trying to answer... here to start answering immediately. - //this one is a bit finicky. Seems that being a bit late is better than earlier - //TransmitFor18092_AsReader(curresp, curlen, frtm+512, 0, 0); - TransmitFor18092_AsReader(curresp, curlen, NULL, 0, 0); + FelicaFrameReset(); + } + } + } + } + if (!listenmode) { + //trying to answer... here to start answering immediately. + //this one is a bit finicky. Seems that being a bit late is better than earlier + //TransmitFor18092_AsReader(curresp, curlen, frtm+512, 0, 0); + TransmitFor18092_AsReader(curresp, curlen, NULL, 0, 0); - //switch back - FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD); + //switch back + FpgaWriteConfWord(FPGA_MAJOR_MODE_ISO18092 | FPGA_HF_ISO18092_FLAG_NOMOD); - FelicaFrameReset(); - listenmode = true; - curlen = 0; - curresp = NULL; + FelicaFrameReset(); + listenmode = true; + curlen = 0; + curresp = NULL; } } switch_off(); - //reset framing + //reset framing AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); DbpString("Felica Lite-S sim end"); @@ -718,80 +718,80 @@ void felica_sim_lite(uint64_t nfcid) { void felica_dump_lite_s() { - uint8_t ndef[8]; - uint8_t poll[10] = { 0xb2,0x4d,0x06,FELICA_POLL_REQ,0xff,0xff,0x00,0x00,0x09,0x21}; - uint16_t liteblks[28] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x90,0x91,0x92,0xa0}; + uint8_t ndef[8]; + uint8_t poll[10] = { 0xb2,0x4d,0x06,FELICA_POLL_REQ,0xff,0xff,0x00,0x00,0x09,0x21}; + uint16_t liteblks[28] = {0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,0x08,0x09,0x0a,0x0b,0x0c,0x0d,0x0e,0x80,0x81,0x82,0x83,0x84,0x85,0x86,0x87,0x88,0x90,0x91,0x92,0xa0}; - // setup device. - iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); + // setup device. + iso18092_setup(FPGA_HF_ISO18092_FLAG_READER | FPGA_HF_ISO18092_FLAG_NOMOD); - uint8_t blknum; - bool isOK = false; - uint16_t cnt = 0, cntfails = 0; - uint8_t *dest = BigBuf_get_addr(); + uint8_t blknum; + bool isOK = false; + uint16_t cnt = 0, cntfails = 0; + uint8_t *dest = BigBuf_get_addr(); - while (!BUTTON_PRESS() && !usb_poll_validate_length()) { + while (!BUTTON_PRESS() && !usb_poll_validate_length()) { - WDT_HIT(); + WDT_HIT(); - // polling? - //TransmitFor18092_AsReader(poll, 10, GetCountSspClk()+512, 1, 0); - TransmitFor18092_AsReader(poll, 10, NULL, 1, 0); + // polling? + //TransmitFor18092_AsReader(poll, 10, GetCountSspClk()+512, 1, 0); + TransmitFor18092_AsReader(poll, 10, NULL, 1, 0); - if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK) { + if (WaitForFelicaReply(512) && FelicaFrame.framebytes[3] == FELICA_POLL_ACK) { - // copy 8bytes to ndef. - memcpy(ndef, FelicaFrame.framebytes + 4, 8); - // for (c=0; c < 8; c++) - // ndef[c] = FelicaFrame.framebytes[c+4]; + // copy 8bytes to ndef. + memcpy(ndef, FelicaFrame.framebytes + 4, 8); + // for (c=0; c < 8; c++) + // ndef[c] = FelicaFrame.framebytes[c+4]; - for (blknum=0; blknum < sizeof(liteblks); ) { + for (blknum=0; blknum < sizeof(liteblks); ) { - // block to read. - BuildFliteRdblk(ndef, 1, &liteblks[blknum]); + // block to read. + BuildFliteRdblk(ndef, 1, &liteblks[blknum]); - //TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, GetCountSspClk()+512, 1, 0); - TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, NULL, 1, 0); + //TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, GetCountSspClk()+512, 1, 0); + TransmitFor18092_AsReader(frameSpace, frameSpace[2]+4, NULL, 1, 0); - // read block - if (WaitForFelicaReply(1024) && FelicaFrame.framebytes[3] == FELICA_RDBLK_ACK) { + // read block + if (WaitForFelicaReply(1024) && FelicaFrame.framebytes[3] == FELICA_RDBLK_ACK) { - dest[cnt++] = liteblks[blknum]; + dest[cnt++] = liteblks[blknum]; - uint8_t *fb = FelicaFrame.framebytes; - dest[cnt++] = fb[12]; - dest[cnt++] = fb[13]; + uint8_t *fb = FelicaFrame.framebytes; + dest[cnt++] = fb[12]; + dest[cnt++] = fb[13]; - //memcpy(dest+cnt, FelicaFrame.framebytes + 15, 16); - //cnt += 16; - for(uint8_t j=0; j < 16; j++) - dest[cnt++] = fb[15+j]; + //memcpy(dest+cnt, FelicaFrame.framebytes + 15, 16); + //cnt += 16; + for(uint8_t j=0; j < 16; j++) + dest[cnt++] = fb[15+j]; - blknum++; - cntfails = 0; + blknum++; + cntfails = 0; - // // print raw log. - // Dbprintf("LEN %u | Dump bytes count %u ", FelicaFrame.len, cnt); - Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes+15, 0); - } else { - cntfails++; - if (cntfails > 12) { - blknum++; - cntfails = 0; - } - } - } - isOK = true; - break; - } - } + // // print raw log. + // Dbprintf("LEN %u | Dump bytes count %u ", FelicaFrame.len, cnt); + Dbhexdump(FelicaFrame.len, FelicaFrame.framebytes+15, 0); + } else { + cntfails++; + if (cntfails > 12) { + blknum++; + cntfails = 0; + } + } + } + isOK = true; + break; + } + } - switch_off(); + switch_off(); - //Resetting Frame mode (First set in fpgaloader.c) + //Resetting Frame mode (First set in fpgaloader.c) AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - //setting tracelen - important! it was set by buffer overflow before + //setting tracelen - important! it was set by buffer overflow before set_tracelen(cnt); - cmd_send(CMD_ACK, isOK, cnt, 0, 0, 0); + cmd_send(CMD_ACK, isOK, cnt, 0, 0, 0); } diff --git a/armsrc/flashmem.c b/armsrc/flashmem.c index c3b7a6e82..1c9304c43 100644 --- a/armsrc/flashmem.c +++ b/armsrc/flashmem.c @@ -18,118 +18,118 @@ void FlashmemSetSpiBaudrate(uint32_t baudrate){ Dbprintf("Spi Baudrate : %dMhz", FLASHMEM_SPIBAUDRATE/1000000); } -// initialize +// initialize bool FlashInit() { - FlashSetup(FLASHMEM_SPIBAUDRATE); + FlashSetup(FLASHMEM_SPIBAUDRATE); - StartTicks(); + StartTicks(); - if (Flash_CheckBusy(BUSY_TIMEOUT)) { - StopTicks(); - return false; - } + if (Flash_CheckBusy(BUSY_TIMEOUT)) { + StopTicks(); + return false; + } - return true; + return true; } void FlashSetup(uint32_t baudrate){ //WDT_DISABLE AT91C_BASE_WDTC->WDTC_WDMR = AT91C_WDTC_WDDIS; - // PA10 -> SPI_NCS2 chip select (FLASHMEM) - // PA11 -> SPI_NCS0 chip select (FPGA) - // PA12 -> SPI_MISO Master-In Slave-Out - // PA13 -> SPI_MOSI Master-Out Slave-In - // PA14 -> SPI_SPCK Serial Clock + // PA10 -> SPI_NCS2 chip select (FLASHMEM) + // PA11 -> SPI_NCS0 chip select (FPGA) + // PA12 -> SPI_MISO Master-In Slave-Out + // PA13 -> SPI_MOSI Master-Out Slave-In + // PA14 -> SPI_SPCK Serial Clock - // Disable PIO control of the following pins, allows use by the SPI peripheral - AT91C_BASE_PIOA->PIO_PDR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2); + // Disable PIO control of the following pins, allows use by the SPI peripheral + AT91C_BASE_PIOA->PIO_PDR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2); - // Pull-up Enable - AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2); + // Pull-up Enable + AT91C_BASE_PIOA->PIO_PPUER |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK | GPIO_NCS2); - // Peripheral A - AT91C_BASE_PIOA->PIO_ASR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK); + // Peripheral A + AT91C_BASE_PIOA->PIO_ASR |= (GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK); - // Peripheral B - AT91C_BASE_PIOA->PIO_BSR |= GPIO_NCS2; + // Peripheral B + AT91C_BASE_PIOA->PIO_BSR |= GPIO_NCS2; - //enable the SPI Peripheral clock - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI); + //enable the SPI Peripheral clock + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI); - //reset spi needs double SWRST, see atmel's errata on this case - AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; - AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; + //reset spi needs double SWRST, see atmel's errata on this case + AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; + AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SWRST; - // Enable SPI - AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN; + // Enable SPI + AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN; - // NPCS2 Mode 0 - AT91C_BASE_SPI->SPI_MR = - (0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT: - // If DLYBCS is less than or equal to six, six MCK periods - // will be inserted by default. - SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10) - ( 0 << 7) | // Disable LLB (1=MOSI2MISO test mode) - ( 1 << 4) | // Disable ModeFault Protection - ( 0 << 3) | // makes spi operate at MCK (1 is MCK/2) - ( 0 << 2) | // Chip selects connected directly to peripheral - AT91C_SPI_PS_FIXED | // Fixed Peripheral Select - AT91C_SPI_MSTR; // Master Mode + // NPCS2 Mode 0 + AT91C_BASE_SPI->SPI_MR = + (0 << 24) | // Delay between chip selects = DYLBCS/MCK BUT: + // If DLYBCS is less than or equal to six, six MCK periods + // will be inserted by default. + SPI_PCS(SPI_CSR_NUM) | // Peripheral Chip Select (selects SPI_NCS2 or PA10) + ( 0 << 7) | // Disable LLB (1=MOSI2MISO test mode) + ( 1 << 4) | // Disable ModeFault Protection + ( 0 << 3) | // makes spi operate at MCK (1 is MCK/2) + ( 0 << 2) | // Chip selects connected directly to peripheral + AT91C_SPI_PS_FIXED | // Fixed Peripheral Select + AT91C_SPI_MSTR; // Master Mode - uint8_t csaat = 1; - uint32_t dlybct = 0; + uint8_t csaat = 1; + uint32_t dlybct = 0; if (baudrate > FLASH_MINFAST) { - baudrate = FLASH_FASTBAUD; - //csaat = 0; - dlybct = 1500; - } + baudrate = FLASH_FASTBAUD; + //csaat = 0; + dlybct = 1500; + } - AT91C_BASE_SPI->SPI_CSR[2] = - SPI_DLYBCT(dlybct,MCK) | // Delay between Consecutive Transfers (32 MCK periods) - SPI_DLYBS(0,MCK) | // Delay Beforce SPCK CLock - SPI_SCBR(baudrate,MCK) | // SPI Baudrate Selection - AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits) - //AT91C_SPI_CSAAT | // Chip Select inactive after transfer - // 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1 - // If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on - // the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been - // transferred in the shifter. This can imply for example, that the second data is sent twice. - // COLIN :: For now we STILL use CSAAT=1 to avoid having to (de)assert NPCS manually via PIO lines and we deal with delay - ( csaat << 3) | - /* Spi modes: - Mode CPOL CPHA NCPHA - 0 0 0 1 clock normally low read on rising edge - 1 0 1 0 clock normally low read on falling edge - 2 1 0 1 clock normally high read on falling edge - 3 1 1 0 clock normally high read on rising edge - However, page 512 of the AT91SAM7Sx datasheet say "Note that in SPI - master mode the ATSAM7S512/256/128/64/321/32 does not sample the data - (MISO) on the opposite edge where data clocks out (MOSI) but the same - edge is used as shown in Figure 36-3 and Figure 36-4." Figure 36-3 - shows that CPOL=NCPHA=0 or CPOL=NCPHA=1 samples on the rising edge and - that the data changes sometime after the rising edge (about 2 ns). To - be consistent with normal SPI operation, it is probably safe to say - that the data changes on the falling edge and should be sampled on the - rising edge. Therefore, it appears that NCPHA should be treated the - same as CPHA. Thus: - Mode CPOL CPHA NCPHA - 0 0 0 0 clock normally low read on rising edge - 1 0 1 1 clock normally low read on falling edge - 2 1 0 0 clock normally high read on falling edge - 3 1 1 1 clock normally high read on rising edge - */ - ( 0 << 1) | // Clock Phase data captured on leading edge, changes on following edge - ( 0 << 0); // Clock Polarity inactive state is logic 0 + AT91C_BASE_SPI->SPI_CSR[2] = + SPI_DLYBCT(dlybct,MCK)| // Delay between Consecutive Transfers (32 MCK periods) + SPI_DLYBS(0,MCK) | // Delay Beforce SPCK CLock + SPI_SCBR(baudrate,MCK)| // SPI Baudrate Selection + AT91C_SPI_BITS_8 | // Bits per Transfer (8 bits) + //AT91C_SPI_CSAAT | // Chip Select inactive after transfer + // 40.4.6.2 SPI: Bad tx_ready Behavior when CSAAT = 1 and SCBR = 1 + // If the SPI is programmed with CSAAT = 1, SCBR(baudrate) = 1 and two transfers are performed consecutively on + // the same slave with an IDLE state between them, the tx_ready signal does not rise after the second data has been + // transferred in the shifter. This can imply for example, that the second data is sent twice. + // COLIN :: For now we STILL use CSAAT=1 to avoid having to (de)assert NPCS manually via PIO lines and we deal with delay + ( csaat << 3) | + /* Spi modes: + Mode CPOL CPHA NCPHA + 0 0 0 1 clock normally low read on rising edge + 1 0 1 0 clock normally low read on falling edge + 2 1 0 1 clock normally high read on falling edge + 3 1 1 0 clock normally high read on rising edge + However, page 512 of the AT91SAM7Sx datasheet say "Note that in SPI + master mode the ATSAM7S512/256/128/64/321/32 does not sample the data + (MISO) on the opposite edge where data clocks out (MOSI) but the same + edge is used as shown in Figure 36-3 and Figure 36-4." Figure 36-3 + shows that CPOL=NCPHA=0 or CPOL=NCPHA=1 samples on the rising edge and + that the data changes sometime after the rising edge (about 2 ns). To + be consistent with normal SPI operation, it is probably safe to say + that the data changes on the falling edge and should be sampled on the + rising edge. Therefore, it appears that NCPHA should be treated the + same as CPHA. Thus: + Mode CPOL CPHA NCPHA + 0 0 0 0 clock normally low read on rising edge + 1 0 1 1 clock normally low read on falling edge + 2 1 0 0 clock normally high read on falling edge + 3 1 1 1 clock normally high read on rising edge + */ + ( 0 << 1) | // Clock Phase data captured on leading edge, changes on following edge + ( 0 << 0); // Clock Polarity inactive state is logic 0 - // read first, empty buffer - if (AT91C_BASE_SPI->SPI_RDR == 0) {}; + // read first, empty buffer + if (AT91C_BASE_SPI->SPI_RDR == 0) {}; } void FlashStop(void) { - //Bof - //* Reset all the Chip Select register + //Bof + //* Reset all the Chip Select register AT91C_BASE_SPI->SPI_CSR[0] = 0; AT91C_BASE_SPI->SPI_CSR[1] = 0; AT91C_BASE_SPI->SPI_CSR[2] = 0; @@ -141,164 +141,164 @@ void FlashStop(void) { // Disable all interrupts AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF; - // SPI disable - AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS; + // SPI disable + AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS; - if ( MF_DBGLEVEL > 3 ) Dbprintf("FlashStop"); + if ( MF_DBGLEVEL > 3 ) Dbprintf("FlashStop"); - StopTicks(); + StopTicks(); } -// send one byte over SPI +// send one byte over SPI uint16_t FlashSendByte(uint32_t data) { - // wait until SPI is ready for transfer - //if you are checking for incoming data returned then the TXEMPTY flag is redundant - //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {}; + // wait until SPI is ready for transfer + //if you are checking for incoming data returned then the TXEMPTY flag is redundant + //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0) {}; - // send the data - AT91C_BASE_SPI->SPI_TDR = data; + // send the data + AT91C_BASE_SPI->SPI_TDR = data; //while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TDRE) == 0){}; - // wait recive transfer is complete - while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0){}; + // wait recive transfer is complete + while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF) == 0){}; - // reading incoming data - return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF); + // reading incoming data + return ((AT91C_BASE_SPI->SPI_RDR) & 0xFFFF); } -// send last byte over SPI +// send last byte over SPI uint16_t FlashSendLastByte(uint32_t data) { - return FlashSendByte(data | AT91C_SPI_LASTXFER); + return FlashSendByte(data | AT91C_SPI_LASTXFER); } -// read state register 1 +// read state register 1 uint8_t Flash_ReadStat1(void) { - FlashSendByte(READSTAT1); - return FlashSendLastByte(0xFF); + FlashSendByte(READSTAT1); + return FlashSendLastByte(0xFF); } bool Flash_CheckBusy(uint32_t timeout) { - WaitUS(WINBOND_WRITE_DELAY); - StartCountUS(); - uint32_t _time = GetCountUS(); + WaitUS(WINBOND_WRITE_DELAY); + StartCountUS(); + uint32_t _time = GetCountUS(); - if ( MF_DBGLEVEL > 3 ) Dbprintf("Checkbusy in..."); + if ( MF_DBGLEVEL > 3 ) Dbprintf("Checkbusy in..."); - do - { - if (!(Flash_ReadStat1() & BUSY)) - { - return false; - } - } while ((GetCountUS() - _time) < timeout); + do + { + if (!(Flash_ReadStat1() & BUSY)) + { + return false; + } + } while ((GetCountUS() - _time) < timeout); - if (timeout <= (GetCountUS() - _time)) - { - return true; - } + if (timeout <= (GetCountUS() - _time)) + { + return true; + } - return false; + return false; } // read ID out uint8_t Flash_ReadID(void) { - if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0; + if (Flash_CheckBusy(BUSY_TIMEOUT)) return 0; - // Manufacture ID / device ID - FlashSendByte(ID); - FlashSendByte(0x00); - FlashSendByte(0x00); - FlashSendByte(0x00); + // Manufacture ID / device ID + FlashSendByte(ID); + FlashSendByte(0x00); + FlashSendByte(0x00); + FlashSendByte(0x00); uint8_t man_id = FlashSendByte(0xFF); - uint8_t dev_id = FlashSendLastByte(0xFF); + uint8_t dev_id = FlashSendLastByte(0xFF); - if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash ReadID | Man ID %02x | Device ID %02x", man_id, dev_id); + if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash ReadID | Man ID %02x | Device ID %02x", man_id, dev_id); - if ( (man_id == WINBOND_MANID ) && (dev_id == WINBOND_DEVID) ) - return dev_id; + if ( (man_id == WINBOND_MANID ) && (dev_id == WINBOND_DEVID) ) + return dev_id; - return 0; + return 0; } // read unique id for chip. void Flash_UniqueID(uint8_t *uid) { - if (Flash_CheckBusy(BUSY_TIMEOUT)) return; + if (Flash_CheckBusy(BUSY_TIMEOUT)) return; - // reading unique serial number - FlashSendByte(UNIQUE_ID); - FlashSendByte(0xFF); - FlashSendByte(0xFF); - FlashSendByte(0xFF); - FlashSendByte(0xFF); + // reading unique serial number + FlashSendByte(UNIQUE_ID); + FlashSendByte(0xFF); + FlashSendByte(0xFF); + FlashSendByte(0xFF); + FlashSendByte(0xFF); - uid[7] = FlashSendByte(0xFF); - uid[6] = FlashSendByte(0xFF); - uid[5] = FlashSendByte(0xFF); - uid[4] = FlashSendByte(0xFF); + uid[7] = FlashSendByte(0xFF); + uid[6] = FlashSendByte(0xFF); + uid[5] = FlashSendByte(0xFF); + uid[4] = FlashSendByte(0xFF); uid[3] = FlashSendByte(0xFF); - uid[2] = FlashSendByte(0xFF); - uid[1] = FlashSendByte(0xFF); - uid[0] = FlashSendLastByte(0xFF); + uid[2] = FlashSendByte(0xFF); + uid[1] = FlashSendByte(0xFF); + uid[0] = FlashSendLastByte(0xFF); } uint16_t Flash_ReadData(uint32_t address, uint8_t *out, uint16_t len) { - if (!FlashInit()) return 0; + if (!FlashInit()) return 0; - // length should never be zero - if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0; + // length should never be zero + if (!len || Flash_CheckBusy(BUSY_TIMEOUT)) return 0; uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA; - FlashSendByte(cmd); - Flash_TransferAdresse(address); + FlashSendByte(cmd); + Flash_TransferAdresse(address); - if (FASTFLASH){ - FlashSendByte(DUMMYBYTE); - } + if (FASTFLASH){ + FlashSendByte(DUMMYBYTE); + } - uint16_t i = 0; - for (; i < (len - 1); i++) - out[i] = FlashSendByte(0xFF); + uint16_t i = 0; + for (; i < (len - 1); i++) + out[i] = FlashSendByte(0xFF); - out[i] = FlashSendLastByte(0xFF); - FlashStop(); - return len; + out[i] = FlashSendLastByte(0xFF); + FlashStop(); + return len; } void Flash_TransferAdresse(uint32_t address){ - FlashSendByte((address >> 16) & 0xFF); - FlashSendByte((address >> 8) & 0xFF); - FlashSendByte((address >> 0) & 0xFF); + FlashSendByte((address >> 16) & 0xFF); + FlashSendByte((address >> 8) & 0xFF); + FlashSendByte((address >> 0) & 0xFF); } /* This ensure we can ReadData without having to cycle through initialization everytime */ uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) { - // length should never be zero - if (!len) return 0; + // length should never be zero + if (!len) return 0; uint8_t cmd = (FASTFLASH) ? FASTREAD : READDATA; - FlashSendByte(cmd); - Flash_TransferAdresse(address); + FlashSendByte(cmd); + Flash_TransferAdresse(address); if (FASTFLASH){ - FlashSendByte(DUMMYBYTE); - } + FlashSendByte(DUMMYBYTE); + } - uint16_t i = 0; - for (; i < (len - 1); i++) - out[i] = FlashSendByte(0xFF); + uint16_t i = 0; + for (; i < (len - 1); i++) + out[i] = FlashSendByte(0xFF); - out[i] = FlashSendLastByte(0xFF); - return len; + out[i] = FlashSendLastByte(0xFF); + return len; } @@ -307,89 +307,89 @@ uint16_t Flash_ReadDataCont(uint32_t address, uint8_t *out, uint16_t len) { // if len > 256, it might wrap around and overwrite pos 0. uint16_t Flash_WriteData(uint32_t address, uint8_t *in, uint16_t len) { - // length should never be zero - if (!len) - return 0; + // length should never be zero + if (!len) + return 0; - // Max 256 bytes write - if (((address & 0xFF) + len) > 256) { - Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len ); - return 0; - } + // Max 256 bytes write + if (((address & 0xFF) + len) > 256) { + Dbprintf("Flash_WriteData 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len ); + return 0; + } - // out-of-range - if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) { - Dbprintf("Flash_WriteData, block out-of-range"); - return 0; - } + // out-of-range + if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) { + Dbprintf("Flash_WriteData, block out-of-range"); + return 0; + } - if (!FlashInit()) { - if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); - return 0; - } + if (!FlashInit()) { + if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); + return 0; + } - Flash_CheckBusy(BUSY_TIMEOUT); + Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); + Flash_WriteEnable(); - FlashSendByte(PAGEPROG); - FlashSendByte((address >> 16) & 0xFF); - FlashSendByte((address >> 8) & 0xFF); - FlashSendByte((address >> 0) & 0xFF); + FlashSendByte(PAGEPROG); + FlashSendByte((address >> 16) & 0xFF); + FlashSendByte((address >> 8) & 0xFF); + FlashSendByte((address >> 0) & 0xFF); - uint16_t i = 0; - for (; i < (len - 1); i++) - FlashSendByte(in[i]); + uint16_t i = 0; + for (; i < (len - 1); i++) + FlashSendByte(in[i]); - FlashSendLastByte(in[i]); + FlashSendLastByte(in[i]); - FlashStop(); - return len; + FlashStop(); + return len; } // length should never be zero -// Max 256 bytes write +// Max 256 bytes write // out-of-range uint16_t Flash_WriteDataCont(uint32_t address, uint8_t *in, uint16_t len) { - if (!len) - return 0; + if (!len) + return 0; - if (((address & 0xFF) + len) > 256) { - Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len ); - return 0; - } + if (((address & 0xFF) + len) > 256) { + Dbprintf("Flash_WriteDataCont 256 fail [ 0x%02x ] [ %u ]", (address & 0xFF)+len, len ); + return 0; + } - if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) { - Dbprintf("Flash_WriteDataCont, block out-of-range"); - return 0; - } + if ( (( address >> 16 ) & 0xFF ) > MAX_BLOCKS) { + Dbprintf("Flash_WriteDataCont, block out-of-range"); + return 0; + } - FlashSendByte(PAGEPROG); - FlashSendByte((address >> 16) & 0xFF); - FlashSendByte((address >> 8) & 0xFF); - FlashSendByte((address >> 0) & 0xFF); + FlashSendByte(PAGEPROG); + FlashSendByte((address >> 16) & 0xFF); + FlashSendByte((address >> 8) & 0xFF); + FlashSendByte((address >> 0) & 0xFF); - uint16_t i = 0; - for (; i < (len - 1); i++) - FlashSendByte(in[i]); + uint16_t i = 0; + for (; i < (len - 1); i++) + FlashSendByte(in[i]); - FlashSendLastByte(in[i]); - return len; + FlashSendLastByte(in[i]); + return len; } // assumes valid start 256 based 00 address // uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len) { - bool isok; - uint16_t res, bytes_sent = 0, bytes_remaining = len; + bool isok; + uint16_t res, bytes_sent = 0, bytes_remaining = len; uint8_t buf[FLASH_MEM_BLOCK_SIZE]; while (bytes_remaining > 0) { - Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); + Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); @@ -397,85 +397,85 @@ uint16_t Flash_Write(uint32_t address, uint8_t *in, uint16_t len) { res = Flash_WriteDataCont(address + bytes_sent, buf, bytes_in_packet); - bytes_remaining -= bytes_in_packet; + bytes_remaining -= bytes_in_packet; bytes_sent += bytes_in_packet; isok = (res == bytes_in_packet); if (!isok) - goto out; + goto out; } out: - FlashStop(); - return len; + FlashStop(); + return len; } bool Flash_WipeMemoryPage(uint8_t page) { - if (!FlashInit()) { - if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); - return false; - } - Flash_ReadStat1(); + if (!FlashInit()) { + if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); + return false; + } + Flash_ReadStat1(); - // Each block is 64Kb. One block erase takes 1s ( 1000ms ) - Flash_WriteEnable(); Flash_Erase64k(page); Flash_CheckBusy(BUSY_TIMEOUT); + // Each block is 64Kb. One block erase takes 1s ( 1000ms ) + Flash_WriteEnable(); Flash_Erase64k(page); Flash_CheckBusy(BUSY_TIMEOUT); - FlashStop(); - return true; + FlashStop(); + return true; } // Wipes flash memory completely, fills with 0xFF bool Flash_WipeMemory() { - if (!FlashInit()) { - if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); - return false; - } - Flash_ReadStat1(); + if (!FlashInit()) { + if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash_WriteData init fail"); + return false; + } + Flash_ReadStat1(); - // Each block is 64Kb. Four blocks - // one block erase takes 1s ( 1000ms ) - Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(BUSY_TIMEOUT); - Flash_WriteEnable(); Flash_Erase64k(3); Flash_CheckBusy(BUSY_TIMEOUT); + // Each block is 64Kb. Four blocks + // one block erase takes 1s ( 1000ms ) + Flash_WriteEnable(); Flash_Erase64k(0); Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); Flash_Erase64k(1); Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); Flash_Erase64k(2); Flash_CheckBusy(BUSY_TIMEOUT); + Flash_WriteEnable(); Flash_Erase64k(3); Flash_CheckBusy(BUSY_TIMEOUT); - FlashStop(); - return true; + FlashStop(); + return true; } -// enable the flash write +// enable the flash write void Flash_WriteEnable() { - FlashSendLastByte(WRITEENABLE); - if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash Write enabled"); + FlashSendLastByte(WRITEENABLE); + if ( MF_DBGLEVEL > 3 ) Dbprintf("Flash Write enabled"); } -// erase 4K at one time +// erase 4K at one time // execution time: 0.8ms / 800us bool Flash_Erase4k(uint8_t block, uint8_t sector) { - if (block > MAX_BLOCKS || sector > MAX_SECTORS) return false; + if (block > MAX_BLOCKS || sector > MAX_SECTORS) return false; - FlashSendByte(SECTORERASE); - FlashSendByte(block); - FlashSendByte(sector << 4); - FlashSendLastByte(00); - return true; + FlashSendByte(SECTORERASE); + FlashSendByte(block); + FlashSendByte(sector << 4); + FlashSendLastByte(00); + return true; } /* -// erase 32K at one time +// erase 32K at one time // execution time: 0,3s / 300ms bool Flash_Erase32k(uint32_t address) { - if (address & (32*1024 - 1)) { - if ( MF_DBGLEVEL > 1 ) Dbprintf("Flash_Erase32k : Address is not align at 4096"); - return false; - } - FlashSendByte(BLOCK32ERASE); - FlashSendByte((address >> 16) & 0xFF); - FlashSendByte((address >> 8) & 0xFF); - FlashSendLastByte((address >> 0) & 0xFF); - return true; + if (address & (32*1024 - 1)) { + if ( MF_DBGLEVEL > 1 ) Dbprintf("Flash_Erase32k : Address is not align at 4096"); + return false; + } + FlashSendByte(BLOCK32ERASE); + FlashSendByte((address >> 16) & 0xFF); + FlashSendByte((address >> 8) & 0xFF); + FlashSendLastByte((address >> 0) & 0xFF); + return true; } */ @@ -489,52 +489,52 @@ bool Flash_Erase32k(uint32_t address) { // 0x03 00 00 -- 0x 03 FF FF == block 3 bool Flash_Erase64k(uint8_t block) { - if (block > MAX_BLOCKS) return false; + if (block > MAX_BLOCKS) return false; - FlashSendByte(BLOCK64ERASE); - FlashSendByte(block); - FlashSendByte(0x00); - FlashSendLastByte(0x00); - return true; + FlashSendByte(BLOCK64ERASE); + FlashSendByte(block); + FlashSendByte(0x00); + FlashSendLastByte(0x00); + return true; } -// Erase chip +// Erase chip void Flash_EraseChip(void) { - FlashSendLastByte(CHIPERASE); + FlashSendLastByte(CHIPERASE); } void Flashmem_print_status(void) { - DbpString("Flash memory"); - Dbprintf(" Baudrate................%dMHz",FLASHMEM_SPIBAUDRATE/1000000); + DbpString("Flash memory"); + Dbprintf(" Baudrate................%dMHz",FLASHMEM_SPIBAUDRATE/1000000); - if (!FlashInit()) { - DbpString(" Init....................FAIL"); - return; - } - DbpString(" Init....................OK"); + if (!FlashInit()) { + DbpString(" Init....................FAIL"); + return; + } + DbpString(" Init....................OK"); - uint8_t dev_id = Flash_ReadID(); - switch (dev_id) { - case 0x11 : - DbpString(" Memory size.............2 mbits / 256kb"); - break; - case 0x10 : - DbpString(" Memory size..... .......1 mbits / 128kb"); - break; - case 0x05 : - DbpString(" Memory size.............512 kbits / 64kb"); - break; - default : - DbpString(" Device ID............... --> Unknown <--"); - break; - } + uint8_t dev_id = Flash_ReadID(); + switch (dev_id) { + case 0x11 : + DbpString(" Memory size.............2 mbits / 256kb"); + break; + case 0x10 : + DbpString(" Memory size..... .......1 mbits / 128kb"); + break; + case 0x05 : + DbpString(" Memory size.............512 kbits / 64kb"); + break; + default : + DbpString(" Device ID............... --> Unknown <--"); + break; + } - uint8_t uid[8] = {0,0,0,0,0,0,0,0}; - Flash_UniqueID(uid); - Dbprintf(" Unique ID...............0x%02x%02x%02x%02x%02x%02x%02x%02x", - uid[7], uid[6], uid[5], uid[4], - uid[3], uid[2], uid[1], uid[0] - ); + uint8_t uid[8] = {0,0,0,0,0,0,0,0}; + Flash_UniqueID(uid); + Dbprintf(" Unique ID...............0x%02x%02x%02x%02x%02x%02x%02x%02x", + uid[7], uid[6], uid[5], uid[4], + uid[3], uid[2], uid[1], uid[0] + ); - FlashStop(); + FlashStop(); } diff --git a/armsrc/flashmem.h b/armsrc/flashmem.h index da81363c0..4af499d3a 100644 --- a/armsrc/flashmem.h +++ b/armsrc/flashmem.h @@ -23,7 +23,7 @@ * . */ //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -// Common Instructions // +// Common Instructions // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// #ifndef __FLASHMEM_H #define __FLASHMEM_H @@ -32,74 +32,74 @@ #include "apps.h" #include "ticks.h" -// Used Command -#define ID 0x90 -#define MANID 0x90 -#define JEDECID 0x9F +// Used Command +#define ID 0x90 +#define MANID 0x90 +#define JEDECID 0x9F -#define READSTAT1 0x05 -#define READSTAT2 0x35 -#define WRITESTAT 0x01 +#define READSTAT1 0x05 +#define READSTAT2 0x35 +#define WRITESTAT 0x01 -#define WRITEDISABLE 0x04 -#define WRITEENABLE 0x06 +#define WRITEDISABLE 0x04 +#define WRITEENABLE 0x06 -#define READDATA 0x03 -#define FASTREAD 0x0B -#define PAGEPROG 0x02 +#define READDATA 0x03 +#define FASTREAD 0x0B +#define PAGEPROG 0x02 -#define SECTORERASE 0x20 -#define BLOCK32ERASE 0x52 -#define BLOCK64ERASE 0xD8 -#define CHIPERASE 0xC7 +#define SECTORERASE 0x20 +#define BLOCK32ERASE 0x52 +#define BLOCK64ERASE 0xD8 +#define CHIPERASE 0xC7 -#define UNIQUE_ID 0x4B +#define UNIQUE_ID 0x4B -// Not used or not support command -#define RELEASE 0xAB -#define POWERDOWN 0xB9 -#define SUSPEND 0x75 -#define RESUME 0x7A +// Not used or not support command +#define RELEASE 0xAB +#define POWERDOWN 0xB9 +#define SUSPEND 0x75 +#define RESUME 0x7A -#define BUSY_TIMEOUT 1000000000L +#define BUSY_TIMEOUT 1000000000L -#define WINBOND_MANID 0xEF -#define WINBOND_DEVID 0x11 -#define PAGESIZE 0x100 +#define WINBOND_MANID 0xEF +#define WINBOND_DEVID 0x11 +#define PAGESIZE 0x100 #define WINBOND_WRITE_DELAY 0x02 -#define SPI_CLK 48000000 +#define SPI_CLK 48000000 -#define BUSY 0x01 -#define WRTEN 0x02 -#define SUS 0x40 +#define BUSY 0x01 +#define WRTEN 0x02 +#define SUS 0x40 -#define DUMMYBYTE 0xEE -#define NULLBYTE 0x00 -#define NULLINT 0x0000 -#define NO_CONTINUE 0x00 -#define PASS 0x01 -#define FAIL 0x00 -#define maxAddress capacity +#define DUMMYBYTE 0xEE +#define NULLBYTE 0x00 +#define NULLINT 0x0000 +#define NO_CONTINUE 0x00 +#define PASS 0x01 +#define FAIL 0x00 +#define maxAddress capacity //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -// List of Error codes // +// List of Error codes // //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~// -#define SUCCESS 0x00 -#define CALLBEGIN 0x01 -#define UNKNOWNCHIP 0x02 -#define UNKNOWNCAP 0x03 -#define CHIPBUSY 0x04 -#define OUTOFBOUNDS 0x05 -#define CANTENWRITE 0x06 -#define PREVWRITTEN 0x07 -#define LOWRAM 0x08 -#define NOSUSPEND 0x09 -#define UNKNOWNERROR 0xFF +#define SUCCESS 0x00 +#define CALLBEGIN 0x01 +#define UNKNOWNCHIP 0x02 +#define UNKNOWNCAP 0x03 +#define CHIPBUSY 0x04 +#define OUTOFBOUNDS 0x05 +#define CANTENWRITE 0x06 +#define PREVWRITTEN 0x07 +#define LOWRAM 0x08 +#define NOSUSPEND 0x09 +#define UNKNOWNERROR 0xFF // List of blocks -#define MAX_BLOCKS 4 -#define MAX_SECTORS 16 +#define MAX_BLOCKS 4 +#define MAX_SECTORS 16 diff --git a/armsrc/fonts.c b/armsrc/fonts.c index d79a61d84..1e4b418c9 100644 --- a/armsrc/fonts.c +++ b/armsrc/fonts.c @@ -7,302 +7,302 @@ //----------------------------------------------------------------------------- const char FONT6x8[97][8] = { - {0x06,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes per char - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space - {0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00}, // ! - {0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00}, // " - {0x50,0x50,0xF8,0x50,0xF8,0x50,0x50,0x00}, // # - {0x20,0x78,0xA0,0x70,0x28,0xF0,0x20,0x00}, // $ - {0xC0,0xC8,0x10,0x20,0x40,0x98,0x18,0x00}, // % - {0x40,0xA0,0xA0,0x40,0xA8,0x90,0x68,0x00}, // & - {0x30,0x30,0x20,0x40,0x00,0x00,0x00,0x00}, // ' - {0x10,0x20,0x40,0x40,0x40,0x20,0x10,0x00}, // ( - {0x40,0x20,0x10,0x10,0x10,0x20,0x40,0x00}, // ) - {0x00,0x20,0xA8,0x70,0x70,0xA8,0x20,0x00}, // * - {0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00}, // + - {0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40}, // , - {0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00}, // - - {0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00}, // . - {0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00}, // / - {0x70,0x88,0x88,0xA8,0x88,0x88,0x70,0x00}, // 0 - {0x20,0x60,0x20,0x20,0x20,0x20,0x70,0x00}, // 1 - {0x70,0x88,0x08,0x70,0x80,0x80,0xF8,0x00}, // 2 - {0xF8,0x08,0x10,0x30,0x08,0x88,0x70,0x00}, // 3 - {0x10,0x30,0x50,0x90,0xF8,0x10,0x10,0x00}, // 4 - {0xF8,0x80,0xF0,0x08,0x08,0x88,0x70,0x00}, // 5 - {0x38,0x40,0x80,0xF0,0x88,0x88,0x70,0x00}, // 6 - {0xF8,0x08,0x08,0x10,0x20,0x40,0x80,0x00}, // 7 - {0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00}, // 8 - {0x70,0x88,0x88,0x78,0x08,0x10,0xE0,0x00}, // 9 - {0x00,0x00,0x20,0x00,0x20,0x00,0x00,0x00}, // : - {0x00,0x00,0x20,0x00,0x20,0x20,0x40,0x00}, // ; - {0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x00}, // < - {0x00,0x00,0xF8,0x00,0xF8,0x00,0x00,0x00}, // = - {0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00}, // > - {0x70,0x88,0x08,0x30,0x20,0x00,0x20,0x00}, // ? - {0x70,0x88,0xA8,0xB8,0xB0,0x80,0x78,0x00}, // @ - {0x20,0x50,0x88,0x88,0xF8,0x88,0x88,0x00}, // A - {0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x00}, // B - {0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00}, // C - {0xF0,0x88,0x88,0x88,0x88,0x88,0xF0,0x00}, // D - {0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8,0x00}, // E - {0xF8,0x80,0x80,0xF0,0x80,0x80,0x80,0x00}, // F - {0x78,0x88,0x80,0x80,0x98,0x88,0x78,0x00}, // G - {0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x00}, // H - {0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00}, // I - {0x38,0x10,0x10,0x10,0x10,0x90,0x60,0x00}, // J - {0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x00}, // K - {0x80,0x80,0x80,0x80,0x80,0x80,0xF8,0x00}, // L - {0x88,0xD8,0xA8,0xA8,0xA8,0x88,0x88,0x00}, // M - {0x88,0x88,0xC8,0xA8,0x98,0x88,0x88,0x00}, // N - {0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00}, // O - {0xF0,0x88,0x88,0xF0,0x80,0x80,0x80,0x00}, // P - {0x70,0x88,0x88,0x88,0xA8,0x90,0x68,0x00}, // Q - {0xF0,0x88,0x88,0xF0,0xA0,0x90,0x88,0x00}, // R - {0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00}, // S - {0xF8,0xA8,0x20,0x20,0x20,0x20,0x20,0x00}, // T - {0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00}, // U - {0x88,0x88,0x88,0x88,0x88,0x50,0x20,0x00}, // V - {0x88,0x88,0x88,0xA8,0xA8,0xA8,0x50,0x00}, // W - {0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00}, // X - {0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00}, // Y - {0xF8,0x08,0x10,0x70,0x40,0x80,0xF8,0x00}, // Z - {0x78,0x40,0x40,0x40,0x40,0x40,0x78,0x00}, // [ - {0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00}, // backslash - {0x78,0x08,0x08,0x08,0x08,0x08,0x78,0x00}, // ] - {0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00}, // ^ - {0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00}, // _ - {0x60,0x60,0x20,0x10,0x00,0x00,0x00,0x00}, // ` - {0x00,0x00,0x60,0x10,0x70,0x90,0x78,0x00}, // a - {0x80,0x80,0xB0,0xC8,0x88,0xC8,0xB0,0x00}, // b - {0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x00}, // c - {0x08,0x08,0x68,0x98,0x88,0x98,0x68,0x00}, // d - {0x00,0x00,0x70,0x88,0xF8,0x80,0x70,0x00}, // e - {0x10,0x28,0x20,0x70,0x20,0x20,0x20,0x00}, // f - {0x00,0x00,0x70,0x98,0x98,0x68,0x08,0x70}, // g - {0x80,0x80,0xB0,0xC8,0x88,0x88,0x88,0x00}, // h - {0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00}, // i - {0x10,0x00,0x10,0x10,0x10,0x90,0x60,0x00}, // j - {0x80,0x80,0x90,0xA0,0xC0,0xA0,0x90,0x00}, // k - {0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00}, // l - {0x00,0x00,0xD0,0xA8,0xA8,0xA8,0xA8,0x00}, // m - {0x00,0x00,0xB0,0xC8,0x88,0x88,0x88,0x00}, // n - {0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00}, // o - {0x00,0x00,0xB0,0xC8,0xC8,0xB0,0x80,0x80}, // p - {0x00,0x00,0x68,0x98,0x98,0x68,0x08,0x08}, // q - {0x00,0x00,0xB0,0xC8,0x80,0x80,0x80,0x00}, // r - {0x00,0x00,0x78,0x80,0x70,0x08,0xF0,0x00}, // s - {0x20,0x20,0xF8,0x20,0x20,0x28,0x10,0x00}, // t - {0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x00}, // u - {0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x00}, // v - {0x00,0x00,0x88,0x88,0xA8,0xA8,0x50,0x00}, // w - {0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00}, // x - {0x00,0x00,0x88,0x88,0x78,0x08,0x88,0x70}, // y - {0x00,0x00,0xF8,0x10,0x20,0x40,0xF8,0x00}, // z - {0x10,0x20,0x20,0x40,0x20,0x20,0x10,0x00}, // { - {0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x00}, // | - {0x40,0x20,0x20,0x10,0x20,0x20,0x40,0x00}, // } - {0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00}, // ~ - {0x70,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00} // DEL + {0x06,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes per char + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space + {0x20,0x20,0x20,0x20,0x20,0x00,0x20,0x00}, // ! + {0x50,0x50,0x50,0x00,0x00,0x00,0x00,0x00}, // " + {0x50,0x50,0xF8,0x50,0xF8,0x50,0x50,0x00}, // # + {0x20,0x78,0xA0,0x70,0x28,0xF0,0x20,0x00}, // $ + {0xC0,0xC8,0x10,0x20,0x40,0x98,0x18,0x00}, // % + {0x40,0xA0,0xA0,0x40,0xA8,0x90,0x68,0x00}, // & + {0x30,0x30,0x20,0x40,0x00,0x00,0x00,0x00}, // ' + {0x10,0x20,0x40,0x40,0x40,0x20,0x10,0x00}, // ( + {0x40,0x20,0x10,0x10,0x10,0x20,0x40,0x00}, // ) + {0x00,0x20,0xA8,0x70,0x70,0xA8,0x20,0x00}, // * + {0x00,0x20,0x20,0xF8,0x20,0x20,0x00,0x00}, // + + {0x00,0x00,0x00,0x00,0x30,0x30,0x20,0x40}, // , + {0x00,0x00,0x00,0xF8,0x00,0x00,0x00,0x00}, // - + {0x00,0x00,0x00,0x00,0x00,0x30,0x30,0x00}, // . + {0x00,0x08,0x10,0x20,0x40,0x80,0x00,0x00}, // / + {0x70,0x88,0x88,0xA8,0x88,0x88,0x70,0x00}, // 0 + {0x20,0x60,0x20,0x20,0x20,0x20,0x70,0x00}, // 1 + {0x70,0x88,0x08,0x70,0x80,0x80,0xF8,0x00}, // 2 + {0xF8,0x08,0x10,0x30,0x08,0x88,0x70,0x00}, // 3 + {0x10,0x30,0x50,0x90,0xF8,0x10,0x10,0x00}, // 4 + {0xF8,0x80,0xF0,0x08,0x08,0x88,0x70,0x00}, // 5 + {0x38,0x40,0x80,0xF0,0x88,0x88,0x70,0x00}, // 6 + {0xF8,0x08,0x08,0x10,0x20,0x40,0x80,0x00}, // 7 + {0x70,0x88,0x88,0x70,0x88,0x88,0x70,0x00}, // 8 + {0x70,0x88,0x88,0x78,0x08,0x10,0xE0,0x00}, // 9 + {0x00,0x00,0x20,0x00,0x20,0x00,0x00,0x00}, // : + {0x00,0x00,0x20,0x00,0x20,0x20,0x40,0x00}, // ; + {0x08,0x10,0x20,0x40,0x20,0x10,0x08,0x00}, // < + {0x00,0x00,0xF8,0x00,0xF8,0x00,0x00,0x00}, // = + {0x40,0x20,0x10,0x08,0x10,0x20,0x40,0x00}, // > + {0x70,0x88,0x08,0x30,0x20,0x00,0x20,0x00}, // ? + {0x70,0x88,0xA8,0xB8,0xB0,0x80,0x78,0x00}, // @ + {0x20,0x50,0x88,0x88,0xF8,0x88,0x88,0x00}, // A + {0xF0,0x88,0x88,0xF0,0x88,0x88,0xF0,0x00}, // B + {0x70,0x88,0x80,0x80,0x80,0x88,0x70,0x00}, // C + {0xF0,0x88,0x88,0x88,0x88,0x88,0xF0,0x00}, // D + {0xF8,0x80,0x80,0xF0,0x80,0x80,0xF8,0x00}, // E + {0xF8,0x80,0x80,0xF0,0x80,0x80,0x80,0x00}, // F + {0x78,0x88,0x80,0x80,0x98,0x88,0x78,0x00}, // G + {0x88,0x88,0x88,0xF8,0x88,0x88,0x88,0x00}, // H + {0x70,0x20,0x20,0x20,0x20,0x20,0x70,0x00}, // I + {0x38,0x10,0x10,0x10,0x10,0x90,0x60,0x00}, // J + {0x88,0x90,0xA0,0xC0,0xA0,0x90,0x88,0x00}, // K + {0x80,0x80,0x80,0x80,0x80,0x80,0xF8,0x00}, // L + {0x88,0xD8,0xA8,0xA8,0xA8,0x88,0x88,0x00}, // M + {0x88,0x88,0xC8,0xA8,0x98,0x88,0x88,0x00}, // N + {0x70,0x88,0x88,0x88,0x88,0x88,0x70,0x00}, // O + {0xF0,0x88,0x88,0xF0,0x80,0x80,0x80,0x00}, // P + {0x70,0x88,0x88,0x88,0xA8,0x90,0x68,0x00}, // Q + {0xF0,0x88,0x88,0xF0,0xA0,0x90,0x88,0x00}, // R + {0x70,0x88,0x80,0x70,0x08,0x88,0x70,0x00}, // S + {0xF8,0xA8,0x20,0x20,0x20,0x20,0x20,0x00}, // T + {0x88,0x88,0x88,0x88,0x88,0x88,0x70,0x00}, // U + {0x88,0x88,0x88,0x88,0x88,0x50,0x20,0x00}, // V + {0x88,0x88,0x88,0xA8,0xA8,0xA8,0x50,0x00}, // W + {0x88,0x88,0x50,0x20,0x50,0x88,0x88,0x00}, // X + {0x88,0x88,0x50,0x20,0x20,0x20,0x20,0x00}, // Y + {0xF8,0x08,0x10,0x70,0x40,0x80,0xF8,0x00}, // Z + {0x78,0x40,0x40,0x40,0x40,0x40,0x78,0x00}, // [ + {0x00,0x80,0x40,0x20,0x10,0x08,0x00,0x00}, // backslash + {0x78,0x08,0x08,0x08,0x08,0x08,0x78,0x00}, // ] + {0x20,0x50,0x88,0x00,0x00,0x00,0x00,0x00}, // ^ + {0x00,0x00,0x00,0x00,0x00,0x00,0xF8,0x00}, // _ + {0x60,0x60,0x20,0x10,0x00,0x00,0x00,0x00}, // ` + {0x00,0x00,0x60,0x10,0x70,0x90,0x78,0x00}, // a + {0x80,0x80,0xB0,0xC8,0x88,0xC8,0xB0,0x00}, // b + {0x00,0x00,0x70,0x88,0x80,0x88,0x70,0x00}, // c + {0x08,0x08,0x68,0x98,0x88,0x98,0x68,0x00}, // d + {0x00,0x00,0x70,0x88,0xF8,0x80,0x70,0x00}, // e + {0x10,0x28,0x20,0x70,0x20,0x20,0x20,0x00}, // f + {0x00,0x00,0x70,0x98,0x98,0x68,0x08,0x70}, // g + {0x80,0x80,0xB0,0xC8,0x88,0x88,0x88,0x00}, // h + {0x20,0x00,0x60,0x20,0x20,0x20,0x70,0x00}, // i + {0x10,0x00,0x10,0x10,0x10,0x90,0x60,0x00}, // j + {0x80,0x80,0x90,0xA0,0xC0,0xA0,0x90,0x00}, // k + {0x60,0x20,0x20,0x20,0x20,0x20,0x70,0x00}, // l + {0x00,0x00,0xD0,0xA8,0xA8,0xA8,0xA8,0x00}, // m + {0x00,0x00,0xB0,0xC8,0x88,0x88,0x88,0x00}, // n + {0x00,0x00,0x70,0x88,0x88,0x88,0x70,0x00}, // o + {0x00,0x00,0xB0,0xC8,0xC8,0xB0,0x80,0x80}, // p + {0x00,0x00,0x68,0x98,0x98,0x68,0x08,0x08}, // q + {0x00,0x00,0xB0,0xC8,0x80,0x80,0x80,0x00}, // r + {0x00,0x00,0x78,0x80,0x70,0x08,0xF0,0x00}, // s + {0x20,0x20,0xF8,0x20,0x20,0x28,0x10,0x00}, // t + {0x00,0x00,0x88,0x88,0x88,0x98,0x68,0x00}, // u + {0x00,0x00,0x88,0x88,0x88,0x50,0x20,0x00}, // v + {0x00,0x00,0x88,0x88,0xA8,0xA8,0x50,0x00}, // w + {0x00,0x00,0x88,0x50,0x20,0x50,0x88,0x00}, // x + {0x00,0x00,0x88,0x88,0x78,0x08,0x88,0x70}, // y + {0x00,0x00,0xF8,0x10,0x20,0x40,0xF8,0x00}, // z + {0x10,0x20,0x20,0x40,0x20,0x20,0x10,0x00}, // { + {0x20,0x20,0x20,0x00,0x20,0x20,0x20,0x00}, // | + {0x40,0x20,0x20,0x10,0x20,0x20,0x40,0x00}, // } + {0x40,0xA8,0x10,0x00,0x00,0x00,0x00,0x00}, // ~ + {0x70,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00} // DEL }; /* const char FONT8x8F[97][8] = { - {0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes per char - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space - {0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00}, // ! - {0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00}, // " - {0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00}, // # - {0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00}, // $ - {0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00}, // % - {0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00}, // & - {0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00}, // ' - {0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00}, // ( - {0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00}, // ) - {0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00}, // * - {0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00}, // + - {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30}, // , - {0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00}, // - - {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}, // . - {0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00}, // / - {0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00}, // 0 - {0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00}, // 1 - {0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00}, // 2 - {0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00}, // 3 - {0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00}, // 4 - {0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00}, // 5 - {0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00}, // 6 - {0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00}, // 7 - {0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00}, // 8 - {0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00}, // 9 - {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00}, // : - {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30}, // ; - {0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00}, // < - {0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00}, // = - {0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00}, // > - {0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00}, // ? - {0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00}, // @ - {0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00}, // A - {0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00}, // B - {0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00}, // C - {0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00}, // D - {0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00}, // E - {0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00}, // F - {0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00}, // G - {0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00}, // H - {0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // I - {0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00}, // J - {0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00}, // K - {0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00}, // L - {0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00}, // M - {0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00}, // N - {0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00}, // O - {0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00}, // P - {0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00}, // Q - {0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00}, // R - {0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00}, // S - {0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00}, // T - {0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00}, // U - {0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00}, // V - {0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00}, // W - {0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00}, // X - {0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00}, // Y - {0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00}, // Z - {0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00}, // [ - {0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00}, // backslash - {0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00}, // ] - {0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00}, // ^ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF}, // _ - {0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00}, // ` - {0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00}, // a - {0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00}, // b - {0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00}, // c - {0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00}, // d - {0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00}, // e - {0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00}, // f - {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C}, // g - {0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00}, // h - {0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00}, // i - {0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C}, // j - {0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00}, // k - {0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // l - {0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00}, // m - {0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00}, // n - {0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00}, // o - {0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78}, // p - {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F}, // q - {0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00}, // r - {0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00}, // s - {0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00}, // t - {0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00}, // u - {0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00}, // v - {0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00}, // w - {0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00}, // x - {0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C}, // y - {0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00}, // z - {0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00}, // { - {0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00}, // | - {0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00}, // } - {0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00}, // ~ - {0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00} // DEL + {0x08,0x08,0x08,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes per char + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space + {0x30,0x78,0x78,0x30,0x30,0x00,0x30,0x00}, // ! + {0x6C,0x6C,0x6C,0x00,0x00,0x00,0x00,0x00}, // " + {0x6C,0x6C,0xFE,0x6C,0xFE,0x6C,0x6C,0x00}, // # + {0x18,0x3E,0x60,0x3C,0x06,0x7C,0x18,0x00}, // $ + {0x00,0x63,0x66,0x0C,0x18,0x33,0x63,0x00}, // % + {0x1C,0x36,0x1C,0x3B,0x6E,0x66,0x3B,0x00}, // & + {0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00}, // ' + {0x0C,0x18,0x30,0x30,0x30,0x18,0x0C,0x00}, // ( + {0x30,0x18,0x0C,0x0C,0x0C,0x18,0x30,0x00}, // ) + {0x00,0x66,0x3C,0xFF,0x3C,0x66,0x00,0x00}, // * + {0x00,0x30,0x30,0xFC,0x30,0x30,0x00,0x00}, // + + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x30}, // , + {0x00,0x00,0x00,0x7E,0x00,0x00,0x00,0x00}, // - + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00}, // . + {0x03,0x06,0x0C,0x18,0x30,0x60,0x40,0x00}, // / + {0x3E,0x63,0x63,0x6B,0x63,0x63,0x3E,0x00}, // 0 + {0x18,0x38,0x58,0x18,0x18,0x18,0x7E,0x00}, // 1 + {0x3C,0x66,0x06,0x1C,0x30,0x66,0x7E,0x00}, // 2 + {0x3C,0x66,0x06,0x1C,0x06,0x66,0x3C,0x00}, // 3 + {0x0E,0x1E,0x36,0x66,0x7F,0x06,0x0F,0x00}, // 4 + {0x7E,0x60,0x7C,0x06,0x06,0x66,0x3C,0x00}, // 5 + {0x1C,0x30,0x60,0x7C,0x66,0x66,0x3C,0x00}, // 6 + {0x7E,0x66,0x06,0x0C,0x18,0x18,0x18,0x00}, // 7 + {0x3C,0x66,0x66,0x3C,0x66,0x66,0x3C,0x00}, // 8 + {0x3C,0x66,0x66,0x3E,0x06,0x0C,0x38,0x00}, // 9 + {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x00}, // : + {0x00,0x18,0x18,0x00,0x00,0x18,0x18,0x30}, // ; + {0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x00}, // < + {0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00}, // = + {0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x00}, // > + {0x3C,0x66,0x06,0x0C,0x18,0x00,0x18,0x00}, // ? + {0x3E,0x63,0x6F,0x69,0x6F,0x60,0x3E,0x00}, // @ + {0x18,0x3C,0x66,0x66,0x7E,0x66,0x66,0x00}, // A + {0x7E,0x33,0x33,0x3E,0x33,0x33,0x7E,0x00}, // B + {0x1E,0x33,0x60,0x60,0x60,0x33,0x1E,0x00}, // C + {0x7C,0x36,0x33,0x33,0x33,0x36,0x7C,0x00}, // D + {0x7F,0x31,0x34,0x3C,0x34,0x31,0x7F,0x00}, // E + {0x7F,0x31,0x34,0x3C,0x34,0x30,0x78,0x00}, // F + {0x1E,0x33,0x60,0x60,0x67,0x33,0x1F,0x00}, // G + {0x66,0x66,0x66,0x7E,0x66,0x66,0x66,0x00}, // H + {0x3C,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // I + {0x0F,0x06,0x06,0x06,0x66,0x66,0x3C,0x00}, // J + {0x73,0x33,0x36,0x3C,0x36,0x33,0x73,0x00}, // K + {0x78,0x30,0x30,0x30,0x31,0x33,0x7F,0x00}, // L + {0x63,0x77,0x7F,0x7F,0x6B,0x63,0x63,0x00}, // M + {0x63,0x73,0x7B,0x6F,0x67,0x63,0x63,0x00}, // N + {0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00}, // O + {0x7E,0x33,0x33,0x3E,0x30,0x30,0x78,0x00}, // P + {0x3C,0x66,0x66,0x66,0x6E,0x3C,0x0E,0x00}, // Q + {0x7E,0x33,0x33,0x3E,0x36,0x33,0x73,0x00}, // R + {0x3C,0x66,0x30,0x18,0x0C,0x66,0x3C,0x00}, // S + {0x7E,0x5A,0x18,0x18,0x18,0x18,0x3C,0x00}, // T + {0x66,0x66,0x66,0x66,0x66,0x66,0x7E,0x00}, // U + {0x66,0x66,0x66,0x66,0x66,0x3C,0x18,0x00}, // V + {0x63,0x63,0x63,0x6B,0x7F,0x77,0x63,0x00}, // W + {0x63,0x63,0x36,0x1C,0x1C,0x36,0x63,0x00}, // X + {0x66,0x66,0x66,0x3C,0x18,0x18,0x3C,0x00}, // Y + {0x7F,0x63,0x46,0x0C,0x19,0x33,0x7F,0x00}, // Z + {0x3C,0x30,0x30,0x30,0x30,0x30,0x3C,0x00}, // [ + {0x60,0x30,0x18,0x0C,0x06,0x03,0x01,0x00}, // backslash + {0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00}, // ] + {0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00}, // ^ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF}, // _ + {0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00}, // ` + {0x00,0x00,0x3C,0x06,0x3E,0x66,0x3B,0x00}, // a + {0x70,0x30,0x3E,0x33,0x33,0x33,0x6E,0x00}, // b + {0x00,0x00,0x3C,0x66,0x60,0x66,0x3C,0x00}, // c + {0x0E,0x06,0x3E,0x66,0x66,0x66,0x3B,0x00}, // d + {0x00,0x00,0x3C,0x66,0x7E,0x60,0x3C,0x00}, // e + {0x1C,0x36,0x30,0x78,0x30,0x30,0x78,0x00}, // f + {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x7C}, // g + {0x70,0x30,0x36,0x3B,0x33,0x33,0x73,0x00}, // h + {0x18,0x00,0x38,0x18,0x18,0x18,0x3C,0x00}, // i + {0x06,0x00,0x06,0x06,0x06,0x66,0x66,0x3C}, // j + {0x70,0x30,0x33,0x36,0x3C,0x36,0x73,0x00}, // k + {0x38,0x18,0x18,0x18,0x18,0x18,0x3C,0x00}, // l + {0x00,0x00,0x66,0x7F,0x7F,0x6B,0x63,0x00}, // m + {0x00,0x00,0x7C,0x66,0x66,0x66,0x66,0x00}, // n + {0x00,0x00,0x3C,0x66,0x66,0x66,0x3C,0x00}, // o + {0x00,0x00,0x6E,0x33,0x33,0x3E,0x30,0x78}, // p + {0x00,0x00,0x3B,0x66,0x66,0x3E,0x06,0x0F}, // q + {0x00,0x00,0x6E,0x3B,0x33,0x30,0x78,0x00}, // r + {0x00,0x00,0x3E,0x60,0x3C,0x06,0x7C,0x00}, // s + {0x08,0x18,0x3E,0x18,0x18,0x1A,0x0C,0x00}, // t + {0x00,0x00,0x66,0x66,0x66,0x66,0x3B,0x00}, // u + {0x00,0x00,0x66,0x66,0x66,0x3C,0x18,0x00}, // v + {0x00,0x00,0x63,0x6B,0x7F,0x7F,0x36,0x00}, // w + {0x00,0x00,0x63,0x36,0x1C,0x36,0x63,0x00}, // x + {0x00,0x00,0x66,0x66,0x66,0x3E,0x06,0x7C}, // y + {0x00,0x00,0x7E,0x4C,0x18,0x32,0x7E,0x00}, // z + {0x0E,0x18,0x18,0x70,0x18,0x18,0x0E,0x00}, // { + {0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x0C,0x00}, // | + {0x70,0x18,0x18,0x0E,0x18,0x18,0x70,0x00}, // } + {0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00}, // ~ + {0x1C,0x36,0x36,0x1C,0x00,0x00,0x00,0x00} // DEL }; const char FONT8x16[97][16] = { - {0x08,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes per char - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space - {0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // ! - {0x00,0x63,0x63,0x63,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // " - {0x00,0x00,0x00,0x36,0x36,0x7F,0x36,0x36,0x36,0x7F,0x36,0x36,0x00,0x00,0x00,0x00}, // # - {0x0C,0x0C,0x3E,0x63,0x61,0x60,0x3E,0x03,0x03,0x43,0x63,0x3E,0x0C,0x0C,0x00,0x00}, // $ - {0x00,0x00,0x00,0x00,0x00,0x61,0x63,0x06,0x0C,0x18,0x33,0x63,0x00,0x00,0x00,0x00}, // % - {0x00,0x00,0x00,0x1C,0x36,0x36,0x1C,0x3B,0x6E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // & - {0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ' - {0x00,0x00,0x0C,0x18,0x18,0x30,0x30,0x30,0x30,0x18,0x18,0x0C,0x00,0x00,0x00,0x00}, // ( - {0x00,0x00,0x18,0x0C,0x0C,0x06,0x06,0x06,0x06,0x0C,0x0C,0x18,0x00,0x00,0x00,0x00}, // ) - {0x00,0x00,0x00,0x00,0x42,0x66,0x3C,0xFF,0x3C,0x66,0x42,0x00,0x00,0x00,0x00,0x00}, // * - {0x00,0x00,0x00,0x00,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00}, // + - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00}, // , - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // - - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // . - {0x00,0x00,0x01,0x03,0x07,0x0E,0x1C,0x38,0x70,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00}, // / - {0x00,0x00,0x3E,0x63,0x63,0x63,0x6B,0x6B,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // 0 - {0x00,0x00,0x0C,0x1C,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3F,0x00,0x00,0x00,0x00}, // 1 - {0x00,0x00,0x3E,0x63,0x03,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00}, // 2 - {0x00,0x00,0x3E,0x63,0x03,0x03,0x1E,0x03,0x03,0x03,0x63,0x3E,0x00,0x00,0x00,0x00}, // 3 - {0x00,0x00,0x06,0x0E,0x1E,0x36,0x66,0x66,0x7F,0x06,0x06,0x0F,0x00,0x00,0x00,0x00}, // 4 - {0x00,0x00,0x7F,0x60,0x60,0x60,0x7E,0x03,0x03,0x63,0x73,0x3E,0x00,0x00,0x00,0x00}, // 5 - {0x00,0x00,0x1C,0x30,0x60,0x60,0x7E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // 6 - {0x00,0x00,0x7F,0x63,0x03,0x06,0x06,0x0C,0x0C,0x18,0x18,0x18,0x00,0x00,0x00,0x00}, // 7 - {0x00,0x00,0x3E,0x63,0x63,0x63,0x3E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // 8 - {0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x3F,0x03,0x03,0x06,0x3C,0x00,0x00,0x00,0x00}, // 9 - {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // : - {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00}, // ; - {0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00}, // < - {0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00}, // = - {0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00}, // > - {0x00,0x00,0x3E,0x63,0x63,0x06,0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x00,0x00,0x00,0x00}, // ? - {0x00,0x00,0x3E,0x63,0x63,0x6F,0x6B,0x6B,0x6E,0x60,0x60,0x3E,0x00,0x00,0x00,0x00}, // @ - {0x00,0x00,0x08,0x1C,0x36,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // A - {0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x33,0x33,0x33,0x33,0x7E,0x00,0x00,0x00,0x00}, // B - {0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x60,0x60,0x61,0x33,0x1E,0x00,0x00,0x00,0x00}, // C - {0x00,0x00,0x7C,0x36,0x33,0x33,0x33,0x33,0x33,0x33,0x36,0x7C,0x00,0x00,0x00,0x00}, // D - {0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00}, // E - {0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // F - {0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x6F,0x63,0x63,0x37,0x1D,0x00,0x00,0x00,0x00}, // G - {0x00,0x00,0x63,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // H - {0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, // I - {0x00,0x00,0x0F,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00,0x00,0x00}, // J - {0x00,0x00,0x73,0x33,0x36,0x36,0x3C,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00}, // K - {0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00}, // L - {0x00,0x00,0x63,0x77,0x7F,0x6B,0x63,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // M - {0x00,0x00,0x63,0x63,0x73,0x7B,0x7F,0x6F,0x67,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // N - {0x00,0x00,0x1C,0x36,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x00,0x00,0x00,0x00}, // O - {0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // P - {0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x63,0x6B,0x6F,0x3E,0x06,0x07,0x00,0x00}, // Q - {0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00}, // R - {0x00,0x00,0x3E,0x63,0x63,0x30,0x1C,0x06,0x03,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // S - {0x00,0x00,0xFF,0xDB,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, // T - {0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // U - {0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x08,0x00,0x00,0x00,0x00}, // V - {0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x36,0x00,0x00,0x00,0x00}, // W - {0x00,0x00,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x3C,0x66,0xC3,0xC3,0x00,0x00,0x00,0x00}, // X - {0x00,0x00,0xC3,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, // Y - {0x00,0x00,0x7F,0x63,0x43,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00}, // Z - {0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00}, // [ - {0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x07,0x03,0x01,0x00,0x00,0x00,0x00}, // backslash - {0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00}, // ] - {0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ^ - {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00}, // _ - {0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ` - {0x00,0x00,0x00,0x00,0x00,0x3C,0x46,0x06,0x3E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // a - {0x00,0x00,0x70,0x30,0x30,0x3C,0x36,0x33,0x33,0x33,0x33,0x6E,0x00,0x00,0x00,0x00}, // b - {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x60,0x60,0x60,0x63,0x3E,0x00,0x00,0x00,0x00}, // c - {0x00,0x00,0x0E,0x06,0x06,0x1E,0x36,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // d - {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x7E,0x60,0x63,0x3E,0x00,0x00,0x00,0x00}, // e - {0x00,0x00,0x1C,0x36,0x32,0x30,0x7C,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // f - {0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00,0x00}, // g - {0x00,0x00,0x70,0x30,0x30,0x36,0x3B,0x33,0x33,0x33,0x33,0x73,0x00,0x00,0x00,0x00}, // h - {0x00,0x00,0x0C,0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00}, // i - {0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00}, // j - {0x00,0x00,0x70,0x30,0x30,0x33,0x33,0x36,0x3C,0x36,0x33,0x73,0x00,0x00,0x00,0x00}, // k - {0x00,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00}, // l - {0x00,0x00,0x00,0x00,0x00,0x6E,0x7F,0x6B,0x6B,0x6B,0x6B,0x6B,0x00,0x00,0x00,0x00}, // m - {0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x00}, // n - {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // o - {0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x3E,0x30,0x30,0x78,0x00,0x00}, // p - {0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x06,0x0F,0x00,0x00}, // q - {0x00,0x00,0x00,0x00,0x00,0x6E,0x3B,0x33,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // r - {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x38,0x0E,0x03,0x63,0x3E,0x00,0x00,0x00,0x00}, // s - {0x00,0x00,0x08,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x1B,0x0E,0x00,0x00,0x00,0x00}, // t - {0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // u - {0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x36,0x36,0x1C,0x1C,0x08,0x00,0x00,0x00,0x00}, // v - {0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x00,0x00,0x00,0x00}, // w - {0x00,0x00,0x00,0x00,0x00,0x63,0x36,0x1C,0x1C,0x1C,0x36,0x63,0x00,0x00,0x00,0x00}, // x - {0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x3F,0x03,0x06,0x3C,0x00,0x00}, // y - {0x00,0x00,0x00,0x00,0x00,0x7F,0x66,0x0C,0x18,0x30,0x63,0x7F,0x00,0x00,0x00,0x00}, // z - {0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00}, // { - {0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00}, // | - {0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00}, // } - {0x00,0x00,0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ~ - {0x00,0x70,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // DEL + {0x08,0x10,0x10,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // columns, rows, bytes per char + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // space + {0x00,0x00,0x18,0x3C,0x3C,0x3C,0x18,0x18,0x18,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // ! + {0x00,0x63,0x63,0x63,0x22,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // " + {0x00,0x00,0x00,0x36,0x36,0x7F,0x36,0x36,0x36,0x7F,0x36,0x36,0x00,0x00,0x00,0x00}, // # + {0x0C,0x0C,0x3E,0x63,0x61,0x60,0x3E,0x03,0x03,0x43,0x63,0x3E,0x0C,0x0C,0x00,0x00}, // $ + {0x00,0x00,0x00,0x00,0x00,0x61,0x63,0x06,0x0C,0x18,0x33,0x63,0x00,0x00,0x00,0x00}, // % + {0x00,0x00,0x00,0x1C,0x36,0x36,0x1C,0x3B,0x6E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // & + {0x00,0x30,0x30,0x30,0x60,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ' + {0x00,0x00,0x0C,0x18,0x18,0x30,0x30,0x30,0x30,0x18,0x18,0x0C,0x00,0x00,0x00,0x00}, // ( + {0x00,0x00,0x18,0x0C,0x0C,0x06,0x06,0x06,0x06,0x0C,0x0C,0x18,0x00,0x00,0x00,0x00}, // ) + {0x00,0x00,0x00,0x00,0x42,0x66,0x3C,0xFF,0x3C,0x66,0x42,0x00,0x00,0x00,0x00,0x00}, // * + {0x00,0x00,0x00,0x00,0x18,0x18,0x18,0xFF,0x18,0x18,0x18,0x00,0x00,0x00,0x00,0x00}, // + + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00}, // , + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // - + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // . + {0x00,0x00,0x01,0x03,0x07,0x0E,0x1C,0x38,0x70,0xE0,0xC0,0x80,0x00,0x00,0x00,0x00}, // / + {0x00,0x00,0x3E,0x63,0x63,0x63,0x6B,0x6B,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // 0 + {0x00,0x00,0x0C,0x1C,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3F,0x00,0x00,0x00,0x00}, // 1 + {0x00,0x00,0x3E,0x63,0x03,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00}, // 2 + {0x00,0x00,0x3E,0x63,0x03,0x03,0x1E,0x03,0x03,0x03,0x63,0x3E,0x00,0x00,0x00,0x00}, // 3 + {0x00,0x00,0x06,0x0E,0x1E,0x36,0x66,0x66,0x7F,0x06,0x06,0x0F,0x00,0x00,0x00,0x00}, // 4 + {0x00,0x00,0x7F,0x60,0x60,0x60,0x7E,0x03,0x03,0x63,0x73,0x3E,0x00,0x00,0x00,0x00}, // 5 + {0x00,0x00,0x1C,0x30,0x60,0x60,0x7E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // 6 + {0x00,0x00,0x7F,0x63,0x03,0x06,0x06,0x0C,0x0C,0x18,0x18,0x18,0x00,0x00,0x00,0x00}, // 7 + {0x00,0x00,0x3E,0x63,0x63,0x63,0x3E,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // 8 + {0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x3F,0x03,0x03,0x06,0x3C,0x00,0x00,0x00,0x00}, // 9 + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x00}, // : + {0x00,0x00,0x00,0x00,0x00,0x18,0x18,0x00,0x00,0x00,0x18,0x18,0x18,0x30,0x00,0x00}, // ; + {0x00,0x00,0x00,0x06,0x0C,0x18,0x30,0x60,0x30,0x18,0x0C,0x06,0x00,0x00,0x00,0x00}, // < + {0x00,0x00,0x00,0x00,0x00,0x00,0x7E,0x00,0x00,0x7E,0x00,0x00,0x00,0x00,0x00,0x00}, // = + {0x00,0x00,0x00,0x60,0x30,0x18,0x0C,0x06,0x0C,0x18,0x30,0x60,0x00,0x00,0x00,0x00}, // > + {0x00,0x00,0x3E,0x63,0x63,0x06,0x0C,0x0C,0x0C,0x00,0x0C,0x0C,0x00,0x00,0x00,0x00}, // ? + {0x00,0x00,0x3E,0x63,0x63,0x6F,0x6B,0x6B,0x6E,0x60,0x60,0x3E,0x00,0x00,0x00,0x00}, // @ + {0x00,0x00,0x08,0x1C,0x36,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // A + {0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x33,0x33,0x33,0x33,0x7E,0x00,0x00,0x00,0x00}, // B + {0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x60,0x60,0x61,0x33,0x1E,0x00,0x00,0x00,0x00}, // C + {0x00,0x00,0x7C,0x36,0x33,0x33,0x33,0x33,0x33,0x33,0x36,0x7C,0x00,0x00,0x00,0x00}, // D + {0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00}, // E + {0x00,0x00,0x7F,0x33,0x31,0x34,0x3C,0x34,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // F + {0x00,0x00,0x1E,0x33,0x61,0x60,0x60,0x6F,0x63,0x63,0x37,0x1D,0x00,0x00,0x00,0x00}, // G + {0x00,0x00,0x63,0x63,0x63,0x63,0x7F,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // H + {0x00,0x00,0x3C,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, // I + {0x00,0x00,0x0F,0x06,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00,0x00,0x00}, // J + {0x00,0x00,0x73,0x33,0x36,0x36,0x3C,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00}, // K + {0x00,0x00,0x78,0x30,0x30,0x30,0x30,0x30,0x30,0x31,0x33,0x7F,0x00,0x00,0x00,0x00}, // L + {0x00,0x00,0x63,0x77,0x7F,0x6B,0x63,0x63,0x63,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // M + {0x00,0x00,0x63,0x63,0x73,0x7B,0x7F,0x6F,0x67,0x63,0x63,0x63,0x00,0x00,0x00,0x00}, // N + {0x00,0x00,0x1C,0x36,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x00,0x00,0x00,0x00}, // O + {0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // P + {0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x63,0x6B,0x6F,0x3E,0x06,0x07,0x00,0x00}, // Q + {0x00,0x00,0x7E,0x33,0x33,0x33,0x3E,0x36,0x36,0x33,0x33,0x73,0x00,0x00,0x00,0x00}, // R + {0x00,0x00,0x3E,0x63,0x63,0x30,0x1C,0x06,0x03,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // S + {0x00,0x00,0xFF,0xDB,0x99,0x18,0x18,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, // T + {0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // U + {0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x63,0x63,0x36,0x1C,0x08,0x00,0x00,0x00,0x00}, // V + {0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x36,0x00,0x00,0x00,0x00}, // W + {0x00,0x00,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x3C,0x66,0xC3,0xC3,0x00,0x00,0x00,0x00}, // X + {0x00,0x00,0xC3,0xC3,0xC3,0x66,0x3C,0x18,0x18,0x18,0x18,0x3C,0x00,0x00,0x00,0x00}, // Y + {0x00,0x00,0x7F,0x63,0x43,0x06,0x0C,0x18,0x30,0x61,0x63,0x7F,0x00,0x00,0x00,0x00}, // Z + {0x00,0x00,0x3C,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x30,0x3C,0x00,0x00,0x00,0x00}, // [ + {0x00,0x00,0x80,0xC0,0xE0,0x70,0x38,0x1C,0x0E,0x07,0x03,0x01,0x00,0x00,0x00,0x00}, // backslash + {0x00,0x00,0x3C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x3C,0x00,0x00,0x00,0x00}, // ] + {0x08,0x1C,0x36,0x63,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ^ + {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xFF,0x00,0x00,0x00}, // _ + {0x18,0x18,0x0C,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ` + {0x00,0x00,0x00,0x00,0x00,0x3C,0x46,0x06,0x3E,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // a + {0x00,0x00,0x70,0x30,0x30,0x3C,0x36,0x33,0x33,0x33,0x33,0x6E,0x00,0x00,0x00,0x00}, // b + {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x60,0x60,0x60,0x63,0x3E,0x00,0x00,0x00,0x00}, // c + {0x00,0x00,0x0E,0x06,0x06,0x1E,0x36,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // d + {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x7E,0x60,0x63,0x3E,0x00,0x00,0x00,0x00}, // e + {0x00,0x00,0x1C,0x36,0x32,0x30,0x7C,0x30,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // f + {0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x66,0x3C,0x00,0x00}, // g + {0x00,0x00,0x70,0x30,0x30,0x36,0x3B,0x33,0x33,0x33,0x33,0x73,0x00,0x00,0x00,0x00}, // h + {0x00,0x00,0x0C,0x0C,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00}, // i + {0x00,0x00,0x06,0x06,0x00,0x0E,0x06,0x06,0x06,0x06,0x06,0x66,0x66,0x3C,0x00,0x00}, // j + {0x00,0x00,0x70,0x30,0x30,0x33,0x33,0x36,0x3C,0x36,0x33,0x73,0x00,0x00,0x00,0x00}, // k + {0x00,0x00,0x1C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x0C,0x1E,0x00,0x00,0x00,0x00}, // l + {0x00,0x00,0x00,0x00,0x00,0x6E,0x7F,0x6B,0x6B,0x6B,0x6B,0x6B,0x00,0x00,0x00,0x00}, // m + {0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x33,0x33,0x00,0x00,0x00,0x00}, // n + {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x63,0x63,0x63,0x63,0x3E,0x00,0x00,0x00,0x00}, // o + {0x00,0x00,0x00,0x00,0x00,0x6E,0x33,0x33,0x33,0x33,0x3E,0x30,0x30,0x78,0x00,0x00}, // p + {0x00,0x00,0x00,0x00,0x00,0x3B,0x66,0x66,0x66,0x66,0x3E,0x06,0x06,0x0F,0x00,0x00}, // q + {0x00,0x00,0x00,0x00,0x00,0x6E,0x3B,0x33,0x30,0x30,0x30,0x78,0x00,0x00,0x00,0x00}, // r + {0x00,0x00,0x00,0x00,0x00,0x3E,0x63,0x38,0x0E,0x03,0x63,0x3E,0x00,0x00,0x00,0x00}, // s + {0x00,0x00,0x08,0x18,0x18,0x7E,0x18,0x18,0x18,0x18,0x1B,0x0E,0x00,0x00,0x00,0x00}, // t + {0x00,0x00,0x00,0x00,0x00,0x66,0x66,0x66,0x66,0x66,0x66,0x3B,0x00,0x00,0x00,0x00}, // u + {0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x36,0x36,0x1C,0x1C,0x08,0x00,0x00,0x00,0x00}, // v + {0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x6B,0x6B,0x7F,0x36,0x00,0x00,0x00,0x00}, // w + {0x00,0x00,0x00,0x00,0x00,0x63,0x36,0x1C,0x1C,0x1C,0x36,0x63,0x00,0x00,0x00,0x00}, // x + {0x00,0x00,0x00,0x00,0x00,0x63,0x63,0x63,0x63,0x63,0x3F,0x03,0x06,0x3C,0x00,0x00}, // y + {0x00,0x00,0x00,0x00,0x00,0x7F,0x66,0x0C,0x18,0x30,0x63,0x7F,0x00,0x00,0x00,0x00}, // z + {0x00,0x00,0x0E,0x18,0x18,0x18,0x70,0x18,0x18,0x18,0x18,0x0E,0x00,0x00,0x00,0x00}, // { + {0x00,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x18,0x18,0x18,0x18,0x18,0x00,0x00,0x00}, // | + {0x00,0x00,0x70,0x18,0x18,0x18,0x0E,0x18,0x18,0x18,0x18,0x70,0x00,0x00,0x00,0x00}, // } + {0x00,0x00,0x3B,0x6E,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00}, // ~ + {0x00,0x70,0xD8,0xD8,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00} // DEL }; */ diff --git a/armsrc/fpgaloader.c b/armsrc/fpgaloader.c index 18430b78b..2af6fd0ec 100644 --- a/armsrc/fpgaloader.c +++ b/armsrc/fpgaloader.c @@ -21,7 +21,7 @@ extern uint8_t _binary_obj_fpga_all_bit_z_start, _binary_obj_fpga_all_bit_z_end; static uint8_t *fpga_image_ptr = NULL; static uint32_t uncompressed_bytes_cnt; -#define OUTPUT_BUFFER_LEN 80 +#define OUTPUT_BUFFER_LEN 80 //----------------------------------------------------------------------------- // Set up the Serial Peripheral Interface as master @@ -29,7 +29,7 @@ static uint32_t uncompressed_bytes_cnt; // May also be used to write to other SPI attached devices like an LCD //----------------------------------------------------------------------------- static void DisableSpi(void) { - //* Reset all the Chip Select register + //* Reset all the Chip Select register AT91C_BASE_SPI->SPI_CSR[0] = 0; AT91C_BASE_SPI->SPI_CSR[1] = 0; AT91C_BASE_SPI->SPI_CSR[2] = 0; @@ -41,77 +41,77 @@ static void DisableSpi(void) { // Disable all interrupts AT91C_BASE_SPI->SPI_IDR = 0xFFFFFFFF; - // SPI disable - AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS; + // SPI disable + AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIDIS; } void SetupSpi(int mode) { - // PA1 -> SPI_NCS3 chip select (MEM) - // PA10 -> SPI_NCS2 chip select (LCD) - // PA11 -> SPI_NCS0 chip select (FPGA) - // PA12 -> SPI_MISO Master-In Slave-Out - // PA13 -> SPI_MOSI Master-Out Slave-In - // PA14 -> SPI_SPCK Serial Clock + // PA1 -> SPI_NCS3 chip select (MEM) + // PA10 -> SPI_NCS2 chip select (LCD) + // PA11 -> SPI_NCS0 chip select (FPGA) + // PA12 -> SPI_MISO Master-In Slave-Out + // PA13 -> SPI_MOSI Master-Out Slave-In + // PA14 -> SPI_SPCK Serial Clock - // Disable PIO control of the following pins, allows use by the SPI peripheral - AT91C_BASE_PIOA->PIO_PDR = GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK; + // Disable PIO control of the following pins, allows use by the SPI peripheral + AT91C_BASE_PIOA->PIO_PDR = GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK; - // Peripheral A - AT91C_BASE_PIOA->PIO_ASR = GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK; + // Peripheral A + AT91C_BASE_PIOA->PIO_ASR = GPIO_NCS0 | GPIO_MISO | GPIO_MOSI | GPIO_SPCK; - // Peripheral B - //AT91C_BASE_PIOA->PIO_BSR |= GPIO_NCS2; + // Peripheral B + //AT91C_BASE_PIOA->PIO_BSR |= GPIO_NCS2; - //enable the SPI Peripheral clock - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI); - // Enable SPI - AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN; + //enable the SPI Peripheral clock + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SPI); + // Enable SPI + AT91C_BASE_SPI->SPI_CR = AT91C_SPI_SPIEN; - switch (mode) { - case SPI_FPGA_MODE: - AT91C_BASE_SPI->SPI_MR = - ( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods) - (0xE << 16) | // Peripheral Chip Select (selects FPGA SPI_NCS0 or PA11) - ( 0 << 7) | // Local Loopback Disabled - AT91C_SPI_MODFDIS | // Mode Fault Detection disabled - ( 0 << 2) | // Chip selects connected directly to peripheral - AT91C_SPI_PS_FIXED | // Fixed Peripheral Select - AT91C_SPI_MSTR; // Master Mode + switch (mode) { + case SPI_FPGA_MODE: + AT91C_BASE_SPI->SPI_MR = + ( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods) + (0xE << 16) | // Peripheral Chip Select (selects FPGA SPI_NCS0 or PA11) + ( 0 << 7) | // Local Loopback Disabled + AT91C_SPI_MODFDIS | // Mode Fault Detection disabled + ( 0 << 2) | // Chip selects connected directly to peripheral + AT91C_SPI_PS_FIXED | // Fixed Peripheral Select + AT91C_SPI_MSTR; // Master Mode - AT91C_BASE_SPI->SPI_CSR[0] = - ( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods) - ( 1 << 16) | // Delay Before SPCK (1 MCK period) - ( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud - AT91C_SPI_BITS_16 | // Bits per Transfer (16 bits) - ( 0 << 3) | // Chip Select inactive after transfer - AT91C_SPI_NCPHA | // Clock Phase data captured on leading edge, changes on following edge - ( 0 << 0); // Clock Polarity inactive state is logic 0 - break; + AT91C_BASE_SPI->SPI_CSR[0] = + ( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods) + ( 1 << 16) | // Delay Before SPCK (1 MCK period) + ( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud + AT91C_SPI_BITS_16 | // Bits per Transfer (16 bits) + ( 0 << 3) | // Chip Select inactive after transfer + AT91C_SPI_NCPHA | // Clock Phase data captured on leading edge, changes on following edge + ( 0 << 0); // Clock Polarity inactive state is logic 0 + break; /* - case SPI_LCD_MODE: - AT91C_BASE_SPI->SPI_MR = - ( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods) - (0xB << 16) | // Peripheral Chip Select (selects LCD SPI_NCS2 or PA10) - ( 0 << 7) | // Local Loopback Disabled - ( 1 << 4) | // Mode Fault Detection disabled - ( 0 << 2) | // Chip selects connected directly to peripheral - ( 0 << 1) | // Fixed Peripheral Select - ( 1 << 0); // Master Mode + case SPI_LCD_MODE: + AT91C_BASE_SPI->SPI_MR = + ( 0 << 24) | // Delay between chip selects (take default: 6 MCK periods) + (0xB << 16) | // Peripheral Chip Select (selects LCD SPI_NCS2 or PA10) + ( 0 << 7) | // Local Loopback Disabled + ( 1 << 4) | // Mode Fault Detection disabled + ( 0 << 2) | // Chip selects connected directly to peripheral + ( 0 << 1) | // Fixed Peripheral Select + ( 1 << 0); // Master Mode - AT91C_BASE_SPI->SPI_CSR[2] = - ( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods) - ( 1 << 16) | // Delay Before SPCK (1 MCK period) - ( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud - AT91C_SPI_BITS_9 | // Bits per Transfer (9 bits) - ( 0 << 3) | // Chip Select inactive after transfer - ( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge - ( 0 << 0); // Clock Polarity inactive state is logic 0 - break; + AT91C_BASE_SPI->SPI_CSR[2] = + ( 1 << 24) | // Delay between Consecutive Transfers (32 MCK periods) + ( 1 << 16) | // Delay Before SPCK (1 MCK period) + ( 6 << 8) | // Serial Clock Baud Rate (baudrate = MCK/6 = 24Mhz/6 = 4M baud + AT91C_SPI_BITS_9 | // Bits per Transfer (9 bits) + ( 0 << 3) | // Chip Select inactive after transfer + ( 1 << 1) | // Clock Phase data captured on leading edge, changes on following edge + ( 0 << 0); // Clock Polarity inactive state is logic 0 + break; */ - default: - DisableSpi(); - break; - } + default: + DisableSpi(); + break; + } } //----------------------------------------------------------------------------- @@ -119,35 +119,35 @@ void SetupSpi(int mode) { // always use when we are talking to the FPGA. Both RX and TX are enabled. //----------------------------------------------------------------------------- void FpgaSetupSsc(void) { - // First configure the GPIOs, and get ourselves a clock. - AT91C_BASE_PIOA->PIO_ASR = - GPIO_SSC_FRAME | - GPIO_SSC_DIN | - GPIO_SSC_DOUT | - GPIO_SSC_CLK; - AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT; + // First configure the GPIOs, and get ourselves a clock. + AT91C_BASE_PIOA->PIO_ASR = + GPIO_SSC_FRAME | + GPIO_SSC_DIN | + GPIO_SSC_DOUT | + GPIO_SSC_CLK; + AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT; - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SSC); + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_SSC); - // Now set up the SSC proper, starting from a known state. - AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; + // Now set up the SSC proper, starting from a known state. + AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; - // RX clock comes from TX clock, RX starts when TX starts, data changes - // on RX clock rising edge, sampled on falling edge - AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(1) | SSC_CLOCK_MODE_START(1); + // RX clock comes from TX clock, RX starts when TX starts, data changes + // on RX clock rising edge, sampled on falling edge + AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(1) | SSC_CLOCK_MODE_START(1); - // 8 bits per transfer, no loopback, MSB first, 1 transfer per sync - // pulse, no output sync - AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); + // 8 bits per transfer, no loopback, MSB first, 1 transfer per sync + // pulse, no output sync + AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - // clock comes from TK pin, no clock output, outputs change on falling - // edge of TK, sample on rising edge of TK, start on positive-going edge of sync - AT91C_BASE_SSC->SSC_TCMR = SSC_CLOCK_MODE_SELECT(2) | SSC_CLOCK_MODE_START(5); + // clock comes from TK pin, no clock output, outputs change on falling + // edge of TK, sample on rising edge of TK, start on positive-going edge of sync + AT91C_BASE_SSC->SSC_TCMR = SSC_CLOCK_MODE_SELECT(2) | SSC_CLOCK_MODE_START(5); - // tx framing is the same as the rx framing - AT91C_BASE_SSC->SSC_TFMR = AT91C_BASE_SSC->SSC_RFMR; + // tx framing is the same as the rx framing + AT91C_BASE_SSC->SSC_TFMR = AT91C_BASE_SSC->SSC_RFMR; - AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN; + AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN; } //----------------------------------------------------------------------------- @@ -157,15 +157,15 @@ void FpgaSetupSsc(void) { // is in apps.h, because it should be inlined, for speed. //----------------------------------------------------------------------------- bool FpgaSetupSscDma(uint8_t *buf, int len) { - if (buf == NULL) return false; + if (buf == NULL) return false; - FpgaDisableSscDma(); - AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) buf; // transfer to this memory address - AT91C_BASE_PDC_SSC->PDC_RCR = len; // transfer this many bytes - AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) buf; // next transfer to same memory address - AT91C_BASE_PDC_SSC->PDC_RNCR = len; // ... with same number of bytes - FpgaEnableSscDma(); - return true; + FpgaDisableSscDma(); + AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) buf; // transfer to this memory address + AT91C_BASE_PDC_SSC->PDC_RCR = len; // transfer this many bytes + AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) buf; // next transfer to same memory address + AT91C_BASE_PDC_SSC->PDC_RNCR = len; // ... with same number of bytes + FpgaEnableSscDma(); + return true; } //---------------------------------------------------------------------------- @@ -173,20 +173,20 @@ bool FpgaSetupSscDma(uint8_t *buf, int len) { // each call. //---------------------------------------------------------------------------- static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8_t *output_buffer) { - if (fpga_image_ptr == compressed_fpga_stream->next_out) { // need more data - compressed_fpga_stream->next_out = output_buffer; - compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN; - fpga_image_ptr = output_buffer; - int res = inflate(compressed_fpga_stream, Z_SYNC_FLUSH); + if (fpga_image_ptr == compressed_fpga_stream->next_out) { // need more data + compressed_fpga_stream->next_out = output_buffer; + compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN; + fpga_image_ptr = output_buffer; + int res = inflate(compressed_fpga_stream, Z_SYNC_FLUSH); - if (res != Z_OK) - Dbprintf("inflate returned: %d, %s", res, compressed_fpga_stream->msg); + if (res != Z_OK) + Dbprintf("inflate returned: %d, %s", res, compressed_fpga_stream->msg); - if (res < 0) - return res; - } - uncompressed_bytes_cnt++; - return *fpga_image_ptr++; + if (res < 0) + return res; + } + uncompressed_bytes_cnt++; + return *fpga_image_ptr++; } //---------------------------------------------------------------------------- @@ -195,140 +195,140 @@ static int get_from_fpga_combined_stream(z_streamp compressed_fpga_stream, uint8 // 288 bytes from FPGA file 1, followed by 288 bytes from FGPA file 2, etc. //---------------------------------------------------------------------------- static int get_from_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { - while((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % fpga_bitstream_num != (bitstream_version - 1)) { - // skip undesired data belonging to other bitstream_versions - get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer); - } + while((uncompressed_bytes_cnt / FPGA_INTERLEAVE_SIZE) % fpga_bitstream_num != (bitstream_version - 1)) { + // skip undesired data belonging to other bitstream_versions + get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer); + } - return get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer); + return get_from_fpga_combined_stream(compressed_fpga_stream, output_buffer); } static voidpf fpga_inflate_malloc(voidpf opaque, uInt items, uInt size) { - return BigBuf_malloc(items*size); + return BigBuf_malloc(items*size); } // free eventually allocated BigBuf memory static void fpga_inflate_free(voidpf opaque, voidpf address) { - BigBuf_free(); BigBuf_Clear_ext(false); + BigBuf_free(); BigBuf_Clear_ext(false); } //---------------------------------------------------------------------------- // Initialize decompression of the respective (HF or LF) FPGA stream //---------------------------------------------------------------------------- static bool reset_fpga_stream(int bitstream_version, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { - uint8_t header[FPGA_BITSTREAM_FIXED_HEADER_SIZE]; + uint8_t header[FPGA_BITSTREAM_FIXED_HEADER_SIZE]; - uncompressed_bytes_cnt = 0; + uncompressed_bytes_cnt = 0; - // initialize z_stream structure for inflate: - compressed_fpga_stream->next_in = &_binary_obj_fpga_all_bit_z_start; - compressed_fpga_stream->avail_in = &_binary_obj_fpga_all_bit_z_end - &_binary_obj_fpga_all_bit_z_start; - compressed_fpga_stream->next_out = output_buffer; - compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN; - compressed_fpga_stream->zalloc = &fpga_inflate_malloc; - compressed_fpga_stream->zfree = &fpga_inflate_free; + // initialize z_stream structure for inflate: + compressed_fpga_stream->next_in = &_binary_obj_fpga_all_bit_z_start; + compressed_fpga_stream->avail_in = &_binary_obj_fpga_all_bit_z_end - &_binary_obj_fpga_all_bit_z_start; + compressed_fpga_stream->next_out = output_buffer; + compressed_fpga_stream->avail_out = OUTPUT_BUFFER_LEN; + compressed_fpga_stream->zalloc = &fpga_inflate_malloc; + compressed_fpga_stream->zfree = &fpga_inflate_free; - inflateInit2(compressed_fpga_stream, 0); + inflateInit2(compressed_fpga_stream, 0); - fpga_image_ptr = output_buffer; + fpga_image_ptr = output_buffer; - for (uint16_t i = 0; i < FPGA_BITSTREAM_FIXED_HEADER_SIZE; i++) - header[i] = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); + for (uint16_t i = 0; i < FPGA_BITSTREAM_FIXED_HEADER_SIZE; i++) + header[i] = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); - // Check for a valid .bit file (starts with bitparse_fixed_header) - if (memcmp(bitparse_fixed_header, header, FPGA_BITSTREAM_FIXED_HEADER_SIZE) == 0) - return true; + // Check for a valid .bit file (starts with bitparse_fixed_header) + if (memcmp(bitparse_fixed_header, header, FPGA_BITSTREAM_FIXED_HEADER_SIZE) == 0) + return true; - return false; + return false; } static void DownloadFPGA_byte( uint8_t w) { #define SEND_BIT(x) { if(w & (1<PIO_OER = GPIO_FPGA_ON; - AT91C_BASE_PIOA->PIO_PER = GPIO_FPGA_ON; - HIGH(GPIO_FPGA_ON); // ensure everything is powered on + AT91C_BASE_PIOA->PIO_OER = GPIO_FPGA_ON; + AT91C_BASE_PIOA->PIO_PER = GPIO_FPGA_ON; + HIGH(GPIO_FPGA_ON); // ensure everything is powered on - SpinDelay(50); + SpinDelay(50); - LED_D_ON(); + LED_D_ON(); - // These pins are inputs + // These pins are inputs AT91C_BASE_PIOA->PIO_ODR = - GPIO_FPGA_NINIT | - GPIO_FPGA_DONE; - // PIO controls the following pins + GPIO_FPGA_NINIT | + GPIO_FPGA_DONE; + // PIO controls the following pins AT91C_BASE_PIOA->PIO_PER = - GPIO_FPGA_NINIT | - GPIO_FPGA_DONE; - // Enable pull-ups - AT91C_BASE_PIOA->PIO_PPUER = - GPIO_FPGA_NINIT | - GPIO_FPGA_DONE; + GPIO_FPGA_NINIT | + GPIO_FPGA_DONE; + // Enable pull-ups + AT91C_BASE_PIOA->PIO_PPUER = + GPIO_FPGA_NINIT | + GPIO_FPGA_DONE; - // setup initial logic state - HIGH(GPIO_FPGA_NPROGRAM); - LOW(GPIO_FPGA_CCLK); - LOW(GPIO_FPGA_DIN); - // These pins are outputs - AT91C_BASE_PIOA->PIO_OER = - GPIO_FPGA_NPROGRAM | - GPIO_FPGA_CCLK | - GPIO_FPGA_DIN; + // setup initial logic state + HIGH(GPIO_FPGA_NPROGRAM); + LOW(GPIO_FPGA_CCLK); + LOW(GPIO_FPGA_DIN); + // These pins are outputs + AT91C_BASE_PIOA->PIO_OER = + GPIO_FPGA_NPROGRAM | + GPIO_FPGA_CCLK | + GPIO_FPGA_DIN; - // enter FPGA configuration mode - LOW(GPIO_FPGA_NPROGRAM); - SpinDelay(50); - HIGH(GPIO_FPGA_NPROGRAM); + // enter FPGA configuration mode + LOW(GPIO_FPGA_NPROGRAM); + SpinDelay(50); + HIGH(GPIO_FPGA_NPROGRAM); - i = 100000; - // wait for FPGA ready to accept data signal - while ((i) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_NINIT ) ) ) { - i--; - } + i = 100000; + // wait for FPGA ready to accept data signal + while ((i) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_NINIT ) ) ) { + i--; + } - // crude error indicator, leave both red LEDs on and return - if (i==0){ - LED_C_ON(); - LED_D_ON(); - return; - } + // crude error indicator, leave both red LEDs on and return + if (i==0){ + LED_C_ON(); + LED_D_ON(); + return; + } - for (i = 0; i < FpgaImageLen; i++) { - int b = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); - if (b < 0) { - Dbprintf("Error %d during FpgaDownload", b); - break; - } - DownloadFPGA_byte(b); - } + for (i = 0; i < FpgaImageLen; i++) { + int b = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); + if (b < 0) { + Dbprintf("Error %d during FpgaDownload", b); + break; + } + DownloadFPGA_byte(b); + } - // continue to clock FPGA until ready signal goes high - i = 100000; - while ( (i--) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE ) ) ) { - HIGH(GPIO_FPGA_CCLK); - LOW(GPIO_FPGA_CCLK); - } - // crude error indicator, leave both red LEDs on and return - if (i==0){ - LED_C_ON(); - LED_D_ON(); - return; - } - LED_D_OFF(); + // continue to clock FPGA until ready signal goes high + i = 100000; + while ( (i--) && ( !(AT91C_BASE_PIOA->PIO_PDSR & GPIO_FPGA_DONE ) ) ) { + HIGH(GPIO_FPGA_CCLK); + LOW(GPIO_FPGA_CCLK); + } + // crude error indicator, leave both red LEDs on and return + if (i==0){ + LED_C_ON(); + LED_D_ON(); + return; + } + LED_D_OFF(); } /* Simple Xilinx .bit parser. The file starts with the fixed opaque byte sequence @@ -338,48 +338,48 @@ static void DownloadFPGA(int bitstream_version, int FpgaImageLen, z_streamp comp * length. */ static int bitparse_find_section(int bitstream_version, char section_name, uint32_t *section_length, z_streamp compressed_fpga_stream, uint8_t *output_buffer) { - int result = 0; - #define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section - uint16_t numbytes = 0; - while(numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) { - char current_name = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); - numbytes++; - uint32_t current_length = 0; - if (current_name < 'a' || current_name > 'e') { - /* Strange section name, abort */ - break; - } - current_length = 0; - switch (current_name) { - case 'e': - /* Four byte length field */ - current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 24; - current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16; - numbytes += 2; - default: /* Fall through, two byte length field */ - current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8; - current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0; - numbytes += 2; - } + int result = 0; + #define MAX_FPGA_BIT_STREAM_HEADER_SEARCH 100 // maximum number of bytes to search for the requested section + uint16_t numbytes = 0; + while(numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH) { + char current_name = get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); + numbytes++; + uint32_t current_length = 0; + if (current_name < 'a' || current_name > 'e') { + /* Strange section name, abort */ + break; + } + current_length = 0; + switch (current_name) { + case 'e': + /* Four byte length field */ + current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 24; + current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 16; + numbytes += 2; + default: /* Fall through, two byte length field */ + current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 8; + current_length += get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer) << 0; + numbytes += 2; + } - if (current_name != 'e' && current_length > 255) { - /* Maybe a parse error */ - break; - } + if (current_name != 'e' && current_length > 255) { + /* Maybe a parse error */ + break; + } - if (current_name == section_name) { - /* Found it */ - *section_length = current_length; - result = 1; - break; - } + if (current_name == section_name) { + /* Found it */ + *section_length = current_length; + result = 1; + break; + } - for (uint16_t i = 0; i < current_length && numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH; i++) { - get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); - numbytes++; - } - } - return result; + for (uint16_t i = 0; i < current_length && numbytes < MAX_FPGA_BIT_STREAM_HEADER_SEARCH; i++) { + get_from_fpga_stream(bitstream_version, compressed_fpga_stream, output_buffer); + numbytes++; + } + } + return result; } //---------------------------------------------------------------------------- @@ -388,34 +388,34 @@ static int bitparse_find_section(int bitstream_version, char section_name, uint3 //---------------------------------------------------------------------------- void FpgaDownloadAndGo(int bitstream_version) { - // check whether or not the bitstream is already loaded - if (downloaded_bitstream == bitstream_version) - return; + // check whether or not the bitstream is already loaded + if (downloaded_bitstream == bitstream_version) + return; - z_stream compressed_fpga_stream; - uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00}; + z_stream compressed_fpga_stream; + uint8_t output_buffer[OUTPUT_BUFFER_LEN] = {0x00}; - bool verbose = (MF_DBGLEVEL > 3); + bool verbose = (MF_DBGLEVEL > 3); - // make sure that we have enough memory to decompress - BigBuf_free(); BigBuf_Clear_ext(verbose); + // make sure that we have enough memory to decompress + BigBuf_free(); BigBuf_Clear_ext(verbose); - if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer)) - return; + if (!reset_fpga_stream(bitstream_version, &compressed_fpga_stream, output_buffer)) + return; - uint32_t bitstream_length; - if (bitparse_find_section(bitstream_version, 'e', &bitstream_length, &compressed_fpga_stream, output_buffer)) { - DownloadFPGA(bitstream_version, bitstream_length, &compressed_fpga_stream, output_buffer); - downloaded_bitstream = bitstream_version; - } + uint32_t bitstream_length; + if (bitparse_find_section(bitstream_version, 'e', &bitstream_length, &compressed_fpga_stream, output_buffer)) { + DownloadFPGA(bitstream_version, bitstream_length, &compressed_fpga_stream, output_buffer); + downloaded_bitstream = bitstream_version; + } - inflateEnd(&compressed_fpga_stream); + inflateEnd(&compressed_fpga_stream); - // turn off antenna - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + // turn off antenna + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - // free eventually allocated BigBuf memory - BigBuf_free(); BigBuf_Clear_ext(false); + // free eventually allocated BigBuf memory + BigBuf_free(); BigBuf_Clear_ext(false); } //----------------------------------------------------------------------------- @@ -424,10 +424,10 @@ void FpgaDownloadAndGo(int bitstream_version) { // where C is the 4 bit command and D is the 12 bit data //----------------------------------------------------------------------------- void FpgaSendCommand(uint16_t cmd, uint16_t v) { - SetupSpi(SPI_FPGA_MODE); - while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete - AT91C_BASE_SPI->SPI_TDR = AT91C_SPI_LASTXFER | cmd | v; // send the data - while (!(AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF)) {}; // wait till transfer is complete + SetupSpi(SPI_FPGA_MODE); + while ((AT91C_BASE_SPI->SPI_SR & AT91C_SPI_TXEMPTY) == 0); // wait for the transfer to complete + AT91C_BASE_SPI->SPI_TDR = AT91C_SPI_LASTXFER | cmd | v; // send the data + while (!(AT91C_BASE_SPI->SPI_SR & AT91C_SPI_RDRF)) {}; // wait till transfer is complete } //----------------------------------------------------------------------------- // Write the FPGA setup word (that determines what mode the logic is in, read @@ -435,7 +435,7 @@ void FpgaSendCommand(uint16_t cmd, uint16_t v) { // avoid changing this function's occurence everywhere in the source code. //----------------------------------------------------------------------------- void FpgaWriteConfWord(uint8_t v) { - FpgaSendCommand(FPGA_CMD_SET_CONFREG, v); + FpgaSendCommand(FPGA_CMD_SET_CONFREG, v); } //----------------------------------------------------------------------------- @@ -444,35 +444,35 @@ void FpgaWriteConfWord(uint8_t v) { // the samples from the ADC always flow through the FPGA. //----------------------------------------------------------------------------- void SetAdcMuxFor(uint32_t whichGpio) { - AT91C_BASE_PIOA->PIO_OER = - GPIO_MUXSEL_HIPKD | - GPIO_MUXSEL_LOPKD | - GPIO_MUXSEL_LORAW | - GPIO_MUXSEL_HIRAW; + AT91C_BASE_PIOA->PIO_OER = + GPIO_MUXSEL_HIPKD | + GPIO_MUXSEL_LOPKD | + GPIO_MUXSEL_LORAW | + GPIO_MUXSEL_HIRAW; - AT91C_BASE_PIOA->PIO_PER = - GPIO_MUXSEL_HIPKD | - GPIO_MUXSEL_LOPKD | - GPIO_MUXSEL_LORAW | - GPIO_MUXSEL_HIRAW; + AT91C_BASE_PIOA->PIO_PER = + GPIO_MUXSEL_HIPKD | + GPIO_MUXSEL_LOPKD | + GPIO_MUXSEL_LORAW | + GPIO_MUXSEL_HIRAW; - LOW(GPIO_MUXSEL_HIPKD); - LOW(GPIO_MUXSEL_LOPKD); + LOW(GPIO_MUXSEL_HIPKD); + LOW(GPIO_MUXSEL_LOPKD); #ifndef WITH_FPC - LOW(GPIO_MUXSEL_HIRAW); - LOW(GPIO_MUXSEL_LORAW); + LOW(GPIO_MUXSEL_HIRAW); + LOW(GPIO_MUXSEL_LORAW); #endif - HIGH(whichGpio); + HIGH(whichGpio); } void Fpga_print_status(void) { - Dbprintf("Currently loaded FPGA image"); - Dbprintf(" mode....................%s", fpga_version_information[downloaded_bitstream-1]); + Dbprintf("Currently loaded FPGA image"); + Dbprintf(" mode....................%s", fpga_version_information[downloaded_bitstream-1]); } int FpgaGetCurrent(void) { - return downloaded_bitstream; + return downloaded_bitstream; } // Turns off the antenna, @@ -480,10 +480,10 @@ int FpgaGetCurrent(void) { // if HF, Disable SSC DMA // turn off trace and leds off. void switch_off(void) { - if (MF_DBGLEVEL > 3) Dbprintf("switch_off"); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - if (downloaded_bitstream == FPGA_BITSTREAM_HF ) - FpgaDisableSscDma(); - set_tracing(false); - LEDsoff(); + if (MF_DBGLEVEL > 3) Dbprintf("switch_off"); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + if (downloaded_bitstream == FPGA_BITSTREAM_HF ) + FpgaDisableSscDma(); + set_tracing(false); + LEDsoff(); } diff --git a/armsrc/fpgaloader.h b/armsrc/fpgaloader.h index 7f9ec28e6..ef278cc3e 100644 --- a/armsrc/fpgaloader.h +++ b/armsrc/fpgaloader.h @@ -16,11 +16,11 @@ #include #include "apps.h" #include "fpga.h" -#include "common.h" // standard definitions -#include "proxmark3.h" // common area +#include "common.h" // standard definitions +#include "proxmark3.h" // common area #include "string.h" -#include "BigBuf.h" // bigbuf mem -#include "zlib.h" // uncompress +#include "BigBuf.h" // bigbuf mem +#include "zlib.h" // uncompress void FpgaSendCommand(uint16_t cmd, uint16_t v); @@ -32,7 +32,7 @@ void SetupSpi(int mode); bool FpgaSetupSscDma(uint8_t *buf, int len); void Fpga_print_status(void); int FpgaGetCurrent(void); -#define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; +#define FpgaDisableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTDIS; #define FpgaEnableSscDma(void) AT91C_BASE_PDC_SSC->PDC_PTCR = AT91C_PDC_RXTEN; void SetAdcMuxFor(uint32_t whichGpio); @@ -45,56 +45,56 @@ extern void switch_off(void); //#define FPGA_BITSTREAM_FELICA 3 // Definitions for the FPGA commands. -#define FPGA_CMD_SET_CONFREG (1<<12) -#define FPGA_CMD_SET_DIVISOR (2<<12) -#define FPGA_CMD_SET_USER_BYTE1 (3<<12) +#define FPGA_CMD_SET_CONFREG (1<<12) +#define FPGA_CMD_SET_DIVISOR (2<<12) +#define FPGA_CMD_SET_USER_BYTE1 (3<<12) // Definitions for the FPGA configuration word. // LF -#define FPGA_MAJOR_MODE_LF_ADC (0<<5) -#define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5) -#define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<5) +#define FPGA_MAJOR_MODE_LF_ADC (0<<5) +#define FPGA_MAJOR_MODE_LF_EDGE_DETECT (1<<5) +#define FPGA_MAJOR_MODE_LF_PASSTHRU (2<<5) // HF -#define FPGA_MAJOR_MODE_HF_READER_TX (0<<5) -#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5) -#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5) -#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5) -#define FPGA_MAJOR_MODE_HF_SNOOP (4<<5) -#define FPGA_MAJOR_MODE_HF_FELICA (5<<5) +#define FPGA_MAJOR_MODE_HF_READER_TX (0<<5) +#define FPGA_MAJOR_MODE_HF_READER_RX_XCORR (1<<5) +#define FPGA_MAJOR_MODE_HF_SIMULATOR (2<<5) +#define FPGA_MAJOR_MODE_HF_ISO14443A (3<<5) +#define FPGA_MAJOR_MODE_HF_SNOOP (4<<5) +#define FPGA_MAJOR_MODE_HF_FELICA (5<<5) // BOTH -#define FPGA_MAJOR_MODE_OFF_LF (6<<5) -#define FPGA_MAJOR_MODE_OFF (7<<5) +#define FPGA_MAJOR_MODE_OFF_LF (6<<5) +#define FPGA_MAJOR_MODE_OFF (7<<5) // Options for LF_ADC -#define FPGA_LF_ADC_READER_FIELD (1<<0) +#define FPGA_LF_ADC_READER_FIELD (1<<0) // Options for LF_EDGE_DETECT -#define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1 -#define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0) -#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE (1<<1) +#define FPGA_CMD_SET_EDGE_DETECT_THRESHOLD FPGA_CMD_SET_USER_BYTE1 +#define FPGA_LF_EDGE_DETECT_READER_FIELD (1<<0) +#define FPGA_LF_EDGE_DETECT_TOGGLE_MODE (1<<1) // Options for the HF reader, tx to tag -#define FPGA_HF_READER_TX_SHALLOW_MOD (1<<0) +#define FPGA_HF_READER_TX_SHALLOW_MOD (1<<0) // Options for the HF reader, correlating against rx from tag -#define FPGA_HF_READER_RX_XCORR_848_KHZ (1<<0) -#define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1) -#define FPGA_HF_READER_RX_XCORR_QUARTER (1<<2) +#define FPGA_HF_READER_RX_XCORR_848_KHZ (1<<0) +#define FPGA_HF_READER_RX_XCORR_SNOOP (1<<1) +#define FPGA_HF_READER_RX_XCORR_QUARTER (1<<2) // Options for the HF simulated tag, how to modulate -#define FPGA_HF_SIMULATOR_NO_MODULATION 0x0 // 0000 -#define FPGA_HF_SIMULATOR_MODULATE_BPSK 0x1 // 0001 -#define FPGA_HF_SIMULATOR_MODULATE_212K 0x2 // 0010 -#define FPGA_HF_SIMULATOR_MODULATE_424K 0x4 // 0100 -#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5 // 0101 +#define FPGA_HF_SIMULATOR_NO_MODULATION 0x0 // 0000 +#define FPGA_HF_SIMULATOR_MODULATE_BPSK 0x1 // 0001 +#define FPGA_HF_SIMULATOR_MODULATE_212K 0x2 // 0010 +#define FPGA_HF_SIMULATOR_MODULATE_424K 0x4 // 0100 +#define FPGA_HF_SIMULATOR_MODULATE_424K_8BIT 0x5 // 0101 // no 848K // Options for ISO14443A -#define FPGA_HF_ISO14443A_SNIFFER (0<<0) -#define FPGA_HF_ISO14443A_TAGSIM_LISTEN (1<<0) -#define FPGA_HF_ISO14443A_TAGSIM_MOD (2<<0) -#define FPGA_HF_ISO14443A_READER_LISTEN (3<<0) -#define FPGA_HF_ISO14443A_READER_MOD (4<<0) +#define FPGA_HF_ISO14443A_SNIFFER (0<<0) +#define FPGA_HF_ISO14443A_TAGSIM_LISTEN (1<<0) +#define FPGA_HF_ISO14443A_TAGSIM_MOD (2<<0) +#define FPGA_HF_ISO14443A_READER_LISTEN (3<<0) +#define FPGA_HF_ISO14443A_READER_MOD (4<<0) //options for Felica. -#define FPGA_MAJOR_MODE_ISO18092 (5<<5) // 01010 0000 +#define FPGA_MAJOR_MODE_ISO18092 (5<<5) // 01010 0000 #define FPGA_HF_ISO18092_FLAG_NOMOD (1<<0) // 0001 disable modulation module #define FPGA_HF_ISO18092_FLAG_424K (2<<0) // 0010 should enable 414k mode (untested). No autodetect -#define FPGA_HF_ISO18092_FLAG_READER (4<<0) // 0100 enables antenna power, to act as a reader instead of tag +#define FPGA_HF_ISO18092_FLAG_READER (4<<0) // 0100 enables antenna power, to act as a reader instead of tag -#endif \ No newline at end of file +#endif diff --git a/armsrc/hfsnoop.c b/armsrc/hfsnoop.c index d66f88276..117e064e8 100644 --- a/armsrc/hfsnoop.c +++ b/armsrc/hfsnoop.c @@ -2,79 +2,79 @@ #include "apps.h" #include "BigBuf.h" #include "util.h" -#include "usb_cdc.h" // for usb_poll_validate_length +#include "usb_cdc.h" // for usb_poll_validate_length static void RAMFUNC optimizedSnoop(void); static void RAMFUNC optimizedSnoop(void) { - int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory + int n = BigBuf_max_traceLen() / sizeof(uint16_t); // take all memory - uint16_t *dest = (uint16_t *)BigBuf_get_addr(); + uint16_t *dest = (uint16_t *)BigBuf_get_addr(); uint16_t *destend = dest + n-1; - // Reading data loop - while(dest <= destend) { - if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - *dest = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); - dest++; - } - } + // Reading data loop + while(dest <= destend) { + if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + *dest = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); + dest++; + } + } //setting tracelen - important! it was set by buffer overflow before set_tracelen( BigBuf_max_traceLen()); } void HfSnoop(int samplesToSkip, int triggersToSkip) { - BigBuf_free(); BigBuf_Clear(); + BigBuf_free(); BigBuf_Clear(); - Dbprintf("Skipping first %d sample pairs, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); - int trigger_cnt = 0; + Dbprintf("Skipping first %d sample pairs, Skipping %d triggers.\n", samplesToSkip, triggersToSkip); + int trigger_cnt = 0; - LED_D_ON(); + LED_D_ON(); - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - // Set up the synchronous serial port - FpgaSetupSsc(); + // Set up the synchronous serial port + FpgaSetupSsc(); - // Setting Frame Mode For better performance on high speed data transfer. - AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16); + // Setting Frame Mode For better performance on high speed data transfer. + AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(16); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNOOP); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SNOOP); SpinDelay(100); - uint16_t r = 0; - while (!BUTTON_PRESS() && !usb_poll_validate_length() ) { - WDT_HIT(); + uint16_t r = 0; + while (!BUTTON_PRESS() && !usb_poll_validate_length() ) { + WDT_HIT(); - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - r = (uint16_t)AT91C_BASE_SSC->SSC_RHR; - r = MAX(r & 0xff, r >> 8); + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + r = (uint16_t)AT91C_BASE_SSC->SSC_RHR; + r = MAX(r & 0xff, r >> 8); if (r >= 180) { // 0xB4 ?? if (++trigger_cnt > triggersToSkip) - break; - } - } - } + break; + } + } + } - if (!BUTTON_PRESS()) { - int waitcount = samplesToSkip; // lets wait 40000 ticks of pck0 - while(waitcount != 0) { + if (!BUTTON_PRESS()) { + int waitcount = samplesToSkip; // lets wait 40000 ticks of pck0 + while(waitcount != 0) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) - waitcount--; - } - optimizedSnoop(); - Dbprintf("Trigger kicked! Value: %d, Dumping Samples Hispeed now.", r); - } + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) + waitcount--; + } + optimizedSnoop(); + Dbprintf("Trigger kicked! Value: %d, Dumping Samples Hispeed now.", r); + } - //Resetting Frame mode (First set in fpgaloader.c) - AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); + //Resetting Frame mode (First set in fpgaloader.c) + AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(8) | AT91C_SSC_MSBF | SSC_FRAME_MODE_WORDS_PER_TRANSFER(0); - DbpString("HF Snoop end"); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LED_D_OFF(); + DbpString("HF Snoop end"); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); } diff --git a/armsrc/hitag2.c b/armsrc/hitag2.c index 32db10190..913ea92ab 100644 --- a/armsrc/hitag2.c +++ b/armsrc/hitag2.c @@ -30,17 +30,17 @@ static bool bPwd; static bool bSuccessful; struct hitag2_tag { - uint32_t uid; - enum { - TAG_STATE_RESET = 0x01, // Just powered up, awaiting GetSnr - TAG_STATE_ACTIVATING = 0x02 , // In activation phase (password mode), sent UID, awaiting reader password - TAG_STATE_ACTIVATED = 0x03, // Activation complete, awaiting read/write commands - TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written - } state; - unsigned int active_sector; - uint8_t crypto_active; - uint64_t cs; - uint8_t sectors[12][4]; + uint32_t uid; + enum { + TAG_STATE_RESET = 0x01, // Just powered up, awaiting GetSnr + TAG_STATE_ACTIVATING = 0x02 , // In activation phase (password mode), sent UID, awaiting reader password + TAG_STATE_ACTIVATED = 0x03, // Activation complete, awaiting read/write commands + TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written + } state; + unsigned int active_sector; + uint8_t crypto_active; + uint64_t cs; + uint8_t sectors[12][4]; }; static struct hitag2_tag tag = { @@ -62,9 +62,9 @@ static struct hitag2_tag tag = { }; static enum { - WRITE_STATE_START = 0x0, - WRITE_STATE_PAGENUM_WRITTEN, - WRITE_STATE_PROG + WRITE_STATE_START = 0x0, + WRITE_STATE_PAGENUM_WRITTEN, + WRITE_STATE_PROG } writestate; @@ -89,63 +89,63 @@ static uint64_t cipher_state; // Basic macros: -#define u8 uint8_t -#define u32 uint32_t -#define u64 uint64_t -#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7)) -#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8)) -#define rev32(x) (rev16(x)+(rev16(x>>16)<<16)) -#define rev64(x) (rev32(x)+(rev32(x>>32)<<32)) -#define bit(x,n) (((x)>>(n))&1) -#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1) -#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31)) -#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63))) +#define u8 uint8_t +#define u32 uint32_t +#define u64 uint64_t +#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7)) +#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8)) +#define rev32(x) (rev16(x)+(rev16(x>>16)<<16)) +#define rev64(x) (rev32(x)+(rev32(x>>32)<<32)) +#define bit(x,n) (((x)>>(n))&1) +#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1) +#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31)) +#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63))) // Single bit Hitag2 functions: -#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8)) +#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8)) -static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001 -static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001 -static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 +static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001 +static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001 +static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 static u32 _f20 (const u64 x) { - u32 i5; + u32 i5; - i5 = ((ht2_f4a >> i4 (x, 1, 2, 4, 5)) & 1)* 1 - + ((ht2_f4b >> i4 (x, 7,11,13,14)) & 1)* 2 - + ((ht2_f4b >> i4 (x,16,20,22,25)) & 1)* 4 - + ((ht2_f4b >> i4 (x,27,28,30,32)) & 1)* 8 - + ((ht2_f4a >> i4 (x,33,42,43,45)) & 1)*16; + i5 = ((ht2_f4a >> i4 (x, 1, 2, 4, 5)) & 1)* 1 + + ((ht2_f4b >> i4 (x, 7,11,13,14)) & 1)* 2 + + ((ht2_f4b >> i4 (x,16,20,22,25)) & 1)* 4 + + ((ht2_f4b >> i4 (x,27,28,30,32)) & 1)* 8 + + ((ht2_f4a >> i4 (x,33,42,43,45)) & 1)*16; - return (ht2_f5c >> i5) & 1; + return (ht2_f5c >> i5) & 1; } static u64 _hitag2_init (const u64 key, const u32 serial, const u32 IV) { - u32 i; - u64 x = ((key & 0xFFFF) << 32) + serial; + u32 i; + u64 x = ((key & 0xFFFF) << 32) + serial; - for (i = 0; i < 32; i++) - { - x >>= 1; - x += (u64) (_f20 (x) ^ (((IV >> i) ^ (key >> (i+16))) & 1)) << 47; - } - return x; + for (i = 0; i < 32; i++) + { + x >>= 1; + x += (u64) (_f20 (x) ^ (((IV >> i) ^ (key >> (i+16))) & 1)) << 47; + } + return x; } static u64 _hitag2_round (u64 *state) { - u64 x = *state; + u64 x = *state; - x = (x >> 1) + - ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) - ^ (x >> 7) ^ (x >> 8) ^ (x >> 16) ^ (x >> 22) - ^ (x >> 23) ^ (x >> 26) ^ (x >> 30) ^ (x >> 41) - ^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) & 1) << 47); + x = (x >> 1) + + ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) + ^ (x >> 7) ^ (x >> 8) ^ (x >> 16) ^ (x >> 22) + ^ (x >> 23) ^ (x >> 26) ^ (x >> 30) ^ (x >> 41) + ^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) & 1) << 47); - *state = x; - return _f20 (x); + *state = x; + return _f20 (x); } // "MIKRON" = O N M I K R @@ -160,426 +160,426 @@ static u64 _hitag2_round (u64 *state) static u32 _hitag2_byte (u64 * x) { - u32 i, c; + u32 i, c; - for (i = 0, c = 0; i < 8; i++) c += (u32) _hitag2_round (x) << (i^7); - return c; + for (i = 0, c = 0; i < 8; i++) c += (u32) _hitag2_round (x) << (i^7); + return c; } static int hitag2_reset(void) { - tag.state = TAG_STATE_RESET; - tag.crypto_active = 0; - return 0; + tag.state = TAG_STATE_RESET; + tag.crypto_active = 0; + return 0; } static int hitag2_init(void) { - hitag2_reset(); - return 0; + hitag2_reset(); + return 0; } static void hitag2_cipher_reset(struct hitag2_tag *tag, const uint8_t *iv) { - uint64_t key = ((uint64_t)tag->sectors[2][2]) | + uint64_t key = ((uint64_t)tag->sectors[2][2]) | ((uint64_t)tag->sectors[2][3] << 8) | ((uint64_t)tag->sectors[1][0] << 16) | ((uint64_t)tag->sectors[1][1] << 24) | ((uint64_t)tag->sectors[1][2] << 32) | ((uint64_t)tag->sectors[1][3] << 40); - uint32_t uid = ((uint32_t)tag->sectors[0][0]) | + uint32_t uid = ((uint32_t)tag->sectors[0][0]) | ((uint32_t)tag->sectors[0][1] << 8) | ((uint32_t)tag->sectors[0][2] << 16) | ((uint32_t)tag->sectors[0][3] << 24); - uint32_t iv_ = (((uint32_t)(iv[0]))) | - (((uint32_t)(iv[1])) << 8) | - (((uint32_t)(iv[2])) << 16) | - (((uint32_t)(iv[3])) << 24); - tag->cs = _hitag2_init(rev64(key), rev32(uid), rev32(iv_)); + uint32_t iv_ = (((uint32_t)(iv[0]))) | + (((uint32_t)(iv[1])) << 8) | + (((uint32_t)(iv[2])) << 16) | + (((uint32_t)(iv[3])) << 24); + tag->cs = _hitag2_init(rev64(key), rev32(uid), rev32(iv_)); } static int hitag2_cipher_authenticate(uint64_t* cs, const uint8_t *authenticator_is) { - uint8_t authenticator_should[4]; - authenticator_should[0] = ~_hitag2_byte(cs); - authenticator_should[1] = ~_hitag2_byte(cs); - authenticator_should[2] = ~_hitag2_byte(cs); - authenticator_should[3] = ~_hitag2_byte(cs); - return (memcmp(authenticator_should, authenticator_is, 4) == 0); + uint8_t authenticator_should[4]; + authenticator_should[0] = ~_hitag2_byte(cs); + authenticator_should[1] = ~_hitag2_byte(cs); + authenticator_should[2] = ~_hitag2_byte(cs); + authenticator_should[3] = ~_hitag2_byte(cs); + return (memcmp(authenticator_should, authenticator_is, 4) == 0); } static int hitag2_cipher_transcrypt(uint64_t* cs, uint8_t *data, unsigned int bytes, unsigned int bits) { - int i; - for(i=0; i 36 */ -#define HITAG_T_LOW 8 /* T_LOW should be 4..10 */ -#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */ -#define HITAG_T_1_MIN 25 /* T[1] should be 26..30 */ -//#define HITAG_T_EOF 40 /* T_EOF should be > 36 */ -#define HITAG_T_EOF 80 /* T_EOF should be > 36 */ -#define HITAG_T_WAIT_1 200 /* T_wresp should be 199..206 */ -#define HITAG_T_WAIT_2 90 /* T_wresp should be 199..206 */ +#define HITAG_FRAME_LEN 20 +#define HITAG_T_STOP 36 /* T_EOF should be > 36 */ +#define HITAG_T_LOW 8 /* T_LOW should be 4..10 */ +#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */ +#define HITAG_T_1_MIN 25 /* T[1] should be 26..30 */ +//#define HITAG_T_EOF 40 /* T_EOF should be > 36 */ +#define HITAG_T_EOF 80 /* T_EOF should be > 36 */ +#define HITAG_T_WAIT_1 200 /* T_wresp should be 199..206 */ +#define HITAG_T_WAIT_2 90 /* T_wresp should be 199..206 */ #define HITAG_T_WAIT_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */ -#define HITAG_T_PROG 614 +#define HITAG_T_PROG 614 -#define HITAG_T_TAG_ONE_HALF_PERIOD 10 -#define HITAG_T_TAG_TWO_HALF_PERIOD 25 -#define HITAG_T_TAG_THREE_HALF_PERIOD 41 -#define HITAG_T_TAG_FOUR_HALF_PERIOD 57 +#define HITAG_T_TAG_ONE_HALF_PERIOD 10 +#define HITAG_T_TAG_TWO_HALF_PERIOD 25 +#define HITAG_T_TAG_THREE_HALF_PERIOD 41 +#define HITAG_T_TAG_FOUR_HALF_PERIOD 57 -#define HITAG_T_TAG_HALF_PERIOD 16 -#define HITAG_T_TAG_FULL_PERIOD 32 +#define HITAG_T_TAG_HALF_PERIOD 16 +#define HITAG_T_TAG_FULL_PERIOD 32 -#define HITAG_T_TAG_CAPTURE_ONE_HALF 13 -#define HITAG_T_TAG_CAPTURE_TWO_HALF 25 -#define HITAG_T_TAG_CAPTURE_THREE_HALF 41 +#define HITAG_T_TAG_CAPTURE_ONE_HALF 13 +#define HITAG_T_TAG_CAPTURE_TWO_HALF 25 +#define HITAG_T_TAG_CAPTURE_THREE_HALF 41 #define HITAG_T_TAG_CAPTURE_FOUR_HALF 57 static void hitag_send_bit(int bit) { - LED_A_ON(); - // Reset clock for the next bit - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + LED_A_ON(); + // Reset clock for the next bit + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - // Fixed modulation, earlier proxmark version used inverted signal - if(bit == 0) { - // Manchester: Unloaded, then loaded |__--| - LOW(GPIO_SSC_DOUT); - while(AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_HALF_PERIOD); - HIGH(GPIO_SSC_DOUT); - while(AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_FULL_PERIOD); - } else { - // Manchester: Loaded, then unloaded |--__| - HIGH(GPIO_SSC_DOUT); - while(AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_HALF_PERIOD); - LOW(GPIO_SSC_DOUT); - while(AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_FULL_PERIOD); - } - LED_A_OFF(); + // Fixed modulation, earlier proxmark version used inverted signal + if(bit == 0) { + // Manchester: Unloaded, then loaded |__--| + LOW(GPIO_SSC_DOUT); + while(AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_HALF_PERIOD); + HIGH(GPIO_SSC_DOUT); + while(AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_FULL_PERIOD); + } else { + // Manchester: Loaded, then unloaded |--__| + HIGH(GPIO_SSC_DOUT); + while(AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_HALF_PERIOD); + LOW(GPIO_SSC_DOUT); + while(AT91C_BASE_TC0->TC_CV < T0*HITAG_T_TAG_FULL_PERIOD); + } + LED_A_OFF(); } static void hitag_send_frame(const uint8_t* frame, size_t frame_len) { - // Send start of frame - for(size_t i=0; i<5; i++) { - hitag_send_bit(1); - } + // Send start of frame + for(size_t i=0; i<5; i++) { + hitag_send_bit(1); + } - // Send the content of the frame - for(size_t i=0; i> (7-(i%8)))&1); - } + // Send the content of the frame + for(size_t i=0; i> (7-(i%8)))&1); + } - // Drop the modulation - LOW(GPIO_SSC_DOUT); + // Drop the modulation + LOW(GPIO_SSC_DOUT); } static void hitag2_handle_reader_command(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen) { - uint8_t rx_air[HITAG_FRAME_LEN]; + uint8_t rx_air[HITAG_FRAME_LEN]; - // Copy the (original) received frame how it is send over the air - memcpy(rx_air,rx,nbytes(rxlen)); + // Copy the (original) received frame how it is send over the air + memcpy(rx_air,rx,nbytes(rxlen)); - if(tag.crypto_active) { - hitag2_cipher_transcrypt(&(tag.cs),rx,rxlen/8,rxlen%8); - } + if(tag.crypto_active) { + hitag2_cipher_transcrypt(&(tag.cs),rx,rxlen/8,rxlen%8); + } - // Reset the transmission frame length - *txlen = 0; + // Reset the transmission frame length + *txlen = 0; - // Try to find out which command was send by selecting on length (in bits) - switch (rxlen) { - // Received 11000 from the reader, request for UID, send UID - case 05: { - // Always send over the air in the clear plaintext mode - if(rx_air[0] != 0xC0) { - // Unknown frame ? - return; - } - *txlen = 32; - memcpy(tx,tag.sectors[0],4); - tag.crypto_active = 0; - } - break; + // Try to find out which command was send by selecting on length (in bits) + switch (rxlen) { + // Received 11000 from the reader, request for UID, send UID + case 05: { + // Always send over the air in the clear plaintext mode + if(rx_air[0] != 0xC0) { + // Unknown frame ? + return; + } + *txlen = 32; + memcpy(tx,tag.sectors[0],4); + tag.crypto_active = 0; + } + break; - // Read/Write command: ..xx x..y yy with yyy == ~xxx, xxx is sector number - case 10: { - unsigned int sector = (~( ((rx[0]<<2)&0x04) | ((rx[1]>>6)&0x03) ) & 0x07); - // Verify complement of sector index - if(sector != ((rx[0]>>3)&0x07)) { - //DbpString("Transmission error (read/write)"); - return; - } + // Read/Write command: ..xx x..y yy with yyy == ~xxx, xxx is sector number + case 10: { + unsigned int sector = (~( ((rx[0]<<2)&0x04) | ((rx[1]>>6)&0x03) ) & 0x07); + // Verify complement of sector index + if(sector != ((rx[0]>>3)&0x07)) { + //DbpString("Transmission error (read/write)"); + return; + } - switch (rx[0] & 0xC6) { - // Read command: 11xx x00y - case 0xC0: - memcpy(tx,tag.sectors[sector],4); - *txlen = 32; - break; + switch (rx[0] & 0xC6) { + // Read command: 11xx x00y + case 0xC0: + memcpy(tx,tag.sectors[sector],4); + *txlen = 32; + break; - // Inverted Read command: 01xx x10y - case 0x44: - for (size_t i=0; i<4; i++) { - tx[i] = tag.sectors[sector][i] ^ 0xff; - } - *txlen = 32; - break; + // Inverted Read command: 01xx x10y + case 0x44: + for (size_t i=0; i<4; i++) { + tx[i] = tag.sectors[sector][i] ^ 0xff; + } + *txlen = 32; + break; - // Write command: 10xx x01y - case 0x82: - // Prepare write, acknowledge by repeating command - memcpy(tx,rx,nbytes(rxlen)); - *txlen = rxlen; - tag.active_sector = sector; - tag.state=TAG_STATE_WRITING; - break; + // Write command: 10xx x01y + case 0x82: + // Prepare write, acknowledge by repeating command + memcpy(tx,rx,nbytes(rxlen)); + *txlen = rxlen; + tag.active_sector = sector; + tag.state=TAG_STATE_WRITING; + break; - // Unknown command - default: - Dbprintf("Unknown command: %02x %02x",rx[0],rx[1]); - return; - break; - } - } - break; + // Unknown command + default: + Dbprintf("Unknown command: %02x %02x",rx[0],rx[1]); + return; + break; + } + } + break; - // Writing data or Reader password - case 32: { - if(tag.state == TAG_STATE_WRITING) { - // These are the sector contents to be written. We don't have to do anything else. - memcpy(tag.sectors[tag.active_sector],rx,nbytes(rxlen)); - tag.state=TAG_STATE_RESET; - return; - } else { - // Received RWD password, respond with configuration and our password - if(memcmp(rx,tag.sectors[1],4) != 0) { - DbpString("Reader password is wrong"); - return; - } - *txlen = 32; - memcpy(tx,tag.sectors[3],4); - } - } - break; + // Writing data or Reader password + case 32: { + if(tag.state == TAG_STATE_WRITING) { + // These are the sector contents to be written. We don't have to do anything else. + memcpy(tag.sectors[tag.active_sector],rx,nbytes(rxlen)); + tag.state=TAG_STATE_RESET; + return; + } else { + // Received RWD password, respond with configuration and our password + if(memcmp(rx,tag.sectors[1],4) != 0) { + DbpString("Reader password is wrong"); + return; + } + *txlen = 32; + memcpy(tx,tag.sectors[3],4); + } + } + break; - // Received RWD authentication challenge and respnse - case 64: { - // Store the authentication attempt - if (auth_table_len < (AUTH_TABLE_LENGTH-8)) { - memcpy(auth_table+auth_table_len,rx,8); - auth_table_len += 8; - } + // Received RWD authentication challenge and respnse + case 64: { + // Store the authentication attempt + if (auth_table_len < (AUTH_TABLE_LENGTH-8)) { + memcpy(auth_table+auth_table_len,rx,8); + auth_table_len += 8; + } - // Reset the cipher state - hitag2_cipher_reset(&tag,rx); - // Check if the authentication was correct - if(!hitag2_cipher_authenticate(&(tag.cs),rx+4)) { - // The reader failed to authenticate, do nothing - Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed!",rx[0],rx[1],rx[2],rx[3],rx[4],rx[5],rx[6],rx[7]); - return; - } - // Succesful, but commented out reporting back to the Host, this may delay to much. - // Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x OK!",rx[0],rx[1],rx[2],rx[3],rx[4],rx[5],rx[6],rx[7]); + // Reset the cipher state + hitag2_cipher_reset(&tag,rx); + // Check if the authentication was correct + if(!hitag2_cipher_authenticate(&(tag.cs),rx+4)) { + // The reader failed to authenticate, do nothing + Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed!",rx[0],rx[1],rx[2],rx[3],rx[4],rx[5],rx[6],rx[7]); + return; + } + // Succesful, but commented out reporting back to the Host, this may delay to much. + // Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x OK!",rx[0],rx[1],rx[2],rx[3],rx[4],rx[5],rx[6],rx[7]); - // Activate encryption algorithm for all further communication - tag.crypto_active = 1; + // Activate encryption algorithm for all further communication + tag.crypto_active = 1; - // Use the tag password as response - memcpy(tx,tag.sectors[3],4); - *txlen = 32; - } - break; - } + // Use the tag password as response + memcpy(tx,tag.sectors[3],4); + *txlen = 32; + } + break; + } -// LogTraceHitag(rx,rxlen,0,0,false); -// LogTraceHitag(tx,*txlen,0,0,true); +// LogTraceHitag(rx,rxlen,0,0,false); +// LogTraceHitag(tx,*txlen,0,0,true); - if(tag.crypto_active) { - hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen/8, *txlen%8); - } + if(tag.crypto_active) { + hitag2_cipher_transcrypt(&(tag.cs), tx, *txlen/8, *txlen%8); + } } static void hitag_reader_send_bit(int bit) { - LED_A_ON(); - // Reset clock for the next bit - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + LED_A_ON(); + // Reset clock for the next bit + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - // Binary puls length modulation (BPLM) is used to encode the data stream - // This means that a transmission of a one takes longer than that of a zero + // Binary puls length modulation (BPLM) is used to encode the data stream + // This means that a transmission of a one takes longer than that of a zero - // Enable modulation, which means, drop the field - HIGH(GPIO_SSC_DOUT); + // Enable modulation, which means, drop the field + HIGH(GPIO_SSC_DOUT); - // Wait for 4-10 times the carrier period - while(AT91C_BASE_TC0->TC_CV < T0*6); - // SpinDelayUs(8*8); + // Wait for 4-10 times the carrier period + while(AT91C_BASE_TC0->TC_CV < T0*6); + // SpinDelayUs(8*8); - // Disable modulation, just activates the field again - LOW(GPIO_SSC_DOUT); + // Disable modulation, just activates the field again + LOW(GPIO_SSC_DOUT); - if(bit == 0) { - // Zero bit: |_-| - while (AT91C_BASE_TC0->TC_CV < T0*22) {}; + if(bit == 0) { + // Zero bit: |_-| + while (AT91C_BASE_TC0->TC_CV < T0*22) {}; - } else { - // One bit: |_--| - while (AT91C_BASE_TC0->TC_CV < T0*28) {}; - } - LED_A_OFF(); + } else { + // One bit: |_--| + while (AT91C_BASE_TC0->TC_CV < T0*28) {}; + } + LED_A_OFF(); } static void hitag_reader_send_frame(const uint8_t* frame, size_t frame_len) { - // Send the content of the frame - for(size_t i=0; i> (7-(i%8)))&1); - } - // Send EOF - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - // Enable modulation, which means, drop the field - HIGH(GPIO_SSC_DOUT); - // Wait for 4-10 times the carrier period - while(AT91C_BASE_TC0->TC_CV < T0*6); - // Disable modulation, just activates the field again - LOW(GPIO_SSC_DOUT); + // Send the content of the frame + for(size_t i=0; i> (7-(i%8)))&1); + } + // Send EOF + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + // Enable modulation, which means, drop the field + HIGH(GPIO_SSC_DOUT); + // Wait for 4-10 times the carrier period + while(AT91C_BASE_TC0->TC_CV < T0*6); + // Disable modulation, just activates the field again + LOW(GPIO_SSC_DOUT); } size_t blocknr; static bool hitag2_password(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen) { - // Reset the transmission frame length - *txlen = 0; + // Reset the transmission frame length + *txlen = 0; - // Try to find out which command was send by selecting on length (in bits) - switch (rxlen) { - // No answer, try to resurrect - case 0: { - // Stop if there is no answer (after sending password) - if (bPwd) { - DbpString("Password failed!"); - return false; - } - *txlen = 5; - memcpy(tx,"\xc0",nbytes(*txlen)); - } break; + // Try to find out which command was send by selecting on length (in bits) + switch (rxlen) { + // No answer, try to resurrect + case 0: { + // Stop if there is no answer (after sending password) + if (bPwd) { + DbpString("Password failed!"); + return false; + } + *txlen = 5; + memcpy(tx,"\xc0",nbytes(*txlen)); + } break; - // Received UID, tag password - case 32: { - if (!bPwd) { - *txlen = 32; - memcpy(tx,password,4); - bPwd = true; - memcpy(tag.sectors[blocknr],rx,4); - blocknr++; - } else { + // Received UID, tag password + case 32: { + if (!bPwd) { + *txlen = 32; + memcpy(tx,password,4); + bPwd = true; + memcpy(tag.sectors[blocknr],rx,4); + blocknr++; + } else { - if(blocknr == 1){ - //store password in block1, the TAG answers with Block3, but we need the password in memory - memcpy(tag.sectors[blocknr],tx,4); - } else { - memcpy(tag.sectors[blocknr],rx,4); - } + if(blocknr == 1){ + //store password in block1, the TAG answers with Block3, but we need the password in memory + memcpy(tag.sectors[blocknr],tx,4); + } else { + memcpy(tag.sectors[blocknr],rx,4); + } - blocknr++; - if (blocknr > 7) { - DbpString("Read succesful!"); - bSuccessful = true; - return false; - } - *txlen = 10; - tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2); - tx[1] = ((blocknr^7) << 6); - } - } break; + blocknr++; + if (blocknr > 7) { + DbpString("Read succesful!"); + bSuccessful = true; + return false; + } + *txlen = 10; + tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2); + tx[1] = ((blocknr^7) << 6); + } + } break; - // Unexpected response + // Unexpected response default: { - Dbprintf("Uknown frame length: %d",rxlen); - return false; - } break; - } - return true; + Dbprintf("Uknown frame length: %d",rxlen); + return false; + } break; + } + return true; } static bool hitag2_write_page(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen) { - switch (writestate) { - case WRITE_STATE_START: - *txlen = 10; - tx[0] = 0x82 | (blocknr << 3) | ((blocknr^7) >> 2); - tx[1] = ((blocknr^7) << 6); - writestate = WRITE_STATE_PAGENUM_WRITTEN; - break; - case WRITE_STATE_PAGENUM_WRITTEN: - // Check if page number was received correctly - if ((rxlen == 10) && - (rx[0] == (0x82 | (blocknr << 3) | ((blocknr^7) >> 2))) && - (rx[1] == (((blocknr & 0x3) ^ 0x3) << 6))) { - *txlen = 32; - memset(tx, 0, HITAG_FRAME_LEN); - memcpy(tx, writedata, 4); - writestate = WRITE_STATE_PROG; - } else { - Dbprintf("hitag2_write_page: Page number was not received correctly: rxlen=%d rx=%02x%02x%02x%02x", - rxlen, rx[0], rx[1], rx[2], rx[3]); - bSuccessful = false; - return false; - } - break; - case WRITE_STATE_PROG: - if (rxlen == 0) { - bSuccessful = true; - } else { - bSuccessful = false; - Dbprintf("hitag2_write_page: unexpected rx data (%d) after page write", rxlen); - } - return false; - default: - DbpString("hitag2_write_page: Unknown state %d"); - bSuccessful = false; - return false; - } + switch (writestate) { + case WRITE_STATE_START: + *txlen = 10; + tx[0] = 0x82 | (blocknr << 3) | ((blocknr^7) >> 2); + tx[1] = ((blocknr^7) << 6); + writestate = WRITE_STATE_PAGENUM_WRITTEN; + break; + case WRITE_STATE_PAGENUM_WRITTEN: + // Check if page number was received correctly + if ((rxlen == 10) && + (rx[0] == (0x82 | (blocknr << 3) | ((blocknr^7) >> 2))) && + (rx[1] == (((blocknr & 0x3) ^ 0x3) << 6))) { + *txlen = 32; + memset(tx, 0, HITAG_FRAME_LEN); + memcpy(tx, writedata, 4); + writestate = WRITE_STATE_PROG; + } else { + Dbprintf("hitag2_write_page: Page number was not received correctly: rxlen=%d rx=%02x%02x%02x%02x", + rxlen, rx[0], rx[1], rx[2], rx[3]); + bSuccessful = false; + return false; + } + break; + case WRITE_STATE_PROG: + if (rxlen == 0) { + bSuccessful = true; + } else { + bSuccessful = false; + Dbprintf("hitag2_write_page: unexpected rx data (%d) after page write", rxlen); + } + return false; + default: + DbpString("hitag2_write_page: Unknown state %d"); + bSuccessful = false; + return false; + } - return true; + return true; } static bool hitag2_crypto(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen, bool write) { - // Reset the transmission frame length - *txlen = 0; + // Reset the transmission frame length + *txlen = 0; if(bCrypto) { - hitag2_cipher_transcrypt(&cipher_state,rx,rxlen/8,rxlen%8); - } + hitag2_cipher_transcrypt(&cipher_state,rx,rxlen/8,rxlen%8); + } - if (bCrypto && !bAuthenticating && write) { - if (!hitag2_write_page(rx, rxlen, tx, txlen)) { - return false; - } - } else { + if (bCrypto && !bAuthenticating && write) { + if (!hitag2_write_page(rx, rxlen, tx, txlen)) { + return false; + } + } else { - // Try to find out which command was send by selecting on length (in bits) - switch (rxlen) { + // Try to find out which command was send by selecting on length (in bits) + switch (rxlen) { // No answer, try to resurrect - case 0: { - // Stop if there is no answer while we are in crypto mode (after sending NrAr) - if (bCrypto) { + case 0: { + // Stop if there is no answer while we are in crypto mode (after sending NrAr) + if (bCrypto) { // Failed during authentication if (bAuthenticating) { DbpString("Authentication failed!"); @@ -602,1190 +602,1190 @@ static bool hitag2_crypto(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* blocknr++; bCrypto = false; } - } else { - *txlen = 5; - memcpy(tx,"\xc0",nbytes(*txlen)); - } - break; - } + } else { + *txlen = 5; + memcpy(tx,"\xc0",nbytes(*txlen)); + } + break; + } // Received UID, crypto tag answer - case 32: { - if (!bCrypto) { + case 32: { + if (!bCrypto) { uint64_t ui64key = key[0] | ((uint64_t)key[1]) << 8 | ((uint64_t)key[2]) << 16 | ((uint64_t)key[3]) << 24 | ((uint64_t)key[4]) << 32 | ((uint64_t)key[5]) << 40; uint32_t ui32uid = rx[0] | ((uint32_t)rx[1]) << 8 | ((uint32_t)rx[2]) << 16 | ((uint32_t)rx[3]) << 24; - Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x", (uint32_t) ((rev64(ui64key)) >> 32), (uint32_t) ((rev64(ui64key)) & 0xffffffff), rev32(ui32uid)); + Dbprintf("hitag2_crypto: key=0x%x%x uid=0x%x", (uint32_t) ((rev64(ui64key)) >> 32), (uint32_t) ((rev64(ui64key)) & 0xffffffff), rev32(ui32uid)); cipher_state = _hitag2_init(rev64(ui64key), rev32(ui32uid), 0); memset(tx,0x00,4); memset(tx+4,0xff,4); hitag2_cipher_transcrypt(&cipher_state,tx+4,4,0); - *txlen = 64; - bCrypto = true; - bAuthenticating = true; - } else { + *txlen = 64; + bCrypto = true; + bAuthenticating = true; + } else { // Check if we received answer tag (at) if (bAuthenticating) { - bAuthenticating = false; - if (write) { - if (!hitag2_write_page(rx, rxlen, tx, txlen)) { - return false; - } - break; - } + bAuthenticating = false; + if (write) { + if (!hitag2_write_page(rx, rxlen, tx, txlen)) { + return false; + } + break; + } } else { - // Store the received block - memcpy(tag.sectors[blocknr],rx,4); - blocknr++; + // Store the received block + memcpy(tag.sectors[blocknr],rx,4); + blocknr++; } if (blocknr > 7) { - DbpString("Read succesful!"); - bSuccessful = true; - return false; - } else { + DbpString("Read succesful!"); + bSuccessful = true; + return false; + } else { *txlen = 10; tx[0] = 0xc0 | (blocknr << 3) | ((blocknr^7) >> 2); tx[1] = ((blocknr^7) << 6); - } - } - } break; + } + } + } break; // Unexpected response - default: { - Dbprintf("Uknown frame length: %d",rxlen); - return false; - } break; - } - } + default: { + Dbprintf("Uknown frame length: %d",rxlen); + return false; + } break; + } + } - if(bCrypto) { - // We have to return now to avoid double encryption - if (!bAuthenticating) { - hitag2_cipher_transcrypt(&cipher_state, tx, *txlen/8, *txlen%8); - } - } + if(bCrypto) { + // We have to return now to avoid double encryption + if (!bAuthenticating) { + hitag2_cipher_transcrypt(&cipher_state, tx, *txlen/8, *txlen%8); + } + } - return true; + return true; } static bool hitag2_authenticate(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen) { - // Reset the transmission frame length - *txlen = 0; + // Reset the transmission frame length + *txlen = 0; - // Try to find out which command was send by selecting on length (in bits) - switch (rxlen) { - // No answer, try to resurrect - case 0: { - // Stop if there is no answer while we are in crypto mode (after sending NrAr) - if (bCrypto) { - DbpString("Authentication failed!"); - return false; - } - *txlen = 5; - memcpy(tx,"\xc0", nbytes(*txlen)); - } break; + // Try to find out which command was send by selecting on length (in bits) + switch (rxlen) { + // No answer, try to resurrect + case 0: { + // Stop if there is no answer while we are in crypto mode (after sending NrAr) + if (bCrypto) { + DbpString("Authentication failed!"); + return false; + } + *txlen = 5; + memcpy(tx,"\xc0", nbytes(*txlen)); + } break; - // Received UID, crypto tag answer - case 32: { - if (!bCrypto) { - *txlen = 64; - memcpy(tx, NrAr, 8); - bCrypto = true; - } else { - DbpString("Authentication succesful!"); - return true; - } - } break; + // Received UID, crypto tag answer + case 32: { + if (!bCrypto) { + *txlen = 64; + memcpy(tx, NrAr, 8); + bCrypto = true; + } else { + DbpString("Authentication succesful!"); + return true; + } + } break; - // Unexpected response - default: { - Dbprintf("Uknown frame length: %d", rxlen); - return false; - } break; - } + // Unexpected response + default: { + Dbprintf("Uknown frame length: %d", rxlen); + return false; + } break; + } - return true; + return true; } static bool hitag2_test_auth_attempts(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen) { - // Reset the transmission frame length - *txlen = 0; + // Reset the transmission frame length + *txlen = 0; - // Try to find out which command was send by selecting on length (in bits) - switch (rxlen) { - // No answer, try to resurrect - case 0: { - // Stop if there is no answer while we are in crypto mode (after sending NrAr) - if (bCrypto) { - Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed, removed entry!",NrAr[0],NrAr[1],NrAr[2],NrAr[3],NrAr[4],NrAr[5],NrAr[6],NrAr[7]); + // Try to find out which command was send by selecting on length (in bits) + switch (rxlen) { + // No answer, try to resurrect + case 0: { + // Stop if there is no answer while we are in crypto mode (after sending NrAr) + if (bCrypto) { + Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x Failed, removed entry!",NrAr[0],NrAr[1],NrAr[2],NrAr[3],NrAr[4],NrAr[5],NrAr[6],NrAr[7]); - // Removing failed entry from authentiations table - memcpy(auth_table+auth_table_pos,auth_table+auth_table_pos+8,8); - auth_table_len -= 8; + // Removing failed entry from authentiations table + memcpy(auth_table+auth_table_pos,auth_table+auth_table_pos+8,8); + auth_table_len -= 8; - // Return if we reached the end of the authentications table - bCrypto = false; - if (auth_table_pos == auth_table_len) { - return false; - } + // Return if we reached the end of the authentications table + bCrypto = false; + if (auth_table_pos == auth_table_len) { + return false; + } - // Copy the next authentication attempt in row (at the same position, b/c we removed last failed entry) - memcpy(NrAr,auth_table+auth_table_pos,8); - } - *txlen = 5; - memcpy(tx,"\xc0",nbytes(*txlen)); - } break; + // Copy the next authentication attempt in row (at the same position, b/c we removed last failed entry) + memcpy(NrAr,auth_table+auth_table_pos,8); + } + *txlen = 5; + memcpy(tx,"\xc0",nbytes(*txlen)); + } break; - // Received UID, crypto tag answer, or read block response - case 32: { - if (!bCrypto) { - *txlen = 64; - memcpy(tx,NrAr,8); - bCrypto = true; - } else { - Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x OK",NrAr[0],NrAr[1],NrAr[2],NrAr[3],NrAr[4],NrAr[5],NrAr[6],NrAr[7]); - bCrypto = false; - if ((auth_table_pos+8) == auth_table_len) { - return false; - } - auth_table_pos += 8; - memcpy(NrAr,auth_table+auth_table_pos,8); - } - } break; + // Received UID, crypto tag answer, or read block response + case 32: { + if (!bCrypto) { + *txlen = 64; + memcpy(tx,NrAr,8); + bCrypto = true; + } else { + Dbprintf("auth: %02x%02x%02x%02x%02x%02x%02x%02x OK",NrAr[0],NrAr[1],NrAr[2],NrAr[3],NrAr[4],NrAr[5],NrAr[6],NrAr[7]); + bCrypto = false; + if ((auth_table_pos+8) == auth_table_len) { + return false; + } + auth_table_pos += 8; + memcpy(NrAr,auth_table+auth_table_pos,8); + } + } break; - default: { - Dbprintf("Uknown frame length: %d",rxlen); - return false; - } break; - } + default: { + Dbprintf("Uknown frame length: %d",rxlen); + return false; + } break; + } - return true; + return true; } static bool hitag2_read_uid(uint8_t* rx, const size_t rxlen, uint8_t* tx, size_t* txlen) { - // Reset the transmission frame length - *txlen = 0; + // Reset the transmission frame length + *txlen = 0; - // Try to find out which command was send by selecting on length (in bits) - switch (rxlen) { - // No answer, try to resurrect - case 0: { - // Just starting or if there is no answer - *txlen = 5; - memcpy(tx, "\xC0", nbytes(*txlen) ); - } break; - // Received UID - case 32: { - // Check if we received answer tag (at) - if (bAuthenticating) { - bAuthenticating = false; - } else { - // Store the received block - memcpy(tag.sectors[blocknr], rx, 4); - blocknr++; - } - if (blocknr > 0) { - // DbpString("Read successful!"); - bSuccessful = true; - return false; - } - } break; - // Unexpected response - default: { - Dbprintf("Uknown frame length: %d", rxlen); - return false; - } break; - } - return true; + // Try to find out which command was send by selecting on length (in bits) + switch (rxlen) { + // No answer, try to resurrect + case 0: { + // Just starting or if there is no answer + *txlen = 5; + memcpy(tx, "\xC0", nbytes(*txlen) ); + } break; + // Received UID + case 32: { + // Check if we received answer tag (at) + if (bAuthenticating) { + bAuthenticating = false; + } else { + // Store the received block + memcpy(tag.sectors[blocknr], rx, 4); + blocknr++; + } + if (blocknr > 0) { + // DbpString("Read successful!"); + bSuccessful = true; + return false; + } + } break; + // Unexpected response + default: { + Dbprintf("Uknown frame length: %d", rxlen); + return false; + } break; + } + return true; } void SnoopHitag(uint32_t type) { - int frame_count; - int response; - int overflow; - bool rising_edge; - bool reader_frame; - int lastbit; - bool bSkip; - int tag_sof; - uint8_t rx[HITAG_FRAME_LEN]; - size_t rxlen=0; + int frame_count; + int response; + int overflow; + bool rising_edge; + bool reader_frame; + int lastbit; + bool bSkip; + int tag_sof; + uint8_t rx[HITAG_FRAME_LEN]; + size_t rxlen=0; - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - // free eventually allocated BigBuf memory - BigBuf_free(); BigBuf_Clear_ext(false); + // free eventually allocated BigBuf memory + BigBuf_free(); BigBuf_Clear_ext(false); - // Clean up trace and prepare it for storing frames - clear_trace(); - set_tracing(true); + // Clean up trace and prepare it for storing frames + clear_trace(); + set_tracing(true); - auth_table_len = 0; - auth_table_pos = 0; + auth_table_len = 0; + auth_table_pos = 0; auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); - memset(auth_table, 0x00, AUTH_TABLE_LENGTH); + memset(auth_table, 0x00, AUTH_TABLE_LENGTH); - DbpString("Starting Hitag2 snoop"); - LED_D_ON(); + DbpString("Starting Hitag2 snoop"); + LED_D_ON(); - // Set up eavesdropping mode, frequency divisor which will drive the FPGA - // and analog mux selection. - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); + // Set up eavesdropping mode, frequency divisor which will drive the FPGA + // and analog mux selection. + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); - // Configure output pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + // Configure output pin that is connected to the FPGA (for modulating) + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - // Disable modulation, we are going to eavesdrop, not modulate ;) - LOW(GPIO_SSC_DOUT); + // Disable modulation, we are going to eavesdrop, not modulate ;) + LOW(GPIO_SSC_DOUT); - // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); - AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - // Disable timer during configuration - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + // Disable timer during configuration + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, - // external trigger rising edge, load RA on rising edge of TIOA. - uint32_t t1_channel_mode = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH; - AT91C_BASE_TC1->TC_CMR = t1_channel_mode; + // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // external trigger rising edge, load RA on rising edge of TIOA. + uint32_t t1_channel_mode = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_BOTH | AT91C_TC_ABETRG | AT91C_TC_LDRA_BOTH; + AT91C_BASE_TC1->TC_CMR = t1_channel_mode; - // Enable and reset counter - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Enable and reset counter + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - // Reset the received frame, frame count and timing info - memset(rx, 0x00, sizeof(rx)); - frame_count = 0; - response = 0; - overflow = 0; - reader_frame = false; - lastbit = 1; - bSkip = true; - tag_sof = 4; + // Reset the received frame, frame count and timing info + memset(rx, 0x00, sizeof(rx)); + frame_count = 0; + response = 0; + overflow = 0; + reader_frame = false; + lastbit = 1; + bSkip = true; + tag_sof = 4; - while(!BUTTON_PRESS() && !usb_poll_validate_length()) { - // Watchdog hit - WDT_HIT(); + while(!BUTTON_PRESS() && !usb_poll_validate_length()) { + // Watchdog hit + WDT_HIT(); - // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_EOF) { - // Check if rising edge in modulation is detected - if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values - int ra = (AT91C_BASE_TC1->TC_RA/T0); + // Receive frame, watch for at most T0*EOF periods + while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_EOF) { + // Check if rising edge in modulation is detected + if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { + // Retrieve the new timing values + int ra = (AT91C_BASE_TC1->TC_RA/T0); - // Find out if we are dealing with a rising or falling edge - rising_edge = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME) > 0; + // Find out if we are dealing with a rising or falling edge + rising_edge = (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME) > 0; - // Shorter periods will only happen with reader frames - if (!reader_frame && rising_edge && ra < HITAG_T_TAG_CAPTURE_ONE_HALF) { - // Switch from tag to reader capture - LED_C_OFF(); - reader_frame = true; - memset(rx,0x00,sizeof(rx)); - rxlen = 0; - } + // Shorter periods will only happen with reader frames + if (!reader_frame && rising_edge && ra < HITAG_T_TAG_CAPTURE_ONE_HALF) { + // Switch from tag to reader capture + LED_C_OFF(); + reader_frame = true; + memset(rx,0x00,sizeof(rx)); + rxlen = 0; + } - // Only handle if reader frame and rising edge, or tag frame and falling edge - if (reader_frame != rising_edge) { - overflow += ra; - continue; - } + // Only handle if reader frame and rising edge, or tag frame and falling edge + if (reader_frame != rising_edge) { + overflow += ra; + continue; + } - // Add the buffered timing values of earlier captured edges which were skipped - ra += overflow; - overflow = 0; + // Add the buffered timing values of earlier captured edges which were skipped + ra += overflow; + overflow = 0; - if (reader_frame) { - LED_B_ON(); - // Capture reader frame - if(ra >= HITAG_T_STOP) { - if (rxlen != 0) { - //DbpString("wierd0?"); - } - // Capture the T0 periods that have passed since last communication or field drop (reset) - response = (ra - HITAG_T_LOW); - } else if(ra >= HITAG_T_1_MIN ) { - // '1' bit - rx[rxlen / 8] |= 1 << (7-(rxlen%8)); - rxlen++; - } else if(ra >= HITAG_T_0_MIN) { - // '0' bit - rx[rxlen / 8] |= 0 << (7-(rxlen%8)); - rxlen++; - } else { - // Ignore wierd value, is to small to mean anything - } - } else { - LED_C_ON(); - // Capture tag frame (manchester decoding using only falling edges) - if(ra >= HITAG_T_EOF) { - if (rxlen != 0) { - //DbpString("wierd1?"); - } - // Capture the T0 periods that have passed since last communication or field drop (reset) - // We always recieve a 'one' first, which has the falling edge after a half period |-_| - response = ra-HITAG_T_TAG_HALF_PERIOD; - } else if(ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { - // Manchester coding example |-_|_-|-_| (101) - rx[rxlen / 8] |= 0 << (7-(rxlen%8)); - rxlen++; - rx[rxlen / 8] |= 1 << (7-(rxlen%8)); - rxlen++; - } else if(ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { - // Manchester coding example |_-|...|_-|-_| (0...01) - rx[rxlen / 8] |= 0 << (7-(rxlen%8)); - rxlen++; - // We have to skip this half period at start and add the 'one' the second time - if (!bSkip) { - rx[rxlen / 8] |= 1 << (7-(rxlen%8)); - rxlen++; - } - lastbit = !lastbit; - bSkip = !bSkip; - } else if(ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { - // Manchester coding example |_-|_-| (00) or |-_|-_| (11) - if (tag_sof) { - // Ignore bits that are transmitted during SOF - tag_sof--; - } else { - // bit is same as last bit - rx[rxlen / 8] |= lastbit << (7-(rxlen%8)); - rxlen++; - } - } else { - // Ignore wierd value, is to small to mean anything - } - } - } - } + if (reader_frame) { + LED_B_ON(); + // Capture reader frame + if(ra >= HITAG_T_STOP) { + if (rxlen != 0) { + //DbpString("wierd0?"); + } + // Capture the T0 periods that have passed since last communication or field drop (reset) + response = (ra - HITAG_T_LOW); + } else if(ra >= HITAG_T_1_MIN ) { + // '1' bit + rx[rxlen / 8] |= 1 << (7-(rxlen%8)); + rxlen++; + } else if(ra >= HITAG_T_0_MIN) { + // '0' bit + rx[rxlen / 8] |= 0 << (7-(rxlen%8)); + rxlen++; + } else { + // Ignore wierd value, is to small to mean anything + } + } else { + LED_C_ON(); + // Capture tag frame (manchester decoding using only falling edges) + if(ra >= HITAG_T_EOF) { + if (rxlen != 0) { + //DbpString("wierd1?"); + } + // Capture the T0 periods that have passed since last communication or field drop (reset) + // We always recieve a 'one' first, which has the falling edge after a half period |-_| + response = ra-HITAG_T_TAG_HALF_PERIOD; + } else if(ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { + // Manchester coding example |-_|_-|-_| (101) + rx[rxlen / 8] |= 0 << (7-(rxlen%8)); + rxlen++; + rx[rxlen / 8] |= 1 << (7-(rxlen%8)); + rxlen++; + } else if(ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { + // Manchester coding example |_-|...|_-|-_| (0...01) + rx[rxlen / 8] |= 0 << (7-(rxlen%8)); + rxlen++; + // We have to skip this half period at start and add the 'one' the second time + if (!bSkip) { + rx[rxlen / 8] |= 1 << (7-(rxlen%8)); + rxlen++; + } + lastbit = !lastbit; + bSkip = !bSkip; + } else if(ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { + // Manchester coding example |_-|_-| (00) or |-_|-_| (11) + if (tag_sof) { + // Ignore bits that are transmitted during SOF + tag_sof--; + } else { + // bit is same as last bit + rx[rxlen / 8] |= lastbit << (7-(rxlen%8)); + rxlen++; + } + } else { + // Ignore wierd value, is to small to mean anything + } + } + } + } - // Check if frame was captured - if(rxlen > 0) { - frame_count++; - if (!LogTraceHitag(rx,rxlen,response,0,reader_frame)) { - DbpString("Trace full"); - break; - } + // Check if frame was captured + if(rxlen > 0) { + frame_count++; + if (!LogTraceHitag(rx,rxlen,response,0,reader_frame)) { + DbpString("Trace full"); + break; + } - // Check if we recognize a valid authentication attempt - if (nbytes(rxlen) == 8) { - // Store the authentication attempt - if (auth_table_len < (AUTH_TABLE_LENGTH-8)) { - memcpy(auth_table+auth_table_len,rx,8); - auth_table_len += 8; - } - } + // Check if we recognize a valid authentication attempt + if (nbytes(rxlen) == 8) { + // Store the authentication attempt + if (auth_table_len < (AUTH_TABLE_LENGTH-8)) { + memcpy(auth_table+auth_table_len,rx,8); + auth_table_len += 8; + } + } - // Reset the received frame and response timing info - memset(rx,0x00,sizeof(rx)); - response = 0; - reader_frame = false; - lastbit = 1; - bSkip = true; - tag_sof = 4; - overflow = 0; + // Reset the received frame and response timing info + memset(rx,0x00,sizeof(rx)); + response = 0; + reader_frame = false; + lastbit = 1; + bSkip = true; + tag_sof = 4; + overflow = 0; - LED_B_OFF(); - LED_C_OFF(); - } else { - // Save the timer overflow, will be 0 when frame was received - overflow += (AT91C_BASE_TC1->TC_CV/T0); - } - // Reset the frame length - rxlen = 0; - // Reset the timer to restart while-loop that receives frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; - } + LED_B_OFF(); + LED_C_OFF(); + } else { + // Save the timer overflow, will be 0 when frame was received + overflow += (AT91C_BASE_TC1->TC_CV/T0); + } + // Reset the frame length + rxlen = 0; + // Reset the timer to restart while-loop that receives frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + } LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); - LED_D_OFF(); - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + LED_B_OFF(); + LED_C_OFF(); + LED_D_OFF(); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); LED_A_OFF(); - set_tracing(false); -// Dbprintf("frame received: %d",frame_count); -// Dbprintf("Authentication Attempts: %d",(auth_table_len/8)); -// DbpString("All done"); + set_tracing(false); +// Dbprintf("frame received: %d",frame_count); +// Dbprintf("Authentication Attempts: %d",(auth_table_len/8)); +// DbpString("All done"); } void SimulateHitagTag(bool tag_mem_supplied, uint8_t* data) { - int frame_count; - int response; - int overflow; - uint8_t rx[HITAG_FRAME_LEN]; - size_t rxlen=0; - uint8_t tx[HITAG_FRAME_LEN]; - size_t txlen=0; - bool bQuitTraceFull = false; - bQuiet = false; + int frame_count; + int response; + int overflow; + uint8_t rx[HITAG_FRAME_LEN]; + size_t rxlen=0; + uint8_t tx[HITAG_FRAME_LEN]; + size_t txlen=0; + bool bQuitTraceFull = false; + bQuiet = false; - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - // free eventually allocated BigBuf memory - BigBuf_free(); BigBuf_Clear_ext(false); + // free eventually allocated BigBuf memory + BigBuf_free(); BigBuf_Clear_ext(false); - // Clean up trace and prepare it for storing frames - clear_trace(); - set_tracing(true); + // Clean up trace and prepare it for storing frames + clear_trace(); + set_tracing(true); - auth_table_len = 0; - auth_table_pos = 0; + auth_table_len = 0; + auth_table_pos = 0; uint8_t* auth_table; auth_table = (uint8_t *)BigBuf_malloc(AUTH_TABLE_LENGTH); - memset(auth_table, 0x00, AUTH_TABLE_LENGTH); + memset(auth_table, 0x00, AUTH_TABLE_LENGTH); - DbpString("Starting Hitag2 simulation"); - LED_D_ON(); - hitag2_init(); + DbpString("Starting Hitag2 simulation"); + LED_D_ON(); + hitag2_init(); - if (tag_mem_supplied) { - DbpString("Loading hitag2 memory..."); - memcpy((uint8_t*)tag.sectors,data,48); - } + if (tag_mem_supplied) { + DbpString("Loading hitag2 memory..."); + memcpy((uint8_t*)tag.sectors,data,48); + } - uint32_t block = 0; - for (size_t i=0; i<12; i++) { - for (size_t j=0; j<4; j++) { - block <<= 8; - block |= tag.sectors[i][j]; - } - Dbprintf("| %d | %08x |",i,block); - } + uint32_t block = 0; + for (size_t i=0; i<12; i++) { + for (size_t j=0; j<4; j++) { + block <<= 8; + block |= tag.sectors[i][j]; + } + Dbprintf("| %d | %08x |",i,block); + } - // Set up simulator mode, frequency divisor which will drive the FPGA - // and analog mux selection. - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); - SpinDelay(50); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); + // Set up simulator mode, frequency divisor which will drive the FPGA + // and analog mux selection. + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); + SpinDelay(50); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); - // Configure output pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + // Configure output pin that is connected to the FPGA (for modulating) + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - // Disable modulation at default, which means release resistance - LOW(GPIO_SSC_DOUT); + // Disable modulation at default, which means release resistance + LOW(GPIO_SSC_DOUT); - // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); - // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); - AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; // Disable timer during configuration - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, - // external trigger rising edge, load RA on rising edge of TIOA. - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; + // Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // external trigger rising edge, load RA on rising edge of TIOA. + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; - // Reset the received frame, frame count and timing info - memset(rx,0x00,sizeof(rx)); - frame_count = 0; - response = 0; - overflow = 0; + // Reset the received frame, frame count and timing info + memset(rx,0x00,sizeof(rx)); + frame_count = 0; + response = 0; + overflow = 0; - // Enable and reset counter - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Enable and reset counter + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - while(!BUTTON_PRESS() && !usb_poll_validate_length()) { - // Watchdog hit - WDT_HIT(); + while(!BUTTON_PRESS() && !usb_poll_validate_length()) { + // Watchdog hit + WDT_HIT(); - // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_EOF) { - // Check if rising edge in modulation is detected - if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values - int ra = (AT91C_BASE_TC1->TC_RA/T0) + overflow; - overflow = 0; + // Receive frame, watch for at most T0*EOF periods + while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_EOF) { + // Check if rising edge in modulation is detected + if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { + // Retrieve the new timing values + int ra = (AT91C_BASE_TC1->TC_RA/T0) + overflow; + overflow = 0; - // Reset timer every frame, we have to capture the last edge for timing - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Reset timer every frame, we have to capture the last edge for timing + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - LED_B_ON(); + LED_B_ON(); - // Capture reader frame - if(ra >= HITAG_T_STOP) { - if (rxlen != 0) { - //DbpString("wierd0?"); - } - // Capture the T0 periods that have passed since last communication or field drop (reset) - response = (ra - HITAG_T_LOW); - } else if(ra >= HITAG_T_1_MIN ) { - // '1' bit - rx[rxlen / 8] |= 1 << (7-(rxlen%8)); - rxlen++; - } else if(ra >= HITAG_T_0_MIN) { - // '0' bit - rx[rxlen / 8] |= 0 << (7-(rxlen%8)); - rxlen++; - } else { - // Ignore wierd value, is to small to mean anything - } - } - } + // Capture reader frame + if(ra >= HITAG_T_STOP) { + if (rxlen != 0) { + //DbpString("wierd0?"); + } + // Capture the T0 periods that have passed since last communication or field drop (reset) + response = (ra - HITAG_T_LOW); + } else if(ra >= HITAG_T_1_MIN ) { + // '1' bit + rx[rxlen / 8] |= 1 << (7-(rxlen%8)); + rxlen++; + } else if(ra >= HITAG_T_0_MIN) { + // '0' bit + rx[rxlen / 8] |= 0 << (7-(rxlen%8)); + rxlen++; + } else { + // Ignore wierd value, is to small to mean anything + } + } + } - // Check if frame was captured - if(rxlen > 4) { - frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx,rxlen,response,0,true)) { - DbpString("Trace full"); - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } + // Check if frame was captured + if(rxlen > 4) { + frame_count++; + if (!bQuiet) { + if (!LogTraceHitag(rx,rxlen,response,0,true)) { + DbpString("Trace full"); + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } - // Disable timer 1 with external trigger to avoid triggers during our own modulation - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + // Disable timer 1 with external trigger to avoid triggers during our own modulation + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Process the incoming frame (rx) and prepare the outgoing frame (tx) - hitag2_handle_reader_command(rx,rxlen,tx,&txlen); + // Process the incoming frame (rx) and prepare the outgoing frame (tx) + hitag2_handle_reader_command(rx,rxlen,tx,&txlen); - // Wait for HITAG_T_WAIT_1 carrier periods after the last reader bit, - // not that since the clock counts since the rising edge, but T_Wait1 is - // with respect to the falling edge, we need to wait actually (T_Wait1 - T_Low) - // periods. The gap time T_Low varies (4..10). All timer values are in - // terms of T0 units - while(AT91C_BASE_TC0->TC_CV < T0*(HITAG_T_WAIT_1-HITAG_T_LOW)); + // Wait for HITAG_T_WAIT_1 carrier periods after the last reader bit, + // not that since the clock counts since the rising edge, but T_Wait1 is + // with respect to the falling edge, we need to wait actually (T_Wait1 - T_Low) + // periods. The gap time T_Low varies (4..10). All timer values are in + // terms of T0 units + while(AT91C_BASE_TC0->TC_CV < T0*(HITAG_T_WAIT_1-HITAG_T_LOW)); - // Send and store the tag answer (if there is any) - if (txlen) { - // Transmit the tag frame - hitag_send_frame(tx,txlen); - // Store the frame in the trace - if (!bQuiet) { - if (!LogTraceHitag(tx,txlen,0,0,false)) { - DbpString("Trace full"); - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } - } + // Send and store the tag answer (if there is any) + if (txlen) { + // Transmit the tag frame + hitag_send_frame(tx,txlen); + // Store the frame in the trace + if (!bQuiet) { + if (!LogTraceHitag(tx,txlen,0,0,false)) { + DbpString("Trace full"); + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } + } - // Reset the received frame and response timing info - memset(rx,0x00,sizeof(rx)); - response = 0; + // Reset the received frame and response timing info + memset(rx,0x00,sizeof(rx)); + response = 0; - // Enable and reset external trigger in timer for capturing future frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - LED_B_OFF(); - } - // Reset the frame length - rxlen = 0; - // Save the timer overflow, will be 0 when frame was received - overflow += (AT91C_BASE_TC1->TC_CV/T0); - // Reset the timer to restart while-loop that receives frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; - } - LED_B_OFF(); - LED_D_OFF(); - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + // Enable and reset external trigger in timer for capturing future frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + LED_B_OFF(); + } + // Reset the frame length + rxlen = 0; + // Save the timer overflow, will be 0 when frame was received + overflow += (AT91C_BASE_TC1->TC_CV/T0); + // Reset the timer to restart while-loop that receives frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + } + LED_B_OFF(); + LED_D_OFF(); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - DbpString("Sim Stopped"); - set_tracing(false); + DbpString("Sim Stopped"); + set_tracing(false); } void ReaderHitag(hitag_function htf, hitag_data* htd) { - int frame_count = 0; - int response = 0; - uint8_t rx[HITAG_FRAME_LEN]; - size_t rxlen = 0; - uint8_t txbuf[HITAG_FRAME_LEN]; - uint8_t* tx = txbuf; - size_t txlen = 0; - int lastbit = 1; - bool bSkip; - int reset_sof; - int tag_sof; - int t_wait = HITAG_T_WAIT_MAX; - bool bStop = false; - bool bQuitTraceFull = false; + int frame_count = 0; + int response = 0; + uint8_t rx[HITAG_FRAME_LEN]; + size_t rxlen = 0; + uint8_t txbuf[HITAG_FRAME_LEN]; + uint8_t* tx = txbuf; + size_t txlen = 0; + int lastbit = 1; + bool bSkip; + int reset_sof; + int tag_sof; + int t_wait = HITAG_T_WAIT_MAX; + bool bStop = false; + bool bQuitTraceFull = false; - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - // Reset the return status - bSuccessful = false; + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + // Reset the return status + bSuccessful = false; - // Clean up trace and prepare it for storing frames - clear_trace(); - set_tracing(true); + // Clean up trace and prepare it for storing frames + clear_trace(); + set_tracing(true); - //DbpString("Starting Hitag reader family"); + //DbpString("Starting Hitag reader family"); - // Check configuration - switch (htf) { - case RHT2F_PASSWORD: { - Dbprintf("List identifier in password mode"); - memcpy(password,htd->pwd.password, 4); - blocknr = 0; - bQuitTraceFull = false; - bQuiet = false; - bPwd = false; - } break; + // Check configuration + switch (htf) { + case RHT2F_PASSWORD: { + Dbprintf("List identifier in password mode"); + memcpy(password,htd->pwd.password, 4); + blocknr = 0; + bQuitTraceFull = false; + bQuiet = false; + bPwd = false; + } break; - case RHT2F_AUTHENTICATE: { - DbpString("Authenticating using nr,ar pair:"); - memcpy(NrAr,htd->auth.NrAr, 8); - Dbhexdump(8,NrAr,false); - bQuiet = false; - bCrypto = false; - bAuthenticating = false; - bQuitTraceFull = true; - } break; + case RHT2F_AUTHENTICATE: { + DbpString("Authenticating using nr,ar pair:"); + memcpy(NrAr,htd->auth.NrAr, 8); + Dbhexdump(8,NrAr,false); + bQuiet = false; + bCrypto = false; + bAuthenticating = false; + bQuitTraceFull = true; + } break; - case RHT2F_CRYPTO: { - DbpString("Authenticating using key:"); - memcpy(key,htd->crypto.key, 6); //HACK; 4 or 6?? I read both in the code. - Dbhexdump(6,key,false); - blocknr = 0; - bQuiet = false; - bCrypto = false; - bAuthenticating = false; - bQuitTraceFull = true; - } break; + case RHT2F_CRYPTO: { + DbpString("Authenticating using key:"); + memcpy(key,htd->crypto.key, 6); //HACK; 4 or 6?? I read both in the code. + Dbhexdump(6,key,false); + blocknr = 0; + bQuiet = false; + bCrypto = false; + bAuthenticating = false; + bQuitTraceFull = true; + } break; - case RHT2F_TEST_AUTH_ATTEMPTS: { - Dbprintf("Testing %d authentication attempts",(auth_table_len/8)); - auth_table_pos = 0; - memcpy(NrAr, auth_table, 8); - bQuitTraceFull = false; - bQuiet = false; - bCrypto = false; - } break; - case RHT2F_UID_ONLY: { - blocknr = 0; - bQuiet = false; - bCrypto = false; - bAuthenticating = false; - bQuitTraceFull = true; - } break; - default: { - Dbprintf("Error, unknown function: %d",htf); - set_tracing(false); - return; - } break; - } + case RHT2F_TEST_AUTH_ATTEMPTS: { + Dbprintf("Testing %d authentication attempts",(auth_table_len/8)); + auth_table_pos = 0; + memcpy(NrAr, auth_table, 8); + bQuitTraceFull = false; + bQuiet = false; + bCrypto = false; + } break; + case RHT2F_UID_ONLY: { + blocknr = 0; + bQuiet = false; + bCrypto = false; + bAuthenticating = false; + bQuitTraceFull = true; + } break; + default: { + Dbprintf("Error, unknown function: %d",htf); + set_tracing(false); + return; + } break; + } - LED_D_ON(); - hitag2_init(); + LED_D_ON(); + hitag2_init(); - // Configure output and enable pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + // Configure output and enable pin that is connected to the FPGA (for modulating) + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - // Set fpga in edge detect with reader field, we can modulate as reader now - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - SpinDelay(20); + // Set fpga in edge detect with reader field, we can modulate as reader now + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + SpinDelay(20); - // Set Frequency divisor which will drive the FPGA and analog mux selection - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); + // Set Frequency divisor which will drive the FPGA and analog mux selection + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); - // Disable modulation at default, which means enable the field - LOW(GPIO_SSC_DOUT); + // Disable modulation at default, which means enable the field + LOW(GPIO_SSC_DOUT); - // Give it a bit of time for the resonant antenna to settle. - SpinDelay(30); + // Give it a bit of time for the resonant antenna to settle. + SpinDelay(30); - // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); - // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); - AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; // Disable timer during configuration - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, - // external trigger rising edge, load RA on falling edge of TIOA. - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; + // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // external trigger rising edge, load RA on falling edge of TIOA. + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; - // Enable and reset counters - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Enable and reset counters + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - // Tag specific configuration settings (sof, timings, etc.) - if (htf < 10){ - // hitagS settings - reset_sof = 1; - t_wait = 200; + // Tag specific configuration settings (sof, timings, etc.) + if (htf < 10){ + // hitagS settings + reset_sof = 1; + t_wait = 200; // DbpString("Configured for hitagS reader"); - } else if (htf < 20) { - // hitag1 settings - reset_sof = 1; - t_wait = 200; + } else if (htf < 20) { + // hitag1 settings + reset_sof = 1; + t_wait = 200; // DbpString("Configured for hitag1 reader"); - } else if (htf < 30) { - // hitag2 settings - reset_sof = 4; - t_wait = HITAG_T_WAIT_2; + } else if (htf < 30) { + // hitag2 settings + reset_sof = 4; + t_wait = HITAG_T_WAIT_2; // DbpString("Configured for hitag2 reader"); - } else { - Dbprintf("Error, unknown hitag reader type: %d",htf); - set_tracing(false); - LED_D_OFF(); - return; - } - uint8_t attempt_count=0; - while (!bStop && !BUTTON_PRESS()) { - // Watchdog hit - WDT_HIT(); + } else { + Dbprintf("Error, unknown hitag reader type: %d",htf); + set_tracing(false); + LED_D_OFF(); + return; + } + uint8_t attempt_count=0; + while (!bStop && !BUTTON_PRESS()) { + // Watchdog hit + WDT_HIT(); - // Check if frame was captured and store it - if (rxlen > 0) { - frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx,rxlen, response, 0, false)) { - DbpString("Trace full"); - if (bQuitTraceFull) - break; - else - bQuiet = true; - } - } - } + // Check if frame was captured and store it + if (rxlen > 0) { + frame_count++; + if (!bQuiet) { + if (!LogTraceHitag(rx,rxlen, response, 0, false)) { + DbpString("Trace full"); + if (bQuitTraceFull) + break; + else + bQuiet = true; + } + } + } - // By default reset the transmission buffer - tx = txbuf; - switch (htf) { - case RHT2F_PASSWORD: { - bStop = !hitag2_password(rx,rxlen,tx,&txlen); - } break; - case RHT2F_AUTHENTICATE: { - bStop = !hitag2_authenticate(rx,rxlen,tx,&txlen); - } break; - case RHT2F_CRYPTO: { - bStop = !hitag2_crypto(rx,rxlen,tx,&txlen, false); - } break; - case RHT2F_TEST_AUTH_ATTEMPTS: { - bStop = !hitag2_test_auth_attempts(rx,rxlen,tx,&txlen); - } break; - case RHT2F_UID_ONLY: { - bStop = !hitag2_read_uid(rx, rxlen, tx, &txlen); - attempt_count++; //attempt 3 times to get uid then quit - if (!bStop && attempt_count == 3) - bStop = true; - } break; - default: { - Dbprintf("Error, unknown function: %d",htf); - set_tracing(false); - LED_D_OFF(); - return; - } break; - } + // By default reset the transmission buffer + tx = txbuf; + switch (htf) { + case RHT2F_PASSWORD: { + bStop = !hitag2_password(rx,rxlen,tx,&txlen); + } break; + case RHT2F_AUTHENTICATE: { + bStop = !hitag2_authenticate(rx,rxlen,tx,&txlen); + } break; + case RHT2F_CRYPTO: { + bStop = !hitag2_crypto(rx,rxlen,tx,&txlen, false); + } break; + case RHT2F_TEST_AUTH_ATTEMPTS: { + bStop = !hitag2_test_auth_attempts(rx,rxlen,tx,&txlen); + } break; + case RHT2F_UID_ONLY: { + bStop = !hitag2_read_uid(rx, rxlen, tx, &txlen); + attempt_count++; //attempt 3 times to get uid then quit + if (!bStop && attempt_count == 3) + bStop = true; + } break; + default: { + Dbprintf("Error, unknown function: %d",htf); + set_tracing(false); + LED_D_OFF(); + return; + } break; + } - // Send and store the reader command - // Disable timer 1 with external trigger to avoid triggers during our own modulation - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + // Send and store the reader command + // Disable timer 1 with external trigger to avoid triggers during our own modulation + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, - // Since the clock counts since the last falling edge, a 'one' means that the - // falling edge occured halfway the period. with respect to this falling edge, - // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. - // All timer values are in terms of T0 units - while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))); + // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, + // Since the clock counts since the last falling edge, a 'one' means that the + // falling edge occured halfway the period. with respect to this falling edge, + // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. + // All timer values are in terms of T0 units + while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))); - // Transmit the reader frame - hitag_reader_send_frame(tx, txlen); + // Transmit the reader frame + hitag_reader_send_frame(tx, txlen); - // Enable and reset external trigger in timer for capturing future frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Enable and reset external trigger in timer for capturing future frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - // Add transmitted frame to total count - if (txlen > 0) { - frame_count++; - if (!bQuiet) { - // Store the frame in the trace - if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } - } + // Add transmitted frame to total count + if (txlen > 0) { + frame_count++; + if (!bQuiet) { + // Store the frame in the trace + if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } + } - // Reset values for receiving frames - memset(rx, 0x00, sizeof(rx)); - rxlen = 0; - lastbit = 1; - bSkip = true; - tag_sof = reset_sof; - response = 0; - uint32_t errorCount = 0; + // Reset values for receiving frames + memset(rx, 0x00, sizeof(rx)); + rxlen = 0; + lastbit = 1; + bSkip = true; + tag_sof = reset_sof; + response = 0; + uint32_t errorCount = 0; - // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { - // Check if falling edge in tag modulation is detected - if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values - int ra = (AT91C_BASE_TC1->TC_RA/T0); + // Receive frame, watch for at most T0*EOF periods + while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { + // Check if falling edge in tag modulation is detected + if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { + // Retrieve the new timing values + int ra = (AT91C_BASE_TC1->TC_RA/T0); - // Reset timer every frame, we have to capture the last edge for timing - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + // Reset timer every frame, we have to capture the last edge for timing + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - LED_B_ON(); + LED_B_ON(); - // Capture tag frame (manchester decoding using only falling edges) - if (ra >= HITAG_T_EOF) { - // Capture the T0 periods that have passed since last communication or field drop (reset) - // We always recieve a 'one' first, which has the falling edge after a half period |-_| - response = ra-HITAG_T_TAG_HALF_PERIOD; - } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { - // Manchester coding example |-_|_-|-_| (101) - rx[rxlen / 8] |= 0 << (7-(rxlen%8)); - rxlen++; - rx[rxlen / 8] |= 1 << (7-(rxlen%8)); - rxlen++; - } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { - // Manchester coding example |_-|...|_-|-_| (0...01) - rx[rxlen / 8] |= 0 << (7-(rxlen%8)); - rxlen++; - // We have to skip this half period at start and add the 'one' the second time - if (!bSkip) { - rx[rxlen / 8] |= 1 << (7-(rxlen%8)); - rxlen++; - } - lastbit = !lastbit; - bSkip = !bSkip; - } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { - // Manchester coding example |_-|_-| (00) or |-_|-_| (11) - if (tag_sof) { - // Ignore bits that are transmitted during SOF - tag_sof--; - } else { - // bit is same as last bit - rx[rxlen / 8] |= lastbit << (7-(rxlen%8)); - rxlen++; - } - } else { - //Dbprintf("DEBUG: Wierd2"); - errorCount++; - // Ignore wierd value, is to small to mean anything - } - } - //if we saw over 100 wierd values break it probably isn't hitag... - if (errorCount > 100) break; - // We can break this loop if we received the last bit from a frame - if (AT91C_BASE_TC1->TC_CV > T0*HITAG_T_EOF) { - if (rxlen > 0) break; - } - } - } - LED_B_OFF(); - LED_D_OFF(); - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - set_tracing(false); + // Capture tag frame (manchester decoding using only falling edges) + if (ra >= HITAG_T_EOF) { + // Capture the T0 periods that have passed since last communication or field drop (reset) + // We always recieve a 'one' first, which has the falling edge after a half period |-_| + response = ra-HITAG_T_TAG_HALF_PERIOD; + } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { + // Manchester coding example |-_|_-|-_| (101) + rx[rxlen / 8] |= 0 << (7-(rxlen%8)); + rxlen++; + rx[rxlen / 8] |= 1 << (7-(rxlen%8)); + rxlen++; + } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { + // Manchester coding example |_-|...|_-|-_| (0...01) + rx[rxlen / 8] |= 0 << (7-(rxlen%8)); + rxlen++; + // We have to skip this half period at start and add the 'one' the second time + if (!bSkip) { + rx[rxlen / 8] |= 1 << (7-(rxlen%8)); + rxlen++; + } + lastbit = !lastbit; + bSkip = !bSkip; + } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { + // Manchester coding example |_-|_-| (00) or |-_|-_| (11) + if (tag_sof) { + // Ignore bits that are transmitted during SOF + tag_sof--; + } else { + // bit is same as last bit + rx[rxlen / 8] |= lastbit << (7-(rxlen%8)); + rxlen++; + } + } else { + //Dbprintf("DEBUG: Wierd2"); + errorCount++; + // Ignore wierd value, is to small to mean anything + } + } + //if we saw over 100 wierd values break it probably isn't hitag... + if (errorCount > 100) break; + // We can break this loop if we received the last bit from a frame + if (AT91C_BASE_TC1->TC_CV > T0*HITAG_T_EOF) { + if (rxlen > 0) break; + } + } + } + LED_B_OFF(); + LED_D_OFF(); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(false); - if ( bSuccessful ) - cmd_send(CMD_ACK, bSuccessful, 0, 0, (uint8_t*)tag.sectors, 48); - else - cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); + if ( bSuccessful ) + cmd_send(CMD_ACK, bSuccessful, 0, 0, (uint8_t*)tag.sectors, 48); + else + cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); } void WriterHitag(hitag_function htf, hitag_data* htd, int page) { - int frame_count; - int response; - uint8_t rx[HITAG_FRAME_LEN]; - size_t rxlen=0; - uint8_t txbuf[HITAG_FRAME_LEN]; - uint8_t* tx = txbuf; - size_t txlen=0; - int lastbit; - bool bSkip; - int reset_sof; - int tag_sof; - int t_wait = HITAG_T_WAIT_MAX; - bool bStop; - bool bQuitTraceFull = false; + int frame_count; + int response; + uint8_t rx[HITAG_FRAME_LEN]; + size_t rxlen=0; + uint8_t txbuf[HITAG_FRAME_LEN]; + uint8_t* tx = txbuf; + size_t txlen=0; + int lastbit; + bool bSkip; + int reset_sof; + int tag_sof; + int t_wait = HITAG_T_WAIT_MAX; + bool bStop; + bool bQuitTraceFull = false; - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - // Reset the return status - bSuccessful = false; + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + // Reset the return status + bSuccessful = false; - // Clean up trace and prepare it for storing frames - set_tracing(true); - clear_trace(); + // Clean up trace and prepare it for storing frames + set_tracing(true); + clear_trace(); - // DbpString("Starting Hitag reader family"); + // DbpString("Starting Hitag reader family"); - // Check configuration - switch(htf) { - case WHT2F_CRYPTO: { - DbpString("Authenticating using key:"); - memcpy(key,htd->crypto.key,6); //HACK; 4 or 6?? I read both in the code. - memcpy(writedata, htd->crypto.data, 4); - Dbhexdump(6,key,false); - blocknr = page; - bQuiet = false; - bCrypto = false; - bAuthenticating = false; - bQuitTraceFull = true; - writestate = WRITE_STATE_START; - } break; - default: { - Dbprintf("Error, unknown function: %d",htf); - return; - } break; - } + // Check configuration + switch(htf) { + case WHT2F_CRYPTO: { + DbpString("Authenticating using key:"); + memcpy(key,htd->crypto.key,6); //HACK; 4 or 6?? I read both in the code. + memcpy(writedata, htd->crypto.data, 4); + Dbhexdump(6,key,false); + blocknr = page; + bQuiet = false; + bCrypto = false; + bAuthenticating = false; + bQuitTraceFull = true; + writestate = WRITE_STATE_START; + } break; + default: { + Dbprintf("Error, unknown function: %d",htf); + return; + } break; + } - LED_D_ON(); - hitag2_init(); + LED_D_ON(); + hitag2_init(); - // Configure output and enable pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + // Configure output and enable pin that is connected to the FPGA (for modulating) + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - // Set fpga in edge detect with reader field, we can modulate as reader now - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + // Set fpga in edge detect with reader field, we can modulate as reader now + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - // Set Frequency divisor which will drive the FPGA and analog mux selection - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); + // Set Frequency divisor which will drive the FPGA and analog mux selection + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); - // Disable modulation at default, which means enable the field - LOW(GPIO_SSC_DOUT); + // Disable modulation at default, which means enable the field + LOW(GPIO_SSC_DOUT); - // Give it a bit of time for the resonant antenna to settle. - SpinDelay(30); + // Give it a bit of time for the resonant antenna to settle. + SpinDelay(30); - // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); - // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); - AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - // Disable timer during configuration - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + // Disable timer during configuration + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, - // external trigger rising edge, load RA on falling edge of TIOA. - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; + // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // external trigger rising edge, load RA on falling edge of TIOA. + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; - // Enable and reset counters - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Enable and reset counters + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - // Reset the received frame, frame count and timing info - frame_count = 0; - response = 0; - lastbit = 1; - bStop = false; + // Reset the received frame, frame count and timing info + frame_count = 0; + response = 0; + lastbit = 1; + bStop = false; - // Tag specific configuration settings (sof, timings, etc.) - if (htf < 10){ - // hitagS settings - reset_sof = 1; - t_wait = 200; - // DbpString("Configured for hitagS reader"); - } else if (htf < 20) { - // hitag1 settings - reset_sof = 1; - t_wait = 200; - // DbpString("Configured for hitag1 reader"); - } else if (htf < 30) { - // hitag2 settings - reset_sof = 4; - t_wait = HITAG_T_WAIT_2; - // DbpString("Configured for hitag2 reader"); - } else { - Dbprintf("Error, unknown hitag reader type: %d",htf); - return; - } - while(!bStop && !BUTTON_PRESS()) { - // Watchdog hit - WDT_HIT(); + // Tag specific configuration settings (sof, timings, etc.) + if (htf < 10){ + // hitagS settings + reset_sof = 1; + t_wait = 200; + // DbpString("Configured for hitagS reader"); + } else if (htf < 20) { + // hitag1 settings + reset_sof = 1; + t_wait = 200; + // DbpString("Configured for hitag1 reader"); + } else if (htf < 30) { + // hitag2 settings + reset_sof = 4; + t_wait = HITAG_T_WAIT_2; + // DbpString("Configured for hitag2 reader"); + } else { + Dbprintf("Error, unknown hitag reader type: %d",htf); + return; + } + while(!bStop && !BUTTON_PRESS()) { + // Watchdog hit + WDT_HIT(); - // Check if frame was captured and store it - if(rxlen > 0) { - frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx,rxlen,response,0,false)) { - DbpString("Trace full"); - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } - } + // Check if frame was captured and store it + if(rxlen > 0) { + frame_count++; + if (!bQuiet) { + if (!LogTraceHitag(rx,rxlen,response,0,false)) { + DbpString("Trace full"); + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } + } - // By default reset the transmission buffer - tx = txbuf; - switch(htf) { - case WHT2F_CRYPTO: { - bStop = !hitag2_crypto(rx,rxlen,tx,&txlen, true); - } break; - default: { - Dbprintf("Error, unknown function: %d",htf); - return; - } break; - } + // By default reset the transmission buffer + tx = txbuf; + switch(htf) { + case WHT2F_CRYPTO: { + bStop = !hitag2_crypto(rx,rxlen,tx,&txlen, true); + } break; + default: { + Dbprintf("Error, unknown function: %d",htf); + return; + } break; + } - // Send and store the reader command - // Disable timer 1 with external trigger to avoid triggers during our own modulation - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + // Send and store the reader command + // Disable timer 1 with external trigger to avoid triggers during our own modulation + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, - // Since the clock counts since the last falling edge, a 'one' means that the - // falling edge occured halfway the period. with respect to this falling edge, - // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. - // All timer values are in terms of T0 units - while(AT91C_BASE_TC0->TC_CV < T0*(t_wait+(HITAG_T_TAG_HALF_PERIOD*lastbit))); + // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, + // Since the clock counts since the last falling edge, a 'one' means that the + // falling edge occured halfway the period. with respect to this falling edge, + // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. + // All timer values are in terms of T0 units + while(AT91C_BASE_TC0->TC_CV < T0*(t_wait+(HITAG_T_TAG_HALF_PERIOD*lastbit))); - // Dbprintf("DEBUG: Sending reader frame"); + // Dbprintf("DEBUG: Sending reader frame"); - // Transmit the reader frame - hitag_reader_send_frame(tx,txlen); + // Transmit the reader frame + hitag_reader_send_frame(tx,txlen); - // Enable and reset external trigger in timer for capturing future frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Enable and reset external trigger in timer for capturing future frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - // Add transmitted frame to total count - if(txlen > 0) { - frame_count++; - if (!bQuiet) { - // Store the frame in the trace - if (!LogTraceHitag(tx,txlen,HITAG_T_WAIT_2,0,true)) { - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } - } + // Add transmitted frame to total count + if(txlen > 0) { + frame_count++; + if (!bQuiet) { + // Store the frame in the trace + if (!LogTraceHitag(tx,txlen,HITAG_T_WAIT_2,0,true)) { + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } + } - // Reset values for receiving frames - memset(rx,0x00,sizeof(rx)); - rxlen = 0; - lastbit = 1; - bSkip = true; - tag_sof = reset_sof; - response = 0; - // Dbprintf("DEBUG: Waiting to receive frame"); - uint32_t errorCount = 0; + // Reset values for receiving frames + memset(rx,0x00,sizeof(rx)); + rxlen = 0; + lastbit = 1; + bSkip = true; + tag_sof = reset_sof; + response = 0; + // Dbprintf("DEBUG: Waiting to receive frame"); + uint32_t errorCount = 0; - // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_WAIT_MAX) { - // Check if falling edge in tag modulation is detected - if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values - int ra = (AT91C_BASE_TC1->TC_RA/T0); + // Receive frame, watch for at most T0*EOF periods + while (AT91C_BASE_TC1->TC_CV < T0*HITAG_T_WAIT_MAX) { + // Check if falling edge in tag modulation is detected + if(AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { + // Retrieve the new timing values + int ra = (AT91C_BASE_TC1->TC_RA/T0); - // Reset timer every frame, we have to capture the last edge for timing - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + // Reset timer every frame, we have to capture the last edge for timing + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - LED_B_ON(); + LED_B_ON(); - // Capture tag frame (manchester decoding using only falling edges) - if(ra >= HITAG_T_EOF) { - if (rxlen != 0) { - //Dbprintf("DEBUG: Wierd1"); - } - // Capture the T0 periods that have passed since last communication or field drop (reset) - // We always recieve a 'one' first, which has the falling edge after a half period |-_| - response = ra-HITAG_T_TAG_HALF_PERIOD; - } else if(ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { - // Manchester coding example |-_|_-|-_| (101) + // Capture tag frame (manchester decoding using only falling edges) + if(ra >= HITAG_T_EOF) { + if (rxlen != 0) { + //Dbprintf("DEBUG: Wierd1"); + } + // Capture the T0 periods that have passed since last communication or field drop (reset) + // We always recieve a 'one' first, which has the falling edge after a half period |-_| + response = ra-HITAG_T_TAG_HALF_PERIOD; + } else if(ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { + // Manchester coding example |-_|_-|-_| (101) - // need to test to verify we don't exceed memory... - // if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { - // break; - // } - rx[rxlen / 8] |= 0 << (7-(rxlen%8)); - rxlen++; - rx[rxlen / 8] |= 1 << (7-(rxlen%8)); - rxlen++; - } else if(ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { - // Manchester coding example |_-|...|_-|-_| (0...01) + // need to test to verify we don't exceed memory... + // if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { + // break; + // } + rx[rxlen / 8] |= 0 << (7-(rxlen%8)); + rxlen++; + rx[rxlen / 8] |= 1 << (7-(rxlen%8)); + rxlen++; + } else if(ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { + // Manchester coding example |_-|...|_-|-_| (0...01) - // need to test to verify we don't exceed memory... - // if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { - // break; - // } - rx[rxlen / 8] |= 0 << (7-(rxlen%8)); - rxlen++; - // We have to skip this half period at start and add the 'one' the second time - if (!bSkip) { - rx[rxlen / 8] |= 1 << (7-(rxlen%8)); - rxlen++; - } - lastbit = !lastbit; - bSkip = !bSkip; - } else if(ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { - // Manchester coding example |_-|_-| (00) or |-_|-_| (11) + // need to test to verify we don't exceed memory... + // if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { + // break; + // } + rx[rxlen / 8] |= 0 << (7-(rxlen%8)); + rxlen++; + // We have to skip this half period at start and add the 'one' the second time + if (!bSkip) { + rx[rxlen / 8] |= 1 << (7-(rxlen%8)); + rxlen++; + } + lastbit = !lastbit; + bSkip = !bSkip; + } else if(ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { + // Manchester coding example |_-|_-| (00) or |-_|-_| (11) - // need to test to verify we don't exceed memory... - // if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { - // break; - // } - if (tag_sof) { - // Ignore bits that are transmitted during SOF - tag_sof--; - } else { - // bit is same as last bit - rx[rxlen / 8] |= lastbit << (7-(rxlen%8)); - rxlen++; - } - } else { - // Dbprintf("DEBUG: Wierd2"); - errorCount++; - // Ignore wierd value, is to small to mean anything - } - } - // if we saw over 100 wierd values break it probably isn't hitag... - if (errorCount >100) break; - // We can break this loop if we received the last bit from a frame - if (AT91C_BASE_TC1->TC_CV > T0*HITAG_T_EOF) { - if (rxlen>0) break; - } - } + // need to test to verify we don't exceed memory... + // if ( ((rxlen+2) / 8) > HITAG_FRAME_LEN) { + // break; + // } + if (tag_sof) { + // Ignore bits that are transmitted during SOF + tag_sof--; + } else { + // bit is same as last bit + rx[rxlen / 8] |= lastbit << (7-(rxlen%8)); + rxlen++; + } + } else { + // Dbprintf("DEBUG: Wierd2"); + errorCount++; + // Ignore wierd value, is to small to mean anything + } + } + // if we saw over 100 wierd values break it probably isn't hitag... + if (errorCount >100) break; + // We can break this loop if we received the last bit from a frame + if (AT91C_BASE_TC1->TC_CV > T0*HITAG_T_EOF) { + if (rxlen>0) break; + } + } - // Wait some extra time for flash to be programmed - if ((rxlen == 0) && (writestate == WRITE_STATE_PROG)) - { - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - while(AT91C_BASE_TC0->TC_CV < T0*(HITAG_T_PROG - HITAG_T_WAIT_MAX)); - } - } - // Dbprintf("DEBUG: Done waiting for frame"); + // Wait some extra time for flash to be programmed + if ((rxlen == 0) && (writestate == WRITE_STATE_PROG)) + { + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + while(AT91C_BASE_TC0->TC_CV < T0*(HITAG_T_PROG - HITAG_T_WAIT_MAX)); + } + } + // Dbprintf("DEBUG: Done waiting for frame"); - LED_B_OFF(); - LED_D_OFF(); - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - // Dbprintf("frame received: %d",frame_count); - // DbpString("All done"); - cmd_send(CMD_ACK,bSuccessful,0,0,(uint8_t*)tag.sectors,48); + LED_B_OFF(); + LED_D_OFF(); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + // Dbprintf("frame received: %d",frame_count); + // DbpString("All done"); + cmd_send(CMD_ACK,bSuccessful,0,0,(uint8_t*)tag.sectors,48); } diff --git a/armsrc/hitagS.c b/armsrc/hitagS.c index 489cf9f7e..544dbf086 100644 --- a/armsrc/hitagS.c +++ b/armsrc/hitagS.c @@ -22,17 +22,17 @@ #define CRC_PRESET 0xFF #define CRC_POLYNOM 0x1D -#define u8 uint8_t -#define u32 uint32_t -#define u64 uint64_t -#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7)) -#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8)) -#define rev32(x) (rev16(x)+(rev16(x>>16)<<16)) -#define rev64(x) (rev32(x)+(rev32(x>>32)<<32)) -#define bit(x,n) (((x)>>(n))&1) -#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1) -#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31)) -#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63))) +#define u8 uint8_t +#define u32 uint32_t +#define u64 uint64_t +#define rev8(x) ((((x)>>7)&1)+((((x)>>6)&1)<<1)+((((x)>>5)&1)<<2)+((((x)>>4)&1)<<3)+((((x)>>3)&1)<<4)+((((x)>>2)&1)<<5)+((((x)>>1)&1)<<6)+(((x)&1)<<7)) +#define rev16(x) (rev8 (x)+(rev8 (x>> 8)<< 8)) +#define rev32(x) (rev16(x)+(rev16(x>>16)<<16)) +#define rev64(x) (rev32(x)+(rev32(x>>32)<<32)) +#define bit(x,n) (((x)>>(n))&1) +#define bit32(x,n) ((((x)[(n)>>5])>>((n)))&1) +#define inv32(x,i,n) ((x)[(i)>>5]^=((u32)(n))<<((i)&31)) +#define rotl64(x, n) ((((u64)(x))<<((n)&63))+(((u64)(x))>>((0-(n))&63))) static bool bQuiet; static bool bSuccessful; @@ -40,103 +40,103 @@ static struct hitagS_tag tag; static byte_t page_to_be_written = 0; static int block_data_left = 0; typedef enum modulation { - AC2K = 0, - AC4K, - MC4K, - MC8K + AC2K = 0, + AC4K, + MC4K, + MC8K } MOD; -static MOD m = AC2K; //used modulation +static MOD m = AC2K; //used modulation static uint32_t temp_uid; static int temp2 = 0; -static int sof_bits; //number of start-of-frame bits -static byte_t pwdh0, pwdl0, pwdl1; //password bytes -static uint32_t rnd = 0x74124485; //randomnumber +static int sof_bits; //number of start-of-frame bits +static byte_t pwdh0, pwdl0, pwdl1; //password bytes +static uint32_t rnd = 0x74124485; //randomnumber static int test = 0; size_t blocknr; bool end=false; // Single bit Hitag2 functions: -#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8)) -static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001 -static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001 -static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 -#define ht2bs_4a(a,b,c,d) (~(((a|b)&c)^(a|d)^b)) -#define ht2bs_4b(a,b,c,d) (~(((d|c)&(a^b))^(d|a|b))) -#define ht2bs_5c(a,b,c,d,e) (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c)))) -#define uf20bs u32 +#define i4(x,a,b,c,d) ((u32)((((x)>>(a))&1)+(((x)>>(b))&1)*2+(((x)>>(c))&1)*4+(((x)>>(d))&1)*8)) +static const u32 ht2_f4a = 0x2C79; // 0010 1100 0111 1001 +static const u32 ht2_f4b = 0x6671; // 0110 0110 0111 0001 +static const u32 ht2_f5c = 0x7907287B; // 0111 1001 0000 0111 0010 1000 0111 1011 +#define ht2bs_4a(a,b,c,d) (~(((a|b)&c)^(a|d)^b)) +#define ht2bs_4b(a,b,c,d) (~(((d|c)&(a^b))^(d|a|b))) +#define ht2bs_5c(a,b,c,d,e) (~((((((c^e)|d)&a)^b)&(c^b))^(((d^e)|a)&((d^b)|c)))) +#define uf20bs u32 static u32 f20(const u64 x) { - u32 i5; + u32 i5; - i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1 - + ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2 - + ((ht2_f4b >> i4(x, 16, 20, 22, 25)) & 1) * 4 - + ((ht2_f4b >> i4(x, 27, 28, 30, 32)) & 1) * 8 - + ((ht2_f4a >> i4(x, 33, 42, 43, 45)) & 1) * 16; + i5 = ((ht2_f4a >> i4(x, 1, 2, 4, 5)) & 1) * 1 + + ((ht2_f4b >> i4(x, 7, 11, 13, 14)) & 1) * 2 + + ((ht2_f4b >> i4(x, 16, 20, 22, 25)) & 1) * 4 + + ((ht2_f4b >> i4(x, 27, 28, 30, 32)) & 1) * 8 + + ((ht2_f4a >> i4(x, 33, 42, 43, 45)) & 1) * 16; - return (ht2_f5c >> i5) & 1; + return (ht2_f5c >> i5) & 1; } static u64 hitag2_round(u64 *state) { - u64 x = *state; + u64 x = *state; - x = (x >> 1) - + ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) ^ (x >> 7) ^ (x >> 8) - ^ (x >> 16) ^ (x >> 22) ^ (x >> 23) ^ (x >> 26) ^ (x >> 30) - ^ (x >> 41) ^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) - & 1) << 47); + x = (x >> 1) + + ((((x >> 0) ^ (x >> 2) ^ (x >> 3) ^ (x >> 6) ^ (x >> 7) ^ (x >> 8) + ^ (x >> 16) ^ (x >> 22) ^ (x >> 23) ^ (x >> 26) ^ (x >> 30) + ^ (x >> 41) ^ (x >> 42) ^ (x >> 43) ^ (x >> 46) ^ (x >> 47)) + & 1) << 47); - *state = x; - return f20(x); + *state = x; + return f20(x); } static u64 hitag2_init(const u64 key, const u32 serial, const u32 IV) { - u32 i; - u64 x = ((key & 0xFFFF) << 32) + serial; - for (i = 0; i < 32; i++) { - x >>= 1; - x += (u64) (f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47; - } - return x; + u32 i; + u64 x = ((key & 0xFFFF) << 32) + serial; + for (i = 0; i < 32; i++) { + x >>= 1; + x += (u64) (f20(x) ^ (((IV >> i) ^ (key >> (i + 16))) & 1)) << 47; + } + return x; } static u32 hitag2_byte(u64 *x) { - u32 i, c; + u32 i, c; - for (i = 0, c = 0; i < 8; i++) - c += (u32) hitag2_round(x) << (i ^ 7); - return c; + for (i = 0, c = 0; i < 8; i++) + c += (u32) hitag2_round(x) << (i ^ 7); + return c; } // Sam7s has several timers, we will use the source TIMER_CLOCK1 (aka AT91C_TC_CLKS_TIMER_DIV1_CLOCK) // TIMER_CLOCK1 = MCK/2, MCK is running at 48 MHz, Timer is running at 48/2 = 24 MHz // Hitag units (T0) have duration of 8 microseconds (us), which is 1/125000 per second (carrier) // T0 = TIMER_CLOCK1 / 125000 = 192 -#define T0 192 +#define T0 192 -#define SHORT_COIL() LOW(GPIO_SSC_DOUT) -#define OPEN_COIL() HIGH(GPIO_SSC_DOUT) +#define SHORT_COIL() LOW(GPIO_SSC_DOUT) +#define OPEN_COIL() HIGH(GPIO_SSC_DOUT) -#define HITAG_FRAME_LEN 20 -#define HITAG_T_STOP 36 /* T_EOF should be > 36 */ -#define HITAG_T_LOW 8 /* T_LOW should be 4..10 */ -#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */ -#define HITAG_T_1_MIN 25 /* T[1] should be 26..30 */ +#define HITAG_FRAME_LEN 20 +#define HITAG_T_STOP 36 /* T_EOF should be > 36 */ +#define HITAG_T_LOW 8 /* T_LOW should be 4..10 */ +#define HITAG_T_0_MIN 15 /* T[0] should be 18..22 */ +#define HITAG_T_1_MIN 25 /* T[1] should be 26..30 */ //#define HITAG_T_EOF 40 /* T_EOF should be > 36 */ -#define HITAG_T_EOF 80 /* T_EOF should be > 36 */ -#define HITAG_T_WAIT_1 200 /* T_wresp should be 199..206 */ -#define HITAG_T_WAIT_2 90 /* T_wresp should be 199..206 */ -#define HITAG_T_WAIT_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */ +#define HITAG_T_EOF 80 /* T_EOF should be > 36 */ +#define HITAG_T_WAIT_1 200 /* T_wresp should be 199..206 */ +#define HITAG_T_WAIT_2 90 /* T_wresp should be 199..206 */ +#define HITAG_T_WAIT_MAX 300 /* bit more than HITAG_T_WAIT_1 + HITAG_T_WAIT_2 */ -#define HITAG_T_TAG_ONE_HALF_PERIOD 10 -#define HITAG_T_TAG_TWO_HALF_PERIOD 25 -#define HITAG_T_TAG_THREE_HALF_PERIOD 41 -#define HITAG_T_TAG_FOUR_HALF_PERIOD 57 +#define HITAG_T_TAG_ONE_HALF_PERIOD 10 +#define HITAG_T_TAG_TWO_HALF_PERIOD 25 +#define HITAG_T_TAG_THREE_HALF_PERIOD 41 +#define HITAG_T_TAG_FOUR_HALF_PERIOD 57 -#define HITAG_T_TAG_HALF_PERIOD 16 -#define HITAG_T_TAG_FULL_PERIOD 32 +#define HITAG_T_TAG_HALF_PERIOD 16 +#define HITAG_T_TAG_FULL_PERIOD 32 -#define HITAG_T_TAG_CAPTURE_ONE_HALF 13 -#define HITAG_T_TAG_CAPTURE_TWO_HALF 25 -#define HITAG_T_TAG_CAPTURE_THREE_HALF 41 -#define HITAG_T_TAG_CAPTURE_FOUR_HALF 57 +#define HITAG_T_TAG_CAPTURE_ONE_HALF 13 +#define HITAG_T_TAG_CAPTURE_TWO_HALF 25 +#define HITAG_T_TAG_CAPTURE_THREE_HALF 41 +#define HITAG_T_TAG_CAPTURE_FOUR_HALF 57 #define DEBUG 0 @@ -145,793 +145,793 @@ static u32 hitag2_byte(u64 *x) { * from http://www.proxmark.org/files/Documents/125%20kHz%20-%20Hitag/HitagS.V11.pdf */ void calc_crc(unsigned char * crc, unsigned char data, unsigned char Bitcount) { - *crc ^= data; // crc = crc (exor) data - do { - if (*crc & 0x80) // if (MSB-CRC == 1) - { - *crc <<= 1; // CRC = CRC Bit-shift left - *crc ^= CRC_POLYNOM; // CRC = CRC (exor) CRC_POLYNOM - } else { - *crc <<= 1; // CRC = CRC Bit-shift left - } - } while (--Bitcount); + *crc ^= data; // crc = crc (exor) data + do { + if (*crc & 0x80) // if (MSB-CRC == 1) + { + *crc <<= 1; // CRC = CRC Bit-shift left + *crc ^= CRC_POLYNOM; // CRC = CRC (exor) CRC_POLYNOM + } else { + *crc <<= 1; // CRC = CRC Bit-shift left + } + } while (--Bitcount); } static void hitag_send_bit(int bit) { - LED_A_ON(); - // Reset clock for the next bit - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + LED_A_ON(); + // Reset clock for the next bit + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - switch (m) { - case AC2K: - if (bit == 0) { - // AC Coding --__ - HIGH(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 32) {}; + switch (m) { + case AC2K: + if (bit == 0) { + // AC Coding --__ + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 32) {}; - LOW(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 64) {}; + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 64) {}; - } else { - // AC coding -_-_ - HIGH(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; + } else { + // AC coding -_-_ + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; - LOW(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 32) {}; + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 32) {}; - HIGH(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 48) {}; + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 48) {}; - LOW(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 64) {}; + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 64) {}; - } - LED_A_OFF(); - break; - case AC4K: - if (bit == 0) { - // AC Coding --__ - HIGH(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_HALF_PERIOD) {}; + } + LED_A_OFF(); + break; + case AC4K: + if (bit == 0) { + // AC Coding --__ + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_HALF_PERIOD) {}; - LOW(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_FULL_PERIOD) {}; + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * HITAG_T_TAG_FULL_PERIOD) {}; - } else { - // AC coding -_-_ - HIGH(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 8) {}; + } else { + // AC coding -_-_ + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 8) {}; - LOW(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; - HIGH(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 24) {}; + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 24) {}; - LOW(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 32) {}; - } - LED_A_OFF(); - break; - case MC4K: - if (bit == 0) { - // Manchester: Unloaded, then loaded |__--| - LOW(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 32) {}; + } + LED_A_OFF(); + break; + case MC4K: + if (bit == 0) { + // Manchester: Unloaded, then loaded |__--| + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; - HIGH(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 32) {}; + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 32) {}; - } else { - // Manchester: Loaded, then unloaded |--__| - HIGH(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; + } else { + // Manchester: Loaded, then unloaded |--__| + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; - LOW(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 32) {}; + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 32) {}; - } - LED_A_OFF(); - break; - case MC8K: - if (bit == 0) { - // Manchester: Unloaded, then loaded |__--| - LOW(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 8) {}; + } + LED_A_OFF(); + break; + case MC8K: + if (bit == 0) { + // Manchester: Unloaded, then loaded |__--| + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 8) {}; - HIGH(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; - } else { - // Manchester: Loaded, then unloaded |--__| - HIGH(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 8) {}; + } else { + // Manchester: Loaded, then unloaded |--__| + HIGH(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 8) {}; - LOW(GPIO_SSC_DOUT); - while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; + LOW(GPIO_SSC_DOUT); + while (AT91C_BASE_TC0->TC_CV < T0 * 16) {}; - } - LED_A_OFF(); - break; - default: - break; - } + } + LED_A_OFF(); + break; + default: + break; + } } static void hitag_send_frame(const byte_t* frame, size_t frame_len) { // Send start of frame - for (size_t i = 0; i < sof_bits; i++) { - hitag_send_bit(1); - } + for (size_t i = 0; i < sof_bits; i++) { + hitag_send_bit(1); + } // Send the content of the frame - for (size_t i = 0; i < frame_len; i++) { - hitag_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); - } + for (size_t i = 0; i < frame_len; i++) { + hitag_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); + } // Drop the modulation - LOW(GPIO_SSC_DOUT); + LOW(GPIO_SSC_DOUT); } static void hitag_reader_send_bit(int bit) { //Dbprintf("BIT: %d",bit); - LED_A_ON(); + LED_A_ON(); // Reset clock for the next bit - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; // Binary puls length modulation (BPLM) is used to encode the data stream // This means that a transmission of a one takes longer than that of a zero // Enable modulation, which means, drop the the field - HIGH(GPIO_SSC_DOUT); - if (test == 1) { - // Wait for 4-10 times the carrier period - while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; + HIGH(GPIO_SSC_DOUT); + if (test == 1) { + // Wait for 4-10 times the carrier period + while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; - // SpinDelayUs(8*8); + // SpinDelayUs(8*8); - // Disable modulation, just activates the field again - LOW(GPIO_SSC_DOUT); + // Disable modulation, just activates the field again + LOW(GPIO_SSC_DOUT); - if (bit == 0) { - // Zero bit: |_-| - while (AT91C_BASE_TC0->TC_CV < T0 * 11) {}; + if (bit == 0) { + // Zero bit: |_-| + while (AT91C_BASE_TC0->TC_CV < T0 * 11) {}; - // SpinDelayUs(16*8); - } else { - // One bit: |_--| - while (AT91C_BASE_TC0->TC_CV < T0 * 14) {}; + // SpinDelayUs(16*8); + } else { + // One bit: |_--| + while (AT91C_BASE_TC0->TC_CV < T0 * 14) {}; - // SpinDelayUs(22*8); - } - } else { - // Wait for 4-10 times the carrier period - while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; + // SpinDelayUs(22*8); + } + } else { + // Wait for 4-10 times the carrier period + while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; - // SpinDelayUs(8*8); + // SpinDelayUs(8*8); - // Disable modulation, just activates the field again - LOW(GPIO_SSC_DOUT); + // Disable modulation, just activates the field again + LOW(GPIO_SSC_DOUT); - if (bit == 0) { - // Zero bit: |_-| - while (AT91C_BASE_TC0->TC_CV < T0 * 22) {}; + if (bit == 0) { + // Zero bit: |_-| + while (AT91C_BASE_TC0->TC_CV < T0 * 22) {}; - // SpinDelayUs(16*8); - } else { - // One bit: |_--| - while (AT91C_BASE_TC0->TC_CV < T0 * 28) {}; + // SpinDelayUs(16*8); + } else { + // One bit: |_--| + while (AT91C_BASE_TC0->TC_CV < T0 * 28) {}; - // SpinDelayUs(22*8); - } - } + // SpinDelayUs(22*8); + } + } - LED_A_OFF(); + LED_A_OFF(); } static void hitag_reader_send_frame(const byte_t* frame, size_t frame_len) { // Send the content of the frame - for (size_t i = 0; i < frame_len; i++) { - if (frame[0] == 0xf8) { - //Dbprintf("BIT: %d",(frame[i / 8] >> (7 - (i % 8))) & 1); - } - hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); - } + for (size_t i = 0; i < frame_len; i++) { + if (frame[0] == 0xf8) { + //Dbprintf("BIT: %d",(frame[i / 8] >> (7 - (i % 8))) & 1); + } + hitag_reader_send_bit((frame[i / 8] >> (7 - (i % 8))) & 1); + } // Send EOF - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; // Enable modulation, which means, drop the the field - HIGH(GPIO_SSC_DOUT); + HIGH(GPIO_SSC_DOUT); // Wait for 4-10 times the carrier period - while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; + while (AT91C_BASE_TC0->TC_CV < T0 * 6) {}; // Disable modulation, just activates the field again - LOW(GPIO_SSC_DOUT); + LOW(GPIO_SSC_DOUT); } /* * to check if the right uid was selected */ static int check_select(byte_t* rx, uint32_t uid) { - unsigned char resp[48]; - int i; - uint32_t ans = 0x0; - for (i = 0; i < 48; i++) - resp[i] = (rx[i / 8] >> (7 - (i % 8))) & 0x1; - for (i = 0; i < 32; i++) - ans += resp[5 + i] << (31 - i); - /*if (rx[0] == 0x01 && rx[1] == 0x15 && rx[2] == 0xc1 && rx[3] == 0x14 - && rx[4] == 0x65 && rx[5] == 0x38) - Dbprintf("got uid %X", ans);*/ - temp_uid = ans; - if (ans == tag.uid) - return 1; - return 0; + unsigned char resp[48]; + int i; + uint32_t ans = 0x0; + for (i = 0; i < 48; i++) + resp[i] = (rx[i / 8] >> (7 - (i % 8))) & 0x1; + for (i = 0; i < 32; i++) + ans += resp[5 + i] << (31 - i); + /*if (rx[0] == 0x01 && rx[1] == 0x15 && rx[2] == 0xc1 && rx[3] == 0x14 + && rx[4] == 0x65 && rx[5] == 0x38) + Dbprintf("got uid %X", ans);*/ + temp_uid = ans; + if (ans == tag.uid) + return 1; + return 0; } /* * handles all commands from a reader */ static void hitagS_handle_reader_command(byte_t* rx, const size_t rxlen, - byte_t* tx, size_t* txlen) { - byte_t rx_air[HITAG_FRAME_LEN]; - byte_t page; - int i; - u64 state; - unsigned char crc; + byte_t* tx, size_t* txlen) { + byte_t rx_air[HITAG_FRAME_LEN]; + byte_t page; + int i; + u64 state; + unsigned char crc; // Copy the (original) received frame how it is send over the air - memcpy(rx_air, rx, nbytes(rxlen)); + memcpy(rx_air, rx, nbytes(rxlen)); // Reset the transmission frame length - *txlen = 0; + *txlen = 0; // Try to find out which command was send by selecting on length (in bits) - switch (rxlen) { - case 5: { - //UID request with a selected response protocol mode - tag.pstate = HT_READY; - tag.tstate = HT_NO_OP; - if ((rx[0] & 0xf0) == 0x30) { - tag.mode = HT_STANDARD; - sof_bits = 1; - m = AC2K; - } - if ((rx[0] & 0xf0) == 0xc0) { - tag.mode = HT_ADVANCED; - sof_bits = 3; - m = AC2K; - } + switch (rxlen) { + case 5: { + //UID request with a selected response protocol mode + tag.pstate = HT_READY; + tag.tstate = HT_NO_OP; + if ((rx[0] & 0xf0) == 0x30) { + tag.mode = HT_STANDARD; + sof_bits = 1; + m = AC2K; + } + if ((rx[0] & 0xf0) == 0xc0) { + tag.mode = HT_ADVANCED; + sof_bits = 3; + m = AC2K; + } - if ((rx[0] & 0xf0) == 0xd0) { - tag.mode = HT_FAST_ADVANCED; - sof_bits = 3; - m = AC4K; - } - //send uid as a response - *txlen = 32; - for (i = 0; i < 4; i++) - tx[i] = (tag.uid >> (24 - (i * 8))) & 0xff; - } - break; - case 45: { - //select command from reader received - if (check_select(rx, tag.uid) == 1) { - //if the right tag was selected - *txlen = 32; - switch (tag.mode) { - case HT_STANDARD: - sof_bits = 1; - m = MC4K; - break; - case HT_ADVANCED: - sof_bits = 6; - m = MC4K; - break; - case HT_FAST_ADVANCED: - sof_bits = 6; - m = MC8K; - break; - default: - break; - } + if ((rx[0] & 0xf0) == 0xd0) { + tag.mode = HT_FAST_ADVANCED; + sof_bits = 3; + m = AC4K; + } + //send uid as a response + *txlen = 32; + for (i = 0; i < 4; i++) + tx[i] = (tag.uid >> (24 - (i * 8))) & 0xff; + } + break; + case 45: { + //select command from reader received + if (check_select(rx, tag.uid) == 1) { + //if the right tag was selected + *txlen = 32; + switch (tag.mode) { + case HT_STANDARD: + sof_bits = 1; + m = MC4K; + break; + case HT_ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case HT_FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } - //send configuration - for (i = 0; i < 4; i++) - tx[i] = (tag.pages[0][1] >> (i * 8)) & 0xff; - tx[3] = 0xff; - if (tag.mode != HT_STANDARD) { - *txlen = 40; - crc = CRC_PRESET; - for (i = 0; i < 4; i++) - calc_crc(&crc, tx[i], 8); - tx[4] = crc; - } - } - } - break; - case 64: { - //challenge message received - Dbprintf("Challenge for UID: %X", temp_uid); - temp2++; - *txlen = 32; - state = hitag2_init(rev64(tag.key), rev32(tag.pages[0][0]), - rev32(((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0]))); - Dbprintf( - ",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}", - rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]); - switch (tag.mode) { - case HT_STANDARD: - sof_bits = 1; - m = MC4K; - break; - case HT_ADVANCED: - sof_bits = 6; - m = MC4K; - break; - case HT_FAST_ADVANCED: - sof_bits = 6; - m = MC8K; - break; - default: - break; - } + //send configuration + for (i = 0; i < 4; i++) + tx[i] = (tag.pages[0][1] >> (i * 8)) & 0xff; + tx[3] = 0xff; + if (tag.mode != HT_STANDARD) { + *txlen = 40; + crc = CRC_PRESET; + for (i = 0; i < 4; i++) + calc_crc(&crc, tx[i], 8); + tx[4] = crc; + } + } + } + break; + case 64: { + //challenge message received + Dbprintf("Challenge for UID: %X", temp_uid); + temp2++; + *txlen = 32; + state = hitag2_init(rev64(tag.key), rev32(tag.pages[0][0]), + rev32(((rx[3] << 24) + (rx[2] << 16) + (rx[1] << 8) + rx[0]))); + Dbprintf( + ",{0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X, 0x%02X}", + rx[0], rx[1], rx[2], rx[3], rx[4], rx[5], rx[6], rx[7]); + switch (tag.mode) { + case HT_STANDARD: + sof_bits = 1; + m = MC4K; + break; + case HT_ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case HT_FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } - for (i = 0; i < 4; i++) - hitag2_byte(&state); - //send con2,pwdh0,pwdl0,pwdl1 encrypted as a response - tx[0] = hitag2_byte(&state) ^ ((tag.pages[0][1] >> 16) & 0xff); - tx[1] = hitag2_byte(&state) ^ tag.pwdh0; - tx[2] = hitag2_byte(&state) ^ tag.pwdl0; - tx[3] = hitag2_byte(&state) ^ tag.pwdl1; - if (tag.mode != HT_STANDARD) { - //add crc8 - *txlen = 40; - crc = CRC_PRESET; - calc_crc(&crc, ((tag.pages[0][1] >> 16) & 0xff), 8); - calc_crc(&crc, tag.pwdh0, 8); - calc_crc(&crc, tag.pwdl0, 8); - calc_crc(&crc, tag.pwdl1, 8); - tx[4] = (crc ^ hitag2_byte(&state)); - } - /* - * some readers do not allow to authenticate multiple times in a row with the same tag. - * use this to change the uid between authentications. - */ + for (i = 0; i < 4; i++) + hitag2_byte(&state); + //send con2,pwdh0,pwdl0,pwdl1 encrypted as a response + tx[0] = hitag2_byte(&state) ^ ((tag.pages[0][1] >> 16) & 0xff); + tx[1] = hitag2_byte(&state) ^ tag.pwdh0; + tx[2] = hitag2_byte(&state) ^ tag.pwdl0; + tx[3] = hitag2_byte(&state) ^ tag.pwdl1; + if (tag.mode != HT_STANDARD) { + //add crc8 + *txlen = 40; + crc = CRC_PRESET; + calc_crc(&crc, ((tag.pages[0][1] >> 16) & 0xff), 8); + calc_crc(&crc, tag.pwdh0, 8); + calc_crc(&crc, tag.pwdl0, 8); + calc_crc(&crc, tag.pwdl1, 8); + tx[4] = (crc ^ hitag2_byte(&state)); + } + /* + * some readers do not allow to authenticate multiple times in a row with the same tag. + * use this to change the uid between authentications. + */ - /* - if (temp2 % 2 == 0) { - tag.uid = 0x11223344; - tag.pages[0][0] = 0x44332211; - } else { - tag.uid = 0x55667788; - tag.pages[0][0] = 0x88776655; - } - */ - } - case 40: - //data received to be written - if (tag.tstate == HT_WRITING_PAGE_DATA) { - tag.tstate = HT_NO_OP; - tag.pages[page_to_be_written / 4][page_to_be_written % 4] = (rx[0] - << 0) + (rx[1] << 8) + (rx[2] << 16) + (rx[3] << 24); - //send ack - *txlen = 2; - tx[0] = 0x40; - page_to_be_written = 0; - switch (tag.mode) { - case HT_STANDARD: - sof_bits = 1; - m = MC4K; - break; - case HT_ADVANCED: - sof_bits = 6; - m = MC4K; - break; - case HT_FAST_ADVANCED: - sof_bits = 6; - m = MC8K; - break; - default: - break; - } - } else if (tag.tstate == HT_WRITING_BLOCK_DATA) { - tag.pages[page_to_be_written / 4][page_to_be_written % 4] = (rx[0] - << 24) + (rx[1] << 16) + (rx[2] << 8) + rx[3]; - //send ack - *txlen = 2; - tx[0] = 0x40; - switch (tag.mode) { - case HT_STANDARD: - sof_bits = 1; - m = MC4K; - break; - case HT_ADVANCED: - sof_bits = 6; - m = MC4K; - break; - case HT_FAST_ADVANCED: - sof_bits = 6; - m = MC8K; - break; - default: - break; - } - page_to_be_written++; - block_data_left--; - if (block_data_left == 0) { - tag.tstate = HT_NO_OP; - page_to_be_written = 0; - } - } - break; - case 20: { - //write page, write block, read page or read block command received - if ((rx[0] & 0xf0) == 0xc0) //read page - { - //send page data - page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16); - *txlen = 32; - tx[0] = (tag.pages[page / 4][page % 4]) & 0xff; - tx[1] = (tag.pages[page / 4][page % 4] >> 8) & 0xff; - tx[2] = (tag.pages[page / 4][page % 4] >> 16) & 0xff; - tx[3] = (tag.pages[page / 4][page % 4] >> 24) & 0xff; - if (tag.LKP && page == 1) - tx[3] = 0xff; + /* + if (temp2 % 2 == 0) { + tag.uid = 0x11223344; + tag.pages[0][0] = 0x44332211; + } else { + tag.uid = 0x55667788; + tag.pages[0][0] = 0x88776655; + } + */ + } + case 40: + //data received to be written + if (tag.tstate == HT_WRITING_PAGE_DATA) { + tag.tstate = HT_NO_OP; + tag.pages[page_to_be_written / 4][page_to_be_written % 4] = (rx[0] + << 0) + (rx[1] << 8) + (rx[2] << 16) + (rx[3] << 24); + //send ack + *txlen = 2; + tx[0] = 0x40; + page_to_be_written = 0; + switch (tag.mode) { + case HT_STANDARD: + sof_bits = 1; + m = MC4K; + break; + case HT_ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case HT_FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } + } else if (tag.tstate == HT_WRITING_BLOCK_DATA) { + tag.pages[page_to_be_written / 4][page_to_be_written % 4] = (rx[0] + << 24) + (rx[1] << 16) + (rx[2] << 8) + rx[3]; + //send ack + *txlen = 2; + tx[0] = 0x40; + switch (tag.mode) { + case HT_STANDARD: + sof_bits = 1; + m = MC4K; + break; + case HT_ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case HT_FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } + page_to_be_written++; + block_data_left--; + if (block_data_left == 0) { + tag.tstate = HT_NO_OP; + page_to_be_written = 0; + } + } + break; + case 20: { + //write page, write block, read page or read block command received + if ((rx[0] & 0xf0) == 0xc0) //read page + { + //send page data + page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16); + *txlen = 32; + tx[0] = (tag.pages[page / 4][page % 4]) & 0xff; + tx[1] = (tag.pages[page / 4][page % 4] >> 8) & 0xff; + tx[2] = (tag.pages[page / 4][page % 4] >> 16) & 0xff; + tx[3] = (tag.pages[page / 4][page % 4] >> 24) & 0xff; + if (tag.LKP && page == 1) + tx[3] = 0xff; - switch (tag.mode) { - case HT_STANDARD: - sof_bits = 1; - m = MC4K; - break; - case HT_ADVANCED: - sof_bits = 6; - m = MC4K; - break; - case HT_FAST_ADVANCED: - sof_bits = 6; - m = MC8K; - break; - default: - break; - } + switch (tag.mode) { + case HT_STANDARD: + sof_bits = 1; + m = MC4K; + break; + case HT_ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case HT_FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } - if (tag.mode != HT_STANDARD) { - //add crc8 - *txlen = 40; - crc = CRC_PRESET; - for (i = 0; i < 4; i++) - calc_crc(&crc, tx[i], 8); - tx[4] = crc; - } + if (tag.mode != HT_STANDARD) { + //add crc8 + *txlen = 40; + crc = CRC_PRESET; + for (i = 0; i < 4; i++) + calc_crc(&crc, tx[i], 8); + tx[4] = crc; + } - if (tag.LKP && (page == 2 || page == 3)) { - //if reader asks for key or password and the LKP-mark is set do not respond - sof_bits = 0; - *txlen = 0; - } - } else if ((rx[0] & 0xf0) == 0xd0) //read block - { - page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16); - *txlen = 32 * 4; - //send page,...,page+3 data - for (i = 0; i < 4; i++) { - tx[0 + i * 4] = (tag.pages[page / 4][page % 4]) & 0xff; - tx[1 + i * 4] = (tag.pages[page / 4][page % 4] >> 8) & 0xff; - tx[2 + i * 4] = (tag.pages[page / 4][page % 4] >> 16) & 0xff; - tx[3 + i * 4] = (tag.pages[page / 4][page % 4] >> 24) & 0xff; - page++; - } + if (tag.LKP && (page == 2 || page == 3)) { + //if reader asks for key or password and the LKP-mark is set do not respond + sof_bits = 0; + *txlen = 0; + } + } else if ((rx[0] & 0xf0) == 0xd0) //read block + { + page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16); + *txlen = 32 * 4; + //send page,...,page+3 data + for (i = 0; i < 4; i++) { + tx[0 + i * 4] = (tag.pages[page / 4][page % 4]) & 0xff; + tx[1 + i * 4] = (tag.pages[page / 4][page % 4] >> 8) & 0xff; + tx[2 + i * 4] = (tag.pages[page / 4][page % 4] >> 16) & 0xff; + tx[3 + i * 4] = (tag.pages[page / 4][page % 4] >> 24) & 0xff; + page++; + } - switch (tag.mode) { - case HT_STANDARD: - sof_bits = 1; - m = MC4K; - break; - case HT_ADVANCED: - sof_bits = 6; - m = MC4K; - break; - case HT_FAST_ADVANCED: - sof_bits = 6; - m = MC8K; - break; - default: - break; - } + switch (tag.mode) { + case HT_STANDARD: + sof_bits = 1; + m = MC4K; + break; + case HT_ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case HT_FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } - if (tag.mode != HT_STANDARD) { - //add crc8 - *txlen = 32 * 4 + 8; - crc = CRC_PRESET; - for (i = 0; i < 16; i++) - calc_crc(&crc, tx[i], 8); - tx[16] = crc; - } + if (tag.mode != HT_STANDARD) { + //add crc8 + *txlen = 32 * 4 + 8; + crc = CRC_PRESET; + for (i = 0; i < 16; i++) + calc_crc(&crc, tx[i], 8); + tx[16] = crc; + } - if ((page - 4) % 4 != 0 || (tag.LKP && (page - 4) == 0)) { - sof_bits = 0; - *txlen = 0; - } - } else if ((rx[0] & 0xf0) == 0x80) //write page - { - page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16); + if ((page - 4) % 4 != 0 || (tag.LKP && (page - 4) == 0)) { + sof_bits = 0; + *txlen = 0; + } + } else if ((rx[0] & 0xf0) == 0x80) //write page + { + page = ((rx[0] & 0x0f) * 16) + ((rx[1] & 0xf0) / 16); - switch (tag.mode) { - case HT_STANDARD: - sof_bits = 1; - m = MC4K; - break; - case HT_ADVANCED: - sof_bits = 6; - m = MC4K; - break; - case HT_FAST_ADVANCED: - sof_bits = 6; - m = MC8K; - break; - default: - break; - } - if ((tag.LCON && page == 1) - || (tag.LKP && (page == 2 || page == 3))) { - //deny - *txlen = 0; - } else { - //allow - *txlen = 2; - tx[0] = 0x40; - page_to_be_written = page; - tag.tstate = HT_WRITING_PAGE_DATA; - } + switch (tag.mode) { + case HT_STANDARD: + sof_bits = 1; + m = MC4K; + break; + case HT_ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case HT_FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } + if ((tag.LCON && page == 1) + || (tag.LKP && (page == 2 || page == 3))) { + //deny + *txlen = 0; + } else { + //allow + *txlen = 2; + tx[0] = 0x40; + page_to_be_written = page; + tag.tstate = HT_WRITING_PAGE_DATA; + } - } else if ((rx[0] & 0xf0) == 0x90) //write block - { - page = ((rx[0] & 0x0f) * 6) + ((rx[1] & 0xf0) / 16); - switch (tag.mode) { - case HT_STANDARD: - sof_bits = 1; - m = MC4K; - break; - case HT_ADVANCED: - sof_bits = 6; - m = MC4K; - break; - case HT_FAST_ADVANCED: - sof_bits = 6; - m = MC8K; - break; - default: - break; - } - if (page % 4 != 0 || page == 0) { - //deny - *txlen = 0; - } else { - //allow - *txlen = 2; - tx[0] = 0x40; - page_to_be_written = page; - block_data_left = 4; - tag.tstate = HT_WRITING_BLOCK_DATA; - } - } - } - break; - default: + } else if ((rx[0] & 0xf0) == 0x90) //write block + { + page = ((rx[0] & 0x0f) * 6) + ((rx[1] & 0xf0) / 16); + switch (tag.mode) { + case HT_STANDARD: + sof_bits = 1; + m = MC4K; + break; + case HT_ADVANCED: + sof_bits = 6; + m = MC4K; + break; + case HT_FAST_ADVANCED: + sof_bits = 6; + m = MC8K; + break; + default: + break; + } + if (page % 4 != 0 || page == 0) { + //deny + *txlen = 0; + } else { + //allow + *txlen = 2; + tx[0] = 0x40; + page_to_be_written = page; + block_data_left = 4; + tag.tstate = HT_WRITING_BLOCK_DATA; + } + } + } + break; + default: - break; - } + break; + } } /* * to autenticate to a tag with the given key or challenge */ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr, byte_t* rx, const size_t rxlen, byte_t* tx, - size_t* txlen) { - byte_t rx_air[HITAG_FRAME_LEN]; - int response_bit[200]; - int i, j, z, k; - unsigned char mask = 1; - unsigned char uid[32]; - byte_t uid1 = 0x00, uid2 = 0x00, uid3 = 0x00, uid4 = 0x00; - unsigned char crc; - u64 state; - byte_t auth_ks[4]; - byte_t conf_pages[3]; - memcpy(rx_air, rx, nbytes(rxlen)); - *txlen = 0; + size_t* txlen) { + byte_t rx_air[HITAG_FRAME_LEN]; + int response_bit[200]; + int i, j, z, k; + unsigned char mask = 1; + unsigned char uid[32]; + byte_t uid1 = 0x00, uid2 = 0x00, uid3 = 0x00, uid4 = 0x00; + unsigned char crc; + u64 state; + byte_t auth_ks[4]; + byte_t conf_pages[3]; + memcpy(rx_air, rx, nbytes(rxlen)); + *txlen = 0; - if (tag.pstate == HT_READY && rxlen >= 67) { - //received uid - if(end==true) { - Dbprintf("authentication failed!"); - return -1; - } - z = 0; - for (i = 0; i < 10; i++) { - for (j = 0; j < 8; j++) { - response_bit[z] = 0; - if ((rx[i] & ((mask << 7) >> j)) != 0) - response_bit[z] = 1; - z++; - } - } - k = 0; - for (i = 5; i < z; i += 2) { - uid[k] = response_bit[i]; - k++; - if (k > 31) - break; - } - uid1 = (uid[0] << 7) | (uid[1] << 6) | (uid[2] << 5) | (uid[3] << 4) - | (uid[4] << 3) | (uid[5] << 2) | (uid[6] << 1) | uid[7]; - uid2 = (uid[8] << 7) | (uid[9] << 6) | (uid[10] << 5) | (uid[11] << 4) - | (uid[12] << 3) | (uid[13] << 2) | (uid[14] << 1) | uid[15]; - uid3 = (uid[16] << 7) | (uid[17] << 6) | (uid[18] << 5) | (uid[19] << 4) - | (uid[20] << 3) | (uid[21] << 2) | (uid[22] << 1) | uid[23]; - uid4 = (uid[24] << 7) | (uid[25] << 6) | (uid[26] << 5) | (uid[27] << 4) - | (uid[28] << 3) | (uid[29] << 2) | (uid[30] << 1) | uid[31]; - if (DEBUG) - Dbprintf("UID: %02X %02X %02X %02X", uid1, uid2, uid3, uid4); - tag.uid = (uid4 << 24 | uid3 << 16 | uid2 << 8 | uid1); + if (tag.pstate == HT_READY && rxlen >= 67) { + //received uid + if(end==true) { + Dbprintf("authentication failed!"); + return -1; + } + z = 0; + for (i = 0; i < 10; i++) { + for (j = 0; j < 8; j++) { + response_bit[z] = 0; + if ((rx[i] & ((mask << 7) >> j)) != 0) + response_bit[z] = 1; + z++; + } + } + k = 0; + for (i = 5; i < z; i += 2) { + uid[k] = response_bit[i]; + k++; + if (k > 31) + break; + } + uid1 = (uid[0] << 7) | (uid[1] << 6) | (uid[2] << 5) | (uid[3] << 4) + | (uid[4] << 3) | (uid[5] << 2) | (uid[6] << 1) | uid[7]; + uid2 = (uid[8] << 7) | (uid[9] << 6) | (uid[10] << 5) | (uid[11] << 4) + | (uid[12] << 3) | (uid[13] << 2) | (uid[14] << 1) | uid[15]; + uid3 = (uid[16] << 7) | (uid[17] << 6) | (uid[18] << 5) | (uid[19] << 4) + | (uid[20] << 3) | (uid[21] << 2) | (uid[22] << 1) | uid[23]; + uid4 = (uid[24] << 7) | (uid[25] << 6) | (uid[26] << 5) | (uid[27] << 4) + | (uid[28] << 3) | (uid[29] << 2) | (uid[30] << 1) | uid[31]; + if (DEBUG) + Dbprintf("UID: %02X %02X %02X %02X", uid1, uid2, uid3, uid4); + tag.uid = (uid4 << 24 | uid3 << 16 | uid2 << 8 | uid1); - //select uid - *txlen = 45; - crc = CRC_PRESET; - calc_crc(&crc, 0x00, 5); - calc_crc(&crc, uid1, 8); - calc_crc(&crc, uid2, 8); - calc_crc(&crc, uid3, 8); - calc_crc(&crc, uid4, 8); - for (i = 0; i < 100; i++) { - response_bit[i] = 0; - } - for (i = 0; i < 5; i++) { - response_bit[i] = 0; - } - for (i = 5; i < 37; i++) { - response_bit[i] = uid[i - 5]; - } - for (j = 0; j < 8; j++) { - response_bit[i] = 0; - if ((crc & ((mask << 7) >> j)) != 0) - response_bit[i] = 1; - i++; - } - k = 0; - for (i = 0; i < 6; i++) { - tx[i] = (response_bit[k] << 7) | (response_bit[k + 1] << 6) - | (response_bit[k + 2] << 5) | (response_bit[k + 3] << 4) - | (response_bit[k + 4] << 3) | (response_bit[k + 5] << 2) - | (response_bit[k + 6] << 1) | response_bit[k + 7]; - k += 8; - } - tag.pstate = HT_INIT; - } else if (tag.pstate == HT_INIT && rxlen == 44) { - // received configuration after select command - z = 0; - for (i = 0; i < 6; i++) { - for (j = 0; j < 8; j++) { - response_bit[z] = 0; - if ((rx[i] & ((mask << 7) >> j)) != 0) - response_bit[z] = 1; - z++; - } - } - conf_pages[0] = ((response_bit[4] << 7) | (response_bit[5] << 6) - | (response_bit[6] << 5) | (response_bit[7] << 4) - | (response_bit[8] << 3) | (response_bit[9] << 2) - | (response_bit[10] << 1) | response_bit[11]); - //check wich memorysize this tag has - if (response_bit[10] == 0 && response_bit[11] == 0) - tag.max_page = 32 / 32; - if (response_bit[10] == 0 && response_bit[11] == 1) - tag.max_page = 256 / 32; - if (response_bit[10] == 1 && response_bit[11] == 0) - tag.max_page = 2048 / 32; - conf_pages[1] = ((response_bit[12] << 7) | (response_bit[13] << 6) - | (response_bit[14] << 5) | (response_bit[15] << 4) - | (response_bit[16] << 3) | (response_bit[17] << 2) - | (response_bit[18] << 1) | response_bit[19]); - tag.auth = response_bit[12]; - tag.TTFC = response_bit[13]; - //tag.TTFDR in response_bit[14] and response_bit[15] - //tag.TTFM in response_bit[16] and response_bit[17] - tag.LCON = response_bit[18]; - tag.LKP = response_bit[19]; - conf_pages[2] = ((response_bit[20] << 7) | (response_bit[21] << 6) - | (response_bit[22] << 5) | (response_bit[23] << 4) - | (response_bit[24] << 3) | (response_bit[25] << 2) - | (response_bit[26] << 1) | response_bit[27]); - tag.LCK7 = response_bit[20]; - tag.LCK6 = response_bit[21]; - tag.LCK5 = response_bit[22]; - tag.LCK4 = response_bit[23]; - tag.LCK3 = response_bit[24]; - tag.LCK2 = response_bit[25]; - tag.LCK1 = response_bit[26]; - tag.LCK0 = response_bit[27]; + //select uid + *txlen = 45; + crc = CRC_PRESET; + calc_crc(&crc, 0x00, 5); + calc_crc(&crc, uid1, 8); + calc_crc(&crc, uid2, 8); + calc_crc(&crc, uid3, 8); + calc_crc(&crc, uid4, 8); + for (i = 0; i < 100; i++) { + response_bit[i] = 0; + } + for (i = 0; i < 5; i++) { + response_bit[i] = 0; + } + for (i = 5; i < 37; i++) { + response_bit[i] = uid[i - 5]; + } + for (j = 0; j < 8; j++) { + response_bit[i] = 0; + if ((crc & ((mask << 7) >> j)) != 0) + response_bit[i] = 1; + i++; + } + k = 0; + for (i = 0; i < 6; i++) { + tx[i] = (response_bit[k] << 7) | (response_bit[k + 1] << 6) + | (response_bit[k + 2] << 5) | (response_bit[k + 3] << 4) + | (response_bit[k + 4] << 3) | (response_bit[k + 5] << 2) + | (response_bit[k + 6] << 1) | response_bit[k + 7]; + k += 8; + } + tag.pstate = HT_INIT; + } else if (tag.pstate == HT_INIT && rxlen == 44) { + // received configuration after select command + z = 0; + for (i = 0; i < 6; i++) { + for (j = 0; j < 8; j++) { + response_bit[z] = 0; + if ((rx[i] & ((mask << 7) >> j)) != 0) + response_bit[z] = 1; + z++; + } + } + conf_pages[0] = ((response_bit[4] << 7) | (response_bit[5] << 6) + | (response_bit[6] << 5) | (response_bit[7] << 4) + | (response_bit[8] << 3) | (response_bit[9] << 2) + | (response_bit[10] << 1) | response_bit[11]); + //check wich memorysize this tag has + if (response_bit[10] == 0 && response_bit[11] == 0) + tag.max_page = 32 / 32; + if (response_bit[10] == 0 && response_bit[11] == 1) + tag.max_page = 256 / 32; + if (response_bit[10] == 1 && response_bit[11] == 0) + tag.max_page = 2048 / 32; + conf_pages[1] = ((response_bit[12] << 7) | (response_bit[13] << 6) + | (response_bit[14] << 5) | (response_bit[15] << 4) + | (response_bit[16] << 3) | (response_bit[17] << 2) + | (response_bit[18] << 1) | response_bit[19]); + tag.auth = response_bit[12]; + tag.TTFC = response_bit[13]; + //tag.TTFDR in response_bit[14] and response_bit[15] + //tag.TTFM in response_bit[16] and response_bit[17] + tag.LCON = response_bit[18]; + tag.LKP = response_bit[19]; + conf_pages[2] = ((response_bit[20] << 7) | (response_bit[21] << 6) + | (response_bit[22] << 5) | (response_bit[23] << 4) + | (response_bit[24] << 3) | (response_bit[25] << 2) + | (response_bit[26] << 1) | response_bit[27]); + tag.LCK7 = response_bit[20]; + tag.LCK6 = response_bit[21]; + tag.LCK5 = response_bit[22]; + tag.LCK4 = response_bit[23]; + tag.LCK3 = response_bit[24]; + tag.LCK2 = response_bit[25]; + tag.LCK1 = response_bit[26]; + tag.LCK0 = response_bit[27]; - if (DEBUG) - Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0], - conf_pages[1], conf_pages[2]); - if (tag.auth == 1) { - //if the tag is in authentication mode try the key or challenge - *txlen = 64; - if(end!=true){ - if(htf==02||htf==04){ //RHTS_KEY //WHTS_KEY - state = hitag2_init(rev64(key), rev32(tag.uid), - rev32(rnd)); + if (DEBUG) + Dbprintf("conf0: %02X conf1: %02X conf2: %02X", conf_pages[0], + conf_pages[1], conf_pages[2]); + if (tag.auth == 1) { + //if the tag is in authentication mode try the key or challenge + *txlen = 64; + if(end!=true){ + if(htf==02||htf==04){ //RHTS_KEY //WHTS_KEY + state = hitag2_init(rev64(key), rev32(tag.uid), + rev32(rnd)); - for (i = 0; i < 4; i++) { - auth_ks[i] = hitag2_byte(&state) ^ 0xff; - } - *txlen = 64; - tx[0] = rnd & 0xff; - tx[1] = (rnd >> 8) & 0xff; - tx[2] = (rnd >> 16) & 0xff; - tx[3] = (rnd >> 24) & 0xff; + for (i = 0; i < 4; i++) { + auth_ks[i] = hitag2_byte(&state) ^ 0xff; + } + *txlen = 64; + tx[0] = rnd & 0xff; + tx[1] = (rnd >> 8) & 0xff; + tx[2] = (rnd >> 16) & 0xff; + tx[3] = (rnd >> 24) & 0xff; - tx[4] = auth_ks[0]; - tx[5] = auth_ks[1]; - tx[6] = auth_ks[2]; - tx[7] = auth_ks[3]; - if (DEBUG) - Dbprintf("%02X %02X %02X %02X %02X %02X %02X %02X", tx[0], - tx[1], tx[2], tx[3], tx[4], tx[5], tx[6], tx[7]); - } else if(htf==01 || htf==03) { //RHTS_CHALLENGE //WHTS_CHALLENGE - for (i = 0; i < 8; i++) - tx[i]=((NrAr>>(56-(i*8)))&0xff); - } - end=true; - tag.pstate = HT_AUTHENTICATE; - } else { - Dbprintf("authentication failed!"); - return -1; - } - } else if (tag.auth == 0) { - tag.pstate = HT_SELECTED; - } + tx[4] = auth_ks[0]; + tx[5] = auth_ks[1]; + tx[6] = auth_ks[2]; + tx[7] = auth_ks[3]; + if (DEBUG) + Dbprintf("%02X %02X %02X %02X %02X %02X %02X %02X", tx[0], + tx[1], tx[2], tx[3], tx[4], tx[5], tx[6], tx[7]); + } else if(htf==01 || htf==03) { //RHTS_CHALLENGE //WHTS_CHALLENGE + for (i = 0; i < 8; i++) + tx[i]=((NrAr>>(56-(i*8)))&0xff); + } + end=true; + tag.pstate = HT_AUTHENTICATE; + } else { + Dbprintf("authentication failed!"); + return -1; + } + } else if (tag.auth == 0) { + tag.pstate = HT_SELECTED; + } - } else if (tag.pstate == HT_AUTHENTICATE && rxlen == 44) { - //encrypted con2,password received. - crc = CRC_PRESET; - calc_crc(&crc, 0x80, 1); - calc_crc(&crc, ((rx[0] & 0x0f) * 16 + ((rx[1] & 0xf0) / 16)), 8); - calc_crc(&crc, ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)), 8); - calc_crc(&crc, ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)), 8); - calc_crc(&crc, ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)), 8); - if (DEBUG) { - Dbprintf("UID:::%X", tag.uid); - Dbprintf("RND:::%X", rnd); - } + } else if (tag.pstate == HT_AUTHENTICATE && rxlen == 44) { + //encrypted con2,password received. + crc = CRC_PRESET; + calc_crc(&crc, 0x80, 1); + calc_crc(&crc, ((rx[0] & 0x0f) * 16 + ((rx[1] & 0xf0) / 16)), 8); + calc_crc(&crc, ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)), 8); + calc_crc(&crc, ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)), 8); + calc_crc(&crc, ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)), 8); + if (DEBUG) { + Dbprintf("UID:::%X", tag.uid); + Dbprintf("RND:::%X", rnd); + } - //decrypt password - pwdh0=0; - pwdl0=0; - pwdl1=0; - if(htf==02 || htf==04){ //RHTS_KEY //WHTS_KEY - { - state = hitag2_init(rev64(key), rev32(tag.uid), rev32(rnd)); - for (i = 0; i < 5; i++) - hitag2_byte(&state); - pwdh0 = ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)) - ^ hitag2_byte(&state); - pwdl0 = ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)) - ^ hitag2_byte(&state); - pwdl1 = ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)) - ^ hitag2_byte(&state); - } + //decrypt password + pwdh0=0; + pwdl0=0; + pwdl1=0; + if(htf==02 || htf==04){ //RHTS_KEY //WHTS_KEY + { + state = hitag2_init(rev64(key), rev32(tag.uid), rev32(rnd)); + for (i = 0; i < 5; i++) + hitag2_byte(&state); + pwdh0 = ((rx[1] & 0x0f) * 16 + ((rx[2] & 0xf0) / 16)) + ^ hitag2_byte(&state); + pwdl0 = ((rx[2] & 0x0f) * 16 + ((rx[3] & 0xf0) / 16)) + ^ hitag2_byte(&state); + pwdl1 = ((rx[3] & 0x0f) * 16 + ((rx[4] & 0xf0) / 16)) + ^ hitag2_byte(&state); + } - if (DEBUG) - Dbprintf("pwdh0 %02X pwdl0 %02X pwdl1 %02X", pwdh0, pwdl0, pwdl1); + if (DEBUG) + Dbprintf("pwdh0 %02X pwdl0 %02X pwdl1 %02X", pwdh0, pwdl0, pwdl1); - //Dbprintf("%X %02X", rnd, ((rx[4] & 0x0f) * 16) + ((rx[5] & 0xf0) / 16)); - //rnd += 1; - } - tag.pstate = HT_SELECTED; //tag is now ready for read/write commands - } - return 0; + //Dbprintf("%X %02X", rnd, ((rx[4] & 0x0f) * 16) + ((rx[5] & 0xf0) / 16)); + //rnd += 1; + } + tag.pstate = HT_SELECTED; //tag is now ready for read/write commands + } + return 0; } @@ -939,223 +939,223 @@ static int hitagS_handle_tag_auth(hitag_function htf,uint64_t key, uint64_t NrAr * Emulates a Hitag S Tag with the given data from the .hts file */ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) { - int frame_count; - int response; - int overflow; - int i, j; - byte_t rx[HITAG_FRAME_LEN]; - size_t rxlen = 0; - //bool bQuitTraceFull = false; - bQuiet = false; - byte_t txbuf[HITAG_FRAME_LEN]; - byte_t* tx = txbuf; - size_t txlen = 0; - // free eventually allocated BigBuf memory - BigBuf_free(); BigBuf_Clear_ext(false); + int frame_count; + int response; + int overflow; + int i, j; + byte_t rx[HITAG_FRAME_LEN]; + size_t rxlen = 0; + //bool bQuitTraceFull = false; + bQuiet = false; + byte_t txbuf[HITAG_FRAME_LEN]; + byte_t* tx = txbuf; + size_t txlen = 0; + // free eventually allocated BigBuf memory + BigBuf_free(); BigBuf_Clear_ext(false); - // Clean up trace and prepare it for storing frames - set_tracing(true); - clear_trace(); + // Clean up trace and prepare it for storing frames + set_tracing(true); + clear_trace(); - DbpString("Starting HitagS simulation"); - LED_D_ON(); + DbpString("Starting HitagS simulation"); + LED_D_ON(); - tag.pstate = HT_READY; - tag.tstate = HT_NO_OP; - for (i = 0; i < 16; i++) - for (j = 0; j < 4; j++) - tag.pages[i][j] = 0x0; - //read tag data into memory - if (tag_mem_supplied) { - DbpString("Loading hitagS memory..."); - memcpy((byte_t*)tag.pages,data,4*64); - } - tag.uid=(uint32_t)tag.pages[0]; - Dbprintf("Hitag S simulation started"); - tag.key=(intptr_t)tag.pages[3]; - tag.key<<=16; - tag.key+=((tag.pages[2][0])<<8)+tag.pages[2][1]; - tag.pwdl0=tag.pages[2][3]; - tag.pwdl1=tag.pages[2][2]; - tag.pwdh0=tag.pages[1][0]; - //con0 - tag.max_page=64; - if((tag.pages[1][3]&0x2)==0 && (tag.pages[1][3]&0x1)==1) - tag.max_page=8; - if((tag.pages[1][3]&0x2)==0 && (tag.pages[1][3]&0x1)==0) - tag.max_page=0; - //con1 - tag.auth=0; - if((tag.pages[1][2]&0x80) == 0x80) - tag.auth=1; - tag.LCON=0; - if((tag.pages[1][2]&0x2) == 0x02) - tag.LCON=1; - tag.LKP=0; - if((tag.pages[1][2]&0x1) == 0x01) - tag.LKP=1; - //con2 - //0=read write 1=read only - tag.LCK7=0; - if((tag.pages[1][1]&0x80) == 0x80) - tag.LCK7=1; - tag.LCK6=0; - if((tag.pages[1][1]&0x40) == 0x040) - tag.LCK6=1; - tag.LCK5=0; - if((tag.pages[1][1]&0x20) == 0x20) - tag.LCK5=1; - tag.LCK4=0; - if((tag.pages[1][1]&0x10) == 0x10) - tag.LCK4=1; - tag.LCK3=0; - if((tag.pages[1][1]&0x8) == 0x08) - tag.LCK3=1; - tag.LCK2=0; - if((tag.pages[1][1]&0x4) == 0x04) - tag.LCK2=1; - tag.LCK1=0; - if((tag.pages[1][1]&0x2) == 0x02) - tag.LCK1=1; - tag.LCK0=0; - if((tag.pages[1][1]&0x1) == 0x01) - tag.LCK0=1; + tag.pstate = HT_READY; + tag.tstate = HT_NO_OP; + for (i = 0; i < 16; i++) + for (j = 0; j < 4; j++) + tag.pages[i][j] = 0x0; + //read tag data into memory + if (tag_mem_supplied) { + DbpString("Loading hitagS memory..."); + memcpy((byte_t*)tag.pages,data,4*64); + } + tag.uid=(uint32_t)tag.pages[0]; + Dbprintf("Hitag S simulation started"); + tag.key=(intptr_t)tag.pages[3]; + tag.key<<=16; + tag.key+=((tag.pages[2][0])<<8)+tag.pages[2][1]; + tag.pwdl0=tag.pages[2][3]; + tag.pwdl1=tag.pages[2][2]; + tag.pwdh0=tag.pages[1][0]; + //con0 + tag.max_page=64; + if((tag.pages[1][3]&0x2)==0 && (tag.pages[1][3]&0x1)==1) + tag.max_page=8; + if((tag.pages[1][3]&0x2)==0 && (tag.pages[1][3]&0x1)==0) + tag.max_page=0; + //con1 + tag.auth=0; + if((tag.pages[1][2]&0x80) == 0x80) + tag.auth=1; + tag.LCON=0; + if((tag.pages[1][2]&0x2) == 0x02) + tag.LCON=1; + tag.LKP=0; + if((tag.pages[1][2]&0x1) == 0x01) + tag.LKP=1; + //con2 + //0=read write 1=read only + tag.LCK7=0; + if((tag.pages[1][1]&0x80) == 0x80) + tag.LCK7=1; + tag.LCK6=0; + if((tag.pages[1][1]&0x40) == 0x040) + tag.LCK6=1; + tag.LCK5=0; + if((tag.pages[1][1]&0x20) == 0x20) + tag.LCK5=1; + tag.LCK4=0; + if((tag.pages[1][1]&0x10) == 0x10) + tag.LCK4=1; + tag.LCK3=0; + if((tag.pages[1][1]&0x8) == 0x08) + tag.LCK3=1; + tag.LCK2=0; + if((tag.pages[1][1]&0x4) == 0x04) + tag.LCK2=1; + tag.LCK1=0; + if((tag.pages[1][1]&0x2) == 0x02) + tag.LCK1=1; + tag.LCK0=0; + if((tag.pages[1][1]&0x1) == 0x01) + tag.LCK0=1; // Set up simulator mode, frequency divisor which will drive the FPGA // and analog mux selection. - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); - SpinDelay(20); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); + SpinDelay(20); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); // Configure output pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; // Disable modulation at default, which means release resistance - LOW(GPIO_SSC_DOUT); + LOW(GPIO_SSC_DOUT); // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the reader frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); - AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; // Disable timer during configuration - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // Capture mode, default timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on rising edge of TIOA. - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK - | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK + | AT91C_TC_ETRGEDG_RISING | AT91C_TC_ABETRG | AT91C_TC_LDRA_RISING; // Reset the received frame, frame count and timing info - memset(rx, 0x00, sizeof(rx)); - frame_count = 0; - response = 0; - overflow = 0; + memset(rx, 0x00, sizeof(rx)); + frame_count = 0; + response = 0; + overflow = 0; // Enable and reset counter - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - while (!BUTTON_PRESS()) { - // Watchdog hit - WDT_HIT(); + while (!BUTTON_PRESS()) { + // Watchdog hit + WDT_HIT(); - // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_EOF) { - // Check if rising edge in modulation is detected - if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values - int ra = (AT91C_BASE_TC1->TC_RA / T0) + overflow; - overflow = 0; + // Receive frame, watch for at most T0*EOF periods + while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_EOF) { + // Check if rising edge in modulation is detected + if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { + // Retrieve the new timing values + int ra = (AT91C_BASE_TC1->TC_RA / T0) + overflow; + overflow = 0; - // Reset timer every frame, we have to capture the last edge for timing - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Reset timer every frame, we have to capture the last edge for timing + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - LED_B_ON(); + LED_B_ON(); - // Capture reader frame - if (ra >= HITAG_T_STOP) { - if (rxlen != 0) { - //DbpString("wierd0?"); - } - // Capture the T0 periods that have passed since last communication or field drop (reset) - response = (ra - HITAG_T_LOW); - } else if (ra >= HITAG_T_1_MIN) { - // '1' bit - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } else if (ra >= HITAG_T_0_MIN) { - // '0' bit - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - } else { - // Ignore wierd value, is to small to mean anything - } - } - } + // Capture reader frame + if (ra >= HITAG_T_STOP) { + if (rxlen != 0) { + //DbpString("wierd0?"); + } + // Capture the T0 periods that have passed since last communication or field drop (reset) + response = (ra - HITAG_T_LOW); + } else if (ra >= HITAG_T_1_MIN) { + // '1' bit + rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); + rxlen++; + } else if (ra >= HITAG_T_0_MIN) { + // '0' bit + rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); + rxlen++; + } else { + // Ignore wierd value, is to small to mean anything + } + } + } - // Check if frame was captured - if (rxlen > 0) { - frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx, rxlen, response, 0, true)) { - DbpString("Trace full"); - clear_trace(); - } - } + // Check if frame was captured + if (rxlen > 0) { + frame_count++; + if (!bQuiet) { + if (!LogTraceHitag(rx, rxlen, response, 0, true)) { + DbpString("Trace full"); + clear_trace(); + } + } - // Disable timer 1 with external trigger to avoid triggers during our own modulation - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + // Disable timer 1 with external trigger to avoid triggers during our own modulation + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Process the incoming frame (rx) and prepare the outgoing frame (tx) - hitagS_handle_reader_command(rx, rxlen, tx, &txlen); + // Process the incoming frame (rx) and prepare the outgoing frame (tx) + hitagS_handle_reader_command(rx, rxlen, tx, &txlen); - // Wait for HITAG_T_WAIT_1 carrier periods after the last reader bit, - // not that since the clock counts since the rising edge, but T_Wait1 is - // with respect to the falling edge, we need to wait actually (T_Wait1 - T_Low) - // periods. The gap time T_Low varies (4..10). All timer values are in - // terms of T0 units - while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_WAIT_1 - HITAG_T_LOW)) - ; + // Wait for HITAG_T_WAIT_1 carrier periods after the last reader bit, + // not that since the clock counts since the rising edge, but T_Wait1 is + // with respect to the falling edge, we need to wait actually (T_Wait1 - T_Low) + // periods. The gap time T_Low varies (4..10). All timer values are in + // terms of T0 units + while (AT91C_BASE_TC0->TC_CV < T0 * (HITAG_T_WAIT_1 - HITAG_T_LOW)) + ; - // Send and store the tag answer (if there is any) - if (txlen > 0) { - // Transmit the tag frame - hitag_send_frame(tx, txlen); - // Store the frame in the trace - if (!bQuiet) { - if (!LogTraceHitag(tx, txlen, 0, 0, false)) { - DbpString("Trace full"); - clear_trace(); - } - } - } + // Send and store the tag answer (if there is any) + if (txlen > 0) { + // Transmit the tag frame + hitag_send_frame(tx, txlen); + // Store the frame in the trace + if (!bQuiet) { + if (!LogTraceHitag(tx, txlen, 0, 0, false)) { + DbpString("Trace full"); + clear_trace(); + } + } + } - // Reset the received frame and response timing info - memset(rx, 0x00, sizeof(rx)); - response = 0; + // Reset the received frame and response timing info + memset(rx, 0x00, sizeof(rx)); + response = 0; - // Enable and reset external trigger in timer for capturing future frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - LED_B_OFF(); - } - // Reset the frame length - rxlen = 0; - // Save the timer overflow, will be 0 when frame was received - overflow += (AT91C_BASE_TC1->TC_CV / T0); - // Reset the timer to restart while-loop that receives frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; - } - LED_B_OFF(); - LED_D_OFF(); - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + // Enable and reset external trigger in timer for capturing future frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + LED_B_OFF(); + } + // Reset the frame length + rxlen = 0; + // Save the timer overflow, will be 0 when frame was received + overflow += (AT91C_BASE_TC1->TC_CV / T0); + // Reset the timer to restart while-loop that receives frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + } + LED_B_OFF(); + LED_D_OFF(); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); } /* @@ -1164,341 +1164,341 @@ void SimulateHitagSTag(bool tag_mem_supplied, byte_t* data) { * Reads every page of a hitag S transpoder. */ void ReadHitagS(hitag_function htf, hitag_data* htd) { - int i, j, z, k; - int frame_count; - int response_bit[200]; - int response; - byte_t rx[HITAG_FRAME_LEN]; - size_t rxlen = 0; - byte_t txbuf[HITAG_FRAME_LEN]; - byte_t* tx = txbuf; - size_t txlen = 0; - int lastbit; - bool bSkip; - int reset_sof; - int tag_sof; - int t_wait = HITAG_T_WAIT_MAX; - bool bStop = false; - bool bQuitTraceFull = false; - int sendNum = 0; - unsigned char mask = 1; - unsigned char crc; - unsigned char pageData[32]; - page_to_be_written = 0; + int i, j, z, k; + int frame_count; + int response_bit[200]; + int response; + byte_t rx[HITAG_FRAME_LEN]; + size_t rxlen = 0; + byte_t txbuf[HITAG_FRAME_LEN]; + byte_t* tx = txbuf; + size_t txlen = 0; + int lastbit; + bool bSkip; + int reset_sof; + int tag_sof; + int t_wait = HITAG_T_WAIT_MAX; + bool bStop = false; + bool bQuitTraceFull = false; + int sendNum = 0; + unsigned char mask = 1; + unsigned char crc; + unsigned char pageData[32]; + page_to_be_written = 0; - //read given key/challenge - byte_t NrAr_[8]; - uint64_t key = 0; - uint64_t NrAr = 0; - byte_t key_[6]; - switch (htf) { - case 01: { //RHTS_CHALLENGE - DbpString("Authenticating using nr,ar pair:"); - memcpy(NrAr_, htd->auth.NrAr, 8); - Dbhexdump(8, NrAr_, false); - NrAr = NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 | - ((uint64_t)NrAr_[2]) << 40| ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56; - } break; - case 02: { //RHTS_KEY - DbpString("Authenticating using key:"); - memcpy(key_, htd->crypto.key, 6); - Dbhexdump(6, key_, false); - key = key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40; - } break; - default: { - Dbprintf("Error , unknown function: %d",htf); - return; - } break; - } + //read given key/challenge + byte_t NrAr_[8]; + uint64_t key = 0; + uint64_t NrAr = 0; + byte_t key_[6]; + switch (htf) { + case 01: { //RHTS_CHALLENGE + DbpString("Authenticating using nr,ar pair:"); + memcpy(NrAr_, htd->auth.NrAr, 8); + Dbhexdump(8, NrAr_, false); + NrAr = NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 | + ((uint64_t)NrAr_[2]) << 40| ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56; + } break; + case 02: { //RHTS_KEY + DbpString("Authenticating using key:"); + memcpy(key_, htd->crypto.key, 6); + Dbhexdump(6, key_, false); + key = key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40; + } break; + default: { + Dbprintf("Error , unknown function: %d",htf); + return; + } break; + } - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - // Reset the return status - bSuccessful = false; + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + // Reset the return status + bSuccessful = false; - // Clean up trace and prepare it for storing frames - set_tracing(true); - clear_trace(); + // Clean up trace and prepare it for storing frames + set_tracing(true); + clear_trace(); - bQuiet = false; - bQuitTraceFull = true; + bQuiet = false; + bQuitTraceFull = true; - LED_D_ON(); + LED_D_ON(); - // Configure output and enable pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + // Configure output and enable pin that is connected to the FPGA (for modulating) + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - // Set fpga in edge detect with reader field, we can modulate as reader now - FpgaWriteConfWord( - FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + // Set fpga in edge detect with reader field, we can modulate as reader now + FpgaWriteConfWord( + FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - // Set Frequency divisor which will drive the FPGA and analog mux selection - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); + // Set Frequency divisor which will drive the FPGA and analog mux selection + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); - // Disable modulation at default, which means enable the field - LOW(GPIO_SSC_DOUT); + // Disable modulation at default, which means enable the field + LOW(GPIO_SSC_DOUT); - // Give it a bit of time for the resonant antenna to settle. - SpinDelay(30); + // Give it a bit of time for the resonant antenna to settle. + SpinDelay(30); - // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); - // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); - AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; + // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; - // Disable timer during configuration - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + // Disable timer during configuration + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, - // external trigger rising edge, load RA on falling edge of TIOA. - AT91C_BASE_TC1->TC_CMR = - AT91C_TC_CLKS_TIMER_DIV1_CLOCK | - AT91C_TC_ETRGEDG_FALLING | - AT91C_TC_ABETRG | - AT91C_TC_LDRA_FALLING; + // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, + // external trigger rising edge, load RA on falling edge of TIOA. + AT91C_BASE_TC1->TC_CMR = + AT91C_TC_CLKS_TIMER_DIV1_CLOCK | + AT91C_TC_ETRGEDG_FALLING | + AT91C_TC_ABETRG | + AT91C_TC_LDRA_FALLING; - // Enable and reset counters - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Enable and reset counters + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - // Reset the received frame, frame count and timing info - frame_count = 0; - response = 0; - lastbit = 1; - bStop = false; + // Reset the received frame, frame count and timing info + frame_count = 0; + response = 0; + lastbit = 1; + bStop = false; - reset_sof = 1; - t_wait = 200; + reset_sof = 1; + t_wait = 200; - while (!bStop && !BUTTON_PRESS()) { - // Watchdog hit - WDT_HIT(); + while (!bStop && !BUTTON_PRESS()) { + // Watchdog hit + WDT_HIT(); - // Check if frame was captured and store it - if (rxlen > 0) { - frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx, rxlen, response, 0, false)) { - DbpString("Trace full"); - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } - } + // Check if frame was captured and store it + if (rxlen > 0) { + frame_count++; + if (!bQuiet) { + if (!LogTraceHitag(rx, rxlen, response, 0, false)) { + DbpString("Trace full"); + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } + } - // By default reset the transmission buffer - tx = txbuf; - txlen = 0; + // By default reset the transmission buffer + tx = txbuf; + txlen = 0; - if (rxlen == 0) { - //start authentication - txlen = 5; - memcpy(tx, "\xc0", nbytes(txlen)); - tag.pstate = HT_READY; - tag.tstate = HT_NO_OP; - } else if (tag.pstate != HT_SELECTED) { - if (hitagS_handle_tag_auth(htf, key,NrAr,rx, rxlen, tx, &txlen) == -1) - bStop = !false; - } - if (tag.pstate == HT_SELECTED && tag.tstate == HT_NO_OP && rxlen > 0) { - //send read request - tag.tstate = HT_READING_PAGE; - txlen = 20; - crc = CRC_PRESET; - tx[0] = 0xc0 + (sendNum / 16); - calc_crc(&crc, tx[0], 8); - calc_crc(&crc, 0x00 + ((sendNum % 16) * 16), 4); - tx[1] = 0x00 + ((sendNum % 16) * 16) + (crc / 16); - tx[2] = 0x00 + (crc % 16) * 16; - } else if (tag.pstate == HT_SELECTED && tag.tstate == HT_READING_PAGE - && rxlen > 0) { - //save received data - z = 0; - for (i = 0; i < 5; i++) { - for (j = 0; j < 8; j++) { - response_bit[z] = 0; - if ((rx[i] & ((mask << 7) >> j)) != 0) - response_bit[z] = 1; - z++; - } - } - k = 0; - for (i = 4; i < 36; i++) { - pageData[k] = response_bit[i]; - k++; - } - for (i = 0; i < 4; i++) - tag.pages[sendNum / 4][sendNum % 4] = 0x0; - for (i = 0; i < 4; i++) { - tag.pages[sendNum / 4][sendNum % 4] += ((pageData[i * 8] << 7) - | (pageData[1 + (i * 8)] << 6) - | (pageData[2 + (i * 8)] << 5) - | (pageData[3 + (i * 8)] << 4) - | (pageData[4 + (i * 8)] << 3) - | (pageData[5 + (i * 8)] << 2) - | (pageData[6 + (i * 8)] << 1) | pageData[7 + (i * 8)]) - << (i * 8); - } - if (tag.auth && tag.LKP && sendNum == 1) { - Dbprintf("Page[%2d]: %02X %02X %02X %02X", sendNum, pwdh0, - (tag.pages[sendNum / 4][sendNum % 4] >> 16) & 0xff, - (tag.pages[sendNum / 4][sendNum % 4] >> 8) & 0xff, - tag.pages[sendNum / 4][sendNum % 4] & 0xff); - } else { - Dbprintf("Page[%2d]: %02X %02X %02X %02X", sendNum, - (tag.pages[sendNum / 4][sendNum % 4] >> 24) & 0xff, - (tag.pages[sendNum / 4][sendNum % 4] >> 16) & 0xff, - (tag.pages[sendNum / 4][sendNum % 4] >> 8) & 0xff, - tag.pages[sendNum / 4][sendNum % 4] & 0xff); - } + if (rxlen == 0) { + //start authentication + txlen = 5; + memcpy(tx, "\xc0", nbytes(txlen)); + tag.pstate = HT_READY; + tag.tstate = HT_NO_OP; + } else if (tag.pstate != HT_SELECTED) { + if (hitagS_handle_tag_auth(htf, key,NrAr,rx, rxlen, tx, &txlen) == -1) + bStop = !false; + } + if (tag.pstate == HT_SELECTED && tag.tstate == HT_NO_OP && rxlen > 0) { + //send read request + tag.tstate = HT_READING_PAGE; + txlen = 20; + crc = CRC_PRESET; + tx[0] = 0xc0 + (sendNum / 16); + calc_crc(&crc, tx[0], 8); + calc_crc(&crc, 0x00 + ((sendNum % 16) * 16), 4); + tx[1] = 0x00 + ((sendNum % 16) * 16) + (crc / 16); + tx[2] = 0x00 + (crc % 16) * 16; + } else if (tag.pstate == HT_SELECTED && tag.tstate == HT_READING_PAGE + && rxlen > 0) { + //save received data + z = 0; + for (i = 0; i < 5; i++) { + for (j = 0; j < 8; j++) { + response_bit[z] = 0; + if ((rx[i] & ((mask << 7) >> j)) != 0) + response_bit[z] = 1; + z++; + } + } + k = 0; + for (i = 4; i < 36; i++) { + pageData[k] = response_bit[i]; + k++; + } + for (i = 0; i < 4; i++) + tag.pages[sendNum / 4][sendNum % 4] = 0x0; + for (i = 0; i < 4; i++) { + tag.pages[sendNum / 4][sendNum % 4] += ((pageData[i * 8] << 7) + | (pageData[1 + (i * 8)] << 6) + | (pageData[2 + (i * 8)] << 5) + | (pageData[3 + (i * 8)] << 4) + | (pageData[4 + (i * 8)] << 3) + | (pageData[5 + (i * 8)] << 2) + | (pageData[6 + (i * 8)] << 1) | pageData[7 + (i * 8)]) + << (i * 8); + } + if (tag.auth && tag.LKP && sendNum == 1) { + Dbprintf("Page[%2d]: %02X %02X %02X %02X", sendNum, pwdh0, + (tag.pages[sendNum / 4][sendNum % 4] >> 16) & 0xff, + (tag.pages[sendNum / 4][sendNum % 4] >> 8) & 0xff, + tag.pages[sendNum / 4][sendNum % 4] & 0xff); + } else { + Dbprintf("Page[%2d]: %02X %02X %02X %02X", sendNum, + (tag.pages[sendNum / 4][sendNum % 4] >> 24) & 0xff, + (tag.pages[sendNum / 4][sendNum % 4] >> 16) & 0xff, + (tag.pages[sendNum / 4][sendNum % 4] >> 8) & 0xff, + tag.pages[sendNum / 4][sendNum % 4] & 0xff); + } - sendNum++; - //display key and password if possible - if (sendNum == 2 && tag.auth == 1 && tag.LKP) { - if (htf == 02) { //RHTS_KEY - Dbprintf("Page[ 2]: %02X %02X %02X %02X", - (byte_t)(key >> 8) & 0xff, - (byte_t) key & 0xff, pwdl1, pwdl0); - Dbprintf("Page[ 3]: %02X %02X %02X %02X", - (byte_t)(key >> 40) & 0xff, - (byte_t)(key >> 32) & 0xff, - (byte_t)(key >> 24) & 0xff, - (byte_t)(key >> 16) & 0xff); - } else { - //if the authentication is done with a challenge the key and password are unknown - Dbprintf("Page[ 2]: __ __ __ __"); - Dbprintf("Page[ 3]: __ __ __ __"); - } - } + sendNum++; + //display key and password if possible + if (sendNum == 2 && tag.auth == 1 && tag.LKP) { + if (htf == 02) { //RHTS_KEY + Dbprintf("Page[ 2]: %02X %02X %02X %02X", + (byte_t)(key >> 8) & 0xff, + (byte_t) key & 0xff, pwdl1, pwdl0); + Dbprintf("Page[ 3]: %02X %02X %02X %02X", + (byte_t)(key >> 40) & 0xff, + (byte_t)(key >> 32) & 0xff, + (byte_t)(key >> 24) & 0xff, + (byte_t)(key >> 16) & 0xff); + } else { + //if the authentication is done with a challenge the key and password are unknown + Dbprintf("Page[ 2]: __ __ __ __"); + Dbprintf("Page[ 3]: __ __ __ __"); + } + } - txlen = 20; - crc = CRC_PRESET; - tx[0] = 0xc0 + (sendNum / 16); - calc_crc(&crc, tx[0], 8); - calc_crc(&crc, 0x00 + ((sendNum % 16) * 16), 4); - tx[1] = 0x00 + ((sendNum % 16) * 16) + (crc / 16); - tx[2] = 0x00 + (crc % 16) * 16; - if (sendNum >= tag.max_page) { - bStop = !false; - } - } + txlen = 20; + crc = CRC_PRESET; + tx[0] = 0xc0 + (sendNum / 16); + calc_crc(&crc, tx[0], 8); + calc_crc(&crc, 0x00 + ((sendNum % 16) * 16), 4); + tx[1] = 0x00 + ((sendNum % 16) * 16) + (crc / 16); + tx[2] = 0x00 + (crc % 16) * 16; + if (sendNum >= tag.max_page) { + bStop = !false; + } + } - // Send and store the reader command - // Disable timer 1 with external trigger to avoid triggers during our own modulation - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + // Send and store the reader command + // Disable timer 1 with external trigger to avoid triggers during our own modulation + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, - // Since the clock counts since the last falling edge, a 'one' means that the - // falling edge occured halfway the period. with respect to this falling edge, - // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. - // All timer values are in terms of T0 units + // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, + // Since the clock counts since the last falling edge, a 'one' means that the + // falling edge occured halfway the period. with respect to this falling edge, + // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. + // All timer values are in terms of T0 units - while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; + while (AT91C_BASE_TC0->TC_CV < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) {}; - // Transmit the reader frame - hitag_reader_send_frame(tx, txlen); + // Transmit the reader frame + hitag_reader_send_frame(tx, txlen); - // Enable and reset external trigger in timer for capturing future frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Enable and reset external trigger in timer for capturing future frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - // Add transmitted frame to total count - if (txlen > 0) { - frame_count++; - if (!bQuiet) { - // Store the frame in the trace - if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { - if (bQuitTraceFull) { - DbpString("Trace full"); - break; - } else { - bQuiet = true; - } - } - } - } + // Add transmitted frame to total count + if (txlen > 0) { + frame_count++; + if (!bQuiet) { + // Store the frame in the trace + if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { + if (bQuitTraceFull) { + DbpString("Trace full"); + break; + } else { + bQuiet = true; + } + } + } + } - // Reset values for receiving frames - memset(rx, 0x00, sizeof(rx)); - rxlen = 0; - lastbit = 1; - bSkip = true; - tag_sof = reset_sof; - response = 0; + // Reset values for receiving frames + memset(rx, 0x00, sizeof(rx)); + rxlen = 0; + lastbit = 1; + bSkip = true; + tag_sof = reset_sof; + response = 0; - // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { - // Check if falling edge in tag modulation is detected - if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values - int ra = (AT91C_BASE_TC1->TC_RA / T0); + // Receive frame, watch for at most T0*EOF periods + while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { + // Check if falling edge in tag modulation is detected + if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { + // Retrieve the new timing values + int ra = (AT91C_BASE_TC1->TC_RA / T0); - // Reset timer every frame, we have to capture the last edge for timing - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + // Reset timer every frame, we have to capture the last edge for timing + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - LED_B_ON(); + LED_B_ON(); - // Capture tag frame (manchester decoding using only falling edges) - if (ra >= HITAG_T_EOF) { - if (rxlen != 0) { - //DbpString("wierd1?"); - } - // Capture the T0 periods that have passed since last communication or field drop (reset) - // We always recieve a 'one' first, which has the falling edge after a half period |-_| - response = ra - HITAG_T_TAG_HALF_PERIOD; - } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { - // Manchester coding example |-_|_-|-_| (101) - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { - // Manchester coding example |_-|...|_-|-_| (0...01) - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - // We have to skip this half period at start and add the 'one' the second time - if (!bSkip) { - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } - lastbit = !lastbit; - bSkip = !bSkip; - } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { - // Manchester coding example |_-|_-| (00) or |-_|-_| (11) - if (tag_sof) { - // Ignore bits that are transmitted during SOF - tag_sof--; - } else { - // bit is same as last bit - rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8)); - rxlen++; - } - } else { - // Ignore wierd value, is to small to mean anything - } - } + // Capture tag frame (manchester decoding using only falling edges) + if (ra >= HITAG_T_EOF) { + if (rxlen != 0) { + //DbpString("wierd1?"); + } + // Capture the T0 periods that have passed since last communication or field drop (reset) + // We always recieve a 'one' first, which has the falling edge after a half period |-_| + response = ra - HITAG_T_TAG_HALF_PERIOD; + } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { + // Manchester coding example |-_|_-|-_| (101) + rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); + rxlen++; + rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); + rxlen++; + } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { + // Manchester coding example |_-|...|_-|-_| (0...01) + rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); + rxlen++; + // We have to skip this half period at start and add the 'one' the second time + if (!bSkip) { + rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); + rxlen++; + } + lastbit = !lastbit; + bSkip = !bSkip; + } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { + // Manchester coding example |_-|_-| (00) or |-_|-_| (11) + if (tag_sof) { + // Ignore bits that are transmitted during SOF + tag_sof--; + } else { + // bit is same as last bit + rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8)); + rxlen++; + } + } else { + // Ignore wierd value, is to small to mean anything + } + } - // We can break this loop if we received the last bit from a frame - if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { - if (rxlen > 0) - break; - } - } - } - end = false; - LED_B_OFF(); - LED_D_OFF(); - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + // We can break this loop if we received the last bit from a frame + if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { + if (rxlen > 0) + break; + } + } + } + end = false; + LED_B_OFF(); + LED_D_OFF(); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); + cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); } /* @@ -1506,309 +1506,309 @@ void ReadHitagS(hitag_function htf, hitag_data* htd) { * Writes the given 32Bit data into page_ */ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) { - int frame_count; - int response; - byte_t rx[HITAG_FRAME_LEN]; - size_t rxlen = 0; - byte_t txbuf[HITAG_FRAME_LEN]; - byte_t* tx = txbuf; - size_t txlen = 0; - int lastbit; - bool bSkip; - int reset_sof; - int tag_sof; - int t_wait = HITAG_T_WAIT_MAX; - bool bStop; - bool bQuitTraceFull = false; - int page = page_; - unsigned char crc; - byte_t data[4]= {0,0,0,0}; + int frame_count; + int response; + byte_t rx[HITAG_FRAME_LEN]; + size_t rxlen = 0; + byte_t txbuf[HITAG_FRAME_LEN]; + byte_t* tx = txbuf; + size_t txlen = 0; + int lastbit; + bool bSkip; + int reset_sof; + int tag_sof; + int t_wait = HITAG_T_WAIT_MAX; + bool bStop; + bool bQuitTraceFull = false; + int page = page_; + unsigned char crc; + byte_t data[4]= {0,0,0,0}; - //read given key/challenge, the page and the data - byte_t NrAr_[8]; - uint64_t key=0; - uint64_t NrAr=0; - byte_t key_[6]; - switch(htf) { - case 03: { //WHTS_CHALLENGE - memcpy(data,htd->auth.data,4); - DbpString("Authenticating using nr,ar pair:"); - memcpy(NrAr_,htd->auth.NrAr,8); - Dbhexdump(8,NrAr_,false); - NrAr=NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 | - ((uint64_t)NrAr_[2]) << 40| ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56; - } break; - case 04: { //WHTS_KEY - memcpy(data,htd->crypto.data,4); - DbpString("Authenticating using key:"); - memcpy(key_,htd->crypto.key,6); - Dbhexdump(6,key_,false); - key=key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40; - } break; - default: { - Dbprintf("Error , unknown function: %d",htf); - return; - } break; - } + //read given key/challenge, the page and the data + byte_t NrAr_[8]; + uint64_t key=0; + uint64_t NrAr=0; + byte_t key_[6]; + switch(htf) { + case 03: { //WHTS_CHALLENGE + memcpy(data,htd->auth.data,4); + DbpString("Authenticating using nr,ar pair:"); + memcpy(NrAr_,htd->auth.NrAr,8); + Dbhexdump(8,NrAr_,false); + NrAr=NrAr_[7] | ((uint64_t)NrAr_[6]) << 8 | ((uint64_t)NrAr_[5]) << 16 | ((uint64_t)NrAr_[4]) << 24 | ((uint64_t)NrAr_[3]) << 32 | + ((uint64_t)NrAr_[2]) << 40| ((uint64_t)NrAr_[1]) << 48 | ((uint64_t)NrAr_[0]) << 56; + } break; + case 04: { //WHTS_KEY + memcpy(data,htd->crypto.data,4); + DbpString("Authenticating using key:"); + memcpy(key_,htd->crypto.key,6); + Dbhexdump(6,key_,false); + key=key_[5] | ((uint64_t)key_[4]) << 8 | ((uint64_t)key_[3]) << 16 | ((uint64_t)key_[2]) << 24 | ((uint64_t)key_[1]) << 32 | ((uint64_t)key_[0]) << 40; + } break; + default: { + Dbprintf("Error , unknown function: %d",htf); + return; + } break; + } - Dbprintf("Page: %d",page_); - Dbprintf("DATA: %02X %02X %02X %02X", data[0], data[1], data[2], data[3]); - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + Dbprintf("Page: %d",page_); + Dbprintf("DATA: %02X %02X %02X %02X", data[0], data[1], data[2], data[3]); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); // Reset the return status - bSuccessful = false; + bSuccessful = false; - tag.pstate = HT_READY; - tag.tstate = HT_NO_OP; + tag.pstate = HT_READY; + tag.tstate = HT_NO_OP; // Clean up trace and prepare it for storing frames - set_tracing(true); - clear_trace(); + set_tracing(true); + clear_trace(); - bQuiet = false; - bQuitTraceFull = true; + bQuiet = false; + bQuitTraceFull = true; - LED_D_ON(); + LED_D_ON(); // Configure output and enable pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; // Set fpga in edge detect with reader field, we can modulate as reader now - FpgaWriteConfWord( - FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + FpgaWriteConfWord( + FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); // Set Frequency divisor which will drive the FPGA and analog mux selection - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); // Disable modulation at default, which means enable the field - LOW(GPIO_SSC_DOUT); + LOW(GPIO_SSC_DOUT); // Give it a bit of time for the resonant antenna to settle. - SpinDelay(30); + SpinDelay(30); // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); - AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; // Disable timer during configuration - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on falling edge of TIOA. - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK - | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG - | AT91C_TC_LDRA_FALLING; + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK + | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG + | AT91C_TC_LDRA_FALLING; // Enable and reset counters - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // Reset the received frame, frame count and timing info - frame_count = 0; - response = 0; - lastbit = 1; - bStop = false; + frame_count = 0; + response = 0; + lastbit = 1; + bStop = false; - reset_sof = 1; - t_wait = 200; + reset_sof = 1; + t_wait = 200; - while (!bStop && !BUTTON_PRESS()) { - // Watchdog hit - WDT_HIT(); + while (!bStop && !BUTTON_PRESS()) { + // Watchdog hit + WDT_HIT(); - // Check if frame was captured and store it - if (rxlen > 0) { - frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx, rxlen, response, 0, false)) { - DbpString("Trace full"); - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } - } + // Check if frame was captured and store it + if (rxlen > 0) { + frame_count++; + if (!bQuiet) { + if (!LogTraceHitag(rx, rxlen, response, 0, false)) { + DbpString("Trace full"); + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } + } - //check for valid input - if (page == 0) { - Dbprintf( - "usage: lf hitag writer [03 | 04] [CHALLENGE | KEY] [page] [byte0] [byte1] [byte2] [byte3]"); - bStop = !false; - } + //check for valid input + if (page == 0) { + Dbprintf( + "usage: lf hitag writer [03 | 04] [CHALLENGE | KEY] [page] [byte0] [byte1] [byte2] [byte3]"); + bStop = !false; + } - // By default reset the transmission buffer - tx = txbuf; - txlen = 0; + // By default reset the transmission buffer + tx = txbuf; + txlen = 0; - if (rxlen == 0 && tag.tstate == HT_WRITING_PAGE_ACK) { - //no write access on this page - Dbprintf("no write access on page %d", page_); - bStop = !false; - } else if (rxlen == 0 && tag.tstate != HT_WRITING_PAGE_DATA) { - //start the authetication - txlen = 5; - memcpy(tx, "\xc0", nbytes(txlen)); - tag.pstate = HT_READY; - tag.tstate = HT_NO_OP; - } else if (tag.pstate != HT_SELECTED) { - //try to authenticate with the given key or challenge - if (hitagS_handle_tag_auth(htf,key,NrAr,rx, rxlen, tx, &txlen) == -1) - bStop = !false; - } - if (tag.pstate == HT_SELECTED && tag.tstate == HT_NO_OP && rxlen > 0) { - //check if the given page exists - if (page > tag.max_page) { - Dbprintf("page number too big"); - bStop = !false; - } - //ask Tag for write permission - tag.tstate = HT_WRITING_PAGE_ACK; - txlen = 20; - crc = CRC_PRESET; - tx[0] = 0x90 + (page / 16); - calc_crc(&crc, tx[0], 8); - calc_crc(&crc, 0x00 + ((page % 16) * 16), 4); - tx[1] = 0x00 + ((page % 16) * 16) + (crc / 16); - tx[2] = 0x00 + (crc % 16) * 16; - } else if (tag.pstate == HT_SELECTED && tag.tstate == HT_WRITING_PAGE_ACK - && rxlen == 6 && rx[0] == 0xf4) { - //ACK recieved to write the page. send data - tag.tstate = HT_WRITING_PAGE_DATA; - txlen = 40; - crc = CRC_PRESET; - calc_crc(&crc, data[3], 8); - calc_crc(&crc, data[2], 8); - calc_crc(&crc, data[1], 8); - calc_crc(&crc, data[0], 8); - tx[0] = data[3]; - tx[1] = data[2]; - tx[2] = data[1]; - tx[3] = data[0]; - tx[4] = crc; - } else if (tag.pstate == HT_SELECTED && tag.tstate == HT_WRITING_PAGE_DATA - && rxlen == 6 && rx[0] == 0xf4) { - //received ACK - Dbprintf("Successful!"); - bStop = !false; - } + if (rxlen == 0 && tag.tstate == HT_WRITING_PAGE_ACK) { + //no write access on this page + Dbprintf("no write access on page %d", page_); + bStop = !false; + } else if (rxlen == 0 && tag.tstate != HT_WRITING_PAGE_DATA) { + //start the authetication + txlen = 5; + memcpy(tx, "\xc0", nbytes(txlen)); + tag.pstate = HT_READY; + tag.tstate = HT_NO_OP; + } else if (tag.pstate != HT_SELECTED) { + //try to authenticate with the given key or challenge + if (hitagS_handle_tag_auth(htf,key,NrAr,rx, rxlen, tx, &txlen) == -1) + bStop = !false; + } + if (tag.pstate == HT_SELECTED && tag.tstate == HT_NO_OP && rxlen > 0) { + //check if the given page exists + if (page > tag.max_page) { + Dbprintf("page number too big"); + bStop = !false; + } + //ask Tag for write permission + tag.tstate = HT_WRITING_PAGE_ACK; + txlen = 20; + crc = CRC_PRESET; + tx[0] = 0x90 + (page / 16); + calc_crc(&crc, tx[0], 8); + calc_crc(&crc, 0x00 + ((page % 16) * 16), 4); + tx[1] = 0x00 + ((page % 16) * 16) + (crc / 16); + tx[2] = 0x00 + (crc % 16) * 16; + } else if (tag.pstate == HT_SELECTED && tag.tstate == HT_WRITING_PAGE_ACK + && rxlen == 6 && rx[0] == 0xf4) { + //ACK recieved to write the page. send data + tag.tstate = HT_WRITING_PAGE_DATA; + txlen = 40; + crc = CRC_PRESET; + calc_crc(&crc, data[3], 8); + calc_crc(&crc, data[2], 8); + calc_crc(&crc, data[1], 8); + calc_crc(&crc, data[0], 8); + tx[0] = data[3]; + tx[1] = data[2]; + tx[2] = data[1]; + tx[3] = data[0]; + tx[4] = crc; + } else if (tag.pstate == HT_SELECTED && tag.tstate == HT_WRITING_PAGE_DATA + && rxlen == 6 && rx[0] == 0xf4) { + //received ACK + Dbprintf("Successful!"); + bStop = !false; + } - // Send and store the reader command - // Disable timer 1 with external trigger to avoid triggers during our own modulation - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + // Send and store the reader command + // Disable timer 1 with external trigger to avoid triggers during our own modulation + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, - // Since the clock counts since the last falling edge, a 'one' means that the - // falling edge occured halfway the period. with respect to this falling edge, - // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. - // All timer values are in terms of T0 units + // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, + // Since the clock counts since the last falling edge, a 'one' means that the + // falling edge occured halfway the period. with respect to this falling edge, + // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. + // All timer values are in terms of T0 units - while (AT91C_BASE_TC0->TC_CV - < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) - ; + while (AT91C_BASE_TC0->TC_CV + < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) + ; - // Transmit the reader frame - hitag_reader_send_frame(tx, txlen); + // Transmit the reader frame + hitag_reader_send_frame(tx, txlen); - // Enable and reset external trigger in timer for capturing future frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Enable and reset external trigger in timer for capturing future frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - // Add transmitted frame to total count - if (txlen > 0) { - frame_count++; - if (!bQuiet) { - // Store the frame in the trace - if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { - if (bQuitTraceFull) { - DbpString("Trace full"); - break; - } else { - bQuiet = true; - } - } - } - } + // Add transmitted frame to total count + if (txlen > 0) { + frame_count++; + if (!bQuiet) { + // Store the frame in the trace + if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { + if (bQuitTraceFull) { + DbpString("Trace full"); + break; + } else { + bQuiet = true; + } + } + } + } - // Reset values for receiving frames - memset(rx, 0x00, sizeof(rx)); - rxlen = 0; - lastbit = 1; - bSkip = true; - tag_sof = reset_sof; - response = 0; + // Reset values for receiving frames + memset(rx, 0x00, sizeof(rx)); + rxlen = 0; + lastbit = 1; + bSkip = true; + tag_sof = reset_sof; + response = 0; - // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { - // Check if falling edge in tag modulation is detected - if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values - int ra = (AT91C_BASE_TC1->TC_RA / T0); + // Receive frame, watch for at most T0*EOF periods + while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { + // Check if falling edge in tag modulation is detected + if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { + // Retrieve the new timing values + int ra = (AT91C_BASE_TC1->TC_RA / T0); - // Reset timer every frame, we have to capture the last edge for timing - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + // Reset timer every frame, we have to capture the last edge for timing + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - LED_B_ON(); + LED_B_ON(); - // Capture tag frame (manchester decoding using only falling edges) - if (ra >= HITAG_T_EOF) { - if (rxlen != 0) { - //DbpString("wierd1?"); - } - // Capture the T0 periods that have passed since last communication or field drop (reset) - // We always recieve a 'one' first, which has the falling edge after a half period |-_| - response = ra - HITAG_T_TAG_HALF_PERIOD; - } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { - // Manchester coding example |-_|_-|-_| (101) - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { - // Manchester coding example |_-|...|_-|-_| (0...01) - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - // We have to skip this half period at start and add the 'one' the second time - if (!bSkip) { - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } - lastbit = !lastbit; - bSkip = !bSkip; - } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { - // Manchester coding example |_-|_-| (00) or |-_|-_| (11) - if (tag_sof) { - // Ignore bits that are transmitted during SOF - tag_sof--; - } else { - // bit is same as last bit - rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8)); - rxlen++; - } - } else { - // Ignore wierd value, is to small to mean anything - } - } + // Capture tag frame (manchester decoding using only falling edges) + if (ra >= HITAG_T_EOF) { + if (rxlen != 0) { + //DbpString("wierd1?"); + } + // Capture the T0 periods that have passed since last communication or field drop (reset) + // We always recieve a 'one' first, which has the falling edge after a half period |-_| + response = ra - HITAG_T_TAG_HALF_PERIOD; + } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { + // Manchester coding example |-_|_-|-_| (101) + rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); + rxlen++; + rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); + rxlen++; + } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { + // Manchester coding example |_-|...|_-|-_| (0...01) + rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); + rxlen++; + // We have to skip this half period at start and add the 'one' the second time + if (!bSkip) { + rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); + rxlen++; + } + lastbit = !lastbit; + bSkip = !bSkip; + } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { + // Manchester coding example |_-|_-| (00) or |-_|-_| (11) + if (tag_sof) { + // Ignore bits that are transmitted during SOF + tag_sof--; + } else { + // bit is same as last bit + rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8)); + rxlen++; + } + } else { + // Ignore wierd value, is to small to mean anything + } + } - // We can break this loop if we received the last bit from a frame - if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { - if (rxlen > 0) - break; - } - } - } - end=false; - LED_B_OFF(); - LED_D_OFF(); - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); + // We can break this loop if we received the last bit from a frame + if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { + if (rxlen > 0) + break; + } + } + } + end=false; + LED_B_OFF(); + LED_D_OFF(); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); } /* @@ -1819,327 +1819,327 @@ void WritePageHitagS(hitag_function htf, hitag_data* htd,int page_) { * detects these challenges. */ void check_challenges(bool file_given, byte_t* data) { - int i, j, z, k; - byte_t uid_byte[4]; - int frame_count; - int response; - byte_t rx[HITAG_FRAME_LEN]; - byte_t unlocker[60][8]; - int u1 = 0; - size_t rxlen = 0; - byte_t txbuf[HITAG_FRAME_LEN]; - byte_t* tx = txbuf; - size_t txlen = 0; - int lastbit; - bool bSkip; - int reset_sof; - int tag_sof; - int t_wait = HITAG_T_WAIT_MAX; - int STATE = 0; - bool bStop; - bool bQuitTraceFull = false; - int response_bit[200]; - unsigned char mask = 1; - unsigned char uid[32]; - unsigned char crc; + int i, j, z, k; + byte_t uid_byte[4]; + int frame_count; + int response; + byte_t rx[HITAG_FRAME_LEN]; + byte_t unlocker[60][8]; + int u1 = 0; + size_t rxlen = 0; + byte_t txbuf[HITAG_FRAME_LEN]; + byte_t* tx = txbuf; + size_t txlen = 0; + int lastbit; + bool bSkip; + int reset_sof; + int tag_sof; + int t_wait = HITAG_T_WAIT_MAX; + int STATE = 0; + bool bStop; + bool bQuitTraceFull = false; + int response_bit[200]; + unsigned char mask = 1; + unsigned char uid[32]; + unsigned char crc; - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); // Reset the return status - bSuccessful = false; + bSuccessful = false; // Clean up trace and prepare it for storing frames - set_tracing(true); - clear_trace(); + set_tracing(true); + clear_trace(); - bQuiet = false; - bQuitTraceFull = true; + bQuiet = false; + bQuitTraceFull = true; - LED_D_ON(); + LED_D_ON(); // Configure output and enable pin that is connected to the FPGA (for modulating) - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; // Set fpga in edge detect with reader field, we can modulate as reader now - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); - SpinDelay(50); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_READER_FIELD); + SpinDelay(50); // Set Frequency divisor which will drive the FPGA and analog mux selection - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - RELAY_OFF(); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + RELAY_OFF(); // Disable modulation at default, which means enable the field - LOW(GPIO_SSC_DOUT); + LOW(GPIO_SSC_DOUT); // Give it a bit of time for the resonant antenna to settle. - SpinDelay(30); + SpinDelay(30); // Enable Peripheral Clock for TIMER_CLOCK0, used to measure exact timing before answering - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC0); // Enable Peripheral Clock for TIMER_CLOCK1, used to capture edges of the tag frames - AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); - AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; + AT91C_BASE_PMC->PMC_PCER = (1 << AT91C_ID_TC1); + AT91C_BASE_PIOA->PIO_BSR = GPIO_SSC_FRAME; // Disable timer during configuration - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // Capture mode, defaul timer source = MCK/2 (TIMER_CLOCK1), TIOA is external trigger, // external trigger rising edge, load RA on falling edge of TIOA. - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK - | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; + | AT91C_TC_ETRGEDG_FALLING | AT91C_TC_ABETRG | AT91C_TC_LDRA_FALLING; // Enable and reset counters - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // Reset the received frame, frame count and timing info - frame_count = 0; - response = 0; - lastbit = 1; - bStop = false; + frame_count = 0; + response = 0; + lastbit = 1; + bStop = false; - reset_sof = 1; - t_wait = 200; + reset_sof = 1; + t_wait = 200; - if (file_given) { - DbpString("Loading challenges..."); - memcpy((byte_t*)unlocker,data,60*8); - } + if (file_given) { + DbpString("Loading challenges..."); + memcpy((byte_t*)unlocker,data,60*8); + } - while (file_given && !bStop && !BUTTON_PRESS()) { - // Watchdog hit - WDT_HIT(); + while (file_given && !bStop && !BUTTON_PRESS()) { + // Watchdog hit + WDT_HIT(); - // Check if frame was captured and store it - if (rxlen > 0) { - frame_count++; - if (!bQuiet) { - if (!LogTraceHitag(rx, rxlen, response, 0, false)) { - DbpString("Trace full"); - if (bQuitTraceFull) { - break; - } else { - bQuiet = true; - } - } - } - } + // Check if frame was captured and store it + if (rxlen > 0) { + frame_count++; + if (!bQuiet) { + if (!LogTraceHitag(rx, rxlen, response, 0, false)) { + DbpString("Trace full"); + if (bQuitTraceFull) { + break; + } else { + bQuiet = true; + } + } + } + } - tx = txbuf; - txlen = 0; - if (rxlen == 0) { - if (STATE == 2) - // challenge failed - Dbprintf("Challenge failed: %02X %02X %02X %02X %02X %02X %02X %02X", - unlocker[u1 - 1][0], unlocker[u1 - 1][1], - unlocker[u1 - 1][2], unlocker[u1 - 1][3], - unlocker[u1 - 1][4], unlocker[u1 - 1][5], - unlocker[u1 - 1][6], unlocker[u1 - 1][7]); - STATE = 0; - txlen = 5; - //start new authentication - memcpy(tx, "\xc0", nbytes(txlen)); - } else if (rxlen >= 67 && STATE == 0) { - //received uid - z = 0; - for (i = 0; i < 10; i++) { - for (j = 0; j < 8; j++) { - response_bit[z] = 0; - if ((rx[i] & ((mask << 7) >> j)) != 0) - response_bit[z] = 1; - z++; - } - } - k = 0; - for (i = 5; i < z; i += 2) { - uid[k] = response_bit[i]; - k++; - if (k > 31) - break; - } - uid_byte[0] = (uid[0] << 7) | (uid[1] << 6) | (uid[2] << 5) - | (uid[3] << 4) | (uid[4] << 3) | (uid[5] << 2) - | (uid[6] << 1) | uid[7]; - uid_byte[1] = (uid[8] << 7) | (uid[9] << 6) | (uid[10] << 5) - | (uid[11] << 4) | (uid[12] << 3) | (uid[13] << 2) - | (uid[14] << 1) | uid[15]; - uid_byte[2] = (uid[16] << 7) | (uid[17] << 6) | (uid[18] << 5) - | (uid[19] << 4) | (uid[20] << 3) | (uid[21] << 2) - | (uid[22] << 1) | uid[23]; - uid_byte[3] = (uid[24] << 7) | (uid[25] << 6) | (uid[26] << 5) - | (uid[27] << 4) | (uid[28] << 3) | (uid[29] << 2) - | (uid[30] << 1) | uid[31]; - //Dbhexdump(10, rx, rxlen); - STATE = 1; - txlen = 45; - crc = CRC_PRESET; - calc_crc(&crc, 0x00, 5); - calc_crc(&crc, uid_byte[0], 8); - calc_crc(&crc, uid_byte[1], 8); - calc_crc(&crc, uid_byte[2], 8); - calc_crc(&crc, uid_byte[3], 8); - for (i = 0; i < 100; i++) { - response_bit[i] = 0; - } - for (i = 0; i < 5; i++) { - response_bit[i] = 0; - } - for (i = 5; i < 37; i++) { - response_bit[i] = uid[i - 5]; - } - for (j = 0; j < 8; j++) { - response_bit[i] = 0; - if ((crc & ((mask << 7) >> j)) != 0) - response_bit[i] = 1; - i++; - } - k = 0; - for (i = 0; i < 6; i++) { - tx[i] = (response_bit[k] << 7) | (response_bit[k + 1] << 6) - | (response_bit[k + 2] << 5) - | (response_bit[k + 3] << 4) - | (response_bit[k + 4] << 3) - | (response_bit[k + 5] << 2) - | (response_bit[k + 6] << 1) | response_bit[k + 7]; - k += 8; - } + tx = txbuf; + txlen = 0; + if (rxlen == 0) { + if (STATE == 2) + // challenge failed + Dbprintf("Challenge failed: %02X %02X %02X %02X %02X %02X %02X %02X", + unlocker[u1 - 1][0], unlocker[u1 - 1][1], + unlocker[u1 - 1][2], unlocker[u1 - 1][3], + unlocker[u1 - 1][4], unlocker[u1 - 1][5], + unlocker[u1 - 1][6], unlocker[u1 - 1][7]); + STATE = 0; + txlen = 5; + //start new authentication + memcpy(tx, "\xc0", nbytes(txlen)); + } else if (rxlen >= 67 && STATE == 0) { + //received uid + z = 0; + for (i = 0; i < 10; i++) { + for (j = 0; j < 8; j++) { + response_bit[z] = 0; + if ((rx[i] & ((mask << 7) >> j)) != 0) + response_bit[z] = 1; + z++; + } + } + k = 0; + for (i = 5; i < z; i += 2) { + uid[k] = response_bit[i]; + k++; + if (k > 31) + break; + } + uid_byte[0] = (uid[0] << 7) | (uid[1] << 6) | (uid[2] << 5) + | (uid[3] << 4) | (uid[4] << 3) | (uid[5] << 2) + | (uid[6] << 1) | uid[7]; + uid_byte[1] = (uid[8] << 7) | (uid[9] << 6) | (uid[10] << 5) + | (uid[11] << 4) | (uid[12] << 3) | (uid[13] << 2) + | (uid[14] << 1) | uid[15]; + uid_byte[2] = (uid[16] << 7) | (uid[17] << 6) | (uid[18] << 5) + | (uid[19] << 4) | (uid[20] << 3) | (uid[21] << 2) + | (uid[22] << 1) | uid[23]; + uid_byte[3] = (uid[24] << 7) | (uid[25] << 6) | (uid[26] << 5) + | (uid[27] << 4) | (uid[28] << 3) | (uid[29] << 2) + | (uid[30] << 1) | uid[31]; + //Dbhexdump(10, rx, rxlen); + STATE = 1; + txlen = 45; + crc = CRC_PRESET; + calc_crc(&crc, 0x00, 5); + calc_crc(&crc, uid_byte[0], 8); + calc_crc(&crc, uid_byte[1], 8); + calc_crc(&crc, uid_byte[2], 8); + calc_crc(&crc, uid_byte[3], 8); + for (i = 0; i < 100; i++) { + response_bit[i] = 0; + } + for (i = 0; i < 5; i++) { + response_bit[i] = 0; + } + for (i = 5; i < 37; i++) { + response_bit[i] = uid[i - 5]; + } + for (j = 0; j < 8; j++) { + response_bit[i] = 0; + if ((crc & ((mask << 7) >> j)) != 0) + response_bit[i] = 1; + i++; + } + k = 0; + for (i = 0; i < 6; i++) { + tx[i] = (response_bit[k] << 7) | (response_bit[k + 1] << 6) + | (response_bit[k + 2] << 5) + | (response_bit[k + 3] << 4) + | (response_bit[k + 4] << 3) + | (response_bit[k + 5] << 2) + | (response_bit[k + 6] << 1) | response_bit[k + 7]; + k += 8; + } - } else if (STATE == 1 && rxlen == 44) { - //received configuration - STATE = 2; - z = 0; - for (i = 0; i < 6; i++) { - for (j = 0; j < 8; j++) { - response_bit[z] = 0; - if ((rx[i] & ((mask << 7) >> j)) != 0) - response_bit[z] = 1; - z++; - } - } - txlen = 64; + } else if (STATE == 1 && rxlen == 44) { + //received configuration + STATE = 2; + z = 0; + for (i = 0; i < 6; i++) { + for (j = 0; j < 8; j++) { + response_bit[z] = 0; + if ((rx[i] & ((mask << 7) >> j)) != 0) + response_bit[z] = 1; + z++; + } + } + txlen = 64; - if (u1 >= (sizeof(unlocker) / sizeof(unlocker[0]))) - bStop = !false; - for (i = 0; i < 8; i++) - tx[i] = unlocker[u1][i]; - u1++; + if (u1 >= (sizeof(unlocker) / sizeof(unlocker[0]))) + bStop = !false; + for (i = 0; i < 8; i++) + tx[i] = unlocker[u1][i]; + u1++; - } else if (STATE == 2 && rxlen >= 44) { - STATE = 0; - } + } else if (STATE == 2 && rxlen >= 44) { + STATE = 0; + } - // Send and store the reader command - // Disable timer 1 with external trigger to avoid triggers during our own modulation - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + // Send and store the reader command + // Disable timer 1 with external trigger to avoid triggers during our own modulation + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, - // Since the clock counts since the last falling edge, a 'one' means that the - // falling edge occured halfway the period. with respect to this falling edge, - // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. - // All timer values are in terms of T0 units + // Wait for HITAG_T_WAIT_2 carrier periods after the last tag bit before transmitting, + // Since the clock counts since the last falling edge, a 'one' means that the + // falling edge occured halfway the period. with respect to this falling edge, + // we need to wait (T_Wait2 + half_tag_period) when the last was a 'one'. + // All timer values are in terms of T0 units - while (AT91C_BASE_TC0->TC_CV - < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) - ; + while (AT91C_BASE_TC0->TC_CV + < T0 * (t_wait + (HITAG_T_TAG_HALF_PERIOD * lastbit))) + ; - // Transmit the reader frame - hitag_reader_send_frame(tx, txlen); + // Transmit the reader frame + hitag_reader_send_frame(tx, txlen); - // Enable and reset external trigger in timer for capturing future frames - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + // Enable and reset external trigger in timer for capturing future frames + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - // Add transmitted frame to total count - if (txlen > 0) { - frame_count++; - if (!bQuiet) { - // Store the frame in the trace - if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { - if (bQuitTraceFull) { - DbpString("Trace full"); - break; - } else { - bQuiet = true; - } - } - } - } + // Add transmitted frame to total count + if (txlen > 0) { + frame_count++; + if (!bQuiet) { + // Store the frame in the trace + if (!LogTraceHitag(tx, txlen, HITAG_T_WAIT_2, 0, true)) { + if (bQuitTraceFull) { + DbpString("Trace full"); + break; + } else { + bQuiet = true; + } + } + } + } - // Reset values for receiving frames - memset(rx, 0x00, sizeof(rx)); - rxlen = 0; - lastbit = 1; - bSkip = true; - tag_sof = reset_sof; - response = 0; + // Reset values for receiving frames + memset(rx, 0x00, sizeof(rx)); + rxlen = 0; + lastbit = 1; + bSkip = true; + tag_sof = reset_sof; + response = 0; - // Receive frame, watch for at most T0*EOF periods - while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { - // Check if falling edge in tag modulation is detected - if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { - // Retrieve the new timing values - int ra = (AT91C_BASE_TC1->TC_RA / T0); + // Receive frame, watch for at most T0*EOF periods + while (AT91C_BASE_TC1->TC_CV < T0 * HITAG_T_WAIT_MAX) { + // Check if falling edge in tag modulation is detected + if (AT91C_BASE_TC1->TC_SR & AT91C_TC_LDRAS) { + // Retrieve the new timing values + int ra = (AT91C_BASE_TC1->TC_RA / T0); - // Reset timer every frame, we have to capture the last edge for timing - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + // Reset timer every frame, we have to capture the last edge for timing + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - LED_B_ON(); + LED_B_ON(); - // Capture tag frame (manchester decoding using only falling edges) - if (ra >= HITAG_T_EOF) { - if (rxlen != 0) { - //DbpString("wierd1?"); - } - // Capture the T0 periods that have passed since last communication or field drop (reset) - // We always recieve a 'one' first, which has the falling edge after a half period |-_| - response = ra - HITAG_T_TAG_HALF_PERIOD; - } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { - // Manchester coding example |-_|_-|-_| (101) - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { - // Manchester coding example |_-|...|_-|-_| (0...01) - rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); - rxlen++; - // We have to skip this half period at start and add the 'one' the second time - if (!bSkip) { - rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); - rxlen++; - } - lastbit = !lastbit; - bSkip = !bSkip; - } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { - // Manchester coding example |_-|_-| (00) or |-_|-_| (11) - if (tag_sof) { - // Ignore bits that are transmitted during SOF - tag_sof--; - } else { - // bit is same as last bit - rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8)); - rxlen++; - } - } else { - // Ignore wierd value, is to small to mean anything - } - } + // Capture tag frame (manchester decoding using only falling edges) + if (ra >= HITAG_T_EOF) { + if (rxlen != 0) { + //DbpString("wierd1?"); + } + // Capture the T0 periods that have passed since last communication or field drop (reset) + // We always recieve a 'one' first, which has the falling edge after a half period |-_| + response = ra - HITAG_T_TAG_HALF_PERIOD; + } else if (ra >= HITAG_T_TAG_CAPTURE_FOUR_HALF) { + // Manchester coding example |-_|_-|-_| (101) + rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); + rxlen++; + rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); + rxlen++; + } else if (ra >= HITAG_T_TAG_CAPTURE_THREE_HALF) { + // Manchester coding example |_-|...|_-|-_| (0...01) + rx[rxlen / 8] |= 0 << (7 - (rxlen % 8)); + rxlen++; + // We have to skip this half period at start and add the 'one' the second time + if (!bSkip) { + rx[rxlen / 8] |= 1 << (7 - (rxlen % 8)); + rxlen++; + } + lastbit = !lastbit; + bSkip = !bSkip; + } else if (ra >= HITAG_T_TAG_CAPTURE_TWO_HALF) { + // Manchester coding example |_-|_-| (00) or |-_|-_| (11) + if (tag_sof) { + // Ignore bits that are transmitted during SOF + tag_sof--; + } else { + // bit is same as last bit + rx[rxlen / 8] |= lastbit << (7 - (rxlen % 8)); + rxlen++; + } + } else { + // Ignore wierd value, is to small to mean anything + } + } - // We can break this loop if we received the last bit from a frame - if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { - if (rxlen > 0) - break; - } - } - } - LED_B_OFF(); - LED_D_OFF(); - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); + // We can break this loop if we received the last bit from a frame + if (AT91C_BASE_TC1->TC_CV > T0 * HITAG_T_EOF) { + if (rxlen > 0) + break; + } + } + } + LED_B_OFF(); + LED_D_OFF(); + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + cmd_send(CMD_ACK, bSuccessful, 0, 0, 0, 0); } diff --git a/armsrc/iclass.c b/armsrc/iclass.c index af85c18fc..7b529a999 100644 --- a/armsrc/iclass.c +++ b/armsrc/iclass.c @@ -61,10 +61,10 @@ int doIClassSimulation(int simulationMode, uint8_t *reader_mac_buf); // The length of a received command will in most cases be no more than 18 bytes. // 32 should be enough! #ifndef ICLASS_BUFFER_SIZE - #define ICLASS_BUFFER_SIZE 32 + #define ICLASS_BUFFER_SIZE 32 #endif -#define AddCrc(data, len) compute_crc(CRC_ICLASS, (data), (len), (data)+(len), (data)+(len)+1) +#define AddCrc(data, len) compute_crc(CRC_ICLASS, (data), (len), (data)+(len), (data)+(len)+1) //----------------------------------------------------------------------------- // The software UART that receives commands from the reader, and its state @@ -75,7 +75,7 @@ typedef struct { enum { STATE_UNSYNCD, STATE_START_OF_COMMUNICATION, - STATE_RECEIVING + STATE_RECEIVING } state; uint16_t shiftReg; int bitCnt; @@ -97,33 +97,33 @@ typedef struct { typedef struct { enum { DEMOD_UNSYNCD, - DEMOD_START_OF_COMMUNICATION, - DEMOD_START_OF_COMMUNICATION2, - DEMOD_START_OF_COMMUNICATION3, - DEMOD_SOF_COMPLETE, - DEMOD_MANCHESTER_D, - DEMOD_MANCHESTER_E, - DEMOD_END_OF_COMMUNICATION, - DEMOD_END_OF_COMMUNICATION2, - DEMOD_MANCHESTER_F, + DEMOD_START_OF_COMMUNICATION, + DEMOD_START_OF_COMMUNICATION2, + DEMOD_START_OF_COMMUNICATION3, + DEMOD_SOF_COMPLETE, + DEMOD_MANCHESTER_D, + DEMOD_MANCHESTER_E, + DEMOD_END_OF_COMMUNICATION, + DEMOD_END_OF_COMMUNICATION2, + DEMOD_MANCHESTER_F, DEMOD_ERROR_WAIT } state; int bitCount; int posCount; - int syncBit; + int syncBit; uint16_t shiftReg; - uint32_t buffer; - uint32_t buffer2; - uint32_t buffer3; - int buff; - int samples; + uint32_t buffer; + uint32_t buffer2; + uint32_t buffer3; + int buff; + int samples; int len; - enum { - SUB_NONE, - SUB_FIRST_HALF, - SUB_SECOND_HALF, - SUB_BOTH - } sub; + enum { + SUB_NONE, + SUB_FIRST_HALF, + SUB_SECOND_HALF, + SUB_BOTH + } sub; uint8_t *output; } tDemod; @@ -133,22 +133,22 @@ typedef struct { */ // Static vars for UART typedef struct { - bool synced; - bool frame; - bool frame_done; - uint8_t *buf; - int len; + bool synced; + bool frame; + bool frame_done; + uint8_t *buf; + int len; } tUart; static tUart Uart; static void uart_reset(void){ - Uart.frame_done = false; - Uart.synced = false; - Uart.frame = false; + Uart.frame_done = false; + Uart.synced = false; + Uart.frame = false; } static void uart_init(uint8_t *data){ - Uart.buf = data; - uart_reset(); + Uart.buf = data; + uart_reset(); } static void uart_bit(uint8_t bit) { static uint8_t buf = 0xff; @@ -159,7 +159,7 @@ static void uart_bit(uint8_t bit) { buf |= bit ? 1 : 0; if (!Uart.frame) { - if (buf == 0x7b) { // 0b0111 1011 + if (buf == 0x7b) { // 0b0111 1011 Uart.frame = true; n_buf = 0; Uart.len = 0; @@ -188,7 +188,7 @@ static void uart_bit(uint8_t bit) { break; default: Uart.frame = false; - Uart.synced = false; + Uart.synced = false; Dbprintf("[-] bad %02X at %d:%d", buf, Uart.len, nmsg_byte); } @@ -255,8 +255,8 @@ again: /* static void UartReset(){ - Uart.state = STATE_UNSYNCD; - Uart.shiftReg = 0; + Uart.state = STATE_UNSYNCD; + Uart.shiftReg = 0; Uart.bitCnt = 0; Uart.byteCnt = 0; Uart.posCnt = 0; @@ -279,220 +279,220 @@ static void UartReset(){ */ /* static RAMFUNC int OutOfNDecoding(int bit) { - //int error = 0; - int bitright; + //int error = 0; + int bitright; - if (!Uart.bitBuffer) { - Uart.bitBuffer = bit ^ 0xFF0; - return false; - } else { - Uart.bitBuffer <<= 4; - Uart.bitBuffer ^= bit; - } + if (!Uart.bitBuffer) { + Uart.bitBuffer = bit ^ 0xFF0; + return false; + } else { + Uart.bitBuffer <<= 4; + Uart.bitBuffer ^= bit; + } - // if (Uart.swapper) { - // Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF; - // Uart.byteCnt++; - // Uart.swapper = 0; - // if (Uart.byteCnt > 15) return true; - //} - //else { - // Uart.swapper = 1; - //} + // if (Uart.swapper) { + // Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF; + // Uart.byteCnt++; + // Uart.swapper = 0; + // if (Uart.byteCnt > 15) return true; + // } + // else { + // Uart.swapper = 1; + // } - if (Uart.state != STATE_UNSYNCD) { - Uart.posCnt++; + if (Uart.state != STATE_UNSYNCD) { + Uart.posCnt++; - if ((Uart.bitBuffer & Uart.syncBit) ^ Uart.syncBit) - bit = 0; - else - bit = 1; + if ((Uart.bitBuffer & Uart.syncBit) ^ Uart.syncBit) + bit = 0; + else + bit = 1; - if (((Uart.bitBuffer << 1) & Uart.syncBit) ^ Uart.syncBit) - bitright = 0; - else - bitright = 1; + if (((Uart.bitBuffer << 1) & Uart.syncBit) ^ Uart.syncBit) + bitright = 0; + else + bitright = 1; - if(bit != bitright) - bit = bitright; + if(bit != bitright) + bit = bitright; - // So, now we only have to deal with *bit*, lets see... - if (Uart.posCnt == 1) { - // measurement first half bitperiod - if (!bit) { - // Drop in first half means that we are either seeing - // an SOF or an EOF. + // So, now we only have to deal with *bit*, lets see... + if (Uart.posCnt == 1) { + // measurement first half bitperiod + if (!bit) { + // Drop in first half means that we are either seeing + // an SOF or an EOF. - if (Uart.nOutOfCnt == 1) { - // End of Communication - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - if (Uart.byteCnt == 0) { - // Its not straightforward to show single EOFs - // So just leave it and do not return TRUE - Uart.output[0] = 0xf0; - Uart.byteCnt++; - } else { - return true; - } - } else if (Uart.state != STATE_START_OF_COMMUNICATION) { - // When not part of SOF or EOF, it is an error - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - //error = 4; - } - } - } else { - // measurement second half bitperiod - // Count the bitslot we are in... (ISO 15693) - Uart.nOutOfCnt++; + if (Uart.nOutOfCnt == 1) { + // End of Communication + Uart.state = STATE_UNSYNCD; + Uart.highCnt = 0; + if (Uart.byteCnt == 0) { + // Its not straightforward to show single EOFs + // So just leave it and do not return TRUE + Uart.output[0] = 0xf0; + Uart.byteCnt++; + } else { + return true; + } + } else if (Uart.state != STATE_START_OF_COMMUNICATION) { + // When not part of SOF or EOF, it is an error + Uart.state = STATE_UNSYNCD; + Uart.highCnt = 0; + //error = 4; + } + } + } else { + // measurement second half bitperiod + // Count the bitslot we are in... (ISO 15693) + Uart.nOutOfCnt++; - if (!bit) { - if (Uart.dropPosition) { - if (Uart.state == STATE_START_OF_COMMUNICATION) { - //error = 1; - } else { - //error = 7; - } - // It is an error if we already have seen a drop in current frame - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - } else { - Uart.dropPosition = Uart.nOutOfCnt; - } - } - Uart.posCnt = 0; + if (!bit) { + if (Uart.dropPosition) { + if (Uart.state == STATE_START_OF_COMMUNICATION) { + //error = 1; + } else { + //error = 7; + } + // It is an error if we already have seen a drop in current frame + Uart.state = STATE_UNSYNCD; + Uart.highCnt = 0; + } else { + Uart.dropPosition = Uart.nOutOfCnt; + } + } + Uart.posCnt = 0; - if (Uart.nOutOfCnt == Uart.OutOfCnt && Uart.OutOfCnt == 4) { - Uart.nOutOfCnt = 0; + if (Uart.nOutOfCnt == Uart.OutOfCnt && Uart.OutOfCnt == 4) { + Uart.nOutOfCnt = 0; - if (Uart.state == STATE_START_OF_COMMUNICATION) { - if (Uart.dropPosition == 4) { - Uart.state = STATE_RECEIVING; - Uart.OutOfCnt = 256; - } else if (Uart.dropPosition == 3) { - Uart.state = STATE_RECEIVING; - Uart.OutOfCnt = 4; - //Uart.output[Uart.byteCnt] = 0xdd; - //Uart.byteCnt++; - } else { - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - } - Uart.dropPosition = 0; - } else { - // RECEIVING DATA - // 1 out of 4 - if (!Uart.dropPosition) { - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - //error = 9; - } else { - Uart.shiftReg >>= 2; + if (Uart.state == STATE_START_OF_COMMUNICATION) { + if (Uart.dropPosition == 4) { + Uart.state = STATE_RECEIVING; + Uart.OutOfCnt = 256; + } else if (Uart.dropPosition == 3) { + Uart.state = STATE_RECEIVING; + Uart.OutOfCnt = 4; + //Uart.output[Uart.byteCnt] = 0xdd; + //Uart.byteCnt++; + } else { + Uart.state = STATE_UNSYNCD; + Uart.highCnt = 0; + } + Uart.dropPosition = 0; + } else { + // RECEIVING DATA + // 1 out of 4 + if (!Uart.dropPosition) { + Uart.state = STATE_UNSYNCD; + Uart.highCnt = 0; + //error = 9; + } else { + Uart.shiftReg >>= 2; - // Swap bit order - Uart.dropPosition--; - //if(Uart.dropPosition == 1) { Uart.dropPosition = 2; } - //else if(Uart.dropPosition == 2) { Uart.dropPosition = 1; } + // Swap bit order + Uart.dropPosition--; + //if(Uart.dropPosition == 1) { Uart.dropPosition = 2; } + //else if(Uart.dropPosition == 2) { Uart.dropPosition = 1; } - Uart.shiftReg ^= ((Uart.dropPosition & 0x03) << 6); - Uart.bitCnt += 2; - Uart.dropPosition = 0; + Uart.shiftReg ^= ((Uart.dropPosition & 0x03) << 6); + Uart.bitCnt += 2; + Uart.dropPosition = 0; - if (Uart.bitCnt == 8) { - Uart.output[Uart.byteCnt] = (Uart.shiftReg & 0xff); - Uart.byteCnt++; - Uart.bitCnt = 0; - Uart.shiftReg = 0; - } - } - } - } else if (Uart.nOutOfCnt == Uart.OutOfCnt) { - // RECEIVING DATA - // 1 out of 256 - if (!Uart.dropPosition) { - Uart.state = STATE_UNSYNCD; - Uart.highCnt = 0; - //error = 3; - } else { - Uart.dropPosition--; - Uart.output[Uart.byteCnt] = (Uart.dropPosition & 0xff); - Uart.byteCnt++; - Uart.bitCnt = 0; - Uart.shiftReg = 0; - Uart.nOutOfCnt = 0; - Uart.dropPosition = 0; - } - } + if (Uart.bitCnt == 8) { + Uart.output[Uart.byteCnt] = (Uart.shiftReg & 0xff); + Uart.byteCnt++; + Uart.bitCnt = 0; + Uart.shiftReg = 0; + } + } + } + } else if (Uart.nOutOfCnt == Uart.OutOfCnt) { + // RECEIVING DATA + // 1 out of 256 + if (!Uart.dropPosition) { + Uart.state = STATE_UNSYNCD; + Uart.highCnt = 0; + //error = 3; + } else { + Uart.dropPosition--; + Uart.output[Uart.byteCnt] = (Uart.dropPosition & 0xff); + Uart.byteCnt++; + Uart.bitCnt = 0; + Uart.shiftReg = 0; + Uart.nOutOfCnt = 0; + Uart.dropPosition = 0; + } + } */ - /*if (error) { - Uart.output[Uart.byteCnt] = 0xAA; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = error & 0xFF; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = 0xAA; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = (Uart.bitBuffer >> 8) & 0xFF; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = (Uart.syncBit >> 3) & 0xFF; - Uart.byteCnt++; - Uart.output[Uart.byteCnt] = 0xAA; - Uart.byteCnt++; - return true; - }*/ + /*if (error) { + Uart.output[Uart.byteCnt] = 0xAA; + Uart.byteCnt++; + Uart.output[Uart.byteCnt] = error & 0xFF; + Uart.byteCnt++; + Uart.output[Uart.byteCnt] = 0xAA; + Uart.byteCnt++; + Uart.output[Uart.byteCnt] = (Uart.bitBuffer >> 8) & 0xFF; + Uart.byteCnt++; + Uart.output[Uart.byteCnt] = Uart.bitBuffer & 0xFF; + Uart.byteCnt++; + Uart.output[Uart.byteCnt] = (Uart.syncBit >> 3) & 0xFF; + Uart.byteCnt++; + Uart.output[Uart.byteCnt] = 0xAA; + Uart.byteCnt++; + return true; + }*/ /* - } - } else { - bit = Uart.bitBuffer & 0xf0; - bit >>= 4; - bit ^= 0x0F; // drops become 1s ;-) - if (bit) { - // should have been high or at least (4 * 128) / fc - // according to ISO this should be at least (9 * 128 + 20) / fc - if (Uart.highCnt == 8) { - // we went low, so this could be start of communication - // it turns out to be safer to choose a less significant - // syncbit... so we check whether the neighbour also represents the drop - Uart.posCnt = 1; // apparently we are busy with our first half bit period - Uart.syncBit = bit & 8; - Uart.samples = 3; + } + } else { + bit = Uart.bitBuffer & 0xf0; + bit >>= 4; + bit ^= 0x0F; // drops become 1s ;-) + if (bit) { + // should have been high or at least (4 * 128) / fc + // according to ISO this should be at least (9 * 128 + 20) / fc + if (Uart.highCnt == 8) { + // we went low, so this could be start of communication + // it turns out to be safer to choose a less significant + // syncbit... so we check whether the neighbour also represents the drop + Uart.posCnt = 1; // apparently we are busy with our first half bit period + Uart.syncBit = bit & 8; + Uart.samples = 3; - if (!Uart.syncBit) { Uart.syncBit = bit & 4; Uart.samples = 2; } - else if (bit & 4) { Uart.syncBit = bit & 4; Uart.samples = 2; bit <<= 2; } + if (!Uart.syncBit) { Uart.syncBit = bit & 4; Uart.samples = 2; } + else if (bit & 4) { Uart.syncBit = bit & 4; Uart.samples = 2; bit <<= 2; } - if (!Uart.syncBit) { Uart.syncBit = bit & 2; Uart.samples = 1; } - else if (bit & 2) { Uart.syncBit = bit & 2; Uart.samples = 1; bit <<= 1; } + if (!Uart.syncBit) { Uart.syncBit = bit & 2; Uart.samples = 1; } + else if (bit & 2) { Uart.syncBit = bit & 2; Uart.samples = 1; bit <<= 1; } - if (!Uart.syncBit) { Uart.syncBit = bit & 1; Uart.samples = 0; - if (Uart.syncBit && (Uart.bitBuffer & 8)) { - Uart.syncBit = 8; + if (!Uart.syncBit) { Uart.syncBit = bit & 1; Uart.samples = 0; + if (Uart.syncBit && (Uart.bitBuffer & 8)) { + Uart.syncBit = 8; - // the first half bit period is expected in next sample - Uart.posCnt = 0; - Uart.samples = 3; - } - } else if (bit & 1) { Uart.syncBit = bit & 1; Uart.samples = 0; } + // the first half bit period is expected in next sample + Uart.posCnt = 0; + Uart.samples = 3; + } + } else if (bit & 1) { Uart.syncBit = bit & 1; Uart.samples = 0; } - Uart.syncBit <<= 4; - Uart.state = STATE_START_OF_COMMUNICATION; - Uart.bitCnt = 0; - Uart.byteCnt = 0; - Uart.nOutOfCnt = 0; - Uart.OutOfCnt = 4; // Start at 1/4, could switch to 1/256 - Uart.dropPosition = 0; - Uart.shiftReg = 0; - //error = 0; - } else { - Uart.highCnt = 0; - } - } else { - if (Uart.highCnt < 8) - Uart.highCnt++; - } - } + Uart.syncBit <<= 4; + Uart.state = STATE_START_OF_COMMUNICATION; + Uart.bitCnt = 0; + Uart.byteCnt = 0; + Uart.nOutOfCnt = 0; + Uart.OutOfCnt = 4; // Start at 1/4, could switch to 1/256 + Uart.dropPosition = 0; + Uart.shiftReg = 0; + //error = 0; + } else { + Uart.highCnt = 0; + } + } else { + if (Uart.highCnt < 8) + Uart.highCnt++; + } + } return false; } */ @@ -501,22 +501,22 @@ static RAMFUNC int OutOfNDecoding(int bit) { //============================================================================= static tDemod Demod; static void DemodReset() { - Demod.bitCount = 0; - Demod.posCount = 0; - Demod.syncBit = 0; - Demod.shiftReg = 0; - Demod.buffer = 0; - Demod.buffer2 = 0; - Demod.buffer3 = 0; - Demod.buff = 0; - Demod.samples = 0; - Demod.len = 0; - Demod.sub = SUB_NONE; - Demod.state = DEMOD_UNSYNCD; + Demod.bitCount = 0; + Demod.posCount = 0; + Demod.syncBit = 0; + Demod.shiftReg = 0; + Demod.buffer = 0; + Demod.buffer2 = 0; + Demod.buffer3 = 0; + Demod.buff = 0; + Demod.samples = 0; + Demod.len = 0; + Demod.sub = SUB_NONE; + Demod.state = DEMOD_UNSYNCD; } static void DemodInit(uint8_t *data) { - Demod.output = data; - DemodReset(); + Demod.output = data; + DemodReset(); } // UART debug @@ -541,23 +541,23 @@ Recorded Activity (TraceLen = 162 bytes) 3232 | 3232 | Tag |bb! d4! bb! 02 02 08 04 bb! | ok | */ static void uart_debug(int error, int bit) { - Demod.output[Demod.len] = 0xBB; - Demod.len++; - Demod.output[Demod.len] = error & 0xFF; - Demod.len++; - Demod.output[Demod.len] = 0xBB; - Demod.len++; - Demod.output[Demod.len] = bit & 0xFF; - Demod.len++; - Demod.output[Demod.len] = Demod.buffer & 0xFF; - Demod.len++; - // Look harder ;-) - Demod.output[Demod.len] = Demod.buffer2 & 0xFF; - Demod.len++; - Demod.output[Demod.len] = Demod.syncBit & 0xFF; - Demod.len++; - Demod.output[Demod.len] = 0xBB; - Demod.len++; + Demod.output[Demod.len] = 0xBB; + Demod.len++; + Demod.output[Demod.len] = error & 0xFF; + Demod.len++; + Demod.output[Demod.len] = 0xBB; + Demod.len++; + Demod.output[Demod.len] = bit & 0xFF; + Demod.len++; + Demod.output[Demod.len] = Demod.buffer & 0xFF; + Demod.len++; + // Look harder ;-) + Demod.output[Demod.len] = Demod.buffer2 & 0xFF; + Demod.len++; + Demod.output[Demod.len] = Demod.syncBit & 0xFF; + Demod.len++; + Demod.output[Demod.len] = 0xBB; + Demod.len++; } /* @@ -569,219 +569,219 @@ static void uart_debug(int error, int bit) { * ISO 15693-2 * Tout = 330 µs, Tprog 1 = 4 to 15 ms, Tslot = 330 µs + (number of slots x 160 µs) * ISO 14443a -* Tout = 100 µs, Tprog = 4 to 15 ms, Tslot = 100 µs+ (number of slots x 80 µs) +* Tout = 100 µs, Tprog = 4 to 15 ms, Tslot = 100 µs+ (number of slots x 80 µs) * ISO 14443b - Tout = 76 µs, Tprog = 4 to 15 ms, Tslot = 119 µs+ (number of slots x 150 µs) + Tout = 76 µs, Tprog = 4 to 15 ms, Tslot = 119 µs+ (number of slots x 150 µs) * * * So for current implementation in ISO15693, its 330 µs from end of reader, to start of card. */ static RAMFUNC int ManchesterDecoding_iclass( uint32_t v) { - int bit; - int modulation; - int error = 0; + int bit; + int modulation; + int error = 0; - bit = Demod.buffer; - Demod.buffer = Demod.buffer2; - Demod.buffer2 = Demod.buffer3; - Demod.buffer3 = v; + bit = Demod.buffer; + Demod.buffer = Demod.buffer2; + Demod.buffer2 = Demod.buffer3; + Demod.buffer3 = v; - // too few bits? - if (Demod.buff < 3) { - Demod.buff++; - return false; - } + // too few bits? + if (Demod.buff < 3) { + Demod.buff++; + return false; + } - if (Demod.state == DEMOD_UNSYNCD) { - Demod.output[Demod.len] = 0xfa; - Demod.syncBit = 0; - //Demod.samples = 0; - Demod.posCount = 1; // This is the first half bit period, so after syncing handle the second part + if (Demod.state == DEMOD_UNSYNCD) { + Demod.output[Demod.len] = 0xfa; + Demod.syncBit = 0; + //Demod.samples = 0; + Demod.posCount = 1; // This is the first half bit period, so after syncing handle the second part - if (bit & 0x08) - Demod.syncBit = 0x08; + if (bit & 0x08) + Demod.syncBit = 0x08; - if (bit & 0x04) { - if (Demod.syncBit) - bit <<= 4; + if (bit & 0x04) { + if (Demod.syncBit) + bit <<= 4; - Demod.syncBit = 0x04; - } + Demod.syncBit = 0x04; + } - if (bit & 0x02) { - if (Demod.syncBit) - bit <<= 2; + if (bit & 0x02) { + if (Demod.syncBit) + bit <<= 2; - Demod.syncBit = 0x02; - } + Demod.syncBit = 0x02; + } - if (bit & 0x01 && Demod.syncBit) - Demod.syncBit = 0x01; + if (bit & 0x01 && Demod.syncBit) + Demod.syncBit = 0x01; - if (Demod.syncBit) { - Demod.len = 0; - Demod.state = DEMOD_START_OF_COMMUNICATION; - Demod.sub = SUB_FIRST_HALF; - Demod.bitCount = 0; - Demod.shiftReg = 0; - Demod.samples = 0; + if (Demod.syncBit) { + Demod.len = 0; + Demod.state = DEMOD_START_OF_COMMUNICATION; + Demod.sub = SUB_FIRST_HALF; + Demod.bitCount = 0; + Demod.shiftReg = 0; + Demod.samples = 0; - if (Demod.posCount) { + if (Demod.posCount) { - switch (Demod.syncBit) { - case 0x08: Demod.samples = 3; break; - case 0x04: Demod.samples = 2; break; - case 0x02: Demod.samples = 1; break; - case 0x01: Demod.samples = 0; break; - } - // SOF must be long burst... otherwise stay unsynced!!! - if (!(Demod.buffer & Demod.syncBit) || !(Demod.buffer2 & Demod.syncBit)) - Demod.state = DEMOD_UNSYNCD; + switch (Demod.syncBit) { + case 0x08: Demod.samples = 3; break; + case 0x04: Demod.samples = 2; break; + case 0x02: Demod.samples = 1; break; + case 0x01: Demod.samples = 0; break; + } + // SOF must be long burst... otherwise stay unsynced!!! + if (!(Demod.buffer & Demod.syncBit) || !(Demod.buffer2 & Demod.syncBit)) + Demod.state = DEMOD_UNSYNCD; - } else { - // SOF must be long burst... otherwise stay unsynced!!! - if (!(Demod.buffer2 & Demod.syncBit) || !(Demod.buffer3 & Demod.syncBit)) { - Demod.state = DEMOD_UNSYNCD; - error = 0x88; - uart_debug(error, bit); - return false; - } - } - error = 0; - } - return false; - } + } else { + // SOF must be long burst... otherwise stay unsynced!!! + if (!(Demod.buffer2 & Demod.syncBit) || !(Demod.buffer3 & Demod.syncBit)) { + Demod.state = DEMOD_UNSYNCD; + error = 0x88; + uart_debug(error, bit); + return false; + } + } + error = 0; + } + return false; + } - // state is DEMOD is in SYNC from here on. + // state is DEMOD is in SYNC from here on. - modulation = bit & Demod.syncBit; - modulation |= ((bit << 1) ^ ((Demod.buffer & 0x08) >> 3)) & Demod.syncBit; - Demod.samples += 4; + modulation = bit & Demod.syncBit; + modulation |= ((bit << 1) ^ ((Demod.buffer & 0x08) >> 3)) & Demod.syncBit; + Demod.samples += 4; - if (Demod.posCount == 0) { - Demod.posCount = 1; - Demod.sub = (modulation) ? SUB_FIRST_HALF : SUB_NONE; - return false; - } + if (Demod.posCount == 0) { + Demod.posCount = 1; + Demod.sub = (modulation) ? SUB_FIRST_HALF : SUB_NONE; + return false; + } - Demod.posCount = 0; + Demod.posCount = 0; - if (modulation) { + if (modulation) { - if (Demod.sub == SUB_FIRST_HALF) - Demod.sub = SUB_BOTH; - else - Demod.sub = SUB_SECOND_HALF; - } + if (Demod.sub == SUB_FIRST_HALF) + Demod.sub = SUB_BOTH; + else + Demod.sub = SUB_SECOND_HALF; + } - if (Demod.sub == SUB_NONE) { - if (Demod.state == DEMOD_SOF_COMPLETE) { - Demod.output[Demod.len] = 0x0f; - Demod.len++; - Demod.state = DEMOD_UNSYNCD; - return true; - } else { - Demod.state = DEMOD_ERROR_WAIT; - error = 0x33; - } - } + if (Demod.sub == SUB_NONE) { + if (Demod.state == DEMOD_SOF_COMPLETE) { + Demod.output[Demod.len] = 0x0f; + Demod.len++; + Demod.state = DEMOD_UNSYNCD; + return true; + } else { + Demod.state = DEMOD_ERROR_WAIT; + error = 0x33; + } + } - switch (Demod.state) { + switch (Demod.state) { - case DEMOD_START_OF_COMMUNICATION: - if (Demod.sub == SUB_BOTH) { + case DEMOD_START_OF_COMMUNICATION: + if (Demod.sub == SUB_BOTH) { - Demod.state = DEMOD_START_OF_COMMUNICATION2; - Demod.posCount = 1; - Demod.sub = SUB_NONE; - } else { - Demod.output[Demod.len] = 0xab; - Demod.state = DEMOD_ERROR_WAIT; - error = 0xd2; - } - break; + Demod.state = DEMOD_START_OF_COMMUNICATION2; + Demod.posCount = 1; + Demod.sub = SUB_NONE; + } else { + Demod.output[Demod.len] = 0xab; + Demod.state = DEMOD_ERROR_WAIT; + error = 0xd2; + } + break; - case DEMOD_START_OF_COMMUNICATION2: - if (Demod.sub == SUB_SECOND_HALF) { - Demod.state = DEMOD_START_OF_COMMUNICATION3; - } else { - Demod.output[Demod.len] = 0xab; - Demod.state = DEMOD_ERROR_WAIT; - error = 0xd3; - } - break; + case DEMOD_START_OF_COMMUNICATION2: + if (Demod.sub == SUB_SECOND_HALF) { + Demod.state = DEMOD_START_OF_COMMUNICATION3; + } else { + Demod.output[Demod.len] = 0xab; + Demod.state = DEMOD_ERROR_WAIT; + error = 0xd3; + } + break; - case DEMOD_START_OF_COMMUNICATION3: - if (Demod.sub == SUB_SECOND_HALF) { - Demod.state = DEMOD_SOF_COMPLETE; - } else { - Demod.output[Demod.len] = 0xab; - Demod.state = DEMOD_ERROR_WAIT; - error = 0xd4; - } - break; + case DEMOD_START_OF_COMMUNICATION3: + if (Demod.sub == SUB_SECOND_HALF) { + Demod.state = DEMOD_SOF_COMPLETE; + } else { + Demod.output[Demod.len] = 0xab; + Demod.state = DEMOD_ERROR_WAIT; + error = 0xd4; + } + break; - case DEMOD_SOF_COMPLETE: - case DEMOD_MANCHESTER_D: - case DEMOD_MANCHESTER_E: - // OPPOSITE FROM ISO14443 - 11110000 = 0 (1 in 14443) - // 00001111 = 1 (0 in 14443) - if (Demod.sub == SUB_SECOND_HALF) { // SUB_FIRST_HALF - Demod.bitCount++; - Demod.shiftReg = (Demod.shiftReg >> 1) ^ 0x100; - Demod.state = DEMOD_MANCHESTER_D; - } else if (Demod.sub == SUB_FIRST_HALF) { // SUB_SECOND_HALF - Demod.bitCount++; - Demod.shiftReg >>= 1; - Demod.state = DEMOD_MANCHESTER_E; - } else if (Demod.sub == SUB_BOTH) { - Demod.state = DEMOD_MANCHESTER_F; - } else { - Demod.state = DEMOD_ERROR_WAIT; - error = 0x55; - } - break; + case DEMOD_SOF_COMPLETE: + case DEMOD_MANCHESTER_D: + case DEMOD_MANCHESTER_E: + // OPPOSITE FROM ISO14443 - 11110000 = 0 (1 in 14443) + // 00001111 = 1 (0 in 14443) + if (Demod.sub == SUB_SECOND_HALF) { // SUB_FIRST_HALF + Demod.bitCount++; + Demod.shiftReg = (Demod.shiftReg >> 1) ^ 0x100; + Demod.state = DEMOD_MANCHESTER_D; + } else if (Demod.sub == SUB_FIRST_HALF) { // SUB_SECOND_HALF + Demod.bitCount++; + Demod.shiftReg >>= 1; + Demod.state = DEMOD_MANCHESTER_E; + } else if (Demod.sub == SUB_BOTH) { + Demod.state = DEMOD_MANCHESTER_F; + } else { + Demod.state = DEMOD_ERROR_WAIT; + error = 0x55; + } + break; - case DEMOD_MANCHESTER_F: - // Tag response does not need to be a complete byte! - if (Demod.len > 0 || Demod.bitCount > 0) { - if (Demod.bitCount > 1) { // was > 0, do not interpret last closing bit, is part of EOF - Demod.shiftReg >>= (9 - Demod.bitCount); // right align data - Demod.output[Demod.len] = Demod.shiftReg & 0xff; - Demod.len++; - } + case DEMOD_MANCHESTER_F: + // Tag response does not need to be a complete byte! + if (Demod.len > 0 || Demod.bitCount > 0) { + if (Demod.bitCount > 1) { // was > 0, do not interpret last closing bit, is part of EOF + Demod.shiftReg >>= (9 - Demod.bitCount); // right align data + Demod.output[Demod.len] = Demod.shiftReg & 0xff; + Demod.len++; + } - Demod.state = DEMOD_UNSYNCD; - return true; - } else { - Demod.output[Demod.len] = 0xad; - Demod.state = DEMOD_ERROR_WAIT; - error = 0x03; - } - break; + Demod.state = DEMOD_UNSYNCD; + return true; + } else { + Demod.output[Demod.len] = 0xad; + Demod.state = DEMOD_ERROR_WAIT; + error = 0x03; + } + break; - case DEMOD_ERROR_WAIT: - Demod.state = DEMOD_UNSYNCD; - break; + case DEMOD_ERROR_WAIT: + Demod.state = DEMOD_UNSYNCD; + break; - default: - Demod.output[Demod.len] = 0xdd; - Demod.state = DEMOD_UNSYNCD; - break; - } + default: + Demod.output[Demod.len] = 0xdd; + Demod.state = DEMOD_UNSYNCD; + break; + } - if (Demod.bitCount >= 8) { - Demod.shiftReg >>= 1; - Demod.output[Demod.len] = (Demod.shiftReg & 0xff); - Demod.len++; - Demod.bitCount = 0; - Demod.shiftReg = 0; - } + if (Demod.bitCount >= 8) { + Demod.shiftReg >>= 1; + Demod.output[Demod.len] = (Demod.shiftReg & 0xff); + Demod.len++; + Demod.bitCount = 0; + Demod.shiftReg = 0; + } - if (error) { - uart_debug(error, bit); - return true; - } + if (error) { + uart_debug(error, bit); + return true; + } return false; } @@ -791,49 +791,49 @@ static RAMFUNC int ManchesterDecoding_iclass( uint32_t v) { // Both sides of communication! //============================================================================= static void iclass_setup_sniff(void){ - if (MF_DBGLEVEL > 3) Dbprintf("iclass_setup_sniff Enter"); + if (MF_DBGLEVEL > 3) Dbprintf("iclass_setup_sniff Enter"); - LEDsoff(); + LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - // connect Demodulated Signal to ADC: - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + // connect Demodulated Signal to ADC: + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - // Set up the synchronous serial port - FpgaSetupSsc(); + // Set up the synchronous serial port + FpgaSetupSsc(); - BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); - set_tracing(true); + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); - // Initialize Demod and Uart structs - DemodInit(BigBuf_malloc(ICLASS_BUFFER_SIZE)); + // Initialize Demod and Uart structs + DemodInit(BigBuf_malloc(ICLASS_BUFFER_SIZE)); - uart_init(BigBuf_malloc(ICLASS_BUFFER_SIZE)); - //UartInit(BigBuf_malloc(ICLASS_BUFFER_SIZE)); + uart_init(BigBuf_malloc(ICLASS_BUFFER_SIZE)); + //UartInit(BigBuf_malloc(ICLASS_BUFFER_SIZE)); - if (MF_DBGLEVEL > 1) { - // Print debug information about the buffer sizes - Dbprintf("[+] Sniffing buffers initialized:"); - Dbprintf(" Trace: %i bytes", BigBuf_max_traceLen()); - Dbprintf(" Reader -> tag: %i bytes", ICLASS_BUFFER_SIZE); - Dbprintf(" tag -> Reader: %i bytes", ICLASS_BUFFER_SIZE); - Dbprintf(" DMA: %i bytes", ICLASS_DMA_BUFFER_SIZE); - } + if (MF_DBGLEVEL > 1) { + // Print debug information about the buffer sizes + Dbprintf("[+] Sniffing buffers initialized:"); + Dbprintf(" Trace: %i bytes", BigBuf_max_traceLen()); + Dbprintf(" Reader -> tag: %i bytes", ICLASS_BUFFER_SIZE); + Dbprintf(" tag -> Reader: %i bytes", ICLASS_BUFFER_SIZE); + Dbprintf(" DMA: %i bytes", ICLASS_DMA_BUFFER_SIZE); + } - // Set FPGA in the appropriate mode + // Set FPGA in the appropriate mode // put the FPGA in the appropriate mode FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_SNIFFER); - SpinDelay(200); + SpinDelay(200); - // Start the SSP timer - StartCountSspClk(); + // Start the SSP timer + StartCountSspClk(); - LED_A_ON(); - if (MF_DBGLEVEL > 3) Dbprintf("[+] iclass_setup_sniff Exit"); + LED_A_ON(); + if (MF_DBGLEVEL > 3) Dbprintf("[+] iclass_setup_sniff Exit"); } //----------------------------------------------------------------------------- @@ -844,130 +844,130 @@ static void iclass_setup_sniff(void){ // turn off afterwards void RAMFUNC SniffIClass(void) { - //int datalen = 0; - uint32_t previous_data = 0; - uint32_t time_0 = 0, time_start = 0, time_stop = 0; + //int datalen = 0; + uint32_t previous_data = 0; + uint32_t time_0 = 0, time_start = 0, time_stop = 0; uint32_t sniffCounter = 0; - bool TagIsActive = false; - bool ReaderIsActive = false; + bool TagIsActive = false; + bool ReaderIsActive = false; - iclass_setup_sniff(); + iclass_setup_sniff(); // The DMA buffer, used to stream samples from the FPGA - // *dmaBuf is the start reference. + // *dmaBuf is the start reference. uint8_t *dmaBuf = BigBuf_malloc(ICLASS_DMA_BUFFER_SIZE); - // pointer to samples from fpga + // pointer to samples from fpga uint8_t *data = dmaBuf; - // Setup and start DMA. - if ( !FpgaSetupSscDma(dmaBuf, ICLASS_DMA_BUFFER_SIZE) ){ - if (MF_DBGLEVEL > 1) DbpString("[-] FpgaSetupSscDma failed. Exiting"); - return; - } + // Setup and start DMA. + if ( !FpgaSetupSscDma(dmaBuf, ICLASS_DMA_BUFFER_SIZE) ){ + if (MF_DBGLEVEL > 1) DbpString("[-] FpgaSetupSscDma failed. Exiting"); + return; + } - // time ZERO, the point from which it all is calculated. - time_0 = GetCountSspClk(); + // time ZERO, the point from which it all is calculated. + time_0 = GetCountSspClk(); - int div = 0; - uint8_t tag_byte = 0, foo = 0; + int div = 0; + uint8_t tag_byte = 0, foo = 0; // loop and listen - // every sample (1byte in data), - // contains HIGH nibble = reader data - // contains LOW nibble = tag data - // so two bytes are needed in order to get 1byte of either reader or tag data. (ie 2 sample bytes) - // since reader data is manchester encoded, we need 2bytes of data in order to get one demoded byte. (ie: 4 sample bytes) - while (!BUTTON_PRESS()) { + // every sample (1byte in data), + // contains HIGH nibble = reader data + // contains LOW nibble = tag data + // so two bytes are needed in order to get 1byte of either reader or tag data. (ie 2 sample bytes) + // since reader data is manchester encoded, we need 2bytes of data in order to get one demoded byte. (ie: 4 sample bytes) + while (!BUTTON_PRESS()) { WDT_HIT(); - previous_data <<= 8; - previous_data |= *data; + previous_data <<= 8; + previous_data |= *data; - sniffCounter++; - data++; + sniffCounter++; + data++; - if (data == dmaBuf + ICLASS_DMA_BUFFER_SIZE) { - data = dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RNCR = ICLASS_DMA_BUFFER_SIZE; - } + if (data == dmaBuf + ICLASS_DMA_BUFFER_SIZE) { + data = dmaBuf; + AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; + AT91C_BASE_PDC_SSC->PDC_RNCR = ICLASS_DMA_BUFFER_SIZE; + } - if ( *data & 0xF) { - //tag_byte <<= 1; - tag_byte ^= (1 << 4); - foo ^= (1 << (3 - div)); - Dbprintf(" %d|%x == %d|%x", tag_byte, tag_byte, foo, foo); - } - div++; + if ( *data & 0xF) { + //tag_byte <<= 1; + tag_byte ^= (1 << 4); + foo ^= (1 << (3 - div)); + Dbprintf(" %d|%x == %d|%x", tag_byte, tag_byte, foo, foo); + } + div++; - // every odd sample - if (sniffCounter & 0x01) { - // no need to try decoding reader data if the tag is sending - // READER TO CARD - if (!TagIsActive) { - LED_C_INV(); - // HIGH nibble is always reader data. - uint8_t reader_byte = (previous_data & 0xF0) | (*data >> 4); - uart_samples(reader_byte); - if (Uart.frame_done) { - time_stop = GetCountSspClk() - time_0; - LogTrace( Uart.buf, Uart.len, time_start, time_stop, NULL, true); - DemodReset(); - uart_reset(); - } else { - time_start = GetCountSspClk() - time_0; - } - ReaderIsActive = Uart.frame_done; - } - } - // every four sample - if ( (sniffCounter % 4) == 0) { - // need two samples to feed Manchester - // no need to try decoding tag data if the reader is sending - and we cannot afford the time - // CARD TO READER - if (!ReaderIsActive) { - LED_C_INV(); - // LOW nibble is always tag data. - /* + // every odd sample + if (sniffCounter & 0x01) { + // no need to try decoding reader data if the tag is sending + // READER TO CARD + if (!TagIsActive) { + LED_C_INV(); + // HIGH nibble is always reader data. + uint8_t reader_byte = (previous_data & 0xF0) | (*data >> 4); + uart_samples(reader_byte); + if (Uart.frame_done) { + time_stop = GetCountSspClk() - time_0; + LogTrace( Uart.buf, Uart.len, time_start, time_stop, NULL, true); + DemodReset(); + uart_reset(); + } else { + time_start = GetCountSspClk() - time_0; + } + ReaderIsActive = Uart.frame_done; + } + } + // every four sample + if ( (sniffCounter % 4) == 0) { + // need two samples to feed Manchester + // no need to try decoding tag data if the reader is sending - and we cannot afford the time + // CARD TO READER + if (!ReaderIsActive) { + LED_C_INV(); + // LOW nibble is always tag data. + /* - uint32_t tag_byte = - ((previous_data & 0x0F000000) >> 8 ) | - ((previous_data & 0x000F0000) >> 4 ) | - ((previous_data & 0x00000F00) ) | - ((previous_data & 0x0000000F) << 4 ) | - (*data & 0xF); - */ + uint32_t tag_byte = + ((previous_data & 0x0F000000) >> 8 ) | + ((previous_data & 0x000F0000) >> 4 ) | + ((previous_data & 0x00000F00) ) | + ((previous_data & 0x0000000F) << 4 ) | + (*data & 0xF); + */ - //uint8_t tag_byte = ((previous_data & 0xF) << 4 ) | (*data & 0xF); - if (ManchesterDecoding_iclass(foo)) { - time_stop = GetCountSspClk() - time_0; - LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false); - DemodReset(); - uart_reset(); - } else { - time_start = GetCountSspClk() - time_0; - } - TagIsActive = (Demod.state != DEMOD_UNSYNCD); - } - tag_byte = 0; - foo = 0; - div = 0; - } - } // end main loop + //uint8_t tag_byte = ((previous_data & 0xF) << 4 ) | (*data & 0xF); + if (ManchesterDecoding_iclass(foo)) { + time_stop = GetCountSspClk() - time_0; + LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false); + DemodReset(); + uart_reset(); + } else { + time_start = GetCountSspClk() - time_0; + } + TagIsActive = (Demod.state != DEMOD_UNSYNCD); + } + tag_byte = 0; + foo = 0; + div = 0; + } + } // end main loop - if (MF_DBGLEVEL >= 1) { - DbpString("[+] Sniff statistics:"); - Dbhexdump(ICLASS_DMA_BUFFER_SIZE, data, false); - } + if (MF_DBGLEVEL >= 1) { + DbpString("[+] Sniff statistics:"); + Dbhexdump(ICLASS_DMA_BUFFER_SIZE, data, false); + } - switch_off(); + switch_off(); } void rotateCSN(uint8_t* originalCSN, uint8_t* rotatedCSN) { - int i; - for(i = 0; i < 8; i++) - rotatedCSN[i] = (originalCSN[i] >> 3) | (originalCSN[(i+1)%8] << 5); + int i; + for(i = 0; i < 8; i++) + rotatedCSN[i] = (originalCSN[i] >> 3) | (originalCSN[(i+1)%8] << 5); } //----------------------------------------------------------------------------- @@ -981,142 +981,142 @@ static bool GetIClassCommandFromReader(uint8_t *received, int *len, int maxLen) // only, since we are receiving, not transmitting). // Signal field is off with the appropriate LED LED_D_OFF(); - uart_init(received); + uart_init(received); FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); - // clear RXRDY: + // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - while (!BUTTON_PRESS()) { + while (!BUTTON_PRESS()) { WDT_HIT(); - // keep tx buffer in a defined state anyway. + // keep tx buffer in a defined state anyway. if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) AT91C_BASE_SSC->SSC_THR = 0x00; - // wait for byte to become available in rx holding register + // wait for byte to become available in rx holding register if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; uart_samples(b); if (Uart.frame_done) { *len = Uart.len; - return true; - } + return true; + } } } - return false; + return false; } static uint8_t encode4Bits(const uint8_t b) { - // OTA, the least significant bits first - // Manchester encoding added - // The columns are - // 1 - Bit value to send - // 2 - Reversed (big-endian) - // 3 - Machester Encoded - // 4 - Hex values + // OTA, the least significant bits first + // Manchester encoding added + // The columns are + // 1 - Bit value to send + // 2 - Reversed (big-endian) + // 3 - Machester Encoded + // 4 - Hex values - uint8_t c = b & 0xF; - switch (c) { - // 1 2 3 4 - case 15: return 0x55; // 1111 -> 1111 -> 01010101 -> 0x55 - case 14: return 0x95; // 1110 -> 0111 -> 10010101 -> 0x95 - case 13: return 0x65; // 1101 -> 1011 -> 01100101 -> 0x65 - case 12: return 0xa5; // 1100 -> 0011 -> 10100101 -> 0xa5 - case 11: return 0x59; // 1011 -> 1101 -> 01011001 -> 0x59 - case 10: return 0x99; // 1010 -> 0101 -> 10011001 -> 0x99 - case 9: return 0x69; // 1001 -> 1001 -> 01101001 -> 0x69 - case 8: return 0xa9; // 1000 -> 0001 -> 10101001 -> 0xa9 - case 7: return 0x56; // 0111 -> 1110 -> 01010110 -> 0x56 - case 6: return 0x96; // 0110 -> 0110 -> 10010110 -> 0x96 - case 5: return 0x66; // 0101 -> 1010 -> 01100110 -> 0x66 - case 4: return 0xa6; // 0100 -> 0010 -> 10100110 -> 0xa6 - case 3: return 0x5a; // 0011 -> 1100 -> 01011010 -> 0x5a - case 2: return 0x9a; // 0010 -> 0100 -> 10011010 -> 0x9a - case 1: return 0x6a; // 0001 -> 1000 -> 01101010 -> 0x6a - default: return 0xaa; // 0000 -> 0000 -> 10101010 -> 0xaa - } + uint8_t c = b & 0xF; + switch (c) { + // 1 2 3 4 + case 15: return 0x55; // 1111 -> 1111 -> 01010101 -> 0x55 + case 14: return 0x95; // 1110 -> 0111 -> 10010101 -> 0x95 + case 13: return 0x65; // 1101 -> 1011 -> 01100101 -> 0x65 + case 12: return 0xa5; // 1100 -> 0011 -> 10100101 -> 0xa5 + case 11: return 0x59; // 1011 -> 1101 -> 01011001 -> 0x59 + case 10: return 0x99; // 1010 -> 0101 -> 10011001 -> 0x99 + case 9: return 0x69; // 1001 -> 1001 -> 01101001 -> 0x69 + case 8: return 0xa9; // 1000 -> 0001 -> 10101001 -> 0xa9 + case 7: return 0x56; // 0111 -> 1110 -> 01010110 -> 0x56 + case 6: return 0x96; // 0110 -> 0110 -> 10010110 -> 0x96 + case 5: return 0x66; // 0101 -> 1010 -> 01100110 -> 0x66 + case 4: return 0xa6; // 0100 -> 0010 -> 10100110 -> 0xa6 + case 3: return 0x5a; // 0011 -> 1100 -> 01011010 -> 0x5a + case 2: return 0x9a; // 0010 -> 0100 -> 10011010 -> 0x9a + case 1: return 0x6a; // 0001 -> 1000 -> 01101010 -> 0x6a + default: return 0xaa; // 0000 -> 0000 -> 10101010 -> 0xaa + } } //----------------------------------------------------------------------------- // Prepare tag messages //----------------------------------------------------------------------------- static void CodeIClassTagAnswer(const uint8_t *cmd, int len) { - /* - * SOF comprises 3 parts; - * * An unmodulated time of 56.64 us - * * 24 pulses of 423.75 KHz (fc/32) - * * A logic 1, which starts with an unmodulated time of 18.88us - * followed by 8 pulses of 423.75kHz (fc/32) - * - * - * EOF comprises 3 parts: - * - A logic 0 (which starts with 8 pulses of fc/32 followed by an unmodulated - * time of 18.88us. - * - 24 pulses of fc/32 - * - An unmodulated time of 56.64 us - * - * - * A logic 0 starts with 8 pulses of fc/32 - * followed by an unmodulated time of 256/fc (~18,88us). - * - * A logic 0 starts with unmodulated time of 256/fc (~18,88us) followed by - * 8 pulses of fc/32 (also 18.88us) - * - * The mode FPGA_HF_SIMULATOR_MODULATE_424K_8BIT which we use to simulate tag, - * works like this. - * - A 1-bit input to the FPGA becomes 8 pulses on 423.5kHz (fc/32) (18.88us). - * - A 0-bit input to the FPGA becomes an unmodulated time of 18.88us - * - * In this mode - * SOF can be written as 00011101 = 0x1D - * EOF can be written as 10111000 = 0xb8 - * logic 1 be written as 01 = 0x1 - * logic 0 be written as 10 = 0x2 - * - * */ - ToSendReset(); + /* + * SOF comprises 3 parts; + * * An unmodulated time of 56.64 us + * * 24 pulses of 423.75 KHz (fc/32) + * * A logic 1, which starts with an unmodulated time of 18.88us + * followed by 8 pulses of 423.75kHz (fc/32) + * + * + * EOF comprises 3 parts: + * - A logic 0 (which starts with 8 pulses of fc/32 followed by an unmodulated + * time of 18.88us. + * - 24 pulses of fc/32 + * - An unmodulated time of 56.64 us + * + * + * A logic 0 starts with 8 pulses of fc/32 + * followed by an unmodulated time of 256/fc (~18,88us). + * + * A logic 0 starts with unmodulated time of 256/fc (~18,88us) followed by + * 8 pulses of fc/32 (also 18.88us) + * + * The mode FPGA_HF_SIMULATOR_MODULATE_424K_8BIT which we use to simulate tag, + * works like this. + * - A 1-bit input to the FPGA becomes 8 pulses on 423.5kHz (fc/32) (18.88us). + * - A 0-bit input to the FPGA becomes an unmodulated time of 18.88us + * + * In this mode + * SOF can be written as 00011101 = 0x1D + * EOF can be written as 10111000 = 0xb8 + * logic 1 be written as 01 = 0x1 + * logic 0 be written as 10 = 0x2 + * + * */ + ToSendReset(); - // Send SOF - ToSend[++ToSendMax] = 0x1D; + // Send SOF + ToSend[++ToSendMax] = 0x1D; - int i; - for(i = 0; i < len; i++) { - uint8_t b = cmd[i]; - ToSend[++ToSendMax] = encode4Bits(b & 0xF); // least significant half - ToSend[++ToSendMax] = encode4Bits((b >> 4) & 0xF); // most significant half - } + int i; + for(i = 0; i < len; i++) { + uint8_t b = cmd[i]; + ToSend[++ToSendMax] = encode4Bits(b & 0xF); // least significant half + ToSend[++ToSendMax] = encode4Bits((b >> 4) & 0xF); // most significant half + } - // Send EOF - ToSend[++ToSendMax] = 0xB8; - //lastProxToAirDuration = 8*ToSendMax - 3*8 - 3*8;//Not counting zeroes in the beginning or end - // Convert from last byte pos to length - ToSendMax++; + // Send EOF + ToSend[++ToSendMax] = 0xB8; + //lastProxToAirDuration = 8*ToSendMax - 3*8 - 3*8;//Not counting zeroes in the beginning or end + // Convert from last byte pos to length + ToSendMax++; } // Only SOF static void CodeIClassTagSOF() { - //So far a dummy implementation, not used - //int lastProxToAirDuration =0; + //So far a dummy implementation, not used + //int lastProxToAirDuration =0; - ToSendReset(); - // Send SOF - ToSend[++ToSendMax] = 0x1D; - // lastProxToAirDuration = 8*ToSendMax - 3*8;//Not counting zeroes in the beginning + ToSendReset(); + // Send SOF + ToSend[++ToSendMax] = 0x1D; + // lastProxToAirDuration = 8*ToSendMax - 3*8;//Not counting zeroes in the beginning - // Convert from last byte pos to length - ToSendMax++; + // Convert from last byte pos to length + ToSendMax++; } /** * @brief SimulateIClass simulates an iClass card. * @param arg0 type of simulation - * - 0 uses the first 8 bytes in usb data as CSN - * - 2 "dismantling iclass"-attack. This mode iterates through all CSN's specified - * in the usb data. This mode collects MAC from the reader, in order to do an offline - * attack on the keys. For more info, see "dismantling iclass" and proxclone.com. - * - Other : Uses the default CSN (031fec8af7ff12e0) + * - 0 uses the first 8 bytes in usb data as CSN + * - 2 "dismantling iclass"-attack. This mode iterates through all CSN's specified + * in the usb data. This mode collects MAC from the reader, in order to do an offline + * attack on the keys. For more info, see "dismantling iclass" and proxclone.com. + * - Other : Uses the default CSN (031fec8af7ff12e0) * @param arg1 - number of CSN's contained in datain (applicable for mode 2 only) * @param arg2 * @param datain @@ -1124,107 +1124,107 @@ static void CodeIClassTagSOF() { // turn off afterwards void SimulateIClass(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { - if (MF_DBGLEVEL > 3) Dbprintf("[+] iClass_simulate Enter"); + if (MF_DBGLEVEL > 3) Dbprintf("[+] iClass_simulate Enter"); - LEDsoff(); + LEDsoff(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - // this will clear out bigbuf memory, the eload command must select this before! - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - FpgaSetupSsc(); - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + // this will clear out bigbuf memory, the eload command must select this before! + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + FpgaSetupSsc(); + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - // Enable and clear the trace - clear_trace(); - set_tracing(true); + // Enable and clear the trace + clear_trace(); + set_tracing(true); - uint32_t simType = arg0; - uint32_t numberOfCSNS = arg1; + uint32_t simType = arg0; + uint32_t numberOfCSNS = arg1; - //Use the emulator memory for SIM - uint8_t *emulator = BigBuf_get_EM_addr(); - uint8_t mac_responses[USB_CMD_DATA_SIZE] = { 0 }; + //Use the emulator memory for SIM + uint8_t *emulator = BigBuf_get_EM_addr(); + uint8_t mac_responses[USB_CMD_DATA_SIZE] = { 0 }; - if (simType == 0) { - // Use the CSN from commandline - memcpy(emulator, datain, 8); - doIClassSimulation(MODE_SIM_CSN, NULL); - } else if (simType == 1) { - //Default CSN - uint8_t csn_crc[] = { 0x03, 0x1f, 0xec, 0x8a, 0xf7, 0xff, 0x12, 0xe0, 0x00, 0x00 }; - // Use the CSN from commandline - memcpy(emulator, csn_crc, 8); - doIClassSimulation(MODE_SIM_CSN, NULL); - } else if (simType == 2) { + if (simType == 0) { + // Use the CSN from commandline + memcpy(emulator, datain, 8); + doIClassSimulation(MODE_SIM_CSN, NULL); + } else if (simType == 1) { + //Default CSN + uint8_t csn_crc[] = { 0x03, 0x1f, 0xec, 0x8a, 0xf7, 0xff, 0x12, 0xe0, 0x00, 0x00 }; + // Use the CSN from commandline + memcpy(emulator, csn_crc, 8); + doIClassSimulation(MODE_SIM_CSN, NULL); + } else if (simType == 2) { - Dbprintf("[+] going into attack mode, %d CSNS sent", numberOfCSNS); - // In this mode, a number of csns are within datain. We'll simulate each one, one at a time - // in order to collect MAC's from the reader. This can later be used in an offlne-attack - // in order to obtain the keys, as in the "dismantling iclass"-paper. - #define EPURSE_MAC_SIZE 16 - int i = 0; - for (; i < numberOfCSNS && i * EPURSE_MAC_SIZE + 8 < USB_CMD_DATA_SIZE; i++) { - // The usb data is 512 bytes, fitting 65 8-byte CSNs in there. + Dbprintf("[+] going into attack mode, %d CSNS sent", numberOfCSNS); + // In this mode, a number of csns are within datain. We'll simulate each one, one at a time + // in order to collect MAC's from the reader. This can later be used in an offlne-attack + // in order to obtain the keys, as in the "dismantling iclass"-paper. + #define EPURSE_MAC_SIZE 16 + int i = 0; + for (; i < numberOfCSNS && i * EPURSE_MAC_SIZE + 8 < USB_CMD_DATA_SIZE; i++) { + // The usb data is 512 bytes, fitting 65 8-byte CSNs in there. - memcpy(emulator, datain + (i*8), 8); + memcpy(emulator, datain + (i*8), 8); - if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses+i * EPURSE_MAC_SIZE)) { - // Button pressed - cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i * EPURSE_MAC_SIZE); - goto out; - } - } - cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i * EPURSE_MAC_SIZE); + if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses+i * EPURSE_MAC_SIZE)) { + // Button pressed + cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i * EPURSE_MAC_SIZE); + goto out; + } + } + cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i, 0, mac_responses, i * EPURSE_MAC_SIZE); - } else if (simType == 3){ - //This is 'full sim' mode, where we use the emulator storage for data. - //ie: BigBuf_get_EM_addr should be previously filled with data from the "eload" command - doIClassSimulation(MODE_FULLSIM, NULL); - } else if (simType == 4){ + } else if (simType == 3){ + //This is 'full sim' mode, where we use the emulator storage for data. + //ie: BigBuf_get_EM_addr should be previously filled with data from the "eload" command + doIClassSimulation(MODE_FULLSIM, NULL); + } else if (simType == 4){ - // This is the KEYROLL version of sim 2. - // the collected data (mac_response) is doubled out since we are trying to collect both keys in the keyroll process. - // Keyroll iceman 9 csns * 8 * 2 = 144 - // keyroll CARL55 15csns * 8 * 2 = 15 * 8 * 2 = 240 - Dbprintf("[+] going into attack keyroll mode, %d CSNS sent", numberOfCSNS); - // In this mode, a number of csns are within datain. We'll simulate each one, one at a time - // in order to collect MAC's from the reader. This can later be used in an offlne-attack - // in order to obtain the keys, as in the "dismantling iclass"-paper. + // This is the KEYROLL version of sim 2. + // the collected data (mac_response) is doubled out since we are trying to collect both keys in the keyroll process. + // Keyroll iceman 9 csns * 8 * 2 = 144 + // keyroll CARL55 15csns * 8 * 2 = 15 * 8 * 2 = 240 + Dbprintf("[+] going into attack keyroll mode, %d CSNS sent", numberOfCSNS); + // In this mode, a number of csns are within datain. We'll simulate each one, one at a time + // in order to collect MAC's from the reader. This can later be used in an offlne-attack + // in order to obtain the keys, as in the "dismantling iclass"-paper. - // keyroll mode, reader swaps between old key and new key alternatively when fail a authentication. - // attack below is same as SIM 2, but we run the CSN twice to collected the mac for both keys. - int i = 0; - // The usb data is 512 bytes, fitting 65 8-byte CSNs in there. iceman fork uses 9 CSNS - for (; i < numberOfCSNS && i * EPURSE_MAC_SIZE + 8 < USB_CMD_DATA_SIZE; i++) { + // keyroll mode, reader swaps between old key and new key alternatively when fail a authentication. + // attack below is same as SIM 2, but we run the CSN twice to collected the mac for both keys. + int i = 0; + // The usb data is 512 bytes, fitting 65 8-byte CSNs in there. iceman fork uses 9 CSNS + for (; i < numberOfCSNS && i * EPURSE_MAC_SIZE + 8 < USB_CMD_DATA_SIZE; i++) { - memcpy(emulator, datain + (i*8), 8); + memcpy(emulator, datain + (i*8), 8); - // keyroll 1 - if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE )) { - cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2); - // Button pressed - goto out; - } + // keyroll 1 + if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + i * EPURSE_MAC_SIZE )) { + cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2); + // Button pressed + goto out; + } - // keyroll 2 - if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + (i + numberOfCSNS) * EPURSE_MAC_SIZE )) { - cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * EPURSE_MAC_SIZE* 2); - // Button pressed - goto out; - } - } - // double the amount of collected data. - cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2 ); + // keyroll 2 + if (doIClassSimulation(MODE_EXIT_AFTER_MAC, mac_responses + (i + numberOfCSNS) * EPURSE_MAC_SIZE )) { + cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * EPURSE_MAC_SIZE* 2); + // Button pressed + goto out; + } + } + // double the amount of collected data. + cmd_send(CMD_ACK, CMD_SIMULATE_TAG_ICLASS, i*2, 0, mac_responses, i * EPURSE_MAC_SIZE * 2 ); - } else { - // We may want a mode here where we hardcode the csns to use (from proxclone). - // That will speed things up a little, but not required just yet. - DbpString("[-] the mode is not implemented, reserved for future use"); - } + } else { + // We may want a mode here where we hardcode the csns to use (from proxclone). + // That will speed things up a little, but not required just yet. + DbpString("[-] the mode is not implemented, reserved for future use"); + } out: - switch_off(); - BigBuf_free_keep_EM(); + switch_off(); + BigBuf_free_keep_EM(); } /** @@ -1234,344 +1234,344 @@ out: */ int doIClassSimulation( int simulationMode, uint8_t *reader_mac_buf) { - // free eventually allocated BigBuf memory - BigBuf_free_keep_EM(); + // free eventually allocated BigBuf memory + BigBuf_free_keep_EM(); - State cipher_state; + State cipher_state; - uint8_t *csn = BigBuf_get_EM_addr(); - uint8_t *emulator = csn; - uint8_t sof_data[] = { 0x0F} ; + uint8_t *csn = BigBuf_get_EM_addr(); + uint8_t *emulator = csn; + uint8_t sof_data[] = { 0x0F} ; - // CSN followed by two CRC bytes - uint8_t anticoll_data[10] = { 0 }; - uint8_t csn_data[10] = { 0 }; - memcpy(csn_data, csn, sizeof(csn_data)); + // CSN followed by two CRC bytes + uint8_t anticoll_data[10] = { 0 }; + uint8_t csn_data[10] = { 0 }; + memcpy(csn_data, csn, sizeof(csn_data)); - // Construct anticollision-CSN - rotateCSN(csn_data, anticoll_data); + // Construct anticollision-CSN + rotateCSN(csn_data, anticoll_data); - // Compute CRC on both CSNs - AddCrc(anticoll_data, 8); - AddCrc(csn_data, 8); + // Compute CRC on both CSNs + AddCrc(anticoll_data, 8); + AddCrc(csn_data, 8); - uint8_t diversified_key[8] = { 0 }; - // e-Purse - uint8_t card_challenge_data[8] = { 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; - //uint8_t card_challenge_data[8] = { 0 }; - if (simulationMode == MODE_FULLSIM) { - //The diversified key should be stored on block 3 - //Get the diversified key from emulator memory - memcpy(diversified_key, emulator+(8*3),8); + uint8_t diversified_key[8] = { 0 }; + // e-Purse + uint8_t card_challenge_data[8] = { 0xfe,0xff,0xff,0xff,0xff,0xff,0xff,0xff }; + //uint8_t card_challenge_data[8] = { 0 }; + if (simulationMode == MODE_FULLSIM) { + //The diversified key should be stored on block 3 + //Get the diversified key from emulator memory + memcpy(diversified_key, emulator+(8*3),8); - //Card challenge, a.k.a e-purse is on block 2 - memcpy(card_challenge_data, emulator + (8 * 2) ,8); - //Precalculate the cipher state, feeding it the CC - cipher_state = opt_doTagMAC_1(card_challenge_data, diversified_key); - } - // set epurse of sim2,4 attack - if (reader_mac_buf != NULL) { - memcpy(reader_mac_buf, card_challenge_data, 8); - } + //Card challenge, a.k.a e-purse is on block 2 + memcpy(card_challenge_data, emulator + (8 * 2) ,8); + //Precalculate the cipher state, feeding it the CC + cipher_state = opt_doTagMAC_1(card_challenge_data, diversified_key); + } + // set epurse of sim2,4 attack + if (reader_mac_buf != NULL) { + memcpy(reader_mac_buf, card_challenge_data, 8); + } - int exitLoop = 0; - // Reader 0a - // Tag 0f - // Reader 0c - // Tag anticoll. CSN - // Reader 81 anticoll. CSN - // Tag CSN + int exitLoop = 0; + // Reader 0a + // Tag 0f + // Reader 0c + // Tag anticoll. CSN + // Reader 81 anticoll. CSN + // Tag CSN - uint8_t *modulated_response; - int modulated_response_size = 0; - uint8_t* trace_data = NULL; - int trace_data_size = 0; + uint8_t *modulated_response; + int modulated_response_size = 0; + uint8_t* trace_data = NULL; + int trace_data_size = 0; - // Respond SOF -- takes 1 bytes - uint8_t *resp_sof = BigBuf_malloc(2); - int resp_sof_Len; + // Respond SOF -- takes 1 bytes + uint8_t *resp_sof = BigBuf_malloc(2); + int resp_sof_Len; - // Anticollision CSN (rotated CSN) - // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte) - uint8_t *resp_anticoll = BigBuf_malloc(28); - int resp_anticoll_len; + // Anticollision CSN (rotated CSN) + // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte) + uint8_t *resp_anticoll = BigBuf_malloc(28); + int resp_anticoll_len; - // CSN - // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte) - uint8_t *resp_csn = BigBuf_malloc(28); - int resp_csn_len; + // CSN + // 22: Takes 2 bytes for SOF/EOF and 10 * 2 = 20 bytes (2 bytes/byte) + uint8_t *resp_csn = BigBuf_malloc(28); + int resp_csn_len; - // configuration picopass 2ks - uint8_t *resp_conf = BigBuf_malloc(28); - int resp_conf_len; - uint8_t conf_data[10] = {0x12,0xFF,0xFF,0xFF,0x7F,0x1F,0xFF,0x3C,0x00,0x00}; - AddCrc(conf_data, 8); + // configuration picopass 2ks + uint8_t *resp_conf = BigBuf_malloc(28); + int resp_conf_len; + uint8_t conf_data[10] = {0x12,0xFF,0xFF,0xFF,0x7F,0x1F,0xFF,0x3C,0x00,0x00}; + AddCrc(conf_data, 8); - // e-Purse - // 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/bit) - uint8_t *resp_cc = BigBuf_malloc(28); - int resp_cc_len; + // e-Purse + // 18: Takes 2 bytes for SOF/EOF and 8 * 2 = 16 bytes (2 bytes/bit) + uint8_t *resp_cc = BigBuf_malloc(28); + int resp_cc_len; - // Application Issuer Area - uint8_t *resp_aia = BigBuf_malloc(28); - int resp_aia_len; - uint8_t aia_data[10] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00}; - AddCrc(aia_data, 8); + // Application Issuer Area + uint8_t *resp_aia = BigBuf_malloc(28); + int resp_aia_len; + uint8_t aia_data[10] = {0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0x00,0x00}; + AddCrc(aia_data, 8); - // receive command - uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); - int len = 0; + // receive command + uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); + int len = 0; - // Prepare card messages - ToSendMax = 0; + // Prepare card messages + ToSendMax = 0; - // First card answer: SOF - CodeIClassTagSOF(); - memcpy(resp_sof, ToSend, ToSendMax); resp_sof_Len = ToSendMax; + // First card answer: SOF + CodeIClassTagSOF(); + memcpy(resp_sof, ToSend, ToSendMax); resp_sof_Len = ToSendMax; - // Anticollision CSN - CodeIClassTagAnswer(anticoll_data, sizeof(anticoll_data)); - memcpy(resp_anticoll, ToSend, ToSendMax); resp_anticoll_len = ToSendMax; + // Anticollision CSN + CodeIClassTagAnswer(anticoll_data, sizeof(anticoll_data)); + memcpy(resp_anticoll, ToSend, ToSendMax); resp_anticoll_len = ToSendMax; - // CSN - CodeIClassTagAnswer(csn_data, sizeof(csn_data)); - memcpy(resp_csn, ToSend, ToSendMax); resp_csn_len = ToSendMax; + // CSN + CodeIClassTagAnswer(csn_data, sizeof(csn_data)); + memcpy(resp_csn, ToSend, ToSendMax); resp_csn_len = ToSendMax; - // Configuration - CodeIClassTagAnswer(conf_data, sizeof(conf_data)); - memcpy(resp_conf, ToSend, ToSendMax); resp_conf_len = ToSendMax; + // Configuration + CodeIClassTagAnswer(conf_data, sizeof(conf_data)); + memcpy(resp_conf, ToSend, ToSendMax); resp_conf_len = ToSendMax; - // e-Purse - CodeIClassTagAnswer(card_challenge_data, sizeof(card_challenge_data)); - memcpy(resp_cc, ToSend, ToSendMax); resp_cc_len = ToSendMax; + // e-Purse + CodeIClassTagAnswer(card_challenge_data, sizeof(card_challenge_data)); + memcpy(resp_cc, ToSend, ToSendMax); resp_cc_len = ToSendMax; - // Application Issuer Area - CodeIClassTagAnswer(aia_data, sizeof(aia_data)); - memcpy(resp_aia, ToSend, ToSendMax); resp_aia_len = ToSendMax; + // Application Issuer Area + CodeIClassTagAnswer(aia_data, sizeof(aia_data)); + memcpy(resp_aia, ToSend, ToSendMax); resp_aia_len = ToSendMax; - //This is used for responding to READ-block commands or other data which is dynamically generated - //First the 'trace'-data, not encoded for FPGA - uint8_t *data_generic_trace = BigBuf_malloc(8 + 2);//8 bytes data + 2byte CRC is max tag answer + //This is used for responding to READ-block commands or other data which is dynamically generated + //First the 'trace'-data, not encoded for FPGA + uint8_t *data_generic_trace = BigBuf_malloc(8 + 2);//8 bytes data + 2byte CRC is max tag answer - //Then storage for the modulated data - //Each bit is doubled when modulated for FPGA, and we also have SOF and EOF (2 bytes) - uint8_t *data_response = BigBuf_malloc( (8+2) * 2 + 2); + //Then storage for the modulated data + //Each bit is doubled when modulated for FPGA, and we also have SOF and EOF (2 bytes) + uint8_t *data_response = BigBuf_malloc( (8+2) * 2 + 2); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); - SpinDelay(100); - StartCountSspClk(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); + SpinDelay(100); + StartCountSspClk(); - // To control where we are in the protocol - uint32_t time_0 = GetCountSspClk(); - uint32_t t2r_stime = 0, t2r_etime = 0; - uint32_t r2t_stime = 0, r2t_etime = 0; + // To control where we are in the protocol + uint32_t time_0 = GetCountSspClk(); + uint32_t t2r_stime = 0, t2r_etime = 0; + uint32_t r2t_stime = 0, r2t_etime = 0; - LED_A_ON(); - bool buttonPressed = false; + LED_A_ON(); + bool buttonPressed = false; - while (!exitLoop) { - WDT_HIT(); + while (!exitLoop) { + WDT_HIT(); - //Signal tracer, can be used to get a trigger for an oscilloscope.. - LED_B_OFF(); LED_C_OFF(); + //Signal tracer, can be used to get a trigger for an oscilloscope.. + LED_B_OFF(); LED_C_OFF(); - r2t_stime = (GetCountSspClk() - time_0) << 4; - if (!GetIClassCommandFromReader(receivedCmd, &len, 0)) { - buttonPressed = true; - exitLoop = true; - continue; - } - r2t_etime = ((GetCountSspClk() - time_0) << 4 ) - r2t_stime; + r2t_stime = (GetCountSspClk() - time_0) << 4; + if (!GetIClassCommandFromReader(receivedCmd, &len, 0)) { + buttonPressed = true; + exitLoop = true; + continue; + } + r2t_etime = ((GetCountSspClk() - time_0) << 4 ) - r2t_stime; - // 330us normal wait, adjusted for our execution + // 330us normal wait, adjusted for our execution - LED_C_ON(); //Signal tracer + LED_C_ON(); //Signal tracer - if (receivedCmd[0] == ICLASS_CMD_ACTALL ) { // 0x0A - // Reader in anticollission phase - modulated_response = resp_sof; modulated_response_size = resp_sof_Len; //order = 1; - trace_data = sof_data; - trace_data_size = sizeof(sof_data); - // adjusted for 330 + (160*num of slot) - goto send; - } else if (receivedCmd[0] == ICLASS_CMD_READ_OR_IDENTIFY) { // 0x0C - if (len == 1) { - // Reader asks for anticollission CSN - modulated_response = resp_anticoll; modulated_response_size = resp_anticoll_len; //order = 2; - trace_data = anticoll_data; - trace_data_size = sizeof(anticoll_data); - goto send; - } - if (len == 4){ - // block0,1,2,5 is always readable. - switch (receivedCmd[1]){ - case 0: // csn (0c 00) - modulated_response = resp_csn; modulated_response_size = resp_csn_len; - trace_data = csn_data; - trace_data_size = sizeof(csn_data); - break; - case 1: // configuration (0c 01) - modulated_response = resp_conf; modulated_response_size = resp_conf_len; - trace_data = conf_data; - trace_data_size = sizeof(conf_data); - break; - case 2: // e-purse (0c 02) - modulated_response = resp_cc; modulated_response_size = resp_cc_len; - trace_data = card_challenge_data; - trace_data_size = sizeof(card_challenge_data); - // set epurse of sim2,4 attack - if (reader_mac_buf != NULL) { - memcpy(reader_mac_buf, card_challenge_data, 8); - } - break; - case 5:// Application Issuer Area (0c 05) - modulated_response = resp_aia; modulated_response_size = resp_aia_len; - trace_data = aia_data; - trace_data_size = sizeof(aia_data); - break; - default: break; - } - goto send; - } + if (receivedCmd[0] == ICLASS_CMD_ACTALL ) { // 0x0A + // Reader in anticollission phase + modulated_response = resp_sof; modulated_response_size = resp_sof_Len; //order = 1; + trace_data = sof_data; + trace_data_size = sizeof(sof_data); + // adjusted for 330 + (160*num of slot) + goto send; + } else if (receivedCmd[0] == ICLASS_CMD_READ_OR_IDENTIFY) { // 0x0C + if (len == 1) { + // Reader asks for anticollission CSN + modulated_response = resp_anticoll; modulated_response_size = resp_anticoll_len; //order = 2; + trace_data = anticoll_data; + trace_data_size = sizeof(anticoll_data); + goto send; + } + if (len == 4){ + // block0,1,2,5 is always readable. + switch (receivedCmd[1]){ + case 0: // csn (0c 00) + modulated_response = resp_csn; modulated_response_size = resp_csn_len; + trace_data = csn_data; + trace_data_size = sizeof(csn_data); + break; + case 1: // configuration (0c 01) + modulated_response = resp_conf; modulated_response_size = resp_conf_len; + trace_data = conf_data; + trace_data_size = sizeof(conf_data); + break; + case 2: // e-purse (0c 02) + modulated_response = resp_cc; modulated_response_size = resp_cc_len; + trace_data = card_challenge_data; + trace_data_size = sizeof(card_challenge_data); + // set epurse of sim2,4 attack + if (reader_mac_buf != NULL) { + memcpy(reader_mac_buf, card_challenge_data, 8); + } + break; + case 5:// Application Issuer Area (0c 05) + modulated_response = resp_aia; modulated_response_size = resp_aia_len; + trace_data = aia_data; + trace_data_size = sizeof(aia_data); + break; + default: break; + } + goto send; + } - } else if (receivedCmd[0] == ICLASS_CMD_SELECT) { // 0x81 - // Reader selects anticollission CSN. - // Tag sends the corresponding real CSN - modulated_response = resp_csn; modulated_response_size = resp_csn_len; //order = 3; - trace_data = csn_data; - trace_data_size = sizeof(csn_data); - goto send; - } else if (receivedCmd[0] == ICLASS_CMD_READCHECK_KD) { // 0x88 - // Read e-purse (88 02) - modulated_response = resp_cc; modulated_response_size = resp_cc_len; //order = 4; - trace_data = card_challenge_data; - trace_data_size = sizeof(card_challenge_data); - LED_B_ON(); - goto send; - } else if (receivedCmd[0] == ICLASS_CMD_READCHECK_KC) { // 0x18 - // Read e-purse (18 02) - modulated_response = resp_cc; modulated_response_size = resp_cc_len; //order = 4; - trace_data = card_challenge_data; - trace_data_size = sizeof(card_challenge_data); - LED_B_ON(); - goto send; - } else if (receivedCmd[0] == ICLASS_CMD_CHECK) { // 0x05 - // Reader random and reader MAC!!! - if (simulationMode == MODE_FULLSIM) { - // NR, from reader, is in receivedCmd +1 - opt_doTagMAC_2(cipher_state, receivedCmd+1, data_generic_trace, diversified_key); + } else if (receivedCmd[0] == ICLASS_CMD_SELECT) { // 0x81 + // Reader selects anticollission CSN. + // Tag sends the corresponding real CSN + modulated_response = resp_csn; modulated_response_size = resp_csn_len; //order = 3; + trace_data = csn_data; + trace_data_size = sizeof(csn_data); + goto send; + } else if (receivedCmd[0] == ICLASS_CMD_READCHECK_KD) { // 0x88 + // Read e-purse (88 02) + modulated_response = resp_cc; modulated_response_size = resp_cc_len; //order = 4; + trace_data = card_challenge_data; + trace_data_size = sizeof(card_challenge_data); + LED_B_ON(); + goto send; + } else if (receivedCmd[0] == ICLASS_CMD_READCHECK_KC) { // 0x18 + // Read e-purse (18 02) + modulated_response = resp_cc; modulated_response_size = resp_cc_len; //order = 4; + trace_data = card_challenge_data; + trace_data_size = sizeof(card_challenge_data); + LED_B_ON(); + goto send; + } else if (receivedCmd[0] == ICLASS_CMD_CHECK) { // 0x05 + // Reader random and reader MAC!!! + if (simulationMode == MODE_FULLSIM) { + // NR, from reader, is in receivedCmd +1 + opt_doTagMAC_2(cipher_state, receivedCmd+1, data_generic_trace, diversified_key); - trace_data = data_generic_trace; - trace_data_size = 4; - CodeIClassTagAnswer(trace_data , trace_data_size); - memcpy(data_response, ToSend, ToSendMax); - modulated_response = data_response; - modulated_response_size = ToSendMax; - } else { - // Not fullsim, we don't respond - // We do not know what to answer, so lets keep quiet - modulated_response = resp_sof; modulated_response_size = 0; - trace_data = NULL; - trace_data_size = 0; + trace_data = data_generic_trace; + trace_data_size = 4; + CodeIClassTagAnswer(trace_data , trace_data_size); + memcpy(data_response, ToSend, ToSendMax); + modulated_response = data_response; + modulated_response_size = ToSendMax; + } else { + // Not fullsim, we don't respond + // We do not know what to answer, so lets keep quiet + modulated_response = resp_sof; modulated_response_size = 0; + trace_data = NULL; + trace_data_size = 0; - if (simulationMode == MODE_EXIT_AFTER_MAC) { + if (simulationMode == MODE_EXIT_AFTER_MAC) { - if ( MF_DBGLEVEL == MF_DBG_EXTENDED) { - Dbprintf("[+] CSN: %02x %02x %02x %02x %02x %02x %02x %02x", csn[0], csn[1], csn[2], csn[3], csn[4], csn[5], csn[6], csn[7]); - Dbprintf("[+] RDR: (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x", len, - receivedCmd[0], receivedCmd[1], receivedCmd[2], - receivedCmd[3], receivedCmd[4], receivedCmd[5], - receivedCmd[6], receivedCmd[7], receivedCmd[8]); - } else { - Dbprintf("[+] CSN: %02x .... %02x OK", csn[0], csn[7]); - } - if (reader_mac_buf != NULL) { - memcpy(reader_mac_buf + 8, receivedCmd+1, 8); - } - exitLoop = true; - } - } - goto send; - } else if (receivedCmd[0] == ICLASS_CMD_HALT && len == 1) { - // Reader ends the session - modulated_response = resp_sof; modulated_response_size = 0; //order = 0; - trace_data = NULL; - trace_data_size = 0; - goto send; - } else if (simulationMode == MODE_FULLSIM && receivedCmd[0] == ICLASS_CMD_READ_OR_IDENTIFY && len == 4){ // 0x0C - //Read block - uint16_t blk = receivedCmd[1]; - //Take the data... - memcpy(data_generic_trace, emulator+(blk << 3),8); - AddCrc(data_generic_trace, 8); - trace_data = data_generic_trace; - trace_data_size = 10; - CodeIClassTagAnswer(trace_data , trace_data_size); - memcpy(data_response, ToSend, ToSendMax); - modulated_response = data_response; - modulated_response_size = ToSendMax; - goto send; - } else if (simulationMode == MODE_FULLSIM && receivedCmd[0] == ICLASS_CMD_UPDATE) { + if ( MF_DBGLEVEL == MF_DBG_EXTENDED) { + Dbprintf("[+] CSN: %02x %02x %02x %02x %02x %02x %02x %02x", csn[0], csn[1], csn[2], csn[3], csn[4], csn[5], csn[6], csn[7]); + Dbprintf("[+] RDR: (len=%02d): %02x %02x %02x %02x %02x %02x %02x %02x %02x", len, + receivedCmd[0], receivedCmd[1], receivedCmd[2], + receivedCmd[3], receivedCmd[4], receivedCmd[5], + receivedCmd[6], receivedCmd[7], receivedCmd[8]); + } else { + Dbprintf("[+] CSN: %02x .... %02x OK", csn[0], csn[7]); + } + if (reader_mac_buf != NULL) { + memcpy(reader_mac_buf + 8, receivedCmd+1, 8); + } + exitLoop = true; + } + } + goto send; + } else if (receivedCmd[0] == ICLASS_CMD_HALT && len == 1) { + // Reader ends the session + modulated_response = resp_sof; modulated_response_size = 0; //order = 0; + trace_data = NULL; + trace_data_size = 0; + goto send; + } else if (simulationMode == MODE_FULLSIM && receivedCmd[0] == ICLASS_CMD_READ_OR_IDENTIFY && len == 4){ // 0x0C + //Read block + uint16_t blk = receivedCmd[1]; + //Take the data... + memcpy(data_generic_trace, emulator+(blk << 3),8); + AddCrc(data_generic_trace, 8); + trace_data = data_generic_trace; + trace_data_size = 10; + CodeIClassTagAnswer(trace_data , trace_data_size); + memcpy(data_response, ToSend, ToSendMax); + modulated_response = data_response; + modulated_response_size = ToSendMax; + goto send; + } else if (simulationMode == MODE_FULLSIM && receivedCmd[0] == ICLASS_CMD_UPDATE) { - //Probably the reader wants to update the nonce. Let's just ignore that for now. - // OBS! If this is implemented, don't forget to regenerate the cipher_state - //We're expected to respond with the data+crc, exactly what's already in the receivedcmd - //receivedcmd is now UPDATE 1b | ADDRESS 1b| DATA 8b| Signature 4b or CRC 2b| + //Probably the reader wants to update the nonce. Let's just ignore that for now. + // OBS! If this is implemented, don't forget to regenerate the cipher_state + //We're expected to respond with the data+crc, exactly what's already in the receivedcmd + //receivedcmd is now UPDATE 1b | ADDRESS 1b| DATA 8b| Signature 4b or CRC 2b| - //Take the data... - memcpy(data_generic_trace, receivedCmd+2, 8); - AddCrc(data_generic_trace, 8); - trace_data = data_generic_trace; - trace_data_size = 10; - CodeIClassTagAnswer(trace_data, trace_data_size); + //Take the data... + memcpy(data_generic_trace, receivedCmd+2, 8); + AddCrc(data_generic_trace, 8); + trace_data = data_generic_trace; + trace_data_size = 10; + CodeIClassTagAnswer(trace_data, trace_data_size); - memcpy(data_response, ToSend, ToSendMax); - modulated_response = data_response; - modulated_response_size = ToSendMax; -// response_delay = 4600 * 1.5; // tPROG 4-15ms - goto send; -// } else if(receivedCmd[0] == ICLASS_CMD_PAGESEL) { // 0x84 - //Pagesel - //Pagesel enables to select a page in the selected chip memory and return its configuration block - //Chips with a single page will not answer to this command - // It appears we're fine ignoring this. - //Otherwise, we should answer 8bytes (block) + 2bytes CRC -// } else if(receivedCmd[0] == ICLASS_CMD_DETECT) { // 0x0F - } else { - //#db# Unknown command received from reader (len=5): 26 1 0 f6 a 44 44 44 44 - // Never seen this command before - if ( MF_DBGLEVEL == MF_DBG_EXTENDED) - print_result("[-] Unhandled command received ", receivedCmd, len); + memcpy(data_response, ToSend, ToSendMax); + modulated_response = data_response; + modulated_response_size = ToSendMax; +// response_delay = 4600 * 1.5; // tPROG 4-15ms + goto send; +// } else if(receivedCmd[0] == ICLASS_CMD_PAGESEL) { // 0x84 + //Pagesel + //Pagesel enables to select a page in the selected chip memory and return its configuration block + //Chips with a single page will not answer to this command + // It appears we're fine ignoring this. + //Otherwise, we should answer 8bytes (block) + 2bytes CRC +// } else if(receivedCmd[0] == ICLASS_CMD_DETECT) { // 0x0F + } else { + //#db# Unknown command received from reader (len=5): 26 1 0 f6 a 44 44 44 44 + // Never seen this command before + if ( MF_DBGLEVEL == MF_DBG_EXTENDED) + print_result("[-] Unhandled command received ", receivedCmd, len); - // Do not respond - modulated_response = resp_sof; - modulated_response_size = 0; //order = 0; - trace_data = NULL; - trace_data_size = 0; - } + // Do not respond + modulated_response = resp_sof; + modulated_response_size = 0; //order = 0; + trace_data = NULL; + trace_data_size = 0; + } send: - /** - A legit tag has about 330us delay between reader EOT and tag SOF. - **/ - if (modulated_response_size > 0) { - t2r_stime = (GetCountSspClk() - time_0) << 4; - SendIClassAnswer(modulated_response, modulated_response_size, 0); - t2r_etime = ((GetCountSspClk() - time_0) << 4 ) - t2r_stime; - } + /** + A legit tag has about 330us delay between reader EOT and tag SOF. + **/ + if (modulated_response_size > 0) { + t2r_stime = (GetCountSspClk() - time_0) << 4; + SendIClassAnswer(modulated_response, modulated_response_size, 0); + t2r_etime = ((GetCountSspClk() - time_0) << 4 ) - t2r_stime; + } - LogTrace(receivedCmd, len, r2t_stime, r2t_etime, NULL, true); + LogTrace(receivedCmd, len, r2t_stime, r2t_etime, NULL, true); - if (trace_data != NULL) - LogTrace(trace_data, trace_data_size, t2r_stime, t2r_etime, NULL, false); - } + if (trace_data != NULL) + LogTrace(trace_data, trace_data_size, t2r_stime, t2r_etime, NULL, false); + } - LEDsoff(); + LEDsoff(); - if (buttonPressed) - DbpString("[+] button pressed"); + if (buttonPressed) + DbpString("[+] button pressed"); - return buttonPressed; + return buttonPressed; } /** @@ -1581,35 +1581,35 @@ send: * @param delay */ static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay) { - int i = 0; - volatile uint8_t b = 0; + int i = 0; + volatile uint8_t b = 0; - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K_8BIT); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K_8BIT); - AT91C_BASE_SSC->SSC_THR = 0x00; + AT91C_BASE_SSC->SSC_THR = 0x00; - while (!BUTTON_PRESS()) { + while (!BUTTON_PRESS()) { - // Prevent rx holding register from overflowing - if ( (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)){ - b = AT91C_BASE_SSC->SSC_RHR; (void) b; - } + // Prevent rx holding register from overflowing + if ( (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)){ + b = AT91C_BASE_SSC->SSC_RHR; (void) b; + } - // Put byte into tx holding register as soon as it is ready - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)){ - b = 0x00; - if ( i < respLen){ - b = resp[i]; - //Hack - //b = 0xAC; - } - i++; - AT91C_BASE_SSC->SSC_THR = b; - } -// if (i > respLen + 4) break; - if (i > respLen + 1) break; - } - return 0; + // Put byte into tx holding register as soon as it is ready + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)){ + b = 0x00; + if ( i < respLen){ + b = resp[i]; + //Hack + //b = 0xAC; + } + i++; + AT91C_BASE_SSC->SSC_THR = b; + } +// if (i > respLen + 4) break; + if (i > respLen + 1) break; + } + return 0; } /// THE READER CODE @@ -1619,114 +1619,114 @@ static int SendIClassAnswer(uint8_t *resp, int respLen, uint16_t delay) { //----------------------------------------------------------------------------- static void TransmitIClassCommand(const uint8_t *cmd, int len, int *samples, int *wait) { - int c = 0; - volatile uint32_t b; - bool firstpart = true; - uint8_t sendbyte; + int c = 0; + volatile uint32_t b; + bool firstpart = true; + uint8_t sendbyte; - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); - AT91C_BASE_SSC->SSC_THR = 0x00; + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); + AT91C_BASE_SSC->SSC_THR = 0x00; - // make sure we timeout previous comms. - if ( *wait ) - SpinDelayUs(*wait); + // make sure we timeout previous comms. + if ( *wait ) + SpinDelayUs(*wait); - for (;;) { + for (;;) { - WDT_HIT(); + WDT_HIT(); - // Put byte into tx holding register as soon as it is ready - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + // Put byte into tx holding register as soon as it is ready + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - // DOUBLE THE SAMPLES! - if (firstpart) { - sendbyte = (cmd[c] & 0xf0) | (cmd[c] >> 4); - } else { - sendbyte = (cmd[c] & 0x0f) | (cmd[c] << 4); - c++; - } + // DOUBLE THE SAMPLES! + if (firstpart) { + sendbyte = (cmd[c] & 0xf0) | (cmd[c] >> 4); + } else { + sendbyte = (cmd[c] & 0x0f) | (cmd[c] << 4); + c++; + } - if (sendbyte == 0xff) - sendbyte = 0xfe; + if (sendbyte == 0xff) + sendbyte = 0xfe; - AT91C_BASE_SSC->SSC_THR = sendbyte; - firstpart = !firstpart; + AT91C_BASE_SSC->SSC_THR = sendbyte; + firstpart = !firstpart; - if (c >= len) break; - } + if (c >= len) break; + } - // Prevent rx holding register from overflowing - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - b = AT91C_BASE_SSC->SSC_RHR; (void)b; - } - } + // Prevent rx holding register from overflowing + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + b = AT91C_BASE_SSC->SSC_RHR; (void)b; + } + } - if (samples) { - if (wait) - *samples = (c + *wait) << 3; - else - *samples = c << 3; - } + if (samples) { + if (wait) + *samples = (c + *wait) << 3; + else + *samples = c << 3; + } } //----------------------------------------------------------------------------- // Prepare iClass reader command to send to FPGA //----------------------------------------------------------------------------- void CodeIClassCommand(const uint8_t* cmd, int len) { - int i, j, k; - uint8_t b; + int i, j, k; + uint8_t b; - ToSendReset(); + ToSendReset(); - // (SOC) Start of Communication: 1 out of 4 - ToSend[++ToSendMax] = 0xf0; - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0x0f; - ToSend[++ToSendMax] = 0x00; + // (SOC) Start of Communication: 1 out of 4 + ToSend[++ToSendMax] = 0xf0; + ToSend[++ToSendMax] = 0x00; + ToSend[++ToSendMax] = 0x0f; + ToSend[++ToSendMax] = 0x00; - // Modulate the bytes - for (i = 0; i < len; i++) { - b = cmd[i]; - for (j = 0; j < 4; j++) { - for (k = 0; k < 4; k++) { + // Modulate the bytes + for (i = 0; i < len; i++) { + b = cmd[i]; + for (j = 0; j < 4; j++) { + for (k = 0; k < 4; k++) { - if (k == (b & 3)) - ToSend[++ToSendMax] = 0xf0; - else - ToSend[++ToSendMax] = 0x00; - } - b >>= 2; - } - } + if (k == (b & 3)) + ToSend[++ToSendMax] = 0xf0; + else + ToSend[++ToSendMax] = 0x00; + } + b >>= 2; + } + } - // (EOC) End of Communication - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0x00; - ToSend[++ToSendMax] = 0xf0; - ToSend[++ToSendMax] = 0x00; + // (EOC) End of Communication + ToSend[++ToSendMax] = 0x00; + ToSend[++ToSendMax] = 0x00; + ToSend[++ToSendMax] = 0xf0; + ToSend[++ToSendMax] = 0x00; - // Convert from last character reference to length - ToSendMax++; + // Convert from last character reference to length + ToSendMax++; } void ReaderTransmitIClass_ext(uint8_t* frame, int len, int wait) { - int samples = 0; + int samples = 0; - // This is tied to other size changes - CodeIClassCommand(frame, len); + // This is tied to other size changes + CodeIClassCommand(frame, len); - // Select the card - TransmitIClassCommand(ToSend, ToSendMax, &samples, &wait); - if (trigger) - LED_A_ON(); + // Select the card + TransmitIClassCommand(ToSend, ToSendMax, &samples, &wait); + if (trigger) + LED_A_ON(); - rsamples += samples; + rsamples += samples; - LogTrace(frame, len, rsamples, rsamples, NULL, true); + LogTrace(frame, len, rsamples, rsamples, NULL, true); } void ReaderTransmitIClass(uint8_t* frame, int len) { - ReaderTransmitIClass_ext(frame, len, 330); + ReaderTransmitIClass_ext(frame, len, 330); } //----------------------------------------------------------------------------- @@ -1735,75 +1735,75 @@ void ReaderTransmitIClass(uint8_t* frame, int len) { // If it takes too long return FALSE //----------------------------------------------------------------------------- static int GetIClassAnswer(uint8_t* receivedResponse, int maxLen, int *samples, int *elapsed) { - // buffer needs to be 512 bytes - // maxLen is not used... + // buffer needs to be 512 bytes + // maxLen is not used... - int c = 0; - bool skip = false; + int c = 0; + bool skip = false; - // Setup UART/DEMOD to receive - DemodInit(receivedResponse); + // Setup UART/DEMOD to receive + DemodInit(receivedResponse); - if (elapsed) *elapsed = 0; + if (elapsed) *elapsed = 0; - // Set FPGA mode to "reader listen mode", no modulation (listen - // only, since we are receiving, not transmitting). - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN); - SpinDelayUs(320); //310 Tout= 330us (iso15603-2) (330/21.3) take consideration for clock increments. + // Set FPGA mode to "reader listen mode", no modulation (listen + // only, since we are receiving, not transmitting). + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN); + SpinDelayUs(320); //310 Tout= 330us (iso15603-2) (330/21.3) take consideration for clock increments. - // clear RXRDY: + // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - while (!BUTTON_PRESS()) { - WDT_HIT(); + while (!BUTTON_PRESS()) { + WDT_HIT(); - // keep tx buffer in a defined state anyway. - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x00; - // To make use of exact timing of next command from reader!! - if (elapsed) (*elapsed)++; - } + // keep tx buffer in a defined state anyway. + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0x00; + // To make use of exact timing of next command from reader!! + if (elapsed) (*elapsed)++; + } - // Wait for byte be become available in rx holding register - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - if (c >= timeout) return false; + // Wait for byte be become available in rx holding register + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + if (c >= timeout) return false; - c++; + c++; - b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - skip = !skip; - if (skip) continue; + skip = !skip; + if (skip) continue; - if (ManchesterDecoding_iclass(b & 0x0f)) { - if (samples) - *samples = c << 3; - return true; - } - } - } - return false; + if (ManchesterDecoding_iclass(b & 0x0f)) { + if (samples) + *samples = c << 3; + return true; + } + } + } + return false; } int ReaderReceiveIClass(uint8_t* receivedAnswer) { - int samples = 0; + int samples = 0; - if (!GetIClassAnswer(receivedAnswer, 0, &samples, NULL)) - return false; + if (!GetIClassAnswer(receivedAnswer, 0, &samples, NULL)) + return false; - rsamples += samples; + rsamples += samples; - LogTrace(receivedAnswer, Demod.len, rsamples, rsamples, NULL, false); + LogTrace(receivedAnswer, Demod.len, rsamples, rsamples, NULL, false); - if (samples == 0) - return false; + if (samples == 0) + return false; - return Demod.len; + return Demod.len; } void setupIclassReader() { - LEDsoff(); + LEDsoff(); // Start from off (no field generated) // Signal field is off with the appropriate LED @@ -1815,39 +1815,39 @@ void setupIclassReader() { SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - clear_trace(); - set_tracing(true); + clear_trace(); + set_tracing(true); // Now give it time to spin up. // Signal field is on with the appropriate LED FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); SpinDelay(300); - StartCountSspClk(); + StartCountSspClk(); LED_A_ON(); } bool sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* resp, uint8_t expected_size, uint8_t retries) { - uint8_t got_n = 0; - while (retries-- > 0) { + uint8_t got_n = 0; + while (retries-- > 0) { - ReaderTransmitIClass(command, cmdsize); + ReaderTransmitIClass(command, cmdsize); - //iceman - if received size is bigger than expected, we smash the stack here - // since its called with fixed sized arrays - got_n = ReaderReceiveIClass(resp); + //iceman - if received size is bigger than expected, we smash the stack here + // since its called with fixed sized arrays + got_n = ReaderReceiveIClass(resp); - // 0xBB is the internal debug separator byte.. - if ( expected_size != got_n|| (resp[0] == 0xBB || resp[7] == 0xBB || resp[2] == 0xBB)) { - //try again - continue; - } + // 0xBB is the internal debug separator byte.. + if ( expected_size != got_n|| (resp[0] == 0xBB || resp[7] == 0xBB || resp[2] == 0xBB)) { + //try again + continue; + } - if (got_n == expected_size) - return true; - } - return false; + if (got_n == expected_size) + return true; + } + return false; } /** @@ -1859,357 +1859,357 @@ bool sendCmdGetResponseWithRetries(uint8_t* command, size_t cmdsize, uint8_t* re */ uint8_t handshakeIclassTag_ext(uint8_t *card_data, bool use_credit_key) { - // act_all... - static uint8_t act_all[] = { ICLASS_CMD_ACTALL }; - static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 }; - static uint8_t select[] = { ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK_KD, 0x02 }; + // act_all... + static uint8_t act_all[] = { ICLASS_CMD_ACTALL }; + static uint8_t identify[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x00, 0x73, 0x33 }; + static uint8_t select[] = { ICLASS_CMD_SELECT, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK_KD, 0x02 }; - if (use_credit_key) - readcheck_cc[0] = ICLASS_CMD_READCHECK_KC; + if (use_credit_key) + readcheck_cc[0] = ICLASS_CMD_READCHECK_KC; - uint8_t resp[ICLASS_BUFFER_SIZE] = {0}; - uint8_t read_status = 0; + uint8_t resp[ICLASS_BUFFER_SIZE] = {0}; + uint8_t read_status = 0; - // Send act_all - ReaderTransmitIClass_ext(act_all, 1, 330+160); - // Card present? - if (!ReaderReceiveIClass(resp)) return read_status;//Fail + // Send act_all + ReaderTransmitIClass_ext(act_all, 1, 330+160); + // Card present? + if (!ReaderReceiveIClass(resp)) return read_status;//Fail - //Send Identify - ReaderTransmitIClass(identify, 1); + //Send Identify + ReaderTransmitIClass(identify, 1); - //We expect a 10-byte response here, 8 byte anticollision-CSN and 2 byte CRC - uint8_t len = ReaderReceiveIClass(resp); - if (len != 10) return read_status;//Fail + //We expect a 10-byte response here, 8 byte anticollision-CSN and 2 byte CRC + uint8_t len = ReaderReceiveIClass(resp); + if (len != 10) return read_status;//Fail - //Copy the Anti-collision CSN to our select-packet - memcpy(&select[1], resp, 8); + //Copy the Anti-collision CSN to our select-packet + memcpy(&select[1], resp, 8); - //Select the card - ReaderTransmitIClass(select, sizeof(select)); + //Select the card + ReaderTransmitIClass(select, sizeof(select)); - //We expect a 10-byte response here, 8 byte CSN and 2 byte CRC - len = ReaderReceiveIClass(resp); - if (len != 10) return read_status;//Fail + //We expect a 10-byte response here, 8 byte CSN and 2 byte CRC + len = ReaderReceiveIClass(resp); + if (len != 10) return read_status;//Fail - //Success - level 1, we got CSN - //Save CSN in response data - memcpy(card_data, resp, 8); + //Success - level 1, we got CSN + //Save CSN in response data + memcpy(card_data, resp, 8); - //Flag that we got to at least stage 1, read CSN - read_status = 1; + //Flag that we got to at least stage 1, read CSN + read_status = 1; - // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC) - // ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); - // if (ReaderReceiveIClass(resp) == 8) { - // //Save CC (e-purse) in response data - // memcpy(card_data+8, resp, 8); - // read_status++; - // } + // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC) + // ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); + // if (ReaderReceiveIClass(resp) == 8) { + // //Save CC (e-purse) in response data + // memcpy(card_data+8, resp, 8); + // read_status++; + // } - bool isOK = sendCmdGetResponseWithRetries(readcheck_cc, sizeof(readcheck_cc), resp, 8, 3); - if (!isOK) return read_status; + bool isOK = sendCmdGetResponseWithRetries(readcheck_cc, sizeof(readcheck_cc), resp, 8, 3); + if (!isOK) return read_status; - //Save CC (e-purse) in response data - memcpy(card_data+8, resp, 8); - read_status++; - return read_status; + //Save CC (e-purse) in response data + memcpy(card_data+8, resp, 8); + read_status++; + return read_status; } uint8_t handshakeIclassTag(uint8_t *card_data){ - return handshakeIclassTag_ext(card_data, false); + return handshakeIclassTag_ext(card_data, false); } // Reader iClass Anticollission // turn off afterwards void ReaderIClass(uint8_t arg0) { - uint8_t card_data[6 * 8] = {0}; - uint8_t last_csn[8] = {0,0,0,0,0,0,0,0}; - uint8_t resp[ICLASS_BUFFER_SIZE]; + uint8_t card_data[6 * 8] = {0}; + uint8_t last_csn[8] = {0,0,0,0,0,0,0,0}; + uint8_t resp[ICLASS_BUFFER_SIZE]; - memset(card_data, 0xFF, sizeof(card_data)); - memset(resp, 0xFF, sizeof(resp)); + memset(card_data, 0xFF, sizeof(card_data)); + memset(resp, 0xFF, sizeof(resp)); - //Read conf block CRC(0x01) => 0xfa 0x22 - uint8_t readConf[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x01, 0xfa, 0x22}; + //Read conf block CRC(0x01) => 0xfa 0x22 + uint8_t readConf[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x01, 0xfa, 0x22}; - //Read App Issuer Area block CRC(0x05) => 0xde 0x64 - uint8_t readAA[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64}; + //Read App Issuer Area block CRC(0x05) => 0xde 0x64 + uint8_t readAA[] = { ICLASS_CMD_READ_OR_IDENTIFY, 0x05, 0xde, 0x64}; int read_status = 0; - uint16_t tryCnt = 0; - uint8_t result_status = 0; + uint16_t tryCnt = 0; + uint8_t result_status = 0; - bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; // flag to read until one tag is found successfully - bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY; // flag to not to loop continuously, looking for tag - bool use_credit_key = arg0 & FLAG_ICLASS_READER_CEDITKEY; // flag to use credit key - bool flagReadConfig = arg0 & FLAG_ICLASS_READER_CONF; // flag to read block1, configuration - bool flagReadCC = arg0 & FLAG_ICLASS_READER_CC; // flag to read block2, e-purse - bool flagReadAIA = arg0 & FLAG_ICLASS_READER_AIA; // flag to read block5, application issuer area + bool abort_after_read = arg0 & FLAG_ICLASS_READER_ONLY_ONCE; // flag to read until one tag is found successfully + bool try_once = arg0 & FLAG_ICLASS_READER_ONE_TRY; // flag to not to loop continuously, looking for tag + bool use_credit_key = arg0 & FLAG_ICLASS_READER_CEDITKEY; // flag to use credit key + bool flagReadConfig = arg0 & FLAG_ICLASS_READER_CONF; // flag to read block1, configuration + bool flagReadCC = arg0 & FLAG_ICLASS_READER_CC; // flag to read block2, e-purse + bool flagReadAIA = arg0 & FLAG_ICLASS_READER_AIA; // flag to read block5, application issuer area - setupIclassReader(); + setupIclassReader(); - bool userCancelled = BUTTON_PRESS() || usb_poll_validate_length(); - while (!userCancelled) { + bool userCancelled = BUTTON_PRESS() || usb_poll_validate_length(); + while (!userCancelled) { - WDT_HIT(); + WDT_HIT(); - // if only looking for one card try 2 times if we missed it the first time - if (try_once && tryCnt > 2) { - if (MF_DBGLEVEL > 1) DbpString("Failed to find a tag"); - break; - } + // if only looking for one card try 2 times if we missed it the first time + if (try_once && tryCnt > 2) { + if (MF_DBGLEVEL > 1) DbpString("Failed to find a tag"); + break; + } - tryCnt++; - result_status = 0; + tryCnt++; + result_status = 0; - read_status = handshakeIclassTag_ext(card_data, use_credit_key); + read_status = handshakeIclassTag_ext(card_data, use_credit_key); - if (read_status == 0) continue; - if (read_status == 1) result_status = FLAG_ICLASS_READER_CSN; - if (read_status == 2) result_status = FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CC; + if (read_status == 0) continue; + if (read_status == 1) result_status = FLAG_ICLASS_READER_CSN; + if (read_status == 2) result_status = FLAG_ICLASS_READER_CSN | FLAG_ICLASS_READER_CC; - // handshakeIclass returns CSN|CC, but the actual block - // layout is CSN|CONFIG|CC, so here we reorder the data, - // moving CC forward 8 bytes - memcpy(card_data+16, card_data+8, 8); + // handshakeIclass returns CSN|CC, but the actual block + // layout is CSN|CONFIG|CC, so here we reorder the data, + // moving CC forward 8 bytes + memcpy(card_data+16, card_data+8, 8); - //Read block 1, config - if (flagReadConfig) { - if (sendCmdGetResponseWithRetries(readConf, sizeof(readConf), resp, 10, 5)) { - result_status |= FLAG_ICLASS_READER_CONF; - memcpy(card_data+8, resp, 8); - } else { - if (MF_DBGLEVEL > 1) DbpString("Failed to dump config block"); - } - } + //Read block 1, config + if (flagReadConfig) { + if (sendCmdGetResponseWithRetries(readConf, sizeof(readConf), resp, 10, 5)) { + result_status |= FLAG_ICLASS_READER_CONF; + memcpy(card_data+8, resp, 8); + } else { + if (MF_DBGLEVEL > 1) DbpString("Failed to dump config block"); + } + } - //Read block 5, AIA - if (flagReadAIA) { - if (sendCmdGetResponseWithRetries(readAA, sizeof(readAA), resp, 10, 5)) { - result_status |= FLAG_ICLASS_READER_AIA; - memcpy(card_data+(8*5), resp, 8); - } else { - if (MF_DBGLEVEL > 1) DbpString("Failed to dump AA block"); - } - } + //Read block 5, AIA + if (flagReadAIA) { + if (sendCmdGetResponseWithRetries(readAA, sizeof(readAA), resp, 10, 5)) { + result_status |= FLAG_ICLASS_READER_AIA; + memcpy(card_data+(8*5), resp, 8); + } else { + if (MF_DBGLEVEL > 1) DbpString("Failed to dump AA block"); + } + } - // 0 : CSN - // 1 : Configuration - // 2 : e-purse - // 3 : kd / debit / aa2 (write-only) - // 4 : kc / credit / aa1 (write-only) - // 5 : AIA, Application issuer area - // - //Then we can 'ship' back the 6 * 8 bytes of data, - // with 0xFF:s in block 3 and 4. + // 0 : CSN + // 1 : Configuration + // 2 : e-purse + // 3 : kd / debit / aa2 (write-only) + // 4 : kc / credit / aa1 (write-only) + // 5 : AIA, Application issuer area + // + //Then we can 'ship' back the 6 * 8 bytes of data, + // with 0xFF:s in block 3 and 4. - LED_B_ON(); - //Send back to client, but don't bother if we already sent this - - // only useful if looping in arm (not try_once && not abort_after_read) - if (memcmp(last_csn, card_data, 8) != 0) { - // If caller requires that we get Conf, CC, AA, continue until we got it - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("STATUS %02X | CSN %c | CONF %c | CC %c | AIA %c | ONCE %c | 1TRY %c", - result_status, - (result_status & FLAG_ICLASS_READER_CSN) ? 'Y':'N', - (result_status & FLAG_ICLASS_READER_CONF)? 'Y':'N', - (result_status & FLAG_ICLASS_READER_CC) ? 'Y':'N', - (result_status & FLAG_ICLASS_READER_AIA) ? 'Y':'N' - ); - Dbprintf(" aar %c | to %c, | uc %c | frc %c | fra %c | cc %c", - abort_after_read ? 'Y':'N', - try_once ? 'Y':'N', - use_credit_key ? 'Y':'N', - flagReadConfig ? 'Y':'N', - flagReadAIA ? 'Y':'N', - flagReadCC ? 'Y':'N' - ); - } + LED_B_ON(); + //Send back to client, but don't bother if we already sent this - + // only useful if looping in arm (not try_once && not abort_after_read) + if (memcmp(last_csn, card_data, 8) != 0) { + // If caller requires that we get Conf, CC, AA, continue until we got it + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("STATUS %02X | CSN %c | CONF %c | CC %c | AIA %c | ONCE %c | 1TRY %c", + result_status, + (result_status & FLAG_ICLASS_READER_CSN) ? 'Y':'N', + (result_status & FLAG_ICLASS_READER_CONF)? 'Y':'N', + (result_status & FLAG_ICLASS_READER_CC) ? 'Y':'N', + (result_status & FLAG_ICLASS_READER_AIA) ? 'Y':'N' + ); + Dbprintf(" aar %c | to %c, | uc %c | frc %c | fra %c | cc %c", + abort_after_read ? 'Y':'N', + try_once ? 'Y':'N', + use_credit_key ? 'Y':'N', + flagReadConfig ? 'Y':'N', + flagReadAIA ? 'Y':'N', + flagReadCC ? 'Y':'N' + ); + } - bool send = (result_status & FLAG_ICLASS_READER_CSN ); - if (flagReadCC) - send |= (result_status & FLAG_ICLASS_READER_CC ); - if (flagReadAIA) - send |= (result_status & FLAG_ICLASS_READER_AIA ); - if (flagReadConfig) - send |= (result_status & FLAG_ICLASS_READER_CONF ); + bool send = (result_status & FLAG_ICLASS_READER_CSN ); + if (flagReadCC) + send |= (result_status & FLAG_ICLASS_READER_CC ); + if (flagReadAIA) + send |= (result_status & FLAG_ICLASS_READER_AIA ); + if (flagReadConfig) + send |= (result_status & FLAG_ICLASS_READER_CONF ); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SEND %c", send?'y':'n'); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("SEND %c", send?'y':'n'); - if ( send ) { - cmd_send(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data) ); - if (abort_after_read) { - LED_B_OFF(); - return; - } - //Save that we already sent this.... - memcpy(last_csn, card_data, 8); - } - } - LED_B_OFF(); - userCancelled = BUTTON_PRESS() || usb_poll_validate_length(); - } + if ( send ) { + cmd_send(CMD_ACK, result_status, 0, 0, card_data, sizeof(card_data) ); + if (abort_after_read) { + LED_B_OFF(); + return; + } + //Save that we already sent this.... + memcpy(last_csn, card_data, 8); + } + } + LED_B_OFF(); + userCancelled = BUTTON_PRESS() || usb_poll_validate_length(); + } - if (userCancelled) { - cmd_send(CMD_ACK, 0xFF, 0, 0, card_data, 0); - switch_off(); - } else { - cmd_send(CMD_ACK, 0, 0, 0, card_data, 0); - } + if (userCancelled) { + cmd_send(CMD_ACK, 0xFF, 0, 0, card_data, 0); + switch_off(); + } else { + cmd_send(CMD_ACK, 0, 0, 0, card_data, 0); + } } // turn off afterwards void ReaderIClass_Replay(uint8_t arg0, uint8_t *MAC) { - uint8_t cardsize = 0; - uint8_t mem = 0; - uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 }; - uint8_t card_data[USB_CMD_DATA_SIZE] = {0}; - uint8_t resp[ICLASS_BUFFER_SIZE] = {0}; + uint8_t cardsize = 0; + uint8_t mem = 0; + uint8_t check[] = { 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t read[] = { 0x0c, 0x00, 0x00, 0x00 }; + uint8_t card_data[USB_CMD_DATA_SIZE] = {0}; + uint8_t resp[ICLASS_BUFFER_SIZE] = {0}; - static struct memory_t{ - int k16; - int book; - int k2; - int lockauth; - int keyaccess; - } memory; + static struct memory_t{ + int k16; + int book; + int k2; + int lockauth; + int keyaccess; + } memory; setupIclassReader(); - while (!BUTTON_PRESS()) { + while (!BUTTON_PRESS()) { - WDT_HIT(); + WDT_HIT(); - uint8_t read_status = handshakeIclassTag(card_data); - if (read_status < 2) continue; + uint8_t read_status = handshakeIclassTag(card_data); + if (read_status < 2) continue; - //for now replay captured auth (as cc not updated) - memcpy(check+5, MAC, 4); + //for now replay captured auth (as cc not updated) + memcpy(check+5, MAC, 4); - if (!sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 5)) { - DbpString("Error: Authentication Fail!"); - continue; - } + if (!sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 5)) { + DbpString("Error: Authentication Fail!"); + continue; + } - //first get configuration block (block 1) - read[1] = 1; - AddCrc( read+1, 1 ); + //first get configuration block (block 1) + read[1] = 1; + AddCrc( read+1, 1 ); - if (!sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 5)) { - DbpString("Dump config (block 1) failed"); - continue; - } + if (!sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 5)) { + DbpString("Dump config (block 1) failed"); + continue; + } - mem = resp[5]; - memory.k16 = (mem & 0x80); - memory.book = (mem & 0x20); - memory.k2 = (mem & 0x8); - memory.lockauth = (mem & 0x2); - memory.keyaccess = (mem & 0x1); + mem = resp[5]; + memory.k16 = (mem & 0x80); + memory.book = (mem & 0x20); + memory.k2 = (mem & 0x8); + memory.lockauth = (mem & 0x2); + memory.keyaccess = (mem & 0x1); - cardsize = memory.k16 ? 255 : 32; + cardsize = memory.k16 ? 255 : 32; - WDT_HIT(); - //Set card_data to all zeroes, we'll fill it with data - memset(card_data, 0x0, USB_CMD_DATA_SIZE); - uint8_t failedRead = 0; - uint32_t stored_data_length = 0; + WDT_HIT(); + //Set card_data to all zeroes, we'll fill it with data + memset(card_data, 0x0, USB_CMD_DATA_SIZE); + uint8_t failedRead = 0; + uint32_t stored_data_length = 0; - //then loop around remaining blocks - for ( uint16_t block=0; block < cardsize; block++) { + //then loop around remaining blocks + for ( uint16_t block=0; block < cardsize; block++) { - read[1] = block; - AddCrc( read+1, 1 ); + read[1] = block; + AddCrc( read+1, 1 ); - if (sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 5)) { - Dbprintf(" %02x: %02x %02x %02x %02x %02x %02x %02x %02x", - block, resp[0], resp[1], resp[2], - resp[3], resp[4], resp[5], - resp[6], resp[7] - ); + if (sendCmdGetResponseWithRetries(read, sizeof(read), resp, 10, 5)) { + Dbprintf(" %02x: %02x %02x %02x %02x %02x %02x %02x %02x", + block, resp[0], resp[1], resp[2], + resp[3], resp[4], resp[5], + resp[6], resp[7] + ); - //Fill up the buffer - memcpy(card_data + stored_data_length, resp, 8); - stored_data_length += 8; - if (stored_data_length + 8 > USB_CMD_DATA_SIZE) { - //Time to send this off and start afresh - cmd_send(CMD_ACK, - stored_data_length,//data length - failedRead,//Failed blocks? - 0,//Not used ATM - card_data, - stored_data_length - ); - //reset - stored_data_length = 0; - failedRead = 0; - } - } else { - failedRead = 1; - stored_data_length += 8;//Otherwise, data becomes misaligned - Dbprintf("Failed to dump block %d", block); - } - } + //Fill up the buffer + memcpy(card_data + stored_data_length, resp, 8); + stored_data_length += 8; + if (stored_data_length + 8 > USB_CMD_DATA_SIZE) { + //Time to send this off and start afresh + cmd_send(CMD_ACK, + stored_data_length,//data length + failedRead,//Failed blocks? + 0,//Not used ATM + card_data, + stored_data_length + ); + //reset + stored_data_length = 0; + failedRead = 0; + } + } else { + failedRead = 1; + stored_data_length += 8;//Otherwise, data becomes misaligned + Dbprintf("Failed to dump block %d", block); + } + } - //Send off any remaining data - if (stored_data_length > 0) { - cmd_send(CMD_ACK, - stored_data_length,//data length - failedRead,//Failed blocks? - 0,//Not used ATM - card_data, - stored_data_length - ); - } - //If we got here, let's break - break; - } - //Signal end of transmission - cmd_send(CMD_ACK, - 0,//data length - 0,//Failed blocks? - 0,//Not used ATM - card_data, - 0 - ); - switch_off(); + //Send off any remaining data + if (stored_data_length > 0) { + cmd_send(CMD_ACK, + stored_data_length,//data length + failedRead,//Failed blocks? + 0,//Not used ATM + card_data, + stored_data_length + ); + } + //If we got here, let's break + break; + } + //Signal end of transmission + cmd_send(CMD_ACK, + 0,//data length + 0,//Failed blocks? + 0,//Not used ATM + card_data, + 0 + ); + switch_off(); } // not used. ?!? ( CMD_ICLASS_READCHECK) // turn off afterwards void iClass_ReadCheck(uint8_t blockNo, uint8_t keyType) { - uint8_t readcheck[] = { keyType, blockNo }; - uint8_t resp[] = {0,0,0,0,0,0,0,0}; - size_t isOK = 0; - isOK = sendCmdGetResponseWithRetries(readcheck, sizeof(readcheck), resp, sizeof(resp), 6); - cmd_send(CMD_ACK,isOK,0,0,0,0); - switch_off(); + uint8_t readcheck[] = { keyType, blockNo }; + uint8_t resp[] = {0,0,0,0,0,0,0,0}; + size_t isOK = 0; + isOK = sendCmdGetResponseWithRetries(readcheck, sizeof(readcheck), resp, sizeof(resp), 6); + cmd_send(CMD_ACK,isOK,0,0,0,0); + switch_off(); } // used with function select_and_auth (cmdhficlass.c) // which needs to authenticate before doing more things like read/write void iClass_Authentication(uint8_t *mac) { - uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t resp[ICLASS_BUFFER_SIZE]; + uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t resp[ICLASS_BUFFER_SIZE]; - // copy MAC to check command (readersignature) - check[5] = mac[0]; - check[6] = mac[1]; - check[7] = mac[2]; - check[8] = mac[3]; - //memcpy(check+5, mac, 4); + // copy MAC to check command (readersignature) + check[5] = mac[0]; + check[6] = mac[1]; + check[7] = mac[2]; + check[8] = mac[3]; + //memcpy(check+5, mac, 4); - // 6 retries - bool isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 6); - cmd_send(CMD_ACK,isOK,0,0,0,0); + // 6 retries + bool isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 6); + cmd_send(CMD_ACK,isOK,0,0,0,0); } typedef struct iclass_premac { - uint8_t mac[4]; + uint8_t mac[4]; } iclass_premac_t; /* this function works on the following assumptions. @@ -2220,194 +2220,194 @@ typedef struct iclass_premac { * to cover debit and credit key. (AA1/AA2) */ void iClass_Authentication_fast(uint64_t arg0, uint64_t arg1, uint8_t *datain) { - uint8_t i = 0, isOK = 0; - uint8_t lastChunk = ((arg0 >> 8) & 0xFF); - bool use_credit_key =((arg0 >> 16) & 0xFF); - uint8_t keyCount = arg1 & 0xFF; - uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - uint8_t resp[ICLASS_BUFFER_SIZE]; - uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK_KD, 0x02 }; + uint8_t i = 0, isOK = 0; + uint8_t lastChunk = ((arg0 >> 8) & 0xFF); + bool use_credit_key =((arg0 >> 16) & 0xFF); + uint8_t keyCount = arg1 & 0xFF; + uint8_t check[] = { ICLASS_CMD_CHECK, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + uint8_t resp[ICLASS_BUFFER_SIZE]; + uint8_t readcheck_cc[] = { ICLASS_CMD_READCHECK_KD, 0x02 }; - if (use_credit_key) - readcheck_cc[0] = ICLASS_CMD_READCHECK_KC; + if (use_credit_key) + readcheck_cc[0] = ICLASS_CMD_READCHECK_KC; - // select card / e-purse - uint8_t card_data[6 * 8] = {0}; + // select card / e-purse + uint8_t card_data[6 * 8] = {0}; - iclass_premac_t *keys = (iclass_premac_t *)datain; + iclass_premac_t *keys = (iclass_premac_t *)datain; - LED_A_ON(); + LED_A_ON(); - switch_off(); - SpinDelay(20); + switch_off(); + SpinDelay(20); - setupIclassReader(); + setupIclassReader(); - int read_status = 0; - uint8_t startup_limit = 10; - while ( read_status != 2) { + int read_status = 0; + uint8_t startup_limit = 10; + while ( read_status != 2) { - if (BUTTON_PRESS() && !usb_poll_validate_length()) goto out; + if (BUTTON_PRESS() && !usb_poll_validate_length()) goto out; - read_status = handshakeIclassTag_ext(card_data, use_credit_key); - if ( startup_limit-- == 0 ) { - Dbprintf("[-] Handshake status | %d (fail 10)", read_status); - isOK = 99; - goto out; - } - }; - // since handshakeIclassTag_ext call sends s readcheck, we start with sending first response. + read_status = handshakeIclassTag_ext(card_data, use_credit_key); + if ( startup_limit-- == 0 ) { + Dbprintf("[-] Handshake status | %d (fail 10)", read_status); + isOK = 99; + goto out; + } + }; + // since handshakeIclassTag_ext call sends s readcheck, we start with sending first response. - // Keychunk loop - for (i = 0; i < keyCount; i++) { + // Keychunk loop + for (i = 0; i < keyCount; i++) { - // Allow button press / usb cmd to interrupt device - if (BUTTON_PRESS() && !usb_poll_validate_length()) break; + // Allow button press / usb cmd to interrupt device + if (BUTTON_PRESS() && !usb_poll_validate_length()) break; - WDT_HIT(); - LED_B_ON(); + WDT_HIT(); + LED_B_ON(); - // copy MAC to check command (readersignature) - check[5] = keys[i].mac[0]; - check[6] = keys[i].mac[1]; - check[7] = keys[i].mac[2]; - check[8] = keys[i].mac[3]; + // copy MAC to check command (readersignature) + check[5] = keys[i].mac[0]; + check[6] = keys[i].mac[1]; + check[7] = keys[i].mac[2]; + check[8] = keys[i].mac[3]; - // expect 4bytes, 3 retries times.. - isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 3); - if ( isOK ) - goto out; + // expect 4bytes, 3 retries times.. + isOK = sendCmdGetResponseWithRetries(check, sizeof(check), resp, 4, 3); + if ( isOK ) + goto out; - SpinDelayUs(400); //iClass (iso15693-2) should timeout after 330us. + SpinDelayUs(400); //iClass (iso15693-2) should timeout after 330us. - // Auth Sequence MUST begin with reading e-purse. (block2) - // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC) - ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); + // Auth Sequence MUST begin with reading e-purse. (block2) + // Card selected, now read e-purse (cc) (block2) (only 8 bytes no CRC) + ReaderTransmitIClass(readcheck_cc, sizeof(readcheck_cc)); - LED_B_OFF(); - } + LED_B_OFF(); + } out: - // send keyindex. - cmd_send(CMD_ACK, isOK, i, 0, 0, 0); + // send keyindex. + cmd_send(CMD_ACK, isOK, i, 0, 0, 0); - if ( isOK >= 1 || lastChunk ) { - switch_off(); - LED_A_OFF(); - } + if ( isOK >= 1 || lastChunk ) { + switch_off(); + LED_A_OFF(); + } - LED_B_OFF(); - LED_C_OFF(); + LED_B_OFF(); + LED_C_OFF(); } // Tries to read block. // retries 10times. bool iClass_ReadBlock(uint8_t blockNo, uint8_t *data, uint8_t len) { - uint8_t resp[10]; - uint8_t cmd[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockNo, 0x00, 0x00}; - AddCrc( cmd+1, 1 ); - // expect size 10, retry 5times - bool isOK = sendCmdGetResponseWithRetries(cmd, sizeof(cmd), resp, 10, 5); - memcpy(data, resp, len); - return isOK; + uint8_t resp[10]; + uint8_t cmd[] = {ICLASS_CMD_READ_OR_IDENTIFY, blockNo, 0x00, 0x00}; + AddCrc( cmd+1, 1 ); + // expect size 10, retry 5times + bool isOK = sendCmdGetResponseWithRetries(cmd, sizeof(cmd), resp, 10, 5); + memcpy(data, resp, len); + return isOK; } // turn off afterwards // readblock 8 + 2. only want 8. void iClass_ReadBlk(uint8_t blockno) { - uint8_t data[] = {0,0,0,0,0,0,0,0,0,0}; - bool isOK = iClass_ReadBlock(blockno, data, sizeof(data)); - cmd_send(CMD_ACK, isOK, 0, 0, data, sizeof(data)); - switch_off(); + uint8_t data[] = {0,0,0,0,0,0,0,0,0,0}; + bool isOK = iClass_ReadBlock(blockno, data, sizeof(data)); + cmd_send(CMD_ACK, isOK, 0, 0, data, sizeof(data)); + switch_off(); } // turn off afterwards void iClass_Dump(uint8_t blockno, uint8_t numblks) { - uint8_t blockdata[] = {0,0,0,0,0,0,0,0,0,0}; - bool isOK = false; - uint8_t blkCnt = 0; + uint8_t blockdata[] = {0,0,0,0,0,0,0,0,0,0}; + bool isOK = false; + uint8_t blkCnt = 0; - BigBuf_free(); - uint8_t *dataout = BigBuf_malloc(255*8); - if (dataout == NULL){ - DbpString("[!] out of memory"); - OnError(1); - return; - } - // fill mem with 0xFF - memset(dataout, 0xFF, 255*8); + BigBuf_free(); + uint8_t *dataout = BigBuf_malloc(255*8); + if (dataout == NULL){ + DbpString("[!] out of memory"); + OnError(1); + return; + } + // fill mem with 0xFF + memset(dataout, 0xFF, 255*8); - for (;blkCnt < numblks; blkCnt++) { - isOK = iClass_ReadBlock(blockno + blkCnt, blockdata, sizeof(blockdata)); + for (;blkCnt < numblks; blkCnt++) { + isOK = iClass_ReadBlock(blockno + blkCnt, blockdata, sizeof(blockdata)); - // 0xBB is the internal debug separator byte.. - if (!isOK || (blockdata[0] == 0xBB || blockdata[7] == 0xBB || blockdata[2] == 0xBB)) { //try again - isOK = iClass_ReadBlock(blockno + blkCnt, blockdata, sizeof(blockdata)); - if (!isOK) { - Dbprintf("[!] block %02X failed to read", blkCnt + blockno); - break; - } - } - memcpy(dataout + (blkCnt * 8), blockdata, 8); - } - //return pointer to dump memory in arg3 - cmd_send(CMD_ACK, isOK, blkCnt, BigBuf_max_traceLen(), 0, 0); - switch_off(); - BigBuf_free(); + // 0xBB is the internal debug separator byte.. + if (!isOK || (blockdata[0] == 0xBB || blockdata[7] == 0xBB || blockdata[2] == 0xBB)) { //try again + isOK = iClass_ReadBlock(blockno + blkCnt, blockdata, sizeof(blockdata)); + if (!isOK) { + Dbprintf("[!] block %02X failed to read", blkCnt + blockno); + break; + } + } + memcpy(dataout + (blkCnt * 8), blockdata, 8); + } + //return pointer to dump memory in arg3 + cmd_send(CMD_ACK, isOK, blkCnt, BigBuf_max_traceLen(), 0, 0); + switch_off(); + BigBuf_free(); } bool iClass_WriteBlock_ext(uint8_t blockNo, uint8_t *data) { - uint8_t resp[] = {0,0,0,0,0,0,0,0,0,0}; - uint8_t write[] = { ICLASS_CMD_UPDATE, blockNo, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; - memcpy(write+2, data, 12); // data + mac - AddCrc(write+1, 13); + uint8_t resp[] = {0,0,0,0,0,0,0,0,0,0}; + uint8_t write[] = { ICLASS_CMD_UPDATE, blockNo, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; + memcpy(write+2, data, 12); // data + mac + AddCrc(write+1, 13); - bool isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 5); - if (isOK) { //if reader responded correctly + bool isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 5); + if (isOK) { //if reader responded correctly - //if response is not equal to write values - if (memcmp(write + 2, resp, 8)) { + //if response is not equal to write values + if (memcmp(write + 2, resp, 8)) { - //if not programming key areas (note key blocks don't get programmed with actual key data it is xor data) - if (blockNo != 3 && blockNo != 4) { - isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 5); - } - } - } - return isOK; + //if not programming key areas (note key blocks don't get programmed with actual key data it is xor data) + if (blockNo != 3 && blockNo != 4) { + isOK = sendCmdGetResponseWithRetries(write, sizeof(write), resp, sizeof(resp), 5); + } + } + } + return isOK; } // turn off afterwards void iClass_WriteBlock(uint8_t blockNo, uint8_t *data) { - bool isOK = iClass_WriteBlock_ext(blockNo, data); - cmd_send(CMD_ACK,isOK,0,0,0,0); - switch_off(); + bool isOK = iClass_WriteBlock_ext(blockNo, data); + cmd_send(CMD_ACK,isOK,0,0,0,0); + switch_off(); } // turn off afterwards void iClass_Clone(uint8_t startblock, uint8_t endblock, uint8_t *data) { - int i, written = 0; - int total_block = (endblock - startblock) + 1; - for (i = 0; i < total_block; i++){ - // block number - if (iClass_WriteBlock_ext(i + startblock, data + ( i*12 ) )){ - Dbprintf("Write block [%02x] successful", i + startblock); - written++; - } else { - if (iClass_WriteBlock_ext(i + startblock, data + ( i*12 ) )){ - Dbprintf("Write block [%02x] successful", i + startblock); - written++; - } else { - Dbprintf("Write block [%02x] failed", i + startblock); - } - } - } - if (written == total_block) - DbpString("Clone complete"); - else - DbpString("Clone incomplete"); + int i, written = 0; + int total_block = (endblock - startblock) + 1; + for (i = 0; i < total_block; i++){ + // block number + if (iClass_WriteBlock_ext(i + startblock, data + ( i*12 ) )){ + Dbprintf("Write block [%02x] successful", i + startblock); + written++; + } else { + if (iClass_WriteBlock_ext(i + startblock, data + ( i*12 ) )){ + Dbprintf("Write block [%02x] successful", i + startblock); + written++; + } else { + Dbprintf("Write block [%02x] failed", i + startblock); + } + } + } + if (written == total_block) + DbpString("Clone complete"); + else + DbpString("Clone incomplete"); - cmd_send(CMD_ACK,1,0,0,0,0); - switch_off(); + cmd_send(CMD_ACK,1,0,0,0,0); + switch_off(); } \ No newline at end of file diff --git a/armsrc/iso14443a.c b/armsrc/iso14443a.c index 9e415fcdb..e44af5fe3 100644 --- a/armsrc/iso14443a.c +++ b/armsrc/iso14443a.c @@ -112,49 +112,49 @@ static uint32_t LastProxToAirDuration; // Sequence X: 00001100 drop after half a period // Sequence Y: 00000000 no drop // Sequence Z: 11000000 drop at start -#define SEC_D 0xf0 -#define SEC_E 0x0f -#define SEC_F 0x00 +#define SEC_D 0xf0 +#define SEC_E 0x0f +#define SEC_F 0x00 #define SEC_COLL 0xff -#define SEC_X 0x0c -#define SEC_Y 0x00 -#define SEC_Z 0xc0 +#define SEC_X 0x0c +#define SEC_Y 0x00 +#define SEC_Z 0xc0 void iso14a_set_trigger(bool enable) { - trigger = enable; + trigger = enable; } void iso14a_set_timeout(uint32_t timeout) { - iso14a_timeout = timeout + (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/(16*8) + 2; + iso14a_timeout = timeout + (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/(16*8) + 2; } uint32_t iso14a_get_timeout(void) { - return iso14a_timeout - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/(16*8) - 2; + return iso14a_timeout - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/(16*8) - 2; } //----------------------------------------------------------------------------- // Generate the parity value for a byte sequence //----------------------------------------------------------------------------- void GetParity(const uint8_t *pbtCmd, uint16_t iLen, uint8_t *par) { - uint16_t paritybit_cnt = 0; - uint16_t paritybyte_cnt = 0; - uint8_t parityBits = 0; + uint16_t paritybit_cnt = 0; + uint16_t paritybyte_cnt = 0; + uint8_t parityBits = 0; - for (uint16_t i = 0; i < iLen; i++) { - // Generate the parity bits - parityBits |= ((oddparity8(pbtCmd[i])) << (7-paritybit_cnt)); - if (paritybit_cnt == 7) { - par[paritybyte_cnt] = parityBits; // save 8 Bits parity - parityBits = 0; // and advance to next Parity Byte - paritybyte_cnt++; - paritybit_cnt = 0; - } else { - paritybit_cnt++; - } - } + for (uint16_t i = 0; i < iLen; i++) { + // Generate the parity bits + parityBits |= ((oddparity8(pbtCmd[i])) << (7-paritybit_cnt)); + if (paritybit_cnt == 7) { + par[paritybyte_cnt] = parityBits; // save 8 Bits parity + parityBits = 0; // and advance to next Parity Byte + paritybyte_cnt++; + paritybit_cnt = 0; + } else { + paritybit_cnt++; + } + } - // save remaining parity bits - par[paritybyte_cnt] = parityBits; + // save remaining parity bits + par[paritybyte_cnt] = parityBits; } @@ -168,9 +168,9 @@ void GetParity(const uint8_t *pbtCmd, uint16_t iLen, uint8_t *par) { // The FPGA does a comparison with a threshold and would deliver e.g.: // ........ 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 0 0 1 1 1 1 1 1 1 1 1 1 ....... // The Miller decoder needs to identify the following sequences: -// 2 (or 3) ticks pause followed by 6 (or 5) ticks unmodulated: pause at beginning - Sequence Z ("start of communication" or a "0") -// 8 ticks without a modulation: no pause - Sequence Y (a "0" or "end of communication" or "no information") -// 4 ticks unmodulated followed by 2 (or 3) ticks pause: pause in second half - Sequence X (a "1") +// 2 (or 3) ticks pause followed by 6 (or 5) ticks unmodulated: pause at beginning - Sequence Z ("start of communication" or a "0") +// 8 ticks without a modulation: no pause - Sequence Y (a "0" or "end of communication" or "no information") +// 4 ticks unmodulated followed by 2 (or 3) ticks pause: pause in second half - Sequence X (a "1") // Note 1: the bitstream may start at any time. We therefore need to sync. // Note 2: the interpretation of Sequence Y and Z depends on the preceding sequence. //----------------------------------------------------------------------------- @@ -183,155 +183,155 @@ static tUart Uart; // 0111 - a 2 tick wide pause shifted left // 1001 - a 2 tick wide pause shifted right const bool Mod_Miller_LUT[] = { - false, true, false, true, false, false, false, true, - false, true, false, false, false, false, false, false + false, true, false, true, false, false, false, true, + false, true, false, false, false, false, false, false }; #define IsMillerModulationNibble1(b) (Mod_Miller_LUT[(b & 0x000000F0) >> 4]) #define IsMillerModulationNibble2(b) (Mod_Miller_LUT[(b & 0x0000000F)]) tUart* GetUart() { - return &Uart; + return &Uart; } void UartReset(void) { - Uart.state = STATE_UNSYNCD; - Uart.bitCount = 0; - Uart.len = 0; // number of decoded data bytes - Uart.parityLen = 0; // number of decoded parity bytes - Uart.shiftReg = 0; // shiftreg to hold decoded data bits - Uart.parityBits = 0; // holds 8 parity bits - Uart.startTime = 0; - Uart.endTime = 0; - Uart.fourBits = 0x00000000; // clear the buffer for 4 Bits - Uart.posCnt = 0; - Uart.syncBit = 9999; + Uart.state = STATE_UNSYNCD; + Uart.bitCount = 0; + Uart.len = 0; // number of decoded data bytes + Uart.parityLen = 0; // number of decoded parity bytes + Uart.shiftReg = 0; // shiftreg to hold decoded data bits + Uart.parityBits = 0; // holds 8 parity bits + Uart.startTime = 0; + Uart.endTime = 0; + Uart.fourBits = 0x00000000; // clear the buffer for 4 Bits + Uart.posCnt = 0; + Uart.syncBit = 9999; } void UartInit(uint8_t *data, uint8_t *parity) { - Uart.output = data; - Uart.parity = parity; - UartReset(); + Uart.output = data; + Uart.parity = parity; + UartReset(); } // use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) { - Uart.fourBits = (Uart.fourBits << 8) | bit; + Uart.fourBits = (Uart.fourBits << 8) | bit; - if (Uart.state == STATE_UNSYNCD) { // not yet synced - Uart.syncBit = 9999; // not set + if (Uart.state == STATE_UNSYNCD) { // not yet synced + Uart.syncBit = 9999; // not set - // 00x11111 2|3 ticks pause followed by 6|5 ticks unmodulated Sequence Z (a "0" or "start of communication") - // 11111111 8 ticks unmodulation Sequence Y (a "0" or "end of communication" or "no information") - // 111100x1 4 ticks unmodulated followed by 2|3 ticks pause Sequence X (a "1") + // 00x11111 2|3 ticks pause followed by 6|5 ticks unmodulated Sequence Z (a "0" or "start of communication") + // 11111111 8 ticks unmodulation Sequence Y (a "0" or "end of communication" or "no information") + // 111100x1 4 ticks unmodulated followed by 2|3 ticks pause Sequence X (a "1") - // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from - // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111) - // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern - // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's) - #define ISO14443A_STARTBIT_MASK 0x07FFEF80 // mask is 00000111 11111111 11101111 10000000 - #define ISO14443A_STARTBIT_PATTERN 0x07FF8F80 // pattern is 00000111 11111111 10001111 10000000 - if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 0)) == ISO14443A_STARTBIT_PATTERN >> 0) Uart.syncBit = 7; - else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 1)) == ISO14443A_STARTBIT_PATTERN >> 1) Uart.syncBit = 6; - else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 2)) == ISO14443A_STARTBIT_PATTERN >> 2) Uart.syncBit = 5; - else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 3)) == ISO14443A_STARTBIT_PATTERN >> 3) Uart.syncBit = 4; - else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 4)) == ISO14443A_STARTBIT_PATTERN >> 4) Uart.syncBit = 3; - else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 5)) == ISO14443A_STARTBIT_PATTERN >> 5) Uart.syncBit = 2; - else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 6)) == ISO14443A_STARTBIT_PATTERN >> 6) Uart.syncBit = 1; - else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 7)) == ISO14443A_STARTBIT_PATTERN >> 7) Uart.syncBit = 0; + // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from + // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111) + // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern + // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's) + #define ISO14443A_STARTBIT_MASK 0x07FFEF80 // mask is 00000111 11111111 11101111 10000000 + #define ISO14443A_STARTBIT_PATTERN 0x07FF8F80 // pattern is 00000111 11111111 10001111 10000000 + if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 0)) == ISO14443A_STARTBIT_PATTERN >> 0) Uart.syncBit = 7; + else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 1)) == ISO14443A_STARTBIT_PATTERN >> 1) Uart.syncBit = 6; + else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 2)) == ISO14443A_STARTBIT_PATTERN >> 2) Uart.syncBit = 5; + else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 3)) == ISO14443A_STARTBIT_PATTERN >> 3) Uart.syncBit = 4; + else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 4)) == ISO14443A_STARTBIT_PATTERN >> 4) Uart.syncBit = 3; + else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 5)) == ISO14443A_STARTBIT_PATTERN >> 5) Uart.syncBit = 2; + else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 6)) == ISO14443A_STARTBIT_PATTERN >> 6) Uart.syncBit = 1; + else if ((Uart.fourBits & (ISO14443A_STARTBIT_MASK >> 7)) == ISO14443A_STARTBIT_PATTERN >> 7) Uart.syncBit = 0; - if (Uart.syncBit != 9999) { // found a sync bit - Uart.startTime = non_real_time ? non_real_time : (GetCountSspClk() & 0xfffffff8); - Uart.startTime -= Uart.syncBit; - Uart.endTime = Uart.startTime; - Uart.state = STATE_START_OF_COMMUNICATION; - } - } else { + if (Uart.syncBit != 9999) { // found a sync bit + Uart.startTime = non_real_time ? non_real_time : (GetCountSspClk() & 0xfffffff8); + Uart.startTime -= Uart.syncBit; + Uart.endTime = Uart.startTime; + Uart.state = STATE_START_OF_COMMUNICATION; + } + } else { - if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) { - if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation in both halves - error - UartReset(); - } else { // Modulation in first half = Sequence Z = logic "0" - if (Uart.state == STATE_MILLER_X) { // error - must not follow after X - UartReset(); - } else { - Uart.bitCount++; - Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg - Uart.state = STATE_MILLER_Z; - Uart.endTime = Uart.startTime + 8 * (9 * Uart.len + Uart.bitCount + 1) - 6; - if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity) - Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); - Uart.parityBits <<= 1; // make room for the parity bit - Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit - Uart.bitCount = 0; - Uart.shiftReg = 0; - if ((Uart.len & 0x0007) == 0) { // every 8 data bytes - Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits - Uart.parityBits = 0; - } - } - } - } - } else { - if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation second half = Sequence X = logic "1" - Uart.bitCount++; - Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100; // add a 1 to the shiftreg - Uart.state = STATE_MILLER_X; - Uart.endTime = Uart.startTime + 8 * (9 * Uart.len + Uart.bitCount + 1) - 2; - if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity) - Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); - Uart.parityBits <<= 1; // make room for the new parity bit - Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit - Uart.bitCount = 0; - Uart.shiftReg = 0; - if ((Uart.len & 0x0007) == 0) { // every 8 data bytes - Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits - Uart.parityBits = 0; - } - } - } else { // no modulation in both halves - Sequence Y - if (Uart.state == STATE_MILLER_Z || Uart.state == STATE_MILLER_Y) { // Y after logic "0" - End of Communication - Uart.state = STATE_UNSYNCD; - Uart.bitCount--; // last "0" was part of EOC sequence - Uart.shiftReg <<= 1; // drop it - if (Uart.bitCount > 0) { // if we decoded some bits - Uart.shiftReg >>= (9 - Uart.bitCount); // right align them - Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); // add last byte to the output - Uart.parityBits <<= 1; // add a (void) parity bit - Uart.parityBits <<= (8 - (Uart.len&0x0007)); // left align parity bits - Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store it - return true; - } else if (Uart.len & 0x0007) { // there are some parity bits to store - Uart.parityBits <<= (8 - (Uart.len&0x0007)); // left align remaining parity bits - Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store them - } - if (Uart.len) { - return true; // we are finished with decoding the raw data sequence - } else { - UartReset(); // Nothing received - start over - } - } - if (Uart.state == STATE_START_OF_COMMUNICATION) { // error - must not follow directly after SOC - UartReset(); - } else { // a logic "0" - Uart.bitCount++; - Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg - Uart.state = STATE_MILLER_Y; - if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity) - Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); - Uart.parityBits <<= 1; // make room for the parity bit - Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit - Uart.bitCount = 0; - Uart.shiftReg = 0; - if ((Uart.len & 0x0007) == 0) { // every 8 data bytes - Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits - Uart.parityBits = 0; - } - } - } - } - } - } - return false; // not finished yet, need more data + if (IsMillerModulationNibble1(Uart.fourBits >> Uart.syncBit)) { + if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation in both halves - error + UartReset(); + } else { // Modulation in first half = Sequence Z = logic "0" + if (Uart.state == STATE_MILLER_X) { // error - must not follow after X + UartReset(); + } else { + Uart.bitCount++; + Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg + Uart.state = STATE_MILLER_Z; + Uart.endTime = Uart.startTime + 8 * (9 * Uart.len + Uart.bitCount + 1) - 6; + if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity) + Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); + Uart.parityBits <<= 1; // make room for the parity bit + Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit + Uart.bitCount = 0; + Uart.shiftReg = 0; + if ((Uart.len & 0x0007) == 0) { // every 8 data bytes + Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits + Uart.parityBits = 0; + } + } + } + } + } else { + if (IsMillerModulationNibble2(Uart.fourBits >> Uart.syncBit)) { // Modulation second half = Sequence X = logic "1" + Uart.bitCount++; + Uart.shiftReg = (Uart.shiftReg >> 1) | 0x100; // add a 1 to the shiftreg + Uart.state = STATE_MILLER_X; + Uart.endTime = Uart.startTime + 8 * (9 * Uart.len + Uart.bitCount + 1) - 2; + if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity) + Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); + Uart.parityBits <<= 1; // make room for the new parity bit + Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit + Uart.bitCount = 0; + Uart.shiftReg = 0; + if ((Uart.len & 0x0007) == 0) { // every 8 data bytes + Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits + Uart.parityBits = 0; + } + } + } else { // no modulation in both halves - Sequence Y + if (Uart.state == STATE_MILLER_Z || Uart.state == STATE_MILLER_Y) { // Y after logic "0" - End of Communication + Uart.state = STATE_UNSYNCD; + Uart.bitCount--; // last "0" was part of EOC sequence + Uart.shiftReg <<= 1; // drop it + if (Uart.bitCount > 0) { // if we decoded some bits + Uart.shiftReg >>= (9 - Uart.bitCount); // right align them + Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); // add last byte to the output + Uart.parityBits <<= 1; // add a (void) parity bit + Uart.parityBits <<= (8 - (Uart.len&0x0007)); // left align parity bits + Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store it + return true; + } else if (Uart.len & 0x0007) { // there are some parity bits to store + Uart.parityBits <<= (8 - (Uart.len&0x0007)); // left align remaining parity bits + Uart.parity[Uart.parityLen++] = Uart.parityBits; // and store them + } + if (Uart.len) { + return true; // we are finished with decoding the raw data sequence + } else { + UartReset(); // Nothing received - start over + } + } + if (Uart.state == STATE_START_OF_COMMUNICATION) { // error - must not follow directly after SOC + UartReset(); + } else { // a logic "0" + Uart.bitCount++; + Uart.shiftReg = (Uart.shiftReg >> 1); // add a 0 to the shiftreg + Uart.state = STATE_MILLER_Y; + if (Uart.bitCount >= 9) { // if we decoded a full byte (including parity) + Uart.output[Uart.len++] = (Uart.shiftReg & 0xff); + Uart.parityBits <<= 1; // make room for the parity bit + Uart.parityBits |= ((Uart.shiftReg >> 8) & 0x01); // store parity bit + Uart.bitCount = 0; + Uart.shiftReg = 0; + if ((Uart.len & 0x0007) == 0) { // every 8 data bytes + Uart.parity[Uart.parityLen++] = Uart.parityBits; // store 8 parity bits + Uart.parityBits = 0; + } + } + } + } + } + } + return false; // not finished yet, need more data } //============================================================================= @@ -343,10 +343,10 @@ RAMFUNC bool MillerDecoding(uint8_t bit, uint32_t non_real_time) { // at the reader antenna will be modulated as well. The FPGA detects the modulation for us and would deliver e.g. the following: // ........ 0 0 1 1 1 1 0 0 0 0 0 0 0 0 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 ....... // The Manchester decoder needs to identify the following sequences: -// 4 ticks modulated followed by 4 ticks unmodulated: Sequence D = 1 (also used as "start of communication") -// 4 ticks unmodulated followed by 4 ticks modulated: Sequence E = 0 -// 8 ticks unmodulated: Sequence F = end of communication -// 8 ticks modulated: A collision. Save the collision position and treat as Sequence D +// 4 ticks modulated followed by 4 ticks unmodulated: Sequence D = 1 (also used as "start of communication") +// 4 ticks unmodulated followed by 4 ticks modulated: Sequence E = 0 +// 8 ticks unmodulated: Sequence F = end of communication +// 8 ticks modulated: A collision. Save the collision position and treat as Sequence D // Note 1: the bitstream may start at any time. We therefore need to sync. // Note 2: parameter offset is used to determine the position of the parity bits (required for the anticollision command only) tDemod Demod; @@ -354,126 +354,126 @@ tDemod Demod; // Lookup-Table to decide if 4 raw bits are a modulation. // We accept three or four "1" in any position const bool Mod_Manchester_LUT[] = { - false, false, false, false, false, false, false, true, - false, false, false, true, false, true, true, true + false, false, false, false, false, false, false, true, + false, false, false, true, false, true, true, true }; #define IsManchesterModulationNibble1(b) (Mod_Manchester_LUT[(b & 0x00F0) >> 4]) #define IsManchesterModulationNibble2(b) (Mod_Manchester_LUT[(b & 0x000F)]) tDemod* GetDemod() { - return &Demod; + return &Demod; } void DemodReset(void) { - Demod.state = DEMOD_UNSYNCD; - Demod.len = 0; // number of decoded data bytes - Demod.parityLen = 0; - Demod.shiftReg = 0; // shiftreg to hold decoded data bits - Demod.parityBits = 0; // - Demod.collisionPos = 0; // Position of collision bit - Demod.twoBits = 0xFFFF; // buffer for 2 Bits - Demod.highCnt = 0; - Demod.startTime = 0; - Demod.endTime = 0; - Demod.bitCount = 0; - Demod.syncBit = 0xFFFF; - Demod.samples = 0; + Demod.state = DEMOD_UNSYNCD; + Demod.len = 0; // number of decoded data bytes + Demod.parityLen = 0; + Demod.shiftReg = 0; // shiftreg to hold decoded data bits + Demod.parityBits = 0; // + Demod.collisionPos = 0; // Position of collision bit + Demod.twoBits = 0xFFFF; // buffer for 2 Bits + Demod.highCnt = 0; + Demod.startTime = 0; + Demod.endTime = 0; + Demod.bitCount = 0; + Demod.syncBit = 0xFFFF; + Demod.samples = 0; } void DemodInit(uint8_t *data, uint8_t *parity) { - Demod.output = data; - Demod.parity = parity; - DemodReset(); + Demod.output = data; + Demod.parity = parity; + DemodReset(); } // use parameter non_real_time to provide a timestamp. Set to 0 if the decoder should measure real time RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_time) { - Demod.twoBits = (Demod.twoBits << 8) | bit; + Demod.twoBits = (Demod.twoBits << 8) | bit; - if (Demod.state == DEMOD_UNSYNCD) { + if (Demod.state == DEMOD_UNSYNCD) { - if (Demod.highCnt < 2) { // wait for a stable unmodulated signal - if (Demod.twoBits == 0x0000) { - Demod.highCnt++; - } else { - Demod.highCnt = 0; - } - } else { - Demod.syncBit = 0xFFFF; // not set - if ((Demod.twoBits & 0x7700) == 0x7000) Demod.syncBit = 7; - else if ((Demod.twoBits & 0x3B80) == 0x3800) Demod.syncBit = 6; - else if ((Demod.twoBits & 0x1DC0) == 0x1C00) Demod.syncBit = 5; - else if ((Demod.twoBits & 0x0EE0) == 0x0E00) Demod.syncBit = 4; - else if ((Demod.twoBits & 0x0770) == 0x0700) Demod.syncBit = 3; - else if ((Demod.twoBits & 0x03B8) == 0x0380) Demod.syncBit = 2; - else if ((Demod.twoBits & 0x01DC) == 0x01C0) Demod.syncBit = 1; - else if ((Demod.twoBits & 0x00EE) == 0x00E0) Demod.syncBit = 0; - if (Demod.syncBit != 0xFFFF) { - Demod.startTime = non_real_time ? non_real_time : (GetCountSspClk() & 0xfffffff8); - Demod.startTime -= Demod.syncBit; - Demod.bitCount = offset; // number of decoded data bits - Demod.state = DEMOD_MANCHESTER_DATA; - } - } - } else { + if (Demod.highCnt < 2) { // wait for a stable unmodulated signal + if (Demod.twoBits == 0x0000) { + Demod.highCnt++; + } else { + Demod.highCnt = 0; + } + } else { + Demod.syncBit = 0xFFFF; // not set + if ((Demod.twoBits & 0x7700) == 0x7000) Demod.syncBit = 7; + else if ((Demod.twoBits & 0x3B80) == 0x3800) Demod.syncBit = 6; + else if ((Demod.twoBits & 0x1DC0) == 0x1C00) Demod.syncBit = 5; + else if ((Demod.twoBits & 0x0EE0) == 0x0E00) Demod.syncBit = 4; + else if ((Demod.twoBits & 0x0770) == 0x0700) Demod.syncBit = 3; + else if ((Demod.twoBits & 0x03B8) == 0x0380) Demod.syncBit = 2; + else if ((Demod.twoBits & 0x01DC) == 0x01C0) Demod.syncBit = 1; + else if ((Demod.twoBits & 0x00EE) == 0x00E0) Demod.syncBit = 0; + if (Demod.syncBit != 0xFFFF) { + Demod.startTime = non_real_time ? non_real_time : (GetCountSspClk() & 0xfffffff8); + Demod.startTime -= Demod.syncBit; + Demod.bitCount = offset; // number of decoded data bits + Demod.state = DEMOD_MANCHESTER_DATA; + } + } + } else { - if (IsManchesterModulationNibble1(Demod.twoBits >> Demod.syncBit)) { // modulation in first half - if (IsManchesterModulationNibble2(Demod.twoBits >> Demod.syncBit)) { // ... and in second half = collision - if (!Demod.collisionPos) { - Demod.collisionPos = (Demod.len << 3) + Demod.bitCount; - } - } // modulation in first half only - Sequence D = 1 - Demod.bitCount++; - Demod.shiftReg = (Demod.shiftReg >> 1) | 0x100; // in both cases, add a 1 to the shiftreg - if (Demod.bitCount == 9) { // if we decoded a full byte (including parity) - Demod.output[Demod.len++] = (Demod.shiftReg & 0xff); - Demod.parityBits <<= 1; // make room for the parity bit - Demod.parityBits |= ((Demod.shiftReg >> 8) & 0x01); // store parity bit - Demod.bitCount = 0; - Demod.shiftReg = 0; - if ((Demod.len & 0x0007) == 0) { // every 8 data bytes - Demod.parity[Demod.parityLen++] = Demod.parityBits; // store 8 parity bits - Demod.parityBits = 0; - } - } - Demod.endTime = Demod.startTime + 8 * (9 * Demod.len + Demod.bitCount + 1) - 4; - } else { // no modulation in first half - if (IsManchesterModulationNibble2(Demod.twoBits >> Demod.syncBit)) { // and modulation in second half = Sequence E = 0 - Demod.bitCount++; - Demod.shiftReg = (Demod.shiftReg >> 1); // add a 0 to the shiftreg - if (Demod.bitCount >= 9) { // if we decoded a full byte (including parity) - Demod.output[Demod.len++] = (Demod.shiftReg & 0xff); - Demod.parityBits <<= 1; // make room for the new parity bit - Demod.parityBits |= ((Demod.shiftReg >> 8) & 0x01); // store parity bit - Demod.bitCount = 0; - Demod.shiftReg = 0; - if ((Demod.len & 0x0007) == 0) { // every 8 data bytes - Demod.parity[Demod.parityLen++] = Demod.parityBits; // store 8 parity bits1 - Demod.parityBits = 0; - } - } - Demod.endTime = Demod.startTime + 8 * (9 * Demod.len + Demod.bitCount + 1); - } else { // no modulation in both halves - End of communication - if(Demod.bitCount > 0) { // there are some remaining data bits - Demod.shiftReg >>= (9 - Demod.bitCount); // right align the decoded bits - Demod.output[Demod.len++] = Demod.shiftReg & 0xff; // and add them to the output - Demod.parityBits <<= 1; // add a (void) parity bit - Demod.parityBits <<= (8 - (Demod.len&0x0007)); // left align remaining parity bits - Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them - return true; - } else if (Demod.len & 0x0007) { // there are some parity bits to store - Demod.parityBits <<= (8 - (Demod.len&0x0007)); // left align remaining parity bits - Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them - } - if (Demod.len) { - return true; // we are finished with decoding the raw data sequence - } else { // nothing received. Start over - DemodReset(); - } - } - } - } - return false; // not finished yet, need more data + if (IsManchesterModulationNibble1(Demod.twoBits >> Demod.syncBit)) { // modulation in first half + if (IsManchesterModulationNibble2(Demod.twoBits >> Demod.syncBit)) { // ... and in second half = collision + if (!Demod.collisionPos) { + Demod.collisionPos = (Demod.len << 3) + Demod.bitCount; + } + } // modulation in first half only - Sequence D = 1 + Demod.bitCount++; + Demod.shiftReg = (Demod.shiftReg >> 1) | 0x100; // in both cases, add a 1 to the shiftreg + if (Demod.bitCount == 9) { // if we decoded a full byte (including parity) + Demod.output[Demod.len++] = (Demod.shiftReg & 0xff); + Demod.parityBits <<= 1; // make room for the parity bit + Demod.parityBits |= ((Demod.shiftReg >> 8) & 0x01); // store parity bit + Demod.bitCount = 0; + Demod.shiftReg = 0; + if ((Demod.len & 0x0007) == 0) { // every 8 data bytes + Demod.parity[Demod.parityLen++] = Demod.parityBits; // store 8 parity bits + Demod.parityBits = 0; + } + } + Demod.endTime = Demod.startTime + 8 * (9 * Demod.len + Demod.bitCount + 1) - 4; + } else { // no modulation in first half + if (IsManchesterModulationNibble2(Demod.twoBits >> Demod.syncBit)) { // and modulation in second half = Sequence E = 0 + Demod.bitCount++; + Demod.shiftReg = (Demod.shiftReg >> 1); // add a 0 to the shiftreg + if (Demod.bitCount >= 9) { // if we decoded a full byte (including parity) + Demod.output[Demod.len++] = (Demod.shiftReg & 0xff); + Demod.parityBits <<= 1; // make room for the new parity bit + Demod.parityBits |= ((Demod.shiftReg >> 8) & 0x01); // store parity bit + Demod.bitCount = 0; + Demod.shiftReg = 0; + if ((Demod.len & 0x0007) == 0) { // every 8 data bytes + Demod.parity[Demod.parityLen++] = Demod.parityBits; // store 8 parity bits1 + Demod.parityBits = 0; + } + } + Demod.endTime = Demod.startTime + 8 * (9 * Demod.len + Demod.bitCount + 1); + } else { // no modulation in both halves - End of communication + if(Demod.bitCount > 0) { // there are some remaining data bits + Demod.shiftReg >>= (9 - Demod.bitCount); // right align the decoded bits + Demod.output[Demod.len++] = Demod.shiftReg & 0xff; // and add them to the output + Demod.parityBits <<= 1; // add a (void) parity bit + Demod.parityBits <<= (8 - (Demod.len&0x0007)); // left align remaining parity bits + Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them + return true; + } else if (Demod.len & 0x0007) { // there are some parity bits to store + Demod.parityBits <<= (8 - (Demod.len&0x0007)); // left align remaining parity bits + Demod.parity[Demod.parityLen++] = Demod.parityBits; // and store them + } + if (Demod.len) { + return true; // we are finished with decoding the raw data sequence + } else { // nothing received. Start over + DemodReset(); + } + } + } + } + return false; // not finished yet, need more data } //============================================================================= @@ -488,162 +488,162 @@ RAMFUNC int ManchesterDecoding(uint8_t bit, uint16_t offset, uint32_t non_real_t // "hf 14a sniff" //----------------------------------------------------------------------------- void RAMFUNC SniffIso14443a(uint8_t param) { - LEDsoff(); - // param: - // bit 0 - trigger from first card answer - // bit 1 - trigger from first reader 7-bit request - iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); + LEDsoff(); + // param: + // bit 0 - trigger from first card answer + // bit 1 - trigger from first reader 7-bit request + iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); - // Allocate memory from BigBuf for some buffers - // free all previous allocations first - BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); - set_tracing(true); + // Allocate memory from BigBuf for some buffers + // free all previous allocations first + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); - // The command (reader -> tag) that we're receiving. - uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); - uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE); + // The command (reader -> tag) that we're receiving. + uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); + uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE); - // The response (tag -> reader) that we're receiving. - uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE); - uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE); + // The response (tag -> reader) that we're receiving. + uint8_t *receivedResp = BigBuf_malloc(MAX_FRAME_SIZE); + uint8_t *receivedRespPar = BigBuf_malloc(MAX_PARITY_SIZE); - // The DMA buffer, used to stream samples from the FPGA - uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); - uint8_t *data = dmaBuf; + // The DMA buffer, used to stream samples from the FPGA + uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); + uint8_t *data = dmaBuf; - uint8_t previous_data = 0; - int maxDataLen = 0; - int dataLen = 0; - bool TagIsActive = false; - bool ReaderIsActive = false; + uint8_t previous_data = 0; + int maxDataLen = 0; + int dataLen = 0; + bool TagIsActive = false; + bool ReaderIsActive = false; - // Set up the demodulator for tag -> reader responses. - DemodInit(receivedResp, receivedRespPar); + // Set up the demodulator for tag -> reader responses. + DemodInit(receivedResp, receivedRespPar); - // Set up the demodulator for the reader -> tag commands - UartInit(receivedCmd, receivedCmdPar); + // Set up the demodulator for the reader -> tag commands + UartInit(receivedCmd, receivedCmdPar); - // Setup and start DMA. - if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE) ){ - if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); - return; - } + // Setup and start DMA. + if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, DMA_BUFFER_SIZE) ){ + if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); + return; + } - // We won't start recording the frames that we acquire until we trigger; - // a good trigger condition to get started is probably when we see a - // response from the tag. - // triggered == false -- to wait first for card - bool triggered = !(param & 0x03); + // We won't start recording the frames that we acquire until we trigger; + // a good trigger condition to get started is probably when we see a + // response from the tag. + // triggered == false -- to wait first for card + bool triggered = !(param & 0x03); - uint32_t rsamples = 0; + uint32_t rsamples = 0; - DbpString("Starting to sniff"); + DbpString("Starting to sniff"); - // loop and listen - while (!BUTTON_PRESS()) { + // loop and listen + while (!BUTTON_PRESS()) { WDT_HIT(); LED_A_ON(); - int register readBufDataP = data - dmaBuf; - int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; - if (readBufDataP <= dmaBufDataP) - dataLen = dmaBufDataP - readBufDataP; - else - dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; + int register readBufDataP = data - dmaBuf; + int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; + if (readBufDataP <= dmaBufDataP) + dataLen = dmaBufDataP - readBufDataP; + else + dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; - // test for length of buffer - if (dataLen > maxDataLen) { - maxDataLen = dataLen; - if (dataLen > (9 * DMA_BUFFER_SIZE / 10)) { - Dbprintf("[!] blew circular buffer! | datalen %u", dataLen); - break; - } - } - if (dataLen < 1) continue; + // test for length of buffer + if (dataLen > maxDataLen) { + maxDataLen = dataLen; + if (dataLen > (9 * DMA_BUFFER_SIZE / 10)) { + Dbprintf("[!] blew circular buffer! | datalen %u", dataLen); + break; + } + } + if (dataLen < 1) continue; - // primary buffer was stopped( <-- we lost data! - if (!AT91C_BASE_PDC_SSC->PDC_RCR) { - AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE; - Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary - } - // secondary buffer sets as primary, secondary buffer was stopped - if (!AT91C_BASE_PDC_SSC->PDC_RNCR) { - AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; - } + // primary buffer was stopped( <-- we lost data! + if (!AT91C_BASE_PDC_SSC->PDC_RCR) { + AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t) dmaBuf; + AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE; + Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary + } + // secondary buffer sets as primary, secondary buffer was stopped + if (!AT91C_BASE_PDC_SSC->PDC_RNCR) { + AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; + AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; + } - LED_A_OFF(); + LED_A_OFF(); - // Need two samples to feed Miller and Manchester-Decoder - if (rsamples & 0x01) { + // Need two samples to feed Miller and Manchester-Decoder + if (rsamples & 0x01) { - if (!TagIsActive) { // no need to try decoding reader data if the tag is sending - uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4); - if (MillerDecoding(readerdata, (rsamples-1)*4)) { - LED_C_ON(); + if (!TagIsActive) { // no need to try decoding reader data if the tag is sending + uint8_t readerdata = (previous_data & 0xF0) | (*data >> 4); + if (MillerDecoding(readerdata, (rsamples-1)*4)) { + LED_C_ON(); - // check - if there is a short 7bit request from reader - if ((!triggered) && (param & 0x02) && (Uart.len == 1) && (Uart.bitCount == 7)) triggered = true; + // check - if there is a short 7bit request from reader + if ((!triggered) && (param & 0x02) && (Uart.len == 1) && (Uart.bitCount == 7)) triggered = true; - if (triggered) { - if (!LogTrace(receivedCmd, - Uart.len, - Uart.startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, - Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, - Uart.parity, - true)) break; - } - /* ready to receive another command. */ - UartReset(); - /* reset the demod code, which might have been */ - /* false-triggered by the commands from the reader. */ - DemodReset(); - LED_B_OFF(); - } - ReaderIsActive = (Uart.state != STATE_UNSYNCD); - } + if (triggered) { + if (!LogTrace(receivedCmd, + Uart.len, + Uart.startTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, + Uart.endTime*16 - DELAY_READER_AIR2ARM_AS_SNIFFER, + Uart.parity, + true)) break; + } + /* ready to receive another command. */ + UartReset(); + /* reset the demod code, which might have been */ + /* false-triggered by the commands from the reader. */ + DemodReset(); + LED_B_OFF(); + } + ReaderIsActive = (Uart.state != STATE_UNSYNCD); + } - // no need to try decoding tag data if the reader is sending - and we cannot afford the time - if (!ReaderIsActive) { - uint8_t tagdata = (previous_data << 4) | (*data & 0x0F); - if (ManchesterDecoding(tagdata, 0, (rsamples-1)*4)) { - LED_B_ON(); + // no need to try decoding tag data if the reader is sending - and we cannot afford the time + if (!ReaderIsActive) { + uint8_t tagdata = (previous_data << 4) | (*data & 0x0F); + if (ManchesterDecoding(tagdata, 0, (rsamples-1)*4)) { + LED_B_ON(); - if (!LogTrace(receivedResp, - Demod.len, - Demod.startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, - Demod.endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, - Demod.parity, - false)) break; + if (!LogTrace(receivedResp, + Demod.len, + Demod.startTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, + Demod.endTime*16 - DELAY_TAG_AIR2ARM_AS_SNIFFER, + Demod.parity, + false)) break; - if ((!triggered) && (param & 0x01)) triggered = true; + if ((!triggered) && (param & 0x01)) triggered = true; - // ready to receive another response. - DemodReset(); - // reset the Miller decoder including its (now outdated) input buffer - UartReset(); - //UartInit(receivedCmd, receivedCmdPar); - LED_C_OFF(); - } - TagIsActive = (Demod.state != DEMOD_UNSYNCD); - } - } + // ready to receive another response. + DemodReset(); + // reset the Miller decoder including its (now outdated) input buffer + UartReset(); + //UartInit(receivedCmd, receivedCmdPar); + LED_C_OFF(); + } + TagIsActive = (Demod.state != DEMOD_UNSYNCD); + } + } - previous_data = *data; - rsamples++; - data++; - if (data == dmaBuf + DMA_BUFFER_SIZE) { - data = dmaBuf; - } - } // end main loop + previous_data = *data; + rsamples++; + data++; + if (data == dmaBuf + DMA_BUFFER_SIZE) { + data = dmaBuf; + } + } // end main loop - if (MF_DBGLEVEL >= 1) { - Dbprintf("maxDataLen=%d, Uart.state=%x, Uart.len=%d", maxDataLen, Uart.state, Uart.len); - Dbprintf("traceLen=%d, Uart.output[0]=%08x", BigBuf_get_traceLen(), (uint32_t)Uart.output[0]); - } - switch_off(); + if (MF_DBGLEVEL >= 1) { + Dbprintf("maxDataLen=%d, Uart.state=%x, Uart.len=%d", maxDataLen, Uart.state, Uart.len); + Dbprintf("traceLen=%d, Uart.output[0]=%08x", BigBuf_get_traceLen(), (uint32_t)Uart.output[0]); + } + switch_off(); } //----------------------------------------------------------------------------- @@ -651,107 +651,107 @@ void RAMFUNC SniffIso14443a(uint8_t param) { //----------------------------------------------------------------------------- static void CodeIso14443aAsTagPar(const uint8_t *cmd, uint16_t len, uint8_t *parity, bool collision) { - //uint8_t localCol = 0; - ToSendReset(); + //uint8_t localCol = 0; + ToSendReset(); - // Correction bit, might be removed when not needed - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(1); // <----- - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); + // Correction bit, might be removed when not needed + ToSendStuffBit(0); + ToSendStuffBit(0); + ToSendStuffBit(0); + ToSendStuffBit(0); + ToSendStuffBit(1); // <----- + ToSendStuffBit(0); + ToSendStuffBit(0); + ToSendStuffBit(0); - // Send startbit - ToSend[++ToSendMax] = SEC_D; - LastProxToAirDuration = 8 * ToSendMax - 4; + // Send startbit + ToSend[++ToSendMax] = SEC_D; + LastProxToAirDuration = 8 * ToSendMax - 4; - for(uint16_t i = 0; i < len; i++) { - uint8_t b = cmd[i]; + for(uint16_t i = 0; i < len; i++) { + uint8_t b = cmd[i]; - // Data bits - for(uint16_t j = 0; j < 8; j++) { - //if (collision && (localCol >= colpos)){ - if (collision) { - ToSend[++ToSendMax] = SEC_COLL; - //localCol++; + // Data bits + for(uint16_t j = 0; j < 8; j++) { + //if (collision && (localCol >= colpos)){ + if (collision) { + ToSend[++ToSendMax] = SEC_COLL; + //localCol++; } else { - if (b & 1) { - ToSend[++ToSendMax] = SEC_D; - } else { - ToSend[++ToSendMax] = SEC_E; - } - b >>= 1; - } - } + if (b & 1) { + ToSend[++ToSendMax] = SEC_D; + } else { + ToSend[++ToSendMax] = SEC_E; + } + b >>= 1; + } + } - if (collision) { - ToSend[++ToSendMax] = SEC_COLL; - LastProxToAirDuration = 8 * ToSendMax; - } else { - // Get the parity bit - if (parity[i>>3] & (0x80>>(i&0x0007))) { - ToSend[++ToSendMax] = SEC_D; - LastProxToAirDuration = 8 * ToSendMax - 4; - } else { - ToSend[++ToSendMax] = SEC_E; - LastProxToAirDuration = 8 * ToSendMax; - } - } - } + if (collision) { + ToSend[++ToSendMax] = SEC_COLL; + LastProxToAirDuration = 8 * ToSendMax; + } else { + // Get the parity bit + if (parity[i>>3] & (0x80>>(i&0x0007))) { + ToSend[++ToSendMax] = SEC_D; + LastProxToAirDuration = 8 * ToSendMax - 4; + } else { + ToSend[++ToSendMax] = SEC_E; + LastProxToAirDuration = 8 * ToSendMax; + } + } + } - // Send stopbit - ToSend[++ToSendMax] = SEC_F; + // Send stopbit + ToSend[++ToSendMax] = SEC_F; - // Convert from last byte pos to length - ToSendMax++; + // Convert from last byte pos to length + ToSendMax++; } static void CodeIso14443aAsTagEx(const uint8_t *cmd, uint16_t len, bool collision) { - uint8_t par[MAX_PARITY_SIZE] = {0}; - GetParity(cmd, len, par); - CodeIso14443aAsTagPar(cmd, len, par, collision); + uint8_t par[MAX_PARITY_SIZE] = {0}; + GetParity(cmd, len, par); + CodeIso14443aAsTagPar(cmd, len, par, collision); } static void CodeIso14443aAsTag(const uint8_t *cmd, uint16_t len) { - CodeIso14443aAsTagEx(cmd, len, false); + CodeIso14443aAsTagEx(cmd, len, false); } static void Code4bitAnswerAsTag(uint8_t cmd) { - uint8_t b = cmd; + uint8_t b = cmd; - ToSendReset(); + ToSendReset(); - // Correction bit, might be removed when not needed - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(1); // 1 - ToSendStuffBit(0); - ToSendStuffBit(0); - ToSendStuffBit(0); + // Correction bit, might be removed when not needed + ToSendStuffBit(0); + ToSendStuffBit(0); + ToSendStuffBit(0); + ToSendStuffBit(0); + ToSendStuffBit(1); // 1 + ToSendStuffBit(0); + ToSendStuffBit(0); + ToSendStuffBit(0); - // Send startbit - ToSend[++ToSendMax] = SEC_D; + // Send startbit + ToSend[++ToSendMax] = SEC_D; - for(uint8_t i = 0; i < 4; i++) { - if(b & 1) { - ToSend[++ToSendMax] = SEC_D; - LastProxToAirDuration = 8 * ToSendMax - 4; - } else { - ToSend[++ToSendMax] = SEC_E; - LastProxToAirDuration = 8 * ToSendMax; - } - b >>= 1; - } + for(uint8_t i = 0; i < 4; i++) { + if(b & 1) { + ToSend[++ToSendMax] = SEC_D; + LastProxToAirDuration = 8 * ToSendMax - 4; + } else { + ToSend[++ToSendMax] = SEC_E; + LastProxToAirDuration = 8 * ToSendMax; + } + b >>= 1; + } - // Send stopbit - ToSend[++ToSendMax] = SEC_F; + // Send stopbit + ToSend[++ToSendMax] = SEC_F; - // Convert from last byte pos to length - ToSendMax++; + // Convert from last byte pos to length + ToSendMax++; } //----------------------------------------------------------------------------- @@ -767,9 +767,9 @@ int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len) FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); // Now run a `software UART` on the stream of incoming samples. - UartInit(received, parity); + UartInit(received, parity); - // clear RXRDY: + // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; while (!BUTTON_PRESS()) { @@ -777,43 +777,43 @@ int GetIso14443aCommandFromReader(uint8_t *received, uint8_t *parity, int *len) if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - if (MillerDecoding(b, 0)) { - *len = Uart.len; - return true; - } - } + if (MillerDecoding(b, 0)) { + *len = Uart.len; + return true; + } + } } - return false; + return false; } bool prepare_tag_modulation(tag_response_info_t* response_info, size_t max_buffer_size) { - // Example response, answer to MIFARE Classic read block will be 16 bytes + 2 CRC = 18 bytes - // This will need the following byte array for a modulation sequence - // 144 data bits (18 * 8) - // 18 parity bits - // 2 Start and stop - // 1 Correction bit (Answer in 1172 or 1236 periods, see FPGA) - // 1 just for the case - // ----------- + - // 166 bytes, since every bit that needs to be send costs us a byte - // - // Prepare the tag modulation bits from the message - CodeIso14443aAsTag(response_info->response,response_info->response_n); + // Example response, answer to MIFARE Classic read block will be 16 bytes + 2 CRC = 18 bytes + // This will need the following byte array for a modulation sequence + // 144 data bits (18 * 8) + // 18 parity bits + // 2 Start and stop + // 1 Correction bit (Answer in 1172 or 1236 periods, see FPGA) + // 1 just for the case + // ----------- + + // 166 bytes, since every bit that needs to be send costs us a byte + // + // Prepare the tag modulation bits from the message + CodeIso14443aAsTag(response_info->response,response_info->response_n); - // Make sure we do not exceed the free buffer space - if (ToSendMax > max_buffer_size) { - Dbprintf("Out of memory, when modulating bits for tag answer:"); - Dbhexdump(response_info->response_n, response_info->response, false); - return false; - } + // Make sure we do not exceed the free buffer space + if (ToSendMax > max_buffer_size) { + Dbprintf("Out of memory, when modulating bits for tag answer:"); + Dbhexdump(response_info->response_n, response_info->response, false); + return false; + } - // Copy the byte array, used for this modulation to the buffer position - memcpy(response_info->modulation, ToSend, ToSendMax); + // Copy the byte array, used for this modulation to the buffer position + memcpy(response_info->modulation, ToSend, ToSendMax); - // Store the number of bytes that were used for encoding/modulation and the time needed to transfer them - response_info->modulation_n = ToSendMax; - response_info->ProxToAirDuration = LastProxToAirDuration; - return true; + // Store the number of bytes that were used for encoding/modulation and the time needed to transfer them + response_info->modulation_n = ToSendMax; + response_info->ProxToAirDuration = LastProxToAirDuration; + return true; } // "precompile" responses. There are 7 predefined responses with a total of 28 bytes data to transmit. @@ -825,20 +825,20 @@ bool prepare_tag_modulation(tag_response_info_t* response_info, size_t max_buffe #define ALLOCATED_TAG_MODULATION_BUFFER_SIZE 453 bool prepare_allocated_tag_modulation(tag_response_info_t* response_info) { - // Retrieve and store the current buffer index - response_info->modulation = free_buffer_pointer; + // Retrieve and store the current buffer index + response_info->modulation = free_buffer_pointer; - // Determine the maximum size we can use from our buffer - size_t max_buffer_size = ALLOCATED_TAG_MODULATION_BUFFER_SIZE; + // Determine the maximum size we can use from our buffer + size_t max_buffer_size = ALLOCATED_TAG_MODULATION_BUFFER_SIZE; - // Forward the prepare tag modulation function to the inner function - if (prepare_tag_modulation(response_info, max_buffer_size)) { - // Update the free buffer offset - free_buffer_pointer += ToSendMax; - return true; - } else { - return false; - } + // Forward the prepare tag modulation function to the inner function + if (prepare_tag_modulation(response_info, max_buffer_size)) { + // Update the free buffer offset + free_buffer_pointer += ToSendMax; + return true; + } else { + return false; + } } //----------------------------------------------------------------------------- @@ -848,699 +848,699 @@ bool prepare_allocated_tag_modulation(tag_response_info_t* response_info) { //----------------------------------------------------------------------------- void SimulateIso14443aTag(int tagType, int flags, uint8_t* data) { - #define ATTACK_KEY_COUNT 8 // keep same as define in cmdhfmf.c -> readerAttack() + #define ATTACK_KEY_COUNT 8 // keep same as define in cmdhfmf.c -> readerAttack() - uint8_t sak = 0; - uint32_t cuid = 0; - uint32_t nonce = 0; + uint8_t sak = 0; + uint32_t cuid = 0; + uint32_t nonce = 0; - // PACK response to PWD AUTH for EV1/NTAG - uint8_t response8[4] = {0,0,0,0}; - // Counter for EV1/NTAG - uint32_t counters[] = {0,0,0}; + // PACK response to PWD AUTH for EV1/NTAG + uint8_t response8[4] = {0,0,0,0}; + // Counter for EV1/NTAG + uint32_t counters[] = {0,0,0}; - // The first response contains the ATQA (note: bytes are transmitted in reverse order). - uint8_t response1[] = {0,0}; + // The first response contains the ATQA (note: bytes are transmitted in reverse order). + uint8_t response1[] = {0,0}; - // Here, we collect CUID, block1, keytype1, NT1, NR1, AR1, CUID, block2, keytyp2, NT2, NR2, AR2 - // it should also collect block, keytype. - uint8_t cardAUTHSC = 0; - uint8_t cardAUTHKEY = 0xff; // no authentication - // allow collecting up to 8 sets of nonces to allow recovery of up to 8 keys + // Here, we collect CUID, block1, keytype1, NT1, NR1, AR1, CUID, block2, keytyp2, NT2, NR2, AR2 + // it should also collect block, keytype. + uint8_t cardAUTHSC = 0; + uint8_t cardAUTHKEY = 0xff; // no authentication + // allow collecting up to 8 sets of nonces to allow recovery of up to 8 keys - nonces_t ar_nr_nonces[ATTACK_KEY_COUNT]; // for attack types moebius - memset(ar_nr_nonces, 0x00, sizeof(ar_nr_nonces)); - uint8_t moebius_count = 0; + nonces_t ar_nr_nonces[ATTACK_KEY_COUNT]; // for attack types moebius + memset(ar_nr_nonces, 0x00, sizeof(ar_nr_nonces)); + uint8_t moebius_count = 0; - switch (tagType) { - case 1: { // MIFARE Classic 1k - response1[0] = 0x04; - sak = 0x08; - } break; - case 2: { // MIFARE Ultralight - response1[0] = 0x44; - sak = 0x00; - } break; - case 3: { // MIFARE DESFire - response1[0] = 0x04; - response1[1] = 0x03; - sak = 0x20; - } break; - case 4: { // ISO/IEC 14443-4 - javacard (JCOP) - response1[0] = 0x04; - sak = 0x28; - } break; - case 5: { // MIFARE TNP3XXX - response1[0] = 0x01; - response1[1] = 0x0f; - sak = 0x01; - } break; - case 6: { // MIFARE Mini 320b - response1[0] = 0x44; - sak = 0x09; - } break; - case 7: { // NTAG - response1[0] = 0x44; - sak = 0x00; - // PACK - response8[0] = 0x80; - response8[1] = 0x80; - compute_crc(CRC_14443_A, response8, 2, &response8[2], &response8[3]); - // uid not supplied then get from emulator memory - if (data[0]==0) { - uint16_t start = 4 * (0+12); - uint8_t emdata[8]; - emlGetMemBt( emdata, start, sizeof(emdata)); - memcpy(data, emdata, 3); // uid bytes 0-2 - memcpy(data+3, emdata+4, 4); // uid bytes 3-7 - flags |= FLAG_7B_UID_IN_DATA; - } - } break; - case 8: { // MIFARE Classic 4k - response1[0] = 0x02; - sak = 0x18; - } break; - case 9 : { // FM11RF005SH (Shanghai Metro) - response1[0] = 0x03; - response1[1] = 0x00; - sak = 0x0A; - } - default: { - Dbprintf("Error: unkown tagtype (%d)",tagType); - return; - } break; - } + switch (tagType) { + case 1: { // MIFARE Classic 1k + response1[0] = 0x04; + sak = 0x08; + } break; + case 2: { // MIFARE Ultralight + response1[0] = 0x44; + sak = 0x00; + } break; + case 3: { // MIFARE DESFire + response1[0] = 0x04; + response1[1] = 0x03; + sak = 0x20; + } break; + case 4: { // ISO/IEC 14443-4 - javacard (JCOP) + response1[0] = 0x04; + sak = 0x28; + } break; + case 5: { // MIFARE TNP3XXX + response1[0] = 0x01; + response1[1] = 0x0f; + sak = 0x01; + } break; + case 6: { // MIFARE Mini 320b + response1[0] = 0x44; + sak = 0x09; + } break; + case 7: { // NTAG + response1[0] = 0x44; + sak = 0x00; + // PACK + response8[0] = 0x80; + response8[1] = 0x80; + compute_crc(CRC_14443_A, response8, 2, &response8[2], &response8[3]); + // uid not supplied then get from emulator memory + if (data[0]==0) { + uint16_t start = 4 * (0+12); + uint8_t emdata[8]; + emlGetMemBt( emdata, start, sizeof(emdata)); + memcpy(data, emdata, 3); // uid bytes 0-2 + memcpy(data+3, emdata+4, 4); // uid bytes 3-7 + flags |= FLAG_7B_UID_IN_DATA; + } + } break; + case 8: { // MIFARE Classic 4k + response1[0] = 0x02; + sak = 0x18; + } break; + case 9 : { // FM11RF005SH (Shanghai Metro) + response1[0] = 0x03; + response1[1] = 0x00; + sak = 0x0A; + } + default: { + Dbprintf("Error: unkown tagtype (%d)",tagType); + return; + } break; + } - // The second response contains the (mandatory) first 24 bits of the UID - uint8_t response2[5] = {0x00}; + // The second response contains the (mandatory) first 24 bits of the UID + uint8_t response2[5] = {0x00}; - // For UID size 7, - uint8_t response2a[5] = {0x00}; + // For UID size 7, + uint8_t response2a[5] = {0x00}; - if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA ) { - response2[0] = 0x88; // Cascade Tag marker - response2[1] = data[0]; - response2[2] = data[1]; - response2[3] = data[2]; + if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA ) { + response2[0] = 0x88; // Cascade Tag marker + response2[1] = data[0]; + response2[2] = data[1]; + response2[3] = data[2]; - response2a[0] = data[3]; - response2a[1] = data[4]; - response2a[2] = data[5]; - response2a[3] = data[6]; //?? - response2a[4] = response2a[0] ^ response2a[1] ^ response2a[2] ^ response2a[3]; + response2a[0] = data[3]; + response2a[1] = data[4]; + response2a[2] = data[5]; + response2a[3] = data[6]; //?? + response2a[4] = response2a[0] ^ response2a[1] ^ response2a[2] ^ response2a[3]; - // Configure the ATQA and SAK accordingly - response1[0] |= 0x40; - sak |= 0x04; + // Configure the ATQA and SAK accordingly + response1[0] |= 0x40; + sak |= 0x04; - cuid = bytes_to_num(data+3, 4); - } else { - memcpy(response2, data, 4); - // Configure the ATQA and SAK accordingly - response1[0] &= 0xBF; - sak &= 0xFB; - cuid = bytes_to_num(data, 4); - } + cuid = bytes_to_num(data+3, 4); + } else { + memcpy(response2, data, 4); + // Configure the ATQA and SAK accordingly + response1[0] &= 0xBF; + sak &= 0xFB; + cuid = bytes_to_num(data, 4); + } - // Calculate the BitCountCheck (BCC) for the first 4 bytes of the UID. - response2[4] = response2[0] ^ response2[1] ^ response2[2] ^ response2[3]; + // Calculate the BitCountCheck (BCC) for the first 4 bytes of the UID. + response2[4] = response2[0] ^ response2[1] ^ response2[2] ^ response2[3]; - // Prepare the mandatory SAK (for 4 and 7 byte UID) - uint8_t response3[3] = {sak, 0x00, 0x00}; - compute_crc(CRC_14443_A, response3, 1, &response3[1], &response3[2]); + // Prepare the mandatory SAK (for 4 and 7 byte UID) + uint8_t response3[3] = {sak, 0x00, 0x00}; + compute_crc(CRC_14443_A, response3, 1, &response3[1], &response3[2]); - // Prepare the optional second SAK (for 7 byte UID), drop the cascade bit - uint8_t response3a[3] = {0x00}; - response3a[0] = sak & 0xFB; - compute_crc(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); + // Prepare the optional second SAK (for 7 byte UID), drop the cascade bit + uint8_t response3a[3] = {0x00}; + response3a[0] = sak & 0xFB; + compute_crc(CRC_14443_A, response3a, 1, &response3a[1], &response3a[2]); - // Tag NONCE. - uint8_t response5[4]; + // Tag NONCE. + uint8_t response5[4]; - uint8_t response6[] = { 0x04, 0x58, 0x80, 0x02, 0x00, 0x00 }; // dummy ATS (pseudo-ATR), answer to RATS: + 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 - // TB(1) = not present. Defaults: FWI = 4 (FWT = 256 * 16 * 2^4 * 1/fc = 4833us), SFGI = 0 (SFG = 256 * 16 * 2^0 * 1/fc = 302us) - // TC(1) = 0x02: CID supported, NAD not supported - compute_crc(CRC_14443_A, response6, 4, &response6[4], &response6[5]); + // Format byte = 0x58: FSCI=0x08 (FSC=256), TA(1) and TC(1) present, + // TA(1) = 0x80: different divisors not supported, DR = 1, DS = 1 + // TB(1) = not present. Defaults: FWI = 4 (FWT = 256 * 16 * 2^4 * 1/fc = 4833us), SFGI = 0 (SFG = 256 * 16 * 2^0 * 1/fc = 302us) + // TC(1) = 0x02: CID supported, NAD not supported + compute_crc(CRC_14443_A, response6, 4, &response6[4], &response6[5]); - // Prepare GET_VERSION (different for UL EV-1 / NTAG) - // uint8_t response7_EV1[] = {0x00, 0x04, 0x03, 0x01, 0x01, 0x00, 0x0b, 0x03, 0xfd, 0xf7}; //EV1 48bytes VERSION. - // uint8_t response7_NTAG[] = {0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x11, 0x03, 0x01, 0x9e}; //NTAG 215 - // Prepare CHK_TEARING - // uint8_t response9[] = {0xBD,0x90,0x3f}; + // Prepare GET_VERSION (different for UL EV-1 / NTAG) + // uint8_t response7_EV1[] = {0x00, 0x04, 0x03, 0x01, 0x01, 0x00, 0x0b, 0x03, 0xfd, 0xf7}; //EV1 48bytes VERSION. + // uint8_t response7_NTAG[] = {0x00, 0x04, 0x04, 0x02, 0x01, 0x00, 0x11, 0x03, 0x01, 0x9e}; //NTAG 215 + // Prepare CHK_TEARING + // uint8_t response9[] = {0xBD,0x90,0x3f}; - #define TAG_RESPONSE_COUNT 10 - tag_response_info_t responses[TAG_RESPONSE_COUNT] = { - { .response = response1, .response_n = sizeof(response1) }, // Answer to request - respond with card type - { .response = response2, .response_n = sizeof(response2) }, // Anticollision cascade1 - respond with uid - { .response = response2a, .response_n = sizeof(response2a) }, // Anticollision cascade2 - respond with 2nd half of uid if asked - { .response = response3, .response_n = sizeof(response3) }, // Acknowledge select - cascade 1 - { .response = response3a, .response_n = sizeof(response3a) }, // Acknowledge select - cascade 2 - { .response = response5, .response_n = sizeof(response5) }, // Authentication answer (random nonce) - { .response = response6, .response_n = sizeof(response6) }, // dummy ATS (pseudo-ATR), answer to RATS + #define TAG_RESPONSE_COUNT 10 + tag_response_info_t responses[TAG_RESPONSE_COUNT] = { + { .response = response1, .response_n = sizeof(response1) }, // Answer to request - respond with card type + { .response = response2, .response_n = sizeof(response2) }, // Anticollision cascade1 - respond with uid + { .response = response2a, .response_n = sizeof(response2a) }, // Anticollision cascade2 - respond with 2nd half of uid if asked + { .response = response3, .response_n = sizeof(response3) }, // Acknowledge select - cascade 1 + { .response = response3a, .response_n = sizeof(response3a) }, // Acknowledge select - cascade 2 + { .response = response5, .response_n = sizeof(response5) }, // Authentication answer (random nonce) + { .response = response6, .response_n = sizeof(response6) }, // dummy ATS (pseudo-ATR), answer to RATS - { .response = response8, .response_n = sizeof(response8) } // EV1/NTAG PACK response - }; - // { .response = response7_NTAG, .response_n = sizeof(response7_NTAG)}, // EV1/NTAG GET_VERSION response - // { .response = response9, .response_n = sizeof(response9) } // EV1/NTAG CHK_TEAR response + { .response = response8, .response_n = sizeof(response8) } // EV1/NTAG PACK response + }; + // { .response = response7_NTAG, .response_n = sizeof(response7_NTAG)}, // EV1/NTAG GET_VERSION response + // { .response = response9, .response_n = sizeof(response9) } // EV1/NTAG CHK_TEAR response - // Allocate 512 bytes for the dynamic modulation, created when the reader queries for it - // Such a response is less time critical, so we can prepare them on the fly - #define DYNAMIC_RESPONSE_BUFFER_SIZE 64 - #define DYNAMIC_MODULATION_BUFFER_SIZE 512 - uint8_t dynamic_response_buffer[DYNAMIC_RESPONSE_BUFFER_SIZE]; - uint8_t dynamic_modulation_buffer[DYNAMIC_MODULATION_BUFFER_SIZE]; - tag_response_info_t dynamic_response_info = { - .response = dynamic_response_buffer, - .response_n = 0, - .modulation = dynamic_modulation_buffer, - .modulation_n = 0 - }; + // Allocate 512 bytes for the dynamic modulation, created when the reader queries for it + // Such a response is less time critical, so we can prepare them on the fly + #define DYNAMIC_RESPONSE_BUFFER_SIZE 64 + #define DYNAMIC_MODULATION_BUFFER_SIZE 512 + uint8_t dynamic_response_buffer[DYNAMIC_RESPONSE_BUFFER_SIZE]; + uint8_t dynamic_modulation_buffer[DYNAMIC_MODULATION_BUFFER_SIZE]; + tag_response_info_t dynamic_response_info = { + .response = dynamic_response_buffer, + .response_n = 0, + .modulation = dynamic_modulation_buffer, + .modulation_n = 0 + }; - // We need to listen to the high-frequency, peak-detected path. - iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); + // We need to listen to the high-frequency, peak-detected path. + iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); - BigBuf_free_keep_EM(); - clear_trace(); - set_tracing(true); + BigBuf_free_keep_EM(); + clear_trace(); + set_tracing(true); - // allocate buffers: - uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); - uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE); - free_buffer_pointer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE); + // allocate buffers: + uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); + uint8_t *receivedCmdPar = BigBuf_malloc(MAX_PARITY_SIZE); + free_buffer_pointer = BigBuf_malloc(ALLOCATED_TAG_MODULATION_BUFFER_SIZE); - // Prepare the responses of the anticollision phase - // there will be not enough time to do this at the moment the reader sends it REQA - for (size_t i=0; i 2) { - // send NACK 0x0 == invalid argument - uint8_t nack[] = {0x00}; - EmSendCmd(nack,sizeof(nack)); - } else { - uint8_t cmd[] = {0x00,0x00,0x00,0x14,0xa5}; - num_to_bytes(counters[index], 3, cmd); - AddCrc14A(cmd, sizeof(cmd)-2); - EmSendCmd(cmd,sizeof(cmd)); - } - p_response = NULL; - } else if (receivedCmd[0] == MIFARE_ULEV1_INCR_CNT && tagType == 7) { // Received a INC COUNTER -- - uint8_t index = receivedCmd[1]; - if ( index > 2) { - // send NACK 0x0 == invalid argument - uint8_t nack[] = {0x00}; - EmSendCmd(nack,sizeof(nack)); - } else { + // Okay, look at the command now. + lastorder = order; + if (receivedCmd[0] == ISO14443A_CMD_REQA) { // Received a REQUEST + p_response = &responses[0]; order = 1; + } else if (receivedCmd[0] == ISO14443A_CMD_WUPA) { // Received a WAKEUP + p_response = &responses[0]; order = 6; + } else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received request for UID (cascade 1) + p_response = &responses[1]; order = 2; + } else if (receivedCmd[1] == 0x20 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received request for UID (cascade 2) + p_response = &responses[2]; order = 20; + } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received a SELECT (cascade 1) + p_response = &responses[3]; order = 3; + } else if (receivedCmd[1] == 0x70 && receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received a SELECT (cascade 2) + p_response = &responses[4]; order = 30; + } else if (receivedCmd[0] == ISO14443A_CMD_READBLOCK) { // Received a (plain) READ + uint8_t block = receivedCmd[1]; + // if Ultralight or NTAG (4 byte blocks) + if ( tagType == 7 || tagType == 2 ) { + // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] + uint16_t start = 4 * (block+12); + uint8_t emdata[MAX_MIFARE_FRAME_SIZE]; + emlGetMemBt( emdata, start, 16); + AddCrc14A(emdata, 16); + EmSendCmd(emdata, sizeof(emdata)); + // We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below + p_response = NULL; + } else if ( tagType == 9 && block == 1 ) { + // FM11005SH. 16blocks, 4bytes / block. + // block0 = 2byte Customer ID (CID), 2byte Manufacture ID (MID) + // block1 = 4byte UID. + p_response = &responses[1]; + } else { // all other tags (16 byte block tags) + uint8_t emdata[MAX_MIFARE_FRAME_SIZE]; + emlGetMemBt( emdata, block, 16); + AddCrc14A(emdata, 16); + EmSendCmd(emdata, sizeof(emdata)); + // EmSendCmd(data+(4*receivedCmd[1]),16); + // Dbprintf("Read request from reader: %x %x",receivedCmd[0],receivedCmd[1]); + // We already responded, do not send anything with the EmSendCmd14443aRaw() that is called below + p_response = NULL; + } + } else if (receivedCmd[0] == MIFARE_ULEV1_FASTREAD) { // Received a FAST READ (ranged read) + uint8_t emdata[MAX_FRAME_SIZE]; + // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] + int start = (receivedCmd[1]+12) * 4; + int len = (receivedCmd[2] - receivedCmd[1] + 1) * 4; + emlGetMemBt( emdata, start, len); + AddCrc14A(emdata, len); + EmSendCmd(emdata, len+2); + p_response = NULL; + } else if (receivedCmd[0] == MIFARE_ULEV1_READSIG && tagType == 7) { // Received a READ SIGNATURE -- + // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] + uint16_t start = 4 * 4; + uint8_t emdata[34]; + emlGetMemBt( emdata, start, 32); + AddCrc14A(emdata, 32); + EmSendCmd(emdata, sizeof(emdata)); + p_response = NULL; + } else if (receivedCmd[0] == MIFARE_ULEV1_READ_CNT && tagType == 7) { // Received a READ COUNTER -- + uint8_t index = receivedCmd[1]; + if (index > 2) { + // send NACK 0x0 == invalid argument + uint8_t nack[] = {0x00}; + EmSendCmd(nack,sizeof(nack)); + } else { + uint8_t cmd[] = {0x00,0x00,0x00,0x14,0xa5}; + num_to_bytes(counters[index], 3, cmd); + AddCrc14A(cmd, sizeof(cmd)-2); + EmSendCmd(cmd,sizeof(cmd)); + } + p_response = NULL; + } else if (receivedCmd[0] == MIFARE_ULEV1_INCR_CNT && tagType == 7) { // Received a INC COUNTER -- + uint8_t index = receivedCmd[1]; + if ( index > 2) { + // send NACK 0x0 == invalid argument + uint8_t nack[] = {0x00}; + EmSendCmd(nack,sizeof(nack)); + } else { - uint32_t val = bytes_to_num(receivedCmd+2,4); + uint32_t val = bytes_to_num(receivedCmd+2,4); - // if new value + old value is bigger 24bits, fail - if ( val + counters[index] > 0xFFFFFF ) { - // send NACK 0x4 == counter overflow - uint8_t nack[] = {0x04}; - EmSendCmd(nack,sizeof(nack)); - } else { - counters[index] = val; - // send ACK - uint8_t ack[] = {0x0a}; - EmSendCmd(ack,sizeof(ack)); - } - } - p_response = NULL; - } else if (receivedCmd[0] == MIFARE_ULEV1_CHECKTEAR && tagType == 7) { // Received a CHECK_TEARING_EVENT -- - // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] - uint8_t emdata[3]; - uint8_t index = receivedCmd[1]; - if ( index > 2) { - // send NACK 0x0 == invalid argument - uint8_t nack[] = {0x00}; - EmSendCmd(nack,sizeof(nack)); - } else { - emlGetMemBt( emdata, 10+index, 1); - AddCrc14A(emdata, sizeof(emdata)-2); - EmSendCmd(emdata, sizeof(emdata)); - } - p_response = NULL; - } else if (receivedCmd[0] == ISO14443A_CMD_HALT) { // Received a HALT - LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - p_response = NULL; - } else if (receivedCmd[0] == MIFARE_AUTH_KEYA || receivedCmd[0] == MIFARE_AUTH_KEYB) { // Received an authentication request - if ( tagType == 7 ) { // IF NTAG /EV1 0x60 == GET_VERSION, not a authentication request. - uint8_t emdata[10]; - emlGetMemBt( emdata, 0, 8 ); - AddCrc14A(emdata, sizeof(emdata)-2); - EmSendCmd(emdata, sizeof(emdata)); - p_response = NULL; - } else { + // if new value + old value is bigger 24bits, fail + if ( val + counters[index] > 0xFFFFFF ) { + // send NACK 0x4 == counter overflow + uint8_t nack[] = {0x04}; + EmSendCmd(nack,sizeof(nack)); + } else { + counters[index] = val; + // send ACK + uint8_t ack[] = {0x0a}; + EmSendCmd(ack,sizeof(ack)); + } + } + p_response = NULL; + } else if (receivedCmd[0] == MIFARE_ULEV1_CHECKTEAR && tagType == 7) { // Received a CHECK_TEARING_EVENT -- + // first 12 blocks of emu are [getversion answer - check tearing - pack - 0x00 - signature] + uint8_t emdata[3]; + uint8_t index = receivedCmd[1]; + if ( index > 2) { + // send NACK 0x0 == invalid argument + uint8_t nack[] = {0x00}; + EmSendCmd(nack,sizeof(nack)); + } else { + emlGetMemBt( emdata, 10+index, 1); + AddCrc14A(emdata, sizeof(emdata)-2); + EmSendCmd(emdata, sizeof(emdata)); + } + p_response = NULL; + } else if (receivedCmd[0] == ISO14443A_CMD_HALT) { // Received a HALT + LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + p_response = NULL; + } else if (receivedCmd[0] == MIFARE_AUTH_KEYA || receivedCmd[0] == MIFARE_AUTH_KEYB) { // Received an authentication request + if ( tagType == 7 ) { // IF NTAG /EV1 0x60 == GET_VERSION, not a authentication request. + uint8_t emdata[10]; + emlGetMemBt( emdata, 0, 8 ); + AddCrc14A(emdata, sizeof(emdata)-2); + EmSendCmd(emdata, sizeof(emdata)); + p_response = NULL; + } else { - cardAUTHKEY = receivedCmd[0] - 0x60; - cardAUTHSC = receivedCmd[1] / 4; // received block num + cardAUTHKEY = receivedCmd[0] - 0x60; + cardAUTHSC = receivedCmd[1] / 4; // received block num - // incease nonce at AUTH requests. this is time consuming. - nonce = prng_successor( GetTickCount(), 32 ); - //num_to_bytes(nonce, 4, response5); - num_to_bytes(nonce, 4, dynamic_response_info.response); - dynamic_response_info.response_n = 4; + // incease nonce at AUTH requests. this is time consuming. + nonce = prng_successor( GetTickCount(), 32 ); + //num_to_bytes(nonce, 4, response5); + num_to_bytes(nonce, 4, dynamic_response_info.response); + dynamic_response_info.response_n = 4; - //prepare_tag_modulation(&responses[5], DYNAMIC_MODULATION_BUFFER_SIZE); - prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE); - p_response = &dynamic_response_info; - //p_response = &responses[5]; - order = 7; - } - } else if (receivedCmd[0] == ISO14443A_CMD_RATS) { // Received a RATS request - if (tagType == 1 || tagType == 2) { // RATS not supported - EmSend4bit(CARD_NACK_NA); - p_response = NULL; - } else { - p_response = &responses[6]; order = 70; - } - } else if (order == 7 && len == 8) { // Received {nr] and {ar} (part of authentication) - LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - uint32_t nr = bytes_to_num(receivedCmd,4); - uint32_t ar = bytes_to_num(receivedCmd+4,4); + //prepare_tag_modulation(&responses[5], DYNAMIC_MODULATION_BUFFER_SIZE); + prepare_tag_modulation(&dynamic_response_info, DYNAMIC_MODULATION_BUFFER_SIZE); + p_response = &dynamic_response_info; + //p_response = &responses[5]; + order = 7; + } + } else if (receivedCmd[0] == ISO14443A_CMD_RATS) { // Received a RATS request + if (tagType == 1 || tagType == 2) { // RATS not supported + EmSend4bit(CARD_NACK_NA); + p_response = NULL; + } else { + p_response = &responses[6]; order = 70; + } + } else if (order == 7 && len == 8) { // Received {nr] and {ar} (part of authentication) + LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + uint32_t nr = bytes_to_num(receivedCmd,4); + uint32_t ar = bytes_to_num(receivedCmd+4,4); - // Collect AR/NR per keytype & sector - if ( (flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK ) { + // Collect AR/NR per keytype & sector + if ( (flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK ) { - int8_t index = -1; - int8_t empty = -1; - for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { - // find which index to use - if ( (cardAUTHSC == ar_nr_nonces[i].sector) && (cardAUTHKEY == ar_nr_nonces[i].keytype)) - index = i; + int8_t index = -1; + int8_t empty = -1; + for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { + // find which index to use + if ( (cardAUTHSC == ar_nr_nonces[i].sector) && (cardAUTHKEY == ar_nr_nonces[i].keytype)) + index = i; - // keep track of empty slots. - if ( ar_nr_nonces[i].state == EMPTY) - empty = i; - } - // if no empty slots. Choose first and overwrite. - if ( index == -1 ) { - if ( empty == -1 ) { - index = 0; - ar_nr_nonces[index].state = EMPTY; - } else { - index = empty; - } - } + // keep track of empty slots. + if ( ar_nr_nonces[i].state == EMPTY) + empty = i; + } + // if no empty slots. Choose first and overwrite. + if ( index == -1 ) { + if ( empty == -1 ) { + index = 0; + ar_nr_nonces[index].state = EMPTY; + } else { + index = empty; + } + } - switch(ar_nr_nonces[index].state) { - case EMPTY: { - // first nonce collect - ar_nr_nonces[index].cuid = cuid; - ar_nr_nonces[index].sector = cardAUTHSC; - ar_nr_nonces[index].keytype = cardAUTHKEY; - ar_nr_nonces[index].nonce = nonce; - ar_nr_nonces[index].nr = nr; - ar_nr_nonces[index].ar = ar; - ar_nr_nonces[index].state = FIRST; - break; - } - case FIRST : { - // second nonce collect - ar_nr_nonces[index].nonce2 = nonce; - ar_nr_nonces[index].nr2 = nr; - ar_nr_nonces[index].ar2 = ar; - ar_nr_nonces[index].state = SECOND; + switch(ar_nr_nonces[index].state) { + case EMPTY: { + // first nonce collect + ar_nr_nonces[index].cuid = cuid; + ar_nr_nonces[index].sector = cardAUTHSC; + ar_nr_nonces[index].keytype = cardAUTHKEY; + ar_nr_nonces[index].nonce = nonce; + ar_nr_nonces[index].nr = nr; + ar_nr_nonces[index].ar = ar; + ar_nr_nonces[index].state = FIRST; + break; + } + case FIRST : { + // second nonce collect + ar_nr_nonces[index].nonce2 = nonce; + ar_nr_nonces[index].nr2 = nr; + ar_nr_nonces[index].ar2 = ar; + ar_nr_nonces[index].state = SECOND; - // send to client - cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, 0, 0, &ar_nr_nonces[index], sizeof(nonces_t)); + // send to client + cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, 0, 0, &ar_nr_nonces[index], sizeof(nonces_t)); - ar_nr_nonces[index].state = EMPTY; - ar_nr_nonces[index].sector = 0; - ar_nr_nonces[index].keytype = 0; + ar_nr_nonces[index].state = EMPTY; + ar_nr_nonces[index].sector = 0; + ar_nr_nonces[index].keytype = 0; - moebius_count++; - break; - } - default: break; - } - } - p_response = NULL; + moebius_count++; + break; + } + default: break; + } + } + p_response = NULL; - } else if (receivedCmd[0] == MIFARE_ULC_AUTH_1 ) { // ULC authentication, or Desfire Authentication - } else if (receivedCmd[0] == MIFARE_ULEV1_AUTH) { // NTAG / EV-1 authentication - if ( tagType == 7 ) { - uint16_t start = 13; // first 4 blocks of emu are [getversion answer - check tearing - pack - 0x00] - uint8_t emdata[4]; - emlGetMemBt( emdata, start, 2); - AddCrc14A(emdata, 2); - EmSendCmd(emdata, sizeof(emdata)); - p_response = NULL; - uint32_t pwd = bytes_to_num(receivedCmd+1,4); + } else if (receivedCmd[0] == MIFARE_ULC_AUTH_1 ) { // ULC authentication, or Desfire Authentication + } else if (receivedCmd[0] == MIFARE_ULEV1_AUTH) { // NTAG / EV-1 authentication + if ( tagType == 7 ) { + uint16_t start = 13; // first 4 blocks of emu are [getversion answer - check tearing - pack - 0x00] + uint8_t emdata[4]; + emlGetMemBt( emdata, start, 2); + AddCrc14A(emdata, 2); + EmSendCmd(emdata, sizeof(emdata)); + p_response = NULL; + uint32_t pwd = bytes_to_num(receivedCmd+1,4); - if ( MF_DBGLEVEL >= 3) Dbprintf("Auth attempt: %08x", pwd); - } - } else { - // Check for ISO 14443A-4 compliant commands, look at left nibble - switch (receivedCmd[0]) { - case 0x02: - case 0x03: { // IBlock (command no CID) - dynamic_response_info.response[0] = receivedCmd[0]; - dynamic_response_info.response[1] = 0x90; - dynamic_response_info.response[2] = 0x00; - dynamic_response_info.response_n = 3; - } break; - case 0x0B: - case 0x0A: { // IBlock (command CID) - dynamic_response_info.response[0] = receivedCmd[0]; - dynamic_response_info.response[1] = 0x00; - dynamic_response_info.response[2] = 0x90; - dynamic_response_info.response[3] = 0x00; - dynamic_response_info.response_n = 4; - } break; + if ( MF_DBGLEVEL >= 3) Dbprintf("Auth attempt: %08x", pwd); + } + } else { + // Check for ISO 14443A-4 compliant commands, look at left nibble + switch (receivedCmd[0]) { + case 0x02: + case 0x03: { // IBlock (command no CID) + dynamic_response_info.response[0] = receivedCmd[0]; + dynamic_response_info.response[1] = 0x90; + dynamic_response_info.response[2] = 0x00; + dynamic_response_info.response_n = 3; + } break; + case 0x0B: + case 0x0A: { // IBlock (command CID) + dynamic_response_info.response[0] = receivedCmd[0]; + dynamic_response_info.response[1] = 0x00; + dynamic_response_info.response[2] = 0x90; + dynamic_response_info.response[3] = 0x00; + dynamic_response_info.response_n = 4; + } break; - case 0x1A: - case 0x1B: { // Chaining command - dynamic_response_info.response[0] = 0xaa | ((receivedCmd[0]) & 1); - dynamic_response_info.response_n = 2; - } break; + case 0x1A: + case 0x1B: { // Chaining command + dynamic_response_info.response[0] = 0xaa | ((receivedCmd[0]) & 1); + dynamic_response_info.response_n = 2; + } break; - case 0xAA: - case 0xBB: { - dynamic_response_info.response[0] = receivedCmd[0] ^ 0x11; - dynamic_response_info.response_n = 2; - } break; + case 0xAA: + case 0xBB: { + dynamic_response_info.response[0] = receivedCmd[0] ^ 0x11; + dynamic_response_info.response_n = 2; + } break; - case 0xBA: { // ping / pong - dynamic_response_info.response[0] = 0xAB; - dynamic_response_info.response[1] = 0x00; - dynamic_response_info.response_n = 2; - } break; + case 0xBA: { // ping / pong + dynamic_response_info.response[0] = 0xAB; + dynamic_response_info.response[1] = 0x00; + dynamic_response_info.response_n = 2; + } break; - case 0xCA: - case 0xC2: { // Readers sends deselect command - dynamic_response_info.response[0] = 0xCA; - dynamic_response_info.response[1] = 0x00; - dynamic_response_info.response_n = 2; - } break; + case 0xCA: + case 0xC2: { // Readers sends deselect command + dynamic_response_info.response[0] = 0xCA; + dynamic_response_info.response[1] = 0x00; + dynamic_response_info.response_n = 2; + } break; - default: { - // Never seen this command before - LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - Dbprintf("Received unknown command (len=%d):",len); - Dbhexdump(len,receivedCmd,false); - // Do not respond - dynamic_response_info.response_n = 0; - } break; - } + default: { + // Never seen this command before + LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + Dbprintf("Received unknown command (len=%d):",len); + Dbhexdump(len,receivedCmd,false); + // Do not respond + dynamic_response_info.response_n = 0; + } break; + } - if (dynamic_response_info.response_n > 0) { - // Copy the CID from the reader query - dynamic_response_info.response[1] = receivedCmd[1]; + if (dynamic_response_info.response_n > 0) { + // Copy the CID from the reader query + dynamic_response_info.response[1] = receivedCmd[1]; - // Add CRC bytes, always used in ISO 14443A-4 compliant cards - AddCrc14A(dynamic_response_info.response, dynamic_response_info.response_n); - dynamic_response_info.response_n += 2; + // Add CRC bytes, always used in ISO 14443A-4 compliant cards + AddCrc14A(dynamic_response_info.response, dynamic_response_info.response_n); + dynamic_response_info.response_n += 2; - if (prepare_tag_modulation(&dynamic_response_info,DYNAMIC_MODULATION_BUFFER_SIZE) == false) { - DbpString("Error preparing tag response"); - LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } - p_response = &dynamic_response_info; - } - } + if (prepare_tag_modulation(&dynamic_response_info,DYNAMIC_MODULATION_BUFFER_SIZE) == false) { + DbpString("Error preparing tag response"); + LogTrace(receivedCmd, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + break; + } + p_response = &dynamic_response_info; + } + } - // Count number of wakeups received after a halt - if (order == 6 && lastorder == 5) { happened++; } + // Count number of wakeups received after a halt + if (order == 6 && lastorder == 5) { happened++; } - // Count number of other messages after a halt - if (order != 6 && lastorder == 5) { happened2++; } + // Count number of other messages after a halt + if (order != 6 && lastorder == 5) { happened2++; } - cmdsRecvd++; + cmdsRecvd++; - if (p_response != NULL) { - EmSendCmd14443aRaw(p_response->modulation, p_response->modulation_n); - // do the tracing for the previous reader request and this tag answer: - uint8_t par[MAX_PARITY_SIZE] = {0x00}; - GetParity(p_response->response, p_response->response_n, par); + if (p_response != NULL) { + EmSendCmd14443aRaw(p_response->modulation, p_response->modulation_n); + // do the tracing for the previous reader request and this tag answer: + uint8_t par[MAX_PARITY_SIZE] = {0x00}; + GetParity(p_response->response, p_response->response_n, par); - EmLogTrace(Uart.output, - Uart.len, - Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.parity, - p_response->response, - p_response->response_n, - LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, - (LastTimeProxToAirStart + p_response->ProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, - par); - } - } + EmLogTrace(Uart.output, + Uart.len, + Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, + Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, + Uart.parity, + p_response->response, + p_response->response_n, + LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, + (LastTimeProxToAirStart + p_response->ProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, + par); + } + } - cmd_send(CMD_ACK,1,0,0,0,0); - switch_off(); + cmd_send(CMD_ACK,1,0,0,0,0); + switch_off(); - BigBuf_free_keep_EM(); + BigBuf_free_keep_EM(); - if (MF_DBGLEVEL >= 4){ - Dbprintf("-[ Wake ups after halt [%d]", happened); - Dbprintf("-[ Messages after halt [%d]", happened2); - Dbprintf("-[ Num of received cmd [%d]", cmdsRecvd); - Dbprintf("-[ Num of moebius tries [%d]", moebius_count); - } + if (MF_DBGLEVEL >= 4){ + Dbprintf("-[ Wake ups after halt [%d]", happened); + Dbprintf("-[ Messages after halt [%d]", happened2); + Dbprintf("-[ Num of received cmd [%d]", cmdsRecvd); + Dbprintf("-[ Num of moebius tries [%d]", moebius_count); + } } // prepare a delayed transfer. This simply shifts ToSend[] by a number // of bits specified in the delay parameter. void PrepareDelayedTransfer(uint16_t delay) { - delay &= 0x07; - if (!delay) return; + delay &= 0x07; + if (!delay) return; - uint8_t bitmask = 0; - uint8_t bits_to_shift = 0; - uint8_t bits_shifted = 0; - uint16_t i = 0; + uint8_t bitmask = 0; + uint8_t bits_to_shift = 0; + uint8_t bits_shifted = 0; + uint16_t i = 0; - for (i = 0; i < delay; i++) - bitmask |= (0x01 << i); + for (i = 0; i < delay; i++) + bitmask |= (0x01 << i); - ToSend[ToSendMax++] = 0x00; + ToSend[ToSendMax++] = 0x00; - for (i = 0; i < ToSendMax; i++) { - bits_to_shift = ToSend[i] & bitmask; - ToSend[i] = ToSend[i] >> delay; - ToSend[i] = ToSend[i] | (bits_shifted << (8 - delay)); - bits_shifted = bits_to_shift; - } - } + for (i = 0; i < ToSendMax; i++) { + bits_to_shift = ToSend[i] & bitmask; + ToSend[i] = ToSend[i] >> delay; + ToSend[i] = ToSend[i] | (bits_shifted << (8 - delay)); + bits_shifted = bits_to_shift; + } + } //------------------------------------------------------------------------------------- // Transmit the command (to the tag) that was placed in ToSend[]. // Parameter timing: // if NULL: transfer at next possible time, taking into account -// request guard time and frame delay time -// if == 0: transfer immediately and return time of transfer +// request guard time and frame delay time +// if == 0: transfer immediately and return time of transfer // if != 0: delay transfer until time specified //------------------------------------------------------------------------------------- static void TransmitFor14443a(const uint8_t *cmd, uint16_t len, uint32_t *timing) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_MOD); - if (timing) { - if (*timing == 0) // Measure time - *timing = (GetCountSspClk() + 8) & 0xfffffff8; - else - PrepareDelayedTransfer(*timing & 0x00000007); // Delay transfer (fine tuning - up to 7 MF clock ticks) + if (timing) { + if (*timing == 0) // Measure time + *timing = (GetCountSspClk() + 8) & 0xfffffff8; + else + PrepareDelayedTransfer(*timing & 0x00000007); // Delay transfer (fine tuning - up to 7 MF clock ticks) - if(MF_DBGLEVEL >= 4 && GetCountSspClk() >= (*timing & 0xfffffff8)) - Dbprintf("TransmitFor14443a: Missed timing"); - while (GetCountSspClk() < (*timing & 0xfffffff8)) {}; // Delay transfer (multiple of 8 MF clock ticks) - LastTimeProxToAirStart = *timing; - } else { + if(MF_DBGLEVEL >= 4 && GetCountSspClk() >= (*timing & 0xfffffff8)) + Dbprintf("TransmitFor14443a: Missed timing"); + while (GetCountSspClk() < (*timing & 0xfffffff8)) {}; // Delay transfer (multiple of 8 MF clock ticks) + LastTimeProxToAirStart = *timing; + } else { - uint32_t ThisTransferTime = 0; - ThisTransferTime = ((MAX(NextTransferTime, GetCountSspClk()) & 0xfffffff8) + 8); + uint32_t ThisTransferTime = 0; + ThisTransferTime = ((MAX(NextTransferTime, GetCountSspClk()) & 0xfffffff8) + 8); - while (GetCountSspClk() < ThisTransferTime) {}; + while (GetCountSspClk() < ThisTransferTime) {}; - LastTimeProxToAirStart = ThisTransferTime; - } + LastTimeProxToAirStart = ThisTransferTime; + } - // clear TXRDY - AT91C_BASE_SSC->SSC_THR = SEC_Y; + // clear TXRDY + AT91C_BASE_SSC->SSC_THR = SEC_Y; - volatile uint8_t b; - uint16_t c = 0; - while (c < len) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = cmd[c++]; - } - //iceman test - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); (void)b; - } - } + volatile uint8_t b; + uint16_t c = 0; + while (c < len) { + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = cmd[c++]; + } + //iceman test + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); (void)b; + } + } - NextTransferTime = MAX(NextTransferTime, LastTimeProxToAirStart + REQUEST_GUARD_TIME); + NextTransferTime = MAX(NextTransferTime, LastTimeProxToAirStart + REQUEST_GUARD_TIME); } //----------------------------------------------------------------------------- // Prepare reader command (in bits, support short frames) to send to FPGA //----------------------------------------------------------------------------- void CodeIso14443aBitsAsReaderPar(const uint8_t *cmd, uint16_t bits, const uint8_t *parity) { - int i, j; - int last = 0; - uint8_t b; + int i, j; + int last = 0; + uint8_t b; - ToSendReset(); + ToSendReset(); - // Start of Communication (Seq. Z) - ToSend[++ToSendMax] = SEC_Z; - LastProxToAirDuration = 8 * (ToSendMax+1) - 6; + // Start of Communication (Seq. Z) + ToSend[++ToSendMax] = SEC_Z; + LastProxToAirDuration = 8 * (ToSendMax+1) - 6; - size_t bytecount = nbytes(bits); - // Generate send structure for the data bits - for (i = 0; i < bytecount; i++) { - // Get the current byte to send - b = cmd[i]; - size_t bitsleft = MIN((bits-(i*8)),8); + size_t bytecount = nbytes(bits); + // Generate send structure for the data bits + for (i = 0; i < bytecount; i++) { + // Get the current byte to send + b = cmd[i]; + size_t bitsleft = MIN((bits-(i*8)),8); - for (j = 0; j < bitsleft; j++) { - if (b & 1) { - // Sequence X - ToSend[++ToSendMax] = SEC_X; - LastProxToAirDuration = 8 * (ToSendMax+1) - 2; - last = 1; - } else { - if (last == 0) { - // Sequence Z - ToSend[++ToSendMax] = SEC_Z; - LastProxToAirDuration = 8 * (ToSendMax+1) - 6; - } else { - // Sequence Y - ToSend[++ToSendMax] = SEC_Y; - last = 0; - } - } - b >>= 1; - } + for (j = 0; j < bitsleft; j++) { + if (b & 1) { + // Sequence X + ToSend[++ToSendMax] = SEC_X; + LastProxToAirDuration = 8 * (ToSendMax+1) - 2; + last = 1; + } else { + if (last == 0) { + // Sequence Z + ToSend[++ToSendMax] = SEC_Z; + LastProxToAirDuration = 8 * (ToSendMax+1) - 6; + } else { + // Sequence Y + ToSend[++ToSendMax] = SEC_Y; + last = 0; + } + } + b >>= 1; + } - // Only transmit parity bit if we transmitted a complete byte - if (j == 8 && parity != NULL) { - // Get the parity bit - if (parity[i>>3] & (0x80 >> (i&0x0007))) { - // Sequence X - ToSend[++ToSendMax] = SEC_X; - LastProxToAirDuration = 8 * (ToSendMax+1) - 2; - last = 1; - } else { - if (last == 0) { - // Sequence Z - ToSend[++ToSendMax] = SEC_Z; - LastProxToAirDuration = 8 * (ToSendMax+1) - 6; - } else { - // Sequence Y - ToSend[++ToSendMax] = SEC_Y; - last = 0; - } - } - } - } + // Only transmit parity bit if we transmitted a complete byte + if (j == 8 && parity != NULL) { + // Get the parity bit + if (parity[i>>3] & (0x80 >> (i&0x0007))) { + // Sequence X + ToSend[++ToSendMax] = SEC_X; + LastProxToAirDuration = 8 * (ToSendMax+1) - 2; + last = 1; + } else { + if (last == 0) { + // Sequence Z + ToSend[++ToSendMax] = SEC_Z; + LastProxToAirDuration = 8 * (ToSendMax+1) - 6; + } else { + // Sequence Y + ToSend[++ToSendMax] = SEC_Y; + last = 0; + } + } + } + } - // End of Communication: Logic 0 followed by Sequence Y - if (last == 0) { - // Sequence Z - ToSend[++ToSendMax] = SEC_Z; - LastProxToAirDuration = 8 * (ToSendMax+1) - 6; - } else { - // Sequence Y - ToSend[++ToSendMax] = SEC_Y; - last = 0; - } - ToSend[++ToSendMax] = SEC_Y; + // End of Communication: Logic 0 followed by Sequence Y + if (last == 0) { + // Sequence Z + ToSend[++ToSendMax] = SEC_Z; + LastProxToAirDuration = 8 * (ToSendMax+1) - 6; + } else { + // Sequence Y + ToSend[++ToSendMax] = SEC_Y; + last = 0; + } + ToSend[++ToSendMax] = SEC_Y; - // Convert to length of command: - ToSendMax++; + // Convert to length of command: + ToSendMax++; } //----------------------------------------------------------------------------- @@ -1556,196 +1556,196 @@ void CodeIso14443aAsReaderPar(const uint8_t *cmd, uint16_t len, const uint8_t *p // Or return 0 when command is captured //----------------------------------------------------------------------------- int EmGetCmd(uint8_t *received, uint16_t *len, uint8_t *parity) { - *len = 0; + *len = 0; - uint32_t timer = 0, vtime = 0; - int analogCnt = 0; - int analogAVG = 0; + uint32_t timer = 0, vtime = 0; + int analogCnt = 0; + int analogAVG = 0; - // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen - // only, since we are receiving, not transmitting). - // Signal field is off with the appropriate LED - LED_D_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); + // Set FPGA mode to "simulated ISO 14443 tag", no modulation (listen + // only, since we are receiving, not transmitting). + // Signal field is off with the appropriate LED + LED_D_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_LISTEN); - // Set ADC to read field strength - AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST; - AT91C_BASE_ADC->ADC_MR = - ADC_MODE_PRESCALE(63) | - ADC_MODE_STARTUP_TIME(1) | - ADC_MODE_SAMPLE_HOLD_TIME(15); - AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ADC_CHAN_HF); - // start ADC - AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; + // Set ADC to read field strength + AT91C_BASE_ADC->ADC_CR = AT91C_ADC_SWRST; + AT91C_BASE_ADC->ADC_MR = + ADC_MODE_PRESCALE(63) | + ADC_MODE_STARTUP_TIME(1) | + ADC_MODE_SAMPLE_HOLD_TIME(15); + AT91C_BASE_ADC->ADC_CHER = ADC_CHANNEL(ADC_CHAN_HF); + // start ADC + AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; - // Now run a 'software UART' on the stream of incoming samples. - UartInit(received, parity); + // Now run a 'software UART' on the stream of incoming samples. + UartInit(received, parity); - // Clear RXRDY: + // Clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - for(;;) { - WDT_HIT(); + for(;;) { + WDT_HIT(); - if (BUTTON_PRESS()) return 1; + if (BUTTON_PRESS()) return 1; - // test if the field exists - if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF)) { - analogCnt++; - analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF]; - AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; - if (analogCnt >= 32) { - if ((MAX_ADC_HF_VOLTAGE * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) { - vtime = GetTickCount(); - if (!timer) timer = vtime; - // 50ms no field --> card to idle state - if (vtime - timer > 50) return 2; - } else - if (timer) timer = 0; - analogCnt = 0; - analogAVG = 0; - } - } + // test if the field exists + if (AT91C_BASE_ADC->ADC_SR & ADC_END_OF_CONVERSION(ADC_CHAN_HF)) { + analogCnt++; + analogAVG += AT91C_BASE_ADC->ADC_CDR[ADC_CHAN_HF]; + AT91C_BASE_ADC->ADC_CR = AT91C_ADC_START; + if (analogCnt >= 32) { + if ((MAX_ADC_HF_VOLTAGE * (analogAVG / analogCnt) >> 10) < MF_MINFIELDV) { + vtime = GetTickCount(); + if (!timer) timer = vtime; + // 50ms no field --> card to idle state + if (vtime - timer > 50) return 2; + } else + if (timer) timer = 0; + analogCnt = 0; + analogAVG = 0; + } + } - // receive and test the miller decoding + // receive and test the miller decoding if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - if(MillerDecoding(b, 0)) { - *len = Uart.len; - return 0; - } + if(MillerDecoding(b, 0)) { + *len = Uart.len; + return 0; + } } - } + } } int EmSendCmd14443aRaw(uint8_t *resp, uint16_t respLen) { - volatile uint8_t b; - uint16_t i = 0; - uint32_t ThisTransferTime; - bool correctionNeeded; + volatile uint8_t b; + uint16_t i = 0; + uint32_t ThisTransferTime; + bool correctionNeeded; - // Modulate Manchester - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD); + // Modulate Manchester + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_TAGSIM_MOD); - // Include correction bit if necessary - if (Uart.bitCount == 7) - { - // Short tags (7 bits) don't have parity, determine the correct value from MSB - correctionNeeded = Uart.output[0] & 0x40; - } - else - { - // The parity bits are left-aligned - correctionNeeded = Uart.parity[(Uart.len-1)/8] & (0x80 >> ((Uart.len-1) & 7)); - } - // 1236, so correction bit needed - i = (correctionNeeded) ? 0 : 1; + // Include correction bit if necessary + if (Uart.bitCount == 7) + { + // Short tags (7 bits) don't have parity, determine the correct value from MSB + correctionNeeded = Uart.output[0] & 0x40; + } + else + { + // The parity bits are left-aligned + correctionNeeded = Uart.parity[(Uart.len-1)/8] & (0x80 >> ((Uart.len-1) & 7)); + } + // 1236, so correction bit needed + i = (correctionNeeded) ? 0 : 1; - // clear receiving shift register and holding register - while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)); - b = AT91C_BASE_SSC->SSC_RHR; (void) b; - while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)); - b = AT91C_BASE_SSC->SSC_RHR; (void) b; + // clear receiving shift register and holding register + while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)); + b = AT91C_BASE_SSC->SSC_RHR; (void) b; + while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)); + b = AT91C_BASE_SSC->SSC_RHR; (void) b; - // wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line) - for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never - while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)); - if (AT91C_BASE_SSC->SSC_RHR) break; - } + // wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line) + for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never + while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)); + if (AT91C_BASE_SSC->SSC_RHR) break; + } - while ((ThisTransferTime = GetCountSspClk()) & 0x00000007); + while ((ThisTransferTime = GetCountSspClk()) & 0x00000007); - // Clear TXRDY: - AT91C_BASE_SSC->SSC_THR = SEC_F; + // Clear TXRDY: + AT91C_BASE_SSC->SSC_THR = SEC_F; - // send cycle - for(; i < respLen; ) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = resp[i++]; - FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - } + // send cycle + for(; i < respLen; ) { + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = resp[i++]; + FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + } - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); (void)b; - } - if(BUTTON_PRESS()) break; - } + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + b = (uint16_t)(AT91C_BASE_SSC->SSC_RHR); (void)b; + } + if(BUTTON_PRESS()) break; + } - // Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again: - uint8_t fpga_queued_bits = FpgaSendQueueDelay >> 3; - for (i = 0; i <= fpga_queued_bits/8 + 1; ) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = SEC_F; - FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - i++; - } - } - LastTimeProxToAirStart = ThisTransferTime + (correctionNeeded ? 8 : 0); - return 0; + // Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again: + uint8_t fpga_queued_bits = FpgaSendQueueDelay >> 3; + for (i = 0; i <= fpga_queued_bits/8 + 1; ) { + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = SEC_F; + FpgaSendQueueDelay = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + i++; + } + } + LastTimeProxToAirStart = ThisTransferTime + (correctionNeeded ? 8 : 0); + return 0; } int EmSend4bit(uint8_t resp){ - Code4bitAnswerAsTag(resp); - int res = EmSendCmd14443aRaw(ToSend, ToSendMax); - // do the tracing for the previous reader request and this tag answer: - uint8_t par[1] = {0x00}; - GetParity(&resp, 1, par); - EmLogTrace(Uart.output, - Uart.len, - Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.parity, - &resp, - 1, - LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, - (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, - par); - return res; + Code4bitAnswerAsTag(resp); + int res = EmSendCmd14443aRaw(ToSend, ToSendMax); + // do the tracing for the previous reader request and this tag answer: + uint8_t par[1] = {0x00}; + GetParity(&resp, 1, par); + EmLogTrace(Uart.output, + Uart.len, + Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, + Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, + Uart.parity, + &resp, + 1, + LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, + (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, + par); + return res; } int EmSendCmdPar(uint8_t *resp, uint16_t respLen, uint8_t *par) { - return EmSendCmdParEx(resp, respLen, par, false); + return EmSendCmdParEx(resp, respLen, par, false); } int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool collision){ - CodeIso14443aAsTagPar(resp, respLen, par, collision); - int res = EmSendCmd14443aRaw(ToSend, ToSendMax); - // do the tracing for the previous reader request and this tag answer: - EmLogTrace(Uart.output, - Uart.len, - Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, - Uart.parity, - resp, - respLen, - LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, - (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, - par); - return res; + CodeIso14443aAsTagPar(resp, respLen, par, collision); + int res = EmSendCmd14443aRaw(ToSend, ToSendMax); + // do the tracing for the previous reader request and this tag answer: + EmLogTrace(Uart.output, + Uart.len, + Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, + Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, + Uart.parity, + resp, + respLen, + LastTimeProxToAirStart*16 + DELAY_ARM2AIR_AS_TAG, + (LastTimeProxToAirStart + LastProxToAirDuration)*16 + DELAY_ARM2AIR_AS_TAG, + par); + return res; } int EmSendCmd(uint8_t *resp, uint16_t respLen){ - return EmSendCmdEx(resp, respLen, false); + return EmSendCmdEx(resp, respLen, false); } int EmSendCmdEx(uint8_t *resp, uint16_t respLen, bool collision){ - uint8_t par[MAX_PARITY_SIZE] = {0x00}; - GetParity(resp, respLen, par); - return EmSendCmdParEx(resp, respLen, par, collision); + uint8_t par[MAX_PARITY_SIZE] = {0x00}; + GetParity(resp, respLen, par); + return EmSendCmdParEx(resp, respLen, par, collision); } bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity, - uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity) + uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity) { - // we cannot exactly measure the end and start of a received command from reader. However we know that the delay from - // end of the received command to start of the tag's (simulated by us) answer is n*128+20 or n*128+84 resp. - // with n >= 9. The start of the tags answer can be measured and therefore the end of the received command be calculated: - uint16_t reader_modlen = reader_EndTime - reader_StartTime; - uint16_t approx_fdt = tag_StartTime - reader_EndTime; - uint16_t exact_fdt = (approx_fdt - 20 + 32)/64 * 64 + 20; - reader_EndTime = tag_StartTime - exact_fdt; - reader_StartTime = reader_EndTime - reader_modlen; + // we cannot exactly measure the end and start of a received command from reader. However we know that the delay from + // end of the received command to start of the tag's (simulated by us) answer is n*128+20 or n*128+84 resp. + // with n >= 9. The start of the tags answer can be measured and therefore the end of the received command be calculated: + uint16_t reader_modlen = reader_EndTime - reader_StartTime; + uint16_t approx_fdt = tag_StartTime - reader_EndTime; + uint16_t exact_fdt = (approx_fdt - 20 + 32)/64 * 64 + 20; + reader_EndTime = tag_StartTime - exact_fdt; + reader_StartTime = reader_EndTime - reader_modlen; - if (!LogTrace(reader_data, reader_len, reader_StartTime, reader_EndTime, reader_Parity, true)) - return false; - else - return(!LogTrace(tag_data, tag_len, tag_StartTime, tag_EndTime, tag_Parity, false)); + if (!LogTrace(reader_data, reader_len, reader_StartTime, reader_EndTime, reader_Parity, true)) + return false; + else + return(!LogTrace(tag_data, tag_len, tag_StartTime, tag_EndTime, tag_Parity, false)); } @@ -1755,44 +1755,44 @@ bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_Start // If it takes too long return FALSE //----------------------------------------------------------------------------- static int GetIso14443aAnswerFromTag(uint8_t *receivedResponse, uint8_t *receivedResponsePar, uint16_t offset) { - uint32_t c = 0; + uint32_t c = 0; - // Set FPGA mode to "reader listen mode", no modulation (listen - // only, since we are receiving, not transmitting). - // Signal field is on with the appropriate LED - LED_D_ON(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN); + // Set FPGA mode to "reader listen mode", no modulation (listen + // only, since we are receiving, not transmitting). + // Signal field is on with the appropriate LED + LED_D_ON(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | FPGA_HF_ISO14443A_READER_LISTEN); - // Now get the answer from the card - DemodInit(receivedResponse, receivedResponsePar); + // Now get the answer from the card + DemodInit(receivedResponse, receivedResponsePar); - // clear RXRDY: + // clear RXRDY: uint8_t b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - uint32_t timeout = iso14a_get_timeout(); - for(;;) { - WDT_HIT(); + uint32_t timeout = iso14a_get_timeout(); + for(;;) { + WDT_HIT(); - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - if (ManchesterDecoding(b, offset, 0)) { - NextTransferTime = MAX(NextTransferTime, Demod.endTime - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/16 + FRAME_DELAY_TIME_PICC_TO_PCD); - return true; - } else if (c++ > timeout && Demod.state == DEMOD_UNSYNCD) { - return false; - } - } - } + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + b = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + if (ManchesterDecoding(b, offset, 0)) { + NextTransferTime = MAX(NextTransferTime, Demod.endTime - (DELAY_AIR2ARM_AS_READER + DELAY_ARM2AIR_AS_READER)/16 + FRAME_DELAY_TIME_PICC_TO_PCD); + return true; + } else if (c++ > timeout && Demod.state == DEMOD_UNSYNCD) { + return false; + } + } + } } void ReaderTransmitBitsPar(uint8_t* frame, uint16_t bits, uint8_t *par, uint32_t *timing) { - CodeIso14443aBitsAsReaderPar(frame, bits, par); - // Send command to tag - TransmitFor14443a(ToSend, ToSendMax, timing); - if(trigger) LED_A_ON(); + CodeIso14443aBitsAsReaderPar(frame, bits, par); + // Send command to tag + TransmitFor14443a(ToSend, ToSendMax, timing); + if(trigger) LED_A_ON(); - LogTrace(frame, nbytes(bits), (LastTimeProxToAirStart<<4) + DELAY_ARM2AIR_AS_READER, ((LastTimeProxToAirStart + LastProxToAirDuration)<<4) + DELAY_ARM2AIR_AS_READER, par, true); + LogTrace(frame, nbytes(bits), (LastTimeProxToAirStart<<4) + DELAY_ARM2AIR_AS_READER, ((LastTimeProxToAirStart + LastProxToAirDuration)<<4) + DELAY_ARM2AIR_AS_READER, par, true); } void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *timing) { @@ -1800,31 +1800,31 @@ void ReaderTransmitPar(uint8_t* frame, uint16_t len, uint8_t *par, uint32_t *tim } void ReaderTransmitBits(uint8_t* frame, uint16_t len, uint32_t *timing) { - // Generate parity and redirect - uint8_t par[MAX_PARITY_SIZE] = {0x00}; - GetParity(frame, len/8, par); - ReaderTransmitBitsPar(frame, len, par, timing); + // Generate parity and redirect + uint8_t par[MAX_PARITY_SIZE] = {0x00}; + GetParity(frame, len/8, par); + ReaderTransmitBitsPar(frame, len, par, timing); } void ReaderTransmit(uint8_t* frame, uint16_t len, uint32_t *timing) { - // Generate parity and redirect - uint8_t par[MAX_PARITY_SIZE] = {0x00}; - GetParity(frame, len, par); - ReaderTransmitBitsPar(frame, len*8, par, timing); + // Generate parity and redirect + uint8_t par[MAX_PARITY_SIZE] = {0x00}; + GetParity(frame, len, par); + ReaderTransmitBitsPar(frame, len*8, par, timing); } int ReaderReceiveOffset(uint8_t* receivedAnswer, uint16_t offset, uint8_t *parity) { - if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, offset)) - return false; - LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, false); - return Demod.len; + if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, offset)) + return false; + LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, false); + return Demod.len; } int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity) { - if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, 0)) - return false; - LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, false); - return Demod.len; + if (!GetIso14443aAnswerFromTag(receivedAnswer, parity, 0)) + return false; + LogTrace(receivedAnswer, Demod.len, Demod.startTime*16 - DELAY_AIR2ARM_AS_READER, Demod.endTime*16 - DELAY_AIR2ARM_AS_READER, parity, false); + return Demod.len; } // This function misstreats the ISO 14443a anticollision procedure. @@ -1832,125 +1832,125 @@ int ReaderReceive(uint8_t *receivedAnswer, uint8_t *parity) { // increase the uid bytes. The might be an overflow, DoS will occure. void iso14443a_antifuzz(uint32_t flags){ - // We need to listen to the high-frequency, peak-detected path. - iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); + // We need to listen to the high-frequency, peak-detected path. + iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); - BigBuf_free_keep_EM(); - clear_trace(); - set_tracing(true); + BigBuf_free_keep_EM(); + clear_trace(); + set_tracing(true); - int len = 0; + int len = 0; - // allocate buffers: - uint8_t *received = BigBuf_malloc(MAX_FRAME_SIZE); - uint8_t *receivedPar = BigBuf_malloc(MAX_PARITY_SIZE); - uint8_t *resp = BigBuf_malloc(20); + // allocate buffers: + uint8_t *received = BigBuf_malloc(MAX_FRAME_SIZE); + uint8_t *receivedPar = BigBuf_malloc(MAX_PARITY_SIZE); + uint8_t *resp = BigBuf_malloc(20); - memset(resp, 0xFF , 20); + memset(resp, 0xFF , 20); - LED_A_ON(); - for (;;) { - WDT_HIT(); + LED_A_ON(); + for (;;) { + WDT_HIT(); - // Clean receive command buffer - if (!GetIso14443aCommandFromReader(received, receivedPar, &len)) { - Dbprintf("Anti-fuzz stopped. Trace length: %d ", BigBuf_get_traceLen()); - break; - } - if ( received[0] == ISO14443A_CMD_WUPA || received[0] == ISO14443A_CMD_REQA) { - resp[0] = 0x04; - resp[1] = 0x00; + // Clean receive command buffer + if (!GetIso14443aCommandFromReader(received, receivedPar, &len)) { + Dbprintf("Anti-fuzz stopped. Trace length: %d ", BigBuf_get_traceLen()); + break; + } + if ( received[0] == ISO14443A_CMD_WUPA || received[0] == ISO14443A_CMD_REQA) { + resp[0] = 0x04; + resp[1] = 0x00; - if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA ) { - resp[0] = 0x44; - } + if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA ) { + resp[0] = 0x44; + } - EmSendCmd(resp, 2); - continue; - } + EmSendCmd(resp, 2); + continue; + } - // Received request for UID (cascade 1) - //if (received[1] >= 0x20 && received[1] <= 0x57 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { - if (received[1] >= 0x20 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { - resp[0] = 0xFF; - resp[1] = 0xFF; - resp[2] = 0xFF; - resp[3] = 0xFF; - resp[4] = resp[0] ^ resp[1] ^ resp[2] ^ resp[3]; - colpos = 0; + // Received request for UID (cascade 1) + //if (received[1] >= 0x20 && received[1] <= 0x57 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { + if (received[1] >= 0x20 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { + resp[0] = 0xFF; + resp[1] = 0xFF; + resp[2] = 0xFF; + resp[3] = 0xFF; + resp[4] = resp[0] ^ resp[1] ^ resp[2] ^ resp[3]; + colpos = 0; - if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA ) { - resp[0] = 0x88; - colpos = 8; - } + if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA ) { + resp[0] = 0x88; + colpos = 8; + } - EmSendCmdEx(resp, 5, true); - if (MF_DBGLEVEL >= 4) Dbprintf("ANTICOLL or SELECT %x", received[1]); - LED_D_INV(); + EmSendCmdEx(resp, 5, true); + if (MF_DBGLEVEL >= 4) Dbprintf("ANTICOLL or SELECT %x", received[1]); + LED_D_INV(); - continue; - } else if (received[1] == 0x20 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received request for UID (cascade 2) - if (MF_DBGLEVEL >= 4) Dbprintf("ANTICOLL or SELECT_2"); - } else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received a SELECT (cascade 1) - } else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received a SELECT (cascade 2) - } else { - Dbprintf("unknown command %x", received[0]); - } - } + continue; + } else if (received[1] == 0x20 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received request for UID (cascade 2) + if (MF_DBGLEVEL >= 4) Dbprintf("ANTICOLL or SELECT_2"); + } else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT) { // Received a SELECT (cascade 1) + } else if (received[1] == 0x70 && received[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2) { // Received a SELECT (cascade 2) + } else { + Dbprintf("unknown command %x", received[0]); + } + } - cmd_send(CMD_ACK,1,0,0,0,0); - switch_off(); - BigBuf_free_keep_EM(); + cmd_send(CMD_ACK,1,0,0,0,0); + switch_off(); + BigBuf_free_keep_EM(); } static void iso14a_set_ATS_times(uint8_t *ats) { - uint8_t tb1; - uint8_t fwi, sfgi; - uint32_t fwt, sfgt; + uint8_t tb1; + uint8_t fwi, sfgi; + uint32_t fwt, sfgt; - if (ats[0] > 1) { // there is a format byte T0 - if ((ats[1] & 0x20) == 0x20) { // there is an interface byte TB(1) - if ((ats[1] & 0x10) == 0x10) { // there is an interface byte TA(1) preceding TB(1) - tb1 = ats[3]; - } else { - tb1 = ats[2]; - } - fwi = (tb1 & 0xf0) >> 4; // frame waiting time integer (FWI) - if (fwi != 15) { - fwt = 256 * 16 * (1 << fwi); // frame waiting time (FWT) in 1/fc - iso14a_set_timeout(fwt/(8*16)); - } - sfgi = tb1 & 0x0f; // startup frame guard time integer (SFGI) - if (sfgi != 0 && sfgi != 15) { - sfgt = 256 * 16 * (1 << sfgi); // startup frame guard time (SFGT) in 1/fc - NextTransferTime = MAX(NextTransferTime, Demod.endTime + (sfgt - DELAY_AIR2ARM_AS_READER - DELAY_ARM2AIR_AS_READER)/16); - } - } - } + if (ats[0] > 1) { // there is a format byte T0 + if ((ats[1] & 0x20) == 0x20) { // there is an interface byte TB(1) + if ((ats[1] & 0x10) == 0x10) { // there is an interface byte TA(1) preceding TB(1) + tb1 = ats[3]; + } else { + tb1 = ats[2]; + } + fwi = (tb1 & 0xf0) >> 4; // frame waiting time integer (FWI) + if (fwi != 15) { + fwt = 256 * 16 * (1 << fwi); // frame waiting time (FWT) in 1/fc + iso14a_set_timeout(fwt/(8*16)); + } + sfgi = tb1 & 0x0f; // startup frame guard time integer (SFGI) + if (sfgi != 0 && sfgi != 15) { + sfgt = 256 * 16 * (1 << sfgi); // startup frame guard time (SFGT) in 1/fc + NextTransferTime = MAX(NextTransferTime, Demod.endTime + (sfgt - DELAY_AIR2ARM_AS_READER - DELAY_ARM2AIR_AS_READER)/16); + } + } + } } static int GetATQA(uint8_t *resp, uint8_t *resp_par) { -#define WUPA_RETRY_TIMEOUT 10 // 10ms - uint8_t wupa[] = { ISO14443A_CMD_WUPA }; // 0x26 - REQA 0x52 - WAKE-UP +#define WUPA_RETRY_TIMEOUT 10 // 10ms + uint8_t wupa[] = { ISO14443A_CMD_WUPA }; // 0x26 - REQA 0x52 - WAKE-UP - uint32_t save_iso14a_timeout = iso14a_get_timeout(); - iso14a_set_timeout(1236/(16*8)+1); // response to WUPA is expected at exactly 1236/fc. No need to wait longer. + uint32_t save_iso14a_timeout = iso14a_get_timeout(); + iso14a_set_timeout(1236/(16*8)+1); // response to WUPA is expected at exactly 1236/fc. No need to wait longer. - uint32_t start_time = GetTickCount(); - int len; + uint32_t start_time = GetTickCount(); + int len; - // we may need several tries if we did send an unknown command or a wrong authentication before... - do { - // Broadcast for a card, WUPA (0x52) will force response from all cards in the field - ReaderTransmitBitsPar(wupa, 7, NULL, NULL); - // Receive the ATQA - len = ReaderReceive(resp, resp_par); - } while (len == 0 && GetTickCount() <= start_time + WUPA_RETRY_TIMEOUT); + // we may need several tries if we did send an unknown command or a wrong authentication before... + do { + // Broadcast for a card, WUPA (0x52) will force response from all cards in the field + ReaderTransmitBitsPar(wupa, 7, NULL, NULL); + // Receive the ATQA + len = ReaderReceive(resp, resp_par); + } while (len == 0 && GetTickCount() <= start_time + WUPA_RETRY_TIMEOUT); - iso14a_set_timeout(save_iso14a_timeout); - return len; + iso14a_set_timeout(save_iso14a_timeout); + return len; } // performs iso14443a anticollision (optional) and card select procedure @@ -1961,238 +1961,238 @@ static int GetATQA(uint8_t *resp, uint8_t *resp_par) { // requests ATS unless no_rats is true int iso14443a_select_card(byte_t *uid_ptr, iso14a_card_select_t *p_card, uint32_t *cuid_ptr, bool anticollision, uint8_t num_cascades, bool no_rats) { - uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT,0x20 }; - uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8_t rats[] = { ISO14443A_CMD_RATS,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0 - uint8_t resp[MAX_FRAME_SIZE] = {0}; // theoretically. A usual RATS will be much smaller - uint8_t resp_par[MAX_PARITY_SIZE] = {0}; - uint8_t uid_resp[4] = {0}; - size_t uid_resp_len = 0; + uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT,0x20 }; + uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t rats[] = { ISO14443A_CMD_RATS,0x80,0x00,0x00 }; // FSD=256, FSDI=8, CID=0 + uint8_t resp[MAX_FRAME_SIZE] = {0}; // theoretically. A usual RATS will be much smaller + uint8_t resp_par[MAX_PARITY_SIZE] = {0}; + uint8_t uid_resp[4] = {0}; + size_t uid_resp_len = 0; - uint8_t sak = 0x04; // cascade uid - int cascade_level = 0; - int len; + uint8_t sak = 0x04; // cascade uid + int cascade_level = 0; + int len; - if (p_card) { - p_card->uidlen = 0; - memset(p_card->uid, 0, 10); - p_card->ats_len = 0; - } + if (p_card) { + p_card->uidlen = 0; + memset(p_card->uid, 0, 10); + p_card->ats_len = 0; + } - if (!GetATQA(resp, resp_par)) { - return 0; - } + if (!GetATQA(resp, resp_par)) { + return 0; + } - if (p_card) { - p_card->atqa[0] = resp[0]; - p_card->atqa[1] = resp[1]; - } + if (p_card) { + p_card->atqa[0] = resp[0]; + p_card->atqa[1] = resp[1]; + } - if (anticollision) { - // clear uid - if (uid_ptr) - memset(uid_ptr, 0, 10); - } + if (anticollision) { + // clear uid + if (uid_ptr) + memset(uid_ptr, 0, 10); + } - // check for proprietary anticollision: - if ((resp[0] & 0x1F) == 0) return 3; + // check for proprietary anticollision: + if ((resp[0] & 0x1F) == 0) return 3; - // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in - // which case we need to make a cascade 2 request and select - this is a long UID - // While the UID is not complete, the 3nd bit (from the right) is set in the SAK. - for(; sak & 0x04; cascade_level++) { - // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97) - sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2; + // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in + // which case we need to make a cascade 2 request and select - this is a long UID + // While the UID is not complete, the 3nd bit (from the right) is set in the SAK. + for(; sak & 0x04; cascade_level++) { + // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97) + sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2; - if (anticollision) { - // SELECT_ALL - ReaderTransmit(sel_all, sizeof(sel_all), NULL); - if (!ReaderReceive(resp, resp_par)) return 0; + if (anticollision) { + // SELECT_ALL + ReaderTransmit(sel_all, sizeof(sel_all), NULL); + if (!ReaderReceive(resp, resp_par)) return 0; - if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit - memset(uid_resp, 0, 4); - uint16_t uid_resp_bits = 0; - uint16_t collision_answer_offset = 0; - // anti-collision-loop: - while (Demod.collisionPos) { - Dbprintf("Multiple tags detected. Collision after Bit %d", Demod.collisionPos); - for (uint16_t i = collision_answer_offset; i < Demod.collisionPos; i++, uid_resp_bits++) { // add valid UID bits before collision point - uint16_t UIDbit = (resp[i/8] >> (i % 8)) & 0x01; - uid_resp[uid_resp_bits / 8] |= UIDbit << (uid_resp_bits % 8); - } - uid_resp[uid_resp_bits/8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position - uid_resp_bits++; - // construct anticollosion command: - sel_uid[1] = ((2 + uid_resp_bits/8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits - for (uint16_t i = 0; i <= uid_resp_bits/8; i++) { - sel_uid[2+i] = uid_resp[i]; - } - collision_answer_offset = uid_resp_bits%8; - ReaderTransmitBits(sel_uid, 16 + uid_resp_bits, NULL); - if (!ReaderReceiveOffset(resp, collision_answer_offset, resp_par)) return 0; - } - // finally, add the last bits and BCC of the UID - for (uint16_t i = collision_answer_offset; i < (Demod.len-1)*8; i++, uid_resp_bits++) { - uint16_t UIDbit = (resp[i/8] >> (i%8)) & 0x01; - uid_resp[uid_resp_bits/8] |= UIDbit << (uid_resp_bits % 8); - } + if (Demod.collisionPos) { // we had a collision and need to construct the UID bit by bit + memset(uid_resp, 0, 4); + uint16_t uid_resp_bits = 0; + uint16_t collision_answer_offset = 0; + // anti-collision-loop: + while (Demod.collisionPos) { + Dbprintf("Multiple tags detected. Collision after Bit %d", Demod.collisionPos); + for (uint16_t i = collision_answer_offset; i < Demod.collisionPos; i++, uid_resp_bits++) { // add valid UID bits before collision point + uint16_t UIDbit = (resp[i/8] >> (i % 8)) & 0x01; + uid_resp[uid_resp_bits / 8] |= UIDbit << (uid_resp_bits % 8); + } + uid_resp[uid_resp_bits/8] |= 1 << (uid_resp_bits % 8); // next time select the card(s) with a 1 in the collision position + uid_resp_bits++; + // construct anticollosion command: + sel_uid[1] = ((2 + uid_resp_bits/8) << 4) | (uid_resp_bits & 0x07); // length of data in bytes and bits + for (uint16_t i = 0; i <= uid_resp_bits/8; i++) { + sel_uid[2+i] = uid_resp[i]; + } + collision_answer_offset = uid_resp_bits%8; + ReaderTransmitBits(sel_uid, 16 + uid_resp_bits, NULL); + if (!ReaderReceiveOffset(resp, collision_answer_offset, resp_par)) return 0; + } + // finally, add the last bits and BCC of the UID + for (uint16_t i = collision_answer_offset; i < (Demod.len-1)*8; i++, uid_resp_bits++) { + uint16_t UIDbit = (resp[i/8] >> (i%8)) & 0x01; + uid_resp[uid_resp_bits/8] |= UIDbit << (uid_resp_bits % 8); + } - } else { // no collision, use the response to SELECT_ALL as current uid - memcpy(uid_resp, resp, 4); - } + } else { // no collision, use the response to SELECT_ALL as current uid + memcpy(uid_resp, resp, 4); + } - } else { - if (cascade_level < num_cascades - 1) { - uid_resp[0] = 0x88; - memcpy(uid_resp+1, uid_ptr+cascade_level*3, 3); - } else { - memcpy(uid_resp, uid_ptr+cascade_level*3, 4); - } - } - uid_resp_len = 4; + } else { + if (cascade_level < num_cascades - 1) { + uid_resp[0] = 0x88; + memcpy(uid_resp+1, uid_ptr+cascade_level*3, 3); + } else { + memcpy(uid_resp, uid_ptr+cascade_level*3, 4); + } + } + uid_resp_len = 4; - // calculate crypto UID. Always use last 4 Bytes. - if(cuid_ptr) - *cuid_ptr = bytes_to_num(uid_resp, 4); + // calculate crypto UID. Always use last 4 Bytes. + if(cuid_ptr) + *cuid_ptr = bytes_to_num(uid_resp, 4); - // Construct SELECT UID command - sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC) - memcpy(sel_uid+2, uid_resp, 4); // the UID received during anticollision, or the provided UID - sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC - AddCrc14A(sel_uid, 7); // calculate and add CRC - ReaderTransmit(sel_uid, sizeof(sel_uid), NULL); + // Construct SELECT UID command + sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC) + memcpy(sel_uid+2, uid_resp, 4); // the UID received during anticollision, or the provided UID + sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC + AddCrc14A(sel_uid, 7); // calculate and add CRC + ReaderTransmit(sel_uid, sizeof(sel_uid), NULL); - // Receive the SAK - if (!ReaderReceive(resp, resp_par)) return 0; + // Receive the SAK + if (!ReaderReceive(resp, resp_par)) return 0; - sak = resp[0]; + sak = resp[0]; - // Test if more parts of the uid are coming - if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) { - // Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of: - // http://www.nxp.com/documents/application_note/AN10927.pdf - uid_resp[0] = uid_resp[1]; - uid_resp[1] = uid_resp[2]; - uid_resp[2] = uid_resp[3]; - uid_resp_len = 3; - } + // Test if more parts of the uid are coming + if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) { + // Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of: + // http://www.nxp.com/documents/application_note/AN10927.pdf + uid_resp[0] = uid_resp[1]; + uid_resp[1] = uid_resp[2]; + uid_resp[2] = uid_resp[3]; + uid_resp_len = 3; + } - if(uid_ptr && anticollision) - memcpy(uid_ptr + (cascade_level*3), uid_resp, uid_resp_len); + if(uid_ptr && anticollision) + memcpy(uid_ptr + (cascade_level*3), uid_resp, uid_resp_len); - if(p_card) { - memcpy(p_card->uid + (cascade_level*3), uid_resp, uid_resp_len); - p_card->uidlen += uid_resp_len; - } - } + if(p_card) { + memcpy(p_card->uid + (cascade_level*3), uid_resp, uid_resp_len); + p_card->uidlen += uid_resp_len; + } + } - if (p_card) { - p_card->sak = sak; - } + if (p_card) { + p_card->sak = sak; + } - // PICC compilant with iso14443a-4 ---> (SAK & 0x20 != 0) - if( (sak & 0x20) == 0) return 2; + // PICC compilant with iso14443a-4 ---> (SAK & 0x20 != 0) + if( (sak & 0x20) == 0) return 2; - // RATS, Request for answer to select - if ( !no_rats ) { + // RATS, Request for answer to select + if ( !no_rats ) { - AddCrc14A(rats, 2); - ReaderTransmit(rats, sizeof(rats), NULL); - len = ReaderReceive(resp, resp_par); + AddCrc14A(rats, 2); + ReaderTransmit(rats, sizeof(rats), NULL); + len = ReaderReceive(resp, resp_par); - if (!len) return 0; + if (!len) return 0; - if (p_card) { - memcpy(p_card->ats, resp, sizeof(p_card->ats)); - p_card->ats_len = len; - } + if (p_card) { + memcpy(p_card->ats, resp, sizeof(p_card->ats)); + p_card->ats_len = len; + } - // reset the PCB block number - iso14_pcb_blocknum = 0; + // reset the PCB block number + iso14_pcb_blocknum = 0; - // set default timeout and delay next transfer based on ATS - iso14a_set_ATS_times(resp); - } - return 1; + // set default timeout and delay next transfer based on ATS + iso14a_set_ATS_times(resp); + } + return 1; } int iso14443a_fast_select_card(uint8_t *uid_ptr, uint8_t num_cascades) { - uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT,0x20 }; - uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; - uint8_t resp[5] = {0}; // theoretically. A usual RATS will be much smaller - uint8_t resp_par[1] = {0}; - uint8_t uid_resp[4] = {0}; + uint8_t sel_all[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT,0x20 }; + uint8_t sel_uid[] = { ISO14443A_CMD_ANTICOLL_OR_SELECT,0x70,0x00,0x00,0x00,0x00,0x00,0x00,0x00}; + uint8_t resp[5] = {0}; // theoretically. A usual RATS will be much smaller + uint8_t resp_par[1] = {0}; + uint8_t uid_resp[4] = {0}; - uint8_t sak = 0x04; // cascade uid - int cascade_level = 0; + uint8_t sak = 0x04; // cascade uid + int cascade_level = 0; - if (!GetATQA(resp, resp_par)) { - return 0; - } + if (!GetATQA(resp, resp_par)) { + return 0; + } - // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in - // which case we need to make a cascade 2 request and select - this is a long UID - // While the UID is not complete, the 3nd bit (from the right) is set in the SAK. - for(; sak & 0x04; cascade_level++) { - // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97) - sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2; + // OK we will select at least at cascade 1, lets see if first byte of UID was 0x88 in + // which case we need to make a cascade 2 request and select - this is a long UID + // While the UID is not complete, the 3nd bit (from the right) is set in the SAK. + for(; sak & 0x04; cascade_level++) { + // SELECT_* (L1: 0x93, L2: 0x95, L3: 0x97) + sel_uid[0] = sel_all[0] = 0x93 + cascade_level * 2; - if (cascade_level < num_cascades - 1) { - uid_resp[0] = 0x88; - memcpy(uid_resp+1, uid_ptr+cascade_level*3, 3); - } else { - memcpy(uid_resp, uid_ptr+cascade_level*3, 4); - } + if (cascade_level < num_cascades - 1) { + uid_resp[0] = 0x88; + memcpy(uid_resp+1, uid_ptr+cascade_level*3, 3); + } else { + memcpy(uid_resp, uid_ptr+cascade_level*3, 4); + } - // Construct SELECT UID command - //sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC) - memcpy(sel_uid+2, uid_resp, 4); // the UID received during anticollision, or the provided UID - sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC - AddCrc14A(sel_uid, 7); // calculate and add CRC - ReaderTransmit(sel_uid, sizeof(sel_uid), NULL); + // Construct SELECT UID command + //sel_uid[1] = 0x70; // transmitting a full UID (1 Byte cmd, 1 Byte NVB, 4 Byte UID, 1 Byte BCC, 2 Bytes CRC) + memcpy(sel_uid+2, uid_resp, 4); // the UID received during anticollision, or the provided UID + sel_uid[6] = sel_uid[2] ^ sel_uid[3] ^ sel_uid[4] ^ sel_uid[5]; // calculate and add BCC + AddCrc14A(sel_uid, 7); // calculate and add CRC + ReaderTransmit(sel_uid, sizeof(sel_uid), NULL); - // Receive the SAK - if (!ReaderReceive(resp, resp_par)) return 0; + // Receive the SAK + if (!ReaderReceive(resp, resp_par)) return 0; - sak = resp[0]; + sak = resp[0]; - // Test if more parts of the uid are coming - if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) { - // Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of: - // http://www.nxp.com/documents/application_note/AN10927.pdf - uid_resp[0] = uid_resp[1]; - uid_resp[1] = uid_resp[2]; - uid_resp[2] = uid_resp[3]; - } - } - return 1; + // Test if more parts of the uid are coming + if ((sak & 0x04) /* && uid_resp[0] == 0x88 */) { + // Remove first byte, 0x88 is not an UID byte, it CT, see page 3 of: + // http://www.nxp.com/documents/application_note/AN10927.pdf + uid_resp[0] = uid_resp[1]; + uid_resp[1] = uid_resp[2]; + uid_resp[2] = uid_resp[3]; + } + } + return 1; } void iso14443a_setup(uint8_t fpga_minor_mode) { - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - // Set up the synchronous serial port - FpgaSetupSsc(); - // connect Demodulated Signal to ADC: - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + // Set up the synchronous serial port + FpgaSetupSsc(); + // connect Demodulated Signal to ADC: + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - LED_D_OFF(); - // Signal field is on with the appropriate LED - if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD || - fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN) - LED_D_ON(); + LED_D_OFF(); + // Signal field is on with the appropriate LED + if (fpga_minor_mode == FPGA_HF_ISO14443A_READER_MOD || + fpga_minor_mode == FPGA_HF_ISO14443A_READER_LISTEN) + LED_D_ON(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode); - SpinDelay(100); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_ISO14443A | fpga_minor_mode); + SpinDelay(100); - // Start the timer - StartCountSspClk(); + // Start the timer + StartCountSspClk(); - // Prepare the demodulation functions - DemodReset(); - UartReset(); - NextTransferTime = 2 * DELAY_ARM2AIR_AS_READER; - iso14a_set_timeout(1060); // 106 * 10ms default + // Prepare the demodulation functions + DemodReset(); + UartReset(); + NextTransferTime = 2 * DELAY_ARM2AIR_AS_READER; + iso14a_set_timeout(1060); // 106 * 10ms default } /* Peter Fillmore 2015 @@ -2220,187 +2220,187 @@ b5,b6 = 00 - DESELECT 11 - WTX */ int iso14_apdu(uint8_t *cmd, uint16_t cmd_len, bool send_chaining, void *data, uint8_t *res) { - uint8_t parity[MAX_PARITY_SIZE] = {0x00}; - uint8_t real_cmd[cmd_len + 4]; + uint8_t parity[MAX_PARITY_SIZE] = {0x00}; + uint8_t real_cmd[cmd_len + 4]; - if (cmd_len) { - // ISO 14443 APDU frame: PCB [CID] [NAD] APDU CRC PCB=0x02 - real_cmd[0] = 0x02; // bnr,nad,cid,chn=0; i-block(0x00) - if (send_chaining) { - real_cmd[0] |= 0x10; - } - // put block number into the PCB - real_cmd[0] |= iso14_pcb_blocknum; - memcpy(real_cmd + 1, cmd, cmd_len); - } else { - // R-block. ACK - real_cmd[0] = 0xA2; // r-block + ACK - real_cmd[0] |= iso14_pcb_blocknum; - } - AddCrc14A(real_cmd, cmd_len + 1); + if (cmd_len) { + // ISO 14443 APDU frame: PCB [CID] [NAD] APDU CRC PCB=0x02 + real_cmd[0] = 0x02; // bnr,nad,cid,chn=0; i-block(0x00) + if (send_chaining) { + real_cmd[0] |= 0x10; + } + // put block number into the PCB + real_cmd[0] |= iso14_pcb_blocknum; + memcpy(real_cmd + 1, cmd, cmd_len); + } else { + // R-block. ACK + real_cmd[0] = 0xA2; // r-block + ACK + real_cmd[0] |= iso14_pcb_blocknum; + } + AddCrc14A(real_cmd, cmd_len + 1); - ReaderTransmit(real_cmd, cmd_len + 3, NULL); + ReaderTransmit(real_cmd, cmd_len + 3, NULL); - size_t len = ReaderReceive(data, parity); - uint8_t *data_bytes = (uint8_t *) data; + size_t len = ReaderReceive(data, parity); + uint8_t *data_bytes = (uint8_t *) data; - if (!len) { - return 0; //DATA LINK ERROR - } else{ - // S-Block WTX - while(len && ((data_bytes[0] & 0xF2) == 0xF2)) { - uint32_t save_iso14a_timeout = iso14a_get_timeout(); - // temporarily increase timeout - iso14a_set_timeout( MAX((data_bytes[1] & 0x3f) * save_iso14a_timeout, MAX_ISO14A_TIMEOUT) ); - // Transmit WTX back - // byte1 - WTXM [1..59]. command FWT=FWT*WTXM - data_bytes[1] = data_bytes[1] & 0x3f; // 2 high bits mandatory set to 0b - // now need to fix CRC. - AddCrc14A(data_bytes, len - 2); - // transmit S-Block - ReaderTransmit(data_bytes, len, NULL); - // retrieve the result again (with increased timeout) - len = ReaderReceive(data, parity); - data_bytes = data; - // restore timeout - iso14a_set_timeout(save_iso14a_timeout); - } + if (!len) { + return 0; //DATA LINK ERROR + } else{ + // S-Block WTX + while(len && ((data_bytes[0] & 0xF2) == 0xF2)) { + uint32_t save_iso14a_timeout = iso14a_get_timeout(); + // temporarily increase timeout + iso14a_set_timeout( MAX((data_bytes[1] & 0x3f) * save_iso14a_timeout, MAX_ISO14A_TIMEOUT) ); + // Transmit WTX back + // byte1 - WTXM [1..59]. command FWT=FWT*WTXM + data_bytes[1] = data_bytes[1] & 0x3f; // 2 high bits mandatory set to 0b + // now need to fix CRC. + AddCrc14A(data_bytes, len - 2); + // transmit S-Block + ReaderTransmit(data_bytes, len, NULL); + // retrieve the result again (with increased timeout) + len = ReaderReceive(data, parity); + data_bytes = data; + // restore timeout + iso14a_set_timeout(save_iso14a_timeout); + } - // if we received an I- or R(ACK)-Block with a block number equal to the - // current block number, toggle the current block number - if (len >= 3 // PCB+CRC = 3 bytes - && ((data_bytes[0] & 0xC0) == 0 // I-Block - || (data_bytes[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0 - && (data_bytes[0] & 0x01) == iso14_pcb_blocknum) // equal block numbers - { - iso14_pcb_blocknum ^= 1; - } + // if we received an I- or R(ACK)-Block with a block number equal to the + // current block number, toggle the current block number + if (len >= 3 // PCB+CRC = 3 bytes + && ((data_bytes[0] & 0xC0) == 0 // I-Block + || (data_bytes[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0 + && (data_bytes[0] & 0x01) == iso14_pcb_blocknum) // equal block numbers + { + iso14_pcb_blocknum ^= 1; + } - // if we received I-block with chaining we need to send ACK and receive another block of data - if (res) - *res = data_bytes[0]; + // if we received I-block with chaining we need to send ACK and receive another block of data + if (res) + *res = data_bytes[0]; - // crc check - if (len >= 3 && !check_crc(CRC_14443_A, data_bytes, len)) { - return -1; - } + // crc check + if (len >= 3 && !check_crc(CRC_14443_A, data_bytes, len)) { + return -1; + } - } + } - if (len) { - // cut frame byte - len -= 1; - // memmove(data_bytes, data_bytes + 1, len); - for (int i = 0; i < len; i++) - data_bytes[i] = data_bytes[i + 1]; - } + if (len) { + // cut frame byte + len -= 1; + // memmove(data_bytes, data_bytes + 1, len); + for (int i = 0; i < len; i++) + data_bytes[i] = data_bytes[i + 1]; + } - return len; + return len; } //----------------------------------------------------------------------------- // Read an ISO 14443a tag. Send out commands and store answers. //----------------------------------------------------------------------------- -// arg0 iso_14a flags -// arg1 high :: number of bits, if you want to send 7bits etc -// low :: len of commandbytes -// arg2 timeout +// arg0 iso_14a flags +// arg1 high :: number of bits, if you want to send 7bits etc +// low :: len of commandbytes +// arg2 timeout // d.asBytes command bytes to send void ReaderIso14443a(UsbCommand *c) { - iso14a_command_t param = c->arg[0]; - size_t len = c->arg[1] & 0xffff; - size_t lenbits = c->arg[1] >> 16; - uint32_t timeout = c->arg[2]; - uint8_t *cmd = c->d.asBytes; - uint32_t arg0 = 0; - uint8_t buf[USB_CMD_DATA_SIZE] = {0x00}; - uint8_t par[MAX_PARITY_SIZE] = {0x00}; + iso14a_command_t param = c->arg[0]; + size_t len = c->arg[1] & 0xffff; + size_t lenbits = c->arg[1] >> 16; + uint32_t timeout = c->arg[2]; + uint8_t *cmd = c->d.asBytes; + uint32_t arg0 = 0; + uint8_t buf[USB_CMD_DATA_SIZE] = {0x00}; + uint8_t par[MAX_PARITY_SIZE] = {0x00}; - if ((param & ISO14A_CONNECT)) - clear_trace(); + if ((param & ISO14A_CONNECT)) + clear_trace(); - set_tracing(true); + set_tracing(true); - if ((param & ISO14A_REQUEST_TRIGGER)) - iso14a_set_trigger(true); + if ((param & ISO14A_REQUEST_TRIGGER)) + iso14a_set_trigger(true); - if ((param & ISO14A_CONNECT)) { - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + if ((param & ISO14A_CONNECT)) { + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - // notify client selecting status. - // if failed selecting, turn off antenna and quite. - if( !(param & ISO14A_NO_SELECT) ) { - iso14a_card_select_t *card = (iso14a_card_select_t*)buf; - arg0 = iso14443a_select_card(NULL, card, NULL, true, 0, param & ISO14A_NO_RATS ); - cmd_send(CMD_ACK, arg0, card->uidlen, 0, buf, sizeof(iso14a_card_select_t)); - if ( arg0 == 0 ) - goto OUT; - } - } + // notify client selecting status. + // if failed selecting, turn off antenna and quite. + if( !(param & ISO14A_NO_SELECT) ) { + iso14a_card_select_t *card = (iso14a_card_select_t*)buf; + arg0 = iso14443a_select_card(NULL, card, NULL, true, 0, param & ISO14A_NO_RATS ); + cmd_send(CMD_ACK, arg0, card->uidlen, 0, buf, sizeof(iso14a_card_select_t)); + if ( arg0 == 0 ) + goto OUT; + } + } - if ((param & ISO14A_SET_TIMEOUT)) - iso14a_set_timeout(timeout); + if ((param & ISO14A_SET_TIMEOUT)) + iso14a_set_timeout(timeout); - if ((param & ISO14A_APDU)) { - uint8_t res; - arg0 = iso14_apdu(cmd, len, (param & ISO14A_SEND_CHAINING), buf, &res); - cmd_send(CMD_ACK, arg0, res, 0, buf, sizeof(buf)); - } + if ((param & ISO14A_APDU)) { + uint8_t res; + arg0 = iso14_apdu(cmd, len, (param & ISO14A_SEND_CHAINING), buf, &res); + cmd_send(CMD_ACK, arg0, res, 0, buf, sizeof(buf)); + } - if ((param & ISO14A_RAW)) { + if ((param & ISO14A_RAW)) { - if ((param & ISO14A_APPEND_CRC)) { - // Don't append crc on empty bytearray... - if ( len > 0 ) { - if ((param & ISO14A_TOPAZMODE)) - AddCrc14B(cmd, len); - else - AddCrc14A(cmd, len); + if ((param & ISO14A_APPEND_CRC)) { + // Don't append crc on empty bytearray... + if ( len > 0 ) { + if ((param & ISO14A_TOPAZMODE)) + AddCrc14B(cmd, len); + else + AddCrc14A(cmd, len); - len += 2; - if (lenbits) lenbits += 16; - } - } + len += 2; + if (lenbits) lenbits += 16; + } + } - if (lenbits > 0) { // want to send a specific number of bits (e.g. short commands) - if ((param & ISO14A_TOPAZMODE)) { - int bits_to_send = lenbits; - uint16_t i = 0; - ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 7), NULL, NULL); // first byte is always short (7bits) and no parity - bits_to_send -= 7; - while (bits_to_send > 0) { - ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 8), NULL, NULL); // following bytes are 8 bit and no parity - bits_to_send -= 8; - } - } else { - GetParity(cmd, lenbits/8, par); - ReaderTransmitBitsPar(cmd, lenbits, par, NULL); // bytes are 8 bit with odd parity - } - } else { // want to send complete bytes only - if ((param & ISO14A_TOPAZMODE)) { - uint16_t i = 0; - ReaderTransmitBitsPar(&cmd[i++], 7, NULL, NULL); // first byte: 7 bits, no paritiy - while (i < len) { - ReaderTransmitBitsPar(&cmd[i++], 8, NULL, NULL); // following bytes: 8 bits, no paritiy - } - } else { - ReaderTransmit(cmd, len, NULL); // 8 bits, odd parity - } - } - arg0 = ReaderReceive(buf, par); - cmd_send(CMD_ACK, arg0, 0, 0, buf, sizeof(buf)); - } + if (lenbits > 0) { // want to send a specific number of bits (e.g. short commands) + if ((param & ISO14A_TOPAZMODE)) { + int bits_to_send = lenbits; + uint16_t i = 0; + ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 7), NULL, NULL); // first byte is always short (7bits) and no parity + bits_to_send -= 7; + while (bits_to_send > 0) { + ReaderTransmitBitsPar(&cmd[i++], MIN(bits_to_send, 8), NULL, NULL); // following bytes are 8 bit and no parity + bits_to_send -= 8; + } + } else { + GetParity(cmd, lenbits/8, par); + ReaderTransmitBitsPar(cmd, lenbits, par, NULL); // bytes are 8 bit with odd parity + } + } else { // want to send complete bytes only + if ((param & ISO14A_TOPAZMODE)) { + uint16_t i = 0; + ReaderTransmitBitsPar(&cmd[i++], 7, NULL, NULL); // first byte: 7 bits, no paritiy + while (i < len) { + ReaderTransmitBitsPar(&cmd[i++], 8, NULL, NULL); // following bytes: 8 bits, no paritiy + } + } else { + ReaderTransmit(cmd, len, NULL); // 8 bits, odd parity + } + } + arg0 = ReaderReceive(buf, par); + cmd_send(CMD_ACK, arg0, 0, 0, buf, sizeof(buf)); + } - if ((param & ISO14A_REQUEST_TRIGGER)) - iso14a_set_trigger(false); + if ((param & ISO14A_REQUEST_TRIGGER)) + iso14a_set_trigger(false); - if ((param & ISO14A_NO_DISCONNECT)) - return; + if ((param & ISO14A_NO_DISCONNECT)) + return; OUT: - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - set_tracing(false); - LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + set_tracing(false); + LEDsoff(); } // Determine the distance between two nonces. @@ -2408,26 +2408,26 @@ OUT: // Therefore try in alternating directions. int32_t dist_nt(uint32_t nt1, uint32_t nt2) { - if (nt1 == nt2) return 0; + if (nt1 == nt2) return 0; - uint32_t nttmp1 = nt1; - uint32_t nttmp2 = nt2; + uint32_t nttmp1 = nt1; + uint32_t nttmp2 = nt2; - for (uint16_t i = 1; i < 32768; i++) { - nttmp1 = prng_successor(nttmp1, 1); - if (nttmp1 == nt2) return i; + for (uint16_t i = 1; i < 32768; i++) { + nttmp1 = prng_successor(nttmp1, 1); + if (nttmp1 == nt2) return i; - nttmp2 = prng_successor(nttmp2, 1); - if (nttmp2 == nt1) return -i; - } + nttmp2 = prng_successor(nttmp2, 1); + if (nttmp2 == nt1) return -i; + } - return(-99999); // either nt1 or nt2 are invalid nonces + return(-99999); // either nt1 or nt2 are invalid nonces } -#define PRNG_SEQUENCE_LENGTH (1 << 16) -#define MAX_UNEXPECTED_RANDOM 4 // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up. -#define MAX_SYNC_TRIES 32 +#define PRNG_SEQUENCE_LENGTH (1 << 16) +#define MAX_UNEXPECTED_RANDOM 4 // maximum number of unexpected (i.e. real) random numbers when trying to sync. Then give up. +#define MAX_SYNC_TRIES 32 //----------------------------------------------------------------------------- // Recover several bits of the cypher stream. This implements (first stages of) @@ -2437,259 +2437,259 @@ int32_t dist_nt(uint32_t nt1, uint32_t nt2) { //----------------------------------------------------------------------------- void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { - iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); + iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); - BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); - set_tracing(true); + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); - uint8_t mf_auth[] = { keytype, block, 0x00, 0x00 }; - uint8_t mf_nr_ar[] = {0,0,0,0,0,0,0,0}; - uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; - uint8_t par_list[8] = {0,0,0,0,0,0,0,0}; - uint8_t ks_list[8] = {0,0,0,0,0,0,0,0}; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - uint8_t par[1] = {0}; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough - uint8_t nt_diff = 0; + uint8_t mf_auth[] = { keytype, block, 0x00, 0x00 }; + uint8_t mf_nr_ar[] = {0,0,0,0,0,0,0,0}; + uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; + uint8_t par_list[8] = {0,0,0,0,0,0,0,0}; + uint8_t ks_list[8] = {0,0,0,0,0,0,0,0}; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + uint8_t par[1] = {0}; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough + uint8_t nt_diff = 0; - uint32_t nt = 0, previous_nt = 0, cuid = 0; - uint32_t sync_time = GetCountSspClk() & 0xfffffff8; + uint32_t nt = 0, previous_nt = 0, cuid = 0; + uint32_t sync_time = GetCountSspClk() & 0xfffffff8; - int32_t catch_up_cycles = 0; - int32_t last_catch_up = 0; - int32_t isOK = 0; + int32_t catch_up_cycles = 0; + int32_t last_catch_up = 0; + int32_t isOK = 0; - uint16_t elapsed_prng_sequences = 1; - uint16_t consecutive_resyncs = 0; - uint16_t unexpected_random = 0; - uint16_t sync_tries = 0; + uint16_t elapsed_prng_sequences = 1; + uint16_t consecutive_resyncs = 0; + uint16_t unexpected_random = 0; + uint16_t sync_tries = 0; - bool have_uid = false; - bool received_nack; - uint8_t cascade_levels = 0; + bool have_uid = false; + bool received_nack; + uint8_t cascade_levels = 0; - // static variables here, is re-used in the next call - static uint32_t nt_attacked = 0; - static int32_t sync_cycles = 0; - static uint8_t par_low = 0; - static uint8_t mf_nr_ar3 = 0; + // static variables here, is re-used in the next call + static uint32_t nt_attacked = 0; + static int32_t sync_cycles = 0; + static uint8_t par_low = 0; + static uint8_t mf_nr_ar3 = 0; - AddCrc14A(mf_auth, 2); + AddCrc14A(mf_auth, 2); - if (first_try) { - sync_cycles = PRNG_SEQUENCE_LENGTH; // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). - nt_attacked = 0; - mf_nr_ar3 = 0; - par_low = 0; - } else { - // we were unsuccessful on a previous call. - // Try another READER nonce (first 3 parity bits remain the same) - mf_nr_ar3++; - mf_nr_ar[3] = mf_nr_ar3; - par[0] = par_low; - } + if (first_try) { + sync_cycles = PRNG_SEQUENCE_LENGTH; // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). + nt_attacked = 0; + mf_nr_ar3 = 0; + par_low = 0; + } else { + // we were unsuccessful on a previous call. + // Try another READER nonce (first 3 parity bits remain the same) + mf_nr_ar3++; + mf_nr_ar[3] = mf_nr_ar3; + par[0] = par_low; + } - LED_C_ON(); - uint16_t i; - for (i = 0; true; ++i) { + LED_C_ON(); + uint16_t i; + for (i = 0; true; ++i) { - received_nack = false; + received_nack = false; - WDT_HIT(); + WDT_HIT(); - // Test if the action was cancelled - if (BUTTON_PRESS()) { - isOK = -1; - break; - } + // Test if the action was cancelled + if (BUTTON_PRESS()) { + isOK = -1; + break; + } - // this part is from Piwi's faster nonce collecting part in Hardnested. - if (!have_uid) { // need a full select cycle to get the uid first - iso14a_card_select_t card_info; - if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card (ALL)"); - continue; - } - switch (card_info.uidlen) { - case 4 : cascade_levels = 1; break; - case 7 : cascade_levels = 2; break; - case 10: cascade_levels = 3; break; - default: break; - } - have_uid = true; - } else { // no need for anticollision. We can directly select the card - if (!iso14443a_fast_select_card(uid, cascade_levels)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card (UID)"); - continue; - } - } + // this part is from Piwi's faster nonce collecting part in Hardnested. + if (!have_uid) { // need a full select cycle to get the uid first + iso14a_card_select_t card_info; + if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card (ALL)"); + continue; + } + switch (card_info.uidlen) { + case 4 : cascade_levels = 1; break; + case 7 : cascade_levels = 2; break; + case 10: cascade_levels = 3; break; + default: break; + } + have_uid = true; + } else { // no need for anticollision. We can directly select the card + if (!iso14443a_fast_select_card(uid, cascade_levels)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card (UID)"); + continue; + } + } - elapsed_prng_sequences = 1; + elapsed_prng_sequences = 1; - // Sending timeslot of ISO14443a frame - sync_time = (sync_time & 0xfffffff8 ) + sync_cycles + catch_up_cycles; - catch_up_cycles = 0; + // Sending timeslot of ISO14443a frame + sync_time = (sync_time & 0xfffffff8 ) + sync_cycles + catch_up_cycles; + catch_up_cycles = 0; - #define SYNC_TIME_BUFFER 16 // if there is only SYNC_TIME_BUFFER left before next planned sync, wait for next PRNG cycle + #define SYNC_TIME_BUFFER 16 // if there is only SYNC_TIME_BUFFER left before next planned sync, wait for next PRNG cycle - // if we missed the sync time already or are about to miss it, advance to the next nonce repeat - while ( sync_time < GetCountSspClk() + SYNC_TIME_BUFFER) { - ++elapsed_prng_sequences; - sync_time = (sync_time & 0xfffffff8 ) + sync_cycles; - } + // if we missed the sync time already or are about to miss it, advance to the next nonce repeat + while ( sync_time < GetCountSspClk() + SYNC_TIME_BUFFER) { + ++elapsed_prng_sequences; + 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); - // Receive the (4 Byte) "random" TAG nonce - if (!ReaderReceive(receivedAnswer, receivedAnswerPar)) - continue; + // Receive the (4 Byte) "random" TAG nonce + if (!ReaderReceive(receivedAnswer, receivedAnswerPar)) + continue; - previous_nt = nt; - nt = bytes_to_num(receivedAnswer, 4); + previous_nt = nt; + nt = bytes_to_num(receivedAnswer, 4); - // Transmit reader nonce with fake par - ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); + // Transmit reader nonce with fake par + ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); - // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding - if (ReaderReceive(receivedAnswer, receivedAnswerPar)) - received_nack = true; + // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding + if (ReaderReceive(receivedAnswer, receivedAnswerPar)) + received_nack = true; - // we didn't calibrate our clock yet, - // iceman: has to be calibrated every time. - if (previous_nt && !nt_attacked) { + // we didn't calibrate our clock yet, + // iceman: has to be calibrated every time. + if (previous_nt && !nt_attacked) { - int nt_distance = dist_nt(previous_nt, nt); + int nt_distance = dist_nt(previous_nt, nt); - // if no distance between, then we are in sync. - if (nt_distance == 0) { - nt_attacked = nt; - } else { - if (nt_distance == -99999) { // invalid nonce received - unexpected_random++; - if (unexpected_random > MAX_UNEXPECTED_RANDOM) { - isOK = -3; // Card has an unpredictable PRNG. Give up - break; - } else { - continue; // continue trying... - } - } + // if no distance between, then we are in sync. + if (nt_distance == 0) { + nt_attacked = nt; + } else { + if (nt_distance == -99999) { // invalid nonce received + unexpected_random++; + if (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) { - isOK = -4; // Card's PRNG runs at an unexpected frequency or resets unexpectedly - break; - } + if (++sync_tries > MAX_SYNC_TRIES) { + isOK = -4; // Card's PRNG runs at an unexpected frequency or resets unexpectedly + break; + } - sync_cycles = (sync_cycles - nt_distance)/elapsed_prng_sequences; + sync_cycles = (sync_cycles - nt_distance)/elapsed_prng_sequences; - // no negative sync_cycles - if (sync_cycles <= 0) sync_cycles += PRNG_SEQUENCE_LENGTH; + // no negative sync_cycles + if (sync_cycles <= 0) sync_cycles += PRNG_SEQUENCE_LENGTH; - // reset sync_cycles - if (sync_cycles > PRNG_SEQUENCE_LENGTH * 2 ) { - sync_cycles = PRNG_SEQUENCE_LENGTH; - sync_time = GetCountSspClk() & 0xfffffff8; - } + // reset sync_cycles + if (sync_cycles > PRNG_SEQUENCE_LENGTH * 2 ) { + sync_cycles = PRNG_SEQUENCE_LENGTH; + sync_time = GetCountSspClk() & 0xfffffff8; + } - if (MF_DBGLEVEL >= 4) - Dbprintf("calibrating in cycle %d. nt_distance=%d, elapsed_prng_sequences=%d, new sync_cycles: %d\n", i, nt_distance, elapsed_prng_sequences, sync_cycles); + if (MF_DBGLEVEL >= 4) + Dbprintf("calibrating in cycle %d. nt_distance=%d, elapsed_prng_sequences=%d, new sync_cycles: %d\n", i, nt_distance, elapsed_prng_sequences, sync_cycles); - LED_B_OFF(); - continue; - } - } - LED_B_OFF(); + LED_B_OFF(); + continue; + } + } + LED_B_OFF(); - if ( (nt != nt_attacked) && nt_attacked) { // we somehow lost sync. Try to catch up again... + if ( (nt != nt_attacked) && nt_attacked) { // we somehow lost sync. Try to catch up again... - catch_up_cycles = -dist_nt(nt_attacked, nt); - if (catch_up_cycles == 99999) { // invalid nonce received. Don't resync on that one. - catch_up_cycles = 0; - continue; - } - // average? - catch_up_cycles /= elapsed_prng_sequences; + catch_up_cycles = -dist_nt(nt_attacked, nt); + if (catch_up_cycles == 99999) { // invalid nonce received. Don't resync on that one. + catch_up_cycles = 0; + continue; + } + // average? + catch_up_cycles /= elapsed_prng_sequences; - if (catch_up_cycles == last_catch_up) { - consecutive_resyncs++; - } else { - last_catch_up = catch_up_cycles; - consecutive_resyncs = 0; - } + if (catch_up_cycles == last_catch_up) { + consecutive_resyncs++; + } else { + last_catch_up = catch_up_cycles; + consecutive_resyncs = 0; + } - if (consecutive_resyncs < 3) { - if (MF_DBGLEVEL >= 4) { - Dbprintf("Lost sync in cycle %d. nt_distance=%d. Consecutive Resyncs = %d. Trying one time catch up...\n", i, catch_up_cycles, consecutive_resyncs); - } - } else { - sync_cycles += catch_up_cycles; + if (consecutive_resyncs < 3) { + if (MF_DBGLEVEL >= 4) { + Dbprintf("Lost sync in cycle %d. nt_distance=%d. Consecutive Resyncs = %d. Trying one time catch up...\n", i, catch_up_cycles, consecutive_resyncs); + } + } else { + sync_cycles += catch_up_cycles; - if (MF_DBGLEVEL >= 4) - Dbprintf("Lost sync in cycle %d for the fourth time consecutively (nt_distance = %d). Adjusting sync_cycles to %d.\n", i, catch_up_cycles, sync_cycles); + if (MF_DBGLEVEL >= 4) + Dbprintf("Lost sync in cycle %d for the fourth time consecutively (nt_distance = %d). Adjusting sync_cycles to %d.\n", i, catch_up_cycles, sync_cycles); - last_catch_up = 0; - catch_up_cycles = 0; - consecutive_resyncs = 0; - } - continue; - } + last_catch_up = 0; + catch_up_cycles = 0; + consecutive_resyncs = 0; + } + continue; + } - // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding - if (received_nack) { - catch_up_cycles = 8; // the PRNG is delayed by 8 cycles due to the NAC (4Bits = 0x05 encrypted) transfer + // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding + if (received_nack) { + catch_up_cycles = 8; // the PRNG is delayed by 8 cycles due to the NAC (4Bits = 0x05 encrypted) transfer - if (nt_diff == 0) - par_low = par[0] & 0xE0; // there is no need to check all parities for other nt_diff. Parity Bits for mf_nr_ar[0..2] won't change + if (nt_diff == 0) + par_low = par[0] & 0xE0; // there is no need to check all parities for other nt_diff. Parity Bits for mf_nr_ar[0..2] won't change - par_list[nt_diff] = reflect8(par[0]); - ks_list[nt_diff] = receivedAnswer[0] ^ 0x05; // xor with NACK value to get keystream + par_list[nt_diff] = reflect8(par[0]); + ks_list[nt_diff] = receivedAnswer[0] ^ 0x05; // xor with NACK value to get keystream - // Test if the information is complete - if (nt_diff == 0x07) { - isOK = 1; - break; - } + // Test if the information is complete + if (nt_diff == 0x07) { + isOK = 1; + break; + } - nt_diff = (nt_diff + 1) & 0x07; - mf_nr_ar[3] = (mf_nr_ar[3] & 0x1F) | (nt_diff << 5); - par[0] = par_low; + nt_diff = (nt_diff + 1) & 0x07; + mf_nr_ar[3] = (mf_nr_ar[3] & 0x1F) | (nt_diff << 5); + par[0] = par_low; - } else { - // No NACK. - if (nt_diff == 0 && first_try) { - par[0]++; - if (par[0] == 0) { // tried all 256 possible parities without success. Card doesn't send NACK. - isOK = -2; - break; - } - } else { - // Why this? - par[0] = ((par[0] & 0x1F) + 1) | par_low; - } - } + } else { + // No NACK. + if (nt_diff == 0 && first_try) { + par[0]++; + if (par[0] == 0) { // tried all 256 possible parities without success. Card doesn't send NACK. + isOK = -2; + break; + } + } else { + // Why this? + par[0] = ((par[0] & 0x1F) + 1) | par_low; + } + } - // reset the resyncs since we got a complete transaction on right time. - consecutive_resyncs = 0; - } // end for loop + // reset the resyncs since we got a complete transaction on right time. + consecutive_resyncs = 0; + } // end for loop - mf_nr_ar[3] &= 0x1F; + mf_nr_ar[3] &= 0x1F; - if (MF_DBGLEVEL >= 4) Dbprintf("Number of sent auth requestes: %u", i); + if (MF_DBGLEVEL >= 4) Dbprintf("Number of sent auth requestes: %u", i); - uint8_t buf[32] = {0x00}; - memset(buf, 0x00, sizeof(buf)); - num_to_bytes(cuid, 4, buf); - num_to_bytes(nt, 4, buf + 4); - memcpy(buf + 8, par_list, 8); - memcpy(buf + 16, ks_list, 8); - memcpy(buf + 24, mf_nr_ar, 8); + uint8_t buf[32] = {0x00}; + memset(buf, 0x00, sizeof(buf)); + num_to_bytes(cuid, 4, buf); + num_to_bytes(nt, 4, buf + 4); + memcpy(buf + 8, par_list, 8); + memcpy(buf + 16, ks_list, 8); + memcpy(buf + 24, mf_nr_ar, 8); - cmd_send(CMD_ACK, isOK, 0, 0, buf, sizeof(buf) ); + cmd_send(CMD_ACK, isOK, 0, 0, buf, sizeof(buf) ); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); } /* @@ -2697,819 +2697,820 @@ void ReaderMifare(bool first_try, uint8_t block, uint8_t keytype ) { * Thanks to @doegox for the feedback and new approaches. */ void DetectNACKbug() { - uint8_t mf_auth[] = {0x60, 0x00, 0xF5, 0x7B}; - uint8_t mf_nr_ar[] = {0,0,0,0,0,0,0,0}; - uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - uint8_t par[1] = {0}; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough + uint8_t mf_auth[] = {0x60, 0x00, 0xF5, 0x7B}; + uint8_t mf_nr_ar[] = {0,0,0,0,0,0,0,0}; + uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + uint8_t par[1] = {0}; // maximum 8 Bytes to be sent here, 1 byte parity is therefore enough - uint32_t nt = 0, previous_nt = 0, nt_attacked = 0, cuid = 0; - int32_t isOK = 0, catch_up_cycles = 0, last_catch_up = 0; - uint8_t cascade_levels = 0, num_nacks = 0; - uint16_t elapsed_prng_sequences = 1; - uint16_t consecutive_resyncs = 0; - uint16_t unexpected_random = 0; - uint16_t sync_tries = 0; - uint32_t sync_time = 0; - bool have_uid = false; - bool received_nack; + uint32_t nt = 0, previous_nt = 0, nt_attacked = 0, cuid = 0; + int32_t isOK = 0, catch_up_cycles = 0, last_catch_up = 0; + uint8_t cascade_levels = 0, num_nacks = 0; + uint16_t elapsed_prng_sequences = 1; + uint16_t consecutive_resyncs = 0; + uint16_t unexpected_random = 0; + uint16_t sync_tries = 0; + uint32_t sync_time = 0; + bool have_uid = false; + bool received_nack; - // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). - uint32_t sync_cycles = PRNG_SEQUENCE_LENGTH; + // Mifare Classic's random generator repeats every 2^16 cycles (and so do the nonces). + uint32_t sync_cycles = PRNG_SEQUENCE_LENGTH; - BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); - set_tracing(true); - iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); + iso14443a_setup(FPGA_HF_ISO14443A_READER_MOD); - sync_time = GetCountSspClk() & 0xfffffff8; + sync_time = GetCountSspClk() & 0xfffffff8; - LED_C_ON(); - uint16_t i; - for (i = 1; true; ++i) { + LED_C_ON(); + uint16_t i; + for (i = 1; true; ++i) { - received_nack = false; + received_nack = false; - // Cards always leaks a NACK, no matter the parity - if ((i==10) && (num_nacks == i-1)) { - isOK = 2; - break; - } + // Cards always leaks a NACK, no matter the parity + if ((i==10) && (num_nacks == i-1)) { + isOK = 2; + break; + } - WDT_HIT(); + WDT_HIT(); - // Test if the action was cancelled - if (BUTTON_PRESS()) { - isOK = 99; - break; - } + // Test if the action was cancelled + if (BUTTON_PRESS()) { + isOK = 99; + break; + } - // this part is from Piwi's faster nonce collecting part in Hardnested. - if (!have_uid) { // need a full select cycle to get the uid first - iso14a_card_select_t card_info; - if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card (ALL)"); - continue; - } - switch (card_info.uidlen) { - case 4 : cascade_levels = 1; break; - case 7 : cascade_levels = 2; break; - case 10: cascade_levels = 3; break; - default: break; - } - have_uid = true; - } else { // no need for anticollision. We can directly select the card - if (!iso14443a_fast_select_card(uid, cascade_levels)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card (UID)"); - continue; - } - } + // this part is from Piwi's faster nonce collecting part in Hardnested. + if (!have_uid) { // need a full select cycle to get the uid first + iso14a_card_select_t card_info; + if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card (ALL)"); + continue; + } + switch (card_info.uidlen) { + case 4 : cascade_levels = 1; break; + case 7 : cascade_levels = 2; break; + case 10: cascade_levels = 3; break; + default: break; + } + have_uid = true; + } else { // no need for anticollision. We can directly select the card + if (!iso14443a_fast_select_card(uid, cascade_levels)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Mifare: Can't select card (UID)"); + continue; + } + } - elapsed_prng_sequences = 1; + elapsed_prng_sequences = 1; - // Sending timeslot of ISO14443a frame - sync_time = (sync_time & 0xfffffff8 ) + sync_cycles + catch_up_cycles; - catch_up_cycles = 0; + // Sending timeslot of ISO14443a frame + 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) { - ++elapsed_prng_sequences; - sync_time = (sync_time & 0xfffffff8 ) + sync_cycles; - } + // if we missed the sync time already, advance to the next nonce repeat + while ( GetCountSspClk() > sync_time) { + ++elapsed_prng_sequences; + 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); - // Receive the (4 Byte) "random" TAG nonce - if (!ReaderReceive(receivedAnswer, receivedAnswerPar)) - continue; + // Receive the (4 Byte) "random" TAG nonce + if (!ReaderReceive(receivedAnswer, receivedAnswerPar)) + continue; - previous_nt = nt; - nt = bytes_to_num(receivedAnswer, 4); + previous_nt = nt; + nt = bytes_to_num(receivedAnswer, 4); - // Transmit reader nonce with fake par - ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); + // Transmit reader nonce with fake par + ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); - if (ReaderReceive(receivedAnswer, receivedAnswerPar)) { - received_nack = true; - num_nacks++; - // ALWAYS leak Detection. - if ( i == num_nacks ) { - continue; - } - } + if (ReaderReceive(receivedAnswer, receivedAnswerPar)) { + received_nack = true; + num_nacks++; + // ALWAYS leak Detection. + if ( i == num_nacks ) { + continue; + } + } - // we didn't calibrate our clock yet, - // iceman: has to be calibrated every time. - if (previous_nt && !nt_attacked) { + // we didn't calibrate our clock yet, + // iceman: has to be calibrated every time. + if (previous_nt && !nt_attacked) { - int nt_distance = dist_nt(previous_nt, nt); + int nt_distance = dist_nt(previous_nt, nt); - // if no distance between, then we are in sync. - if (nt_distance == 0) { - nt_attacked = nt; - } else { - if (nt_distance == -99999) { // invalid nonce received - unexpected_random++; - if (unexpected_random > MAX_UNEXPECTED_RANDOM ) { - // Card has an unpredictable PRNG. Give up - isOK = 98; - break; - } else { - if (sync_cycles <= 0) { - sync_cycles += PRNG_SEQUENCE_LENGTH; - } - continue; - } - } + // if no distance between, then we are in sync. + if (nt_distance == 0) { + nt_attacked = nt; + } else { + if (nt_distance == -99999) { // invalid nonce received + unexpected_random++; + if (unexpected_random > MAX_UNEXPECTED_RANDOM ) { + // Card has an unpredictable PRNG. Give up + isOK = 98; + break; + } else { + if (sync_cycles <= 0) { + sync_cycles += PRNG_SEQUENCE_LENGTH; + } + continue; + } + } - if (++sync_tries > MAX_SYNC_TRIES) { - isOK = 97; // Card's PRNG runs at an unexpected frequency or resets unexpectedly - break; - } + if (++sync_tries > MAX_SYNC_TRIES) { + isOK = 97; // Card's PRNG runs at an unexpected frequency or resets unexpectedly + break; + } - sync_cycles = (sync_cycles - nt_distance)/elapsed_prng_sequences; + sync_cycles = (sync_cycles - nt_distance)/elapsed_prng_sequences; - if (sync_cycles <= 0) - sync_cycles += PRNG_SEQUENCE_LENGTH; + if (sync_cycles <= 0) + sync_cycles += PRNG_SEQUENCE_LENGTH; - if (sync_cycles > PRNG_SEQUENCE_LENGTH * 2 ) { - isOK = 96; // Card's PRNG runs at an unexpected frequency or resets unexpectedly - break; - } + if (sync_cycles > PRNG_SEQUENCE_LENGTH * 2 ) { + isOK = 96; // Card's PRNG runs at an unexpected frequency or resets unexpectedly + break; + } - if (MF_DBGLEVEL >= 4) - Dbprintf("calibrating in cycle %d. nt_distance=%d, elapsed_prng_sequences=%d, new sync_cycles: %d\n", i, nt_distance, elapsed_prng_sequences, sync_cycles); + if (MF_DBGLEVEL >= 4) + Dbprintf("calibrating in cycle %d. nt_distance=%d, elapsed_prng_sequences=%d, new sync_cycles: %d\n", i, nt_distance, elapsed_prng_sequences, sync_cycles); - continue; - } - } + continue; + } + } - if ( (nt != nt_attacked) && nt_attacked) { - // we somehow lost sync. Try to catch up again... - catch_up_cycles = -dist_nt(nt_attacked, nt); + if ( (nt != nt_attacked) && nt_attacked) { + // we somehow lost sync. Try to catch up again... + catch_up_cycles = -dist_nt(nt_attacked, nt); - if (catch_up_cycles == 99999) { - // invalid nonce received. Don't resync on that one. - catch_up_cycles = 0; - continue; - } - // average? - catch_up_cycles /= elapsed_prng_sequences; + if (catch_up_cycles == 99999) { + // invalid nonce received. Don't resync on that one. + catch_up_cycles = 0; + continue; + } + // average? + catch_up_cycles /= elapsed_prng_sequences; - if (catch_up_cycles == last_catch_up) { - consecutive_resyncs++; - } else { - last_catch_up = catch_up_cycles; - consecutive_resyncs = 0; - } + if (catch_up_cycles == last_catch_up) { + consecutive_resyncs++; + } else { + last_catch_up = catch_up_cycles; + consecutive_resyncs = 0; + } - if (consecutive_resyncs < 3) { - if (MF_DBGLEVEL >= 4) { - Dbprintf("Lost sync in cycle %d. nt_distance=%d. Consecutive Resyncs = %d. Trying one time catch up...\n", i, catch_up_cycles, consecutive_resyncs); - } - } else { - sync_cycles += catch_up_cycles; + if (consecutive_resyncs < 3) { + if (MF_DBGLEVEL >= 4) { + Dbprintf("Lost sync in cycle %d. nt_distance=%d. Consecutive Resyncs = %d. Trying one time catch up...\n", i, catch_up_cycles, consecutive_resyncs); + } + } else { + sync_cycles += catch_up_cycles; - if (MF_DBGLEVEL >= 4) { - Dbprintf("Lost sync in cycle %d for the fourth time consecutively (nt_distance = %d). Adjusting sync_cycles to %d.\n", i, catch_up_cycles, sync_cycles); - Dbprintf("nt [%08x] attacted [%08x]", nt, nt_attacked ); - } - last_catch_up = 0; - catch_up_cycles = 0; - consecutive_resyncs = 0; - } - continue; - } + if (MF_DBGLEVEL >= 4) { + Dbprintf("Lost sync in cycle %d for the fourth time consecutively (nt_distance = %d). Adjusting sync_cycles to %d.\n", i, catch_up_cycles, sync_cycles); + Dbprintf("nt [%08x] attacted [%08x]", nt, nt_attacked ); + } + last_catch_up = 0; + catch_up_cycles = 0; + consecutive_resyncs = 0; + } + continue; + } - // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding - if (received_nack) - catch_up_cycles = 8; // the PRNG is delayed by 8 cycles due to the NAC (4Bits = 0x05 encrypted) transfer + // Receive answer. This will be a 4 Bit NACK when the 8 parity bits are OK after decoding + if (received_nack) + catch_up_cycles = 8; // the PRNG is delayed by 8 cycles due to the NAC (4Bits = 0x05 encrypted) transfer - // we are testing all 256 possibilities. - par[0]++; + // we are testing all 256 possibilities. + par[0]++; - // tried all 256 possible parities without success. - if (par[0] == 0) { - if ( num_nacks == 1 ) - isOK = 1; - break; - } + // tried all 256 possible parities without success. + if (par[0] == 0) { + if ( num_nacks == 1 ) + isOK = 1; + break; + } - // reset the resyncs since we got a complete transaction on right time. - consecutive_resyncs = 0; - } // end for loop + // reset the resyncs since we got a complete transaction on right time. + consecutive_resyncs = 0; + } // end for loop - // num_nacks = number of nacks recieved. should be only 1. if not its a clone card which always sends NACK (parity == 0) ? - // i = number of authentications sent. Not always 256, since we are trying to sync but close to it. - cmd_send(CMD_ACK, isOK, num_nacks, i, 0, 0 ); + // num_nacks = number of nacks recieved. should be only 1. if not its a clone card which always sends NACK (parity == 0) ? + // i = number of authentications sent. Not always 256, since we are trying to sync but close to it. + cmd_send(CMD_ACK, isOK, num_nacks, i, 0, 0 ); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); } /** *MIFARE 1K simulate. * *@param flags : - * FLAG_INTERACTIVE - In interactive mode, we are expected to finish the operation with an ACK - * FLAG_4B_UID_IN_DATA - use 4-byte UID in the data-section - * FLAG_7B_UID_IN_DATA - use 7-byte UID in the data-section - * FLAG_10B_UID_IN_DATA - use 10-byte UID in the data-section - * FLAG_UID_IN_EMUL - use 4-byte UID from emulator memory - * FLAG_NR_AR_ATTACK - collect NR_AR responses for bruteforcing later + * FLAG_INTERACTIVE - In interactive mode, we are expected to finish the operation with an ACK + * FLAG_4B_UID_IN_DATA - use 4-byte UID in the data-section + * FLAG_7B_UID_IN_DATA - use 7-byte UID in the data-section + * FLAG_10B_UID_IN_DATA - use 10-byte UID in the data-section + * FLAG_UID_IN_EMUL - use 4-byte UID from emulator memory + * FLAG_NR_AR_ATTACK - collect NR_AR responses for bruteforcing later *@param exitAfterNReads, exit simulation after n blocks have been read, 0 is inifite * (unless reader attack mode enabled then it runs util it gets enough nonces to recover all keys attmpted) */ void Mifare1ksim(uint8_t flags, uint8_t exitAfterNReads, uint8_t arg2, uint8_t *datain) { - int cardSTATE = MFEMUL_NOFIELD; - int _UID_LEN = 0; // 4, 7, 10 - int vHf = 0; // in mV - int res = 0; - uint32_t selTimer = 0; - uint32_t authTimer = 0; - uint16_t len = 0; - uint8_t cardWRBL = 0; - uint8_t cardAUTHSC = 0; - uint8_t cardAUTHKEY = 0xff; // no authentication - uint32_t cuid = 0; - uint32_t ans = 0; - uint32_t cardINTREG = 0; - uint8_t cardINTBLOCK = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - uint32_t numReads = 0; // Counts numer of times reader read a block - uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedCmd_par[MAX_MIFARE_PARITY_SIZE] = {0x00}; - uint8_t response[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t response_par[MAX_MIFARE_PARITY_SIZE] = {0x00}; + int cardSTATE = MFEMUL_NOFIELD; + int _UID_LEN = 0; // 4, 7, 10 + int vHf = 0; // in mV + int res = 0; + uint32_t selTimer = 0; + uint32_t authTimer = 0; + uint16_t len = 0; + uint8_t cardWRBL = 0; + uint8_t cardAUTHSC = 0; + uint8_t cardAUTHKEY = 0xff; // no authentication + uint32_t cuid = 0; + uint32_t ans = 0; + uint32_t cardINTREG = 0; + uint8_t cardINTBLOCK = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + uint32_t numReads = 0; // Counts numer of times reader read a block + uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedCmd_par[MAX_MIFARE_PARITY_SIZE] = {0x00}; + uint8_t response[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t response_par[MAX_MIFARE_PARITY_SIZE] = {0x00}; - uint8_t atqa[] = {0x04, 0x00}; // Mifare classic 1k - uint8_t sak_4[] = {0x0C, 0x00, 0x00}; // CL1 - 4b uid - uint8_t sak_7[] = {0x0C, 0x00, 0x00}; // CL2 - 7b uid - uint8_t sak_10[] = {0x0C, 0x00, 0x00}; // CL3 - 10b uid - // uint8_t sak[] = {0x09, 0x3f, 0xcc }; // Mifare Mini + uint8_t atqa[] = {0x04, 0x00}; // Mifare classic 1k + uint8_t sak_4[] = {0x0C, 0x00, 0x00}; // CL1 - 4b uid + uint8_t sak_7[] = {0x0C, 0x00, 0x00}; // CL2 - 7b uid + uint8_t sak_10[] = {0x0C, 0x00, 0x00}; // CL3 - 10b uid + // uint8_t sak[] = {0x09, 0x3f, 0xcc }; // Mifare Mini - uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; - uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; - uint8_t rUIDBCC3[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; + uint8_t rUIDBCC1[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; + uint8_t rUIDBCC2[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; + uint8_t rUIDBCC3[] = {0xde, 0xad, 0xbe, 0xaf, 0x62}; - // TAG Nonce - Authenticate response - uint8_t rAUTH_NT[4]; - uint32_t nonce = prng_successor( GetTickCount(), 32 ); - num_to_bytes(nonce, 4, rAUTH_NT); + // TAG Nonce - Authenticate response + uint8_t rAUTH_NT[4]; + uint32_t nonce = prng_successor( GetTickCount(), 32 ); + num_to_bytes(nonce, 4, rAUTH_NT); - // uint8_t rAUTH_NT[] = {0x55, 0x41, 0x49, 0x92};// nonce from nested? why this? - uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00}; + // uint8_t rAUTH_NT[] = {0x55, 0x41, 0x49, 0x92};// nonce from nested? why this? + uint8_t rAUTH_AT[] = {0x00, 0x00, 0x00, 0x00}; - // Here, we collect CUID, NT, NR, AR, CUID2, NT2, NR2, AR2 - // This can be used in a reader-only attack. - nonces_t ar_nr_nonces[ATTACK_KEY_COUNT]; - memset(ar_nr_nonces, 0x00, sizeof(ar_nr_nonces)); + // Here, we collect CUID, NT, NR, AR, CUID2, NT2, NR2, AR2 + // This can be used in a reader-only attack. + nonces_t ar_nr_nonces[ATTACK_KEY_COUNT]; + memset(ar_nr_nonces, 0x00, sizeof(ar_nr_nonces)); - // -- Determine the UID - // Can be set from emulator memory or incoming data - // Length: 4,7,or 10 bytes - if ( (flags & FLAG_UID_IN_EMUL) == FLAG_UID_IN_EMUL) - emlGetMemBt(datain, 0, 10); // load 10bytes from EMUL to the datain pointer. to be used below. + // -- Determine the UID + // Can be set from emulator memory or incoming data + // Length: 4,7,or 10 bytes + if ( (flags & FLAG_UID_IN_EMUL) == FLAG_UID_IN_EMUL) + emlGetMemBt(datain, 0, 10); // load 10bytes from EMUL to the datain pointer. to be used below. - if ( (flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) { - memcpy(rUIDBCC1, datain, 4); - _UID_LEN = 4; - } else if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) { - memcpy(&rUIDBCC1[1], datain, 3); - memcpy( rUIDBCC2, datain+3, 4); - _UID_LEN = 7; - } else if ( (flags & FLAG_10B_UID_IN_DATA) == FLAG_10B_UID_IN_DATA) { - memcpy(&rUIDBCC1[1], datain, 3); - memcpy(&rUIDBCC2[1], datain+3, 3); - memcpy( rUIDBCC3, datain+6, 4); - _UID_LEN = 10; - } + if ( (flags & FLAG_4B_UID_IN_DATA) == FLAG_4B_UID_IN_DATA) { + memcpy(rUIDBCC1, datain, 4); + _UID_LEN = 4; + } else if ( (flags & FLAG_7B_UID_IN_DATA) == FLAG_7B_UID_IN_DATA) { + memcpy(&rUIDBCC1[1], datain, 3); + memcpy( rUIDBCC2, datain+3, 4); + _UID_LEN = 7; + } else if ( (flags & FLAG_10B_UID_IN_DATA) == FLAG_10B_UID_IN_DATA) { + memcpy(&rUIDBCC1[1], datain, 3); + memcpy(&rUIDBCC2[1], datain+3, 3); + memcpy( rUIDBCC3, datain+6, 4); + _UID_LEN = 10; + } - switch (_UID_LEN) { - case 4: - sak_4[0] &= 0xFB; - // save CUID - cuid = bytes_to_num(rUIDBCC1, 4); - // BCC - rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; - if (MF_DBGLEVEL >= 2) { - Dbprintf("4B UID: %02x%02x%02x%02x", - rUIDBCC1[0], - rUIDBCC1[1], - rUIDBCC1[2], - rUIDBCC1[3] - ); - } - break; - case 7: - atqa[0] |= 0x40; - sak_7[0] &= 0xFB; - // save CUID - cuid = bytes_to_num(rUIDBCC2, 4); - // CascadeTag, CT - rUIDBCC1[0] = 0x88; - // BCC - rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; - rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; - if (MF_DBGLEVEL >= 2) { - Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x", - rUIDBCC1[1], - rUIDBCC1[2], - rUIDBCC1[3], - rUIDBCC2[0], - rUIDBCC2[1], - rUIDBCC2[2], - rUIDBCC2[3] - ); - } - break; - case 10: - atqa[0] |= 0x80; - sak_10[0] &= 0xFB; - // save CUID - cuid = bytes_to_num(rUIDBCC3, 4); - // CascadeTag, CT - rUIDBCC1[0] = 0x88; - rUIDBCC2[0] = 0x88; - // BCC - rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; - rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; - rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3]; + switch (_UID_LEN) { + case 4: + sak_4[0] &= 0xFB; + // save CUID + cuid = bytes_to_num(rUIDBCC1, 4); + // BCC + rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; + if (MF_DBGLEVEL >= 2) { + Dbprintf("4B UID: %02x%02x%02x%02x", + rUIDBCC1[0], + rUIDBCC1[1], + rUIDBCC1[2], + rUIDBCC1[3] + ); + } + break; + case 7: + atqa[0] |= 0x40; + sak_7[0] &= 0xFB; + // save CUID + cuid = bytes_to_num(rUIDBCC2, 4); + // CascadeTag, CT + rUIDBCC1[0] = 0x88; + // BCC + rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; + rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; + if (MF_DBGLEVEL >= 2) { + Dbprintf("7B UID: %02x %02x %02x %02x %02x %02x %02x", + rUIDBCC1[1], + rUIDBCC1[2], + rUIDBCC1[3], + rUIDBCC2[0], + rUIDBCC2[1], + rUIDBCC2[2], + rUIDBCC2[3] + ); + } + break; + case 10: + atqa[0] |= 0x80; + sak_10[0] &= 0xFB; + // save CUID + cuid = bytes_to_num(rUIDBCC3, 4); + // CascadeTag, CT + rUIDBCC1[0] = 0x88; + rUIDBCC2[0] = 0x88; + // BCC + rUIDBCC1[4] = rUIDBCC1[0] ^ rUIDBCC1[1] ^ rUIDBCC1[2] ^ rUIDBCC1[3]; + rUIDBCC2[4] = rUIDBCC2[0] ^ rUIDBCC2[1] ^ rUIDBCC2[2] ^ rUIDBCC2[3]; + rUIDBCC3[4] = rUIDBCC3[0] ^ rUIDBCC3[1] ^ rUIDBCC3[2] ^ rUIDBCC3[3]; - if (MF_DBGLEVEL >= 2) { - Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", - rUIDBCC1[1], - rUIDBCC1[2], - rUIDBCC1[3], - rUIDBCC2[1], - rUIDBCC2[2], - rUIDBCC2[3], - rUIDBCC3[0], - rUIDBCC3[1], - rUIDBCC3[2], - rUIDBCC3[3] - ); - } - break; - default: - break; - } - // calc some crcs - compute_crc(CRC_14443_A, sak_4, 1, &sak_4[1], &sak_4[2]); - compute_crc(CRC_14443_A, sak_7, 1, &sak_7[1], &sak_7[2]); - compute_crc(CRC_14443_A, sak_10, 1, &sak_10[1], &sak_10[2]); + if (MF_DBGLEVEL >= 2) { + Dbprintf("10B UID: %02x %02x %02x %02x %02x %02x %02x %02x %02x %02x", + rUIDBCC1[1], + rUIDBCC1[2], + rUIDBCC1[3], + rUIDBCC2[1], + rUIDBCC2[2], + rUIDBCC2[3], + rUIDBCC3[0], + rUIDBCC3[1], + rUIDBCC3[2], + rUIDBCC3[3] + ); + } + break; + default: + break; + } + // calc some crcs + compute_crc(CRC_14443_A, sak_4, 1, &sak_4[1], &sak_4[2]); + compute_crc(CRC_14443_A, sak_7, 1, &sak_7[1], &sak_7[2]); + compute_crc(CRC_14443_A, sak_10, 1, &sak_10[1], &sak_10[2]); - // We need to listen to the high-frequency, peak-detected path. - iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); + // We need to listen to the high-frequency, peak-detected path. + iso14443a_setup(FPGA_HF_ISO14443A_TAGSIM_LISTEN); - // free eventually allocated BigBuf memory but keep Emulator Memory - BigBuf_free_keep_EM(); - clear_trace(); - set_tracing(true); - LED_D_ON(); + // free eventually allocated BigBuf memory but keep Emulator Memory + BigBuf_free_keep_EM(); + clear_trace(); + set_tracing(true); + LED_D_ON(); - bool finished = false; - while (!BUTTON_PRESS() && !finished && !usb_poll_validate_length()) { - WDT_HIT(); + bool finished = false; + while (!BUTTON_PRESS() && !finished && !usb_poll_validate_length()) { + WDT_HIT(); - // find reader field - if (cardSTATE == MFEMUL_NOFIELD) { + // find reader field + if (cardSTATE == MFEMUL_NOFIELD) { - vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; - if (vHf > MF_MINFIELDV) { - cardSTATE_TO_IDLE(); - LED_A_ON(); - } - } - if (cardSTATE == MFEMUL_NOFIELD) continue; + vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; + if (vHf > MF_MINFIELDV) { + cardSTATE_TO_IDLE(); + LED_A_ON(); + } + } + if (cardSTATE == MFEMUL_NOFIELD) continue; - // Now, get data - res = EmGetCmd(receivedCmd, &len, receivedCmd_par); - if (res == 2) { //Field is off! - cardSTATE = MFEMUL_NOFIELD; - LEDsoff(); - continue; - } else if (res == 1) { - break; // return value 1 means button press - } + // Now, get data + res = EmGetCmd(receivedCmd, &len, receivedCmd_par); + if (res == 2) { //Field is off! + cardSTATE = MFEMUL_NOFIELD; + LEDsoff(); + continue; + } else if (res == 1) { + break; // return value 1 means button press + } - // REQ or WUP request in ANY state and WUP in HALTED state - // this if-statement doesn't match the specification above. (iceman) - if (len == 1 && ((receivedCmd[0] == ISO14443A_CMD_REQA && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == ISO14443A_CMD_WUPA)) { - selTimer = GetTickCount(); - EmSendCmd(atqa, sizeof(atqa)); - cardSTATE = MFEMUL_SELECT1; - crypto1_destroy(pcs); - cardAUTHKEY = 0xff; - nonce = prng_successor(selTimer, 32); - continue; - } + // REQ or WUP request in ANY state and WUP in HALTED state + // this if-statement doesn't match the specification above. (iceman) + if (len == 1 && ((receivedCmd[0] == ISO14443A_CMD_REQA && cardSTATE != MFEMUL_HALTED) || receivedCmd[0] == ISO14443A_CMD_WUPA)) { + selTimer = GetTickCount(); + EmSendCmd(atqa, sizeof(atqa)); + cardSTATE = MFEMUL_SELECT1; + crypto1_destroy(pcs); + cardAUTHKEY = 0xff; + nonce = prng_successor(selTimer, 32); + continue; + } - switch (cardSTATE) { - case MFEMUL_NOFIELD: - case MFEMUL_HALTED: - case MFEMUL_IDLE:{ - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } - case MFEMUL_SELECT1:{ - if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x20)) { - if (MF_DBGLEVEL >= 4) Dbprintf("SELECT ALL received"); - EmSendCmd(rUIDBCC1, sizeof(rUIDBCC1)); - break; - } - // select card - if (len == 9 && - ( receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && - receivedCmd[1] == 0x70 && - memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) { + switch (cardSTATE) { + case MFEMUL_NOFIELD: + case MFEMUL_HALTED: + case MFEMUL_IDLE:{ + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + break; + } + case MFEMUL_SELECT1:{ + if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && receivedCmd[1] == 0x20)) { + if (MF_DBGLEVEL >= 4) Dbprintf("SELECT ALL received"); + EmSendCmd(rUIDBCC1, sizeof(rUIDBCC1)); + break; + } + // select card + if (len == 9 && + ( receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT && + receivedCmd[1] == 0x70 && + memcmp(&receivedCmd[2], rUIDBCC1, 4) == 0)) { - // SAK 4b - EmSendCmd(sak_4, sizeof(sak_4)); - switch(_UID_LEN){ - case 4: - cardSTATE = MFEMUL_WORK; - LED_B_ON(); - if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - selTimer); - continue; - case 7: - case 10: - cardSTATE = MFEMUL_SELECT2; - continue; - default:break; - } - } else { - cardSTATE_TO_IDLE(); - } - break; - } - case MFEMUL_SELECT2:{ - if (!len) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } - if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x20)) { - EmSendCmd(rUIDBCC2, sizeof(rUIDBCC2)); - break; - } - if (len == 9 && - (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && - receivedCmd[1] == 0x70 && - memcmp(&receivedCmd[2], rUIDBCC2, 4) == 0) ) { + // SAK 4b + EmSendCmd(sak_4, sizeof(sak_4)); + switch(_UID_LEN){ + case 4: + cardSTATE = MFEMUL_WORK; + LED_B_ON(); + if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol1 time: %d", GetTickCount() - selTimer); + continue; + case 7: + case 10: + cardSTATE = MFEMUL_SELECT2; + continue; + default:break; + } + } else { + cardSTATE_TO_IDLE(); + } + break; + } + case MFEMUL_SELECT2:{ + if (!len) { + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + break; + } + if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && receivedCmd[1] == 0x20)) { + EmSendCmd(rUIDBCC2, sizeof(rUIDBCC2)); + break; + } + if (len == 9 && + (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2 && + receivedCmd[1] == 0x70 && + memcmp(&receivedCmd[2], rUIDBCC2, 4) == 0) ) { - EmSendCmd(sak_7, sizeof(sak_7)); - switch(_UID_LEN){ - case 7: - cardSTATE = MFEMUL_WORK; - LED_B_ON(); - if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - selTimer); - continue; - case 10: - cardSTATE = MFEMUL_SELECT3; - continue; - default:break; - } - } - cardSTATE_TO_IDLE(); - break; - } - case MFEMUL_SELECT3:{ - if (!len) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } - if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && receivedCmd[1] == 0x20)) { - EmSendCmd(rUIDBCC3, sizeof(rUIDBCC3)); - break; - } - if (len == 9 && - (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && - receivedCmd[1] == 0x70 && - memcmp(&receivedCmd[2], rUIDBCC3, 4) == 0) ) { + EmSendCmd(sak_7, sizeof(sak_7)); + switch(_UID_LEN){ + case 7: + cardSTATE = MFEMUL_WORK; + LED_B_ON(); + if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol2 time: %d", GetTickCount() - selTimer); + continue; + case 10: + cardSTATE = MFEMUL_SELECT3; + continue; + default:break; + } + } + cardSTATE_TO_IDLE(); + break; + } + case MFEMUL_SELECT3:{ + if (!len) { + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + break; + } + if (len == 2 && (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && receivedCmd[1] == 0x20)) { + EmSendCmd(rUIDBCC3, sizeof(rUIDBCC3)); + break; + } + if (len == 9 && + (receivedCmd[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3 && + receivedCmd[1] == 0x70 && + memcmp(&receivedCmd[2], rUIDBCC3, 4) == 0) ) { - EmSendCmd(sak_10, sizeof(sak_10)); - cardSTATE = MFEMUL_WORK; - LED_B_ON(); - if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol3 time: %d", GetTickCount() - selTimer); - break; - } - cardSTATE_TO_IDLE(); - break; - } - case MFEMUL_AUTH1:{ - if( len != 8) { - cardSTATE_TO_IDLE(); - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } + EmSendCmd(sak_10, sizeof(sak_10)); + cardSTATE = MFEMUL_WORK; + LED_B_ON(); + if (MF_DBGLEVEL >= 4) Dbprintf("--> WORK. anticol3 time: %d", GetTickCount() - selTimer); + break; + } + cardSTATE_TO_IDLE(); + break; + } + case MFEMUL_AUTH1:{ + if( len != 8) { + cardSTATE_TO_IDLE(); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + break; + } - uint32_t nr = bytes_to_num(receivedCmd, 4); - uint32_t ar = bytes_to_num(&receivedCmd[4], 4); + uint32_t nr = bytes_to_num(receivedCmd, 4); + uint32_t ar = bytes_to_num(&receivedCmd[4], 4); - // Collect AR/NR per keytype & sector - if ( (flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK ) { + // Collect AR/NR per keytype & sector + if ( (flags & FLAG_NR_AR_ATTACK) == FLAG_NR_AR_ATTACK ) { - int8_t index = -1; - int8_t empty = -1; - for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { - // find which index to use - if ( (cardAUTHSC == ar_nr_nonces[i].sector) && (cardAUTHKEY == ar_nr_nonces[i].keytype)) - index = i; + int8_t index = -1; + int8_t empty = -1; + for (uint8_t i = 0; i < ATTACK_KEY_COUNT; i++) { + // find which index to use + if ( (cardAUTHSC == ar_nr_nonces[i].sector) && (cardAUTHKEY == ar_nr_nonces[i].keytype)) + index = i; - // keep track of empty slots. - if ( ar_nr_nonces[i].state == EMPTY) - empty = i; - } - // if no empty slots. Choose first and overwrite. - if ( index == -1 ) { - if ( empty == -1 ) { - index = 0; - ar_nr_nonces[index].state = EMPTY; - } else { - index = empty; - } - } + // keep track of empty slots. + if ( ar_nr_nonces[i].state == EMPTY) + empty = i; + } + // if no empty slots. Choose first and overwrite. + if ( index == -1 ) { + if ( empty == -1 ) { + index = 0; + ar_nr_nonces[index].state = EMPTY; + } else { + index = empty; + } + } - switch(ar_nr_nonces[index].state) { - case EMPTY: { - // first nonce collect - ar_nr_nonces[index].cuid = cuid; - ar_nr_nonces[index].sector = cardAUTHSC; - ar_nr_nonces[index].keytype = cardAUTHKEY; - ar_nr_nonces[index].nonce = nonce; - ar_nr_nonces[index].nr = nr; - ar_nr_nonces[index].ar = ar; - ar_nr_nonces[index].state = FIRST; - break; - } - case FIRST : { - // second nonce collect - ar_nr_nonces[index].nonce2 = nonce; - ar_nr_nonces[index].nr2 = nr; - ar_nr_nonces[index].ar2 = ar; - ar_nr_nonces[index].state = SECOND; + switch(ar_nr_nonces[index].state) { + case EMPTY: { + // first nonce collect + ar_nr_nonces[index].cuid = cuid; + ar_nr_nonces[index].sector = cardAUTHSC; + ar_nr_nonces[index].keytype = cardAUTHKEY; + ar_nr_nonces[index].nonce = nonce; + ar_nr_nonces[index].nr = nr; + ar_nr_nonces[index].ar = ar; + ar_nr_nonces[index].state = FIRST; + break; + } + case FIRST : { + // second nonce collect + ar_nr_nonces[index].nonce2 = nonce; + ar_nr_nonces[index].nr2 = nr; + ar_nr_nonces[index].ar2 = ar; + ar_nr_nonces[index].state = SECOND; - // send to client - cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, 0, 0, &ar_nr_nonces[index], sizeof(nonces_t)); + // send to client + cmd_send(CMD_ACK, CMD_SIMULATE_MIFARE_CARD, 0, 0, &ar_nr_nonces[index], sizeof(nonces_t)); - ar_nr_nonces[index].state = EMPTY; - ar_nr_nonces[index].sector = 0; - ar_nr_nonces[index].keytype = 0; - break; - } - default: break; - } - } + ar_nr_nonces[index].state = EMPTY; + ar_nr_nonces[index].sector = 0; + ar_nr_nonces[index].keytype = 0; + break; + } + default: break; + } + } - crypto1_word(pcs, nr , 1); - uint32_t cardRr = ar ^ crypto1_word(pcs, 0, 0); + crypto1_word(pcs, nr , 1); + uint32_t cardRr = ar ^ crypto1_word(pcs, 0, 0); - //test if auth OK - if (cardRr != prng_successor(nonce, 64)){ + //test if auth OK + if (cardRr != prng_successor(nonce, 64)){ - if (MF_DBGLEVEL >= 3) { - Dbprintf("AUTH FAILED for sector %d with key %c. [nr=%08x cardRr=%08x] [nt=%08x succ=%08x]" - , cardAUTHSC - , (cardAUTHKEY == 0) ? 'A' : 'B' - , nr - , cardRr - , nonce // nt - , prng_successor(nonce, 64) - ); - } - // Shouldn't we respond anything here? - // Right now, we don't nack or anything, which causes the - // reader to do a WUPA after a while. /Martin - // -- which is the correct response. /piwi - cardSTATE_TO_IDLE(); - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } + if (MF_DBGLEVEL >= 3) { + Dbprintf("AUTH FAILED for sector %d with key %c. [nr=%08x cardRr=%08x] [nt=%08x succ=%08x]" + , cardAUTHSC + , (cardAUTHKEY == 0) ? 'A' : 'B' + , nr + , cardRr + , nonce // nt + , prng_successor(nonce, 64) + ); + } + // Shouldn't we respond anything here? + // Right now, we don't nack or anything, which causes the + // reader to do a WUPA after a while. /Martin + // -- which is the correct response. /piwi + cardSTATE_TO_IDLE(); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + break; + } - ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0); - num_to_bytes(ans, 4, rAUTH_AT); - EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); - LED_C_ON(); + ans = prng_successor(nonce, 96) ^ crypto1_word(pcs, 0, 0); + num_to_bytes(ans, 4, rAUTH_AT); + EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); + LED_C_ON(); - if (MF_DBGLEVEL >= 3) { - Dbprintf("AUTH COMPLETED for sector %d with key %c. time=%d", - cardAUTHSC, - cardAUTHKEY == 0 ? 'A' : 'B', - GetTickCount() - authTimer - ); - } - cardSTATE = MFEMUL_WORK; - break; - } - case MFEMUL_WORK:{ - if (len == 0) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } - bool encrypted_data = (cardAUTHKEY != 0xFF) ; + if (MF_DBGLEVEL >= 3) { + Dbprintf("AUTH COMPLETED for sector %d with key %c. time=%d", + cardAUTHSC, + cardAUTHKEY == 0 ? 'A' : 'B', + GetTickCount() - authTimer + ); + } + cardSTATE = MFEMUL_WORK; + break; + } + case MFEMUL_WORK:{ + if (len == 0) { + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + break; + } + bool encrypted_data = (cardAUTHKEY != 0xFF) ; - if(encrypted_data) - mf_crypto1_decrypt(pcs, receivedCmd, len); + if(encrypted_data) + mf_crypto1_decrypt(pcs, receivedCmd, len); - if (len == 4 && (receivedCmd[0] == MIFARE_AUTH_KEYA || - receivedCmd[0] == MIFARE_AUTH_KEYB) ) { + if (len == 4 && (receivedCmd[0] == MIFARE_AUTH_KEYA || + receivedCmd[0] == MIFARE_AUTH_KEYB) ) { - authTimer = GetTickCount(); - cardAUTHSC = receivedCmd[1] / 4; // received block -> sector - cardAUTHKEY = receivedCmd[0] & 0x1; - crypto1_destroy(pcs); + authTimer = GetTickCount(); + cardAUTHSC = receivedCmd[1] / 4; // received block -> sector + cardAUTHKEY = receivedCmd[0] & 0x1; + crypto1_destroy(pcs); - // load key into crypto - crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY)); + // load key into crypto + crypto1_create(pcs, emlGetKey(cardAUTHSC, cardAUTHKEY)); - if (!encrypted_data) { - // first authentication - // Update crypto state init (UID ^ NONCE) - crypto1_word(pcs, cuid ^ nonce, 0); - num_to_bytes(nonce, 4, rAUTH_AT); - } else { - // nested authentication - ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0); - num_to_bytes(ans, 4, rAUTH_AT); + if (!encrypted_data) { + // first authentication + // Update crypto state init (UID ^ NONCE) + crypto1_word(pcs, cuid ^ nonce, 0); + num_to_bytes(nonce, 4, rAUTH_AT); + } else { + // nested authentication + ans = nonce ^ crypto1_word(pcs, cuid ^ nonce, 0); + num_to_bytes(ans, 4, rAUTH_AT); - if (MF_DBGLEVEL >= 3) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %c", receivedCmd[1], receivedCmd[1], cardAUTHKEY == 0 ? 'A' : 'B'); - } + if (MF_DBGLEVEL >= 3) Dbprintf("Reader doing nested authentication for block %d (0x%02x) with key %c", receivedCmd[1], receivedCmd[1], cardAUTHKEY == 0 ? 'A' : 'B'); + } - EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); - cardSTATE = MFEMUL_AUTH1; - break; - } + EmSendCmd(rAUTH_AT, sizeof(rAUTH_AT)); + cardSTATE = MFEMUL_AUTH1; + break; + } - // rule 13 of 7.5.3. in ISO 14443-4. chaining shall be continued - // BUT... ACK --> NACK - if (len == 1 && receivedCmd[0] == CARD_ACK) { - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - break; - } + // rule 13 of 7.5.3. in ISO 14443-4. chaining shall be continued + // BUT... ACK --> NACK + if (len == 1 && receivedCmd[0] == CARD_ACK) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + break; + } - // rule 12 of 7.5.3. in ISO 14443-4. R(NAK) --> R(ACK) - if (len == 1 && receivedCmd[0] == CARD_NACK_NA) { - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); - break; - } + // rule 12 of 7.5.3. in ISO 14443-4. R(NAK) --> R(ACK) + if (len == 1 && receivedCmd[0] == CARD_NACK_NA) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + break; + } - if(len != 4) { - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } + if(len != 4) { + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + break; + } - if ( receivedCmd[0] == ISO14443A_CMD_READBLOCK || - receivedCmd[0] == ISO14443A_CMD_WRITEBLOCK || - receivedCmd[0] == MIFARE_CMD_INC || - receivedCmd[0] == MIFARE_CMD_DEC || - receivedCmd[0] == MIFARE_CMD_RESTORE || - receivedCmd[0] == MIFARE_CMD_TRANSFER ) { + if ( receivedCmd[0] == ISO14443A_CMD_READBLOCK || + receivedCmd[0] == ISO14443A_CMD_WRITEBLOCK || + receivedCmd[0] == MIFARE_CMD_INC || + receivedCmd[0] == MIFARE_CMD_DEC || + receivedCmd[0] == MIFARE_CMD_RESTORE || + receivedCmd[0] == MIFARE_CMD_TRANSFER ) { - if (receivedCmd[1] >= 16 * 4) { - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate (0x%02) on out of range block: %d (0x%02x), nacking",receivedCmd[0],receivedCmd[1],receivedCmd[1]); - break; - } + if (receivedCmd[1] >= 16 * 4) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate (0x%02) on out of range block: %d (0x%02x), nacking",receivedCmd[0],receivedCmd[1],receivedCmd[1]); + break; + } - if (receivedCmd[1] / 4 != cardAUTHSC) { - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate (0x%02) on block (0x%02x) not authenticated for (0x%02x), nacking",receivedCmd[0],receivedCmd[1],cardAUTHSC); - break; - } - } - // read block - if (receivedCmd[0] == ISO14443A_CMD_READBLOCK) { - if (MF_DBGLEVEL >= 4) Dbprintf("Reader reading block %d (0x%02x)", receivedCmd[1], receivedCmd[1]); + if (receivedCmd[1] / 4 != cardAUTHSC) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate (0x%02) on block (0x%02x) not authenticated for (0x%02x), nacking",receivedCmd[0],receivedCmd[1],cardAUTHSC); + break; + } + } + // read block + if (receivedCmd[0] == ISO14443A_CMD_READBLOCK) { + if (MF_DBGLEVEL >= 4) Dbprintf("Reader reading block %d (0x%02x)", receivedCmd[1], receivedCmd[1]); - emlGetMem(response, receivedCmd[1], 1); - AddCrc14A(response, 16); - mf_crypto1_encrypt(pcs, response, 18, response_par); - EmSendCmdPar(response, 18, response_par); - numReads++; - if(exitAfterNReads > 0 && numReads >= exitAfterNReads) { - Dbprintf("%d reads done, exiting", numReads); - finished = true; - } - break; - } - // write block - if (receivedCmd[0] == ISO14443A_CMD_WRITEBLOCK) { - if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0xA0 write block %d (%02x)", receivedCmd[1], receivedCmd[1]); - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); - cardSTATE = MFEMUL_WRITEBL2; - cardWRBL = receivedCmd[1]; - break; - } - // increment, decrement, restore - if ( receivedCmd[0] == MIFARE_CMD_INC || - receivedCmd[0] == MIFARE_CMD_DEC || - receivedCmd[0] == MIFARE_CMD_RESTORE) { + emlGetMem(response, receivedCmd[1], 1); + AddCrc14A(response, 16); + mf_crypto1_encrypt(pcs, response, 18, response_par); + EmSendCmdPar(response, 18, response_par); + numReads++; + if(exitAfterNReads > 0 && numReads >= exitAfterNReads) { + Dbprintf("%d reads done, exiting", numReads); + finished = true; + } + break; + } + // write block + if (receivedCmd[0] == ISO14443A_CMD_WRITEBLOCK) { + if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0xA0 write block %d (%02x)", receivedCmd[1], receivedCmd[1]); + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + cardSTATE = MFEMUL_WRITEBL2; + cardWRBL = receivedCmd[1]; + break; + } + // increment, decrement, restore + if ( receivedCmd[0] == MIFARE_CMD_INC || + receivedCmd[0] == MIFARE_CMD_DEC || + receivedCmd[0] == MIFARE_CMD_RESTORE) { - if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)",receivedCmd[0], receivedCmd[1], receivedCmd[1]); + if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x inc(0xC1)/dec(0xC0)/restore(0xC2) block %d (%02x)",receivedCmd[0], receivedCmd[1], receivedCmd[1]); - if (emlCheckValBl(receivedCmd[1])) { - if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate on block, but emlCheckValBl failed, nacking"); - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - break; - } - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); - if (receivedCmd[0] == MIFARE_CMD_INC) cardSTATE = MFEMUL_INTREG_INC; - if (receivedCmd[0] == MIFARE_CMD_DEC) cardSTATE = MFEMUL_INTREG_DEC; - if (receivedCmd[0] == MIFARE_CMD_RESTORE) cardSTATE = MFEMUL_INTREG_REST; - cardWRBL = receivedCmd[1]; - break; - } - // transfer - if (receivedCmd[0] == MIFARE_CMD_TRANSFER) { - if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x transfer block %d (%02x)", receivedCmd[0], receivedCmd[1], receivedCmd[1]); - if (emlSetValBl(cardINTREG, cardINTBLOCK, receivedCmd[1])) - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - else - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); - break; - } - // halt - if (receivedCmd[0] == ISO14443A_CMD_HALT && receivedCmd[1] == 0x00) { - LED_B_OFF(); - LED_C_OFF(); - cardSTATE = MFEMUL_HALTED; - if (MF_DBGLEVEL >= 4) Dbprintf("--> HALTED. Selected time: %d ms", GetTickCount() - selTimer); - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - break; - } - // RATS - if (receivedCmd[0] == ISO14443A_CMD_RATS) { - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - break; - } - // command not allowed - if (MF_DBGLEVEL >= 4) Dbprintf("Received command not allowed, nacking"); - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - break; - } - case MFEMUL_WRITEBL2:{ - if (len == 18) { - mf_crypto1_decrypt(pcs, receivedCmd, len); - emlSetMem(receivedCmd, cardWRBL, 1); - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); - cardSTATE = MFEMUL_WORK; - } else { - cardSTATE_TO_IDLE(); - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - } - break; - } - case MFEMUL_INTREG_INC:{ - mf_crypto1_decrypt(pcs, receivedCmd, len); - memcpy(&ans, receivedCmd, 4); - if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - cardSTATE_TO_IDLE(); - break; - } - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - cardINTREG = cardINTREG + ans; - cardSTATE = MFEMUL_WORK; - break; - } - case MFEMUL_INTREG_DEC:{ - mf_crypto1_decrypt(pcs, receivedCmd, len); - memcpy(&ans, receivedCmd, 4); - if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - cardSTATE_TO_IDLE(); - break; - } - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - cardINTREG = cardINTREG - ans; - cardSTATE = MFEMUL_WORK; - break; - } - case MFEMUL_INTREG_REST:{ - mf_crypto1_decrypt(pcs, receivedCmd, len); - memcpy(&ans, receivedCmd, 4); - if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { - EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); - cardSTATE_TO_IDLE(); - break; - } - LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); - cardSTATE = MFEMUL_WORK; - break; - } - } - } + if (emlCheckValBl(receivedCmd[1])) { + if (MF_DBGLEVEL >= 4) Dbprintf("Reader tried to operate on block, but emlCheckValBl failed, nacking"); + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + break; + } + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + if (receivedCmd[0] == MIFARE_CMD_INC) cardSTATE = MFEMUL_INTREG_INC; + if (receivedCmd[0] == MIFARE_CMD_DEC) cardSTATE = MFEMUL_INTREG_DEC; + if (receivedCmd[0] == MIFARE_CMD_RESTORE) cardSTATE = MFEMUL_INTREG_REST; + cardWRBL = receivedCmd[1]; + break; + } + // transfer + if (receivedCmd[0] == MIFARE_CMD_TRANSFER) { + if (MF_DBGLEVEL >= 4) Dbprintf("RECV 0x%02x transfer block %d (%02x)", receivedCmd[0], receivedCmd[1], receivedCmd[1]); + if (emlSetValBl(cardINTREG, cardINTBLOCK, receivedCmd[1])) + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + else + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + break; + } + // halt + if (receivedCmd[0] == ISO14443A_CMD_HALT && receivedCmd[1] == 0x00) { + LED_B_OFF(); + LED_C_OFF(); + cardSTATE = MFEMUL_HALTED; + if (MF_DBGLEVEL >= 4) Dbprintf("--> HALTED. Selected time: %d ms", GetTickCount() - selTimer); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + break; + } + // RATS + if (receivedCmd[0] == ISO14443A_CMD_RATS) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + break; + } + // command not allowed + if (MF_DBGLEVEL >= 4) Dbprintf("Received command not allowed, nacking"); + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + break; + } + case MFEMUL_WRITEBL2:{ + if (len == 18) { + mf_crypto1_decrypt(pcs, receivedCmd, len); + emlSetMem(receivedCmd, cardWRBL, 1); + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_ACK)); + cardSTATE = MFEMUL_WORK; + } else { + cardSTATE_TO_IDLE(); + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + } + break; + } + case MFEMUL_INTREG_INC:{ + mf_crypto1_decrypt(pcs, receivedCmd, len); + memcpy(&ans, receivedCmd, 4); + if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + cardSTATE_TO_IDLE(); + break; + } + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + cardINTREG = cardINTREG + ans; + cardSTATE = MFEMUL_WORK; + break; + } + case MFEMUL_INTREG_DEC:{ + mf_crypto1_decrypt(pcs, receivedCmd, len); + memcpy(&ans, receivedCmd, 4); + if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + cardSTATE_TO_IDLE(); + break; + } + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + cardINTREG = cardINTREG - ans; + cardSTATE = MFEMUL_WORK; + break; + } + case MFEMUL_INTREG_REST:{ + mf_crypto1_decrypt(pcs, receivedCmd, len); + memcpy(&ans, receivedCmd, 4); + if (emlGetValBl(&cardINTREG, &cardINTBLOCK, cardWRBL)) { + EmSend4bit(mf_crypto1_encrypt4bit(pcs, CARD_NACK_NA)); + cardSTATE_TO_IDLE(); + break; + } + LogTrace(Uart.output, Uart.len, Uart.startTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.endTime*16 - DELAY_AIR2ARM_AS_TAG, Uart.parity, true); + cardSTATE = MFEMUL_WORK; + break; + } + } + } - if (MF_DBGLEVEL >= 1) - Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen()); + if (MF_DBGLEVEL >= 1) + Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen()); - cmd_send(CMD_ACK,1,0,0,0,0); FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); + cmd_send(CMD_ACK,1,0,0,0,0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); } diff --git a/armsrc/iso14443a.h b/armsrc/iso14443a.h index c5e1e62f1..38d0b99e1 100644 --- a/armsrc/iso14443a.h +++ b/armsrc/iso14443a.h @@ -31,66 +31,66 @@ extern "C" { #include "mifare.h" // structs typedef struct { - enum { - DEMOD_UNSYNCD, - // DEMOD_HALF_SYNCD, - // DEMOD_MOD_FIRST_HALF, - // DEMOD_NOMOD_FIRST_HALF, - DEMOD_MANCHESTER_DATA - } state; - uint16_t twoBits; - uint16_t highCnt; - uint16_t bitCount; - uint16_t collisionPos; - uint16_t syncBit; - uint8_t parityBits; - uint8_t parityLen; - uint16_t shiftReg; - uint16_t samples; - uint16_t len; - uint32_t startTime, endTime; - uint8_t *output; - uint8_t *parity; + enum { + DEMOD_UNSYNCD, + // DEMOD_HALF_SYNCD, + // DEMOD_MOD_FIRST_HALF, + // DEMOD_NOMOD_FIRST_HALF, + DEMOD_MANCHESTER_DATA + } state; + uint16_t twoBits; + uint16_t highCnt; + uint16_t bitCount; + uint16_t collisionPos; + uint16_t syncBit; + uint8_t parityBits; + uint8_t parityLen; + uint16_t shiftReg; + uint16_t samples; + uint16_t len; + uint32_t startTime, endTime; + uint8_t *output; + uint8_t *parity; } tDemod; /* typedef enum { - MOD_NOMOD = 0, - MOD_SECOND_HALF, - MOD_FIRST_HALF, - MOD_BOTH_HALVES - } Modulation_t; + MOD_NOMOD = 0, + MOD_SECOND_HALF, + MOD_FIRST_HALF, + MOD_BOTH_HALVES + } Modulation_t; */ typedef struct { - enum { - STATE_UNSYNCD, - STATE_START_OF_COMMUNICATION, - STATE_MILLER_X, - STATE_MILLER_Y, - STATE_MILLER_Z, - // DROP_NONE, - // DROP_FIRST_HALF, - } state; - uint16_t shiftReg; - int16_t bitCount; - uint16_t len; - //uint16_t byteCntMax; - uint16_t posCnt; - uint16_t syncBit; - uint8_t parityBits; - uint8_t parityLen; - uint32_t fourBits; - uint32_t startTime, endTime; + enum { + STATE_UNSYNCD, + STATE_START_OF_COMMUNICATION, + STATE_MILLER_X, + STATE_MILLER_Y, + STATE_MILLER_Z, + // DROP_NONE, + // DROP_FIRST_HALF, + } state; + uint16_t shiftReg; + int16_t bitCount; + uint16_t len; + //uint16_t byteCntMax; + uint16_t posCnt; + uint16_t syncBit; + uint8_t parityBits; + uint8_t parityLen; + uint32_t fourBits; + uint32_t startTime, endTime; uint8_t *output; - uint8_t *parity; + uint8_t *parity; } tUart; #ifndef AddCrc14A -# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1) +# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1) #endif #ifndef AddCrc14B -# define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1) +# define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1) #endif extern void GetParity(const uint8_t *pbtCmd, uint16_t len, uint8_t *par); @@ -129,7 +129,7 @@ extern int EmSendCmdParEx(uint8_t *resp, uint16_t respLen, uint8_t *par, bool co extern int EmSendPrecompiledCmd(tag_response_info_t *response_info); bool EmLogTrace(uint8_t *reader_data, uint16_t reader_len, uint32_t reader_StartTime, uint32_t reader_EndTime, uint8_t *reader_Parity, - uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity); + uint8_t *tag_data, uint16_t tag_len, uint32_t tag_StartTime, uint32_t tag_EndTime, uint8_t *tag_Parity); //extern bool prepare_allocated_tag_modulation(tag_response_info_t *response_info, uint8_t **buffer, size_t *buffer_size); diff --git a/armsrc/iso14443b.c b/armsrc/iso14443b.c index f093fb1a7..2e2aec7cd 100644 --- a/armsrc/iso14443b.c +++ b/armsrc/iso14443b.c @@ -40,7 +40,7 @@ //#define SEND4STUFFBIT(x) ToSendStuffBit(x); // iceman, this threshold value, what makes 8 a good amplitude for this IQ values? #ifndef SUBCARRIER_DETECT_THRESHOLD -# define SUBCARRIER_DETECT_THRESHOLD 8 +# define SUBCARRIER_DETECT_THRESHOLD 8 #endif static void iso14b_set_timeout(uint32_t timeout); @@ -63,80 +63,80 @@ static uint32_t iso14b_timeout = FWT_TIMEOUT_14B; // The software UART that receives commands from the reader, and its state variables. //----------------------------------------------------------------------------- static struct { - enum { - STATE_UNSYNCD, - STATE_GOT_FALLING_EDGE_OF_SOF, - STATE_AWAITING_START_BIT, - STATE_RECEIVING_DATA - } state; - uint16_t shiftReg; - int bitCnt; - int byteCnt; - int byteCntMax; - int posCnt; - uint8_t *output; + enum { + STATE_UNSYNCD, + STATE_GOT_FALLING_EDGE_OF_SOF, + STATE_AWAITING_START_BIT, + STATE_RECEIVING_DATA + } state; + uint16_t shiftReg; + int bitCnt; + int byteCnt; + int byteCntMax; + int posCnt; + uint8_t *output; } Uart; static void UartReset() { - Uart.state = STATE_UNSYNCD; - Uart.shiftReg = 0; - Uart.bitCnt = 0; - Uart.byteCnt = 0; - Uart.byteCntMax = MAX_FRAME_SIZE; - Uart.posCnt = 0; + Uart.state = STATE_UNSYNCD; + Uart.shiftReg = 0; + Uart.bitCnt = 0; + Uart.byteCnt = 0; + Uart.byteCntMax = MAX_FRAME_SIZE; + Uart.posCnt = 0; } static void UartInit(uint8_t *data) { - Uart.output = data; - UartReset(); -// memset(Uart.output, 0x00, MAX_FRAME_SIZE); + Uart.output = data; + UartReset(); +// memset(Uart.output, 0x00, MAX_FRAME_SIZE); } //----------------------------------------------------------------------------- // The software Demod that receives commands from the tag, and its state variables. //----------------------------------------------------------------------------- static struct { - enum { - DEMOD_UNSYNCD, - DEMOD_PHASE_REF_TRAINING, - DEMOD_AWAITING_FALLING_EDGE_OF_SOF, - DEMOD_GOT_FALLING_EDGE_OF_SOF, - DEMOD_AWAITING_START_BIT, - DEMOD_RECEIVING_DATA - } state; - uint16_t bitCount; - int posCount; - int thisBit; + enum { + DEMOD_UNSYNCD, + DEMOD_PHASE_REF_TRAINING, + DEMOD_AWAITING_FALLING_EDGE_OF_SOF, + DEMOD_GOT_FALLING_EDGE_OF_SOF, + DEMOD_AWAITING_START_BIT, + DEMOD_RECEIVING_DATA + } state; + uint16_t bitCount; + int posCount; + int thisBit; /* this had been used to add RSSI (Received Signal Strength Indication) to traces. Currently not implemented. - int metric; - int metricN; + int metric; + int metricN; */ - uint16_t shiftReg; - uint8_t *output; - uint16_t len; - int sumI; - int sumQ; - uint32_t startTime, endTime; + uint16_t shiftReg; + uint8_t *output; + uint16_t len; + int sumI; + int sumQ; + uint32_t startTime, endTime; } Demod; // Clear out the state of the "UART" that receives from the tag. static void DemodReset() { - Demod.state = DEMOD_UNSYNCD; - Demod.bitCount = 0; - Demod.posCount = 0; - Demod.thisBit = 0; - Demod.shiftReg = 0; - Demod.len = 0; - Demod.sumI = 0; - Demod.sumQ = 0; - Demod.startTime = 0; - Demod.endTime = 0; + Demod.state = DEMOD_UNSYNCD; + Demod.bitCount = 0; + Demod.posCount = 0; + Demod.thisBit = 0; + Demod.shiftReg = 0; + Demod.len = 0; + Demod.sumI = 0; + Demod.sumQ = 0; + Demod.startTime = 0; + Demod.endTime = 0; } static void DemodInit(uint8_t *data) { - Demod.output = data; - DemodReset(); - // memset(Demod.output, 0x00, MAX_FRAME_SIZE); + Demod.output = data; + DemodReset(); + // memset(Demod.output, 0x00, MAX_FRAME_SIZE); } @@ -154,19 +154,19 @@ static void DemodInit(uint8_t *data) { * @param timeout is in frame wait time, fwt, measured in ETUs */ static void iso14b_set_timeout(uint32_t timeout) { - #define MAX_TIMEOUT 40542464 // 13560000Hz * 1000ms / (2^32-1) * (8*16) - if(timeout > MAX_TIMEOUT) - timeout = MAX_TIMEOUT; + #define MAX_TIMEOUT 40542464 // 13560000Hz * 1000ms / (2^32-1) * (8*16) + if(timeout > MAX_TIMEOUT) + timeout = MAX_TIMEOUT; - iso14b_timeout = timeout; - if(MF_DBGLEVEL >= 3) Dbprintf("ISO14443B Timeout set to %ld fwt", iso14b_timeout); + iso14b_timeout = timeout; + if(MF_DBGLEVEL >= 3) Dbprintf("ISO14443B Timeout set to %ld fwt", iso14b_timeout); } static void iso14b_set_maxframesize(uint16_t size) { - if (size > 256) - size = MAX_FRAME_SIZE; + if (size > 256) + size = MAX_FRAME_SIZE; - Uart.byteCntMax = size; - if(MF_DBGLEVEL >= 3) Dbprintf("ISO14443B Max frame size set to %d bytes", Uart.byteCntMax); + Uart.byteCntMax = size; + if(MF_DBGLEVEL >= 3) Dbprintf("ISO14443B Max frame size set to %d bytes", Uart.byteCntMax); } //----------------------------------------------------------------------------- @@ -175,132 +175,132 @@ static void iso14b_set_maxframesize(uint16_t size) { // them yet, just leaves them ready to send in ToSend[]. //----------------------------------------------------------------------------- static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { - /* ISO 14443 B - * - * Reader to card | ASK - Amplitude Shift Keying Modulation (PCD to PICC for Type B) (NRZ-L encodig) - * Card to reader | BPSK - Binary Phase Shift Keying Modulation, (PICC to PCD for Type B) - * - * fc - carrier frequency 13.56mHz - * TR0 - Guard Time per 14443-2 - * TR1 - Synchronization Time per 14443-2 - * TR2 - PICC to PCD Frame Delay Time (per 14443-3 Amendment 1) - * - * Elementary Time Unit (ETU) is - * - 128 Carrier Cycles (9.4395 µS) = 8 Subcarrier Units - * - 1 ETU = 1 bit - * - 10 ETU = 1 startbit, 8 databits, 1 stopbit (10bits length) - * - startbit is a 0 - * - stopbit is a 1 - * - * Start of frame (SOF) is - * - [10-11] ETU of ZEROS, unmodulated time - * - [2-3] ETU of ONES, - * - * End of frame (EOF) is - * - [10-11] ETU of ZEROS, unmodulated time - * - * -TO VERIFY THIS BELOW- - * The mode FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK which we use to simulate tag - * works like this: - * - A 1-bit input to the FPGA becomes 8 pulses at 847.5kHz (1.18µS / pulse) == 9.44us - * - A 0-bit input to the FPGA becomes an unmodulated time of 1.18µS or does it become 8 nonpulses for 9.44us - * - * FPGA doesn't seem to work with ETU. It seems to work with pulse / duration instead. - * - * Card sends data ub 847.e kHz subcarrier - * subcar |duration| FC division - * -------+--------+------------ - * 106kHz | 9.44µS | FC/128 - * 212kHz | 4.72µS | FC/64 - * 424kHz | 2.36µS | FC/32 - * 848kHz | 1.18µS | FC/16 - * -------+--------+------------ - * - * Reader data transmission: - * - no modulation ONES - * - SOF - * - Command, data and CRC_B - * - EOF - * - no modulation ONES - * - * Card data transmission - * - TR1 - * - SOF - * - data (each bytes is: 1startbit, 8bits, 1stopbit) - * - CRC_B - * - EOF - * - * FPGA implementation : - * At this point only Type A is implemented. This means that we are using a - * bit rate of 106 kbit/s, or fc/128. Oversample by 4, which ought to make - * things practical for the ARM (fc/32, 423.8 kbits/s, ~50 kbytes/s) - * - */ + /* ISO 14443 B + * + * Reader to card | ASK - Amplitude Shift Keying Modulation (PCD to PICC for Type B) (NRZ-L encodig) + * Card to reader | BPSK - Binary Phase Shift Keying Modulation, (PICC to PCD for Type B) + * + * fc - carrier frequency 13.56mHz + * TR0 - Guard Time per 14443-2 + * TR1 - Synchronization Time per 14443-2 + * TR2 - PICC to PCD Frame Delay Time (per 14443-3 Amendment 1) + * + * Elementary Time Unit (ETU) is + * - 128 Carrier Cycles (9.4395 µS) = 8 Subcarrier Units + * - 1 ETU = 1 bit + * - 10 ETU = 1 startbit, 8 databits, 1 stopbit (10bits length) + * - startbit is a 0 + * - stopbit is a 1 + * + * Start of frame (SOF) is + * - [10-11] ETU of ZEROS, unmodulated time + * - [2-3] ETU of ONES, + * + * End of frame (EOF) is + * - [10-11] ETU of ZEROS, unmodulated time + * + * -TO VERIFY THIS BELOW- + * The mode FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK which we use to simulate tag + * works like this: + * - A 1-bit input to the FPGA becomes 8 pulses at 847.5kHz (1.18µS / pulse) == 9.44us + * - A 0-bit input to the FPGA becomes an unmodulated time of 1.18µS or does it become 8 nonpulses for 9.44us + * + * FPGA doesn't seem to work with ETU. It seems to work with pulse / duration instead. + * + * Card sends data ub 847.e kHz subcarrier + * subcar |duration| FC division + * -------+--------+------------ + * 106kHz | 9.44µS | FC/128 + * 212kHz | 4.72µS | FC/64 + * 424kHz | 2.36µS | FC/32 + * 848kHz | 1.18µS | FC/16 + * -------+--------+------------ + * + * Reader data transmission: + * - no modulation ONES + * - SOF + * - Command, data and CRC_B + * - EOF + * - no modulation ONES + * + * Card data transmission + * - TR1 + * - SOF + * - data (each bytes is: 1startbit, 8bits, 1stopbit) + * - CRC_B + * - EOF + * + * FPGA implementation : + * At this point only Type A is implemented. This means that we are using a + * bit rate of 106 kbit/s, or fc/128. Oversample by 4, which ought to make + * things practical for the ARM (fc/32, 423.8 kbits/s, ~50 kbytes/s) + * + */ - int i,j; - uint8_t b; + int i,j; + uint8_t b; - ToSendReset(); + ToSendReset(); - // Transmit a burst of ones, as the initial thing that lets the - // reader get phase sync. - // This loop is TR1, per specification - // TR1 minimum must be > 80/fs - // TR1 maximum 200/fs - // 80/fs < TR1 < 200/fs - // 10 ETU < TR1 < 24 ETU + // Transmit a burst of ones, as the initial thing that lets the + // reader get phase sync. + // This loop is TR1, per specification + // TR1 minimum must be > 80/fs + // TR1 maximum 200/fs + // 80/fs < TR1 < 200/fs + // 10 ETU < TR1 < 24 ETU - // Send SOF. - // 10-11 ETU * 4times samples ZEROS - for(i = 0; i < 10; i++) { SEND4STUFFBIT(0); } - //for(i = 0; i < 10; i++) { ToSendStuffBit(0); } + // Send SOF. + // 10-11 ETU * 4times samples ZEROS + for(i = 0; i < 10; i++) { SEND4STUFFBIT(0); } + //for(i = 0; i < 10; i++) { ToSendStuffBit(0); } - // 2-3 ETU * 4times samples ONES - for(i = 0; i < 3; i++) { SEND4STUFFBIT(1); } - //for(i = 0; i < 3; i++) { ToSendStuffBit(1); } + // 2-3 ETU * 4times samples ONES + for(i = 0; i < 3; i++) { SEND4STUFFBIT(1); } + //for(i = 0; i < 3; i++) { ToSendStuffBit(1); } - // data - for(i = 0; i < len; ++i) { + // data + for(i = 0; i < len; ++i) { - // Start bit - SEND4STUFFBIT(0); - //ToSendStuffBit(0); + // Start bit + SEND4STUFFBIT(0); + //ToSendStuffBit(0); - // Data bits - b = cmd[i]; - for(j = 0; j < 8; ++j) { - // if(b & 1) { - // SEND4STUFFBIT(1); - // //ToSendStuffBit(1); - // } else { - // SEND4STUFFBIT(0); - // //ToSendStuffBit(0); - // } - SEND4STUFFBIT( b & 1 ); - b >>= 1; - } + // Data bits + b = cmd[i]; + for(j = 0; j < 8; ++j) { + // if(b & 1) { + // SEND4STUFFBIT(1); + // //ToSendStuffBit(1); + // } else { + // SEND4STUFFBIT(0); + // //ToSendStuffBit(0); + // } + SEND4STUFFBIT( b & 1 ); + b >>= 1; + } - // Stop bit - SEND4STUFFBIT(1); - //ToSendStuffBit(1); + // Stop bit + SEND4STUFFBIT(1); + //ToSendStuffBit(1); - // Extra Guard bit - // For PICC it ranges 0-18us (1etu = 9us) - SEND4STUFFBIT(1); - //ToSendStuffBit(1); - } + // Extra Guard bit + // For PICC it ranges 0-18us (1etu = 9us) + SEND4STUFFBIT(1); + //ToSendStuffBit(1); + } - // Send EOF. - // 10-11 ETU * 4 sample rate = ZEROS - for(i = 0; i < 10; i++) { SEND4STUFFBIT(0); } - //for(i = 0; i < 10; i++) { ToSendStuffBit(0); } + // Send EOF. + // 10-11 ETU * 4 sample rate = ZEROS + for(i = 0; i < 10; i++) { SEND4STUFFBIT(0); } + //for(i = 0; i < 10; i++) { ToSendStuffBit(0); } - // why this? - for(i = 0; i < 40; i++) { SEND4STUFFBIT(1); } - //for(i = 0; i < 40; i++) { ToSendStuffBit(1); } + // why this? + for(i = 0; i < 40; i++) { SEND4STUFFBIT(1); } + //for(i = 0; i < 40; i++) { ToSendStuffBit(1); } - // Convert from last byte pos to length - ++ToSendMax; + // Convert from last byte pos to length + ++ToSendMax; } @@ -317,111 +317,111 @@ static void CodeIso14443bAsTag(const uint8_t *cmd, int len) { * false if we are still waiting for some more */ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) { - switch (Uart.state) { - case STATE_UNSYNCD: - if (!bit) { - // we went low, so this could be the beginning of an SOF - Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF; - Uart.posCnt = 0; - Uart.bitCnt = 0; - } - break; + switch (Uart.state) { + case STATE_UNSYNCD: + if (!bit) { + // we went low, so this could be the beginning of an SOF + Uart.state = STATE_GOT_FALLING_EDGE_OF_SOF; + Uart.posCnt = 0; + Uart.bitCnt = 0; + } + break; - case STATE_GOT_FALLING_EDGE_OF_SOF: - Uart.posCnt++; - if (Uart.posCnt == 2) { // sample every 4 1/fs in the middle of a bit - if (bit) { - if (Uart.bitCnt > 9) { - // we've seen enough consecutive - // zeros that it's a valid SOF - Uart.posCnt = 0; - Uart.byteCnt = 0; - Uart.state = STATE_AWAITING_START_BIT; - LED_A_ON(); // Indicate we got a valid SOF - } else { - // didn't stay down long enough before going high, error - Uart.state = STATE_UNSYNCD; - } - } else { - // do nothing, keep waiting - } - Uart.bitCnt++; - } - if (Uart.posCnt >= 4) Uart.posCnt = 0; - if (Uart.bitCnt > 12) { - // Give up if we see too many zeros without a one, too. - LED_A_OFF(); - Uart.state = STATE_UNSYNCD; - } - break; + case STATE_GOT_FALLING_EDGE_OF_SOF: + Uart.posCnt++; + if (Uart.posCnt == 2) { // sample every 4 1/fs in the middle of a bit + if (bit) { + if (Uart.bitCnt > 9) { + // we've seen enough consecutive + // zeros that it's a valid SOF + Uart.posCnt = 0; + Uart.byteCnt = 0; + Uart.state = STATE_AWAITING_START_BIT; + LED_A_ON(); // Indicate we got a valid SOF + } else { + // didn't stay down long enough before going high, error + Uart.state = STATE_UNSYNCD; + } + } else { + // do nothing, keep waiting + } + Uart.bitCnt++; + } + if (Uart.posCnt >= 4) Uart.posCnt = 0; + if (Uart.bitCnt > 12) { + // Give up if we see too many zeros without a one, too. + LED_A_OFF(); + Uart.state = STATE_UNSYNCD; + } + break; - case STATE_AWAITING_START_BIT: - Uart.posCnt++; - if (bit) { - if (Uart.posCnt > 50/2) { // max 57us between characters = 49 1/fs, max 3 etus after low phase of SOF = 24 1/fs - // stayed high for too long between characters, error - Uart.state = STATE_UNSYNCD; - } - } else { - // falling edge, this starts the data byte - Uart.posCnt = 0; - Uart.bitCnt = 0; - Uart.shiftReg = 0; - Uart.state = STATE_RECEIVING_DATA; - } - break; + case STATE_AWAITING_START_BIT: + Uart.posCnt++; + if (bit) { + if (Uart.posCnt > 50/2) { // max 57us between characters = 49 1/fs, max 3 etus after low phase of SOF = 24 1/fs + // stayed high for too long between characters, error + Uart.state = STATE_UNSYNCD; + } + } else { + // falling edge, this starts the data byte + Uart.posCnt = 0; + Uart.bitCnt = 0; + Uart.shiftReg = 0; + Uart.state = STATE_RECEIVING_DATA; + } + break; - case STATE_RECEIVING_DATA: - Uart.posCnt++; - if (Uart.posCnt == 2) { - // time to sample a bit - Uart.shiftReg >>= 1; - if (bit) { - Uart.shiftReg |= 0x200; - } - Uart.bitCnt++; - } - if (Uart.posCnt >= 4) { - Uart.posCnt = 0; - } - if (Uart.bitCnt == 10) { - if ((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001)) - { - // this is a data byte, with correct - // start and stop bits - Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff; - Uart.byteCnt++; + case STATE_RECEIVING_DATA: + Uart.posCnt++; + if (Uart.posCnt == 2) { + // time to sample a bit + Uart.shiftReg >>= 1; + if (bit) { + Uart.shiftReg |= 0x200; + } + Uart.bitCnt++; + } + if (Uart.posCnt >= 4) { + Uart.posCnt = 0; + } + if (Uart.bitCnt == 10) { + if ((Uart.shiftReg & 0x200) && !(Uart.shiftReg & 0x001)) + { + // this is a data byte, with correct + // start and stop bits + Uart.output[Uart.byteCnt] = (Uart.shiftReg >> 1) & 0xff; + Uart.byteCnt++; - if (Uart.byteCnt >= Uart.byteCntMax) { - // Buffer overflowed, give up - LED_A_OFF(); - Uart.state = STATE_UNSYNCD; - } else { - // so get the next byte now - Uart.posCnt = 0; - Uart.state = STATE_AWAITING_START_BIT; - } - } else if (Uart.shiftReg == 0x000) { - // this is an EOF byte - LED_A_OFF(); // Finished receiving - Uart.state = STATE_UNSYNCD; - if (Uart.byteCnt != 0) - return true; + if (Uart.byteCnt >= Uart.byteCntMax) { + // Buffer overflowed, give up + LED_A_OFF(); + Uart.state = STATE_UNSYNCD; + } else { + // so get the next byte now + Uart.posCnt = 0; + Uart.state = STATE_AWAITING_START_BIT; + } + } else if (Uart.shiftReg == 0x000) { + // this is an EOF byte + LED_A_OFF(); // Finished receiving + Uart.state = STATE_UNSYNCD; + if (Uart.byteCnt != 0) + return true; - } else { - // this is an error - LED_A_OFF(); - Uart.state = STATE_UNSYNCD; - } - } - break; + } else { + // this is an error + LED_A_OFF(); + Uart.state = STATE_UNSYNCD; + } + } + break; - default: - LED_A_OFF(); - Uart.state = STATE_UNSYNCD; - break; - } - return false; + default: + LED_A_OFF(); + Uart.state = STATE_UNSYNCD; + break; + } + return false; } //----------------------------------------------------------------------------- @@ -434,123 +434,123 @@ static RAMFUNC int Handle14443bReaderUartBit(uint8_t bit) { // correctly. //----------------------------------------------------------------------------- static int GetIso14443bCommandFromReader(uint8_t *received, uint16_t *len) { - // Set FPGA mode to "simulated ISO 14443B tag", no modulation (listen - // only, since we are receiving, not transmitting). - // Signal field is off with the appropriate LED - LED_D_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION); + // Set FPGA mode to "simulated ISO 14443B tag", no modulation (listen + // only, since we are receiving, not transmitting). + // Signal field is off with the appropriate LED + LED_D_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_NO_MODULATION); - StartCountSspClk(); + StartCountSspClk(); - volatile uint8_t b = 0; + volatile uint8_t b = 0; - // clear receiving shift register and holding register - // What does this loop do? Is it TR1? - // loop is a wait/delay ? + // clear receiving shift register and holding register + // What does this loop do? Is it TR1? + // loop is a wait/delay ? /* - for(uint8_t c = 0; c < 10;) { + for(uint8_t c = 0; c < 10;) { - // keep tx buffer in a defined state anyway. - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0xFF; - ++c; - } - } - */ - // Now run a `software UART' on the stream of incoming samples. - UartInit(received); + // keep tx buffer in a defined state anyway. + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0xFF; + ++c; + } + } + */ + // Now run a `software UART' on the stream of incoming samples. + UartInit(received); - uint8_t mask; - while( !BUTTON_PRESS() ) { - WDT_HIT(); + uint8_t mask; + while( !BUTTON_PRESS() ) { + WDT_HIT(); - // keep tx buffer in a defined state anyway. - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x00; - } + // keep tx buffer in a defined state anyway. + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0x00; + } - // Wait for byte be become available in rx holding register - if ( AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY ) { + // Wait for byte be become available in rx holding register + if ( AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY ) { - b = (uint8_t) AT91C_BASE_SSC->SSC_RHR; + b = (uint8_t) AT91C_BASE_SSC->SSC_RHR; - for ( mask = 0x80; mask != 0; mask >>= 1) { - if ( Handle14443bReaderUartBit(b & mask)) { - *len = Uart.byteCnt; - return true; - } - } - } - } - return false; + for ( mask = 0x80; mask != 0; mask >>= 1) { + if ( Handle14443bReaderUartBit(b & mask)) { + *len = Uart.byteCnt; + return true; + } + } + } + } + return false; } void ClearFpgaShiftingRegisters(void){ - volatile uint8_t b; + volatile uint8_t b; - // clear receiving shift register and holding register - while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {}; + // clear receiving shift register and holding register + while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {}; - b = AT91C_BASE_SSC->SSC_RHR; (void) b; + b = AT91C_BASE_SSC->SSC_RHR; (void) b; - while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {}; + while(!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {}; - b = AT91C_BASE_SSC->SSC_RHR; (void) b; + b = AT91C_BASE_SSC->SSC_RHR; (void) b; - // wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line) - for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never - while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {}; - if (AT91C_BASE_SSC->SSC_RHR) break; - } + // wait for the FPGA to signal fdt_indicator == 1 (the FPGA is ready to queue new data in its delay line) + for (uint8_t j = 0; j < 5; j++) { // allow timeout - better late than never + while (!(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY)) {}; + if (AT91C_BASE_SSC->SSC_RHR) break; + } - // Clear TXRDY: - //AT91C_BASE_SSC->SSC_THR = 0xFF; + // Clear TXRDY: + //AT91C_BASE_SSC->SSC_THR = 0xFF; } void WaitForFpgaDelayQueueIsEmpty( uint16_t delay ){ - // Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again: - uint8_t fpga_queued_bits = delay >> 3; // twich /8 ?? >>3, - for (uint8_t i = 0; i <= fpga_queued_bits/8 + 1; ) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0xFF; - i++; - } - } + // Ensure that the FPGA Delay Queue is empty before we switch to TAGSIM_LISTEN again: + uint8_t fpga_queued_bits = delay >> 3; // twich /8 ?? >>3, + for (uint8_t i = 0; i <= fpga_queued_bits/8 + 1; ) { + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0xFF; + i++; + } + } } static void TransmitFor14443b_AsTag( uint8_t *response, uint16_t len) { - volatile uint32_t b; + volatile uint32_t b; - // Signal field is off with the appropriate LED - LED_D_OFF(); - //uint16_t fpgasendQueueDelay = 0; + // Signal field is off with the appropriate LED + LED_D_OFF(); + //uint16_t fpgasendQueueDelay = 0; - // Modulate BPSK - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK); - SpinDelay(40); + // Modulate BPSK + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_BPSK); + SpinDelay(40); - ClearFpgaShiftingRegisters(); + ClearFpgaShiftingRegisters(); - FpgaSetupSsc(); + FpgaSetupSsc(); - // Transmit the response. - for(uint16_t i = 0; i < len;) { + // Transmit the response. + for(uint16_t i = 0; i < len;) { - // Put byte into tx holding register as soon as it is ready - if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { - AT91C_BASE_SSC->SSC_THR = response[++i]; - } + // Put byte into tx holding register as soon as it is ready + if(AT91C_BASE_SSC->SSC_SR & AT91C_SSC_TXRDY) { + AT91C_BASE_SSC->SSC_THR = response[++i]; + } - // Prevent rx holding register from overflowing - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - b = AT91C_BASE_SSC->SSC_RHR;(void)b; - } - } + // Prevent rx holding register from overflowing + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + b = AT91C_BASE_SSC->SSC_RHR;(void)b; + } + } - //WaitForFpgaDelayQueueIsEmpty(fpgasendQueueDelay); - AT91C_BASE_SSC->SSC_THR = 0xFF; + //WaitForFpgaDelayQueueIsEmpty(fpgasendQueueDelay); + AT91C_BASE_SSC->SSC_THR = 0xFF; } //----------------------------------------------------------------------------- // Main loop of simulated tag: receive commands from reader, decide what @@ -558,160 +558,160 @@ static void TransmitFor14443b_AsTag( uint8_t *response, uint16_t len) { //----------------------------------------------------------------------------- void SimulateIso14443bTag(uint32_t pupi) { - // setup device. - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - // connect Demodulated Signal to ADC: - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - // Set up the synchronous serial port - FpgaSetupSsc(); + // setup device. + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + // connect Demodulated Signal to ADC: + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + // Set up the synchronous serial port + FpgaSetupSsc(); - // allocate command receive buffer - BigBuf_free(); BigBuf_Clear_ext(false); + // allocate command receive buffer + BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); //sim - set_tracing(true); + clear_trace(); //sim + set_tracing(true); - uint16_t len, cmdsReceived = 0; - int cardSTATE = SIM_NOFIELD; - int vHf = 0; // in mV - // uint32_t time_0 = 0; - // uint32_t t2r_time = 0; - // uint32_t r2t_time = 0; - uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); + uint16_t len, cmdsReceived = 0; + int cardSTATE = SIM_NOFIELD; + int vHf = 0; // in mV + // uint32_t time_0 = 0; + // uint32_t t2r_time = 0; + // uint32_t r2t_time = 0; + uint8_t *receivedCmd = BigBuf_malloc(MAX_FRAME_SIZE); - // the only commands we understand is WUPB, AFI=0, Select All, N=1: -// static const uint8_t cmdWUPB[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 }; // WUPB - // ... and REQB, AFI=0, Normal Request, N=1: -// static const uint8_t cmdREQB[] = { ISO14443B_REQB, 0x00, 0x00, 0x71, 0xFF }; // REQB - // ... and ATTRIB -// static const uint8_t cmdATTRIB[] = { ISO14443B_ATTRIB, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // ATTRIB + // the only commands we understand is WUPB, AFI=0, Select All, N=1: +// static const uint8_t cmdWUPB[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 }; // WUPB + // ... and REQB, AFI=0, Normal Request, N=1: +// static const uint8_t cmdREQB[] = { ISO14443B_REQB, 0x00, 0x00, 0x71, 0xFF }; // REQB + // ... and ATTRIB +// static const uint8_t cmdATTRIB[] = { ISO14443B_ATTRIB, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; // ATTRIB - // ... if not PUPI/UID is supplied we always respond with ATQB, PUPI = 820de174, Application Data = 0x20381922, - // supports only 106kBit/s in both directions, max frame size = 32Bytes, - // supports ISO14443-4, FWI=8 (77ms), NAD supported, CID not supported: - uint8_t respATQB[] = { 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, - 0x22, 0x00, 0x21, 0x85, 0x5e, 0xd7 }; + // ... if not PUPI/UID is supplied we always respond with ATQB, PUPI = 820de174, Application Data = 0x20381922, + // supports only 106kBit/s in both directions, max frame size = 32Bytes, + // supports ISO14443-4, FWI=8 (77ms), NAD supported, CID not supported: + uint8_t respATQB[] = { 0x50, 0x82, 0x0d, 0xe1, 0x74, 0x20, 0x38, 0x19, + 0x22, 0x00, 0x21, 0x85, 0x5e, 0xd7 }; - // response to HLTB and ATTRIB - static const uint8_t respOK[] = {0x00, 0x78, 0xF0}; + // response to HLTB and ATTRIB + static const uint8_t respOK[] = {0x00, 0x78, 0xF0}; - // ...PUPI/UID supplied from user. Adjust ATQB response accordingly - if ( pupi > 0 ) { - num_to_bytes(pupi, 4, respATQB+1); - AddCrc14B(respATQB, 12); - } + // ...PUPI/UID supplied from user. Adjust ATQB response accordingly + if ( pupi > 0 ) { + num_to_bytes(pupi, 4, respATQB+1); + AddCrc14B(respATQB, 12); + } - // prepare "ATQB" tag answer (encoded): - CodeIso14443bAsTag(respATQB, sizeof(respATQB)); - uint8_t *encodedATQB = BigBuf_malloc(ToSendMax); - uint16_t encodedATQBLen = ToSendMax; - memcpy(encodedATQB, ToSend, ToSendMax); + // prepare "ATQB" tag answer (encoded): + CodeIso14443bAsTag(respATQB, sizeof(respATQB)); + uint8_t *encodedATQB = BigBuf_malloc(ToSendMax); + uint16_t encodedATQBLen = ToSendMax; + memcpy(encodedATQB, ToSend, ToSendMax); - // prepare "OK" tag answer (encoded): - CodeIso14443bAsTag(respOK, sizeof(respOK)); - uint8_t *encodedOK = BigBuf_malloc(ToSendMax); - uint16_t encodedOKLen = ToSendMax; - memcpy(encodedOK, ToSend, ToSendMax); + // prepare "OK" tag answer (encoded): + CodeIso14443bAsTag(respOK, sizeof(respOK)); + uint8_t *encodedOK = BigBuf_malloc(ToSendMax); + uint16_t encodedOKLen = ToSendMax; + memcpy(encodedOK, ToSend, ToSendMax); - // Simulation loop - while (!BUTTON_PRESS() && !usb_poll_validate_length()) { - WDT_HIT(); + // Simulation loop + while (!BUTTON_PRESS() && !usb_poll_validate_length()) { + WDT_HIT(); - // find reader field - if (cardSTATE == SIM_NOFIELD) { - vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; - if ( vHf > MF_MINFIELDV ) { - cardSTATE = SIM_IDLE; - LED_A_ON(); - } - } - if (cardSTATE == SIM_NOFIELD) continue; + // find reader field + if (cardSTATE == SIM_NOFIELD) { + vHf = (MAX_ADC_HF_VOLTAGE * AvgAdc(ADC_CHAN_HF)) >> 10; + if ( vHf > MF_MINFIELDV ) { + cardSTATE = SIM_IDLE; + LED_A_ON(); + } + } + if (cardSTATE == SIM_NOFIELD) continue; - // Get reader command - if (!GetIso14443bCommandFromReader(receivedCmd, &len)) { - Dbprintf("button pressed, received %d commands", cmdsReceived); - break; - } + // Get reader command + if (!GetIso14443bCommandFromReader(receivedCmd, &len)) { + Dbprintf("button pressed, received %d commands", cmdsReceived); + break; + } - // ISO14443-B protocol states: - // REQ or WUP request in ANY state - // WUP in HALTED state - if (len == 5 ) { - if ( (receivedCmd[0] == ISO14443B_REQB && (receivedCmd[2] & 0x8)== 0x8 && cardSTATE == SIM_HALTED) || - receivedCmd[0] == ISO14443B_REQB ){ - LogTrace(receivedCmd, len, 0, 0, NULL, true); - cardSTATE = SIM_SELECTING; - } - } + // ISO14443-B protocol states: + // REQ or WUP request in ANY state + // WUP in HALTED state + if (len == 5 ) { + if ( (receivedCmd[0] == ISO14443B_REQB && (receivedCmd[2] & 0x8)== 0x8 && cardSTATE == SIM_HALTED) || + receivedCmd[0] == ISO14443B_REQB ){ + LogTrace(receivedCmd, len, 0, 0, NULL, true); + cardSTATE = SIM_SELECTING; + } + } - /* - * How should this flow go? - * REQB or WUPB - * send response ( waiting for Attrib) - * ATTRIB - * send response ( waiting for commands 7816) - * HALT - send halt response ( waiting for wupb ) - */ + /* + * How should this flow go? + * REQB or WUPB + * send response ( waiting for Attrib) + * ATTRIB + * send response ( waiting for commands 7816) + * HALT + send halt response ( waiting for wupb ) + */ - switch (cardSTATE) { - //case SIM_NOFIELD: - case SIM_HALTED: - case SIM_IDLE: { - LogTrace(receivedCmd, len, 0, 0, NULL, true); - break; - } - case SIM_SELECTING: { - TransmitFor14443b_AsTag( encodedATQB, encodedATQBLen ); - LogTrace(respATQB, sizeof(respATQB), 0, 0, NULL, false); - cardSTATE = SIM_WORK; - break; - } - case SIM_HALTING: { - TransmitFor14443b_AsTag( encodedOK, encodedOKLen ); - LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false); - cardSTATE = SIM_HALTED; - break; - } - case SIM_ACKNOWLEDGE: { - TransmitFor14443b_AsTag( encodedOK, encodedOKLen ); - LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false); - cardSTATE = SIM_IDLE; - break; - } - case SIM_WORK: { - if ( len == 7 && receivedCmd[0] == ISO14443B_HALT ) { - cardSTATE = SIM_HALTED; - } else if ( len == 11 && receivedCmd[0] == ISO14443B_ATTRIB ) { - cardSTATE = SIM_ACKNOWLEDGE; - } else { - // Todo: - // - SLOT MARKER - // - ISO7816 - // - emulate with a memory dump - Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsReceived); + switch (cardSTATE) { + //case SIM_NOFIELD: + case SIM_HALTED: + case SIM_IDLE: { + LogTrace(receivedCmd, len, 0, 0, NULL, true); + break; + } + case SIM_SELECTING: { + TransmitFor14443b_AsTag( encodedATQB, encodedATQBLen ); + LogTrace(respATQB, sizeof(respATQB), 0, 0, NULL, false); + cardSTATE = SIM_WORK; + break; + } + case SIM_HALTING: { + TransmitFor14443b_AsTag( encodedOK, encodedOKLen ); + LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false); + cardSTATE = SIM_HALTED; + break; + } + case SIM_ACKNOWLEDGE: { + TransmitFor14443b_AsTag( encodedOK, encodedOKLen ); + LogTrace(respOK, sizeof(respOK), 0, 0, NULL, false); + cardSTATE = SIM_IDLE; + break; + } + case SIM_WORK: { + if ( len == 7 && receivedCmd[0] == ISO14443B_HALT ) { + cardSTATE = SIM_HALTED; + } else if ( len == 11 && receivedCmd[0] == ISO14443B_ATTRIB ) { + cardSTATE = SIM_ACKNOWLEDGE; + } else { + // Todo: + // - SLOT MARKER + // - ISO7816 + // - emulate with a memory dump + Dbprintf("new cmd from reader: len=%d, cmdsRecvd=%d", len, cmdsReceived); - // CRC Check - if (len >= 3){ // if crc exists + // CRC Check + if (len >= 3){ // if crc exists - if (!check_crc(CRC_14443_B, receivedCmd, len)) - DbpString("+++CRC fail"); - else - DbpString("CRC passes"); - } - cardSTATE = SIM_IDLE; - } - break; - } - default: break; - } + if (!check_crc(CRC_14443_B, receivedCmd, len)) + DbpString("+++CRC fail"); + else + DbpString("CRC passes"); + } + cardSTATE = SIM_IDLE; + } + break; + } + default: break; + } - ++cmdsReceived; - } - if (MF_DBGLEVEL >= 2) - Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen()); - switch_off(); //simulate + ++cmdsReceived; + } + if (MF_DBGLEVEL >= 2) + Dbprintf("Emulator stopped. Trace length: %d ", BigBuf_get_traceLen()); + switch_off(); //simulate } //============================================================================= @@ -736,202 +736,202 @@ void SimulateIso14443bTag(uint32_t pupi) { * */ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { - int v = 0, myI = ABS(ci), myQ = ABS(cq); + int v = 0, myI = ABS(ci), myQ = ABS(cq); // The soft decision on the bit uses an estimate of just the // quadrant of the reference angle, not the exact angle. #define MAKE_SOFT_DECISION() { \ - if (Demod.sumI > 0) { \ - v = ci; \ - } else { \ - v = -ci; \ - } \ - if (Demod.sumQ > 0) { \ - v += cq; \ - } else { \ - v -= cq; \ - } \ - } + if (Demod.sumI > 0) { \ + v = ci; \ + } else { \ + v = -ci; \ + } \ + if (Demod.sumQ > 0) { \ + v += cq; \ + } else { \ + v -= cq; \ + } \ + } // Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by abs(ci) + abs(cq) // Subcarrier amplitude v = sqrt(ci^2 + cq^2), approximated here by max(abs(ci),abs(cq)) + 1/2*min(abs(ci),abs(cq))) #define CHECK_FOR_SUBCARRIER_old() { \ - if (ci < 0) { \ - if (cq < 0) { /* ci < 0, cq < 0 */ \ - if (cq < ci) { \ - v = -cq - (ci >> 1); \ - } else { \ - v = -ci - (cq >> 1); \ - } \ - } else { /* ci < 0, cq >= 0 */ \ - if (cq < -ci) { \ - v = -ci + (cq >> 1); \ - } else { \ - v = cq - (ci >> 1); \ - } \ - } \ - } else { \ - if (cq < 0) { /* ci >= 0, cq < 0 */ \ - if (-cq < ci) { \ - v = ci - (cq >> 1); \ - } else { \ - v = -cq + (ci >> 1); \ - } \ - } else { /* ci >= 0, cq >= 0 */ \ - if (cq < ci) { \ - v = ci + (cq >> 1); \ - } else { \ - v = cq + (ci >> 1); \ - } \ - } \ - } \ - } + if (ci < 0) { \ + if (cq < 0) { /* ci < 0, cq < 0 */ \ + if (cq < ci) { \ + v = -cq - (ci >> 1); \ + } else { \ + v = -ci - (cq >> 1); \ + } \ + } else { /* ci < 0, cq >= 0 */ \ + if (cq < -ci) { \ + v = -ci + (cq >> 1); \ + } else { \ + v = cq - (ci >> 1); \ + } \ + } \ + } else { \ + if (cq < 0) { /* ci >= 0, cq < 0 */ \ + if (-cq < ci) { \ + v = ci - (cq >> 1); \ + } else { \ + v = -cq + (ci >> 1); \ + } \ + } else { /* ci >= 0, cq >= 0 */ \ + if (cq < ci) { \ + v = ci + (cq >> 1); \ + } else { \ + v = cq + (ci >> 1); \ + } \ + } \ + } \ + } //note: couldn't we just use MAX(ABS(ci),ABS(cq)) + (MIN(ABS(ci),ABS(cq))/2) from common.h - marshmellow #define CHECK_FOR_SUBCARRIER() { v = MAX(myI, myQ) + (MIN(myI, myQ) >> 1); } - switch(Demod.state) { - case DEMOD_UNSYNCD: + switch(Demod.state) { + case DEMOD_UNSYNCD: - CHECK_FOR_SUBCARRIER(); + CHECK_FOR_SUBCARRIER(); - // subcarrier detected + // subcarrier detected - if (v > SUBCARRIER_DETECT_THRESHOLD) { - Demod.state = DEMOD_PHASE_REF_TRAINING; - Demod.sumI = ci; - Demod.sumQ = cq; - Demod.posCount = 1; - } - break; + if (v > SUBCARRIER_DETECT_THRESHOLD) { + Demod.state = DEMOD_PHASE_REF_TRAINING; + Demod.sumI = ci; + Demod.sumQ = cq; + Demod.posCount = 1; + } + break; - case DEMOD_PHASE_REF_TRAINING: - if (Demod.posCount < 8) { + case DEMOD_PHASE_REF_TRAINING: + if (Demod.posCount < 8) { - CHECK_FOR_SUBCARRIER(); + CHECK_FOR_SUBCARRIER(); - if (v > SUBCARRIER_DETECT_THRESHOLD) { - // set the reference phase (will code a logic '1') by averaging over 32 1/fs. - // note: synchronization time > 80 1/fs - Demod.sumI += ci; - Demod.sumQ += cq; - Demod.posCount++; - } else { - // subcarrier lost - Demod.state = DEMOD_UNSYNCD; - } - } else { - Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF; - } - break; + if (v > SUBCARRIER_DETECT_THRESHOLD) { + // set the reference phase (will code a logic '1') by averaging over 32 1/fs. + // note: synchronization time > 80 1/fs + Demod.sumI += ci; + Demod.sumQ += cq; + Demod.posCount++; + } else { + // subcarrier lost + Demod.state = DEMOD_UNSYNCD; + } + } else { + Demod.state = DEMOD_AWAITING_FALLING_EDGE_OF_SOF; + } + break; - case DEMOD_AWAITING_FALLING_EDGE_OF_SOF: + case DEMOD_AWAITING_FALLING_EDGE_OF_SOF: - MAKE_SOFT_DECISION(); + MAKE_SOFT_DECISION(); - if (v < 0) { // logic '0' detected - Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF; - Demod.posCount = 0; // start of SOF sequence - } else { - // maximum length of TR1 = 200 1/fs - if (Demod.posCount > 200/4) Demod.state = DEMOD_UNSYNCD; - } - Demod.posCount++; - break; + if (v < 0) { // logic '0' detected + Demod.state = DEMOD_GOT_FALLING_EDGE_OF_SOF; + Demod.posCount = 0; // start of SOF sequence + } else { + // maximum length of TR1 = 200 1/fs + if (Demod.posCount > 200/4) Demod.state = DEMOD_UNSYNCD; + } + Demod.posCount++; + break; - case DEMOD_GOT_FALLING_EDGE_OF_SOF: - Demod.posCount++; + case DEMOD_GOT_FALLING_EDGE_OF_SOF: + Demod.posCount++; - MAKE_SOFT_DECISION(); + MAKE_SOFT_DECISION(); - if (v > 0) { - // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges - if (Demod.posCount < 9*2) { - Demod.state = DEMOD_UNSYNCD; - } else { - LED_C_ON(); // Got SOF - Demod.state = DEMOD_AWAITING_START_BIT; - Demod.posCount = 0; - Demod.len = 0; - } - } else { - // low phase of SOF too long (> 12 etu) - if (Demod.posCount > 14*2) { - Demod.state = DEMOD_UNSYNCD; - LED_C_OFF(); - } - } - break; + if (v > 0) { + // low phase of SOF too short (< 9 etu). Note: spec is >= 10, but FPGA tends to "smear" edges + if (Demod.posCount < 9*2) { + Demod.state = DEMOD_UNSYNCD; + } else { + LED_C_ON(); // Got SOF + Demod.state = DEMOD_AWAITING_START_BIT; + Demod.posCount = 0; + Demod.len = 0; + } + } else { + // low phase of SOF too long (> 12 etu) + if (Demod.posCount > 14*2) { + Demod.state = DEMOD_UNSYNCD; + LED_C_OFF(); + } + } + break; - case DEMOD_AWAITING_START_BIT: - Demod.posCount++; + case DEMOD_AWAITING_START_BIT: + Demod.posCount++; - MAKE_SOFT_DECISION(); + MAKE_SOFT_DECISION(); - if (v > 0) { - if (Demod.posCount > 6*2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs - Demod.state = DEMOD_UNSYNCD; - LED_C_OFF(); - } - } else { // start bit detected - Demod.bitCount = 0; - Demod.posCount = 1; // this was the first half - Demod.thisBit = v; - Demod.shiftReg = 0; - Demod.state = DEMOD_RECEIVING_DATA; - } - break; + if (v > 0) { + if (Demod.posCount > 6*2) { // max 19us between characters = 16 1/fs, max 3 etu after low phase of SOF = 24 1/fs + Demod.state = DEMOD_UNSYNCD; + LED_C_OFF(); + } + } else { // start bit detected + Demod.bitCount = 0; + Demod.posCount = 1; // this was the first half + Demod.thisBit = v; + Demod.shiftReg = 0; + Demod.state = DEMOD_RECEIVING_DATA; + } + break; - case DEMOD_RECEIVING_DATA: + case DEMOD_RECEIVING_DATA: - MAKE_SOFT_DECISION(); + MAKE_SOFT_DECISION(); - if (Demod.posCount == 0) { - // first half of bit - Demod.thisBit = v; - Demod.posCount = 1; - } else { - // second half of bit - Demod.thisBit += v; - Demod.shiftReg >>= 1; + if (Demod.posCount == 0) { + // first half of bit + Demod.thisBit = v; + Demod.posCount = 1; + } else { + // second half of bit + Demod.thisBit += v; + Demod.shiftReg >>= 1; - // OR in a logic '1' - if (Demod.thisBit > 0) - Demod.shiftReg |= 0x200; + // OR in a logic '1' + if (Demod.thisBit > 0) + Demod.shiftReg |= 0x200; - Demod.bitCount++; + Demod.bitCount++; - // 1 start 8 data 1 stop = 10 - if (Demod.bitCount == 10) { + // 1 start 8 data 1 stop = 10 + if (Demod.bitCount == 10) { - uint16_t s = Demod.shiftReg; + uint16_t s = Demod.shiftReg; - // stop bit == '1', start bit == '0' - if ((s & 0x200) && (s & 0x001) == 0 ) { - // left shift to drop the startbit - uint8_t b = (s >> 1); - Demod.output[Demod.len] = b; - ++Demod.len; - Demod.state = DEMOD_AWAITING_START_BIT; - } else { - // this one is a bit hard, either its a correc byte or its unsynced. - Demod.state = DEMOD_UNSYNCD; - LED_C_OFF(); + // stop bit == '1', start bit == '0' + if ((s & 0x200) && (s & 0x001) == 0 ) { + // left shift to drop the startbit + uint8_t b = (s >> 1); + Demod.output[Demod.len] = b; + ++Demod.len; + Demod.state = DEMOD_AWAITING_START_BIT; + } else { + // this one is a bit hard, either its a correc byte or its unsynced. + Demod.state = DEMOD_UNSYNCD; + LED_C_OFF(); - // This is EOF (start, stop and all data bits == '0' - if (s == 0) return true; - } - } - Demod.posCount = 0; - } - break; + // This is EOF (start, stop and all data bits == '0' + if (s == 0) return true; + } + } + Demod.posCount = 0; + } + break; - default: - Demod.state = DEMOD_UNSYNCD; - LED_C_OFF(); - break; - } - return false; + default: + Demod.state = DEMOD_UNSYNCD; + LED_C_OFF(); + break; + } + return false; } @@ -940,99 +940,99 @@ static RAMFUNC int Handle14443bTagSamplesDemod(int ci, int cq) { * quiet: set to 'TRUE' to disable debug output */ static void GetTagSamplesFor14443bDemod() { - bool gotFrame = false, finished = false; - int lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; - int ci = 0, cq = 0; - uint32_t time_0 = 0, time_stop = 0; + bool gotFrame = false, finished = false; + int lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; + int ci = 0, cq = 0; + uint32_t time_0 = 0, time_stop = 0; - BigBuf_free(); + BigBuf_free(); - // Set up the demodulator for tag -> reader responses. - DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); + // Set up the demodulator for tag -> reader responses. + DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); - // The DMA buffer, used to stream samples from the FPGA - int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); - int8_t *upTo = dmaBuf; + // The DMA buffer, used to stream samples from the FPGA + int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); + int8_t *upTo = dmaBuf; - // Setup and start DMA. - if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE) ){ - if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); - return; - } + // Setup and start DMA. + if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE) ){ + if (MF_DBGLEVEL > 1) Dbprintf("FpgaSetupSscDma failed. Exiting"); + return; + } - // And put the FPGA in the appropriate mode - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ); + // And put the FPGA in the appropriate mode + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ); - // get current clock - time_0 = GetCountSspClk(); + // get current clock + time_0 = GetCountSspClk(); - // rx counter - dma counter? (how much?) & (mod) mask > 2. (since 2bytes at the time is read) - while ( !finished ) { + // rx counter - dma counter? (how much?) & (mod) mask > 2. (since 2bytes at the time is read) + while ( !finished ) { - LED_A_INV(); - WDT_HIT(); + LED_A_INV(); + WDT_HIT(); - // LSB is a fpga signal bit. - ci = upTo[0]; - cq = upTo[1]; - upTo += 2; - lastRxCounter -= 2; + // LSB is a fpga signal bit. + ci = upTo[0]; + cq = upTo[1]; + upTo += 2; + lastRxCounter -= 2; - // restart DMA buffer to receive again. - if(upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { - upTo = dmaBuf; - lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; - AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo; - AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; - } + // restart DMA buffer to receive again. + if(upTo >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { + upTo = dmaBuf; + lastRxCounter = ISO14443B_DMA_BUFFER_SIZE; + AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) upTo; + AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; + } - // https://github.com/Proxmark/proxmark3/issues/103 - gotFrame = Handle14443bTagSamplesDemod(ci, cq); - time_stop = GetCountSspClk() - time_0; + // https://github.com/Proxmark/proxmark3/issues/103 + gotFrame = Handle14443bTagSamplesDemod(ci, cq); + time_stop = GetCountSspClk() - time_0; - finished = (time_stop > iso14b_timeout || gotFrame); - } + finished = (time_stop > iso14b_timeout || gotFrame); + } - FpgaDisableSscDma(); + FpgaDisableSscDma(); - if ( upTo ) - upTo = NULL; + if ( upTo ) + upTo = NULL; - if ( Demod.len > 0 ) - LogTrace(Demod.output, Demod.len, time_0, time_stop, NULL, false); + if ( Demod.len > 0 ) + LogTrace(Demod.output, Demod.len, time_0, time_stop, NULL, false); } //----------------------------------------------------------------------------- // Transmit the command (to the tag) that was placed in ToSend[]. //----------------------------------------------------------------------------- static void TransmitFor14443b_AsReader(void) { - int c; + int c; - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); - SpinDelay(60); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); + SpinDelay(60); - // What does this loop do? Is it TR1? - // 0xFF = 8 bits of 1. 1 bit == 1Etu,.. - // loop 10 * 8 = 80 ETU of delay, with a non modulated signal. why? - // 80*9 = 720us. + // What does this loop do? Is it TR1? + // 0xFF = 8 bits of 1. 1 bit == 1Etu,.. + // loop 10 * 8 = 80 ETU of delay, with a non modulated signal. why? + // 80*9 = 720us. - for(c = 0; c < 50;) { + for(c = 0; c < 50;) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0xFF; - c++; - } - } + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0xFF; + c++; + } + } - // Send frame loop - for(c = 0; c < ToSendMax;) { + // Send frame loop + for(c = 0; c < ToSendMax;) { - // Put byte into tx holding register as soon as it is ready - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = ToSend[c++]; - } - } - WDT_HIT(); + // Put byte into tx holding register as soon as it is ready + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = ToSend[c++]; + } + } + WDT_HIT(); } //----------------------------------------------------------------------------- @@ -1040,81 +1040,81 @@ static void TransmitFor14443b_AsReader(void) { // so that it is ready to transmit to the tag using TransmitFor14443b(). //----------------------------------------------------------------------------- static void CodeIso14443bAsReader(const uint8_t *cmd, int len) { - /* - * Reader data transmission: - * - no modulation ONES - * - SOF - * - Command, data and CRC_B - * - EOF - * - no modulation ONES - * - * 1 ETU == 1 BIT! - * TR0 - 8 ETUS minimum. - * - * QUESTION: how long is a 1 or 0 in pulses in the xcorr_848 mode? - * 1 "stuffbit" = 1ETU (9us) - */ - int i; - uint8_t b; + /* + * Reader data transmission: + * - no modulation ONES + * - SOF + * - Command, data and CRC_B + * - EOF + * - no modulation ONES + * + * 1 ETU == 1 BIT! + * TR0 - 8 ETUS minimum. + * + * QUESTION: how long is a 1 or 0 in pulses in the xcorr_848 mode? + * 1 "stuffbit" = 1ETU (9us) + */ + int i; + uint8_t b; - ToSendReset(); + ToSendReset(); - // Send SOF - // 10-11 ETUs of ZERO - for(i = 0; i < 10; ++i) ToSendStuffBit(0); + // Send SOF + // 10-11 ETUs of ZERO + for(i = 0; i < 10; ++i) ToSendStuffBit(0); - // 2-3 ETUs of ONE - ToSendStuffBit(1); - ToSendStuffBit(1); -// ToSendStuffBit(1); + // 2-3 ETUs of ONE + ToSendStuffBit(1); + ToSendStuffBit(1); +// ToSendStuffBit(1); - // Sending cmd, LSB - // from here we add BITS - for(i = 0; i < len; ++i) { - // Start bit - ToSendStuffBit(0); - // Data bits - b = cmd[i]; - // if ( b & 1 ) ToSendStuffBit(1); else ToSendStuffBit(0); - // if ( (b>>1) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - // if ( (b>>2) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - // if ( (b>>3) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - // if ( (b>>4) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - // if ( (b>>5) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - // if ( (b>>6) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - // if ( (b>>7) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + // Sending cmd, LSB + // from here we add BITS + for(i = 0; i < len; ++i) { + // Start bit + ToSendStuffBit(0); + // Data bits + b = cmd[i]; + // if ( b & 1 ) ToSendStuffBit(1); else ToSendStuffBit(0); + // if ( (b>>1) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + // if ( (b>>2) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + // if ( (b>>3) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + // if ( (b>>4) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + // if ( (b>>5) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + // if ( (b>>6) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); + // if ( (b>>7) & 1) ToSendStuffBit(1); else ToSendStuffBit(0); - ToSendStuffBit( b & 1); - ToSendStuffBit( (b>>1) & 1); - ToSendStuffBit( (b>>2) & 1); - ToSendStuffBit( (b>>3) & 1); - ToSendStuffBit( (b>>4) & 1); - ToSendStuffBit( (b>>5) & 1); - ToSendStuffBit( (b>>6) & 1); - ToSendStuffBit( (b>>7) & 1); + ToSendStuffBit( b & 1); + ToSendStuffBit( (b>>1) & 1); + ToSendStuffBit( (b>>2) & 1); + ToSendStuffBit( (b>>3) & 1); + ToSendStuffBit( (b>>4) & 1); + ToSendStuffBit( (b>>5) & 1); + ToSendStuffBit( (b>>6) & 1); + ToSendStuffBit( (b>>7) & 1); - // Stop bit - ToSendStuffBit(1); - // EGT extra guard time - // For PCD it ranges 0-57us (1etu = 9us) - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - } + // Stop bit + ToSendStuffBit(1); + // EGT extra guard time + // For PCD it ranges 0-57us (1etu = 9us) + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + } - // Send EOF - // 10-11 ETUs of ZERO - for(i = 0; i < 10; ++i) ToSendStuffBit(0); + // Send EOF + // 10-11 ETUs of ZERO + for(i = 0; i < 10; ++i) ToSendStuffBit(0); - // Transition time. TR0 - guard time - // 8ETUS minum? - // Per specification, Subcarrier must be stopped no later than 2 ETUs after EOF. - // I'm guessing this is for the FPGA to be able to send all bits before we switch to listening mode - for(i = 0; i < 24 ; ++i) ToSendStuffBit(1); + // Transition time. TR0 - guard time + // 8ETUS minum? + // Per specification, Subcarrier must be stopped no later than 2 ETUs after EOF. + // I'm guessing this is for the FPGA to be able to send all bits before we switch to listening mode + for(i = 0; i < 24 ; ++i) ToSendStuffBit(1); - // TR1 - Synchronization time - // Convert from last character reference to length - ToSendMax++; + // TR1 - Synchronization time + // Convert from last character reference to length + ToSendMax++; } /* @@ -1122,15 +1122,15 @@ static void CodeIso14443bAsReader(const uint8_t *cmd, int len) { */ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) { - uint32_t time_start = GetCountSspClk(); + uint32_t time_start = GetCountSspClk(); - CodeIso14443bAsReader(cmd, len); + CodeIso14443bAsReader(cmd, len); - TransmitFor14443b_AsReader(); + TransmitFor14443b_AsReader(); - if(trigger) LED_A_ON(); + if(trigger) LED_A_ON(); - LogTrace(cmd, len, time_start, GetCountSspClk()-time_start, NULL, true); + LogTrace(cmd, len, time_start, GetCountSspClk()-time_start, NULL, true); } /* Sends an APDU to the tag @@ -1138,91 +1138,91 @@ static void CodeAndTransmit14443bAsReader(const uint8_t *cmd, int len) { */ uint8_t iso14443b_apdu(uint8_t const *message, size_t message_length, uint8_t *response) { - uint8_t message_frame[message_length + 4]; - // PCB - message_frame[0] = 0x0A | pcb_blocknum; - pcb_blocknum ^= 1; - // CID - message_frame[1] = 0; - // INF - memcpy(message_frame + 2, message, message_length); - // EDC (CRC) - AddCrc14B(message_frame, message_length + 2); - // send - CodeAndTransmit14443bAsReader(message_frame, message_length + 4); //no - // get response - GetTagSamplesFor14443bDemod(); //no - if(Demod.len < 3) - return 0; + uint8_t message_frame[message_length + 4]; + // PCB + message_frame[0] = 0x0A | pcb_blocknum; + pcb_blocknum ^= 1; + // CID + message_frame[1] = 0; + // INF + memcpy(message_frame + 2, message, message_length); + // EDC (CRC) + AddCrc14B(message_frame, message_length + 2); + // send + CodeAndTransmit14443bAsReader(message_frame, message_length + 4); //no + // get response + GetTagSamplesFor14443bDemod(); //no + if(Demod.len < 3) + return 0; - // VALIDATE CRC - if (!check_crc(CRC_14443_B, Demod.output, Demod.len)){ - if (MF_DBGLEVEL > 3) Dbprintf("crc fail ICE"); - return 0; - } - // copy response contents - if(response != NULL) - memcpy(response, Demod.output, Demod.len); + // VALIDATE CRC + if (!check_crc(CRC_14443_B, Demod.output, Demod.len)){ + if (MF_DBGLEVEL > 3) Dbprintf("crc fail ICE"); + return 0; + } + // copy response contents + if(response != NULL) + memcpy(response, Demod.output, Demod.len); - return Demod.len; + return Demod.len; } /** * SRx Initialise. */ uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card ) { - // INITIATE command: wake up the tag using the INITIATE - static const uint8_t init_srx[] = { ISO14443B_INITIATE, 0x00, 0x97, 0x5b }; - // SELECT command (with space for CRC) - uint8_t select_srx[] = { ISO14443B_SELECT, 0x00, 0x00, 0x00}; + // INITIATE command: wake up the tag using the INITIATE + static const uint8_t init_srx[] = { ISO14443B_INITIATE, 0x00, 0x97, 0x5b }; + // SELECT command (with space for CRC) + uint8_t select_srx[] = { ISO14443B_SELECT, 0x00, 0x00, 0x00}; - CodeAndTransmit14443bAsReader(init_srx, sizeof(init_srx)); - GetTagSamplesFor14443bDemod(); //no + CodeAndTransmit14443bAsReader(init_srx, sizeof(init_srx)); + GetTagSamplesFor14443bDemod(); //no - if (Demod.len == 0) - return 2; + if (Demod.len == 0) + return 2; - // Randomly generated Chip ID - if (card) card->chipid = Demod.output[0]; + // Randomly generated Chip ID + if (card) card->chipid = Demod.output[0]; - select_srx[1] = Demod.output[0]; + select_srx[1] = Demod.output[0]; - AddCrc14B(select_srx, 2); + AddCrc14B(select_srx, 2); - CodeAndTransmit14443bAsReader(select_srx, sizeof(select_srx)); - GetTagSamplesFor14443bDemod(); //no + CodeAndTransmit14443bAsReader(select_srx, sizeof(select_srx)); + GetTagSamplesFor14443bDemod(); //no - if (Demod.len != 3) - return 2; + if (Demod.len != 3) + return 2; - // Check the CRC of the answer: - if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) - return 3; + // Check the CRC of the answer: + if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) + return 3; - // Check response from the tag: should be the same UID as the command we just sent: - if (select_srx[1] != Demod.output[0]) - return 1; + // Check response from the tag: should be the same UID as the command we just sent: + if (select_srx[1] != Demod.output[0]) + return 1; - // First get the tag's UID: - select_srx[0] = ISO14443B_GET_UID; + // First get the tag's UID: + select_srx[0] = ISO14443B_GET_UID; - AddCrc14B(select_srx, 1); - CodeAndTransmit14443bAsReader(select_srx, 3); // Only first three bytes for this one - GetTagSamplesFor14443bDemod(); //no + AddCrc14B(select_srx, 1); + CodeAndTransmit14443bAsReader(select_srx, 3); // Only first three bytes for this one + GetTagSamplesFor14443bDemod(); //no - if (Demod.len != 10) - return 2; + if (Demod.len != 10) + return 2; - // The check the CRC of the answer - if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) - return 3; + // The check the CRC of the answer + if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) + return 3; - if (card) { - card->uidlen = 8; - memcpy(card->uid, Demod.output, 8); - } + if (card) { + card->uidlen = 8; + memcpy(card->uid, Demod.output, 8); + } - return 0; + return 0; } /* Perform the ISO 14443 B Card Selection procedure * Currently does NOT do any collision handling. @@ -1231,29 +1231,29 @@ uint8_t iso14443b_select_srx_card(iso14b_card_select_t *card ) { * TODO: Verify CRC checksums */ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) { - // WUPB command (including CRC) - // Note: WUPB wakes up all tags, REQB doesn't wake up tags in HALT state - static const uint8_t wupb[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 }; - // ATTRIB command (with space for CRC) - uint8_t attrib[] = { ISO14443B_ATTRIB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}; + // WUPB command (including CRC) + // Note: WUPB wakes up all tags, REQB doesn't wake up tags in HALT state + static const uint8_t wupb[] = { ISO14443B_REQB, 0x00, 0x08, 0x39, 0x73 }; + // ATTRIB command (with space for CRC) + uint8_t attrib[] = { ISO14443B_ATTRIB, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x00, 0x00, 0x00, 0x00}; - // first, wake up the tag - CodeAndTransmit14443bAsReader(wupb, sizeof(wupb)); - GetTagSamplesFor14443bDemod(); //select_card + // first, wake up the tag + CodeAndTransmit14443bAsReader(wupb, sizeof(wupb)); + GetTagSamplesFor14443bDemod(); //select_card - // ATQB too short? - if (Demod.len < 14) - return 2; + // ATQB too short? + if (Demod.len < 14) + return 2; - // VALIDATE CRC - if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) - return 3; + // VALIDATE CRC + if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) + return 3; - if (card) { - card->uidlen = 4; - memcpy(card->uid, Demod.output+1, 4); - memcpy(card->atqb, Demod.output+5, 7); - } + if (card) { + card->uidlen = 4; + memcpy(card->uid, Demod.output+1, 4); + memcpy(card->atqb, Demod.output+5, 7); + } // copy the PUPI to ATTRIB ( PUPI == UID ) memcpy(attrib + 1, Demod.output + 1, 4); @@ -1267,63 +1267,63 @@ uint8_t iso14443b_select_card(iso14b_card_select_t *card ) { // Answer to ATTRIB too short? if(Demod.len < 3) - return 2; + return 2; - // VALIDATE CRC - if (!check_crc(CRC_14443_B, Demod.output, Demod.len) ) - return 3; + // VALIDATE CRC + if (!check_crc(CRC_14443_B, Demod.output, Demod.len) ) + return 3; - if (card) { + if (card) { - // CID - card->cid = Demod.output[0]; + // CID + card->cid = Demod.output[0]; - // MAX FRAME - uint16_t maxFrame = card->atqb[5] >> 4; - if (maxFrame < 5) maxFrame = 8 * maxFrame + 16; - else if (maxFrame == 5) maxFrame = 64; - else if (maxFrame == 6) maxFrame = 96; - else if (maxFrame == 7) maxFrame = 128; - else if (maxFrame == 8) maxFrame = 256; - else maxFrame = 257; - iso14b_set_maxframesize(maxFrame); + // MAX FRAME + uint16_t maxFrame = card->atqb[5] >> 4; + if (maxFrame < 5) maxFrame = 8 * maxFrame + 16; + else if (maxFrame == 5) maxFrame = 64; + else if (maxFrame == 6) maxFrame = 96; + else if (maxFrame == 7) maxFrame = 128; + else if (maxFrame == 8) maxFrame = 256; + else maxFrame = 257; + iso14b_set_maxframesize(maxFrame); - // FWT - uint8_t fwt = card->atqb[6] >> 4; - if ( fwt < 16 ){ - uint32_t fwt_time = (302 << fwt); - iso14b_set_timeout( fwt_time); - } - } - // reset PCB block number - pcb_blocknum = 0; - return 0; + // FWT + uint8_t fwt = card->atqb[6] >> 4; + if ( fwt < 16 ){ + uint32_t fwt_time = (302 << fwt); + iso14b_set_timeout( fwt_time); + } + } + // reset PCB block number + pcb_blocknum = 0; + return 0; } // Set up ISO 14443 Type B communication (similar to iso14443a_setup) // field is setup for "Sending as Reader" void iso14443b_setup() { - LEDsoff(); - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + LEDsoff(); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - // Initialize Demod and Uart structs - DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); - UartInit(BigBuf_malloc(MAX_FRAME_SIZE)); + // Initialize Demod and Uart structs + DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); + UartInit(BigBuf_malloc(MAX_FRAME_SIZE)); - // connect Demodulated Signal to ADC: - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + // connect Demodulated Signal to ADC: + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - // Set up the synchronous serial port - FpgaSetupSsc(); + // Set up the synchronous serial port + FpgaSetupSsc(); - // Signal field is on with the appropriate LED - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); - SpinDelay(100); + // Signal field is on with the appropriate LED + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX | FPGA_HF_READER_TX_SHALLOW_MOD); + SpinDelay(100); - // Start the timer - StartCountSspClk(); + // Start the timer + StartCountSspClk(); - LED_D_ON(); + LED_D_ON(); } //----------------------------------------------------------------------------- @@ -1336,106 +1336,106 @@ void iso14443b_setup() { // I tried to be systematic and check every answer of the tag, every CRC, etc... //----------------------------------------------------------------------------- static bool ReadSTBlock(uint8_t block) { - uint8_t cmd[] = {ISO14443B_READ_BLK, block, 0x00, 0x00}; - AddCrc14B(cmd, 2); - CodeAndTransmit14443bAsReader(cmd, sizeof(cmd)); - GetTagSamplesFor14443bDemod(); + uint8_t cmd[] = {ISO14443B_READ_BLK, block, 0x00, 0x00}; + AddCrc14B(cmd, 2); + CodeAndTransmit14443bAsReader(cmd, sizeof(cmd)); + GetTagSamplesFor14443bDemod(); - // Check if we got an answer from the tag - if (Demod.len != 6) { - DbpString("[!] expected 6 bytes from tag, got less..."); - return false; - } - // The check the CRC of the answer - if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) { - DbpString("[!] CRC Error block!"); - return false; - } - return true; + // Check if we got an answer from the tag + if (Demod.len != 6) { + DbpString("[!] expected 6 bytes from tag, got less..."); + return false; + } + // The check the CRC of the answer + if (!check_crc(CRC_14443_B, Demod.output, Demod.len)) { + DbpString("[!] CRC Error block!"); + return false; + } + return true; } void ReadSTMemoryIso14443b(uint8_t numofblocks) { - // Make sure that we start from off, since the tags are stateful; - // confusing things will happen if we don't reset them between reads. - //switch_off(); + // Make sure that we start from off, since the tags are stateful; + // confusing things will happen if we don't reset them between reads. + //switch_off(); - uint8_t i = 0x00; - uint8_t *buf = BigBuf_malloc(sizeof(iso14b_card_select_t)); + uint8_t i = 0x00; + uint8_t *buf = BigBuf_malloc(sizeof(iso14b_card_select_t)); - iso14443b_setup(); + iso14443b_setup(); - iso14b_card_select_t *card = (iso14b_card_select_t*)buf; - uint8_t res = iso14443b_select_srx_card(card); + iso14b_card_select_t *card = (iso14b_card_select_t*)buf; + uint8_t res = iso14443b_select_srx_card(card); - // 0: OK 2: attrib fail, 3:crc fail, - if ( res > 0 ) goto out; + // 0: OK 2: attrib fail, 3:crc fail, + if ( res > 0 ) goto out; - Dbprintf("[+] Tag memory dump, block 0 to %d", numofblocks); + Dbprintf("[+] Tag memory dump, block 0 to %d", numofblocks); - ++numofblocks; + ++numofblocks; - for (;;) { - if (i == numofblocks) { - DbpString("System area block (0xFF):"); - i = 0xff; - } + for (;;) { + if (i == numofblocks) { + DbpString("System area block (0xFF):"); + i = 0xff; + } - uint8_t retries = 3; - do { - res = ReadSTBlock(i); - } while (!res && --retries); + uint8_t retries = 3; + do { + res = ReadSTBlock(i); + } while (!res && --retries); - if (!res && !retries) { - goto out; - } + if (!res && !retries) { + goto out; + } - // Now print out the memory location: - Dbprintf("Address=%02x, Contents=%08x, CRC=%04x", i, - (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0], - (Demod.output[4]<<8)+Demod.output[5]); + // Now print out the memory location: + Dbprintf("Address=%02x, Contents=%08x, CRC=%04x", i, + (Demod.output[3]<<24) + (Demod.output[2]<<16) + (Demod.output[1]<<8) + Demod.output[0], + (Demod.output[4]<<8)+Demod.output[5]); - if (i == 0xff) break; - ++i; - } + if (i == 0xff) break; + ++i; + } out: - switch_off(); // disconnect raw - SpinDelay(20); + switch_off(); // disconnect raw + SpinDelay(20); } static void iso1444b_setup_sniff(void){ - LEDsoff(); - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - BigBuf_free(); - BigBuf_Clear_ext(false); - clear_trace();//setup snoop - set_tracing(true); + LEDsoff(); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + BigBuf_free(); + BigBuf_Clear_ext(false); + clear_trace();//setup snoop + set_tracing(true); - // Initialize Demod and Uart structs - DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); - UartInit(BigBuf_malloc(MAX_FRAME_SIZE)); + // Initialize Demod and Uart structs + DemodInit(BigBuf_malloc(MAX_FRAME_SIZE)); + UartInit(BigBuf_malloc(MAX_FRAME_SIZE)); - if (MF_DBGLEVEL > 1) { - // Print debug information about the buffer sizes - Dbprintf("[+] Sniff buffers initialized:"); - Dbprintf("[+] trace: %i bytes", BigBuf_max_traceLen()); - Dbprintf("[+] reader -> tag: %i bytes", MAX_FRAME_SIZE); - Dbprintf("[+] tag -> reader: %i bytes", MAX_FRAME_SIZE); - Dbprintf("[+] DMA: %i bytes", ISO14443B_DMA_BUFFER_SIZE); - } + if (MF_DBGLEVEL > 1) { + // Print debug information about the buffer sizes + Dbprintf("[+] Sniff buffers initialized:"); + Dbprintf("[+] trace: %i bytes", BigBuf_max_traceLen()); + Dbprintf("[+] reader -> tag: %i bytes", MAX_FRAME_SIZE); + Dbprintf("[+] tag -> reader: %i bytes", MAX_FRAME_SIZE); + Dbprintf("[+] DMA: %i bytes", ISO14443B_DMA_BUFFER_SIZE); + } - // connect Demodulated Signal to ADC: - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + // connect Demodulated Signal to ADC: + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - // Setup for the DMA. - FpgaSetupSsc(); + // Setup for the DMA. + FpgaSetupSsc(); - // Set FPGA in the appropriate mode - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP); - SpinDelay(20); + // Set FPGA in the appropriate mode + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR | FPGA_HF_READER_RX_XCORR_848_KHZ | FPGA_HF_READER_RX_XCORR_SNOOP); + SpinDelay(20); - // Start the SSP timer - StartCountSspClk(); + // Start the SSP timer + StartCountSspClk(); } //============================================================================= @@ -1457,98 +1457,98 @@ static void iso1444b_setup_sniff(void){ */ void RAMFUNC SniffIso14443b(void) { - uint32_t time_0 = 0, time_start = 0, time_stop = 0; - int ci = 0, cq = 0; + uint32_t time_0 = 0, time_start = 0, time_stop = 0; + int ci = 0, cq = 0; - // We won't start recording the frames that we acquire until we trigger; - // a good trigger condition to get started is probably when we see a - // response from the tag. - bool TagIsActive = false; - bool ReaderIsActive = false; + // We won't start recording the frames that we acquire until we trigger; + // a good trigger condition to get started is probably when we see a + // response from the tag. + bool TagIsActive = false; + bool ReaderIsActive = false; - iso1444b_setup_sniff(); + iso1444b_setup_sniff(); - // The DMA buffer, used to stream samples from the FPGA - int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); - int8_t *data = dmaBuf; + // The DMA buffer, used to stream samples from the FPGA + int8_t *dmaBuf = (int8_t*) BigBuf_malloc(ISO14443B_DMA_BUFFER_SIZE); + int8_t *data = dmaBuf; - // Setup and start DMA. - if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE) ){ - if (MF_DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting"); - BigBuf_free(); - return; - } + // Setup and start DMA. + if ( !FpgaSetupSscDma((uint8_t*) dmaBuf, ISO14443B_DMA_BUFFER_SIZE) ){ + if (MF_DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting"); + BigBuf_free(); + return; + } - // time ZERO, the point from which it all is calculated. - time_0 = GetCountSspClk(); + // time ZERO, the point from which it all is calculated. + time_0 = GetCountSspClk(); // loop and listen - while (!BUTTON_PRESS()) { - WDT_HIT(); + while (!BUTTON_PRESS()) { + WDT_HIT(); - ci = data[0]; - cq = data[1]; - data += 2; + ci = data[0]; + cq = data[1]; + data += 2; - if (data >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { - data = dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; - } + if (data >= dmaBuf + ISO14443B_DMA_BUFFER_SIZE) { + data = dmaBuf; + AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t) dmaBuf; + AT91C_BASE_PDC_SSC->PDC_RNCR = ISO14443B_DMA_BUFFER_SIZE; + } - // no need to try decoding reader data if the tag is sending - if (!TagIsActive) { + // no need to try decoding reader data if the tag is sending + if (!TagIsActive) { - LED_A_INV(); + LED_A_INV(); - if (Handle14443bReaderUartBit(ci & 0x01)) { - time_stop = GetCountSspClk() - time_0; - LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true); - UartReset(); - DemodReset(); - } else { - time_start = GetCountSspClk() - time_0; - } + if (Handle14443bReaderUartBit(ci & 0x01)) { + time_stop = GetCountSspClk() - time_0; + LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true); + UartReset(); + DemodReset(); + } else { + time_start = GetCountSspClk() - time_0; + } - if (Handle14443bReaderUartBit(cq & 0x01)) { - time_stop = GetCountSspClk() - time_0; - LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true); - UartReset(); - DemodReset(); - } else { - time_start = GetCountSspClk() - time_0; - } - ReaderIsActive = (Uart.state > STATE_GOT_FALLING_EDGE_OF_SOF); - } + if (Handle14443bReaderUartBit(cq & 0x01)) { + time_stop = GetCountSspClk() - time_0; + LogTrace(Uart.output, Uart.byteCnt, time_start, time_stop, NULL, true); + UartReset(); + DemodReset(); + } else { + time_start = GetCountSspClk() - time_0; + } + ReaderIsActive = (Uart.state > STATE_GOT_FALLING_EDGE_OF_SOF); + } - // no need to try decoding tag data if the reader is sending - and we cannot afford the time - if (!ReaderIsActive) { + // no need to try decoding tag data if the reader is sending - and we cannot afford the time + if (!ReaderIsActive) { - // is this | 0x01 the error? & 0xfe in https://github.com/Proxmark/proxmark3/issues/103 - // LSB is a fpga signal bit. - if (Handle14443bTagSamplesDemod(ci, cq)) { - time_stop = GetCountSspClk() - time_0; - LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false); - UartReset(); - DemodReset(); - } else { - time_start = GetCountSspClk() - time_0; - } - TagIsActive = (Demod.state > DEMOD_GOT_FALLING_EDGE_OF_SOF); - } - } + // is this | 0x01 the error? & 0xfe in https://github.com/Proxmark/proxmark3/issues/103 + // LSB is a fpga signal bit. + if (Handle14443bTagSamplesDemod(ci, cq)) { + time_stop = GetCountSspClk() - time_0; + LogTrace(Demod.output, Demod.len, time_start, time_stop, NULL, false); + UartReset(); + DemodReset(); + } else { + time_start = GetCountSspClk() - time_0; + } + TagIsActive = (Demod.state > DEMOD_GOT_FALLING_EDGE_OF_SOF); + } + } - if (MF_DBGLEVEL >= 2) { - DbpString("[+] Sniff statistics:"); - Dbprintf("[+] uart State: %x ByteCount: %i ByteCountMax: %i", Uart.state, Uart.byteCnt, Uart.byteCntMax); - Dbprintf("[+] trace length: %i", BigBuf_get_traceLen()); - } + if (MF_DBGLEVEL >= 2) { + DbpString("[+] Sniff statistics:"); + Dbprintf("[+] uart State: %x ByteCount: %i ByteCountMax: %i", Uart.state, Uart.byteCnt, Uart.byteCntMax); + Dbprintf("[+] trace length: %i", BigBuf_get_traceLen()); + } - switch_off(); + switch_off(); } void iso14b_set_trigger(bool enable) { - trigger = enable; + trigger = enable; } /* @@ -1563,70 +1563,70 @@ void iso14b_set_trigger(bool enable) { * */ void SendRawCommand14443B_Ex(UsbCommand *c) { - iso14b_command_t param = c->arg[0]; - size_t len = c->arg[1] & 0xffff; - uint8_t *cmd = c->d.asBytes; - uint8_t status = 0; - uint32_t sendlen = sizeof(iso14b_card_select_t); - uint8_t buf[USB_CMD_DATA_SIZE] = {0x00}; + iso14b_command_t param = c->arg[0]; + size_t len = c->arg[1] & 0xffff; + uint8_t *cmd = c->d.asBytes; + uint8_t status = 0; + uint32_t sendlen = sizeof(iso14b_card_select_t); + uint8_t buf[USB_CMD_DATA_SIZE] = {0x00}; - if (MF_DBGLEVEL > 3) Dbprintf("14b raw: param, %04x", param ); + if (MF_DBGLEVEL > 3) Dbprintf("14b raw: param, %04x", param ); - // turn on trigger (LED_A) - if ((param & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER) - iso14b_set_trigger(true); + // turn on trigger (LED_A) + if ((param & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER) + iso14b_set_trigger(true); - if ((param & ISO14B_CONNECT) == ISO14B_CONNECT) { - iso14443b_setup(); - clear_trace(); - } + if ((param & ISO14B_CONNECT) == ISO14B_CONNECT) { + iso14443b_setup(); + clear_trace(); + } - set_tracing(true); + set_tracing(true); - if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) { - iso14b_card_select_t *card = (iso14b_card_select_t*)buf; - status = iso14443b_select_card(card); - cmd_send(CMD_ACK, status, sendlen, 0, buf, sendlen); - // 0: OK 2: attrib fail, 3:crc fail, - if ( status > 0 ) goto out; - } + if ((param & ISO14B_SELECT_STD) == ISO14B_SELECT_STD) { + iso14b_card_select_t *card = (iso14b_card_select_t*)buf; + status = iso14443b_select_card(card); + cmd_send(CMD_ACK, status, sendlen, 0, buf, sendlen); + // 0: OK 2: attrib fail, 3:crc fail, + if ( status > 0 ) goto out; + } - if ((param & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) { - iso14b_card_select_t *card = (iso14b_card_select_t*)buf; - status = iso14443b_select_srx_card(card); - cmd_send(CMD_ACK, status, sendlen, 0, buf, sendlen); - // 0: OK 2: demod fail, 3:crc fail, - if ( status > 0 ) goto out; - } + if ((param & ISO14B_SELECT_SR) == ISO14B_SELECT_SR) { + iso14b_card_select_t *card = (iso14b_card_select_t*)buf; + status = iso14443b_select_srx_card(card); + cmd_send(CMD_ACK, status, sendlen, 0, buf, sendlen); + // 0: OK 2: demod fail, 3:crc fail, + if ( status > 0 ) goto out; + } - if ((param & ISO14B_APDU) == ISO14B_APDU) { - status = iso14443b_apdu(cmd, len, buf); - cmd_send(CMD_ACK, status, status, 0, buf, status); - } + if ((param & ISO14B_APDU) == ISO14B_APDU) { + status = iso14443b_apdu(cmd, len, buf); + cmd_send(CMD_ACK, status, status, 0, buf, status); + } - if ((param & ISO14B_RAW) == ISO14B_RAW) { - if((param & ISO14B_APPEND_CRC) == ISO14B_APPEND_CRC) { - AddCrc14B(cmd, len); - len += 2; - } + if ((param & ISO14B_RAW) == ISO14B_RAW) { + if((param & ISO14B_APPEND_CRC) == ISO14B_APPEND_CRC) { + AddCrc14B(cmd, len); + len += 2; + } - CodeAndTransmit14443bAsReader(cmd, len); // raw - GetTagSamplesFor14443bDemod(); // raw + CodeAndTransmit14443bAsReader(cmd, len); // raw + GetTagSamplesFor14443bDemod(); // raw - sendlen = MIN(Demod.len, USB_CMD_DATA_SIZE); - status = (Demod.len > 0) ? 0 : 1; - cmd_send(CMD_ACK, status, sendlen, 0, Demod.output, sendlen); - } + sendlen = MIN(Demod.len, USB_CMD_DATA_SIZE); + status = (Demod.len > 0) ? 0 : 1; + cmd_send(CMD_ACK, status, sendlen, 0, Demod.output, sendlen); + } out: - // turn off trigger (LED_A) - if ((param & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER) - iso14b_set_trigger(false); + // turn off trigger (LED_A) + if ((param & ISO14B_REQUEST_TRIGGER) == ISO14B_REQUEST_TRIGGER) + iso14b_set_trigger(false); - // turn off antenna et al - // we don't send a HALT command. - if ((param & ISO14B_DISCONNECT) == ISO14B_DISCONNECT) { - switch_off(); // disconnect raw - SpinDelay(20); - } + // turn off antenna et al + // we don't send a HALT command. + if ((param & ISO14B_DISCONNECT) == ISO14B_DISCONNECT) { + switch_off(); // disconnect raw + SpinDelay(20); + } } \ No newline at end of file diff --git a/armsrc/iso14443b.h b/armsrc/iso14443b.h index 84765537a..c7e98f182 100644 --- a/armsrc/iso14443b.h +++ b/armsrc/iso14443b.h @@ -18,7 +18,7 @@ extern "C" { #endif #include "proxmark3.h" -#include "common.h" // access to global variable: MF_DBGLEVEL +#include "common.h" // access to global variable: MF_DBGLEVEL #include "apps.h" #include "util.h" #include "string.h" @@ -27,11 +27,11 @@ extern "C" { #include "protocols.h" #ifndef AddCrc14A -# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1) +# define AddCrc14A(data, len) compute_crc(CRC_14443_A, (data), (len), (data)+(len), (data)+(len)+1) #endif #ifndef AddCrc14B -# define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1) +# define AddCrc14B(data, len) compute_crc(CRC_14443_B, (data), (len), (data)+(len), (data)+(len)+1) #endif extern void SendRawCommand14443B_Ex(UsbCommand *c); @@ -45,13 +45,13 @@ extern void WaitForFpgaDelayQueueIsEmpty( uint16_t delay ); extern void ClearFpgaShiftingRegisters(void); // States for 14B SIM command -#define SIM_NOFIELD 0 -#define SIM_IDLE 1 -#define SIM_HALTED 2 -#define SIM_SELECTING 3 -#define SIM_HALTING 4 +#define SIM_NOFIELD 0 +#define SIM_IDLE 1 +#define SIM_HALTED 2 +#define SIM_SELECTING 3 +#define SIM_HALTING 4 #define SIM_ACKNOWLEDGE 5 -#define SIM_WORK 6 +#define SIM_WORK 6 #ifdef __cplusplus } diff --git a/armsrc/iso15693.c b/armsrc/iso15693.c index 61e0e1130..1afaac95f 100644 --- a/armsrc/iso15693.c +++ b/armsrc/iso15693.c @@ -24,21 +24,21 @@ // // VCD (reader) -> VICC (tag) // 1 out of 256: -// data rate: 1,66 kbit/s (fc/8192) -// used for long range +// data rate: 1,66 kbit/s (fc/8192) +// used for long range // 1 out of 4: -// data rate: 26,48 kbit/s (fc/512) -// used for short range, high speed +// data rate: 26,48 kbit/s (fc/512) +// used for short range, high speed // // VICC (tag) -> VCD (reader) // Modulation: -// ASK / one subcarrier (423,75 khz) -// FSK / two subcarriers (423,75 khz && 484,28 khz) +// ASK / one subcarrier (423,75 khz) +// FSK / two subcarriers (423,75 khz && 484,28 khz) // Data Rates / Modes: -// low ASK: 6,62 kbit/s -// low FSK: 6.67 kbit/s -// high ASK: 26,48 kbit/s -// high FSK: 26,69 kbit/s +// low ASK: 6,62 kbit/s +// low FSK: 6.67 kbit/s +// high ASK: 26,48 kbit/s +// high FSK: 26,69 kbit/s //----------------------------------------------------------------------------- // added "1 out of 256" mode (for VCD->PICC) - atrox 20100911 @@ -54,8 +54,8 @@ // *) add anti-collission support for inventory-commands // *) read security status of a block // *) sniffing and simulation do only support one transmission mode. need to support -// all 8 transmission combinations -// *) remove or refactor code under "depricated" +// all 8 transmission combinations +// *) remove or refactor code under "depricated" // *) document all the functions #include "proxmark3.h" @@ -71,21 +71,21 @@ /////////////////////////////////////////////////////////////////////// // 32 + 2 crc + 1 -#define ISO15_MAX_FRAME 35 -#define CMD_ID_RESP 5 -#define CMD_READ_RESP 13 -#define CMD_INV_RESP 12 +#define ISO15_MAX_FRAME 35 +#define CMD_ID_RESP 5 +#define CMD_READ_RESP 13 +#define CMD_INV_RESP 12 #define FrameSOF Iso15693FrameSOF #define Logic0 Iso15693Logic0 #define Logic1 Iso15693Logic1 #define FrameEOF Iso15693FrameEOF -#define Crc(data, len) crc(CRC_15693, (data), (len)) -#define CheckCrc(data, len) check_crc(CRC_15693, (data), (len)) -#define AddCrc(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1) +#define Crc(data, len) crc(CRC_15693, (data), (len)) +#define CheckCrc(data, len) check_crc(CRC_15693, (data), (len)) +#define AddCrc(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1) -#define sprintUID(target,uid) Iso15693sprintUID((target), (uid)) +#define sprintUID(target,uid) Iso15693sprintUID((target), (uid)) static void BuildIdentifyRequest(uint8_t *cmdout); //static void BuildReadBlockRequest(uint8_t *cmdout, uint8_t *uid, uint8_t blockNumber ); @@ -100,156 +100,156 @@ static void BuildInventoryResponse(uint8_t *cmdout, uint8_t *uid); // cmd ... data // n ... length of data static void CodeIso15693AsReader(uint8_t *cmd, int n) { - int i, j; + int i, j; - ToSendReset(); + ToSendReset(); - // Give it a bit of slack at the beginning - for(i = 0; i < 24; i++) - ToSendStuffBit(1); + // Give it a bit of slack at the beginning + for(i = 0; i < 24; i++) + ToSendStuffBit(1); - // SOF for 1of4 - ToSendStuffBit(0); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(0); - ToSendStuffBit(1); - ToSendStuffBit(1); - for(i = 0; i < n; i++) { - for(j = 0; j < 8; j += 2) { - int these = (cmd[i] >> j) & 3; - switch(these) { - case 0: - ToSendStuffBit(1); - ToSendStuffBit(0); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - break; - case 1: - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(0); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - break; - case 2: - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(0); - ToSendStuffBit(1); - ToSendStuffBit(1); - break; - case 3: - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(0); - break; - } - } - } - // EOF - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(0); - ToSendStuffBit(1); + // SOF for 1of4 + ToSendStuffBit(0); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(0); + ToSendStuffBit(1); + ToSendStuffBit(1); + for(i = 0; i < n; i++) { + for(j = 0; j < 8; j += 2) { + int these = (cmd[i] >> j) & 3; + switch(these) { + case 0: + ToSendStuffBit(1); + ToSendStuffBit(0); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + break; + case 1: + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(0); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + break; + case 2: + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(0); + ToSendStuffBit(1); + ToSendStuffBit(1); + break; + case 3: + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(0); + break; + } + } + } + // EOF + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(0); + ToSendStuffBit(1); - // And slack at the end, too. - for(i = 0; i < 24; i++) - ToSendStuffBit(1); + // And slack at the end, too. + for(i = 0; i < 24; i++) + ToSendStuffBit(1); } // encode data using "1 out of 256" sheme // data rate is 1,66 kbit/s (fc/8192) // is designed for more robust communication over longer distances static void CodeIso15693AsReader256(uint8_t *cmd, int n) { - int i, j; + int i, j; - ToSendReset(); + ToSendReset(); - // Give it a bit of slack at the beginning - for(i = 0; i < 24; i++) - ToSendStuffBit(1); + // Give it a bit of slack at the beginning + for(i = 0; i < 24; i++) + ToSendStuffBit(1); - // SOF for 1of256 - ToSendStuffBit(0); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(0); + // SOF for 1of256 + ToSendStuffBit(0); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(0); - for(i = 0; i < n; i++) { - for (j = 0; j <= 255; j++) { - if (cmd[i] == j) { - ToSendStuffBit(1); - ToSendStuffBit(0); - } else { - ToSendStuffBit(1); - ToSendStuffBit(1); - } - } - } - // EOF - ToSendStuffBit(1); - ToSendStuffBit(1); - ToSendStuffBit(0); - ToSendStuffBit(1); + for(i = 0; i < n; i++) { + for (j = 0; j <= 255; j++) { + if (cmd[i] == j) { + ToSendStuffBit(1); + ToSendStuffBit(0); + } else { + ToSendStuffBit(1); + ToSendStuffBit(1); + } + } + } + // EOF + ToSendStuffBit(1); + ToSendStuffBit(1); + ToSendStuffBit(0); + ToSendStuffBit(1); - // And slack at the end, too. - for(i = 0; i < 24; i++) - ToSendStuffBit(1); + // And slack at the end, too. + for(i = 0; i < 24; i++) + ToSendStuffBit(1); } // Transmit the command (to the tag) that was placed in ToSend[]. static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *wait) { int c; - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX); - if (wait) { - for (c = 0; c < *wait;) { - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing! - ++c; - } - WDT_HIT(); - } - } + if (wait) { + for (c = 0; c < *wait;) { + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing! + ++c; + } + WDT_HIT(); + } + } c = 0; for(;;) { - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = cmd[c]; if( ++c >= len) break; } WDT_HIT(); } - if (samples) { - if (wait) - *samples = (c + *wait) << 3; - else - *samples = c << 3; - } + if (samples) { + if (wait) + *samples = (c + *wait) << 3; + else + *samples = c << 3; + } } //----------------------------------------------------------------------------- @@ -257,32 +257,32 @@ static void TransmitTo15693Tag(const uint8_t *cmd, int len, int *samples, int *w //----------------------------------------------------------------------------- static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int *wait) { int c = 0; - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_SIMULATOR | FPGA_HF_SIMULATOR_MODULATE_424K); - if (wait) { - for (c = 0; c < *wait;) { - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing! - ++c; - } - WDT_HIT(); - } - } + if (wait) { + for (c = 0; c < *wait;) { + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0x00; // For exact timing! + ++c; + } + WDT_HIT(); + } + } c = 0; for(;;) { - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { AT91C_BASE_SSC->SSC_THR = cmd[c]; if( ++c >= len) break; } WDT_HIT(); } - if (samples) { - if (wait) - *samples = (c + *wait) << 3; - else - *samples = c << 3; - } + if (samples) { + if (wait) + *samples = (c + *wait) << 3; + else + *samples = c << 3; + } } //----------------------------------------------------------------------------- @@ -290,146 +290,146 @@ static void TransmitTo15693Reader(const uint8_t *cmd, int len, int *samples, int //----------------------------------------------------------------------------- static int DemodAnswer(uint8_t *received, uint8_t *dest, uint16_t samplecount) { - int i, j; - int max = 0, maxPos = 0, skip = 4; - int k = 0; // this will be our return value + int i, j; + int max = 0, maxPos = 0, skip = 4; + int k = 0; // this will be our return value - // First, correlate for SOF - for (i = 0; i < samplecount; i++) { - int corr = 0; - for ( j = 0; j < ARRAYLEN(FrameSOF); j += skip) { - corr += FrameSOF[j] * dest[i+(j/skip)]; - } - if (corr > max) { - max = corr; - maxPos = i; - } - } - // DbpString("SOF at %d, correlation %d", maxPos,max/(ARRAYLEN(FrameSOF)/skip)); + // First, correlate for SOF + for (i = 0; i < samplecount; i++) { + int corr = 0; + for ( j = 0; j < ARRAYLEN(FrameSOF); j += skip) { + corr += FrameSOF[j] * dest[i+(j/skip)]; + } + if (corr > max) { + max = corr; + maxPos = i; + } + } + // DbpString("SOF at %d, correlation %d", maxPos,max/(ARRAYLEN(FrameSOF)/skip)); - // greg - If correlation is less than 1 then there's little point in continuing - if ((max / (ARRAYLEN(FrameSOF)/skip) ) < 1) - return k; + // greg - If correlation is less than 1 then there's little point in continuing + if ((max / (ARRAYLEN(FrameSOF)/skip) ) < 1) + return k; - i = maxPos + ARRAYLEN(FrameSOF) / skip; + i = maxPos + ARRAYLEN(FrameSOF) / skip; - uint8_t outBuf[ISO15_MAX_FRAME]; - memset(outBuf, 0, sizeof(outBuf)); - uint8_t mask = 0x01; - for(;;) { - int corr0 = 0, corr1 = 0, corrEOF = 0; - for (j = 0; j < ARRAYLEN(Logic0); j += skip) { - corr0 += Logic0[j] * dest[i+(j/skip)]; - } - for (j = 0; j < ARRAYLEN(Logic1); j += skip) { - corr1 += Logic1[j] * dest[i+(j/skip)]; - } - for (j = 0; j < ARRAYLEN(FrameEOF); j += skip) { - corrEOF += FrameEOF[j] * dest[i+(j/skip)]; - } - // Even things out by the length of the target waveform. - corr0 *= 4; - corr1 *= 4; - // if (MF_DBGLEVEL >= MF_DBG_EXTENDED) - // Dbprintf("Corr1 %d, Corr0 %d, CorrEOF %d", corr1, corr0, corrEOF); + uint8_t outBuf[ISO15_MAX_FRAME]; + memset(outBuf, 0, sizeof(outBuf)); + uint8_t mask = 0x01; + for(;;) { + int corr0 = 0, corr1 = 0, corrEOF = 0; + for (j = 0; j < ARRAYLEN(Logic0); j += skip) { + corr0 += Logic0[j] * dest[i+(j/skip)]; + } + for (j = 0; j < ARRAYLEN(Logic1); j += skip) { + corr1 += Logic1[j] * dest[i+(j/skip)]; + } + for (j = 0; j < ARRAYLEN(FrameEOF); j += skip) { + corrEOF += FrameEOF[j] * dest[i+(j/skip)]; + } + // Even things out by the length of the target waveform. + corr0 *= 4; + corr1 *= 4; + // if (MF_DBGLEVEL >= MF_DBG_EXTENDED) + // Dbprintf("Corr1 %d, Corr0 %d, CorrEOF %d", corr1, corr0, corrEOF); - if (corrEOF > corr1 && corrEOF > corr0) - break; + if (corrEOF > corr1 && corrEOF > corr0) + break; - if (corr1 > corr0) { - i += ARRAYLEN(Logic1) / skip; - outBuf[k] |= mask; - } else { - i += ARRAYLEN(Logic0) / skip; - } + if (corr1 > corr0) { + i += ARRAYLEN(Logic1) / skip; + outBuf[k] |= mask; + } else { + i += ARRAYLEN(Logic0) / skip; + } - mask <<= 1; + mask <<= 1; - if (mask == 0) { - k++; - mask = 0x01; - } + if (mask == 0) { + k++; + mask = 0x01; + } - if ( ( i + (int)ARRAYLEN(FrameEOF)) >= samplecount-1) { - //Dbprintf("[!] ran off end! %d | %d",( i + (int)ARRAYLEN(FrameEOF)), samplecount-1); - break; - } - } + if ( ( i + (int)ARRAYLEN(FrameEOF)) >= samplecount-1) { + //Dbprintf("[!] ran off end! %d | %d",( i + (int)ARRAYLEN(FrameEOF)), samplecount-1); + break; + } + } - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("ice: demod bytes %u", k); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("ice: demod bytes %u", k); - if (mask != 0x01) { // this happens, when we miss the EOF + if (mask != 0x01) { // this happens, when we miss the EOF - // TODO: for some reason this happens quite often - if (MF_DBGLEVEL >= MF_DBG_ERROR && k != 0) Dbprintf("[!] error, uneven octet! (extra bits!) mask %02x", mask); - //if (mask < 0x08) k--; // discard the last uneven octet; - // 0x08 is an assumption - but works quite often - } + // TODO: for some reason this happens quite often + if (MF_DBGLEVEL >= MF_DBG_ERROR && k != 0) Dbprintf("[!] error, uneven octet! (extra bits!) mask %02x", mask); + //if (mask < 0x08) k--; // discard the last uneven octet; + // 0x08 is an assumption - but works quite often + } - for(i = 0; i < k; i++) - received[i] = outBuf[i]; + for(i = 0; i < k; i++) + received[i] = outBuf[i]; - // return the number of bytes demodulated - return k; + // return the number of bytes demodulated + return k; } // Read from Tag // Parameters: -// received -// samples -// elapsed +// received +// samples +// elapsed // returns: -// number of decoded bytes +// number of decoded bytes // logging enabled static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) { #define SIGNAL_BUFF_SIZE 15000 - // get current clock - uint32_t time_0 = GetCountSspClk(); - uint32_t time_stop = 0; - bool getNext = false; - int counter = 0, ci = 0, cq = 0; - uint8_t *buf = BigBuf_malloc(SIGNAL_BUFF_SIZE); + // get current clock + uint32_t time_0 = GetCountSspClk(); + uint32_t time_stop = 0; + bool getNext = false; + int counter = 0, ci = 0, cq = 0; + uint8_t *buf = BigBuf_malloc(SIGNAL_BUFF_SIZE); - if (elapsed) *elapsed = 0; + if (elapsed) *elapsed = 0; - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); - for(;;) { - WDT_HIT(); + for(;;) { + WDT_HIT(); - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = 0x00; //0x43; - // To make use of exact timing of next command from reader!! - if (elapsed) (*elapsed)++; - } - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = 0x00; //0x43; + // To make use of exact timing of next command from reader!! + if (elapsed) (*elapsed)++; + } + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - ci = (int8_t)AT91C_BASE_SSC->SSC_RHR; - ci = ABS(ci); + ci = (int8_t)AT91C_BASE_SSC->SSC_RHR; + ci = ABS(ci); - // The samples are correlations against I and Q versions of the - // tone that the tag AM-modulates, so every other sample is I, - // every other is Q. We just want power, so abs(I) + abs(Q) is - // close to what we want. - // iceman 2016, amplitude sqrt(abs(i) + abs(q)) - if (getNext) { + // The samples are correlations against I and Q versions of the + // tone that the tag AM-modulates, so every other sample is I, + // every other is Q. We just want power, so abs(I) + abs(Q) is + // close to what we want. + // iceman 2016, amplitude sqrt(abs(i) + abs(q)) + if (getNext) { - buf[counter++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1)); + buf[counter++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1)); - if (counter >= SIGNAL_BUFF_SIZE) - break; - } else { - cq = ci; - } - getNext = !getNext; - } - } - time_stop = GetCountSspClk() - time_0 ; - int len = DemodAnswer(received, buf, counter); - LogTrace(received, len, time_0 << 4, time_stop << 4, NULL, false); - BigBuf_free(); - return len; + if (counter >= SIGNAL_BUFF_SIZE) + break; + } else { + cq = ci; + } + getNext = !getNext; + } + } + time_stop = GetCountSspClk() - time_0 ; + int len = DemodAnswer(received, buf, counter); + LogTrace(received, len, time_0 << 4, time_stop << 4, NULL, false); + BigBuf_free(); + return len; } @@ -437,45 +437,45 @@ static int GetIso15693AnswerFromTag(uint8_t *received, int *elapsed) { // logging enable, static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elapsed) { - bool getNext = false; - int counter = 0, ci = 0, cq = 0; - uint32_t time_0 = 0, time_stop = 0; - uint8_t *buf = BigBuf_get_addr(); + bool getNext = false; + int counter = 0, ci = 0, cq = 0; + uint32_t time_0 = 0, time_stop = 0; + uint8_t *buf = BigBuf_get_addr(); - // get current clock - time_0 = GetCountSspClk(); + // get current clock + time_0 = GetCountSspClk(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); - for(;;) { - WDT_HIT(); + for(;;) { + WDT_HIT(); - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - ci = (int8_t)AT91C_BASE_SSC->SSC_RHR; - ci = ABS(ci); + ci = (int8_t)AT91C_BASE_SSC->SSC_RHR; + ci = ABS(ci); - // The samples are correlations against I and Q versions of the - // tone that the tag AM-modulates, so every other sample is I, - // every other is Q. We just want power, so abs(I) + abs(Q) is - // close to what we want. - if (getNext) { + // The samples are correlations against I and Q versions of the + // tone that the tag AM-modulates, so every other sample is I, + // every other is Q. We just want power, so abs(I) + abs(Q) is + // close to what we want. + if (getNext) { - buf[counter++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1)); + buf[counter++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1)); - if(counter >= 20000) - break; - } else { - cq = ci; - } - getNext = !getNext; - } - } + if(counter >= 20000) + break; + } else { + cq = ci; + } + getNext = !getNext; + } + } - time_stop = GetCountSspClk() - time_0; - int k = DemodAnswer(received, buf, counter); - LogTrace(received, k, time_0 << 4, time_stop << 4, NULL, false); - return k; + time_stop = GetCountSspClk() - time_0; + int k = DemodAnswer(received, buf, counter); + LogTrace(received, k, time_0 << 4, time_stop << 4, NULL, false); + return k; } //----------------------------------------------------------------------------- @@ -484,134 +484,134 @@ static int GetIso15693AnswerFromSniff(uint8_t *received, int *samples, int *elap // so that it can be downloaded to a PC and processed there. //----------------------------------------------------------------------------- void AcquireRawAdcSamplesIso15693(void) { - int c = 0, getNext = false; - int ci = 0, cq = 0; + int c = 0, getNext = false; + int ci = 0, cq = 0; - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - FpgaSetupSsc(); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + FpgaSetupSsc(); - // Now send the command - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX); - SpinDelay(200); + // Now send the command + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_TX); + SpinDelay(200); - uint8_t *buf = BigBuf_get_addr(); + uint8_t *buf = BigBuf_get_addr(); - uint32_t time_start = GetCountSspClk(); - uint8_t cmd[CMD_ID_RESP] = {0}; - BuildIdentifyRequest(cmd); + uint32_t time_start = GetCountSspClk(); + uint8_t cmd[CMD_ID_RESP] = {0}; + BuildIdentifyRequest(cmd); - // sending command - c = 0; - for(;;) { - WDT_HIT(); + // sending command + c = 0; + for(;;) { + WDT_HIT(); - if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { - AT91C_BASE_SSC->SSC_THR = ToSend[c]; - c++; - if(c == ToSendMax + 3) { - break; - } - } - } + if(AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_TXRDY)) { + AT91C_BASE_SSC->SSC_THR = ToSend[c]; + c++; + if(c == ToSendMax + 3) { + break; + } + } + } - LogTrace(cmd, CMD_ID_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true); + LogTrace(cmd, CMD_ID_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true); - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); - c = 0; - for(;;) { - WDT_HIT(); + c = 0; + for(;;) { + WDT_HIT(); - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - ci = (int8_t)AT91C_BASE_SSC->SSC_RHR; - ci = ABS(ci); + ci = (int8_t)AT91C_BASE_SSC->SSC_RHR; + ci = ABS(ci); - // The samples are correlations against I and Q versions of the - // tone that the tag AM-modulates, so every other sample is I, - // every other is Q. We just want power, so abs(I) + abs(Q) is - // close to what we want. - // iceman 2016, amplitude sqrt(abs(i) + abs(q)) - if (getNext) { + // The samples are correlations against I and Q versions of the + // tone that the tag AM-modulates, so every other sample is I, + // every other is Q. We just want power, so abs(I) + abs(Q) is + // close to what we want. + // iceman 2016, amplitude sqrt(abs(i) + abs(q)) + if (getNext) { - buf[c++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1)); + buf[c++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1)); - if (c >= 7000) break; + if (c >= 7000) break; - } else { - cq = ci; - } - getNext = !getNext; - } - } + } else { + cq = ci; + } + getNext = !getNext; + } + } } // switch_off, initreader, no logging void RecordRawAdcSamplesIso15693(void) { - int c = 0, getNext = false; - int ci = 0, cq = 0; + int c = 0, getNext = false; + int ci = 0, cq = 0; - Iso15693InitReader(); + Iso15693InitReader(); - uint8_t *buf = BigBuf_get_addr(); + uint8_t *buf = BigBuf_get_addr(); - for(;;) { - WDT_HIT(); + for(;;) { + WDT_HIT(); - if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { + if (AT91C_BASE_SSC->SSC_SR & (AT91C_SSC_RXRDY)) { - ci = (int8_t)AT91C_BASE_SSC->SSC_RHR; - ci = ABS(ci); - // The samples are correlations against I and Q versions of the - // tone that the tag AM-modulates, so every other sample is I, - // every other is Q. We just want power, so abs(I) + abs(Q) is - // close to what we want. - if (getNext) { + ci = (int8_t)AT91C_BASE_SSC->SSC_RHR; + ci = ABS(ci); + // The samples are correlations against I and Q versions of the + // tone that the tag AM-modulates, so every other sample is I, + // every other is Q. We just want power, so abs(I) + abs(Q) is + // close to what we want. + if (getNext) { - buf[c++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1)); + buf[c++] = (uint8_t)(MAX(ci,cq) + (MIN(ci, cq) >> 1)); - if(c >= 7000) - break; - } else { - cq = ci; - } + if(c >= 7000) + break; + } else { + cq = ci; + } - getNext = !getNext; - } - } + getNext = !getNext; + } + } - Dbprintf("done"); - switch_off(); + Dbprintf("done"); + switch_off(); } // Initialize the proxmark as iso15k reader // (this might produces glitches that confuse some tags void Iso15693InitReader(void) { - LEDsoff(); - clear_trace(); - set_tracing(true); + LEDsoff(); + clear_trace(); + set_tracing(true); - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - // Start from off (no field generated) - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelay(10); + // Start from off (no field generated) + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(10); - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - FpgaSetupSsc(); + FpgaSetupSsc(); - // Give the tags time to energize - FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); - SpinDelay(200); + // Give the tags time to energize + FpgaWriteConfWord(FPGA_MAJOR_MODE_HF_READER_RX_XCORR); + SpinDelay(200); - // Start the timer - StartCountSspClk(); + // Start the timer + StartCountSspClk(); - LED_A_ON(); + LED_A_ON(); } /////////////////////////////////////////////////////////////////////// @@ -623,109 +623,109 @@ void Iso15693InitReader(void) { // thing that you must send to a tag to get a response. static void BuildIdentifyRequest(uint8_t *out) { - uint8_t cmd[CMD_ID_RESP] = {0, ISO15_CMD_INVENTORY, 0, 0, 0}; - // flags - cmd[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; - // no mask - cmd[2] = 0x00; - // CRC - AddCrc(cmd, 3); - // coding as high speed (1 out of 4) - CodeIso15693AsReader(cmd, CMD_ID_RESP); - memcpy(out, cmd, CMD_ID_RESP); + uint8_t cmd[CMD_ID_RESP] = {0, ISO15_CMD_INVENTORY, 0, 0, 0}; + // flags + cmd[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; + // no mask + cmd[2] = 0x00; + // CRC + AddCrc(cmd, 3); + // coding as high speed (1 out of 4) + CodeIso15693AsReader(cmd, CMD_ID_RESP); + memcpy(out, cmd, CMD_ID_RESP); } // uid is in transmission order (which is reverse of display order) /* static void BuildReadBlockRequest(uint8_t **out, uint8_t *uid, uint8_t blockNumber ) { - uint8_t cmd[CMD_READ_RESP] = {0,0,0,0,0,0,0,0,0,0,0,0,0}; - // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block - // followed by teh block data - // one sub-carrier, inventory, 1 slot, fast rate - cmd[0] = (1 << 6)| (1 << 5) | (1 << 1); // no SELECT bit, ADDR bit, OPTION bit - // READ BLOCK command code - cmd[1] = 0x20; - // UID may be optionally specified here - // 64-bit UID - cmd[2] = uid[0]; - cmd[3] = uid[1]; - cmd[4] = uid[2]; - cmd[5] = uid[3]; - cmd[6] = uid[4]; - cmd[7] = uid[5]; - cmd[8] = uid[6]; - cmd[9] = uid[7]; // 0xe0; // always e0 (not exactly unique) - // Block number to read - cmd[10] = blockNumber;//0x00; - // CRC - AddCrc(cmd, 11); - CodeIso15693AsReader(cmd, CMD_READ_RESP); - memcpy(out, cmd, CMD_ID_RESP); + uint8_t cmd[CMD_READ_RESP] = {0,0,0,0,0,0,0,0,0,0,0,0,0}; + // If we set the Option_Flag in this request, the VICC will respond with the secuirty status of the block + // followed by teh block data + // one sub-carrier, inventory, 1 slot, fast rate + cmd[0] = (1 << 6)| (1 << 5) | (1 << 1); // no SELECT bit, ADDR bit, OPTION bit + // READ BLOCK command code + cmd[1] = 0x20; + // UID may be optionally specified here + // 64-bit UID + cmd[2] = uid[0]; + cmd[3] = uid[1]; + cmd[4] = uid[2]; + cmd[5] = uid[3]; + cmd[6] = uid[4]; + cmd[7] = uid[5]; + cmd[8] = uid[6]; + cmd[9] = uid[7]; // 0xe0; // always e0 (not exactly unique) + // Block number to read + cmd[10] = blockNumber;//0x00; + // CRC + AddCrc(cmd, 11); + CodeIso15693AsReader(cmd, CMD_READ_RESP); + memcpy(out, cmd, CMD_ID_RESP); } */ // Now the VICC>VCD responses when we are simulating a tag static void BuildInventoryResponse(uint8_t *out, uint8_t *uid) { - uint8_t cmd[CMD_INV_RESP] = {0,0,0,0,0,0,0,0,0,0,0,0}; + uint8_t cmd[CMD_INV_RESP] = {0,0,0,0,0,0,0,0,0,0,0,0}; - // one sub-carrier, inventory, 1 slot, fast rate - // AFI is at bit 5 (1<<4) when doing an INVENTORY + // one sub-carrier, inventory, 1 slot, fast rate + // AFI is at bit 5 (1<<4) when doing an INVENTORY //(1 << 2) | (1 << 5) | (1 << 1); - cmd[0] = 0; // - cmd[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported - // 64-bit UID - cmd[2] = uid[7]; //0x32; - cmd[3] = uid[6]; //0x4b; - cmd[4] = uid[5]; //0x03; - cmd[5] = uid[4]; //0x01; - cmd[6] = uid[3]; //0x00; - cmd[7] = uid[2]; //0x10; - cmd[8] = uid[1]; //0x05; - cmd[9] = uid[0]; //0xe0; - // CRC - AddCrc(cmd, 10); - CodeIso15693AsReader(cmd, CMD_INV_RESP); - memcpy(out, cmd, CMD_ID_RESP); + cmd[0] = 0; // + cmd[1] = 0; // DSFID (data storage format identifier). 0x00 = not supported + // 64-bit UID + cmd[2] = uid[7]; //0x32; + cmd[3] = uid[6]; //0x4b; + cmd[4] = uid[5]; //0x03; + cmd[5] = uid[4]; //0x01; + cmd[6] = uid[3]; //0x00; + cmd[7] = uid[2]; //0x10; + cmd[8] = uid[1]; //0x05; + cmd[9] = uid[0]; //0xe0; + // CRC + AddCrc(cmd, 10); + CodeIso15693AsReader(cmd, CMD_INV_RESP); + memcpy(out, cmd, CMD_ID_RESP); } // Universal Method for sending to and recv bytes from a tag -// init ... should we initialize the reader? -// speed ... 0 low speed, 1 hi speed -// **recv will return you a pointer to the received data -// If you do not need the answer use NULL for *recv[] -// return: lenght of received data +// init ... should we initialize the reader? +// speed ... 0 low speed, 1 hi speed +// **recv will return you a pointer to the received data +// If you do not need the answer use NULL for *recv[] +// return: lenght of received data // logging enabled int SendDataTag(uint8_t *send, int sendlen, bool init, int speed, uint8_t *outdata) { - int t_samples = 0, wait = 0, elapsed = 0, answer_len = 0; + int t_samples = 0, wait = 0, elapsed = 0, answer_len = 0; - LEDsoff(); + LEDsoff(); - if (init) Iso15693InitReader(); + if (init) Iso15693InitReader(); - LED_A_ON(); + LED_A_ON(); - if (!speed) - CodeIso15693AsReader256(send, sendlen); // low speed (1 out of 256) - else - CodeIso15693AsReader(send, sendlen); // high speed (1 out of 4) + if (!speed) + CodeIso15693AsReader256(send, sendlen); // low speed (1 out of 256) + else + CodeIso15693AsReader(send, sendlen); // high speed (1 out of 4) - LED_A_INV(); + LED_A_INV(); - uint32_t time_start = GetCountSspClk(); + uint32_t time_start = GetCountSspClk(); - TransmitTo15693Tag(ToSend, ToSendMax, &t_samples, &wait); - LogTrace(send, sendlen, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true); + TransmitTo15693Tag(ToSend, ToSendMax, &t_samples, &wait); + LogTrace(send, sendlen, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true); - // Now wait for a response - if (outdata != NULL) { - LED_B_INV(); - answer_len = GetIso15693AnswerFromTag(outdata, &elapsed); - } + // Now wait for a response + if (outdata != NULL) { + LED_B_INV(); + answer_len = GetIso15693AnswerFromTag(outdata, &elapsed); + } - LEDsoff(); - return answer_len; + LEDsoff(); + return answer_len; } // -------------------------------------------------------------------- @@ -735,57 +735,57 @@ int SendDataTag(uint8_t *send, int sendlen, bool init, int speed, uint8_t *outda // Decodes a message from a tag and displays its metadata and content #define DBD15STATLEN 48 void DbdecodeIso15693Answer(int len, uint8_t *d) { - char status[DBD15STATLEN+1] = {0}; + char status[DBD15STATLEN+1] = {0}; - if (len > 3) { - if (d[0] & ( 1 << 3 )) - strncat(status, "ProtExt ", DBD15STATLEN); - if (d[0] & 1) { - // error - strncat(status, "Error ", DBD15STATLEN); - switch (d[1]) { - case 0x01: - strncat(status, "01: not supported", DBD15STATLEN); - break; - case 0x02: - strncat(status, "02: not recognized", DBD15STATLEN); - break; - case 0x03: - strncat(status, "03: opt not supported", DBD15STATLEN); - break; - case 0x0f: - strncat(status, "0F: no info", DBD15STATLEN); - break; - case 0x10: - strncat(status, "10: dont exist", DBD15STATLEN); - break; - case 0x11: - strncat(status, "11: lock again", DBD15STATLEN); - break; - case 0x12: - strncat(status, "12: locked", DBD15STATLEN); - break; - case 0x13: - strncat(status, "13: program error", DBD15STATLEN); - break; - case 0x14: - strncat(status, "14: lock error", DBD15STATLEN); - break; - default: - strncat(status, "unknown error", DBD15STATLEN); - } - strncat(status ," " ,DBD15STATLEN); - } else { - strncat(status ,"No error ", DBD15STATLEN); - } + if (len > 3) { + if (d[0] & ( 1 << 3 )) + strncat(status, "ProtExt ", DBD15STATLEN); + if (d[0] & 1) { + // error + strncat(status, "Error ", DBD15STATLEN); + switch (d[1]) { + case 0x01: + strncat(status, "01: not supported", DBD15STATLEN); + break; + case 0x02: + strncat(status, "02: not recognized", DBD15STATLEN); + break; + case 0x03: + strncat(status, "03: opt not supported", DBD15STATLEN); + break; + case 0x0f: + strncat(status, "0F: no info", DBD15STATLEN); + break; + case 0x10: + strncat(status, "10: dont exist", DBD15STATLEN); + break; + case 0x11: + strncat(status, "11: lock again", DBD15STATLEN); + break; + case 0x12: + strncat(status, "12: locked", DBD15STATLEN); + break; + case 0x13: + strncat(status, "13: program error", DBD15STATLEN); + break; + case 0x14: + strncat(status, "14: lock error", DBD15STATLEN); + break; + default: + strncat(status, "unknown error", DBD15STATLEN); + } + strncat(status ," " ,DBD15STATLEN); + } else { + strncat(status ,"No error ", DBD15STATLEN); + } - if (CheckCrc(d, len)) - strncat(status, "[+] crc OK", DBD15STATLEN); - else - strncat(status, "[!] crc fail", DBD15STATLEN); + if (CheckCrc(d, len)) + strncat(status, "[+] crc OK", DBD15STATLEN); + else + strncat(status, "[!] crc fail", DBD15STATLEN); - if ( MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%s", status); - } + if ( MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%s", status); + } } /////////////////////////////////////////////////////////////////////// @@ -799,204 +799,204 @@ void DbdecodeIso15693Answer(int len, uint8_t *d) { // ok // parameter is unused !?! void ReaderIso15693(uint32_t parameter) { - int answerLen1 = 0; - int tsamples = 0, wait = 0, elapsed = 0; + int answerLen1 = 0; + int tsamples = 0, wait = 0, elapsed = 0; - uint8_t uid[8] = {0,0,0,0,0,0,0,0}; + uint8_t uid[8] = {0,0,0,0,0,0,0,0}; - // set up device/fpga - Iso15693InitReader(); + // set up device/fpga + Iso15693InitReader(); - uint8_t *answer1 = BigBuf_malloc(50); - uint8_t *answer2 = BigBuf_malloc(50); + uint8_t *answer1 = BigBuf_malloc(50); + uint8_t *answer2 = BigBuf_malloc(50); - // Blank arrays - memset(answer1, 0x00, 50); - memset(answer2, 0x00, 50); + // Blank arrays + memset(answer1, 0x00, 50); + memset(answer2, 0x00, 50); - // Now send the IDENTIFY command - // FIRST WE RUN AN INVENTORY TO GET THE TAG UID - // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME - uint32_t time_start = GetCountSspClk(); - uint8_t cmd[CMD_ID_RESP] = {0}; - BuildIdentifyRequest( cmd ); - TransmitTo15693Tag(ToSend, ToSendMax, &tsamples, &wait); - LogTrace(cmd, CMD_ID_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true); + // Now send the IDENTIFY command + // FIRST WE RUN AN INVENTORY TO GET THE TAG UID + // THIS MEANS WE CAN PRE-BUILD REQUESTS TO SAVE CPU TIME + uint32_t time_start = GetCountSspClk(); + uint8_t cmd[CMD_ID_RESP] = {0}; + BuildIdentifyRequest( cmd ); + TransmitTo15693Tag(ToSend, ToSendMax, &tsamples, &wait); + LogTrace(cmd, CMD_ID_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true); - // Now wait for a response - answerLen1 = GetIso15693AnswerFromTag(answer1, &elapsed) ; + // Now wait for a response + answerLen1 = GetIso15693AnswerFromTag(answer1, &elapsed) ; - // we should do a better check than this - if (answerLen1 >= 12) { - uid[0] = answer1[9]; // always E0 - uid[1] = answer1[8]; // IC Manufacturer code - uid[2] = answer1[7]; - uid[3] = answer1[6]; - uid[4] = answer1[5]; - uid[5] = answer1[4]; - uid[6] = answer1[3]; - uid[7] = answer1[2]; + // we should do a better check than this + if (answerLen1 >= 12) { + uid[0] = answer1[9]; // always E0 + uid[1] = answer1[8]; // IC Manufacturer code + uid[2] = answer1[7]; + uid[3] = answer1[6]; + uid[4] = answer1[5]; + uid[5] = answer1[4]; + uid[6] = answer1[3]; + uid[7] = answer1[2]; - if ( MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("[+] UID = %02X%02X%02X%02X%02X%02X%02X%02X", - uid[0], uid[1], uid[2], uid[3], - uid[4], uid[5], uid[5], uid[6] - ); - } - // send UID back to client. - // arg0 = 1 = OK - // arg1 = len of response (12 bytes) - // arg2 = rtf - // asbytes = uid. - cmd_send(CMD_ACK, 1, sizeof(uid), 0, uid, sizeof(uid)); - } + if ( MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("[+] UID = %02X%02X%02X%02X%02X%02X%02X%02X", + uid[0], uid[1], uid[2], uid[3], + uid[4], uid[5], uid[5], uid[6] + ); + } + // send UID back to client. + // arg0 = 1 = OK + // arg1 = len of response (12 bytes) + // arg2 = rtf + // asbytes = uid. + cmd_send(CMD_ACK, 1, sizeof(uid), 0, uid, sizeof(uid)); + } - if ( MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("[+] %d octets read from IDENTIFY request:", answerLen1); - DbdecodeIso15693Answer(answerLen1, answer1); - Dbhexdump(answerLen1, answer1, true); - } + if ( MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("[+] %d octets read from IDENTIFY request:", answerLen1); + DbdecodeIso15693Answer(answerLen1, answer1); + Dbhexdump(answerLen1, answer1, true); + } - switch_off(); + switch_off(); } // Simulate an ISO15693 TAG, perform anti-collision and then print any reader commands // all demodulation performed in arm rather than host. - greg void SimTagIso15693(uint32_t parameter, uint8_t *uid) { - LEDsoff(); - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - SetAdcMuxFor(GPIO_MUXSEL_HIPKD); - FpgaSetupSsc(); - // Start from off (no field generated) + LEDsoff(); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + SetAdcMuxFor(GPIO_MUXSEL_HIPKD); + FpgaSetupSsc(); + // Start from off (no field generated) FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelay(200); + SpinDelay(200); - LED_A_ON(); + LED_A_ON(); - uint32_t time_start = 0; - int ans = 0, samples = 0, tsamples = 0; - int wait = 0, elapsed = 0; + uint32_t time_start = 0; + int ans = 0, samples = 0, tsamples = 0; + int wait = 0, elapsed = 0; - Dbprintf("ISO-15963 Simulating uid: %02X%02X%02X%02X%02X%02X%02X%02X", uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]); + Dbprintf("ISO-15963 Simulating uid: %02X%02X%02X%02X%02X%02X%02X%02X", uid[0], uid[1], uid[2], uid[3], uid[4], uid[5], uid[6], uid[7]); - uint8_t buf[ISO15_MAX_FRAME]; - memset(buf, 0x00, sizeof(buf)); + uint8_t buf[ISO15_MAX_FRAME]; + memset(buf, 0x00, sizeof(buf)); - LED_C_ON(); + LED_C_ON(); - // Build a suitable reponse to the reader INVENTORY cocmmand - // not so obsvious, but in the call to BuildInventoryResponse, the command is copied to the global ToSend buffer used below. - uint8_t cmd[CMD_INV_RESP] = {0}; - BuildInventoryResponse(cmd, uid); + // Build a suitable reponse to the reader INVENTORY cocmmand + // not so obsvious, but in the call to BuildInventoryResponse, the command is copied to the global ToSend buffer used below. + uint8_t cmd[CMD_INV_RESP] = {0}; + BuildInventoryResponse(cmd, uid); - while (!BUTTON_PRESS() && !usb_poll_validate_length() ) { - WDT_HIT(); + while (!BUTTON_PRESS() && !usb_poll_validate_length() ) { + WDT_HIT(); - // Listen to reader - ans = GetIso15693AnswerFromSniff(buf, &samples, &elapsed) ; + // Listen to reader + ans = GetIso15693AnswerFromSniff(buf, &samples, &elapsed) ; - // we should do a better check than this - if (ans >= 1 ) { + // we should do a better check than this + if (ans >= 1 ) { - time_start = GetCountSspClk(); - TransmitTo15693Reader(ToSend, ToSendMax, &tsamples, &wait); - LogTrace(cmd, CMD_INV_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true); + time_start = GetCountSspClk(); + TransmitTo15693Reader(ToSend, ToSendMax, &tsamples, &wait); + LogTrace(cmd, CMD_INV_RESP, time_start << 4, (GetCountSspClk() - time_start) << 4, NULL, true); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("[+] %d octets read from reader command: %x %x %x %x %x %x %x %x", ans, - buf[0], buf[1], buf[2], buf[3], - buf[4], buf[5], buf[6], buf[7] - ); - } - } - } - switch_off(); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("[+] %d octets read from reader command: %x %x %x %x %x %x %x %x", ans, + buf[0], buf[1], buf[2], buf[3], + buf[4], buf[5], buf[6], buf[7] + ); + } + } + } + switch_off(); } // Since there is no standardized way of reading the AFI out of a tag, we will brute force it // (some manufactures offer a way to read the AFI, though) void BruteforceIso15693Afi(uint32_t speed) { - uint8_t data[7] = {0,0,0,0,0,0,0}; - uint8_t buf[ISO15_MAX_FRAME]; - memset(buf, 0x00, sizeof(buf)); - int datalen = 0, recvlen = 0; + uint8_t data[7] = {0,0,0,0,0,0,0}; + uint8_t buf[ISO15_MAX_FRAME]; + memset(buf, 0x00, sizeof(buf)); + int datalen = 0, recvlen = 0; - Iso15693InitReader(); + Iso15693InitReader(); - // first without AFI - // Tags should respond wihtout AFI and with AFI=0 even when AFI is active + // first without AFI + // Tags should respond wihtout AFI and with AFI=0 even when AFI is active - data[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; - data[1] = ISO15_CMD_INVENTORY; - data[2] = 0; // mask length - AddCrc(data, 3); - datalen += 2; + data[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; + data[1] = ISO15_CMD_INVENTORY; + data[2] = 0; // mask length + AddCrc(data, 3); + datalen += 2; - recvlen = SendDataTag(data, datalen, false, speed, buf); + recvlen = SendDataTag(data, datalen, false, speed, buf); - WDT_HIT(); + WDT_HIT(); - if (recvlen >= 12) { - Dbprintf("NoAFI UID = %s", sprintUID(NULL, buf + 2) ); - } + if (recvlen >= 12) { + Dbprintf("NoAFI UID = %s", sprintUID(NULL, buf + 2) ); + } - // now with AFI - data[0] |= ISO15_REQINV_AFI; - //data[1] = ISO15_CMD_INVENTORY; - data[2] = 0; // AFI - data[3] = 0; // mask length + // now with AFI + data[0] |= ISO15_REQINV_AFI; + //data[1] = ISO15_CMD_INVENTORY; + data[2] = 0; // AFI + data[3] = 0; // mask length - for (uint16_t i = 0; i < 256; i++) { - data[2] = i & 0xFF; - AddCrc(data, 4); - datalen += 2; - recvlen = SendDataTag(data, datalen, false, speed, buf); - WDT_HIT(); - if (recvlen >= 12) { - Dbprintf("AFI = %i UID = %s", i, sprintUID(NULL, buf + 2) ); - } + for (uint16_t i = 0; i < 256; i++) { + data[2] = i & 0xFF; + AddCrc(data, 4); + datalen += 2; + recvlen = SendDataTag(data, datalen, false, speed, buf); + WDT_HIT(); + if (recvlen >= 12) { + Dbprintf("AFI = %i UID = %s", i, sprintUID(NULL, buf + 2) ); + } - if (BUTTON_PRESS()) { - DbpString("button pressed, aborting.."); - break; - } - } + if (BUTTON_PRESS()) { + DbpString("button pressed, aborting.."); + break; + } + } - DbpString("AFI Bruteforcing done."); - switch_off(); + DbpString("AFI Bruteforcing done."); + switch_off(); } // Allows to directly send commands to the tag via the client // Has to increase dialog between device and client. void DirectTag15693Command(uint32_t datalen, uint32_t speed, uint32_t recv, uint8_t *data) { - bool init = true; - int buflen = 0; - uint8_t buf[ISO15_MAX_FRAME]; - memset(buf, 0x00, sizeof(buf)); + bool init = true; + int buflen = 0; + uint8_t buf[ISO15_MAX_FRAME]; + memset(buf, 0x00, sizeof(buf)); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - DbpString("[+] SEND"); - Dbhexdump(datalen, data, true); - } + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + DbpString("[+] SEND"); + Dbhexdump(datalen, data, true); + } - buflen = SendDataTag(data, datalen, init, speed, (recv ? buf : NULL)); + buflen = SendDataTag(data, datalen, init, speed, (recv ? buf : NULL)); - if (recv) { - buflen = (buflen > ISO15_MAX_FRAME) ? ISO15_MAX_FRAME : buflen; + if (recv) { + buflen = (buflen > ISO15_MAX_FRAME) ? ISO15_MAX_FRAME : buflen; - LED_B_ON(); - cmd_send(CMD_ACK, buflen, 0, 0, buf, buflen); - LED_B_OFF(); + LED_B_ON(); + cmd_send(CMD_ACK, buflen, 0, 0, buf, buflen); + LED_B_OFF(); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - DbpString("[+] RECV"); - DbdecodeIso15693Answer(buflen, buf); - Dbhexdump(buflen, buf, true); - } - } else { - cmd_send(CMD_ACK,1,0,0,0,0); - } + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + DbpString("[+] RECV"); + DbdecodeIso15693Answer(buflen, buf); + Dbhexdump(buflen, buf, true); + } + } else { + cmd_send(CMD_ACK,1,0,0,0,0); + } } \ No newline at end of file diff --git a/armsrc/lfops.c b/armsrc/lfops.c index 3296aff8c..bd34e46df 100644 --- a/armsrc/lfops.c +++ b/armsrc/lfops.c @@ -22,10 +22,10 @@ #include "flashmem.h" // persistence on mem #ifndef SHORT_COIL -# define SHORT_COIL() LOW(GPIO_SSC_DOUT) +# define SHORT_COIL() LOW(GPIO_SSC_DOUT) #endif #ifndef OPEN_COIL -# define OPEN_COIL() HIGH(GPIO_SSC_DOUT) +# define OPEN_COIL() HIGH(GPIO_SSC_DOUT) #endif //#define START_GAP 31*8 // was 250 // SPEC: 1*8 to 50*8 - typ 15*8 (15fc) @@ -53,99 +53,99 @@ // 1fc = 8us = 12ticks /* Default LF T55xx config is set to: - startgap = 31*8 - writegap = 17*8 - write_0 = 15*8 - write_1 = 47*8 - read_gap = 15*8 + startgap = 31*8 + writegap = 17*8 + write_0 = 15*8 + write_1 = 47*8 + read_gap = 15*8 */ t55xx_config t_config = { 29*8, 17*8, 15*8, 47*8, 15*8 } ; void printT55xxConfig(void) { - Dbprintf("LF T55XX config"); - Dbprintf(" [a] startgap............%d*8 (%d)", t_config.start_gap/8, t_config.start_gap); - Dbprintf(" [b] writegap............%d*8 (%d)", t_config.write_gap/8, t_config.write_gap); - Dbprintf(" [c] write_0.............%d*8 (%d)", t_config.write_0/8, t_config.write_0); - Dbprintf(" [d] write_1.............%d*8 (%d)", t_config.write_1/8, t_config.write_1); - Dbprintf(" [e] readgap.............%d*8 (%d)", t_config.read_gap/8, t_config.read_gap); + Dbprintf("LF T55XX config"); + Dbprintf(" [a] startgap............%d*8 (%d)", t_config.start_gap/8, t_config.start_gap); + Dbprintf(" [b] writegap............%d*8 (%d)", t_config.write_gap/8, t_config.write_gap); + Dbprintf(" [c] write_0.............%d*8 (%d)", t_config.write_0/8, t_config.write_0); + Dbprintf(" [d] write_1.............%d*8 (%d)", t_config.write_1/8, t_config.write_1); + Dbprintf(" [e] readgap.............%d*8 (%d)", t_config.read_gap/8, t_config.read_gap); } void setT55xxConfig(uint8_t arg0, t55xx_config *c) { - if (c->start_gap != 0) t_config.start_gap = c->start_gap; - if (c->write_gap != 0) t_config.write_gap = c->write_gap; - if (c->write_0 != 0) t_config.write_0 = c->write_0; - if (c->write_1 != 0) t_config.write_1 = c->write_1; - if (c->read_gap != 0) t_config.read_gap = c->read_gap; + if (c->start_gap != 0) t_config.start_gap = c->start_gap; + if (c->write_gap != 0) t_config.write_gap = c->write_gap; + if (c->write_0 != 0) t_config.write_0 = c->write_0; + if (c->write_1 != 0) t_config.write_1 = c->write_1; + if (c->read_gap != 0) t_config.read_gap = c->read_gap; - printT55xxConfig(); + printT55xxConfig(); #ifdef WITH_FLASH - // shall persist to flashmem - if (arg0 == 0) { - return; - } + // shall persist to flashmem + if (arg0 == 0) { + return; + } if (!FlashInit()) { return; - } + } - uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN); - Flash_CheckBusy(BUSY_TIMEOUT); - uint16_t res = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN); - if ( res == 0) { - FlashStop(); - BigBuf_free(); - return; - } + uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN); + Flash_CheckBusy(BUSY_TIMEOUT); + uint16_t res = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN); + if ( res == 0) { + FlashStop(); + BigBuf_free(); + return; + } - memcpy(buf, &t_config, T55XX_CONFIG_LEN); + memcpy(buf, &t_config, T55XX_CONFIG_LEN); - Flash_CheckBusy(BUSY_TIMEOUT); + Flash_CheckBusy(BUSY_TIMEOUT); Flash_WriteEnable(); - Flash_Erase4k(3, 0xD); - res = Flash_Write(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN); + Flash_Erase4k(3, 0xD); + res = Flash_Write(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN); - if ( res == T55XX_CONFIG_LEN && MF_DBGLEVEL > 1) { - DbpString("T55XX Config save success"); - } + if ( res == T55XX_CONFIG_LEN && MF_DBGLEVEL > 1) { + DbpString("T55XX Config save success"); + } - BigBuf_free(); + BigBuf_free(); #endif } t55xx_config* getT55xxConfig(void) { - return &t_config; + return &t_config; } void loadT55xxConfig(void) { #ifdef WITH_FLASH if (!FlashInit()) { return; - } + } - uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN); + uint8_t *buf = BigBuf_malloc(T55XX_CONFIG_LEN); - Flash_CheckBusy(BUSY_TIMEOUT); - uint16_t isok = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN); - FlashStop(); + Flash_CheckBusy(BUSY_TIMEOUT); + uint16_t isok = Flash_ReadDataCont(T55XX_CONFIG_OFFSET, buf, T55XX_CONFIG_LEN); + FlashStop(); - // verify read mem is actual data. - uint8_t cntA = T55XX_CONFIG_LEN, cntB = T55XX_CONFIG_LEN; - for (int i=0; i< T55XX_CONFIG_LEN; i++) { - if ( buf[i] == 0xFF) cntA--; - if ( buf[i] == 0x00) cntB--; - } - if ( !cntA || !cntB ) { - BigBuf_free(); - return; - } + // verify read mem is actual data. + uint8_t cntA = T55XX_CONFIG_LEN, cntB = T55XX_CONFIG_LEN; + for (int i=0; i< T55XX_CONFIG_LEN; i++) { + if ( buf[i] == 0xFF) cntA--; + if ( buf[i] == 0x00) cntB--; + } + if ( !cntA || !cntB ) { + BigBuf_free(); + return; + } - memcpy((uint8_t *)&t_config, buf, T55XX_CONFIG_LEN); + memcpy((uint8_t *)&t_config, buf, T55XX_CONFIG_LEN); - if ( isok == T55XX_CONFIG_LEN) { - if (MF_DBGLEVEL > 1) DbpString("T55XX Config load success"); - } + if ( isok == T55XX_CONFIG_LEN) { + if (MF_DBGLEVEL > 1) DbpString("T55XX Config load success"); + } #endif } @@ -158,98 +158,98 @@ void loadT55xxConfig(void) { */ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint32_t period_1, uint8_t *command) { - // start timer - StartTicks(); + // start timer + StartTicks(); - // use lf config settings - sample_config *sc = getSamplingConfig(); + // use lf config settings + sample_config *sc = getSamplingConfig(); - // Make sure the tag is reset - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitMS(500); + // Make sure the tag is reset + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + WaitMS(500); - // clear read buffer - BigBuf_Clear_keep_EM(); + // clear read buffer + BigBuf_Clear_keep_EM(); - LFSetupFPGAForADC(sc->divisor, 1); + LFSetupFPGAForADC(sc->divisor, 1); - // little more time for the tag to fully power up - WaitMS(200); + // little more time for the tag to fully power up + WaitMS(200); - // if delay_off = 0 then just bitbang 1 = antenna on 0 = off for respective periods. - bool bitbang = delay_off == 0; - // now modulate the reader field - if (bitbang) { - // HACK it appears the loop and if statements take up about 7us so adjust waits accordingly... - uint8_t hack_cnt = 7; - if (period_0 < hack_cnt || period_1 < hack_cnt) { - DbpString("[!] Warning periods cannot be less than 7us in bit bang mode"); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LED_D_OFF(); - return; - } + // if delay_off = 0 then just bitbang 1 = antenna on 0 = off for respective periods. + bool bitbang = delay_off == 0; + // now modulate the reader field + if (bitbang) { + // HACK it appears the loop and if statements take up about 7us so adjust waits accordingly... + uint8_t hack_cnt = 7; + if (period_0 < hack_cnt || period_1 < hack_cnt) { + DbpString("[!] Warning periods cannot be less than 7us in bit bang mode"); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); + return; + } - // hack2 needed--- it appears to take about 8-16us to turn the antenna back on - // leading to ~ 1 to 2 125khz samples extra in every off period - // so we should test for last 0 before next 1 and reduce period_0 by this extra amount... - // but is this time different for every antenna or other hw builds??? more testing needed + // hack2 needed--- it appears to take about 8-16us to turn the antenna back on + // leading to ~ 1 to 2 125khz samples extra in every off period + // so we should test for last 0 before next 1 and reduce period_0 by this extra amount... + // but is this time different for every antenna or other hw builds??? more testing needed - // prime cmd_len to save time comparing strings while modulating - int cmd_len = 0; - while(command[cmd_len] != '\0' && command[cmd_len] != ' ') - cmd_len++; + // prime cmd_len to save time comparing strings while modulating + int cmd_len = 0; + while(command[cmd_len] != '\0' && command[cmd_len] != ' ') + cmd_len++; - int counter = 0; - bool off = false; - for (counter = 0; counter < cmd_len; counter++) { - // if cmd = 0 then turn field off - if (command[counter] == '0') { - // if field already off leave alone (affects timing otherwise) - if (off == false) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LED_D_OFF(); - off = true; - } - // note we appear to take about 7us to switch over (or run the if statements/loop...) - WaitUS(period_0 - hack_cnt); - // else if cmd = 1 then turn field on - } else { - // if field already on leave alone (affects timing otherwise) - if (off) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); - LED_D_ON(); - off = false; - } - // note we appear to take about 7us to switch over (or run the if statements/loop...) - WaitUS(period_1 - hack_cnt); - } - } - } else { // old mode of cmd read using delay as off period - while(*command != '\0' && *command != ' ') { - LED_D_ON(); - if (*(command++) == '0') - TurnReadLFOn(period_0); - else - TurnReadLFOn(period_1); + int counter = 0; + bool off = false; + for (counter = 0; counter < cmd_len; counter++) { + // if cmd = 0 then turn field off + if (command[counter] == '0') { + // if field already off leave alone (affects timing otherwise) + if (off == false) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); + off = true; + } + // note we appear to take about 7us to switch over (or run the if statements/loop...) + WaitUS(period_0 - hack_cnt); + // else if cmd = 1 then turn field on + } else { + // if field already on leave alone (affects timing otherwise) + if (off) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + LED_D_ON(); + off = false; + } + // note we appear to take about 7us to switch over (or run the if statements/loop...) + WaitUS(period_1 - hack_cnt); + } + } + } else { // old mode of cmd read using delay as off period + while(*command != '\0' && *command != ' ') { + LED_D_ON(); + if (*(command++) == '0') + TurnReadLFOn(period_0); + else + TurnReadLFOn(period_1); - LED_D_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(delay_off); - } + LED_D_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + WaitUS(delay_off); + } - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor); - } + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor); + } - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); - // now do the read - DoAcquisition_config(false, 0); + // now do the read + DoAcquisition_config(false, 0); - // Turn off antenna - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - // tell client we are done - cmd_send(CMD_ACK,0,0,0,0,0); + // Turn off antenna + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + // tell client we are done + cmd_send(CMD_ACK,0,0,0,0,0); } /* blank r/w tag data stream @@ -263,238 +263,238 @@ void ModThenAcquireRawAdcSamples125k(uint32_t delay_off, uint32_t period_0, uint */ void ReadTItag(void) { - StartTicks(); - // some hardcoded initial params - // 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 + StartTicks(); + // some hardcoded initial params + // 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 - signed char *dest = (signed char *)BigBuf_get_addr(); - uint16_t n = BigBuf_max_traceLen(); - // 128 bit shift register [shift3:shift2:shift1:shift0] - uint32_t shift3 = 0, shift2 = 0, shift1 = 0, shift0 = 0; + signed char *dest = (signed char *)BigBuf_get_addr(); + uint16_t n = BigBuf_max_traceLen(); + // 128 bit shift register [shift3:shift2:shift1:shift0] + uint32_t shift3 = 0, shift2 = 0, shift1 = 0, shift0 = 0; - int i, cycles=0, samples=0; - // how many sample points fit in 16 cycles of each frequency - uint32_t sampleslo = (FSAMPLE<<4)/FREQLO, sampleshi = (FSAMPLE<<4)/FREQHI; - // when to tell if we're close enough to one freq or another - uint32_t threshold = (sampleslo - sampleshi + 1)>>1; + int i, cycles=0, samples=0; + // how many sample points fit in 16 cycles of each frequency + uint32_t sampleslo = (FSAMPLE<<4)/FREQLO, sampleshi = (FSAMPLE<<4)/FREQHI; + // when to tell if we're close enough to one freq or another + uint32_t threshold = (sampleslo - sampleshi + 1)>>1; - // TI tags charge at 134.2Khz - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz + // TI tags charge at 134.2Khz + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz - // Place FPGA in passthrough mode, in this mode the CROSS_LO line - // connects to SSP_DIN and the SSP_DOUT logic level controls - // whether we're modulating the antenna (high) - // or listening to the antenna (low) - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU); + // Place FPGA in passthrough mode, in this mode the CROSS_LO line + // connects to SSP_DIN and the SSP_DOUT logic level controls + // whether we're modulating the antenna (high) + // or listening to the antenna (low) + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU); - // get TI tag data into the buffer - AcquireTiType(); + // get TI tag data into the buffer + AcquireTiType(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - for (i=0; i0) ) { - cycles++; - // after 16 cycles, measure the frequency - if (cycles>15) { - cycles=0; - samples=i-samples; // number of samples in these 16 cycles + for (i=0; i0) ) { + cycles++; + // after 16 cycles, measure the frequency + if (cycles>15) { + cycles=0; + samples=i-samples; // number of samples in these 16 cycles - // TI bits are coming to us lsb first so shift them - // right through our 128 bit right shift register - shift0 = (shift0>>1) | (shift1 << 31); - shift1 = (shift1>>1) | (shift2 << 31); - shift2 = (shift2>>1) | (shift3 << 31); - shift3 >>= 1; + // TI bits are coming to us lsb first so shift them + // right through our 128 bit right shift register + shift0 = (shift0>>1) | (shift1 << 31); + shift1 = (shift1>>1) | (shift2 << 31); + shift2 = (shift2>>1) | (shift3 << 31); + shift3 >>= 1; - // check if the cycles fall close to the number - // expected for either the low or high frequency - if ( (samples>(sampleslo-threshold)) && (samples<(sampleslo+threshold)) ) { - // low frequency represents a 1 - shift3 |= (1<<31); - } else if ( (samples>(sampleshi-threshold)) && (samples<(sampleshi+threshold)) ) { - // high frequency represents a 0 - } else { - // probably detected a gay waveform or noise - // use this as gaydar or discard shift register and start again - shift3 = shift2 = shift1 = shift0 = 0; - } - samples = i; + // check if the cycles fall close to the number + // expected for either the low or high frequency + if ( (samples>(sampleslo-threshold)) && (samples<(sampleslo+threshold)) ) { + // low frequency represents a 1 + shift3 |= (1<<31); + } else if ( (samples>(sampleshi-threshold)) && (samples<(sampleshi+threshold)) ) { + // high frequency represents a 0 + } else { + // probably detected a gay waveform or noise + // use this as gaydar or discard shift register and start again + shift3 = shift2 = shift1 = shift0 = 0; + } + samples = i; - // for each bit we receive, test if we've detected a valid tag + // for each bit we receive, test if we've detected a valid tag - // if we see 17 zeroes followed by 6 ones, we might have a tag - // remember the bits are backwards - if ( ((shift0 & 0x7fffff) == 0x7e0000) ) { - // if start and end bytes match, we have a tag so break out of the loop - if ( ((shift0>>16)&0xff) == ((shift3>>8)&0xff) ) { - cycles = 0xF0B; //use this as a flag (ugly but whatever) - break; - } - } - } - } - } + // if we see 17 zeroes followed by 6 ones, we might have a tag + // remember the bits are backwards + if ( ((shift0 & 0x7fffff) == 0x7e0000) ) { + // if start and end bytes match, we have a tag so break out of the loop + if ( ((shift0>>16)&0xff) == ((shift3>>8)&0xff) ) { + cycles = 0xF0B; //use this as a flag (ugly but whatever) + break; + } + } + } + } + } - // if flag is set we have a tag - if (cycles!=0xF0B) { - DbpString("Info: No valid tag detected."); - } else { - // put 64 bit data into shift1 and shift0 - shift0 = (shift0>>24) | (shift1 << 8); - shift1 = (shift1>>24) | (shift2 << 8); + // if flag is set we have a tag + if (cycles!=0xF0B) { + DbpString("Info: No valid tag detected."); + } else { + // put 64 bit data into shift1 and shift0 + shift0 = (shift0>>24) | (shift1 << 8); + shift1 = (shift1>>24) | (shift2 << 8); - // align 16 bit crc into lower half of shift2 - shift2 = ((shift2>>24) | (shift3 << 8)) & 0x0ffff; + // align 16 bit crc into lower half of shift2 + shift2 = ((shift2>>24) | (shift3 << 8)) & 0x0ffff; - // if r/w tag, check ident match - if (shift3 & (1<<15) ) { - DbpString("Info: TI tag is rewriteable"); - // only 15 bits compare, last bit of ident is not valid - if (((shift3 >> 16) ^ shift0) & 0x7fff ) { - DbpString("Error: Ident mismatch!"); - } else { - DbpString("Info: TI tag ident is valid"); - } - } else { - DbpString("Info: TI tag is readonly"); - } + // if r/w tag, check ident match + if (shift3 & (1<<15) ) { + DbpString("Info: TI tag is rewriteable"); + // only 15 bits compare, last bit of ident is not valid + if (((shift3 >> 16) ^ shift0) & 0x7fff ) { + DbpString("Error: Ident mismatch!"); + } else { + DbpString("Info: TI tag ident is valid"); + } + } else { + DbpString("Info: TI tag is readonly"); + } - // WARNING the order of the bytes in which we calc crc below needs checking - // i'm 99% sure the crc algorithm is correct, but it may need to eat the - // bytes in reverse or something - // calculate CRC - uint32_t crc=0; + // WARNING the order of the bytes in which we calc crc below needs checking + // i'm 99% sure the crc algorithm is correct, but it may need to eat the + // bytes in reverse or something + // calculate CRC + uint32_t crc=0; - crc = update_crc16(crc, (shift0)&0xff); - crc = update_crc16(crc, (shift0>>8)&0xff); - crc = update_crc16(crc, (shift0>>16)&0xff); - crc = update_crc16(crc, (shift0>>24)&0xff); - crc = update_crc16(crc, (shift1)&0xff); - crc = update_crc16(crc, (shift1>>8)&0xff); - crc = update_crc16(crc, (shift1>>16)&0xff); - crc = update_crc16(crc, (shift1>>24)&0xff); + crc = update_crc16(crc, (shift0)&0xff); + crc = update_crc16(crc, (shift0>>8)&0xff); + crc = update_crc16(crc, (shift0>>16)&0xff); + crc = update_crc16(crc, (shift0>>24)&0xff); + crc = update_crc16(crc, (shift1)&0xff); + crc = update_crc16(crc, (shift1>>8)&0xff); + crc = update_crc16(crc, (shift1>>16)&0xff); + crc = update_crc16(crc, (shift1>>24)&0xff); - Dbprintf("Info: Tag data: %x%08x, crc=%x", (unsigned int)shift1, (unsigned int)shift0, (unsigned int)shift2 & 0xFFFF); - if (crc != (shift2&0xffff)) { - Dbprintf("Error: CRC mismatch, expected %x", (unsigned int)crc); - } else { - DbpString("Info: CRC is good"); - } - } - StopTicks(); + Dbprintf("Info: Tag data: %x%08x, crc=%x", (unsigned int)shift1, (unsigned int)shift0, (unsigned int)shift2 & 0xFFFF); + if (crc != (shift2&0xffff)) { + Dbprintf("Error: CRC mismatch, expected %x", (unsigned int)crc); + } else { + DbpString("Info: CRC is good"); + } + } + StopTicks(); } void WriteTIbyte(uint8_t b) { - int i = 0; + int i = 0; - // modulate 8 bits out to the antenna - for (i=0; i<8; i++) - { - if ( b & ( 1 << i ) ) { - // stop modulating antenna 1ms - LOW(GPIO_SSC_DOUT); - WaitUS(1000); - // modulate antenna 1ms - HIGH(GPIO_SSC_DOUT); - WaitUS(1000); - } else { - // stop modulating antenna 0.3ms - LOW(GPIO_SSC_DOUT); - WaitUS(300); - // modulate antenna 1.7ms - HIGH(GPIO_SSC_DOUT); - WaitUS(1700); - } - } + // modulate 8 bits out to the antenna + for (i=0; i<8; i++) + { + if ( b & ( 1 << i ) ) { + // stop modulating antenna 1ms + LOW(GPIO_SSC_DOUT); + WaitUS(1000); + // modulate antenna 1ms + HIGH(GPIO_SSC_DOUT); + WaitUS(1000); + } else { + // stop modulating antenna 0.3ms + LOW(GPIO_SSC_DOUT); + WaitUS(300); + // modulate antenna 1.7ms + HIGH(GPIO_SSC_DOUT); + WaitUS(1700); + } + } } void AcquireTiType(void) { - int i, j, n; - // tag transmission is <20ms, sampling at 2M gives us 40K samples max - // each sample is 1 bit stuffed into a uint32_t so we need 1250 uint32_t - #define TIBUFLEN 1250 + int i, j, n; + // tag transmission is <20ms, sampling at 2M gives us 40K samples max + // each sample is 1 bit stuffed into a uint32_t so we need 1250 uint32_t + #define TIBUFLEN 1250 - // clear buffer - uint32_t *buf = (uint32_t *)BigBuf_get_addr(); + // clear buffer + uint32_t *buf = (uint32_t *)BigBuf_get_addr(); - //clear buffer now so it does not interfere with timing later - BigBuf_Clear_ext(false); + //clear buffer now so it does not interfere with timing later + BigBuf_Clear_ext(false); - // Set up the synchronous serial port - AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DIN; - AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN; + // Set up the synchronous serial port + AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DIN; + AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN; - // steal this pin from the SSP and use it to control the modulation - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + // steal this pin from the SSP and use it to control the modulation + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; - AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN; + AT91C_BASE_SSC->SSC_CR = AT91C_SSC_SWRST; + AT91C_BASE_SSC->SSC_CR = AT91C_SSC_RXEN | AT91C_SSC_TXEN; - // Sample at 2 Mbit/s, so TI tags are 16.2 vs. 14.9 clocks long - // 48/2 = 24 MHz clock must be divided by 12 - AT91C_BASE_SSC->SSC_CMR = 12; + // Sample at 2 Mbit/s, so TI tags are 16.2 vs. 14.9 clocks long + // 48/2 = 24 MHz clock must be divided by 12 + AT91C_BASE_SSC->SSC_CMR = 12; - AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(0); - AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(32) | AT91C_SSC_MSBF; - // Transmit Clock Mode Register - AT91C_BASE_SSC->SSC_TCMR = 0; - // Transmit Frame Mode Register - AT91C_BASE_SSC->SSC_TFMR = 0; - // iceman, FpgaSetupSsc() ?? the code above? can it be replaced? - LED_D_ON(); + AT91C_BASE_SSC->SSC_RCMR = SSC_CLOCK_MODE_SELECT(0); + AT91C_BASE_SSC->SSC_RFMR = SSC_FRAME_MODE_BITS_IN_WORD(32) | AT91C_SSC_MSBF; + // Transmit Clock Mode Register + AT91C_BASE_SSC->SSC_TCMR = 0; + // Transmit Frame Mode Register + AT91C_BASE_SSC->SSC_TFMR = 0; + // iceman, FpgaSetupSsc() ?? the code above? can it be replaced? + LED_D_ON(); - // modulate antenna - HIGH(GPIO_SSC_DOUT); + // modulate antenna + HIGH(GPIO_SSC_DOUT); - // Charge TI tag for 50ms. - WaitMS(50); + // Charge TI tag for 50ms. + WaitMS(50); - // stop modulating antenna and listen - LOW(GPIO_SSC_DOUT); + // stop modulating antenna and listen + LOW(GPIO_SSC_DOUT); - LED_D_OFF(); + LED_D_OFF(); - i = 0; - for (;;) { - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - buf[i] = AT91C_BASE_SSC->SSC_RHR; // store 32 bit values in buffer - i++; - if (i >= TIBUFLEN) break; - } - WDT_HIT(); - } + i = 0; + for (;;) { + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + buf[i] = AT91C_BASE_SSC->SSC_RHR; // store 32 bit values in buffer + i++; + if (i >= TIBUFLEN) break; + } + WDT_HIT(); + } - // return stolen pin to SSP - AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN | GPIO_SSC_DOUT; + // return stolen pin to SSP + AT91C_BASE_PIOA->PIO_PDR = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_ASR = GPIO_SSC_DIN | GPIO_SSC_DOUT; - char *dest = (char *)BigBuf_get_addr(); - n = TIBUFLEN * 32; + char *dest = (char *)BigBuf_get_addr(); + n = TIBUFLEN * 32; - // unpack buffer - for (i = TIBUFLEN-1; i >= 0; i--) { - for (j = 0; j < 32; j++) { - if(buf[i] & (1 << j)) { - dest[--n] = 1; - } else { - dest[--n] = -1; - } - } - } + // unpack buffer + for (i = TIBUFLEN-1; i >= 0; i--) { + for (j = 0; j < 32; j++) { + if(buf[i] & (1 << j)) { + dest[--n] = 1; + } else { + dest[--n] = -1; + } + } + } - // reset SSC - FpgaSetupSsc(); + // reset SSC + FpgaSetupSsc(); } // arguments: 64bit data split into 32bit idhi:idlo and optional 16bit crc @@ -502,162 +502,163 @@ void AcquireTiType(void) // if not provided a valid crc will be computed from the data and written. void WriteTItag(uint32_t idhi, uint32_t idlo, uint16_t crc) { - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - if(crc == 0) { - crc = update_crc16(crc, (idlo)&0xff); - crc = update_crc16(crc, (idlo>>8)&0xff); - crc = update_crc16(crc, (idlo>>16)&0xff); - crc = update_crc16(crc, (idlo>>24)&0xff); - crc = update_crc16(crc, (idhi)&0xff); - crc = update_crc16(crc, (idhi>>8)&0xff); - crc = update_crc16(crc, (idhi>>16)&0xff); - crc = update_crc16(crc, (idhi>>24)&0xff); - } - Dbprintf("Writing to tag: %x%08x, crc=%x", idhi, idlo, crc); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + if(crc == 0) { + crc = update_crc16(crc, (idlo)&0xff); + crc = update_crc16(crc, (idlo>>8)&0xff); + crc = update_crc16(crc, (idlo>>16)&0xff); + crc = update_crc16(crc, (idlo>>24)&0xff); + crc = update_crc16(crc, (idhi)&0xff); + crc = update_crc16(crc, (idhi>>8)&0xff); + crc = update_crc16(crc, (idhi>>16)&0xff); + crc = update_crc16(crc, (idhi>>24)&0xff); + } + Dbprintf("Writing to tag: %x%08x, crc=%x", idhi, idlo, crc); - // TI tags charge at 134.2Khz - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz - // Place FPGA in passthrough mode, in this mode the CROSS_LO line - // connects to SSP_DIN and the SSP_DOUT logic level controls - // whether we're modulating the antenna (high) - // or listening to the antenna (low) - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU); - StartTicks(); + // TI tags charge at 134.2Khz + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz + // Place FPGA in passthrough mode, in this mode the CROSS_LO line + // connects to SSP_DIN and the SSP_DOUT logic level controls + // whether we're modulating the antenna (high) + // or listening to the antenna (low) + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU); + StartTicks(); - LED_A_ON(); + LED_A_ON(); - // steal this pin from the SSP and use it to control the modulation - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + // steal this pin from the SSP and use it to control the modulation + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - // writing algorithm: - // a high bit consists of a field off for 1ms and field on for 1ms - // a low bit consists of a field off for 0.3ms and field on for 1.7ms - // initiate a charge time of 50ms (field on) then immediately start writing bits - // start by writing 0xBB (keyword) and 0xEB (password) - // then write 80 bits of data (or 64 bit data + 16 bit crc if you prefer) - // finally end with 0x0300 (write frame) - // all data is sent lsb first - // finish with 50ms programming time + // writing algorithm: + // a high bit consists of a field off for 1ms and field on for 1ms + // a low bit consists of a field off for 0.3ms and field on for 1.7ms + // initiate a charge time of 50ms (field on) then immediately start writing bits + // start by writing 0xBB (keyword) and 0xEB (password) + // then write 80 bits of data (or 64 bit data + 16 bit crc if you prefer) + // finally end with 0x0300 (write frame) + // all data is sent lsb first + // finish with 50ms programming time - // modulate antenna - HIGH(GPIO_SSC_DOUT); - WaitMS(50); // charge time + // modulate antenna + HIGH(GPIO_SSC_DOUT); + WaitMS(50); // charge time - WriteTIbyte(0xbb); // keyword - WriteTIbyte(0xeb); // password - WriteTIbyte( (idlo )&0xff ); - WriteTIbyte( (idlo>>8 )&0xff ); - WriteTIbyte( (idlo>>16)&0xff ); - WriteTIbyte( (idlo>>24)&0xff ); - WriteTIbyte( (idhi )&0xff ); - WriteTIbyte( (idhi>>8 )&0xff ); - WriteTIbyte( (idhi>>16)&0xff ); - WriteTIbyte( (idhi>>24)&0xff ); // data hi to lo - WriteTIbyte( (crc )&0xff ); // crc lo - WriteTIbyte( (crc>>8 )&0xff ); // crc hi - WriteTIbyte(0x00); // write frame lo - WriteTIbyte(0x03); // write frame hi - HIGH(GPIO_SSC_DOUT); - WaitMS(50); // programming time + WriteTIbyte(0xbb); // keyword + WriteTIbyte(0xeb); // password + WriteTIbyte( (idlo )&0xff ); + WriteTIbyte( (idlo>>8 )&0xff ); + WriteTIbyte( (idlo>>16)&0xff ); + WriteTIbyte( (idlo>>24)&0xff ); + WriteTIbyte( (idhi )&0xff ); + WriteTIbyte( (idhi>>8 )&0xff ); + WriteTIbyte( (idhi>>16)&0xff ); + WriteTIbyte( (idhi>>24)&0xff ); // data hi to lo + WriteTIbyte( (crc )&0xff ); // crc lo + WriteTIbyte( (crc>>8 )&0xff ); // crc hi + WriteTIbyte(0x00); // write frame lo + WriteTIbyte(0x03); // write frame hi + HIGH(GPIO_SSC_DOUT); + WaitMS(50); // programming time - LED_A_OFF(); + LED_A_OFF(); - // get TI tag data into the buffer - AcquireTiType(); + // get TI tag data into the buffer + AcquireTiType(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - DbpString("Now use `lf ti read` to check"); - StopTicks(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + DbpString("Now use `lf ti read` to check"); + StopTicks(); } // note: a call to FpgaDownloadAndGo(FPGA_BITSTREAM_LF) must be done before, but // this may destroy the bigbuf so be sure this is called before calling SimulateTagLowFrequencyEx void SimulateTagLowFrequencyEx(int period, int gap, int ledcontrol, int numcycles) { - // start us timer - StartTicks(); + // start us timer + StartTicks(); - //FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE ); - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); - WaitMS(20); + //FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT | FPGA_LF_EDGE_DETECT_TOGGLE_MODE ); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_EDGE_DETECT); + WaitMS(20); - int i = 0, x = 0; - uint8_t *buf = BigBuf_get_addr(); + int i = 0, x = 0; + uint8_t *buf = BigBuf_get_addr(); - // set frequency, get values from 'lf config' command - sample_config *sc = getSamplingConfig(); + // set frequency, get values from 'lf config' command + sample_config *sc = getSamplingConfig(); - if ( (sc->divisor == 1) || (sc->divisor < 0) || (sc->divisor > 255) ) - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz - else if (sc->divisor == 0) - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - else - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor); + if ( (sc->divisor == 1) || (sc->divisor < 0) || (sc->divisor > 255) ) + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz + else if (sc->divisor == 0) + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + else + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, sc->divisor); - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK; - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK; + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT | GPIO_SSC_CLK; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_ODR = GPIO_SSC_CLK; - uint8_t check = 1; + uint8_t check = 1; - for(;;) { + for(;;) { - if ( numcycles > -1 ) { - if ( x != numcycles ) { - ++x; - } else { - // exit without turning of field - return; - } - } + if ( numcycles > -1 ) { + if ( x != numcycles ) { + ++x; + } else { + // exit without turning of field + return; + } + } - if (ledcontrol) LED_D_ON(); + if (ledcontrol) LED_D_ON(); - // wait until SSC_CLK goes HIGH - // used as a simple detection of a reader field? - while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) { - WDT_HIT(); - if ( !check ) { - if ( usb_poll_validate_length() || BUTTON_PRESS() ) - goto OUT; - } - ++check; } + // wait until SSC_CLK goes HIGH + // used as a simple detection of a reader field? + while (!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)) { + WDT_HIT(); + if ( !check ) { + if ( usb_poll_validate_length() || BUTTON_PRESS() ) + goto OUT; + } + ++check; + } - if (buf[i]) - OPEN_COIL(); - else - SHORT_COIL(); + if (buf[i]) + OPEN_COIL(); + else + SHORT_COIL(); - //wait until SSC_CLK goes LOW - while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) { - WDT_HIT(); - if ( !check ) { - if ( usb_poll_validate_length() || BUTTON_PRESS() ) - goto OUT; - } - ++check; - } + //wait until SSC_CLK goes LOW + while (AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK) { + WDT_HIT(); + if ( !check ) { + if ( usb_poll_validate_length() || BUTTON_PRESS() ) + goto OUT; + } + ++check; + } - i++; - if (i == period) { - i = 0; - if (gap) { - SHORT_COIL(); - WaitUS(gap); - } - } + i++; + if (i == period) { + i = 0; + if (gap) { + SHORT_COIL(); + WaitUS(gap); + } + } - if (ledcontrol) LED_D_OFF(); - } + if (ledcontrol) LED_D_OFF(); + } OUT: - StopTicks(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LED_D_OFF(); + StopTicks(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_D_OFF(); } void SimulateTagLowFrequency(int period, int gap, int ledcontrol) { - SimulateTagLowFrequencyEx(period, gap, ledcontrol, -1); + SimulateTagLowFrequencyEx(period, gap, ledcontrol, -1); } @@ -671,680 +672,680 @@ void SimulateTagLowFrequencyBidir(int divisor, int t0) // also manchester, static void fc(int c, int *n) { - uint8_t *dest = BigBuf_get_addr(); - int idx; + uint8_t *dest = BigBuf_get_addr(); + int idx; - // for when we want an fc8 pattern every 4 logical bits - if (c == 0) { - dest[((*n)++)] = 1; - dest[((*n)++)] = 1; - dest[((*n)++)] = 1; - dest[((*n)++)] = 1; - dest[((*n)++)] = 0; - dest[((*n)++)] = 0; - dest[((*n)++)] = 0; - dest[((*n)++)] = 0; - } + // for when we want an fc8 pattern every 4 logical bits + if (c == 0) { + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + } - // an fc/8 encoded bit is a bit pattern of 11110000 x6 = 48 samples - if (c == 8) { - for (idx=0; idx < 6; idx++) { - dest[((*n)++)] = 1; - dest[((*n)++)] = 1; - dest[((*n)++)] = 1; - dest[((*n)++)] = 1; - dest[((*n)++)] = 0; - dest[((*n)++)] = 0; - dest[((*n)++)] = 0; - dest[((*n)++)] = 0; - } - } + // an fc/8 encoded bit is a bit pattern of 11110000 x6 = 48 samples + if (c == 8) { + for (idx=0; idx < 6; idx++) { + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + } + } - // an fc/10 encoded bit is a bit pattern of 1111100000 x5 = 50 samples - if (c == 10) { - for (idx = 0; idx < 5; idx++) { - dest[((*n)++)] = 1; - dest[((*n)++)] = 1; - dest[((*n)++)] = 1; - dest[((*n)++)] = 1; - dest[((*n)++)] = 1; - dest[((*n)++)] = 0; - dest[((*n)++)] = 0; - dest[((*n)++)] = 0; - dest[((*n)++)] = 0; - dest[((*n)++)] = 0; - } - } + // an fc/10 encoded bit is a bit pattern of 1111100000 x5 = 50 samples + if (c == 10) { + for (idx = 0; idx < 5; idx++) { + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 1; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + dest[((*n)++)] = 0; + } + } } // special start of frame marker containing invalid bit sequences // this one is focused on HID, with manchester encoding. static void fcSTT(int *n) { - fc(8, n); fc(8, n); // invalid - fc(8, n); fc(10, n); // logical 0 - fc(10, n); fc(10, n); // invalid - fc(8, n); fc(10, n); // logical 0 + fc(8, n); fc(8, n); // invalid + fc(8, n); fc(10, n); // logical 0 + fc(10, n); fc(10, n); // invalid + fc(8, n); fc(10, n); // logical 0 } // compose fc/X fc/Y waveform (FSKx) static void fcAll(uint8_t fc, int *n, uint8_t clock, uint16_t *modCnt) { - uint8_t *dest = BigBuf_get_addr(); - uint8_t halfFC = fc >> 1; - uint8_t wavesPerClock = clock/fc; - uint8_t mod = clock % fc; //modifier - uint8_t modAdj = fc/mod; //how often to apply modifier - bool modAdjOk = !(fc % mod); //if (fc % mod==0) modAdjOk = true; + uint8_t *dest = BigBuf_get_addr(); + uint8_t halfFC = fc >> 1; + uint8_t wavesPerClock = clock/fc; + uint8_t mod = clock % fc; //modifier + uint8_t modAdj = fc/mod; //how often to apply modifier + bool modAdjOk = !(fc % mod); //if (fc % mod==0) modAdjOk = true; - // loop through clock - step field clock - for (uint8_t idx=0; idx < wavesPerClock; idx++){ - // put 1/2 FC length 1's and 1/2 0's per field clock wave (to create the wave) - memset(dest + (*n), 0, fc - halfFC); //in case of odd number use extra here - memset(dest + (*n) + (fc - halfFC), 1, halfFC); - *n += fc; - } - if (mod > 0) (*modCnt)++; + // loop through clock - step field clock + for (uint8_t idx=0; idx < wavesPerClock; idx++){ + // put 1/2 FC length 1's and 1/2 0's per field clock wave (to create the wave) + memset(dest + (*n), 0, fc - halfFC); //in case of odd number use extra here + memset(dest + (*n) + (fc - halfFC), 1, halfFC); + *n += fc; + } + if (mod > 0) (*modCnt)++; - if ((mod > 0) && modAdjOk){ //fsk2 - if ((*modCnt % modAdj) == 0){ //if 4th 8 length wave in a rf/50 add extra 8 length wave - memset(dest + (*n), 0, fc - halfFC); - memset(dest + (*n) + ( fc - halfFC), 1, halfFC); - *n += fc; - } - } - if (mod > 0 && !modAdjOk){ //fsk1 - memset(dest + (*n), 0, mod - (mod >> 1)); - memset(dest + (*n) + (mod - (mod >> 1)), 1, mod >> 1); - *n += mod; - } + if ((mod > 0) && modAdjOk){ //fsk2 + if ((*modCnt % modAdj) == 0){ //if 4th 8 length wave in a rf/50 add extra 8 length wave + memset(dest + (*n), 0, fc - halfFC); + memset(dest + (*n) + ( fc - halfFC), 1, halfFC); + *n += fc; + } + } + if (mod > 0 && !modAdjOk){ //fsk1 + memset(dest + (*n), 0, mod - (mod >> 1)); + memset(dest + (*n) + (mod - (mod >> 1)), 1, mod >> 1); + *n += mod; + } } // prepare a waveform pattern in the buffer based on the ID given then // simulate a HID tag until the button is pressed void CmdHIDsimTAGEx( uint32_t hi, uint32_t lo, int ledcontrol, int numcycles) { - if (hi > 0xFFF) { - DbpString("[!] tags can only have 44 bits. - USE lf simfsk for larger tags"); - return; - } + if (hi > 0xFFF) { + DbpString("[!] tags can only have 44 bits. - USE lf simfsk for larger tags"); + return; + } - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - set_tracing(false); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + set_tracing(false); - int n = 0, i = 0; - /* - HID tag bitstream format - The tag contains a 44bit unique code. This is sent out MSB first in sets of 4 bits - A 1 bit is represented as 6 fc8 and 5 fc10 patterns (manchester 10) during 2 clock periods. (1bit = 1clock period) - A 0 bit is represented as 5 fc10 and 6 fc8 patterns (manchester 01) - A fc8 is inserted before every 4 bits - A special start of frame pattern is used consisting a0b0 where a and b are neither 0 - nor 1 bits, they are special patterns (a = set of 12 fc8 and b = set of 10 fc10) + int n = 0, i = 0; + /* + HID tag bitstream format + The tag contains a 44bit unique code. This is sent out MSB first in sets of 4 bits + A 1 bit is represented as 6 fc8 and 5 fc10 patterns (manchester 10) during 2 clock periods. (1bit = 1clock period) + A 0 bit is represented as 5 fc10 and 6 fc8 patterns (manchester 01) + A fc8 is inserted before every 4 bits + A special start of frame pattern is used consisting a0b0 where a and b are neither 0 + nor 1 bits, they are special patterns (a = set of 12 fc8 and b = set of 10 fc10) - FSK2a - bit 1 = fc10 - bit 0 = fc8 - */ + FSK2a + bit 1 = fc10 + bit 0 = fc8 + */ - fc(0, &n); + fc(0, &n); - // special start of frame marker containing invalid bit sequences - fcSTT(&n); + // special start of frame marker containing invalid bit sequences + fcSTT(&n); - // manchester encode bits 43 to 32 - for (i = 11; i >= 0; i--) { + // manchester encode bits 43 to 32 + for (i = 11; i >= 0; i--) { - if ((i % 4) == 3) fc(0, &n); + if ((i % 4) == 3) fc(0, &n); - if ((hi >> i) & 1) { - fc(10, &n); fc(8, &n); // low-high transition - } else { - fc(8, &n); fc(10, &n); // high-low transition - } - } + if ((hi >> i) & 1) { + fc(10, &n); fc(8, &n); // low-high transition + } else { + fc(8, &n); fc(10, &n); // high-low transition + } + } - // manchester encode bits 31 to 0 - for (i = 31; i >= 0; i--) { + // manchester encode bits 31 to 0 + for (i = 31; i >= 0; i--) { - if ((i % 4) == 3) fc(0, &n); + if ((i % 4) == 3) fc(0, &n); - if (( lo >> i ) & 1) { - fc(10, &n); fc(8, &n); // low-high transition - } else { - fc(8, &n); fc(10, &n); // high-low transition - } - } + if (( lo >> i ) & 1) { + fc(10, &n); fc(8, &n); // low-high transition + } else { + fc(8, &n); fc(10, &n); // high-low transition + } + } - if (ledcontrol) LED_A_ON(); - SimulateTagLowFrequencyEx(n, 0, ledcontrol, numcycles); - if (ledcontrol) LED_A_OFF(); + if (ledcontrol) LED_A_ON(); + SimulateTagLowFrequencyEx(n, 0, ledcontrol, numcycles); + if (ledcontrol) LED_A_OFF(); } void CmdHIDsimTAG( uint32_t hi, uint32_t lo, int ledcontrol) { - CmdHIDsimTAGEx( hi, lo, ledcontrol, -1); - DbpString("[!] simulation finished"); + CmdHIDsimTAGEx( hi, lo, ledcontrol, -1); + DbpString("[!] simulation finished"); } // prepare a waveform pattern in the buffer based on the ID given then // simulate a FSK tag until the button is pressed // arg1 contains fcHigh and fcLow, arg2 contains STT marker and clock void CmdFSKsimTAG(uint16_t arg1, uint16_t arg2, size_t size, uint8_t *bits) { - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - // free eventually allocated BigBuf memory - BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); - set_tracing(false); + // free eventually allocated BigBuf memory + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(false); - int ledcontrol = 1, n = 0, i = 0; - uint8_t fcHigh = arg1 >> 8; - uint8_t fcLow = arg1 & 0xFF; - uint16_t modCnt = 0; - uint8_t clk = arg2 & 0xFF; - uint8_t stt = (arg2 >> 8) & 1; + int ledcontrol = 1, n = 0, i = 0; + uint8_t fcHigh = arg1 >> 8; + uint8_t fcLow = arg1 & 0xFF; + uint16_t modCnt = 0; + uint8_t clk = arg2 & 0xFF; + uint8_t stt = (arg2 >> 8) & 1; - if ( stt ) { - //int fsktype = ( fcHigh == 8 && fcLow == 5) ? 1 : 2; - //fcSTT(&n); - } + if ( stt ) { + //int fsktype = ( fcHigh == 8 && fcLow == 5) ? 1 : 2; + //fcSTT(&n); + } - for (i=0; i> 8) & 0xFF; - uint8_t encoding = arg1 & 0xFF; - uint8_t separator = arg2 & 1; - uint8_t invert = (arg2 >> 8) & 1; + int ledcontrol = 1, n = 0, i = 0; + uint8_t clk = (arg1 >> 8) & 0xFF; + uint8_t encoding = arg1 & 0xFF; + uint8_t separator = arg2 & 1; + uint8_t invert = (arg2 >> 8) & 1; - if (encoding == 2){ //biphase - uint8_t phase = 0; - for (i=0; i> 8; - uint8_t carrier = arg1 & 0xFF; - uint8_t invert = arg2 & 0xFF; - uint8_t curPhase = 0; - for (i=0; i> 8; + uint8_t carrier = arg1 & 0xFF; + uint8_t invert = arg2 & 0xFF; + uint8_t curPhase = 0; + for (i=0; i 0 && lo > 0 && (size == 96 || size == 192)){ - // go over previously decoded manchester data and decode into usable tag ID - if (hi2 != 0){ //extra large HID tags 88/192 bits - Dbprintf("TAG ID: %x%08x%08x (%d)", - hi2, - hi, - lo, - (lo >> 1) & 0xFFFF - ); - } else { //standard HID tags 44/96 bits - uint8_t bitlen = 0; - uint32_t fc = 0; - uint32_t cardnum = 0; + if (idx > 0 && lo > 0 && (size == 96 || size == 192)){ + // go over previously decoded manchester data and decode into usable tag ID + if (hi2 != 0){ //extra large HID tags 88/192 bits + Dbprintf("TAG ID: %x%08x%08x (%d)", + hi2, + hi, + lo, + (lo >> 1) & 0xFFFF + ); + } else { //standard HID tags 44/96 bits + uint8_t bitlen = 0; + uint32_t fc = 0; + uint32_t cardnum = 0; - if (((hi >> 5) & 1) == 1){//if bit 38 is set then < 37 bit format is used - uint32_t lo2 = 0; - lo2=(((hi & 31) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit - uint8_t idx3 = 1; - while (lo2 > 1){ //find last bit set to 1 (format len bit) - lo2 >>= 1; - idx3++; - } - bitlen = idx3 + 19; - fc = 0; - cardnum = 0; - if (bitlen == 26){ - cardnum = (lo >> 1) & 0xFFFF; - fc = (lo >> 17) & 0xFF; - } - if (bitlen == 37){ - cardnum = (lo >> 1 ) & 0x7FFFF; - fc = ((hi & 0xF) << 12) | (lo >> 20); - } - if (bitlen == 34){ - cardnum = (lo >> 1) & 0xFFFF; - fc = ((hi & 1) << 15) | (lo >> 17); - } - if (bitlen == 35){ - cardnum = (lo >> 1) & 0xFFFFF; - fc = ((hi & 1) << 11)|(lo >> 21); - } - } - else { //if bit 38 is not set then 37 bit format is used - bitlen= 37; - fc = 0; - cardnum = 0; - if (bitlen == 37){ - cardnum = (lo >> 1) & 0x7FFFF; - fc = ((hi & 0xF) << 12) | (lo >> 20); - } - } - Dbprintf("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d", - hi, - lo, - (lo >> 1) & 0xFFFF, - bitlen, - fc, - cardnum - ); - } - if (findone){ - *high = hi; - *low = lo; - break; - } - // reset - } - hi2 = hi = lo = idx = 0; - } - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - DbpString("Stopped"); - if (ledcontrol) LED_A_OFF(); + if (((hi >> 5) & 1) == 1){//if bit 38 is set then < 37 bit format is used + uint32_t lo2 = 0; + lo2=(((hi & 31) << 12) | (lo>>20)); //get bits 21-37 to check for format len bit + uint8_t idx3 = 1; + while (lo2 > 1){ //find last bit set to 1 (format len bit) + lo2 >>= 1; + idx3++; + } + bitlen = idx3 + 19; + fc = 0; + cardnum = 0; + if (bitlen == 26){ + cardnum = (lo >> 1) & 0xFFFF; + fc = (lo >> 17) & 0xFF; + } + if (bitlen == 37){ + cardnum = (lo >> 1 ) & 0x7FFFF; + fc = ((hi & 0xF) << 12) | (lo >> 20); + } + if (bitlen == 34){ + cardnum = (lo >> 1) & 0xFFFF; + fc = ((hi & 1) << 15) | (lo >> 17); + } + if (bitlen == 35){ + cardnum = (lo >> 1) & 0xFFFFF; + fc = ((hi & 1) << 11)|(lo >> 21); + } + } + else { //if bit 38 is not set then 37 bit format is used + bitlen= 37; + fc = 0; + cardnum = 0; + if (bitlen == 37){ + cardnum = (lo >> 1) & 0x7FFFF; + fc = ((hi & 0xF) << 12) | (lo >> 20); + } + } + Dbprintf("TAG ID: %x%08x (%d) - Format Len: %dbit - FC: %d - Card: %d", + hi, + lo, + (lo >> 1) & 0xFFFF, + bitlen, + fc, + cardnum + ); + } + if (findone){ + *high = hi; + *low = lo; + break; + } + // reset + } + hi2 = hi = lo = idx = 0; + } + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + DbpString("Stopped"); + if (ledcontrol) LED_A_OFF(); } // loop to get raw HID waveform then FSK demodulate the TAG ID from it void CmdAWIDdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { - uint8_t *dest = BigBuf_get_addr(); + uint8_t *dest = BigBuf_get_addr(); - //big enough to catch 2 sequences of largest format - size_t size = 12800; //50 * 128 * 2; + //big enough to catch 2 sequences of largest format + size_t size = 12800; //50 * 128 * 2; - int idx = 0, dummyIdx = 0; + int idx = 0, dummyIdx = 0; - BigBuf_Clear_keep_EM(); + BigBuf_Clear_keep_EM(); - LFSetupFPGAForADC(95, true); + LFSetupFPGAForADC(95, true); - while (!BUTTON_PRESS() && !usb_poll_validate_length()) { + while (!BUTTON_PRESS() && !usb_poll_validate_length()) { - WDT_HIT(); - if (ledcontrol) LED_A_ON(); + WDT_HIT(); + if (ledcontrol) LED_A_ON(); - DoAcquisition_default(-1, true); - // FSK demodulator + DoAcquisition_default(-1, true); + // FSK demodulator - idx = detectAWID(dest, &size, &dummyIdx); + idx = detectAWID(dest, &size, &dummyIdx); - if (idx <= 0 || size != 96) continue; - // Index map - // 0 10 20 30 40 50 60 - // | | | | | | | - // 01234567 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 - to 96 - // ----------------------------------------------------------------------------- - // 00000001 000 1 110 1 101 1 011 1 101 1 010 0 000 1 000 1 010 0 001 0 110 1 100 0 000 1 000 1 - // premable bbb o bbb o bbw o fff o fff o ffc o ccc o ccc o ccc o ccc o ccc o wxx o xxx o xxx o - to 96 - // |---26 bit---| |-----117----||-------------142-------------| - // b = format bit len, o = odd parity of last 3 bits - // f = facility code, c = card number - // w = wiegand parity - // (26 bit format shown) + if (idx <= 0 || size != 96) continue; + // Index map + // 0 10 20 30 40 50 60 + // | | | | | | | + // 01234567 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 456 7 890 1 234 5 678 9 012 3 - to 96 + // ----------------------------------------------------------------------------- + // 00000001 000 1 110 1 101 1 011 1 101 1 010 0 000 1 000 1 010 0 001 0 110 1 100 0 000 1 000 1 + // premable bbb o bbb o bbw o fff o fff o ffc o ccc o ccc o ccc o ccc o ccc o wxx o xxx o xxx o - to 96 + // |---26 bit---| |-----117----||-------------142-------------| + // b = format bit len, o = odd parity of last 3 bits + // f = facility code, c = card number + // w = wiegand parity + // (26 bit format shown) - //get raw ID before removing parities - uint32_t rawLo = bytebits_to_byte(dest+idx+64, 32); - uint32_t rawHi = bytebits_to_byte(dest+idx+32, 32); - uint32_t rawHi2 = bytebits_to_byte(dest+idx, 32); + //get raw ID before removing parities + uint32_t rawLo = bytebits_to_byte(dest+idx+64, 32); + uint32_t rawHi = bytebits_to_byte(dest+idx+32, 32); + uint32_t rawHi2 = bytebits_to_byte(dest+idx, 32); - size = removeParity(dest, idx+8, 4, 1, 88); - if (size != 66) continue; - // ok valid card found! + size = removeParity(dest, idx+8, 4, 1, 88); + if (size != 66) continue; + // ok valid card found! - // Index map - // 0 10 20 30 40 50 60 - // | | | | | | | - // 01234567 8 90123456 7890123456789012 3 456789012345678901234567890123456 - // ----------------------------------------------------------------------------- - // 00011010 1 01110101 0000000010001110 1 000000000000000000000000000000000 - // bbbbbbbb w ffffffff cccccccccccccccc w xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx - // |26 bit| |-117--| |-----142------| - // b = format bit len, o = odd parity of last 3 bits - // f = facility code, c = card number - // w = wiegand parity - // (26 bit format shown) + // Index map + // 0 10 20 30 40 50 60 + // | | | | | | | + // 01234567 8 90123456 7890123456789012 3 456789012345678901234567890123456 + // ----------------------------------------------------------------------------- + // 00011010 1 01110101 0000000010001110 1 000000000000000000000000000000000 + // bbbbbbbb w ffffffff cccccccccccccccc w xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx + // |26 bit| |-117--| |-----142------| + // b = format bit len, o = odd parity of last 3 bits + // f = facility code, c = card number + // w = wiegand parity + // (26 bit format shown) - uint32_t fc = 0; - uint32_t cardnum = 0; - uint32_t code1 = 0; - uint32_t code2 = 0; - uint8_t fmtLen = bytebits_to_byte(dest, 8); - if (fmtLen == 26){ - fc = bytebits_to_byte(dest+9, 8); - cardnum = bytebits_to_byte(dest+17, 16); - code1 = bytebits_to_byte(dest+8, fmtLen); - Dbprintf("AWID Found - BitLength: %d, FC: %d, Card: %d - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi2, rawHi, rawLo); - } else { - cardnum = bytebits_to_byte(dest+8+(fmtLen-17), 16); - if (fmtLen > 32){ - code1 = bytebits_to_byte(dest+8, fmtLen-32); - code2 = bytebits_to_byte(dest+8+(fmtLen-32), 32); - Dbprintf("AWID Found - BitLength: %d -unknown BitLength- (%d) - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo); - } else{ - code1 = bytebits_to_byte(dest+8, fmtLen); - Dbprintf("AWID Found - BitLength: %d -unknown BitLength- (%d) - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo); - } - } - if (findone){ - if (ledcontrol) LED_A_OFF(); - *high = rawHi; - *low = rawLo; - break; - } - // reset - idx = 0; - WDT_HIT(); - } - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - DbpString("Stopped"); - if (ledcontrol) LED_A_OFF(); + uint32_t fc = 0; + uint32_t cardnum = 0; + uint32_t code1 = 0; + uint32_t code2 = 0; + uint8_t fmtLen = bytebits_to_byte(dest, 8); + if (fmtLen == 26){ + fc = bytebits_to_byte(dest+9, 8); + cardnum = bytebits_to_byte(dest+17, 16); + code1 = bytebits_to_byte(dest+8, fmtLen); + Dbprintf("AWID Found - BitLength: %d, FC: %d, Card: %d - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, fc, cardnum, code1, rawHi2, rawHi, rawLo); + } else { + cardnum = bytebits_to_byte(dest+8+(fmtLen-17), 16); + if (fmtLen > 32){ + code1 = bytebits_to_byte(dest+8, fmtLen-32); + code2 = bytebits_to_byte(dest+8+(fmtLen-32), 32); + Dbprintf("AWID Found - BitLength: %d -unknown BitLength- (%d) - Wiegand: %x%08x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, code2, rawHi2, rawHi, rawLo); + } else{ + code1 = bytebits_to_byte(dest+8, fmtLen); + Dbprintf("AWID Found - BitLength: %d -unknown BitLength- (%d) - Wiegand: %x, Raw: %08x%08x%08x", fmtLen, cardnum, code1, rawHi2, rawHi, rawLo); + } + } + if (findone){ + if (ledcontrol) LED_A_OFF(); + *high = rawHi; + *low = rawLo; + break; + } + // reset + idx = 0; + WDT_HIT(); + } + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + DbpString("Stopped"); + if (ledcontrol) LED_A_OFF(); } void CmdEM410xdemod(int findone, uint32_t *high, uint64_t *low, int ledcontrol) { - uint8_t *dest = BigBuf_get_addr(); + uint8_t *dest = BigBuf_get_addr(); - size_t size = 0, idx = 0; - int clk = 0, invert = 0, errCnt = 0, maxErr = 20; - uint32_t hi = 0; - uint64_t lo = 0; + size_t size = 0, idx = 0; + int clk = 0, invert = 0, errCnt = 0, maxErr = 20; + uint32_t hi = 0; + uint64_t lo = 0; - BigBuf_Clear_keep_EM(); + BigBuf_Clear_keep_EM(); - LFSetupFPGAForADC(95, true); + LFSetupFPGAForADC(95, true); - while(!BUTTON_PRESS() && !usb_poll_validate_length()) { + while(!BUTTON_PRESS() && !usb_poll_validate_length()) { - WDT_HIT(); - if (ledcontrol) LED_A_ON(); + WDT_HIT(); + if (ledcontrol) LED_A_ON(); - DoAcquisition_default(-1, true); + DoAcquisition_default(-1, true); - size = BigBuf_max_traceLen(); - //askdemod and manchester decode - if (size > 16385) size = 16385; //big enough to catch 2 sequences of largest format - errCnt = askdemod(dest, &size, &clk, &invert, maxErr, 0, 1); - WDT_HIT(); + size = BigBuf_max_traceLen(); + //askdemod and manchester decode + if (size > 16385) size = 16385; //big enough to catch 2 sequences of largest format + errCnt = askdemod(dest, &size, &clk, &invert, maxErr, 0, 1); + WDT_HIT(); - if (errCnt < 0) continue; + if (errCnt < 0) continue; - errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo); - if (errCnt == 1){ - if (size == 128){ - Dbprintf("EM XL TAG ID: %06x%08x%08x - (%05d_%03d_%08d)", - hi, - (uint32_t)(lo >> 32), - (uint32_t)lo, - (uint32_t)(lo & 0xFFFF), - (uint32_t)((lo >> 16LL) & 0xFF), - (uint32_t)(lo & 0xFFFFFF)); - } else { - Dbprintf("EM TAG ID: %02x%08x - (%05d_%03d_%08d)", - (uint32_t)(lo >> 32), - (uint32_t)lo, - (uint32_t)(lo & 0xFFFF), - (uint32_t)((lo >> 16LL) & 0xFF), - (uint32_t)(lo & 0xFFFFFF)); - } + errCnt = Em410xDecode(dest, &size, &idx, &hi, &lo); + if (errCnt == 1){ + if (size == 128){ + Dbprintf("EM XL TAG ID: %06x%08x%08x - (%05d_%03d_%08d)", + hi, + (uint32_t)(lo >> 32), + (uint32_t)lo, + (uint32_t)(lo & 0xFFFF), + (uint32_t)((lo >> 16LL) & 0xFF), + (uint32_t)(lo & 0xFFFFFF)); + } else { + Dbprintf("EM TAG ID: %02x%08x - (%05d_%03d_%08d)", + (uint32_t)(lo >> 32), + (uint32_t)lo, + (uint32_t)(lo & 0xFFFF), + (uint32_t)((lo >> 16LL) & 0xFF), + (uint32_t)(lo & 0xFFFFFF)); + } - if (findone){ - if (ledcontrol) LED_A_OFF(); - *high = hi; - *low = lo; - break; - } - } - WDT_HIT(); - hi = lo = size = idx = 0; - clk = invert = errCnt = 0; - } - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - DbpString("Stopped"); - if (ledcontrol) LED_A_OFF(); + if (findone){ + if (ledcontrol) LED_A_OFF(); + *high = hi; + *low = lo; + break; + } + } + WDT_HIT(); + hi = lo = size = idx = 0; + clk = invert = errCnt = 0; + } + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + DbpString("Stopped"); + if (ledcontrol) LED_A_OFF(); } void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { - uint8_t *dest = BigBuf_get_addr(); + uint8_t *dest = BigBuf_get_addr(); - int dummyIdx = 0, idx = 0; - uint32_t code = 0, code2 = 0; - uint8_t version = 0, facilitycode = 0, crc = 0; - uint16_t number = 0, calccrc = 0; + int dummyIdx = 0, idx = 0; + uint32_t code = 0, code2 = 0; + uint8_t version = 0, facilitycode = 0, crc = 0; + uint16_t number = 0, calccrc = 0; - size_t size = BigBuf_max_traceLen(); + size_t size = BigBuf_max_traceLen(); - BigBuf_Clear_keep_EM(); + BigBuf_Clear_keep_EM(); - // Configure to go in 125Khz listen mode - LFSetupFPGAForADC(95, true); + // Configure to go in 125Khz listen mode + LFSetupFPGAForADC(95, true); - while (!BUTTON_PRESS() && !usb_poll_validate_length()) { - WDT_HIT(); - if (ledcontrol) LED_A_ON(); + while (!BUTTON_PRESS() && !usb_poll_validate_length()) { + WDT_HIT(); + if (ledcontrol) LED_A_ON(); - DoAcquisition_default(-1, true); + DoAcquisition_default(-1, true); - //fskdemod and get start index - WDT_HIT(); - idx = detectIOProx(dest, &size, &dummyIdx); - if (idx < 0) continue; - //valid tag found + //fskdemod and get start index + WDT_HIT(); + idx = detectIOProx(dest, &size, &dummyIdx); + if (idx < 0) continue; + //valid tag found - //Index map - //0 10 20 30 40 50 60 - //| | | | | | | - //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23 - //----------------------------------------------------------------------------- + //Index map + //0 10 20 30 40 50 60 + //| | | | | | | + //01234567 8 90123456 7 89012345 6 78901234 5 67890123 4 56789012 3 45678901 23 + //----------------------------------------------------------------------------- //00000000 0 11110000 1 facility 1 version* 1 code*one 1 code*two 1 checksum 11 - // - //Checksum: - //00000000 0 11110000 1 11100000 1 00000001 1 00000011 1 10110110 1 01110101 11 - //preamble F0 E0 01 03 B6 75 - // How to calc checksum, - // http://www.proxmark.org/forum/viewtopic.php?id=364&p=6 - // F0 + E0 + 01 + 03 + B6 = 28A - // 28A & FF = 8A - // FF - 8A = 75 - // Checksum: 0x75 - //XSF(version)facility:codeone+codetwo - //Handle the data - // if(findone){ //only print binary if we are doing one - // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx], dest[idx+1], dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7],dest[idx+8]); - // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15],dest[idx+16],dest[idx+17]); - // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23],dest[idx+24],dest[idx+25],dest[idx+26]); - // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31],dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35]); - // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39],dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44]); - // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+45],dest[idx+46],dest[idx+47],dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53]); - // Dbprintf("%d%d%d%d%d%d%d%d %d%d",dest[idx+54],dest[idx+55],dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]); - // } - code = bytebits_to_byte(dest+idx, 32); - code2 = bytebits_to_byte(dest+idx+32, 32); - version = bytebits_to_byte(dest+idx+27, 8); //14,4 - facilitycode = bytebits_to_byte(dest+idx+18, 8); - number = (bytebits_to_byte(dest+idx+36, 8) << 8) | (bytebits_to_byte(dest+idx+45, 8)); //36,9 + // + //Checksum: + //00000000 0 11110000 1 11100000 1 00000001 1 00000011 1 10110110 1 01110101 11 + //preamble F0 E0 01 03 B6 75 + // How to calc checksum, + // http://www.proxmark.org/forum/viewtopic.php?id=364&p=6 + // F0 + E0 + 01 + 03 + B6 = 28A + // 28A & FF = 8A + // FF - 8A = 75 + // Checksum: 0x75 + //XSF(version)facility:codeone+codetwo + //Handle the data + // if(findone){ //only print binary if we are doing one + // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx], dest[idx+1], dest[idx+2],dest[idx+3],dest[idx+4],dest[idx+5],dest[idx+6],dest[idx+7],dest[idx+8]); + // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+9], dest[idx+10],dest[idx+11],dest[idx+12],dest[idx+13],dest[idx+14],dest[idx+15],dest[idx+16],dest[idx+17]); + // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+18],dest[idx+19],dest[idx+20],dest[idx+21],dest[idx+22],dest[idx+23],dest[idx+24],dest[idx+25],dest[idx+26]); + // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+27],dest[idx+28],dest[idx+29],dest[idx+30],dest[idx+31],dest[idx+32],dest[idx+33],dest[idx+34],dest[idx+35]); + // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+36],dest[idx+37],dest[idx+38],dest[idx+39],dest[idx+40],dest[idx+41],dest[idx+42],dest[idx+43],dest[idx+44]); + // Dbprintf("%d%d%d%d%d%d%d%d %d",dest[idx+45],dest[idx+46],dest[idx+47],dest[idx+48],dest[idx+49],dest[idx+50],dest[idx+51],dest[idx+52],dest[idx+53]); + // Dbprintf("%d%d%d%d%d%d%d%d %d%d",dest[idx+54],dest[idx+55],dest[idx+56],dest[idx+57],dest[idx+58],dest[idx+59],dest[idx+60],dest[idx+61],dest[idx+62],dest[idx+63]); + // } + code = bytebits_to_byte(dest+idx, 32); + code2 = bytebits_to_byte(dest+idx+32, 32); + version = bytebits_to_byte(dest+idx+27, 8); //14,4 + facilitycode = bytebits_to_byte(dest+idx+18, 8); + number = (bytebits_to_byte(dest+idx+36, 8) << 8) | (bytebits_to_byte(dest+idx+45, 8)); //36,9 - crc = bytebits_to_byte(dest+idx+54, 8); - for (uint8_t i=1; i<6; ++i) - calccrc += bytebits_to_byte(dest+idx+9*i, 8); - calccrc &= 0xff; - calccrc = 0xff - calccrc; + crc = bytebits_to_byte(dest+idx+54, 8); + for (uint8_t i=1; i<6; ++i) + calccrc += bytebits_to_byte(dest+idx+9*i, 8); + calccrc &= 0xff; + calccrc = 0xff - calccrc; - char *crcStr = (crc == calccrc) ? "ok" : "!crc"; + char *crcStr = (crc == calccrc) ? "ok" : "!crc"; Dbprintf("IO Prox XSF(%02d)%02x:%05d (%08x%08x) [%02x %s]", version, facilitycode, number, code, code2, crc, crcStr); - // if we're only looking for one tag - if (findone){ - if (ledcontrol) LED_A_OFF(); - *high = code; - *low = code2; - break; - } - code = code2 = 0; - version = facilitycode = 0; - number = 0; - idx = 0; + // if we're only looking for one tag + if (findone){ + if (ledcontrol) LED_A_OFF(); + *high = code; + *low = code2; + break; + } + code = code2 = 0; + version = facilitycode = 0; + number = 0; + idx = 0; - WDT_HIT(); - } - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - DbpString("Stopped"); - if (ledcontrol) LED_A_OFF(); + WDT_HIT(); + } + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + DbpString("Stopped"); + if (ledcontrol) LED_A_OFF(); } /*------------------------------ @@ -1359,521 +1360,521 @@ void CmdIOdemodFSK(int findone, uint32_t *high, uint32_t *low, int ledcontrol) { */ void TurnReadLFOn(uint32_t delay) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); - // measure antenna strength. - //int adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10); - WaitUS(delay); + // measure antenna strength. + //int adcval = ((MAX_ADC_LF_VOLTAGE * AvgAdc(ADC_CHAN_LF)) >> 10); + WaitUS(delay); } void TurnReadLF_off(uint32_t delay) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(delay); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + WaitUS(delay); } // Write one bit to card void T55xxWriteBit(int bit) { - if (!bit) - TurnReadLFOn(t_config.write_0); - else - TurnReadLFOn(t_config.write_1); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(t_config.write_gap); + if (!bit) + TurnReadLFOn(t_config.write_0); + else + TurnReadLFOn(t_config.write_1); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + WaitUS(t_config.write_gap); } // Send T5577 reset command then read stream (see if we can identify the start of the stream) void T55xxResetRead(void) { - LED_A_ON(); - //clear buffer now so it does not interfere with timing later - BigBuf_Clear_keep_EM(); + LED_A_ON(); + //clear buffer now so it does not interfere with timing later + BigBuf_Clear_keep_EM(); - StartTicks(); + StartTicks(); - // Set up FPGA, 125kHz - LFSetupFPGAForADC(95, true); - // make sure tag is fully powered up... - WaitMS(4); + // Set up FPGA, 125kHz + LFSetupFPGAForADC(95, true); + // make sure tag is fully powered up... + WaitMS(4); - // Trigger T55x7 in mode. - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(t_config.start_gap); + // Trigger T55x7 in mode. + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + WaitUS(t_config.start_gap); - // reset tag - op code 00 - T55xxWriteBit(0); - T55xxWriteBit(0); + // reset tag - op code 00 + T55xxWriteBit(0); + T55xxWriteBit(0); - TurnReadLFOn(t_config.read_gap); + TurnReadLFOn(t_config.read_gap); - // Acquisition - DoPartialAcquisition(0, true, BigBuf_max_traceLen(), 0); + // Acquisition + DoPartialAcquisition(0, true, BigBuf_max_traceLen(), 0); - // Turn the field off - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off - cmd_send(CMD_ACK,0,0,0,0,0); - LED_A_OFF(); + // Turn the field off + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off + cmd_send(CMD_ACK,0,0,0,0,0); + LED_A_OFF(); } // Write one card block in page 0, no lock void T55xxWriteBlockExt(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) { - LED_A_ON(); - bool PwdMode = arg & 0x1; - uint8_t Page = (arg & 0x2)>>1; - bool testMode = arg & 0x4; - uint32_t i = 0; + LED_A_ON(); + bool PwdMode = arg & 0x1; + uint8_t Page = (arg & 0x2)>>1; + bool testMode = arg & 0x4; + uint32_t i = 0; - StartTicks(); + StartTicks(); - // Set up FPGA, 125kHz - LFSetupFPGAForADC(95, true); + // Set up FPGA, 125kHz + LFSetupFPGAForADC(95, true); - // make sure tag is fully powered up... - WaitMS(4); - // Trigger T55x7 in mode. - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(t_config.start_gap); + // make sure tag is fully powered up... + WaitMS(4); + // Trigger T55x7 in mode. + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + WaitUS(t_config.start_gap); - if (testMode) Dbprintf("TestMODE"); - // Std Opcode 10 - T55xxWriteBit(testMode ? 0 : 1); - T55xxWriteBit(testMode ? 1 : Page); //Page 0 + if (testMode) Dbprintf("TestMODE"); + // Std Opcode 10 + T55xxWriteBit(testMode ? 0 : 1); + T55xxWriteBit(testMode ? 1 : Page); //Page 0 - if (PwdMode){ - // Send Pwd - for (i = 0x80000000; i != 0; i >>= 1) - T55xxWriteBit(Pwd & i); - } - // Send Lock bit - T55xxWriteBit(0); + if (PwdMode){ + // Send Pwd + for (i = 0x80000000; i != 0; i >>= 1) + T55xxWriteBit(Pwd & i); + } + // Send Lock bit + T55xxWriteBit(0); - // Send Data - for (i = 0x80000000; i != 0; i >>= 1) - T55xxWriteBit(Data & i); + // Send Data + for (i = 0x80000000; i != 0; i >>= 1) + T55xxWriteBit(Data & i); - // Send Block number - for (i = 0x04; i != 0; i >>= 1) - T55xxWriteBit(Block & i); + // Send Block number + for (i = 0x04; i != 0; i >>= 1) + T55xxWriteBit(Block & i); - // Perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550, - // so wait a little more) + // Perform write (nominal is 5.6 ms for T55x7 and 18ms for E5550, + // so wait a little more) - // "there is a clock delay before programming" - // - programming takes ~5.6ms for t5577 ~18ms for E5550 or t5567 - // so we should wait 1 clock + 5.6ms then read response? - // but we need to know we are dealing with t5577 vs t5567 vs e5550 (or q5) marshmellow... - if (testMode) { - //TESTMODE TIMING TESTS: - // <566us does nothing - // 566-568 switches between wiping to 0s and doing nothing - // 5184 wipes and allows 1 block to be programmed. - // indefinite power on wipes and then programs all blocks with bitshifted data sent. - TurnReadLFOn(5184); + // "there is a clock delay before programming" + // - programming takes ~5.6ms for t5577 ~18ms for E5550 or t5567 + // so we should wait 1 clock + 5.6ms then read response? + // but we need to know we are dealing with t5577 vs t5567 vs e5550 (or q5) marshmellow... + if (testMode) { + //TESTMODE TIMING TESTS: + // <566us does nothing + // 566-568 switches between wiping to 0s and doing nothing + // 5184 wipes and allows 1 block to be programmed. + // indefinite power on wipes and then programs all blocks with bitshifted data sent. + TurnReadLFOn(5184); - } else { - TurnReadLFOn(20 * 1000); + } else { + TurnReadLFOn(20 * 1000); - //could attempt to do a read to confirm write took - // as the tag should repeat back the new block - // until it is reset, but to confirm it we would - // need to know the current block 0 config mode for - // modulation clock an other details to demod the response... - // response should be (for t55x7) a 0 bit then (ST if on) - // block data written in on repeat until reset. + //could attempt to do a read to confirm write took + // as the tag should repeat back the new block + // until it is reset, but to confirm it we would + // need to know the current block 0 config mode for + // modulation clock an other details to demod the response... + // response should be (for t55x7) a 0 bit then (ST if on) + // block data written in on repeat until reset. - //DoPartialAcquisition(20, true, 12000); - } + //DoPartialAcquisition(20, true, 12000); + } - // turn field off - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LED_A_OFF(); + // turn field off + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LED_A_OFF(); } // Write one card block in page 0, no lock void T55xxWriteBlock(uint32_t Data, uint8_t Block, uint32_t Pwd, uint8_t arg) { - T55xxWriteBlockExt(Data, Block, Pwd, arg); - cmd_send(CMD_ACK,0,0,0,0,0); + T55xxWriteBlockExt(Data, Block, Pwd, arg); + cmd_send(CMD_ACK,0,0,0,0,0); } // Read one card block in page [page] void T55xxReadBlock(uint16_t arg0, uint8_t Block, uint32_t Pwd) { - LED_A_ON(); - bool PwdMode = arg0 & 0x1; - uint8_t Page = ( arg0 & 0x2 ) >> 1; - bool brute_mem = arg0 & 0x4; + LED_A_ON(); + bool PwdMode = arg0 & 0x1; + uint8_t Page = ( arg0 & 0x2 ) >> 1; + bool brute_mem = arg0 & 0x4; - uint32_t i = 0; + uint32_t i = 0; - // regular read mode - bool RegReadMode = (Block == 0xFF); + // regular read mode + bool RegReadMode = (Block == 0xFF); - uint8_t start_wait = 4; - size_t samples = 12000; - if ( brute_mem ) { - start_wait = 0; - samples = 1024; - } + uint8_t start_wait = 4; + size_t samples = 12000; + if ( brute_mem ) { + start_wait = 0; + samples = 1024; + } - //clear buffer now so it does not interfere with timing later - BigBuf_Clear_keep_EM(); + //clear buffer now so it does not interfere with timing later + BigBuf_Clear_keep_EM(); - //make sure block is at max 7 - Block &= 0x7; + //make sure block is at max 7 + Block &= 0x7; - StartTicks(); + StartTicks(); - // Set up FPGA, 125kHz to power up the tag - LFSetupFPGAForADC(95, true); - // make sure tag is fully powered up... - WaitMS(start_wait); + // Set up FPGA, 125kHz to power up the tag + LFSetupFPGAForADC(95, true); + // make sure tag is fully powered up... + WaitMS(start_wait); - // Trigger T55x7 Direct Access Mode with start gap - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(t_config.start_gap); + // Trigger T55x7 Direct Access Mode with start gap + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + WaitUS(t_config.start_gap); - // Opcode 1[page] - T55xxWriteBit(1); - T55xxWriteBit(Page); //Page 0 + // Opcode 1[page] + T55xxWriteBit(1); + T55xxWriteBit(Page); //Page 0 - if (PwdMode){ - // Send Pwd - for (i = 0x80000000; i != 0; i >>= 1) - T55xxWriteBit(Pwd & i); - } - // Send a zero bit separation - T55xxWriteBit(0); + if (PwdMode){ + // Send Pwd + for (i = 0x80000000; i != 0; i >>= 1) + T55xxWriteBit(Pwd & i); + } + // Send a zero bit separation + T55xxWriteBit(0); - // Send Block number (if direct access mode) - if (!RegReadMode) - for (i = 0x04; i != 0; i >>= 1) - T55xxWriteBit(Block & i); + // Send Block number (if direct access mode) + if (!RegReadMode) + for (i = 0x04; i != 0; i >>= 1) + T55xxWriteBit(Block & i); - // Turn field on to read the response - // 137*8 seems to get to the start of data pretty well... - // but we want to go past the start and let the repeating data settle in... - TurnReadLFOn(200*8); + // Turn field on to read the response + // 137*8 seems to get to the start of data pretty well... + // but we want to go past the start and let the repeating data settle in... + TurnReadLFOn(200*8); - // Acquisition - // Now do the acquisition - DoPartialAcquisition(0, true, samples, 0); + // Acquisition + // Now do the acquisition + DoPartialAcquisition(0, true, samples, 0); - // Turn the field off - if ( !brute_mem ) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - cmd_send(CMD_ACK,0,0,0,0,0); - LED_A_OFF(); - } + // Turn the field off + if ( !brute_mem ) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + cmd_send(CMD_ACK,0,0,0,0,0); + LED_A_OFF(); + } } void T55xx_ChkPwds() { - DbpString("[+] T55XX Check pwds using flashmemory starting"); + DbpString("[+] T55XX Check pwds using flashmemory starting"); - uint8_t ret = 0; - // First get baseline and setup LF mode. - // tends to mess up BigBuf - uint8_t *buf = BigBuf_get_addr(); + uint8_t ret = 0; + // First get baseline and setup LF mode. + // tends to mess up BigBuf + uint8_t *buf = BigBuf_get_addr(); - uint32_t b1, baseline = 0; + uint32_t b1, baseline = 0; - // collect baseline for failed attempt - uint8_t x = 32; - while (x--) { - b1 = 0; - T55xxReadBlock(4, 1, 0); - for (uint16_t j=0; j < 1024; ++j) - b1 += buf[j]; + // collect baseline for failed attempt + uint8_t x = 32; + while (x--) { + b1 = 0; + T55xxReadBlock(4, 1, 0); + for (uint16_t j=0; j < 1024; ++j) + b1 += buf[j]; - b1 *= b1; - b1 >>= 8; - baseline += b1; - } + b1 *= b1; + b1 >>= 8; + baseline += b1; + } - baseline >>= 5; - Dbprintf("[=] Baseline determined [%u]", baseline); + baseline >>= 5; + Dbprintf("[=] Baseline determined [%u]", baseline); - uint8_t *pwds = BigBuf_get_EM_addr(); - uint16_t pwdCount = 0; - uint32_t candidate = 0; + uint8_t *pwds = BigBuf_get_EM_addr(); + uint16_t pwdCount = 0; + uint32_t candidate = 0; #ifdef WITH_FLASH - bool use_flashmem = true; - if ( use_flashmem ) { - BigBuf_Clear_EM(); - uint16_t isok = 0; - uint8_t counter[2] = {0x00, 0x00}; - isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET, counter, sizeof(counter) ); - if ( isok != sizeof(counter) ) - goto OUT; + bool use_flashmem = true; + if ( use_flashmem ) { + BigBuf_Clear_EM(); + uint16_t isok = 0; + uint8_t counter[2] = {0x00, 0x00}; + isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET, counter, sizeof(counter) ); + if ( isok != sizeof(counter) ) + goto OUT; - pwdCount = counter[1] << 8 | counter[0]; + pwdCount = counter[1] << 8 | counter[0]; - if ( pwdCount == 0 && pwdCount == 0xFFFF) - goto OUT; + if ( pwdCount == 0 && pwdCount == 0xFFFF) + goto OUT; - isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET+2, pwds, pwdCount * 4); - if ( isok != pwdCount * 4 ) - goto OUT; + isok = Flash_ReadData(DEFAULT_T55XX_KEYS_OFFSET+2, pwds, pwdCount * 4); + if ( isok != pwdCount * 4 ) + goto OUT; - Dbprintf("[=] Password dictionary count %d ", pwdCount); - } + Dbprintf("[=] Password dictionary count %d ", pwdCount); + } #endif - uint32_t pwd = 0, curr = 0, prev = 0; - for (uint16_t i =0; i< pwdCount; ++i) { + uint32_t pwd = 0, curr = 0, prev = 0; + for (uint16_t i =0; i< pwdCount; ++i) { - if (BUTTON_PRESS() && !usb_poll_validate_length()) { - goto OUT; - } + if (BUTTON_PRESS() && !usb_poll_validate_length()) { + goto OUT; + } - pwd = bytes_to_num(pwds + i * 4, 4); + pwd = bytes_to_num(pwds + i * 4, 4); - T55xxReadBlock(5, 0, pwd); + T55xxReadBlock(5, 0, pwd); - // calc mean of BigBuf 1024 samples. - uint32_t sum = 0; - for (uint16_t j=0; j<1024; ++j) { - sum += buf[j]; - } + // calc mean of BigBuf 1024 samples. + uint32_t sum = 0; + for (uint16_t j=0; j<1024; ++j) { + sum += buf[j]; + } - sum *= sum; - sum >>= 8; + sum *= sum; + sum >>= 8; - int32_t tmp = (sum - baseline); - curr = ABS(tmp); + int32_t tmp = (sum - baseline); + curr = ABS(tmp); - Dbprintf("[=] Pwd %08X | ABS %u", pwd, curr ); + Dbprintf("[=] Pwd %08X | ABS %u", pwd, curr ); - if ( curr > prev ) { + if ( curr > prev ) { - Dbprintf("[=] --> ABS %u Candidate %08X <--", curr, pwd ); - candidate = pwd; - prev = curr; - } - } + Dbprintf("[=] --> ABS %u Candidate %08X <--", curr, pwd ); + candidate = pwd; + prev = curr; + } + } - if ( candidate ) - ret = 1; + if ( candidate ) + ret = 1; OUT: - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - cmd_send(CMD_ACK,ret,candidate,0,0,0); - LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + cmd_send(CMD_ACK,ret,candidate,0,0,0); + LEDsoff(); } void T55xxWakeUp(uint32_t Pwd){ - LED_B_ON(); - uint32_t i = 0; + LED_B_ON(); + uint32_t i = 0; - StartTicks(); + StartTicks(); - // Set up FPGA, 125kHz - LFSetupFPGAForADC(95, true); - // make sure tag is fully powered up... - WaitMS(4); + // Set up FPGA, 125kHz + LFSetupFPGAForADC(95, true); + // make sure tag is fully powered up... + WaitMS(4); - // Trigger T55x7 Direct Access Mode - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - WaitUS(t_config.start_gap); + // Trigger T55x7 Direct Access Mode + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + WaitUS(t_config.start_gap); - // Opcode 10 - T55xxWriteBit(1); - T55xxWriteBit(0); //Page 0 + // Opcode 10 + T55xxWriteBit(1); + T55xxWriteBit(0); //Page 0 - // Send Pwd - for (i = 0x80000000; i != 0; i >>= 1) - T55xxWriteBit(Pwd & i); + // Send Pwd + for (i = 0x80000000; i != 0; i >>= 1) + T55xxWriteBit(Pwd & i); - // Turn and leave field on to let the begin repeating transmission - TurnReadLFOn(20*1000); + // Turn and leave field on to let the begin repeating transmission + TurnReadLFOn(20*1000); } /*-------------- Cloning routines -----------*/ void WriteT55xx(uint32_t *blockdata, uint8_t startblock, uint8_t numblocks) { - // write last block first and config block last (if included) - for (uint8_t i = numblocks+startblock; i > startblock; i--) - T55xxWriteBlockExt(blockdata[i-1], i-1, 0, 0); + // write last block first and config block last (if included) + for (uint8_t i = numblocks+startblock; i > startblock; i--) + T55xxWriteBlockExt(blockdata[i-1], i-1, 0, 0); } // Copy HID id to card and setup block 0 config void CopyHIDtoT55x7(uint32_t hi2, uint32_t hi, uint32_t lo, uint8_t longFMT) { - uint32_t data[] = {0,0,0,0,0,0,0}; - uint8_t last_block = 0; + uint32_t data[] = {0,0,0,0,0,0,0}; + uint8_t last_block = 0; - if (longFMT){ - // Ensure no more than 84 bits supplied - if (hi2 > 0xFFFFF) { - DbpString("Tags can only have 84 bits."); - return; - } - // Build the 6 data blocks for supplied 84bit ID - last_block = 6; - // load preamble (1D) & long format identifier (9E manchester encoded) - data[1] = 0x1D96A900 | (manchesterEncode2Bytes((hi2 >> 16) & 0xF) & 0xFF); - // load raw id from hi2, hi, lo to data blocks (manchester encoded) - data[2] = manchesterEncode2Bytes(hi2 & 0xFFFF); - data[3] = manchesterEncode2Bytes(hi >> 16); - data[4] = manchesterEncode2Bytes(hi & 0xFFFF); - data[5] = manchesterEncode2Bytes(lo >> 16); - data[6] = manchesterEncode2Bytes(lo & 0xFFFF); - } else { - // Ensure no more than 44 bits supplied - if (hi > 0xFFF) { - DbpString("Tags can only have 44 bits."); - return; - } - // Build the 3 data blocks for supplied 44bit ID - last_block = 3; - // load preamble - data[1] = 0x1D000000 | (manchesterEncode2Bytes(hi) & 0xFFFFFF); - data[2] = manchesterEncode2Bytes(lo >> 16); - data[3] = manchesterEncode2Bytes(lo & 0xFFFF); - } - // load chip config block - data[0] = T55x7_BITRATE_RF_50 | T55x7_MODULATION_FSK2a | last_block << T55x7_MAXBLOCK_SHIFT; + if (longFMT){ + // Ensure no more than 84 bits supplied + if (hi2 > 0xFFFFF) { + DbpString("Tags can only have 84 bits."); + return; + } + // Build the 6 data blocks for supplied 84bit ID + last_block = 6; + // load preamble (1D) & long format identifier (9E manchester encoded) + data[1] = 0x1D96A900 | (manchesterEncode2Bytes((hi2 >> 16) & 0xF) & 0xFF); + // load raw id from hi2, hi, lo to data blocks (manchester encoded) + data[2] = manchesterEncode2Bytes(hi2 & 0xFFFF); + data[3] = manchesterEncode2Bytes(hi >> 16); + data[4] = manchesterEncode2Bytes(hi & 0xFFFF); + data[5] = manchesterEncode2Bytes(lo >> 16); + data[6] = manchesterEncode2Bytes(lo & 0xFFFF); + } else { + // Ensure no more than 44 bits supplied + if (hi > 0xFFF) { + DbpString("Tags can only have 44 bits."); + return; + } + // Build the 3 data blocks for supplied 44bit ID + last_block = 3; + // load preamble + data[1] = 0x1D000000 | (manchesterEncode2Bytes(hi) & 0xFFFFFF); + data[2] = manchesterEncode2Bytes(lo >> 16); + data[3] = manchesterEncode2Bytes(lo & 0xFFFF); + } + // load chip config block + data[0] = T55x7_BITRATE_RF_50 | T55x7_MODULATION_FSK2a | last_block << T55x7_MAXBLOCK_SHIFT; - //TODO add selection of chip for Q5 or T55x7 - // data[0] = T5555_SET_BITRATE(50) | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | last_block << T5555_MAXBLOCK_SHIFT; + //TODO add selection of chip for Q5 or T55x7 + // data[0] = T5555_SET_BITRATE(50) | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | last_block << T5555_MAXBLOCK_SHIFT; - LED_D_ON(); - WriteT55xx(data, 0, last_block+1); - LED_D_OFF(); + LED_D_ON(); + WriteT55xx(data, 0, last_block+1); + LED_D_OFF(); } void CopyIOtoT55x7(uint32_t hi, uint32_t lo) { - uint32_t data[] = {T55x7_BITRATE_RF_64 | T55x7_MODULATION_FSK2a | (2 << T55x7_MAXBLOCK_SHIFT), hi, lo}; - //TODO add selection of chip for Q5 or T55x7 - // data[0] = T5555_SET_BITRATE(64) | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | 2 << T5555_MAXBLOCK_SHIFT; + uint32_t data[] = {T55x7_BITRATE_RF_64 | T55x7_MODULATION_FSK2a | (2 << T55x7_MAXBLOCK_SHIFT), hi, lo}; + //TODO add selection of chip for Q5 or T55x7 + // data[0] = T5555_SET_BITRATE(64) | T5555_MODULATION_FSK2 | T5555_INVERT_OUTPUT | 2 << T5555_MAXBLOCK_SHIFT; - LED_D_ON(); - // Program the data blocks for supplied ID - // and the block 0 config - WriteT55xx(data, 0, 3); - LED_D_OFF(); + LED_D_ON(); + // Program the data blocks for supplied ID + // and the block 0 config + WriteT55xx(data, 0, 3); + LED_D_OFF(); } // Clone Indala 64-bit tag by UID to T55x7 void CopyIndala64toT55x7(uint32_t hi, uint32_t lo) { - //Program the 2 data blocks for supplied 64bit UID - // and the Config for Indala 64 format (RF/32;PSK2 with RF/2;Maxblock=2) - uint32_t data[] = { T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (2 << T55x7_MAXBLOCK_SHIFT), hi, lo}; - //TODO add selection of chip for Q5 or T55x7 - // data[0] = T5555_SET_BITRATE(32 | T5555_MODULATION_PSK2 | 2 << T5555_MAXBLOCK_SHIFT; + //Program the 2 data blocks for supplied 64bit UID + // and the Config for Indala 64 format (RF/32;PSK2 with RF/2;Maxblock=2) + uint32_t data[] = { T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (2 << T55x7_MAXBLOCK_SHIFT), hi, lo}; + //TODO add selection of chip for Q5 or T55x7 + // data[0] = T5555_SET_BITRATE(32 | T5555_MODULATION_PSK2 | 2 << T5555_MAXBLOCK_SHIFT; - WriteT55xx(data, 0, 3); - //Alternative config for Indala (Extended mode;RF/32;PSK2 with RF/2;Maxblock=2;Inverse data) - // T5567WriteBlock(0x603E1042,0); + WriteT55xx(data, 0, 3); + //Alternative config for Indala (Extended mode;RF/32;PSK2 with RF/2;Maxblock=2;Inverse data) + // T5567WriteBlock(0x603E1042,0); } // Clone Indala 224-bit tag by UID to T55x7 void CopyIndala224toT55x7(uint32_t uid1, uint32_t uid2, uint32_t uid3, uint32_t uid4, uint32_t uid5, uint32_t uid6, uint32_t uid7) { - //Program the 7 data blocks for supplied 224bit UID - uint32_t data[] = {0, uid1, uid2, uid3, uid4, uid5, uid6, uid7}; - // and the block 0 for Indala224 format - //Config for Indala (RF/32;PSK2 with RF/2;Maxblock=7) - data[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (7 << T55x7_MAXBLOCK_SHIFT); - //TODO add selection of chip for Q5 or T55x7 - // data[0] = T5555_SET_BITRATE(32 | T5555_MODULATION_PSK2 | 7 << T5555_MAXBLOCK_SHIFT; - WriteT55xx(data, 0, 8); - //Alternative config for Indala (Extended mode;RF/32;PSK2 with RF/2;Maxblock=7;Inverse data) - // T5567WriteBlock(0x603E10E2,0); + //Program the 7 data blocks for supplied 224bit UID + uint32_t data[] = {0, uid1, uid2, uid3, uid4, uid5, uid6, uid7}; + // and the block 0 for Indala224 format + //Config for Indala (RF/32;PSK2 with RF/2;Maxblock=7) + data[0] = T55x7_BITRATE_RF_32 | T55x7_MODULATION_PSK2 | (7 << T55x7_MAXBLOCK_SHIFT); + //TODO add selection of chip for Q5 or T55x7 + // data[0] = T5555_SET_BITRATE(32 | T5555_MODULATION_PSK2 | 7 << T5555_MAXBLOCK_SHIFT; + WriteT55xx(data, 0, 8); + //Alternative config for Indala (Extended mode;RF/32;PSK2 with RF/2;Maxblock=7;Inverse data) + // T5567WriteBlock(0x603E10E2,0); } // clone viking tag to T55xx void CopyVikingtoT55xx(uint32_t block1, uint32_t block2, uint8_t Q5) { - uint32_t data[] = {T55x7_BITRATE_RF_32 | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT), block1, block2}; - if (Q5) data[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_MANCHESTER | 2 << T5555_MAXBLOCK_SHIFT; - // Program the data blocks for supplied ID and the block 0 config - WriteT55xx(data, 0, 3); - LED_D_OFF(); - cmd_send(CMD_ACK,0,0,0,0,0); + uint32_t data[] = {T55x7_BITRATE_RF_32 | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT), block1, block2}; + if (Q5) data[0] = T5555_SET_BITRATE(32) | T5555_MODULATION_MANCHESTER | 2 << T5555_MAXBLOCK_SHIFT; + // Program the data blocks for supplied ID and the block 0 config + WriteT55xx(data, 0, 3); + LED_D_OFF(); + cmd_send(CMD_ACK,0,0,0,0,0); } // Define 9bit header for EM410x tags -#define EM410X_HEADER 0x1FF -#define EM410X_ID_LENGTH 40 +#define EM410X_HEADER 0x1FF +#define EM410X_ID_LENGTH 40 void WriteEM410x(uint32_t card, uint32_t id_hi, uint32_t id_lo) { - int i, id_bit; - uint64_t id = EM410X_HEADER; - uint64_t rev_id = 0; // reversed ID - int c_parity[4]; // column parity - int r_parity = 0; // row parity - uint32_t clock = 0; + int i, id_bit; + uint64_t id = EM410X_HEADER; + uint64_t rev_id = 0; // reversed ID + int c_parity[4]; // column parity + int r_parity = 0; // row parity + uint32_t clock = 0; - // Reverse ID bits given as parameter (for simpler operations) - for (i = 0; i < EM410X_ID_LENGTH; ++i) { - if (i < 32) { - rev_id = (rev_id << 1) | (id_lo & 1); - id_lo >>= 1; - } else { - rev_id = (rev_id << 1) | (id_hi & 1); - id_hi >>= 1; - } - } + // Reverse ID bits given as parameter (for simpler operations) + for (i = 0; i < EM410X_ID_LENGTH; ++i) { + if (i < 32) { + rev_id = (rev_id << 1) | (id_lo & 1); + id_lo >>= 1; + } else { + rev_id = (rev_id << 1) | (id_hi & 1); + id_hi >>= 1; + } + } - for (i = 0; i < EM410X_ID_LENGTH; ++i) { - id_bit = rev_id & 1; + for (i = 0; i < EM410X_ID_LENGTH; ++i) { + id_bit = rev_id & 1; - if (i % 4 == 0) { - // Don't write row parity bit at start of parsing - if (i) - id = (id << 1) | r_parity; - // Start counting parity for new row - r_parity = id_bit; - } else { - // Count row parity - r_parity ^= id_bit; - } + if (i % 4 == 0) { + // Don't write row parity bit at start of parsing + if (i) + id = (id << 1) | r_parity; + // Start counting parity for new row + r_parity = id_bit; + } else { + // Count row parity + r_parity ^= id_bit; + } - // First elements in column? - if (i < 4) - // Fill out first elements - c_parity[i] = id_bit; - else - // Count column parity - c_parity[i % 4] ^= id_bit; + // First elements in column? + if (i < 4) + // Fill out first elements + c_parity[i] = id_bit; + else + // Count column parity + c_parity[i % 4] ^= id_bit; - // Insert ID bit - id = (id << 1) | id_bit; - rev_id >>= 1; - } + // Insert ID bit + id = (id << 1) | id_bit; + rev_id >>= 1; + } - // Insert parity bit of last row - id = (id << 1) | r_parity; + // Insert parity bit of last row + id = (id << 1) | r_parity; - // Fill out column parity at the end of tag - for (i = 0; i < 4; ++i) - id = (id << 1) | c_parity[i]; + // Fill out column parity at the end of tag + for (i = 0; i < 4; ++i) + id = (id << 1) | c_parity[i]; - // Add stop bit - id <<= 1; + // Add stop bit + id <<= 1; - Dbprintf("Started writing %s tag ...", card ? "T55x7":"T5555"); - LED_D_ON(); + Dbprintf("Started writing %s tag ...", card ? "T55x7":"T5555"); + LED_D_ON(); - // Write EM410x ID - uint32_t data[] = {0, (uint32_t)(id>>32), (uint32_t)(id & 0xFFFFFFFF)}; + // Write EM410x ID + uint32_t data[] = {0, (uint32_t)(id>>32), (uint32_t)(id & 0xFFFFFFFF)}; - clock = (card & 0xFF00) >> 8; - clock = (clock == 0) ? 64 : clock; - Dbprintf("Clock rate: %d", clock); - if (card & 0xFF) { //t55x7 - clock = GetT55xxClockBit(clock); - if (clock == 0) { - Dbprintf("Invalid clock rate: %d", clock); - return; - } - data[0] = clock | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT); - } else { //t5555 (Q5) - data[0] = T5555_SET_BITRATE(clock) | T5555_MODULATION_MANCHESTER | (2 << T5555_MAXBLOCK_SHIFT); - } + clock = (card & 0xFF00) >> 8; + clock = (clock == 0) ? 64 : clock; + Dbprintf("Clock rate: %d", clock); + if (card & 0xFF) { //t55x7 + clock = GetT55xxClockBit(clock); + if (clock == 0) { + Dbprintf("Invalid clock rate: %d", clock); + return; + } + data[0] = clock | T55x7_MODULATION_MANCHESTER | (2 << T55x7_MAXBLOCK_SHIFT); + } else { //t5555 (Q5) + data[0] = T5555_SET_BITRATE(clock) | T5555_MODULATION_MANCHESTER | (2 << T5555_MAXBLOCK_SHIFT); + } - WriteT55xx(data, 0, 3); + WriteT55xx(data, 0, 3); - LED_D_OFF(); - Dbprintf("Tag %s written with 0x%08x%08x\n", - card ? "T55x7":"T5555", - (uint32_t)(id >> 32), - (uint32_t)id); + LED_D_OFF(); + Dbprintf("Tag %s written with 0x%08x%08x\n", + card ? "T55x7":"T5555", + (uint32_t)(id >> 32), + (uint32_t)id); } //----------------------------------- @@ -1906,18 +1907,18 @@ uint8_t * fwd_write_ptr; //forwardlink bit pointer uint8_t Prepare_Cmd( uint8_t cmd ) { - *forward_ptr++ = 0; //start bit - *forward_ptr++ = 0; //second pause for 4050 code + *forward_ptr++ = 0; //start bit + *forward_ptr++ = 0; //second pause for 4050 code - *forward_ptr++ = cmd; - cmd >>= 1; - *forward_ptr++ = cmd; - cmd >>= 1; - *forward_ptr++ = cmd; - cmd >>= 1; - *forward_ptr++ = cmd; + *forward_ptr++ = cmd; + cmd >>= 1; + *forward_ptr++ = cmd; + cmd >>= 1; + *forward_ptr++ = cmd; + cmd >>= 1; + *forward_ptr++ = cmd; - return 6; //return number of emited bits + return 6; //return number of emited bits } //==================================================================== @@ -1926,19 +1927,19 @@ uint8_t Prepare_Cmd( uint8_t cmd ) { //==================================================================== uint8_t Prepare_Addr( uint8_t addr ) { - register uint8_t line_parity; + register uint8_t line_parity; - uint8_t i; - line_parity = 0; - for( i=0; i<6; i++ ) { - *forward_ptr++ = addr; - line_parity ^= addr; - addr >>= 1; - } + uint8_t i; + line_parity = 0; + for( i=0; i<6; i++ ) { + *forward_ptr++ = addr; + line_parity ^= addr; + addr >>= 1; + } - *forward_ptr++ = (line_parity & 1); + *forward_ptr++ = (line_parity & 1); - return 7; //return number of emited bits + return 7; //return number of emited bits } //==================================================================== @@ -1947,34 +1948,34 @@ uint8_t Prepare_Addr( uint8_t addr ) { //==================================================================== uint8_t Prepare_Data( uint16_t data_low, uint16_t data_hi) { - register uint8_t line_parity; - register uint8_t column_parity; - register uint8_t i, j; - register uint16_t data; + register uint8_t line_parity; + register uint8_t column_parity; + register uint8_t i, j; + register uint16_t data; - data = data_low; - column_parity = 0; + data = data_low; + column_parity = 0; - for(i=0; i<4; i++) { - line_parity = 0; - for(j=0; j<8; j++) { - line_parity ^= data; - column_parity ^= (data & 1) << j; - *forward_ptr++ = data; - data >>= 1; - } - *forward_ptr++ = line_parity; - if(i == 1) - data = data_hi; - } + for(i=0; i<4; i++) { + line_parity = 0; + for(j=0; j<8; j++) { + line_parity ^= data; + column_parity ^= (data & 1) << j; + *forward_ptr++ = data; + data >>= 1; + } + *forward_ptr++ = line_parity; + if(i == 1) + data = data_hi; + } - for(j=0; j<8; j++) { - *forward_ptr++ = column_parity; - column_parity >>= 1; - } - *forward_ptr = 0; + for(j=0; j<8; j++) { + *forward_ptr++ = column_parity; + column_parity >>= 1; + } + *forward_ptr = 0; - return 45; //return number of emited bits + return 45; //return number of emited bits } //==================================================================== @@ -1992,108 +1993,108 @@ void SendForward(uint8_t fwd_bit_count) { #define EM_START_GAP 55*8 #endif - fwd_write_ptr = forwardLink_data; - fwd_bit_sz = fwd_bit_count; + fwd_write_ptr = forwardLink_data; + fwd_bit_sz = fwd_bit_count; - // Set up FPGA, 125kHz or 95 divisor - LFSetupFPGAForADC(95, true); + // Set up FPGA, 125kHz or 95 divisor + LFSetupFPGAForADC(95, true); - // force 1st mod pulse (start gap must be longer for 4305) - fwd_bit_sz--; //prepare next bit modulation - fwd_write_ptr++; + // force 1st mod pulse (start gap must be longer for 4305) + fwd_bit_sz--; //prepare next bit modulation + fwd_write_ptr++; - TurnReadLF_off(EM_START_GAP); - TurnReadLFOn(18*8); + TurnReadLF_off(EM_START_GAP); + TurnReadLFOn(18*8); - // now start writting with bitbanging the antenna. - while(fwd_bit_sz-- > 0) { //prepare next bit modulation - if(((*fwd_write_ptr++) & 1) == 1) { - WaitUS(32*8); - } else { - TurnReadLF_off(23*8); - TurnReadLFOn(18*8); - } - } + // now start writting with bitbanging the antenna. + while(fwd_bit_sz-- > 0) { //prepare next bit modulation + if(((*fwd_write_ptr++) & 1) == 1) { + WaitUS(32*8); + } else { + TurnReadLF_off(23*8); + TurnReadLFOn(18*8); + } + } } void EM4xLogin(uint32_t pwd) { - uint8_t len; - forward_ptr = forwardLink_data; - len = Prepare_Cmd( FWD_CMD_LOGIN ); - len += Prepare_Data( pwd & 0xFFFF, pwd >> 16 ); - SendForward(len); - //WaitUS(20); // no wait for login command. - // should receive - // 0000 1010 ok. - // 0000 0001 fail + uint8_t len; + forward_ptr = forwardLink_data; + len = Prepare_Cmd( FWD_CMD_LOGIN ); + len += Prepare_Data( pwd & 0xFFFF, pwd >> 16 ); + SendForward(len); + //WaitUS(20); // no wait for login command. + // should receive + // 0000 1010 ok. + // 0000 0001 fail } void EM4xReadWord(uint8_t addr, uint32_t pwd, uint8_t usepwd) { - LED_A_ON(); - uint8_t len; + LED_A_ON(); + uint8_t len; - //clear buffer now so it does not interfere with timing later - BigBuf_Clear_ext(false); + //clear buffer now so it does not interfere with timing later + BigBuf_Clear_ext(false); - StartTicks(); - /* should we read answer from Logincommand? - * - * should receive - * 0000 1010 ok. - * 0000 0001 fail - **/ - if (usepwd) EM4xLogin(pwd); + StartTicks(); + /* should we read answer from Logincommand? + * + * should receive + * 0000 1010 ok. + * 0000 0001 fail + **/ + if (usepwd) EM4xLogin(pwd); - forward_ptr = forwardLink_data; - len = Prepare_Cmd( FWD_CMD_READ ); - len += Prepare_Addr( addr ); + forward_ptr = forwardLink_data; + len = Prepare_Cmd( FWD_CMD_READ ); + len += Prepare_Addr( addr ); - SendForward(len); + SendForward(len); - WaitUS(400); + WaitUS(400); - DoPartialAcquisition(20, true, 6000, 1000); + DoPartialAcquisition(20, true, 6000, 1000); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - cmd_send(CMD_ACK,0,0,0,0,0); - LED_A_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + cmd_send(CMD_ACK,0,0,0,0,0); + LED_A_OFF(); } void EM4xWriteWord(uint32_t flag, uint32_t data, uint32_t pwd) { - LED_A_ON(); + LED_A_ON(); - bool usePwd = (flag & 0xF); - uint8_t addr = (flag >> 8) & 0xFF; - uint8_t len; + bool usePwd = (flag & 0xF); + uint8_t addr = (flag >> 8) & 0xFF; + uint8_t len; - //clear buffer now so it does not interfere with timing later - BigBuf_Clear_ext(false); - StartTicks(); - /* should we read answer from Logincommand? - * - * should receive - * 0000 1010 ok. - * 0000 0001 fail - **/ - if (usePwd) EM4xLogin(pwd); + //clear buffer now so it does not interfere with timing later + BigBuf_Clear_ext(false); + StartTicks(); + /* should we read answer from Logincommand? + * + * should receive + * 0000 1010 ok. + * 0000 0001 fail + **/ + if (usePwd) EM4xLogin(pwd); - forward_ptr = forwardLink_data; - len = Prepare_Cmd( FWD_CMD_WRITE ); - len += Prepare_Addr( addr ); - len += Prepare_Data( data & 0xFFFF, data >> 16 ); + forward_ptr = forwardLink_data; + len = Prepare_Cmd( FWD_CMD_WRITE ); + len += Prepare_Addr( addr ); + len += Prepare_Data( data & 0xFFFF, data >> 16 ); - SendForward(len); + SendForward(len); - //Wait 20ms for write to complete? - WaitMS(7); + //Wait 20ms for write to complete? + WaitMS(7); - DoPartialAcquisition(20, true, 6000, 1000); + DoPartialAcquisition(20, true, 6000, 1000); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - cmd_send(CMD_ACK,0,0,0,0,0); - LED_A_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + cmd_send(CMD_ACK,0,0,0,0,0); + LED_A_OFF(); } /* @@ -2112,36 +2113,36 @@ This triggers a COTAG tag to response */ void Cotag(uint32_t arg0) { #ifndef OFF -# define OFF(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS((x)); } +# define OFF(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); WaitUS((x)); } #endif #ifndef ON # define ON(x) { FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | FPGA_LF_ADC_READER_FIELD); WaitUS((x)); } #endif - uint8_t rawsignal = arg0 & 0xF; + uint8_t rawsignal = arg0 & 0xF; - LED_A_ON(); + LED_A_ON(); - LFSetupFPGAForADC(89, true); + LFSetupFPGAForADC(89, true); - //clear buffer now so it does not interfere with timing later - BigBuf_Clear_ext(false); + //clear buffer now so it does not interfere with timing later + BigBuf_Clear_ext(false); - //send COTAG start pulse - ON(740) OFF(2035) - ON(3330) OFF(2035) - ON(740) OFF(2035) - ON(1000) + //send COTAG start pulse + ON(740) OFF(2035) + ON(3330) OFF(2035) + ON(740) OFF(2035) + ON(1000) - switch(rawsignal) { - case 0: doCotagAcquisition(50000); break; - case 1: doCotagAcquisitionManchester(); break; - case 2: DoAcquisition_config(true, 0); break; - } + switch(rawsignal) { + case 0: doCotagAcquisition(50000); break; + case 1: doCotagAcquisitionManchester(); break; + case 2: DoAcquisition_config(true, 0); break; + } - // Turn the field off - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off - cmd_send(CMD_ACK,0,0,0,0,0); - LEDsoff(); + // Turn the field off + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); // field off + cmd_send(CMD_ACK,0,0,0,0,0); + LEDsoff(); } /* diff --git a/armsrc/lfsampling.c b/armsrc/lfsampling.c index 80d95bb4a..93ba535b6 100644 --- a/armsrc/lfsampling.c +++ b/armsrc/lfsampling.c @@ -10,21 +10,21 @@ /* Default LF config is set to: - decimation = 1 (we keep 1 out of 1 samples) - bits_per_sample = 8 - averaging = YES - divisor = 95 (125khz) - trigger_threshold = 0 - */ + decimation = 1 (we keep 1 out of 1 samples) + bits_per_sample = 8 + averaging = YES + divisor = 95 (125khz) + trigger_threshold = 0 + */ sample_config config = { 1, 8, 1, 95, 0 } ; void printConfig() { - Dbprintf("LF Sampling config"); - Dbprintf(" [q] divisor.............%d (%d KHz)", config.divisor, 12000 / (config.divisor+1)); - Dbprintf(" [b] bps.................%d", config.bits_per_sample); - Dbprintf(" [d] decimation..........%d", config.decimation); - Dbprintf(" [a] averaging...........%s", (config.averaging) ? "Yes" : "No"); - Dbprintf(" [t] trigger threshold...%d", config.trigger_threshold); + Dbprintf("LF Sampling config"); + Dbprintf(" [q] divisor.............%d (%d KHz)", config.divisor, 12000 / (config.divisor+1)); + Dbprintf(" [b] bps.................%d", config.bits_per_sample); + Dbprintf(" [d] decimation..........%d", config.decimation); + Dbprintf(" [a] averaging...........%s", (config.averaging) ? "Yes" : "No"); + Dbprintf(" [t] trigger threshold...%d", config.trigger_threshold); } /** @@ -39,25 +39,25 @@ void printConfig() { * @param sc */ void setSamplingConfig(sample_config *sc) { - if(sc->divisor != 0) config.divisor = sc->divisor; - if(sc->bits_per_sample != 0) config.bits_per_sample = sc->bits_per_sample; - if(sc->trigger_threshold != -1) config.trigger_threshold = sc->trigger_threshold; + if(sc->divisor != 0) config.divisor = sc->divisor; + if(sc->bits_per_sample != 0) config.bits_per_sample = sc->bits_per_sample; + if(sc->trigger_threshold != -1) config.trigger_threshold = sc->trigger_threshold; - config.decimation = (sc->decimation != 0) ? sc->decimation : 1; - config.averaging = sc->averaging; - if(config.bits_per_sample > 8) config.bits_per_sample = 8; + config.decimation = (sc->decimation != 0) ? sc->decimation : 1; + config.averaging = sc->averaging; + if(config.bits_per_sample > 8) config.bits_per_sample = 8; - printConfig(); + printConfig(); } sample_config* getSamplingConfig() { - return &config; + return &config; } struct BitstreamOut { - uint8_t * buffer; - uint32_t numbits; - uint32_t position; + uint8_t * buffer; + uint32_t numbits; + uint32_t position; }; /** @@ -66,39 +66,39 @@ struct BitstreamOut { * @param bit */ void pushBit( BitstreamOut* stream, uint8_t bit) { - int bytepos = stream->position >> 3; // divide by 8 - int bitpos = stream->position & 7; - *(stream->buffer+bytepos) |= (bit > 0) << (7 - bitpos); - stream->position++; - stream->numbits++; + int bytepos = stream->position >> 3; // divide by 8 + int bitpos = stream->position & 7; + *(stream->buffer+bytepos) |= (bit > 0) << (7 - bitpos); + stream->position++; + stream->numbits++; } /** * Setup the FPGA to listen for samples. This method downloads the FPGA bitstream * if not already loaded, sets divisor and starts up the antenna. * @param divisor : 1, 88> 255 or negative ==> 134.8 KHz -* 0 or 95 ==> 125 KHz +* 0 or 95 ==> 125 KHz * **/ void LFSetupFPGAForADC(int divisor, bool lf_field) { - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - if ( (divisor == 1) || (divisor < 0) || (divisor > 255) ) - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz - else if (divisor == 0) - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - else - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + if ( (divisor == 1) || (divisor < 0) || (divisor > 255) ) + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 88); //134.8Khz + else if (divisor == 0) + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + else + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, divisor); - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | (lf_field ? FPGA_LF_ADC_READER_FIELD : 0)); + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_ADC | (lf_field ? FPGA_LF_ADC_READER_FIELD : 0)); - // Connect the A/D to the peak-detected low-frequency path. - SetAdcMuxFor(GPIO_MUXSEL_LOPKD); - // 50ms for the resonant antenna to settle. - SpinDelay(50); - // Now set up the SSC to get the ADC samples that are now streaming at us. - FpgaSetupSsc(); - // start a 1.5ticks is 1us - StartTicks(); + // Connect the A/D to the peak-detected low-frequency path. + SetAdcMuxFor(GPIO_MUXSEL_LOPKD); + // 50ms for the resonant antenna to settle. + SpinDelay(50); + // Now set up the SSC to get the ADC samples that are now streaming at us. + FpgaSetupSsc(); + // start a 1.5ticks is 1us + StartTicks(); } /** @@ -118,97 +118,97 @@ void LFSetupFPGAForADC(int divisor, bool lf_field) { */ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averaging, int trigger_threshold, bool silent, int bufsize, uint32_t cancel_after) { - uint8_t *dest = BigBuf_get_addr(); + uint8_t *dest = BigBuf_get_addr(); bufsize = (bufsize > 0 && bufsize < BigBuf_max_traceLen()) ? bufsize : BigBuf_max_traceLen(); - if (bits_per_sample < 1) bits_per_sample = 1; - if (bits_per_sample > 8) bits_per_sample = 8; + if (bits_per_sample < 1) bits_per_sample = 1; + if (bits_per_sample > 8) bits_per_sample = 8; - if (decimation < 1) decimation = 1; + if (decimation < 1) decimation = 1; - // use a bit stream to handle the output - BitstreamOut data = { dest , 0, 0}; - int sample_counter = 0; - uint8_t sample = 0; + // use a bit stream to handle the output + BitstreamOut data = { dest , 0, 0}; + int sample_counter = 0; + uint8_t sample = 0; - // if we want to do averaging - uint32_t sample_sum =0 ; - uint32_t sample_total_numbers = 0; - uint32_t sample_total_saved = 0; - uint32_t cancel_counter = 0; + // if we want to do averaging + uint32_t sample_sum =0 ; + uint32_t sample_total_numbers = 0; + uint32_t sample_total_saved = 0; + uint32_t cancel_counter = 0; - while (!BUTTON_PRESS() && !usb_poll_validate_length() ) { - WDT_HIT(); + while (!BUTTON_PRESS() && !usb_poll_validate_length() ) { + WDT_HIT(); - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - // Testpoint 8 (TP8) can be used to trigger oscilliscope - LED_D_OFF(); + // Testpoint 8 (TP8) can be used to trigger oscilliscope + LED_D_OFF(); - // threshold either high or low values 128 = center 0. if trigger = 178 - if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) { - if (cancel_after > 0) { - cancel_counter++; - if (cancel_after == cancel_counter) - break; - } - continue; - } + // threshold either high or low values 128 = center 0. if trigger = 178 + if ((trigger_threshold > 0) && (sample < (trigger_threshold + 128)) && (sample > (128 - trigger_threshold))) { + if (cancel_after > 0) { + cancel_counter++; + if (cancel_after == cancel_counter) + break; + } + continue; + } - trigger_threshold = 0; - sample_total_numbers++; + trigger_threshold = 0; + sample_total_numbers++; - if (averaging) - sample_sum += sample; + if (averaging) + sample_sum += sample; - // check decimation - if (decimation > 1) { - sample_counter++; - if (sample_counter < decimation) continue; - sample_counter = 0; - } + // check decimation + if (decimation > 1) { + sample_counter++; + if (sample_counter < decimation) continue; + sample_counter = 0; + } - // averaging - if (averaging && decimation > 1) { - sample = sample_sum / decimation; - sample_sum =0; - } + // averaging + if (averaging && decimation > 1) { + sample = sample_sum / decimation; + sample_sum =0; + } - // store the sample - sample_total_saved ++; - if (bits_per_sample == 8) { - dest[sample_total_saved-1] = sample; + // store the sample + sample_total_saved ++; + if (bits_per_sample == 8) { + dest[sample_total_saved-1] = sample; - // Get the return value correct - data.numbits = sample_total_saved << 3; - if (sample_total_saved >= bufsize) break; + // Get the return value correct + data.numbits = sample_total_saved << 3; + if (sample_total_saved >= bufsize) break; - } else { - pushBit(&data, sample & 0x80); - if (bits_per_sample > 1) pushBit(&data, sample & 0x40); - if (bits_per_sample > 2) pushBit(&data, sample & 0x20); - if (bits_per_sample > 3) pushBit(&data, sample & 0x10); - if (bits_per_sample > 4) pushBit(&data, sample & 0x08); - if (bits_per_sample > 5) pushBit(&data, sample & 0x04); - if (bits_per_sample > 6) pushBit(&data, sample & 0x02); + } else { + pushBit(&data, sample & 0x80); + if (bits_per_sample > 1) pushBit(&data, sample & 0x40); + if (bits_per_sample > 2) pushBit(&data, sample & 0x20); + if (bits_per_sample > 3) pushBit(&data, sample & 0x10); + if (bits_per_sample > 4) pushBit(&data, sample & 0x08); + if (bits_per_sample > 5) pushBit(&data, sample & 0x04); + if (bits_per_sample > 6) pushBit(&data, sample & 0x02); - if ((data.numbits >> 3) + 1 >= bufsize) break; - } - } - } + if ((data.numbits >> 3) + 1 >= bufsize) break; + } + } + } - if (!silent) { - Dbprintf("Done, saved %d out of %d seen samples at %d bits/sample", sample_total_saved, sample_total_numbers, bits_per_sample); - Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...", - dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); - } + if (!silent) { + Dbprintf("Done, saved %d out of %d seen samples at %d bits/sample", sample_total_saved, sample_total_numbers, bits_per_sample); + Dbprintf("buffer samples: %02x %02x %02x %02x %02x %02x %02x %02x ...", + dest[0], dest[1], dest[2], dest[3], dest[4], dest[5], dest[6], dest[7]); + } - // Ensure that DC offset removal and noise check is performed for any device-side processing - removeSignalOffset(dest, bufsize); - computeSignalProperties(dest, bufsize); + // Ensure that DC offset removal and noise check is performed for any device-side processing + removeSignalOffset(dest, bufsize); + computeSignalProperties(dest, bufsize); - return data.numbits; + return data.numbits; } /** * @brief Does sample acquisition, ignoring the config values set in the sample_config. @@ -219,27 +219,27 @@ uint32_t DoAcquisition(uint8_t decimation, uint32_t bits_per_sample, bool averag * @return number of bits sampled */ uint32_t DoAcquisition_default(int trigger_threshold, bool silent) { - return DoAcquisition(1, 8, 0,trigger_threshold, silent, 0, 0); + return DoAcquisition(1, 8, 0,trigger_threshold, silent, 0, 0); } uint32_t DoAcquisition_config( bool silent, int sample_size) { - return DoAcquisition(config.decimation - ,config.bits_per_sample - ,config.averaging - ,config.trigger_threshold - ,silent - ,sample_size - ,0); + return DoAcquisition(config.decimation + ,config.bits_per_sample + ,config.averaging + ,config.trigger_threshold + ,silent + ,sample_size + ,0); } uint32_t DoPartialAcquisition(int trigger_threshold, bool silent, int sample_size, uint32_t cancel_after) { - return DoAcquisition(1, 8, 0, trigger_threshold, silent, sample_size, cancel_after); + return DoAcquisition(1, 8, 0, trigger_threshold, silent, sample_size, cancel_after); } uint32_t ReadLF(bool activeField, bool silent, int sample_size) { - if (!silent) - printConfig(); - LFSetupFPGAForADC(config.divisor, activeField); - return DoAcquisition_config(silent, sample_size); + if (!silent) + printConfig(); + LFSetupFPGAForADC(config.divisor, activeField); + return DoAcquisition_config(silent, sample_size); } /** @@ -247,20 +247,20 @@ uint32_t ReadLF(bool activeField, bool silent, int sample_size) { * @return number of bits sampled **/ uint32_t SampleLF(bool printCfg, int sample_size) { - BigBuf_Clear_ext(false); - uint32_t ret = ReadLF(true, printCfg, sample_size); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - return ret; + BigBuf_Clear_ext(false); + uint32_t ret = ReadLF(true, printCfg, sample_size); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + return ret; } /** * Initializes the FPGA for snoop-mode (field off), and acquires the samples. * @return number of bits sampled **/ uint32_t SnoopLF() { - BigBuf_Clear_ext(false); - uint32_t ret = ReadLF(false, true, 0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - return ret; + BigBuf_Clear_ext(false); + uint32_t ret = ReadLF(false, true, 0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + return ret; } /** @@ -269,61 +269,61 @@ uint32_t SnoopLF() { **/ void doT55x7Acquisition(size_t sample_size) { - #define T55xx_READ_UPPER_THRESHOLD 128+60 // 60 grph - #define T55xx_READ_LOWER_THRESHOLD 128-60 // -60 grph - #define T55xx_READ_TOL 5 + #define T55xx_READ_UPPER_THRESHOLD 128+60 // 60 grph + #define T55xx_READ_LOWER_THRESHOLD 128-60 // -60 grph + #define T55xx_READ_TOL 5 - uint8_t *dest = BigBuf_get_addr(); - uint16_t bufsize = BigBuf_max_traceLen(); + uint8_t *dest = BigBuf_get_addr(); + uint16_t bufsize = BigBuf_max_traceLen(); - if ( bufsize > sample_size ) - bufsize = sample_size; + if ( bufsize > sample_size ) + bufsize = sample_size; - uint8_t curSample = 0, lastSample = 0; - uint16_t i = 0, skipCnt = 0; - bool startFound = false; - bool highFound = false; - bool lowFound = false; + uint8_t curSample = 0, lastSample = 0; + uint16_t i = 0, skipCnt = 0; + bool startFound = false; + bool highFound = false; + bool lowFound = false; - while(!BUTTON_PRESS() && !usb_poll_validate_length() && skipCnt < 1000 && (i < bufsize) ) { - WDT_HIT(); + while(!BUTTON_PRESS() && !usb_poll_validate_length() && skipCnt < 1000 && (i < bufsize) ) { + WDT_HIT(); - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - curSample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - LED_D_OFF(); + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + curSample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + LED_D_OFF(); - // skip until the first high sample above threshold - if (!startFound && curSample > T55xx_READ_UPPER_THRESHOLD) { - //if (curSample > lastSample) - // lastSample = curSample; - highFound = true; - } else if (!highFound) { - skipCnt++; - continue; - } - // skip until the first low sample below threshold - if (!startFound && curSample < T55xx_READ_LOWER_THRESHOLD) { - //if (curSample > lastSample) - lastSample = curSample; - lowFound = true; - } else if (!lowFound) { - skipCnt++; - continue; - } + // skip until the first high sample above threshold + if (!startFound && curSample > T55xx_READ_UPPER_THRESHOLD) { + //if (curSample > lastSample) + // lastSample = curSample; + highFound = true; + } else if (!highFound) { + skipCnt++; + continue; + } + // skip until the first low sample below threshold + if (!startFound && curSample < T55xx_READ_LOWER_THRESHOLD) { + //if (curSample > lastSample) + lastSample = curSample; + lowFound = true; + } else if (!lowFound) { + skipCnt++; + continue; + } - // skip until first high samples begin to change - if (startFound || curSample > T55xx_READ_LOWER_THRESHOLD + T55xx_READ_TOL){ - // if just found start - recover last sample - if (!startFound) { - dest[i++] = lastSample; - startFound = true; - } - // collect samples - dest[i++] = curSample; - } - } - } + // skip until first high samples begin to change + if (startFound || curSample > T55xx_READ_LOWER_THRESHOLD + T55xx_READ_TOL){ + // if just found start - recover last sample + if (!startFound) { + dest[i++] = lastSample; + startFound = true; + } + // collect samples + dest[i++] = curSample; + } + } + } } /** * acquisition of Cotag LF signal. Similart to other LF, since the Cotag has such long datarate RF/384 @@ -339,117 +339,117 @@ void doT55x7Acquisition(size_t sample_size) { #endif void doCotagAcquisition(size_t sample_size) { - uint8_t *dest = BigBuf_get_addr(); - uint16_t bufsize = BigBuf_max_traceLen(); + uint8_t *dest = BigBuf_get_addr(); + uint16_t bufsize = BigBuf_max_traceLen(); - if ( bufsize > sample_size ) - bufsize = sample_size; + if ( bufsize > sample_size ) + bufsize = sample_size; - dest[0] = 0; - uint8_t sample = 0, firsthigh = 0, firstlow = 0; - uint16_t i = 0; - uint16_t noise_counter = 0; + dest[0] = 0; + uint8_t sample = 0, firsthigh = 0, firstlow = 0; + uint16_t i = 0; + uint16_t noise_counter = 0; - while (!BUTTON_PRESS() && !usb_poll_validate_length() && (i < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) { - WDT_HIT(); + while (!BUTTON_PRESS() && !usb_poll_validate_length() && (i < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) { + WDT_HIT(); - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - LED_D_OFF(); + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + LED_D_OFF(); - // find first peak - if ( !firsthigh ) { - if (sample < COTAG_ONE_THRESHOLD) { - noise_counter++; - continue; - } - noise_counter = 0; - firsthigh = 1; - } - if ( !firstlow ){ - if (sample > COTAG_ZERO_THRESHOLD ) { - noise_counter++; - continue; - } - noise_counter = 0; - firstlow = 1; - } + // find first peak + if ( !firsthigh ) { + if (sample < COTAG_ONE_THRESHOLD) { + noise_counter++; + continue; + } + noise_counter = 0; + firsthigh = 1; + } + if ( !firstlow ){ + if (sample > COTAG_ZERO_THRESHOLD ) { + noise_counter++; + continue; + } + noise_counter = 0; + firstlow = 1; + } - ++i; + ++i; - if ( sample > COTAG_ONE_THRESHOLD) - dest[i] = 255; - else if ( sample < COTAG_ZERO_THRESHOLD) - dest[i] = 0; - else - dest[i] = dest[i-1]; - } - } + if ( sample > COTAG_ONE_THRESHOLD) + dest[i] = 255; + else if ( sample < COTAG_ZERO_THRESHOLD) + dest[i] = 0; + else + dest[i] = dest[i-1]; + } + } } uint32_t doCotagAcquisitionManchester() { - uint8_t *dest = BigBuf_get_addr(); - uint16_t bufsize = BigBuf_max_traceLen(); + uint8_t *dest = BigBuf_get_addr(); + uint16_t bufsize = BigBuf_max_traceLen(); - if ( bufsize > COTAG_BITS ) - bufsize = COTAG_BITS; + if ( bufsize > COTAG_BITS ) + bufsize = COTAG_BITS; - dest[0] = 0; - uint8_t sample = 0, firsthigh = 0, firstlow = 0; - uint16_t sample_counter = 0, period = 0; - uint8_t curr = 0, prev = 0; - uint16_t noise_counter = 0; + dest[0] = 0; + uint8_t sample = 0, firsthigh = 0, firstlow = 0; + uint16_t sample_counter = 0, period = 0; + uint8_t curr = 0, prev = 0; + uint16_t noise_counter = 0; - while (!BUTTON_PRESS() && !usb_poll_validate_length() && (sample_counter < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) { - WDT_HIT(); + while (!BUTTON_PRESS() && !usb_poll_validate_length() && (sample_counter < bufsize) && (noise_counter < (COTAG_T1 << 1)) ) { + WDT_HIT(); - if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { - sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; - LED_D_OFF(); + if (AT91C_BASE_SSC->SSC_SR & AT91C_SSC_RXRDY) { + sample = (uint8_t)AT91C_BASE_SSC->SSC_RHR; + LED_D_OFF(); - // find first peak - if ( !firsthigh ) { - if (sample < COTAG_ONE_THRESHOLD) { - noise_counter++; - continue; - } - noise_counter = 0; - firsthigh = 1; - } + // find first peak + if ( !firsthigh ) { + if (sample < COTAG_ONE_THRESHOLD) { + noise_counter++; + continue; + } + noise_counter = 0; + firsthigh = 1; + } - if ( !firstlow ){ - if (sample > COTAG_ZERO_THRESHOLD ) { - noise_counter++; - continue; - } - noise_counter = 0; - firstlow = 1; - } + if ( !firstlow ){ + if (sample > COTAG_ZERO_THRESHOLD ) { + noise_counter++; + continue; + } + noise_counter = 0; + firstlow = 1; + } - // set sample 255, 0, or previous - if ( sample > COTAG_ONE_THRESHOLD){ - prev = curr; - curr = 1; - } - else if ( sample < COTAG_ZERO_THRESHOLD) { - prev = curr; - curr = 0; - } - else { - curr = prev; - } + // set sample 255, 0, or previous + if ( sample > COTAG_ONE_THRESHOLD){ + prev = curr; + curr = 1; + } + else if ( sample < COTAG_ZERO_THRESHOLD) { + prev = curr; + curr = 0; + } + else { + curr = prev; + } - // full T1 periods, - if ( period > 0 ) { - --period; - continue; - } + // full T1 periods, + if ( period > 0 ) { + --period; + continue; + } - dest[sample_counter] = curr; - ++sample_counter; - period = COTAG_T1; - } - } - return sample_counter; + dest[sample_counter] = curr; + ++sample_counter; + period = COTAG_T1; + } + } + return sample_counter; } diff --git a/armsrc/lfsampling.h b/armsrc/lfsampling.h index aadf0a822..15510198a 100644 --- a/armsrc/lfsampling.h +++ b/armsrc/lfsampling.h @@ -5,8 +5,8 @@ #include "apps.h" #include "util.h" #include "string.h" -#include "usb_cdc.h" // for usb_poll_validate_length -#include "ticks.h" // for StartTicks +#include "usb_cdc.h" // for usb_poll_validate_length +#include "ticks.h" // for StartTicks typedef struct BitstreamOut BitstreamOut; @@ -60,7 +60,7 @@ uint32_t DoAcquisition_config(bool silent, int sample_size); * Setup the FPGA to listen for samples. This method downloads the FPGA bitstream * if not already loaded, sets divisor and starts up the antenna. * @param divisor : 1, 88> 255 or negative ==> 134.8 KHz -* 0 or 95 ==> 125 KHz +* 0 or 95 ==> 125 KHz * **/ void LFSetupFPGAForADC(int divisor, bool lf_field); diff --git a/armsrc/mifarecmd.c b/armsrc/mifarecmd.c index a10925da7..4889afce0 100644 --- a/armsrc/mifarecmd.c +++ b/armsrc/mifarecmd.c @@ -17,18 +17,18 @@ #include #ifndef HARDNESTED_AUTHENTICATION_TIMEOUT -# define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) +# define HARDNESTED_AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) #endif #ifndef HARDNESTED_PRE_AUTHENTICATION_LEADTIME -# define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication +# define HARDNESTED_PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication #endif // send an incomplete dummy response in order to trigger the card's authentication failure timeout #ifndef CHK_TIMEOUT # define CHK_TIMEOUT() { \ - ReaderTransmit(&dummy_answer, 1, NULL); \ - uint32_t timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT; \ - while (GetCountSspClk() < timeout) {}; \ + ReaderTransmit(&dummy_answer, 1, NULL); \ + uint32_t timeout = GetCountSspClk() + HARDNESTED_AUTHENTICATION_TIMEOUT; \ + while (GetCountSspClk() < timeout) {}; \ } #endif @@ -41,94 +41,94 @@ static uint8_t dummy_answer = 0; void MifareReadBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { // params - uint8_t blockNo = arg0; - uint8_t keyType = arg1; - uint64_t ui64Key = 0; - ui64Key = bytes_to_num(datain, 6); + uint8_t blockNo = arg0; + uint8_t keyType = arg1; + uint64_t ui64Key = 0; + ui64Key = bytes_to_num(datain, 6); - // variables - byte_t isOK = 0; - byte_t dataoutbuf[16] = {0x00}; - uint8_t uid[10] = {0x00}; - uint32_t cuid = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; + // variables + byte_t isOK = 0; + byte_t dataoutbuf[16] = {0x00}; + uint8_t uid[10] = {0x00}; + uint32_t cuid = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); + clear_trace(); + set_tracing(true); - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); - while (true) { - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - break; - }; + while (true) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + break; + }; - if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); - break; - }; + if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); + break; + }; - if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Read block error"); - break; - }; + if(mifare_classic_readblock(pcs, cuid, blockNo, dataoutbuf)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Read block error"); + break; + }; - if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - break; - }; + if(mifare_classic_halt(pcs, cuid)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + break; + }; - isOK = 1; - break; - } + isOK = 1; + break; + } - crypto1_destroy(pcs); + crypto1_destroy(pcs); - if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED"); + if (MF_DBGLEVEL >= 2) DbpString("READ BLOCK FINISHED"); - LED_B_ON(); - cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16); - LED_B_OFF(); + LED_B_ON(); + cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16); + LED_B_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); } void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){ - bool turnOffField = (arg0 == 1); + bool turnOffField = (arg0 == 1); - LED_A_ON(); LED_B_OFF(); LED_C_OFF(); + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); + clear_trace(); + set_tracing(true); - if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); - OnError(0); - return; - }; + if(!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); + OnError(0); + return; + }; - if(!mifare_ultra_auth(keybytes)){ - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed"); - OnError(1); - return; - } + if(!mifare_ultra_auth(keybytes)){ + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed"); + OnError(1); + return; + } - if (turnOffField) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - } - cmd_send(CMD_ACK,1,0,0,0,0); + if (turnOffField) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + } + cmd_send(CMD_ACK,1,0,0,0,0); } // Arg0 = BlockNo, @@ -136,62 +136,62 @@ void MifareUC_Auth(uint8_t arg0, uint8_t *keybytes){ // datain = PWD bytes, void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) { - uint8_t blockNo = arg0; - byte_t dataout[16] = {0x00}; - bool useKey = (arg1 == 1); //UL_C - bool usePwd = (arg1 == 2); //UL_EV1/NTAG + uint8_t blockNo = arg0; + byte_t dataout[16] = {0x00}; + bool useKey = (arg1 == 1); //UL_C + bool usePwd = (arg1 == 2); //UL_EV1/NTAG - LEDsoff(); - LED_A_ON(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + LEDsoff(); + LED_A_ON(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); + clear_trace(); + set_tracing(true); - int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true); - if(!len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len); - OnError(1); - return; - } + int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true); + if(!len) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%02X)",len); + OnError(1); + return; + } - // UL-C authentication - if ( useKey ) { - uint8_t key[16] = {0x00}; - memcpy(key, datain, sizeof(key) ); + // UL-C authentication + if ( useKey ) { + uint8_t key[16] = {0x00}; + memcpy(key, datain, sizeof(key) ); - if ( !mifare_ultra_auth(key) ) { - OnError(1); - return; - } - } + if ( !mifare_ultra_auth(key) ) { + OnError(1); + return; + } + } - // UL-EV1 / NTAG authentication - if ( usePwd ) { - uint8_t pwd[4] = {0x00}; - memcpy(pwd, datain, 4); - uint8_t pack[4] = {0,0,0,0}; - if (!mifare_ul_ev1_auth(pwd, pack)) { - OnError(1); - return; - } - } + // UL-EV1 / NTAG authentication + if ( usePwd ) { + uint8_t pwd[4] = {0x00}; + memcpy(pwd, datain, 4); + uint8_t pack[4] = {0,0,0,0}; + if (!mifare_ul_ev1_auth(pwd, pack)) { + OnError(1); + return; + } + } - if( mifare_ultra_readblock(blockNo, dataout) ) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error"); - OnError(2); - return; - } + if( mifare_ultra_readblock(blockNo, dataout) ) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block error"); + OnError(2); + return; + } - if( mifare_ultra_halt() ) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); - OnError(3); - return; - } + if( mifare_ultra_halt() ) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); + OnError(3); + return; + } cmd_send(CMD_ACK,1,0,0,dataout,16); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); } //----------------------------------------------------------------------------- @@ -201,64 +201,64 @@ void MifareUReadBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { // params - uint8_t sectorNo = arg0; - uint8_t keyType = arg1; - uint64_t ui64Key = 0; - ui64Key = bytes_to_num(datain, 6); + uint8_t sectorNo = arg0; + uint8_t keyType = arg1; + uint64_t ui64Key = 0; + ui64Key = bytes_to_num(datain, 6); - // variables - byte_t isOK = 0; - byte_t dataoutbuf[16 * 16]; - uint8_t uid[10] = {0x00}; - uint32_t cuid = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; + // variables + byte_t isOK = 0; + byte_t dataoutbuf[16 * 16]; + uint8_t uid[10] = {0x00}; + uint32_t cuid = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); + clear_trace(); + set_tracing(true); - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); - isOK = 1; - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - isOK = 0; - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - } + isOK = 1; + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + isOK = 0; + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + } - if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { - isOK = 0; - if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); - } + if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { + isOK = 0; + if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); + } - for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { - if(mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) { - isOK = 0; - if (MF_DBGLEVEL >= 1) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo); - break; - } - } + for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { + if(mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf + 16 * blockNo)) { + isOK = 0; + if (MF_DBGLEVEL >= 1) Dbprintf("Read sector %2d block %2d error", sectorNo, blockNo); + break; + } + } - if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - } + if(mifare_classic_halt(pcs, cuid)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + } - if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED"); + if (MF_DBGLEVEL >= 2) DbpString("READ SECTOR FINISHED"); - crypto1_destroy(pcs); + crypto1_destroy(pcs); - LED_B_ON(); - cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16*NumBlocksPerSector(sectorNo)); - LED_B_OFF(); + LED_B_ON(); + cmd_send(CMD_ACK,isOK,0,0,dataoutbuf,16*NumBlocksPerSector(sectorNo)); + LED_B_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); } // arg0 = blockNo (start) @@ -267,97 +267,97 @@ void MifareReadSector(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) // datain = KEY bytes void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) { - LEDsoff(); - LED_A_ON(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + LEDsoff(); + LED_A_ON(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - // free eventually allocated BigBuf memory - BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); - set_tracing(true); + // free eventually allocated BigBuf memory + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); - // params - uint8_t blockNo = arg0; - uint16_t blocks = arg1; - bool useKey = (arg2 == 1); //UL_C - bool usePwd = (arg2 == 2); //UL_EV1/NTAG - uint32_t countblocks = 0; - uint8_t *dataout = BigBuf_malloc(CARD_MEMORY_SIZE); - if (dataout == NULL){ - Dbprintf("out of memory"); - OnError(1); - return; - } + // params + uint8_t blockNo = arg0; + uint16_t blocks = arg1; + bool useKey = (arg2 == 1); //UL_C + bool usePwd = (arg2 == 2); //UL_EV1/NTAG + uint32_t countblocks = 0; + uint8_t *dataout = BigBuf_malloc(CARD_MEMORY_SIZE); + if (dataout == NULL){ + Dbprintf("out of memory"); + OnError(1); + return; + } - int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true); - if (!len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%d)",len); - OnError(1); - return; - } + int len = iso14443a_select_card(NULL, NULL, NULL, true, 0, true); + if (!len) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card (RC:%d)",len); + OnError(1); + return; + } - // UL-C authentication - if ( useKey ) { - uint8_t key[16] = {0x00}; - memcpy(key, datain, sizeof(key) ); + // UL-C authentication + if ( useKey ) { + uint8_t key[16] = {0x00}; + memcpy(key, datain, sizeof(key) ); - if ( !mifare_ultra_auth(key) ) { - OnError(1); - return; - } - } + if ( !mifare_ultra_auth(key) ) { + OnError(1); + return; + } + } - // UL-EV1 / NTAG authentication - if (usePwd) { - uint8_t pwd[4] = {0x00}; - memcpy(pwd, datain, sizeof(pwd)); - uint8_t pack[4] = {0,0,0,0}; + // UL-EV1 / NTAG authentication + if (usePwd) { + uint8_t pwd[4] = {0x00}; + memcpy(pwd, datain, sizeof(pwd)); + uint8_t pack[4] = {0,0,0,0}; - if (!mifare_ul_ev1_auth(pwd, pack)){ - OnError(1); - return; - } - } + if (!mifare_ul_ev1_auth(pwd, pack)){ + OnError(1); + return; + } + } - for (int i = 0; i < blocks; i++){ - if ((i*4) + 4 >= CARD_MEMORY_SIZE) { - Dbprintf("Data exceeds buffer!!"); - break; - } + for (int i = 0; i < blocks; i++){ + if ((i*4) + 4 >= CARD_MEMORY_SIZE) { + Dbprintf("Data exceeds buffer!!"); + break; + } - len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i); + len = mifare_ultra_readblock(blockNo + i, dataout + 4 * i); - if (len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i); - // if no blocks read - error out - if (i == 0) { - OnError(2); - return; - } else { - //stop at last successful read block and return what we got - break; - } - } else { - countblocks++; - } - } + if (len) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Read block %d error",i); + // if no blocks read - error out + if (i == 0) { + OnError(2); + return; + } else { + //stop at last successful read block and return what we got + break; + } + } else { + countblocks++; + } + } - len = mifare_ultra_halt(); - if (len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); - OnError(3); - return; - } + len = mifare_ultra_halt(); + if (len) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Halt error"); + OnError(3); + return; + } - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Blocks read %d", countblocks); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Blocks read %d", countblocks); - countblocks *= 4; + countblocks *= 4; - cmd_send(CMD_ACK, 1, countblocks, BigBuf_max_traceLen(), 0, 0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - BigBuf_free(); - set_tracing(false); + cmd_send(CMD_ACK, 1, countblocks, BigBuf_max_traceLen(), 0, 0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + BigBuf_free(); + set_tracing(false); } //----------------------------------------------------------------------------- @@ -366,106 +366,106 @@ void MifareUReadCard(uint8_t arg0, uint16_t arg1, uint8_t arg2, uint8_t *datain) //----------------------------------------------------------------------------- void MifareWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { - // params - uint8_t blockNo = arg0; - uint8_t keyType = arg1; - uint64_t ui64Key = 0; - byte_t blockdata[16] = {0x00}; + // params + uint8_t blockNo = arg0; + uint8_t keyType = arg1; + uint64_t ui64Key = 0; + byte_t blockdata[16] = {0x00}; - ui64Key = bytes_to_num(datain, 6); - memcpy(blockdata, datain + 10, 16); + ui64Key = bytes_to_num(datain, 6); + memcpy(blockdata, datain + 10, 16); - // variables - byte_t isOK = 0; - uint8_t uid[10] = {0x00}; - uint32_t cuid = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; + // variables + byte_t isOK = 0; + uint8_t uid[10] = {0x00}; + uint32_t cuid = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); + clear_trace(); + set_tracing(true); - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); - while (true) { - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - break; - }; + while (true) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + break; + }; - if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); - break; - }; + if(mifare_classic_auth(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); + break; + }; - if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); - break; - }; + if(mifare_classic_writeblock(pcs, cuid, blockNo, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + break; + }; - if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - break; - }; + if(mifare_classic_halt(pcs, cuid)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + break; + }; - isOK = 1; - break; - } + isOK = 1; + break; + } - crypto1_destroy(pcs); + crypto1_destroy(pcs); - if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); + if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); - cmd_send(CMD_ACK,isOK,0,0,0,0); + cmd_send(CMD_ACK,isOK,0,0,0,0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); } /* // Command not needed but left for future testing void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain) { - uint8_t blockNo = arg0; - byte_t blockdata[16] = {0x00}; + uint8_t blockNo = arg0; + byte_t blockdata[16] = {0x00}; - memcpy(blockdata, datain, 16); + memcpy(blockdata, datain, 16); - uint8_t uid[10] = {0x00}; + uint8_t uid[10] = {0x00}; - LED_A_ON(); LED_B_OFF(); LED_C_OFF(); + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - clear_trace(); - set_tracing(true); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + clear_trace(); + set_tracing(true); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - if(!iso14443a_select_card(uid, NULL, NULL, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - OnError(0); - return; - }; + if(!iso14443a_select_card(uid, NULL, NULL, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + OnError(0); + return; + }; - if(mifare_ultra_writeblock_compat(blockNo, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); - OnError(0); - return; }; + if(mifare_ultra_writeblock_compat(blockNo, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(0); + return; }; - if(mifare_ultra_halt()) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - OnError(0); - return; - }; + if(mifare_ultra_halt()) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + OnError(0); + return; + }; - if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); + if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); - cmd_send(CMD_ACK,1,0,0,0,0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + cmd_send(CMD_ACK,1,0,0,0,0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); } */ @@ -477,238 +477,238 @@ void MifareUWriteBlockCompat(uint8_t arg0, uint8_t *datain) // : 4/16 next bytes is authentication key. void MifareUWriteBlock(uint8_t arg0, uint8_t arg1, uint8_t *datain) { - uint8_t blockNo = arg0; - bool useKey = (arg1 == 1); //UL_C - bool usePwd = (arg1 == 2); //UL_EV1/NTAG - byte_t blockdata[4] = {0x00}; + uint8_t blockNo = arg0; + bool useKey = (arg1 == 1); //UL_C + bool usePwd = (arg1 == 2); //UL_EV1/NTAG + byte_t blockdata[4] = {0x00}; - memcpy(blockdata, datain, 4); + memcpy(blockdata, datain, 4); - LEDsoff(); - LED_A_ON(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + LEDsoff(); + LED_A_ON(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); + clear_trace(); + set_tracing(true); - if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - OnError(0); - return; - }; + if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + OnError(0); + return; + }; - // UL-C authentication - if ( useKey ) { - uint8_t key[16] = {0x00}; - memcpy(key, datain+4, sizeof(key) ); + // UL-C authentication + if ( useKey ) { + uint8_t key[16] = {0x00}; + memcpy(key, datain+4, sizeof(key) ); - if ( !mifare_ultra_auth(key) ) { - OnError(1); - return; - } - } + if ( !mifare_ultra_auth(key) ) { + OnError(1); + return; + } + } - // UL-EV1 / NTAG authentication - if (usePwd) { - uint8_t pwd[4] = {0x00}; - memcpy(pwd, datain+4, 4); - uint8_t pack[4] = {0,0,0,0}; - if (!mifare_ul_ev1_auth(pwd, pack)) { - OnError(1); - return; - } - } + // UL-EV1 / NTAG authentication + if (usePwd) { + uint8_t pwd[4] = {0x00}; + memcpy(pwd, datain+4, 4); + uint8_t pack[4] = {0,0,0,0}; + if (!mifare_ul_ev1_auth(pwd, pack)) { + OnError(1); + return; + } + } - if (mifare_ultra_writeblock(blockNo, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); - OnError(0); - return; - }; + if (mifare_ultra_writeblock(blockNo, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(0); + return; + }; - if (mifare_ultra_halt()) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - OnError(0); - return; - }; + if (mifare_ultra_halt()) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + OnError(0); + return; + }; - if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); + if (MF_DBGLEVEL >= 2) DbpString("WRITE BLOCK FINISHED"); - cmd_send(CMD_ACK,1,0,0,0,0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); + cmd_send(CMD_ACK,1,0,0,0,0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); } void MifareUSetPwd(uint8_t arg0, uint8_t *datain){ - uint8_t pwd[16] = {0x00}; - byte_t blockdata[4] = {0x00}; + uint8_t pwd[16] = {0x00}; + byte_t blockdata[4] = {0x00}; - memcpy(pwd, datain, 16); + memcpy(pwd, datain, 16); - LED_A_ON(); LED_B_OFF(); LED_C_OFF(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + LED_A_ON(); LED_B_OFF(); LED_C_OFF(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); + clear_trace(); + set_tracing(true); - if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - OnError(0); - return; - }; + if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + OnError(0); + return; + }; - blockdata[0] = pwd[7]; - blockdata[1] = pwd[6]; - blockdata[2] = pwd[5]; - blockdata[3] = pwd[4]; - if (mifare_ultra_writeblock( 44, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); - OnError(44); - return; - }; + blockdata[0] = pwd[7]; + blockdata[1] = pwd[6]; + blockdata[2] = pwd[5]; + blockdata[3] = pwd[4]; + if (mifare_ultra_writeblock( 44, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(44); + return; + }; - blockdata[0] = pwd[3]; - blockdata[1] = pwd[2]; - blockdata[2] = pwd[1]; - blockdata[3] = pwd[0]; - if (mifare_ultra_writeblock( 45, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); - OnError(45); - return; - }; + blockdata[0] = pwd[3]; + blockdata[1] = pwd[2]; + blockdata[2] = pwd[1]; + blockdata[3] = pwd[0]; + if (mifare_ultra_writeblock( 45, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(45); + return; + }; - blockdata[0] = pwd[15]; - blockdata[1] = pwd[14]; - blockdata[2] = pwd[13]; - blockdata[3] = pwd[12]; - if (mifare_ultra_writeblock( 46, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); - OnError(46); - return; - }; + blockdata[0] = pwd[15]; + blockdata[1] = pwd[14]; + blockdata[2] = pwd[13]; + blockdata[3] = pwd[12]; + if (mifare_ultra_writeblock( 46, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(46); + return; + }; - blockdata[0] = pwd[11]; - blockdata[1] = pwd[10]; - blockdata[2] = pwd[9]; - blockdata[3] = pwd[8]; - if (mifare_ultra_writeblock( 47, blockdata)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); - OnError(47); - return; - }; + blockdata[0] = pwd[11]; + blockdata[1] = pwd[10]; + blockdata[2] = pwd[9]; + blockdata[3] = pwd[8]; + if (mifare_ultra_writeblock( 47, blockdata)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Write block error"); + OnError(47); + return; + }; - if (mifare_ultra_halt()) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - OnError(0); - return; - }; + if (mifare_ultra_halt()) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + OnError(0); + return; + }; - cmd_send(CMD_ACK,1,0,0,0,0); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); + cmd_send(CMD_ACK,1,0,0,0,0); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); } // Return 1 if the nonce is invalid else return 0 int valid_nonce(uint32_t Nt, uint32_t NtEnc, uint32_t Ks1, uint8_t *parity) { - return ((oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \ - (oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \ - (oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0; + return ((oddparity8((Nt >> 24) & 0xFF) == ((parity[0]) ^ oddparity8((NtEnc >> 24) & 0xFF) ^ BIT(Ks1,16))) & \ + (oddparity8((Nt >> 16) & 0xFF) == ((parity[1]) ^ oddparity8((NtEnc >> 16) & 0xFF) ^ BIT(Ks1,8))) & \ + (oddparity8((Nt >> 8) & 0xFF) == ((parity[2]) ^ oddparity8((NtEnc >> 8) & 0xFF) ^ BIT(Ks1,0)))) ? 1 : 0; } void MifareAcquireNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain) { - uint8_t uid[10] = {0x00}; - uint8_t answer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t par[1] = {0x00}; - uint8_t buf[USB_CMD_DATA_SIZE] = {0x00}; - uint32_t cuid = 0; - int16_t isOK = 0; - uint16_t num_nonces = 0; - uint8_t cascade_levels = 0; - uint8_t blockNo = arg0 & 0xff; - uint8_t keyType = (arg0 >> 8) & 0xff; - bool initialize = flags & 0x0001; - bool field_off = flags & 0x0004; - bool have_uid = false; + uint8_t uid[10] = {0x00}; + uint8_t answer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t par[1] = {0x00}; + uint8_t buf[USB_CMD_DATA_SIZE] = {0x00}; + uint32_t cuid = 0; + int16_t isOK = 0; + uint16_t num_nonces = 0; + uint8_t cascade_levels = 0; + uint8_t blockNo = arg0 & 0xff; + uint8_t keyType = (arg0 >> 8) & 0xff; + bool initialize = flags & 0x0001; + bool field_off = flags & 0x0004; + bool have_uid = false; - LED_A_ON(); - LED_C_OFF(); + LED_A_ON(); + LED_C_OFF(); - BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); - set_tracing(true); + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); - if (initialize) - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + if (initialize) + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - LED_C_ON(); + LED_C_ON(); - for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE-4; i += 4 ) { + for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE-4; i += 4 ) { - // Test if the action was cancelled - if (BUTTON_PRESS()) { - isOK = 2; - field_off = true; - break; - } + // Test if the action was cancelled + if (BUTTON_PRESS()) { + isOK = 2; + field_off = true; + break; + } - if (!have_uid) { // need a full select cycle to get the uid first - iso14a_card_select_t card_info; - if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); - continue; - } - switch (card_info.uidlen) { - case 4 : cascade_levels = 1; break; - case 7 : cascade_levels = 2; break; - case 10: cascade_levels = 3; break; - default: break; - } - have_uid = true; - } else { // no need for anticollision. We can directly select the card - if (!iso14443a_fast_select_card(uid, cascade_levels)) { - if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); - continue; - } - } + if (!have_uid) { // need a full select cycle to get the uid first + iso14a_card_select_t card_info; + if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); + continue; + } + switch (card_info.uidlen) { + case 4 : cascade_levels = 1; break; + case 7 : cascade_levels = 2; break; + case 10: cascade_levels = 3; break; + default: break; + } + have_uid = true; + } else { // no need for anticollision. We can directly select the card + if (!iso14443a_fast_select_card(uid, cascade_levels)) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); + continue; + } + } - // Transmit MIFARE_CLASSIC_AUTH - uint8_t dcmd[4] = {0x60 + (keyType & 0x01), blockNo, 0x00, 0x00}; - AddCrc14A(dcmd, 2); - ReaderTransmit(dcmd, sizeof(dcmd), NULL); - int len = ReaderReceive(answer, par); + // Transmit MIFARE_CLASSIC_AUTH + uint8_t dcmd[4] = {0x60 + (keyType & 0x01), blockNo, 0x00, 0x00}; + AddCrc14A(dcmd, 2); + ReaderTransmit(dcmd, sizeof(dcmd), NULL); + int len = ReaderReceive(answer, par); - // wait for the card to become ready again - CHK_TIMEOUT(); + // wait for the card to become ready again + CHK_TIMEOUT(); - if (len != 4) { - if (MF_DBGLEVEL >= 2) Dbprintf("AcquireNonces: Auth1 error"); - continue; - } + if (len != 4) { + if (MF_DBGLEVEL >= 2) Dbprintf("AcquireNonces: Auth1 error"); + continue; + } - num_nonces++; + num_nonces++; - // Save the tag nonce (nt) - buf[i] = answer[0]; - buf[i+1] = answer[1]; - buf[i+2] = answer[2]; - buf[i+3] = answer[3]; - } + // Save the tag nonce (nt) + buf[i] = answer[0]; + buf[i+1] = answer[1]; + buf[i+2] = answer[2]; + buf[i+3] = answer[3]; + } - LED_C_OFF(); - LED_B_ON(); - cmd_send(CMD_ACK, isOK, cuid, num_nonces-1, buf, sizeof(buf)); - LED_B_OFF(); + LED_C_OFF(); + LED_B_ON(); + cmd_send(CMD_ACK, isOK, cuid, num_nonces-1, buf, sizeof(buf)); + LED_B_OFF(); - if (MF_DBGLEVEL >= 3) DbpString("AcquireNonces finished"); + if (MF_DBGLEVEL >= 3) DbpString("AcquireNonces finished"); - if (field_off) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); - } + if (field_off) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); + } } //----------------------------------------------------------------------------- @@ -719,116 +719,116 @@ void MifareAcquireNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t * //----------------------------------------------------------------------------- void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, uint8_t *datain) { - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; - uint8_t uid[10] = {0x00}; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t par_enc[1] = {0x00}; - uint8_t buf[USB_CMD_DATA_SIZE] = {0x00}; + uint8_t uid[10] = {0x00}; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t par_enc[1] = {0x00}; + uint8_t buf[USB_CMD_DATA_SIZE] = {0x00}; - uint64_t ui64Key = bytes_to_num(datain, 6); - uint32_t cuid = 0; - int16_t isOK = 0; - uint16_t num_nonces = 0; - uint8_t nt_par_enc = 0; - uint8_t cascade_levels = 0; - uint8_t blockNo = arg0 & 0xff; - uint8_t keyType = (arg0 >> 8) & 0xff; - uint8_t targetBlockNo = arg1 & 0xff; - uint8_t targetKeyType = (arg1 >> 8) & 0xff; - bool initialize = flags & 0x0001; - bool slow = flags & 0x0002; - bool field_off = flags & 0x0004; - bool have_uid = false; + uint64_t ui64Key = bytes_to_num(datain, 6); + uint32_t cuid = 0; + int16_t isOK = 0; + uint16_t num_nonces = 0; + uint8_t nt_par_enc = 0; + uint8_t cascade_levels = 0; + uint8_t blockNo = arg0 & 0xff; + uint8_t keyType = (arg0 >> 8) & 0xff; + uint8_t targetBlockNo = arg1 & 0xff; + uint8_t targetKeyType = (arg1 >> 8) & 0xff; + bool initialize = flags & 0x0001; + bool slow = flags & 0x0002; + bool field_off = flags & 0x0004; + bool have_uid = false; - LED_A_ON(); - LED_C_OFF(); + LED_A_ON(); + LED_C_OFF(); - BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); - set_tracing(false); + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(false); - if (initialize) - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + if (initialize) + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - LED_C_ON(); + LED_C_ON(); - for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE - 9; ) { + for (uint16_t i = 0; i <= USB_CMD_DATA_SIZE - 9; ) { - // Test if the action was cancelled - if(BUTTON_PRESS()) { - isOK = 2; - field_off = true; - break; - } + // Test if the action was cancelled + if(BUTTON_PRESS()) { + isOK = 2; + field_off = true; + break; + } - if (!have_uid) { // need a full select cycle to get the uid first - iso14a_card_select_t card_info; - if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); - continue; - } - switch (card_info.uidlen) { - case 4 : cascade_levels = 1; break; - case 7 : cascade_levels = 2; break; - case 10: cascade_levels = 3; break; - default: break; - } - have_uid = true; - } else { // no need for anticollision. We can directly select the card - if (!iso14443a_fast_select_card(uid, cascade_levels)) { - if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); - continue; - } - } + if (!have_uid) { // need a full select cycle to get the uid first + iso14a_card_select_t card_info; + if(!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (ALL)"); + continue; + } + switch (card_info.uidlen) { + case 4 : cascade_levels = 1; break; + case 7 : cascade_levels = 2; break; + case 10: cascade_levels = 3; break; + default: break; + } + have_uid = true; + } else { // no need for anticollision. We can directly select the card + if (!iso14443a_fast_select_card(uid, cascade_levels)) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Can't select card (UID)"); + continue; + } + } - if (slow) - SpinDelayUs(HARDNESTED_PRE_AUTHENTICATION_LEADTIME); + if (slow) + SpinDelayUs(HARDNESTED_PRE_AUTHENTICATION_LEADTIME); - uint32_t nt1; - if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) { - if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error"); - continue; - } + uint32_t nt1; + if (mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, NULL)) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth1 error"); + continue; + } - // nested authentication - uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL); + // nested authentication + uint16_t len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par_enc, NULL); - // wait for the card to become ready again - CHK_TIMEOUT(); + // wait for the card to become ready again + CHK_TIMEOUT(); - if (len != 4) { - if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len); - continue; - } + if (len != 4) { + if (MF_DBGLEVEL >= 1) Dbprintf("AcquireNonces: Auth2 error len=%d", len); + continue; + } - num_nonces++; - if (num_nonces % 2) { - memcpy(buf+i, receivedAnswer, 4); - nt_par_enc = par_enc[0] & 0xf0; - } else { - nt_par_enc |= par_enc[0] >> 4; - memcpy(buf+i+4, receivedAnswer, 4); - memcpy(buf+i+8, &nt_par_enc, 1); - i += 9; - } - } + num_nonces++; + if (num_nonces % 2) { + memcpy(buf+i, receivedAnswer, 4); + nt_par_enc = par_enc[0] & 0xf0; + } else { + nt_par_enc |= par_enc[0] >> 4; + memcpy(buf+i+4, receivedAnswer, 4); + memcpy(buf+i+8, &nt_par_enc, 1); + i += 9; + } + } - LED_C_OFF(); - crypto1_destroy(pcs); - LED_B_ON(); - cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf)); - LED_B_OFF(); + LED_C_OFF(); + crypto1_destroy(pcs); + LED_B_ON(); + cmd_send(CMD_ACK, isOK, cuid, num_nonces, buf, sizeof(buf)); + LED_B_OFF(); - if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished"); + if (MF_DBGLEVEL >= 3) DbpString("AcquireEncryptedNonces finished"); - if (field_off) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); - } + if (field_off) { + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); + } } @@ -838,215 +838,215 @@ void MifareAcquireEncryptedNonces(uint32_t arg0, uint32_t arg1, uint32_t flags, //----------------------------------------------------------------------------- void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *datain) { - // params - uint8_t blockNo = arg0 & 0xff; - uint8_t keyType = (arg0 >> 8) & 0xff; - uint8_t targetBlockNo = arg1 & 0xff; - uint8_t targetKeyType = (arg1 >> 8) & 0xff; - uint64_t ui64Key = 0; + // params + uint8_t blockNo = arg0 & 0xff; + uint8_t keyType = (arg0 >> 8) & 0xff; + uint8_t targetBlockNo = arg1 & 0xff; + uint8_t targetKeyType = (arg1 >> 8) & 0xff; + uint64_t ui64Key = 0; - ui64Key = bytes_to_num(datain, 6); + ui64Key = bytes_to_num(datain, 6); - // variables - uint16_t rtr, i, j, len; - uint16_t davg = 0; - static uint16_t dmin, dmax; - uint8_t uid[10] = {0x00}; - uint32_t cuid = 0, nt1, nt2, nttmp, nttest, ks1; - uint8_t par[1] = {0x00}; - uint32_t target_nt[2] = {0x00}, target_ks[2] = {0x00}; + // variables + uint16_t rtr, i, j, len; + uint16_t davg = 0; + static uint16_t dmin, dmax; + uint8_t uid[10] = {0x00}; + uint32_t cuid = 0, nt1, nt2, nttmp, nttest, ks1; + uint8_t par[1] = {0x00}; + uint32_t target_nt[2] = {0x00}, target_ks[2] = {0x00}; - uint8_t par_array[4] = {0x00}; - uint16_t ncount = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t par_array[4] = {0x00}; + uint16_t ncount = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint32_t auth1_time, auth2_time; - static uint16_t delta_time = 0; + uint32_t auth1_time, auth2_time; + static uint16_t delta_time = 0; - LED_A_ON(); - LED_C_OFF(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + LED_A_ON(); + LED_C_OFF(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - // free eventually allocated BigBuf memory - BigBuf_free(); BigBuf_Clear_ext(false); + // free eventually allocated BigBuf memory + BigBuf_free(); BigBuf_Clear_ext(false); - if (calibrate) clear_trace(); - set_tracing(true); + if (calibrate) clear_trace(); + set_tracing(true); - // statistics on nonce distance - int16_t isOK = 0; - #define NESTED_MAX_TRIES 12 - uint16_t unsuccessfull_tries = 0; - if (calibrate) { // for first call only. Otherwise reuse previous calibration - LED_B_ON(); - WDT_HIT(); + // statistics on nonce distance + int16_t isOK = 0; + #define NESTED_MAX_TRIES 12 + uint16_t unsuccessfull_tries = 0; + if (calibrate) { // for first call only. Otherwise reuse previous calibration + LED_B_ON(); + WDT_HIT(); - davg = dmax = 0; - dmin = 2000; - delta_time = 0; + davg = dmax = 0; + dmin = 2000; + delta_time = 0; - for (rtr = 0; rtr < 17; rtr++) { + for (rtr = 0; rtr < 17; rtr++) { - // Test if the action was cancelled - if(BUTTON_PRESS()) { - isOK = -2; - break; - } + // Test if the action was cancelled + if(BUTTON_PRESS()) { + isOK = -2; + break; + } - // prepare next select. No need to power down the card. - if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Halt error"); - rtr--; - continue; - } + // prepare next select. No need to power down the card. + if(mifare_classic_halt(pcs, cuid)) { + if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Halt error"); + rtr--; + continue; + } - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Can't select card"); - rtr--; - continue; - }; + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Can't select card"); + rtr--; + continue; + }; - auth1_time = 0; - if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) { - if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth1 error"); - rtr--; - continue; - }; - auth2_time = (delta_time) ? auth1_time + delta_time : 0; + auth1_time = 0; + if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) { + if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth1 error"); + rtr--; + continue; + }; + auth2_time = (delta_time) ? auth1_time + delta_time : 0; - if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2, &auth2_time)) { - if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth2 error"); - rtr--; - continue; - }; + if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_NESTED, &nt2, &auth2_time)) { + if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth2 error"); + rtr--; + continue; + }; - nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160 - for (i = 101; i < 1200; i++) { - nttmp = prng_successor(nttmp, 1); - if (nttmp == nt2) break; - } + nttmp = prng_successor(nt1, 100); //NXP Mifare is typical around 840,but for some unlicensed/compatible mifare card this can be 160 + for (i = 101; i < 1200; i++) { + nttmp = prng_successor(nttmp, 1); + if (nttmp == nt2) break; + } - if (i != 1200) { - if (rtr != 0) { - davg += i; - dmin = MIN(dmin, i); - dmax = MAX(dmax, i); - } - else { - delta_time = auth2_time - auth1_time + 32; // allow some slack for proper timing - } - if (MF_DBGLEVEL >= 3) Dbprintf("Nested: calibrating... ntdist=%d", i); - } else { - unsuccessfull_tries++; - if (unsuccessfull_tries > NESTED_MAX_TRIES) { // card isn't vulnerable to nested attack (random numbers are not predictable) - isOK = -3; - } - } - } + if (i != 1200) { + if (rtr != 0) { + davg += i; + dmin = MIN(dmin, i); + dmax = MAX(dmax, i); + } + else { + delta_time = auth2_time - auth1_time + 32; // allow some slack for proper timing + } + if (MF_DBGLEVEL >= 3) Dbprintf("Nested: calibrating... ntdist=%d", i); + } else { + unsuccessfull_tries++; + if (unsuccessfull_tries > NESTED_MAX_TRIES) { // card isn't vulnerable to nested attack (random numbers are not predictable) + isOK = -3; + } + } + } - davg = (davg + (rtr - 1)/2) / (rtr - 1); + davg = (davg + (rtr - 1)/2) / (rtr - 1); - if (MF_DBGLEVEL >= 3) Dbprintf("rtr=%d isOK=%d min=%d max=%d avg=%d, delta_time=%d", rtr, isOK, dmin, dmax, davg, delta_time); + if (MF_DBGLEVEL >= 3) Dbprintf("rtr=%d isOK=%d min=%d max=%d avg=%d, delta_time=%d", rtr, isOK, dmin, dmax, davg, delta_time); - dmin = davg - 2; - dmax = davg + 2; + dmin = davg - 2; + dmax = davg + 2; - LED_B_OFF(); - } + LED_B_OFF(); + } // ------------------------------------------------------------------------------------------------- - LED_C_ON(); + LED_C_ON(); - // get crypted nonces for target sector - for(i=0; i < 2 && !isOK; i++) { // look for exactly two different nonces + // get crypted nonces for target sector + for(i=0; i < 2 && !isOK; i++) { // look for exactly two different nonces - target_nt[i] = 0; - while(target_nt[i] == 0) { // continue until we have an unambiguous nonce + target_nt[i] = 0; + while(target_nt[i] == 0) { // continue until we have an unambiguous nonce - // prepare next select. No need to power down the card. - if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Halt error"); - continue; - } + // prepare next select. No need to power down the card. + if(mifare_classic_halt(pcs, cuid)) { + if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Halt error"); + continue; + } - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Can't select card"); - continue; - }; + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Can't select card"); + continue; + }; - auth1_time = 0; - if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) { - if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth1 error"); - continue; - }; + auth1_time = 0; + if(mifare_classic_authex(pcs, cuid, blockNo, keyType, ui64Key, AUTH_FIRST, &nt1, &auth1_time)) { + if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth1 error"); + continue; + }; - // nested authentication - auth2_time = auth1_time + delta_time; + // nested authentication + auth2_time = auth1_time + delta_time; - len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time); - if (len != 4) { - if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth2 error len=%d", len); - continue; - }; + len = mifare_sendcmd_short(pcs, AUTH_NESTED, 0x60 + (targetKeyType & 0x01), targetBlockNo, receivedAnswer, par, &auth2_time); + if (len != 4) { + if (MF_DBGLEVEL >= 2) Dbprintf("Nested: Auth2 error len=%d", len); + continue; + }; - nt2 = bytes_to_num(receivedAnswer, 4); - if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: Testing nt1=%08x nt2enc=%08x nt2par=%02x", i+1, nt1, nt2, par[0]); + nt2 = bytes_to_num(receivedAnswer, 4); + if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: Testing nt1=%08x nt2enc=%08x nt2par=%02x", i+1, nt1, nt2, par[0]); - // Parity validity check - for (j = 0; j < 4; j++) { - par_array[j] = (oddparity8(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01)); - } + // Parity validity check + for (j = 0; j < 4; j++) { + par_array[j] = (oddparity8(receivedAnswer[j]) != ((par[0] >> (7-j)) & 0x01)); + } - ncount = 0; - nttest = prng_successor(nt1, dmin - 1); - for (j = dmin; j < dmax + 1; j++) { - nttest = prng_successor(nttest, 1); - ks1 = nt2 ^ nttest; + ncount = 0; + nttest = prng_successor(nt1, dmin - 1); + for (j = dmin; j < dmax + 1; j++) { + nttest = prng_successor(nttest, 1); + ks1 = nt2 ^ nttest; - if (valid_nonce(nttest, nt2, ks1, par_array)){ - if (ncount > 0) { // we are only interested in disambiguous nonces, try again - if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (ambigous), ntdist=%d", i+1, j); - target_nt[i] = 0; - break; - } - target_nt[i] = nttest; - target_ks[i] = ks1; - ncount++; - if (i == 1 && target_nt[1] == target_nt[0]) { // we need two different nonces - target_nt[i] = 0; - if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#2: dismissed (= nonce#1), ntdist=%d", j); - break; - } - if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: valid, ntdist=%d", i+1, j); - } - } - if (target_nt[i] == 0 && j == dmax+1 && MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (all invalid)", i+1); - } - } + if (valid_nonce(nttest, nt2, ks1, par_array)){ + if (ncount > 0) { // we are only interested in disambiguous nonces, try again + if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (ambigous), ntdist=%d", i+1, j); + target_nt[i] = 0; + break; + } + target_nt[i] = nttest; + target_ks[i] = ks1; + ncount++; + if (i == 1 && target_nt[1] == target_nt[0]) { // we need two different nonces + target_nt[i] = 0; + if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#2: dismissed (= nonce#1), ntdist=%d", j); + break; + } + if (MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: valid, ntdist=%d", i+1, j); + } + } + if (target_nt[i] == 0 && j == dmax+1 && MF_DBGLEVEL >= 3) Dbprintf("Nonce#%d: dismissed (all invalid)", i+1); + } + } - LED_C_OFF(); + LED_C_OFF(); - crypto1_destroy(pcs); + crypto1_destroy(pcs); - uint8_t buf[4 + 4 * 4] = {0}; - memcpy(buf, &cuid, 4); - memcpy(buf+4, &target_nt[0], 4); - memcpy(buf+8, &target_ks[0], 4); - memcpy(buf+12, &target_nt[1], 4); - memcpy(buf+16, &target_ks[1], 4); + uint8_t buf[4 + 4 * 4] = {0}; + memcpy(buf, &cuid, 4); + memcpy(buf+4, &target_nt[0], 4); + memcpy(buf+8, &target_ks[0], 4); + memcpy(buf+12, &target_nt[1], 4); + memcpy(buf+16, &target_ks[1], 4); - LED_B_ON(); - cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf)); - LED_B_OFF(); + LED_B_ON(); + cmd_send(CMD_ACK, isOK, 0, targetBlockNo + (targetKeyType * 0x100), buf, sizeof(buf)); + LED_B_OFF(); - if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED"); + if (MF_DBGLEVEL >= 3) DbpString("NESTED FINISHED"); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); } //----------------------------------------------------------------------------- @@ -1054,18 +1054,18 @@ void MifareNested(uint32_t arg0, uint32_t arg1, uint32_t calibrate, uint8_t *dat // //----------------------------------------------------------------------------- typedef struct sector_t { - uint8_t keyA[6]; - uint8_t keyB[6]; + uint8_t keyA[6]; + uint8_t keyB[6]; } sector_t; typedef struct chk_t { - uint64_t key; - uint32_t cuid; - uint8_t cl; - uint8_t block; - uint8_t keyType; - uint8_t *uid; - struct Crypto1State *pcs; + uint64_t key; + uint32_t cuid; + uint8_t cl; + uint8_t block; + uint8_t keyType; + uint8_t *uid; + struct Crypto1State *pcs; } chk_t; // checks one key. @@ -1076,117 +1076,117 @@ typedef struct chk_t { // 1 = wrong key // 0 = correct key uint8_t chkKey( struct chk_t *c ) { - uint8_t i = 0, res = 2; - while( i < 5 ) { - // this part is from Piwi's faster nonce collecting part in Hardnested. - // assume: fast select - if (!iso14443a_fast_select_card(c->uid, c->cl)) { - ++i; - continue; - } - res = mifare_classic_authex(c->pcs, c->cuid, c->block, c->keyType, c->key, AUTH_FIRST, NULL, NULL); + uint8_t i = 0, res = 2; + while( i < 5 ) { + // this part is from Piwi's faster nonce collecting part in Hardnested. + // assume: fast select + if (!iso14443a_fast_select_card(c->uid, c->cl)) { + ++i; + continue; + } + res = mifare_classic_authex(c->pcs, c->cuid, c->block, c->keyType, c->key, AUTH_FIRST, NULL, NULL); - CHK_TIMEOUT(); + CHK_TIMEOUT(); - // if successfull auth, send HALT - // if ( !res ) - // mifare_classic_halt_ex(c->pcs); - break; - } - return res; + // if successfull auth, send HALT + // if ( !res ) + // mifare_classic_halt_ex(c->pcs); + break; + } + return res; } uint8_t chkKey_readb(struct chk_t *c, uint8_t *keyb) { - if (!iso14443a_fast_select_card(c->uid, c->cl)) - return 2; + if (!iso14443a_fast_select_card(c->uid, c->cl)) + return 2; - if ( mifare_classic_authex(c->pcs, c->cuid, c->block, 0, c->key, AUTH_FIRST, NULL, NULL) ) - return 1; + if ( mifare_classic_authex(c->pcs, c->cuid, c->block, 0, c->key, AUTH_FIRST, NULL, NULL) ) + return 1; - uint8_t data[16] = {0x00}; - uint8_t res = mifare_classic_readblock(c->pcs, c->cuid, c->block, data); + uint8_t data[16] = {0x00}; + uint8_t res = mifare_classic_readblock(c->pcs, c->cuid, c->block, data); - // successful read - if ( !res ) { - // data was something else than zeros. - if ( memcmp(data+10, "\x00\x00\x00\x00\x00\x00", 6) != 0) { - memcpy(keyb, data+10, 6); - res = 0; - } else { - res = 3; - } - mifare_classic_halt_ex(c->pcs); - } - return res; + // successful read + if ( !res ) { + // data was something else than zeros. + if ( memcmp(data+10, "\x00\x00\x00\x00\x00\x00", 6) != 0) { + memcpy(keyb, data+10, 6); + res = 0; + } else { + res = 3; + } + mifare_classic_halt_ex(c->pcs); + } + return res; } void chkKey_scanA(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { - for (uint8_t s = 0; s < *sectorcnt; s++) { + for (uint8_t s = 0; s < *sectorcnt; s++) { - // skip already found A keys - if ( found[(s*2)] ) - continue; + // skip already found A keys + if ( found[(s*2)] ) + continue; - c->block = FirstBlockOfSector( s ); - if ( chkKey( c ) == 0 ) { - num_to_bytes(c->key, 6, k_sector[s].keyA); - found[(s*2)] = 1; - ++*foundkeys; + c->block = FirstBlockOfSector( s ); + if ( chkKey( c ) == 0 ) { + num_to_bytes(c->key, 6, k_sector[s].keyA); + found[(s*2)] = 1; + ++*foundkeys; - if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan A found (%d)", c->block); - } - } + if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan A found (%d)", c->block); + } + } } void chkKey_scanB(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { - for (uint8_t s = 0; s < *sectorcnt; s++) { + for (uint8_t s = 0; s < *sectorcnt; s++) { - // skip already found B keys - if ( found[(s*2)+1] ) - continue; + // skip already found B keys + if ( found[(s*2)+1] ) + continue; - c->block = FirstBlockOfSector( s ); - if ( chkKey( c ) == 0 ) { - num_to_bytes(c->key, 6, k_sector[s].keyB); - found[(s*2)+1] = 1; - ++*foundkeys; + c->block = FirstBlockOfSector( s ); + if ( chkKey( c ) == 0 ) { + num_to_bytes(c->key, 6, k_sector[s].keyB); + found[(s*2)+1] = 1; + ++*foundkeys; - if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan B found (%d)", c->block); - } - } + if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Scan B found (%d)", c->block); + } + } } // loop all A keys, // when A is found but not B, try to read B. void chkKey_loopBonly(struct chk_t *c, struct sector_t *k_sector, uint8_t *found, uint8_t *sectorcnt, uint8_t *foundkeys) { - // read Block B, if A is found. - for (uint8_t s = 0; s < *sectorcnt; ++s) { + // read Block B, if A is found. + for (uint8_t s = 0; s < *sectorcnt; ++s) { - if ( found[(s*2)] && found[(s*2)+1] ) - continue; + if ( found[(s*2)] && found[(s*2)+1] ) + continue; - c->block = (FirstBlockOfSector( s ) + NumBlocksPerSector( s ) - 1); + c->block = (FirstBlockOfSector( s ) + NumBlocksPerSector( s ) - 1); - // A but not B - if ( found[(s*2)] && !found[(s*2)+1] ){ - c->key = bytes_to_num(k_sector[s].keyA, 6); - uint8_t status = chkKey_readb(c, k_sector[s].keyB); - if ( status == 0 ){ - found[(s*2)+1] = 1; - ++*foundkeys; + // A but not B + if ( found[(s*2)] && !found[(s*2)+1] ){ + c->key = bytes_to_num(k_sector[s].keyA, 6); + uint8_t status = chkKey_readb(c, k_sector[s].keyB); + if ( status == 0 ){ + found[(s*2)+1] = 1; + ++*foundkeys; - if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Reading B found (%d)", c->block); + if (MF_DBGLEVEL >= 3) Dbprintf("ChkKeys_fast: Reading B found (%d)", c->block); - // try quick find all B? - // assume: keys comes in groups. Find one B, test against all B. - c->key = bytes_to_num( k_sector[s].keyB, 6); - c->keyType = 1; - chkKey_scanB(c, k_sector, found, sectorcnt, foundkeys); - } - } - } + // try quick find all B? + // assume: keys comes in groups. Find one B, test against all B. + c->key = bytes_to_num( k_sector[s].keyB, 6); + c->keyType = 1; + chkKey_scanB(c, k_sector, found, sectorcnt, foundkeys); + } + } + } } @@ -1199,376 +1199,376 @@ void chkKey_loopBonly(struct chk_t *c, struct sector_t *k_sector, uint8_t *found // datain = keys as array void MifareChkKeys_fast(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) { - // first call or - uint8_t sectorcnt = arg0 & 0xFF; // 16; - uint8_t firstchunk = (arg0 >> 8) & 0xF; - uint8_t lastchunk = (arg0 >> 12) & 0xF; - uint8_t strategy = arg1 & 0xFF; - uint8_t use_flashmem = (arg1 >> 8) & 0xFF; - uint16_t keyCount = arg2 & 0xFF; - uint8_t status = 0; + // first call or + uint8_t sectorcnt = arg0 & 0xFF; // 16; + uint8_t firstchunk = (arg0 >> 8) & 0xF; + uint8_t lastchunk = (arg0 >> 12) & 0xF; + uint8_t strategy = arg1 & 0xFF; + uint8_t use_flashmem = (arg1 >> 8) & 0xFF; + uint16_t keyCount = arg2 & 0xFF; + uint8_t status = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; - struct chk_t chk_data; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; + struct chk_t chk_data; - uint8_t allkeys = sectorcnt << 1; + uint8_t allkeys = sectorcnt << 1; - static uint32_t cuid = 0; - static uint8_t cascade_levels = 0; - static uint8_t foundkeys = 0; - static sector_t k_sector[80]; - static uint8_t found[80]; - static uint8_t *uid; + static uint32_t cuid = 0; + static uint8_t cascade_levels = 0; + static uint8_t foundkeys = 0; + static sector_t k_sector[80]; + static uint8_t found[80]; + static uint8_t *uid; #ifdef WITH_FLASH - if ( use_flashmem ) { - BigBuf_free(); - uint16_t isok = 0; - uint8_t size[2] = {0x00, 0x00}; - isok = Flash_ReadData(DEFAULT_MF_KEYS_OFFSET, size, 2); - if ( isok != 2 ) - goto OUT; + if ( use_flashmem ) { + BigBuf_free(); + uint16_t isok = 0; + uint8_t size[2] = {0x00, 0x00}; + isok = Flash_ReadData(DEFAULT_MF_KEYS_OFFSET, size, 2); + if ( isok != 2 ) + goto OUT; - keyCount = size[1] << 8 | size[0]; + keyCount = size[1] << 8 | size[0]; - if ( keyCount == 0 && keyCount == 0xFFFF) - goto OUT; + if ( keyCount == 0 && keyCount == 0xFFFF) + goto OUT; - datain = BigBuf_malloc( keyCount * 6); - if (datain == NULL ) - goto OUT; + datain = BigBuf_malloc( keyCount * 6); + if (datain == NULL ) + goto OUT; - isok = Flash_ReadData(DEFAULT_MF_KEYS_OFFSET+2, datain, keyCount * 6); - if ( isok != keyCount * 6 ) - goto OUT; + isok = Flash_ReadData(DEFAULT_MF_KEYS_OFFSET+2, datain, keyCount * 6); + if ( isok != keyCount * 6 ) + goto OUT; - } + } #endif - if (uid == NULL || firstchunk) { - uid = BigBuf_malloc(10); - if (uid == NULL ) - goto OUT; - } + if (uid == NULL || firstchunk) { + uid = BigBuf_malloc(10); + if (uid == NULL ) + goto OUT; + } - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - LEDsoff(); - LED_A_ON(); + LEDsoff(); + LED_A_ON(); - if ( firstchunk ) { - clear_trace(); - set_tracing(false); + if ( firstchunk ) { + clear_trace(); + set_tracing(false); - memset(k_sector, 0x00, 480+10); - memset(found, 0x00, sizeof(found)); - foundkeys = 0; + memset(k_sector, 0x00, 480+10); + memset(found, 0x00, sizeof(found)); + foundkeys = 0; - iso14a_card_select_t card_info; - if ( !iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys_fast: Can't select card (ALL)"); - goto OUT; - } + iso14a_card_select_t card_info; + if ( !iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys_fast: Can't select card (ALL)"); + goto OUT; + } - switch (card_info.uidlen) { - case 4 : cascade_levels = 1; break; - case 7 : cascade_levels = 2; break; - case 10: cascade_levels = 3; break; - default: break; - } + switch (card_info.uidlen) { + case 4 : cascade_levels = 1; break; + case 7 : cascade_levels = 2; break; + case 10: cascade_levels = 3; break; + default: break; + } - CHK_TIMEOUT(); - } + CHK_TIMEOUT(); + } - // set check struct. - chk_data.uid = uid; - chk_data.cuid = cuid; - chk_data.cl = cascade_levels; - chk_data.pcs = pcs; - chk_data.block = 0; + // set check struct. + chk_data.uid = uid; + chk_data.cuid = cuid; + chk_data.cl = cascade_levels; + chk_data.pcs = pcs; + chk_data.block = 0; - // keychunk loop - depth first one sector. - if ( strategy == 1 || use_flashmem) { + // keychunk loop - depth first one sector. + if ( strategy == 1 || use_flashmem) { - uint8_t newfound = foundkeys; + uint8_t newfound = foundkeys; - uint16_t lastpos = 0; - uint16_t s_point = 0; - // Sector main loop - // keep track of how many sectors on card. - for (uint8_t s = 0; s < sectorcnt; ++s) { + uint16_t lastpos = 0; + uint16_t s_point = 0; + // Sector main loop + // keep track of how many sectors on card. + for (uint8_t s = 0; s < sectorcnt; ++s) { - if ( found[(s*2)] && found[(s*2)+1] ) - continue; + if ( found[(s*2)] && found[(s*2)+1] ) + continue; - for (uint16_t i = s_point; i < keyCount; ++i) { + for (uint16_t i = s_point; i < keyCount; ++i) { - //if ( i % 100 == 0) Dbprintf("ChkKeys_fast: sector %d | checking %d | %d found | s_point %d", s, i, foundkeys, s_point); + //if ( i % 100 == 0) Dbprintf("ChkKeys_fast: sector %d | checking %d | %d found | s_point %d", s, i, foundkeys, s_point); - // Allow button press / usb cmd to interrupt device - if (BUTTON_PRESS() && !usb_poll_validate_length()) { - goto OUT; - } + // Allow button press / usb cmd to interrupt device + if (BUTTON_PRESS() && !usb_poll_validate_length()) { + goto OUT; + } - // found all keys? - if ( foundkeys == allkeys ) - goto OUT; + // found all keys? + if ( foundkeys == allkeys ) + goto OUT; - WDT_HIT(); + WDT_HIT(); - // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector - chk_data.block = FirstBlockOfSector( s ); + // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector + chk_data.block = FirstBlockOfSector( s ); - // new key - chk_data.key = bytes_to_num(datain + i * 6, 6); + // new key + chk_data.key = bytes_to_num(datain + i * 6, 6); - // skip already found A keys - if( !found[(s*2)] ) { - chk_data.keyType = 0; - status = chkKey( &chk_data); - if ( status == 0 ) { - memcpy(k_sector[s].keyA, datain + i * 6, 6); - found[(s*2)] = 1; - ++foundkeys; + // skip already found A keys + if( !found[(s*2)] ) { + chk_data.keyType = 0; + status = chkKey( &chk_data); + if ( status == 0 ) { + memcpy(k_sector[s].keyA, datain + i * 6, 6); + found[(s*2)] = 1; + ++foundkeys; - chkKey_scanA(&chk_data, k_sector, found, §orcnt, &foundkeys); + chkKey_scanA(&chk_data, k_sector, found, §orcnt, &foundkeys); - // read Block B, if A is found. - chkKey_loopBonly( &chk_data, k_sector, found, §orcnt, &foundkeys); + // read Block B, if A is found. + chkKey_loopBonly( &chk_data, k_sector, found, §orcnt, &foundkeys); - chk_data.keyType = 1; - chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); + chk_data.keyType = 1; + chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); - chk_data.keyType = 0; - chk_data.block = FirstBlockOfSector( s ); + chk_data.keyType = 0; + chk_data.block = FirstBlockOfSector( s ); - if ( use_flashmem ) { - if ( lastpos != i && lastpos != 0) { - if ( i - lastpos < 0xF) { - s_point = i & 0xFFF0; - } - } else { - lastpos = i; - } - } - } - } + if ( use_flashmem ) { + if ( lastpos != i && lastpos != 0) { + if ( i - lastpos < 0xF) { + s_point = i & 0xFFF0; + } + } else { + lastpos = i; + } + } + } + } - // skip already found B keys - if( !found[(s*2)+1] ) { - chk_data.keyType = 1; - status = chkKey( &chk_data); - if ( status == 0 ) { - memcpy(k_sector[s].keyB, datain + i * 6, 6); - found[(s*2)+1] = 1; - ++foundkeys; + // skip already found B keys + if( !found[(s*2)+1] ) { + chk_data.keyType = 1; + status = chkKey( &chk_data); + if ( status == 0 ) { + memcpy(k_sector[s].keyB, datain + i * 6, 6); + found[(s*2)+1] = 1; + ++foundkeys; - chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); + chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); - if ( use_flashmem ) { - if ( lastpos != i && lastpos != 0) { + if ( use_flashmem ) { + if ( lastpos != i && lastpos != 0) { - if ( i - lastpos < 0xF) - s_point = i & 0xFFF0; - } else { - lastpos = i; - } - } - } - } + if ( i - lastpos < 0xF) + s_point = i & 0xFFF0; + } else { + lastpos = i; + } + } + } + } - if ( found[(s*2)] && found[(s*2)+1] ) - break; + if ( found[(s*2)] && found[(s*2)+1] ) + break; - } // end keys test loop - depth first + } // end keys test loop - depth first - // assume1. if no keys found in first sector, get next keychunk from client - if ( !use_flashmem && (newfound-foundkeys == 0) ) - goto OUT; + // assume1. if no keys found in first sector, get next keychunk from client + if ( !use_flashmem && (newfound-foundkeys == 0) ) + goto OUT; - } // end loop - sector - } // end strategy 1 + } // end loop - sector + } // end strategy 1 - if ( foundkeys == allkeys ) - goto OUT; + if ( foundkeys == allkeys ) + goto OUT; - if ( strategy == 2 || use_flashmem ) { + if ( strategy == 2 || use_flashmem ) { - // Keychunk loop - for (uint16_t i = 0; i < keyCount; i++) { + // Keychunk loop + for (uint16_t i = 0; i < keyCount; i++) { - // Allow button press / usb cmd to interrupt device - if (BUTTON_PRESS() && !usb_poll_validate_length()) break; + // Allow button press / usb cmd to interrupt device + if (BUTTON_PRESS() && !usb_poll_validate_length()) break; - // found all keys? - if ( foundkeys == allkeys ) - goto OUT; + // found all keys? + if ( foundkeys == allkeys ) + goto OUT; - WDT_HIT(); + WDT_HIT(); - // new key - chk_data.key = bytes_to_num(datain + i * 6, 6); + // new key + chk_data.key = bytes_to_num(datain + i * 6, 6); - // Sector main loop - // keep track of how many sectors on card. - for (uint8_t s = 0; s < sectorcnt; ++s) { + // Sector main loop + // keep track of how many sectors on card. + for (uint8_t s = 0; s < sectorcnt; ++s) { - if ( found[(s*2)] && found[(s*2)+1] ) continue; + if ( found[(s*2)] && found[(s*2)+1] ) continue; - // found all keys? - if ( foundkeys == allkeys ) - goto OUT; + // found all keys? + if ( foundkeys == allkeys ) + goto OUT; - // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector - chk_data.block = FirstBlockOfSector( s ); + // assume: block0,1,2 has more read rights in accessbits than the sectortrailer. authenticating against block0 in each sector + chk_data.block = FirstBlockOfSector( s ); - // skip already found A keys - if( !found[(s*2)] ) { - chk_data.keyType = 0; - status = chkKey( &chk_data); - if ( status == 0 ) { - memcpy(k_sector[s].keyA, datain + i * 6, 6); - found[(s*2)] = 1; - ++foundkeys; + // skip already found A keys + if( !found[(s*2)] ) { + chk_data.keyType = 0; + status = chkKey( &chk_data); + if ( status == 0 ) { + memcpy(k_sector[s].keyA, datain + i * 6, 6); + found[(s*2)] = 1; + ++foundkeys; - chkKey_scanA( &chk_data, k_sector, found, §orcnt, &foundkeys); + chkKey_scanA( &chk_data, k_sector, found, §orcnt, &foundkeys); - // read Block B, if A is found. - chkKey_loopBonly( &chk_data, k_sector, found, §orcnt, &foundkeys); + // read Block B, if A is found. + chkKey_loopBonly( &chk_data, k_sector, found, §orcnt, &foundkeys); - chk_data.block = FirstBlockOfSector( s ); - } - } + chk_data.block = FirstBlockOfSector( s ); + } + } - // skip already found B keys - if( !found[(s*2)+1] ) { - chk_data.keyType = 1; - status = chkKey( &chk_data); - if ( status == 0 ) { - memcpy(k_sector[s].keyB, datain + i * 6, 6); - found[(s*2)+1] = 1; - ++foundkeys; + // skip already found B keys + if( !found[(s*2)+1] ) { + chk_data.keyType = 1; + status = chkKey( &chk_data); + if ( status == 0 ) { + memcpy(k_sector[s].keyB, datain + i * 6, 6); + found[(s*2)+1] = 1; + ++foundkeys; - chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); - } - } - } // end loop sectors - } // end loop keys - } // end loop strategy 2 + chkKey_scanB(&chk_data, k_sector, found, §orcnt, &foundkeys); + } + } + } // end loop sectors + } // end loop keys + } // end loop strategy 2 OUT: - LEDsoff(); + LEDsoff(); - crypto1_destroy(pcs); + crypto1_destroy(pcs); - // All keys found, send to client, or last keychunk from client - if (foundkeys == allkeys || lastchunk ) { + // All keys found, send to client, or last keychunk from client + if (foundkeys == allkeys || lastchunk ) { - uint64_t foo = 0; - for (uint8_t m = 0; m < 64; m++) { - foo |= ((uint64_t)(found[m] & 1) << m); - } + uint64_t foo = 0; + for (uint8_t m = 0; m < 64; m++) { + foo |= ((uint64_t)(found[m] & 1) << m); + } - uint16_t bar = 0; - uint8_t j = 0; - for (uint8_t m=64; m < sizeof(found); m++) { - bar |= ((uint16_t)(found[m] & 1) << j++); - } + uint16_t bar = 0; + uint8_t j = 0; + for (uint8_t m=64; m < sizeof(found); m++) { + bar |= ((uint16_t)(found[m] & 1) << j++); + } - uint8_t *tmp = BigBuf_malloc(480+10); - memcpy(tmp, k_sector, sectorcnt * sizeof(sector_t) ); - num_to_bytes(foo, 8, tmp+480); - tmp[488] = bar & 0xFF; - tmp[489] = bar >> 8 & 0xFF; + uint8_t *tmp = BigBuf_malloc(480+10); + memcpy(tmp, k_sector, sectorcnt * sizeof(sector_t) ); + num_to_bytes(foo, 8, tmp+480); + tmp[488] = bar & 0xFF; + tmp[489] = bar >> 8 & 0xFF; - cmd_send(CMD_ACK, foundkeys, 0, 0, tmp, 480+10); + cmd_send(CMD_ACK, foundkeys, 0, 0, tmp, 480+10); - set_tracing(false); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - BigBuf_free(); BigBuf_Clear_ext(false); - } else { - // partial/none keys found - cmd_send(CMD_ACK, foundkeys, 0, 0, 0, 0); - } + set_tracing(false); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + BigBuf_free(); BigBuf_Clear_ext(false); + } else { + // partial/none keys found + cmd_send(CMD_ACK, foundkeys, 0, 0, 0, 0); + } } void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; - uint8_t uid[10] = {0x00}; + uint8_t uid[10] = {0x00}; - uint64_t key = 0; - uint32_t cuid = 0; - int i, res; - uint8_t blockNo = arg0 & 0xFF; - uint8_t keyType = (arg0 >> 8) & 0xFF; - uint8_t keyCount = arg2; - uint8_t cascade_levels = 0; - uint8_t isOK = 0; - bool have_uid = false; - bool clearTrace = arg1 & 0xFF; + uint64_t key = 0; + uint32_t cuid = 0; + int i, res; + uint8_t blockNo = arg0 & 0xFF; + uint8_t keyType = (arg0 >> 8) & 0xFF; + uint8_t keyCount = arg2; + uint8_t cascade_levels = 0; + uint8_t isOK = 0; + bool have_uid = false; + bool clearTrace = arg1 & 0xFF; - LEDsoff(); - LED_A_ON(); + LEDsoff(); + LED_A_ON(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - if (clearTrace) - clear_trace(); + if (clearTrace) + clear_trace(); - set_tracing(true); + set_tracing(true); - for (i = 0; i < keyCount; i++) { + for (i = 0; i < keyCount; i++) { - // Iceman: use piwi's faster nonce collecting part in hardnested. - if (!have_uid) { // need a full select cycle to get the uid first - iso14a_card_select_t card_info; - if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (ALL)"); - --i; // try same key once again - continue; - } - switch (card_info.uidlen) { - case 4 : cascade_levels = 1; break; - case 7 : cascade_levels = 2; break; - case 10: cascade_levels = 3; break; - default: break; - } - have_uid = true; - } else { // no need for anticollision. We can directly select the card - if (!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (UID)"); - --i; // try same key once again - continue; - } - } + // Iceman: use piwi's faster nonce collecting part in hardnested. + if (!have_uid) { // need a full select cycle to get the uid first + iso14a_card_select_t card_info; + if (!iso14443a_select_card(uid, &card_info, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (ALL)"); + --i; // try same key once again + continue; + } + switch (card_info.uidlen) { + case 4 : cascade_levels = 1; break; + case 7 : cascade_levels = 2; break; + case 10: cascade_levels = 3; break; + default: break; + } + have_uid = true; + } else { // no need for anticollision. We can directly select the card + if (!iso14443a_select_card(uid, NULL, NULL, false, cascade_levels, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("ChkKeys: Can't select card (UID)"); + --i; // try same key once again + continue; + } + } - key = bytes_to_num(datain + i * 6, 6); - res = mifare_classic_auth(pcs, cuid, blockNo, keyType, key, AUTH_FIRST); + key = bytes_to_num(datain + i * 6, 6); + res = mifare_classic_auth(pcs, cuid, blockNo, keyType, key, AUTH_FIRST); - CHK_TIMEOUT(); + CHK_TIMEOUT(); - if (res) - continue; + if (res) + continue; - isOK = 1; - break; - } + isOK = 1; + break; + } - LED_B_ON(); + LED_B_ON(); cmd_send(CMD_ACK, isOK, 0, 0, datain + i * 6, 6); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); - set_tracing(false); - crypto1_destroy(pcs); + set_tracing(false); + crypto1_destroy(pcs); } //----------------------------------------------------------------------------- @@ -1576,8 +1576,8 @@ void MifareChkKeys(uint16_t arg0, uint8_t arg1, uint8_t arg2, uint8_t *datain) { // //----------------------------------------------------------------------------- void MifareSetDbgLvl(uint16_t arg0){ - MF_DBGLEVEL = arg0; - Dbprintf("Debug level: %d", MF_DBGLEVEL); + MF_DBGLEVEL = arg0; + Dbprintf("Debug level: %d", MF_DBGLEVEL); } //----------------------------------------------------------------------------- @@ -1589,24 +1589,24 @@ void MifareSetDbgLvl(uint16_t arg0){ //----------------------------------------------------------------------------- void MifareEMemClr(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - emlClearMem(); + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + emlClearMem(); } void MifareEMemSet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - if (arg2==0) arg2 = 16; // backwards compat... default bytewidth - emlSetMem_xt(datain, arg0, arg1, arg2); // data, block num, blocks count, block byte width + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + if (arg2==0) arg2 = 16; // backwards compat... default bytewidth + 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){ - FpgaDownloadAndGo(FPGA_BITSTREAM_HF); - byte_t buf[USB_CMD_DATA_SIZE] = {0x00}; - emlGetMem(buf, arg0, arg1); // data, block num, blocks count (max 4) + FpgaDownloadAndGo(FPGA_BITSTREAM_HF); + byte_t buf[USB_CMD_DATA_SIZE] = {0x00}; + emlGetMem(buf, arg0, arg1); // data, block num, blocks count (max 4) - LED_B_ON(); - cmd_send(CMD_ACK,arg0,arg1,0,buf,USB_CMD_DATA_SIZE); - LED_B_OFF(); + LED_B_ON(); + cmd_send(CMD_ACK,arg0,arg1,0,buf,USB_CMD_DATA_SIZE); + LED_B_OFF(); } //----------------------------------------------------------------------------- @@ -1614,82 +1614,82 @@ void MifareEMemGet(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain) // //----------------------------------------------------------------------------- void MifareECardLoad(uint32_t arg0, uint32_t arg1, uint32_t arg2, uint8_t *datain){ - uint8_t numSectors = arg0; - uint8_t keyType = arg1; - uint64_t ui64Key = 0; - uint32_t cuid = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs; - pcs = &mpcs; + uint8_t numSectors = arg0; + uint8_t keyType = arg1; + uint64_t ui64Key = 0; + uint32_t cuid = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs; + pcs = &mpcs; - // variables - byte_t dataoutbuf[16] = {0x00}; - byte_t dataoutbuf2[16] = {0x00}; - uint8_t uid[10] = {0x00}; + // variables + byte_t dataoutbuf[16] = {0x00}; + byte_t dataoutbuf2[16] = {0x00}; + uint8_t uid[10] = {0x00}; - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); + clear_trace(); + set_tracing(true); - bool isOK = true; + bool isOK = true; - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - isOK = false; - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - } + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + isOK = false; + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + } - for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) { - ui64Key = emlGetKey(sectorNo, keyType); - if (sectorNo == 0){ - if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { - isOK = false; - if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo); - break; - } - } else { - if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) { - isOK = false; - if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth nested error", sectorNo); - break; - } - } + for (uint8_t sectorNo = 0; isOK && sectorNo < numSectors; sectorNo++) { + ui64Key = emlGetKey(sectorNo, keyType); + if (sectorNo == 0){ + if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_FIRST)) { + isOK = false; + if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth error", sectorNo); + break; + } + } else { + if(isOK && mifare_classic_auth(pcs, cuid, FirstBlockOfSector(sectorNo), keyType, ui64Key, AUTH_NESTED)) { + isOK = false; + if (MF_DBGLEVEL >= 1) Dbprintf("Sector[%2d]. Auth nested error", sectorNo); + break; + } + } - for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { - if(isOK && mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) { - isOK = false; - if (MF_DBGLEVEL >= 1) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo); - break; - } - if (isOK) { - if (blockNo < NumBlocksPerSector(sectorNo) - 1) { - emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1); - } else { // sector trailer, keep the keys, set only the AC - emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); - memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4); - emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); - } - } - } + for (uint8_t blockNo = 0; isOK && blockNo < NumBlocksPerSector(sectorNo); blockNo++) { + if(isOK && mifare_classic_readblock(pcs, cuid, FirstBlockOfSector(sectorNo) + blockNo, dataoutbuf)) { + isOK = false; + if (MF_DBGLEVEL >= 1) Dbprintf("Error reading sector %2d block %2d", sectorNo, blockNo); + break; + } + if (isOK) { + if (blockNo < NumBlocksPerSector(sectorNo) - 1) { + emlSetMem(dataoutbuf, FirstBlockOfSector(sectorNo) + blockNo, 1); + } else { // sector trailer, keep the keys, set only the AC + emlGetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); + memcpy(&dataoutbuf2[6], &dataoutbuf[6], 4); + emlSetMem(dataoutbuf2, FirstBlockOfSector(sectorNo) + blockNo, 1); + } + } + } - } + } - if(mifare_classic_halt(pcs, cuid)) - if (MF_DBGLEVEL >= 1) - Dbprintf("Halt error"); + if(mifare_classic_halt(pcs, cuid)) + if (MF_DBGLEVEL >= 1) + Dbprintf("Halt error"); - // ----------------------------- crypto1 destroy - crypto1_destroy(pcs); + // ----------------------------- crypto1 destroy + crypto1_destroy(pcs); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); - if (MF_DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED"); + if (MF_DBGLEVEL >= 2) DbpString("EMUL FILL SECTORS FINISHED"); - set_tracing(false); + set_tracing(false); } @@ -1712,359 +1712,359 @@ uint8_t wipeC[] = { MIFARE_MAGICWIPEC }; void MifareCSetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){ - // params - uint8_t workFlags = arg0; - uint8_t blockNo = arg1; + // params + uint8_t workFlags = arg0; + uint8_t blockNo = arg1; - // detect 1a/1b - bool is1b = false; + // detect 1a/1b + bool is1b = false; - // variables - bool isOK = false; //assume we will get an error - uint8_t errormsg = 0x00; - uint8_t uid[10] = {0x00}; - uint8_t data[18] = {0x00}; - uint32_t cuid = 0; + // variables + bool isOK = false; //assume we will get an error + uint8_t errormsg = 0x00; + uint8_t uid[10] = {0x00}; + uint8_t data[18] = {0x00}; + uint32_t cuid = 0; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - if (workFlags & MAGIC_INIT) { - LED_A_ON(); - LED_B_OFF(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); - } + if (workFlags & MAGIC_INIT) { + LED_A_ON(); + LED_B_OFF(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + clear_trace(); + set_tracing(true); + } - //loop doesn't loop just breaks out if error - while (true) { - // read UID and return to client with write - if (workFlags & MAGIC_UID) { - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); - errormsg = MAGIC_UID; - } - mifare_classic_halt_ex(NULL); - break; - } + //loop doesn't loop just breaks out if error + while (true) { + // read UID and return to client with write + if (workFlags & MAGIC_UID) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); + errormsg = MAGIC_UID; + } + mifare_classic_halt_ex(NULL); + break; + } - // wipe tag, fill it with zeros - if (workFlags & MAGIC_WIPE){ - ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC1 error"); - errormsg = MAGIC_WIPE; - break; - } + // wipe tag, fill it with zeros + if (workFlags & MAGIC_WIPE){ + ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC1 error"); + errormsg = MAGIC_WIPE; + break; + } - ReaderTransmit(wipeC, sizeof(wipeC), NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wipeC error"); - errormsg = MAGIC_WIPE; - break; - } + ReaderTransmit(wipeC, sizeof(wipeC), NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wipeC error"); + errormsg = MAGIC_WIPE; + break; + } - mifare_classic_halt_ex(NULL); - } + mifare_classic_halt_ex(NULL); + } - // write block - if (workFlags & MAGIC_WUPC) { - ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC1 error"); - errormsg = MAGIC_WUPC; - break; - } + // write block + if (workFlags & MAGIC_WUPC) { + ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC1 error"); + errormsg = MAGIC_WUPC; + break; + } - if ( !is1b ) { - ReaderTransmit(wupC2, sizeof(wupC2), NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Assuming Magic Gen 1B tag. [wupC2 failed]"); - is1b = true; - continue; - } - } - } + if ( !is1b ) { + ReaderTransmit(wupC2, sizeof(wupC2), NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Assuming Magic Gen 1B tag. [wupC2 failed]"); + is1b = true; + continue; + } + } + } - if ((mifare_sendcmd_short(NULL, 0, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("write block send command error"); - errormsg = 4; - break; - } + if ((mifare_sendcmd_short(NULL, 0, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 1) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("write block send command error"); + errormsg = 4; + break; + } - memcpy(data, datain, 16); - AddCrc14A(data, 16); + memcpy(data, datain, 16); + AddCrc14A(data, 16); - ReaderTransmit(data, sizeof(data), NULL); - if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("write block send data error"); - errormsg = 0; - break; - } + ReaderTransmit(data, sizeof(data), NULL); + if ((ReaderReceive(receivedAnswer, receivedAnswerPar) != 1) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("write block send data error"); + errormsg = 0; + break; + } - if (workFlags & MAGIC_HALT) - mifare_classic_halt_ex(NULL); + if (workFlags & MAGIC_HALT) + mifare_classic_halt_ex(NULL); - isOK = true; - break; + isOK = true; + break; - } // end while + } // end while - if (isOK ) - cmd_send(CMD_ACK,1,0,0,uid,sizeof(uid)); - else - OnErrorMagic(errormsg); + if (isOK ) + cmd_send(CMD_ACK,1,0,0,uid,sizeof(uid)); + else + OnErrorMagic(errormsg); - if (workFlags & MAGIC_OFF) - OnSuccessMagic(); + if (workFlags & MAGIC_OFF) + OnSuccessMagic(); } void MifareCGetBlock(uint32_t arg0, uint32_t arg1, uint8_t *datain){ - uint8_t workFlags = arg0; - uint8_t blockNo = arg1; - uint8_t errormsg = 0x00; - bool isOK = false; //assume we will get an error + uint8_t workFlags = arg0; + uint8_t blockNo = arg1; + uint8_t errormsg = 0x00; + bool isOK = false; //assume we will get an error - // detect 1a/1b - bool is1b = false; + // detect 1a/1b + bool is1b = false; - // variables - uint8_t data[MAX_MIFARE_FRAME_SIZE]; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + // variables + uint8_t data[MAX_MIFARE_FRAME_SIZE]; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - memset(data, 0x00, sizeof(data)); + memset(data, 0x00, sizeof(data)); - if (workFlags & MAGIC_INIT) { - LED_A_ON(); - LED_B_OFF(); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); - } + if (workFlags & MAGIC_INIT) { + LED_A_ON(); + LED_B_OFF(); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + clear_trace(); + set_tracing(true); + } - //loop doesn't loop just breaks out if error or done - while (true) { - if (workFlags & MAGIC_WUPC) { - ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC1 error"); - errormsg = MAGIC_WUPC; - break; - } + //loop doesn't loop just breaks out if error or done + while (true) { + if (workFlags & MAGIC_WUPC) { + ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("wupC1 error"); + errormsg = MAGIC_WUPC; + break; + } - if ( !is1b ) { - ReaderTransmit(wupC2, sizeof(wupC2), NULL); - if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Assuming Magic Gen 1B tag. [wupC2 failed]"); - is1b = true; - continue; - } - } - } + if ( !is1b ) { + ReaderTransmit(wupC2, sizeof(wupC2), NULL); + if(!ReaderReceive(receivedAnswer, receivedAnswerPar) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Assuming Magic Gen 1B tag. [wupC2 failed]"); + is1b = true; + continue; + } + } + } - // read block - if ((mifare_sendcmd_short(NULL, 0, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("read block send command error"); - errormsg = 0; - break; - } + // read block + if ((mifare_sendcmd_short(NULL, 0, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL) != 18)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("read block send command error"); + errormsg = 0; + break; + } - memcpy(data, receivedAnswer, sizeof(data)); + memcpy(data, receivedAnswer, sizeof(data)); - // send HALT - if (workFlags & MAGIC_HALT) - mifare_classic_halt_ex(NULL); + // send HALT + if (workFlags & MAGIC_HALT) + mifare_classic_halt_ex(NULL); - isOK = true; - break; - } - // if MAGIC_DATAIN, the data stays on device side. - if (workFlags & MAGIC_DATAIN) { - if (isOK) - memcpy(datain, data, sizeof(data)); - } else { - if (isOK) - cmd_send(CMD_ACK,1,0,0,data,sizeof(data)); - else - OnErrorMagic(errormsg); - } + isOK = true; + break; + } + // if MAGIC_DATAIN, the data stays on device side. + if (workFlags & MAGIC_DATAIN) { + if (isOK) + memcpy(datain, data, sizeof(data)); + } else { + if (isOK) + cmd_send(CMD_ACK,1,0,0,data,sizeof(data)); + else + OnErrorMagic(errormsg); + } - if (workFlags & MAGIC_OFF) - OnSuccessMagic(); + if (workFlags & MAGIC_OFF) + OnSuccessMagic(); } void MifareCIdent(){ - #define GEN_1A 1 - #define GEN_1B 2 - #define GEN_2 4 - // variables - uint8_t isGen = 0; - uint8_t rec[1] = {0x00}; - uint8_t recpar[1] = {0x00}; + #define GEN_1A 1 + #define GEN_1B 2 + #define GEN_2 4 + // variables + uint8_t isGen = 0; + uint8_t rec[1] = {0x00}; + uint8_t recpar[1] = {0x00}; - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - // Generation 1 test - ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); - if(!ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) { - goto TEST2; - }; - isGen = GEN_1B; + // Generation 1 test + ReaderTransmitBitsPar(wupC1, 7, NULL, NULL); + if(!ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) { + goto TEST2; + }; + isGen = GEN_1B; - ReaderTransmit(wupC2, sizeof(wupC2), NULL); - if(!ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) { - goto OUT; - }; - isGen = GEN_1A; - goto OUT; + ReaderTransmit(wupC2, sizeof(wupC2), NULL); + if(!ReaderReceive(rec, recpar) || (rec[0] != 0x0a)) { + goto OUT; + }; + isGen = GEN_1A; + goto OUT; TEST2:; /* - // Generation 2 test + // Generation 2 test - // halt previous. - mifare_classic_halt(NULL, 0); + // halt previous. + mifare_classic_halt(NULL, 0); - //select - if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { - goto OUT; - }; + //select + if (!iso14443a_select_card(NULL, NULL, NULL, true, 0, true)) { + goto OUT; + }; - // MIFARE_CLASSIC_WRITEBLOCK 0xA0 - // ACK 0x0a - uint16_t len = mifare_sendcmd_short(null, 1, 0xA0, 0, rec, recpar, NULL); - if ((len != 1) || (rec[0] != 0x0A)) { - isGen = GEN_2; - }; - */ + // MIFARE_CLASSIC_WRITEBLOCK 0xA0 + // ACK 0x0a + uint16_t len = mifare_sendcmd_short(null, 1, 0xA0, 0, rec, recpar, NULL); + if ((len != 1) || (rec[0] != 0x0A)) { + isGen = GEN_2; + }; + */ OUT:; - // removed the if, since some magic tags misbehavies and send an answer to it. - mifare_classic_halt_ex(NULL); - cmd_send(CMD_ACK, isGen, 0, 0, 0, 0); - // turns off - OnSuccessMagic(); + // removed the if, since some magic tags misbehavies and send an answer to it. + mifare_classic_halt_ex(NULL); + cmd_send(CMD_ACK, isGen, 0, 0, 0, 0); + // turns off + OnSuccessMagic(); } void OnSuccessMagic(){ - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); } void OnErrorMagic(uint8_t reason){ - // ACK, ISOK, reason,0,0,0 - cmd_send(CMD_ACK,0,reason,0,0,0); - OnSuccessMagic(); + // ACK, ISOK, reason,0,0,0 + cmd_send(CMD_ACK,0,reason,0,0,0); + OnSuccessMagic(); } void MifareSetMod(uint8_t mod, uint8_t *key) { - uint64_t ui64Key = bytes_to_num(key, 6); + uint64_t ui64Key = bytes_to_num(key, 6); - // variables - uint8_t isOK = 0; - uint8_t uid[10] = {0}; - uint32_t cuid = 0; - struct Crypto1State mpcs = {0, 0}; - struct Crypto1State *pcs = &mpcs; - int respLen = 0; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0}; + // variables + uint8_t isOK = 0; + uint8_t uid[10] = {0}; + uint32_t cuid = 0; + struct Crypto1State mpcs = {0, 0}; + struct Crypto1State *pcs = &mpcs; + int respLen = 0; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0}; - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); + clear_trace(); + set_tracing(true); - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); - while (true) { - if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); - break; - } + while (true) { + if(!iso14443a_select_card(uid, NULL, &cuid, true, 0, true)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Can't select card"); + break; + } - if(mifare_classic_auth(pcs, cuid, 0, 0, ui64Key, AUTH_FIRST)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); - break; - } + if(mifare_classic_auth(pcs, cuid, 0, 0, ui64Key, AUTH_FIRST)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Auth error"); + break; + } - if (((respLen = mifare_sendcmd_short(pcs, 1, 0x43, mod, receivedAnswer, receivedAnswerPar, NULL)) != 1) || (receivedAnswer[0] != 0x0a)) { - if (MF_DBGLEVEL >= 1) Dbprintf("SetMod error; response[0]: %hhX, len: %d", receivedAnswer[0], respLen); - break; - } + if (((respLen = mifare_sendcmd_short(pcs, 1, 0x43, mod, receivedAnswer, receivedAnswerPar, NULL)) != 1) || (receivedAnswer[0] != 0x0a)) { + if (MF_DBGLEVEL >= 1) Dbprintf("SetMod error; response[0]: %hhX, len: %d", receivedAnswer[0], respLen); + break; + } - if(mifare_classic_halt(pcs, cuid)) { - if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); - break; - } + if(mifare_classic_halt(pcs, cuid)) { + if (MF_DBGLEVEL >= 1) Dbprintf("Halt error"); + break; + } - isOK = 1; - break; - } + isOK = 1; + break; + } - crypto1_destroy(pcs); + crypto1_destroy(pcs); - LED_B_ON(); - cmd_send(CMD_ACK, isOK, 0, 0, 0, 0); - LED_B_OFF(); + LED_B_ON(); + cmd_send(CMD_ACK, isOK, 0, 0, 0, 0); + LED_B_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); } // // DESFIRE // void Mifare_DES_Auth1(uint8_t arg0, uint8_t *datain){ - byte_t dataout[12] = {0x00}; - uint8_t uid[10] = {0x00}; - uint32_t cuid = 0; + byte_t dataout[12] = {0x00}; + uint8_t uid[10] = {0x00}; + uint32_t cuid = 0; - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - clear_trace(); - set_tracing(true); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + clear_trace(); + set_tracing(true); - int len = iso14443a_select_card(uid, NULL, &cuid, true, 0, false); - if(!len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); - OnError(1); - return; - }; + int len = iso14443a_select_card(uid, NULL, &cuid, true, 0, false); + if(!len) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Can't select card"); + OnError(1); + return; + }; - if(mifare_desfire_des_auth1(cuid, dataout)){ - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part1: Fail."); - OnError(4); - return; - } + if(mifare_desfire_des_auth1(cuid, dataout)){ + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication part1: Fail."); + OnError(4); + return; + } - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 1 FINISHED"); cmd_send(CMD_ACK, 1, cuid, 0, dataout, sizeof(dataout)); } void Mifare_DES_Auth2(uint32_t arg0, uint8_t *datain){ - uint32_t cuid = arg0; - uint8_t key[16] = {0x00}; - byte_t dataout[12] = {0x00}; - byte_t isOK = 0; + uint32_t cuid = arg0; + uint8_t key[16] = {0x00}; + byte_t dataout[12] = {0x00}; + byte_t isOK = 0; - memcpy(key, datain, 16); + memcpy(key, datain, 16); - isOK = mifare_desfire_des_auth2(cuid, key, dataout); + isOK = mifare_desfire_des_auth2(cuid, key, dataout); - if( isOK) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed"); - OnError(4); - return; - } + if( isOK) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication part2: Failed"); + OnError(4); + return; + } - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED"); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) DbpString("AUTH 2 FINISHED"); - cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout)); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - LEDsoff(); - set_tracing(false); + cmd_send(CMD_ACK, isOK, 0, 0, dataout, sizeof(dataout)); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + LEDsoff(); + set_tracing(false); } \ No newline at end of file diff --git a/armsrc/mifaredesfire.c b/armsrc/mifaredesfire.c index 4cafca16c..e53ac0f59 100644 --- a/armsrc/mifaredesfire.c +++ b/armsrc/mifaredesfire.c @@ -18,189 +18,189 @@ static uint8_t deselect_cmd[] = {0xc2,0xe0,0xb4}; bool InitDesfireCard(){ - iso14a_card_select_t card; + iso14a_card_select_t card; - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - set_tracing(true); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + set_tracing(true); - if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) DbpString("Can't select card"); - OnError(1); - return false; - } - return true; + if (!iso14443a_select_card(NULL, &card, NULL, true, 0, false)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) DbpString("Can't select card"); + OnError(1); + return false; + } + return true; } // ARG0 flag enums enum { - NONE = 0x00, - INIT = 0x01, - DISCONNECT = 0x02, - CLEARTRACE = 0x04, - BAR = 0x08, + NONE = 0x00, + INIT = 0x01, + DISCONNECT = 0x02, + CLEARTRACE = 0x04, + BAR = 0x08, } CmdOptions ; void MifareSendCommand(uint8_t arg0, uint8_t arg1, uint8_t *datain){ - /* ARG0 contains flags. - 0x01 = init card. - 0x02 = Disconnect - 0x03 - */ - uint8_t flags = arg0; - size_t datalen = arg1; - uint8_t resp[RECEIVE_SIZE]; - memset(resp,0,sizeof(resp)); + /* ARG0 contains flags. + 0x01 = init card. + 0x02 = Disconnect + 0x03 + */ + uint8_t flags = arg0; + size_t datalen = arg1; + uint8_t resp[RECEIVE_SIZE]; + memset(resp,0,sizeof(resp)); - if (MF_DBGLEVEL >= 4) { - Dbprintf(" flags : %02X", flags); - Dbprintf(" len : %02X", datalen); - print_result(" RX : ", datain, datalen); - } + if (MF_DBGLEVEL >= 4) { + Dbprintf(" flags : %02X", flags); + Dbprintf(" len : %02X", datalen); + print_result(" RX : ", datain, datalen); + } - if ( flags & CLEARTRACE ) - clear_trace(); + if ( flags & CLEARTRACE ) + clear_trace(); - if ( flags & INIT ){ - if ( !InitDesfireCard() ) - return; - } + if ( flags & INIT ){ + if ( !InitDesfireCard() ) + return; + } - int len = DesfireAPDU(datain, datalen, resp); - if (MF_DBGLEVEL >= 4) - print_result("ERR <--: ", resp, len); + int len = DesfireAPDU(datain, datalen, resp); + if (MF_DBGLEVEL >= 4) + print_result("ERR <--: ", resp, len); - if ( !len ) { - OnError(2); - return; - } + if ( !len ) { + OnError(2); + return; + } - // reset the pcb_blocknum, - pcb_blocknum = 0; + // reset the pcb_blocknum, + pcb_blocknum = 0; - if ( flags & DISCONNECT ) - OnSuccess(); + if ( flags & DISCONNECT ) + OnSuccess(); - cmd_send(CMD_ACK,1,len,0,resp,len); + cmd_send(CMD_ACK,1,len,0,resp,len); } void MifareDesfireGetInformation(){ - int len = 0; - iso14a_card_select_t card; - uint8_t resp[USB_CMD_DATA_SIZE] = {0x00}; - uint8_t dataout[USB_CMD_DATA_SIZE] = {0x00}; + int len = 0; + iso14a_card_select_t card; + uint8_t resp[USB_CMD_DATA_SIZE] = {0x00}; + uint8_t dataout[USB_CMD_DATA_SIZE] = {0x00}; - /* - 1 = PCB 1 - 2 = cid 2 - 3 = desfire command 3 - 4-5 = crc 4 key - 5-6 crc - PCB == 0x0A because sending CID byte. - CID == 0x00 first card? - */ - clear_trace(); - set_tracing(true); - iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); + /* + 1 = PCB 1 + 2 = cid 2 + 3 = desfire command 3 + 4-5 = crc 4 key + 5-6 crc + PCB == 0x0A because sending CID byte. + CID == 0x00 first card? + */ + clear_trace(); + set_tracing(true); + iso14443a_setup(FPGA_HF_ISO14443A_READER_LISTEN); - // card select - information - if ( !iso14443a_select_card(NULL, &card, NULL, true, 0, false) ) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) DbpString("Can't select card"); - OnError(1); - return; - } + // card select - information + if ( !iso14443a_select_card(NULL, &card, NULL, true, 0, false) ) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) DbpString("Can't select card"); + OnError(1); + return; + } - if ( card.uidlen != 7 ) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Wrong UID size. Expected 7byte got %d", card.uidlen); - OnError(2); - return; - } + if ( card.uidlen != 7 ) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Wrong UID size. Expected 7byte got %d", card.uidlen); + OnError(2); + return; + } - memcpy(dataout, card.uid, 7); + memcpy(dataout, card.uid, 7); - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); - uint8_t cmd[] = {GET_VERSION}; - size_t cmd_len = sizeof(cmd); + uint8_t cmd[] = {GET_VERSION}; + size_t cmd_len = sizeof(cmd); - len = DesfireAPDU(cmd, cmd_len, resp); - if ( !len ) { - print_result("ERROR <--: ", resp, len); - OnError(3); - return; - } + len = DesfireAPDU(cmd, cmd_len, resp); + if ( !len ) { + print_result("ERROR <--: ", resp, len); + OnError(3); + return; + } - LED_A_OFF(); - LED_B_ON(); - memcpy(dataout+7,resp+3,7); + LED_A_OFF(); + LED_B_ON(); + memcpy(dataout+7,resp+3,7); - // ADDITION_FRAME 1 - cmd[0] = ADDITIONAL_FRAME; - len = DesfireAPDU(cmd, cmd_len, resp); - if ( !len ) { - print_result("ERROR <--: ", resp, len); - OnError(3); - return; - } + // ADDITION_FRAME 1 + cmd[0] = ADDITIONAL_FRAME; + len = DesfireAPDU(cmd, cmd_len, resp); + if ( !len ) { + print_result("ERROR <--: ", resp, len); + OnError(3); + return; + } - LED_B_OFF(); - LED_C_ON(); - memcpy(dataout+7+7,resp+3,7); + LED_B_OFF(); + LED_C_ON(); + memcpy(dataout+7+7,resp+3,7); - // ADDITION_FRAME 2 - len = DesfireAPDU(cmd, cmd_len, resp); - if ( !len ) { - print_result("ERROR <--: ", resp, len); - OnError(3); - return; - } + // ADDITION_FRAME 2 + len = DesfireAPDU(cmd, cmd_len, resp); + if ( !len ) { + print_result("ERROR <--: ", resp, len); + OnError(3); + return; + } - memcpy(dataout+7+7+7,resp+3,14); + memcpy(dataout+7+7+7,resp+3,14); - cmd_send(CMD_ACK,1,0,0,dataout,sizeof(dataout)); + cmd_send(CMD_ACK,1,0,0,dataout,sizeof(dataout)); - // reset the pcb_blocknum, - pcb_blocknum = 0; - OnSuccess(); + // reset the pcb_blocknum, + pcb_blocknum = 0; + OnSuccess(); } void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain){ - int len = 0; - //uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47}; - uint8_t PICC_MASTER_KEY16[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f }; - uint8_t null_key_data8[8] = {0x00}; - //uint8_t null_key_data16[16] = {0x00}; - //uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; - //uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF}; + int len = 0; + //uint8_t PICC_MASTER_KEY8[8] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47}; + uint8_t PICC_MASTER_KEY16[16] = { 0x40,0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f }; + uint8_t null_key_data8[8] = {0x00}; + //uint8_t null_key_data16[16] = {0x00}; + //uint8_t new_key_data8[8] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77}; + //uint8_t new_key_data16[16] = { 0x00,0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88,0x99,0xAA,0xBB,0xCC,0xDD,0xEE,0xFF}; - uint8_t resp[256] = {0x00}; - uint8_t IV[16] = {0x00}; + uint8_t resp[256] = {0x00}; + uint8_t IV[16] = {0x00}; - size_t datalen = datain[0]; + size_t datalen = datain[0]; - uint8_t cmd[40] = {0x00}; - uint8_t encRndB[16] = {0x00}; - uint8_t decRndB[16] = {0x00}; - uint8_t nonce[16] = {0x00}; - uint8_t both[32] = {0x00}; - uint8_t encBoth[32] = {0x00}; + uint8_t cmd[40] = {0x00}; + uint8_t encRndB[16] = {0x00}; + uint8_t decRndB[16] = {0x00}; + uint8_t nonce[16] = {0x00}; + uint8_t both[32] = {0x00}; + uint8_t encBoth[32] = {0x00}; - InitDesfireCard(); + InitDesfireCard(); - LED_A_ON(); - LED_B_OFF(); - LED_C_OFF(); + LED_A_ON(); + LED_B_OFF(); + LED_C_OFF(); - // 3 olika stt att authenticera. AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) - // 4 olika crypto algo DES, 3DES, 3K3DES, AES - // 3 olika kommunikations stt, PLAIN,MAC,CRYPTO + // 3 olika stt att authenticera. AUTH (CRC16) , AUTH_ISO (CRC32) , AUTH_AES (CRC32) + // 4 olika crypto algo DES, 3DES, 3K3DES, AES + // 3 olika kommunikations stt, PLAIN,MAC,CRYPTO - // des, nyckel 0, - switch (mode){ + // des, nyckel 0, + switch (mode){ case 1:{ uint8_t keybytes[16]; uint8_t RndA[8] = {0x00}; @@ -416,83 +416,83 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain return; } } - break; - case 2: - //SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp); - break; - case 3:{ + break; + case 2: + //SendDesfireCommand(AUTHENTICATE_ISO, &keyno, resp); + break; + case 3:{ - //defaultkey - uint8_t keybytes[16] = {0x00}; - if (datain[1] == 0xff){ - memcpy(keybytes,PICC_MASTER_KEY16,16); - } else{ - memcpy(keybytes, datain+1, datalen); - } + //defaultkey + uint8_t keybytes[16] = {0x00}; + if (datain[1] == 0xff){ + memcpy(keybytes,PICC_MASTER_KEY16,16); + } else{ + memcpy(keybytes, datain+1, datalen); + } - struct desfire_key defaultkey = {0x00}; - desfirekey_t key = &defaultkey; - Desfire_aes_key_new( keybytes, key); + struct desfire_key defaultkey = {0x00}; + desfirekey_t key = &defaultkey; + Desfire_aes_key_new( keybytes, key); - AesCtx ctx; - if ( AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0 ){ - if( MF_DBGLEVEL >= 4) { - DbpString("AES context failed to init"); - } - OnError(7); - return; - } + AesCtx ctx; + if ( AesCtxIni(&ctx, IV, key->data, KEY128, CBC) < 0 ){ + if( MF_DBGLEVEL >= 4) { + DbpString("AES context failed to init"); + } + OnError(7); + return; + } - cmd[0] = AUTHENTICATE_AES; - cmd[1] = 0x00; //keynumber - len = DesfireAPDU(cmd, 2, resp); - if ( !len ) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) { - DbpString("Authentication failed. Card timeout."); - } - OnError(3); - return; - } - - memcpy( encRndB, resp+3, 16); - - // dekryptera tagnonce. - AesDecrypt(&ctx, encRndB, decRndB, 16); - rol(decRndB,16); - memcpy(both, nonce,16); - memcpy(both+16, decRndB ,16 ); - AesEncrypt(&ctx, both, encBoth, 32 ); - - cmd[0] = ADDITIONAL_FRAME; - memcpy(cmd+1, encBoth, 32 ); - - len = DesfireAPDU(cmd, 33, resp); // 1 + 32 == 33 - if ( !len ) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) { - DbpString("Authentication failed. Card timeout."); - } + cmd[0] = AUTHENTICATE_AES; + cmd[1] = 0x00; //keynumber + len = DesfireAPDU(cmd, 2, resp); + if ( !len ) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) { + DbpString("Authentication failed. Card timeout."); + } OnError(3); - return; - } + return; + } - if ( resp[2] == 0x00 ){ - // Create AES Session key - struct desfire_key sessionKey = {0}; - desfirekey_t skey = &sessionKey; - Desfire_session_key_new( nonce, decRndB , key, skey ); - print_result("SESSION : ", skey->data, 16); - } else { - DbpString("Authentication failed."); - OnError(7); - return; - } + memcpy( encRndB, resp+3, 16); - break; - } - } + // dekryptera tagnonce. + AesDecrypt(&ctx, encRndB, decRndB, 16); + rol(decRndB,16); + memcpy(both, nonce,16); + memcpy(both+16, decRndB ,16 ); + AesEncrypt(&ctx, both, encBoth, 32 ); - OnSuccess(); - cmd_send(CMD_ACK,1,len,0,resp,len); + cmd[0] = ADDITIONAL_FRAME; + memcpy(cmd+1, encBoth, 32 ); + + len = DesfireAPDU(cmd, 33, resp); // 1 + 32 == 33 + if ( !len ) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) { + DbpString("Authentication failed. Card timeout."); + } + OnError(3); + return; + } + + if ( resp[2] == 0x00 ){ + // Create AES Session key + struct desfire_key sessionKey = {0}; + desfirekey_t skey = &sessionKey; + Desfire_session_key_new( nonce, decRndB , key, skey ); + print_result("SESSION : ", skey->data, 16); + } else { + DbpString("Authentication failed."); + OnError(7); + return; + } + + break; + } + } + + OnSuccess(); + cmd_send(CMD_ACK,1,len,0,resp,len); } // 3 olika ISO stt att skicka data till DESFIRE (direkt, inkapslat, inkapslat ISO) @@ -501,71 +501,71 @@ void MifareDES_Auth1(uint8_t mode, uint8_t algo, uint8_t keyno, uint8_t *datain // dataout = pointer to response data array int DesfireAPDU(uint8_t *cmd, size_t cmd_len, uint8_t *dataout){ - size_t len = 0; - size_t wrappedLen = 0; - uint8_t wCmd[USB_CMD_DATA_SIZE] = {0x00}; - uint8_t resp[MAX_FRAME_SIZE]; + size_t len = 0; + size_t wrappedLen = 0; + uint8_t wCmd[USB_CMD_DATA_SIZE] = {0x00}; + uint8_t resp[MAX_FRAME_SIZE]; uint8_t par[MAX_PARITY_SIZE]; - wrappedLen = CreateAPDU( cmd, cmd_len, wCmd); + wrappedLen = CreateAPDU( cmd, cmd_len, wCmd); - if (MF_DBGLEVEL >= 4) - print_result("WCMD <--: ", wCmd, wrappedLen); + if (MF_DBGLEVEL >= 4) + print_result("WCMD <--: ", wCmd, wrappedLen); - ReaderTransmit( wCmd, wrappedLen, NULL); + ReaderTransmit( wCmd, wrappedLen, NULL); - len = ReaderReceive(resp, par); - if ( !len ) { - if (MF_DBGLEVEL >= 4) Dbprintf("fukked"); - return false; //DATA LINK ERROR - } - // if we received an I- or R(ACK)-Block with a block number equal to the - // current block number, toggle the current block number - else if (len >= 4 // PCB+CID+CRC = 4 bytes - && ((resp[0] & 0xC0) == 0 // I-Block - || (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0 - && (resp[0] & 0x01) == pcb_blocknum) // equal block numbers - { - pcb_blocknum ^= 1; //toggle next block - } + len = ReaderReceive(resp, par); + if ( !len ) { + if (MF_DBGLEVEL >= 4) Dbprintf("fukked"); + return false; //DATA LINK ERROR + } + // if we received an I- or R(ACK)-Block with a block number equal to the + // current block number, toggle the current block number + else if (len >= 4 // PCB+CID+CRC = 4 bytes + && ((resp[0] & 0xC0) == 0 // I-Block + || (resp[0] & 0xD0) == 0x80) // R-Block with ACK bit set to 0 + && (resp[0] & 0x01) == pcb_blocknum) // equal block numbers + { + pcb_blocknum ^= 1; //toggle next block + } - memcpy(dataout, resp, len); - return len; + memcpy(dataout, resp, len); + return len; } // CreateAPDU size_t CreateAPDU( uint8_t *datain, size_t len, uint8_t *dataout){ - size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1); + size_t cmdlen = MIN(len+4, USB_CMD_DATA_SIZE-1); - uint8_t cmd[cmdlen]; - memset(cmd, 0, cmdlen); + uint8_t cmd[cmdlen]; + memset(cmd, 0, cmdlen); - cmd[0] = 0x0A; // 0x0A = skicka cid, 0x02 = ingen cid. Srskilda bitar // - cmd[0] |= pcb_blocknum; // OR the block number into the PCB - cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards + cmd[0] = 0x0A; // 0x0A = skicka cid, 0x02 = ingen cid. Srskilda bitar // + cmd[0] |= pcb_blocknum; // OR the block number into the PCB + cmd[1] = 0x00; // CID: 0x00 //TODO: allow multiple selected cards - memcpy(cmd+2, datain, len); - AddCrc14A(cmd, len+2); + memcpy(cmd+2, datain, len); + AddCrc14A(cmd, len+2); - memcpy(dataout, cmd, cmdlen); + memcpy(dataout, cmd, cmdlen); - return cmdlen; + return cmdlen; } - // crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */ - // crc_update(&desfire_crc32, addr, addr_sz); - // crc_update(&desfire_crc32, byte, 8); - // uint32_t crc = crc_finish(&desfire_crc32); + // crc_update(&desfire_crc32, 0, 1); /* CMD_WRITE */ + // crc_update(&desfire_crc32, addr, addr_sz); + // crc_update(&desfire_crc32, byte, 8); + // uint32_t crc = crc_finish(&desfire_crc32); void OnSuccess(){ - pcb_blocknum = 0; - ReaderTransmit(deselect_cmd, 3 , NULL); - mifare_ultra_halt(); - switch_off(); + pcb_blocknum = 0; + ReaderTransmit(deselect_cmd, 3 , NULL); + mifare_ultra_halt(); + switch_off(); } void OnError(uint8_t reason){ - cmd_send(CMD_ACK,0,reason,0,0,0); - OnSuccess(); + cmd_send(CMD_ACK,0,reason,0,0,0); + OnSuccess(); } diff --git a/armsrc/mifaresniff.c b/armsrc/mifaresniff.c index 43e416086..cbdf3a99d 100644 --- a/armsrc/mifaresniff.c +++ b/armsrc/mifaresniff.c @@ -25,300 +25,300 @@ static uint32_t timerData = 0; //----------------------------------------------------------------------------- // "hf mf sniff" void RAMFUNC SniffMifare(uint8_t param) { - // param: - // bit 0 - trigger from first card answer - // bit 1 - trigger from first reader 7-bit request + // param: + // bit 0 - trigger from first card answer + // bit 1 - trigger from first reader 7-bit request - // C(red) A(yellow) B(green) - LEDsoff(); - iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); + // C(red) A(yellow) B(green) + LEDsoff(); + iso14443a_setup(FPGA_HF_ISO14443A_SNIFFER); - // Allocate memory from BigBuf for some buffers - // free all previous allocations first - BigBuf_free(); BigBuf_Clear_ext(false); - clear_trace(); - set_tracing(true); + // Allocate memory from BigBuf for some buffers + // free all previous allocations first + BigBuf_free(); BigBuf_Clear_ext(false); + clear_trace(); + set_tracing(true); - // The command (reader -> tag) that we're receiving. - uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedCmdPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + // The command (reader -> tag) that we're receiving. + uint8_t receivedCmd[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedCmdPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - // The response (tag -> reader) that we're receiving. - uint8_t receivedResp[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedRespPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + // The response (tag -> reader) that we're receiving. + uint8_t receivedResp[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedRespPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - // allocate the DMA buffer, used to stream samples from the FPGA - uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); - uint8_t *data = dmaBuf; - uint8_t previous_data = 0; - int maxDataLen = 0; - int dataLen = 0; - bool ReaderIsActive = false; - bool TagIsActive = false; + // allocate the DMA buffer, used to stream samples from the FPGA + uint8_t *dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); + uint8_t *data = dmaBuf; + uint8_t previous_data = 0; + int maxDataLen = 0; + int dataLen = 0; + bool ReaderIsActive = false; + bool TagIsActive = false; - // We won't start recording the frames that we acquire until we trigger; - // a good trigger condition to get started is probably when we see a - // response from the tag. - // triggered == false -- to wait first for card - //bool triggered = !(param & 0x03); + // We won't start recording the frames that we acquire until we trigger; + // a good trigger condition to get started is probably when we see a + // response from the tag. + // triggered == false -- to wait first for card + //bool triggered = !(param & 0x03); - // Set up the demodulator for tag -> reader responses. - DemodInit(receivedResp, receivedRespPar); + // Set up the demodulator for tag -> reader responses. + DemodInit(receivedResp, receivedRespPar); - // Set up the demodulator for the reader -> tag commands - UartInit(receivedCmd, receivedCmdPar); + // Set up the demodulator for the reader -> tag commands + UartInit(receivedCmd, receivedCmdPar); - // Setup and start DMA. - // set transfer address and number of bytes. Start transfer. - if ( !FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE) ){ - if (MF_DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting"); - return; - } + // Setup and start DMA. + // set transfer address and number of bytes. Start transfer. + if ( !FpgaSetupSscDma(dmaBuf, DMA_BUFFER_SIZE) ){ + if (MF_DBGLEVEL > 1) Dbprintf("[!] FpgaSetupSscDma failed. Exiting"); + return; + } - tUart* uart = GetUart(); - tDemod* demod = GetDemod(); + tUart* uart = GetUart(); + tDemod* demod = GetDemod(); - MfSniffInit(); + MfSniffInit(); - uint32_t sniffCounter = 0; + uint32_t sniffCounter = 0; // loop and listen - while (!BUTTON_PRESS()) { - WDT_HIT(); - LED_A_ON(); + while (!BUTTON_PRESS()) { + WDT_HIT(); + LED_A_ON(); /* - if ((sniffCounter & 0x0000FFFF) == 0) { // from time to time - // check if a transaction is completed (timeout after 2000ms). - // if yes, stop the DMA transfer and send what we have so far to the client - if (BigBuf_get_traceLen()) { - MfSniffSend(); - // Reset everything - we missed some sniffed data anyway while the DMA was stopped - sniffCounter = 0; - dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); - data = dmaBuf; - maxDataLen = 0; - ReaderIsActive = false; - TagIsActive = false; - FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); // set transfer address and number of bytes. Start transfer. - } - } - */ + if ((sniffCounter & 0x0000FFFF) == 0) { // from time to time + // check if a transaction is completed (timeout after 2000ms). + // if yes, stop the DMA transfer and send what we have so far to the client + if (BigBuf_get_traceLen()) { + MfSniffSend(); + // Reset everything - we missed some sniffed data anyway while the DMA was stopped + sniffCounter = 0; + dmaBuf = BigBuf_malloc(DMA_BUFFER_SIZE); + data = dmaBuf; + maxDataLen = 0; + ReaderIsActive = false; + TagIsActive = false; + FpgaSetupSscDma((uint8_t *)dmaBuf, DMA_BUFFER_SIZE); // set transfer address and number of bytes. Start transfer. + } + } + */ - // number of bytes we have processed so far - int register readBufDataP = data - dmaBuf; - // number of bytes already transferred - int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; - if (readBufDataP <= dmaBufDataP) // we are processing the same block of data which is currently being transferred - dataLen = dmaBufDataP - readBufDataP; // number of bytes still to be processed - else - dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; // number of bytes still to be processed + // number of bytes we have processed so far + int register readBufDataP = data - dmaBuf; + // number of bytes already transferred + int register dmaBufDataP = DMA_BUFFER_SIZE - AT91C_BASE_PDC_SSC->PDC_RCR; + if (readBufDataP <= dmaBufDataP) // we are processing the same block of data which is currently being transferred + dataLen = dmaBufDataP - readBufDataP; // number of bytes still to be processed + else + dataLen = DMA_BUFFER_SIZE - readBufDataP + dmaBufDataP; // number of bytes still to be processed - // test for length of buffer - if (dataLen > maxDataLen) { // we are more behind than ever... - maxDataLen = dataLen; - if (dataLen > (9 * DMA_BUFFER_SIZE / 10)) { - Dbprintf("[!] blew circular buffer! | datalen %u", dataLen); - break; - } - } - if (dataLen < 1) continue; + // test for length of buffer + if (dataLen > maxDataLen) { // we are more behind than ever... + maxDataLen = dataLen; + if (dataLen > (9 * DMA_BUFFER_SIZE / 10)) { + Dbprintf("[!] blew circular buffer! | datalen %u", dataLen); + break; + } + } + if (dataLen < 1) continue; - // primary buffer was stopped ( <-- we lost data! - if (!AT91C_BASE_PDC_SSC->PDC_RCR) { - AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t)dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE; - Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary - } - // secondary buffer sets as primary, secondary buffer was stopped - if (!AT91C_BASE_PDC_SSC->PDC_RNCR) { - AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)dmaBuf; - AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; - } + // primary buffer was stopped ( <-- we lost data! + if (!AT91C_BASE_PDC_SSC->PDC_RCR) { + AT91C_BASE_PDC_SSC->PDC_RPR = (uint32_t)dmaBuf; + AT91C_BASE_PDC_SSC->PDC_RCR = DMA_BUFFER_SIZE; + Dbprintf("[-] RxEmpty ERROR | data length %d", dataLen); // temporary + } + // secondary buffer sets as primary, secondary buffer was stopped + if (!AT91C_BASE_PDC_SSC->PDC_RNCR) { + AT91C_BASE_PDC_SSC->PDC_RNPR = (uint32_t)dmaBuf; + AT91C_BASE_PDC_SSC->PDC_RNCR = DMA_BUFFER_SIZE; + } - LED_A_OFF(); + LED_A_OFF(); - // Need two samples to feed Miller and Manchester-Decoder - if (sniffCounter & 0x01) { + // Need two samples to feed Miller and Manchester-Decoder + if (sniffCounter & 0x01) { - // no need to try decoding tag data if the reader is sending - if (!TagIsActive) { - uint8_t readerbyte = (previous_data & 0xF0) | (*data >> 4); - if (MillerDecoding(readerbyte, (sniffCounter-1)*4)) { - LogTrace(receivedCmd, uart->len, 0, 0, NULL, true); - DemodReset(); - UartReset(); - } - ReaderIsActive = (uart->state != STATE_UNSYNCD); - } + // no need to try decoding tag data if the reader is sending + if (!TagIsActive) { + uint8_t readerbyte = (previous_data & 0xF0) | (*data >> 4); + if (MillerDecoding(readerbyte, (sniffCounter-1)*4)) { + LogTrace(receivedCmd, uart->len, 0, 0, NULL, true); + DemodReset(); + UartReset(); + } + ReaderIsActive = (uart->state != STATE_UNSYNCD); + } - // no need to try decoding tag data if the reader is sending - if (!ReaderIsActive) { - uint8_t tagbyte = (previous_data << 4) | (*data & 0x0F); - if (ManchesterDecoding(tagbyte, 0, (sniffCounter-1)*4)) { - LogTrace(receivedResp, demod->len, 0, 0, NULL, false); - DemodReset(); - UartReset(); - } - TagIsActive = (demod->state != DEMOD_UNSYNCD); - } - } - previous_data = *data; - sniffCounter++; - data++; + // no need to try decoding tag data if the reader is sending + if (!ReaderIsActive) { + uint8_t tagbyte = (previous_data << 4) | (*data & 0x0F); + if (ManchesterDecoding(tagbyte, 0, (sniffCounter-1)*4)) { + LogTrace(receivedResp, demod->len, 0, 0, NULL, false); + DemodReset(); + UartReset(); + } + TagIsActive = (demod->state != DEMOD_UNSYNCD); + } + } + previous_data = *data; + sniffCounter++; + data++; - if (data == dmaBuf + DMA_BUFFER_SIZE) - data = dmaBuf; + if (data == dmaBuf + DMA_BUFFER_SIZE) + data = dmaBuf; - } // main cycle + } // main cycle - MfSniffEnd(); - switch_off(); + MfSniffEnd(); + switch_off(); } void MfSniffInit(void){ - memset(sniffUID, 0x00, sizeof(sniffUID)); - memset(sniffATQA, 0x00, sizeof(sniffATQA)); - memset(sniffBuf, 0x00, sizeof(sniffBuf)); - sniffSAK = 0; - sniffUIDType = SNF_UID_4; - timerData = 0; + memset(sniffUID, 0x00, sizeof(sniffUID)); + memset(sniffATQA, 0x00, sizeof(sniffATQA)); + memset(sniffBuf, 0x00, sizeof(sniffBuf)); + sniffSAK = 0; + sniffUIDType = SNF_UID_4; + timerData = 0; } void MfSniffEnd(void){ - LED_B_ON(); - cmd_send(CMD_ACK,0,0,0,0,0); - LED_B_OFF(); + LED_B_ON(); + cmd_send(CMD_ACK,0,0,0,0,0); + LED_B_OFF(); } /* bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader) { - // reset on 7-Bit commands from reader - if (reader && (len == 1) && (bitCnt == 7)) { - sniffState = SNF_INIT; - } + // reset on 7-Bit commands from reader + if (reader && (len == 1) && (bitCnt == 7)) { + sniffState = SNF_INIT; + } - switch (sniffState) { - case SNF_INIT:{ - // REQA,WUPA or MAGICWUP from reader - if ((len == 1) && (reader) && (bitCnt == 7) ) { - MfSniffInit(); - sniffState = (data[0] == MIFARE_MAGICWUPC1) ? SNF_MAGIC_WUPC2 : SNF_ATQA; - } - break; - } - case SNF_MAGIC_WUPC2: { - if ((len == 1) && (reader) && (data[0] == MIFARE_MAGICWUPC2) ) { - sniffState = SNF_CARD_IDLE; - } - break; - } - case SNF_ATQA:{ - // ATQA from tag - if ((!reader) && (len == 2)) { - sniffATQA[0] = data[0]; - sniffATQA[1] = data[1]; - sniffState = SNF_UID; - } - break; - } - case SNF_UID: { + switch (sniffState) { + case SNF_INIT:{ + // REQA,WUPA or MAGICWUP from reader + if ((len == 1) && (reader) && (bitCnt == 7) ) { + MfSniffInit(); + sniffState = (data[0] == MIFARE_MAGICWUPC1) ? SNF_MAGIC_WUPC2 : SNF_ATQA; + } + break; + } + case SNF_MAGIC_WUPC2: { + if ((len == 1) && (reader) && (data[0] == MIFARE_MAGICWUPC2) ) { + sniffState = SNF_CARD_IDLE; + } + break; + } + case SNF_ATQA:{ + // ATQA from tag + if ((!reader) && (len == 2)) { + sniffATQA[0] = data[0]; + sniffATQA[1] = data[1]; + sniffState = SNF_UID; + } + break; + } + case SNF_UID: { - if ( !reader ) break; - if ( len != 9 ) break; - if ( !CheckCrc14443(CRC_14443_A, data, 9)) break; - if ( data[1] != 0x70 ) break; + if ( !reader ) break; + if ( len != 9 ) break; + if ( !CheckCrc14443(CRC_14443_A, data, 9)) break; + if ( data[1] != 0x70 ) break; - Dbprintf("[!] UID | %x", data[0]); + Dbprintf("[!] UID | %x", data[0]); - if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT)) { - // UID_4 - select 4 Byte UID from reader - memcpy(sniffUID, data+2, 4); - sniffUIDType = SNF_UID_4; - sniffState = SNF_SAK; - } else if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2)) { - // UID_7 - Select 2nd part of 7 Byte UID + if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT)) { + // UID_4 - select 4 Byte UID from reader + memcpy(sniffUID, data+2, 4); + sniffUIDType = SNF_UID_4; + sniffState = SNF_SAK; + } else if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_2)) { + // UID_7 - Select 2nd part of 7 Byte UID - // get rid of 0x88 - sniffUID[0] = sniffUID[1]; - sniffUID[1] = sniffUID[2]; - sniffUID[2] = sniffUID[3]; - //new uid bytes - memcpy(sniffUID+3, data+2, 4); - sniffUIDType = SNF_UID_7; - sniffState = SNF_SAK; - } else if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3)) { - // UID_10 - Select 3nd part of 10 Byte UID - // 3+3+4 = 10. - // get ride of previous 0x88 - sniffUID[3] = sniffUID[4]; - sniffUID[4] = sniffUID[5]; - sniffUID[5] = sniffUID[6]; - // new uid bytes - memcpy(sniffUID+6, data+2, 4); - sniffUIDType = SNF_UID_10; - sniffState = SNF_SAK; - } - break; - } - case SNF_SAK:{ - // SAK from card? - if ((!reader) && (len == 3) && (CheckCrc14443(CRC_14443_A, data, 3))) { - sniffSAK = data[0]; - // CL2 UID part to be expected - if (( sniffSAK == 0x04) && (sniffUIDType == SNF_UID_4)) { - sniffState = SNF_UID; - // CL3 UID part to be expected - } else if ((sniffSAK == 0x04) && (sniffUIDType == SNF_UID_7)) { - sniffState = SNF_UID; - } else { - // select completed - sniffState = SNF_CARD_IDLE; - } - } - break; - } - case SNF_CARD_IDLE:{ // trace the card select sequence - sniffBuf[0] = 0xFF; - sniffBuf[1] = 0xFF; - memcpy(sniffBuf + 2, sniffUID, sizeof(sniffUID)); - memcpy(sniffBuf + 12, sniffATQA, sizeof(sniffATQA)); - sniffBuf[14] = sniffSAK; - sniffBuf[15] = 0xFF; - sniffBuf[16] = 0xFF; - LogTrace(sniffBuf, sizeof(sniffBuf), 0, 0, NULL, true); - sniffState = SNF_CARD_CMD; - } // intentionally no break; - case SNF_CARD_CMD:{ - LogTrace(data, len, 0, 0, NULL, reader); - timerData = GetTickCount(); - break; - } - default: - sniffState = SNF_INIT; - break; - } - return false; + // get rid of 0x88 + sniffUID[0] = sniffUID[1]; + sniffUID[1] = sniffUID[2]; + sniffUID[2] = sniffUID[3]; + //new uid bytes + memcpy(sniffUID+3, data+2, 4); + sniffUIDType = SNF_UID_7; + sniffState = SNF_SAK; + } else if ((data[0] == ISO14443A_CMD_ANTICOLL_OR_SELECT_3)) { + // UID_10 - Select 3nd part of 10 Byte UID + // 3+3+4 = 10. + // get ride of previous 0x88 + sniffUID[3] = sniffUID[4]; + sniffUID[4] = sniffUID[5]; + sniffUID[5] = sniffUID[6]; + // new uid bytes + memcpy(sniffUID+6, data+2, 4); + sniffUIDType = SNF_UID_10; + sniffState = SNF_SAK; + } + break; + } + case SNF_SAK:{ + // SAK from card? + if ((!reader) && (len == 3) && (CheckCrc14443(CRC_14443_A, data, 3))) { + sniffSAK = data[0]; + // CL2 UID part to be expected + if (( sniffSAK == 0x04) && (sniffUIDType == SNF_UID_4)) { + sniffState = SNF_UID; + // CL3 UID part to be expected + } else if ((sniffSAK == 0x04) && (sniffUIDType == SNF_UID_7)) { + sniffState = SNF_UID; + } else { + // select completed + sniffState = SNF_CARD_IDLE; + } + } + break; + } + case SNF_CARD_IDLE:{ // trace the card select sequence + sniffBuf[0] = 0xFF; + sniffBuf[1] = 0xFF; + memcpy(sniffBuf + 2, sniffUID, sizeof(sniffUID)); + memcpy(sniffBuf + 12, sniffATQA, sizeof(sniffATQA)); + sniffBuf[14] = sniffSAK; + sniffBuf[15] = 0xFF; + sniffBuf[16] = 0xFF; + LogTrace(sniffBuf, sizeof(sniffBuf), 0, 0, NULL, true); + sniffState = SNF_CARD_CMD; + } // intentionally no break; + case SNF_CARD_CMD:{ + LogTrace(data, len, 0, 0, NULL, reader); + timerData = GetTickCount(); + break; + } + default: + sniffState = SNF_INIT; + break; + } + return false; } */ void RAMFUNC MfSniffSend() { - uint16_t tracelen = BigBuf_get_traceLen(); - uint16_t chunksize = 0; - int packlen = tracelen; // total number of bytes to send - uint8_t *data = BigBuf_get_addr(); + uint16_t tracelen = BigBuf_get_traceLen(); + uint16_t chunksize = 0; + int packlen = tracelen; // total number of bytes to send + uint8_t *data = BigBuf_get_addr(); - while (packlen > 0) { - LED_B_ON(); - chunksize = MIN(USB_CMD_DATA_SIZE, packlen); // chunk size 512 - cmd_send(CMD_ACK, 1, tracelen, chunksize, data + tracelen - packlen, chunksize); - packlen -= chunksize; - LED_B_OFF(); - } + while (packlen > 0) { + LED_B_ON(); + chunksize = MIN(USB_CMD_DATA_SIZE, packlen); // chunk size 512 + cmd_send(CMD_ACK, 1, tracelen, chunksize, data + tracelen - packlen, chunksize); + packlen -= chunksize; + LED_B_OFF(); + } - LED_B_ON(); - cmd_send(CMD_ACK, 2, 0, 0, 0, 0); // 2 == data transfer finished. - LED_B_OFF(); + LED_B_ON(); + cmd_send(CMD_ACK, 2, 0, 0, 0, 0); // 2 == data transfer finished. + LED_B_OFF(); } \ No newline at end of file diff --git a/armsrc/mifaresniff.h b/armsrc/mifaresniff.h index efd34fdeb..debfd5a09 100644 --- a/armsrc/mifaresniff.h +++ b/armsrc/mifaresniff.h @@ -21,18 +21,18 @@ #include "mifareutil.h" #include "common.h" -#define SNF_INIT 0 -#define SNF_NO_FIELD 1 -#define SNF_ATQA 2 -#define SNF_UID 3 -#define SNF_SAK 4 -#define SNF_CARD_IDLE 5 -#define SNF_CARD_CMD 6 -#define SNF_MAGIC_WUPC2 7 +#define SNF_INIT 0 +#define SNF_NO_FIELD 1 +#define SNF_ATQA 2 +#define SNF_UID 3 +#define SNF_SAK 4 +#define SNF_CARD_IDLE 5 +#define SNF_CARD_CMD 6 +#define SNF_MAGIC_WUPC2 7 -#define SNF_UID_4 0 -#define SNF_UID_7 0 -#define SNF_UID_10 0 +#define SNF_UID_4 0 +#define SNF_UID_7 0 +#define SNF_UID_10 0 void MfSniffInit(void); bool RAMFUNC MfSniffLogic(const uint8_t *data, uint16_t len, uint8_t *parity, uint16_t bitCnt, bool reader); diff --git a/armsrc/mifareutil.c b/armsrc/mifareutil.c index 86048ae88..f15d13dec 100644 --- a/armsrc/mifareutil.c +++ b/armsrc/mifareutil.c @@ -14,676 +14,676 @@ int MF_DBGLEVEL = MF_DBG_ERROR; // crypto1 helpers void mf_crypto1_decryptEx(struct Crypto1State *pcs, uint8_t *data_in, int len, uint8_t *data_out){ - uint8_t bt = 0; - int i; + uint8_t bt = 0; + int i; - if (len != 1) { - for (i = 0; i < len; i++) - data_out[i] = crypto1_byte(pcs, 0x00, 0) ^ data_in[i]; - } else { - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 0)) << 0; - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 1)) << 1; - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 2)) << 2; - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 3)) << 3; - data_out[0] = bt; - } - return; + if (len != 1) { + for (i = 0; i < len; i++) + data_out[i] = crypto1_byte(pcs, 0x00, 0) ^ data_in[i]; + } else { + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 0)) << 0; + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 1)) << 1; + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 2)) << 2; + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data_in[0], 3)) << 3; + data_out[0] = bt; + } + return; } void mf_crypto1_decrypt(struct Crypto1State *pcs, uint8_t *data, int len){ - mf_crypto1_decryptEx(pcs, data, len, data); + mf_crypto1_decryptEx(pcs, data, len, data); } void mf_crypto1_encrypt(struct Crypto1State *pcs, uint8_t *data, uint16_t len, uint8_t *par) { - uint8_t bt = 0; - int i; - par[0] = 0; + uint8_t bt = 0; + int i; + par[0] = 0; - for (i = 0; i < len; i++) { - bt = data[i]; - data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i]; - if ( ( i & 0x0007 ) == 0) - par[ i >> 3 ] = 0; - par[ i >> 3 ] |= (((filter(pcs->odd) ^ oddparity8(bt)) & 0x01)<<(7-(i&0x0007))); - } + for (i = 0; i < len; i++) { + bt = data[i]; + data[i] = crypto1_byte(pcs, 0x00, 0) ^ data[i]; + if ( ( i & 0x0007 ) == 0) + par[ i >> 3 ] = 0; + par[ i >> 3 ] |= (((filter(pcs->odd) ^ oddparity8(bt)) & 0x01)<<(7-(i&0x0007))); + } } uint8_t mf_crypto1_encrypt4bit(struct Crypto1State *pcs, uint8_t data) { - uint8_t bt = 0; - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 0)) << 0; - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 1)) << 1; - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 2)) << 2; - bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 3)) << 3; - return bt; + uint8_t bt = 0; + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 0)) << 0; + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 1)) << 1; + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 2)) << 2; + bt |= (crypto1_bit(pcs, 0, 0) ^ BIT(data, 3)) << 3; + return bt; } // send X byte basic commands int mifare_sendcmd(uint8_t cmd, uint8_t* data, uint8_t data_size, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing) { - uint8_t dcmd[data_size+3]; + uint8_t dcmd[data_size+3]; dcmd[0] = cmd; - memcpy(dcmd+1, data, data_size); - AddCrc14A(dcmd, data_size+1); - ReaderTransmit(dcmd, sizeof(dcmd), timing); - int len = ReaderReceive(answer, answer_parity); - if(!len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%02X Cmd failed. Card timeout.", cmd); - len = ReaderReceive(answer,answer_parity); + memcpy(dcmd+1, data, data_size); + AddCrc14A(dcmd, data_size+1); + ReaderTransmit(dcmd, sizeof(dcmd), timing); + int len = ReaderReceive(answer, answer_parity); + if(!len) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("%02X Cmd failed. Card timeout.", cmd); + len = ReaderReceive(answer,answer_parity); } - return len; + return len; } // send 2 byte commands int mifare_sendcmd_short(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t data, uint8_t *answer, uint8_t *answer_parity, uint32_t *timing) { - uint16_t pos, res; - uint8_t dcmd[4] = {cmd, data, 0x00, 0x00}; - uint8_t ecmd[4] = {0x00, 0x00, 0x00, 0x00}; - uint8_t par[1] = {0x00}; // 1 Byte parity is enough here - AddCrc14A(dcmd, 2); - memcpy(ecmd, dcmd, sizeof(dcmd)); + uint16_t pos, res; + uint8_t dcmd[4] = {cmd, data, 0x00, 0x00}; + uint8_t ecmd[4] = {0x00, 0x00, 0x00, 0x00}; + uint8_t par[1] = {0x00}; // 1 Byte parity is enough here + AddCrc14A(dcmd, 2); + memcpy(ecmd, dcmd, sizeof(dcmd)); - if (crypted) { - par[0] = 0; - for (pos = 0; pos < 4; pos++) { - ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos]; - par[0] |= (((filter(pcs->odd) ^ oddparity8(dcmd[pos])) & 0x01) << (7-pos)); - } - ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing); - } else { - ReaderTransmit(dcmd, sizeof(dcmd), timing); - } + if (crypted) { + par[0] = 0; + for (pos = 0; pos < 4; pos++) { + ecmd[pos] = crypto1_byte(pcs, 0x00, 0) ^ dcmd[pos]; + par[0] |= (((filter(pcs->odd) ^ oddparity8(dcmd[pos])) & 0x01) << (7-pos)); + } + ReaderTransmitPar(ecmd, sizeof(ecmd), par, timing); + } else { + ReaderTransmit(dcmd, sizeof(dcmd), timing); + } - int len = ReaderReceive(answer, par); + int len = ReaderReceive(answer, par); - if (answer_parity) *answer_parity = par[0]; + if (answer_parity) *answer_parity = par[0]; - if (crypted == CRYPT_ALL) { - if (len == 1) { - res = 0; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 0)) << 0; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 1)) << 1; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 2)) << 2; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 3)) << 3; - answer[0] = res; - } else { - for (pos = 0; pos < len; pos++) - answer[pos] = crypto1_byte(pcs, 0x00, 0) ^ answer[pos]; - } - } - return len; + if (crypted == CRYPT_ALL) { + if (len == 1) { + res = 0; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 0)) << 0; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 1)) << 1; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 2)) << 2; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(answer[0], 3)) << 3; + answer[0] = res; + } else { + for (pos = 0; pos < len; pos++) + answer[pos] = crypto1_byte(pcs, 0x00, 0) ^ answer[pos]; + } + } + return len; } // mifare classic commands int mifare_classic_auth(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested) { - return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL); + return mifare_classic_authex(pcs, uid, blockNo, keyType, ui64Key, isNested, NULL, NULL); } int mifare_classic_authex(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t keyType, uint64_t ui64Key, uint8_t isNested, uint32_t *ntptr, uint32_t *timing) { - int len; - uint32_t pos, nt, ntpp; // Supplied tag nonce - uint8_t par[1] = {0x00}; - uint8_t nr[4]; - uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + int len; + uint32_t pos, nt, ntpp; // Supplied tag nonce + uint8_t par[1] = {0x00}; + uint8_t nr[4]; + uint8_t mf_nr_ar[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - // "random" reader nonce: - num_to_bytes( prng_successor( GetTickCount(), 32), 4, nr); + // "random" reader nonce: + num_to_bytes( prng_successor( GetTickCount(), 32), 4, nr); - // Transmit MIFARE_CLASSIC_AUTH - len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing); - if (len != 4) return 1; + // Transmit MIFARE_CLASSIC_AUTH + len = mifare_sendcmd_short(pcs, isNested, 0x60 + (keyType & 0x01), blockNo, receivedAnswer, receivedAnswerPar, timing); + if (len != 4) return 1; - // Save the tag nonce (nt) - nt = bytes_to_num(receivedAnswer, 4); + // Save the tag nonce (nt) + nt = bytes_to_num(receivedAnswer, 4); - // ----------------------------- crypto1 create - if (isNested) - crypto1_destroy(pcs); + // ----------------------------- crypto1 create + if (isNested) + crypto1_destroy(pcs); - // Init cipher with key - crypto1_create(pcs, ui64Key); + // Init cipher with key + crypto1_create(pcs, ui64Key); - if (isNested == AUTH_NESTED) { - // decrypt nt with help of new key - nt = crypto1_word(pcs, nt ^ uid, 1) ^ nt; - } else { - // Load (plain) uid^nt into the cipher - crypto1_word(pcs, nt ^ uid, 0); - } + if (isNested == AUTH_NESTED) { + // decrypt nt with help of new key + nt = crypto1_word(pcs, nt ^ uid, 1) ^ nt; + } else { + // Load (plain) uid^nt into the cipher + crypto1_word(pcs, nt ^ uid, 0); + } - // some statistic - if (!ntptr && (MF_DBGLEVEL >= MF_DBG_EXTENDED)) - Dbprintf("auth uid: %08x | nr: %08x | nt: %08x", uid, nr, nt); + // some statistic + if (!ntptr && (MF_DBGLEVEL >= MF_DBG_EXTENDED)) + Dbprintf("auth uid: %08x | nr: %08x | nt: %08x", uid, nr, nt); - // save Nt - if (ntptr) - *ntptr = nt; + // save Nt + if (ntptr) + *ntptr = nt; - // Generate (encrypted) nr+parity by loading it into the cipher (Nr) - par[0] = 0; - for (pos = 0; pos < 4; pos++) { - mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos]; - par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7-pos)); - } + // Generate (encrypted) nr+parity by loading it into the cipher (Nr) + par[0] = 0; + for (pos = 0; pos < 4; pos++) { + mf_nr_ar[pos] = crypto1_byte(pcs, nr[pos], 0) ^ nr[pos]; + par[0] |= (((filter(pcs->odd) ^ oddparity8(nr[pos])) & 0x01) << (7-pos)); + } - // Skip 32 bits in pseudo random generator - nt = prng_successor(nt, 32); + // Skip 32 bits in pseudo random generator + nt = prng_successor(nt, 32); - // ar+parity - for (pos = 4; pos < 8; pos++) { - nt = prng_successor(nt,8); - mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff); - par[0] |= (((filter(pcs->odd) ^ oddparity8(nt & 0xff)) & 0x01) << (7-pos)); - } + // ar+parity + for (pos = 4; pos < 8; pos++) { + nt = prng_successor(nt,8); + mf_nr_ar[pos] = crypto1_byte(pcs,0x00,0) ^ (nt & 0xff); + par[0] |= (((filter(pcs->odd) ^ oddparity8(nt & 0xff)) & 0x01) << (7-pos)); + } - // Transmit reader nonce and reader answer - ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); + // Transmit reader nonce and reader answer + ReaderTransmitPar(mf_nr_ar, sizeof(mf_nr_ar), par, NULL); - // Receive 4 byte tag answer - len = ReaderReceive(receivedAnswer, receivedAnswerPar); - if (!len) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication failed. Card timeout."); - return 2; - } + // Receive 4 byte tag answer + len = ReaderReceive(receivedAnswer, receivedAnswerPar); + if (!len) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication failed. Card timeout."); + return 2; + } - ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0,0); + ntpp = prng_successor(nt, 32) ^ crypto1_word(pcs, 0,0); - if (ntpp != bytes_to_num(receivedAnswer, 4)) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication failed. Error card response."); - return 3; - } - return 0; + if (ntpp != bytes_to_num(receivedAnswer, 4)) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("Authentication failed. Error card response."); + return 3; + } + return 0; } int mifare_classic_readblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) { - int len; - uint8_t bt[2] = {0x00, 0x00}; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + int len; + uint8_t bt[2] = {0x00, 0x00}; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); - if (len == 1) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); - return 1; - } - if (len != 18) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: wrong response len: %x (expected 18)", len); - return 2; - } + len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); + if (len == 1) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + return 1; + } + if (len != 18) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: wrong response len: %x (expected 18)", len); + return 2; + } - memcpy(bt, receivedAnswer + 16, 2); - AddCrc14A(receivedAnswer, 16); - if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { - if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Cmd CRC response error."); - return 3; - } + memcpy(bt, receivedAnswer + 16, 2); + AddCrc14A(receivedAnswer, 16); + if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { + if (MF_DBGLEVEL >= MF_DBG_ALL) Dbprintf("Cmd CRC response error."); + return 3; + } - memcpy(blockData, receivedAnswer, 16); - return 0; + memcpy(blockData, receivedAnswer, 16); + return 0; } // mifare ultralight commands int mifare_ul_ev1_auth(uint8_t *keybytes, uint8_t *pack){ - uint16_t len = 0; - uint8_t resp[4] = {0x00, 0x00, 0x00, 0x00}; - uint8_t respPar[1] = {0x00}; - uint8_t key[4] = {0x00, 0x00, 0x00, 0x00}; - memcpy(key, keybytes, 4); + uint16_t len = 0; + uint8_t resp[4] = {0x00, 0x00, 0x00, 0x00}; + uint8_t respPar[1] = {0x00}; + uint8_t key[4] = {0x00, 0x00, 0x00, 0x00}; + memcpy(key, keybytes, 4); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) - Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) + Dbprintf("EV1 Auth : %02x%02x%02x%02x", key[0], key[1], key[2], key[3]); - len = mifare_sendcmd(MIFARE_ULEV1_AUTH, key, sizeof(key), resp, respPar, NULL); + len = mifare_sendcmd(MIFARE_ULEV1_AUTH, key, sizeof(key), resp, respPar, NULL); - if (len != 4) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len); - return 0; - } + if (len != 4) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x %u", resp[0], len); + return 0; + } - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) - Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0],resp[1],resp[2],resp[3]); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) + Dbprintf("Auth Resp: %02x%02x%02x%02x", resp[0],resp[1],resp[2],resp[3]); - memcpy(pack, resp, 4); - return 1; + memcpy(pack, resp, 4); + return 1; } int mifare_ultra_auth(uint8_t *keybytes){ - /// 3des2k - uint8_t random_a[8] = {1,1,1,1,1,1,1,1}; - uint8_t random_b[8] = {0x00}; - uint8_t enc_random_b[8] = {0x00}; - uint8_t rnd_ab[16] = {0x00}; - uint8_t IV[8] = {0x00}; - uint8_t key[16] = {0x00}; - memcpy(key, keybytes, 16); + /// 3des2k + uint8_t random_a[8] = {1,1,1,1,1,1,1,1}; + uint8_t random_b[8] = {0x00}; + uint8_t enc_random_b[8] = {0x00}; + uint8_t rnd_ab[16] = {0x00}; + uint8_t IV[8] = {0x00}; + uint8_t key[16] = {0x00}; + memcpy(key, keybytes, 16); - uint16_t len = 0; - uint8_t resp[19] = {0x00}; - uint8_t respPar[3] = {0,0,0}; + uint16_t len = 0; + uint8_t resp[19] = {0x00}; + uint8_t respPar[3] = {0,0,0}; - // REQUEST AUTHENTICATION - len = mifare_sendcmd_short(NULL, 1, MIFARE_ULC_AUTH_1, 0x00, resp, respPar ,NULL); - if (len != 11) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); - return 0; - } + // REQUEST AUTHENTICATION + len = mifare_sendcmd_short(NULL, 1, MIFARE_ULC_AUTH_1, 0x00, resp, respPar ,NULL); + if (len != 11) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); + return 0; + } - // tag nonce. - memcpy(enc_random_b,resp+1,8); + // tag nonce. + memcpy(enc_random_b,resp+1,8); - // decrypt nonce. - tdes_2key_dec((void*)random_b, (void*)enc_random_b, sizeof(random_b), (const void*)key, IV ); - rol(random_b,8); - memcpy(rnd_ab ,random_a,8); - memcpy(rnd_ab+8,random_b,8); + // decrypt nonce. + tdes_2key_dec((void*)random_b, (void*)enc_random_b, sizeof(random_b), (const void*)key, IV ); + rol(random_b,8); + memcpy(rnd_ab ,random_a,8); + memcpy(rnd_ab+8,random_b,8); - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x", - enc_random_b[0],enc_random_b[1],enc_random_b[2],enc_random_b[3],enc_random_b[4],enc_random_b[5],enc_random_b[6],enc_random_b[7]); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("enc_B: %02x %02x %02x %02x %02x %02x %02x %02x", + enc_random_b[0],enc_random_b[1],enc_random_b[2],enc_random_b[3],enc_random_b[4],enc_random_b[5],enc_random_b[6],enc_random_b[7]); - Dbprintf(" B: %02x %02x %02x %02x %02x %02x %02x %02x", - random_b[0],random_b[1],random_b[2],random_b[3],random_b[4],random_b[5],random_b[6],random_b[7]); + Dbprintf(" B: %02x %02x %02x %02x %02x %02x %02x %02x", + random_b[0],random_b[1],random_b[2],random_b[3],random_b[4],random_b[5],random_b[6],random_b[7]); - Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", - rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3],rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); + Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", + rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3],rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); - Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", - rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11],rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15] ); - } + Dbprintf("rnd_ab: %02x %02x %02x %02x %02x %02x %02x %02x", + rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11],rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15] ); + } - // encrypt out, in, length, key, iv - tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b); + // encrypt out, in, length, key, iv + tdes_2key_enc(rnd_ab, rnd_ab, sizeof(rnd_ab), key, enc_random_b); - len = mifare_sendcmd(MIFARE_ULC_AUTH_2, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL); - if (len != 11) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); - return 0; - } + len = mifare_sendcmd(MIFARE_ULC_AUTH_2, rnd_ab, sizeof(rnd_ab), resp, respPar, NULL); + if (len != 11) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", resp[0]); + return 0; + } - uint8_t enc_resp[8] = { 0,0,0,0,0,0,0,0 }; - uint8_t resp_random_a[8] = { 0,0,0,0,0,0,0,0 }; - memcpy(enc_resp, resp+1, 8); + uint8_t enc_resp[8] = { 0,0,0,0,0,0,0,0 }; + uint8_t resp_random_a[8] = { 0,0,0,0,0,0,0,0 }; + memcpy(enc_resp, resp+1, 8); - // decrypt out, in, length, key, iv - tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b); - if ( memcmp(resp_random_a, random_a, 8) != 0 ) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("failed authentication"); - return 0; - } + // decrypt out, in, length, key, iv + tdes_2key_dec(resp_random_a, enc_resp, 8, key, enc_random_b); + if ( memcmp(resp_random_a, random_a, 8) != 0 ) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("failed authentication"); + return 0; + } - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", - rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3], - rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", + rnd_ab[0],rnd_ab[1],rnd_ab[2],rnd_ab[3], + rnd_ab[4],rnd_ab[5],rnd_ab[6],rnd_ab[7]); - Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", - rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11], - rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15]); + Dbprintf("e_AB: %02x %02x %02x %02x %02x %02x %02x %02x", + rnd_ab[8],rnd_ab[9],rnd_ab[10],rnd_ab[11], + rnd_ab[12],rnd_ab[13],rnd_ab[14],rnd_ab[15]); - Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x", - random_a[0],random_a[1],random_a[2],random_a[3], - random_a[4],random_a[5],random_a[6],random_a[7]); + Dbprintf("a: %02x %02x %02x %02x %02x %02x %02x %02x", + random_a[0],random_a[1],random_a[2],random_a[3], + random_a[4],random_a[5],random_a[6],random_a[7]); - Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x", - resp_random_a[0],resp_random_a[1],resp_random_a[2],resp_random_a[3], - resp_random_a[4],resp_random_a[5],resp_random_a[6],resp_random_a[7]); - } - return 1; + Dbprintf("b: %02x %02x %02x %02x %02x %02x %02x %02x", + resp_random_a[0],resp_random_a[1],resp_random_a[2],resp_random_a[3], + resp_random_a[4],resp_random_a[5],resp_random_a[6],resp_random_a[7]); + } + return 1; } int mifare_ultra_readblockEx(uint8_t blockNo, uint8_t *blockData) { - uint16_t len = 0; - uint8_t bt[2] = {0x00, 0x00}; - uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; + uint16_t len = 0; + uint8_t bt[2] = {0x00, 0x00}; + uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; - len = mifare_sendcmd_short(NULL, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); - if (len == 1) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); - return 1; - } - if (len != 18) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: card timeout. len: %x", len); - return 2; - } + len = mifare_sendcmd_short(NULL, 1, ISO14443A_CMD_READBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); + if (len == 1) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + return 1; + } + if (len != 18) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: card timeout. len: %x", len); + return 2; + } - memcpy(bt, receivedAnswer + 16, 2); - AddCrc14A(receivedAnswer, 16); - if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd CRC response error."); - return 3; - } + memcpy(bt, receivedAnswer + 16, 2); + AddCrc14A(receivedAnswer, 16); + if (bt[0] != receivedAnswer[16] || bt[1] != receivedAnswer[17]) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd CRC response error."); + return 3; + } - memcpy(blockData, receivedAnswer, 14); - return 0; + memcpy(blockData, receivedAnswer, 14); + return 0; } int mifare_ultra_readblock(uint8_t blockNo, uint8_t *blockData) { - #define MFU_MAX_RETRIES 5 - uint8_t res; + #define MFU_MAX_RETRIES 5 + uint8_t res; - for (uint8_t retries = 0; retries < MFU_MAX_RETRIES; ++retries) { - res = mifare_ultra_readblockEx(blockNo, blockData); + for (uint8_t retries = 0; retries < MFU_MAX_RETRIES; ++retries) { + res = mifare_ultra_readblockEx(blockNo, blockData); - // break if OK, or NACK. - switch ( res ) { - case 0: - case 1: - return res; - default: - continue; - } - } - return res; + // break if OK, or NACK. + switch ( res ) { + case 0: + case 1: + return res; + default: + continue; + } + } + return res; } int mifare_classic_writeblock(struct Crypto1State *pcs, uint32_t uid, uint8_t blockNo, uint8_t *blockData) { - // variables - uint16_t len = 0; - uint32_t pos = 0; - uint8_t par[3] = {0x00, 0x00, 0x00}; // enough for 18 Bytes to send - byte_t res = 0; + // variables + uint16_t len = 0; + uint32_t pos = 0; + uint8_t par[3] = {0x00, 0x00, 0x00}; // enough for 18 Bytes to send + byte_t res = 0; - uint8_t d_block[18], d_block_enc[18]; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + uint8_t d_block[18], d_block_enc[18]; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; - // command MIFARE_CLASSIC_WRITEBLOCK - len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); + // command MIFARE_CLASSIC_WRITEBLOCK + len = mifare_sendcmd_short(pcs, 1, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); - if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); - return 1; - } + if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + return 1; + } - memcpy(d_block, blockData, 16); - AddCrc14A(d_block, 16); + memcpy(d_block, blockData, 16); + AddCrc14A(d_block, 16); - // crypto - for (pos = 0; pos < 18; pos++) { - d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos]; - par[pos>>3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos&0x0007))); - } + // crypto + for (pos = 0; pos < 18; pos++) { + d_block_enc[pos] = crypto1_byte(pcs, 0x00, 0) ^ d_block[pos]; + par[pos>>3] |= (((filter(pcs->odd) ^ oddparity8(d_block[pos])) & 0x01) << (7 - (pos&0x0007))); + } - ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL); + ReaderTransmitPar(d_block_enc, sizeof(d_block_enc), par, NULL); - // Receive the response - len = ReaderReceive(receivedAnswer, receivedAnswerPar); + // Receive the response + len = ReaderReceive(receivedAnswer, receivedAnswerPar); - res = 0; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 1)) << 1; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2; - res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3; + res = 0; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 0)) << 0; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 1)) << 1; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 2)) << 2; + res |= (crypto1_bit(pcs, 0, 0) ^ BIT(receivedAnswer[0], 3)) << 3; - if ((len != 1) || (res != 0x0A)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd send data2 Error: %02x", res); - return 2; - } - return 0; + if ((len != 1) || (res != 0x0A)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Cmd send data2 Error: %02x", res); + return 2; + } + return 0; } /* // command not needed, but left for future testing int mifare_ultra_writeblock_compat(uint8_t blockNo, uint8_t *blockData) { - uint16_t len; + uint16_t len; uint8_t par[3] = {0}; // enough for 18 parity bits - uint8_t d_block[18] = {0x00}; - uint8_t receivedAnswer[MAX_FRAME_SIZE]; - uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; + uint8_t d_block[18] = {0x00}; + uint8_t receivedAnswer[MAX_FRAME_SIZE]; + uint8_t receivedAnswerPar[MAX_PARITY_SIZE]; len = mifare_sendcmd_short(NULL, true, ISO14443A_CMD_WRITEBLOCK, blockNo, receivedAnswer, receivedAnswerPar, NULL); if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]); + if (MF_DBGLEVEL >= MF_DBG_ERROR) + Dbprintf("Cmd Addr Error: %02x", receivedAnswer[0]); return 1; } - memcpy(d_block, blockData, 16); + memcpy(d_block, blockData, 16); AddCrc14A(d_block, 16); - ReaderTransmitPar(d_block, sizeof(d_block), par, NULL); + ReaderTransmitPar(d_block, sizeof(d_block), par, NULL); - len = ReaderReceive(receivedAnswer, receivedAnswerPar); + len = ReaderReceive(receivedAnswer, receivedAnswerPar); - if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len); + if ((len != 1) || (receivedAnswer[0] != 0x0A)) { // 0x0a - ACK + if (MF_DBGLEVEL >= MF_DBG_ERROR) + Dbprintf("Cmd Data Error: %02x %d", receivedAnswer[0],len); return 2; - } + } return 0; } */ int mifare_ultra_writeblock(uint8_t blockNo, uint8_t *blockData) { uint16_t len = 0; - uint8_t block[5] = {blockNo, 0x00, 0x00, 0x00, 0x00 }; - uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; + uint8_t block[5] = {blockNo, 0x00, 0x00, 0x00, 0x00 }; + uint8_t receivedAnswer[MAX_MIFARE_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_MIFARE_PARITY_SIZE] = {0x00}; // command MIFARE_CLASSIC_WRITEBLOCK - memcpy(block+1, blockData, 4); + memcpy(block+1, blockData, 4); - len = mifare_sendcmd( MIFARE_ULC_WRITE, block, sizeof(block), receivedAnswer, receivedAnswerPar, NULL); + len = mifare_sendcmd( MIFARE_ULC_WRITE, block, sizeof(block), receivedAnswer, receivedAnswerPar, NULL); if (receivedAnswer[0] != 0x0A) { // 0x0a - ACK - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len); + if (MF_DBGLEVEL >= MF_DBG_ERROR) + Dbprintf("Cmd Send Error: %02x %d", receivedAnswer[0],len); return 1; } return 0; } int mifare_classic_halt_ex(struct Crypto1State *pcs) { - uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00}; - uint16_t len = mifare_sendcmd_short(pcs, (pcs == NULL) ? CRYPT_NONE : CRYPT_ALL, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL); - if (len != 0) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len); - return 1; - } - return 0; + uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00}; + uint16_t len = mifare_sendcmd_short(pcs, (pcs == NULL) ? CRYPT_NONE : CRYPT_ALL, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL); + if (len != 0) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len); + return 1; + } + return 0; } int mifare_classic_halt(struct Crypto1State *pcs, uint32_t uid) { - return mifare_classic_halt_ex(pcs); + return mifare_classic_halt_ex(pcs); } int mifare_ultra_halt() { - uint16_t len = 0; - uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00}; - len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL); - if (len != 0) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len); - return 1; - } - return 0; + uint16_t len = 0; + uint8_t receivedAnswer[4] = {0x00, 0x00, 0x00, 0x00}; + len = mifare_sendcmd_short(NULL, CRYPT_NONE, ISO14443A_CMD_HALT, 0x00, receivedAnswer, NULL, NULL); + if (len != 0) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) Dbprintf("halt warning. response len: %x", len); + return 1; + } + return 0; } // Mifare Memory Structure: up to 32 Sectors with 4 blocks each (1k and 2k cards), // plus evtl. 8 sectors with 16 blocks each (4k cards) uint8_t NumBlocksPerSector(uint8_t sectorNo) { - return (sectorNo < 32) ? 4 : 16; + return (sectorNo < 32) ? 4 : 16; } uint8_t FirstBlockOfSector(uint8_t sectorNo) { - if (sectorNo < 32) - return sectorNo * 4; - else - return 32*4 + (sectorNo - 32) * 16; + if (sectorNo < 32) + return sectorNo * 4; + else + return 32*4 + (sectorNo - 32) * 16; } // work with emulator memory void emlSetMem(uint8_t *data, int blockNum, int blocksCount) { - emlSetMem_xt(data, blockNum, blocksCount, 16); + 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 * blockBtWidth, data, blocksCount * blockBtWidth); + uint8_t* emCARD = BigBuf_get_EM_addr(); + memcpy(emCARD + blockNum * blockBtWidth, data, blocksCount * blockBtWidth); } void emlGetMem(uint8_t *data, int blockNum, int blocksCount) { - uint8_t* emCARD = BigBuf_get_EM_addr(); - memcpy(data, emCARD + blockNum * 16, blocksCount * 16); + uint8_t* emCARD = BigBuf_get_EM_addr(); + memcpy(data, emCARD + blockNum * 16, blocksCount * 16); } void emlGetMemBt(uint8_t *data, int bytePtr, int byteCount) { - uint8_t* emCARD = BigBuf_get_EM_addr(); - memcpy(data, emCARD + bytePtr, byteCount); + uint8_t* emCARD = BigBuf_get_EM_addr(); + memcpy(data, emCARD + bytePtr, byteCount); } int emlCheckValBl(int blockNum) { - uint8_t* emCARD = BigBuf_get_EM_addr(); - uint8_t* data = emCARD + blockNum * 16; + uint8_t* emCARD = BigBuf_get_EM_addr(); + uint8_t* data = emCARD + blockNum * 16; - if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) || - (data[1] != (data[5] ^ 0xff)) || (data[1] != data[9]) || - (data[2] != (data[6] ^ 0xff)) || (data[2] != data[10]) || - (data[3] != (data[7] ^ 0xff)) || (data[3] != data[11]) || - (data[12] != (data[13] ^ 0xff)) || (data[12] != data[14]) || - (data[12] != (data[15] ^ 0xff)) - ) - return 1; - return 0; + if ((data[0] != (data[4] ^ 0xff)) || (data[0] != data[8]) || + (data[1] != (data[5] ^ 0xff)) || (data[1] != data[9]) || + (data[2] != (data[6] ^ 0xff)) || (data[2] != data[10]) || + (data[3] != (data[7] ^ 0xff)) || (data[3] != data[11]) || + (data[12] != (data[13] ^ 0xff)) || (data[12] != data[14]) || + (data[12] != (data[15] ^ 0xff)) + ) + return 1; + return 0; } int emlGetValBl(uint32_t *blReg, uint8_t *blBlock, int blockNum) { - uint8_t* emCARD = BigBuf_get_EM_addr(); - uint8_t* data = emCARD + blockNum * 16; + uint8_t* emCARD = BigBuf_get_EM_addr(); + uint8_t* data = emCARD + blockNum * 16; - if (emlCheckValBl(blockNum)) - return 1; + if (emlCheckValBl(blockNum)) + return 1; - memcpy(blReg, data, 4); - *blBlock = data[12]; - return 0; + memcpy(blReg, data, 4); + *blBlock = data[12]; + return 0; } int emlSetValBl(uint32_t blReg, uint8_t blBlock, int blockNum) { - uint8_t* emCARD = BigBuf_get_EM_addr(); - uint8_t* data = emCARD + blockNum * 16; + uint8_t* emCARD = BigBuf_get_EM_addr(); + uint8_t* data = emCARD + blockNum * 16; - memcpy(data + 0, &blReg, 4); - memcpy(data + 8, &blReg, 4); - blReg = blReg ^ 0xffffffff; - memcpy(data + 4, &blReg, 4); + memcpy(data + 0, &blReg, 4); + memcpy(data + 8, &blReg, 4); + blReg = blReg ^ 0xffffffff; + memcpy(data + 4, &blReg, 4); - data[12] = blBlock; - data[13] = blBlock ^ 0xff; - data[14] = blBlock; - data[15] = blBlock ^ 0xff; + data[12] = blBlock; + data[13] = blBlock ^ 0xff; + data[14] = blBlock; + data[15] = blBlock ^ 0xff; - return 0; + return 0; } uint64_t emlGetKey(int sectorNum, int keyType) { - uint8_t key[6] = {0x00}; - uint8_t* emCARD = BigBuf_get_EM_addr(); - memcpy(key, emCARD + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6); - return bytes_to_num(key, 6); + uint8_t key[6] = {0x00}; + uint8_t* emCARD = BigBuf_get_EM_addr(); + memcpy(key, emCARD + 16 * (FirstBlockOfSector(sectorNum) + NumBlocksPerSector(sectorNum) - 1) + keyType * 10, 6); + return bytes_to_num(key, 6); } void emlClearMem(void) { - const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; - const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04}; - uint8_t* emCARD = BigBuf_get_EM_addr(); - memset(emCARD, 0, CARD_MEMORY_SIZE); + const uint8_t trailer[] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x07, 0x80, 0x69, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff}; + const uint8_t uid[] = {0xe6, 0x84, 0x87, 0xf3, 0x16, 0x88, 0x04, 0x00, 0x46, 0x8e, 0x45, 0x55, 0x4d, 0x70, 0x41, 0x04}; + uint8_t* emCARD = BigBuf_get_EM_addr(); + memset(emCARD, 0, CARD_MEMORY_SIZE); - // fill sectors trailer data - for(uint16_t b = 3; b < 256; ((b < 127) ? (b += 4) : (b += 16))) - emlSetMem((uint8_t *)trailer, b, 1); + // fill sectors trailer data + for(uint16_t b = 3; b < 256; ((b < 127) ? (b += 4) : (b += 16))) + emlSetMem((uint8_t *)trailer, b, 1); - // uid - emlSetMem((uint8_t *)uid, 0, 1); - return; + // uid + emlSetMem((uint8_t *)uid, 0, 1); + return; } // Mifare desfire commands int mifare_sendcmd_special(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer, uint8_t *answer_parity, uint32_t *timing) { uint8_t dcmd[5] = {cmd, data[0], data[1], 0x00, 0x00}; - AddCrc14A(dcmd, 3); + AddCrc14A(dcmd, 3); - ReaderTransmit(dcmd, sizeof(dcmd), NULL); - int len = ReaderReceive(answer, answer_parity); - if(!len) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout."); - return 1; + ReaderTransmit(dcmd, sizeof(dcmd), NULL); + int len = ReaderReceive(answer, answer_parity); + if(!len) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout."); + return 1; } - return len; + return len; } int mifare_sendcmd_special2(struct Crypto1State *pcs, uint8_t crypted, uint8_t cmd, uint8_t* data, uint8_t* answer,uint8_t *answer_parity, uint32_t *timing) { uint8_t dcmd[20] = {0x00}; dcmd[0] = cmd; memcpy(dcmd+1,data,17); - AddCrc14A(dcmd, 18); + AddCrc14A(dcmd, 18); - ReaderTransmit(dcmd, sizeof(dcmd), NULL); - int len = ReaderReceive(answer, answer_parity); - if(!len){ + ReaderTransmit(dcmd, sizeof(dcmd), NULL); + int len = ReaderReceive(answer, answer_parity); + if(!len){ if (MF_DBGLEVEL >= MF_DBG_ERROR) Dbprintf("Authentication failed. Card timeout."); - return 1; + return 1; } - return len; + return len; } int mifare_desfire_des_auth1(uint32_t uid, uint8_t *blockData){ - int len; - // load key, keynumber - uint8_t data[2]={MFDES_AUTHENTICATE, 0x00}; - uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; + int len; + // load key, keynumber + uint8_t data[2]={MFDES_AUTHENTICATE, 0x00}; + uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; - len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer,receivedAnswerPar,NULL); - if (len == 1) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Cmd Error: %02x", receivedAnswer[0]); - return 1; - } + len = mifare_sendcmd_special(NULL, 1, 0x02, data, receivedAnswer,receivedAnswerPar,NULL); + if (len == 1) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) + Dbprintf("Cmd Error: %02x", receivedAnswer[0]); + return 1; + } - if (len == 12) { - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4], - receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9], - receivedAnswer[10],receivedAnswer[11]); - } - memcpy(blockData, receivedAnswer, 12); - return 0; - } - return 1; + if (len == 12) { + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("Auth1 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4], + receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9], + receivedAnswer[10],receivedAnswer[11]); + } + memcpy(blockData, receivedAnswer, 12); + return 0; + } + return 1; } int mifare_desfire_des_auth2(uint32_t uid, uint8_t *key, uint8_t *blockData){ - int len; - uint8_t data[17] = {MFDES_AUTHENTICATION_FRAME}; - memcpy(data+1,key,16); + int len; + uint8_t data[17] = {MFDES_AUTHENTICATION_FRAME}; + memcpy(data+1,key,16); - uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; - uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; + uint8_t receivedAnswer[MAX_FRAME_SIZE] = {0x00}; + uint8_t receivedAnswerPar[MAX_PARITY_SIZE] = {0x00}; - len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar ,NULL); + len = mifare_sendcmd_special2(NULL, 1, 0x03, data, receivedAnswer, receivedAnswerPar ,NULL); - if ((receivedAnswer[0] == 0x03) && (receivedAnswer[1] == 0xae)) { - if (MF_DBGLEVEL >= MF_DBG_ERROR) - Dbprintf("Auth Error: %02x %02x", receivedAnswer[0], receivedAnswer[1]); - return 1; - } + if ((receivedAnswer[0] == 0x03) && (receivedAnswer[1] == 0xae)) { + if (MF_DBGLEVEL >= MF_DBG_ERROR) + Dbprintf("Auth Error: %02x %02x", receivedAnswer[0], receivedAnswer[1]); + return 1; + } - if (len == 12){ - if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { - Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", - receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4], - receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9], - receivedAnswer[10],receivedAnswer[11]); - } - memcpy(blockData, receivedAnswer, 12); - return 0; - } - return 1; + if (len == 12){ + if (MF_DBGLEVEL >= MF_DBG_EXTENDED) { + Dbprintf("Auth2 Resp: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x", + receivedAnswer[0],receivedAnswer[1],receivedAnswer[2],receivedAnswer[3],receivedAnswer[4], + receivedAnswer[5],receivedAnswer[6],receivedAnswer[7],receivedAnswer[8],receivedAnswer[9], + receivedAnswer[10],receivedAnswer[11]); + } + memcpy(blockData, receivedAnswer, 12); + return 0; + } + return 1; } diff --git a/armsrc/mifareutil.h b/armsrc/mifareutil.h index 594b7ca80..ad01a7078 100644 --- a/armsrc/mifareutil.h +++ b/armsrc/mifareutil.h @@ -21,7 +21,7 @@ #include "iso14443a.h" #include "crapto1/crapto1.h" #include "des.h" -#include "random.h" // fast_prand, prand +#include "random.h" // fast_prand, prand // mifare authentication #define CRYPT_NONE 0 @@ -30,8 +30,8 @@ #define AUTH_FIRST 0 #define AUTH_NESTED 2 -#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) -#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication +#define AUTHENTICATION_TIMEOUT 848 // card times out 1ms after wrong authentication (according to NXP documentation) +#define PRE_AUTHENTICATION_LEADTIME 400 // some (non standard) cards need a pause after select before they are ready for first authentication // mifare 4bit card answers #define CARD_ACK 0x0A // 1010 - ACK @@ -48,7 +48,7 @@ #define MFEMUL_SELECT3 4 #define MFEMUL_AUTH1 5 #define MFEMUL_AUTH2 6 -#define MFEMUL_WORK 7 +#define MFEMUL_WORK 7 #define MFEMUL_WRITEBL2 8 #define MFEMUL_INTREG_INC 9 #define MFEMUL_INTREG_DEC 10 diff --git a/armsrc/optimized_cipher.c b/armsrc/optimized_cipher.c index 98ab88041..f8ddc19d2 100644 --- a/armsrc/optimized_cipher.c +++ b/armsrc/optimized_cipher.c @@ -41,8 +41,8 @@ This file contains an optimized version of the MAC-calculation algorithm. Some measurements on a std laptop showed it runs in about 1/3 of the time: - Std: 0.428962 - Opt: 0.151609 + Std: 0.428962 + Opt: 0.151609 Additionally, it is self-reliant, not requiring e.g. bitstreams from the cipherutils, thus can be easily dropped into a code base. @@ -67,162 +67,162 @@ #define opt_B(s) (((s->b >> 6) ^ (s->b >> 5) ^ (s->b >> 4) ^ (s->b)) & 0x1) #define opt__select(x,y,r) (4 & (((r & (r << 2)) >> 5) ^ ((r & ~(r << 2)) >> 4) ^ ( (r | r << 2) >> 3)))\ - |(2 & (((r | r << 2) >> 6) ^ ( (r | r << 2) >> 1) ^ (r >> 5) ^ r ^ ((x^y) << 1)))\ - |(1 & (((r & ~(r << 2)) >> 4) ^ ((r & (r << 2)) >> 3) ^ r ^ x)) + |(2 & (((r | r << 2) >> 6) ^ ( (r | r << 2) >> 1) ^ (r >> 5) ^ r ^ ((x^y) << 1)))\ + |(1 & (((r & ~(r << 2)) >> 4) ^ ((r & (r << 2)) >> 3) ^ r ^ x)) /* * Some background on the expression above can be found here... uint8_t xopt__select(bool x, bool y, uint8_t r) { - uint8_t r_ls2 = r << 2; - uint8_t r_and_ls2 = r & r_ls2; - uint8_t r_or_ls2 = r | r_ls2; + uint8_t r_ls2 = r << 2; + uint8_t r_and_ls2 = r & r_ls2; + uint8_t r_or_ls2 = r | r_ls2; - //r: r0 r1 r2 r3 r4 r5 r6 r7 - //r_ls2: r2 r3 r4 r5 r6 r7 0 0 - // z0 - // z1 + //r: r0 r1 r2 r3 r4 r5 r6 r7 + //r_ls2: r2 r3 r4 r5 r6 r7 0 0 + // z0 + // z1 -// uint8_t z0 = (r0 & r2) ^ (r1 & ~r3) ^ (r2 | r4); // <-- original - uint8_t z0 = (r_and_ls2 >> 5) ^ ((r & ~r_ls2) >> 4) ^ ( r_or_ls2 >> 3); +// uint8_t z0 = (r0 & r2) ^ (r1 & ~r3) ^ (r2 | r4); // <-- original + uint8_t z0 = (r_and_ls2 >> 5) ^ ((r & ~r_ls2) >> 4) ^ ( r_or_ls2 >> 3); -// uint8_t z1 = (r0 | r2) ^ ( r5 | r7) ^ r1 ^ r6 ^ x ^ y; // <-- original - uint8_t z1 = (r_or_ls2 >> 6) ^ ( r_or_ls2 >> 1) ^ (r >> 5) ^ r ^ ((x^y) << 1); +// uint8_t z1 = (r0 | r2) ^ ( r5 | r7) ^ r1 ^ r6 ^ x ^ y; // <-- original + uint8_t z1 = (r_or_ls2 >> 6) ^ ( r_or_ls2 >> 1) ^ (r >> 5) ^ r ^ ((x^y) << 1); -// uint8_t z2 = (r3 & ~r5) ^ (r4 & r6 ) ^ r7 ^ x; // <-- original - uint8_t z2 = ((r & ~r_ls2) >> 4) ^ (r_and_ls2 >> 3) ^ r ^ x; +// uint8_t z2 = (r3 & ~r5) ^ (r4 & r6 ) ^ r7 ^ x; // <-- original + uint8_t z2 = ((r & ~r_ls2) >> 4) ^ (r_and_ls2 >> 3) ^ r ^ x; - return (z0 & 4) | (z1 & 2) | (z2 & 1); + return (z0 & 4) | (z1 & 2) | (z2 & 1); } */ void opt_successor(const uint8_t* k, State *s, bool y, State* successor) { - uint8_t Tt = 1 & opt_T(s); + uint8_t Tt = 1 & opt_T(s); - successor->t = (s->t >> 1); - successor->t |= (Tt ^ (s->r >> 7 & 0x1) ^ (s->r >> 3 & 0x1)) << 15; + successor->t = (s->t >> 1); + successor->t |= (Tt ^ (s->r >> 7 & 0x1) ^ (s->r >> 3 & 0x1)) << 15; - successor->b = s->b >> 1; - successor->b |= (opt_B(s) ^ (s->r & 0x1)) << 7; + successor->b = s->b >> 1; + successor->b |= (opt_B(s) ^ (s->r & 0x1)) << 7; - successor->r = (k[opt__select(Tt,y,s->r)] ^ successor->b) + s->l ; - successor->l = successor->r+s->r; + successor->r = (k[opt__select(Tt,y,s->r)] ^ successor->b) + s->l ; + successor->l = successor->r+s->r; } void opt_suc(const uint8_t* k,State* s, uint8_t *in, uint8_t length, bool add32Zeroes) { - State x2; - int i; - uint8_t head = 0; - for (i = 0; i < length; i++) { - head = 1 & (in[i] >> 7); - opt_successor(k, s, head, &x2); + State x2; + int i; + uint8_t head = 0; + for (i = 0; i < length; i++) { + head = 1 & (in[i] >> 7); + opt_successor(k, s, head, &x2); - head = 1 & (in[i] >> 6); - opt_successor(k, &x2, head, s); + head = 1 & (in[i] >> 6); + opt_successor(k, &x2, head, s); - head = 1 & (in[i] >> 5); - opt_successor(k, s, head, &x2); + head = 1 & (in[i] >> 5); + opt_successor(k, s, head, &x2); - head = 1 & (in[i] >> 4); - opt_successor(k, &x2, head, s); + head = 1 & (in[i] >> 4); + opt_successor(k, &x2, head, s); - head = 1 & (in[i] >> 3); - opt_successor(k, s, head, &x2); + head = 1 & (in[i] >> 3); + opt_successor(k, s, head, &x2); - head = 1 & (in[i] >> 2); - opt_successor(k, &x2, head, s); + head = 1 & (in[i] >> 2); + opt_successor(k, &x2, head, s); - head = 1 & (in[i] >> 1); - opt_successor(k, s, head, &x2); + head = 1 & (in[i] >> 1); + opt_successor(k, s, head, &x2); - head = 1 & in[i]; - opt_successor(k, &x2, head, s); - } + head = 1 & in[i]; + opt_successor(k, &x2, head, s); + } - //For tag MAC, an additional 32 zeroes - if (add32Zeroes) { - for (i = 0; i < 16; i++) { - opt_successor(k, s, 0, &x2); - opt_successor(k, &x2, 0, s); - } - } + //For tag MAC, an additional 32 zeroes + if (add32Zeroes) { + for (i = 0; i < 16; i++) { + opt_successor(k, s, 0, &x2); + opt_successor(k, &x2, 0, s); + } + } } void opt_output(const uint8_t* k,State* s, uint8_t *buffer) { - uint8_t times = 0; - uint8_t bout = 0; - State temp = {0,0,0,0}; - for ( ; times < 4; times++) { - bout =0; - bout |= (s->r & 0x4) << 5; - opt_successor(k, s, 0, &temp); - bout |= (temp.r & 0x4) << 4; - opt_successor(k, &temp, 0, s); - bout |= (s->r & 0x4) << 3; - opt_successor(k, s, 0, &temp); - bout |= (temp.r & 0x4) << 2; - opt_successor(k, &temp, 0, s); - bout |= (s->r & 0x4) << 1; - opt_successor(k, s, 0, &temp); - bout |= (temp.r & 0x4) ; - opt_successor(k, &temp, 0, s); - bout |= (s->r & 0x4) >> 1; - opt_successor(k, s, 0, &temp); - bout |= (temp.r & 0x4) >> 2; - opt_successor(k, &temp, 0, s); - buffer[times] = bout; - } + uint8_t times = 0; + uint8_t bout = 0; + State temp = {0,0,0,0}; + for ( ; times < 4; times++) { + bout =0; + bout |= (s->r & 0x4) << 5; + opt_successor(k, s, 0, &temp); + bout |= (temp.r & 0x4) << 4; + opt_successor(k, &temp, 0, s); + bout |= (s->r & 0x4) << 3; + opt_successor(k, s, 0, &temp); + bout |= (temp.r & 0x4) << 2; + opt_successor(k, &temp, 0, s); + bout |= (s->r & 0x4) << 1; + opt_successor(k, s, 0, &temp); + bout |= (temp.r & 0x4) ; + opt_successor(k, &temp, 0, s); + bout |= (s->r & 0x4) >> 1; + opt_successor(k, s, 0, &temp); + bout |= (temp.r & 0x4) >> 2; + opt_successor(k, &temp, 0, s); + buffer[times] = bout; + } } void opt_MAC(uint8_t* k, uint8_t* input, uint8_t* out) { - State _init = { - ((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l - ((k[0] ^ 0x4c) + 0x21) & 0xFF,// r - 0x4c, // b - 0xE012 // t - }; + State _init = { + ((k[0] ^ 0x4c) + 0xEC) & 0xFF,// l + ((k[0] ^ 0x4c) + 0x21) & 0xFF,// r + 0x4c, // b + 0xE012 // t + }; - opt_suc(k,&_init,input,12, false); - opt_output(k,&_init, out); + opt_suc(k,&_init,input,12, false); + opt_output(k,&_init, out); } uint8_t rev_byte(uint8_t b) { - b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; - b = (b & 0xCC) >> 2 | (b & 0x33) << 2; - b = (b & 0xAA) >> 1 | (b & 0x55) << 1; + b = (b & 0xF0) >> 4 | (b & 0x0F) << 4; + b = (b & 0xCC) >> 2 | (b & 0x33) << 2; + b = (b & 0xAA) >> 1 | (b & 0x55) << 1; return b; } void opt_reverse_arraybytecpy(uint8_t* dest, uint8_t *src, size_t len) { - uint8_t i; - for ( i =0; i< len ; i++) - dest[i] = rev_byte(src[i]); + uint8_t i; + for ( i =0; i< len ; i++) + dest[i] = rev_byte(src[i]); } void opt_doReaderMAC(uint8_t *cc_nr_p, uint8_t *div_key_p, uint8_t mac[4]) { - static uint8_t cc_nr[12]; - opt_reverse_arraybytecpy(cc_nr, cc_nr_p, 12); - uint8_t dest [] = {0,0,0,0,0,0,0,0}; - opt_MAC(div_key_p, cc_nr, dest); - //The output MAC must also be reversed - opt_reverse_arraybytecpy(mac, dest, 4); - return; + static uint8_t cc_nr[12]; + opt_reverse_arraybytecpy(cc_nr, cc_nr_p, 12); + uint8_t dest [] = {0,0,0,0,0,0,0,0}; + opt_MAC(div_key_p, cc_nr, dest); + //The output MAC must also be reversed + opt_reverse_arraybytecpy(mac, dest, 4); + return; } void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) { - static uint8_t cc_nr[8+4+4]; - opt_reverse_arraybytecpy(cc_nr, cc_p, 12); - State _init = { - ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l - ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r - 0x4c, // b - 0xE012 // t - }; - opt_suc(div_key_p, &_init, cc_nr, 12, true); - uint8_t dest [] = {0,0,0,0}; - opt_output(div_key_p, &_init, dest); - //The output MAC must also be reversed - opt_reverse_arraybytecpy(mac, dest,4); - return; + static uint8_t cc_nr[8+4+4]; + opt_reverse_arraybytecpy(cc_nr, cc_p, 12); + State _init = { + ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l + ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r + 0x4c, // b + 0xE012 // t + }; + opt_suc(div_key_p, &_init, cc_nr, 12, true); + uint8_t dest [] = {0,0,0,0}; + opt_output(div_key_p, &_init, dest); + //The output MAC must also be reversed + opt_reverse_arraybytecpy(mac, dest,4); + return; } /** @@ -234,16 +234,16 @@ void opt_doTagMAC(uint8_t *cc_p, const uint8_t *div_key_p, uint8_t mac[4]) { * @return the cipher state */ State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) { - static uint8_t cc_nr[8]; - opt_reverse_arraybytecpy(cc_nr, cc_p, 8); - State _init = { - ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l - ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r - 0x4c, // b - 0xE012 // t - }; - opt_suc(div_key_p, &_init, cc_nr, 8, false); - return _init; + static uint8_t cc_nr[8]; + opt_reverse_arraybytecpy(cc_nr, cc_p, 8); + State _init = { + ((div_key_p[0] ^ 0x4c) + 0xEC) & 0xFF,// l + ((div_key_p[0] ^ 0x4c) + 0x21) & 0xFF,// r + 0x4c, // b + 0xE012 // t + }; + opt_suc(div_key_p, &_init, cc_nr, 8, false); + return _init; } /** * The second part of the tag MAC calculation, since the CC is already calculated into the state, @@ -255,13 +255,13 @@ State opt_doTagMAC_1(uint8_t *cc_p, const uint8_t *div_key_p) { * @param div_key_p - the key to use */ void opt_doTagMAC_2(State _init, uint8_t* nr, uint8_t mac[4], const uint8_t* div_key_p) { - static uint8_t _nr[4]; - opt_reverse_arraybytecpy(_nr, nr, 4); - opt_suc(div_key_p, &_init,_nr, 4, true); + static uint8_t _nr[4]; + opt_reverse_arraybytecpy(_nr, nr, 4); + opt_suc(div_key_p, &_init,_nr, 4, true); - uint8_t dest [] = {0,0,0,0}; - opt_output(div_key_p, &_init, dest); - //The output MAC must also be reversed - opt_reverse_arraybytecpy(mac, dest,4); - return; + uint8_t dest [] = {0,0,0,0}; + opt_output(div_key_p, &_init, dest); + //The output MAC must also be reversed + opt_reverse_arraybytecpy(mac, dest,4); + return; } diff --git a/armsrc/optimized_cipher.h b/armsrc/optimized_cipher.h index 7398069f0..ad4649d3f 100644 --- a/armsrc/optimized_cipher.h +++ b/armsrc/optimized_cipher.h @@ -8,16 +8,16 @@ /** * Definition 1 (Cipher state). A cipher state of iClass s is an element of F 40/2 * consisting of the following four components: -* 1. the left register l = (l 0 . . . l 7 ) ∈ F 8/2 ; -* 2. the right register r = (r 0 . . . r 7 ) ∈ F 8/2 ; -* 3. the top register t = (t 0 . . . t 15 ) ∈ F 16/2 . -* 4. the bottom register b = (b 0 . . . b 7 ) ∈ F 8/2 . +* 1. the left register l = (l 0 . . . l 7 ) ∈ F 8/2 ; +* 2. the right register r = (r 0 . . . r 7 ) ∈ F 8/2 ; +* 3. the top register t = (t 0 . . . t 15 ) ∈ F 16/2 . +* 4. the bottom register b = (b 0 . . . b 7 ) ∈ F 8/2 . **/ typedef struct { - uint8_t l; - uint8_t r; - uint8_t b; - uint16_t t; + uint8_t l; + uint8_t r; + uint8_t b; + uint16_t t; } State; /** The reader MAC is MAC(key, CC * NR ) diff --git a/armsrc/pcf7931.c b/armsrc/pcf7931.c index 4c8259ea5..be56bc37f 100644 --- a/armsrc/pcf7931.c +++ b/armsrc/pcf7931.c @@ -5,384 +5,384 @@ size_t DemodPCF7931(uint8_t **outBlocks) { uint8_t bits[256] = {0x00}; - uint8_t blocks[8][16]; + uint8_t blocks[8][16]; uint8_t *dest = BigBuf_get_addr(); - int GraphTraceLen = BigBuf_max_traceLen(); - if ( GraphTraceLen > 18000 ) - GraphTraceLen = 18000; + int GraphTraceLen = BigBuf_max_traceLen(); + if ( GraphTraceLen > 18000 ) + GraphTraceLen = 18000; - int i, j, lastval, bitidx, half_switch; - int clock = 64; - int tolerance = clock / 8; - int pmc, block_done; - int lc, warnings = 0; - size_t num_blocks = 0; - int lmin=128, lmax=128; - uint8_t dir; - //clear read buffer - BigBuf_Clear_keep_EM(); + int i, j, lastval, bitidx, half_switch; + int clock = 64; + int tolerance = clock / 8; + int pmc, block_done; + int lc, warnings = 0; + size_t num_blocks = 0; + int lmin=128, lmax=128; + uint8_t dir; + //clear read buffer + BigBuf_Clear_keep_EM(); - LFSetupFPGAForADC(95, true); - DoAcquisition_default(0, true); + LFSetupFPGAForADC(95, true); + DoAcquisition_default(0, true); - lmin = 64; - lmax = 192; + lmin = 64; + lmax = 192; - i = 2; + i = 2; - /* Find first local max/min */ + /* Find first local max/min */ if(dest[1] > dest[0]) { - while(i < GraphTraceLen) { + while(i < GraphTraceLen) { if( !(dest[i] > dest[i-1]) && dest[i] > lmax) - break; - i++; - } - dir = 0; - } else { - while(i < GraphTraceLen) { + break; + i++; + } + dir = 0; + } else { + while(i < GraphTraceLen) { if( !(dest[i] < dest[i-1]) && dest[i] < lmin) - break; - i++; - } - dir = 1; - } + break; + i++; + } + dir = 1; + } - lastval = i++; - half_switch = 0; - pmc = 0; - block_done = 0; + lastval = i++; + half_switch = 0; + pmc = 0; + block_done = 0; - for (bitidx = 0; i < GraphTraceLen; i++) { - if ((dest[i-1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i-1] < dest[i] && dir == 0 && dest[i] < lmin)) { - lc = i - lastval; - lastval = i; + for (bitidx = 0; i < GraphTraceLen; i++) { + if ((dest[i-1] > dest[i] && dir == 1 && dest[i] > lmax) || (dest[i-1] < dest[i] && dir == 0 && dest[i] < lmin)) { + lc = i - lastval; + lastval = i; - // Switch depending on lc length: - // Tolerance is 1/8 of clock rate (arbitrary) - if (ABS(lc-clock/4) < tolerance) { - // 16T0 - if((i - pmc) == lc) { /* 16T0 was previous one */ - /* It's a PMC ! */ - i += (128+127+16+32+33+16)-1; - lastval = i; - pmc = 0; - block_done = 1; - } else { - pmc = i; - } - } else if (ABS(lc-clock/2) < tolerance) { - // 32TO - if((i - pmc) == lc) { /* 16T0 was previous one */ - /* It's a PMC ! */ - i += (128+127+16+32+33)-1; - lastval = i; - pmc = 0; - block_done = 1; - } else if(half_switch == 1) { + // Switch depending on lc length: + // Tolerance is 1/8 of clock rate (arbitrary) + if (ABS(lc-clock/4) < tolerance) { + // 16T0 + if((i - pmc) == lc) { /* 16T0 was previous one */ + /* It's a PMC ! */ + i += (128+127+16+32+33+16)-1; + lastval = i; + pmc = 0; + block_done = 1; + } else { + pmc = i; + } + } else if (ABS(lc-clock/2) < tolerance) { + // 32TO + if((i - pmc) == lc) { /* 16T0 was previous one */ + /* It's a PMC ! */ + i += (128+127+16+32+33)-1; + lastval = i; + pmc = 0; + block_done = 1; + } else if(half_switch == 1) { bits[bitidx++] = 0; - half_switch = 0; - } - else - half_switch++; - } else if (ABS(lc-clock) < tolerance) { - // 64TO + half_switch = 0; + } + else + half_switch++; + } else if (ABS(lc-clock) < tolerance) { + // 64TO bits[bitidx++] = 1; - } else { - // Error - if (++warnings > 10) { - Dbprintf("Error: too many detection errors, aborting."); - return 0; - } - } + } else { + // Error + if (++warnings > 10) { + Dbprintf("Error: too many detection errors, aborting."); + return 0; + } + } - if(block_done == 1) { - if(bitidx == 128) { - for(j = 0; j < 16; ++j) { - blocks[num_blocks][j] = - 128 * bits[j*8 + 7]+ + if(block_done == 1) { + if(bitidx == 128) { + for(j = 0; j < 16; ++j) { + blocks[num_blocks][j] = + 128 * bits[j*8 + 7]+ 64*bits[j*8+6]+ 32*bits[j*8+5]+ 16*bits[j*8+4]+ 8*bits[j*8+3]+ 4*bits[j*8+2]+ 2*bits[j*8+1]+ - bits[j*8] - ; - } - num_blocks++; - } - bitidx = 0; - block_done = 0; - half_switch = 0; - } - if(i < GraphTraceLen) + bits[j*8] + ; + } + num_blocks++; + } + bitidx = 0; + block_done = 0; + half_switch = 0; + } + if(i < GraphTraceLen) dir =(dest[i-1] > dest[i]) ? 0 : 1; - } - if(bitidx==255) - bitidx=0; - warnings = 0; - if(num_blocks == 4) break; - } + } + if(bitidx==255) + bitidx=0; + warnings = 0; + if(num_blocks == 4) break; + } memcpy(outBlocks, blocks, 16*num_blocks); - return num_blocks; + return num_blocks; } bool IsBlock0PCF7931(uint8_t *block) { - // assuming all RFU bits are set to 0 - // if PAC is enabled password is set to 0 - if (block[7] == 0x01) - { - if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7) && !memcmp(block+9, "\x00\x00\x00\x00\x00\x00\x00", 7)) - return true; - } - else if (block[7] == 0x00) - { - if (!memcmp(block+9, "\x00\x00\x00\x00\x00\x00\x00", 7)) - return true; - } - return false; + // assuming all RFU bits are set to 0 + // if PAC is enabled password is set to 0 + if (block[7] == 0x01) + { + if (!memcmp(block, "\x00\x00\x00\x00\x00\x00\x00", 7) && !memcmp(block+9, "\x00\x00\x00\x00\x00\x00\x00", 7)) + return true; + } + else if (block[7] == 0x00) + { + if (!memcmp(block+9, "\x00\x00\x00\x00\x00\x00\x00", 7)) + return true; + } + return false; } bool IsBlock1PCF7931(uint8_t *block) { - // assuming all RFU bits are set to 0 - if (block[10] == 0 && block[11] == 0 && block[12] == 0 && block[13] == 0) - if((block[14] & 0x7f) <= 9 && block[15] <= 9) - return true; + // assuming all RFU bits are set to 0 + if (block[10] == 0 && block[11] == 0 && block[12] == 0 && block[13] == 0) + if((block[14] & 0x7f) <= 9 && block[15] <= 9) + return true; - return false; + return false; } void ReadPCF7931() { - int found_blocks = 0; // successfully read blocks - int max_blocks = 8; // readable blocks - uint8_t memory_blocks[8][17]; // PCF content + int found_blocks = 0; // successfully read blocks + int max_blocks = 8; // readable blocks + uint8_t memory_blocks[8][17]; // PCF content - uint8_t single_blocks[8][17]; // PFC blocks with unknown position - int single_blocks_cnt = 0; + uint8_t single_blocks[8][17]; // PFC blocks with unknown position + int single_blocks_cnt = 0; - size_t n = 0; // transmitted blocks - uint8_t tmp_blocks[4][16]; // temporary read buffer + size_t n = 0; // transmitted blocks + uint8_t tmp_blocks[4][16]; // temporary read buffer - uint8_t found_0_1 = 0; // flag: blocks 0 and 1 were found - int errors = 0; // error counter - int tries = 0; // tries counter + uint8_t found_0_1 = 0; // flag: blocks 0 and 1 were found + int errors = 0; // error counter + int tries = 0; // tries counter - memset(memory_blocks, 0, 8*17*sizeof(uint8_t)); - memset(single_blocks, 0, 8*17*sizeof(uint8_t)); + memset(memory_blocks, 0, 8*17*sizeof(uint8_t)); + memset(single_blocks, 0, 8*17*sizeof(uint8_t)); - int i = 0, j = 0; + int i = 0, j = 0; - do { - i = 0; + do { + i = 0; - memset(tmp_blocks, 0, 4*16*sizeof(uint8_t)); - n = DemodPCF7931((uint8_t**)tmp_blocks); - if(!n) - ++errors; + memset(tmp_blocks, 0, 4*16*sizeof(uint8_t)); + n = DemodPCF7931((uint8_t**)tmp_blocks); + if(!n) + ++errors; - // exit if no block is received - if (errors >= 10 && found_blocks == 0 && single_blocks_cnt == 0) { - Dbprintf("Error, no tag or bad tag"); - return; - } - // exit if too many errors during reading - if (tries > 50 && (2*errors > tries)) { - Dbprintf("Error reading the tag"); - Dbprintf("Here is the partial content"); - goto end; - } + // exit if no block is received + if (errors >= 10 && found_blocks == 0 && single_blocks_cnt == 0) { + Dbprintf("Error, no tag or bad tag"); + return; + } + // exit if too many errors during reading + if (tries > 50 && (2*errors > tries)) { + Dbprintf("Error reading the tag"); + Dbprintf("Here is the partial content"); + goto end; + } - // our logic breaks if we don't get at least two blocks - if (n < 2) { - if (n == 0 || !memcmp(tmp_blocks[0], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) - continue; + // our logic breaks if we don't get at least two blocks + if (n < 2) { + if (n == 0 || !memcmp(tmp_blocks[0], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) + continue; - if (single_blocks_cnt < max_blocks) { - for (i = 0; i < single_blocks_cnt; ++i) { - if (!memcmp(single_blocks[i], tmp_blocks[0], 16)) { - j = 1; - break; - } - } - if (j != 1) { - memcpy(single_blocks[single_blocks_cnt], tmp_blocks[0], 16); - single_blocks_cnt++; - } - j = 0; - } - ++tries; - continue; - } + if (single_blocks_cnt < max_blocks) { + for (i = 0; i < single_blocks_cnt; ++i) { + if (!memcmp(single_blocks[i], tmp_blocks[0], 16)) { + j = 1; + break; + } + } + if (j != 1) { + memcpy(single_blocks[single_blocks_cnt], tmp_blocks[0], 16); + single_blocks_cnt++; + } + j = 0; + } + ++tries; + continue; + } - Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (max_blocks == 0 ? found_blocks : max_blocks), tries, errors); + Dbprintf("(dbg) got %d blocks (%d/%d found) (%d tries, %d errors)", n, found_blocks, (max_blocks == 0 ? found_blocks : max_blocks), tries, errors); - i = 0; - if(!found_0_1) { - while (i < n - 1) { - if (IsBlock0PCF7931(tmp_blocks[i]) && IsBlock1PCF7931(tmp_blocks[i+1])) { - found_0_1 = 1; - memcpy(memory_blocks[0], tmp_blocks[i], 16); - memcpy(memory_blocks[1], tmp_blocks[i+1], 16); - memory_blocks[0][ALLOC] = memory_blocks[1][ALLOC] = 1; - // block 1 tells how many blocks are going to be sent - max_blocks = MAX((memory_blocks[1][14] & 0x7f), memory_blocks[1][15]) + 1; - found_blocks = 2; + i = 0; + if(!found_0_1) { + while (i < n - 1) { + if (IsBlock0PCF7931(tmp_blocks[i]) && IsBlock1PCF7931(tmp_blocks[i+1])) { + found_0_1 = 1; + memcpy(memory_blocks[0], tmp_blocks[i], 16); + memcpy(memory_blocks[1], tmp_blocks[i+1], 16); + memory_blocks[0][ALLOC] = memory_blocks[1][ALLOC] = 1; + // block 1 tells how many blocks are going to be sent + max_blocks = MAX((memory_blocks[1][14] & 0x7f), memory_blocks[1][15]) + 1; + found_blocks = 2; - Dbprintf("Found blocks 0 and 1. PCF is transmitting %d blocks.", max_blocks); + Dbprintf("Found blocks 0 and 1. PCF is transmitting %d blocks.", max_blocks); - // handle the following blocks - for (j = i + 2; j < n; ++j) { - memcpy(memory_blocks[found_blocks], tmp_blocks[j], 16); - memory_blocks[found_blocks][ALLOC] = 1; - ++found_blocks; - } - break; - } - ++i; - } - } else { - // Trying to re-order blocks - // Look for identical block in memory blocks - while (i < n-1) { - // skip all zeroes blocks - if (memcmp(tmp_blocks[i], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) { - for (j = 1; j < max_blocks - 1; ++j) { - if (!memcmp(tmp_blocks[i], memory_blocks[j], 16) && !memory_blocks[j+1][ALLOC]) { - memcpy(memory_blocks[j+1], tmp_blocks[i+1], 16); - memory_blocks[j+1][ALLOC] = 1; - if (++found_blocks >= max_blocks) goto end; - } - } - } - if (memcmp(tmp_blocks[i+1], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) { - for (j = 0; j < max_blocks; ++j) { - if (!memcmp(tmp_blocks[i+1], memory_blocks[j], 16) && !memory_blocks[(j == 0 ? max_blocks : j) -1][ALLOC]) { - if (j == 0) { - memcpy(memory_blocks[max_blocks - 1], tmp_blocks[i], 16); - memory_blocks[max_blocks - 1][ALLOC] = 1; - } else { - memcpy(memory_blocks[j-1], tmp_blocks[i], 16); - memory_blocks[j-1][ALLOC] = 1; - } - if (++found_blocks >= max_blocks) goto end; - } - } - } - ++i; - } - } - ++tries; - if (BUTTON_PRESS()) { - Dbprintf("Button pressed, stopping."); - goto end; - } - } - while (found_blocks != max_blocks); + // handle the following blocks + for (j = i + 2; j < n; ++j) { + memcpy(memory_blocks[found_blocks], tmp_blocks[j], 16); + memory_blocks[found_blocks][ALLOC] = 1; + ++found_blocks; + } + break; + } + ++i; + } + } else { + // Trying to re-order blocks + // Look for identical block in memory blocks + while (i < n-1) { + // skip all zeroes blocks + if (memcmp(tmp_blocks[i], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) { + for (j = 1; j < max_blocks - 1; ++j) { + if (!memcmp(tmp_blocks[i], memory_blocks[j], 16) && !memory_blocks[j+1][ALLOC]) { + memcpy(memory_blocks[j+1], tmp_blocks[i+1], 16); + memory_blocks[j+1][ALLOC] = 1; + if (++found_blocks >= max_blocks) goto end; + } + } + } + if (memcmp(tmp_blocks[i+1], "\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00", 16)) { + for (j = 0; j < max_blocks; ++j) { + if (!memcmp(tmp_blocks[i+1], memory_blocks[j], 16) && !memory_blocks[(j == 0 ? max_blocks : j) -1][ALLOC]) { + if (j == 0) { + memcpy(memory_blocks[max_blocks - 1], tmp_blocks[i], 16); + memory_blocks[max_blocks - 1][ALLOC] = 1; + } else { + memcpy(memory_blocks[j-1], tmp_blocks[i], 16); + memory_blocks[j-1][ALLOC] = 1; + } + if (++found_blocks >= max_blocks) goto end; + } + } + } + ++i; + } + } + ++tries; + if (BUTTON_PRESS()) { + Dbprintf("Button pressed, stopping."); + goto end; + } + } + while (found_blocks != max_blocks); end: - Dbprintf("-----------------------------------------"); - Dbprintf("Memory content:"); - Dbprintf("-----------------------------------------"); - for (i = 0; i < max_blocks; ++i) { - if (memory_blocks[i][ALLOC]) - print_result("Block", memory_blocks[i], 16); - else - Dbprintf("", i); - } - Dbprintf("-----------------------------------------"); + Dbprintf("-----------------------------------------"); + Dbprintf("Memory content:"); + Dbprintf("-----------------------------------------"); + for (i = 0; i < max_blocks; ++i) { + if (memory_blocks[i][ALLOC]) + print_result("Block", memory_blocks[i], 16); + else + Dbprintf("", i); + } + Dbprintf("-----------------------------------------"); - if (found_blocks < max_blocks) { - Dbprintf("-----------------------------------------"); - Dbprintf("Blocks with unknown position:"); - Dbprintf("-----------------------------------------"); - for (i = 0; i < single_blocks_cnt; ++i) - print_result("Block", single_blocks[i], 16); + if (found_blocks < max_blocks) { + Dbprintf("-----------------------------------------"); + Dbprintf("Blocks with unknown position:"); + Dbprintf("-----------------------------------------"); + for (i = 0; i < single_blocks_cnt; ++i) + print_result("Block", single_blocks[i], 16); - Dbprintf("-----------------------------------------"); - } - cmd_send(CMD_ACK,0,0,0,0,0); + Dbprintf("-----------------------------------------"); + } + cmd_send(CMD_ACK,0,0,0,0,0); } static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) { - uint32_t tab[1024] = {0}; // data times frame - uint32_t u = 0; - uint8_t parity = 0; - bool comp = 0; + uint32_t tab[1024] = {0}; // data times frame + uint32_t u = 0; + uint8_t parity = 0; + bool comp = 0; - //BUILD OF THE DATA FRAME - //alimentation of the tag (time for initializing) - AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab); - AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab); - //password indication bit - AddBitPCF7931(1, tab, l, p); - //password (on 56 bits) - AddBytePCF7931(pass[0], tab, l, p); - AddBytePCF7931(pass[1], tab, l, p); - AddBytePCF7931(pass[2], tab, l, p); - AddBytePCF7931(pass[3], tab, l, p); - AddBytePCF7931(pass[4], tab, l, p); - AddBytePCF7931(pass[5], tab, l, p); - AddBytePCF7931(pass[6], tab, l, p); - //programming mode (0 or 1) - AddBitPCF7931(0, tab, l, p); + //BUILD OF THE DATA FRAME + //alimentation of the tag (time for initializing) + AddPatternPCF7931(init_delay, 0, 8192/2*T0_PCF, tab); + AddPatternPCF7931(8192/2*T0_PCF + 319*T0_PCF+70, 3*T0_PCF, 29*T0_PCF, tab); + //password indication bit + AddBitPCF7931(1, tab, l, p); + //password (on 56 bits) + AddBytePCF7931(pass[0], tab, l, p); + AddBytePCF7931(pass[1], tab, l, p); + AddBytePCF7931(pass[2], tab, l, p); + AddBytePCF7931(pass[3], tab, l, p); + AddBytePCF7931(pass[4], tab, l, p); + AddBytePCF7931(pass[5], tab, l, p); + AddBytePCF7931(pass[6], tab, l, p); + //programming mode (0 or 1) + AddBitPCF7931(0, tab, l, p); - //block adress on 6 bits - for (u = 0; u < 6; ++u) { - if (address&(1< 0xFFFF){ - tab[u] -= 0xFFFF; - comp = 0; - } - } + //compensation of the counter reload + while (!comp){ + comp = 1; + for (u = 0; tab[u] != 0; ++u) + if(tab[u] > 0xFFFF){ + tab[u] -= 0xFFFF; + comp = 0; + } + } - SendCmdPCF7931(tab); + SendCmdPCF7931(tab); } /* Write on a byte of a PCF7931 tag @@ -391,16 +391,16 @@ static void RealWritePCF7931(uint8_t *pass, uint16_t init_delay, int32_t l, int3 @param data : data to write */ void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, uint8_t pass5, uint8_t pass6, uint8_t pass7, uint16_t init_delay, int32_t l, int32_t p, uint8_t address, uint8_t byte, uint8_t data) { - Dbprintf("Initialization delay : %d us", init_delay); - Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p); - Dbprintf("Password (LSB first on each byte): %02x %02x %02x %02x %02x %02x %02x", pass1, pass2, pass3, pass4, pass5, pass6, pass7); - Dbprintf("Block address : %02x", address); - Dbprintf("Byte address : %02x", byte); - Dbprintf("Data : %02x", data); + Dbprintf("Initialization delay : %d us", init_delay); + Dbprintf("Offsets : %d us on the low pulses width, %d us on the low pulses positions", l, p); + Dbprintf("Password (LSB first on each byte): %02x %02x %02x %02x %02x %02x %02x", pass1, pass2, pass3, pass4, pass5, pass6, pass7); + Dbprintf("Block address : %02x", address); + Dbprintf("Byte address : %02x", byte); + Dbprintf("Data : %02x", data); - uint8_t password[7] = {pass1, pass2, pass3, pass4, pass5, pass6, pass7}; + uint8_t password[7] = {pass1, pass2, pass3, pass4, pass5, pass6, pass7}; - RealWritePCF7931 (password, init_delay, l, p, address, byte, data); + RealWritePCF7931 (password, init_delay, l, p, address, byte, data); } @@ -409,52 +409,52 @@ void WritePCF7931(uint8_t pass1, uint8_t pass2, uint8_t pass3, uint8_t pass4, ui */ void SendCmdPCF7931(uint32_t * tab){ - uint16_t u=0, tempo=0; + uint16_t u=0, tempo=0; - Dbprintf("Sending data frame..."); + Dbprintf("Sending data frame..."); - FpgaDownloadAndGo(FPGA_BITSTREAM_LF); - FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz - FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU ); + FpgaDownloadAndGo(FPGA_BITSTREAM_LF); + FpgaSendCommand(FPGA_CMD_SET_DIVISOR, 95); //125Khz + FpgaWriteConfWord(FPGA_MAJOR_MODE_LF_PASSTHRU ); - LED_A_ON(); + LED_A_ON(); - // steal this pin from the SSP and use it to control the modulation - AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; - AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; + // steal this pin from the SSP and use it to control the modulation + AT91C_BASE_PIOA->PIO_PER = GPIO_SSC_DOUT; + AT91C_BASE_PIOA->PIO_OER = GPIO_SSC_DOUT; - //initialization of the timer - AT91C_BASE_PMC->PMC_PCER |= (0x1 << AT91C_ID_TC0); - AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; //clock at 48/32 MHz - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN; - AT91C_BASE_TCB->TCB_BCR = 1; + //initialization of the timer + AT91C_BASE_PMC->PMC_PCER |= (0x1 << AT91C_ID_TC0); + AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK; //clock at 48/32 MHz + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN; + AT91C_BASE_TCB->TCB_BCR = 1; - tempo = AT91C_BASE_TC0->TC_CV; - for( u = 0; tab[u] != 0; u += 3){ - // modulate antenna - HIGH(GPIO_SSC_DOUT); - while (tempo != tab[u]) - tempo = AT91C_BASE_TC0->TC_CV; + tempo = AT91C_BASE_TC0->TC_CV; + for( u = 0; tab[u] != 0; u += 3){ + // modulate antenna + HIGH(GPIO_SSC_DOUT); + while (tempo != tab[u]) + tempo = AT91C_BASE_TC0->TC_CV; - // stop modulating antenna - LOW(GPIO_SSC_DOUT); - while (tempo != tab[u+1]) - tempo = AT91C_BASE_TC0->TC_CV; + // stop modulating antenna + LOW(GPIO_SSC_DOUT); + while (tempo != tab[u+1]) + tempo = AT91C_BASE_TC0->TC_CV; - // modulate antenna - HIGH(GPIO_SSC_DOUT); - while (tempo != tab[u+2]) - tempo = AT91C_BASE_TC0->TC_CV; - } + // modulate antenna + HIGH(GPIO_SSC_DOUT); + while (tempo != tab[u+2]) + tempo = AT91C_BASE_TC0->TC_CV; + } - LED_A_OFF(); - FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); - SpinDelay(200); + LED_A_OFF(); + FpgaWriteConfWord(FPGA_MAJOR_MODE_OFF); + SpinDelay(200); - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable - LED(0xFFFF, 1000); + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable + LED(0xFFFF, 1000); } @@ -465,16 +465,16 @@ void SendCmdPCF7931(uint32_t * tab){ * @param p : offset on low pulse positioning */ bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){ - uint32_t u; - for (u = 0; u < 8; ++u) { - if (byte & (1 << u)) { //bit is 1 - if( AddBitPCF7931(1, tab, l, p)==1) return 1; - } else { //bit is 0 - if (AddBitPCF7931(0, tab, l, p)==1) return 1; - } - } + uint32_t u; + for (u = 0; u < 8; ++u) { + if (byte & (1 << u)) { //bit is 1 + if( AddBitPCF7931(1, tab, l, p)==1) return 1; + } else { //bit is 0 + if (AddBitPCF7931(0, tab, l, p)==1) return 1; + } + } - return 0; + return 0; } /* Add a bits for building the data frame of PCF7931 tags @@ -484,32 +484,32 @@ bool AddBytePCF7931(uint8_t byte, uint32_t * tab, int32_t l, int32_t p){ * @param p : offset on low pulse positioning */ bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p){ - uint8_t u = 0; + uint8_t u = 0; - //we put the cursor at the last value of the array - for ( u = 0; tab[u] != 0; u += 3 ) { } + //we put the cursor at the last value of the array + for ( u = 0; tab[u] != 0; u += 3 ) { } - if ( b == 1 ) { //add a bit 1 - if ( u == 0 ) - tab[u] = 34 * T0_PCF + p; - else - tab[u] = 34 * T0_PCF + tab[u-1] + p; + if ( b == 1 ) { //add a bit 1 + if ( u == 0 ) + tab[u] = 34 * T0_PCF + p; + else + tab[u] = 34 * T0_PCF + tab[u-1] + p; - tab[u+1] = 6 * T0_PCF + tab[u] + l; - tab[u+2] = 88 * T0_PCF + tab[u+1] - l - p; - return 0; - } else { //add a bit 0 + tab[u+1] = 6 * T0_PCF + tab[u] + l; + tab[u+2] = 88 * T0_PCF + tab[u+1] - l - p; + return 0; + } else { //add a bit 0 - if ( u == 0 ) - tab[u] = 98 * T0_PCF + p; - else - tab[u] = 98 * T0_PCF + tab[u-1] + p; + if ( u == 0 ) + tab[u] = 98 * T0_PCF + p; + else + tab[u] = 98 * T0_PCF + tab[u-1] + p; - tab[u+1] = 6 * T0_PCF + tab[u] + l; - tab[u+2] = 24 * T0_PCF + tab[u+1] - l - p; - return 0; - } - return 1; + tab[u+1] = 6 * T0_PCF + tab[u] + l; + tab[u+2] = 24 * T0_PCF + tab[u+1] - l - p; + return 0; + } + return 1; } /* Add a custom pattern in the data frame @@ -519,12 +519,12 @@ bool AddBitPCF7931(bool b, uint32_t * tab, int32_t l, int32_t p){ * @param tab : array of the data frame */ bool AddPatternPCF7931(uint32_t a, uint32_t b, uint32_t c, uint32_t * tab){ - uint32_t u = 0; - for(u = 0; tab[u] != 0; u += 3){} //we put the cursor at the last value of the array + uint32_t u = 0; + for(u = 0; tab[u] != 0; u += 3){} //we put the cursor at the last value of the array - tab[u] = (u == 0) ? a : a + tab[u-1]; - tab[u+1] = b + tab[u]; - tab[u+2] = c + tab[u+1]; + tab[u] = (u == 0) ? a : a + tab[u-1]; + tab[u+1] = b + tab[u]; + tab[u+2] = c + tab[u+1]; - return 0; + return 0; } \ No newline at end of file diff --git a/armsrc/printf.c b/armsrc/printf.c index c148bc9fd..ff48dec1c 100644 --- a/armsrc/printf.c +++ b/armsrc/printf.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 1986, 1988, 1991, 1993 - * The Regents of the University of California. All rights reserved. + * The Regents of the University of California. All rights reserved. * (c) UNIX System Laboratories, Inc. * All or some portions of this file are derived from material licensed * to the University of California by American Telephone and Telegraph @@ -31,7 +31,7 @@ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * - * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 + * @(#)subr_prf.c 8.3 (Berkeley) 1/21/94 */ #include "printf.h" @@ -50,7 +50,7 @@ char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz"; #define toupper(c) ((c) - 0x20 * (((c) >= 'a') && ((c) <= 'z'))) /* Max number conversion buffer length: a u_quad_t in base 2, plus NUL byte. */ -#define MAXNBUF (sizeof(intmax_t) * NBBY + 1) +#define MAXNBUF (sizeof(intmax_t) * NBBY + 1) /* * Put a NUL-terminated ASCII number (base <= 36) in a buffer in reverse @@ -61,17 +61,17 @@ char const hex2ascii_data[] = "0123456789abcdefghijklmnopqrstuvwxyz"; static char * ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) { - char *p, c; + char *p, c; - p = nbuf; - *p = '\0'; - do { - c = hex2ascii(num % base); - *++p = upper ? toupper(c) : c; - } while (num /= base); - if (lenp) - *lenp = p - nbuf; - return (p); + p = nbuf; + *p = '\0'; + do { + c = hex2ascii(num % base); + *++p = upper ? toupper(c) : c; + } while (num /= base); + if (lenp) + *lenp = p - nbuf; + return (p); } /* @@ -82,7 +82,7 @@ ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) * The format %b is supported to decode error registers. * Its usage is: * - * printf("reg=%b\n", regval, "*"); + * printf("reg=%b\n", regval, "*"); * * where is the output base expressed as a control character, e.g. * \10 gives octal; \20 gives hex. Each arg is a sequence of characters, @@ -90,340 +90,340 @@ ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper) * the next characters (up to a control character, i.e. a character <= 32), * give the name of the register. Thus: * - * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); + * kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n"); * * would produce output: * - * reg=3 + * reg=3 * * XXX: %D -- Hexdump, takes pointer and separator string: - * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX - * ("%*D", len, ptr, " " -> XX XX XX XX ... + * ("%6D", ptr, ":") -> XX:XX:XX:XX:XX:XX + * ("%*D", len, ptr, " " -> XX XX XX XX ... */ int kvsprintf(char const *fmt, void *arg, int radix, va_list ap) { #define PCHAR(c) {int cc=(c); *d++ = cc; retval++; } - char nbuf[MAXNBUF]; - char *d; - const char *p, *percent, *q; - u_char *up; - int ch, n; - uintmax_t num; - int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; - int cflag, hflag, jflag, tflag, zflag; - int dwidth, upper; - char padc; - int stop = 0, retval = 0; + char nbuf[MAXNBUF]; + char *d; + const char *p, *percent, *q; + u_char *up; + int ch, n; + uintmax_t num; + int base, lflag, qflag, tmp, width, ladjust, sharpflag, neg, sign, dot; + int cflag, hflag, jflag, tflag, zflag; + int dwidth, upper; + char padc; + int stop = 0, retval = 0; - num = 0; - d = (char *) arg; + num = 0; + d = (char *) arg; - if (fmt == NULL) - fmt = "(fmt null)\n"; + if (fmt == NULL) + fmt = "(fmt null)\n"; - if (radix < 2 || radix > 36) - radix = 10; + if (radix < 2 || radix > 36) + radix = 10; - for (;;) { - padc = ' '; - width = 0; - while ((ch = (u_char)*fmt++) != '%' || stop) { - PCHAR(ch); - if (ch == '\0') - return (retval); - } - percent = fmt - 1; - qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; - sign = 0; dot = 0; dwidth = 0; upper = 0; - cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; -reswitch: switch (ch = (u_char)*fmt++) { - case '.': - dot = 1; - goto reswitch; - case '#': - sharpflag = 1; - goto reswitch; - case '+': - sign = 1; - goto reswitch; - case '-': - ladjust = 1; - goto reswitch; - case '%': - PCHAR(ch); - break; - case '*': - if (!dot) { - width = va_arg(ap, int); - if (width < 0) { - ladjust = !ladjust; - width = -width; - } - } else { - dwidth = va_arg(ap, int); - } - goto reswitch; - case '0': - if (!dot) { - padc = '0'; - goto reswitch; - } - case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - for (n = 0;; ++fmt) { - n = n * 10 + ch - '0'; - ch = *fmt; - if (ch < '0' || ch > '9') - break; - } - if (dot) - dwidth = n; - else - width = n; - goto reswitch; - case 'b': - num = (u_int)va_arg(ap, int); - p = va_arg(ap, char *); - for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) - PCHAR(*q--); + for (;;) { + padc = ' '; + width = 0; + while ((ch = (u_char)*fmt++) != '%' || stop) { + PCHAR(ch); + if (ch == '\0') + return (retval); + } + percent = fmt - 1; + qflag = 0; lflag = 0; ladjust = 0; sharpflag = 0; neg = 0; + sign = 0; dot = 0; dwidth = 0; upper = 0; + cflag = 0; hflag = 0; jflag = 0; tflag = 0; zflag = 0; +reswitch: switch (ch = (u_char)*fmt++) { + case '.': + dot = 1; + goto reswitch; + case '#': + sharpflag = 1; + goto reswitch; + case '+': + sign = 1; + goto reswitch; + case '-': + ladjust = 1; + goto reswitch; + case '%': + PCHAR(ch); + break; + case '*': + if (!dot) { + width = va_arg(ap, int); + if (width < 0) { + ladjust = !ladjust; + width = -width; + } + } else { + dwidth = va_arg(ap, int); + } + goto reswitch; + case '0': + if (!dot) { + padc = '0'; + goto reswitch; + } + case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + for (n = 0;; ++fmt) { + n = n * 10 + ch - '0'; + ch = *fmt; + if (ch < '0' || ch > '9') + break; + } + if (dot) + dwidth = n; + else + width = n; + goto reswitch; + case 'b': + num = (u_int)va_arg(ap, int); + p = va_arg(ap, char *); + for (q = ksprintn(nbuf, num, *p++, NULL, 0); *q;) + PCHAR(*q--); - if (num == 0) - break; + if (num == 0) + break; - for (tmp = 0; *p;) { - n = *p++; - if (num & (1 << (n - 1))) { - PCHAR(tmp ? ',' : '<'); - for (; (n = *p) > ' '; ++p) - PCHAR(n); - tmp = 1; - } else - for (; *p > ' '; ++p) - continue; - } - if (tmp) - PCHAR('>'); - break; - case 'c': - PCHAR(va_arg(ap, int)); - break; - case 'D': - up = va_arg(ap, u_char *); - p = va_arg(ap, char *); - if (!width) - width = 16; - while(width--) { - PCHAR(hex2ascii(*up >> 4)); - PCHAR(hex2ascii(*up & 0x0f)); - up++; - if (width) - for (q=p;*q;q++) - PCHAR(*q); - } - break; - case 'd': - case 'i': - base = 10; - sign = 1; - goto handle_sign; - case 'h': - if (hflag) { - hflag = 0; - cflag = 1; - } else - hflag = 1; - goto reswitch; - case 'j': - jflag = 1; - goto reswitch; - case 'l': - if (lflag) { - lflag = 0; - qflag = 1; - } else - lflag = 1; - goto reswitch; - case 'n': - if (jflag) - *(va_arg(ap, intmax_t *)) = retval; - else if (qflag) - *(va_arg(ap, quad_t *)) = retval; - else if (lflag) - *(va_arg(ap, long *)) = retval; - else if (zflag) - *(va_arg(ap, size_t *)) = retval; - else if (hflag) - *(va_arg(ap, short *)) = retval; - else if (cflag) - *(va_arg(ap, char *)) = retval; - else - *(va_arg(ap, int *)) = retval; - break; - case 'o': - base = 8; - goto handle_nosign; - case 'p': - base = 16; - sharpflag = (width == 0); - sign = 0; - num = (uintptr_t)va_arg(ap, void *); - goto number; - case 'q': - qflag = 1; - goto reswitch; - case 'r': - base = radix; - if (sign) - goto handle_sign; - goto handle_nosign; - case 's': - p = va_arg(ap, char *); - if (p == NULL) - p = "(null)"; - if (!dot) - n = strlen (p); - else - for (n = 0; n < dwidth && p[n]; n++) - continue; + for (tmp = 0; *p;) { + n = *p++; + if (num & (1 << (n - 1))) { + PCHAR(tmp ? ',' : '<'); + for (; (n = *p) > ' '; ++p) + PCHAR(n); + tmp = 1; + } else + for (; *p > ' '; ++p) + continue; + } + if (tmp) + PCHAR('>'); + break; + case 'c': + PCHAR(va_arg(ap, int)); + break; + case 'D': + up = va_arg(ap, u_char *); + p = va_arg(ap, char *); + if (!width) + width = 16; + while(width--) { + PCHAR(hex2ascii(*up >> 4)); + PCHAR(hex2ascii(*up & 0x0f)); + up++; + if (width) + for (q=p;*q;q++) + PCHAR(*q); + } + break; + case 'd': + case 'i': + base = 10; + sign = 1; + goto handle_sign; + case 'h': + if (hflag) { + hflag = 0; + cflag = 1; + } else + hflag = 1; + goto reswitch; + case 'j': + jflag = 1; + goto reswitch; + case 'l': + if (lflag) { + lflag = 0; + qflag = 1; + } else + lflag = 1; + goto reswitch; + case 'n': + if (jflag) + *(va_arg(ap, intmax_t *)) = retval; + else if (qflag) + *(va_arg(ap, quad_t *)) = retval; + else if (lflag) + *(va_arg(ap, long *)) = retval; + else if (zflag) + *(va_arg(ap, size_t *)) = retval; + else if (hflag) + *(va_arg(ap, short *)) = retval; + else if (cflag) + *(va_arg(ap, char *)) = retval; + else + *(va_arg(ap, int *)) = retval; + break; + case 'o': + base = 8; + goto handle_nosign; + case 'p': + base = 16; + sharpflag = (width == 0); + sign = 0; + num = (uintptr_t)va_arg(ap, void *); + goto number; + case 'q': + qflag = 1; + goto reswitch; + case 'r': + base = radix; + if (sign) + goto handle_sign; + goto handle_nosign; + case 's': + p = va_arg(ap, char *); + if (p == NULL) + p = "(null)"; + if (!dot) + n = strlen (p); + else + for (n = 0; n < dwidth && p[n]; n++) + continue; - width -= n; + width -= n; - if (!ladjust && width > 0) - while (width--) - PCHAR(padc); - while (n--) - PCHAR(*p++); - if (ladjust && width > 0) - while (width--) - PCHAR(padc); - break; - case 't': - tflag = 1; - goto reswitch; - case 'u': - base = 10; - goto handle_nosign; - case 'X': - upper = 1; - case 'x': - base = 16; - goto handle_nosign; - case 'y': - base = 16; - sign = 1; - goto handle_sign; - case 'z': - zflag = 1; - goto reswitch; + if (!ladjust && width > 0) + while (width--) + PCHAR(padc); + while (n--) + PCHAR(*p++); + if (ladjust && width > 0) + while (width--) + PCHAR(padc); + break; + case 't': + tflag = 1; + goto reswitch; + case 'u': + base = 10; + goto handle_nosign; + case 'X': + upper = 1; + case 'x': + base = 16; + goto handle_nosign; + case 'y': + base = 16; + sign = 1; + goto handle_sign; + case 'z': + zflag = 1; + goto reswitch; handle_nosign: - sign = 0; - if (jflag) - num = va_arg(ap, uintmax_t); - else if (qflag) - num = va_arg(ap, u_quad_t); - else if (tflag) - num = va_arg(ap, ptrdiff_t); - else if (lflag) - num = va_arg(ap, u_long); - else if (zflag) - num = va_arg(ap, size_t); - else if (hflag) - num = (u_short)va_arg(ap, int); - else if (cflag) - num = (u_char)va_arg(ap, int); - else - num = va_arg(ap, u_int); - goto number; + sign = 0; + if (jflag) + num = va_arg(ap, uintmax_t); + else if (qflag) + num = va_arg(ap, u_quad_t); + else if (tflag) + num = va_arg(ap, ptrdiff_t); + else if (lflag) + num = va_arg(ap, u_long); + else if (zflag) + num = va_arg(ap, size_t); + else if (hflag) + num = (u_short)va_arg(ap, int); + else if (cflag) + num = (u_char)va_arg(ap, int); + else + num = va_arg(ap, u_int); + goto number; handle_sign: - if (jflag) - num = va_arg(ap, intmax_t); - else if (qflag) - num = va_arg(ap, quad_t); - else if (tflag) - num = va_arg(ap, ptrdiff_t); - else if (lflag) - num = va_arg(ap, long); - else if (zflag) - num = va_arg(ap, ssize_t); - else if (hflag) - num = (short)va_arg(ap, int); - else if (cflag) - num = (char)va_arg(ap, int); - else - num = va_arg(ap, int); + if (jflag) + num = va_arg(ap, intmax_t); + else if (qflag) + num = va_arg(ap, quad_t); + else if (tflag) + num = va_arg(ap, ptrdiff_t); + else if (lflag) + num = va_arg(ap, long); + else if (zflag) + num = va_arg(ap, ssize_t); + else if (hflag) + num = (short)va_arg(ap, int); + else if (cflag) + num = (char)va_arg(ap, int); + else + num = va_arg(ap, int); number: - if (sign && (intmax_t)num < 0) { - neg = 1; - num = -(intmax_t)num; - } - p = ksprintn(nbuf, num, base, &tmp, upper); - if (sharpflag && num != 0) { - if (base == 8) - tmp++; - else if (base == 16) - tmp += 2; - } - if (neg) - tmp++; + if (sign && (intmax_t)num < 0) { + neg = 1; + num = -(intmax_t)num; + } + p = ksprintn(nbuf, num, base, &tmp, upper); + if (sharpflag && num != 0) { + if (base == 8) + tmp++; + else if (base == 16) + tmp += 2; + } + if (neg) + tmp++; - if (!ladjust && padc != '0' && width - && (width -= tmp) > 0) - while (width--) - PCHAR(padc); - if (neg) - PCHAR('-'); - if (sharpflag && num != 0) { - if (base == 8) { - PCHAR('0'); - } else if (base == 16) { - PCHAR('0'); - PCHAR('x'); - } - } - if (!ladjust && width && (width -= tmp) > 0) - while (width--) - PCHAR(padc); + if (!ladjust && padc != '0' && width + && (width -= tmp) > 0) + while (width--) + PCHAR(padc); + if (neg) + PCHAR('-'); + if (sharpflag && num != 0) { + if (base == 8) { + PCHAR('0'); + } else if (base == 16) { + PCHAR('0'); + PCHAR('x'); + } + } + if (!ladjust && width && (width -= tmp) > 0) + while (width--) + PCHAR(padc); - while (*p) - PCHAR(*p--); + while (*p) + PCHAR(*p--); - if (ladjust && width && (width -= tmp) > 0) - while (width--) - PCHAR(padc); + if (ladjust && width && (width -= tmp) > 0) + while (width--) + PCHAR(padc); - break; - default: - while (percent < fmt) - PCHAR(*percent++); - /* - * Since we ignore an formatting argument it is no - * longer safe to obey the remaining formatting - * arguments as the arguments will no longer match - * the format specs. - */ - stop = 1; - break; - } - } - PCHAR(0); - return retval; + break; + default: + while (percent < fmt) + PCHAR(*percent++); + /* + * Since we ignore an formatting argument it is no + * longer safe to obey the remaining formatting + * arguments as the arguments will no longer match + * the format specs. + */ + stop = 1; + break; + } + } + PCHAR(0); + return retval; #undef PCHAR } int vsprintf(char *dest, const char *fmt, va_list ap) { - return kvsprintf(fmt, dest, 10, ap); + return kvsprintf(fmt, dest, 10, ap); } int sprintf(char *dest, const char *fmt, ...) { - /* http://www.pagetable.com/?p=298 */ - int retval; - va_list ap; - va_start(ap, fmt); - retval = kvsprintf(fmt, dest, 10, ap); - va_end(ap); - return retval; + /* http://www.pagetable.com/?p=298 */ + int retval; + va_list ap; + va_start(ap, fmt); + retval = kvsprintf(fmt, dest, 10, ap); + va_end(ap); + return retval; } diff --git a/armsrc/start.c b/armsrc/start.c index 5d55f24e0..dcec6f59a 100644 --- a/armsrc/start.c +++ b/armsrc/start.c @@ -23,62 +23,62 @@ extern char __data_src_start__, __data_start__, __data_end__, __bss_start__, __b static voidpf inflate_malloc(voidpf opaque, uInt items, uInt size) { - uint8_t *allocated_memory; + uint8_t *allocated_memory; - allocated_memory = next_free_memory; - next_free_memory += items*size; - return allocated_memory; + allocated_memory = next_free_memory; + next_free_memory += items*size; + return allocated_memory; } static void inflate_free(voidpf opaque, voidpf address) { - // nothing to do + // nothing to do } static void uncompress_data_section(void) { - z_stream data_section; + z_stream data_section; - next_free_memory = BigBuf_get_addr(); + next_free_memory = BigBuf_get_addr(); - // initialize zstream structure - data_section.next_in = (uint8_t *) &__data_src_start__; - data_section.avail_in = &__data_end__ - &__data_start__; // uncompressed size. Wrong but doesn't matter. - data_section.next_out = (uint8_t *) &__data_start__; - data_section.avail_out = &__data_end__ - &__data_start__; // uncompressed size. Correct. - data_section.zalloc = &inflate_malloc; - data_section.zfree = &inflate_free; - data_section.opaque = NULL; + // initialize zstream structure + data_section.next_in = (uint8_t *) &__data_src_start__; + data_section.avail_in = &__data_end__ - &__data_start__; // uncompressed size. Wrong but doesn't matter. + data_section.next_out = (uint8_t *) &__data_start__; + data_section.avail_out = &__data_end__ - &__data_start__; // uncompressed size. Correct. + data_section.zalloc = &inflate_malloc; + data_section.zfree = &inflate_free; + data_section.opaque = NULL; - // initialize zlib for inflate - inflateInit2(&data_section, 15); + // initialize zlib for inflate + inflateInit2(&data_section, 15); - // uncompress data segment to RAM - inflate(&data_section, Z_FINISH); + // uncompress data segment to RAM + inflate(&data_section, Z_FINISH); - // save the size of the compressed data section - common_area.arg1 = data_section.total_in; + // save the size of the compressed data section + common_area.arg1 = data_section.total_in; } void __attribute__((section(".startos"))) Vector(void) { - /* Stack should have been set up by the bootloader */ - // char *src; - char *dst, *end; + /* Stack should have been set up by the bootloader */ + // char *src; + char *dst, *end; - uncompress_data_section(); + uncompress_data_section(); - /* Set up (that is: clear) BSS. */ - dst = &__bss_start__; - end = &__bss_end__; - while(dst < end) *dst++ = 0; + /* Set up (that is: clear) BSS. */ + dst = &__bss_start__; + end = &__bss_end__; + while(dst < end) *dst++ = 0; - // Set up data segment: Copy from flash to ram - // src = &__data_src_start__; - // dst = &__data_start__; - // end = &__data_end__; - // while(dst < end) *dst++ = *src++; + // Set up data segment: Copy from flash to ram + // src = &__data_src_start__; + // dst = &__data_start__; + // end = &__data_end__; + // while(dst < end) *dst++ = *src++; - AppMain(); + AppMain(); } #endif \ No newline at end of file diff --git a/armsrc/string.c b/armsrc/string.c index 6552ce1c9..e63ba4b05 100644 --- a/armsrc/string.c +++ b/armsrc/string.c @@ -11,39 +11,39 @@ void *memcpy(void *dest, const void *src, int len) { - uint8_t *d = dest; - const uint8_t *s = src; - while((len--) > 0) { - *d = *s; - d++; - s++; - } - return dest; + uint8_t *d = dest; + const uint8_t *s = src; + while((len--) > 0) { + *d = *s; + d++; + s++; + } + return dest; } void *memset(void *dest, int c, int len) { - uint8_t *d = dest; - while((len--) > 0) { - *d = c; - d++; - } - return dest; + uint8_t *d = dest; + while((len--) > 0) { + *d = c; + d++; + } + return dest; } int memcmp(const void *av, const void *bv, int len) { - const uint8_t *a = av; - const uint8_t *b = bv; + const uint8_t *a = av; + const uint8_t *b = bv; - while((len--) > 0) { - if(*a != *b) { - return *a - *b; - } - a++; - b++; - } - return 0; + while((len--) > 0) { + if(*a != *b) { + return *a - *b; + } + a++; + b++; + } + return 0; } void memxor(uint8_t * dest, uint8_t * src, size_t len) { @@ -53,36 +53,36 @@ void memxor(uint8_t * dest, uint8_t * src, size_t len) { int strlen(const char *str) { - int l = 0; - while(*str) { - l++; - str++; - } - return l; + int l = 0; + while(*str) { + l++; + str++; + } + return l; } char* strncat(char *dest, const char *src, unsigned int n) { - unsigned int dest_len = strlen(dest); - unsigned int i; + unsigned int dest_len = strlen(dest); + unsigned int i; - for (i = 0 ; i < n && src[i] != '\0' ; i++) - dest[dest_len + i] = src[i]; - dest[dest_len + i] = '\0'; + for (i = 0 ; i < n && src[i] != '\0' ; i++) + dest[dest_len + i] = src[i]; + dest[dest_len + i] = '\0'; - return dest; + return dest; } char* strcat(char *dest, const char *src) { - unsigned int dest_len = strlen(dest); - unsigned int i; + unsigned int dest_len = strlen(dest); + unsigned int i; - for (i = 0 ; src[i] != '\0' ; i++) - dest[dest_len + i] = src[i]; - dest[dest_len + i] = '\0'; + for (i = 0 ; src[i] != '\0' ; i++) + dest[dest_len + i] = src[i]; + dest[dest_len + i] = '\0'; - return dest; + return dest; } ////////////////////////////////////////// code to do 'itoa' diff --git a/armsrc/ticks.c b/armsrc/ticks.c index cfa36d12f..7445781bf 100644 --- a/armsrc/ticks.c +++ b/armsrc/ticks.c @@ -12,160 +12,160 @@ // attempt at high resolution microsecond timer // beware: timer counts in 21.3uS increments (1024/48Mhz) void SpinDelayUs(int us) { - int ticks = (48 * us) >> 10; + int ticks = (48 * us) >> 10; - // Borrow a PWM unit for my real-time clock - AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0); + // Borrow a PWM unit for my real-time clock + AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0); - // 48 MHz / 1024 gives 46.875 kHz - AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); // Channel Mode Register - AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; // Channel Duty Cycle Register - AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; // Channel Period Register + // 48 MHz / 1024 gives 46.875 kHz + AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); // Channel Mode Register + AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; // Channel Duty Cycle Register + AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; // Channel Period Register - uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; + uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; - for(;;) { - uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; - if (now == (uint16_t)(start + ticks)) - return; + for(;;) { + uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; + if (now == (uint16_t)(start + ticks)) + return; - WDT_HIT(); - } + WDT_HIT(); + } } void SpinDelay(int ms) { // convert to uS and call microsecond delay function - SpinDelayUs(ms*1000); + SpinDelayUs(ms*1000); } // ------------------------------------------------------------------------- // timer lib // ------------------------------------------------------------------------- // test procedure: // -// ti = GetTickCount(); -// SpinDelay(1000); -// ti = GetTickCount() - ti; -// Dbprintf("timer(1s): %d t=%d", ti, GetTickCount()); +// ti = GetTickCount(); +// SpinDelay(1000); +// ti = GetTickCount() - ti; +// Dbprintf("timer(1s): %d t=%d", ti, GetTickCount()); void StartTickCount(void) { - // This timer is based on the slow clock. The slow clock frequency is between 22kHz and 40kHz. - // We can determine the actual slow clock frequency by looking at the Main Clock Frequency Register. - uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & 0xffff; // = 16 * main clock frequency (16MHz) / slow clock frequency - // set RealTimeCounter divider to count at 1kHz: - AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST | ((256000 + (mainf/2)) / mainf); - // note: worst case precision is approx 2.5% + // This timer is based on the slow clock. The slow clock frequency is between 22kHz and 40kHz. + // We can determine the actual slow clock frequency by looking at the Main Clock Frequency Register. + uint16_t mainf = AT91C_BASE_PMC->PMC_MCFR & 0xffff; // = 16 * main clock frequency (16MHz) / slow clock frequency + // set RealTimeCounter divider to count at 1kHz: + AT91C_BASE_RTTC->RTTC_RTMR = AT91C_RTTC_RTTRST | ((256000 + (mainf/2)) / mainf); + // note: worst case precision is approx 2.5% } /* * Get the current count. */ uint32_t RAMFUNC GetTickCount(void){ - return AT91C_BASE_RTTC->RTTC_RTVR;// was * 2; + return AT91C_BASE_RTTC->RTTC_RTVR;// was * 2; } // ------------------------------------------------------------------------- // microseconds timer // ------------------------------------------------------------------------- void StartCountUS(void) { - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); - AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; + AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); + AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; - // fast clock - // tick=1.5mks - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32 - AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR | - AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET; - AT91C_BASE_TC0->TC_RA = 1; - AT91C_BASE_TC0->TC_RC = 0xBFFF + 1; // 0xC000 + // fast clock + // tick=1.5mks + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // timer disable + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32 + AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | AT91C_TC_ACPA_CLEAR | + AT91C_TC_ACPC_SET | AT91C_TC_ASWTRG_SET; + AT91C_BASE_TC0->TC_RA = 1; + AT91C_BASE_TC0->TC_RC = 0xBFFF + 1; // 0xC000 - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // from timer 0 + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // timer disable + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // from timer 0 - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TCB->TCB_BCR = 1; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + AT91C_BASE_TCB->TCB_BCR = 1; - while (AT91C_BASE_TC1->TC_CV > 0); + while (AT91C_BASE_TC1->TC_CV > 0); } uint32_t RAMFUNC GetCountUS(void){ - //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 ((uint32_t)AT91C_BASE_TC1->TC_CV) * 0x8000 + (((uint32_t)AT91C_BASE_TC0->TC_CV) * 2) / 3; + //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 ((uint32_t)AT91C_BASE_TC1->TC_CV) * 0x8000 + (((uint32_t)AT91C_BASE_TC0->TC_CV) * 2) / 3; } // ------------------------------------------------------------------------- // Timer for iso14443 commands. Uses ssp_clk from FPGA // ------------------------------------------------------------------------- void StartCountSspClk(void) { - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1) | (1 << AT91C_ID_TC2); // Enable Clock to all timers - AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_TIOA1 // XC0 Clock = TIOA1 - | AT91C_TCB_TC1XC1S_NONE // XC1 Clock = none - | AT91C_TCB_TC2XC2S_TIOA0; // XC2 Clock = TIOA0 + AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1) | (1 << AT91C_ID_TC2); // Enable Clock to all timers + AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_TIOA1 // XC0 Clock = TIOA1 + | AT91C_TCB_TC1XC1S_NONE // XC1 Clock = none + | AT91C_TCB_TC2XC2S_TIOA0; // XC2 Clock = TIOA0 - // configure TC1 to create a short pulse on TIOA1 when a rising edge on TIOB1 (= ssp_clk from FPGA) occurs: - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // disable TC1 - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK // TC1 Clock = MCK(48MHz)/2 = 24MHz - | AT91C_TC_CPCSTOP // Stop clock on RC compare - | AT91C_TC_EEVTEDG_RISING // Trigger on rising edge of Event - | AT91C_TC_EEVT_TIOB // Event-Source: TIOB1 (= ssp_clk from FPGA = 13,56MHz/16) - | AT91C_TC_ENETRG // Enable external trigger event - | AT91C_TC_WAVESEL_UP // Upmode without automatic trigger on RC compare - | AT91C_TC_WAVE // Waveform Mode - | AT91C_TC_AEEVT_SET // Set TIOA1 on external event - | AT91C_TC_ACPC_CLEAR; // Clear TIOA1 on RC Compare - AT91C_BASE_TC1->TC_RC = 0x04; // RC Compare value = 0x04 + // configure TC1 to create a short pulse on TIOA1 when a rising edge on TIOB1 (= ssp_clk from FPGA) occurs: + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; // disable TC1 + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_TIMER_DIV1_CLOCK // TC1 Clock = MCK(48MHz)/2 = 24MHz + | AT91C_TC_CPCSTOP // Stop clock on RC compare + | AT91C_TC_EEVTEDG_RISING // Trigger on rising edge of Event + | AT91C_TC_EEVT_TIOB // Event-Source: TIOB1 (= ssp_clk from FPGA = 13,56MHz/16) + | AT91C_TC_ENETRG // Enable external trigger event + | AT91C_TC_WAVESEL_UP // Upmode without automatic trigger on RC compare + | AT91C_TC_WAVE // Waveform Mode + | AT91C_TC_AEEVT_SET // Set TIOA1 on external event + | AT91C_TC_ACPC_CLEAR; // Clear TIOA1 on RC Compare + AT91C_BASE_TC1->TC_RC = 0x04; // RC Compare value = 0x04 - // use TC0 to count TIOA1 pulses - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // disable TC0 - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_XC0 // TC0 clock = XC0 clock = TIOA1 - | AT91C_TC_WAVE // Waveform Mode - | AT91C_TC_WAVESEL_UP // just count - | AT91C_TC_ACPA_CLEAR // Clear TIOA0 on RA Compare - | AT91C_TC_ACPC_SET; // Set TIOA0 on RC Compare - AT91C_BASE_TC0->TC_RA = 1; // RA Compare value = 1; pulse width to TC2 - AT91C_BASE_TC0->TC_RC = 0; // RC Compare value = 0; increment TC2 on overflow + // use TC0 to count TIOA1 pulses + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; // disable TC0 + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_XC0 // TC0 clock = XC0 clock = TIOA1 + | AT91C_TC_WAVE // Waveform Mode + | AT91C_TC_WAVESEL_UP // just count + | AT91C_TC_ACPA_CLEAR // Clear TIOA0 on RA Compare + | AT91C_TC_ACPC_SET; // Set TIOA0 on RC Compare + AT91C_BASE_TC0->TC_RA = 1; // RA Compare value = 1; pulse width to TC2 + AT91C_BASE_TC0->TC_RC = 0; // RC Compare value = 0; increment TC2 on overflow - // use TC2 to count TIOA0 pulses (giving us a 32bit counter (TC0/TC2) clocked by ssp_clk) - AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS; // disable TC2 - AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_XC2 // TC2 clock = XC2 clock = TIOA0 - | AT91C_TC_WAVE // Waveform Mode - | AT91C_TC_WAVESEL_UP; // just count + // use TC2 to count TIOA0 pulses (giving us a 32bit counter (TC0/TC2) clocked by ssp_clk) + AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKDIS; // disable TC2 + AT91C_BASE_TC2->TC_CMR = AT91C_TC_CLKS_XC2 // TC2 clock = XC2 clock = TIOA0 + | AT91C_TC_WAVE // Waveform Mode + | AT91C_TC_WAVESEL_UP; // just count - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC0 - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC1 - AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC2 + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC0 + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC1 + AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // enable and reset TC2 - // synchronize the counter with the ssp_frame signal. - // Note: FPGA must be in any iso14443 mode, otherwise the frame signal would not be present - while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME)); // wait for ssp_frame to go high (start of frame) - while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME); // wait for ssp_frame to be low - while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high + // synchronize the counter with the ssp_frame signal. + // Note: FPGA must be in any iso14443 mode, otherwise the frame signal would not be present + while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME)); // wait for ssp_frame to go high (start of frame) + while(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_FRAME); // wait for ssp_frame to be low + while(!(AT91C_BASE_PIOA->PIO_PDSR & GPIO_SSC_CLK)); // wait for ssp_clk to go high - // note: up to now two ssp_clk rising edges have passed since the rising edge of ssp_frame - // it is now safe to assert a sync signal. This sets all timers to 0 on next active clock edge - AT91C_BASE_TCB->TCB_BCR = 1; // assert Sync (set all timers to 0 on next active clock edge) - // at the next (3rd) ssp_clk rising edge, TC1 will be reset (and not generate a clock signal to TC0) - // at the next (4th) ssp_clk rising edge, TC0 (the low word of our counter) will be reset. From now on, - // whenever the last three bits of our counter go 0, we can be sure to be in the middle of a frame transfer. - // (just started with the transfer of the 4th Bit). + // note: up to now two ssp_clk rising edges have passed since the rising edge of ssp_frame + // it is now safe to assert a sync signal. This sets all timers to 0 on next active clock edge + AT91C_BASE_TCB->TCB_BCR = 1; // assert Sync (set all timers to 0 on next active clock edge) + // at the next (3rd) ssp_clk rising edge, TC1 will be reset (and not generate a clock signal to TC0) + // at the next (4th) ssp_clk rising edge, TC0 (the low word of our counter) will be reset. From now on, + // whenever the last three bits of our counter go 0, we can be sure to be in the middle of a frame transfer. + // (just started with the transfer of the 4th Bit). - // The high word of the counter (TC2) will not reset until the low word (TC0) overflows. - // Therefore need to wait quite some time before we can use the counter. - while (AT91C_BASE_TC2->TC_CV > 0); + // The high word of the counter (TC2) will not reset until the low word (TC0) overflows. + // Therefore need to wait quite some time before we can use the counter. + while (AT91C_BASE_TC2->TC_CV > 0); } void ResetSspClk(void) { - //enable clock of timer and software trigger - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; - while (AT91C_BASE_TC2->TC_CV > 0); + //enable clock of timer and software trigger + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + AT91C_BASE_TC2->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; + while (AT91C_BASE_TC2->TC_CV > 0); } uint32_t RAMFUNC GetCountSspClk(void) { - uint32_t tmp_count = (AT91C_BASE_TC2->TC_CV << 16) | AT91C_BASE_TC0->TC_CV; - if ((tmp_count & 0x0000ffff) == 0) //small chance that we may have missed an increment in TC2 - return (AT91C_BASE_TC2->TC_CV << 16); - return tmp_count; + uint32_t tmp_count = (AT91C_BASE_TC2->TC_CV << 16) | AT91C_BASE_TC0->TC_CV; + if ((tmp_count & 0x0000ffff) == 0) //small chance that we may have missed an increment in TC2 + return (AT91C_BASE_TC2->TC_CV << 16); + return tmp_count; } // ------------------------------------------------------------------------- @@ -173,68 +173,68 @@ uint32_t RAMFUNC GetCountSspClk(void) { // 1us = 1.5ticks // ------------------------------------------------------------------------- void StartTicks(void){ - // initialization of the timer - AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); - AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; + // initialization of the timer + AT91C_BASE_PMC->PMC_PCER |= (1 << AT91C_ID_TC0) | (1 << AT91C_ID_TC1); + AT91C_BASE_TCB->TCB_BMR = AT91C_TCB_TC0XC0S_NONE | AT91C_TCB_TC1XC1S_TIOA0 | AT91C_TCB_TC2XC2S_NONE; - // disable TC0 and TC1 for re-configuration - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + // disable TC0 and TC1 for re-configuration + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; - // first configure TC1 (higher, 0xFFFF0000) 16 bit counter - AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // just connect to TIOA0 from TC0 - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // re-enable timer and wait for TC0 + // first configure TC1 (higher, 0xFFFF0000) 16 bit counter + AT91C_BASE_TC1->TC_CMR = AT91C_TC_CLKS_XC1; // just connect to TIOA0 from TC0 + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // re-enable timer and wait for TC0 - // second configure TC0 (lower, 0x0000FFFF) 16 bit counter - AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32 - AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | - AT91C_TC_ACPA_CLEAR | // RA comperator clears TIOA (carry bit) - AT91C_TC_ACPC_SET | // RC comperator sets TIOA (carry bit) - AT91C_TC_ASWTRG_SET; // SWTriger sets TIOA (carry bit) - AT91C_BASE_TC0->TC_RC = 0; // set TIOA (carry bit) on overflow, return to zero - AT91C_BASE_TC0->TC_RA = 1; // clear carry bit on next clock cycle - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // reset and re-enable timer + // second configure TC0 (lower, 0x0000FFFF) 16 bit counter + AT91C_BASE_TC0->TC_CMR = AT91C_TC_CLKS_TIMER_DIV3_CLOCK | // MCK(48MHz) / 32 + AT91C_TC_WAVE | AT91C_TC_WAVESEL_UP_AUTO | + AT91C_TC_ACPA_CLEAR | // RA comperator clears TIOA (carry bit) + AT91C_TC_ACPC_SET | // RC comperator sets TIOA (carry bit) + AT91C_TC_ASWTRG_SET; // SWTriger sets TIOA (carry bit) + AT91C_BASE_TC0->TC_RC = 0; // set TIOA (carry bit) on overflow, return to zero + AT91C_BASE_TC0->TC_RA = 1; // clear carry bit on next clock cycle + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKEN | AT91C_TC_SWTRG; // reset and re-enable timer - // synchronized startup procedure - while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero - while (AT91C_BASE_TC0->TC_CV < 2); // and has started (TC_CV > TC_RA, now TC1 is cleared) + // synchronized startup procedure + while (AT91C_BASE_TC0->TC_CV > 0); // wait until TC0 returned to zero + while (AT91C_BASE_TC0->TC_CV < 2); // and has started (TC_CV > TC_RA, now TC1 is cleared) - // return to zero - AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; - AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; - while (AT91C_BASE_TC0->TC_CV > 0); + // return to zero + AT91C_BASE_TC1->TC_CCR = AT91C_TC_SWTRG; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_SWTRG; + while (AT91C_BASE_TC0->TC_CV > 0); } uint32_t GetTicks(void) { - uint32_t hi, lo; + uint32_t hi, lo; - do { - hi = AT91C_BASE_TC1->TC_CV; - lo = AT91C_BASE_TC0->TC_CV; - } while(hi != AT91C_BASE_TC1->TC_CV); + do { + hi = AT91C_BASE_TC1->TC_CV; + lo = AT91C_BASE_TC0->TC_CV; + } while(hi != AT91C_BASE_TC1->TC_CV); - return (hi << 16) | lo; + return (hi << 16) | lo; } // Wait - Spindelay in ticks. // if called with a high number, this will trigger the WDT... void WaitTicks(uint32_t ticks){ - if ( ticks == 0 ) return; - ticks += GetTicks(); - while (GetTicks() < ticks); + if ( ticks == 0 ) return; + ticks += GetTicks(); + while (GetTicks() < ticks); } // Wait / Spindelay in us (microseconds) // 1us = 1.5ticks. void WaitUS(uint16_t us){ - WaitTicks( (uint32_t)us * 3/2 ); + WaitTicks( (uint32_t)us * 3/2 ); } void WaitMS(uint16_t ms){ - WaitTicks( (uint32_t)ms * 1500 ); + WaitTicks( (uint32_t)ms * 1500 ); } // stop clock void StopTicks(void){ - AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; - AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC0->TC_CCR = AT91C_TC_CLKDIS; + AT91C_BASE_TC1->TC_CCR = AT91C_TC_CLKDIS; } diff --git a/armsrc/util.c b/armsrc/util.c index 04cf1fc33..e3027c997 100644 --- a/armsrc/util.c +++ b/armsrc/util.c @@ -10,7 +10,7 @@ #include "util.h" size_t nbytes(size_t nbits) { - return (nbits >> 3)+((nbits % 8) > 0); + return (nbits >> 3)+((nbits % 8) > 0); } /* @@ -19,19 +19,19 @@ size_t nbytes(size_t nbits) { Example: reflect(0x3e23L,3) == 0x3e26 */ uint32_t reflect(uint32_t v, int b) { - uint32_t t = v; - for ( int i = 0; i < b; ++i) { - if (t & 1) - v |= BITMASK((b-1)-i); - else - v &= ~BITMASK((b-1)-i); - t>>=1; - } - return v; + uint32_t t = v; + for ( int i = 0; i < b; ++i) { + if (t & 1) + v |= BITMASK((b-1)-i); + else + v &= ~BITMASK((b-1)-i); + t>>=1; + } + return v; } uint8_t reflect8(uint8_t b) { - return ((b * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32; + return ((b * 0x80200802ULL) & 0x0884422110ULL) * 0x0101010101ULL >> 32; } uint16_t reflect16(uint16_t b) { uint16_t v = 0; @@ -56,19 +56,19 @@ uint16_t reflect16(uint16_t b) { } void num_to_bytes(uint64_t n, size_t len, uint8_t* dest) { - while (len--) { - dest[len] = (uint8_t) n; - n >>= 8; - } + while (len--) { + dest[len] = (uint8_t) n; + n >>= 8; + } } uint64_t bytes_to_num(uint8_t* src, size_t len) { - uint64_t num = 0; - while (len--) { - num = (num << 8) | (*src); - src++; - } - return num; + uint64_t num = 0; + while (len--) { + num = (num << 8) | (*src); + src++; + } + return num; } // RotateLeft - Ultralight, Desfire @@ -107,11 +107,11 @@ uint8_t hex2int(char hexchar){ case 'a': case 'A': return 10; break; case 'b': - case 'B': return 11; break; + case 'B': return 11; break; case 'c': case 'C': return 12; break; case 'd': - case 'D': return 13; break; + case 'D': return 13; break; case 'e': case 'E': return 14; break; case 'f': @@ -122,36 +122,36 @@ uint8_t hex2int(char hexchar){ } void LEDsoff() { - LED_A_OFF(); - LED_B_OFF(); - LED_C_OFF(); - LED_D_OFF(); + LED_A_OFF(); + LED_B_OFF(); + LED_C_OFF(); + LED_D_OFF(); } // LEDs: R(C) O(A) G(B) -- R(D) [1, 2, 4 and 8] void LED(int led, int ms) { - if (led & LED_RED) - LED_C_ON(); - if (led & LED_ORANGE) - LED_A_ON(); - if (led & LED_GREEN) - LED_B_ON(); - if (led & LED_RED2) - LED_D_ON(); + if (led & LED_RED) + LED_C_ON(); + if (led & LED_ORANGE) + LED_A_ON(); + if (led & LED_GREEN) + LED_B_ON(); + if (led & LED_RED2) + LED_D_ON(); - if (!ms) - return; + if (!ms) + return; - SpinDelay(ms); + SpinDelay(ms); - if (led & LED_RED) - LED_C_OFF(); - if (led & LED_ORANGE) - LED_A_OFF(); - if (led & LED_GREEN) - LED_B_OFF(); - if (led & LED_RED2) - LED_D_OFF(); + if (led & LED_RED) + LED_C_OFF(); + if (led & LED_ORANGE) + LED_A_OFF(); + if (led & LED_GREEN) + LED_B_OFF(); + if (led & LED_RED2) + LED_D_OFF(); } void SpinOff(uint32_t pause) { @@ -166,7 +166,7 @@ void SpinOff(uint32_t pause) { void SpinErr(uint8_t led, uint32_t speed, uint8_t times) { SpinOff(speed); NTIME(times) - { + { switch (led) { case 0: LED_A_INV(); @@ -223,102 +223,102 @@ void SpinUp(uint32_t speed) { // In general, don't use this function unless you expect a // double click, otherwise it will waste 500ms -- use BUTTON_HELD instead int BUTTON_CLICKED(int ms) { - // Up to 500ms in between clicks to mean a double click - int ticks = (48000 * (ms ? ms : 1000)) >> 10; + // Up to 500ms in between clicks to mean a double click + int ticks = (48000 * (ms ? ms : 1000)) >> 10; - // If we're not even pressed, forget about it! - if (!BUTTON_PRESS()) - return BUTTON_NO_CLICK; + // If we're not even pressed, forget about it! + if (!BUTTON_PRESS()) + return BUTTON_NO_CLICK; - // Borrow a PWM unit for my real-time clock - AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0); - // 48 MHz / 1024 gives 46.875 kHz - AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); - AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; - AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; + // Borrow a PWM unit for my real-time clock + AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0); + // 48 MHz / 1024 gives 46.875 kHz + AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); + AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; + AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; - uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; + uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; - int letoff = 0; - for(;;) - { - uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; + int letoff = 0; + for(;;) + { + uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; - // We haven't let off the button yet - if (!letoff) - { - // We just let it off! - if (!BUTTON_PRESS()) - { - letoff = 1; + // We haven't let off the button yet + if (!letoff) + { + // We just let it off! + if (!BUTTON_PRESS()) + { + letoff = 1; - // reset our timer for 500ms - start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; - ticks = (48000 * (500)) >> 10; - } + // reset our timer for 500ms + start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; + ticks = (48000 * (500)) >> 10; + } - // Still haven't let it off - else - // Have we held down a full second? - if (now == (uint16_t)(start + ticks)) - return BUTTON_HOLD; - } + // Still haven't let it off + else + // Have we held down a full second? + if (now == (uint16_t)(start + ticks)) + return BUTTON_HOLD; + } - // We already let off, did we click again? - else - // Sweet, double click! - if (BUTTON_PRESS()) - return BUTTON_DOUBLE_CLICK; + // We already let off, did we click again? + else + // Sweet, double click! + if (BUTTON_PRESS()) + return BUTTON_DOUBLE_CLICK; - // Have we ran out of time to double click? - else - if (now == (uint16_t)(start + ticks)) - // At least we did a single click - return BUTTON_SINGLE_CLICK; + // Have we ran out of time to double click? + else + if (now == (uint16_t)(start + ticks)) + // At least we did a single click + return BUTTON_SINGLE_CLICK; - WDT_HIT(); - } + WDT_HIT(); + } - // We should never get here - return BUTTON_ERROR; + // We should never get here + return BUTTON_ERROR; } // Determine if a button is held down int BUTTON_HELD(int ms) { - // If button is held for one second - int ticks = (48000 * (ms ? ms : 1000)) >> 10; + // If button is held for one second + int ticks = (48000 * (ms ? ms : 1000)) >> 10; - // If we're not even pressed, forget about it! - if (!BUTTON_PRESS()) - return BUTTON_NO_CLICK; + // If we're not even pressed, forget about it! + if (!BUTTON_PRESS()) + return BUTTON_NO_CLICK; - // Borrow a PWM unit for my real-time clock - AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0); - // 48 MHz / 1024 gives 46.875 kHz - AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); - AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; - AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; + // Borrow a PWM unit for my real-time clock + AT91C_BASE_PWMC->PWMC_ENA = PWM_CHANNEL(0); + // 48 MHz / 1024 gives 46.875 kHz + AT91C_BASE_PWMC_CH0->PWMC_CMR = PWM_CH_MODE_PRESCALER(10); + AT91C_BASE_PWMC_CH0->PWMC_CDTYR = 0; + AT91C_BASE_PWMC_CH0->PWMC_CPRDR = 0xffff; - uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; + uint16_t start = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; - for(;;) - { - uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; + for(;;) + { + uint16_t now = AT91C_BASE_PWMC_CH0->PWMC_CCNTR; - // As soon as our button let go, we didn't hold long enough - if (!BUTTON_PRESS()) - return BUTTON_SINGLE_CLICK; + // As soon as our button let go, we didn't hold long enough + if (!BUTTON_PRESS()) + return BUTTON_SINGLE_CLICK; - // Have we waited the full second? - else - if (now == (uint16_t)(start + ticks)) - return BUTTON_HOLD; + // Have we waited the full second? + else + if (now == (uint16_t)(start + ticks)) + return BUTTON_HOLD; - WDT_HIT(); - } + WDT_HIT(); + } - // We should never get here - return BUTTON_ERROR; + // We should never get here + return BUTTON_ERROR; } /* Similar to FpgaGatherVersion this formats stored version information @@ -327,30 +327,30 @@ int BUTTON_HELD(int ms) { * prefix in dst. */ void FormatVersionInformation(char *dst, int len, const char *prefix, void *version_information) { - struct version_information *v = (struct version_information*)version_information; - dst[0] = 0; - strncat(dst, prefix, len-1); - if (v->magic != VERSION_INFORMATION_MAGIC) { - strncat(dst, "Missing/Invalid version information\n", len - strlen(dst) - 1); - return; - } - if (v->versionversion != 1) { - strncat(dst, "Version information not understood\n", len - strlen(dst) - 1); - return; - } - if (!v->present) { - strncat(dst, "Version information not available\n", len - strlen(dst) - 1); - return; - } + struct version_information *v = (struct version_information*)version_information; + dst[0] = 0; + strncat(dst, prefix, len-1); + if (v->magic != VERSION_INFORMATION_MAGIC) { + strncat(dst, "Missing/Invalid version information\n", len - strlen(dst) - 1); + return; + } + if (v->versionversion != 1) { + strncat(dst, "Version information not understood\n", len - strlen(dst) - 1); + return; + } + if (!v->present) { + strncat(dst, "Version information not available\n", len - strlen(dst) - 1); + return; + } - strncat(dst, v->gitversion, len - strlen(dst) - 1); - if (v->clean == 0) { - strncat(dst, "-unclean", len - strlen(dst) - 1); - } else if (v->clean == 2) { - strncat(dst, "-suspect", len - strlen(dst) - 1); - } + strncat(dst, v->gitversion, len - strlen(dst) - 1); + if (v->clean == 0) { + strncat(dst, "-unclean", len - strlen(dst) - 1); + } else if (v->clean == 2) { + strncat(dst, "-suspect", len - strlen(dst) - 1); + } - strncat(dst, " ", len - strlen(dst) - 1); - strncat(dst, v->buildtime, len - strlen(dst) - 1); - strncat(dst, "\n", len - strlen(dst) - 1); + strncat(dst, " ", len - strlen(dst) - 1); + strncat(dst, v->buildtime, len - strlen(dst) - 1); + strncat(dst, "\n", len - strlen(dst) - 1); } diff --git a/armsrc/util.h b/armsrc/util.h index cc613b273..bca073273 100644 --- a/armsrc/util.h +++ b/armsrc/util.h @@ -46,8 +46,8 @@ size_t nbytes(size_t nbits); extern uint32_t reflect(uint32_t v, int b); // used in crc.c ... -extern uint8_t reflect8(uint8_t b); // dedicated 8bit reversal -extern uint16_t reflect16(uint16_t b); // dedicated 16bit reversal +extern uint8_t reflect8(uint8_t b); // dedicated 8bit reversal +extern uint16_t reflect16(uint16_t b); // dedicated 16bit reversal void num_to_bytes(uint64_t n, size_t len, uint8_t* dest); uint64_t bytes_to_num(uint8_t* src, size_t len); From e8d15d0c1847b5fd40c439ba3e70e6b5cc49193c Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 20:47:57 +0100 Subject: [PATCH 0710/1938] FIX: 'data load' - now loads large files again (TITEST.txt) --- client/cmddata.c | 12 +++++++----- client/graph.c | 2 +- 2 files changed, 8 insertions(+), 6 deletions(-) diff --git a/client/cmddata.c b/client/cmddata.c index 6d83a4e0b..45bce9c9c 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -1600,19 +1600,23 @@ int CmdLoad(const char *Cmd) { len = strlen(Cmd); if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; memcpy(filename, Cmd, len); - + FILE *f = fopen(filename, "r"); if (!f) { PrintAndLogEx(WARNING, "couldn't open '%s'", filename); return 0; } - + GraphTraceLen = 0; char line[80]; while (fgets(line, sizeof (line), f)) { GraphBuffer[GraphTraceLen] = atoi(line); GraphTraceLen++; + + if ( GraphTraceLen >= MAX_GRAPH_TRACE_LEN ) + break; } + if (f) fclose(f); @@ -1620,11 +1624,9 @@ int CmdLoad(const char *Cmd) { uint8_t bits[GraphTraceLen]; size_t size = getFromGraphBuf(bits); - // set signal properties low/high/mean/amplitude and is_noise detection + removeSignalOffset(bits, size); - // push it back to graph setGraphBuf(bits, size); - // set signal properties low/high/mean/amplitude and is_noise detection computeSignalProperties(bits, size); setClockGrid(0,0); diff --git a/client/graph.c b/client/graph.c index c3f6a2b99..2df0d8202 100644 --- a/client/graph.c +++ b/client/graph.c @@ -67,7 +67,7 @@ void setGraphBuf(uint8_t *buf, size_t size) { if ( size > MAX_GRAPH_TRACE_LEN ) size = MAX_GRAPH_TRACE_LEN; - for (uint16_t i = 0; i < size; ++i) + for (uint32_t i = 0; i < size; ++i) GraphBuffer[i] = buf[i] - 128; GraphTraceLen = size; From 902a5f06ffa4e94b4f0214ebd981aba6f07f392b Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 21:42:40 +0100 Subject: [PATCH 0711/1938] chg: 'lf search' - added TI detection --- client/cmdlf.c | 4 +- client/cmdlfti.c | 135 +++++++++++++++++++++++++---------------------- 2 files changed, 75 insertions(+), 64 deletions(-) diff --git a/client/cmdlf.c b/client/cmdlf.c index 71c429f00..b877f8f3b 100644 --- a/client/cmdlf.c +++ b/client/cmdlf.c @@ -912,9 +912,9 @@ int CmdLFfind(const char *Cmd) { if (CmdSecurakeyDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Securakey ID Found!"); goto out;} if (CmdVikingDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Viking ID Found!"); goto out;} if (CmdVisa2kDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Visa2000 ID Found!"); goto out;} - + if (CmdTIDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Texas Instrument ID Found!"); goto out;} //if (CmdFermaxDemod("")) { PrintAndLogEx(SUCCESS, "\nValid Fermax ID Found!"); goto out;} - // TIdemod? flexdemod? + // flexdemod? PrintAndLogEx(FAILED, "\nNo known 125/134 KHz tags Found!\n"); diff --git a/client/cmdlfti.c b/client/cmdlfti.c index 9928faf27..1eb649ca5 100644 --- a/client/cmdlfti.c +++ b/client/cmdlfti.c @@ -21,8 +21,7 @@ static int CmdHelp(const char *Cmd); -int CmdTIDemod(const char *Cmd) -{ +int CmdTIDemod(const char *Cmd) { /* MATLAB as follows: f_s = 2000000; % sampling frequency f_l = 123200; % low FSK tone @@ -77,14 +76,18 @@ int CmdTIDemod(const char *Cmd) 1, 1, 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, -1, -1, 1, 1, 1, 1, 1, 1, 1, 1 }; - int lowLen = sizeof(LowTone) / sizeof(int); - int highLen = sizeof(HighTone) / sizeof(int); - int convLen = (highLen > lowLen) ? highLen : lowLen; - uint16_t crc; - int i, j, TagType; - int lowSum = 0, highSum = 0;; - int lowTot = 0, highTot = 0; + save_restoreGB(GRAPH_SAVE); + + int lowLen = sizeof(LowTone) / sizeof(int); + int highLen = sizeof(HighTone) / sizeof(int); + int convLen = (highLen > lowLen) ? highLen : lowLen; + uint16_t crc; + int i, j, TagType; + int lowSum = 0, highSum = 0;; + int lowTot = 0, highTot = 0; + int retval = 0; + for (i = 0; i < GraphTraceLen - convLen; i++) { lowSum = 0; highSum = 0;; @@ -95,10 +98,10 @@ int CmdTIDemod(const char *Cmd) for (j = 0; j < highLen; j++) { highSum += HighTone[j] * GraphBuffer[i+j]; } - lowSum = abs((100*lowSum) / lowLen); - highSum = abs((100*highSum) / highLen); - lowSum = (lowSum<0) ? -lowSum : lowSum; - highSum = (highSum<0) ? -highSum : highSum; + lowSum = abs((100 * lowSum) / lowLen); + highSum = abs((100 * highSum) / highLen); + lowSum = (lowSum < 0) ? -lowSum : lowSum; + highSum = (highSum < 0) ? -highSum : highSum; GraphBuffer[i] = (highSum << 16) | lowSum; } @@ -157,17 +160,16 @@ int CmdTIDemod(const char *Cmd) GraphBuffer[maxPos+1] = -800; // advance pointer to start of actual data stream (after 16 pre and 8 start bits) - maxPos += 17*lowLen; - maxPos += 6*highLen; + maxPos += 17 * lowLen; + maxPos += 6 * highLen; // place a marker in the buffer to visually aid location // of the end of sync GraphBuffer[maxPos] = 800; GraphBuffer[maxPos+1] = -800; - PrintAndLogEx(NORMAL, "actual data bits start at sample %d", maxPos); - - PrintAndLogEx(NORMAL, "length %d/%d", highLen, lowLen); + PrintAndLogEx(DEBUG, "actual data bits start at sample %d", maxPos); + PrintAndLogEx(DEBUG, "length %d/%d", highLen, lowLen); uint8_t bits[1+64+16+8+16]; bits[sizeof(bits)-1] = '\0'; @@ -208,67 +210,75 @@ int CmdTIDemod(const char *Cmd) RepaintGraphWindow(); - PrintAndLogEx(INFO, "INFO: raw tag bits = %s", bits); + PrintAndLogEx(INFO, "raw tag bits = %s", bits); - TagType = (shift3>>8)&0xff; - if ( TagType != ((shift0>>16)&0xff) ) { + TagType = (shift3 >> 8) & 0xFF; + if ( TagType != ((shift0 >> 16) & 0xFF) ) { PrintAndLogEx(WARNING, "Error: start and stop bits do not match!"); - return 0; + goto out; } - else if (TagType == 0x7e) { - PrintAndLogEx(INFO, "INFO: Readonly TI tag detected."); - return 0; + else if (TagType == 0x7E) { + PrintAndLogEx(INFO, "Readonly TI tag detected."); + retval = 1; + goto out; } - else if (TagType == 0xfe) { - PrintAndLogEx(INFO, "INFO: Rewriteable TI tag detected."); + else if (TagType == 0xFE) { + PrintAndLogEx(INFO, "Rewriteable TI tag detected."); // put 64 bit data into shift1 and shift0 - shift0 = (shift0>>24) | (shift1 << 8); - shift1 = (shift1>>24) | (shift2 << 8); + shift0 = (shift0 >> 24) | (shift1 << 8); + shift1 = (shift1 >> 24) | (shift2 << 8); // align 16 bit crc into lower half of shift2 - shift2 = ((shift2>>24) | (shift3 << 8)) & 0x0ffff; + shift2 = ((shift2 >> 24) | (shift3 << 8)) & 0x0FFFF; // align 16 bit "end bits" or "ident" into lower half of shift3 shift3 >>= 16; // only 15 bits compare, last bit of ident is not valid - if ( (shift3^shift0)&0x7fff ) { + if ( (shift3 ^ shift0) & 0x7FFF ) { PrintAndLogEx(WARNING, "Error: Ident mismatch!"); } // WARNING the order of the bytes in which we calc crc below needs checking // i'm 99% sure the crc algorithm is correct, but it may need to eat the // bytes in reverse or something // calculate CRC - crc=0; - crc = update_crc16(crc, (shift0)&0xff); - crc = update_crc16(crc, (shift0>>8)&0xff); - crc = update_crc16(crc, (shift0>>16)&0xff); - crc = update_crc16(crc, (shift0>>24)&0xff); - crc = update_crc16(crc, (shift1)&0xff); - crc = update_crc16(crc, (shift1>>8)&0xff); - crc = update_crc16(crc, (shift1>>16)&0xff); - crc = update_crc16(crc, (shift1>>24)&0xff); + crc = 0; + crc = update_crc16(crc, (shift0 >> 0) & 0xFF); + crc = update_crc16(crc, (shift0 >> 8) & 0xFF); + crc = update_crc16(crc, (shift0 >> 16) & 0xFF); + crc = update_crc16(crc, (shift0 >> 24) & 0xFF); + + crc = update_crc16(crc, (shift1 >> 0) & 0xFF); + crc = update_crc16(crc, (shift1 >> 8) & 0xFF); + crc = update_crc16(crc, (shift1 >> 16) & 0xFF); + crc = update_crc16(crc, (shift1 >> 24) & 0xFF); //crc = crc16_ccitt(message, sizeof(message); - char *crcStr = (crc == (shift2&0xffff) ) ? "Passed" : "Failed"; + char *crcStr = (crc == (shift2 & 0xFFFF) ) ? "Passed" : "Failed"; - PrintAndLogEx(NORMAL, "Tag data = %08X%08X [Crc %04X %s]", shift1, shift0, crc, crcStr ); - - if (crc != (shift2&0xffff)) - PrintAndLogEx(WARNING, "Error: CRC mismatch, calculated %04X, got %04X", crc, shift2&0xffff); + PrintAndLogEx(INFO, "Tag data = %08X%08X [Crc %04X %s]", shift1, shift0, crc, crcStr ); + if (crc != (shift2 & 0xFFFF)) + PrintAndLogEx(WARNING, "Error: CRC mismatch, calculated %04X, got %04X", crc, shift2 & 0xFFFF); + + retval = 1; + goto out; } else { PrintAndLogEx(WARNING, "Unknown tag type."); } - return 0; + +out: + if ( retval == 0) + save_restoreGB(GRAPH_RESTORE); + + return retval; } // read a TI tag and return its ID -int CmdTIRead(const char *Cmd) -{ +int CmdTIRead(const char *Cmd) { UsbCommand c = {CMD_READ_TI_TYPE}; clearCommandBuffer(); SendCommand(&c); @@ -276,15 +286,16 @@ int CmdTIRead(const char *Cmd) } // write new data to a r/w TI tag -int CmdTIWrite(const char *Cmd) -{ +int CmdTIWrite(const char *Cmd) { int res = 0; UsbCommand c = {CMD_WRITE_TI_TYPE}; res = sscanf(Cmd, "%012" SCNx64 " %012" SCNx64 " %012" SCNx64 "", &c.arg[0], &c.arg[1], &c.arg[2]); - if (res == 2) c.arg[2]=0; + if (res == 2) + c.arg[2] = 0; + if (res < 2) { - PrintAndLogEx(NORMAL, "Please specify the data as two hex strings, optionally the CRC as a third"); + PrintAndLogEx(WARNING, "Please specify the data as two hex strings, optionally the CRC as a third"); return 1; } clearCommandBuffer(); @@ -293,20 +304,20 @@ int CmdTIWrite(const char *Cmd) } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"demod", CmdTIDemod, 1, "Demodulate raw bits for TI-type LF tag from the GraphBuffer"}, - {"read", CmdTIRead, 0, "Read and decode a TI 134 kHz tag"}, - {"write", CmdTIWrite, 0, "Write new data to a r/w TI 134 kHz tag"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"demod", CmdTIDemod, 1, "Demodulate raw bits for TI-type LF tag from the GraphBuffer"}, + {"read", CmdTIRead, 0, "Read and decode a TI 134 kHz tag"}, + {"write", CmdTIWrite, 0, "Write new data to a r/w TI 134 kHz tag"}, + {NULL, NULL, 0, NULL} }; int CmdLFTI(const char *Cmd){ - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd){ - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } From 38503b55d57c5271224c49fddde1e44124831da7 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 21:43:03 +0100 Subject: [PATCH 0712/1938] chg: cleanup --- client/cmdlfparadox.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/client/cmdlfparadox.c b/client/cmdlfparadox.c index 238d7bc00..80088c85c 100644 --- a/client/cmdlfparadox.c +++ b/client/cmdlfparadox.c @@ -79,15 +79,15 @@ int detectParadox(uint8_t *dest, size_t *size, uint32_t *hi2, uint32_t *hi, uint //print full Paradox Prox ID and some bit format details if found int CmdParadoxDemod(const char *Cmd) { //raw fsk demod no manchester decoding no start bit finding just get binary from wave - uint8_t bits[MAX_GRAPH_TRACE_LEN]={0}; + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; size_t size = getFromGraphBuf(bits); if (size == 0) { PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox not enough samples"); return 0; } - uint32_t hi2=0, hi=0, lo=0; - int waveIdx=0; + uint32_t hi2 = 0, hi = 0, lo = 0; + int waveIdx = 0; //get binary from fsk wave int idx = detectParadox(bits, &size, &hi2, &hi, &lo, &waveIdx); if (idx < 0){ @@ -109,24 +109,24 @@ int CmdParadoxDemod(const char *Cmd) { } setDemodBuf(bits, size, idx); - setClockGrid(50, waveIdx + (idx*50)); + setClockGrid(50, waveIdx + (idx * 50)); - if (hi2==0 && hi==0 && lo==0){ - if (g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox no value found"); + if (hi2 == 0 && hi == 0 && lo == 0){ + PrintAndLogEx(DEBUG, "DEBUG: Error - Paradox no value found"); return 0; } - uint32_t fc = ((hi & 0x3)<<6) | (lo>>26); - uint32_t cardnum = (lo>>10) & 0xFFFF; + uint32_t fc = ((hi & 0x3) << 6) | (lo >> 26); + uint32_t cardnum = (lo >> 10) & 0xFFFF; uint32_t rawLo = bytebits_to_byte(bits + idx + 64, 32); uint32_t rawHi = bytebits_to_byte(bits + idx + 32, 32); uint32_t rawHi2 = bytebits_to_byte(bits + idx, 32); PrintAndLogEx(NORMAL, "Paradox TAG ID: %x%08x - FC: %d - Card: %d - Checksum: %02x - RAW: %08x%08x%08x", hi >> 10, - (hi & 0x3)<<26 | (lo>>10), + (hi & 0x3) << 26 | (lo >> 10), fc, cardnum, - (lo>>2) & 0xFF, + (lo >> 2) & 0xFF, rawHi2, rawHi, rawLo @@ -193,6 +193,7 @@ static command_t CommandTable[] = { }; int CmdLFParadox(const char *Cmd) { + clearCommandBuffer(); CmdsParse(CommandTable, Cmd); return 0; } From 112411042fe3691d7cdcbb08fad893fca2ce1688 Mon Sep 17 00:00:00 2001 From: iceman1001 Date: Sat, 9 Mar 2019 21:59:00 +0100 Subject: [PATCH 0713/1938] cleaning up --- client/cmdhficlass.c | 112 +++++++++++++------------------------------ 1 file changed, 34 insertions(+), 78 deletions(-) diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index e21de76ab..bf8976e8a 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -574,16 +574,16 @@ int HFiClassReader(const char *Cmd, bool loop, bool verbose) { } int CmdHFiClassReader(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (cmdp == 'h' || cmdp == 'H') return usage_hf_iclass_reader(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_iclass_reader(); bool findone = (cmdp == '1') ? false : true; return HFiClassReader(Cmd, findone, true); } int CmdHFiClassReader_Replay(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd)<1 || cmdp == 'H' || cmdp == 'h') return usage_hf_iclass_replay(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd)<1 || cmdp == 'h') return usage_hf_iclass_replay(); uint8_t readerType = 0; uint8_t MAC[4] = {0x00, 0x00, 0x00, 0x00}; @@ -610,13 +610,12 @@ int iclassEmlSetMem(uint8_t *data, int blockNum, int blocksCount) { int CmdHFiClassELoad(const char *Cmd) { - char ctmp = param_getchar(Cmd, 0); - if (strlen(Cmd)< 1 || ctmp == 'h' || ctmp == 'H') return usage_hf_iclass_eload(); + char ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd)< 1 || ctmp == 'h') return usage_hf_iclass_eload(); - if ( ctmp != 'f' && ctmp != 'F') return usage_hf_iclass_eload(); + if ( ctmp != 'f' ) return usage_hf_iclass_eload(); //File handling and reading - FILE *f; char filename[FILE_PATH_SIZE]; if ( param_getstr(Cmd, 1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) { @@ -624,7 +623,7 @@ int CmdHFiClassELoad(const char *Cmd) { return 1; } - f = fopen(filename, "rb"); + FILE *f = fopen(filename, "rb"); if ( !f ){ PrintAndLogEx(FAILED, "File: " _YELLOW_(%s) ": not found or locked.", filename); return 1; @@ -703,8 +702,8 @@ static int readKeyfile(const char *filename, size_t len, uint8_t* buffer) { int CmdHFiClassDecrypt(const char *Cmd) { - char opt = param_getchar(Cmd, 0); - if (strlen(Cmd)<1 || opt == 'h' || opt == 'H') return usage_hf_iclass_decrypt(); + char opt = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd)<1 || opt == 'h') return usage_hf_iclass_decrypt(); uint8_t key[16] = { 0 }; if (readKeyfile("iclass_decryptionkey.bin", 16, key)) return usage_hf_iclass_decrypt(); @@ -807,8 +806,8 @@ static int iClassEncryptBlkData(uint8_t *blkData) { int CmdHFiClassEncryptBlk(const char *Cmd) { uint8_t blkData[8] = {0}; - char opt = param_getchar(Cmd, 0); - if (strlen(Cmd)<1 || opt == 'h' || opt == 'H') return usage_hf_iclass_encrypt(); + char opt = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd)<1 || opt == 'h') return usage_hf_iclass_encrypt(); //get the bytes to encrypt if (param_gethex(Cmd, 0, blkData, 16)) { @@ -924,12 +923,10 @@ int CmdHFiClassReader_Dump(const char *Cmd) { uint8_t cmdp = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (param_getchar(Cmd, cmdp)) { + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': - case 'H': return usage_hf_iclass_dump(); case 'c': - case 'C': have_credit_key = true; dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { @@ -949,12 +946,10 @@ int CmdHFiClassReader_Dump(const char *Cmd) { cmdp += 2; break; case 'e': - case 'E': elite = true; cmdp++; break; case 'f': - case 'F': fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); if (fileNameLen < 1) { PrintAndLogEx(WARNING, "no filename found after f"); @@ -963,7 +958,6 @@ int CmdHFiClassReader_Dump(const char *Cmd) { cmdp += 2; break; case 'k': - case 'K': have_debit_key = true; dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { @@ -983,12 +977,10 @@ int CmdHFiClassReader_Dump(const char *Cmd) { cmdp += 2; break; case 'r': - case 'R': rawkey = true; cmdp++; break; case 'v': - case 'V': verbose = true; cmdp++; break; @@ -1198,13 +1190,11 @@ int CmdHFiClass_WriteBlock(const char *Cmd) { bool errors = false; bool verbose = false; uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': - case 'H': return usage_hf_iclass_writeblock(); case 'b': - case 'B': if (param_gethex(Cmd, cmdp+1, &blockno, 2)) { PrintAndLogEx(WARNING, "Block No must include 2 HEX symbols\n"); errors = true; @@ -1212,12 +1202,10 @@ int CmdHFiClass_WriteBlock(const char *Cmd) { cmdp += 2; break; case 'c': - case 'C': use_credit_key = true; cmdp++; break; case 'd': - case 'D': if (param_gethex(Cmd, cmdp+1, bldata, 16)) { PrintAndLogEx(WARNING, "Data must include 16 HEX symbols\n"); errors = true; @@ -1225,12 +1213,10 @@ int CmdHFiClass_WriteBlock(const char *Cmd) { cmdp += 2; break; case 'e': - case 'E': elite = true; cmdp++; break; case 'k': - case 'K': dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { errors = param_gethex(tempStr, 0, KEY, dataLen); @@ -1249,12 +1235,10 @@ int CmdHFiClass_WriteBlock(const char *Cmd) { cmdp += 2; break; case 'r': - case 'R': rawkey = true; cmdp++; break; case 'v': - case 'V': verbose = true; cmdp++; break; @@ -1286,13 +1270,11 @@ int CmdHFiClassCloneTag(const char *Cmd) { bool errors = false; bool verbose = false; uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': - case 'H': return usage_hf_iclass_clone(); case 'b': - case 'B': if (param_gethex(Cmd, cmdp+1, &startblock, 2)) { PrintAndLogEx(WARNING, "start block No must include 2 HEX symbols\n"); errors = true; @@ -1300,17 +1282,14 @@ int CmdHFiClassCloneTag(const char *Cmd) { cmdp += 2; break; case 'c': - case 'C': use_credit_key = true; cmdp++; break; case 'e': - case 'E': elite = true; cmdp++; break; case 'f': - case 'F': fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); if (fileNameLen < 1) { PrintAndLogEx(WARNING, "No filename found after f"); @@ -1319,7 +1298,6 @@ int CmdHFiClassCloneTag(const char *Cmd) { cmdp += 2; break; case 'k': - case 'K': dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { errors = param_gethex(tempStr, 0, KEY, dataLen); @@ -1338,7 +1316,6 @@ int CmdHFiClassCloneTag(const char *Cmd) { cmdp += 2; break; case 'l': - case 'L': if (param_gethex(Cmd, cmdp+1, &endblock, 2)) { PrintAndLogEx(WARNING, "start Block No must include 2 HEX symbols\n"); errors = true; @@ -1346,12 +1323,10 @@ int CmdHFiClassCloneTag(const char *Cmd) { cmdp += 2; break; case 'r': - case 'R': rawkey = true; cmdp++; break; case 'v': - case 'V': verbose = true; cmdp++; break; @@ -1368,17 +1343,17 @@ int CmdHFiClassCloneTag(const char *Cmd) { iclass_block_t tag_data[USB_CMD_DATA_SIZE/12]; - if ((endblock-startblock+1)*12 > USB_CMD_DATA_SIZE) { + if ((endblock - startblock + 1) * 12 > USB_CMD_DATA_SIZE) { PrintAndLogEx(NORMAL, "Trying to write too many blocks at once. Max: %d", USB_CMD_DATA_SIZE/8); } // file handling and reading - f = fopen(filename,"rb"); + f = fopen(filename, "rb"); if(!f) { PrintAndLogEx(WARNING, "failed to read file '%s'", filename); return 1; } - if (startblock<5) { + if (startblock < 5) { PrintAndLogEx(WARNING, "you cannot write key blocks this way. yet... make your start block > 4"); fclose(f); return 0; @@ -1480,12 +1455,10 @@ int CmdHFiClass_ReadBlock(const char *Cmd) { bool verbose = false; uint8_t cmdp = 0; while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (param_getchar(Cmd, cmdp)) { + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': - case 'H': return usage_hf_iclass_readblock(); case 'b': - case 'B': if (param_gethex(Cmd, cmdp+1, &blockno, 2)) { PrintAndLogEx(WARNING, "Block No must include 2 HEX symbols\n"); errors = true; @@ -1493,17 +1466,14 @@ int CmdHFiClass_ReadBlock(const char *Cmd) { cmdp += 2; break; case 'c': - case 'C': keyType = 0x18; cmdp++; break; case 'e': - case 'E': elite = true; cmdp++; break; case 'k': - case 'K': auth = true; dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { @@ -1523,12 +1493,10 @@ int CmdHFiClass_ReadBlock(const char *Cmd) { cmdp += 2; break; case 'r': - case 'R': rawkey = true; cmdp++; break; case 'v': - case 'V': verbose = true; cmdp++; break; @@ -1546,7 +1514,7 @@ int CmdHFiClass_ReadBlock(const char *Cmd) { } int CmdHFiClass_loclass(const char *Cmd) { - char opt = param_getchar(Cmd, 0); + char opt = tolower(param_getchar(Cmd, 0)); if (strlen(Cmd)<1 || opt == 'h') usage_hf_iclass_loclass(); @@ -1617,15 +1585,15 @@ int CmdHFiClassReadTagFile(const char *Cmd) { if (param_getstr(Cmd, 1, tempnum, sizeof(tempnum)) < 1) startblock = 0; else - sscanf(tempnum,"%d",&startblock); + sscanf(tempnum, "%d", &startblock); if (param_getstr(Cmd,2, tempnum, sizeof(tempnum)) < 1) endblock = 0; else - sscanf(tempnum,"%d",&endblock); + sscanf(tempnum, "%d", &endblock); // file handling and reading - f = fopen(filename,"rb"); + f = fopen(filename, "rb"); if(!f) { PrintAndLogEx(WARNING, "Failed to read from file '%s'", filename); return 1; @@ -1711,13 +1679,11 @@ int CmdHFiClassCalcNewKey(const char *Cmd) { bool elite = false; bool errors = false; uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': - case 'H': return usage_hf_iclass_calc_newkey(); case 'e': - case 'E': dataLen = param_getstr(Cmd, cmdp, tempStr, sizeof(tempStr)); if (dataLen==2) oldElite = true; @@ -1725,7 +1691,6 @@ int CmdHFiClassCalcNewKey(const char *Cmd) { cmdp++; break; case 'n': - case 'N': dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { errors = param_gethex(tempStr, 0, NEWKEY, dataLen); @@ -1744,7 +1709,6 @@ int CmdHFiClassCalcNewKey(const char *Cmd) { cmdp += 2; break; case 'o': - case 'O': dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { errors = param_gethex(tempStr, 0, OLDKEY, dataLen); @@ -1763,7 +1727,6 @@ int CmdHFiClassCalcNewKey(const char *Cmd) { cmdp += 2; break; case 's': - case 'S': givenCSN = true; if (param_gethex(Cmd, cmdp+1, CSN, 16)) return usage_hf_iclass_calc_newkey(); @@ -1787,7 +1750,7 @@ int CmdHFiClassCalcNewKey(const char *Cmd) { static int loadKeys(char *filename) { FILE *f; - f = fopen(filename,"rb"); + f = fopen(filename, "rb"); if(!f) { PrintAndLogEx(WARNING, "Failed to read from file '%s'", filename); return 0; @@ -1826,7 +1789,7 @@ static int loadKeys(char *filename) { static int saveKeys(char *filename) { FILE *f; - f = fopen(filename,"wb"); + f = fopen(filename, "wb"); if (!f) { PrintAndLogEx(NORMAL, "[!] error opening file %s\n",filename); return 0; @@ -1860,13 +1823,11 @@ int CmdHFiClassManageKeys(const char *Cmd) { char tempStr[20]; uint8_t cmdp = 0; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { case 'h': - case 'H': return usage_hf_iclass_managekeys(); case 'f': - case 'F': fileNameLen = param_getstr(Cmd, cmdp+1, filename, sizeof(filename)); if (fileNameLen < 1) { PrintAndLogEx(WARNING, "No filename found after f"); @@ -1875,7 +1836,6 @@ int CmdHFiClassManageKeys(const char *Cmd) { cmdp += 2; break; case 'n': - case 'N': keyNbr = param_get8(Cmd, cmdp+1); if (keyNbr >= ICLASS_KEYS_MAX) { PrintAndLogEx(WARNING, "Invalid block number"); @@ -1884,7 +1844,6 @@ int CmdHFiClassManageKeys(const char *Cmd) { cmdp += 2; break; case 'k': - case 'K': operation += 3; //set key dataLen = param_getstr(Cmd, cmdp+1, tempStr, sizeof(tempStr)); if (dataLen == 16) { //ul-c or ev1/ntag key length @@ -1896,17 +1855,14 @@ int CmdHFiClassManageKeys(const char *Cmd) { cmdp += 2; break; case 'p': - case 'P': operation += 4; //print keys in memory cmdp++; break; case 'l': - case 'L': operation += 5; //load keys from file cmdp++; break; case 's': - case 'S': operation += 6; //save keys to file cmdp++; break; @@ -2491,10 +2447,10 @@ int CmdHFiClassPermuteKey(const char *Cmd) { uint8_t data[16] = {0}; bool isReverse = false; int len = 0; - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd) == 0|| cmdp == 'h' || cmdp == 'H') return usage_hf_iclass_permutekey(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0|| cmdp == 'h') return usage_hf_iclass_permutekey(); - isReverse = ( cmdp == 'r' || cmdp == 'R' ); + isReverse = ( cmdp == 'r' ); param_gethex_ex(Cmd, 1, data, &len); if ( len%2 ) return usage_hf_iclass_permutekey(); From 0d9223a5472dc90e225be6fefc7c2fd591994c00 Mon Sep 17 00:00:00 2001 From: Philippe Teuwen Date: Sat, 9 Mar 2019 23:35:06 +0100 Subject: [PATCH 0714/1938] client: fix mix of spaces & tabs --- Makefile | 2 +- client/amiitool/amiibo.c | 226 +- client/amiitool/amiibo.h | 4 +- client/amiitool/amiitool.c | 274 +- client/amiitool/drbg.c | 90 +- client/amiitool/drbg.h | 14 +- client/amiitool/keygen.c | 56 +- client/amiitool/keygen.h | 18 +- client/cliparser/argtable3.c | 1768 +++--- client/cliparser/cliparser.c | 262 +- client/cliparser/getopt.h | 44 +- client/cmdanalyse.c | 1262 ++-- client/cmdanalyse.h | 10 +- client/cmdcrc.c | 736 +-- client/cmddata.c | 3076 +++++----- client/cmddata.h | 2 +- client/cmdflashmem.c | 858 +-- client/cmdflashmem.h | 14 +- client/cmdhf.c | 196 +- client/cmdhf.h | 26 +- client/cmdhf14a.c | 1988 +++---- client/cmdhf14a.h | 6 +- client/cmdhf14b.c | 1490 ++--- client/cmdhf14b.h | 4 +- client/cmdhf15.c | 1900 +++--- client/cmdhf15.h | 6 +- client/cmdhfepa.c | 272 +- client/cmdhffelica.c | 704 +-- client/cmdhffelica.h | 6 +- client/cmdhffido.c | 1428 ++--- client/cmdhficlass.c | 4112 ++++++------- client/cmdhficlass.h | 10 +- client/cmdhflegic.c | 2036 +++---- client/cmdhflist.c | 1400 ++--- client/cmdhflist.h | 50 +- client/cmdhfmf.c | 5546 +++++++++--------- client/cmdhfmf.h | 16 +- client/cmdhfmfdes.c | 1000 ++-- client/cmdhfmfdes.h | 190 +- client/cmdhfmfdesfire.c | 24 +- client/cmdhfmfhard.c | 3478 +++++------ client/cmdhfmfhard.h | 34 +- client/cmdhfmfp.c | 1316 ++--- client/cmdhfmfu.c | 4000 ++++++------- client/cmdhfmfu.h | 76 +- client/cmdhftopaz.c | 714 +-- client/cmdhw.c | 462 +- client/cmdlf.c | 1594 ++--- client/cmdlf.h | 66 +- client/cmdlfawid.c | 904 +-- client/cmdlfawid.h | 4 +- client/cmdlfcotag.c | 144 +- client/cmdlfcotag.h | 6 +- client/cmdlfem4x.c | 2148 +++---- client/cmdlffdx.c | 536 +- client/cmdlffdx.h | 8 +- client/cmdlfguard.c | 506 +- client/cmdlfhid.c | 888 +-- client/cmdlfhid.h | 4 +- client/cmdlfhitag.c | 648 +- client/cmdlfindala.c | 764 +-- client/cmdlfindala.h | 2 +- client/cmdlfio.c | 506 +- client/cmdlfjablotron.c | 320 +- client/cmdlfkeri.c | 318 +- client/cmdlfnedap.c | 428 +- client/cmdlfnexwatch.c | 132 +- client/cmdlfnoralsy.c | 352 +- client/cmdlfpac.c | 100 +- client/cmdlfparadox.c | 258 +- client/cmdlfpcf7931.c | 192 +- client/cmdlfpcf7931.h | 10 +- client/cmdlfpresco.c | 358 +- client/cmdlfpyramid.c | 514 +- client/cmdlfsecurakey.c | 176 +- client/cmdlft55xx.c | 3278 +++++------ client/cmdlft55xx.h | 150 +- client/cmdlfti.c | 356 +- client/cmdlfviking.c | 216 +- client/cmdlfvisa2000.c | 296 +- client/cmdmain.c | 62 +- client/cmdmain.h | 6 +- client/cmdparser.c | 178 +- client/cmdscript.c | 72 +- client/cmdsmartcard.c | 1708 +++--- client/cmdsmartcard.h | 10 +- client/cmdtrace.c | 934 +-- client/cmdtrace.h | 16 +- client/comms.c | 590 +- client/comms.h | 16 +- client/crypto/asn1dump.c | 520 +- client/crypto/asn1utils.c | 98 +- client/crypto/libpcrypto.c | 482 +- client/elf.h | 44 +- client/emv/apduinfo.c | 570 +- client/emv/apduinfo.h | 16 +- client/emv/cmdemv.c | 3298 +++++------ client/emv/crypto.c | 136 +- client/emv/crypto.h | 8 +- client/emv/crypto_backend.h | 30 +- client/emv/crypto_polarssl.c | 386 +- client/emv/dol.c | 156 +- client/emv/dump.c | 48 +- client/emv/emv_pk.c | 680 +-- client/emv/emv_pk.h | 26 +- client/emv/emv_pki.c | 804 +-- client/emv/emv_pki.h | 18 +- client/emv/emv_pki_priv.c | 364 +- client/emv/emv_pki_priv.h | 4 +- client/emv/emv_roca.c | 188 +- client/emv/emv_roca.h | 2 +- client/emv/emv_tags.c | 1340 ++--- client/emv/emvcore.c | 1612 ++--- client/emv/emvcore.h | 38 +- client/emv/emvjson.c | 492 +- client/emv/emvjson.h | 4 +- client/emv/test/cda_test.c | 618 +- client/emv/test/crypto_test.c | 460 +- client/emv/test/cryptotest.c | 92 +- client/emv/test/dda_test.c | 538 +- client/emv/test/sda_test.c | 364 +- client/emv/tlv.c | 690 +-- client/emv/tlv.h | 6 +- client/fido/additional_ca.c | 46 +- client/fido/cbortools.c | 680 +-- client/fido/cose.c | 334 +- client/fido/fidocore.c | 1236 ++-- client/fido/fidocore.h | 22 +- client/flash.c | 714 +-- client/flash.h | 14 +- client/flasher.c | 136 +- client/fpga_compress.c | 700 +-- client/graph.c | 330 +- client/guidummy.cpp | 10 +- client/hardnested/hardnested_bf_core.c | 558 +- client/hardnested/hardnested_bf_core.h | 16 +- client/hardnested/hardnested_bitarray_core.c | 502 +- client/hardnested/hardnested_bruteforce.c | 576 +- client/hardnested/hardnested_bruteforce.h | 6 +- client/hardnested/hardnested_tables.c | 860 +-- client/hid-flasher/elf.h | 44 +- client/hid-flasher/flash.c | 704 +-- client/hid-flasher/flash.h | 14 +- client/hid-flasher/flasher.c | 112 +- client/hid-flasher/proxendian.h | 4 +- client/hid-flasher/proxusb.c | 114 +- client/hid-flasher/usb_cmd.h | 104 +- client/jansson/error.c | 2 +- client/jansson/jansson.h | 8 +- client/loclass/cipher.c | 296 +- client/loclass/cipherutils.c | 250 +- client/loclass/cipherutils.h | 12 +- client/loclass/elite_crack.c | 648 +- client/loclass/elite_crack.h | 26 +- client/loclass/fileutils.c | 716 +-- client/loclass/fileutils.h | 8 +- client/loclass/ikeys.c | 1046 ++-- client/loclass/ikeys.h | 6 +- client/loclass/main.c | 112 +- client/mifare/mad.c | 364 +- client/mifare/mad.h | 4 +- client/mifare/mfkey.c | 238 +- client/mifare/mifare4.c | 634 +- client/mifare/mifare4.h | 36 +- client/mifare/mifaredefault.h | 46 +- client/mifare/mifarehost.c | 1478 ++--- client/mifare/mifarehost.h | 62 +- client/mifare/ndef.c | 524 +- client/mifare/ndef.h | 60 +- client/pm3_binlib.c | 134 +- client/pm3_bitlib.c | 10 +- client/proxendian.h | 4 +- client/proxgui.cpp | 42 +- client/proxguiqt.cpp | 912 +-- client/proxguiqt.h | 166 +- client/proxmark3.c | 520 +- client/reveng/bmpbit.c | 58 +- client/reveng/cli.c | 1004 ++-- client/reveng/config.h | 8 +- client/reveng/getopt.c | 62 +- client/reveng/model.c | 326 +- client/reveng/poly.c | 1746 +++--- client/reveng/preset.c | 1352 ++--- client/reveng/reveng.c | 760 +-- client/reveng/reveng.h | 20 +- client/scandir.c | 100 +- client/scripting.c | 590 +- client/scripting.h | 6 +- client/ui.c | 298 +- client/usb_cmd_h2lua.awk | 14 +- client/util.c | 796 +-- client/util.h | 128 +- client/util_darwin.m | 26 +- client/util_posix.c | 148 +- client/util_posix.h | 4 +- client/whereami.c | 2 +- common/protocols.h | 6 +- 197 files changed, 49383 insertions(+), 49383 deletions(-) diff --git a/Makefile b/Makefile index 93ee2d19c..bf298e652 100644 --- a/Makefile +++ b/Makefile @@ -89,7 +89,7 @@ endif print-%: ; @echo $* = $($*) style: - find . \( -name "*.[ch]" -or -name "*.cpp" \) -exec perl -pi -e 's/[ \t\r]+$$//' {} \; + find . \( -name "*.[ch]" -or -name "*.cpp" -or -name "*.lua" \) -exec perl -pi -e 's/[ \t\r]+$$//' {} \; # Dummy target to test for GNU make availability _test: diff --git a/client/amiitool/amiibo.c b/client/amiitool/amiibo.c index 85b7b226a..24a9f158d 100644 --- a/client/amiitool/amiibo.c +++ b/client/amiitool/amiibo.c @@ -13,168 +13,168 @@ #define HMAC_POS_TAG 0x1B4 void nfc3d_amiibo_calc_seed(const uint8_t * dump, uint8_t * key) { - memcpy(key + 0x00, dump + 0x029, 0x02); - memset(key + 0x02, 0x00, 0x0E); - memcpy(key + 0x10, dump + 0x1D4, 0x08); - memcpy(key + 0x18, dump + 0x1D4, 0x08); - memcpy(key + 0x20, dump + 0x1E8, 0x20); + memcpy(key + 0x00, dump + 0x029, 0x02); + memset(key + 0x02, 0x00, 0x0E); + memcpy(key + 0x10, dump + 0x1D4, 0x08); + memcpy(key + 0x18, dump + 0x1D4, 0x08); + memcpy(key + 0x20, dump + 0x1E8, 0x20); } void nfc3d_amiibo_keygen(const nfc3d_keygen_masterkeys * masterKeys, const uint8_t * dump, nfc3d_keygen_derivedkeys * derivedKeys) { - uint8_t seed[NFC3D_KEYGEN_SEED_SIZE]; + uint8_t seed[NFC3D_KEYGEN_SEED_SIZE]; - nfc3d_amiibo_calc_seed(dump, seed); - nfc3d_keygen(masterKeys, seed, derivedKeys); + nfc3d_amiibo_calc_seed(dump, seed); + nfc3d_keygen(masterKeys, seed, derivedKeys); } void nfc3d_amiibo_cipher(const nfc3d_keygen_derivedkeys * keys, const uint8_t * in, uint8_t * out) { - mbedtls_aes_context aes; - size_t nc_off = 0; - unsigned char nonce_counter[16]; - unsigned char stream_block[16]; + mbedtls_aes_context aes; + size_t nc_off = 0; + unsigned char nonce_counter[16]; + unsigned char stream_block[16]; - mbedtls_aes_setkey_enc( &aes, keys->aesKey, 128 ); - memset(nonce_counter, 0, sizeof(nonce_counter)); - memset(stream_block, 0, sizeof(stream_block)); - memcpy(nonce_counter, keys->aesIV, sizeof(nonce_counter)); - mbedtls_aes_crypt_ctr( &aes, 0x188, &nc_off, nonce_counter, stream_block, in + 0x02C, out + 0x02C ); + mbedtls_aes_setkey_enc( &aes, keys->aesKey, 128 ); + memset(nonce_counter, 0, sizeof(nonce_counter)); + memset(stream_block, 0, sizeof(stream_block)); + memcpy(nonce_counter, keys->aesIV, sizeof(nonce_counter)); + mbedtls_aes_crypt_ctr( &aes, 0x188, &nc_off, nonce_counter, stream_block, in + 0x02C, out + 0x02C ); - memcpy(out + 0x000, in + 0x000, 0x008); - // Data signature NOT copied - memcpy(out + 0x028, in + 0x028, 0x004); - // Tag signature NOT copied - memcpy(out + 0x1D4, in + 0x1D4, 0x034); + memcpy(out + 0x000, in + 0x000, 0x008); + // Data signature NOT copied + memcpy(out + 0x028, in + 0x028, 0x004); + // Tag signature NOT copied + memcpy(out + 0x1D4, in + 0x1D4, 0x034); } void nfc3d_amiibo_tag_to_internal(const uint8_t * tag, uint8_t * intl) { - memcpy(intl + 0x000, tag + 0x008, 0x008); - memcpy(intl + 0x008, tag + 0x080, 0x020); - memcpy(intl + 0x028, tag + 0x010, 0x024); - memcpy(intl + 0x04C, tag + 0x0A0, 0x168); - memcpy(intl + 0x1B4, tag + 0x034, 0x020); - memcpy(intl + 0x1D4, tag + 0x000, 0x008); - memcpy(intl + 0x1DC, tag + 0x054, 0x02C); + memcpy(intl + 0x000, tag + 0x008, 0x008); + memcpy(intl + 0x008, tag + 0x080, 0x020); + memcpy(intl + 0x028, tag + 0x010, 0x024); + memcpy(intl + 0x04C, tag + 0x0A0, 0x168); + memcpy(intl + 0x1B4, tag + 0x034, 0x020); + memcpy(intl + 0x1D4, tag + 0x000, 0x008); + memcpy(intl + 0x1DC, tag + 0x054, 0x02C); } void nfc3d_amiibo_internal_to_tag(const uint8_t * intl, uint8_t * tag) { - memcpy(tag + 0x008, intl + 0x000, 0x008); - memcpy(tag + 0x080, intl + 0x008, 0x020); - memcpy(tag + 0x010, intl + 0x028, 0x024); - memcpy(tag + 0x0A0, intl + 0x04C, 0x168); - memcpy(tag + 0x034, intl + 0x1B4, 0x020); - memcpy(tag + 0x000, intl + 0x1D4, 0x008); - memcpy(tag + 0x054, intl + 0x1DC, 0x02C); + memcpy(tag + 0x008, intl + 0x000, 0x008); + memcpy(tag + 0x080, intl + 0x008, 0x020); + memcpy(tag + 0x010, intl + 0x028, 0x024); + memcpy(tag + 0x0A0, intl + 0x04C, 0x168); + memcpy(tag + 0x034, intl + 0x1B4, 0x020); + memcpy(tag + 0x000, intl + 0x1D4, 0x008); + memcpy(tag + 0x054, intl + 0x1DC, 0x02C); } bool nfc3d_amiibo_unpack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * tag, uint8_t * plain) { - uint8_t internal[NFC3D_AMIIBO_SIZE]; - nfc3d_keygen_derivedkeys dataKeys; - nfc3d_keygen_derivedkeys tagKeys; + uint8_t internal[NFC3D_AMIIBO_SIZE]; + nfc3d_keygen_derivedkeys dataKeys; + nfc3d_keygen_derivedkeys tagKeys; - // Convert format - nfc3d_amiibo_tag_to_internal(tag, internal); + // Convert format + nfc3d_amiibo_tag_to_internal(tag, internal); - // Generate keys - nfc3d_amiibo_keygen(&amiiboKeys->data, internal, &dataKeys); - nfc3d_amiibo_keygen(&amiiboKeys->tag, internal, &tagKeys); + // Generate keys + nfc3d_amiibo_keygen(&amiiboKeys->data, internal, &dataKeys); + nfc3d_amiibo_keygen(&amiiboKeys->tag, internal, &tagKeys); - // Decrypt - nfc3d_amiibo_cipher(&dataKeys, internal, plain); + // Decrypt + nfc3d_amiibo_cipher(&dataKeys, internal, plain); - // Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC! - mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey), - plain + 0x1D4, 0x34, plain + HMAC_POS_TAG ); + // Regenerate tag HMAC. Note: order matters, data HMAC depends on tag HMAC! + mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey), + plain + 0x1D4, 0x34, plain + HMAC_POS_TAG ); - // Regenerate data HMAC - mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), dataKeys.hmacKey, sizeof(dataKeys.hmacKey), - plain + 0x029, 0x1DF, plain + HMAC_POS_DATA ); + // Regenerate data HMAC + mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), dataKeys.hmacKey, sizeof(dataKeys.hmacKey), + plain + 0x029, 0x1DF, plain + HMAC_POS_DATA ); - return - memcmp(plain + HMAC_POS_DATA, internal + HMAC_POS_DATA, 32) == 0 && - memcmp(plain + HMAC_POS_TAG, internal + HMAC_POS_TAG, 32) == 0; + return + memcmp(plain + HMAC_POS_DATA, internal + HMAC_POS_DATA, 32) == 0 && + memcmp(plain + HMAC_POS_TAG, internal + HMAC_POS_TAG, 32) == 0; } void nfc3d_amiibo_pack(const nfc3d_amiibo_keys * amiiboKeys, const uint8_t * plain, uint8_t * tag) { - uint8_t cipher[NFC3D_AMIIBO_SIZE]; - nfc3d_keygen_derivedkeys tagKeys; - nfc3d_keygen_derivedkeys dataKeys; + uint8_t cipher[NFC3D_AMIIBO_SIZE]; + nfc3d_keygen_derivedkeys tagKeys; + nfc3d_keygen_derivedkeys dataKeys; - // Generate keys - nfc3d_amiibo_keygen(&amiiboKeys->tag, plain, &tagKeys); - nfc3d_amiibo_keygen(&amiiboKeys->data, plain, &dataKeys); + // Generate keys + nfc3d_amiibo_keygen(&amiiboKeys->tag, plain, &tagKeys); + nfc3d_amiibo_keygen(&amiiboKeys->data, plain, &dataKeys); - // Generate tag HMAC - mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey), - plain + 0x1D4, 0x34, cipher + HMAC_POS_TAG ); + // Generate tag HMAC + mbedtls_md_hmac( mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), tagKeys.hmacKey, sizeof(tagKeys.hmacKey), + plain + 0x1D4, 0x34, cipher + HMAC_POS_TAG ); - // Init mbedtls HMAC context - mbedtls_md_context_t ctx; - mbedtls_md_init( &ctx ); - mbedtls_md_setup( &ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1 ); + // Init mbedtls HMAC context + mbedtls_md_context_t ctx; + mbedtls_md_init( &ctx ); + mbedtls_md_setup( &ctx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1 ); - // Generate data HMAC - mbedtls_md_hmac_starts( &ctx, dataKeys.hmacKey, sizeof(dataKeys.hmacKey) ); - mbedtls_md_hmac_update( &ctx, plain + 0x029, 0x18B ); // Data - mbedtls_md_hmac_update( &ctx, cipher + HMAC_POS_TAG, 0x20 ); // Tag HMAC - mbedtls_md_hmac_update( &ctx, plain + 0x1D4, 0x34 ); // Here be dragons + // Generate data HMAC + mbedtls_md_hmac_starts( &ctx, dataKeys.hmacKey, sizeof(dataKeys.hmacKey) ); + mbedtls_md_hmac_update( &ctx, plain + 0x029, 0x18B ); // Data + mbedtls_md_hmac_update( &ctx, cipher + HMAC_POS_TAG, 0x20 ); // Tag HMAC + mbedtls_md_hmac_update( &ctx, plain + 0x1D4, 0x34 ); // Here be dragons - mbedtls_md_hmac_finish( &ctx, cipher + HMAC_POS_DATA ); + mbedtls_md_hmac_finish( &ctx, cipher + HMAC_POS_DATA ); - // HMAC cleanup - mbedtls_md_free( &ctx ); + // HMAC cleanup + mbedtls_md_free( &ctx ); - // Encrypt - nfc3d_amiibo_cipher(&dataKeys, plain, cipher); + // Encrypt + nfc3d_amiibo_cipher(&dataKeys, plain, cipher); - // Convert back to hardware - nfc3d_amiibo_internal_to_tag(cipher, tag); + // Convert back to hardware + nfc3d_amiibo_internal_to_tag(cipher, tag); } bool nfc3d_amiibo_load_keys(nfc3d_amiibo_keys * amiiboKeys, const char * path) { - FILE * f = fopen(path, "rb"); - if (!f) { - return false; - } + FILE * f = fopen(path, "rb"); + if (!f) { + return false; + } - if (!fread(amiiboKeys, sizeof(*amiiboKeys), 1, f)) { - fclose(f); - return false; - } - fclose(f); + if (!fread(amiiboKeys, sizeof(*amiiboKeys), 1, f)) { + fclose(f); + return false; + } + fclose(f); - if ( - (amiiboKeys->data.magicBytesSize > 16) || - (amiiboKeys->tag.magicBytesSize > 16) - ) { - return false; - } + if ( + (amiiboKeys->data.magicBytesSize > 16) || + (amiiboKeys->tag.magicBytesSize > 16) + ) { + return false; + } - return true; + return true; } void nfc3d_amiibo_copy_app_data(const uint8_t * src, uint8_t * dst) { - //uint16_t *ami_nb_wr = (uint16_t*)(dst + 0x29); - //uint16_t *cfg_nb_wr = (uint16_t*)(dst + 0xB4); + //uint16_t *ami_nb_wr = (uint16_t*)(dst + 0x29); + //uint16_t *cfg_nb_wr = (uint16_t*)(dst + 0xB4); - /* increment write counters */ - //*ami_nb_wr = htobe16(be16toh(*ami_nb_wr) + 1); - //*cfg_nb_wr = htobe16(be16toh(*cfg_nb_wr) + 1); + /* increment write counters */ + //*ami_nb_wr = htobe16(be16toh(*ami_nb_wr) + 1); + //*cfg_nb_wr = htobe16(be16toh(*cfg_nb_wr) + 1); - uint16_t ami_nb_wr = ((uint16_t)bytes_to_num(dst + 0x29, 2)) + 1; - uint16_t cfg_nb_wr = ((uint16_t)bytes_to_num(dst + 0xB4, 2)) + 1; + uint16_t ami_nb_wr = ((uint16_t)bytes_to_num(dst + 0x29, 2)) + 1; + uint16_t cfg_nb_wr = ((uint16_t)bytes_to_num(dst + 0xB4, 2)) + 1; - num_to_bytes(ami_nb_wr, 2, dst + 0x29); - num_to_bytes(cfg_nb_wr, 2, dst + 0xB4); + num_to_bytes(ami_nb_wr, 2, dst + 0x29); + num_to_bytes(cfg_nb_wr, 2, dst + 0xB4); - /* copy flags */ - dst[0x2C] = src[0x2C]; - /* copy programID */ - memcpy(dst + 0xAC, src + 0xAC, 8); - /* copy AppID */ - memcpy(dst + 0xB6, src + 0xB6, 4); - /* copy AppData */ - memcpy(dst + 0xDC, src + 0xDC, 216); + /* copy flags */ + dst[0x2C] = src[0x2C]; + /* copy programID */ + memcpy(dst + 0xAC, src + 0xAC, 8); + /* copy AppID */ + memcpy(dst + 0xB6, src + 0xB6, 4); + /* copy AppData */ + memcpy(dst + 0xDC, src + 0xDC, 216); } diff --git a/client/amiitool/amiibo.h b/client/amiitool/amiibo.h index 3c7dccc70..5b45e9b98 100644 --- a/client/amiitool/amiibo.h +++ b/client/amiitool/amiibo.h @@ -19,8 +19,8 @@ #pragma pack(1) typedef struct { - nfc3d_keygen_masterkeys data; - nfc3d_keygen_masterkeys tag; + nfc3d_keygen_masterkeys data; + nfc3d_keygen_masterkeys tag; } nfc3d_amiibo_keys; #pragma pack() diff --git a/client/amiitool/amiitool.c b/client/amiitool/amiitool.c index 163e6529c..2643ffa36 100644 --- a/client/amiitool/amiitool.c +++ b/client/amiitool/amiitool.c @@ -15,161 +15,161 @@ static char * self; void amiitool_usage() { - fprintf(stderr, - "amiitool build %i (commit %s-%08x)\n" - "by Marcos Del Sol Vives \n" - "\n" - "Usage: %s (-e|-d|-c) -k keyfile [-i input] [-s input2] [-o output]\n" - " -e encrypt and sign amiibo\n" - " -d decrypt and test amiibo\n" - " -c decrypt, copy AppData and encrypt amiibo\n" - " -k key set file. For retail amiibo, use \"retail unfixed\" key set\n" - " -i input file. If not specified, stdin will be used.\n" - " -s input save file, save from this file will replace input file ones.\n" - " -o output file. If not specified, stdout will be used.\n" - " -l decrypt files with invalid signatures.\n", - , self - ); + fprintf(stderr, + "amiitool build %i (commit %s-%08x)\n" + "by Marcos Del Sol Vives \n" + "\n" + "Usage: %s (-e|-d|-c) -k keyfile [-i input] [-s input2] [-o output]\n" + " -e encrypt and sign amiibo\n" + " -d decrypt and test amiibo\n" + " -c decrypt, copy AppData and encrypt amiibo\n" + " -k key set file. For retail amiibo, use \"retail unfixed\" key set\n" + " -i input file. If not specified, stdin will be used.\n" + " -s input save file, save from this file will replace input file ones.\n" + " -o output file. If not specified, stdout will be used.\n" + " -l decrypt files with invalid signatures.\n", + , self + ); } static bool LoadAmiikey(nfc3d_amiibo_keys keys, char* keyfile) { - if (!nfc3d_amiibo_load_keys(&keys, keyfile)) { - PrintAndLogEx(ERR, "Could not load keys from '%s'", keyfile); - return false; - } - return true; + if (!nfc3d_amiibo_load_keys(&keys, keyfile)) { + PrintAndLogEx(ERR, "Could not load keys from '%s'", keyfile); + return false; + } + return true; } int main(int argc, char ** argv) { - self = argv[0]; + self = argv[0]; - char * infile = NULL; - char * savefile = NULL; - char * outfile = NULL; - char * keyfile = NULL; - char op = '\0'; - bool lenient = false; + char * infile = NULL; + char * savefile = NULL; + char * outfile = NULL; + char * keyfile = NULL; + char op = '\0'; + bool lenient = false; - char c; - while ((c = getopt(argc, argv, "edci:s:o:k:l")) != -1) { - switch (c) { - case 'e': - case 'd': - case 'c': - op = c; - break; - case 'i': - infile = optarg; - break; - case 's': - savefile = optarg; - break; - case 'o': - outfile = optarg; - break; - case 'l': - lenient = true; - break; - default: - amiitool_usage(); - return 2; - } - } + char c; + while ((c = getopt(argc, argv, "edci:s:o:k:l")) != -1) { + switch (c) { + case 'e': + case 'd': + case 'c': + op = c; + break; + case 'i': + infile = optarg; + break; + case 's': + savefile = optarg; + break; + case 'o': + outfile = optarg; + break; + case 'l': + lenient = true; + break; + default: + amiitool_usage(); + return 2; + } + } - if (op == '\0' || keyfile == NULL) { - amiitool_usage(); - return 1; - } + if (op == '\0' || keyfile == NULL) { + amiitool_usage(); + return 1; + } - nfc3d_amiibo_keys amiiboKeys; + nfc3d_amiibo_keys amiiboKeys; - uint8_t original[NTAG215_SIZE]; - uint8_t modified[NFC3D_AMIIBO_SIZE]; + uint8_t original[NTAG215_SIZE]; + uint8_t modified[NFC3D_AMIIBO_SIZE]; - FILE * f = stdin; - if (infile) { - f = fopen(infile, "rb"); - if (!f) { - fprintf(stderr, "Could not open input file\n"); - return 3; - } - } - size_t readPages = fread(original, 4, NTAG215_SIZE / 4, f); - if (readPages < NFC3D_AMIIBO_SIZE / 4) { - fprintf(stderr, "Could not read from input\n"); - fclose(f); - return 3; - } - fclose(f); + FILE * f = stdin; + if (infile) { + f = fopen(infile, "rb"); + if (!f) { + fprintf(stderr, "Could not open input file\n"); + return 3; + } + } + size_t readPages = fread(original, 4, NTAG215_SIZE / 4, f); + if (readPages < NFC3D_AMIIBO_SIZE / 4) { + fprintf(stderr, "Could not read from input\n"); + fclose(f); + return 3; + } + fclose(f); - if (op == 'e') { - nfc3d_amiibo_pack(&amiiboKeys, original, modified); - } else if (op == 'd') { - if (!nfc3d_amiibo_unpack(&amiiboKeys, original, modified)) { - fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n"); - if (!lenient) { - return 6; - } - } - } else { /* copy */ - uint8_t plain_base[NFC3D_AMIIBO_SIZE]; - uint8_t plain_save[NFC3D_AMIIBO_SIZE]; + if (op == 'e') { + nfc3d_amiibo_pack(&amiiboKeys, original, modified); + } else if (op == 'd') { + if (!nfc3d_amiibo_unpack(&amiiboKeys, original, modified)) { + fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n"); + if (!lenient) { + return 6; + } + } + } else { /* copy */ + uint8_t plain_base[NFC3D_AMIIBO_SIZE]; + uint8_t plain_save[NFC3D_AMIIBO_SIZE]; - if (!nfc3d_amiibo_unpack(&amiiboKeys, original, plain_base)) { - fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n"); - if (!lenient) { - return 6; - } - } - if (savefile) { - f = fopen(savefile, "rb"); - if (!f) { - fprintf(stderr, "Could not open save file\n"); - return 3; - } - } - size_t readPages = fread(original, 4, NTAG215_SIZE / 4, f); - if (readPages < NFC3D_AMIIBO_SIZE / 4) { - fprintf(stderr, "Could not read from save\n"); - fclose(f); - return 3; - } - fclose(f); + if (!nfc3d_amiibo_unpack(&amiiboKeys, original, plain_base)) { + fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n"); + if (!lenient) { + return 6; + } + } + if (savefile) { + f = fopen(savefile, "rb"); + if (!f) { + fprintf(stderr, "Could not open save file\n"); + return 3; + } + } + size_t readPages = fread(original, 4, NTAG215_SIZE / 4, f); + if (readPages < NFC3D_AMIIBO_SIZE / 4) { + fprintf(stderr, "Could not read from save\n"); + fclose(f); + return 3; + } + fclose(f); - if (!nfc3d_amiibo_unpack(&amiiboKeys, original, plain_save)) { - fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n"); - if (!lenient) { - return 6; - } - } + if (!nfc3d_amiibo_unpack(&amiiboKeys, original, plain_save)) { + fprintf(stderr, "!!! WARNING !!!: Tag signature was NOT valid\n"); + if (!lenient) { + return 6; + } + } - nfc3d_amiibo_copy_app_data(plain_save, plain_base); - nfc3d_amiibo_pack(&amiiboKeys, plain_base, modified); - } + nfc3d_amiibo_copy_app_data(plain_save, plain_base); + nfc3d_amiibo_pack(&amiiboKeys, plain_base, modified); + } - f = stdout; - if (outfile) { - f = fopen(outfile, "wb"); - if (!f) { - fprintf(stderr, "Could not open output file\n"); - return 4; - } - } - if (fwrite(modified, NFC3D_AMIIBO_SIZE, 1, f) != 1) { - fprintf(stderr, "Could not write to output\n"); - fclose(f); - return 4; - } - if (readPages > NFC3D_AMIIBO_SIZE / 4) { - if (fwrite(original + NFC3D_AMIIBO_SIZE, readPages * 4 - NFC3D_AMIIBO_SIZE, 1, f) != 1) { - fprintf(stderr, "Could not write to output:\n"); - fclose(f); - return 4; - } - } - fclose(f); - return 0; + f = stdout; + if (outfile) { + f = fopen(outfile, "wb"); + if (!f) { + fprintf(stderr, "Could not open output file\n"); + return 4; + } + } + if (fwrite(modified, NFC3D_AMIIBO_SIZE, 1, f) != 1) { + fprintf(stderr, "Could not write to output\n"); + fclose(f); + return 4; + } + if (readPages > NFC3D_AMIIBO_SIZE / 4) { + if (fwrite(original + NFC3D_AMIIBO_SIZE, readPages * 4 - NFC3D_AMIIBO_SIZE, 1, f) != 1) { + fprintf(stderr, "Could not write to output:\n"); + fclose(f); + return 4; + } + } + fclose(f); + return 0; } diff --git a/client/amiitool/drbg.c b/client/amiitool/drbg.c index d56366077..aaf0acef5 100644 --- a/client/amiitool/drbg.c +++ b/client/amiitool/drbg.c @@ -11,68 +11,68 @@ #include void nfc3d_drbg_init(nfc3d_drbg_ctx * ctx, const uint8_t * hmacKey, size_t hmacKeySize, const uint8_t * seed, size_t seedSize) { - assert(ctx != NULL); - assert(hmacKey != NULL); - assert(seed != NULL); - assert(seedSize <= NFC3D_DRBG_MAX_SEED_SIZE); + assert(ctx != NULL); + assert(hmacKey != NULL); + assert(seed != NULL); + assert(seedSize <= NFC3D_DRBG_MAX_SEED_SIZE); - // Initialize primitives - ctx->used = false; - ctx->iteration = 0; - ctx->bufferSize = sizeof(ctx->iteration) + seedSize; + // Initialize primitives + ctx->used = false; + ctx->iteration = 0; + ctx->bufferSize = sizeof(ctx->iteration) + seedSize; - // The 16-bit counter is prepended to the seed when hashing, so we'll leave 2 bytes at the start - memcpy(ctx->buffer + sizeof(uint16_t), seed, seedSize); + // The 16-bit counter is prepended to the seed when hashing, so we'll leave 2 bytes at the start + memcpy(ctx->buffer + sizeof(uint16_t), seed, seedSize); - // Initialize underlying HMAC context - mbedtls_md_init(&ctx->hmacCtx); - mbedtls_md_setup(&ctx->hmacCtx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1); - mbedtls_md_hmac_starts(&ctx->hmacCtx, hmacKey, hmacKeySize); + // Initialize underlying HMAC context + mbedtls_md_init(&ctx->hmacCtx); + mbedtls_md_setup(&ctx->hmacCtx, mbedtls_md_info_from_type(MBEDTLS_MD_SHA256), 1); + mbedtls_md_hmac_starts(&ctx->hmacCtx, hmacKey, hmacKeySize); } void nfc3d_drbg_step(nfc3d_drbg_ctx * ctx, uint8_t * output) { - assert(ctx != NULL); - assert(output != NULL); + assert(ctx != NULL); + assert(output != NULL); - if (ctx->used) { - // If used at least once, reinitialize the HMAC - mbedtls_md_hmac_reset(&ctx->hmacCtx); - } else { - ctx->used = true; - } + if (ctx->used) { + // If used at least once, reinitialize the HMAC + mbedtls_md_hmac_reset(&ctx->hmacCtx); + } else { + ctx->used = true; + } - // Store counter in big endian, and increment it - ctx->buffer[0] = ctx->iteration >> 8; - ctx->buffer[1] = ctx->iteration >> 0; - ctx->iteration++; + // Store counter in big endian, and increment it + ctx->buffer[0] = ctx->iteration >> 8; + ctx->buffer[1] = ctx->iteration >> 0; + ctx->iteration++; - // Do HMAC magic - mbedtls_md_hmac_update(&ctx->hmacCtx, ctx->buffer, ctx->bufferSize); - mbedtls_md_hmac_finish(&ctx->hmacCtx, output); + // Do HMAC magic + mbedtls_md_hmac_update(&ctx->hmacCtx, ctx->buffer, ctx->bufferSize); + mbedtls_md_hmac_finish(&ctx->hmacCtx, output); } void nfc3d_drbg_cleanup(nfc3d_drbg_ctx * ctx) { - assert(ctx != NULL); - mbedtls_md_free(&ctx->hmacCtx); + assert(ctx != NULL); + mbedtls_md_free(&ctx->hmacCtx); } void nfc3d_drbg_generate_bytes(const uint8_t * hmacKey, size_t hmacKeySize, const uint8_t * seed, size_t seedSize, uint8_t * output, size_t outputSize) { - uint8_t temp[NFC3D_DRBG_OUTPUT_SIZE]; + uint8_t temp[NFC3D_DRBG_OUTPUT_SIZE]; - nfc3d_drbg_ctx rngCtx; - nfc3d_drbg_init(&rngCtx, hmacKey, hmacKeySize, seed, seedSize); + nfc3d_drbg_ctx rngCtx; + nfc3d_drbg_init(&rngCtx, hmacKey, hmacKeySize, seed, seedSize); - while (outputSize > 0) { - if (outputSize < NFC3D_DRBG_OUTPUT_SIZE) { - nfc3d_drbg_step(&rngCtx, temp); - memcpy(output, temp, outputSize); - break; - } + while (outputSize > 0) { + if (outputSize < NFC3D_DRBG_OUTPUT_SIZE) { + nfc3d_drbg_step(&rngCtx, temp); + memcpy(output, temp, outputSize); + break; + } - nfc3d_drbg_step(&rngCtx, output); - output += NFC3D_DRBG_OUTPUT_SIZE; - outputSize -= NFC3D_DRBG_OUTPUT_SIZE; - } + nfc3d_drbg_step(&rngCtx, output); + output += NFC3D_DRBG_OUTPUT_SIZE; + outputSize -= NFC3D_DRBG_OUTPUT_SIZE; + } - nfc3d_drbg_cleanup(&rngCtx); + nfc3d_drbg_cleanup(&rngCtx); } diff --git a/client/amiitool/drbg.h b/client/amiitool/drbg.h index 0e93abfc0..7b5bddc86 100644 --- a/client/amiitool/drbg.h +++ b/client/amiitool/drbg.h @@ -12,16 +12,16 @@ #include #include "mbedtls/md.h" -#define NFC3D_DRBG_MAX_SEED_SIZE 480 /* Hardcoded max size in 3DS NFC module */ -#define NFC3D_DRBG_OUTPUT_SIZE 32 /* Every iteration generates 32 bytes */ +#define NFC3D_DRBG_MAX_SEED_SIZE 480 /* Hardcoded max size in 3DS NFC module */ +#define NFC3D_DRBG_OUTPUT_SIZE 32 /* Every iteration generates 32 bytes */ typedef struct { - mbedtls_md_context_t hmacCtx; - bool used; - uint16_t iteration; + mbedtls_md_context_t hmacCtx; + bool used; + uint16_t iteration; - uint8_t buffer[sizeof(uint16_t) + NFC3D_DRBG_MAX_SEED_SIZE]; - size_t bufferSize; + uint8_t buffer[sizeof(uint16_t) + NFC3D_DRBG_MAX_SEED_SIZE]; + size_t bufferSize; } nfc3d_drbg_ctx; void nfc3d_drbg_init(nfc3d_drbg_ctx * ctx, const uint8_t * hmacKey, size_t hmacKeySize, const uint8_t * seed, size_t seedSize); diff --git a/client/amiitool/keygen.c b/client/amiitool/keygen.c index c82e3abee..1c0a91344 100644 --- a/client/amiitool/keygen.c +++ b/client/amiitool/keygen.c @@ -11,43 +11,43 @@ #include void nfc3d_keygen_prepare_seed(const nfc3d_keygen_masterkeys * baseKeys, const uint8_t * baseSeed, uint8_t * output, size_t * outputSize) { - assert(baseKeys != NULL); - assert(baseSeed != NULL); - assert(output != NULL); - assert(outputSize != NULL); + assert(baseKeys != NULL); + assert(baseSeed != NULL); + assert(output != NULL); + assert(outputSize != NULL); - uint8_t * start = output; + uint8_t * start = output; - // 1: Copy whole type string - output = memccpy(output, baseKeys->typeString, '\0', sizeof(baseKeys->typeString)); + // 1: Copy whole type string + output = memccpy(output, baseKeys->typeString, '\0', sizeof(baseKeys->typeString)); - // 2: Append (16 - magicBytesSize) from the input seed - size_t leadingSeedBytes = 16 - baseKeys->magicBytesSize; - memcpy(output, baseSeed, leadingSeedBytes); - output += leadingSeedBytes; + // 2: Append (16 - magicBytesSize) from the input seed + size_t leadingSeedBytes = 16 - baseKeys->magicBytesSize; + memcpy(output, baseSeed, leadingSeedBytes); + output += leadingSeedBytes; - // 3: Append all bytes from magicBytes - memcpy(output, baseKeys->magicBytes, baseKeys->magicBytesSize); - output += baseKeys->magicBytesSize; + // 3: Append all bytes from magicBytes + memcpy(output, baseKeys->magicBytes, baseKeys->magicBytesSize); + output += baseKeys->magicBytesSize; - // 4: Append bytes 0x10-0x1F from input seed - memcpy(output, baseSeed + 0x10, 16); - output += 16; + // 4: Append bytes 0x10-0x1F from input seed + memcpy(output, baseSeed + 0x10, 16); + output += 16; - // 5: Xor last bytes 0x20-0x3F of input seed with AES XOR pad and append them - unsigned int i; - for (i = 0; i < 32; i++) { - output[i] = baseSeed[i + 32] ^ baseKeys->xorPad[i]; - } - output += 32; + // 5: Xor last bytes 0x20-0x3F of input seed with AES XOR pad and append them + unsigned int i; + for (i = 0; i < 32; i++) { + output[i] = baseSeed[i + 32] ^ baseKeys->xorPad[i]; + } + output += 32; - *outputSize = output - start; + *outputSize = output - start; } void nfc3d_keygen(const nfc3d_keygen_masterkeys * baseKeys, const uint8_t * baseSeed, nfc3d_keygen_derivedkeys * derivedKeys) { - uint8_t preparedSeed[NFC3D_DRBG_MAX_SEED_SIZE]; - size_t preparedSeedSize; + uint8_t preparedSeed[NFC3D_DRBG_MAX_SEED_SIZE]; + size_t preparedSeedSize; - nfc3d_keygen_prepare_seed(baseKeys, baseSeed, preparedSeed, &preparedSeedSize); - nfc3d_drbg_generate_bytes(baseKeys->hmacKey, sizeof(baseKeys->hmacKey), preparedSeed, preparedSeedSize, (uint8_t *) derivedKeys, sizeof(*derivedKeys)); + nfc3d_keygen_prepare_seed(baseKeys, baseSeed, preparedSeed, &preparedSeedSize); + nfc3d_drbg_generate_bytes(baseKeys->hmacKey, sizeof(baseKeys->hmacKey), preparedSeed, preparedSeedSize, (uint8_t *) derivedKeys, sizeof(*derivedKeys)); } diff --git a/client/amiitool/keygen.h b/client/amiitool/keygen.h index 35595e3ef..5e371074e 100644 --- a/client/amiitool/keygen.h +++ b/client/amiitool/keygen.h @@ -14,18 +14,18 @@ #pragma pack(1) typedef struct { - uint8_t hmacKey[16]; - char typeString[14]; - uint8_t rfu; - uint8_t magicBytesSize; - uint8_t magicBytes[16]; - uint8_t xorPad[32]; + uint8_t hmacKey[16]; + char typeString[14]; + uint8_t rfu; + uint8_t magicBytesSize; + uint8_t magicBytes[16]; + uint8_t xorPad[32]; } nfc3d_keygen_masterkeys; typedef struct { - const uint8_t aesKey[16]; - const uint8_t aesIV[16]; - const uint8_t hmacKey[16]; + const uint8_t aesKey[16]; + const uint8_t aesIV[16]; + const uint8_t hmacKey[16]; } nfc3d_keygen_derivedkeys; #pragma pack() diff --git a/client/cliparser/argtable3.c b/client/cliparser/argtable3.c index 7e3461b37..63e847be1 100644 --- a/client/cliparser/argtable3.c +++ b/client/cliparser/argtable3.c @@ -168,9 +168,9 @@ void dbg_printf(const char *fmt, ...) #include "getopt.h" -/* $Id: getopt_long.c,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $ */ -/* $OpenBSD: getopt_long.c,v 1.23 2007/10/31 12:34:57 chl Exp $ */ -/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ +/* $Id: getopt_long.c,v 1.1 2009/10/16 19:50:28 rodney Exp rodney $ */ +/* $OpenBSD: getopt_long.c,v 1.23 2007/10/31 12:34:57 chl Exp $ */ +/* $NetBSD: getopt_long.c,v 1.15 2002/01/31 22:43:40 tv Exp $ */ /* * Copyright (c) 2002 Todd C. Miller @@ -231,33 +231,33 @@ void dbg_printf(const char *fmt, ...) #include -#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ +#define REPLACE_GETOPT /* use this getopt as the system getopt(3) */ #ifdef REPLACE_GETOPT -int opterr = 1; /* if error message should be printed */ -int optind = 1; /* index into parent argv vector */ -int optopt = '?'; /* character checked for validity */ -int optreset; /* reset getopt */ -char *optarg; /* argument associated with option */ +int opterr = 1; /* if error message should be printed */ +int optind = 1; /* index into parent argv vector */ +int optopt = '?'; /* character checked for validity */ +int optreset; /* reset getopt */ +char *optarg; /* argument associated with option */ #endif -#define PRINT_ERROR ((opterr) && (*options != ':')) +#define PRINT_ERROR ((opterr) && (*options != ':')) -#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ -#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ -#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ +#define FLAG_PERMUTE 0x01 /* permute non-options to the end of argv */ +#define FLAG_ALLARGS 0x02 /* treat non-options as args to option "-1" */ +#define FLAG_LONGONLY 0x04 /* operate as getopt_long_only */ /* return values */ -#define BADCH (int)'?' -#define BADARG ((*options == ':') ? (int)':' : (int)'?') -#define INORDER (int)1 +#define BADCH (int)'?' +#define BADARG ((*options == ':') ? (int)':' : (int)'?') +#define INORDER (int)1 -#define EMSG "" +#define EMSG "" static int getopt_internal(int, char * const *, const char *, - const struct option *, int *, int); + const struct option *, int *, int); static int parse_long_options(char * const *, const char *, - const struct option *, int *, int); + const struct option *, int *, int); static int gcd(int, int); static void permute_args(int, int, int, char * const *); @@ -296,22 +296,22 @@ char opterrmsg[MAX_OPTER_MSG_SIZE]; /* buffer for the last error message */ static void warnx(const char *fmt, ...) { - va_list ap; - va_start(ap, fmt); + va_list ap; + va_start(ap, fmt); /* Make sure opterrmsg is always zero-terminated despite the _vsnprintf() implementation specifics and manually suppress the warning. */ memset(opterrmsg, 0, sizeof opterrmsg); - if (fmt != NULL) + if (fmt != NULL) #ifdef __STDC_WANT_SECURE_LIB__ _vsnprintf_s(opterrmsg, MAX_OPTER_MSG_SIZE, sizeof(opterrmsg) - 1, fmt, ap); #else _vsnprintf(opterrmsg, sizeof(opterrmsg) - 1, fmt, ap); #endif - va_end(ap); + va_end(ap); - fprintf(stderr, "%s\n", opterrmsg); + fprintf(stderr, "%s\n", opterrmsg); } #else @@ -325,16 +325,16 @@ static void warnx(const char *fmt, ...) static int gcd(int a, int b) { - int c; + int c; - c = a % b; - while (c != 0) { - a = b; - b = c; - c = a % b; - } + c = a % b; + while (c != 0) { + a = b; + b = c; + c = a % b; + } - return (b); + return (b); } /* @@ -344,179 +344,179 @@ gcd(int a, int b) */ static void permute_args(int panonopt_start, int panonopt_end, int opt_end, - char * const *nargv) + char * const *nargv) { - int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; - char *swap; + int cstart, cyclelen, i, j, ncycle, nnonopts, nopts, pos; + char *swap; - /* - * compute lengths of blocks and number and size of cycles - */ - nnonopts = panonopt_end - panonopt_start; - nopts = opt_end - panonopt_end; - ncycle = gcd(nnonopts, nopts); - cyclelen = (opt_end - panonopt_start) / ncycle; + /* + * compute lengths of blocks and number and size of cycles + */ + nnonopts = panonopt_end - panonopt_start; + nopts = opt_end - panonopt_end; + ncycle = gcd(nnonopts, nopts); + cyclelen = (opt_end - panonopt_start) / ncycle; - for (i = 0; i < ncycle; i++) { - cstart = panonopt_end+i; - pos = cstart; - for (j = 0; j < cyclelen; j++) { - if (pos >= panonopt_end) - pos -= nnonopts; - else - pos += nopts; - swap = nargv[pos]; - /* LINTED const cast */ - ((char **) nargv)[pos] = nargv[cstart]; - /* LINTED const cast */ - ((char **)nargv)[cstart] = swap; - } - } + for (i = 0; i < ncycle; i++) { + cstart = panonopt_end+i; + pos = cstart; + for (j = 0; j < cyclelen; j++) { + if (pos >= panonopt_end) + pos -= nnonopts; + else + pos += nopts; + swap = nargv[pos]; + /* LINTED const cast */ + ((char **) nargv)[pos] = nargv[cstart]; + /* LINTED const cast */ + ((char **)nargv)[cstart] = swap; + } + } } /* * parse_long_options -- - * Parse long options in argc/argv argument vector. + * Parse long options in argc/argv argument vector. * Returns -1 if short_too is set and the option does not match long_options. */ static int parse_long_options(char * const *nargv, const char *options, - const struct option *long_options, int *idx, int short_too) + const struct option *long_options, int *idx, int short_too) { - char *current_argv, *has_equal; - size_t current_argv_len; - int i, match; + char *current_argv, *has_equal; + size_t current_argv_len; + int i, match; - current_argv = place; - match = -1; + current_argv = place; + match = -1; - optind++; + optind++; - if ((has_equal = strchr(current_argv, '=')) != NULL) { - /* argument found (--option=arg) */ - current_argv_len = has_equal - current_argv; - has_equal++; - } else - current_argv_len = strlen(current_argv); + if ((has_equal = strchr(current_argv, '=')) != NULL) { + /* argument found (--option=arg) */ + current_argv_len = has_equal - current_argv; + has_equal++; + } else + current_argv_len = strlen(current_argv); - for (i = 0; long_options[i].name; i++) { - /* find matching long option */ - if (strncmp(current_argv, long_options[i].name, - current_argv_len)) - continue; + for (i = 0; long_options[i].name; i++) { + /* find matching long option */ + if (strncmp(current_argv, long_options[i].name, + current_argv_len)) + continue; - if (strlen(long_options[i].name) == current_argv_len) { - /* exact match */ - match = i; - break; - } - /* - * If this is a known short option, don't allow - * a partial match of a single character. - */ - if (short_too && current_argv_len == 1) - continue; + if (strlen(long_options[i].name) == current_argv_len) { + /* exact match */ + match = i; + break; + } + /* + * If this is a known short option, don't allow + * a partial match of a single character. + */ + if (short_too && current_argv_len == 1) + continue; - if (match == -1) /* partial match */ - match = i; - else { - /* ambiguous abbreviation */ - if (PRINT_ERROR) - warnx(ambig, (int)current_argv_len, - current_argv); - optopt = 0; - return (BADCH); - } - } - if (match != -1) { /* option found */ - if (long_options[match].has_arg == no_argument - && has_equal) { - if (PRINT_ERROR) - warnx(noarg, (int)current_argv_len, - current_argv); - /* - * XXX: GNU sets optopt to val regardless of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - return (BADARG); - } - if (long_options[match].has_arg == required_argument || - long_options[match].has_arg == optional_argument) { - if (has_equal) - optarg = has_equal; - else if (long_options[match].has_arg == - required_argument) { - /* - * optional argument doesn't use next nargv - */ - optarg = nargv[optind++]; - } - } - if ((long_options[match].has_arg == required_argument) - && (optarg == NULL)) { - /* - * Missing argument; leading ':' indicates no error - * should be generated. - */ - if (PRINT_ERROR) - warnx(recargstring, - current_argv); - /* - * XXX: GNU sets optopt to val regardless of flag - */ - if (long_options[match].flag == NULL) - optopt = long_options[match].val; - else - optopt = 0; - --optind; - return (BADARG); - } - } else { /* unknown option */ - if (short_too) { - --optind; - return (-1); - } - if (PRINT_ERROR) - warnx(illoptstring, current_argv); - optopt = 0; - return (BADCH); - } - if (idx) - *idx = match; - if (long_options[match].flag) { - *long_options[match].flag = long_options[match].val; - return (0); - } else - return (long_options[match].val); + if (match == -1) /* partial match */ + match = i; + else { + /* ambiguous abbreviation */ + if (PRINT_ERROR) + warnx(ambig, (int)current_argv_len, + current_argv); + optopt = 0; + return (BADCH); + } + } + if (match != -1) { /* option found */ + if (long_options[match].has_arg == no_argument + && has_equal) { + if (PRINT_ERROR) + warnx(noarg, (int)current_argv_len, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + return (BADARG); + } + if (long_options[match].has_arg == required_argument || + long_options[match].has_arg == optional_argument) { + if (has_equal) + optarg = has_equal; + else if (long_options[match].has_arg == + required_argument) { + /* + * optional argument doesn't use next nargv + */ + optarg = nargv[optind++]; + } + } + if ((long_options[match].has_arg == required_argument) + && (optarg == NULL)) { + /* + * Missing argument; leading ':' indicates no error + * should be generated. + */ + if (PRINT_ERROR) + warnx(recargstring, + current_argv); + /* + * XXX: GNU sets optopt to val regardless of flag + */ + if (long_options[match].flag == NULL) + optopt = long_options[match].val; + else + optopt = 0; + --optind; + return (BADARG); + } + } else { /* unknown option */ + if (short_too) { + --optind; + return (-1); + } + if (PRINT_ERROR) + warnx(illoptstring, current_argv); + optopt = 0; + return (BADCH); + } + if (idx) + *idx = match; + if (long_options[match].flag) { + *long_options[match].flag = long_options[match].val; + return (0); + } else + return (long_options[match].val); } /* * getopt_internal -- - * Parse argc/argv argument vector. Called by user level routines. + * Parse argc/argv argument vector. Called by user level routines. */ static int getopt_internal(int nargc, char * const *nargv, const char *options, - const struct option *long_options, int *idx, int flags) + const struct option *long_options, int *idx, int flags) { - char *oli; /* option letter list index */ - int optchar, short_too; - static int posixly_correct = -1; + char *oli; /* option letter list index */ + int optchar, short_too; + static int posixly_correct = -1; #ifdef __STDC_WANT_SECURE_LIB__ char* buffer = NULL; size_t buffer_size = 0; errno_t err = 0; #endif - if (options == NULL) - return (-1); + if (options == NULL) + return (-1); - /* - * Disable GNU extensions if POSIXLY_CORRECT is set or options - * string begins with a '+'. - */ + /* + * Disable GNU extensions if POSIXLY_CORRECT is set or options + * string begins with a '+'. + */ #ifdef __STDC_WANT_SECURE_LIB__ if (posixly_correct == -1) { @@ -530,183 +530,183 @@ getopt_internal(int nargc, char * const *nargv, const char *options, if (posixly_correct == -1) posixly_correct = (getenv("POSIXLY_CORRECT") != NULL); #endif - if (posixly_correct || *options == '+') - flags &= ~FLAG_PERMUTE; - else if (*options == '-') - flags |= FLAG_ALLARGS; - if (*options == '+' || *options == '-') - options++; + if (posixly_correct || *options == '+') + flags &= ~FLAG_PERMUTE; + else if (*options == '-') + flags |= FLAG_ALLARGS; + if (*options == '+' || *options == '-') + options++; - /* - * XXX Some GNU programs (like cvs) set optind to 0 instead of - * XXX using optreset. Work around this braindamage. - */ - if (optind == 0) - optind = optreset = 1; + /* + * XXX Some GNU programs (like cvs) set optind to 0 instead of + * XXX using optreset. Work around this braindamage. + */ + if (optind == 0) + optind = optreset = 1; - optarg = NULL; - if (optreset) - nonopt_start = nonopt_end = -1; + optarg = NULL; + if (optreset) + nonopt_start = nonopt_end = -1; start: - if (optreset || !*place) { /* update scanning pointer */ - optreset = 0; - if (optind >= nargc) { /* end of argument vector */ - place = EMSG; - if (nonopt_end != -1) { - /* do permutation, if we have to */ - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - else if (nonopt_start != -1) { - /* - * If we skipped non-options, set optind - * to the first of them. - */ - optind = nonopt_start; - } - nonopt_start = nonopt_end = -1; - return (-1); - } - if (*(place = nargv[optind]) != '-' || - (place[1] == '\0' && strchr(options, '-') == NULL)) { - place = EMSG; /* found non-option */ - if (flags & FLAG_ALLARGS) { - /* - * GNU extension: - * return non-option as argument to option 1 - */ - optarg = nargv[optind++]; - return (INORDER); - } - if (!(flags & FLAG_PERMUTE)) { - /* - * If no permutation wanted, stop parsing - * at first non-option. - */ - return (-1); - } - /* do permutation */ - if (nonopt_start == -1) - nonopt_start = optind; - else if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - nonopt_start = optind - - (nonopt_end - nonopt_start); - nonopt_end = -1; - } - optind++; - /* process next argument */ - goto start; - } - if (nonopt_start != -1 && nonopt_end == -1) - nonopt_end = optind; + if (optreset || !*place) { /* update scanning pointer */ + optreset = 0; + if (optind >= nargc) { /* end of argument vector */ + place = EMSG; + if (nonopt_end != -1) { + /* do permutation, if we have to */ + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + else if (nonopt_start != -1) { + /* + * If we skipped non-options, set optind + * to the first of them. + */ + optind = nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + if (*(place = nargv[optind]) != '-' || + (place[1] == '\0' && strchr(options, '-') == NULL)) { + place = EMSG; /* found non-option */ + if (flags & FLAG_ALLARGS) { + /* + * GNU extension: + * return non-option as argument to option 1 + */ + optarg = nargv[optind++]; + return (INORDER); + } + if (!(flags & FLAG_PERMUTE)) { + /* + * If no permutation wanted, stop parsing + * at first non-option. + */ + return (-1); + } + /* do permutation */ + if (nonopt_start == -1) + nonopt_start = optind; + else if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + nonopt_start = optind - + (nonopt_end - nonopt_start); + nonopt_end = -1; + } + optind++; + /* process next argument */ + goto start; + } + if (nonopt_start != -1 && nonopt_end == -1) + nonopt_end = optind; - /* - * If we have "-" do nothing, if "--" we are done. - */ - if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { - optind++; - place = EMSG; - /* - * We found an option (--), so if we skipped - * non-options, we have to permute. - */ - if (nonopt_end != -1) { - permute_args(nonopt_start, nonopt_end, - optind, nargv); - optind -= nonopt_end - nonopt_start; - } - nonopt_start = nonopt_end = -1; - return (-1); - } - } + /* + * If we have "-" do nothing, if "--" we are done. + */ + if (place[1] != '\0' && *++place == '-' && place[1] == '\0') { + optind++; + place = EMSG; + /* + * We found an option (--), so if we skipped + * non-options, we have to permute. + */ + if (nonopt_end != -1) { + permute_args(nonopt_start, nonopt_end, + optind, nargv); + optind -= nonopt_end - nonopt_start; + } + nonopt_start = nonopt_end = -1; + return (-1); + } + } - /* - * Check long options if: - * 1) we were passed some - * 2) the arg is not just "-" - * 3) either the arg starts with -- we are getopt_long_only() - */ - if (long_options != NULL && place != nargv[optind] && - (*place == '-' || (flags & FLAG_LONGONLY))) { - short_too = 0; - if (*place == '-') - place++; /* --foo long option */ - else if (*place != ':' && strchr(options, *place) != NULL) - short_too = 1; /* could be short option too */ + /* + * Check long options if: + * 1) we were passed some + * 2) the arg is not just "-" + * 3) either the arg starts with -- we are getopt_long_only() + */ + if (long_options != NULL && place != nargv[optind] && + (*place == '-' || (flags & FLAG_LONGONLY))) { + short_too = 0; + if (*place == '-') + place++; /* --foo long option */ + else if (*place != ':' && strchr(options, *place) != NULL) + short_too = 1; /* could be short option too */ - optchar = parse_long_options(nargv, options, long_options, - idx, short_too); - if (optchar != -1) { - place = EMSG; - return (optchar); - } - } + optchar = parse_long_options(nargv, options, long_options, + idx, short_too); + if (optchar != -1) { + place = EMSG; + return (optchar); + } + } - if ((optchar = (int)*place++) == (int)':' || - (optchar == (int)'-' && *place != '\0') || - (oli = strchr(options, optchar)) == NULL) { - /* - * If the user specified "-" and '-' isn't listed in - * options, return -1 (non-option) as per POSIX. - * Otherwise, it is an unknown option character (or ':'). - */ - if (optchar == (int)'-' && *place == '\0') - return (-1); - if (!*place) - ++optind; - if (PRINT_ERROR) - warnx(illoptchar, optchar); - optopt = optchar; - return (BADCH); - } - if (long_options != NULL && optchar == 'W' && oli[1] == ';') { - /* -W long-option */ - if (*place) /* no space */ - /* NOTHING */; - else if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return (BADARG); - } else /* white space */ - place = nargv[optind]; - optchar = parse_long_options(nargv, options, long_options, - idx, 0); - place = EMSG; - return (optchar); - } - if (*++oli != ':') { /* doesn't take argument */ - if (!*place) - ++optind; - } else { /* takes (optional) argument */ - optarg = NULL; - if (*place) /* no white space */ - optarg = place; - else if (oli[1] != ':') { /* arg not optional */ - if (++optind >= nargc) { /* no arg */ - place = EMSG; - if (PRINT_ERROR) - warnx(recargchar, optchar); - optopt = optchar; - return (BADARG); - } else - optarg = nargv[optind]; - } - place = EMSG; - ++optind; - } - /* dump back option letter */ - return (optchar); + if ((optchar = (int)*place++) == (int)':' || + (optchar == (int)'-' && *place != '\0') || + (oli = strchr(options, optchar)) == NULL) { + /* + * If the user specified "-" and '-' isn't listed in + * options, return -1 (non-option) as per POSIX. + * Otherwise, it is an unknown option character (or ':'). + */ + if (optchar == (int)'-' && *place == '\0') + return (-1); + if (!*place) + ++optind; + if (PRINT_ERROR) + warnx(illoptchar, optchar); + optopt = optchar; + return (BADCH); + } + if (long_options != NULL && optchar == 'W' && oli[1] == ';') { + /* -W long-option */ + if (*place) /* no space */ + /* NOTHING */; + else if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else /* white space */ + place = nargv[optind]; + optchar = parse_long_options(nargv, options, long_options, + idx, 0); + place = EMSG; + return (optchar); + } + if (*++oli != ':') { /* doesn't take argument */ + if (!*place) + ++optind; + } else { /* takes (optional) argument */ + optarg = NULL; + if (*place) /* no white space */ + optarg = place; + else if (oli[1] != ':') { /* arg not optional */ + if (++optind >= nargc) { /* no arg */ + place = EMSG; + if (PRINT_ERROR) + warnx(recargchar, optchar); + optopt = optchar; + return (BADARG); + } else + optarg = nargv[optind]; + } + place = EMSG; + ++optind; + } + /* dump back option letter */ + return (optchar); } #ifdef REPLACE_GETOPT /* * getopt -- - * Parse argc/argv argument vector. + * Parse argc/argv argument vector. * * [eventually this will replace the BSD getopt] */ @@ -714,42 +714,42 @@ int getopt(int nargc, char * const *nargv, const char *options) { - /* - * We don't pass FLAG_PERMUTE to getopt_internal() since - * the BSD getopt(3) (unlike GNU) has never done this. - * - * Furthermore, since many privileged programs call getopt() - * before dropping privileges it makes sense to keep things - * as simple (and bug-free) as possible. - */ - return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); + /* + * We don't pass FLAG_PERMUTE to getopt_internal() since + * the BSD getopt(3) (unlike GNU) has never done this. + * + * Furthermore, since many privileged programs call getopt() + * before dropping privileges it makes sense to keep things + * as simple (and bug-free) as possible. + */ + return (getopt_internal(nargc, nargv, options, NULL, NULL, 0)); } #endif /* REPLACE_GETOPT */ /* * getopt_long -- - * Parse argc/argv argument vector. + * Parse argc/argv argument vector. */ int getopt_long(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx) { - return (getopt_internal(nargc, nargv, options, long_options, idx, - FLAG_PERMUTE)); + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE)); } /* * getopt_long_only -- - * Parse argc/argv argument vector. + * Parse argc/argv argument vector. */ int getopt_long_only(int nargc, char * const *nargv, const char *options, const struct option *long_options, int *idx) { - return (getopt_internal(nargc, nargv, options, long_options, idx, - FLAG_PERMUTE|FLAG_LONGONLY)); + return (getopt_internal(nargc, nargv, options, long_options, idx, + FLAG_PERMUTE|FLAG_LONGONLY)); } /******************************************************************************* * This file is part of the argtable3 library. @@ -2573,29 +2573,29 @@ struct arg_rem *arg_rem(const char *datatype, const char *glossary) #ifndef _TREX_H_ #define _TREX_H_ /*************************************************************** - T-Rex a tiny regular expression library + T-Rex a tiny regular expression library - Copyright (C) 2003-2006 Alberto Demichelis + Copyright (C) 2003-2006 Alberto Demichelis - This software is provided 'as-is', without any express - or implied warranty. In no event will the authors be held - liable for any damages arising from the use of this software. + This software is provided 'as-is', without any express + or implied warranty. In no event will the authors be held + liable for any damages arising from the use of this software. - Permission is granted to anyone to use this software for - any purpose, including commercial applications, and to alter - it and redistribute it freely, subject to the following restrictions: + Permission is granted to anyone to use this software for + any purpose, including commercial applications, and to alter + it and redistribute it freely, subject to the following restrictions: - 1. The origin of this software must not be misrepresented; - you must not claim that you wrote the original software. - If you use this software in a product, an acknowledgment - in the product documentation would be appreciated but - is not required. + 1. The origin of this software must not be misrepresented; + you must not claim that you wrote the original software. + If you use this software in a product, an acknowledgment + in the product documentation would be appreciated but + is not required. - 2. Altered source versions must be plainly marked as such, - and must not be misrepresented as being the original software. + 2. Altered source versions must be plainly marked as such, + and must not be misrepresented as being the original software. - 3. This notice may not be removed or altered from any - source distribution. + 3. This notice may not be removed or altered from any + source distribution. ****************************************************************/ @@ -2630,8 +2630,8 @@ typedef unsigned int TRexBool; typedef struct TRex TRex; typedef struct { - const TRexChar *begin; - int len; + const TRexChar *begin; + int len; } TRexMatch; TREX_API TRex *trex_compile(const TRexChar *pattern, const TRexChar **error, int flags); @@ -2899,26 +2899,26 @@ struct arg_rex * arg_rexn(const char * shortopts, static const TRexChar *g_nnames[] = { - _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"), - _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"), - _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"), - _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB") + _SC("NONE"),_SC("OP_GREEDY"), _SC("OP_OR"), + _SC("OP_EXPR"),_SC("OP_NOCAPEXPR"),_SC("OP_DOT"), _SC("OP_CLASS"), + _SC("OP_CCLASS"),_SC("OP_NCLASS"),_SC("OP_RANGE"),_SC("OP_CHAR"), + _SC("OP_EOL"),_SC("OP_BOL"),_SC("OP_WB") }; #endif -#define OP_GREEDY (MAX_CHAR+1) // * + ? {n} -#define OP_OR (MAX_CHAR+2) -#define OP_EXPR (MAX_CHAR+3) //parentesis () -#define OP_NOCAPEXPR (MAX_CHAR+4) //parentesis (?:) -#define OP_DOT (MAX_CHAR+5) -#define OP_CLASS (MAX_CHAR+6) -#define OP_CCLASS (MAX_CHAR+7) -#define OP_NCLASS (MAX_CHAR+8) //negates class the [^ -#define OP_RANGE (MAX_CHAR+9) -#define OP_CHAR (MAX_CHAR+10) -#define OP_EOL (MAX_CHAR+11) -#define OP_BOL (MAX_CHAR+12) -#define OP_WB (MAX_CHAR+13) +#define OP_GREEDY (MAX_CHAR+1) // * + ? {n} +#define OP_OR (MAX_CHAR+2) +#define OP_EXPR (MAX_CHAR+3) //parentesis () +#define OP_NOCAPEXPR (MAX_CHAR+4) //parentesis (?:) +#define OP_DOT (MAX_CHAR+5) +#define OP_CLASS (MAX_CHAR+6) +#define OP_CCLASS (MAX_CHAR+7) +#define OP_NCLASS (MAX_CHAR+8) //negates class the [^ +#define OP_RANGE (MAX_CHAR+9) +#define OP_CHAR (MAX_CHAR+10) +#define OP_EOL (MAX_CHAR+11) +#define OP_BOL (MAX_CHAR+12) +#define OP_WB (MAX_CHAR+13) #define TREX_SYMBOL_ANY_CHAR ('.') #define TREX_SYMBOL_GREEDY_ONE_OR_MORE ('+') @@ -2933,610 +2933,610 @@ static const TRexChar *g_nnames[] = typedef int TRexNodeType; typedef struct tagTRexNode{ - TRexNodeType type; - int left; - int right; - int next; + TRexNodeType type; + int left; + int right; + int next; }TRexNode; struct TRex{ - const TRexChar *_eol; - const TRexChar *_bol; - const TRexChar *_p; - int _first; - int _op; - TRexNode *_nodes; - int _nallocated; - int _nsize; - int _nsubexpr; - TRexMatch *_matches; - int _currsubexp; - void *_jmpbuf; - const TRexChar **_error; - int _flags; + const TRexChar *_eol; + const TRexChar *_bol; + const TRexChar *_p; + int _first; + int _op; + TRexNode *_nodes; + int _nallocated; + int _nsize; + int _nsubexpr; + TRexMatch *_matches; + int _currsubexp; + void *_jmpbuf; + const TRexChar **_error; + int _flags; }; static int trex_list(TRex *exp); static int trex_newnode(TRex *exp, TRexNodeType type) { - TRexNode n; - int newid; - n.type = type; - n.next = n.right = n.left = -1; - if(type == OP_EXPR) - n.right = exp->_nsubexpr++; - if(exp->_nallocated < (exp->_nsize + 1)) { - exp->_nallocated *= 2; - exp->_nodes = (TRexNode *)realloc(exp->_nodes, exp->_nallocated * sizeof(TRexNode)); - } - exp->_nodes[exp->_nsize++] = n; - newid = exp->_nsize - 1; - return (int)newid; + TRexNode n; + int newid; + n.type = type; + n.next = n.right = n.left = -1; + if(type == OP_EXPR) + n.right = exp->_nsubexpr++; + if(exp->_nallocated < (exp->_nsize + 1)) { + exp->_nallocated *= 2; + exp->_nodes = (TRexNode *)realloc(exp->_nodes, exp->_nallocated * sizeof(TRexNode)); + } + exp->_nodes[exp->_nsize++] = n; + newid = exp->_nsize - 1; + return (int)newid; } static void trex_error(TRex *exp,const TRexChar *error) { - if(exp->_error) *exp->_error = error; - longjmp(*((jmp_buf*)exp->_jmpbuf),-1); + if(exp->_error) *exp->_error = error; + longjmp(*((jmp_buf*)exp->_jmpbuf),-1); } static void trex_expect(TRex *exp, int n){ - if((*exp->_p) != n) - trex_error(exp, _SC("expected paren")); - exp->_p++; + if((*exp->_p) != n) + trex_error(exp, _SC("expected paren")); + exp->_p++; } static TRexChar trex_escapechar(TRex *exp) { - if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR){ - exp->_p++; - switch(*exp->_p) { - case 'v': exp->_p++; return '\v'; - case 'n': exp->_p++; return '\n'; - case 't': exp->_p++; return '\t'; - case 'r': exp->_p++; return '\r'; - case 'f': exp->_p++; return '\f'; - default: return (*exp->_p++); - } - } else if(!scisprint(*exp->_p)) trex_error(exp,_SC("letter expected")); - return (*exp->_p++); + if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR){ + exp->_p++; + switch(*exp->_p) { + case 'v': exp->_p++; return '\v'; + case 'n': exp->_p++; return '\n'; + case 't': exp->_p++; return '\t'; + case 'r': exp->_p++; return '\r'; + case 'f': exp->_p++; return '\f'; + default: return (*exp->_p++); + } + } else if(!scisprint(*exp->_p)) trex_error(exp,_SC("letter expected")); + return (*exp->_p++); } static int trex_charclass(TRex *exp,int classid) { - int n = trex_newnode(exp,OP_CCLASS); - exp->_nodes[n].left = classid; - return n; + int n = trex_newnode(exp,OP_CCLASS); + exp->_nodes[n].left = classid; + return n; } static int trex_charnode(TRex *exp,TRexBool isclass) { - TRexChar t; - if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) { - exp->_p++; - switch(*exp->_p) { - case 'n': exp->_p++; return trex_newnode(exp,'\n'); - case 't': exp->_p++; return trex_newnode(exp,'\t'); - case 'r': exp->_p++; return trex_newnode(exp,'\r'); - case 'f': exp->_p++; return trex_newnode(exp,'\f'); - case 'v': exp->_p++; return trex_newnode(exp,'\v'); - case 'a': case 'A': case 'w': case 'W': case 's': case 'S': - case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': - case 'p': case 'P': case 'l': case 'u': - { - t = *exp->_p; exp->_p++; - return trex_charclass(exp,t); - } - case 'b': - case 'B': - if(!isclass) { - int node = trex_newnode(exp,OP_WB); - exp->_nodes[node].left = *exp->_p; - exp->_p++; - return node; - } //else default - default: - t = *exp->_p; exp->_p++; - return trex_newnode(exp,t); - } - } - else if(!scisprint(*exp->_p)) { + TRexChar t; + if(*exp->_p == TREX_SYMBOL_ESCAPE_CHAR) { + exp->_p++; + switch(*exp->_p) { + case 'n': exp->_p++; return trex_newnode(exp,'\n'); + case 't': exp->_p++; return trex_newnode(exp,'\t'); + case 'r': exp->_p++; return trex_newnode(exp,'\r'); + case 'f': exp->_p++; return trex_newnode(exp,'\f'); + case 'v': exp->_p++; return trex_newnode(exp,'\v'); + case 'a': case 'A': case 'w': case 'W': case 's': case 'S': + case 'd': case 'D': case 'x': case 'X': case 'c': case 'C': + case 'p': case 'P': case 'l': case 'u': + { + t = *exp->_p; exp->_p++; + return trex_charclass(exp,t); + } + case 'b': + case 'B': + if(!isclass) { + int node = trex_newnode(exp,OP_WB); + exp->_nodes[node].left = *exp->_p; + exp->_p++; + return node; + } //else default + default: + t = *exp->_p; exp->_p++; + return trex_newnode(exp,t); + } + } + else if(!scisprint(*exp->_p)) { - trex_error(exp,_SC("letter expected")); - } - t = *exp->_p; exp->_p++; - return trex_newnode(exp,t); + trex_error(exp,_SC("letter expected")); + } + t = *exp->_p; exp->_p++; + return trex_newnode(exp,t); } static int trex_class(TRex *exp) { - int ret = -1; - int first = -1,chain; - if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING){ - ret = trex_newnode(exp,OP_NCLASS); - exp->_p++; - }else ret = trex_newnode(exp,OP_CLASS); + int ret = -1; + int first = -1,chain; + if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING){ + ret = trex_newnode(exp,OP_NCLASS); + exp->_p++; + }else ret = trex_newnode(exp,OP_CLASS); - if(*exp->_p == ']') trex_error(exp,_SC("empty class")); - chain = ret; - while(*exp->_p != ']' && exp->_p != exp->_eol) { - if(*exp->_p == '-' && first != -1){ - int r,t; - if(*exp->_p++ == ']') trex_error(exp,_SC("unfinished range")); - r = trex_newnode(exp,OP_RANGE); - if(first>*exp->_p) trex_error(exp,_SC("invalid range")); - if(exp->_nodes[first].type == OP_CCLASS) trex_error(exp,_SC("cannot use character classes in ranges")); - exp->_nodes[r].left = exp->_nodes[first].type; - t = trex_escapechar(exp); - exp->_nodes[r].right = t; + if(*exp->_p == ']') trex_error(exp,_SC("empty class")); + chain = ret; + while(*exp->_p != ']' && exp->_p != exp->_eol) { + if(*exp->_p == '-' && first != -1){ + int r,t; + if(*exp->_p++ == ']') trex_error(exp,_SC("unfinished range")); + r = trex_newnode(exp,OP_RANGE); + if(first>*exp->_p) trex_error(exp,_SC("invalid range")); + if(exp->_nodes[first].type == OP_CCLASS) trex_error(exp,_SC("cannot use character classes in ranges")); + exp->_nodes[r].left = exp->_nodes[first].type; + t = trex_escapechar(exp); + exp->_nodes[r].right = t; exp->_nodes[chain].next = r; - chain = r; - first = -1; - } - else{ - if(first!=-1){ - int c = first; - exp->_nodes[chain].next = c; - chain = c; - first = trex_charnode(exp,TRex_True); - } - else{ - first = trex_charnode(exp,TRex_True); - } - } - } - if(first!=-1){ - int c = first; - exp->_nodes[chain].next = c; - chain = c; - first = -1; - } - /* hack? */ - exp->_nodes[ret].left = exp->_nodes[ret].next; - exp->_nodes[ret].next = -1; - return ret; + chain = r; + first = -1; + } + else{ + if(first!=-1){ + int c = first; + exp->_nodes[chain].next = c; + chain = c; + first = trex_charnode(exp,TRex_True); + } + else{ + first = trex_charnode(exp,TRex_True); + } + } + } + if(first!=-1){ + int c = first; + exp->_nodes[chain].next = c; + chain = c; + first = -1; + } + /* hack? */ + exp->_nodes[ret].left = exp->_nodes[ret].next; + exp->_nodes[ret].next = -1; + return ret; } static int trex_parsenumber(TRex *exp) { - int ret = *exp->_p-'0'; - int positions = 10; - exp->_p++; - while(isdigit(*exp->_p)) { - ret = ret*10+(*exp->_p++-'0'); - if(positions==1000000000) trex_error(exp,_SC("overflow in numeric constant")); - positions *= 10; - }; - return ret; + int ret = *exp->_p-'0'; + int positions = 10; + exp->_p++; + while(isdigit(*exp->_p)) { + ret = ret*10+(*exp->_p++-'0'); + if(positions==1000000000) trex_error(exp,_SC("overflow in numeric constant")); + positions *= 10; + }; + return ret; } static int trex_element(TRex *exp) { - int ret = -1; - switch(*exp->_p) - { - case '(': { - int expr,newn; - exp->_p++; + int ret = -1; + switch(*exp->_p) + { + case '(': { + int expr,newn; + exp->_p++; - if(*exp->_p =='?') { - exp->_p++; - trex_expect(exp,':'); - expr = trex_newnode(exp,OP_NOCAPEXPR); - } - else - expr = trex_newnode(exp,OP_EXPR); - newn = trex_list(exp); - exp->_nodes[expr].left = newn; - ret = expr; - trex_expect(exp,')'); - } - break; - case '[': - exp->_p++; - ret = trex_class(exp); - trex_expect(exp,']'); - break; - case TREX_SYMBOL_END_OF_STRING: exp->_p++; ret = trex_newnode(exp,OP_EOL);break; - case TREX_SYMBOL_ANY_CHAR: exp->_p++; ret = trex_newnode(exp,OP_DOT);break; - default: - ret = trex_charnode(exp,TRex_False); - break; - } + if(*exp->_p =='?') { + exp->_p++; + trex_expect(exp,':'); + expr = trex_newnode(exp,OP_NOCAPEXPR); + } + else + expr = trex_newnode(exp,OP_EXPR); + newn = trex_list(exp); + exp->_nodes[expr].left = newn; + ret = expr; + trex_expect(exp,')'); + } + break; + case '[': + exp->_p++; + ret = trex_class(exp); + trex_expect(exp,']'); + break; + case TREX_SYMBOL_END_OF_STRING: exp->_p++; ret = trex_newnode(exp,OP_EOL);break; + case TREX_SYMBOL_ANY_CHAR: exp->_p++; ret = trex_newnode(exp,OP_DOT);break; + default: + ret = trex_charnode(exp,TRex_False); + break; + } - { - TRexBool isgreedy = TRex_False; - unsigned short p0 = 0, p1 = 0; - switch(*exp->_p){ - case TREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; - case TREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; - case TREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = TRex_True; break; - case '{': - exp->_p++; - if(!isdigit(*exp->_p)) trex_error(exp,_SC("number expected")); - p0 = (unsigned short)trex_parsenumber(exp); - /*******************************/ - switch(*exp->_p) { - case '}': - p1 = p0; exp->_p++; - break; - case ',': - exp->_p++; - p1 = 0xFFFF; - if(isdigit(*exp->_p)){ - p1 = (unsigned short)trex_parsenumber(exp); - } - trex_expect(exp,'}'); - break; - default: - trex_error(exp,_SC(", or } expected")); - } - /*******************************/ - isgreedy = TRex_True; - break; + { + TRexBool isgreedy = TRex_False; + unsigned short p0 = 0, p1 = 0; + switch(*exp->_p){ + case TREX_SYMBOL_GREEDY_ZERO_OR_MORE: p0 = 0; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; + case TREX_SYMBOL_GREEDY_ONE_OR_MORE: p0 = 1; p1 = 0xFFFF; exp->_p++; isgreedy = TRex_True; break; + case TREX_SYMBOL_GREEDY_ZERO_OR_ONE: p0 = 0; p1 = 1; exp->_p++; isgreedy = TRex_True; break; + case '{': + exp->_p++; + if(!isdigit(*exp->_p)) trex_error(exp,_SC("number expected")); + p0 = (unsigned short)trex_parsenumber(exp); + /*******************************/ + switch(*exp->_p) { + case '}': + p1 = p0; exp->_p++; + break; + case ',': + exp->_p++; + p1 = 0xFFFF; + if(isdigit(*exp->_p)){ + p1 = (unsigned short)trex_parsenumber(exp); + } + trex_expect(exp,'}'); + break; + default: + trex_error(exp,_SC(", or } expected")); + } + /*******************************/ + isgreedy = TRex_True; + break; - } - if(isgreedy) { - int nnode = trex_newnode(exp,OP_GREEDY); - exp->_nodes[nnode].left = ret; - exp->_nodes[nnode].right = ((p0)<<16)|p1; - ret = nnode; - } - } - if((*exp->_p != TREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != TREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != TREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) { - int nnode = trex_element(exp); - exp->_nodes[ret].next = nnode; - } + } + if(isgreedy) { + int nnode = trex_newnode(exp,OP_GREEDY); + exp->_nodes[nnode].left = ret; + exp->_nodes[nnode].right = ((p0)<<16)|p1; + ret = nnode; + } + } + if((*exp->_p != TREX_SYMBOL_BRANCH) && (*exp->_p != ')') && (*exp->_p != TREX_SYMBOL_GREEDY_ZERO_OR_MORE) && (*exp->_p != TREX_SYMBOL_GREEDY_ONE_OR_MORE) && (*exp->_p != '\0')) { + int nnode = trex_element(exp); + exp->_nodes[ret].next = nnode; + } - return ret; + return ret; } static int trex_list(TRex *exp) { - int ret=-1,e; - if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) { - exp->_p++; - ret = trex_newnode(exp,OP_BOL); - } - e = trex_element(exp); - if(ret != -1) { - exp->_nodes[ret].next = e; - } - else ret = e; + int ret=-1,e; + if(*exp->_p == TREX_SYMBOL_BEGINNING_OF_STRING) { + exp->_p++; + ret = trex_newnode(exp,OP_BOL); + } + e = trex_element(exp); + if(ret != -1) { + exp->_nodes[ret].next = e; + } + else ret = e; - if(*exp->_p == TREX_SYMBOL_BRANCH) { - int temp,tright; - exp->_p++; - temp = trex_newnode(exp,OP_OR); - exp->_nodes[temp].left = ret; - tright = trex_list(exp); - exp->_nodes[temp].right = tright; - ret = temp; - } - return ret; + if(*exp->_p == TREX_SYMBOL_BRANCH) { + int temp,tright; + exp->_p++; + temp = trex_newnode(exp,OP_OR); + exp->_nodes[temp].left = ret; + tright = trex_list(exp); + exp->_nodes[temp].right = tright; + ret = temp; + } + return ret; } static TRexBool trex_matchcclass(int cclass,TRexChar c) { - switch(cclass) { - case 'a': return isalpha(c)?TRex_True:TRex_False; - case 'A': return !isalpha(c)?TRex_True:TRex_False; - case 'w': return (isalnum(c) || c == '_')?TRex_True:TRex_False; - case 'W': return (!isalnum(c) && c != '_')?TRex_True:TRex_False; - case 's': return ISSPACE(c)?TRex_True:TRex_False; - case 'S': return !ISSPACE(c)?TRex_True:TRex_False; - case 'd': return isdigit(c)?TRex_True:TRex_False; - case 'D': return !isdigit(c)?TRex_True:TRex_False; - case 'x': return isxdigit(c)?TRex_True:TRex_False; - case 'X': return !isxdigit(c)?TRex_True:TRex_False; - case 'c': return iscntrl(c)?TRex_True:TRex_False; - case 'C': return !iscntrl(c)?TRex_True:TRex_False; - case 'p': return ispunct(c)?TRex_True:TRex_False; - case 'P': return !ispunct(c)?TRex_True:TRex_False; - case 'l': return islower(c)?TRex_True:TRex_False; - case 'u': return isupper(c)?TRex_True:TRex_False; - } - return TRex_False; /*cannot happen*/ + switch(cclass) { + case 'a': return isalpha(c)?TRex_True:TRex_False; + case 'A': return !isalpha(c)?TRex_True:TRex_False; + case 'w': return (isalnum(c) || c == '_')?TRex_True:TRex_False; + case 'W': return (!isalnum(c) && c != '_')?TRex_True:TRex_False; + case 's': return ISSPACE(c)?TRex_True:TRex_False; + case 'S': return !ISSPACE(c)?TRex_True:TRex_False; + case 'd': return isdigit(c)?TRex_True:TRex_False; + case 'D': return !isdigit(c)?TRex_True:TRex_False; + case 'x': return isxdigit(c)?TRex_True:TRex_False; + case 'X': return !isxdigit(c)?TRex_True:TRex_False; + case 'c': return iscntrl(c)?TRex_True:TRex_False; + case 'C': return !iscntrl(c)?TRex_True:TRex_False; + case 'p': return ispunct(c)?TRex_True:TRex_False; + case 'P': return !ispunct(c)?TRex_True:TRex_False; + case 'l': return islower(c)?TRex_True:TRex_False; + case 'u': return isupper(c)?TRex_True:TRex_False; + } + return TRex_False; /*cannot happen*/ } static TRexBool trex_matchclass(TRex* exp,TRexNode *node,TRexChar c) { - do { - switch(node->type) { - case OP_RANGE: - if (exp->_flags & TREX_ICASE) - { - if(c >= toupper(node->left) && c <= toupper(node->right)) return TRex_True; - if(c >= tolower(node->left) && c <= tolower(node->right)) return TRex_True; - } - else - { - if(c >= node->left && c <= node->right) return TRex_True; - } - break; - case OP_CCLASS: - if(trex_matchcclass(node->left,c)) return TRex_True; - break; - default: - if (exp->_flags & TREX_ICASE) - { - if (c == tolower(node->type) || c == toupper(node->type)) return TRex_True; - } - else - { - if(c == node->type)return TRex_True; - } + do { + switch(node->type) { + case OP_RANGE: + if (exp->_flags & TREX_ICASE) + { + if(c >= toupper(node->left) && c <= toupper(node->right)) return TRex_True; + if(c >= tolower(node->left) && c <= tolower(node->right)) return TRex_True; + } + else + { + if(c >= node->left && c <= node->right) return TRex_True; + } + break; + case OP_CCLASS: + if(trex_matchcclass(node->left,c)) return TRex_True; + break; + default: + if (exp->_flags & TREX_ICASE) + { + if (c == tolower(node->type) || c == toupper(node->type)) return TRex_True; + } + else + { + if(c == node->type)return TRex_True; + } - } - } while((node->next != -1) && (node = &exp->_nodes[node->next])); - return TRex_False; + } + } while((node->next != -1) && (node = &exp->_nodes[node->next])); + return TRex_False; } static const TRexChar *trex_matchnode(TRex* exp,TRexNode *node,const TRexChar *str,TRexNode *next) { - TRexNodeType type = node->type; - switch(type) { - case OP_GREEDY: { - //TRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; - TRexNode *greedystop = NULL; - int p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0; - const TRexChar *s=str, *good = str; + TRexNodeType type = node->type; + switch(type) { + case OP_GREEDY: { + //TRexNode *greedystop = (node->next != -1) ? &exp->_nodes[node->next] : NULL; + TRexNode *greedystop = NULL; + int p0 = (node->right >> 16)&0x0000FFFF, p1 = node->right&0x0000FFFF, nmaches = 0; + const TRexChar *s=str, *good = str; - if(node->next != -1) { - greedystop = &exp->_nodes[node->next]; - } - else { - greedystop = next; - } + if(node->next != -1) { + greedystop = &exp->_nodes[node->next]; + } + else { + greedystop = next; + } - while((nmaches == 0xFFFF || nmaches < p1)) { + while((nmaches == 0xFFFF || nmaches < p1)) { - const TRexChar *stop; - if(!(s = trex_matchnode(exp,&exp->_nodes[node->left],s,greedystop))) - break; - nmaches++; - good=s; - if(greedystop) { - //checks that 0 matches satisfy the expression(if so skips) - //if not would always stop(for instance if is a '?') - if(greedystop->type != OP_GREEDY || - (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0)) - { - TRexNode *gnext = NULL; - if(greedystop->next != -1) { - gnext = &exp->_nodes[greedystop->next]; - }else if(next && next->next != -1){ - gnext = &exp->_nodes[next->next]; - } - stop = trex_matchnode(exp,greedystop,s,gnext); - if(stop) { - //if satisfied stop it - if(p0 == p1 && p0 == nmaches) break; - else if(nmaches >= p0 && p1 == 0xFFFF) break; - else if(nmaches >= p0 && nmaches <= p1) break; - } - } - } + const TRexChar *stop; + if(!(s = trex_matchnode(exp,&exp->_nodes[node->left],s,greedystop))) + break; + nmaches++; + good=s; + if(greedystop) { + //checks that 0 matches satisfy the expression(if so skips) + //if not would always stop(for instance if is a '?') + if(greedystop->type != OP_GREEDY || + (greedystop->type == OP_GREEDY && ((greedystop->right >> 16)&0x0000FFFF) != 0)) + { + TRexNode *gnext = NULL; + if(greedystop->next != -1) { + gnext = &exp->_nodes[greedystop->next]; + }else if(next && next->next != -1){ + gnext = &exp->_nodes[next->next]; + } + stop = trex_matchnode(exp,greedystop,s,gnext); + if(stop) { + //if satisfied stop it + if(p0 == p1 && p0 == nmaches) break; + else if(nmaches >= p0 && p1 == 0xFFFF) break; + else if(nmaches >= p0 && nmaches <= p1) break; + } + } + } - if(s >= exp->_eol) - break; - } - if(p0 == p1 && p0 == nmaches) return good; - else if(nmaches >= p0 && p1 == 0xFFFF) return good; - else if(nmaches >= p0 && nmaches <= p1) return good; - return NULL; - } - case OP_OR: { - const TRexChar *asd = str; - TRexNode *temp=&exp->_nodes[node->left]; - while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) { - if(temp->next != -1) - temp = &exp->_nodes[temp->next]; - else - return asd; - } - asd = str; - temp = &exp->_nodes[node->right]; - while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) { - if(temp->next != -1) - temp = &exp->_nodes[temp->next]; - else - return asd; - } - return NULL; - break; - } - case OP_EXPR: - case OP_NOCAPEXPR:{ - TRexNode *n = &exp->_nodes[node->left]; - const TRexChar *cur = str; - int capture = -1; - if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) { - capture = exp->_currsubexp; - exp->_matches[capture].begin = cur; - exp->_currsubexp++; - } + if(s >= exp->_eol) + break; + } + if(p0 == p1 && p0 == nmaches) return good; + else if(nmaches >= p0 && p1 == 0xFFFF) return good; + else if(nmaches >= p0 && nmaches <= p1) return good; + return NULL; + } + case OP_OR: { + const TRexChar *asd = str; + TRexNode *temp=&exp->_nodes[node->left]; + while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) { + if(temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + asd = str; + temp = &exp->_nodes[node->right]; + while( (asd = trex_matchnode(exp,temp,asd,NULL)) ) { + if(temp->next != -1) + temp = &exp->_nodes[temp->next]; + else + return asd; + } + return NULL; + break; + } + case OP_EXPR: + case OP_NOCAPEXPR:{ + TRexNode *n = &exp->_nodes[node->left]; + const TRexChar *cur = str; + int capture = -1; + if(node->type != OP_NOCAPEXPR && node->right == exp->_currsubexp) { + capture = exp->_currsubexp; + exp->_matches[capture].begin = cur; + exp->_currsubexp++; + } - do { - TRexNode *subnext = NULL; - if(n->next != -1) { - subnext = &exp->_nodes[n->next]; - }else { - subnext = next; - } - if(!(cur = trex_matchnode(exp,n,cur,subnext))) { - if(capture != -1){ - exp->_matches[capture].begin = 0; - exp->_matches[capture].len = 0; - } - return NULL; - } - } while((n->next != -1) && (n = &exp->_nodes[n->next])); + do { + TRexNode *subnext = NULL; + if(n->next != -1) { + subnext = &exp->_nodes[n->next]; + }else { + subnext = next; + } + if(!(cur = trex_matchnode(exp,n,cur,subnext))) { + if(capture != -1){ + exp->_matches[capture].begin = 0; + exp->_matches[capture].len = 0; + } + return NULL; + } + } while((n->next != -1) && (n = &exp->_nodes[n->next])); - if(capture != -1) - exp->_matches[capture].len = (int)(cur - exp->_matches[capture].begin); - return cur; - } - case OP_WB: - if((str == exp->_bol && !ISSPACE(*str)) - || ((str == exp->_eol && !ISSPACE(*(str-1)))) - || ((!ISSPACE(*str) && ISSPACE(*(str+1)))) - || ((ISSPACE(*str) && !ISSPACE(*(str+1)))) ) { - return (node->left == 'b')?str:NULL; - } - return (node->left == 'b')?NULL:str; - case OP_BOL: - if(str == exp->_bol) return str; - return NULL; - case OP_EOL: - if(str == exp->_eol) return str; - return NULL; - case OP_DOT: - str++; - return str; - case OP_NCLASS: - case OP_CLASS: - if(trex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?TRex_True:TRex_False):(type == OP_NCLASS?TRex_True:TRex_False)) { + if(capture != -1) + exp->_matches[capture].len = (int)(cur - exp->_matches[capture].begin); + return cur; + } + case OP_WB: + if((str == exp->_bol && !ISSPACE(*str)) + || ((str == exp->_eol && !ISSPACE(*(str-1)))) + || ((!ISSPACE(*str) && ISSPACE(*(str+1)))) + || ((ISSPACE(*str) && !ISSPACE(*(str+1)))) ) { + return (node->left == 'b')?str:NULL; + } + return (node->left == 'b')?NULL:str; + case OP_BOL: + if(str == exp->_bol) return str; + return NULL; + case OP_EOL: + if(str == exp->_eol) return str; + return NULL; + case OP_DOT: + str++; + return str; + case OP_NCLASS: + case OP_CLASS: + if(trex_matchclass(exp,&exp->_nodes[node->left],*str)?(type == OP_CLASS?TRex_True:TRex_False):(type == OP_NCLASS?TRex_True:TRex_False)) { str++; - return str; - } - return NULL; - case OP_CCLASS: - if(trex_matchcclass(node->left,*str)) { + return str; + } + return NULL; + case OP_CCLASS: + if(trex_matchcclass(node->left,*str)) { str++; - return str; - } - return NULL; - default: /* char */ - if (exp->_flags & TREX_ICASE) - { - if(*str != tolower(node->type) && *str != toupper(node->type)) return NULL; - } - else - { - if (*str != node->type) return NULL; - } - str++; - return str; - } - return NULL; + return str; + } + return NULL; + default: /* char */ + if (exp->_flags & TREX_ICASE) + { + if(*str != tolower(node->type) && *str != toupper(node->type)) return NULL; + } + else + { + if (*str != node->type) return NULL; + } + str++; + return str; + } + return NULL; } /* public api */ TRex *trex_compile(const TRexChar *pattern,const TRexChar **error,int flags) { - TRex *exp = (TRex *)malloc(sizeof(TRex)); - exp->_eol = exp->_bol = NULL; - exp->_p = pattern; - exp->_nallocated = (int)scstrlen(pattern) * sizeof(TRexChar); - exp->_nodes = (TRexNode *)malloc(exp->_nallocated * sizeof(TRexNode)); - exp->_nsize = 0; - exp->_matches = 0; - exp->_nsubexpr = 0; - exp->_first = trex_newnode(exp,OP_EXPR); - exp->_error = error; - exp->_jmpbuf = malloc(sizeof(jmp_buf)); - exp->_flags = flags; - if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) { - int res = trex_list(exp); - exp->_nodes[exp->_first].left = res; - if(*exp->_p!='\0') - trex_error(exp,_SC("unexpected character")); + TRex *exp = (TRex *)malloc(sizeof(TRex)); + exp->_eol = exp->_bol = NULL; + exp->_p = pattern; + exp->_nallocated = (int)scstrlen(pattern) * sizeof(TRexChar); + exp->_nodes = (TRexNode *)malloc(exp->_nallocated * sizeof(TRexNode)); + exp->_nsize = 0; + exp->_matches = 0; + exp->_nsubexpr = 0; + exp->_first = trex_newnode(exp,OP_EXPR); + exp->_error = error; + exp->_jmpbuf = malloc(sizeof(jmp_buf)); + exp->_flags = flags; + if(setjmp(*((jmp_buf*)exp->_jmpbuf)) == 0) { + int res = trex_list(exp); + exp->_nodes[exp->_first].left = res; + if(*exp->_p!='\0') + trex_error(exp,_SC("unexpected character")); #ifdef _DEBUG - { - int nsize,i; - TRexNode *t; - nsize = exp->_nsize; - t = &exp->_nodes[0]; - scprintf(_SC("\n")); - for(i = 0;i < nsize; i++) { - if(exp->_nodes[i].type>MAX_CHAR) - scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]); - else - scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type); - scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next); - } - scprintf(_SC("\n")); - } + { + int nsize,i; + TRexNode *t; + nsize = exp->_nsize; + t = &exp->_nodes[0]; + scprintf(_SC("\n")); + for(i = 0;i < nsize; i++) { + if(exp->_nodes[i].type>MAX_CHAR) + scprintf(_SC("[%02d] %10s "),i,g_nnames[exp->_nodes[i].type-MAX_CHAR]); + else + scprintf(_SC("[%02d] %10c "),i,exp->_nodes[i].type); + scprintf(_SC("left %02d right %02d next %02d\n"),exp->_nodes[i].left,exp->_nodes[i].right,exp->_nodes[i].next); + } + scprintf(_SC("\n")); + } #endif - exp->_matches = (TRexMatch *) malloc(exp->_nsubexpr * sizeof(TRexMatch)); - memset(exp->_matches,0,exp->_nsubexpr * sizeof(TRexMatch)); - } - else{ - trex_free(exp); - return NULL; - } - return exp; + exp->_matches = (TRexMatch *) malloc(exp->_nsubexpr * sizeof(TRexMatch)); + memset(exp->_matches,0,exp->_nsubexpr * sizeof(TRexMatch)); + } + else{ + trex_free(exp); + return NULL; + } + return exp; } void trex_free(TRex *exp) { - if(exp) { - if(exp->_nodes) free(exp->_nodes); - if(exp->_jmpbuf) free(exp->_jmpbuf); - if(exp->_matches) free(exp->_matches); - free(exp); - } + if(exp) { + if(exp->_nodes) free(exp->_nodes); + if(exp->_jmpbuf) free(exp->_jmpbuf); + if(exp->_matches) free(exp->_matches); + free(exp); + } } TRexBool trex_match(TRex* exp,const TRexChar* text) { - const TRexChar* res = NULL; - exp->_bol = text; - exp->_eol = text + scstrlen(text); - exp->_currsubexp = 0; - res = trex_matchnode(exp,exp->_nodes,text,NULL); - if(res == NULL || res != exp->_eol) - return TRex_False; - return TRex_True; + const TRexChar* res = NULL; + exp->_bol = text; + exp->_eol = text + scstrlen(text); + exp->_currsubexp = 0; + res = trex_matchnode(exp,exp->_nodes,text,NULL); + if(res == NULL || res != exp->_eol) + return TRex_False; + return TRex_True; } TRexBool trex_searchrange(TRex* exp,const TRexChar* text_begin,const TRexChar* text_end,const TRexChar** out_begin, const TRexChar** out_end) { - const TRexChar *cur = NULL; - int node = exp->_first; - if(text_begin >= text_end) return TRex_False; - exp->_bol = text_begin; - exp->_eol = text_end; - do { - cur = text_begin; - while(node != -1) { - exp->_currsubexp = 0; - cur = trex_matchnode(exp,&exp->_nodes[node],cur,NULL); - if(!cur) - break; - node = exp->_nodes[node].next; - } - text_begin++; - } while(cur == NULL && text_begin != text_end); + const TRexChar *cur = NULL; + int node = exp->_first; + if(text_begin >= text_end) return TRex_False; + exp->_bol = text_begin; + exp->_eol = text_end; + do { + cur = text_begin; + while(node != -1) { + exp->_currsubexp = 0; + cur = trex_matchnode(exp,&exp->_nodes[node],cur,NULL); + if(!cur) + break; + node = exp->_nodes[node].next; + } + text_begin++; + } while(cur == NULL && text_begin != text_end); - if(cur == NULL) - return TRex_False; + if(cur == NULL) + return TRex_False; - --text_begin; + --text_begin; - if(out_begin) *out_begin = text_begin; - if(out_end) *out_end = cur; - return TRex_True; + if(out_begin) *out_begin = text_begin; + if(out_end) *out_end = cur; + return TRex_True; } TRexBool trex_search(TRex* exp,const TRexChar* text, const TRexChar** out_begin, const TRexChar** out_end) { - return trex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end); + return trex_searchrange(exp,text,text + scstrlen(text),out_begin,out_end); } int trex_getsubexpcount(TRex* exp) { - return exp->_nsubexpr; + return exp->_nsubexpr; } TRexBool trex_getsubexp(TRex* exp, int n, TRexMatch *subexp) { - if( n<0 || n >= exp->_nsubexpr) return TRex_False; - *subexp = exp->_matches[n]; - return TRex_True; + if( n<0 || n >= exp->_nsubexpr) return TRex_False; + *subexp = exp->_matches[n]; + return TRex_True; } /******************************************************************************* * This file is part of the argtable3 library. diff --git a/client/cliparser/cliparser.c b/client/cliparser/cliparser.c index f1f2e3b1e..e0c853d23 100644 --- a/client/cliparser/cliparser.c +++ b/client/cliparser/cliparser.c @@ -20,186 +20,186 @@ char *programHelp = NULL; char buf[500] = {0}; int CLIParserInit(char *vprogramName, char *vprogramHint, char *vprogramHelp) { - argtable = NULL; - argtableLen = 0; - programName = vprogramName; - programHint = vprogramHint; - programHelp = vprogramHelp; - memset(buf, 0x00, 500); + argtable = NULL; + argtableLen = 0; + programName = vprogramName; + programHint = vprogramHint; + programHelp = vprogramHelp; + memset(buf, 0x00, 500); - return 0; + return 0; } int CLIParserParseArg(int argc, char **argv, void* vargtable[], size_t vargtableLen, bool allowEmptyExec) { - int nerrors; + int nerrors; - argtable = vargtable; - argtableLen = vargtableLen; + argtable = vargtable; + argtableLen = vargtableLen; - /* verify the argtable[] entries were allocated sucessfully */ - if (arg_nullcheck(argtable) != 0) { - /* NULL entries were detected, some allocations must have failed */ - printf("ERROR: Insufficient memory\n"); - return 2; - } - /* Parse the command line as defined by argtable[] */ - nerrors = arg_parse(argc, argv, argtable); + /* verify the argtable[] entries were allocated sucessfully */ + if (arg_nullcheck(argtable) != 0) { + /* NULL entries were detected, some allocations must have failed */ + printf("ERROR: Insufficient memory\n"); + return 2; + } + /* Parse the command line as defined by argtable[] */ + nerrors = arg_parse(argc, argv, argtable); - /* special case: '--help' takes precedence over error reporting */ - if ((argc < 2 && !allowEmptyExec) ||((struct arg_lit *)argtable[0])->count > 0) { // help must be the first record - printf("Usage: %s", programName); - arg_print_syntaxv(stdout, argtable, "\n"); - if (programHint) - printf("%s\n\n", programHint); - arg_print_glossary(stdout, argtable, " %-20s %s\n"); - printf("\n"); - if (programHelp) - printf("%s \n", programHelp); + /* special case: '--help' takes precedence over error reporting */ + if ((argc < 2 && !allowEmptyExec) ||((struct arg_lit *)argtable[0])->count > 0) { // help must be the first record + printf("Usage: %s", programName); + arg_print_syntaxv(stdout, argtable, "\n"); + if (programHint) + printf("%s\n\n", programHint); + arg_print_glossary(stdout, argtable, " %-20s %s\n"); + printf("\n"); + if (programHelp) + printf("%s \n", programHelp); - return 1; - } + return 1; + } - /* If the parser returned any errors then display them and exit */ - if (nerrors > 0) { - /* Display the error details contained in the arg_end struct.*/ - arg_print_errors(stdout, ((struct arg_end *)argtable[vargtableLen - 1]), programName); - printf("Try '%s --help' for more information.\n", programName); + /* If the parser returned any errors then display them and exit */ + if (nerrors > 0) { + /* Display the error details contained in the arg_end struct.*/ + arg_print_errors(stdout, ((struct arg_end *)argtable[vargtableLen - 1]), programName); + printf("Try '%s --help' for more information.\n", programName); - return 3; - } + return 3; + } - return 0; + return 0; } enum ParserState { - PS_FIRST, - PS_ARGUMENT, - PS_OPTION, + PS_FIRST, + PS_ARGUMENT, + PS_OPTION, }; #define isSpace(c)(c == ' ' || c == '\t') int CLIParserParseString(const char* str, void* vargtable[], size_t vargtableLen, bool allowEmptyExec) { - return CLIParserParseStringEx(str, vargtable, vargtableLen, allowEmptyExec, false); + return CLIParserParseStringEx(str, vargtable, vargtableLen, allowEmptyExec, false); } int CLIParserParseStringEx(const char* str, void* vargtable[], size_t vargtableLen, bool allowEmptyExec, bool clueData) { - int argc = 0; - char *argv[200] = {NULL}; + int argc = 0; + char *argv[200] = {NULL}; - int len = strlen(str); - char *bufptr = buf; - char *spaceptr = NULL; - enum ParserState state = PS_FIRST; + int len = strlen(str); + char *bufptr = buf; + char *spaceptr = NULL; + enum ParserState state = PS_FIRST; - argv[argc++] = bufptr; - // param0 = program name - memcpy(buf, programName, strlen(programName) + 1); // with 0x00 - bufptr += strlen(programName) + 1; - if (len) - argv[argc++] = bufptr; + argv[argc++] = bufptr; + // param0 = program name + memcpy(buf, programName, strlen(programName) + 1); // with 0x00 + bufptr += strlen(programName) + 1; + if (len) + argv[argc++] = bufptr; - // parse params - for (int i = 0; i < len; i++) { - switch(state){ - case PS_FIRST: // first char - if (!clueData || str[i] == '-'){ // first char before space is '-' - next element - option OR not "clueData" for not-option fields - state = PS_OPTION; + // parse params + for (int i = 0; i < len; i++) { + switch(state){ + case PS_FIRST: // first char + if (!clueData || str[i] == '-'){ // first char before space is '-' - next element - option OR not "clueData" for not-option fields + state = PS_OPTION; - if (spaceptr) { - bufptr = spaceptr; - *bufptr = 0x00; - bufptr++; - argv[argc++] = bufptr; - } - } - spaceptr = NULL; - case PS_ARGUMENT: - if (state == PS_FIRST) - state = PS_ARGUMENT; - if (isSpace(str[i])) { - spaceptr = bufptr; - state = PS_FIRST; - } - *bufptr = str[i]; - bufptr++; - break; - case PS_OPTION: - if (isSpace(str[i])){ - state = PS_FIRST; + if (spaceptr) { + bufptr = spaceptr; + *bufptr = 0x00; + bufptr++; + argv[argc++] = bufptr; + } + } + spaceptr = NULL; + case PS_ARGUMENT: + if (state == PS_FIRST) + state = PS_ARGUMENT; + if (isSpace(str[i])) { + spaceptr = bufptr; + state = PS_FIRST; + } + *bufptr = str[i]; + bufptr++; + break; + case PS_OPTION: + if (isSpace(str[i])){ + state = PS_FIRST; - *bufptr = 0x00; - bufptr++; - argv[argc++] = bufptr; - break; - } + *bufptr = 0x00; + bufptr++; + argv[argc++] = bufptr; + break; + } - *bufptr = str[i]; - bufptr++; - break; - } - } + *bufptr = str[i]; + bufptr++; + break; + } + } - return CLIParserParseArg(argc, argv, vargtable, vargtableLen, allowEmptyExec); + return CLIParserParseArg(argc, argv, vargtable, vargtableLen, allowEmptyExec); } void CLIParserFree() { - arg_freetable(argtable, argtableLen); - argtable = NULL; + arg_freetable(argtable, argtableLen); + argtable = NULL; - return; + return; } // convertors int CLIParamHexToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) { - *datalen = 0; + *datalen = 0; - int ibuf = 0; - uint8_t buf[256] = {0}; - int res = CLIParamStrToBuf(argstr, buf, maxdatalen * 2, &ibuf); // *2 because here HEX - if (res || !ibuf) - return res; + int ibuf = 0; + uint8_t buf[256] = {0}; + int res = CLIParamStrToBuf(argstr, buf, maxdatalen * 2, &ibuf); // *2 because here HEX + if (res || !ibuf) + return res; - switch(param_gethex_to_eol((char *)buf, 0, data, maxdatalen, datalen)) { - case 1: - printf("Parameter error: Invalid HEX value.\n"); - return 1; - case 2: - printf("Parameter error: parameter too large.\n"); - return 2; - case 3: - printf("Parameter error: Hex string must have even number of digits.\n"); - return 3; - } + switch(param_gethex_to_eol((char *)buf, 0, data, maxdatalen, datalen)) { + case 1: + printf("Parameter error: Invalid HEX value.\n"); + return 1; + case 2: + printf("Parameter error: parameter too large.\n"); + return 2; + case 3: + printf("Parameter error: Hex string must have even number of digits.\n"); + return 3; + } - return 0; + return 0; } int CLIParamStrToBuf(struct arg_str *argstr, uint8_t *data, int maxdatalen, int *datalen) { - *datalen = 0; - if (!argstr->count) - return 0; + *datalen = 0; + if (!argstr->count) + return 0; - uint8_t buf[256] = {0}; - int ibuf = 0; + uint8_t buf[256] = {0}; + int ibuf = 0; - for (int i = 0; i < argstr->count; i++) { - int len = strlen(argstr->sval[i]); - memcpy(&buf[ibuf], argstr->sval[i], len); - ibuf += len; - } - buf[ibuf] = 0; + for (int i = 0; i < argstr->count; i++) { + int len = strlen(argstr->sval[i]); + memcpy(&buf[ibuf], argstr->sval[i], len); + ibuf += len; + } + buf[ibuf] = 0; - if (!ibuf) - return 0; + if (!ibuf) + return 0; - if (ibuf > maxdatalen) - return 2; + if (ibuf > maxdatalen) + return 2; - memcpy(data, buf, ibuf); - *datalen = ibuf; + memcpy(data, buf, ibuf); + *datalen = ibuf; - return 0; + return 0; } diff --git a/client/cliparser/getopt.h b/client/cliparser/getopt.h index 09ff126b4..c036ff686 100644 --- a/client/cliparser/getopt.h +++ b/client/cliparser/getopt.h @@ -1,5 +1,5 @@ -/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ -/* $FreeBSD$ */ +/* $NetBSD: getopt.h,v 1.4 2000/07/07 10:43:54 ad Exp $ */ +/* $FreeBSD$ */ /*- * SPDX-License-Identifier: BSD-2-Clause-NetBSD @@ -46,34 +46,34 @@ #define optional_argument 2 struct option { - /* name of long option */ - const char *name; - /* - * one of no_argument, required_argument, and optional_argument: - * whether option takes an argument - */ - int has_arg; - /* if not NULL, set *flag to val when option found */ - int *flag; - /* if flag not NULL, value to set *flag to; else return value */ - int val; + /* name of long option */ + const char *name; + /* + * one of no_argument, required_argument, and optional_argument: + * whether option takes an argument + */ + int has_arg; + /* if not NULL, set *flag to val when option found */ + int *flag; + /* if flag not NULL, value to set *flag to; else return value */ + int val; }; __BEGIN_DECLS -int getopt_long(int, char * const *, const char *, - const struct option *, int *); -int getopt_long_only(int, char * const *, const char *, - const struct option *, int *); +int getopt_long(int, char * const *, const char *, + const struct option *, int *); +int getopt_long_only(int, char * const *, const char *, + const struct option *, int *); #ifndef _GETOPT_DECLARED -#define _GETOPT_DECLARED -int getopt(int, char * const [], const char *); +#define _GETOPT_DECLARED +int getopt(int, char * const [], const char *); -extern char *optarg; /* getopt(3) external variables */ +extern char *optarg; /* getopt(3) external variables */ extern int optind, opterr, optopt; #endif #ifndef _OPTRESET_DECLARED -#define _OPTRESET_DECLARED -extern int optreset; /* getopt(3) external variable */ +#define _OPTRESET_DECLARED +extern int optreset; /* getopt(3) external variable */ #endif __END_DECLS diff --git a/client/cmdanalyse.c b/client/cmdanalyse.c index 94411f8b5..c0e455fe2 100644 --- a/client/cmdanalyse.c +++ b/client/cmdanalyse.c @@ -12,70 +12,70 @@ static int CmdHelp(const char *Cmd); int usage_analyse_lcr(void) { - PrintAndLogEx(NORMAL, "Specifying the bytes of a UID with a known LRC will find the last byte value"); - PrintAndLogEx(NORMAL, "needed to generate that LRC with a rolling XOR. All bytes should be specified in HEX."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: analyse lcr [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " bytes to calc missing XOR in a LCR"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " analyse lcr 04008064BA"); - PrintAndLogEx(NORMAL, "expected output: Target (BA) requires final LRC XOR byte value: 5A"); - return 0; + PrintAndLogEx(NORMAL, "Specifying the bytes of a UID with a known LRC will find the last byte value"); + PrintAndLogEx(NORMAL, "needed to generate that LRC with a rolling XOR. All bytes should be specified in HEX."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: analyse lcr [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " bytes to calc missing XOR in a LCR"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " analyse lcr 04008064BA"); + PrintAndLogEx(NORMAL, "expected output: Target (BA) requires final LRC XOR byte value: 5A"); + return 0; } int usage_analyse_checksum(void) { - PrintAndLogEx(NORMAL, "The bytes will be added with eachother and than limited with the applied mask"); - PrintAndLogEx(NORMAL, "Finally compute ones' complement of the least significant bytes"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: analyse chksum [h] [v] b m "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " v supress header"); - PrintAndLogEx(NORMAL, " b bytes to calc missing XOR in a LCR"); - PrintAndLogEx(NORMAL, " m bit mask to limit the outpuyt"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " analyse chksum b 137AF00A0A0D m FF"); - PrintAndLogEx(NORMAL, "expected output: 0x61"); - return 0; + PrintAndLogEx(NORMAL, "The bytes will be added with eachother and than limited with the applied mask"); + PrintAndLogEx(NORMAL, "Finally compute ones' complement of the least significant bytes"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: analyse chksum [h] [v] b m "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " v supress header"); + PrintAndLogEx(NORMAL, " b bytes to calc missing XOR in a LCR"); + PrintAndLogEx(NORMAL, " m bit mask to limit the outpuyt"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " analyse chksum b 137AF00A0A0D m FF"); + PrintAndLogEx(NORMAL, "expected output: 0x61"); + return 0; } int usage_analyse_crc(void){ - PrintAndLogEx(NORMAL, "A stub method to test different crc implementations inside the PM3 sourcecode. Just because you figured out the poly, doesn't mean you get the desired output"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: analyse crc [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " bytes to calc crc"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " analyse crc 137AF00A0A0D"); - return 0; + PrintAndLogEx(NORMAL, "A stub method to test different crc implementations inside the PM3 sourcecode. Just because you figured out the poly, doesn't mean you get the desired output"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: analyse crc [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " bytes to calc crc"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " analyse crc 137AF00A0A0D"); + return 0; } int usage_analyse_nuid(void){ - PrintAndLogEx(NORMAL, "Generate 4byte NUID from 7byte UID"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: analyse hid [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " input bytes (14 hexsymbols)"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " analyse nuid 11223344556677"); - return 0; + PrintAndLogEx(NORMAL, "Generate 4byte NUID from 7byte UID"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: analyse hid [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " input bytes (14 hexsymbols)"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " analyse nuid 11223344556677"); + return 0; } int usage_analyse_a(void) { - PrintAndLogEx(NORMAL, "Iceman's personal garbage test command"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Usage: analyse a [h] d "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " d bytes to send to device"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " analyse a d 137AF00A0A0D"); - return 0; + PrintAndLogEx(NORMAL, "Iceman's personal garbage test command"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Usage: analyse a [h] d "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " d bytes to send to device"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " analyse a d 137AF00A0A0D"); + return 0; } static uint8_t calculateLRC( uint8_t* bytes, uint8_t len) { @@ -94,129 +94,129 @@ static uint16_t matrixadd ( uint8_t* bytes, uint8_t len){ ----------------- C32F 9d74 - return 0; + return 0; } */ /* static uint16_t shiftadd ( uint8_t* bytes, uint8_t len){ - return 0; + return 0; } */ static uint16_t calcSumCrumbAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { uint16_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum += CRUMB(bytes[i], 0); - sum += CRUMB(bytes[i], 2); - sum += CRUMB(bytes[i], 4); - sum += CRUMB(bytes[i], 6); - } - sum &= mask; + sum += CRUMB(bytes[i], 2); + sum += CRUMB(bytes[i], 4); + sum += CRUMB(bytes[i], 6); + } + sum &= mask; return sum; } static uint16_t calcSumCrumbAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask) { - return (~calcSumCrumbAdd(bytes, len, mask) & mask); + return (~calcSumCrumbAdd(bytes, len, mask) & mask); } static uint16_t calcSumNibbleAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { uint16_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum += NIBBLE_LOW(bytes[i]); - sum += NIBBLE_HIGH(bytes[i]); - } - sum &= mask; + sum += NIBBLE_HIGH(bytes[i]); + } + sum &= mask; return sum; } static uint16_t calcSumNibbleAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask){ - return (~calcSumNibbleAdd(bytes, len, mask) & mask); + return (~calcSumNibbleAdd(bytes, len, mask) & mask); } static uint16_t calcSumCrumbXor( uint8_t* bytes, uint8_t len, uint32_t mask) { uint16_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum ^= CRUMB(bytes[i], 0); - sum ^= CRUMB(bytes[i], 2); - sum ^= CRUMB(bytes[i], 4); - sum ^= CRUMB(bytes[i], 6); - } - sum &= mask; + sum ^= CRUMB(bytes[i], 2); + sum ^= CRUMB(bytes[i], 4); + sum ^= CRUMB(bytes[i], 6); + } + sum &= mask; return sum; } static uint16_t calcSumNibbleXor( uint8_t* bytes, uint8_t len, uint32_t mask) { uint16_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum ^= NIBBLE_LOW(bytes[i]); - sum ^= NIBBLE_HIGH(bytes[i]); - } - sum &= mask; + sum ^= NIBBLE_HIGH(bytes[i]); + } + sum &= mask; return sum; } static uint16_t calcSumByteXor( uint8_t* bytes, uint8_t len, uint32_t mask) { uint16_t sum = 0; for (uint8_t i = 0; i < len; i++) { - sum ^= bytes[i]; - } - sum &= mask; + sum ^= bytes[i]; + } + sum &= mask; return sum; } static uint16_t calcSumByteAdd( uint8_t* bytes, uint8_t len, uint32_t mask) { uint16_t sum = 0; for (uint8_t i = 0; i < len; i++) { - sum += bytes[i]; - } - sum &= mask; + sum += bytes[i]; + } + sum &= mask; return sum; } // Ones complement static uint16_t calcSumByteAddOnes( uint8_t* bytes, uint8_t len, uint32_t mask) { - return (~calcSumByteAdd(bytes, len, mask) & mask); + return (~calcSumByteAdd(bytes, len, mask) & mask); } static uint16_t calcSumByteSub( uint8_t* bytes, uint8_t len, uint32_t mask) { uint8_t sum = 0; for (uint8_t i = 0; i < len; i++) { - sum -= bytes[i]; - } - sum &= mask; + sum -= bytes[i]; + } + sum &= mask; return sum; } static uint16_t calcSumByteSubOnes( uint8_t* bytes, uint8_t len, uint32_t mask){ - return (~calcSumByteSub(bytes, len, mask) & mask); + return (~calcSumByteSub(bytes, len, mask) & mask); } static uint16_t calcSumNibbleSub( uint8_t* bytes, uint8_t len, uint32_t mask) { uint8_t sum = 0; for (uint8_t i = 0; i < len; i++) { sum -= NIBBLE_LOW(bytes[i]); - sum -= NIBBLE_HIGH(bytes[i]); - } - sum &= mask; + sum -= NIBBLE_HIGH(bytes[i]); + } + sum &= mask; return sum; } static uint16_t calcSumNibbleSubOnes( uint8_t* bytes, uint8_t len, uint32_t mask) { - return (~calcSumNibbleSub(bytes, len, mask) & mask); + return (~calcSumNibbleSub(bytes, len, mask) & mask); } // BSD shift checksum 8bit version static uint16_t calcBSDchecksum8( uint8_t* bytes, uint8_t len, uint32_t mask){ - uint16_t sum = 0; - for(uint8_t i = 0; i < len; i++){ - sum = ((sum & 0xFF) >> 1) | ((sum & 0x1) << 7); // rotate accumulator - sum += bytes[i]; // add next byte - sum &= 0xFF; // - } - sum &= mask; - return sum; + uint16_t sum = 0; + for(uint8_t i = 0; i < len; i++){ + sum = ((sum & 0xFF) >> 1) | ((sum & 0x1) << 7); // rotate accumulator + sum += bytes[i]; // add next byte + sum &= 0xFF; // + } + sum &= mask; + return sum; } // BSD shift checksum 4bit version static uint16_t calcBSDchecksum4( uint8_t* bytes, uint8_t len, uint32_t mask){ - uint16_t sum = 0; - for(uint8_t i = 0; i < len; i++){ - sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator - sum += NIBBLE_HIGH(bytes[i]); // add high nibble - sum &= 0xF; // - sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator - sum += NIBBLE_LOW(bytes[i]); // add low nibble - sum &= 0xF; // - } - sum &= mask; - return sum; + uint16_t sum = 0; + for(uint8_t i = 0; i < len; i++){ + sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator + sum += NIBBLE_HIGH(bytes[i]); // add high nibble + sum &= 0xF; // + sum = ((sum & 0xF) >> 1) | ((sum & 0x1) << 3); // rotate accumulator + sum += NIBBLE_LOW(bytes[i]); // add low nibble + sum &= 0xF; // + } + sum &= mask; + return sum; } // measuring LFSR maximum length @@ -226,334 +226,334 @@ int CmdAnalyseLfsr(const char *Cmd){ uint16_t lfsr = start_state; //uint32_t period = 0; - uint8_t iv = param_get8ex(Cmd, 0, 0, 16); - uint8_t find = param_get8ex(Cmd, 1, 0, 16); + uint8_t iv = param_get8ex(Cmd, 0, 0, 16); + uint8_t find = param_get8ex(Cmd, 1, 0, 16); - PrintAndLogEx(NORMAL, "LEGIC LFSR IV 0x%02X: \n", iv); - PrintAndLogEx(NORMAL, " bit# | lfsr | ^0x40 | 0x%02X ^ lfsr \n",find); + PrintAndLogEx(NORMAL, "LEGIC LFSR IV 0x%02X: \n", iv); + PrintAndLogEx(NORMAL, " bit# | lfsr | ^0x40 | 0x%02X ^ lfsr \n",find); - for (uint8_t i = 0x01; i < 0x30; i += 1) { - //period = 0; - legic_prng_init(iv); - legic_prng_forward(i); - lfsr = legic_prng_get_bits(12); + for (uint8_t i = 0x01; i < 0x30; i += 1) { + //period = 0; + legic_prng_init(iv); + legic_prng_forward(i); + lfsr = legic_prng_get_bits(12); - PrintAndLogEx(NORMAL, " %02X | %03X | %03X | %03X \n",i, lfsr, 0x40 ^ lfsr, find ^ lfsr); - } - return 0; + PrintAndLogEx(NORMAL, " %02X | %03X | %03X | %03X \n",i, lfsr, 0x40 ^ lfsr, find ^ lfsr); + } + return 0; } int CmdAnalyseLCR(const char *Cmd) { - uint8_t data[50]; - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) == 0|| cmdp == 'h') return usage_analyse_lcr(); + uint8_t data[50]; + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0|| cmdp == 'h') return usage_analyse_lcr(); - int len = 0; - switch (param_gethex_to_eol(Cmd, 0, data, sizeof(data), &len)) { - case 1: - PrintAndLogEx(WARNING, "Invalid HEX value."); - return 1; - case 2: - PrintAndLogEx(WARNING, "Too many bytes. Max %d bytes", sizeof(data)); - return 1; - case 3: - PrintAndLogEx(WARNING, "Hex must have even number of digits."); - return 1; - } - uint8_t finalXor = calculateLRC(data, len); - PrintAndLogEx(NORMAL, "Target [%02X] requires final LRC XOR byte value: 0x%02X",data[len-1] ,finalXor); - return 0; + int len = 0; + switch (param_gethex_to_eol(Cmd, 0, data, sizeof(data), &len)) { + case 1: + PrintAndLogEx(WARNING, "Invalid HEX value."); + return 1; + case 2: + PrintAndLogEx(WARNING, "Too many bytes. Max %d bytes", sizeof(data)); + return 1; + case 3: + PrintAndLogEx(WARNING, "Hex must have even number of digits."); + return 1; + } + uint8_t finalXor = calculateLRC(data, len); + PrintAndLogEx(NORMAL, "Target [%02X] requires final LRC XOR byte value: 0x%02X",data[len-1] ,finalXor); + return 0; } int CmdAnalyseCRC(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) == 0 || cmdp == 'h') return usage_analyse_crc(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0 || cmdp == 'h') return usage_analyse_crc(); - int len = strlen(Cmd); - if ( len & 1 ) return usage_analyse_crc(); + int len = strlen(Cmd); + if ( len & 1 ) return usage_analyse_crc(); - // add 1 for null terminator. - uint8_t *data = calloc(len+1, sizeof(uint8_t)); - if ( !data ) return 1; + // add 1 for null terminator. + uint8_t *data = calloc(len+1, sizeof(uint8_t)); + if ( !data ) return 1; - if ( param_gethex(Cmd, 0, data, len)) { - free(data); - return usage_analyse_crc(); - } - len >>= 1; + if ( param_gethex(Cmd, 0, data, len)) { + free(data); + return usage_analyse_crc(); + } + len >>= 1; - PrintAndLogEx(NORMAL, "\nTests with (%d) | %s",len, sprint_hex(data, len)); + PrintAndLogEx(NORMAL, "\nTests with (%d) | %s",len, sprint_hex(data, len)); - // 51 f5 7a d6 - uint8_t uid[] = {0x51, 0xf5, 0x7a, 0xd6}; //12 34 56 - init_table(CRC_LEGIC); - uint8_t legic8 = CRC8Legic(uid, sizeof(uid)); - PrintAndLogEx(NORMAL, "Legic 16 | %X (EF6F expected) [legic8 = %02x]", crc16_legic(data, len, legic8), legic8); - init_table(CRC_FELICA); - PrintAndLogEx(NORMAL, "FeliCa | %X ", crc16_xmodem(data, len)); + // 51 f5 7a d6 + uint8_t uid[] = {0x51, 0xf5, 0x7a, 0xd6}; //12 34 56 + init_table(CRC_LEGIC); + uint8_t legic8 = CRC8Legic(uid, sizeof(uid)); + PrintAndLogEx(NORMAL, "Legic 16 | %X (EF6F expected) [legic8 = %02x]", crc16_legic(data, len, legic8), legic8); + init_table(CRC_FELICA); + PrintAndLogEx(NORMAL, "FeliCa | %X ", crc16_xmodem(data, len)); - PrintAndLogEx(NORMAL, "\nTests of reflection. Current methods in source code"); - PrintAndLogEx(NORMAL, " reflect(0x3e23L,3) is %04X == 0x3e26", reflect(0x3e23L,3) ); - PrintAndLogEx(NORMAL, " reflect8(0x80) is %02X == 0x01", reflect8(0x80)); - PrintAndLogEx(NORMAL, " reflect16(0x8000) is %04X == 0x0001", reflect16(0xc6c6)); + PrintAndLogEx(NORMAL, "\nTests of reflection. Current methods in source code"); + PrintAndLogEx(NORMAL, " reflect(0x3e23L,3) is %04X == 0x3e26", reflect(0x3e23L,3) ); + PrintAndLogEx(NORMAL, " reflect8(0x80) is %02X == 0x01", reflect8(0x80)); + PrintAndLogEx(NORMAL, " reflect16(0x8000) is %04X == 0x0001", reflect16(0xc6c6)); - uint8_t b1, b2; - // ISO14443 crc B - compute_crc(CRC_14443_B, data, len, &b1, &b2); - uint16_t crcBB_1 = b1 << 8 | b2; - uint16_t bbb = crc(CRC_14443_B, data, len); - PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x == %04x \n", crcBB_1, bbb ); + uint8_t b1, b2; + // ISO14443 crc B + compute_crc(CRC_14443_B, data, len, &b1, &b2); + uint16_t crcBB_1 = b1 << 8 | b2; + uint16_t bbb = crc(CRC_14443_B, data, len); + PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x == %04x \n", crcBB_1, bbb ); - // Test of CRC16, '123456789' string. - // + // Test of CRC16, '123456789' string. + // - PrintAndLogEx(NORMAL, "\n\nStandard test with 31 32 33 34 35 36 37 38 39 '123456789'\n\n"); - uint8_t dataStr[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39 }; - legic8 = CRC8Legic(dataStr, sizeof(dataStr)); + PrintAndLogEx(NORMAL, "\n\nStandard test with 31 32 33 34 35 36 37 38 39 '123456789'\n\n"); + uint8_t dataStr[] = { 0x31,0x32,0x33,0x34,0x35,0x36,0x37,0x38,0x39 }; + legic8 = CRC8Legic(dataStr, sizeof(dataStr)); - //these below has been tested OK. - PrintAndLogEx(NORMAL, "Confirmed CRC Implementations"); - PrintAndLogEx(NORMAL, "-------------------------------------\n"); - PrintAndLogEx(NORMAL, "CRC 8 based\n\n"); - PrintAndLogEx(NORMAL, "LEGIC: CRC8 : %X (C6 expected)", legic8); - PrintAndLogEx(NORMAL, "MAXIM: CRC8 : %X (A1 expected)", CRC8Maxim(dataStr, sizeof(dataStr))); - PrintAndLogEx(NORMAL, "-------------------------------------\n"); - PrintAndLogEx(NORMAL, "CRC16 based\n\n"); + //these below has been tested OK. + PrintAndLogEx(NORMAL, "Confirmed CRC Implementations"); + PrintAndLogEx(NORMAL, "-------------------------------------\n"); + PrintAndLogEx(NORMAL, "CRC 8 based\n\n"); + PrintAndLogEx(NORMAL, "LEGIC: CRC8 : %X (C6 expected)", legic8); + PrintAndLogEx(NORMAL, "MAXIM: CRC8 : %X (A1 expected)", CRC8Maxim(dataStr, sizeof(dataStr))); + PrintAndLogEx(NORMAL, "-------------------------------------\n"); + PrintAndLogEx(NORMAL, "CRC16 based\n\n"); - // input from commandline - PrintAndLogEx(NORMAL, "CCITT | %X (29B1 expected)", crc(CRC_CCITT, dataStr, sizeof(dataStr))); + // input from commandline + PrintAndLogEx(NORMAL, "CCITT | %X (29B1 expected)", crc(CRC_CCITT, dataStr, sizeof(dataStr))); - uint8_t poll[] = {0xb2,0x4d,0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; - PrintAndLogEx(NORMAL, "FeliCa | %04X (B37F expected)", crc(CRC_FELICA, poll+2, sizeof(poll)-4)); - PrintAndLogEx(NORMAL, "FeliCa | %04X (0000 expected)", crc(CRC_FELICA, poll+2, sizeof(poll)-2)); + uint8_t poll[] = {0xb2,0x4d,0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; + PrintAndLogEx(NORMAL, "FeliCa | %04X (B37F expected)", crc(CRC_FELICA, poll+2, sizeof(poll)-4)); + PrintAndLogEx(NORMAL, "FeliCa | %04X (0000 expected)", crc(CRC_FELICA, poll+2, sizeof(poll)-2)); - uint8_t sel_corr[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01}; - PrintAndLogEx(NORMAL, "iCLASS | %04x (0143 expected)", crc(CRC_ICLASS, sel_corr, sizeof(sel_corr)-2)); - PrintAndLogEx(NORMAL, "---------------------------------------------------------------\n\n\n"); + uint8_t sel_corr[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01}; + PrintAndLogEx(NORMAL, "iCLASS | %04x (0143 expected)", crc(CRC_ICLASS, sel_corr, sizeof(sel_corr)-2)); + PrintAndLogEx(NORMAL, "---------------------------------------------------------------\n\n\n"); - // ISO14443 crc A - compute_crc(CRC_14443_A, dataStr, sizeof(dataStr), &b1, &b2); - uint16_t crcAA = b1 << 8 | b2; - PrintAndLogEx(NORMAL, "ISO14443 crc A | %04x or %04x (BF05 expected)\n", crcAA, crc(CRC_14443_A, dataStr, sizeof(dataStr)) ); + // ISO14443 crc A + compute_crc(CRC_14443_A, dataStr, sizeof(dataStr), &b1, &b2); + uint16_t crcAA = b1 << 8 | b2; + PrintAndLogEx(NORMAL, "ISO14443 crc A | %04x or %04x (BF05 expected)\n", crcAA, crc(CRC_14443_A, dataStr, sizeof(dataStr)) ); - // ISO14443 crc B - compute_crc(CRC_14443_B, dataStr, sizeof(dataStr), &b1, &b2); - uint16_t crcBB = b1 << 8 | b2; - PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x or %04x (906E expected)\n", crcBB, crc(CRC_14443_B, dataStr, sizeof(dataStr)) ); + // ISO14443 crc B + compute_crc(CRC_14443_B, dataStr, sizeof(dataStr), &b1, &b2); + uint16_t crcBB = b1 << 8 | b2; + PrintAndLogEx(NORMAL, "ISO14443 crc B | %04x or %04x (906E expected)\n", crcBB, crc(CRC_14443_B, dataStr, sizeof(dataStr)) ); - // ISO15693 crc (x.25) - compute_crc(CRC_15693, dataStr, sizeof(dataStr), &b1, &b2); - uint16_t crcCC = b1 << 8 | b2; - PrintAndLogEx(NORMAL, "ISO15693 crc X25| %04x or %04x (906E expected)\n", crcCC, crc(CRC_15693, dataStr, sizeof(dataStr)) ); + // ISO15693 crc (x.25) + compute_crc(CRC_15693, dataStr, sizeof(dataStr), &b1, &b2); + uint16_t crcCC = b1 << 8 | b2; + PrintAndLogEx(NORMAL, "ISO15693 crc X25| %04x or %04x (906E expected)\n", crcCC, crc(CRC_15693, dataStr, sizeof(dataStr)) ); - // ICLASS - compute_crc(CRC_ICLASS, dataStr, sizeof(dataStr), &b1, &b2); - uint16_t crcDD = b1 << 8 | b2; - PrintAndLogEx(NORMAL, "ICLASS crc | %04x or %04x\n", crcDD, crc(CRC_ICLASS, dataStr, sizeof(dataStr)) ); + // ICLASS + compute_crc(CRC_ICLASS, dataStr, sizeof(dataStr), &b1, &b2); + uint16_t crcDD = b1 << 8 | b2; + PrintAndLogEx(NORMAL, "ICLASS crc | %04x or %04x\n", crcDD, crc(CRC_ICLASS, dataStr, sizeof(dataStr)) ); - // FeliCa - compute_crc(CRC_FELICA, dataStr, sizeof(dataStr), &b1, &b2); - uint16_t crcEE = b1 << 8 | b2; - PrintAndLogEx(NORMAL, "FeliCa | %04x or %04x (31C3 expected)\n", crcEE, crc(CRC_FELICA, dataStr, sizeof(dataStr))); + // FeliCa + compute_crc(CRC_FELICA, dataStr, sizeof(dataStr), &b1, &b2); + uint16_t crcEE = b1 << 8 | b2; + PrintAndLogEx(NORMAL, "FeliCa | %04x or %04x (31C3 expected)\n", crcEE, crc(CRC_FELICA, dataStr, sizeof(dataStr))); - free(data); - return 0; + free(data); + return 0; } int CmdAnalyseCHKSUM(const char *Cmd){ - uint8_t data[50]; - uint8_t cmdp = 0; - uint32_t mask = 0xFFFF; - bool errors = false; - bool useHeader = false; - int len = 0; - memset(data, 0x0, sizeof(data)); + uint8_t data[50]; + uint8_t cmdp = 0; + uint32_t mask = 0xFFFF; + bool errors = false; + bool useHeader = false; + int len = 0; + memset(data, 0x0, sizeof(data)); - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { - case 'b': - case 'B': - param_gethex_ex(Cmd, cmdp+1, data, &len); - if ( len%2 ) errors = true; - len >>= 1; - cmdp += 2; - break; - case 'm': - case 'M': - mask = param_get32ex(Cmd, cmdp+1, 0, 16); - cmdp += 2; - break; - case 'v': - case 'V': - useHeader = true; - cmdp++; - break; - case 'h': - case 'H': - return usage_analyse_checksum(); - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors || cmdp == 0 ) return usage_analyse_checksum(); + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch(param_getchar(Cmd, cmdp)) { + case 'b': + case 'B': + param_gethex_ex(Cmd, cmdp+1, data, &len); + if ( len%2 ) errors = true; + len >>= 1; + cmdp += 2; + break; + case 'm': + case 'M': + mask = param_get32ex(Cmd, cmdp+1, 0, 16); + cmdp += 2; + break; + case 'v': + case 'V': + useHeader = true; + cmdp++; + break; + case 'h': + case 'H': + return usage_analyse_checksum(); + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + //Validations + if (errors || cmdp == 0 ) return usage_analyse_checksum(); - if (useHeader) { - PrintAndLogEx(NORMAL, " add | sub | add 1's compl | sub 1's compl | xor"); - PrintAndLogEx(NORMAL, "byte nibble crumb | byte nibble | byte nibble cumb | byte nibble | byte nibble cumb | BSD |"); - PrintAndLogEx(NORMAL, "------------------+-------------+------------------+-----------------+--------------------"); - } - PrintAndLogEx(NORMAL, "0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X |\n", - calcSumByteAdd(data, len, mask) - , calcSumNibbleAdd(data, len, mask) - , calcSumCrumbAdd(data, len, mask) - , calcSumByteSub(data, len, mask) - , calcSumNibbleSub(data, len, mask) - , calcSumByteAddOnes(data, len, mask) - , calcSumNibbleAddOnes(data, len, mask) - , calcSumCrumbAddOnes(data, len, mask) - , calcSumByteSubOnes(data, len, mask) - , calcSumNibbleSubOnes(data, len, mask) - , calcSumByteXor(data, len, mask) - , calcSumNibbleXor(data, len, mask) - , calcSumCrumbXor(data, len, mask) - , calcBSDchecksum8(data, len, mask) - , calcBSDchecksum4(data, len, mask) - ); - return 0; + if (useHeader) { + PrintAndLogEx(NORMAL, " add | sub | add 1's compl | sub 1's compl | xor"); + PrintAndLogEx(NORMAL, "byte nibble crumb | byte nibble | byte nibble cumb | byte nibble | byte nibble cumb | BSD |"); + PrintAndLogEx(NORMAL, "------------------+-------------+------------------+-----------------+--------------------"); + } + PrintAndLogEx(NORMAL, "0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X | 0x%X 0x%X 0x%X | 0x%X 0x%X |\n", + calcSumByteAdd(data, len, mask) + , calcSumNibbleAdd(data, len, mask) + , calcSumCrumbAdd(data, len, mask) + , calcSumByteSub(data, len, mask) + , calcSumNibbleSub(data, len, mask) + , calcSumByteAddOnes(data, len, mask) + , calcSumNibbleAddOnes(data, len, mask) + , calcSumCrumbAddOnes(data, len, mask) + , calcSumByteSubOnes(data, len, mask) + , calcSumNibbleSubOnes(data, len, mask) + , calcSumByteXor(data, len, mask) + , calcSumNibbleXor(data, len, mask) + , calcSumCrumbXor(data, len, mask) + , calcBSDchecksum8(data, len, mask) + , calcBSDchecksum4(data, len, mask) + ); + return 0; } int CmdAnalyseDates(const char *Cmd){ - // look for datestamps in a given array of bytes - PrintAndLogEx(NORMAL, "To be implemented. Feel free to contribute!"); - return 0; + // look for datestamps in a given array of bytes + PrintAndLogEx(NORMAL, "To be implemented. Feel free to contribute!"); + return 0; } int CmdAnalyseTEASelfTest(const char *Cmd){ - uint8_t v[8], v_le[8]; - memset(v, 0x00, sizeof(v)); - memset(v_le, 0x00, sizeof(v_le)); - uint8_t* v_ptr = v_le; + uint8_t v[8], v_le[8]; + memset(v, 0x00, sizeof(v)); + memset(v_le, 0x00, sizeof(v_le)); + uint8_t* v_ptr = v_le; - uint8_t cmdlen = strlen(Cmd); - cmdlen = ( sizeof(v)<<2 < cmdlen ) ? sizeof(v)<<2 : cmdlen; + uint8_t cmdlen = strlen(Cmd); + cmdlen = ( sizeof(v)<<2 < cmdlen ) ? sizeof(v)<<2 : cmdlen; - if ( param_gethex(Cmd, 0, v, cmdlen) > 0 ){ - PrintAndLogEx(WARNING, "Can't read hex chars, uneven? :: %u", cmdlen); - return 1; - } + if ( param_gethex(Cmd, 0, v, cmdlen) > 0 ){ + PrintAndLogEx(WARNING, "Can't read hex chars, uneven? :: %u", cmdlen); + return 1; + } - SwapEndian64ex(v , 8, 4, v_ptr); + SwapEndian64ex(v , 8, 4, v_ptr); - // ENCRYPTION KEY: - uint8_t key[16] = {0x55,0xFE,0xF6,0x30,0x62,0xBF,0x0B,0xC1,0xC9,0xB3,0x7C,0x34,0x97,0x3E,0x29,0xFB }; - uint8_t keyle[16]; - uint8_t* key_ptr = keyle; - SwapEndian64ex(key , sizeof(key), 4, key_ptr); + // ENCRYPTION KEY: + uint8_t key[16] = {0x55,0xFE,0xF6,0x30,0x62,0xBF,0x0B,0xC1,0xC9,0xB3,0x7C,0x34,0x97,0x3E,0x29,0xFB }; + uint8_t keyle[16]; + uint8_t* key_ptr = keyle; + SwapEndian64ex(key , sizeof(key), 4, key_ptr); - PrintAndLogEx(NORMAL, "TEST LE enc| %s", sprint_hex(v_ptr, 8)); + PrintAndLogEx(NORMAL, "TEST LE enc| %s", sprint_hex(v_ptr, 8)); - tea_decrypt(v_ptr, key_ptr); - PrintAndLogEx(NORMAL, "TEST LE dec | %s", sprint_hex_ascii(v_ptr, 8)); + tea_decrypt(v_ptr, key_ptr); + PrintAndLogEx(NORMAL, "TEST LE dec | %s", sprint_hex_ascii(v_ptr, 8)); - tea_encrypt(v_ptr, key_ptr); - tea_encrypt(v_ptr, key_ptr); - PrintAndLogEx(NORMAL, "TEST enc2 | %s", sprint_hex_ascii(v_ptr, 8)); + tea_encrypt(v_ptr, key_ptr); + tea_encrypt(v_ptr, key_ptr); + PrintAndLogEx(NORMAL, "TEST enc2 | %s", sprint_hex_ascii(v_ptr, 8)); - return 0; + return 0; } char* pb(uint32_t b) { - static char buf1[33] = {0}; - static char buf2[33] = {0}; - static char *s; + static char buf1[33] = {0}; + static char buf2[33] = {0}; + static char *s; - if (s != buf1) - s = buf1; - else - s = buf2; + if (s != buf1) + s = buf1; + else + s = buf2; - memset(s, 0, sizeof(buf1)); + memset(s, 0, sizeof(buf1)); - uint32_t mask = 0x80000000; - for (uint8_t i=0; i<32;i++) { - s[i] = (mask & b)?'1':'0'; - mask >>= 1; - } - return s; + uint32_t mask = 0x80000000; + for (uint8_t i=0; i<32;i++) { + s[i] = (mask & b)?'1':'0'; + mask >>= 1; + } + return s; } int CmdAnalyseA(const char *Cmd){ - int hexlen = 0; - uint8_t cmdp = 0; - bool errors = false; - uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; + int hexlen = 0; + uint8_t cmdp = 0; + bool errors = false; + uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'd': - param_gethex_ex(Cmd, cmdp+1, data, &hexlen); - hexlen >>= 1; - if ( hexlen != sizeof(data) ) { - PrintAndLogEx(WARNING, "Read %d bytes of %u", hexlen, sizeof(data) ); - } - cmdp += 2; - break; - case 'h': - return usage_analyse_a(); - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors || cmdp == 0 ) return usage_analyse_a(); + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'd': + param_gethex_ex(Cmd, cmdp+1, data, &hexlen); + hexlen >>= 1; + if ( hexlen != sizeof(data) ) { + PrintAndLogEx(WARNING, "Read %d bytes of %u", hexlen, sizeof(data) ); + } + cmdp += 2; + break; + case 'h': + return usage_analyse_a(); + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + //Validations + if (errors || cmdp == 0 ) return usage_analyse_a(); - UsbCommand c = {CMD_FPC_SEND, {0, 0, 0}}; - memcpy(c.d.asBytes, data, USB_CMD_DATA_SIZE); - clearCommandBuffer(); - SendCommand(&c); + UsbCommand c = {CMD_FPC_SEND, {0, 0, 0}}; + memcpy(c.d.asBytes, data, USB_CMD_DATA_SIZE); + clearCommandBuffer(); + SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - return 1; - } - PrintAndLogEx(NORMAL, "got ack. Status %d", resp.arg[0]); - return 0; + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { + return 1; + } + PrintAndLogEx(NORMAL, "got ack. Status %d", resp.arg[0]); + return 0; - PrintAndLogEx(NORMAL, "-- " _BLUE_(its my message) "\n"); - PrintAndLogEx(NORMAL, "-- " _RED_(its my message) "\n"); - PrintAndLogEx(NORMAL, "-- " _YELLOW_(its my message) "\n"); - PrintAndLogEx(NORMAL, "-- " _GREEN_(its my message) "\n"); + PrintAndLogEx(NORMAL, "-- " _BLUE_(its my message) "\n"); + PrintAndLogEx(NORMAL, "-- " _RED_(its my message) "\n"); + PrintAndLogEx(NORMAL, "-- " _YELLOW_(its my message) "\n"); + PrintAndLogEx(NORMAL, "-- " _GREEN_(its my message) "\n"); - //uint8_t syncBit = 99; - // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from - // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111) - // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern - // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's) - # define SYNC_16BIT 0xB24D - uint32_t shiftReg = param_get32ex(Cmd, 0, 0xb24d, 16); - uint8_t bt = param_get8ex(Cmd, 1, 0xBB, 16); - uint8_t byte_offset = 99; - // reverse byte - uint8_t rev = reflect8(bt); - PrintAndLogEx(NORMAL, "input %02x | %02x \n", bt, rev); - // add byte to shift register - shiftReg = shiftReg << 8 | rev; + //uint8_t syncBit = 99; + // The start bit is one ore more Sequence Y followed by a Sequence Z (... 11111111 00x11111). We need to distinguish from + // Sequence X followed by Sequence Y followed by Sequence Z (111100x1 11111111 00x11111) + // we therefore look for a ...xx1111 11111111 00x11111xxxxxx... pattern + // (12 '1's followed by 2 '0's, eventually followed by another '0', followed by 5 '1's) + # define SYNC_16BIT 0xB24D + uint32_t shiftReg = param_get32ex(Cmd, 0, 0xb24d, 16); + uint8_t bt = param_get8ex(Cmd, 1, 0xBB, 16); + uint8_t byte_offset = 99; + // reverse byte + uint8_t rev = reflect8(bt); + PrintAndLogEx(NORMAL, "input %02x | %02x \n", bt, rev); + // add byte to shift register + shiftReg = shiftReg << 8 | rev; - PrintAndLogEx(NORMAL, "shiftreg after %08x | pattern %08x \n", shiftReg, SYNC_16BIT); + PrintAndLogEx(NORMAL, "shiftreg after %08x | pattern %08x \n", shiftReg, SYNC_16BIT); - uint8_t n0 = 0, n1 = 0; + uint8_t n0 = 0, n1 = 0; - n0 = (rev & (uint8_t)(~(0xFF >> (8-4)))) >> 4; - n1 = (n1 << 4) | (rev & (uint8_t)(~(0xFF << 4))); + n0 = (rev & (uint8_t)(~(0xFF >> (8-4)))) >> 4; + n1 = (n1 << 4) | (rev & (uint8_t)(~(0xFF << 4))); - PrintAndLogEx(NORMAL, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1) ); + PrintAndLogEx(NORMAL, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1) ); /* hex(0xb24d shr 0) 0xB24D 0b1011001001001101 @@ -562,111 +562,111 @@ hex(0xb24d shr 2) 0x2C93 */ for ( int i =0; i< 16; i++) { - PrintAndLogEx(NORMAL, " (shiftReg >> %d) & 0xFFFF == %08x ---", i, (( shiftReg >> i) & 0xFFFF )); + PrintAndLogEx(NORMAL, " (shiftReg >> %d) & 0xFFFF == %08x ---", i, (( shiftReg >> i) & 0xFFFF )); - // kolla om SYNC_PATTERN finns. - if ((( shiftReg >> 7) & 0xFFFF ) == SYNC_16BIT) byte_offset = 7; - else if ((( shiftReg >> 6) & 0xFFFF ) == SYNC_16BIT) byte_offset = 6; - else if ((( shiftReg >> 5) & 0xFFFF ) == SYNC_16BIT) byte_offset = 5; - else if ((( shiftReg >> 4) & 0xFFFF ) == SYNC_16BIT) byte_offset = 4; - else if ((( shiftReg >> 3) & 0xFFFF ) == SYNC_16BIT) byte_offset = 3; - else if ((( shiftReg >> 2) & 0xFFFF ) == SYNC_16BIT) byte_offset = 2; - else if ((( shiftReg >> 1) & 0xFFFF ) == SYNC_16BIT) byte_offset = 1; - else if ((( shiftReg >> 0) & 0xFFFF ) == SYNC_16BIT) byte_offset = 0; + // kolla om SYNC_PATTERN finns. + if ((( shiftReg >> 7) & 0xFFFF ) == SYNC_16BIT) byte_offset = 7; + else if ((( shiftReg >> 6) & 0xFFFF ) == SYNC_16BIT) byte_offset = 6; + else if ((( shiftReg >> 5) & 0xFFFF ) == SYNC_16BIT) byte_offset = 5; + else if ((( shiftReg >> 4) & 0xFFFF ) == SYNC_16BIT) byte_offset = 4; + else if ((( shiftReg >> 3) & 0xFFFF ) == SYNC_16BIT) byte_offset = 3; + else if ((( shiftReg >> 2) & 0xFFFF ) == SYNC_16BIT) byte_offset = 2; + else if ((( shiftReg >> 1) & 0xFFFF ) == SYNC_16BIT) byte_offset = 1; + else if ((( shiftReg >> 0) & 0xFFFF ) == SYNC_16BIT) byte_offset = 0; - PrintAndLogEx(NORMAL, "Offset %u \n", byte_offset); - if ( byte_offset != 99 ) - break; + PrintAndLogEx(NORMAL, "Offset %u \n", byte_offset); + if ( byte_offset != 99 ) + break; - shiftReg >>=1; + shiftReg >>=1; } - uint8_t p1 = (rev & (uint8_t)(~(0xFF << byte_offset))); - PrintAndLogEx(NORMAL, "Offset %u | leftovers %02x %s \n", byte_offset, p1, pb(p1) ); + uint8_t p1 = (rev & (uint8_t)(~(0xFF << byte_offset))); + PrintAndLogEx(NORMAL, "Offset %u | leftovers %02x %s \n", byte_offset, p1, pb(p1) ); - /* + /* pm3 --> da hex2bin 4db2 0100110110110010 */ - return 0; + return 0; /* - // split byte into two parts. - uint8_t offset = 3, n0 = 0, n1 = 0; - rev = 0xB2; - for (uint8_t m=0; m<8; m++) { - offset = m; - n0 = (rev & (uint8_t)(~(0xFF >> (8-offset)))) >> offset; - n1 = (n1 << offset) | (rev & (uint8_t)(~(0xFF << offset))); + // split byte into two parts. + uint8_t offset = 3, n0 = 0, n1 = 0; + rev = 0xB2; + for (uint8_t m=0; m<8; m++) { + offset = m; + n0 = (rev & (uint8_t)(~(0xFF >> (8-offset)))) >> offset; + n1 = (n1 << offset) | (rev & (uint8_t)(~(0xFF << offset))); - PrintAndLogEx(NORMAL, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1) ); - n0 = 0, n1 = 0; - // PrintAndLogEx(NORMAL, " (0xFF >> offset) == %s |\n", pb( (0xFF >> offset)) ); - //PrintAndLogEx(NORMAL, "~(0xFF >> (8-offset)) == %s |\n", pb( (uint8_t)(~(0xFF >> (8-offset))) ) ); - //PrintAndLogEx(NORMAL, " rev & xxx == %s\n\n", pb( (rev & (uint8_t)(~(0xFF << offset))) )); - } + PrintAndLogEx(NORMAL, "rev %02X | %02X %s | %02X %s |\n", rev, n0, pb(n0), n1, pb(n1) ); + n0 = 0, n1 = 0; + // PrintAndLogEx(NORMAL, " (0xFF >> offset) == %s |\n", pb( (0xFF >> offset)) ); + //PrintAndLogEx(NORMAL, "~(0xFF >> (8-offset)) == %s |\n", pb( (uint8_t)(~(0xFF >> (8-offset))) ) ); + //PrintAndLogEx(NORMAL, " rev & xxx == %s\n\n", pb( (rev & (uint8_t)(~(0xFF << offset))) )); + } return 0; - // from A -- x bits into B and the rest into C. + // from A -- x bits into B and the rest into C. - for ( uint8_t i=0; i<8; i++){ - PrintAndLogEx(NORMAL, "%u | %02X %s | %02X %s |\n", i, a, pb(a), b, pb(b) ); - b = a & (a & (0xFF >> (8-i))); - a >>=1; - } + for ( uint8_t i=0; i<8; i++){ + PrintAndLogEx(NORMAL, "%u | %02X %s | %02X %s |\n", i, a, pb(a), b, pb(b) ); + b = a & (a & (0xFF >> (8-i))); + a >>=1; + } - */ - return 0; + */ + return 0; - // 14443-A - uint8_t u14_c[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe8 }; // atqs w crc - uint8_t u14_w[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe7 }; // atqs w crc - PrintAndLogEx(FAILED, "14a check wrong crc | %s\n", (check_crc(CRC_14443_A, u14_w, sizeof(u14_w))) ? "YES": "NO" ); - PrintAndLogEx(SUCCESS, "14a check correct crc | %s\n", (check_crc(CRC_14443_A, u14_c, sizeof(u14_c))) ? "YES": "NO" ); + // 14443-A + uint8_t u14_c[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe8 }; // atqs w crc + uint8_t u14_w[] = {0x09, 0x78, 0x00, 0x92, 0x02, 0x54, 0x13, 0x02, 0x04, 0x2d, 0xe7 }; // atqs w crc + PrintAndLogEx(FAILED, "14a check wrong crc | %s\n", (check_crc(CRC_14443_A, u14_w, sizeof(u14_w))) ? "YES": "NO" ); + PrintAndLogEx(SUCCESS, "14a check correct crc | %s\n", (check_crc(CRC_14443_A, u14_c, sizeof(u14_c))) ? "YES": "NO" ); - // 14443-B - uint8_t u14b[] = {0x05,0x00,0x08,0x39,0x73}; - PrintAndLogEx(NORMAL, "14b check crc | %s\n", (check_crc(CRC_14443_B, u14b, sizeof(u14b))) ? "YES": "NO"); + // 14443-B + uint8_t u14b[] = {0x05,0x00,0x08,0x39,0x73}; + PrintAndLogEx(NORMAL, "14b check crc | %s\n", (check_crc(CRC_14443_B, u14b, sizeof(u14b))) ? "YES": "NO"); - // 15693 test - uint8_t u15_c[] = {0x05,0x00,0x08,0x39,0x73}; // correct - uint8_t u15_w[] = {0x05,0x00,0x08,0x39,0x72}; // wrong - PrintAndLogEx(FAILED, "15 check wrong crc | %s\n", (check_crc(CRC_15693, u15_w, sizeof(u15_w))) ? "YES": "NO"); - PrintAndLogEx(SUCCESS, "15 check correct crc | %s\n", (check_crc(CRC_15693, u15_c, sizeof(u15_c))) ? "YES": "NO"); + // 15693 test + uint8_t u15_c[] = {0x05,0x00,0x08,0x39,0x73}; // correct + uint8_t u15_w[] = {0x05,0x00,0x08,0x39,0x72}; // wrong + PrintAndLogEx(FAILED, "15 check wrong crc | %s\n", (check_crc(CRC_15693, u15_w, sizeof(u15_w))) ? "YES": "NO"); + PrintAndLogEx(SUCCESS, "15 check correct crc | %s\n", (check_crc(CRC_15693, u15_c, sizeof(u15_c))) ? "YES": "NO"); - // iCLASS test - wrong crc , swapped bytes. - uint8_t iclass_w[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x01, 0x43}; - uint8_t iclass_c[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01}; - PrintAndLogEx(FAILED, "iCLASS check wrong crc | %s\n", (check_crc(CRC_ICLASS, iclass_w, sizeof(iclass_w))) ? "YES": "NO"); - PrintAndLogEx(SUCCESS, "iCLASS check correct crc | %s\n", (check_crc(CRC_ICLASS, iclass_c, sizeof(iclass_c))) ? "YES": "NO"); + // iCLASS test - wrong crc , swapped bytes. + uint8_t iclass_w[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x01, 0x43}; + uint8_t iclass_c[] = { 0x40, 0xe1, 0xe1, 0xff, 0xfe, 0x5f, 0x02, 0x3c, 0x43, 0x01}; + PrintAndLogEx(FAILED, "iCLASS check wrong crc | %s\n", (check_crc(CRC_ICLASS, iclass_w, sizeof(iclass_w))) ? "YES": "NO"); + PrintAndLogEx(SUCCESS, "iCLASS check correct crc | %s\n", (check_crc(CRC_ICLASS, iclass_c, sizeof(iclass_c))) ? "YES": "NO"); - // FeliCa test - uint8_t felica_w[] = {0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7e}; - uint8_t felica_c[] = {0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; - PrintAndLogEx(FAILED, "FeliCa check wrong crc | %s\n", (check_crc(CRC_FELICA, felica_w, sizeof(felica_w))) ? "YES": "NO"); - PrintAndLogEx(SUCCESS, "FeliCa check correct crc | %s\n", (check_crc(CRC_FELICA, felica_c, sizeof(felica_c))) ? "YES": "NO"); + // FeliCa test + uint8_t felica_w[] = {0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7e}; + uint8_t felica_c[] = {0x12,0x01,0x01,0x2e,0x3d,0x17,0x26,0x47,0x80, 0x95,0x00,0xf1,0x00,0x00,0x00,0x01,0x43,0x00,0xb3,0x7f}; + PrintAndLogEx(FAILED, "FeliCa check wrong crc | %s\n", (check_crc(CRC_FELICA, felica_w, sizeof(felica_w))) ? "YES": "NO"); + PrintAndLogEx(SUCCESS, "FeliCa check correct crc | %s\n", (check_crc(CRC_FELICA, felica_c, sizeof(felica_c))) ? "YES": "NO"); - PrintAndLogEx(NORMAL, "\n\n"); + PrintAndLogEx(NORMAL, "\n\n"); - return 0; - /* - bool term = !isatty(STDIN_FILENO); - if (!term) { - char star[4]; - star[0] = '-'; - star[1] = '\\'; - star[2] = '|'; - star[3] = '/'; + return 0; + /* + bool term = !isatty(STDIN_FILENO); + if (!term) { + char star[4]; + star[0] = '-'; + star[1] = '\\'; + star[2] = '|'; + star[3] = '/'; - for (uint8_t k=0; k<4; k = (k+1) % 4 ) { - PrintAndLogEx(NORMAL, "\e[s%c\e[u", star[k]); - fflush(stdout); - if (ukbhit()) { - int gc = getchar(); (void)gc; - break; - } - } - } - */ + for (uint8_t k=0; k<4; k = (k+1) % 4 ) { + PrintAndLogEx(NORMAL, "\e[s%c\e[u", star[k]); + fflush(stdout); + if (ukbhit()) { + int gc = getchar(); (void)gc; + break; + } + } + } + */ //piwi // uid(2e086b1a) nt(230736f6) ks(0b0008000804000e) nr(000000000) @@ -691,225 +691,225 @@ return 0; uid(3e172b29) nt(039b7bd2) ks(0c0e0f0505080800) nr(00000001) uid(3e172b29) nt(039b7bd2) ks(0e06090d03000b0f) nr(00000002) */ - uint64_t *keylistA = NULL, *keylistB = NULL; - uint32_t keycountA = 0, keycountB = 0; -// uint64_t d1[] = {0x3e172b29, 0x039b7bd2, 0x0000001, 0, 0x0c0e0f0505080800}; -// uint64_t d2[] = {0x3e172b29, 0x039b7bd2, 0x0000002, 0, 0x0e06090d03000b0f}; + uint64_t *keylistA = NULL, *keylistB = NULL; + uint32_t keycountA = 0, keycountB = 0; +// uint64_t d1[] = {0x3e172b29, 0x039b7bd2, 0x0000001, 0, 0x0c0e0f0505080800}; +// uint64_t d2[] = {0x3e172b29, 0x039b7bd2, 0x0000002, 0, 0x0e06090d03000b0f}; uint64_t d1[] = {0x6e442129, 0x8f699195, 0x0000001, 0, 0x090d0b0305020f02}; uint64_t d2[] = {0x6e442129, 0x8f699195, 0x0000004, 0, 0x00040f0f0305030e}; - keycountA = nonce2key(d1[0], d1[1], d1[2], 0, d1[3], d1[4] ,&keylistA); - keycountB = nonce2key(d2[0], d2[1], d2[2], 0, d2[3], d2[4], &keylistB); + keycountA = nonce2key(d1[0], d1[1], d1[2], 0, d1[3], d1[4] ,&keylistA); + keycountB = nonce2key(d2[0], d2[1], d2[2], 0, d2[3], d2[4], &keylistB); - switch (keycountA) { - case 0: PrintAndLogEx(FAILED, "Key test A failed\n"); break; - case 1: PrintAndLogEx(SUCCESS, "KEY A | %012" PRIX64 " ", keylistA[0]); break; - } - switch (keycountB) { - case 0: PrintAndLogEx(FAILED, "Key test B failed\n"); break; - case 1: PrintAndLogEx(SUCCESS, "KEY B | %012" PRIX64 " ", keylistB[0]); break; - } + switch (keycountA) { + case 0: PrintAndLogEx(FAILED, "Key test A failed\n"); break; + case 1: PrintAndLogEx(SUCCESS, "KEY A | %012" PRIX64 " ", keylistA[0]); break; + } + switch (keycountB) { + case 0: PrintAndLogEx(FAILED, "Key test B failed\n"); break; + case 1: PrintAndLogEx(SUCCESS, "KEY B | %012" PRIX64 " ", keylistB[0]); break; + } - free(keylistA); - free(keylistB); + free(keylistA); + free(keylistB); -// qsort(keylist, keycount, sizeof(*keylist), compare_uint64); -// keycount = intersection(last_keylist, keylist); +// qsort(keylist, keycount, sizeof(*keylist), compare_uint64); +// keycount = intersection(last_keylist, keylist); - /* - uint64_t keys[] = { - 0x7b5b8144a32f, 0x76b46ccc461e, 0x03c3c36ea7a2, 0x171414d31961, - 0xe2bfc7153eea, 0x48023d1d1985, 0xff7e1a410953, 0x49a3110249d3, - 0xe3515546d015, 0x667c2ac86f85, 0x5774a8d5d6a9, 0xe401c2ca602c, - 0x3be7e5020a7e, 0x66dbec3cf90b, 0x4e13f1534605, 0x5c172e1e78c9, - 0xeafe51411fbf, 0xc579f0fcdd8f, 0x2146a0d745c3, 0xab31ca60171a, - 0x3169130a5035, 0xde5e11ea4923, 0x96fe2aeb9924, 0x828b61e6fcba, - 0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b, - 0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe - }; + /* + uint64_t keys[] = { + 0x7b5b8144a32f, 0x76b46ccc461e, 0x03c3c36ea7a2, 0x171414d31961, + 0xe2bfc7153eea, 0x48023d1d1985, 0xff7e1a410953, 0x49a3110249d3, + 0xe3515546d015, 0x667c2ac86f85, 0x5774a8d5d6a9, 0xe401c2ca602c, + 0x3be7e5020a7e, 0x66dbec3cf90b, 0x4e13f1534605, 0x5c172e1e78c9, + 0xeafe51411fbf, 0xc579f0fcdd8f, 0x2146a0d745c3, 0xab31ca60171a, + 0x3169130a5035, 0xde5e11ea4923, 0x96fe2aeb9924, 0x828b61e6fcba, + 0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b, + 0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe + }; - uint64_t keya[] = { - 0x7b5b8144a32f, 0x76b46ccc461e, 0x03c3c36ea7a2, 0x171414d31961, - 0xe2bfc7153eea, 0x48023d1d1985, 0xff7e1a410953, 0x49a3110249d3, - 0xe3515546d015, 0x667c2ac86f85, 0x5774a8d5d6a9, 0xe401c2ca602c, - 0x3be7e5020a7e, 0x66dbec3cf90b, 0x4e13f1534605, 0x5c172e1e78c9 - }; - uint64_t keyb[] = { - 0xeafe51411fbf, 0xc579f0fcdd8f, 0x2146a0d745c3, 0xab31ca60171a, - 0x3169130a5035, 0xde5e11ea4923, 0x96fe2aeb9924, 0x828b61e6fcba, - 0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b, - 0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe - }; + uint64_t keya[] = { + 0x7b5b8144a32f, 0x76b46ccc461e, 0x03c3c36ea7a2, 0x171414d31961, + 0xe2bfc7153eea, 0x48023d1d1985, 0xff7e1a410953, 0x49a3110249d3, + 0xe3515546d015, 0x667c2ac86f85, 0x5774a8d5d6a9, 0xe401c2ca602c, + 0x3be7e5020a7e, 0x66dbec3cf90b, 0x4e13f1534605, 0x5c172e1e78c9 + }; + uint64_t keyb[] = { + 0xeafe51411fbf, 0xc579f0fcdd8f, 0x2146a0d745c3, 0xab31ca60171a, + 0x3169130a5035, 0xde5e11ea4923, 0x96fe2aeb9924, 0x828b61e6fcba, + 0x8211b0607367, 0xe2936b320f76, 0xaff501e84378, 0x82b31cedb21b, + 0xb725d31d4cd3, 0x3b984145b2f1, 0x3b4adb3e82ba, 0x8779075210fe + }; - */ + */ - /* - uint64_t xor[] = { - 0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B, - 0xAABDFA08276F, 0xB77C275C10D6, 0xB6DD0B434080, 0xAAF2444499C6, - 0x852D7F8EBF90, 0x3108821DB92C, 0xB3756A1FB685, 0xDFE627C86A52, - 0x5D3C093EF375, 0x28C81D6FBF0E, 0x1204DF4D3ECC, 0xB6E97F5F6776, - 0x2F87A1BDC230, 0xE43F502B984C, 0x8A776AB752D9, 0x9A58D96A472F, - 0xEF3702E01916, 0x48A03B01D007, 0x14754B0D659E, 0x009AD1868FDD, - 0x6082DB527C11, 0x4D666ADA4C0E, 0x2D461D05F163, 0x3596CFF0FEC8, - 0x8CBD9258FE22, 0x00D29A7B304B, 0xBC33DC6C9244 - }; + /* + uint64_t xor[] = { + 0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B, + 0xAABDFA08276F, 0xB77C275C10D6, 0xB6DD0B434080, 0xAAF2444499C6, + 0x852D7F8EBF90, 0x3108821DB92C, 0xB3756A1FB685, 0xDFE627C86A52, + 0x5D3C093EF375, 0x28C81D6FBF0E, 0x1204DF4D3ECC, 0xB6E97F5F6776, + 0x2F87A1BDC230, 0xE43F502B984C, 0x8A776AB752D9, 0x9A58D96A472F, + 0xEF3702E01916, 0x48A03B01D007, 0x14754B0D659E, 0x009AD1868FDD, + 0x6082DB527C11, 0x4D666ADA4C0E, 0x2D461D05F163, 0x3596CFF0FEC8, + 0x8CBD9258FE22, 0x00D29A7B304B, 0xBC33DC6C9244 + }; - uint64_t xorA[] = { - 0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B, - 0xAABDFA08276F, 0xB77C275C10D6, 0xB6DD0B434080, 0xAAF2444499C6, - 0x852D7F8EBF90, 0x3108821DB92C, 0xB3756A1FB685, 0xDFE627C86A52, - 0x5D3C093EF375, 0x28C81D6FBF0E, 0x1204DF4D3ECC - }; - uint64_t xorB[] = { - 0x2F87A1BDC230, 0xE43F502B984C, 0x8A776AB752D9, 0x9A58D96A472F, - 0xEF3702E01916, 0x48A03B01D007, 0x14754B0D659E, 0x009AD1868FDD, - 0x6082DB527C11, 0x4D666ADA4C0E, 0x2D461D05F163, 0x3596CFF0FEC8, - 0x8CBD9258FE22, 0x00D29A7B304B, 0xBC33DC6C9244 - }; - */ - /* - // xor key A | xor key B - 1 | 0DEFED88E531 | 2F87A1BDC230 - 2 | 7577AFA2E1BC | E43F502B984C - 3 | 14D7D7BDBEC3 | 8A776AB752D9 - 4 | F5ABD3C6278B | 9A58D96A472F - 5 | AABDFA08276F | EF3702E01916 - 6 | B77C275C10D6 | 48A03B01D007 - 7 | B6DD0B434080 | 14754B0D659E - 8 | AAF2444499C6 | 009AD1868FDD - 9 | 852D7F8EBF90 | 6082DB527C11 - 10 | 3108821DB92C | 4D666ADA4C0E - 11 | B3756A1FB685 | 2D461D05F163 - 12 | DFE627C86A52 | 3596CFF0FEC8 - 13 | 5D3C093EF375 | 8CBD9258FE22 - 14 | 28C81D6FBF0E | 00D29A7B304B - 15 | 1204DF4D3ECC | BC33DC6C9244 - */ + uint64_t xorA[] = { + 0x0DEFED88E531, 0x7577AFA2E1BC, 0x14D7D7BDBEC3, 0xF5ABD3C6278B, + 0xAABDFA08276F, 0xB77C275C10D6, 0xB6DD0B434080, 0xAAF2444499C6, + 0x852D7F8EBF90, 0x3108821DB92C, 0xB3756A1FB685, 0xDFE627C86A52, + 0x5D3C093EF375, 0x28C81D6FBF0E, 0x1204DF4D3ECC + }; + uint64_t xorB[] = { + 0x2F87A1BDC230, 0xE43F502B984C, 0x8A776AB752D9, 0x9A58D96A472F, + 0xEF3702E01916, 0x48A03B01D007, 0x14754B0D659E, 0x009AD1868FDD, + 0x6082DB527C11, 0x4D666ADA4C0E, 0x2D461D05F163, 0x3596CFF0FEC8, + 0x8CBD9258FE22, 0x00D29A7B304B, 0xBC33DC6C9244 + }; + */ + /* + // xor key A | xor key B + 1 | 0DEFED88E531 | 2F87A1BDC230 + 2 | 7577AFA2E1BC | E43F502B984C + 3 | 14D7D7BDBEC3 | 8A776AB752D9 + 4 | F5ABD3C6278B | 9A58D96A472F + 5 | AABDFA08276F | EF3702E01916 + 6 | B77C275C10D6 | 48A03B01D007 + 7 | B6DD0B434080 | 14754B0D659E + 8 | AAF2444499C6 | 009AD1868FDD + 9 | 852D7F8EBF90 | 6082DB527C11 + 10 | 3108821DB92C | 4D666ADA4C0E + 11 | B3756A1FB685 | 2D461D05F163 + 12 | DFE627C86A52 | 3596CFF0FEC8 + 13 | 5D3C093EF375 | 8CBD9258FE22 + 14 | 28C81D6FBF0E | 00D29A7B304B + 15 | 1204DF4D3ECC | BC33DC6C9244 + */ - // generate xor table :) - /* - for (uint8_t i=0; i<31; i++){ - uint64_t a = keys[i] ^ keys[i+1]; - PrintAndLogEx(NORMAL, "%u | %012" PRIX64 " | \n", i, a); - } - */ + // generate xor table :) + /* + for (uint8_t i=0; i<31; i++){ + uint64_t a = keys[i] ^ keys[i+1]; + PrintAndLogEx(NORMAL, "%u | %012" PRIX64 " | \n", i, a); + } + */ - /* - uint32_t id = param_get32ex(Cmd, 0, 0x93290142, 16); - uint8_t uid[6] = {0}; - num_to_bytes(id,4,uid); + /* + uint32_t id = param_get32ex(Cmd, 0, 0x93290142, 16); + uint8_t uid[6] = {0}; + num_to_bytes(id,4,uid); - uint8_t key_s0a[] = { - uid[1] ^ uid[2] ^ uid[3] ^ 0x11, - uid[1] ^ 0x72, - uid[2] ^ 0x80, - (uid[0] + uid[1] + uid[2] + uid[3] ) ^ uid[3] ^ 0x19, - 0xA3, - 0x2F - }; + uint8_t key_s0a[] = { + uid[1] ^ uid[2] ^ uid[3] ^ 0x11, + uid[1] ^ 0x72, + uid[2] ^ 0x80, + (uid[0] + uid[1] + uid[2] + uid[3] ) ^ uid[3] ^ 0x19, + 0xA3, + 0x2F + }; - PrintAndLogEx(NORMAL, "UID | %s\n", sprint_hex(uid,4 )); - PrintAndLogEx(NORMAL, "KEY A | %s\n", sprint_hex(key_s0a, 6)); + PrintAndLogEx(NORMAL, "UID | %s\n", sprint_hex(uid,4 )); + PrintAndLogEx(NORMAL, "KEY A | %s\n", sprint_hex(key_s0a, 6)); - // arrays w all keys - uint64_t foo[32] = {0}; + // arrays w all keys + uint64_t foo[32] = {0}; - //A - foo[0] = bytes_to_num(key_s0a, 6); - //B - //foo[16] = 0xcafe71411fbf; - foo[16] = 0xeafe51411fbf; + //A + foo[0] = bytes_to_num(key_s0a, 6); + //B + //foo[16] = 0xcafe71411fbf; + foo[16] = 0xeafe51411fbf; - for (uint8_t i=0; i<15; i++){ - foo[i+1] = foo[i] ^ xorA[i]; - foo[i+16+1] = foo[i+16] ^ xorB[i]; + for (uint8_t i=0; i<15; i++){ + foo[i+1] = foo[i] ^ xorA[i]; + foo[i+16+1] = foo[i+16] ^ xorB[i]; - } - for (uint8_t i=0; i<15; i++){ - uint64_t a = foo[i]; - uint64_t b = foo[i+16]; + } + for (uint8_t i=0; i<15; i++){ + uint64_t a = foo[i]; + uint64_t b = foo[i+16]; - PrintAndLogEx(NORMAL, "%02u | %012" PRIX64 " %s | %012" PRIX64 " %s\n", - i, - a, - ( a == keya[i])?"ok":"err", - b, - ( b == keyb[i])?"ok":"err" - ); - } - */ - return 0; + PrintAndLogEx(NORMAL, "%02u | %012" PRIX64 " %s | %012" PRIX64 " %s\n", + i, + a, + ( a == keya[i])?"ok":"err", + b, + ( b == keyb[i])?"ok":"err" + ); + } + */ + return 0; } void generate4bNUID(uint8_t *uid, uint8_t *nuid){ - uint16_t crc; - uint8_t b1, b2; + uint16_t crc; + uint8_t b1, b2; - compute_crc(CRC_14443_A, uid, 3, &b1, &b2); - nuid[0] = (b2 & 0xE0) | 0xF; - nuid[1] = b1; - crc = b1; - crc |= b2 << 8; - crc = crc16_fast(&uid[3], 4, reflect16(crc), true, true); - nuid[2] = (crc >> 8) & 0xFF ; - nuid[3] = crc & 0xFF; + compute_crc(CRC_14443_A, uid, 3, &b1, &b2); + nuid[0] = (b2 & 0xE0) | 0xF; + nuid[1] = b1; + crc = b1; + crc |= b2 << 8; + crc = crc16_fast(&uid[3], 4, reflect16(crc), true, true); + nuid[2] = (crc >> 8) & 0xFF ; + nuid[3] = crc & 0xFF; } int CmdAnalyseNuid(const char *Cmd){ - uint8_t nuid[4] = {0}; - uint8_t uid[7] = {0}; - int len = 0; - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) == 0|| cmdp == 'h') return usage_analyse_nuid(); + uint8_t nuid[4] = {0}; + uint8_t uid[7] = {0}; + int len = 0; + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) == 0|| cmdp == 'h') return usage_analyse_nuid(); - /* src: https://www.nxp.com/docs/en/application-note/AN10927.pdf */ - /* selftest1 UID 040D681AB52281 -> NUID 8F430FEF */ - /* selftest2 UID 04183F09321B85 -> NUID 4F505D7D */ - if (cmdp == 't') { - memcpy(uid, "\x04\x0d\x68\x1a\xb5\x22\x81", 7); - generate4bNUID(uid, nuid); + /* src: https://www.nxp.com/docs/en/application-note/AN10927.pdf */ + /* selftest1 UID 040D681AB52281 -> NUID 8F430FEF */ + /* selftest2 UID 04183F09321B85 -> NUID 4F505D7D */ + if (cmdp == 't') { + memcpy(uid, "\x04\x0d\x68\x1a\xb5\x22\x81", 7); + generate4bNUID(uid, nuid); - bool test1 = (0 == memcmp(nuid, "\x8f\x43\x0f\xef", 4)); - PrintAndLogEx(SUCCESS, "Selftest1 %s\n", test1 ? _GREEN_(OK): _RED_(Fail)); + bool test1 = (0 == memcmp(nuid, "\x8f\x43\x0f\xef", 4)); + PrintAndLogEx(SUCCESS, "Selftest1 %s\n", test1 ? _GREEN_(OK): _RED_(Fail)); - memcpy(uid, "\x04\x18\x3f\x09\x32\x1b\x85", 7); - generate4bNUID(uid, nuid); - bool test2 = (0 == memcmp(nuid, "\x4f\x50\x5d\x7d", 4)); - PrintAndLogEx(SUCCESS, "Selftest2 %s\n", test2 ? _GREEN_(OK) : _RED_(Fail)); - return 0; - } + memcpy(uid, "\x04\x18\x3f\x09\x32\x1b\x85", 7); + generate4bNUID(uid, nuid); + bool test2 = (0 == memcmp(nuid, "\x4f\x50\x5d\x7d", 4)); + PrintAndLogEx(SUCCESS, "Selftest2 %s\n", test2 ? _GREEN_(OK) : _RED_(Fail)); + return 0; + } - param_gethex_ex(Cmd, 0, uid, &len); - if ( len%2 || len != 14) return usage_analyse_nuid(); + param_gethex_ex(Cmd, 0, uid, &len); + if ( len%2 || len != 14) return usage_analyse_nuid(); - generate4bNUID(uid, nuid); + generate4bNUID(uid, nuid); - PrintAndLogEx(NORMAL, "UID | %s \n", sprint_hex(uid, 7)); - PrintAndLogEx(NORMAL, "NUID | %s \n", sprint_hex(nuid, 4)); - return 0; + PrintAndLogEx(NORMAL, "UID | %s \n", sprint_hex(uid, 7)); + PrintAndLogEx(NORMAL, "NUID | %s \n", sprint_hex(nuid, 4)); + return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"lcr", CmdAnalyseLCR, 1, "Generate final byte for XOR LRC"}, - {"crc", CmdAnalyseCRC, 1, "Stub method for CRC evaluations"}, - {"chksum", CmdAnalyseCHKSUM, 1, "Checksum with adding, masking and one's complement"}, - {"dates", CmdAnalyseDates, 1, "Look for datestamps in a given array of bytes"}, - {"tea", CmdAnalyseTEASelfTest, 1, "Crypto TEA test"}, - {"lfsr", CmdAnalyseLfsr, 1, "LFSR tests"}, - {"a", CmdAnalyseA, 1, "num bits test"}, - {"nuid", CmdAnalyseNuid, 1, "create NUID from 7byte UID"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"lcr", CmdAnalyseLCR, 1, "Generate final byte for XOR LRC"}, + {"crc", CmdAnalyseCRC, 1, "Stub method for CRC evaluations"}, + {"chksum", CmdAnalyseCHKSUM, 1, "Checksum with adding, masking and one's complement"}, + {"dates", CmdAnalyseDates, 1, "Look for datestamps in a given array of bytes"}, + {"tea", CmdAnalyseTEASelfTest, 1, "Crypto TEA test"}, + {"lfsr", CmdAnalyseLfsr, 1, "LFSR tests"}, + {"a", CmdAnalyseA, 1, "num bits test"}, + {"nuid", CmdAnalyseNuid, 1, "create NUID from 7byte UID"}, + {NULL, NULL, 0, NULL} }; int CmdAnalyse(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } diff --git a/client/cmdanalyse.h b/client/cmdanalyse.h index c362744c0..131fe0d11 100644 --- a/client/cmdanalyse.h +++ b/client/cmdanalyse.h @@ -11,20 +11,20 @@ #ifndef CMDANALYSE_H__ #define CMDANALYSE_H__ -#include //size_t +#include // size_t #include #include #include "cmdmain.h" #include "proxmark3.h" -#include "ui.h" // PrintAndLog +#include "ui.h" // PrintAndLog #include "util.h" #include "crc.h" -#include "crc16.h" // crc16 ccitt +#include "crc16.h" // crc16 ccitt #include "tea.h" #include "legic_prng.h" #include "loclass/elite_crack.h" -#include "mifare/mfkey.h" //nonce2key -#include "util_posix.h" // msclock +#include "mifare/mfkey.h" // nonce2key +#include "util_posix.h" // msclock int usage_analyse_lcr(void); diff --git a/client/cmdcrc.c b/client/cmdcrc.c index a54653d3e..38d5a2005 100644 --- a/client/cmdcrc.c +++ b/client/cmdcrc.c @@ -23,7 +23,7 @@ int split(char *str, char *arr[MAX_ARGS]){ } if(str[beginIndex] == '\0') { break; - } + } endIndex = beginIndex; while (str[endIndex] && !isspace(str[endIndex])) { ++endIndex; @@ -40,202 +40,202 @@ int split(char *str, char *arr[MAX_ARGS]){ } int CmdCrc(const char *Cmd) { - char name[] = {"reveng "}; - char Cmd2[100 + 7]; - memcpy(Cmd2, name, 7); - memcpy(Cmd2 + 7, Cmd, 100); - char *argv[MAX_ARGS]; - int argc = split(Cmd2, argv); + char name[] = {"reveng "}; + char Cmd2[100 + 7]; + memcpy(Cmd2, name, 7); + memcpy(Cmd2 + 7, Cmd, 100); + char *argv[MAX_ARGS]; + int argc = split(Cmd2, argv); - if (argc == 3 && memcmp(argv[1], "-g", 2) == 0) { - CmdrevengSearch(argv[2]); - } else { - reveng_main(argc, argv); - } - for(int i = 0; i < argc; ++i) { - free(argv[i]); - } - return 0; + if (argc == 3 && memcmp(argv[1], "-g", 2) == 0) { + CmdrevengSearch(argv[2]); + } else { + reveng_main(argc, argv); + } + for(int i = 0; i < argc; ++i) { + free(argv[i]); + } + return 0; } //returns array of model names and the count of models returning // as well as a width array for the width of each model int GetModels(char *Models[], int *count, uint8_t *width){ - /* default values */ - static model_t model = MZERO; + /* default values */ + static model_t model = MZERO; - int ibperhx = 8;//, obperhx = 8; - int rflags = 0, uflags = 0; /* search and UI flags */ - poly_t apoly, crc, qpoly = PZERO, *apolys = NULL, *pptr = NULL, *qptr = NULL; - model_t pset = model, *candmods, *mptr; + int ibperhx = 8;//, obperhx = 8; + int rflags = 0, uflags = 0; /* search and UI flags */ + poly_t apoly, crc, qpoly = PZERO, *apolys = NULL, *pptr = NULL, *qptr = NULL; + model_t pset = model, *candmods, *mptr; - /* stdin must be binary */ - #ifdef _WIN32 - _setmode(STDIN_FILENO, _O_BINARY); - #endif /* _WIN32 */ + /* stdin must be binary */ + #ifdef _WIN32 + _setmode(STDIN_FILENO, _O_BINARY); + #endif /* _WIN32 */ - SETBMP(); + SETBMP(); - int args = 0, psets, pass; - int Cnt = 0; - if (width[0] == 0) { //reveng -D - *count = mcount(); - if (!*count){ - PrintAndLogEx(WARNING, "no preset models available"); - return 0; - } - for (int mode = 0; mode < *count; ++mode) { - mbynum(&model, mode); - mcanon(&model); - size_t size = (model.name && *model.name) ? strlen(model.name) : 7; - char *tmp = calloc(size+1, sizeof(char)); - if (tmp==NULL){ - PrintAndLogEx(WARNING, "out of memory?"); - return 0; - } - memcpy(tmp, model.name, size); - Models[mode] = tmp; - width[mode] = plen(model.spoly); - } - mfree(&model); - } else { //reveng -s + int args = 0, psets, pass; + int Cnt = 0; + if (width[0] == 0) { //reveng -D + *count = mcount(); + if (!*count){ + PrintAndLogEx(WARNING, "no preset models available"); + return 0; + } + for (int mode = 0; mode < *count; ++mode) { + mbynum(&model, mode); + mcanon(&model); + size_t size = (model.name && *model.name) ? strlen(model.name) : 7; + char *tmp = calloc(size+1, sizeof(char)); + if (tmp==NULL){ + PrintAndLogEx(WARNING, "out of memory?"); + return 0; + } + memcpy(tmp, model.name, size); + Models[mode] = tmp; + width[mode] = plen(model.spoly); + } + mfree(&model); + } else { //reveng -s - if (~model.flags & P_MULXN){ - PrintAndLogEx(WARNING, "cannot search for non-Williams compliant models"); - return 0; - } - praloc(&model.spoly, (unsigned long)width[0]); - praloc(&model.init, (unsigned long)width[0]); - praloc(&model.xorout, (unsigned long)width[0]); + if (~model.flags & P_MULXN){ + PrintAndLogEx(WARNING, "cannot search for non-Williams compliant models"); + return 0; + } + praloc(&model.spoly, (unsigned long)width[0]); + praloc(&model.init, (unsigned long)width[0]); + praloc(&model.xorout, (unsigned long)width[0]); - if (!plen(model.spoly)) - palloc(&model.spoly, (unsigned long)width[0]); - else - width[0] = (uint8_t)plen(model.spoly); + if (!plen(model.spoly)) + palloc(&model.spoly, (unsigned long)width[0]); + else + width[0] = (uint8_t)plen(model.spoly); - /* special case if qpoly is zero, search to end of range */ - if (!ptst(qpoly)) - rflags &= ~R_HAVEQ; + /* special case if qpoly is zero, search to end of range */ + if (!ptst(qpoly)) + rflags &= ~R_HAVEQ; - /* if endianness not specified, try - * little-endian then big-endian. - * NB: crossed-endian algorithms will not be - * searched. - */ - /* scan against preset models */ - if (~uflags & C_NOPCK) { - pass = 0; - Cnt = 0; - do { - psets = mcount(); + /* if endianness not specified, try + * little-endian then big-endian. + * NB: crossed-endian algorithms will not be + * searched. + */ + /* scan against preset models */ + if (~uflags & C_NOPCK) { + pass = 0; + Cnt = 0; + do { + psets = mcount(); - while (psets) { - mbynum(&pset, --psets); + while (psets) { + mbynum(&pset, --psets); - /* skip if different width, or refin or refout don't match */ - if( plen(pset.spoly) != width[0] || (model.flags ^ pset.flags) & (P_REFIN | P_REFOUT)) - continue; - /* skip if the preset doesn't match specified parameters */ - if (rflags & R_HAVEP && pcmp(&model.spoly, &pset.spoly)) - continue; - if (rflags & R_HAVEI && psncmp(&model.init, &pset.init)) - continue; - if (rflags & R_HAVEX && psncmp(&model.xorout, &pset.xorout)) - continue; + /* skip if different width, or refin or refout don't match */ + if( plen(pset.spoly) != width[0] || (model.flags ^ pset.flags) & (P_REFIN | P_REFOUT)) + continue; + /* skip if the preset doesn't match specified parameters */ + if (rflags & R_HAVEP && pcmp(&model.spoly, &pset.spoly)) + continue; + if (rflags & R_HAVEI && psncmp(&model.init, &pset.init)) + continue; + if (rflags & R_HAVEX && psncmp(&model.xorout, &pset.xorout)) + continue; - //for additional args (not used yet, maybe future?) - apoly = pclone(pset.xorout); + //for additional args (not used yet, maybe future?) + apoly = pclone(pset.xorout); - if (pset.flags & P_REFOUT) - prev(&apoly); + if (pset.flags & P_REFOUT) + prev(&apoly); - for (qptr = apolys; qptr < pptr; ++qptr) { - crc = pcrc(*qptr, pset.spoly, pset.init, apoly, 0); - if (ptst(crc)) { - pfree(&crc); - break; - } - pfree(&crc); - } - pfree(&apoly); + for (qptr = apolys; qptr < pptr; ++qptr) { + crc = pcrc(*qptr, pset.spoly, pset.init, apoly, 0); + if (ptst(crc)) { + pfree(&crc); + break; + } + pfree(&crc); + } + pfree(&apoly); - if (qptr == pptr) { + if (qptr == pptr) { - /* the selected model solved all arguments */ - mcanon(&pset); + /* the selected model solved all arguments */ + mcanon(&pset); - size_t size = (pset.name && *pset.name) ? strlen(pset.name) : 7; - //PrintAndLogEx(NORMAL, "Size: %d, %s, count: %d",size,pset.name, Cnt); - char *tmp = calloc(size+1, sizeof(char)); - if (tmp == NULL){ - PrintAndLogEx(WARNING, "out of memory?"); - return 0; - } - width[Cnt] = width[0]; - memcpy(tmp, pset.name, size); - Models[Cnt++] = tmp; - *count = Cnt; - uflags |= C_RESULT; - } - } - mfree(&pset); + size_t size = (pset.name && *pset.name) ? strlen(pset.name) : 7; + //PrintAndLogEx(NORMAL, "Size: %d, %s, count: %d",size,pset.name, Cnt); + char *tmp = calloc(size+1, sizeof(char)); + if (tmp == NULL){ + PrintAndLogEx(WARNING, "out of memory?"); + return 0; + } + width[Cnt] = width[0]; + memcpy(tmp, pset.name, size); + Models[Cnt++] = tmp; + *count = Cnt; + uflags |= C_RESULT; + } + } + mfree(&pset); - /* toggle refIn/refOut and reflect arguments */ - if (~rflags & R_HAVERI) { - model.flags ^= P_REFIN | P_REFOUT; - for (qptr = apolys; qptr < pptr; ++qptr) { - prevch(qptr, ibperhx); - } - } - } while (~rflags & R_HAVERI && ++pass < 2); - } - //got everything now free the memory... + /* toggle refIn/refOut and reflect arguments */ + if (~rflags & R_HAVERI) { + model.flags ^= P_REFIN | P_REFOUT; + for (qptr = apolys; qptr < pptr; ++qptr) { + prevch(qptr, ibperhx); + } + } + } while (~rflags & R_HAVERI && ++pass < 2); + } + //got everything now free the memory... - if (uflags & C_RESULT) { - for (qptr = apolys; qptr < pptr; ++qptr) { - pfree(qptr); - } - } - if(uflags & C_NOBFS && ~rflags & R_HAVEP) { - PrintAndLogEx(WARNING, "no models found"); - return 0; - } + if (uflags & C_RESULT) { + for (qptr = apolys; qptr < pptr; ++qptr) { + pfree(qptr); + } + } + if(uflags & C_NOBFS && ~rflags & R_HAVEP) { + PrintAndLogEx(WARNING, "no models found"); + return 0; + } - if (!(model.flags & P_REFIN) != !(model.flags & P_REFOUT)){ - PrintAndLogEx(WARNING, "cannot search for crossed-endian models"); - return 0; - } - pass = 0; - do { - mptr = candmods = reveng(&model, qpoly, rflags, args, apolys); - if (mptr && plen(mptr->spoly)) { - uflags |= C_RESULT; - } - while (mptr && plen(mptr->spoly)) { - mfree(mptr++); - } - free(candmods); - if (~rflags & R_HAVERI) { - model.flags ^= P_REFIN | P_REFOUT; - for (qptr = apolys; qptr < pptr; ++qptr) { - prevch(qptr, ibperhx); - } - } - } while (~rflags & R_HAVERI && ++pass < 2); + if (!(model.flags & P_REFIN) != !(model.flags & P_REFOUT)){ + PrintAndLogEx(WARNING, "cannot search for crossed-endian models"); + return 0; + } + pass = 0; + do { + mptr = candmods = reveng(&model, qpoly, rflags, args, apolys); + if (mptr && plen(mptr->spoly)) { + uflags |= C_RESULT; + } + while (mptr && plen(mptr->spoly)) { + mfree(mptr++); + } + free(candmods); + if (~rflags & R_HAVERI) { + model.flags ^= P_REFIN | P_REFOUT; + for (qptr = apolys; qptr < pptr; ++qptr) { + prevch(qptr, ibperhx); + } + } + } while (~rflags & R_HAVERI && ++pass < 2); - for (qptr = apolys; qptr < pptr; ++qptr) { - pfree(qptr); - } - free(apolys); - mfree(&model); + for (qptr = apolys; qptr < pptr; ++qptr) { + pfree(qptr); + } + free(apolys); + mfree(&model); - if (~uflags & C_RESULT){ - PrintAndLogEx(WARNING, "no models found"); - return 0; - } - } - return 1; + if (~uflags & C_RESULT){ + PrintAndLogEx(WARNING, "no models found"); + return 0; + } + } + return 1; } //-c || -v @@ -246,156 +246,156 @@ int GetModels(char *Models[], int *count, uint8_t *width){ // l = little endian input and output, L = little endian output only, t = left justified} //result = calculated crc hex string int RunModel(char *inModel, char *inHexStr, bool reverse, char endian, char *result){ - /* default values */ - static model_t model = MZERO; + /* default values */ + static model_t model = MZERO; - int ibperhx = 8, obperhx = 8; - int rflags = 0; // search flags - int c; - poly_t apoly, crc; + int ibperhx = 8, obperhx = 8; + int rflags = 0; // search flags + int c; + poly_t apoly, crc; - char *string; + char *string; - // stdin must be binary - #ifdef _WIN32 - _setmode(STDIN_FILENO, _O_BINARY); - #endif /* _WIN32 */ + // stdin must be binary + #ifdef _WIN32 + _setmode(STDIN_FILENO, _O_BINARY); + #endif /* _WIN32 */ - SETBMP(); - //set model - c = mbynam(&model, inModel); - if (!c) { - PrintAndLogEx(WARNING, "error: preset model '%s' not found. Use reveng -D to list presets. [%d]", inModel, c); - return 0; - } - if (c < 0){ - PrintAndLogEx(WARNING, "no preset models available"); - return 0; - } - rflags |= R_HAVEP | R_HAVEI | R_HAVERI | R_HAVERO | R_HAVEX; + SETBMP(); + //set model + c = mbynam(&model, inModel); + if (!c) { + PrintAndLogEx(WARNING, "error: preset model '%s' not found. Use reveng -D to list presets. [%d]", inModel, c); + return 0; + } + if (c < 0){ + PrintAndLogEx(WARNING, "no preset models available"); + return 0; + } + rflags |= R_HAVEP | R_HAVEI | R_HAVERI | R_HAVERO | R_HAVEX; - //set flags - switch (endian) { - case 'b': /* b big-endian (RefIn = false, RefOut = false ) */ - model.flags &= ~P_REFIN; - rflags |= R_HAVERI; - /* fall through: */ - case 'B': /* B big-endian output (RefOut = false) */ - model.flags &= ~P_REFOUT; - rflags |= R_HAVERO; - mnovel(&model); - /* fall through: */ - case 'r': /* r right-justified */ - model.flags |= P_RTJUST; - break; - case 'l': /* l little-endian input and output */ - model.flags |= P_REFIN; - rflags |= R_HAVERI; - /* fall through: */ - case 'L': /* L little-endian output */ - model.flags |= P_REFOUT; - rflags |= R_HAVERO; - mnovel(&model); - /* fall through: */ - case 't': /* t left-justified */ - model.flags &= ~P_RTJUST; - break; - } - /* canonicalise the model, so the one we dump is the one we - * calculate with (not with -s, spoly may be blank which will - * normalise to zero and clear init and xorout.) - */ - mcanon(&model); + //set flags + switch (endian) { + case 'b': /* b big-endian (RefIn = false, RefOut = false ) */ + model.flags &= ~P_REFIN; + rflags |= R_HAVERI; + /* fall through: */ + case 'B': /* B big-endian output (RefOut = false) */ + model.flags &= ~P_REFOUT; + rflags |= R_HAVERO; + mnovel(&model); + /* fall through: */ + case 'r': /* r right-justified */ + model.flags |= P_RTJUST; + break; + case 'l': /* l little-endian input and output */ + model.flags |= P_REFIN; + rflags |= R_HAVERI; + /* fall through: */ + case 'L': /* L little-endian output */ + model.flags |= P_REFOUT; + rflags |= R_HAVERO; + mnovel(&model); + /* fall through: */ + case 't': /* t left-justified */ + model.flags &= ~P_RTJUST; + break; + } + /* canonicalise the model, so the one we dump is the one we + * calculate with (not with -s, spoly may be blank which will + * normalise to zero and clear init and xorout.) + */ + mcanon(&model); - if (reverse) { - // v calculate reversed CRC - /* Distinct from the -V switch as this causes - * the arguments and output to be reversed as well. - */ - // reciprocate Poly - prcp(&model.spoly); + if (reverse) { + // v calculate reversed CRC + /* Distinct from the -V switch as this causes + * the arguments and output to be reversed as well. + */ + // reciprocate Poly + prcp(&model.spoly); - /* mrev() does: - * if(refout) prev(init); else prev(xorout); - * but here the entire argument polynomial is - * reflected, not just the characters, so RefIn - * and RefOut are not inverted as with -V. - * Consequently Init is the mirror image of the - * one resulting from -V, and so we have: - */ - if (~model.flags & P_REFOUT) { - prev(&model.init); - prev(&model.xorout); - } + /* mrev() does: + * if(refout) prev(init); else prev(xorout); + * but here the entire argument polynomial is + * reflected, not just the characters, so RefIn + * and RefOut are not inverted as with -V. + * Consequently Init is the mirror image of the + * one resulting from -V, and so we have: + */ + if (~model.flags & P_REFOUT) { + prev(&model.init); + prev(&model.xorout); + } - // swap init and xorout - apoly = model.init; - model.init = model.xorout; - model.xorout = apoly; - } - // c calculate CRC + // swap init and xorout + apoly = model.init; + model.init = model.xorout; + model.xorout = apoly; + } + // c calculate CRC - /* in the Williams model, xorout is applied after the refout stage. - * as refout is part of ptostr(), we reverse xorout here. - */ - if (model.flags & P_REFOUT) - prev(&model.xorout); + /* in the Williams model, xorout is applied after the refout stage. + * as refout is part of ptostr(), we reverse xorout here. + */ + if (model.flags & P_REFOUT) + prev(&model.xorout); - apoly = strtop(inHexStr, model.flags, ibperhx); + apoly = strtop(inHexStr, model.flags, ibperhx); - if (reverse) - prev(&apoly); + if (reverse) + prev(&apoly); - crc = pcrc(apoly, model.spoly, model.init, model.xorout, model.flags); + crc = pcrc(apoly, model.spoly, model.init, model.xorout, model.flags); - if (reverse) - prev(&crc); + if (reverse) + prev(&crc); - string = ptostr(crc, model.flags, obperhx); - for (int i = 0; i < 50; i++){ - result[i] = string[i]; - if (result[i]==0) break; - } - free(string); - pfree(&crc); - pfree(&apoly); - return 1; + string = ptostr(crc, model.flags, obperhx); + for (int i = 0; i < 50; i++){ + result[i] = string[i]; + if (result[i]==0) break; + } + free(string); + pfree(&crc); + pfree(&apoly); + return 1; } //test call to RunModel int CmdrevengTestC(const char *Cmd){ - int cmdp = 0; - char inModel[30] = {0x00}; - char inHexStr[30] = {0x00}; - char result[30]; - int dataLen; - char endian = 0; - dataLen = param_getstr(Cmd, cmdp++, inModel, sizeof(inModel)); - if (dataLen < 4) return 0; - dataLen = param_getstr(Cmd, cmdp++, inHexStr, sizeof(inHexStr)); - if (dataLen < 4) return 0; - bool reverse = (param_get8(Cmd, cmdp++)) ? true : false; - endian = param_getchar(Cmd, cmdp++); + int cmdp = 0; + char inModel[30] = {0x00}; + char inHexStr[30] = {0x00}; + char result[30]; + int dataLen; + char endian = 0; + dataLen = param_getstr(Cmd, cmdp++, inModel, sizeof(inModel)); + if (dataLen < 4) return 0; + dataLen = param_getstr(Cmd, cmdp++, inHexStr, sizeof(inHexStr)); + if (dataLen < 4) return 0; + bool reverse = (param_get8(Cmd, cmdp++)) ? true : false; + endian = param_getchar(Cmd, cmdp++); - //PrintAndLogEx(NORMAL, "mod: %s, hex: %s, rev %d", inModel, inHexStr, reverse); - int ans = RunModel(inModel, inHexStr, reverse, endian, result); - if (!ans) return 0; + //PrintAndLogEx(NORMAL, "mod: %s, hex: %s, rev %d", inModel, inHexStr, reverse); + int ans = RunModel(inModel, inHexStr, reverse, endian, result); + if (!ans) return 0; - PrintAndLogEx(SUCCESS, "result: %s",result); - return 1; + PrintAndLogEx(SUCCESS, "result: %s",result); + return 1; } //returns a calloced string (needs to be freed) char *SwapEndianStr(const char *inStr, const size_t len, const uint8_t blockSize){ - char *tmp = calloc(len+1, sizeof(char)); - for (uint8_t block=0; block < (uint8_t)(len/blockSize); block++){ - for (size_t i = 0; i < blockSize; i+=2){ - tmp[i+(blockSize*block)] = inStr[(blockSize-1-i-1)+(blockSize*block)]; - tmp[i+(blockSize*block)+1] = inStr[(blockSize-1-i)+(blockSize*block)]; - } - } - return tmp; + char *tmp = calloc(len+1, sizeof(char)); + for (uint8_t block=0; block < (uint8_t)(len/blockSize); block++){ + for (size_t i = 0; i < blockSize; i+=2){ + tmp[i+(blockSize*block)] = inStr[(blockSize-1-i-1)+(blockSize*block)]; + tmp[i+(blockSize*block)+1] = inStr[(blockSize-1-i)+(blockSize*block)]; + } + } + return tmp; } // takes hex string in and searches for a matching result (hex string must include checksum) @@ -403,84 +403,84 @@ int CmdrevengSearch(const char *Cmd){ #define NMODELS 105 - char inHexStr[100] = {0x00}; - int dataLen = param_getstr(Cmd, 0, inHexStr, sizeof(inHexStr)); - if (dataLen < 4) return 0; + char inHexStr[100] = {0x00}; + int dataLen = param_getstr(Cmd, 0, inHexStr, sizeof(inHexStr)); + if (dataLen < 4) return 0; - // these two arrays, must match preset size. - char *Models[NMODELS]; - uint8_t width[NMODELS] = {0}; - int count = 0; + // these two arrays, must match preset size. + char *Models[NMODELS]; + uint8_t width[NMODELS] = {0}; + int count = 0; - uint8_t crcChars = 0; - char result[30]; - char revResult[30]; - int ans = GetModels(Models, &count, width); - bool found = false; - if (!ans) return 0; + uint8_t crcChars = 0; + char result[30]; + char revResult[30]; + int ans = GetModels(Models, &count, width); + bool found = false; + if (!ans) return 0; - // try each model and get result - for (int i = 0; i < count; i++){ - /*if (found) { - free(Models[i]); - continue; - }*/ - // round up to # of characters in this model's crc - crcChars = ((width[i]+7)/8)*2; - // can't test a model that has more crc digits than our data - if (crcChars >= dataLen) - continue; - memset(result, 0, 30); - char *inCRC = calloc(crcChars+1, sizeof(char)); - memcpy(inCRC, inHexStr+(dataLen-crcChars), crcChars); + // try each model and get result + for (int i = 0; i < count; i++){ + /*if (found) { + free(Models[i]); + continue; + }*/ + // round up to # of characters in this model's crc + crcChars = ((width[i]+7)/8)*2; + // can't test a model that has more crc digits than our data + if (crcChars >= dataLen) + continue; + memset(result, 0, 30); + char *inCRC = calloc(crcChars+1, sizeof(char)); + memcpy(inCRC, inHexStr+(dataLen-crcChars), crcChars); - char *outHex = calloc(dataLen-crcChars+1, sizeof(char)); - memcpy(outHex, inHexStr, dataLen-crcChars); + char *outHex = calloc(dataLen-crcChars+1, sizeof(char)); + memcpy(outHex, inHexStr, dataLen-crcChars); - PrintAndLogEx(DEBUG, "DEBUG: dataLen: %d, crcChars: %d, Model: %s, CRC: %s, width: %d, outHex: %s",dataLen, crcChars, Models[i], inCRC, width[i], outHex); - ans = RunModel(Models[i], outHex, false, 0, result); - if (ans) { - // test for match - if (memcmp(result, inCRC, crcChars) == 0){ - PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel: %s | value: %s\n", Models[i], result); - //optional - stop searching if found... - found = true; - } else { - if (crcChars > 2){ - char *swapEndian = SwapEndianStr(result, crcChars, crcChars); - if (memcmp(swapEndian, inCRC, crcChars) == 0){ - PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel: %s | value endian swapped: %s\n", Models[i], swapEndian); - // optional - stop searching if found... - found = true; - } - free(swapEndian); - } - } - } - ans = RunModel(Models[i], outHex, true, 0, revResult); - if (ans) { - // test for match - if (memcmp(revResult, inCRC, crcChars) == 0){ - PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel reversed: %s | value: %s\n", Models[i], revResult); - // optional - stop searching if found... - found = true; - } else { - if (crcChars > 2){ - char *swapEndian = SwapEndianStr(revResult, crcChars, crcChars); - if (memcmp(swapEndian, inCRC, crcChars) == 0){ - PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel reversed: %s | value endian swapped: %s\n", Models[i], swapEndian); - // optional - stop searching if found... - found = true; - } - free(swapEndian); - } - } - } - free(inCRC); - free(outHex); - free(Models[i]); - } + PrintAndLogEx(DEBUG, "DEBUG: dataLen: %d, crcChars: %d, Model: %s, CRC: %s, width: %d, outHex: %s",dataLen, crcChars, Models[i], inCRC, width[i], outHex); + ans = RunModel(Models[i], outHex, false, 0, result); + if (ans) { + // test for match + if (memcmp(result, inCRC, crcChars) == 0){ + PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel: %s | value: %s\n", Models[i], result); + //optional - stop searching if found... + found = true; + } else { + if (crcChars > 2){ + char *swapEndian = SwapEndianStr(result, crcChars, crcChars); + if (memcmp(swapEndian, inCRC, crcChars) == 0){ + PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel: %s | value endian swapped: %s\n", Models[i], swapEndian); + // optional - stop searching if found... + found = true; + } + free(swapEndian); + } + } + } + ans = RunModel(Models[i], outHex, true, 0, revResult); + if (ans) { + // test for match + if (memcmp(revResult, inCRC, crcChars) == 0){ + PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel reversed: %s | value: %s\n", Models[i], revResult); + // optional - stop searching if found... + found = true; + } else { + if (crcChars > 2){ + char *swapEndian = SwapEndianStr(revResult, crcChars, crcChars); + if (memcmp(swapEndian, inCRC, crcChars) == 0){ + PrintAndLogEx(SUCCESS, "\nfound possible match\nmodel reversed: %s | value endian swapped: %s\n", Models[i], swapEndian); + // optional - stop searching if found... + found = true; + } + free(swapEndian); + } + } + } + free(inCRC); + free(outHex); + free(Models[i]); + } - if (!found) PrintAndLogEx(FAILED, "\nno matches found\n"); - return 1; + if (!found) PrintAndLogEx(FAILED, "\nno matches found\n"); + return 1; } \ No newline at end of file diff --git a/client/cmddata.c b/client/cmddata.c index 45bce9c9c..9753701e5 100644 --- a/client/cmddata.c +++ b/client/cmddata.c @@ -18,267 +18,267 @@ int g_DemodClock = 0; static int CmdHelp(const char *Cmd); int usage_data_printdemodbuf(void){ - PrintAndLogEx(NORMAL, "Usage: data printdemodbuffer x o l "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " x output in hex (omit for binary output)"); - PrintAndLogEx(NORMAL, " o enter offset in # of bits"); - PrintAndLogEx(NORMAL, " l enter length to print in # of bits or hex characters respectively"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data printdemodbuffer x o l "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " x output in hex (omit for binary output)"); + PrintAndLogEx(NORMAL, " o enter offset in # of bits"); + PrintAndLogEx(NORMAL, " l enter length to print in # of bits or hex characters respectively"); + return 0; } int usage_data_manrawdecode(void){ - PrintAndLogEx(NORMAL, "Usage: data manrawdecode [invert] [maxErr]"); - PrintAndLogEx(NORMAL, " Takes 10 and 01 and converts to 0 and 1 respectively"); - PrintAndLogEx(NORMAL, " --must have binary sequence in demodbuffer (run data askrawdemod first)"); - PrintAndLogEx(NORMAL, " [invert] invert output"); - PrintAndLogEx(NORMAL, " [maxErr] set number of errors allowed (default = 20)"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data manrawdecode = decode manchester bitstream from the demodbuffer"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data manrawdecode [invert] [maxErr]"); + PrintAndLogEx(NORMAL, " Takes 10 and 01 and converts to 0 and 1 respectively"); + PrintAndLogEx(NORMAL, " --must have binary sequence in demodbuffer (run data askrawdemod first)"); + PrintAndLogEx(NORMAL, " [invert] invert output"); + PrintAndLogEx(NORMAL, " [maxErr] set number of errors allowed (default = 20)"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data manrawdecode = decode manchester bitstream from the demodbuffer"); + return 0; } int usage_data_biphaserawdecode(void){ - PrintAndLogEx(NORMAL, "Usage: data biphaserawdecode [offset] [invert] [maxErr]"); - PrintAndLogEx(NORMAL, " Converts 10 or 01 to 1 and 11 or 00 to 0"); - PrintAndLogEx(NORMAL, " --must have binary sequence in demodbuffer (run data askrawdemod first)"); - PrintAndLogEx(NORMAL, " --invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " [offset <0|1>], set to 0 not to adjust start position or to 1 to adjust decode start position"); - PrintAndLogEx(NORMAL, " [invert <0|1>], set to 1 to invert output"); - PrintAndLogEx(NORMAL, " [maxErr int], set max errors tolerated - default=20"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data biphaserawdecode = decode biphase bitstream from the demodbuffer"); - PrintAndLogEx(NORMAL, " Example: data biphaserawdecode 1 1 = decode biphase bitstream from the demodbuffer, set offset, and invert output"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data biphaserawdecode [offset] [invert] [maxErr]"); + PrintAndLogEx(NORMAL, " Converts 10 or 01 to 1 and 11 or 00 to 0"); + PrintAndLogEx(NORMAL, " --must have binary sequence in demodbuffer (run data askrawdemod first)"); + PrintAndLogEx(NORMAL, " --invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " [offset <0|1>], set to 0 not to adjust start position or to 1 to adjust decode start position"); + PrintAndLogEx(NORMAL, " [invert <0|1>], set to 1 to invert output"); + PrintAndLogEx(NORMAL, " [maxErr int], set max errors tolerated - default=20"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data biphaserawdecode = decode biphase bitstream from the demodbuffer"); + PrintAndLogEx(NORMAL, " Example: data biphaserawdecode 1 1 = decode biphase bitstream from the demodbuffer, set offset, and invert output"); + return 0; } int usage_data_rawdemod(void){ - PrintAndLogEx(NORMAL, "Usage: data rawdemod [modulation] |"); - PrintAndLogEx(NORMAL, " [modulation] as 2 char, 'ab' for ask/biphase, 'am' for ask/manchester, 'ar' for ask/raw, 'fs' for fsk, ..."); - PrintAndLogEx(NORMAL, " 'nr' for nrz/direct, 'p1' for psk1, 'p2' for psk2"); - PrintAndLogEx(NORMAL, " as 'h', prints the help for the specific modulation"); - PrintAndLogEx(NORMAL, " see specific modulation help for optional parameters"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod fs h = print help specific to fsk demod"); - PrintAndLogEx(NORMAL, " : data rawdemod fs = demod GraphBuffer using: fsk - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod ab = demod GraphBuffer using: ask/biphase - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod am = demod GraphBuffer using: ask/manchester - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod ar = demod GraphBuffer using: ask/raw - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod nr = demod GraphBuffer using: nrz/direct - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod p1 = demod GraphBuffer using: psk1 - autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod p2 = demod GraphBuffer using: psk2 - autodetect"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data rawdemod [modulation] |"); + PrintAndLogEx(NORMAL, " [modulation] as 2 char, 'ab' for ask/biphase, 'am' for ask/manchester, 'ar' for ask/raw, 'fs' for fsk, ..."); + PrintAndLogEx(NORMAL, " 'nr' for nrz/direct, 'p1' for psk1, 'p2' for psk2"); + PrintAndLogEx(NORMAL, " as 'h', prints the help for the specific modulation"); + PrintAndLogEx(NORMAL, " see specific modulation help for optional parameters"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data rawdemod fs h = print help specific to fsk demod"); + PrintAndLogEx(NORMAL, " : data rawdemod fs = demod GraphBuffer using: fsk - autodetect"); + PrintAndLogEx(NORMAL, " : data rawdemod ab = demod GraphBuffer using: ask/biphase - autodetect"); + PrintAndLogEx(NORMAL, " : data rawdemod am = demod GraphBuffer using: ask/manchester - autodetect"); + PrintAndLogEx(NORMAL, " : data rawdemod ar = demod GraphBuffer using: ask/raw - autodetect"); + PrintAndLogEx(NORMAL, " : data rawdemod nr = demod GraphBuffer using: nrz/direct - autodetect"); + PrintAndLogEx(NORMAL, " : data rawdemod p1 = demod GraphBuffer using: psk1 - autodetect"); + PrintAndLogEx(NORMAL, " : data rawdemod p2 = demod GraphBuffer using: psk2 - autodetect"); + return 0; } int usage_data_rawdemod_am(void){ - PrintAndLogEx(NORMAL, "Usage: data rawdemod am [clock] [maxError] [maxLen] [amplify]"); - PrintAndLogEx(NORMAL, " ['s'] optional, check for Sequence Terminator"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect"); - PrintAndLogEx(NORMAL, " , 1 to invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100"); - PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (512 bits at rf/64)"); - PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod am = demod an ask/manchester tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod am 32 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod am 32 1 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod am 1 = demod an ask/manchester tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod am 64 1 0 = demod an ask/manchester tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data rawdemod am [clock] [maxError] [maxLen] [amplify]"); + PrintAndLogEx(NORMAL, " ['s'] optional, check for Sequence Terminator"); + PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect"); + PrintAndLogEx(NORMAL, " , 1 to invert output"); + PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100"); + PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (512 bits at rf/64)"); + PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data rawdemod am = demod an ask/manchester tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " : data rawdemod am 32 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32"); + PrintAndLogEx(NORMAL, " : data rawdemod am 32 1 = demod an ask/manchester tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod am 1 = demod an ask/manchester tag from GraphBuffer while inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod am 64 1 0 = demod an ask/manchester tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + return 0; } int usage_data_rawdemod_ab(void){ - PrintAndLogEx(NORMAL, "Usage: data rawdemod ab [offset] [clock] [maxError] [maxLen] "); - PrintAndLogEx(NORMAL, " [offset], offset to begin biphase, default=0"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect"); - PrintAndLogEx(NORMAL, " , 1 to invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100"); - PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (512 bits at rf/64)"); - PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); - PrintAndLogEx(NORMAL, " NOTE: can be entered as second or third argument"); - PrintAndLogEx(NORMAL, " NOTE: can be entered as first, second or last argument"); - PrintAndLogEx(NORMAL, " NOTE: any other arg must have previous args set to work"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " NOTE: --invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod ab = demod an ask/biph tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 0 a = demod an ask/biph tag from GraphBuffer, amplified"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 1 32 = demod an ask/biph tag from GraphBuffer using an offset of 1 and a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 0 32 1 = demod an ask/biph tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 0 1 = demod an ask/biph tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 0 64 1 0 = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - PrintAndLogEx(NORMAL, " : data rawdemod ab 0 64 1 0 0 a = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data rawdemod ab [offset] [clock] [maxError] [maxLen] "); + PrintAndLogEx(NORMAL, " [offset], offset to begin biphase, default=0"); + PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect"); + PrintAndLogEx(NORMAL, " , 1 to invert output"); + PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100"); + PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (512 bits at rf/64)"); + PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); + PrintAndLogEx(NORMAL, " NOTE: can be entered as second or third argument"); + PrintAndLogEx(NORMAL, " NOTE: can be entered as first, second or last argument"); + PrintAndLogEx(NORMAL, " NOTE: any other arg must have previous args set to work"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " NOTE: --invert for Conditional Dephase Encoding (CDP) AKA Differential Manchester"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data rawdemod ab = demod an ask/biph tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " : data rawdemod ab 0 a = demod an ask/biph tag from GraphBuffer, amplified"); + PrintAndLogEx(NORMAL, " : data rawdemod ab 1 32 = demod an ask/biph tag from GraphBuffer using an offset of 1 and a clock of RF/32"); + PrintAndLogEx(NORMAL, " : data rawdemod ab 0 32 1 = demod an ask/biph tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod ab 0 1 = demod an ask/biph tag from GraphBuffer while inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod ab 0 64 1 0 = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + PrintAndLogEx(NORMAL, " : data rawdemod ab 0 64 1 0 0 a = demod an ask/biph tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); + return 0; } int usage_data_rawdemod_ar(void){ - PrintAndLogEx(NORMAL, "Usage: data rawdemod ar [clock] [maxError] [maxLen] [amplify]"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect"); - PrintAndLogEx(NORMAL, " , 1 to invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100"); - PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (1024 bits at rf/64)"); - PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod ar = demod an ask tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod ar a = demod an ask tag from GraphBuffer, amplified"); - PrintAndLogEx(NORMAL, " : data rawdemod ar 32 = demod an ask tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod ar 32 1 = demod an ask tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod ar 1 = demod an ask tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod ar 64 1 0 = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - PrintAndLogEx(NORMAL, " : data rawdemod ar 64 1 0 0 a = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data rawdemod ar [clock] [maxError] [maxLen] [amplify]"); + PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect"); + PrintAndLogEx(NORMAL, " , 1 to invert output"); + PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100"); + PrintAndLogEx(NORMAL, " [set maximum Samples to read], default = 32768 (1024 bits at rf/64)"); + PrintAndLogEx(NORMAL, " , 'a' to attempt demod with ask amplification, default = no amp"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data rawdemod ar = demod an ask tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " : data rawdemod ar a = demod an ask tag from GraphBuffer, amplified"); + PrintAndLogEx(NORMAL, " : data rawdemod ar 32 = demod an ask tag from GraphBuffer using a clock of RF/32"); + PrintAndLogEx(NORMAL, " : data rawdemod ar 32 1 = demod an ask tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod ar 1 = demod an ask tag from GraphBuffer while inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod ar 64 1 0 = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + PrintAndLogEx(NORMAL, " : data rawdemod ar 64 1 0 0 a = demod an ask tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors, and amp"); + return 0; } int usage_data_rawdemod_fs(void){ - PrintAndLogEx(NORMAL, "Usage: data rawdemod fs [clock] [fchigh] [fclow]"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, omit for autodetect."); - PrintAndLogEx(NORMAL, " , 1 for invert output, can be used even if the clock is omitted"); - PrintAndLogEx(NORMAL, " [fchigh], larger field clock length, omit for autodetect"); - PrintAndLogEx(NORMAL, " [fclow], small field clock length, omit for autodetect"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod fs = demod an fsk tag from GraphBuffer using autodetect"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 32 = demod an fsk tag from GraphBuffer using a clock of RF/32, autodetect fc"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 1 = demod an fsk tag from GraphBuffer using autodetect, invert output"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 32 1 = demod an fsk tag from GraphBuffer using a clock of RF/32, invert output, autodetect fc"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 64 0 8 5 = demod an fsk1 RF/64 tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 50 0 10 8 = demod an fsk2 RF/50 tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod fs 50 1 10 8 = demod an fsk2a RF/50 tag from GraphBuffer"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data rawdemod fs [clock] [fchigh] [fclow]"); + PrintAndLogEx(NORMAL, " [set clock as integer] optional, omit for autodetect."); + PrintAndLogEx(NORMAL, " , 1 for invert output, can be used even if the clock is omitted"); + PrintAndLogEx(NORMAL, " [fchigh], larger field clock length, omit for autodetect"); + PrintAndLogEx(NORMAL, " [fclow], small field clock length, omit for autodetect"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data rawdemod fs = demod an fsk tag from GraphBuffer using autodetect"); + PrintAndLogEx(NORMAL, " : data rawdemod fs 32 = demod an fsk tag from GraphBuffer using a clock of RF/32, autodetect fc"); + PrintAndLogEx(NORMAL, " : data rawdemod fs 1 = demod an fsk tag from GraphBuffer using autodetect, invert output"); + PrintAndLogEx(NORMAL, " : data rawdemod fs 32 1 = demod an fsk tag from GraphBuffer using a clock of RF/32, invert output, autodetect fc"); + PrintAndLogEx(NORMAL, " : data rawdemod fs 64 0 8 5 = demod an fsk1 RF/64 tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " : data rawdemod fs 50 0 10 8 = demod an fsk2 RF/50 tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " : data rawdemod fs 50 1 10 8 = demod an fsk2a RF/50 tag from GraphBuffer"); + return 0; } int usage_data_rawdemod_nr(void){ - PrintAndLogEx(NORMAL, "Usage: data rawdemod nr [clock] <0|1> [maxError]"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect."); - PrintAndLogEx(NORMAL, " , 1 for invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod nr = demod a nrz/direct tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod nr 32 = demod a nrz/direct tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod nr 32 1 = demod a nrz/direct tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod nr 1 = demod a nrz/direct tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod nr 64 1 0 = demod a nrz/direct tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data rawdemod nr [clock] <0|1> [maxError]"); + PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect."); + PrintAndLogEx(NORMAL, " , 1 for invert output"); + PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data rawdemod nr = demod a nrz/direct tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " : data rawdemod nr 32 = demod a nrz/direct tag from GraphBuffer using a clock of RF/32"); + PrintAndLogEx(NORMAL, " : data rawdemod nr 32 1 = demod a nrz/direct tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod nr 1 = demod a nrz/direct tag from GraphBuffer while inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod nr 64 1 0 = demod a nrz/direct tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + return 0; } int usage_data_rawdemod_p1(void){ - PrintAndLogEx(NORMAL, "Usage: data rawdemod p1 [clock] <0|1> [maxError]"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect."); - PrintAndLogEx(NORMAL, " , 1 for invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod p1 = demod a psk1 tag from GraphBuffer"); - PrintAndLogEx(NORMAL, " : data rawdemod p1 32 = demod a psk1 tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod p1 32 1 = demod a psk1 tag from GraphBuffer using a clock of RF/32 and inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod p1 1 = demod a psk1 tag from GraphBuffer while inverting data"); - PrintAndLogEx(NORMAL, " : data rawdemod p1 64 1 0 = demod a psk1 tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data rawdemod p1 [clock] <0|1> [maxError]"); + PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect."); + PrintAndLogEx(NORMAL, " , 1 for invert output"); + PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data rawdemod p1 = demod a psk1 tag from GraphBuffer"); + PrintAndLogEx(NORMAL, " : data rawdemod p1 32 = demod a psk1 tag from GraphBuffer using a clock of RF/32"); + PrintAndLogEx(NORMAL, " : data rawdemod p1 32 1 = demod a psk1 tag from GraphBuffer using a clock of RF/32 and inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod p1 1 = demod a psk1 tag from GraphBuffer while inverting data"); + PrintAndLogEx(NORMAL, " : data rawdemod p1 64 1 0 = demod a psk1 tag from GraphBuffer using a clock of RF/64, inverting data and allowing 0 demod errors"); + return 0; } int usage_data_rawdemod_p2(void){ - PrintAndLogEx(NORMAL, "Usage: data rawdemod p2 [clock] <0|1> [maxError]"); - PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect."); - PrintAndLogEx(NORMAL, " , 1 for invert output"); - PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data rawdemod p2 = demod a psk2 tag from GraphBuffer, autodetect clock"); - PrintAndLogEx(NORMAL, " : data rawdemod p2 32 = demod a psk2 tag from GraphBuffer using a clock of RF/32"); - PrintAndLogEx(NORMAL, " : data rawdemod p2 32 1 = demod a psk2 tag from GraphBuffer using a clock of RF/32 and inverting output"); - PrintAndLogEx(NORMAL, " : data rawdemod p2 1 = demod a psk2 tag from GraphBuffer, autodetect clock and invert output"); - PrintAndLogEx(NORMAL, " : data rawdemod p2 64 1 0 = demod a psk2 tag from GraphBuffer using a clock of RF/64, inverting output and allowing 0 demod errors"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data rawdemod p2 [clock] <0|1> [maxError]"); + PrintAndLogEx(NORMAL, " [set clock as integer] optional, if not set, autodetect."); + PrintAndLogEx(NORMAL, " , 1 for invert output"); + PrintAndLogEx(NORMAL, " [set maximum allowed errors], default = 100."); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data rawdemod p2 = demod a psk2 tag from GraphBuffer, autodetect clock"); + PrintAndLogEx(NORMAL, " : data rawdemod p2 32 = demod a psk2 tag from GraphBuffer using a clock of RF/32"); + PrintAndLogEx(NORMAL, " : data rawdemod p2 32 1 = demod a psk2 tag from GraphBuffer using a clock of RF/32 and inverting output"); + PrintAndLogEx(NORMAL, " : data rawdemod p2 1 = demod a psk2 tag from GraphBuffer, autodetect clock and invert output"); + PrintAndLogEx(NORMAL, " : data rawdemod p2 64 1 0 = demod a psk2 tag from GraphBuffer using a clock of RF/64, inverting output and allowing 0 demod errors"); + return 0; } int usage_data_autocorr(void) { - PrintAndLogEx(NORMAL, "Autocorrelate is used to detect repeating sequences. We use it as detection of length in bits a message inside the signal is"); - PrintAndLogEx(NORMAL, "Usage: data autocorr w [g]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " w window length for correlation - default = 4000"); - PrintAndLogEx(NORMAL, " g save back to GraphBuffer (overwrite)"); - return 0; + PrintAndLogEx(NORMAL, "Autocorrelate is used to detect repeating sequences. We use it as detection of length in bits a message inside the signal is"); + PrintAndLogEx(NORMAL, "Usage: data autocorr w [g]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " w window length for correlation - default = 4000"); + PrintAndLogEx(NORMAL, " g save back to GraphBuffer (overwrite)"); + return 0; } int usage_data_undecimate(void){ - PrintAndLogEx(NORMAL, "Usage: data undec [factor]"); - PrintAndLogEx(NORMAL, "This function performs un-decimation, by repeating each sample N times"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " factor The number of times to repeat each sample.[default:2]"); - PrintAndLogEx(NORMAL, "Example: 'data undec 3'"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data undec [factor]"); + PrintAndLogEx(NORMAL, "This function performs un-decimation, by repeating each sample N times"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " factor The number of times to repeat each sample.[default:2]"); + PrintAndLogEx(NORMAL, "Example: 'data undec 3'"); + return 0; } int usage_data_detectclock(void){ - PrintAndLogEx(NORMAL, "Usage: data detectclock [modulation] "); - PrintAndLogEx(NORMAL, " [modulation as char], specify the modulation type you want to detect the clock of"); - PrintAndLogEx(NORMAL, " , specify the clock (optional - to get best start position only)"); - PrintAndLogEx(NORMAL, " 'a' = ask, 'f' = fsk, 'n' = nrz/direct, 'p' = psk"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, " Example: data detectclock a = detect the clock of an ask modulated wave in the GraphBuffer"); - PrintAndLogEx(NORMAL, " data detectclock f = detect the clock of an fsk modulated wave in the GraphBuffer"); - PrintAndLogEx(NORMAL, " data detectclock p = detect the clock of an psk modulated wave in the GraphBuffer"); - PrintAndLogEx(NORMAL, " data detectclock n = detect the clock of an nrz/direct modulated wave in the GraphBuffer"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data detectclock [modulation] "); + PrintAndLogEx(NORMAL, " [modulation as char], specify the modulation type you want to detect the clock of"); + PrintAndLogEx(NORMAL, " , specify the clock (optional - to get best start position only)"); + PrintAndLogEx(NORMAL, " 'a' = ask, 'f' = fsk, 'n' = nrz/direct, 'p' = psk"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, " Example: data detectclock a = detect the clock of an ask modulated wave in the GraphBuffer"); + PrintAndLogEx(NORMAL, " data detectclock f = detect the clock of an fsk modulated wave in the GraphBuffer"); + PrintAndLogEx(NORMAL, " data detectclock p = detect the clock of an psk modulated wave in the GraphBuffer"); + PrintAndLogEx(NORMAL, " data detectclock n = detect the clock of an nrz/direct modulated wave in the GraphBuffer"); + return 0; } int usage_data_hex2bin(void){ - PrintAndLogEx(NORMAL, "Usage: data hex2bin "); - PrintAndLogEx(NORMAL, " This function will ignore all non-hexadecimal characters (but stop reading on whitespace)"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data hex2bin "); + PrintAndLogEx(NORMAL, " This function will ignore all non-hexadecimal characters (but stop reading on whitespace)"); + return 0; } int usage_data_bin2hex(void){ - PrintAndLogEx(NORMAL, "Usage: data bin2hex "); - PrintAndLogEx(NORMAL, " This function will ignore all characters not 1 or 0 (but stop reading on whitespace)"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data bin2hex "); + PrintAndLogEx(NORMAL, " This function will ignore all characters not 1 or 0 (but stop reading on whitespace)"); + return 0; } int usage_data_buffclear(void){ - PrintAndLogEx(NORMAL, "This function clears the bigbuff on deviceside"); - PrintAndLogEx(NORMAL, "Usage: data buffclear [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - return 0; + PrintAndLogEx(NORMAL, "This function clears the bigbuff on deviceside"); + PrintAndLogEx(NORMAL, "Usage: data buffclear [h]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + return 0; } int usage_data_fsktonrz() { - PrintAndLogEx(NORMAL, "Usage: data fsktonrz c l f "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h This help"); - PrintAndLogEx(NORMAL, " c enter the a clock (omit to autodetect)"); - PrintAndLogEx(NORMAL, " l enter a field clock (omit to autodetect)"); - PrintAndLogEx(NORMAL, " f enter a field clock (omit to autodetect)"); - return 0; + PrintAndLogEx(NORMAL, "Usage: data fsktonrz c l f "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h This help"); + PrintAndLogEx(NORMAL, " c enter the a clock (omit to autodetect)"); + PrintAndLogEx(NORMAL, " l enter a field clock (omit to autodetect)"); + PrintAndLogEx(NORMAL, " f enter a field clock (omit to autodetect)"); + return 0; } //set the demod buffer with given array of binary (one bit per byte) //by marshmellow void setDemodBuf(uint8_t *buf, size_t size, size_t start_idx) { - if (buf == NULL) return; + if (buf == NULL) return; - if ( size > MAX_DEMOD_BUF_LEN - start_idx) - size = MAX_DEMOD_BUF_LEN - start_idx; + if ( size > MAX_DEMOD_BUF_LEN - start_idx) + size = MAX_DEMOD_BUF_LEN - start_idx; - for (size_t i = 0; i < size; i++) - DemodBuffer[i] = buf[start_idx++]; + for (size_t i = 0; i < size; i++) + DemodBuffer[i] = buf[start_idx++]; - DemodBufferLen = size; + DemodBufferLen = size; } bool getDemodBuf(uint8_t *buf, size_t *size) { - if (buf == NULL) return false; - if (size == NULL) return false; - if (*size == 0) return false; + if (buf == NULL) return false; + if (size == NULL) return false; + if (*size == 0) return false; - *size = (*size > DemodBufferLen) ? DemodBufferLen : *size; + *size = (*size > DemodBufferLen) ? DemodBufferLen : *size; - memcpy(buf, DemodBuffer, *size); - return true; + memcpy(buf, DemodBuffer, *size); + return true; } // include // Root mean square double rms(double *v, size_t n) { - double sum = 0.0; - for(size_t i = 0; i < n; i++) - sum += v[i] * v[i]; - return sqrt(sum / n); + double sum = 0.0; + for(size_t i = 0; i < n; i++) + sum += v[i] * v[i]; + return sqrt(sum / n); } int cmp_int( const void *a, const void *b) { if (*(const int *)a < *(const int *)b) - return -1; + return -1; else - return *(const int *)a > *(const int *)b; + return *(const int *)a > *(const int *)b; } int cmp_uint8( const void *a, const void *b) { if (*(const uint8_t *)a < *(const uint8_t *)b) - return -1; + return -1; else - return *(const uint8_t *)a > *(const uint8_t *)b; + return *(const uint8_t *)a > *(const uint8_t *)b; } // Median of a array of values double median_int( int *src, size_t size ) { @@ -291,23 +291,23 @@ double median_uint8( uint8_t *src, size_t size ) { } // function to compute mean for a series static double compute_mean(const int *data, size_t n) { - double mean = 0.0; - for (size_t i=0; i < n; i++) - mean += data[i]; - mean /= n; - return mean; + double mean = 0.0; + for (size_t i=0; i < n; i++) + mean += data[i]; + mean /= n; + return mean; } // function to compute variance for a series static double compute_variance(const int *data, size_t n) { - double variance = 0.0; - double mean = compute_mean(data, n); + double variance = 0.0; + double mean = compute_mean(data, n); - for (size_t i=0; i < n; i++) - variance += pow(( data[i] - mean), 2.0); + for (size_t i=0; i < n; i++) + variance += pow(( data[i] - mean), 2.0); - variance /= n; - return variance; + variance /= n; + return variance; } // Function to compute autocorrelation for a series @@ -315,133 +315,133 @@ static double compute_variance(const int *data, size_t n) { // - Corrected divide by n to divide (n - lag) from Tobias Mueller /* static double compute_autoc(const int *data, size_t n, int lag) { - double autocv = 0.0; // Autocovariance value - double ac_value; // Computed autocorrelation value to be returned - double variance; // Computed variance - double mean; + double autocv = 0.0; // Autocovariance value + double ac_value; // Computed autocorrelation value to be returned + double variance; // Computed variance + double mean; - mean = compute_mean(data, n); - variance = compute_variance(data, n); + mean = compute_mean(data, n); + variance = compute_variance(data, n); - for (size_t i=0; i < (n - lag); i++) - autocv += (data[i] - mean) * (data[i+lag] - mean); + for (size_t i=0; i < (n - lag); i++) + autocv += (data[i] - mean) * (data[i+lag] - mean); - autocv = (1.0 / (n - lag)) * autocv; + autocv = (1.0 / (n - lag)) * autocv; - // Autocorrelation is autocovariance divided by variance - ac_value = autocv / variance; - return ac_value; + // Autocorrelation is autocovariance divided by variance + ac_value = autocv / variance; + return ac_value; } */ // option '1' to save DemodBuffer any other to restore void save_restoreDB(uint8_t saveOpt) { - static uint8_t SavedDB[MAX_DEMOD_BUF_LEN]; - static size_t SavedDBlen; - static bool DB_Saved = false; - static size_t savedDemodStartIdx = 0; - static int savedDemodClock = 0; + static uint8_t SavedDB[MAX_DEMOD_BUF_LEN]; + static size_t SavedDBlen; + static bool DB_Saved = false; + static size_t savedDemodStartIdx = 0; + static int savedDemodClock = 0; - if (saveOpt == GRAPH_SAVE) { //save + if (saveOpt == GRAPH_SAVE) { //save - memcpy(SavedDB, DemodBuffer, sizeof(DemodBuffer)); - SavedDBlen = DemodBufferLen; - DB_Saved = true; - savedDemodStartIdx = g_DemodStartIdx; - savedDemodClock = g_DemodClock; - } else if (DB_Saved) { //restore + memcpy(SavedDB, DemodBuffer, sizeof(DemodBuffer)); + SavedDBlen = DemodBufferLen; + DB_Saved = true; + savedDemodStartIdx = g_DemodStartIdx; + savedDemodClock = g_DemodClock; + } else if (DB_Saved) { //restore - memcpy(DemodBuffer, SavedDB, sizeof(DemodBuffer)); - DemodBufferLen = SavedDBlen; - g_DemodClock = savedDemodClock; - g_DemodStartIdx = savedDemodStartIdx; - } + memcpy(DemodBuffer, SavedDB, sizeof(DemodBuffer)); + DemodBufferLen = SavedDBlen; + g_DemodClock = savedDemodClock; + g_DemodStartIdx = savedDemodStartIdx; + } } int CmdSetDebugMode(const char *Cmd) { - int demod = 0; - sscanf(Cmd, "%i", &demod); - g_debugMode = (uint8_t)demod; - return 1; + int demod = 0; + sscanf(Cmd, "%i", &demod); + g_debugMode = (uint8_t)demod; + return 1; } //by marshmellow // max output to 512 bits if we have more - should be plenty void printDemodBuff(void) { - int len = DemodBufferLen; - if (len < 1) { - PrintAndLogEx(NORMAL, "(printDemodBuff) no bits found in demod buffer"); - return; - } - if (len > 512) len = 512; + int len = DemodBufferLen; + if (len < 1) { + PrintAndLogEx(NORMAL, "(printDemodBuff) no bits found in demod buffer"); + return; + } + if (len > 512) len = 512; - PrintAndLogEx(NORMAL, "%s", sprint_bin_break(DemodBuffer, len, 16) ); + PrintAndLogEx(NORMAL, "%s", sprint_bin_break(DemodBuffer, len, 16) ); } int CmdPrintDemodBuff(const char *Cmd) { - char hex[512] = {0x00}; - bool hexMode = false; - bool errors = false; - uint32_t offset = 0; - uint32_t length = 512; - char cmdp = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_data_printdemodbuf(); - case 'x': - hexMode = true; - cmdp++; - break; - case 'o': - offset = param_get32ex(Cmd, cmdp+1, 0, 10); - if (!offset) errors = true; - cmdp += 2; - break; - case 'l': - length = param_get32ex(Cmd, cmdp+1, 512, 10); - if (!length) errors = true; - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors) return usage_data_printdemodbuf(); + char hex[512] = {0x00}; + bool hexMode = false; + bool errors = false; + uint32_t offset = 0; + uint32_t length = 512; + char cmdp = 0; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_data_printdemodbuf(); + case 'x': + hexMode = true; + cmdp++; + break; + case 'o': + offset = param_get32ex(Cmd, cmdp+1, 0, 10); + if (!offset) errors = true; + cmdp += 2; + break; + case 'l': + length = param_get32ex(Cmd, cmdp+1, 512, 10); + if (!length) errors = true; + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + //Validations + if (errors) return usage_data_printdemodbuf(); - if (DemodBufferLen == 0) { - PrintAndLogEx(NORMAL, "Demodbuffer is empty"); - return 0; - } - length = (length > (DemodBufferLen-offset)) ? DemodBufferLen-offset : length; - int numBits = (length) & 0x00FFC; //make sure we don't exceed our string + if (DemodBufferLen == 0) { + PrintAndLogEx(NORMAL, "Demodbuffer is empty"); + return 0; + } + length = (length > (DemodBufferLen-offset)) ? DemodBufferLen-offset : length; + int numBits = (length) & 0x00FFC; //make sure we don't exceed our string - if (hexMode){ - char *buf = (char *) (DemodBuffer + offset); - numBits = (numBits > sizeof(hex)) ? sizeof(hex) : numBits; - numBits = binarraytohex(hex, buf, numBits); - if (numBits == 0) { - return 0; - } - PrintAndLogEx(NORMAL, "DemodBuffer: %s", hex); - } else { - PrintAndLogEx(NORMAL, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer+offset, numBits, 16)); - } - return 1; + if (hexMode){ + char *buf = (char *) (DemodBuffer + offset); + numBits = (numBits > sizeof(hex)) ? sizeof(hex) : numBits; + numBits = binarraytohex(hex, buf, numBits); + if (numBits == 0) { + return 0; + } + PrintAndLogEx(NORMAL, "DemodBuffer: %s", hex); + } else { + PrintAndLogEx(NORMAL, "DemodBuffer:\n%s", sprint_bin_break(DemodBuffer+offset, numBits, 16)); + } + return 1; } //by marshmellow //this function strictly converts >1 to 1 and <1 to 0 for each sample in the graphbuffer int CmdGetBitStream(const char *Cmd) { - CmdHpf(Cmd); - for (uint32_t i = 0; i < GraphTraceLen; i++) - GraphBuffer[i] = (GraphBuffer[i] >= 1) ? 1 : 0; + CmdHpf(Cmd); + for (uint32_t i = 0; i < GraphTraceLen; i++) + GraphBuffer[i] = (GraphBuffer[i] >= 1) ? 1 : 0; - RepaintGraphWindow(); - return 0; + RepaintGraphWindow(); + return 0; } //by marshmellow @@ -451,94 +451,94 @@ int CmdGetBitStream(const char *Cmd) { //emSearch will auto search for EM410x format in bitstream //askType switches decode: ask/raw = 0, ask/manchester = 1 int ASKDemod_ext(const char *Cmd, bool verbose, bool emSearch, uint8_t askType, bool *stCheck) { - int invert = 0; - int clk = 0; - int maxErr = 100; - int maxLen = 0; - uint8_t askamp = 0; - char amp = tolower(param_getchar(Cmd, 0)); - uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; + int invert = 0; + int clk = 0; + int maxErr = 100; + int maxLen = 0; + uint8_t askamp = 0; + char amp = tolower(param_getchar(Cmd, 0)); + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; - sscanf(Cmd, "%i %i %i %i %c", &clk, &invert, &maxErr, &maxLen, &); + sscanf(Cmd, "%i %i %i %i %c", &clk, &invert, &maxErr, &maxLen, &); - if (!maxLen) maxLen = BIGBUF_SIZE; + if (!maxLen) maxLen = BIGBUF_SIZE; - if (invert != 0 && invert != 1) { - PrintAndLogEx(WARNING, "Invalid argument: %s", Cmd); - return 0; - } + if (invert != 0 && invert != 1) { + PrintAndLogEx(WARNING, "Invalid argument: %s", Cmd); + return 0; + } - if (clk == 1) { - invert = 1; - clk = 0; - } + if (clk == 1) { + invert = 1; + clk = 0; + } - size_t BitLen = getFromGraphBuf(bits); + size_t BitLen = getFromGraphBuf(bits); - PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Bitlen from grphbuff: %d", BitLen); + PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Bitlen from grphbuff: %d", BitLen); - if (BitLen < 255) return 0; + if (BitLen < 255) return 0; - if (maxLen < BitLen && maxLen != 0) BitLen = maxLen; + if (maxLen < BitLen && maxLen != 0) BitLen = maxLen; - int foundclk = 0; - //amp before ST check - if (amp == 'a') - askAmp(bits, BitLen); + int foundclk = 0; + //amp before ST check + if (amp == 'a') + askAmp(bits, BitLen); - bool st = false; - size_t ststart = 0, stend = 0; - if (*stCheck) - st = DetectST(bits, &BitLen, &foundclk, &ststart, &stend); + bool st = false; + size_t ststart = 0, stend = 0; + if (*stCheck) + st = DetectST(bits, &BitLen, &foundclk, &ststart, &stend); - if (st) { - *stCheck = st; - clk = (clk == 0) ? foundclk : clk; - CursorCPos = ststart; - CursorDPos = stend; - if (verbose || g_debugMode) - PrintAndLogEx(NORMAL, "Found Sequence Terminator - First one is shown by orange and blue graph markers"); - } + if (st) { + *stCheck = st; + clk = (clk == 0) ? foundclk : clk; + CursorCPos = ststart; + CursorDPos = stend; + if (verbose || g_debugMode) + PrintAndLogEx(NORMAL, "Found Sequence Terminator - First one is shown by orange and blue graph markers"); + } - int startIdx = 0; - int errCnt = askdemod_ext(bits, &BitLen, &clk, &invert, maxErr, askamp, askType, &startIdx); + int startIdx = 0; + int errCnt = askdemod_ext(bits, &BitLen, &clk, &invert, maxErr, askamp, askType, &startIdx); - if (errCnt < 0 || BitLen < 16){ //if fatal error (or -1) - PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) No data found errors:%d, invert:%c, bitlen:%d, clock:%d", errCnt, (invert)?'Y':'N', BitLen, clk); - return 0; - } + if (errCnt < 0 || BitLen < 16){ //if fatal error (or -1) + PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) No data found errors:%d, invert:%c, bitlen:%d, clock:%d", errCnt, (invert)?'Y':'N', BitLen, clk); + return 0; + } - if (errCnt > maxErr){ - PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Too many errors found, errors:%d, bits:%d, clock:%d", errCnt, BitLen, clk); - return 0; - } + if (errCnt > maxErr){ + PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Too many errors found, errors:%d, bits:%d, clock:%d", errCnt, BitLen, clk); + return 0; + } - if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Using clock:%d, invert:%d, bits found:%d", clk, invert, BitLen); + if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (ASKDemod_ext) Using clock:%d, invert:%d, bits found:%d", clk, invert, BitLen); - //output - setDemodBuf(bits, BitLen, 0); - setClockGrid(clk, startIdx); + //output + setDemodBuf(bits, BitLen, 0); + setClockGrid(clk, startIdx); - if (verbose || g_debugMode){ - if (errCnt > 0) - PrintAndLogEx(NORMAL, "# Errors during Demoding (shown as 7 in bit stream): %d",errCnt); - if (askType) - PrintAndLogEx(NORMAL, "ASK/Manchester - Clock: %d - Decoded bitstream:",clk); - else - PrintAndLogEx(NORMAL, "ASK/Raw - Clock: %d - Decoded bitstream:",clk); - // Now output the bitstream to the scrollback by line of 16 bits - printDemodBuff(); - } - uint64_t lo = 0; - uint32_t hi = 0; - if (emSearch) - AskEm410xDecode(true, &hi, &lo); + if (verbose || g_debugMode){ + if (errCnt > 0) + PrintAndLogEx(NORMAL, "# Errors during Demoding (shown as 7 in bit stream): %d",errCnt); + if (askType) + PrintAndLogEx(NORMAL, "ASK/Manchester - Clock: %d - Decoded bitstream:",clk); + else + PrintAndLogEx(NORMAL, "ASK/Raw - Clock: %d - Decoded bitstream:",clk); + // Now output the bitstream to the scrollback by line of 16 bits + printDemodBuff(); + } + uint64_t lo = 0; + uint32_t hi = 0; + if (emSearch) + AskEm410xDecode(true, &hi, &lo); - return 1; + return 1; } int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType) { - bool st = false; - return ASKDemod_ext(Cmd, verbose, emSearch, askType, &st); + bool st = false; + return ASKDemod_ext(Cmd, verbose, emSearch, askType, &st); } //by marshmellow @@ -547,68 +547,68 @@ int ASKDemod(const char *Cmd, bool verbose, bool emSearch, uint8_t askType) { //prints binary found and saves in graphbuffer for further commands int Cmdaskmandemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 45 || cmdp == 'h') return usage_data_rawdemod_am(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 45 || cmdp == 'h') return usage_data_rawdemod_am(); - bool st = true; - if (Cmd[0] == 's') - return ASKDemod_ext(Cmd++, true, true, 1, &st); - else if (Cmd[1] == 's') - return ASKDemod_ext(Cmd += 2, true, true, 1, &st); + bool st = true; + if (Cmd[0] == 's') + return ASKDemod_ext(Cmd++, true, true, 1, &st); + else if (Cmd[1] == 's') + return ASKDemod_ext(Cmd += 2, true, true, 1, &st); - return ASKDemod(Cmd, true, true, 1); + return ASKDemod(Cmd, true, true, 1); } //by marshmellow //manchester decode //stricktly take 10 and 01 and convert to 0 and 1 int Cmdmandecoderaw(const char *Cmd) { - size_t size = 0; - int high = 0, low = 0; - int i = 0, errCnt = 0, invert = 0, maxErr = 20; - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 5 || cmdp == 'h') return usage_data_manrawdecode(); + size_t size = 0; + int high = 0, low = 0; + int i = 0, errCnt = 0, invert = 0, maxErr = 20; + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 5 || cmdp == 'h') return usage_data_manrawdecode(); - if (DemodBufferLen == 0) return 0; + if (DemodBufferLen == 0) return 0; - uint8_t bits[MAX_DEMOD_BUF_LEN] = {0}; + uint8_t bits[MAX_DEMOD_BUF_LEN] = {0}; - for (; i < DemodBufferLen; ++i){ - if (DemodBuffer[i] > high) - high = DemodBuffer[i]; - else if(DemodBuffer[i] < low) - low = DemodBuffer[i]; - bits[i] = DemodBuffer[i]; - } + for (; i < DemodBufferLen; ++i){ + if (DemodBuffer[i] > high) + high = DemodBuffer[i]; + else if(DemodBuffer[i] < low) + low = DemodBuffer[i]; + bits[i] = DemodBuffer[i]; + } - if (high > 7 || low < 0 ){ - PrintAndLogEx(WARNING, "Error: please raw demod the wave first then manchester raw decode"); - return 0; - } + if (high > 7 || low < 0 ){ + PrintAndLogEx(WARNING, "Error: please raw demod the wave first then manchester raw decode"); + return 0; + } - sscanf(Cmd, "%i %i", &invert, &maxErr); - size = i; - uint8_t alignPos = 0; - errCnt = manrawdecode(bits, &size, invert, &alignPos); - if (errCnt >= maxErr){ - PrintAndLogEx(WARNING, "Too many errors: %d",errCnt); - return 0; - } + sscanf(Cmd, "%i %i", &invert, &maxErr); + size = i; + uint8_t alignPos = 0; + errCnt = manrawdecode(bits, &size, invert, &alignPos); + if (errCnt >= maxErr){ + PrintAndLogEx(WARNING, "Too many errors: %d",errCnt); + return 0; + } - PrintAndLogEx(NORMAL, "Manchester Decoded - # errors:%d - data:",errCnt); - PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 16)); + PrintAndLogEx(NORMAL, "Manchester Decoded - # errors:%d - data:",errCnt); + PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 16)); - if (errCnt == 0){ - uint64_t id = 0; - uint32_t hi = 0; - size_t idx = 0; - if (Em410xDecode(bits, &size, &idx, &hi, &id) == 1){ - //need to adjust to set bitstream back to manchester encoded data - //setDemodBuf(bits, size, idx); - printEM410x(hi, id); - } - } - return 1; + if (errCnt == 0){ + uint64_t id = 0; + uint32_t hi = 0; + size_t idx = 0; + if (Em410xDecode(bits, &size, &idx, &hi, &id) == 1){ + //need to adjust to set bitstream back to manchester encoded data + //setDemodBuf(bits, size, idx); + printEM410x(hi, id); + } + } + return 1; } //by marshmellow @@ -618,269 +618,269 @@ int Cmdmandecoderaw(const char *Cmd) { // and "invert" default = 0 if 1 it will invert output // the argument offset allows us to manually shift if the output is incorrect - [EDIT: now auto detects] int CmdBiphaseDecodeRaw(const char *Cmd) { - size_t size = 0; - int offset = 0, invert = 0, maxErr = 20, errCnt = 0; - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 3 || cmdp == 'h') return usage_data_biphaserawdecode(); + size_t size = 0; + int offset = 0, invert = 0, maxErr = 20, errCnt = 0; + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 3 || cmdp == 'h') return usage_data_biphaserawdecode(); - sscanf(Cmd, "%i %i %i", &offset, &invert, &maxErr); - if (DemodBufferLen == 0){ - PrintAndLogEx(NORMAL, "DemodBuffer Empty - run 'data rawdemod ar' first"); - return 0; - } + sscanf(Cmd, "%i %i %i", &offset, &invert, &maxErr); + if (DemodBufferLen == 0){ + PrintAndLogEx(NORMAL, "DemodBuffer Empty - run 'data rawdemod ar' first"); + return 0; + } - uint8_t bits[MAX_DEMOD_BUF_LEN] = {0}; - size = sizeof(bits); - if ( !getDemodBuf(bits, &size) ) return 0; + uint8_t bits[MAX_DEMOD_BUF_LEN] = {0}; + size = sizeof(bits); + if ( !getDemodBuf(bits, &size) ) return 0; - errCnt = BiphaseRawDecode(bits, &size, &offset, invert); - if (errCnt < 0){ - PrintAndLogEx(WARNING, "Error during decode:%d", errCnt); - return 0; - } - if (errCnt > maxErr){ - PrintAndLogEx(WARNING, "Too many errors attempting to decode: %d",errCnt); - return 0; - } + errCnt = BiphaseRawDecode(bits, &size, &offset, invert); + if (errCnt < 0){ + PrintAndLogEx(WARNING, "Error during decode:%d", errCnt); + return 0; + } + if (errCnt > maxErr){ + PrintAndLogEx(WARNING, "Too many errors attempting to decode: %d",errCnt); + return 0; + } - if (errCnt > 0) - PrintAndLogEx(WARNING, "# Errors found during Demod (shown as 7 in bit stream): %d",errCnt); + if (errCnt > 0) + PrintAndLogEx(WARNING, "# Errors found during Demod (shown as 7 in bit stream): %d",errCnt); - PrintAndLogEx(NORMAL, "Biphase Decoded using offset: %d - # invert:%d - data:",offset,invert); - PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 16)); + PrintAndLogEx(NORMAL, "Biphase Decoded using offset: %d - # invert:%d - data:",offset,invert); + PrintAndLogEx(NORMAL, "%s", sprint_bin_break(bits, size, 16)); - //remove first bit from raw demod - if (offset) - setDemodBuf(DemodBuffer,DemodBufferLen-offset, offset); + //remove first bit from raw demod + if (offset) + setDemodBuf(DemodBuffer,DemodBufferLen-offset, offset); - setClockGrid(g_DemodClock, g_DemodStartIdx + g_DemodClock*offset/2); - return 1; + setClockGrid(g_DemodClock, g_DemodStartIdx + g_DemodClock*offset/2); + return 1; } //by marshmellow // - ASK Demod then Biphase decode GraphBuffer samples int ASKbiphaseDemod(const char *Cmd, bool verbose) { - //ask raw demod GraphBuffer first - int offset=0, clk=0, invert=0, maxErr=0; - sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr); + //ask raw demod GraphBuffer first + int offset=0, clk=0, invert=0, maxErr=0; + sscanf(Cmd, "%i %i %i %i", &offset, &clk, &invert, &maxErr); - uint8_t BitStream[MAX_DEMOD_BUF_LEN]; - size_t size = getFromGraphBuf(BitStream); - if (size == 0 ) { - PrintAndLogEx(DEBUG, "DEBUG: no data in graphbuf"); - return 0; - } - int startIdx = 0; - //invert here inverts the ask raw demoded bits which has no effect on the demod, but we need the pointer - int errCnt = askdemod_ext(BitStream, &size, &clk, &invert, maxErr, 0, 0, &startIdx); - if ( errCnt < 0 || errCnt > maxErr ) { - PrintAndLogEx(DEBUG, "DEBUG: no data or error found %d, clock: %d", errCnt, clk); - return 0; - } + uint8_t BitStream[MAX_DEMOD_BUF_LEN]; + size_t size = getFromGraphBuf(BitStream); + if (size == 0 ) { + PrintAndLogEx(DEBUG, "DEBUG: no data in graphbuf"); + return 0; + } + int startIdx = 0; + //invert here inverts the ask raw demoded bits which has no effect on the demod, but we need the pointer + int errCnt = askdemod_ext(BitStream, &size, &clk, &invert, maxErr, 0, 0, &startIdx); + if ( errCnt < 0 || errCnt > maxErr ) { + PrintAndLogEx(DEBUG, "DEBUG: no data or error found %d, clock: %d", errCnt, clk); + return 0; + } - //attempt to Biphase decode BitStream - errCnt = BiphaseRawDecode(BitStream, &size, &offset, invert); - if (errCnt < 0){ - if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode: %d", errCnt); - return 0; - } - if (errCnt > maxErr) { - if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode too many errors: %d", errCnt); - return 0; - } - //success set DemodBuffer and return - setDemodBuf(BitStream, size, 0); - setClockGrid(clk, startIdx + clk*offset/2); - if (g_debugMode || verbose){ - PrintAndLogEx(NORMAL, "Biphase Decoded using offset: %d - clock: %d - # errors:%d - data:",offset,clk,errCnt); - printDemodBuff(); - } - return 1; + //attempt to Biphase decode BitStream + errCnt = BiphaseRawDecode(BitStream, &size, &offset, invert); + if (errCnt < 0){ + if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode: %d", errCnt); + return 0; + } + if (errCnt > maxErr) { + if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: Error BiphaseRawDecode too many errors: %d", errCnt); + return 0; + } + //success set DemodBuffer and return + setDemodBuf(BitStream, size, 0); + setClockGrid(clk, startIdx + clk*offset/2); + if (g_debugMode || verbose){ + PrintAndLogEx(NORMAL, "Biphase Decoded using offset: %d - clock: %d - # errors:%d - data:",offset,clk,errCnt); + printDemodBuff(); + } + return 1; } //by marshmellow - see ASKbiphaseDemod int Cmdaskbiphdemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ab(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ab(); - return ASKbiphaseDemod(Cmd, true); + return ASKbiphaseDemod(Cmd, true); } //by marshmellow - see ASKDemod int Cmdaskrawdemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ar(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 25 || cmdp == 'h') return usage_data_rawdemod_ar(); - return ASKDemod(Cmd, true, false, 0); + return ASKDemod(Cmd, true, false, 0); } int AutoCorrelate(const int *in, int *out, size_t len, int window, bool SaveGrph, bool verbose) { - // sanity check - if ( window > len ) window = len; + // sanity check + if ( window > len ) window = len; - if (verbose) PrintAndLogEx(INFO, "performing %d correlations", GraphTraceLen - window); + if (verbose) PrintAndLogEx(INFO, "performing %d correlations", GraphTraceLen - window); - //test - double autocv = 0.0; // Autocovariance value - double ac_value; // Computed autocorrelation value to be returned - double variance; // Computed variance - double mean; - size_t correlation = 0; - int lastmax = 0; + //test + double autocv = 0.0; // Autocovariance value + double ac_value; // Computed autocorrelation value to be returned + double variance; // Computed variance + double mean; + size_t correlation = 0; + int lastmax = 0; - // in, len, 4000 - mean = compute_mean(in, len); - variance = compute_variance(in, len); + // in, len, 4000 + mean = compute_mean(in, len); + variance = compute_variance(in, len); - static int CorrelBuffer[MAX_GRAPH_TRACE_LEN]; + static int CorrelBuffer[MAX_GRAPH_TRACE_LEN]; - for (int i = 0; i < len - window; ++i) { + for (int i = 0; i < len - window; ++i) { - for (size_t j=0; j < (len - i); j++) { - autocv += (in[j] - mean) * (in[j+i] - mean); - } - autocv = (1.0 / (len - i)) * autocv; + for (size_t j=0; j < (len - i); j++) { + autocv += (in[j] - mean) * (in[j+i] - mean); + } + autocv = (1.0 / (len - i)) * autocv; - CorrelBuffer[i] = autocv; + CorrelBuffer[i] = autocv; - // Autocorrelation is autocovariance divided by variance - ac_value = autocv / variance; + // Autocorrelation is autocovariance divided by variance + ac_value = autocv / variance; - // keep track of which distance is repeating. - if ( ac_value > 1) { - correlation = i-lastmax; - lastmax = i; - } - } + // keep track of which distance is repeating. + if ( ac_value > 1) { + correlation = i-lastmax; + lastmax = i; + } + } - // - int hi = 0, idx = 0; - int distance = 0, hi_1 = 0, idx_1 = 0; - for (int i = 0; i <= len; ++i){ - if ( CorrelBuffer[i] > hi) { - hi = CorrelBuffer[i]; - idx = i; - } - } + // + int hi = 0, idx = 0; + int distance = 0, hi_1 = 0, idx_1 = 0; + for (int i = 0; i <= len; ++i){ + if ( CorrelBuffer[i] > hi) { + hi = CorrelBuffer[i]; + idx = i; + } + } - for (int i = idx+1; i <= window; ++i){ - if ( CorrelBuffer[i] > hi_1 ) { - hi_1 = CorrelBuffer[i]; - idx_1 = i; - } - } + for (int i = idx+1; i <= window; ++i){ + if ( CorrelBuffer[i] > hi_1 ) { + hi_1 = CorrelBuffer[i]; + idx_1 = i; + } + } - int foo = ABS(hi-hi_1); - int bar = (int)((int)((hi+hi_1) / 2) * 0.03); - if ( verbose && foo < bar ) { - distance = idx_1 - idx; - PrintAndLogEx(SUCCESS, "possible 3% visible correlation %4d samples", distance); - } else if (verbose && ( correlation > 1 ) ) { - PrintAndLogEx(SUCCESS, "possible correlation %4d samples", correlation); - } else { - PrintAndLogEx(FAILED, "no repeating pattern found, try increasing window size"); - } + int foo = ABS(hi-hi_1); + int bar = (int)((int)((hi+hi_1) / 2) * 0.03); + if ( verbose && foo < bar ) { + distance = idx_1 - idx; + PrintAndLogEx(SUCCESS, "possible 3% visible correlation %4d samples", distance); + } else if (verbose && ( correlation > 1 ) ) { + PrintAndLogEx(SUCCESS, "possible correlation %4d samples", correlation); + } else { + PrintAndLogEx(FAILED, "no repeating pattern found, try increasing window size"); + } - int retval = correlation; - if (SaveGrph) { - //GraphTraceLen = GraphTraceLen - window; - memcpy(out, CorrelBuffer, len * sizeof(int)); - if ( distance > 0) { - setClockGrid(distance, idx); - retval = distance; - } - else - setClockGrid(correlation, idx); + int retval = correlation; + if (SaveGrph) { + //GraphTraceLen = GraphTraceLen - window; + memcpy(out, CorrelBuffer, len * sizeof(int)); + if ( distance > 0) { + setClockGrid(distance, idx); + retval = distance; + } + else + setClockGrid(correlation, idx); - CursorCPos = idx_1; - CursorDPos = idx_1+retval; - DemodBufferLen = 0; - RepaintGraphWindow(); - } + CursorCPos = idx_1; + CursorDPos = idx_1+retval; + DemodBufferLen = 0; + RepaintGraphWindow(); + } - return retval; + return retval; } int CmdAutoCorr(const char *Cmd) { - uint32_t window = 4000; - uint8_t cmdp = 0; - bool updateGrph = false; - bool errors = false; + uint32_t window = 4000; + uint8_t cmdp = 0; + bool updateGrph = false; + bool errors = false; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_data_autocorr(); - case 'g': - updateGrph = true; - cmdp++; - break; - case 'w': - window = param_get32ex(Cmd, cmdp+1, 4000, 10); - if (window >= GraphTraceLen) { - PrintAndLogEx(WARNING, "window must be smaller than trace (%d samples)", GraphTraceLen); - errors = true; - } - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors || cmdp == 0 ) return usage_data_autocorr(); + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_data_autocorr(); + case 'g': + updateGrph = true; + cmdp++; + break; + case 'w': + window = param_get32ex(Cmd, cmdp+1, 4000, 10); + if (window >= GraphTraceLen) { + PrintAndLogEx(WARNING, "window must be smaller than trace (%d samples)", GraphTraceLen); + errors = true; + } + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + //Validations + if (errors || cmdp == 0 ) return usage_data_autocorr(); - return AutoCorrelate(GraphBuffer, GraphBuffer, GraphTraceLen, window, updateGrph, true); + return AutoCorrelate(GraphBuffer, GraphBuffer, GraphTraceLen, window, updateGrph, true); } int CmdBitsamples(const char *Cmd) { - int cnt = 0; - uint8_t got[12288]; + int cnt = 0; + uint8_t got[12288]; - if (!GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 2500 , false)) { - PrintAndLogEx(WARNING, "command execution time out"); - return false; - } + if (!GetFromDevice(BIG_BUF, got, sizeof(got), 0, NULL, 2500 , false)) { + PrintAndLogEx(WARNING, "command execution time out"); + return false; + } - for (int j = 0; j < sizeof(got); j++) { - for (int k = 0; k < 8; k++) { - if(got[j] & (1 << (7 - k))) - GraphBuffer[cnt++] = 1; - else - GraphBuffer[cnt++] = 0; - } - } - GraphTraceLen = cnt; - RepaintGraphWindow(); - return 0; + for (int j = 0; j < sizeof(got); j++) { + for (int k = 0; k < 8; k++) { + if(got[j] & (1 << (7 - k))) + GraphBuffer[cnt++] = 1; + else + GraphBuffer[cnt++] = 0; + } + } + GraphTraceLen = cnt; + RepaintGraphWindow(); + return 0; } int CmdBuffClear(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_data_buffclear(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_data_buffclear(); - UsbCommand c = {CMD_BUFF_CLEAR, {0,0,0}}; - clearCommandBuffer(); - SendCommand(&c); - ClearGraph(true); - return 0; + UsbCommand c = {CMD_BUFF_CLEAR, {0,0,0}}; + clearCommandBuffer(); + SendCommand(&c); + ClearGraph(true); + return 0; } int CmdDec(const char *Cmd) { - for (int i = 0; i < (GraphTraceLen / 2); ++i) - GraphBuffer[i] = GraphBuffer[i * 2]; - GraphTraceLen /= 2; - PrintAndLogEx(NORMAL, "decimated by 2"); - RepaintGraphWindow(); - return 0; + for (int i = 0; i < (GraphTraceLen / 2); ++i) + GraphBuffer[i] = GraphBuffer[i * 2]; + GraphTraceLen /= 2; + PrintAndLogEx(NORMAL, "decimated by 2"); + RepaintGraphWindow(); + return 0; } /** * Undecimate - I'd call it 'interpolate', but we'll save that @@ -891,62 +891,62 @@ int CmdDec(const char *Cmd) */ int CmdUndec(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_data_undecimate(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_data_undecimate(); - uint8_t factor = param_get8ex(Cmd, 0, 2, 10); + uint8_t factor = param_get8ex(Cmd, 0, 2, 10); - //We have memory, don't we? - int swap[MAX_GRAPH_TRACE_LEN] = {0}; - uint32_t g_index = 0, s_index = 0; - while(g_index < GraphTraceLen && s_index + factor < MAX_GRAPH_TRACE_LEN) - { - int count = 0; - for (count = 0; count < factor && s_index + count < MAX_GRAPH_TRACE_LEN; count++) - swap[s_index+count] = GraphBuffer[g_index]; - s_index += count; - g_index++; - } + //We have memory, don't we? + int swap[MAX_GRAPH_TRACE_LEN] = {0}; + uint32_t g_index = 0, s_index = 0; + while(g_index < GraphTraceLen && s_index + factor < MAX_GRAPH_TRACE_LEN) + { + int count = 0; + for (count = 0; count < factor && s_index + count < MAX_GRAPH_TRACE_LEN; count++) + swap[s_index+count] = GraphBuffer[g_index]; + s_index += count; + g_index++; + } - memcpy(GraphBuffer, swap, s_index * sizeof(int)); - GraphTraceLen = s_index; - RepaintGraphWindow(); - return 0; + memcpy(GraphBuffer, swap, s_index * sizeof(int)); + GraphTraceLen = s_index; + RepaintGraphWindow(); + return 0; } //by marshmellow //shift graph zero up or down based on input + or - int CmdGraphShiftZero(const char *Cmd) { - int shift = 0, shiftedVal = 0; - //set options from parameters entered with the command - sscanf(Cmd, "%i", &shift); + int shift = 0, shiftedVal = 0; + //set options from parameters entered with the command + sscanf(Cmd, "%i", &shift); - for(int i = 0; i < GraphTraceLen; i++){ - if ( i+shift >= GraphTraceLen) - shiftedVal = GraphBuffer[i]; - else - shiftedVal = GraphBuffer[i] + shift; + for(int i = 0; i < GraphTraceLen; i++){ + if ( i+shift >= GraphTraceLen) + shiftedVal = GraphBuffer[i]; + else + shiftedVal = GraphBuffer[i] + shift; - if (shiftedVal > 127) - shiftedVal = 127; - else if (shiftedVal < -127) - shiftedVal = -127; - GraphBuffer[i] = shiftedVal; - } - CmdNorm(""); - return 0; + if (shiftedVal > 127) + shiftedVal = 127; + else if (shiftedVal < -127) + shiftedVal = -127; + GraphBuffer[i] = shiftedVal; + } + CmdNorm(""); + return 0; } int AskEdgeDetect(const int *in, int *out, int len, int threshold) { - int last = 0; - for(int i = 1; i= threshold) //large jump up - last = 127; - else if (in[i] - in[i-1] <= -1 * threshold) //large jump down - last = -127; - out[i-1] = last; - } - return 0; + int last = 0; + for(int i = 1; i= threshold) //large jump up + last = 127; + else if (in[i] - in[i-1] <= -1 * threshold) //large jump down + last = -127; + out[i-1] = last; + } + return 0; } //by marshmellow @@ -954,69 +954,69 @@ int AskEdgeDetect(const int *in, int *out, int len, int threshold) { //similar to dirtheshold, threshold commands //takes a threshold length which is the measured length between two samples then determines an edge int CmdAskEdgeDetect(const char *Cmd) { - int thresLen = 25; - int ans = 0; - sscanf(Cmd, "%i", &thresLen); + int thresLen = 25; + int ans = 0; + sscanf(Cmd, "%i", &thresLen); - ans = AskEdgeDetect(GraphBuffer, GraphBuffer, GraphTraceLen, thresLen); - RepaintGraphWindow(); - return ans; + ans = AskEdgeDetect(GraphBuffer, GraphBuffer, GraphTraceLen, thresLen); + RepaintGraphWindow(); + return ans; } /* Print our clock rate */ // uses data from graphbuffer // adjusted to take char parameter for type of modulation to find the clock - by marshmellow. int CmdDetectClockRate(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 6 || strlen(Cmd) == 0 || cmdp == 'h') - return usage_data_detectclock(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 6 || strlen(Cmd) == 0 || cmdp == 'h') + return usage_data_detectclock(); - int clock = 0; - switch ( cmdp ) { - case 'a' : - clock = GetAskClock(Cmd+1, true); - break; - case 'f' : - clock = GetFskClock("", true); - break; - case 'n' : - clock = GetNrzClock("", true); - break; - case 'p' : - clock = GetPskClock("", true); - break; - default : - PrintAndLogEx(NORMAL, "Please specify a valid modulation to detect the clock of - see option h for help"); - break; - } - RepaintGraphWindow(); - return clock; + int clock = 0; + switch ( cmdp ) { + case 'a' : + clock = GetAskClock(Cmd+1, true); + break; + case 'f' : + clock = GetFskClock("", true); + break; + case 'n' : + clock = GetNrzClock("", true); + break; + case 'p' : + clock = GetPskClock("", true); + break; + default : + PrintAndLogEx(NORMAL, "Please specify a valid modulation to detect the clock of - see option h for help"); + break; + } + RepaintGraphWindow(); + return clock; } char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert) { - static char fType[8]; - memset(fType, 0x00, 8); - char *fskType = fType; + static char fType[8]; + memset(fType, 0x00, 8); + char *fskType = fType; - if (fchigh == 10 && fclow == 8){ + if (fchigh == 10 && fclow == 8){ - if (invert) - memcpy(fskType, "FSK2a", 5); - else - memcpy(fskType, "FSK2", 4); + if (invert) + memcpy(fskType, "FSK2a", 5); + else + memcpy(fskType, "FSK2", 4); - } else if (fchigh == 8 && fclow == 5) { + } else if (fchigh == 8 && fclow == 5) { - if (invert) - memcpy(fskType, "FSK1", 4); - else - memcpy(fskType, "FSK1a", 5); + if (invert) + memcpy(fskType, "FSK1", 4); + else + memcpy(fskType, "FSK1a", 5); - } else { - memcpy(fskType, "FSK??", 5); - } - return fskType; + } else { + memcpy(fskType, "FSK??", 5); + } + return fskType; } //by marshmellow @@ -1024,65 +1024,65 @@ char *GetFSKType(uint8_t fchigh, uint8_t fclow, uint8_t invert) //takes 4 arguments - Clock, invert, fchigh, fclow //defaults: clock = 50, invert=1, fchigh=10, fclow=8 (RF/10 RF/8 (fsk2a)) int FSKrawDemod(const char *Cmd, bool verbose) { - //raw fsk demod no manchester decoding no start bit finding just get binary from wave - uint8_t rfLen, invert, fchigh, fclow; + //raw fsk demod no manchester decoding no start bit finding just get binary from wave + uint8_t rfLen, invert, fchigh, fclow; - //set defaults - //set options from parameters entered with the command - rfLen = param_get8(Cmd, 0); - invert = param_get8(Cmd, 1); - fchigh = param_get8(Cmd, 2); - fclow = param_get8(Cmd, 3); + //set defaults + //set options from parameters entered with the command + rfLen = param_get8(Cmd, 0); + invert = param_get8(Cmd, 1); + fchigh = param_get8(Cmd, 2); + fclow = param_get8(Cmd, 3); - if (strlen(Cmd) > 0 && strlen(Cmd) <= 2) { - if (rfLen == 1) { - invert = 1; //if invert option only is used - rfLen = 0; - } - } + if (strlen(Cmd) > 0 && strlen(Cmd) <= 2) { + if (rfLen == 1) { + invert = 1; //if invert option only is used + rfLen = 0; + } + } if (getSignalProperties()->isnoise) return 0; - - uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; - size_t BitLen = getFromGraphBuf(bits); - if (BitLen == 0) return 0; - //get field clock lengths - uint16_t fcs = 0; - if (!fchigh || !fclow) { - fcs = countFC(bits, BitLen, true); - if (!fcs) { - fchigh = 10; - fclow = 8; - } else { - fchigh = (fcs >> 8) & 0x00FF; - fclow = fcs & 0x00FF; - } - } - //get bit clock length - if (!rfLen) { - int firstClockEdge = 0; //todo - align grid on graph with this... - rfLen = detectFSKClk(bits, BitLen, fchigh, fclow, &firstClockEdge); - if (!rfLen) rfLen = 50; - } - int startIdx = 0; - int size = fskdemod(bits, BitLen, rfLen, invert, fchigh, fclow, &startIdx); - if (size > 0) { - setDemodBuf(bits, size, 0); - setClockGrid(rfLen, startIdx); + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; + size_t BitLen = getFromGraphBuf(bits); + if (BitLen == 0) return 0; - // Now output the bitstream to the scrollback by line of 16 bits - if (verbose || g_debugMode) { - PrintAndLogEx(DEBUG, "DEBUG: (FSKrawDemod) Using Clock:%u, invert:%u, fchigh:%u, fclow:%u", rfLen, invert, fchigh, fclow); - PrintAndLogEx(NORMAL, "%s decoded bitstream:", GetFSKType(fchigh, fclow, invert)); - printDemodBuff(); - } - return 1; - } else { - if (g_debugMode) PrintAndLogEx(NORMAL, "no FSK data found"); - } - return 0; + //get field clock lengths + uint16_t fcs = 0; + if (!fchigh || !fclow) { + fcs = countFC(bits, BitLen, true); + if (!fcs) { + fchigh = 10; + fclow = 8; + } else { + fchigh = (fcs >> 8) & 0x00FF; + fclow = fcs & 0x00FF; + } + } + //get bit clock length + if (!rfLen) { + int firstClockEdge = 0; //todo - align grid on graph with this... + rfLen = detectFSKClk(bits, BitLen, fchigh, fclow, &firstClockEdge); + if (!rfLen) rfLen = 50; + } + int startIdx = 0; + int size = fskdemod(bits, BitLen, rfLen, invert, fchigh, fclow, &startIdx); + if (size > 0) { + setDemodBuf(bits, size, 0); + setClockGrid(rfLen, startIdx); + + // Now output the bitstream to the scrollback by line of 16 bits + if (verbose || g_debugMode) { + PrintAndLogEx(DEBUG, "DEBUG: (FSKrawDemod) Using Clock:%u, invert:%u, fchigh:%u, fclow:%u", rfLen, invert, fchigh, fclow); + PrintAndLogEx(NORMAL, "%s decoded bitstream:", GetFSKType(fchigh, fclow, invert)); + printDemodBuff(); + } + return 1; + } else { + if (g_debugMode) PrintAndLogEx(NORMAL, "no FSK data found"); + } + return 0; } //by marshmellow @@ -1090,113 +1090,113 @@ int FSKrawDemod(const char *Cmd, bool verbose) { //takes 4 arguments - Clock, invert, fchigh, fclow //defaults: clock = 50, invert=1, fchigh=10, fclow=8 (RF/10 RF/8 (fsk2a)) int CmdFSKrawdemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 20 || cmdp == 'h') return usage_data_rawdemod_fs(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 20 || cmdp == 'h') return usage_data_rawdemod_fs(); - return FSKrawDemod(Cmd, true); + return FSKrawDemod(Cmd, true); } //by marshmellow //attempt to psk1 demod graph buffer int PSKDemod(const char *Cmd, bool verbose) { - int invert = 0, clk = 0, maxErr = 100; - sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr); - if (clk == 1) { - invert = 1; - clk = 0; - } - if (invert != 0 && invert != 1) { - if (g_debugMode || verbose) PrintAndLogEx(WARNING, "Invalid argument: %s", Cmd); - return 0; - } - + int invert = 0, clk = 0, maxErr = 100; + sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr); + if (clk == 1) { + invert = 1; + clk = 0; + } + if (invert != 0 && invert != 1) { + if (g_debugMode || verbose) PrintAndLogEx(WARNING, "Invalid argument: %s", Cmd); + return 0; + } + if (getSignalProperties()->isnoise) return 0; - - uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; - size_t BitLen = getFromGraphBuf(BitStream); - if (BitLen == 0) return 0; - int errCnt = 0; - int startIdx = 0; - errCnt = pskRawDemod_ext(BitStream, &BitLen, &clk, &invert, &startIdx); - if (errCnt > maxErr){ - if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); - return 0; - } - if (errCnt < 0|| BitLen < 16){ //throw away static - allow 1 and -1 (in case of threshold command first) - if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); - return 0; - } - if (verbose || g_debugMode){ - PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) Using Clock:%d, invert:%d, Bits Found:%d",clk, invert, BitLen); - if (errCnt > 0){ - PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) errors during Demoding (shown as 7 in bit stream): %d", errCnt); - } - } - //prime demod buffer for output - setDemodBuf(BitStream, BitLen, 0); - setClockGrid(clk, startIdx); - return 1; + + uint8_t BitStream[MAX_GRAPH_TRACE_LEN] = {0}; + size_t BitLen = getFromGraphBuf(BitStream); + if (BitLen == 0) return 0; + int errCnt = 0; + int startIdx = 0; + errCnt = pskRawDemod_ext(BitStream, &BitLen, &clk, &invert, &startIdx); + if (errCnt > maxErr){ + if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); + return 0; + } + if (errCnt < 0|| BitLen < 16){ //throw away static - allow 1 and -1 (in case of threshold command first) + if (g_debugMode || verbose) PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); + return 0; + } + if (verbose || g_debugMode){ + PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) Using Clock:%d, invert:%d, Bits Found:%d",clk, invert, BitLen); + if (errCnt > 0){ + PrintAndLogEx(DEBUG, "DEBUG: (PSKdemod) errors during Demoding (shown as 7 in bit stream): %d", errCnt); + } + } + //prime demod buffer for output + setDemodBuf(BitStream, BitLen, 0); + setClockGrid(clk, startIdx); + return 1; } int CmdPSKIdteck(const char *Cmd) { - if (!PSKDemod("", false)) { - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed"); - return 0; - } - size_t size = DemodBufferLen; + if (!PSKDemod("", false)) { + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed"); + return 0; + } + size_t size = DemodBufferLen; - //get binary from PSK1 wave - int idx = detectIdteck(DemodBuffer, &size); - if (idx < 0){ + //get binary from PSK1 wave + int idx = detectIdteck(DemodBuffer, &size); + if (idx < 0){ - if (idx == -1) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: not enough samples"); - else if (idx == -2) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: just noise"); - else if (idx == -3) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: preamble not found"); - else if (idx == -4) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: size not correct: %d", size); - else - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: idx: %d",idx); + if (idx == -1) + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: not enough samples"); + else if (idx == -2) + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: just noise"); + else if (idx == -3) + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: preamble not found"); + else if (idx == -4) + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: size not correct: %d", size); + else + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: idx: %d",idx); - // if didn't find preamble try again inverting - if (!PSKDemod("1", false)) { - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed"); - return 0; - } - idx = detectIdteck(DemodBuffer, &size); - if (idx < 0){ + // if didn't find preamble try again inverting + if (!PSKDemod("1", false)) { + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck PSKDemod failed"); + return 0; + } + idx = detectIdteck(DemodBuffer, &size); + if (idx < 0){ - if (idx == -1) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: not enough samples"); - else if (idx == -2) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: just noise"); - else if (idx == -3) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: preamble not found"); - else if (idx == -4) - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: size not correct: %d", size); - else - PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: idx: %d",idx); + if (idx == -1) + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: not enough samples"); + else if (idx == -2) + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: just noise"); + else if (idx == -3) + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: preamble not found"); + else if (idx == -4) + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: size not correct: %d", size); + else + PrintAndLogEx(DEBUG, "DEBUG: Error - Idteck: idx: %d",idx); - return 0; - } - } - setDemodBuf(DemodBuffer, 64, idx); + return 0; + } + } + setDemodBuf(DemodBuffer, 64, idx); - //got a good demod - uint32_t id = 0; - uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); - uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); + //got a good demod + uint32_t id = 0; + uint32_t raw1 = bytebits_to_byte(DemodBuffer, 32); + uint32_t raw2 = bytebits_to_byte(DemodBuffer+32, 32); - //parity check (TBD) - //checksum check (TBD) + //parity check (TBD) + //checksum check (TBD) - //output - PrintAndLogEx(SUCCESS, "IDTECK Tag Found: Card ID %u , Raw: %08X%08X", id, raw1, raw2); - return 1; + //output + PrintAndLogEx(SUCCESS, "IDTECK Tag Found: Card ID %u , Raw: %08X%08X", id, raw1, raw2); + return 1; } // by marshmellow @@ -1205,56 +1205,56 @@ int CmdPSKIdteck(const char *Cmd) { // prints binary found and saves in demodbuffer for further commands int NRZrawDemod(const char *Cmd, bool verbose) { - int errCnt = 0, clkStartIdx = 0; - int invert = 0, clk = 0, maxErr = 100; - sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr); - if (clk == 1){ - invert = 1; - clk = 0; - } + int errCnt = 0, clkStartIdx = 0; + int invert = 0, clk = 0, maxErr = 100; + sscanf(Cmd, "%i %i %i", &clk, &invert, &maxErr); + if (clk == 1){ + invert = 1; + clk = 0; + } + + if (invert != 0 && invert != 1) { + PrintAndLogEx(WARNING, "(NRZrawDemod) Invalid argument: %s", Cmd); + return 0; + } - if (invert != 0 && invert != 1) { - PrintAndLogEx(WARNING, "(NRZrawDemod) Invalid argument: %s", Cmd); - return 0; - } - if (getSignalProperties()->isnoise) return 0; - uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; - size_t BitLen = getFromGraphBuf(bits); + uint8_t bits[MAX_GRAPH_TRACE_LEN] = {0}; + size_t BitLen = getFromGraphBuf(bits); - if (BitLen == 0) return 0; + if (BitLen == 0) return 0; - errCnt = nrzRawDemod(bits, &BitLen, &clk, &invert, &clkStartIdx); - if (errCnt > maxErr){ - PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt); - return 0; - } - if (errCnt < 0 || BitLen < 16){ //throw away static - allow 1 and -1 (in case of threshold command first) - PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); - return 0; - } - if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Tried NRZ Demod using Clock: %d - invert: %d - Bits Found: %d", clk, invert, BitLen); - //prime demod buffer for output - setDemodBuf(bits, BitLen, 0); - setClockGrid(clk, clkStartIdx); + errCnt = nrzRawDemod(bits, &BitLen, &clk, &invert, &clkStartIdx); + if (errCnt > maxErr){ + PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Too many errors found, clk: %d, invert: %d, numbits: %d, errCnt: %d",clk,invert,BitLen,errCnt); + return 0; + } + if (errCnt < 0 || BitLen < 16){ //throw away static - allow 1 and -1 (in case of threshold command first) + PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) no data found, clk: %d, invert: %d, numbits: %d, errCnt: %d", clk, invert, BitLen, errCnt); + return 0; + } + if (verbose || g_debugMode) PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Tried NRZ Demod using Clock: %d - invert: %d - Bits Found: %d", clk, invert, BitLen); + //prime demod buffer for output + setDemodBuf(bits, BitLen, 0); + setClockGrid(clk, clkStartIdx); - if (errCnt > 0 && (verbose || g_debugMode)) PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Errors during Demoding (shown as 7 in bit stream): %d", errCnt); - if (verbose || g_debugMode) { - PrintAndLogEx(NORMAL, "NRZ demoded bitstream:"); - // Now output the bitstream to the scrollback by line of 16 bits - printDemodBuff(); - } - return 1; + if (errCnt > 0 && (verbose || g_debugMode)) PrintAndLogEx(DEBUG, "DEBUG: (NRZrawDemod) Errors during Demoding (shown as 7 in bit stream): %d", errCnt); + if (verbose || g_debugMode) { + PrintAndLogEx(NORMAL, "NRZ demoded bitstream:"); + // Now output the bitstream to the scrollback by line of 16 bits + printDemodBuff(); + } + return 1; } int CmdNRZrawDemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_nr(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_nr(); - return NRZrawDemod(Cmd, true); + return NRZrawDemod(Cmd, true); } // by marshmellow @@ -1262,569 +1262,569 @@ int CmdNRZrawDemod(const char *Cmd) { // attempts to demodulate psk only // prints binary found and saves in demodbuffer for further commands int CmdPSK1rawDemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_p1(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_p1(); - int ans = PSKDemod(Cmd, true); - //output - if (!ans){ - if (g_debugMode) PrintAndLogEx(WARNING, "Error demoding: %d",ans); - return 0; - } - PrintAndLogEx(NORMAL, "PSK1 demoded bitstream:"); - // Now output the bitstream to the scrollback by line of 16 bits - printDemodBuff(); - return 1; + int ans = PSKDemod(Cmd, true); + //output + if (!ans){ + if (g_debugMode) PrintAndLogEx(WARNING, "Error demoding: %d",ans); + return 0; + } + PrintAndLogEx(NORMAL, "PSK1 demoded bitstream:"); + // Now output the bitstream to the scrollback by line of 16 bits + printDemodBuff(); + return 1; } // by marshmellow // takes same args as cmdpsk1rawdemod int CmdPSK2rawDemod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_p2(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) > 16 || cmdp == 'h') return usage_data_rawdemod_p2(); - int ans = PSKDemod(Cmd, true); - if (!ans){ - if (g_debugMode) PrintAndLogEx(WARNING, "Error demoding: %d",ans); - return 0; - } - psk1TOpsk2(DemodBuffer, DemodBufferLen); - PrintAndLogEx(NORMAL, "PSK2 demoded bitstream:"); - // Now output the bitstream to the scrollback by line of 16 bits - printDemodBuff(); - return 1; + int ans = PSKDemod(Cmd, true); + if (!ans){ + if (g_debugMode) PrintAndLogEx(WARNING, "Error demoding: %d",ans); + return 0; + } + psk1TOpsk2(DemodBuffer, DemodBufferLen); + PrintAndLogEx(NORMAL, "PSK2 demoded bitstream:"); + // Now output the bitstream to the scrollback by line of 16 bits + printDemodBuff(); + return 1; } // by marshmellow - combines all raw demod functions into one menu command int CmdRawDemod(const char *Cmd) { - int ans = 0; + int ans = 0; - if (strlen(Cmd) > 35 || strlen(Cmd) < 2) - return usage_data_rawdemod(); + if (strlen(Cmd) > 35 || strlen(Cmd) < 2) + return usage_data_rawdemod(); - str_lower( (char *)Cmd); + str_lower( (char *)Cmd); - if (str_startswith(Cmd, "fs")) ans = CmdFSKrawdemod(Cmd+2); - else if(str_startswith(Cmd, "ab")) ans = Cmdaskbiphdemod(Cmd+2); - else if(str_startswith(Cmd, "am")) ans = Cmdaskmandemod(Cmd+2); - else if(str_startswith(Cmd, "ar")) ans = Cmdaskrawdemod(Cmd+2); - else if(str_startswith(Cmd, "nr")) ans = CmdNRZrawDemod(Cmd+2); - else if(str_startswith(Cmd, "p1")) ans = CmdPSK1rawDemod(Cmd+2); - else if(str_startswith(Cmd, "p2")) ans = CmdPSK2rawDemod(Cmd+2); - else PrintAndLogEx(WARNING, "Unknown modulation entered - see help ('h') for parameter structure"); + if (str_startswith(Cmd, "fs")) ans = CmdFSKrawdemod(Cmd+2); + else if(str_startswith(Cmd, "ab")) ans = Cmdaskbiphdemod(Cmd+2); + else if(str_startswith(Cmd, "am")) ans = Cmdaskmandemod(Cmd+2); + else if(str_startswith(Cmd, "ar")) ans = Cmdaskrawdemod(Cmd+2); + else if(str_startswith(Cmd, "nr")) ans = CmdNRZrawDemod(Cmd+2); + else if(str_startswith(Cmd, "p1")) ans = CmdPSK1rawDemod(Cmd+2); + else if(str_startswith(Cmd, "p2")) ans = CmdPSK2rawDemod(Cmd+2); + else PrintAndLogEx(WARNING, "Unknown modulation entered - see help ('h') for parameter structure"); - return ans; + return ans; } void setClockGrid(int clk, int offset) { - g_DemodStartIdx = offset; - g_DemodClock = clk; - PrintAndLogEx(DEBUG, "DEBUG: (setClockGrid) demodoffset %d, clk %d", offset, clk); + g_DemodStartIdx = offset; + g_DemodClock = clk; + PrintAndLogEx(DEBUG, "DEBUG: (setClockGrid) demodoffset %d, clk %d", offset, clk); - if (offset > clk) offset %= clk; - if (offset < 0) offset += clk; + if (offset > clk) offset %= clk; + if (offset < 0) offset += clk; - if (offset > GraphTraceLen || offset < 0) return; - if (clk < 8 || clk > GraphTraceLen) { - GridLocked = false; - GridOffset = 0; - PlotGridX = 0; - PlotGridXdefault = 0; - RepaintGraphWindow(); - } else { - GridLocked = true; - GridOffset = offset; - PlotGridX = clk; - PlotGridXdefault = clk; - RepaintGraphWindow(); - } + if (offset > GraphTraceLen || offset < 0) return; + if (clk < 8 || clk > GraphTraceLen) { + GridLocked = false; + GridOffset = 0; + PlotGridX = 0; + PlotGridXdefault = 0; + RepaintGraphWindow(); + } else { + GridLocked = true; + GridOffset = offset; + PlotGridX = clk; + PlotGridXdefault = clk; + RepaintGraphWindow(); + } } int CmdGrid(const char *Cmd) { - sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY); - PlotGridXdefault = PlotGridX; - PlotGridYdefault = PlotGridY; - RepaintGraphWindow(); - return 0; + sscanf(Cmd, "%i %i", &PlotGridX, &PlotGridY); + PlotGridXdefault = PlotGridX; + PlotGridYdefault = PlotGridY; + RepaintGraphWindow(); + return 0; } int CmdSetGraphMarkers(const char *Cmd) { - sscanf(Cmd, "%i %i", &CursorCPos, &CursorDPos); - RepaintGraphWindow(); - return 0; + sscanf(Cmd, "%i %i", &CursorCPos, &CursorDPos); + RepaintGraphWindow(); + return 0; } int CmdHexsamples(const char *Cmd) { - int i, j, requested = 0, offset = 0; - char string_buf[25]; - char* string_ptr = string_buf; - uint8_t got[BIGBUF_SIZE]; + int i, j, requested = 0, offset = 0; + char string_buf[25]; + char* string_ptr = string_buf; + uint8_t got[BIGBUF_SIZE]; - sscanf(Cmd, "%i %i", &requested, &offset); + sscanf(Cmd, "%i %i", &requested, &offset); - /* if no args send something */ - if (requested == 0) - requested = 8; + /* if no args send something */ + if (requested == 0) + requested = 8; - if (offset + requested > sizeof(got)) { - PrintAndLogEx(NORMAL, "Tried to read past end of buffer, + > %d", BIGBUF_SIZE); - return 0; - } + if (offset + requested > sizeof(got)) { + PrintAndLogEx(NORMAL, "Tried to read past end of buffer, + > %d", BIGBUF_SIZE); + return 0; + } - if ( !GetFromDevice(BIG_BUF, got, requested, offset, NULL, 2500, false)) { - PrintAndLogEx(WARNING, "command execution time out"); - return false; - } + if ( !GetFromDevice(BIG_BUF, got, requested, offset, NULL, 2500, false)) { + PrintAndLogEx(WARNING, "command execution time out"); + return false; + } - i = 0; - for (j = 0; j < requested; j++) { - i++; - string_ptr += sprintf(string_ptr, "%02x ", got[j]); - if (i == 8) { - *(string_ptr - 1) = '\0'; // remove the trailing space - PrintAndLogEx(NORMAL, "%s", string_buf); - string_buf[0] = '\0'; - string_ptr = string_buf; - i = 0; - } - if (j == requested - 1 && string_buf[0] != '\0') { // print any remaining bytes - *(string_ptr - 1) = '\0'; - PrintAndLogEx(NORMAL, "%s", string_buf); - string_buf[0] = '\0'; - } - } - return 0; + i = 0; + for (j = 0; j < requested; j++) { + i++; + string_ptr += sprintf(string_ptr, "%02x ", got[j]); + if (i == 8) { + *(string_ptr - 1) = '\0'; // remove the trailing space + PrintAndLogEx(NORMAL, "%s", string_buf); + string_buf[0] = '\0'; + string_ptr = string_buf; + i = 0; + } + if (j == requested - 1 && string_buf[0] != '\0') { // print any remaining bytes + *(string_ptr - 1) = '\0'; + PrintAndLogEx(NORMAL, "%s", string_buf); + string_buf[0] = '\0'; + } + } + return 0; } int CmdHide(const char *Cmd) { - HideGraphWindow(); - return 0; + HideGraphWindow(); + return 0; } //zero mean GraphBuffer int CmdHpf(const char *Cmd) { - uint8_t bits[GraphTraceLen]; - size_t size = getFromGraphBuf(bits); - removeSignalOffset(bits, size); - // push it back to graph - setGraphBuf(bits, size); - // set signal properties low/high/mean/amplitude and is_noise detection - computeSignalProperties(bits, size); + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + removeSignalOffset(bits, size); + // push it back to graph + setGraphBuf(bits, size); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(bits, size); - RepaintGraphWindow(); - return 0; + RepaintGraphWindow(); + return 0; } bool _headBit( BitstreamOut *stream) { - int bytepos = stream->position >> 3; // divide by 8 - int bitpos = (stream->position++) & 7; // mask out 00000111 - return (*(stream->buffer + bytepos) >> (7-bitpos)) & 1; + int bytepos = stream->position >> 3; // divide by 8 + int bitpos = (stream->position++) & 7; // mask out 00000111 + return (*(stream->buffer + bytepos) >> (7-bitpos)) & 1; } uint8_t getByte(uint8_t bits_per_sample, BitstreamOut* b) { - uint8_t val = 0; - for(int i = 0 ; i < bits_per_sample; i++) - val |= (_headBit(b) << (7-i)); + uint8_t val = 0; + for(int i = 0 ; i < bits_per_sample; i++) + val |= (_headBit(b) << (7-i)); - return val; + return val; } int getSamples(int n, bool silent) { - //If we get all but the last byte in bigbuf, - // we don't have to worry about remaining trash - // in the last byte in case the bits-per-sample - // does not line up on byte boundaries - uint8_t got[BIGBUF_SIZE-1] = { 0 }; + //If we get all but the last byte in bigbuf, + // we don't have to worry about remaining trash + // in the last byte in case the bits-per-sample + // does not line up on byte boundaries + uint8_t got[BIGBUF_SIZE-1] = { 0 }; - if ( n == 0 || n > sizeof(got)) - n = sizeof(got); + if ( n == 0 || n > sizeof(got)) + n = sizeof(got); - if (!silent) PrintAndLogEx(NORMAL, "Reading %d bytes from device memory\n", n); + if (!silent) PrintAndLogEx(NORMAL, "Reading %d bytes from device memory\n", n); - UsbCommand response; - if ( !GetFromDevice(BIG_BUF, got, n, 0, &response, 10000, true) ) { + UsbCommand response; + if ( !GetFromDevice(BIG_BUF, got, n, 0, &response, 10000, true) ) { PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 1; + return 1; } - if (!silent) PrintAndLogEx(NORMAL, "Data fetched"); + if (!silent) PrintAndLogEx(NORMAL, "Data fetched"); - uint8_t bits_per_sample = 8; + uint8_t bits_per_sample = 8; - //Old devices without this feature would send 0 at arg[0] - if (response.arg[0] > 0) { - sample_config *sc = (sample_config *) response.d.asBytes; - if (!silent) PrintAndLogEx(NORMAL, "Samples @ %d bits/smpl, decimation 1:%d ", sc->bits_per_sample, sc->decimation); - bits_per_sample = sc->bits_per_sample; - } + //Old devices without this feature would send 0 at arg[0] + if (response.arg[0] > 0) { + sample_config *sc = (sample_config *) response.d.asBytes; + if (!silent) PrintAndLogEx(NORMAL, "Samples @ %d bits/smpl, decimation 1:%d ", sc->bits_per_sample, sc->decimation); + bits_per_sample = sc->bits_per_sample; + } - if (bits_per_sample < 8) { + if (bits_per_sample < 8) { - if (!silent) PrintAndLogEx(NORMAL, "Unpacking..."); + if (!silent) PrintAndLogEx(NORMAL, "Unpacking..."); - BitstreamOut bout = { got, bits_per_sample * n, 0}; - int j =0; - for (j = 0; j * bits_per_sample < n * 8 && j < n; j++) { - uint8_t sample = getByte(bits_per_sample, &bout); - GraphBuffer[j] = ((int) sample )- 128; - } - GraphTraceLen = j; + BitstreamOut bout = { got, bits_per_sample * n, 0}; + int j =0; + for (j = 0; j * bits_per_sample < n * 8 && j < n; j++) { + uint8_t sample = getByte(bits_per_sample, &bout); + GraphBuffer[j] = ((int) sample )- 128; + } + GraphTraceLen = j; - if (!silent) PrintAndLogEx(NORMAL, "Unpacked %d samples" , j ); + if (!silent) PrintAndLogEx(NORMAL, "Unpacked %d samples" , j ); - } else { - for (int j = 0; j < n; j++) { - GraphBuffer[j] = ((int)got[j]) - 128; - } - GraphTraceLen = n; - } + } else { + for (int j = 0; j < n; j++) { + GraphBuffer[j] = ((int)got[j]) - 128; + } + GraphTraceLen = n; + } - uint8_t bits[GraphTraceLen]; - size_t size = getFromGraphBuf(bits); - // set signal properties low/high/mean/amplitude and is_noise detection - computeSignalProperties(bits, size); + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(bits, size); - setClockGrid(0, 0); - DemodBufferLen = 0; - RepaintGraphWindow(); - return 0; + setClockGrid(0, 0); + DemodBufferLen = 0; + RepaintGraphWindow(); + return 0; } int CmdSamples(const char *Cmd) { - int n = strtol(Cmd, NULL, 0); - return getSamples(n, false); + int n = strtol(Cmd, NULL, 0); + return getSamples(n, false); } int CmdTuneSamples(const char *Cmd) { -#define NON_VOLTAGE 1000 -#define LF_UNUSABLE_V 2000 -#define LF_MARGINAL_V 10000 -#define HF_UNUSABLE_V 3000 -#define HF_MARGINAL_V 5000 -#define ANTENNA_ERROR 1.03 // current algo has 3% error margin. +#define NON_VOLTAGE 1000 +#define LF_UNUSABLE_V 2000 +#define LF_MARGINAL_V 10000 +#define HF_UNUSABLE_V 3000 +#define HF_MARGINAL_V 5000 +#define ANTENNA_ERROR 1.03 // current algo has 3% error margin. - // hide demod plot line - DemodBufferLen = 0; - setClockGrid(0, 0); - RepaintGraphWindow(); + // hide demod plot line + DemodBufferLen = 0; + setClockGrid(0, 0); + RepaintGraphWindow(); - int timeout = 0; - PrintAndLogEx(INFO, "\nmeasuring antenna characteristics, please wait..."); + int timeout = 0; + PrintAndLogEx(INFO, "\nmeasuring antenna characteristics, please wait..."); - UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING, {0,0,0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - while (!WaitForResponseTimeout(CMD_MEASURED_ANTENNA_TUNING, &resp, 2000)) { - timeout++; - printf("."); fflush(stdout); - if (timeout > 7) { - PrintAndLogEx(WARNING, "\nno response from Proxmark. Aborting..."); - return 1; - } - } - PrintAndLogEx(NORMAL, "\n"); + UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING, {0,0,0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + while (!WaitForResponseTimeout(CMD_MEASURED_ANTENNA_TUNING, &resp, 2000)) { + timeout++; + printf("."); fflush(stdout); + if (timeout > 7) { + PrintAndLogEx(WARNING, "\nno response from Proxmark. Aborting..."); + return 1; + } + } + PrintAndLogEx(NORMAL, "\n"); - uint32_t v_lf125 = resp.arg[0]; - uint32_t v_lf134 = resp.arg[0] >> 32; + uint32_t v_lf125 = resp.arg[0]; + uint32_t v_lf134 = resp.arg[0] >> 32; - uint32_t v_hf = resp.arg[1]; - uint32_t peakf = resp.arg[2]; - uint32_t peakv = resp.arg[2] >> 32; + uint32_t v_hf = resp.arg[1]; + uint32_t peakf = resp.arg[2]; + uint32_t peakv = resp.arg[2] >> 32; - if ( v_lf125 > NON_VOLTAGE ) - PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - 125.00 kHz", (v_lf125 * ANTENNA_ERROR)/1000.0); - if ( v_lf134 > NON_VOLTAGE ) - PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - 134.00 kHz", (v_lf134 * ANTENNA_ERROR)/1000.0); - if ( peakv > NON_VOLTAGE && peakf > 0 ) - PrintAndLogEx(SUCCESS, "LF optimal: %5.2f V - %6.2f kHz", (peakv * ANTENNA_ERROR)/1000.0, 12000.0/(peakf+1)); + if ( v_lf125 > NON_VOLTAGE ) + PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - 125.00 kHz", (v_lf125 * ANTENNA_ERROR)/1000.0); + if ( v_lf134 > NON_VOLTAGE ) + PrintAndLogEx(SUCCESS, "LF antenna: %5.2f V - 134.00 kHz", (v_lf134 * ANTENNA_ERROR)/1000.0); + if ( peakv > NON_VOLTAGE && peakf > 0 ) + PrintAndLogEx(SUCCESS, "LF optimal: %5.2f V - %6.2f kHz", (peakv * ANTENNA_ERROR)/1000.0, 12000.0/(peakf+1)); - char judgement[20]; - memset(judgement, 0, sizeof(judgement)); - // LF evaluation - if (peakv < LF_UNUSABLE_V) - sprintf(judgement, _RED_(UNUSABLE) ); - else if (peakv < LF_MARGINAL_V) - sprintf(judgement, _YELLOW_(MARGINAL) ); - else - sprintf(judgement, _GREEN_(OK) ); + char judgement[20]; + memset(judgement, 0, sizeof(judgement)); + // LF evaluation + if (peakv < LF_UNUSABLE_V) + sprintf(judgement, _RED_(UNUSABLE) ); + else if (peakv < LF_MARGINAL_V) + sprintf(judgement, _YELLOW_(MARGINAL) ); + else + sprintf(judgement, _GREEN_(OK) ); - PrintAndLogEx(NORMAL, "%sLF antenna is %s \n" - , (peakv < LF_UNUSABLE_V) ? _CYAN_([!]) : _GREEN_([+]) - , judgement - ); + PrintAndLogEx(NORMAL, "%sLF antenna is %s \n" + , (peakv < LF_UNUSABLE_V) ? _CYAN_([!]) : _GREEN_([+]) + , judgement + ); - // HF evaluation - if ( v_hf > NON_VOLTAGE ) - PrintAndLogEx(SUCCESS, "HF antenna: %5.2f V - 13.56 MHz", (v_hf * ANTENNA_ERROR)/1000.0); + // HF evaluation + if ( v_hf > NON_VOLTAGE ) + PrintAndLogEx(SUCCESS, "HF antenna: %5.2f V - 13.56 MHz", (v_hf * ANTENNA_ERROR)/1000.0); - memset(judgement, 0, sizeof(judgement)); + memset(judgement, 0, sizeof(judgement)); - if (v_hf < HF_UNUSABLE_V) - sprintf(judgement, _RED_(UNUSABLE) ); - else if (v_hf < HF_MARGINAL_V) - sprintf(judgement, _YELLOW_(MARGINAL) ); - else - sprintf(judgement, _GREEN_(OK) ); + if (v_hf < HF_UNUSABLE_V) + sprintf(judgement, _RED_(UNUSABLE) ); + else if (v_hf < HF_MARGINAL_V) + sprintf(judgement, _YELLOW_(MARGINAL) ); + else + sprintf(judgement, _GREEN_(OK) ); - PrintAndLogEx(NORMAL, "%sHF antenna is %s" - , (v_hf < HF_UNUSABLE_V) ? _CYAN_([!]) : _GREEN_([+]) - , judgement - ); + PrintAndLogEx(NORMAL, "%sHF antenna is %s" + , (v_hf < HF_UNUSABLE_V) ? _CYAN_([!]) : _GREEN_([+]) + , judgement + ); - // graph LF measurements - // even here, these values has 3% error. - uint16_t test = 0; - for (int i = 0; i < 256; i++) { - GraphBuffer[i] = resp.d.asBytes[i] - 128; - test += resp.d.asBytes[i]; - } - if ( test > 0 ) { - PrintAndLogEx(SUCCESS, "\nDisplaying LF tuning graph. Divisor 89 is 134khz, 95 is 125khz.\n\n"); - GraphTraceLen = 256; - ShowGraphWindow(); - RepaintGraphWindow(); - } else { + // graph LF measurements + // even here, these values has 3% error. + uint16_t test = 0; + for (int i = 0; i < 256; i++) { + GraphBuffer[i] = resp.d.asBytes[i] - 128; + test += resp.d.asBytes[i]; + } + if ( test > 0 ) { + PrintAndLogEx(SUCCESS, "\nDisplaying LF tuning graph. Divisor 89 is 134khz, 95 is 125khz.\n\n"); + GraphTraceLen = 256; + ShowGraphWindow(); + RepaintGraphWindow(); + } else { - PrintAndLogEx(FAILED, "\nNot showing LF tuning graph since all values is zero.\n\n"); - } + PrintAndLogEx(FAILED, "\nNot showing LF tuning graph since all values is zero.\n\n"); + } - return 0; + return 0; } int CmdLoad(const char *Cmd) { - char filename[FILE_PATH_SIZE] = {0x00}; - int len = 0; + char filename[FILE_PATH_SIZE] = {0x00}; + int len = 0; + + len = strlen(Cmd); + if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; + memcpy(filename, Cmd, len); + + FILE *f = fopen(filename, "r"); + if (!f) { + PrintAndLogEx(WARNING, "couldn't open '%s'", filename); + return 0; + } + + GraphTraceLen = 0; + char line[80]; + while (fgets(line, sizeof (line), f)) { + GraphBuffer[GraphTraceLen] = atoi(line); + GraphTraceLen++; - len = strlen(Cmd); - if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; - memcpy(filename, Cmd, len); - - FILE *f = fopen(filename, "r"); - if (!f) { - PrintAndLogEx(WARNING, "couldn't open '%s'", filename); - return 0; - } - - GraphTraceLen = 0; - char line[80]; - while (fgets(line, sizeof (line), f)) { - GraphBuffer[GraphTraceLen] = atoi(line); - GraphTraceLen++; - if ( GraphTraceLen >= MAX_GRAPH_TRACE_LEN ) break; - } - - if (f) - fclose(f); + } - PrintAndLogEx(SUCCESS, "loaded %d samples", GraphTraceLen); + if (f) + fclose(f); - uint8_t bits[GraphTraceLen]; - size_t size = getFromGraphBuf(bits); - - removeSignalOffset(bits, size); - setGraphBuf(bits, size); - computeSignalProperties(bits, size); + PrintAndLogEx(SUCCESS, "loaded %d samples", GraphTraceLen); - setClockGrid(0,0); - DemodBufferLen = 0; - RepaintGraphWindow(); - return 0; + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + + removeSignalOffset(bits, size); + setGraphBuf(bits, size); + computeSignalProperties(bits, size); + + setClockGrid(0,0); + DemodBufferLen = 0; + RepaintGraphWindow(); + return 0; } // trim graph from the end int CmdLtrim(const char *Cmd) { - // sanitycheck - if (GraphTraceLen <= 0) return 1; + // sanitycheck + if (GraphTraceLen <= 0) return 1; - int ds = atoi(Cmd); - for (int i = ds; i < GraphTraceLen; ++i) - GraphBuffer[i-ds] = GraphBuffer[i]; + int ds = atoi(Cmd); + for (int i = ds; i < GraphTraceLen; ++i) + GraphBuffer[i-ds] = GraphBuffer[i]; - GraphTraceLen -= ds; - RepaintGraphWindow(); - return 0; + GraphTraceLen -= ds; + RepaintGraphWindow(); + return 0; } // trim graph from the beginning int CmdRtrim(const char *Cmd) { - int ds = atoi(Cmd); + int ds = atoi(Cmd); - // sanitycheck - if (GraphTraceLen <= ds) return 1; + // sanitycheck + if (GraphTraceLen <= ds) return 1; - GraphTraceLen = ds; - RepaintGraphWindow(); - return 0; + GraphTraceLen = ds; + RepaintGraphWindow(); + return 0; } // trim graph (middle) piece int CmdMtrim(const char *Cmd) { - int start = 0, stop = 0; - sscanf(Cmd, "%i %i", &start, &stop); + int start = 0, stop = 0; + sscanf(Cmd, "%i %i", &start, &stop); - if (start > GraphTraceLen || stop > GraphTraceLen || start > stop) return 1; + if (start > GraphTraceLen || stop > GraphTraceLen || start > stop) return 1; - // leave start position sample - start++; + // leave start position sample + start++; - GraphTraceLen = stop - start; - for (int i = 0; i < GraphTraceLen; i++) - GraphBuffer[i] = GraphBuffer[start+i]; + GraphTraceLen = stop - start; + for (int i = 0; i < GraphTraceLen; i++) + GraphBuffer[i] = GraphBuffer[start+i]; - return 0; + return 0; } int CmdNorm(const char *Cmd) { - int i; - int max = INT_MIN, min = INT_MAX; + int i; + int max = INT_MIN, min = INT_MAX; - // Find local min, max - for (i = 10; i < GraphTraceLen; ++i) { - if (GraphBuffer[i] > max) max = GraphBuffer[i]; - if (GraphBuffer[i] < min) min = GraphBuffer[i]; - } + // Find local min, max + for (i = 10; i < GraphTraceLen; ++i) { + if (GraphBuffer[i] > max) max = GraphBuffer[i]; + if (GraphBuffer[i] < min) min = GraphBuffer[i]; + } - if (max != min) { - for (i = 0; i < GraphTraceLen; ++i) { - GraphBuffer[i] = ((long)(GraphBuffer[i] - ((max + min) / 2)) * 256) / (max - min); - //marshmelow: adjusted *1000 to *256 to make +/- 128 so demod commands still work - } - } + if (max != min) { + for (i = 0; i < GraphTraceLen; ++i) { + GraphBuffer[i] = ((long)(GraphBuffer[i] - ((max + min) / 2)) * 256) / (max - min); + //marshmelow: adjusted *1000 to *256 to make +/- 128 so demod commands still work + } + } - uint8_t bits[GraphTraceLen]; - size_t size = getFromGraphBuf(bits); - // set signal properties low/high/mean/amplitude and is_noise detection - computeSignalProperties(bits, size); + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(bits, size); - RepaintGraphWindow(); - return 0; + RepaintGraphWindow(); + return 0; } int CmdPlot(const char *Cmd) { - ShowGraphWindow(); - return 0; + ShowGraphWindow(); + return 0; } int CmdSave(const char *Cmd) { - int len = 0; - char filename[FILE_PATH_SIZE] = {0x00}; + int len = 0; + char filename[FILE_PATH_SIZE] = {0x00}; - len = strlen(Cmd); - if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; - memcpy(filename, Cmd, len); + len = strlen(Cmd); + if (len > FILE_PATH_SIZE) len = FILE_PATH_SIZE; + memcpy(filename, Cmd, len); - FILE *f = fopen(filename, "w"); - if(!f) { - PrintAndLogEx(WARNING, "couldn't open '%s'", filename); - return 0; - } + FILE *f = fopen(filename, "w"); + if(!f) { + PrintAndLogEx(WARNING, "couldn't open '%s'", filename); + return 0; + } - for (int i = 0; i < GraphTraceLen; i++) - fprintf(f, "%d\n", GraphBuffer[i]); + for (int i = 0; i < GraphTraceLen; i++) + fprintf(f, "%d\n", GraphBuffer[i]); - if (f) - fclose(f); + if (f) + fclose(f); - PrintAndLogEx(SUCCESS, "saved to '%s'", Cmd); - return 0; + PrintAndLogEx(SUCCESS, "saved to '%s'", Cmd); + return 0; } int CmdScale(const char *Cmd) { - CursorScaleFactor = atoi(Cmd); - if (CursorScaleFactor == 0) { - PrintAndLogEx(FAILED, "bad, can't have zero scale"); - CursorScaleFactor = 1; - } - RepaintGraphWindow(); - return 0; + CursorScaleFactor = atoi(Cmd); + if (CursorScaleFactor == 0) { + PrintAndLogEx(FAILED, "bad, can't have zero scale"); + CursorScaleFactor = 1; + } + RepaintGraphWindow(); + return 0; } int directionalThreshold(const int* in, int *out, size_t len, int8_t up, int8_t down) { - int lastValue = in[0]; + int lastValue = in[0]; - // Will be changed at the end, but init 0 as we adjust to last samples - // value if no threshold kicks in. - out[0] = 0; + // Will be changed at the end, but init 0 as we adjust to last samples + // value if no threshold kicks in. + out[0] = 0; - for (size_t i = 1; i < len; ++i) { - // Apply first threshold to samples heading up - if (in[i] >= up && in[i] > lastValue) - { - lastValue = out[i]; // Buffer last value as we overwrite it. - out[i] = 1; - } - // Apply second threshold to samples heading down - else if (in[i] <= down && in[i] < lastValue) - { - lastValue = out[i]; // Buffer last value as we overwrite it. - out[i] = -1; - } - else - { - lastValue = out[i]; // Buffer last value as we overwrite it. - out[i] = out[i-1]; - } - } + for (size_t i = 1; i < len; ++i) { + // Apply first threshold to samples heading up + if (in[i] >= up && in[i] > lastValue) + { + lastValue = out[i]; // Buffer last value as we overwrite it. + out[i] = 1; + } + // Apply second threshold to samples heading down + else if (in[i] <= down && in[i] < lastValue) + { + lastValue = out[i]; // Buffer last value as we overwrite it. + out[i] = -1; + } + else + { + lastValue = out[i]; // Buffer last value as we overwrite it. + out[i] = out[i-1]; + } + } - // Align with first edited sample. - out[0] = out[1]; - return 0; + // Align with first edited sample. + out[0] = out[1]; + return 0; } int CmdDirectionalThreshold(const char *Cmd) { - int8_t up = param_get8(Cmd, 0); - int8_t down = param_get8(Cmd, 1); + int8_t up = param_get8(Cmd, 0); + int8_t down = param_get8(Cmd, 1); - PrintAndLogEx(INFO, "Applying Up Threshold: %d, Down Threshold: %d\n", up, down); + PrintAndLogEx(INFO, "Applying Up Threshold: %d, Down Threshold: %d\n", up, down); - directionalThreshold(GraphBuffer, GraphBuffer, GraphTraceLen, up, down); + directionalThreshold(GraphBuffer, GraphBuffer, GraphTraceLen, up, down); - // set signal properties low/high/mean/amplitude and isnoice detection - uint8_t bits[GraphTraceLen]; - size_t size = getFromGraphBuf(bits); - // set signal properties low/high/mean/amplitude and is_noice detection - computeSignalProperties(bits, size); + // set signal properties low/high/mean/amplitude and isnoice detection + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + // set signal properties low/high/mean/amplitude and is_noice detection + computeSignalProperties(bits, size); - RepaintGraphWindow(); - return 0; + RepaintGraphWindow(); + return 0; } int CmdZerocrossings(const char *Cmd) { - // Zero-crossings aren't meaningful unless the signal is zero-mean. - CmdHpf(""); + // Zero-crossings aren't meaningful unless the signal is zero-mean. + CmdHpf(""); - int sign = 1, zc = 0, lastZc = 0; + int sign = 1, zc = 0, lastZc = 0; - for (int i = 0; i < GraphTraceLen; ++i) { - if (GraphBuffer[i] * sign >= 0) { - // No change in sign, reproduce the previous sample count. - zc++; - GraphBuffer[i] = lastZc; - } else { - // Change in sign, reset the sample count. - sign = -sign; - GraphBuffer[i] = lastZc; - if (sign > 0) { - lastZc = zc; - zc = 0; - } - } - } + for (int i = 0; i < GraphTraceLen; ++i) { + if (GraphBuffer[i] * sign >= 0) { + // No change in sign, reproduce the previous sample count. + zc++; + GraphBuffer[i] = lastZc; + } else { + // Change in sign, reset the sample count. + sign = -sign; + GraphBuffer[i] = lastZc; + if (sign > 0) { + lastZc = zc; + zc = 0; + } + } + } - uint8_t bits[GraphTraceLen]; - size_t size = getFromGraphBuf(bits); - // set signal properties low/high/mean/amplitude and is_noise detection - computeSignalProperties(bits, size); + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(bits, size); - RepaintGraphWindow(); - return 0; + RepaintGraphWindow(); + return 0; } /** @@ -1833,304 +1833,304 @@ int CmdZerocrossings(const char *Cmd) { * @return */ int Cmdbin2hex(const char *Cmd) { - int bg = 0, en = 0; - if (param_getptr(Cmd, &bg, &en, 0)) - return usage_data_bin2hex(); + 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 *) calloc(bytelen, sizeof(uint8_t)); - memset(arr, 0, bytelen); - BitstreamOut bout = { arr, 0, 0 }; + //Number of digits supplied as argument + size_t length = en - bg + 1; + size_t bytelen = (length+7) / 8; + uint8_t* arr = (uint8_t *) calloc(bytelen, sizeof(uint8_t)); + 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 - PrintAndLogEx(NORMAL, "Ignoring '%c'", c); - } + for (; bg <= en; bg++) { + char c = Cmd[bg]; + if( c == '1') + pushBit(&bout, 1); + else if( c == '0') + pushBit(&bout, 0); + else + PrintAndLogEx(NORMAL, "Ignoring '%c'", c); + } - if (bout.numbits % 8 != 0) - PrintAndLogEx(NORMAL, "[padded with %d zeroes]", 8 - (bout.numbits % 8)); + if (bout.numbits % 8 != 0) + PrintAndLogEx(NORMAL, "[padded with %d zeroes]", 8 - (bout.numbits % 8)); - PrintAndLogEx(NORMAL, "%s", sprint_hex(arr, bytelen)); - free(arr); - return 0; + PrintAndLogEx(NORMAL, "%s", sprint_hex(arr, bytelen)); + free(arr); + return 0; } int Cmdhex2bin(const char *Cmd) { - int bg = 0, en = 0; - if (param_getptr(Cmd, &bg, &en, 0)) return usage_data_hex2bin(); + 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; + 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) - PrintAndLogEx(NORMAL, "%d",(x >> (3 - i)) & 1); - } - PrintAndLogEx(NORMAL, "\n"); - return 0; + //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) + PrintAndLogEx(NORMAL, "%d",(x >> (3 - i)) & 1); + } + PrintAndLogEx(NORMAL, "\n"); + return 0; } - /* // example of FSK2 RF/50 Tones - static const int LowTone[] = { - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, - 1, 1, 1, 1, 1, -1, -1, -1, -1, -1 - }; - static const int HighTone[] = { - 1, 1, 1, 1, 1, -1, -1, -1, -1, // note one extra 1 to padd due to 50/8 remainder (1/2 the remainder) - 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, - 1, 1, 1, 1, -1, -1, -1, -1, -1, // note one extra -1 to padd due to 50/8 remainder - }; - */ + /* // example of FSK2 RF/50 Tones + static const int LowTone[] = { + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1, + 1, 1, 1, 1, 1, -1, -1, -1, -1, -1 + }; + static const int HighTone[] = { + 1, 1, 1, 1, 1, -1, -1, -1, -1, // note one extra 1 to padd due to 50/8 remainder (1/2 the remainder) + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, + 1, 1, 1, 1, -1, -1, -1, -1, -1, // note one extra -1 to padd due to 50/8 remainder + }; + */ void GetHiLoTone(int *LowTone, int *HighTone, int clk, int LowToneFC, int HighToneFC) { - int i,j=0; - int Left_Modifier = ((clk % LowToneFC) % 2) + ((clk % LowToneFC)/2); - int Right_Modifier = (clk % LowToneFC) / 2; - //int HighToneMod = clk mod HighToneFC; - int LeftHalfFCCnt = (LowToneFC % 2) + (LowToneFC/2); //truncate - int FCs_per_clk = clk / LowToneFC; + int i,j=0; + int Left_Modifier = ((clk % LowToneFC) % 2) + ((clk % LowToneFC)/2); + int Right_Modifier = (clk % LowToneFC) / 2; + //int HighToneMod = clk mod HighToneFC; + int LeftHalfFCCnt = (LowToneFC % 2) + (LowToneFC/2); //truncate + int FCs_per_clk = clk / LowToneFC; - // need to correctly split up the clock to field clocks. - // First attempt uses modifiers on each end to make up for when FCs don't evenly divide into Clk + // need to correctly split up the clock to field clocks. + // First attempt uses modifiers on each end to make up for when FCs don't evenly divide into Clk - // start with LowTone - // set extra 1 modifiers to make up for when FC doesn't divide evenly into Clk - for (i = 0; i < Left_Modifier; i++) { - LowTone[i] = 1; - } + // start with LowTone + // set extra 1 modifiers to make up for when FC doesn't divide evenly into Clk + for (i = 0; i < Left_Modifier; i++) { + LowTone[i] = 1; + } - // loop # of field clocks inside the main clock - for (i = 0; i < (FCs_per_clk); i++) { - // loop # of samples per field clock - for (j = 0; j < LowToneFC; j++) { - LowTone[ (i * LowToneFC) + Left_Modifier + j] = ( j < LeftHalfFCCnt ) ? 1 : -1; - } - } + // loop # of field clocks inside the main clock + for (i = 0; i < (FCs_per_clk); i++) { + // loop # of samples per field clock + for (j = 0; j < LowToneFC; j++) { + LowTone[ (i * LowToneFC) + Left_Modifier + j] = ( j < LeftHalfFCCnt ) ? 1 : -1; + } + } - int k; - // add last -1 modifiers - for (k = 0; k < Right_Modifier; k++) { - LowTone[ ( (i-1) * LowToneFC) + Left_Modifier + j + k] = -1; - } + int k; + // add last -1 modifiers + for (k = 0; k < Right_Modifier; k++) { + LowTone[ ( (i-1) * LowToneFC) + Left_Modifier + j + k] = -1; + } - // now do hightone - Left_Modifier = ((clk % HighToneFC) % 2) + ((clk % HighToneFC)/2); - Right_Modifier = (clk % HighToneFC) / 2; - LeftHalfFCCnt = (HighToneFC % 2) + (HighToneFC/2); //truncate - FCs_per_clk = clk/HighToneFC; + // now do hightone + Left_Modifier = ((clk % HighToneFC) % 2) + ((clk % HighToneFC)/2); + Right_Modifier = (clk % HighToneFC) / 2; + LeftHalfFCCnt = (HighToneFC % 2) + (HighToneFC/2); //truncate + FCs_per_clk = clk/HighToneFC; - for (i = 0; i < Left_Modifier; i++) { - HighTone[i] = 1; - } + for (i = 0; i < Left_Modifier; i++) { + HighTone[i] = 1; + } - // loop # of field clocks inside the main clock - for (i = 0; i < (FCs_per_clk); i++) { - // loop # of samples per field clock - for (j = 0; j < HighToneFC; j++) { - HighTone[(i * HighToneFC) + Left_Modifier + j] = ( j < LeftHalfFCCnt ) ? 1 : -1; - } - } + // loop # of field clocks inside the main clock + for (i = 0; i < (FCs_per_clk); i++) { + // loop # of samples per field clock + for (j = 0; j < HighToneFC; j++) { + HighTone[(i * HighToneFC) + Left_Modifier + j] = ( j < LeftHalfFCCnt ) ? 1 : -1; + } + } - // add last -1 modifiers - for (k = 0; k < Right_Modifier; k++) { - PrintAndLogEx(NORMAL, "(i-1)*HighToneFC+lm+j+k %i", ((i-1) * HighToneFC) + Left_Modifier + j + k); - HighTone[ ( (i-1) * HighToneFC) + Left_Modifier + j + k] = -1; - } - if (g_debugMode == 2) { - for ( i = 0; i < clk; i++) { - PrintAndLogEx(NORMAL, "Low: %i, High: %i", LowTone[i], HighTone[i]); - } - } + // add last -1 modifiers + for (k = 0; k < Right_Modifier; k++) { + PrintAndLogEx(NORMAL, "(i-1)*HighToneFC+lm+j+k %i", ((i-1) * HighToneFC) + Left_Modifier + j + k); + HighTone[ ( (i-1) * HighToneFC) + Left_Modifier + j + k] = -1; + } + if (g_debugMode == 2) { + for ( i = 0; i < clk; i++) { + PrintAndLogEx(NORMAL, "Low: %i, High: %i", LowTone[i], HighTone[i]); + } + } } //old CmdFSKdemod adapted by marshmellow //converts FSK to clear NRZ style wave. (or demodulates) int FSKToNRZ(int *data, int *dataLen, int clk, int LowToneFC, int HighToneFC) { - uint8_t ans = 0; - if (clk == 0 || LowToneFC == 0 || HighToneFC == 0) { - int firstClockEdge=0; - ans = fskClocks((uint8_t *) &LowToneFC, (uint8_t *) &HighToneFC, (uint8_t *) &clk, &firstClockEdge); - if (g_debugMode > 1) { - PrintAndLog ("DEBUG FSKtoNRZ: detected clocks: fc_low %i, fc_high %i, clk %i, firstClockEdge %i, ans %u", LowToneFC, HighToneFC, clk, firstClockEdge, ans); - } - } - // currently only know fsk modulations with field clocks < 10 samples and > 4 samples. filter out to remove false positives (and possibly destroying ask/psk modulated waves...) - if (ans == 0 || clk == 0 || LowToneFC == 0 || HighToneFC == 0 || LowToneFC > 10 || HighToneFC < 4) { - if (g_debugMode > 1) { - PrintAndLog ("DEBUG FSKtoNRZ: no fsk clocks found"); - } - return 0; - } + uint8_t ans = 0; + if (clk == 0 || LowToneFC == 0 || HighToneFC == 0) { + int firstClockEdge=0; + ans = fskClocks((uint8_t *) &LowToneFC, (uint8_t *) &HighToneFC, (uint8_t *) &clk, &firstClockEdge); + if (g_debugMode > 1) { + PrintAndLog ("DEBUG FSKtoNRZ: detected clocks: fc_low %i, fc_high %i, clk %i, firstClockEdge %i, ans %u", LowToneFC, HighToneFC, clk, firstClockEdge, ans); + } + } + // currently only know fsk modulations with field clocks < 10 samples and > 4 samples. filter out to remove false positives (and possibly destroying ask/psk modulated waves...) + if (ans == 0 || clk == 0 || LowToneFC == 0 || HighToneFC == 0 || LowToneFC > 10 || HighToneFC < 4) { + if (g_debugMode > 1) { + PrintAndLog ("DEBUG FSKtoNRZ: no fsk clocks found"); + } + return 0; + } - int i, j; - int LowTone[clk]; - int HighTone[clk]; - GetHiLoTone(LowTone, HighTone, clk, LowToneFC, HighToneFC); + int i, j; + int LowTone[clk]; + int HighTone[clk]; + GetHiLoTone(LowTone, HighTone, clk, LowToneFC, HighToneFC); - // loop through ([all samples] - clk) - for (i = 0; i < *dataLen - clk; ++i) { - int lowSum = 0, highSum = 0; + // loop through ([all samples] - clk) + for (i = 0; i < *dataLen - clk; ++i) { + int lowSum = 0, highSum = 0; - // sum all samples together starting from this sample for [clk] samples for each tone (multiply tone value with sample data) - for (j = 0; j < clk; ++j) { - lowSum += LowTone[j] * data[i + j]; - highSum += HighTone[j] * data[i + j]; - } - // get abs( [average sample value per clk] * 100 ) (or a rolling average of sorts) - lowSum = abs(100 * lowSum / clk); - highSum = abs(100 * highSum / clk); - // save these back to buffer for later use - data[i] = (highSum << 16) | lowSum; - } + // sum all samples together starting from this sample for [clk] samples for each tone (multiply tone value with sample data) + for (j = 0; j < clk; ++j) { + lowSum += LowTone[j] * data[i + j]; + highSum += HighTone[j] * data[i + j]; + } + // get abs( [average sample value per clk] * 100 ) (or a rolling average of sorts) + lowSum = abs(100 * lowSum / clk); + highSum = abs(100 * highSum / clk); + // save these back to buffer for later use + data[i] = (highSum << 16) | lowSum; + } - // now we have the abs( [average sample value per clk] * 100 ) for each tone - // loop through again [all samples] - clk - 16 - // note why 16??? is 16 the largest FC? changed to LowToneFC as that should be the > fc - for(i = 0; i < *dataLen - clk - LowToneFC; ++i) { - int lowTot = 0, highTot = 0; + // now we have the abs( [average sample value per clk] * 100 ) for each tone + // loop through again [all samples] - clk - 16 + // note why 16??? is 16 the largest FC? changed to LowToneFC as that should be the > fc + for(i = 0; i < *dataLen - clk - LowToneFC; ++i) { + int lowTot = 0, highTot = 0; - // sum a field clock width of abs( [average sample values per clk] * 100) for each tone - for (j = 0; j < LowToneFC; ++j) { //10 for fsk2 - lowTot += (data[i + j] & 0xffff); - } - for (j = 0; j < HighToneFC; j++) { //8 for fsk2 - highTot += (data[i + j] >> 16); - } + // sum a field clock width of abs( [average sample values per clk] * 100) for each tone + for (j = 0; j < LowToneFC; ++j) { //10 for fsk2 + lowTot += (data[i + j] & 0xffff); + } + for (j = 0; j < HighToneFC; j++) { //8 for fsk2 + highTot += (data[i + j] >> 16); + } - // subtract the sum of lowTone averages by the sum of highTone averages as it - // and write back the new graph value - data[i] = lowTot - highTot; - } - // update dataLen to what we put back to the data sample buffer - *dataLen -= (clk + LowToneFC); - return 0; + // subtract the sum of lowTone averages by the sum of highTone averages as it + // and write back the new graph value + data[i] = lowTot - highTot; + } + // update dataLen to what we put back to the data sample buffer + *dataLen -= (clk + LowToneFC); + return 0; } int CmdFSKToNRZ(const char *Cmd) { - // take clk, fc_low, fc_high - // blank = auto; - bool errors = false; - char cmdp = 0; - int clk = 0, fc_low = 10, fc_high = 8; - while (param_getchar(Cmd, cmdp) != 0x00) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_data_fsktonrz(); - case 'c': - clk = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - case 'f': - fc_high = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - case 'l': - fc_low = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - if(errors) break; - } - //Validations - if (errors) return usage_data_fsktonrz(); + // take clk, fc_low, fc_high + // blank = auto; + bool errors = false; + char cmdp = 0; + int clk = 0, fc_low = 10, fc_high = 8; + while (param_getchar(Cmd, cmdp) != 0x00) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_data_fsktonrz(); + case 'c': + clk = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 'f': + fc_high = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 'l': + fc_low = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + if(errors) break; + } + //Validations + if (errors) return usage_data_fsktonrz(); - setClockGrid(0, 0); - DemodBufferLen = 0; - int ans = FSKToNRZ(GraphBuffer, &GraphTraceLen, clk, fc_low, fc_high); - CmdNorm(""); - RepaintGraphWindow(); - return ans; + setClockGrid(0, 0); + DemodBufferLen = 0; + int ans = FSKToNRZ(GraphBuffer, &GraphTraceLen, clk, fc_low, fc_high); + CmdNorm(""); + RepaintGraphWindow(); + return ans; } int CmdDataIIR(const char *Cmd){ - uint8_t k = param_get8(Cmd, 0); - //iceIIR_Butterworth(GraphBuffer, GraphTraceLen); - iceSimple_Filter(GraphBuffer, GraphTraceLen, k); + uint8_t k = param_get8(Cmd, 0); + //iceIIR_Butterworth(GraphBuffer, GraphTraceLen); + iceSimple_Filter(GraphBuffer, GraphTraceLen, k); - uint8_t bits[GraphTraceLen]; - size_t size = getFromGraphBuf(bits); - // set signal properties low/high/mean/amplitude and is_noise detection - computeSignalProperties(bits, size); - RepaintGraphWindow(); - return 0; + uint8_t bits[GraphTraceLen]; + size_t size = getFromGraphBuf(bits); + // set signal properties low/high/mean/amplitude and is_noise detection + computeSignalProperties(bits, size); + RepaintGraphWindow(); + return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"askedgedetect", CmdAskEdgeDetect, 1, "[threshold] Adjust Graph for manual ASK demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)"}, - {"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, " -- Converts binary to hexadecimal"}, - {"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"}, - {"buffclear", CmdBuffClear, 1, "Clears bigbuff on deviceside and graph window"}, - {"dec", CmdDec, 1, "Decimate samples"}, - {"detectclock", CmdDetectClockRate, 1, "[] Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer"}, - {"fsktonrz", CmdFSKToNRZ, 1, "Convert fsk2 to nrz wave for alternate fsk demodulating (for weak fsk)"}, + {"help", CmdHelp, 1, "This help"}, + {"askedgedetect", CmdAskEdgeDetect, 1, "[threshold] Adjust Graph for manual ASK demod using the length of sample differences to detect the edge of a wave (use 20-45, def:25)"}, + {"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, " -- Converts binary to hexadecimal"}, + {"bitsamples", CmdBitsamples, 0, "Get raw samples as bitstring"}, + {"buffclear", CmdBuffClear, 1, "Clears bigbuff on deviceside and graph window"}, + {"dec", CmdDec, 1, "Decimate samples"}, + {"detectclock", CmdDetectClockRate, 1, "[] Detect ASK, FSK, NRZ, PSK clock rate of wave in GraphBuffer"}, + {"fsktonrz", CmdFSKToNRZ, 1, "Convert fsk2 to nrz wave for alternate fsk demodulating (for weak fsk)"}, - {"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, " -- 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"}, - {"ltrim", CmdLtrim, 1, " -- Trim samples from left of trace"}, - {"rtrim", CmdRtrim, 1, " -- Trim samples from right of trace"}, - {"mtrim", CmdMtrim, 1, " -- Trim out samples from the specified start to the specified stop"}, - {"manrawdecode", Cmdmandecoderaw, 1, "[invert] [maxErr] -- Manchester decode binary stream in DemodBuffer"}, - {"norm", CmdNorm, 1, "Normalize max/min to +/-128"}, - {"plot", CmdPlot, 1, "Show graph window (hit 'h' in window for keystroke help)"}, - {"printdemodbuffer",CmdPrintDemodBuff, 1, "[x] [o] [l] -- print the data in the DemodBuffer - 'x' for hex output"}, - {"rawdemod", CmdRawDemod, 1, "[modulation] ... -see help (h option) -- Demodulate the data in the GraphBuffer and output binary"}, - {"samples", CmdSamples, 0, "[512 - 40000] -- Get raw samples for graph window (GraphBuffer)"}, - {"save", CmdSave, 1, " -- Save trace (from graph window)"}, - {"setgraphmarkers", CmdSetGraphMarkers, 1, "[orange_marker] [blue_marker] (in graph window)"}, - {"scale", CmdScale, 1, " -- Set cursor display scale"}, - {"setdebugmode", CmdSetDebugMode, 1, "<0|1|2> -- Turn on or off Debugging Level for lf demods"}, - {"shiftgraphzero", CmdGraphShiftZero, 1, " -- Shift 0 for Graphed wave + or - shift value"}, - {"dirthreshold", CmdDirectionalThreshold, 1, " -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."}, - {"tune", CmdTuneSamples, 0, "Get hw tune samples for graph window"}, - {"undec", CmdUndec, 1, "Un-decimate samples by 2"}, - {"zerocrossings", CmdZerocrossings, 1, "Count time between zero-crossings"}, - {"iir", CmdDataIIR, 0, "apply IIR buttersworth filter on plotdata"}, - {NULL, NULL, 0, NULL} + {"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, " -- 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"}, + {"ltrim", CmdLtrim, 1, " -- Trim samples from left of trace"}, + {"rtrim", CmdRtrim, 1, " -- Trim samples from right of trace"}, + {"mtrim", CmdMtrim, 1, " -- Trim out samples from the specified start to the specified stop"}, + {"manrawdecode", Cmdmandecoderaw, 1, "[invert] [maxErr] -- Manchester decode binary stream in DemodBuffer"}, + {"norm", CmdNorm, 1, "Normalize max/min to +/-128"}, + {"plot", CmdPlot, 1, "Show graph window (hit 'h' in window for keystroke help)"}, + {"printdemodbuffer",CmdPrintDemodBuff, 1, "[x] [o] [l] -- print the data in the DemodBuffer - 'x' for hex output"}, + {"rawdemod", CmdRawDemod, 1, "[modulation] ... -see help (h option) -- Demodulate the data in the GraphBuffer and output binary"}, + {"samples", CmdSamples, 0, "[512 - 40000] -- Get raw samples for graph window (GraphBuffer)"}, + {"save", CmdSave, 1, " -- Save trace (from graph window)"}, + {"setgraphmarkers", CmdSetGraphMarkers, 1, "[orange_marker] [blue_marker] (in graph window)"}, + {"scale", CmdScale, 1, " -- Set cursor display scale"}, + {"setdebugmode", CmdSetDebugMode, 1, "<0|1|2> -- Turn on or off Debugging Level for lf demods"}, + {"shiftgraphzero", CmdGraphShiftZero, 1, " -- Shift 0 for Graphed wave + or - shift value"}, + {"dirthreshold", CmdDirectionalThreshold, 1, " -- Max rising higher up-thres/ Min falling lower down-thres, keep rest as prev."}, + {"tune", CmdTuneSamples, 0, "Get hw tune samples for graph window"}, + {"undec", CmdUndec, 1, "Un-decimate samples by 2"}, + {"zerocrossings", CmdZerocrossings, 1, "Count time between zero-crossings"}, + {"iir", CmdDataIIR, 0, "apply IIR buttersworth filter on plotdata"}, + {NULL, NULL, 0, NULL} }; int CmdData(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } diff --git a/client/cmddata.h b/client/cmddata.h index 27c446ecb..605bc3298 100644 --- a/client/cmddata.h +++ b/client/cmddata.h @@ -22,7 +22,7 @@ #include // for CmdNorm INT_MIN && INT_MAX #include "util.h" #include "cmdmain.h" -#include "proxmark3.h" // sendcommand +#include "proxmark3.h"// sendcommand #include "ui.h" // for show graph controls #include "graph.h" // for graph data #include "comms.h" diff --git a/client/cmdflashmem.c b/client/cmdflashmem.c index b576f43f7..f6a6e8518 100644 --- a/client/cmdflashmem.c +++ b/client/cmdflashmem.c @@ -27,435 +27,435 @@ static int CmdHelp(const char *Cmd); int usage_flashmem_spibaud(void){ - PrintAndLogEx(NORMAL, "Usage: mem spibaud [h] "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " SPI baudrate in MHz [24|48]"); - PrintAndLogEx(NORMAL, " "); - PrintAndLogEx(NORMAL, " If >= 24Mhz, FASTREADS instead of READS instruction will be used."); - PrintAndLogEx(NORMAL, " Reading Flash ID will virtually always fail under 48Mhz setting"); - PrintAndLogEx(NORMAL, " Unless you know what you are doing, please stay at 24Mhz"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " mem spibaud 48"); - return 0; + PrintAndLogEx(NORMAL, "Usage: mem spibaud [h] "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " SPI baudrate in MHz [24|48]"); + PrintAndLogEx(NORMAL, " "); + PrintAndLogEx(NORMAL, " If >= 24Mhz, FASTREADS instead of READS instruction will be used."); + PrintAndLogEx(NORMAL, " Reading Flash ID will virtually always fail under 48Mhz setting"); + PrintAndLogEx(NORMAL, " Unless you know what you are doing, please stay at 24Mhz"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " mem spibaud 48"); + return 0; } int usage_flashmem_read(void){ - PrintAndLogEx(NORMAL, "Read flash memory on device"); - PrintAndLogEx(NORMAL, "Usage: mem read o l "); - PrintAndLogEx(NORMAL, " o : offset in memory"); - PrintAndLogEx(NORMAL, " l : length"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " mem read o 0 l 32"); // read 32 bytes starting at offset 0 - PrintAndLogEx(NORMAL, " mem read o 1024 l 10"); // read 10 bytes starting at offset 1024 - return 0; + PrintAndLogEx(NORMAL, "Read flash memory on device"); + PrintAndLogEx(NORMAL, "Usage: mem read o l "); + PrintAndLogEx(NORMAL, " o : offset in memory"); + PrintAndLogEx(NORMAL, " l : length"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " mem read o 0 l 32"); // read 32 bytes starting at offset 0 + PrintAndLogEx(NORMAL, " mem read o 1024 l 10"); // read 10 bytes starting at offset 1024 + return 0; } int usage_flashmem_load(void){ - PrintAndLogEx(NORMAL, "Loads binary file into flash memory on device"); - PrintAndLogEx(NORMAL, "Usage: mem load o f m t i"); - PrintAndLogEx(NORMAL, " o : offset in memory"); - PrintAndLogEx(NORMAL, " f : file name"); - PrintAndLogEx(NORMAL, " m : upload 6 bytes keys (mifare key dictionary)"); - PrintAndLogEx(NORMAL, " i : upload 8 bytes keys (iClass key dictionary)"); - PrintAndLogEx(NORMAL, " t : upload 4 bytes keys (pwd dictionary)"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " mem load f myfile"); // upload file myfile at default offset 0 - PrintAndLogEx(NORMAL, " mem load f myfile o 1024"); // upload file myfile at offset 1024 - PrintAndLogEx(NORMAL, " mem load f default_keys m"); - PrintAndLogEx(NORMAL, " mem load f default_pwd t"); - PrintAndLogEx(NORMAL, " mem load f default_iclass_keys i"); - return 0; + PrintAndLogEx(NORMAL, "Loads binary file into flash memory on device"); + PrintAndLogEx(NORMAL, "Usage: mem load o f m t i"); + PrintAndLogEx(NORMAL, " o : offset in memory"); + PrintAndLogEx(NORMAL, " f : file name"); + PrintAndLogEx(NORMAL, " m : upload 6 bytes keys (mifare key dictionary)"); + PrintAndLogEx(NORMAL, " i : upload 8 bytes keys (iClass key dictionary)"); + PrintAndLogEx(NORMAL, " t : upload 4 bytes keys (pwd dictionary)"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " mem load f myfile"); // upload file myfile at default offset 0 + PrintAndLogEx(NORMAL, " mem load f myfile o 1024"); // upload file myfile at offset 1024 + PrintAndLogEx(NORMAL, " mem load f default_keys m"); + PrintAndLogEx(NORMAL, " mem load f default_pwd t"); + PrintAndLogEx(NORMAL, " mem load f default_iclass_keys i"); + return 0; } int usage_flashmem_save(void){ - PrintAndLogEx(NORMAL, "Saves flash memory on device into the file"); - PrintAndLogEx(NORMAL, " Usage: mem save o l f "); - PrintAndLogEx(NORMAL, " o : offset in memory"); - PrintAndLogEx(NORMAL, " l : length"); - PrintAndLogEx(NORMAL, " f : file name"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " mem save f myfile"); // download whole flashmem to file myfile - PrintAndLogEx(NORMAL, " mem save f myfile l 4096"); // download 4096 bytes from default offset 0 to file myfile - PrintAndLogEx(NORMAL, " mem save f myfile o 1024 l 4096"); // downlowd 4096 bytes from offset 1024 to file myfile - return 0; + PrintAndLogEx(NORMAL, "Saves flash memory on device into the file"); + PrintAndLogEx(NORMAL, " Usage: mem save o l f "); + PrintAndLogEx(NORMAL, " o : offset in memory"); + PrintAndLogEx(NORMAL, " l : length"); + PrintAndLogEx(NORMAL, " f : file name"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " mem save f myfile"); // download whole flashmem to file myfile + PrintAndLogEx(NORMAL, " mem save f myfile l 4096"); // download 4096 bytes from default offset 0 to file myfile + PrintAndLogEx(NORMAL, " mem save f myfile o 1024 l 4096"); // downlowd 4096 bytes from offset 1024 to file myfile + return 0; } int usage_flashmem_wipe(void){ - PrintAndLogEx(WARNING, "[OBS] use with caution."); - PrintAndLogEx(NORMAL, "Wipe flash memory on device, which fills memory with 0xFF\n"); + PrintAndLogEx(WARNING, "[OBS] use with caution."); + PrintAndLogEx(NORMAL, "Wipe flash memory on device, which fills memory with 0xFF\n"); - PrintAndLogEx(NORMAL, " Usage: mem wipe p "); - PrintAndLogEx(NORMAL, " p : 0,1,2 page memory"); -// PrintAndLogEx(NORMAL, " i : inital total wipe"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " mem wipe "); // wipe page 0,1,2 - PrintAndLogEx(NORMAL, " mem wipe p 0"); // wipes first page. - return 0; + PrintAndLogEx(NORMAL, " Usage: mem wipe p "); + PrintAndLogEx(NORMAL, " p : 0,1,2 page memory"); +// PrintAndLogEx(NORMAL, " i : inital total wipe"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " mem wipe "); // wipe page 0,1,2 + PrintAndLogEx(NORMAL, " mem wipe p 0"); // wipes first page. + return 0; } int usage_flashmem_info(void){ - PrintAndLogEx(NORMAL, "Collect signature and verify it from flash memory\n"); - PrintAndLogEx(NORMAL, " Usage: mem info [h|s|w]"); - PrintAndLogEx(NORMAL, " s : create a signature"); - PrintAndLogEx(NORMAL, " w : write signature to flash memory"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " mem info"); - PrintAndLogEx(NORMAL, " mem info s"); - return 0; + PrintAndLogEx(NORMAL, "Collect signature and verify it from flash memory\n"); + PrintAndLogEx(NORMAL, " Usage: mem info [h|s|w]"); + PrintAndLogEx(NORMAL, " s : create a signature"); + PrintAndLogEx(NORMAL, " w : write signature to flash memory"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " mem info"); + PrintAndLogEx(NORMAL, " mem info s"); + return 0; } int CmdFlashMemRead(const char *Cmd) { - uint8_t cmdp = 0; - bool errors = false; - uint32_t start_index = 0, len = 0; + uint8_t cmdp = 0; + bool errors = false; + uint32_t start_index = 0, len = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'o': - start_index = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - case 'l': - len = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - case 'h': - return usage_flashmem_read(); - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'o': + start_index = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 'l': + len = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 'h': + return usage_flashmem_read(); + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - //Validations - if (errors || cmdp == 0 ) return usage_flashmem_read(); + //Validations + if (errors || cmdp == 0 ) return usage_flashmem_read(); - if (start_index + len > FLASH_MEM_MAX_SIZE) { - PrintAndLogDevice(WARNING, "error, start_index + length is larger than available memory"); - return 1; - } + if (start_index + len > FLASH_MEM_MAX_SIZE) { + PrintAndLogDevice(WARNING, "error, start_index + length is larger than available memory"); + return 1; + } - UsbCommand c = {CMD_FLASHMEM_READ, {start_index, len, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_FLASHMEM_READ, {start_index, len, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } int CmdFlashmemSpiBaudrate(const char *Cmd) { - char ctmp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || ctmp == 'h') return usage_flashmem_spibaud(); - uint32_t baudrate = param_get32ex(Cmd, 0, 0, 10); - baudrate = baudrate * 1000000; - if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD ) return usage_flashmem_spibaud(); - UsbCommand c = {CMD_FLASHMEM_SET_SPIBAUDRATE, {baudrate, 0, 0}}; - SendCommand(&c); - return 0; + char ctmp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || ctmp == 'h') return usage_flashmem_spibaud(); + uint32_t baudrate = param_get32ex(Cmd, 0, 0, 10); + baudrate = baudrate * 1000000; + if (baudrate != FLASH_BAUD && baudrate != FLASH_MINBAUD ) return usage_flashmem_spibaud(); + UsbCommand c = {CMD_FLASHMEM_SET_SPIBAUDRATE, {baudrate, 0, 0}}; + SendCommand(&c); + return 0; } int CmdFlashMemLoad(const char *Cmd){ - uint32_t start_index = 0; - char filename[FILE_PATH_SIZE] = {0}; - bool errors = false; - uint8_t cmdp = 0; - Dictionary_t d = DICTIONARY_NONE; + uint32_t start_index = 0; + char filename[FILE_PATH_SIZE] = {0}; + bool errors = false; + uint8_t cmdp = 0; + Dictionary_t d = DICTIONARY_NONE; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_flashmem_load(); - case 'f': - if ( param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) { - PrintAndLogEx(FAILED, "Filename too long"); - errors = true; - break; - } - cmdp += 2; - break; - case 'o': - start_index = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - case 'm': - d = DICTIONARY_MIFARE; - cmdp++; - break; - case 't': - d = DICTIONARY_T55XX; - cmdp++; - break; - case 'i': - d = DICTIONARY_ICLASS; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_flashmem_load(); + case 'f': + if ( param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) { + PrintAndLogEx(FAILED, "Filename too long"); + errors = true; + break; + } + cmdp += 2; + break; + case 'o': + start_index = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 'm': + d = DICTIONARY_MIFARE; + cmdp++; + break; + case 't': + d = DICTIONARY_T55XX; + cmdp++; + break; + case 'i': + d = DICTIONARY_ICLASS; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - //Validations - if (errors || cmdp == 0 ) return usage_flashmem_load(); + //Validations + if (errors || cmdp == 0 ) return usage_flashmem_load(); - size_t datalen = 0; - uint16_t keycount = 0; - int res = 0; - uint8_t *data = calloc(FLASH_MEM_MAX_SIZE, sizeof(uint8_t)); + size_t datalen = 0; + uint16_t keycount = 0; + int res = 0; + uint8_t *data = calloc(FLASH_MEM_MAX_SIZE, sizeof(uint8_t)); - switch (d) { - case DICTIONARY_MIFARE: - start_index = DEFAULT_MF_KEYS_OFFSET; - res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 6, &keycount ); - if ( res || !keycount) { - free(data); - return 1; - } - data[0] = (keycount >> 0) & 0xFF; - data[1] = (keycount >> 8) & 0xFF; - datalen += 2; - break; - case DICTIONARY_T55XX: - start_index = DEFAULT_T55XX_KEYS_OFFSET; - res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 4, &keycount ); - if ( res || !keycount) { - free(data); - return 1; - } - data[0] = (keycount >> 0) & 0xFF; - data[1] = (keycount >> 8) & 0xFF; - datalen += 2; - break; - case DICTIONARY_ICLASS: - start_index = DEFAULT_ICLASS_KEYS_OFFSET; - res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 8, &keycount ); - if ( res || !keycount) { - free(data); - return 1; - } - data[0] = (keycount >> 0) & 0xFF; - data[1] = (keycount >> 8) & 0xFF; - datalen += 2; - break; - default: + switch (d) { + case DICTIONARY_MIFARE: + start_index = DEFAULT_MF_KEYS_OFFSET; + res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 6, &keycount ); + if ( res || !keycount) { + free(data); + return 1; + } + data[0] = (keycount >> 0) & 0xFF; + data[1] = (keycount >> 8) & 0xFF; + datalen += 2; + break; + case DICTIONARY_T55XX: + start_index = DEFAULT_T55XX_KEYS_OFFSET; + res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 4, &keycount ); + if ( res || !keycount) { + free(data); + return 1; + } + data[0] = (keycount >> 0) & 0xFF; + data[1] = (keycount >> 8) & 0xFF; + datalen += 2; + break; + case DICTIONARY_ICLASS: + start_index = DEFAULT_ICLASS_KEYS_OFFSET; + res = loadFileDICTIONARY(filename, "dic", data+2, &datalen, 8, &keycount ); + if ( res || !keycount) { + free(data); + return 1; + } + data[0] = (keycount >> 0) & 0xFF; + data[1] = (keycount >> 8) & 0xFF; + datalen += 2; + break; + default: - res = loadFile(filename, "bin", data, &datalen); - //int res = loadFileEML( filename, "eml", data, &datalen); - if ( res ) { - free(data); - return 1; - } + res = loadFile(filename, "bin", data, &datalen); + //int res = loadFileEML( filename, "eml", data, &datalen); + if ( res ) { + free(data); + return 1; + } - if (datalen > FLASH_MEM_MAX_SIZE) { - PrintAndLogDevice(WARNING, "error, filesize is larger than available memory"); - free(data); - return 1; - } - break; - } + if (datalen > FLASH_MEM_MAX_SIZE) { + PrintAndLogDevice(WARNING, "error, filesize is larger than available memory"); + free(data); + return 1; + } + break; + } - data = realloc(data, datalen); + data = realloc(data, datalen); - //Send to device - uint32_t bytes_sent = 0; - uint32_t bytes_remaining = datalen; + //Send to device + uint32_t bytes_sent = 0; + uint32_t bytes_remaining = datalen; - while (bytes_remaining > 0){ - uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); + while (bytes_remaining > 0){ + uint32_t bytes_in_packet = MIN(FLASH_MEM_BLOCK_SIZE, bytes_remaining); - UsbCommand c = {CMD_FLASHMEM_WRITE, {start_index + bytes_sent, bytes_in_packet, 0}}; + UsbCommand c = {CMD_FLASHMEM_WRITE, {start_index + bytes_sent, bytes_in_packet, 0}}; - memcpy(c.d.asBytes, data + bytes_sent, bytes_in_packet); - clearCommandBuffer(); - SendCommand(&c); + memcpy(c.d.asBytes, data + bytes_sent, bytes_in_packet); + clearCommandBuffer(); + SendCommand(&c); - bytes_remaining -= bytes_in_packet; - bytes_sent += bytes_in_packet; + bytes_remaining -= bytes_in_packet; + bytes_sent += bytes_in_packet; - UsbCommand resp; - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - free(data); - return 1; - } + UsbCommand resp; + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + free(data); + return 1; + } - uint8_t isok = resp.arg[0] & 0xFF; - if (!isok) - PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent); + uint8_t isok = resp.arg[0] & 0xFF; + if (!isok) + PrintAndLogEx(FAILED, "Flash write fail [offset %u]", bytes_sent); - } - free(data); + } + free(data); - PrintAndLogEx(SUCCESS, "Wrote %u bytes to offset %u", datalen, start_index); - return 0; + PrintAndLogEx(SUCCESS, "Wrote %u bytes to offset %u", datalen, start_index); + return 0; } int CmdFlashMemSave(const char *Cmd){ - char filename[FILE_PATH_SIZE] = {0}; - uint8_t cmdp = 0; - bool errors = false; - uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE; + char filename[FILE_PATH_SIZE] = {0}; + uint8_t cmdp = 0; + bool errors = false; + uint32_t start_index = 0, len = FLASH_MEM_MAX_SIZE; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': return usage_flashmem_save(); - case 'l': - len = param_get32ex(Cmd, cmdp+1, FLASH_MEM_MAX_SIZE, 10); - cmdp += 2; - break; - case 'o': - start_index = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - case 'f': - //File handling - if ( param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) { - PrintAndLogEx(FAILED, "Filename too long"); - errors = true; - break; - } - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': return usage_flashmem_save(); + case 'l': + len = param_get32ex(Cmd, cmdp+1, FLASH_MEM_MAX_SIZE, 10); + cmdp += 2; + break; + case 'o': + start_index = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 'f': + //File handling + if ( param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE) >= FILE_PATH_SIZE ) { + PrintAndLogEx(FAILED, "Filename too long"); + errors = true; + break; + } + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - //Validations - if (errors || cmdp == 0 ) return usage_flashmem_save(); + //Validations + if (errors || cmdp == 0 ) return usage_flashmem_save(); - uint8_t* dump = calloc(len, sizeof(uint8_t)); - if (!dump) { - PrintAndLogDevice(WARNING, "error, cannot allocate memory "); - return 1; - } + uint8_t* dump = calloc(len, sizeof(uint8_t)); + if (!dump) { + PrintAndLogDevice(WARNING, "error, cannot allocate memory "); + return 1; + } - PrintAndLogEx(NORMAL, "downloading %u bytes from flashmem", len); - if ( !GetFromDevice(FLASH_MEM, dump, len, start_index, NULL, -1, true) ) { - PrintAndLogEx(FAILED, "ERROR; downloading flashmem"); - free(dump); - return 1; - } + PrintAndLogEx(NORMAL, "downloading %u bytes from flashmem", len); + if ( !GetFromDevice(FLASH_MEM, dump, len, start_index, NULL, -1, true) ) { + PrintAndLogEx(FAILED, "ERROR; downloading flashmem"); + free(dump); + return 1; + } - saveFile(filename, "bin", dump, len); - saveFileEML(filename, "eml", dump, len, 16); - free(dump); - return 0; + saveFile(filename, "bin", dump, len); + saveFileEML(filename, "eml", dump, len, 16); + free(dump); + return 0; } int CmdFlashMemWipe(const char *Cmd){ - uint8_t cmdp = 0; - bool errors = false; - bool initalwipe = false; - uint8_t page = 0; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': return usage_flashmem_wipe(); - case 'p': - page = param_get8ex(Cmd, cmdp+1, 0, 10); - if ( page > 2 ) { - PrintAndLogEx(WARNING, "page must be 0, 1 or 2"); - errors = true; - break; - } - cmdp += 2; - break; - case 'i': - initalwipe = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + uint8_t cmdp = 0; + bool errors = false; + bool initalwipe = false; + uint8_t page = 0; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': return usage_flashmem_wipe(); + case 'p': + page = param_get8ex(Cmd, cmdp+1, 0, 10); + if ( page > 2 ) { + PrintAndLogEx(WARNING, "page must be 0, 1 or 2"); + errors = true; + break; + } + cmdp += 2; + break; + case 'i': + initalwipe = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - //Validations - if (errors || cmdp == 0 ) return usage_flashmem_wipe(); + //Validations + if (errors || cmdp == 0 ) return usage_flashmem_wipe(); - UsbCommand c = {CMD_FLASHMEM_WIPE, {page, initalwipe, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 8000) ) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 1; - } - uint8_t isok = resp.arg[0] & 0xFF; - if (isok) - PrintAndLogEx(SUCCESS, "Flash WIPE ok"); - else - PrintAndLogEx(FAILED, "Flash WIPE failed"); + UsbCommand c = {CMD_FLASHMEM_WIPE, {page, initalwipe, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 8000) ) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + return 1; + } + uint8_t isok = resp.arg[0] & 0xFF; + if (isok) + PrintAndLogEx(SUCCESS, "Flash WIPE ok"); + else + PrintAndLogEx(FAILED, "Flash WIPE failed"); - return 0; + return 0; } int CmdFlashMemInfo(const char *Cmd){ - uint8_t sha_hash[20] = {0}; - mbedtls_rsa_context rsa; + uint8_t sha_hash[20] = {0}; + mbedtls_rsa_context rsa; - uint8_t cmdp = 0; - bool errors = false, shall_write = false, shall_sign = false; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': return usage_flashmem_info(); - case 's': { - shall_sign = true; - cmdp++; - break; - } - case 'w': - shall_write = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + uint8_t cmdp = 0; + bool errors = false, shall_write = false, shall_sign = false; + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': return usage_flashmem_info(); + case 's': { + shall_sign = true; + cmdp++; + break; + } + case 'w': + shall_write = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - //Validations - if (errors ) return usage_flashmem_info(); + //Validations + if (errors ) return usage_flashmem_info(); - UsbCommand c = {CMD_FLASHMEM_INFO, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 1; - } + UsbCommand c = {CMD_FLASHMEM_INFO, {0, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2500) ) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + return 1; + } - uint8_t isok = resp.arg[0] & 0xFF; - if (!isok) { - PrintAndLogEx(FAILED, "failed"); - return 1; - } + uint8_t isok = resp.arg[0] & 0xFF; + if (!isok) { + PrintAndLogEx(FAILED, "failed"); + return 1; + } - // validate signature here - rdv40_validation_t mem; - memcpy(&mem, (rdv40_validation_t *)resp.d.asBytes, sizeof(rdv40_validation_t)); + // validate signature here + rdv40_validation_t mem; + memcpy(&mem, (rdv40_validation_t *)resp.d.asBytes, sizeof(rdv40_validation_t)); - // Flash ID hash (sha1) - mbedtls_sha1( mem.flashid, sizeof(mem.flashid), sha_hash ); + // Flash ID hash (sha1) + mbedtls_sha1( mem.flashid, sizeof(mem.flashid), sha_hash ); - // print header - PrintAndLogEx(INFO, "\n--- Flash memory Information ---------"); - PrintAndLogEx(INFO, "-------------------------------------------------------------"); - PrintAndLogEx(INFO, "ID | %s", sprint_hex(mem.flashid, sizeof(mem.flashid) )); - PrintAndLogEx(INFO, "SHA1 | %s", sprint_hex(sha_hash, sizeof(sha_hash))); - PrintAndLogEx(INFO, "RSA SIGNATURE |"); - print_hex_break( mem.signature, sizeof(mem.signature), 32); + // print header + PrintAndLogEx(INFO, "\n--- Flash memory Information ---------"); + PrintAndLogEx(INFO, "-------------------------------------------------------------"); + PrintAndLogEx(INFO, "ID | %s", sprint_hex(mem.flashid, sizeof(mem.flashid) )); + PrintAndLogEx(INFO, "SHA1 | %s", sprint_hex(sha_hash, sizeof(sha_hash))); + PrintAndLogEx(INFO, "RSA SIGNATURE |"); + print_hex_break( mem.signature, sizeof(mem.signature), 32); //------------------------------------------------------------------------------- // Example RSA-1024 keypair, for test purposes (from common/polarssl/rsa.c) @@ -514,98 +514,98 @@ int CmdFlashMemInfo(const char *Cmd){ #define KEY_LEN 128 - mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0); + mbedtls_rsa_init(&rsa, MBEDTLS_RSA_PKCS_V15, 0); - rsa.len = KEY_LEN; + rsa.len = KEY_LEN; - mbedtls_mpi_read_string( &rsa.N , 16, RSA_N ); - mbedtls_mpi_read_string( &rsa.E , 16, RSA_E ); - mbedtls_mpi_read_string( &rsa.D , 16, RSA_D ); - mbedtls_mpi_read_string( &rsa.P , 16, RSA_P ); - mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q ); - mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP ); - mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ ); - mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ); + mbedtls_mpi_read_string( &rsa.N , 16, RSA_N ); + mbedtls_mpi_read_string( &rsa.E , 16, RSA_E ); + mbedtls_mpi_read_string( &rsa.D , 16, RSA_D ); + mbedtls_mpi_read_string( &rsa.P , 16, RSA_P ); + mbedtls_mpi_read_string( &rsa.Q , 16, RSA_Q ); + mbedtls_mpi_read_string( &rsa.DP, 16, RSA_DP ); + mbedtls_mpi_read_string( &rsa.DQ, 16, RSA_DQ ); + mbedtls_mpi_read_string( &rsa.QP, 16, RSA_QP ); - PrintAndLogEx(INFO, "KEY length | %d", KEY_LEN); + PrintAndLogEx(INFO, "KEY length | %d", KEY_LEN); - bool is_keyok = ( mbedtls_rsa_check_pubkey( &rsa ) == 0 || mbedtls_rsa_check_privkey( &rsa ) == 0 ); - if (is_keyok) - PrintAndLogEx(SUCCESS, "RSA key validation ok"); - else - PrintAndLogEx(FAILED, "RSA key validation failed"); + bool is_keyok = ( mbedtls_rsa_check_pubkey( &rsa ) == 0 || mbedtls_rsa_check_privkey( &rsa ) == 0 ); + if (is_keyok) + PrintAndLogEx(SUCCESS, "RSA key validation ok"); + else + PrintAndLogEx(FAILED, "RSA key validation failed"); - // - uint8_t from_device[KEY_LEN]; - uint8_t sign[KEY_LEN]; + // + uint8_t from_device[KEY_LEN]; + uint8_t sign[KEY_LEN]; - // to be verified - memcpy(from_device, mem.signature, KEY_LEN); + // to be verified + memcpy(from_device, mem.signature, KEY_LEN); - // to be signed (all zeros - memset(sign, 0, KEY_LEN); + // to be signed (all zeros + memset(sign, 0, KEY_LEN); - // Signing (private key) - if (shall_sign) { + // Signing (private key) + if (shall_sign) { - int is_signed = mbedtls_rsa_pkcs1_sign( &rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign ); - if (is_signed == 0) - PrintAndLogEx(SUCCESS, "RSA Signing ok"); - else - PrintAndLogEx(FAILED, "RSA Signing failed"); + int is_signed = mbedtls_rsa_pkcs1_sign( &rsa, NULL, NULL, MBEDTLS_RSA_PRIVATE, MBEDTLS_MD_SHA1, 20, sha_hash, sign ); + if (is_signed == 0) + PrintAndLogEx(SUCCESS, "RSA Signing ok"); + else + PrintAndLogEx(FAILED, "RSA Signing failed"); - if (shall_write) { - // save to mem - c = (UsbCommand){CMD_FLASHMEM_WRITE, {FLASH_MEM_SIGNATURE_OFFSET, FLASH_MEM_SIGNATURE_LEN, 0}}; - memcpy(c.d.asBytes, sign, sizeof(sign)); - clearCommandBuffer(); - SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - } else { + if (shall_write) { + // save to mem + c = (UsbCommand){CMD_FLASHMEM_WRITE, {FLASH_MEM_SIGNATURE_OFFSET, FLASH_MEM_SIGNATURE_LEN, 0}}; + memcpy(c.d.asBytes, sign, sizeof(sign)); + clearCommandBuffer(); + SendCommand(&c); + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + } else { - if (!resp.arg[0]) - PrintAndLogEx(FAILED, "Writing signature failed"); - else - PrintAndLogEx(SUCCESS, "Writing signature ok [offset: %u]", FLASH_MEM_SIGNATURE_OFFSET); + if (!resp.arg[0]) + PrintAndLogEx(FAILED, "Writing signature failed"); + else + PrintAndLogEx(SUCCESS, "Writing signature ok [offset: %u]", FLASH_MEM_SIGNATURE_OFFSET); - } - } - PrintAndLogEx(INFO, "Signed | "); - print_hex_break( sign, sizeof(sign), 32); - } + } + } + PrintAndLogEx(INFO, "Signed | "); + print_hex_break( sign, sizeof(sign), 32); + } - // Verify (public key) - int is_verified = mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device ); - if (is_verified == 0) - PrintAndLogEx(SUCCESS, "RSA Verification ok"); - else - PrintAndLogEx(FAILED, "RSA Verification failed"); + // Verify (public key) + int is_verified = mbedtls_rsa_pkcs1_verify( &rsa, NULL, NULL, MBEDTLS_RSA_PUBLIC, MBEDTLS_MD_SHA1, 20, sha_hash, from_device ); + if (is_verified == 0) + PrintAndLogEx(SUCCESS, "RSA Verification ok"); + else + PrintAndLogEx(FAILED, "RSA Verification failed"); - mbedtls_rsa_free(&rsa); - return 0; + mbedtls_rsa_free(&rsa); + return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"spibaud", CmdFlashmemSpiBaudrate, 1, "Set Flash memory Spi baudrate [rdv40]"}, - {"read", CmdFlashMemRead, 1, "Read Flash memory [rdv40]"}, - {"info", CmdFlashMemInfo, 1, "Flash memory information [rdv40]"}, - {"load", CmdFlashMemLoad, 1, "Load data into flash memory [rdv40]"}, - {"save", CmdFlashMemSave, 1, "Save data from flash memory [rdv40]"}, - {"wipe", CmdFlashMemWipe, 1, "Wipe data from flash memory [rdv40]"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"spibaud", CmdFlashmemSpiBaudrate, 1, "Set Flash memory Spi baudrate [rdv40]"}, + {"read", CmdFlashMemRead, 1, "Read Flash memory [rdv40]"}, + {"info", CmdFlashMemInfo, 1, "Flash memory information [rdv40]"}, + {"load", CmdFlashMemLoad, 1, "Load data into flash memory [rdv40]"}, + {"save", CmdFlashMemSave, 1, "Save data from flash memory [rdv40]"}, + {"wipe", CmdFlashMemWipe, 1, "Wipe data from flash memory [rdv40]"}, + {NULL, NULL, 0, NULL} }; int CmdFlashMem(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } #endif diff --git a/client/cmdflashmem.h b/client/cmdflashmem.h index ee661bf18..c7c6f8979 100644 --- a/client/cmdflashmem.h +++ b/client/cmdflashmem.h @@ -22,15 +22,15 @@ #include "cmdparser.h" #include "common.h" #include "util.h" -#include "util_posix.h" // msclock -#include "loclass/fileutils.h" //saveFile -#include "comms.h" //getfromdevice +#include "util_posix.h" // msclock +#include "loclass/fileutils.h" //saveFile +#include "comms.h" //getfromdevice typedef enum { - DICTIONARY_NONE = 0, - DICTIONARY_MIFARE, - DICTIONARY_T55XX, - DICTIONARY_ICLASS + DICTIONARY_NONE = 0, + DICTIONARY_MIFARE, + DICTIONARY_T55XX, + DICTIONARY_ICLASS } Dictionary_t; extern int CmdFlashMem(const char *Cmd); diff --git a/client/cmdhf.c b/client/cmdhf.c index 6931f5c14..475a2659d 100644 --- a/client/cmdhf.c +++ b/client/cmdhf.c @@ -13,128 +13,128 @@ static int CmdHelp(const char *Cmd); int usage_hf_search(){ - PrintAndLogEx(NORMAL, "Usage: hf search"); - PrintAndLogEx(NORMAL, "Will try to find a HF read out of the unknown tag. Stops when found."); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - This help"); - PrintAndLogEx(NORMAL, ""); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf search"); + PrintAndLogEx(NORMAL, "Will try to find a HF read out of the unknown tag. Stops when found."); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - This help"); + PrintAndLogEx(NORMAL, ""); + return 0; } int usage_hf_snoop(){ - PrintAndLogEx(NORMAL, "Usage: hf snoop "); - PrintAndLogEx(NORMAL, "The high frequence snoop will assign all available memory on device for snooped data"); - PrintAndLogEx(NORMAL, "User the 'data samples' command to download from device, and 'data plot' to look at it"); - PrintAndLogEx(NORMAL, "Press button to quit the snooping."); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h - This help"); - PrintAndLogEx(NORMAL, " - skip sample pairs"); - PrintAndLogEx(NORMAL, " - skip number of triggers"); - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf snoop"); - PrintAndLogEx(NORMAL, " hf snoop 1000 0"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf snoop "); + PrintAndLogEx(NORMAL, "The high frequence snoop will assign all available memory on device for snooped data"); + PrintAndLogEx(NORMAL, "User the 'data samples' command to download from device, and 'data plot' to look at it"); + PrintAndLogEx(NORMAL, "Press button to quit the snooping."); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h - This help"); + PrintAndLogEx(NORMAL, " - skip sample pairs"); + PrintAndLogEx(NORMAL, " - skip number of triggers"); + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf snoop"); + PrintAndLogEx(NORMAL, " hf snoop 1000 0"); + return 0; } int CmdHFSearch(const char *Cmd){ - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_search(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_search(); - int ans = CmdHF14AInfo("s"); - if (ans > 0) { - PrintAndLogEx(SUCCESS, "\nValid ISO14443-A Tag Found\n"); - return ans; - } - ans = HF15Reader("", false); - if (ans) { - PrintAndLogEx(SUCCESS, "\nValid ISO15693 Tag Found\n"); - return ans; - } - ans = HFLegicReader("", false); - if ( ans == 0) { - PrintAndLogEx(SUCCESS, "\nValid LEGIC Tag Found\n"); - return 1; - } - ans = CmdHFTopazReader("s"); - if (ans == 0) { - PrintAndLogEx(SUCCESS, "\nValid Topaz Tag Found\n"); - return 1; - } - // 14b and iclass is the longest test (put last) - ans = HF14BReader(false); //CmdHF14BReader("s"); - if (ans) { - PrintAndLogEx(SUCCESS, "\nValid ISO14443-B Tag Found\n"); - return ans; - } - ans = HFiClassReader("", false, false); - if (ans) { - PrintAndLogEx(SUCCESS, "\nValid iClass Tag (or PicoPass Tag) Found\n"); - return ans; - } + int ans = CmdHF14AInfo("s"); + if (ans > 0) { + PrintAndLogEx(SUCCESS, "\nValid ISO14443-A Tag Found\n"); + return ans; + } + ans = HF15Reader("", false); + if (ans) { + PrintAndLogEx(SUCCESS, "\nValid ISO15693 Tag Found\n"); + return ans; + } + ans = HFLegicReader("", false); + if ( ans == 0) { + PrintAndLogEx(SUCCESS, "\nValid LEGIC Tag Found\n"); + return 1; + } + ans = CmdHFTopazReader("s"); + if (ans == 0) { + PrintAndLogEx(SUCCESS, "\nValid Topaz Tag Found\n"); + return 1; + } + // 14b and iclass is the longest test (put last) + ans = HF14BReader(false); //CmdHF14BReader("s"); + if (ans) { + PrintAndLogEx(SUCCESS, "\nValid ISO14443-B Tag Found\n"); + return ans; + } + ans = HFiClassReader("", false, false); + if (ans) { + PrintAndLogEx(SUCCESS, "\nValid iClass Tag (or PicoPass Tag) Found\n"); + return ans; + } - /* - ans = CmdHFFelicaReader("s"); - if (ans) { - PrintAndLogEx(NORMAL, "\nValid ISO18092 / FeliCa Found\n"); - return ans; - } - */ + /* + ans = CmdHFFelicaReader("s"); + if (ans) { + PrintAndLogEx(NORMAL, "\nValid ISO18092 / FeliCa Found\n"); + return ans; + } + */ - PrintAndLogEx(FAILED, "\nno known/supported 13.56 MHz tags found\n"); - return 0; + PrintAndLogEx(FAILED, "\nno known/supported 13.56 MHz tags found\n"); + return 0; } int CmdHFTune(const char *Cmd) { - PrintAndLogEx(SUCCESS, "Measuring HF antenna, press button to exit"); - UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING_HF}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + PrintAndLogEx(SUCCESS, "Measuring HF antenna, press button to exit"); + UsbCommand c = {CMD_MEASURE_ANTENNA_TUNING_HF}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } int CmdHFSnoop(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_snoop(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_snoop(); - int skippairs = param_get32ex(Cmd, 0, 0, 10); - int skiptriggers = param_get32ex(Cmd, 1, 0, 10); + int skippairs = param_get32ex(Cmd, 0, 0, 10); + int skiptriggers = param_get32ex(Cmd, 1, 0, 10); - UsbCommand c = {CMD_HF_SNIFFER, {skippairs, skiptriggers, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_HF_SNIFFER, {skippairs, skiptriggers, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"}, - {"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"}, - {"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"}, - {"epa", CmdHFEPA, 1, "{ German Identification Card... }"}, - {"felica", CmdHFFelica, 1, "{ ISO18092 / Felica RFIDs... }"}, - {"legic", CmdHFLegic, 1, "{ LEGIC RFIDs... }"}, - {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, - {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, - {"mfp", CmdHFMFP, 1, "{ MIFARE Plus RFIDs... }"}, - {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, - {"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"}, - {"topaz", CmdHFTopaz, 1, "{ TOPAZ (NFC Type 1) RFIDs... }"}, - {"fido", CmdHFFido, 1, "{ FIDO and FIDO2 authenticators... }"}, - {"list", CmdTraceList, 0, "List protocol data in trace buffer"}, - {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, - {"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"}, - {"snoop", CmdHFSnoop, 0, " Generic HF Snoop"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"14a", CmdHF14A, 1, "{ ISO14443A RFIDs... }"}, + {"14b", CmdHF14B, 1, "{ ISO14443B RFIDs... }"}, + {"15", CmdHF15, 1, "{ ISO15693 RFIDs... }"}, + {"epa", CmdHFEPA, 1, "{ German Identification Card... }"}, + {"felica", CmdHFFelica, 1, "{ ISO18092 / Felica RFIDs... }"}, + {"legic", CmdHFLegic, 1, "{ LEGIC RFIDs... }"}, + {"iclass", CmdHFiClass, 1, "{ ICLASS RFIDs... }"}, + {"mf", CmdHFMF, 1, "{ MIFARE RFIDs... }"}, + {"mfp", CmdHFMFP, 1, "{ MIFARE Plus RFIDs... }"}, + {"mfu", CmdHFMFUltra, 1, "{ MIFARE Ultralight RFIDs... }"}, + {"mfdes", CmdHFMFDes, 1, "{ MIFARE Desfire RFIDs... }"}, + {"topaz", CmdHFTopaz, 1, "{ TOPAZ (NFC Type 1) RFIDs... }"}, + {"fido", CmdHFFido, 1, "{ FIDO and FIDO2 authenticators... }"}, + {"list", CmdTraceList, 0, "List protocol data in trace buffer"}, + {"tune", CmdHFTune, 0, "Continuously measure HF antenna tuning"}, + {"search", CmdHFSearch, 1, "Search for known HF tags [preliminary]"}, + {"snoop", CmdHFSnoop, 0, " Generic HF Snoop"}, + {NULL, NULL, 0, NULL} }; int CmdHF(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } diff --git a/client/cmdhf.h b/client/cmdhf.h index b2dcc10f1..6511cc2b8 100644 --- a/client/cmdhf.h +++ b/client/cmdhf.h @@ -18,20 +18,20 @@ #include "graph.h" #include "ui.h" #include "cmdparser.h" -#include "cmdhf14a.h" // ISO14443-A -#include "cmdhf14b.h" // ISO14443-B -#include "cmdhf15.h" // ISO15693 +#include "cmdhf14a.h" // ISO14443-A +#include "cmdhf14b.h" // ISO14443-B +#include "cmdhf15.h" // ISO15693 #include "cmdhfepa.h" -#include "cmdhflegic.h" // LEGIC -#include "cmdhficlass.h" // ICLASS -#include "cmdhfmf.h" // CLASSIC -#include "cmdhfmfu.h" // ULTRALIGHT/NTAG etc -#include "cmdhfmfp.h" // Mifare Plus -#include "cmdhfmfdes.h" // DESFIRE -#include "cmdhftopaz.h" // TOPAZ -#include "cmdhffelica.h" // ISO18092 / FeliCa -#include "cmdhffido.h" // FIDO authenticators -#include "cmdtrace.h" // trace list +#include "cmdhflegic.h" // LEGIC +#include "cmdhficlass.h" // ICLASS +#include "cmdhfmf.h" // CLASSIC +#include "cmdhfmfu.h" // ULTRALIGHT/NTAG etc +#include "cmdhfmfp.h" // Mifare Plus +#include "cmdhfmfdes.h" // DESFIRE +#include "cmdhftopaz.h" // TOPAZ +#include "cmdhffelica.h" // ISO18092 / FeliCa +#include "cmdhffido.h" // FIDO authenticators +#include "cmdtrace.h" // trace list extern int CmdHF(const char *Cmd); extern int CmdHFTune(const char *Cmd); diff --git a/client/cmdhf14a.c b/client/cmdhf14a.c index 98a6168b2..d88746e3f 100644 --- a/client/cmdhf14a.c +++ b/client/cmdhf14a.c @@ -18,135 +18,135 @@ static int CmdHelp(const char *Cmd); static int waitCmd(uint8_t iLen); static const manufactureName manufactureMapping[] = { - // ID, "Vendor Country" - { 0x01, "Motorola UK" }, - { 0x02, "ST Microelectronics SA France" }, - { 0x03, "Hitachi, Ltd Japan" }, - { 0x04, "NXP Semiconductors Germany" }, - { 0x05, "Infineon Technologies AG Germany" }, - { 0x06, "Cylink USA" }, - { 0x07, "Texas Instrument France" }, - { 0x08, "Fujitsu Limited Japan" }, - { 0x09, "Matsushita Electronics Corporation, Semiconductor Company Japan" }, - { 0x0A, "NEC Japan" }, - { 0x0B, "Oki Electric Industry Co. Ltd Japan" }, - { 0x0C, "Toshiba Corp. Japan" }, - { 0x0D, "Mitsubishi Electric Corp. Japan" }, - { 0x0E, "Samsung Electronics Co. Ltd Korea" }, - { 0x0F, "Hynix / Hyundai, Korea" }, - { 0x10, "LG-Semiconductors Co. Ltd Korea" }, - { 0x11, "Emosyn-EM Microelectronics USA" }, - { 0x12, "INSIDE Technology France" }, - { 0x13, "ORGA Kartensysteme GmbH Germany" }, - { 0x14, "SHARP Corporation Japan" }, - { 0x15, "ATMEL France" }, - { 0x16, "EM Microelectronic-Marin SA Switzerland" }, - { 0x17, "KSW Microtec GmbH Germany" }, - { 0x18, "ZMD AG Germany" }, - { 0x19, "XICOR, Inc. USA" }, - { 0x1A, "Sony Corporation Japan" }, - { 0x1B, "Malaysia Microelectronic Solutions Sdn. Bhd Malaysia" }, - { 0x1C, "Emosyn USA" }, - { 0x1D, "Shanghai Fudan Microelectronics Co. Ltd. P.R. China" }, - { 0x1E, "Magellan Technology Pty Limited Australia" }, - { 0x1F, "Melexis NV BO Switzerland" }, - { 0x20, "Renesas Technology Corp. Japan" }, - { 0x21, "TAGSYS France" }, - { 0x22, "Transcore USA" }, - { 0x23, "Shanghai belling corp., ltd. China" }, - { 0x24, "Masktech Germany Gmbh Germany" }, - { 0x25, "Innovision Research and Technology Plc UK" }, - { 0x26, "Hitachi ULSI Systems Co., Ltd. Japan" }, - { 0x27, "Cypak AB Sweden" }, - { 0x28, "Ricoh Japan" }, - { 0x29, "ASK France" }, - { 0x2A, "Unicore Microsystems, LLC Russian Federation" }, - { 0x2B, "Dallas Semiconductor/Maxim USA" }, - { 0x2C, "Impinj, Inc. USA" }, - { 0x2D, "RightPlug Alliance USA" }, - { 0x2E, "Broadcom Corporation USA" }, - { 0x2F, "MStar Semiconductor, Inc Taiwan, ROC" }, - { 0x30, "BeeDar Technology Inc. USA" }, - { 0x31, "RFIDsec Denmark" }, - { 0x32, "Schweizer Electronic AG Germany" }, - { 0x33, "AMIC Technology Corp Taiwan" }, - { 0x34, "Mikron JSC Russia" }, - { 0x35, "Fraunhofer Institute for Photonic Microsystems Germany" }, - { 0x36, "IDS Microchip AG Switzerland" }, - { 0x37, "Kovio USA" }, - { 0x38, "HMT Microelectronic Ltd Switzerland" }, - { 0x39, "Silicon Craft Technology Thailand" }, - { 0x3A, "Advanced Film Device Inc. Japan" }, - { 0x3B, "Nitecrest Ltd UK" }, - { 0x3C, "Verayo Inc. USA" }, - { 0x3D, "HID Global USA" }, - { 0x3E, "Productivity Engineering Gmbh Germany" }, - { 0x3F, "Austriamicrosystems AG (reserved) Austria" }, - { 0x40, "Gemalto SA France" }, - { 0x41, "Renesas Electronics Corporation Japan" }, - { 0x42, "3Alogics Inc Korea" }, - { 0x43, "Top TroniQ Asia Limited Hong Kong" }, - { 0x44, "Gentag Inc. USA" }, - { 0x45, "Invengo Information Technology Co.Ltd China" }, - { 0x46, "Guangzhou Sysur Microelectronics, Inc China" }, - { 0x47, "CEITEC S.A. Brazil" }, - { 0x48, "Shanghai Quanray Electronics Co. Ltd. China" }, - { 0x49, "MediaTek Inc Taiwan" }, - { 0x4A, "Angstrem PJSC Russia" }, - { 0x4B, "Celisic Semiconductor (Hong Kong) Limited China" }, - { 0x4C, "LEGIC Identsystems AG Switzerland" }, - { 0x4D, "Balluff GmbH Germany" }, - { 0x4E, "Oberthur Technologies France" }, - { 0x4F, "Silterra Malaysia Sdn. Bhd. Malaysia" }, - { 0x50, "DELTA Danish Electronics, Light & Acoustics Denmark" }, - { 0x51, "Giesecke & Devrient GmbH Germany" }, - { 0x52, "Shenzhen China Vision Microelectronics Co., Ltd. China" }, - { 0x53, "Shanghai Feiju Microelectronics Co. Ltd. China" }, - { 0x54, "Intel Corporation USA" }, - { 0x55, "Microsensys GmbH Germany" }, - { 0x56, "Sonix Technology Co., Ltd. Taiwan" }, - { 0x57, "Qualcomm Technologies Inc USA" }, - { 0x58, "Realtek Semiconductor Corp Taiwan" }, - { 0x59, "Freevision Technologies Co. Ltd China" }, - { 0x5A, "Giantec Semiconductor Inc. China" }, - { 0x5B, "JSC Angstrem-T Russia" }, - { 0x5C, "STARCHIP France" }, - { 0x5D, "SPIRTECH France" }, - { 0x5E, "GANTNER Electronic GmbH Austria" }, - { 0x5F, "Nordic Semiconductor Norway" }, - { 0x60, "Verisiti Inc USA" }, - { 0x61, "Wearlinks Technology Inc. China" }, - { 0x62, "Userstar Information Systems Co., Ltd Taiwan" }, - { 0x63, "Pragmatic Printing Ltd. UK" }, - { 0x64, "Associacao do Laboratorio de Sistemas Integraveis Tecnologico – LSI-TEC Brazil" }, - { 0x65, "Tendyron Corporation China" }, - { 0x66, "MUTO Smart Co., Ltd. Korea" }, - { 0x67, "ON Semiconductor USA" }, - { 0x68, "TUBITAK BILGEM Turkey" }, - { 0x69, "Huada Semiconductor Co., Ltd China" }, - { 0x6A, "SEVENEY France" }, - { 0x6B, "ISSM France" }, - { 0x6C, "Wisesec Ltd Israel" }, - { 0x7C, "DB HiTek Co Ltd Korea" }, - { 0x7D, "SATO Vicinity Australia" }, - { 0x7E, "Holtek Taiwan" }, - { 0x00, "no tag-info available" } // must be the last entry + // ID, "Vendor Country" + { 0x01, "Motorola UK" }, + { 0x02, "ST Microelectronics SA France" }, + { 0x03, "Hitachi, Ltd Japan" }, + { 0x04, "NXP Semiconductors Germany" }, + { 0x05, "Infineon Technologies AG Germany" }, + { 0x06, "Cylink USA" }, + { 0x07, "Texas Instrument France" }, + { 0x08, "Fujitsu Limited Japan" }, + { 0x09, "Matsushita Electronics Corporation, Semiconductor Company Japan" }, + { 0x0A, "NEC Japan" }, + { 0x0B, "Oki Electric Industry Co. Ltd Japan" }, + { 0x0C, "Toshiba Corp. Japan" }, + { 0x0D, "Mitsubishi Electric Corp. Japan" }, + { 0x0E, "Samsung Electronics Co. Ltd Korea" }, + { 0x0F, "Hynix / Hyundai, Korea" }, + { 0x10, "LG-Semiconductors Co. Ltd Korea" }, + { 0x11, "Emosyn-EM Microelectronics USA" }, + { 0x12, "INSIDE Technology France" }, + { 0x13, "ORGA Kartensysteme GmbH Germany" }, + { 0x14, "SHARP Corporation Japan" }, + { 0x15, "ATMEL France" }, + { 0x16, "EM Microelectronic-Marin SA Switzerland" }, + { 0x17, "KSW Microtec GmbH Germany" }, + { 0x18, "ZMD AG Germany" }, + { 0x19, "XICOR, Inc. USA" }, + { 0x1A, "Sony Corporation Japan" }, + { 0x1B, "Malaysia Microelectronic Solutions Sdn. Bhd Malaysia" }, + { 0x1C, "Emosyn USA" }, + { 0x1D, "Shanghai Fudan Microelectronics Co. Ltd. P.R. China" }, + { 0x1E, "Magellan Technology Pty Limited Australia" }, + { 0x1F, "Melexis NV BO Switzerland" }, + { 0x20, "Renesas Technology Corp. Japan" }, + { 0x21, "TAGSYS France" }, + { 0x22, "Transcore USA" }, + { 0x23, "Shanghai belling corp., ltd. China" }, + { 0x24, "Masktech Germany Gmbh Germany" }, + { 0x25, "Innovision Research and Technology Plc UK" }, + { 0x26, "Hitachi ULSI Systems Co., Ltd. Japan" }, + { 0x27, "Cypak AB Sweden" }, + { 0x28, "Ricoh Japan" }, + { 0x29, "ASK France" }, + { 0x2A, "Unicore Microsystems, LLC Russian Federation" }, + { 0x2B, "Dallas Semiconductor/Maxim USA" }, + { 0x2C, "Impinj, Inc. USA" }, + { 0x2D, "RightPlug Alliance USA" }, + { 0x2E, "Broadcom Corporation USA" }, + { 0x2F, "MStar Semiconductor, Inc Taiwan, ROC" }, + { 0x30, "BeeDar Technology Inc. USA" }, + { 0x31, "RFIDsec Denmark" }, + { 0x32, "Schweizer Electronic AG Germany" }, + { 0x33, "AMIC Technology Corp Taiwan" }, + { 0x34, "Mikron JSC Russia" }, + { 0x35, "Fraunhofer Institute for Photonic Microsystems Germany" }, + { 0x36, "IDS Microchip AG Switzerland" }, + { 0x37, "Kovio USA" }, + { 0x38, "HMT Microelectronic Ltd Switzerland" }, + { 0x39, "Silicon Craft Technology Thailand" }, + { 0x3A, "Advanced Film Device Inc. Japan" }, + { 0x3B, "Nitecrest Ltd UK" }, + { 0x3C, "Verayo Inc. USA" }, + { 0x3D, "HID Global USA" }, + { 0x3E, "Productivity Engineering Gmbh Germany" }, + { 0x3F, "Austriamicrosystems AG (reserved) Austria" }, + { 0x40, "Gemalto SA France" }, + { 0x41, "Renesas Electronics Corporation Japan" }, + { 0x42, "3Alogics Inc Korea" }, + { 0x43, "Top TroniQ Asia Limited Hong Kong" }, + { 0x44, "Gentag Inc. USA" }, + { 0x45, "Invengo Information Technology Co.Ltd China" }, + { 0x46, "Guangzhou Sysur Microelectronics, Inc China" }, + { 0x47, "CEITEC S.A. Brazil" }, + { 0x48, "Shanghai Quanray Electronics Co. Ltd. China" }, + { 0x49, "MediaTek Inc Taiwan" }, + { 0x4A, "Angstrem PJSC Russia" }, + { 0x4B, "Celisic Semiconductor (Hong Kong) Limited China" }, + { 0x4C, "LEGIC Identsystems AG Switzerland" }, + { 0x4D, "Balluff GmbH Germany" }, + { 0x4E, "Oberthur Technologies France" }, + { 0x4F, "Silterra Malaysia Sdn. Bhd. Malaysia" }, + { 0x50, "DELTA Danish Electronics, Light & Acoustics Denmark" }, + { 0x51, "Giesecke & Devrient GmbH Germany" }, + { 0x52, "Shenzhen China Vision Microelectronics Co., Ltd. China" }, + { 0x53, "Shanghai Feiju Microelectronics Co. Ltd. China" }, + { 0x54, "Intel Corporation USA" }, + { 0x55, "Microsensys GmbH Germany" }, + { 0x56, "Sonix Technology Co., Ltd. Taiwan" }, + { 0x57, "Qualcomm Technologies Inc USA" }, + { 0x58, "Realtek Semiconductor Corp Taiwan" }, + { 0x59, "Freevision Technologies Co. Ltd China" }, + { 0x5A, "Giantec Semiconductor Inc. China" }, + { 0x5B, "JSC Angstrem-T Russia" }, + { 0x5C, "STARCHIP France" }, + { 0x5D, "SPIRTECH France" }, + { 0x5E, "GANTNER Electronic GmbH Austria" }, + { 0x5F, "Nordic Semiconductor Norway" }, + { 0x60, "Verisiti Inc USA" }, + { 0x61, "Wearlinks Technology Inc. China" }, + { 0x62, "Userstar Information Systems Co., Ltd Taiwan" }, + { 0x63, "Pragmatic Printing Ltd. UK" }, + { 0x64, "Associacao do Laboratorio de Sistemas Integraveis Tecnologico – LSI-TEC Brazil" }, + { 0x65, "Tendyron Corporation China" }, + { 0x66, "MUTO Smart Co., Ltd. Korea" }, + { 0x67, "ON Semiconductor USA" }, + { 0x68, "TUBITAK BILGEM Turkey" }, + { 0x69, "Huada Semiconductor Co., Ltd China" }, + { 0x6A, "SEVENEY France" }, + { 0x6B, "ISSM France" }, + { 0x6C, "Wisesec Ltd Israel" }, + { 0x7C, "DB HiTek Co Ltd Korea" }, + { 0x7D, "SATO Vicinity Australia" }, + { 0x7E, "Holtek Taiwan" }, + { 0x00, "no tag-info available" } // must be the last entry }; // get a product description based on the UID -// uid[8] tag uid +// uid[8] tag uid // returns description of the best match char* getTagInfo(uint8_t uid) { - int i; - int len = sizeof(manufactureMapping) / sizeof(manufactureName); + int i; + int len = sizeof(manufactureMapping) / sizeof(manufactureName); - for ( i = 0; i < len; ++i ) - if ( uid == manufactureMapping[i].uid) - return manufactureMapping[i].desc; + for ( i = 0; i < len; ++i ) + if ( uid == manufactureMapping[i].uid) + return manufactureMapping[i].desc; - //No match, return default - return manufactureMapping[len-1].desc; + //No match, return default + return manufactureMapping[len-1].desc; } // iso14a apdu input frame length @@ -154,647 +154,647 @@ static uint16_t frameLength = 0; uint16_t atsFSC[] = {16, 24, 32, 40, 48, 64, 96, 128, 256}; int usage_hf_14a_sim(void) { -// PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"); - PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 byte UID\n"); - PrintAndLogEx(NORMAL, "Usage: hf 14a sim [h] t u [x] [e] [v]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " t : 1 = MIFARE Classic 1k"); - PrintAndLogEx(NORMAL, " 2 = MIFARE Ultralight"); - PrintAndLogEx(NORMAL, " 3 = MIFARE Desfire"); - PrintAndLogEx(NORMAL, " 4 = ISO/IEC 14443-4"); - PrintAndLogEx(NORMAL, " 5 = MIFARE Tnp3xxx"); - PrintAndLogEx(NORMAL, " 6 = MIFARE Mini"); - PrintAndLogEx(NORMAL, " 7 = AMIIBO (NTAG 215), pack 0x8080"); - PrintAndLogEx(NORMAL, " 8 = MIFARE Classic 4k"); - PrintAndLogEx(NORMAL, " 9 = FM11RF005SH Shanghai Metro"); -// PrintAndLogEx(NORMAL, " u : 4, 7 or 10 byte UID"); - PrintAndLogEx(NORMAL, " u : 4, 7 byte UID"); - PrintAndLogEx(NORMAL, " x : (Optional) Performs the 'reader attack', nr/ar attack against a reader"); - PrintAndLogEx(NORMAL, " e : (Optional) Fill simulator keys from found keys"); - PrintAndLogEx(NORMAL, " v : (Optional) Verbose"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223344 x"); - PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223344"); - PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223344556677"); -// PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223445566778899AA\n"); - return 0; +// PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 or 10 byte UID\n"); + PrintAndLogEx(NORMAL, "\n Emulating ISO/IEC 14443 type A tag with 4,7 byte UID\n"); + PrintAndLogEx(NORMAL, "Usage: hf 14a sim [h] t u [x] [e] [v]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " t : 1 = MIFARE Classic 1k"); + PrintAndLogEx(NORMAL, " 2 = MIFARE Ultralight"); + PrintAndLogEx(NORMAL, " 3 = MIFARE Desfire"); + PrintAndLogEx(NORMAL, " 4 = ISO/IEC 14443-4"); + PrintAndLogEx(NORMAL, " 5 = MIFARE Tnp3xxx"); + PrintAndLogEx(NORMAL, " 6 = MIFARE Mini"); + PrintAndLogEx(NORMAL, " 7 = AMIIBO (NTAG 215), pack 0x8080"); + PrintAndLogEx(NORMAL, " 8 = MIFARE Classic 4k"); + PrintAndLogEx(NORMAL, " 9 = FM11RF005SH Shanghai Metro"); +// PrintAndLogEx(NORMAL, " u : 4, 7 or 10 byte UID"); + PrintAndLogEx(NORMAL, " u : 4, 7 byte UID"); + PrintAndLogEx(NORMAL, " x : (Optional) Performs the 'reader attack', nr/ar attack against a reader"); + PrintAndLogEx(NORMAL, " e : (Optional) Fill simulator keys from found keys"); + PrintAndLogEx(NORMAL, " v : (Optional) Verbose"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223344 x"); + PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223344"); + PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223344556677"); +// PrintAndLogEx(NORMAL, " hf 14a sim t 1 u 11223445566778899AA\n"); + return 0; } int usage_hf_14a_sniff(void) { - PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer."); - PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list 14a'"); - PrintAndLogEx(NORMAL, "Usage: hf 14a sniff [c][r]"); - PrintAndLogEx(NORMAL, "c - triggered by first data from card"); - PrintAndLogEx(NORMAL, "r - triggered by first 7-bit request from reader (REQ,WUP,...)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf 14a sniff c r"); - return 0; + PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer."); + PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list 14a'"); + PrintAndLogEx(NORMAL, "Usage: hf 14a sniff [c][r]"); + PrintAndLogEx(NORMAL, "c - triggered by first data from card"); + PrintAndLogEx(NORMAL, "r - triggered by first 7-bit request from reader (REQ,WUP,...)"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf 14a sniff c r"); + return 0; } int usage_hf_14a_raw(void) { - PrintAndLogEx(NORMAL, "Usage: hf 14a raw [-h] [-r] [-c] [-p] [-a] [-T] [-t] [-b] <0A 0B 0C ... hex>"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -r do not read response"); - PrintAndLogEx(NORMAL, " -c calculate and append CRC"); - PrintAndLogEx(NORMAL, " -p leave the signal field ON after receive"); - PrintAndLogEx(NORMAL, " -a active signal field ON without select"); - PrintAndLogEx(NORMAL, " -s active signal field ON with select"); - PrintAndLogEx(NORMAL, " -b number of bits to send. Useful for send partial byte"); - PrintAndLogEx(NORMAL, " -t timeout in ms"); - PrintAndLogEx(NORMAL, " -T use Topaz protocol to send command"); - PrintAndLogEx(NORMAL, " -3 ISO14443-3 select only (skip RATS)"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 14a raw [-h] [-r] [-c] [-p] [-a] [-T] [-t] [-b] <0A 0B 0C ... hex>"); + PrintAndLogEx(NORMAL, " -h this help"); + PrintAndLogEx(NORMAL, " -r do not read response"); + PrintAndLogEx(NORMAL, " -c calculate and append CRC"); + PrintAndLogEx(NORMAL, " -p leave the signal field ON after receive"); + PrintAndLogEx(NORMAL, " -a active signal field ON without select"); + PrintAndLogEx(NORMAL, " -s active signal field ON with select"); + PrintAndLogEx(NORMAL, " -b number of bits to send. Useful for send partial byte"); + PrintAndLogEx(NORMAL, " -t timeout in ms"); + PrintAndLogEx(NORMAL, " -T use Topaz protocol to send command"); + PrintAndLogEx(NORMAL, " -3 ISO14443-3 select only (skip RATS)"); + return 0; } int usage_hf_14a_reader(void) { - PrintAndLogEx(NORMAL, "Usage: hf 14a reader [k|s|x] [3]"); - PrintAndLogEx(NORMAL, " k keep the field active after command executed"); - PrintAndLogEx(NORMAL, " s silent (no messages)"); - PrintAndLogEx(NORMAL, " x just drop the signal field"); - PrintAndLogEx(NORMAL, " 3 ISO14443-3 select only (skip RATS)"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 14a reader [k|s|x] [3]"); + PrintAndLogEx(NORMAL, " k keep the field active after command executed"); + PrintAndLogEx(NORMAL, " s silent (no messages)"); + PrintAndLogEx(NORMAL, " x just drop the signal field"); + PrintAndLogEx(NORMAL, " 3 ISO14443-3 select only (skip RATS)"); + return 0; } int usage_hf_14a_info(void){ - PrintAndLogEx(NORMAL, "This command makes more extensive tests against a ISO14443a tag in order to collect information"); - PrintAndLogEx(NORMAL, "Usage: hf 14a info [h|s]"); - PrintAndLogEx(NORMAL, " s silent (no messages)"); - PrintAndLogEx(NORMAL, " n test for nack bug"); - return 0; + PrintAndLogEx(NORMAL, "This command makes more extensive tests against a ISO14443a tag in order to collect information"); + PrintAndLogEx(NORMAL, "Usage: hf 14a info [h|s]"); + PrintAndLogEx(NORMAL, " s silent (no messages)"); + PrintAndLogEx(NORMAL, " n test for nack bug"); + return 0; } int CmdHF14AList(const char *Cmd) { - //PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list 14a' instead"); - CmdTraceList("14a"); - return 0; + //PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list 14a' instead"); + CmdTraceList("14a"); + return 0; } int Hf14443_4aGetCardData(iso14a_card_select_t * card) { - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}}; - SendCommand(&c); + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT, 0, 0}}; + SendCommand(&c); - UsbCommand resp; - WaitForResponse(CMD_ACK,&resp); + UsbCommand resp; + WaitForResponse(CMD_ACK,&resp); - memcpy(card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); + memcpy(card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision + uint64_t select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - if(select_status == 0) { - PrintAndLog("E->iso14443a card select failed"); - return 1; - } + if(select_status == 0) { + PrintAndLog("E->iso14443a card select failed"); + return 1; + } - if(select_status == 2) { - PrintAndLog("E->Card doesn't support iso14443-4 mode"); - return 1; - } + if(select_status == 2) { + PrintAndLog("E->Card doesn't support iso14443-4 mode"); + return 1; + } - if(select_status == 3) { - PrintAndLog("E->Card doesn't support standard iso14443-3 anticollision"); - PrintAndLog("\tATQA : %02x %02x", card->atqa[1], card->atqa[0]); - return 1; - } + if(select_status == 3) { + PrintAndLog("E->Card doesn't support standard iso14443-3 anticollision"); + PrintAndLog("\tATQA : %02x %02x", card->atqa[1], card->atqa[0]); + return 1; + } - PrintAndLog(" UID: %s", sprint_hex(card->uid, card->uidlen)); - PrintAndLog("ATQA: %02x %02x", card->atqa[1], card->atqa[0]); - PrintAndLog(" SAK: %02x [%" PRIu64 "]", card->sak, resp.arg[0]); - if(card->ats_len < 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes - PrintAndLog("E-> Error ATS length(%d) : %s", card->ats_len, sprint_hex(card->ats, card->ats_len)); - return 1; - } - PrintAndLog(" ATS: %s", sprint_hex(card->ats, card->ats_len)); + PrintAndLog(" UID: %s", sprint_hex(card->uid, card->uidlen)); + PrintAndLog("ATQA: %02x %02x", card->atqa[1], card->atqa[0]); + PrintAndLog(" SAK: %02x [%" PRIu64 "]", card->sak, resp.arg[0]); + if(card->ats_len < 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes + PrintAndLog("E-> Error ATS length(%d) : %s", card->ats_len, sprint_hex(card->ats, card->ats_len)); + return 1; + } + PrintAndLog(" ATS: %s", sprint_hex(card->ats, card->ats_len)); - return 0; + return 0; } int CmdHF14AReader(const char *Cmd) { - uint32_t cm = ISO14A_CONNECT; - bool disconnectAfter = true, silent = false; - int cmdp = 0; + uint32_t cm = ISO14A_CONNECT; + bool disconnectAfter = true, silent = false; + int cmdp = 0; - while (param_getchar(Cmd, cmdp) != 0x00) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_14a_reader(); - case '3': - cm |= ISO14A_NO_RATS; - break; - case 'k': - disconnectAfter = false; - break; - case 's': - silent = true; - break; - case 'x': - cm &= ~ISO14A_CONNECT; - break; - default: - PrintAndLogEx(WARNING, "Unknown command."); - return 1; - } - cmdp++; - } + while (param_getchar(Cmd, cmdp) != 0x00) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_hf_14a_reader(); + case '3': + cm |= ISO14A_NO_RATS; + break; + case 'k': + disconnectAfter = false; + break; + case 's': + silent = true; + break; + case 'x': + cm &= ~ISO14A_CONNECT; + break; + default: + PrintAndLogEx(WARNING, "Unknown command."); + return 1; + } + cmdp++; + } - if (!disconnectAfter) - cm |= ISO14A_NO_DISCONNECT; + if (!disconnectAfter) + cm |= ISO14A_NO_DISCONNECT; - UsbCommand c = {CMD_READER_ISO_14443a, {cm, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); + UsbCommand c = {CMD_READER_ISO_14443a, {cm, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); - if (ISO14A_CONNECT & cm) { - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); - DropField(); - return 1; - } + if (ISO14A_CONNECT & cm) { + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { + if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); + DropField(); + return 1; + } - iso14a_card_select_t card; - memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); + iso14a_card_select_t card; + memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - /* - 0: couldn't read - 1: OK, with ATS - 2: OK, no ATS - 3: proprietary Anticollision - */ - uint64_t select_status = resp.arg[0]; + /* + 0: couldn't read + 1: OK, with ATS + 2: OK, no ATS + 3: proprietary Anticollision + */ + uint64_t select_status = resp.arg[0]; - if (select_status == 0) { - if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); - DropField(); - return 1; - } + if (select_status == 0) { + if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); + DropField(); + return 1; + } - if (select_status == 3) { - PrintAndLogEx(NORMAL, "Card doesn't support standard iso14443-3 anticollision"); - PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - DropField(); - return 1; - } + if (select_status == 3) { + PrintAndLogEx(NORMAL, "Card doesn't support standard iso14443-3 anticollision"); + PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); + DropField(); + return 1; + } - PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - PrintAndLogEx(NORMAL, " SAK : %02x [%" PRIu64 "]", card.sak, resp.arg[0]); + PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); + PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); + PrintAndLogEx(NORMAL, " SAK : %02x [%" PRIu64 "]", card.sak, resp.arg[0]); - if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes - PrintAndLogEx(NORMAL, " ATS : %s", sprint_hex(card.ats, card.ats_len)); - } + if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes + PrintAndLogEx(NORMAL, " ATS : %s", sprint_hex(card.ats, card.ats_len)); + } - if (!disconnectAfter) { - if (!silent) PrintAndLogEx(SUCCESS, "Card is selected. You can now start sending commands"); - } - } + if (!disconnectAfter) { + if (!silent) PrintAndLogEx(SUCCESS, "Card is selected. You can now start sending commands"); + } + } - if (disconnectAfter) { - if (!silent) PrintAndLogEx(SUCCESS, "field dropped."); - } + if (disconnectAfter) { + if (!silent) PrintAndLogEx(SUCCESS, "field dropped."); + } - return 0; + return 0; } int CmdHF14AInfo(const char *Cmd) { - if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_hf_14a_info(); + if (Cmd[0] == 'h' || Cmd[0] == 'H') return usage_hf_14a_info(); - bool silent = (Cmd[0] == 's' || Cmd[0] == 'S'); - bool do_nack_test = (Cmd[0] == 'n' || Cmd[0] == 'N'); + bool silent = (Cmd[0] == 's' || Cmd[0] == 'S'); + bool do_nack_test = (Cmd[0] == 'n' || Cmd[0] == 'N'); - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); - DropField(); - return 0; - } + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { + if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); + DropField(); + return 0; + } - iso14a_card_select_t card; - memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); + iso14a_card_select_t card; + memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - /* - 0: couldn't read - 1: OK, with ATS - 2: OK, no ATS - 3: proprietary Anticollision - */ - uint64_t select_status = resp.arg[0]; + /* + 0: couldn't read + 1: OK, with ATS + 2: OK, no ATS + 3: proprietary Anticollision + */ + uint64_t select_status = resp.arg[0]; - if (select_status == 0) { - if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); - DropField(); - return 0; - } + if (select_status == 0) { + if (!silent) PrintAndLogEx(WARNING, "iso14443a card select failed"); + DropField(); + return 0; + } - if (select_status == 3) { - PrintAndLogEx(NORMAL, "Card doesn't support standard iso14443-3 anticollision"); - PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - DropField(); - return select_status; - } + if (select_status == 3) { + PrintAndLogEx(NORMAL, "Card doesn't support standard iso14443-3 anticollision"); + PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); + DropField(); + return select_status; + } - PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); - PrintAndLogEx(NORMAL, " SAK : %02x [%" PRIu64 "]", card.sak, resp.arg[0]); + PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); + PrintAndLogEx(NORMAL, "ATQA : %02x %02x", card.atqa[1], card.atqa[0]); + PrintAndLogEx(NORMAL, " SAK : %02x [%" PRIu64 "]", card.sak, resp.arg[0]); - bool isMifareClassic = true; - switch (card.sak) { - case 0x00: - isMifareClassic = false; + bool isMifareClassic = true; + switch (card.sak) { + case 0x00: + isMifareClassic = false; - // ******** is card of the MFU type (UL/ULC/NTAG/ etc etc) - DropField(); + // ******** is card of the MFU type (UL/ULC/NTAG/ etc etc) + DropField(); - uint32_t tagT = GetHF14AMfU_Type(); - if (tagT != UL_ERROR) - ul_print_type(tagT, 0); - else - PrintAndLogEx(NORMAL, "TYPE: Possible AZTEK (iso14443a compliant)"); + uint32_t tagT = GetHF14AMfU_Type(); + if (tagT != UL_ERROR) + ul_print_type(tagT, 0); + else + PrintAndLogEx(NORMAL, "TYPE: Possible AZTEK (iso14443a compliant)"); - // reconnect for further tests - c.arg[0] = ISO14A_CONNECT | ISO14A_NO_DISCONNECT; - c.arg[1] = 0; - c.arg[2] = 0; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - WaitForResponse(CMD_ACK, &resp); + // reconnect for further tests + c.arg[0] = ISO14A_CONNECT | ISO14A_NO_DISCONNECT; + c.arg[1] = 0; + c.arg[2] = 0; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + WaitForResponse(CMD_ACK, &resp); - memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); + memcpy(&card, (iso14a_card_select_t *)resp.d.asBytes, sizeof(iso14a_card_select_t)); - select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS + select_status = resp.arg[0]; // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS - if(select_status == 0) { - DropField(); - return 0; - } - break; - case 0x01: PrintAndLogEx(NORMAL, "TYPE : NXP TNP3xxx Activision Game Appliance"); break; - case 0x04: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); isMifareClassic = false; break; - case 0x08: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1 | 1k Ev1"); break; - case 0x09: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Mini 0.3k"); break; - case 0x0A: PrintAndLogEx(NORMAL, "TYPE : FM11RF005SH (Shanghai Metro)"); break; - case 0x10: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Plus 2k SL2"); break; - case 0x11: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Plus 4k SL2"); break; - case 0x18: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Classic 4k | Plus 4k SL1 | 4k Ev1"); break; - case 0x20: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k SL3 | JCOP 31/41"); isMifareClassic = false; break; - case 0x24: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE DESFire | DESFire EV1"); isMifareClassic = false; break; - case 0x28: PrintAndLogEx(NORMAL, "TYPE : JCOP31 or JCOP41 v2.3.1"); break; - case 0x38: PrintAndLogEx(NORMAL, "TYPE : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); break; - case 0x88: PrintAndLogEx(NORMAL, "TYPE : Infineon MIFARE CLASSIC 1K"); break; - case 0x98: PrintAndLogEx(NORMAL, "TYPE : Gemplus MPCOS"); break; - default: ; - } + if(select_status == 0) { + DropField(); + return 0; + } + break; + case 0x01: PrintAndLogEx(NORMAL, "TYPE : NXP TNP3xxx Activision Game Appliance"); break; + case 0x04: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE (various !DESFire !DESFire EV1)"); isMifareClassic = false; break; + case 0x08: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE CLASSIC 1k | Plus 2k SL1 | 1k Ev1"); break; + case 0x09: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Mini 0.3k"); break; + case 0x0A: PrintAndLogEx(NORMAL, "TYPE : FM11RF005SH (Shanghai Metro)"); break; + case 0x10: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Plus 2k SL2"); break; + case 0x11: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Plus 4k SL2"); break; + case 0x18: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE Classic 4k | Plus 4k SL1 | 4k Ev1"); break; + case 0x20: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE DESFire 4k | DESFire EV1 2k/4k/8k | Plus 2k/4k SL3 | JCOP 31/41"); isMifareClassic = false; break; + case 0x24: PrintAndLogEx(NORMAL, "TYPE : NXP MIFARE DESFire | DESFire EV1"); isMifareClassic = false; break; + case 0x28: PrintAndLogEx(NORMAL, "TYPE : JCOP31 or JCOP41 v2.3.1"); break; + case 0x38: PrintAndLogEx(NORMAL, "TYPE : Nokia 6212 or 6131 MIFARE CLASSIC 4K"); break; + case 0x88: PrintAndLogEx(NORMAL, "TYPE : Infineon MIFARE CLASSIC 1K"); break; + case 0x98: PrintAndLogEx(NORMAL, "TYPE : Gemplus MPCOS"); break; + default: ; + } - // Double & triple sized UID, can be mapped to a manufacturer. - if ( card.uidlen > 4 ) { - PrintAndLogEx(NORMAL, "MANUFACTURER : %s", getTagInfo(card.uid[0])); - } + // Double & triple sized UID, can be mapped to a manufacturer. + if ( card.uidlen > 4 ) { + PrintAndLogEx(NORMAL, "MANUFACTURER : %s", getTagInfo(card.uid[0])); + } - // try to request ATS even if tag claims not to support it - if (select_status == 2) { - uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 - c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT; - c.arg[1] = 2; - c.arg[2] = 0; - memcpy(c.d.asBytes, rats, 2); - clearCommandBuffer(); - SendCommand(&c); - WaitForResponse(CMD_ACK,&resp); + // try to request ATS even if tag claims not to support it + if (select_status == 2) { + uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 + c.arg[0] = ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT; + c.arg[1] = 2; + c.arg[2] = 0; + memcpy(c.d.asBytes, rats, 2); + clearCommandBuffer(); + SendCommand(&c); + WaitForResponse(CMD_ACK,&resp); - memcpy(card.ats, resp.d.asBytes, resp.arg[0]); - card.ats_len = resp.arg[0]; // note: ats_len includes CRC Bytes - } + memcpy(card.ats, resp.d.asBytes, resp.arg[0]); + card.ats_len = resp.arg[0]; // note: ats_len includes CRC Bytes + } - if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes - bool ta1 = 0, tb1 = 0, tc1 = 0; - int pos; + if(card.ats_len >= 3) { // a valid ATS consists of at least the length byte (TL) and 2 CRC bytes + bool ta1 = 0, tb1 = 0, tc1 = 0; + int pos; - if (select_status == 2) { - PrintAndLogEx(NORMAL, "SAK incorrectly claims that card doesn't support RATS"); - } - PrintAndLogEx(NORMAL, " ATS : %s", sprint_hex(card.ats, card.ats_len)); - PrintAndLogEx(NORMAL, " - TL : length is %d bytes", card.ats[0]); - if (card.ats[0] != card.ats_len - 2) { - PrintAndLogEx(NORMAL, "ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len); - } + if (select_status == 2) { + PrintAndLogEx(NORMAL, "SAK incorrectly claims that card doesn't support RATS"); + } + PrintAndLogEx(NORMAL, " ATS : %s", sprint_hex(card.ats, card.ats_len)); + PrintAndLogEx(NORMAL, " - TL : length is %d bytes", card.ats[0]); + if (card.ats[0] != card.ats_len - 2) { + PrintAndLogEx(NORMAL, "ATS may be corrupted. Length of ATS (%d bytes incl. 2 Bytes CRC) doesn't match TL", card.ats_len); + } - if (card.ats[0] > 1) { // there is a format byte (T0) - ta1 = (card.ats[1] & 0x10) == 0x10; - tb1 = (card.ats[1] & 0x20) == 0x20; - tc1 = (card.ats[1] & 0x40) == 0x40; - int16_t fsci = card.ats[1] & 0x0f; + if (card.ats[0] > 1) { // there is a format byte (T0) + ta1 = (card.ats[1] & 0x10) == 0x10; + tb1 = (card.ats[1] & 0x20) == 0x20; + tc1 = (card.ats[1] & 0x40) == 0x40; + int16_t fsci = card.ats[1] & 0x0f; - PrintAndLogEx(NORMAL, " - T0 : TA1 is%s present, TB1 is%s present, " - "TC1 is%s present, FSCI is %d (FSC = %ld)", - (ta1 ? "" : " NOT"), - (tb1 ? "" : " NOT"), - (tc1 ? "" : " NOT"), - fsci, - fsci < sizeof(atsFSC) ? atsFSC[fsci] : -1 - ); - } - pos = 2; - if (ta1) { - char dr[16], ds[16]; - dr[0] = ds[0] = '\0'; - if (card.ats[pos] & 0x10) strcat(ds, "2, "); - if (card.ats[pos] & 0x20) strcat(ds, "4, "); - if (card.ats[pos] & 0x40) strcat(ds, "8, "); - if (card.ats[pos] & 0x01) strcat(dr, "2, "); - if (card.ats[pos] & 0x02) strcat(dr, "4, "); - if (card.ats[pos] & 0x04) strcat(dr, "8, "); - if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0'; - if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0'; - PrintAndLogEx(NORMAL, " - TA1 : different divisors are%s supported, " - "DR: [%s], DS: [%s]", - (card.ats[pos] & 0x80 ? " NOT" : ""), dr, ds); - pos++; - } - if (tb1) { - uint32_t sfgi = card.ats[pos] & 0x0F; - uint32_t fwi = card.ats[pos] >> 4; - PrintAndLogEx(NORMAL, " - TB1 : SFGI = %d (SFGT = %s%ld/fc), FWI = %d (FWT = %ld/fc)", - (sfgi), - sfgi ? "" : "(not needed) ", - sfgi ? (1 << 12) << sfgi : 0, - fwi, - (1 << 12) << fwi - ); - pos++; - } - if (tc1) { - PrintAndLogEx(NORMAL, " - TC1 : NAD is%s supported, CID is%s supported", - (card.ats[pos] & 0x01) ? "" : " NOT", - (card.ats[pos] & 0x02) ? "" : " NOT"); - pos++; - } - if (card.ats[0] > pos && card.ats[0] < card.ats_len - 2 ) { - char *tip = ""; - if (card.ats[0] - pos >= 7) { - if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) { - tip = "-> MIFARE Plus X 2K or 4K"; - } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { - tip = "-> MIFARE Plus S 2K or 4K"; - } - } - PrintAndLogEx(NORMAL, " - HB : %s%s", sprint_hex(card.ats + pos, card.ats[0] - pos), tip); - if (card.ats[pos] == 0xC1) { - PrintAndLogEx(NORMAL, " c1 -> Mifare or (multiple) virtual cards of various type"); - PrintAndLogEx(NORMAL, " %02x -> Length is %d bytes", card.ats[pos + 1], card.ats[pos + 1]); - switch (card.ats[pos + 2] & 0xf0) { - case 0x10: PrintAndLogEx(NORMAL, " 1x -> MIFARE DESFire"); break; - case 0x20: PrintAndLogEx(NORMAL, " 2x -> MIFARE Plus"); break; - } - switch (card.ats[pos + 2] & 0x0f) { - case 0x00: PrintAndLogEx(NORMAL, " x0 -> <1 kByte"); break; - case 0x01: PrintAndLogEx(NORMAL, " x1 -> 1 kByte"); break; - case 0x02: PrintAndLogEx(NORMAL, " x2 -> 2 kByte"); break; - case 0x03: PrintAndLogEx(NORMAL, " x3 -> 4 kByte"); break; - case 0x04: PrintAndLogEx(NORMAL, " x4 -> 8 kByte"); break; - } - switch (card.ats[pos + 3] & 0xf0) { - case 0x00: PrintAndLogEx(NORMAL, " 0x -> Engineering sample"); break; - case 0x20: PrintAndLogEx(NORMAL, " 2x -> Released"); break; - } - switch (card.ats[pos + 3] & 0x0f) { - case 0x00: PrintAndLogEx(NORMAL, " x0 -> Generation 1"); break; - case 0x01: PrintAndLogEx(NORMAL, " x1 -> Generation 2"); break; - case 0x02: PrintAndLogEx(NORMAL, " x2 -> Generation 3"); break; - } - switch (card.ats[pos + 4] & 0x0f) { - case 0x00: PrintAndLogEx(NORMAL, " x0 -> Only VCSL supported"); break; - case 0x01: PrintAndLogEx(NORMAL, " x1 -> VCS, VCSL, and SVC supported"); break; - case 0x0E: PrintAndLogEx(NORMAL, " xE -> no VCS command supported"); break; - } - } - } - } else { - PrintAndLogEx(INFO, "proprietary non iso14443-4 card found, RATS not supported"); - } + PrintAndLogEx(NORMAL, " - T0 : TA1 is%s present, TB1 is%s present, " + "TC1 is%s present, FSCI is %d (FSC = %ld)", + (ta1 ? "" : " NOT"), + (tb1 ? "" : " NOT"), + (tc1 ? "" : " NOT"), + fsci, + fsci < sizeof(atsFSC) ? atsFSC[fsci] : -1 + ); + } + pos = 2; + if (ta1) { + char dr[16], ds[16]; + dr[0] = ds[0] = '\0'; + if (card.ats[pos] & 0x10) strcat(ds, "2, "); + if (card.ats[pos] & 0x20) strcat(ds, "4, "); + if (card.ats[pos] & 0x40) strcat(ds, "8, "); + if (card.ats[pos] & 0x01) strcat(dr, "2, "); + if (card.ats[pos] & 0x02) strcat(dr, "4, "); + if (card.ats[pos] & 0x04) strcat(dr, "8, "); + if (strlen(ds) != 0) ds[strlen(ds) - 2] = '\0'; + if (strlen(dr) != 0) dr[strlen(dr) - 2] = '\0'; + PrintAndLogEx(NORMAL, " - TA1 : different divisors are%s supported, " + "DR: [%s], DS: [%s]", + (card.ats[pos] & 0x80 ? " NOT" : ""), dr, ds); + pos++; + } + if (tb1) { + uint32_t sfgi = card.ats[pos] & 0x0F; + uint32_t fwi = card.ats[pos] >> 4; + PrintAndLogEx(NORMAL, " - TB1 : SFGI = %d (SFGT = %s%ld/fc), FWI = %d (FWT = %ld/fc)", + (sfgi), + sfgi ? "" : "(not needed) ", + sfgi ? (1 << 12) << sfgi : 0, + fwi, + (1 << 12) << fwi + ); + pos++; + } + if (tc1) { + PrintAndLogEx(NORMAL, " - TC1 : NAD is%s supported, CID is%s supported", + (card.ats[pos] & 0x01) ? "" : " NOT", + (card.ats[pos] & 0x02) ? "" : " NOT"); + pos++; + } + if (card.ats[0] > pos && card.ats[0] < card.ats_len - 2 ) { + char *tip = ""; + if (card.ats[0] - pos >= 7) { + if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x01\xBC\xD6", 7) == 0) { + tip = "-> MIFARE Plus X 2K or 4K"; + } else if (memcmp(card.ats + pos, "\xC1\x05\x2F\x2F\x00\x35\xC7", 7) == 0) { + tip = "-> MIFARE Plus S 2K or 4K"; + } + } + PrintAndLogEx(NORMAL, " - HB : %s%s", sprint_hex(card.ats + pos, card.ats[0] - pos), tip); + if (card.ats[pos] == 0xC1) { + PrintAndLogEx(NORMAL, " c1 -> Mifare or (multiple) virtual cards of various type"); + PrintAndLogEx(NORMAL, " %02x -> Length is %d bytes", card.ats[pos + 1], card.ats[pos + 1]); + switch (card.ats[pos + 2] & 0xf0) { + case 0x10: PrintAndLogEx(NORMAL, " 1x -> MIFARE DESFire"); break; + case 0x20: PrintAndLogEx(NORMAL, " 2x -> MIFARE Plus"); break; + } + switch (card.ats[pos + 2] & 0x0f) { + case 0x00: PrintAndLogEx(NORMAL, " x0 -> <1 kByte"); break; + case 0x01: PrintAndLogEx(NORMAL, " x1 -> 1 kByte"); break; + case 0x02: PrintAndLogEx(NORMAL, " x2 -> 2 kByte"); break; + case 0x03: PrintAndLogEx(NORMAL, " x3 -> 4 kByte"); break; + case 0x04: PrintAndLogEx(NORMAL, " x4 -> 8 kByte"); break; + } + switch (card.ats[pos + 3] & 0xf0) { + case 0x00: PrintAndLogEx(NORMAL, " 0x -> Engineering sample"); break; + case 0x20: PrintAndLogEx(NORMAL, " 2x -> Released"); break; + } + switch (card.ats[pos + 3] & 0x0f) { + case 0x00: PrintAndLogEx(NORMAL, " x0 -> Generation 1"); break; + case 0x01: PrintAndLogEx(NORMAL, " x1 -> Generation 2"); break; + case 0x02: PrintAndLogEx(NORMAL, " x2 -> Generation 3"); break; + } + switch (card.ats[pos + 4] & 0x0f) { + case 0x00: PrintAndLogEx(NORMAL, " x0 -> Only VCSL supported"); break; + case 0x01: PrintAndLogEx(NORMAL, " x1 -> VCS, VCSL, and SVC supported"); break; + case 0x0E: PrintAndLogEx(NORMAL, " xE -> no VCS command supported"); break; + } + } + } + } else { + PrintAndLogEx(INFO, "proprietary non iso14443-4 card found, RATS not supported"); + } - detect_classic_magic(); + detect_classic_magic(); - if (isMifareClassic) { - int res = detect_classic_prng(); - if ( res == 1 ) - PrintAndLogEx(SUCCESS, "Prng detection: " _GREEN_(WEAK)); - else if (res == 0 ) - PrintAndLogEx(SUCCESS, "Prng detection: " _YELLOW_(HARD)); - else - PrintAndLogEx(FAILED, "prng detection: " _RED_(failed)); + if (isMifareClassic) { + int res = detect_classic_prng(); + if ( res == 1 ) + PrintAndLogEx(SUCCESS, "Prng detection: " _GREEN_(WEAK)); + else if (res == 0 ) + PrintAndLogEx(SUCCESS, "Prng detection: " _YELLOW_(HARD)); + else + PrintAndLogEx(FAILED, "prng detection: " _RED_(failed)); - if ( do_nack_test ) - detect_classic_nackbug(silent); - } + if ( do_nack_test ) + detect_classic_nackbug(silent); + } - return select_status; + return select_status; } // Collect ISO14443 Type A UIDs int CmdHF14ACUIDs(const char *Cmd) { - // requested number of UIDs - int n = atoi(Cmd); - // collect at least 1 (e.g. if no parameter was given) - n = n > 0 ? n : 1; + // requested number of UIDs + int n = atoi(Cmd); + // collect at least 1 (e.g. if no parameter was given) + n = n > 0 ? n : 1; - uint64_t t1 = msclock(); - PrintAndLogEx(SUCCESS, "collecting %d UIDs", n); + uint64_t t1 = msclock(); + PrintAndLogEx(SUCCESS, "collecting %d UIDs", n); - // repeat n times - for (int i = 0; i < n; i++) { + // repeat n times + for (int i = 0; i < n; i++) { - if (ukbhit()) { - int gc = getchar(); (void)gc; - PrintAndLogEx(WARNING, "\n[!] aborted via keyboard!\n"); - break; - } + if (ukbhit()) { + int gc = getchar(); (void)gc; + PrintAndLogEx(WARNING, "\n[!] aborted via keyboard!\n"); + break; + } - // execute anticollision procedure - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0}}; - SendCommand(&c); + // execute anticollision procedure + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_RATS, 0, 0}}; + SendCommand(&c); - UsbCommand resp; - WaitForResponse(CMD_ACK,&resp); + UsbCommand resp; + WaitForResponse(CMD_ACK,&resp); - iso14a_card_select_t *card = (iso14a_card_select_t *) resp.d.asBytes; + iso14a_card_select_t *card = (iso14a_card_select_t *) resp.d.asBytes; - // check if command failed - if (resp.arg[0] == 0) { - PrintAndLogEx(WARNING, "card select failed."); - } else { - char uid_string[20]; - for (uint16_t i = 0; i < card->uidlen; i++) { - sprintf(&uid_string[2*i], "%02X", card->uid[i]); - } - PrintAndLogEx(NORMAL, "%s", uid_string); - } - } - PrintAndLogEx(SUCCESS, "end: %" PRIu64 " seconds", (msclock()-t1)/1000); - return 1; + // check if command failed + if (resp.arg[0] == 0) { + PrintAndLogEx(WARNING, "card select failed."); + } else { + char uid_string[20]; + for (uint16_t i = 0; i < card->uidlen; i++) { + sprintf(&uid_string[2*i], "%02X", card->uid[i]); + } + PrintAndLogEx(NORMAL, "%s", uid_string); + } + } + PrintAndLogEx(SUCCESS, "end: %" PRIu64 " seconds", (msclock()-t1)/1000); + return 1; } // ## simulate iso14443a tag int CmdHF14ASim(const char *Cmd) { - bool errors = false; - uint8_t flags = 0; - uint8_t tagtype = 1; - uint8_t cmdp = 0; - uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; - int uidlen = 0; - bool useUIDfromEML = true; - bool setEmulatorMem = false; - bool verbose = false; - nonces_t data[1]; + bool errors = false; + uint8_t flags = 0; + uint8_t tagtype = 1; + uint8_t cmdp = 0; + uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; + int uidlen = 0; + bool useUIDfromEML = true; + bool setEmulatorMem = false; + bool verbose = false; + nonces_t data[1]; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { - case 'h': - case 'H': - return usage_hf_14a_sim(); - case 't': - case 'T': - // Retrieve the tag type - tagtype = param_get8ex(Cmd, cmdp+1, 0, 10); - if (tagtype == 0) - errors = true; - cmdp += 2; - break; - case 'u': - case 'U': - // Retrieve the full 4,7,10 byte long uid - param_gethex_ex(Cmd, cmdp+1, uid, &uidlen); - switch(uidlen) { - //case 20: flags |= FLAG_10B_UID_IN_DATA; break; - case 14: flags |= FLAG_7B_UID_IN_DATA; break; - case 8: flags |= FLAG_4B_UID_IN_DATA; break; - default: errors = true; break; - } - if (!errors) { - PrintAndLogEx(SUCCESS, "Emulating ISO/IEC 14443 type A tag with %d byte UID (%s)", uidlen>>1, sprint_hex(uid, uidlen>>1)); - useUIDfromEML = false; - } - cmdp += 2; - break; - case 'v': - case 'V': - verbose = true; - cmdp++; - break; - case 'x': - case 'X': - flags |= FLAG_NR_AR_ATTACK; - cmdp++; - break; - case 'e': - case 'E': - setEmulatorMem = true; - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch(param_getchar(Cmd, cmdp)) { + case 'h': + case 'H': + return usage_hf_14a_sim(); + case 't': + case 'T': + // Retrieve the tag type + tagtype = param_get8ex(Cmd, cmdp+1, 0, 10); + if (tagtype == 0) + errors = true; + cmdp += 2; + break; + case 'u': + case 'U': + // Retrieve the full 4,7,10 byte long uid + param_gethex_ex(Cmd, cmdp+1, uid, &uidlen); + switch(uidlen) { + //case 20: flags |= FLAG_10B_UID_IN_DATA; break; + case 14: flags |= FLAG_7B_UID_IN_DATA; break; + case 8: flags |= FLAG_4B_UID_IN_DATA; break; + default: errors = true; break; + } + if (!errors) { + PrintAndLogEx(SUCCESS, "Emulating ISO/IEC 14443 type A tag with %d byte UID (%s)", uidlen>>1, sprint_hex(uid, uidlen>>1)); + useUIDfromEML = false; + } + cmdp += 2; + break; + case 'v': + case 'V': + verbose = true; + cmdp++; + break; + case 'x': + case 'X': + flags |= FLAG_NR_AR_ATTACK; + cmdp++; + break; + case 'e': + case 'E': + setEmulatorMem = true; + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - //Validations - if (errors || cmdp == 0) return usage_hf_14a_sim(); + //Validations + if (errors || cmdp == 0) return usage_hf_14a_sim(); - if ( useUIDfromEML ) - flags |= FLAG_UID_IN_EMUL; + if ( useUIDfromEML ) + flags |= FLAG_UID_IN_EMUL; - UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,{ tagtype, flags, 0 }}; - memcpy(c.d.asBytes, uid, uidlen>>1); - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; + UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443a,{ tagtype, flags, 0 }}; + memcpy(c.d.asBytes, uid, uidlen>>1); + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; - PrintAndLogEx(SUCCESS, "press pm3-button to abort simulation"); + PrintAndLogEx(SUCCESS, "press pm3-button to abort simulation"); - while( !ukbhit() ){ - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; - if ( !(flags & FLAG_NR_AR_ATTACK) ) break; - if ( (resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD ) break; + while( !ukbhit() ){ + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; + if ( !(flags & FLAG_NR_AR_ATTACK) ) break; + if ( (resp.arg[0] & 0xffff) != CMD_SIMULATE_MIFARE_CARD ) break; - memcpy(data, resp.d.asBytes, sizeof(data) ); - readerAttack(data[0], setEmulatorMem, verbose); - } - showSectorTable(); - return 0; + memcpy(data, resp.d.asBytes, sizeof(data) ); + readerAttack(data[0], setEmulatorMem, verbose); + } + showSectorTable(); + return 0; } int CmdHF14ASniff(const char *Cmd) { - int param = 0; - uint8_t ctmp; - for (int i = 0; i < 2; i++) { - ctmp = tolower(param_getchar(Cmd, i)); - if (ctmp == 'h') return usage_hf_14a_sniff(); - if (ctmp == 'c') param |= 0x01; - if (ctmp == 'r') param |= 0x02; - } - UsbCommand c = {CMD_SNOOP_ISO_14443a, {param, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + int param = 0; + uint8_t ctmp; + for (int i = 0; i < 2; i++) { + ctmp = tolower(param_getchar(Cmd, i)); + if (ctmp == 'h') return usage_hf_14a_sniff(); + if (ctmp == 'c') param |= 0x01; + if (ctmp == 'r') param |= 0x02; + } + UsbCommand c = {CMD_SNOOP_ISO_14443a, {param, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { - static bool responseNum = false; - uint16_t cmdc = 0; - *dataoutlen = 0; + static bool responseNum = false; + uint16_t cmdc = 0; + *dataoutlen = 0; - if (activateField) { - responseNum = false; - UsbCommand resp; + if (activateField) { + responseNum = false; + UsbCommand resp; - // Anticollision + SELECT card - UsbCommand ca = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; - SendCommand(&ca); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(ERR, "Proxmark connection timeout."); - return 1; - } + // Anticollision + SELECT card + UsbCommand ca = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; + SendCommand(&ca); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + PrintAndLogEx(ERR, "Proxmark connection timeout."); + return 1; + } - // check result - if (resp.arg[0] == 0) { - PrintAndLogEx(ERR, "No card in field."); - return 1; - } + // check result + if (resp.arg[0] == 0) { + PrintAndLogEx(ERR, "No card in field."); + return 1; + } - if (resp.arg[0] != 1 && resp.arg[0] != 2) { - PrintAndLogEx(ERR, "Card not in iso14443-4. res=%d.", resp.arg[0]); - return 1; - } + if (resp.arg[0] != 1 && resp.arg[0] != 2) { + PrintAndLogEx(ERR, "Card not in iso14443-4. res=%d.", resp.arg[0]); + return 1; + } - if (resp.arg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - // get ATS - UsbCommand cr = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0}}; - uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 - memcpy(cr.d.asBytes, rats, 2); - SendCommand(&cr); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(ERR, "Proxmark connection timeout."); - return 1; - } + if (resp.arg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision + // get ATS + UsbCommand cr = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0}}; + uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 + memcpy(cr.d.asBytes, rats, 2); + SendCommand(&cr); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + PrintAndLogEx(ERR, "Proxmark connection timeout."); + return 1; + } - if (resp.arg[0] <= 0) { // ats_len - PrintAndLogEx(ERR, "Can't get ATS."); - return 1; - } - } - } + if (resp.arg[0] <= 0) { // ats_len + PrintAndLogEx(ERR, "Can't get ATS."); + return 1; + } + } + } - if (leaveSignalON) - cmdc |= ISO14A_NO_DISCONNECT; + if (leaveSignalON) + cmdc |= ISO14A_NO_DISCONNECT; - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF) + 2, 0}}; - uint8_t header[] = {0x0a | responseNum, 0x00}; - responseNum ^= 1; - memcpy(c.d.asBytes, header, 2); - memcpy(&c.d.asBytes[2], datain, datainlen); - SendCommand(&c); + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | cmdc, (datainlen & 0xFFFF) + 2, 0}}; + uint8_t header[] = {0x0a | responseNum, 0x00}; + responseNum ^= 1; + memcpy(c.d.asBytes, header, 2); + memcpy(&c.d.asBytes[2], datain, datainlen); + SendCommand(&c); uint8_t *recv; UsbCommand resp; @@ -804,132 +804,132 @@ int ExchangeRAW14a(uint8_t *datain, int datainlen, bool activateField, bool leav int iLen = resp.arg[0]; if(!iLen) { - PrintAndLogEx(ERR, "No card response."); + PrintAndLogEx(ERR, "No card response."); return 1; - } + } - *dataoutlen = iLen - 2; - if (*dataoutlen < 0) - *dataoutlen = 0; + *dataoutlen = iLen - 2; + if (*dataoutlen < 0) + *dataoutlen = 0; - if (maxdataoutlen && *dataoutlen > maxdataoutlen) { - PrintAndLogEx(ERR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); - return 2; - } + if (maxdataoutlen && *dataoutlen > maxdataoutlen) { + PrintAndLogEx(ERR, "Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); + return 2; + } - if (recv[0] != header[0]) { - PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", dataout[0], header[0]); - return 2; - } + if (recv[0] != header[0]) { + PrintAndLogEx(ERR, "iso14443-4 framing error. Card send %2x must be %2x", dataout[0], header[0]); + return 2; + } - memcpy(dataout, &recv[2], *dataoutlen); + memcpy(dataout, &recv[2], *dataoutlen); - // CRC Check - if (iLen == -1) { - PrintAndLogEx(ERR, "ISO 14443A CRC error."); - return 3; - } + // CRC Check + if (iLen == -1) { + PrintAndLogEx(ERR, "ISO 14443A CRC error."); + return 3; + } } else { PrintAndLogEx(ERR, "Reply timeout."); - return 4; + return 4; } - return 0; + return 0; } int SelectCard14443_4(bool disconnect, iso14a_card_select_t *card) { UsbCommand resp; - frameLength = 0; + frameLength = 0; - if (card) - memset(card, 0, sizeof(iso14a_card_select_t)); + if (card) + memset(card, 0, sizeof(iso14a_card_select_t)); - DropField(); + DropField(); - // Anticollision + SELECT card - UsbCommand ca = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; - SendCommand(&ca); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(ERR, "Proxmark connection timeout."); - return 1; - } + // Anticollision + SELECT card + UsbCommand ca = {CMD_READER_ISO_14443a, {ISO14A_CONNECT | ISO14A_NO_DISCONNECT, 0, 0}}; + SendCommand(&ca); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + PrintAndLogEx(ERR, "Proxmark connection timeout."); + return 1; + } - // check result - if (resp.arg[0] == 0) { - PrintAndLogEx(ERR, "No card in field."); - return 1; - } + // check result + if (resp.arg[0] == 0) { + PrintAndLogEx(ERR, "No card in field."); + return 1; + } - if (resp.arg[0] != 1 && resp.arg[0] != 2) { - PrintAndLogEx(ERR, "Card not in iso14443-4. res=%d.", resp.arg[0]); - return 1; - } + if (resp.arg[0] != 1 && resp.arg[0] != 2) { + PrintAndLogEx(ERR, "Card not in iso14443-4. res=%d.", resp.arg[0]); + return 1; + } - if (resp.arg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision - // get ATS - UsbCommand cr = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0}}; - uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 - memcpy(cr.d.asBytes, rats, 2); - SendCommand(&cr); - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - PrintAndLogEx(ERR, "Proxmark connection timeout."); - return 1; - } + if (resp.arg[0] == 2) { // 0: couldn't read, 1: OK, with ATS, 2: OK, no ATS, 3: proprietary Anticollision + // get ATS + UsbCommand cr = {CMD_READER_ISO_14443a, {ISO14A_RAW | ISO14A_APPEND_CRC | ISO14A_NO_DISCONNECT, 2, 0}}; + uint8_t rats[] = { 0xE0, 0x80 }; // FSDI=8 (FSD=256), CID=0 + memcpy(cr.d.asBytes, rats, 2); + SendCommand(&cr); + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { + PrintAndLogEx(ERR, "Proxmark connection timeout."); + return 1; + } - if (resp.arg[0] <= 0) { // ats_len - PrintAndLogEx(ERR, "Can't get ATS."); - return 1; - } + if (resp.arg[0] <= 0) { // ats_len + PrintAndLogEx(ERR, "Can't get ATS."); + return 1; + } - // get frame length from ATS in data field - if (resp.arg[0] > 1) { - uint8_t fsci = resp.d.asBytes[1] & 0x0f; - if (fsci < sizeof(atsFSC)) - frameLength = atsFSC[fsci]; - } - } else { - // get frame length from ATS in card data structure - iso14a_card_select_t *vcard = (iso14a_card_select_t *) resp.d.asBytes; - if (vcard->ats_len > 1) { - uint8_t fsci = vcard->ats[1] & 0x0f; - if (fsci < sizeof(atsFSC)) - frameLength = atsFSC[fsci]; - } + // get frame length from ATS in data field + if (resp.arg[0] > 1) { + uint8_t fsci = resp.d.asBytes[1] & 0x0f; + if (fsci < sizeof(atsFSC)) + frameLength = atsFSC[fsci]; + } + } else { + // get frame length from ATS in card data structure + iso14a_card_select_t *vcard = (iso14a_card_select_t *) resp.d.asBytes; + if (vcard->ats_len > 1) { + uint8_t fsci = vcard->ats[1] & 0x0f; + if (fsci < sizeof(atsFSC)) + frameLength = atsFSC[fsci]; + } - if (card) - memcpy(card, vcard, sizeof(iso14a_card_select_t)); - } + if (card) + memcpy(card, vcard, sizeof(iso14a_card_select_t)); + } - if (disconnect) - DropField(); + if (disconnect) + DropField(); - return 0; + return 0; } int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activateField, uint8_t *dataout, int maxdataoutlen, int *dataoutlen, bool *chainingout) { - *chainingout = false; + *chainingout = false; - if (activateField) { - // select with no disconnect and set frameLength - int selres = SelectCard14443_4(false, NULL); - if (selres) - return selres; - } + if (activateField) { + // select with no disconnect and set frameLength + int selres = SelectCard14443_4(false, NULL); + if (selres) + return selres; + } - uint16_t cmdc = 0; - if (chainingin) - cmdc = ISO14A_SEND_CHAINING; + uint16_t cmdc = 0; + if (chainingin) + cmdc = ISO14A_SEND_CHAINING; - // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes - // https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size - // here length USB_CMD_DATA_SIZE=512 - // timeout must be authomatically set by "get ATS" - UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, (datainlen & 0xFFFF), 0}}; - memcpy(c.d.asBytes, datain, datainlen); - SendCommand(&c); + // "Command APDU" length should be 5+255+1, but javacard's APDU buffer might be smaller - 133 bytes + // https://stackoverflow.com/questions/32994936/safe-max-java-card-apdu-data-command-and-respond-size + // here length USB_CMD_DATA_SIZE=512 + // timeout must be authomatically set by "get ATS" + UsbCommand c = {CMD_READER_ISO_14443a, {ISO14A_APDU | ISO14A_NO_DISCONNECT | cmdc, (datainlen & 0xFFFF), 0}}; + memcpy(c.d.asBytes, datain, datainlen); + SendCommand(&c); uint8_t *recv; UsbCommand resp; @@ -937,177 +937,177 @@ int CmdExchangeAPDU(bool chainingin, uint8_t *datain, int datainlen, bool activa if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { recv = resp.d.asBytes; int iLen = resp.arg[0]; - uint8_t res = resp.arg[1]; + uint8_t res = resp.arg[1]; - int dlen = iLen - 2; - if (dlen < 0) - dlen = 0; - *dataoutlen += dlen; + int dlen = iLen - 2; + if (dlen < 0) + dlen = 0; + *dataoutlen += dlen; - if (maxdataoutlen && *dataoutlen > maxdataoutlen) { - PrintAndLogEx(ERR, "APDU: Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); - return 2; - } + if (maxdataoutlen && *dataoutlen > maxdataoutlen) { + PrintAndLogEx(ERR, "APDU: Buffer too small(%d). Needs %d bytes", *dataoutlen, maxdataoutlen); + return 2; + } - // I-block ACK - if ((res & 0xf2) == 0xa2) { - *dataoutlen = 0; - *chainingout = true; - return 0; - } + // I-block ACK + if ((res & 0xf2) == 0xa2) { + *dataoutlen = 0; + *chainingout = true; + return 0; + } if(!iLen) { - PrintAndLogEx(ERR, "APDU: No APDU response."); + PrintAndLogEx(ERR, "APDU: No APDU response."); return 1; - } + } - // check apdu length - if (iLen < 2 && iLen >= 0) { - PrintAndLogEx(ERR, "APDU: Small APDU response. Len=%d", iLen); - return 2; - } + // check apdu length + if (iLen < 2 && iLen >= 0) { + PrintAndLogEx(ERR, "APDU: Small APDU response. Len=%d", iLen); + return 2; + } - // check block TODO - if (iLen == -2) { - PrintAndLogEx(ERR, "APDU: Block type mismatch."); - return 2; - } + // check block TODO + if (iLen == -2) { + PrintAndLogEx(ERR, "APDU: Block type mismatch."); + return 2; + } - memcpy(dataout, recv, dlen); + memcpy(dataout, recv, dlen); - // chaining - if ((res & 0x10) != 0) { - *chainingout = true; - } + // chaining + if ((res & 0x10) != 0) { + *chainingout = true; + } - // CRC Check - if (iLen == -1) { - PrintAndLogEx(ERR, "APDU: ISO 14443A CRC error."); - return 3; - } + // CRC Check + if (iLen == -1) { + PrintAndLogEx(ERR, "APDU: ISO 14443A CRC error."); + return 3; + } } else { PrintAndLogEx(ERR, "APDU: Reply timeout."); - return 4; + return 4; } - return 0; + return 0; } int ExchangeAPDU14a(uint8_t *datain, int datainlen, bool activateField, bool leaveSignalON, uint8_t *dataout, int maxdataoutlen, int *dataoutlen) { - *dataoutlen = 0; - bool chaining = false; - int res; + *dataoutlen = 0; + bool chaining = false; + int res; - // 3 byte here - 1b framing header, 2b crc16 - if (APDUInFramingEnable && - ( (frameLength && (datainlen > frameLength - 3)) || (datainlen > USB_CMD_DATA_SIZE - 3)) ) { - int clen = 0; + // 3 byte here - 1b framing header, 2b crc16 + if (APDUInFramingEnable && + ( (frameLength && (datainlen > frameLength - 3)) || (datainlen > USB_CMD_DATA_SIZE - 3)) ) { + int clen = 0; - bool vActivateField = activateField; + bool vActivateField = activateField; - do { - int vlen = MIN(frameLength - 3, datainlen - clen); - bool chainBlockNotLast = ((clen + vlen) < datainlen); + do { + int vlen = MIN(frameLength - 3, datainlen - clen); + bool chainBlockNotLast = ((clen + vlen) < datainlen); - *dataoutlen = 0; - res = CmdExchangeAPDU(chainBlockNotLast, &datain[clen], vlen, vActivateField, dataout, maxdataoutlen, dataoutlen, &chaining); - if (res) { - if (!leaveSignalON) - DropField(); + *dataoutlen = 0; + res = CmdExchangeAPDU(chainBlockNotLast, &datain[clen], vlen, vActivateField, dataout, maxdataoutlen, dataoutlen, &chaining); + if (res) { + if (!leaveSignalON) + DropField(); - return 200; - } + return 200; + } - // check R-block ACK - if ((*dataoutlen == 0) && (*dataoutlen != 0 || chaining != chainBlockNotLast)) { - if (!leaveSignalON) - DropField(); + // check R-block ACK + if ((*dataoutlen == 0) && (*dataoutlen != 0 || chaining != chainBlockNotLast)) { + if (!leaveSignalON) + DropField(); - return 201; - } + return 201; + } - clen += vlen; - vActivateField = false; - if (*dataoutlen) { - if (clen != datainlen) - PrintAndLogEx(WARNING, "APDU: I-block/R-block sequence error. Data len=%d, Sent=%d, Last packet len=%d", datainlen, clen, *dataoutlen); - break; - } - } while (clen < datainlen); - } else { - res = CmdExchangeAPDU(false, datain, datainlen, activateField, dataout, maxdataoutlen, dataoutlen, &chaining); - if (res) { - if (!leaveSignalON) - DropField(); + clen += vlen; + vActivateField = false; + if (*dataoutlen) { + if (clen != datainlen) + PrintAndLogEx(WARNING, "APDU: I-block/R-block sequence error. Data len=%d, Sent=%d, Last packet len=%d", datainlen, clen, *dataoutlen); + break; + } + } while (clen < datainlen); + } else { + res = CmdExchangeAPDU(false, datain, datainlen, activateField, dataout, maxdataoutlen, dataoutlen, &chaining); + if (res) { + if (!leaveSignalON) + DropField(); - return res; - } - } + return res; + } + } - while (chaining) { - // I-block with chaining - res = CmdExchangeAPDU(false, NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining); + while (chaining) { + // I-block with chaining + res = CmdExchangeAPDU(false, NULL, 0, false, &dataout[*dataoutlen], maxdataoutlen, dataoutlen, &chaining); - if (res) { - if (!leaveSignalON) - DropField(); + if (res) { + if (!leaveSignalON) + DropField(); - return 100; - } - } + return 100; + } + } - if (!leaveSignalON) - DropField(); + if (!leaveSignalON) + DropField(); - return 0; + return 0; } // ISO14443-4. 7. Half-duplex block transmission protocol int CmdHF14AAPDU(const char *cmd) { - uint8_t data[USB_CMD_DATA_SIZE]; - int datalen = 0; - bool activateField = false; - bool leaveSignalON = false; - bool decodeTLV = false; + uint8_t data[USB_CMD_DATA_SIZE]; + int datalen = 0; + bool activateField = false; + bool leaveSignalON = false; + bool decodeTLV = false; - CLIParserInit("hf 14a apdu", - "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL)", - "Sample:\n\thf 14a apdu -st 00A404000E325041592E5359532E444446303100\n"); + CLIParserInit("hf 14a apdu", + "Sends an ISO 7816-4 APDU via ISO 14443-4 block transmission protocol (T=CL)", + "Sample:\n\thf 14a apdu -st 00A404000E325041592E5359532E444446303100\n"); - void* argtable[] = { - arg_param_begin, - arg_lit0("sS", "select", "activate field and select card"), - arg_lit0("kK", "keep", "leave the signal field ON after receive response"), - arg_lit0("tT", "tlv", "executes TLV decoder if it possible"), - arg_strx1(NULL, NULL, "", NULL), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, false); + void* argtable[] = { + arg_param_begin, + arg_lit0("sS", "select", "activate field and select card"), + arg_lit0("kK", "keep", "leave the signal field ON after receive response"), + arg_lit0("tT", "tlv", "executes TLV decoder if it possible"), + arg_strx1(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, false); - activateField = arg_get_lit(1); - leaveSignalON = arg_get_lit(2); - decodeTLV = arg_get_lit(3); - // len = data + PCB(1b) + CRC(2b) - CLIGetHexBLessWithReturn(4, data, &datalen, 1 + 2); + activateField = arg_get_lit(1); + leaveSignalON = arg_get_lit(2); + decodeTLV = arg_get_lit(3); + // len = data + PCB(1b) + CRC(2b) + CLIGetHexBLessWithReturn(4, data, &datalen, 1 + 2); CLIParserFree(); - PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s", activateField ? "sel ": "", leaveSignalON ? "keep ": "", decodeTLV ? "TLV": "", sprint_hex(data, datalen)); + PrintAndLogEx(NORMAL, ">>>>[%s%s%s] %s", activateField ? "sel ": "", leaveSignalON ? "keep ": "", decodeTLV ? "TLV": "", sprint_hex(data, datalen)); - int res = ExchangeAPDU14a(data, datalen, activateField, leaveSignalON, data, USB_CMD_DATA_SIZE, &datalen); + int res = ExchangeAPDU14a(data, datalen, activateField, leaveSignalON, data, USB_CMD_DATA_SIZE, &datalen); - if (res) - return res; + if (res) + return res; - PrintAndLogEx(NORMAL, "<<<< %s", sprint_hex(data, datalen)); + PrintAndLogEx(NORMAL, "<<<< %s", sprint_hex(data, datalen)); - PrintAndLogEx(SUCCESS, "APDU response: %02x %02x - %s", data[datalen - 2], data[datalen - 1], GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1])); + PrintAndLogEx(SUCCESS, "APDU response: %02x %02x - %s", data[datalen - 2], data[datalen - 1], GetAPDUCodeDescription(data[datalen - 2], data[datalen - 1])); - // TLV decoder - if (decodeTLV && datalen > 4) { - TLVPrintFromBuffer(data, datalen - 2); - } + // TLV decoder + if (decodeTLV && datalen > 4) { + TLVPrintFromBuffer(data, datalen - 2); + } - return 0; + return 0; } int CmdHF14ACmdRaw(const char *cmd) { @@ -1117,16 +1117,16 @@ int CmdHF14ACmdRaw(const char *cmd) { bool power = false; bool active = false; bool active_select = false; - bool no_rats = false; + bool no_rats = false; uint16_t numbits = 0; - bool bTimeout = false; - uint32_t timeout = 0; - bool topazmode = false; + bool bTimeout = false; + uint32_t timeout = 0; + bool topazmode = false; char buf[5]=""; int i = 0; uint8_t data[USB_CMD_DATA_SIZE]; - uint16_t datalen = 0; - uint32_t temp; + uint16_t datalen = 0; + uint32_t temp; if (strlen(cmd) < 2) return usage_hf_14a_raw(); @@ -1137,9 +1137,9 @@ int CmdHF14ACmdRaw(const char *cmd) { if (cmd[i]==' ' || cmd[i]=='\t') { i++; continue; } if (cmd[i]=='-') { switch (cmd[i+1]) { - case 'H': - case 'h': - return usage_hf_14a_raw(); + case 'H': + case 'h': + return usage_hf_14a_raw(); case 'r': reply = false; break; @@ -1162,20 +1162,20 @@ int CmdHF14ACmdRaw(const char *cmd) { while(cmd[i]!=' ' && cmd[i]!='\0') { i++; } i-=2; break; - case 't': - bTimeout = true; - sscanf(cmd+i+2, "%d", &temp); - timeout = temp; - i+=3; - while(cmd[i]!=' ' && cmd[i]!='\0') { i++; } - i-=2; - break; + case 't': + bTimeout = true; + sscanf(cmd+i+2, "%d", &temp); + timeout = temp; + i+=3; + while(cmd[i]!=' ' && cmd[i]!='\0') { i++; } + i-=2; + break; case 'T': - topazmode = true; - break; - case '3': - no_rats = true; - break; + topazmode = true; + break; + case '3': + no_rats = true; + break; default: return usage_hf_14a_raw(); } @@ -1193,11 +1193,11 @@ int CmdHF14ACmdRaw(const char *cmd) { sscanf(buf, "%x", &temp); data[datalen] = (uint8_t)(temp & 0xff); *buf = 0; - if (++datalen >= sizeof(data)){ - if (crc) - PrintAndLogEx(NORMAL, "Buffer is full, we can't add CRC to your data"); - break; - } + if (++datalen >= sizeof(data)){ + if (crc) + PrintAndLogEx(NORMAL, "Buffer is full, we can't add CRC to your data"); + break; + } } continue; } @@ -1207,11 +1207,11 @@ int CmdHF14ACmdRaw(const char *cmd) { if (crc && datalen > 0 && datalen < sizeof(data)-2) { uint8_t first, second; - if (topazmode) { - compute_crc(CRC_14443_B, data, datalen, &first, &second); - } else { - compute_crc(CRC_14443_A, data, datalen, &first, &second); - } + if (topazmode) { + compute_crc(CRC_14443_B, data, datalen, &first, &second); + } else { + compute_crc(CRC_14443_A, data, datalen, &first, &second); + } data[datalen++] = first; data[datalen++] = second; } @@ -1222,45 +1222,45 @@ int CmdHF14ACmdRaw(const char *cmd) { c.arg[0] |= ISO14A_NO_SELECT; } - if (bTimeout){ - #define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s + if (bTimeout){ + #define MAX_TIMEOUT 40542464 // = (2^32-1) * (8*16) / 13560000Hz * 1000ms/s c.arg[0] |= ISO14A_SET_TIMEOUT; if(timeout > MAX_TIMEOUT) { timeout = MAX_TIMEOUT; PrintAndLogEx(NORMAL, "Set timeout to 40542 seconds (11.26 hours). The max we can wait for response"); } - c.arg[2] = 13560000 / 1000 / (8*16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us) - } + c.arg[2] = 13560000 / 1000 / (8*16) * timeout; // timeout in ETUs (time to transfer 1 bit, approx. 9.4 us) + } if (power) { c.arg[0] |= ISO14A_NO_DISCONNECT; - } + } if (datalen > 0) { c.arg[0] |= ISO14A_RAW; - } + } - if (topazmode) { - c.arg[0] |= ISO14A_TOPAZMODE; - } - if (no_rats) { - c.arg[0] |= ISO14A_NO_RATS; - } + if (topazmode) { + c.arg[0] |= ISO14A_TOPAZMODE; + } + if (no_rats) { + c.arg[0] |= ISO14A_NO_RATS; + } - // Max buffer is USB_CMD_DATA_SIZE - datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; + // Max buffer is USB_CMD_DATA_SIZE + datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; c.arg[1] = (datalen & 0xFFFF) | ((uint32_t)(numbits << 16)); memcpy(c.d.asBytes, data, datalen); - clearCommandBuffer(); + clearCommandBuffer(); SendCommand(&c); if (reply) { - int res = 0; + int res = 0; if (active_select) - res = waitCmd(1); - if (!res && datalen > 0) + res = waitCmd(1); + if (!res && datalen > 0) waitCmd(0); } return 0; @@ -1271,108 +1271,108 @@ static int waitCmd(uint8_t iSelect) { uint16_t len = 0; if (WaitForResponseTimeout(CMD_ACK, &resp, 1500)) { - len = (resp.arg[0] & 0xFFFF); - if (iSelect){ - len = (resp.arg[1] & 0xFFFF); - if (len){ - PrintAndLogEx(NORMAL, "Card selected. UID[%i]:", len); - } else { - PrintAndLogEx(WARNING, "Can't select card."); - } - } else { - PrintAndLogEx(NORMAL, "received %i bytes", len); - } + len = (resp.arg[0] & 0xFFFF); + if (iSelect){ + len = (resp.arg[1] & 0xFFFF); + if (len){ + PrintAndLogEx(NORMAL, "Card selected. UID[%i]:", len); + } else { + PrintAndLogEx(WARNING, "Can't select card."); + } + } else { + PrintAndLogEx(NORMAL, "received %i bytes", len); + } if (!len) return 1; - PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) ); + PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) ); } else { PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 3; + return 3; } - return 0; + return 0; } int CmdHF14AAntiFuzz(const char *cmd) { - CLIParserInit("hf 14a antifuzz", - "Tries to fuzz the ISO14443a anticollision phase", - "Usage:\n" - "\thf 14a antifuzz -4\n"); + CLIParserInit("hf 14a antifuzz", + "Tries to fuzz the ISO14443a anticollision phase", + "Usage:\n" + "\thf 14a antifuzz -4\n"); - void* argtable[] = { - arg_param_begin, - arg_lit0("4", NULL, "4 byte uid"), - arg_lit0("7", NULL, "7 byte uid"), - arg_lit0(NULL, "10", "10 byte uid"), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, false); + void* argtable[] = { + arg_param_begin, + arg_lit0("4", NULL, "4 byte uid"), + arg_lit0("7", NULL, "7 byte uid"), + arg_lit0(NULL, "10", "10 byte uid"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, false); - uint8_t arg0 = FLAG_4B_UID_IN_DATA; - if (arg_get_lit(2)) - arg0 = FLAG_7B_UID_IN_DATA; - if (arg_get_lit(3)) - arg0 = FLAG_10B_UID_IN_DATA; + uint8_t arg0 = FLAG_4B_UID_IN_DATA; + if (arg_get_lit(2)) + arg0 = FLAG_7B_UID_IN_DATA; + if (arg_get_lit(3)) + arg0 = FLAG_10B_UID_IN_DATA; - CLIParserFree(); - UsbCommand c = {CMD_ANTIFUZZ_ISO_14443a, {arg0, 0, 0}}; - clearCommandBuffer(); + CLIParserFree(); + UsbCommand c = {CMD_ANTIFUZZ_ISO_14443a, {arg0, 0, 0}}; + clearCommandBuffer(); SendCommand(&c); - return 0; + return 0; } int CmdHF14AChaining(const char *cmd) { - CLIParserInit("hf 14a chaining", - "Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.", - "Usage:\n" - "\thf 14a chaining disable -> disable chaining\n" - "\thf 14a chaining -> show chaining enable/disable state\n"); + CLIParserInit("hf 14a chaining", + "Enable/Disable ISO14443a input chaining. Maximum input length goes from ATS.", + "Usage:\n" + "\thf 14a chaining disable -> disable chaining\n" + "\thf 14a chaining -> show chaining enable/disable state\n"); - void* argtable[] = { - arg_param_begin, - arg_str0(NULL, NULL, "", NULL), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, true); + void* argtable[] = { + arg_param_begin, + arg_str0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); - struct arg_str *str = arg_get_str(1); - int len = arg_get_str_len(1); + struct arg_str *str = arg_get_str(1); + int len = arg_get_str_len(1); - if (len && (!strcmp(str->sval[0], "enable") || !strcmp(str->sval[0], "1"))) - APDUInFramingEnable = true; + if (len && (!strcmp(str->sval[0], "enable") || !strcmp(str->sval[0], "1"))) + APDUInFramingEnable = true; - if (len && (!strcmp(str->sval[0], "disable") || !strcmp(str->sval[0], "0"))) - APDUInFramingEnable = false; + if (len && (!strcmp(str->sval[0], "disable") || !strcmp(str->sval[0], "0"))) + APDUInFramingEnable = false; - CLIParserFree(); + CLIParserFree(); - PrintAndLogEx(INFO, "\nISO 14443-4 input chaining %s.\n", APDUInFramingEnable ? "enabled" : "disabled"); + PrintAndLogEx(INFO, "\nISO 14443-4 input chaining %s.\n", APDUInFramingEnable ? "enabled" : "disabled"); - return 0; + return 0; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"list", CmdHF14AList, 0, "[Deprecated] List ISO 14443-a history"}, - {"info", CmdHF14AInfo, 0, "Tag information"}, - {"reader", CmdHF14AReader, 0, "Act like an ISO14443-a reader"}, - {"cuids", CmdHF14ACUIDs, 0, " Collect n>0 ISO14443-a UIDs in one go"}, - {"sim", CmdHF14ASim, 0, " -- Simulate ISO 14443-a tag"}, - {"sniff", CmdHF14ASniff, 0, "sniff ISO 14443-a traffic"}, - {"apdu", CmdHF14AAPDU, 0, "Send ISO 14443-4 APDU to tag"}, - {"chaining", CmdHF14AChaining, 0, "Control ISO 14443-4 input chaining"}, - {"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"}, - {"antifuzz", CmdHF14AAntiFuzz, 0, "Fuzzing the anticollision phase. Warning! Readers may react strange"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"list", CmdHF14AList, 0, "[Deprecated] List ISO 14443-a history"}, + {"info", CmdHF14AInfo, 0, "Tag information"}, + {"reader", CmdHF14AReader, 0, "Act like an ISO14443-a reader"}, + {"cuids", CmdHF14ACUIDs, 0, " Collect n>0 ISO14443-a UIDs in one go"}, + {"sim", CmdHF14ASim, 0, " -- Simulate ISO 14443-a tag"}, + {"sniff", CmdHF14ASniff, 0, "sniff ISO 14443-a traffic"}, + {"apdu", CmdHF14AAPDU, 0, "Send ISO 14443-4 APDU to tag"}, + {"chaining", CmdHF14AChaining, 0, "Control ISO 14443-4 input chaining"}, + {"raw", CmdHF14ACmdRaw, 0, "Send raw hex data to tag"}, + {"antifuzz", CmdHF14AAntiFuzz, 0, "Fuzzing the anticollision phase. Warning! Readers may react strange"}, + {NULL, NULL, 0, NULL} }; int CmdHF14A(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { diff --git a/client/cmdhf14a.h b/client/cmdhf14a.h index 4396c4b79..73cbd069c 100644 --- a/client/cmdhf14a.h +++ b/client/cmdhf14a.h @@ -28,15 +28,15 @@ #include "mifare.h" #include "cmdhfmf.h" #include "cmdhfmfu.h" -#include "cmdhf.h" // list cmd +#include "cmdhf.h" // list cmd #include "mifare/mifarehost.h" #include "emv/apduinfo.h" #include "emv/emvcore.h" // structure and database for uid -> tagtype lookups typedef struct { - uint8_t uid; - char* desc; + uint8_t uid; + char* desc; } manufactureName; extern int CmdHF14A(const char *Cmd); diff --git a/client/cmdhf14b.c b/client/cmdhf14b.c index f74ca9a34..c3962a17f 100644 --- a/client/cmdhf14b.c +++ b/client/cmdhf14b.c @@ -15,152 +15,152 @@ static int CmdHelp(const char *Cmd); int usage_hf_14b_info(void){ - PrintAndLogEx(NORMAL, "Usage: hf 14b info [h] [s]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " s silently"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " hf 14b info"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 14b info [h] [s]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " s silently"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " hf 14b info"); + return 0; } int usage_hf_14b_reader(void){ - PrintAndLogEx(NORMAL, "Usage: hf 14b reader [h] [s]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " s silently"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " hf 14b reader"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 14b reader [h] [s]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " s silently"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " hf 14b reader"); + return 0; } int usage_hf_14b_raw(void){ - PrintAndLogEx(NORMAL, "Usage: hf 14b raw [-h] [-r] [-c] [-p] [-s || -ss] <0A 0B 0C ... hex>"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -r do not read response"); - PrintAndLogEx(NORMAL, " -c calculate and append CRC"); - PrintAndLogEx(NORMAL, " -p leave the field on after receive"); - PrintAndLogEx(NORMAL, " -s active signal field ON with select"); - PrintAndLogEx(NORMAL, " -ss active signal field ON with select for SRx ST Microelectronics tags"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " hf 14b raw -s -c -p 0200a40400"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 14b raw [-h] [-r] [-c] [-p] [-s || -ss] <0A 0B 0C ... hex>"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " -h this help"); + PrintAndLogEx(NORMAL, " -r do not read response"); + PrintAndLogEx(NORMAL, " -c calculate and append CRC"); + PrintAndLogEx(NORMAL, " -p leave the field on after receive"); + PrintAndLogEx(NORMAL, " -s active signal field ON with select"); + PrintAndLogEx(NORMAL, " -ss active signal field ON with select for SRx ST Microelectronics tags"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " hf 14b raw -s -c -p 0200a40400"); + return 0; } int usage_hf_14b_sniff(void){ - PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer."); - PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list 14b'"); - PrintAndLogEx(NORMAL, "Usage: hf 14b sniff [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " hf 14b sniff"); - return 0; + PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer."); + PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list 14b'"); + PrintAndLogEx(NORMAL, "Usage: hf 14b sniff [h]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " hf 14b sniff"); + return 0; } int usage_hf_14b_sim(void){ - PrintAndLogEx(NORMAL, "Emulating ISO/IEC 14443 type B tag with 4 UID / PUPI"); - PrintAndLogEx(NORMAL, "Usage: hf 14b sim [h] u "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " u 4byte UID/PUPI"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " hf 14b sim"); - PrintAndLogEx(NORMAL, " hf 14b sim u 11223344"); - return 0; + PrintAndLogEx(NORMAL, "Emulating ISO/IEC 14443 type B tag with 4 UID / PUPI"); + PrintAndLogEx(NORMAL, "Usage: hf 14b sim [h] u "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " u 4byte UID/PUPI"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " hf 14b sim"); + PrintAndLogEx(NORMAL, " hf 14b sim u 11223344"); + return 0; } int usage_hf_14b_read_srx(void){ - PrintAndLogEx(NORMAL, "Usage: hf 14b sriread [h] <1|2>"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " <1|2> 1 = SRIX4K , 2 = SRI512"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " hf 14b sriread 1"); - PrintAndLogEx(NORMAL, " hf 14b sriread 2"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 14b sriread [h] <1|2>"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " <1|2> 1 = SRIX4K , 2 = SRI512"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " hf 14b sriread 1"); + PrintAndLogEx(NORMAL, " hf 14b sriread 2"); + return 0; } int usage_hf_14b_write_srx(void){ - PrintAndLogEx(NORMAL, "Usage: hf 14b [h] sriwrite <1|2> "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h this help"); - PrintAndLogEx(NORMAL, " <1|2> 1 = SRIX4K , 2 = SRI512"); - PrintAndLogEx(NORMAL, " BLOCK number depends on tag, special block == FF"); - PrintAndLogEx(NORMAL, " hex bytes of data to be written"); - PrintAndLogEx(NORMAL, "Example:"); - PrintAndLogEx(NORMAL, " hf 14b sriwrite 1 7F 11223344"); - PrintAndLogEx(NORMAL, " hf 14b sriwrite 1 FF 11223344"); - PrintAndLogEx(NORMAL, " hf 14b sriwrite 2 15 11223344"); - PrintAndLogEx(NORMAL, " hf 14b sriwrite 2 FF 11223344"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 14b [h] sriwrite <1|2> "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h this help"); + PrintAndLogEx(NORMAL, " <1|2> 1 = SRIX4K , 2 = SRI512"); + PrintAndLogEx(NORMAL, " BLOCK number depends on tag, special block == FF"); + PrintAndLogEx(NORMAL, " hex bytes of data to be written"); + PrintAndLogEx(NORMAL, "Example:"); + PrintAndLogEx(NORMAL, " hf 14b sriwrite 1 7F 11223344"); + PrintAndLogEx(NORMAL, " hf 14b sriwrite 1 FF 11223344"); + PrintAndLogEx(NORMAL, " hf 14b sriwrite 2 15 11223344"); + PrintAndLogEx(NORMAL, " hf 14b sriwrite 2 FF 11223344"); + return 0; } int usage_hf_14b_dump(void){ - PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-14443-B tag and save it to file\n" - "\n" - "Usage: hf 14b dump [h] [card memory] \n" - "Options:\n" - "\th this help\n" - "\t[card memory] 1 = SRIX4K (default), 2 = SRI512" - "\tf filename, if no UID will be used as filename\n" - "\n" - "Example:\n" - "\thf 14b dump f\n" - "\thf 14b dump 2 f mydump"); - return 0; + PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-14443-B tag and save it to file\n" + "\n" + "Usage: hf 14b dump [h] [card memory] \n" + "Options:\n" + "\th this help\n" + "\t[card memory] 1 = SRIX4K (default), 2 = SRI512" + "\tf filename, if no UID will be used as filename\n" + "\n" + "Example:\n" + "\thf 14b dump f\n" + "\thf 14b dump 2 f mydump"); + return 0; } /* static void switch_on_field_14b(void) { - UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); + UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); } */ static int switch_off_field_14b(void) { - UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_DISCONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_DISCONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } int CmdHF14BList(const char *Cmd) { - CmdTraceList("14b"); - return 0; + CmdTraceList("14b"); + return 0; } int CmdHF14BSim(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_14b_sim(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_14b_sim(); - uint32_t pupi = 0; - if (cmdp == 'u') { - pupi = param_get32ex(Cmd, 1, 0, 16); - } + uint32_t pupi = 0; + if (cmdp == 'u') { + pupi = param_get32ex(Cmd, 1, 0, 16); + } - UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443B, {pupi, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_SIMULATE_TAG_ISO_14443B, {pupi, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } int CmdHF14BSniff(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_14b_sniff(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_14b_sniff(); - UsbCommand c = {CMD_SNOOP_ISO_14443B, {0, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_SNOOP_ISO_14443B, {0, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } int CmdHF14BCmdRaw (const char *Cmd) { - bool reply = true, power = false, select = false; - char buf[5] = ""; - int i = 0; - uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; - uint16_t datalen = 0; - uint32_t flags = ISO14B_CONNECT; - uint32_t temp = 0; + bool reply = true, power = false, select = false; + char buf[5] = ""; + int i = 0; + uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; + uint16_t datalen = 0; + uint32_t flags = ISO14B_CONNECT; + uint32_t temp = 0; - if ( strlen(Cmd) < 3 ) return usage_hf_14b_raw(); + if ( strlen(Cmd) < 3 ) return usage_hf_14b_raw(); // strip while (*Cmd==' ' || *Cmd=='\t') ++Cmd; @@ -169,8 +169,8 @@ int CmdHF14BCmdRaw (const char *Cmd) { if (Cmd[i]==' ' || Cmd[i]=='\t') { ++i; continue; } if (Cmd[i]=='-') { switch (tolower(Cmd[i+1])) { - case 'h': - return usage_hf_14b_raw(); + case 'h': + return usage_hf_14b_raw(); case 'r': reply = false; break; @@ -178,17 +178,17 @@ int CmdHF14BCmdRaw (const char *Cmd) { flags |= ISO14B_APPEND_CRC; break; case 'p': - power = true; + power = true; + break; + case 's': + select = true; + if (tolower(Cmd[i+2]) == 's') { + flags |= ISO14B_SELECT_SR; + ++i; + } else { + flags |= ISO14B_SELECT_STD; + } break; - case 's': - select = true; - if (tolower(Cmd[i+2]) == 's') { - flags |= ISO14B_SELECT_SR; - ++i; - } else { - flags |= ISO14B_SELECT_STD; - } - break; default: return usage_hf_14b_raw(); } @@ -206,87 +206,87 @@ int CmdHF14BCmdRaw (const char *Cmd) { sscanf(buf,"%x",&temp); data[datalen++] = (uint8_t)(temp & 0xff); *buf=0; - memset(buf, 0x00, sizeof(buf)); + memset(buf, 0x00, sizeof(buf)); } continue; } PrintAndLogEx(WARNING, "unknown parameter '%c'\n", param_getchar(Cmd, i)); - return 0; + return 0; } - if (!power) + if (!power) flags |= ISO14B_DISCONNECT; if (datalen > 0) - flags |= ISO14B_RAW; + flags |= ISO14B_RAW; - // Max buffer is USB_CMD_DATA_SIZE - datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; + // Max buffer is USB_CMD_DATA_SIZE + datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; - UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, 0}}; - memcpy(c.d.asBytes, data, datalen); - clearCommandBuffer(); - SendCommand(&c); + UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, 0}}; + memcpy(c.d.asBytes, data, datalen); + clearCommandBuffer(); + SendCommand(&c); - if (!reply) return 1; + if (!reply) return 1; - bool success = true; - // get back iso14b_card_select_t, don't print it. - if (select) - success = waitCmd14b(false); + bool success = true; + // get back iso14b_card_select_t, don't print it. + if (select) + success = waitCmd14b(false); - // get back response from the raw bytes you sent. - if (success && datalen>0) waitCmd14b(true); + // get back response from the raw bytes you sent. + if (success && datalen>0) waitCmd14b(true); return 1; } static bool get_14b_UID(iso14b_card_select_t *card) { - if (!card) - return false; + if (!card) + return false; - int8_t retry = 3; - UsbCommand resp; - UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}}; + int8_t retry = 3; + UsbCommand resp; + UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}}; - // test for 14b SR - while (retry--) { + // test for 14b SR + while (retry--) { - clearCommandBuffer(); - SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + clearCommandBuffer(); + SendCommand(&c); + if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - uint8_t status = resp.arg[0]; - if ( status == 0) { - memcpy(card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); - return true; - } - } - } // retry + uint8_t status = resp.arg[0]; + if ( status == 0) { + memcpy(card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); + return true; + } + } + } // retry - // test 14b standard - c.arg[0] = ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT; - retry = 3; - while (retry--) { + // test 14b standard + c.arg[0] = ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT; + retry = 3; + while (retry--) { - clearCommandBuffer(); - SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + clearCommandBuffer(); + SendCommand(&c); + if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - uint8_t status = resp.arg[0]; - if ( status == 0) { - memcpy(card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); - return true; - } - } - } // retry + uint8_t status = resp.arg[0]; + if ( status == 0) { + memcpy(card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); + return true; + } + } + } // retry - if ( retry <= 0 ) - PrintAndLogEx(WARNING, "timeout while waiting for reply."); + if ( retry <= 0 ) + PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return false; + return false; } // print full atqb info @@ -296,122 +296,122 @@ static bool get_14b_UID(iso14b_card_select_t *card) { // 5 = max frame size / -4 info // 6 = FWI / Coding options static void print_atqb_resp(uint8_t *data, uint8_t cid){ - //PrintAndLogEx(NORMAL, " UID: %s", sprint_hex(data+1,4)); - PrintAndLogEx(NORMAL, " App Data: %s", sprint_hex(data,4)); - PrintAndLogEx(NORMAL, " Protocol: %s", sprint_hex(data+4,3)); - uint8_t BitRate = data[4]; - if (!BitRate) PrintAndLogEx(NORMAL, " Bit Rate: 106 kbit/s only PICC <-> PCD"); - if (BitRate & 0x10) PrintAndLogEx(NORMAL, " Bit Rate: 212 kbit/s PICC -> PCD supported"); - if (BitRate & 0x20) PrintAndLogEx(NORMAL, " Bit Rate: 424 kbit/s PICC -> PCD supported"); - if (BitRate & 0x40) PrintAndLogEx(NORMAL, " Bit Rate: 847 kbit/s PICC -> PCD supported"); - if (BitRate & 0x01) PrintAndLogEx(NORMAL, " Bit Rate: 212 kbit/s PICC <- PCD supported"); - if (BitRate & 0x02) PrintAndLogEx(NORMAL, " Bit Rate: 424 kbit/s PICC <- PCD supported"); - if (BitRate & 0x04) PrintAndLogEx(NORMAL, " Bit Rate: 847 kbit/s PICC <- PCD supported"); - if (BitRate & 0x80) PrintAndLogEx(NORMAL, " Same bit rate <-> required"); + //PrintAndLogEx(NORMAL, " UID: %s", sprint_hex(data+1,4)); + PrintAndLogEx(NORMAL, " App Data: %s", sprint_hex(data,4)); + PrintAndLogEx(NORMAL, " Protocol: %s", sprint_hex(data+4,3)); + uint8_t BitRate = data[4]; + if (!BitRate) PrintAndLogEx(NORMAL, " Bit Rate: 106 kbit/s only PICC <-> PCD"); + if (BitRate & 0x10) PrintAndLogEx(NORMAL, " Bit Rate: 212 kbit/s PICC -> PCD supported"); + if (BitRate & 0x20) PrintAndLogEx(NORMAL, " Bit Rate: 424 kbit/s PICC -> PCD supported"); + if (BitRate & 0x40) PrintAndLogEx(NORMAL, " Bit Rate: 847 kbit/s PICC -> PCD supported"); + if (BitRate & 0x01) PrintAndLogEx(NORMAL, " Bit Rate: 212 kbit/s PICC <- PCD supported"); + if (BitRate & 0x02) PrintAndLogEx(NORMAL, " Bit Rate: 424 kbit/s PICC <- PCD supported"); + if (BitRate & 0x04) PrintAndLogEx(NORMAL, " Bit Rate: 847 kbit/s PICC <- PCD supported"); + if (BitRate & 0x80) PrintAndLogEx(NORMAL, " Same bit rate <-> required"); - uint16_t maxFrame = data[5] >> 4; - if (maxFrame < 5) maxFrame = 8 * maxFrame + 16; - else if (maxFrame == 5) maxFrame = 64; - else if (maxFrame == 6) maxFrame = 96; - else if (maxFrame == 7) maxFrame = 128; - else if (maxFrame == 8) maxFrame = 256; - else maxFrame = 257; + uint16_t maxFrame = data[5] >> 4; + if (maxFrame < 5) maxFrame = 8 * maxFrame + 16; + else if (maxFrame == 5) maxFrame = 64; + else if (maxFrame == 6) maxFrame = 96; + else if (maxFrame == 7) maxFrame = 128; + else if (maxFrame == 8) maxFrame = 256; + else maxFrame = 257; - PrintAndLogEx(NORMAL, "Max Frame Size: %u%s bytes", maxFrame, (maxFrame == 257) ? "+ RFU" : ""); + PrintAndLogEx(NORMAL, "Max Frame Size: %u%s bytes", maxFrame, (maxFrame == 257) ? "+ RFU" : ""); - uint8_t protocolT = data[5] & 0xF; - PrintAndLogEx(NORMAL, " Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4",(protocolT) ? "" : "not " ); + uint8_t protocolT = data[5] & 0xF; + PrintAndLogEx(NORMAL, " Protocol Type: Protocol is %scompliant with ISO/IEC 14443-4",(protocolT) ? "" : "not " ); - uint8_t fwt = data[6]>>4; - if ( fwt < 16 ){ - uint32_t etus = (32 << fwt); - uint32_t fwt_time = (302 << fwt); - PrintAndLogEx(NORMAL, "Frame Wait Integer: %u - %u ETUs | %u us", fwt, etus, fwt_time); - } else { - PrintAndLogEx(NORMAL, "Frame Wait Integer: %u - RFU", fwt); - } + uint8_t fwt = data[6]>>4; + if ( fwt < 16 ){ + uint32_t etus = (32 << fwt); + uint32_t fwt_time = (302 << fwt); + PrintAndLogEx(NORMAL, "Frame Wait Integer: %u - %u ETUs | %u us", fwt, etus, fwt_time); + } else { + PrintAndLogEx(NORMAL, "Frame Wait Integer: %u - RFU", fwt); + } - PrintAndLogEx(NORMAL, " App Data Code: Application is %s",(data[6]&4) ? "Standard" : "Proprietary"); - PrintAndLogEx(NORMAL, " Frame Options: NAD is %ssupported",(data[6]&2) ? "" : "not "); - PrintAndLogEx(NORMAL, " Frame Options: CID is %ssupported",(data[6]&1) ? "" : "not "); - PrintAndLogEx(NORMAL, "Tag :"); - PrintAndLogEx(NORMAL, " Max Buf Length: %u (MBLI) %s", cid>>4, (cid & 0xF0) ? "" : "chained frames not supported"); - PrintAndLogEx(NORMAL, " CID : %u", cid & 0x0f); - return; + PrintAndLogEx(NORMAL, " App Data Code: Application is %s",(data[6]&4) ? "Standard" : "Proprietary"); + PrintAndLogEx(NORMAL, " Frame Options: NAD is %ssupported",(data[6]&2) ? "" : "not "); + PrintAndLogEx(NORMAL, " Frame Options: CID is %ssupported",(data[6]&1) ? "" : "not "); + PrintAndLogEx(NORMAL, "Tag :"); + PrintAndLogEx(NORMAL, " Max Buf Length: %u (MBLI) %s", cid>>4, (cid & 0xF0) ? "" : "chained frames not supported"); + PrintAndLogEx(NORMAL, " CID : %u", cid & 0x0f); + return; } // get SRx chip model (from UID) // from ST Microelectronics char *get_ST_Chip_Model(uint8_t data){ - static char model[20]; - char *retStr = model; - memset(model,0, sizeof(model)); + static char model[20]; + char *retStr = model; + memset(model,0, sizeof(model)); - switch (data) { - case 0x0: sprintf(retStr, "SRIX4K (Special)"); break; - case 0x2: sprintf(retStr, "SR176"); break; - case 0x3: sprintf(retStr, "SRIX4K"); break; - case 0x4: sprintf(retStr, "SRIX512"); break; - case 0x6: sprintf(retStr, "SRI512"); break; - case 0x7: sprintf(retStr, "SRI4K"); break; - case 0xC: sprintf(retStr, "SRT512"); break; - default : sprintf(retStr, "Unknown"); break; - } - return retStr; + switch (data) { + case 0x0: sprintf(retStr, "SRIX4K (Special)"); break; + case 0x2: sprintf(retStr, "SR176"); break; + case 0x3: sprintf(retStr, "SRIX4K"); break; + case 0x4: sprintf(retStr, "SRIX512"); break; + case 0x6: sprintf(retStr, "SRI512"); break; + case 0x7: sprintf(retStr, "SRI4K"); break; + case 0xC: sprintf(retStr, "SRT512"); break; + default : sprintf(retStr, "Unknown"); break; + } + return retStr; } // REMAKE: int print_ST_Lock_info(uint8_t model){ - // PrintAndLogEx(NORMAL, "Chip Write Protection Bits:"); - // // now interpret the data - // switch (model){ - // case 0x0: //fall through (SRIX4K special) - // case 0x3: //fall through (SRIx4K) - // case 0x7: // (SRI4K) - // //only need data[3] - // blk1 = 9; - // PrintAndLogEx(NORMAL, " raw: %s", sprint_bin(data+3, 1)); - // PrintAndLogEx(NORMAL, " 07/08:%slocked", (data[3] & 1) ? " not " : " " ); - // for (uint8_t i = 1; i<8; i++){ - // PrintAndLogEx(NORMAL, " %02u:%slocked", blk1, (data[3] & (1 << i)) ? " not " : " " ); - // blk1++; - // } - // break; - // case 0x4: //fall through (SRIX512) - // case 0x6: //fall through (SRI512) - // case 0xC: // (SRT512) - // //need data[2] and data[3] - // blk1 = 0; - // PrintAndLogEx(NORMAL, " raw: %s", sprint_bin(data+2, 2)); - // for (uint8_t b=2; b<4; b++){ - // for (uint8_t i=0; i<8; i++){ - // PrintAndLogEx(NORMAL, " %02u:%slocked", blk1, (data[b] & (1 << i)) ? " not " : " " ); - // blk1++; - // } - // } - // break; - // case 0x2: // (SR176) - // //need data[2] - // blk1 = 0; - // PrintAndLogEx(NORMAL, " raw: %s", sprint_bin(data+2, 1)); - // for (uint8_t i = 0; i<8; i++){ - // PrintAndLogEx(NORMAL, " %02u/%02u:%slocked", blk1, blk1+1, (data[2] & (1 << i)) ? " " : " not " ); - // blk1+=2; - // } - // break; - // default: - // return rawClose(); - // } - return 1; + // PrintAndLogEx(NORMAL, "Chip Write Protection Bits:"); + // // now interpret the data + // switch (model){ + // case 0x0: //fall through (SRIX4K special) + // case 0x3: //fall through (SRIx4K) + // case 0x7: // (SRI4K) + // //only need data[3] + // blk1 = 9; + // PrintAndLogEx(NORMAL, " raw: %s", sprint_bin(data+3, 1)); + // PrintAndLogEx(NORMAL, " 07/08:%slocked", (data[3] & 1) ? " not " : " " ); + // for (uint8_t i = 1; i<8; i++){ + // PrintAndLogEx(NORMAL, " %02u:%slocked", blk1, (data[3] & (1 << i)) ? " not " : " " ); + // blk1++; + // } + // break; + // case 0x4: //fall through (SRIX512) + // case 0x6: //fall through (SRI512) + // case 0xC: // (SRT512) + // //need data[2] and data[3] + // blk1 = 0; + // PrintAndLogEx(NORMAL, " raw: %s", sprint_bin(data+2, 2)); + // for (uint8_t b=2; b<4; b++){ + // for (uint8_t i=0; i<8; i++){ + // PrintAndLogEx(NORMAL, " %02u:%slocked", blk1, (data[b] & (1 << i)) ? " not " : " " ); + // blk1++; + // } + // } + // break; + // case 0x2: // (SR176) + // //need data[2] + // blk1 = 0; + // PrintAndLogEx(NORMAL, " raw: %s", sprint_bin(data+2, 1)); + // for (uint8_t i = 0; i<8; i++){ + // PrintAndLogEx(NORMAL, " %02u/%02u:%slocked", blk1, blk1+1, (data[2] & (1 << i)) ? " " : " not " ); + // blk1+=2; + // } + // break; + // default: + // return rawClose(); + // } + return 1; } // print UID info from SRx chips (ST Microelectronics) static void print_st_general_info(uint8_t *data, uint8_t len){ - //uid = first 8 bytes in data - PrintAndLogEx(NORMAL, " UID: %s", sprint_hex(SwapEndian64(data,8,8), len)); - PrintAndLogEx(NORMAL, " MFG: %02X, %s", data[6], getTagInfo(data[6])); - PrintAndLogEx(NORMAL, "Chip: %02X, %s", data[5]>>2, get_ST_Chip_Model(data[5]>>2)); - return; + //uid = first 8 bytes in data + PrintAndLogEx(NORMAL, " UID: %s", sprint_hex(SwapEndian64(data,8,8), len)); + PrintAndLogEx(NORMAL, " MFG: %02X, %s", data[6], getTagInfo(data[6])); + PrintAndLogEx(NORMAL, "Chip: %02X, %s", data[5]>>2, get_ST_Chip_Model(data[5]>>2)); + return; } //05 00 00 = find one tag in field @@ -435,281 +435,281 @@ static void print_st_general_info(uint8_t *data, uint8_t len){ // 14b get and print Full Info (as much as we know) bool HF14B_Std_Info(bool verbose){ - bool isSuccess = false; + bool isSuccess = false; - // 14b get and print UID only (general info) - UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; + // 14b get and print UID only (general info) + UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); - switch_off_field_14b(); - return false; + if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); + switch_off_field_14b(); + return false; } - iso14b_card_select_t card; - memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); + iso14b_card_select_t card; + memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); - uint64_t status = resp.arg[0]; + uint64_t status = resp.arg[0]; - switch( status ){ - case 0: - PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLogEx(NORMAL, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); - PrintAndLogEx(NORMAL, " CHIPID : %02X", card.chipid); - print_atqb_resp(card.atqb, card.cid); - isSuccess = true; - break; - case 2: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); - break; - case 3: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); - break; - default: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed"); - break; - } + switch( status ){ + case 0: + PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); + PrintAndLogEx(NORMAL, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); + PrintAndLogEx(NORMAL, " CHIPID : %02X", card.chipid); + print_atqb_resp(card.atqb, card.cid); + isSuccess = true; + break; + case 2: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); + break; + case 3: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); + break; + default: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed"); + break; + } - return isSuccess; + return isSuccess; } // SRx get and print full info (needs more info...) bool HF14B_ST_Info(bool verbose){ - UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; + UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); - return false; + if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); + return false; } - iso14b_card_select_t card; - memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); + iso14b_card_select_t card; + memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); - uint64_t status = resp.arg[0]; - if ( status > 0 ) - return false; + uint64_t status = resp.arg[0]; + if ( status > 0 ) + return false; - print_st_general_info(card.uid, card.uidlen); + print_st_general_info(card.uid, card.uidlen); - //add locking bit information here. uint8_t data[16] = {0x00}; - // uint8_t datalen = 2; - // uint8_t resplen; - // uint8_t blk1; - // data[0] = 0x08; + //add locking bit information here. uint8_t data[16] = {0x00}; + // uint8_t datalen = 2; + // uint8_t resplen; + // uint8_t blk1; + // data[0] = 0x08; - // - // if (model == 0x2) { //SR176 has special command: - // data[1] = 0xf; - // resplen = 4; - // } else { - // data[1] = 0xff; - // resplen = 6; - // } + // + // if (model == 0x2) { //SR176 has special command: + // data[1] = 0xf; + // resplen = 4; + // } else { + // data[1] = 0xff; + // resplen = 6; + // } - // //std read cmd - // if (HF14BCmdRaw(true, true, data, &datalen, false)==0) - // return rawClose(); + // //std read cmd + // if (HF14BCmdRaw(true, true, data, &datalen, false)==0) + // return rawClose(); - // if (datalen != resplen || !crc) return rawClose(); - //print_ST_Lock_info(data[5]>>2); - return true; + // if (datalen != resplen || !crc) return rawClose(); + //print_ST_Lock_info(data[5]>>2); + return true; } // get and print all info known about any known 14b tag bool HF14BInfo(bool verbose){ - // try std 14b (atqb) - if (HF14B_Std_Info(verbose)) return true; + // try std 14b (atqb) + if (HF14B_Std_Info(verbose)) return true; - // try ST 14b - if (HF14B_ST_Info(verbose)) return true; + // try ST 14b + if (HF14B_ST_Info(verbose)) return true; - // try unknown 14b read commands (to be identified later) - // could be read of calypso, CEPAS, moneo, or pico pass. - if (verbose) PrintAndLogEx(FAILED, "no 14443-B tag found"); - return false; + // try unknown 14b read commands (to be identified later) + // could be read of calypso, CEPAS, moneo, or pico pass. + if (verbose) PrintAndLogEx(FAILED, "no 14443-B tag found"); + return false; } // menu command to get and print all info known about any known 14b tag int CmdHF14Binfo(const char *Cmd){ - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_14b_info(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_14b_info(); - bool verbose = !(cmdp == 's'); - return HF14BInfo(verbose); + bool verbose = !(cmdp == 's'); + return HF14BInfo(verbose); } bool HF14B_ST_Reader(bool verbose){ - bool isSuccess = false; + bool isSuccess = false; - // SRx get and print general info about SRx chip from UID - UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); - return false; + // SRx get and print general info about SRx chip from UID + UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_SR | ISO14B_DISCONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); + return false; } - iso14b_card_select_t card; - memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); + iso14b_card_select_t card; + memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); - uint64_t status = resp.arg[0]; + uint64_t status = resp.arg[0]; - switch( status ){ - case 0: - print_st_general_info(card.uid, card.uidlen); - isSuccess = true; - break; - case 1: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 random chip id fail"); - break; - case 2: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); - break; - case 3: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); - break; - default: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select SRx failed"); - break; - } - return isSuccess; + switch( status ){ + case 0: + print_st_general_info(card.uid, card.uidlen); + isSuccess = true; + break; + case 1: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 random chip id fail"); + break; + case 2: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); + break; + case 3: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); + break; + default: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select SRx failed"); + break; + } + return isSuccess; } bool HF14B_Std_Reader(bool verbose){ - bool isSuccess = false; + bool isSuccess = false; - // 14b get and print UID only (general info) - UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; + // 14b get and print UID only (general info) + UsbCommand c = {CMD_ISO_14443B_COMMAND, {ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_DISCONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); - return false; + if (!WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { + if (verbose) PrintAndLogEx(WARNING, "command execution timeout"); + return false; } - iso14b_card_select_t card; - memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); + iso14b_card_select_t card; + memcpy(&card, (iso14b_card_select_t *)resp.d.asBytes, sizeof(iso14b_card_select_t)); - uint64_t status = resp.arg[0]; + uint64_t status = resp.arg[0]; - switch( status ){ - case 0: - PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); - PrintAndLogEx(NORMAL, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); - PrintAndLogEx(NORMAL, " CHIPID : %02X", card.chipid); - print_atqb_resp(card.atqb, card.cid); - isSuccess = true; - break; - case 2: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); - break; - case 3: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); - break; - default: - if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed"); - break; - } - return isSuccess; + switch( status ){ + case 0: + PrintAndLogEx(NORMAL, " UID : %s", sprint_hex(card.uid, card.uidlen)); + PrintAndLogEx(NORMAL, " ATQB : %s", sprint_hex(card.atqb, sizeof(card.atqb))); + PrintAndLogEx(NORMAL, " CHIPID : %02X", card.chipid); + print_atqb_resp(card.atqb, card.cid); + isSuccess = true; + break; + case 2: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 ATTRIB fail"); + break; + case 3: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-3 CRC fail"); + break; + default: + if (verbose) PrintAndLogEx(FAILED, "ISO 14443-b card select failed"); + break; + } + return isSuccess; } // test for other 14b type tags (mimic another reader - don't have tags to identify) bool HF14B_Other_Reader(){ - // uint8_t data[] = {0x00, 0x0b, 0x3f, 0x80}; - // uint8_t datalen = 4; + // uint8_t data[] = {0x00, 0x0b, 0x3f, 0x80}; + // uint8_t datalen = 4; - // // 14b get and print UID only (general info) - // uint32_t flags = ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_RAW | ISO14B_APPEND_CRC; + // // 14b get and print UID only (general info) + // uint32_t flags = ISO14B_CONNECT | ISO14B_SELECT_STD | ISO14B_RAW | ISO14B_APPEND_CRC; - // UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, 0}}; - // memcpy(c.d.asBytes, data, datalen); + // UsbCommand c = {CMD_ISO_14443B_COMMAND, {flags, datalen, 0}}; + // memcpy(c.d.asBytes, data, datalen); - // clearCommandBuffer(); - // SendCommand(&c); - // UsbCommand resp; - // WaitForResponse(CMD_ACK,&resp); + // clearCommandBuffer(); + // SendCommand(&c); + // UsbCommand resp; + // WaitForResponse(CMD_ACK,&resp); - // if (datalen > 2 ) { - // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); - // PrintAndLogEx(NORMAL, "unknown tag type answered to a 0x000b3f80 command ans:"); - // //PrintAndLogEx(NORMAL, "%s", sprint_hex(data, datalen)); - // rawclose(); - // return true; - // } + // if (datalen > 2 ) { + // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); + // PrintAndLogEx(NORMAL, "unknown tag type answered to a 0x000b3f80 command ans:"); + // //PrintAndLogEx(NORMAL, "%s", sprint_hex(data, datalen)); + // rawclose(); + // return true; + // } - // c.arg1 = 1; - // c.d.asBytes[0] = ISO14443B_AUTHENTICATE; - // clearCommandBuffer(); - // SendCommand(&c); - // UsbCommand resp; - // WaitForResponse(CMD_ACK, &resp); + // c.arg1 = 1; + // c.d.asBytes[0] = ISO14443B_AUTHENTICATE; + // clearCommandBuffer(); + // SendCommand(&c); + // UsbCommand resp; + // WaitForResponse(CMD_ACK, &resp); - // if (datalen > 0) { - // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); - // PrintAndLogEx(NORMAL, "Unknown tag type answered to a 0x0A command ans:"); - // // PrintAndLogEx(NORMAL, "%s", sprint_hex(data, datalen)); - // rawClose(); - // return true; - // } + // if (datalen > 0) { + // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); + // PrintAndLogEx(NORMAL, "Unknown tag type answered to a 0x0A command ans:"); + // // PrintAndLogEx(NORMAL, "%s", sprint_hex(data, datalen)); + // rawClose(); + // return true; + // } - // c.arg1 = 1; - // c.d.asBytes[0] = ISO14443B_RESET; - // clearCommandBuffer(); - // SendCommand(&c); - // UsbCommand resp; - // WaitForResponse(CMD_ACK, &resp); + // c.arg1 = 1; + // c.d.asBytes[0] = ISO14443B_RESET; + // clearCommandBuffer(); + // SendCommand(&c); + // UsbCommand resp; + // WaitForResponse(CMD_ACK, &resp); - // if (datalen > 0) { - // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); - // PrintAndLogEx(NORMAL, "Unknown tag type answered to a 0x0C command ans:"); - // PrintAndLogEx(NORMAL, "%s", sprint_hex(data, datalen)); - // rawClose(); - // return true; - // } + // if (datalen > 0) { + // PrintAndLogEx(NORMAL, "\n14443-3b tag found:"); + // PrintAndLogEx(NORMAL, "Unknown tag type answered to a 0x0C command ans:"); + // PrintAndLogEx(NORMAL, "%s", sprint_hex(data, datalen)); + // rawClose(); + // return true; + // } - // rawClose(); - return false; + // rawClose(); + return false; } // get and print general info about all known 14b chips bool HF14BReader(bool verbose){ - // try std 14b (atqb) - if (HF14B_Std_Reader(verbose)) return true; + // try std 14b (atqb) + if (HF14B_Std_Reader(verbose)) return true; - // try ST Microelectronics 14b - if (HF14B_ST_Reader(verbose)) return true; + // try ST Microelectronics 14b + if (HF14B_ST_Reader(verbose)) return true; - // try unknown 14b read commands (to be identified later) - // could be read of calypso, CEPAS, moneo, or pico pass. - if (HF14B_Other_Reader()) return true; + // try unknown 14b read commands (to be identified later) + // could be read of calypso, CEPAS, moneo, or pico pass. + if (HF14B_Other_Reader()) return true; - if (verbose) PrintAndLogEx(FAILED, "no 14443-B tag found"); - return false; + if (verbose) PrintAndLogEx(FAILED, "no 14443-B tag found"); + return false; } // menu command to get and print general info about all known 14b chips int CmdHF14BReader(const char *Cmd){ - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_hf_14b_reader(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_hf_14b_reader(); - bool verbose = !(cmdp == 's'); - return HF14BReader(verbose); + bool verbose = !(cmdp == 's'); + return HF14BReader(verbose); } /* New command to read the contents of a SRI512|SRIX4K tag @@ -717,16 +717,16 @@ int CmdHF14BReader(const char *Cmd){ * this command just dumps the contents of the memory/ */ int CmdHF14BReadSri(const char *Cmd){ - char cmdp = tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_14b_read_srx(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_14b_read_srx(); - uint8_t tagtype = param_get8(Cmd, 0); - uint8_t blocks = (tagtype == 1) ? 0x7F : 0x0F; + uint8_t tagtype = param_get8(Cmd, 0); + uint8_t blocks = (tagtype == 1) ? 0x7F : 0x0F; - UsbCommand c = {CMD_READ_SRI_TAG, {blocks, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_READ_SRI_TAG, {blocks, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } // New command to write a SRI512/SRIX4K tag. int CmdHF14BWriteSri(const char *Cmd){ @@ -740,215 +740,215 @@ int CmdHF14BWriteSri(const char *Cmd){ * Special block FF = otp_lock_reg block. * Data len 4 bytes- */ - char cmdp = tolower(param_getchar(Cmd, 0)); - uint8_t blockno = -1; - uint8_t data[4] = {0x00}; - bool isSrix4k = true; - char str[30]; - memset(str, 0x00, sizeof(str)); + char cmdp = tolower(param_getchar(Cmd, 0)); + uint8_t blockno = -1; + uint8_t data[4] = {0x00}; + bool isSrix4k = true; + char str[30]; + memset(str, 0x00, sizeof(str)); - if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_14b_write_srx(); + if (strlen(Cmd) < 1 || cmdp == 'h') return usage_hf_14b_write_srx(); - if ( cmdp == '2' ) - isSrix4k = false; + if ( cmdp == '2' ) + isSrix4k = false; - //blockno = param_get8(Cmd, 1); + //blockno = param_get8(Cmd, 1); - if ( param_gethex(Cmd, 1, &blockno, 2) ) { - PrintAndLogEx(WARNING, "block number must include 2 HEX symbols"); - return 0; - } + if ( param_gethex(Cmd, 1, &blockno, 2) ) { + PrintAndLogEx(WARNING, "block number must include 2 HEX symbols"); + return 0; + } - if ( isSrix4k ){ - if ( blockno > 0x7f && blockno != 0xff ){ - PrintAndLogEx(FAILED, "block number out of range"); - return 0; - } - } else { - if ( blockno > 0x0f && blockno != 0xff ){ - PrintAndLogEx(FAILED, "block number out of range"); - return 0; - } - } + if ( isSrix4k ){ + if ( blockno > 0x7f && blockno != 0xff ){ + PrintAndLogEx(FAILED, "block number out of range"); + return 0; + } + } else { + if ( blockno > 0x0f && blockno != 0xff ){ + PrintAndLogEx(FAILED, "block number out of range"); + return 0; + } + } - if (param_gethex(Cmd, 2, data, 8)) { - PrintAndLogEx(WARNING, "data must include 8 HEX symbols"); - return 0; - } + if (param_gethex(Cmd, 2, data, 8)) { + PrintAndLogEx(WARNING, "data must include 8 HEX symbols"); + return 0; + } - if ( blockno == 0xff) { - PrintAndLogEx(SUCCESS, "[%s] Write special block %02X [ %s ]", - (isSrix4k) ? "SRIX4K":"SRI512", - blockno, - sprint_hex(data,4) - ); - } else { - PrintAndLogEx(SUCCESS, "[%s] Write block %02X [ %s ]", - (isSrix4k) ? "SRIX4K":"SRI512", - blockno, - sprint_hex(data,4) - ); - } + if ( blockno == 0xff) { + PrintAndLogEx(SUCCESS, "[%s] Write special block %02X [ %s ]", + (isSrix4k) ? "SRIX4K":"SRI512", + blockno, + sprint_hex(data,4) + ); + } else { + PrintAndLogEx(SUCCESS, "[%s] Write block %02X [ %s ]", + (isSrix4k) ? "SRIX4K":"SRI512", + blockno, + sprint_hex(data,4) + ); + } - sprintf(str, "-ss -c %02x %02x %02x %02x %02x %02x", ISO14443B_WRITE_BLK, blockno, data[0], data[1], data[2], data[3]); - CmdHF14BCmdRaw(str); - return 0; + sprintf(str, "-ss -c %02x %02x %02x %02x %02x %02x", ISO14443B_WRITE_BLK, blockno, data[0], data[1], data[2], data[3]); + CmdHF14BCmdRaw(str); + return 0; } // need to write to file int CmdHF14BDump(const char*Cmd) { - uint8_t fileNameLen = 0; - char filename[FILE_PATH_SIZE] = {0}; - char * fptr = filename; - bool errors = false; - uint8_t cmdp = 0, cardtype = 1; - uint16_t cardsize = 0; - uint8_t blocks = 0; - iso14b_card_select_t card; + uint8_t fileNameLen = 0; + char filename[FILE_PATH_SIZE] = {0}; + char * fptr = filename; + bool errors = false; + uint8_t cmdp = 0, cardtype = 1; + uint16_t cardsize = 0; + uint8_t blocks = 0; + iso14b_card_select_t card; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_hf_14b_dump(); - case 'f': - fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); - cmdp += 2; - break; - default: - if (cmdp == 0) { - cardtype = param_get8ex(Cmd, cmdp, 1, 10); - cmdp++; - } else { - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - } + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_hf_14b_dump(); + case 'f': + fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); + cmdp += 2; + break; + default: + if (cmdp == 0) { + cardtype = param_get8ex(Cmd, cmdp, 1, 10); + cmdp++; + } else { + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + } - //Validations - if (errors) return usage_hf_14b_dump(); + //Validations + if (errors) return usage_hf_14b_dump(); - switch (cardtype){ - case 2: - cardsize = (512/8) + 4; - blocks = 0x0F; - break; - case 1: - default: - cardsize = (4096/8) + 4; - blocks = 0x7F; - break; - } + switch (cardtype){ + case 2: + cardsize = (512/8) + 4; + blocks = 0x0F; + break; + case 1: + default: + cardsize = (4096/8) + 4; + blocks = 0x7F; + break; + } - if (!get_14b_UID(&card)) { - PrintAndLogEx(WARNING, "No tag found."); - return 1; - } + if (!get_14b_UID(&card)) { + PrintAndLogEx(WARNING, "No tag found."); + return 1; + } - if (fileNameLen < 1) { - PrintAndLogEx(INFO, "Using UID as filename"); - fptr += sprintf(fptr, "hf-14b-"); - FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen); - } + if (fileNameLen < 1) { + PrintAndLogEx(INFO, "Using UID as filename"); + fptr += sprintf(fptr, "hf-14b-"); + FillFileNameByUID(fptr, card.uid, "-dump", card.uidlen); + } - // detect blocksize from card :) - PrintAndLogEx(NORMAL, "Reading memory from tag UID %s", sprint_hex(card.uid, card.uidlen)); + // detect blocksize from card :) + PrintAndLogEx(NORMAL, "Reading memory from tag UID %s", sprint_hex(card.uid, card.uidlen)); - uint8_t data[cardsize]; - memset(data, 0, sizeof(data)); + uint8_t data[cardsize]; + memset(data, 0, sizeof(data)); - int blocknum = 0; - uint8_t *recv = NULL; + int blocknum = 0; + uint8_t *recv = NULL; - UsbCommand resp; - UsbCommand c = {CMD_ISO_14443B_COMMAND, { ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); + UsbCommand resp; + UsbCommand c = {CMD_ISO_14443B_COMMAND, { ISO14B_CONNECT | ISO14B_SELECT_SR, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); - //select - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - if (resp.arg[0]) { - PrintAndLogEx(INFO, "failed to select %d | %d", resp.arg[0], resp.arg[1]); - goto out; - } - } + //select + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (resp.arg[0]) { + PrintAndLogEx(INFO, "failed to select %d | %d", resp.arg[0], resp.arg[1]); + goto out; + } + } - c.arg[0] = ISO14B_APPEND_CRC | ISO14B_RAW; - c.arg[1] = 2; + c.arg[0] = ISO14B_APPEND_CRC | ISO14B_RAW; + c.arg[1] = 2; - uint8_t *req = c.d.asBytes; - req[0] = ISO14443B_READ_BLK; + uint8_t *req = c.d.asBytes; + req[0] = ISO14443B_READ_BLK; - for (int retry = 0; retry < 5; retry++) { + for (int retry = 0; retry < 5; retry++) { - req[1] = blocknum; + req[1] = blocknum; - clearCommandBuffer(); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - uint8_t status = resp.arg[0] & 0xFF; - if ( status > 0 ) { - continue; - } + uint8_t status = resp.arg[0] & 0xFF; + if ( status > 0 ) { + continue; + } - uint16_t len = (resp.arg[1] & 0xFFFF); - recv = resp.d.asBytes; + uint16_t len = (resp.arg[1] & 0xFFFF); + recv = resp.d.asBytes; - if ( !check_crc(CRC_14443_B, recv, len) ) { - PrintAndLogEx(FAILED, "crc fail, retrying one more time"); - continue; - } + if ( !check_crc(CRC_14443_B, recv, len) ) { + PrintAndLogEx(FAILED, "crc fail, retrying one more time"); + continue; + } - memcpy(data + (blocknum * 4), resp.d.asBytes, 4); + memcpy(data + (blocknum * 4), resp.d.asBytes, 4); - if ( blocknum == 0xFF) { - //last read. - break; - } + if ( blocknum == 0xFF) { + //last read. + break; + } - retry = 0; - blocknum++; - if ( blocknum > blocks ) { - // read config block - blocknum = 0xFF; - } + retry = 0; + blocknum++; + if ( blocknum > blocks ) { + // read config block + blocknum = 0xFF; + } - printf("."); fflush(stdout); - } - } + printf("."); fflush(stdout); + } + } - if ( blocknum != 0xFF) { - PrintAndLogEx(NORMAL, "\n Dump failed"); - goto out; - } + if ( blocknum != 0xFF) { + PrintAndLogEx(NORMAL, "\n Dump failed"); + goto out; + } - PrintAndLogEx(NORMAL, "\n"); - PrintAndLogEx(NORMAL, "block# | data | ascii"); - PrintAndLogEx(NORMAL, "---------+--------------+----------"); + PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(NORMAL, "block# | data | ascii"); + PrintAndLogEx(NORMAL, "---------+--------------+----------"); - for (int i = 0; i <= blocks; i++) { - PrintAndLogEx(NORMAL, - "%3d/0x%02X | %s | %s", - i, - i, - sprint_hex(data + (i*4), 4 ), - sprint_ascii(data + (i*4), 4) - ); - } + for (int i = 0; i <= blocks; i++) { + PrintAndLogEx(NORMAL, + "%3d/0x%02X | %s | %s", + i, + i, + sprint_hex(data + (i*4), 4 ), + sprint_ascii(data + (i*4), 4) + ); + } - PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(NORMAL, "\n"); - size_t datalen = (blocks+1) * 4; - saveFileEML(filename, "eml", data, datalen, 4); - saveFile(filename, "bin", data, datalen); + size_t datalen = (blocks+1) * 4; + saveFileEML(filename, "eml", data, datalen, 4); + saveFile(filename, "bin", data, datalen); out: - return switch_off_field_14b(); + return switch_off_field_14b(); } uint32_t srix4kEncode(uint32_t value) { @@ -956,162 +956,162 @@ uint32_t srix4kEncode(uint32_t value) { // vv = value // pp = position // vv vv vv pp -4 bytes : 00 1A 20 01 +4 bytes : 00 1A 20 01 */ - // only the lower crumbs. - uint8_t block = (value & 0xFF); - uint8_t i = 0; - uint8_t valuebytes[] = {0,0,0}; + // only the lower crumbs. + uint8_t block = (value & 0xFF); + uint8_t i = 0; + uint8_t valuebytes[] = {0,0,0}; - num_to_bytes(value, 3, valuebytes); + num_to_bytes(value, 3, valuebytes); - // Scrambled part - // Crumb swapping of value. - uint8_t temp[] = {0,0}; - temp[0] = (CRUMB(value, 22) << 4 | CRUMB(value, 14 ) << 2 | CRUMB(value, 6)) << 4; - temp[0] |= CRUMB(value, 20) << 4 | CRUMB(value, 12 ) << 2 | CRUMB(value, 4); - temp[1] = (CRUMB(value, 18) << 4 | CRUMB(value, 10 ) << 2 | CRUMB(value, 2)) << 4; - temp[1] |= CRUMB(value, 16) << 4 | CRUMB(value, 8 ) << 2 | CRUMB(value, 0); + // Scrambled part + // Crumb swapping of value. + uint8_t temp[] = {0,0}; + temp[0] = (CRUMB(value, 22) << 4 | CRUMB(value, 14 ) << 2 | CRUMB(value, 6)) << 4; + temp[0] |= CRUMB(value, 20) << 4 | CRUMB(value, 12 ) << 2 | CRUMB(value, 4); + temp[1] = (CRUMB(value, 18) << 4 | CRUMB(value, 10 ) << 2 | CRUMB(value, 2)) << 4; + temp[1] |= CRUMB(value, 16) << 4 | CRUMB(value, 8 ) << 2 | CRUMB(value, 0); - // chksum part - uint32_t chksum = 0xFF - block; + // chksum part + uint32_t chksum = 0xFF - block; - // chksum is reduced by each nibbles of value. - for (i = 0; i < 3; ++i){ - chksum -= NIBBLE_HIGH(valuebytes[i]); - chksum -= NIBBLE_LOW(valuebytes[i]); - } - - // base4 conversion and left shift twice - i = 3; - uint8_t base4[] = {0,0,0,0}; - while( chksum !=0 ){ - base4[i--] = (chksum % 4 << 2); - chksum /= 4; + // chksum is reduced by each nibbles of value. + for (i = 0; i < 3; ++i){ + chksum -= NIBBLE_HIGH(valuebytes[i]); + chksum -= NIBBLE_LOW(valuebytes[i]); } - // merge scambled and chksum parts - uint32_t encvalue = - ( NIBBLE_LOW ( base4[0]) << 28 ) | - ( NIBBLE_HIGH( temp[0]) << 24 ) | + // base4 conversion and left shift twice + i = 3; + uint8_t base4[] = {0,0,0,0}; + while( chksum !=0 ){ + base4[i--] = (chksum % 4 << 2); + chksum /= 4; + } - ( NIBBLE_LOW ( base4[1]) << 20 ) | - ( NIBBLE_LOW ( temp[0]) << 16 ) | + // merge scambled and chksum parts + uint32_t encvalue = + ( NIBBLE_LOW ( base4[0]) << 28 ) | + ( NIBBLE_HIGH( temp[0]) << 24 ) | - ( NIBBLE_LOW ( base4[2]) << 12 ) | - ( NIBBLE_HIGH( temp[1]) << 8 ) | + ( NIBBLE_LOW ( base4[1]) << 20 ) | + ( NIBBLE_LOW ( temp[0]) << 16 ) | - ( NIBBLE_LOW ( base4[3]) << 4 ) | - NIBBLE_LOW ( temp[1] ); + ( NIBBLE_LOW ( base4[2]) << 12 ) | + ( NIBBLE_HIGH( temp[1]) << 8 ) | - PrintAndLogEx(NORMAL, "ICE encoded | %08X -> %08X", value, encvalue); - return encvalue; + ( NIBBLE_LOW ( base4[3]) << 4 ) | + NIBBLE_LOW ( temp[1] ); + + PrintAndLogEx(NORMAL, "ICE encoded | %08X -> %08X", value, encvalue); + return encvalue; } uint32_t srix4kDecode(uint32_t value) { - switch(value) { - case 0xC04F42C5: return 0x003139; - case 0xC1484807: return 0x002943; - case 0xC0C60848: return 0x001A20; - } - return 0; + switch(value) { + case 0xC04F42C5: return 0x003139; + case 0xC1484807: return 0x002943; + case 0xC0C60848: return 0x001A20; + } + return 0; } uint32_t srix4kDecodeCounter(uint32_t num) { - uint32_t value = ~num; - ++value; - return value; + uint32_t value = ~num; + ++value; + return value; } uint32_t srix4kGetMagicbytes( uint64_t uid, uint32_t block6, uint32_t block18, uint32_t block19 ){ #define MASK 0xFFFFFFFF; - uint32_t uid32 = uid & MASK; - uint32_t counter = srix4kDecodeCounter(block6); - uint32_t decodedBlock18 = srix4kDecode(block18); - uint32_t decodedBlock19 = srix4kDecode(block19); - uint32_t doubleBlock = (decodedBlock18 << 16 | decodedBlock19) + 1; + uint32_t uid32 = uid & MASK; + uint32_t counter = srix4kDecodeCounter(block6); + uint32_t decodedBlock18 = srix4kDecode(block18); + uint32_t decodedBlock19 = srix4kDecode(block19); + uint32_t doubleBlock = (decodedBlock18 << 16 | decodedBlock19) + 1; - uint32_t result = (uid32 * doubleBlock * counter) & MASK; - PrintAndLogEx(SUCCESS, "Magic bytes | %08X", result); - return result; + uint32_t result = (uid32 * doubleBlock * counter) & MASK; + PrintAndLogEx(SUCCESS, "Magic bytes | %08X", result); + return result; } int srix4kValid(const char *Cmd){ - uint64_t uid = 0xD00202501A4532F9; - uint32_t block6 = 0xFFFFFFFF; - uint32_t block18 = 0xC04F42C5; - uint32_t block19 = 0xC1484807; - uint32_t block21 = 0xD1BCABA4; + uint64_t uid = 0xD00202501A4532F9; + uint32_t block6 = 0xFFFFFFFF; + uint32_t block18 = 0xC04F42C5; + uint32_t block19 = 0xC1484807; + uint32_t block21 = 0xD1BCABA4; - uint32_t test_b18 = 0x00313918; - uint32_t test_b18_enc = srix4kEncode(test_b18); - //uint32_t test_b18_dec = srix4kDecode(test_b18_enc); - PrintAndLogEx(SUCCESS, "ENCODE & CHECKSUM | %08X -> %08X (%s)", test_b18, test_b18_enc , ""); + uint32_t test_b18 = 0x00313918; + uint32_t test_b18_enc = srix4kEncode(test_b18); + //uint32_t test_b18_dec = srix4kDecode(test_b18_enc); + PrintAndLogEx(SUCCESS, "ENCODE & CHECKSUM | %08X -> %08X (%s)", test_b18, test_b18_enc , ""); - uint32_t magic = srix4kGetMagicbytes(uid, block6, block18, block19); - PrintAndLogEx(SUCCESS, "BLOCK 21 | %08X -> %08X (no XOR)", block21, magic ^ block21); - return 0; + uint32_t magic = srix4kGetMagicbytes(uid, block6, block18, block19); + PrintAndLogEx(SUCCESS, "BLOCK 21 | %08X -> %08X (no XOR)", block21, magic ^ block21); + return 0; } bool waitCmd14b(bool verbose) { - bool crc = false; - uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; - uint8_t status = 0; - uint16_t len = 0; + bool crc = false; + uint8_t data[USB_CMD_DATA_SIZE] = {0x00}; + uint8_t status = 0; + uint16_t len = 0; UsbCommand resp; if (WaitForResponseTimeout(CMD_ACK, &resp, TIMEOUT)) { - status = (resp.arg[0] & 0xFF); - if ( status > 0 ) return false; + status = (resp.arg[0] & 0xFF); + if ( status > 0 ) return false; - len = (resp.arg[1] & 0xFFFF); + len = (resp.arg[1] & 0xFFFF); - memcpy(data, resp.d.asBytes, len); + memcpy(data, resp.d.asBytes, len); - if (verbose) { - if ( len >= 3 ) { - crc = check_crc(CRC_14443_B, data, len); + if (verbose) { + if ( len >= 3 ) { + crc = check_crc(CRC_14443_B, data, len); - PrintAndLogEx(NORMAL, "[LEN %u] %s[%02X %02X] %s", - len, - sprint_hex(data, len-2), - data[len-2], - data[len-1], - (crc) ? "OK" : "FAIL" - ); - } else { - PrintAndLogEx(NORMAL, "[LEN %u] %s", len, sprint_hex(data, len) ); - } - } - return true; + PrintAndLogEx(NORMAL, "[LEN %u] %s[%02X %02X] %s", + len, + sprint_hex(data, len-2), + data[len-2], + data[len-1], + (crc) ? "OK" : "FAIL" + ); + } else { + PrintAndLogEx(NORMAL, "[LEN %u] %s", len, sprint_hex(data, len) ); + } + } + return true; } else { PrintAndLogEx(WARNING, "command execution timeout"); - return false; + return false; } } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"dump", CmdHF14BDump, 0, "Read all memory pages of an ISO14443-B tag, save to file"}, - {"info", CmdHF14Binfo, 0, "Tag information"}, - {"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443B history"}, - {"raw", CmdHF14BCmdRaw, 0, "Send raw hex data to tag"}, - {"reader", CmdHF14BReader, 0, "Act as a 14443B reader to identify a tag"}, - {"sim", CmdHF14BSim, 0, "Fake ISO 14443B tag"}, - {"sniff", CmdHF14BSniff, 0, "Eavesdrop ISO 14443B"}, - {"sriread", CmdHF14BReadSri, 0, "Read contents of a SRI512 | SRIX4K tag"}, - {"sriwrite", CmdHF14BWriteSri, 0, "Write data to a SRI512 | SRIX4K tag"}, - //{"valid", srix4kValid, 1, "srix4k checksum test"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"dump", CmdHF14BDump, 0, "Read all memory pages of an ISO14443-B tag, save to file"}, + {"info", CmdHF14Binfo, 0, "Tag information"}, + {"list", CmdHF14BList, 0, "[Deprecated] List ISO 14443B history"}, + {"raw", CmdHF14BCmdRaw, 0, "Send raw hex data to tag"}, + {"reader", CmdHF14BReader, 0, "Act as a 14443B reader to identify a tag"}, + {"sim", CmdHF14BSim, 0, "Fake ISO 14443B tag"}, + {"sniff", CmdHF14BSniff, 0, "Eavesdrop ISO 14443B"}, + {"sriread", CmdHF14BReadSri, 0, "Read contents of a SRI512 | SRIX4K tag"}, + {"sriwrite", CmdHF14BWriteSri, 0, "Write data to a SRI512 | SRIX4K tag"}, + //{"valid", srix4kValid, 1, "srix4k checksum test"}, + {NULL, NULL, 0, NULL} }; int CmdHF14B(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } diff --git a/client/cmdhf14b.h b/client/cmdhf14b.h index 74b279620..f77658c19 100644 --- a/client/cmdhf14b.h +++ b/client/cmdhf14b.h @@ -26,8 +26,8 @@ #include "cmdhf.h" #include "prng.h" #include "mbedtls/sha1.h" -#include "mifare.h" // structs/enum for ISO14B -#include "protocols.h" // definitions of ISO14B protocol +#include "mifare.h" // structs/enum for ISO14B +#include "protocols.h" // definitions of ISO14B protocol int usage_hf_14b_info(void); int usage_hf_14b_reader(void); diff --git a/client/cmdhf15.c b/client/cmdhf15.c index bdec7c339..9164ac70e 100644 --- a/client/cmdhf15.c +++ b/client/cmdhf15.c @@ -24,313 +24,313 @@ // variant, but offers the possibility to analyze the waveforms directly. #include "cmdhf15.h" -#define FrameSOF Iso15693FrameSOF -#define Logic0 Iso15693Logic0 -#define Logic1 Iso15693Logic1 -#define FrameEOF Iso15693FrameEOF +#define FrameSOF Iso15693FrameSOF +#define Logic0 Iso15693Logic0 +#define Logic1 Iso15693Logic1 +#define FrameEOF Iso15693FrameEOF -#define Crc(data, len) crc(CRC_15693, (data), (len)) -#define CheckCrc(data, len) check_crc(CRC_15693, (data), (len)) -#define AddCrc(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1) +#define Crc(data, len) crc(CRC_15693, (data), (len)) +#define CheckCrc(data, len) check_crc(CRC_15693, (data), (len)) +#define AddCrc(data, len) compute_crc(CRC_15693, (data), (len), (data)+(len), (data)+(len)+1) -#define sprintUID(target, uid) Iso15693sprintUID((target), (uid)) +#define sprintUID(target, uid) Iso15693sprintUID((target), (uid)) // structure and database for uid -> tagtype lookups typedef struct { - uint64_t uid; - int mask; // how many MSB bits used - char* desc; + uint64_t uid; + int mask; // how many MSB bits used + char* desc; } productName; const productName uidmapping[] = { - // UID, #significant Bits, "Vendor(+Product)" - { 0xE001000000000000LL, 16, "Motorola UK" }, + // UID, #significant Bits, "Vendor(+Product)" + { 0xE001000000000000LL, 16, "Motorola UK" }, - // E0 02 xx - // 02 = ST Microelectronics - // XX = IC id (Chip ID Family) - { 0xE002000000000000LL, 16, "ST Microelectronics SA France" }, - { 0xE002050000000000LL, 24, "ST Microelectronics; LRI64 [IC id = 05]"}, - { 0xE002080000000000LL, 24, "ST Microelectronics; LRI2K [IC id = 08]"}, - { 0xE0020A0000000000LL, 24, "ST Microelectronics; LRIS2K [IC id = 10]"}, - { 0xE002440000000000LL, 24, "ST Microelectronics; LRIS64K [IC id = 68]"}, + // E0 02 xx + // 02 = ST Microelectronics + // XX = IC id (Chip ID Family) + { 0xE002000000000000LL, 16, "ST Microelectronics SA France" }, + { 0xE002050000000000LL, 24, "ST Microelectronics; LRI64 [IC id = 05]"}, + { 0xE002080000000000LL, 24, "ST Microelectronics; LRI2K [IC id = 08]"}, + { 0xE0020A0000000000LL, 24, "ST Microelectronics; LRIS2K [IC id = 10]"}, + { 0xE002440000000000LL, 24, "ST Microelectronics; LRIS64K [IC id = 68]"}, - { 0xE003000000000000LL, 16, "Hitachi, Ltd Japan" }, + { 0xE003000000000000LL, 16, "Hitachi, Ltd Japan" }, - // E0 04 xx - // 04 = Manufacturer code (Philips/NXP) - // XX = IC id (Chip ID Family) - //I-Code SLI SL2 ICS20 [IC id = 01] - //I-Code SLI-S [IC id = 02] - //I-Code SLI-L [IC id = 03] - //I-Code SLIX [IC id = 01 + bit36 set to 1 (starting from bit0 - different from normal SLI)] - //I-Code SLIX-S [IC id = 02 + bit36 set to 1] - //I-Code SLIX-L [IC id = 03 + bit36 set to 1] - { 0xE004000000000000LL, 16, "NXP Semiconductors Germany (Philips)" }, - { 0xE004010000000000LL, 24, "NXP(Philips); IC SL2 ICS20/ICS21(SLI) ICS2002/ICS2102(SLIX)" }, - { 0xE004020000000000LL, 24, "NXP(Philips); IC SL2 ICS53/ICS54(SLI-S) ICS5302/ICS5402(SLIX-S)" }, - { 0xE004030000000000LL, 24, "NXP(Philips); IC SL2 ICS50/ICS51(SLI-L) ICS5002/ICS5102(SLIX-L)" }, + // E0 04 xx + // 04 = Manufacturer code (Philips/NXP) + // XX = IC id (Chip ID Family) + //I-Code SLI SL2 ICS20 [IC id = 01] + //I-Code SLI-S [IC id = 02] + //I-Code SLI-L [IC id = 03] + //I-Code SLIX [IC id = 01 + bit36 set to 1 (starting from bit0 - different from normal SLI)] + //I-Code SLIX-S [IC id = 02 + bit36 set to 1] + //I-Code SLIX-L [IC id = 03 + bit36 set to 1] + { 0xE004000000000000LL, 16, "NXP Semiconductors Germany (Philips)" }, + { 0xE004010000000000LL, 24, "NXP(Philips); IC SL2 ICS20/ICS21(SLI) ICS2002/ICS2102(SLIX)" }, + { 0xE004020000000000LL, 24, "NXP(Philips); IC SL2 ICS53/ICS54(SLI-S) ICS5302/ICS5402(SLIX-S)" }, + { 0xE004030000000000LL, 24, "NXP(Philips); IC SL2 ICS50/ICS51(SLI-L) ICS5002/ICS5102(SLIX-L)" }, - // E0 05 XX .. .. .. - // 05 = Manufacturer code (Infineon) - // XX = IC id (Chip ID Family) - { 0xE005000000000000LL, 16, "Infineon Technologies AG Germany" }, - { 0xE005A10000000000LL, 24, "Infineon; SRF55V01P [IC id = 161] plain mode 1kBit"}, - { 0xE005A80000000000LL, 24, "Infineon; SRF55V01P [IC id = 168] pilot series 1kBit"}, - { 0xE005400000000000LL, 24, "Infineon; SRF55V02P [IC id = 64] plain mode 2kBit"}, - { 0xE005000000000000LL, 24, "Infineon; SRF55V10P [IC id = 00] plain mode 10KBit"}, - { 0xE005500000000000LL, 24, "Infineon; SRF55V02S [IC id = 80] secure mode 2kBit"}, - { 0xE005100000000000LL, 24, "Infineon; SRF55V10S [IC id = 16] secure mode 10KBit"}, - { 0xE0051E0000000000LL, 23, "Infineon; SLE66r01P [IC id = 3x = My-d Move or My-d move NFC]"}, - { 0xE005200000000000LL, 21, "Infineon; SLE66r01P [IC id = 3x = My-d Move or My-d move NFC]"}, + // E0 05 XX .. .. .. + // 05 = Manufacturer code (Infineon) + // XX = IC id (Chip ID Family) + { 0xE005000000000000LL, 16, "Infineon Technologies AG Germany" }, + { 0xE005A10000000000LL, 24, "Infineon; SRF55V01P [IC id = 161] plain mode 1kBit"}, + { 0xE005A80000000000LL, 24, "Infineon; SRF55V01P [IC id = 168] pilot series 1kBit"}, + { 0xE005400000000000LL, 24, "Infineon; SRF55V02P [IC id = 64] plain mode 2kBit"}, + { 0xE005000000000000LL, 24, "Infineon; SRF55V10P [IC id = 00] plain mode 10KBit"}, + { 0xE005500000000000LL, 24, "Infineon; SRF55V02S [IC id = 80] secure mode 2kBit"}, + { 0xE005100000000000LL, 24, "Infineon; SRF55V10S [IC id = 16] secure mode 10KBit"}, + { 0xE0051E0000000000LL, 23, "Infineon; SLE66r01P [IC id = 3x = My-d Move or My-d move NFC]"}, + { 0xE005200000000000LL, 21, "Infineon; SLE66r01P [IC id = 3x = My-d Move or My-d move NFC]"}, - { 0xE006000000000000LL, 16, "Cylink USA" }, + { 0xE006000000000000LL, 16, "Cylink USA" }, - // E0 07 xx - // 07 = Texas Instruments - // XX = from bit 41 to bit 43 = product configuration - from bit 44 to bit 47 IC id (Chip ID Family) - //Tag IT RFIDType-I Plus, 2kBit, TI Inlay - //Tag-it HF-I Plus Inlay [IC id = 00] -> b'0000 000 2kBit - //Tag-it HF-I Plus Chip [IC id = 64] -> b'1000 000 2kBit - //Tag-it HF-I Standard Chip / Inlays [IC id = 96] -> b'1100 000 256Bit - //Tag-it HF-I Pro Chip / Inlays [IC id = 98] -> b'1100 010 256Bit, Password protection - { 0xE007000000000000LL, 16, "Texas Instrument France" }, - { 0xE007000000000000LL, 20, "Texas Instrument; Tag-it HF-I Plus Inlay; 64x32bit" }, - { 0xE007100000000000LL, 20, "Texas Instrument; Tag-it HF-I Plus Chip; 64x32bit" }, - { 0xE007800000000000LL, 23, "Texas Instrument; Tag-it HF-I Plus (RF-HDT-DVBB tag or Third Party Products)" }, - { 0xE007C00000000000LL, 23, "Texas Instrument; Tag-it HF-I Standard; 8x32bit" }, - { 0xE007C40000000000LL, 23, "Texas Instrument; Tag-it HF-I Pro; 8x23bit; password" }, + // E0 07 xx + // 07 = Texas Instruments + // XX = from bit 41 to bit 43 = product configuration - from bit 44 to bit 47 IC id (Chip ID Family) + //Tag IT RFIDType-I Plus, 2kBit, TI Inlay + //Tag-it HF-I Plus Inlay [IC id = 00] -> b'0000 000 2kBit + //Tag-it HF-I Plus Chip [IC id = 64] -> b'1000 000 2kBit + //Tag-it HF-I Standard Chip / Inlays [IC id = 96] -> b'1100 000 256Bit + //Tag-it HF-I Pro Chip / Inlays [IC id = 98] -> b'1100 010 256Bit, Password protection + { 0xE007000000000000LL, 16, "Texas Instrument France" }, + { 0xE007000000000000LL, 20, "Texas Instrument; Tag-it HF-I Plus Inlay; 64x32bit" }, + { 0xE007100000000000LL, 20, "Texas Instrument; Tag-it HF-I Plus Chip; 64x32bit" }, + { 0xE007800000000000LL, 23, "Texas Instrument; Tag-it HF-I Plus (RF-HDT-DVBB tag or Third Party Products)" }, + { 0xE007C00000000000LL, 23, "Texas Instrument; Tag-it HF-I Standard; 8x32bit" }, + { 0xE007C40000000000LL, 23, "Texas Instrument; Tag-it HF-I Pro; 8x23bit; password" }, - { 0xE008000000000000LL, 16, "Fujitsu Limited Japan" }, - { 0xE009000000000000LL, 16, "Matsushita Electronics Corporation, Semiconductor Company Japan" }, - { 0xE00A000000000000LL, 16, "NEC Japan" }, - { 0xE00B000000000000LL, 16, "Oki Electric Industry Co. Ltd Japan" }, - { 0xE00C000000000000LL, 16, "Toshiba Corp. Japan" }, - { 0xE00D000000000000LL, 16, "Mitsubishi Electric Corp. Japan" }, - { 0xE00E000000000000LL, 16, "Samsung Electronics Co. Ltd Korea" }, - { 0xE00F000000000000LL, 16, "Hynix / Hyundai, Korea" }, - { 0xE010000000000000LL, 16, "LG-Semiconductors Co. Ltd Korea" }, - { 0xE011000000000000LL, 16, "Emosyn-EM Microelectronics USA" }, + { 0xE008000000000000LL, 16, "Fujitsu Limited Japan" }, + { 0xE009000000000000LL, 16, "Matsushita Electronics Corporation, Semiconductor Company Japan" }, + { 0xE00A000000000000LL, 16, "NEC Japan" }, + { 0xE00B000000000000LL, 16, "Oki Electric Industry Co. Ltd Japan" }, + { 0xE00C000000000000LL, 16, "Toshiba Corp. Japan" }, + { 0xE00D000000000000LL, 16, "Mitsubishi Electric Corp. Japan" }, + { 0xE00E000000000000LL, 16, "Samsung Electronics Co. Ltd Korea" }, + { 0xE00F000000000000LL, 16, "Hynix / Hyundai, Korea" }, + { 0xE010000000000000LL, 16, "LG-Semiconductors Co. Ltd Korea" }, + { 0xE011000000000000LL, 16, "Emosyn-EM Microelectronics USA" }, - { 0xE012000000000000LL, 16, "HID Corporation" }, - { 0xE012000000000000LL, 16, "INSIDE Technology France" }, - { 0xE013000000000000LL, 16, "ORGA Kartensysteme GmbH Germany" }, - { 0xE014000000000000LL, 16, "SHARP Corporation Japan" }, - { 0xE015000000000000LL, 16, "ATMEL France" }, + { 0xE012000000000000LL, 16, "HID Corporation" }, + { 0xE012000000000000LL, 16, "INSIDE Technology France" }, + { 0xE013000000000000LL, 16, "ORGA Kartensysteme GmbH Germany" }, + { 0xE014000000000000LL, 16, "SHARP Corporation Japan" }, + { 0xE015000000000000LL, 16, "ATMEL France" }, - { 0xE016000000000000LL, 16, "EM Microelectronic-Marin SA Switzerland (Skidata)"}, - { 0xE016040000000000LL, 24, "EM-Marin SA (Skidata Keycard-eco); EM4034 [IC id = 01] (Read/Write - no AFI)"}, - { 0xE0160C0000000000LL, 24, "EM-Marin SA (Skidata); EM4035 [IC id = 03] (Read/Write - replaced by 4233)"}, - { 0xE016100000000000LL, 24, "EM-Marin SA (Skidata); EM4135 [IC id = 04] (Read/Write - replaced by 4233) 36x64bit start page 13"}, - { 0xE016140000000000LL, 24, "EM-Marin SA (Skidata); EM4036 [IC id = 05] 28pF"}, - { 0xE016180000000000LL, 24, "EM-Marin SA (Skidata); EM4006 [IC id = 06] (Read Only)"}, - { 0xE0161C0000000000LL, 24, "EM-Marin SA (Skidata); EM4133 [IC id = 07] 23,5pF (Read/Write)"}, - { 0xE016200000000000LL, 24, "EM-Marin SA (Skidata); EM4033 [IC id = 08] 23,5pF (Read Only - no AFI / no DSFID / no security blocks)"}, - { 0xE016240000000000LL, 24, "EM-Marin SA (Skidata); EM4233 [IC id = 09] 23,5pF CustomerID-102"}, - { 0xE016280000000000LL, 24, "EM-Marin SA (Skidata); EM4233 SLIC [IC id = 10] 23,5pF (1Kb flash memory - not provide High Security mode and QuietStorage feature)" }, - { 0xE0163C0000000000LL, 24, "EM-Marin SA (Skidata); EM4237 [IC id = 15] 23,5pF"}, - { 0xE0167C0000000000LL, 24, "EM-Marin SA (Skidata); EM4233 [IC id = 31] 95pF"}, - { 0xE016940000000000LL, 24, "EM-Marin SA (Skidata); EM4036 [IC id = 37] 95pF 51x64bit "}, - { 0xE0169c0000000000LL, 24, "EM-Marin SA (Skidata); EM4133 [IC id = 39] 95pF (Read/Write)" }, - { 0xE016A80000000000LL, 24, "EM-Marin SA (Skidata); EM4233 SLIC [IC id = 42] 97pF" }, - { 0xE016BC0000000000LL, 24, "EM-Marin SA (Skidata); EM4237 [IC id = 47] 97pF" }, + { 0xE016000000000000LL, 16, "EM Microelectronic-Marin SA Switzerland (Skidata)"}, + { 0xE016040000000000LL, 24, "EM-Marin SA (Skidata Keycard-eco); EM4034 [IC id = 01] (Read/Write - no AFI)"}, + { 0xE0160C0000000000LL, 24, "EM-Marin SA (Skidata); EM4035 [IC id = 03] (Read/Write - replaced by 4233)"}, + { 0xE016100000000000LL, 24, "EM-Marin SA (Skidata); EM4135 [IC id = 04] (Read/Write - replaced by 4233) 36x64bit start page 13"}, + { 0xE016140000000000LL, 24, "EM-Marin SA (Skidata); EM4036 [IC id = 05] 28pF"}, + { 0xE016180000000000LL, 24, "EM-Marin SA (Skidata); EM4006 [IC id = 06] (Read Only)"}, + { 0xE0161C0000000000LL, 24, "EM-Marin SA (Skidata); EM4133 [IC id = 07] 23,5pF (Read/Write)"}, + { 0xE016200000000000LL, 24, "EM-Marin SA (Skidata); EM4033 [IC id = 08] 23,5pF (Read Only - no AFI / no DSFID / no security blocks)"}, + { 0xE016240000000000LL, 24, "EM-Marin SA (Skidata); EM4233 [IC id = 09] 23,5pF CustomerID-102"}, + { 0xE016280000000000LL, 24, "EM-Marin SA (Skidata); EM4233 SLIC [IC id = 10] 23,5pF (1Kb flash memory - not provide High Security mode and QuietStorage feature)" }, + { 0xE0163C0000000000LL, 24, "EM-Marin SA (Skidata); EM4237 [IC id = 15] 23,5pF"}, + { 0xE0167C0000000000LL, 24, "EM-Marin SA (Skidata); EM4233 [IC id = 31] 95pF"}, + { 0xE016940000000000LL, 24, "EM-Marin SA (Skidata); EM4036 [IC id = 37] 95pF 51x64bit "}, + { 0xE0169c0000000000LL, 24, "EM-Marin SA (Skidata); EM4133 [IC id = 39] 95pF (Read/Write)" }, + { 0xE016A80000000000LL, 24, "EM-Marin SA (Skidata); EM4233 SLIC [IC id = 42] 97pF" }, + { 0xE016BC0000000000LL, 24, "EM-Marin SA (Skidata); EM4237 [IC id = 47] 97pF" }, - { 0xE017000000000000LL, 16, "KSW Microtec GmbH Germany" }, - { 0xE018000000000000LL, 16, "ZMD AG Germany" }, - { 0xE019000000000000LL, 16, "XICOR, Inc. USA" }, - { 0xE01A000000000000LL, 16, "Sony Corporation Japan Identifier Company Country" }, - { 0xE01B000000000000LL, 16, "Malaysia Microelectronic Solutions Sdn. Bhd Malaysia" }, - { 0xE01C000000000000LL, 16, "Emosyn USA" }, - { 0xE01D000000000000LL, 16, "Shanghai Fudan Microelectronics Co. Ltd. P.R. China" }, - { 0xE01E000000000000LL, 16, "Magellan Technology Pty Limited Australia" }, - { 0xE01F000000000000LL, 16, "Melexis NV BO Switzerland" }, - { 0xE020000000000000LL, 16, "Renesas Technology Corp. Japan" }, - { 0xE021000000000000LL, 16, "TAGSYS France" }, - { 0xE022000000000000LL, 16, "Transcore USA" }, - { 0xE023000000000000LL, 16, "Shanghai belling corp., ltd. China" }, - { 0xE024000000000000LL, 16, "Masktech Germany Gmbh Germany" }, - { 0xE025000000000000LL, 16, "Innovision Research and Technology Plc UK" }, - { 0xE026000000000000LL, 16, "Hitachi ULSI Systems Co., Ltd. Japan" }, - { 0xE027000000000000LL, 16, "Cypak AB Sweden" }, - { 0xE028000000000000LL, 16, "Ricoh Japan" }, - { 0xE029000000000000LL, 16, "ASK France" }, - { 0xE02A000000000000LL, 16, "Unicore Microsystems, LLC Russian Federation" }, - { 0xE02B000000000000LL, 16, "Dallas Semiconductor/Maxim USA" }, - { 0xE02C000000000000LL, 16, "Impinj, Inc. USA" }, - { 0xE02D000000000000LL, 16, "RightPlug Alliance USA" }, - { 0xE02E000000000000LL, 16, "Broadcom Corporation USA" }, - { 0xE02F000000000000LL, 16, "MStar Semiconductor, Inc Taiwan, ROC" }, - { 0xE030000000000000LL, 16, "BeeDar Technology Inc. USA" }, - { 0xE031000000000000LL, 16, "RFIDsec Denmark" }, - { 0xE032000000000000LL, 16, "Schweizer Electronic AG Germany" }, - { 0xE033000000000000LL, 16, "AMIC Technology Corp Taiwan" }, - { 0xE034000000000000LL, 16, "Mikron JSC Russia" }, - { 0xE035000000000000LL, 16, "Fraunhofer Institute for Photonic Microsystems Germany" }, - { 0xE036000000000000LL, 16, "IDS Microchip AG Switzerland" }, - { 0xE037000000000000LL, 16, "Kovio USA" }, - { 0xE038000000000000LL, 16, "HMT Microelectronic Ltd Switzerland Identifier Company Country" }, - { 0xE039000000000000LL, 16, "Silicon Craft Technology Thailand" }, - { 0xE03A000000000000LL, 16, "Advanced Film Device Inc. Japan" }, - { 0xE03B000000000000LL, 16, "Nitecrest Ltd UK" }, - { 0xE03C000000000000LL, 16, "Verayo Inc. USA" }, - { 0xE03D000000000000LL, 16, "HID Global USA" }, - { 0xE03E000000000000LL, 16, "Productivity Engineering Gmbh Germany" }, - { 0xE03F000000000000LL, 16, "Austriamicrosystems AG (reserved) Austria" }, - { 0xE040000000000000LL, 16, "Gemalto SA France" }, - { 0xE041000000000000LL, 16, "Renesas Electronics Corporation Japan" }, - { 0xE042000000000000LL, 16, "3Alogics Inc Korea" }, - { 0xE043000000000000LL, 16, "Top TroniQ Asia Limited Hong Kong" }, - { 0xE044000000000000LL, 16, "Gentag Inc (USA) USA" }, - { 0,0,"no tag-info available" } // must be the last entry + { 0xE017000000000000LL, 16, "KSW Microtec GmbH Germany" }, + { 0xE018000000000000LL, 16, "ZMD AG Germany" }, + { 0xE019000000000000LL, 16, "XICOR, Inc. USA" }, + { 0xE01A000000000000LL, 16, "Sony Corporation Japan Identifier Company Country" }, + { 0xE01B000000000000LL, 16, "Malaysia Microelectronic Solutions Sdn. Bhd Malaysia" }, + { 0xE01C000000000000LL, 16, "Emosyn USA" }, + { 0xE01D000000000000LL, 16, "Shanghai Fudan Microelectronics Co. Ltd. P.R. China" }, + { 0xE01E000000000000LL, 16, "Magellan Technology Pty Limited Australia" }, + { 0xE01F000000000000LL, 16, "Melexis NV BO Switzerland" }, + { 0xE020000000000000LL, 16, "Renesas Technology Corp. Japan" }, + { 0xE021000000000000LL, 16, "TAGSYS France" }, + { 0xE022000000000000LL, 16, "Transcore USA" }, + { 0xE023000000000000LL, 16, "Shanghai belling corp., ltd. China" }, + { 0xE024000000000000LL, 16, "Masktech Germany Gmbh Germany" }, + { 0xE025000000000000LL, 16, "Innovision Research and Technology Plc UK" }, + { 0xE026000000000000LL, 16, "Hitachi ULSI Systems Co., Ltd. Japan" }, + { 0xE027000000000000LL, 16, "Cypak AB Sweden" }, + { 0xE028000000000000LL, 16, "Ricoh Japan" }, + { 0xE029000000000000LL, 16, "ASK France" }, + { 0xE02A000000000000LL, 16, "Unicore Microsystems, LLC Russian Federation" }, + { 0xE02B000000000000LL, 16, "Dallas Semiconductor/Maxim USA" }, + { 0xE02C000000000000LL, 16, "Impinj, Inc. USA" }, + { 0xE02D000000000000LL, 16, "RightPlug Alliance USA" }, + { 0xE02E000000000000LL, 16, "Broadcom Corporation USA" }, + { 0xE02F000000000000LL, 16, "MStar Semiconductor, Inc Taiwan, ROC" }, + { 0xE030000000000000LL, 16, "BeeDar Technology Inc. USA" }, + { 0xE031000000000000LL, 16, "RFIDsec Denmark" }, + { 0xE032000000000000LL, 16, "Schweizer Electronic AG Germany" }, + { 0xE033000000000000LL, 16, "AMIC Technology Corp Taiwan" }, + { 0xE034000000000000LL, 16, "Mikron JSC Russia" }, + { 0xE035000000000000LL, 16, "Fraunhofer Institute for Photonic Microsystems Germany" }, + { 0xE036000000000000LL, 16, "IDS Microchip AG Switzerland" }, + { 0xE037000000000000LL, 16, "Kovio USA" }, + { 0xE038000000000000LL, 16, "HMT Microelectronic Ltd Switzerland Identifier Company Country" }, + { 0xE039000000000000LL, 16, "Silicon Craft Technology Thailand" }, + { 0xE03A000000000000LL, 16, "Advanced Film Device Inc. Japan" }, + { 0xE03B000000000000LL, 16, "Nitecrest Ltd UK" }, + { 0xE03C000000000000LL, 16, "Verayo Inc. USA" }, + { 0xE03D000000000000LL, 16, "HID Global USA" }, + { 0xE03E000000000000LL, 16, "Productivity Engineering Gmbh Germany" }, + { 0xE03F000000000000LL, 16, "Austriamicrosystems AG (reserved) Austria" }, + { 0xE040000000000000LL, 16, "Gemalto SA France" }, + { 0xE041000000000000LL, 16, "Renesas Electronics Corporation Japan" }, + { 0xE042000000000000LL, 16, "3Alogics Inc Korea" }, + { 0xE043000000000000LL, 16, "Top TroniQ Asia Limited Hong Kong" }, + { 0xE044000000000000LL, 16, "Gentag Inc (USA) USA" }, + { 0,0,"no tag-info available" } // must be the last entry }; // fast method to just read the UID of a tag (collission detection not supported) -// *buf should be large enough to fit the 64bit uid +// *buf should be large enough to fit the 64bit uid // returns 1 if suceeded int getUID(uint8_t *buf) { - UsbCommand resp; - UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? + UsbCommand resp; + UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? - c.d.asBytes[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; - c.d.asBytes[1] = ISO15_CMD_INVENTORY; - c.d.asBytes[2] = 0; // mask length + c.d.asBytes[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_INVENTORY | ISO15_REQINV_SLOT1; + c.d.asBytes[1] = ISO15_CMD_INVENTORY; + c.d.asBytes[2] = 0; // mask length - AddCrc(c.d.asBytes, 3); - c.arg[0] = 5; // len + AddCrc(c.d.asBytes, 3); + c.arg[0] = 5; // len - uint8_t retry; + uint8_t retry; - // don't give up the at the first try - for (retry = 0; retry < 3; retry++) { + // don't give up the at the first try + for (retry = 0; retry < 3; retry++) { - clearCommandBuffer(); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - uint8_t resplen = resp.arg[0]; - if (resplen >= 12 && CheckCrc(resp.d.asBytes, 12)) { - memcpy(buf, resp.d.asBytes + 2, 8); - return 1; - } - } - } // retry + uint8_t resplen = resp.arg[0]; + if (resplen >= 12 && CheckCrc(resp.d.asBytes, 12)) { + memcpy(buf, resp.d.asBytes + 2, 8); + return 1; + } + } + } // retry - if ( retry >= 3 ) - PrintAndLogEx(WARNING, "timeout while waiting for reply."); + if ( retry >= 3 ) + PrintAndLogEx(WARNING, "timeout while waiting for reply."); - return 0; + return 0; } // get a product description based on the UID -// uid[8] tag uid +// uid[8] tag uid // returns description of the best match static char* getTagInfo_15(uint8_t *uid) { - uint64_t myuid, mask; - int i = 0, best = -1; - memcpy(&myuid, uid, sizeof(uint64_t)); - while (uidmapping[i].mask > 0) { - mask = (~0LL) << (64-uidmapping[i].mask); - if ((myuid & mask) == uidmapping[i].uid) { - if (best == -1) { - best = i; - } else { - if (uidmapping[i].mask > uidmapping[best].mask) { - best=i; - } - } - } - i++; - } + uint64_t myuid, mask; + int i = 0, best = -1; + memcpy(&myuid, uid, sizeof(uint64_t)); + while (uidmapping[i].mask > 0) { + mask = (~0LL) << (64-uidmapping[i].mask); + if ((myuid & mask) == uidmapping[i].uid) { + if (best == -1) { + best = i; + } else { + if (uidmapping[i].mask > uidmapping[best].mask) { + best=i; + } + } + } + i++; + } - if (best >= 0) - return uidmapping[best].desc; - return uidmapping[i].desc; + if (best >= 0) + return uidmapping[best].desc; + return uidmapping[i].desc; } // return a clear-text message to an errorcode static char* TagErrorStr(uint8_t error) { - switch (error) { - case 0x01: return "The command is not supported"; - case 0x02: return "The command is not recognised"; - case 0x03: return "The option is not supported."; - case 0x0f: return "Unknown error."; - case 0x10: return "The specified block is not available (doesn't exist)."; - case 0x11: return "The specified block is already -locked and thus cannot be locked again"; - case 0x12: return "The specified block is locked and its content cannot be changed."; - case 0x13: return "The specified block was not successfully programmed."; - case 0x14: return "The specified block was not successfully locked."; - default: return "Reserved for Future Use or Custom command error."; - } + switch (error) { + case 0x01: return "The command is not supported"; + case 0x02: return "The command is not recognised"; + case 0x03: return "The option is not supported."; + case 0x0f: return "Unknown error."; + case 0x10: return "The specified block is not available (doesn't exist)."; + case 0x11: return "The specified block is already -locked and thus cannot be locked again"; + case 0x12: return "The specified block is locked and its content cannot be changed."; + case 0x13: return "The specified block was not successfully programmed."; + case 0x14: return "The specified block was not successfully locked."; + default: return "Reserved for Future Use or Custom command error."; + } } int usage_15_demod(void){ - PrintAndLogEx(NORMAL, "Tries to demodulate / decode ISO15693, from downloaded samples.\n" - "Gather samples with 'hf 15 read' / 'hf 15 record'"); - return 0; + PrintAndLogEx(NORMAL, "Tries to demodulate / decode ISO15693, from downloaded samples.\n" + "Gather samples with 'hf 15 read' / 'hf 15 record'"); + return 0; } int usage_15_samples(void){ - PrintAndLogEx(NORMAL, "Acquire samples as Reader (enables carrier, send inquiry\n" - "and download it to graphbuffer. Try 'hf 15 demod' to try to demodulate/decode signal"); - return 0; + PrintAndLogEx(NORMAL, "Acquire samples as Reader (enables carrier, send inquiry\n" + "and download it to graphbuffer. Try 'hf 15 demod' to try to demodulate/decode signal"); + return 0; } int usage_15_info(void){ - PrintAndLogEx(NORMAL, "Uses the optional command 'get_systeminfo' 0x2B to try and extract information\n" - "command may fail, depending on tag.\n" - "defaults to '1 out of 4' mode\n" - "\n" - "Usage: hf 15 info [options] \n" - "Options:\n" - "\t-2 use slower '1 out of 256' mode\n" - "\tuid (either): \n" - "\t <8B hex> full UID eg E011223344556677\n" - "\t u unaddressed mode\n" - "\t * scan for tag\n" - "Examples:\n" - "\thf 15 info u"); - return 0; + PrintAndLogEx(NORMAL, "Uses the optional command 'get_systeminfo' 0x2B to try and extract information\n" + "command may fail, depending on tag.\n" + "defaults to '1 out of 4' mode\n" + "\n" + "Usage: hf 15 info [options] \n" + "Options:\n" + "\t-2 use slower '1 out of 256' mode\n" + "\tuid (either): \n" + "\t <8B hex> full UID eg E011223344556677\n" + "\t u unaddressed mode\n" + "\t * scan for tag\n" + "Examples:\n" + "\thf 15 info u"); + return 0; } int usage_15_record(void){ - PrintAndLogEx(NORMAL, "Record activity without enableing carrier"); - return 0; + PrintAndLogEx(NORMAL, "Record activity without enableing carrier"); + return 0; } int usage_15_reader(void){ - PrintAndLogEx(NORMAL, "This command identifies a ISO 15693 tag\n" - "\n" - "Usage: hf 15 reader [h]\n" - "Options:\n" - "\th this help\n" - "\n" - "Example:\n" - "\thf 15 reader"); - return 0; + PrintAndLogEx(NORMAL, "This command identifies a ISO 15693 tag\n" + "\n" + "Usage: hf 15 reader [h]\n" + "Options:\n" + "\th this help\n" + "\n" + "Example:\n" + "\thf 15 reader"); + return 0; } int usage_15_sim(void){ - PrintAndLogEx(NORMAL, "Usage: hf 15 sim \n" - "\n" - "Example:\n" - "\thf 15 sim E016240000000000"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 15 sim \n" + "\n" + "Example:\n" + "\thf 15 sim E016240000000000"); + return 0; } int usage_15_findafi(void){ - PrintAndLogEx(NORMAL, "'hf 15 finafi' This command needs a helptext. Feel free to add one!"); - return 0; + PrintAndLogEx(NORMAL, "'hf 15 finafi' This command needs a helptext. Feel free to add one!"); + return 0; } int usage_15_dump(void){ - PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-15693 tag and save it to file\n" - "\n" - "Usage: hf 15 dump [h] \n" - "Options:\n" - "\th this help\n" - "\tf filename, if no UID will be used as filename\n" - "\n" - "Example:\n" - "\thf 15 dump f\n" - "\thf 15 dump f mydump"); - return 0; + PrintAndLogEx(NORMAL, "This command dumps the contents of a ISO-15693 tag and save it to file\n" + "\n" + "Usage: hf 15 dump [h] \n" + "Options:\n" + "\th this help\n" + "\tf filename, if no UID will be used as filename\n" + "\n" + "Example:\n" + "\thf 15 dump f\n" + "\thf 15 dump f mydump"); + return 0; } int usage_15_restore(void){ char *options[][2]={ @@ -358,133 +358,133 @@ int usage_15_raw(void){ return 0; } int usage_15_read(void){ - PrintAndLogEx(NORMAL, "Usage: hf 15 read [options] \n" - "Options:\n" - "\t-2 use slower '1 out of 256' mode\n" - "\tuid (either): \n" - "\t <8B hex> full UID eg E011223344556677\n" - "\t u unaddressed mode\n" - "\t * scan for tag\n" - "\tpage#: page number 0-255"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 15 read [options] \n" + "Options:\n" + "\t-2 use slower '1 out of 256' mode\n" + "\tuid (either): \n" + "\t <8B hex> full UID eg E011223344556677\n" + "\t u unaddressed mode\n" + "\t * scan for tag\n" + "\tpage#: page number 0-255"); + return 0; } int usage_15_write(void){ - PrintAndLogEx(NORMAL, "Usage: hf 15 write [options] \n" - "Options:\n" - "\t-2 use slower '1 out of 256' mode\n" - "\t-o set OPTION Flag (needed for TI)\n" - "\tuid (either): \n" - "\t <8B hex> full UID eg E011223344556677\n" - "\t u unaddressed mode\n" - "\t * scan for tag\n" - "\tpage#: page number 0-255\n" - "\thexdata: data to be written eg AA BB CC DD"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 15 write [options] \n" + "Options:\n" + "\t-2 use slower '1 out of 256' mode\n" + "\t-o set OPTION Flag (needed for TI)\n" + "\tuid (either): \n" + "\t <8B hex> full UID eg E011223344556677\n" + "\t u unaddressed mode\n" + "\t * scan for tag\n" + "\tpage#: page number 0-255\n" + "\thexdata: data to be written eg AA BB CC DD"); + return 0; } int usage_15_readmulti(void){ - PrintAndLogEx(NORMAL, "Usage: hf 15 readmulti [options] \n" - "Options:\n" - "\t-2 use slower '1 out of 256' mode\n" - "\tuid (either): \n" - "\t <8B hex> full UID eg E011223344556677\n" - "\t u unaddressed mode\n" - "\t * scan for tag\n" - "\tstart#: page number to start 0-255\n" - "\tcount#: number of pages"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf 15 readmulti [options] \n" + "Options:\n" + "\t-2 use slower '1 out of 256' mode\n" + "\tuid (either): \n" + "\t <8B hex> full UID eg E011223344556677\n" + "\t u unaddressed mode\n" + "\t * scan for tag\n" + "\tstart#: page number to start 0-255\n" + "\tcount#: number of pages"); + return 0; } // Mode 3 //helptext int CmdHF15Demod(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_15_demod(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_15_demod(); - // The sampling rate is 106.353 ksps/s, for T = 18.8 us - int i, j; - int max = 0, maxPos = 0; - int skip = 4; + // The sampling rate is 106.353 ksps/s, for T = 18.8 us + int i, j; + int max = 0, maxPos = 0; + int skip = 4; - if (GraphTraceLen < 1000) return 0; + if (GraphTraceLen < 1000) return 0; - // First, correlate for SOF - for (i = 0; i < 1000; i++) { - int corr = 0; - for (j = 0; j < ARRAYLEN(FrameSOF); j += skip) { - corr += FrameSOF[j] * GraphBuffer[i + (j / skip)]; - } - if (corr > max) { - max = corr; - maxPos = i; - } - } + // First, correlate for SOF + for (i = 0; i < 1000; i++) { + int corr = 0; + for (j = 0; j < ARRAYLEN(FrameSOF); j += skip) { + corr += FrameSOF[j] * GraphBuffer[i + (j / skip)]; + } + if (corr > max) { + max = corr; + maxPos = i; + } + } - PrintAndLogEx(NORMAL, "SOF at %d, correlation %d", maxPos, max / (ARRAYLEN(FrameSOF) / skip)); + PrintAndLogEx(NORMAL, "SOF at %d, correlation %d", maxPos, max / (ARRAYLEN(FrameSOF) / skip)); - i = maxPos + ARRAYLEN(FrameSOF) / skip; - int k = 0; - uint8_t outBuf[20]; - memset(outBuf, 0, sizeof(outBuf)); - uint8_t mask = 0x01; - for (;;) { - int corr0 = 0, corr1 = 0, corrEOF = 0; - for (j = 0; j < ARRAYLEN(Logic0); j += skip) { - corr0 += Logic0[j] * GraphBuffer[i + (j / skip)]; - } - for (j = 0; j < ARRAYLEN(Logic1); j += skip) { - corr1 += Logic1[j] * GraphBuffer[i + (j / skip)]; - } - for (j = 0; j < ARRAYLEN(FrameEOF); j += skip) { - corrEOF += FrameEOF[j] * GraphBuffer[i + (j / skip)]; - } - // Even things out by the length of the target waveform. - corr0 *= 4; - corr1 *= 4; + i = maxPos + ARRAYLEN(FrameSOF) / skip; + int k = 0; + uint8_t outBuf[20]; + memset(outBuf, 0, sizeof(outBuf)); + uint8_t mask = 0x01; + for (;;) { + int corr0 = 0, corr1 = 0, corrEOF = 0; + for (j = 0; j < ARRAYLEN(Logic0); j += skip) { + corr0 += Logic0[j] * GraphBuffer[i + (j / skip)]; + } + for (j = 0; j < ARRAYLEN(Logic1); j += skip) { + corr1 += Logic1[j] * GraphBuffer[i + (j / skip)]; + } + for (j = 0; j < ARRAYLEN(FrameEOF); j += skip) { + corrEOF += FrameEOF[j] * GraphBuffer[i + (j / skip)]; + } + // Even things out by the length of the target waveform. + corr0 *= 4; + corr1 *= 4; - if (corrEOF > corr1 && corrEOF > corr0) { - PrintAndLogEx(NORMAL, "EOF at %d", i); - break; - } else if (corr1 > corr0) { - i += ARRAYLEN(Logic1) / skip; - outBuf[k] |= mask; - } else { - i += ARRAYLEN(Logic0) / skip; - } - mask <<= 1; - if (mask == 0) { - k++; - mask = 0x01; - } - if ((i + (int)ARRAYLEN(FrameEOF)) >= GraphTraceLen) { - PrintAndLogEx(NORMAL, "ran off end!"); - break; - } - } + if (corrEOF > corr1 && corrEOF > corr0) { + PrintAndLogEx(NORMAL, "EOF at %d", i); + break; + } else if (corr1 > corr0) { + i += ARRAYLEN(Logic1) / skip; + outBuf[k] |= mask; + } else { + i += ARRAYLEN(Logic0) / skip; + } + mask <<= 1; + if (mask == 0) { + k++; + mask = 0x01; + } + if ((i + (int)ARRAYLEN(FrameEOF)) >= GraphTraceLen) { + PrintAndLogEx(NORMAL, "ran off end!"); + break; + } + } - if (mask != 0x01) { - PrintAndLogEx(WARNING, "Error, uneven octet! (discard extra bits!)"); - PrintAndLogEx(NORMAL, " mask = %02x", mask); - } - PrintAndLogEx(NORMAL, "%d octets", k); + if (mask != 0x01) { + PrintAndLogEx(WARNING, "Error, uneven octet! (discard extra bits!)"); + PrintAndLogEx(NORMAL, " mask = %02x", mask); + } + PrintAndLogEx(NORMAL, "%d octets", k); - for (i = 0; i < k; i++) - PrintAndLogEx(NORMAL, "# %2d: %02x ", i, outBuf[i]); + for (i = 0; i < k; i++) + PrintAndLogEx(NORMAL, "# %2d: %02x ", i, outBuf[i]); - PrintAndLogEx(NORMAL, "CRC %04x", Crc(outBuf, k - 2)); - return 0; + PrintAndLogEx(NORMAL, "CRC %04x", Crc(outBuf, k - 2)); + return 0; } // * Acquire Samples as Reader (enables carrier, sends inquiry) //helptext int CmdHF15Samples(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_15_samples(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_15_samples(); - UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693, {0,0,0}}; - clearCommandBuffer(); - SendCommand(&c); + UsbCommand c = {CMD_ACQUIRE_RAW_ADC_SAMPLES_ISO_15693, {0,0,0}}; + clearCommandBuffer(); + SendCommand(&c); - getSamples(0, false); - return 0; + getSamples(0, false); + return 0; } /** @@ -493,552 +493,552 @@ int CmdHF15Samples(const char *Cmd) { */ int CmdHF15Info(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd)<1 || cmdp == 'h' || cmdp == 'H') return usage_15_info(); + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd)<1 || cmdp == 'h' || cmdp == 'H') return usage_15_info(); - UsbCommand resp; - uint8_t *recv; - UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? - uint8_t *req = c.d.asBytes; - char cmdbuf[100]; - char *cmd = cmdbuf; - memset(cmdbuf, 0, sizeof(cmdbuf)); + UsbCommand resp; + uint8_t *recv; + UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? + uint8_t *req = c.d.asBytes; + char cmdbuf[100]; + char *cmd = cmdbuf; + memset(cmdbuf, 0, sizeof(cmdbuf)); - strncpy(cmd, Cmd, 99); + strncpy(cmd, Cmd, 99); - if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_SYSINFO) ) - return 0; + if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_SYSINFO) ) + return 0; - AddCrc(req, c.arg[0]); - c.arg[0] += 2; + AddCrc(req, c.arg[0]); + c.arg[0] += 2; - //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(c.d.asBytes, reqlen) ); + //PrintAndLogEx(NORMAL, "cmd %s", sprint_hex(c.d.asBytes, reqlen) ); - clearCommandBuffer(); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - PrintAndLogEx(WARNING, "iso15693 card select failed"); - return 1; - } + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + PrintAndLogEx(WARNING, "iso15693 card select failed"); + return 1; + } - uint32_t status = resp.arg[0]; + uint32_t status = resp.arg[0]; - if ( status < 2 ) { - PrintAndLogEx(WARNING, "iso15693 card doesn't answer to systeminfo command"); - return 1; - } + if ( status < 2 ) { + PrintAndLogEx(WARNING, "iso15693 card doesn't answer to systeminfo command"); + return 1; + } - recv = resp.d.asBytes; + recv = resp.d.asBytes; - if ( recv[0] & ISO15_RES_ERROR ) { - PrintAndLogEx(WARNING, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; - } + if ( recv[0] & ISO15_RES_ERROR ) { + PrintAndLogEx(WARNING, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + return 3; + } - PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, recv+2)); - PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(recv+2)); - PrintAndLogEx(NORMAL, " SYSINFO : %s", sprint_hex(recv, status-2)); + PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, recv+2)); + PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(recv+2)); + PrintAndLogEx(NORMAL, " SYSINFO : %s", sprint_hex(recv, status-2)); - // DSFID - if (recv[1] & 0x01) - PrintAndLogEx(NORMAL, " - DSFID supported [0x%02X]", recv[10]); - else - PrintAndLogEx(NORMAL, " - DSFID not supported"); + // DSFID + if (recv[1] & 0x01) + PrintAndLogEx(NORMAL, " - DSFID supported [0x%02X]", recv[10]); + else + PrintAndLogEx(NORMAL, " - DSFID not supported"); - // AFI - if (recv[1] & 0x02) - PrintAndLogEx(NORMAL, " - AFI supported [0x%02X]", recv[11]); - else - PrintAndLogEx(NORMAL, " - AFI not supported"); + // AFI + if (recv[1] & 0x02) + PrintAndLogEx(NORMAL, " - AFI supported [0x%02X]", recv[11]); + else + PrintAndLogEx(NORMAL, " - AFI not supported"); - // IC reference - if (recv[1] & 0x08) - PrintAndLogEx(NORMAL, " - IC reference supported [0x%02X]", recv[14]); - else - PrintAndLogEx(NORMAL, " - IC reference not supported"); + // IC reference + if (recv[1] & 0x08) + PrintAndLogEx(NORMAL, " - IC reference supported [0x%02X]", recv[14]); + else + PrintAndLogEx(NORMAL, " - IC reference not supported"); - // memory - if (recv[1] & 0x04) { - PrintAndLogEx(NORMAL, " - Tag provides info on memory layout (vendor dependent)"); - uint8_t blocks = recv[12]+1; - uint8_t size = (recv[13] & 0x1F); - PrintAndLogEx(NORMAL, " %u (or %u) bytes/blocks x %u blocks", size+1, size, blocks ); - } else { - PrintAndLogEx(NORMAL, " - Tag does not provide information on memory layout"); - } - PrintAndLogEx(NORMAL, "\n"); - return 0; + // memory + if (recv[1] & 0x04) { + PrintAndLogEx(NORMAL, " - Tag provides info on memory layout (vendor dependent)"); + uint8_t blocks = recv[12]+1; + uint8_t size = (recv[13] & 0x1F); + PrintAndLogEx(NORMAL, " %u (or %u) bytes/blocks x %u blocks", size+1, size, blocks ); + } else { + PrintAndLogEx(NORMAL, " - Tag does not provide information on memory layout"); + } + PrintAndLogEx(NORMAL, "\n"); + return 0; } // Record Activity without enabeling carrier //helptext int CmdHF15Record(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_15_record(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_15_record(); - UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693, {0,0,0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_RECORD_RAW_ADC_SAMPLES_ISO_15693, {0,0,0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } // used with 'hf search' int HF15Reader(const char *Cmd, bool verbose) { - uint8_t uid[8] = {0,0,0,0,0,0,0,0}; - if (!getUID(uid)) { - if (verbose) PrintAndLogEx(WARNING, "No tag found."); - return 0; - } + uint8_t uid[8] = {0,0,0,0,0,0,0,0}; + if (!getUID(uid)) { + if (verbose) PrintAndLogEx(WARNING, "No tag found."); + return 0; + } - PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, uid)); - PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(uid)); - return 1; + PrintAndLogEx(NORMAL, " UID : %s", sprintUID(NULL, uid)); + PrintAndLogEx(NORMAL, " TYPE : %s", getTagInfo_15(uid)); + return 1; } int CmdHF15Reader(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_15_reader(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_15_reader(); - HF15Reader(Cmd, true); - return 0; + HF15Reader(Cmd, true); + return 0; } // Simulation is still not working very good // helptext int CmdHF15Sim(const char *Cmd) { - char cmdp =tolower(param_getchar(Cmd, 0)); - if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_sim(); + char cmdp =tolower(param_getchar(Cmd, 0)); + if (strlen(Cmd) < 1 || cmdp == 'h') return usage_15_sim(); - uint8_t uid[8] = {0,0,0,0,0,0,0,0}; - if (param_gethex(Cmd, 0, uid, 16)) { - PrintAndLogEx(WARNING, "UID must include 16 HEX symbols"); - return 0; - } + uint8_t uid[8] = {0,0,0,0,0,0,0,0}; + if (param_gethex(Cmd, 0, uid, 16)) { + PrintAndLogEx(WARNING, "UID must include 16 HEX symbols"); + return 0; + } - PrintAndLogEx(SUCCESS, "Starting simulating UID %s", sprint_hex(uid, sizeof(uid)) ); + PrintAndLogEx(SUCCESS, "Starting simulating UID %s", sprint_hex(uid, sizeof(uid)) ); - UsbCommand c = {CMD_SIMTAG_ISO_15693, {0, 0, 0}}; - memcpy(c.d.asBytes, uid, 8); - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_SIMTAG_ISO_15693, {0, 0, 0}}; + memcpy(c.d.asBytes, uid, 8); + clearCommandBuffer(); + SendCommand(&c); + return 0; } // finds the AFI (Application Family Idendifier) of a card, by trying all values // (There is no standard way of reading the AFI, allthough some tags support this) // helptext int CmdHF15Afi(const char *Cmd) { - char cmdp = tolower(param_getchar(Cmd, 0)); - if (cmdp == 'h') return usage_15_findafi(); + char cmdp = tolower(param_getchar(Cmd, 0)); + if (cmdp == 'h') return usage_15_findafi(); - PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); + PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); - UsbCommand c = {CMD_ISO_15693_FIND_AFI, {strtol(Cmd, NULL, 0), 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_ISO_15693_FIND_AFI, {strtol(Cmd, NULL, 0), 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } typedef struct { - uint8_t lock; - uint8_t block[4]; + uint8_t lock; + uint8_t block[4]; } t15memory; // Reads all memory pages // need to write to file int CmdHF15Dump(const char*Cmd) { - uint8_t fileNameLen = 0; - char filename[FILE_PATH_SIZE] = {0}; - char * fptr = filename; - bool errors = false; - uint8_t cmdp = 0; - uint8_t uid[8] = {0,0,0,0,0,0,0,0}; + uint8_t fileNameLen = 0; + char filename[FILE_PATH_SIZE] = {0}; + char * fptr = filename; + bool errors = false; + uint8_t cmdp = 0; + uint8_t uid[8] = {0,0,0,0,0,0,0,0}; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (tolower(param_getchar(Cmd, cmdp))) { - case 'h': - return usage_15_dump(); - case 'f': - fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (tolower(param_getchar(Cmd, cmdp))) { + case 'h': + return usage_15_dump(); + case 'f': + fileNameLen = param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'\n", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - //Validations - if (errors) return usage_15_dump(); + //Validations + if (errors) return usage_15_dump(); - if (fileNameLen < 1) { + if (fileNameLen < 1) { - PrintAndLogEx(INFO, "Using UID as filename"); + PrintAndLogEx(INFO, "Using UID as filename"); - if (!getUID(uid)) { - PrintAndLogEx(WARNING, "No tag found."); - return 1; - } + if (!getUID(uid)) { + PrintAndLogEx(WARNING, "No tag found."); + return 1; + } - fptr += sprintf(fptr, "hf-15-"); - FillFileNameByUID(fptr,uid,"-dump",sizeof(uid)); - } - // detect blocksize from card :) + fptr += sprintf(fptr, "hf-15-"); + FillFileNameByUID(fptr,uid,"-dump",sizeof(uid)); + } + // detect blocksize from card :) - PrintAndLogEx(NORMAL, "Reading memory from tag UID " _YELLOW_(%s), sprintUID(NULL, uid)); + PrintAndLogEx(NORMAL, "Reading memory from tag UID " _YELLOW_(%s), sprintUID(NULL, uid)); - int blocknum = 0; - uint8_t *recv = NULL; + int blocknum = 0; + uint8_t *recv = NULL; - // memory. - t15memory mem[256]; + // memory. + t15memory mem[256]; - uint8_t data[256*4] = {0}; - memset(data, 0, sizeof(data)); + uint8_t data[256*4] = {0}; + memset(data, 0, sizeof(data)); - UsbCommand resp; - UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? - uint8_t *req = c.d.asBytes; - req[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; - req[1] = ISO15_CMD_READ; + UsbCommand resp; + UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? + uint8_t *req = c.d.asBytes; + req[0] = ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; + req[1] = ISO15_CMD_READ; - // copy uid to read command - memcpy(req+2, uid, sizeof(uid)); + // copy uid to read command + memcpy(req+2, uid, sizeof(uid)); - for (int retry = 0; retry < 5; retry++) { + for (int retry = 0; retry < 5; retry++) { - req[10] = blocknum; - AddCrc(req, 11); - c.arg[0] = 13; + req[10] = blocknum; + AddCrc(req, 11); + c.arg[0] = 13; - clearCommandBuffer(); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - uint8_t len = resp.arg[0]; - if ( len < 2 ) { - PrintAndLogEx(FAILED, "iso15693 card select failed"); - continue; - } + uint8_t len = resp.arg[0]; + if ( len < 2 ) { + PrintAndLogEx(FAILED, "iso15693 card select failed"); + continue; + } - recv = resp.d.asBytes; + recv = resp.d.asBytes; - if ( !CheckCrc(recv, len) ) { - PrintAndLogEx(FAILED, "crc fail"); - continue; - } + if ( !CheckCrc(recv, len) ) { + PrintAndLogEx(FAILED, "crc fail"); + continue; + } - if (recv[0] & ISO15_RES_ERROR) { - PrintAndLogEx(FAILED, "Tag returned Error %i: %s", recv[1], TagErrorStr(recv[1]) ); - break; - } + if (recv[0] & ISO15_RES_ERROR) { + PrintAndLogEx(FAILED, "Tag returned Error %i: %s", recv[1], TagErrorStr(recv[1]) ); + break; + } - mem[blocknum].lock = resp.d.asBytes[0]; - memcpy(mem[blocknum].block, resp.d.asBytes + 1, 4); - memcpy(data + (blocknum * 4), resp.d.asBytes + 1, 4); + mem[blocknum].lock = resp.d.asBytes[0]; + memcpy(mem[blocknum].block, resp.d.asBytes + 1, 4); + memcpy(data + (blocknum * 4), resp.d.asBytes + 1, 4); - retry = 0; - blocknum++; + retry = 0; + blocknum++; - printf("."); fflush(stdout); - } - } - PrintAndLogEx(NORMAL, "\n"); + printf("."); fflush(stdout); + } + } + PrintAndLogEx(NORMAL, "\n"); - PrintAndLogEx(NORMAL, "block# | data |lck| ascii"); - PrintAndLogEx(NORMAL, "---------+--------------+---+----------"); - for (int i = 0; i < blocknum; i++) { - PrintAndLogEx(NORMAL, "%3d/0x%02X | %s | %d | %s", i, i, sprint_hex(mem[i].block, 4 ), mem[i].lock, sprint_ascii(mem[i].block, 4) ); - } - PrintAndLogEx(NORMAL, "\n"); + PrintAndLogEx(NORMAL, "block# | data |lck| ascii"); + PrintAndLogEx(NORMAL, "---------+--------------+---+----------"); + for (int i = 0; i < blocknum; i++) { + PrintAndLogEx(NORMAL, "%3d/0x%02X | %s | %d | %s", i, i, sprint_hex(mem[i].block, 4 ), mem[i].lock, sprint_ascii(mem[i].block, 4) ); + } + PrintAndLogEx(NORMAL, "\n"); - size_t datalen = blocknum * 4; - saveFileEML(filename, "eml", data, datalen, 4); - saveFile(filename, "bin", data, datalen); - return 0; + size_t datalen = blocknum * 4; + saveFileEML(filename, "eml", data, datalen, 4); + saveFile(filename, "bin", data, datalen); + return 0; } int CmdHF15Restore(const char*Cmd) { - FILE *f; + FILE *f; - uint8_t uid[8]={0x00}; - char filename[FILE_PATH_SIZE] = {0x00}; - char buff[255] = {0x00}; - size_t blocksize=4; - uint8_t cmdp = 0; - char newCmdPrefix[255] = {0x00}, tmpCmd[255] = {0x00}; - char param[FILE_PATH_SIZE]=""; - char hex[255]=""; - uint8_t retries = 3, tried = 0, i = 0; - int retval=0; - size_t bytes_read; + uint8_t uid[8]={0x00}; + char filename[FILE_PATH_SIZE] = {0x00}; + char buff[255] = {0x00}; + size_t blocksize=4; + uint8_t cmdp = 0; + char newCmdPrefix[255] = {0x00}, tmpCmd[255] = {0x00}; + char param[FILE_PATH_SIZE]=""; + char hex[255]=""; + uint8_t retries = 3, tried = 0, i = 0; + int retval=0; + size_t bytes_read; - while(param_getchar(Cmd, cmdp) != 0x00) { - switch(tolower(param_getchar(Cmd, cmdp))) { - case '-': - param_getstr(Cmd, cmdp, param, sizeof(param)); - switch(param[1]) - { - case '2': - case 'o': - strncpy(newCmdPrefix, " ", sizeof(newCmdPrefix)-1); - strncat(newCmdPrefix, param, sizeof(newCmdPrefix)-1); - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%s'", param); - return usage_15_restore(); - } - break; - case 'f': - param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); - cmdp++; - break; - case 'r': - retries=param_get8ex(Cmd, cmdp+1, 3, 10); - cmdp++; - break; - case 'b': - blocksize=param_get8ex(Cmd, cmdp+1, 4, 10); - cmdp++; - break; - case 'u': - param_getstr(Cmd, cmdp+1, buff, FILE_PATH_SIZE); - cmdp++; - snprintf(filename,sizeof(filename),"hf-15-dump-%s-bin",buff); - break; - case 'h': - return usage_15_restore(); - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - return usage_15_restore(); - } - cmdp++; - } + while(param_getchar(Cmd, cmdp) != 0x00) { + switch(tolower(param_getchar(Cmd, cmdp))) { + case '-': + param_getstr(Cmd, cmdp, param, sizeof(param)); + switch(param[1]) + { + case '2': + case 'o': + strncpy(newCmdPrefix, " ", sizeof(newCmdPrefix)-1); + strncat(newCmdPrefix, param, sizeof(newCmdPrefix)-1); + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%s'", param); + return usage_15_restore(); + } + break; + case 'f': + param_getstr(Cmd, cmdp+1, filename, FILE_PATH_SIZE); + cmdp++; + break; + case 'r': + retries=param_get8ex(Cmd, cmdp+1, 3, 10); + cmdp++; + break; + case 'b': + blocksize=param_get8ex(Cmd, cmdp+1, 4, 10); + cmdp++; + break; + case 'u': + param_getstr(Cmd, cmdp+1, buff, FILE_PATH_SIZE); + cmdp++; + snprintf(filename,sizeof(filename),"hf-15-dump-%s-bin",buff); + break; + case 'h': + return usage_15_restore(); + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + return usage_15_restore(); + } + cmdp++; + } - PrintAndLogEx(INFO,"Blocksize: %u",blocksize); + PrintAndLogEx(INFO,"Blocksize: %u",blocksize); - if ( !strlen(filename)) { - PrintAndLogEx(WARNING,"Please provide a filename"); - return usage_15_restore(); - } + if ( !strlen(filename)) { + PrintAndLogEx(WARNING,"Please provide a filename"); + return usage_15_restore(); + } - if ((f = fopen(filename, "rb")) == NULL) { - PrintAndLogEx(WARNING, "Could not find file %s", filename); - return 2; - } + if ((f = fopen(filename, "rb")) == NULL) { + PrintAndLogEx(WARNING, "Could not find file %s", filename); + return 2; + } - if (!getUID(uid)) { - PrintAndLogEx(WARNING, "No tag found"); - fclose(f); - return 3; - } + if (!getUID(uid)) { + PrintAndLogEx(WARNING, "No tag found"); + fclose(f); + return 3; + } - while (1) { - tried = 0; - hex[0] = 0x00; - tmpCmd[0] = 0x00; + while (1) { + tried = 0; + hex[0] = 0x00; + tmpCmd[0] = 0x00; - bytes_read = fread( buff, 1, blocksize, f ); - if ( bytes_read == 0) { - PrintAndLogEx(SUCCESS, "File reading done `%s`", filename); - fclose(f); - return 0; - } else if ( bytes_read != blocksize) { - PrintAndLogEx(WARNING, "File reading error (%s), %u bytes read instead of %u bytes.", filename, bytes_read, blocksize); - fclose(f); - return 2; - } + bytes_read = fread( buff, 1, blocksize, f ); + if ( bytes_read == 0) { + PrintAndLogEx(SUCCESS, "File reading done `%s`", filename); + fclose(f); + return 0; + } else if ( bytes_read != blocksize) { + PrintAndLogEx(WARNING, "File reading error (%s), %u bytes read instead of %u bytes.", filename, bytes_read, blocksize); + fclose(f); + return 2; + } - for(int j=0; j < blocksize; j++) - snprintf(hex+j*2, 3, "%02X", buff[j]); + for(int j=0; j < blocksize; j++) + snprintf(hex+j*2, 3, "%02X", buff[j]); - for(int j=0; j < sizeof(uid)/sizeof(uid[0]); j++) - snprintf(buff+j*2,3,"%02X", uid[j]); + for(int j=0; j < sizeof(uid)/sizeof(uid[0]); j++) + snprintf(buff+j*2,3,"%02X", uid[j]); - //TODO: Addressed mode currently not work - //snprintf(tmpCmd, sizeof(tmpCmd), "%s %s %d %s", newCmdPrefix, buff, i, hex); - snprintf(tmpCmd, sizeof(tmpCmd), "%s u %u %s", newCmdPrefix, i, hex); - PrintAndLogEx(DEBUG, "Command to be sent| %s", tmpCmd); + //TODO: Addressed mode currently not work + //snprintf(tmpCmd, sizeof(tmpCmd), "%s %s %d %s", newCmdPrefix, buff, i, hex); + snprintf(tmpCmd, sizeof(tmpCmd), "%s u %u %s", newCmdPrefix, i, hex); + PrintAndLogEx(DEBUG, "Command to be sent| %s", tmpCmd); - for(tried=0; tried < retries; tried++) - if(!(retval = CmdHF15Write(tmpCmd))) - break; - if(tried >= retries) - return retval; + for(tried=0; tried < retries; tried++) + if(!(retval = CmdHF15Write(tmpCmd))) + break; + if(tried >= retries) + return retval; - i++; - } - fclose(f); + i++; + } + fclose(f); } int CmdHF15List(const char *Cmd) { - //PrintAndLogEx(WARNING, "Deprecated command, use 'hf list 15' instead"); - CmdTraceList("15"); - return 0; + //PrintAndLogEx(WARNING, "Deprecated command, use 'hf list 15' instead"); + CmdTraceList("15"); + return 0; } int CmdHF15Raw(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_raw(); + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_raw(); - UsbCommand resp; - UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? - int reply = 1, fast = 1, i = 0; - bool crc = false; - char buf[5] = ""; - uint8_t data[100]; - uint32_t datalen = 0, temp; + UsbCommand resp; + UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? + int reply = 1, fast = 1, i = 0; + bool crc = false; + char buf[5] = ""; + uint8_t data[100]; + uint32_t datalen = 0, temp; - // strip - while (*Cmd==' ' || *Cmd=='\t') Cmd++; + // strip + while (*Cmd==' ' || *Cmd=='\t') Cmd++; - while (Cmd[i]!='\0') { - if (Cmd[i]==' ' || Cmd[i]=='\t') { i++; continue; } - if (Cmd[i]=='-') { - switch (Cmd[i+1]) { - case 'r': - case 'R': - reply = 0; - break; - case '2': - fast = 0; - break; - case 'c': - case 'C': - crc = true; - break; - default: - PrintAndLogEx(WARNING, "Invalid option"); - return 0; - } - i+=2; - continue; - } - if ((Cmd[i]>='0' && Cmd[i]<='9') || - (Cmd[i]>='a' && Cmd[i]<='f') || - (Cmd[i]>='A' && Cmd[i]<='F') ) { - buf[strlen(buf)+1] = 0; - buf[strlen(buf)] = Cmd[i]; - i++; + while (Cmd[i]!='\0') { + if (Cmd[i]==' ' || Cmd[i]=='\t') { i++; continue; } + if (Cmd[i]=='-') { + switch (Cmd[i+1]) { + case 'r': + case 'R': + reply = 0; + break; + case '2': + fast = 0; + break; + case 'c': + case 'C': + crc = true; + break; + default: + PrintAndLogEx(WARNING, "Invalid option"); + return 0; + } + i+=2; + continue; + } + if ((Cmd[i]>='0' && Cmd[i]<='9') || + (Cmd[i]>='a' && Cmd[i]<='f') || + (Cmd[i]>='A' && Cmd[i]<='F') ) { + buf[strlen(buf)+1] = 0; + buf[strlen(buf)] = Cmd[i]; + i++; - if (strlen(buf) >= 2) { - sscanf(buf, "%x", &temp); - data[datalen] = (uint8_t)(temp & 0xff); - datalen++; - *buf = 0; - } - continue; - } - PrintAndLogEx(WARNING, "Invalid char on input"); - return 0; - } + if (strlen(buf) >= 2) { + sscanf(buf, "%x", &temp); + data[datalen] = (uint8_t)(temp & 0xff); + datalen++; + *buf = 0; + } + continue; + } + PrintAndLogEx(WARNING, "Invalid char on input"); + return 0; + } - if (crc) { - AddCrc(data, datalen); - datalen += 2; - } + if (crc) { + AddCrc(data, datalen); + datalen += 2; + } - c.arg[0] = datalen; - c.arg[1] = fast; - c.arg[2] = reply; - memcpy(c.d.asBytes, data, datalen); + c.arg[0] = datalen; + c.arg[1] = fast; + c.arg[2] = reply; + memcpy(c.d.asBytes, data, datalen); - clearCommandBuffer(); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); - if (reply) { - if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { - uint8_t len = resp.arg[0]; - PrintAndLogEx(NORMAL, "received %i octets", len); - PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) ); - } else { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - } - } - return 0; + if (reply) { + if (WaitForResponseTimeout(CMD_ACK, &resp, 2000)) { + uint8_t len = resp.arg[0]; + PrintAndLogEx(NORMAL, "received %i octets", len); + PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) ); + } else { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + } + } + return 0; } /** * parses common HF 15 CMD parameters and prepares some data structures * Parameters: - * **cmd command line + * **cmd command line */ int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd) { - int temp; - uint8_t *req = c->d.asBytes; - uint8_t uid[8] = {0x00}; - uint32_t reqlen = 0; + int temp; + uint8_t *req = c->d.asBytes; + uint8_t uid[8] = {0x00}; + uint32_t reqlen = 0; - // strip - while (**cmd==' ' || **cmd=='\t') (*cmd)++; + // strip + while (**cmd==' ' || **cmd=='\t') (*cmd)++; - if (strstr(*cmd, "-2") == *cmd) { - c->arg[1] = 0; // use 1of256 - (*cmd) += 2; - } + if (strstr(*cmd, "-2") == *cmd) { + c->arg[1] = 0; // use 1of256 + (*cmd) += 2; + } - // strip - while (**cmd==' ' || **cmd=='\t') (*cmd)++; + // strip + while (**cmd==' ' || **cmd=='\t') (*cmd)++; - if (strstr(*cmd, "-o") == *cmd) { - req[reqlen] = ISO15_REQ_OPTION; - (*cmd) += 2; - } + if (strstr(*cmd, "-o") == *cmd) { + req[reqlen] = ISO15_REQ_OPTION; + (*cmd) += 2; + } - // strip - while (**cmd == ' ' || **cmd == '\t') (*cmd)++; + // strip + while (**cmd == ' ' || **cmd == '\t') (*cmd)++; - switch (**cmd) { - case 0: - PrintAndLogEx(WARNING, "missing addr"); - return 0; - break; - case 'u': - case 'U': - // unaddressed mode may not be supported by all vendors - req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY; - req[reqlen++] = iso15cmd; - break; - case '*': - // we scan for the UID ourself - req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; - req[reqlen++] = iso15cmd; + switch (**cmd) { + case 0: + PrintAndLogEx(WARNING, "missing addr"); + return 0; + break; + case 'u': + case 'U': + // unaddressed mode may not be supported by all vendors + req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY; + req[reqlen++] = iso15cmd; + break; + case '*': + // we scan for the UID ourself + req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; + req[reqlen++] = iso15cmd; - if (!getUID(uid)) { - PrintAndLogEx(WARNING, "No tag found"); - return 0; - } - memcpy(&req[reqlen], uid, sizeof(uid)); - PrintAndLogEx(NORMAL, "Detected UID %s", sprintUID(NULL, uid)); - reqlen += sizeof(uid); - break; - default: - req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; - req[reqlen++] = iso15cmd; + if (!getUID(uid)) { + PrintAndLogEx(WARNING, "No tag found"); + return 0; + } + memcpy(&req[reqlen], uid, sizeof(uid)); + PrintAndLogEx(NORMAL, "Detected UID %s", sprintUID(NULL, uid)); + reqlen += sizeof(uid); + break; + default: + req[reqlen++] |= ISO15_REQ_SUBCARRIER_SINGLE | ISO15_REQ_DATARATE_HIGH | ISO15_REQ_NONINVENTORY | ISO15_REQ_ADDRESS; + req[reqlen++] = iso15cmd; - // parse UID - for (int i=0; i<8 && (*cmd)[i*2] && (*cmd)[i*2+1]; i++) { - sscanf((char[]){(*cmd)[i*2], (*cmd)[i*2+1],0}, "%X", &temp); - uid[7-i] = temp & 0xff; - } + // parse UID + for (int i=0; i<8 && (*cmd)[i*2] && (*cmd)[i*2+1]; i++) { + sscanf((char[]){(*cmd)[i*2], (*cmd)[i*2+1],0}, "%X", &temp); + uid[7-i] = temp & 0xff; + } - PrintAndLogEx(NORMAL, "Using UID %s", sprintUID(NULL, uid)); - memcpy(&req[reqlen], uid, sizeof(uid)); - reqlen += sizeof(uid); - break; - } - // skip to next space - while (**cmd!=' ' && **cmd!='\t') (*cmd)++; - // skip over the space - while (**cmd==' ' || **cmd=='\t') (*cmd)++; + PrintAndLogEx(NORMAL, "Using UID %s", sprintUID(NULL, uid)); + memcpy(&req[reqlen], uid, sizeof(uid)); + reqlen += sizeof(uid); + break; + } + // skip to next space + while (**cmd!=' ' && **cmd!='\t') (*cmd)++; + // skip over the space + while (**cmd==' ' || **cmd=='\t') (*cmd)++; - c->arg[0] = reqlen; - return 1; + c->arg[0] = reqlen; + return 1; } /** @@ -1047,81 +1047,81 @@ int prepareHF15Cmd(char **cmd, UsbCommand *c, uint8_t iso15cmd) { */ int CmdHF15Readmulti(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_readmulti(); + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_readmulti(); - UsbCommand resp; - uint8_t *recv; - UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? - uint8_t *req = c.d.asBytes; - int reqlen = 0; - uint8_t pagenum, pagecount; - char cmdbuf[100]; - char *cmd = cmdbuf; - strncpy(cmd, Cmd, 99); + UsbCommand resp; + uint8_t *recv; + UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? + uint8_t *req = c.d.asBytes; + int reqlen = 0; + uint8_t pagenum, pagecount; + char cmdbuf[100]; + char *cmd = cmdbuf; + strncpy(cmd, Cmd, 99); - if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_READMULTI) ) - return 0; + if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_READMULTI) ) + return 0; - // add OPTION flag, in order to get lock-info - req[0] |= ISO15_REQ_OPTION; + // add OPTION flag, in order to get lock-info + req[0] |= ISO15_REQ_OPTION; - reqlen = c.arg[0]; + reqlen = c.arg[0]; - // decimal - pagenum = param_get8ex(cmd, 0, 0, 10); - pagecount = param_get8ex(cmd, 1, 0, 10); + // decimal + pagenum = param_get8ex(cmd, 0, 0, 10); + pagecount = param_get8ex(cmd, 1, 0, 10); - //PrintAndLogEx(NORMAL, "ice %d %d\n", pagenum, pagecount); + //PrintAndLogEx(NORMAL, "ice %d %d\n", pagenum, pagecount); - // 0 means 1 page, - // 1 means 2 pages, ... - if (pagecount > 0) pagecount--; + // 0 means 1 page, + // 1 means 2 pages, ... + if (pagecount > 0) pagecount--; - req[reqlen++] = pagenum; - req[reqlen++] = pagecount; - AddCrc(req, reqlen); - c.arg[0] = reqlen+2; + req[reqlen++] = pagenum; + req[reqlen++] = pagecount; + AddCrc(req, reqlen); + c.arg[0] = reqlen+2; - clearCommandBuffer(); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - PrintAndLogEx(FAILED, "iso15693 card select failed"); - return 1; - } + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + PrintAndLogEx(FAILED, "iso15693 card select failed"); + return 1; + } - uint32_t status = resp.arg[0]; - if ( status < 2 ) { - PrintAndLogEx(FAILED, "iso15693 card select failed"); - return 1; - } + uint32_t status = resp.arg[0]; + if ( status < 2 ) { + PrintAndLogEx(FAILED, "iso15693 card select failed"); + return 1; + } - recv = resp.d.asBytes; + recv = resp.d.asBytes; - if (!CheckCrc(recv, status)) { - PrintAndLogEx(FAILED, "CRC failed"); - return 2; - } + if (!CheckCrc(recv, status)) { + PrintAndLogEx(FAILED, "CRC failed"); + return 2; + } - if ( recv[0] & ISO15_RES_ERROR ) { - PrintAndLogEx(FAILED, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; - } + if ( recv[0] & ISO15_RES_ERROR ) { + PrintAndLogEx(FAILED, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + return 3; + } - int start = 1; // skip status byte - int stop = (pagecount+1) * 5; - int currblock = pagenum; - // print response - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "block# | data |lck| ascii"); - PrintAndLogEx(NORMAL, "---------+--------------+---+----------"); - for (int i = start; i < stop; i += 5) { - PrintAndLogEx(NORMAL, "%3d/0x%02X | %s | %d | %s", currblock, currblock, sprint_hex(recv+i+1, 4 ), recv[i], sprint_ascii(recv+i+1, 4) ); - currblock++; - } + int start = 1; // skip status byte + int stop = (pagecount+1) * 5; + int currblock = pagenum; + // print response + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "block# | data |lck| ascii"); + PrintAndLogEx(NORMAL, "---------+--------------+---+----------"); + for (int i = start; i < stop; i += 5) { + PrintAndLogEx(NORMAL, "%3d/0x%02X | %s | %d | %s", currblock, currblock, sprint_hex(recv+i+1, 4 ), recv[i], sprint_ascii(recv+i+1, 4) ); + currblock++; + } - return 0; + return 0; } /** @@ -1130,72 +1130,72 @@ int CmdHF15Readmulti(const char *Cmd) { */ int CmdHF15Read(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_read(); + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_read(); - UsbCommand resp; - uint8_t *recv; + UsbCommand resp; + uint8_t *recv; - // UsbCommand arg: len, speed, recv? - // arg0 (datalen, cmd len? .arg0 == crc?) - // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 ) - // arg2 (recv == 1 == expect a response) - UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; - uint8_t *req = c.d.asBytes; - int reqlen = 0, blocknum; - char cmdbuf[100]; - char *cmd = cmdbuf; - strncpy(cmd, Cmd, 99); + // UsbCommand arg: len, speed, recv? + // arg0 (datalen, cmd len? .arg0 == crc?) + // arg1 (speed == 0 == 1 of 256, == 1 == 1 of 4 ) + // arg2 (recv == 1 == expect a response) + UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; + uint8_t *req = c.d.asBytes; + int reqlen = 0, blocknum; + char cmdbuf[100]; + char *cmd = cmdbuf; + strncpy(cmd, Cmd, 99); - if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_READ) ) - return 0; + if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_READ) ) + return 0; - // add OPTION flag, in order to get lock-info - req[0] |= ISO15_REQ_OPTION; + // add OPTION flag, in order to get lock-info + req[0] |= ISO15_REQ_OPTION; - reqlen = c.arg[0]; + reqlen = c.arg[0]; - blocknum = strtol(cmd, NULL, 0); + blocknum = strtol(cmd, NULL, 0); - req[reqlen++] = (uint8_t)blocknum; + req[reqlen++] = (uint8_t)blocknum; - AddCrc(req, reqlen); + AddCrc(req, reqlen); - c.arg[0] = reqlen+2; + c.arg[0] = reqlen+2; - clearCommandBuffer(); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - PrintAndLogEx(NORMAL, "iso15693 card select failed"); - return 1; - } + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + PrintAndLogEx(NORMAL, "iso15693 card select failed"); + return 1; + } - uint32_t status = resp.arg[0]; - if ( status < 2 ) { - PrintAndLogEx(NORMAL, "iso15693 card select failed"); - return 1; - } + uint32_t status = resp.arg[0]; + if ( status < 2 ) { + PrintAndLogEx(NORMAL, "iso15693 card select failed"); + return 1; + } - recv = resp.d.asBytes; + recv = resp.d.asBytes; - if ( !CheckCrc(recv, status) ) { - PrintAndLogEx(NORMAL, "CRC failed"); - return 2; - } + if ( !CheckCrc(recv, status) ) { + PrintAndLogEx(NORMAL, "CRC failed"); + return 2; + } - if ( recv[0] & ISO15_RES_ERROR ) { - PrintAndLogEx(WARNING, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; - } + if ( recv[0] & ISO15_RES_ERROR ) { + PrintAndLogEx(WARNING, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + return 3; + } - // print response - PrintAndLogEx(NORMAL, ""); - PrintAndLogEx(NORMAL, "block #%3d |lck| ascii", blocknum ); - PrintAndLogEx(NORMAL, "------------+---+------" ); - PrintAndLogEx(NORMAL, "%s| %d | %s", sprint_hex(recv+2, status-4), recv[1], sprint_ascii(recv+2, status-4) ); - PrintAndLogEx(NORMAL, ""); - return 0; + // print response + PrintAndLogEx(NORMAL, ""); + PrintAndLogEx(NORMAL, "block #%3d |lck| ascii", blocknum ); + PrintAndLogEx(NORMAL, "------------+---+------" ); + PrintAndLogEx(NORMAL, "%s| %d | %s", sprint_hex(recv+2, status-4), recv[1], sprint_ascii(recv+2, status-4) ); + PrintAndLogEx(NORMAL, ""); + return 0; } /** @@ -1204,105 +1204,105 @@ int CmdHF15Read(const char *Cmd) { */ int CmdHF15Write(const char *Cmd) { - char cmdp = param_getchar(Cmd, 0); - if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_write(); + char cmdp = param_getchar(Cmd, 0); + if (strlen(Cmd)<3 || cmdp == 'h' || cmdp == 'H') return usage_15_write(); - UsbCommand resp; - uint8_t *recv; - UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? - uint8_t *req = c.d.asBytes; - int reqlen = 0, pagenum, temp; - char cmdbuf[100]; - char *cmd = cmdbuf; - char *cmd2; + UsbCommand resp; + uint8_t *recv; + UsbCommand c = {CMD_ISO_15693_COMMAND, {0, 1, 1}}; // len,speed,recv? + uint8_t *req = c.d.asBytes; + int reqlen = 0, pagenum, temp; + char cmdbuf[100]; + char *cmd = cmdbuf; + char *cmd2; - strncpy(cmd, Cmd, 99); + strncpy(cmd, Cmd, 99); - if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_WRITE) ) - return 0; + if ( !prepareHF15Cmd(&cmd, &c, ISO15_CMD_WRITE) ) + return 0; - reqlen = c.arg[0]; + reqlen = c.arg[0]; - // *cmd -> page num ; *cmd2 -> data - cmd2=cmd; - while (*cmd2!=' ' && *cmd2!='\t' && *cmd2) cmd2++; - *cmd2 = 0; - cmd2++; + // *cmd -> page num ; *cmd2 -> data + cmd2=cmd; + while (*cmd2!=' ' && *cmd2!='\t' && *cmd2) cmd2++; + *cmd2 = 0; + cmd2++; - pagenum = strtol(cmd, NULL, 0); + pagenum = strtol(cmd, NULL, 0); - req[reqlen++] = (uint8_t)pagenum; + req[reqlen++] = (uint8_t)pagenum; - while (cmd2[0] && cmd2[1]) { // hexdata, read by 2 hexchars - if (*cmd2==' ') { - cmd2++; - continue; - } - sscanf((char[]){cmd2[0],cmd2[1],0},"%X",&temp); - req[reqlen++]=temp & 0xff; - cmd2+=2; - } - AddCrc(req, reqlen); - c.arg[0] = reqlen+2; + while (cmd2[0] && cmd2[1]) { // hexdata, read by 2 hexchars + if (*cmd2==' ') { + cmd2++; + continue; + } + sscanf((char[]){cmd2[0],cmd2[1],0},"%X",&temp); + req[reqlen++]=temp & 0xff; + cmd2+=2; + } + AddCrc(req, reqlen); + c.arg[0] = reqlen+2; - PrintAndLogEx(NORMAL, "iso15693 writing to page %02d (0x%02X) | data ", pagenum, pagenum); + PrintAndLogEx(NORMAL, "iso15693 writing to page %02d (0x%02X) | data ", pagenum, pagenum); - clearCommandBuffer(); - SendCommand(&c); + clearCommandBuffer(); + SendCommand(&c); - if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - PrintAndLogEx(FAILED, "iso15693 card timeout, data may be written anyway"); - return 1; - } + if ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + PrintAndLogEx(FAILED, "iso15693 card timeout, data may be written anyway"); + return 1; + } - uint32_t status = resp.arg[0]; - if ( status < 2 ) { - PrintAndLogEx(FAILED, "iso15693 card select failed"); - return 1; - } + uint32_t status = resp.arg[0]; + if ( status < 2 ) { + PrintAndLogEx(FAILED, "iso15693 card select failed"); + return 1; + } - recv = resp.d.asBytes; + recv = resp.d.asBytes; - if ( !CheckCrc(recv, status) ) { - PrintAndLogEx(FAILED, "CRC failed"); - return 2; - } + if ( !CheckCrc(recv, status) ) { + PrintAndLogEx(FAILED, "CRC failed"); + return 2; + } - if ( recv[0] & ISO15_RES_ERROR ) { - PrintAndLogEx(NORMAL, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); - return 3; - } + if ( recv[0] & ISO15_RES_ERROR ) { + PrintAndLogEx(NORMAL, "iso15693 card returned error %i: %s", recv[0], TagErrorStr(recv[0])); + return 3; + } - PrintAndLogEx(NORMAL, "OK"); - return 0; + PrintAndLogEx(NORMAL, "OK"); + return 0; } static command_t CommandTable15[] = { - {"help", CmdHF15Help, 1, "This help"}, - {"demod", CmdHF15Demod, 1, "Demodulate ISO15693 from tag"}, - {"dump", CmdHF15Dump, 0, "Read all memory pages of an ISO15693 tag, save to file"}, - {"findafi", CmdHF15Afi, 0, "Brute force AFI of an ISO15693 tag"}, - {"info", CmdHF15Info, 0, "Tag information"}, - {"list", CmdHF15List, 0, "[Deprecated] List ISO15693 history"}, - {"raw", CmdHF15Raw, 0, "Send raw hex data to tag"}, - {"reader", CmdHF15Reader, 0, "Act like an ISO15693 reader"}, - {"record", CmdHF15Record, 0, "Record Samples (ISO15693)"}, - {"restore", CmdHF15Restore, 0, "Restore from file to all memory pages of an ISO15693 tag"}, - {"sim", CmdHF15Sim, 0, "Fake an ISO15693 tag"}, - {"samples", CmdHF15Samples, 0, "Acquire Samples as Reader (enables carrier, sends inquiry)"}, - {"read", CmdHF15Read, 0, "Read a block"}, - {"write", CmdHF15Write, 0, "Write a block"}, - {"readmulti", CmdHF15Readmulti, 0, "Reads multiple Blocks"}, - {NULL, NULL, 0, NULL} + {"help", CmdHF15Help, 1, "This help"}, + {"demod", CmdHF15Demod, 1, "Demodulate ISO15693 from tag"}, + {"dump", CmdHF15Dump, 0, "Read all memory pages of an ISO15693 tag, save to file"}, + {"findafi", CmdHF15Afi, 0, "Brute force AFI of an ISO15693 tag"}, + {"info", CmdHF15Info, 0, "Tag information"}, + {"list", CmdHF15List, 0, "[Deprecated] List ISO15693 history"}, + {"raw", CmdHF15Raw, 0, "Send raw hex data to tag"}, + {"reader", CmdHF15Reader, 0, "Act like an ISO15693 reader"}, + {"record", CmdHF15Record, 0, "Record Samples (ISO15693)"}, + {"restore", CmdHF15Restore, 0, "Restore from file to all memory pages of an ISO15693 tag"}, + {"sim", CmdHF15Sim, 0, "Fake an ISO15693 tag"}, + {"samples", CmdHF15Samples, 0, "Acquire Samples as Reader (enables carrier, sends inquiry)"}, + {"read", CmdHF15Read, 0, "Read a block"}, + {"write", CmdHF15Write, 0, "Write a block"}, + {"readmulti", CmdHF15Readmulti, 0, "Reads multiple Blocks"}, + {NULL, NULL, 0, NULL} }; int CmdHF15(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable15, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable15, Cmd); + return 0; } int CmdHF15Help(const char *Cmd) { - CmdsHelp(CommandTable15); - return 0; + CmdsHelp(CommandTable15); + return 0; } \ No newline at end of file diff --git a/client/cmdhf15.h b/client/cmdhf15.h index 2908a9aab..38f4b7801 100644 --- a/client/cmdhf15.h +++ b/client/cmdhf15.h @@ -21,10 +21,10 @@ #include "ui.h" #include "util.h" #include "cmdparser.h" -#include "crc16.h" // iso15 crc +#include "crc16.h" // iso15 crc #include "cmdmain.h" -#include "cmddata.h" // getsamples -#include "loclass/fileutils.h" // savefileEML +#include "cmddata.h" // getsamples +#include "loclass/fileutils.h" // savefileEML int CmdHF15(const char *Cmd); diff --git a/client/cmdhfepa.c b/client/cmdhfepa.c index 4e7510fe0..be8771b86 100644 --- a/client/cmdhfepa.c +++ b/client/cmdhfepa.c @@ -14,168 +14,168 @@ static int CmdHelp(const char *Cmd); // Perform (part of) the PACE protocol int CmdHFEPACollectPACENonces(const char *Cmd) { - // requested nonce size - uint32_t m = 0; - // requested number of Nonces - uint32_t n = 0; - // delay between requests - uint32_t d = 0; + // requested nonce size + uint32_t m = 0; + // requested number of Nonces + uint32_t n = 0; + // delay between requests + uint32_t d = 0; - sscanf(Cmd, "%u %u %u", &m, &n, &d); + sscanf(Cmd, "%u %u %u", &m, &n, &d); - // values are expected to be > 0 - m = m > 0 ? m : 1; - n = n > 0 ? n : 1; + // values are expected to be > 0 + m = m > 0 ? m : 1; + n = n > 0 ? n : 1; - PrintAndLogEx(NORMAL, "Collecting %u %u byte nonces", n, m); - PrintAndLogEx(NORMAL, "Start: %" PRIu64, msclock()/1000); - // repeat n times - for (uint32_t i = 0; i < n; i++) { - // execute PACE - UsbCommand c = {CMD_EPA_PACE_COLLECT_NONCE, {(int)m, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - WaitForResponse(CMD_ACK,&resp); + PrintAndLogEx(NORMAL, "Collecting %u %u byte nonces", n, m); + PrintAndLogEx(NORMAL, "Start: %" PRIu64, msclock()/1000); + // repeat n times + for (uint32_t i = 0; i < n; i++) { + // execute PACE + UsbCommand c = {CMD_EPA_PACE_COLLECT_NONCE, {(int)m, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + WaitForResponse(CMD_ACK,&resp); - // check if command failed - if (resp.arg[0] != 0) { - PrintAndLogEx(FAILED, "Error in step %d, Return code: %d",resp.arg[0],(int)resp.arg[1]); - } else { - size_t nonce_length = resp.arg[1]; - char *nonce = (char *) calloc(2 * nonce_length + 1, sizeof(uint8_t)); - for(int j = 0; j < nonce_length; j++) { - sprintf(nonce + (2 * j), "%02X", resp.d.asBytes[j]); - } - // print nonce - PrintAndLogEx(NORMAL, "Length: %d, Nonce: %s", nonce_length, nonce); - free(nonce); - } - if (i < n - 1) { - sleep(d); - } - } - PrintAndLogEx(NORMAL, "End: %" PRIu64, msclock()/1000); - return 1; + // check if command failed + if (resp.arg[0] != 0) { + PrintAndLogEx(FAILED, "Error in step %d, Return code: %d",resp.arg[0],(int)resp.arg[1]); + } else { + size_t nonce_length = resp.arg[1]; + char *nonce = (char *) calloc(2 * nonce_length + 1, sizeof(uint8_t)); + for(int j = 0; j < nonce_length; j++) { + sprintf(nonce + (2 * j), "%02X", resp.d.asBytes[j]); + } + // print nonce + PrintAndLogEx(NORMAL, "Length: %d, Nonce: %s", nonce_length, nonce); + free(nonce); + } + if (i < n - 1) { + sleep(d); + } + } + PrintAndLogEx(NORMAL, "End: %" PRIu64, msclock()/1000); + return 1; } // perform the PACE protocol by replaying APDUs int CmdHFEPAPACEReplay(const char *Cmd) { - // the 4 APDUs which are replayed + their lengths - uint8_t msesa_apdu[41], gn_apdu[8], map_apdu[75]; - uint8_t pka_apdu[75], ma_apdu[18], apdu_lengths[5] = {0}; - // pointers to the arrays to be able to iterate - uint8_t *apdus[] = {msesa_apdu, gn_apdu, map_apdu, pka_apdu, ma_apdu}; + // the 4 APDUs which are replayed + their lengths + uint8_t msesa_apdu[41], gn_apdu[8], map_apdu[75]; + uint8_t pka_apdu[75], ma_apdu[18], apdu_lengths[5] = {0}; + // pointers to the arrays to be able to iterate + uint8_t *apdus[] = {msesa_apdu, gn_apdu, map_apdu, pka_apdu, ma_apdu}; - // usage message - static const char *usage_msg = - "Please specify 5 APDUs separated by spaces. " - "Example:\n preplay 0022C1A4 1068000000 1086000002 1234ABCDEF 1A2B3C4D"; + // usage message + static const char *usage_msg = + "Please specify 5 APDUs separated by spaces. " + "Example:\n preplay 0022C1A4 1068000000 1086000002 1234ABCDEF 1A2B3C4D"; - // Proxmark response - UsbCommand resp; + // Proxmark response + UsbCommand resp; - int skip = 0, skip_add = 0, scan_return = 0; - // for each APDU - for (int i = 0; i < sizeof(apdu_lengths); i++) { - // scan to next space or end of string - while (Cmd[skip] != ' ' && Cmd[skip] != '\0') { - // convert - scan_return = sscanf(Cmd + skip, "%2X%n", - (unsigned int *) (apdus[i] + apdu_lengths[i]), - &skip_add); - if (scan_return < 1) { - PrintAndLogEx(NORMAL, (char *)usage_msg); - PrintAndLogEx(WARNING, "Not enough APDUs! Try again!"); - return 0; - } - skip += skip_add; + int skip = 0, skip_add = 0, scan_return = 0; + // for each APDU + for (int i = 0; i < sizeof(apdu_lengths); i++) { + // scan to next space or end of string + while (Cmd[skip] != ' ' && Cmd[skip] != '\0') { + // convert + scan_return = sscanf(Cmd + skip, "%2X%n", + (unsigned int *) (apdus[i] + apdu_lengths[i]), + &skip_add); + if (scan_return < 1) { + PrintAndLogEx(NORMAL, (char *)usage_msg); + PrintAndLogEx(WARNING, "Not enough APDUs! Try again!"); + return 0; + } + skip += skip_add; apdu_lengths[i]++; - } + } - // break on EOF - if (Cmd[skip] == '\0') { - if (i < sizeof(apdu_lengths) - 1) { + // break on EOF + if (Cmd[skip] == '\0') { + if (i < sizeof(apdu_lengths) - 1) { - PrintAndLogEx(NORMAL, (char *)usage_msg); - return 0; - } - break; - } - // skip the space - skip++; - } + PrintAndLogEx(NORMAL, (char *)usage_msg); + return 0; + } + break; + } + // skip the space + skip++; + } - // transfer the APDUs to the Proxmark - UsbCommand usb_cmd; - usb_cmd.cmd = CMD_EPA_PACE_REPLAY; - for (int i = 0; i < sizeof(apdu_lengths); i++) { - // APDU number - usb_cmd.arg[0] = i + 1; - // transfer the APDU in several parts if necessary - for (int j = 0; j * sizeof(usb_cmd.d.asBytes) < apdu_lengths[i]; j++) { - // offset into the APDU - usb_cmd.arg[1] = j * sizeof(usb_cmd.d.asBytes); - // amount of data in this packet - int packet_length = apdu_lengths[i] - (j * sizeof(usb_cmd.d.asBytes)); - if (packet_length > sizeof(usb_cmd.d.asBytes)) { - packet_length = sizeof(usb_cmd.d.asBytes); - } - usb_cmd.arg[2] = packet_length; + // transfer the APDUs to the Proxmark + UsbCommand usb_cmd; + usb_cmd.cmd = CMD_EPA_PACE_REPLAY; + for (int i = 0; i < sizeof(apdu_lengths); i++) { + // APDU number + usb_cmd.arg[0] = i + 1; + // transfer the APDU in several parts if necessary + for (int j = 0; j * sizeof(usb_cmd.d.asBytes) < apdu_lengths[i]; j++) { + // offset into the APDU + usb_cmd.arg[1] = j * sizeof(usb_cmd.d.asBytes); + // amount of data in this packet + int packet_length = apdu_lengths[i] - (j * sizeof(usb_cmd.d.asBytes)); + if (packet_length > sizeof(usb_cmd.d.asBytes)) { + packet_length = sizeof(usb_cmd.d.asBytes); + } + usb_cmd.arg[2] = packet_length; - memcpy(usb_cmd.d.asBytes, // + (j * sizeof(usb_cmd.d.asBytes)), - apdus[i] + (j * sizeof(usb_cmd.d.asBytes)), - packet_length); + memcpy(usb_cmd.d.asBytes, // + (j * sizeof(usb_cmd.d.asBytes)), + apdus[i] + (j * sizeof(usb_cmd.d.asBytes)), + packet_length); - clearCommandBuffer(); - SendCommand(&usb_cmd); - WaitForResponse(CMD_ACK, &resp); - if (resp.arg[0] != 0) { - PrintAndLogEx(WARNING, "Transfer of APDU #%d Part %d failed!", i, j); - return 0; - } - } - } + clearCommandBuffer(); + SendCommand(&usb_cmd); + WaitForResponse(CMD_ACK, &resp); + if (resp.arg[0] != 0) { + PrintAndLogEx(WARNING, "Transfer of APDU #%d Part %d failed!", i, j); + return 0; + } + } + } - // now perform the replay - usb_cmd.arg[0] = 0; - clearCommandBuffer(); - SendCommand(&usb_cmd); - WaitForResponse(CMD_ACK, &resp); - if (resp.arg[0] != 0) { - PrintAndLogEx(NORMAL, "\nPACE replay failed in step %u!", (uint32_t)resp.arg[0]); - PrintAndLogEx(NORMAL, "Measured times:"); - PrintAndLogEx(NORMAL, "MSE Set AT: %u us", resp.d.asDwords[0]); - PrintAndLogEx(NORMAL, "GA Get Nonce: %u us", resp.d.asDwords[1]); - PrintAndLogEx(NORMAL, "GA Map Nonce: %u us", resp.d.asDwords[2]); - PrintAndLogEx(NORMAL, "GA Perform Key Agreement: %u us", resp.d.asDwords[3]); - PrintAndLogEx(NORMAL, "GA Mutual Authenticate: %u us", resp.d.asDwords[4]); - } else { - PrintAndLogEx(NORMAL, "PACE replay successfull!"); - PrintAndLogEx(NORMAL, "MSE Set AT: %u us", resp.d.asDwords[0]); - PrintAndLogEx(NORMAL, "GA Get Nonce: %u us", resp.d.asDwords[1]); - PrintAndLogEx(NORMAL, "GA Map Nonce: %u us", resp.d.asDwords[2]); - PrintAndLogEx(NORMAL, "GA Perform Key Agreement: %u us", resp.d.asDwords[3]); - PrintAndLogEx(NORMAL, "GA Mutual Authenticate: %u us", resp.d.asDwords[4]); - } - return 1; + // now perform the replay + usb_cmd.arg[0] = 0; + clearCommandBuffer(); + SendCommand(&usb_cmd); + WaitForResponse(CMD_ACK, &resp); + if (resp.arg[0] != 0) { + PrintAndLogEx(NORMAL, "\nPACE replay failed in step %u!", (uint32_t)resp.arg[0]); + PrintAndLogEx(NORMAL, "Measured times:"); + PrintAndLogEx(NORMAL, "MSE Set AT: %u us", resp.d.asDwords[0]); + PrintAndLogEx(NORMAL, "GA Get Nonce: %u us", resp.d.asDwords[1]); + PrintAndLogEx(NORMAL, "GA Map Nonce: %u us", resp.d.asDwords[2]); + PrintAndLogEx(NORMAL, "GA Perform Key Agreement: %u us", resp.d.asDwords[3]); + PrintAndLogEx(NORMAL, "GA Mutual Authenticate: %u us", resp.d.asDwords[4]); + } else { + PrintAndLogEx(NORMAL, "PACE replay successfull!"); + PrintAndLogEx(NORMAL, "MSE Set AT: %u us", resp.d.asDwords[0]); + PrintAndLogEx(NORMAL, "GA Get Nonce: %u us", resp.d.asDwords[1]); + PrintAndLogEx(NORMAL, "GA Map Nonce: %u us", resp.d.asDwords[2]); + PrintAndLogEx(NORMAL, "GA Perform Key Agreement: %u us", resp.d.asDwords[3]); + PrintAndLogEx(NORMAL, "GA Mutual Authenticate: %u us", resp.d.asDwords[4]); + } + return 1; } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"cnonces", CmdHFEPACollectPACENonces, 0, " Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses"}, - {"preplay", CmdHFEPAPACEReplay, 0, " Perform PACE protocol by replaying given APDUs"}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help"}, + {"cnonces", CmdHFEPACollectPACENonces, 0, " Acquire n>0 encrypted PACE nonces of size m>0 with d sec pauses"}, + {"preplay", CmdHFEPAPACEReplay, 0, " Perform PACE protocol by replaying given APDUs"}, + {NULL, NULL, 0, NULL} }; int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } int CmdHFEPA(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } \ No newline at end of file diff --git a/client/cmdhffelica.c b/client/cmdhffelica.c index 7a00c2490..615f51049 100644 --- a/client/cmdhffelica.c +++ b/client/cmdhffelica.c @@ -12,406 +12,406 @@ static int CmdHelp(const char *Cmd); int usage_hf_felica_sim(void) { - PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa tag \n"); - PrintAndLogEx(NORMAL, "Usage: hf felica sim [h] t [v]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " t : 1 = FeliCa"); - PrintAndLogEx(NORMAL, " : 2 = FeliCaLiteS"); - PrintAndLogEx(NORMAL, " v : (Optional) Verbose"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf felica sim t 1 "); - return 0; + PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa tag \n"); + PrintAndLogEx(NORMAL, "Usage: hf felica sim [h] t [v]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " t : 1 = FeliCa"); + PrintAndLogEx(NORMAL, " : 2 = FeliCaLiteS"); + PrintAndLogEx(NORMAL, " v : (Optional) Verbose"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf felica sim t 1 "); + return 0; } int usage_hf_felica_sniff(void){ - PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer."); - PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list felica'"); - PrintAndLogEx(NORMAL, "Usage: hf felica sniff "); - PrintAndLogEx(NORMAL, " s samples to skip (decimal)"); - PrintAndLogEx(NORMAL, " t triggers to skip (decimal)"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf felica sniff s 1000"); - return 0; + PrintAndLogEx(NORMAL, "It get data from the field and saves it into command buffer."); + PrintAndLogEx(NORMAL, "Buffer accessible from command 'hf list felica'"); + PrintAndLogEx(NORMAL, "Usage: hf felica sniff "); + PrintAndLogEx(NORMAL, " s samples to skip (decimal)"); + PrintAndLogEx(NORMAL, " t triggers to skip (decimal)"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf felica sniff s 1000"); + return 0; } int usage_hf_felica_simlite(void) { - PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa Lite tag \n"); - PrintAndLogEx(NORMAL, "Usage: hf felica litesim [h] u "); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, " uid : UID in hexsymbol"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf felica litesim 11223344556677"); - return 0; + PrintAndLogEx(NORMAL, "\n Emulating ISO/18092 FeliCa Lite tag \n"); + PrintAndLogEx(NORMAL, "Usage: hf felica litesim [h] u "); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, " uid : UID in hexsymbol"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf felica litesim 11223344556677"); + return 0; } int usage_hf_felica_dumplite(void) { - PrintAndLogEx(NORMAL, "\n Dump ISO/18092 FeliCa Lite tag \n"); - PrintAndLogEx(NORMAL, "press button to abort run, otherwise it will loop for 200sec."); - PrintAndLogEx(NORMAL, "Usage: hf felica litedump [h]"); - PrintAndLogEx(NORMAL, "Options:"); - PrintAndLogEx(NORMAL, " h : This help"); - PrintAndLogEx(NORMAL, "Examples:"); - PrintAndLogEx(NORMAL, " hf felica litedump"); - return 0; + PrintAndLogEx(NORMAL, "\n Dump ISO/18092 FeliCa Lite tag \n"); + PrintAndLogEx(NORMAL, "press button to abort run, otherwise it will loop for 200sec."); + PrintAndLogEx(NORMAL, "Usage: hf felica litedump [h]"); + PrintAndLogEx(NORMAL, "Options:"); + PrintAndLogEx(NORMAL, " h : This help"); + PrintAndLogEx(NORMAL, "Examples:"); + PrintAndLogEx(NORMAL, " hf felica litedump"); + return 0; } int usage_hf_felica_raw(void){ - PrintAndLogEx(NORMAL, "Usage: hf felica raw [-h] [-r] [-c] [-p] [-a] <0A 0B 0C ... hex>"); - PrintAndLogEx(NORMAL, " -h this help"); - PrintAndLogEx(NORMAL, " -r do not read response"); - PrintAndLogEx(NORMAL, " -c calculate and append CRC"); - PrintAndLogEx(NORMAL, " -p leave the signal field ON after receive"); - PrintAndLogEx(NORMAL, " -a active signal field ON without select"); - PrintAndLogEx(NORMAL, " -s active signal field ON with select"); - return 0; + PrintAndLogEx(NORMAL, "Usage: hf felica raw [-h] [-r] [-c] [-p] [-a] <0A 0B 0C ... hex>"); + PrintAndLogEx(NORMAL, " -h this help"); + PrintAndLogEx(NORMAL, " -r do not read response"); + PrintAndLogEx(NORMAL, " -c calculate and append CRC"); + PrintAndLogEx(NORMAL, " -p leave the signal field ON after receive"); + PrintAndLogEx(NORMAL, " -a active signal field ON without select"); + PrintAndLogEx(NORMAL, " -s active signal field ON with select"); + return 0; } int CmdHFFelicaList(const char *Cmd) { - //PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list felica' instead"); - CmdTraceList("felica"); - return 0; + //PrintAndLogEx(NORMAL, "Deprecated command, use 'hf list felica' instead"); + CmdTraceList("felica"); + return 0; } int CmdHFFelicaReader(const char *Cmd) { - bool silent = (Cmd[0] == 's' || Cmd[0] == 'S'); - //UsbCommand cDisconnect = {CMD_FELICA_COMMAND, {0,0,0}}; - UsbCommand c = {CMD_FELICA_COMMAND, {FELICA_CONNECT, 0, 0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; - if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { - if (!silent) PrintAndLogEx(WARNING, "FeliCa card select failed"); - //SendCommand(&cDisconnect); - return 0; - } + bool silent = (Cmd[0] == 's' || Cmd[0] == 'S'); + //UsbCommand cDisconnect = {CMD_FELICA_COMMAND, {0,0,0}}; + UsbCommand c = {CMD_FELICA_COMMAND, {FELICA_CONNECT, 0, 0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; + if (!WaitForResponseTimeout(CMD_ACK, &resp, 2500)) { + if (!silent) PrintAndLogEx(WARNING, "FeliCa card select failed"); + //SendCommand(&cDisconnect); + return 0; + } - felica_card_select_t card; - memcpy(&card, (felica_card_select_t *)resp.d.asBytes, sizeof(felica_card_select_t)); - uint64_t status = resp.arg[0]; + felica_card_select_t card; + memcpy(&card, (felica_card_select_t *)resp.d.asBytes, sizeof(felica_card_select_t)); + uint64_t status = resp.arg[0]; - switch(status) { - case 1: { - if (!silent) - PrintAndLogEx(WARNING, "card timeout"); - break; - } - case 2: { - if (!silent) - PrintAndLogEx(WARNING, "card answered wrong"); - break; - } - case 3: { - if (!silent) - PrintAndLogEx(WARNING, "CRC check failed"); - break; - } - case 0: { - PrintAndLogEx(SUCCESS, "FeliCa tag info"); + switch(status) { + case 1: { + if (!silent) + PrintAndLogEx(WARNING, "card timeout"); + break; + } + case 2: { + if (!silent) + PrintAndLogEx(WARNING, "card answered wrong"); + break; + } + case 3: { + if (!silent) + PrintAndLogEx(WARNING, "CRC check failed"); + break; + } + case 0: { + PrintAndLogEx(SUCCESS, "FeliCa tag info"); - PrintAndLogEx(NORMAL, "IDm %s", sprint_hex(card.IDm, sizeof(card.IDm))); - PrintAndLogEx(NORMAL, " - CODE %s", sprint_hex(card.code, sizeof(card.code))); - PrintAndLogEx(NORMAL, " - NFCID2 %s", sprint_hex(card.uid, sizeof(card.uid))); + PrintAndLogEx(NORMAL, "IDm %s", sprint_hex(card.IDm, sizeof(card.IDm))); + PrintAndLogEx(NORMAL, " - CODE %s", sprint_hex(card.code, sizeof(card.code))); + PrintAndLogEx(NORMAL, " - NFCID2 %s", sprint_hex(card.uid, sizeof(card.uid))); - PrintAndLogEx(NORMAL, "Parameter (PAD) | %s", sprint_hex(card.PMm, sizeof(card.PMm))); - PrintAndLogEx(NORMAL, " - IC CODE %s", sprint_hex(card.iccode, sizeof(card.iccode))); - PrintAndLogEx(NORMAL, " - MRT %s", sprint_hex(card.mrt, sizeof(card.mrt))); + PrintAndLogEx(NORMAL, "Parameter (PAD) | %s", sprint_hex(card.PMm, sizeof(card.PMm))); + PrintAndLogEx(NORMAL, " - IC CODE %s", sprint_hex(card.iccode, sizeof(card.iccode))); + PrintAndLogEx(NORMAL, " - MRT %s", sprint_hex(card.mrt, sizeof(card.mrt))); - PrintAndLogEx(NORMAL, "SERVICE CODE %s", sprint_hex(card.servicecode, sizeof(card.servicecode))); - break; - } - } - return status; + PrintAndLogEx(NORMAL, "SERVICE CODE %s", sprint_hex(card.servicecode, sizeof(card.servicecode))); + break; + } + } + return status; } // simulate iso18092 / FeliCa tag int CmdHFFelicaSim(const char *Cmd) { - bool errors = false; - uint8_t flags = 0; - uint8_t tagtype = 1; - uint8_t cmdp = 0; - uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; - int uidlen = 0; - bool verbose = false; + bool errors = false; + uint8_t flags = 0; + uint8_t tagtype = 1; + uint8_t cmdp = 0; + uint8_t uid[10] = {0,0,0,0,0,0,0,0,0,0}; + int uidlen = 0; + bool verbose = false; - while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch (param_getchar(Cmd, cmdp)) { - case 'h': - case 'H': - return usage_hf_felica_sim(); - case 't': - case 'T': - // Retrieve the tag type - tagtype = param_get8ex(Cmd, cmdp+1, 0, 10); - if (tagtype == 0) - errors = true; - cmdp += 2; - break; - case 'u': - case 'U': - // Retrieve the full 4,7,10 byte long uid - param_gethex_ex(Cmd, cmdp+1, uid, &uidlen); - if (!errors) { - PrintAndLogEx(NORMAL, "Emulating ISO18092/FeliCa tag with %d byte UID (%s)", uidlen>>1, sprint_hex(uid, uidlen>>1)); - } - cmdp += 2; - break; - case 'v': - case 'V': - verbose = true; - cmdp++; - break; - case 'e': - case 'E': - cmdp++; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } + while (param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch (param_getchar(Cmd, cmdp)) { + case 'h': + case 'H': + return usage_hf_felica_sim(); + case 't': + case 'T': + // Retrieve the tag type + tagtype = param_get8ex(Cmd, cmdp+1, 0, 10); + if (tagtype == 0) + errors = true; + cmdp += 2; + break; + case 'u': + case 'U': + // Retrieve the full 4,7,10 byte long uid + param_gethex_ex(Cmd, cmdp+1, uid, &uidlen); + if (!errors) { + PrintAndLogEx(NORMAL, "Emulating ISO18092/FeliCa tag with %d byte UID (%s)", uidlen>>1, sprint_hex(uid, uidlen>>1)); + } + cmdp += 2; + break; + case 'v': + case 'V': + verbose = true; + cmdp++; + break; + case 'e': + case 'E': + cmdp++; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } - //Validations - if (errors || cmdp == 0) return usage_hf_felica_sim(); + //Validations + if (errors || cmdp == 0) return usage_hf_felica_sim(); - UsbCommand c = {CMD_FELICA_SIMULATE_TAG,{ tagtype, flags, 0 }}; - memcpy(c.d.asBytes, uid, uidlen>>1); - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; + UsbCommand c = {CMD_FELICA_SIMULATE_TAG,{ tagtype, flags, 0 }}; + memcpy(c.d.asBytes, uid, uidlen>>1); + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; - if ( verbose ) - PrintAndLogEx(NORMAL, "Press pm3-button to abort simulation"); + if ( verbose ) + PrintAndLogEx(NORMAL, "Press pm3-button to abort simulation"); - while( !ukbhit() ){ - if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; - } - return 0; + while( !ukbhit() ){ + if (!WaitForResponseTimeout(CMD_ACK, &resp, 1500) ) continue; + } + return 0; } int CmdHFFelicaSniff(const char *Cmd) { - uint8_t cmdp = 0; - uint64_t samples2skip = 0; - uint64_t triggers2skip = 0; - bool errors = false; + uint8_t cmdp = 0; + uint64_t samples2skip = 0; + uint64_t triggers2skip = 0; + bool errors = false; - while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { - switch(param_getchar(Cmd, cmdp)) { - case 'h': - case 'H': - return usage_hf_felica_sniff(); - case 's': - case 'S': - samples2skip = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - case 't': - case 'T': - triggers2skip = param_get32ex(Cmd, cmdp+1, 0, 10); - cmdp += 2; - break; - default: - PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); - errors = true; - break; - } - } - //Validations - if (errors || cmdp == 0) return usage_hf_felica_sniff(); + while(param_getchar(Cmd, cmdp) != 0x00 && !errors) { + switch(param_getchar(Cmd, cmdp)) { + case 'h': + case 'H': + return usage_hf_felica_sniff(); + case 's': + case 'S': + samples2skip = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + case 't': + case 'T': + triggers2skip = param_get32ex(Cmd, cmdp+1, 0, 10); + cmdp += 2; + break; + default: + PrintAndLogEx(WARNING, "Unknown parameter '%c'", param_getchar(Cmd, cmdp)); + errors = true; + break; + } + } + //Validations + if (errors || cmdp == 0) return usage_hf_felica_sniff(); - UsbCommand c = {CMD_FELICA_SNOOP, {samples2skip, triggers2skip, 0}}; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_FELICA_SNOOP, {samples2skip, triggers2skip, 0}}; + clearCommandBuffer(); + SendCommand(&c); + return 0; } // uid hex int CmdHFFelicaSimLite(const char *Cmd) { - uint64_t uid = param_get64ex(Cmd, 0, 0, 16); + uint64_t uid = param_get64ex(Cmd, 0, 0, 16); if (!uid) - return usage_hf_felica_simlite(); + return usage_hf_felica_simlite(); - UsbCommand c = {CMD_FELICA_LITE_SIM, {uid, 0, 0} }; - clearCommandBuffer(); - SendCommand(&c); - return 0; + UsbCommand c = {CMD_FELICA_LITE_SIM, {uid, 0, 0} }; + clearCommandBuffer(); + SendCommand(&c); + return 0; } static void printSep() { - PrintAndLogEx(NORMAL, "------------------------------------------------------------------------------------"); + PrintAndLogEx(NORMAL, "------------------------------------------------------------------------------------"); } uint16_t PrintFliteBlock(uint16_t tracepos, uint8_t *trace, uint16_t tracelen) { - if (tracepos+19 >= tracelen) - return tracelen; + if (tracepos+19 >= tracelen) + return tracelen; - trace += tracepos; - uint8_t blocknum = trace[0]; - uint8_t status1 = trace[1]; - uint8_t status2 = trace[2]; + trace += tracepos; + uint8_t blocknum = trace[0]; + uint8_t status1 = trace[1]; + uint8_t status2 = trace[2]; - char line[110] = {0}; - for (int j = 0; j < 16; j++) { - snprintf(line + (j * 4), sizeof(line) - 1 - (j*4) , "%02x ", trace[j+3]); - } + char line[110] = {0}; + for (int j = 0; j < 16; j++) { + snprintf(line + (j * 4), sizeof(line) - 1 - (j*4) , "%02x ", trace[j+3]); + } - PrintAndLogEx(NORMAL, "block number %02x, status: %02x %02x",blocknum,status1, status2); - switch (blocknum) { - case 0x00: PrintAndLogEx(NORMAL, "S_PAD0: %s",line);break; - case 0x01: PrintAndLogEx(NORMAL, "S_PAD1: %s",line);break; - case 0x02: PrintAndLogEx(NORMAL, "S_PAD2: %s",line);break; - case 0x03: PrintAndLogEx(NORMAL, "S_PAD3: %s",line);break; - case 0x04: PrintAndLogEx(NORMAL, "S_PAD4: %s",line);break; - case 0x05: PrintAndLogEx(NORMAL, "S_PAD5: %s",line);break; - case 0x06: PrintAndLogEx(NORMAL, "S_PAD6: %s",line);break; - case 0x07: PrintAndLogEx(NORMAL, "S_PAD7: %s",line);break; - case 0x08: PrintAndLogEx(NORMAL, "S_PAD8: %s",line);break; - case 0x09: PrintAndLogEx(NORMAL, "S_PAD9: %s",line);break; - case 0x0a: PrintAndLogEx(NORMAL, "S_PAD10: %s",line);break; - case 0x0b: PrintAndLogEx(NORMAL, "S_PAD11: %s",line);break; - case 0x0c: PrintAndLogEx(NORMAL, "S_PAD12: %s",line);break; - case 0x0d: PrintAndLogEx(NORMAL, "S_PAD13: %s",line);break; - case 0x0E: { - uint32_t regA = trace[3] | trace[4] << 8 | trace[5] << 16 | trace[ 6] << 24; - uint32_t regB = trace[7] | trace[8] << 8 | trace[9] << 16 | trace[10] << 24; - line[0] = 0; - for (int j = 0; j < 8; j++) - snprintf(line + (j*2), sizeof(line)-1-(j*2), "%02x", trace[j+11]); + PrintAndLogEx(NORMAL, "block number %02x, status: %02x %02x",blocknum,status1, status2); + switch (blocknum) { + case 0x00: PrintAndLogEx(NORMAL, "S_PAD0: %s",line);break; + case 0x01: PrintAndLogEx(NORMAL, "S_PAD1: %s",line);break; + case 0x02: PrintAndLogEx(NORMAL, "S_PAD2: %s",line);break; + case 0x03: PrintAndLogEx(NORMAL, "S_PAD3: %s",line);break; + case 0x04: PrintAndLogEx(NORMAL, "S_PAD4: %s",line);break; + case 0x05: PrintAndLogEx(NORMAL, "S_PAD5: %s",line);break; + case 0x06: PrintAndLogEx(NORMAL, "S_PAD6: %s",line);break; + case 0x07: PrintAndLogEx(NORMAL, "S_PAD7: %s",line);break; + case 0x08: PrintAndLogEx(NORMAL, "S_PAD8: %s",line);break; + case 0x09: PrintAndLogEx(NORMAL, "S_PAD9: %s",line);break; + case 0x0a: PrintAndLogEx(NORMAL, "S_PAD10: %s",line);break; + case 0x0b: PrintAndLogEx(NORMAL, "S_PAD11: %s",line);break; + case 0x0c: PrintAndLogEx(NORMAL, "S_PAD12: %s",line);break; + case 0x0d: PrintAndLogEx(NORMAL, "S_PAD13: %s",line);break; + case 0x0E: { + uint32_t regA = trace[3] | trace[4] << 8 | trace[5] << 16 | trace[ 6] << 24; + uint32_t regB = trace[7] | trace[8] << 8 | trace[9] << 16 | trace[10] << 24; + line[0] = 0; + for (int j = 0; j < 8; j++) + snprintf(line + (j*2), sizeof(line)-1-(j*2), "%02x", trace[j+11]); - PrintAndLogEx(NORMAL, "REG: regA: %d regB: %d regC: %s ", regA, regB, line); - } - break; - case 0x80: PrintAndLogEx(NORMAL, "Random Challenge, WO: %s ", line); break; - case 0x81: PrintAndLogEx(NORMAL, "MAC, only set on dual read: %s ", line); break; - case 0x82: { - char idd[20]; - char idm[20]; - for (int j = 0; j < 8; j++) - snprintf(idd + (j*2), sizeof(idd)-1-(j*2), "%02x", trace[j+3]); + PrintAndLogEx(NORMAL, "REG: regA: %d regB: %d regC: %s ", regA, regB, line); + } + break; + case 0x80: PrintAndLogEx(NORMAL, "Random Challenge, WO: %s ", line); break; + case 0x81: PrintAndLogEx(NORMAL, "MAC, only set on dual read: %s ", line); break; + case 0x82: { + char idd[20]; + char idm[20]; + for (int j = 0; j < 8; j++) + snprintf(idd + (j*2), sizeof(idd)-1-(j*2), "%02x", trace[j+3]); - for (int j = 0; j < 6; j++) - snprintf(idm + (j*2), sizeof(idm)-1-(j*2), "%02x", trace[j+13]); + for (int j = 0; j < 6; j++) + snprintf(idm + (j*2), sizeof(idm)-1-(j*2), "%02x", trace[j+13]); - PrintAndLogEx(NORMAL, "ID Block, IDd: 0x%s DFC: 0x%02x%02x Arb: %s ", idd, trace[11], trace [12], idm); - } - break; - case 0x83: { - char idm[20]; - char pmm[20]; - for (int j = 0; j < 8; j++) - snprintf(idm + (j*2), sizeof(idm)-1-(j*2), "%02x", trace[j+3]); + PrintAndLogEx(NORMAL, "ID Block, IDd: 0x%s DFC: 0x%02x%02x Arb: %s ", idd, trace[11], trace [12], idm); + } + break; + case 0x83: { + char idm[20]; + char pmm[20]; + for (int j = 0; j < 8; j++) + snprintf(idm + (j*2), sizeof(idm)-1-(j*2), "%02x", trace[j+3]); - for (int j = 0; j < 8; j++) - snprintf(pmm + (j*2), sizeof(pmm)-1-(j*2), "%02x", trace[j+11]); + for (int j = 0; j < 8; j++) + snprintf(pmm + (j*2), sizeof(pmm)-1-(j*2), "%02x", trace[j+11]); - PrintAndLogEx(NORMAL, "DeviceId: IDm: 0x%s PMm: 0x%s ", idm, pmm); - } - break; - case 0x84: PrintAndLogEx(NORMAL, "SER_C: 0x%02x%02x ", trace[3], trace[4]); break; - case 0x85: PrintAndLogEx(NORMAL, "SYS_Cl 0x%02x%02x ", trace[3], trace[4]); break; - case 0x86: PrintAndLogEx(NORMAL, "CKV (key version): 0x%02x%02x ", trace[3], trace[4]); break; - case 0x87: PrintAndLogEx(NORMAL, "CK (card key), WO: %s ", line); break; - case 0x88: { - PrintAndLogEx(NORMAL, "Memory Configuration (MC):"); - PrintAndLogEx(NORMAL, "MAC needed to write state: %s", trace[3+12]? "on" : "off"); - //order might be off here... - PrintAndLogEx(NORMAL, "Write with MAC for S_PAD : %s ", sprint_bin(trace+3+10, 2) ); - PrintAndLogEx(NORMAL, "Write with AUTH for S_PAD : %s ", sprint_bin(trace+3+8, 2) ); - PrintAndLogEx(NORMAL, "Read after AUTH for S_PAD : %s ", sprint_bin(trace+3+6, 2) ); - PrintAndLogEx(NORMAL, "MAC needed to write CK and CKV: %s", trace[3+5] ? "on" : "off"); - PrintAndLogEx(NORMAL, "RF parameter: %02x", (trace[3+4] & 0x7) ); - PrintAndLogEx(NORMAL, "Compatible with NDEF: %s", trace[3+3] ? "yes" : "no"); - PrintAndLogEx(NORMAL, "Memory config writable : %s", (trace[3+2] == 0xff) ? "yes" : "no"); - PrintAndLogEx(NORMAL, "RW access for S_PAD : %s ", sprint_bin(trace+3, 2) ); - } - break; - case 0x90: { + PrintAndLogEx(NORMAL, "DeviceId: IDm: 0x%s PMm: 0x%s ", idm, pmm); + } + break; + case 0x84: PrintAndLogEx(NORMAL, "SER_C: 0x%02x%02x ", trace[3], trace[4]); break; + case 0x85: PrintAndLogEx(NORMAL, "SYS_Cl 0x%02x%02x ", trace[3], trace[4]); break; + case 0x86: PrintAndLogEx(NORMAL, "CKV (key version): 0x%02x%02x ", trace[3], trace[4]); break; + case 0x87: PrintAndLogEx(NORMAL, "CK (card key), WO: %s ", line); break; + case 0x88: { + PrintAndLogEx(NORMAL, "Memory Configuration (MC):"); + PrintAndLogEx(NORMAL, "MAC needed to write state: %s", trace[3+12]? "on" : "off"); + //order might be off here... + PrintAndLogEx(NORMAL, "Write with MAC for S_PAD : %s ", sprint_bin(trace+3+10, 2) ); + PrintAndLogEx(NORMAL, "Write with AUTH for S_PAD : %s ", sprint_bin(trace+3+8, 2) ); + PrintAndLogEx(NORMAL, "Read after AUTH for S_PAD : %s ", sprint_bin(trace+3+6, 2) ); + PrintAndLogEx(NORMAL, "MAC needed to write CK and CKV: %s", trace[3+5] ? "on" : "off"); + PrintAndLogEx(NORMAL, "RF parameter: %02x", (trace[3+4] & 0x7) ); + PrintAndLogEx(NORMAL, "Compatible with NDEF: %s", trace[3+3] ? "yes" : "no"); + PrintAndLogEx(NORMAL, "Memory config writable : %s", (trace[3+2] == 0xff) ? "yes" : "no"); + PrintAndLogEx(NORMAL, "RW access for S_PAD : %s ", sprint_bin(trace+3, 2) ); + } + break; + case 0x90: { PrintAndLogEx(NORMAL, "Write count, RO: %02x %02x %02x ", trace[3], trace[4], trace[5]); - } - break; - case 0x91: { + } + break; + case 0x91: { PrintAndLogEx(NORMAL, "MAC_A, RW (auth): %s ", line); } - break; - case 0x92: + break; + case 0x92: PrintAndLogEx(NORMAL, "State:"); PrintAndLogEx(NORMAL, "Polling disabled: %s", trace[3+8] ? "yes" : "no"); PrintAndLogEx(NORMAL, "Authenticated: %s", trace[3] ? "yes" : "no"); - break; - case 0xa0: + break; + case 0xa0: PrintAndLogEx(NORMAL, "CRC of all bloacks match : %s", (trace[3+2]==0xff) ? "no" : "yes"); - break; - default: - PrintAndLogEx(WARNING, "INVALID %d: %s", blocknum, line); - break; - } - return tracepos+19; + break; + default: + PrintAndLogEx(WARNING, "INVALID %d: %s", blocknum, line); + break; + } + return tracepos+19; } int CmdHFFelicaDumpLite(const char *Cmd) { - char ctmp = tolower(param_getchar(Cmd, 0)); - if ( ctmp == 'h') return usage_hf_felica_dumplite(); + char ctmp = tolower(param_getchar(Cmd, 0)); + if ( ctmp == 'h') return usage_hf_felica_dumplite(); - PrintAndLogEx(SUCCESS, "FeliCa lite - dump started"); - PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); - UsbCommand c = {CMD_FELICA_LITE_DUMP, {0,0,0}}; - clearCommandBuffer(); - SendCommand(&c); - UsbCommand resp; + PrintAndLogEx(SUCCESS, "FeliCa lite - dump started"); + PrintAndLogEx(SUCCESS, "press pm3-button to cancel"); + UsbCommand c = {CMD_FELICA_LITE_DUMP, {0,0,0}}; + clearCommandBuffer(); + SendCommand(&c); + UsbCommand resp; - uint8_t timeout = 0; - while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { - timeout++; - printf("."); fflush(stdout); - if (ukbhit()) { - int gc = getchar(); (void)gc; - PrintAndLogEx(WARNING, "\n[!] aborted via keyboard!\n"); - DropField(); - return 1; - } - if (timeout > 100) { - PrintAndLogEx(WARNING, "timeout while waiting for reply."); - DropField(); - return 1; - } - } - if (resp.arg[0] == 0) { - PrintAndLogEx(WARNING, "\nButton pressed. Aborted."); - return 1; - } + uint8_t timeout = 0; + while ( !WaitForResponseTimeout(CMD_ACK, &resp, 2000) ) { + timeout++; + printf("."); fflush(stdout); + if (ukbhit()) { + int gc = getchar(); (void)gc; + PrintAndLogEx(WARNING, "\n[!] aborted via keyboard!\n"); + DropField(); + return 1; + } + if (timeout > 100) { + PrintAndLogEx(WARNING, "timeout while waiting for reply."); + DropField(); + return 1; + } + } + if (resp.arg[0] == 0) { + PrintAndLogEx(WARNING, "\nButton pressed. Aborted."); + return 1; + } - uint64_t tracelen = resp.arg[1]; - uint8_t *trace = calloc(tracelen, sizeof(uint8_t)); - if ( trace == NULL ) { - PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); - return 1; - } + uint64_t tracelen = resp.arg[1]; + uint8_t *trace = calloc(tracelen, sizeof(uint8_t)); + if ( trace == NULL ) { + PrintAndLogEx(WARNING, "Cannot allocate memory for trace"); + return 1; + } - // only download data if there is any. - if ( tracelen > 0 ) { + // only download data if there is any. + if ( tracelen > 0 ) { - if ( !GetFromDevice(BIG_BUF, trace, tracelen, 0, NULL, 2500, false) ){ - PrintAndLogEx(WARNING, "command execution time out"); - free(trace); - return 0; - } + if ( !GetFromDevice(BIG_BUF, trace, tracelen, 0, NULL, 2500, false) ){ + PrintAndLogEx(WARNING, "command execution time out"); + free(trace); + return 0; + } - PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %d bytes)", tracelen); + PrintAndLogEx(SUCCESS, "Recorded Activity (trace len = %d bytes)", tracelen); - print_hex_break(trace, tracelen, 32); + print_hex_break(trace, tracelen, 32); - printSep(); - uint16_t tracepos = 0; - while (tracepos < tracelen) - tracepos = PrintFliteBlock(tracepos, trace, tracelen); + printSep(); + uint16_t tracepos = 0; + while (tracepos < tracelen) + tracepos = PrintFliteBlock(tracepos, trace, tracelen); - printSep(); - } + printSep(); + } free(trace); - return 0; + return 0; } int CmdHFFelicaCmdRaw(const char *cmd) { @@ -425,8 +425,8 @@ int CmdHFFelicaCmdRaw(const char *cmd) { char buf[5]=""; int i = 0; uint8_t data[USB_CMD_DATA_SIZE]; - uint16_t datalen = 0; - uint32_t temp; + uint16_t datalen = 0; + uint32_t temp; if (strlen(cmd) < 2) return usage_hf_felica_raw(); @@ -437,9 +437,9 @@ int CmdHFFelicaCmdRaw(const char *cmd) { if (cmd[i]==' ' || cmd[i]=='\t') { i++; continue; } if (cmd[i]=='-') { switch (cmd[i+1]) { - case 'H': - case 'h': - return usage_hf_felica_raw(); + case 'H': + case 'h': + return usage_hf_felica_raw(); case 'r': reply = false; break; @@ -479,11 +479,11 @@ int CmdHFFelicaCmdRaw(const char *cmd) { sscanf(buf,"%x",&temp); data[datalen]=(uint8_t)(temp & 0xff); *buf=0; - if (++datalen >= sizeof(data)){ - if (crc) - PrintAndLogEx(NORMAL, "Buffer is full, we can't add CRC to your data"); - break; - } + if (++datalen >= sizeof(data)){ + if (crc) + PrintAndLogEx(NORMAL, "Buffer is full, we can't add CRC to your data"); + break; + } } continue; } @@ -493,7 +493,7 @@ int CmdHFFelicaCmdRaw(const char *cmd) { if (crc && datalen>0 && datalen < sizeof(data)-2) { uint8_t b1, b2; - compute_crc(CRC_FELICA, data, datalen, &b1, &b2); + compute_crc(CRC_FELICA, data, datalen, &b1, &b2); data[datalen++] = b1; data[datalen++] = b2; } @@ -506,19 +506,19 @@ int CmdHFFelicaCmdRaw(const char *cmd) { if (power) { c.arg[0] |= FELICA_NO_DISCONNECT; - } + } if (datalen > 0) { c.arg[0] |= FELICA_RAW; - } + } - // Max buffer is USB_CMD_DATA_SIZE - datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; + // Max buffer is USB_CMD_DATA_SIZE + datalen = (datalen > USB_CMD_DATA_SIZE) ? USB_CMD_DATA_SIZE : datalen; c.arg[1] = (datalen & 0xFFFF) | (uint32_t)(numbits << 16); memcpy(c.d.asBytes, data, datalen); - clearCommandBuffer(); + clearCommandBuffer(); SendCommand(&c); if (reply) { @@ -539,32 +539,32 @@ void waitCmdFelica(uint8_t iSelect) { PrintAndLogEx(NORMAL, "received %i octets", len); if(!len) return; - PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) ); + PrintAndLogEx(NORMAL, "%s", sprint_hex(resp.d.asBytes, len) ); } else { PrintAndLogEx(WARNING, "timeout while waiting for reply."); } } static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help"}, - {"list", CmdHFFelicaList, 0, "[Deprecated] List ISO 18092/FeliCa history"}, - {"reader", CmdHFFelicaReader, 0, "Act like an ISO18092/FeliCa reader"}, - {"sim", CmdHFFelicaSim, 0, " -- Simulate ISO 18092/FeliCa tag"}, - {"sniff", CmdHFFelicaSniff, 0, "sniff ISO 18092/Felica traffic"}, - {"raw", CmdHFFelicaCmdRaw, 0, "Send raw hex data to tag"}, + {"help", CmdHelp, 1, "This help"}, + {"list", CmdHFFelicaList, 0, "[Deprecated] List ISO 18092/FeliCa history"}, + {"reader", CmdHFFelicaReader, 0, "Act like an ISO18092/FeliCa reader"}, + {"sim", CmdHFFelicaSim, 0, " -- Simulate ISO 18092/FeliCa tag"}, + {"sniff", CmdHFFelicaSniff, 0, "sniff ISO 18092/Felica traffic"}, + {"raw", CmdHFFelicaCmdRaw, 0, "Send raw hex data to tag"}, - {"litesim", CmdHFFelicaSimLite, 0, " - only reply to poll request"}, - {"litedump", CmdHFFelicaDumpLite, 0, "Wait for and try dumping FelicaLite"}, + {"litesim", CmdHFFelicaSimLite, 0, " - only reply to poll request"}, + {"litedump", CmdHFFelicaDumpLite, 0, "Wait for and try dumping FelicaLite"}, {NULL, NULL, 0, NULL} }; int CmdHFFelica(const char *Cmd) { - clearCommandBuffer(); - CmdsParse(CommandTable, Cmd); - return 0; + clearCommandBuffer(); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { - CmdsHelp(CommandTable); - return 0; + CmdsHelp(CommandTable); + return 0; } \ No newline at end of file diff --git a/client/cmdhffelica.h b/client/cmdhffelica.h index bcec38a0b..80a09f7d3 100644 --- a/client/cmdhffelica.h +++ b/client/cmdhffelica.h @@ -21,10 +21,10 @@ #include "ui.h" #include "util.h" #include "cmdparser.h" -#include "comms.h" // getfromdevice +#include "comms.h" // getfromdevice #include "iso14443crc.h" -#include "cmdhf.h" // list cmd -#include "mifare.h" // felica_card_select_t struct +#include "cmdhf.h" // list cmd +#include "mifare.h" // felica_card_select_t struct extern int CmdHFFelica(const char *Cmd); extern int CmdHFFelicaList(const char *Cmd); diff --git a/client/cmdhffido.c b/client/cmdhffido.c index ea5d55c66..588c3b037 100644 --- a/client/cmdhffido.c +++ b/client/cmdhffido.c @@ -51,872 +51,872 @@ static int CmdHelp(const char *Cmd); int CmdHFFidoInfo(const char *cmd) { - if (cmd && strlen(cmd) > 0) - PrintAndLog("WARNING: command don't have any parameters.\n"); + if (cmd && strlen(cmd) > 0) + PrintAndLog("WARNING: command don't have any parameters.\n"); - // info about 14a part - CmdHF14AInfo(""); + // info about 14a part + CmdHF14AInfo(""); - // FIDO info - PrintAndLog("--------------------------------------------"); - SetAPDULogging(false); + // FIDO info + PrintAndLog("--------------------------------------------"); + SetAPDULogging(false); - uint8_t buf[APDU_RES_LEN] = {0}; - size_t len = 0; - uint16_t sw = 0; - int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); + uint8_t buf[APDU_RES_LEN] = {0}; + size_t len = 0; + uint16_t sw = 0; + int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); - if (res) { - DropField(); - return res; - } + if (res) { + DropField(); + return res; + } - if (sw != 0x9000) { - if (sw) - PrintAndLog("Not a FIDO card! APDU response: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - else - PrintAndLog("APDU exchange error. Card returns 0x0000."); + if (sw != 0x9000) { + if (sw) + PrintAndLog("Not a FIDO card! APDU response: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + else + PrintAndLog("APDU exchange error. Card returns 0x0000."); - DropField(); - return 0; - } + DropField(); + return 0; + } - if (!strncmp((char *)buf, "U2F_V2", 7)) { - if (!strncmp((char *)buf, "FIDO_2_0", 8)) { - PrintAndLog("FIDO2 authenricator detected. Version: %.*s", len, buf); - } else { - PrintAndLog("FIDO authenricator detected (not standard U2F)."); - PrintAndLog("Non U2F authenticator version:"); - dump_buffer((const unsigned char *)buf, len, NULL, 0); - } - } else { - PrintAndLog("FIDO U2F authenricator detected. Version: %.*s", len, buf); - } + if (!strncmp((char *)buf, "U2F_V2", 7)) { + if (!strncmp((char *)buf, "FIDO_2_0", 8)) { + PrintAndLog("FIDO2 authenricator detected. Version: %.*s", len, buf); + } else { + PrintAndLog("FIDO authenricator detected (not standard U2F)."); + PrintAndLog("Non U2F authenticator version:"); + dump_buffer((const unsigned char *)buf, len, NULL, 0); + } + } else { + PrintAndLog("FIDO U2F authenricator detected. Version: %.*s", len, buf); + } - res = FIDO2GetInfo(buf, sizeof(buf), &len, &sw); - DropField(); - if (res) { - return res; - } - if (sw != 0x9000) { - PrintAndLog("FIDO2 version not exists (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + res = FIDO2GetInfo(buf, sizeof(buf), &len, &sw); + DropField(); + if (res) { + return res; + } + if (sw != 0x9000) { + PrintAndLog("FIDO2 version not exists (%04x - %s).", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - return 0; - } + return 0; + } - if(buf[0]) { - PrintAndLog("FIDO2 ger version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); - return 0; - } + if(buf[0]) { + PrintAndLog("FIDO2 ger version error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); + return 0; + } - if (len > 1) { -// if (false) { -// PrintAndLog("FIDO2 version: (len=%d)", len); -// dump_buffer((const unsigned char *)buf, len, NULL, 0); -// } + if (len > 1) { +// if (false) { +// PrintAndLog("FIDO2 version: (len=%d)", len); +// dump_buffer((const unsigned char *)buf, len, NULL, 0); +// } - PrintAndLog("FIDO2 version CBOR decoded:"); - TinyCborPrintFIDOPackage(fido2CmdGetInfo, true, &buf[1], len - 1); - } else { - PrintAndLog("FIDO2 version length error"); - } + PrintAndLog("FIDO2 version CBOR decoded:"); + TinyCborPrintFIDOPackage(fido2CmdGetInfo, true, &buf[1], len - 1); + } else { + PrintAndLog("FIDO2 version length error"); + } - return 0; + return 0; } json_t *OpenJson(int paramnum, char *fname, void* argtable[], bool *err) { - json_t *root = NULL; - json_error_t error; - *err = false; + json_t *root = NULL; + json_error_t error; + *err = false; - uint8_t jsonname[250] ={0}; - char *cjsonname = (char *)jsonname; - int jsonnamelen = 0; + uint8_t jsonname[250] ={0}; + char *cjsonname = (char *)jsonname; + int jsonnamelen = 0; - // CLIGetStrWithReturn(paramnum, jsonname, &jsonnamelen); - if (CLIParamStrToBuf(arg_get_str(paramnum), jsonname, sizeof(jsonname), &jsonnamelen)) { - CLIParserFree(); - return NULL; - } + // CLIGetStrWithReturn(paramnum, jsonname, &jsonnamelen); + if (CLIParamStrToBuf(arg_get_str(paramnum), jsonname, sizeof(jsonname), &jsonnamelen)) { + CLIParserFree(); + return NULL; + } - // current path + file name - if (!strstr(cjsonname, ".json")) - strcat(cjsonname, ".json"); + // current path + file name + if (!strstr(cjsonname, ".json")) + strcat(cjsonname, ".json"); - if (jsonnamelen) { - strcpy(fname, get_my_executable_directory()); - strcat(fname, cjsonname); - if (access(fname, F_OK) != -1) { - root = json_load_file(fname, 0, &error); - if (!root) { - PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); - *err = true; - return NULL; - } + if (jsonnamelen) { + strcpy(fname, get_my_executable_directory()); + strcat(fname, cjsonname); + if (access(fname, F_OK) != -1) { + root = json_load_file(fname, 0, &error); + if (!root) { + PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); + *err = true; + return NULL; + } - if (!json_is_object(root)) { - PrintAndLog("ERROR: Invalid json format. root must be an object."); - json_decref(root); - *err = true; - return NULL; - } + if (!json_is_object(root)) { + PrintAndLog("ERROR: Invalid json format. root must be an object."); + json_decref(root); + *err = true; + return NULL; + } - } else { - root = json_object(); - } - } - return root; + } else { + root = json_object(); + } + } + return root; } int CmdHFFidoRegister(const char *cmd) { - uint8_t data[64] = {0}; - int chlen = 0; - uint8_t cdata[250] = {0}; - int applen = 0; - uint8_t adata[250] = {0}; - json_t *root = NULL; + uint8_t data[64] = {0}; + int chlen = 0; + uint8_t cdata[250] = {0}; + int applen = 0; + uint8_t adata[250] = {0}; + json_t *root = NULL; - CLIParserInit("hf fido reg", - "Initiate a U2F token registration. Needs two 32-byte hash number. \nchallenge parameter (32b) and application parameter (32b).", - "Usage:\n\thf fido reg -> execute command with 2 parameters, filled 0x00\n" - "\thf fido reg 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters" - "\thf fido reg -p s0 s1 -> execute command with plain parameters"); + CLIParserInit("hf fido reg", + "Initiate a U2F token registration. Needs two 32-byte hash number. \nchallenge parameter (32b) and application parameter (32b).", + "Usage:\n\thf fido reg -> execute command with 2 parameters, filled 0x00\n" + "\thf fido reg 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters" + "\thf fido reg -p s0 s1 -> execute command with plain parameters"); - void* argtable[] = { - arg_param_begin, - arg_lit0("aA", "apdu", "show APDU reqests and responses"), - arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), - arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"), - arg_lit0("tT", "tlv", "Show DER certificate contents in TLV representation"), - arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."), - arg_str0(NULL, NULL, "", NULL), - arg_str0(NULL, NULL, "", NULL), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, true); + void* argtable[] = { + arg_param_begin, + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), + arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"), + arg_lit0("tT", "tlv", "Show DER certificate contents in TLV representation"), + arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."), + arg_str0(NULL, NULL, "", NULL), + arg_str0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); - bool APDULogging = arg_get_lit(1); - bool verbose = arg_get_lit(2); - bool verbose2 = arg_get_lit(2) > 1; - bool paramsPlain = arg_get_lit(3); - bool showDERTLV = arg_get_lit(4); + bool APDULogging = arg_get_lit(1); + bool verbose = arg_get_lit(2); + bool verbose2 = arg_get_lit(2) > 1; + bool paramsPlain = arg_get_lit(3); + bool showDERTLV = arg_get_lit(4); - char fname[250] = {0}; - bool err; - root = OpenJson(5, fname, argtable, &err); - if(err) - return 1; - if (root) { - size_t jlen; - JsonLoadBufAsHex(root, "$.ChallengeParam", data, 32, &jlen); - JsonLoadBufAsHex(root, "$.ApplicationParam", &data[32], 32, &jlen); - } + char fname[250] = {0}; + bool err; + root = OpenJson(5, fname, argtable, &err); + if(err) + return 1; + if (root) { + size_t jlen; + JsonLoadBufAsHex(root, "$.ChallengeParam", data, 32, &jlen); + JsonLoadBufAsHex(root, "$.ApplicationParam", &data[32], 32, &jlen); + } - if (paramsPlain) { - memset(cdata, 0x00, 32); - CLIGetStrWithReturn(6, cdata, &chlen); - if (chlen && chlen > 16) { - PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", chlen); - return 1; - } - } else { - CLIGetHexWithReturn(6, cdata, &chlen); - if (chlen && chlen != 32) { - PrintAndLog("ERROR: challenge parameter length must be 32 bytes only."); - return 1; - } - } - if (chlen) - memmove(data, cdata, 32); + if (paramsPlain) { + memset(cdata, 0x00, 32); + CLIGetStrWithReturn(6, cdata, &chlen); + if (chlen && chlen > 16) { + PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", chlen); + return 1; + } + } else { + CLIGetHexWithReturn(6, cdata, &chlen); + if (chlen && chlen != 32) { + PrintAndLog("ERROR: challenge parameter length must be 32 bytes only."); + return 1; + } + } + if (chlen) + memmove(data, cdata, 32); - if (paramsPlain) { - memset(adata, 0x00, 32); - CLIGetStrWithReturn(7, adata, &applen); - if (applen && applen > 16) { - PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", applen); - return 1; - } - } else { - CLIGetHexWithReturn(7, adata, &applen); - if (applen && applen != 32) { - PrintAndLog("ERROR: application parameter length must be 32 bytes only."); - return 1; - } - } - if (applen) - memmove(&data[32], adata, 32); + if (paramsPlain) { + memset(adata, 0x00, 32); + CLIGetStrWithReturn(7, adata, &applen); + if (applen && applen > 16) { + PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", applen); + return 1; + } + } else { + CLIGetHexWithReturn(7, adata, &applen); + if (applen && applen != 32) { + PrintAndLog("ERROR: application parameter length must be 32 bytes only."); + return 1; + } + } + if (applen) + memmove(&data[32], adata, 32); - CLIParserFree(); + CLIParserFree(); - SetAPDULogging(APDULogging); + SetAPDULogging(APDULogging); - // challenge parameter [32 bytes] - The challenge parameter is the SHA-256 hash of the Client Data, a stringified JSON data structure that the FIDO Client prepares - // application parameter [32 bytes] - The application parameter is the SHA-256 hash of the UTF-8 encoding of the application identity + // challenge parameter [32 bytes] - The challenge parameter is the SHA-256 hash of the Client Data, a stringified JSON data structure that the FIDO Client prepares + // application parameter [32 bytes] - The application parameter is the SHA-256 hash of the UTF-8 encoding of the application identity - uint8_t buf[2048] = {0}; - size_t len = 0; - uint16_t sw = 0; + uint8_t buf[2048] = {0}; + size_t len = 0; + uint16_t sw = 0; - DropField(); - int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); + DropField(); + int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); - if (res) { - PrintAndLog("Can't select authenticator. res=%x. Exit...", res); - DropField(); - return res; - } + if (res) { + PrintAndLog("Can't select authenticator. res=%x. Exit...", res); + DropField(); + return res; + } - if (sw != 0x9000) { - PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - DropField(); - return 2; - } + if (sw != 0x9000) { + PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); + return 2; + } - res = FIDORegister(data, buf, sizeof(buf), &len, &sw); - DropField(); - if (res) { - PrintAndLog("Can't execute register command. res=%x. Exit...", res); - return res; - } + res = FIDORegister(data, buf, sizeof(buf), &len, &sw); + DropField(); + if (res) { + PrintAndLog("Can't execute register command. res=%x. Exit...", res); + return res; + } - if (sw != 0x9000) { - PrintAndLog("ERROR execute register command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - return 3; - } + if (sw != 0x9000) { + PrintAndLog("ERROR execute register command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + return 3; + } - PrintAndLog(""); - if (APDULogging) - PrintAndLog("---------------------------------------------------------------"); - PrintAndLog("data len: %d", len); - if (verbose2) { - PrintAndLog("--------------data----------------------"); - dump_buffer((const unsigned char *)buf, len, NULL, 0); - PrintAndLog("--------------data----------------------"); - } + PrintAndLog(""); + if (APDULogging) + PrintAndLog("---------------------------------------------------------------"); + PrintAndLog("data len: %d", len); + if (verbose2) { + PrintAndLog("--------------data----------------------"); + dump_buffer((const unsigned char *)buf, len, NULL, 0); + PrintAndLog("--------------data----------------------"); + } - if (buf[0] != 0x05) { - PrintAndLog("ERROR: First byte must be 0x05, but it %2x", buf[0]); - return 5; - } - PrintAndLog("User public key: %s", sprint_hex(&buf[1], 65)); + if (buf[0] != 0x05) { + PrintAndLog("ERROR: First byte must be 0x05, but it %2x", buf[0]); + return 5; + } + PrintAndLog("User public key: %s", sprint_hex(&buf[1], 65)); - uint8_t keyHandleLen = buf[66]; - PrintAndLog("Key handle[%d]: %s", keyHandleLen, sprint_hex(&buf[67], keyHandleLen)); + uint8_t keyHandleLen = buf[66]; + PrintAndLog("Key handle[%d]: %s", keyHandleLen, sprint_hex(&buf[67], keyHandleLen)); - int derp = 67 + keyHandleLen; - int derLen = (buf[derp + 2] << 8) + buf[derp + 3] + 4; - if (verbose2) { - PrintAndLog("DER certificate[%d]:\n------------------DER-------------------", derLen); - dump_buffer_simple((const unsigned char *)&buf[derp], derLen, NULL); - PrintAndLog("\n----------------DER---------------------"); - } else { - if (verbose) - PrintAndLog("------------------DER-------------------"); - PrintAndLog("DER certificate[%d]: %s...", derLen, sprint_hex(&buf[derp], 20)); - } + int derp = 67 + keyHandleLen; + int derLen = (buf[derp + 2] << 8) + buf[derp + 3] + 4; + if (verbose2) { + PrintAndLog("DER certificate[%d]:\n------------------DER-------------------", derLen); + dump_buffer_simple((const unsigned char *)&buf[derp], derLen, NULL); + PrintAndLog("\n----------------DER---------------------"); + } else { + if (verbose) + PrintAndLog("------------------DER-------------------"); + PrintAndLog("DER certificate[%d]: %s...", derLen, sprint_hex(&buf[derp], 20)); + } - // check and print DER certificate - uint8_t public_key[65] = {0}; + // check and print DER certificate + uint8_t public_key[65] = {0}; - // print DER certificate in TLV view - if (showDERTLV) { - PrintAndLog("----------------DER TLV-----------------"); - asn1_print(&buf[derp], derLen, " "); - PrintAndLog("----------------DER TLV-----------------"); - } + // print DER certificate in TLV view + if (showDERTLV) { + PrintAndLog("----------------DER TLV-----------------"); + asn1_print(&buf[derp], derLen, " "); + PrintAndLog("----------------DER TLV-----------------"); + } FIDOCheckDERAndGetKey(&buf[derp], derLen, verbose, public_key, sizeof(public_key)); - // get hash - int hashp = 1 + 65 + 1 + keyHandleLen + derLen; - PrintAndLog("Hash[%d]: %s", len - hashp, sprint_hex(&buf[hashp], len - hashp)); + // get hash + int hashp = 1 + 65 + 1 + keyHandleLen + derLen; + PrintAndLog("Hash[%d]: %s", len - hashp, sprint_hex(&buf[hashp], len - hashp)); - // check ANSI X9.62 format ECDSA signature (on P-256) - uint8_t rval[300] = {0}; - uint8_t sval[300] = {0}; - res = ecdsa_asn1_get_signature(&buf[hashp], len - hashp, rval, sval); - if (!res) { - if (verbose) { - PrintAndLog(" r: %s", sprint_hex(rval, 32)); - PrintAndLog(" s: %s", sprint_hex(sval, 32)); - } + // check ANSI X9.62 format ECDSA signature (on P-256) + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; + res = ecdsa_asn1_get_signature(&buf[hashp], len - hashp, rval, sval); + if (!res) { + if (verbose) { + PrintAndLog(" r: %s", sprint_hex(rval, 32)); + PrintAndLog(" s: %s", sprint_hex(sval, 32)); + } - uint8_t xbuf[4096] = {0}; - size_t xbuflen = 0; - res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, - "\x00", 1, - &data[32], 32, // application parameter - &data[0], 32, // challenge parameter - &buf[67], keyHandleLen, // keyHandle - &buf[1], 65, // user public key - NULL, 0); - //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); - res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[hashp], len - hashp); - if (res) { - if (res == -0x4e00) { - PrintAndLog("Signature is NOT VALID."); - } else { - PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); - } - } else { - PrintAndLog("Signature is OK."); - } + uint8_t xbuf[4096] = {0}; + size_t xbuflen = 0; + res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, + "\x00", 1, + &data[32], 32, // application parameter + &data[0], 32, // challenge parameter + &buf[67], keyHandleLen, // keyHandle + &buf[1], 65, // user public key + NULL, 0); + //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); + res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[hashp], len - hashp); + if (res) { + if (res == -0x4e00) { + PrintAndLog("Signature is NOT VALID."); + } else { + PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); + } + } else { + PrintAndLog("Signature is OK."); + } - } else { - PrintAndLog("Invalid signature. res=%d.", res); - } + } else { + PrintAndLog("Invalid signature. res=%d.", res); + } - PrintAndLog("\nauth command: "); - printf("hf fido auth %s%s", paramsPlain?"-p ":"", sprint_hex_inrow(&buf[67], keyHandleLen)); - if(chlen || applen) - printf(" %s", paramsPlain?(char *)cdata:sprint_hex_inrow(cdata, 32)); - if(applen) - printf(" %s", paramsPlain?(char *)adata:sprint_hex_inrow(adata, 32)); - printf("\n"); + PrintAndLog("\nauth command: "); + printf("hf fido auth %s%s", paramsPlain?"-p ":"", sprint_hex_inrow(&buf[67], keyHandleLen)); + if(chlen || applen) + printf(" %s", paramsPlain?(char *)cdata:sprint_hex_inrow(cdata, 32)); + if(applen) + printf(" %s", paramsPlain?(char *)adata:sprint_hex_inrow(adata, 32)); + printf("\n"); - if (root) { - JsonSaveBufAsHex(root, "ChallengeParam", data, 32); - JsonSaveBufAsHex(root, "ApplicationParam", &data[32], 32); - JsonSaveBufAsHexCompact(root, "PublicKey", &buf[1], 65); - JsonSaveInt(root, "KeyHandleLen", keyHandleLen); - JsonSaveBufAsHexCompact(root, "KeyHandle", &buf[67], keyHandleLen); - JsonSaveBufAsHexCompact(root, "DER", &buf[67 + keyHandleLen], derLen); + if (root) { + JsonSaveBufAsHex(root, "ChallengeParam", data, 32); + JsonSaveBufAsHex(root, "ApplicationParam", &data[32], 32); + JsonSaveBufAsHexCompact(root, "PublicKey", &buf[1], 65); + JsonSaveInt(root, "KeyHandleLen", keyHandleLen); + JsonSaveBufAsHexCompact(root, "KeyHandle", &buf[67], keyHandleLen); + JsonSaveBufAsHexCompact(root, "DER", &buf[67 + keyHandleLen], derLen); - res = json_dump_file(root, fname, JSON_INDENT(2)); - if (res) { - PrintAndLog("ERROR: can't save the file: %s", fname); - return 200; - } - PrintAndLog("File `%s` saved.", fname); + res = json_dump_file(root, fname, JSON_INDENT(2)); + if (res) { + PrintAndLog("ERROR: can't save the file: %s", fname); + return 200; + } + PrintAndLog("File `%s` saved.", fname); - // free json object - json_decref(root); - } + // free json object + json_decref(root); + } - return 0; + return 0; }; int CmdHFFidoAuthenticate(const char *cmd) { - uint8_t data[512] = {0}; - uint8_t hdata[250] = {0}; - bool public_key_loaded = false; - uint8_t public_key[65] = {0}; - int hdatalen = 0; - uint8_t keyHandleLen = 0; - json_t *root = NULL; + uint8_t data[512] = {0}; + uint8_t hdata[250] = {0}; + bool public_key_loaded = false; + uint8_t public_key[65] = {0}; + int hdatalen = 0; + uint8_t keyHandleLen = 0; + json_t *root = NULL; - CLIParserInit("hf fido auth", - "Initiate a U2F token authentication. Needs key handle and two 32-byte hash number. \nkey handle(var 0..255), challenge parameter (32b) and application parameter (32b).", - "Usage:\n\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n" - "\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f " - "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters"); + CLIParserInit("hf fido auth", + "Initiate a U2F token authentication. Needs key handle and two 32-byte hash number. \nkey handle(var 0..255), challenge parameter (32b) and application parameter (32b).", + "Usage:\n\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with 2 parameters, filled 0x00 and key handle\n" + "\thf fido auth 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f " + "000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f 000102030405060708090a0b0c0d0e0f000102030405060708090a0b0c0d0e0f -> execute command with parameters"); - void* argtable[] = { - arg_param_begin, - arg_lit0("aA", "apdu", "show APDU reqests and responses"), - arg_lit0("vV", "verbose", "show technical data"), - arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"), - arg_rem("default mode:", "dont-enforce-user-presence-and-sign"), - arg_lit0("uU", "user", "mode: enforce-user-presence-and-sign"), - arg_lit0("cC", "check", "mode: check-only"), - arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."), - arg_str0("kK", "key", "public key to verify signature", NULL), - arg_str0(NULL, NULL, "", NULL), - arg_str0(NULL, NULL, "", NULL), - arg_str0(NULL, NULL, "", NULL), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, true); + void* argtable[] = { + arg_param_begin, + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_lit0("vV", "verbose", "show technical data"), + arg_lit0("pP", "plain", "send plain ASCII to challenge and application parameters instead of HEX"), + arg_rem("default mode:", "dont-enforce-user-presence-and-sign"), + arg_lit0("uU", "user", "mode: enforce-user-presence-and-sign"), + arg_lit0("cC", "check", "mode: check-only"), + arg_str0("jJ", "json", "fido.json", "JSON input / output file name for parameters."), + arg_str0("kK", "key", "public key to verify signature", NULL), + arg_str0(NULL, NULL, "", NULL), + arg_str0(NULL, NULL, "", NULL), + arg_str0(NULL, NULL, "", NULL), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); - bool APDULogging = arg_get_lit(1); - bool verbose = arg_get_lit(2); - bool paramsPlain = arg_get_lit(3); - uint8_t controlByte = 0x08; - if (arg_get_lit(5)) - controlByte = 0x03; - if (arg_get_lit(6)) - controlByte = 0x07; + bool APDULogging = arg_get_lit(1); + bool verbose = arg_get_lit(2); + bool paramsPlain = arg_get_lit(3); + uint8_t controlByte = 0x08; + if (arg_get_lit(5)) + controlByte = 0x03; + if (arg_get_lit(6)) + controlByte = 0x07; - char fname[250] = {0}; - bool err; - root = OpenJson(7, fname, argtable, &err); - if(err) - return 1; - if (root) { - size_t jlen; - JsonLoadBufAsHex(root, "$.ChallengeParam", data, 32, &jlen); - JsonLoadBufAsHex(root, "$.ApplicationParam", &data[32], 32, &jlen); - JsonLoadBufAsHex(root, "$.KeyHandle", &data[65], 512 - 67, &jlen); - keyHandleLen = jlen & 0xff; - data[64] = keyHandleLen; - JsonLoadBufAsHex(root, "$.PublicKey", public_key, 65, &jlen); - public_key_loaded = (jlen > 0); - } + char fname[250] = {0}; + bool err; + root = OpenJson(7, fname, argtable, &err); + if(err) + return 1; + if (root) { + size_t jlen; + JsonLoadBufAsHex(root, "$.ChallengeParam", data, 32, &jlen); + JsonLoadBufAsHex(root, "$.ApplicationParam", &data[32], 32, &jlen); + JsonLoadBufAsHex(root, "$.KeyHandle", &data[65], 512 - 67, &jlen); + keyHandleLen = jlen & 0xff; + data[64] = keyHandleLen; + JsonLoadBufAsHex(root, "$.PublicKey", public_key, 65, &jlen); + public_key_loaded = (jlen > 0); + } - // public key - CLIGetHexWithReturn(8, hdata, &hdatalen); - if (hdatalen && hdatalen != 65) { - PrintAndLog("ERROR: public key length must be 65 bytes only."); - return 1; - } - if (hdatalen) { - memmove(public_key, hdata, hdatalen); - public_key_loaded = true; - } + // public key + CLIGetHexWithReturn(8, hdata, &hdatalen); + if (hdatalen && hdatalen != 65) { + PrintAndLog("ERROR: public key length must be 65 bytes only."); + return 1; + } + if (hdatalen) { + memmove(public_key, hdata, hdatalen); + public_key_loaded = true; + } - CLIGetHexWithReturn(9, hdata, &hdatalen); - if (hdatalen > 255) { - PrintAndLog("ERROR: application parameter length must be less than 255."); - return 1; - } - if (hdatalen) { - keyHandleLen = hdatalen; - data[64] = keyHandleLen; - memmove(&data[65], hdata, keyHandleLen); - } + CLIGetHexWithReturn(9, hdata, &hdatalen); + if (hdatalen > 255) { + PrintAndLog("ERROR: application parameter length must be less than 255."); + return 1; + } + if (hdatalen) { + keyHandleLen = hdatalen; + data[64] = keyHandleLen; + memmove(&data[65], hdata, keyHandleLen); + } - if (paramsPlain) { - memset(hdata, 0x00, 32); - CLIGetStrWithReturn(9, hdata, &hdatalen); - if (hdatalen && hdatalen > 16) { - PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen); - return 1; - } - } else { - CLIGetHexWithReturn(10, hdata, &hdatalen); - if (hdatalen && hdatalen != 32) { - PrintAndLog("ERROR: challenge parameter length must be 32 bytes only."); - return 1; - } - } - if (hdatalen) - memmove(data, hdata, 32); + if (paramsPlain) { + memset(hdata, 0x00, 32); + CLIGetStrWithReturn(9, hdata, &hdatalen); + if (hdatalen && hdatalen > 16) { + PrintAndLog("ERROR: challenge parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen); + return 1; + } + } else { + CLIGetHexWithReturn(10, hdata, &hdatalen); + if (hdatalen && hdatalen != 32) { + PrintAndLog("ERROR: challenge parameter length must be 32 bytes only."); + return 1; + } + } + if (hdatalen) + memmove(data, hdata, 32); - if (paramsPlain) { - memset(hdata, 0x00, 32); - CLIGetStrWithReturn(11, hdata, &hdatalen); - if (hdatalen && hdatalen > 16) { - PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen); - return 1; - } - } else { - CLIGetHexWithReturn(10, hdata, &hdatalen); - if (hdatalen && hdatalen != 32) { - PrintAndLog("ERROR: application parameter length must be 32 bytes only."); - return 1; - } - } - if (hdatalen) - memmove(&data[32], hdata, 32); + if (paramsPlain) { + memset(hdata, 0x00, 32); + CLIGetStrWithReturn(11, hdata, &hdatalen); + if (hdatalen && hdatalen > 16) { + PrintAndLog("ERROR: application parameter length in ASCII mode must be less than 16 chars instead of: %d", hdatalen); + return 1; + } + } else { + CLIGetHexWithReturn(10, hdata, &hdatalen); + if (hdatalen && hdatalen != 32) { + PrintAndLog("ERROR: application parameter length must be 32 bytes only."); + return 1; + } + } + if (hdatalen) + memmove(&data[32], hdata, 32); - CLIParserFree(); + CLIParserFree(); - SetAPDULogging(APDULogging); + SetAPDULogging(APDULogging); - // (in parameter) conrtol byte 0x07 - check only, 0x03 - user presense + cign. 0x08 - sign only - // challenge parameter [32 bytes] - // application parameter [32 bytes] - // key handle length [1b] = N - // key handle [N] + // (in parameter) conrtol byte 0x07 - check only, 0x03 - user presense + cign. 0x08 - sign only + // challenge parameter [32 bytes] + // application parameter [32 bytes] + // key handle length [1b] = N + // key handle [N] - uint8_t datalen = 32 + 32 + 1 + keyHandleLen; + uint8_t datalen = 32 + 32 + 1 + keyHandleLen; - uint8_t buf[2048] = {0}; - size_t len = 0; - uint16_t sw = 0; + uint8_t buf[2048] = {0}; + size_t len = 0; + uint16_t sw = 0; - DropField(); - int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); + DropField(); + int res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); - if (res) { - PrintAndLog("Can't select authenticator. res=%x. Exit...", res); - DropField(); - return res; - } + if (res) { + PrintAndLog("Can't select authenticator. res=%x. Exit...", res); + DropField(); + return res; + } - if (sw != 0x9000) { - PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - DropField(); - return 2; - } + if (sw != 0x9000) { + PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); + return 2; + } - res = FIDOAuthentication(data, datalen, controlByte, buf, sizeof(buf), &len, &sw); - DropField(); - if (res) { - PrintAndLog("Can't execute authentication command. res=%x. Exit...", res); - return res; - } + res = FIDOAuthentication(data, datalen, controlByte, buf, sizeof(buf), &len, &sw); + DropField(); + if (res) { + PrintAndLog("Can't execute authentication command. res=%x. Exit...", res); + return res; + } - if (sw != 0x9000) { - PrintAndLog("ERROR execute authentication command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - return 3; - } + if (sw != 0x9000) { + PrintAndLog("ERROR execute authentication command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + return 3; + } - PrintAndLog("---------------------------------------------------------------"); - PrintAndLog("User presence: %s", (buf[0]?"verified":"not verified")); - uint32_t cntr = (uint32_t)bytes_to_num(&buf[1], 4); - PrintAndLog("Counter: %d", cntr); - PrintAndLog("Hash[%d]: %s", len - 5, sprint_hex(&buf[5], len - 5)); + PrintAndLog("---------------------------------------------------------------"); + PrintAndLog("User presence: %s", (buf[0]?"verified":"not verified")); + uint32_t cntr = (uint32_t)bytes_to_num(&buf[1], 4); + PrintAndLog("Counter: %d", cntr); + PrintAndLog("Hash[%d]: %s", len - 5, sprint_hex(&buf[5], len - 5)); - // check ANSI X9.62 format ECDSA signature (on P-256) - uint8_t rval[300] = {0}; - uint8_t sval[300] = {0}; - res = ecdsa_asn1_get_signature(&buf[5], len - 5, rval, sval); - if (!res) { - if (verbose) { - PrintAndLog(" r: %s", sprint_hex(rval, 32)); - PrintAndLog(" s: %s", sprint_hex(sval, 32)); - } - if (public_key_loaded) { - uint8_t xbuf[4096] = {0}; - size_t xbuflen = 0; - res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, - &data[32], 32, // application parameter - &buf[0], 1, // user presence - &buf[1], 4, // counter - data, 32, // challenge parameter - NULL, 0); - //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); - res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[5], len - 5); - if (res) { - if (res == -0x4e00) { - PrintAndLog("Signature is NOT VALID."); - } else { - PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); - } - } else { - PrintAndLog("Signature is OK."); - } - } else { - PrintAndLog("No public key provided. can't check signature."); - } - } else { - PrintAndLog("Invalid signature. res=%d.", res); - } + // check ANSI X9.62 format ECDSA signature (on P-256) + uint8_t rval[300] = {0}; + uint8_t sval[300] = {0}; + res = ecdsa_asn1_get_signature(&buf[5], len - 5, rval, sval); + if (!res) { + if (verbose) { + PrintAndLog(" r: %s", sprint_hex(rval, 32)); + PrintAndLog(" s: %s", sprint_hex(sval, 32)); + } + if (public_key_loaded) { + uint8_t xbuf[4096] = {0}; + size_t xbuflen = 0; + res = FillBuffer(xbuf, sizeof(xbuf), &xbuflen, + &data[32], 32, // application parameter + &buf[0], 1, // user presence + &buf[1], 4, // counter + data, 32, // challenge parameter + NULL, 0); + //PrintAndLog("--xbuf(%d)[%d]: %s", res, xbuflen, sprint_hex(xbuf, xbuflen)); + res = ecdsa_signature_verify(public_key, xbuf, xbuflen, &buf[5], len - 5); + if (res) { + if (res == -0x4e00) { + PrintAndLog("Signature is NOT VALID."); + } else { + PrintAndLog("Other signature check error: %x %s", (res<0)?-res:res, ecdsa_get_error(res)); + } + } else { + PrintAndLog("Signature is OK."); + } + } else { + PrintAndLog("No public key provided. can't check signature."); + } + } else { + PrintAndLog("Invalid signature. res=%d.", res); + } - if (root) { - JsonSaveBufAsHex(root, "ChallengeParam", data, 32); - JsonSaveBufAsHex(root, "ApplicationParam", &data[32], 32); - JsonSaveInt(root, "KeyHandleLen", keyHandleLen); - JsonSaveBufAsHexCompact(root, "KeyHandle", &data[65], keyHandleLen); - JsonSaveInt(root, "Counter", cntr); + if (root) { + JsonSaveBufAsHex(root, "ChallengeParam", data, 32); + JsonSaveBufAsHex(root, "ApplicationParam", &data[32], 32); + JsonSaveInt(root, "KeyHandleLen", keyHandleLen); + JsonSaveBufAsHexCompact(root, "KeyHandle", &data[65], keyHandleLen); + JsonSaveInt(root, "Counter", cntr); - res = json_dump_file(root, fname, JSON_INDENT(2)); - if (res) { - PrintAndLog("ERROR: can't save the file: %s", fname); - return 200; - } - PrintAndLog("File `%s` saved.", fname); + res = json_dump_file(root, fname, JSON_INDENT(2)); + if (res) { + PrintAndLog("ERROR: can't save the file: %s", fname); + return 200; + } + PrintAndLog("File `%s` saved.", fname); - // free json object - json_decref(root); - } - return 0; + // free json object + json_decref(root); + } + return 0; }; void CheckSlash(char *fileName) { - if ((fileName[strlen(fileName) - 1] != '/') && - (fileName[strlen(fileName) - 1] != '\\')) - strcat(fileName, "/"); + if ((fileName[strlen(fileName) - 1] != '/') && + (fileName[strlen(fileName) - 1] != '\\')) + strcat(fileName, "/"); } int GetExistsFileNameJson(char *prefixDir, char *reqestedFileName, char *fileName) { - fileName[0] = 0x00; - strcpy(fileName, get_my_executable_directory()); - CheckSlash(fileName); + fileName[0] = 0x00; + strcpy(fileName, get_my_executable_directory()); + CheckSlash(fileName); - strcat(fileName, prefixDir); - CheckSlash(fileName); + strcat(fileName, prefixDir); + CheckSlash(fileName); - strcat(fileName, reqestedFileName); - if (!strstr(fileName, ".json")) - strcat(fileName, ".json"); + strcat(fileName, reqestedFileName); + if (!strstr(fileName, ".json")) + strcat(fileName, ".json"); - if (access(fileName, F_OK) < 0) { - strcpy(fileName, get_my_executable_directory()); - CheckSlash(fileName); + if (access(fileName, F_OK) < 0) { + strcpy(fileName, get_my_executable_directory()); + CheckSlash(fileName); - strcat(fileName, reqestedFileName); - if (!strstr(fileName, ".json")) - strcat(fileName, ".json"); + strcat(fileName, reqestedFileName); + if (!strstr(fileName, ".json")) + strcat(fileName, ".json"); - if (access(fileName, F_OK) < 0) { - return 1; // file not found - } - } - return 0; + if (access(fileName, F_OK) < 0) { + return 1; // file not found + } + } + return 0; } int CmdHFFido2MakeCredential(const char *cmd) { - json_error_t error; - json_t *root = NULL; - char fname[300] = {0}; + json_error_t error; + json_t *root = NULL; + char fname[300] = {0}; - CLIParserInit("hf fido make", - "Execute a FIDO2 Make Credentional command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", - "Usage:\n\thf fido make -> execute command default parameters file `fido2.json`\n" - "\thf fido make test.json -> execute command with parameters file `text.json`"); + CLIParserInit("hf fido make", + "Execute a FIDO2 Make Credentional command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", + "Usage:\n\thf fido make -> execute command default parameters file `fido2.json`\n" + "\thf fido make test.json -> execute command with parameters file `text.json`"); - void* argtable[] = { - arg_param_begin, - arg_lit0("aA", "apdu", "show APDU reqests and responses"), - arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), - arg_lit0("tT", "tlv", "Show DER certificate contents in TLV representation"), - arg_lit0("cC", "cbor", "show CBOR decoded data"), - arg_str0(NULL, NULL, "", "JSON input / output file name for parameters. Default `fido2.json`"), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, true); + void* argtable[] = { + arg_param_begin, + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), + arg_lit0("tT", "tlv", "Show DER certificate contents in TLV representation"), + arg_lit0("cC", "cbor", "show CBOR decoded data"), + arg_str0(NULL, NULL, "", "JSON input / output file name for parameters. Default `fido2.json`"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); - bool APDULogging = arg_get_lit(1); - bool verbose = arg_get_lit(2); - bool verbose2 = arg_get_lit(2) > 1; - bool showDERTLV = arg_get_lit(3); - bool showCBOR = arg_get_lit(4); + bool APDULogging = arg_get_lit(1); + bool verbose = arg_get_lit(2); + bool verbose2 = arg_get_lit(2) > 1; + bool showDERTLV = arg_get_lit(3); + bool showCBOR = arg_get_lit(4); - uint8_t jsonname[250] ={0}; - char *cjsonname = (char *)jsonname; - int jsonnamelen = 0; - CLIGetStrWithReturn(5, jsonname, &jsonnamelen); + uint8_t jsonname[250] ={0}; + char *cjsonname = (char *)jsonname; + int jsonnamelen = 0; + CLIGetStrWithReturn(5, jsonname, &jsonnamelen); - if (!jsonnamelen) { - strcat(cjsonname, "fido2"); - jsonnamelen = strlen(cjsonname); - } + if (!jsonnamelen) { + strcat(cjsonname, "fido2"); + jsonnamelen = strlen(cjsonname); + } - CLIParserFree(); + CLIParserFree(); - SetAPDULogging(APDULogging); + SetAPDULogging(APDULogging); - int res = GetExistsFileNameJson("fido", cjsonname, fname); - if(res) { - PrintAndLog("ERROR: Can't found the json file."); - return res; - } - PrintAndLog("fname: %s\n", fname); - root = json_load_file(fname, 0, &error); - if (!root) { - PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); - return 1; - } + int res = GetExistsFileNameJson("fido", cjsonname, fname); + if(res) { + PrintAndLog("ERROR: Can't found the json file."); + return res; + } + PrintAndLog("fname: %s\n", fname); + root = json_load_file(fname, 0, &error); + if (!root) { + PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); + return 1; + } - uint8_t data[2048] = {0}; - size_t datalen = 0; - uint8_t buf[2048] = {0}; - size_t len = 0; - uint16_t sw = 0; + uint8_t data[2048] = {0}; + size_t datalen = 0; + uint8_t buf[2048] = {0}; + size_t len = 0; + uint16_t sw = 0; - DropField(); - res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); + DropField(); + res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); - if (res) { - PrintAndLog("Can't select authenticator. res=%x. Exit...", res); - DropField(); - return res; - } + if (res) { + PrintAndLog("Can't select authenticator. res=%x. Exit...", res); + DropField(); + return res; + } - if (sw != 0x9000) { - PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - DropField(); - return 2; - } + if (sw != 0x9000) { + PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); + return 2; + } - res = FIDO2CreateMakeCredentionalReq(root, data, sizeof(data), &datalen); - if (res) - return res; + res = FIDO2CreateMakeCredentionalReq(root, data, sizeof(data), &datalen); + if (res) + return res; - if (showCBOR) { - PrintAndLog("CBOR make credentional request:"); - PrintAndLog("---------------- CBOR ------------------"); - TinyCborPrintFIDOPackage(fido2CmdMakeCredential, false, data, datalen); - PrintAndLog("---------------- CBOR ------------------"); - } + if (showCBOR) { + PrintAndLog("CBOR make credentional request:"); + PrintAndLog("---------------- CBOR ------------------"); + TinyCborPrintFIDOPackage(fido2CmdMakeCredential, false, data, datalen); + PrintAndLog("---------------- CBOR ------------------"); + } - res = FIDO2MakeCredential(data, datalen, buf, sizeof(buf), &len, &sw); - DropField(); - if (res) { - PrintAndLog("Can't execute make credential command. res=%x. Exit...", res); - return res; - } + res = FIDO2MakeCredential(data, datalen, buf, sizeof(buf), &len, &sw); + DropField(); + if (res) { + PrintAndLog("Can't execute make credential command. res=%x. Exit...", res); + return res; + } - if (sw != 0x9000) { - PrintAndLog("ERROR execute make credential command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - return 3; - } + if (sw != 0x9000) { + PrintAndLog("ERROR execute make credential command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + return 3; + } - if(buf[0]) { - PrintAndLog("FIDO2 make credential error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); - return 0; - } + if(buf[0]) { + PrintAndLog("FIDO2 make credential error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); + return 0; + } - PrintAndLog("MakeCredential result (%d b) OK.", len); - if (showCBOR) { - PrintAndLog("CBOR make credentional response:"); - PrintAndLog("---------------- CBOR ------------------"); - TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1); - PrintAndLog("---------------- CBOR ------------------"); - } + PrintAndLog("MakeCredential result (%d b) OK.", len); + if (showCBOR) { + PrintAndLog("CBOR make credentional response:"); + PrintAndLog("---------------- CBOR ------------------"); + TinyCborPrintFIDOPackage(fido2CmdMakeCredential, true, &buf[1], len - 1); + PrintAndLog("---------------- CBOR ------------------"); + } - // parse returned cbor - FIDO2MakeCredentionalParseRes(root, &buf[1], len - 1, verbose, verbose2, showCBOR, showDERTLV); + // parse returned cbor + FIDO2MakeCredentionalParseRes(root, &buf[1], len - 1, verbose, verbose2, showCBOR, showDERTLV); - if (root) { - res = json_dump_file(root, fname, JSON_INDENT(2)); - if (res) { - PrintAndLog("ERROR: can't save the file: %s", fname); - return 200; - } - PrintAndLog("File `%s` saved.", fname); - } + if (root) { + res = json_dump_file(root, fname, JSON_INDENT(2)); + if (res) { + PrintAndLog("ERROR: can't save the file: %s", fname); + return 200; + } + PrintAndLog("File `%s` saved.", fname); + } - json_decref(root); + json_decref(root); - return 0; + return 0; }; int CmdHFFido2GetAssertion(const char *cmd) { - json_error_t error; - json_t *root = NULL; - char fname[300] = {0}; + json_error_t error; + json_t *root = NULL; + char fname[300] = {0}; - CLIParserInit("hf fido assert", - "Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", - "Usage:\n\thf fido assert -> execute command default parameters file `fido2.json`\n" - "\thf fido assert test.json -l -> execute command with parameters file `text.json` and add to request CredentialId"); + CLIParserInit("hf fido assert", + "Execute a FIDO2 Get Assertion command. Needs json file with parameters. Sample file `fido2.json`. File can be placed in proxmark directory or in `proxmark/fido` directory.", + "Usage:\n\thf fido assert -> execute command default parameters file `fido2.json`\n" + "\thf fido assert test.json -l -> execute command with parameters file `text.json` and add to request CredentialId"); - void* argtable[] = { - arg_param_begin, - arg_lit0("aA", "apdu", "show APDU reqests and responses"), - arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), - arg_lit0("cC", "cbor", "show CBOR decoded data"), - arg_lit0("lL", "list", "add CredentialId from json to allowList. Needs if `rk` option is `false` (authenticator don't store credential to its memory)"), - arg_str0(NULL, NULL, "", "JSON input / output file name for parameters. Default `fido2.json`"), - arg_param_end - }; - CLIExecWithReturn(cmd, argtable, true); + void* argtable[] = { + arg_param_begin, + arg_lit0("aA", "apdu", "show APDU reqests and responses"), + arg_litn("vV", "verbose", 0, 2, "show technical data. vv - show full certificates data"), + arg_lit0("cC", "cbor", "show CBOR decoded data"), + arg_lit0("lL", "list", "add CredentialId from json to allowList. Needs if `rk` option is `false` (authenticator don't store credential to its memory)"), + arg_str0(NULL, NULL, "", "JSON input / output file name for parameters. Default `fido2.json`"), + arg_param_end + }; + CLIExecWithReturn(cmd, argtable, true); - bool APDULogging = arg_get_lit(1); - bool verbose = arg_get_lit(2); - bool verbose2 = arg_get_lit(2) > 1; - bool showCBOR = arg_get_lit(3); - bool createAllowList = arg_get_lit(4); + bool APDULogging = arg_get_lit(1); + bool verbose = arg_get_lit(2); + bool verbose2 = arg_get_lit(2) > 1; + bool showCBOR = arg_get_lit(3); + bool createAllowList = arg_get_lit(4); - uint8_t jsonname[250] ={0}; - char *cjsonname = (char *)jsonname; - int jsonnamelen = 0; - CLIGetStrWithReturn(5, jsonname, &jsonnamelen); + uint8_t jsonname[250] ={0}; + char *cjsonname = (char *)jsonname; + int jsonnamelen = 0; + CLIGetStrWithReturn(5, jsonname, &jsonnamelen); - if (!jsonnamelen) { - strcat(cjsonname, "fido2"); - jsonnamelen = strlen(cjsonname); - } + if (!jsonnamelen) { + strcat(cjsonname, "fido2"); + jsonnamelen = strlen(cjsonname); + } - CLIParserFree(); + CLIParserFree(); - SetAPDULogging(APDULogging); + SetAPDULogging(APDULogging); - int res = GetExistsFileNameJson("fido", "fido2", fname); - if(res) { - PrintAndLog("ERROR: Can't found the json file."); - return res; - } - PrintAndLog("fname: %s\n", fname); - root = json_load_file(fname, 0, &error); - if (!root) { - PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); - return 1; - } + int res = GetExistsFileNameJson("fido", "fido2", fname); + if(res) { + PrintAndLog("ERROR: Can't found the json file."); + return res; + } + PrintAndLog("fname: %s\n", fname); + root = json_load_file(fname, 0, &error); + if (!root) { + PrintAndLog("ERROR: json error on line %d: %s", error.line, error.text); + return 1; + } - uint8_t data[2048] = {0}; - size_t datalen = 0; - uint8_t buf[2048] = {0}; - size_t len = 0; - uint16_t sw = 0; + uint8_t data[2048] = {0}; + size_t datalen = 0; + uint8_t buf[2048] = {0}; + size_t len = 0; + uint16_t sw = 0; - DropField(); - res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); + DropField(); + res = FIDOSelect(true, true, buf, sizeof(buf), &len, &sw); - if (res) { - PrintAndLog("Can't select authenticator. res=%x. Exit...", res); - DropField(); - return res; - } + if (res) { + PrintAndLog("Can't select authenticator. res=%x. Exit...", res); + DropField(); + return res; + } - if (sw != 0x9000) { - PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - DropField(); - return 2; - } + if (sw != 0x9000) { + PrintAndLog("Can't select FIDO application. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + DropField(); + return 2; + } - res = FIDO2CreateGetAssertionReq(root, data, sizeof(data), &datalen, createAllowList); - if (res) - return res; + res = FIDO2CreateGetAssertionReq(root, data, sizeof(data), &datalen, createAllowList); + if (res) + return res; - if (showCBOR) { - PrintAndLog("CBOR get assertion request:"); - PrintAndLog("---------------- CBOR ------------------"); - TinyCborPrintFIDOPackage(fido2CmdGetAssertion, false, data, datalen); - PrintAndLog("---------------- CBOR ------------------"); - } + if (showCBOR) { + PrintAndLog("CBOR get assertion request:"); + PrintAndLog("---------------- CBOR ------------------"); + TinyCborPrintFIDOPackage(fido2CmdGetAssertion, false, data, datalen); + PrintAndLog("---------------- CBOR ------------------"); + } - res = FIDO2GetAssertion(data, datalen, buf, sizeof(buf), &len, &sw); - DropField(); - if (res) { - PrintAndLog("Can't execute get assertion command. res=%x. Exit...", res); - return res; - } + res = FIDO2GetAssertion(data, datalen, buf, sizeof(buf), &len, &sw); + DropField(); + if (res) { + PrintAndLog("Can't execute get assertion command. res=%x. Exit...", res); + return res; + } - if (sw != 0x9000) { - PrintAndLog("ERROR execute get assertion command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); - return 3; - } + if (sw != 0x9000) { + PrintAndLog("ERROR execute get assertion command. APDU response status: %04x - %s", sw, GetAPDUCodeDescription(sw >> 8, sw & 0xff)); + return 3; + } - if(buf[0]) { - PrintAndLog("FIDO2 get assertion error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); - return 0; - } + if(buf[0]) { + PrintAndLog("FIDO2 get assertion error: %d - %s", buf[0], fido2GetCmdErrorDescription(buf[0])); + return 0; + } - PrintAndLog("GetAssertion result (%d b) OK.", len); - if (showCBOR) { - PrintAndLog("CBOR get assertion response:"); - PrintAndLog("---------------- CBOR ------------------"); - TinyCborPrintFIDOPackage(fido2CmdGetAssertion, true, &buf[1], len - 1); - PrintAndLog("---------------- CBOR ------------------"); - } + PrintAndLog("GetAssertion result (%d b) OK.", len); + if (showCBOR) { + PrintAndLog("CBOR get assertion response:"); + PrintAndLog("---------------- CBOR ------------------"); + TinyCborPrintFIDOPackage(fido2CmdGetAssertion, true, &buf[1], len - 1); + PrintAndLog("---------------- CBOR ------------------"); + } - // parse returned cbor - FIDO2GetAssertionParseRes(root, &buf[1], len - 1, verbose, verbose2, showCBOR); + // parse returned cbor + FIDO2GetAssertionParseRes(root, &buf[1], len - 1, verbose, verbose2, showCBOR); - if (root) { - res = json_dump_file(root, fname, JSON_INDENT(2)); - if (res) { - PrintAndLog("ERROR: can't save the file: %s", fname); - return 200; - } - PrintAndLog("File `%s` saved.", fname); - } + if (root) { + res = json_dump_file(root, fname, JSON_INDENT(2)); + if (res) { + PrintAndLog("ERROR: can't save the file: %s", fname); + return 200; + } + PrintAndLog("File `%s` saved.", fname); + } - json_decref(root); + json_decref(root); - return 0; + return 0; }; static command_t CommandTable[] = { - {"help", CmdHelp, 1, "This help."}, - {"info", CmdHFFidoInfo, 0, "Info about FIDO tag."}, - {"reg", CmdHFFidoRegister, 0, "FIDO U2F Registration Message."}, - {"auth", CmdHFFidoAuthenticate, 0, "FIDO U2F Authentication Message."}, - {"make", CmdHFFido2MakeCredential, 0, "FIDO2 MakeCredential command."}, - {"assert", CmdHFFido2GetAssertion, 0, "FIDO2 GetAssertion command."}, - {NULL, NULL, 0, NULL} + {"help", CmdHelp, 1, "This help."}, + {"info", CmdHFFidoInfo, 0, "Info about FIDO tag."}, + {"reg", CmdHFFidoRegister, 0, "FIDO U2F Registration Message."}, + {"auth", CmdHFFidoAuthenticate, 0, "FIDO U2F Authentication Message."}, + {"make", CmdHFFido2MakeCredential, 0, "FIDO2 MakeCredential command."}, + {"assert", CmdHFFido2GetAssertion, 0, "FIDO2 GetAssertion command."}, + {NULL, NULL, 0, NULL} }; int CmdHFFido(const char *Cmd) { - (void)WaitForResponseTimeout(CMD_ACK, NULL, 100); - CmdsParse(CommandTable, Cmd); - return 0; + (void)WaitForResponseTimeout(CMD_ACK, NULL, 100); + CmdsParse(CommandTable, Cmd); + return 0; } int CmdHelp(const char *Cmd) { diff --git a/client/cmdhficlass.c b/client/cmdhficlass.c index bf8976e8a..20bcfdf33 100644 --- a/client/cmdhficlass.c +++ b/client/cmdhficlass.c @@ -19,346 +19,346 @@ static int CmdHelp(const char *Cmd); static uint8_t iClass_Key_Table[ICLASS_KEYS_MAX][8] = { - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, - { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }, + { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 } }; int usage_hf_iclass_sim(void) { - PrintAndLogEx(NORMAL, "Usage: hf iclass sim